robert@gitpyr.UUCP (Robert Viduya) (01/21/85)
I've made a few mods to hack. For a list, see the parent of this article. I've made one more mod since I posted the original article and that was a new command that let's you do selective inventories ("What scrolls do I have?"). Here are the modified files in shar format (no, I'm not posting the whole thing over again). I spent about a day tracking down all the changes I made to make the list of modified files. However, being human, I might have missed something. If so, send me mail. robert --------------------Decapitate Here------------------------ #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # hack.cmdlist.c # hack.do.c # hack.invent.c # hack.main.c # hack.o_init.c # hack.read.c # hack.shk.c # hack.termcap.c # hack.topl.c # hack.tty.c # hack.wield.c # hack.zap.c # help # help.nr # hh # mklev.c sed 's/^X//' << '--burp--' > hack.cmdlist.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include "config.h" X#include "def.objclass.h" X#include "def.func_tab.h" X Xint doredraw (), doredotopl (), dodrop (), dodrink (), doread (), X dosearch (), doversion (), doweararm (), dowearring (), X doremarm (), doremring (), dopay (), doapply (), dosave (), X dowield (), ddoinv (), dozap (), ddocall (), dowhatis (), doengrave (), X dohelp (), doeat (), doddrop (), do_mname (), doidtrap (), X doprwep (), doprarm (), doprring (), dodiscovered (), dotypeinv (); X#ifdef SHELL Xint dosh (); X#endif SHELL X#ifdef OPTIONS Xint doset (); X#endif OPTIONS Xint doup (), dodown (), done1 (), donull (); Xint dothrow (); Xstruct func_tab list[] = { X '\022', doredraw, X '\020', doredotopl, X 'a', doapply, X/* 'A' : UNUSED */ X/* 'b', 'B' : go sw */ X 'c', ddocall, X 'C', do_mname, X 'd', dodrop, X 'D', doddrop, X 'e', doeat, X 'E', doengrave, X/* 'f', 'F' : multiple go (might become 'fight') */ X/* 'g', 'G' : UNUSED */ X/* 'h', 'H' : go west */ X 'i', ddoinv, X 'I', dotypeinv, X/* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */ X#ifdef OPTIONS X 'o', doset, X#endif OPTIONS X/* 'O' : UNUSED */ X 'p', dopay, X 'P', dowearring, X 'q', dodrink, X 'Q', done1, X 'r', doread, X 'R', doremring, X 's', dosearch, X 'S', dosave, X 't', dothrow, X 'T', doremarm, X/* 'u', 'U' : go ne */ X 'v', doversion, X/* 'V' : UNUSED */ X 'w', dowield, X 'W', doweararm, X/* 'x', 'X' : UNUSED */ X/* 'y', 'Y' : go nw */ X 'z', dozap, X/* 'Z' : UNUSED */ X '<', doup, X '>', dodown, X '/', dowhatis, X '?', dohelp, X#ifdef SHELL X '!', dosh, X#endif SHELL X '.', donull, X ' ', donull, X '^', doidtrap, X '\\', dodiscovered, X WEAPON_SYM, doprwep, X ARMOR_SYM, doprarm, X RING_SYM, doprring, X 0, 0, 0 X}; --burp-- sed 's/^X//' << '--burp--' > hack.do.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include <stdio.h> X#include <signal.h> X#include <ctype.h> X#include "config.h" X#include "hack.h" X#include "def.func_tab.h" X Xextern char *getenv (), *parse (), *getlogin (), *lowc (), *unctrl (); Xextern int float_down (); Xextern char *nomovemsg; Xextern struct obj *splitobj (), *addinv (); Xextern boolean hmon (); X X/* Routines to do various user commands */ X Xint done1 (); X Xdodrink () X{ X register struct obj *otmp, *objs; X register struct monst *mtmp; X register int unkn = 0, nothing = 0; X X otmp = getobj ("!", "drink"); X if (!otmp) X return (0); X switch (otmp -> otyp) { X case POT_RESTORE_STRENGTH: X unkn++; X pline ("Wow! This makes you feel great!"); X if (u.ustr < u.ustrmax) { X u.ustr = u.ustrmax; X flags.botl = 1; X } X break; X case POT_BOOZE: X unkn++; X pline ("Ooph! This tastes like liquid fire!"); X Confusion += d (3, 8); X /* the whiskey makes us feel better */ X if (u.uhp < u.uhpmax) X losehp (-1, "bottle of whiskey"); X if (!rn2 (4)) { X pline ("You pass out."); X multi = -rnd (15); X nomovemsg = "You awake with a headache."; X } X break; X case POT_INVISIBILITY: X if (Invis) X nothing++; X else { X if (!Blind) X pline ("Gee! All of a sudden, you can't see yourself."); X else X pline ("You feel rather airy."), unkn++; X newsym (u.ux, u.uy); X } X Invis += rn1 (15, 31); X break; X case POT_FRUIT_JUICE: X pline ("This tastes like fruit juice."); X lesshungry (20); X break; X case POT_HEALING: X pline ("You begin to feel better."); X flags.botl = 1; X u.uhp += rnd (10); X if (u.uhp > u.uhpmax) X u.uhp = ++u.uhpmax; X if (Blind) X Blind = 1; /* see on next move */ X if (Sick) X Sick = 0; X break; X case POT_PARALYSIS: X pline ("Your feet are frozen to the floor!"); X nomul (-(rn1 (10, 25))); X break; X case POT_MONSTER_DETECTION: X if (!fmon) { X pline ("You feel threatened."); X strange_feeling (otmp); X return (1); X } X else { X cls (); X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) X if (mtmp -> mx > 0) X at (mtmp -> mx, mtmp -> my, mtmp -> data -> mlet); X prme (); X pline ("You sense the presence of monsters."); X more (); X docrt (); X } X break; X case POT_OBJECT_DETECTION: X if (!fobj) { X pline ("You feel a pull downward."); X strange_feeling (otmp); X return (1); X } X else { X for (objs = fobj; objs; objs = objs -> nobj) X if (objs -> ox != u.ux || objs -> oy != u.uy) X goto outobjmap; X pline ("You sense the presence of objects close nearby."); X break; X outobjmap: X cls (); X for (objs = fobj; objs; objs = objs -> nobj) X at (objs -> ox, objs -> oy, objs -> olet); X prme (); X pline ("You sense the presence of objects."); X more (); X docrt (); X } X break; X case POT_SICKNESS: X pline ("Yech! This stuff tastes like poison."); X if (Poison_resistance) X pline ("(But in fact it was biologically contaminated orange juice.)"); X losestr (rn1 (4, 3)); X losehp (rnd (10), "poison potion"); X break; X case POT_CONFUSION: X if (!Confusion) X pline ("Huh, What? Where am I?"); X else X nothing++; X Confusion += rn1 (7, 16); X break; X case POT_GAIN_STRENGTH: X pline ("Wow do you feel strong!"); X if (u.ustr == 118) X break; 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.botl = 1; X break; X case POT_SPEED: X if (Wounded_legs) { X if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES) X pline ("Your legs feel somewhat better."); X else X pline ("Your leg feels somewhat better."); X Wounded_legs = 0; X unkn++; X break; X } X if (!(Fast & ~INTRINSIC)) X pline ("You are suddenly moving much faster."); X else X pline ("Your legs get new energy."), unkn++; X Fast += rn1 (10, 100); X break; X case POT_BLINDNESS: X if (!Blind) X pline ("A cloud of darkness falls upon you."); X else X nothing++; X Blind += rn1 (100, 250); X seeoff (0); X break; X case POT_GAIN_LEVEL: X pluslvl (); X break; X case POT_EXTRA_HEALING: X pline ("You feel much better."); X flags.botl = 1; X u.uhp += d (2, 20) + 1; X if (u.uhp > u.uhpmax) X u.uhp = (u.uhpmax += 2); X if (Blind) X Blind = 1; X if (Sick) X Sick = 0; X break; X case POT_LEVITATION: X if (!Levitation) X float_up (); X else X nothing++; X Levitation += rnd (100); X u.uprops[PROP (RIN_LEVITATION)].p_tofn = float_down; X break; X default: X pline ("What a funny potion! (%d)", otmp -> otyp); X impossible (); X return (0); X } X if (nothing) { X unkn++; X pline ("You have a peculiar feeling for a moment, then it passes."); X } X if (otmp -> dknown && !objects[otmp -> otyp].oc_name_known) { X if (!unkn) { X objects[otmp -> otyp].oc_name_known = 1; X u.urexp += 10; X } X else X if (!objects[otmp -> otyp].oc_uname) X docall (otmp); X } X useup (otmp); X return (1); X} X Xpluslvl () X{ X register num; X X pline ("You feel more experienced."); X num = rnd (10); X u.uhpmax += num; X u.uhp += num; X u.uexp = (10 * pow (u.ulevel - 1)) + 1; X pline ("Welcome to level %d.", ++u.ulevel); X flags.botl = 1; X} X Xstrange_feeling (obj) Xregister struct obj *obj; X{ X if (!objects[obj -> otyp].oc_name_known && !objects[obj -> otyp].oc_uname) X docall (obj); X useup (obj); X} X Xdodrop () X{ X register struct obj *obj; X X obj = getobj ("0$#", "drop"); X if (!obj) X return (0); X if (obj -> olet == '$') { X if (obj -> quan == 0) X pline ("You didn't drop any gold pieces."); X else { X mkgold ((int) obj -> quan, u.ux, u.uy); X pline ("You dropped %u gold piece%s.", obj -> quan, plur (obj -> quan)); X if (Invis) X newsym (u.ux, u.uy); X } X free ((char *) obj); X return (1); X } X return (drop (obj)); X} X Xdrop (obj) Xregister struct obj *obj; X{ X if (obj -> owornmask & (W_ARMOR | W_RING)) { X pline ("You cannot drop something you are wearing."); X return (0); X } X if (obj == uwep) { X if (uwep -> cursed) { X pline ("Your weapon is welded to your hand!"); X return (0); X } X setuwep ((struct obj *) 0); X } X pline ("You dropped %s.", doname (obj)); X dropx (obj); X return (1); X} X Xdropx (obj) Xregister struct obj *obj; X{ X if (obj -> otyp == CRYSKNIFE) X obj -> otyp = WORM_TOOTH; X freeinv (obj); X obj -> ox = u.ux; X obj -> oy = u.uy; X obj -> nobj = fobj; X fobj = obj; X if (Invis) X newsym (u.ux, u.uy); X subfrombill (obj); X stackobj (obj); X} X X/* drop several things */ Xdoddrop () X{ X return (ggetobj ("drop", drop, 0)); X} X Xrhack (cmd) Xregister char *cmd; X{ X register struct func_tab *tlist = list; X boolean firsttime = FALSE; X register res; X X if (!cmd) { X firsttime = TRUE; X flags.nopick = 0; X cmd = parse (); X } X if (!*cmd || *cmd == 0377) X return; /* probably we just had an interrupt */ X if (movecm (cmd)) { Xwalk: X if (multi) X flags.mv = 1; X domove (); X return; X } X if (movecm (lowc (cmd))) { X flags.run = 1; Xrush: X if (firsttime) { X if (!multi) X multi = COLNO; X u.last_str_turn = 0; X } X flags.mv = 1; X#ifdef QUEST X if (flags.run >= 4) X finddir (); X if (firsttime) { X u.ux0 = u.ux + u.dx; X u.uy0 = u.uy + u.dy; X } X#endif QUEST X domove (); X return; X } X if ((*cmd == 'f' && movecm (cmd + 1)) || movecm (unctrl (cmd))) { X flags.run = 2; X goto rush; X } X if (*cmd == 'F' && movecm (lowc (cmd + 1))) { X flags.run = 3; X goto rush; X } X if (*cmd == 'm' && movecm (cmd + 1)) { X flags.run = 0; X flags.nopick = 1; X goto walk; X } X if (*cmd == 'M' && movecm (lowc (cmd + 1))) { X flags.run = 1; X flags.nopick = 1; X goto rush; X } X#ifdef QUEST X if (*cmd == cmd[1] && (*cmd == 'f' || *cmd == 'F')) { X flags.run = 4; X if (*cmd == 'F') X flags.run += 2; X if (cmd[2] == '-') X flags.run += 1; X goto rush; X } X#endif QUEST X while (tlist -> f_char) { X if (*cmd == tlist -> f_char) { X res = (*(tlist -> f_funct)) (0); X if (!res) { X flags.move = 0; X multi = 0; X } X return; X } X tlist++; X } X pline ("Unknown command '%s'", cmd); X multi = flags.move = 0; X} X Xdoredraw () X{ X docrt (); X return (0); X} X Xdohelp () X{ X FILE * f; X char line[100], c; X int count; X char done; X X pline ("Long or short help? "); X while (((c = readchar ()) != 'l') && (c != 's') && (c != '\033')) X bell (); X if (c == '\033') X return (0); X if ((f = fopen ((c == 'l' ? "help" : "hh"), "r")) == NULL) { X pline ("Can't get help"); X return (0); X } X count = 1; X done = 0; X while (((fgets (line, 100, f)) != NULL) && (!done)) { X curs (1, count); X cl_end (); X puts (line); X count++; X if (count >= ROWNO + 1) { X curs (1, count); X cl_end (); X curs (1, ROWNO + 2); X cl_end (); X standoutbeg (); X fputs ("--More--", stdout); X standoutend (); X while (((c = readchar ()) != ' ') && (c != 'q')) X bell (); X done = (c == 'q'); X count = 1; X } X } X (void) fclose (f); X curs (1, count); X cl_eos (); X curs (1, ROWNO + 2); X standoutbeg (); X fputs ("Hit space to continue...", stdout); X standoutend (); X while (readchar () != ' ') X bell (); X docrt (); X return (0); X} X X#ifdef SHELL Xdosh () X{ X register char *str; X char hackpath[128]; X X (void) getwd (hackpath); X if (child (0)) { X (void) chdir (getenv ("HOME")); X if (str = getenv ("SHELL")) X execl (str, str, (char *) 0); X if (strcmp ("player", getlogin ())) X execl ("/bin/sh", "sh", (char *) 0); X pline ("sh: cannot execute."); X exit (1); X } X (void) chdir (hackpath); X return (0); X} X#endif SHELL X X#ifdef BSD X#include <sys/wait.h> X#else X#include <wait.h> X#endif BSD X Xchild (wt) X{ X register int f = fork (); X if (f == 0) { /* child */ X settty ((char *) 0); X (void) setuid (getuid ()); X (void) setgid (getgid ()); X return (1); X } X if (f == -1) { /* cannot fork */ X pline ("Fork failed. Try again."); X return (0); X } X /* fork succeeded; wait for child to exit */ X (void) signal (SIGINT, SIG_IGN); X (void) signal (SIGQUIT, SIG_IGN); X (void) wait ((union wait *) 0); X setctty (); X (void) signal (SIGINT, done1); X#ifdef WIZARD X if (wizard) X (void) signal (SIGQUIT, SIG_DFL); X#endif WIZARD X if (wt) X getret (); X start_screen (); X docrt (); X return (0); X} X Xdodown () X{ X if (u.ux != xdnstair || u.uy != ydnstair) { X pline ("You can't go down here."); X return (0); X } X if (u.ustuck) { X pline ("You are being held, and cannot go down."); X return (1); X } X if (Levitation) { X pline ("You're floating high above the stairs."); X return (0); X } X X goto_level (dlevel + 1, TRUE); X return (1); X} X Xdoup () X{ X if (u.ux != xupstair || u.uy != yupstair) { X pline ("You can't go up here."); X return (0); X } X if (u.ustuck) { X pline ("You are being held, and cannot go up."); X return (1); X } X if (inv_weight () + 5 > 0) { X pline ("Your load is too heavy to climb the stairs."); X return (1); X } X X goto_level (dlevel - 1, TRUE); X return (1); X} X Xgoto_level (newlevel, at_stairs) Xregister int newlevel; Xregister boolean at_stairs; X{ X register fd; X register boolean up = (newlevel < dlevel); X X if (newlevel <= 0) X done ("escaped"); /* in fact < 0 is impossible */ X if (newlevel == dlevel) X return; /* this cannot happen either */ X X glo (dlevel); X fd = creat (lock, FMASK); X if (fd < 0) { X /* X * This is not quite impossible: e.g., we may have X * exceeded our quota. If that is the case then we X * cannot leave this level, and cannot save either. X */ X pline ("A mysterious force prevents you from going %d.", X up ? "up" : "down"); X return; X } X X if (Punished) X unplacebc (); X keepdogs (); X seeoff (1); X flags.nscrinh = 1; X u.ux = FAR; /* hack */ X (void) inshop (); /* probably was a trapdoor */ X X savelev (fd); X (void) close (fd); X X dlevel = newlevel; X if (maxdlevel < dlevel) X maxdlevel = dlevel; X glo (dlevel); X if ((fd = open (lock, 0)) < 0) X mklev (); X else { X (void) getlev (fd); X (void) close (fd); X } X X if (at_stairs) { X if (up) { X u.ux = xdnstair; X u.uy = ydnstair; X if (!u.ux) { /* entering a maze from below? */ X u.ux = xupstair; /* this will confuse the player! */ X u.uy = yupstair; X } X if (Punished) { X pline ("With great effort you climb the stairs"); X placebc (1); X } X } X else { X u.ux = xupstair; X u.uy = yupstair; X if (inv_weight () + 5 > 0 || Punished) { X pline ("You fall down the stairs."); X losehp (rnd (3), "fall"); X if (Punished) { X if (uwep != uball && rn2 (3)) { X pline ("... and are hit by the iron ball"); X losehp (rnd (20), "iron ball"); X } X placebc (1); X } X selftouch ("Falling, you"); X } X } X } X else { /* trapdoor or level_tele */ X do { X u.ux = rnd (COLNO - 1); X u.uy = rn2 (ROWNO); X } while (levl[u.ux][u.uy].typ != ROOM || X m_at (u.ux, u.uy)); X if (Punished) { X if (uwep != uball && !up /* %% */ && rn2 (5)) { X pline ("The iron ball falls on your head."); X losehp (rnd (25), "iron ball"); X } X placebc (1); X } X selftouch ("Falling, you"); X } X (void) inshop (); X#ifdef TRACK X initrack (); X#endif TRACK X X losedogs (); X flags.nscrinh = 0; X setsee (); X docrt (); X pickup (); X read_engr_at (u.ux, u.uy); X} X Xdonull () X{ X return (1); /* Do nothing, but let other things happen */ X} X Xstruct monst *bhit (), *boomhit (); X Xdothrow () X{ X register struct obj *obj; X register struct monst *mon; X register tmp; X X obj = getobj ("#)", "throw"); /* it is also possible to throw food */ X /* (or jewels, or iron balls ... ) */ X if (!obj || !getdir ()) X return (0); X if (obj -> owornmask & (W_ARMOR | W_RING)) { X pline ("You can't throw something you are wearing"); X return (0); X } X if (obj == uwep) { X if (obj -> cursed) { X pline ("Your weapon is welded to your hand"); X return (1); X } X if (obj -> quan > 1) X setuwep (splitobj (obj, 1)); X else X setuwep ((struct obj *) 0); X } X else X if (obj -> quan > 1) X (void) splitobj (obj, 1); X freeinv (obj); X if (u.uswallow) { X mon = u.ustuck; X bhitpos.x = mon -> mx; X bhitpos.y = mon -> my; X } X else X if (obj -> otyp == BOOMERANG) { X mon = boomhit (u.dx, u.dy); X /* boomhit delivers -1 if the thing was caught */ X if ((int) mon == -1) { X (void) addinv (obj); X return (1); X } X } X else X mon = bhit (u.dx, u.dy, X (!Punished || obj != uball) ? 8 : X !u.ustuck ? 5 : 1, X obj -> olet); X if (mon) { X /* awake monster if sleeping */ X wakeup (mon); X X if (obj -> olet == WEAPON_SYM) { X tmp = -1 + u.ulevel + mon -> data -> ac + abon (); X if (obj -> otyp < ROCK) { X if (!uwep || X uwep -> otyp != obj -> otyp + (BOW - ARROW)) X tmp -= 4; X else { X tmp += uwep -> spe; X } X } X else X if (obj -> otyp == BOOMERANG) X tmp += 4; X tmp += obj -> spe; X if (u.uswallow || tmp >= rnd (20)) { X if (hmon (mon, obj, 1) == TRUE) { X /* mon still alive */ X#ifndef NOWORM X cutworm (mon, bhitpos.x, bhitpos.y, obj -> otyp); X#endif NOWORM X } X else X mon = 0; X /* weapons thrown disappear sometimes */ X if (obj -> otyp < BOOMERANG && rn2 (3)) { X /* check bill; free */ X obfree (obj, (struct obj *) 0); X return (1); X } X } X else X miss (objects[obj -> otyp].oc_name, mon); X } X else X if (obj -> otyp == HEAVY_IRON_BALL) { X tmp = -1 + u.ulevel + mon -> data -> ac + abon (); X if (!Punished || obj != uball) X tmp += 2; X if (u.utrap) X tmp -= 2; X if (u.uswallow || tmp >= rnd (20)) { X if (hmon (mon, obj, 1) == FALSE) X mon = 0; /* he died */ X } X else X miss ("iron ball", mon); X } X else { X if (cansee (bhitpos.x, bhitpos.y)) X pline ("You miss %s.", monnam (mon)); X else X pline ("You miss it."); X if (obj -> olet == FOOD_SYM && mon -> data -> mlet == 'd') X if (tamedog (mon, obj)) X return (1); X if (obj -> olet == GEM_SYM && mon -> data -> mlet == 'u') { X if (obj -> dknown && objects[obj -> otyp].oc_name_known) { X if (objects[obj -> otyp].g_val > 0) { X u.uluck += 5; X goto valuable; X } X else { X pline ("%s is not interested in your junk.", X Monnam (mon)); X } X } X else { /* value unknown to @ */ X u.uluck++; X valuable: X pline ("%s graciously accepts your gift.", X Monnam (mon)); X mpickobj (mon, obj); X rloc (mon); X return (1); X } X } X } X } X obj -> ox = bhitpos.x; X obj -> oy = bhitpos.y; X obj -> nobj = fobj; X fobj = obj; X /* prevent him from throwing articles to the exit and escaping */ X /* subfrombill(obj); */ X stackobj (obj); X if (Punished && obj == uball && X (bhitpos.x != u.ux || bhitpos.y != u.uy)) { X freeobj (uchain); X unpobj (uchain); X if (u.utrap) { X if (u.utraptype == TT_PIT) X pline ("The ball pulls you out of the pit!"); X else { X register int side = X rn2 (3) ? LEFT_SIDE : RIGHT_SIDE; X pline ("The ball pulls you out of the bear trap."); X pline ("Your %s leg is severely damaged.", X (side == LEFT_SIDE) ? "left" : "right"); X Wounded_legs |= side + rnd (1000); X losehp (2, "thrown ball"); X } X u.utrap = 0; X } X unsee (); X uchain -> nobj = fobj; X fobj = uchain; X u.ux = uchain -> ox = bhitpos.x - u.dx; X u.uy = uchain -> oy = bhitpos.y - u.dy; X setsee (); X (void) inshop (); X } X if (cansee (bhitpos.x, bhitpos.y)) X prl (bhitpos.x, bhitpos.y); X return (1); X} X Xgetdir () X{ X char buf[2]; X pline ("What direction?"); X buf[0] = readchar (); X buf[1] = 0; X return (movecm (buf)); X} X X/* split obj so that it gets size num */ X/* remainder is put in the object structure delivered by this call */ Xstruct obj * Xsplitobj (obj, num) Xregister struct obj *obj; Xregister int num; X{ X register struct obj *otmp; X otmp = newobj (0); X *otmp = *obj; /* copies whole structure */ X otmp -> o_id = flags.ident++; X otmp -> onamelth = 0; X obj -> quan = num; X obj -> owt = weight (obj); X otmp -> quan -= num; X otmp -> owt = weight (otmp); /* -= obj->owt ? */ X obj -> nobj = otmp; X if (obj -> unpaid) X splitbill (obj, otmp); X return (otmp); X} X Xchar * Xlowc (str) Xregister char *str; X{ X static char buf[2]; 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 Xchar * Xunctrl (str) Xregister char *str; X{ X static char buf[2]; X if (*str >= ('A' & 037) && *str <= ('Z' & 037)) X *buf = *str + 0140; X else X *buf = *str; X buf[1] = 0; X return (buf); X} --burp-- sed 's/^X//' << '--burp--' > hack.invent.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include "hack.h" X#include <stdio.h> Xextern struct obj *splitobj (); Xextern char morc; X#ifndef NOWORM X#include "def.wseg.h" X Xextern struct wseg *wsegs[32]; X#endif NOWORM X Xstruct obj * Xaddinv (object) Xregister struct obj *object; X{ X register struct obj *otmp, *potmp; X X if (!invent) { /* empty list */ X invent = object; X object -> nobj = 0; X } X else { X potmp = 0; X otmp = invent; X /* search for matching type or greater */ X while ((otmp) && (otmp -> olet < object -> olet)) { X potmp = otmp; X otmp = otmp -> nobj; X } X if (!otmp) { /* ran off end */ X potmp -> nobj = object; X object -> nobj = 0; X } X else if (otmp -> olet > object -> olet) { /* new obj type */ X if (!potmp) { /* top of list */ X object -> nobj = invent; X invent = object; X } X else { X object -> nobj = otmp; X potmp -> nobj = object; X } X } X else { /* must be == */ X while ((otmp) && (otmp -> olet == object -> olet)) { X if (merged (otmp, object, 0)) X return (otmp); X else { X potmp = otmp; X otmp = otmp -> nobj; X } X } X /* not merged - insert after */ X object -> nobj = otmp; X potmp -> nobj = object; X } X } X return (object); X} X Xuseup (obj) Xregister struct obj *obj; X{ X if (obj -> quan > 1) { X obj -> quan--; X obj -> owt = weight (obj); X } X else { X setnotworn (obj); X freeinv (obj); X obfree (obj, (struct obj *) 0); X } X} X Xfreeinv (obj) Xregister struct obj *obj; X{ X register struct obj *otmp; X if (obj == invent) X invent = invent -> nobj; X else { X for (otmp = invent; otmp -> nobj != obj; otmp = otmp -> nobj) X if (!otmp -> nobj) X panic ("freeinv"); X otmp -> nobj = obj -> nobj; X } X} X X/* destroy object in fobj chain (if unpaid, it remains on the bill) */ Xdelobj (obj) Xregister struct obj *obj; X{ X freeobj (obj); X unpobj (obj); X obfree (obj, (struct obj *) 0); X} X X/* unlink obj from chain starting with fobj */ Xfreeobj (obj) Xregister struct obj *obj; X{ X register struct obj *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 ("error in freeobj"); X otmp -> nobj = obj -> nobj; X } X} X X/* Note: freegold throws away its argument! */ Xfreegold (gold) Xregister struct gen *gold; X{ X register struct gen *gtmp; X X if (gold == fgold) X fgold = gold -> ngen; X else { X for (gtmp = fgold; gtmp -> ngen != gold; gtmp = gtmp -> ngen) X if (!gtmp) X panic ("error in freegold"); X gtmp -> ngen = gold -> ngen; X } X free ((char *) gold); X} X Xdeltrap (trap) Xregister struct gen *trap; X{ X register struct gen *gtmp; X X if (trap == ftrap) X ftrap = ftrap -> ngen; X else { X for (gtmp = ftrap; gtmp -> ngen != trap; gtmp = gtmp -> ngen); X gtmp -> ngen = trap -> ngen; X } X free ((char *) trap); X} X Xstruct wseg *m_atseg; X Xstruct monst * Xm_at (x, y) Xregister x, y; X{ X register struct monst *mtmp; X#ifndef NOWORM X register struct wseg *wtmp; X#endif NOWORM X X m_atseg = 0; X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) { X if (mtmp -> mx == x && mtmp -> my == y) X return (mtmp); X#ifndef NOWORM X if (mtmp -> wormno) { X for (wtmp = wsegs[mtmp -> wormno]; wtmp; wtmp = wtmp -> nseg) X if (wtmp -> wx == x && wtmp -> wy == y) { X m_atseg = wtmp; X return (mtmp); X } X } X#endif NOWORM X } X return (0); X} X Xstruct obj * Xo_at (x, y) Xregister x, y; X{ X register struct obj *otmp; X X for (otmp = fobj; otmp; otmp = otmp -> nobj) X if (otmp -> ox == x && otmp -> oy == y) X return (otmp); X return (0); X} X Xstruct obj * Xsobj_at (n, x, y) Xregister n, x, y; X{ X register struct obj *otmp; X X for (otmp = fobj; otmp; otmp = otmp -> nobj) X if (otmp -> ox == x && otmp -> oy == y && otmp -> otyp == n) X return (otmp); X return (0); X} X Xcarried (obj) Xregister struct obj *obj; X{ X register struct obj *otmp; X for (otmp = invent; otmp; otmp = otmp -> nobj) X if (otmp == obj) X return (1); X return (0); X} X Xstruct obj * Xo_on (id, objchn) Xunsigned int id; Xregister struct obj *objchn; X{ X while (objchn) { X if (objchn -> o_id == id) X return (objchn); X objchn = objchn -> nobj; X } X return ((struct obj *) 0); X} X Xstruct gen * Xg_at (x, y, ptr) Xregister x, y; Xregister struct gen *ptr; X{ X while (ptr) { X if (ptr -> gx == x && ptr -> gy == y) X return (ptr); X ptr = ptr -> ngen; X } X return (0); X} X X/* getobj returns: X struct obj *xxx: object to do something with. X 0 error return: no object. X -1 explicitly no object (as in w-). X*/ Xstruct obj * Xgetobj (let, word) Xregister char *let, *word; X{ X register struct obj *otmp; X register char ilet, ilet1, ilet2; X char buf[BUFSZ]; X char lets[BUFSZ]; X register int foo = 0, foo2, cnt; X register char *bp = buf; X xchar allowcnt = 0; /* 0, 1 or 2 */ X boolean allowgold = FALSE; X boolean allowall = FALSE; X boolean allownone = FALSE; X xchar foox = 0; X X if (*let == '0') X let++, allowcnt = 1; X if (*let == '$') X let++, allowgold = TRUE; X if (*let == '#') X let++, allowall = TRUE; X if (*let == '-') X let++, allownone = TRUE; X if (allownone) X *bp++ = '-'; X if (allowgold) X *bp++ = '$'; X if (bp[-1] == '-') X *bp++ = ' '; X X ilet = 'a'; X for (otmp = invent; otmp; otmp = otmp -> nobj) { X if (!*let || index (let, otmp -> olet)) { X bp[foo++] = ilet; X /* ugly check: remove inappropriate things */ X if ((!strcmp (word, "take off") && X !(otmp -> owornmask & (W_ARMOR - W_ARM2))) X || (!strcmp (word, "wear") && X (otmp -> owornmask & (W_ARMOR | W_RING))) X || (!strcmp (word, "wield") && X (otmp -> owornmask & W_WEP))) { X foo--; X foox++; X } X } X if (ilet == 'z') X ilet = 'A'; X else X ilet++; X } X bp[foo] = 0; X if (foo == 0 && bp > buf && bp[-1] == ' ') X *--bp = 0; X (void) strcpy (lets, bp); /* necessary since we destroy buf */ X if (foo > 5) { /* compactify string */ X foo = foo2 = 1; X ilet2 = bp[0]; X ilet1 = bp[1]; X while (ilet = bp[++foo2] = bp[++foo]) { X if (ilet == ilet1 + 1) { X if (ilet1 == ilet2 + 1) X bp[foo2 - 1] = ilet1 = '-'; X else X if (ilet2 == '-') { X bp[--foo2] = ++ilet1; X continue; X } X } X ilet2 = ilet1; X ilet1 = ilet; X } X } X if (!foo && !allowall && !allowgold && !allownone) { X pline ("You don't have anything %sto %s.", X foox ? "else " : "", word); X return (0); X } X for (;;) { X if (!buf[0]) X pline ("What do you want to %s [*]? ", word); X else X pline ("What do you want to %s [%s or ?*]? ", X word, buf); X X cnt = 0; X ilet = readchar (); X while (digit (ilet) && allowcnt) { X cnt = 10 * cnt + (ilet - '0'); X allowcnt = 2; /* signal presence of cnt */ X ilet = readchar (); X } X if (digit (ilet)) { X pline ("No count allowed with this command."); X continue; X } X if (ilet == '\033' || ilet == ' ' || ilet == '\n') X return ((struct obj *) 0); X if (ilet == '-') { X return ((struct obj *) (allownone ? -1 : 0)); X } X if (ilet == '$') { X if (!allowgold) { X pline ("You cannot %s gold.", word); X continue; X } X otmp = newobj (0); X /* should set o_id etc. but otmp will be freed soon */ X otmp -> olet = '$'; X if (allowcnt == 2 && cnt < u.ugold) X u.ugold -= cnt; X else { X cnt = u.ugold; X u.ugold = 0; X } X flags.botl = 1; X otmp -> quan = cnt; X return (otmp); X } X if (ilet == '?') { X doinv (lets); X if (!(ilet = morc)) X continue; X /* he typed a letter (not a space) to more() */ X } X else X if (ilet == '*') { X doinv (""); X if (!(ilet = morc)) X continue; X /* ... */ X } X if (ilet >= 'A' && ilet <= 'Z') X ilet += 'z' - 'A' + 1; X ilet -= 'a'; X for (otmp = invent; otmp && ilet; ilet--, otmp = otmp -> nobj); X if (!otmp) { X pline ("You don't have that object."); X continue; X } X if (cnt < 0 || otmp -> quan < cnt) { X pline ("You don't have that many! [You have %d]" X ,otmp -> quan); X continue; X } X break; X } X if (!allowall && let && !index (let, otmp -> olet)) { X pline ("That is a silly thing to %s.", word); X return (0); X } X if (allowcnt == 2) { /* cnt given */ X if (cnt == 0) X return (0); X if (cnt != otmp -> quan) { X register struct obj *obj; X obj = splitobj (otmp, cnt); X if (otmp == uwep) X setuwep (obj); X } X } X return (otmp); X} X Xckunpaid (otmp) Xregister struct obj *otmp; X{ X return (otmp -> unpaid); X} X X/* interactive version of getobj */ X/* used for Drop and Identify */ Xggetobj (word, fn, max) Xchar *word; Xint (*fn) (), max; X{ X char buf[BUFSZ]; X register char *ip; X register char sym; X register int oletct = 0, iletct = 0; X register boolean allflag = FALSE; X char olets[20], ilets[20]; X int (*ckfn) () = (int (*) ()) 0; X if (!invent) { X pline ("You have nothing to %s.", word); X return (0); X } X else { X register struct obj *otmp = invent; X register int uflg = 0; X X ilets[0] = 0; X while (otmp) { X if (!index (ilets, otmp -> olet)) { X ilets[iletct++] = otmp -> olet; X ilets[iletct] = 0; X } X if (otmp -> unpaid) X uflg = 1; X otmp = otmp -> nobj; X } X ilets[iletct++] = ' '; X if (uflg) X ilets[iletct++] = 'u'; X ilets[iletct++] = 'a'; X ilets[iletct] = 0; X } X pline ("What kinds of thing do you want to %s? [%s] ", X word, ilets); X getlin (buf); X ip = buf; X olets[0] = 0; X while (sym = *ip++) { X if (sym == ' ') X continue; X if (sym == 'a') X allflag = TRUE; X else X if (sym == 'u') X ckfn = ckunpaid; X else X if (index ("!%?[()=*/\"0", sym)) { X if (!index (olets, sym)) { X olets[oletct++] = sym; X olets[oletct] = 0; X } X } X else X pline ("You don't have any %c's.", sym); X } X return askchain (invent, olets, allflag, fn, ckfn, max); X} X X/* Walk through the chain starting at objchn and ask for all objects X with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL) X whether the action in question (i.e., fn) has to be performed. X If allflag then no questions are asked. Max gives the max nr of X objects treated. X */ Xaskchain (objchn, olets, allflag, fn, ckfn, max) Xstruct obj *objchn; Xregister char *olets; Xint allflag; Xint (*fn) (), (*ckfn) (); Xint max; X{ X register struct obj *otmp, *otmp2; X register char sym, ilet; X register int cnt = 0; X ilet = 'a' - 1; X for (otmp = objchn; otmp; otmp = otmp2) { X if (ilet == 'z') X ilet = 'A'; X else X ilet++; X otmp2 = otmp -> nobj; X if (olets && *olets && !index (olets, otmp -> olet)) X continue; X if (ckfn && !(*ckfn) (otmp)) X continue; X if (!allflag) { X prname (otmp, ilet, 1); X addtopl (" (ynaq)? "); X sym = readchar (); X } X else X sym = 'y'; X X switch (sym) { X case 'a': X allflag = 1; X case 'y': X cnt += (*fn) (otmp); X if (--max == 0) X goto ret; X case 'n': X default: X break; X case 'q': X goto ret; X } X } X pline (cnt ? "That was all." : "No applicable objects."); Xret: X if (!flags.echo) X echo (OFF); X return (cnt); X} X Xobj_to_let (obj) Xregister struct obj *obj; X{ X register struct obj *otmp; X register char ilet = 'a'; X X for (otmp = invent; otmp && otmp != obj; otmp = otmp -> nobj) X if (++ilet > 'z') X ilet = 'A'; X return (otmp ? ilet : 0); X} X Xprinv (obj) Xregister struct obj *obj; X{ X prname (obj, obj_to_let (obj), 1); X} X Xprname (obj, let, onelin) Xregister struct obj *obj; Xregister char let; X{ X char li[BUFSZ]; X X (void) sprintf (li, " %c - %s.", let, doname (obj)); X switch (onelin) { X case 1: X pline (li + 1); X break; X case 0: X puts (li + 1); X break; X case -1: X cl_end (); X fputs (li, stdout); X curx += strlen (li); X } X} X Xdotypeinv () X{ X char c[BUFSZ]; X char stuff[BUFSZ]; X register int stct; X register struct obj *otmp = invent; X register char ilet; X X if (!invent) { X pline ("You aren't carrying anything."); X return; X } X else { X stuff[0] = 0; X stct = 0; X while (otmp) { X if (!index (stuff, otmp -> olet)) { X stuff[stct++] = otmp -> olet; X stuff[stct] = 0; X } X otmp = otmp -> nobj; X } X stuff[stct] = 0; X pline ("What objects do you want an inventory of [%s]? ",stuff); X getlin (c); X if ((c[0] == '\033') || (c[0] == '\0')) X return; X stct = 0; X ilet = 'a'; X for (otmp = invent; otmp; otmp = otmp -> nobj) { X if (index (c, otmp -> olet)) X stuff[stct++] = ilet; X if (ilet == 'z') X ilet = 'A'; X else X ilet++; X } X stuff[stct] = '\0'; X doinv (stuff); X } X} X Xddoinv () X{ X doinv ((char *) 0); X return (0); X} X X/* called with "": all objects in inventory; with 0: also usedup ones */ X/* otherwise: all objects with (serial) letter in lets */ Xdoinv (lets) Xregister char *lets; X{ X register struct obj *otmp; X register char ilet = 'a'; X int ct = 0; X int maxlth = 0; X int lth; X int curline; X X if (!invent) { X pline ("Not carrying anything"); X if (lets) X return; X } X if (!flags.oneline) { X if (!lets || !*lets) X for (otmp = invent; otmp; otmp = otmp -> nobj) X ct++; X else X ct = strlen (lets); X if (ct > 1 && ct < ROWNO && (lets || !inshop ())) { X for (otmp = invent; otmp; otmp = otmp -> nobj) { X if (!lets || !*lets || index (lets, ilet)) { X lth = strlen (doname (otmp)); X if (lth > maxlth) X maxlth = lth; X } X if (++ilet > 'z') X ilet = 'A'; X } X ilet = 'a'; X lth = COLNO - maxlth - 7; X if (lth < 10) X goto clrscr; X home (); X cl_end (); X flags.topl = 0; X ct = 0; X for (otmp = invent; otmp; otmp = otmp -> nobj) { X if (!lets || !*lets || index (lets, ilet)) { X curs (lth, ++ct); X prname (otmp, ilet, -1); X } X if (++ilet > 'z') X ilet = 'A'; X } X curs (lth, ct + 1); X cl_end (); X cmore (); /* sets morc */ X /* test whether morc is a reasonable answer */ X if (lets && *lets && !index (lets, morc)) X morc = 0; X X home (); X cl_end (); X docorner (lth, ct); X return; X } X } Xclrscr: X if (ct == 1) { X for (otmp = invent; otmp; otmp = otmp -> nobj) { X if (!lets || !*lets || index (lets, ilet)) X prname (otmp, ilet, 1); X if (++ilet > 'z') X ilet = 'A'; X } X standoutbeg (); X printf ("--More--"); X standoutend (); X if ((morc = readchar ()) == ' ') X morc = 0; X return; X } X else { X cls (); X curline = 1; X for (otmp = invent; otmp; otmp = otmp -> nobj) { X if (!lets || !*lets || index (lets, ilet)) { X curs (1, curline); X cl_end (); X prname (otmp, ilet, 0); X curline++; X if (curline >= ROWNO + 1) { X curs (1, curline); X cl_end (); X curs (1, ROWNO + 2); X cl_end (); X standoutbeg (); X printf ("---More---"); X standoutend (); X if ((morc = readchar ()) != ' ') { X docrt (); X return; X } X curline = 1; X } X } X if (++ilet > 'z') X ilet = 'A'; X } X curs (1, curline); X cl_eos (); X /* tell doinvbill whether we cleared the screen */ X if (!lets) { X curs (1, ROWNO + 2); X standoutbeg (); X printf ("---More---"); X standoutend (); X if ((morc = readchar ()) != ' ') { X docrt (); X return; X } X else X morc = 0; X if (!doinvbill (1)) { X docrt (); X return; X } X else X printf("\r\n"); X } X curs (1, ROWNO + 2); X standoutbeg (); X printf ("Hit space to continue..."); X standoutend (); X if ((morc = readchar ()) == ' ') X morc = 0; X docrt (); X } X} X Xstackobj (obj) Xregister struct obj *obj; X{ X register struct obj *otmp = fobj; X for (otmp = fobj; otmp; otmp = otmp -> nobj) X if (otmp != obj) X if (otmp -> ox == obj -> ox && otmp -> oy == obj -> oy && X merged (obj, otmp, 1)) X return; X} X X/* merge obj with otmp and delete obj if types agree */ Xmerged (otmp, object, lose) Xregister struct obj *otmp, *object; X{ X if (otmp -> otyp == object -> otyp X && object -> unpaid == otmp -> unpaid X && object -> spe == otmp -> spe X && object -> known == otmp -> known X && object -> dknown == otmp -> dknown X && object -> cursed == otmp -> cursed X && ((object -> olet == WEAPON_SYM X && object -> otyp < BOOMERANG) X || index ("%?!*", otmp -> olet))) { X otmp -> quan += object -> quan; X otmp -> owt += object -> owt; X if (lose) X freeobj (object); X obfree (object, otmp); /* free(object), bill->otmp */ X return (1); X } X else X return (0); X} X Xdoprwep () X{ X if (!uwep) X pline ("You are empty handed."); X else X prinv (uwep); X return (0); X} X Xdoprarm () X{ X if (!uarm && !uarmg && !uarms && !uarmh) X pline ("You are not wearing any armor."); X else { X char lets[6]; X register int ct = 0; X X if (uarm) X lets[ct++] = obj_to_let (uarm); X if (uarm2) X lets[ct++] = obj_to_let (uarm2); X if (uarmh) X lets[ct++] = obj_to_let (uarmh); X if (uarms) X lets[ct++] = obj_to_let (uarms); X if (uarmg) X lets[ct++] = obj_to_let (uarmg); X lets[ct] = 0; X doinv (lets); X } X return (0); X} X Xdoprring () X{ X if (!uleft && !uright) X pline ("You are not wearing any rings."); X else { X char lets[3]; X register int ct = 0; X X if (uleft) X lets[ct++] = obj_to_let (uleft); X if (uright) X lets[ct++] = obj_to_let (uright); X lets[ct] = 0; X doinv (lets); X } X return (0); X} X Xdigit (c) Xchar c; X{ X return (c >= '0' && c <= '9'); X} --burp-- sed 's/^X//' << '--burp--' > hack.main.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include <stdio.h> X#include <signal.h> X#include <errno.h> X#include "hack.h" X X#define gpid ((int) getpid()) Xlong time (); X Xextern char *getlogin (); Xextern char plname[PL_NSIZ], pl_character[PL_CSIZ]; Xextern char *getenv (); X Xint (*afternmv) (); Xint done1 (); Xint hangup (); X Xchar safelock[] = "safelock"; Xxchar locknum; /* max num of players */ Xchar SAVEF[PL_NSIZ + 5] = "save/"; Xchar perm[] = "perm"; Xchar *hname; /* name of the game (argv[0] of call) */ Xchar obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */ X Xextern char *nomovemsg; Xextern long wailmsg; X Xmain (argc, argv) Xint argc; Xchar *argv[]; X{ X#ifdef NEWS X int nonews = 0; X#endif NEWS X int fd; X char *dir; X X hname = argv[0]; X X /* X * See if we must change directory to the playground. X * (Perhaps hack runs suid and playground is inaccessible X * for the player.) X * The environment variable HACKDIR is overridden by a X * -d command line option. X */ X dir = getenv ("HACKDIR"); X if (argc > 1 && !strncmp (argv[1], "-d", 2)) { X argc--; X argv++; X dir = argv[0] + 2; X if (*dir == '=' || *dir == ':') X dir++; X if (!*dir && argc > 1) { X argc--; X argv++; X dir = argv[0]; X } X if (!*dir) X error ("Flag -d must be followed by a directory name."); X } X X /* X * Now we know the directory containing 'record' and X * may do a prscore(). X */ X if (argc > 1 && !strncmp (argv[1], "-s", 2)) { X if (dir) X chdirx (dir); X prscore (argc, argv); X exit (0); X } X X /* X * It seems he really wants to play. Find the creation date of X * this game so as to avoid restoring outdated savefiles. X */ X gethdate (hname); X X /* X * We cannot do chdir earlier, otherwise gethdate will fail. X */ X if (dir) X chdirx (dir); X X /* X * Who am i? Perhaps we should use $USER instead? X */ X (void) strncpy (plname, getlogin (), sizeof (plname) - 1); X X /* X * Process options. X */ X while (argc > 1 && argv[1][0] == '-') { X argv++; X argc--; X switch (argv[0][1]) { X#ifdef WIZARD X case 'w': X if (!strcmp (getlogin (), WIZARD)) X wizard = TRUE; X else X printf ("Sorry.\n"); X break; X#endif WIZARD X#ifdef NEWS X case 'n': X nonews++; X break; X#endif NEWS X case 'u': X if (argv[0][2]) X (void) strncpy (plname, argv[0] + 2, sizeof (plname) - 1); X else X if (argc > 1) { X argc--; X argv++; X (void) strncpy (plname, argv[0], sizeof (plname) - 1); X } X else X printf ("Player name expected after -u\n"); X break; X default: X printf ("Unknown option: %s\n", *argv); X } X } X X if (argc > 1) X locknum = atoi (argv[1]); X#ifdef WIZARD X if (wizard) X (void) strcpy (plname, "wizard"); X else X#endif WIZARD X if (!*plname || !strncmp (plname, "player", 4)) X askname (); X plnamesuffix (); /* strip suffix from name */ X X setbuf (stdout, obuf); X (void) srand ((int) time ((long *) 0)); X startup (); X cls (); X (void) signal (SIGHUP, hangup); X#ifdef WIZARD X if (!wizard) { X#endif WIZARD X (void) signal (SIGQUIT, SIG_IGN); X (void) signal (SIGINT, SIG_IGN); X if (locknum) X lockcheck (); X else X (void) strcpy (lock, plname); X#ifdef WIZARD X } X else { X register char *sfoo; X (void) strcpy (lock, plname); X if (sfoo = getenv ("MAGIC")) X while (*sfoo) { X switch (*sfoo++) { X case 'n': X (void) srand (*sfoo++); X break; X } X } X if (sfoo = getenv ("GENOCIDED")) { X if (*sfoo == '!') { X extern struct permonst mons[CMNUM + 2]; X extern char genocided[], fut_geno[]; X register struct permonst *pm = mons; X register char *gp = genocided; X X while (pm < mons + CMNUM + 2) { X if (!index (sfoo, pm -> mlet)) X *gp++ = pm -> mlet; X pm++; X } X *gp = 0; X } X else X (void) strcpy (genocided, sfoo); X (void) strcpy (fut_geno, genocided); X } X } X#endif WIZARD X u.uhp = 1; /* prevent RIP on early quits */ X u.ux = FAR; /* prevent nscr() */ X (void) strcat (SAVEF, plname); X if ((fd = open (SAVEF, 0)) >= 0 && (uptodate (fd) || unlink (SAVEF) == 666)) { X (void) signal (SIGINT, done1); X puts ("Restoring old save file..."); X (void) fflush (stdout); X dorecover (fd); X flags.move = 0; X } X else { X#ifdef NEWS X if (!nonews) X if ((fd = open (NEWS, 0)) >= 0) X outnews (fd); X#endif NEWS X flags.ident = 1; X init_objects (); X u_init (); X (void) signal (SIGINT, done1); X glo (1); X mklev (); X u.ux = xupstair; X u.uy = yupstair; X (void) inshop (); X setsee (); X flags.botlx = 1; X makedog (); X seemons (); X docrt (); X pickup (); X read_engr_at (u.ux, u.uy); /* superfluous ? */ X flags.move = 1; X flags.cbreak = ON; X flags.echo = OFF; X } X setftty (); X#ifdef TRACK X initrack (); X#endif TRACK X for (;;) { X if (flags.move) { X#ifdef TRACK X settrack (); X#endif TRACK X if (moves % 2 == 0 || (!(Fast & ~INTRINSIC) && (!Fast || rn2 (3)))) { X extern struct monst *makemon (); X movemon (); X if (!rn2 (70)) X (void) makemon ((struct permonst *) 0, 0, 0); X } X if (Glib) X glibr (); X timeout (); X ++moves; X if (u.uhp < 1) { X pline ("You die..."); X done ("died"); X } X if (u.uhp * 10 < u.uhpmax && moves - wailmsg > 50) { X wailmsg = moves; X if (u.uhp == 1) X pline ("You hear the wailing of the Banshee..."); X else X pline ("You hear the howling of the CwnAnnwn..."); X } X if (u.uhp < u.uhpmax) { X if (u.ulevel > 9) { X if (Regeneration || !(moves % 3)) { X flags.botl = 1; X u.uhp += rnd ((int) u.ulevel - 9); X if (u.uhp > u.uhpmax) X u.uhp = u.uhpmax; X } X } X else X if (Regeneration || (!(moves % (22 - u.ulevel * 2)))) { X flags.botl = 1; X u.uhp++; X } X } X if (Teleportation && !rn2 (85)) X tele (); X if (Searching && multi >= 0) X (void) dosearch (); X gethungry (); X invault (); X } X if (multi < 0) { X if (!++multi) { X pline (nomovemsg ? nomovemsg : "You can move again."); X nomovemsg = 0; X if (afternmv) X (*afternmv) (); X afternmv = 0; X } X } X flags.move = 1; X find_ac (); X#ifndef QUEST X if (!flags.mv || Blind) X#endif QUEST X { X seeobjs (); X seemons (); X nscr (); X } X if (flags.botl || flags.botlx) X bot (); X if (multi > 0) { X#ifdef QUEST X if (flags.run >= 4) X finddir (); X#endif QUEST X lookaround (); X if (!multi) { /* lookaround may clear multi */ X flags.move = 0; X continue; X } X if (flags.mv) { X if (multi < COLNO && !--multi) X flags.mv = flags.run = 0; X domove (); X } X else { X --multi; X rhack (save_cm); X } X } X else X if (multi == 0) X rhack ((char *) 0); X } X} X Xlockcheck () X{ X extern int errno; X register int i, fd; X X /* we ignore QUIT and INT at this point */ X if (link (perm, safelock) == -1) { X perror ("safelock"); X error ("Cannot link safelock. (Try again or rm safelock.)"); X } X X for (i = 0; i < locknum; i++) { X lock[0] = 'a' + i; X if ((fd = open (lock, 0)) == -1) { X if (errno == ENOENT) X goto gotlock; /* no such file */ X (void) unlink (safelock); X perror (lock); X error ("Cannot open %s", lock); X } X (void) close (fd); X } X (void) unlink (safelock); X error ("Too many hacks running now."); Xgotlock: X fd = creat (lock, FMASK); X if (fd == -1) { X error ("cannot creat lock file."); X } X else { X int pid; X X pid = gpid; X if (write (fd, (char *) & pid, sizeof(int)) != sizeof(int)) { X error ("cannot write lock"); X } X if (close (fd) == -1) { X error ("cannot close lock"); X } X } X if (unlink (safelock) == -1) { X error ("Cannot unlink safelock"); X } X} X X/*VARARGS1*/ Xerror (s, a1, a2, a3, a4) Xchar *s, *a1, *a2, *a3, *a4; X{ X printf ("Error: "); X printf (s, a1, a2, a3, a4); X (void) putchar ('\n'); X exit (1); X} X Xglo (foo) Xregister foo; X{ X /* construct the string xlock.n */ X register char *tf; X X tf = lock; X while (*tf && *tf != '.') X tf++; X (void) sprintf (tf, ".%d", foo); X} X X/* X * plname is filled either by an option (-u Player or -uPlayer) or X * explicitly (-w implies wizard) or by askname. X * It may still contain a suffix denoting pl_character. X */ Xaskname () X{ X register int c, ct; X printf ("\nWho are you? "); X ct = 0; X while ((c = getchar ()) != '\n') { X if (c == EOF) X error ("End of input\n"); X if (c != '-') X if (c < 'A' || (c > 'Z' && c < 'a') || c > 'z') X c = '_'; X if (ct < sizeof (plname) - 1) X plname[ct++] = c; X } X plname[ct] = 0; X if (ct == 0) X askname (); X#ifdef QUEST X else X printf ("Hello %s, welcome to quest!\n", plname); X#else X else X printf ("Hello %s, welcome to hack!\n", plname); X#endif QUEST X} X Ximpossible () X{ X pline ("Program in disorder - perhaps you'd better Quit"); X} X X#ifdef NEWS Xint stopnews; X Xstopnws () X{ X (void) signal (SIGINT, SIG_IGN); X stopnews++; X} X Xoutnews (fd) Xint fd; X{ X int (*prevsig) (); X char ch; X prevsig = signal (SIGINT, stopnws); X while (!stopnews && read (fd, &ch, 1) == 1) X (void) putchar (ch); X (void) putchar ('\n'); X (void) fflush (stdout); X (void) close (fd); X (void) signal (SIGINT, prevsig); X /* See whether we will ask TSKCFW: he might have told us already */ X if (!stopnews && pl_character[0]) X getret (); X} X#endif NEWS X Xchdirx (dir) Xchar *dir; X{ X if (chdir (dir) < 0) { X perror (dir); X error ("Cannot chdir to %s.", dir); X } X} --burp-- sed 's/^X//' << '--burp--' > hack.o_init.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include "config.h" /* for typedefs */ X#include "def.objects.h" X Xint Xletindex (let) Xregister char let; X{ X register int i = 0; X register char ch; X while ((ch = obj_symbols[i++]) != 0) X if (ch == let) X return (i); X return (0); X} X Xinit_objects () X{ X register int i, j, first, last, sum, end; X register char let, *tmp; X /* init base; if probs given check that they add up to 100, otherwise compute probs; shuffle descriptions */ X end = sizeof (objects) / sizeof (objects[0]); X first = 0; X while (first < end) { X let = objects[first].oc_olet; X last = first + 1; X while (last < end && objects[last].oc_olet == let X && objects[last].oc_name != NULL) X last++; X i = letindex (let); X if ((!i && let != ILLOBJ_SYM) || bases[i] != 0) X panic ("initialization error"); X bases[i] = first; Xcheck: X#ifdef MKLEV X#include "hack.onames.h" X if (let == GEM_SYM) { X extern xchar dlevel; X for (j = 0; j < 9 - dlevel / 3; j++) X objects[first + j].oc_prob = 0; X first += j; X if (first >= last || first >= LAST_GEM) X printf ("Not enough gems? - first=%d last=%d j=%d LAST_GEM=%d\n", first, last, j, LAST_GEM); X for (j = first; j < LAST_GEM; j++) X objects[j].oc_prob = (20 + j - first) / (LAST_GEM - first); X } X#endif MKLEV X sum = 0; X for (j = first; j < last; j++) X sum += objects[j].oc_prob; X if (sum == 0) { X for (j = first; j < last; j++) X objects[j].oc_prob = (100 + j - first) / (last - first); X goto check; X } X if (sum != 100) X#ifdef MKLEV X panic X#else X error X#endif MKLEV X ("init-prob error for %c", let); X /* shuffling is rather meaningless in mklev, but we must update last anyway */ X if (objects[first].oc_descr != NULL && let != TOOL_SYM) { X /* shuffle, also some additional descriptions */ X while (last < end && objects[last].oc_olet == let) X last++; X j = last; X while (--j > first) { X i = first + rn2 (j + 1 - first); X tmp = objects[j].oc_descr; X objects[j].oc_descr = objects[i].oc_descr; X objects[i].oc_descr = tmp; X } X } X first = last; X } X} X Xprobtype (let) Xregister char let; X{ X register int i = bases[letindex (let)]; X register int prob = rn2 (100); X while ((prob -= objects[i].oc_prob) >= 0) X i++; X if (objects[i].oc_olet != let || !objects[i].oc_name) X panic ("probtype(%c) error, i=%d", let, i); X return (i); X} X X#ifndef MKLEV X#define SIZE(x) (sizeof x)/(sizeof x[0]) Xextern long *alloc (); X Xsavenames (fd) Xregister fd; X{ X register int i; X unsigned len; X bwrite (fd, (char *) bases, sizeof bases); X bwrite (fd, (char *) objects, sizeof objects); X /* as long as we use only one version of Hack/Quest we need not save oc_name and oc_descr, but we must save oc_uname for all X objects */ X for (i = 0; i < SIZE (objects); i++) { X if (objects[i].oc_uname) { X len = strlen (objects[i].oc_uname) + 1; X bwrite (fd, (char *) & len, sizeof len); X bwrite (fd, objects[i].oc_uname, len); X } X } X} X Xrestnames (fd) Xregister fd; X{ X register int i; X unsigned len; X mread (fd, (char *) bases, sizeof bases); X mread (fd, (char *) objects, sizeof objects); X for (i = 0; i < SIZE (objects); i++) X if (objects[i].oc_uname) { X mread (fd, (char *) & len, sizeof len); X objects[i].oc_uname = (char *) alloc (len); X mread (fd, objects[i].oc_uname, len); X } X} X Xdodiscovered() X{ X register int i, end, curline, c; X int maxlth = 0, lth = 0; X int ct = 0; X char buf[256]; X X end = sizeof(objects) / sizeof(objects[0]); X for (i = 0; i < end; i++) { X if (((objects[i].oc_name_known) || (objects[i].oc_uname != NULL)) X && ((objects[i].oc_olet == POTION_SYM) /* could use index but */ X || (objects[i].oc_olet == SCROLL_SYM) /* i'd like to stay with the */ X || (objects[i].oc_olet == WAND_SYM) /* defined symbols */ X || (objects[i].oc_olet == RING_SYM))) { X ct++; X lth = 8; X if (objects[i].oc_name_known) X lth += (4 + strlen (objects[i].oc_name)); X if (objects[i].oc_uname != NULL) X lth += (8 + strlen (objects[i].oc_uname)); X lth += (2 + strlen(objects[i].oc_descr)); X if (lth > maxlth) X maxlth = lth; X } X } X lth = COLNO - maxlth - 1; X if (ct == 0) X pline ("You haven't discovered anything yet..."); X else if ((ct >= 1 && ct < ROWNO) && (lth >= 10)) { X home (); X cl_end (); X curline = 1; X for (i = 0; i < end; i++) { X if (((objects[i].oc_name_known) || (objects[i].oc_uname != NULL)) X && ((objects[i].oc_olet == POTION_SYM) X || (objects[i].oc_olet == SCROLL_SYM) X || (objects[i].oc_olet == WAND_SYM) X || (objects[i].oc_olet == RING_SYM))) { X curs (lth, curline); X cl_end (); X prdiscobj (i); X curline++; X } X } X curs (lth, curline); X cl_end (); X standoutbeg (); X printf ("--More--"); X standoutend (); X c = readchar (); /* any key */ X home (); X cl_end (); X docorner (lth, curline); X } X else { X curline = 1; X for (i = 0; i < end; i++) { X if (((objects[i].oc_name_known) || (objects[i].oc_uname != NULL)) X && ((objects[i].oc_olet == POTION_SYM) X || (objects[i].oc_olet == SCROLL_SYM) X || (objects[i].oc_olet == WAND_SYM) X || (objects[i].oc_olet == RING_SYM))) { X curs (1, curline); X cl_end (); X prdiscobj (i); X curline++; X ct--; X if (curline >= ROWNO + 1) { X curs (1, curline); X cl_end (); X curs (1, ROWNO + 2); X cl_end (); X standoutbeg (); X printf ("---More---"); X standoutend (); X while (((c = readchar ()) != ' ') && (c != 'q')) X bell (); X if (c == 'q') X break; X curline = 1; X } X } X } X curs (1, curline); X cl_eos (); X curs (1, ROWNO + 2); X standoutbeg(); X printf("Hit space to continue..."); X standoutend(); X while (readchar() != ' ') X bell(); X docrt (); X } X} X Xprdiscobj (i) Xint i; X{ X switch (objects[i].oc_olet) { X case POTION_SYM: X printf (" potion "); X break; X case SCROLL_SYM: X printf (" scroll "); X break; X case WAND_SYM: X printf (" wand "); X break; X case RING_SYM: X printf (" ring "); X break; X default: X printf (" toilet "); X break; X } X if (objects[i].oc_name_known) X printf ("of %s ",objects[i].oc_name); X if (objects[i].oc_uname != NULL) X printf ("called %s ",objects[i].oc_uname); X printf ("(%s)",objects[i].oc_descr); X} X#endif MKLEV --burp-- sed 's/^X//' << '--burp--' > hack.read.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include "hack.h" X Xextern struct monst *makemon (); Xint identify (); X Xdoread () X{ X register struct obj *scroll; X register boolean confused = (Confusion != 0); X register boolean known = FALSE; X X scroll = getobj ("?", "read"); X if (!scroll) X return (0); X if (!scroll -> dknown && Blind) { X pline ("Being blind, you cannot read the formula on the scroll."); X return (0); X } X if (Blind) X pline ("As you pronounce the formula on it, the scroll disappears."); X else X pline ("As you read the scroll, it disappears."); X if (confused) X pline ("Being confused, you mispronounce the magic words ... "); X X switch (scroll -> otyp) { X X case SCR_ENCHANT_ARMOR: X { X extern struct obj *some_armor (); X register struct obj *otmp = some_armor (); X if (!otmp) { X pline ("You skin glows then fades."); X strange_feeling (scroll); X return (1); X } X if (confused) { X pline ("Your %s glows silver for a moment.", X objects[otmp -> otyp].oc_name); X otmp -> rustfree = 1; X break; X } X if (otmp -> spe * 2 + objects[otmp -> otyp].a_ac > 23 && X !rn2 (3)) { X pline ("Your %s glows violently green for a while, then evaporates.", X objects[otmp -> otyp].oc_name); X useup (otmp); X break; X } X pline ("Your %s glows green for a moment.", X objects[otmp -> otyp].oc_name); X otmp -> cursed = 0; X otmp -> spe++; X break; X } X case SCR_DESTROY_ARMOR: X if (confused) { X register struct obj *otmp = some_armor (); X if (!otmp) { X pline ("Your bones itch."); X strange_feeling (scroll); X return (1); X } X pline ("Your %s glows purple for a moment.", X objects[otmp -> otyp].oc_name); X otmp -> rustfree = 0; X break; X } X if (uarm) { X pline ("Your armor turns to dust and falls to the floor!"); X useup (uarm); X } X else X if (uarmh) { X pline ("Your helmet turns to dust and is blown away!"); X useup (uarmh); X } X else X if (uarmg) { X pline ("Your gloves vanish!"); X useup (uarmg); X selftouch ("You"); X } X else { X pline ("Your skin itches."); X strange_feeling (scroll); X return (1); X } X break; X case SCR_CONFUSE_MONSTER: X if (confused) { X pline ("Your hands begin to glow purple."); X Confusion += rnd (100); X } X else { X pline ("Your hands begin to glow blue."); X u.umconf = 1; X } X break; X case SCR_SCARE_MONSTER: X { X register int ct = 0; X register struct monst *mtmp; X X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) X if (cansee (mtmp -> mx, mtmp -> my)) { X if (confused) X mtmp -> mflee = mtmp -> mfroz = X mtmp -> msleep = 0; X else X mtmp -> mflee = 1; X ct++; X } X if (!ct) { X if (confused) X pline ("You hear sad wailing in the distance."); X else X pline ("You hear maniacal laughter in the distance."); X } X break; X } X case SCR_BLANK_PAPER: X if (confused) X pline ("You see strange patterns on this scroll."); X else X pline ("This scroll seems to be blank."); X break; X case SCR_REMOVE_CURSE: X { X register struct obj *obj; X if (confused) X pline ("You feel like you need some help."); X else X pline ("You feel like someone is helping you."); X for (obj = invent; obj; obj = obj -> nobj) X if (obj -> owornmask) X obj -> cursed = confused; X if (Punished && !confused) { X Punished = 0; X freeobj (uchain); X unpobj (uchain); X free ((char *) uchain); X uball -> spe = 0; X uball -> owornmask &= ~W_BALL; X uchain = uball = (struct obj *) 0; X } X break; X } X case SCR_CREATE_MONSTER: X { X register int cnt = 1; X X if (!rn2 (73)) X cnt += rn2 (4) + 1; X if (confused) X cnt += 12; X while (cnt--) X (void) makemon (confused ? PM_ACIDBLOB : X (struct permonst *) 0, u.ux, u.uy); X break; X } X case SCR_ENCHANT_WEAPON: X if (!uwep) { X pline ("Your hands twitch."); X strange_feeling (scroll); X return (1); X } X if (confused) { X pline ("Your %s glows silver for a moment.", X objects[uwep -> otyp].oc_name); X uwep -> rustfree = 1; X } X else X if (!chwepon (scroll, 1)) X return (1); X break; X case SCR_DAMAGE_WEAPON: X if (confused) { X pline ("Your %s glows purple for a moment.", X objects[uwep -> otyp].oc_name); X uwep -> rustfree = 0; X } X else X if (!chwepon (scroll, -1)) X return (1); X break; X case SCR_TAMING: X { X register int i, j; X register int bd = confused ? 5 : 1; X register struct monst *mtmp; X X for (i = -bd; i <= bd; i++) X for (j = -bd; j <= bd; j++) X if (mtmp = m_at (u.ux + i, u.uy + j)) X (void) tamedog (mtmp, (struct obj *) 0); X break; X } X case SCR_GENOCIDE: X { X extern char genocided[], fut_geno[]; X char buf[BUFSZ]; X register struct monst *mtmp, *mtmp2; X X pline ("You have found a scroll of genocide!"); X known = TRUE; X if (confused) X *buf = u.usym; X else X do { X pline ("What monster do you want to genocide (Type the letter)? "); X getlin (buf); X } while (strlen (buf) != 1 || !letter (*buf)); X if (!index (fut_geno, *buf)) X charcat (fut_geno, *buf); X if (!index (genocided, *buf)) X charcat (genocided, *buf); X else { X pline ("Such monsters do not exist in this world."); X break; X } X for (mtmp = fmon; mtmp; mtmp = mtmp2) { X mtmp2 = mtmp -> nmon; X if (mtmp -> data -> mlet == *buf) X mondead (mtmp); X } X pline ("Wiped out all %c's.", *buf); X if (*buf == u.usym) { X killer = "scroll of genocide"; X u.uhp = -1; X } X break; X } X case SCR_LIGHT: X if (!Blind) X known = TRUE; X litroom (!confused); X break; X case SCR_TELEPORTATION: X if (confused) X level_tele (); X else { X#ifdef QUEST X register int oux = u.ux, ouy = u.uy; X tele (); X if (dist (oux, ouy) > 100) X known = TRUE; X#else QUEST X register int uroom = inroom (u.ux, u.uy); X tele (); X if (uroom != inroom (u.ux, u.uy)) X known = TRUE; X#endif QUEST X } X break; X case SCR_GOLD_DETECTION: X { X register struct gen *head = confused ? ftrap : fgold; X register struct gen *gtmp; X X if (!head) { X pline ("You feel materially poor."); X strange_feeling (scroll); X return (1); X } X else { X known = TRUE; X for (gtmp = head; gtmp; gtmp = gtmp -> ngen) X if (gtmp -> gx != u.ux || gtmp -> gy != u.uy) X goto outgoldmap; X /* only under me - no separate display required */ X if (confused) X pline ("You feel very giddy!"); X else X pline ("You notice some gold between your feet."); X break; X outgoldmap: X cls (); X for (gtmp = head; gtmp; gtmp = gtmp -> ngen) X at (gtmp -> gx, gtmp -> gy, '$'); X prme (); X if (confused) X pline ("You feel very greedy!"); X else X pline ("You feel very greedy, and sense gold!"); X more (); X docrt (); X } X break; X } X case SCR_FOOD_DETECTION: X { X register ct = 0, ctu = 0; X register struct obj *obj; X register char foodsym = confused ? POTION_SYM : FOOD_SYM; X X for (obj = fobj; obj; obj = obj -> nobj) X if (obj -> olet == FOOD_SYM) { X if (obj -> ox == u.ux && obj -> oy == u.uy) X ctu++; X else X ct++; X } X if (!ct && !ctu) { X pline ("Your nose twitches."); X strange_feeling (scroll); X return (1); X } X else X if (!ct) { X known = TRUE; X pline ("You smell %s close nearby.", X confused ? "something" : "food"); X X } X else { X known = TRUE; X cls (); X for (obj = fobj; obj; obj = obj -> nobj) X if (obj -> olet == foodsym) X at (obj -> ox, obj -> oy, FOOD_SYM); X prme (); X pline ("Your nose tingles and you smell %s!", X confused ? "something" : "food"); X more (); X docrt (); X } X break; X } X case SCR_IDENTIFY: X known = TRUE; X if (confused) X pline ("You identify this as an identify scroll."); X else X pline ("This is an identify scroll."); X useup (scroll); X objects[SCR_IDENTIFY].oc_name_known = 1; X if (!confused) X while ( X !ggetobj ("identify", identify, rn2 (5) ? 1 : rn2 (5)) X && invent X ); X return (1); X case SCR_MAGIC_MAPPING: X { X register struct rm *lev; X register int num, zx, zy; X X known = TRUE; X pline ("On this scroll %s a map!", X confused ? "was" : "is"); X for (zy = 0; zy < ROWNO; zy++) X for (zx = 0; zx < COLNO; zx++) { X if (confused && rn2 (7)) X continue; X lev = &(levl[zx][zy]); X if ((num = lev -> typ) == 0) X continue; X if (num == SCORR) { X lev -> typ = CORR; X lev -> scrsym = CORR_SYM; X } X else X if (num == SDOOR) { X lev -> typ = DOOR; X lev -> scrsym = '+'; X /* do sth in doors ? */ X } X else X if (lev -> seen) X continue; X#ifndef QUEST X if (num != ROOM) X#endif QUEST X { X lev -> seen = lev -> new = 1; X on_scr (zx, zy); X } X } X break; X } X case SCR_AMNESIA: X { X register int zx, zy; X X known = TRUE; X for (zx = 0; zx < COLNO; zx++) X for (zy = 0; zy < ROWNO; zy++) X if (!confused || rn2 (7)) X if (!cansee (zx, zy)) X levl[zx][zy].seen = 0; X docrt (); X pline ("Thinking of Maud you forget everything else."); X break; X } X case SCR_FIRE: X { X register int num; X X known = TRUE; X if (confused) { X pline ("The scroll catches fire and you burn your hands."); X losehp (1, "scroll of fire"); X } X else { X pline ("The scroll erupts in a tower of flame!"); X if (Fire_resistance) X pline ("You are uninjured."); X else { X num = rnd (6); X u.uhpmax -= num; X losehp (num, "scroll of fire"); X } X } X break; X } X case SCR_PUNISHMENT: X known = TRUE; X if (confused) { X pline ("You feel guilty."); X break; X } X pline ("You are being punished for your misbehaviour!"); X if (Punished) { X pline ("Your iron ball gets heavier."); X uball -> owt += 15; X break; X } X Punished = INTRINSIC; X mkobj_at (CHAIN_SYM, u.ux, u.uy); X setworn (fobj, W_CHAIN); X mkobj_at (BALL_SYM, u.ux, u.uy); X setworn (fobj, W_BALL); X uball -> spe = 1; /* special ball (see save) */ X break; X default: X pline ("What weird language is this written in? (%d)", X scroll -> otyp); X impossible (); X } X if (!objects[scroll -> otyp].oc_name_known) { X if (known && !confused) { X objects[scroll -> otyp].oc_name_known = 1; X u.urexp += 10; X } X else X if (!objects[scroll -> otyp].oc_uname) X docall (scroll); X } X useup (scroll); X return (1); X} X Xidentify (otmp) Xregister struct obj *otmp; X{ X objects[otmp -> otyp].oc_name_known = 1; X otmp -> known = otmp -> dknown = 1; X prinv (otmp); X return (1); X} X Xlitroom (on) Xregister boolean on; X{ X register num, zx, zy; X X /* first produce the text (provided he is not blind) */ X if (Blind) X goto do_it; X if (!on) { X if (u.uswallow || !xdnstair || levl[u.ux][u.uy].typ == CORR || X !levl[u.ux][u.uy].lit) { X pline ("It seems even darker in here than before."); X return; X } X else X pline ("It suddenly becomes dark in here."); X } X else { X if (u.uswallow) { X pline ("%s's stomach is lit.", Monnam (u.ustuck)); X return; X } X if (!xdnstair) { X pline ("Nothing Happens"); X return; X } X#ifdef QUEST X pline ("The cave lights up around you, then fades."); X return; X#else QUEST X if (levl[u.ux][u.uy].typ == CORR) { X pline ("The corridor lights up around you, then fades."); X return; X } X else X if (levl[u.ux][u.uy].lit) { X pline ("The light here seems better now."); X return; X } X else X pline ("The room is lit."); X#endif QUEST X } X Xdo_it: X#ifdef QUEST X return; X#else QUEST X if (levl[u.ux][u.uy].lit == on) 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 X 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 X 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; (num = levl[seelx - 1][zy].typ) != CORR && num != 0; X seelx--); X for (seehx = u.ux; (num = levl[seehx + 1][zy].typ) != CORR && num != 0; X seehx++); X for (seely = u.uy; (num = levl[zx][seely - 1].typ) != CORR && num != 0; X seely--); X for (seehy = u.uy; (num = levl[zx][seehy + 1].typ) != CORR && num != 0; X seehy++); X for (zy = seely; zy <= seehy; zy++) X for (zx = seelx; zx <= seehx; zx++) { X levl[zx][zy].lit = on; X if (!Blind && dist (zx, zy) > 2) X if (on) X prl (zx, zy); X else X nosee (zx, zy); X } X if (!on) X seehx = 0; X#endif QUEST X} --burp-- sed 's/^X//' << '--burp--' > hack.shk.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include "hack.h" X#ifdef QUEST Xint shlevel = 0; Xstruct monst *shopkeeper = 0; Xstruct obj *billobjs = 0; Xobfree (obj, merge) register struct obj *obj, *merge; { X free ((char *) obj); X} Xinshop () { X return (0); X} Xaddtobill () { X} Xsubfrombill () { X} Xsplitbill () { X} Xdopay () { X} Xpaybill () { X} Xdoinvbill () { X} Xshkdead () { X} Xshk_move () { X return (0); X} Xsetshk () { X} Xchar *shkname () { X return (""); X} X X#else X#include "hack.mfndpos.h" X#include "def.eshk.h" X X#define ESHK ((struct eshk *)(&(shopkeeper->mextra[0]))) X#define NOTANGRY shopkeeper->mpeaceful X#define ANGRY !NOTANGRY X Xextern char plname[]; Xextern struct obj *o_on (); Xstruct monst *shopkeeper = 0; Xstruct bill_x *bill; Xint shlevel = 0; /* level of this shopkeeper */ Xstruct obj *billobjs; /* objects on bill with bp->useup */ X/* #define billobjs shopkeeper->minvent X * doesnt work so well, since we do not want these objects to be dropped X * when the shopkeeper is killed. X * (See also the save and restore routines.) X */ X X/* invariants: obj->unpaid iff onbill(obj) [unless bp->useup] X * obj->quan <= bp->bquan X */ X Xlong int total; X Xchar shtypes[] = "=/)%?!["; /* 8 shoptypes: 7 specialized, 1 mixed */ Xchar *shopnam[] = { X "engagement ring", "walking cane", "antique weapon", X "delicatessen", "second hand book", "liquor", X "used armor", "assorted antiques" X}; X Xchar * Xshkname () X{ X return (ESHK -> shknam); X} X Xshkdead () X{ X rooms[ESHK -> shoproom].rtype = 0; X setpaid (); X shopkeeper = 0; X bill = (struct bill_x *) - 1000; /* dump core when referenced */ X} X Xsetpaid () /* caller has checked that shopkeeper exists */ X{ X register struct obj *obj; X for (obj = invent; obj; obj = obj -> nobj) X obj -> unpaid = 0; X for (obj = fobj; obj; obj = obj -> nobj) X obj -> unpaid = 0; X while (obj = billobjs) { X billobjs = obj -> nobj; X free ((char *) obj); X } X ESHK -> billct = 0; X} X Xaddupbill () /* delivers result in total */ X{ X /* caller has checked that shopkeeper exists */ X register ct = ESHK -> billct; X register struct bill_x *bp = bill; X total = 0; X while (ct--) { X total += bp -> price * bp -> bquan; X bp++; X } X} X Xinshop () X{ X register tmp = inroom (u.ux, u.uy); X if (tmp < 0 || rooms[tmp].rtype < 8) { X u.uinshop = 0; X if (shopkeeper && ESHK -> billct) { X pline ("Somehow you escaped the shop without paying!"); X addupbill (); X pline ("You stole for a total worth of %lu zorkmids.", X total); X ESHK -> robbed += total; X setpaid (); X } X if (tmp >= 0 && rooms[tmp].rtype == 7) { X register struct monst *mtmp; X pline ("Welcome to David's treasure zoo!"); X rooms[tmp].rtype = 0; X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) X if (!rn2 (4)) X mtmp -> msleep = 0; X } X } X else { X if (shlevel != dlevel) X setshk (); X if (!shopkeeper) X u.uinshop = 0; X else X if (!u.uinshop) { X if (!ESHK -> visitct || X strncmp (ESHK -> customer, plname, PL_NSIZ)) { X /* He seems to be new here */ X ESHK -> visitct = 0; X (void) strncpy (ESHK -> customer, plname, PL_NSIZ); X NOTANGRY = 1; X } X pline ("Hello %s! Welcome%s to %s's %s shop!", X plname, X ESHK -> visitct++ ? " again" : "", X shkname (), X shopnam[rooms[ESHK -> shoproom].rtype - 8]); X u.uinshop = 1; X } X } X return (u.uinshop); X} X Xsetshk () X{ X register struct monst *mtmp; X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) X if (mtmp -> isshk) { X shopkeeper = mtmp; X bill = &(ESHK -> bill[0]); X shlevel = dlevel; X if (ANGRY && strncpy (ESHK -> customer, plname, PL_NSIZ)) X NOTANGRY = 1; X billobjs = 0; X return; X } X shopkeeper = 0; X bill = (struct bill_x *) - 1000; /* dump core when referenced */ X} X Xstruct bill_x * Xonbill (obj) Xregister struct obj *obj; X{ X register struct bill_x *bp; X if (!shopkeeper) X return (0); X for (bp = bill; bp < &bill[ESHK -> billct]; bp++) X if (bp -> bo_id == obj -> o_id) { X if (!obj -> unpaid) X pline ("onbill: paid obj on bill?"); X return (bp); X } X if (obj -> unpaid) X pline ("onbill: unpaid obj not on bill?"); X return (0); X} X X/* called with two args on merge */ Xobfree (obj, merge) Xregister struct obj *obj, *merge; X{ X register struct bill_x *bp = onbill (obj); X register struct bill_x *bpm; X if (bp) { X if (!merge) { X bp -> useup = 1; X obj -> unpaid = 0; /* only for doinvbill */ X obj -> nobj = billobjs; X billobjs = obj; X return; X } X bpm = onbill (merge); X if (!bpm) { X /* this used to be a rename */ X impossible (); X return; X } X else { X /* this was a merger */ X bpm -> bquan += bp -> bquan; X ESHK -> billct--; X *bp = bill[ESHK -> billct]; X } X } X free ((char *) obj); X} X Xpay (tmp) long tmp; X{ X u.ugold -= tmp; X shopkeeper -> mgold += tmp; X flags.botl = 1; X} X Xdopay () X{ X long ltmp; X register struct bill_x *bp; X int shknear = (shlevel == dlevel && shopkeeper && X dist (shopkeeper -> mx, shopkeeper -> my) < 3); X int pass, tmp; X X multi = 0; X if (!inshop () && !shknear) { X pline ("You are not in a shop."); X return (0); X } X if (!shknear && X inroom (shopkeeper -> mx, shopkeeper -> my) != ESHK -> shoproom) { X pline ("There is nobody here to receive your payment."); X return (0); X } X if (!ESHK -> billct) { X pline ("You do not owe %s anything.", monnam (shopkeeper)); X if (!u.ugold) { X pline ("Moreover, you have no money."); X return (1); X } X if (ESHK -> robbed) { X pline ("But since the shop has been robbed recently,"); X pline ("you %srepay %s's expenses.", X (u.ugold < ESHK -> robbed) ? "partially " : "", X monnam (shopkeeper)); X pay ((u.ugold < ESHK -> robbed) ? u.ugold : ESHK -> robbed); X ESHK -> robbed = 0; X return (1); X } X if (ANGRY) { X pline ("But in order to appease %s,", X amonnam (shopkeeper, "angry")); X if (u.ugold >= 1000) { X ltmp = 1000; X pline (" you give him 1000 gold pieces."); X } X else { X ltmp = u.ugold; X pline (" you give him all your money."); X } X pay (ltmp); X if (rn2 (3)) { X pline ("%s calms down.", Monnam (shopkeeper)); X NOTANGRY = 1; X } X else X pline ("%s is as angry as ever.", X Monnam (shopkeeper)); X } X return (1); X } X for (pass = 0; pass <= 1; pass++) { X tmp = 0; X while (tmp < ESHK -> billct) { X bp = &bill[tmp]; X if (!pass && !bp -> useup) { X tmp++; X continue; X } X if (!dopayobj (bp)) X return (1); X bill[tmp] = bill[--ESHK -> billct]; X } X } X pline ("Thank you for shopping in %s's %s store!", X shkname (), X shopnam[rooms[ESHK -> shoproom].rtype - 8]); X NOTANGRY = 1; X return (1); X} X X/* return 1 if paid successfully */ X/* 0 if not enough money */ X/* -1 if object could not be found (but was paid) */ Xdopayobj (bp) Xregister struct bill_x *bp; X{ X register struct obj *obj; X long ltmp; X X /* find the object on one of the lists */ X if (bp -> useup) X obj = o_on (bp -> bo_id, billobjs); X else X if (!(obj = o_on (bp -> bo_id, invent)) && X !(obj = o_on (bp -> bo_id, fobj)) && X !(obj = o_on (bp -> bo_id, fcobj))) { X register struct monst *mtmp; X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) X if (obj = o_on (bp -> bo_id, mtmp -> minvent)) X break; X for (mtmp = fallen_down; mtmp; mtmp = mtmp -> nmon) X if (obj = o_on (bp -> bo_id, mtmp -> minvent)) X break; X } X if (!obj) { X pline ("Shopkeeper administration out of order."); X impossible (); X setpaid (); /* be nice to the player */ X return (0); X } X X if (!obj -> unpaid && !bp -> useup) { X pline ("Paid object on bill??"); X impossible (); X return (1); X } X obj -> unpaid = 0; X ltmp = bp -> price * bp -> bquan; X if (ANGRY) X ltmp += ltmp / 3; X if (u.ugold < ltmp) { X pline ("You don't have gold enough to pay %s.", X doname (obj)); X obj -> unpaid = 1; X return (0); X } X pay (ltmp); X pline ("You bought %s for %ld gold piece%s.", X doname (obj), ltmp, (ltmp == 1) ? "" : "s"); X if (bp -> useup) { X register struct obj *otmp = billobjs; X if (obj == billobjs) X billobjs = obj -> nobj; X else { X while (otmp && otmp -> nobj != obj) X otmp = otmp -> nobj; X if (otmp) X otmp -> nobj = obj -> nobj; X else X pline ("Error in shopkeeper administration"); X } X free ((char *) obj); X } X return (1); X} X X/* routine called after dying (or quitting) with nonempty bill */ Xpaybill () X{ X if (shopkeeper && ESHK -> billct) { X addupbill (); X if (total > u.ugold) { X shopkeeper -> mgold += u.ugold; X u.ugold = 0; X pline ("%s comes and takes all your possessions.", X Monnam (shopkeeper)); X } X else { X u.ugold -= total; X shopkeeper -> mgold += total; X pline ("%s comes and takes the %ld zorkmids you owed him.", X Monnam (shopkeeper), total); X } X setpaid (); /* in case we create bones */ X } X} X X/* called in hack.c when we pickup an object */ Xaddtobill (obj) Xregister struct obj *obj; X{ X register struct bill_x *bp; X if (!inshop () || (u.ux == ESHK -> shk.x && u.uy == ESHK -> shk.y) || X (u.ux == ESHK -> shd.x && u.uy == ESHK -> shd.y) || X onbill (obj) /* perhaps we threw it away earlier */ X ) X return; X if (ESHK -> billct == BILLSZ) { X pline ("You got that for free!"); X return; X } X bp = &bill[ESHK -> billct]; X bp -> bo_id = obj -> o_id; X bp -> bquan = obj -> quan; X bp -> useup = 0; X bp -> price = getprice (obj); X ESHK -> billct++; X obj -> unpaid = 1; X} X Xsplitbill (obj, otmp) Xregister struct obj *obj, *otmp; X{ X /* otmp has been split off from obj */ X register struct bill_x *bp; X register int tmp; X bp = onbill (obj); X if (!bp) { X impossible (); X return; X } X if (bp -> bquan < otmp -> quan) { X pline ("Negative quantity on bill??"); X impossible (); X } X if (bp -> bquan == otmp -> quan) { X pline ("Zero quantity on bill??"); X impossible (); X } X bp -> bquan -= otmp -> quan; X X /* addtobill(otmp); */ X if (ESHK -> billct == BILLSZ) X otmp -> unpaid = 0; X else { X tmp = bp -> price; X bp = &bill[ESHK -> billct]; X bp -> bo_id = otmp -> o_id; X bp -> bquan = otmp -> quan; X bp -> useup = 0; X bp -> price = tmp; X ESHK -> billct++; X } X} X Xsubfrombill (obj) Xregister struct obj *obj; X{ X long ltmp; X register int tmp; X register struct obj *otmp; X register struct bill_x *bp; X if (!inshop () || (u.ux == ESHK -> shk.x && u.uy == ESHK -> shk.y) || X (u.ux == ESHK -> shd.x && u.uy == ESHK -> shd.y)) X return; X if ((bp = onbill (obj)) != 0) { X obj -> unpaid = 0; X if (bp -> bquan > obj -> quan) { X otmp = newobj (0); X *otmp = *obj; X bp -> bo_id = otmp -> o_id = flags.ident++; X otmp -> quan = (bp -> bquan -= obj -> quan); X otmp -> owt = 0; /* superfluous */ X otmp -> onamelth = 0; X bp -> useup = 1; X otmp -> nobj = billobjs; X billobjs = otmp; X return; X } X ESHK -> billct--; X *bp = bill[ESHK -> billct]; X return; X } X if (obj -> unpaid) { X pline ("%s didn't notice.", Monnam (shopkeeper)); X obj -> unpaid = 0; X return; /* %% */ X } X /* he dropped something of his own - probably wants to sell it */ X if (shopkeeper -> msleep || shopkeeper -> mfroz || X inroom (shopkeeper -> mx, shopkeeper -> my) != ESHK -> shoproom) X return; X if (ESHK -> billct == BILLSZ || X ((tmp = shtypes[rooms[ESHK -> shoproom].rtype - 8]) && tmp != obj -> olet) X || index ("_0", obj -> olet)) { X pline ("%s seems not interested.", Monnam (shopkeeper)); X return; X } X ltmp = getprice (obj) * obj -> quan; X if (ANGRY) { X ltmp /= 3; X NOTANGRY = 1; X } X else X ltmp /= 2; X if (ESHK -> robbed) { X if ((ESHK -> robbed -= ltmp) < 0) X ESHK -> robbed = 0; X pline ("Thank you for your contribution to restock this recently plundered shop."); X return; X } X if (ltmp > shopkeeper -> mgold) X ltmp = shopkeeper -> mgold; X pay (-ltmp); X if (!ltmp) X pline ("%s gladly accepts %s but cannot pay you at present.", X Monnam (shopkeeper), doname (obj)); X else X pline ("You sold %s and got %ld gold piece%s.", doname (obj), ltmp, X (ltmp == 1) ? "" : "s"); X} X Xdoinvbill (cl) Xint cl; X{ X register unsigned tmp, cnt = 0; X register struct obj *obj; X char buf[BUFSZ]; X int retval; X X retval = 0; X if (!shopkeeper) X return (retval); X for (tmp = 0; tmp < ESHK -> billct; tmp++) X if (bill[tmp].useup) X cnt++; X if (!cnt) X return (retval); X if (!cl && !flags.oneline) X cls (); X if (!flags.oneline) { X retval = 1; X puts ("\n\nUnpaid articles already used up:\n"); X } X for (tmp = 0; tmp < ESHK -> billct; tmp++) X if (bill[tmp].useup) { X for (obj = billobjs; obj; obj = obj -> nobj) X if (obj -> o_id == bill[tmp].bo_id) X break; X if (!obj) { X pline ("Bad shopkeeper administration."); X impossible (); X return (retval); X } X retval = 1; X (void) sprintf (buf, "* - %s", doname (obj)); X for (cnt = 0; buf[cnt]; cnt++); X while (cnt < 50) X buf[cnt++] = ' '; X (void) sprintf (&buf[cnt], " %5d zorkmids", X bill[tmp].price * bill[tmp].bquan); X if (flags.oneline) X pline (buf); X else X puts (buf); X } X if (!cl && !flags.oneline) { X getret (); X docrt (); X } X return (retval); X} X Xgetprice (obj) Xregister struct obj *obj; X{ X register int tmp, ac; X switch (obj -> olet) { X case AMULET_SYM: X tmp = 10 * rnd (500); X break; X case TOOL_SYM: X tmp = 10 * rnd (150); X break; X case RING_SYM: X tmp = 10 * rnd (100); X break; X case WAND_SYM: X tmp = 10 * rnd (100); X break; X case SCROLL_SYM: X tmp = 10 * rnd (50); X break; X case POTION_SYM: X tmp = 10 * rnd (50); X break; X case FOOD_SYM: X tmp = 10 * rnd (5 + (2000 / realhunger ())); X break; X case GEM_SYM: X tmp = 10 * rnd (20); X break; X case ARMOR_SYM: X ac = 10 - obj -> spe; X tmp = 100 + (10 - ac) * (10 - ac) * rnd (20 - ac); X break; X case WEAPON_SYM: X if (obj -> otyp < BOOMERANG) X tmp = 5 * rnd (10); X else X if (obj -> otyp == LONG_SWORD || X obj -> otyp == TWO_HANDED_SWORD) X tmp = 10 * rnd (150); X else X tmp = 10 * rnd (75); X break; X case CHAIN_SYM: X pline ("Strange ..., carrying a chain?"); X case BALL_SYM: X tmp = 10; X break; X default: X tmp = 10000; X } X return (tmp); X} X Xrealhunger () /* not completely foolproof */ X{ X register tmp = u.uhunger; X register struct obj *otmp = invent; X while (otmp) { X if (otmp -> olet == FOOD_SYM && !otmp -> unpaid) X tmp += objects[otmp -> otyp].nutrition; X otmp = otmp -> nobj; X } X return ((tmp <= 0) ? 1 : tmp); X} X Xshk_move () X{ X register struct monst *mtmp; X register struct permonst *mdat = shopkeeper -> data; X register xchar gx, gy, omx, omy, nx, ny, nix, niy; X register schar appr, i; X schar shkr, tmp, chi, chcnt, cnt; X boolean uondoor, avoid; X coord poss[9]; X int info[9]; X omx = shopkeeper -> mx; X omy = shopkeeper -> my; X shkr = inroom (omx, omy); X if (ANGRY && dist (omx, omy) < 3) { X (void) hitu (shopkeeper, d (mdat -> damn, mdat -> damd) + 1); X return (0); X } X appr = 1; X gx = ESHK -> shk.x; X gy = ESHK -> shk.y; X if (ANGRY) { X int saveBlind = Blind; X Blind = 0; X if (shopkeeper -> mcansee && !Invis && cansee (omx, omy)) { X gx = u.ux; X gy = u.uy; X } X Blind = saveBlind; X avoid = FALSE; X } X else { X#define GDIST(x,y) ((x-gx)*(x-gx)+(y-gy)*(y-gy)) X if (Invis) X avoid = FALSE; X else { X uondoor = (u.ux == ESHK -> shd.x && u.uy == ESHK -> shd.y); X avoid = ((u.uinshop && dist (gx, gy) > 8) || uondoor); X if (((!ESHK -> robbed && !ESHK -> billct) || avoid) X && GDIST (omx, omy) < 3) { X if (!online (omx, omy)) X return (0); X if (omx == gx && omy == gy) X appr = gx = gy = 0; X } X } X } X if (omx == gx && omy == gy) X return (0); X if (shopkeeper -> mconf) X appr = 0; X nix = omx; X niy = omy; X cnt = mfndpos (shopkeeper, poss, info, X (avoid ? NOTONL : 0) | ALLOW_SSM); X if (cnt == 0 && avoid && uondoor) X cnt = mfndpos (shopkeeper, poss, info, ALLOW_SSM); X chi = -1; X chcnt = 0; X for (i = 0; i < cnt; i++) { X nx = poss[i].x; X ny = poss[i].y; X if ((tmp = levl[nx][ny].typ) == ROOM || X (shkr != ESHK -> shoproom && (tmp == CORR || tmp == DOOR))) X if ((!appr && !rn2 (++chcnt)) || X (appr && GDIST (nx, ny) < GDIST (nix, niy))) { X nix = nx; X niy = ny; X chi = i; X } X } X if (nix != omx || niy != omy) { X if (info[chi] & ALLOW_M) { X mtmp = m_at (nix, niy); X if (hitmm (shopkeeper, mtmp) == 1 && rn2 (3) && X hitmm (mtmp, shopkeeper) == 2) X return (2); X return (0); X } X else X if (info[chi] & ALLOW_U) { X (void) hitu (shopkeeper, d (mdat -> damn, mdat -> damd) + 1); X return (0); X } X shopkeeper -> mx = nix; X shopkeeper -> my = niy; X pmon (shopkeeper); X return (1); X } X return (0); X} X#endif QUEST X Xchar * Xplur (n) unsigned n; X{ X return ((n == 1) ? "" : "s"); X} X Xonline (x, y) X{ X return (x == u.ux || y == u.uy || X (x - u.ux) * (x - u.ux) == (y - u.uy) * (y - u.uy)); X} --burp-- sed 's/^X//' << '--burp--' > hack.termcap.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include <stdio.h> X#include "config.h" /* for ROWNO and COLNO */ Xextern char *tgetstr (), *tgoto (), *getenv (); Xextern long *alloc (); X Xshort ospeed; /* terminal baudrate; used by tputs */ Xchar tbuf[512]; Xchar *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE; Xchar *VS, *VE, *CD; Xint SG; Xchar PC = '\0'; X Xstartup () X{ X register char *tmp; X register char *tptr; X char *tbufptr, *pc; X X gettty (); /* sets ospeed */ X X tptr = (char *) alloc (1024); X X tbufptr = tbuf; X if (!(tmp = getenv ("TERM"))) X error ("Can't get TERM."); X if (tgetent (tptr, tmp) < 1) X error ("Unknown terminal type: %s.", tmp); X if (pc = tgetstr ("pc", &tbufptr)) X PC = *pc; X if (!(BC = tgetstr ("bc", &tbufptr))) { X if (!tgetflag ("bs")) X error ("Terminal must backspace."); X BC = tbufptr; X tbufptr += 2; X *BC = '\b'; X } X HO = tgetstr ("ho", &tbufptr); X if (tgetnum ("co") < COLNO || tgetnum ("li") < ROWNO + 2) X error ("Screen must be at least %d by %d!", X ROWNO + 2, COLNO); X if (!(CL = tgetstr ("cl",&tbufptr)) X || !(ND = tgetstr ("nd", &tbufptr)) X || !(UP = tgetstr ("up",&tbufptr)) X || tgetflag ("os")) X error("Hack needs CL, UP, ND, and no OS."); X if (!(CM = tgetstr ("cm", &tbufptr))) X printf ("Use of hack on terminals without CM is suspect...\n"); X CE = tgetstr ("ce",&tbufptr); X CD = tgetstr ("cd",&tbufptr); X XD = tgetstr ("xd", &tbufptr); X SO = tgetstr ("so", &tbufptr); X SE = tgetstr ("se", &tbufptr); X SG = tgetnum ("sg"); X TI = tgetstr ("ti", &tbufptr); X TE = tgetstr ("te", &tbufptr); X VS = tgetstr ("vs", &tbufptr); X VE = tgetstr ("ve", &tbufptr); X if (!SO || !SE || !SG) X SO = SE = 0; X if (tbufptr - tbuf > sizeof (tbuf)) X error ("TERMCAP entry too big...\n"); X free (tptr); X start_screen (); X} X Xstart_screen () X{ X xputs (TI); X xputs (VS); X} X Xend_screen () X{ X xputs (TE); X xputs (VE); X} X X/* Cursor movements */ Xextern xchar curx, cury; X Xcurs (x, y) Xregister int x, y; /* not xchar: perhaps xchar is unsigned and curx-x would be unsigned as well */ X{ X X if (y == cury && x == curx) X return; X if (abs (cury - y) <= 3 && abs (curx - x) <= 3) X nocmov (x, y); X else X if ((x <= 3 && abs (cury - y) <= 3) || (!CM && x < abs (curx - x))) { X (void) putchar ('\r'); X curx = 1; X nocmov (x, y); X } X else X if (!CM) X nocmov (x, y); X else X cmov (x, y); X} X Xnocmov (x, y) X{ X if (curx < x) { /* Go to the right. */ X while (curx < x) { X xputs (ND); X curx++; X } X } X else X if (curx > x) { X while (curx > x) { /* Go to the left. */ X xputs (BC); X curx--; X } X } X if (cury > y) { X if (UP) { X while (cury > y) { /* Go up. */ X xputs (UP); X cury--; X } X } X else X cmov (x, y); X } X else X if (cury < y) { X if (XD) { X while (cury < y) { X xputs (XD); X cury++; X } X } X else X cmov (x, y); X } X} X Xcmov (x, y) Xregister x, y; X{ X if (!CM) X error ("Tries to cmov from %d %d to %d %d\n", curx, cury, x, y); X xputs (tgoto (CM, x - 1, y - 1)); X cury = y; X curx = x; X} X Xxputc (c) Xchar c; X{ X (void) fputc (c, stdout); X} X Xxputs (s) Xchar *s; X{ X tputs (s, 1, xputc); X} X Xcl_end () X{ X register int i; X X if (CE) X xputs (CE); X else { X for (i = COLNO - curx; i > 0; --i) X xputc (' '); X cmov (curx, cury); X } X} X Xcl_eos () X{ X register int i; X X if (CD) X xputs (CD); X else { X for (i = (ROWNO + 1) - curx; i > 0; --i) { X cl_end (); X putchar ('\r'); X putchar ('\n'); X } X cl_end (); X cmov (curx, cury); X } X} X Xclear_screen () X{ X xputs (CL); X curx = cury = 1; X} X Xhome () X{ X if (HO) X xputs (HO); X else X xputs (tgoto (CM, 0, 0)); X curx = cury = 1; X} X Xstandoutbeg () X{ X if (SO) X xputs (SO); X} X Xstandoutend () X{ X if (SE) X xputs (SE); X} X Xbacksp () X{ X xputs (BC); X curx--; X} X Xbell () X{ X putsym ('\007'); X} X Xdelay_output () X{ X /* delay 40 ms - could also use a 'nap'-system call */ X tputs ("40", 1, xputc); X} --burp-- sed 's/^X//' << '--burp--' > hack.topl.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include "hack.h" X#include <stdio.h> Xextern char *eos (); X#define TOPLSZ (COLNO-8) /* leave room for --More-- */ Xchar toplines[BUFSZ]; Xxchar tlx, tly; /* set by pline; used by addtopl */ X Xstruct topl { X struct topl *next_topl; X char *topl_text; X} *old_toplines, *last_redone_topl; X#define OTLMAX 20 /* max nr of old toplines remembered */ X Xdoredotopl () X{ X if (last_redone_topl) X last_redone_topl = last_redone_topl -> next_topl; X if (!last_redone_topl) X last_redone_topl = old_toplines; X if (last_redone_topl) { X (void) strcpy (toplines, last_redone_topl -> topl_text); X } X redotoplin (); X return (0); X} X Xredotoplin () X{ X home (); X if (index (toplines, '\n')) X cl_end (); X putstr (toplines); X cl_end (); X tlx = curx; X tly = cury; X flags.topl = 1; X if (tly > 1) X more (); X} X Xremember_topl () X{ X register struct topl *tl; X register int cnt = OTLMAX; X if (last_redone_topl && X !strcmp (toplines, last_redone_topl -> topl_text)) X return; X if (old_toplines && X !strcmp (toplines, old_toplines -> topl_text)) X return; X last_redone_topl = 0; X tl = (struct topl *) X alloc ((unsigned) (strlen (toplines) + sizeof (struct topl) + 1)); X tl -> next_topl = old_toplines; X tl -> topl_text = (char *) (tl + 1); X (void) strcpy (tl -> topl_text, toplines); X old_toplines = tl; X while (cnt && tl) { X cnt--; X tl = tl -> next_topl; X } X if (tl && tl -> next_topl) { X free ((char *) tl -> next_topl); X tl -> next_topl = 0; X } X} X Xaddtopl (s) char *s; X{ X curs (tlx, tly); X if (tlx + strlen (s) > COLNO) X putsym ('\n'); X putstr (s); X tlx = curx; X tly = cury; X flags.topl = 1; X} X Xxmore (spaceflag) Xboolean spaceflag; /* TRUE if space required */ X{ X if (flags.topl) { X curs (tlx, tly); X if (tlx + 8 > COLNO) X putsym ('\n'), tly++; X } X standoutbeg (); X putstr ("--More--"); X standoutend (); X xwaitforspace (spaceflag); X if (flags.topl && tly > 1) { X home (); X cl_end (); X docorner (1, tly - 1); X } X flags.topl = 0; X} X Xmore () X{ X xmore (TRUE); X} X Xcmore () X{ X xmore (FALSE); X} X Xclrlin () X{ X if (flags.topl) { X home (); X cl_end (); X if (tly > 1) X docorner (1, tly - 1); X remember_topl (); X } X flags.topl = 0; X} X X/*VARARGS1*/ Xpline (line, arg1, arg2, arg3, arg4, arg5, arg6) Xregister char *line, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6; X{ X char pbuf[BUFSZ]; X register char *bp = pbuf, *tl; X register int n, n0; X X if (!line || !*line) X return; X if (!index (line, '%')) X (void) strcpy (pbuf, line); X else X (void) sprintf (pbuf, line, arg1, arg2, arg3, arg4, arg5, arg6); X if (flags.topl == 1 && !strcmp (pbuf, toplines)) X return; X nscr (); /* %% */ X X /* If there is room on the line, print message on same line */ X /* But messages like "You die..." deserve their own line */ X n0 = strlen (bp); X if (flags.topl == 1 && tly == 1 && X n0 + strlen (toplines) + 3 < TOPLSZ && X strncmp (bp, "You ", 4)) { X (void) strcat (toplines, " "); X (void) strcat (toplines, bp); X tlx += 2; X addtopl (bp); X return; X } X if (flags.topl == 1) X more (); X remember_topl (); X toplines[0] = 0; X while (n0) { X if (n0 >= COLNO) { X /* look for appropriate cut point */ X n0 = 0; X for (n = 0; n < COLNO; n++) X if (bp[n] == ' ') X n0 = n; X if (!n0) X for (n = 0; n < COLNO - 1; n++) X if (!letter (bp[n])) X n0 = n; X if (!n0) X n0 = COLNO - 2; X } X (void) strncpy ((tl = eos (toplines)), bp, n0); X tl[n0] = 0; X bp += n0; X X /* remove trailing spaces, but leave one */ X while (n0 > 1 && tl[n0 - 1] == ' ' && tl[n0 - 2] == ' ') X tl[--n0] = 0; X X n0 = strlen (bp); X if (n0 && tl[0]) X (void) strcat (tl, "\n"); X } X redotoplin (); X} X Xputsym (c) Xchar c; X{ X switch (c) { X case '\b': X backsp (); X return; X case '\n': X curx = 1; X cury++; X if (cury > tly) X tly = cury; X break; X default: X curx++; X if (curx == COLNO) X putsym ('\n'); X } X (void) putchar (c); X} X Xputstr (s) Xregister char *s; X{ X while (*s) X putsym (*s++); X} --burp-- sed 's/^X//' << '--burp--' > hack.tty.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include "hack.h" X#include <stdio.h> X#include <sgtty.h> X#include <ctype.h> X Xstruct sgttyb inittyb, curttyb; Xextern short ospeed; X X Xgettty () X{ X (void) gtty (0, &inittyb); X (void) gtty (0, &curttyb); X ospeed = inittyb.sg_ospeed; X/* X if(ospeed <= B300) flags.oneline = 1; X*/ X getioctls (); X xtabs (); X} X X/* reset terminal to original state */ Xsettty (s) Xchar *s; X{ X clear_screen (); X end_screen (); X if (s) X printf (s); X (void) fflush (stdout); X if (stty (0, &inittyb) == -1) X puts ("Cannot change tty"); X flags.echo = (inittyb.sg_flags & ECHO) ? ON : OFF; X flags.cbreak = (inittyb.sg_flags & CBREAK) ? ON : OFF; X setioctls (); X} X Xsetctty () X{ X if (stty (0, &curttyb) == -1) X puts ("Cannot change tty"); X} X Xsetftty () X{ X register int ef = (flags.echo == ON) ? ECHO : 0; X register int cf = (flags.cbreak == ON) ? CBREAK : 0; X register int change = 0; X if ((curttyb.sg_flags & ECHO) != ef) { X curttyb.sg_flags &= ~ECHO; X curttyb.sg_flags |= ef; X change++; X } X if ((curttyb.sg_flags & CBREAK) != cf) { X curttyb.sg_flags &= ~CBREAK; X curttyb.sg_flags |= cf; X change++; X } X if (change) { X setctty (); X } X} X Xecho (n) Xregister n; X{ X X /* (void) gtty(0,&curttyb); */ X if (n == ON) X curttyb.sg_flags |= ECHO; X else X curttyb.sg_flags &= ~ECHO; X setctty (); X} X X/* always want to expand tabs, or to send a clear line char before X printing something on topline */ Xxtabs () X{ X X /* (void) gtty(0, &curttyb); */ X curttyb.sg_flags |= XTABS; X setctty (); X} X X#ifdef LONG_CMD Xcbreak (n) Xregister n; X{ X X /* (void) gtty(0,&curttyb); */ X if (n == ON) X curttyb.sg_flags |= CBREAK; X else X curttyb.sg_flags &= ~CBREAK; X setctty (); X} X#endif LONG_CMD X Xgetlin (bufp) Xregister char *bufp; X{ X register char *obufp = bufp; X register int c; X X flags.topl = 2; /* nonempty, no --More-- required */ X for (;;) { X (void) fflush (stdout); X if ((c = getchar ()) == EOF) { X *bufp = 0; X return; X } X if (c == '\b') { X if (bufp != obufp) { X bufp--; X putstr ("\b \b"); /* putsym converts \b */ X } X else X bell (); X } X else if (c == '\n') { X *bufp = 0; X return; X } X else if (c == '\177') { X while (bufp != obufp) { X putstr ("\b \b"); X bufp--; X } X } X else if (isprint(c)) { X *bufp = c; X bufp[1] = 0; X putstr (bufp); X if (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO) X bufp++; X } X else X bell(); X } X} X Xgetret () X{ X xgetret (TRUE); X} X Xcgetret () X{ X xgetret (FALSE); X} X Xxgetret (spaceflag) Xboolean spaceflag; /* TRUE if space (return) required */ X{ X printf ("\nHit %s to continue: ", X flags.cbreak ? "space" : "return"); X xwaitforspace (spaceflag); X} X Xchar morc; /* tell the outside world what char he used */ Xxwaitforspace (spaceflag) Xboolean spaceflag; X{ X register int c; X X (void) fflush (stdout); X morc = 0; X X while ((c = getchar ()) != '\n') { X if (c == EOF) { X settty ("End of input?\n"); X exit (0); X } X if (flags.cbreak) { X if (c == ' ') X break; X if (!spaceflag && letter (c)) { X morc = c; X break; X } X } X } X} X Xchar * Xparse () X{ X static char inline[COLNO]; X register foo; X X flags.move = 1; X if (!Invis) X curs (u.ux, u.uy + 2); X else X home (); X (void) fflush (stdout); 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 == EOF) { X settty ("End of input?\n"); X exit (0); X } X if (foo == 'f' || foo == 'F') { X inline[1] = getchar (); X#ifdef QUEST X if (inline[1] == foo) X inline[2] = getchar (); X else X#endif QUEST X inline[2] = 0; X } X if (foo == 'm' || foo == 'M') { X inline[1] = getchar (); X inline[2] = 0; X } X clrlin (); X return (inline); X} X Xchar Xreadchar () X{ X register int sym; X (void) fflush (stdout); X if ((sym = getchar ()) == EOF) { X settty ("End of input?\n"); X exit (0); X } X if (flags.topl == 1) X flags.topl = 2; X return ((char) sym); X} --burp-- sed 's/^X//' << '--burp--' > hack.wield.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include "hack.h" X Xsetuwep (obj) Xregister struct obj *obj; X{ X setworn (obj, W_WEP); X} X Xdowield () X{ X register struct obj *wep; X register int res = 0; X X multi = 0; X if (!(wep = getobj ("#-)", "wield"))) X /* nothing */ ; X else if (uwep == wep) X pline ("You are already wielding that!"); X else if (uwep && uwep -> cursed) X pline ("The %s welded to your hand!", aobjnam (uwep, "are")); X else if ((int) wep == -1) { X if (uwep == 0) { X pline ("You are already empty handed."); X } X else { X setuwep ((struct obj *) 0); X res++; X pline ("You are empty handed."); X } X } X else if (uarms && wep -> otyp == TWO_HANDED_SWORD) X pline ("You cannot wield a two-handed sword and wear a shield."); X else if (wep -> owornmask & (W_ARMOR | W_RING)) X pline ("You cannot wield that!"); X else { X setuwep (wep); X res++; X if (uwep -> cursed) X pline ("The %s itself to your hand!", aobjnam (uwep, "weld")); X else X prinv (uwep); X } X return (res); X} X Xcorrode_weapon () X{ X if (!uwep || uwep -> olet != WEAPON_SYM) X return; /* %% */ X if (uwep -> rustfree) X pline ("Your %s not affected.", aobjnam (uwep, "are")); X else { X pline ("Your %s!", aobjnam (uwep, "corrode")); X uwep -> spe--; X } X} X Xchwepon (otmp, amount) Xregister struct obj *otmp; Xregister amount; X{ X register char *color = (amount < 0) ? "black" : "green"; X register char *time; X if (!uwep || uwep -> olet != WEAPON_SYM) { X pline ((amount > 0) ? "Your hands glow then fade." : "Your hands itch."); X strange_feeling (otmp); X return (0); X } X X if (uwep -> otyp == WORM_TOOTH && amount > 0) { X uwep -> otyp = CRYSKNIFE; X pline ("Your weapon seems sharper now."); X uwep -> cursed = 0; X return (1); X } X X if (uwep -> otyp == CRYSKNIFE && amount < 0) { X uwep -> otyp = WORM_TOOTH; X pline ("Your weapon looks duller now."); X return (1); X } X X /* there is a (soft) upper limit to uwep->spe */ X if (amount > 0 && uwep -> spe > 5 && rn2 (3)) { X pline ("Your %s violently green for a while and then evaporates.", X aobjnam (uwep, "glow")); X useup (uwep); X return (1); X } X if (!rn2 (6)) X amount *= 2; X time = (amount * amount == 1) ? "moment" : "while"; X pline ("Your %s %s for a %s.", X aobjnam (uwep, "glow"), color, time); X uwep -> spe += amount; X if (amount > 0) X uwep -> cursed = 0; X return (1); X} --burp-- sed 's/^X//' << '--burp--' > hack.zap.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include "hack.h" X Xextern struct monst *makemon (); Xstruct monst *bhit (); Xchar *exclam (); X Xchar *fl[] = { X "magic missile", X "bolt of fire", X "sleep ray", X "bolt of cold", X "death ray" X}; X Xdozap () X{ X register struct obj *obj; X register struct monst *mtmp; X xchar zx, zy; X register num; X X obj = getobj ("/", "zap"); X if (!obj) X return (0); X if (obj -> spe < 0 || (obj -> spe == 0 && rn2 (121))) { X pline ("Nothing Happens"); X return (1); X } X if (obj -> spe == 0) X pline ("You wrest one more spell from the worn-out wand."); X if (!(objects[obj -> otyp].bits & NODIR) && !getdir ()) X return (1); /* make him pay for knowing !NODIR */ X obj -> spe--; X if (objects[obj -> otyp].bits & IMMEDIATE) { X if ((u.uswallow && (mtmp = u.ustuck)) || X (mtmp = bhit (u.dx, u.dy, rn1 (8, 6), 0))) { X wakeup (mtmp); X switch (obj -> otyp) { X case WAN_STRIKING: X if (rnd (20) < 10 + mtmp -> data -> ac) { X register int tmp = d (2, 12); X hit ("wand", mtmp, exclam (tmp)); X mtmp -> mhp -= tmp; X if (mtmp -> mhp < 1) X killed (mtmp); X } X else X miss ("wand", mtmp); X break; X case WAN_SLOW_MONSTER: X mtmp -> mspeed = MSLOW; X break; X case WAN_SPEED_MONSTER: X mtmp -> mspeed = MFAST; X break; X case WAN_UNDEAD_TURNING: X if (index ("WVZ&", mtmp -> data -> mlet)) { X mtmp -> mhp -= rnd (8); X if (mtmp -> mhp < 1) X killed (mtmp); X else X mtmp -> mflee = 1; X } X break; X case WAN_POLYMORPH: X if (newcham (mtmp, &mons[rn2 (CMNUM)])) X objects[obj -> otyp].oc_name_known = 1; X break; X case WAN_CANCELLATION: X mtmp -> mcan = 1; X break; X case WAN_TELEPORT_MONSTER: X rloc (mtmp); X break; X case WAN_MAKE_INVISIBLE: X mtmp -> minvis = 1; X break; X#ifdef WAN_PROBING X case WAN_PROBING: X mstatusline (mtmp); X break; X#endif WAN_PROBING X default: X pline ("What an interesting wand (%d)", X obj -> otyp); X impossible (); X } X } X } X else { X switch (obj -> otyp) { X case WAN_LIGHT: X litroom (TRUE); X break; X case WAN_SECRET_DOOR_DETECTION: X if (!findit ()) X return (1); X break; X case WAN_CREATE_MONSTER: X { X register int cnt = 1; X if (!rn2 (23)) X cnt += rn2 (7) + 1; X while (cnt--) X (void) makemon ((struct permonst *) 0, u.ux, u.uy); X } X break; X case WAN_WISHING: X { X char buf[BUFSZ]; X register struct obj *otmp; X extern struct obj *readobjnam (), *addinv (); X if ((u.uluck + rn2 (5) < 0) && (!wizard)) { X pline ("Unfortunately, nothing happens."); X break; X } X pline ("You may wish for an object. What do you want? "); X getlin (buf); X otmp = readobjnam (buf); X otmp = addinv (otmp); X prinv (otmp); X break; X } X case WAN_DIGGING: X { X register struct rm *room; X register int digdepth; X if (u.uswallow) { X pline ("You pierce %s's stomach wall!", X monnam (u.ustuck)); X u.uswallow = 0; X mnexto (u.ustuck); X u.ustuck -> mhp = 1;/* almost dead */ X u.ustuck = 0; X setsee (); X docrt (); X break; X } X zx = u.ux + u.dx; X zy = u.uy + u.dy; X if (!isok (zx, zy)) X break; X digdepth = 4 + rn2 (10); X if (levl[zx][zy].typ == CORR) X num = CORR; X else X num = ROOM; X Tmp_at (-1, '*'); /* open call */ X while (digdepth--) { X if (zx == 0 || zx == COLNO - 1 || X zy == 0 || zy == ROWNO - 1) X break; X room = &levl[zx][zy]; X Tmp_at (zx, zy); X if (!xdnstair) { X if (zx < 3 || zx > COLNO - 3 || X zy < 3 || zy > ROWNO - 3) X break; X if (room -> typ == HWALL || X room -> typ == VWALL) { X room -> typ = ROOM; X break; X } X } X else X if (num == ROOM || num == 10) { X if (room -> typ != ROOM && room -> typ) { X if (room -> typ != CORR) X room -> typ = DOOR; X if (num == 10) X break; X num = 10; X } X else X if (!room -> typ) X room -> typ = CORR; X } X else { X if (room -> typ != CORR && room -> typ) { X room -> typ = DOOR; X break; X } X else X room -> typ = CORR; X } X mnewsym (zx, zy); X zx += u.dx; X zy += u.dy; X } X mnewsym (zx, zy); /* not always necessary */ X Tmp_at (-1, -1); /* closing call */ X break; X } X default: X buzz ((int) obj -> otyp - WAN_MAGIC_MISSILE, X u.ux, u.uy, u.dx, u.dy); X break; X } X if (!objects[obj -> otyp].oc_name_known) { X u.urexp += 10; X objects[obj -> otyp].oc_name_known = 1; X } X } X return (1); X} X Xchar * Xexclam (force) Xregister int force; X{ X /* force == 0 occurs e.g. with sleep ray */ X /* note that large force is usual with wands so that !! would require information about hand/weapon/wand */ X return ((force < 0) ? "?" : (force <= 4) ? "." : "!"); X} X Xhit (str, mtmp, force) Xregister char *str; Xregister struct monst *mtmp; Xregister char *force; /* usually either "." or "!" */ X{ X if (!cansee (mtmp -> mx, mtmp -> my)) X pline ("The %s hits it.", str); X else X pline ("The %s hits %s%s", str, monnam (mtmp), force); X} X Xmiss (str, mtmp) Xregister char *str; Xregister struct monst *mtmp; X{ X if (!cansee (mtmp -> mx, mtmp -> my)) X pline ("The %s misses it.", str); X else X pline ("The %s misses %s.", str, monnam (mtmp)); X} X X/* sets bhitpos to the final position of the weapon thrown */ X/* coord bhitpos; */ X X/* check !u.uswallow before calling bhit() */ Xstruct monst * Xbhit (ddx, ddy, range, sym) Xregister ddx, ddy, range; Xchar sym; X{ X register struct monst *mtmp; X X bhitpos.x = u.ux; X bhitpos.y = u.uy; X X if (sym) X tmp_at (-1, sym); /* open call */ X while (range--) { X bhitpos.x += ddx; X bhitpos.y += ddy; X if (mtmp = m_at (bhitpos.x, bhitpos.y)) { X if (sym) X tmp_at (-1, -1); /* close call */ X return (mtmp); X } X if (levl[bhitpos.x][bhitpos.y].typ < CORR) { X bhitpos.x -= ddx; X bhitpos.y -= ddy; X break; X } X if (sym) X tmp_at (bhitpos.x, bhitpos.y); X } X if (sym) X tmp_at (-1, 0); /* leave last symbol */ X return (0); X} X Xstruct monst * Xboomhit (dx, dy) X{ X register int i, ct; X register struct monst *mtmp; X char sym = ')'; X extern schar xdir[], ydir[]; X X bhitpos.x = u.ux; X bhitpos.y = u.uy; X X for (i = 0; i < 8; i++) X if (xdir[i] == dx && ydir[i] == dy) X break; X tmp_at (-1, sym); /* open call */ X for (ct = 0; ct < 10; ct++) { X if (i == 8) X i = 0; X sym = ')' + '(' - sym; X tmp_at (-2, sym); /* change let call */ X dx = xdir[i]; X dy = ydir[i]; X bhitpos.x += dx; X bhitpos.y += dy; X if (mtmp = m_at (bhitpos.x, bhitpos.y)) { X tmp_at (-1, -1); X return (mtmp); X } X if (levl[bhitpos.x][bhitpos.y].typ < CORR) { X bhitpos.x -= dx; X bhitpos.y -= dy; X break; X } X if (bhitpos.x == u.ux && bhitpos.y == u.uy) {/* ct == 9 */ X if (rn2 (20) >= 10 + u.ulevel) {/* we hit ourselves */ X (void) thitu (10, rnd (10), "boomerang"); X break; X } X else { /* we catch it */ X tmp_at (-1, -1); X pline ("Skillfully, you catch the boomerang."); X return ((struct monst *) - 1); X } X } X tmp_at (bhitpos.x, bhitpos.y); X if (ct % 5 != 0) X i++; X } X tmp_at (-1, -1); /* do not leave last symbol */ X return (0); X} X Xchar Xdirlet (dx, dy) Xregister dx, dy; X{ X return (dx == dy) ? '\\' : (dx && dy) ? '/' : dx ? '-' : '|'; X} X X/* type < 0: monster spitting fire at you */ Xbuzz (type, sx, sy, dx, dy) Xregister int type; Xregister xchar sx, sy; Xregister int dx, dy; X{ X register char *fltxt = (type < 0) ? "blaze of fire" : fl[type]; X struct rm *lev; X xchar range; X struct monst *mon; X X if (u.uswallow) { X register int tmp; X X if (type < 0) X return; X tmp = zhit (u.ustuck, type); X pline ("The %s rips into %s%s", X fltxt, monnam (u.ustuck), exclam (tmp)); X return; X } X if (type < 0) X pru (); X range = rn1 (7, 7); X Tmp_at (-1, dirlet (dx, dy)); /* open call */ X while (range-- > 0) { X sx += dx; X sy += dy; X if ((lev = &levl[sx][sy]) -> typ) X Tmp_at (sx, sy); X else { X int bounce = 0; X if (cansee (sx - dx, sy - dy)) X pline ("The %s bounces!", fltxt); X if (levl[sx][sy - dy].typ > DOOR) X bounce = 1; X if (levl[sx - dx][sy].typ > DOOR) { X if (!bounce || rn2 (2)) X bounce = 2; X } X switch (bounce) { X case 0: X dx = -dx; X dy = -dy; X continue; X case 1: X dy = -dy; X sx -= dx; X break; X case 2: X dx = -dx; X sy -= dy; X break; X } X Tmp_at (-2, dirlet (dx, dy)); X continue; X } X if ((mon = m_at (sx, sy)) && X (type >= 0 || mon -> data -> mlet != 'D')) { X wakeup (mon); X if (rnd (20) < 18 + mon -> data -> ac) { X register int tmp = zhit (mon, type); X if (mon -> mhp < 1) { X if (type < 0) { X if (cansee (mon -> mx, mon -> my)) X pline ("%s is killed by the %s!", X Monnam (mon), fltxt); X mondied (mon); X } X else X killed (mon); X } X else X hit (fltxt, mon, exclam (tmp)); X range -= 2; X } X else X miss (fltxt, mon); X } X else X if (sx == u.ux && sy == u.uy) { X if (rnd (20) < 18 + u.uac) { X register int dam = 0; X range -= 2; X pline ("The %s hits you!", fltxt); X switch (type) { X case 0: X dam = d (2, 6); X break; X case -1: /* dragon fire */ X case 1: X if (Fire_resistance) X pline ("You don't feel hot!"); X else X dam = d (6, 6); X break; X case 2: X nomul (-rnd (25));/* sleep ray */ X break; X case 3: X if (Cold_resistance) X pline ("You don't feel cold!"); X else X dam = d (6, 6); X break; X case 4: X u.uhp = -1; X } X losehp (dam, fltxt); X } X else X pline ("The %s whizzes by you!", fltxt); X } X if (lev -> typ <= DOOR) { X int bounce = 0, rmn; X if (cansee (sx, sy)) X pline ("The %s bounces!", fltxt); X range--; X if (!dx || !dy || !rn2 (20)) { X dx = -dx; X dy = -dy; X } X else { X if ((rmn = levl[sx][sy - dy].typ) > DOOR && X ( X rmn >= ROOM || X levl[sx + dx][sy - dy].typ > DOOR)) { X bounce = 1; X } X if ((rmn = levl[sx - dx][sy].typ) > DOOR && X ( X rmn >= ROOM || X levl[sx - dx][sy + dy].typ > DOOR)) { X if (!bounce || rn2 (2)) { X bounce = 2; X } X } X switch (bounce) { X case 0: X dy = -dy; X dx = -dx; X break; X case 1: X dy = -dy; X break; X case 2: X dx = -dx; X break; X } X Tmp_at (-2, dirlet (dx, dy)); X } X } X } X Tmp_at (-1, -1); X} X Xzhit (mon, type) /* returns damage to mon */ Xregister struct monst *mon; Xregister type; X{ X register int tmp = 0; X X switch (type) { X case 0: /* magic missile */ X tmp = d (2, 6); X break; X case -1: /* Dragon blazing fire */ X case 1: /* fire */ X if (index ("Dg", mon -> data -> mlet)) X break; X tmp = d (6, 6); X if (mon -> data -> mlet == 'Y') X tmp += 7; X break; X case 2: /* sleep */ X mon -> mfroz = 1; X break; X case 3: /* cold */ X if (index ("YFgf", mon -> data -> mlet)) X break; X tmp = d (6, 6); X if (mon -> data -> mlet == 'D') X tmp += 7; X break; X case 4: /* death */ X if (index ("WVZ", mon -> data -> mlet)) X break; X tmp = mon -> mhp + 1; X break; X } X mon -> mhp -= tmp; X return (tmp); X} --burp-- sed 's/^X//' << '--burp--' > help X Welcome to HACK! X XHack is a Dungeons and Dragons like game where you (the adventurer) descend Xinto the depths of the dungeon in search of the Amulet of Yendor (reputed Xto be hidden on the twentieth level). You are accompanied by a little dog Xthat can help you in many ways and can be trained to do all sorts of Xthings. On the way you will find useful (or useless) items, (quite possi- Xbly with magic properties) and assorted monsters. You attack a monster by Xtrying to move into the space a monster is in (but often it is much wiser Xto leave it alone). X XUnlike most adventure games, which give you a verbal description of your Xlocation, hack gives you a visual image of the dungeon level you are on. X XHack uses the following symbols: X X A-Z and a-z Monsters. You can find out what a letter X represents by saying "/ (letter)", as in "/A", X which will tell you that 'A' is a giant ant. X X - and | These form the walls of a room (or maze). X X . this is the floor of a room. X X # this is a corridor. X X > this is the staircase to the next level. X X < the staircase to the previous level. X X ` A large boulder. X X @ You (usually). X X ^ A trap. X X ) A weapon of some sort. X X ( Some other useful object (key, rope, dynamite, X camera, ...) X X [ A suit of armor. X X % A piece of food (not necessarily healthy ...). X X / A wand. X X = A ring. X X ? A scroll. X X ! A magic potion. X X $ A pile or pot of gold. X X X Commands: X X Hack knows the following commands: X X ? help: print this list. X X Q Quit the game. X X < up: go up the staircase (if you are standing on X it). X X > down: go down (just like up). X X kjhlyubn go one step in the direction indicated. k: north X (i.e., to the top of the screen), j: south, h: X west, l: east, y: ne, u: nw, b: se, n: sw. X X KJHLYUBN Go in that direction until you hit a wall or run X into something. X X m (followed by one of kjhlyubn): move without pick- X ing up any objects. X X M (followed by one of KJHLYUBN): Move far, no pick- X up. X X f (followed by one of kjhlyubn): move until some- X thing interesting is found. X X F (followed by one of KJHLYUBN): as previous, but X forking of corridors is not considered interest- X ing. X X i print your inventory. X X I print selected parts of your inventory. X X s search for secret doors and traps around you. X X ^ ask for the type of a trap you found earlier. X X ) ask for current wielded weapon. X X [ ask for current armor. X X = ask for current rings. X X . rest, do nothing. X X ^R redraw the screen. X X ^P repeat last message (subsequent ^P's repeat ear- X lier messages). X X / (followed by any symbol): tell what this symbol X represents. X X e eat food. X X w wield weapon. w- means: wield nothing, use bare X hands. X X q drink (quaff) a potion. X X r read a scroll. X X T Takeoff armor. X X R Remove Ring. X X W Wear armor. X X P Put on a ring. X X t throw or shoot a weapon. X X p pay your shopping bill. X X d drop something. d7a: drop seven items of object a. X X D Drop several things. In answer to the question X "What kinds of things do you want to drop? [!%= X au]" you should give zero or more object symbols X possibly followed by 'a' and/or 'u'. X X a use, apply - Generic command for using a key to X lock or unlock a door, using a camera, using a X rope, etc. X X c call: name a certain object or class of objects. X X C Call: Name an individual monster. X X E Engrave: Write a message in the dust on the floor. X E- means: use fingers for X writing. X X o set options. (see below) X X v print version number. X X \ print a list of things discovered. X X XYou can put a number before a command to repeat it that many times, as in X"20s" or "40.". X X Options: X XTo turn an option on, say 'ox', where x is the optionletter. To turn it Xoff, say 'o!x'. X The following options currently exist. X X X e echo - Echo typed characters. X X o oneline - Give inventories one line at a time (at X the top of your screen). X X X Have Fun, and Good Hacking! X --burp-- sed 's/^X//' << '--burp--' > help.nr X.pl 1 X.ll 75 X.ce 1 X Welcome to HACK! X.sp 1 XHack is a Dungeons and Dragons like game where you (the adventurer) Xdescend into the depths of the dungeon in search of the Amulet of Yendor X(reputed to be hidden on the twentieth level). XYou are accompanied by a little dog that can help you in many ways and Xcan be trained to do all sorts of things. XOn the way you will find useful (or useless) items, (quite possibly with Xmagic properties) and assorted monsters. XYou attack a monster by trying to move into the space a monster is Xin (but often it is much wiser to leave it alone). X XUnlike 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 XHack uses the following symbols: X.de TE X.sp X.ti 0 X.. X.ta 5m 25m X.in 25m X.TE X A-Z\ and a-z \ XMonsters. XYou can find out what a letter represents by saying "/ (letter)", Xas in "/A", which will tell you that 'A' is a giant ant. X.TE X - and | \ XThese form the walls of a room (or maze). X.TE X \. \ Xthis is the floor of a room. X.TE X # \ Xthis is a corridor. X.TE X > \ Xthis is the staircase to the next level. X.TE X < \ Xthe staircase to the previous level. X.TE X ` \ XA large boulder. X.TE X @ \ XYou (usually). X.TE X ^ \ XA trap. X.TE X ) \ XA weapon of some sort. X.TE X ( \ XSome other useful object (key, rope, dynamite, camera, ...) X.TE X [ \ XA suit of armor. X.TE X % \ XA piece of food (not necessarily healthy ...). X.TE X / \ XA wand. X.TE X = \ XA ring. X.TE X ? \ XA scroll. X.TE X ! \ XA magic potion. X.TE X $ \ XA pile or pot of gold. X.TE X.in 0 X.sp X.ce 1 XCommands: X.sp X Hack knows the following commands: X.ta 5m 25m X.in 25m X.TE X ? \ Xhelp: print this list. X.TE X Q \ XQuit the game. X.TE X < \ Xup: go up the staircase (if you are standing on it). X.TE X > \ Xdown: go down (just like up). X.TE X kjhlyubn \ Xgo one step in the direction indicated. Xk: north (i.e., to the top of the screen), j: south, h: west, l: east, y: ne, u: nw, b: se, n: sw. X.TE X KJHLYUBN \ XGo in that direction until you hit a wall or run into something. X.TE X m \ X(followed by one of kjhlyubn): move without picking up any objects. X.TE X M \ X(followed by one of KJHLYUBN): Move far, no pickup. X.TE X f \ X(followed by one of kjhlyubn): move until something interesting is found. X.TE X F \ X(followed by one of KJHLYUBN): as previous, but forking of corridors is not considered interesting. X.TE X i \ Xprint your inventory. X.TE X I \ Xprint selected parts of your inventory. X.TE X s \ Xsearch for secret doors and traps around you. X.TE X ^ \ Xask for the type of a trap you found earlier. X.TE X ) \ Xask for current wielded weapon. X.TE X [ \ Xask for current armor. X.TE X = \ Xask for current rings. X.TE X \. \ Xrest, do nothing. X.TE X ^R \ Xredraw the screen. X.TE X ^P \ Xrepeat last message (subsequent ^P's repeat earlier messages). X.TE X / \ X(followed by any symbol): tell what this symbol represents. X.TE X e \ Xeat food. X.TE X w \ Xwield weapon. w- means: wield nothing, use bare hands. X.TE X q \ Xdrink (quaff) a potion. X.TE X r \ Xread a scroll. X.TE X T \ XTakeoff armor. X.TE X R \ XRemove Ring. X.TE X W \ XWear armor. X.TE X P \ XPut on a ring. X.TE X t \ Xthrow or shoot a weapon. X.TE X p \ Xpay your shopping bill. X.TE X d \ Xdrop something. d7a: drop seven items of object a. X.TE X D \ XDrop several things. XIn answer to the question "What kinds of things do you want to drop? [!%= au]" Xyou should give zero or more object symbols possibly followed by 'a' and/or 'u'. X'a' means: drop all such objects, without asking for confirmation. X'u' means: drop only unpaid objects (when in a shop). X.TE X a \ Xuse, apply - Generic command for using a key to lock or unlock a door, using a camera, using a rope, etc. X.TE X c \ Xcall: name a certain object or class of objects. X.TE X C \ XCall: Name an individual monster. X.TE X E \ XEngrave: Write a message in the dust on the floor. X E- means: use fingers for writing. X.TE X o \ Xset options. (see below) X.TE X v \ Xprint version number. X.TE X \\ \ Xprint a list of things discovered. X.TE X.in 0 X.sp 2 XYou can put a number before a command to repeat it that many times, as in "20s" or "40.". X.sp X.ce 1 X Options: X.sp XTo turn an option on, say 'ox', where x is the optionletter. XTo turn it off, say 'o!x'. X The following options currently exist. X X.ta 5m 25m X.in 25m X.TE X e \ Xecho - Echo typed characters. X.TE X o \ Xoneline - Give inventories one line at a time (at the top of your screen). X.TE X.in 0 X.sp 3 X.ce 1 X Have Fun, and Good Hacking! --burp-- sed 's/^X//' << '--burp--' > hh Xy k u Move commands: X \|/ hykulnjb: single move in specified direction Xh-+-l HYKULNJB: repeated move in specified direction X /|\ (until stopped by e.g. a wall) Xb j n f<dir>: fast movement in direction <dir> X (until something interesting is seen) X m<dir>: move without picking up objects X XMeta commands: XQ quit leave the game XS save save the game (to be continued later) Xo set set options X? help print information X/ whatis give name (and sometimes more info) of specified monster X\ known print list of what's been discovered X! sh escape to some SHELL Xv version print version number X^R redraw redraw the screen (^R denotes the symbol CTRL/R) X^P print repeat last message (subsequent ^P's repeat earlier messages) X XGame commands: Xa apply, use use something (a key, camera, etc.) Xc call give a name to a class of objects Xd drop drop an object. d7a: drop seven items of object a. Xe eat eat something Xi invent list the inventory (and shopping bill) XI invent list selected parts of the inventory Xp pay pay your bill Xq drink quaff a potion Xr read read a scroll Xs search search for secret doors, hidden traps and monsters Xt throw throw or shoot a weapon Xw wield wield a weapon (w- wield nothing) Xz zap zap a wand XC name name an individual monster (e.g., baptize your dog) XD Drop drop several things XE Engrave write a message in the dust on the floor (E- use fingers) XP wear put on a ring XR remove remove a ring XT remove take off some armor XW wear put on some armor X< up go up the stairs X> down go down the stairs X^ trap_id identify a previously found trap X),[,= ask for current weapon, armor, rings, respectively X. or <space> wait a moment --burp-- sed 's/^X//' << '--burp--' > mklev.c X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ X X#include <stdio.h> X#include "mklev.h" X#include "def.trap.h" X Xextern char *getlogin (); Xextern struct monst *makemon (); X Xchar *tfile, *tspe, **args; Xchar nul[40]; Xlong time (); X X#include "savelev.h" X X#ifdef WIZARD Xboolean wizard; X#endif WIZARD X X#define somex() ((rand()%(croom->hx-croom->lx+1))+croom->lx) X#define somey() ((rand()%(croom->hy-croom->ly+1))+croom->ly) X Xstruct rm levl[COLNO][ROWNO]; Xstruct monst *fmon; Xstruct obj *fobj; Xstruct gen *fgold, *ftrap; X Xchar *fut_geno; /* monsters that should not be created anymore */ X Xstruct mkroom rooms[MAXNROFROOMS + 1], *croom, *troom; Xcoord doors[DOORMAX]; Xint doorindex = 0; Xint comp (); X Xxchar dlevel; Xschar nxcor, xx, yy, dx, dy, tx, ty; /* for corridors and other things... */ Xboolean goldseen; Xint nroom; X Xxchar xdnstair, xupstair, ydnstair, yupstair; X X Xmain (argc, argv) Xchar *argv[]; X{ 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 < 1) X panic ("Bad level"); X fut_geno = argv[4]; X#ifdef WIZARD X wizard = (argv[5][0] == 'w'); X#endif WIZARD X (void) srand ((int) time ((long *) 0)); X init_objects (); X rooms[0].hx = -1; /* in case we are in a maze */ X X /* a: normal; b: maze */ X if (*tspe == 'b') { X makemaz (); X savelev (); X exit (0); X } X X /* construct the rooms */ X while (nroom < (MAXNROFROOMS / 3)) { X croom = rooms; X nroom = 0; X (void) makerooms (0); /* not secret */ X } 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 (void) X makemon ((struct permonst *) 0, somex (), somey ()); X X /* put traps and mimics inside */ X goldseen = FALSE; X while (!rn2 (8 - (dlevel / 6))) X mktrap (0, 0); X if (!goldseen && !rn2 (3)) X mkgold (0, somex (), somey ()); X if (!rn2 (3)) { X mkobj_at (0, somex (), somey ()); X tryct = 0; X while (!rn2 (5)) { X if (++tryct > 100) { X printf ("tryct overflow4\n"); X break; X } X mkobj_at (0, somex (), somey ()); X } X } 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' && (!(xdnstair % 2) || !(ydnstair % 2))) || X g_at (xdnstair, ydnstair, ftrap)); X levl[xdnstair][ydnstair].scrsym = '>'; X levl[xdnstair][ydnstair].typ = STAIRS; 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 g_at (xupstair, yupstair, ftrap)); X levl[xupstair][yupstair].scrsym = '<'; X levl[xupstair][yupstair].typ = STAIRS; X X qsort ((char *) rooms, nroom, sizeof (struct mkroom), comp); X croom = rooms; X troom = croom + 1; X nxcor = 0; X mkpos (); X do X makecor (); X while (croom -> hx > 0 && troom -> hx > 0); X X /* make a secret treasure vault, not connected to the rest */ X if (nroom < (2 * MAXNROFROOMS / 3)) X if (!rn2 (3)) { X register int x, y; X troom = croom = &rooms[nroom]; X if (makerooms (1)) { /* make secret room */ X troom -> rtype = 6; /* treasure vault */ X for (x = troom -> lx; x <= troom -> hx; x++) X for (y = troom -> ly; y <= troom -> hy; y++) X mkgold (rnd (dlevel * 100) + 50, x, y); X } X } X X#ifdef WIZARD X if (wizard) { X if (rn2 (3)) X mkshop (); X else X mkzoo (); X } X else X#endif WIZARD X if (dlevel > 1 && dlevel < 20 && rn2 (dlevel) < 2) X mkshop (); X else X if (dlevel > 6 && !rn2 (7)) X mkzoo (); X savelev (); X exit (0); X} X Xmakerooms (secret) int secret; { X register int lowx, lowy; X register int tryct = 0; X while (nroom < (MAXNROFROOMS / 2) || secret) X for (lowy = rn1 (3, 3); lowy < ROWNO - 7; lowy += rn1 (2, 4)) { X for (lowx = rn1 (3, 4); lowx < COLNO - 10; lowx += rn1 (2, 7)) { X if (tryct++ > 10000) X return (0); X if ((lowy += (rn2 (5) - 2)) < 3) X lowy = 3; X else X if (lowy > ROWNO - 6) X lowy = ROWNO - 6; X if (levl[lowx][lowy].typ) X continue; X if ((secret && maker (lowx, 1, lowy, 1)) || X (!secret && maker (lowx, rn1 (9, 2), lowy, rn1 (4, 2)) X && nroom + 2 > MAXNROFROOMS)) X return (1); X } X } X return (1); X} X Xcomp (x, y) Xregister struct mkroom *x, *y; X{ X if (x -> lx < y -> lx) X return (-1); X return (x -> lx > y -> lx); X} X Xcoord Xfinddpos (xl, yl, xh, yh) { X coord ff; X register x, y; X ff.x = (xl == xh) ? xl : (xl + rn2 (xh - xl + 1)); X ff.y = (yl == yh) ? yl : (yl + rn2 (yh - yl + 1)); X if (okdoor (ff.x, ff.y)) X return (ff); X if (xl < xh) X for (x = xl; x <= xh; x++) X if (okdoor (x, ff.y)) { X ff.x = x; X return (ff); X } X if (yl < yh) X for (y = yl; y <= yh; y++) X if (okdoor (ff.x, y)) { X ff.y = y; X return (ff); X } X return (ff); X} X X/* when croom and troom exist, find position for a door in croom X and direction for a corridor towards position [tx,ty] in the wall X of troom */ Xmkpos () { X coord cc, tt; X if (troom -> hx < 0 || croom -> hx < 0 || doorindex >= DOORMAX) X return; X if (troom -> lx > croom -> hx) { X dx = 1; X dy = 0; X xx = croom -> hx + 1; X tx = troom -> lx - 1; X cc = finddpos (xx, croom -> ly, xx, croom -> hy); X tt = finddpos (tx, troom -> ly, tx, troom -> hy); X } X else X if (troom -> hy < croom -> ly) { X dy = -1; X dx = 0; X yy = croom -> ly - 1; X cc = finddpos (croom -> lx, yy, croom -> hx, yy); X ty = troom -> hy + 1; X tt = finddpos (troom -> lx, ty, troom -> hx, ty); X } X else X if (troom -> hx < croom -> lx) { X dx = -1; X dy = 0; X xx = croom -> lx - 1; X tx = troom -> hx + 1; X cc = finddpos (xx, croom -> ly, xx, croom -> hy); X tt = finddpos (tx, troom -> ly, tx, troom -> hy); X } X else { X dy = 1; X dx = 0; X yy = croom -> hy + 1; X ty = troom -> ly - 1; X cc = finddpos (croom -> lx, yy, croom -> hx, yy); X tt = finddpos (troom -> lx, ty, troom -> hx, ty); X } X xx = cc.x; X yy = cc.y; X tx = tt.x; X ty = tt.y; X if (levl[xx + dx][yy + dy].typ) { X if (nxcor) X newloc (); X else { X dodoor (xx, yy, croom); X xx += dx; X yy += dy; X } X return; X } X dodoor (xx, yy, croom); X} X X/* if allowable, create a door at [x,y] */ Xokdoor (x, y) Xregister x, y; X{ X if (levl[x - 1][y].typ == DOOR || levl[x + 1][y].typ == DOOR || X levl[x][y + 1].typ == DOOR || levl[x][y - 1].typ == DOOR || X levl[x - 1][y].typ == SDOOR || levl[x + 1][y].typ == SDOOR || X levl[x][y - 1].typ == SDOOR || levl[x][y + 1].typ == SDOOR || X (levl[x][y].typ != HWALL && levl[x][y].typ != VWALL) || X doorindex >= DOORMAX) X return (0); X return (1); X} X Xdodoor (x, y, aroom) Xregister x, y; Xregister struct mkroom *aroom; X{ X register struct mkroom *broom; X register tmp; X if (doorindex >= DOORMAX) X panic ("DOORMAX exceeded?"); X if (!okdoor (x, y) && nxcor) X return; X if (!rn2 (8)) X levl[x][y].typ = SDOOR; X else { X levl[x][y].scrsym = '+'; X levl[x][y].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] = doors[tmp - 1]; X doorindex++; X doors[tmp].x = x; X doors[tmp].y = y; X for (; broom -> hx >= 0; broom++) X broom -> fdoor++; X} X Xnewloc () { X register a, b; 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 a = rn2 (nroom); X b = rn2 (nroom); X croom = &rooms[a]; X troom = &rooms[b]; X } while (croom == troom || (troom == croom + 1 && !rn2 (3))); X } X mkpos (); X} X X/* make a trap somewhere (in croom if mazeflag = 0) */ Xmktrap (num, mazeflag) Xregister num, mazeflag; X{ X register struct gen *gtmp; X register int kind, nopierc, nomimic, fakedoor, fakegold, tryct = 0; X register xchar mx, my; X X if (!num || num >= TRAPNUM) { X nopierc = (dlevel < 4) ? 1 : 0; X nomimic = (dlevel < 9 || goldseen) ? 1 : 0; X if (index (fut_geno, 'M')) X nomimic = 1; X kind = rn2 (TRAPNUM - nopierc - nomimic); X /* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */ X } X else X kind = num; X X if (kind == MIMIC) { X register struct monst *mtmp; X X fakedoor = (!rn2 (3) && !mazeflag); X fakegold = (!fakedoor && !rn2 (2)); X if (fakegold) X goldseen = TRUE; X do { X if (++tryct > 200) X return; X if (fakedoor) { X /* note: fakedoor maybe on actual door */ X if (rn2 (2)) { X if (rn2 (2)) X mx = croom -> hx + 1; X else X mx = croom -> lx - 1; X my = somey (); X } X else { X if (rn2 (2)) X my = croom -> hy + 1; X else X my = croom -> ly - 1; X mx = somex (); X } X } X else X if (mazeflag) { X extern coord mazexy (); X coord mm; X mm = mazexy (); X mx = mm.x; X my = mm.y; X } X else { X mx = somex (); X my = somey (); X } X } while (m_at (mx, my)); X if (mtmp = makemon (PM_MIMIC, mx, my)) X mtmp -> mimic = X fakegold ? '$' : fakedoor ? '+' : X (mazeflag && rn2 (2)) ? AMULET_SYM : X "=/)%?![<>"[rn2 (9)]; X return; X } X gtmp = newgen (); X gtmp -> gflag = kind; X do { X if (++tryct > 200) { X printf ("tryct overflow7\n"); X free ((char *) gtmp); X return; X } X if (mazeflag) { X extern coord mazexy (); X coord mm; X mm = mazexy (); X gtmp -> gx = mm.x; X gtmp -> gy = mm.y; X } X else { X gtmp -> gx = somex (); X gtmp -> gy = somey (); X } X } while (g_at (gtmp -> gx, gtmp -> gy, ftrap)); X gtmp -> ngen = ftrap; X ftrap = gtmp; X if (mazeflag && !rn2 (10) && gtmp -> gflag < PIERC) X gtmp -> gflag |= SEEN; X} X X/*VARARGS1*/ Xpanic (str, arg1, arg2, arg3) Xchar *str, *arg1, *arg2, *arg3; X{ X char bufr[BUFSZ]; X extern char *sprintf (); X (void) sprintf (bufr, str, arg1, arg2, arg3); X (void) write (1, "\nMKLEV ERROR: ", 15); X puts (bufr); X (void) fflush (stdout); X exit (1); X} X Xmaker (lowx, ddx, lowy, ddy) Xschar lowx, ddx, lowy, ddy; X{ X register x, y, hix = lowx + ddx, hiy = lowy + ddy; X X if (nroom >= MAXNROFROOMS) X return (0); X if (hix > COLNO - 5) X hix = COLNO - 5; X if (hiy > ROWNO - 4) X hiy = ROWNO - 4; Xchk: X if (hix <= lowx || hiy <= lowy) X return (0); X X /* check area around room (and make room smaller if necessary) */ X for (x = lowx - 4; x <= hix + 4; x++) X for (y = lowy - 3; y <= hiy + 3; y++) X if (levl[x][y].typ) { X if (rn2 (3)) X return (0); X lowx = x + 5; X lowy = y + 4; X goto chk; X } X X /* on low levels the room is lit (usually) */ X /* secret vaults are always lit */ X if ((rnd (dlevel) < 10 && rn2 (77)) || (ddx == 1 && ddy == 1)) X for (x = lowx - 1; x <= hix + 1; x++) X for (y = lowy - 1; y <= hiy + 1; y++) X levl[x][y].lit = 1; X croom -> lx = lowx; X croom -> hx = hix; X croom -> ly = lowy; X croom -> hy = hiy; X croom -> rtype = croom -> doorct = croom -> fdoor = 0; X for (x = lowx - 1; x <= hix + 1; x++) X for (y = lowy - 1; y <= hiy + 1; y += (hiy - lowy + 2)) { X levl[x][y].scrsym = '-'; X levl[x][y].typ = HWALL; X } X for (x = lowx - 1; x <= hix + 1; x += (hix - lowx + 2)) X for (y = lowy; y <= hiy; y++) { X levl[x][y].scrsym = '|'; X levl[x][y].typ = VWALL; X } X for (x = lowx; x <= hix; x++) X for (y = lowy; y <= hiy; y++) { X levl[x][y].scrsym = '.'; X levl[x][y].typ = ROOM; X } X croom++; X croom -> hx = -1; X nroom++; X return (1); X} X Xmakecor () { X register nx, ny; X register struct rm *crm; X register dix, diy, secondtry = 0; X Xtryagain: X nx = xx + dx; X ny = yy + dy; X X if (nxcor && !rn2 (35)) { X newloc (); X return; X } X if (nx == COLNO - 1 || nx == 0 || ny == 0 || ny == ROWNO - 1) { X if (nxcor) { X newloc (); X return; X } X else { X printf ("something went wrong. we try again...\n"); X execl ("./mklev", args[0], tfile, tspe, args[3], args[4], args[5], 0); X panic ("cannot execute ./mklev\n"); X } X } X X dix = abs (nx - tx); X diy = abs (ny - ty); X if (dy && dix > diy) { X dy = 0; X dx = (nx > tx) ? -1 : 1; X } X else X if (dx && diy > dix) { X dx = 0; X dy = (ny > ty) ? -1 : 1; X } X X crm = &levl[nx][ny]; X if (!(crm -> typ)) { X if (rn2 (100)) { X crm -> typ = CORR; X crm -> scrsym = CORR_SYM; X } X else { X crm -> typ = SCORR; X crm -> scrsym = ' '; X } X xx = nx; X yy = ny; X if (nxcor && !rn2 (50)) { X mkobj_at (ROCK_SYM, nx, ny); X } X return; X } X if (crm -> typ == CORR || crm -> typ == SCORR) { X xx = nx; X yy = ny; X return; X } X if (nx == tx && ny == ty) { X dodoor (nx, ny, troom); X newloc (); X return; X } X if (!secondtry++ && (nx != xx + dx || ny != yy + dy)) X goto tryagain; X if (dx) { X if (ty < ny) X dy = -1; X else X dy = levl[nx + dx][ny - 1].typ == ROOM ? 1 : -1; X dx = 0; X } X else { X if (tx < nx) X dx = -1; X else X dx = levl[nx - 1][ny + dy].typ == ROOM ? 1 : -1; X dy = 0; X } X} X Xstruct monst * X m_at (x, y) Xregister x, y; X{ X register struct monst *mtmp; X X for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) X if (mtmp -> mx == x && mtmp -> my == y) X return (mtmp); X return (0); X} X Xstruct gen * X g_at (x, y, ptr) Xregister x, y; Xregister struct gen *ptr; X{ X while (ptr) { X if (ptr -> gx == x && ptr -> gy == y) X return (ptr); X ptr = ptr -> ngen; X } X return (0); X} --burp-- exit -- Robert Viduya Office of Computing Services Georgia Institute of Technology, Atlanta GA 30332 Phone: (404) 894-4669 ...!{akgua,allegra,amd,hplabs,ihnp4,masscomp,ut-ngp}!gatech!gitpyr!robert ...!{rlgvax,sb1,uf-cgrl,unmvax,ut-sally}!gatech!gitpyr!robert