1 /* $NetBSD: hack.zap.c,v 1.5 2001/03/25 20:44:04 jsm Exp $ */
4 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
9 __RCSID("$NetBSD: hack.zap.c,v 1.5 2001/03/25 20:44:04 jsm Exp $");
15 const char *const fl
[] = {
23 /* Routines for IMMEDIATE wands. */
24 /* bhitm: monster mtmp was hit by the effect of wand otmp */
33 if (u
.uswallow
|| rnd(20) < 10 + mtmp
->data
->ac
) {
35 hit("wand", mtmp
, exclam(tmp
));
42 case WAN_SLOW_MONSTER
:
45 case WAN_SPEED_MONSTER
:
48 case WAN_UNDEAD_TURNING
:
49 if (strchr(UNDEAD
, mtmp
->data
->mlet
)) {
58 if (newcham(mtmp
, &mons
[rn2(CMNUM
)]))
59 objects
[otmp
->otyp
].oc_name_known
= 1;
61 case WAN_CANCELLATION
:
64 case WAN_TELEPORTATION
:
67 case WAN_MAKE_INVISIBLE
:
74 #endif /* WAN_PROBING */
76 impossible("What an interesting wand (%u)", otmp
->otyp
);
81 bhito(obj
, otmp
) /* object obj was hit by the effect of wand
83 struct obj
*obj
, *otmp
; /* returns TRUE if sth was done */
87 if (obj
== uball
|| obj
== uchain
)
93 * preserve symbol and quantity, but turn rocks into
96 mkobj_at((obj
->otyp
== ROCK
|| obj
->otyp
== ENORMOUS_ROCK
)
97 ? GEM_SYM
: obj
->olet
,
98 obj
->ox
, obj
->oy
)->quan
= obj
->quan
;
102 if (obj
->otyp
== ENORMOUS_ROCK
)
107 case WAN_CANCELLATION
:
108 if (obj
->spe
&& obj
->olet
!= AMULET_SYM
) {
113 case WAN_TELEPORTATION
:
116 case WAN_MAKE_INVISIBLE
:
119 case WAN_UNDEAD_TURNING
:
122 case WAN_SLOW_MONSTER
: /* no effect on objects */
123 case WAN_SPEED_MONSTER
:
126 #endif /* WAN_PROBING */
130 impossible("What an interesting wand (%u)", otmp
->otyp
);
141 obj
= getobj("/", "zap");
144 if (obj
->spe
< 0 || (obj
->spe
== 0 && rn2(121))) {
145 pline("Nothing Happens.");
149 pline("You wrest one more spell from the worn-out wand.");
150 if (!(objects
[obj
->otyp
].bits
& NODIR
) && !getdir(1))
151 return (1); /* make him pay for knowing !NODIR */
153 if (objects
[obj
->otyp
].bits
& IMMEDIATE
) {
155 bhitm(u
.ustuck
, obj
);
158 struct obj
*otmp
= o_at(u
.ux
, u
.uy
);
160 (void) bhito(otmp
, obj
);
163 (void) bhit(u
.dx
, u
.dy
, rn1(8, 6), 0, bhitm
, bhito
, obj
);
169 case WAN_SECRET_DOOR_DETECTION
:
173 case WAN_CREATE_MONSTER
:
179 (void) makemon((struct permonst
*) 0, u
.ux
, u
.uy
);
186 if (u
.uluck
+ rn2(5) < 0) {
187 pline("Unfortunately, nothing happens.");
190 pline("You may wish for an object. What do you want? ");
192 if (buf
[0] == '\033')
194 otmp
= readobjnam(buf
);
201 * Original effect (approximately): from CORR: dig
202 * until we pierce a wall from ROOM: piece wall and
203 * dig until we reach an ACCESSIBLE place. Currently:
204 * dig for digdepth positions; also down on request
205 * of Lennart Augustsson.
211 struct monst
*mtmp
= u
.ustuck
;
213 pline("You pierce %s's stomach wall!",
215 mtmp
->mhp
= 1; /* almost dead */
222 pline("You loosen a rock from the ceiling.");
223 pline("It falls on your head!");
224 losehp(1, "falling rock");
225 mksobj_at(ROCK
, u
.ux
, u
.uy
);
237 digdepth
= 8 + rn2(18);
238 Tmp_at(-1, '*'); /* open call */
239 while (--digdepth
>= 0) {
242 room
= &levl
[zx
][zy
];
245 if (zx
< 3 || zx
> COLNO
- 3 ||
246 zy
< 3 || zy
> ROWNO
- 3)
248 if (room
->typ
== HWALL
||
249 room
->typ
== VWALL
) {
253 } else if (room
->typ
== HWALL
|| room
->typ
== VWALL
||
254 room
->typ
== SDOOR
|| room
->typ
== LDOOR
) {
257 } else if (room
->typ
== SCORR
|| !room
->typ
) {
265 mnewsym(zx
, zy
); /* not always necessary */
266 Tmp_at(-1, -1); /* closing call */
270 buzz((int) obj
->otyp
- WAN_MAGIC_MISSILE
,
271 u
.ux
, u
.uy
, u
.dx
, u
.dy
);
274 if (!objects
[obj
->otyp
].oc_name_known
) {
275 objects
[obj
->otyp
].oc_name_known
= 1;
276 more_experienced(0, 10);
286 /* force == 0 occurs e.g. with sleep ray */
288 * note that large force is usual with wands so that !! would require
289 * information about hand/weapon/wand
291 return ((force
< 0) ? "?" : (force
<= 4) ? "." : "!");
295 hit(str
, mtmp
, force
)
298 const char *force
; /* usually either "." or "!" */
300 if (!cansee(mtmp
->mx
, mtmp
->my
))
301 pline("The %s hits it.", str
);
303 pline("The %s hits %s%s", str
, monnam(mtmp
), force
);
311 if (!cansee(mtmp
->mx
, mtmp
->my
))
312 pline("The %s misses it.", str
);
314 pline("The %s misses %s.", str
, monnam(mtmp
));
318 * bhit: called when a weapon is thrown (sym = obj->olet) or when an
319 * IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of range
320 * or when a monster is hit; the monster is returned, and bhitpos is set to
321 * the final position of the weapon thrown; the ray of a wand may affect
322 * several objects and monsters on its path - for each of these an argument
323 * function is called.
325 /* check !u.uswallow before calling bhit() */
328 bhit(ddx
, ddy
, range
, sym
, fhitm
, fhito
, obj
)
329 int ddx
, ddy
, range
; /* direction and range */
330 char sym
; /* symbol displayed on path */
331 /* fns called when mon/obj hit */
332 void (*fhitm
) __P((struct monst
*, struct obj
*));
333 int (*fhito
) __P((struct obj
*, struct obj
*));
334 struct obj
*obj
; /* 2nd arg to fhitm/fhito */
344 tmp_at(-1, sym
);/* open call */
345 while (range
-- > 0) {
348 typ
= levl
[bhitpos
.x
][bhitpos
.y
].typ
;
349 if ((mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)) != NULL
) {
351 tmp_at(-1, -1); /* close call */
354 (*fhitm
) (mtmp
, obj
);
357 if (fhito
&& (otmp
= o_at(bhitpos
.x
, bhitpos
.y
))) {
358 if ((*fhito
) (otmp
, obj
))
367 tmp_at(bhitpos
.x
, bhitpos
.y
);
370 /* leave last symbol unless in a pool */
372 tmp_at(-1, (levl
[bhitpos
.x
][bhitpos
.y
].typ
== POOL
) ? -1 : 0);
377 boomhit(int dx
, int dy
)
386 for (i
= 0; i
< 8; i
++)
387 if (xdir
[i
] == dx
&& ydir
[i
] == dy
)
389 tmp_at(-1, sym
); /* open call */
390 for (ct
= 0; ct
< 10; ct
++) {
393 sym
= ')' + '(' - sym
;
394 tmp_at(-2, sym
);/* change let call */
399 if ((mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)) != NULL
) {
403 if (!ZAP_POS(levl
[bhitpos
.x
][bhitpos
.y
].typ
)) {
408 if (bhitpos
.x
== u
.ux
&& bhitpos
.y
== u
.uy
) { /* ct == 9 */
409 if (rn2(20) >= 10 + u
.ulevel
) { /* we hit ourselves */
410 (void) thitu(10, rnd(10), "boomerang");
412 } else {/* we catch it */
414 pline("Skillfully, you catch the boomerang.");
418 tmp_at(bhitpos
.x
, bhitpos
.y
);
422 tmp_at(-1, -1); /* do not leave last symbol */
431 (dx
== dy
) ? '\\' : (dx
&& dy
) ? '/' : dx
? '-' : '|';
434 /* type == -1: monster spitting fire at you */
435 /* type == -1,-2,-3: bolts sent out by wizard */
436 /* called with dx = dy = 0 with vertical bolts */
438 buzz(type
, sx
, sy
, dx
, dy
)
443 int abstype
= abs(type
);
444 const char *fltxt
= (type
== -1) ? "blaze of fire" : fl
[abstype
];
454 tmp
= zhit(u
.ustuck
, type
);
455 pline("The %s rips into %s%s",
456 fltxt
, monnam(u
.ustuck
), exclam(tmp
));
462 Tmp_at(-1, dirlet(dx
, dy
)); /* open call */
463 while (range
-- > 0) {
466 if ((lev
= &levl
[sx
][sy
])->typ
)
470 if (cansee(sx
- dx
, sy
- dy
))
471 pline("The %s bounces!", fltxt
);
472 if (ZAP_POS(levl
[sx
][sy
- dy
].typ
))
474 if (ZAP_POS(levl
[sx
- dx
][sy
].typ
)) {
475 if (!bounce
|| rn2(2))
492 Tmp_at(-2, dirlet(dx
, dy
));
495 if (lev
->typ
== POOL
&& abstype
== 1 /* fire */ ) {
498 if (cansee(sx
, sy
)) {
500 pline("The water evaporates.");
502 pline("You hear a hissing sound.");
504 if ((mon
= m_at(sx
, sy
)) &&
505 (type
!= -1 || mon
->data
->mlet
!= 'D')) {
507 if (rnd(20) < 18 + mon
->data
->ac
) {
508 int tmp
= zhit(mon
, abstype
);
511 if (cansee(mon
->mx
, mon
->my
))
512 pline("%s is killed by the %s!",
518 hit(fltxt
, mon
, exclam(tmp
));
522 } else if (sx
== u
.ux
&& sy
== u
.uy
) {
524 if (rnd(20) < 18 + u
.uac
) {
527 pline("The %s hits you!", fltxt
);
534 pline("You don't feel hot!");
541 nomul(-rnd(25)); /* sleep ray */
545 pline("You don't feel cold!");
554 pline("The %s whizzes by you!", fltxt
);
557 if (!ZAP_POS(lev
->typ
)) {
560 pline("The %s bounces!", fltxt
);
562 if (!dx
|| !dy
|| !rn2(20)) {
566 if (ZAP_POS(rmn
= levl
[sx
][sy
- dy
].typ
) &&
567 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
+ dx
][sy
- dy
].typ
)))
569 if (ZAP_POS(rmn
= levl
[sx
- dx
][sy
].typ
) &&
570 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
- dx
][sy
+ dy
].typ
)))
571 if (!bounce
|| rn2(2))
586 Tmp_at(-2, dirlet(dx
, dy
));
594 zhit(mon
, type
) /* returns damage to mon */
601 case 0: /* magic missile */
604 case -1: /* Dragon blazing fire */
606 if (strchr("Dg", mon
->data
->mlet
))
609 if (strchr("YF", mon
->data
->mlet
))
616 if (strchr("YFgf", mon
->data
->mlet
))
619 if (mon
->data
->mlet
== 'D')
623 if (strchr(UNDEAD
, mon
->data
->mlet
))
632 #define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\
633 ? 'a' + (otyp - DEAD_ACID_BLOB)\
634 : '@' + (otyp - DEAD_HUMAN))
639 struct monst
*mtmp
= NULL
;
641 if (obj
->olet
== FOOD_SYM
&& obj
->otyp
> CORPSE
) {
642 /* do not (yet) revive shopkeepers */
644 * Note: this might conceivably produce two monsters at the
645 * same position - strange, but harmless
647 mtmp
= mkmon_at(CORPSE_I_TO_C(obj
->otyp
), obj
->ox
, obj
->oy
);
650 return (!!mtmp
); /* TRUE if some monster created */
657 int tx
, ty
, otx
, oty
;
662 tx
= rn1(COLNO
- 3, 2);
664 } while (!goodpos(tx
, ty
));
667 if (cansee(otx
, oty
))
672 fracture_rock(obj
) /* fractured by pick-axe or wand of striking */
673 struct obj
*obj
; /* no texts here! */
677 obj
->quan
= 7 + rn2(60);
678 obj
->owt
= weight(obj
);
679 obj
->olet
= WEAPON_SYM
;
680 if (cansee(obj
->ox
, obj
->oy
))
681 prl(obj
->ox
, obj
->oy
);
687 struct obj
*obj
, *obj2
;
690 for (obj
= invent
; obj
; obj
= obj2
) {
692 if (obj
->olet
== SCROLL_SYM
) {
698 pline("Your scrolls catch fire!");
699 losehp(cnt
, "burning scrolls");
701 pline("Your scroll catches fire!");
702 losehp(1, "burning scroll");