Source:SLASH'EM 0.0.7E7F2/o init.c

Below is the full text to o_init.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/o_init.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

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