Below is the full text to src/questpgr.c from NetHack 3.4.3. To link to a particular line, write [[questpgr.c#line123]], for example.
Top of file
Edit
1. /* SCCS Id: @(#)questpgr.c 3.4 2000/05/05 */
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.
dump_qtlist
Edit
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.
construct_qtlist
Edit
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.
load_qtlist
Edit
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.
unload_qtlist
Edit
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.
quest_info
Edit
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.
intermed
Edit
174. STATIC_OVL const char *
175. intermed() /* return your intermediate target string */
176. {
177. return (urole.intermed);
178. }
179.
is_quest_artifact
Edit
180. boolean
181. is_quest_artifact(otmp)
182. struct obj *otmp;
183. {
184. return((boolean)(otmp->oartifact == urole.questarti));
185. }
186.
neminame
Edit
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.
guardname
Edit
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.
homebase
Edit
206. STATIC_OVL const char *
207. homebase() /* return your role leader's location */
208. {
209. return(urole.homebase);
210. }
211.
212. STATIC_OVL struct qtmsg *
213. msg_in(qtm_list, msgnum)
214. struct qtmsg *qtm_list;
215. int msgnum;
216. {
217. struct qtmsg *qt_msg;
218.
219. for (qt_msg = qtm_list; qt_msg->msgnum > 0; qt_msg++)
220. if (qt_msg->msgnum == msgnum) return(qt_msg);
221.
222. return((struct qtmsg *)0);
223. }
224.
convert_arg
Edit
225. STATIC_OVL void
226. convert_arg(c)
227. char c;
228. {
229. register const char *str;
230.
231. switch (c) {
232.
233. case 'p': str = plname;
234. break;
235. case 'c': str = (flags.female && urole.name.f) ?
236. urole.name.f : urole.name.m;
237. break;
238. case 'r': str = rank_of(u.ulevel, Role_switch, flags.female);
239. break;
240. case 'R': str = rank_of(MIN_QUEST_LEVEL, Role_switch,
241. flags.female);
242. break;
243. case 's': str = (flags.female) ? "sister" : "brother";
244. break;
245. case 'S': str = (flags.female) ? "daughter" : "son";
246. break;
247. case 'l': str = ldrname();
248. break;
249. case 'i': str = intermed();
250. break;
251. case 'o': str = the(artiname(urole.questarti));
252. break;
253. case 'n': str = neminame();
254. break;
255. case 'g': str = guardname();
256. break;
257. case 'G': str = align_gtitle(u.ualignbase[A_ORIGINAL]);
258. break;
259. case 'H': str = homebase();
260. break;
261. case 'a': str = align_str(u.ualignbase[A_ORIGINAL]);
262. break;
263. case 'A': str = align_str(u.ualign.type);
264. break;
265. case 'd': str = align_gname(u.ualignbase[A_ORIGINAL]);
266. break;
267. case 'D': str = align_gname(A_LAWFUL);
268. break;
269. case 'C': str = "chaotic";
270. break;
271. case 'N': str = "neutral";
272. break;
273. case 'L': str = "lawful";
274. break;
275. case 'x': str = Blind ? "sense" : "see";
276. break;
277. case 'Z': str = dungeons[0].dname;
278. break;
279. case '%': str = "%";
280. break;
281. default: str = "";
282. break;
283. }
284. Strcpy(cvt_buf, str);
285. }
286.
convert_line
Edit
287. STATIC_OVL void
288. convert_line()
289. {
290. char *c, *cc;
291. char xbuf[BUFSZ];
292.
293. cc = out_line;
294. for (c = xcrypt(in_line, xbuf); *c; c++) {
295.
296. *cc = 0;
297. switch(*c) {
298.
299. case '\r':
300. case '\n':
301. *(++cc) = 0;
302. return;
303.
304. case '%':
305. if (*(c+1)) {
306. convert_arg(*(++c));
307. switch (*(++c)) {
308.
309. /* insert "a"/"an" prefix */
310. case 'A': Strcat(cc, An(cvt_buf));
311. cc += strlen(cc);
312. continue; /* for */
313. case 'a': Strcat(cc, an(cvt_buf));
314. cc += strlen(cc);
315. continue; /* for */
316.
317. /* capitalize */
318. case 'C': cvt_buf[0] = highc(cvt_buf[0]);
319. break;
320.
321. /* pluralize */
322. case 'P': cvt_buf[0] = highc(cvt_buf[0]);
323. case 'p': Strcpy(cvt_buf, makeplural(cvt_buf));
324. break;
325.
326. /* append possessive suffix */
327. case 'S': cvt_buf[0] = highc(cvt_buf[0]);
328. case 's': Strcpy(cvt_buf, s_suffix(cvt_buf));
329. break;
330.
331. /* strip any "the" prefix */
332. case 't': if (!strncmpi(cvt_buf, "the ", 4)) {
333. Strcat(cc, &cvt_buf[4]);
334. cc += strlen(cc);
335. continue; /* for */
336. }
337. break;
338.
339. default: --c; /* undo switch increment */
340. break;
341. }
342. Strcat(cc, cvt_buf);
343. cc += strlen(cvt_buf);
344. break;
345. } /* else fall through */
346.
347. default:
348. *cc++ = *c;
349. break;
350. }
351. }
352. if (cc >= out_line + sizeof out_line)
353. panic("convert_line: overflow");
354. *cc = 0;
355. return;
356. }
357.
deliver_by_pline
Edit
358. STATIC_OVL void
359. deliver_by_pline(qt_msg)
360. struct qtmsg *qt_msg;
361. {
362. long size;
363.
364. for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) {
365. (void) dlb_fgets(in_line, 80, msg_file);
366. convert_line();
367. pline(out_line);
368. }
369.
370. }
371.
deliver_by_window
Edit
372. STATIC_OVL void
373. deliver_by_window(qt_msg, how)
374. struct qtmsg *qt_msg;
375. int how;
376. {
377. long size;
378. winid datawin = create_nhwindow(how);
379.
380. for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) {
381. (void) dlb_fgets(in_line, 80, msg_file);
382. convert_line();
383. putstr(datawin, 0, out_line);
384. }
385. display_nhwindow(datawin, TRUE);
386. destroy_nhwindow(datawin);
387. }
388.
389. void
390. com_pager(msgnum)
391. int msgnum;
392. {
393. struct qtmsg *qt_msg;
394.
395. if (!(qt_msg = msg_in(qt_list.common, msgnum))) {
396. impossible("com_pager: message %d not found.", msgnum);
397. return;
398. }
399.
400. (void) dlb_fseek(msg_file, qt_msg->offset, SEEK_SET);
401. if (qt_msg->delivery == 'p') deliver_by_pline(qt_msg);
402. else if (msgnum == 1) deliver_by_window(qt_msg, NHW_MENU);
403. else deliver_by_window(qt_msg, NHW_TEXT);
404. return;
405. }
406.
407. void
408. qt_pager(msgnum)
409. int msgnum;
410. {
411. struct qtmsg *qt_msg;
412.
413. if (!(qt_msg = msg_in(qt_list.chrole, msgnum))) {
414. impossible("qt_pager: message %d not found.", msgnum);
415. return;
416. }
417.
418. (void) dlb_fseek(msg_file, qt_msg->offset, SEEK_SET);
419. if (qt_msg->delivery == 'p' && strcmp(windowprocs.name, "X11"))
420. deliver_by_pline(qt_msg);
421. else deliver_by_window(qt_msg, NHW_TEXT);
422. return;
423. }
424.
qt_montype
Edit
425. struct permonst *
426. qt_montype()
427. {
428. int qpm;
429.
430. if (rn2(5)) {
431. qpm = urole.enemy1num;
432. if (qpm != NON_PM && rn2(5) && !(mvitals[qpm].mvflags & G_GENOD))
433. return (&mons[qpm]);
434. return (mkclass(urole.enemy1sym, 0));
435. }
436. qpm = urole.enemy2num;
437. if (qpm != NON_PM && rn2(5) && !(mvitals[qpm].mvflags & G_GENOD))
438. return (&mons[qpm]);
439. return (mkclass(urole.enemy2sym, 0));
440. }
441.
442. /*questpgr.c*/