Source:NetHack 3.0.0/hack.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to hack.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/hack.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2.    /* NetHack may be freely redistributed.  See license for details. */
3.    
4.    #include "hack.h"
5.    
6.    #if defined(UNIX) && !defined(LINT)
7.    static	const char	SCCS_Id[] = "@(#)hack.c	3.0\t88/10/25";
8.    #endif
9.    
10.   /* called on movement:
11.   	1. when throwing ball+chain far away
12.   	2. when teleporting
13.   	3. when walking out of a lit room
14.    */
15.   void
16.   unsee() {
17.   	register xchar x,y;
18.   	register struct rm *lev;
19.   
20.   	if(seehx){
21.   		seehx = 0;
22.   	} else
23.   	for(x = u.ux-1; x < u.ux+2; x++)
24.   	    for(y = u.uy-1; y < u.uy+2; y++) {
25.   		if(!isok(x, y)) continue;
26.   		lev = &levl[x][y];
27.   		if(!lev->lit && lev->scrsym == ROOM_SYM) {
28.   			lev->scrsym = STONE_SYM;
29.   			lev->new = 1;
30.   			on_scr(x,y);
31.   		}
32.   	    }
33.   }
34.   
35.   /* called:
36.   	in apply.c:  seeoff(0)	- when taking a picture of yourself
37.   				- when donning a blindfold
38.   	in do.c:     seeoff(0)	- blind after drinking potion
39.   	in do.c:     seeoff(1)	- go up or down the stairs
40.   	in eat.c:    seeoff(0)	- blind after eating rotten food
41.   	in mhitu.c:  seeoff(0)	- blinded by a glowing eye
42.   	in mhitu.c:  seeoff(1)	- swallowed
43.   	in mthrow.c: seeoff(0)	- hit by a cream pie.
44.   	in potion.c: seeoff(0)	- quaffing or sniffing a potion of blindness
45.   	in spell.c:  seeoff(0)	- due to a cursed spellbook
46.   	in trap.c:   seeoff(1)	- fall through trapdoor
47.    */
48.   void
49.   seeoff(mode) {	/* 1 to redo @, 0 to leave them */
50.   		/* 1 means misc movement, 0 means blindness */
51.   	register xchar x,y;
52.   	register struct rm *lev;
53.   
54.   	if(u.udispl && mode){
55.   		u.udispl = 0;
56.   		levl[u.udisx][u.udisy].scrsym = news0(u.udisx,u.udisy);
57.   	}
58.   	if(seehx) {
59.   		seehx = 0;
60.   	} else
61.   	    if(!mode) {
62.   		for(x = u.ux-1; x < u.ux+2; x++)
63.   		    for(y = u.uy-1; y < u.uy+2; y++) {
64.   			if(!isok(x, y)) continue;
65.   			lev = &levl[x][y];
66.   			if(lev->mmask) unpmon(m_at(x,y));
67.   			if(!lev->lit && lev->scrsym == ROOM_SYM) {
68.   			    lev->seen = 0;
69.   			    atl(x, y, (char)STONE_SYM);
70.   			}
71.   		    }
72.   	    }
73.   }
74.   
75.   static int
76.   moverock() {
77.   	register xchar rx, ry;
78.   	register struct obj *otmp;
79.   	register struct trap *ttmp;
80.   	register struct	monst *mtmp;
81.   	xchar oldrx, oldry;
82.   
83.   #ifdef POLYSELF
84.   	if (passes_walls(uasmon)) return 0;
85.   #endif
86.   	while(otmp = sobj_at(BOULDER, u.ux+u.dx, u.uy+u.dy)) {
87.   		rx = u.ux+2*u.dx;
88.   		ry = u.uy+2*u.dy;
89.   		nomul(0);
90.   #ifdef POLYSELF
91.   		if (verysmall(uasmon)) {
92.   		    pline("You're too small to push that boulder.");
93.   		    goto cannot_push;
94.   		}
95.   #endif
96.   		if(isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
97.   		    (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy)) &&
98.   		    !sobj_at(BOULDER, rx, ry)) {
99.   			if(levl[rx][ry].mmask) {
100.  			    mtmp = m_at(rx,ry);
101.  			    if(canseemon(mtmp))
102.  				pline("There's %s on the other side.",
103.  				      mon_nam(mtmp));
104.  			    else
105.  				You("hear a monster behind the boulder.");
106.  			    if(flags.verbose)
107.  				pline("Perhaps that's why you cannot move it.");
108.  			    goto cannot_push;
109.  			}
110.  			if(ttmp = t_at(rx,ry))
111.  			    switch(ttmp->ttyp) {
112.  			    case SPIKED_PIT:
113.  			    case PIT:
114.  				You("push the boulder into a pit!");
115.  				deltrap(ttmp);
116.  				delobj(otmp);
117.  				if(flags.verbose)
118.  				    pline("It completely fills the pit!");
119.  				continue;
120.  			    case TRAPDOOR:
121.  				pline("The boulder falls into and plugs a hole in the ground!");
122.  				deltrap(ttmp);
123.  				delobj(otmp);
124.  				continue;
125.  			    case LEVEL_TELEP:
126.  			    case TELEP_TRAP:
127.  				You("push the boulder and suddenly it disappears!");
128.  				rloco(otmp);
129.  				continue;
130.  			    }
131.  			if(levl[rx][ry].typ == DOOR &&
132.  				(levl[rx][ry].doormask & (D_LOCKED | D_CLOSED)))
133.  				goto nopushmsg;
134.  			if(is_pool(rx,ry)) {
135.  #ifdef STRONGHOLD
136.  				if(levl[rx][ry].typ == DRAWBRIDGE_UP)
137.  				    levl[rx][ry].drawbridgemask |= DB_FLOOR;
138.  				else
139.  #endif
140.  				    levl[rx][ry].typ = ROOM;
141.  				mnewsym(rx,ry);
142.  				if(!Blind) prl(rx,ry);
143.  				You("push the boulder into the water.");
144.  				if(flags.verbose && !Blind)
145.  				    pline("Now you can cross the water!");
146.  				delobj(otmp);
147.  				continue;
148.  			}
149.  			oldrx = otmp->ox;
150.  			oldry = otmp->oy;
151.  			otmp->ox = rx;
152.  			otmp->oy = ry;
153.  			set_omask(oldrx, oldry);
154.  			levl[rx][ry].omask = 1;
155.  			/* pobj(otmp); */
156.  			if(cansee(rx,ry)) atl(rx,ry,otmp->olet);
157.  			newsym(u.ux+u.dx, u.uy+u.dy);
158.  
159.  			{
160.  #ifdef LINT	/* static long lastmovetime; */
161.  			long lastmovetime;
162.  			lastmovetime = 0;
163.  #else
164.  			static long lastmovetime;
165.  #endif
166.  			/* note: this var contains garbage initially and
167.  			   after a restore */
168.  			if(moves > lastmovetime+2 || moves < lastmovetime)
169.  			pline("With great effort you move the boulder.");
170.  			lastmovetime = moves;
171.  			}
172.  		} else {
173.  nopushmsg:
174.  		    You("try to move the boulder, but in vain.");
175.  	    cannot_push:
176.  #ifdef POLYSELF
177.  		    if (throws_rocks(uasmon)) {
178.  			if(!flags.pickup)
179.  				pline("However, you easily can push it aside.");
180.  			else
181.  				pline("However, you easily can pick it up.");
182.  			break;
183.  		    }
184.  #endif
185.  		    if((!invent || inv_weight()+90 <= 0) &&
186.  			(!u.dx || !u.dy || (IS_ROCK(levl[u.ux][u.uy+u.dy].typ)
187.  					&& IS_ROCK(levl[u.ux+u.dx][u.uy].typ)))
188.  #ifdef POLYSELF
189.  			|| verysmall(uasmon)
190.  #endif
191.  									)
192.  		    {
193.  			pline("However, you can squeeze yourself into a small opening.");
194.  			break;
195.  		    } else
196.  			return (-1);
197.  		}
198.  	}
199.  	return (0);
200.  }
201.  
202.  void
203.  movobj(obj, ox, oy)
204.  register struct obj *obj;
205.  register xchar ox, oy;
206.  {
207.  	register xchar ox2 = obj->ox, oy2= obj->oy;
208.  
209.  	/* Some dirty programming to get display right */
210.  	freeobj(obj);
211.  	unpobj(obj);
212.  	obj->nobj = fobj;
213.  	fobj = obj;
214.  	obj->ox = ox;
215.  	obj->oy = oy;
216.  	set_omask(ox2,oy2);
217.  	levl[ox][oy].omask = 1;
218.  }
219.  
220.  #ifdef SINKS
221.  static
222.  void
223.  dosinkfall() {
224.  	register struct obj *obj;
225.  
226.  # ifdef POLYSELF
227.  	if (is_floater(uasmon)) {
228.  		You("wobble unsteadily for a moment.");
229.  	} else {
230.  # endif
231.  		You("crash to the floor!");
232.  		losehp((rn1(10, 20 - (int)ACURR(A_CON))),"fall onto a sink");
233.  		if(levl[u.ux][u.uy].omask)
234.  		for(obj=fobj; obj; obj=obj->nobj)
235.  		    if(obj->ox == u.ux && obj->oy == u.uy &&
236.  		       obj->olet == WEAPON_SYM) {
237.  			You("fell on %s.",doname(obj));
238.  			losehp(rn2(3),"fall onto a sink");
239.  		    }
240.  # ifdef POLYSELF
241.  	}
242.  # endif
243.  
244.  	HLevitation = (HLevitation & ~TIMEOUT) + 1;
245.  	if(uleft && uleft->otyp == RIN_LEVITATION) {
246.  	    obj = uleft;
247.  	    Ring_off(obj);
248.  	    off_msg(obj);
249.  	}
250.  	if(uright && uright->otyp == RIN_LEVITATION) {
251.  	    obj = uright;
252.  	    Ring_off(obj);
253.  	    off_msg(obj);
254.  	}
255.  	if(uarmf && uarmf->otyp == LEVITATION_BOOTS) {
256.  	    obj = uarmf;
257.  	    (void)Boots_off();
258.  	    off_msg(obj);
259.  	}
260.  	HLevitation--;
261.  }
262.  #endif
263.  
264.  static boolean
265.  is_edge(x,y)
266.  register xchar x,y;
267.  /* return true if (x,y) is on the edge of a room
268.   * we cannot rely on IS_DOOR(levl[x][y].typ) because some of the stronghold
269.   * "rooms" are actually outside areas without doors
270.   */
271.  {
272.  	register int roomno = inroom(x,y);
273.  
274.  	if(roomno < 0) return FALSE;
275.  	return((x == rooms[roomno].lx - 1) || (x == rooms[roomno].hx + 1) ||
276.  	       (y == rooms[roomno].ly - 1) || (y == rooms[roomno].hy + 1));
277.  }
278.  
279.  boolean
280.  may_dig(x,y)
281.  register xchar x,y;
282.  /* intended to be called only on ROCKs */
283.  {
284.  return (!(IS_STWALL(levl[x][y].typ) && (levl[x][y].diggable & W_NONDIGGABLE)));
285.  }
286.  
287.  static boolean
288.  bad_rock(x,y)
289.  register xchar x,y;
290.  {
291.  	return(IS_ROCK(levl[x][y].typ)
292.  #ifdef POLYSELF
293.  		    && !passes_walls(uasmon)
294.  		    && (!tunnels(uasmon) || needspick(uasmon) || !may_dig(x,y))
295.  #endif
296.  	);
297.  }
298.  
299.  void
300.  domove() {
301.  	register struct monst *mtmp = (struct monst *)0;
302.  	register struct rm *tmpr,*ust;
303.  	register xchar x,y;
304.  	struct trap *trap;
305.  
306.  	u_wipe_engr(rnd(5));
307.  
308.  	if(inv_weight() > 0){
309.  		You("collapse under your load.");
310.  		nomul(0);
311.  		return;
312.  	}
313.  	if(u.uswallow) {
314.  		u.dx = u.dy = 0;
315.  		x = u.ux = u.ustuck->mx;
316.  		y = u.uy = u.ustuck->my;
317.  	} else {
318.  		x = u.ux + u.dx;
319.  		y = u.uy + u.dy;
320.  		if(Stunned || (Confusion && !rn2(5))) {
321.  			register int tries = 0;
322.  
323.  			do {
324.  				if(tries++ > 50) {
325.  					nomul(0);
326.  					return;
327.  				}
328.  				confdir();
329.  				x = u.ux + u.dx;
330.  				y = u.uy + u.dy;
331.  			} while(!isok(x, y) || bad_rock(x, y));
332.  		}
333.  		if(!isok(x, y)) {
334.  			nomul(0);
335.  			return;
336.  		}
337.  		if((trap = t_at(x, y)) && trap->tseen)
338.  			nomul(0);
339.  		if(u.ustuck && (x != u.ustuck->mx ||
340.  				y != u.ustuck->my)) {
341.  			if(dist(u.ustuck->mx, u.ustuck->my) > 2) {
342.  				/* perhaps it fled (or was teleported or ... ) */
343.  				u.ustuck = 0;
344.  			} else {
345.  #ifdef POLYSELF
346.  				/* If polymorphed into a sticking monster,
347.  				 * u.ustuck means it's stuck to you, not you
348.  				 * to it.
349.  				 */
350.  				if (sticks(uasmon)) {
351.  					kludge("You release %s.",
352.  						mon_nam(u.ustuck));
353.  					u.ustuck = 0;
354.  				} else {
355.  #endif
356.  					kludge("You cannot escape from %s!",
357.  						mon_nam(u.ustuck));
358.  					nomul(0);
359.  					return;
360.  #ifdef POLYSELF
361.  				}
362.  #endif
363.  			}
364.  		}
365.  	}
366.  
367.  	u.ux0 = u.ux;
368.  	u.uy0 = u.uy;
369.  	/* attack monster */
370.  	tmpr = &levl[x][y];
371.  	if (tmpr->mmask) {
372.  		mtmp = m_at(x,y);
373.  		/* Don't attack if you're running */
374.  		if (flags.run && !mtmp->mimic &&
375.  		    (Blind ? Telepat : (!mtmp->minvis || See_invisible))) {
376.  			nomul(0);
377.  			flags.move = 0;
378.  			return;
379.  		}
380.  	}
381.  	if(mtmp || u.uswallow) {
382.  		nomul(0);
383.  		gethungry();
384.  		if(multi < 0) return;	/* we just fainted */
385.  
386.  		/* try to attack; note that it might evade */
387.  		if(attack(u.uswallow ? u.ustuck : mtmp))
388.  			return;
389.  	}
390.  	/* not attacking an animal, so we try to move */
391.  #ifdef POLYSELF
392.  	if(!uasmon->mmove) {
393.  		You("are rooted %s.", Levitation ? "in place"
394.  			: "to the ground");
395.  		nomul(0);
396.  		return;
397.  	}
398.  #endif
399.  	if(u.utrap) {
400.  		if(u.utraptype == TT_PIT) {
401.  		    if(flags.verbose)
402.  			You("are still in a pit.");
403.  		    u.utrap--;
404.  		} else if (u.utraptype == TT_WEB) {
405.  		    if(flags.verbose)
406.  		    	You("are stuck to the web.");
407.  		    u.utrap--;
408.  		} else {
409.  		    if(flags.verbose)
410.  			You("are caught in a bear trap.");
411.  		    if((u.dx && u.dy) || !rn2(5)) u.utrap--;
412.  		}
413.  		return;
414.  	}
415.  	/* check for physical obstacles */
416.  #ifdef POLYSELF
417.  	if (!passes_walls(uasmon)) {
418.  #endif
419.  #ifdef STRONGHOLD
420.  	    if(dlevel == stronghold_level && is_db_wall(x,y)) {
421.  		    pline("The drawbridge is up!");
422.  		    nomul(0);
423.  		    return;
424.  	    }
425.  #endif
426.  	    if(IS_DOOR(tmpr->typ) && (tmpr->doormask & (D_LOCKED | D_CLOSED))
427.  #ifdef POLYSELF
428.  	       && !amorphous(uasmon)
429.  #endif
430.  	      ){
431.  		    flags.move = 0;
432.  		    if(x == u.ux || y == u.uy) {
433.  		        if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling)
434.  			    pline("Ouch!  You bump into a door.");
435.  		        else pline("That door is closed.");
436.  		    }
437.  		    nomul(0);
438.  		    return;
439.  	    }
440.  #ifdef POLYSELF
441.  	}
442.  #endif
443.  	ust = &levl[u.ux][u.uy];
444.  	if(bad_rock(x,y) ||
445.  	   (u.dx && u.dy && (IS_DOOR(tmpr->typ) || IS_DOOR(ust->typ)))){
446.  		flags.move = 0;
447.  		nomul(0);
448.  		return;
449.  	}
450.  	if(moverock() < 0) return;
451.  	if(u.dx && u.dy && bad_rock(u.ux,y) &&
452.  			   bad_rock(x,u.uy)) {
453.  #ifdef POLYSELF
454.  	    if (bigmonst(uasmon)) {
455.  		Your("body is too large to fit through.");
456.  		nomul(0);
457.  		return;
458.  	    }
459.  #endif
460.  	    if (invent && inv_weight()+40 > 0) {
461.  		You("are carrying too much to get through.");
462.  		nomul(0);
463.  		return;
464.  	    }
465.  	}
466.  	if(Punished &&
467.  	   dist2(x, y, uchain->ox, uchain->oy) > 2) {
468.  		if(carried(uball)) {
469.  			movobj(uchain, u.ux, u.uy);
470.  			goto nodrag;
471.  		}
472.  
473.  		if(dist2(x, y, uball->ox, uball->oy) < 3) {
474.  			/* leave ball, move chain under/over ball */
475.  			movobj(uchain, uball->ox, uball->oy);
476.  			goto nodrag;
477.  		}
478.  
479.  		if(inv_weight() + (int)(uball->owt >> 1) > 0) {
480.  			You("cannot %sdrag the heavy iron ball.",
481.  			invent ? "carry all that and also " : "");
482.  			nomul(0);
483.  			return;
484.  		}
485.  
486.  		movobj(uball, uchain->ox, uchain->oy);
487.  		unpobj(uball);		/* BAH %% */
488.  		uchain->ox = u.ux;
489.  		uchain->oy = u.uy;
490.  		ust->omask = 1;
491.  		nomul(-2);
492.  		nomovemsg = "";
493.  	nodrag:	;
494.  	}
495.  #ifdef POLYSELF
496.  	if (tunnels(uasmon) && !needspick(uasmon) && IS_ROCK(tmpr->typ)) {
497.  		static char *digtxt;
498.  
499.  		if(dig_pos.x != x || dig_pos.y != y
500.  		    || dig_level != dlevel || dig_down) {
501.  			dig_down = FALSE;
502.  			dig_pos.x = x;
503.  			dig_pos.y = y;
504.  			dig_level = dlevel;
505.  			dig_effort = 30;
506.  			You("start chewing a hole in the rock.");
507.  			return;
508.  		} else if ((dig_effort += 30) < 100)  {
509.  		    if(flags.verbose)
510.  			You("continue chewing the rock up.");
511.  		    return;
512.  		} else {
513.  			if (IS_WALL(tmpr->typ)) {
514.  				digtxt = "You chew a hole in the wall.";
515.  				tmpr->typ = DOOR;
516.  			} else if (tmpr->typ==SDOOR) {
517.  				digtxt = "You chew through a secret door.";
518.  				tmpr->typ = DOOR;
519.  				if(!(tmpr->doormask & D_TRAPPED))
520.  					tmpr->doormask = D_BROKEN;
521.  			} else {
522.  				digtxt = "You chew a passage through the rock.";
523.  				tmpr->typ = CORR;
524.  			}
525.  			mnewsym(x, y);
526.  			prl(x, y);
527.  			pline(digtxt);
528.  			if(IS_DOOR(tmpr->typ) && (tmpr->doormask & D_TRAPPED)) {
529.  				b_trapped("door");
530.  				tmpr->doormask = D_NODOOR;
531.  			}
532.  			dig_level = -1;
533.  		}
534.  	}
535.  #endif
536.  	u.ux += u.dx;
537.  	u.uy += u.dy;
538.  	if(flags.run) {
539.  		if(IS_DOOR(tmpr->typ) ||
540.  #ifdef POLYSELF
541.  		(IS_ROCK(tmpr->typ)) ||
542.  #endif
543.  		(xupstair == u.ux && yupstair == u.uy) ||
544.  		(xdnstair == u.ux && ydnstair == u.uy)
545.  #ifdef STRONGHOLD
546.  		|| (xupladder == u.ux && yupladder == u.uy)
547.  		|| (xdnladder == u.ux && ydnladder == u.uy)
548.  #endif
549.  #ifdef FOUNTAINS
550.  		|| IS_FOUNTAIN(tmpr->typ)
551.  #endif
552.  #ifdef THRONES
553.  		|| IS_THRONE(tmpr->typ)
554.  #endif
555.  #ifdef SINKS
556.  		|| IS_SINK(tmpr->typ)
557.  #endif
558.  #ifdef ALTARS
559.  		|| IS_ALTAR(tmpr->typ)
560.  #endif
561.  		)
562.  			nomul(0);
563.  	}
564.  #ifdef POLYSELF
565.  	if (hides_under(uasmon))
566.  	    u.uundetected = (levl[u.ux][u.uy].omask || levl[u.ux][u.uy].gmask);
567.  	else if (u.dx || u.dy) { /* i.e. piercer */
568.  	    if (u.usym == S_MIMIC_DEF)
569.  		u.usym = S_MIMIC;
570.  	    u.uundetected = 0;
571.  	}
572.  #endif
573.  
574.  /*
575.  	if(u.udispl) {
576.  		u.udispl = 0;
577.  		newsym(u.ux0,u.uy0);
578.  	}
579.  */
580.  	if(!Blind) {
581.  	    register xchar backx = u.ux0 - u.dx;   /* one step beyond old pos */
582.  	    register xchar backy = u.uy0 - u.dy;
583.  	    register xchar frontx = u.ux + u.dx;   /* one step beyond new pos */
584.  	    register xchar fronty = u.uy + u.dy;
585.  	    register boolean newedge = is_edge(u.ux,u.uy);
586.  	    register boolean oldedge = is_edge(u.ux0,u.uy0);
587.  
588.  	    /* ust is old position, tmpr is new position */
589.  	    if(oldedge && newedge && inroom(u.ux0,u.uy0) == inroom(u.ux,u.uy)) {
590.  		/* moving along wall */
591.  		nose1(backx,backy);
592.  		prl1(frontx,fronty);
593.  
594.  	    } else if(oldedge || newedge) {
595.  		if(isok(backx,backy) && levl[backx][backy].lit)
596.  		    setsee();
597.  		else
598.  		    nose1(backx,backy);
599.  
600.  		if(isok(frontx,fronty) && levl[frontx][fronty].lit)
601.  		    setsee();
602.  		else {
603.  		    prl1(frontx,fronty);
604.  		    prl1(u.ux,u.uy);    /* make sure side walls are seen */
605.  		}
606.  
607.  	    } else if(!tmpr->lit) {
608.  		/* we haven't crossed an edge, so old & new are both light or
609.  		 * both dark.  if both light, we need do nothing.
610.  		 */
611.  		nose1(backx,backy);
612.  		prl1(frontx,fronty);
613.  	    }
614.  
615.  	} else {
616.  		pru();
617.  	}
618.  #ifdef WALKIES
619.  	check_leash(u.ux0,u.uy0);
620.  #endif
621.  	if(u.ux0 != u.ux || u.uy0 != u.uy) u.umoved = TRUE;
622.  	spoteffects();
623.  }
624.  
625.  void
626.  spoteffects()
627.  {
628.  	register struct trap *trap;
629.  
630.  	if(is_pool(u.ux,u.uy) && !(Levitation || Wwalking
631.  #ifdef POLYSELF
632.  	    || is_flyer(uasmon)
633.  #endif
634.  	    ))
635.  		drown();	/* not necessarily fatal */
636.  	else {
637.  		(void) inshop();
638.  #ifdef SINKS
639.  		if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
640.  			dosinkfall();
641.  #endif
642.  		if(!flags.nopick &&
643.  		   (levl[u.ux][u.uy].omask || levl[u.ux][u.uy].gmask))
644.  			pickup(1);
645.  		else read_engr_at(u.ux,u.uy);
646.  		if(trap = t_at(u.ux,u.uy))
647.  			dotrap(trap);	/* fall into pit, arrow trap, etc. */
648.  	}
649.  
650.  }
651.  
652.  int
653.  dopickup() {
654.  	/* uswallow case added by GAN 01/29/87 */
655.  	if(u.uswallow)  {
656.  		if (is_animal(u.ustuck->data)) {
657.  		    You("pick up %s's tongue.", mon_nam(u.ustuck));
658.  		    pline("But it's kind of slimy, so you drop it.");
659.  		} else
660.  		    pline("You don't %s anything in here to pick up.",
661.  			  Blind ? "feel" : "see");
662.  		return(1);
663.  	}
664.  	if(levl[u.ux][u.uy].omask == 0 && levl[u.ux][u.uy].gmask == 0) {
665.  		pline("There is nothing here to pick up.");
666.  		return(0);
667.  	}
668.  	if(Levitation) {
669.  		You("cannot reach the floor.");
670.  		return(1);
671.  	}
672.  	pickup(0);
673.  	return(1);
674.  }
675.  
676.  /* stop running if we see something interesting */
677.  /* turn around a corner if that is the only way we can proceed */
678.  /* do not turn left or right twice */
679.  void
680.  lookaround() {
681.  	register int x, y, i, x0, y0, m0, i0 = 9, corrct = 0, noturn = 0;
682.  	register struct monst *mtmp;
683.  #ifdef LINT
684.  	/* suppress "used before set" message */
685.  	x0 = y0 = 0;
686.  #endif
687.  	if(Blind || flags.run == 0) return;
688.  	for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) {
689.  		if(x == u.ux && y == u.uy) continue;
690.  		if(levl[x][y].mmask && (mtmp = m_at(x,y)) && !mtmp->mimic &&
691.  		    (!mtmp->minvis || See_invisible)) {
692.  			if((flags.run != 1 && !mtmp->mtame) || (x == u.ux+u.dx && y == u.uy+u.dy))
693.  				goto stop;
694.  		} else mtmp = 0;
695.  		if(levl[x][y].typ == STONE) continue;
696.  		if(x == u.ux-u.dx && y == u.uy-u.dy) continue;
697.  		{
698.  		register uchar sym = levl[x][y].scrsym;
699.  
700.  		if (IS_ROCK(levl[x][y].typ) || sym == ROOM_SYM) continue;
701.  		else if (sym == DOOR_SYM) {
702.  			if(x != u.ux && y != u.uy) continue;
703.  			if(flags.run != 1) goto stop;
704.  			goto bcorr;
705.  		} else if (sym == CORR_SYM) {
706.  		bcorr:
707.  			if(levl[u.ux][u.uy].typ != ROOM) {
708.  			    if(flags.run == 1 || flags.run == 3) {
709.  				i = dist2(x,y,u.ux+u.dx,u.uy+u.dy);
710.  				if(i > 2) continue;
711.  				if(corrct == 1 && dist2(x,y,x0,y0) != 1)
712.  					noturn = 1;
713.  				if(i < i0) {
714.  					i0 = i;
715.  					x0 = x;
716.  					y0 = y;
717.  					m0 = mtmp ? 1 : 0;
718.  				}
719.  			    }
720.  			    corrct++;
721.  			}
722.  			continue;
723.  		} else if (sym == TRAP_SYM) {
724.  			if(flags.run == 1) goto bcorr;	/* if you must */
725.  			if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
726.  			continue;
727.  		} else if (sym == POOL_SYM) {
728.  			/* pools only stop you if directly in front, and stop
729.  			 * you even if you are running
730.  			 */
731.  			if(!Levitation &&
732.  #ifdef POLYSELF
733.  				!is_flyer(uasmon) &&
734.  #endif
735.  				/* No Wwalking check; otherwise they'd be able
736.  				 * to test boots by trying to SHIFT-direction
737.  				 * into a pool and seeing if the game allowed it
738.  				 */
739.  				x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
740.  			continue;
741.  		} else {		/* e.g. objects or trap or stairs */
742.  			if(flags.run == 1) goto bcorr;
743.  			if(mtmp) continue;		/* d */
744.  		}
745.  		stop:
746.  			nomul(0);
747.  			return;
748.  		}
749.  	}
750.  	if(corrct > 1 && flags.run == 2) goto stop;
751.  	if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&
752.  		(corrct == 1 || (corrct == 2 && i0 == 1))) {
753.  		/* make sure that we do not turn too far */
754.  		if(i0 == 2) {
755.  		    if(u.dx == y0-u.uy && u.dy == u.ux-x0)
756.  			i = 2;		/* straight turn right */
757.  		    else
758.  			i = -2;		/* straight turn left */
759.  		} else if(u.dx && u.dy) {
760.  		    if((u.dx == u.dy && y0 == u.uy) ||
761.  			(u.dx != u.dy && y0 != u.uy))
762.  			i = -1;		/* half turn left */
763.  		    else
764.  			i = 1;		/* half turn right */
765.  		} else {
766.  		    if((x0-u.ux == y0-u.uy && !u.dy) ||
767.  			(x0-u.ux != y0-u.uy && u.dy))
768.  			i = 1;		/* half turn right */
769.  		    else
770.  			i = -1;		/* half turn left */
771.  		}
772.  		i += u.last_str_turn;
773.  		if(i <= 2 && i >= -2) {
774.  			u.last_str_turn = i;
775.  			u.dx = x0-u.ux, u.dy = y0-u.uy;
776.  		}
777.  	}
778.  }
779.  
780.  /* something like lookaround, but we are not running */
781.  /* react only to monsters that might hit us */
782.  int
783.  monster_nearby() {
784.  	register int x,y;
785.  	register struct monst *mtmp;
786.  
787.  	if(!Blind)
788.  	for(x = u.ux-1; x <= u.ux+1; x++)
789.  	    for(y = u.uy-1; y <= u.uy+1; y++) {
790.  		if(x == u.ux && y == u.uy) continue;
791.  		if(levl[x][y].mmask && (mtmp = m_at(x,y)) && !mtmp->mimic &&
792.  		   !mtmp->mtame && !mtmp->mpeaceful &&
793.  		   !noattacks(mtmp->data) &&
794.  		   !mtmp->mfroz && !mtmp->msleep &&  /* aplvax!jcn */
795.  		   (!mtmp->minvis || See_invisible) &&
796.  		   !onscary(u.ux, u.uy, mtmp))
797.  			return(1);
798.  	}
799.  	return(0);
800.  }
801.  
802.  int
803.  cansee(x,y)
804.  xchar x,y;
805.  {
806.  	if(Blind || u.uswallow) return(0);
807.  	if(dist(x,y) < 3) return(1);
808.  	if(IS_ROCK(levl[x][y].typ) && levl[u.ux][u.uy].typ == CORR &&
809.  							!levl[u.ux][u.uy].lit)
810.  		return(0);
811.  	if(levl[x][y].lit &&
812.  		((seelx <= x && x <= seehx && seely <= y && y <= seehy) ||
813.  		(seelx2 <= x && x <= seehx2 && seely2 <= y && y <= seehy2)))
814.  		return(1);
815.  	return(0);
816.  }
817.  
818.  int
819.  sgn(a)
820.  	register int a;
821.  {
822.  	return((a > 0) ? 1 : (a == 0) ? 0 : -1);
823.  }
824.  
825.  void
826.  getcorners(lx1,hx1,ly1,hy1,lx2,hx2,ly2,hy2)
827.  xchar *lx1,*hx1,*ly1,*hy1,*lx2,*hx2,*ly2,*hy2;
828.  /* return corners of one or two rooms player is in, so we can tell what areas
829.   * can be seen, or otherwise affected by room-specific things.  (two rooms are
830.   * possible when in a doorway of the stronghold)
831.   * the player is already known to be in at least one room
832.   */
833.  {
834.  	register int uroom1,uroom2;
835.  	register xchar ux,uy;
836.  
837.  	uroom1 = inroom(u.ux,u.uy);
838.  	*lx1 = rooms[uroom1].lx - 1;
839.  	*hx1 = rooms[uroom1].hx + 1;
840.  	*ly1 = rooms[uroom1].ly - 1;
841.  	*hy1 = rooms[uroom1].hy + 1;
842.  
843.  	if(!IS_DOOR(levl[u.ux][u.uy].typ)) {
844.  		*lx2 = 1;
845.  		*hx2 = 0;
846.  		*ly2 = 1;
847.  		*hy2 = 0;
848.  	} else {
849.  		for(ux = u.ux-1; ux <= u.ux+1; ux++)
850.  			for(uy = u.uy-1; uy <= u.uy+1; uy++) {
851.  				if(IS_ROCK(levl[ux][uy].typ) ||
852.  					IS_DOOR(levl[ux][uy].typ)) continue;
853.  				/* might have side-by-side walls, in which case
854.  				 * should only be able to see one room */
855.  				uroom2 = inroom(ux,uy);
856.  				if(uroom2 >= 0 && uroom2 != uroom1 && 
857.  				   rooms[uroom2].rlit) {
858.  					*lx2 = rooms[uroom2].lx - 1;
859.  					*ly2 = rooms[uroom2].ly - 1;
860.  					*hx2 = rooms[uroom2].hx + 1;
861.  					*hy2 = rooms[uroom2].hy + 1;
862.  					return;
863.  				}
864.  			}
865.  		*lx2 = 1;
866.  		*hx2 = 0;
867.  		*ly2 = 1;
868.  		*hy2 = 0;
869.  	}
870.  }
871.  
872.  void
873.  setsee() {
874.  	register int x, y;
875.  
876.  	if(Blind) {
877.  		pru();
878.  		return;
879.  	}
880.  	if(!levl[u.ux][u.uy].lit) {
881.  		seelx = u.ux-1;
882.  		seehx = u.ux+1;
883.  		seely = u.uy-1;
884.  		seehy = u.uy+1;
885.  		seelx2 = seely2 = 1;
886.  		seehx2 = seehy2 = 0;
887.  	} else {
888.  		getcorners(&seelx,&seehx,&seely,&seehy,
889.  			   &seelx2,&seehx2,&seely2,&seehy2);
890.  	}
891.  	for(y = seely; y <= seehy; y++)
892.  		for(x = seelx; x <= seehx; x++) {
893.  			prl(x,y);
894.  	}
895.  	for(y = seely2; y <= seehy2; y++)
896.  		for(x = seelx2; x <= seehx2; x++) {
897.  			prl(x,y);
898.  	}
899.  	if(!levl[u.ux][u.uy].lit) seehx = 0; /* seems necessary elsewhere */
900.  	else {
901.  	    if(seely == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seely-1);
902.  	    if(seehy == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seehy+1);
903.  	    if(seelx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seelx-1,y);
904.  	    if(seehx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seehx+1,y);
905.  	}
906.  }
907.  
908.  void
909.  nomul(nval)
910.  	register int nval;
911.  {
912.  	if(multi < nval) return;	/* This is a bug fix by ab@unido */
913.  	multi = nval;
914.  	flags.mv = flags.run = 0;
915.  }
916.  
917.  void
918.  losehp(n, knam)
919.  	register int n;
920.  	register char *knam;
921.  {
922.  #ifdef POLYSELF
923.  	if (u.mtimedone) {
924.  		u.mh -= n;
925.  		if (u.mhmax < u.mh) u.mhmax = u.mh;
926.  		flags.botl = 1;
927.  		if (u.mh < 1) rehumanize();
928.  		return;
929.  	}
930.  #endif
931.  	u.uhp -= n;
932.  	if(u.uhp > u.uhpmax)
933.  		u.uhpmax = u.uhp;	/* perhaps n was negative */
934.  	flags.botl = 1;
935.  	if(u.uhp < 1) {
936.  		killer = knam;	/* the thing that killed you */
937.  		You("die...");
938.  		done("died");
939.  	} else if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50 && n > 0){
940.  		wailmsg = moves;
941.  		if(index("WEV", pl_character[0])) {
942.  			if (u.uhp == 1)
943.  				pline("%s is about to die.", pl_character);
944.  			else if (4 <= (!!(HTeleportation & INTRINSIC)) +
945.  				    (!!(HSee_invisible & INTRINSIC)) +
946.  				    (!!(HPoison_resistance & INTRINSIC)) +
947.  				    (!!(HCold_resistance & INTRINSIC)) +
948.  				    (!!(HShock_resistance & INTRINSIC)) +
949.  				    (!!(HFire_resistance & INTRINSIC)) +
950.  				    (!!(HSleep_resistance & INTRINSIC)) +
951.  				    (!!(HDisint_resistance & INTRINSIC)) +
952.  				    (!!(HTeleport_control & INTRINSIC)) +
953.  				    (!!(Fast & INTRINSIC)) +
954.  				    (!!(HInvis & INTRINSIC)))
955.  				pline("%s, all your powers will be lost...",
956.  					pl_character);
957.  			else
958.  				pline("%s, your life force is running out.",
959.  					pl_character);
960.  		} else {
961.  			if(u.uhp == 1)
962.  				You("hear the wailing of the Banshee...");
963.  			else
964.  				You("hear the howling of the CwnAnnwn...");
965.  		}
966.  	}
967.  }
968.  
969.  int
970.  weight_cap() {
971.  	register int carrcap;
972.  
973.  #ifdef HARD
974.  	carrcap = 5 * (((ACURR(A_STR) > 18) ? 20 : ACURR(A_STR)) + u.ulevel);
975.  #else
976.  	carrcap = 5 * u.ulevel;      /* New strength stewr 870807 */
977.  	if (ACURR(A_STR) < 19) carrcap += 5 * ACURR(A_STR);
978.  	if (ACURR(A_STR) > 18) carrcap += ACURR(A_STR) - 18 + 90;
979.  	if (ACURR(A_STR) > 68) carrcap += ACURR(A_STR) - 68;
980.  	if (ACURR(A_STR) > 93) carrcap += ACURR(A_STR) - 93;
981.  	if (ACURR(A_STR) > 108) carrcap += 2 * (ACURR(A_STR) - 108);
982.  	if (ACURR(A_STR) > 113) carrcap += 5 * (ACURR(A_STR) - 113);
983.  	if (ACURR(A_STR) == 118) carrcap += 100;
984.  #endif
985.  #ifdef POLYSELF
986.  	if (u.mtimedone) {
987.  		/* consistent with can_carry() in mon.c */
988.  		if (u.usym==S_NYMPH) carrcap = MAX_CARR_CAP;
989.  		else if (!uasmon->cwt)
990.  			carrcap = (carrcap * uasmon->mlevel * 6)/45;
991.  		else carrcap = (carrcap * uasmon->cwt / 45);
992.  	}
993.  #endif
994.  	if(Levitation) 			/* pugh@cornell */
995.  		carrcap = MAX_CARR_CAP;
996.  	else {
997.  		if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
998.  		if(Wounded_legs & LEFT_SIDE) carrcap -= 10;
999.  		if(Wounded_legs & RIGHT_SIDE) carrcap -= 10;
1000. 	}
1001. 	return(carrcap);
1002. }
1003. 
1004. int
1005. inv_weight() {
1006. 	register struct obj *otmp = invent;
1007. #ifdef LINT	/* long to int conversion */
1008. 	register int wt = 0;
1009. #else
1010. 	register int wt = (int)((u.ugold + 500L)/1000L);
1011. #endif /* LINT */
1012. 	while(otmp){
1013. #ifdef POLYSELF
1014. 		if (otmp->otyp != BOULDER || !throws_rocks(uasmon))
1015. #endif
1016. 			wt += otmp->owt;
1017. 		otmp = otmp->nobj;
1018. 	}
1019. 	return(wt - weight_cap());
1020. }
1021. 
1022. int
1023. inv_cnt() {
1024. 	register struct obj *otmp = invent;
1025. 	register int ct = 0;
1026. 
1027. 	while(otmp){
1028. 		ct++;
1029. 		otmp = otmp->nobj;
1030. 	}
1031. 	return(ct);
1032. }
1033. 
1034. #ifdef STUPID_CPP	/* otherwise these functions are macros in hack.h */
1035. char
1036. yn() {
1037. 	return(yn_function(ynchars, 'n'));
1038. }
1039. 
1040. char
1041. ynq() {
1042. 	return(yn_function(ynqchars, 'q'));
1043. }
1044. 
1045. char
1046. ynaq() {
1047. 	return(yn_function(ynaqchars, 'y'));
1048. }
1049. 
1050. char
1051. nyaq() {
1052. 	return(yn_function(nyaqchars, 'n'));
1053. }
1054. 
1055. int
1056. max(a,b) int a,b; {
1057. 	return((a > b) ? a : b);
1058. }
1059. 
1060. int
1061. min(a,b) int a,b; {
1062. 	return((a < b) ? a : b);
1063. }
1064. 
1065. char *
1066. plur(x) long x; {
1067. 	return((x == 1L) ? "" : "s");
1068. }
1069. 
1070. void
1071. makeknown(x) unsigned x; {
1072. 	objects[x].oc_name_known = 1;
1073. }
1074. #endif /* STUPID_CPP */