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