pc-hack

PC HACK 3.61 source code (archival)
git clone http://frotz.net/git/pc-hack.git
Log | Files | Refs

hack.c (19007B)


      1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
      2 /* hack.c - version 1.0.3 */
      3 
      4 #include <stdio.h>
      5 #include "hack.h"
      6 
      7 extern char news0();
      8 extern char *nomovemsg;
      9 extern char *exclam();
     10 extern struct obj *addinv();
     11 extern boolean hmon();
     12 
     13 /* called on movement:
     14 	1. when throwing ball+chain far away
     15 	2. when teleporting
     16 	3. when walking out of a lit room
     17  */
     18 unsee() {
     19 	register x,y;
     20 	register struct rm *lev;
     21 
     22 /*
     23 	if(u.udispl){
     24 		u.udispl = 0;
     25 		newsym(u.udisx, u.udisy);
     26 	}
     27 */
     28 	if(seehx){
     29 		seehx = 0;
     30 	} else
     31 	for(x = u.ux-1; x < u.ux+2; x++)
     32 	  for(y = u.uy-1; y < u.uy+2; y++) {
     33 		if(!isok(x, y)) continue;
     34 		lev = &levl[x][y];
     35 #ifdef DGK
     36 		if(!lev->lit && lev->scrsym == symbol.room) {
     37 #else
     38 		if(!lev->lit && lev->scrsym == '.') {
     39 #endif
     40 			lev->scrsym =' ';
     41 			lev->new = 1;
     42 			on_scr(x,y);
     43 		}
     44 	}
     45 }
     46 
     47 /* called:
     48 	in eat.c: seeoff(0) - blind after eating rotten food
     49 	in mon.c: seeoff(0) - blinded by a yellow light
     50 	in mon.c: seeoff(1) - swallowed
     51 	in do.c:  seeoff(0) - blind after drinking potion
     52 	in do.c:  seeoff(1) - go up or down the stairs
     53 	in trap.c:seeoff(1) - fall through trapdoor
     54  */
     55 seeoff(mode)	/* 1 to redo @, 0 to leave them */
     56 {	/* 1 means misc movement, 0 means blindness */
     57 	register x,y;
     58 	register struct rm *lev;
     59 
     60 	if(u.udispl && mode){
     61 		u.udispl = 0;
     62 		levl[u.udisx][u.udisy].scrsym = news0(u.udisx,u.udisy);
     63 	}
     64 	if(seehx) {
     65 		seehx = 0;
     66 	} else
     67 	if(!mode) {
     68 		for(x = u.ux-1; x < u.ux+2; x++)
     69 			for(y = u.uy-1; y < u.uy+2; y++) {
     70 				if(!isok(x, y)) continue;
     71 				lev = &levl[x][y];
     72 #ifdef DGK
     73 				if(!lev->lit && lev->scrsym == symbol.room)
     74 #else
     75 				if(!lev->lit && lev->scrsym == '.')
     76 #endif
     77 					lev->seen = 0;
     78 			}
     79 	}
     80 }
     81 
     82 static
     83 moverock() {
     84 	register xchar rx, ry;
     85 	register struct obj *otmp;
     86 	register struct trap *ttmp;
     87 
     88 	while(otmp = sobj_at(ENORMOUS_ROCK, u.ux+u.dx, u.uy+u.dy)) {
     89 		rx = u.ux+2*u.dx;
     90 		ry = u.uy+2*u.dy;
     91 		nomul(0);
     92 		if(isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
     93 		    (levl[rx][ry].typ != DOOR || !(u.dx && u.dy)) &&
     94 		    !sobj_at(ENORMOUS_ROCK, rx, ry)) {
     95 			if(m_at(rx,ry)) {
     96 			    pline("You hear a monster behind the rock.");
     97 			    pline("Perhaps that's why you cannot move it.");
     98 			    goto cannot_push;
     99 			}
    100 			if(ttmp = t_at(rx,ry))
    101 			    switch(ttmp->ttyp) {
    102 			    case PIT:
    103 				pline("You push the rock into a pit!");
    104 				deltrap(ttmp);
    105 				delobj(otmp);
    106 				pline("It completely fills the pit!");
    107 				continue;
    108 			    case TELEP_TRAP:
    109 				pline("You push the rock and suddenly it disappears!");
    110 				delobj(otmp);
    111 				continue;
    112 			    }
    113 			if(levl[rx][ry].typ == POOL) {
    114 				levl[rx][ry].typ = ROOM;
    115 				mnewsym(rx,ry);
    116 				prl(rx,ry);
    117 				pline("You push the rock into the water.");
    118 				pline("Now you can cross the water!");
    119 				delobj(otmp);
    120 				continue;
    121 			}
    122 			otmp->ox = rx;
    123 			otmp->oy = ry;
    124 			/* pobj(otmp); */
    125 			if(cansee(rx,ry)) atl(rx,ry,otmp->olet);
    126 			if(Invisible) newsym(u.ux+u.dx, u.uy+u.dy);
    127 
    128 			{ static long lastmovetime;
    129 			/* note: this var contains garbage initially and
    130 			   after a restore */
    131 			if(moves > lastmovetime+2 || moves < lastmovetime)
    132 			pline("With great effort you move the enormous rock.");
    133 			lastmovetime = moves;
    134 			}
    135 		} else {
    136 		    pline("You try to move the enormous rock, but in vain.");
    137 	    cannot_push:
    138 		    if((!invent || inv_weight()+90 <= 0) &&
    139 			(!u.dx || !u.dy || (IS_ROCK(levl[u.ux][u.uy+u.dy].typ)
    140 					&& IS_ROCK(levl[u.ux+u.dx][u.uy].typ)))){
    141 			pline("However, you can squeeze yourself into a small opening.");
    142 			break;
    143 		    } else
    144 			return (-1);
    145 		}
    146 	}
    147 	return (0);
    148 }
    149 
    150 domove()
    151 {
    152 	register struct monst *mtmp;
    153 	register struct rm *tmpr,*ust;
    154 	struct trap *trap;
    155 	register struct obj *otmp;
    156 
    157 	u_wipe_engr(rnd(5));
    158 
    159 	if(inv_weight() > 0){
    160 		pline("You collapse under your load.");
    161 		nomul(0);
    162 		return;
    163 	}
    164 	if(u.uswallow) {
    165 		u.dx = u.dy = 0;
    166 		u.ux = u.ustuck->mx;
    167 		u.uy = u.ustuck->my;
    168 	} else {
    169 		if(Confusion) {
    170 			do {
    171 				confdir();
    172 			} while(!isok(u.ux+u.dx, u.uy+u.dy) ||
    173 			    IS_ROCK(levl[u.ux+u.dx][u.uy+u.dy].typ));
    174 		}
    175 		if(!isok(u.ux+u.dx, u.uy+u.dy)){
    176 			nomul(0);
    177 			return;
    178 		}
    179 	}
    180 
    181 	ust = &levl[u.ux][u.uy];
    182 	u.ux0 = u.ux;
    183 	u.uy0 = u.uy;
    184 	if(!u.uswallow && (trap = t_at(u.ux+u.dx, u.uy+u.dy)) && trap->tseen)
    185 		nomul(0);
    186 	if(u.ustuck && !u.uswallow && (u.ux+u.dx != u.ustuck->mx ||
    187 		u.uy+u.dy != u.ustuck->my)) {
    188 		if(dist(u.ustuck->mx, u.ustuck->my) > 2){
    189 			/* perhaps it fled (or was teleported or ... ) */
    190 			u.ustuck = 0;
    191 		} else {
    192 			if(Blind) pline("You cannot escape from it!");
    193 			else pline("You cannot escape from %s!",
    194 				monnam(u.ustuck));
    195 			nomul(0);
    196 			return;
    197 		}
    198 	}
    199 	if(u.uswallow || (mtmp = m_at(u.ux+u.dx,u.uy+u.dy))) {
    200 	/* attack monster */
    201 
    202 #ifdef DGK
    203 		/* Don't attack if you're running */
    204 		if (flags.run && !mtmp->mimic
    205 		&& (Blind ? Telepat : (!mtmp->minvis || See_invisible))) {
    206 			nomul(0);
    207 			flags.move = 0;
    208 			return;
    209 		}
    210 #endif
    211 		nomul(0);
    212 		gethungry();
    213 		if(multi < 0) return;	/* we just fainted */
    214 
    215 		/* try to attack; note that it might evade */
    216 		if(attack(u.uswallow ? u.ustuck : mtmp))
    217 			return;
    218 	}
    219 	/* not attacking an animal, so we try to move */
    220 	if(u.utrap) {
    221 		if(u.utraptype == TT_PIT) {
    222 			pline("You are still in a pit.");
    223 			u.utrap--;
    224 		} else {
    225 			pline("You are caught in a beartrap.");
    226 			if((u.dx && u.dy) || !rn2(5)) u.utrap--;
    227 		}
    228 		return;
    229 	}
    230 	tmpr = &levl[u.ux+u.dx][u.uy+u.dy];
    231 	if(IS_ROCK(tmpr->typ) ||
    232 	   (u.dx && u.dy && (tmpr->typ == DOOR || ust->typ == DOOR))){
    233 		flags.move = 0;
    234 		nomul(0);
    235 		return;
    236 	}
    237 	if (moverock() < 0) return;
    238 	if(u.dx && u.dy && IS_ROCK(levl[u.ux][u.uy+u.dy].typ) &&
    239 		IS_ROCK(levl[u.ux+u.dx][u.uy].typ) &&
    240 		invent && inv_weight()+40 > 0) {
    241 		pline("You are carrying too much to get through.");
    242 		nomul(0);
    243 		return;
    244 	}
    245 	if(Punished &&
    246 	   DIST(u.ux+u.dx, u.uy+u.dy, uchain->ox, uchain->oy) > 2){
    247 		if(carried(uball)) {
    248 			movobj(uchain, u.ux, u.uy);
    249 			goto nodrag;
    250 		}
    251 
    252 		if(DIST(u.ux+u.dx, u.uy+u.dy, uball->ox, uball->oy) < 3){
    253 			/* leave ball, move chain under/over ball */
    254 			movobj(uchain, uball->ox, uball->oy);
    255 			goto nodrag;
    256 		}
    257 
    258 		if(inv_weight() + (int) uball->owt/2 > 0) {
    259 			pline("You cannot %sdrag the heavy iron ball.",
    260 			invent ? "carry all that and also " : "");
    261 			nomul(0);
    262 			return;
    263 		}
    264 
    265 		movobj(uball, uchain->ox, uchain->oy);
    266 		unpobj(uball);		/* BAH %% */
    267 		uchain->ox = u.ux;
    268 		uchain->oy = u.uy;
    269 		nomul(-2);
    270 		nomovemsg = "";
    271 	nodrag:	;
    272 	}
    273 	u.ux += u.dx;
    274 	u.uy += u.dy;
    275 	if(flags.run) {
    276 		if(tmpr->typ == DOOR ||
    277 		(xupstair == u.ux && yupstair == u.uy) ||
    278 		(xdnstair == u.ux && ydnstair == u.uy))
    279 			nomul(0);
    280 	}
    281 
    282 	if(tmpr->typ == POOL && !Levitation)
    283 		drown();	/* not necessarily fatal */
    284 
    285 /*
    286 	if(u.udispl) {
    287 		u.udispl = 0;
    288 		newsym(u.ux0,u.uy0);
    289 	}
    290 */
    291 	if(!Blind) {
    292 		if(ust->lit) {
    293 			if(tmpr->lit) {
    294 				if(tmpr->typ == DOOR)
    295 					prl1(u.ux+u.dx,u.uy+u.dy);
    296 				else if(ust->typ == DOOR)
    297 					nose1(u.ux0-u.dx,u.uy0-u.dy);
    298 			} else {
    299 				unsee();
    300 				prl1(u.ux+u.dx,u.uy+u.dy);
    301 			}
    302 		} else {
    303 			if(tmpr->lit) setsee();
    304 			else {
    305 				prl1(u.ux+u.dx,u.uy+u.dy);
    306 				if(tmpr->typ == DOOR) {
    307 					if(u.dy) {
    308 						prl(u.ux-1,u.uy);
    309 						prl(u.ux+1,u.uy);
    310 					} else {
    311 						prl(u.ux,u.uy-1);
    312 						prl(u.ux,u.uy+1);
    313 					}
    314 				}
    315 			}
    316 			nose1(u.ux0-u.dx,u.uy0-u.dy);
    317 		}
    318 	} else {
    319 		pru();
    320 	}
    321 	if(!flags.nopick) pickup(1);
    322 	if(trap) dotrap(trap);		/* fall into pit, arrow trap, etc. */
    323 	(void) inshop();
    324 	if(!Blind) read_engr_at(u.ux,u.uy);
    325 }
    326 
    327 movobj(obj, ox, oy)
    328 register struct obj *obj;
    329 register int ox, oy;
    330 {
    331 	/* Some dirty programming to get display right */
    332 	freeobj(obj);
    333 	unpobj(obj);
    334 	obj->nobj = fobj;
    335 	fobj = obj;
    336 	obj->ox = ox;
    337 	obj->oy = oy;
    338 }
    339 
    340 dopickup(){
    341 	if(!g_at(u.ux,u.uy) && !o_at(u.ux,u.uy)) {
    342 		pline("There is nothing here to pick up.");
    343 		return(0);
    344 	}
    345 	if(Levitation) {
    346 		pline("You cannot reach the floor.");
    347 		return(1);
    348 	}
    349 	pickup(0);
    350 	return(1);
    351 }
    352 
    353 pickup(all)
    354 {
    355 	register struct gold *gold;
    356 	register struct obj *obj, *obj2;
    357 	register int wt;
    358 
    359 	if(Levitation) return;
    360 #ifdef DGK
    361 	if (all && !flags.pickup) {
    362 		int ct = 0;
    363 
    364 		for (obj = fobj; obj; obj = obj->nobj)
    365 			if (obj->ox == u.ux && obj->oy == u.uy)
    366 				if (!Punished || obj != uchain)
    367 					ct++;
    368 		/* If gold is the only thing here, pick it up.
    369 		 */
    370 		if (!ct && g_at(u.ux, u.uy)) {
    371 			if (flags.run) nomul(0);
    372 			while (gold = g_at(u.ux,u.uy)) {
    373 				pline("%ld gold piece%s.", gold->amount,
    374 					plur(gold->amount));
    375 				u.ugold += gold->amount;
    376 				flags.botl = 1;
    377 				freegold(gold);
    378 			}
    379 			if (Invisible) newsym(u.ux,u.uy);
    380 		}
    381 
    382 		/* If there are objects here, take a look.
    383 		 */
    384 		if (ct) {
    385 			if (flags.run)
    386 				nomul(0);
    387 			nscr();
    388 			if (ct < 5)
    389 				dolook();
    390 			else
    391 				pline("There are several objects here.");
    392 		}
    393 		return;
    394 	}
    395 #endif
    396 	while(gold = g_at(u.ux,u.uy)) {
    397 		pline("%ld gold piece%s.", gold->amount, plur(gold->amount));
    398 		u.ugold += gold->amount;
    399 		flags.botl = 1;
    400 		freegold(gold);
    401 		if(flags.run) nomul(0);
    402 		if(Invisible) newsym(u.ux,u.uy);
    403 	}
    404 	/* check for more than one object */
    405 	if(!all) {
    406 		register int ct = 0;
    407 
    408 		for(obj = fobj; obj; obj = obj->nobj)
    409 			if(obj->ox == u.ux && obj->oy == u.uy)
    410 				if(!Punished || obj != uchain)
    411 					ct++;
    412 		if(ct < 2)
    413 			all++;
    414 		else
    415 			pline("There are several objects here.");
    416 	}
    417 
    418 	for(obj = fobj; obj; obj = obj2) {
    419 	    obj2 = obj->nobj;	/* perhaps obj will be picked up */
    420 	    if(obj->ox == u.ux && obj->oy == u.uy) {
    421 		if(flags.run) nomul(0);
    422 
    423 		/* do not pick up uchain */
    424 		if(Punished && obj == uchain)
    425 			continue;
    426 
    427 		if(!all) {
    428 			char c;
    429 
    430 			pline("Pick up %s ? [ynaq]", doname(obj));
    431 			while(!index("ynaq ", (c = readchar())))
    432 				bell();
    433 			if(c == 'q') return;
    434 			if(c == 'n') continue;
    435 			if(c == 'a') all = 1;
    436 		}
    437 
    438 		if(obj->otyp == DEAD_COCKATRICE && !uarmg){
    439 		    pline("Touching the dead cockatrice is a fatal mistake.");
    440 		    pline("You turn to stone.");
    441 		    killer = "cockatrice cadaver";
    442 		    done("died");
    443 		}
    444 
    445 		if(obj->otyp == SCR_SCARE_MONSTER){
    446 		  if(!obj->spe) obj->spe = 1;
    447 		  else {
    448 		    /* Note: perhaps the 1st pickup failed: you cannot
    449 			carry anymore, and so we never dropped it -
    450 			let's assume that treading on it twice also
    451 			destroys the scroll */
    452 		    pline("The scroll turns to dust as you pick it up.");
    453 		    delobj(obj);
    454 		    continue;
    455 		  }
    456 		}
    457 
    458 		wt = inv_weight() + obj->owt;
    459 		if(wt > 0) {
    460 			if(obj->quan > 1) {
    461 				/* see how many we can lift */
    462 				extern struct obj *splitobj();
    463 				int savequan = obj->quan;
    464 				int iw = inv_weight();
    465 				int qq;
    466 				for(qq = 1; qq < savequan; qq++){
    467 					obj->quan = qq;
    468 					if(iw + weight(obj) > 0)
    469 						break;
    470 				}
    471 				obj->quan = savequan;
    472 				qq--;
    473 				/* we can carry qq of them */
    474 				if(!qq) goto too_heavy;
    475 			pline("You can only carry %s of the %s lying here.",
    476 					(qq == 1) ? "one" : "some",
    477 					doname(obj));
    478 				(void) splitobj(obj, qq);
    479 				/* note: obj2 is set already, so we'll never
    480 				 * encounter the other half; if it should be
    481 				 * otherwise then write
    482 				 *	obj2 = splitobj(obj,qq);
    483 				 */
    484 				goto lift_some;
    485 			}
    486 		too_heavy:
    487 			pline("There %s %s here, but %s.",
    488 				(obj->quan == 1) ? "is" : "are",
    489 				doname(obj),
    490 				!invent ? "it is too heavy for you to lift"
    491 					: "you cannot carry anymore");
    492 			break;
    493 		}
    494 	lift_some:
    495 		if(inv_cnt() >= 52) {
    496 		    pline("Your knapsack cannot accomodate anymore items.");
    497 		    break;
    498 		}
    499 		if(wt > -5) pline("You have a little trouble lifting");
    500 		freeobj(obj);
    501 		if(Invisible) newsym(u.ux,u.uy);
    502 		addtobill(obj);       /* sets obj->unpaid if necessary */
    503 		{ int pickquan = obj->quan;
    504 		  int mergquan;
    505 		if(!Blind) obj->dknown = 1;	/* this is done by prinv(),
    506 				 but addinv() needs it already for merging */
    507 		obj = addinv(obj);    /* might merge it with other objects */
    508 		  mergquan = obj->quan;
    509 		  obj->quan = pickquan;	/* to fool prinv() */
    510 		prinv(obj);
    511 		  obj->quan = mergquan;
    512 		}
    513 	    }
    514 	}
    515 }
    516 
    517 /* stop running if we see something interesting */
    518 /* turn around a corner if that is the only way we can proceed */
    519 /* do not turn left or right twice */
    520 lookaround(){
    521 register x,y,i,x0,y0,m0,i0 = 9;
    522 register int corrct = 0, noturn = 0;
    523 register struct monst *mtmp;
    524 #ifdef lint
    525 	/* suppress "used before set" message */
    526 	x0 = y0 = 0;
    527 #endif /* lint /**/
    528 	if(Blind || flags.run == 0) return;
    529 	if(flags.run == 1 && levl[u.ux][u.uy].typ == ROOM) return;
    530 	for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++){
    531 		if(x == u.ux && y == u.uy) continue;
    532 		if(!levl[x][y].typ) continue;
    533 		if((mtmp = m_at(x,y)) && !mtmp->mimic &&
    534 		    (!mtmp->minvis || See_invisible)){
    535 			if(!mtmp->mtame || (x == u.ux+u.dx && y == u.uy+u.dy))
    536 				goto stop;
    537 		} else mtmp = 0; /* invisible M cannot influence us */
    538 		if(x == u.ux-u.dx && y == u.uy-u.dy) continue;
    539 #ifdef DGK
    540 		{
    541 		register uchar sym = levl[x][y].scrsym;
    542 
    543 		if (sym == symbol.vwall || sym == symbol.hwall
    544 			|| sym == symbol.room || sym == ' ' || IS_CORNER(sym))
    545 			continue;
    546 		else if (sym == symbol.door) {
    547 			if(x != u.ux && y != u.uy) continue;
    548 			if(flags.run != 1) goto stop;
    549 			goto corr;
    550 		} else if (sym == symbol.corr) {
    551 		corr:
    552 			if(flags.run == 1 || flags.run == 3) {
    553 				i = DIST(x,y,u.ux+u.dx,u.uy+u.dy);
    554 				if(i > 2) continue;
    555 				if(corrct == 1 && DIST(x,y,x0,y0) != 1)
    556 					noturn = 1;
    557 				if(i < i0) {
    558 					i0 = i;
    559 					x0 = x;
    560 					y0 = y;
    561 					m0 = mtmp ? 1 : 0;
    562 				}
    563 			}
    564 			corrct++;
    565 			continue;
    566 		} else if (sym == '^') {
    567 			if(flags.run == 1) goto corr;	/* if you must */
    568  			if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
    569 			continue;
    570 		} else {		/* e.g. objects or trap or stairs */
    571 			if(flags.run == 1) goto corr;
    572 			if(mtmp) continue;		/* d */
    573 		}
    574 		stop:
    575 			nomul(0);
    576 			return;
    577 		}
    578 #else
    579 		switch(levl[x][y].scrsym){
    580 		case '|':
    581 		case '-':
    582 		case '.':
    583 		case ' ':
    584 			break;
    585 		case '+':
    586 			if(x != u.ux && y != u.uy) break;
    587 			if(flags.run != 1) goto stop;
    588 			/* fall into next case */
    589 		case CORR_SYM:
    590 		corr:
    591 			if(flags.run == 1 || flags.run == 3) {
    592 				i = DIST(x,y,u.ux+u.dx,u.uy+u.dy);
    593 				if(i > 2) break;
    594 				if(corrct == 1 && DIST(x,y,x0,y0) != 1)
    595 					noturn = 1;
    596 				if(i < i0) {
    597 					i0 = i;
    598 					x0 = x;
    599 					y0 = y;
    600 					m0 = mtmp ? 1 : 0;
    601 				}
    602 			}
    603 			corrct++;
    604 			break;
    605 		case '^':
    606 			if(flags.run == 1) goto corr;	/* if you must */
    607  			if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
    608 			break;
    609 		default:	/* e.g. objects or trap or stairs */
    610 			if(flags.run == 1) goto corr;
    611 			if(mtmp) break;		/* d */
    612 		stop:
    613 			nomul(0);
    614 			return;
    615 		}
    616 #endif
    617 	}
    618 	if(corrct > 1 && flags.run == 2) goto stop;
    619 	if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&
    620 		(corrct == 1 || (corrct == 2 && i0 == 1))) {
    621 		/* make sure that we do not turn too far */
    622 		if(i0 == 2) {
    623 		    if(u.dx == y0-u.uy && u.dy == u.ux-x0)
    624 			i = 2;		/* straight turn right */
    625 		    else
    626 			i = -2;		/* straight turn left */
    627 		} else if(u.dx && u.dy) {
    628 		    if((u.dx == u.dy && y0 == u.uy) ||
    629 			(u.dx != u.dy && y0 != u.uy))
    630 			i = -1;		/* half turn left */
    631 		    else
    632 			i = 1;		/* half turn right */
    633 		} else {
    634 		    if((x0-u.ux == y0-u.uy && !u.dy) ||
    635 			(x0-u.ux != y0-u.uy && u.dy))
    636 			i = 1;		/* half turn right */
    637 		    else
    638 			i = -1;		/* half turn left */
    639 		}
    640 		i += u.last_str_turn;
    641 		if(i <= 2 && i >= -2) {
    642 			u.last_str_turn = i;
    643 			u.dx = x0-u.ux, u.dy = y0-u.uy;
    644 		}
    645 	}
    646 }
    647 
    648 /* something like lookaround, but we are not running */
    649 /* react only to monsters that might hit us */
    650 monster_nearby() {
    651 register int x,y;
    652 register struct monst *mtmp;
    653 	if(!Blind)
    654 	for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++){
    655 		if(x == u.ux && y == u.uy) continue;
    656 		if((mtmp = m_at(x,y)) && !mtmp->mimic && !mtmp->mtame &&
    657 			!mtmp->mpeaceful && !index("Ea", mtmp->data->mlet) &&
    658 			!mtmp->mfroz && !mtmp->msleep &&  /* aplvax!jcn */
    659 			(!mtmp->minvis || See_invisible))
    660 			return(1);
    661 	}
    662 	return(0);
    663 }
    664 
    665 cansee(x,y) xchar x,y; {
    666 	if(Blind || u.uswallow) return(0);
    667 	if(dist(x,y) < 3) return(1);
    668 	if(levl[x][y].lit && seelx <= x && x <= seehx && seely <= y &&
    669 		y <= seehy) return(1);
    670 	return(0);
    671 }
    672 
    673 sgn(a) register int a; {
    674 	return((a > 0) ? 1 : (a == 0) ? 0 : -1);
    675 }
    676 
    677 setsee()
    678 {
    679 	register x,y;
    680 
    681 	if(Blind) {
    682 		pru();
    683 		return;
    684 	}
    685 	if(!levl[u.ux][u.uy].lit) {
    686 		seelx = u.ux-1;
    687 		seehx = u.ux+1;
    688 		seely = u.uy-1;
    689 		seehy = u.uy+1;
    690 	} else {
    691 		for(seelx = u.ux; levl[seelx-1][u.uy].lit; seelx--);
    692 		for(seehx = u.ux; levl[seehx+1][u.uy].lit; seehx++);
    693 		for(seely = u.uy; levl[u.ux][seely-1].lit; seely--);
    694 		for(seehy = u.uy; levl[u.ux][seehy+1].lit; seehy++);
    695 	}
    696 	for(y = seely; y <= seehy; y++)
    697 		for(x = seelx; x <= seehx; x++) {
    698 			prl(x,y);
    699 	}
    700 	if(!levl[u.ux][u.uy].lit) seehx = 0; /* seems necessary elsewhere */
    701 	else {
    702 	    if(seely == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seely-1);
    703 	    if(seehy == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seehy+1);
    704 	    if(seelx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seelx-1,y);
    705 	    if(seehx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seehx+1,y);
    706 	}
    707 }
    708 
    709 	
    710 nomul(nval)
    711 register nval;
    712 {
    713 #ifdef DGK
    714 	if(multi < nval) return;	/* This is a bug fix by ab@unido */
    715 #else
    716 	if(multi < 0) return;
    717 #endif
    718 	multi = nval;
    719 	flags.mv = flags.run = 0;
    720 }
    721 
    722 abon()
    723 {
    724 	if(u.ustr == 3) return(-3);
    725 	else if(u.ustr < 6) return(-2);
    726 	else if(u.ustr < 8) return(-1);
    727 	else if(u.ustr < 17) return(0);
    728 	else if(u.ustr < 69) return(1);	/* up to 18/50 */
    729 	else if(u.ustr < 118) return(2);
    730 	else return(3);
    731 }
    732 
    733 dbon()
    734 {
    735 	if(u.ustr < 6) return(-1);
    736 	else if(u.ustr < 16) return(0);
    737 	else if(u.ustr < 18) return(1);
    738 	else if(u.ustr == 18) return(2);	/* up to 18 */
    739 	else if(u.ustr < 94) return(3);		/* up to 18/75 */
    740 	else if(u.ustr < 109) return(4);	/* up to 18/90 */
    741 	else if(u.ustr < 118) return(5);	/* up to 18/99 */
    742 	else return(6);
    743 }
    744 
    745 losestr(num)	/* may kill you; cause may be poison or monster like 'A' */
    746 register num;
    747 {
    748 	u.ustr -= num;
    749 	while(u.ustr < 3) {
    750 		u.ustr++;
    751 		u.uhp -= 6;
    752 		u.uhpmax -= 6;
    753 	}
    754 	flags.botl = 1;
    755 }
    756 
    757 losehp(n,knam)
    758 register n;
    759 register char *knam;
    760 {
    761 	u.uhp -= n;
    762 	if(u.uhp > u.uhpmax)
    763 		u.uhpmax = u.uhp;	/* perhaps n was negative */
    764 	flags.botl = 1;
    765 	if(u.uhp < 1) {
    766 		killer = knam;	/* the thing that killed you */
    767 		done("died");
    768 	}
    769 }
    770 
    771 losehp_m(n,mtmp)
    772 register n;
    773 register struct monst *mtmp;
    774 {
    775 	u.uhp -= n;
    776 	flags.botl = 1;
    777 	if(u.uhp < 1)
    778 		done_in_by(mtmp);
    779 }
    780 
    781 losexp()	/* hit by V or W */
    782 {
    783 	register num;
    784 	extern long newuexp();
    785 
    786 	if(u.ulevel > 1)
    787 		pline("Goodbye level %u.", u.ulevel--);
    788 	else
    789 		u.uhp = -1;
    790 	num = rnd(10);
    791 	u.uhp -= num;
    792 	u.uhpmax -= num;
    793 	u.uexp = newuexp();
    794 	flags.botl = 1;
    795 }
    796 
    797 inv_weight(){
    798 register struct obj *otmp = invent;
    799 register int wt = (u.ugold + 500)/1000;
    800 register int carrcap;
    801 	if(Levitation)			/* pugh@cornell */
    802 		carrcap = MAX_CARR_CAP;
    803 	else {
    804 		carrcap = 5*(((u.ustr > 18) ? 20 : u.ustr) + u.ulevel);
    805 		if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
    806 		if(Wounded_legs & LEFT_SIDE) carrcap -= 10;
    807 		if(Wounded_legs & RIGHT_SIDE) carrcap -= 10;
    808 	}
    809 	while(otmp){
    810 		wt += otmp->owt;
    811 		otmp = otmp->nobj;
    812 	}
    813 	return(wt - carrcap);
    814 }
    815 
    816 inv_cnt(){
    817 register struct obj *otmp = invent;
    818 register int ct = 0;
    819 	while(otmp){
    820 		ct++;
    821 		otmp = otmp->nobj;
    822 	}
    823 	return(ct);
    824 }
    825 
    826 long
    827 newuexp()
    828 {
    829 	return(10*(1L << (u.ulevel-1)));
    830 }