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