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