Difference between revisions of "Source:NetHack 3.1.0/questpgr.c"
Jump to navigation
Jump to search
m (Automated source code upload) |
Kernigh bot (talk | contribs) m (NetHack 3.1.0/questpgr.c moved to Source:NetHack 3.1.0/questpgr.c: Robot: moved page) |
(No difference)
|
Latest revision as of 07:21, 4 March 2008
Below is the full text to questpgr.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/questpgr.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: @(#)questpgr.c 3.1 93/01/20 */ 2. /* Copyright 1991, M. Stephenson */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. 7. #ifdef MULDGN 8. /* quest-specific pager routines. */ 9. 10. #include "qtext.h" 11. 12. #define QTEXT_FILE "quest.dat" 13. #if defined(MICRO) && !defined(AMIGA) 14. # define RDMODE "rb" 15. #else 16. # define RDMODE "r" 17. #endif 18. 19. #ifndef SEEK_SET 20. # define SEEK_SET 0 21. #endif 22. 23. /* #define DEBUG /* uncomment for debugging */ 24. 25. static void FDECL(Fread, (genericptr_t,int,int,FILE *)); 26. static struct qtmsg * FDECL(construct_qtlist, (long)); 27. static unsigned NDECL(class_index); 28. static const char * NDECL(intermed); 29. static const char * NDECL(neminame); 30. static const char * NDECL(guardname); 31. static const char * NDECL(homebase); 32. static struct qtmsg * FDECL(msg_in, (struct qtmsg *,int)); 33. static void FDECL(convert_arg, (CHAR_P)); 34. static void NDECL(convert_line); 35. static void FDECL(deliver_by_pline, (struct qtmsg *)); 36. static void FDECL(deliver_by_window, (struct qtmsg *)); 37. 38. static char in_line[80], cvt_buf[64], out_line[128]; 39. static struct qtlists qt_list; 40. static FILE *msg_file; 41. 42. #ifdef DEBUG 43. static void NDECL(dump_qtlist); 44. 45. static void 46. dump_qtlist() /* dump the character msg list to check appearance */ 47. { 48. struct qtmsg *msg; 49. long size; 50. 51. for (msg = qt_list.chclass; msg->msgnum > 0; msg++) { 52. pline("msgnum %d: delivery %c", 53. msg->msgnum, msg->delivery); 54. more(); 55. (void) fseek(msg_file, msg->offset, SEEK_SET); 56. deliver_by_window(msg); 57. } 58. } 59. #endif /* DEBUG */ 60. 61. static void 62. Fread(ptr, size, nitems, stream) 63. genericptr_t ptr; 64. int size, nitems; 65. FILE *stream; 66. { 67. int cnt; 68. 69. if ((cnt = fread(ptr, size, nitems, stream)) != nitems) { 70. 71. panic("PREMATURE EOF ON QUEST TEXT FILE!\nExpected %d bytes - got %d\n", 72. (size * nitems), (size * cnt)); 73. } 74. } 75. 76. static struct qtmsg * 77. construct_qtlist(hdr_offset) 78. long hdr_offset; 79. { 80. struct qtmsg *msg_list; 81. int n_msgs; 82. 83. (void) fseek(msg_file, hdr_offset, SEEK_SET); 84. Fread(&n_msgs, sizeof(int), 1, msg_file); 85. msg_list = (struct qtmsg *) alloc((n_msgs+1)*sizeof(struct qtmsg)); 86. 87. /* 88. * Load up the list. 89. */ 90. Fread((genericptr_t)msg_list, n_msgs*sizeof(struct qtmsg), 1, msg_file); 91. 92. msg_list[n_msgs].msgnum = -1; 93. return(msg_list); 94. } 95. 96. void 97. load_qtlist() 98. { 99. 100. int n_classes, i; 101. char qt_classes[N_HDR]; 102. long qt_offsets[N_HDR]; 103. 104. msg_file = fopen_datafile(QTEXT_FILE, RDMODE); 105. if (!msg_file) 106. panic("\rCANNOT OPEN QUEST TEXT FILE %s.", QTEXT_FILE); 107. 108. /* 109. * Read in the number of classes, then the ID's & offsets for 110. * each header. 111. */ 112. 113. Fread(&n_classes, sizeof(int), 1, msg_file); 114. Fread(qt_classes, sizeof(char), n_classes, msg_file); 115. Fread(qt_offsets, sizeof(long), n_classes, msg_file); 116. 117. /* 118. * Now construct the message lists for quick reference later 119. * on when we are actually paging the messages out. 120. */ 121. 122. qt_list.common = qt_list.chclass = (struct qtmsg *)0; 123. 124. for (i = 0; i < n_classes; i++) { 125. if (qt_classes[i] == COMMON_ID) 126. qt_list.common = construct_qtlist(qt_offsets[i]); 127. else if (qt_classes[i] == pl_character[0]) 128. qt_list.chclass = construct_qtlist(qt_offsets[i]); 129. } 130. 131. if (!qt_list.common || !qt_list.chclass) 132. impossible("load_qtlist: cannot load quest text."); 133. #ifdef DEBUG 134. dump_qtlist(); 135. #endif 136. return; /* no ***DON'T*** close the msg_file */ 137. } 138. 139. static struct qt_matrix { 140. 141. const char *intermed; /* intermediate goal text */ 142. const char *homebase; /* leader's "location" */ 143. 144. short ldrnum, /* mons[] indicies */ 145. neminum, 146. guardnum; 147. 148. short mtyp1, mtyp2; /* monster types for enemies 0 == random */ 149. char msym1, msym2; /* monster classes for enemies */ 150. 151. short artinum; /* index of quest artifact */ 152. 153. } qt_matrix[] = { 154. 155. /* A */ { "the tomb of the Toltec Kings", 156. "the College of Archeology", 157. PM_LORD_CARNARVON, PM_MINION_OF_HUHETOL, PM_STUDENT, 158. 0, PM_HUMAN_MUMMY, S_SNAKE, S_MUMMY, 159. ART_ORB_OF_DETECTION }, 160. 161. /* B */ { "the Duali Oasis", 162. "the Camp of the Duali Tribe", 163. PM_PELIAS, PM_THOTH_AMON, PM_CHIEFTAIN, 164. PM_OGRE, PM_TROLL, S_OGRE, S_TROLL, 165. ART_HEART_OF_AHRIMAN }, 166. 167. /* C */ { "the Dragon's Lair", 168. "the Caves of the Ancestors", 169. PM_SHAMAN_KARNOV, PM_CHROMATIC_DRAGON, PM_NEANDERTHAL, 170. PM_BUGBEAR, PM_HILL_GIANT, S_HUMANOID, S_GIANT, 171. ART_SCEPTRE_OF_MIGHT }, 172. 173. /* E */ { "the Goblins' Cave", 174. "the great Circle of Earendil", 175. PM_EARENDIL, PM_GOBLIN_KING, PM_HIGH_ELF, 176. PM_URUK_HAI, PM_OGRE, S_ORC, S_OGRE, 177. ART_PALANTIR_OF_WESTERNESSE }, 178. 179. /* E */ { "the Goblins' Cave", 180. "the great Circle of Elwing", 181. PM_ELWING, PM_GOBLIN_KING, PM_HIGH_ELF, 182. PM_URUK_HAI, PM_OGRE, S_ORC, S_OGRE, 183. ART_PALANTIR_OF_WESTERNESSE }, 184. 185. /* H */ { "the Temple of Coeus", 186. "the Isle of the Healers", 187. PM_HIPPOCRATES, PM_CYCLOPS, PM_NURSE, 188. PM_GIANT_RAT, PM_APE, S_RODENT, S_YETI, 189. ART_STAFF_OF_AESCULAPIUS }, 190. 191. /* K */ { "the Isle of Glass", 192. "Camelot Castle", 193. PM_KING_ARTHUR, PM_IXOTH, PM_PAGE, 194. PM_QUASIT, PM_OCHRE_JELLY, S_IMP, S_JELLY, 195. ART_MAGIC_MIRROR_OF_MERLIN }, 196. 197. /* P */ { "the Temple of Nalzok", 198. "the Great Temple", 199. PM_ARCH_PRIEST, PM_NALZOK, PM_ACOLYTE, 200. PM_HUMAN_ZOMBIE, PM_WRAITH, S_ZOMBIE, S_WRAITH, 201. ART_MITRE_OF_HOLINESS }, 202. 203. /* R */ { "the Asassins' Guild Hall", 204. "the Thieves' Guild Hall", 205. PM_MASTER_OF_THIEVES, PM_MASTER_ASSASSIN, PM_THUG, 206. PM_LEPRECHAUN, PM_GUARDIAN_NAGA, S_NYMPH, S_NAGA, 207. ART_MASTER_KEY_OF_THIEVERY }, 208. 209. /* S */ { "the Shogun's Castle", 210. "the castle of the Taro Clan", 211. PM_LORD_SATO, PM_ASHIKAGA_TAKAUJI, PM_NINJA, 212. PM_WOLF, PM_STALKER, S_DOG, S_STALKER, 213. ART_TSURUGI_OF_MURAMASA }, 214. 215. #ifdef TOURIST 216. /* T */ { "the Thieves' Guild Hall", 217. "the Traveller's Aid Office", 218. PM_TWOFLOWER, PM_MASTER_OF_THIEVES, PM_GUIDE, 219. PM_GIANT_SPIDER, PM_FOREST_CENTAUR, S_SPIDER, S_CENTAUR, 220. ART_YENDORIAN_EXPRESS_CARD }, 221. #endif 222. 223. /* V */ { "the cave of Surtur", 224. "the Shrine of Destiny", 225. PM_NORN, PM_LORD_SURTUR, PM_WARRIOR, 226. PM_FIRE_ANT, PM_FIRE_GIANT, S_ANT, S_GIANT, 227. ART_ORB_OF_FATE }, 228. 229. /* W */ { "the Tower of Darkness", 230. "the Tower of the Balance", 231. PM_WIZARD_OF_BALANCE, PM_DARK_ONE, PM_APPRENTICE, 232. PM_VAMPIRE_BAT, PM_XORN, S_BAT, S_WRAITH, 233. ART_EYE_OF_THE_AETHIOPICA }, 234. 235. /* - */ { "", "", 0, 0, 0, 0, 0, 0, 0, 0 } 236. }; 237. 238. static unsigned 239. class_index() 240. { 241. switch (pl_character[0]) { 242. 243. case 'A': return(0); 244. case 'B': return(1); 245. case 'C': return(2); 246. case 'E': return(3+flags.female); 247. case 'H': return(5); 248. case 'K': return(6); 249. case 'P': return(7); 250. case 'R': return(8); 251. case 'S': return(9); 252. #ifdef TOURIST 253. case 'T': return(10); 254. case 'V': return(11); 255. case 'W': return(12); 256. default: return(13); 257. #else 258. case 'V': return(10); 259. case 'W': return(11); 260. default: return(12); 261. #endif 262. } 263. } 264. 265. const char * 266. ldrname() /* return your class leader's name */ 267. { 268. int i = qt_matrix[class_index()].ldrnum; 269. /* return(mons[qt_matrix[class_index()].ldrnum].mname); */ 270. return(mons[i].mname); 271. } 272. 273. static const char * 274. intermed() /* return your intermediate target string */ 275. { 276. return(qt_matrix[class_index()].intermed); 277. } 278. 279. boolean 280. is_quest_artifact(otmp) 281. struct obj *otmp; 282. { 283. return(otmp->oartifact == qt_matrix[class_index()].artinum); 284. } 285. 286. static const char * 287. neminame() /* return your class nemesis' name */ 288. { 289. return(mons[qt_matrix[class_index()].neminum].mname); 290. } 291. 292. static const char * 293. guardname() /* return your class leader's guard monster name */ 294. { 295. return(mons[qt_matrix[class_index()].guardnum].mname); 296. } 297. 298. static const char * 299. homebase() /* return your class leader's location */ 300. { 301. return(qt_matrix[class_index()].homebase); 302. } 303. 304. boolean 305. leaderless() /* return true iff leader is dead */ 306. { 307. int i = qt_matrix[class_index()].ldrnum; 308. return (u.nr_killed[i] > 0); 309. } 310. 311. static struct qtmsg * 312. msg_in(qtm_list, msgnum) 313. struct qtmsg *qtm_list; 314. int msgnum; 315. { 316. struct qtmsg *qt_msg; 317. 318. for (qt_msg = qtm_list; qt_msg->msgnum > 0; qt_msg++) 319. if (qt_msg->msgnum == msgnum) return(qt_msg); 320. 321. return((struct qtmsg *)0); 322. } 323. 324. static void 325. convert_arg(c) 326. char c; 327. { 328. register const char *str; 329. 330. switch (c) { 331. 332. case 'p': str = plname; 333. break; 334. case 'c': str = pl_character; 335. break; 336. case 'r': str = rank_of(u.ulevel, pl_character[0], flags.female); 337. break; 338. case 'R': str = rank_of(MIN_QUEST_LEVEL, pl_character[0], 339. flags.female); 340. break; 341. case 's': str = (flags.female) ? "sister" : "brother"; 342. break; 343. case 'S': str = (flags.female) ? "daughter" : "son"; 344. break; 345. case 'l': str = ldrname(); 346. break; 347. case 'i': str = intermed(); 348. break; 349. case 'o': str = artiname(qt_matrix[class_index()].artinum); 350. break; 351. case 'n': str = neminame(); 352. break; 353. case 'g': str = guardname(); 354. break; 355. case 'H': str = homebase(); 356. break; 357. case 'a': str = align_str(u.ualignbase[0]); 358. break; 359. case 'A': str = align_str(u.ualign.type); 360. break; 361. case 'd': str = u_gname(); 362. break; 363. case 'D': str = align_gname(A_LAWFUL); 364. break; 365. case 'C': str = "chaotic"; 366. break; 367. case 'N': str = "neutral"; 368. break; 369. case 'L': str = "lawful"; 370. break; 371. case 'x': str = Blind ? "sense" : "see"; 372. break; 373. case '%': str = "%"; 374. break; 375. default: str = ""; 376. break; 377. } 378. Strcpy(cvt_buf, str); 379. } 380. 381. static void 382. convert_line() 383. { 384. char *c, *cc; 385. 386. cc = out_line; 387. for (c = xcrypt(in_line); *c; c++) { 388. 389. *cc = 0; 390. switch(*c) { 391. 392. case '\r': 393. case '\n': 394. *(++cc) = 0; 395. return; 396. 397. case '%': 398. if (*(c+1)) { 399. convert_arg(*(++c)); 400. switch (*(c+1)) { 401. 402. case 'P': cvt_buf[0] = highc(cvt_buf[0]); 403. case 'p': Strcpy(cvt_buf, makeplural(cvt_buf)); 404. c++; break; 405. 406. default: break; 407. } 408. Strcat(cc, cvt_buf); 409. cc += strlen(cvt_buf); 410. break; 411. } /* else fall through */ 412. 413. default: 414. *cc++ = *c; 415. break; 416. } 417. } 418. *cc = 0; 419. return; 420. } 421. 422. static void 423. deliver_by_pline(qt_msg) 424. struct qtmsg *qt_msg; 425. { 426. long size; 427. 428. for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) { 429. (void) fgets(in_line, 80, msg_file); 430. convert_line(); 431. pline(out_line); 432. } 433. 434. } 435. 436. static void 437. deliver_by_window(qt_msg) 438. struct qtmsg *qt_msg; 439. { 440. long size; 441. winid datawin = create_nhwindow(NHW_TEXT); 442. 443. for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) { 444. (void) fgets(in_line, 80, msg_file); 445. convert_line(); 446. putstr(datawin, 0, out_line); 447. } 448. display_nhwindow(datawin, TRUE); 449. destroy_nhwindow(datawin); 450. } 451. 452. void 453. com_pager(msgnum) 454. int msgnum; 455. { 456. struct qtmsg *qt_msg; 457. 458. if (!(qt_msg = msg_in(qt_list.common, msgnum))) { 459. impossible("com_pager: message %d not found.", msgnum); 460. return; 461. } 462. 463. (void) fseek(msg_file, qt_msg->offset, SEEK_SET); 464. if (qt_msg->delivery == 'p') deliver_by_pline(qt_msg); 465. else deliver_by_window(qt_msg); 466. return; 467. } 468. 469. void 470. qt_pager(msgnum) 471. int msgnum; 472. { 473. struct qtmsg *qt_msg; 474. 475. if (!(qt_msg = msg_in(qt_list.chclass, msgnum))) { 476. impossible("qt_pager: message %d not found.", msgnum); 477. return; 478. } 479. 480. (void) fseek(msg_file, qt_msg->offset, SEEK_SET); 481. if (qt_msg->delivery == 'p' && strcmp(windowprocs.name, "X11")) 482. deliver_by_pline(qt_msg); 483. else deliver_by_window(qt_msg); 484. return; 485. } 486. 487. struct permonst * 488. qt_montype() 489. { 490. int class = class_index(); 491. 492. if (rn2(5)) { 493. if (qt_matrix[class].mtyp1 && rn2(5) && 494. !(mons[qt_matrix[class].mtyp1].geno & G_GENOD)) 495. return(&mons[qt_matrix[class].mtyp1]); 496. return(mkclass(qt_matrix[class].msym1,0)); 497. } 498. if (qt_matrix[class].mtyp2 && rn2(5) && 499. !(mons[qt_matrix[class].mtyp1].geno & G_GENOD)) 500. return(&mons[qt_matrix[class].mtyp2]); 501. return(mkclass(qt_matrix[class].msym2,0)); 502. } 503. #endif /* MULDGN */ 504. 505. /*questpgr.c*/