Source:NetHack 3.3.0/questpgr.c

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!\nExpected %d bytes - got %d\n",  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("\rCANNOT 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 '\r': 309. 		case '\n': 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*/