Source:NetHack 3.3.0/o init.c

Below is the full text to o_init.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/o_init.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)o_init.c	3.3	1999/12/09	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6.    #include "lev.h"	/* save & restore info */ 7.    8.    STATIC_DCL void FDECL(setgemprobs, (d_level*)); 9.   STATIC_DCL void FDECL(shuffle,(int,int,BOOLEAN_P)); 10.  STATIC_DCL void NDECL(shuffle_all); 11.  STATIC_DCL boolean FDECL(interesting_to_discover,(int)); 12.   13.    14.   static NEARDATA short disco[NUM_OBJECTS] = DUMMY; 15.   16.   #ifdef USE_TILES 17.  STATIC_DCL void NDECL(shuffle_tiles); 18.  extern short glyph2tile[];	/* from tile.c */ 19.   20.   /* Shuffle tile assignments to match descriptions, so a red potion isn't  21. * displayed with a blue tile and so on. 22.   *  23.    * Tile assignments are not saved, and shouldn't be so that a game can 24.   * be resumed on an otherwise identical non-tile-using binary, so we have 25.   * to reshuffle the assignments from oc_descr_idx information when a game 26.   * is restored. So might as well do that the first time instead of writing 27.   * another routine. 28.   */  29.   STATIC_OVL void 30.  shuffle_tiles 31.  {  32.   	int i;  33. short tmp_tilemap[NUM_OBJECTS]; 34.   35.   	for (i = 0; i < NUM_OBJECTS; i++) 36.  		tmp_tilemap[i] = 37.  			glyph2tile[objects[i].oc_descr_idx + GLYPH_OBJ_OFF]; 38.   39.   	for (i = 0; i < NUM_OBJECTS; i++) 40.  		glyph2tile[i + GLYPH_OBJ_OFF] = tmp_tilemap[i]; 41.  }  42.   #endif	/* USE_TILES */ 43.   44.   STATIC_OVL void 45.  setgemprobs(dlev) 46.  d_level *dlev; 47.  {  48.   	int j, first, lev; 49.   50.   	if (dlev) 51.  	    lev = (ledger_no(dlev) > maxledgerno) 52.  				? maxledgerno : ledger_no(dlev); 53.  	else 54.  	    lev = 0; 55.  	first = bases[GEM_CLASS]; 56.   57.   	for(j = 0; j < 9-lev/3; j++) 58.  		objects[first+j].oc_prob = 0; 59.  	first += j;  60. if (first > LAST_GEM || objects[first].oc_class != GEM_CLASS || 61.   	    OBJ_NAME(objects[first]) == (char *)0) { 62.  		raw_printf("Not enough gems? - first=%d j=%d LAST_GEM=%d",  63.   			first, j, LAST_GEM); 64.  		wait_synch; 65.  	    }  66.   	for (j = first; j <= LAST_GEM; j++) 67.  		objects[j].oc_prob = (171+j-first)/(LAST_GEM+1-first); 68.  }  69.    70.   /* shuffle descriptions on objects o_low to o_high */ 71.  STATIC_OVL void 72.  shuffle(o_low, o_high, domaterial) 73.  	int o_low, o_high; 74.  	boolean domaterial; 75.  {  76.   	int i, j, num_to_shuffle; 77.  	short sw; 78.  #ifdef TEXTCOLOR 79.  	int color; 80.  #endif /* TEXTCOLOR */ 81.   82.   	for (num_to_shuffle = 0, j=o_low; j <= o_high; j++) 83.  		if (!objects[j].oc_name_known) num_to_shuffle++; 84.  	if (num_to_shuffle < 2) return; 85.   86.   	for (j=o_low; j <= o_high; j++) { 87.  		if (objects[j].oc_name_known) continue; 88.  		do 89.  			i = j + rn2(o_high-j+1); 90.  		while (objects[i].oc_name_known); 91.  		sw = objects[j].oc_descr_idx; 92.  		objects[j].oc_descr_idx = objects[i].oc_descr_idx; 93.  		objects[i].oc_descr_idx = sw; 94.  		sw = objects[j].oc_tough; 95.  		objects[j].oc_tough = objects[i].oc_tough; 96.  		objects[i].oc_tough = sw; 97.  #ifdef TEXTCOLOR 98.  		color = objects[j].oc_color; 99.  		objects[j].oc_color = objects[i].oc_color; 100. 		objects[i].oc_color = color; 101. #endif /* TEXTCOLOR */ 102. 		/* shuffle material */ 103. 		if (domaterial) { 104. 			sw = objects[j].oc_material; 105. 			objects[j].oc_material = objects[i].oc_material; 106. 			objects[i].oc_material = sw; 107. 		}  108.  	}  109.  }  110.   111.  void 112. init_objects 113. {  114.  register int i, first, last, sum; 115. register char oclass; 116. #ifdef TEXTCOLOR 117. # define COPY_OBJ_DESCR(o_dst,o_src) \ 118. 			o_dst.oc_descr_idx = o_src.oc_descr_idx,\ 119. 			o_dst.oc_color = o_src.oc_color 120. #else 121. # define COPY_OBJ_DESCR(o_dst,o_src) o_dst.oc_descr_idx = o_src.oc_descr_idx 122. #endif 123.  124.  	/* bug fix to prevent "initialization error" abort on Intel Xenix. 125. 	 * reported by mikew@semike 126. 	 */  127.  	for (i = 0; i < MAXOCLASSES; i++) 128. 		bases[i] = 0; 129. 	/* initialize object descriptions */ 130. 	for (i = 0; i < NUM_OBJECTS; i++) 131. 		objects[i].oc_name_idx = objects[i].oc_descr_idx = i;  132. /* init base; if probs given check that they add up to 1000, 133. 	   otherwise compute probs */ 134. 	first = 0; 135. 	while( first < NUM_OBJECTS ) { 136. 		oclass = objects[first].oc_class; 137. 		last = first+1; 138. 		while (last < NUM_OBJECTS && objects[last].oc_class == oclass) last++; 139. 		bases[(int)oclass] = first; 140.  141.  		if (oclass == GEM_CLASS) { 142. 			setgemprobs((d_level *)0); 143.  144.  			if (rn2(2)) { /* change turquoise from green to blue? */ 145.  			    COPY_OBJ_DESCR(objects[TURQUOISE],objects[SAPPHIRE]); 146. 			}  147.  			if (rn2(2)) { /* change aquamarine from green to blue? */ 148.  			    COPY_OBJ_DESCR(objects[AQUAMARINE],objects[SAPPHIRE]); 149. 			}  150.  			switch (rn2(4)) { /* change fluorite from violet? */ 151.  			    case 0:  break; 152. 			    case 1:	/* blue */ 153. 				COPY_OBJ_DESCR(objects[FLUORITE],objects[SAPPHIRE]); 154. 				break; 155. 			    case 2:	/* white */ 156. 				COPY_OBJ_DESCR(objects[FLUORITE],objects[DIAMOND]); 157. 				break; 158. 			    case 3:	/* green */ 159. 				COPY_OBJ_DESCR(objects[FLUORITE],objects[EMERALD]); 160. 				break; 161. 			}  162.  		}  163.  	check: 164. 		sum = 0; 165. 		for(i = first; i < last; i++) sum += objects[i].oc_prob; 166. 		if(sum == 0) { 167. 			for(i = first; i < last; i++) 168. 			    objects[i].oc_prob = (1000+i-first)/(last-first); 169. 			goto check; 170. 		}  171.  		if(sum != 1000) 172. 			error("init-prob error for class %d (%d%%)", oclass, sum); 173. 		first = last; 174. 	}  175.  	/* shuffle descriptions */ 176. 	shuffle_all; 177. #ifdef USE_TILES 178. 	shuffle_tiles; 179. #endif 180. }  181.   182.  STATIC_OVL void 183. shuffle_all 184. {  185.  	int first, last, oclass; 186.  187.  	for (oclass = 1; oclass < MAXOCLASSES; oclass++) { 188. 		first = bases[oclass]; 189. 		last = first+1; 190. 		while (last < NUM_OBJECTS && objects[last].oc_class == oclass) 191. 			last++; 192.  193.  		if (OBJ_DESCR(objects[first]) != (char *)0 &&  194.  				oclass != TOOL_CLASS &&  195.  				oclass != WEAPON_CLASS &&  196.  				oclass != ARMOR_CLASS &&  197.  				oclass != GEM_CLASS) { 198. 			int j = last-1; 199.  200.  			if (oclass == POTION_CLASS) 201. 			    j -= 1;  /* only water has a fixed description */ 202. 			else if (oclass == AMULET_CLASS ||  203.  				 oclass == SCROLL_CLASS ||  204.  				 oclass == SPBOOK_CLASS) { 205. 			    while (!objects[j].oc_magic || objects[j].oc_unique) 206. 				j--; 207. 			}  208.   209.  			/* non-magical amulets, scrolls, and spellbooks 210. 			 * (ex. imitation Amulets, blank, scrolls of mail) 211. 			 * and one-of-a-kind magical artifacts at the end of  212. * their class in objects[] have fixed descriptions. 213. 			 */  214.  			shuffle(first, j, TRUE); 215. 		}  216.  	}  217.   218.  	/* shuffle the helmets */ 219. 	shuffle(HELMET, HELM_OF_TELEPATHY, FALSE); 220.  221.  	/* shuffle the gloves */ 222. 	shuffle(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY, FALSE); 223.  224.  	/* shuffle the cloaks */ 225. 	shuffle(CLOAK_OF_PROTECTION, CLOAK_OF_DISPLACEMENT, FALSE); 226.  227.  	/* shuffle the boots [if they change, update find_skates below] */ 228. 	shuffle(SPEED_BOOTS, LEVITATION_BOOTS, FALSE); 229. }  230.   231.  /* find the object index for snow boots; used [once] by slippery ice code */ 232. int 233. find_skates 234. {  235.      register int i;  236. register const char *s; 237.  238.      for (i = SPEED_BOOTS; i <= LEVITATION_BOOTS; i++) 239. 	if ((s = OBJ_DESCR(objects[i])) != 0 && !strcmp(s, "snow boots")) 240. 	    return i;  241. 242.     impossible("snow boots not found?"); 243.     return -1;	/* not 0, or caller would try again each move */ 244. }  245.   246.  void 247. oinit			/* level dependent initialization */ 248. {  249.  	setgemprobs(&u.uz); 250. }  251.   252.  void 253. savenames(fd, mode) 254. int fd, mode; 255. {  256.  	register int i;  257. unsigned int len; 258.  259.  	if (perform_bwrite(mode)) { 260. 	    bwrite(fd, (genericptr_t)bases, sizeof bases); 261. 	    bwrite(fd, (genericptr_t)disco, sizeof disco); 262. 	    bwrite(fd, (genericptr_t)objects,  263.  		   sizeof(struct objclass) * NUM_OBJECTS); 264. 	}  265.  	/* as long as we use only one version of Hack we  266. need not save oc_name and oc_descr, but we must save 267. 	   oc_uname for all objects */ 268. 	for (i = 0; i < NUM_OBJECTS; i++) 269. 	    if (objects[i].oc_uname) { 270. 		if (perform_bwrite(mode)) { 271. 		    len = strlen(objects[i].oc_uname)+1; 272. 		    bwrite(fd, (genericptr_t)&len, sizeof len); 273. 		    bwrite(fd, (genericptr_t)objects[i].oc_uname, len); 274. 		}  275.  		if (release_data(mode)) { 276. 		    free((genericptr_t)objects[i].oc_uname); 277. 		    objects[i].oc_uname = 0; 278. 		}  279.  	    }  280.  }  281.   282.  void 283. restnames(fd) 284. register int fd; 285. {  286.  	register int i;  287. unsigned int len; 288.  289.  	mread(fd, (genericptr_t) bases, sizeof bases); 290. 	mread(fd, (genericptr_t) disco, sizeof disco); 291. 	mread(fd, (genericptr_t) objects, sizeof(struct objclass) * NUM_OBJECTS); 292. 	for (i = 0; i < NUM_OBJECTS; i++) 293. 	    if (objects[i].oc_uname) { 294. 		mread(fd, (genericptr_t) &len, sizeof len); 295. 		objects[i].oc_uname = (char *) alloc(len); 296. 		mread(fd, (genericptr_t)objects[i].oc_uname, len); 297. 	    }  298.  #ifdef USE_TILES 299. 	shuffle_tiles; 300. #endif 301. }  302.   303.  void 304. discover_object(oindx, mark_as_known, credit_hero) 305. register int oindx; 306. boolean mark_as_known; 307. boolean credit_hero; 308. {  309.      if (!objects[oindx].oc_name_known) { 310. 	register int dindx, acls = objects[oindx].oc_class; 311.  312.  	/* Loop thru disco[] 'til we find the target (which may have been  313.  	   uname'd) or the next open slot; one or the other will be found 314. 	   before we reach the next class...  315. */ 316.  	for (dindx = bases[acls]; disco[dindx] != 0; dindx++) 317. 	    if (disco[dindx] == oindx) break; 318. 	disco[dindx] = oindx; 319.  320.  	if (mark_as_known) { 321. 	    objects[oindx].oc_name_known = 1; 322. 	    if (credit_hero) exercise(A_WIS, TRUE); 323. 	}  324.  	if (moves > 1L) update_inventory; 325.     }  326.  }  327.   328.  /* if a class name has been cleared, we may need to purge it from disco[] */ 329. void 330. undiscover_object(oindx) 331. register int oindx; 332. {  333.      if (!objects[oindx].oc_name_known) { 334. 	register int dindx, acls = objects[oindx].oc_class; 335. 	register boolean found = FALSE; 336.  337.  	/* find the object; shift those behind it forward one slot */ 338. 	for (dindx = bases[acls];  339.  	      dindx < NUM_OBJECTS && disco[dindx] != 0  340.  		&& objects[dindx].oc_class == acls; dindx++) 341. 	    if (found) 342. 		disco[dindx-1] = disco[dindx]; 343. 	    else if (disco[dindx] == oindx) 344. 		found = TRUE; 345.  346.  	/* clear last slot */ 347. 	if (found) disco[dindx-1] = 0; 348. 	else impossible("named object not in disco"); 349. 	update_inventory; 350.     }  351.  }  352.   353.  STATIC_OVL boolean 354. interesting_to_discover(i) 355. register int i;  356. { 357.  	/* Pre-discovered objects are now printed with a '*' */ 358.     return((boolean)(objects[i].oc_uname != (char *)0 || 359. 	    (objects[i].oc_name_known && OBJ_DESCR(objects[i]) != (char *)0))); 360. }  361.   362.  /* items that should stand out once they're known */ 363. static short uniq_objs[] = { 364. 	AMULET_OF_YENDOR, 365. 	SPE_BOOK_OF_THE_DEAD, 366. 	CANDELABRUM_OF_INVOCATION, 367. 	BELL_OF_OPENING, 368. };  369.   370.  int 371. dodiscovered				/* free after Robert Viduya */ 372. {  373.      register int i, dis; 374.     int	ct = 0; 375.     char *s, oclass, prev_class, classes[MAXOCLASSES]; 376.     winid tmpwin; 377. 	char buf[BUFSZ]; 378.  379.      tmpwin = create_nhwindow(NHW_MENU); 380.     putstr(tmpwin, 0, "Discoveries"); 381.     putstr(tmpwin, 0, ""); 382.  383.      /* gather "unique objects" into a pseudo-class; note that they'll  384. also be displayed individually within their regular class */ 385.     for (i = dis = 0; i < SIZE(uniq_objs); i++) 386. 	if (objects[uniq_objs[i]].oc_name_known) { 387. 	    if (!dis++) 388. 		putstr(tmpwin, ATR_INVERSE, "Unique Items"); 389. 		Sprintf(buf, "  %s", OBJ_NAME(objects[uniq_objs[i]])); 390. 	    putstr(tmpwin, 0, buf); 391. 	    ++ct; 392. 	}  393.      /* display any known artifacts as another pseudo-class */ 394.     ct += disp_artifact_discoveries(tmpwin); 395.  396.      /* several classes are omitted from packorder; one is of interest here */ 397.     Strcpy(classes, flags.inv_order); 398.     if (!index(classes, VENOM_CLASS)) { 399. 	s = eos(classes); 400. 	*s++ = VENOM_CLASS; 401. 	*s = '\0'; 402.     }  403.   404.      for (s = classes; *s; s++) { 405. 	oclass = *s; 406. 	prev_class = oclass + 1;	/* forced different from oclass */ 407. 	for (i = bases[(int)oclass];  408.  	     i < NUM_OBJECTS && objects[i].oc_class == oclass; i++) { 409. 	    if ((dis = disco[i]) && interesting_to_discover(dis)) { 410. 		ct++; 411. 		if (oclass != prev_class) { 412. 		    putstr(tmpwin, ATR_INVERSE, let_to_name(oclass, FALSE)); 413. 		    prev_class = oclass; 414. 		}  415.  		Sprintf(buf, "%s %s",(objects[dis].oc_pre_discovered ? "*" : " "), 416.  				obj_typename(dis)); 417. 		putstr(tmpwin, 0, buf); 418. 	    }  419.  	}  420.      }  421.      if (ct == 0) { 422. 	You("haven't discovered anything yet..."); 423.     } else 424. 	display_nhwindow(tmpwin, TRUE); 425.     destroy_nhwindow(tmpwin); 426.  427.      return 0; 428. }  429.   430.  /*o_init.c*/