Home | History | Annotate | Line # | Download | only in hack
      1  1.12    rillig /*	$NetBSD: hack.c,v 1.12 2021/05/02 12:50:44 rillig Exp $	*/
      2   1.4  christos 
      3   1.2   mycroft /*
      4   1.6       jsm  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
      5   1.6       jsm  * Amsterdam
      6   1.6       jsm  * All rights reserved.
      7   1.6       jsm  *
      8   1.6       jsm  * Redistribution and use in source and binary forms, with or without
      9   1.6       jsm  * modification, are permitted provided that the following conditions are
     10   1.6       jsm  * met:
     11   1.6       jsm  *
     12   1.6       jsm  * - Redistributions of source code must retain the above copyright notice,
     13   1.6       jsm  * this list of conditions and the following disclaimer.
     14   1.6       jsm  *
     15   1.6       jsm  * - Redistributions in binary form must reproduce the above copyright
     16   1.6       jsm  * notice, this list of conditions and the following disclaimer in the
     17   1.6       jsm  * documentation and/or other materials provided with the distribution.
     18   1.6       jsm  *
     19   1.6       jsm  * - Neither the name of the Stichting Centrum voor Wiskunde en
     20   1.6       jsm  * Informatica, nor the names of its contributors may be used to endorse or
     21   1.6       jsm  * promote products derived from this software without specific prior
     22   1.6       jsm  * written permission.
     23   1.6       jsm  *
     24   1.6       jsm  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     25   1.6       jsm  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     26   1.6       jsm  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     27   1.6       jsm  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     28   1.6       jsm  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     29   1.6       jsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     30   1.6       jsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     31   1.6       jsm  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     32   1.6       jsm  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     33   1.6       jsm  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     34   1.6       jsm  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     35   1.6       jsm  */
     36   1.6       jsm 
     37   1.6       jsm /*
     38   1.6       jsm  * Copyright (c) 1982 Jay Fenlason <hack (at) gnu.org>
     39   1.6       jsm  * All rights reserved.
     40   1.6       jsm  *
     41   1.6       jsm  * Redistribution and use in source and binary forms, with or without
     42   1.6       jsm  * modification, are permitted provided that the following conditions
     43   1.6       jsm  * are met:
     44   1.6       jsm  * 1. Redistributions of source code must retain the above copyright
     45   1.6       jsm  *    notice, this list of conditions and the following disclaimer.
     46   1.6       jsm  * 2. Redistributions in binary form must reproduce the above copyright
     47   1.6       jsm  *    notice, this list of conditions and the following disclaimer in the
     48   1.6       jsm  *    documentation and/or other materials provided with the distribution.
     49   1.6       jsm  * 3. The name of the author may not be used to endorse or promote products
     50   1.6       jsm  *    derived from this software without specific prior written permission.
     51   1.6       jsm  *
     52   1.6       jsm  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     53   1.6       jsm  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
     54   1.6       jsm  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
     55   1.6       jsm  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     56   1.6       jsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     57   1.6       jsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     58   1.6       jsm  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     59   1.6       jsm  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     60   1.6       jsm  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     61   1.6       jsm  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     62   1.2   mycroft  */
     63   1.2   mycroft 
     64   1.4  christos #include <sys/cdefs.h>
     65   1.2   mycroft #ifndef lint
     66  1.12    rillig __RCSID("$NetBSD: hack.c,v 1.12 2021/05/02 12:50:44 rillig Exp $");
     67   1.4  christos #endif				/* not lint */
     68   1.1       cgd 
     69   1.1       cgd #include "hack.h"
     70   1.4  christos #include "extern.h"
     71   1.1       cgd 
     72   1.9  dholland static void movobj(struct obj *, int, int);
     73   1.9  dholland static int inv_cnt(void);
     74   1.9  dholland 
     75   1.4  christos /*
     76   1.4  christos  * called on movement: 1. when throwing ball+chain far away 2. when
     77   1.4  christos  * teleporting 3. when walking out of a lit room
     78   1.1       cgd  */
     79   1.4  christos void
     80   1.8  dholland unsee(void)
     81   1.4  christos {
     82   1.4  christos 	int x, y;
     83   1.4  christos 	struct rm *lev;
     84   1.1       cgd 
     85   1.4  christos 	/*
     86   1.4  christos 		if(u.udispl){
     87   1.4  christos 			u.udispl = 0;
     88   1.4  christos 			newsym(u.udisx, u.udisy);
     89   1.4  christos 		}
     90   1.4  christos 	*/
     91   1.1       cgd #ifndef QUEST
     92   1.4  christos 	if (seehx) {
     93   1.1       cgd 		seehx = 0;
     94   1.1       cgd 	} else
     95   1.4  christos #endif	/* QUEST */
     96   1.4  christos 		for (x = u.ux - 1; x < u.ux + 2; x++)
     97   1.4  christos 			for (y = u.uy - 1; y < u.uy + 2; y++) {
     98   1.4  christos 				if (!isok(x, y))
     99   1.4  christos 					continue;
    100   1.4  christos 				lev = &levl[x][y];
    101   1.4  christos 				if (!lev->lit && lev->scrsym == '.') {
    102   1.4  christos 					lev->scrsym = ' ';
    103   1.4  christos 					lev->new = 1;
    104   1.4  christos 					on_scr(x, y);
    105   1.4  christos 				}
    106   1.4  christos 			}
    107   1.1       cgd }
    108   1.1       cgd 
    109   1.4  christos /*
    110   1.4  christos  * called: in hack.eat.c: seeoff(0) - blind after eating rotten food in
    111   1.4  christos  * hack.mon.c: seeoff(0) - blinded by a yellow light in hack.mon.c: seeoff(1)
    112   1.4  christos  * - swallowed in hack.do.c:  seeoff(0) - blind after drinking potion in
    113   1.4  christos  * hack.do.c:  seeoff(1) - go up or down the stairs in hack.trap.c:seeoff(1)
    114   1.4  christos  * - fall through trapdoor
    115   1.1       cgd  */
    116   1.8  dholland /* mode: */
    117   1.8  dholland 	/* 1 to redo @, 0 to leave them *//* 1 means
    118   1.8  dholland 	 * misc movement, 0 means blindness */
    119   1.4  christos void
    120   1.8  dholland seeoff(int mode)
    121   1.4  christos {
    122   1.4  christos 	int x, y;
    123   1.4  christos 	struct rm *lev;
    124   1.1       cgd 
    125   1.4  christos 	if (u.udispl && mode) {
    126   1.1       cgd 		u.udispl = 0;
    127   1.4  christos 		levl[u.udisx][u.udisy].scrsym = news0(u.udisx, u.udisy);
    128   1.1       cgd 	}
    129   1.1       cgd #ifndef QUEST
    130   1.4  christos 	if (seehx) {
    131   1.1       cgd 		seehx = 0;
    132   1.1       cgd 	} else
    133   1.4  christos #endif	/* QUEST */
    134   1.4  christos 	if (!mode) {
    135   1.4  christos 		for (x = u.ux - 1; x < u.ux + 2; x++)
    136   1.4  christos 			for (y = u.uy - 1; y < u.uy + 2; y++) {
    137   1.4  christos 				if (!isok(x, y))
    138   1.4  christos 					continue;
    139   1.1       cgd 				lev = &levl[x][y];
    140   1.4  christos 				if (!lev->lit && lev->scrsym == '.')
    141   1.1       cgd 					lev->seen = 0;
    142   1.1       cgd 			}
    143   1.1       cgd 	}
    144   1.1       cgd }
    145   1.1       cgd 
    146   1.4  christos void
    147   1.8  dholland domove(void)
    148   1.1       cgd {
    149   1.4  christos 	xchar           oldx, oldy;
    150   1.4  christos 	struct monst *mtmp = NULL;
    151   1.4  christos 	struct rm *tmpr, *ust;
    152   1.4  christos 	struct trap    *trap = NULL;
    153   1.4  christos 	struct obj *otmp = NULL;
    154   1.1       cgd 
    155   1.1       cgd 	u_wipe_engr(rnd(5));
    156   1.1       cgd 
    157   1.4  christos 	if (inv_weight() > 0) {
    158   1.1       cgd 		pline("You collapse under your load.");
    159   1.1       cgd 		nomul(0);
    160   1.1       cgd 		return;
    161   1.1       cgd 	}
    162   1.4  christos 	if (u.uswallow) {
    163   1.1       cgd 		u.dx = u.dy = 0;
    164   1.1       cgd 		u.ux = u.ustuck->mx;
    165   1.1       cgd 		u.uy = u.ustuck->my;
    166   1.1       cgd 	} else {
    167   1.4  christos 		if (Confusion) {
    168   1.1       cgd 			do {
    169   1.1       cgd 				confdir();
    170   1.4  christos 			} while (!isok(u.ux + u.dx, u.uy + u.dy) ||
    171   1.4  christos 			       IS_ROCK(levl[u.ux + u.dx][u.uy + u.dy].typ));
    172   1.1       cgd 		}
    173   1.4  christos 		if (!isok(u.ux + u.dx, u.uy + u.dy)) {
    174   1.1       cgd 			nomul(0);
    175   1.1       cgd 			return;
    176   1.1       cgd 		}
    177   1.1       cgd 	}
    178   1.1       cgd 
    179   1.1       cgd 	ust = &levl[u.ux][u.uy];
    180   1.1       cgd 	oldx = u.ux;
    181   1.1       cgd 	oldy = u.uy;
    182   1.4  christos 	if (!u.uswallow && (trap = t_at(u.ux + u.dx, u.uy + u.dy)) && trap->tseen)
    183   1.1       cgd 		nomul(0);
    184   1.4  christos 	if (u.ustuck && !u.uswallow && (u.ux + u.dx != u.ustuck->mx ||
    185   1.4  christos 					u.uy + u.dy != u.ustuck->my)) {
    186   1.4  christos 		if (dist(u.ustuck->mx, u.ustuck->my) > 2) {
    187   1.1       cgd 			/* perhaps it fled (or was teleported or ... ) */
    188   1.1       cgd 			u.ustuck = 0;
    189   1.1       cgd 		} else {
    190   1.4  christos 			if (Blind)
    191   1.4  christos 				pline("You cannot escape from it!");
    192   1.4  christos 			else
    193   1.4  christos 				pline("You cannot escape from %s!",
    194   1.4  christos 				      monnam(u.ustuck));
    195   1.1       cgd 			nomul(0);
    196   1.1       cgd 			return;
    197   1.1       cgd 		}
    198   1.1       cgd 	}
    199   1.4  christos 	if (u.uswallow || (mtmp = m_at(u.ux + u.dx, u.uy + u.dy))) {
    200   1.4  christos 		/* attack monster */
    201   1.1       cgd 
    202   1.1       cgd 		nomul(0);
    203   1.1       cgd 		gethungry();
    204   1.4  christos 		if (multi < 0)
    205   1.4  christos 			return;	/* we just fainted */
    206   1.1       cgd 
    207   1.1       cgd 		/* try to attack; note that it might evade */
    208   1.4  christos 		if (attack(u.uswallow ? u.ustuck : mtmp))
    209   1.1       cgd 			return;
    210   1.1       cgd 	}
    211   1.1       cgd 	/* not attacking an animal, so we try to move */
    212   1.4  christos 	if (u.utrap) {
    213   1.4  christos 		if (u.utraptype == TT_PIT) {
    214   1.1       cgd 			pline("You are still in a pit.");
    215   1.1       cgd 			u.utrap--;
    216   1.1       cgd 		} else {
    217   1.1       cgd 			pline("You are caught in a beartrap.");
    218   1.4  christos 			if ((u.dx && u.dy) || !rn2(5))
    219   1.4  christos 				u.utrap--;
    220   1.1       cgd 		}
    221   1.1       cgd 		return;
    222   1.1       cgd 	}
    223   1.4  christos 	tmpr = &levl[u.ux + u.dx][u.uy + u.dy];
    224   1.4  christos 	if (IS_ROCK(tmpr->typ) ||
    225   1.4  christos 	    (u.dx && u.dy && (tmpr->typ == DOOR || ust->typ == DOOR))) {
    226   1.1       cgd 		flags.move = 0;
    227   1.1       cgd 		nomul(0);
    228   1.1       cgd 		return;
    229   1.1       cgd 	}
    230   1.4  christos 	while ((otmp = sobj_at(ENORMOUS_ROCK, u.ux + u.dx, u.uy + u.dy)) != NULL){
    231   1.4  christos 		xchar  rx = u.ux + 2 * u.dx, ry = u.uy + 2 * u.dy;
    232   1.4  christos 		struct trap *ttmp;
    233   1.1       cgd 		nomul(0);
    234   1.4  christos 		if (isok(rx, ry) && !IS_ROCK(levl[rx][ry].typ) &&
    235   1.1       cgd 		    (levl[rx][ry].typ != DOOR || !(u.dx && u.dy)) &&
    236   1.1       cgd 		    !sobj_at(ENORMOUS_ROCK, rx, ry)) {
    237   1.4  christos 			if (m_at(rx, ry)) {
    238   1.4  christos 				pline("You hear a monster behind the rock.");
    239   1.4  christos 				pline("Perhaps that's why you cannot move it.");
    240   1.4  christos 				goto cannot_push;
    241   1.4  christos 			}
    242   1.4  christos 			if ((ttmp = t_at(rx, ry)) != NULL)
    243   1.4  christos 				switch (ttmp->ttyp) {
    244   1.4  christos 				case PIT:
    245   1.4  christos 					pline("You push the rock into a pit!");
    246   1.4  christos 					deltrap(ttmp);
    247   1.4  christos 					delobj(otmp);
    248   1.4  christos 					pline("It completely fills the pit!");
    249   1.4  christos 					continue;
    250   1.4  christos 				case TELEP_TRAP:
    251   1.4  christos 					pline("You push the rock and suddenly it disappears!");
    252   1.4  christos 					delobj(otmp);
    253   1.4  christos 					continue;
    254   1.4  christos 				}
    255   1.4  christos 			if (levl[rx][ry].typ == POOL) {
    256   1.1       cgd 				levl[rx][ry].typ = ROOM;
    257   1.4  christos 				mnewsym(rx, ry);
    258   1.4  christos 				prl(rx, ry);
    259   1.1       cgd 				pline("You push the rock into the water.");
    260   1.1       cgd 				pline("Now you can cross the water!");
    261   1.1       cgd 				delobj(otmp);
    262   1.1       cgd 				continue;
    263   1.1       cgd 			}
    264   1.1       cgd 			otmp->ox = rx;
    265   1.1       cgd 			otmp->oy = ry;
    266   1.1       cgd 			/* pobj(otmp); */
    267   1.4  christos 			if (cansee(rx, ry))
    268   1.4  christos 				atl(rx, ry, otmp->olet);
    269   1.4  christos 			if (Invisible)
    270   1.4  christos 				newsym(u.ux + u.dx, u.uy + u.dy);
    271   1.4  christos 
    272   1.4  christos 			{
    273   1.4  christos 				static long     lastmovetime;
    274   1.4  christos 				/*
    275   1.4  christos 				 * note: this var contains garbage initially
    276   1.4  christos 				 * and after a restore
    277   1.4  christos 				 */
    278   1.4  christos 				if (moves > lastmovetime + 2 || moves < lastmovetime)
    279   1.4  christos 					pline("With great effort you move the enormous rock.");
    280   1.4  christos 				lastmovetime = moves;
    281   1.1       cgd 			}
    282   1.1       cgd 		} else {
    283   1.4  christos 			pline("You try to move the enormous rock, but in vain.");
    284   1.4  christos 	cannot_push:
    285   1.4  christos 			if ((!invent || inv_weight() + 90 <= 0) &&
    286   1.4  christos 			    (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][u.uy + u.dy].typ)
    287   1.4  christos 				&& IS_ROCK(levl[u.ux + u.dx][u.uy].typ)))) {
    288   1.4  christos 				pline("However, you can squeeze yourself into a small opening.");
    289   1.4  christos 				break;
    290   1.4  christos 			} else
    291   1.4  christos 				return;
    292   1.1       cgd 		}
    293   1.4  christos 	}
    294   1.4  christos 	if (u.dx && u.dy && IS_ROCK(levl[u.ux][u.uy + u.dy].typ) &&
    295   1.4  christos 	    IS_ROCK(levl[u.ux + u.dx][u.uy].typ) &&
    296   1.4  christos 	    invent && inv_weight() + 40 > 0) {
    297   1.1       cgd 		pline("You are carrying too much to get through.");
    298   1.1       cgd 		nomul(0);
    299   1.1       cgd 		return;
    300   1.1       cgd 	}
    301   1.4  christos 	if (Punished &&
    302   1.4  christos 	    DIST(u.ux + u.dx, u.uy + u.dy, uchain->ox, uchain->oy) > 2) {
    303   1.4  christos 		if (carried(uball)) {
    304   1.1       cgd 			movobj(uchain, u.ux, u.uy);
    305   1.1       cgd 			goto nodrag;
    306   1.1       cgd 		}
    307   1.4  christos 		if (DIST(u.ux + u.dx, u.uy + u.dy, uball->ox, uball->oy) < 3) {
    308   1.1       cgd 			/* leave ball, move chain under/over ball */
    309   1.1       cgd 			movobj(uchain, uball->ox, uball->oy);
    310   1.1       cgd 			goto nodrag;
    311   1.1       cgd 		}
    312   1.4  christos 		if (inv_weight() + (int) uball->owt / 2 > 0) {
    313   1.1       cgd 			pline("You cannot %sdrag the heavy iron ball.",
    314   1.4  christos 			      invent ? "carry all that and also " : "");
    315   1.1       cgd 			nomul(0);
    316   1.1       cgd 			return;
    317   1.1       cgd 		}
    318   1.1       cgd 		movobj(uball, uchain->ox, uchain->oy);
    319   1.4  christos 		unpobj(uball);	/* BAH %% */
    320   1.1       cgd 		uchain->ox = u.ux;
    321   1.1       cgd 		uchain->oy = u.uy;
    322   1.1       cgd 		nomul(-2);
    323   1.1       cgd 		nomovemsg = "";
    324   1.4  christos nodrag:	;
    325   1.1       cgd 	}
    326   1.1       cgd 	u.ux += u.dx;
    327   1.1       cgd 	u.uy += u.dy;
    328   1.4  christos 	if (flags.run) {
    329   1.4  christos 		if (tmpr->typ == DOOR ||
    330   1.4  christos 		    (xupstair == u.ux && yupstair == u.uy) ||
    331   1.4  christos 		    (xdnstair == u.ux && ydnstair == u.uy))
    332   1.1       cgd 			nomul(0);
    333   1.1       cgd 	}
    334   1.4  christos 	if (tmpr->typ == POOL && !Levitation)
    335   1.1       cgd 		drown();	/* not necessarily fatal */
    336   1.1       cgd 
    337   1.4  christos 	/*
    338   1.4  christos 		if(u.udispl) {
    339   1.4  christos 			u.udispl = 0;
    340   1.4  christos 			newsym(oldx,oldy);
    341   1.4  christos 		}
    342   1.4  christos 	*/
    343   1.4  christos 	if (!Blind) {
    344   1.1       cgd #ifdef QUEST
    345   1.1       cgd 		setsee();
    346   1.1       cgd #else
    347   1.4  christos 		if (ust->lit) {
    348   1.4  christos 			if (tmpr->lit) {
    349   1.4  christos 				if (tmpr->typ == DOOR)
    350   1.4  christos 					prl1(u.ux + u.dx, u.uy + u.dy);
    351   1.4  christos 				else if (ust->typ == DOOR)
    352   1.4  christos 					nose1(oldx - u.dx, oldy - u.dy);
    353   1.1       cgd 			} else {
    354   1.1       cgd 				unsee();
    355   1.4  christos 				prl1(u.ux + u.dx, u.uy + u.dy);
    356   1.1       cgd 			}
    357   1.1       cgd 		} else {
    358   1.4  christos 			if (tmpr->lit)
    359   1.4  christos 				setsee();
    360   1.1       cgd 			else {
    361   1.4  christos 				prl1(u.ux + u.dx, u.uy + u.dy);
    362   1.4  christos 				if (tmpr->typ == DOOR) {
    363   1.4  christos 					if (u.dy) {
    364   1.4  christos 						prl(u.ux - 1, u.uy);
    365   1.4  christos 						prl(u.ux + 1, u.uy);
    366   1.1       cgd 					} else {
    367   1.4  christos 						prl(u.ux, u.uy - 1);
    368   1.4  christos 						prl(u.ux, u.uy + 1);
    369   1.1       cgd 					}
    370   1.1       cgd 				}
    371   1.1       cgd 			}
    372   1.4  christos 			nose1(oldx - u.dx, oldy - u.dy);
    373   1.1       cgd 		}
    374   1.4  christos #endif	/* QUEST */
    375   1.1       cgd 	} else {
    376   1.1       cgd 		pru();
    377   1.1       cgd 	}
    378   1.4  christos 	if (!flags.nopick)
    379   1.4  christos 		pickup(1);
    380   1.4  christos 	if (trap)
    381   1.4  christos 		dotrap(trap);	/* fall into pit, arrow trap, etc. */
    382   1.1       cgd 	(void) inshop();
    383   1.4  christos 	if (!Blind)
    384   1.4  christos 		read_engr_at(u.ux, u.uy);
    385   1.1       cgd }
    386   1.1       cgd 
    387   1.9  dholland static void
    388   1.8  dholland movobj(struct obj *obj, int ox, int oy)
    389   1.1       cgd {
    390   1.1       cgd 	/* Some dirty programming to get display right */
    391   1.1       cgd 	freeobj(obj);
    392   1.1       cgd 	unpobj(obj);
    393   1.1       cgd 	obj->nobj = fobj;
    394   1.1       cgd 	fobj = obj;
    395   1.1       cgd 	obj->ox = ox;
    396   1.1       cgd 	obj->oy = oy;
    397   1.1       cgd }
    398   1.1       cgd 
    399   1.4  christos int
    400   1.8  dholland dopickup(void)
    401   1.4  christos {
    402   1.4  christos 	if (!g_at(u.ux, u.uy) && !o_at(u.ux, u.uy)) {
    403   1.1       cgd 		pline("There is nothing here to pick up.");
    404   1.4  christos 		return (0);
    405   1.1       cgd 	}
    406   1.4  christos 	if (Levitation) {
    407   1.1       cgd 		pline("You cannot reach the floor.");
    408   1.4  christos 		return (1);
    409   1.1       cgd 	}
    410   1.1       cgd 	pickup(0);
    411   1.4  christos 	return (1);
    412   1.1       cgd }
    413   1.1       cgd 
    414   1.4  christos void
    415   1.5       jsm pickup(int all)
    416   1.1       cgd {
    417   1.4  christos 	struct gold *gold;
    418   1.4  christos 	struct obj *obj, *obj2;
    419   1.4  christos 	int    wt;
    420   1.1       cgd 
    421   1.4  christos 	if (Levitation)
    422   1.4  christos 		return;
    423   1.4  christos 	while ((gold = g_at(u.ux, u.uy)) != NULL) {
    424   1.1       cgd 		pline("%ld gold piece%s.", gold->amount, plur(gold->amount));
    425   1.1       cgd 		u.ugold += gold->amount;
    426   1.1       cgd 		flags.botl = 1;
    427   1.1       cgd 		freegold(gold);
    428   1.4  christos 		if (flags.run)
    429   1.4  christos 			nomul(0);
    430   1.4  christos 		if (Invisible)
    431   1.4  christos 			newsym(u.ux, u.uy);
    432   1.1       cgd 	}
    433   1.1       cgd 
    434   1.1       cgd 	/* check for more than one object */
    435   1.4  christos 	if (!all) {
    436   1.4  christos 		int    ct = 0;
    437   1.1       cgd 
    438   1.4  christos 		for (obj = fobj; obj; obj = obj->nobj)
    439   1.4  christos 			if (obj->ox == u.ux && obj->oy == u.uy)
    440   1.4  christos 				if (!Punished || obj != uchain)
    441   1.1       cgd 					ct++;
    442   1.4  christos 		if (ct < 2)
    443   1.1       cgd 			all++;
    444   1.1       cgd 		else
    445   1.1       cgd 			pline("There are several objects here.");
    446   1.1       cgd 	}
    447   1.4  christos 	for (obj = fobj; obj; obj = obj2) {
    448   1.4  christos 		obj2 = obj->nobj;	/* perhaps obj will be picked up */
    449   1.4  christos 		if (obj->ox == u.ux && obj->oy == u.uy) {
    450   1.4  christos 			if (flags.run)
    451   1.4  christos 				nomul(0);
    452   1.1       cgd 
    453   1.4  christos 			/* do not pick up uchain */
    454   1.4  christos 			if (Punished && obj == uchain)
    455   1.4  christos 				continue;
    456   1.4  christos 
    457   1.4  christos 			if (!all) {
    458   1.4  christos 				char            c;
    459   1.4  christos 
    460   1.4  christos 				pline("Pick up %s ? [ynaq]", doname(obj));
    461   1.4  christos 				while (!strchr("ynaq ", (c = readchar())))
    462  1.10       roy 					sound_bell();
    463   1.4  christos 				if (c == 'q')
    464   1.4  christos 					return;
    465   1.4  christos 				if (c == 'n')
    466   1.4  christos 					continue;
    467   1.4  christos 				if (c == 'a')
    468   1.4  christos 					all = 1;
    469   1.4  christos 			}
    470   1.4  christos 			if (obj->otyp == DEAD_COCKATRICE && !uarmg) {
    471   1.4  christos 				pline("Touching the dead cockatrice is a fatal mistake.");
    472   1.4  christos 				pline("You turn to stone.");
    473   1.4  christos 				killer = "cockatrice cadaver";
    474   1.4  christos 				done("died");
    475   1.4  christos 			}
    476   1.4  christos 			if (obj->otyp == SCR_SCARE_MONSTER) {
    477   1.4  christos 				if (!obj->spe)
    478   1.4  christos 					obj->spe = 1;
    479   1.4  christos 				else {
    480   1.4  christos 					/*
    481   1.4  christos 					 * Note: perhaps the 1st pickup
    482   1.4  christos 					 * failed: you cannot carry anymore,
    483   1.4  christos 					 * and so we never dropped it - let's
    484   1.4  christos 					 * assume that treading on it twice
    485   1.4  christos 					 * also destroys the scroll
    486   1.4  christos 					 */
    487   1.4  christos 					pline("The scroll turns to dust as you pick it up.");
    488   1.4  christos 					delobj(obj);
    489   1.4  christos 					continue;
    490   1.1       cgd 				}
    491   1.1       cgd 			}
    492   1.4  christos 			wt = inv_weight() + obj->owt;
    493   1.4  christos 			if (wt > 0) {
    494   1.4  christos 				if (obj->quan > 1) {
    495   1.4  christos 					/* see how many we can lift */
    496   1.4  christos 					int             savequan = obj->quan;
    497   1.4  christos 					int             iw = inv_weight();
    498   1.4  christos 					int             qq;
    499   1.4  christos 					for (qq = 1; qq < savequan; qq++) {
    500   1.4  christos 						obj->quan = qq;
    501   1.4  christos 						if (iw + weight(obj) > 0)
    502   1.4  christos 							break;
    503   1.4  christos 					}
    504   1.4  christos 					obj->quan = savequan;
    505   1.4  christos 					qq--;
    506   1.4  christos 					/* we can carry qq of them */
    507   1.4  christos 					if (!qq)
    508   1.4  christos 						goto too_heavy;
    509   1.4  christos 					pline("You can only carry %s of the %s lying here.",
    510   1.4  christos 					      (qq == 1) ? "one" : "some",
    511   1.4  christos 					      doname(obj));
    512   1.4  christos 					(void) splitobj(obj, qq);
    513   1.4  christos 					/*
    514   1.4  christos 					 * note: obj2 is set already, so
    515   1.4  christos 					 * we'll never encounter the other
    516   1.4  christos 					 * half; if it should be otherwise
    517   1.4  christos 					 * then write obj2 =
    518   1.4  christos 					 * splitobj(obj,qq);
    519   1.4  christos 					 */
    520   1.4  christos 					goto lift_some;
    521   1.4  christos 				}
    522   1.1       cgd 		too_heavy:
    523   1.4  christos 				pline("There %s %s here, but %s.",
    524   1.4  christos 				      (obj->quan == 1) ? "is" : "are",
    525   1.4  christos 				      doname(obj),
    526   1.4  christos 				 !invent ? "it is too heavy for you to lift"
    527   1.4  christos 				      : "you cannot carry anymore");
    528   1.4  christos 				break;
    529   1.4  christos 			}
    530   1.1       cgd 	lift_some:
    531   1.4  christos 			if (inv_cnt() >= 52) {
    532   1.7  christos 				pline("Your knapsack cannot accommodate anymore items.");
    533   1.4  christos 				break;
    534   1.4  christos 			}
    535   1.4  christos 			if (wt > -5)
    536   1.4  christos 				pline("You have a little trouble lifting");
    537   1.4  christos 			freeobj(obj);
    538   1.4  christos 			if (Invisible)
    539   1.4  christos 				newsym(u.ux, u.uy);
    540   1.4  christos 			addtobill(obj);	/* sets obj->unpaid if necessary */
    541   1.4  christos 			{
    542   1.4  christos 				int             pickquan = obj->quan;
    543   1.4  christos 				int             mergquan;
    544   1.4  christos 				if (!Blind)
    545   1.4  christos 					obj->dknown = 1;	/* this is done by
    546   1.4  christos 								 * prinv(), but addinv()
    547   1.4  christos 								 * needs it already for
    548   1.4  christos 								 * merging */
    549   1.4  christos 				obj = addinv(obj);	/* might merge it with
    550   1.4  christos 							 * other objects */
    551   1.4  christos 				mergquan = obj->quan;
    552   1.4  christos 				obj->quan = pickquan;	/* to fool prinv() */
    553   1.4  christos 				prinv(obj);
    554   1.4  christos 				obj->quan = mergquan;
    555   1.4  christos 			}
    556   1.1       cgd 		}
    557   1.1       cgd 	}
    558   1.1       cgd }
    559   1.1       cgd 
    560   1.1       cgd /* stop running if we see something interesting */
    561   1.1       cgd /* turn around a corner if that is the only way we can proceed */
    562   1.1       cgd /* do not turn left or right twice */
    563   1.4  christos void
    564   1.8  dholland lookaround(void)
    565   1.4  christos {
    566   1.4  christos 	int    x, y, i, x0 = 0, y0 = 0, m0 = 0, i0 = 9;
    567   1.4  christos 	int    corrct = 0, noturn = 0;
    568   1.4  christos 	struct monst *mtmp;
    569   1.4  christos 	if (Blind || flags.run == 0)
    570   1.4  christos 		return;
    571   1.4  christos 	if (flags.run == 1 && levl[u.ux][u.uy].typ == ROOM)
    572   1.4  christos 		return;
    573   1.1       cgd #ifdef QUEST
    574   1.4  christos 	if (u.ux0 == u.ux + u.dx && u.uy0 == u.uy + u.dy)
    575   1.4  christos 		goto stop;
    576   1.4  christos #endif	/* QUEST */
    577   1.4  christos 	for (x = u.ux - 1; x <= u.ux + 1; x++)
    578   1.4  christos 		for (y = u.uy - 1; y <= u.uy + 1; y++) {
    579   1.4  christos 			if (x == u.ux && y == u.uy)
    580   1.4  christos 				continue;
    581   1.4  christos 			if (!levl[x][y].typ)
    582   1.4  christos 				continue;
    583   1.4  christos 			if ((mtmp = m_at(x, y)) && !mtmp->mimic &&
    584   1.4  christos 			    (!mtmp->minvis || See_invisible)) {
    585   1.4  christos 				if (!mtmp->mtame || (x == u.ux + u.dx && y == u.uy + u.dy))
    586   1.4  christos 					goto stop;
    587   1.4  christos 			} else
    588   1.4  christos 				mtmp = 0;	/* invisible M cannot
    589   1.4  christos 						 * influence us */
    590   1.4  christos 			if (x == u.ux - u.dx && y == u.uy - u.dy)
    591   1.4  christos 				continue;
    592   1.4  christos 			switch (levl[x][y].scrsym) {
    593   1.4  christos 			case '|':
    594   1.4  christos 			case '-':
    595   1.4  christos 			case '.':
    596   1.4  christos 			case ' ':
    597   1.4  christos 				break;
    598   1.4  christos 			case '+':
    599   1.4  christos 				if (x != u.ux && y != u.uy)
    600   1.4  christos 					break;
    601   1.4  christos 				if (flags.run != 1)
    602   1.4  christos 					goto stop;
    603  1.11  dholland 				/* FALLTHROUGH */
    604   1.4  christos 			case CORR_SYM:
    605   1.1       cgd 		corr:
    606   1.4  christos 				if (flags.run == 1 || flags.run == 3) {
    607   1.4  christos 					i = DIST(x, y, u.ux + u.dx, u.uy + u.dy);
    608   1.4  christos 					if (i > 2)
    609   1.4  christos 						break;
    610   1.4  christos 					if (corrct == 1 && DIST(x, y, x0, y0) != 1)
    611   1.4  christos 						noturn = 1;
    612   1.4  christos 					if (i < i0) {
    613   1.4  christos 						i0 = i;
    614   1.4  christos 						x0 = x;
    615   1.4  christos 						y0 = y;
    616   1.4  christos 						m0 = mtmp ? 1 : 0;
    617   1.4  christos 					}
    618   1.1       cgd 				}
    619   1.4  christos 				corrct++;
    620   1.4  christos 				break;
    621   1.4  christos 			case '^':
    622   1.4  christos 				if (flags.run == 1)
    623   1.4  christos 					goto corr;	/* if you must */
    624   1.4  christos 				if (x == u.ux + u.dx && y == u.uy + u.dy)
    625   1.4  christos 					goto stop;
    626   1.4  christos 				break;
    627   1.4  christos 			default:	/* e.g. objects or trap or stairs */
    628   1.4  christos 				if (flags.run == 1)
    629   1.4  christos 					goto corr;
    630   1.4  christos 				if (mtmp)
    631   1.4  christos 					break;	/* d */
    632   1.4  christos 		stop:
    633   1.4  christos 				nomul(0);
    634   1.4  christos 				return;
    635   1.1       cgd 			}
    636   1.1       cgd 		}
    637   1.1       cgd #ifdef QUEST
    638   1.4  christos 	if (corrct > 0 && (flags.run == 4 || flags.run == 5))
    639   1.4  christos 		goto stop;
    640   1.4  christos #endif	/* QUEST */
    641   1.4  christos 	if (corrct > 1 && flags.run == 2)
    642   1.4  christos 		goto stop;
    643   1.4  christos 	if ((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&
    644   1.4  christos 	    (corrct == 1 || (corrct == 2 && i0 == 1))) {
    645   1.1       cgd 		/* make sure that we do not turn too far */
    646   1.4  christos 		if (i0 == 2) {
    647   1.4  christos 			if (u.dx == y0 - u.uy && u.dy == u.ux - x0)
    648   1.4  christos 				i = 2;	/* straight turn right */
    649   1.4  christos 			else
    650   1.4  christos 				i = -2;	/* straight turn left */
    651   1.4  christos 		} else if (u.dx && u.dy) {
    652   1.4  christos 			if ((u.dx == u.dy && y0 == u.uy) ||
    653   1.4  christos 			    (u.dx != u.dy && y0 != u.uy))
    654   1.4  christos 				i = -1;	/* half turn left */
    655   1.4  christos 			else
    656   1.4  christos 				i = 1;	/* half turn right */
    657   1.1       cgd 		} else {
    658   1.4  christos 			if ((x0 - u.ux == y0 - u.uy && !u.dy) ||
    659   1.4  christos 			    (x0 - u.ux != y0 - u.uy && u.dy))
    660   1.4  christos 				i = 1;	/* half turn right */
    661   1.4  christos 			else
    662   1.4  christos 				i = -1;	/* half turn left */
    663   1.1       cgd 		}
    664   1.1       cgd 		i += u.last_str_turn;
    665   1.4  christos 		if (i <= 2 && i >= -2) {
    666   1.1       cgd 			u.last_str_turn = i;
    667   1.4  christos 			u.dx = x0 - u.ux, u.dy = y0 - u.uy;
    668   1.1       cgd 		}
    669   1.1       cgd 	}
    670   1.1       cgd }
    671   1.1       cgd 
    672   1.1       cgd /* something like lookaround, but we are not running */
    673   1.1       cgd /* react only to monsters that might hit us */
    674   1.4  christos int
    675   1.8  dholland monster_nearby(void)
    676   1.4  christos {
    677   1.4  christos 	int    x, y;
    678   1.4  christos 	struct monst *mtmp;
    679   1.4  christos 	if (!Blind)
    680   1.4  christos 		for (x = u.ux - 1; x <= u.ux + 1; x++)
    681   1.4  christos 			for (y = u.uy - 1; y <= u.uy + 1; y++) {
    682   1.4  christos 				if (x == u.ux && y == u.uy)
    683   1.4  christos 					continue;
    684   1.4  christos 				if ((mtmp = m_at(x, y)) && !mtmp->mimic && !mtmp->mtame &&
    685   1.4  christos 				    !mtmp->mpeaceful && !strchr("Ea", mtmp->data->mlet) &&
    686   1.4  christos 				    !mtmp->mfroz && !mtmp->msleep &&	/* aplvax!jcn */
    687   1.4  christos 				    (!mtmp->minvis || See_invisible))
    688   1.4  christos 					return (1);
    689   1.4  christos 			}
    690   1.4  christos 	return (0);
    691   1.1       cgd }
    692   1.1       cgd 
    693   1.1       cgd #ifdef QUEST
    694   1.4  christos int
    695   1.8  dholland cansee(xchar x, xchar y)
    696   1.4  christos {
    697   1.4  christos 	int    dx, dy, adx, ady, sdx, sdy, dmax, d;
    698   1.4  christos 	if (Blind)
    699   1.4  christos 		return (0);
    700   1.4  christos 	if (!isok(x, y))
    701   1.4  christos 		return (0);
    702   1.4  christos 	d = dist(x, y);
    703   1.4  christos 	if (d < 3)
    704   1.4  christos 		return (1);
    705   1.4  christos 	if (d > u.uhorizon * u.uhorizon)
    706   1.4  christos 		return (0);
    707   1.4  christos 	if (!levl[x][y].lit)
    708   1.4  christos 		return (0);
    709   1.4  christos 	dx = x - u.ux;
    710   1.4  christos 	adx = abs(dx);
    711   1.4  christos 	sdx = sgn(dx);
    712   1.4  christos 	dy = y - u.uy;
    713   1.4  christos 	ady = abs(dy);
    714   1.4  christos 	sdy = sgn(dy);
    715   1.4  christos 	if (dx == 0 || dy == 0 || adx == ady) {
    716   1.1       cgd 		dmax = (dx == 0) ? ady : adx;
    717   1.4  christos 		for (d = 1; d <= dmax; d++)
    718   1.4  christos 			if (!rroom(sdx * d, sdy * d))
    719   1.4  christos 				return (0);
    720   1.4  christos 		return (1);
    721   1.4  christos 	} else if (ady > adx) {
    722   1.4  christos 		for (d = 1; d <= ady; d++) {
    723   1.4  christos 			if (!rroom(sdx * ((d * adx) / ady), sdy * d) ||
    724   1.4  christos 			    !rroom(sdx * ((d * adx - 1) / ady + 1), sdy * d))
    725   1.4  christos 				return (0);
    726   1.1       cgd 		}
    727   1.4  christos 		return (1);
    728   1.1       cgd 	} else {
    729   1.4  christos 		for (d = 1; d <= adx; d++) {
    730   1.4  christos 			if (!rroom(sdx * d, sdy * ((d * ady) / adx)) ||
    731   1.4  christos 			    !rroom(sdx * d, sdy * ((d * ady - 1) / adx + 1)))
    732   1.4  christos 				return (0);
    733   1.1       cgd 		}
    734   1.4  christos 		return (1);
    735   1.1       cgd 	}
    736   1.1       cgd }
    737   1.1       cgd 
    738   1.4  christos int
    739   1.8  dholland rroom(int x, int y)
    740   1.4  christos {
    741   1.4  christos 	return (IS_ROOM(levl[u.ux + x][u.uy + y].typ));
    742   1.1       cgd }
    743   1.1       cgd 
    744   1.1       cgd #else
    745   1.1       cgd 
    746   1.4  christos int
    747   1.8  dholland cansee(xchar x, xchar y)
    748   1.4  christos {
    749   1.4  christos 	if (Blind || u.uswallow)
    750   1.4  christos 		return (0);
    751   1.4  christos 	if (dist(x, y) < 3)
    752   1.4  christos 		return (1);
    753   1.4  christos 	if (levl[x][y].lit && seelx <= x && x <= seehx && seely <= y &&
    754   1.4  christos 	    y <= seehy)
    755   1.4  christos 		return (1);
    756   1.4  christos 	return (0);
    757   1.4  christos }
    758   1.4  christos #endif	/* QUEST */
    759   1.4  christos 
    760   1.4  christos int
    761   1.8  dholland sgn(int a)
    762   1.4  christos {
    763   1.4  christos 	return ((a > 0) ? 1 : (a == 0) ? 0 : -1);
    764   1.1       cgd }
    765   1.1       cgd 
    766   1.1       cgd #ifdef QUEST
    767   1.4  christos void
    768   1.8  dholland setsee(void)
    769   1.1       cgd {
    770   1.4  christos 	int	x, y;
    771   1.1       cgd 
    772   1.4  christos 	if (Blind) {
    773   1.1       cgd 		pru();
    774   1.1       cgd 		return;
    775   1.1       cgd 	}
    776   1.4  christos 	for (y = u.uy - u.uhorizon; y <= u.uy + u.uhorizon; y++)
    777   1.4  christos 		for (x = u.ux - u.uhorizon; x <= u.ux + u.uhorizon; x++) {
    778   1.4  christos 			if (cansee(x, y))
    779   1.4  christos 				prl(x, y);
    780   1.4  christos 		}
    781   1.1       cgd }
    782   1.1       cgd 
    783   1.1       cgd #else
    784   1.1       cgd 
    785   1.4  christos void
    786   1.8  dholland setsee(void)
    787   1.1       cgd {
    788   1.4  christos 	int x, y;
    789   1.1       cgd 
    790   1.4  christos 	if (Blind) {
    791   1.1       cgd 		pru();
    792   1.1       cgd 		return;
    793   1.1       cgd 	}
    794   1.4  christos 	if (!levl[u.ux][u.uy].lit) {
    795   1.4  christos 		seelx = u.ux - 1;
    796   1.4  christos 		seehx = u.ux + 1;
    797   1.4  christos 		seely = u.uy - 1;
    798   1.4  christos 		seehy = u.uy + 1;
    799   1.1       cgd 	} else {
    800   1.4  christos 		for (seelx = u.ux; levl[seelx - 1][u.uy].lit; seelx--);
    801   1.4  christos 		for (seehx = u.ux; levl[seehx + 1][u.uy].lit; seehx++);
    802   1.4  christos 		for (seely = u.uy; levl[u.ux][seely - 1].lit; seely--);
    803   1.4  christos 		for (seehy = u.uy; levl[u.ux][seehy + 1].lit; seehy++);
    804   1.4  christos 	}
    805   1.4  christos 	for (y = seely; y <= seehy; y++)
    806   1.4  christos 		for (x = seelx; x <= seehx; x++) {
    807   1.4  christos 			prl(x, y);
    808   1.4  christos 		}
    809   1.4  christos 	if (!levl[u.ux][u.uy].lit)
    810   1.4  christos 		seehx = 0;	/* seems necessary elsewhere */
    811   1.1       cgd 	else {
    812   1.4  christos 		if (seely == u.uy)
    813   1.4  christos 			for (x = u.ux - 1; x <= u.ux + 1; x++)
    814   1.4  christos 				prl(x, seely - 1);
    815   1.4  christos 		if (seehy == u.uy)
    816   1.4  christos 			for (x = u.ux - 1; x <= u.ux + 1; x++)
    817   1.4  christos 				prl(x, seehy + 1);
    818   1.4  christos 		if (seelx == u.ux)
    819   1.4  christos 			for (y = u.uy - 1; y <= u.uy + 1; y++)
    820   1.4  christos 				prl(seelx - 1, y);
    821   1.4  christos 		if (seehx == u.ux)
    822   1.4  christos 			for (y = u.uy - 1; y <= u.uy + 1; y++)
    823   1.4  christos 				prl(seehx + 1, y);
    824   1.1       cgd 	}
    825   1.1       cgd }
    826   1.4  christos #endif	/* QUEST */
    827   1.1       cgd 
    828   1.4  christos void
    829   1.8  dholland nomul(int nval)
    830   1.1       cgd {
    831   1.4  christos 	if (multi < 0)
    832   1.4  christos 		return;
    833   1.1       cgd 	multi = nval;
    834   1.1       cgd 	flags.mv = flags.run = 0;
    835   1.1       cgd }
    836   1.1       cgd 
    837   1.4  christos int
    838   1.8  dholland abon(void)
    839   1.1       cgd {
    840   1.4  christos 	if (u.ustr == 3)
    841   1.4  christos 		return (-3);
    842   1.4  christos 	else if (u.ustr < 6)
    843   1.4  christos 		return (-2);
    844   1.4  christos 	else if (u.ustr < 8)
    845   1.4  christos 		return (-1);
    846   1.4  christos 	else if (u.ustr < 17)
    847   1.4  christos 		return (0);
    848   1.4  christos 	else if (u.ustr < 69)
    849   1.4  christos 		return (1);	/* up to 18/50 */
    850   1.4  christos 	else if (u.ustr < 118)
    851   1.4  christos 		return (2);
    852   1.4  christos 	else
    853   1.4  christos 		return (3);
    854   1.1       cgd }
    855   1.1       cgd 
    856   1.4  christos int
    857   1.8  dholland dbon(void)
    858   1.1       cgd {
    859   1.4  christos 	if (u.ustr < 6)
    860   1.4  christos 		return (-1);
    861   1.4  christos 	else if (u.ustr < 16)
    862   1.4  christos 		return (0);
    863   1.4  christos 	else if (u.ustr < 18)
    864   1.4  christos 		return (1);
    865   1.4  christos 	else if (u.ustr == 18)
    866   1.4  christos 		return (2);	/* up to 18 */
    867   1.4  christos 	else if (u.ustr < 94)
    868   1.4  christos 		return (3);	/* up to 18/75 */
    869   1.4  christos 	else if (u.ustr < 109)
    870   1.4  christos 		return (4);	/* up to 18/90 */
    871   1.4  christos 	else if (u.ustr < 118)
    872   1.4  christos 		return (5);	/* up to 18/99 */
    873   1.4  christos 	else
    874   1.4  christos 		return (6);
    875   1.1       cgd }
    876   1.1       cgd 
    877   1.8  dholland /* may kill you; cause may be poison or */
    878   1.8  dholland /* monster like 'A' */
    879   1.4  christos void
    880  1.12    rillig losestr(int num)
    881   1.1       cgd {
    882   1.1       cgd 	u.ustr -= num;
    883   1.4  christos 	while (u.ustr < 3) {
    884   1.1       cgd 		u.ustr++;
    885   1.1       cgd 		u.uhp -= 6;
    886   1.1       cgd 		u.uhpmax -= 6;
    887   1.1       cgd 	}
    888   1.1       cgd 	flags.botl = 1;
    889   1.1       cgd }
    890   1.1       cgd 
    891   1.4  christos void
    892   1.8  dholland losehp(int n, const char *knam)
    893   1.1       cgd {
    894   1.1       cgd 	u.uhp -= n;
    895   1.4  christos 	if (u.uhp > u.uhpmax)
    896   1.1       cgd 		u.uhpmax = u.uhp;	/* perhaps n was negative */
    897   1.1       cgd 	flags.botl = 1;
    898   1.4  christos 	if (u.uhp < 1) {
    899   1.1       cgd 		killer = knam;	/* the thing that killed you */
    900   1.1       cgd 		done("died");
    901   1.1       cgd 	}
    902   1.1       cgd }
    903   1.1       cgd 
    904   1.4  christos void
    905   1.8  dholland losehp_m(int n, struct monst *mtmp)
    906   1.1       cgd {
    907   1.1       cgd 	u.uhp -= n;
    908   1.1       cgd 	flags.botl = 1;
    909   1.4  christos 	if (u.uhp < 1)
    910   1.1       cgd 		done_in_by(mtmp);
    911   1.1       cgd }
    912   1.1       cgd 
    913   1.4  christos void
    914   1.8  dholland losexp(void)
    915   1.4  christos {				/* hit by V or W */
    916   1.4  christos 	int num;
    917   1.1       cgd 
    918   1.4  christos 	if (u.ulevel > 1)
    919   1.1       cgd 		pline("Goodbye level %u.", u.ulevel--);
    920   1.1       cgd 	else
    921   1.1       cgd 		u.uhp = -1;
    922   1.1       cgd 	num = rnd(10);
    923   1.1       cgd 	u.uhp -= num;
    924   1.1       cgd 	u.uhpmax -= num;
    925   1.1       cgd 	u.uexp = newuexp();
    926   1.1       cgd 	flags.botl = 1;
    927   1.1       cgd }
    928   1.1       cgd 
    929   1.4  christos int
    930   1.8  dholland inv_weight(void)
    931   1.4  christos {
    932   1.4  christos 	struct obj *otmp = invent;
    933   1.4  christos 	int    wt = (u.ugold + 500) / 1000;
    934   1.4  christos 	int    carrcap;
    935   1.4  christos 	if (Levitation)		/* pugh@cornell */
    936   1.1       cgd 		carrcap = MAX_CARR_CAP;
    937   1.1       cgd 	else {
    938   1.4  christos 		carrcap = 5 * (((u.ustr > 18) ? 20 : u.ustr) + u.ulevel);
    939   1.4  christos 		if (carrcap > MAX_CARR_CAP)
    940   1.4  christos 			carrcap = MAX_CARR_CAP;
    941   1.4  christos 		if (Wounded_legs & LEFT_SIDE)
    942   1.4  christos 			carrcap -= 10;
    943   1.4  christos 		if (Wounded_legs & RIGHT_SIDE)
    944   1.4  christos 			carrcap -= 10;
    945   1.1       cgd 	}
    946   1.4  christos 	while (otmp) {
    947   1.1       cgd 		wt += otmp->owt;
    948   1.1       cgd 		otmp = otmp->nobj;
    949   1.1       cgd 	}
    950   1.4  christos 	return (wt - carrcap);
    951   1.1       cgd }
    952   1.1       cgd 
    953   1.9  dholland static int
    954   1.8  dholland inv_cnt(void)
    955   1.4  christos {
    956   1.4  christos 	struct obj *otmp = invent;
    957   1.4  christos 	int    ct = 0;
    958   1.4  christos 	while (otmp) {
    959   1.1       cgd 		ct++;
    960   1.1       cgd 		otmp = otmp->nobj;
    961   1.1       cgd 	}
    962   1.4  christos 	return (ct);
    963   1.1       cgd }
    964   1.1       cgd 
    965   1.1       cgd long
    966   1.8  dholland newuexp(void)
    967   1.1       cgd {
    968   1.4  christos 	return (10 * (1L << (u.ulevel - 1)));
    969   1.1       cgd }
    970