/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.zap.c - version 1.0.3 */
extern struct obj
*mkobj_at();
extern struct monst
*makemon(), *mkmon_at(), youmonst
;
/* Routines for IMMEDIATE wands. */
/* bhitm: monster mtmp was hit by the effect of wand otmp */
register struct monst
*mtmp
;
register struct obj
*otmp
;
if(u
.uswallow
|| rnd(20) < 10+mtmp
->data
->ac
) {
register int tmp
= d(2,12);
hit("wand", mtmp
, exclam(tmp
));
if(mtmp
->mhp
< 1) killed(mtmp
);
} else miss("wand", mtmp
);
if(index(UNDEAD
,mtmp
->data
->mlet
)) {
if(mtmp
->mhp
< 1) killed(mtmp
);
if( newcham(mtmp
,&mons
[rn2(CMNUM
)]) )
objects
[otmp
->otyp
].oc_name_known
= 1;
impossible("What an interesting wand (%u)", otmp
->otyp
);
bhito(obj
, otmp
) /* object obj was hit by the effect of wand otmp */
register struct obj
*obj
, *otmp
; /* returns TRUE if sth was done */
if(obj
== uball
|| obj
== uchain
)
/* preserve symbol and quantity, but turn rocks into gems */
mkobj_at((obj
->otyp
== ROCK
|| obj
->otyp
== ENORMOUS_ROCK
)
obj
->ox
, obj
->oy
) -> quan
= obj
->quan
;
if(obj
->otyp
== ENORMOUS_ROCK
)
if(obj
->spe
&& obj
->olet
!= AMULET_SYM
) {
case WAN_SLOW_MONSTER
: /* no effect on objects */
impossible("What an interesting wand (%u)", otmp
->otyp
);
register struct obj
*obj
;
obj
= getobj("/", "zap");
if(obj
->spe
< 0 || (obj
->spe
== 0 && rn2(121))) {
pline("Nothing Happens.");
pline("You wrest one more spell from the worn-out wand.");
if(!(objects
[obj
->otyp
].bits
& NODIR
) && !getdir(1))
return(1); /* make him pay for knowing !NODIR */
if(objects
[obj
->otyp
].bits
& IMMEDIATE
) {
register struct obj
*otmp
= o_at(u
.ux
, u
.uy
);
(void) bhit(u
.dx
,u
.dy
,rn1(8,6),0,bhitm
,bhito
,obj
);
case WAN_SECRET_DOOR_DETECTION
:
if(!rn2(23)) cnt
+= rn2(7) + 1;
(void) makemon((struct permonst
*) 0, u
.ux
, u
.uy
);
register struct obj
*otmp
;
extern struct obj
*readobjnam(), *addinv();
if(u
.uluck
+ rn2(5) < 0) {
pline("Unfortunately, nothing happens.");
pline("You may wish for an object. What do you want? ");
if(buf
[0] == '\033') buf
[0] = 0;
/* Original effect (approximately):
* from CORR: dig until we pierce a wall
* from ROOM: piece wall and dig until we reach
* Currently: dig for digdepth positions;
* also down on request of Lennart Augustsson.
{ register struct rm
*room
;
register struct monst
*mtmp
= u
.ustuck
;
pline("You pierce %s's stomach wall!",
mtmp
->mhp
= 1; /* almost dead */
pline("You loosen a rock from the ceiling.");
pline("It falls on your head!");
losehp(1, "falling rock");
mksobj_at(ROCK
, u
.ux
, u
.uy
);
if(Invisible
) newsym(u
.ux
, u
.uy
);
Tmp_at(-1, '*'); /* open call */
if(zx
< 3 || zx
> COLNO
-3 ||
if(room
->typ
== HWALL
|| room
->typ
== VWALL
||
room
->typ
== SDOOR
|| room
->typ
== LDOOR
){
if(room
->typ
== SCORR
|| !room
->typ
) {
mnewsym(zx
,zy
); /* not always necessary */
Tmp_at(-1,-1); /* closing call */
buzz((int) obj
->otyp
- WAN_MAGIC_MISSILE
,
if(!objects
[obj
->otyp
].oc_name_known
) {
objects
[obj
->otyp
].oc_name_known
= 1;
/* force == 0 occurs e.g. with sleep ray */
/* note that large force is usual with wands so that !! would
require information about hand/weapon/wand */
return( (force
< 0) ? "?" : (force
<= 4) ? "." : "!" );
register struct monst
*mtmp
;
register char *force
; /* usually either "." or "!" */
if(!cansee(mtmp
->mx
,mtmp
->my
)) pline("The %s hits it.", str
);
else pline("The %s hits %s%s", str
, monnam(mtmp
), force
);
register struct monst
*mtmp
;
if(!cansee(mtmp
->mx
,mtmp
->my
)) pline("The %s misses it.",str
);
else pline("The %s misses %s.",str
,monnam(mtmp
));
/* bhit: called when a weapon is thrown (sym = obj->olet) or when an
IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of
range or when a monster is hit; the monster is returned, and bhitpos
is set to the final position of the weapon thrown; the ray of a wand
may affect several objects and monsters on its path - for each of
these an argument function is called. */
/* check !u.uswallow before calling bhit() */
bhit(ddx
,ddy
,range
,sym
,fhitm
,fhito
,obj
)
register int ddx
,ddy
,range
; /* direction and range */
char sym
; /* symbol displayed on path */
int (*fhitm
)(), (*fhito
)(); /* fns called when mon/obj hit */
struct obj
*obj
; /* 2nd arg to fhitm/fhito */
register struct monst
*mtmp
;
register struct obj
*otmp
;
if(sym
) tmp_at(-1, sym
); /* open call */
typ
= levl
[bhitpos
.x
][bhitpos
.y
].typ
;
if(mtmp
= m_at(bhitpos
.x
,bhitpos
.y
)){
tmp_at(-1, -1); /* close call */
if(fhito
&& (otmp
= o_at(bhitpos
.x
,bhitpos
.y
))){
if(sym
) tmp_at(bhitpos
.x
, bhitpos
.y
);
/* leave last symbol unless in a pool */
tmp_at(-1, (levl
[bhitpos
.x
][bhitpos
.y
].typ
== POOL
) ? -1 : 0);
register struct monst
*mtmp
;
extern schar xdir
[], ydir
[];
for(i
=0; i
<8; i
++) if(xdir
[i
] == dx
&& ydir
[i
] == dy
) break;
tmp_at(-1, sym
); /* open call */
tmp_at(-2, sym
); /* change let call */
if(mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)){
if(!ZAP_POS(levl
[bhitpos
.x
][bhitpos
.y
].typ
)) {
if(bhitpos
.x
== u
.ux
&& bhitpos
.y
== u
.uy
) { /* ct == 9 */
if(rn2(20) >= 10+u
.ulevel
){ /* we hit ourselves */
(void) thitu(10, rnd(10), "boomerang");
} else { /* we catch it */
pline("Skillfully, you catch the boomerang.");
tmp_at(bhitpos
.x
, bhitpos
.y
);
tmp_at(-1, -1); /* do not leave last symbol */
dirlet(dx
,dy
) register dx
,dy
; {
(dx
== dy
) ? '\\' : (dx
&& dy
) ? '/' : dx
? '-' : '|';
/* type == -1: monster spitting fire at you */
/* type == -1,-2,-3: bolts sent out by wizard */
/* called with dx = dy = 0 with vertical bolts */
register char *fltxt
= (type
== -1) ? "blaze of fire" : fl
[abstype
];
tmp
= zhit(u
.ustuck
, type
);
pline("The %s rips into %s%s",
fltxt
, monnam(u
.ustuck
), exclam(tmp
));
Tmp_at(-1, dirlet(dx
,dy
)); /* open call */
if((lev
= &levl
[sx
][sy
])->typ
) Tmp_at(sx
,sy
);
pline("The %s bounces!", fltxt
);
if(ZAP_POS(levl
[sx
][sy
-dy
].typ
))
if(ZAP_POS(levl
[sx
-dx
][sy
].typ
)) {
if(!bounce
|| rn2(2)) bounce
= 2;
Tmp_at(-2,dirlet(dx
,dy
));
if(lev
->typ
== POOL
&& abstype
== 1 /* fire */) {
pline("The water evaporates.");
pline("You hear a hissing sound.");
if((mon
= m_at(sx
,sy
)) &&
(type
!= -1 || mon
->data
->mlet
!= 'D')) {
if(rnd(20) < 18 + mon
->data
->ac
) {
register int tmp
= zhit(mon
,abstype
);
if(cansee(mon
->mx
,mon
->my
))
pline("%s is killed by the %s!",
hit(fltxt
, mon
, exclam(tmp
));
} else if(sx
== u
.ux
&& sy
== u
.uy
) {
pline("The %s hits you!",fltxt
);
pline("You don't feel hot!");
nomul(-rnd(25)); /* sleep ray */
pline("You don't feel cold!");
} else pline("The %s whizzes by you!",fltxt
);
if(cansee(sx
,sy
)) pline("The %s bounces!",fltxt
);
if(!dx
|| !dy
|| !rn2(20)){
if(ZAP_POS(rmn
= levl
[sx
][sy
-dy
].typ
) &&
(IS_ROOM(rmn
) || ZAP_POS(levl
[sx
+dx
][sy
-dy
].typ
)))
if(ZAP_POS(rmn
= levl
[sx
-dx
][sy
].typ
) &&
(IS_ROOM(rmn
) || ZAP_POS(levl
[sx
-dx
][sy
+dy
].typ
)))
Tmp_at(-2, dirlet(dx
,dy
));
zhit(mon
,type
) /* returns damage to mon */
register struct monst
*mon
;
case 0: /* magic missile */
case -1: /* Dragon blazing fire */
if(index("Dg", mon
->data
->mlet
)) break;
if(index("YF", mon
->data
->mlet
)) tmp
+= 7;
if(index("YFgf", mon
->data
->mlet
)) break;
if(mon
->data
->mlet
== 'D') tmp
+= 7;
if(index(UNDEAD
, mon
->data
->mlet
)) break;
#define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\
? 'a' + (otyp - DEAD_ACID_BLOB)\
: '@' + (otyp - DEAD_HUMAN))
register struct obj
*obj
;
register struct monst
*mtmp
;
if(obj
->olet
== FOOD_SYM
&& obj
->otyp
> CORPSE
) {
/* do not (yet) revive shopkeepers */
/* Note: this might conceivably produce two monsters
at the same position - strange, but harmless */
mtmp
= mkmon_at(CORPSE_I_TO_C(obj
->otyp
),obj
->ox
,obj
->oy
);
return(!!mtmp
); /* TRUE if some monster created */
register struct obj
*obj
;
} while(!goodpos(tx
,ty
));
fracture_rock(obj
) /* fractured by pick-axe or wand of striking */
register struct obj
*obj
; /* no texts here! */
if(cansee(obj
->ox
,obj
->oy
))
register struct obj
*obj
, *obj2
;
for(obj
= invent
; obj
; obj
= obj2
) {
if(obj
->olet
== SCROLL_SYM
) {
pline("Your scrolls catch fire!");
losehp(cnt
, "burning scrolls");
pline("Your scroll catches fire!");
losehp(1, "burning scroll");