Source:NetHack 3.2.0/questpgr.c

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