From 48e35fe8a3f4f855aa6fd63f3f7b1a8d1f31a013 Mon Sep 17 00:00:00 2001 From: jwalz Date: Sat, 5 Jan 2002 21:05:52 +0000 Subject: [PATCH] *** empty log message *** --- src/questpgr.c | 451 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 451 insertions(+) create mode 100644 src/questpgr.c diff --git a/src/questpgr.c b/src/questpgr.c new file mode 100644 index 000000000..93351a6a3 --- /dev/null +++ b/src/questpgr.c @@ -0,0 +1,451 @@ +/* SCCS Id: @(#)questpgr.c 3.3 2000/05/05 */ +/* Copyright 1991, M. Stephenson */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" +#include "dlb.h" + +/* quest-specific pager routines. */ + +#include "qtext.h" + +#define QTEXT_FILE "quest.dat" + +/* #define DEBUG */ /* uncomment for debugging */ + +static void FDECL(Fread, (genericptr_t,int,int,dlb *)); +STATIC_DCL struct qtmsg * FDECL(construct_qtlist, (long)); +STATIC_DCL const char * NDECL(intermed); +STATIC_DCL const char * NDECL(neminame); +STATIC_DCL const char * NDECL(guardname); +STATIC_DCL const char * NDECL(homebase); +STATIC_DCL struct qtmsg * FDECL(msg_in, (struct qtmsg *,int)); +STATIC_DCL void FDECL(convert_arg, (CHAR_P)); +STATIC_DCL void NDECL(convert_line); +STATIC_DCL void FDECL(deliver_by_pline, (struct qtmsg *)); +STATIC_DCL void FDECL(deliver_by_window, (struct qtmsg *,int)); + +static char in_line[80], cvt_buf[64], out_line[128]; +static struct qtlists qt_list; +static dlb *msg_file; +/* used by ldrname() and neminame(), then copied into cvt_buf */ +static char nambuf[sizeof cvt_buf]; + +#ifdef DEBUG +static void NDECL(dump_qtlist); + +static void +dump_qtlist() /* dump the character msg list to check appearance */ +{ + struct qtmsg *msg; + long size; + + for (msg = qt_list.chrole; msg->msgnum > 0; msg++) { + pline("msgnum %d: delivery %c", + msg->msgnum, msg->delivery); + more(); + (void) dlb_fseek(msg_file, msg->offset, SEEK_SET); + deliver_by_window(msg, NHW_TEXT); + } +} +#endif /* DEBUG */ + +static void +Fread(ptr, size, nitems, stream) +genericptr_t ptr; +int size, nitems; +dlb *stream; +{ + int cnt; + + if ((cnt = dlb_fread(ptr, size, nitems, stream)) != nitems) { + + panic("PREMATURE EOF ON QUEST TEXT FILE!\nExpected %d bytes - got %d\n", + (size * nitems), (size * cnt)); + } +} + +STATIC_OVL struct qtmsg * +construct_qtlist(hdr_offset) +long hdr_offset; +{ + struct qtmsg *msg_list; + int n_msgs; + + (void) dlb_fseek(msg_file, hdr_offset, SEEK_SET); + Fread(&n_msgs, sizeof(int), 1, msg_file); + msg_list = (struct qtmsg *) + alloc((unsigned)(n_msgs+1)*sizeof(struct qtmsg)); + + /* + * Load up the list. + */ + Fread((genericptr_t)msg_list, n_msgs*sizeof(struct qtmsg), 1, msg_file); + + msg_list[n_msgs].msgnum = -1; + return(msg_list); +} + +void +load_qtlist() +{ + + int n_classes, i; + char qt_classes[N_HDR][LEN_HDR]; + long qt_offsets[N_HDR]; + + msg_file = dlb_fopen(QTEXT_FILE, RDBMODE); + if (!msg_file) + panic("\rCANNOT OPEN QUEST TEXT FILE %s.", QTEXT_FILE); + + /* + * Read in the number of classes, then the ID's & offsets for + * each header. + */ + + Fread(&n_classes, sizeof(int), 1, msg_file); + Fread(&qt_classes[0][0], sizeof(char)*LEN_HDR, n_classes, msg_file); + Fread(qt_offsets, sizeof(long), n_classes, msg_file); + + /* + * Now construct the message lists for quick reference later + * on when we are actually paging the messages out. + */ + + qt_list.common = qt_list.chrole = (struct qtmsg *)0; + + for (i = 0; i < n_classes; i++) { + if (!strncmp(COMMON_ID, qt_classes[i], LEN_HDR)) + qt_list.common = construct_qtlist(qt_offsets[i]); + else if (!strncmp(urole.filecode, qt_classes[i], LEN_HDR)) + qt_list.chrole = construct_qtlist(qt_offsets[i]); +#if 0 /* UNUSED but available */ + else if (!strncmp(urace.filecode, qt_classes[i], LEN_HDR)) + qt_list.chrace = construct_qtlist(qt_offsets[i]); +#endif + } + + if (!qt_list.common || !qt_list.chrole) + impossible("load_qtlist: cannot load quest text."); +#ifdef DEBUG + dump_qtlist(); +#endif + return; /* no ***DON'T*** close the msg_file */ +} + +/* called at program exit */ +void +unload_qtlist() +{ + if (msg_file) + (void) dlb_fclose(msg_file), msg_file = 0; + if (qt_list.common) + free((genericptr_t) qt_list.common), qt_list.common = 0; + if (qt_list.chrole) + free((genericptr_t) qt_list.chrole), qt_list.chrole = 0; + return; +} + +short +quest_info(typ) +int typ; +{ + switch (typ) { + case 0: return (urole.questarti); + case MS_LEADER: return (urole.ldrnum); + case MS_NEMESIS: return (urole.neminum); + case MS_GUARDIAN: return (urole.guardnum); + default: impossible("quest_info(%d)", typ); + } + return 0; +} + +const char * +ldrname() /* return your role leader's name */ +{ + int i = urole.ldrnum; + + Sprintf(nambuf, "%s%s", + type_is_pname(&mons[i]) ? "" : "the ", + mons[i].mname); + return nambuf; +} + +STATIC_OVL const char * +intermed() /* return your intermediate target string */ +{ + return (urole.intermed); +} + +boolean +is_quest_artifact(otmp) +struct obj *otmp; +{ + return((boolean)(otmp->oartifact == urole.questarti)); +} + +STATIC_OVL const char * +neminame() /* return your role nemesis' name */ +{ + int i = urole.neminum; + + Sprintf(nambuf, "%s%s", + type_is_pname(&mons[i]) ? "" : "the ", + mons[i].mname); + return nambuf; +} + +STATIC_OVL const char * +guardname() /* return your role leader's guard monster name */ +{ + int i = urole.guardnum; + + return(mons[i].mname); +} + +STATIC_OVL const char * +homebase() /* return your role leader's location */ +{ + return(urole.homebase); +} + +boolean +leaderless() /* return true iff leader is dead */ +{ + int i = urole.ldrnum; + /* BUG: This doesn't take the possibility of resurrection + via wand or spell of undead turning into account. */ + return (boolean)(mvitals[i].died > 0); +} + +STATIC_OVL struct qtmsg * +msg_in(qtm_list, msgnum) +struct qtmsg *qtm_list; +int msgnum; +{ + struct qtmsg *qt_msg; + + for (qt_msg = qtm_list; qt_msg->msgnum > 0; qt_msg++) + if (qt_msg->msgnum == msgnum) return(qt_msg); + + return((struct qtmsg *)0); +} + +STATIC_OVL void +convert_arg(c) +char c; +{ + register const char *str; + + switch (c) { + + case 'p': str = plname; + break; + case 'c': str = (flags.female && urole.name.f) ? + urole.name.f : urole.name.m; + break; + case 'r': str = rank_of(u.ulevel, Role_switch, flags.female); + break; + case 'R': str = rank_of(MIN_QUEST_LEVEL, Role_switch, + flags.female); + break; + case 's': str = (flags.female) ? "sister" : "brother"; + break; + case 'S': str = (flags.female) ? "daughter" : "son"; + break; + case 'l': str = ldrname(); + break; + case 'i': str = intermed(); + break; + case 'o': str = the(artiname(urole.questarti)); + break; + case 'n': str = neminame(); + break; + case 'g': str = guardname(); + break; + case 'G': str = align_gtitle(u.ualignbase[A_ORIGINAL]); + break; + case 'H': str = homebase(); + break; + case 'a': str = align_str(u.ualignbase[A_ORIGINAL]); + break; + case 'A': str = align_str(u.ualign.type); + break; + case 'd': str = align_gname(u.ualignbase[A_ORIGINAL]); + break; + case 'D': str = align_gname(A_LAWFUL); + break; + case 'C': str = "chaotic"; + break; + case 'N': str = "neutral"; + break; + case 'L': str = "lawful"; + break; + case 'x': str = Blind ? "sense" : "see"; + break; + case 'Z': str = dungeons[0].dname; + break; + case '%': str = "%"; + break; + default: str = ""; + break; + } + Strcpy(cvt_buf, str); +} + +STATIC_OVL void +convert_line() +{ + char *c, *cc; + char xbuf[BUFSZ]; + + cc = out_line; + for (c = xcrypt(in_line, xbuf); *c; c++) { + + *cc = 0; + switch(*c) { + + case '\r': + case '\n': + *(++cc) = 0; + return; + + case '%': + if (*(c+1)) { + convert_arg(*(++c)); + switch (*(++c)) { + + /* insert "a"/"an" prefix */ + case 'A': Strcat(cc, An(cvt_buf)); + cc += strlen(cc); + continue; /* for */ + case 'a': Strcat(cc, an(cvt_buf)); + cc += strlen(cc); + continue; /* for */ + + /* capitalize */ + case 'C': cvt_buf[0] = highc(cvt_buf[0]); + break; + + /* pluralize */ + case 'P': cvt_buf[0] = highc(cvt_buf[0]); + case 'p': Strcpy(cvt_buf, makeplural(cvt_buf)); + break; + + /* append possessive suffix */ + case 'S': cvt_buf[0] = highc(cvt_buf[0]); + case 's': Strcpy(cvt_buf, s_suffix(cvt_buf)); + break; + + /* strip any "the" prefix */ + case 't': if (!strncmpi(cvt_buf, "the ", 4)) { + Strcat(cc, &cvt_buf[4]); + cc += strlen(cc); + continue; /* for */ + } + break; + + default: --c; /* undo switch increment */ + break; + } + Strcat(cc, cvt_buf); + cc += strlen(cvt_buf); + break; + } /* else fall through */ + + default: + *cc++ = *c; + break; + } + } + if (cc >= out_line + sizeof out_line) + panic("convert_line: overflow"); + *cc = 0; + return; +} + +STATIC_OVL void +deliver_by_pline(qt_msg) +struct qtmsg *qt_msg; +{ + long size; + + for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) { + (void) dlb_fgets(in_line, 80, msg_file); + convert_line(); + pline(out_line); + } + +} + +STATIC_OVL void +deliver_by_window(qt_msg, how) +struct qtmsg *qt_msg; +int how; +{ + long size; + winid datawin = create_nhwindow(how); + + for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) { + (void) dlb_fgets(in_line, 80, msg_file); + convert_line(); + putstr(datawin, 0, out_line); + } + display_nhwindow(datawin, TRUE); + destroy_nhwindow(datawin); +} + +void +com_pager(msgnum) +int msgnum; +{ + struct qtmsg *qt_msg; + + if (!(qt_msg = msg_in(qt_list.common, msgnum))) { + impossible("com_pager: message %d not found.", msgnum); + return; + } + + (void) dlb_fseek(msg_file, qt_msg->offset, SEEK_SET); + if (qt_msg->delivery == 'p') deliver_by_pline(qt_msg); + else if (msgnum == 1) deliver_by_window(qt_msg, NHW_MENU); + else deliver_by_window(qt_msg, NHW_TEXT); + return; +} + +void +qt_pager(msgnum) +int msgnum; +{ + struct qtmsg *qt_msg; + + if (!(qt_msg = msg_in(qt_list.chrole, msgnum))) { + impossible("qt_pager: message %d not found.", msgnum); + return; + } + + (void) dlb_fseek(msg_file, qt_msg->offset, SEEK_SET); + if (qt_msg->delivery == 'p' && strcmp(windowprocs.name, "X11")) + deliver_by_pline(qt_msg); + else deliver_by_window(qt_msg, NHW_TEXT); + return; +} + +struct permonst * +qt_montype() +{ + int qpm; + + if (rn2(5)) { + qpm = urole.enemy1num; + if (qpm != NON_PM && rn2(5) && !(mvitals[qpm].mvflags & G_GENOD)) + return (&mons[qpm]); + return (mkclass(urole.enemy1sym, 0)); + } + qpm = urole.enemy2num; + if (qpm != NON_PM && rn2(5) && !(mvitals[qpm].mvflags & G_GENOD)) + return (&mons[qpm]); + return (mkclass(urole.enemy2sym, 0)); +} + +/*questpgr.c*/