1 /* $NetBSD: hack.zap.c,v 1.8 2009/06/07 18:30:39 dholland Exp $ */
4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * - Neither the name of the Stichting Centrum voor Wiskunde en
20 * Informatica, nor the names of its contributors may be used to endorse or
21 * promote products derived from this software without specific prior
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39 * All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 #include <sys/cdefs.h>
66 __RCSID("$NetBSD: hack.zap.c,v 1.8 2009/06/07 18:30:39 dholland Exp $");
72 static const char *const fl
[] = {
80 static void bhitm(struct monst
*, struct obj
*);
81 static int bhito(struct obj
*, struct obj
*);
82 static char dirlet(int, int);
83 static int zhit(struct monst
*, int);
84 static int revive(struct obj
*);
85 static void rloco(struct obj
*);
86 static void burn_scrolls(void);
88 /* Routines for IMMEDIATE wands. */
89 /* bhitm: monster mtmp was hit by the effect of wand otmp */
91 bhitm(struct monst
*mtmp
, struct obj
*otmp
)
96 if (u
.uswallow
|| rnd(20) < 10 + mtmp
->data
->ac
) {
98 hit("wand", mtmp
, exclam(tmp
));
105 case WAN_SLOW_MONSTER
:
106 mtmp
->mspeed
= MSLOW
;
108 case WAN_SPEED_MONSTER
:
109 mtmp
->mspeed
= MFAST
;
111 case WAN_UNDEAD_TURNING
:
112 if (strchr(UNDEAD
, mtmp
->data
->mlet
)) {
121 if (newcham(mtmp
, &mons
[rn2(CMNUM
)]))
122 objects
[otmp
->otyp
].oc_name_known
= 1;
124 case WAN_CANCELLATION
:
127 case WAN_TELEPORTATION
:
130 case WAN_MAKE_INVISIBLE
:
137 #endif /* WAN_PROBING */
139 impossible("What an interesting wand (%u)", otmp
->otyp
);
144 * object obj was hit by the effect of wand otmp
145 * returns TRUE if sth was done
148 bhito(struct obj
*obj
, struct obj
*otmp
)
152 if (obj
== uball
|| obj
== uchain
)
155 switch (otmp
->otyp
) {
158 * preserve symbol and quantity, but turn rocks into
161 mkobj_at((obj
->otyp
== ROCK
|| obj
->otyp
== ENORMOUS_ROCK
)
162 ? GEM_SYM
: obj
->olet
,
163 obj
->ox
, obj
->oy
)->quan
= obj
->quan
;
167 if (obj
->otyp
== ENORMOUS_ROCK
)
172 case WAN_CANCELLATION
:
173 if (obj
->spe
&& obj
->olet
!= AMULET_SYM
) {
178 case WAN_TELEPORTATION
:
181 case WAN_MAKE_INVISIBLE
:
184 case WAN_UNDEAD_TURNING
:
187 case WAN_SLOW_MONSTER
: /* no effect on objects */
188 case WAN_SPEED_MONSTER
:
191 #endif /* WAN_PROBING */
195 impossible("What an interesting wand (%u)", otmp
->otyp
);
206 obj
= getobj("/", "zap");
209 if (obj
->spe
< 0 || (obj
->spe
== 0 && rn2(121))) {
210 pline("Nothing Happens.");
214 pline("You wrest one more spell from the worn-out wand.");
215 if (!(objects
[obj
->otyp
].bits
& NODIR
) && !getdir(1))
216 return (1); /* make him pay for knowing !NODIR */
218 if (objects
[obj
->otyp
].bits
& IMMEDIATE
) {
220 bhitm(u
.ustuck
, obj
);
223 struct obj
*otmp
= o_at(u
.ux
, u
.uy
);
225 (void) bhito(otmp
, obj
);
228 (void) bhit(u
.dx
, u
.dy
, rn1(8, 6), 0, bhitm
, bhito
, obj
);
234 case WAN_SECRET_DOOR_DETECTION
:
238 case WAN_CREATE_MONSTER
:
244 (void) makemon((struct permonst
*) 0, u
.ux
, u
.uy
);
251 if (u
.uluck
+ rn2(5) < 0) {
252 pline("Unfortunately, nothing happens.");
255 pline("You may wish for an object. What do you want? ");
257 if (buf
[0] == '\033')
259 otmp
= readobjnam(buf
);
266 * Original effect (approximately): from CORR: dig
267 * until we pierce a wall from ROOM: piece wall and
268 * dig until we reach an ACCESSIBLE place. Currently:
269 * dig for digdepth positions; also down on request
270 * of Lennart Augustsson.
276 struct monst
*mtmp
= u
.ustuck
;
278 pline("You pierce %s's stomach wall!",
280 mtmp
->mhp
= 1; /* almost dead */
287 pline("You loosen a rock from the ceiling.");
288 pline("It falls on your head!");
289 losehp(1, "falling rock");
290 mksobj_at(ROCK
, u
.ux
, u
.uy
);
302 digdepth
= 8 + rn2(18);
303 Tmp_at(-1, '*'); /* open call */
304 while (--digdepth
>= 0) {
307 room
= &levl
[zx
][zy
];
310 if (zx
< 3 || zx
> COLNO
- 3 ||
311 zy
< 3 || zy
> ROWNO
- 3)
313 if (room
->typ
== HWALL
||
314 room
->typ
== VWALL
) {
318 } else if (room
->typ
== HWALL
|| room
->typ
== VWALL
||
319 room
->typ
== SDOOR
|| room
->typ
== LDOOR
) {
322 } else if (room
->typ
== SCORR
|| !room
->typ
) {
330 mnewsym(zx
, zy
); /* not always necessary */
331 Tmp_at(-1, -1); /* closing call */
335 buzz((int) obj
->otyp
- WAN_MAGIC_MISSILE
,
336 u
.ux
, u
.uy
, u
.dx
, u
.dy
);
339 if (!objects
[obj
->otyp
].oc_name_known
) {
340 objects
[obj
->otyp
].oc_name_known
= 1;
341 more_experienced(0, 10);
350 /* force == 0 occurs e.g. with sleep ray */
352 * note that large force is usual with wands so that !! would require
353 * information about hand/weapon/wand
355 return ((force
< 0) ? "?" : (force
<= 4) ? "." : "!");
359 hit(const char *str
, struct monst
*mtmp
, const char *force
)
361 /* force is usually either "." or "!" */
363 if (!cansee(mtmp
->mx
, mtmp
->my
))
364 pline("The %s hits it.", str
);
366 pline("The %s hits %s%s", str
, monnam(mtmp
), force
);
370 miss(const char *str
, struct monst
*mtmp
)
372 if (!cansee(mtmp
->mx
, mtmp
->my
))
373 pline("The %s misses it.", str
);
375 pline("The %s misses %s.", str
, monnam(mtmp
));
379 * bhit: called when a weapon is thrown (sym = obj->olet) or when an
380 * IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of range
381 * or when a monster is hit; the monster is returned, and bhitpos is set to
382 * the final position of the weapon thrown; the ray of a wand may affect
383 * several objects and monsters on its path - for each of these an argument
384 * function is called.
386 /* check !u.uswallow before calling bhit() */
389 bhit(int ddx
, int ddy
, int range
, /* direction and range */
390 int sym
, /* symbol displayed on path */
391 /* fns called when mon/obj hit */
392 void (*fhitm
)(struct monst
*, struct obj
*),
393 int (*fhito
)(struct obj
*, struct obj
*),
394 struct obj
*obj
) /* 2nd arg to fhitm/fhito */
404 tmp_at(-1, sym
);/* open call */
405 while (range
-- > 0) {
408 typ
= levl
[bhitpos
.x
][bhitpos
.y
].typ
;
409 if ((mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)) != NULL
) {
411 tmp_at(-1, -1); /* close call */
414 (*fhitm
) (mtmp
, obj
);
417 if (fhito
&& (otmp
= o_at(bhitpos
.x
, bhitpos
.y
))) {
418 if ((*fhito
) (otmp
, obj
))
427 tmp_at(bhitpos
.x
, bhitpos
.y
);
430 /* leave last symbol unless in a pool */
432 tmp_at(-1, (levl
[bhitpos
.x
][bhitpos
.y
].typ
== POOL
) ? -1 : 0);
437 boomhit(int dx
, int dy
)
446 for (i
= 0; i
< 8; i
++)
447 if (xdir
[i
] == dx
&& ydir
[i
] == dy
)
449 tmp_at(-1, sym
); /* open call */
450 for (ct
= 0; ct
< 10; ct
++) {
453 sym
= ')' + '(' - sym
;
454 tmp_at(-2, sym
);/* change let call */
459 if ((mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)) != NULL
) {
463 if (!ZAP_POS(levl
[bhitpos
.x
][bhitpos
.y
].typ
)) {
468 if (bhitpos
.x
== u
.ux
&& bhitpos
.y
== u
.uy
) { /* ct == 9 */
469 if (rn2(20) >= 10 + u
.ulevel
) { /* we hit ourselves */
470 (void) thitu(10, rnd(10), "boomerang");
472 } else {/* we catch it */
474 pline("Skillfully, you catch the boomerang.");
478 tmp_at(bhitpos
.x
, bhitpos
.y
);
482 tmp_at(-1, -1); /* do not leave last symbol */
487 dirlet(int dx
, int dy
)
490 (dx
== dy
) ? '\\' : (dx
&& dy
) ? '/' : dx
? '-' : '|';
493 /* type == -1: monster spitting fire at you */
494 /* type == -1,-2,-3: bolts sent out by wizard */
495 /* called with dx = dy = 0 with vertical bolts */
497 buzz(int type
, xchar sx
, xchar sy
, int dx
, int dy
)
499 int abstype
= abs(type
);
500 const char *fltxt
= (type
== -1) ? "blaze of fire" : fl
[abstype
];
510 tmp
= zhit(u
.ustuck
, type
);
511 pline("The %s rips into %s%s",
512 fltxt
, monnam(u
.ustuck
), exclam(tmp
));
518 Tmp_at(-1, dirlet(dx
, dy
)); /* open call */
519 while (range
-- > 0) {
522 if ((lev
= &levl
[sx
][sy
])->typ
)
526 if (cansee(sx
- dx
, sy
- dy
))
527 pline("The %s bounces!", fltxt
);
528 if (ZAP_POS(levl
[sx
][sy
- dy
].typ
))
530 if (ZAP_POS(levl
[sx
- dx
][sy
].typ
)) {
531 if (!bounce
|| rn2(2))
548 Tmp_at(-2, dirlet(dx
, dy
));
551 if (lev
->typ
== POOL
&& abstype
== 1 /* fire */ ) {
554 if (cansee(sx
, sy
)) {
556 pline("The water evaporates.");
558 pline("You hear a hissing sound.");
560 if ((mon
= m_at(sx
, sy
)) &&
561 (type
!= -1 || mon
->data
->mlet
!= 'D')) {
563 if (rnd(20) < 18 + mon
->data
->ac
) {
564 int tmp
= zhit(mon
, abstype
);
567 if (cansee(mon
->mx
, mon
->my
))
568 pline("%s is killed by the %s!",
574 hit(fltxt
, mon
, exclam(tmp
));
578 } else if (sx
== u
.ux
&& sy
== u
.uy
) {
580 if (rnd(20) < 18 + u
.uac
) {
583 pline("The %s hits you!", fltxt
);
590 pline("You don't feel hot!");
597 nomul(-rnd(25)); /* sleep ray */
601 pline("You don't feel cold!");
610 pline("The %s whizzes by you!", fltxt
);
613 if (!ZAP_POS(lev
->typ
)) {
616 pline("The %s bounces!", fltxt
);
618 if (!dx
|| !dy
|| !rn2(20)) {
622 if (ZAP_POS(rmn
= levl
[sx
][sy
- dy
].typ
) &&
623 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
+ dx
][sy
- dy
].typ
)))
625 if (ZAP_POS(rmn
= levl
[sx
- dx
][sy
].typ
) &&
626 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
- dx
][sy
+ dy
].typ
)))
627 if (!bounce
|| rn2(2))
642 Tmp_at(-2, dirlet(dx
, dy
));
650 zhit(struct monst
*mon
, int type
) /* returns damage to mon */
655 case 0: /* magic missile */
658 case -1: /* Dragon blazing fire */
660 if (strchr("Dg", mon
->data
->mlet
))
663 if (strchr("YF", mon
->data
->mlet
))
670 if (strchr("YFgf", mon
->data
->mlet
))
673 if (mon
->data
->mlet
== 'D')
677 if (strchr(UNDEAD
, mon
->data
->mlet
))
686 #define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\
687 ? 'a' + (otyp - DEAD_ACID_BLOB)\
688 : '@' + (otyp - DEAD_HUMAN))
690 revive(struct obj
*obj
)
692 struct monst
*mtmp
= NULL
;
694 if (obj
->olet
== FOOD_SYM
&& obj
->otyp
> CORPSE
) {
695 /* do not (yet) revive shopkeepers */
697 * Note: this might conceivably produce two monsters at the
698 * same position - strange, but harmless
700 mtmp
= mkmon_at(CORPSE_I_TO_C(obj
->otyp
), obj
->ox
, obj
->oy
);
703 return (!!mtmp
); /* TRUE if some monster created */
707 rloco(struct obj
*obj
)
709 int tx
, ty
, otx
, oty
;
714 tx
= rn1(COLNO
- 3, 2);
716 } while (!goodpos(tx
, ty
));
719 if (cansee(otx
, oty
))
723 /* fractured by pick-axe or wand of striking */
726 fracture_rock(struct obj
*obj
)
730 obj
->quan
= 7 + rn2(60);
731 obj
->owt
= weight(obj
);
732 obj
->olet
= WEAPON_SYM
;
733 if (cansee(obj
->ox
, obj
->oy
))
734 prl(obj
->ox
, obj
->oy
);
740 struct obj
*obj
, *obj2
;
743 for (obj
= invent
; obj
; obj
= obj2
) {
745 if (obj
->olet
== SCROLL_SYM
) {
751 pline("Your scrolls catch fire!");
752 losehp(cnt
, "burning scrolls");
754 pline("Your scroll catches fire!");
755 losehp(1, "burning scroll");