abstract
| - 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*/
|