Source:O init.c

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