Source:NetHack 3.1.0/o init.c
Jump to navigation
Jump to search
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
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
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*/