diff --git a/include/context.h b/include/context.h index 22a43fa02..772df192f 100644 --- a/include/context.h +++ b/include/context.h @@ -75,12 +75,13 @@ struct warntype_info { struct tribute_info { size_t tributesz; /* make it possible to skip this in future */ - char *name; /* what is this tribute for */ boolean enabled; /* Do we have tributes turned on? */ - Bitfield(book,1); /* Have we completed the book tribute? */ + Bitfield(bookstock,1); /* Have we stocked the book? */ /* Markers for other tributes can go here */ /* 31 free bits */ - int bookidx; + int bookidx; /* Index of book in list of book titles */ + int passagecnt; /* Number of passages for this book avail */ + int passagenum; /* Passage last read */ }; struct context_info { diff --git a/include/extern.h b/include/extern.h index f0c8e8c74..f382f8ca2 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1839,6 +1839,7 @@ E void FDECL(punish, (struct obj *)); E void NDECL(unpunish); E boolean FDECL(cant_revive, (int *,BOOLEAN_P,struct obj *)); E boolean NDECL(create_particular); +E void FDECL(read_tribbook, (const char *, struct obj *)); /* ### rect.c ### */ diff --git a/include/global.h b/include/global.h index a67066d64..50479b97e 100644 --- a/include/global.h +++ b/include/global.h @@ -33,6 +33,7 @@ #define EPITAPHFILE "epitaph" /* random epitaphs on graves */ #define ENGRAVEFILE "engrave" /* random engravings on the floor */ #define BOGUSMONFILE "bogusmon" /* hallucinatory monsters */ +#define TRIBUTEFILE "tribute" /* 3.6 tribute to Terry Pratchett */ #define LEV_EXT ".lev" /* extension for special level files */ diff --git a/src/read.c b/src/read.c index 9be9f9390..ef46903c3 100644 --- a/src/read.c +++ b/src/read.c @@ -4,6 +4,7 @@ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" +#include "dlb.h" #define Your_Own_Role(mndx) \ ((mndx) == urole.malenum || \ @@ -2119,4 +2120,134 @@ create_particular() return madeany; } +/* 3.6 tribute code */ + +#define SECTIONSCOPE 1 +#define BOOKSCOPE 2 +#define PASSAGESCOPE 3 + +void +read_tribbook(tribtitle, bookobj) +char *tribtitle; +struct obj *bookobj; +{ + dlb *fp; + char *endp; + char line[BUFSZ]; + + int scopes[4] = {0, SECTIONSCOPE, BOOKSCOPE, PASSAGESCOPE}; + int scope = 0, section = 0, passage = 0, book = 0; + int linect = 0, passagecnt = 0, rndpassage = 0; + char *sectionnm = "", *booknm = ""; + boolean matched = FALSE; + winid tribwin = WIN_ERR; + + if (!tribtitle || !bookobj) { + pline("It is an incomprehensible foreign translation of \"%s\"", + tribtitle); + return; + } + + debugpline2("Reading %s, a %s.", tribtitle, xname(bookobj)); + + fp = dlb_fopen(TRIBUTEFILE, "r"); + if (!fp) { + /* this is actually an error - cannot open tribute file! */ + pline("Overcome with fond memories, you snap \"%s\" shut!", + tribtitle); + return; + } + + /* + * Syntax (not case-sensitive): + * %section books + * %section death + * + * In the books section: + * %book title(n) + * where title=book title + * (n)= total number of passages present for this book + * %passage n + * where n=sequential passage number + * + * %e ends the passage/book/section + * If in a passage, it marks the end of that passage. + * If in a book, it marks the end of that book. + * If in a section, it marks the end of that section. + */ + + while (dlb_fgets(line, sizeof line, fp) != 0) { + linect++; + if ((endp = index(line, '\n')) != 0) *endp = 0; + switch (line[0]) { + case '%': + if (!strncmpi(&line[1], "section ", sizeof("section ")-1)) { + + } else if (!strncmpi(&line[1], "book ", sizeof("book ")-1)) { + char *st = &line[6], *p1, *p2; + if ((p1 = index(st, '(')) != 0) { + *p1++ = '\0'; + if ((p2 = index(p1, ')')) != 0) { + *p2 = '\0'; + passagecnt = atoi(p1); + /* sanity check here caps #passages at 50 */ + if ((passagecnt > 0) && (passagecnt < 50)) { + scope = BOOKSCOPE; + if (!strcmpi(st, tribtitle)) { + matched = TRUE; + rndpassage = rnd(passagecnt); + context.tribute.passagecnt = passagecnt; + context.tribute.passagenum = rndpassage; + } else { + matched = FALSE; + rndpassage = 0; + context.tribute.passagecnt = 0; + context.tribute.passagenum = 0; + + /* this should not happen, but compensate */ + if (tribwin != WIN_ERR) + destroy_nhwindow(tribwin); + } + } + } + } + } else if (!strncmpi(&line[1], "passage ", sizeof("passage ")-1)) { + int passagenum = 0; + char *st = &line[9]; + while(*st == ' ' || *st == '\t') st++; + if (*st && digit(*st) && (strlen(st) < 3)) + passagenum = atoi(st); + if (passagenum && (passagenum <= passagecnt)) { + scope = PASSAGESCOPE; + if (passagenum == rndpassage) + tribwin = create_nhwindow(NHW_MENU); + } + } else if (!strncmpi(&line[1], "e ", sizeof("e ")-1)) { + if (matched && (scope == PASSAGESCOPE) && tribwin != WIN_ERR) + goto cleanup; + } else { + pline("tribute file error: bad %%e command, line %d.", + linect); + } + break; + case '#': + /* comment only, next! */ + break; + default: + if (matched && (scope == PASSAGESCOPE) && tribwin != WIN_ERR) { + putstr(tribwin, 0, line); + } + } + } + +cleanup: + if (tribwin != WIN_ERR) { + if (matched && (scope == PASSAGESCOPE)) + display_nhwindow(tribwin, FALSE); + destroy_nhwindow(tribwin); + tribwin = WIN_ERR; + } + (void) dlb_fclose(fp); + return; +} /*read.c*/ diff --git a/src/shknam.c b/src/shknam.c index ae1776cc4..88b983c8d 100644 --- a/src/shknam.c +++ b/src/shknam.c @@ -373,7 +373,9 @@ boolean mkspecl; struct obj *novel=mksobj_at(SPE_NOVEL, sx, sy, FALSE, FALSE); if (novel) novel = oname(novel, noveltitle(&novidx)); context.tribute.bookidx = novidx; - context.tribute.book = 1; + context.tribute.passagecnt = 0; + context.tribute.passagenum = 0; + context.tribute.bookstock = TRUE; return; } @@ -620,7 +622,7 @@ register struct mkroom *sroom; make_engr_at(m, n, buf, 0L, DUST); } - if (context.tribute.enabled && !context.tribute.book) { + if (context.tribute.enabled && !context.tribute.bookstock) { /* * Out of the number of spots where we're actually * going to put stuff, randomly single out one in particular. diff --git a/src/spell.c b/src/spell.c index 05782cbae..cf847c089 100644 --- a/src/spell.c +++ b/src/spell.c @@ -413,7 +413,6 @@ register struct obj *spellbook; { int booktype = spellbook->otyp; boolean confused = (Confusion != 0); - const char *whatchadoin = "memorize the spell"; boolean too_hard = FALSE; /* attempting to read dull book may make hero fall asleep */ @@ -454,15 +453,9 @@ register struct obj *spellbook; /* 3.6 tribute */ if (booktype == SPE_NOVEL) { /* Obtain current Terry Pratchett book - title for the current game. */ + title for the current game. */ const char *tribtitle = noveltitle(&context.tribute.bookidx); - - /* - * Place code here to pull desireable - * random passages from somewhere (data.base?) - * using tribtitle as the key? - */ - pline("Reading \"%s.\"", tribtitle); /* debug confirmation */ + read_tribbook(tribtitle, spellbook); return(1); } diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index 847aa3797..070ecd80d 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -305,6 +305,9 @@ PDBFILE= /PDB:"$(O)$(GAME).PDB" MAPFILE= /MAP:"$(O)$(GAME).MAP" INCLDIR= /I..\include +ldebug=/DEBUG +cdebug = -Zi -Od + !IF ("$(ldebug)" != "") !IF ("$(ldebug)" != "/RELEASE") ldebug = /DEBUG @@ -341,14 +344,14 @@ LIBS= user32.lib winmm.lib $(ZLIB) !IF ("$(GRAPHICAL)"=="Y") cflagsGame = $(cdebug) $(cflags2) $(guiflags) $(INCLDIR) \ - $(WINPFLAG) $(DLBFLG) $(GAMEPDBFILE) $(GAMEMAPFILE) -lflagsGame = $(ldebug) $(lflags) $(guilibs) + $(WINPFLAG) $(DLBFLG) +lflagsGame = $(ldebug) $(lflags) $(guilibs) $(GAMEPDBFILE) $(GAMEMAPFILE) !ELSE cflagsGame = $(cdebug) $(cflags2) $(conflags) $(INCLDIR) \ - $(WINPFLAG) $(DLBFLG) $(GAMEPDBFILE) $(GAMEMAPFILE) -lflagsGame = $(ldebug) $(lflags) $(conlibs) + $(WINPFLAG) $(DLBFLG) +lflagsGame = $(ldebug) $(lflags) $(conlibs) $(GAMEPDBFILE) $(GAMEMAPFILE) !ENDIF @@ -607,6 +610,7 @@ all : install install: envchk $(GAME) $(O)install.tag @echo Done. + $(O)install.tag: $(DAT)\data $(DAT)\rumors $(DAT)\dungeon \ $(DAT)\oracles $(DAT)\quest.dat $(O)sp_lev.tag $(DLB) ! IF ("$(USE_DLB)"=="Y") @@ -840,6 +844,14 @@ $(INCL)\vis_tab.h: $(U)makedefs.exe $(SRC)\vis_tab.c: $(U)makedefs.exe $(U)makedefs -z +$(DAT)\engrave: $(DAT)\engrave.txt $(U)makedefs.exe + ..\util\makedefs -s +$(DAT)\epitaph: $(DAT)\epitaph.txt $(U)makedefs.exe + ..\util\makedefs -s +$(DAT)\bogusmon: $(DAT)\bogusmon.txt $(U)makedefs.exe + ..\util\makedefs -s + + #========================================== # uudecode utility and uuencoded targets #========================================== @@ -1081,7 +1093,8 @@ $(DAT)\porthelp: $(NTSYS)\porthelp nhdat: $(U)dlb_main.exe $(DAT)\data $(DAT)\oracles $(OPTIONS_FILE) \ $(DAT)\quest.dat $(DAT)\rumors $(DAT)\help $(DAT)\hh $(DAT)\cmdhelp \ $(DAT)\history $(DAT)\opthelp $(DAT)\wizhelp $(DAT)\dungeon $(DAT)\porthelp \ - $(DAT)\license $(O)sp_lev.tag + $(DAT)\license $(DAT)\engrave $(DAT)\epitaph $(DAT)\bogusmon \ + $(DAT)\tribute $(O)sp_lev.tag cd $(DAT) echo data >dlb.lst echo oracles >>dlb.lst @@ -1091,6 +1104,10 @@ nhdat: $(U)dlb_main.exe $(DAT)\data $(DAT)\oracles $(OPTIONS_FILE) \ if exist porthelp echo porthelp >>dlb.lst echo quest.dat >>dlb.lst echo rumors >>dlb.lst + echo engrave >>dlb.lst + echo epitaph >>dlb.lst + echo bogusmon >>dlb.lst + echo tribute >>dlb.lst echo help >>dlb.lst echo hh >>dlb.lst echo cmdhelp >>dlb.lst @@ -1238,6 +1255,9 @@ spotless: clean if exist $(U)*.map del $(U)*.map if exist $(DAT)\data del $(DAT)\data if exist $(DAT)\rumors del $(DAT)\rumors + if exist $(DAT)\engrave del $(DAT)\engrave + if exist $(DAT)\epitaph del $(DAT)\epitaph + if exist $(DAT)\bogusmon del $(DAT)\bogusmon if exist $(DAT)\???-fil?.lev del $(DAT)\???-fil?.lev if exist $(DAT)\???-goal.lev del $(DAT)\???-goal.lev if exist $(DAT)\???-loca.lev del $(DAT)\???-loca.lev