1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.zap.c - version 1.0.3 */
3 /* $FreeBSD: src/games/hack/hack.zap.c,v 1.4 1999/11/16 10:26:38 marcel Exp $ */
4 /* $DragonFly: src/games/hack/hack.zap.c,v 1.4 2005/05/22 03:37:05 y0netan1 Exp $ */
8 extern struct obj
*mkobj_at();
9 extern struct monst
*makemon(), *mkmon_at(), youmonst
;
12 static const char *fl
[]= {
20 /* Routines for IMMEDIATE wands. */
21 /* bhitm: monster mtmp was hit by the effect of wand otmp */
29 if(u
.uswallow
|| rnd(20) < 10+mtmp
->data
->ac
) {
31 hit("wand", mtmp
, exclam(tmp
));
33 if(mtmp
->mhp
< 1) killed(mtmp
);
34 } else miss("wand", mtmp
);
36 case WAN_SLOW_MONSTER
:
39 case WAN_SPEED_MONSTER
:
42 case WAN_UNDEAD_TURNING
:
43 if(index(UNDEAD
,mtmp
->data
->mlet
)) {
45 if(mtmp
->mhp
< 1) killed(mtmp
);
50 if( newcham(mtmp
,&mons
[rn2(CMNUM
)]) )
51 objects
[otmp
->otyp
].oc_name_known
= 1;
53 case WAN_CANCELLATION
:
56 case WAN_TELEPORTATION
:
59 case WAN_MAKE_INVISIBLE
:
66 #endif /* WAN_PROBING */
68 impossible("What an interesting wand (%u)", otmp
->otyp
);
72 bhito(obj
, otmp
) /* object obj was hit by the effect of wand otmp */
73 struct obj
*obj
, *otmp
; /* returns TRUE if sth was done */
77 if(obj
== uball
|| obj
== uchain
)
82 /* preserve symbol and quantity, but turn rocks into gems */
83 mkobj_at((obj
->otyp
== ROCK
|| obj
->otyp
== ENORMOUS_ROCK
)
84 ? GEM_SYM
: obj
->olet
,
85 obj
->ox
, obj
->oy
) -> quan
= obj
->quan
;
89 if(obj
->otyp
== ENORMOUS_ROCK
)
94 case WAN_CANCELLATION
:
95 if(obj
->spe
&& obj
->olet
!= AMULET_SYM
) {
100 case WAN_TELEPORTATION
:
103 case WAN_MAKE_INVISIBLE
:
106 case WAN_UNDEAD_TURNING
:
109 case WAN_SLOW_MONSTER
: /* no effect on objects */
110 case WAN_SPEED_MONSTER
:
113 #endif /* WAN_PROBING */
117 impossible("What an interesting wand (%u)", otmp
->otyp
);
127 obj
= getobj("/", "zap");
129 if(obj
->spe
< 0 || (obj
->spe
== 0 && rn2(121))) {
130 pline("Nothing Happens.");
134 pline("You wrest one more spell from the worn-out wand.");
135 if(!(objects
[obj
->otyp
].bits
& NODIR
) && !getdir(1))
136 return(1); /* make him pay for knowing !NODIR */
138 if(objects
[obj
->otyp
].bits
& IMMEDIATE
) {
140 bhitm(u
.ustuck
, obj
);
143 struct obj
*otmp
= o_at(u
.ux
, u
.uy
);
145 (void) bhito(otmp
, obj
);
148 (void) bhit(u
.dx
,u
.dy
,rn1(8,6),0,bhitm
,bhito
,obj
);
154 case WAN_SECRET_DOOR_DETECTION
:
155 if(!findit()) return(1);
157 case WAN_CREATE_MONSTER
:
159 if(!rn2(23)) cnt
+= rn2(7) + 1;
161 (void) makemon((struct permonst
*) 0, u
.ux
, u
.uy
);
167 extern struct obj
*readobjnam(), *addinv();
168 if(u
.uluck
+ rn2(5) < 0) {
169 pline("Unfortunately, nothing happens.");
172 pline("You may wish for an object. What do you want? ");
174 if(buf
[0] == '\033') buf
[0] = 0;
175 otmp
= readobjnam(buf
);
181 /* Original effect (approximately):
182 * from CORR: dig until we pierce a wall
183 * from ROOM: piece wall and dig until we reach
184 * an ACCESSIBLE place.
185 * Currently: dig for digdepth positions;
186 * also down on request of Lennart Augustsson.
191 struct monst
*mtmp
= u
.ustuck
;
193 pline("You pierce %s's stomach wall!",
195 mtmp
->mhp
= 1; /* almost dead */
202 pline("You loosen a rock from the ceiling.");
203 pline("It falls on your head!");
204 losehp(1, "falling rock");
205 mksobj_at(ROCK
, u
.ux
, u
.uy
);
208 if(Invisible
) newsym(u
.ux
, u
.uy
);
216 digdepth
= 8 + rn2(18);
217 Tmp_at(-1, '*'); /* open call */
218 while(--digdepth
>= 0) {
219 if(!isok(zx
,zy
)) break;
220 room
= &levl
[zx
][zy
];
223 if(zx
< 3 || zx
> COLNO
-3 ||
224 zy
< 3 || zy
> ROWNO
-3)
226 if(room
->typ
== HWALL
||
232 if(room
->typ
== HWALL
|| room
->typ
== VWALL
||
233 room
->typ
== SDOOR
|| room
->typ
== LDOOR
){
237 if(room
->typ
== SCORR
|| !room
->typ
) {
245 mnewsym(zx
,zy
); /* not always necessary */
246 Tmp_at(-1,-1); /* closing call */
250 buzz((int) obj
->otyp
- WAN_MAGIC_MISSILE
,
251 u
.ux
, u
.uy
, u
.dx
, u
.dy
);
254 if(!objects
[obj
->otyp
].oc_name_known
) {
255 objects
[obj
->otyp
].oc_name_known
= 1;
256 more_experienced(0,10);
265 /* force == 0 occurs e.g. with sleep ray */
266 /* note that large force is usual with wands so that !! would
267 require information about hand/weapon/wand */
268 return( (force
< 0) ? "?" : (force
<= 4) ? "." : "!" );
274 char *force
; /* usually either "." or "!" */
276 if(!cansee(mtmp
->mx
,mtmp
->my
)) pline("The %s hits it.", str
);
277 else pline("The %s hits %s%s", str
, monnam(mtmp
), force
);
284 if(!cansee(mtmp
->mx
,mtmp
->my
)) pline("The %s misses it.",str
);
285 else pline("The %s misses %s.",str
,monnam(mtmp
));
288 /* bhit: called when a weapon is thrown (sym = obj->olet) or when an
289 IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of
290 range or when a monster is hit; the monster is returned, and bhitpos
291 is set to the final position of the weapon thrown; the ray of a wand
292 may affect several objects and monsters on its path - for each of
293 these an argument function is called. */
294 /* check !u.uswallow before calling bhit() */
297 bhit(ddx
,ddy
,range
,sym
,fhitm
,fhito
,obj
)
298 int ddx
,ddy
,range
; /* direction and range */
299 char sym
; /* symbol displayed on path */
300 int (*fhitm
)(), (*fhito
)(); /* fns called when mon/obj hit */
301 struct obj
*obj
; /* 2nd arg to fhitm/fhito */
310 if(sym
) tmp_at(-1, sym
); /* open call */
314 typ
= levl
[bhitpos
.x
][bhitpos
.y
].typ
;
315 if(mtmp
= m_at(bhitpos
.x
,bhitpos
.y
)){
317 tmp_at(-1, -1); /* close call */
323 if(fhito
&& (otmp
= o_at(bhitpos
.x
,bhitpos
.y
))){
324 if((*fhito
)(otmp
, obj
))
332 if(sym
) tmp_at(bhitpos
.x
, bhitpos
.y
);
335 /* leave last symbol unless in a pool */
337 tmp_at(-1, (levl
[bhitpos
.x
][bhitpos
.y
].typ
== POOL
) ? -1 : 0);
346 extern schar xdir
[], ydir
[];
351 for(i
=0; i
<8; i
++) if(xdir
[i
] == dx
&& ydir
[i
] == dy
) break;
352 tmp_at(-1, sym
); /* open call */
353 for(ct
=0; ct
<10; ct
++) {
355 sym
= ')' + '(' - sym
;
356 tmp_at(-2, sym
); /* change let call */
361 if(mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)){
365 if(!ZAP_POS(levl
[bhitpos
.x
][bhitpos
.y
].typ
)) {
370 if(bhitpos
.x
== u
.ux
&& bhitpos
.y
== u
.uy
) { /* ct == 9 */
371 if(rn2(20) >= 10+u
.ulevel
){ /* we hit ourselves */
372 (void) thitu(10, rnd(10), "boomerang");
374 } else { /* we catch it */
376 pline("Skillfully, you catch the boomerang.");
380 tmp_at(bhitpos
.x
, bhitpos
.y
);
383 tmp_at(-1, -1); /* do not leave last symbol */
388 dirlet(dx
,dy
) int dx
,dy
; {
390 (dx
== dy
) ? '\\' : (dx
&& dy
) ? '/' : dx
? '-' : '|';
393 /* type == -1: monster spitting fire at you */
394 /* type == -1,-2,-3: bolts sent out by wizard */
395 /* called with dx = dy = 0 with vertical bolts */
396 buzz(type
,sx
,sy
,dx
,dy
)
401 int abstype
= abs(type
);
402 const char *fltxt
= (type
== -1) ? "blaze of fire" : fl
[abstype
];
411 tmp
= zhit(u
.ustuck
, type
);
412 pline("The %s rips into %s%s",
413 fltxt
, monnam(u
.ustuck
), exclam(tmp
));
418 Tmp_at(-1, dirlet(dx
,dy
)); /* open call */
422 if((lev
= &levl
[sx
][sy
])->typ
) Tmp_at(sx
,sy
);
425 if(cansee(sx
-dx
,sy
-dy
))
426 pline("The %s bounces!", fltxt
);
427 if(ZAP_POS(levl
[sx
][sy
-dy
].typ
))
429 if(ZAP_POS(levl
[sx
-dx
][sy
].typ
)) {
430 if(!bounce
|| rn2(2)) bounce
= 2;
446 Tmp_at(-2,dirlet(dx
,dy
));
449 if(lev
->typ
== POOL
&& abstype
== 1 /* fire */) {
454 pline("The water evaporates.");
456 pline("You hear a hissing sound.");
458 if((mon
= m_at(sx
,sy
)) &&
459 (type
!= -1 || mon
->data
->mlet
!= 'D')) {
461 if(rnd(20) < 18 + mon
->data
->ac
) {
462 int tmp
= zhit(mon
,abstype
);
465 if(cansee(mon
->mx
,mon
->my
))
466 pline("%s is killed by the %s!",
472 hit(fltxt
, mon
, exclam(tmp
));
476 } else if(sx
== u
.ux
&& sy
== u
.uy
) {
478 if(rnd(20) < 18+u
.uac
) {
481 pline("The %s hits you!",fltxt
);
488 pline("You don't feel hot!");
494 nomul(-rnd(25)); /* sleep ray */
498 pline("You don't feel cold!");
505 } else pline("The %s whizzes by you!",fltxt
);
508 if(!ZAP_POS(lev
->typ
)) {
510 if(cansee(sx
,sy
)) pline("The %s bounces!",fltxt
);
512 if(!dx
|| !dy
|| !rn2(20)){
516 if(ZAP_POS(rmn
= levl
[sx
][sy
-dy
].typ
) &&
517 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
+dx
][sy
-dy
].typ
)))
519 if(ZAP_POS(rmn
= levl
[sx
-dx
][sy
].typ
) &&
520 (IS_ROOM(rmn
) || ZAP_POS(levl
[sx
-dx
][sy
+dy
].typ
)))
521 if(!bounce
|| rn2(2))
536 Tmp_at(-2, dirlet(dx
,dy
));
543 zhit(mon
,type
) /* returns damage to mon */
550 case 0: /* magic missile */
553 case -1: /* Dragon blazing fire */
555 if(index("Dg", mon
->data
->mlet
)) break;
557 if(index("YF", mon
->data
->mlet
)) tmp
+= 7;
563 if(index("YFgf", mon
->data
->mlet
)) break;
565 if(mon
->data
->mlet
== 'D') tmp
+= 7;
568 if(index(UNDEAD
, mon
->data
->mlet
)) break;
576 #define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\
577 ? 'a' + (otyp - DEAD_ACID_BLOB)\
578 : '@' + (otyp - DEAD_HUMAN))
584 if(obj
->olet
== FOOD_SYM
&& obj
->otyp
> CORPSE
) {
585 /* do not (yet) revive shopkeepers */
586 /* Note: this might conceivably produce two monsters
587 at the same position - strange, but harmless */
588 mtmp
= mkmon_at(CORPSE_I_TO_C(obj
->otyp
),obj
->ox
,obj
->oy
);
591 return(!!mtmp
); /* TRUE if some monster created */
604 } while(!goodpos(tx
,ty
));
611 fracture_rock(obj
) /* fractured by pick-axe or wand of striking */
612 struct obj
*obj
; /* no texts here! */
616 obj
->quan
= 7 + rn2(60);
617 obj
->owt
= weight(obj
);
618 obj
->olet
= WEAPON_SYM
;
619 if(cansee(obj
->ox
,obj
->oy
))
620 prl(obj
->ox
,obj
->oy
);
625 struct obj
*obj
, *obj2
;
628 for(obj
= invent
; obj
; obj
= obj2
) {
630 if(obj
->olet
== SCROLL_SYM
) {
636 pline("Your scrolls catch fire!");
637 losehp(cnt
, "burning scrolls");
639 pline("Your scroll catches fire!");
640 losehp(1, "burning scroll");