1 /* $NetBSD: hack.zap.c,v 1.6 2003/04/02 18:36:42 jsm 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.6 2003/04/02 18:36:42 jsm Exp $");
72 const char *const fl
[] = {
80 /* Routines for IMMEDIATE wands. */
81 /* bhitm: monster mtmp was hit by the effect of wand otmp */
90 if (u
.uswallow
|| rnd(20) < 10 + mtmp
->data
->ac
) {
92 hit("wand", mtmp
, exclam(tmp
));
99 case WAN_SLOW_MONSTER
:
100 mtmp
->mspeed
= MSLOW
;
102 case WAN_SPEED_MONSTER
:
103 mtmp
->mspeed
= MFAST
;
105 case WAN_UNDEAD_TURNING
:
106 if (strchr(UNDEAD
, mtmp
->data
->mlet
)) {
115 if (newcham(mtmp
, &mons
[rn2(CMNUM
)]))
116 objects
[otmp
->otyp
].oc_name_known
= 1;
118 case WAN_CANCELLATION
:
121 case WAN_TELEPORTATION
:
124 case WAN_MAKE_INVISIBLE
:
131 #endif /* WAN_PROBING */
133 impossible("What an interesting wand (%u)", otmp
->otyp
);
138 bhito(obj
, otmp
) /* object obj was hit by the effect of wand
140 struct obj
*obj
, *otmp
; /* returns TRUE if sth was done */
144 if (obj
== uball
|| obj
== uchain
)
147 switch (otmp
->otyp
) {
150 * preserve symbol and quantity, but turn rocks into
153 mkobj_at((obj
->otyp
== ROCK
|| obj
->otyp
== ENORMOUS_ROCK
)
154 ? GEM_SYM
: obj
->olet
,
155 obj
->ox
, obj
->oy
)->quan
= obj
->quan
;
159 if (obj
->otyp
== ENORMOUS_ROCK
)
164 case WAN_CANCELLATION
:
165 if (obj
->spe
&& obj
->olet
!= AMULET_SYM
) {
170 case WAN_TELEPORTATION
:
173 case WAN_MAKE_INVISIBLE
:
176 case WAN_UNDEAD_TURNING
:
179 case WAN_SLOW_MONSTER
: /* no effect on objects */
180 case WAN_SPEED_MONSTER
:
183 #endif /* WAN_PROBING */
187 impossible("What an interesting wand (%u)", otmp
->otyp
);
198 obj
= getobj("/", "zap");
201 if (obj
->spe
< 0 || (obj
->spe
== 0 && rn2(121))) {
202 pline("Nothing Happens.");
206 pline("You wrest one more spell from the worn-out wand.");
207 if (!(objects
[obj
->otyp
].bits
& NODIR
) && !getdir(1))
208 return (1); /* make him pay for knowing !NODIR */
210 if (objects
[obj
->otyp
].bits
& IMMEDIATE
) {
212 bhitm(u
.ustuck
, obj
);
215 struct obj
*otmp
= o_at(u
.ux
, u
.uy
);
217 (void) bhito(otmp
, obj
);
220 (void) bhit(u
.dx
, u
.dy
, rn1(8, 6), 0, bhitm
, bhito
, obj
);
226 case WAN_SECRET_DOOR_DETECTION
:
230 case WAN_CREATE_MONSTER
:
236 (void) makemon((struct permonst
*) 0, u
.ux
, u
.uy
);
243 if (u
.uluck
+ rn2(5) < 0) {
244 pline("Unfortunately, nothing happens.");
247 pline("You may wish for an object. What do you want? ");
249 if (buf
[0] == '\033')
251 otmp
= readobjnam(buf
);
258 * Original effect (approximately): from CORR: dig
259 * until we pierce a wall from ROOM: piece wall and
260 * dig until we reach an ACCESSIBLE place. Currently:
261 * dig for digdepth positions; also down on request
262 * of Lennart Augustsson.
268 struct monst
*mtmp
= u
.ustuck
;
270 pline("You pierce %s's stomach wall!",
272 mtmp
->mhp
= 1; /* almost dead */
279 pline("You loosen a rock from the ceiling.");
280 pline("It falls on your head!");
281 losehp(1, "falling rock");
282 mksobj_at(ROCK
, u
.ux
, u
.uy
);
294 digdepth
= 8 + rn2(18);
295 Tmp_at(-1, '*'); /* open call */
296 while (--digdepth
>= 0) {
299 room
= &levl
[zx
][zy
];
302 if (zx
< 3 || zx
> COLNO
- 3 ||
303 zy
< 3 || zy
> ROWNO
- 3)
305 if (room
->typ
== HWALL
||
306 room
->typ
== VWALL
) {
310 } else if (room
->typ
== HWALL
|| room
->typ
== VWALL
||
311 room
->typ
== SDOOR
|| room
->typ
== LDOOR
) {
314 } else if (room
->typ
== SCORR
|| !room
->typ
) {
322 mnewsym(zx
, zy
); /* not always necessary */
323 Tmp_at(-1, -1); /* closing call */
327 buzz((int) obj
->otyp
- WAN_MAGIC_MISSILE
,
328 u
.ux
, u
.uy
, u
.dx
, u
.dy
);
331 if (!objects
[obj
->otyp
].oc_name_known
) {
332 objects
[obj
->otyp
].oc_name_known
= 1;
333 more_experienced(0, 10);
343 /* force == 0 occurs e.g. with sleep ray */
345 * note that large force is usual with wands so that !! would require
346 * information about hand/weapon/wand
348 return ((force
< 0) ? "?" : (force
<= 4) ? "." : "!");
352 hit(str
, mtmp
, force
)
355 const char *force
; /* usually either "." or "!" */
357 if (!cansee(mtmp
->mx
, mtmp
->my
))
358 pline("The %s hits it.", str
);
360 pline("The %s hits %s%s", str
, monnam(mtmp
), force
);
368 if (!cansee(mtmp
->mx
, mtmp
->my
))
369 pline("The %s misses it.", str
);
371 pline("The %s misses %s.", str
, monnam(mtmp
));
375 * bhit: called when a weapon is thrown (sym = obj->olet) or when an
376 * IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of range
377 * or when a monster is hit; the monster is returned, and bhitpos is set to
378 * the final position of the weapon thrown; the ray of a wand may affect
379 * several objects and monsters on its path - for each of these an argument
380 * function is called.
382 /* check !u.uswallow before calling bhit() */
385 bhit(ddx
, ddy
, range
, sym
, fhitm
, fhito
, obj
)
386 int ddx
, ddy
, range
; /* direction and range */
387 char sym
; /* symbol displayed on path */
388 /* fns called when mon/obj hit */
389 void (*fhitm
)(struct monst
*, struct obj
*);
390 int (*fhito
)(struct obj
*, struct obj
*);
391 struct obj
*obj
; /* 2nd arg to fhitm/fhito */
401 tmp_at(-1, sym
);/* open call */
402 while (range
-- > 0) {
405 typ
= levl
[bhitpos
.x
][bhitpos
.y
].typ
;
406 if ((mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)) != NULL
) {
408 tmp_at(-1, -1); /* close call */
411 (*fhitm
) (mtmp
, obj
);
414 if (fhito
&& (otmp
= o_at(bhitpos
.x
, bhitpos
.y
))) {
415 if ((*fhito
) (otmp
, obj
))
424 tmp_at(bhitpos
.x
, bhitpos
.y
);
427 /* leave last symbol unless in a pool */
429 tmp_at(-1, (levl
[bhitpos
.x
][bhitpos
.y
].typ
== POOL
) ? -1 : 0);
434 boomhit(int dx
, int dy
)
443 for (i
= 0; i
< 8; i
++)
444 if (xdir
[i
] == dx
&& ydir
[i
] == dy
)
446 tmp_at(-1, sym
); /* open call */
447 for (ct
= 0; ct
< 10; ct
++) {
450 sym
= ')' + '(' - sym
;
451 tmp_at(-2, sym
);/* change let call */
456 if ((mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)) != NULL
) {
460 if (!ZAP_POS(levl
[bhitpos
.x
][bhitpos
.y
].typ
)) {
465 if (bhitpos
.x
== u
.ux
&& bhitpos
.y
== u
.uy
) { /* ct == 9 */
466 if (rn2(20) >= 10 + u
.ulevel
) { /* we hit ourselves */
467 (void) thitu(10, rnd(10), "boomerang");
469 } else {/* we catch it */
471 pline("Skillfully, you catch the boomerang.");
475 tmp_at(bhitpos
.x
, bhitpos
.y
);
479 tmp_at(-1, -1); /* do not leave last symbol */
488 (dx
== dy
) ? '\\' : (dx
&& dy
) ? '/' : dx
? '-' : '|';
491 /* type == -1: monster spitting fire at you */
492 /* type == -1,-2,-3: bolts sent out by wizard */
493 /* called with dx = dy = 0 with vertical bolts */
495 buzz(type
, sx
, sy
, dx
, dy
)
500 int abstype
= abs(type
);
501 const char *fltxt
= (type
== -1) ? "blaze of fire" : fl
[abstype
];
511 tmp
= zhit(u
.ustuck
, type
);
512 pline("The %s rips into %s%s",
513 fltxt
, monnam(u
.ustuck
), exclam(tmp
));
519 Tmp_at(-1, dirlet(dx
, dy
)); /* open call */
520 while (range
-- > 0) {
523 if ((lev
= &levl
[sx
][sy
])->typ
)
527 if (cansee(sx
- dx
, sy
- dy
))
528 pline("The %s bounces!", fltxt
);
529 if (ZAP_POS(levl
[sx
][sy
- dy
].typ
))
531 if (ZAP_POS(levl
[sx
- dx
][sy
].typ
)) {
532 if (!bounce
|| rn2(2))
549 Tmp_at(-2, dirlet(dx
, dy
));
552 if (lev
->typ
== POOL
&& abstype
== 1 /* fire */ ) {
555 if (cansee(sx
, sy
)) {
557 pline("The water evaporates.");
559 pline("You hear a hissing sound.");
561 if ((mon
= m_at(sx
, sy
)) &&
562 (type
!= -1 || mon
->data
->mlet
!= 'D')) {
564 if (rnd(20) < 18 + mon
->data
->ac
) {
565 int tmp
= zhit(mon
, abstype
);
568 if (cansee(mon
->mx
, mon
->my
))
569 pline("%s is killed by the %s!",
575 hit(fltxt
, mon
, exclam(tmp
));
579 } else if (sx
== u
.ux
&& sy
== u
.uy
) {
581 if (rnd(20) < 18 + u
.uac
) {
584 pline("The %s hits you!", fltxt
);
591 pline("You don't feel hot!");
598 nomul(-rnd(25)); /* sleep ray */
602 pline("You don't feel cold!");
611 pline("The %s whizzes by you!", fltxt
);
614 if (!ZAP_POS(lev
->typ
)) {
617 pline("The %s bounces!", fltxt
);
619 if (!dx
|| !dy
|| !rn2(20)) {
623 if (ZAP_POS(rmn
= levl
[sx
][sy
- dy
].typ
) &&
624 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
+ dx
][sy
- dy
].typ
)))
626 if (ZAP_POS(rmn
= levl
[sx
- dx
][sy
].typ
) &&
627 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
- dx
][sy
+ dy
].typ
)))
628 if (!bounce
|| rn2(2))
643 Tmp_at(-2, dirlet(dx
, dy
));
651 zhit(mon
, type
) /* returns damage to mon */
658 case 0: /* magic missile */
661 case -1: /* Dragon blazing fire */
663 if (strchr("Dg", mon
->data
->mlet
))
666 if (strchr("YF", mon
->data
->mlet
))
673 if (strchr("YFgf", mon
->data
->mlet
))
676 if (mon
->data
->mlet
== 'D')
680 if (strchr(UNDEAD
, mon
->data
->mlet
))
689 #define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\
690 ? 'a' + (otyp - DEAD_ACID_BLOB)\
691 : '@' + (otyp - DEAD_HUMAN))
696 struct monst
*mtmp
= NULL
;
698 if (obj
->olet
== FOOD_SYM
&& obj
->otyp
> CORPSE
) {
699 /* do not (yet) revive shopkeepers */
701 * Note: this might conceivably produce two monsters at the
702 * same position - strange, but harmless
704 mtmp
= mkmon_at(CORPSE_I_TO_C(obj
->otyp
), obj
->ox
, obj
->oy
);
707 return (!!mtmp
); /* TRUE if some monster created */
714 int tx
, ty
, otx
, oty
;
719 tx
= rn1(COLNO
- 3, 2);
721 } while (!goodpos(tx
, ty
));
724 if (cansee(otx
, oty
))
729 fracture_rock(obj
) /* fractured by pick-axe or wand of striking */
730 struct obj
*obj
; /* no texts here! */
734 obj
->quan
= 7 + rn2(60);
735 obj
->owt
= weight(obj
);
736 obj
->olet
= WEAPON_SYM
;
737 if (cansee(obj
->ox
, obj
->oy
))
738 prl(obj
->ox
, obj
->oy
);
744 struct obj
*obj
, *obj2
;
747 for (obj
= invent
; obj
; obj
= obj2
) {
749 if (obj
->olet
== SCROLL_SYM
) {
755 pline("Your scrolls catch fire!");
756 losehp(cnt
, "burning scrolls");
758 pline("Your scroll catches fire!");
759 losehp(1, "burning scroll");