| abstract
| - Below is the full text to questpgr.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/questpgr.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)questpgr.c 3.3 1999/11/26 */ 2. /* Copyright 1991, M. Stephenson */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "dlb.h" 7. 8. /* quest-specific pager routines. */ 9. 10. #include "qtext.h" 11. 12. #define QTEXT_FILE "quest.dat" 13. 14. /* #define DEBUG */ /* uncomment for debugging */ 15. 16. static void FDECL(Fread, (genericptr_t,int,int,dlb *)); 17. STATIC_DCL struct qtmsg * FDECL(construct_qtlist, (long)); 18. STATIC_DCL const char * NDECL(intermed); 19. STATIC_DCL const char * NDECL(neminame); 20. STATIC_DCL const char * NDECL(guardname); 21. STATIC_DCL const char * NDECL(homebase); 22. STATIC_DCL struct qtmsg * FDECL(msg_in, (struct qtmsg *,int)); 23. STATIC_DCL void FDECL(convert_arg, (CHAR_P)); 24. STATIC_DCL void NDECL(convert_line); 25. STATIC_DCL void FDECL(deliver_by_pline, (struct qtmsg *)); 26. STATIC_DCL void FDECL(deliver_by_window, (struct qtmsg *,int)); 27. 28. static char in_line[80], cvt_buf[64], out_line[128]; 29. static struct qtlists qt_list; 30. static dlb *msg_file; 31. /* used by ldrname() and neminame(), then copied into cvt_buf */ 32. static char nambuf[sizeof cvt_buf]; 33. 34. #ifdef DEBUG 35. static void NDECL(dump_qtlist); 36. 37. static void 38. dump_qtlist() /* dump the character msg list to check appearance */ 39. { 40. struct qtmsg *msg; 41. long size; 42. 43. for (msg = qt_list.chrole; msg->msgnum > 0; msg++) { 44. pline("msgnum %d: delivery %c", 45. msg->msgnum, msg->delivery); 46. more(); 47. (void) dlb_fseek(msg_file, msg->offset, SEEK_SET); 48. deliver_by_window(msg, NHW_TEXT); 49. } 50. } 51. #endif /* DEBUG */ 52. 53. static void 54. Fread(ptr, size, nitems, stream) 55. genericptr_t ptr; 56. int size, nitems; 57. dlb *stream; 58. { 59. int cnt; 60. 61. if ((cnt = dlb_fread(ptr, size, nitems, stream)) != nitems) { 62. 63. panic("PREMATURE EOF ON QUEST TEXT FILE!
Expected %d bytes - got %d
", 64. (size * nitems), (size * cnt)); 65. } 66. } 67. 68. STATIC_OVL struct qtmsg * 69. construct_qtlist(hdr_offset) 70. long hdr_offset; 71. { 72. struct qtmsg *msg_list; 73. int n_msgs; 74. 75. (void) dlb_fseek(msg_file, hdr_offset, SEEK_SET); 76. Fread(&n_msgs, sizeof(int), 1, msg_file); 77. msg_list = (struct qtmsg *) 78. alloc((unsigned)(n_msgs+1)*sizeof(struct qtmsg)); 79. 80. /* 81. * Load up the list. 82. */ 83. Fread((genericptr_t)msg_list, n_msgs*sizeof(struct qtmsg), 1, msg_file); 84. 85. msg_list[n_msgs].msgnum = -1; 86. return(msg_list); 87. } 88. 89. void 90. load_qtlist() 91. { 92. 93. int n_classes, i; 94. char qt_classes[N_HDR][LEN_HDR]; 95. long qt_offsets[N_HDR]; 96. 97. msg_file = dlb_fopen(QTEXT_FILE, RDBMODE); 98. if (!msg_file) 99. panic("CANNOT OPEN QUEST TEXT FILE %s.", QTEXT_FILE); 100. 101. /* 102. * Read in the number of classes, then the ID's & offsets for 103. * each header. 104. */ 105. 106. Fread(&n_classes, sizeof(int), 1, msg_file); 107. Fread(&qt_classes[0][0], sizeof(char)*LEN_HDR, n_classes, msg_file); 108. Fread(qt_offsets, sizeof(long), n_classes, msg_file); 109. 110. /* 111. * Now construct the message lists for quick reference later 112. * on when we are actually paging the messages out. 113. */ 114. 115. qt_list.common = qt_list.chrole = (struct qtmsg *)0; 116. 117. for (i = 0; i < n_classes; i++) { 118. if (!strncmp(COMMON_ID, qt_classes[i], LEN_HDR)) 119. qt_list.common = construct_qtlist(qt_offsets[i]); 120. else if (!strncmp(urole.filecode, qt_classes[i], LEN_HDR)) 121. qt_list.chrole = construct_qtlist(qt_offsets[i]); 122. #if 0 /* UNUSED but available */ 123. else if (!strncmp(urace.filecode, qt_classes[i], LEN_HDR)) 124. qt_list.chrace = construct_qtlist(qt_offsets[i]); 125. #endif 126. } 127. 128. if (!qt_list.common || !qt_list.chrole) 129. impossible("load_qtlist: cannot load quest text."); 130. #ifdef DEBUG 131. dump_qtlist(); 132. #endif 133. return; /* no ***DON'T*** close the msg_file */ 134. } 135. 136. /* called at program exit */ 137. void 138. unload_qtlist() 139. { 140. if (msg_file) 141. (void) dlb_fclose(msg_file), msg_file = 0; 142. if (qt_list.common) 143. free((genericptr_t) qt_list.common), qt_list.common = 0; 144. if (qt_list.chrole) 145. free((genericptr_t) qt_list.chrole), qt_list.chrole = 0; 146. return; 147. } 148. 149. short 150. quest_info(typ) 151. int typ; 152. { 153. switch (typ) { 154. case 0: return (urole.questarti); 155. case MS_LEADER: return (urole.ldrnum); 156. case MS_NEMESIS: return (urole.neminum); 157. case MS_GUARDIAN: return (urole.guardnum); 158. default: impossible("quest_info(%d)", typ); 159. } 160. return 0; 161. } 162. 163. const char * 164. ldrname() /* return your role leader's name */ 165. { 166. int i = urole.ldrnum; 167. 168. Sprintf(nambuf, "%s%s", 169. type_is_pname(&mons[i]) ? "" : "the ", 170. mons[i].mname); 171. return nambuf; 172. } 173. 174. STATIC_OVL const char * 175. intermed() /* return your intermediate target string */ 176. { 177. return (urole.intermed); 178. } 179. 180. boolean 181. is_quest_artifact(otmp) 182. struct obj *otmp; 183. { 184. return((boolean)(otmp->oartifact == urole.questarti)); 185. } 186. 187. STATIC_OVL const char * 188. neminame() /* return your role nemesis' name */ 189. { 190. int i = urole.neminum; 191. 192. Sprintf(nambuf, "%s%s", 193. type_is_pname(&mons[i]) ? "" : "the ", 194. mons[i].mname); 195. return nambuf; 196. } 197. 198. STATIC_OVL const char * 199. guardname() /* return your role leader's guard monster name */ 200. { 201. int i = urole.guardnum; 202. 203. return(mons[i].mname); 204. } 205. 206. STATIC_OVL const char * 207. homebase() /* return your role leader's location */ 208. { 209. return(urole.homebase); 210. } 211. 212. boolean 213. leaderless() /* return true iff leader is dead */ 214. { 215. int i = urole.ldrnum; 216. /* BUG: This doesn't take the possibility of resurrection 217. via wand or spell of undead turning into account. */ 218. return (boolean)(mvitals[i].died > 0); 219. } 220. 221. STATIC_OVL struct qtmsg * 222. msg_in(qtm_list, msgnum) 223. struct qtmsg *qtm_list; 224. int msgnum; 225. { 226. struct qtmsg *qt_msg; 227. 228. for (qt_msg = qtm_list; qt_msg->msgnum > 0; qt_msg++) 229. if (qt_msg->msgnum == msgnum) return(qt_msg); 230. 231. return((struct qtmsg *)0); 232. } 233. 234. STATIC_OVL void 235. convert_arg(c) 236. char c; 237. { 238. register const char *str; 239. 240. switch (c) { 241. 242. case 'p': str = plname; 243. break; 244. case 'c': str = (flags.female && urole.name.f) ? 245. urole.name.f : urole.name.m; 246. break; 247. case 'r': str = rank_of(u.ulevel, Role_switch, flags.female); 248. break; 249. case 'R': str = rank_of(MIN_QUEST_LEVEL, Role_switch, 250. flags.female); 251. break; 252. case 's': str = (flags.female) ? "sister" : "brother"; 253. break; 254. case 'S': str = (flags.female) ? "daughter" : "son"; 255. break; 256. case 'l': str = ldrname(); 257. break; 258. case 'i': str = intermed(); 259. break; 260. case 'o': str = the(artiname(urole.questarti)); 261. break; 262. case 'n': str = neminame(); 263. break; 264. case 'g': str = guardname(); 265. break; 266. case 'G': str = align_gtitle(u.ualignbase[1]); 267. break; 268. case 'H': str = homebase(); 269. break; 270. case 'a': str = align_str(u.ualignbase[1]); 271. break; 272. case 'A': str = align_str(u.ualign.type); 273. break; 274. case 'd': str = align_gname(u.ualignbase[1]); 275. break; 276. case 'D': str = align_gname(A_LAWFUL); 277. break; 278. case 'C': str = "chaotic"; 279. break; 280. case 'N': str = "neutral"; 281. break; 282. case 'L': str = "lawful"; 283. break; 284. case 'x': str = Blind ? "sense" : "see"; 285. break; 286. case 'Z': str = dungeons[0].dname; 287. break; 288. case '%': str = "%"; 289. break; 290. default: str = ""; 291. break; 292. } 293. Strcpy(cvt_buf, str); 294. } 295. 296. STATIC_OVL void 297. convert_line() 298. { 299. char *c, *cc; 300. char xbuf[BUFSZ]; 301. 302. cc = out_line; 303. for (c = xcrypt(in_line, xbuf); *c; c++) { 304. 305. *cc = 0; 306. switch(*c) { 307. 308. case '': 309. case '
': 310. *(++cc) = 0; 311. return; 312. 313. case '%': 314. if (*(c+1)) { 315. convert_arg(*(++c)); 316. switch (*(++c)) { 317. 318. /* insert "a"/"an" prefix */ 319. case 'A': Strcat(cc, An(cvt_buf)); 320. cc += strlen(cc); 321. continue; /* for */ 322. case 'a': Strcat(cc, an(cvt_buf)); 323. cc += strlen(cc); 324. continue; /* for */ 325. 326. /* capitalize */ 327. case 'C': cvt_buf[0] = highc(cvt_buf[0]); 328. break; 329. 330. /* pluralize */ 331. case 'P': cvt_buf[0] = highc(cvt_buf[0]); 332. case 'p': Strcpy(cvt_buf, makeplural(cvt_buf)); 333. break; 334. 335. /* append possessive suffix */ 336. case 'S': cvt_buf[0] = highc(cvt_buf[0]); 337. case 's': Strcpy(cvt_buf, s_suffix(cvt_buf)); 338. break; 339. 340. /* strip any "the" prefix */ 341. case 't': if (!strncmpi(cvt_buf, "the ", 4)) { 342. Strcat(cc, &cvt_buf[4]); 343. cc += strlen(cc); 344. continue; /* for */ 345. } 346. break; 347. 348. default: --c; /* undo switch increment */ 349. break; 350. } 351. Strcat(cc, cvt_buf); 352. cc += strlen(cvt_buf); 353. break; 354. } /* else fall through */ 355. 356. default: 357. *cc++ = *c; 358. break; 359. } 360. } 361. if (cc >= out_line + sizeof out_line) 362. panic("convert_line: overflow"); 363. *cc = 0; 364. return; 365. } 366. 367. STATIC_OVL void 368. deliver_by_pline(qt_msg) 369. struct qtmsg *qt_msg; 370. { 371. long size; 372. 373. for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) { 374. (void) dlb_fgets(in_line, 80, msg_file); 375. convert_line(); 376. pline(out_line); 377. } 378. 379. } 380. 381. STATIC_OVL void 382. deliver_by_window(qt_msg, how) 383. struct qtmsg *qt_msg; 384. int how; 385. { 386. long size; 387. winid datawin = create_nhwindow(how); 388. 389. for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) { 390. (void) dlb_fgets(in_line, 80, msg_file); 391. convert_line(); 392. putstr(datawin, 0, out_line); 393. } 394. display_nhwindow(datawin, TRUE); 395. destroy_nhwindow(datawin); 396. } 397. 398. void 399. com_pager(msgnum) 400. int msgnum; 401. { 402. struct qtmsg *qt_msg; 403. 404. if (!(qt_msg = msg_in(qt_list.common, msgnum))) { 405. impossible("com_pager: message %d not found.", msgnum); 406. return; 407. } 408. 409. (void) dlb_fseek(msg_file, qt_msg->offset, SEEK_SET); 410. if (qt_msg->delivery == 'p') deliver_by_pline(qt_msg); 411. else if (msgnum == 1) deliver_by_window(qt_msg, NHW_MENU); 412. else deliver_by_window(qt_msg, NHW_TEXT); 413. return; 414. } 415. 416. void 417. qt_pager(msgnum) 418. int msgnum; 419. { 420. struct qtmsg *qt_msg; 421. 422. if (!(qt_msg = msg_in(qt_list.chrole, msgnum))) { 423. impossible("qt_pager: message %d not found.", msgnum); 424. return; 425. } 426. 427. (void) dlb_fseek(msg_file, qt_msg->offset, SEEK_SET); 428. if (qt_msg->delivery == 'p' && strcmp(windowprocs.name, "X11")) 429. deliver_by_pline(qt_msg); 430. else deliver_by_window(qt_msg, NHW_TEXT); 431. return; 432. } 433. 434. struct permonst * 435. qt_montype() 436. { 437. int qpm; 438. 439. if (rn2(5)) { 440. qpm = urole.enemy1num; 441. if (qpm != NON_PM && rn2(5) && !(mvitals[qpm].mvflags & G_GENOD)) 442. return (&mons[qpm]); 443. return (mkclass(urole.enemy1sym, 0)); 444. } 445. qpm = urole.enemy2num; 446. if (qpm != NON_PM && rn2(5) && !(mvitals[qpm].mvflags & G_GENOD)) 447. return (&mons[qpm]); 448. return (mkclass(urole.enemy2sym, 0)); 449. } 450. 451. /*questpgr.c*/
|