games-request@tekred.TEK.COM (12/02/87)
Submitted by: mike@genat.UUCP (Mike Stephenson) Comp.sources.games: Volume 3, Issue 13 Archive-name: nethack2.2/Part13 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 13 (of 20)." # Contents: Fixes.2.2 cmd.c date.h save.c spell.c unixunix.c # Wrapped by billr@tekred on Tue Dec 1 16:25:06 1987 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f Fixes.2.2 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Fixes.2.2\" else echo shar: Extracting \"Fixes.2.2\" \(8320 characters\) sed "s/^X//" >Fixes.2.2 <<'END_OF_Fixes.2.2' X NetHack Fixes List Revision 2.2 X XGuidebook.mn New file "Guide to the Mazes of Menace". By Eric Raymond. XGuidebook A file for preparation using the "mn" macros supplied with X the 2.11 news release, as well as an ascii version of the X same. X XNetHack.cnf Sample configuration file for the PC. (creps@silver) X XMakefiles Corrected problem in which the linking was done on build and X(unix/xenix) on install. (Contributed by Janet Walz - walz@mimsy) X XMakefile.att Added a makefile for the AT&T Unix PC using shared libraries. X (Contributed by ahby@umn-cs) X XMakefile.pc Streamlined compilation of main.o, tty.o, and unix.o XMakefile.tcc (Contributed by polder@cs.vu.nl). X Xdata.base deletion of duplicate lines and spelling fixes. (sweet@scubed) X Xinvent.c REDO problem with "What do you want to..." text fixed. X down stairway identification fixed. X Alloc "buf" to allow for variable length HI/HE. (tom@uw-warp) X Xengrave.c Correction to "feel" code. (mike@genat) X Corrected switch for message determination. (patrickm@hpisof0) X BURN'ed engravings made un-erasable again. (kyrimis@princeton) X Xpri.c Added colour highliting functions (sweet@scubed) X Xprisym.c changed "symbol.room" to "ROOM_SYM" (one I missed) X (Ralf.Brown@b.gp.cs.cmu.edu) X Changed "dirlet()" to return an int. (maartenj@cs.vu.nl) X Xmsdos.c Changed "symbol" to "showsyms" (Ralf.Brown@b.gp.cs.cmu.edu) X Fixed up REDO & IBMBIOS stuff. (Kevin Sweet - sweet@scubed) X Xdo.c Dropping gold asked for only when gold posessed. (walz@mimsy) X Potential unsigned value problem fixed (u.ucreamed) X Added leash dropping code. (maartenj@cs.vu.nl) X Blind modifications for blindfolding. (eric@snark) X Value wrap fixed for u.ucreamed X Xfight.c Dog's name now used in hitting avoidence message. (walz@mimsy) X Variable initialization fixed w.r.t. #ifdef / #else. X (Reported by Erwin Unruh - unruh@infbs) X Added giant rats and kobolds back into code. (sweet@scubed) X Xspell.c Potential unsigned value problem fixed (u.ulevel). X Typos corrected. (Tom May - tom@uw-warp) X Blind modifications for blindfolding. (eric@snark) X Xshk.c "inshop" crash bug corrected (many sources). X extern declaration of carrying() moved to avoid a Turbo-C X type mismatch msg. (Ralf.Brown@b.gp.cs.cmu.edu) X Added new "online()" which executes faster. (tom@uw-warp) X Blind modifications for blindfolding. (eric@snark) X Added item pricing shopkeeper talk. X (Idea from a hacked up 1.0.1 source sent in by michael@stb) X Cleaned up Kops code. (sweet@scubed) X Xmhitu.c Argument mismatches fixed. (walz@mimsy) X Scorpion/spider mixup fix. (William LeFebvre - phil@rice.edu) X Blind modifications for blindfolding. (eric@snark) X Xpotion.c Argument mismatch fixed. (walz@mimsy) X Blind modifications for blindfolding. (eric@snark) X Poison handling made more dependant on poison resistance. X (From an idea by Steve Creps - creps@silver) X Xmklev.c Fixed up installation of vamp traps. (sweet@scubed) X Xmakemon.c Monster creation location bug fixed. (walz@mimsy) X Monster creation crash fixed. (many sources) X Monster posessions bug fixed. (S. Wrammerfors stewr@obelix) X Added giant rats and kobolds back into code. (sweet@scubed) X Xhack.c "Elbereth" effectiveness increased under "HARD" option to X be reasonable. (walz@mimsy) X Declaration of "register struct monst *m_at()" fixed. (many) X Typo fixed. (tom@uw-warp) X Fixed scroll of scare monster pickup problems (and giveaway) X (polder@cs.vu.nl) X Documentation modifications for blindfolding. (eric@snark) X Xioctl.c ioctl call for SET changed to function properly under X Xunixtty.c Sys V R3 mods. (tom@uw-warp) X Xdecl.c in_doagain initialized. (many sources) X Xwield.c Ability to remove cursed weapons w. w- removed. (many sources) X Xoptions.c Major rewrite of options help. Now uses pager. (mike@genat) X Rewrote GRAPHICS setup. (maartenj@cs.vu.nl) X Allowed reassignment of inventory order #ifdef DGK X (polder@cs.vu.nl) X Xpray.c Fixed mk_obj of spellbook under all conditions to make book X if "SPELLS" defined, and scroll otherwise. (unruh@infbs) X Fixed typo in "gods angry" text. (tom@uw-warp) X Fixed blessing code. (Simon Brown - simon@its63b) X Blind modifications for blindfolding. (eric@snark) X Xzap.c Potion of invis. breakage message improved. (unruh@infbs) X Added WAN_PROBING to "zapyourself". X Changed "dirlet()" to return an int. (maartenj@cs.vu.nl) X Fixed cancellation code to work properly on wands (spe X set to -1 instead of 0) this means no infinite wands of X wishing. (Ron Wessels - ron@utcsri) X Fixed bug in "buzz()" causing crash when destroying a X trapper from inside with a wand/spell. (mike@genat) X Added fcn to destroy wands with zero charges. (sweet@scubed) X Xpcmain.c Added a routine to zero out the fileinfo array in order to X prevent crashes on level change. (ralf@b.gp.cs.cmu.edu) X Added chdir to HACKDIR before looking for .CNF file. X Added call "uptodate(savefile)". (polder@cs.vu.nl) X Xpager.c changed "cornline()" to use xputs for HI/HE. (tom@uw-warp) X added choice for dowhatis() to allow letter or cursor object X selection. (polder@cs.vu.nl) X Xcmd.c Added ^W (wish) and ^I (ident-all) commands for WIZARD-mode. X (Paul Polderman - polder@cs.vu.nl) X Added "Z" as alternate to "# cast" (Eric Raymond - eric@snark) X Xu_init.c Expanded a tab which didn't show in raw mode. X Changed trobj.trotyp to "unsigned short" to avoid >255 X problems. (Maarten Jan Huisjes - maartenj@cs.vu.nl) X Removed wand of wishing from WIZARD's inventory (due to X the above cmd additions). (polder@cs.vu.nl) X Fixed declaration of leash. (simon@its63b) X Beefed up Wizard class. X Added Wakizashi for Samurai. X Added holy water for Priest(ess)es. X Modifications to provide blindfolds. (eric@snark) X Xend.c changed inventory identification on death to list form. X (polder@cs.vu.nl) X added hallucination effects to done_in_by() X added posession of amulet flag for scoreboard (sweet@scubed) X Xwizard.c corrected "nasties" decl. (maartenj@cs.vu.nl) X Blind modifications for blindfolding. (eric@snark) X Xdo_wear.c Prot. from shape changers logic fixed. (maartenj@cs.vu.nl) X Xlev.c Prot. from shape changers logic fixed. (maartenj@cs.vu.nl) X Xmon.c Inserted cast to fix compiler warning. (maartenj@cs.vu.nl) X Nymphs now leave potions of object detection when killed. X Kops now don't leave treasure behind. (sweet@scubed) X Xtopl.c Changed size of "toplines" to avoid overflow in "parseoptions" X when help is asked for. (probably n/a) (maartenj@cs.vu.nl) X Xtopten.c Added longer death descriptions, including name of X shopkeeper who killed character. (many sources) X Xtermcap.c Changed allocation of HI/HO for copying SI/SO to allow room X for null. (maartenj@cs.vu.nl) X Added PCHack 3.61 termcap stuff. X Added colour highliting code. (sweet@scubed) X Xversion.c Expanded a tab for rawmode io. (maartenj@cs.vu.nl) X Xobjnam.c Allow the WIZARD to wish for really excessive objects. X (polder@cs.vu.nl) X Xmakedefs.c Added "freopen" which works (MSC 4.0 drops first couple X of lines). Solves missing #define AMULET... problem. X (Nathan Glasser - nathan@mit-eddie) X Xrnd.c Changed around random number generation: X BSD uses "random()". (Paul Eggert - eggert@grand) X SYSV uses "lrand48()". (mike@genat from above) X Xeat.c Changed "choke()" code to waste food rather than choke on X it #ifndef HARD. (Allan Pratt - apratt@atari) X Blind modifications for blindfolding. (eric@snark) X Xobjects.h added blindfold object (tool). (eric@snark) X Xyou.h changed Blind/BLIND to Blinded/Blinded X added Blindfolded/BLINDFOLDED X redefined Blind in terms of above parameters. (eric@snark) X Xapply.c added blindfold code. (eric@snark) X Xtimeout.c Blind modifications for blindfolding. (eric@snark) X Xsit.c Blind modifications for blindfolding. (eric@snark) X Xtrap.c Blind modifications for blindfolding. (eric@snark) X Level teleportation to hell fixed so that it will not X do so unless character has Fire_resistance. (many sources) X Added polymorph trap. (many sources) X Xmonmove.c added check on presence of "fobj" before atl() call X to avoid potential segmentation problem with ROCKMOLE. X (Reported by Doug Rudoff - doug@wiley) X Xvarious files Fixed typos. Also converted British English words to X American English for uniformity. (Original list of typos X submitted by Steve Creps - creps@silver) END_OF_Fixes.2.2 if test 8320 -ne `wc -c <Fixes.2.2`; then echo shar: \"Fixes.2.2\" unpacked with wrong size! fi # end of overwriting check fi if test -f cmd.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"cmd.c\" else echo shar: Extracting \"cmd.c\" \(10896 characters\) sed "s/^X//" >cmd.c <<'END_OF_cmd.c' X/* SCCS Id: @(#)cmd.c 2.0 87/09/15 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include "hack.h" X#include "func_tab.h" X Xint doredraw(),doredotopl(),dodrop(),dodrink(),doread(),dosearch(),dopickup(), Xdoversion(),doweararm(),dowearring(),doremarm(),doddoremarm(),doremring(), Xdopay(),doapply(),dosave(),dowield(),ddoinv(),dozap(),ddocall(),dowhatis(), Xdoengrave(),dotele(),dohelp(),doeat(),doddrop(),do_mname(),doidtrap(), Xdoprwep(),doprarm(),doprring(),doprgold(),dodiscovered(),dotypeinv(),dolook(), Xdoset(),doup(), dodown(), done1(), donull(), dothrow(), doextcmd(), dodip(), Xdopray(), doextlist(); X#ifdef WIZARD Xint wiz_wish(), wiz_identify(); X#endif X#ifdef NEWCLASS Xint dosit(), doturn(); X#endif X#ifdef SPELLS Xint docast(), dovspell(), doxcribe(); X#endif X#ifdef SHELL Xint dosh(); X#endif X#ifdef SUSPEND Xint dosuspend(); X#endif X#ifdef KAA Xint doremove(), dobreathe(); X# ifdef KOPS Xint dowipe(); X# endif X#endif X Xint rndobjsym(), rndmonsym(); Xchar *hcolor(), *rndmonnam(), *defmonnam(); X Xextern char *occtxt; Xextern int (*occupation)(); X X#ifdef DGKMOD Xint dotogglepickup(), doMSCversion(); X# ifdef DEBUG Xint dodebug(); X# endif X Xstatic int (*timed_occ_fn)(); X X/* Count down by decrementing multi */ Xtimed_occupation() { X (*timed_occ_fn)(); X if (multi > 0) X multi--; X return (multi > 0); X} X X/* If a time is given, use it to timeout this function, otherwise the X * function times out by its own means. X */ Xvoid Xset_occupation(fn, txt, time) Xint (*fn)(); Xchar *txt; X{ X if (time) { X occupation = timed_occupation; X timed_occ_fn = fn; X } else X occupation = fn; X occtxt = txt; X occtime = 0; X} X#endif /* DGKMOD */ X X#ifdef REDO X/* Provide a means to redo the last command. The flag `in_doagain' is set X * to true while redoing the command. This flag is tested in commands that X * require additional input (like `throw' which requires a thing and a X * direction), and the input prompt is not shown. Also, while in_doagain is X * TRUE, no keystrokes can be saved into the saveq. X */ X#define BSIZE 20 Xstatic char pushq[BSIZE], saveq[BSIZE]; Xstatic int phead, ptail, shead, stail; Xextern int in_doagain; X Xchar Xpopch() { X /* If occupied, return 0, letting tgetch know a character should X * be read from the keyboard. If the character read is not the X * ABORT character (as checked in main.c), that character will be X * pushed back on the pushq. X */ X if (occupation) return(0); X if (in_doagain) return ((shead != stail) ? saveq[stail++] : 0); X else return ((phead != ptail) ? pushq[ptail++] : 0); X} X X/* A ch == 0 resets the pushq */ Xvoid Xpushch(ch) Xchar ch; X{ X if (!ch) X phead = ptail = 0; X if (phead < BSIZE) X pushq[phead++] = ch; X} X X/* A ch == 0 resets the saveq. Only save keystrokes when not X * replaying a previous command. X */ Xvoid Xsavech(ch) Xchar ch; X{ X if (!in_doagain) { X if (!ch) X phead = ptail = shead = stail = 0; X else if (shead < BSIZE) X saveq[shead++] = ch; X } X} X#endif /* REDO */ X Xstruct func_tab cmdlist[]={ X#ifdef WIZARD X {'\011', wiz_identify}, X#endif X {'\020', doredotopl}, X {'\022', doredraw}, X {'\024', dotele}, X#ifdef WIZARD X {'\027', wiz_wish}, X#endif X#ifdef SUSPEND X {'\032', dosuspend}, X#endif X {'a', doapply}, X {'A', doddoremarm}, X/* 'b', 'B' : go sw */ X {'c', ddocall}, X {'C', do_mname}, X {'d', dodrop}, X {'D', doddrop}, X {'e', doeat}, X {'E', doengrave}, X/* Soon to be X {'f', dofight, "fighting"}, X {'F', doFight, "fighting"}, X */ X/* 'g', 'G' : multiple go */ X/* 'h', 'H' : go west */ X {'I', dotypeinv}, /* Robert Viduya */ X {'i', ddoinv}, X/* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */ X/* 'o', doopen, */ X {'O', doset}, X {'p', dopay}, X {'P', dowearring}, X {'q', dodrink}, X {'Q', done1}, X {'r', doread}, X {'R', doremring}, X {'s', dosearch, "searching"}, X {'S', dosave}, X {'t', dothrow}, X {'T', doremarm}, X/* 'u', 'U' : go ne */ X {'v', doversion}, X {'w', dowield}, X {'W', doweararm}, X#ifdef SPELLS X {'x', dovspell}, /* Mike Stephenson */ X {'X', doxcribe}, /* Mike Stephenson */ X#endif X/* 'y', 'Y' : go nw */ X {'z', dozap}, X#ifdef SPELLS X {'Z', docast}, X#endif X {'<', doup}, X {'>', dodown}, X {'/', dowhatis}, X {'?', dohelp}, X#ifdef SHELL X {'!', dosh}, X#endif X {'.', donull, "waiting"}, X {' ', donull, "waiting"}, X {',', dopickup}, X {':', dolook}, X {'^', doidtrap}, X {'\\', dodiscovered}, /* Robert Viduya */ X#ifdef DGKMOD X {'@', dotogglepickup}, X {'V', doMSCversion}, X# ifdef DEBUG_DOESNT_WORK X {'\004', dodebug}, /* generic debug function */ X# endif X#endif X {WEAPON_SYM, doprwep}, X {ARMOR_SYM, doprarm}, X {RING_SYM, doprring}, X {GOLD_SYM, doprgold}, X {'#', doextcmd}, X {0,0,0} X}; X Xstruct ext_func_tab extcmdlist[] = { X#ifdef KAA X "breathe", "breathe like a dragon", dobreathe, X#endif X#ifdef SPELLS X "cast", "cast a spell", docast, X#endif X "dip", "dip an object into something", dodip, X "pray", "pray to the gods for help", dopray, X#ifdef KAA X "remove", "remove a cursed item", doremove, X#endif X#ifdef NEWCLASS X "sit", "sit down", dosit, X "turn", "turn undead", doturn, X#endif X#if defined(KOPS) && defined(KAA) X "wipe", "wipe your face off", dowipe, X#endif X "?", "get this list of extended commands", doextlist, X (char *) 0, (char *) 0, donull X}; X Xextern char *parse(), lowc(), unctrl(), quitchars[]; X Xrhack(cmd) Xregister char *cmd; X{ X register struct func_tab *tlist = cmdlist; X boolean firsttime = FALSE; X register res; X X if(!cmd) { X firsttime = TRUE; X flags.nopick = 0; X cmd = parse(); X } X#ifdef REDO X if (*cmd == DOAGAIN && !in_doagain && saveq[0]) { X in_doagain = TRUE; X stail = 0; X rhack((char *) 0); /* read and execute command */ X in_doagain = FALSE; X return; X } X X /* Special case of *cmd == ' ' handled better below */ X if(!*cmd || *cmd == (char)0377) { X#else X if(!*cmd || *cmd == (char)0377 || (flags.no_rest_on_space && *cmd == ' ')){ X#endif X bell(); X flags.move = 0; X return; /* probably we just had an interrupt */ X } X if(movecmd(*cmd)) { X walk: X if(multi) flags.mv = 1; X domove(); X return; X } X if(movecmd(lowc(*cmd))) { X flags.run = 1; X rush: X if(firsttime){ X if(!multi) multi = COLNO; X u.last_str_turn = 0; X } X flags.mv = 1; X#ifdef QUEST X if(flags.run >= 4) finddir(); X if(firsttime){ X u.ux0 = u.ux + u.dx; X u.uy0 = u.uy + u.dy; X } X#endif X domove(); X return; X } X if((*cmd == 'g' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) { X flags.run = 2; X goto rush; X } X if(*cmd == 'G' && movecmd(lowc(cmd[1]))) { X flags.run = 3; X goto rush; X } X if(*cmd == 'm' && movecmd(cmd[1])) { X flags.run = 0; X flags.nopick = 1; X goto walk; X } X if(*cmd == 'M' && movecmd(lowc(cmd[1]))) { X flags.run = 1; X flags.nopick = 1; X goto rush; X } X#ifdef QUEST X if(*cmd == cmd[1] && (*cmd == 'g' || *cmd == 'G')) { X flags.run = 4; X if(*cmd == 'G') flags.run += 2; X if(cmd[2] == '-') flags.run += 1; X goto rush; X } X#endif X while(tlist->f_char) { X if(*cmd == tlist->f_char){ X#ifdef DGKMOD X /* Special case of *cmd == ' ' handled here */ X if (*cmd == ' ' && flags.no_rest_on_space) X break; X X /* Now control-A can stop lengthy commands */ X if (tlist->f_text && !occupation && multi) X set_occupation(tlist->f_funct, tlist->f_text, X multi); X#endif X res = (*(tlist->f_funct))(); X if(!res) { X flags.move = 0; X multi = 0; X } X return; X } X tlist++; X } X { char expcmd[10]; X register char *cp = expcmd; X while(*cmd && cp-expcmd < sizeof(expcmd)-2) { X if(*cmd >= 040 && *cmd < 0177) X *cp++ = *cmd++; X else { X *cp++ = '^'; X *cp++ = *cmd++ ^ 0100; X } X } X *cp++ = 0; X pline("Unknown command '%s'.", expcmd); X } X multi = flags.move = 0; X return; X} X Xdoextcmd() /* here after # - now read a full-word command */ X{ X char buf[BUFSZ]; X register struct ext_func_tab *efp = extcmdlist; X X pline("# "); X#ifdef COM_COMPL X get_ext_cmd(buf); X#else X getlin(buf); X#endif X clrlin(); X if(buf[0] == '\033') X return(0); X while(efp->ef_txt) { X if(!strcmp(efp->ef_txt, buf)) X return((*(efp->ef_funct))()); X efp++; X } X pline("%s: unknown command.", buf); X return(0); X} X Xdoextlist() /* here after #? - now list all full-word commands */ X{ X register struct ext_func_tab *efp = extcmdlist; X char buf[BUFSZ]; X X set_pager(0); X if(page_line("") || X page_line(" Extended Command Set:") || X page_line("")) goto quit; X X while(efp->ef_txt) { X X (void)sprintf(buf, " %-8s - %s.", efp->ef_txt, efp->ef_desc); X if(page_line(buf)) goto quit; X efp++; X } X set_pager(1); X return(0); Xquit: X set_pager(2); X return(0); X} X Xchar Xlowc(sym) Xchar sym; X{ X return( (sym >= 'A' && sym <= 'Z') ? sym+'a'-'A' : sym ); X} X Xchar Xunctrl(sym) Xchar sym; X{ X return( (sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym ); X} X X/* 'rogue'-like direction commands */ Xchar sdir[] = "hykulnjb><"; Xschar xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 }; Xschar ydir[10] = { 0,-1,-1,-1, 0, 1, 1, 1, 0, 0 }; Xschar zdir[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1,-1 }; X Xmovecmd(sym) /* also sets u.dz, but returns false for <> */ Xchar sym; X{ X register char *dp; X X u.dz = 0; X if(!(dp = index(sdir, sym))) return(0); X u.dx = xdir[dp-sdir]; X u.dy = ydir[dp-sdir]; X u.dz = zdir[dp-sdir]; X return(!u.dz); X} X Xgetdir(s) Xboolean s; X{ X char dirsym; X X#ifdef REDO X if (!in_doagain) X#endif X if(s) pline("In what direction?"); X dirsym = readchar(); X#ifdef REDO X savech(dirsym); X#endif X#ifdef KAA X if(dirsym == '.' || dirsym == 's') X u.dx = u.dy = u.dz = 0; X else X#endif X if(!movecmd(dirsym) && !u.dz) { X if(!index(quitchars, dirsym)) X pline("What a strange direction!"); X return(0); X } X if(Confusion && !u.dz) confdir(); X return(1); X} X Xconfdir() X{ X register x = rn2(8); X u.dx = xdir[x]; X u.dy = ydir[x]; X} X X#ifdef QUEST Xfinddir(){ Xregister int i, ui = u.di; X for(i = 0; i <= 8; i++){ X if(flags.run & 1) ui++; else ui += 7; X ui %= 8; X if(i == 8){ X pline("Not near a wall."); X flags.move = multi = 0; X return(0); X } X if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui])) X break; X } X for(i = 0; i <= 8; i++){ X if(flags.run & 1) ui += 7; else ui++; X ui %= 8; X if(i == 8){ X pline("Not near a room."); X flags.move = multi = 0; X return(0); X } X if(isroom(u.ux+xdir[ui], u.uy+ydir[ui])) X break; X } X u.di = ui; X u.dx = xdir[ui]; X u.dy = ydir[ui]; X} X Xisroom(x,y) register x,y; { /* what about POOL? */ X return(isok(x,y) && (levl[x][y].typ == ROOM || X (levl[x][y].typ >= LDOOR && flags.run >= 6))); X} X#endif /* QUEST /**/ X Xisok(x,y) register x,y; { X /* x corresponds to curx, so x==1 is the first column. Ach. %% */ X return(x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1); X} X X#ifdef WIZARD Xint wiz_wish() /* Unlimited wishes for wizard mode by Paul Polderman */ X{ X if (!wizard) { X pline("Alas! You are not allowed to make a wish."); X pline("Nice try though..."); X } else X makewish(); X return(0); X} X Xint wiz_identify() X{ X struct obj *obj; X X if (!wizard) X pline("You don't have the proper identity!"); X else { X for (obj = invent; obj; obj = obj->nobj) X if (!objects[obj->otyp].oc_name_known || !obj->known) X identify(obj); X } X return(0); X} X#endif /* WIZARD */ END_OF_cmd.c if test 10896 -ne `wc -c <cmd.c`; then echo shar: \"cmd.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f date.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"date.h\" else echo shar: Extracting \"date.h\" \(88 characters\) sed "s/^X//" >date.h <<'END_OF_date.h' X/* SCCS Id: @(#)date.h 1.4 87/08/08 */ X Xchar datestring[] = "Mon Nov 30 01:25:12 1987"; END_OF_date.h if test 88 -ne `wc -c <date.h`; then echo shar: \"date.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f save.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"save.c\" else echo shar: Extracting \"save.c\" \(10663 characters\) sed "s/^X//" >save.c <<'END_OF_save.c' X/* SCCS Id: @(#)save.c 2.1 87/10/07 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include <signal.h> X#include <stdio.h> X#include "hack.h" Xextern char genocided[60]; /* defined in Decl.c */ Xextern char fut_geno[60]; /* idem */ Xextern struct permonst pm_wizard; /* since the wizard evolves */ X Xextern char SAVEF[], nul[]; Xextern char pl_character[PL_CSIZ]; Xextern long lseek(); Xextern struct obj *restobjchn(); Xextern struct monst *restmonchn(); X Xdosave(){ X clear_screen(); X fflush(stdout); X if(dosave0(0)) { X settty("Be seeing you ...\n"); X exit(0); X } X#ifdef LINT X return(0); X#endif X} X X#ifndef NOSAVEONHANGUP Xhangup(){ X (void) dosave0(1); X exit(1); X} X#endif X X/* returns 1 if save successful */ Xdosave0(hu) int hu; { X register fd, ofd; X int tmp; /* not register ! */ X#ifdef DGK X long fds, needed; X extern long bytes_counted; X int mode; X#endif X#ifdef UNIX X (void) signal(SIGHUP, SIG_IGN); X#endif X#ifndef __TURBOC__ X (void) signal(SIGINT, SIG_IGN); X#endif X#ifdef DGK X if (!saveDiskPrompt(0)) X return 0; X fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT, FMASK); X#else X fd = creat(SAVEF, FMASK); X#endif X if(fd < 0) { X if(!hu) pline("Cannot open save file. (Continue or Quit)"); X (void) unlink(SAVEF); /* ab@unido */ X return(0); X } X if(flags.moonphase == FULL_MOON) /* ut-sally!fletcher */ X u.uluck--; /* and unido!ab */ X#ifdef DGKMOD X home(); X cl_end(); X#endif X#ifdef DGK X msmsg("Saving: "); X mode = COUNT; Xagain: X savelev(fd, dlevel, mode); X /* count_only will be set properly by savelev */ X#else X savelev(fd,dlevel); X#endif X saveobjchn(fd, invent); X saveobjchn(fd, fcobj); X savemonchn(fd, fallen_down); X tmp = getuid(); X bwrite(fd, (char *) &tmp, sizeof tmp); X bwrite(fd, (char *) &flags, sizeof(struct flag)); X bwrite(fd, (char *) &dlevel, sizeof dlevel); X bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel); X bwrite(fd, (char *) &moves, sizeof moves); X bwrite(fd, (char *) &u, sizeof(struct you)); X#ifdef SPELLS X bwrite(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); X#endif X if(u.ustuck) X bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id); X bwrite(fd, (char *) pl_character, sizeof pl_character); X bwrite(fd, (char *) genocided, sizeof genocided); X bwrite(fd, (char *) fut_geno, sizeof fut_geno); X#ifdef HARD X bwrite(fd, (char *) &pm_wizard, sizeof(struct permonst)); X#endif X savenames(fd); X#ifdef DGK X if (mode == COUNT) { X /* make sure there is enough disk space */ X needed = bytes_counted; X for (tmp = 1; tmp <= maxdlevel; tmp++) X if (tmp != dlevel && fileinfo[tmp].where) X needed += fileinfo[tmp].size + (sizeof tmp); X fds = freediskspace(SAVEF); X if (needed > fds) { X pline("There is insufficient space on SAVE disk."); X pline("Require %ld bytes but only have %ld.", needed, X fds); X flushout(); X (void) close(fd); X (void) unlink(SAVEF); X return 0; X } X mode = WRITE; X goto again; X } X#endif X for(tmp = 1; tmp <= maxdlevel; tmp++) { X extern int hackpid; X#ifdef DGK X if (tmp == dlevel || !fileinfo[tmp].where) continue; X if (fileinfo[tmp].where != ACTIVE) X swapin_file(tmp); X#else X extern boolean level_exists[]; X X if(tmp == dlevel || !level_exists[tmp]) continue; X#endif X glo(tmp); X#ifdef DGK X msmsg("."); X#endif X if((ofd = open(lock, 0)) < 0) { X if(!hu) pline("Error while saving: cannot read %s.", lock); X (void) close(fd); X (void) unlink(SAVEF); X if(!hu) done("tricked"); X return(0); X } X getlev(ofd, hackpid, tmp); X (void) close(ofd); X bwrite(fd, (char *) &tmp, sizeof tmp); /* level number */ X#ifdef DGK X savelev(fd,tmp,WRITE); /* actual level */ X#else X savelev(fd,tmp); /* actual level */ X#endif X (void) unlink(lock); X } X (void) close(fd); X glo(dlevel); X (void) unlink(lock); /* get rid of current level --jgm */ X glo(0); X (void) unlink(lock); X return(1); X} X Xdorecover(fd) Xregister fd; X{ X register nfd; X int tmp; /* not a register ! */ X unsigned mid; /* idem */ X struct obj *otmp; X extern boolean restoring; X#ifdef DGK X struct flag oldflags; X X oldflags = flags; /* Save flags set in the config file */ X#endif X restoring = TRUE; X getlev(fd, 0, 0); X invent = restobjchn(fd); X for(otmp = invent; otmp; otmp = otmp->nobj) X if(otmp->owornmask) X setworn(otmp, otmp->owornmask); X fcobj = restobjchn(fd); X fallen_down = restmonchn(fd); X mread(fd, (char *) &tmp, sizeof tmp); X#ifdef WIZARD X if(!wizard) X#endif X if(tmp != getuid()) { /* strange ... */ X (void) close(fd); X (void) unlink(SAVEF); X puts("Saved game was not yours."); X restoring = FALSE; X return(0); X } X mread(fd, (char *) &flags, sizeof(struct flag)); X#ifdef DGK X /* Some config file OPTIONS take precedence over those in save file. X */ X flags.rawio = oldflags.rawio; X flags.DECRainbow = oldflags.DECRainbow; X flags.IBMBIOS = oldflags.IBMBIOS; X#endif X mread(fd, (char *) &dlevel, sizeof dlevel); X mread(fd, (char *) &maxdlevel, sizeof maxdlevel); X mread(fd, (char *) &moves, sizeof moves); X mread(fd, (char *) &u, sizeof(struct you)); X#ifdef SPELLS X mread(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); X#endif X if(u.ustuck) X mread(fd, (char *) &mid, sizeof mid); X mread(fd, (char *) pl_character, sizeof pl_character); X mread(fd, (char *) genocided, sizeof genocided); X mread(fd, (char *) fut_geno, sizeof fut_geno); X#ifdef HARD X mread(fd, (char *) &pm_wizard, sizeof(struct permonst)); X#endif X restnames(fd); X#ifdef DGK X msmsg("\n"); X cl_end(); X msmsg("You got as far as level %d%s.\n", maxdlevel, X flags.debug ? " in WIZARD mode" : ""); X cl_end(); X msmsg("Restoring: "); X#endif X while(1) { X if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp) X break; X getlev(fd, 0, tmp); X glo(tmp); X#ifdef DGK X msmsg("."); X nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FMASK); X#else X nfd = creat(lock, FMASK); X#endif X if (nfd < 0) panic("Cannot open temp file %s!\n", lock); X#ifdef DGK X if (!savelev(nfd, tmp, COUNT | WRITE)) { X X /* The savelev can't proceed because the size required X * is greater than the available disk space. X */ X msmsg("\nNot enough space on `%s' to restore your game.\n", X levels); X X /* Remove levels and bones that may have been created. X */ X (void) close(nfd); X eraseall(levels, alllevels); X eraseall(levels, allbones); X X /* Perhaps the person would like to play without a X * RAMdisk. X */ X if (ramdisk) { X /* PlaywoRAMdisk may not return, but if it does X * it is certain that ramdisk will be 0. X */ X playwoRAMdisk(); X (void) lseek(fd, 0L, 0); /* Rewind save file */ X return dorecover(fd); /* and try again */ X } else { X msmsg("Be seeing you ...\n"); X exit(0); X } X } X#else X savelev(nfd,tmp); X#endif X (void) close(nfd); X } X (void) lseek(fd, 0L, 0); X getlev(fd, 0, 0); X (void) close(fd); X (void) unlink(SAVEF); X if(Punished) { X for(otmp = fobj; otmp; otmp = otmp->nobj) X if(otmp->olet == CHAIN_SYM) goto chainfnd; X panic("Cannot find the iron chain?"); X chainfnd: X uchain = otmp; X if(!uball){ X for(otmp = fobj; otmp; otmp = otmp->nobj) X if(otmp->olet == BALL_SYM && otmp->spe) X goto ballfnd; X panic("Cannot find the iron ball?"); X ballfnd: X uball = otmp; X } X } X if(u.ustuck) { X register struct monst *mtmp; X X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) X if(mtmp->m_id == mid) goto monfnd; X panic("Cannot find the monster ustuck."); X monfnd: X u.ustuck = mtmp; X } X#ifndef QUEST X setsee(); /* only to recompute seelx etc. - these weren't saved */ X#endif X#ifdef DGK X gameDiskPrompt(); X#endif X docrt(); X restoring = FALSE; X return(1); X} X Xstruct obj * Xrestobjchn(fd) Xregister fd; X{ X register struct obj *otmp, *otmp2; X register struct obj *first = 0; X int xl; X#ifdef LINT X /* suppress "used before set" warning from lint */ X otmp2 = 0; X#endif X while(1) { X mread(fd, (char *) &xl, sizeof(xl)); X if(xl == -1) break; X otmp = newobj(xl); X if(!first) first = otmp; X else otmp2->nobj = otmp; X mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj)); X if(!otmp->o_id) otmp->o_id = flags.ident++; X otmp2 = otmp; X } X if(first && otmp2->nobj){ X impossible("Restobjchn: error reading objchn."); X otmp2->nobj = 0; X } X return(first); X} X#ifdef MSDOS Xstruct monst * Xrestmonchn(fd) Xregister fd; X{ X register struct monst *mtmp, *mtmp2; X register struct monst *first = 0; X int xl; X int monsindex, mi; X extern struct permonst li_dog, dog, la_dog; X#ifdef KAA X extern struct permonst hell_hound; X# ifdef HARD X extern struct permonst d_lord, d_prince; X# endif X# ifdef KJSMODS X extern struct permonst pm_guard, pm_ghost, pm_eel; X# endif X#endif X X#ifdef lint X /* suppress "used before set" warning from lint */ X mtmp2 = 0; X#endif /* lint /**/ X while(1) { X mread(fd, (char *) &xl, sizeof(xl)); X if(xl == -1) break; X mtmp = newmonst(xl); X if(!first) first = mtmp; X else mtmp2->nmon = mtmp; X mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); X if(!mtmp->m_id) X mtmp->m_id = flags.ident++; X monsindex = *((int *)&mtmp->data); X if (monsindex == (mi = -1)) /* Special fake index */ X mtmp->data = &li_dog; X else if (monsindex == --mi) /* Special fake index */ X mtmp->data = &dog; X else if (monsindex == --mi) /* Special fake index */ X mtmp->data = &la_dog; X#ifdef KAA X else if (monsindex == --mi) X mtmp->data = &hell_hound; X# ifdef HARD X else if (monsindex == --mi) X mtmp->data = &d_lord; X X else if (monsindex == --mi) X mtmp->data = &d_prince; X# endif X# ifdef KJSMODS X else if (monsindex == --mi) X mtmp->data = &pm_guard; X X else if (monsindex == --mi) X mtmp->data = &pm_ghost; X X else if (monsindex == --mi) X mtmp->data = &pm_eel; X# endif X#endif X else X mtmp->data = &mons[monsindex]; X if(mtmp->minvent) X mtmp->minvent = restobjchn(fd); X mtmp2 = mtmp; X } X if(first && mtmp2->nmon){ X impossible("Restmonchn: error reading monchn."); X mtmp2->nmon = 0; X } X return(first); X} X#else Xstruct monst * Xrestmonchn(fd) Xregister fd; X{ X register struct monst *mtmp, *mtmp2; X register struct monst *first = 0; X int xl; X X struct permonst *monbegin; X long differ; X X mread(fd, (char *)&monbegin, sizeof(monbegin)); X differ = (char *)(&mons[0]) - (char *)(monbegin); X X#ifdef LINT X /* suppress "used before set" warning from lint */ X mtmp2 = 0; X#endif X while(1) { X mread(fd, (char *) &xl, sizeof(xl)); X if(xl == -1) break; X mtmp = newmonst(xl); X if(!first) first = mtmp; X else mtmp2->nmon = mtmp; X mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); X if(!mtmp->m_id) X mtmp->m_id = flags.ident++; X mtmp->data = (struct permonst *) X ((char *) mtmp->data + differ); X if(mtmp->minvent) X mtmp->minvent = restobjchn(fd); X mtmp2 = mtmp; X } X if(first && mtmp2->nmon){ X impossible("Restmonchn: error reading monchn."); X mtmp2->nmon = 0; X } X return(first); X} X#endif END_OF_save.c if test 10663 -ne `wc -c <save.c`; then echo shar: \"save.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f spell.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"spell.c\" else echo shar: Extracting \"spell.c\" \(10416 characters\) sed "s/^X//" >spell.c <<'END_OF_spell.c' X/* SCCS Id: @(#)spell.c 2.1 87/10/07 X */ X X#include "hack.h" X#ifdef SPELLS Xextern char *nomovemsg; X Xdoxcribe() { X register struct obj *book; X struct obj *getobj(); X register boolean confused = (Confusion != 0); X register boolean oops; X register schar delay; X register int booktype; X register int i; X X book = getobj("+", "transcribe"); X if(!book) return(0); X X if(Blind) { X pline("Being blind, you cannot read the mystic runes."); X useup(book); /* well, if you are stupid... */ X return(0); X } X X if(confused) { X pline("Being confused, you cannot grasp the meaning of this tome."); X useup(book); /* and more stupidity... */ X return(0); X } X booktype = book->otyp; X oops = !rn2(u.ulevel - objects[booktype].spl_lev + 7); X switch(booktype) { X X/* level 1 spells */ X case SPE_HEALING: X case SPE_DETECT_MONSTERS: X case SPE_FORCE_BOLT: X case SPE_LIGHT: X case SPE_SLEEP: X/* level 2 spells */ X case SPE_MAGIC_MISSILE: X case SPE_CONFUSE_MONSTER: X case SPE_SLOW_MONSTER: X case SPE_CURE_BLINDNESS: X case SPE_CREATE_MONSTER: X case SPE_DETECT_FOOD: X delay = -objects[booktype].oc_delay; X break; X/* level 3 spells */ X case SPE_HASTE_SELF: X case SPE_CAUSE_FEAR: X case SPE_CURE_SICKNESS: X case SPE_DETECT_UNSEEN: X case SPE_EXTRA_HEALING: X case SPE_CHARM_MONSTER: X/* level 4 spells */ X case SPE_LEVITATION: X case SPE_RESTORE_STRENGTH: X case SPE_INVISIBILITY: X case SPE_FIREBALL: X case SPE_DETECT_TREASURE: X delay = -(objects[booktype].spl_lev - 1) * objects[booktype].oc_delay; X break; X/* level 5 spells */ X case SPE_REMOVE_CURSE: X case SPE_MAGIC_MAPPING: X case SPE_CONE_OF_COLD: X case SPE_IDENTIFY: X case SPE_DIG: X/* level 6 spells */ X case SPE_TURN_UNDEAD: X case SPE_POLYMORPH: X case SPE_CREATE_FAMILIAR: X case SPE_TELEPORT_AWAY: X delay = -objects[booktype].spl_lev * objects[booktype].oc_delay; X break; X/* level 7 spells */ X case SPE_CANCELLATION: X case SPE_FINGER_OF_DEATH: X case SPE_GENOCIDE: X delay = -8 * objects[booktype].oc_delay; X break; X/* impossible */ X default: X impossible("Unknown spell-book, %d;", booktype); X return(0); X } X X pline("You begin to transcribe the spell."); X if(oops || book->cursed) { X cursed_book(objects[booktype].spl_lev); X nomul(delay); /* study time */ X } else { X nomul(delay); /* study time */ X for(i = 0; i < MAXSPELL; i++) { X if(spl_book[i].sp_id == booktype) { X#ifdef HARD X nomovemsg = "You make that spell more legible."; X spl_book[i].sp_uses += rn1(3,8-spl_book[i].sp_lev); X#else X nomovemsg = "Oh, you already know that one!"; X#endif X useup(book); X return(1); X } else if (spl_book[i].sp_id == NO_SPELL) { X spl_book[i].sp_id = booktype; X spl_book[i].sp_lev = objects[booktype].spl_lev; X spl_book[i].sp_flags = objects[booktype].bits; X#ifdef HARD X /* spells have 2 .. 10-level uses. */ X /* ie 2 or 3 uses w/ most potent */ X spl_book[i].sp_uses = rn1(3,8-spl_book[i].sp_lev); X#endif X nomovemsg = "You add the spell to your books."; X objects[booktype].oc_name_known = 1; X useup(book); X return(1); X } X } X impossible("Too many spells in spellbook!"); X } X useup(book); X return(1); X} X Xcursed_book(level) X register int level; X{ X switch(rn2(level)) { X case 0: X pline("You feel a wrenching sensation."); X tele(); /* teleport him */ X break; X case 1: X pline("You feel threatened."); X aggravate(); X break; X case 2: X if(!Blind) pline("A cloud of darkness falls upon you."); X Blinded += rn1(100,250); X seeoff(0); X break; X case 3: X if (u.ugold <= 0) { X pline("You feel a strange sensation."); X } else { X pline("You notice you have no gold!"); X u.ugold = 0; X flags.botl = 1; X } X break; X case 4: X pline("These runes were just too much to comprehend."); X HConfusion += rn1(7,16); X break; X case 5: X pline("The book was coated with contact poison!"); X if(Poison_resistance) { X losestr(rn1(1,2)); X losehp(rnd(6), "contact poison"); X } else { X losestr(rn1(4,3)); X losehp(rnd(10), "contact poison"); X } X break; X case 6: X pline("As you read the book, it explodes in your face!"); X losehp (2*rnd(10)+5, "exploding rune"); X break; X default: X rndcurse(); X break; X } X return(0); X} X Xdocast() X{ X register int spell, energy, damage; X register boolean confused = (Confusion != 0); X register struct obj *pseudo; X struct obj *mksobj(); X X spell = getspell(); X if (!spell) return(0); X else { X#ifdef HARD X /* note that turning to the page decrements the # of uses, */ X /* even if the mage does not have enough food/energy to use */ X /* the spell */ X switch (spelluses(spell)) { X case 0: X pline ("That page is too faint to read at the moment."); X return(0); X case 1: X pline ("You can barely make out the runes on this page."); X break; X case 2: X pline ("This spell is starting to look well used."); X break; X default: X break; X } X decrnuses(spell); X#endif X energy = spellev(spell); X#ifdef BVH X if (has_amulet()) { X X pline("You feel the amulet draining your energy away."); X energy *= rnd(6); X } X#endif X if(energy > u.uen) { X pline("You are too weak to cast that spell."); X return(0); X } else if ((u.uhunger <= 100) || (u.ustr < 6)) { X pline("You miss the strength for that spell."); X return(0); X } else { X morehungry(energy * 10); X u.uen -= energy; X } X flags.botl = 1; X } X#ifdef HARD X if (confused || X (rn2(10) + (int)(u.ulevel + u.uluck) - 3*spellev(spell)) < 0) { X X if (Hallucination) X pline("Far out... a light show!"); X else pline("The air around you crackles as you goof up."); X return(0); X } X#endif X X/* pseudo is a temporary "false" object containing the spell stats. */ X pseudo = mksobj(spellid(spell)); X pseudo->quan = 20; /* do not let useup get it */ X switch(pseudo->otyp) { X X/* These spells are all duplicates of wand effects */ X case SPE_FORCE_BOLT: X case SPE_SLEEP: X case SPE_MAGIC_MISSILE: X case SPE_SLOW_MONSTER: X case SPE_FIREBALL: X case SPE_CONE_OF_COLD: X case SPE_DIG: X case SPE_TURN_UNDEAD: X case SPE_POLYMORPH: X case SPE_TELEPORT_AWAY: X case SPE_CANCELLATION: X case SPE_FINGER_OF_DEATH: X case SPE_LIGHT: X case SPE_DETECT_UNSEEN: X if (!(objects[pseudo->otyp].bits & NODIR)) { X getdir(1); X if(!u.dx && !u.dy && !u.dz && (u.ulevel > 8)) { X if((damage = zapyourself(pseudo))) X losehp(damage, "self-inflicted injury"); X } else weffects(pseudo); X } else weffects(pseudo); X break; X/* These are all duplicates of scroll effects */ X case SPE_CONFUSE_MONSTER: X case SPE_DETECT_FOOD: X case SPE_CAUSE_FEAR: X case SPE_CHARM_MONSTER: X case SPE_REMOVE_CURSE: X case SPE_MAGIC_MAPPING: X case SPE_CREATE_MONSTER: X case SPE_IDENTIFY: X case SPE_GENOCIDE: X seffects(pseudo); X break; X case SPE_HASTE_SELF: X case SPE_DETECT_TREASURE: X case SPE_DETECT_MONSTERS: X case SPE_LEVITATION: X case SPE_RESTORE_STRENGTH: X case SPE_INVISIBILITY: X peffects(pseudo); X break; X case SPE_HEALING: X pline("You feel a bit better."); X healup(rnd(8), 0, 0, 0); X break; X case SPE_CURE_BLINDNESS: X healup(0, 0, 0, 1); X break; X case SPE_CURE_SICKNESS: X pline("You are no longer ill."); X healup(0, 0, 1, 0); X break; X case SPE_EXTRA_HEALING: X pline("You feel a fair bit better."); X healup(d(2,8), 1, 0, 0); X break; X case SPE_CREATE_FAMILIAR: X { register struct monst *mtmp; X struct monst *makedog(); X X mtmp = makedog(); X if(mtmp) { X /* make it into something else */ X (void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); X if(confused) X mtmp->mtame = mtmp->mpeaceful = 0; X } X } X break; X default: X impossible("Unknown spell %d attempted.", spell); X obfree(pseudo, (struct obj *)0); X return(0); X } X obfree(pseudo, (struct obj *)0); /* now, get rid of it */ X return(1); X} X Xgetspell() { X X register int max, ilet, i; X char lets[BUFSZ], buf[BUFSZ]; X X if (spl_book[0].sp_id == NO_SPELL) { X X pline("You don't know any spells right now."); X return(0); X } else { X X for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++); X if (max >= MAXSPELL) { X X impossible("Too many spells memorized."); X return(0); X } X X for(i = 0; (i < max) && (i < 26); buf[++i] = 0) buf[i] = 'a' + i; X for(i = 26; (i < max) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26; X X if (max == 1) strcpy(lets, "a"); X else if (max < 27) sprintf(lets, "a-%c", 'a' + max - 1); X else if (max == 27) sprintf(lets, "a-z A"); X else sprintf(lets, "a-z A-%c", 'A' + max - 27); X for(;;) { X X pline("Cast which spell [%s ?]: ", lets); X if ((ilet = readchar()) == '?') { X dovspell(); X continue; X } else if ((ilet == '\033')||(ilet == '\n')||(ilet == ' ')) X return(0); X else for(i = 0; buf[i] != 0; i++) if(ilet == buf[i]) return(++i); X pline("You don't know that spell."); X } X } X} X Xlosespells() { X register boolean confused = (Confusion != 0); X register int n, nzap, i; X X for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++); X if (!n) return; X if (n < MAXSPELL) { X nzap = rnd(n); X if (nzap < n) nzap += confused; X for (i = 0; i < nzap; i++) spl_book[n-i-1].sp_id = NO_SPELL; X } else impossible("Too many spells in spellbook!"); X return; X} X Xdovspell() { X X register int max, i, side; X char buf[BUFSZ], X *spellname(); X X if (spl_book[0].sp_id == NO_SPELL) { X X pline("You don't know any spells right now."); X return(0); X } else { X X for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++); X if (max >= MAXSPELL) { X X impossible("Too many spells memorized."); X return(0); X } X } X set_pager(0); X side = (max + 1) / 2; X if(page_line("Currently known spells:") || page_line("")) goto quit; X X for(i = 1; i <= side; i++) { X X if((i < side) || !(max % 2)) { X X (void) sprintf(buf, "%c - (%d) %22s %c - (%d) %22s", X spellet(i), spellev(i), spellname(i), X spellet(i + side), spellev(i + side), spellname(i + side)); X } else { X X (void) sprintf(buf, "%c - (%d) %22s", spellet(i), spellev(i), spellname(i)); X } X if(page_line(buf)) goto quit; X } X X set_pager(1); X return(0); Xquit: X set_pager(2); X return(0); X} X Xspellet(spl) { X X if (spl < 27) return('a' + spl - 1); X else return('A' + spl - 27); X} X Xspellev(spl) { X X return(spl_book[spl-1].sp_lev); X} X Xchar * Xspellname(spl) { X X return(objects[spl_book[spl-1].sp_id].oc_name); X} X Xspellid(spl) { return(spl_book[spl-1].sp_id); } X X#ifdef HARD Xspelluses(spell) { return(spl_book[spell-1].sp_uses); } Xdecrnuses(spell) { spl_book[spell-1].sp_uses--; } X#endif X X#endif /* SPELLS /**/ END_OF_spell.c if test 10416 -ne `wc -c <spell.c`; then echo shar: \"spell.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f unixunix.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"unixunix.c\" else echo shar: Extracting \"unixunix.c\" \(10405 characters\) sed "s/^X//" >unixunix.c <<'END_OF_unixunix.c' X/* SCCS Id: @(#)unixunix.c 1.4 87/08/08 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* hack.unix.c - version 1.0.3 */ X X/* This file collects some Unix dependencies; pager.c contains some more */ X X/* X * The time is used for: X * - seed for rand() X * - year on tombstone and yymmdd in record file X * - phase of the moon (various monsters react to NEW_MOON or FULL_MOON) X * - night and midnight (the undead are dangerous at midnight) X * - determination of what files are "very old" X */ X X#include <stdio.h> X#include <errno.h> X#include "hack.h" /* mainly for index() which depends on BSD */ X X#include <sys/types.h> /* for time_t and stat */ X#include <sys/stat.h> X#ifdef BSD X#include <sys/time.h> X#else X#include <time.h> X#endif X Xextern char *getenv(); Xextern time_t time(); X Xsetrandom() X{ X (void) srand((int) time ((time_t *) 0)); X} X Xstruct tm * Xgetlt() X{ X time_t date; X struct tm *localtime(); X X (void) time(&date); X return(localtime(&date)); X} X Xgetyear() X{ X return(1900 + getlt()->tm_year); X} X Xchar * Xgetdate() X{ X static char datestr[7]; X register struct tm *lt = getlt(); X X (void) sprintf(datestr, "%2d%2d%2d", X lt->tm_year, lt->tm_mon + 1, lt->tm_mday); X if(datestr[2] == ' ') datestr[2] = '0'; X if(datestr[4] == ' ') datestr[4] = '0'; X return(datestr); X} X Xphase_of_the_moon() /* 0-7, with 0: new, 4: full */ X{ /* moon period: 29.5306 days */ X /* year: 365.2422 days */ X register struct tm *lt = getlt(); X register int epact, diy, golden; X X diy = lt->tm_yday; X golden = (lt->tm_year % 19) + 1; X epact = (11 * golden + 18) % 30; X if ((epact == 25 && golden > 11) || epact == 24) X epact++; X X return( (((((diy + epact) * 6) + 11) % 177) / 22) & 7 ); X} X Xnight() X{ X register int hour = getlt()->tm_hour; X X return(hour < 6 || hour > 21); X} X Xmidnight() X{ X return(getlt()->tm_hour == 0); X} X Xstruct stat buf, hbuf; X Xgethdate(name) char *name; { X/* old version - for people short of space */ X/* X/* register char *np; X/* if(stat(name, &hbuf)) X/* error("Cannot get status of %s.", X/* (np = rindex(name, '/')) ? np+1 : name); X/* X/* version using PATH from: seismo!gregc@ucsf-cgl.ARPA (Greg Couch) */ X X X/* X * The problem with #include <sys/param.h> is that this include file X * does not exist on all systems, and moreover, that it sometimes includes X * <sys/types.h> again, so that the compiler sees these typedefs twice. X */ X#define MAXPATHLEN 1024 X Xregister char *np, *path; Xchar filename[MAXPATHLEN+1]; X if (index(name, '/') != NULL || (path = getenv("PATH")) == NULL) X path = ""; X X for (;;) { X if ((np = index(path, ':')) == NULL) X np = path + strlen(path); /* point to end str */ X if (np - path <= 1) /* %% */ X (void) strcpy(filename, name); X else { X (void) strncpy(filename, path, np - path); X filename[np - path] = '/'; X (void) strcpy(filename + (np - path) + 1, name); X } X if (stat(filename, &hbuf) == 0) X return; X if (*np == '\0') X break; X path = np + 1; X } X error("Cannot get status of %s.", X (np = rindex(name, '/')) ? np+1 : name); X} X Xuptodate(fd) { X if(fstat(fd, &buf)) { X pline("Cannot get status of saved level? "); X return(0); X } X if(buf.st_mtime < hbuf.st_mtime) { X pline("Saved level is out of date. "); X return(0); X } X return(1); X} X X/* see whether we should throw away this xlock file */ Xveryold(fd) { X register int i; X time_t date; X X if(fstat(fd, &buf)) return(0); /* cannot get status */ X if(buf.st_size != sizeof(int)) return(0); /* not an xlock file */ X (void) time(&date); X if(date - buf.st_mtime < 3L*24L*60L*60L) { /* recent */ X extern int errno; X int lockedpid; /* should be the same size as hackpid */ X X if(read(fd, (char *)&lockedpid, sizeof(lockedpid)) != X sizeof(lockedpid)) X /* strange ... */ X return(0); X X /* From: Rick Adams <seismo!rick> X /* This will work on 4.1cbsd, 4.2bsd and system 3? & 5. X /* It will do nothing on V7 or 4.1bsd. */ X if(!(kill(lockedpid, 0) == -1 && errno == ESRCH)) X return(0); X } X (void) close(fd); X for(i = 1; i <= MAXLEVEL; i++) { /* try to remove all */ X glo(i); X (void) unlink(lock); X } X glo(0); X if(unlink(lock)) return(0); /* cannot remove it */ X return(1); /* success! */ X} X Xgetlock() X{ X extern int errno, hackpid, locknum; X register int i = 0, fd; X X (void) fflush(stdout); X X /* we ignore QUIT and INT at this point */ X if (link(HLOCK, LLOCK) == -1) { X register int errnosv = errno; X X perror(HLOCK); X printf("Cannot link %s to %s\n", LLOCK, HLOCK); X switch(errnosv) { X case ENOENT: X printf("Perhaps there is no (empty) file %s ?\n", HLOCK); X break; X case EACCES: X printf("It seems you don't have write permission here.\n"); X break; X case EEXIST: X printf("(Try again or rm %s.)\n", LLOCK); X break; X default: X printf("I don't know what is wrong."); X } X getret(); X error(""); X /*NOTREACHED*/ X } X X regularize(lock); X glo(0); X if(locknum > 25) locknum = 25; X X do { X if(locknum) lock[0] = 'a' + i++; X X if((fd = open(lock, 0)) == -1) { X if(errno == ENOENT) goto gotlock; /* no such file */ X perror(lock); X (void) unlink(LLOCK); X error("Cannot open %s", lock); X } X X if(veryold(fd)) /* if true, this closes fd and unlinks lock */ X goto gotlock; X (void) close(fd); X } while(i < locknum); X X (void) unlink(LLOCK); X error(locknum ? "Too many hacks running now." X : "There is a game in progress under your name."); Xgotlock: X fd = creat(lock, FMASK); X if(unlink(LLOCK) == -1) X error("Cannot unlink %s.", LLOCK); X if(fd == -1) { X error("cannot creat lock file."); X } else { X if(write(fd, (char *) &hackpid, sizeof(hackpid)) X != sizeof(hackpid)){ X error("cannot write lock"); X } X if(close(fd) == -1) { X error("cannot close lock"); X } X } X} X X#ifdef MAIL X X/* X * Notify user when new mail has arrived. [Idea from Merlyn Leroy, but X * I don't know the details of his implementation.] X * { Later note: he disliked my calling a general mailreader and felt that X * hack should do the paging itself. But when I get mail, I want to put it X * in some folder, reply, etc. - it would be unreasonable to put all these X * functions in hack. } X * The mail daemon '2' is at present not a real monster, but only a visual X * effect. Thus, makemon() is superfluous. This might become otherwise, X * however. The motion of '2' is less restrained than usual: diagonal moves X * from a DOOR are possible. He might also use SDOOR's. Also, '2' is visible X * in a ROOM, even when you are Blind. X * Its path should be longer when you are Telepat-hic and Blind. X * X * Interesting side effects: X * - You can get rich by sending yourself a lot of mail and selling X * it to the shopkeeper. Unfortunately mail isn't very valuable. X * - You might die in case '2' comes along at a critical moment during X * a fight and delivers a scroll the weight of which causes you to X * collapse. X * X * Possible extensions: X * - Open the file MAIL and do fstat instead of stat for efficiency. X * (But sh uses stat, so this cannot be too bad.) X * - Examine the mail and produce a scroll of mail called "From somebody". X * - Invoke MAILREADER in such a way that only this single letter is read. X * X * - Make him lose his mail when a Nymph steals the letter. X * - Do something to the text when the scroll is enchanted or cancelled. X */ X#include "mkroom.h" Xstatic struct stat omstat,nmstat; Xstatic char *mailbox; Xstatic long laststattime; X Xgetmailstatus() { X if(!(mailbox = getenv("MAIL"))) X return; X if(stat(mailbox, &omstat)){ X#ifdef PERMANENT_MAILBOX X pline("Cannot get status of MAIL=%s .", mailbox); X mailbox = 0; X#else X omstat.st_mtime = 0; X#endif X } X} X Xckmailstatus() { X if(!mailbox X#ifdef MAILCKFREQ X || moves < laststattime + MAILCKFREQ X#endif X ) X return; X laststattime = moves; X if(stat(mailbox, &nmstat)){ X#ifdef PERMANENT_MAILBOX X pline("Cannot get status of MAIL=%s anymore.", mailbox); X mailbox = 0; X#else X nmstat.st_mtime = 0; X#endif X } else if(nmstat.st_mtime > omstat.st_mtime) { X if(nmstat.st_size) X newmail(); X getmailstatus(); /* might be too late ... */ X } X} X Xnewmail() { X /* produce a scroll of mail */ X register struct obj *obj; X register struct monst *md; X extern char plname[]; X extern struct obj *mksobj(), *addinv(); X extern struct monst *makemon(); X extern struct permonst pm_mail_daemon; X X obj = mksobj(SCR_MAIL); X if(md = makemon(&pm_mail_daemon, u.ux, u.uy)) /* always succeeds */ X mdrush(md,0); X X pline("\"Hello, %s! I have some mail for you.\"", plname); X if(md) { X if(dist(md->mx,md->my) > 2) X pline("\"Catch!\""); X more(); X X /* let him disappear again */ X mdrush(md,1); X mondead(md); X } X X obj = addinv(obj); X (void) identify(obj); /* set known and do prinv() */ X} X X/* make md run through the cave */ Xmdrush(md,away) Xregister struct monst *md; Xboolean away; X{ X register int uroom = inroom(u.ux, u.uy); X if(uroom >= 0) { X register int tmp = rooms[uroom].fdoor; X register int cnt = rooms[uroom].doorct; X register int fx = u.ux, fy = u.uy; X while(cnt--) { X if(dist(fx,fy) < dist(doors[tmp].x, doors[tmp].y)){ X fx = doors[tmp].x; X fy = doors[tmp].y; X } X tmp++; X } X tmp_at(-1, md->data->mlet); /* open call */ X if(away) { /* interchange origin and destination */ X unpmon(md); X tmp = fx; fx = md->mx; md->mx = tmp; X tmp = fy; fy = md->my; md->my = tmp; X } X while(fx != md->mx || fy != md->my) { X register int dx,dy,nfx = fx,nfy = fy,d1,d2; X X tmp_at(fx,fy); X d1 = DIST(fx,fy,md->mx,md->my); X for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++) X if(dx || dy) { X d2 = DIST(fx+dx,fy+dy,md->mx,md->my); X if(d2 < d1) { X d1 = d2; X nfx = fx+dx; X nfy = fy+dy; X } X } X if(nfx != fx || nfy != fy) { X fx = nfx; X fy = nfy; X } else { X if(!away) { X md->mx = fx; X md->my = fy; X } X break; X } X } X tmp_at(-1,-1); /* close call */ X } X if(!away) X pmon(md); X} X Xreadmail() { X#ifdef DEF_MAILREADER /* This implies that UNIX is defined */ X register char *mr = 0; X more(); X if(!(mr = getenv("MAILREADER"))) X mr = DEF_MAILREADER; X if(child(1)){ X execl(mr, mr, (char *) 0); X exit(1); X } X#else X (void) page_file(mailbox, FALSE); X#endif X /* get new stat; not entirely correct: there is a small time X window where we do not see new mail */ X getmailstatus(); X} X#endif /* MAIL /**/ X Xregularize(s) /* normalize file name - we don't like ..'s or /'s */ Xregister char *s; X{ X register char *lp; X X while((lp = index(s, '.')) || (lp = index(s, '/'))) X *lp = '_'; X} END_OF_unixunix.c if test 10405 -ne `wc -c <unixunix.c`; then echo shar: \"unixunix.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 13 \(of 20\). cp /dev/null ark13isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 20 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0