1 /* $NetBSD: hack.zap.c,v 1.9 2009/08/12 07:28:41 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.
67 static const char *const fl
[] = {
75 static void bhitm(struct monst
*, struct obj
*);
76 static int bhito(struct obj
*, struct obj
*);
77 static char dirlet(int, int);
78 static int zhit(struct monst
*, int);
79 static int revive(struct obj
*);
80 static void rloco(struct obj
*);
81 static void burn_scrolls(void);
83 /* Routines for IMMEDIATE wands. */
84 /* bhitm: monster mtmp was hit by the effect of wand otmp */
86 bhitm(struct monst
*mtmp
, struct obj
*otmp
)
91 if (u
.uswallow
|| rnd(20) < 10 + mtmp
->data
->ac
) {
93 hit("wand", mtmp
, exclam(tmp
));
100 case WAN_SLOW_MONSTER
:
101 mtmp
->mspeed
= MSLOW
;
103 case WAN_SPEED_MONSTER
:
104 mtmp
->mspeed
= MFAST
;
106 case WAN_UNDEAD_TURNING
:
107 if (strchr(UNDEAD
, mtmp
->data
->mlet
)) {
116 if (newcham(mtmp
, &mons
[rn2(CMNUM
)]))
117 objects
[otmp
->otyp
].oc_name_known
= 1;
119 case WAN_CANCELLATION
:
122 case WAN_TELEPORTATION
:
125 case WAN_MAKE_INVISIBLE
:
132 #endif /* WAN_PROBING */
134 impossible("What an interesting wand (%u)", otmp
->otyp
);
139 * object obj was hit by the effect of wand otmp
140 * returns TRUE if sth was done
143 bhito(struct obj
*obj
, struct obj
*otmp
)
147 if (obj
== uball
|| obj
== uchain
)
150 switch (otmp
->otyp
) {
153 * preserve symbol and quantity, but turn rocks into
156 mkobj_at((obj
->otyp
== ROCK
|| obj
->otyp
== ENORMOUS_ROCK
)
157 ? GEM_SYM
: obj
->olet
,
158 obj
->ox
, obj
->oy
)->quan
= obj
->quan
;
162 if (obj
->otyp
== ENORMOUS_ROCK
)
167 case WAN_CANCELLATION
:
168 if (obj
->spe
&& obj
->olet
!= AMULET_SYM
) {
173 case WAN_TELEPORTATION
:
176 case WAN_MAKE_INVISIBLE
:
179 case WAN_UNDEAD_TURNING
:
182 case WAN_SLOW_MONSTER
: /* no effect on objects */
183 case WAN_SPEED_MONSTER
:
186 #endif /* WAN_PROBING */
190 impossible("What an interesting wand (%u)", otmp
->otyp
);
201 obj
= getobj("/", "zap");
204 if (obj
->spe
< 0 || (obj
->spe
== 0 && rn2(121))) {
205 pline("Nothing Happens.");
209 pline("You wrest one more spell from the worn-out wand.");
210 if (!(objects
[obj
->otyp
].bits
& NODIR
) && !getdir(1))
211 return (1); /* make him pay for knowing !NODIR */
213 if (objects
[obj
->otyp
].bits
& IMMEDIATE
) {
215 bhitm(u
.ustuck
, obj
);
218 struct obj
*otmp
= o_at(u
.ux
, u
.uy
);
220 (void) bhito(otmp
, obj
);
223 (void) bhit(u
.dx
, u
.dy
, rn1(8, 6), 0, bhitm
, bhito
, obj
);
229 case WAN_SECRET_DOOR_DETECTION
:
233 case WAN_CREATE_MONSTER
:
239 (void) makemon((struct permonst
*) 0, u
.ux
, u
.uy
);
246 if (u
.uluck
+ rn2(5) < 0) {
247 pline("Unfortunately, nothing happens.");
250 pline("You may wish for an object. What do you want? ");
252 if (buf
[0] == '\033')
254 otmp
= readobjnam(buf
);
261 * Original effect (approximately): from CORR: dig
262 * until we pierce a wall from ROOM: piece wall and
263 * dig until we reach an ACCESSIBLE place. Currently:
264 * dig for digdepth positions; also down on request
265 * of Lennart Augustsson.
271 struct monst
*mtmp
= u
.ustuck
;
273 pline("You pierce %s's stomach wall!",
275 mtmp
->mhp
= 1; /* almost dead */
282 pline("You loosen a rock from the ceiling.");
283 pline("It falls on your head!");
284 losehp(1, "falling rock");
285 mksobj_at(ROCK
, u
.ux
, u
.uy
);
297 digdepth
= 8 + rn2(18);
298 Tmp_at(-1, '*'); /* open call */
299 while (--digdepth
>= 0) {
302 room
= &levl
[zx
][zy
];
305 if (zx
< 3 || zx
> COLNO
- 3 ||
306 zy
< 3 || zy
> ROWNO
- 3)
308 if (room
->typ
== HWALL
||
309 room
->typ
== VWALL
) {
313 } else if (room
->typ
== HWALL
|| room
->typ
== VWALL
||
314 room
->typ
== SDOOR
|| room
->typ
== LDOOR
) {
317 } else if (room
->typ
== SCORR
|| !room
->typ
) {
325 mnewsym(zx
, zy
); /* not always necessary */
326 Tmp_at(-1, -1); /* closing call */
330 buzz((int) obj
->otyp
- WAN_MAGIC_MISSILE
,
331 u
.ux
, u
.uy
, u
.dx
, u
.dy
);
334 if (!objects
[obj
->otyp
].oc_name_known
) {
335 objects
[obj
->otyp
].oc_name_known
= 1;
336 more_experienced(0, 10);
345 /* force == 0 occurs e.g. with sleep ray */
347 * note that large force is usual with wands so that !! would require
348 * information about hand/weapon/wand
350 return ((force
< 0) ? "?" : (force
<= 4) ? "." : "!");
354 hit(const char *str
, struct monst
*mtmp
, const char *force
)
356 /* force is usually either "." or "!" */
358 if (!cansee(mtmp
->mx
, mtmp
->my
))
359 pline("The %s hits it.", str
);
361 pline("The %s hits %s%s", str
, monnam(mtmp
), force
);
365 miss(const char *str
, struct monst
*mtmp
)
367 if (!cansee(mtmp
->mx
, mtmp
->my
))
368 pline("The %s misses it.", str
);
370 pline("The %s misses %s.", str
, monnam(mtmp
));
374 * bhit: called when a weapon is thrown (sym = obj->olet) or when an
375 * IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of range
376 * or when a monster is hit; the monster is returned, and bhitpos is set to
377 * the final position of the weapon thrown; the ray of a wand may affect
378 * several objects and monsters on its path - for each of these an argument
379 * function is called.
381 /* check !u.uswallow before calling bhit() */
384 bhit(int ddx
, int ddy
, int range
, /* direction and range */
385 int sym
, /* symbol displayed on path */
386 /* fns called when mon/obj hit */
387 void (*fhitm
)(struct monst
*, struct obj
*),
388 int (*fhito
)(struct obj
*, struct obj
*),
389 struct obj
*obj
) /* 2nd arg to fhitm/fhito */
399 tmp_at(-1, sym
);/* open call */
400 while (range
-- > 0) {
403 typ
= levl
[bhitpos
.x
][bhitpos
.y
].typ
;
404 if ((mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)) != NULL
) {
406 tmp_at(-1, -1); /* close call */
409 (*fhitm
) (mtmp
, obj
);
412 if (fhito
&& (otmp
= o_at(bhitpos
.x
, bhitpos
.y
))) {
413 if ((*fhito
) (otmp
, obj
))
422 tmp_at(bhitpos
.x
, bhitpos
.y
);
425 /* leave last symbol unless in a pool */
427 tmp_at(-1, (levl
[bhitpos
.x
][bhitpos
.y
].typ
== POOL
) ? -1 : 0);
432 boomhit(int dx
, int dy
)
441 for (i
= 0; i
< 8; i
++)
442 if (xdir
[i
] == dx
&& ydir
[i
] == dy
)
444 tmp_at(-1, sym
); /* open call */
445 for (ct
= 0; ct
< 10; ct
++) {
448 sym
= ')' + '(' - sym
;
449 tmp_at(-2, sym
);/* change let call */
454 if ((mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)) != NULL
) {
458 if (!ZAP_POS(levl
[bhitpos
.x
][bhitpos
.y
].typ
)) {
463 if (bhitpos
.x
== u
.ux
&& bhitpos
.y
== u
.uy
) { /* ct == 9 */
464 if (rn2(20) >= 10 + u
.ulevel
) { /* we hit ourselves */
465 (void) thitu(10, rnd(10), "boomerang");
467 } else {/* we catch it */
469 pline("Skillfully, you catch the boomerang.");
473 tmp_at(bhitpos
.x
, bhitpos
.y
);
477 tmp_at(-1, -1); /* do not leave last symbol */
482 dirlet(int dx
, int dy
)
485 (dx
== dy
) ? '\\' : (dx
&& dy
) ? '/' : dx
? '-' : '|';
488 /* type == -1: monster spitting fire at you */
489 /* type == -1,-2,-3: bolts sent out by wizard */
490 /* called with dx = dy = 0 with vertical bolts */
492 buzz(int type
, xchar sx
, xchar sy
, int dx
, int dy
)
494 int abstype
= abs(type
);
495 const char *fltxt
= (type
== -1) ? "blaze of fire" : fl
[abstype
];
505 tmp
= zhit(u
.ustuck
, type
);
506 pline("The %s rips into %s%s",
507 fltxt
, monnam(u
.ustuck
), exclam(tmp
));
513 Tmp_at(-1, dirlet(dx
, dy
)); /* open call */
514 while (range
-- > 0) {
517 if ((lev
= &levl
[sx
][sy
])->typ
)
521 if (cansee(sx
- dx
, sy
- dy
))
522 pline("The %s bounces!", fltxt
);
523 if (ZAP_POS(levl
[sx
][sy
- dy
].typ
))
525 if (ZAP_POS(levl
[sx
- dx
][sy
].typ
)) {
526 if (!bounce
|| rn2(2))
543 Tmp_at(-2, dirlet(dx
, dy
));
546 if (lev
->typ
== POOL
&& abstype
== 1 /* fire */ ) {
549 if (cansee(sx
, sy
)) {
551 pline("The water evaporates.");
553 pline("You hear a hissing sound.");
555 if ((mon
= m_at(sx
, sy
)) &&
556 (type
!= -1 || mon
->data
->mlet
!= 'D')) {
558 if (rnd(20) < 18 + mon
->data
->ac
) {
559 int tmp
= zhit(mon
, abstype
);
562 if (cansee(mon
->mx
, mon
->my
))
563 pline("%s is killed by the %s!",
569 hit(fltxt
, mon
, exclam(tmp
));
573 } else if (sx
== u
.ux
&& sy
== u
.uy
) {
575 if (rnd(20) < 18 + u
.uac
) {
578 pline("The %s hits you!", fltxt
);
585 pline("You don't feel hot!");
592 nomul(-rnd(25)); /* sleep ray */
596 pline("You don't feel cold!");
605 pline("The %s whizzes by you!", fltxt
);
608 if (!ZAP_POS(lev
->typ
)) {
611 pline("The %s bounces!", fltxt
);
613 if (!dx
|| !dy
|| !rn2(20)) {
617 if (ZAP_POS(rmn
= levl
[sx
][sy
- dy
].typ
) &&
618 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
+ dx
][sy
- dy
].typ
)))
620 if (ZAP_POS(rmn
= levl
[sx
- dx
][sy
].typ
) &&
621 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
- dx
][sy
+ dy
].typ
)))
622 if (!bounce
|| rn2(2))
637 Tmp_at(-2, dirlet(dx
, dy
));
645 zhit(struct monst
*mon
, int type
) /* returns damage to mon */
650 case 0: /* magic missile */
653 case -1: /* Dragon blazing fire */
655 if (strchr("Dg", mon
->data
->mlet
))
658 if (strchr("YF", mon
->data
->mlet
))
665 if (strchr("YFgf", mon
->data
->mlet
))
668 if (mon
->data
->mlet
== 'D')
672 if (strchr(UNDEAD
, mon
->data
->mlet
))
681 #define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\
682 ? 'a' + (otyp - DEAD_ACID_BLOB)\
683 : '@' + (otyp - DEAD_HUMAN))
685 revive(struct obj
*obj
)
687 struct monst
*mtmp
= NULL
;
689 if (obj
->olet
== FOOD_SYM
&& obj
->otyp
> CORPSE
) {
690 /* do not (yet) revive shopkeepers */
692 * Note: this might conceivably produce two monsters at the
693 * same position - strange, but harmless
695 mtmp
= mkmon_at(CORPSE_I_TO_C(obj
->otyp
), obj
->ox
, obj
->oy
);
698 return (!!mtmp
); /* TRUE if some monster created */
702 rloco(struct obj
*obj
)
704 int tx
, ty
, otx
, oty
;
709 tx
= rn1(COLNO
- 3, 2);
711 } while (!goodpos(tx
, ty
));
714 if (cansee(otx
, oty
))
718 /* fractured by pick-axe or wand of striking */
721 fracture_rock(struct obj
*obj
)
725 obj
->quan
= 7 + rn2(60);
726 obj
->owt
= weight(obj
);
727 obj
->olet
= WEAPON_SYM
;
728 if (cansee(obj
->ox
, obj
->oy
))
729 prl(obj
->ox
, obj
->oy
);
735 struct obj
*obj
, *obj2
;
738 for (obj
= invent
; obj
; obj
= obj2
) {
740 if (obj
->olet
== SCROLL_SYM
) {
746 pline("Your scrolls catch fire!");
747 losehp(cnt
, "burning scrolls");
749 pline("Your scroll catches fire!");
750 losehp(1, "burning scroll");