# Source:Hack 1.0/hack.c
Below is the full text to hack.c from the source code of Hack 1.0. To link to a particular line, write [[Hack 1.0/hack.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code

Screenshots and source code from Hack are used under the CWI license.

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 &lt; u.ux+2; x++)
36.   	  for(y = u.uy-1; y &lt; u.uy+2; y++) {
37.   		lev = &amp;levl[x][y];
38.   		if(!lev-&gt;lit &amp;&amp; lev-&gt;scrsym == '.') {
39.   			lev-&gt;scrsym =' ';
40.   			lev-&gt;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 &amp;&amp; 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 &lt; u.ux+2; x++)
70.   			for(y = u.uy-1; y &lt; u.uy+2; y++) {
71.   				lev = &amp;levl[x][y];
72.   				if(!lev-&gt;lit &amp;&amp; lev-&gt;scrsym == '.')
73.   					lev-&gt;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 &lt;= 8; i++){
97.   		if(flags.run &amp; 1) ui++; else ui += 7;
98.   		ui&nbsp;%= 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 &lt;= 8; i++){
108.  		if(flags.run &amp; 1) ui += 7; else ui++;
109.  		ui&nbsp;%= 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) &amp;&amp; (levl[x][y].typ == ROOM ||
125.  				(levl[x][y].typ &gt;= LDOOR &amp;&amp; flags.run &gt;= 6)));
126.  }
127.  #endif QUEST
128.  
129.  isok(x,y) register x,y; {
130.  	return(x &gt;= 0 &amp;&amp; x &lt;= COLNO-1 &amp;&amp; y &gt;= 0 &amp;&amp; y &lt;= 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() &gt; 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 = &amp;levl[u.ux+u.dx][u.uy+u.dy];
152.  		} while((!u.dx &amp;&amp; !u.dy) ||
153.  			!isok(u.ux+u.dx, u.uy+u.dy) || tmpr-&gt;typ &lt; DOOR);
154.  	} else tmpr = &amp;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 = &amp;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-&gt;gflag &amp; SEEN) nomul(0);
166.  	}
167.  	if(u.ustuck &amp;&amp; !u.uswallow &amp;&amp; (u.ux+u.dx&nbsp;!= u.ustuck-&gt;mx ||
168.  		u.uy+u.dy&nbsp;!= u.ustuck-&gt;my)) {
169.  		if(dist(u.ustuck-&gt;mx, u.ustuck-&gt;my) &gt; 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 &lt; 0) return;	/* we just fainted */
189.  		if(u.uswallow) mtmp = u.ustuck;
190.  		mdat = mtmp-&gt;data;
191.  		if(mdat-&gt;mlet == 'L' &amp;&amp; !mtmp-&gt;mfroz &amp;&amp; !mtmp-&gt;msleep &amp;&amp;
192.  		   !mtmp-&gt;mconf &amp;&amp; mtmp-&gt;mcansee &amp;&amp; !rn2(7) &amp;&amp;
193.  		   (m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */
194.  			mtmp-&gt;mx&nbsp;!= u.ux+u.dx || mtmp-&gt;my&nbsp;!= u.uy+u.dy))
195.  			goto nomon;
196.  		if(mtmp-&gt;mimic){
197.  			if(!u.ustuck &amp;&amp; !mtmp-&gt;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-&gt;mimic */
209.  			return;
210.  		}
211.  		wakeup(mtmp);	/* clears mtmp-&gt;mimic */
212.  		if(mtmp-&gt;mhide &amp;&amp; mtmp-&gt;mundetected){
213.  			register struct obj *obj;
214.  			mtmp-&gt;mundetected = 0;
215.  			if((obj = o_at(mtmp-&gt;mx,mtmp-&gt;my)) &amp;&amp; !Blind)
216.  				pline("Wait! There's a %s hiding under %s!",
217.  					mdat-&gt;mname, doname(obj));
218.  			return;
219.  		}
220.  		tmp = u.uluck + u.ulevel + mdat-&gt;ac + abon();
221.  		if(uwep) {
222.  			if(uwep-&gt;olet == WEAPON_SYM)
223.  				tmp += uwep-&gt;spe;
224.  			if(uwep-&gt;otyp == TWO_HANDED_SWORD) tmp -= 1;
225.  			else if(uwep-&gt;otyp == DAGGER) tmp += 2;
226.  			else if(uwep-&gt;otyp == CRYSKNIFE) tmp += 3;
227.  			else if(uwep-&gt;otyp == SPEAR &amp;&amp;
228.  				index("XDne", mdat-&gt;mlet)) tmp += 2;
229.  		}
230.  		if(mtmp-&gt;msleep) {
231.  			mtmp-&gt;msleep = 0;
232.  			tmp += 2;
233.  		}
234.  		if(mtmp-&gt;mfroz) {
235.  			tmp += 4;
236.  			if(!rn2(10)) mtmp-&gt;mfroz = 0;
237.  		}
238.  		if(mtmp-&gt;mflee) tmp += 2;
239.  		if(u.utrap) tmp -= 3;
240.  		if(tmp &lt;= rnd(20) &amp;&amp; !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) &amp;&amp; mtmp-&gt;mhp &lt; mtmp-&gt;orig_hp/2) {
249.  					mtmp-&gt;mflee = 1;
250.  					if(u.ustuck == mtmp &amp;&amp; !u.uswallow)
251.  						u.ustuck = 0;
252.  				}
253.  #ifndef NOWORM
254.  				if(mtmp-&gt;wormno)
255.  					cutworm(mtmp, u.ux+u.dx, u.uy+u.dy,
256.  						uwep&nbsp;? uwep-&gt;otyp&nbsp;: 0);
257.  #endif NOWORM
258.  			}
259.  			if(mdat-&gt;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 &amp;&amp; !Blind &amp;&amp; mdat-&gt;mlet == 'E' &amp;&amp; rn2(3)) {
269.  		    if(mtmp-&gt;mcansee) {
270.  		      pline("You are frozen by the floating eye's gaze!");
271.  		      nomul((u.ulevel &gt; 6 || rn2(4))&nbsp;? rn1(20,-21)&nbsp;: -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 &amp;&amp; u.dy) || !rn2(5)) u.utrap--;
288.  		}
289.  		return;
290.  	}
291.  	if((tmpr-&gt;typ &lt; DOOR) ||
292.  	   (u.dx &amp;&amp; u.dy &amp;&amp; (tmpr-&gt;typ == DOOR || ust-&gt;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) &amp;&amp; (levl[rx][ry].typ &gt; DOOR ||
302.  		    (levl[rx][ry].typ == DOOR &amp;&amp; (!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-&gt;gflag &amp; ~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-&gt;ox = rx;
323.  			otmp-&gt;oy = ry;
324.  			/* pobj(otmp); */
325.  			if(cansee(rx,ry)) atl(rx,ry,otmp-&gt;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 &gt; lastmovetime+2 || moves &lt; 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 &amp;&amp; u.dy &amp;&amp; levl[u.ux][u.uy+u.dy].typ &lt; DOOR &amp;&amp;
341.  		levl[u.ux+u.dx][u.uy].typ &lt; DOOR &amp;&amp;
342.  		invent &amp;&amp; inv_weight()+40 &gt; 0) {
343.  		pline("You are carrying too much to get through.");
344.  		nomul(0);
345.  		return;
346.  	}
347.  	if(Punished &amp;&amp;
348.  	   DIST(u.ux+u.dx, u.uy+u.dy, uchain-&gt;ox, uchain-&gt;oy) &gt; 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-&gt;ox, uball-&gt;oy) &lt; 3){
355.  			/* leave ball, move chain under/over ball */
356.  			movobj(uchain, uball-&gt;ox, uball-&gt;oy);
357.  			goto nodrag;
358.  		}
359.  
360.  		if(inv_weight() + (int) uball-&gt;owt/2 &gt; 0) {
361.  			pline("You cannot %sdrag the heavy iron ball.",
362.  			invent&nbsp;? "carry all that and also "&nbsp;: "");
363.  			nomul(0);
364.  			return;
365.  		}
366.  
367.  		movobj(uball, uchain-&gt;ox, uchain-&gt;oy);
368.  		unpobj(uball);		/* BAH&nbsp;%% */
369.  		uchain-&gt;ox = u.ux;
370.  		uchain-&gt;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-&gt;typ == DOOR ||
379.  		(xupstair == u.ux &amp;&amp; yupstair == u.uy) ||
380.  		(xdnstair == u.ux &amp;&amp; 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-&gt;lit) {
394.  			if(tmpr-&gt;lit) {
395.  				if(tmpr-&gt;typ == DOOR) prl1(u.ux+u.dx,u.uy+u.dy);
396.  				else if(ust-&gt;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-&gt;lit) setsee();
403.  			else {
404.  				prl1(u.ux+u.dx,u.uy+u.dy);
405.  				if(tmpr-&gt;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-&gt;nobj = fobj;
435.  	fobj = obj;
436.  	obj-&gt;ox = ox;
437.  	obj-&gt;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-&gt;gflag, plur(gold-&gt;gflag));
447.  		u.ugold += gold-&gt;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-&gt;nobj;	/* perhaps obj will be picked up */
455.  	    if(obj-&gt;ox == u.ux &amp;&amp; obj-&gt;oy == u.uy) {
456.  		if(flags.run) nomul(0);
457.  
458.  #define	DEAD_c	CORPSE+('c'-'a'+'Z'-'@'+1)
459.  		if(obj-&gt;otyp == DEAD_COCKATRICE &amp;&amp; !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-&gt;otyp == SCR_SCARE_MONSTER){
467.  		  if(!obj-&gt;spe) obj-&gt;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 &amp;&amp; obj == uchain)
481.  			continue;
482.  
483.  		wt = inv_weight() + obj-&gt;owt;
484.  		if(wt &gt; 0) {
485.  			if(obj-&gt;quan &gt; 1) {
486.  				/* see how many we can lift */
487.  				extern struct obj *splitobj();
488.  				int savequan = obj-&gt;quan;
489.  				int iw = inv_weight();
490.  				int qq;
491.  				for(qq = 1; qq &lt; savequan; qq++){
492.  					obj-&gt;quan = qq;
493.  					if(iw + weight(obj) &gt; 0)
494.  						break;
495.  				}
496.  				obj-&gt;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)&nbsp;? "one"&nbsp;: "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-&gt;quan == 1)&nbsp;? "is"&nbsp;: "are",
514.  				doname(obj),
515.  				!invent&nbsp;? "it is too heavy for you to lift"
516.  					: "you cannot carry anymore");
517.  			break;
518.  		}
519.  	lift_some:
520.  		if(inv_cnt() &gt;= 52) {
521.  		    pline("Your knapsack cannot accomodate anymore items.");
522.  		    break;
523.  		}
524.  		if(wt &gt; -5) pline("You have a little trouble lifting");
525.  		freeobj(obj);
526.  		if(Invis) newsym(u.ux,u.uy);
527.  		addtobill(obj);       /* sets obj-&gt;unpaid if necessary */
528.  		{ int pickquan = obj-&gt;quan;
529.  		  int mergquan;
530.  		if(!Blind) obj-&gt;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-&gt;quan;
534.  		  obj-&gt;quan = pickquan;	/* to fool prinv() */
535.  		prinv(obj);
536.  		  obj-&gt;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 &amp;&amp; levl[u.ux][u.uy].typ &gt;= ROOM) return;
555.  #ifdef QUEST
556.  	if(u.ux0 == u.ux+u.dx &amp;&amp; u.uy0 == u.uy+u.dy) goto stop;
557.  #endif QUEST
558.  	for(x = u.ux-1; x &lt;= u.ux+1; x++) for(y = u.uy-1; y &lt;= u.uy+1; y++){
559.  		if(x == u.ux &amp;&amp; y == u.uy) continue;
560.  		if(!levl[x][y].typ) continue;
561.  		if((mtmp = m_at(x,y)) &amp;&amp; !mtmp-&gt;mimic &amp;&amp;
562.  		    (!mtmp-&gt;minvis || See_invisible)){
563.  			if(!mtmp-&gt;mtame || (x == u.ux+u.dx &amp;&amp; y == u.uy+u.dy))
564.  				goto stop;
565.  		} else mtmp = 0; /* invisible M cannot influence us */
566.  		if(x == u.ux-u.dx &amp;&amp; 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&nbsp;!= u.ux &amp;&amp; y&nbsp;!= u.uy) break;
575.  			if(flags.run&nbsp;!= 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 &gt; 2) break;
582.  				if(corrct == 1 &amp;&amp; DIST(x,y,x0,y0)&nbsp;!= 1)
583.  					noturn = 1;
584.  				if(i &lt; i0) {
585.  					i0 = i;
586.  					x0 = x;
587.  					y0 = y;
588.  					m0 = mtmp&nbsp;? 1&nbsp;: 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 &amp;&amp; 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 &gt; 0 &amp;&amp; (flags.run == 4 || flags.run == 5)) goto stop;
607.  #endif QUEST
608.  	if(corrct &gt; 1 &amp;&amp; flags.run == 2) goto stop;
609.  	if((flags.run == 1 || flags.run == 3) &amp;&amp; !noturn &amp;&amp; !m0 &amp;&amp; i0 &amp;&amp;
610.  		(corrct == 1 || (corrct == 2 &amp;&amp; i0 == 1))) {
611.  		/* make sure that we do not turn too far */
612.  		if(i0 == 2) {
613.  		    if(u.dx == y0-u.uy &amp;&amp; u.dy == u.ux-x0)
614.  			i = 2;		/* straight turn right */
615.  		    else
616.  			i = -2;		/* straight turn left */
617.  		} else if(u.dx &amp;&amp; u.dy) {
618.  		    if((u.dx == u.dy &amp;&amp; y0 == u.uy) ||
619.  			(u.dx&nbsp;!= u.dy &amp;&amp; y0&nbsp;!= 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 &amp;&amp; !u.dy) ||
625.  			(x0-u.ux&nbsp;!= y0-u.uy &amp;&amp; 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 &lt;= 2 &amp;&amp; i &gt;= -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 &lt; 3) return(1);
645.  	if(d &gt; 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)&nbsp;? ady&nbsp;: adx;
652.  		for(d = 1; d &lt;= dmax; d++)
653.  			if(!rroom(sdx*d,sdy*d))
654.  				return(0);
655.  		return(1);
656.  	} else if(ady &gt; adx){
657.  		for(d = 1; d &lt;= 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 &lt;= 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 &gt;= 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) &lt; 3) return(1);
682.  	if(levl[x][y].lit &amp;&amp; seelx &lt;= x &amp;&amp; x &lt;= seehx &amp;&amp; seely &lt;= y &amp;&amp;
683.  		y &lt;= seehy) return(1);
684.  	return(0);
685.  }
686.  #endif QUEST
687.  
688.  sgn(a) register int a; {
689.  	return((a&gt; 0)&nbsp;? 1&nbsp;: (a == 0)&nbsp;? 0&nbsp;: -1);
690.  }
691.  
692.  pow(num) /* returns 2 to the num */
693.  register unsigned num;
694.  {
695.  	return(1 &lt;&lt; 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 &lt;= u.uy+u.uhorizon; y++)
708.  		for(x = u.ux-u.uhorizon; x &lt;= 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 &lt;= seehy; y++)
736.  		for(x = seelx; x &lt;= 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 &lt;= u.ux+1; x++) prl(x,seely-1);
742.  	    if(seehy == u.uy) for(x = u.ux-1; x &lt;= u.ux+1; x++) prl(x,seehy+1);
743.  	    if(seelx == u.ux) for(y = u.uy-1; y &lt;= u.uy+1; y++) prl(seelx-1,y);
744.  	    if(seehx == u.ux) for(y = u.uy-1; y &lt;= u.uy+1; y++) prl(seehx+1,y);
745.  	}
746.  }
747.  #endif QUEST
748.  
749.  nomul(nval)
750.  register nval;
751.  {
752.  	if(multi &lt; 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 &lt; 6) return(-2);
761.  	else if(u.ustr &lt; 8) return(-1);
762.  	else if(u.ustr &lt; 17) return(0);
763.  	else if(u.ustr &lt; 69) return(1);	/* up to 18/50 */
764.  	else if(u.ustr &lt; 118) return(2);
765.  	else return(3);
766.  }
767.  
768.  dbon()
769.  {
770.  	if(u.ustr &lt; 6) return(-1);
771.  	else if(u.ustr &lt; 16) return(0);
772.  	else if(u.ustr &lt; 18) return(1);
773.  	else if(u.ustr == 18) return(2);	/* up to 18 */
774.  	else if(u.ustr &lt; 94) return(3);	/* up to 18/75 */
775.  	else if(u.ustr &lt; 109) return(4);	/* up to 18/90 */
776.  	else if(u.ustr &lt; 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 &lt; 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 &gt; u.uhpmax)
798.  		u.uhpmax = u.uhp;	/* perhaps n was negative */
799.  	flags.botl = 1;
800.  	if(u.uhp &lt; 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 &lt; 1) done_in_by(mtmp);
811.  }
812.  
813.  losexp()	/* hit by V or W */
814.  {
815.  	register num;
816.  
817.  	if(u.ulevel &gt; 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 &gt; 18)&nbsp;? 20&nbsp;: u.ustr) + u.ulevel);
830.  	if(carrcap &gt; MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
831.  	if(Wounded_legs &amp; LEFT_SIDE) carrcap -= 10;
832.  	if(Wounded_legs &amp; RIGHT_SIDE) carrcap -= 10;
833.  	while(otmp){
834.  		wt += otmp-&gt;owt;
835.  		otmp = otmp-&gt;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-&gt;nobj;
846.  	}
847.  	return(ct);
848.  }

</stdio.h>