Fandom

Wikihack

Source:NetHack 3.1.0/questpgr.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

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.
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*/

Also on Fandom

Random Wiki