2 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
6 static char rcsid
[] = "$NetBSD: hack.zap.c,v 1.3 1995/03/23 08:32:21 cgd Exp $";
11 extern struct obj
*mkobj_at();
12 extern struct monst
*makemon(), *mkmon_at(), youmonst
;
24 /* Routines for IMMEDIATE wands. */
25 /* bhitm: monster mtmp was hit by the effect of wand otmp */
27 register struct monst
*mtmp
;
28 register struct obj
*otmp
;
33 if(u
.uswallow
|| rnd(20) < 10+mtmp
->data
->ac
) {
34 register int tmp
= d(2,12);
35 hit("wand", mtmp
, exclam(tmp
));
37 if(mtmp
->mhp
< 1) killed(mtmp
);
38 } else miss("wand", mtmp
);
40 case WAN_SLOW_MONSTER
:
43 case WAN_SPEED_MONSTER
:
46 case WAN_UNDEAD_TURNING
:
47 if(index(UNDEAD
,mtmp
->data
->mlet
)) {
49 if(mtmp
->mhp
< 1) killed(mtmp
);
54 if( newcham(mtmp
,&mons
[rn2(CMNUM
)]) )
55 objects
[otmp
->otyp
].oc_name_known
= 1;
57 case WAN_CANCELLATION
:
60 case WAN_TELEPORTATION
:
63 case WAN_MAKE_INVISIBLE
:
72 impossible("What an interesting wand (%u)", otmp
->otyp
);
76 bhito(obj
, otmp
) /* object obj was hit by the effect of wand otmp */
77 register struct obj
*obj
, *otmp
; /* returns TRUE if sth was done */
79 register int res
= TRUE
;
81 if(obj
== uball
|| obj
== uchain
)
86 /* preserve symbol and quantity, but turn rocks into gems */
87 mkobj_at((obj
->otyp
== ROCK
|| obj
->otyp
== ENORMOUS_ROCK
)
88 ? GEM_SYM
: obj
->olet
,
89 obj
->ox
, obj
->oy
) -> quan
= obj
->quan
;
93 if(obj
->otyp
== ENORMOUS_ROCK
)
98 case WAN_CANCELLATION
:
99 if(obj
->spe
&& obj
->olet
!= AMULET_SYM
) {
104 case WAN_TELEPORTATION
:
107 case WAN_MAKE_INVISIBLE
:
110 case WAN_UNDEAD_TURNING
:
113 case WAN_SLOW_MONSTER
: /* no effect on objects */
114 case WAN_SPEED_MONSTER
:
121 impossible("What an interesting wand (%u)", otmp
->otyp
);
128 register struct obj
*obj
;
131 obj
= getobj("/", "zap");
133 if(obj
->spe
< 0 || (obj
->spe
== 0 && rn2(121))) {
134 pline("Nothing Happens.");
138 pline("You wrest one more spell from the worn-out wand.");
139 if(!(objects
[obj
->otyp
].bits
& NODIR
) && !getdir(1))
140 return(1); /* make him pay for knowing !NODIR */
142 if(objects
[obj
->otyp
].bits
& IMMEDIATE
) {
144 bhitm(u
.ustuck
, obj
);
147 register struct obj
*otmp
= o_at(u
.ux
, u
.uy
);
149 (void) bhito(otmp
, obj
);
152 (void) bhit(u
.dx
,u
.dy
,rn1(8,6),0,bhitm
,bhito
,obj
);
158 case WAN_SECRET_DOOR_DETECTION
:
159 if(!findit()) return(1);
161 case WAN_CREATE_MONSTER
:
162 { register int cnt
= 1;
163 if(!rn2(23)) cnt
+= rn2(7) + 1;
165 (void) makemon((struct permonst
*) 0, u
.ux
, u
.uy
);
170 register struct obj
*otmp
;
171 extern struct obj
*readobjnam(), *addinv();
172 if(u
.uluck
+ rn2(5) < 0) {
173 pline("Unfortunately, nothing happens.");
176 pline("You may wish for an object. What do you want? ");
178 if(buf
[0] == '\033') buf
[0] = 0;
179 otmp
= readobjnam(buf
);
185 /* Original effect (approximately):
186 * from CORR: dig until we pierce a wall
187 * from ROOM: piece wall and dig until we reach
188 * an ACCESSIBLE place.
189 * Currently: dig for digdepth positions;
190 * also down on request of Lennart Augustsson.
192 { register struct rm
*room
;
193 register int digdepth
;
195 register struct monst
*mtmp
= u
.ustuck
;
197 pline("You pierce %s's stomach wall!",
199 mtmp
->mhp
= 1; /* almost dead */
206 pline("You loosen a rock from the ceiling.");
207 pline("It falls on your head!");
208 losehp(1, "falling rock");
209 mksobj_at(ROCK
, u
.ux
, u
.uy
);
212 if(Invisible
) newsym(u
.ux
, u
.uy
);
220 digdepth
= 8 + rn2(18);
221 Tmp_at(-1, '*'); /* open call */
222 while(--digdepth
>= 0) {
223 if(!isok(zx
,zy
)) break;
224 room
= &levl
[zx
][zy
];
227 if(zx
< 3 || zx
> COLNO
-3 ||
228 zy
< 3 || zy
> ROWNO
-3)
230 if(room
->typ
== HWALL
||
236 if(room
->typ
== HWALL
|| room
->typ
== VWALL
||
237 room
->typ
== SDOOR
|| room
->typ
== LDOOR
){
241 if(room
->typ
== SCORR
|| !room
->typ
) {
249 mnewsym(zx
,zy
); /* not always necessary */
250 Tmp_at(-1,-1); /* closing call */
254 buzz((int) obj
->otyp
- WAN_MAGIC_MISSILE
,
255 u
.ux
, u
.uy
, u
.dx
, u
.dy
);
258 if(!objects
[obj
->otyp
].oc_name_known
) {
259 objects
[obj
->otyp
].oc_name_known
= 1;
260 more_experienced(0,10);
270 /* force == 0 occurs e.g. with sleep ray */
271 /* note that large force is usual with wands so that !! would
272 require information about hand/weapon/wand */
273 return( (force
< 0) ? "?" : (force
<= 4) ? "." : "!" );
278 register struct monst
*mtmp
;
279 register char *force
; /* usually either "." or "!" */
281 if(!cansee(mtmp
->mx
,mtmp
->my
)) pline("The %s hits it.", str
);
282 else pline("The %s hits %s%s", str
, monnam(mtmp
), force
);
287 register struct monst
*mtmp
;
289 if(!cansee(mtmp
->mx
,mtmp
->my
)) pline("The %s misses it.",str
);
290 else pline("The %s misses %s.",str
,monnam(mtmp
));
293 /* bhit: called when a weapon is thrown (sym = obj->olet) or when an
294 IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of
295 range or when a monster is hit; the monster is returned, and bhitpos
296 is set to the final position of the weapon thrown; the ray of a wand
297 may affect several objects and monsters on its path - for each of
298 these an argument function is called. */
299 /* check !u.uswallow before calling bhit() */
302 bhit(ddx
,ddy
,range
,sym
,fhitm
,fhito
,obj
)
303 register int ddx
,ddy
,range
; /* direction and range */
304 char sym
; /* symbol displayed on path */
305 int (*fhitm
)(), (*fhito
)(); /* fns called when mon/obj hit */
306 struct obj
*obj
; /* 2nd arg to fhitm/fhito */
308 register struct monst
*mtmp
;
309 register struct obj
*otmp
;
315 if(sym
) tmp_at(-1, sym
); /* open call */
319 typ
= levl
[bhitpos
.x
][bhitpos
.y
].typ
;
320 if(mtmp
= m_at(bhitpos
.x
,bhitpos
.y
)){
322 tmp_at(-1, -1); /* close call */
328 if(fhito
&& (otmp
= o_at(bhitpos
.x
,bhitpos
.y
))){
329 if((*fhito
)(otmp
, obj
))
337 if(sym
) tmp_at(bhitpos
.x
, bhitpos
.y
);
340 /* leave last symbol unless in a pool */
342 tmp_at(-1, (levl
[bhitpos
.x
][bhitpos
.y
].typ
== POOL
) ? -1 : 0);
349 register struct monst
*mtmp
;
351 extern schar xdir
[], ydir
[];
356 for(i
=0; i
<8; i
++) if(xdir
[i
] == dx
&& ydir
[i
] == dy
) break;
357 tmp_at(-1, sym
); /* open call */
358 for(ct
=0; ct
<10; ct
++) {
360 sym
= ')' + '(' - sym
;
361 tmp_at(-2, sym
); /* change let call */
366 if(mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)){
370 if(!ZAP_POS(levl
[bhitpos
.x
][bhitpos
.y
].typ
)) {
375 if(bhitpos
.x
== u
.ux
&& bhitpos
.y
== u
.uy
) { /* ct == 9 */
376 if(rn2(20) >= 10+u
.ulevel
){ /* we hit ourselves */
377 (void) thitu(10, rnd(10), "boomerang");
379 } else { /* we catch it */
381 pline("Skillfully, you catch the boomerang.");
385 tmp_at(bhitpos
.x
, bhitpos
.y
);
388 tmp_at(-1, -1); /* do not leave last symbol */
393 dirlet(dx
,dy
) register dx
,dy
; {
395 (dx
== dy
) ? '\\' : (dx
&& dy
) ? '/' : dx
? '-' : '|';
398 /* type == -1: monster spitting fire at you */
399 /* type == -1,-2,-3: bolts sent out by wizard */
400 /* called with dx = dy = 0 with vertical bolts */
401 buzz(type
,sx
,sy
,dx
,dy
)
403 register xchar sx
,sy
;
406 int abstype
= abs(type
);
407 register char *fltxt
= (type
== -1) ? "blaze of fire" : fl
[abstype
];
416 tmp
= zhit(u
.ustuck
, type
);
417 pline("The %s rips into %s%s",
418 fltxt
, monnam(u
.ustuck
), exclam(tmp
));
423 Tmp_at(-1, dirlet(dx
,dy
)); /* open call */
427 if((lev
= &levl
[sx
][sy
])->typ
) Tmp_at(sx
,sy
);
430 if(cansee(sx
-dx
,sy
-dy
))
431 pline("The %s bounces!", fltxt
);
432 if(ZAP_POS(levl
[sx
][sy
-dy
].typ
))
434 if(ZAP_POS(levl
[sx
-dx
][sy
].typ
)) {
435 if(!bounce
|| rn2(2)) bounce
= 2;
451 Tmp_at(-2,dirlet(dx
,dy
));
454 if(lev
->typ
== POOL
&& abstype
== 1 /* fire */) {
459 pline("The water evaporates.");
461 pline("You hear a hissing sound.");
463 if((mon
= m_at(sx
,sy
)) &&
464 (type
!= -1 || mon
->data
->mlet
!= 'D')) {
466 if(rnd(20) < 18 + mon
->data
->ac
) {
467 register int tmp
= zhit(mon
,abstype
);
470 if(cansee(mon
->mx
,mon
->my
))
471 pline("%s is killed by the %s!",
477 hit(fltxt
, mon
, exclam(tmp
));
481 } else if(sx
== u
.ux
&& sy
== u
.uy
) {
483 if(rnd(20) < 18+u
.uac
) {
484 register int dam
= 0;
486 pline("The %s hits you!",fltxt
);
493 pline("You don't feel hot!");
499 nomul(-rnd(25)); /* sleep ray */
503 pline("You don't feel cold!");
510 } else pline("The %s whizzes by you!",fltxt
);
513 if(!ZAP_POS(lev
->typ
)) {
515 if(cansee(sx
,sy
)) pline("The %s bounces!",fltxt
);
517 if(!dx
|| !dy
|| !rn2(20)){
521 if(ZAP_POS(rmn
= levl
[sx
][sy
-dy
].typ
) &&
522 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
+dx
][sy
-dy
].typ
)))
524 if(ZAP_POS(rmn
= levl
[sx
-dx
][sy
].typ
) &&
525 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
-dx
][sy
+dy
].typ
)))
526 if(!bounce
|| rn2(2))
541 Tmp_at(-2, dirlet(dx
,dy
));
548 zhit(mon
,type
) /* returns damage to mon */
549 register struct monst
*mon
;
552 register int tmp
= 0;
555 case 0: /* magic missile */
558 case -1: /* Dragon blazing fire */
560 if(index("Dg", mon
->data
->mlet
)) break;
562 if(index("YF", mon
->data
->mlet
)) tmp
+= 7;
568 if(index("YFgf", mon
->data
->mlet
)) break;
570 if(mon
->data
->mlet
== 'D') tmp
+= 7;
573 if(index(UNDEAD
, mon
->data
->mlet
)) break;
581 #define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\
582 ? 'a' + (otyp - DEAD_ACID_BLOB)\
583 : '@' + (otyp - DEAD_HUMAN))
585 register struct obj
*obj
;
587 register struct monst
*mtmp
;
589 if(obj
->olet
== FOOD_SYM
&& obj
->otyp
> CORPSE
) {
590 /* do not (yet) revive shopkeepers */
591 /* Note: this might conceivably produce two monsters
592 at the same position - strange, but harmless */
593 mtmp
= mkmon_at(CORPSE_I_TO_C(obj
->otyp
),obj
->ox
,obj
->oy
);
596 return(!!mtmp
); /* TRUE if some monster created */
600 register struct obj
*obj
;
602 register tx
,ty
,otx
,oty
;
609 } while(!goodpos(tx
,ty
));
616 fracture_rock(obj
) /* fractured by pick-axe or wand of striking */
617 register struct obj
*obj
; /* no texts here! */
621 obj
->quan
= 7 + rn2(60);
622 obj
->owt
= weight(obj
);
623 obj
->olet
= WEAPON_SYM
;
624 if(cansee(obj
->ox
,obj
->oy
))
625 prl(obj
->ox
,obj
->oy
);
630 register struct obj
*obj
, *obj2
;
631 register int cnt
= 0;
633 for(obj
= invent
; obj
; obj
= obj2
) {
635 if(obj
->olet
== SCROLL_SYM
) {
641 pline("Your scrolls catch fire!");
642 losehp(cnt
, "burning scrolls");
644 pline("Your scroll catches fire!");
645 losehp(1, "burning scroll");