home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
part34
< prev
next >
Wrap
Internet Message Format
|
1993-02-01
|
59KB
Path: uunet!news.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v16i034: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part34/108
Message-ID: <4322@master.CNA.TEK.COM>
Date: 29 Jan 93 20:47:05 GMT
Sender: news@master.CNA.TEK.COM
Lines: 1942
Approved: billr@saab.CNA.TEK.COM
Xref: uunet comp.sources.games:1591
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 16, Issue 34
Archive-name: nethack31/Part34
Supersedes: nethack3p9: Volume 10, Issue 46-102
Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 34 (of 108)."
# Contents: src/hack.c sys/os2/Install.os2
# Wrapped by billr@saab on Wed Jan 27 16:08:59 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/hack.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/hack.c'\"
else
echo shar: Extracting \"'src/hack.c'\" \(39188 characters\)
sed "s/^X//" >'src/hack.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)hack.c 3.1 92/12/04 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
XSTATIC_DCL int NDECL(moverock);
X#ifdef POLYSELF
XSTATIC_DCL int FDECL(still_chewing,(XCHAR_P,XCHAR_P));
X#endif
X#ifdef SINKS
XSTATIC_DCL void NDECL(dosinkfall);
X#endif
XSTATIC_DCL boolean FDECL(bad_rock,(XCHAR_P,XCHAR_P));
XSTATIC_DCL boolean FDECL(monstinroom, (struct permonst *,int));
X
Xstatic void FDECL(move_update, (BOOLEAN_P));
X
X#define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE)
X
X#ifdef OVL2
X
Xboolean
Xrevive_nasty(x, y, msg)
Xint x,y;
Xconst char *msg;
X{
X register struct obj *otmp, *otmp2;
X struct monst *mtmp;
X coord cc;
X boolean revived = FALSE;
X
X /* prevent freeobj() of revivable corpses */
X for(otmp = level.objects[x][y]; otmp; otmp = otmp2) {
X otmp2 = otmp->nexthere;
X if (otmp->otyp == CORPSE &&
X (is_rider(&mons[otmp->corpsenm]) ||
X otmp->corpsenm == PM_WIZARD_OF_YENDOR)) {
X /* move any living monster already at that location */
X if((mtmp = m_at(x,y)) && enexto(&cc, x, y, mtmp->data))
X rloc_to(mtmp, cc.x, cc.y);
X if(msg) Norep("%s", msg);
X revive_corpse(otmp, 0, FALSE);
X revived = MON_AT(x,y);
X }
X }
X
X /* this location might not be safe, if not, move revived monster */
X if (revived) {
X mtmp = m_at(x,y);
X if (mtmp && !goodpos(x, y, mtmp, mtmp->data) &&
X enexto(&cc, x, y, mtmp->data)) {
X rloc_to(mtmp, cc.x, cc.y);
X }
X /* else impossible? */
X }
X
X return (revived);
X}
X
XSTATIC_OVL int
Xmoverock()
X{
X register xchar rx, ry;
X register struct obj *otmp, *otmp2;
X register struct trap *ttmp;
X register struct monst *mtmp;
X
X while ((otmp = sobj_at(BOULDER, u.ux+u.dx, u.uy+u.dy)) != 0) {
X rx = u.ux+2*u.dx;
X ry = u.uy+2*u.dy;
X nomul(0);
X if (Levitation || Is_airlevel(&u.uz)) {
X if (Blind) feel_location(u.ux+u.dx,u.uy+u.dy);
X You("don't have enough leverage to push %s.", the(xname(otmp)));
X /* Give them a chance to climb over it? */
X return -1;
X }
X#ifdef POLYSELF
X if (verysmall(uasmon)) {
X if (Blind) feel_location(u.ux+u.dx,u.uy+u.dy);
X pline("You're too small to push that %s.", xname(otmp));
X goto cannot_push;
X }
X#endif
X if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
X (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) || (
X#ifdef REINCARNATION
X !Is_rogue_level(&u.uz) &&
X#endif
X (levl[rx][ry].doormask & ~D_BROKEN) == D_NODOOR)) &&
X !sobj_at(BOULDER, rx, ry)) {
X ttmp = t_at(rx, ry);
X mtmp = m_at(rx, ry);
X
X if (revive_nasty(rx, ry, "You sense movement on the other side."))
X return (-1);
X
X if (mtmp && (!mtmp->mtrapped ||
X !(ttmp && ((ttmp->ttyp == PIT) ||
X (ttmp->ttyp == SPIKED_PIT))))) {
X if (canseemon(mtmp))
X pline("There's %s on the other side.", mon_nam(mtmp));
X else {
X if (Blind) feel_location(u.ux+u.dx,u.uy+u.dy);
X You("hear a monster behind %s.", the(xname(otmp)));
X }
X if (flags.verbose)
X pline("Perhaps that's why you cannot move it.");
X goto cannot_push;
X }
X
X if (ttmp)
X switch(ttmp->ttyp) {
X case SPIKED_PIT:
X case PIT:
X freeobj(otmp);
X if (!flooreffects(otmp, rx, ry, "fall")) {
X place_object(otmp, rx, ry);
X otmp->nobj = fobj;
X fobj = otmp;
X }
X continue;
X case TRAPDOOR:
X pline("%s falls into and plugs a hole in the ground!",
X The(xname(otmp)));
X deltrap(ttmp);
X delobj(otmp);
X delallobj(rx, ry);
X if (cansee(rx,ry)) newsym(rx,ry);
X continue;
X case LEVEL_TELEP:
X case TELEP_TRAP:
X You("push %s and suddenly it disappears!",
X the(xname(otmp)));
X rloco(otmp);
X continue;
X }
X if (closed_door(rx, ry))
X goto nopushmsg;
X if (boulder_hits_pool(otmp, rx, ry, TRUE))
X continue;
X /*
X * Re-link at top of fobj chain so that pile order is preserved
X * when level is restored.
X */
X if (otmp != fobj) {
X otmp2 = fobj;
X while (otmp2->nobj && otmp2->nobj != otmp)
X otmp2 = otmp2->nobj;
X if (!otmp2->nobj) {
X impossible("moverock: error in fobj chain");
X } else {
X otmp2->nobj = otmp->nobj;
X otmp->nobj = fobj;
X fobj = otmp;
X }
X }
X
X {
X#ifdef LINT /* static long lastmovetime; */
X long lastmovetime;
X lastmovetime = 0;
X#else
X static long NEARDATA lastmovetime;
X#endif
X /* note: this var contains garbage initially and
X after a restore */
X if (moves > lastmovetime+2 || moves < lastmovetime)
X pline("With great effort you move %s.", the(xname(otmp)));
X exercise(A_STR, TRUE);
X lastmovetime = moves;
X }
X
X /* Move the boulder *after* the message. */
X move_object(otmp, rx, ry);
X if (Blind) {
X feel_location(rx,ry);
X feel_location(u.ux+u.dx, u.uy+u.dy);
X } else {
X newsym(rx,ry);
X newsym(u.ux+u.dx, u.uy+u.dy);
X }
X } else {
X nopushmsg:
X You("try to move %s, but in vain.", the(xname(otmp)));
X if (Blind) feel_location(u.ux+u.dx, u.uy+u.dy);
X cannot_push:
X#ifdef POLYSELF
X if (throws_rocks(uasmon)) {
X if (!flags.pickup)
X pline("However, you easily can push it aside.");
X else
X pline("However, you easily can pick it up.");
X break;
X }
X#endif
X if (((!invent || inv_weight() <= -850) &&
X (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][u.uy+u.dy].typ)
X && IS_ROCK(levl[u.ux+u.dx][u.uy].typ))))
X#ifdef POLYSELF
X || verysmall(uasmon)
X#endif
X ) {
X pline("However, you can squeeze yourself into a small opening.");
X break;
X } else
X return (-1);
X }
X }
X return (0);
X}
X
X#ifdef POLYSELF
X/*
X * still_chewing()
X *
X * Chew on a wall, door, or boulder. Returns TRUE if still eating, FALSE
X * when done.
X */
XSTATIC_OVL int
Xstill_chewing(x,y)
X xchar x, y;
X{
X struct rm *lev = &(levl[x][y]);
X struct obj *boulder = sobj_at(BOULDER,x,y);
X
X if (dig_pos.x != x || dig_pos.y != y ||
X !on_level(&dig_level, &u.uz) || dig_down) {
X if (!boulder && (lev->diggable & W_NONDIGGABLE))
X You("hurt your teeth on the hard stone.");
X else {
X dig_down = FALSE;
X dig_pos.x = x;
X dig_pos.y = y;
X assign_level(&dig_level, &u.uz);
X dig_effort = IS_ROCK(lev->typ) ? 30 : 60; /* rock takes more time */
X if (boulder)
X You("start chewing on a boulder.");
X else
X You("start chewing a hole in the %s.",
X IS_ROCK(lev->typ) ? "rock" : "door");
X }
X return 1;
X } else if ((dig_effort += 30) < 100) {
X if (flags.verbose)
X You("continue chewing on the %s.", boulder ? "boulder" :
X (IS_ROCK(lev->typ) ? "rock" : "door"));
X return 1;
X }
X
X if (boulder) {
X You("eat the boulder."); /* yum */
X delobj(boulder); /* boulder goes bye-bye */
X
X /*
X * The location could still block because of
X * 1. More than one boulder
X * 2. Boulder stuck in a wall/stone/door.
X *
X * [perhaps use does_block() below (from vision.c)]
X */
X if (IS_ROCK(lev->typ) || closed_door(x,y) || sobj_at(BOULDER,x,y)) {
X block_point(x,y); /* delobj will unblock the point */
X dig_pos.x = 0; /* reset dig messages */
X return 1;
X }
X
X } else if (IS_WALL(lev->typ)) {
X You("chew a hole in the wall.");
X if (level.flags.is_maze_lev) {
X lev->typ = ROOM;
X } else if (level.flags.is_cavernous_lev) {
X lev->typ = CORR;
X } else {
X lev->typ = DOOR;
X lev->doormask = D_NODOOR;
X }
X } else if (lev->typ == SDOOR) {
X if (lev->doormask & D_TRAPPED) {
X b_trapped("secret door");
X lev->doormask = D_NODOOR;
X } else {
X You("chew through the secret door.");
X lev->doormask = D_BROKEN;
X }
X lev->typ = DOOR;
X
X } else if (IS_DOOR(lev->typ)) {
X if (lev->doormask & D_TRAPPED) {
X b_trapped("door");
X lev->doormask = D_NODOOR;
X } else {
X You("chew through the door.");
X lev->doormask = D_BROKEN;
X }
X
X } else { /* STONE or SCORR */
X You("chew a passage through the rock.");
X lev->typ = CORR;
X }
X
X unblock_point(x, y); /* vision */
X newsym(x, y);
X dig_level.dnum = 0;
X dig_level.dlevel = -1;
X return 0;
X}
X#endif /* POLYSELF */
X
X#endif /* OVL2 */
X#ifdef OVLB
X
Xvoid
Xmovobj(obj, ox, oy)
Xregister struct obj *obj;
Xregister xchar ox, oy;
X{
X remove_object(obj);
X newsym(obj->ox, obj->oy);
X place_object(obj, ox, oy);
X newsym(ox, oy);
X}
X
X#ifdef SINKS
XSTATIC_OVL void
Xdosinkfall()
X{
X register struct obj *obj;
X
X# ifdef POLYSELF
X if (is_floater(uasmon)) {
X You("wobble unsteadily for a moment.");
X } else {
X# endif
X You("crash to the floor!");
X losehp((rn1(10, 20 - (int)ACURR(A_CON))),
X "fell onto a sink", NO_KILLER_PREFIX);
X exercise(A_DEX, FALSE);
X for(obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
X if(obj->oclass == WEAPON_CLASS) {
X You("fell on %s.",doname(obj));
X losehp(rn2(3),"fell onto a sink", NO_KILLER_PREFIX);
X exercise(A_CON, FALSE);
X }
X# ifdef POLYSELF
X }
X# endif
X
X HLevitation = (HLevitation & ~TIMEOUT) + 1;
X if(uleft && uleft->otyp == RIN_LEVITATION) {
X obj = uleft;
X Ring_off(obj);
X off_msg(obj);
X }
X if(uright && uright->otyp == RIN_LEVITATION) {
X obj = uright;
X Ring_off(obj);
X off_msg(obj);
X }
X if(uarmf && uarmf->otyp == LEVITATION_BOOTS) {
X obj = uarmf;
X (void)Boots_off();
X off_msg(obj);
X }
X HLevitation--;
X}
X#endif
X
X#endif /* OVLB */
X
X#ifdef OVLB
X
Xboolean
Xmay_dig(x,y)
Xregister xchar x,y;
X/* intended to be called only on ROCKs */
X{
Xreturn (!(IS_STWALL(levl[x][y].typ) && (levl[x][y].diggable & W_NONDIGGABLE)));
X}
X
X#endif /* OVLB */
X#ifdef OVL1
X
XSTATIC_OVL boolean
Xbad_rock(x,y)
Xregister xchar x,y;
X{
X return(IS_ROCK(levl[x][y].typ)
X#ifdef POLYSELF
X && !passes_walls(uasmon)
X && (!tunnels(uasmon) || needspick(uasmon) || !may_dig(x,y))
X#endif
X );
X}
X
Xboolean
Xinvocation_pos(x, y)
Xxchar x, y;
X{
X return(Invocation_lev(&u.uz) && x == inv_pos.x && y == inv_pos.y);
X}
X
X#endif /* OVL1 */
X#ifdef OVL3
X
Xvoid
Xdomove()
X{
X register struct monst *mtmp;
X register struct rm *tmpr,*ust;
X register xchar x,y;
X struct trap *trap;
X int wtcap;
X boolean on_ice;
X xchar chainx, chainy, ballx, bally; /* ball&chain new positions */
X int bc_control; /* control for ball&chain */
X
X u_wipe_engr(rnd(5));
X
X if(((wtcap = near_capacity()) >= OVERLOADED
X || (wtcap > SLT_ENCUMBER && (u.uhp < 10 && u.uhp != u.uhpmax)))
X && !Is_airlevel(&u.uz)) {
X if(wtcap < OVERLOADED) {
X You("don't have enough stamina to move.");
X exercise(A_CON, FALSE);
X } else
X You("collapse under your load.");
X nomul(0);
X return;
X }
X if(u.uswallow) {
X u.dx = u.dy = 0;
X u.ux = x = u.ustuck->mx;
X u.uy = y = u.ustuck->my;
X mtmp = u.ustuck;
X } else {
X if(Is_airlevel(&u.uz) && rn2(4) && !Levitation
X#ifdef POLYSELF
X && !is_flyer(uasmon)
X#endif
X ) {
X switch(rn2(3)) {
X case 0:
X You("tumble in place.");
X exercise(A_DEX, FALSE);
X break;
X case 1:
X You("can't control your movements very well."); break;
X case 2:
X pline("It's hard to walk in thin air.");
X exercise(A_DEX, TRUE);
X break;
X }
X return;
X }
X
X /* check slippery ice */
X on_ice = !Levitation && is_ice(u.ux, u.uy);
X if (on_ice) {
X static int skates = 0;
X if (!skates) skates = find_skates();
X if ((uarmf && uarmf->otyp == skates)
X#ifdef POLYSELF
X || resists_cold(uasmon) || is_flyer(uasmon)
X || is_floater(uasmon) || is_clinger(uasmon)
X || is_whirly(uasmon)
X#endif
X ) on_ice = FALSE;
X else if (!rn2(Cold_resistance ? 3 : 2)) {
X Fumbling |= FROMOUTSIDE;
X if (!(Fumbling & TIMEOUT)) Fumbling += rnd(20);
X }
X }
X if (!on_ice && (Fumbling & FROMOUTSIDE)) {
X Fumbling &= ~FROMOUTSIDE;
X if (!(Fumbling & ~TIMEOUT)) Fumbling = 0;
X }
X
X x = u.ux + u.dx;
X y = u.uy + u.dy;
X if(Stunned || (Confusion && !rn2(5))) {
X register int tries = 0;
X
X do {
X if(tries++ > 50) {
X nomul(0);
X return;
X }
X confdir();
X x = u.ux + u.dx;
X y = u.uy + u.dy;
X } while(!isok(x, y) || bad_rock(x, y));
X }
X if(!isok(x, y)) {
X nomul(0);
X return;
X }
X if((trap = t_at(x, y)) && trap->tseen) {
X if(flags.run >= 2) {
X nomul(0);
X flags.move = 0;
X return;
X } else
X nomul(0);
X }
X
X if(u.ustuck && (x != u.ustuck->mx ||
X y != u.ustuck->my)) {
X if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
X /* perhaps it fled (or was teleported or ... ) */
X u.ustuck = 0;
X } else {
X#ifdef POLYSELF
X /* If polymorphed into a sticking monster,
X * u.ustuck means it's stuck to you, not you
X * to it.
X */
X if (sticks(uasmon)) {
X You("release %s.", mon_nam(u.ustuck));
X u.ustuck = 0;
X } else {
X#endif
X You("cannot escape from %s!",
X mon_nam(u.ustuck));
X nomul(0);
X return;
X#ifdef POLYSELF
X }
X#endif
X }
X }
X mtmp = m_at(x,y);
X if (mtmp) {
X /* Don't attack if you're running, and can see it */
X if (flags.run &&
X ((!Blind && mon_visible(mtmp) &&
X ((mtmp->m_ap_type != M_AP_FURNITURE &&
X mtmp->m_ap_type != M_AP_OBJECT) ||
X Protection_from_shape_changers)) ||
X sensemon(mtmp))) {
X nomul(0);
X flags.move = 0;
X return;
X }
X }
X }
X
X u.ux0 = u.ux;
X u.uy0 = u.uy;
X bhitpos.x = x;
X bhitpos.y = y;
X tmpr = &levl[x][y];
X
X /* attack monster */
X if(mtmp) {
X nomul(0);
X /* only attack if we know it's there */
X /* or if it hides_under, in which case we call attack() to print
X * the Wait! message.
X * This is different from ceiling hiders, who aren't handled in
X * attack().
X */
X if(!mtmp->mundetected || sensemon(mtmp) ||
X (hides_under(mtmp->data) && !is_safepet(mtmp))){
X gethungry();
X if(wtcap >= HVY_ENCUMBER && moves%3) {
X if(u.uhp > 1)
X u.uhp--;
X else {
X pline("You pass out from exertion!");
X exercise(A_CON, FALSE);
X nomul(-10);
X u.usleep = 1;
X }
X }
X if(multi < 0) return; /* we just fainted */
X
X /* try to attack; note that it might evade */
X /* also, we don't attack tame when _safepet_ */
X if(attack(mtmp)) return;
X }
X }
X
X /* not attacking an animal, so we try to move */
X#ifdef POLYSELF
X if(!uasmon->mmove) {
X You("are rooted %s.",
X Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
X "in place" : "to the ground");
X nomul(0);
X return;
X }
X#endif
X if(u.utrap) {
X if(u.utraptype == TT_PIT) {
X if (!rn2(2) && sobj_at(BOULDER, u.ux, u.uy)) {
X Your("%s gets stuck in a crevice.", body_part(LEG));
X display_nhwindow(WIN_MESSAGE, FALSE);
X clear_nhwindow(WIN_MESSAGE);
X You("free your %s.", body_part(LEG));
X } else if (!(--u.utrap)) {
X You("crawl to the edge of the pit.");
X fill_pit(u.ux, u.uy);
X vision_full_recalc = 1; /* vision limits change */
X } else if (flags.verbose)
X Norep( (Hallucination && !rn2(5)) ?
X "You've fallen, and you can't get up." :
X "You are still in a pit." );
X } else if (u.utraptype == TT_LAVA) {
X if(flags.verbose)
X Norep("You are stuck in the lava.");
X if(!is_lava(x,y)) {
X u.utrap--;
X if((u.utrap & 0xff) == 0) {
X You("pull yourself to the edge of the lava.");
X u.utrap = 0;
X }
X }
X u.umoved = TRUE;
X } else if (u.utraptype == TT_WEB) {
X if(--u.utrap) {
X if(flags.verbose)
X Norep("You are stuck to the web.");
X } else You("disentangle yourself.");
X } else if (u.utraptype == TT_INFLOOR) {
X if(--u.utrap) {
X if(flags.verbose)
X Norep("You are stuck in the floor.");
X } else You("finally wiggle free.");
X } else {
X if(flags.verbose)
X Norep("You are caught in a bear trap.");
X if((u.dx && u.dy) || !rn2(5)) u.utrap--;
X }
X return;
X }
X
X
X /*
X * Check for physical obstacles. First, the place we are going.
X */
X if (IS_ROCK(tmpr->typ)) {
X if (Blind) feel_location(x,y);
X#ifdef POLYSELF
X if (passes_walls(uasmon)) {
X ; /* do nothing */
X } else if (tunnels(uasmon) && !needspick(uasmon)) {
X /* Eat the rock. */
X if (still_chewing(x,y)) return;
X } else {
X#endif
X if (Is_stronghold(&u.uz) && is_db_wall(x,y))
X pline("The drawbridge is up!");
X flags.move = 0;
X nomul(0);
X return;
X#ifdef POLYSELF
X }
X#endif
X } else if (IS_DOOR(tmpr->typ)) {
X if (closed_door(x,y)) {
X if (Blind) feel_location(x,y);
X#ifdef POLYSELF
X if (passes_walls(uasmon))
X ; /* do nothing */
X else if (amorphous(uasmon))
X You("ooze under the door.");
X else if (tunnels(uasmon) && !needspick(uasmon)) {
X /* Eat the door. */
X if (still_chewing(x,y)) return;
X } else {
X#endif
X flags.move = 0;
X if (x == u.ux || y == u.uy) {
X if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) {
X pline("Ouch! You bump into a door.");
X exercise(A_DEX, FALSE);
X } else pline("That door is closed.");
X }
X nomul(0);
X return;
X#ifdef POLYSELF
X }
X#endif
X } else if (u.dx && u.dy
X#ifdef POLYSELF
X && !passes_walls(uasmon)
X#endif
X && ((tmpr->doormask & ~D_BROKEN)
X#ifdef REINCARNATION
X || Is_rogue_level(&u.uz)
X#endif
X || block_door(x,y))) {
X /* Diagonal moves into a door are not allowed. */
X if (Blind) feel_location(x,y); /* ?? */
X flags.move = 0;
X nomul(0);
X return;
X }
X }
X if (u.dx && u.dy && bad_rock(u.ux,y) && bad_rock(x,u.uy)) {
X /* Move at a diagonal. */
X#ifdef POLYSELF
X if (bigmonst(uasmon)) {
X Your("body is too large to fit through.");
X nomul(0);
X return;
X }
X#endif
X if (invent && inv_weight() > -400) {
X You("are carrying too much to get through.");
X nomul(0);
X return;
X }
X }
X
X ust = &levl[u.ux][u.uy];
X
X /* Now see if other things block our way . . */
X if (u.dx && u.dy
X#ifdef POLYSELF
X && !passes_walls(uasmon)
X#endif
X && (IS_DOOR(ust->typ) && ((ust->doormask & ~D_BROKEN)
X#ifdef REINCARNATION
X || Is_rogue_level(&u.uz)
X#endif
X || block_entry(x, y))
X )) {
X /* Can't move at a diagonal out of a doorway with door. */
X flags.move = 0;
X nomul(0);
X return;
X }
X
X if (sobj_at(BOULDER,x,y)
X#ifdef POLYSELF
X && !passes_walls(uasmon)
X#endif
X ) {
X if (!(Blind || Hallucination) && (flags.run >= 2)) {
X nomul(0);
X flags.move = 0;
X return;
X }
X#ifdef POLYSELF
X /* tunneling monsters will chew before pushing */
X if (tunnels(uasmon) && !needspick(uasmon)) {
X if (still_chewing(x,y)) return;
X } else
X#endif
X if (moverock() < 0) return;
X }
X
X /* OK, it is a legal place to move. */
X
X /* Move ball and chain. */
X if (Punished)
X if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy))
X return;
X
X /* now move the hero */
X mtmp = m_at(x, y);
X if (u.uinwater) water_friction();
X u.ux += u.dx;
X u.uy += u.dy;
X /* if safepet at destination then move the pet to the hero's
X * previous location using the same conditions as in attack().
X * there are special extenuating circumstances:
X * (1) if the pet dies then your god angers,
X * (2) if the pet gets trapped then your god may disapprove,
X * (3) if the pet was already trapped and you attempt to free it
X * not only do you encounter the trap but you may frighten your
X * pet causing it to go wild! moral: don't abuse this privilege.
X */
X /* Ceiling-hiding pets are skipped by this section of code, to
X * be caught by the normal falling-monster code.
X */
X if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
X int swap_result;
X
X /* if trapped, there's a chance the pet goes wild */
X if (mtmp->mtrapped && !rn2(4)) {
X pline ("%s suddenly goes wild!",
X mtmp->mnamelth ? NAME(mtmp) : Monnam(mtmp));
X mtmp->mtame = mtmp->mpeaceful = mtmp->msleep = 0;
X }
X
X mtmp->mtrapped = 0;
X mtmp->mundetected = 0;
X remove_monster(x, y);
X place_monster(mtmp, u.ux0, u.uy0);
X
X /* check first to see if monster drowned.
X * then check for traps.
X */
X if (minwater(mtmp)) {
X swap_result = 2;
X } else swap_result = mintrap(mtmp);
X
X switch (swap_result) {
X case 0:
X You("%s %s.", mtmp->mtame ? "displaced" : "frightened",
X mtmp->mnamelth ? NAME(mtmp) : mon_nam(mtmp));
X break;
X case 1: /* trapped */
X case 3: /* changed levels */
X /* there's already been a trap message, reinforce it */
X pline("Trapping your pet was a selfish move.");
X if (!rn2(4)) {
X pline("You'll pay!");
X adjalign(-5);
X }
X break;
X case 2:
X /* it may have drowned or died. that's no way to
X * treat a pet! your god gets angry and complains.
X */
X if (rn2(4)) {
X pline ("%s complains in a booming voice:", u_gname());
X verbalize("Losing your pet like this was a mistake!");
X u.ugangr++ ;
X adjalign(-15);
X }
X break;
X default:
X pline("that's strange, unknown mintrap result!");
X break;
X }
X }
X
X reset_occupations();
X if(flags.run) {
X if(IS_DOOR(tmpr->typ) ||
X#ifdef POLYSELF
X (IS_ROCK(tmpr->typ)) ||
X#endif
X (xupstair == u.ux && yupstair == u.uy) ||
X (xdnstair == u.ux && ydnstair == u.uy)
X || (sstairs.sx == u.ux && sstairs.sy == u.uy)
X || (xupladder == u.ux && yupladder == u.uy)
X || (xdnladder == u.ux && ydnladder == u.uy)
X || IS_FOUNTAIN(tmpr->typ)
X || IS_THRONE(tmpr->typ)
X#ifdef SINKS
X || IS_SINK(tmpr->typ)
X#endif
X || IS_ALTAR(tmpr->typ)
X )
X nomul(0);
X }
X#ifdef POLYSELF
X if (hides_under(uasmon))
X u.uundetected = OBJ_AT(u.ux, u.uy);
X else if (u.dx || u.dy) { /* piercer */
X if (u.usym == S_MIMIC_DEF)
X u.usym = S_MIMIC;
X u.uundetected = 0;
X }
X#endif
X
X#ifdef WALKIES
X check_leash(u.ux0,u.uy0);
X#endif
X if(u.ux0 != u.ux || u.uy0 != u.uy) {
X u.umoved = TRUE;
X /* Clean old position -- vision_recalc() will print our new one. */
X newsym(u.ux0,u.uy0);
X /* Since the hero has moved, adjust what can be seen/unseen. */
X vision_recalc(1); /* Do the work now in the recover time. */
X
X /* a special clue-msg when on the Invocation position */
X if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
X register struct obj *otmp;
X
X You("feel a strange vibration under your %s.",
X makeplural(body_part(FOOT)));
X
X for(otmp = invent; otmp; otmp = otmp->nobj) {
X if(otmp->otyp == CANDELABRUM_OF_INVOCATION &&
X otmp->spe == 7 && otmp->lamplit) {
X pline("%s glows with a strange light!",
X The(xname(otmp)));
X break;
X }
X }
X
X }
X }
X
X if (Punished) /* put back ball and chain */
X move_bc(0,bc_control,ballx,bally,chainx,chainy);
X
X spoteffects();
X}
X
X#endif /* OVL3 */
X#ifdef OVL2
X
Xvoid
Xspoteffects()
X{
X register struct trap *trap;
X register struct monst *mtmp;
X
X if(u.uinwater) {
X int was_underwater;
X
X if (!is_pool(u.ux,u.uy)) {
X if (Is_waterlevel(&u.uz))
X You("pop into an air bubble.");
X else
X You("are on solid ground again.");
X }
X else if (Is_waterlevel(&u.uz))
X goto stillinwater;
X else if (Levitation || is_floater(uasmon))
X You("pop out of the water like a cork!");
X else if (is_flyer(uasmon))
X You("fly out of the water.");
X else if (Wwalking)
X You("slowly rise above the surface.");
X else
X goto stillinwater;
X was_underwater = Underwater && !Is_waterlevel(&u.uz);
X u.uinwater = 0; /* leave the water */
X if (was_underwater) { /* restore vision */
X docrt();
X vision_full_recalc = 1;
X }
X }
Xstillinwater:;
X if(!Levitation && !u.ustuck
X#ifdef POLYSELF
X && !is_flyer(uasmon)
X#endif
X ) {
X /* limit recursive calls through teleds() */
X if(is_lava(u.ux,u.uy) && lava_effects())
X return;
X if(is_pool(u.ux,u.uy) && !Wwalking && drown())
X return;
X }
X check_special_room(FALSE);
X#ifdef SINKS
X if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
X dosinkfall();
X#endif
X if(!flags.nopick && OBJ_AT(u.ux, u.uy) &&
X (!is_pool(u.ux,u.uy) || Underwater))
X pickup(1);
X else read_engr_at(u.ux,u.uy);
X if(trap = t_at(u.ux,u.uy))
X dotrap(trap); /* fall into pit, arrow trap, etc. */
X if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
X mtmp->mundetected = 0;
X switch(mtmp->data->mlet) {
X case S_PIERCER:
X pline("%s suddenly drops from the ceiling!",
X Amonnam(mtmp));
X if(mtmp->mtame) /* jumps to greet you, not attack */
X ;
X else if(uarmh)
X pline("Its blow glances off your helmet.");
X else if (u.uac + 3 <= rnd(20))
X You("are almost hit by %s!",
X x_monnam(mtmp, 2, "falling", 1));
X else {
X int dmg;
X You("are hit by %s!",
X x_monnam(mtmp, 2, "falling", 1));
X dmg = d(4,6);
X if(Half_physical_damage) dmg = (dmg+1) / 2;
X mdamageu(mtmp, dmg);
X }
X break;
X default: /* monster surprises you. */
X if(mtmp->mtame)
X pline("%s jumps near you from the ceiling.",
X Amonnam(mtmp));
X else if(mtmp->mpeaceful) {
X You("surprise %s!",
X Blind && !sensemon(mtmp) ?
X "something" : a_monnam(mtmp));
X mtmp->mpeaceful = 0;
X } else
X pline("%s attacks you by surprise!",
X Amonnam(mtmp));
X break;
X }
X mnexto(mtmp); /* have to move the monster */
X }
X}
X
XSTATIC_OVL boolean
Xmonstinroom(mdat,roomno)
Xstruct permonst *mdat;
Xint roomno;
X{
X register struct monst *mtmp;
X
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X if(mtmp->data == mdat &&
X index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
X return(TRUE);
X return(FALSE);
X}
X
Xchar *
Xin_rooms(x, y, typewanted)
Xregister xchar x, y;
Xregister int typewanted;
X{
X static char buf[5];
X char rno, *ptr = &buf[4];
X int typefound, min_x, min_y, max_x, max_y_offset, step;
X register struct rm *lev;
X
X#define goodtype(rno) (!typewanted || \
X ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) || \
X ((typewanted == SHOPBASE) && (typefound > SHOPBASE))) \
X
X switch (rno = levl[x][y].roomno) {
X case NO_ROOM:
X return(ptr);
X case SHARED:
X step = 2;
X break;
X case SHARED_PLUS:
X step = 1;
X break;
X default: /* i.e. a regular room # */
X if (goodtype(rno))
X *(--ptr) = rno;
X return(ptr);
X }
X
X min_x = x - 1;
X max_x = x + 1;
X if (x < 0)
X min_x += step;
X else
X if (x >= COLNO)
X max_x -= step;
X
X min_y = y - 1;
X max_y_offset = 2;
X if (min_y < 0) {
X min_y += step;
X max_y_offset -= step;
X } else
X if ((min_y + max_y_offset) >= ROWNO)
X max_y_offset -= step;
X
X for (x = min_x; x <= max_x; x += step) {
X lev = &levl[x][min_y];
X y = 0;
X if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
X !index(ptr, rno) && goodtype(rno))
X *(--ptr) = rno;
X y += step;
X if (y > max_y_offset)
X continue;
X if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
X !index(ptr, rno) && goodtype(rno))
X *(--ptr) = rno;
X y += step;
X if (y > max_y_offset)
X continue;
X if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
X !index(ptr, rno) && goodtype(rno))
X *(--ptr) = rno;
X }
X return(ptr);
X}
X
Xstatic void
Xmove_update(newlev)
Xregister boolean newlev;
X{
X char *ptr1, *ptr2, *ptr3, *ptr4;
X
X Strcpy(u.urooms0, u.urooms);
X Strcpy(u.ushops0, u.ushops);
X if (newlev) {
X u.urooms[0] = '\0';
X u.uentered[0] = '\0';
X u.ushops[0] = '\0';
X u.ushops_entered[0] = '\0';
X Strcpy(u.ushops_left, u.ushops0);
X return;
X }
X Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
X
X for (ptr1 = &u.urooms[0],
X ptr2 = &u.uentered[0],
X ptr3 = &u.ushops[0],
X ptr4 = &u.ushops_entered[0];
X *ptr1; ptr1++) {
X if (!index(u.urooms0, *ptr1))
X *(ptr2++) = *ptr1;
X if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
X *(ptr3++) = *ptr1;
X if (!index(u.ushops0, *ptr1))
X *(ptr4++) = *ptr1;
X }
X }
X *ptr2 = '\0';
X *ptr3 = '\0';
X *ptr4 = '\0';
X
X /* filter u.ushops0 -> u.ushops_left */
X for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
X if (!index(u.ushops, *ptr1))
X *(ptr2++) = *ptr1;
X *ptr2 = '\0';
X}
X
Xvoid
Xcheck_special_room(newlev)
Xregister boolean newlev;
X{
X register struct monst *mtmp;
X char *ptr;
X
X move_update(newlev);
X
X if (*u.ushops0)
X u_left_shop(u.ushops_left, newlev);
X
X if (!*u.uentered && !*u.ushops_entered)
X return; /* no entrance messages necessary */
X
X /* Did we just enter a shop? */
X if (*u.ushops_entered)
X u_entered_shop(u.ushops_entered);
X
X for (ptr = &u.uentered[0]; *ptr; ptr++) {
X register int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
X
X /* Did we just enter some other special room? */
X /* vault.c insists that a vault remain a VAULT,
X * and temples should remain TEMPLEs,
X * but everything else gives a message only the first time */
X if(!newlev)
X switch (rt) {
X case ZOO:
X pline("Welcome to David's treasure zoo!");
X break;
X case SWAMP:
X pline("It %s rather %s down here.",
X Blind ? "feels" : "looks",
X Blind ? "humid" : "muddy");
X break;
X case COURT:
X You("enter an opulent throne room!");
X break;
X case MORGUE:
X if(midnight())
X pline("Run away! Run away!");
X else
X You("have an uncanny feeling...");
X break;
X case BEEHIVE:
X You("enter a giant beehive!");
X break;
X#ifdef ARMY
X case BARRACKS:
X if(monstinroom(&mons[PM_SOLDIER], roomno) ||
X monstinroom(&mons[PM_SERGEANT], roomno) ||
X monstinroom(&mons[PM_LIEUTENANT], roomno) ||
X monstinroom(&mons[PM_CAPTAIN], roomno))
X You("enter a military barracks!");
X else
X You("enter an abandoned barracks.");
X break;
X#endif
X case DELPHI:
X if(monstinroom(&mons[PM_ORACLE], roomno))
X verbalize("Hello, %s, welcome to Delphi!", plname);
X break;
X case TEMPLE:
X intemple(roomno + ROOMOFFSET);
X /* fall through */
X default:
X rt = 0;
X }
X else
X rt = 0;
X
X if(rt != 0) {
X rooms[roomno].rtype = OROOM;
X if (!search_special(rt)) {
X /* No more room of that type */
X switch(rt) {
X case COURT:
X level.flags.has_court = 0;
X break;
X case SWAMP:
X level.flags.has_swamp = 0;
X break;
X case MORGUE:
X level.flags.has_morgue = 0;
X break;
X case ZOO:
X level.flags.has_zoo = 0;
X break;
X#ifdef ARMY
X case BARRACKS:
X level.flags.has_barracks = 0;
X break;
X#endif
X case TEMPLE:
X level.flags.has_temple = 0;
X break;
X case BEEHIVE:
X level.flags.has_beehive = 0;
X break;
X }
X }
X if(rt==COURT || rt==SWAMP || rt==MORGUE || rt==ZOO)
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X if(!Stealth && !rn2(3))
X mtmp->msleep = 0;
X }
X }
X
X return;
X}
X
X#endif /* OVL2 */
X#ifdef OVLB
X
Xint
Xdopickup()
X{
X int count;
X /* awful kludge to work around parse()'s pre-decrement */
X count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
X multi = 0; /* always reset */
X /* uswallow case added by GAN 01/29/87 */
X if(u.uswallow) {
X if (is_animal(u.ustuck->data)) {
X You("pick up %s tongue.",
X s_suffix(mon_nam(u.ustuck)));
X pline("But it's kind of slimy, so you drop it.");
X } else
X You("don't %s anything in here to pick up.",
X Blind ? "feel" : "see");
X return(1);
X }
X if(!OBJ_AT(u.ux, u.uy)) {
X pline("There is nothing here to pick up.");
X return(0);
X }
X if(Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) {
X You("cannot reach the floor.");
X return(1);
X }
X if(is_pool(u.ux, u.uy)) {
X if(Wwalking
X#ifdef POLYSELF
X || is_flyer(uasmon) || is_clinger(uasmon)
X#endif
X ) {
X You("cannot dive into the water to pick things up.");
X return(1);
X }
X else if(!Underwater) {
X You("can't even see the bottom, let alone pick up something.");
X return(1);
X }
X }
X pickup(-count);
X return(1);
X}
X
X#endif /* OVLB */
X#ifdef OVL2
X
X/* stop running if we see something interesting */
X/* turn around a corner if that is the only way we can proceed */
X/* do not turn left or right twice */
Xvoid
Xlookaround()
X{
X register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
X register int corrct = 0, noturn = 0;
X register struct monst *mtmp;
X register struct trap *trap;
X
X#ifdef POLYSELF
X /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */
X /* they polymorphed while in the middle of a long move. */
X if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) {
X nomul(0);
X return;
X }
X#endif
X if(Blind || flags.run == 0) return;
X for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) {
X if(!isok(x,y)) continue;
X#ifdef POLYSELF
X if(u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy) continue;
X#endif
X if(x == u.ux && y == u.uy) continue;
X
X if((mtmp = m_at(x,y)) &&
X mtmp->m_ap_type != M_AP_FURNITURE &&
X mtmp->m_ap_type != M_AP_OBJECT &&
X (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
X if((flags.run != 1 && !mtmp->mtame)
X || (x == u.ux+u.dx && y == u.uy+u.dy))
X goto stop;
X }
X
X if (levl[x][y].typ == STONE) continue;
X if (x == u.ux-u.dx && y == u.uy-u.dy) continue;
X
X if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) ||
X IS_AIR(levl[x][y].typ))
X continue;
X else if (closed_door(x,y)) {
X if(x != u.ux && y != u.uy) continue;
X if(flags.run != 1) goto stop;
X goto bcorr;
X } else if (levl[x][y].typ == CORR) {
Xbcorr:
X if(levl[u.ux][u.uy].typ != ROOM) {
X if(flags.run == 1 || flags.run == 3) {
X i = dist2(x,y,u.ux+u.dx,u.uy+u.dy);
X if(i > 2) continue;
X if(corrct == 1 && dist2(x,y,x0,y0) != 1)
X noturn = 1;
X if(i < i0) {
X i0 = i;
X x0 = x;
X y0 = y;
X m0 = mtmp ? 1 : 0;
X }
X }
X corrct++;
X }
X continue;
X } else if ((trap = t_at(x,y)) && trap->tseen) {
X if(flags.run == 1) goto bcorr; /* if you must */
X if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
X continue;
X } else if (is_pool(x,y) || is_lava(x,y)) {
X /* water and lava only stop you if directly in front, and stop
X * you even if you are running
X */
X if(!Levitation &&
X#ifdef POLYSELF
X !is_flyer(uasmon) && !is_clinger(uasmon) &&
X#endif
X /* No Wwalking check; otherwise they'd be able
X * to test boots by trying to SHIFT-direction
X * into a pool and seeing if the game allowed it
X */
X x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
X continue;
X } else { /* e.g. objects or trap or stairs */
X if(flags.run == 1) goto bcorr;
X if(mtmp) continue; /* d */
X if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) ||
X ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
X continue;
X }
Xstop:
X nomul(0);
X return;
X } /* end for loops */
X
X if(corrct > 1 && flags.run == 2) goto stop;
X if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&
X (corrct == 1 || (corrct == 2 && i0 == 1))) {
X /* make sure that we do not turn too far */
X if(i0 == 2) {
X if(u.dx == y0-u.uy && u.dy == u.ux-x0)
X i = 2; /* straight turn right */
X else
X i = -2; /* straight turn left */
X } else if(u.dx && u.dy) {
X if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
X i = -1; /* half turn left */
X else
X i = 1; /* half turn right */
X } else {
X if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy))
X i = 1; /* half turn right */
X else
X i = -1; /* half turn left */
X }
X
X i += u.last_str_turn;
X if(i <= 2 && i >= -2) {
X u.last_str_turn = i;
X u.dx = x0-u.ux;
X u.dy = y0-u.uy;
X }
X }
X}
X
X/* something like lookaround, but we are not running */
X/* react only to monsters that might hit us */
Xint
Xmonster_nearby()
X{
X register int x,y;
X register struct monst *mtmp;
X
X if(!Blind)
X for(x = u.ux-1; x <= u.ux+1; x++)
X for(y = u.uy-1; y <= u.uy+1; y++) {
X if(!isok(x,y)) continue;
X if(x == u.ux && y == u.uy) continue;
X if((mtmp = m_at(x,y)) &&
X mtmp->m_ap_type != M_AP_FURNITURE &&
X mtmp->m_ap_type != M_AP_OBJECT &&
X !mtmp->mpeaceful &&
X (!is_hider(mtmp->data) || !mtmp->mundetected) &&
X !noattacks(mtmp->data) &&
X mtmp->mcanmove && !mtmp->msleep && /* aplvax!jcn */
X (!mtmp->minvis || See_invisible) &&
X !onscary(u.ux, u.uy, mtmp))
X return(1);
X }
X return(0);
X}
X
Xvoid
Xnomul(nval)
X register int nval;
X{
X if(multi < nval) return; /* This is a bug fix by ab@unido */
X u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
X u.usleep = 0;
X multi = nval;
X flags.mv = flags.run = 0;
X}
X
X#endif /* OVL2 */
X#ifdef OVL1
X
Xvoid
Xlosehp(n, knam, k_format)
Xregister int n;
Xregister const char *knam;
Xboolean k_format;
X{
X#ifdef POLYSELF
X if (u.mtimedone) {
X u.mh -= n;
X if (u.mhmax < u.mh) u.mhmax = u.mh;
X flags.botl = 1;
X if (u.mh < 1) rehumanize();
X return;
X }
X#endif
X u.uhp -= n;
X if(u.uhp > u.uhpmax)
X u.uhpmax = u.uhp; /* perhaps n was negative */
X flags.botl = 1;
X if(u.uhp < 1) {
X killer_format = k_format;
X killer = knam; /* the thing that killed you */
X You("die...");
X done(DIED);
X } else if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50 && n > 0){
X wailmsg = moves;
X if(index("WEV", pl_character[0])) {
X if (u.uhp == 1)
X pline("%s is about to die.", pl_character);
X else if (4 <= (!!(HTeleportation & INTRINSIC)) +
X (!!(HSee_invisible & INTRINSIC)) +
X (!!(HPoison_resistance & INTRINSIC)) +
X (!!(HCold_resistance & INTRINSIC)) +
X (!!(HShock_resistance & INTRINSIC)) +
X (!!(HFire_resistance & INTRINSIC)) +
X (!!(HSleep_resistance & INTRINSIC)) +
X (!!(HDisint_resistance & INTRINSIC)) +
X (!!(HTeleport_control & INTRINSIC)) +
X (!!(Stealth & INTRINSIC)) +
X (!!(Fast & INTRINSIC)) +
X (!!(HInvis & INTRINSIC)))
X pline("%s, all your powers will be lost...",
X pl_character);
X else
X pline("%s, your life force is running out.",
X pl_character);
X } else {
X if(u.uhp == 1)
X You("hear the wailing of the Banshee...");
X else
X You("hear the howling of the CwnAnnwn...");
X }
X }
X}
X
Xint
Xweight_cap()
X{
X register long carrcap;
X
X carrcap = (((ACURRSTR + ACURR(A_CON))/2)+1)*50;
X#ifdef POLYSELF
X if (u.mtimedone) {
X /* consistent with can_carry() in mon.c */
X if (u.usym == S_NYMPH)
X carrcap = MAX_CARR_CAP;
X else if (!uasmon->cwt)
X carrcap = (carrcap * (long)uasmon->msize) / MZ_HUMAN;
X else if (!strongmonst(uasmon)
X || (strongmonst(uasmon) && (uasmon->cwt > WT_HUMAN)))
X carrcap = (carrcap * (long)uasmon->cwt / WT_HUMAN);
X }
X#endif
X if(Levitation || Is_airlevel(&u.uz)) /* pugh@cornell */
X carrcap = MAX_CARR_CAP;
X else {
X if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
X if(Wounded_legs & LEFT_SIDE) carrcap -= 100;
X if(Wounded_legs & RIGHT_SIDE) carrcap -= 100;
X }
X return((int) carrcap);
X}
X
X/* returns how far beyond the normal capacity the player is currently. */
X/* inv_weight() is negative if the player is below normal capacity. */
Xint
Xinv_weight()
X{
X register struct obj *otmp = invent;
X#ifdef LINT /* long to int conversion */
X register int wt = 0;
X#else
X register int wt = (int)((u.ugold + 50L)/100L);
X#endif /* LINT */
X while(otmp){
X#ifdef POLYSELF
X if (otmp->otyp != BOULDER || !throws_rocks(uasmon))
X#endif
X wt += otmp->owt;
X otmp = otmp->nobj;
X }
X return(wt - weight_cap());
X}
X
X/*
X * Returns 0 if below normal capacity, or the number of "capacity units"
X * over the normal capacity the player is loaded. Max is 5.
X */
Xint
Xnear_capacity()
X{
X int cap, wt = inv_weight();
X
X if (wt < 0) return UNENCUMBERED;
X cap = (wt / (weight_cap()/2)) + 1;
X return min(cap, OVERLOADED);
X}
X
Xint
Xmax_capacity()
X{
X return(inv_weight() - (2 * weight_cap()));
X}
X
Xboolean
Xcheck_capacity(str)
Xconst char *str;
X{
X if(near_capacity() >= EXT_ENCUMBER) {
X if(str)
X pline(str);
X else
X You("can't do that while carrying so much stuff.");
X return 1;
X }
X return 0;
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
Xint
Xinv_cnt()
X{
X register struct obj *otmp = invent;
X register int ct = 0;
X
X while(otmp){
X ct++;
X otmp = otmp->nobj;
X }
X return(ct);
X}
X
Xint
Xidentify(otmp) /* also called by newmail() */
X register struct obj *otmp;
X{
X makeknown(otmp->otyp);
X otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
X prinv(NULL, otmp, 0L);
X return(1);
X}
X
X#endif /* OVLB */
X
X/*hack.c*/
END_OF_FILE
if test 39188 -ne `wc -c <'src/hack.c'`; then
echo shar: \"'src/hack.c'\" unpacked with wrong size!
fi
# end of 'src/hack.c'
fi
if test -f 'sys/os2/Install.os2' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sys/os2/Install.os2'\"
else
echo shar: Extracting \"'sys/os2/Install.os2'\" \(14816 characters\)
sed "s/^X//" >'sys/os2/Install.os2' <<'END_OF_FILE'
X Instructions for compiling and installing NetHack 3.1
X on an OS/2 system
X =====================================================
X Timo Hakulinen
X Last revision: 24 Jan 1993
X
X0. Read this entire file before starting, and come back to the Notes below if
X you have any problems.
X
X1. Make sure all the NetHack files are in the appropriate directory
X structure. You should have a top directory (e.g. nh31, or whatever you
X like) with subdirectories dat, doc, include, src, util, sys\share,
X sys\os2, and win\tty. You may have other subdirectories under sys and
X win, but they will not affect compilation for an OS/2 system. If you do
X not follow this structure, the makefile will not function properly. The
X .c files for the main program belong in src, those for utility programs in
X util, and OS/2-specific ones in sys\os2. All the .h files belong in
X include, the documentation in doc, and assorted data files in dat. There
X are also some necessary files in sys\share (pc*.c, random.c, dgn_*.*,
X lev_*.*). A more detailed explanation of the directory structure is found
X in file Files, which should be in the top directory.
X
X If you downloaded or ftp'd the sources from a UNIX system, the lines may
X end in UNIX-style newlines, instead of the carriage return and line feed
X pairs used by DOS and OS/2. You'll have to convert them (with a utility
X like Rahul Dhesi's "flip"). Also, every file should end with a carriage
X return / line feed pair, because Microsoft C has had a habit of ignoring
X the last line of each file otherwise. Besides, even editing UNIX-style
X files with DOS editors is often a royal pain.
X
X2. The makefile for OS/2, Makefile.os2, is found in directory sys\os2. Copy
X it to directory src and rename it Makefile. From now on, Makefile.os2
X will be referred to as "Makefile" in this document.
X
X The Makefile supports the following make utilities:
X
X NDMAKE a public domain make utility for DOS by Don Kneller
X NMAKE make shipped with Microsoft languages and IBM C Set/2
X DMAKE a public domain make for DOS and OS/2 by Dennis Vadura
X
X Both NDMAKE and DMAKE are available at major archive sites. The
X following compilers are supported:
X
X compiler: runs in: compiles for:
X
X Microsoft C 5.1 DOS / OS/2 1.0-2.x OS/2 1.x
X Microsoft 6.0A (see note 5) - " - - " -
X IBM C Set/2 1.00, Toolkit/2 2.00 OS/2 2.x OS/2 2.x
X GCC emx 0.8f (see note 6) OS/2 2.x OS/2 2.x
X
X Note that code compiled for OS/2 versions 1.0-1.3 runs unmodified in OS/2
X versions 2.0 and up. It should in principle be possible to cross compile
X NetHack 3.1 for OS/2 in DOS using NDMAKE and MSC, but this is not
X recommended (see note 3).
X
X If you're using some other compiler than one listed above, you will have
X to adapt Makefile to your needs. In particular, change the CC, CFLAGS,
X LINK, and LFLAGS macros to your C compiler's and linker's liking. See
X Makefile for more information.
X
X If you are going to be constructing the Fred Fish termlib library you will
X need Makefile.lib in sys\share (see note 4).
X
X3. Go to the include subdirectory. First edit config.h according to the
X comments to match your system and desired set of features. In particular,
X make sure that OS2 is defined, and that UNIX, HACKDIR, and COMPRESS are
X *not* defined. If your compiler is ANSI compliant (like practically all
X OS/2 compilers are), it's probable that nothing else needs to be
X configured in config.h. However, if you have VISION_TABLES defined and
X get a compilation error while processing vis_tab.c, you may have to
X uncomment BRACES too.
X
X Next look at os2conf.h. This file shouldn't need much changing. If you
X want to use the hardcoded OS/2 system definitions in def_os2.h instead of
X the compiler's standard headers, comment out OS2_USESYSHEADERS. This may
X become necessary if you are using a compiler which doesn't come with
X proper system headers by default. In this case you may have to edit the
X definitions there, because every compiler has its own way of declaring
X the necessary system functions and data structures. In general you
X should prefer the compiler's offerings, if possible.
X
X If you are using a 32 bit compiler other than GCC emx 0.8f or C Set/2 in
X OS/2 2.x, force OS2_32BITAPI to be defined. Otherwise it is defined only
X for the above mentioned compilers.
X
X If you are not going to include random.c, because you are using the
X random number generator provided by your compiler, you will need to
X comment out RANDOM.
X
X If you want to muck with different termcap settings, uncomment TERMLIB to
X enable use of termcap routines (see note 4). This is not necessary to
X create a fully functional game, however.
X
X4. If you are using another compiler than MSC, GCC, or IBM C Set/2, you may
X want to look through system.h in the include directory. This file matches
X the return and parameter types for system calls and library routines with
X various flavors of compilers and operating systems. Leaving this file
X alone is unlikely to cause problems, but if you get compile errors with
X any functions in the standard library, it's worth checking the
X declarations there.
X
X5. If you want to change the high score list behavior, examine the top of
X topten.c, in the src directory. You may want to change the definitions of
X PERSMAX, POINTSMIN, and ENTRYMAX.
X
X6. Go to the src directory and edit the top of Makefile. Be sure the
X directory you want the game installed in actually exists.
X
X You'll need nroff and/or TeX to do the files in doc. If you don't have
X either of these, you can skip it.
X
X If you elected not to use the high-quality BSD random number routines by
X commenting out RANDOM in os2conf.h, comment out (or set equal to nothing)
X the RANDOM macro in Makefile.
X
X If you elected to use Fred Fish's termcap library (bundled in as
X termcap.uu in directory sys\share), you will have to generate termlib.lib
X from those sources by typing "make -f makefile.lib termlib.lib". You must
X set the TERMLIB option in Makefile to link in the resulting termlib.lib.
X
X If you are recompiling after patching your sources, or if you got your
X files from somewhere other than the official distribution, "touch
X makedefs.c" to ensure that certain files (onames.h and pm.h) are remade,
X lest potentially troublesome timestamps fool make.
X
X If you have lex and yacc programs, or the equivalent flex and bison
X programs, you can set up Makefile to generate the appropriate .h and .c
X files from their .l and .y counterparts whenever you recompile. This is
X done by changing the do_yacc and do_lex targets in Makefile to depend on
X targets yacc_act and lex_act instead of yacc_cpy and lex_cpy. Otherwise
X Makefile will copy pre-generated yacc and lex output files dgn_*.* and
X lev_*.* from directory sys\share to util and include.
X
X Now, enter "make all", and take a siesta; your computer will be occupied
X for a fair amount of time. If all goes well, you will get an executable.
X
X7. All the support data files should have been copied to the game directory
X by the make process. Here is the complete list in alphabetical order of
X all the files that should have gotten there during a full build:
X
X A-filla.lev A-fillb.lev A-goal.lev A-locate.lev A-start.lev
X B-filla.lev B-fillb.lev B-goal.lev B-locate.lev B-start.lev
X C-filla.lev C-fillb.lev C-goal.lev C-locate.lev C-start.lev
X E-filla.lev E-fillb.lev E-goal.lev E-locate.lev E-start.lev
X H-filla.lev H-fillb.lev H-goal.lev H-locate.lev H-start.lev
X K-filla.lev K-fillb.lev K-goal.lev K-locate.lev K-start.lev
X P-filla.lev P-fillb.lev P-goal.lev P-locate.lev P-start.lev
X R-filla.lev R-fillb.lev R-goal.lev R-locate.lev R-start.lev
X S-filla.lev S-fillb.lev S-goal.lev S-locate.lev S-start.lev
X T-filla.lev T-fillb.lev T-goal.lev T-locate.lev T-start.lev
X V-filla.lev V-fillb.lev V-goal.lev V-locate.lev V-start.lev
X W-filla.lev W-fillb.lev W-goal.lev W-locate.lev W-start.lev
X air.lev asmodeus.lev astral.lev baalz.lev bigroom.lev
X castle.lev cmdhelp data dungeon earth.lev
X fakewiz1.lev fakewiz2.lev fire.lev help hh
X history juiblex.lev knox.lev license medusa-1.lev
X medusa-2.lev mine_end.lev minefill.lev minetown.lev nethack.cmd
X nethack.cnf nethack.exe nethack.ico opthelp options
X oracle.lev oracles orcus.lev quest.dat recover.exe
X rumors sanctum.lev tower1.lev tower2.lev tower3.lev
X valley.lev water.lev wizard1.lev wizard2.lev wizard3.lev
X wizhelp
X
X Yes. It's 106 files for a full featured NetHack 3.1. If any of the files
X are missing, try to rerun make. If that doesn't help, you'll have to try
X to decipher Makefile to find out how to manually create the missing
X files. These kinds of troubles shouldn't happen except for two reasons:
X You've run out of disk space while compiling or your make utility doesn't
X understand Makefile properly for some reason. In either case, you should
X get some warnings from the make, though.
X
X If you have old record, logfile, or news files in the game directory, they
X are not overwritten. Of course, old records from NetHack 3.0 are not
X worth keeping with 3.1, since these games are really quite different.
X
X Edit file nethack.cnf in the game directory to reflect your particular
X setup and personal preferences, following the comments there. More info
X about settable options can be found in the file opthelp and the Guidebook.
X
X If you compiled in the TERMLIB feature, also move the sys\share\termcap
X file to your game directory.
X
X8. If you'll be running NetHack from a different subdirectory, you will want
X to "set HACKDIR=c:\games\nh31" (or whatever directory you want to use).
X Add it to your config.sys, if you'll be playing often.
X
X You can also create a special NetHack entry in your Presentation Manager /
X Workplace Shell desktop. This will use the included NetHack icon.
X The following is a sample program description for OS/2 1.3 desktop, but
X it's similar for OS/2 2.0:
X
X Program title: NetHack 3.1
X Path and file name: c:\games\nh31\nethack.cmd
X Parameters:
X Working directory: c:\games\nh31
X Program type: OS/2 Full screen
X
X Naturally you must fill in your own game directory and parameters if you
X want to set any. The program type can be either OS/2 Full screen or OS/2
X Windowed. Note that you should set the executable path to use the .cmd
X file generated by Makefile. This file generates an extra pause after the
X program exit, because otherwise you wouldn't get to see the high score
X list upon quitting due to PM/WPS automatically closing the program window.
X When starting NetHack normally from OS/2 command prompt, the command
X processor starts nethack.exe instead, so no extra pause is generated.
X
X9. If you want to clear up the temporary files and objects created by the
X compilation process, you may issue "make spotless". This will return your
X source tree to near-distribution condition. Naturally, it will not touch
X your newly built game files in any way.
X
X10. Play NetHack. If it works, you're done!
X
X
XNotes
X-----
X
X1) Save files and bones files from previous versions will not work with
X NetHack 3.1. Don't bother trying to keep them.
X
X2) To install an update of NetHack after changing something, enter "make"
X from the src directory. If you add, delete, or reorder monsters or
X objects, or you change the format of saved level files, delete any save
X and bones files. (Trying to use such files sometimes produces amusing
X confusions on the game's part, but usually crashes.)
X
X3) When cross-compiling for OS/2 in DOS, NDMAKE is the best choice because it
X requires the least RAM for itself. Note however, that cross-compilation
X in DOS is discouraged, because it is considered obsolete (OS/2 is really
X a much better place to compile). If you still want to try, here are some
X suggestions:
X
X During linking, the Microsoft linker will need temporary storage space.
X Make sure you have about a meg of free disk where-ever you have defined
X your temporary storage. It is also a good idea to compile with as much
X free RAM as possible. It may otherwise get crowded with the bigger, more
X complex source files (compiler bombs with "out of heap space" or similar).
X If this happens, strip your configuration, zap TSR's, get a better memory
X manager etc.
X
X4) The file sys\share\termcap.uu is the fixed version of the Fred Fish
X termcap library. You will need to run a uudecode utility on it to
X generate the file termcap.zip. termcap.zip contains several files of
X termcap routines. Using them with NetHack involves very little knowledge
X of the UNIX concept of a termcap database; mostly you need to know enough
X to set a TERM environment variable. You can unzip termcap.zip in the
X sys\share directory, but if you are going to use it, it is probably best
X to unzip a copy in the src directory. That way you will not miss copying
X any files over. Wherever you unzip it, get rid of the included makefile
X since a better version has been provided as Makefile.lib. After creating
X the termcap library file termlib.lib, copy it to src before compiling the
X game main source.
X
X5) When compiling with MSC 6.0, the maintenance version 6.0A should be used
X instead of the original 6.0, which was all too buggy to successfully build
X NetHack 3.1.
X
X6) Note that emx 0.8f is the first version of GCC for OS/2 that can properly
X compile NetHack. Earlier versions do not work, because they don't support
X the 16 bit API calls of OS/2.
X
X GCC emx 0.8f does not currently work properly when fseek() function is
X used with text files. This is well documented in the compiler's
X documentation. Unfortunately NetHack uses fseek() in several places in
X connection with text data. This means that some help texts may not come
X out right, but no serious problems should emerge.
END_OF_FILE
if test 14816 -ne `wc -c <'sys/os2/Install.os2'`; then
echo shar: \"'sys/os2/Install.os2'\" unpacked with wrong size!
fi
# end of 'sys/os2/Install.os2'
fi
echo shar: End of archive 34 \(of 108\).
cp /dev/null ark34isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
101 102 103 104 105 106 107 108 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 108 archives.
echo "Now execute 'rebuild.sh'"
rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0