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