abstract
| - Below is the full text to rumors.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/rumors.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)rumors.c 3.4 1996/04/20 */ 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" 7. #include "dlb.h" 8. 9. /* [note: this comment is fairly old, but still accurate for 3.1] 10. * Rumors have been entirely rewritten to speed up the access. This is 11. * essential when working from floppies. Using fseek() the way that's done 12. * here means rumors following longer rumors are output more often than those 13. * following shorter rumors. Also, you may see the same rumor more than once 14. * in a particular game (although the odds are highly against it), but 15. * this also happens with real fortune cookies. -dgk 16. */ 17. 18. /* 3.1 19. * The rumors file consists of a "do not edit" line, a hexadecimal number 20. * giving the number of bytes of useful/true rumors, followed by those 21. * true rumors (one per line), followed by the useless/false/misleading/cute 22. * rumors (also one per line). Number of bytes of untrue rumors is derived 23. * via fseek(EOF)+ftell(). 24. * 25. * The oracles file consists of a "do not edit" comment, a decimal count N 26. * and set of N+1 hexadecimal fseek offsets, followed by N multiple-line 27. * records, separated by "---" lines. The first oracle is a special case, 28. * and placed there by 'makedefs'. 29. */ 30. 31. STATIC_DCL void FDECL(init_rumors, (dlb *)); 32. STATIC_DCL void FDECL(init_oracles, (dlb *)); 33. 34. static long true_rumor_start, true_rumor_size, true_rumor_end, 35. false_rumor_start, false_rumor_size, false_rumor_end; 36. static int oracle_flg = 0; /* -1=>don't use, 0=>need init, 1=>init done */ 37. static unsigned oracle_cnt = 0; 38. static long *oracle_loc = 0; 39. 40. STATIC_OVL void 41. init_rumors(fp) 42. dlb *fp; 43. { 44. char line[BUFSZ]; 45. 46. (void) dlb_fgets(line, sizeof line, fp); /* skip "don't edit" comment */ 47. (void) dlb_fgets(line, sizeof line, fp); 48. if (sscanf(line, "%6lx
", &true_rumor_size) == 1 && 49. true_rumor_size > 0L) { 50. (void) dlb_fseek(fp, 0L, SEEK_CUR); 51. true_rumor_start = dlb_ftell(fp); 52. true_rumor_end = true_rumor_start + true_rumor_size; 53. (void) dlb_fseek(fp, 0L, SEEK_END); 54. false_rumor_end = dlb_ftell(fp); 55. false_rumor_start = true_rumor_end; /* ok, so it's redundant... */ 56. false_rumor_size = false_rumor_end - false_rumor_start; 57. } else 58. true_rumor_size = -1L; /* init failed */ 59. } 60. 61. /* exclude_cookie is a hack used because we sometimes want to get rumors in a 62. * context where messages such as "You swallowed the fortune!" that refer to 63. * cookies should not appear. This has no effect for true rumors since none 64. * of them contain such references anyway. 65. */ 66. char * 67. getrumor(truth, rumor_buf, exclude_cookie) 68. int truth; /* 1=true, -1=false, 0=either */ 69. char *rumor_buf; 70. boolean exclude_cookie; 71. { 72. dlb *rumors; 73. long tidbit, beginning; 74. char *endp, line[BUFSZ], xbuf[BUFSZ]; 75. 76. rumor_buf[0] = '\0'; 77. if (true_rumor_size < 0L) /* we couldn't open RUMORFILE */ 78. return rumor_buf; 79. 80. rumors = dlb_fopen(RUMORFILE, "r"); 81. 82. if (rumors) { 83. int count = 0; 84. int adjtruth; 85. 86. do { 87. rumor_buf[0] = '\0'; 88. if (true_rumor_size == 0L) { /* if this is 1st outrumor() */ 89. init_rumors(rumors); 90. if (true_rumor_size < 0L) { /* init failed */ 91. Sprintf(rumor_buf, "Error reading \"%.80s\".", 92. RUMORFILE); 93. return rumor_buf; 94. } 95. } 96. /* 97. * input: 1 0 -1 98. * rn2 \ +1 2=T 1=T 0=F 99. * adj./ +0 1=T 0=F -1=F 100. */ 101. switch (adjtruth = truth + rn2(2)) { 102. case 2: /*(might let a bogus input arg sneak thru)*/ 103. case 1: beginning = true_rumor_start; 104. tidbit = Rand() % true_rumor_size; 105. break; 106. case 0: /* once here, 0 => false rather than "either"*/ 107. case -1: beginning = false_rumor_start; 108. tidbit = Rand() % false_rumor_size; 109. break; 110. default: 111. impossible("strange truth value for rumor"); 112. return strcpy(rumor_buf, "Oops..."); 113. } 114. (void) dlb_fseek(rumors, beginning + tidbit, SEEK_SET); 115. (void) dlb_fgets(line, sizeof line, rumors); 116. if (!dlb_fgets(line, sizeof line, rumors) || 117. (adjtruth > 0 && dlb_ftell(rumors) > true_rumor_end)) { 118. /* reached end of rumors -- go back to beginning */ 119. (void) dlb_fseek(rumors, beginning, SEEK_SET); 120. (void) dlb_fgets(line, sizeof line, rumors); 121. } 122. if ((endp = index(line, '
')) != 0) *endp = 0; 123. Strcat(rumor_buf, xcrypt(line, xbuf)); 124. } while(count++ < 50 && exclude_cookie && (strstri(rumor_buf, "fortune") || strstri(rumor_buf, "pity"))); 125. (void) dlb_fclose(rumors); 126. if (count >= 50) 127. impossible("Can't find non-cookie rumor?"); 128. else 129. exercise(A_WIS, (adjtruth > 0)); 130. } else { 131. pline("Can't open rumors file!"); 132. true_rumor_size = -1; /* don't try to open it again */ 133. } 134. return rumor_buf; 135. } 136. 137. void 138. outrumor(truth, mechanism) 139. int truth; /* 1=true, -1=false, 0=either */ 140. int mechanism; 141. { 142. static const char fortune_msg[] = 143. "This cookie has a scrap of paper inside."; 144. const char *line; 145. char buf[BUFSZ]; 146. boolean reading = (mechanism == BY_COOKIE || 147. mechanism == BY_PAPER); 148. 149. if (reading) { 150. /* deal with various things that prevent reading */ 151. if (is_fainted() && mechanism == BY_COOKIE) 152. return; 153. else if (Blind) { 154. if (mechanism == BY_COOKIE) 155. pline(fortune_msg); 156. pline("What a pity that you cannot read it!"); 157. return; 158. } 159. } 160. line = getrumor(truth, buf, reading ? FALSE : TRUE); 161. if (!*line) 162. line = "NetHack rumors file closed for renovation."; 163. switch (mechanism) { 164. case BY_ORACLE: 165. /* Oracle delivers the rumor */ 166. pline("True to her word, the Oracle %ssays: ", 167. (!rn2(4) ? "offhandedly " : (!rn2(3) ? "casually " : 168. (rn2(2) ? "nonchalantly " : "")))); 169. verbalize("%s", line); 170. exercise(A_WIS, TRUE); 171. return; 172. case BY_COOKIE: 173. pline(fortune_msg); 174. /* FALLTHRU */ 175. case BY_PAPER: 176. pline("It reads:"); 177. break; 178. } 179. pline("%s", line); 180. } 181. 182. STATIC_OVL void 183. init_oracles(fp) 184. dlb *fp; 185. { 186. register int i; 187. char line[BUFSZ]; 188. int cnt = 0; 189. 190. /* this assumes we're only called once */ 191. (void) dlb_fgets(line, sizeof line, fp); /* skip "don't edit" comment*/ 192. (void) dlb_fgets(line, sizeof line, fp); 193. if (sscanf(line, "%5d
", &cnt) == 1 && cnt > 0) { 194. oracle_cnt = (unsigned) cnt; 195. oracle_loc = (long *) alloc((unsigned)cnt * sizeof (long)); 196. for (i = 0; i < cnt; i++) { 197. (void) dlb_fgets(line, sizeof line, fp); 198. (void) sscanf(line, "%5lx
", &oracle_loc[i]); 199. } 200. } 201. return; 202. } 203. 204. void 205. save_oracles(fd, mode) 206. int fd, mode; 207. { 208. if (perform_bwrite(mode)) { 209. bwrite(fd, (genericptr_t) &oracle_cnt, sizeof oracle_cnt); 210. if (oracle_cnt) 211. bwrite(fd, (genericptr_t)oracle_loc, oracle_cnt*sizeof (long)); 212. } 213. if (release_data(mode)) { 214. if (oracle_cnt) { 215. free((genericptr_t)oracle_loc); 216. oracle_loc = 0, oracle_cnt = 0, oracle_flg = 0; 217. } 218. } 219. } 220. 221. void 222. restore_oracles(fd) 223. int fd; 224. { 225. mread(fd, (genericptr_t) &oracle_cnt, sizeof oracle_cnt); 226. if (oracle_cnt) { 227. oracle_loc = (long *) alloc(oracle_cnt * sizeof (long)); 228. mread(fd, (genericptr_t) oracle_loc, oracle_cnt * sizeof (long)); 229. oracle_flg = 1; /* no need to call init_oracles() */ 230. } 231. } 232. 233. void 234. outoracle(special, delphi) 235. boolean special; 236. boolean delphi; 237. { 238. char line[COLNO]; 239. char *endp; 240. dlb *oracles; 241. int oracle_idx; 242. char xbuf[BUFSZ]; 243. 244. if(oracle_flg < 0 || /* couldn't open ORACLEFILE */ 245. (oracle_flg > 0 && oracle_cnt == 0)) /* oracles already exhausted */ 246. return; 247. 248. oracles = dlb_fopen(ORACLEFILE, "r"); 249. 250. if (oracles) { 251. winid tmpwin; 252. if (oracle_flg == 0) { /* if this is the first outoracle() */ 253. init_oracles(oracles); 254. oracle_flg = 1; 255. if (oracle_cnt == 0) return; 256. } 257. /* oracle_loc[0] is the special oracle; */ 258. /* oracle_loc[1..oracle_cnt-1] are normal ones */ 259. if (oracle_cnt <= 1 && !special) return; /*(shouldn't happen)*/ 260. oracle_idx = special ? 0 : rnd((int) oracle_cnt - 1); 261. (void) dlb_fseek(oracles, oracle_loc[oracle_idx], SEEK_SET); 262. if (!special) oracle_loc[oracle_idx] = oracle_loc[--oracle_cnt]; 263. 264. tmpwin = create_nhwindow(NHW_TEXT); 265. if (delphi) 266. putstr(tmpwin, 0, special ? 267. "The Oracle scornfully takes all your money and says:" : 268. "The Oracle meditates for a moment and then intones:"); 269. else 270. putstr(tmpwin, 0, "The message reads:"); 271. putstr(tmpwin, 0, ""); 272. 273. while(dlb_fgets(line, COLNO, oracles) && strcmp(line,"---
")) { 274. if ((endp = index(line, '
')) != 0) *endp = 0; 275. putstr(tmpwin, 0, xcrypt(line, xbuf)); 276. } 277. display_nhwindow(tmpwin, TRUE); 278. destroy_nhwindow(tmpwin); 279. (void) dlb_fclose(oracles); 280. } else { 281. pline("Can't open oracles file!"); 282. oracle_flg = -1; /* don't try to open it again */ 283. } 284. } 285. 286. int 287. doconsult(oracl) 288. register struct monst *oracl; 289. { 290. #ifdef GOLDOBJ 291. long umoney = money_cnt(invent); 292. #endif 293. int u_pay, minor_cost = 50, major_cost = 500 + 50 * u.ulevel; 294. int add_xpts; 295. char qbuf[QBUFSZ]; 296. 297. multi = 0; 298. 299. if (!oracl) { 300. There("is no one here to consult."); 301. return 0; 302. } else if (!oracl->mpeaceful) { 303. pline("%s is in no mood for consultations.", Monnam(oracl)); 304. return 0; 305. #ifndef GOLDOBJ 306. } else if (!u.ugold) { 307. #else 308. } else if (!umoney) { 309. #endif 310. You("have no money."); 311. return 0; 312. } 313. 314. Sprintf(qbuf, 315. "\"Wilt thou settle for a minor consultation?\" (%d %s)", 316. minor_cost, currency((long)minor_cost)); 317. switch (ynq(qbuf)) { 318. default: 319. case 'q': 320. return 0; 321. case 'y': 322. #ifndef GOLDOBJ 323. if (u.ugold < (long)minor_cost) { 324. #else 325. if (umoney < (long)minor_cost) { 326. #endif 327. You("don't even have enough money for that!"); 328. return 0; 329. } 330. u_pay = minor_cost; 331. break; 332. case 'n': 333. #ifndef GOLDOBJ 334. if (u.ugold <= (long)minor_cost || /* don't even ask */ 335. #else 336. if (umoney <= (long)minor_cost || /* don't even ask */ 337. #endif 338. (oracle_cnt == 1 || oracle_flg < 0)) return 0; 339. Sprintf(qbuf, 340. "\"Then dost thou desire a major one?\" (%d %s)", 341. major_cost, currency((long)major_cost)); 342. if (yn(qbuf) != 'y') return 0; 343. #ifndef GOLDOBJ 344. u_pay = (u.ugold < (long)major_cost ? (int)u.ugold 345. : major_cost); 346. #else 347. u_pay = (umoney < (long)major_cost ? (int)umoney 348. : major_cost); 349. #endif 350. break; 351. } 352. #ifndef GOLDOBJ 353. u.ugold -= (long)u_pay; 354. oracl->mgold += (long)u_pay; 355. #else 356. money2mon(oracl, (long)u_pay); 357. #endif 358. flags.botl = 1; 359. add_xpts = 0; /* first oracle of each type gives experience points */ 360. if (u_pay == minor_cost) { 361. outrumor(1, BY_ORACLE); 362. if (!u.uevent.minor_oracle) 363. add_xpts = u_pay / (u.uevent.major_oracle ? 25 : 10); 364. /* 5 pts if very 1st, or 2 pts if major already done */ 365. u.uevent.minor_oracle = TRUE; 366. } else { 367. boolean cheapskate = u_pay < major_cost; 368. outoracle(cheapskate, TRUE); 369. if (!cheapskate && !u.uevent.major_oracle) 370. add_xpts = u_pay / (u.uevent.minor_oracle ? 25 : 10); 371. /* ~100 pts if very 1st, ~40 pts if minor already done */ 372. u.uevent.major_oracle = TRUE; 373. exercise(A_WIS, !cheapskate); 374. } 375. if (add_xpts) { 376. more_experienced(add_xpts, u_pay/50); 377. newexplevel(); 378. } 379. return 1; 380. } 381. 382. /*rumors.c*/
|