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