Source:NetHack 3.1.0/o init.c

Below is the full text to o_init.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.1	92/12/11	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include	"hack.h"		/* for typedefs */ 6.    7.    static void NDECL(setgemprobs); 8.   static void FDECL(shuffle,(int,int,BOOLEAN_P)); 9.   static boolean FDECL(interesting_to_discover,(int)); 10.   11.   /* note that NROFOBJECTS is the number of legal objects, which does not count 12.   * the strange object and null object that take up positions 0 and NROFOBJECTS+1 13.   * in the objects array 14.   */  15.   #define TOTAL_OBJS	(NROFOBJECTS+2) 16.   17.   const char obj_symbols[] = { 18.  	ILLOBJ_CLASS, AMULET_CLASS, GOLD_CLASS, FOOD_CLASS, WEAPON_CLASS, 19.  	TOOL_CLASS, BALL_CLASS, CHAIN_CLASS, ROCK_CLASS, ARMOR_CLASS, 20.  	POTION_CLASS, SCROLL_CLASS, WAND_CLASS, 21.  	SPBOOK_CLASS, RING_CLASS, GEM_CLASS, 0 }; 22.   23.   static short NEARDATA disco[TOTAL_OBJS] = DUMMY; 24.   25.   int 26.  letindex(acls) register char acls; { 27.  register int i = 0; 28.  register char ch; 29.  	while ((ch = obj_symbols[i++]) != 0) 30.  		if (ch == acls) return(i); 31.  	return(0); 32.  }  33.    34.   static void 35.  setgemprobs 36.  {  37.   	register int j, first; 38.  	int lev = (ledger_no(&u.uz) > maxledgerno) 39.  				? maxledgerno : ledger_no(&u.uz); 40.   41.   	first = bases[letindex(GEM_CLASS)]; 42.   43.   	for(j = 0; j < 9-lev/3; j++) 44.  		objects[first+j].oc_prob = 0; 45.  	first += j;  46. if (first > LAST_GEM || objects[first].oc_class != GEM_CLASS || 47.   	    OBJ_NAME(objects[first]) == NULL) { 48.  		raw_printf("Not enough gems? - first=%d j=%d LAST_GEM=%d",  49.   			first, j, LAST_GEM); 50.  		wait_synch; 51.  	    }  52.   	for (j = first; j <= LAST_GEM; j++) 53.  		objects[j].oc_prob = (184+j-first)/(LAST_GEM+1-first); 54.  }  55.    56.   /* shuffle descriptions on objects o_low to o_high */ 57.  static void 58.  shuffle(o_low, o_high, domaterial) 59.  	register int o_low, o_high; 60.  	register boolean domaterial; 61.  {  62.   	register int i, j;  63. #ifdef TEXTCOLOR 64.  	int color; 65.  #endif /* TEXTCOLOR */ 66.  	register short sw; 67.   68.   	for (j=o_low; j <= o_high; j++) { 69.  		i = o_low + rn2(j+1-o_low); 70.  		sw = objects[j].oc_descr_idx; 71.  		objects[j].oc_descr_idx = objects[i].oc_descr_idx; 72.  		objects[i].oc_descr_idx = sw; 73.  #ifdef TEXTCOLOR 74.  		color = objects[j].oc_color; 75.  		objects[j].oc_color = objects[i].oc_color; 76.  		objects[i].oc_color = color; 77.  #endif /* TEXTCOLOR */ 78.  		/* shuffle material */ 79.  		if (domaterial) { 80.  			sw = objects[j].oc_material; 81.  			objects[j].oc_material = objects[i].oc_material; 82.  			objects[i].oc_material = sw; 83.  		}  84.   	}  85.   }  86.    87.   void 88.  init_objects{ 89.  register int i, j, first, last, sum, end; 90.  register char acls; 91.  #ifdef TEXTCOLOR 92.  # define COPY_OBJ_DESCR(o_dst,o_src) \ 93.  			o_dst.oc_descr_idx = o_src.oc_descr_idx,\ 94.  			o_dst.oc_color = o_src.oc_color 95.  #else 96.  # define COPY_OBJ_DESCR(o_dst,o_src) o_dst.oc_descr_idx = o_src.oc_descr_idx 97.  #endif 98.   99.   	/* bug fix to prevent "initialization error" abort on Intel Xenix. 100. 	 * reported by mikew@semike 101. 	 */  102.  	for (i = 0; i < sizeof(obj_symbols); i++) 103. 		bases[i] = 0; 104. 	/* initialize object descriptions */ 105. 	for (i = 0; i < TOTAL_OBJS; i++) 106. 		objects[i].oc_name_idx = objects[i].oc_descr_idx = i;  107. init_artifacts; 108. 	/* init base; if probs given check that they add up to 1000, 109. 	   otherwise compute probs; shuffle descriptions */ 110. 	end = TOTAL_OBJS; 111. 	first = 0; 112. 	while( first < end ) { 113. 		acls = objects[first].oc_class; 114. 		last = first+1; 115. 		while (last < end && objects[last].oc_class == acls) last++; 116. 		i = letindex(acls); 117. 		if ((!i && acls != ILLOBJ_CLASS && acls != VENOM_CLASS) ||  118.  								bases[i] != 0) 119. 			error("initialization error for object class %d", acls); 120. 		bases[i] = first; 121.  122.  		if (acls == GEM_CLASS) setgemprobs; 123. 	check: 124. 		sum = 0; 125. 		for(j = first; j < last; j++) sum += objects[j].oc_prob; 126. 		if(sum == 0) { 127. 			for(j = first; j < last; j++) 128. 			    objects[j].oc_prob = (1000+j-first)/(last-first); 129. 			goto check; 130. 		}  131.  		if(sum != 1000) 132. 			error("init-prob error for %d (%d%%)", acls, sum); 133.  134.  		if (OBJ_DESCR(objects[first]) != NULL &&  135.  		   acls != TOOL_CLASS && acls != WEAPON_CLASS && acls != ARMOR_CLASS) { 136.  137.  		    /* shuffle, also some additional descriptions */ 138. 		    while (last < end && objects[last].oc_class == acls) 139. 			last++; 140. 		    j = last; 141. 		    if (acls == GEM_CLASS) { 142. 			if (rn2(2)) { /* change turquoise from green to blue? */ 143.  			    COPY_OBJ_DESCR(objects[TURQUOISE],objects[SAPPHIRE]); 144. 			}  145.  			if (rn2(2)) { /* change aquamarine from green to blue? */ 146.  			    COPY_OBJ_DESCR(objects[AQUAMARINE],objects[SAPPHIRE]); 147. 			}  148.  			switch (rn2(4)) { /* change fluorite from violet? */ 149.  			    case 0:  break; 150. 			    case 1:	/* blue */ 151. 				COPY_OBJ_DESCR(objects[FLUORITE],objects[SAPPHIRE]); 152. 				break; 153. 			    case 2:	/* white */ 154. 				COPY_OBJ_DESCR(objects[FLUORITE],objects[DIAMOND]); 155. 				break; 156. 			    case 3:	/* green */ 157. 				COPY_OBJ_DESCR(objects[FLUORITE],objects[EMERALD]); 158. 				break; 159. 			}  160.  		    } else { 161. 			if (acls == POTION_CLASS) 162. 			    j--;  /* only water has a fixed description */ 163. 			else if (acls == AMULET_CLASS ||  164.  				 acls == SCROLL_CLASS ||  165.  				 acls == SPBOOK_CLASS) 166. 			    do { j--; } 167. 			    while (!objects[j].oc_magic || objects[j].oc_unique); 168. 			/* non-magical amulets, scrolls, and spellbooks 169. 			 * (ex. imitation Amulets, blank, scrolls of mail) 170. 			 * and one-of-a-kind magical artifacts at the end of  171. * their class in objects[] have fixed descriptions. 172. 			 */  173.  			shuffle(first, --j, TRUE); 174. 		    }  175.  		}  176.  		first = last; 177. 	}  178.   179.  	/* shuffle the helmets */ 180. 	shuffle(HELMET, HELM_OF_TELEPATHY, FALSE); 181.  182.  	/* shuffle the gloves */ 183. 	shuffle(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY, FALSE); 184.  185.  	/* shuffle the cloaks */ 186. 	shuffle(CLOAK_OF_PROTECTION, CLOAK_OF_DISPLACEMENT, FALSE); 187.  188.  	/* shuffle the boots [if they change, update find_skates below] */ 189. 	shuffle(SPEED_BOOTS, LEVITATION_BOOTS, FALSE); 190. }  191.   192.  /* find the object index for snow boots; used [once] by slippery ice code */ 193. int 194. find_skates 195. {  196.      register int i;  197. register const char *s; 198.  199.      for (i = SPEED_BOOTS; i <= LEVITATION_BOOTS; i++) 200. 	if ((s = OBJ_DESCR(objects[i])) != 0 && !strcmp(s, "snow boots")) 201. 	    return i;  202. 203.     impossible("snow boots not found?"); 204.     return -1;	/* not 0, or caller would try again each move */ 205. }  206.   207.  void 208. oinit			/* level dependent initialization */ 209. {  210.  	setgemprobs; 211. }  212.   213.  void 214. savenames(fd) 215. register int fd; 216. {  217.  	register int i;  218. unsigned int len; 219.  220.  	bwrite(fd, (genericptr_t)bases, MAXOCLASSES * sizeof *bases); 221. 	bwrite(fd, (genericptr_t)disco, sizeof disco); 222. 	bwrite(fd, (genericptr_t)objects, sizeof(struct objclass) * TOTAL_OBJS); 223. 	/* as long as we use only one version of Hack we  224. need not save oc_name and oc_descr, but we must save 225. 	   oc_uname for all objects */ 226. 	for(i=0; i < TOTAL_OBJS; i++) { 227. 		if(objects[i].oc_uname) { 228. 			len = strlen(objects[i].oc_uname)+1; 229. 			bwrite(fd, (genericptr_t)&len, sizeof len); 230. 			bwrite(fd, (genericptr_t)objects[i].oc_uname, len); 231. 		}  232.  	}  233.  }  234.   235.  void 236. restnames(fd) 237. register int fd; 238. {  239.  	register int i;  240. unsigned int len; 241.  242.  	mread(fd, (genericptr_t) bases, MAXOCLASSES * sizeof *bases); 243. 	mread(fd, (genericptr_t) disco, sizeof disco); 244. 	mread(fd, (genericptr_t) objects, sizeof(struct objclass) * TOTAL_OBJS); 245. 	for(i=0; i < TOTAL_OBJS; i++) { 246. 		if (objects[i].oc_uname) { 247. 			mread(fd, (genericptr_t) &len, sizeof len); 248. 			objects[i].oc_uname = (char *) alloc(len); 249. 			mread(fd, (genericptr_t)objects[i].oc_uname, len); 250. 		}  251.  	}  252.  }  253.   254.  void 255. discover_object(oindx, mark_as_known) 256. register int oindx; 257. boolean mark_as_known; 258. {  259.      if (!objects[oindx].oc_name_known) { 260. 	register int dindx, acls = objects[oindx].oc_class; 261.  262.  	/* Loop thru disco[] 'til we find the target (which may have been  263.  	   uname'd) or the next open slot; one or the other will be found 264. 	   before we reach the next class...  265. */ 266.  	for (dindx = bases[letindex(acls)]; disco[dindx] != 0; dindx++) 267. 	    if (disco[dindx] == oindx) break; 268. 	disco[dindx] = oindx; 269.  270.  	if (mark_as_known) { 271. 	    objects[oindx].oc_name_known = 1; 272. 	    exercise(A_WIS, TRUE); 273. 	}  274.      }  275.  }  276.   277.  /* if a class name has been cleared, we may need to purge it from disco[] */ 278. void 279. undiscover_object(oindx) 280. register int oindx; 281. {  282.      if (!objects[oindx].oc_name_known) { 283. 	register int dindx, acls = objects[oindx].oc_class; 284. 	register boolean found = FALSE; 285.  286.  	/* find the object; shift those behind it forward one slot */ 287. 	for (dindx = bases[letindex(acls)];  288.  	      dindx <= NROFOBJECTS && disco[dindx] != 0  289.  		&& objects[dindx].oc_class == acls; dindx++) 290. 	    if (found) 291. 		disco[dindx-1] = disco[dindx]; 292. 	    else if (disco[dindx] == oindx) 293. 		found = TRUE; 294.  295.  	/* clear last slot */ 296. 	if (found) disco[dindx-1] = 0; 297. 	else impossible("named object not in disco"); 298.     }  299.  }  300.   301.  static boolean 302. interesting_to_discover(i) 303. register int i;  304. { 305.      return objects[i].oc_uname != NULL || 306. 		(objects[i].oc_name_known && OBJ_DESCR(objects[i]) != NULL); 307. }  308.   309.  int 310. dodiscovered				/* free after Robert Viduya */ 311. {  312.      register int i, dis; 313.     int	ct = 0; 314.     char class = -1; 315.     winid tmpwin; 316.  317.      tmpwin = create_nhwindow(NHW_MENU); 318.     putstr(tmpwin, 0, "Discoveries"); 319.     putstr(tmpwin, 0, ""); 320.  321.      for (i = 0; i <= NROFOBJECTS; i++) { 322. 	if ((dis = disco[i]) && interesting_to_discover(dis)) { 323. 	    ct++; 324. 	    if (objects[dis].oc_class != class) { 325. 		class = objects[dis].oc_class; 326. 		putstr(tmpwin, ATR_INVERSE, let_to_name(class, FALSE)); 327. 	    }  328.  	    putstr(tmpwin, 0, typename(dis)); 329. 	}  330.      }  331.      if (ct == 0) { 332. 	You("haven't discovered anything yet..."); 333.     } else 334. 	display_nhwindow(tmpwin, TRUE); 335.     destroy_nhwindow(tmpwin); 336.  337.      return 0; 338. }  339.   340.  /*o_init.c*/