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