Difference between revisions of "Source:Hack 1.0/hack.c"

From NetHackWiki
Jump to navigation Jump to search
(prospective version)
 
(No difference)

Revision as of 17:12, 29 August 2006

Below is the full text to hack.c from Hack 1.0. To link to a particular line, write [[hack.c-1.0#line123]], for example.

Note: for the latest version, see Source code

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