huisjes@ark.UUCP (Michiel B. Huisjes) (02/06/85)
#!/bin/sh # # # # This is a shell archive. These archives are packed by the program # packmail(1). If you have the program unshar(1), I suggest you use it. # If you don't remove anything before the cut line and then feed to # sh(1) # # =====CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=== # echo 'Start of Hack, part 01 of 05:' echo 'x - hack.debug.c' sed 's/^X//' > hack.debug.c << '/' X/* X * Hack.debug.c X * X * Debug function, only exists when DEBUG if defined X * Michiel and Fred X */ X X#include "hack.h" X X#ifdef DEBUG Xdebug () { X nomove (); X pline( "You're in the debug function!" ); X} X#endif DEBUG / echo 'x - hack.do.c' sed 's/^X//' > hack.do.c << '/' X/* X * Hack.do.c X */ X X#include "hack.h" X Xextern char NOTHIN[], WCLEV[], *nomvmsg; X Xchar WELDED[] = "The %s is welded into your hand!"; X X#define LETTER(ch) ((ch >= '@' && ch <= 'Z' ) || \ X (ch >= 'a' && ch <= 'z')) X#define CURSED 1 X#define NOTCURSED 0 X#define MAXLEVEL 40 X X#define SIZE( x ) sizeof( x )/sizeof( x[0] ) X X/* Routines to do various user commands */ X Xdoglow (num) Xregister num; X{ X pline ("Your %s glows %s for a %s.", (flags.dac) ? X armors[uarm -> otyp].armnam : weapons[uwep -> otyp].wepnam, X (num < 0) ? X "black" : "green", X (num * num == 1) ? X "moment" : "while"); X} X Xdoread () { X register OBJECT otmp; X register MONSTER mtmp, mtmp2; X register GOLD_TRAP gtmp; X OBJECT otmp2, otmp3; X int num, zx, zy, xtmp, ytmp; X X if (!(otmp = getobj ("?", "read"))) { X nomove (); X return; X } X pline ("As you read the scroll, it disappears."); X X /* X Sometimes a scroll doesn't do anything X */ X if (!rn2 (20)) { X pline ("You can't read the dialect!"); X useup (otmp); X return; X } X X switch (otmp -> otyp) { X X case S_ENCH_ARMOR: X if (!uarm) { X nothin (otmp); X return; X } X uarm -> cursed = 0; X uarm -> spe++; X u.uac--; X flags.dac = 1; X doglow (1); X break; X X case S_DROP: X/* X * New scroll instead of scroll of monster confusion. This scroll X * drops everything you have on you. And put it somewhere on the level X * Michiel and Fred X */ X pline ("Bloody hell, what's going on?"); X do { X xtmp = rn2 (80); X ytmp = rn2 (22); X } while (levl[xtmp][ytmp].typ != ROOM); X useup (otmp); X oiden[S_DROP] |= SCRN; X doring (uleft, OFF); X /* Checked on existence in routine */ X doring (uright, OFF); X for (otmp2 = invent; otmp2; otmp2 = otmp3) { X otmp3 = otmp2 -> nobj; X if (otmp2 == uarm || otmp2 == uarm2) { X u.uac += otmp2 -> spe; X flags.dac = 1; X } X otmp2 -> ox = xtmp; X otmp2 -> oy = ytmp; X subfrombill (otmp2); X otmp -> unpaid = 0; X otmp2 -> nobj = fobj; X fobj = otmp2; X } X if (u.ugold) { X gtmp = newgen (); X gtmp -> gx = xtmp; X gtmp -> gy = ytmp; X gtmp -> gflag = (unsigned) u.ugold; X gtmp -> ngen = fgold; X fgold = gtmp; X u.ugold = 0L; X flags.dgold = 1; X } X uright = NULL; X uleft = NULL; X uwep = NULL; X invent = NULL; X uarm = NULL; X uarm2 = NULL; X levl[xtmp][ytmp].scrsym = fobj -> olet; X levl[xtmp][ytmp].new = 0; X return; X X case S_CURSE_LEV: /* Michiel */ X pline ("Your body begins to glow black."); X docurse (); X u.uhcursed = 1; X break; X X case S_REM_CURSE: X pline ("You feel like someone is helping you."); X if (uleft) X uleft -> cursed = 0; X if (uright) X uright -> cursed = 0; X if (uarm) X uarm -> cursed = 0; X if (uarm2) X uarm2 -> cursed = 0; X if (uwep) X uwep -> cursed = 0; X break; X X case S_ENCH_WEP: X case S_DAM_WEP: X if (!uwep) { X nothin (otmp); X return; X } X num = 5 - otmp -> otyp;/* 4 or 6 */ X if (!rn2 (6)) X num <<= 1; X uwep -> spe += num; X if (num > 0) X uwep -> cursed = 0; X doglow (num); X break; X X case S_CREAT_MON: X makemon (0); X mnexto (fmon); X break; X X case S_GENOCIDE: X pline ("You have found a scroll of genocide!"); X do { X pline ("What monster do you want to genocide (Type the letter)? "); X flags.topl = 0; X getlin (buf); X } while (strlen (buf) != 1 || !LETTER (*buf) || X /* a3 */ index (genocided, *buf)); X strcat (genocided, buf); X for (mtmp = fmon; mtmp; mtmp = mtmp2) { X mtmp2 = mtmp -> nmon; X if (mtmp -> data -> mlet == *buf) X cmdel (mtmp); X } X if (*buf == '@') { X killer = "scroll of genocide"; X u.uhp = 0; X } X break; X X case S_DESTR_ARMOR: X if (!uarm) { X nothin (otmp); X return; X } X pline ("Your armor turns to dust and falls to the floor!"); X u.uac += uarm -> spe; X flags.dac = 1; X useup (uarm); X uarm = uarm2; X uarm2 = 0; X break; X X case S_LIGHT: X litroom (); X break; X X case S_TELEPORT: X/* X * Extended by Michiel and Fred: X * One can jump between levels X */ X pline ("The scroll turns into an elevator."); X do { X pline ("Which stock please? "); X getlin (buf); X num = atoi (buf); X } while (num > MAXLEVEL - 3 && num != dlevel); X if (!*buf) X break; X if (num <= 0) X pline ("Don't fool around"); X else if (num == dlevel) X tele (); X else if (u.ufloat || u.ustuck || getinventory ("\"")) { X nothin (otmp); X pline ("The elevator vanishes"); X return; X } X else { X home (); X flush (); X keepdogs (1); X unCoff (COFF, 1); X dosavelev (); X if (num > dlevel) { X dlevel = (num > maxdlevel) ? X maxdlevel : num - 1; X while (dlevel < num) { X dodown (); X levl[u.ux][u.uy].scrsym = '<'; X } X } X else { X dlevel = num + 1; X doup (); X levl[u.ux][u.uy].scrsym = '>'; X } X land (); X losedogs (); X setCon (CON); X inshop ();/* a3: zie tele */ X } X pline ("The elevator vanishes"); X break; X X case S_GOLD_DETEC: X if (!fgold) { X nothin (otmp); X return; X } X cls (); X for (gtmp = fgold; gtmp; gtmp = gtmp -> ngen) X at (gtmp -> gx, gtmp -> gy, '$'); X prme (); X pline ("You feel very greedy, and sense gold!"); X more (); X docrt (); X break; X X case S_IDENTIFY: X pline ("This is an identify scroll."); X useup (otmp); X oiden[S_IDENTIFY] |= SCRN; X otmp = getobj (0, "identify"); X if (otmp) { X switch (otmp -> olet) { X case '!': X oiden[otmp -> otyp] |= POTN; X break; X case '?': X oiden[otmp -> otyp] |= SCRN; X break; X case '/': X oiden[otmp -> otyp] |= WANN; X case '[': X case ')': X otmp -> known = 1; X break; X case '=': X oiden[otmp -> otyp] |= RINN; X if (otmp -> otyp >= R_GAIN_STR) X otmp -> known = 1; X break; X } X prinv (otmp); X } X return; X X case S_MAG_MAP: X pline ("On this scroll is a map!"); X for (zy = 0; zy < 22; zy++) X for (zx = 0; zx < 80; zx++) { X if ((num = levl[zx][zy].typ) == SDOOR) { X levl[zx][zy].typ = DOOR; X atl (zx, zy, '+'); X } X else if ((num >= WALL && num <= CORR) && X /* or DOOR; no SDOOR */ X !levl[zx][zy].seen) X newunseen (zx, zy); X else if (num >= 30 && num <= 41) X newunseen (zx, zy); X } X newunseen (xupstair, yupstair); X if (xdnstair)/* maze */ X newunseen (xdnstair, ydnstair); X break; X X case S_FIRE: X pline ("The scroll erupts in a tower of flame!"); X if (u.ufireres) X pline ("You are uninjured."); X else { X num = rnd (6); X losehp (num, "scroll of fire"); X u.uhpmax -= num; X flags.dhpmax = 1; X } X break; X X default: X pline ("Bad(%d)scroll", otmp -> otyp); X impossible (); X X } X if (!(oiden[otmp -> otyp] & SCRN)) { X if (otmp -> otyp > S_CREAT_MON && (otmp -> otyp != S_LIGHT X || !u.ublind)) { X oiden[otmp -> otyp] |= SCRN; X u.urexp += 10; X } X else if (!scrcall[otmp -> otyp]) X docall (otmp); X } X if (u.uhcursed && otmp -> otyp == S_REM_CURSE) { X u.uhcursed = 0; X pline ("Your body stops glowing black."); X } X useup (otmp); X} X Xlitroom () { X register zx, zy; X X if (!xdnstair || !dlevel) { X pline (NOTHIN); X return; X } X if (levl[u.ux][u.uy].typ == CORR) { X if (!u.ublind) X pline ("The corridor lights up around you, then fades."); X return; X } X else if (!u.ublind) X if (levl[u.ux][u.uy].lit) X pline ("The room lights up around you."); X else X pline ("The room is lit."); X if (levl[u.ux][u.uy].lit) X return; X if (levl[u.ux][u.uy].typ == DOOR) { X if (levl[u.ux][u.uy + 1].typ == ROOM) X zy = u.uy + 1; X else if (levl[u.ux][u.uy - 1].typ == ROOM) X zy = u.uy - 1; X else X zy = u.uy; X if (levl[u.ux + 1][u.uy].typ == ROOM) X zx = u.ux + 1; X else if (levl[u.ux - 1][u.uy].typ == ROOM) X zx = u.ux - 1; X else X zx = u.ux; X } X else { X zx = u.ux; X zy = u.uy; X } X for (seelx = u.ux; levl[seelx - 1][zy].typ % 2; seelx--); X /* ROOM or WALL or DOOR */ X for (seehx = u.ux; levl[seehx + 1][zy].typ % 2; seehx++); X for (seely = u.uy; levl[zx][seely - 1].typ % 2; seely--); X for (seehy = u.uy; levl[zx][seehy + 1].typ % 2; seehy++); X for (zy = seely; zy <= seehy; zy++) X for (zx = seelx; zx <= seehx; zx++) { X levl[zx][zy].lit = 1; X if (!u.ublind && dist (zx, zy) > 2) X prl (zx, zy); X } X} X Xdodrink () { X register OBJECT otmp, objs; X register MONSTER mtmp; X register num; X X if (!(otmp = getobj ("!", "drink"))) { X nomove (); X return; X } X switch (otmp -> otyp) { X X case P_REST_STR: X pline ("Wow! This makes you feel great!"); X if (u.ustr < u.ustrmax) { X u.ustr = u.ustrmax; X flags.dstr = 1; X } X break; X X case P_BOOZE: X pline ("Ooph! This tastes like liquid fire!"); X u.uconfused += d (3, 8); X if (u.uhp < u.uhpmax) X losehp (-1, ""); X if (!rn2 (4)) { X pline ("You pass out."); X multi = -rnd (15); X nomvmsg = "You awake with a headache."; X } X break; X X case P_INVIS: X pline ("Gee! All of a sudden, you can't see yourself."); X newsym (u.ux, u.uy); X u.uinvis += rn1 (15, 31); X break; X X case P_JUICE: X pline ("This tastes like fruit juice."); X lesshungry (20); X break; X X case P_HEALING: X pline ("You begin to feel better."); X num = rnd (10); X H: X if (u.uhp + num > u.uhpmax) { X u.uhp = ++u.uhpmax; X if (otmp -> otyp == P_EXTRA_HEALING) X u.uhp = ++u.uhpmax; X flags.dhpmax = 1; X } X else X u.uhp += num; X flags.dhp = 1; X if (u.ublind) X u.ublind = 1; X break; X X case P_FROZEN: X pline ("Your feet are frozen to the floor!"); X nomul (-rn1 (10, 25)); X break; X X case P_MONDETEC: X if (!fmon) { X nothin (otmp); X return; X } X cls (); X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) X at (mtmp -> mx, mtmp -> my, mtmp -> data -> mlet); X killer = "monster"; X P: X prme (); X pline ("You sense the presence of %ss.", killer); X more (); X docrt (); X break; X X case P_OBJDETEC: X if (!fobj) { X nothin (otmp); X return; X } X cls (); X for (objs = fobj; objs; objs = objs -> nobj) X at (objs -> ox, objs -> oy, objs -> olet); X killer = "object"; X goto P; X X case P_POISON: X pline ("Yech! This stuff tastes like poison."); X losestr (rn1 (4, 3)); X losehp (rnd (10), "poison potion"); X break; X X case P_CONF: X pline ("Huh, What? Where am I?"); X u.uconfused += rn1 (7, 16); X break; X X case P_GAIN_STR: X if (u.ustr == 118) { X pline ("You've had enough of it!"); X break;/* Michiel */ X } X pline ("Wow do you feel strong!"); X if (u.ustr > 17) X u.ustr += rnd (118 - u.ustr); X else X u.ustr++; X if (u.ustr > u.ustrmax) X u.ustrmax = u.ustr; X flags.dstr = 1; X break; X X case P_SPEED: X pline ("You are suddenly moving much faster."); X u.ufast += rn1 (10, 100); X break; X X case P_BLIND: X pline ("A cloud of darkness falls upon you."); X u.ublind += rn1 (100, 250); X unCoff (COFF, 0); X break; X X case P_GAIN_LEV: X num = rnd (10); X u.uhpmax += num; X u.uhp += num; X if (u.ulevel < 14) {/* a3 */ X pline ("You feel more experienced."); X u.uexp = (10 * pow (u.ulevel - 1)) + 1; X pline (WCLEV, ++u.ulevel); X flags.dulev = 1; X flags.dexp = 1; X } X else X pline ("You feel more capable."); X flags.dhpmax = 1; X flags.dhp = 1; X break; X X case P_EXTRA_HEALING: X pline ("You feel much better."); X num = d (2, 20) + 1; X goto H; /* a3 */ X X default: X pline ("Bad(%d)potion", otmp -> otyp); X impossible (); X } X X if (!(oiden[otmp -> otyp] & POTN)) { X if (otmp -> otyp > P_BOOZE) { X oiden[otmp -> otyp] |= POTN; X u.urexp += 10; X } X else if (!potcall[otmp -> otyp]) X docall (otmp); X } X useup (otmp); X} X Xnothin (obj) Xregister OBJECT obj; X{ X pline ("You have a strange feeling for a moment, then it passes."); X if (obj -> olet == '?') { X if ((!(oiden[obj -> otyp] & SCRN)) && X (!scrcall[obj -> otyp])) X docall (obj); X } X else if ((!(oiden[obj -> otyp] & POTN)) && X (!potcall[obj -> otyp])) X docall (obj); X useup (obj); X} X Xdodrop () { X register OBJECT obj, otmp; X register int num; X X if (!(obj = getobj (0, "drop"))) { X nomove (); X return; X } X if (obj -> quan > 1 && !obj -> unpaid) { X pline ("How many do you want to drop (%d max) ?", X obj -> quan); X getlin (buf); X num = atoi (buf); X X if (num > obj -> quan || (num <= 0 && *buf) || X *buf == 0) { X if (num != 0) X pline ("You can't drop that %s!", X (num > 0) ? "many" : "few"); X nomove (); X return; X } X if (num != obj -> quan) { X otmp = newobj (); X *otmp = *obj;/* Copies whole structure */ X obj -> quan = num; X otmp -> quan -= num; X obj -> nobj = otmp; X } X } X if (obj == uarm || obj == uarm2 || X obj == uright || obj == uleft) { X pline ("You cannot drop something you are wearing."); X nomove (); X return; X } X /* (a3) i.p.v. `if( obj==uwep) uwep=0;': */ X if (obj == uwep && uwepcursed ()) X return; X dropit (obj); X doname (fobj, buf); X pline ("You dropped %s.", buf); X subfrombill (obj); X} X Xgemsdrop () { X register OBJECT obj; X register counting = 0; X X for (obj = invent; obj;) { X if (obj -> olet == '*') { X counting += obj -> quan; X dropit (obj); X subfrombill (obj); X obj = invent; X } X else X obj = obj -> nobj; X } X if (!counting) { X nomove (); X pline ("You ain't got no gems, Hacker!"); X } X else X pline ("You dropped %d gem%s.", counting, X counting == 1 ? "" : "s"); X} X Xuwepcursed () { /* a3,drop or throw uwep */ X if (uwep -> cursed) { X multi = 0; /* Dowield() */ X pline (WELDED, weapons[uwep -> otyp].wepnam); X return CURSED; X } X uwep = 0; X return NOTCURSED; X} X Xgetinventory (string) Xchar *string; X{ X register OBJECT otmp; X X for (otmp = invent; otmp && !index (string, otmp -> olet); otmp = X otmp -> nobj); X return (otmp ? 1 : 0); X} X Xdropit (obj) Xregister OBJECT obj; X{ X register OBJECT otmp; X X if (obj == invent) X invent = invent -> nobj; X else { X for (otmp = invent; otmp -> nobj != obj; X otmp = otmp -> nobj); X otmp -> nobj = obj -> nobj; X } X obj -> ox = u.ux; X obj -> oy = u.uy; X obj -> nobj = fobj; X fobj = obj; X if (u.uinvis) X newsym (u.ux, u.uy); X} / echo 'x - hack.h' sed 's/^X//' > hack.h << '/' X/* X * Hack.h X */ X X#define NORMAL_IO X#ifdef NORMAL_IO X X#include <stdio.h> X#define flush() fflush( stdout ) X X#else X X#undef putchar X#undef getchar X#define NULL 0 X#define STDOUT 0 /* Defines print in I/O packet */ X X#endif NORMAL_IO X X#include "envir.h" X#include "hack.name.h" X Xchar *index (); X Xlong pow (); X X#define BUFSZ 256 X X X/* Arguments for panic to give just an error message or a core dump */ X#define NOCORE 0 X#define CORE 1 X X#define ON 1 X#define OFF 0 X X#define WALL 1 X#define SDOOR 2 X#define DOOR 3 X#define CORR 4 X#define ROOM 5 X#define POOL 7 X#define VAULT 9 X X#define TRAPNUM 9 X X#define MSLOW 1 X#define MFAST 2 X X#define BEAR 0 X#define ARROW 1 X#define DART 2 X#define TDOOR 3 X#define TELE 4 X#define PIT 5 X#define SLPTRP 6 X#define PIERC 7 X#define MIMIC 8 X#define SEEN 32 X X#define UWEP 0 X#define UARM 1 X#define UARM2 2 X#define ULEFT 3 X#define URIGHT 4 X X#define POTN 1 X#define SCRN 2 X#define WANN 4 X#define RINN 8 X X#define UNC 1 /* unCoff(): */ X#define COFF 0 X X#define SETC 1 /* setCon(): */ X#define CON 0 X X#define IT1 1 X#define THEIT2 2 /* kluns */ X X#define CHOKED 0 X#define DIED 1 X#define STARVED 2 X#define DROWNED 3 X#define QUIT 4 /* Michiel args how you died */ X#define ESCAPED 5 X X#define NOMOVE 0 X#define MOVE 1 X#define DEAD 2 X X#define MISS 0 X#define HIT 1 X#define KILL 2 X X X Xtypedef struct func_tab { X char f_char; X int (*f_funct) (); X} FUNCTIONS; Xextern FUNCTIONS list[]; X X X Xstruct rm { X unsigned scrsym: 7; X unsigned typ: 6; X unsigned new: 1; X unsigned seen: 1; X unsigned lit: 1; X}; Xtypedef struct rm PART; Xextern PART levl[80][22]; X X X X Xstruct mkroom { X char lx, hx, ly, hy, rtype, rlit, doorct, fdoor; X}; Xtypedef struct mkroom MKROOM; Xextern MKROOM rooms[15]; X X X X#define DOORMAX 100 Xstruct coord { X char x, y; X}; Xtypedef struct coord COORDINATES; Xextern COORDINATES doors[DOORMAX]; X X X Xstruct food { X char *foodnam, prob, delay; X int nutrition; X}; Xtypedef struct food *FOOD; Xextern struct food foods[]; X X X Xstruct armor { X char *armnam, prob, delay, a_ac, a_can; X}; Xtypedef struct armor *ARMOR; Xextern struct armor armors[]; X X X X X Xstruct weapon { X char *wepnam, prob, wsdam, wldam; X}; Xtypedef struct weapon *WEAPON; Xextern struct weapon weapons[]; X X X X Xstruct permonst { X char *mname, mlet, mhd, mmove, ac, damn, damd; X unsigned pxlth; X}; Xtypedef struct permonst *MONSTDATA; Xextern struct permonst mon[8][7]; X#define PM_MIMIC &mon[5][2] X#define PM_PIERC &mon[2][3] X#define PM_DEMON &mon[7][6] X#define PM_CHAM &mon[6][6] X X X X Xstruct obj { X struct obj *nobj; X char otyp; X int spe; X unsigned ox: 7; X unsigned oy: 5; X unsigned olet: 7; X unsigned quan: 5; X unsigned known: 1; X unsigned cursed: 1; X unsigned unpaid: 1; X}; Xtypedef struct obj *OBJECT; Xextern OBJECT fobj, invent, uwep, uarm, uarm2, uleft, uright; X X X Xstruct stole { X OBJECT sobj; X unsigned sgold; X}; Xtypedef struct stole *STOLE; X X Xstruct monst { X struct monst *nmon; X MONSTDATA data; X STOLE mstole; X char mx, my; X int mhp, orig_hp; X unsigned invis: 1; X unsigned cham: 1; X unsigned angry: 1; /* Michiel: only for shopkeeper */ X unsigned ale: 1; /* Michiel: is it an ale?? */ X unsigned mspeed: 2; X unsigned msleep: 1; X unsigned mfroz: 1; X unsigned mconf: 1; X unsigned mflee: 1; X unsigned mcan: 1; X unsigned mtame: 1; X unsigned wormno: 5; X unsigned mxlth; X char mextra[1]; X}; Xtypedef struct monst *MONSTER; Xextern MONSTER fmon, shopkeeper, vaultkeeper; Xextern struct permonst treasurer; X XMONSTER m_at (); X X X Xstruct wseg { X struct wseg *nseg; X char wx, wy; X}; X Xtypedef struct wseg *WORMSEGMENT; X X#define newseg() (alloc( sizeof(struct wseg) )->Wseg) X X Xstruct gen { X struct gen *ngen; X char gx, gy; X unsigned gflag; X}; Xtypedef struct gen *GOLD_TRAP; Xextern GOLD_TRAP fgold, ftrap; X XGOLD_TRAP g_at (); XOBJECT o_at (), getobj (); X X Xstruct flag { X unsigned topl: 1; X unsigned botl: 1; X /* faint:1, screen:1, */ X unsigned oneline: 1; X unsigned next: 1; X unsigned move: 1; X unsigned mv: 1; X unsigned run: 2; X unsigned dgold: 1; X unsigned dhp: 1; X unsigned dhpmax: 1; X unsigned dstr: 1; X unsigned dac: 1; X unsigned dulev: 1; X unsigned dexp: 1; X unsigned dhs: 1; X unsigned dscr: 1; X}; Xtypedef struct flag FLAG; Xextern FLAG flags; X Xstruct you { X char ux, uy, ustr, ustrmax, udaminc, uac; X int uhunger; X unsigned ufast: 7; X unsigned uconfused: 6; X unsigned uinvis: 6; X unsigned ulevel: 5; X unsigned utrap: 3; X unsigned upit: 1; X unsigned uinshop: 1; X unsigned uinzoo: 1; X unsigned uinyard: 1; X unsigned uinswamp: 1; X unsigned uinknox: 1; X unsigned umconf: 1; X unsigned uhcursed: 1; X unsigned ufireres: 1; X unsigned ucoldres: 1; X unsigned utel: 1; X unsigned upres: 1; X unsigned ustelth: 1; X unsigned uagmon: 1; X unsigned ufeed: 1; X unsigned usearch: 1; X unsigned ucinvis: 1; X unsigned uregen: 1; X unsigned ufloat: 1; X unsigned uswallow: 1; X unsigned uswldtim: 4; X unsigned ucham: 1; X unsigned uhs: 2; X unsigned ublind; X short uhp, uhpmax; X long ugold, uexp, urexp; X MONSTER ustuck; X}; Xtypedef struct you YOU; Xextern YOU u; X X X Xextern char *wepnam[], *pottyp[], *scrtyp[], *traps[], X *wantyp[], *ringtyp[], *potcol[], *scrnam[], X *wannam[], *rinnam[], wdam[], oiden[], X *potcall[], *scrcall[], *wandcall[], *ringcall[], X curx, cury, savx, X xdnstair, ydnstair, xupstair, yupstair, X seehx, seelx, seehy, seely, X *save_cm, *killer, dlevel, maxdlevel, X dx, dy, buf[], lock[], X genocided[60], oldux, olduy, wizard; X Xextern unsigned moves; X Xextern multi; X X#define newmonst(xl) (alloc( xl + sizeof(struct monst) )->Mtmp ) X#define newobj() (alloc( sizeof(struct obj) )->Otmp ) X#define newgen() (alloc( sizeof(struct gen) )->Gtmp ) X#define newstole() (alloc( sizeof(struct stole) )->Stmp ) X X X#define CHAR_NULL (char *)NULL X#define OBJ_NULL (struct obj *)NULL X#define TRAP_NULL (struct gen *)NULL X#define MON_NULL (struct monst *)NULL X#define STOLE_NULL (struct stole *)NULL X X#ifndef SHOW Xunion PTRS { X GOLD_TRAP Gtmp; X MONSTER Mtmp; X OBJECT Otmp; X STOLE Stmp; X WORMSEGMENT Wseg; X char *Val; X}; X Xextern union PTRS * alloc (); X#endif SHOW / echo 'x - hack.mon.do.c' sed 's/^X//' > hack.mon.do.c << '/' X/* X * Hack.mon.do.c X */ X X/* Contains monster control routines */ X X#include "hack.h" X Xextern MONSTER bhit (); X Xmovemon () { X register MONSTER mtmp, mtmp2; X X for (mtmp = fmon; mtmp; mtmp = mtmp2) { X mtmp2 = mtmp -> nmon; X if (mtmp -> mspeed != MSLOW || moves % 2 == 0) X if (dochug (mtmp)) X continue;/* Monster died */ X if (mtmp -> mspeed == MFAST) X if (dochug (mtmp)) X continue; X X/* If we left the room: make monsters invis, even if they didn't move */ X X if (!cansee (mtmp -> mx, mtmp -> my)) X levlsym (mtmp -> mx, mtmp -> my, mtmp -> data -> mlet); X if (mtmp -> wormno && mtmp -> data -> mlet == 'w') X wormsee (mtmp -> wormno); X } X} X Xjustswld (mtmp) Xregister MONSTER mtmp; X{ X newsym (mtmp -> mx, mtmp -> my); X mtmp -> mx = u.ux; X mtmp -> my = u.uy; X u.ustuck = mtmp; X at (u.ux, u.uy, mtmp -> data -> mlet); X pseebl ("%s swallows you!", mtmp -> data -> mname); X more (); X u.uswallow = 1; X docrt (); X} X Xyouswld (mtmp, dam, die) Xregister MONSTER mtmp; Xregister dam, die; X{ X pseebl ("%s digests you!", killer = mtmp -> data -> mname); X if (dam > 0) { X u.uhp -= dam; X flags.dhp = 1; X } X if (u.uswldtim++ == die) { X pline ("It totally digests you!"); X u.uhp = 0; X } X} X Xx2hitu (mlev, x, name) Xregister mlev, x; Xregister char *name; /* a3 */ X{ X register i; X X for (i = 0; i < 2; i++) X hitu (mlev, (x < 0) ? d (2, x) : (x == 0) ? d (3, 4) : X rnd (x), name); X} X Xdochug (mtmp) Xregister MONSTER mtmp; X{ X register MONSTDATA mdat; X register tmp = 0, ctmp; X X if (mtmp -> mhp <= 0 && !mtmp -> mtame) X return 1; /* Killed by dog or ? */ X if (mtmp -> cham && !rn2 (6)) X newcham (mtmp, &mon[rn1 (6, 2)][rn2 (7)]); X mdat = mtmp -> data; X /* X if( mdat->mhd < 0 ) X panic( CORE, "Bad(%d)monster %c", mdat->mhd, X mdat->mlet ); X */ X if ((moves % 20 == 0 || index ("ViT", mdat -> mlet)) && X mtmp -> mhp < mtmp -> orig_hp) X mtmp -> mhp++; /* Regenerate monsters */ X if (mtmp -> mfroz) X return 0; /* Frozen monsters don't do anything */ X if (mtmp -> msleep) { X /* Wake up a monster, or get out of here */ X if (cansee (mtmp -> mx, mtmp -> my) && !u.ustelth && X (!rn2 (7) || u.uagmon)) X mtmp -> msleep = 0; X else X return 0; X } X X/* Confused monsters get unconfused with small probability */ X X if (mtmp -> mconf && !rn2 (50)) X mtmp -> mconf = 0; X if (mdat -> mmove >= rnd (12) && (mtmp -> mflee || mtmp -> mconf || X dist (mtmp -> mx, mtmp -> my) > 2 || mtmp -> mtame || X mtmp == shopkeeper) && (tmp = m_move (mtmp, 0)) && X mdat -> mmove <= 12) X return (tmp == 2); X /* Move monsters and exit if rate<=12 */ X if (tmp == 2) X return 1; /* Monster died moving */ X X if (!index ("Ea", mdat -> mlet) && dist (mtmp -> mx, mtmp -> my) < 3 X && !mtmp -> mtame && mtmp != shopkeeper && u.uhp > 0) { X nomul (tmp = 0); X if (u.uswallow) { X if (mtmp != u.ustuck) X if (mdat -> mmove - 12 > rnd (12)) X tmp = m_move (mtmp, 1); X } X else if (!index ("&DyF", mdat -> mlet)) { X if (mtmp -> ale && cansee (mtmp -> mx, mtmp -> my)) { X mtmp -> invis = 0; X pmon (mtmp); X } X tmp = hitu (mdat -> mhd, d (mdat -> damn, mdat -> damd), X mdat -> mname); X } X X/* Increase chance of hitting (no damage) for L and R */ X if (index ("LR", mdat -> mlet) && hitu (5, 0, mdat -> mname)) X tmp++; X X ctmp = (tmp && !mtmp -> mcan && (!uarm || X armors[uarm -> otyp].a_can < rnd (3))); X X switch (mdat -> mlet) { X X case ';': X if (mtmp -> mcan) X break; X if (!u.ustuck && !rn2 (20)) { X p2xthe ("%s swings itself around you!", X mdat -> mname); X u.ustuck = mtmp; X } X else if (u.ustuck == mtmp && ctmp) { X p2xthe ("%s drowns you...", mdat -> mname); X more (); X done (DROWNED); X } X break; X X case '&': X if (!mtmp -> mcan && !rn2 (15)) { X makemon (PM_DEMON); X mnexto (fmon); X } X else { X x2hitu (10, -6, mdat -> mname); X x2hitu (10, 3, mdat -> mname); X hitu (10, rn1 (4, 2), mdat -> mname); X } X break; X X case ',': X case '\'': X if (u.uswallow) X if (mdat -> mlet == ',') X youswld (mtmp, 4 + u.uac, 5); X else X youswld (mtmp, rnd (6), 7); X else if (tmp) X justswld (mtmp); X break; X X case 'A': X if (ctmp && rn2 (2)) { X pline ("You feel weaker!"); X losestr (1); X } X break; X X case 'C': X case 'Y': X hitu (4, rnd (6), mdat -> mname); X break; X X case 'c': X if (ctmp && !rn2 (5)) { X pline ("You get turned to stone!"); X u.uhp = 0; X } X break; X X case 'D': X if (rn2 (6) || mtmp -> mcan) { X hitu (10, d (3, 10), mdat -> mname); X x2hitu (10, 8, mdat -> mname); X break; X } X pseebl ("%s breathes fire!", mdat -> mname); X buzz (Z_FIRE, mtmp -> mx, mtmp -> my, X u.ux - mtmp -> mx, X u.uy - mtmp -> my); X break; X X case 'd': X hitu (6, d (2, 4), mdat -> mname); X break; X X case 'e': X hitu (10, d (3, 6), mdat -> mname); X break; X X case 'F': X if (mtmp -> mcan) X break; X pseebl ("%s explodes!", mdat -> mname); X if (u.ucoldres) X pline ("You don't seem affected by it."); X else { X if (17 - (u.ulevel >> 1) > rnd (20)) { X pline ("You get blasted!"); X tmp = 6; X } X else { X pline ("You duck the blast..."); X tmp = 3; X } X losehp (d (tmp, 6), mdat -> mname); X } X cmdel (mtmp); X return 1; X X case 'g': X if (!ctmp || multi < 0 || rn2 (6)) X break; X pseebl ("You are frozen by %ss juices", "cube'"); X nomul (-rnd (10)); X break; X X case 'h': X if (!ctmp || multi < 0 || rn2 (5)) X break; X pseebl ("You are put to sleep by %ss bite!", X "homunculus'"); X nomul (-rnd (10)); X break; X X case 'j': X tmp = hitu (4, rnd (3), mdat -> mname); X tmp &= hitu (4, rnd (3), mdat -> mname); X if (tmp) X x2hitu (4, 4, mdat -> mname); X break; X X case 'k': X if ((hitu (4, rnd (4), mdat -> mname) || !rn2 (3)) X && ctmp) X poisoned ("bee's sting", mdat -> mname); X break; X X case 'L': X if (ctmp && u.ugold && rn2 (2)) { X u.ugold -= (ctmp = somegold ()); X pline ("Your purse feels lighter."); X flags.dgold = 1; X X /* Michiel save stolen gold */ X if (mtmp -> mstole) X mtmp -> mstole -> sgold += ctmp; X else { X mtmp -> mstole = newstole (); X mtmp -> mstole -> sobj = 0; X mtmp -> mstole -> sgold = ctmp; X } X mtmp -> mflee = 1; X rloc (mtmp); X } X break; X X case 'N': X if (ctmp && invent && rn2 (2)) { X steal (mtmp); X rloc (mtmp); X mtmp -> mflee = 1; X } X break; X X case 'n': X x2hitu (11, -6, mdat -> mname); X break; X X case 'o': X hitu (5, rnd (6), mdat -> mname); X /* tmp= ?? */ X if (hitu (5, rnd (6), mdat -> mname) && ctmp && X !u.ustuck && rn2 (2)) { X u.ustuck = mtmp; X pseebl ("%s has grabbed you!", X mdat -> mname); X u.uhp -= d (2, 8); X break; X } X if (u.ustuck == mtmp) { X pline ("You are being crushed."); X u.uhp -= d (2, 8); X } X break; X X case 'P': X if (u.uswallow) X youswld (mtmp, d (2, 4), 12); X else if (ctmp && !rn2 (4)) X justswld (mtmp); X else X hitu (15, d (2, 4), mdat -> mname); X break; X X case 'Q': X x2hitu (3, 2, mdat -> mname); X break; X X case 'R': X if (ctmp && uarm && uarm -> otyp < A_STD_LEATHER X && uarm -> spe > -2) { X pline ("Your armor rusts!"); X --uarm -> spe; X u.uac++; X flags.dac = 1; X } X break; X X case 'S': X if (ctmp && !rn2 (8)) X poisoned ("snake's bite", mdat -> mname); X break; X X case 's': X if (tmp && !rn2 (8)) X poisoned ("scorpion's sting", X mdat -> mname); X x2hitu (5, 8, mdat -> mname); X break; X X case 'T': X x2hitu (6, 6, mdat -> mname); X break; X X case 'U': X x2hitu (9, 0, mdat -> mname);/* 0: d(3,4) */ X break; X X case 'v': X if (ctmp && !u.ustuck) X u.ustuck = mtmp; X break; X X case 'V': X if (tmp) X u.uhp -= 4; X if (rn2 (3)) X break; X V: X if (ctmp) {/* hit by V or W */ X if (u.ulevel > 1) X pline ("Goodbye level %d.", X u.ulevel--); X else X u.uhp = 0; X ctmp = rnd (10); X u.uhp -= ctmp; X u.uhpmax -= ctmp; X u.uexp = 10L * pow (u.ulevel - 1) - 1L; X flags.dhp = 1; X flags.dhpmax = 1; X flags.dulev = 1; X flags.dexp = 1; X } X break; X X case 'W': X if (rn2 (5)) X break; X goto V; X case 'w': X if (tmp) X wormhit (mtmp); X break; X case 'X': X for (tmp = 0; tmp < 3; tmp++) X hitu (8, rnd (3), mdat -> mname); X break; X X case 'y': X if (mtmp -> mcan) X break; X cmdel (mtmp); X if (!u.ublind) { X pline ("You are blinded by a blast of light!"); X u.ublind = d (4, 12); X unCoff (COFF, 0); X } X return 1; X } /* switch */ X X if (u.uhp <= 0) X killer = mdat -> mname; X } X else if (mtmp -> ale && cansee (mtmp -> mx, mtmp -> my)) { X mtmp -> invis = 1; X newsym (mtmp -> mx, mtmp -> my); X } X/* Extra movement for fast monsters */ X if (mdat -> mmove - 12 > rnd (12)) X tmp = m_move (mtmp, 1); X return (tmp == 2); X} X Xcmdel (mtmp) Xregister MONSTER mtmp; X{ X register char mx = mtmp -> mx, my = mtmp -> my; X X delmon (mtmp); X if (cansee (mx, my)) X newsym (mx, my); X} X Xinrange (mtmp) Xregister MONSTER mtmp; X{ X int zx, zy; X register char tx = u.ux - mtmp -> mx, ty = u.uy - mtmp -> my; X X/* This mess figures out if the person is within 8 */ X if ((!tx && abs (ty) < 8) || (!ty && abs (tx) < 8) || X (abs (tx) == abs (ty) && abs (tx) < 8)) { X if (tx == 0) X zx = 0; X else X zx = tx / abs (tx); X if (ty == 0) X zy = 0; X else X zy = ty / abs (ty); X/* If we don't save dx and dy a capital move may screw up: */ X tx = dx; X ty = dy; X if (bhit (zx, zy, 8) == mtmp) X buzz (Z_FIRE, mtmp -> mx, mtmp -> my, dx, dy); X dx = zx; X dy = zy; X } X} X Xm_move (mtmp, after) Xregister MONSTER mtmp; X{ X register MONSTER mtmp2; X register nix, niy, omx, omy, appr, nearer, cnt, zx, zy; X char ddx, ddy, mmoved = 0; X X/* My dog gets a special treatment */ X if (mtmp -> mtame) X return dog_move (mtmp, after); X X if (u.uswallow) X return (1); /* a3 */ X/* Likewise for shopkeeper */ X if (mtmp == shopkeeper) X return shk_move (); X if (mtmp == vaultkeeper && !mtmp -> angry) X return (0); X X if (mtmp -> data -> mlet == 't' && !rn2 (19)) { X if (rn2 (2)) { X ddx = mtmp -> mx; X ddy = mtmp -> my; X mnexto (mtmp);/* Doesn't change old position */ X levlsym (ddx, ddy, 't'); X } X else X rloc (mtmp);/* Rloc does */ X return 1; X } X if (!mtmp -> mcan) X switch (mtmp -> data -> mlet) { X case 'D': X inrange (mtmp); X break; X case 'U': X if (!rn2 (10) && !u.uconfused && X cansee (mtmp -> mx, mtmp -> my)) { X pline ("You are confused!"); X u.uconfused = d (3, 4); X } X if (!mtmp -> mflee && u.uswallow && X u.ustuck != mtmp) X return 1; X } X appr = 1; X if (mtmp -> mflee) X appr = -1; X if (mtmp -> mconf || u.uinvis || (index ("BI", mtmp -> data -> mlet) && X !rn2 (3))) X appr = 0; X omx = mtmp -> mx; X omy = mtmp -> my; X nix = omx; X niy = omy; X cnt = 0; X for (ddx = -1; ddx <= 1; ddx++) X for (ddy = -1; ddy <= 1; ddy++) X if (r_free (zx = omx + ddx, zy = omy + ddy, mtmp) X && (ddx || ddy) X && !(ddx && ddy && (levl[omx][omy].typ == DOOR || X levl[zx][zy].typ == DOOR))) { X if (!mtmp -> mconf && m_at (zx, zy)) X continue; X nearer = (dist (zx, zy) < dist (nix, niy)); X if ((appr > 0 && nearer) || (appr < 0 && X !nearer) || X (!mmoved && mtmp -> wormno) || X (!appr && !rn2 (++cnt))) { X nix = zx; X niy = zy; X mmoved++; X } X } X if (mmoved) { X if (mtmp -> mconf && (mtmp2 = m_at (nix, niy))) { X if (hitmm (mtmp, mtmp2) == 1 && rn2 (4) && X hitmm (mtmp2, mtmp) == 2) X return 2; X return 0; X } X if (!mtmp -> ale) { X mtmp -> mx = nix; X mtmp -> my = niy; X } X else if (levl[nix][niy].typ == POOL) { X mtmp -> mx = nix; X mtmp -> my = niy; X } X X if (mtmp -> wormno && mtmp -> data -> mlet == 'w') X worm_move (mtmp); X } X else { X if (!rn2 (10) && index ("tNL", mtmp -> data -> mlet)) { X rloc (mtmp); X return 0; X } X if (mtmp -> wormno) X worm_nomove (mtmp); X } X if (mmoved || !cansee (omx, omy)) X levlsym (omx, omy, mtmp -> data -> mlet); X pmon (mtmp); X return (mmoved); X} / echo 'x - mklev.make.c' sed 's/^X//' > mklev.make.c << '/' X/* X * Mklev.make.c X */ X X#define ZOO 1 X#define GRAVEYARD 2 X#define SWAMP 3 X#define FORT_KNOX 4 X#define MAZE 6 X X#define NORMAL_IO X#include "hack.h" X Xextern char mmon[8][8]; X X#define MAZX ((rnd(37) << 1) + 1) X#define MAZY ((rnd(8) << 1) + 1) X X#define somex() rn1( croom->hx - croom->lx + 1, croom->lx ) X#define somey() rn1( croom->hy - croom->ly + 1, croom->ly ) X Xextern PART levl[80][22]; X Xextern MONSTER fmon; Xextern OBJECT fobj; Xextern GOLD_TRAP fgold, ftrap; X Xextern MKROOM rooms[15], *croom; X Xextern COORDINATES doors[DOORMAX]; X Xextern int doorindex, nroom, comp (); X Xextern char dlevel, *geno, goldseen, X xdnstair, xupstair, ydnstair, yupstair, X wizard, nxcor, x, y, X dx, dy, tx, ty; X /* For corridors and other things... */ X Xmakemaz () { X X/* This is all Kenny's fault. He seems to have his x and y reversed */ X X int xx, yy, a, q, sp, dir, dirs[5], stack[200]; X register int zx, zy; X register OBJECT otmp; X X for (xx = 2; xx < 19; xx++) X for (yy = 2; yy < 77; yy++) { X if (xx % 2 == 0 || yy % 2 == 0) X levl[yy][xx].typ++;/* WALL==1 */ X } X zx = MAZY; X zy = MAZX; X sp = 1; X stack[1] = 100 * zx + zy; X while (sp) { X xx = stack[sp] / 100; X yy = stack[sp] % 100; X levl[yy][xx].typ = 2; X q = 0; X for (a = 0; a < 4; a++) X if (okay (xx, yy, a)) X dirs[q++] = a; X if (q) { X dir = dirs[rn2 (q)]; X move (&xx, &yy, dir); X levl[yy][xx].typ = 0; X move (&xx, &yy, dir); X stack[++sp] = 100 * xx + yy; X } X else X sp--; X } X for (xx = 2; xx < 77; xx++) X for (yy = 2; yy < 19; yy++) {/* This was mine */ X if (levl[xx][yy].typ == WALL) X levl[xx][yy].scrsym = '-'; X else { X levl[xx][yy].typ = ROOM; X levl[xx][yy].scrsym = '.'; X } X } X for (xx = rn1 (8, 11); xx; xx--) { X mkobj (0); X levl[(fobj -> ox = MAZX)][(fobj -> oy = MAZY)].scrsym = fobj -> olet; X } X for (xx = rn1 (5, 7); xx; xx--) X makemon (1, MAZX, MAZY); X for (xx = rn1 (6, 7); xx; xx--) X mkgold (0, MAZX, MAZY); X for (xx = rn1 (6, 7); xx; xx--) X mktrap (0, 1); X levl[(xupstair = MAZX)][(yupstair = MAZY)].scrsym = '<'; X levl[zy][zx].scrsym = '"'; X otmp = newobj (); X otmp -> nobj = fobj; X fobj = otmp; X otmp -> ox = zy; X otmp -> oy = zx; X otmp -> olet = '"'; X xdnstair = 0; X ydnstair = 0; X} X X/* Make a trap somewhere (in croom if mazeflag=0) */ Xmktrap (num, mazeflag) Xregister int num, mazeflag; X{ X register GOLD_TRAP gtmp; X register int nopierc; X int nomimic, fakedoor, fakegold, tryct = 0; X X gtmp = newgen (); X if (!num || num >= TRAPNUM) { X nopierc = (dlevel < 4); X nomimic = (dlevel < 9 || goldseen); X gtmp -> gflag = rn2 (TRAPNUM - nopierc - nomimic); X/* Note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */ X } X else X gtmp -> gflag = num; X fakedoor = (gtmp -> gflag == MIMIC && rn2 (2) && !mazeflag); X fakegold = (gtmp -> gflag == MIMIC && !fakedoor); X do { X if (++tryct > 200) { X printf ("tryct overflow7\n"); X free (gtmp); X return; X } X if (mazeflag) { X gtmp -> gx = MAZX; X gtmp -> gy = MAZY; X } X else if (!fakedoor) { X gtmp -> gx = somex (); X gtmp -> gy = somey (); X } X else { X if (rn2 (2)) { X if (rn2 (2)) X gtmp -> gx = croom -> hx + 1; X else X gtmp -> gx = croom -> lx - 1; X gtmp -> gy = somey (); X } X else { X if (rn2 (2)) X gtmp -> gy = croom -> hy + 1; X else X gtmp -> gy = croom -> ly - 1; X gtmp -> gx = somex (); X } X } X } while (g_at (gtmp -> gx, gtmp -> gy, (fakegold) ? fgold : ftrap)); X if (!fakegold) { X gtmp -> ngen = ftrap; X ftrap = gtmp; X } X else { X gtmp -> gflag = 0; X gtmp -> ngen = fgold; X fgold = gtmp; X goldseen++; X } X if (mazeflag && !rn2 (10) && gtmp -> gflag < PIERC) X gtmp -> gflag |= SEEN; X if (fakedoor) X num = '+'; X else if (fakegold) X num = '$'; X else X return; X levl[gtmp -> gx][gtmp -> gy].scrsym = num; X} X Xmkgold (num, goldx, goldy) Xregister int num; X{ X register GOLD_TRAP gtmp; X X gtmp = newgen (); X gtmp -> ngen = fgold; X levl[gtmp -> gx = goldx][gtmp -> gy = goldy].scrsym = '$'; X gtmp -> gflag = (num) ? num : 1 + rnd (dlevel + 2) * rnd (30); X fgold = gtmp; X} X X/*VARARGS*/ Xpanic (str, arg1, arg2) Xregister char *str; X{ X fprintf (stderr, "\nMKLEV ERROR: "); X fprintf (stderr, str, arg1, arg2); X abort (); X} X Xmakemon (sl, monx, mony) Xregister int sl, monx, mony; X{ X register MONSTER mtmp; X register int tryct = 0; X X mtmp = newmonst (0); X mtmp -> mstole = STOLE_NULL; X mtmp -> msleep = sl; X mtmp -> mx = monx; X mtmp -> my = mony; X mtmp -> mfroz = 0; X mtmp -> mconf = 0; X mtmp -> mflee = 0; X mtmp -> mspeed = 0; X mtmp -> mtame = 0; X mtmp -> angry = 0; X mtmp -> mxlth = 0; X mtmp -> wormno = 0; X mtmp -> ale = 0; X if (levl[monx][mony].typ == POOL) { X mtmp -> ale = 1; X mtmp -> invis = 1; X } X else { X do { X if (++tryct > 100) { X printf ("tryct overflow8\n"); X free (mtmp); X return; X } X mtmp -> mhp = rn2 (dlevel / 3 + 1) % 8; X mtmp -> orig_hp = rn2 (7); X } while (index (geno, mmon[mtmp -> mhp][mtmp -> orig_hp])); X } X mtmp -> nmon = fmon; X fmon = mtmp; X} X X Xchar shtypes[] = "=/)%?!["; /* 8 shoptypes: 7 specialised, 1 mixed */ Xchar shprobs[] = { X 3, 3, 5, 5, 10, 10, 14, 50 X}; /* Their probabilities */ X Xmkshop () { X register MKROOM * sroom; X register int sh, sx, sy, i; X register char let; X X for (sroom = &rooms[0];; sroom++) { X if (sroom -> hx < 0) X return; X if (ch_upstairs (sroom) || ch_dnstairs (sroom)) X continue; X if (sroom -> doorct == 1) X break; X } X for (i = rn2 (100), let = 0; (i -= shprobs[let]) >= 0; let++) X if (!shtypes[let]) X break; /* Superfluous */ X sroom -> rtype = 8 + let; X let = shtypes[let]; X sh = sroom -> fdoor; X for (sx = sroom -> lx; sx <= sroom -> hx; sx++) X for (sy = sroom -> ly; sy <= sroom -> hy; sy++) { X if (sx == sroom -> lx && doors[sh].x == sx - 1 || X sx == sroom -> hx && doors[sh].x == sx + 1 || X sy == sroom -> ly && doors[sh].y == sy - 1 || X sy == sroom -> hy && doors[sh].y == sy + 1) X continue; X mkobj (let); X levl[fobj -> ox = sx][fobj -> oy = sy].scrsym = X fobj -> olet; X } X} X Xmkzoo () { X register MKROOM * zroom; X register int zx, zy; X X for (;;) { X zroom = &rooms[rn2 (nroom)]; X if (zroom -> hx < 0 || zroom -> rtype >= 8 || X ch_upstairs (zroom)) X continue;/* Niet in kamer met terugweg */ X break; /* Kamer gevonden */ X } X zroom -> rtype = ZOO; X for (zx = zroom -> lx; zx <= zroom -> hx; zx++) X for (zy = zroom -> ly; zy <= zroom -> hy; zy++) { X if (!m_at (zx, zy)) { X mkgold (0, zx, zy); X makemon (1, zx, zy); X } X } X} X X Xmkyard () { X register MKROOM * yroom; X register int yx, yy; X X for (;;) { X yroom = &rooms[rn2 (nroom)]; X if (yroom -> hx < 0 || yroom -> rtype >= 8 || X ch_upstairs (yroom)) X continue;/* Niet in kamer met terugweg */ X break; /* Kamer gevonden */ X } X yroom -> rtype = GRAVEYARD; X for (yx = yroom -> lx; yx <= yroom -> hx; yx++) X for (yy = yroom -> ly; yy <= yroom -> hy; yy++) { X if (!mymakemon (yx, yy)) { X if (fmon -> mhp == 7) X mymakemon (yx, yy); X /* Not so many demons */ X mkgold (0, yx, yy); X if (fmon -> mhp != 1) { X mkobj (0); X if (rn2 (8)) X fobj -> cursed = 1; X levl[fobj -> ox = yx][fobj -> oy = yy].scrsym = fobj -> olet; X } X } X } X} X X#define NOMON 1 X#define MON 0 X Xmymakemon (monx, mony) { X register MONSTER mtmp; X register int tryct = 0; X register int tmp = 0; X X if (m_at (monx, mony)) X return NOMON; X mtmp = newmonst (0); X mtmp -> mstole = STOLE_NULL; X mtmp -> msleep = 1; X mtmp -> mx = monx; X mtmp -> my = mony; X mtmp -> mfroz = 0; X mtmp -> mconf = 0; X mtmp -> mflee = 0; X mtmp -> mspeed = 0; X mtmp -> mtame = 0; X mtmp -> angry = 0; X mtmp -> mxlth = 0; X mtmp -> wormno = 0; X do { X if (++tryct > 1000) { X printf ("tryct overflow yard\n"); X free (mtmp); X return NOMON; X } X tmp = putyard (mtmp); X } while (index (geno, mmon[mtmp -> mhp][mtmp -> orig_hp]) || tmp); X mtmp -> nmon = fmon; X fmon = mtmp; X return 0; X} X Xputyard (mtmp) XMONSTER mtmp; X{ X switch (rn2 (5)) { X case 0: X mtmp -> mhp = 1;/* level 3 */ X mtmp -> orig_hp = 6;/* ZOMBIE */ X break; X case 1: X if (dlevel < 18) X return NOMON; X mtmp -> mhp = 6;/* level 18 */ X mtmp -> orig_hp = 2;/* VAMPIRE */ X break; X case 2: X mtmp -> mhp = 4;/* level 12 */ X mtmp -> orig_hp = 5;/* Wraith */ X break; X case 3: X if (dlevel < 21) X return NOMON; X mtmp -> mhp = 7;/* level 21 */ X mtmp -> orig_hp = 6;/* DEMON */ X break; X case 4: X mtmp -> mhp = 10;/* altijd */ X mtmp -> orig_hp = 10;/* GHOST */ X break; X default: X mtmp -> mhp = rn2 (dlevel / 3 + 1) % 8; X mtmp -> orig_hp = rn2 (7); X } X return MON; X} X Xmkswamp () { X register MKROOM * zroom; X register int zx, zy; X register int first = 0; X X for (;;) { X zroom = &rooms[rn2 (nroom)]; X if (zroom -> hx < 0) X return; X if (ch_upstairs (zroom) || ch_dnstairs (zroom)) X continue; X if (zroom -> hx < 0 || zroom -> rtype >= 8) X continue; X /* Niet in kamer met terugweg of weg naar beneden */ X break; /* Kamer gevonden */ X } X zroom -> rtype = SWAMP; X for (zx = zroom -> lx; zx <= zroom -> hx; zx++) X for (zy = zroom -> ly; zy <= zroom -> hy; zy++) { X if ((zx + zy) % 2 && !o_at (zx, zy) && X !g_at (zx, zy, fgold) && !m_at (zx, zy) && X ch_doors (zx, zy)) { X levl[zx][zy].typ = POOL; X levl[zx][zy].scrsym = '}'; X if (!first) { X makemon (0, zx, zy); X ++first; X } X else if (!rn2 (4)) X makemon (0, zx, zy); X } X } X} X Xch_doors (zx, zy) Xregister int zx, zy; X{ X register int xx, yy; X register int status = 1; X X for (xx = zx - 1; xx <= zx + 1; xx++) X for (yy = zy - 1; yy <= zy + 1; yy++) { X if (levl[xx][yy].typ == DOOR) X status = 0; X else if (levl[xx][yy].typ == SDOOR) { X levl[xx][yy].typ = DOOR; X levl[xx][yy].scrsym = '+'; X status = 0; X } X } X return status; X} X Xmk_knox () { X register MKROOM * kroom; X register int kx, ky; X register int tmp = 10000; X OBJECT otmp; X MONSTER mtmp; X GOLD_TRAP gtmp; X X for (kroom = &rooms[0];; ++kroom) { X if (kroom -> hx < 0) X return; X if (ch_upstairs (kroom) || ch_dnstairs (kroom)) X continue; X if ((kroom -> rtype >= 8 || kroom -> rtype <= SWAMP) X && kroom -> rtype) X /* Shop or Zoo or Graveyard or Swamp */ X continue; X if (kroom -> hx - kroom -> lx <= 3 || kroom -> hy - kroom -> ly <= 3) X continue; X break; X } X kroom -> rtype = FORT_KNOX; X kx = ((kroom -> hx - kroom -> lx) / 2) + kroom -> lx; X ky = ((kroom -> hy - kroom -> ly) / 2) + kroom -> ly; X for (tx = kx - 1; tx <= kx + 1; ++tx) X for (ty = ky - 1; ty <= ky + 1; ++ty) { X if (tx == kx && ty == ky) X continue; X if ((otmp = o_at (tx, ty))) { X otmp -> ox = kx; X otmp -> oy = ky; X } X if ((mtmp = m_at (tx, ty))) X delmon (mtmp); X if ((gtmp = g_at (tx, ty, fgold))) { X tmp += gtmp -> gflag; X delgen (gtmp, fgold); X } X if ((gtmp = g_at (tx, ty, ftrap))) X delgen (gtmp, ftrap); X levl[tx][ty].typ = VAULT; X levl[tx][ty].scrsym = (ty == ky) ? '|' : '-'; X } X mkgold (tmp, kx, ky); X} X Xch_upstairs (mroom) Xregister MKROOM * mroom; X{ X return (mroom -> lx <= xupstair && xupstair <= mroom -> hx && X mroom -> ly <= yupstair && yupstair <= mroom -> hy); X} X Xch_dnstairs (mroom) Xregister MKROOM * mroom; X{ X return (mroom -> lx <= xdnstair && xdnstair <= mroom -> hx && X mroom -> ly <= ydnstair && ydnstair <= mroom -> hy); X} X Xdelmon (mtmp) Xregister MONSTER mtmp; X{ X register MONSTER mtmp2; X X if (mtmp == fmon) X fmon = fmon -> nmon; X else { X for (mtmp2 = fmon; mtmp2 -> nmon != mtmp; X mtmp2 = mtmp2 -> nmon); X mtmp2 -> nmon = mtmp -> nmon; X } X} X Xdelgen (gtmp, key) Xregister GOLD_TRAP gtmp, key; X{ X register GOLD_TRAP gtmp2; X X if (gtmp == key) X key = key -> ngen; X else { X for (gtmp2 = key; gtmp2 -> ngen != gtmp; X gtmp2 = gtmp2 -> ngen); X gtmp2 -> ngen = gtmp -> ngen; X } X} / echo 'Part 01 of Hack complete.' exit -- Michiel Huisjes. {seismo|decvax|philabs}!mcvax!vu44!ark!huisjes
huisjes@ark.UUCP (Michiel B. Huisjes) (02/06/85)
#!/bin/sh # # # # This is a shell archive. These archives are packed by the program # packmail(1). If you have the program unshar(1), I suggest you use it. # If you don't remove anything before the cut line and then feed to # sh(1) # # =====CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=== # echo 'Start of Hack, part 02 of 05:' echo 'x - hack.do1.c' sed 's/^X//' > hack.do1.c << '/' X/* X * Hack.do1.c X */ X X#include "hack.h" X Xextern char NOTHIN[], WAND[]; X Xextern MONSTER shopkeeper; XMONSTER vaultkeeper; X Xchar *wandeffect[] = { X "magic missile", X "bolt of fire", X "sleep ray", X "bolt of cold", X "death ray", X "bolt of confusion" X}; X X#define MAXLEVEL 40 X Xchar vaultflag[MAXLEVEL]; X XMONSTER bhit (); X X X X/* More various user do commands */ X X X X Xdozap () { X register OBJECT obj; X register MONSTER mtmp; X char zx, zy; X register num; X X if (!(obj = getobj ("/", "zap"))) { X nomove (); X return; X } X if (!obj -> spe) { X pline (NOTHIN); X return; X } X obj -> spe--; X if (obj -> otyp <= Z_CREATE_MON) { X switch (obj -> otyp) { X X case Z_LIGHT: X if (dlevel) X litroom (); X else X pline (NOTHIN); X break; X X case Z_DETEC: X if (!findit ()) X return; X break; X X case Z_CREATE_MON: X makemon (0); X mnexto (fmon); X break; X } X X if (oiden[obj -> otyp] & WANN) X return; X u.urexp += 10; X oiden[obj -> otyp] |= WANN; X return; X } X if (!getdir ()) { X obj -> spe++; X nomove (); X return; X } X if (obj -> otyp <= Z_TELEPORT) { X if (mtmp = bhit (dx, dy, rn1 (8, 6))) { X switch (obj -> otyp) { X X case Z_EXHAUST: X pline ("You fight and fight and fight......"); X home (); X flush (); X sleep (2); X flags.topl = 0; X u.uhp -= mtmp -> mhp; X if (u.uhp <= 0) { X pseebl ("You cannot beat %s", X mtmp -> data -> mname); X pline ("You die...."); X done (DIED); X } X else { X mtmp -> mhp = 0; X flags.dhp = 1; X killed (mtmp); X } X oiden[obj -> otyp] |= WANN; X break; X X case Z_SLOW_MON: X mtmp -> mspeed = MSLOW; X break; X X case Z_SPEED_MON: X mtmp -> mspeed = MFAST; X break; X X case Z_UND_TUR: X if (index (" WVZ&", mtmp -> data -> mlet)) { X mtmp -> mhp -= rnd (8); X if (alive (mtmp)) X mtmp -> mflee = 1; X } X break; X X case Z_POLYMORF: X if (mtmp -> ale && !cansee (mtmp -> mx, mtmp -> my)) X break; X if (mtmp == shopkeeper) X shkdead ();/* Michiel */ X unstuck (mtmp); X newcham (mtmp, &mon[rn2 (8)][rn2 (7)]); X oiden[obj -> otyp] |= WANN; X return; X X case Z_CAN: X mtmp -> mcan = 1; X break; X X case Z_TELEPORT: X unstuck (u.ustuck); X oiden[obj -> otyp] |= WANN; X if (mtmp == shopkeeper) X setangry ();/* FRED */ X else if (mtmp == vaultkeeper) X mtmp -> angry = 1; X rloc (mtmp); X break; X X } X } X return; X } X if (obj -> otyp == Z_CLOSING) { X PART * room; X X zx = u.ux + dx; X zy = u.uy + dy; X room = &levl[zx][zy]; X while (room -> typ >= CORR) { X zx += dx; X zy += dy; X room = &levl[zx][zy]; X } X if (room -> typ == DOOR || room -> typ == SDOOR) { X pline ("The %sdoor closes forever.", X room -> typ == SDOOR ? "secret " : ""); X oiden[obj -> otyp] |= WANN; X room -> typ = WALL; X newsym (zx, zy); X } X return; X } X if (obj -> otyp == Z_DIGGING) { X /* This is further improved by Michiel and Fred */ X PART * room; X int range = 1; X X zx = u.ux + dx; X zy = u.uy + dy; X num = ROOM; X for (;;) { X if (zx < 1 || zx > 78 || zy < 1 || zy > 21) { X zx -= dx; X zy -= dy; X break; X } X atl (zx, zy, '*'); X at (zx, zy, '*'); X ++range; X room = &levl[zx][zy]; X if (!xdnstair) { X if (zx < 3 || zx > 76 || zy < 3 || X zy > 18) X break; X if (room -> typ == WALL) { X room -> typ = ROOM; X break; X } X } X else if (room -> typ == POOL) X goto check; X else if (num == ROOM || num == 10) { X if (room -> typ) { X if (room -> typ == VAULT) X vaultinit (); X if (room -> typ != ROOM) { X if (room -> typ == VAULT) X room -> typ = ROOM; X else X if (room -> typ != CORR) X room -> typ = DOOR; X if (num == 10) X break; X num = 10; X } X } X else X room -> typ = CORR; X } X else { X if (room -> typ == VAULT) X vaultinit (); X if (room -> typ % 4) { X /* WALL,(S)DOOR,ROOM */ X room -> typ = DOOR; X break; X } X else X room -> typ = CORR; X } X check: X newsym (zx, zy); X zx += dx; X zy += dy; X } X while (--range) { X newsym (zx, zy); X if (mtmp = m_at (zx, zy)) X pmon (mtmp); X zx -= dx; X zy -= dy; X } X } X else X buzz (obj -> otyp, u.ux, u.uy, dx, dy); X oiden[obj -> otyp] |= WANN; X} X Xhit (str, mtmp) Xregister char *str; Xregister MONSTER mtmp; X{ X psee (THEIT2, mtmp -> mx, mtmp -> my, "%s hits %s", str, X mtmp -> data -> mname); X} X Xmiss (str, mtmp) Xregister char *str; Xregister MONSTER mtmp; X{ X psee (THEIT2, mtmp -> mx, mtmp -> my, "%s misses %s", str, X mtmp -> data -> mname); X} X Xfindit () { X char num, lx, hx, ly, hy; X register char zx, zy; X register GOLD_TRAP gtmp, gt1; X X for (lx = u.ux; levl[lx - 1][u.uy].typ % CORR; lx--);/* typ!=0 */ X /* WALL, SDOOR, DOOR, or ROOM (see hack.h) */ X X for (hx = u.ux; levl[hx + 1][u.uy].typ % 4; hx++); X for (ly = u.uy; levl[u.ux][ly - 1].typ % 4; ly--); X for (hy = u.uy; levl[u.ux][hy + 1].typ % 4; hy++); X num = 0; X for (zy = ly; zy <= hy; zy++) X for (zx = lx; zx <= hx; zx++) { X if (levl[zx][zy].typ == SDOOR) { X levl[zx][zy].typ = DOOR; X atl (zx, zy, '+'); X num++; X } X else if (gtmp = g_at (zx, zy, ftrap)) { X if (gtmp -> gflag == PIERC) { X mkmonat (PM_PIERC, zx, zy); X num++; X deltrap (gtmp); X } X else if (gtmp -> gflag == MIMIC) { X deltrap (gtmp); X M: X mkmonat (PM_MIMIC, zx, zy); X num++; X } X else if (!gtmp -> gflag & SEEN) { X gtmp -> gflag |= SEEN; X atl (zx, zy, '^'); X num++; X } X } X else if ((gtmp = g_at (zx, zy, fgold)) && X !gtmp -> gflag) { X if (gtmp == fgold) X fgold = gtmp -> ngen; X else { X for (gt1 = fgold; gt1 -> ngen != X gtmp; gt1 = gt1 -> ngen); X gt1 -> ngen = gtmp -> ngen; X } X free (gtmp); X goto M; X } X } X return (num); X} X X/* Sets dx,dy to the final position of the weapon thrown */ XMONSTER bhit (ddx, ddy, range) { X register MONSTER mtmp; X X dx = u.ux; X dy = u.uy; X if (u.uswallow) X return u.ustuck;/* a3 */ X while (range-- > 0) { X dx += ddx; X dy += ddy; X if (mtmp = m_at (dx, dy)) X return (mtmp); X if (levl[dx][dy].typ < CORR) { X dx -= ddx; X dy -= ddy; X return (0); X } X } X return (0); X} X Xbuzz (type, sx, sy, ddx, ddy) Xregister sx, sy; X{ X PART * lev; X register char range, let; X register MONSTER mtmp; X register wandeftype = type - 11; X X if (u.uswallow) { X pline ("The %s rips into the %s.", X wandeffect[wandeftype], X u.ustuck -> data -> mname); X zhit (u.ustuck, type); X alive (u.ustuck);/* a3 */ X return; X } X range = rn1 (7, 7); X if (ddx == ddy) X let = '\\'; X else if (ddx && ddy) X let = '/'; X else if (ddx) X let = '-'; X else X let = '|'; X while (range-- > 0) { X sx += ddx; X sy += ddy; X if ((lev = &levl[sx][sy]) -> typ) { X at (sx, sy, let); X on (sx, sy); X lev -> new = 1; X } X if (mtmp = m_at (sx, sy)) { X if (mtmp == vaultkeeper) X mtmp -> angry = 1; X if (rnd (20) < 18 + mtmp -> data -> ac) { X zhit (mtmp, type); X if (alive (mtmp)) X hit (wandeffect[wandeftype], X mtmp); X range -= 2; X } X else X miss (wandeffect[wandeftype], mtmp); X } X else if (sx == u.ux && sy == u.uy) { X if (rnd (20) < 18 + u.uac) { X range -= 2; X flags.dhp = 1;/* Michiel */ X pline ("The %s hits you!", X wandeffect[wandeftype]); X switch (type) { X case Z_MAG_MISSILE: X u.uhp -= d (2, 6); X break; X case Z_FIRE: X if (u.ufireres) { X pline ("You don't feel hot!"); X break; X } X u.uhp -= d (6, 6); X break; X case Z_SLEEP: X nomul (-rnd (25)); X break; X case Z_COLD: X if (u.ucoldres) { X pline ("You don't feel cold!"); X break; X } X u.uhp -= d (6, 6); X break; X case Z_DEATH: X u.uhp = 0; X break; X case Z_CONF_MON: X u.uconfused = d (4, 6); X } X if (u.uhp <= 0) X killer = wandeffect[wandeftype]; X } X else X pline ("The %s wizzes by you!", X wandeffect[wandeftype]); X } X if (lev -> typ <= DOOR || lev -> typ == VAULT) { X psee (0, sx, sy, "%s bounces!", X wandeffect[wandeftype], NULL); X ddx = -ddx; X ddy = -ddy; X range--; X } X } X} X Xzhit (mtmp, type) Xregister MONSTER mtmp; Xregister type; X{ X if (mtmp == shopkeeper) X setangry (); X switch (type) { X case Z_MAG_MISSILE: X mtmp -> mhp -= d (2, 6); X break; X case Z_FIRE: X if (index ("Dg", mtmp -> data -> mlet)) X return; X mtmp -> mhp -= d (6, 6); X if (mtmp -> data -> mlet == 'Y') X mtmp -> mhp -= 7; X break; X case Z_SLEEP: X mtmp -> mfroz = 1; X break; X case Z_COLD: X if (index ("Ygf", mtmp -> data -> mlet)) X return; X if (mtmp -> data -> mlet == 'D') X mtmp -> mhp -= 7; X mtmp -> mhp -= d (6, 6); X break; X case Z_DEATH: X if (index ("WVZ ", mtmp -> data -> mlet)) X return; X mtmp -> mhp = 0; X break; X case Z_CONF_MON: X if (mtmp == u.ustuck) X return; X mtmp -> mconf = 1; X break; X X } X} X Xdowhatis () { X register fd; X register char *str; X X X pline ("Specify what? "); X flags.topl = 0; X getlin (buf); X str = buf; X while (*str == ' ') X str++; X nomove (); X buf[52] = '\0'; X if (*(str + 1)) X pline ("One character please."); X else if ((fd = open (DATA, 0)) < 0) X pline ("Cannot open data file!"); X else { X lseek (fd, (long) (*str * 51), 0); X if (read (fd, buf, 51) > 0 && *buf != '\\') X pline (buf); X else X pline ("Unknown symbol."); X close (fd); X } X} X Xdoshow () { /* Michiel: Show everything you're wearing */ X nomove (); X show (uarm2); X show (uarm); X show (uwep); X show (uleft); X show (uright); X} X Xshow (otmp) Xregister OBJECT otmp; X{ X if (otmp) X prinv (otmp); X} X Xdosearch () { X register char x, y; X register GOLD_TRAP tgen; X X for (x = u.ux - 1; x < u.ux + 2; x++) X for (y = u.uy - 1; y < u.uy + 2; y++) X if (levl[x][y].typ == SDOOR && !rn2 (7)) { X levl[x][y].typ = DOOR; X atl (x, y, '+'); X nomul (0); X } X else { X for (tgen = ftrap; tgen; tgen = tgen -> ngen) X if (tgen -> gx == x && tgen -> gy == y && X (!rn2 (8) || ((!u.usearch) && X tgen -> gflag & SEEN))) { X nomul (0); X pline ("You find a%s", traps[tgen -> gflag & 037]); X if ((tgen -> gflag & 037) == X PIERC) { X deltrap (tgen); X mkmonat (PM_PIERC, x, y); X return; X } X if ((tgen -> gflag & 037) == X MIMIC) { X deltrap (tgen); X mkmonat (PM_MIMIC, x, y); X return; X } X if (!(tgen -> gflag & SEEN)) { X tgen -> gflag |= SEEN; X atl (x, y, '^'); X } X } X } X} X Xdoset () { X pline ("Give one inventory per line? "); X flush (); X flags.oneline = (getchar () == 'y'); X nomove (); X} X X X X/* X * The whole vault was implemented by Fred and Michiel X * X */ X X Xstruct permonst treasurer = { X "treasurer", '@', 15, 12, -1, 4, 8, 0 X}; X Xvaultinit () { X GOLD_TRAP gtmp; X X if (vaultflag[dlevel]) X return; X vaultflag[dlevel] = 1;; X makemon (&treasurer); X vaultkeeper = fmon; X for (gtmp = fgold; gtmp -> gflag < 10000; gtmp = gtmp -> ngen); X fmon -> mx = gtmp -> gx; X fmon -> my = gtmp -> gy; X if (!u.ublind) X pmon (fmon); X} / echo 'x - hack.mon.c' sed 's/^X//' > hack.mon.c << '/' X/* X * Hack.mon.c X */ X X/* Contains various monster routines */ X X#include "hack.h" X Xextern char WCLEV[], STOPGLOW[]; X Xdist (x, y) Xregister x, y; X{ X x -= u.ux; X y -= u.uy; X return (x * x + y * y); X} X Xr_free (x, y, mtmp) Xregister x, y; Xregister MONSTER mtmp; X{ X if (mtmp -> ale) X return (levl[x][y].typ == POOL); X else X return (levl[x][y].typ > SDOOR && X (x != u.ux || y != u.uy) && levl[x][y].typ < POOL); X /* DOOR,CORR,ROOM */ X} X X X/* Puts m next to u, or anywhere if there isn't room there */ Xmnexto (mtmp) XMONSTER mtmp; X{ X register x, y, z; X struct { X char zx, zy; X } foo[15], *tfoo; X int range; X X tfoo = foo; X range = 1; X do { /* Full kludge action */ X for (y = 0; y < 2; y++) X for (x = u.ux - range; x <= u.ux + range; x++) { X z = range; X if (!y) X z = -z; X if (test (x, z += u.uy)) { X tfoo -> zx = x; X tfoo++ -> zy = z; X if (tfoo == &foo[15]) X goto foofull; X } X } X for (x = 0; x < 2; x++) X for (y = u.uy + 1 - range; y < u.uy + range; X y++) { X z = range; X if (!x) X z = -z; X if (test (z += u.ux, y)) { X tfoo -> zx = z; X tfoo++ -> zy = y; X if (tfoo == &foo[15]) X goto foofull; X } X } X range++; X } while (tfoo == foo); Xfoofull: X tfoo = &foo[rn2 (tfoo - foo)]; X mtmp -> mx = tfoo -> zx; X mtmp -> my = tfoo -> zy; X pmon (mtmp); X if (mtmp -> data -> mlet == 'w') X initworm (mtmp); X} X Xrloc (mtmp) XMONSTER mtmp; X{ X register tx, ty; X register char ch = mtmp -> data -> mlet; X X if (ch == 'w' && mtmp -> mx) X return; /* Do not relocate worms */ X levlsym (mtmp -> mx, mtmp -> my, ch); X if (mtmp -> ale) { X do { X tx = rn1 (77, 2); X ty = rn2 (22); X /* until CORR,DORR,or ROOM; or... */ X } while (levl[tx][ty].typ != POOL || m_at (tx, ty) || X (tx == u.ux && ty == u.uy)); X } X else { X do { X tx = rn1 (77, 2); X ty = rn2 (22); X /* until CORR,DORR,or ROOM; or... */ X } while (levl[tx][ty].typ < DOOR || m_at (tx, ty) || X (tx == u.ux && ty == u.uy) X || levl[tx][ty].typ >= 7); X } X mtmp -> mx = tx; X mtmp -> my = ty; X pmon (mtmp); X if (ch == 'w') X initworm (mtmp); X} X Xtest (x, y) { X if (x <= 0 || x > 78 || y <= 0 || y > 20) X return 0; X if (m_at (x, y) || levl[x][y].typ < DOOR || levl[x][y].typ >= 7) X return 0; X return 1; X} X Xpoisoned (string, pname) Xregister char *string, *pname; X{ X pseebl ("%s was poisoned!", string); X if (u.upres) { X pline ("The poison doesn't seem to affect you."); X return; X } X X switch (rn2 (6)) { X case 0: X u.uhp = 0; X break; X case 1: X case 2: X case 3: X losestr (rn1 (3, 3)); X break; X case 4: X case 5: X losehp (rn1 (10, 6), pname); X return; X } X X if (u.uhp <= 0) X killer = pname; X} X Xsteal (mtmp) XMONSTER mtmp; X{ X register OBJECT otmp, ot1; X register tmp; X X for (otmp = invent, tmp = 0; otmp -> nobj; otmp = otmp -> nobj, tmp++); X X tmp = rn2 (tmp); X otmp = invent; X if (!tmp) X invent = invent -> nobj; X else { X for (; otmp && tmp; tmp--, otmp = otmp -> nobj); X ot1 = otmp -> nobj; X otmp -> nobj = ot1 -> nobj;/* rm obj from invent */ X otmp = ot1; X } X if (otmp == uarm || otmp == uarm2) { X u.uac += otmp -> spe; X if (otmp == uarm) X uarm = uarm2; X uarm2 = 0; X flags.dac = 1; X } X else if (otmp == uwep) X uwep = 0; X else if (otmp == uleft) { X uleft = 0; X doring (otmp, OFF); X } X else if (otmp == uright) { X uright = 0; X doring (otmp, OFF); X } X doname (otmp, buf); X pline ("She stole %s.", buf); X stlobj (mtmp, otmp); X} X Xstlobj (mtmp, otmp) Xregister MONSTER mtmp; Xregister OBJECT otmp; X{ X otmp -> nobj = 0; /* Michiel: dog and two objects? */ X if (mtmp -> mstole) { X otmp -> nobj = mtmp -> mstole -> sobj; X mtmp -> mstole -> sobj = otmp; X return; X } /* Michiel save stolen object */ X else { X mtmp -> mstole = newstole (); X mtmp -> mstole -> sobj = otmp; X mtmp -> mstole -> sgold = 0; X } X} X Xdelmon (mtmp) Xregister MONSTER mtmp; X{ X unstuck (mtmp); /* a3 */ X relmon (mtmp); X if (mtmp == shopkeeper) X shkdead (); X if (mtmp == vaultkeeper) { X mtmp -> data -> mmove = -1; X vaultkeeper = 0; X } X if (mtmp -> wormno) X wormdead (mtmp); X free (mtmp); X} X Xrelmon (mtmp) Xregister MONSTER mtmp; X{ X register MONSTER mtmp2; X X if (mtmp == fmon) X fmon = fmon -> nmon; X else { X for (mtmp2 = fmon; mtmp2 -> nmon != mtmp; mtmp2 = mtmp2 -> nmon); X mtmp2 -> nmon = mtmp -> nmon; X } X} X X/* Release the objects the killed animal has stolen */ Xrelobj (mtmp) Xregister MONSTER mtmp; X{ X register GOLD_TRAP gtmp; X register tmp = 0; X OBJECT otmp, otmp2; X X if (mtmp -> mstole) { /* Michiel drop stolen obj or gold */ X if (mtmp -> mstole -> sgold) X tmp = mtmp -> mstole -> sgold; X else { X otmp = mtmp -> mstole -> sobj; X do { X otmp -> ox = mtmp -> mx; X otmp -> oy = mtmp -> my; X otmp2 = otmp; X otmp = otmp -> nobj; X } while (otmp); X otmp2 -> nobj = fobj; X fobj = mtmp -> mstole -> sobj; X if (mtmp -> data -> mlet != 'd') X seeatl (otmp -> ox, otmp -> oy, otmp -> olet); X } X free (mtmp -> mstole); X mtmp -> mstole = NULL; X } X if (mtmp -> data -> mlet == 'L') { X gtmp = newgen (); X gtmp -> ngen = fgold; X gtmp -> gx = mtmp -> mx; X gtmp -> gy = mtmp -> my; X if (dlevel) X gtmp -> gflag = tmp + d (dlevel, 30); X else X gtmp -> gflag = tmp + d (maxdlevel, 30); X fgold = gtmp; X seeatl (mtmp -> mx, mtmp -> my, '$'); X } X} X X/* a3 */ Xunstuck (mtmp) Xregister MONSTER mtmp; X{ X if (mtmp == u.ustuck) { X if (u.uswallow) { X u.uswallow = 0; X u.uswldtim = 0; X docrt (); X setCon (SETC);/* Try a3 */ X } X u.ustuck = 0; X } X} X Xkilled (mtmp) Xregister MONSTER mtmp; X{ X register tmp; X X unstuck (mtmp); X levlsym (mtmp -> mx, mtmp -> my, mtmp -> data -> mlet); X if (mtmp -> cham) X mtmp -> data = (PM_CHAM); X pseebl ("You destroy %s!", mtmp -> data -> mname); X if (!u.ublind && u.umconf) { X pline (STOPGLOW); X u.umconf = 0; X } X tmp = mtmp -> data -> mhd; X tmp *= tmp; X ++tmp; X if (mtmp -> data -> ac < 3) X tmp += (7 - mtmp -> data -> ac) << 1; X if (index ("AcsSDXaeRTVWU&In:P", mtmp -> data -> mlet)) X tmp += mtmp -> data -> mhd << 1; X if (index ("DeV&P", mtmp -> data -> mlet)) X tmp += 7 * mtmp -> data -> mhd; X if (mtmp -> data -> mhd > 6) X tmp += 50; X if (mtmp -> ale) X tmp += 1000; X relobj (mtmp); X if ((index ("NTV&", mtmp -> data -> mlet) || !rn2 (5)) && !mtmp -> ale X && levl[mtmp -> mx][mtmp -> my].typ > SDOOR) { X /* Mimic in wall? */ X mkobj (0); X fobj -> ox = mtmp -> mx; X fobj -> oy = mtmp -> my; X if (!u.ublind) X atl (mtmp -> mx, mtmp -> my, fobj -> olet); X } X delmon (mtmp); X u.urexp += tmp << 2; X u.uexp += tmp; X flags.dexp = 1; X while (u.uexp >= 10L * pow (u.ulevel - 1)) { X pline (WCLEV, ++u.ulevel); X tmp = rnd (10); X if (tmp < 3) X tmp = rnd (10); X u.uhpmax += tmp; X u.uhp += tmp; X flags.dhp = 1; X flags.dhpmax = 1; X flags.dulev = 1; X } X} X X#define TBLIND 5 X#define NOTEST 6 X X/*VARARGS*/ Xpsee (mode, x, y, str, name, arg)/* Str bevat %s */ Xregister char *str, *name, *arg; X{ X char *a1, *a2; X X a1 = "the %s"; X a2 = "the %s"; X if (mode == TBLIND) { X if (u.ublind) X a1 = "it"; X } X else if (mode != NOTEST && !cansee (x, y)) X switch (mode) { X case IT1: X a1 = "it"; X break; X case THEIT2: X a2 = "it"; X break; X case 0: X return 0; X default: X pline ("Bad(%d) mode in psee", mode); X } X sprintf (buf, str, a1, a2); X if (*buf >= 'a' && *buf <= 'z') X *buf += 'A' - 'a'; X pline (buf, name, arg); X return 1; X} X X/*VARARGS*/ Xp2xthe (str, name, arg) Xregister char *str, *name, *arg; X{ X psee (NOTEST, 0, 0, str, name, arg); X} X Xpseebl (str, name) Xregister char *str, *name; X{ X psee (TBLIND, 0, 0, str, name, NULL); X} X Xrescham () { /* Force all chameleons to become normal */ X register MONSTER mtmp; X X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) X if (mtmp -> cham) { X mtmp -> cham = 0; X if (u.uswallow && u.ustuck == mtmp) { X unstuck (mtmp); X mnexto (mtmp); X } X newcham (mtmp, PM_CHAM); X } X} X X/* Make a chameleon look like a new monster */ Xnewcham (mtmp, mdat) Xregister MONSTER mtmp; Xregister MONSTDATA mdat; X{ X register mhp, hpn, hpd; X X if (mdat == mtmp -> data) X return; /* Still the same monster */ X if (u.uswallow && mdat -> mlet == 'w') X return; X if (mtmp -> wormno) X wormdead (mtmp);/* Throw tail away */ X hpn = mtmp -> mhp; X hpd = mtmp -> data -> mhd << 3; X mtmp -> data = mdat; X mtmp -> invis = 0; X mtmp -> mtame = 0; X mhp = mdat -> mhd << 3; X/* New hp: same fraction of max as before */ X mtmp -> mhp = 2 + (hpn * mhp) / hpd; X hpn = mtmp -> orig_hp; X mtmp -> orig_hp = 2 + (hpn * mhp) / hpd; X if (mdat -> mlet == 'I') { X ++mtmp -> invis; X if (cansee (mtmp -> mx, mtmp -> my)) X prl (mtmp -> mx, mtmp -> my); X } X if (mdat -> mlet == 'w' && getwn (mtmp)) X initworm (mtmp); X if (u.uswallow && mtmp == u.ustuck && X !index (",'P", mdat -> mlet)) { X unstuck (mtmp); X mnexto (mtmp); X } X pmon (mtmp); X} X Xmakemon (ptr) Xregister MONSTDATA ptr; X{ X register MONSTER mtmp; X X if (!ptr) { X do X ptr = &mon[rn2 (dlevel / 3 + 1) % 8][rn2 (7)]; X while (index (genocided, ptr -> mlet)); X } X else { X if (index (genocided, ptr -> mlet)) { X if (!u.ublind) X p2xthe ("%s vanishes!", ptr -> mname); X return 1; X } X } X mtmp = newmonst (ptr -> pxlth); X mtmp -> nmon = fmon; X fmon = mtmp; X mtmp -> mstole = 0; X mtmp -> invis = 0; X mtmp -> cham = 0; X mtmp -> msleep = 0; X mtmp -> mfroz = 0; X mtmp -> mconf = 0; X mtmp -> mflee = 0; X mtmp -> mtame = 0; X mtmp -> mspeed = 0; X mtmp -> mcan = 0; X mtmp -> angry = 0; X mtmp -> mxlth = 0; X mtmp -> ale = 0; X mtmp -> data = ptr; X switch (ptr -> mlet) { X case 'I': X ++mtmp -> invis; X break; X case 'L': X mtmp -> msleep = u.uhcursed; X break; X case ':': X ++mtmp -> cham; X if (!u.ucham) X newcham (mtmp, &mon[rn1 (6, 2)][rn2 (7)]); X break; X case ';': X mtmp -> ale = 1; X break; X } X if (ptr -> mlet != 'w' || !getwn (mtmp)) X mtmp -> wormno = 0; X mtmp -> mhp = rnd (4); X if (ptr -> mhd) X mtmp -> mhp = d (ptr -> mhd, 8); X mtmp -> orig_hp = mtmp -> mhp; X return 0; X} X Xsomegold () { X return ((u.ugold < 100L) ? u.ugold : X (u.ugold > 10000L) ? rnd (10000) : rnd ((int) u.ugold)); X} X Xmkmonat (ptr, x, y) Xregister MONSTDATA ptr; Xregister x, y; X{ X if (makemon (ptr)) X return; X if (x == u.ux && y == u.uy) X mnexto (fmon); X else { X atl (x, y, ptr -> mlet); X fmon -> mx = x; X fmon -> my = y; X } X} / echo 'x - hack.move.c' sed 's/^X//' > hack.move.c << '/' X/* X * Hack.move.c X */ X X#include "hack.h" X Xextern char STOPGLOW[], UMISS[], *setan (); X X Xextern OBJECT addinv (); X Xchar seelx, seehx, seely, seehy;/* Corners of lit room */ X /* l for Low, h for High */ X X#define ZOO 1 X#define GRAVEYARD 2 X#define SWAMP 3 X#define FORT_KNOX 4 X X X/* Contains move commands */ X Xchar sdir[] = "hjklyubn"; Xshort xdir[8] = { X -1, 0, 0, 1, -1, 1, -1, 1 X} , X ydir[8] = { X 0, 1, -1, 0, -1, -1, 1, 1 X}; X Xmovecm (cmd) Xregister char *cmd; X{ X register char *dp; X X if (!(dp = index (sdir, *cmd))) X return 0; X dx = xdir[dp - sdir]; X dy = ydir[dp - sdir]; X return 1; X} X X Xdomove () { X char nx, ny, tmpx, tmpy, let; X register MONSTER mtmp; X register PART * tmpr, *ust; X GOLD_TRAP gold, trap, gtm1; X OBJECT otmp, obj; X X if (u.uswallow) { X nx = u.ux; X ny = u.uy; X goto M; X } X /* n<letter> is used for u.u<letter> + d<letter> */ X if (u.uconfused) { X do { X dx = rn2 (3); X dy = rn2 (3); X dx--; X dy--; X tmpr = &levl[u.ux + dx][u.uy + dy]; X } X while ((!dx && !dy) || tmpr -> typ < DOOR); X } X else X tmpr = &levl[u.ux + dx][u.uy + dy]; X ust = &levl[u.ux][u.uy]; X tmpx = u.ux; X tmpy = u.uy; X nx = u.ux + dx; X ny = u.uy + dy; X if (trap = g_at (nx, ny, ftrap)) { X if (trap -> gflag == MIMIC) { X nomul (0); X pline ("The door is actually a mimic."); X deltrap (trap); X if (makemon (PM_MIMIC)) { X newsym (nx, ny); X return; X } X if (m_at (nx, ny)) X mnexto (fmon); X else { X fmon -> mx = nx; X fmon -> my = ny; X } X if (!u.ustuck) X u.ustuck = fmon; X pmon (fmon); X return; X } X if (trap -> gflag & SEEN) X nomul (0); X } X if (u.ustuck && (nx != u.ustuck -> mx || ny != u.ustuck -> my)) { X pseebl ("You cannot escape from %s!", X u.ustuck -> data -> mname); X nomul (0); X return; X } XM: X if (mtmp = m_at (nx, ny)) { X/* Attack monster */ X char tmp; X register MONSTDATA mdat = mtmp -> data; X X tmp = u.ulevel - 1 + mdat -> ac + abon (); X if (uwep) { X tmp += uwep -> spe; X if (uwep -> otyp == W_TWOH_SWORD) X tmp--; X else if (uwep -> otyp == W_DAGGER) X tmp += 2; X else if (uwep -> otyp == W_SPEAR && index ("XDne", X mdat -> mlet)) X tmp += 2; X } X if (mtmp -> msleep) { X mtmp -> msleep = 0; X tmp += 2; X } X if (mtmp -> mfroz) { X tmp += 4; X if (!rn2 (10)) X mtmp -> mfroz = 0; X } X if (mtmp -> mflee) X tmp += 2; X if (u.utrap) X tmp -= 3; X if (mtmp == shopkeeper) X setangry (); X if (tmp < rnd (20) && !u.uswallow) X pseebl (UMISS, mdat -> mname); X else { X/* We hit the monster; but: it might die! */ X X if (hmon (mtmp, uwep)) { X /* 0-destroy,1-hit */ X if (!u.uswallow && !rn2 (25) && X mtmp -> mhp < mtmp -> orig_hp >> 1) { X/* You might be stucked at this point ! { FRED } */ X if (mtmp == u.ustuck) X unstuck (mtmp); X mtmp -> mflee = 1; X } X pseebl ("You hit %s!", mdat -> mname); X if (u.umconf && !u.uswallow) {/* a3 */ X if (!u.ublind) { X pline (STOPGLOW); X pseebl ("The %s appears confused.", mdat -> mname); X } X mtmp -> mconf = 1; X u.umconf = 0; X } X if (mtmp -> wormno) X cutworm (mtmp, nx, ny, X uwep -> otyp); X switch (mdat -> mlet) { X X case 'a': X if (rn2 (2)) { X pline ("You are splashed by the blob's acid!"); X losehp (rnd (6), mdat -> mname); X } X if (!rn2 (6) && uwep) { X pline ("Your %s corrodes!", X weapons[uwep -> otyp].wepnam); X --uwep -> spe; X } X break; X X case 'E': X if (!u.ublind && rn2 (2)) { X pline ("You are frozen by the floating eye's gaze!"); X nomul (rn1 (20, -20)); X return; X } X break; X } X } X } X nomul (0); X return; X } X X/* Not attacking an animal, so we try to move */ X if (u.utrap) { X pline ((u.upit) ? "You are still in a pit." : X "You are caught in a beartrap."); X if (u.upit || (dx && dy) || !rn2 (5)) X u.utrap--; X return; X } X if ((dx && dy && (tmpr -> typ == DOOR || ust -> typ == DOOR)) || X tmpr -> typ < DOOR || tmpr -> typ == VAULT) { X /* 0, WALL, or SDOOR */ X flags.move = 0; X nomul (0); X return; X } X u.ux = nx; /* u.ux+=dx; u.uy+=dy; */ X u.uy = ny; X nx += dx; X ny += dy; X if (flags.run) X if (tmpr -> typ == DOOR || X (xupstair == u.ux && yupstair == u.uy) || X (xdnstair == u.ux && ydnstair == u.uy)) X nomul (0); X if (tmpr -> typ >= 30 && tmpr -> typ <= 41) { X for (otmp = invent; otmp; otmp = otmp -> nobj) { X if (otmp -> otyp == tmpr -> typ && otmp -> olet == '_') { X pline ("The door opens."); X doname (otmp, buf); X pline ("The %s vanishes.", buf); X useup (otmp); X tmpr -> typ = DOOR; X break; X } X } X if (!otmp) { X if (rn2 (2)) X pline ("The door is locked!"); X else X pline ("You cannot unlock the door!"); X u.ux -= dx; X u.uy -= dy; X return; X } X } X if (ust -> scrsym == '@') { X newsym (tmpx, tmpy); X oldux = tmpx; X olduy = tmpy; X } X if (!u.ublind) { X if (ust -> lit) { X if (tmpr -> lit) { X if (tmpr -> typ == DOOR) X prl1 (nx, ny); X if (ust -> typ == DOOR) X nose1 (tmpx - dx, tmpy - dy); X } X else { X unCoff (UNC, 1); X prl1 (nx, ny); X } X } X else { X if (tmpr -> lit) X setCon (SETC); X else { X prl1 (nx, ny); X if (tmpr -> typ == DOOR) { X if (dy) { X prl (u.ux - 1, u.uy); X prl (u.ux + 1, u.uy); X } X else { X prl (u.ux, u.uy - 1); X prl (u.ux, u.uy + 1); X } X } X } X nose1 (tmpx - dx, tmpy - dy); X } X } X else X newunseen (tmpx, tmpy); X if (!multi) X pru (); X while (gold = g_at (u.ux, u.uy, fgold)) { X if (!gold -> gflag) { X pline ("The chest was a mimic!"); X if (!makemon (PM_MIMIC)) { X mnexto (fmon); X u.ustuck = fmon; X } X nomul (0); X } X else { X if (u.uhcursed) { X pline ("You cannot pick up the gold!"); X break; X } X if (gold -> gflag == 1) X gold -> gflag++;/* a3 */ X pline ("%u gold pieces", gold -> gflag); X u.ugold += gold -> gflag; X flags.dgold = 1; X } X if (gold == fgold) X fgold = fgold -> ngen; X else { X for (gtm1 = fgold; gtm1 -> ngen != gold; X gtm1 = gtm1 -> ngen); X gtm1 -> ngen = gold -> ngen; X } X free (gold); X if (flags.run) X nomul (0); X if (u.uinvis) X newsym (u.ux, u.uy); X } X while (obj = o_at (u.ux, u.uy)) { X for (otmp = invent, let = 0; otmp; otmp = otmp -> nobj) X let += weight (otmp); X let += weight (obj); X if (let > 85) { X pline ("You can't carry anything more."); X if (flags.run) X nomul (0); X break; X } X if (let > 80) X pline ("You have a little trouble lifting"); X if (!(obj -> cursed)) X obj -> cursed = u.uhcursed; X freeobj (obj); X addtobill (obj);/* Sets obj->unpaid if necessary */ X prinv (addinv (obj)); X /* Might merge it with other objects */ X if (u.uinvis) X newsym (u.ux, u.uy); X if (flags.run) X nomul (0); X } X if (trap) { X nomul (0); X if (trap -> gflag & SEEN && !rn2 (5)) X pline ("You escape a%s.", X traps[trap -> gflag & 037]); X else { X trap -> gflag |= SEEN; X switch (((trap -> gflag) & 037)) { X X case SLPTRP: X pline ("A cloud of gas puts you to sleep!"); X nomul (-rnd (25)); X break; X X case BEAR: X u.utrap = rn1 (4, 4); X u.upit = 0; X pline ("A bear trap closes on your foot!"); X break; X X case PIERC: X pline ("A piercer suddenly drops from the ceiling!"); X deltrap (trap); X if (!makemon (PM_PIERC)) { X mnexto (fmon); X hitu (3, d (4, 6), X "falling piercer"); X } X break; X X case ARROW: X pline ("An arrow shoots out at you!"); X hitu (8, rnd (6), "arrow"); X break; X X case TDOOR: X if (!xdnstair) { X pline ("A trap door in the ceiling opens and a rock falls on your head!"); X losehp (d (2, 10), X "falling rock"); X break; X } X pline ("A trap door opens up under you!"); X if (u.ufloat || u.ustuck) { X pline ("For some reason you don't fall in."); X break; X } X more (); X keepdogs (1); X unCoff (COFF, 1); X do { X dosavelev (); X dodown (); X levl[u.ux][u.uy].scrsym = '<'; X } while (!rn2 (4) && xdnstair); X land (); X losedogs (); X setCon (CON); X inshop ();/* a3:zie tele */ X break; X X case DART: X pline ("A little dart shoots out at you!"); X if (hitu (7, rnd (3), "little dart") && X !rn2 (6)) X poisoned ("dart", "poison dart"); X break; X X case TELE: X newsym (u.ux, u.uy); X tele (); X break; X X case PIT: X if (u.ufloat) { X pline ("A pit opens up under you!"); X pline ("You don't fall in!"); X break; X } X pline ("You fall into a pit!"); X u.utrap = rn1 (6, 2); X u.upit = 1; X losehp (rnd (6), "pit"); X break; X X default: X pline ("Bad(%d)trap", trap -> gflag); X impossible (); X } X } X } X if (tmpr -> typ == DOOR && dlevel) { X inshop (); X switch (rooms[inroom (u.ux, u.uy)].rtype) { X case ZOO: X if (!u.uinzoo) { X pline ("Welcome to the Zoo!"); X u.uinzoo++; X } X break; X case GRAVEYARD: X if (!u.uinyard) { X pline ("Welcome to the Graveyard!"); X u.uinyard++; X } X break; X case SWAMP: X if (!u.uinswamp) { X pline ("Welcome to the Swamp!"); X u.uinswamp++; X } X break; X case FORT_KNOX: X if (!u.uinknox) { X pline ("Welcome to Fort Knox!"); X u.uinknox++; X } X break; X default: X break;/* Who knows what more may come */ X } X } X if (tmpr -> typ == CORR) { X if (u.uinshop) X inshop ();/* Outside shop now */ X u.uinzoo = 0; /* You left the Zoo ?? */ X u.uinyard = 0; /* You left the Graveyard ?? */ X u.uinswamp = 0; /* You left the Swamp ?? */ X u.uinknox = 0; /* You left Fort Knox ?? */ X } X if (tmpr -> typ == POOL) X if (!u.ufloat) { X pline ("You fall into a pool!"); X pline ("You can't swim!"); X pline ("You drown..."); X more (); X killer = "Pool of water"; X done (DROWNED); X } X} X X/* Stop running if we see something interesting */ Xlookaround () { X register x, y, corrct = 0; X register MONSTER mtmp; X X if (u.ublind || flags.run < 2) X return; X for (x = u.ux - 1; x <= u.ux + 1; x++) X for (y = u.uy - 1; y <= u.uy + 1; y++) { X if (x == u.ux && y == u.uy) X continue; X/* Note: we cannot call r_free: perhaps a M is hidden in the wall */ X if (!levl[x][y].typ) X continue; X if (mtmp = m_at (x, y)) X if (!mtmp -> mtame || (x == u.ux + dx && X y == u.uy + dy)) { X nomul (0); X return; X } X if (x == u.ux - dx && y == u.uy - dy) X continue; X if (mtmp) X corrct++; X else X switch (levl[x][y].scrsym) { X case '+': X if (x == u.ux || y == u.uy) { X nomul (0); X return; X } X case '0': X multi = 0; X flags.run = 0; X return; X case '.': X case '|': X case '-': X break; X case '#': X corrct++; X break; X default: X nomul (0); X return; X } X } X if (corrct > 1 && flags.run == 2) X nomul (0); X} X Xnomul (nval) Xregister nval; X{ X if (multi < 0) X return; X if (flags.mv) X pru (); X multi = nval; X flags.mv = 0; X flags.run = 0; X} X Xchar * X parse () { X static char inline[80]; X register foo; X X oldux = 0; X olduy = 0; X flags.move = 1; X if (!u.uinvis) X curs (u.ux, u.uy + 2); X else X home (); X flush (); X while ((foo = getchar ()) >= '0' && foo <= '9') X multi += 10 * multi + foo - '0'; X if (multi) { X multi--; X save_cm = inline; X } X inline[0] = foo; X inline[1] = 0; X if (foo == 'f' || foo == 'F') { X inline[1] = getchar (); X inline[2] = 0; X } X if (flags.topl) { X home (); X cl_end (); X flags.topl = 0; X } X return (inline); X} X Xnomove () { X multi = 0; X flags.move = 0; X} / echo 'x - hack.shk.c' sed 's/^X//' > hack.shk.c << '/' X/* X * Hack.shk.c X */ X X#include "hack.h" X X#define BILLSZ 200 X#define ONBILL 1 X#define NOTONBILL 0 X#define GDIST(x, y) ((x - gx)*(x - gx) + (y - gy)*(y - gy) ) X Xstruct { X OBJECT op; Xunsigned useup: 1; Xunsigned bquan: 5; X unsigned price; X} bill[BILLSZ]; X XMONSTER shopkeeper; X Xstruct permonst shk_pm = { X "shopkeeper", '@', 10, 12, 0, 4, 8, 0 X}; X Xlong robbed = 0, total; X X/* X * shoproom = index in rooms; set by inshop() X * shlevel = last level we initialized shopkeeper X */ X Xchar billct = 0, shoproom, shlevel; Xchar *shopnam[] = { X "engagement ring", "walking cane", "antique weapon", X "delicatessen", "second hand book", "liquor", X "used armor", "assorted antiques" X}; X XCOORDINATES shk, shd; X /* Usual position shopkeeper;position shop door */ X X#define SHOP_NAME shopnam[rooms[shoproom].rtype - 8] X Xshkdead () { X shopkeeper = 0; X rooms[shoproom].rtype = 0; X setpaid (); X} X Xsetpaid () { X register tmp; X register OBJECT obj; X X for (obj = invent; obj; obj = obj -> nobj) X obj -> unpaid = 0; X for (tmp = 0; tmp < billct; tmp++) X if (bill[tmp].useup) X ofree (bill[tmp].op); X billct = 0; X} X Xaddupbill () { /* Delivers result in total */ X register ct = billct; X X total = 0; X while (ct--) X total += bill[ct].price; X} X Xinshproom (x, y) Xregister x, y; /* a3 */ X{ X return (inroom (x, y) == shoproom); X} X Xinshop () { X register tmp = inroom (u.ux, u.uy); X X if (tmp < 0 || rooms[tmp].rtype < 8) { X u.uinshop = 0; X if (billct) { X pline ("Somehow you escaped the shop without paying!"); X addupbill (); X pline ("You stole for a total worth of %U zorkmids.", total); X robbed += total; X setpaid (); X } X } X else { X shoproom = tmp; X if (shlevel != dlevel) X shopinit (); X if (!u.uinshop) { X pline ("%s to Dirk's %s shop!", X (shopkeeper -> angry) ? X "You're not that welcome" : "Welcome", X SHOP_NAME); X ++u.uinshop; X } X } X return (u.uinshop); X} X X/* Called by useup and dothrow only */ Xonbill (obj) Xregister OBJECT obj; X{ X register tmp; X X for (tmp = 0; tmp < billct; tmp++) X if (bill[tmp].op == obj) { X bill[tmp].useup = 1; X obj -> unpaid = 0;/* only for doinvbill */ X return (ONBILL); X } X return (NOTONBILL); X} X Xdopay () { X register unsigned tmp; X char buffer[BUFSZ]; X X multi = 0; X if (!inshop ()) { X flags.move = 0; X pline ("You are not in a shop."); X return; X } X X if (!shopkeeper || !inshproom (shopkeeper -> mx, X shopkeeper -> my)) { X pline ("There is nobody here to receive your payment."); X return; X } X if (!billct) { X pline ("You do not owe the shopkeeper anything."); X if (!u.ugold) { X pline ("Moreover, you have no money."); X return; X } X if (robbed) { X pline ("But since the shop has been robbed recently"); X pline ("You %srepay the shopkeeper's expenses.", (u.ugold < robbed) ? X "partially " : ""); X u.ugold -= robbed; X if (u.ugold < 0) X u.ugold = 0; X flags.dgold = 1; X robbed = 0; X return; X } X if (shopkeeper -> angry) { X pline ("But in order to appease the angry shopkeeper,"); X if (u.ugold >= 1000L) { X tmp = 1000; X pline ("You give him 1000 gold pieces."); X } X else { X tmp = (int) u.ugold; X pline ("You give him all your money."); X } X u.ugold -= (long) tmp; X flags.dgold = 1; X if (rn2 (3)) { X pline ("The shopkeeper calms down."); X shopkeeper -> angry = 0; X } X else X pline ("The shopkeeper is as angry as ever."); X } X return; X } X X while (billct) { X billct--; X bill[billct].op -> unpaid = 0; X doname (bill[billct].op, buffer); X tmp = bill[billct].price; X if (shopkeeper -> angry) X tmp += tmp / 3; X if (u.ugold < tmp) { X ++bill[billct].op -> unpaid; X billct++; X pline ("You don't have gold enough to pay %s.", X buffer); X return; X } X u.ugold -= tmp; X flags.dgold = 1; X pline ("You bought %s for %d gold pieces.", buffer, tmp); X if (bill[billct].useup) X ofree (bill[billct].op); X } X pline ("Thank you for shopping in Dirk's %s store!", X SHOP_NAME); X shopkeeper -> angry = 0; X} X Xpaybill () { /* Called after dying (or quitting) with X nonempty bill */ X if (shopkeeper) { X addupbill (); X if (total > u.ugold) { X u.ugold = 0; X if (invent) X pline ("The shopkeeper comes and takes all your possessions."); X } X else { X u.ugold -= total; X pline ("The shopkeeper comes and takes the %D zorkmids you owed him.", X total); X } X } X more (); X} X Xaddtobill (obj) Xregister OBJECT obj; X{ X if (!inshop ()) X return; X if (billct == BILLSZ) { X pline ("You got that for free!"); X return; X } X bill[billct].op = obj; X bill[billct].bquan = obj -> quan; X bill[billct].useup = 0; X bill[billct++].price = getprice (obj); X obj -> unpaid = 1; X} X Xsubfrombill (obj) Xregister OBJECT obj; X{ X register tmp; X register OBJECT otmp; X X if (!inshop ()) X return; X for (tmp = 0; tmp < billct; tmp++) X if (bill[tmp].op == obj) { X obj -> unpaid = 0; X if (bill[tmp].bquan != obj -> quan) { X bill[tmp].op = otmp = newobj (); X *otmp = *obj; X otmp -> quan = (bill[tmp].bquan -= X obj -> quan); X bill[tmp].price *= otmp -> quan; X bill[tmp].price /= (otmp -> quan + X obj -> quan); X bill[tmp].useup = 1; X return; X } X billct--; X bill[tmp] = bill[billct]; X return; X } X/* I dropped something of my own, wanting to sell it */ X if (shopkeeper -> msleep || shopkeeper -> mfroz || X !inshproom (shopkeeper -> mx, shopkeeper -> my) || X robbed || u.ux == shk.x && u.uy == shk.y || X u.ux == shd.x && u.uy == shd.y) X return; X tmp = getprice (obj); X if (shopkeeper -> angry) { X tmp /= 3; X shopkeeper -> angry = 0; X } X else X tmp >>= 1; X if (tmp < 2) X tmp = 2; X u.ugold += tmp; X flags.dgold = 1; X doname (obj, buf); X pline ("You sold %s and got %d gold pieces.", buf, tmp); X} X Xdoinvbill () { X register unsigned tmp, cnt = 0; X X for (tmp = 0; tmp < billct; tmp++) X if (bill[tmp].useup) { X if (!cnt && !flags.oneline) { X getret (); X cls (); X printf ("\n\nUnpaid articles already used up:\n\n"); X } X strcpy (buf, "* - "); X doname (bill[tmp].op, &buf[5]); X for (cnt = 0; buf[cnt]; cnt++); X while (cnt < 50) X buf[cnt++] = ' '; X sprintf (&buf[cnt], " %5d zorkmids", X bill[tmp].price); X if (flags.oneline) X pline (buf); X else X printf ("%s\n", buf); X if (!cnt % 20) X getret (); X } X} X Xgetprice (obj) Xregister OBJECT obj; X{ X register tmp, ac; X X switch (obj -> olet) { X case '"': X tmp = rnd (500); X break; X case '=': X case '/': X tmp = rnd (100); X break; X case '?': X case '!': X tmp = rnd (50); X break; X case '*': X tmp = rnd (6); X break; X case '%': X tmp = rnd (5 + 2000 / realhunger ()); X break; X case '[': X ac = obj -> spe; X tmp = (100 + ac * ac * rnd (10 + ac)) / 10; X break; X case ')': X if (obj -> otyp <= W_AMMUNITION) X tmp = rnd (10); X else if (obj -> otyp == W_LONG_SWORD || obj -> otyp == X W_TWOH_SWORD) X tmp = rnd (150); X else X tmp = rnd (75); X break; X case '_': X default: X tmp = 1000; X } X return (10 * obj -> quan * tmp); X} X Xrealhunger () { /* not completely foolproof (??) */ X register tmp = u.uhunger; X register OBJECT otmp = invent; X X while (otmp) { X if (otmp -> olet == '%' && !otmp -> unpaid) X tmp += foods[otmp -> otyp].nutrition; X otmp = otmp -> nobj; X } X return tmp; X} X Xshopinit () { X register MKROOM * sroom = &rooms[shoproom]; X register i, j, x, y; X X shlevel = dlevel; X shd = doors[sroom -> fdoor]; X shk.x = shd.x; X shk.y = shd.y; X if (shk.x == sroom -> lx - 1) X shk.x++; X else if (shk.x == sroom -> hx + 1) X shk.x--; X else if (shk.y == sroom -> ly - 1) X shk.y++; X else if (shk.y == sroom -> hy + 1) X shk.y--; X else { X sroom -> rtype = 0; X pline ("Where is shopdoor?"); X impossible (); X return; X } X if (shopkeeper) X return; /* We have been on this level before */ X if (makemon (&shk_pm)) X panic (CORE, "Cannot create shopkeeper?"); X shopkeeper = fmon; X shopkeeper -> angry = u.uhcursed; X if (m_at (shk.x, shk.y) || (shk.x == u.ux && shk.y == u.uy)) { X /* (a3)`mnexto(shopkeeper)' is fout gaan */ X prl (shk.x, shk.y); X for (i = -1; i < 2; i++) X for (j = -1; j < 2; j++) X if (levl[x = shk.x + i][y = shk.y + j].typ == X ROOM) X if (!m_at (x, y)) { X fmon -> mx = x; X fmon -> my = y; X pmon (shopkeeper); X return; X } X fmon -> mx = shk.x; X fmon -> my = shk.y; X return; /* bovenop een ander monster */ X } X else { X fmon -> mx = shk.x; X fmon -> my = shk.y; X } X pmon (shopkeeper); X} X Xsetangry () { X if (shopkeeper -> data -> mlet == '@' && !shopkeeper -> angry) { X pline ("The shopkeeper gets angry."); X ++shopkeeper -> angry; X } X} X Xshk_move () { X register MONSTER mtmp; X char gx, gy, omx, omy, cnt, appr, X nix, niy, ddx, ddy, zx, zy, num; X X omx = shopkeeper -> mx; X omy = shopkeeper -> my; X if (!u.uinshop && inshproom (omx, omy) && X levl[omx][omy].typ == ROOM) X return NOMOVE; X if (shopkeeper -> angry && dist (omx, omy) < 3) { X hitu (shk_pm.mhd, d (shk_pm.damn, shk_pm.damd), X shk_pm.mname); X return NOMOVE; X } X appr = 1; X if ((shopkeeper -> angry) && !u.uinvis) { X gx = u.ux; /* Fred */ X gy = u.uy; X } X else if (shk.x == omx && shk.y == omy && !billct && X !shopkeeper -> angry && X (!robbed || (u.ux == shd.x && u.uy == shd.y)) && X dist (omx, omy) < 3) { X appr = 0; X gx = 0; X gy = 0; X } X else { X gx = shk.x; X gy = shk.y; X } X cnt = 0; X if (omx == gx && omy == gy) X return NOMOVE; X if (shopkeeper -> mconf) X appr = 0; X nix = omx; X niy = omy; X for (ddx = -1; ddx <= 1; ddx++) X for (ddy = -1; ddy <= 1; ddy++) { X zx = omx + ddx; X zy = omy + ddy; X num = levl[zx][zy].typ;/* a3 */ X if ((ddx || ddy) && (num == ROOM || !inshproom (omx, omy) X && (num == CORR || num == DOOR)) && X (shopkeeper -> mconf || X ((zx != u.ux || zy != u.uy) && !m_at (zx, zy))) && X (!appr && !rn2 (++cnt) || appr && GDIST (zx, zy) < X GDIST (nix, niy))) { X nix = zx; X niy = zy; X } X } X if (nix != omx || niy != omy) { X if (shopkeeper -> mconf && (mtmp = m_at (nix, niy))) { X if (hitmm (shopkeeper, mtmp) == 1 && rn2 (3) X && hitmm (mtmp, shopkeeper) == DEAD) X return DEAD; X return NOMOVE; X } X shopkeeper -> mx = nix; X shopkeeper -> my = niy; X/* The shopkeeper might have been turned into an X */ X levlsym (omx, omy, shopkeeper -> data -> mlet); X pmon (shopkeeper); X return MOVE; X } X return NOMOVE; X} / echo 'x - mklev.svlev.c' sed 's/^X//' > mklev.svlev.c << '/' X/* X * Mklev.savelev.c X */ X Xsavelev () { X register int fd; X register MONSTER mtmp, mtmp2; X register GOLD_TRAP gtmp, gtmp2; X register OBJECT otmp, otmp2; X int minusone = -1; X X if ((fd = creat (tfile, 0644)) < 0) X panic ("Cannot create %s\n", tfile); X bwrite (fd, levl, sizeof (levl)); X bwrite (fd, nul, sizeof (unsigned)); X bwrite (fd, (char *) & xupstair, 1); X bwrite (fd, (char *) & yupstair, 1); X bwrite (fd, (char *) & xdnstair, 1); X bwrite (fd, (char *) & ydnstair, 1); X for (mtmp = fmon; mtmp; mtmp = mtmp2) { X mtmp2 = mtmp -> nmon; X bwrite (fd, &mtmp -> mxlth, sizeof (int)); X bwrite (fd, mtmp, mtmp -> mxlth + sizeof (struct monst)); X X/* Michiel save stolen objects */ X bwrite (fd, nul, sizeof (struct stole)); X } X bwrite (fd, &minusone, sizeof (int)); X for (gtmp = fgold; gtmp; gtmp = gtmp2) { X gtmp2 = gtmp -> ngen; X bwrite (fd, gtmp, sizeof (struct gen)); X free (gtmp); X } X bwrite (fd, nul, sizeof (struct gen)); X for (gtmp = ftrap; gtmp; gtmp = gtmp2) { X gtmp2 = gtmp -> ngen; X bwrite (fd, gtmp, sizeof (struct gen)); X free (gtmp); X } X bwrite (fd, nul, sizeof (struct gen)); X for (otmp = fobj; otmp; otmp = otmp2) { X otmp2 = otmp -> nobj; X bwrite (fd, otmp, sizeof (struct obj)); X free (otmp); X } X bwrite (fd, nul, sizeof (struct obj)); X bwrite (fd, rooms, sizeof (rooms)); X bwrite (fd, doors, sizeof (doors)); X fgold = TRAP_NULL; X ftrap = TRAP_NULL; X fmon = MON_NULL; X fobj = OBJ_NULL; X} X X/*NOSTRICT*/ Xbwrite (fd, loc, num) Xregister int fd, num; Xregister char *loc; X{ X if (write (fd, loc, num) != num) X panic ("Cannot write %d bytes to file #%d", num, fd); X} / echo 'Part 02 of Hack complete.' exit -- Michiel Huisjes. {seismo|decvax|philabs}!mcvax!vu44!ark!huisjes
huisjes@ark.UUCP (Michiel B. Huisjes) (02/06/85)
#!/bin/sh # # # # This is a shell archive. These archives are packed by the program # packmail(1). If you have the program unshar(1), I suggest you use it. # If you don't remove anything before the cut line and then feed to # sh(1) # # =====CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=== # echo 'Start of Hack, part 03 of 05:' echo 'x - hack.c' sed 's/^X//' > hack.c << '/' X/* X * Hack.c X */ X X#include "hack.h" X Xextern char news0 (), *setan (); X Xextern char seelx, seehx, seely, seehy;/* Corners of lit room */ X /* l for Low, h for High */ X X#define CANSEE 1 X#define CANNOTSEE 0 X#define HITYOU 1 X#define MISSYOU 0 X#define MONALIVE 1 X#define MONDEAD 0 X X Xchar * X lowc (str) Xregister char *str; X{ X if (*str >= 'A' && *str <= 'Z') X *buf = *str + 'a' - 'A'; X else X *buf = *str++; X buf[1] = 0; X return (buf); X} X X/* (a3) mix van setsee() en seeon() */ XsetCon (setc) { /* setc: 1-setsee, 0-seeon (we just went to a X new level) */ X register x, y; X register MONSTER mtmp; X int lx, hx, ly, hy; X X if (u.ublind) { X if (setc) X pru (); X else X docrt (); X return; X } X if (levl[u.ux][u.uy].lit) { X for (seelx = u.ux; levl[seelx - 1][u.uy].lit; seelx--); X for (seehx = u.ux; levl[seehx + 1][u.uy].lit; seehx++); X for (seely = u.uy; levl[u.ux][seely - 1].lit; seely--); X for (seehy = u.uy; levl[u.ux][seehy + 1].lit; seehy++); X lx = seelx; X hx = seehx; X ly = seely; X hy = seehy; X } X else { X seehx = 0; X lx = u.ux - 1; X hx = u.ux + 1; X ly = u.uy - 1; X hy = u.uy + 1; X if (setc) { X seelx = lx; X seehx = hx; X seely = ly; X seehy = hy; X } X } X for (x = lx; x <= hx; x++) X for (y = ly; y <= hy; y++) { X if (setc) X prl (x, y); X else { X if (!levl[u.ux][u.uy].lit && X !levl[x][y].typ) X continue; X levl[x][y].seen = 1; X if (mtmp = m_at (x, y)) X pmon (mtmp); X } X } X if (!setc) { X docrt (); X return; X } X if (!levl[u.ux][u.uy].lit) X seehx = 0; /* Seems necessary elsewhere */ X else { X if (seely == u.uy) X for (x = u.ux - 1; x <= u.ux + 1; x++) X prl (x, seely - 1); X if (seehy == u.uy) X for (x = u.ux - 1; x <= u.ux + 1; x++) X prl (x, seehy + 1); X if (seelx == u.ux) X for (y = u.uy - 1; y <= u.uy + 1; y++) X prl (seelx - 1, y); X if (seehx == u.ux) X for (y = u.uy - 1; y <= u.uy + 1; y++) X prl (seehx - 1, y); X } X} X XunCoff (unc, mode) { X /* X * (a3) mix van unsee() en seeoff() X * unc: 1-unsee, 0-seeoff X * mode: 1-redo @ (misc movement), X * 0-leave them (blindness (Usually)) X */ X X register x, y; X register PART * lev; X int lx, hx, ly, hy; X X if (seehx) { X lx = seelx; X hx = seehx; X ly = seely; X hy = seehy; X } X else { X lx = u.ux - 1; X hx = u.ux + 1; X ly = u.uy - 1; X hy = u.uy + 1; X } X for (x = lx; x <= hx; x++) X for (y = ly; y <= hy; y++) { X lev = &levl[x][y]; X if (lev -> scrsym == '@' && mode) { X if (unc) X newsym (x, y); X else X lev -> scrsym = news0 (x, y); X } X else if (!seehx && lev -> scrsym == '.') { X if (mode) { X if (unc) { X lev -> scrsym = ' '; X lev -> new = 1; X on (x, y); X } X } X else X lev -> seen = 0; X } X } X seehx = 0; X} X Xhitu (mlev, dam, name) Xregister mlev, dam; Xregister char *name; X{ X mlev += (u.uac - 1); X if (multi < 0) X mlev += 4; X if (u.uinvis) X mlev -= 2; X if (mlev < rnd (20)) { X pseebl ("%s misses", name); X return (MISSYOU); X } X pseebl ("%s hits!", name); X if (name == NULL) X impossible (); X losehp (dam, name); X return (HITYOU); X} X Xcansee (x, y) Xchar x, y; X{ X if (u.ublind || u.uswallow) X return (CANNOTSEE); X if (dist (x, y) < 3) X return (CANSEE); X if (levl[x][y].lit && seelx <= x && x <= seehx && seely <= y && X y <= seehy) X return (CANSEE); X return (CANNOTSEE); X} X Xlong X pow (num) Xregister num; /* Returns 2^num */ X{ X return (1 << num); X} X Xland () { /* a3 */ X do { X u.ux = rn2 (80); X u.uy = rn2 (22); X } while (levl[u.ux][u.uy].typ != ROOM || m_at (u.ux, u.uy)); X} X Xtele () { X unCoff (UNC, 0); /* Dat was een 1 (a3) */ X unstuck (u.ustuck); /* a3 */ X u.utrap = 0; X do X land (); X while (o_at (u.ux, u.uy) || g_at (u.ux, u.uy, ftrap) || X g_at (u.ux, u.uy, fgold)); X setCon (SETC); X inshop (); X} X Xchar * X sitoa (a) Xregister int a; X{ X static char buffer[8]; X X sprintf (buffer, "+%d", a); X return ((a < 0) ? buffer + 1 : buffer); X} X Xdoname (obj, buffer) Xregister OBJECT obj; Xregister char *buffer; X{ X switch (obj -> olet) { X X case '"': X strcpy (buffer, "The amulet of Frobozz"); X break; X X case '%': X if (obj -> quan > 1) X sprintf (buffer, "%d %ss", obj -> quan, X foods[obj -> otyp].foodnam); X else X strcpy (buffer, setan (foods[obj -> otyp].foodnam)); X break; X X case ')': X killer = weapons[obj -> otyp].wepnam;/* a3 */ X if (obj -> known) { X if (obj -> quan > 1) X sprintf (buffer, "%d %s %ss", obj -> quan, X sitoa (obj -> spe), killer); X else X sprintf (buffer, "a %s %s", sitoa (obj -> spe), X killer); X } X else { X if (obj -> quan > 1) X sprintf (buffer, "%d %ss", obj -> quan, X killer); X else X strcpy (buffer, setan (killer)); X } X if (obj == uwep) X strcat (buffer, " (weapon in hand)"); X break; X X case '[': X if (obj -> known) X sprintf (buffer, "%s %s", X sitoa (obj -> spe - 10 + armors[obj -> otyp].a_ac), X armors[obj -> otyp].armnam); X else X strcpy (buffer, armors[obj -> otyp].armnam); X if (obj == uarm || obj == uarm2) X strcat (buffer, " (being worn)"); X break; X X case '!': X if (oiden[obj -> otyp] & POTN || potcall[obj -> otyp]) { X if (obj -> quan > 1) X sprintf (buffer, "%d potions ", obj -> quan); X else X strcpy (buffer, "a potion "); X while (*buffer) X buffer++; X if (potcall[obj -> otyp]) X sprintf (buffer, "called %s", X potcall[obj -> otyp]); X else X sprintf (buffer, "of %s", X pottyp[obj -> otyp]); X } X else { X killer = " potion"; X P: X if (obj -> quan > 1) X sprintf (buffer, "%d %s%ss", obj -> quan, X potcol[obj -> otyp], killer); X else X sprintf (buffer, "%s%s", X setan (potcol[obj -> otyp]), X killer); X } X break; X X case '?': X if (obj -> quan > 1) X sprintf (buffer, "%d scrolls ", obj -> quan); X else X strcpy (buffer, "a scroll "); X while (*buffer) X buffer++; X if (oiden[obj -> otyp] & SCRN) X sprintf (buffer, "of %s", scrtyp[obj -> otyp]); X else if (scrcall[obj -> otyp]) X sprintf (buffer, "called %s", scrcall[obj -> otyp]); X else X sprintf (buffer, "labeled %s", scrnam[obj -> otyp]); X break; X X case '/': X if (oiden[obj -> otyp] & WANN) X sprintf (buffer, "a wand of %s", wantyp[obj -> otyp]); X else if (wandcall[obj -> otyp]) X sprintf (buffer, "a wand called %s", X wandcall[obj -> otyp]); X else X sprintf (buffer, "%s wand", X setan (wannam[obj -> otyp])); X if (obj -> known) { X while (*buffer) X buffer++; X sprintf (buffer, " (%d)", obj -> spe); X } X break; X X case '=': X if (oiden[obj -> otyp] & RINN) { X if (obj -> known) X sprintf (buffer, "a %s ring of %s", X sitoa (obj -> spe), X ringtyp[obj -> otyp]); X else X sprintf (buffer, "a ring of %s", X ringtyp[obj -> otyp]); X } X else if (ringcall[obj -> otyp]) X sprintf (buffer, "a ring called %s", X ringcall[obj -> otyp]); X else X sprintf (buffer, "%s ring", X setan (rinnam[obj -> otyp])); X if (obj == uright) X strcat (buffer, " (on right hand)"); X if (obj == uleft) X strcat (buffer, " (on left hand)"); X break; X X case '*': X killer = " gem"; X goto P; X X case '_': X sprintf (buffer, "%s key", X setan (potcol[obj -> otyp - 30])); X break; X X default: X sprintf (buffer, "a%dglorkum %c(0%o)%d", obj -> otyp, X obj -> olet, obj -> olet, obj -> spe); X } X if (obj -> unpaid) X strcat (buffer, " (unpaid)"); X} X Xabon () { X if (u.ustr == 3) X return - 3; X if (u.ustr < 6) X return - 2; X if (u.ustr < 8) X return - 1; X if (u.ustr < 17) X return 0; X if (u.ustr < 69) X return 1; /* up to 18/50 */ X if (u.ustr < 118) X return 2; X return 3; X} X Xdbon () { X if (u.ustr < 6) X return - 1; X if (u.ustr < 16) X return 0; X if (u.ustr < 18) X return 1; X if (u.ustr == 18) X return 2; /* up to 18 */ X if (u.ustr < 94) X return 3; /* up to 18/75 */ X if (u.ustr < 109) X return 4; /* up to 18/90 */ X if (u.ustr < 118) X return 5; /* up to 18/99 */ X return 6; /* 18/00 */ X} X Xlosestr (num) Xregister num; X{ X u.ustr -= num; X while (u.ustr < 3) { X u.ustr++; X u.uhp -= 6; X u.uhpmax -= 6; X flags.dhp = flags.dhpmax = 1; X } X flags.dstr = 1; X} X Xlosehp (n, knam) Xregister n; Xchar *knam; X{ X u.uhp -= n; X flags.dhp = 1; X if (u.uhp <= 0) X killer = knam; X} X Xchar * X setan (str) Xregister char *str; /* a3 */ X{ X static char buffer[BUFSZ]; X X sprintf (buffer, "a%s %s", index ("aeiou", *str) ? "n" : "", str); X return buffer; X} X Xweight (obj) Xregister OBJECT obj; X{ X switch (obj -> olet) { X case '"': X return 2; X case '[': X return 8; X case '%': X if (obj -> otyp)/* Not a food ration */ X case '*': X return obj -> quan; X case '?': X return (obj -> quan * 3); X case '!': X return (obj -> quan << 1); X case ')': X if (obj -> otyp == W_TWOH_SWORD) X return 4; X if (obj -> otyp <= W_AMMUNITION)/* darst arrows etc */ X return (obj -> quan >> 1); X case '/': X return 3; X case '_': X case '=': X return 1; X default: X pline ("Weight: bad(%d) object 0%o.", obj -> otyp, X obj -> olet); X return 0; X } X} X Xchar mlarge[] = "bCDdegIlmnoPSsTUwY',&"; X Xhmon (monst, obj) Xregister MONSTER monst; Xregister OBJECT obj; X{ X register tmp; X X if (!obj || obj == uwep && (obj -> otyp >= W_USE_AMMO || X obj -> otyp <= W_AMMUNITION)) X tmp = rnd (2); X else { X if (index (mlarge, monst -> data -> mlet)) { X tmp = rnd (weapons[obj -> otyp].wldam); X if (obj -> otyp == W_TWOH_SWORD) X tmp += d (2, 6); X else if (obj -> otyp == W_LONG_SWORD) X tmp += rnd (4); X } X else { X tmp = rnd (weapons[obj -> otyp].wsdam); X if (obj -> otyp == W_FLAIL || obj -> otyp == W_MACE) X tmp++; X } X tmp += obj -> spe; X } X tmp += u.udaminc + dbon (); X if (u.uswallow) { X if (monst -> data -> mlet == 'P') X tmp++; X } X else if (tmp <= 0) X tmp = 1; X monst -> mhp -= tmp; X return alive (monst); X} X Xalive (monst) Xregister MONSTER monst; X{ X if (monst -> mhp > 0) X return (MONALIVE); X killed (monst); X return (MONDEAD); X} / echo 'x - hack.dog.c' sed 's/^X//' > hack.dog.c << '/' X/* X * Hack.dog.c X */ X X#include "hack.h" X#include "hack.dog.h" X X#define UNDEF 127 /* Some large number */ X#define EDOG(mp) ( (struct edog *)(&(mp->mextra[0])) ) X Xextern struct permonst li_dog, dog, la_dog; X Xchar SADFEEL[] = "You have a sad feeling for a moment, then it passes"; X Xmakedog () { X if (makemon (&li_dog)) X return; /* Dogs were genocided */ X mnexto (fmon); X initedog (fmon); X} X Xinitedog (mtmp) Xregister MONSTER mtmp; X{ X mtmp -> mtame = 1; X EDOG (mtmp) -> hungrytime = 1000 + moves; X EDOG (mtmp) -> eattime = 0; X EDOG (mtmp) -> droptime = 0; X EDOG (mtmp) -> dropdist = 10000; X EDOG (mtmp) -> apport = 10; X EDOG (mtmp) -> carry = 0; X} X X/* Attach the monsters that went down (or up) together with @ */ X XMONSTER mydogs = 0; X Xlosedogs () { X register MONSTER mtmp; X X while (mtmp = mydogs) { X mydogs = mtmp -> nmon; X mtmp -> nmon = fmon; X fmon = mtmp; X mnexto (mtmp); X } X} X Xkeepdogs (checkdist) Xint checkdist; X{ X register MONSTER mtmp; X register PART * dr; X X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) X if (mtmp -> mtame) { X if (checkdist && dist (mtmp -> mx, mtmp -> my) > 2) { X mtmp -> mtame = 0;/* Dog becomes wild */ X mtmp -> mxlth = 0; X continue; X } X relmon (mtmp); X mtmp -> nmon = mydogs; X mydogs = mtmp; X dr = &levl[mtmp -> mx][mtmp -> my]; X if (dr -> scrsym == mtmp -> data -> mlet) X dr -> scrsym = news0 (mtmp -> mx, mtmp -> my); X /* We destroyed the link, so use recursion */ X keepdogs (checkdist); X return; /* (admittedly somewhat primitive) */ X } X} X X#define GDIST(x, y) ((x - gx)*(x - gx) + (y - gy)*(y - gy) ) X#define DDIST(x, y) ((x - omx)*(x - omx) + (y - omy)*(y - omy) ) X Xdog_move (mtmp, after) Xregister MONSTER mtmp; X{ X register MONSTER mtmp2; X register struct edog *edog = EDOG (mtmp); X int nix, niy, omx, omy, appr, nearer, cnt, udist, zx, zy; X register OBJECT obj; X register GOLD_TRAP trap; X char ddx, ddy, dogroom, uroom, X gx = 0, gy = 0, gtyp;/* Current goal */ X X if (moves <= edog -> eattime) X return NOMOVE; /* Dog is still eating */ X omx = mtmp -> mx; X omy = mtmp -> my; X if (moves > edog -> hungrytime + 500 && !mtmp -> mconf) { X mtmp -> mconf = 1; X mtmp -> orig_hp /= 3; X if (mtmp -> mhp > mtmp -> orig_hp) X mtmp -> mhp = mtmp -> orig_hp; X psee (0, omx, omy, "%s is confused from hunger", X mtmp -> data -> mname); X } X else if (moves > edog -> hungrytime + 750 || mtmp -> mhp <= 0) { X if (!psee (0, omx, omy, "%s dies from hunger", X mtmp -> data -> mname)) X pline (SADFEEL); X levlsym (omx, omy, mtmp -> data -> mlet); X delmon (mtmp); X return DEAD; X } X dogroom = inroom (omx, omy); X uroom = inroom (u.ux, u.uy); X udist = dist (omx, omy); X X/* X * if we are carrying stg then we drop it (perhaps near @ ) X * Note: if apport == 1 then our behaviour is independent of udist X */ X if (edog -> carry) { X if (!rn2 (udist) || !rn2 (edog -> apport)) X if (rn2 (10) < edog -> apport) { X relobj (mtmp); X if (edog -> apport > 1) X edog -> apport--; X edog -> carry = 0; X } X } X else { X if (obj = o_at (omx, omy)) X if (rn2 (20) < edog -> apport + 3) X if (rn2 (udist) || !rn2 (edog -> apport)) { X edog -> carry = 1; X freeobj (obj); X levlsym (omx, omy, obj -> olet); X stlobj (mtmp, obj); X } X } X X/* First we look for food */ X gtyp = UNDEF; /* No goal as yet */ X obj = fobj; X while (obj) { X if (obj -> olet == '%' X && inroom (obj -> ox, obj -> oy) == dogroom X && (gtyp == UNDEF || (gtyp != 1 && obj -> otyp == 1) X || (((gtyp != 1 && obj -> otyp < 5) X || (gtyp == 1 && obj -> otyp == 1)) X && DDIST (obj -> ox, obj -> oy) < DDIST (gx, gy)))) { X gx = obj -> ox; X gy = obj -> oy; X gtyp = obj -> otyp; X } X else if ((gtyp == UNDEF || gtyp == 67) && dogroom >= 0 X && inroom (obj -> ox, obj -> oy) == dogroom X && uroom == dogroom X && !edog -> carry && edog -> apport > rn2 (8)) { X gx = obj -> ox; X gy = obj -> oy; X gtyp = 66 + obj -> cursed;/* Random */ X } X obj = obj -> nobj; X } X if (gtyp == UNDEF X || (gtyp != 1 && gtyp != 66 && moves < edog -> hungrytime)) { X if (dogroom < 0 || dogroom == uroom) { X gx = u.ux; X gy = u.uy; X } X else { X int tmp = rooms[dogroom].fdoor; X X cnt = rooms[dogroom].doorct; X gx = gy = 100;/* Random, far away */ X while (cnt--) { X if (dist (gx, gy) > dist (doors[tmp].x, X doors[tmp].y)) { X gx = doors[tmp].x; X gy = doors[tmp].y; X } X tmp++; X X } X if (gy == 100) X panic (CORE, "No doors nearby?"); X if (gx == omx && gy == omy) { X gx = u.ux; X gy = u.uy; X } X } X appr = 0; X if (udist >= 9) X appr++; X else if (mtmp -> mflee) X appr--; X if (after && udist <= 4 && gx == u.ux && gy == u.uy) X return NOMOVE; X if (udist > 1) { X if (levl[u.ux][u.uy].typ < ROOM || !rn2 (4) || X (edog -> carry && rn2 (edog -> apport))) X appr = 1; X } X/* If you have dog food he'll follow you more closely */ X if (appr == 0) { X obj = invent; X while (obj) { X if (obj -> olet == '%' && obj -> otyp == 1) { X appr = 1; X break; X } X obj = obj -> nobj; X } X } X } X else X appr = 1; X if (mtmp -> mconf) X appr = 0; X nix = omx; X niy = omy; X cnt = 0; X for (ddx = -1; ddx <= 1; ddx++) X for (ddy = -1; ddy <= 1; ddy++) { X if (!ddx && !ddy) X continue; X zx = omx + ddx; X zy = omy + ddy; X if (mtmp2 = m_at (zx, zy)) { X if (mtmp2 -> data -> mhd >= mtmp -> data -> mhd + 2) X continue; X if (mtmp2 -> mtame) X continue; X if (after) X return NOMOVE; X /* Hit only once each move */ X if (hitmm (mtmp, mtmp2) == HIT && rn2 (4) && X hitmm (mtmp2, mtmp) == DEAD) X return DEAD; X return NOMOVE; X } X if (r_free (zx, zy, mtmp) && !(ddx && ddy X && (levl[omx][omy].typ == DOOR X || levl[zx][zy].typ == DOOR))) { X/* M_at(zx,zy) is impossible here */ X X/* Dog avoids unseen traps */ X if ((trap = g_at (zx, zy, ftrap)) X && !(trap -> gflag & SEEN) && rn2 (10)) X continue; X X/* Dog eschewes cursed objects but likes dog food */ X obj = fobj; X while (obj) { X if (obj -> ox != zx || obj -> oy != zy) X goto nextobj; X if (obj -> cursed) X goto newdxy; X if (obj -> olet == '%' && X (obj -> otyp == 1 || (obj -> otyp < 5 && X edog -> hungrytime <= moves))) { X nix = zx; X niy = zy; X edog -> eattime = moves + X foods[obj -> otyp].delay; X edog -> hungrytime = moves + 5 * X foods[obj -> otyp].nutrition; X if (cansee (nix, niy)) { X X char buffer[BUFSZ]; X X doname (obj, buffer); X pline ("The %s ate %s.", mtmp -> data -> mname, buffer); X } X delobj (obj); X/* perhaps this was a reward */ X edog -> apport += 200 / (edog -> dropdist + moves - edog -> droptime); X goto newdogpos; X } X nextobj: X obj = obj -> nobj; X } X X nearer = GDIST (zx, zy) - GDIST (nix, niy); X nearer *= appr; X if (!nearer && !rn2 (++cnt) || nearer < 0 X || nearer > 0 && (omx == nix && omy == X niy && !rn2 (3) || !rn2 (12))) { X nix = zx; X niy = zy; X if (nearer < 0) X cnt = 0; X } X } X newdxy: ; X } Xnewdogpos: X if (nix != omx || niy != omy) { X mtmp -> mx = nix; X mtmp -> my = niy; X } X levlsym (omx, omy, mtmp -> data -> mlet); X pmon (mtmp); X return MOVE; X} X Xhitmm (magr, mdef) Xregister MONSTER magr, mdef; X{ X register MONSTDATA pa = magr -> data; X register MONSTDATA pd = mdef -> data; X int hit; X char tmp, vis; X X if (index ("Eay", magr -> data -> mlet)) X return NOMOVE; X tmp = pd -> ac + pa -> mhd - 1; X if (mdef -> mconf || mdef -> mfroz || mdef -> msleep) { X tmp += 4; X mdef -> msleep = 0; X } X hit = (tmp >= rnd (20)); X vis = (cansee (magr -> mx, magr -> my) && X cansee (mdef -> mx, mdef -> my)); X if (vis) X pline ("The %s %s the %s.", pa -> mname, X (hit) ? "hits" : "misses", pd -> mname); X else X pline ("You hear some noises %s.", X (dist (magr -> mx, magr -> my) > 15) ? "in the distance" X : ""); X if (hit) { X if ((mdef -> mhp -= d (pa -> damn, pa -> damd)) <= 0) { X if (vis) X p2xthe ("%s is killed!", pd -> mname); X else X if (mdef -> mtame) X pline (SADFEEL); X unstuck (mdef);/* a3 */ X relobj (mdef); X levlsym (mdef -> mx, mdef -> my, pd -> mlet); X magr -> orig_hp += rnd (pd -> mhd + 1); X if (magr -> mtame && magr -> orig_hp > X pa -> mhd << 3) { X if (pa == &li_dog) X magr -> data = pa = &dog; X else if (pa == &dog) X magr -> data = pa = &la_dog; X } X delmon (mdef); X hit = DEAD; X } X } X return hit; X} X X/* Return roomnumber or -1 */ Xinroom (x, y) Xchar x, y; X{ X register MKROOM * croom = &rooms[0]; X X if (xdnstair && dlevel) /* a3 */ X while (croom -> hx >= 0) { X if (croom -> hx >= x - 1 && croom -> lx <= x + 1 X && croom -> hy >= y - 1 && croom -> ly <= y + 1) X return (croom - rooms); X croom++; X } X return - 1; /* In corridor or in maze */ X} X X#define NOTTAME 0 X#define TAME 1 X Xtamedog (mtmp, obj) Xregister MONSTER mtmp; Xregister OBJECT obj; X{ X register MONSTER mtmp2; X X if (obj -> otyp >= 5 || mtmp -> mtame) X return NOTTAME; X psee (0, mtmp -> mx, mtmp -> my, "%s devours %s.", X mtmp -> data -> mname, foods[obj -> otyp].foodnam); X delobj (obj); X mtmp2 = newmonst (sizeof (struct edog)); X *mtmp2 = *mtmp; X mtmp2 -> mxlth = sizeof (struct edog); X initedog (mtmp2); X mtmp2 -> nmon = fmon; X fmon = mtmp2; X delmon (mtmp); /* %% */ X return TAME; X} / echo 'x - hack.invinit.c' sed 's/^X//' > hack.invinit.c << '/' X/* X * Hack.invinit.c X */ X X#include "hack.h" X X/* X * struct obj { X * struct obj *nobj; X * char otyp, spe; X * ox, oy, olet, quan, known, cursed, unpaid X * }; X */ X Xstruct obj arrows0 = { X (struct obj *)0, X W_ARROW, 0, 0, 0, ')', 25, 1, 0, 0 /* 25 +0 arrows */ X}; X Xstruct obj bow0 = { X &arrows0, X W_BOW, 1, 0, 0, ')', 1, 1, 0, 0 /* +1 bow */ X}; X Xstruct obj mace0 = { X &bow0, X W_MACE, 1, 0, 0, ')', 1, 1, 0, 0 /* +1 mace */ X}; X Xstruct obj uarm0 = { X &mace0, X A_RING, 4, 0, 0, '[', 1, 1, 0, 0 /* +1 ring mail */ X}; X Xstruct obj food0 = { X &uarm0, X F_FOOD, 0, 0, 0, '%', 2, 1, 0, 0 /* 2 food rations */ X}; X Xstruct obj *yourinvent0 = &food0; / echo 'x - hack.pri.c' sed 's/^X//' > hack.pri.c << '/' X/* X * Hack.pri.c X */ X X#include "hack.h" X Xchar scrlx, scrhx, scrly, scrhy; X Xextern short ospeed; Xchar xcurses[200]; /* Contain's curser stuff */ Xchar *HO, *CL, *CE, *CM, *UP, *BC; Xchar PC; Xextern char *tgetstr (), *getenv (), *tgoto (), *malloc (); Xint putch (); X /* Corners of new area on screen */ Xextern char SAVEFILE[]; X XCOORDINATES ou = { X -1, 0 X}; /* Coordinates of @ on screen (if ou.x>=0) */ X Xextern char *getenv (), *hu_stat[4];/* In eat.c */ X#ifdef NORMAL_IO Xchar obuf[BUFSIZ]; X#endif NORMAL_IO X Xstartup () { X char *bp = malloc (1024); X char *atcurs = xcurses; X X if (tgetent (bp, getenv ("TERM")) <= 0) X panic (NOCORE, "I know about many terminals but alas, not this one\n"); X PC = tgetflag ("pc"); X HO = tgetstr ("ho", &atcurs); X CL = tgetstr ("cl", &atcurs); X CE = tgetstr ("ce", &atcurs); X UP = tgetstr ("up", &atcurs); X if (!(BC = tgetstr ("bc", &atcurs))) { X if (!tgetflag ("bs")) X panic (NOCORE, X "You don't have a backspaced terminal\n"); X BC = (char *) NULL; X } X if (!(CM = tgetstr ("cm", &atcurs))) X panic (NOCORE, "Hack needs cursor addressible terminals\n"); X else if (!UP || !CL || tgetflag ("os")) X panic (NOCORE, "Hack needs `up' and `cl' and no `os'\n"); X free (bp); X#ifdef NORMAL_IO X setbuf (stdout, obuf); X#endif NORMAL_IO X} X X/*VARARGS*/ Xpanic (coredump, str, a1, a2, a3, a4, a5, a6) Xregister char *str; X{ X home (); X#ifdef NORMAL_IO X printf ("ERROR: ", 10); X#else X WRITE ("ERROR: ", 10); X#endif NORMAL_IO X printf (str, a1, a2, a3, a4, a5, a6); X hackmode (OFF); X if (!unlink (SAVEFILE)) X printf ("Savefile removed.\n"); X flush (); X if (coredump) X abort (); X exit (2); X} X Xseeatl (x, y, c) Xregister x, y, c; X{ X if (cansee (x, y)) X atl (x, y, c); X} X Xcls () { X tputs (CL, 0, putch); X curx = 1; X cury = 1; X ou.x = -1; X flags.topl = 0; X} X Xhome () { X if (HO) X tputs (HO, 0, putch); X else X tgoto (CM, 0, 0); X curx = 1; X cury = 1; X} X Xatl (x, y, ch) Xregister x, y; X{ X register PART * crm = &levl[x][y]; X X if (crm -> scrsym == ch) X return; X if (x < 0 || x > 79 || y < 0 || y > 21) X panic (CORE, "atl(%d,%d,%c_%d_)", x, y, ch, ch); X crm -> scrsym = ch; X crm -> new = 1; X on (x, y); X} X Xon (x, y) Xregister x, y; X{ X if (flags.dscr) { X if (x < scrlx) X scrlx = x; X else if (x > scrhx) X scrhx = x; X if (y < scrly) X scrly = y; X else if (y > scrhy) X scrhy = y; X } X else { X flags.dscr = 1; X scrlx = scrhx = x; X scrly = scrhy = y; X } X} X Xat (x, y, ch) Xregister x, y; Xregister char ch; X{ X if (!ch || x < 0 || x > 79 || y < 0 || y > 21) X panic (CORE, "at(%d %d,%d) at %d %d", x, y, ch, X u.ux, u.uy); X y += 2; X curs (x, y); X putchar (ch == '\t' ? ' ' : ch); X curx++; X} X Xprme () { X if (!u.uinvis) X at (u.ux, u.uy, '@'); X} X Xpru () { X prl (u.ux, u.uy); X} X Xprl (x, y) { X register PART * room; X register MONSTER mtmp; X X room = &levl[x][y]; X if (!room -> typ || (room -> typ < DOOR && X levl[u.ux][u.uy].typ == CORR)) X return; X if ((mtmp = m_at (x, y)) && (!mtmp -> invis || u.ucinvis)) X atl (x, y, X (mtmp -> wormno && (mtmp -> mx != x || mtmp -> my != y)) ? X '~' : X mtmp -> data -> mlet); X else X newunseen (x, y); X} X Xnewunseen (x, y) Xregister x, y; X{ X if (!levl[x][y].seen) { X levl[x][y].new = 1; X on (x, y); X } X} X Xchar X news0 (x, y) Xregister x, y; X{ X register OBJECT otmp; X register GOLD_TRAP gtmp; X PART * room; X register char tmp; X X room = &levl[x][y]; X if (!u.ublind && (otmp = o_at (x, y))) X tmp = otmp -> olet; X else if (!u.ublind && g_at (x, y, fgold)) X tmp = '$'; X else if (gtmp = g_at (x, y, ftrap)) { X if (gtmp -> gflag == MIMIC) X tmp = '+'; X else if (gtmp -> gflag & SEEN) X tmp = '^'; X else X tmp = '.'; X } X else if (room -> typ >= 30 && room -> typ <= 41) X tmp = '0'; X else X switch (room -> typ) { X X case SDOOR: X case WALL: X if ((room - 1) -> typ == WALL && (room + 1) -> typ X == WALL) X tmp = '|'; X else X tmp = '-'; X break; X X case DOOR: X tmp = '+'; X break; X X case ROOM: X if (x == xupstair && y == yupstair) X tmp = '<'; X else if (x == xdnstair && y == ydnstair) X tmp = '>'; X else if (room -> lit || cansee (x, y) || u.ublind) X tmp = '.'; X else X tmp = ' '; X break; X X case CORR: X tmp = '#'; X break; X X case POOL: X tmp = '}'; X break; X case VAULT: X tmp = '-'; X break; X X default: X tmp = '`'; X impossible (); X } X return tmp; X} X Xnewsym (x, y) Xregister x, y; X{ X atl (x, y, news0 (x, y)); X} X Xlevlsym (x, y, c) Xregister x, y, c; X{ X if (levl[x][y].scrsym == c) X newsym (x, y); X} X Xnosee (x, y) Xregister x, y; X{ X register PART * room; X X room = &levl[x][y]; X if (room -> scrsym == '.' && !room -> lit && !u.ublind) { X if (room -> new && (x != oldux || y != olduy)) X room -> new = 0; X else { X room -> scrsym = ' '; X room -> new = 1; X on (x, y); X } X } X} X Xprl1 (x, y) Xregister x, y; X{ X register count; X X if (dx) { X if (dy) { X prl (x - (dx << 1), y); X prl (x - dx, y); X prl (x, y); X prl (x, y - dy); X prl (x, y - (dy << 1)); X } X else X for (count = -1; count <= 1; ++count) X prl (x, y + count); X } X else X for (count = -1; count <= 1; ++count) X prl (x + count, y); X} X Xnose1 (x, y) Xregister x, y; X{ X register count; X X if (dx) X if (dy) { X nosee (x, u.uy); X nosee (x, u.uy - dy); X nosee (x, y); X nosee (u.ux - dx, y); X nosee (u.ux, y); X } X else X for (count = -1; count <= 1; ++count) X nosee (x, y + count); X else X for (count = -1; count <= 1; ++count) X nosee (x + count, y); X} X Xdoreprint () { X nomove (); X pline ("\200"); /* Michiel: Code for repeating last message */ X} X X/* VARARGS1 */ Xpline (line, arg1, arg2, arg3, arg4) Xregister char *line; X{ X char pbuf[BUFSZ]; X static char prevbuf[BUFSZ]; X X if (index (line, '\200')) X strcpy (pbuf, prevbuf); X else { X if (!index (line, '%')) X strcpy (pbuf, line); X else X sprintf (pbuf, line, arg1, arg2, arg3, arg4); X if (multi && !strcmp (pbuf, prevbuf)) X return; X strcpy (prevbuf, pbuf); X } X if (flags.dscr) X nscr (); X if (flags.topl) { X curs (savx, 1); X more (); X } X flags.topl = 1; X home (); X cl_end (); X printf (pbuf); X savx = strlen (pbuf); X curx = ++savx; X} X Xprustr () { X if (u.ustr > 18) { X if (u.ustr > 117) X printf ("18/00"); X else X printf ("18/%02d", u.ustr - 18); X } X else X printf ("%-5d", u.ustr); X curx += 5; X} X Xpmon (mtmp) Xregister MONSTER mtmp; X{ X if (!mtmp -> invis || u.ucinvis) X seeatl (mtmp -> mx, mtmp -> my, mtmp -> data -> mlet); X} X Xdocrt () { X cls (); X if (u.uswallow) { X curs (u.ux - 1, u.uy - 1); X printf ("/-\\"); X curs (u.ux - 1, u.uy); X printf ("|@|"); X curs (u.ux - 1, u.uy + 1); X printf ("\\-/"); X curx = u.ux + 2; X } X else X donscrt (0, 0); /* a3 */ X bot (); X} X Xnscr () { X register umv; X X umv = ((ou.x < 0 && !u.uinvis) || (ou.x >= 0 && X (u.uinvis || ou.x != u.ux || ou.y != u.uy))); X if (ou.x >= 0 && umv && !levl[ou.x][ou.y].new) X newsym (ou.x, ou.y); X donscrt (1, umv); X} X Xdonscrt (mode, umv) { /* mode: 0- docrt(), 1- nscr() */ X register PART * room; X register x, y, ly, hy, lx, hx; X X if (u.uinvis) { X if (mode) X ou.x = -1; X } X else { X ou.x = u.ux; X ou.y = u.uy; X if (mode && umv) X atl (ou.x, ou.y, '@'); X else { X (room = &levl[ou.x][ou.y]) -> scrsym = '@'; X if (!mode) X room -> seen = 1; X else X room -> new = 0; X } X } X if (mode) { X ly = scrly; X hy = scrhy; X lx = scrlx; X hx = scrhx; X } X else { X ly = 0; X hy = 21; X lx = 0; X hx = 79; X } X for (y = ly; y <= hy; y++) X for (x = lx; x <= hx; x++) X if ((room = &levl[x][y]) -> new) { X room -> new = 0; X at (x, y, room -> scrsym); X if (room -> scrsym == ' ') { X room -> seen = 0; X room -> scrsym = '.'; X } X else X room -> seen = 1; X } X else if (!mode) X if (room -> seen) X at (x, y, room -> scrsym); X flags.dscr = 0; X scrhx = 0; X scrhy = 0; X scrlx = 80; X scrly = 22; X} X Xbot () { X flags.botl = 0; X flags.dhp = 0; X flags.dhpmax = 0; X flags.dac = 0; X flags.dstr = 0; X flags.dgold = 0; X flags.dhs = 0; X curs (1, 24); X printf ("Level %-4dGold %-7UHp%4d(%d)", X dlevel, u.ugold, u.uhp, u.uhpmax); X if (u.uhpmax < 10) X printf (" "); X else if (u.uhpmax < 100) X putchar (' '); X printf ("Ac %-5dStr ", u.uac); X prustr (); X printf (" Exp%3d/", u.ulevel); X if (u.ulevel < 14) X printf ("%-11U", u.uexp); X else X printf ("%-11s", "MAX++"); X printf ("%s", hu_stat[u.uhs]); X curx = 78; X} X Xcurs (x, y) Xregister x, y; X{ X if (y == cury && x == curx) X return; /* Do nothing, gracefully */ X tputs (tgoto (CM, x - 1, y - 1), 0, putch); X flush (); X cury = y; X curx = x; X} X Xcl_end () { X if (CE) X tputs (CE, 0, putch); X else { X printf ("%80s", ""); X home (); X } X} X Xputch (c) Xchar c; X{ X#ifdef NORMAL_IO X putchar (c); X#else X WRITE (&c, 1); X#endif NORMAL_IO X} / echo 'x - mklev.c' sed 's/^X//' > mklev.c << '/' X/* X * Mklev.c X */ X X#define NORMAL_IO X#include "hack.h" X Xchar *tfile, *tspe, **args, nul[20]; X X#include "mklev.svlev.c" X Xchar mmon[8][8] = { X "BGHJKLr", X "aEhiOyZ", X "AfNpQqv", X "bCcgjkS", X "FoRstWw", X "dlMmTuY", X "IUVXxz:", X "De'n,P&" X}; X X#define MAZX ((rnd(37) << 1) + 1) X#define MAZY ((rnd(8) << 1) + 1) X X#define somex() rn1( croom->hx - croom->lx + 1, croom->lx ) X#define somey() rn1( croom->hy - croom->ly + 1, croom->ly ) X X#define NOT_HERE 0 X XPART levl[80][22]; X XMONSTER fmon; XOBJECT fobj; XGOLD_TRAP fgold, ftrap; X XMKROOM rooms[15], *croom, *troom; X XCOORDINATES doors[DOORMAX]; X Xint doorindex = 0, nroom, comp (); X Xchar dlevel, *geno, goldseen, X xdnstair, xupstair, ydnstair, yupstair, X wizard, nxcor, x, y, X dx, dy, tx, ty; X /* For corridors and other things... */ X X#define RUIN 5 X#define MAZE 6 X Xmain (argc, argv) Xchar *argv[]; X{ X char lowy, lowx; X register unsigned tryct; X X if (argc < 6) X panic ("Too few arguments!!"); X args = argv; X tfile = argv[1]; X tspe = argv[2]; X dlevel = atoi (argv[3]); X if (dlevel >= 30) X dlevel = 30; X geno = argv[4]; X wizard = (*argv[5] == 'w'); X srand (getpid ()); X/* for( lowy=2;lowy<19;lowy++) for( lowx=2;lowx<77;lowx++ ) X levl[lowx][lowy].typ = 0; * / X X/* X * a: normal; X * b: maze; X * n: next level will be maze X */ X if (*tspe == 'b') { X makemaz (); X savelev (); X exit (1); X } X X/* Construct the rooms */ X croom = rooms; X tryct = 0; X while (nroom < 7) { X for (lowy = rn1 (3, 3); lowy < 15; lowy += rn1 (2, 4)) X for (lowx = rn1 (3, 4); lowx < 70; lowx += X rn1 (2, 7)) { X if (++tryct > 10000) { X printf ("tryct overflow\n"); X goto jumpout; X } X if ((lowy += rn1 (5, -2)) < 3) X lowy = 3; X else if (lowy > 16) X lowy = 16; X if (levl[lowx][lowy].typ) X continue; X if (maker (lowx, rn1 (9, lowx + 2), lowy, X rn1 (4, lowy + 2)) && nroom > 13) X goto jumpout; X } X } Xjumpout: X croom -> hx = -1; X X/* For each room: put things inside */ X for (croom = rooms; croom -> hx > 0; croom++) { X X/* Put a sleeping monster inside */ X if (!rn2 (3)) X makemon (1, somex (), somey ()); X X/* Put traps and mimics inside */ X goldseen = 0; X while (!rn2 (8 - (dlevel / 6))) X mktrap (0, 0); X if (!goldseen && !rn2 (3)) X mkgold (0, somex (), somey ()); X tryct = 0; X if (!rn2 (3)) X do { X mkobj (0); X levl[fobj -> ox = somex ()][fobj -> oy = somey ()].scrsym = fobj -> olet; X if (tryct++ > 100) { X printf ("tryct overflow4\n"); X break; X } X } while (!rn2 (5)); X } X tryct = 0; X do { X if (++tryct > 1000) X panic ("Cannot make dnstairs\n"); X croom = &rooms[rn2 (nroom)]; X xdnstair = somex (); X ydnstair = somey (); X } while ((*tspe == 'n' && X (xdnstair % 2 == 0 || ydnstair % 2 == 0)) || X g_at (xdnstair, ydnstair, ftrap)); X levl[xdnstair][ydnstair].scrsym = '>'; X troom = croom; X do { X if (++tryct > 2000) X panic ("Cannot make upstairs\n"); X croom = &rooms[rn2 (nroom)]; X xupstair = somex (); X yupstair = somey (); X } while (croom == troom || m_at (xupstair, yupstair) || X o_at (xupstair, yupstair) || X g_at (xupstair, yupstair, ftrap)); X levl[xupstair][yupstair].scrsym = '<'; X qsort (rooms, nroom, sizeof (MKROOM), comp); X croom = rooms; X troom = croom + 1; X nxcor = 0; X mkpos (); X do X makecor (x + dx, y + dy); X while (croom -> hx > 0 && troom -> hx > 0); X if ((dlevel < 10 && rn2 (2)) || (dlevel > 9 && !rn2 (3)) || X wizard) X mkshop (); X if (dlevel > 7 && !rn2 (6)) X mkzoo (); X else if (dlevel > 11 && !rn2 (6) || wizard) X mkyard (); X else if ((dlevel > 18 && !rn2 (6))) X mkswamp (); X else if ((dlevel > 8 && !rn2 (8)) || wizard) X mk_knox (); X savelev (); X} X Xcomp (xcoord, ycoord) Xregister MKROOM * xcoord, *ycoord; X{ X if (xcoord -> lx < ycoord -> lx) X return - 1; X return (xcoord -> lx > ycoord -> lx); X} X Xmkpos () { X if (troom -> hx < 0 || croom -> hx < 0) X return; X if (troom -> lx > croom -> hx) { X x = croom -> hx + 1; X dx = 1; X tx = troom -> lx - 1; X } X else if (troom -> hy < croom -> ly) { X y = croom -> ly - 1; X dy = -1; X dx = 0; X ty = troom -> hy + 1; X } X else if (troom -> hx < croom -> lx) { X x = croom -> lx - 1; X dx = -1; X tx = troom -> hx + 1; X } X else { X y = croom -> hy + 1; X dy = 1; X dx = 0; X ty = troom -> ly - 1; X } X if (dx) { X dy = 0; X y = croom -> ly + rn2 (croom -> hy - croom -> ly + 1); X ty = troom -> ly + rn2 (troom -> hy - troom -> ly + 1); X } X else { X x = croom -> lx + rn2 (croom -> hx - croom -> lx + 1); X tx = troom -> lx + rn2 (troom -> hx - troom -> lx + 1); X } X if (levl[x + dx][y + dy].typ) { X if (nxcor) X newloc (); X else { X dodoor (x, y, croom); X x += dx; X y += dy; X } X return; X } X dodoor (x, y, croom); X} X Xdodoor (doorx, doory, aroom) Xregister int doorx, doory; Xregister MKROOM * aroom; X{ X register MKROOM * broom; X register int tmp; X X if ((tmp = levl[doorx - 1][doory].typ) == DOOR || tmp == SDOOR) X return; X if ((tmp = levl[doorx + 1][doory].typ) == DOOR || tmp == SDOOR) X return; X if ((tmp = levl[doorx][doory - 1].typ) == DOOR || tmp == SDOOR) X return; X if ((tmp = levl[doorx][doory + 1].typ) == DOOR || tmp == SDOOR) X return; X if (levl[doorx][doory].typ != WALL || doorindex >= DOORMAX) X return; X if (!rn2 (8)) X levl[doorx][doory].typ = SDOOR; X else { X levl[doorx][doory].scrsym = '+'; X levl[doorx][doory].typ = DOOR; X } X aroom -> doorct++; X broom = aroom + 1; X if (broom -> hx < 0) X tmp = doorindex; X else X for (tmp = doorindex; tmp > broom -> fdoor; tmp--) { X doors[tmp].x = doors[tmp - 1].x; X doors[tmp].y = doors[tmp - 1].y; X } X doorindex++; X doors[tmp].x = doorx; X doors[tmp].y = doory; X for (; broom -> hx >= 0; broom++) X broom -> fdoor++; X} X Xnewloc () { X register int tryct = 0; X X ++croom; X ++troom; X if (nxcor || croom -> hx < 0 || troom -> hx < 0) { X if (nxcor++ > rn1 (nroom, 4)) { X croom = &rooms[nroom]; X return; X } X do { X if (++tryct > 100) { X printf ("tryct overflow5\n"); X croom = &rooms[nroom]; X return; X } X croom = &rooms[rn2 (nroom)]; X troom = &rooms[rn2 (nroom)]; X } X while (croom == troom || (troom == croom + 1 && X !rn2 (3))); X } X mkpos (); X} X Xmove (xdir, ydir, dir) Xregister int *xdir, *ydir, dir; X{ X switch (dir) { X case 0: X --(*xdir); X break; X case 1: X (*ydir)++; X break; X case 2: X (*xdir)++; X break; X case 3: X --(*ydir); X break; X } X} X Xokay (xx, yy, dir) Xint xx, yy; Xregister int dir; X{ X move (&xx, &yy, dir); X move (&xx, &yy, dir); X if (xx < 3 || yy < 3 || xx > 17 || yy > 75 || levl[yy][xx].typ != 0) X return 0; X return 1; X} X Xmaker (lowx, hix, lowy, hiy) Xchar lowx, hix, lowy, hiy; X{ X register PART * ltmp, *lmax; X register int tmpx; X X if (hix > 75) X hix = 75; X if (hiy > 18) X hiy = 18; X for (tmpx = lowx - 4; tmpx < hix + 5; tmpx++) X for (ltmp = &levl[tmpx][lowy - 3], X lmax = &levl[tmpx][hiy + 4]; X ltmp != lmax; ltmp++) X if (ltmp -> typ) X return 0; X if (10 > rnd (dlevel)) { X for (tmpx = lowx - 1; tmpx < hix + 2; tmpx++) X for (ltmp = &levl[tmpx][lowy - 1], X lmax = &levl[tmpx][hiy + 2]; X ltmp != lmax; ltmp++) X ltmp -> lit = 1; X } X croom -> lx = lowx; X croom -> hx = hix; X croom -> ly = lowy; X croom -> hy = hiy; X croom -> rtype = 0; X croom -> doorct = 0; X croom -> fdoor = 0; X croom++; X for (tmpx = lowx - 1; tmpx <= hix + 1; tmpx++) { X ltmp = &levl[tmpx][lowy - 1]; X lmax = &levl[tmpx][hiy + 1]; X ltmp -> scrsym = '-'; X ltmp -> typ = WALL; X while (++ltmp != lmax) { X if (tmpx >= lowx && tmpx <= hix) { X ltmp -> scrsym = '.'; X ltmp -> typ = ROOM; X } X else { X ltmp -> scrsym = '|'; X ltmp -> typ = WALL; X } X } X ltmp -> scrsym = '-'; X ltmp -> typ = WALL; X } X /* X ------- X |.....| X |.....| (This sort of room is made) (a3) X |.....| X ------- X */ X ++nroom; X return 1; X} X Xmakecor (nx, ny) Xregister int nx, ny; X{ X register PART * crm; X register int dix, diy; X X if (nxcor && !rn2 (35)) { X newloc (); X return; X } X dix = abs (nx - tx); X diy = abs (ny - ty); X if (nx == 79 || !nx || !ny || ny == 21) { X if (nxcor) { X newloc (); X return; X } X printf ("something went wrong. we try again...\n"); X execl ("./mklev", args[0], tfile, tspe, args[3], X args[4], 0); X panic ("cannot execute ./mklev\n"); X } X if (dy && dix > diy) { X dy = 0; X dx = (nx > tx) ? -1 : 1; X } X else if (dx && diy > dix) { X dx = 0; X dy = (ny > ty) ? -1 : 1; X } X crm = &levl[nx][ny]; X if (!crm -> typ) { X crm -> typ = CORR; X crm -> scrsym = '#'; X x = nx; X y = ny; X return; X } X if (crm -> typ == CORR) { X x = nx; X y = ny; X return; X } X if (nx == tx && ny == ty) { X dodoor (nx, ny, troom); X newloc (); X return; X } X if (x + dx != nx || y + dy != ny) X return; X if (dx) { X dy = 1; X if (ty < ny || levl[nx + dx][ny - 1].typ != ROOM) X dy = -1; X dx = 0; X } X else { X dx = 1; X if (tx < nx || levl[nx - 1][ny + dy].typ != ROOM) X dx = -1; X dy = 0; X } X} X XMONSTER m_at (monx, mony) Xregister int monx, mony; X{ X register MONSTER mtmp; X X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) X if (mtmp -> mx == monx && mtmp -> my == mony) X return (mtmp); X return (NOT_HERE); X} X XOBJECT o_at (objx, objy) Xregister int objx, objy; X{ X register OBJECT obj; X X for (obj = fobj; obj; obj = obj -> nobj) X if (obj -> ox == objx && obj -> oy == objy) X return (obj); X return (NOT_HERE); X} X XGOLD_TRAP g_at (gtx, gty, ptr) Xregister int gtx, gty; Xregister GOLD_TRAP ptr; X{ X while (ptr) { X if (ptr -> gx == gtx && ptr -> gy == gty) X return (ptr); X ptr = ptr -> ngen; X } X return NOT_HERE; X} / echo 'x - show.c' sed 's/^X//' > show.c << '/' X/* X * Showlevel.c X */ X X#define NORMAL_IO X#define SHOW X#include "hack.h" X XPART levl[80][22]; X Xchar mmon[8][8] = { X "BGHJKLr", X "aEhiOyZ", X "AfNpQqv", X "bCcgjkS", X "FoRstWw", X "dlMmTuY", X "IUVXxz:", X "De'n,P&" X}; X Xchar stairs[4], mbuf[1000], obuf[BUFSIZ]; X Xunsigned omoves; Xextern char *setan (); X Xmain (argc, argv) Xint argc; Xchar **argv; X{ X register fd; X register MONSTER mtmp = (MONSTER) mbuf; X char buffer[100]; X struct stole stmp; X struct obj otmp; X char buf[BUFSZ]; X int xl; X X setbuf (stdout, obuf); X if (!strcmp (argv[1], "-r")) { X showrecord (); X exit (0); X } X if (!strcmp (argv[1], "-d")) { X delrecord (); X exit (0); X } X while (--argc) { X printf ("Next file is %s\n", argv[argc]); X if ((fd = open (argv[argc], 0)) < 0) { X printf ("Cannot open %s\n", argv[argc]); X getret (); X continue; X } X if (read (fd, levl, sizeof levl) != sizeof levl) { X printf ("Error reading level\n"); X getret (); X continue; X } X show (); X mread (fd, &omoves, sizeof (unsigned)); X mread (fd, stairs, 4); X mread (fd, &xl, sizeof (int)); X printf ("Show Monsters? (%sSpecified) ", omoves ? "Not " : ""); X fflush (stdout); X gets (buffer); X if (strcmp (buffer, "y")) X continue; X while (xl != -1) { X mread (fd, mtmp, xl + sizeof (struct monst)); X mread (fd, &stmp, sizeof (struct stole)); X if (!omoves) { X if (mtmp -> mhp == 10 && mtmp -> orig_hp == 10) X printf ("\' \'"); X else if (mtmp -> mhp == 9 && mtmp -> orig_hp == 9) X printf ("Ale"); X else X printf ("%c", X mmon[mtmp -> mhp][mtmp -> orig_hp]); X printf (" at [%d,%d]", mtmp -> mx, mtmp -> my); X } X else { X printf ("monster at [%d,%d]", mtmp -> mx, mtmp -> my); X if (stmp.sgold || stmp.sobj) { X printf (" stole "); X if (stmp.sgold) X printf ("%u goldpieces", stmp.sgold); X for (;;) { X mread (fd, &otmp, X sizeof (struct obj)); X if (!otmp.olet) X break; X doname (otmp.olet, buf); X printf (" %s", buf); X } X } X } X if (mtmp -> msleep) X printf (" SLEEP"); X if (mtmp -> invis) X printf (" INVIS"); X if (mtmp -> cham) X printf (" CHAM"); X if (mtmp -> mspeed) X printf (" MSPEED"); X if (mtmp -> mconf) X printf (" MCONF"); X if (mtmp -> mflee) X printf (" MFLEE"); X if (mtmp -> mcan) X printf (" MCAN"); X if (mtmp -> mtame) X printf (" TAME"); X if (mtmp -> angry) X printf (" MANGRY"); X if (mtmp -> wormno) X printf (" WORM[%d]", mtmp -> wormno); X if (mtmp -> mxlth) X printf (" +%d extra", mtmp -> mxlth); X if (mtmp -> mfroz) X printf (" FROZ"); X putchar ('\n'); X mread (fd, &xl, sizeof (int)); X } X getret (); X } X} X Xmread (fd, buf, n) { X register nn; X X if ((nn = read (fd, buf, n)) != n) { X printf ("error: read %d instead of %d bytes\n", nn, n); X exit (2); X } X} X Xshow () { X register i, j; X X for (j = 0; j < 22; j++) X for (i = 0; i < 80; i++) X pch (levl[i][j].scrsym); X printf ("*** "); X} X Xpch (ch) Xchar ch; X{ X putchar (ch ? ch : '_'); X} X Xextern char *malloc (); X Xchar * X alloc (num) Xregister num; X{ X register char *val; X X if (!(val = malloc (num))) X error ("Cannot get %d bytes", num); X return val; X} X Xerror (s) { X printf (s); X putchar ('\n'); X fflush (stdout); X exit (1); X} X Xextern char *itoa (); X X#define NAMESIZE 8 X#define DEATHSIZE 40 X Xstruct recitem { X long points; X int level, maxlvl, hp, maxhp; X char str[NAMESIZE + 1], death[DEATHSIZE + 1]; X} record; X Xshowrecord () { X register killed; X register place = 0; X register rfile; X X if ((rfile = open (RECORD, 0)) < 0) X error ("Cannot open %s", RECORD); X printf ("Number Points Name\n"); X while (read (rfile, &record, sizeof (struct recitem)) > 0) { X printf ("%2d %6D %8s ", ++place, record.points, X record.str); X killed = 0; X if (*record.death == 'e') X printf ("escaped the dungeon [max level %d]", X record.maxlvl); X else { X switch (record.death[1]) { X case 'u': X printf ("quit"); X break; X case 'h': X printf ("choked in his/her food"); X break; X case 't': X printf ("starved"); X break; X case 'r': X printf ("drowned"); X break; X default: X printf ("was killed"); X killed++; X } X printf (" on%s level %d", killed ? "" : X " dungeon", record.level); X if (record.maxlvl != record.level) X printf (" [%d]", record.maxlvl); X } X if (killed) X printf (" by %s", record.death); X putchar ('.'); X if (record.maxhp) X printf (" Hp: %s [%d]", (record.hp > 0) ? X itoa (record.hp) : "-", record.maxhp); X putchar ('\n'); X } X close (rfile); X} X Xint deleted[45]; X Xdelrecord () { X register int fd, fd2; X int count = 0; X X printf ("Delete (Terminate with a zero): "); X fflush (stdout); X fd = open (RECORD, 0); X fd2 = creat (".Temp", 0777); X if (fd < 0 || fd2 < 0) { X printf ("Cannot open files!\n"); X exit (2); X } X do { X scanf ("%d", &count); X ++deleted[count]; X } while (count); X fprintf (stderr, "Deleted nr"); X count = 1; X while (read (fd, &record, sizeof (struct recitem)) > 0) { X if (!deleted[count]) X write (fd2, &record, sizeof (struct recitem)); X else X fprintf (stderr, " %d", count); X ++count; X } X putc ('\n', stderr); X close (fd); X close (fd2); X execl ("/bin/mv", "mv", ".Temp", RECORD, NULL); X} X Xchar * X itoa (a) Xregister int a; X{ X static char buf[8]; X X sprintf (buf, "%d", a); X return (buf); X} X Xdoname (let, buf) Xregister char let; Xregister char *buf; X{ X switch (let) { X X case '"': X strcpy (buf, "The amulet of Frobozz"); X break; X X case '%': X strcpy (buf, "some food"); X break; X X case ')': X strcpy (buf, "a weapon"); X break; X X case '[': X strcpy (buf, "armor"); X break; X X case '!': X strcpy (buf, "a potion"); X break; X X case '?': X strcpy (buf, "a scroll"); X break; X X case '/': X strcpy (buf, "a wand"); X break; X X case '=': X strcpy (buf, "a ring"); X break; X X case '*': X strcpy (buf, "a gem"); X break; X X default: X sprintf (buf, "a glorkum %c(0%o)", let, let); X } X} X Xgetret () { X printf ("AHit j<return>k to continue"); X fflush (stdout); X while (getchar () != '\n'); X} / echo 'Part 03 of Hack complete.' exit -- Michiel Huisjes. {seismo|decvax|philabs}!mcvax!vu44!ark!huisjes
huisjes@ark.UUCP (Michiel B. Huisjes) (02/06/85)
#!/bin/sh # # # # This is a shell archive. These archives are packed by the program # packmail(1). If you have the program unshar(1), I suggest you use it. # If you don't remove anything before the cut line and then feed to # sh(1) # # =====CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=== # echo 'Start of Hack, part 04 of 05:' echo 'x - data' sed 's/^X//' > data << '/' X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X! a potion X" The amulet of Frobozz X# a corridor X$ a pile, pot or chest of gold X% a piece of food X& a demon X' a lurker above X\ X) a weapon X* a gem X+ a door X, a trapper X- a wall X. the floor of a room X/ a wand X\ X\ X\ X\ X\ X\ X\ X\ X\ X\ X: a chameleon X; a giant ale X< the staircase to the previous level X= a ring X> the staircase to the next level X? a scroll X@ a human (or you) XA a giant ant XB a giant bat XC a centaur XD a dragon XE a floating eye XF a freezing sphere XG a gnome XH a hobgoblin XI an invisible stalker XJ a jackal XK a kobold XL a leprechaun XM a mimic XN a nymph XO an orc XP a purple worm XQ a quasit XR a rust monster XS a snake XT a troll XU an umber hulk XV a vampire XW a wraith XX a xorn XY a yeti XZ a zombie X[ a suit of armor X\ X\ X^ a trap X\ X\ Xa an acid blob Xb a giant beetle Xc a cockatrice Xd a dog Xe an ettin Xf a fog cloud Xg a gelatinous cube Xh a homunculus Xi an imp Xj a jaguar Xk a killer bee Xl a leocrotta Xm a minouter Xn a neo-otyugh Xo an owlbear Xp a piercer Xq a quivering blob Xr a giant rat Xs a giant scorpion Xt a teleporter Xu a ugod Xv a violet fungi Xw a long worm Xx a xerp Xy a yellow light Xz a zelomp X\ X| a wall X} a water filled area X~ a wormsegment X\ / echo 'x - hack.do.misc.c' sed 's/^X//' > hack.do.misc.c << '/' X/* X * Hack.do.misc.c X */ X X/* Routines to do various user commands */ X X#include <signal.h> X#include "hack.h" X#include "hack.do.vars.h" X /* (MT) has 'do' structures and lists */ X Xextern char *getenv (), UMISS[], WELDED[]; X X#define MAXLEVEL 40 X XOBJECT loseone (); X Xint done1 (); X Xchar upxstairs[MAXLEVEL], upystairs[MAXLEVEL]; X Xrhack (cmd) Xregister char *cmd; X{ X register FUNCTIONS * tlist = list; X X if (!cmd) { X pline ("Rhack: 0"); X impossible (); X return; X } X if (!*cmd || *cmd == -1) X return; /* Probably interrupt? */ X if (movecm (cmd)) { X if (multi) X flags.mv = 1; X domove (); X return; X } X if (movecm (lowc (cmd))) { X flags.run = 1; X multi = 80; X flags.mv = 1; X domove (); X return; X } X if (*cmd == 'f' && movecm (cmd + 1)) { X flags.run = 2; X multi = 80; X flags.mv = 1; X domove (); X return; X } X if (*cmd == 'F' && movecm (lowc (cmd + 1))) { X flags.run = 3; X multi = 80; X flags.mv = 1; X domove (); X return; X } X while (tlist -> f_char) { X if (*cmd == tlist -> f_char) { X (*(tlist -> f_funct)) (); X return; X } X tlist++; X } X pline ("Unknown command '%s'", cmd); X nomove (); X} X Xdoredraw () { X docrt (); X nomove (); X} X X/* X * VARIABELE ARGUMENTS, but if not given the last argument will always X * be a NULL. (Michiel) X */ X/*VARARGS*/ Xhackexec (num, file, arg1, arg2, arg3, arg4, arg5, arg6) Xregister int num; Xregister char *file, *arg1; Xchar *arg2, *arg3, *arg4, *arg5, *arg6; X{ X nomove (); X switch (fork ()) { X case -1: X pline ("Fork failed. Will try again."); X hackexec (num, file, arg1, arg2, arg3, arg4, X arg5, arg6); X break; X case 0: X if (num) { X signal (SIGINT, SIG_DFL); X setuid (getuid ()); X hackmode (OFF); X cls (); X flush (); X if (num == 2) X chdir (getenv ("HOME")); X } X else X signal (SIGINT, SIG_IGN); X execl (file, file, arg1, arg2, arg3, arg4, arg5, arg6); X panic (NOCORE, "%s: cannot execute.", file); X break; X default: X signal (SIGINT, SIG_IGN); X signal (SIGQUIT, SIG_IGN); X wait (0); X if (num) { X hackmode (ON); X docrt (); X } X signal (SIGINT, done1); X signal (SIGQUIT, SIG_DFL); X break; X } X} X Xdohelp () { X hackexec (1, MORE, HELP, NULL); X} X Xdosh () { X register char *str; X X if (str = getenv ("SHELL")) X hackexec (2, str, NULL); X else X hackexec (2, "/bin/sh", "-i", NULL); X} X Xdowield () { X register OBJECT wep; X X multi = 0; X if (!(wep = getobj (")", "wield"))) X flags.move = 0; X else if (uwep && uwep -> cursed) X pline (WELDED, weapons[uwep -> otyp].wepnam); X else { X uwep = wep; X if (uwep -> cursed) X pline ("The %s welds itself to your hand!", X weapons[uwep -> otyp].wepnam); X else X prinv (uwep); X } X} X Xddodown () { X dostairs ("down"); X} X Xddoup () { X dostairs ("up"); X} X Xdostairs (dir) Xregister char *dir; X{ X if (u.ustuck || X (*dir == 'd' && (u.ux != xdnstair || u.uy != ydnstair)) || X (*dir == 'u' && (u.ux != xupstair || u.uy != yupstair))) { X pline ("You can't go %s here", dir); X nomove (); X return; X } X keepdogs (1); X unCoff (COFF, 1); X dosavelev (); X if (*dir == 'd') X dodown (); X else X doup (); X losedogs (); X if (u.ucham) X rescham (); X setCon (CON); X if (u.uhcursed) X docurse (); X} X Xdosavelev () { X register fd; X X glo (dlevel); X fd = creat (lock, 0644); X savelev (fd); X close (fd); X} X Xextern int uid; X Xchecklev (dir) /* Michiel: Geen geknoei */ Xregister char *dir; X{ X if ((upxstairs[dlevel] != xupstair || X upystairs[dlevel] != yupstair) && !wizard) { X clearlocks (); X panic (NOCORE, "Way %s has been changed...", dir); X } X} X Xdodown () { X register fd; X X glo (++dlevel); X if ((fd = open (lock, 0)) < 0) X mklev (); X else { X if (maxdlevel < dlevel) X mklev ();/* Bad file */ X else X getlev (fd); X close (fd); X checklev ("down"); X } X if (maxdlevel < dlevel) X maxdlevel = dlevel;/* Trapdoor/stairs */ X u.ux = xupstair; X u.uy = yupstair; X inshop (); X} X Xdoup () { X register fd; X X if (dlevel == 1) X done (ESCAPED); X glo (--dlevel); X if ((fd = open (lock, 0)) < 0) X panic (CORE, "Cannot open %s\n", lock); X getlev (fd); X close (fd); X checklev ("up"); X u.ux = xdnstair; X u.uy = ydnstair; X} X Xm_call () { X register OBJECT obj; X X obj = getobj ("?!=/", "call"); X if (obj) X docall (obj); X flags.move = 0; X} X Xdocall (obj) Xregister OBJECT obj; X{ X register char *str, **str1; X X pline ("Call it:"); X getlin (buf); X flags.topl = 0; X if (!*buf) X return; X str = alloc (strlen (buf) + 1) -> Val; X strcpy (str, buf); X switch (obj -> olet) { X case '_': X free (str); X return; X case '?': X str1 = &scrcall[obj -> otyp]; X break; X case '!': X str1 = &potcall[obj -> otyp]; X break; X case '/': X str1 = &wandcall[obj -> otyp]; X break; X case '=': X str1 = &ringcall[obj -> otyp]; X break; X default: X pline ("What a weird(%c %d)thing to call", obj -> olet, obj -> otyp); X X } X if (*str1) X free (*str1); X *str1 = str; X} X Xdonull () { X} X XMONSTER bhit (); X Xdothrow () { X register OBJECT obj; X register MONSTER monst; X register tmp; X char x, y; X X obj = getobj ("#%)", "throw"); X /* One can also throw food */ X if (!obj || !getdir ()) { X nomove (); X return; /* Sets dx and dy to direction */ X } X if (obj == uarm || obj == uarm2 || obj == uleft || X obj == uright) { X pline ("You can't throw something you are wearing"); X return; X } X if (obj == uwep && uwepcursed ()) X return; X monst = bhit (dx, dy, 8); X x = dx; X y = dy; X obj = loseone (obj); /* Separate one out from list */ X if (monst) { X if (obj -> olet == ')') { X tmp = u.ulevel - 1 + monst -> data -> ac + abon (); X if (obj -> otyp <= W_AMMUNITION) { X if (!uwep || uwep -> otyp != obj -> otyp + X 11) X tmp -= 4; X else { X if (uwep -> cursed) X tmp -= uwep -> spe; X else X tmp += uwep -> spe; X } X } X else { X if (obj -> cursed) X tmp -= obj -> spe; X else X tmp += obj -> spe; X } X if (tmp >= rnd (20)) { X if (hmon (monst, obj)) { X hit (weapons[obj -> otyp].wepnam, X monst); X cutworm (monst, x, y, obj -> otyp); X } X else X monst = 0; X if (obj -> otyp <= W_AMMUNITION && X rn2 (2)) { X freeobj (obj); X if (!onbill (obj)) X ofree (obj); X return; X } X } X else X miss (weapons[obj -> otyp].wepnam, monst); X } X else { X psee (IT1, x, y, UMISS, monst -> data -> mname, NULL); X if (obj -> olet == '%' && monst -> data -> mlet == 'd') X if (tamedog (monst, obj)) X return; X } X/* Awake monster if sleeping */ X if (monst) { X monst -> msleep = 0; X if (monst == shopkeeper) X setangry (); X } X } X obj -> ox = x; X obj -> oy = y; X if (obj -> unpaid && inshproom (x, y)) X subfrombill (obj); X if (!m_at (x, y)) X newsym (x, y); X} X X/* Create a new object (at fobj) of multiplicity 1 X remove obj from invent if necessary */ XOBJECT loseone (obj) Xregister OBJECT obj; X{ X register OBJECT otmp; X X if (!index ("/=", obj -> olet) && obj -> quan > 1) { X obj -> quan--; X otmp = newobj (); X *otmp = *obj; X otmp -> quan = 1; X otmp -> unpaid = 0;/* Obj is still on the bill */ X otmp -> nobj = fobj; X fobj = otmp; X } X else { X if (obj == invent) X invent = invent -> nobj; X else { X for (otmp = invent; otmp -> nobj != obj; X otmp = otmp -> nobj); X otmp -> nobj = obj -> nobj; X } X obj -> nobj = fobj; X fobj = obj; X } X return (fobj); X} X Xgetdir () { X pline ("What direction?"); X flush (); X *buf = getchar (); X flags.topl = 0; X return (movecm (buf)); X} X Xdocurse () { X register MONSTER mtmp; X X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) { X mtmp -> msleep = 0; X mtmp -> mtame = 0; X } X if (shopkeeper) X shopkeeper -> angry = 1; X if (vaultkeeper) X vaultkeeper -> angry = 1; X} / echo 'x - hack.end.c' sed 's/^X//' > hack.end.c << '/' X/* X * Hack.end.c X */ X X#include "hack.h" X#include <signal.h> X X#define MAXLEVEL 40 X Xextern char plname[], *itoa (), *setan (); X Xextern int billct, rfile; X Xchar maxdlevel = 0, *strcat (); X Xchar *statxx[] = { X "choked", X "died", X "starved", X "drowned", X "quit", X "escaped" X}; X Xdone1 () { X register char c; X X nomove (); X signal (SIGINT, done1); X pline ("Really quit?"); X flush (); X if ((c = getchar ()) == 'y') X done (QUIT); X else if (c == 'S') X hangup (); X} X Xdone (status) Xregister int status; X{ X if (wizard && status != QUIT && status != ESCAPED) { X u.ustr = (u.ustrmax += 2); X u.uhp = (u.uhpmax += 10); X u.uac--; X if (uwep) X uwep -> spe++; X pline ("For some reason you are still alive."); X nomove (); X flags.botl = 1; X return; X } X if (status == QUIT && u.uhp <= 0) X status = DIED; X if (billct) X paybill (); X clearlocks (); X if (status < QUIT) { /* Not when quit or escaped */ X#ifndef DEBUG X savebones (); X#endif DEBUG X outrip (); X } X hackmode (OFF); X cls (); X printf ("Goodbye %s...\n\n", plname); X u.urexp += u.ugold; X if (status == DIED) { X strcpy (killer, setan (killer)); X u.urexp -= u.ugold / 10; X } X else X killer = statxx[status]; X if (status == ESCAPED) { X OBJECT otmp; X X u.urexp += 150; X for (otmp = invent; otmp; otmp = otmp -> nobj) { X if (otmp -> olet == '*') X u.urexp += otmp -> quan * 10 * rnd (250); X else if (otmp -> olet == '"') X u.urexp += 25000; X } X printf ("You escaped from the dungeon"); X } X else X printf ("You %s on dungeon level %d,", statxx[status], X dlevel); X printf (" with %U points\n", u.urexp); X printf ("and %U pieces of gold, after %u moves.\n", X u.ugold, moves); X printf ("You were level %d with a maximum of %d hit points when you %s.\n\n", u.ulevel, u.uhpmax, statxx[status]); X topten (); X flush (); X exit (0); X} X X#define NAMESIZE 8 X#define DEATHSIZE 40 X#define TOPPRINT 15 /* Aantal scores dat wordt afgedrukt */ X#define TOPLIST 25 /* Length of 'top ten' list */ X Xtopten () { X int tmp; X struct recitem { X long points; X int level, maxlvl, hp, maxhp; X char str[NAMESIZE + 1], death[DEATHSIZE + 1]; X } rec[TOPLIST + 1], *t1; X register flg; X X for (t1 = rec; t1 < &rec[TOPLIST]; t1++) X if (read (rfile, t1, sizeof (struct recitem)) <= 0) X t1 -> points = 0; X flg = 0; X if (u.urexp > rec[TOPLIST - 1].points && !wizard) { X signal (SIGINT, SIG_IGN); X if (u.urexp > rec[TOPPRINT - 1].points) X printf ("You made the top %d list!\n", TOPPRINT); X if (lseek (rfile, 0L, 0) < 0) X panic (CORE, "Cannot lseek on record file"); X X/* Stick in new entry. NB: we save the last few X entries that disappeared from the list */ X X for (tmp = TOPLIST - 2; tmp >= 0 && rec[tmp].points < X u.urexp; tmp--) X rec[tmp + 1] = rec[tmp]; X tmp++; /* Point to right place */ X rec[tmp].points = u.urexp; X rec[tmp].level = dlevel; X rec[tmp].maxlvl = maxdlevel; X rec[tmp].hp = u.uhp; X rec[tmp].maxhp = u.uhpmax; X strncpy (rec[tmp].str, plname, NAMESIZE); X rec[tmp].str[NAMESIZE] = 0; X strncpy (rec[tmp].death, killer, DEATHSIZE); X rec[tmp].death[DEATHSIZE] = 0; X flg++; X } X printf ("Number Points Name\n"); X for (t1 = rec, tmp = 1; t1 < &rec[TOPLIST]; tmp++, t1++) { X char killed = 0; X X if (flg && t1 -> points) X write (rfile, t1, sizeof (struct recitem)); X if (t1 >= &rec[TOPPRINT] || t1 -> points == 0) X continue; X printf ("%2d %6D %8s ", tmp, t1 -> points, X t1 -> str); X if (*t1 -> death == 'e') X printf ("escaped the dungeon [max level %d]", t1 -> maxlvl); X else { X switch (t1 -> death[1]) { X case 'u': X printf ("quit"); X break; X case 'h': X printf ("choked on his food"); X break; X case 't': X printf ("starved"); X break; X case 'r': X printf ("drowned"); X break; X default: X printf ("was killed"); X killed++; X } X printf (" on%s level %d", X killed ? "" : " dungeon", t1 -> level); X if (t1 -> maxlvl != t1 -> level) X printf (" [%d]", t1 -> maxlvl); X } X if (killed) X printf (" by %s", t1 -> death); X putchar ('.'); X if (t1 -> maxhp) X printf (" Hp: %s [%d]", (t1 -> hp > 0) ? X itoa (t1 -> hp) : "-", t1 -> maxhp); X putchar ('\n'); X } X close (rfile); X} X Xchar * X itoa (a) Xregister int a; X{ X static char buffer[8]; X X sprintf (buffer, "%d", a); X return (buffer); X} X Xclearlocks () { X register x; X X signal (SIGINT, SIG_IGN); X for (x = 1; x <= MAXLEVEL; x++) { X glo (x); X if (unlink (lock)) X break; X } X#ifdef DEBUG X glo (0); X unlink (lock); X#endif DEBUG X} X Xhangup () { X save (); X clearlocks (); X exit (1); X} / echo 'x - hack.invent.c' sed 's/^X//' > hack.invent.c << '/' X/* X * Hack.invent.c X */ X X#include "hack.h" X X#define NOT_AT 0 X#define NO_OBJ 0 X Xextern WORMSEGMENT wsegs[32]; X Xextern OBJECT yourinvent0; X XOBJECT addinv (obj) Xregister OBJECT obj; X{ X register OBJECT otmp; X X for (otmp = invent; otmp; otmp = otmp -> nobj) { X if (otmp -> otyp == obj -> otyp && otmp -> olet == obj -> olet X && !obj -> unpaid && !otmp -> unpaid && X ((obj -> otyp < F_COOKIE && X obj -> olet == ')' && X obj -> quan + otmp -> quan < 32 && X obj -> spe == otmp -> spe) || X index ("%?!*", otmp -> olet))) { X otmp -> quan += obj -> quan; X ofree (obj); X return otmp; X } X if (!otmp -> nobj) { X otmp -> nobj = obj; X obj -> nobj = 0; X return obj; X } X } X invent = obj; X obj -> nobj = 0; X return obj; X} X Xuseup (obj) Xregister OBJECT obj; X{ X register OBJECT otmp; X X if (obj -> quan > 1) { X obj -> quan--; X return; X } X if (obj == invent) X invent = invent -> nobj; X else { X for (otmp = invent; otmp -> nobj != obj; X otmp = otmp -> nobj); X otmp -> nobj = obj -> nobj; X } X if (!onbill (obj)) X ofree (obj); X} X Xdelobj (obj) Xregister OBJECT obj; X{ X freeobj (obj); X ofree (obj); X} X Xofree (obj) Xregister OBJECT obj; X{ X if (obj > yourinvent0) X free (obj); X} X X/* Unlink obj from chain starting with fobj */ X Xfreeobj (obj) Xregister OBJECT obj; X{ X register OBJECT otmp; X X if (obj == fobj) X fobj = fobj -> nobj; X else { X for (otmp = fobj; otmp -> nobj != obj; otmp = otmp -> nobj) X if (!otmp) X panic (CORE, "Try to free non-existing object"); X otmp -> nobj = obj -> nobj; X } X} X Xdeltrap (trap) Xregister GOLD_TRAP trap; X{ X register GOLD_TRAP gtmp; X X if (trap == ftrap) X ftrap = ftrap -> ngen; X else { X for (gtmp = ftrap; gtmp -> ngen != trap; X gtmp = gtmp -> ngen); X gtmp -> ngen = trap -> ngen; X } X free (trap); X} X XMONSTER m_at (x, y) Xregister x, y; X{ X register MONSTER mtmp; X register WORMSEGMENT wtmp; X X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) { X if (mtmp -> mx == x && mtmp -> my == y) X return (mtmp); X if (mtmp -> wormno) X for (wtmp = wsegs[mtmp -> wormno]; wtmp; X wtmp = wtmp -> nseg) X if (wtmp -> wx == x && wtmp -> wy == y) X return (mtmp); X } X return (NOT_AT); X} X XOBJECT o_at (x, y) Xregister x, y; X{ X register OBJECT otmp; X X for (otmp = fobj; otmp; otmp = otmp -> nobj) X if (otmp -> ox == x && otmp -> oy == y) X return (otmp); X return (NOT_AT); X} X XGOLD_TRAP g_at (x, y, ptr) Xregister x, y; Xregister GOLD_TRAP ptr; X{ X while (ptr) { X if (ptr -> gx == x && ptr -> gy == y) X return (ptr); X ptr = ptr -> ngen; X } X return (NOT_AT); X} X XOBJECT getobj (let, word) Xregister char *let, *word; X{ X register OBJECT otmp; X register char ilet, ilet1, ilet2; X char buffer[BUFSZ], allowall = 0; X register foo = 0, foo2; X X if (*let == '#') { X let++; X allowall++; X } X ilet = 'a'; X for (otmp = invent; otmp; otmp = otmp -> nobj) { X if (!let || index (let, otmp -> olet)) X buffer[foo++] = ilet; X if (ilet == 'z') X ilet = 'A'; X else X ilet++; X } X buffer[foo] = 0; X if (foo > 5) { /* Compactify string */ X foo = foo2 = 1; X ilet2 = buffer[0]; X ilet1 = buffer[1]; X while (ilet = buffer[++foo2] = buffer[++foo]) { X if (ilet == ilet1 + 1) { X if (ilet1 == ilet2 + 1) X buffer[foo2 - 1] = ilet1 = '-'; X else if (ilet2 == '-') { X buffer[--foo2] = ++ilet1; X continue; X } X } X ilet2 = ilet1; X ilet1 = ilet; X } X } X if (!foo && !allowall) { X pline ("You don't have anything to %s.", word); X return (NO_OBJ); X } X for (;;) { X pline ((foo) ? "What do you want to %s [%s or ?]? " : X "What do you want to %s? ", word, buffer); X flags.topl = 0; X flush (); X ilet = getchar (); X if (ilet == '\33' || ilet == ' ' || ilet == '\n') X if (strcmp (word, "identify")) X return (NO_OBJ); X else X continue;/* sukkel */ X if (ilet == '?') X doinv (foo ? let : 0, 0); X else { X if (ilet >= 'A' && ilet <= 'Z') X ilet += 26 - 'A'; X else X ilet -= 'a'; X for (otmp = invent; otmp && ilet; ilet--, X otmp = otmp -> nobj); X if (!otmp) { X pline ("You don't have that object."); X continue; X } X break; X } X } X if (!allowall && let && !index (let, otmp -> olet)) { X pline ("That is a silly thing to %s.", word); X return (NO_OBJ); X } X return (otmp); X} X Xprinv (obj) Xregister OBJECT obj; X{ X register OBJECT otmp; X register char ilet = 'a'; X X for (otmp = invent; otmp != obj; otmp = otmp -> nobj) X if (++ilet > 'z') X ilet = 'A'; X prname (obj, ilet, 1); X} X Xprname (obj, let, onelin) Xregister OBJECT obj; Xregister char let; X{ X char li[BUFSZ]; X X doname (obj, buf); X sprintf (li, "%c - %s.", let, buf); X if (onelin) X pline (li); X else X printf ("%s\n", li); X} X Xddoinv () { X nomove (); X if (!invent) X pline ("You are empty handed."); X else X doinv (0, 1); X} X X/* X * Page inventory done by Fred X * X */ X Xdoinv (str, opt) Xregister char *str; Xint opt; X{ X register OBJECT otmp; X register char ilet = 'a'; X register int count = 1; X int ct = 0; X X if (!flags.oneline) X for (otmp = invent; otmp; otmp = otmp -> nobj) X if (!str || index (str, otmp -> olet)) X ct++; X if (ct > 1) X cls (); X for (otmp = invent; otmp; otmp = otmp -> nobj) { X if (!str || index (str, otmp -> olet)) { X prname (otmp, ilet, ct <= 1); X count++; X } X if (++ilet > 'z') X ilet = 'A'; X if (!(count % 22) && otmp -> nobj) { X getret (); X cls (); /* M. F. Page listing */ X } X } X if (!str && opt) X doinvbill (); X if (ct > 1) { X getret (); X docrt (); X } X} / echo 'x - hack.lev.c' sed 's/^X//' > hack.lev.c << '/' X/* X * Hack.lev.c X */ X X#include "hack.h" X#include <signal.h> X X#define MAXLEVEL 40 X#define ERROR 1 X#define OK 0 X Xextern char *itoa (), nul[], upxstairs[MAXLEVEL], upystairs[MAXLEVEL]; X Xextern WORMSEGMENT wsegs[32], wheads[32]; Xextern unsigned wgrowtime[32]; Xextern struct permonst pm_ghost; X X#include "hack.savelev.c" X Xstruct permonst pm_ale = { X "giant eel", ';', 15, 6, -3, 3, 6, 0 X}; X Xgetlev (fd) { X register MONSTER mtmp; X register GOLD_TRAP gtmp; X register OBJECT otmp; X register WORMSEGMENT wtmp; X int tmp, xl; X unsigned tmoves, omoves; X STOLE stmp; X X if (fd < 0 || read (fd, levl, sizeof (levl)) != sizeof (levl)) X return ERROR; X fmon = 0; X fobj = 0; X fgold = 0; X ftrap = 0; X shopkeeper = 0; X vaultkeeper = 0; X mread (fd, &omoves, sizeof (unsigned)); X mread (fd, &xupstair, 1); X mread (fd, &yupstair, 1); X mread (fd, &xdnstair, 1); X mread (fd, &ydnstair, 1); X if (omoves) X tmoves = (moves > omoves) ? moves - omoves : 0; X for (;;) { X mread (fd, &xl, sizeof (int)); X if (xl == -1) X break; X mtmp = newmonst (xl); X mread (fd, mtmp, xl + sizeof (struct monst)); X X/* Michiel restore stolen objects */ X stmp = newstole (); X mread (fd, stmp, sizeof (struct stole)); X if (stmp -> sgold || stmp -> sobj) { X mtmp -> mstole = stmp; X mtmp -> mstole -> sobj = 0; X for (;;) { X otmp = newobj (); X mread (fd, otmp, sizeof (struct obj)); X if (!otmp -> olet) X break; X otmp -> nobj = mtmp -> mstole -> sobj; X mtmp -> mstole -> sobj = otmp; X } X ofree (otmp); X } X else X free (stmp); X/* Regenerate animals if you've been on another level */ X if (omoves) { X if (!index (genocided, mtmp -> data -> mlet)) { X if (index ("ViT", mtmp -> data -> mlet)) X mtmp -> mhp += mtmp -> mhp + tmoves; X else X mtmp -> mhp += tmoves / 20; X if (mtmp -> mhp > mtmp -> orig_hp) X mtmp -> mhp = mtmp -> orig_hp; X if (mtmp -> data -> mlet == '@') { X if (*mtmp -> data -> mname == 's') X shopkeeper = mtmp; X else if (*mtmp -> data -> mname == 'v') X vaultkeeper = mtmp; X } X mtmp -> nmon = fmon; X fmon = mtmp; X } X } X else { /* Convert code from MKLEV */ X if (mtmp -> mhp == 10) X mtmp -> data = &pm_ghost; X else if (mtmp -> ale) X mtmp -> data = &pm_ale; X else X mtmp -> data = &mon[mtmp -> mhp][mtmp -> orig_hp]; X if (mtmp -> data -> mlet == 'D') X mtmp -> mhp = 80; X else X mtmp -> mhp = mtmp -> data -> mhd ? X d (mtmp -> data -> mhd, 8) : rnd (4); X mtmp -> orig_hp = mtmp -> mhp; X mtmp -> cham = (mtmp -> data -> mlet == ':'); X mtmp -> invis = (mtmp -> data -> mlet == 'I'); X if (mtmp -> data -> mlet == 'w' && X getwn (mtmp)) X initworm (mtmp); X mtmp -> nmon = fmon; X fmon = mtmp; X } X } X for (;;) { X gtmp = newgen (); X mread (fd, gtmp, sizeof (struct gen)); X if (!gtmp -> gx) X break; X gtmp -> ngen = fgold; X fgold = gtmp; X } X for (;;) { X mread (fd, gtmp, sizeof (struct gen)); X if (!gtmp -> gx) X break; X gtmp -> ngen = ftrap; X ftrap = gtmp; X gtmp = newgen (); X } X free (gtmp); X for (;;) { X otmp = newobj (); X mread (fd, otmp, sizeof (struct obj)); X if (!otmp -> olet) X break; X otmp -> nobj = fobj; X fobj = otmp; X } X ofree (otmp); X mread (fd, rooms, sizeof (rooms)); X mread (fd, doors, sizeof (doors)); X if (!omoves) X return OK; /* From MKLEV */ X mread (fd, wsegs, sizeof (wsegs)); X for (tmp = 1; tmp < 32; tmp++) X if (wsegs[tmp]) { X wheads[tmp] = wsegs[tmp] = wtmp = newseg (); X for (;;) { X mread (fd, wtmp, sizeof (struct wseg)); X if (!wtmp -> nseg) X break; X wheads[tmp] -> nseg = wtmp = newseg (); X wheads[tmp] = wtmp; X } X } X mread (fd, wgrowtime, sizeof (wgrowtime)); X return OK; X} X Xmread (fd, buffer, len) Xregister fd, len; Xregister char *buffer; X{ X register rlen; X X if ((rlen = read (fd, buffer, len)) != len) X panic (CORE, "Read %d instead of %d bytes from file #%d\n", X rlen, len, fd); X} X Xmklev () { X register fd; X char type[2]; X X#ifndef DEBUG X if (getbones ()) { X sleep (2); X goto Z; X } X#endif DEBUG X if (flags.next) { X flags.next = 0; X type[0] = 'b'; X } X else if (dlevel < rn1 (3, MAXLEVEL - 3)) X type[0] = 'a'; X else { X type[0] = 'n'; X flags.next = 1; X } X type[1] = '\0'; X hackexec (0, "./mklev", lock, type, itoa (dlevel), genocided, X wizard ? "w" : "", NULL); X if ((fd = open (lock, 0)) < 0) { X pline ("Can't open %s! Second try.", lock); X flush (); X hackexec (0, "./mklev", lock, type, itoa (dlevel), genocided, X wizard ? "w" : "", NULL); X if ((fd = open (lock, 0)) < 0) X panic (NOCORE, "Mklev error no level"); X } X getlev (fd); X close (fd); XZ: X if (!upxstairs[dlevel] && !upystairs[dlevel]) { X upxstairs[dlevel] = xupstair; X upystairs[dlevel] = yupstair; X } X} / echo 'x - hack.main.c' sed 's/^X//' > hack.main.c << '/' X/* X * Hack.main.c X */ X X#include <signal.h> X#include "hack.h" X X#define exception( id ) ( id == uid ) X#define HUISJES 2201 X#define WILDE 2216 X Xextern char *hu_stat[4], *getenv (), *malloc (), *parse (); X Xint rfile; X XCOORDINATES doors[DOORMAX]; X XPART levl[80][22]; XMKROOM rooms[15]; XMONSTER fmon = 0; XGOLD_TRAP fgold = 0, ftrap = 0; XFLAG flags; XYOU u; XOBJECT fobj = 0, invent, uwep, uarm, Xuarm2 = 0, uright = 0, uleft = 0; X Xextern OBJECT yourinvent0; Xextern struct obj mace0, uarm0; X Xchar nul[20]; /* Contains zeros */ X/* Lock contains 'pid'.dlevel */ Xchar plname[10], lock[16], wizard, X curx, cury, savx, X xupstair, yupstair, xdnstair, ydnstair, X *save_cm = 0, *killer, *nomvmsg, dlevel = 0, X dx, dy, buf[BUFSZ], genocided[60], X SAVEFILE[37] = SAVEDIR; X Xunsigned moves = 1; X Xint multi = 0, done1 (), hangup (), hackpid; Xint uid; X Xmain (argc, argv) Xchar *argv[]; X{ X int fd; X char *getlogin(); X register char *yourname = getlogin (); X X uid = getuid (); X /* X * Check on UID's X */ X X if (kantoor () && !exception (HUISJES) && !exception (WILDE)) { X printf ("Sorry, You can't play hack now\n" ); X flush (); X exit (0); X } X if (!access (LOCK, 0) && strcmp (WIZARD, yourname)) { X printf ("Sorry, I'm busy with debugging.\nTry again later.\n"); X flush (); X exit (0); X } X X strncpy (plname, yourname, sizeof (plname) - 1); X#ifdef WIZARD X while (argc > 1 && **++argv == '-') { X switch (argv[0][1]) { X case 'w': X if (!exception (HUISJES) && !exception (WILDE) && strcmp (yourname, WIZARD)) X printf ("Sorry\n"); X else { X strcpy (plname, "wizard"); X wizard++; X } X break; X default: X printf ("Unknown option: %s\n", *argv); X } X flush (); X } X#endif WIZARD X X if (chdir (PLAYGROUND) < 0) X panic (NOCORE, "Cannot chdir to %s!", PLAYGROUND); X if ((rfile = open (RECORD, 2)) < 0) X panic (NOCORE, "Can't open %s!", RECORD); X setuid (getuid ()); X umask (0); X srand (hackpid = getpid ()); X startup (); X signal (SIGHUP, hangup); X signal (SIGINT, done1); X hackmode (ON); X if (!wizard) { X cls (); X flush (); X } X strcat (SAVEFILE, plname); X fd = open (SAVEFILE, 0); X if (fd >= 0) { X if (dorecover (fd) < 0) X goto normalplay; X flags.move = 0; X } X else { Xnormalplay: X shuffle (); X invent = yourinvent0; X uwep = &mace0; X uarm = &uarm0; X u.uac = 6; /* 10 - uarm->spe */ X u.ulevel = 1; X u.uhunger = 900; X u.uhpmax = u.uhp = 12; X u.ustrmax = u.ustr = rn2 (20) ? 16 : rn1 (7, 14); X flags.move = 1; X dodown (); /* a3 */ X cls (); X setCon (SETC); X flags.botl = 1; X makedog (); X } X for (;;) { X if (flags.move) { X if (!u.ufast || moves % 2 == 0) { X if (fmon) X movemon (); X if (!rn2 (70)) { X makemon (0); X fmon -> mx = 0; X fmon -> my = 0; X rloc (fmon); X seeatl (fmon -> mx, fmon -> my, X fmon -> data -> mlet); X } X } X if (u.ufast && !--u.ufast) X pline ("You feel yourself slowing down"); X if (u.uconfused && !--u.uconfused) X pline ("You feel less confused now"); X if (u.ublind && !--u.ublind) { X pline ("You can see again"); X if (!u.uswallow) X setCon (SETC); X } X if (u.uinvis && !--u.uinvis) { X if (!u.uswallow) X on (u.ux, u.uy); X pline ("You are no longer invisible"); X } X ++moves; X if (u.uhp <= 0) { X pline ("You die..."); X more (); X done (DIED); X } X if (u.uhp < u.uhpmax) { X if (u.ulevel > 9) { X if (u.uregen || moves % 3 == 0) { X flags.dhp = 1; X u.uhp += X rnd (u.ulevel - 9); X if (u.uhp > u.uhpmax) X u.uhp = u.uhpmax; X } X } X else if (u.uregen || moves % X (22 - (u.ulevel << 1)) == 0) { X flags.dhp = 1; X u.uhp++; X } X } X if (u.utel && !rn2 (85)) X tele (); X if (u.usearch) X dosearch (); X gethungry (); X } X flags.move = 1; X if (flags.dscr && !flags.mv) X nscr (); X if (flags.botl) X bot (); X else if (flags.dgold) { X flags.dgold = 0; X curs (16, 24); X curx = 21; X printf ("%-5U", u.ugold); X } X if (flags.dhp) { X flags.dhp = 0; X curs (26, 24); X curx = 29; X printf ("%3d", u.uhp); X } X if (flags.dhpmax) { X flags.dhpmax = 0; X curs (30, 24); X printf ("%d)", u.uhpmax); X if (u.uhpmax < 100) X putchar (' '); X curx = (u.uhpmax < 10) ? 33 : 34; X } X if (flags.dac) { X flags.dac = 0; X curs (37, 24); X printf ("%-3d", u.uac); X curx = 40; X } X if (flags.dstr) { X flags.dstr = 0; X curs (46, 24); X prustr (); X curx = 51; X } X if (flags.dulev) { X flags.dulev = 0; X curs (57, 24); X printf ("%2d", u.ulevel); X curx = 59; X } X if (flags.dexp) { X flags.dexp = 0; X curs (60, 24); X if (u.ulevel < 14) X printf ("%-5U", u.uexp); X else X printf ("MAX++"); X curx = 65; X } X if (flags.dhs) { X flags.dhs = 0; X curs (71, 24); X printf (hu_stat[u.uhs]); X curx = 79; X } X if (multi < 0) { X if (!++multi) { X pline (nomvmsg ? nomvmsg : X "You can move again."); X nomvmsg = 0; X } X } X else { X if (multi) { X lookaround (); X if (!multi) { X flags.move = 0; X continue; X } X if (flags.mv) { X if (multi < 80 && !--multi) { X flags.mv = 0; X flags.run = 0; X } X domove (); X } X else { X --multi; X rhack (save_cm); X } X } X else X rhack (parse ()); X } X } X} X Xglo (n) Xregister n; /* Construct the string `hackpid.n' */ X{ X/* X register char *tf = lock; X X while( *tf && *tf != '.' ) X tf++; X *tf++ = '.'; X sprintf( tf, "%d", n ); X*/ X sprintf (lock, "%d.%d", hackpid, n); X} X Ximpossible () { X pline ("Program in disorder - perhaps you'd better Quit"); X} / echo 'x - hack.mkobj.c' sed 's/^X//' > hack.mkobj.c << '/' X/* X * Hack.mkobj.c X */ X X#include "hack.h" X#include "hack.vars.h" X Xmkfood () { X register FOOD fp; X register i = rn2 (100); X X fp = &foods[0]; X while ((i -= fp -> prob) >= 0) X fp++; X return (fp - foods); X} X Xmkarm () { X register ARMOR ap; X register i = rn2 (100); X X ap = &armors[0]; X while ((i -= ap -> prob) >= 0) X ap++; X return (ap - armors); X} X Xmkwep () { X register WEAPON wp; X register i = rn2 (100); X X wp = &weapons[0]; X while ((i -= wp -> prob) >= 0) X wp++; X return (wp - weapons); X} X Xchar mkobjstr[] = "))[[!!!!????%%%%//=**"; X Xmkobj (let) Xregister let; X{ X register OBJECT otmp; X X otmp = newobj (); X otmp -> nobj = fobj; X fobj = otmp; X otmp -> known = 0; X otmp -> cursed = 0; X otmp -> spe = 0; X otmp -> unpaid = 0; X otmp -> quan = 1; X if (!let) X let = mkobjstr[rn2 (sizeof (mkobjstr) - 1)]; X otmp -> olet = let; X switch (let) { X X case ')': X otmp -> otyp = mkwep (); X if (otmp -> otyp <= W_AMMUNITION) X otmp -> quan = rn1 (6, 6); X if (!rn2 (11)) X otmp -> spe = rnd (3); X else if (!rn2 (10)) { X otmp -> cursed = 1; X otmp -> spe = -rnd (3); X } X break; X X case '*': X otmp -> otyp = rn2 (SIZE (potcol)); X otmp -> quan = rn2 (6) ? 1 : 2; X break; X X case '[': X otmp -> otyp = mkarm (); X if (!rn2 (8)) X otmp -> cursed = 1; X if (!rn2 (10)) X otmp -> spe = rnd (3); X else if (!rn2 (9)) { X otmp -> spe = -rnd (3); X otmp -> cursed = 1; X } X otmp -> spe += 10 - armors[otmp -> otyp].a_ac; X break; X X case '!': X otmp -> otyp = rn2 (SIZE (pottyp)); X break; X X case '?': X otmp -> otyp = rn2 (SIZE (scrtyp)); X break; X X case '%': X otmp -> otyp = mkfood (); X otmp -> quan = rn2 (6) ? 1 : 2; X break; X X case '/': X otmp -> otyp = rn2 (SIZE (wantyp)); X if (otmp -> otyp == Z_DEATH) X otmp -> otyp = rn2 (SIZE (wantyp)); X otmp -> spe = rn1 (5, (otmp -> otyp <= Z_CREATE_MON) ? X 11 : 4); X /* detection and light and create monster */ X break; X X case '=': X otmp -> otyp = rn2 (SIZE (ringtyp)); X if (otmp -> otyp >= R_GAIN_STR) { X if (!rn2 (3)) { X otmp -> spe = -rnd (2); X otmp -> cursed = 1; X break; X } X else X otmp -> spe = rnd (2); X } X else if (otmp -> otyp == R_TELE || X otmp -> otyp == R_AGGRAV_MON || X otmp -> otyp == R_HUNGER) X otmp -> cursed = 1; X break; X X default: X panic (CORE, "Impossible mkobj"); X } X} X Xshufl (base, num) Xregister char *base[]; Xregister num; X{ X char **tmp, *tmp1; X int curnum; X X for (curnum = num - 1; curnum > 0; curnum--) { X tmp = &base[rn2 (curnum)]; X tmp1 = *tmp; X *tmp = base[curnum]; X base[curnum] = tmp1; X } X} X Xshuffle () { X shufl (wannam, SIZE (wantyp)); X shufl (potcol, SIZE (potcol)); X shufl (rinnam, SIZE (ringtyp)); X shufl (scrnam, SIZE (scrtyp)); X} X Xsavenames (fd) Xregister fd; X{ X bwrite (fd, oiden, sizeof oiden); X bwrite (fd, potcol, sizeof potcol); X bwrite (fd, scrnam, sizeof scrnam); X bwrite (fd, wannam, sizeof wannam); X bwrite (fd, rinnam, sizeof rinnam); X} X Xrestnames (fd) Xregister fd; X{ X mread (fd, oiden, sizeof oiden); X mread (fd, potcol, sizeof potcol); X mread (fd, scrnam, sizeof scrnam); X mread (fd, wannam, sizeof wannam); X mread (fd, rinnam, sizeof rinnam); X} X X/* Restore the names we have given to things */ Xcallsrestore (fd) Xregister fd; X{ X restcalls (fd, potcall, SIZE (pottyp)); X restcalls (fd, wandcall, SIZE (wantyp)); X restcalls (fd, ringcall, SIZE (ringtyp)); X restcalls (fd, scrcall, SIZE (scrtyp)); X} X X/* Save things we have given names to */ Xcallssave (fd) Xregister fd; X{ X savecalls (fd, potcall, SIZE (pottyp)); X savecalls (fd, wandcall, SIZE (wantyp)); X savecalls (fd, ringcall, SIZE (ringtyp)); X savecalls (fd, scrcall, SIZE (scrtyp)); X} X Xsavecalls (fd, strings, max) Xchar *strings[]; Xregister int max, fd; X{ X register teller; X X for (teller = 0; teller < max; ++teller) { X if (strings[teller]) X bwrite (fd, strings[teller], X strlen (strings[teller]) + 1); X else X bwrite (fd, "\0", 1); X } X} X Xrestcalls (fd, strings, max) Xregister int fd, max; Xchar *strings[]; X{ X register teller; X char *str; X int cnt; X char buffer[BUFSZ]; X X str = NULL; X for (teller = 0; teller < max; ++teller) { X cnt = -1; X do { X ++cnt; X mread (fd, str, 1); X buffer[cnt] = *str; X } while (*str != '\0'); X if (cnt) { X strings[teller] = alloc (strlen (buffer) + 1) -> Val; X strcpy (strings[teller], buffer); X } X } X} / echo 'x - hack.save.c' sed 's/^X//' > hack.save.c << '/' X/* X * Hack.save.c X */ X X/* X * The old version of save () didn't work at all. Many things are changed, X * but some things are not implemented yet, like saving in a shop, or saving X * while swallowed or stuck X */ X X#include "hack.h" X#include "hack.dog.h" X#include <signal.h> X X#define MAXLEVEL 40 X Xextern char SAVEFILE[], nul[], upxstairs[MAXLEVEL], X upystairs[MAXLEVEL], shlevel, vaultflag[MAXLEVEL]; Xextern long robbed; Xextern unsigned starved; Xextern COORDINATES shk, shd; Xextern MONSTER shopkeeper; Xextern MONSTER mydogs; X Xsave () { X register fd, ofd, tmp; X register OBJECT otmp, otmp2; X MONSTER mtmp; X int version = VERSION; X X nomove (); X if (shopkeeper && inshproom (u.ux, u.uy)) { X pline ("You are not allowed to save in a shop. (Continue or Quit)"); X return; X } X else if (u.ustuck || u.uswallow) { X pline ("Not implemented when you're stuck or swallowed. (Continue or Quit)"); X return; X } X if ((fd = creat (SAVEFILE, 0644)) < 0) { X pline ("Cannot creat save file. (Continue or Quit)"); X return; X } X signal (SIGINT, SIG_IGN); X signal (SIGQUIT, SIG_IGN); X X bwrite (fd, &version, sizeof (version)); X keepdogs (0); X savelev (fd); X for (otmp = invent; otmp; otmp = otmp2) { X bwrite (fd, otmp, sizeof (struct obj)); X if (otmp == uarm) X bwrite (fd, "a", 1); X else if (otmp == uarm2) X bwrite (fd, "b", 1); X else if (otmp == uwep) X bwrite (fd, "w", 1); X else if (otmp == uleft) X bwrite (fd, "l", 1); X else if (otmp == uright) X bwrite (fd, "r", 1); X else X bwrite (fd, "n", 1); X otmp2 = otmp -> nobj; X ofree (otmp); X } X bwrite (fd, nul, sizeof (struct obj)); X bwrite (fd, &flags, sizeof (struct flag)); X bwrite (fd, &dlevel, sizeof dlevel); X bwrite (fd, &moves, sizeof moves); X bwrite (fd, &u, sizeof (struct you)); X bwrite (fd, genocided, sizeof genocided); X bwrite (fd, upxstairs, sizeof upxstairs); X bwrite (fd, upystairs, sizeof upystairs); X bwrite (fd, vaultflag, sizeof vaultflag); X X savenames (fd); X X/* SHOP part */ X bwrite (fd, &shd, sizeof (struct coord)); X bwrite (fd, &shk, sizeof (struct coord)); X bwrite (fd, &shlevel, sizeof shlevel); X bwrite (fd, &robbed, sizeof robbed); X X/* Various globals */ X bwrite (fd, &starved, sizeof starved); X bwrite (fd, &seehx, sizeof seehx); X bwrite (fd, &seelx, sizeof seelx); X bwrite (fd, &seehy, sizeof seehy); X bwrite (fd, &seely, sizeof seely); X bwrite (fd, &dx, sizeof dx); X bwrite (fd, &dy, sizeof dy); X bwrite (fd, &maxdlevel, sizeof maxdlevel); X X/* And the dog(s) if any */ X for (mtmp = mydogs; mtmp; mtmp = mtmp -> nmon) X bwrite (fd, mtmp, sizeof (struct monst) + X sizeof (struct edog)); X bwrite (fd, nul, sizeof (struct monst) + sizeof (struct edog)); X X callssave (fd); X X cls (); X printf ("Saving level "); X flush (); X for (tmp = 1;; tmp++) { X glo (tmp); X if ((ofd = open (lock, 0)) < 0) X break; X getlev (ofd); X close (ofd); X savelev (fd); X printf ("%2d - %s", tmp, X (tmp % 10) ? "" : "\n "); X flush (); X unlink (lock); X } X X close (fd); X (*index (lock, '.')) = '\0';/* Remove main lock */ X unlink (lock); X printf ("\n\nSee you around...\n"); X flush (); X hackmode (OFF); X exit (0); X} X Xdorecover (fd) Xregister fd; X{ X register nfd, tmp; X register OBJECT otmp, olast; X MONSTER mtmp; X int version; X X cls (); X printf ("Starting up a suspended game....\n"); X flush (); X mread (fd, &version, sizeof (version)); X if (version != VERSION) { X printf ("Sorry, you're savefile is out of date.\n"); X printf ("I will have to remove it.\n"); X printf ("Type <space> to continue."); X close (fd); X unlink (SAVEFILE); X flush (); X while (getchar () != ' '); X return - 1; X } X X getlev (fd); X X invent = otmp = newobj (); X while (1) { X mread (fd, otmp, sizeof (struct obj)); X if (!otmp -> olet) { X if (otmp == invent) X invent = 0; X else X olast -> nobj = 0; X ofree (otmp); X break; X } X olast = otmp; X olast -> nobj = otmp = newobj (); X mread (fd, buf, 1); X switch (*buf) { X case 'w': X uwep = olast; X break; X case 'r': X uright = olast; X break; X case 'l': X uleft = olast; X break; X case 'a': X uarm = olast; X break; X case 'b': X uarm2 = olast; X case 'n': X break; X default: X panic (CORE, "Error reading save file"); X } X } X mread (fd, &flags, sizeof (struct flag)); X mread (fd, &dlevel, sizeof dlevel); X mread (fd, &moves, sizeof moves); X mread (fd, &u, sizeof (struct you)); X mread (fd, genocided, sizeof genocided); X mread (fd, upxstairs, sizeof upxstairs); X mread (fd, upystairs, sizeof upystairs); X mread (fd, vaultflag, sizeof vaultflag); X X restnames (fd); X X/* Restore shop part */ X mread (fd, &shd, sizeof (struct coord)); X mread (fd, &shk, sizeof (shk)); X mread (fd, &shlevel, sizeof shlevel); X mread (fd, &robbed, sizeof robbed); X X/* Restore various globals */ X mread (fd, &starved, sizeof starved); X mread (fd, &seehx, sizeof seehx); X mread (fd, &seelx, sizeof seelx); X mread (fd, &seehy, sizeof seehy); X mread (fd, &seely, sizeof seely); X mread (fd, &dx, sizeof dx); X mread (fd, &dy, sizeof dy); X mread (fd, &maxdlevel, sizeof maxdlevel); X X/* Let's try the dog again */ X while (1) { X mtmp = newmonst (sizeof (struct edog)); X mread (fd, mtmp, sizeof (struct monst) + X sizeof (struct edog)); X if (mtmp -> data == 0) X break; X else { X mtmp -> nmon = mydogs; X mydogs = mtmp; X } X } X free (mtmp); X X callsrestore (fd); X X printf ("Restoring level "); X flush (); X for (tmp = 1;; tmp++) { X if (getlev (fd)) X break; X glo (tmp); X if ((nfd = creat (lock, 0644)) < 0) X panic (CORE, "Cannot open temp file %s!\n", X lock); X savelev (nfd); X printf ("%2d - %s", tmp, X (tmp % 10) ? "" : "\n "); X flush (); X close (nfd); X } X X lseek (fd, (long) (sizeof (version)), 0); X getlev (fd); X close (fd); X losedogs (); X unlink (SAVEFILE); X docrt (); X return 1; X} / echo 'Part 04 of Hack complete.' exit -- Michiel Huisjes. {seismo|decvax|philabs}!mcvax!vu44!ark!huisjes
huisjes@ark.UUCP (Michiel B. Huisjes) (02/06/85)
#!/bin/sh # # # # This is a shell archive. These archives are packed by the program # packmail(1). If you have the program unshar(1), I suggest you use it. # If you don't remove anything before the cut line and then feed to # sh(1) # # =====CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=== # echo 'Start of Hack, part 05 of 05:' echo 'x - Makefile' sed 's/^X//' > Makefile << '/' X# hack makefile. X# layout en verdere verbeteringen Michiel en Fred X XPLAYDIR = /usr/games/playdir XSAVEDIR = /usr/games/playdir/save X XCFLAGS = -O -i XLIB = -ltermlib X XTARGET = hack X XHFILES = hack.c hack.lev.c hack.pri.c hack.do.c hack.do1.c hack.main.c\ Xhack.mon.c hack.dog.c hack.invent.c hack.eat.c hack.save.c\ Xhack.do_wear.c hack.shk.c hack.io.c hack.end.c hack.rip.c\ Xhack.bones.c hack.mkobj.c hack.monst.c hack.invinit.c hack.worm.c\ Xhack.debug.c hack.move.c hack.do.misc.c hack.mon.do.c hack.str.c\ Xhack.office.c X XMFILES = mklev.c mklev.make.c mklev.mkobj.c mklev.svlev.c X XGFILES = rnd.c alloc.c X XHOBJ = hack.o hack.lev.o hack.pri.o hack.do.o hack.do1.o hack.main.o\ Xhack.mon.o hack.dog.o hack.invent.o hack.eat.o hack.save.o\ Xhack.do_wear.o hack.shk.o hack.io.o hack.end.o hack.rip.o\ Xhack.bones.o hack.mkobj.o hack.monst.o hack.invinit.o hack.worm.o\ Xhack.debug.o hack.move.o hack.do.misc.o hack.mon.do.o hack.str.o\ Xhack.office.o X XGOBJ = rnd.o alloc.o X XMKOBJ = mklev.o mklev.make.o mklev.mkobj.o X Xall: hack mklev show X X$(TARGET) : $(HOBJ) $(GOBJ) X @echo Loading... X @$(CC) $(CFLAGS) -o $(TARGET) $(GOBJ) $(HOBJ) $(LIB) X @size $(TARGET) X @echo 'Done Hack' X X$(HOBJ) $(MKOBJ) : hack.h Xhack.do.misc.o: hack.do.vars.h envir.h Xhack.vars.h: hack.foods.h hack.armors.h hack.weapons.h Xhack.lev.o: hack.savelev.c Xhack.dog.o hack.monst.o: hack.dog.h Xhack.mkobj.o mklev.mkobj.o: hack.vars.h Xhack.main.o hack.lev.o hack.debug.o \ Xhack.do.misc.o hack.end.o hack.invinit.o: envir.h X Xhack.invinit.o: X cc $(CFLAGS) -c hack.invinit.c X Xmklev.o: hack.h envir.h X cc $(CFLAGS) -c mklev.c X Xmklev: $(MKOBJ) $(GOBJ) mklev.svlev.c X cc $(CFLAGS) $(MKOBJ) $(GOBJ) -o mklev X @echo 'Done mklev' X Xshow: show.c hack.h envir.h X cc -O show.c -o show X @echo 'Done show' X Xcleanup: X rm -f $(HOBJ) $(GOBJ) $(PLAYDIR)/show $(PLAYDIR)/makelev \ X $(PLAYDIR)/bones_* mklev.mkobj.o mklev.o X Xinstall: all X rm -f $(PLAYDIR)/bones_* X install -c -m 4711 $(TARGET) $(PLAYDIR)/$(TARGET) X install -c -m 711 mklev $(PLAYDIR)/mklev X install -c -m 700 show $(PLAYDIR)/show X Xnew: dirs install X Xdirs: X mkdir $(PLAYDIR) X mkdir $(SAVEDIR) X mv help $(PLAYDIR) X cp /dev/null $(PLAYDIR)/record X chmod 700 $(PLAYDIR)/record X Xlint: X lint -phbxac mk*.c rnd.c alloc.c -lc / echo 'x - READ_ME' sed 's/^X//' > READ_ME << '/' X XWell, here they are, the sources of Hack for pdp11/44 and pdp11/45. X XHow to install these on your machine. XThis is actually quite simple. Edit the file ``envir.h'' to define the Xlocal parameters. Edit the Makefile to define the playdir directory X(default /usr/games). Determine who will be the owner of the game, since Xit has the setuid bits on. XAfter you unshared the shar-files (in a new directory), Xyou should have the following files: X 1) - help data Makefile show.c rnd.c alloc.c X X 2) - envir.h hack.armors.h hack.do.vars.h hack.dog.h hack.foods.h X - hack.h hack.name.h hack.vars.h hack.weapons.h X X 3) - hack.bones.c hack.c hack.debug.c hack.do.c hack.do.misc.c X - hack.do1.c hack.do_wear.c hack.dog.c hack.eat.c hack.end.c X - hack.invent.c hack.invinit.c hack.io.c hack.lev.c hack.main.c X - hack.mkobj.c hack.mon.c hack.mon.do.c hack.monst.c hack.move.c X - hack.office.c hack.pri.c hack.rip.c hack.save.c hack.savelev.c X - hack.shk.c hack.str.c hack.worm.c X X 4) - mklev.c mklev.make.c mklev.mkobj.c mklev.svlev.c X XNow type ``make'' and the file ``hack'', ``mklev'' and ``show'' will be created. XNow type make new and the program will be installed in the right place. X XOne of the main problems of Hack is its size. If you add about 1000 bytes of Xtext more, your text segment will be to big. Therefore we saved text wherever Xthis was possible. We removed the function fscanf(), and made the record file Xbinary. To show the contents, use the program show (with flag -r). X XSome additions we (Fred de Wilde and Michiel Huisjes) made are X - The Vault X - The Swamp X - The Zoo X - The Graveyard X - Maxlevel = 40 X - Proper Saving X - Several bugs X - And many, many more... XA great bug that still exists is the display of the screen when you're blind. XSome more bugs are still existing, but you'll find those out while playing. X XThere is not a manual included with these sources. I suggest you use the Xmanual of the distributed version of hack (1.0.1) of CWI. X XHave fun, and good hacking! X X Michiel Huisjes and Fred de Wilde X {seismo|decvax|philabs}!mcvac!vu44!ark!huisjes X ...!wilde / echo 'x - alloc.c' sed 's/^X//' > alloc.c << '/' X/* X * Alloc.c X * X * Added new return values Michiel and Fred X * X */ X X/* X * The strange return value of alloc is implemented to shut lint up X */ X X#include "hack.h" X Xextern char *malloc (); X Xunion PTRS ptrs; X Xunion PTRS * Xalloc (num) Xregister num; X{ X register char *val; X X if (!(val = malloc (num))) X panic (CORE, "Cannot get %d bytes", num); X ptrs.Val = val; X return (&ptrs); X} / echo 'x - envir.h' sed 's/^X//' > envir.h << '/' X/* X * Envir.h X */ X X#define PLAYGROUND "/usr/games/playdir" X#define HELP "/usr/games/playdir/help" X#define HELP "/usr/games/playdir/data" X#define RECORD "/usr/games/playdir/record" X#define LOCK "/usr/games/playdir/hack.lock" X#define WIZARD "huisjes" X/* X#define DEBUG X*/ X X#define SAVEDIR "save/" X#define MORE "/usr/ucb/more" X#define VERSION 1 / echo 'x - hack.armors.h' sed 's/^X//' > hack.armors.h << '/' X/* X * Hack.armors.h X */ X Xstruct armor armors[] = { X { "plate mail", 5, 5, 3, 2 }, X { "splint mail", 10, 5, 4, 1 }, X { "banded mail", 10, 5, 4, 0 }, X { "chain mail", 10, 5, 5, 1 }, X { "scale mail", 10, 5, 6, 0 }, X { "ring mail", 15, 5, 7, 0 }, X { "studded leather armor", 15, 3, 7, 1 }, X { "leather armor", 20, 3, 8, 0 }, X { "elven cloak", 5, 0, 9, 3 }, X { "PROG ERROR", 100, 0, 0, 0 } X }; / echo 'x - hack.bones.c' sed 's/^X//' > hack.bones.c << '/' X/* X * Hack.bones.c X * X * Added increased chances on bones files. X * Fixed bug with mad shopkeeper. X * X */ X X#include "hack.h" X X#define NOBONES 0 X#define BONES 1 X Xextern char plname[10]; Xextern MONSTER shopkeeper; X Xstruct permonst pm_ghost = { X "ghost", '\t', 10, 3, -5, 1, 1, sizeof (plname) X}; X X/* (a3)#define GHMAX 10 */ X Xchar bones[] = "bones_xx"; X X/* Save bones and possessions of a deceased adventurer */ Xsavebones () { X register fd; X register OBJECT otmp; X register GOLD_TRAP gtmp; X register MONSTER mtmp; X X if (!rn2 (1 + dlevel/2)) X return; /* not so many ghosts on low levels */ X sprintf (&bones[6], "%d", dlevel); X if ((fd = open (bones, 0)) >= 0 ) { X close (fd); X return; X } X X /* Drop everything; the corpse's possessions are usually cursed */ X otmp = invent; X while (otmp) { X otmp -> ox = u.ux; X otmp -> oy = u.uy; X otmp -> unpaid = 0; X otmp -> known = 0; X if (rn2 (5)) X otmp -> cursed = 1; X if (!otmp -> nobj) { X otmp -> nobj = fobj; X fobj = invent; X invent = 0;/* Superfluous */ X break; X } X otmp = otmp -> nobj; X } X if (makemon (&pm_ghost)) X return; X fmon -> mx = u.ux; X fmon -> my = u.uy; X fmon -> msleep = 1; X/* Added: sizeof fmon->extra */ X/* This is actually nonsens. Ghosts do not have names in this version */ X strncpy (fmon -> mextra, plname, sizeof fmon -> mextra); X if (shopkeeper && X inshproom (shopkeeper -> mx, shopkeeper -> my)) X shopkeeper -> angry = 0; X gtmp = newgen (); X gtmp -> ngen = fgold; X fgold = gtmp; X gtmp -> gx = u.ux; X gtmp -> gy = u.uy; X gtmp -> gflag = somegold () + d (dlevel, 30); X u.ux = u.uy = 100; /* Random outside map */ X keepdogs (1); /* All tame animals become wild again */ X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) X levlsym (mtmp -> mx, mtmp -> my, mtmp -> data -> mlet); X if ((fd = creat (bones, 0644)) < 0) X return; X savelev (fd); X close (fd); X} X Xgetbones () { X register fd, x, y; X X sprintf (&bones[6], "%d", dlevel); X if ((fd = open (bones, 0)) < 0 || rn2 (3)) { X close (fd); /* Sometimes we find bones */ X return NOBONES; X } X getlev (fd); X close (fd); X if (unlink (bones) < 0) { X pline ("Cannot unlink %s", bones); X return NOBONES; X } X for (x = 0; x < 80; x++) X for (y = 0; y < 22; y++) { X levl[x][y].seen = 0; X levl[x][y].new = 0; X } X return BONES; X} / echo 'x - hack.do.vars.h' sed 's/^X//' > hack.do.vars.h << '/' X/* X * Hack.do.vars.h X */ X Xint doredraw(), dodrop(), dodrink(), doread(), X dosearch(), armwear(), dowearring(), doremarm(), X doremring(), dopay(), save(), dowield(), X ddoinv(), dozap(), m_call(), doset(), X dowhatis(), dohelp(), doeat(), ddoup(), X ddodown(), done1(), donull(), dothrow(), X doshow(), dosh(), doreprint(), gemsdrop(); X X#ifdef DEBUG Xint debug(); X#endif DEBUG X XFUNCTIONS list[] = { X '\020', doredraw, /* was '\014' */ X 'A', doreprint, /* Michiel: Repeat last message printed */ X#ifdef DEBUG X 'D', debug, X#endif DEBUG X 'P', dowearring, X 'Q', done1, X 'R', doremring, X 'G', gemsdrop, X 'S', save, X 'T', doremarm, X 'W', armwear, X 'a', doshow, /* Michiel: show everything you're wearing */ X 'c', m_call, X 'd', dodrop, X 'e', doeat, X 'i', ddoinv, X 'o', doset, X 'p', dopay, X 'q', dodrink, X 'r', doread, X 's', dosearch, X 't', dothrow, X 'w', dowield, X 'z', dozap, X '<', ddoup, X '>', ddodown, X '/', dowhatis, X '?', dohelp, X '!', dosh, X '\n', donull, X ' ', donull, X 0, 0 X}; / echo 'x - hack.do_wear.c' sed 's/^X//' > hack.do_wear.c << '/' X/* X * Hack.do_wear.c X */ X X#include "hack.h" X X#define CURSED 1 X#define NOTCURSED 0 X Xoff_msg (otmp) Xregister OBJECT otmp; X{ X doname (otmp, buf); X pline ("You were wearing %s.", buf); X} X Xdoremarm () { X register OBJECT oldarm = uarm; X X nomove (); X if (!uarm) { X pline ("Not wearing any armor."); X return; X } X flags.move = 1; X if (cursed (uarm)) X return; X nomul (-armors[uarm -> otyp].delay); X u.uac += uarm -> spe; X uarm = uarm2; X uarm2 = 0; X off_msg (oldarm); X flags.dac = 1; X} X Xdoremring () { X X nomove (); X if (!uleft && !uright) { X pline ("Not wearing any ring."); X return; X } X if (!uleft) X dorr (&uright); X else if (!uright) X dorr (&uleft); X else X for (;;) { X pline ("What ring, Right or Left? "); X flush (); X *buf = getchar (); X flags.topl = 0; X if (*buf == '\n' || *buf == '\033') X return; X if (*buf == 'l' || *buf == 'L') { X dorr (&uleft); X return; X } X if (*buf == 'r' || *buf == 'R') { X dorr (&uright); X return; X } X if (*buf == '?') X doinv ("=", 0); X } X} X Xdorr (ring) Xregister OBJECT * ring; X{ X register OBJECT otmp = *ring; X X if (cursed (otmp)) X return; X *ring = 0; X doring (otmp, OFF); X off_msg (otmp); X} X Xcursed (otmp) Xregister OBJECT otmp; X{ X if (otmp -> cursed) { X pline ("You can't. It appears to be cursed."); X return (CURSED); X } X return (NOTCURSED); X} X Xarmwear () { X register OBJECT otmp; X X otmp = getobj ("[", "wear"); X if (!otmp) { X nomove (); X return; X } X if (uarm) { X if (otmp -> otyp == A_ELVEN_CLOAK && !uarm2) X uarm2 = uarm; X else { X pline ("You are already wearing some armor."); X flags.move = 0; X return; X } X } X uarm = otmp; X nomul (-armors[otmp -> otyp].delay); X uarm -> known = 1; X u.uac -= uarm -> spe; X flags.dac = 1; X} X Xdowearring () { X register OBJECT otmp; X X otmp = getobj ("=", "wear"); X if (!otmp) { XR: X nomove (); X return; X } X if (uleft && uright) { X pline ("There are no more fingers to fill."); X goto R; X } X if (otmp == uleft || otmp == uright) { X pline ("You are already wearing that."); X goto R; X } X if (uleft) X uright = otmp; X else if (uright) X uleft = otmp; X else X while (!uright && !uleft) { X pline ("What finger, Right or Left? "); X flush (); X *buf = getchar (); X flags.topl = 0; X if (*buf == 'l' || *buf == 'L') X uleft = otmp; X else if (*buf == 'r' || *buf == 'R') X uright = otmp; X } X doring (otmp, ON); X prinv (otmp); X} X Xdoring (obj, eff) Xregister OBJECT obj; Xregister eff; X{ X register tmp; X X if (!obj) X return; X tmp = obj -> spe; X if (eff == OFF) X tmp = -tmp; X if (uleft && uright && uleft == uright && X obj -> otyp <= R_GAIN_STR) X return; X /* If wearing the same ring sometimes the flag must remain actif. */ X switch (obj -> otyp) { X case R_TELE: X u.utel = eff; X case R_ADORNMENT: X break; X case R_REGEN: X u.uregen = eff; X break; X case R_SEARCH: X u.usearch = eff; X break; X case R_SEE_INV: X u.ucinvis = eff; X break; X case R_STEALTH: X u.ustelth = eff; X break; X case R_FLOAT: X u.ufloat = eff; X break; X case R_POISON_RES: X u.upres = eff; X break; X case R_AGGRAV_MON: X u.uagmon = eff; X break; X case R_HUNGER: X u.ufeed = eff; X break; X case R_FIRE_RES: X u.ufireres = eff; X break; X case R_COLD_RES: X u.ucoldres = eff; X break; X case R_SHAPE: X u.ucham = eff; X if (eff != OFF) X rescham (); X break; X case R_GAIN_STR: X u.ustr += tmp; X u.ustrmax += tmp; X flags.dstr = 1; X break; X case R_DAM_INC: X u.udaminc += tmp; X break; X case R_PROTECTION: X u.uac -= tmp; X flags.dac = 1; X break; X default: X pline ("Bad(%d)ring", obj -> otyp); X impossible (); X } X} / echo 'x - hack.dog.h' sed 's/^X//' > hack.dog.h << '/' X/* X * Hack.dog.h X */ X Xstruct edog { X unsigned hungrytime; /* At this time dog gets hungry */ X unsigned eattime; /* Dog is eating */ X unsigned droptime; /* Moment dog dropped object */ X unsigned dropdist; /* Dist of drpped obj from @ */ X unsigned apport; /* Amount of training */ X unsigned carry: 1; /* The dog is carrying sth */ X}; / echo 'x - hack.eat.c' sed 's/^X//' > hack.eat.c << '/' X/* X * hack.eat.c X */ X X#include "hack.h" X Xextern char *nomvmsg; X Xunsigned starved = 0; /* Michiel: after 30 times fainting you starve X to death */ X Xchar *hu_stat[4] = { X " ", X "Hungry ", /* Hunger texts used in main (each 8 chars X long) */ X "Weak ", X "Fainting" X}; X Xdoeat () { X register OBJECT otmp; X register FOOD ftmp; X X if (!(otmp = getobj ("%", "eat"))) { X nomove (); X return; X } X starved = 0; X ftmp = &foods[otmp -> otyp]; X if (!rn2 (7)) { X pline ("Blecch! Rotten food!"); X if (!rn2 (4)) { X pline ("You feel rather light headed."); X u.uconfused += d (2, 4); X } X else if (!rn2 (4) && !u.ublind) { X pline ("Everything suddenly goes dark."); X u.ublind = d (2, 10); X unCoff (COFF, 0); X } X else if (!rn2 (3)) { X pline ("The world spins and goes dark."); X nomul (-rnd (10)); X nomvmsg = "You are conscious again"; X } X lesshungry (ftmp -> nutrition >> 2); X } X else { X multi = -ftmp -> delay; X switch (otmp -> otyp) { X X case F_FOOD: X if (u.uhunger < 500) X pline ("That food really hit the spot!"); X else if (u.uhunger < 1000) X pline ("That satiated your stomach!"); X else if (u.uhunger < 1500) { X pline ("You're having a hard time getting all that food down."); X multi -= 2; X } X else { X pline ("You choke over your food."); X more (); X killer = ftmp -> foodnam; X done (CHOKED); X } X lesshungry (ftmp -> nutrition); X if (multi < 0) X nomvmsg = "You finished your meal."; X break; X X case F_TRIPE: X pline ("Yak - dog food!"); X if (rn2 (2)) { X pline ("You vomit."); X lesshungry (-20); X } X else X lesshungry (ftmp -> nutrition); X break; X X default: X pline ("That %s was delicious!", ftmp -> foodnam); X lesshungry (ftmp -> nutrition); X break; X } X } X if (multi < 0 && !nomvmsg) { X static char msgbuf[40]; X X sprintf (msgbuf, "You finished eating your %s.", X ftmp -> foodnam); X nomvmsg = msgbuf; X } X useup (otmp); X} X Xlesshungry (num) /* Eat stg or drink fruit juice */ Xregister num; X{ X register newhunger; X X newhunger = u.uhunger + num; X if (u.uhunger < 151 && newhunger > 150) { X if (u.uhunger < 51 && u.ustr < u.ustrmax) X losestr (-1); X u.uhs = 0; X goto Ldohs; X } X if (u.uhunger < 51 && newhunger > 50) { X pline ("You only feel hungry now."); X if (u.ustr < u.ustrmax) X losestr (-1); X u.uhs = 1; X goto Ldohs; X } X if (u.uhunger <= 0 && newhunger < 50) { X pline ("You feel weak now."); X u.uhs = 2; XLdohs: X flags.dhs = 1; X } X u.uhunger = newhunger; X} X Xgethungry () { /* Called in main */ X --u.uhunger; X if ((u.uregen || u.ufeed) && moves % 2) X u.uhunger--; X if (u.uhunger <= 150 && !u.uhs) { X pline ("You are beginning to feel hungry."); X u.uhs = 1; X goto Ldohs; X } X if (u.uhunger <= 50 && u.uhs == 1) { X pline ("You are beginning to feel weak."); X losestr (1); X u.uhs = 2; X goto Ldohs; X } X if (u.uhunger <= 0) { X pline ("You faint from lack of food."); X if (starved++ == 100) { X pline ("You starve!"); X more (); X done (STARVED); X } X nomul (-20); X u.uhunger = rn1 (4, 22); X if (u.uhs != 3) { X u.uhs = 3; X Ldohs: X flags.dhs = 1; X } X } X} / echo 'x - hack.foods.h' sed 's/^X//' > hack.foods.h << '/' X/* X * Hack.foods.h X */ X X/* Dog eats foods 0-4 but prefers 1 above 0, 2, 3, 4 */ X Xstruct food foods[] = { X { "food ration", 50, 5, 800 }, X { "tripe ration", 20, 1, 200 }, X { "pancake", 3, 1, 200 }, X { "dead lizard", 3, 0, 40 }, X { "cookie", 7, 0, 40 }, X { "orange", 3, 0, 80 }, X { "apple", 3, 0, 50 }, X { "pear", 3, 0, 50 }, X { "melon", 1, 0, 100 }, X { "banana", 3, 0, 80 }, X { "candy bar", 3, 0, 100 }, X { "egg", 1, 0, 80 }, X { "PROG ERROR", 100, 0, 0 } X}; / echo 'x - hack.io.c' sed 's/^X//' > hack.io.c << '/' X/* X * Hack.io.c X */ X X#include "hack.h" X#include <sgtty.h> X Xshort ospeed; /* Used by tputs */ X Xgetlin (str) Xregister char *str; X{ X register char *ostr = str; X X flags.topl = 0; X flush (); X for (;;) { X *str = getchar (); X if (*str == '\b') { X if (str != ostr) { X str--; X write (1, "\b \b", 3); X } X else X write (1, "\7", 1); X } X else if (*str == '\n') { X *str = 0; X return; X } X else if (*str >= ' ') { X write (1, str, 1); X str++; X } X } X} X Xgetret () { X printf ("\nHit space to continue: "); X flush (); X while (getchar () != ' '); X} X/* X * Put together cbreak-mode and echo --- Michiel X */ X Xhackmode (x) Xregister x; X{ X struct sgttyb ttyp; X X ioctl (1, TIOCGETP, &ttyp);/* Use of basic functions */ X ospeed = ttyp.sg_ospeed; X if (x) { X ttyp.sg_flags &= ~ECHO; X ttyp.sg_flags |= CBREAK; X } X else { X ttyp.sg_flags |= ECHO; X ttyp.sg_flags &= ~CBREAK; X } X if (ioctl (1, TIOCSETP, &ttyp) < 0) { X printf ("ERROR: Cannot change tty"); X exit (1); X } X} X Xmore () { X printf (" --More--"); X flush (); X while (getchar () != ' '); X flags.topl = 0; X} X X#ifndef NORMAL_IO Xgetchar () { X char c; X X read (0, &c, 1); X return (c); X} X#endif NORMAL_IO / echo 'x - hack.monst.c' sed 's/^X//' > hack.monst.c << '/' X/* X * Hack.monst.c X */ X X#include "hack.h" X#include "hack.dog.h" X X/* X * Unfortunately the syntax for structure initialization is X * different on VAX and 11/45. Define VAX to get the VAX syntax X */ X X#define VAX X X#ifdef VAX X X#define SOSEP { X#define SCSEP } X#define GOSEP X#define GMSEP X#define GCSEP X X#else X X#define SOSEP X#define SCSEP X#define GOSEP { X#define GMSEP },{ X#define GCSEP } X X#endif VAX X Xstruct permonst mon[8][7]={ X GOSEP X SOSEP "bat", 'B',1,22,8,1,4,0 SCSEP, X SOSEP "gnome", 'G',1,6,5,1,6,0 SCSEP, X SOSEP "hobgoblin", 'H',1,9,5,1,8,0 SCSEP, X SOSEP "jackal", 'J',0,12,7,1,2,0 SCSEP, X SOSEP "kobold", 'K',1,6,7,1,4,0 SCSEP, X SOSEP "leprechaun", 'L',1,15,8,1,5,0 SCSEP, X SOSEP "giant rat", 'r',0,12,7,1,3,0 SCSEP, X GMSEP X SOSEP "acid blob", 'a',2,3,8,0,0,0 SCSEP, X SOSEP "floating eye", 'E',2,1,9,0,0,0 SCSEP, X SOSEP "homunculus", 'h',2,6,6,1,3,0 SCSEP, X SOSEP "imp", 'i',2,6,2,1,4,0 SCSEP, X SOSEP "orc", 'O',2,9,6,1,8,0 SCSEP, X SOSEP "yellow light", 'y',3,15,0,0,0,0 SCSEP, X SOSEP "zombie", 'Z',2,6,8,1,8,0 SCSEP, X GMSEP X SOSEP "giant ant", 'A',3,18,3,1,6,0 SCSEP, X SOSEP "fog cloud", 'f',3,1,0,1,6,0 SCSEP, X SOSEP "nymph", 'N',3,12,9,1,4,0 SCSEP, X SOSEP "piercer", 'p',3,1,3,2,6,0 SCSEP, X SOSEP "quasit", 'Q',3,15,3,1,4,0 SCSEP, X SOSEP "quivering blob", 'q',3,1,8,1,8,0 SCSEP, X SOSEP "violet fungi", 'v',3,1,7,1,4,0 SCSEP, X GMSEP X SOSEP "giant beetle", 'b',4,6,4,3,4,0 SCSEP, X SOSEP "centaur", 'C',4,18,4,1,6,0 SCSEP, X SOSEP "cockatrice", 'c',4,6,6,1,3,0 SCSEP, X SOSEP "gelatinous cube",'g',4,6,8,2,4,0 SCSEP, X SOSEP "jaguar", 'j',4,15,6,1,8,0 SCSEP, X SOSEP "killer bee", 'k',4,6,4,2,4,0 SCSEP, X SOSEP "snake", 'S',4,15,3,1,6,0 SCSEP, X GMSEP X SOSEP "freezing sphere",'F',2,13,4,0,0,0 SCSEP, X SOSEP "owlbear", 'o',5,12,5,2,6,0 SCSEP, X SOSEP "rust monster", 'R',5,18,3,0,0,0 SCSEP, X SOSEP "giant scorpion", 's',5,15,3,1,4,0 SCSEP, X SOSEP "teleporter", 't',5,3,5,1,7,0 SCSEP, X SOSEP "wraith", 'W',5,12,5,1,6,0 SCSEP, X SOSEP "long worm", 'w',6,3,5,2,5,0 SCSEP, X GMSEP X SOSEP "large dog", 'd',6,15,4,2,4,0 SCSEP, X SOSEP "leocrotta", 'l',6,18,4,3,6,0 SCSEP, X SOSEP "mimic", 'M',7,3,7,3,4,0 SCSEP, X SOSEP "minotaur", 'm',6,12,6,2,8,0 SCSEP, X SOSEP "troll", 'T',7,12,4,2,6,0 SCSEP, X SOSEP "ugod", 'u',6,11,5,1,10,0 SCSEP, X SOSEP "yeti", 'Y',5,15,6,1,6,0 SCSEP, X GMSEP X SOSEP "invisible stalker",'I',8,12,3,4,4,0 SCSEP, X SOSEP "umber hulk", 'U',9,6,2,2,14,0 SCSEP, X SOSEP "vampire", 'V',8,12,1,1,6,0 SCSEP, X SOSEP "xorn", 'X',8,9,-2,4,6,0 SCSEP, X SOSEP "xerp", 'x',7,6,3,2,4,0 SCSEP, X SOSEP "zelomp", 'z',9,8,3,3,6,0 SCSEP, X SOSEP "chameleon", ':',6,5,6,4,2,0 SCSEP, X GMSEP X SOSEP "dragon", 'D',20,9,-1,3,8,0 SCSEP, X SOSEP "ettin", 'e',10,12,3,2,8,0 SCSEP, X SOSEP "lurker above", '\'',10,3,3,0,0,0 SCSEP, X SOSEP "neo-otyugh", 'n',11,6,0,1,3,0 SCSEP, X SOSEP "trapper", ',',12,3,3,0,0,0 SCSEP, X SOSEP "purple worm", 'P',20,9,-1,2,8,0 SCSEP, X SOSEP "demon", '&',14,9,-4,1,6,0 SCSEP X GCSEP X}; Xstruct permonst /* _mon={0,0,0,0,0,0,0,0},*/ X li_dog={"little dog", 'd',2,18,6,1,6,sizeof(struct edog)}, X dog={"dog", 'd',4,16,5,1,6,sizeof(struct edog)}, X la_dog={"large dog", 'd',6,15,4,2,4,sizeof(struct edog)}; / echo 'x - hack.name.h' sed 's/^X//' > hack.name.h << '/' X/* X * Hack.name.h X */ X X#define S_ENCH_ARMOR 0 X#define S_DROP 1 X#define S_CURSE_LEV 2 X#define S_REM_CURSE 3 X#define S_ENCH_WEP 4 X#define S_CREAT_MON 5 X#define S_DAM_WEP 6 X#define S_GENOCIDE 7 X#define S_DESTR_ARMOR 8 X#define S_LIGHT 9 X#define S_TELEPORT 10 X#define S_GOLD_DETEC 11 X#define S_IDENTIFY 12 X#define S_MAG_MAP 13 X#define S_FIRE 14 X X#define P_REST_STR 0 X#define P_BOOZE 1 X#define P_INVIS 2 X#define P_JUICE 3 X#define P_HEALING 4 X#define P_FROZEN 5 X#define P_MONDETEC 6 X#define P_OBJDETEC 7 X#define P_POISON 8 X#define P_CONF 9 X#define P_GAIN_STR 10 X#define P_SPEED 11 X#define P_BLIND 12 X#define P_GAIN_LEV 13 X#define P_EXTRA_HEALING 14 X X#define Z_LIGHT 0 X#define Z_DETEC 1 X#define Z_CREATE_MON 2 X#define Z_EXHAUST 3 X#define Z_SLOW_MON 4 X#define Z_SPEED_MON 5 X#define Z_UND_TUR 6 X#define Z_POLYMORF 7 X#define Z_CAN 8 X#define Z_TELEPORT 9 X#define Z_DIGGING 10 X#define Z_MAG_MISSILE 11 X#define Z_FIRE 12 X#define Z_SLEEP 13 X#define Z_COLD 14 X#define Z_DEATH 15 X#define Z_CONF_MON 16 X#define Z_CLOSING 17 X X#define R_ADORNMENT 0 X#define R_TELE 1 X#define R_REGEN 2 X#define R_SEARCH 3 X#define R_SEE_INV 4 X#define R_STEALTH 5 X#define R_FLOAT 6 X#define R_POISON_RES 7 X#define R_AGGRAV_MON 8 X#define R_HUNGER 9 X#define R_FIRE_RES 10 X#define R_COLD_RES 11 X#define R_SHAPE 12 X#define R_GAIN_STR 13 X#define R_DAM_INC 14 X#define R_PROTECTION 15 X X#define W_ARROW 0 X#define W_SL_BULLET 1 X#define W_CROSS_BOLT 2 X#define W_DART 3 X#define W_MACE 4 X#define W_AXE 5 X#define W_FLAIL 6 X#define W_LONG_SWORD 7 X#define W_TWOH_SWORD 8 X#define W_DAGGER 9 X#define W_SPEAR 10 X#define W_BOW 11 X#define W_SLING 12 X#define W_CROSSBOW 13 X X#define W_USE_AMMO 11 X#define W_AMMUNITION 3 X X#define A_PLATE 0 X#define A_SPLINT 1 X#define A_BANDED 2 X#define A_CHAIN 3 X#define A_SCALE 4 X#define A_RING 5 X#define A_STD_LEATHER 6 X#define A_LEATHER 7 X#define A_ELVEN_CLOAK 8 X X#define F_FOOD 0 X#define F_TRIPE 1 X#define F_PANCAKE 2 X#define F_LIZARD 3 X#define F_COOKIE 4 X#define F_ORANGE 5 X#define F_APPLE 6 X#define F_PEAR 7 X#define F_MELON 8 X#define F_BANANA 9 X#define F_CANDY 10 X#define F_EGG 11 / echo 'x - hack.office.c' sed 's/^X//' > hack.office.c << '/' X/* X * Hack.office.c X */ X Xstruct tm { /* see ctime(3) */ X int tm_sec; X int tm_min; X int tm_hour; X int tm_mday; X int tm_mon; X int tm_year; X int tm_wday; X int tm_yday; X int tm_isdst; X}; X X X#define SUNDAY 0 X#define SATURDAY 6 X Xextern struct tm *localtime (); X Xkantoor () { X struct tm *s; X long clock; X X time (&clock); X s = localtime (&clock); X return (s -> tm_wday != SUNDAY && s -> tm_wday != SATURDAY && X s -> tm_hour <= 17 && s -> tm_hour > 9); X} / echo 'x - hack.rip.c' sed 's/^X//' > hack.rip.c << '/' X/* X * Hack.rip.c X */ X X#include <time.h> X#include "hack.h" X Xextern char plname[]; X Xstatic char *rip[] = { X " ----------", X " / \\", X " / REST \\", X " / IN \\", X " / PEACE \\", X " / \\", X " | |", X " | |", X " | killed by a |", X " | |", X " | 1001 |", X " *| * * * | *", X " _________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______", X 0 X}; X Xoutrip () { X register char **dp = rip; X register struct tm *lt; X long date; X char buffer[BUFSZ]; X struct tm *localtime (); X X time (&date); X lt = localtime (&date); X cls (); X strcpy (buffer, plname); X center (6, buffer); X sprintf (buffer, "%D Au", u.ugold); X center (7, buffer); X strcpy (buffer, killer); X center (9, buffer); X sprintf (buffer, "19%2d", lt -> tm_year); X center (10, buffer); X curs (1, 8); X while (*dp) X printf ("%s\n", *dp++); X getret (); X} X Xcenter (line, text) Xregister int line; Xregister char *text; X{ X register char *ip, *op; X X ip = text; X op = &rip[line][28 - ((strlen (text) + 1) >> 1)]; X while (*ip) X *op++ = *ip++; X} / echo 'x - hack.savelev.c' sed 's/^X//' > hack.savelev.c << '/' X/* X * Hack.savelev.c X */ X Xsavelev (fd) { X register MONSTER mtmp, mtmp2; X register GOLD_TRAP gtmp, gtmp2; X register OBJECT otmp, otmp2; X register WORMSEGMENT wtmp, wtmp2; X register tmp; X int minusone = -1; X X if (fd < 0) X panic (CORE, "Save on bad file!"); X bwrite (fd, levl, sizeof (levl)); X bwrite (fd, &moves, sizeof (unsigned)); X bwrite (fd, &xupstair, 1); X bwrite (fd, &yupstair, 1); X bwrite (fd, &xdnstair, 1); X bwrite (fd, &ydnstair, 1); X for (mtmp = fmon; mtmp; mtmp = mtmp2) { X mtmp2 = mtmp -> nmon; X bwrite (fd, &mtmp -> mxlth, sizeof (int)); X bwrite (fd, mtmp, mtmp -> mxlth + sizeof (struct monst)); X X/* Michiel save stolen objects */ X if (mtmp -> mstole) { X bwrite (fd, mtmp -> mstole, sizeof (struct stole)); X for (otmp = mtmp -> mstole -> sobj; otmp; X otmp = otmp -> nobj) X bwrite (fd, otmp, sizeof (struct obj)); X bwrite (fd, nul, sizeof (struct obj)); X free (mtmp -> mstole); X } X else X bwrite (fd, nul, sizeof (struct stole)); X free (mtmp); X } X bwrite (fd, &minusone, sizeof (int)); X for (gtmp = fgold; gtmp; gtmp = gtmp2) { X gtmp2 = gtmp -> ngen; X bwrite (fd, gtmp, sizeof (struct gen)); X free (gtmp); X } X bwrite (fd, nul, sizeof (struct gen)); X for (gtmp = ftrap; gtmp; gtmp = gtmp2) { X gtmp2 = gtmp -> ngen; X bwrite (fd, gtmp, sizeof (struct gen)); X free (gtmp); X } X bwrite (fd, nul, sizeof (struct gen)); X for (otmp = fobj; otmp; otmp = otmp2) { X otmp2 = otmp -> nobj; X bwrite (fd, otmp, sizeof (struct obj)); X ofree (otmp); X } X bwrite (fd, nul, sizeof (struct obj)); X bwrite (fd, rooms, sizeof (rooms)); X bwrite (fd, doors, sizeof (doors)); X fgold = 0; X ftrap = 0; X fmon = 0; X fobj = 0; X bwrite (fd, wsegs, sizeof (wsegs)); X for (tmp = 1; tmp < 32; tmp++) { X for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) { X wtmp2 = wtmp -> nseg; X bwrite (fd, wtmp, sizeof (struct wseg)); X } X wsegs[tmp] = 0; X } X bwrite (fd, wgrowtime, sizeof (wgrowtime)); X shopkeeper = 0; X} X Xbwrite (fd, loc, num) Xregister fd, num; Xregister char *loc; X{ X if (write (fd, loc, num) != num) X panic (CORE, "Cannot write %d bytes to file #%d", num, X fd); X} / echo 'x - hack.str.c' sed 's/^X//' > hack.str.c << '/' X/* X * Hack.str.c X */ X X/* X * strprint() : Cheap alternative for sprintf() and printf(), by X * Fred and Michiel. If you want the normal io just define NORMAL_IO X */ X X X#include "hack.h" X X#ifndef NORMAL_IO X X#define ARINDEX 512 Xstatic char output_buffer[ARINDEX]; Xstatic arcount = 0; X Xchar *litoa(); X X/*VARARGS10*/ Xstrprint( dest, src, argptr ) Xregister char *dest, *src; Xregister int *argptr; X{ X register kar; X register char *string; X register field; X int negated; X int printflag = 0; X static char extra[512]; X X if ( dest == STDOUT ) { X dest = extra; X printflag++; X } X X while( *src ) { X if ( *src == '%' ) { X field = 0; X negated = 0; X if ( *++src == '-' ) X ++negated; X else X --src; X while( *++src & 060 && *src <= '9' ) X field = 10*field + ( *src & 017 ); X if ( (kar = *src) == '%' ) X *dest++ = '%'; X else if ( kar == 'c' ) X *dest++ = (char)*argptr++; X else { X switch ( kar ) { X X case 'd' : X string = litoa( (long)(*argptr)); X break; X case 'U' : X case 'D' : X string = litoa( *((long *)argptr++) ); X break; X case 'u' : X string = X litoa( (long)( *((unsigned *)argptr)) ); X break; X case 's' : X string = (char *)(*argptr); X break; X default : X strcpy( string, "%'" ); X } X if ( field ) X field -= strlen( string ); X if ( field > 0 && !negated ) X while( --field >= 0 ) X *dest++ = ' '; X while( *dest++ = *string++ ) X ; X dest--; /* Remove '\0' character */ X if ( field > 0 && negated ) X while( --field >= 0 ) X *dest++ = ' '; X argptr++; X } X src++; X } X else X *dest++ = *src++; X } X *dest = 0; X if ( printflag ) { X WRITE( extra, strlen(extra) ); X } X} X Xchar * Xlitoa( l_arg ) Xlong l_arg; X{ X static char string[20]; X register int i = 0; X register char *str2 = string; X char pipo[20]; X X if ( !l_arg ) X return( "0" ); X if ( l_arg < 0L ) { X *str2++ = '-'; X l_arg = -l_arg; X } X X while( l_arg ) { X pipo[i++] = (int)( l_arg % 10L + '0'); X l_arg /= 10L; X } X while( --i >= 0 ) /* Michiel */ X *str2++ = pipo[i]; X *str2 = '\0'; X return( string ); X} X XWRITE( string , length ) Xregister char *string; Xregister length; X{ X if ( arcount + length >= ARINDEX ) X flush(); X strcat( output_buffer, string ); X arcount += length; X} X Xflush() X{ X write( 1, output_buffer, arcount ); X arcount = 0; X output_buffer[0] = 0; X} X Xputchar ( c ) X{ X WRITE( &c, 1 ); X} X Xprintf( fmt, args ) X{ X strprint( STDOUT, fmt, &args ); X} X Xsprintf( buffer, fmt, args ) X{ X strprint( buffer, fmt, &args ); X} X#endif NORMAL_IO / echo 'x - hack.vars.h' sed 's/^X//' > hack.vars.h << '/' X/* X * Hack.vars.h X */ X X#define SIZE(x) (sizeof x)/(sizeof x[0]) X Xchar NOTHIN[] = "Nothing Happens", X WCLEV[] = "Welcome to level %d.", X STOPGLOW[] = "Your hands stop glowing blue.", X UMISS[] = "You miss %s."; X X Xchar *traps[] = { X " bear trap", X "n arrow trap", X " dart trap", X " trapdoor", X " teleportation trap", X " pit", X " sleeping gas trap", X " piercer", X " mimic" X}; X X#include "hack.foods.h" X#include "hack.armors.h" X#include "hack.weapons.h" X Xchar *pottyp[] = { X "restore strength", X "booze", X "invisibility", X "fruit juice", X "healing", X "paralysis", X "monster detection", X "object detection", X "sickness", X "confusion", X "gain strength", X "speed", X "blindness", X "gain level", X "extra healing" X}; X X X Xchar *potcol[] = { X "ebony", X "magenta", X "clear", X "brilliant blue", X "sky blue", X "emerald", X "dark green", X "ruby", X "purple-red", X "swirly", X "white", X "yellow", X "purple", X "puce", X "pink", X "smokey", X "glowing", X "bubbly", X "orange" X}; X Xchar *potcall[SIZE (pottyp)]; X X /* SCROLLS */ X Xchar *scrtyp[] = { X "enchant armor", X "losing", X "curse levels", X "remove curse", X "enchant weapon", X "create monster", X "damage weapon", X "genocide", X "destroy armor", X "light", X "transportation", X "gold detection", X "identify", X "magic mapping", X "fire" X}; X X Xchar *scrnam[] = { X "VELOX NEB", X "FOOBIE BLETCH", X "TEMOV", X "GARVEN DEH", X "ZELGO MER", X "ANDOVA BEGARIN", X "ELAM EBOW", X "KERNOD WEL", X "THARR", X "VENZAR BORGAVVE", X /* "ELBIB YLOH", */ X "VERR YED HORRE", X "JUYED AWK YACC", X "HACKEM MUCHE", X "LEP GEX VEN ZEA", X "DAIYEN FOOELS" X}; Xchar *scrcall[SIZE (scrtyp)]; X X X /* WANDS */ X Xchar *wantyp[] = { X "light", X "secret door + trap detection", X "create monster", X "exhaustion", X "slow monster", X "speed monster", X "undead turning", X "polymorph", X "cancellation", X "teleport monster", X "digging", X "magic missile", X "fire", X "sleep", X "cold", X "death", X "confusion", X "door closing" X}; X X Xchar *wannam[] = { X "oak", X "ebony", X "runed", X "long", X "short", X "curved", X "steel", X "aluminium", X "iron", X "marble", X "pine", X "maple", X "brass", X "silver", X "copper", X "balsa", X "zinc", X "platinum" X}; Xchar *wandcall[SIZE (wantyp)]; X X X /* RINGS */ X Xchar *ringtyp[] = { X "adornment", X "teleportation", X "regeneration", X "searching", X "see invisible", X "stealth", X "floating", X "poison resistance", X "aggravate monster", X "hunger", X "fire resistance", X "cold resistance", X "protection from shape-changers", X "gain strength", X "increase damage", X "protection" X}; X X Xchar *rinnam[] = { X "blackened", X /* "ivory", */ X "granite", X "silver", X "ruby", X "jade", X "diamond", X "copper", X "gold", X "shining", X "tiger eye", X "agate", X "moonstone", X "sapphire", X "pearl", X "topaz", X /* "black onix", */ X "wired" X}; X Xchar *ringcall[SIZE (ringtyp)], oiden[40], oldux, olduy; / echo 'x - hack.weapons.h' sed 's/^X//' > hack.weapons.h << '/' X/* X * Hack.weapons.h X */ X X/* X * weapons 0-4 come several at a time X * weapons 0-2 are shot using 11-13 X */ X Xstruct weapon weapons[] = { X { "arrow", 7, 6, 6 }, X { "sling bullet", 7, 4, 6 }, X { "crossbow bolt", 7, 4, 6 }, X { "dart", 7, 3, 2 }, X { "mace", 7, 6, 6 }, X { "axe", 7, 6, 4 }, X { "flail", 7, 6, 4 }, X { "long sword", 9, 8,12 }, X { "two handed sword", 7,10, 6 }, X { "dagger", 7, 4, 3 }, X { "spear", 7, 6, 8 }, X { "bow", 7, 4, 6 }, X { "sling", 7, 6, 6 }, X { "crossbow", 7, 4, 6 }, X { "PROG ERROR", 100, 0, 0 } X }; / echo 'x - hack.worm.c' sed 's/^X//' > hack.worm.c << '/' X/* X * Hack.worm.c X */ X X#include "hack.h" X X/* Linked list, tail first */ XWORMSEGMENT wsegs[32], wheads[32]; X Xunsigned wgrowtime[32]; X Xgetwn (mtmp) XMONSTER mtmp; X{ X register tmp; X X for (tmp = 1; tmp < 32; tmp++) X if (!wsegs[tmp]) { X mtmp -> wormno = tmp; X return 1; X } X return 0; /* Level infested with worms */ X} X Xinitworm (mtmp) XMONSTER mtmp; X{ X register WORMSEGMENT wtmp; X register tmp = mtmp -> wormno; X X if (!tmp) X return; X wheads[tmp] = wsegs[tmp] = wtmp = newseg (); X wgrowtime[tmp] = 0; X wtmp -> wx = mtmp -> mx; X wtmp -> wy = mtmp -> my; X wtmp -> nseg = 0; X} X Xworm_move (mtmp) XMONSTER mtmp; X{ X register WORMSEGMENT wtmp, whd; X register tmp = mtmp -> wormno; X X wtmp = newseg (); X wtmp -> wx = mtmp -> mx; X wtmp -> wy = mtmp -> my; X wtmp -> nseg = 0; X whd = wheads[tmp]; X whd -> nseg = wtmp; X wheads[tmp] = wtmp; X seeatl (whd -> wx, whd -> wy, '~'); X if (wgrowtime[tmp] <= moves) { X if (!wgrowtime[tmp]) X wgrowtime[tmp] = moves + rnd (5); X else X wgrowtime[tmp] += 2 + rnd (15); X mtmp -> orig_hp++; X mtmp -> mhp++; X return; X } X whd = wsegs[tmp]; X wsegs[tmp] = whd -> nseg; X remseg (whd); X} X Xworm_nomove (mtmp) Xregister MONSTER mtmp; X{ X register tmp; X register WORMSEGMENT wtmp; X X tmp = mtmp -> wormno; X wtmp = wsegs[tmp]; X if (wtmp == wheads[tmp]) X return; X wsegs[tmp] = wtmp -> nseg; X remseg (wtmp); X mtmp -> mhp--; /* Orig_hp not changed! */ X} X Xwormdead (mtmp) Xregister MONSTER mtmp; X{ X register tmp = mtmp -> wormno; X register WORMSEGMENT wtmp, wtmp2; X X if (!tmp) X return; X for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) { X wtmp2 = wtmp -> nseg; X remseg (wtmp); X } X wsegs[tmp] = 0; X} X Xwormhit (mtmp) Xregister MONSTER mtmp; X{ X register tmp = mtmp -> wormno; X register MONSTDATA mdat = mtmp -> data; X register WORMSEGMENT wtmp; X X if (!tmp) X return; /* Worm without tail */ X for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp -> nseg) X hitu (mdat -> mhd, 1, mdat -> mname); X} X Xwormsee (tmp) Xregister tmp; X{ X register WORMSEGMENT wtmp; X X for (wtmp = wsegs[tmp]; wtmp -> nseg; wtmp = wtmp -> nseg) X if (!cansee (wtmp -> wx, wtmp -> wy)) X levlsym (wtmp -> wx, wtmp -> wy, '~'); X} X Xcutworm (mtmp, x, y, weptyp) Xregister MONSTER mtmp; Xregister char x, y; Xregister unsigned weptyp; X{ X register WORMSEGMENT wtmp, wtmp2; X register MONSTER mtmp2; X register tmp, tmp2; X X if (mtmp -> mx == x && mtmp -> my == y) X return; /* Hit headon */ X X/* Cutting goes best with axe or sword */ X tmp = rnd (20); X if (weptyp == 7 || weptyp == 8 || weptyp == 5) X tmp += 5; X if (tmp < 16) X return; X X/* If tail then worm just loses a tail segment */ X tmp = mtmp -> wormno; X wtmp = wsegs[tmp]; X if (wtmp -> wx == x && wtmp -> wy == y) { X wsegs[tmp] = wtmp -> nseg; X remseg (wtmp); X return; X } X X/* Cut the worm in two halves */ X mtmp2 = newmonst (0); X *mtmp2 = *mtmp; X X/* Sometimes the tail end dies */ X if (rn2 (8) || !getwn (mtmp2)) {/* Michiel was rn2(3) */ X free (mtmp2); X tmp2 = 0; X } X else { X tmp2 = mtmp2 -> wormno; X wsegs[tmp2] = wsegs[tmp]; X wgrowtime[tmp2] = 0; X } X do { X if (wtmp -> nseg -> wx == x && wtmp -> nseg -> wy == y) { X if (tmp2) X wheads[tmp2] = wtmp; X wsegs[tmp] = wtmp -> nseg -> nseg; X remseg (wtmp -> nseg); X wtmp -> nseg = 0; X if (tmp2) { X pline ("You cut the worm in half."); X mtmp2 -> orig_hp = mtmp2 -> mhp = X d (mtmp2 -> data -> mhd, 8); X mtmp2 -> mx = wtmp -> wx; X mtmp2 -> my = wtmp -> wy; X mtmp2 -> nmon = fmon; X fmon = mtmp2; X pmon (mtmp2); X } X else { X pline ("You cut off part of the worm's tail."); X remseg (wtmp); X } X mtmp -> mhp >>= 1; X return; X } X wtmp2 = wtmp -> nseg; X if (!tmp2) X remseg (wtmp); X wtmp = wtmp2; X } while (wtmp -> nseg); X panic (CORE, "Cannot find worm segment"); X} X Xremseg (wtmp) Xregister WORMSEGMENT wtmp; X{ X levlsym (wtmp -> wx, wtmp -> wy, '~'); X free (wtmp); X} / echo 'x - help' sed 's/^X//' > help << '/' X Welcome to HACK! X X Hack is a Dungeons and Dragons like game where you (the adventurer) Xdescend into the depths of the dungeon in search of the Amulet of Guyver X(reputed to be hidden on the twentieth level). On the way you will find Xuseful (or useless) magic items, and assorted monsters. You attack a monster Xby trying to move into the space a monster is in. X X Unlike most adventure games, which give you a verbal description of Xyour location, hack gives you a visual image of the dungeon level you are on. X X Hack uses the following symbols: X A to Z and a to z: monsters. You can find out what a letter Xrepresents by saying "whatis (letter)", as in "whatis A", which will tell you Xthat 'A' is a giant ant. X - and | These form the walls of a room. X . this is the floor of a room. X # this is a corridor. X } this is a water filled area. X > this is the staircase to the next level. X < the staircase to the previous level. X @ You (usually). X ^ A trap. X ) A weapon of some sort. X [ A suit of armor. X % A piece of food. X / A wand. X = A ring. X ? A scroll. X ! A magic potion. X $ A pile or pot of gold. X XCommands: X Hack knows the following commands: X help print this list. (Hack mode: ?) X quit quit the game. (Hack mode: Q) X up go up the staircase. (if you are standing on it) X (Hack mode: <) X down go down (just like up). X (Hack mode: >) X n,s,ne,etc. go one space in the direction indicated. X North is toward the top of the screen. X N,S,NE, etc. Go in that direction until you hit a wall or X run into something. X invent Print your inventory. X (Hack mode: i) X search search for secret doors and traps in the X locations next to you. X (hack mode: s) X (return) rest, do nothing. X redraw redraws the screen, useful if you type too fast X or your terminal is too slow. X (Hack mode: ^z (control/z)) X whatis ~ (~ is any symbol printed on your screen) X Tell what ~ is. (For instance 'whatis A' X will tell you that A is a giant ant. X (Hack mode: /) X eat Eat food. It will then ask what object you X want to eat. X (Hack mode: e) X wield Change the weapon you use to attack with. X It will ask what you want to wield. X (Hack mode: w) X drink Drink a potion. (Hack mode: q quaff) X read Read a scroll. (Hack mode: r) X remove Remove your armor or ring. X (Hack mode: T takeoff armor; R remove ring) X wear Wear a suit of armor or a ring. X (Hack mode: W wear armor; P put on ring) X pay Pay your shopping bill. X (Hack mode: p) X show Show all you are wearing on armor and rings. X (Hack mode: a) X repeat Repeat last message printed. X (Hack mode: A) X drop gems Drop all your gems that you are currently X holding. X (Hack mode: G) X oneline Give inventories one line at a time X (at the top of your screen). X (Hack mode: o) X X You can put a number before a command to repeat it that many times, X as in "20 search" or "40" (40 rest). X You can also put more than one command on a line by putting commas X between them, as in "20 search,2 e,20 search", or X "n,e,n,e,n". X X In hack mode you have the commands h (left), j (down), k (up), X l (right), y (nw), u (ne), b (sw), n(se); these move you one step. X Also HJKLYUBN - these move you as far as possible in the indicated X direction. X Also fh, fj etc. - these move you repeatedly in the indicated X direction until something interesting happens. X Finally FH, FJ etc. - these work like the previous, but branching X in a corridor is not considered interesting. X X X Have Fun, and Good Hacking! / echo 'x - mklev.mkobj.c' sed 's/^X//' > mklev.mkobj.c << '/' X/* X * Mklev.mkobj.c X */ X X#define NORMAL_IO X#include "hack.h" X#include "hack.vars.h" X Xmkfood () { X register FOOD fp; X register i = rn2 (100); X X fp = &foods[0]; X while ((i -= fp -> prob) >= 0) X fp++; X return (fp - foods); X} X Xmkarm () { X register ARMOR ap; X register i = rn2 (100); X X ap = &armors[0]; X while ((i -= ap -> prob) >= 0) X ap++; X return (ap - armors); X} X Xmkwep () { X register WEAPON wp; X register i = rn2 (100); X wp = &weapons[0]; X while ((i -= wp -> prob) >= 0) X wp++; X return (wp - weapons); X} X Xchar mkobjstr[] = "))[[!!!!????%%%%//=**"; X Xmkobj (let) Xregister let; X{ X register OBJECT otmp; X X otmp = newobj (); X otmp -> nobj = fobj; X fobj = otmp; X otmp -> known = 0; X otmp -> cursed = 0; X otmp -> spe = 0; X otmp -> unpaid = 0; X otmp -> quan = 1; X if (!let) X let = mkobjstr[rn2 (sizeof (mkobjstr) - 1)]; X otmp -> olet = let; X switch (let) { X X case ')': X otmp -> otyp = mkwep (); X if (otmp -> otyp <= W_AMMUNITION) X otmp -> quan = rn1 (6, 6); X if (!rn2 (11)) X otmp -> spe = rnd (3); X else if (!rn2 (10)) { X otmp -> cursed = 1; X otmp -> spe = -rnd (3); X } X break; X X case '*': X otmp -> otyp = rn2 (SIZE (potcol)); X otmp -> quan = rn2 (6) ? 1 : 2; X break; X X case '[': X otmp -> otyp = mkarm (); X if (!rn2 (8)) X otmp -> cursed = 1; X if (!rn2 (10)) X otmp -> spe = rnd (3); X else if (!rn2 (9)) { X otmp -> spe = -rnd (3); X otmp -> cursed = 1; X } X otmp -> spe += 10 - armors[otmp -> otyp].a_ac; X break; X X case '!': X otmp -> otyp = rn2 (SIZE (pottyp)); X break; X X case '?': X otmp -> otyp = rn2 (SIZE (scrtyp)); X break; X X case '%': X otmp -> otyp = mkfood (); X otmp -> quan = rn2 (6) ? 1 : 2; X break; X X case '/': X otmp -> otyp = rn2 (SIZE (wantyp)); X if (otmp -> otyp == Z_DEATH) X otmp -> otyp = rn2 (SIZE (wantyp)); X otmp -> spe = rn1 (5, (otmp -> otyp <= Z_CREATE_MON) ? X 11 : 4); X break; X X case '=': X otmp -> otyp = rn2 (SIZE (ringtyp)); X if (otmp -> otyp >= R_GAIN_STR) { X if (!rn2 (3)) { X otmp -> spe = -rnd (2); X otmp -> cursed = 1; X } X else X otmp -> spe = rnd (2); X } X else if (otmp -> otyp == R_TELE || X otmp -> otyp == R_AGGRAV_MON || X otmp -> otyp == R_HUNGER) X otmp -> cursed = 1; X break; X X default: X panic ("impossible mkobj"); X } X} / echo 'x - rnd.c' sed 's/^X//' > rnd.c << '/' X/* X * Rnd.c X */ X X#define RND(x) ((rand() >> 3) % x) X Xrn1 (x, y) Xregister x, y; X{ X return (RND (x) + y); X} X Xrn2 (x) Xregister x; X{ X return (RND (x)); X} X Xrnd (x) Xregister x; X{ X return (RND (x) + 1); X} X Xd (n, x) Xregister n, x; X{ X register tmp = n; X X while (n--) X tmp += RND (x); X return tmp; X} / echo 'Part 05 of Hack complete.' exit -- Michiel Huisjes. {seismo|decvax|philabs}!mcvax!vu44!ark!huisjes