1 /* SCCS Id: @(#)dig.c 3.4 2003/03/23 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
7 /* #define DEBUG */ /* turn on for diagnostics */
11 static NEARDATA boolean did_dig_msg
;
13 STATIC_DCL boolean
rm_waslit(void);
14 STATIC_DCL
void mkcavepos(XCHAR_P
,XCHAR_P
,int,BOOLEAN_P
,BOOLEAN_P
);
15 STATIC_DCL
void mkcavearea(BOOLEAN_P
);
16 STATIC_DCL
int dig_typ(struct obj
*,XCHAR_P
,XCHAR_P
);
17 STATIC_DCL
int dig(void);
18 STATIC_DCL schar
fillholetyp(int, int);
19 STATIC_DCL
void dig_up_grave(void);
21 /* Indices returned by dig_typ() */
22 #define DIGTYP_UNDIGGABLE 0
24 #define DIGTYP_STATUE 2
25 #define DIGTYP_BOULDER 3
28 #define DIGTYP_IRONBAR 6
29 #define DIGTYP_FIREAXE 7
30 /* keep d_action and d_target in sync!!! otherwise, CRASH with illegible backtrace "?? at 07f49320" or something --Amy */
37 if(levl
[u
.ux
][u
.uy
].typ
== ROOM
&& levl
[u
.ux
][u
.uy
].waslit
)
39 for(x
= u
.ux
-2; x
< u
.ux
+3; x
++)
40 for(y
= u
.uy
-1; y
< u
.uy
+2; y
++)
41 if(isok(x
,y
) && levl
[x
][y
].waslit
) return(TRUE
);
45 /* Change level topology. Messes with vision tables and ignores things like
46 * boulders in the name of a nice effect. Vision will get fixed up again
47 * immediately after the effect is complete.
50 mkcavepos(x
, y
, dist
, waslit
, rockit
)
53 boolean waslit
, rockit
;
55 register struct rm
*lev
;
57 if(!isok(x
,y
)) return;
61 register struct monst
*mtmp
;
63 if(IS_ROCK(lev
->typ
)) return;
64 if(t_at(x
, y
)) return; /* don't cover the portal */
65 if ((mtmp
= m_at(x
, y
)) != 0) /* make sure crucial monsters survive */
66 if(!passes_walls(mtmp
->data
) && (!mtmp
->egotype_wallwalk
)) (void) rloc(mtmp
, FALSE
);
67 } else if(lev
->typ
== ROOM
) return;
69 unblock_point(x
,y
); /* make sure vision knows this location is open */
70 if (!(levl
[x
][y
].wall_info
& W_HARDGROWTH
)) levl
[x
][y
].wall_info
|= W_EASYGROWTH
;
72 /* fake out saved state */
75 if(dist
< 3) lev
->lit
= (rockit
? FALSE
: TRUE
);
76 if(waslit
) lev
->waslit
= (rockit
? FALSE
: TRUE
);
77 lev
->horizontal
= FALSE
;
78 viz_array
[y
][x
] = (dist
< 3 ) ?
79 (IN_SIGHT
|COULD_SEE
) : /* short-circuit vision recalc */
81 lev
->typ
= (rockit
? STONE
: ROOM
);
83 impossible("mkcavepos called with dist %d", dist
);
91 register boolean rockit
;
94 xchar xmin
= u
.ux
, xmax
= u
.ux
;
95 xchar ymin
= u
.uy
, ymax
= u
.uy
;
97 register boolean waslit
= rm_waslit();
99 if(rockit
) pline("Crash! The ceiling collapses around you!");
100 else pline("A mysterious force %s cave around you!",
101 (levl
[u
.ux
][u
.uy
].typ
== CORR
) ? "creates a" : "extends the");
102 display_nhwindow(WIN_MESSAGE
, TRUE
);
104 for(dist
= 1; dist
<= 2; dist
++) {
108 if(dist
< 2) { /* the area is wider that it is high */
110 for(i
= xmin
+1; i
< xmax
; i
++) {
111 mkcavepos(i
, ymin
, dist
, waslit
, rockit
);
112 mkcavepos(i
, ymax
, dist
, waslit
, rockit
);
117 for(i
= ymin
; i
<= ymax
; i
++) {
118 mkcavepos(xmin
, i
, dist
, waslit
, rockit
);
119 mkcavepos(xmax
, i
, dist
, waslit
, rockit
);
122 flush_screen(1); /* make sure the new glyphs shows up */
126 if(!rockit
&& levl
[u
.ux
][u
.uy
].typ
== CORR
) {
127 levl
[u
.ux
][u
.uy
].typ
= /*ROOM*/CORR
;
128 if(waslit
) levl
[u
.ux
][u
.uy
].waslit
= TRUE
;
129 newsym(u
.ux
, u
.uy
); /* in case player is invisible */
132 vision_full_recalc
= 1; /* everything changed */
135 /* When digging into location <x,y>, what are you actually digging into? */
141 boolean ispick
= is_pick(otmp
);
142 boolean isantibar
= is_antibar(otmp
);
143 boolean issaber
= is_lightsaber(otmp
);
145 if (otmp
->oartifact
== ART_BREAK_EVERYTHING
&& Role_if(PM_FIREFIGHTER
)) {
146 if (IS_IRONBAR(levl
[x
][y
].typ
) || IS_TREE(levl
[x
][y
].typ
) || IS_FARMLAND(levl
[x
][y
].typ
) || IS_MOUNTAIN(levl
[x
][y
].typ
)) {
148 return DIGTYP_FIREAXE
;
154 ) && sobj_at(STATUE
, x
, y
) ? DIGTYP_STATUE
:
155 (isantibar
&& IS_IRONBAR(levl
[x
][y
].typ
)) ? DIGTYP_IRONBAR
:
158 ) && sobj_at(BOULDER
, x
, y
) ? DIGTYP_BOULDER
:
159 closed_door(x
, y
) ? DIGTYP_DOOR
:
160 IS_TREE(levl
[x
][y
].typ
) ?
161 (ispick
? DIGTYP_UNDIGGABLE
: DIGTYP_TREE
) :
164 ) && (IS_ROCK(levl
[x
][y
].typ
) || IS_WATERTUNNEL(levl
[x
][y
].typ
)) &&
165 (!level
.flags
.arboreal
|| IS_WALL(levl
[x
][y
].typ
)) ?
166 DIGTYP_ROCK
: DIGTYP_UNDIGGABLE
);
172 if (occupation
== dig
) {
178 #define BY_YOU (&youmonst)
179 #define BY_OBJECT ((struct monst *)0)
182 dig_check(madeby
, verbose
, x
, y
)
183 struct monst
*madeby
;
187 struct trap
*ttmp
= t_at(x
, y
);
189 (madeby
!= BY_YOU
|| !uwep
|| is_pick(uwep
)) ? "dig in" :
190 is_lightsaber(uwep
) ? "cut" :
193 if (On_stairs(x
, y
)) {
194 if (x
== xdnladder
|| x
== xupladder
) {
195 if(verbose
) pline_The("ladder resists your effort.");
196 } else if(verbose
) pline_The("stairs are too hard to %s.", verb
);
198 /* ALI - Artifact doors */
199 } else if (IS_DOOR(levl
[x
][y
].typ
) && artifact_door(x
, y
)) {
200 if(verbose
) pline_The("%s here is too hard to dig in.",
203 } else if (IS_THRONE(levl
[x
][y
].typ
) && madeby
!= BY_OBJECT
) {
204 if(verbose
) pline_The("throne is too hard to break apart.");
206 } else if (IS_FARMLAND(levl
[x
][y
].typ
) && madeby
!= BY_OBJECT
) {
207 if(verbose
) pline("Farmland cannot be dug out.");
209 } else if (IS_MOUNTAIN(levl
[x
][y
].typ
) && madeby
!= BY_OBJECT
) {
210 if(verbose
) pline_The("mountain is too hard to dig into.");
212 } else if (IS_GRAVEWALL(levl
[x
][y
].typ
) && madeby
!= BY_OBJECT
) {
213 if(verbose
) pline_The("grave wall needs to be dug by moving into it.");
215 } else if (IS_ALTAR(levl
[x
][y
].typ
) && (madeby
!= BY_OBJECT
||
216 Is_astralevel(&u
.uz
) || Is_sanctum(&u
.uz
))) {
217 if(verbose
) pline_The("altar is too hard to break apart.");
219 } else if (Is_airlevel(&u
.uz
)) {
220 if(verbose
) You("cannot %s thin air.", verb
);
222 } else if (Is_waterlevel(&u
.uz
)) {
223 if(verbose
) pline_The("water splashes and subsides.");
225 } else if ((IS_ROCK(levl
[x
][y
].typ
) && levl
[x
][y
].typ
!= SDOOR
&&
226 ((levl
[x
][y
].wall_info
& W_NONDIGGABLE
) != 0 && !(u
.dynamitehack
)) )
227 || (IS_FARMLAND(levl
[x
][y
].typ
)) || (IS_MOUNTAIN(levl
[x
][y
].typ
)) || (IS_GRAVEWALL(levl
[x
][y
].typ
))
229 (ttmp
->ttyp
== MAGIC_PORTAL
|| ttmp
->ttyp
== HEEL_TRAP
|| ttmp
->ttyp
== ATTACKING_HEEL_TRAP
|| ttmp
->ttyp
== LOUDSPEAKER
|| ttmp
->ttyp
== KOP_CUBE
|| ttmp
->ttyp
== BOSS_SPAWNER
|| ttmp
->ttyp
== ARABELLA_SPEAKER
|| ttmp
->ttyp
== FART_TRAP
|| ttmp
->ttyp
== PERSISTENT_FART_TRAP
|| !Can_dig_down(&u
.uz
)))) {
230 if(verbose
) pline_The("%s here is too hard to %s.",
233 } else if (sobj_at(BOULDER
, x
, y
)) {
234 if(verbose
) There("isn't enough room to %s here.", verb
);
236 } else if (madeby
== BY_OBJECT
&&
237 /* the block against existing traps is mainly to
238 prevent broken wands from turning holes into pits */
239 (ttmp
|| is_waterypool(x
,y
) || is_styxriver(x
,y
) || is_lava(x
,y
))) {
240 /* digging by player handles pools separately */
249 register struct rm
*lev
;
250 register xchar dpx
= digging
.pos
.x
, dpy
= digging
.pos
.y
;
251 register boolean ispick
= uwep
&& is_pick(uwep
);
253 (!uwep
|| is_pick(uwep
)) ? "dig into" :
254 is_lightsaber(uwep
) ? "cut through" :
258 lev
= &levl
[dpx
][dpy
];
259 /* perhaps a nymph stole your pick-axe while you were busy digging */
260 /* or perhaps you teleported away */
261 /* WAC allow lightsabers */
262 if (u
.uswallow
|| !uwep
|| (!ispick
&&
263 (!is_lightsaber(uwep
) || (!uwep
->lamplit
&& !Role_if(PM_SHADOW_JEDI
)) ) &&
264 !is_axe(uwep
) && !is_antibar(uwep
)) ||
265 !on_level(&digging
.level
, &u
.uz
) ||
266 ((digging
.down
? (dpx
!= u
.ux
|| dpy
!= u
.uy
)
267 : (distu(dpx
,dpy
) > 2))))
271 if(!dig_check(BY_YOU
, TRUE
, u
.ux
, u
.uy
)) return(0);
272 } else { /* !digging.down */
273 if (IS_TREE(lev
->typ
) && !may_dig(dpx
,dpy
) &&
274 dig_typ(uwep
, dpx
, dpy
) == DIGTYP_TREE
) {
275 pline("This tree seems to be petrified.");
278 /* ALI - Artifact doors */
279 if (IS_ROCK(lev
->typ
) && !may_dig(dpx
,dpy
) &&
280 dig_typ(uwep
, dpx
, dpy
) == DIGTYP_ROCK
||
281 IS_DOOR(lev
->typ
) && artifact_door(dpx
, dpy
)) {
282 pline("This %s is too hard to %s.",
283 IS_DOOR(lev
->typ
) ? "door" : IS_MOUNTAIN(lev
->typ
) ? "mountain" : IS_FARMLAND(lev
->typ
) ? "farmland" : "wall", verb
);
288 /* Can't exactly miss holding a lightsaber to the wall */
289 !is_lightsaber(uwep
) &&
294 You("fumble and drop your %s.", xname(uwep
));
298 Your("%s %s and %s %s!",
300 otense(uwep
, "bounce"), otense(uwep
, "hit"),
303 pline("Ouch! Your %s %s and %s you!",
305 otense(uwep
, "bounce"), otense(uwep
, "hit"));
306 set_wounded_legs(RIGHT_SIDE
, HWounded_legs
+ 5 + rnd(5));
310 pline("Bang! You hit with the broad side of %s!",
313 default: Your("swing misses its mark.");
319 /* calculate digging effort */
320 bonus
= 4 + rn2(5) + abon() + uwep
->spe
- greatest_erosionX(uwep
) + increase_damage_bonus_value() + RngeBloodlust
+ (Drunken_boxing
&& Confusion
) + (StrongDrunken_boxing
&& Confusion
);
321 if (uarms
&& uarms
->oartifact
== ART_TEH_BASH_R
) bonus
+= 2;
322 if (uarmh
&& uarmh
->oartifact
== ART_HELMET_OF_DIGGING
) bonus
+= 5;
323 if (uarmg
&& itemhasappearance(uarmg
, APP_DIGGER_GLOVES
)) bonus
+= 5;
324 if (uwep
&& uwep
->oartifact
== ART_COPPERED_OFF_FROM_ME
) bonus
+= 5;
325 if (uwep
&& uwep
->oartifact
== ART_STONEBITER
) bonus
+= 5;
326 if (uwep
&& uwep
->oartifact
== ART_BREAK_OUT
) bonus
+= 5;
327 if (uwep
&& uwep
->oartifact
== ART_MINE_OUT
) bonus
+= 5;
328 if (uarmh
&& uarmh
->oartifact
== ART_THIRD_CAR
) bonus
+= 10;
329 if (uwep
&& uwep
->oartifact
== ART_DIG__OF_COURSE
) bonus
+= 5;
330 if (uwep
&& uwep
->oartifact
== ART_NOTHING_FOR_IT
) bonus
+= 5;
331 if (uarm
&& uarm
->oartifact
== ART_CLANGFRIEND
) bonus
+= 5;
332 if (uarmf
&& uarmf
->oartifact
== ART_GRAVY_HIDE
) bonus
+= 5;
333 if (uarmc
&& uarmc
->oartifact
== ART_MINING_FOR_FUN_AND_PROFIT
) bonus
+= 5;
334 if (tunnels(youmonst
.data
)) bonus
+= rn2(3); /* digging monsters really should have a bonus here --Amy */
335 if (needspick(youmonst
.data
)) bonus
+= rn2(3); /* and more so if they're dedicated miners (e.g. dwarf) */
336 if (!PlayerCannotUseSkills
) {
338 if (uwep
&& is_lightsaber(uwep
)) {
339 switch (P_SKILL(P_WEDI
)) {
341 case P_BASIC
: bonus
+= 5; break;
342 case P_SKILLED
: bonus
+= 10; break;
343 case P_EXPERT
: bonus
+= 14; break;
344 case P_MASTER
: bonus
+= 17; break;
345 case P_GRAND_MASTER
: bonus
+= 21; break;
346 case P_SUPREME_MASTER
: bonus
+= 25; break;
350 switch (P_SKILL(P_WEDI
)) {
352 case P_BASIC
: bonus
+= 3; break;
353 case P_SKILLED
: bonus
+= 6; break;
354 case P_EXPERT
: bonus
+= 10; break;
355 case P_MASTER
: bonus
+= 13; break;
356 case P_GRAND_MASTER
: bonus
+= 16; break;
357 case P_SUPREME_MASTER
: bonus
+= 20; break;
363 if (Race_if(PM_DWARF
) || Role_if(PM_MIDGET
) )
365 if (Race_if(PM_IRAHA
)) bonus
*= rnd(3);
366 if (isfriday
&& bonus
> 1) bonus
/= 2;
368 if (uwep
&& uwep
->oartifact
== ART_ETERNALE_DELAY
) bonus
-= 5;
369 if (uwep
&& uwep
->oartifact
== ART_DE_SID
&& uwep
->altmode
) bonus
+= rnd(20);
371 if (uwep
&& uwep
->otyp
== SHOVEL
&& !(uwep
->oartifact
== ART_AFTERMINE
) )
372 bonus
-= rn2(Role_if(PM_UNDERTAKER
) ? 5 : 20); /* digging with a shovel takes longer */
374 if (uwep
&& is_lightsaber(uwep
) && !(uwep
->oartifact
== ART_DE_SID
) ) /* Melting a hole takes longer */
375 bonus
-= (uwep
->lamplit
&& uwep
->altmode
) ? rn2(8) : rn2(20); /* but is faster if both blades are lit --Amy */
376 if (uwep
&& is_lightsaber(uwep
) && !uwep
->lamplit
)
377 bonus
-= rn2(200); /* and if the saber isn't lit (shadow jedi role), it takes like forever --Amy */
379 digging
.effort
+= bonus
;
382 register struct trap
*ttmp
;
384 if (digging
.effort
> 250) {
385 (void) dighole(FALSE
);
386 (void) memset((void *)&digging
, 0, sizeof digging
);
387 return(0); /* done with digging */
390 if (digging
.effort
<= 50 ||
391 is_lightsaber(uwep
) ||
392 ((ttmp
= t_at(dpx
,dpy
)) != 0 &&
393 (ttmp
->ttyp
== PIT
|| ttmp
->ttyp
== SPIKED_PIT
|| ttmp
->ttyp
== GIANT_CHASM
|| ttmp
->ttyp
== SHIT_PIT
|| ttmp
->ttyp
== MANA_PIT
|| ttmp
->ttyp
== ANOXIC_PIT
|| ttmp
->ttyp
== HYPOXIC_PIT
|| ttmp
->ttyp
== ACID_PIT
|| ttmp
->ttyp
== SHAFT_TRAP
|| ttmp
->ttyp
== CURRENT_SHAFT
||
394 ttmp
->ttyp
== TRAPDOOR
|| ttmp
->ttyp
== HOLE
)))
397 if (IS_ALTAR(lev
->typ
)) {
398 altar_wrath(dpx
, dpy
);
402 if (dighole(TRUE
)) { /* make pit at <u.ux,u.uy> */
403 digging
.level
.dnum
= 0;
404 digging
.level
.dlevel
= -1;
409 if (digging
.effort
> 100) {
410 register const char *digtxt
, *dmgtxt
= (const char*) 0;
411 register struct obj
*obj
;
412 register boolean shopedge
= *in_rooms(dpx
, dpy
, SHOPBASE
);
414 if (Role_if(PM_FIREFIGHTER
) && uwep
&& uwep
->oartifact
== ART_BREAK_EVERYTHING
&& (IS_IRONBAR(lev
->typ
) || IS_TREE(lev
->typ
) || IS_FARMLAND(lev
->typ
) || IS_MOUNTAIN(lev
->typ
) ) ) {
416 digtxt
= "You cleared away the obstructing terrain.";
417 } else if ((obj
= sobj_at(STATUE
, dpx
, dpy
)) != 0) {
418 if (break_statue(obj
)) {
419 digtxt
= "The statue shatters.";
420 if (uwep
&& is_lightsaber(uwep
) && (uwep
->lamplit
|| Role_if(PM_SHADOW_JEDI
)) ) {
421 use_skill(P_WEDI
, 1);
423 if (uwep
&& uwep
->oartifact
== ART_DIGSRU
) {
424 use_skill(P_WEDI
, 1);
427 /* it was a statue trap; break_statue()
428 * printed a message and updated the screen
431 } else if ((obj
= sobj_at(BOULDER
, dpx
, dpy
)) != 0) {
435 if ((bobj
= sobj_at(BOULDER
, dpx
, dpy
)) != 0) {
436 /* another boulder here, restack it to the top */
437 obj_extract_self(bobj
);
438 place_object(bobj
, dpx
, dpy
);
440 digtxt
= "The boulder falls apart.";
441 if (uwep
&& is_lightsaber(uwep
) && (uwep
->lamplit
|| Role_if(PM_SHADOW_JEDI
)) ) {
442 use_skill(P_WEDI
, 1);
444 if (uwep
&& uwep
->oartifact
== ART_DIGSRU
) {
445 use_skill(P_WEDI
, 1);
447 } else if (lev
->typ
== STONE
|| lev
->typ
== WATERTUNNEL
|| lev
->typ
== SCORR
|| IS_IRONBAR(lev
->typ
) ||
449 if(Is_earthlevel(&u
.uz
)) {
450 if(uwep
->blessed
&& !rn2(3)) {
453 } else if((uwep
->cursed
&& !rn2(4)) ||
454 (!uwep
->blessed
&& !rn2(6))) {
459 if (IS_TREE(lev
->typ
)) {
460 digtxt
= "You cut down the tree.";
461 u
.cnd_treechopamount
++;
462 if (u
.ualign
.type
== A_CHAOTIC
) adjalign(1);
464 /* the tree squads do not want people who kill trees, and will aggressively chase them --Amy */
465 u
.treesquadwantedlevel
+= (100 + rnd(u
.cnd_treechopamount
* 5));
466 if (Role_if(PM_BOSMER
)) { /* you have angered Yavanna... */
467 You("violated the sanctity of the grove!");
469 increasesincounter(1);
471 u
.treesquadwantedlevel
+= 1000;
475 if (!rn2(5)) wake_nearby(); /* felling a tree can make a loud noise, try it in real life! --Amy */
477 if (!rn2(5) && !(lev
->looted
& TREE_LOOTED
) ) (void) rnd_treefruit_at(dpx
, dpy
);
479 if (uwep
&& is_lightsaber(uwep
) && (uwep
->lamplit
|| Role_if(PM_SHADOW_JEDI
)) ) {
480 use_skill(P_WEDI
, 1);
482 if (uwep
&& uwep
->oartifact
== ART_DIGSRU
) {
483 use_skill(P_WEDI
, 1);
486 if (!(lev
->looted
& TREE_SWARM
) && !rn2(16)) {
487 int cnt
= rnl(4) + 2;
490 mm
.x
= dpx
; mm
.y
= dpy
;
495 if (enexto(&mm
, mm
.x
, mm
.y
, &mons
[PM_WOOD_NYMPH
]) &&
496 makemon(mkclass(S_NYMPH
,0), mm
.x
, mm
.y
, MM_ANGRY
))
499 wake_nearby(); /* make sure they're awake --Amy */
504 if (enexto(&mm
, mm
.x
, mm
.y
, &mons
[PM_KILLER_BEE
]) &&
505 makemon(beehivemon(), mm
.x
, mm
.y
, MM_ANGRY
))
511 pline("You've attracted the tree's former occupants!");
513 You("smell stale honey.");
517 if (!rn2(50)) { /* summon the tree squad! --Amy */
523 int tsdamount
= rnd(4);
524 if (!rn2(10)) tsdamount
+= rnd(8);
527 reset_rndmonst(NON_PM
);
532 struct permonst
*pm
= 0;
534 if (!enexto(&dd
, u
.ux
, u
.uy
, (struct permonst
*)0) ) continue;
540 if (attempts
&& (attempts
% 10000 == 0)) u
.mondiffhack
++;
541 if (!rn2(2000)) reset_rndmonst(NON_PM
);
543 } while ( (!pm
|| (pm
&& !(pm
->msound
== MS_TREESQUAD
))) && attempts
< 50000);
545 if (!pm
&& rn2(50) ) {
549 if (pm
&& !(pm
->msound
== MS_TREESQUAD
) && rn2(50) ) {
554 if (pm
) (void) makemon(pm
, cx
, cy
, MM_ANGRY
|MM_FRENZIED
|MM_XFRENZIED
|MM_ADJACENTOK
);
564 } else if (IS_WATERTUNNEL(lev
->typ
)) {
565 digtxt
= "You smash the solid part of the tunnel apart. Now it's a moat!";
566 u
.cnd_diggingamount
++;
568 if (uwep
&& is_lightsaber(uwep
) && (uwep
->lamplit
|| Role_if(PM_SHADOW_JEDI
)) ) {
569 use_skill(P_WEDI
, 1);
571 if (uwep
&& uwep
->oartifact
== ART_DIGSRU
) {
572 use_skill(P_WEDI
, 1);
574 } else if (uwep
&& IS_IRONBAR(lev
->typ
) && is_antibar(uwep
) ) {
576 digtxt
= "You smash the bars to the ground.";
577 u
.cnd_barbashamount
++;
581 monstcnt
= 1 + rnd(3);
582 struct permonst
*pm
= 0;
584 if (Aggravate_monster
) {
586 reset_rndmonst(NON_PM
);
593 if (attempts
&& (attempts
% 10000 == 0)) u
.mondiffhack
++;
594 if (!rn2(2000)) reset_rndmonst(NON_PM
);
596 } while ( (!pm
|| (pm
&& !(pm
->msound
== MS_METALMAFIA
))) && attempts
< 50000);
598 if (!pm
&& rn2(50) ) {
600 goto newbossMETALMAFIA
;
602 if (pm
&& !(pm
->msound
== MS_METALMAFIA
) && rn2(50) ) {
604 goto newbossMETALMAFIA
;
607 if (pm
) (void) makemon(pm
, 0, 0, MM_ANGRY
);
613 if (monstcnt
> 0) goto newbossMETALMAFIA
;
620 if (In_sokoban(&u
.uz
) && !playercancheatinsoko()) {
622 pline("You cheater!");
623 if (evilfriday
) u
.ugangr
++;
626 if (!issoviet
|| !rn2(10)) lev
->typ
= ROOM
;
628 pline("V sootvetstvii s tipom bloka l'da eto ne imeyet nikakogo smysla. I poetomu on ne rabotayet. Khar Khar Khar on on on bwar khar khar!");
629 digging
.quiet
= TRUE
; /* suppress misleading message */
630 /* In Soviet Russia, iron bars are supposed to be nigh impenetrable. After all, someone's gotta keep all those
631 * capitalist prisoners at bay. Therefore, you can try to smash iron bars many times but only rarely it will
632 * work. Actually, it's supposed to be possible to cut through bars with a lightsaber instead according to
633 * Soviet, but seriously, fuck that shit, I'm not gonna bother coding that just for an obscure special mode
634 * that 99.9% of players won't use anyway because they don't understand russian. --Amy */
636 if (uwep
->obrittle
== 3 || uwep
->obrittle2
== 3) {
637 Your("weapon was destroyed!");
641 if (!rn2(2)) uwep
->obrittle
++;
642 else uwep
->obrittle2
++;
643 Your("weapon has taken damage from smashing the bars!");
645 /* it's intentional that the weapon cannot resist, because otherwise you could take one that
646 * is highly resistant to erosion or even immune to being destroyed and simply smash all bars
647 * in the entire dungeon, which isn't what we want --Amy */
649 if (!rn2(5)) mkobj_at(CHAIN_CLASS
, dpx
, dpy
, FALSE
, FALSE
); /* maybe make a chain from the bars --Amy */
652 digtxt
= "You succeed in cutting away some rock.";
653 u
.cnd_diggingamount
++;
656 if (uwep
&& uwep
->oartifact
== ART_MFFAP
&& !rn2(20)) {
657 struct trap
*extramine
;
658 if (!t_at(dpx
, dpy
)) {
659 extramine
= maketrap(dpx
, dpy
, LANDMINE
, 0, FALSE
);
661 extramine
->tseen
= TRUE
;
662 extramine
->hiddentrap
= FALSE
;
663 extramine
->madeby_u
= TRUE
;
664 pline("CLICK! A mine has been set!");
669 if (uwep
&& is_lightsaber(uwep
) && (uwep
->lamplit
|| Role_if(PM_SHADOW_JEDI
)) ) {
670 use_skill(P_WEDI
, 1);
672 if (uwep
&& uwep
->oartifact
== ART_DIGSRU
) {
673 use_skill(P_WEDI
, 1);
676 } else if(IS_WALL(lev
->typ
)) {
678 add_damage(dpx
, dpy
, 10L * ACURRSTR
);
681 if (level
.flags
.is_maze_lev
) {
682 lev
->typ
= /*ROOM*/CORR
;
683 } else if (level
.flags
.is_cavernous_lev
&&
684 !in_town(dpx
, dpy
)) {
686 } else if (IS_WATERTUNNEL(lev
->typ
)) {
688 } else if (IS_DIGGABLEWALL(lev
->typ
)) {
692 lev
->doormask
= D_NODOOR
;
694 digtxt
= "You make an opening in the wall.";
695 u
.cnd_diggingamount
++;
697 if (uwep
&& is_lightsaber(uwep
) && (uwep
->lamplit
|| Role_if(PM_SHADOW_JEDI
)) ) {
698 use_skill(P_WEDI
, 1);
700 if (uwep
&& uwep
->oartifact
== ART_DIGSRU
) {
701 use_skill(P_WEDI
, 1);
704 } else if(lev
->typ
== SDOOR
) {
705 cvt_sdoor_to_door(lev
); /* ->typ = DOOR */
706 digtxt
= "You break through a secret door!";
707 if (uwep
&& is_lightsaber(uwep
) && (uwep
->lamplit
|| Role_if(PM_SHADOW_JEDI
)) ) {
708 use_skill(P_WEDI
, 1);
710 if (uwep
&& uwep
->oartifact
== ART_DIGSRU
) {
711 use_skill(P_WEDI
, 1);
713 if(!(lev
->doormask
& D_TRAPPED
))
714 lev
->doormask
= D_BROKEN
;
715 } else if(closed_door(dpx
, dpy
)) {
716 digtxt
= "You break through the door.";
717 if (uwep
&& is_lightsaber(uwep
) && (uwep
->lamplit
|| Role_if(PM_SHADOW_JEDI
)) ) {
718 use_skill(P_WEDI
, 1);
720 if (uwep
&& uwep
->oartifact
== ART_DIGSRU
) {
721 use_skill(P_WEDI
, 1);
724 add_damage(dpx
, dpy
, 400L);
727 if(!(lev
->doormask
& D_TRAPPED
))
728 lev
->doormask
= D_BROKEN
;
729 } else return(0); /* statue or boulder got taken */
731 if(!does_block(dpx
,dpy
,&levl
[dpx
][dpy
]))
732 unblock_point(dpx
,dpy
); /* vision: can see through */
733 if (!(levl
[dpx
][dpy
].wall_info
& W_HARDGROWTH
)) levl
[dpx
][dpy
].wall_info
|= W_EASYGROWTH
;
735 feel_location(dpx
, dpy
);
738 if(digtxt
&& !digging
.quiet
) pline("%s", digtxt
); /* after newsym */
740 pay_for_damage(dmgtxt
, FALSE
);
742 if(Is_earthlevel(&u
.uz
) && !rn2(3)) {
743 register struct monst
*mtmp
;
747 mtmp
= makemon(&mons
[PM_EARTH_ELEMENTAL
],
748 dpx
, dpy
, NO_MM_FLAGS
);
751 mtmp
= makemon(&mons
[PM_XORN
],
752 dpx
, dpy
, NO_MM_FLAGS
);
755 if(mtmp
) pline_The("debris reassembles and comes to life!");
757 if(IS_DOOR(lev
->typ
) && (lev
->doormask
& D_TRAPPED
)) {
758 lev
->doormask
= D_NODOOR
;
759 b_trapped("door", 0);
763 digging
.lastdigtime
= moves
;
764 digging
.quiet
= FALSE
;
765 digging
.level
.dnum
= 0;
766 digging
.level
.dlevel
= -1;
768 } else { /* not enough effort has been spent yet */
769 static const char *const d_target
[8] = {
770 "", "rock", "statue", "boulder", "door", "tree", "bars", "obstruction"
772 int dig_target
= dig_typ(uwep
, dpx
, dpy
);
774 if (IS_WALL(lev
->typ
) || dig_target
== DIGTYP_DOOR
) {
775 if(*in_rooms(dpx
, dpy
, SHOPBASE
)) {
776 pline("This %s seems too hard to %s.",
777 IS_DOOR(lev
->typ
) ? "door" : IS_MOUNTAIN(lev
->typ
) ? "mountain" : IS_FARMLAND(lev
->typ
) ? "farmland" : "wall", verb
);
780 } else if (!IS_ROCK(lev
->typ
) && !IS_WATERTUNNEL(lev
->typ
) && dig_target
== DIGTYP_ROCK
)
781 return(0); /* statue or boulder got taken */
783 if (is_lightsaber(uwep
)) You("burn steadily through %s.",
784 the(d_target
[dig_target
]));
786 You("hit the %s with all your might.",
787 d_target
[dig_target
]);
794 /* When will hole be finished? Very rough indication used by shopkeeper. */
798 if(occupation
!= dig
|| !*u
.ushops
) return(-1);
799 return ((250 - digging
.effort
) / 20);
802 /* Return typ of liquid to fill a hole with, or ROOM, if no liquid nearby */
809 int lo_x
= max(1,x
-1), hi_x
= min(x
+1,COLNO
-1),
810 lo_y
= max(0,y
-1), hi_y
= min(y
+1,ROWNO
-1);
811 int pool_cnt
= 0, moat_cnt
= 0, lava_cnt
= 0, urine_cnt
= 0, styx_cnt
= 0, shifting_cnt
= 0;
813 for (x1
= lo_x
; x1
<= hi_x
; x1
++)
814 for (y1
= lo_y
; y1
<= hi_y
; y1
++)
815 if (levl
[x1
][y1
].typ
== POOL
)
817 else if (levl
[x1
][y1
].typ
== MOAT
||
818 (levl
[x1
][y1
].typ
== DRAWBRIDGE_UP
&&
819 (levl
[x1
][y1
].drawbridgemask
& DB_UNDER
) == DB_MOAT
))
821 else if (levl
[x1
][y1
].typ
== LAVAPOOL
||
822 (levl
[x1
][y1
].typ
== DRAWBRIDGE_UP
&&
823 (levl
[x1
][y1
].drawbridgemask
& DB_UNDER
) == DB_LAVA
))
825 else if (levl
[x1
][y1
].typ
== URINELAKE
)
827 else if (levl
[x1
][y1
].typ
== STYXRIVER
)
829 else if (levl
[x1
][y1
].typ
== SHIFTINGSAND
)
831 pool_cnt
/= 3; /* not as much liquid as the others */
833 if (lava_cnt
> moat_cnt
+ pool_cnt
&& rn2(lava_cnt
+ 1))
835 else if (moat_cnt
> 0 && rn2(moat_cnt
+ 1))
837 else if (pool_cnt
> 0 && rn2(pool_cnt
+ 1))
839 else if (urine_cnt
> 0 && rn2(urine_cnt
+ 1))
841 else if (styx_cnt
> 0 && rn2(styx_cnt
+ 1))
843 else if (shifting_cnt
> 0 && rn2(shifting_cnt
+ 1))
850 digactualhole(x
, y
, madeby
, ttyp
)
852 struct monst
*madeby
;
855 struct obj
*oldobjs
, *newobjs
;
856 register struct trap
*ttmp
;
857 char surface_type
[BUFSZ
];
858 struct rm
*lev
= &levl
[x
][y
];
860 struct monst
*mtmp
= m_at(x
, y
); /* may be madeby */
861 boolean madeby_u
= (madeby
== BY_YOU
);
862 boolean madeby_obj
= (madeby
== BY_OBJECT
);
863 boolean at_u
= (x
== u
.ux
) && (y
== u
.uy
);
864 boolean wont_fall
= Levitation
|| Flying
;
866 if (u
.utrap
&& u
.utraptype
== TT_INFLOOR
) u
.utrap
= 0;
868 /* these furniture checks were in dighole(), but wand
869 breaking bypasses that routine and calls us directly */
870 if (IS_FOUNTAIN(lev
->typ
)) {
872 SET_FOUNTAIN_WARNED(x
,y
); /* force dryup */
873 dryup(x
, y
, madeby_u
);
875 } else if (IS_SINK(lev
->typ
)) {
878 } else if (IS_TOILET(lev
->typ
)) {
879 breaktoilet(u
.ux
,u
.uy
);
880 } else if (lev
->typ
== DRAWBRIDGE_DOWN
||
881 (is_drawbridge_wall(x
, y
) >= 0)) {
883 /* if under the portcullis, the bridge is adjacent */
884 (void) find_drawbridge(&bx
, &by
);
885 destroy_drawbridge(bx
, by
);
889 if (ttyp
!= PIT
&& !Can_dig_down(&u
.uz
)) {
890 impossible("digactualhole: can't dig %s on this level.",
891 defsyms
[trap_to_defsym(ttyp
)].explanation
);
895 /* maketrap() might change it, also, in this situation,
896 surface() returns an inappropriate string for a grave */
897 if (IS_GRAVE(lev
->typ
))
898 strcpy(surface_type
, "grave");
900 strcpy(surface_type
, surface(x
,y
));
901 shopdoor
= IS_DOOR(lev
->typ
) && *in_rooms(x
, y
, SHOPBASE
);
902 oldobjs
= level
.objects
[x
][y
];
903 ttmp
= maketrap(x
, y
, ttyp
, 0, FALSE
);
905 newobjs
= level
.objects
[x
][y
];
906 ttmp
->tseen
= ((madeby_u
|| cansee(x
,y
)) && !ttmp
->hiddentrap
);
907 ttmp
->madeby_u
= madeby_u
;
908 newsym(ttmp
->tx
,ttmp
->ty
);
913 You("dig a pit in the %s.", surface_type
);
914 u
.cnd_diggingamount
++;
915 if (shopdoor
) pay_for_damage("ruin", FALSE
);
916 } else if (!madeby_obj
&& canseemon(madeby
))
917 pline("%s digs a pit in the %s.", Monnam(madeby
), surface_type
);
918 else if (cansee(x
, y
) && flags
.verbose
)
919 pline("A pit appears in the %s.", surface_type
);
925 u
.utraptype
= TT_PIT
;
926 vision_full_recalc
= 1; /* vision limits change */
929 if (oldobjs
!= newobjs
) /* something unearthed */
930 (void) pickup(1); /* detects pit */
932 if(is_flyer(mtmp
->data
) || mtmp
->egotype_flying
|| is_floater(mtmp
->data
)) {
934 pline("%s %s over the pit.", Monnam(mtmp
),
935 (is_flyer(mtmp
->data
)) ?
937 } else if(mtmp
!= madeby
)
938 (void) mintrap(mtmp
);
940 } else { /* was TRAPDOOR now a HOLE*/
943 You("dig a hole through the %s.", surface_type
);
944 u
.cnd_diggingamount
++;
945 } else if(!madeby_obj
&& canseemon(madeby
))
946 pline("%s digs a hole through the %s.",
947 Monnam(madeby
), surface_type
);
948 else if(cansee(x
, y
) && flags
.verbose
)
949 pline("A hole appears in the %s.", surface_type
);
952 if (!u
.ustuck
&& !wont_fall
&& !next_to_u()) {
953 You("are jerked back by your pet!");
957 /* Floor objects get a chance of falling down. The case where
958 * the hero does NOT fall down is treated here. The case
959 * where the hero does fall down is treated in goto_level().
961 if (u
.ustuck
|| wont_fall
) {
963 impact_drop((struct obj
*)0, x
, y
, 0);
964 if (oldobjs
!= newobjs
)
966 if (shopdoor
&& madeby_u
) pay_for_damage("ruin", FALSE
);
970 const char *You_fall
= "You fall through...";
972 if (*u
.ushops
&& madeby_u
)
973 shopdig(1); /* shk might snatch pack */
974 /* handle earlier damage, eg breaking wand of digging */
975 else if (!madeby_u
) pay_for_damage("dig into", TRUE
);
977 /* Earlier checks must ensure that the destination
978 * level exists and is in the present dungeon.
980 newlevel
.dnum
= u
.uz
.dnum
;
981 newlevel
.dlevel
= u
.uz
.dlevel
+ 1;
982 /* Cope with holes caused by monster's actions -- ALI */
983 if (flags
.mon_moving
) {
984 schedule_goto(&newlevel
, FALSE
, TRUE
, FALSE
,
985 You_fall
, (char *)0);
987 pline("%s", You_fall
);
988 goto_level(&newlevel
, FALSE
, TRUE
, FALSE
);
989 /* messages for arriving in special rooms */
994 if (shopdoor
&& madeby_u
) pay_for_damage("ruin", FALSE
);
996 impact_drop((struct obj
*)0, x
, y
, 0);
998 /*[don't we need special sokoban handling here?]*/
999 if (is_flyer(mtmp
->data
) || mtmp
->egotype_flying
|| is_floater(mtmp
->data
) ||
1000 mtmp
->data
== &mons
[PM_WUMPUS
] ||
1001 (mtmp
->wormno
&& count_wsegs(mtmp
) > 5) ||
1002 mtmp
->data
->msize
>= MZ_HUGE
) return;
1003 if (mtmp
== u
.ustuck
) /* probably a vortex */
1004 return; /* temporary? kludge */
1006 if (teleport_pet(mtmp
, FALSE
)) {
1009 if (Is_stronghold(&u
.uz
)) {
1010 assign_level(&tolevel
, &valley_level
);
1011 } else if (Is_botlevel(&u
.uz
)) {
1012 if (canseemon(mtmp
))
1013 pline("%s avoids the trap.", Monnam(mtmp
));
1016 get_level(&tolevel
, depth(&u
.uz
) + 1);
1018 if (mtmp
->isshk
) make_angry_shk(mtmp
, 0, 0);
1019 migrate_to_level(mtmp
, ledger_no(&tolevel
),
1020 MIGR_RANDOM
, (coord
*)0);
1027 /* return TRUE if digging succeeded, FALSE otherwise */
1032 register struct trap
*ttmp
= t_at(u
.ux
, u
.uy
);
1033 struct rm
*lev
= &levl
[u
.ux
][u
.uy
];
1034 struct obj
*boulder_here
;
1036 boolean nohole
= !Can_dig_down(&u
.uz
);
1038 if ((ttmp
&& (ttmp
->ttyp
== MAGIC_PORTAL
|| ttmp
->ttyp
== HEEL_TRAP
|| ttmp
->ttyp
== ATTACKING_HEEL_TRAP
|| ttmp
->ttyp
== LOUDSPEAKER
|| ttmp
->ttyp
== KOP_CUBE
|| ttmp
->ttyp
== BOSS_SPAWNER
|| ttmp
->ttyp
== ARABELLA_SPEAKER
|| ttmp
->ttyp
== FART_TRAP
|| ttmp
->ttyp
== PERSISTENT_FART_TRAP
|| nohole
)) ||
1039 In_minotaurmaze(&u
.uz
) ||
1040 /* ALI - artifact doors */
1041 IS_DOOR(levl
[u
.ux
][u
.uy
].typ
) && artifact_door(u
.ux
, u
.uy
) ||
1042 (IS_ROCK(lev
->typ
) && lev
->typ
!= SDOOR
&&
1043 (lev
->wall_info
& W_NONDIGGABLE
) != 0)) {
1044 pline_The("%s here is too hard to dig in.", surface(u
.ux
,u
.uy
));
1046 } else if (is_waterypool(u
.ux
, u
.uy
) || is_styxriver(u
.ux
, u
.uy
) || is_lava(u
.ux
, u
.uy
)) {
1047 pline_The("%s sloshes furiously for a moment, then subsides.",
1048 is_lava(u
.ux
, u
.uy
) ? "lava" : "water");
1049 wake_nearby(); /* splashing */
1051 } else if (lev
->typ
== DRAWBRIDGE_DOWN
||
1052 (is_drawbridge_wall(u
.ux
, u
.uy
) >= 0)) {
1053 /* drawbridge_down is the platform crossing the moat when the
1054 bridge is extended; drawbridge_wall is the open "doorway" or
1055 closed "door" where the portcullis/mechanism is located */
1057 pline_The("drawbridge seems too hard to dig through.");
1059 } else if (IS_GRAVE(lev
->typ
)) {
1060 digactualhole(u
.ux
, u
.uy
, BY_YOU
, PIT
);
1064 int x
= u
.ux
, y
= u
.uy
;
1065 /* if under the portcullis, the bridge is adjacent */
1066 (void) find_drawbridge(&x
, &y
);
1067 destroy_drawbridge(x
, y
);
1071 } else if ((boulder_here
= sobj_at(BOULDER
, u
.ux
, u
.uy
)) != 0) {
1072 if (ttmp
&& (ttmp
->ttyp
== PIT
|| ttmp
->ttyp
== SPIKED_PIT
|| ttmp
->ttyp
== SHIT_PIT
|| ttmp
->ttyp
== MANA_PIT
|| ttmp
->ttyp
== ANOXIC_PIT
|| ttmp
->ttyp
== HYPOXIC_PIT
|| ttmp
->ttyp
== ACID_PIT
) &&
1074 pline_The("boulder settles into the pit.");
1075 ttmp
->ttyp
= PIT
; /* crush spikes */
1076 } else if (ttmp
&& ttmp
->ttyp
== GIANT_CHASM
) {
1077 pline("KADOOM! The boulder falls in!");
1080 * digging makes a hole, but the boulder immediately
1081 * fills it. Final outcome: no hole, no boulder.
1083 pline("KADOOM! The boulder falls in!");
1084 (void) delfloortrap(ttmp
);
1086 delobj(boulder_here
);
1089 } else if (IS_GRAVE(lev
->typ
)) {
1091 digactualhole(u
.ux
, u
.uy
, BY_YOU
, PIT
);
1093 } else if (lev
->typ
== DRAWBRIDGE_UP
) {
1094 /* must be floor or ice, other cases handled above */
1095 /* dig "pit" and let fluid flow in (if possible) */
1096 typ
= fillholetyp(u
.ux
,u
.uy
);
1100 * We can't dig a hole here since that will destroy
1101 * the drawbridge. The following is a cop-out. --dlc
1103 pline_The("%s here is too hard to dig in.",
1104 surface(u
.ux
, u
.uy
));
1108 lev
->drawbridgemask
&= ~DB_UNDER
;
1109 lev
->drawbridgemask
|= (typ
== LAVAPOOL
) ? DB_LAVA
: DB_MOAT
;
1112 if (ttmp
) (void) delfloortrap(ttmp
);
1113 /* if any objects were frozen here, they're released now */
1114 unearth_objs(u
.ux
, u
.uy
);
1116 pline("As you dig, the hole fills with %s!",
1117 typ
== LAVAPOOL
? "lava" : typ
== STYXRIVER
? "an icky green liquid" : typ
== URINELAKE
? "urine" : typ
== SHIFTINGSAND
? "quicksand" : "water");
1118 /* KMH, balance patch -- new intrinsic */
1119 if (!Levitation
&& !Flying
&& typ
!= STYXRIVER
&& typ
!= URINELAKE
&& typ
!= SHIFTINGSAND
) {
1120 if (typ
== LAVAPOOL
)
1121 (void) lava_effects();
1122 else if (!Wwalking
&& !Race_if(PM_KORONST
) && !Swimming
)
1127 /* the following two are here for the wand of digging */
1128 } else if (IS_THRONE(lev
->typ
)) {
1129 pline_The("throne is too hard to break apart.");
1131 } else if (IS_FARMLAND(lev
->typ
)) {
1132 pline("Farmland cannot be dug out.");
1133 } else if (IS_MOUNTAIN(lev
->typ
)) {
1134 pline_The("mountain is too hard to dig into.");
1135 } else if (IS_GRAVEWALL(lev
->typ
)) {
1136 pline_The("grave wall needs to be dug by moving into it.");
1138 } else if (IS_ALTAR(lev
->typ
)) {
1139 pline_The("altar is too hard to break apart.");
1142 typ
= fillholetyp(u
.ux
,u
.uy
);
1149 /* finally we get to make a hole */
1150 if (nohole
|| pit_only
)
1151 digactualhole(u
.ux
, u
.uy
, BY_YOU
, PIT
);
1153 digactualhole(u
.ux
, u
.uy
, BY_YOU
, HOLE
);
1166 /* Grave-robbing is frowned upon... */
1167 exercise(A_WIS
, FALSE
);
1168 if (uwep
&& uwep
->oartifact
== ART_JAPANESE_WOMEN
) {
1170 increasesincounter(1);
1173 You("disturb the honorable dead!");
1175 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_JAPANESE_WOMEN
) {
1177 increasesincounter(1);
1180 You("disturb the honorable dead!");
1182 if (uwep
&& uwep
->oartifact
== ART_SAKUSHNIR
) {
1184 increasesincounter(1);
1187 You("disturb the honorable dead!");
1189 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_SAKUSHNIR
) {
1191 increasesincounter(1);
1194 You("disturb the honorable dead!");
1196 if (Role_if(PM_ARCHEOLOGIST
)) {
1197 adjalign(-sgn(u
.ualign
.type
)*3);
1198 increasesincounter(1);
1201 You_feel("like a despicable grave-robber!");
1203 if (Role_if(PM_SAMURAI
)) {
1204 adjalign(-sgn(u
.ualign
.type
)*5); /* stiffer penalty */
1205 increasesincounter(1);
1208 You("disturb the honorable dead!");
1210 if (uwep
&& uwep
->otyp
== HONOR_KATANA
) {
1211 adjalign(-sgn(u
.ualign
.type
)*5); /* stiffer penalty */
1212 increasesincounter(1);
1215 You("disturb the honorable dead!");
1217 if (u
.twoweap
&& uswapwep
&& uswapwep
->otyp
== HONOR_KATANA
) {
1218 adjalign(-sgn(u
.ualign
.type
)*5); /* stiffer penalty */
1219 increasesincounter(1);
1222 You("disturb the honorable dead!");
1224 if (u
.ualign
.type
== A_LAWFUL
) {
1225 adjalign(-sgn(u
.ualign
.type
)*2);
1226 You("have violated the sanctity of this grave!");
1232 You("unearth a corpse.");
1233 if (!!(otmp
= mk_tt_object(CORPSE
, u
.ux
, u
.uy
)))
1234 otmp
->age
-= 100; /* this is an *OLD* corpse */;
1237 if (!Blind
) pline(FunnyHallu
? "Dude! The living dead!" :
1238 "The grave's owner is very upset!");
1240 if (Aggravate_monster
) {
1242 reset_rndmonst(NON_PM
);
1245 (void) makemon(mkclass(S_ZOMBIE
,0), u
.ux
, u
.uy
, NO_MM_FLAGS
);
1251 if (!Blind
) pline(FunnyHallu
? "I want my mummy!" :
1252 "You've disturbed a tomb!");
1254 if (Aggravate_monster
) {
1256 reset_rndmonst(NON_PM
);
1259 (void) makemon(mkclass(S_MUMMY
,0), u
.ux
, u
.uy
, NO_MM_FLAGS
);
1266 pline_The("grave seems unused. Strange....");
1269 levl
[u
.ux
][u
.uy
].typ
= ROOM
;
1270 del_engr_at(u
.ux
, u
.uy
);
1283 register char *dsp
= dirsyms
;
1284 register int rx
, ry
;
1286 register const char *sdp
, *verb
;
1288 if(iflags
.num_pad
) sdp
= ndir
; else sdp
= sdir
; /* DICE workaround */
1292 if (!wield_tool(obj
, "swing")) return 0;
1295 ispick
= is_pick(obj
);
1296 isantibar
= is_antibar(obj
);
1297 verb
= ispick
? "dig" : isantibar
? "lash out" : "chop";
1299 if (u
.utrap
&& u
.utraptype
== TT_WEB
) {
1300 pline("%s you can't %s while entangled in a web.",
1301 /* res==0 => no prior message;
1302 res==1 => just got "You now wield a pick-axe." message */
1303 !res
? "Unfortunately," : "But", verb
);
1304 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1308 if (u
.utrap
&& u
.utraptype
== TT_GLUE
) {
1309 pline("%s you can't %s while being held by the glue.",
1310 /* res==0 => no prior message;
1311 res==1 => just got "You now wield a pick-axe." message */
1312 !res
? "Unfortunately," : "But", verb
);
1313 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1318 (void) movecmd(*sdp
); /* sets u.dx and u.dy and u.dz */
1321 /* Include down even with axe, so we have at least one direction */
1323 (u
.dz
== 0 && isok(rx
, ry
) &&
1324 dig_typ(obj
, rx
, ry
) != DIGTYP_UNDIGGABLE
))
1329 sprintf(qbuf
, "In what direction do you want to %s? [%s]", verb
, dirsyms
);
1333 return (use_pick_axe2(obj
));
1336 /* general dig through doors/etc. function
1337 * Handles pickaxes/lightsabers/axes
1338 * called from doforce and use_pick_axe
1341 /* MRKR: use_pick_axe() is split in two to allow autodig to bypass */
1342 /* the "In what direction do you want to dig?" query. */
1343 /* use_pick_axe2() uses the existing u.dx, u.dy and u.dz */
1345 int use_pick_axe2(obj
)
1348 register int rx
, ry
;
1349 register struct rm
*lev
;
1350 int dig_target
, digtyp
;
1351 boolean ispick
= is_pick(obj
);
1352 const char *verbing
= ispick
? "digging" :
1353 is_lightsaber(uwep
) ? "cutting" :
1356 /* 0 = pick, 1 = lightsaber, 2 = axe */
1357 digtyp
= (is_pick(uwep
) ? 0 :
1358 is_lightsaber(uwep
) ? 1 :
1361 if (u
.uswallow
&& attack(u
.ustuck
)) {
1363 } else if (Underwater
) {
1364 pline("Turbulence torpedoes your %s attempts.", verbing
);
1365 } else if(u
.dz
< 0) {
1368 pline_The("ceiling is too hard to cut through.");
1370 You("don't have enough leverage.");
1372 You_cant("reach the %s.",ceiling(u
.ux
,u
.uy
));
1373 } else if(!u
.dx
&& !u
.dy
&& !u
.dz
) {
1374 /* NOTREACHED for lightsabers/axes called from doforce */
1379 dam
= rnd(2) + dbon() + obj
->spe
;
1380 if (dam
<= 0) dam
= 1;
1381 if (obj
->otyp
== SEXY_LEATHER_PUMP
) {
1382 if (ACURR(A_INT
) >= 6) pline("Klock! You hit yourself with your sexy leather pump, producing a beautiful sound.");
1383 else pline("Klock! You hit yourself with your sexy leather pump, producing a hollow sound.");
1384 } else if (obj
->otyp
== BLOCK_HEELED_COMBAT_BOOT
) You_feel("a wonderfully painful sensation as you hit yourself with your fleecy block-heeled combat boot.");
1385 else if (obj
->otyp
== TORPEDO
) pline("You deal yourself a deep gash with your torpedo!");
1386 else if (obj
->otyp
== YATAGAN
) pline("You terribly hurt yourself with your blade!");
1387 else if (obj
->otyp
== DIAMOND_SMASHER
) pline("You see lots of little asterisks as the diamond club hits you!");
1388 else if (obj
->otyp
== HOMING_TORPEDO
) pline("The torpedo strikes right into your vital organs!");
1389 else if (obj
->otyp
== RADIOACTIVE_DAGGER
) pline("You irradiate yourself with your dagger!");
1390 else if (obj
->otyp
== IMPACT_STAFF
) pline("Dock! You hit yourself with your staff!");
1391 else if (obj
->otyp
== BLOCK_HEELED_SANDAL
) pline("Mmmmmmmm, the massive block heel hits your %s so wonderfully painfully!", body_part(HEAD
));
1392 else if (obj
->otyp
== INKA_BOOT
) pline("You come right as the lovely, soft boot heel hits you.");
1393 else if (obj
->otyp
== SEXY_MARY_JANE
) pline("Wow, the area between your %s gets all wet as the fleecy-soft, massive block heel hits you!", makeplural(body_part(LEG
)) );
1394 else if (obj
->otyp
== PROSTITUTE_SHOE
) pline("You have an orgasm as you hit yourself with the incredibly female prostitute shoe.");
1395 else if (obj
->otyp
== SOFT_LADY_SHOE
) pline("You feel wonderful intense pain as the incredibly soft lady shoe hits you.");
1396 else if (obj
->otyp
== STEEL_WHIP
) {
1397 if (flags
.female
) You_feel("like a submissive girl as you whip yourself!");
1398 else pline("You enjoy the feeling of pain as the whip hits your bare skin!");
1400 else if (obj
->otyp
== HIGH_HEELED_SANDAL
) pline("Ouch - you hit yourself with a massive high heel! It's very painful!");
1401 else if (obj
->otyp
== WEDGED_LITTLE_GIRL_SANDAL
) pline("You hit yourself with a lovely wedge heel! Even though it looks very innocuous, you can definitely feel intense pain...");
1402 else if (obj
->otyp
== HUGGING_BOOT
) pline("You bonk yourself with a thick winter boot - seems that this boot is made from a harder material than your %s...", body_part(HEAD
));
1403 else You("hit yourself with %s.", yname(uwep
));
1404 sprintf(buf
, "%s own %s", uhis(),
1405 OBJ_NAME(objects
[obj
->otyp
]));
1406 losehp(dam
, buf
, KILLED_BY
);
1409 } else if(u
.dz
== 0) {
1410 if ((Stunned
&& !rn2(issoviet
? 1 : StrongStun_resist
? 20 : Stun_resist
? 8 : 2)) || (Confusion
&& !rn2(issoviet
? 2 : StrongConf_resist
? 200 : Conf_resist
? 40 : 8))) confdir();
1414 if (digtyp
== 1) pline("Your %s bounces off harmlessly.",
1415 aobjnam(obj
, (char *)0));
1416 else pline("Clash!");
1419 lev
= &levl
[rx
][ry
];
1420 if(MON_AT(rx
, ry
) && attack(m_at(rx
, ry
)))
1422 dig_target
= dig_typ(obj
, rx
, ry
);
1423 if (dig_target
== DIGTYP_UNDIGGABLE
) {
1424 /* ACCESSIBLE or POOL */
1425 struct trap
*trap
= t_at(rx
, ry
);
1427 if (trap
&& trap
->ttyp
== WEB
) {
1428 if (!trap
->tseen
&& !trap
->hiddentrap
) {
1430 There("is a spider web there!");
1432 Your("%s entangled in the web.",
1433 aobjnam(obj
, "become"));
1434 /* you ought to be able to let go; tough luck */
1435 /* (maybe `move_into_trap()' would be better) */
1436 nomul(-d(2,2), "stuck in a spider web", TRUE
);
1437 nomovemsg
= "You pull free.";
1438 } else if (lev
->typ
== IRONBARS
) {
1441 } else if (IS_TREE(lev
->typ
))
1442 You("need an axe to cut down a tree.");
1443 else if (IS_FARMLAND(lev
->typ
))
1444 You("need to use the force to remove farmland.");
1445 else if (IS_MOUNTAIN(lev
->typ
))
1446 You("cannot dig out an entire mountain.");
1447 else if (IS_ROCK(lev
->typ
))
1448 You("need a pick to dig rock.");
1449 else if (!ispick
&& (sobj_at(STATUE
, rx
, ry
) ||
1450 sobj_at(BOULDER
, rx
, ry
))) {
1451 boolean vibrate
= !rn2(3);
1452 pline("Sparks fly as you whack the %s.%s",
1453 sobj_at(STATUE
, rx
, ry
) ? "statue" : "boulder",
1454 vibrate
? " The axe-handle vibrates violently!" : "");
1455 if (vibrate
) losehp(2, "axing a hard object", KILLED_BY
);
1458 You("swing your %s through thin air.", aobjnam(obj
, (char *)0));
1459 if (FunnyHallu
) pline("It creates erotic air current noises.");
1462 static const char * const d_action
[8][2] = {
1463 {"swinging","slicing the air"},
1464 {"digging","cutting through the wall"},
1465 {"chipping the statue","cutting the statue"},
1466 {"hitting the boulder","cutting through the boulder"},
1467 {"chopping at the door","burning through the door"},
1468 {"cutting the tree","razing the tree"},
1469 {"smashing the bars","breaking the bars"},
1470 {"smashing the obstruction","breaking the obstruction"}
1472 did_dig_msg
= FALSE
;
1473 digging
.quiet
= FALSE
;
1474 if (digging
.pos
.x
!= rx
|| digging
.pos
.y
!= ry
||
1475 !on_level(&digging
.level
, &u
.uz
) || digging
.down
) {
1476 if (flags
.autodig
&&
1477 dig_target
== DIGTYP_ROCK
&& !digging
.down
&&
1478 digging
.pos
.x
== u
.ux
&&
1479 digging
.pos
.y
== u
.uy
&&
1480 (moves
<= digging
.lastdigtime
+2 &&
1481 moves
>= digging
.lastdigtime
)) {
1482 /* avoid messages if repeated autodigging */
1484 digging
.quiet
= TRUE
;
1486 digging
.down
= digging
.chew
= FALSE
;
1487 digging
.warned
= FALSE
;
1490 assign_level(&digging
.level
, &u
.uz
);
1493 You("start %s.", d_action
[dig_target
][digtyp
== 1]);
1495 You("%s %s.", digging
.chew
? "begin" : "continue",
1496 d_action
[dig_target
][digtyp
== 1]);
1497 digging
.chew
= FALSE
;
1499 set_occupation(dig
, verbing
, 0);
1500 if (AutoDestruct
|| u
.uprops
[AUTO_DESTRUCT
].extrinsic
|| (uarmf
&& uarmf
->oartifact
== ART_KHOR_S_REQUIRED_IDEA
) || have_autodestructstone() || (uchain
&& uchain
->oartifact
== ART_SIYID
) ) dig();
1502 } else if (Is_airlevel(&u
.uz
) || Is_waterlevel(&u
.uz
)) {
1503 /* it must be air -- water checked above */
1504 You("swing your %s through thin air.", aobjnam(obj
, (char *)0));
1505 if (FunnyHallu
) pline("It creates erotic air current noises.");
1506 } else if (!can_reach_floor()) {
1507 You_cant("reach the %s.", surface(u
.ux
,u
.uy
));
1508 } else if (is_waterypool(u
.ux
, u
.uy
) || is_lava(u
.ux
, u
.uy
)) {
1509 /* Monsters which swim also happen not to be able to dig */
1510 You("cannot stay under%s long enough.",
1511 is_waterypool(u
.ux
, u
.uy
) ? "water" : " the lava");
1512 } else if (digtyp
== 2) {
1513 Your("%s merely scratches the %s.",
1514 aobjnam(obj
, (char *)0), surface(u
.ux
,u
.uy
));
1517 if (digging
.pos
.x
!= u
.ux
|| digging
.pos
.y
!= u
.uy
||
1518 !on_level(&digging
.level
, &u
.uz
) || !digging
.down
) {
1519 digging
.chew
= FALSE
;
1520 digging
.down
= TRUE
;
1521 digging
.warned
= FALSE
;
1522 digging
.pos
.x
= u
.ux
;
1523 digging
.pos
.y
= u
.uy
;
1524 assign_level(&digging
.level
, &u
.uz
);
1526 You("start %s downward.", verbing
);
1527 if (*u
.ushops
) shopdig(0);
1529 You("continue %s downward.", verbing
);
1530 did_dig_msg
= FALSE
;
1531 set_occupation(dig
, verbing
, 0);
1532 if (AutoDestruct
|| u
.uprops
[AUTO_DESTRUCT
].extrinsic
|| (uarmf
&& uarmf
->oartifact
== ART_KHOR_S_REQUIRED_IDEA
) || have_autodestructstone() || (uchain
&& uchain
->oartifact
== ART_SIYID
) ) dig();
1538 * Town Watchmen frown on damage to the town walls, trees or fountains.
1539 * It's OK to dig holes in the ground, however.
1540 * If mtmp is assumed to be a watchman, a watchman is found if mtmp == 0
1541 * zap == TRUE if wand/spell of digging, FALSE otherwise (chewing)
1544 watch_dig(mtmp
, x
, y
, zap
)
1549 struct rm
*lev
= &levl
[x
][y
];
1551 if (in_town(x
, y
) &&
1552 (closed_door(x
, y
) || lev
->typ
== SDOOR
||
1553 IS_WALL(lev
->typ
) || IS_FOUNTAIN(lev
->typ
) || IS_TREE(lev
->typ
))) {
1555 for(mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
1556 if (DEADMONSTER(mtmp
)) continue;
1557 if ((mtmp
->data
== &mons
[PM_WATCHMAN
] || mtmp
->data
== &mons
[PM_WATCH_LIEUTENANT
] || mtmp
->data
== &mons
[PM_WATCH_LEADER
] || mtmp
->data
== &mons
[PM_WATCH_CAPTAIN
]) &&
1558 mtmp
->mcansee
&& m_canseeu(mtmp
) &&
1559 couldsee(mtmp
->mx
, mtmp
->my
) && mtmp
->mpeaceful
)
1565 if(zap
|| digging
.warned
) {
1566 verbalize("Halt, vandal! You're under arrest!");
1567 (void) angry_guards(!(flags
.soundok
));
1571 if (IS_DOOR(lev
->typ
))
1573 else if (IS_TREE(lev
->typ
))
1575 else if (IS_ROCK(lev
->typ
))
1579 verbalize("Hey, stop damaging that %s!", str
);
1580 digging
.warned
= TRUE
;
1591 /* Return TRUE if monster died, FALSE otherwise. Called from m_move(). */
1594 register struct monst
*mtmp
;
1596 register struct rm
*here
;
1597 int pile
= rnd(24); /* nerf by Amy - if this is lower than 5, create a pile, used to be rnd(12) */
1599 here
= &levl
[mtmp
->mx
][mtmp
->my
];
1600 if (here
->typ
== SDOOR
)
1601 cvt_sdoor_to_door(here
); /* ->typ = DOOR */
1603 /* Eats away door if present & closed or locked */
1604 if (closed_door(mtmp
->mx
, mtmp
->my
)) {
1605 if (*in_rooms(mtmp
->mx
, mtmp
->my
, SHOPBASE
))
1606 add_damage(mtmp
->mx
, mtmp
->my
, 0L);
1607 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1608 if (!(levl
[mtmp
->mx
][mtmp
->my
].wall_info
& W_HARDGROWTH
)) levl
[mtmp
->mx
][mtmp
->my
].wall_info
|= W_EASYGROWTH
;
1609 if (here
->doormask
& D_TRAPPED
) {
1610 here
->doormask
= D_NODOOR
;
1611 if (mb_trapped(mtmp
)) { /* mtmp is killed */
1612 newsym(mtmp
->mx
, mtmp
->my
);
1616 if (!rn2(3) && flags
.verbose
) /* not too often.. */
1617 You_feel("an unexpected draft.");
1618 here
->doormask
= D_BROKEN
;
1620 newsym(mtmp
->mx
, mtmp
->my
);
1622 } else if ((!IS_ROCK(here
->typ
) && !IS_WATERTUNNEL(here
->typ
) && !IS_TREE(here
->typ
)) || IS_FARMLAND(here
->typ
) || IS_MOUNTAIN(here
->typ
) || IS_GRAVEWALL(here
->typ
)) /* no dig */
1625 /* Only rock, trees, and walls fall through to this point. */
1626 if ((here
->wall_info
& W_NONDIGGABLE
) != 0) { /* This is not a bug. So let's get rid of the message. --Amy */
1627 /*impossible*//*pline("mdig_tunnel: %s at (%d,%d) is undiggable",
1628 (IS_WALL(here->typ) ? "wall" : IS_MOUNTAIN(here->typ) ? "mountain" : IS_FARMLAND(here->typ) ? "farmland" : "stone"),
1629 (int) mtmp->mx, (int) mtmp->my);*/
1630 return FALSE
; /* still alive */
1633 if (IS_WALL(here
->typ
)) {
1635 u
.cnd_monsterdigamount
++;
1637 /* KMH -- Okay on arboreal levels (room walls are still stone) */
1638 if (flags
.soundok
&& flags
.verbose
&& !rn2(5)) {
1639 /* KMH -- Okay on arboreal levels (room walls are still stone) */
1640 You_hear("crashing rock.");
1641 if (PlayerHearsSoundEffects
) pline(issoviet
? "Stena teper' ushla navsegda." : "Derrsch!");
1643 if (*in_rooms(mtmp
->mx
, mtmp
->my
, SHOPBASE
))
1644 add_damage(mtmp
->mx
, mtmp
->my
, 0L);
1645 if (level
.flags
.is_maze_lev
) {
1647 } else if (level
.flags
.is_cavernous_lev
&&
1648 !in_town(mtmp
->mx
, mtmp
->my
)) {
1650 } else if (IS_WATERTUNNEL(here
->typ
)) {
1652 } else if (IS_DIGGABLEWALL(here
->typ
)) {
1656 here
->doormask
= D_NODOOR
;
1658 } else if (IS_TREE(here
->typ
)) {
1660 if (!rn2(50) && !(here
->looted
& TREE_LOOTED
) && pile
&& pile
< 5) /* it shouldn't be that easy to get tree fruits... --Amy */
1661 (void) rnd_treefruit_at(mtmp
->mx
, mtmp
->my
);
1662 } else if (IS_WATERTUNNEL(here
->typ
)) {
1663 u
.cnd_monsterdigamount
++;
1666 u
.cnd_monsterdigamount
++;
1668 if (!rn2(7) && pile
&& pile
< 5) /* if you dig out rock yourself, you don't get boulders or rock either! --Amy */
1669 (void) mksobj_at((pile
== 1) ? BOULDER
: ROCK
,
1670 mtmp
->mx
, mtmp
->my
, TRUE
, FALSE
, FALSE
);
1672 newsym(mtmp
->mx
, mtmp
->my
);
1673 if (!sobj_at(BOULDER
, mtmp
->mx
, mtmp
->my
))
1674 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1675 if (!(levl
[mtmp
->mx
][mtmp
->my
].wall_info
& W_HARDGROWTH
)) levl
[mtmp
->mx
][mtmp
->my
].wall_info
|= W_EASYGROWTH
;
1685 register struct obj
*otmp
, *next_obj
;
1686 int zx
, zy
, digdepth
;
1687 boolean shopdoor
, shopwall
, maze_dig
;
1689 int diggingiteration
= 0;
1693 switch (diggingiteration
) {
1730 /* normal case: digging across the level */
1731 shopdoor
= shopwall
= FALSE
;
1732 maze_dig
= level
.flags
.is_maze_lev
&& !Is_earthlevel(&u
.uz
);
1735 digdepth
= rn1(18, 8);
1736 if (Race_if(PM_IRAHA
)) digdepth
*= 2;
1737 tmp_at(DISP_BEAM
, cmap_to_glyph(S_digbeam
));
1738 while (--digdepth
>= 0) {
1739 if (!isok(zx
,zy
)) break;
1740 room
= &levl
[zx
][zy
];
1742 delay_output(); /* wait a little bit */
1744 /* WAC check for monster, boulder */
1745 if ((mtmp
= m_at(zx
, zy
)) != 0) {
1746 if (made_of_rock(mtmp
->data
)) {
1747 You("gouge a hole in %s!", mon_nam(mtmp
));
1749 if (mtmp
->mhp
< 1) mtmp
->mhp
= 1;
1751 } else pline("%s is unaffected!", Monnam(mtmp
));
1753 for(otmp
= level
.objects
[zx
][zy
]; otmp
; otmp
= next_obj
) {
1754 next_obj
= otmp
->nexthere
;
1755 /* vaporize boulders */
1756 if (otmp
->otyp
== BOULDER
) {
1758 /* A little Sokoban guilt... */
1759 if (In_sokoban(&u
.uz
) && !playercancheatinsoko()) {
1761 pline("You cheater!");
1762 if (evilfriday
) u
.ugangr
++;
1764 unblock_point(zx
, zy
);
1766 pline_The("boulder is vaporized!");
1771 if (closed_door(zx
, zy
) || room
->typ
== SDOOR
) {
1772 /* ALI - Artifact doors */
1773 if (artifact_door(zx
, zy
)) {
1775 pline_The("door glows then fades.");
1778 if (*in_rooms(zx
,zy
,SHOPBASE
)) {
1779 add_damage(zx
, zy
, 400L);
1782 if (room
->typ
== SDOOR
)
1784 else if (cansee(zx
, zy
))
1785 pline_The("door is razed!");
1786 watch_dig((struct monst
*)0, zx
, zy
, TRUE
);
1787 room
->doormask
= D_NODOOR
;
1788 unblock_point(zx
,zy
); /* vision */
1790 if (issoviet
&& maze_dig
) pline("Vy ne mozhete kopat'! Poskol'ku Sovetskiy Pyat' Lo nenavidit vashi kishki!");
1791 if (issoviet
&& maze_dig
) break;
1792 } else if (maze_dig
) {
1793 if (IS_WATERTUNNEL(room
->typ
)) {
1795 unblock_point(zx
,zy
); /* vision */
1796 digdepth
-= 2; /* fix stupidity --Amy */
1797 if (issoviet
) pline("Vy ne mozhete kopat'! Poskol'ku Sovetskiy Pyat' Lo nenavidit vashi kishki!");
1798 if (issoviet
) break;
1800 } if (IS_WALL(room
->typ
) && !(IS_FARMLAND(room
->typ
)) && !(IS_MOUNTAIN(room
->typ
)) && !(IS_GRAVEWALL(room
->typ
)) ) {
1801 if (!(room
->wall_info
& W_NONDIGGABLE
)) {
1802 if (*in_rooms(zx
,zy
,SHOPBASE
)) {
1803 add_damage(zx
, zy
, 200L);
1806 room
->typ
= /*ROOM*/CORR
;
1807 unblock_point(zx
,zy
); /* vision */
1808 if (!(levl
[zx
][zy
].wall_info
& W_HARDGROWTH
)) levl
[zx
][zy
].wall_info
|= W_EASYGROWTH
;
1809 digdepth
-= 2; /* fix stupidity --Amy */
1810 if (issoviet
) pline("Vy ne mozhete kopat'! Poskol'ku Sovetskiy Pyat' Lo nenavidit vashi kishki!");
1811 if (issoviet
) break;
1812 } else if (!Blind
) {
1813 pline_The("wall glows then fades.");
1816 } else if (IS_TREE(room
->typ
)) { /* check trees before stone */
1817 if (!(room
->wall_info
& W_NONDIGGABLE
)) {
1819 unblock_point(zx
,zy
); /* vision */
1820 if (!(levl
[zx
][zy
].wall_info
& W_HARDGROWTH
)) levl
[zx
][zy
].wall_info
|= W_EASYGROWTH
;
1821 digdepth
-= 2; /* fix stupidity --Amy */
1822 if (issoviet
) pline("Vy ne mozhete kopat'! Poskol'ku Sovetskiy Pyat' Lo nenavidit vashi kishki!");
1823 if (issoviet
) break;
1824 } else if (!Blind
) {
1825 pline_The("tree shudders but is unharmed.");
1828 } else if (room
->typ
== STONE
|| room
->typ
== SCORR
) {
1829 if (!(room
->wall_info
& W_NONDIGGABLE
)) {
1831 unblock_point(zx
,zy
); /* vision */
1832 if (!(levl
[zx
][zy
].wall_info
& W_HARDGROWTH
)) levl
[zx
][zy
].wall_info
|= W_EASYGROWTH
;
1833 digdepth
--; /* fix stupidity --Amy */
1834 /* In Soviet Russia, digging has to be done one block at a time. Faster digging methods are capitalistic
1835 * and evil, so they're not allowed. I wonder how long until they decide to make mazes undiggable... --Amy */
1836 if (issoviet
) pline("Vy ne mozhete kopat'! Poskol'ku Sovetskiy Pyat' Lo nenavidit vashi kishki!");
1837 if (issoviet
) break;
1838 } else if (!Blind
) {
1839 pline_The("rock glows then fades.");
1843 } else if (IS_ROCK(room
->typ
) || IS_WATERTUNNEL(room
->typ
)) {
1844 if (!may_dig(zx
,zy
)) break;
1845 if (IS_WALL(room
->typ
) || room
->typ
== SDOOR
) {
1846 if (*in_rooms(zx
,zy
,SHOPBASE
)) {
1847 add_damage(zx
, zy
, 200L);
1850 watch_dig((struct monst
*)0, zx
, zy
, TRUE
);
1851 if (level
.flags
.is_cavernous_lev
&& !in_town(zx
, zy
)) {
1853 } else if (IS_WATERTUNNEL(room
->typ
)) {
1855 } else if (IS_DIGGABLEWALL(room
->typ
)) {
1859 room
->doormask
= D_NODOOR
;
1862 } else if (IS_TREE(room
->typ
)) {
1865 } else if (IS_WATERTUNNEL(room
->typ
)) {
1868 } else { /* IS_ROCK but not IS_WALL or SDOOR */
1872 unblock_point(zx
,zy
); /* vision */
1873 if (!(levl
[zx
][zy
].wall_info
& W_HARDGROWTH
)) levl
[zx
][zy
].wall_info
|= W_EASYGROWTH
;
1878 tmp_at(DISP_END
,0); /* closing call */
1879 if (shopdoor
|| shopwall
)
1880 pay_for_damage(shopdoor
? "destroy" : "dig into", FALSE
);
1884 if (diggingiteration
< 8) goto nextiteration
;
1893 /* digging via wand zap or spell cast */
1900 /* struct obj *otmp;*/
1901 register struct obj
*otmp
, *next_obj
;
1902 int zx
, zy
, digdepth
;
1903 boolean shopdoor
, shopwall
, maze_dig
;
1905 * Original effect (approximately):
1906 * from CORR: dig until we pierce a wall
1907 * from ROOM: pierce wall and dig until we reach
1908 * an ACCESSIBLE place.
1909 * Currently: dig for digdepth positions;
1910 * also down on request of Lennart Augustsson.
1916 if (!is_whirly(mtmp
->data
)) {
1917 if (is_animal(mtmp
->data
))
1918 You("pierce %s %s wall!",
1919 s_suffix(mon_nam(mtmp
)), mbodypart(mtmp
, STOMACH
));
1921 mtmp
->mhp
/= 5; /* prevent easy Jubilex killing --Amy */
1926 if (mtmp
->mhp
< 1) mtmp
->mhp
= 1; /* fixes the bug where killing gray newts causes error messages */
1927 expels(mtmp
, mtmp
->data
, !is_animal(mtmp
->data
));
1933 if (!Is_airlevel(&u
.uz
) && !Is_waterlevel(&u
.uz
) && !Underwater
) {
1934 if (u
.dz
< 0 || On_stairs(u
.ux
, u
.uy
)) {
1935 if (On_stairs(u
.ux
, u
.uy
))
1936 pline_The("beam bounces off the %s and hits the %s.",
1937 (u
.ux
== xdnladder
|| u
.ux
== xupladder
) ?
1938 "ladder" : "stairs", ceiling(u
.ux
, u
.uy
));
1939 You("loosen a rock from the %s.", ceiling(u
.ux
, u
.uy
));
1940 pline("It falls on your %s!", body_part(HEAD
));
1941 losehp(rnd((uarmh
&& is_hardmaterial(uarmh
)) ? 2 : 6),
1942 "falling rock", KILLED_BY_AN
);
1943 otmp
= mksobj_at(ROCK
, u
.ux
, u
.uy
, FALSE
, FALSE
, FALSE
);
1948 if (rn2(2)) otmp
->blessed
= rn2(2);
1949 else blessorcurse(otmp
, 3);
1950 } else if(!rn2(10)) {
1951 if (rn2(10)) curse(otmp
);
1952 else blessorcurse(otmp
, 3);
1953 otmp
->spe
= -rne(2);
1954 } else blessorcurse(otmp
, 10);
1956 (void)xname(otmp
); /* set dknown, maybe bknown */
1961 watch_dig((struct monst
*)0, u
.ux
, u
.uy
, TRUE
);
1962 (void) dighole(FALSE
);
1968 /* normal case: digging across the level */
1969 shopdoor
= shopwall
= FALSE
;
1970 maze_dig
= level
.flags
.is_maze_lev
&& !Is_earthlevel(&u
.uz
);
1973 digdepth
= bigrange
? rn1(18, 8) : 1;
1974 if (Race_if(PM_IRAHA
)) digdepth
*= 2;
1975 tmp_at(DISP_BEAM
, cmap_to_glyph(S_digbeam
));
1976 while (--digdepth
>= 0) {
1977 if (!isok(zx
,zy
)) break;
1978 room
= &levl
[zx
][zy
];
1980 delay_output(); /* wait a little bit */
1982 /* WAC check for monster, boulder */
1983 if ((mtmp
= m_at(zx
, zy
)) != 0) {
1984 if (made_of_rock(mtmp
->data
)) {
1985 You("gouge a hole in %s!", mon_nam(mtmp
));
1987 if (mtmp
->mhp
< 1) mtmp
->mhp
= 1;
1989 } else pline("%s is unaffected!", Monnam(mtmp
));
1991 for(otmp
= level
.objects
[zx
][zy
]; otmp
; otmp
= next_obj
) {
1992 next_obj
= otmp
->nexthere
;
1993 /* vaporize boulders */
1994 if (otmp
->otyp
== BOULDER
) {
1996 /* A little Sokoban guilt... */
1997 if (In_sokoban(&u
.uz
) && !playercancheatinsoko()) {
1999 pline("You cheater!");
2000 if (evilfriday
) u
.ugangr
++;
2002 unblock_point(zx
, zy
);
2004 pline_The("boulder is vaporized!");
2009 if (closed_door(zx
, zy
) || room
->typ
== SDOOR
) {
2010 /* ALI - Artifact doors */
2011 if (artifact_door(zx
, zy
)) {
2013 pline_The("door glows then fades.");
2016 if (*in_rooms(zx
,zy
,SHOPBASE
)) {
2017 add_damage(zx
, zy
, 400L);
2020 if (room
->typ
== SDOOR
)
2022 else if (cansee(zx
, zy
))
2023 pline_The("door is razed!");
2024 watch_dig((struct monst
*)0, zx
, zy
, TRUE
);
2025 room
->doormask
= D_NODOOR
;
2026 unblock_point(zx
,zy
); /* vision */
2028 if (issoviet
&& maze_dig
) pline("Vy ne mozhete kopat'! Poskol'ku Sovetskiy Pyat' Lo nenavidit vashi kishki!");
2029 if (issoviet
&& maze_dig
) break;
2030 } else if (maze_dig
) {
2031 if (IS_WATERTUNNEL(room
->typ
)) {
2033 unblock_point(zx
,zy
); /* vision */
2034 digdepth
-= 2; /* fix stupidity --Amy */
2035 if (issoviet
) pline("Vy ne mozhete kopat'! Poskol'ku Sovetskiy Pyat' Lo nenavidit vashi kishki!");
2036 if (issoviet
) break;
2038 } if (IS_WALL(room
->typ
) && !(IS_FARMLAND(room
->typ
)) && !(IS_MOUNTAIN(room
->typ
)) && !(IS_GRAVEWALL(room
->typ
)) ) {
2039 if (!(room
->wall_info
& W_NONDIGGABLE
)) {
2040 if (*in_rooms(zx
,zy
,SHOPBASE
)) {
2041 add_damage(zx
, zy
, 200L);
2044 room
->typ
= /*ROOM*/CORR
;
2045 unblock_point(zx
,zy
); /* vision */
2046 if (!(levl
[zx
][zy
].wall_info
& W_HARDGROWTH
)) levl
[zx
][zy
].wall_info
|= W_EASYGROWTH
;
2047 digdepth
-= 2; /* fix stupidity --Amy */
2048 if (issoviet
) pline("Vy ne mozhete kopat'! Poskol'ku Sovetskiy Pyat' Lo nenavidit vashi kishki!");
2049 if (issoviet
) break;
2050 } else if (!Blind
) {
2051 pline_The("wall glows then fades.");
2054 } else if (IS_TREE(room
->typ
)) { /* check trees before stone */
2055 if (!(room
->wall_info
& W_NONDIGGABLE
)) {
2057 unblock_point(zx
,zy
); /* vision */
2058 if (!(levl
[zx
][zy
].wall_info
& W_HARDGROWTH
)) levl
[zx
][zy
].wall_info
|= W_EASYGROWTH
;
2059 digdepth
-= 2; /* fix stupidity --Amy */
2060 if (issoviet
) pline("Vy ne mozhete kopat'! Poskol'ku Sovetskiy Pyat' Lo nenavidit vashi kishki!");
2061 if (issoviet
) break;
2062 } else if (!Blind
) {
2063 pline_The("tree shudders but is unharmed.");
2066 } else if (room
->typ
== STONE
|| room
->typ
== SCORR
) {
2067 if (!(room
->wall_info
& W_NONDIGGABLE
)) {
2069 unblock_point(zx
,zy
); /* vision */
2070 if (!(levl
[zx
][zy
].wall_info
& W_HARDGROWTH
)) levl
[zx
][zy
].wall_info
|= W_EASYGROWTH
;
2071 digdepth
--; /* fix stupidity --Amy */
2072 /* In Soviet Russia, digging has to be done one block at a time. Faster digging methods are capitalistic
2073 * and evil, so they're not allowed. I wonder how long until they decide to make mazes undiggable... --Amy */
2074 if (issoviet
) pline("Vy ne mozhete kopat'! Poskol'ku Sovetskiy Pyat' Lo nenavidit vashi kishki!");
2075 if (issoviet
) break;
2076 } else if (!Blind
) {
2077 pline_The("rock glows then fades.");
2081 } else if (IS_ROCK(room
->typ
) || IS_WATERTUNNEL(room
->typ
)) {
2082 if (!may_dig(zx
,zy
)) break;
2083 if (IS_WALL(room
->typ
) || room
->typ
== SDOOR
) {
2084 if (*in_rooms(zx
,zy
,SHOPBASE
)) {
2085 add_damage(zx
, zy
, 200L);
2088 watch_dig((struct monst
*)0, zx
, zy
, TRUE
);
2089 if (level
.flags
.is_cavernous_lev
&& !in_town(zx
, zy
)) {
2091 } else if (IS_WATERTUNNEL(room
->typ
)) {
2093 } else if (IS_DIGGABLEWALL(room
->typ
)) {
2097 room
->doormask
= D_NODOOR
;
2100 } else if (IS_TREE(room
->typ
)) {
2103 } else if (IS_WATERTUNNEL(room
->typ
)) {
2106 } else { /* IS_ROCK but not IS_WALL or SDOOR */
2110 unblock_point(zx
,zy
); /* vision */
2111 if (!(levl
[zx
][zy
].wall_info
& W_HARDGROWTH
)) levl
[zx
][zy
].wall_info
|= W_EASYGROWTH
;
2116 tmp_at(DISP_END
,0); /* closing call */
2117 if (shopdoor
|| shopwall
)
2118 pay_for_damage(shopdoor
? "destroy" : "dig into", FALSE
);
2122 /* move objects from fobj/nexthere lists to buriedobjlist, keeping position */
2132 pline("bury_an_obj: %s", xname(otmp
));
2136 /* after unpunish(), or might get deallocated chain */
2137 otmp2
= otmp
->nexthere
;
2139 * obj_resists(,0,0) prevents Rider corpses from being buried.
2140 * It also prevents The Amulet and invocation tools from being
2141 * buried. Since they can't be confined to bags and statues,
2142 * it makes sense that they can't be buried either, even though
2143 * the real reason there (direct accessibility when carried) is
2144 * completely different.
2146 if (otmp
== uchain
|| obj_resists(otmp
, 0, 0))
2149 if (otmp
->otyp
== LEATHER_LEASH
&& otmp
->leashmon
!= 0)
2152 if (otmp
->otyp
== INKA_LEASH
&& otmp
->leashmon
!= 0)
2155 if (otmp
->otyp
== ADAMANT_LEASH
&& otmp
->leashmon
!= 0)
2158 if (otmp
== usaddle
)
2159 dismount_steed(DISMOUNT_GENERIC
);
2161 if (otmp
->lamplit
&& otmp
->otyp
!= POT_OIL
)
2162 end_burn(otmp
, TRUE
);
2164 obj_extract_self(otmp
);
2166 under_ice
= is_ice(otmp
->ox
, otmp
->oy
);
2167 if (otmp
->otyp
== ROCK
&& !under_ice
) {
2168 /* merges into burying material */
2169 obfree(otmp
, (struct obj
*)0);
2173 * Start a rot on organic material. Not corpses -- they
2174 * are already handled.
2176 if (otmp
->otyp
== CORPSE
) {
2177 ; /* should cancel timer if under_ice */
2178 } else if ((under_ice
? otmp
->oclass
== POTION_CLASS
: is_organic(otmp
))
2179 && !obj_resists(otmp
, 5, 95)) {
2180 (void) start_timer((under_ice
? 0L : 250L) + (long)rnd(250),
2181 TIMER_OBJECT
, ROT_ORGANIC
, (void *)otmp
);
2183 add_to_buried(otmp
);
2191 struct obj
*otmp
, *otmp2
;
2194 if(level
.objects
[x
][y
] != (struct obj
*)0)
2195 pline("bury_objs: at %d, %d", x
, y
);
2197 for (otmp
= level
.objects
[x
][y
]; otmp
; otmp
= otmp2
)
2198 otmp2
= bury_an_obj(otmp
);
2200 /* don't expect any engravings here, but just in case */
2205 /* move objects from buriedobjlist to fobj/nexthere lists */
2210 struct obj
*otmp
, *otmp2
;
2213 pline("unearth_objs: at %d, %d", x
, y
);
2215 for (otmp
= level
.buriedobjlist
; otmp
; otmp
= otmp2
) {
2217 if (otmp
->ox
== x
&& otmp
->oy
== y
) {
2218 obj_extract_self(otmp
);
2220 (void) stop_timer(ROT_ORGANIC
, (void *)otmp
);
2221 place_object(otmp
, x
, y
);
2230 * The organic material has rotted away while buried. As an expansion,
2231 * we could add add partial damage. A damage count is kept in the object
2232 * and every time we are called we increment the count and reschedule another
2233 * timeout. Eventually the object rots away.
2235 * This is used by buried objects other than corpses. When a container rots
2236 * away, any contents become newly buried objects.
2240 rot_organic(arg
, timeout
)
2242 long timeout
; /* unused */
2244 #if defined(MAC_MPW)
2245 # pragma unused ( timeout )
2247 struct obj
*obj
= (struct obj
*) arg
;
2249 /* nope, you do not get to retrieve the medical kit contents that way, you filthy exploit exploiter --Amy */
2250 if (obj
&& obj
->otyp
== MEDICAL_KIT
&& Has_contents(obj
)) {
2251 delete_contents(obj
);
2254 while (Has_contents(obj
)) {
2255 /* We don't need to place contained object on the floor
2256 first, but we do need to update its map coordinates. */
2257 obj
->cobj
->ox
= obj
->ox
, obj
->cobj
->oy
= obj
->oy
;
2258 /* Everything which can be held in a container can also be
2259 buried, so bury_an_obj's use of obj_extract_self insures
2260 that Has_contents(obj) will eventually become false. */
2261 (void)bury_an_obj(obj
->cobj
);
2263 obj_extract_self(obj
);
2264 obfree(obj
, (struct obj
*) 0);
2268 * Called when a corpse has rotted completely away.
2271 rot_corpse(arg
, timeout
)
2273 long timeout
; /* unused */
2276 struct obj
*obj
= (struct obj
*) arg
;
2277 boolean on_floor
= obj
->where
== OBJ_FLOOR
,
2278 in_minvent
= obj
->where
== OBJ_MINVENT
,
2279 in_invent
= obj
->where
== OBJ_INVENT
;
2284 } else if (in_minvent
) {
2285 /* WAC unwield if wielded */
2286 if (MON_WEP(obj
->ocarry
) && MON_WEP(obj
->ocarry
) == obj
) {
2287 obj
->owornmask
&= ~W_WEP
;
2288 MON_NOWEP(obj
->ocarry
);
2290 } else if (in_invent
) {
2291 if (flags
.verbose
) {
2292 char *cname
= corpse_xname(obj
, FALSE
);
2293 Your("%s%s %s away%c",
2294 obj
== uwep
? "wielded " : nul
, cname
,
2295 otense(obj
, "rot"), obj
== uwep
? '!' : '.');
2298 uwepgone(); /* now bare handed */
2300 } else if (obj
== uswapwep
) {
2303 } else if (obj
== uquiver
) {
2306 } else if (obj
== uswapwep
) {
2309 } else if (obj
== uquiver
) {
2313 } else if (obj
->where
== OBJ_MINVENT
&& obj
->owornmask
) {
2314 if (obj
== MON_WEP(obj
->ocarry
)) {
2315 setmnotwielded(obj
->ocarry
,obj
);
2316 MON_NOWEP(obj
->ocarry
);
2319 rot_organic(arg
, timeout
);
2320 if (on_floor
) newsym(x
, y
);
2321 else if (in_invent
) update_inventory();
2330 pline("bury_monst: %s", mon_nam(mtmp
));
2332 if(canseemon(mtmp
)) {
2333 if(is_flyer(mtmp
->data
) || mtmp
->egotype_flying
|| is_floater(mtmp
->data
)) {
2334 pline_The("%s opens up, but %s is not swallowed!",
2335 surface(mtmp
->mx
, mtmp
->my
), mon_nam(mtmp
));
2338 pline_The("%s opens up and swallows %s!",
2339 surface(mtmp
->mx
, mtmp
->my
), mon_nam(mtmp
));
2342 mtmp
->mburied
= TRUE
;
2343 wakeup(mtmp
); /* at least give it a chance :-) */
2344 newsym(mtmp
->mx
, mtmp
->my
);
2353 /* KMH, balance patch -- new intrinsic */
2354 if (!Levitation
&& !Flying
) {
2356 You_feel("a sensation like falling into a trap!");
2358 pline_The("%s opens beneath you and you fall in!",
2359 surface(u
.ux
, u
.uy
));
2362 if(!Strangled
&& !Breathless
) Strangled
= 11;
2371 pline("unearth_you");
2375 if(!uamul
|| uamul
->otyp
!= AMULET_OF_STRANGULATION
)
2384 pline("escape_tomb");
2386 if ((Teleportation
|| can_teleport(youmonst
.data
)) &&
2387 (Teleport_control
|| rn2(3) < Luck
+2)) {
2388 You("attempt a teleport spell.");
2389 (void) dotele_post(FALSE
); /* calls unearth_you() */
2390 } else if(u
.uburied
) { /* still buried after 'port attempt */
2393 if(amorphous(youmonst
.data
) || Passes_walls
||
2394 noncorporeal(youmonst
.data
) || unsolid(youmonst
.data
) || (uarmf
&& uarmf
->oartifact
== ART_STONEWALL_CHECKERBOARD_DIS
) || (Race_if(PM_SCURRIER
) && !Upolyd
) ||
2395 (tunnels(youmonst
.data
) && !needspick(youmonst
.data
))) {
2397 You("%s up through the %s.",
2398 (tunnels(youmonst
.data
) && !needspick(youmonst
.data
)) ?
2399 "try to tunnel" : (uarmf
&& uarmf
->oartifact
== ART_STONEWALL_CHECKERBOARD_DIS
) ? "try to tunnel" : (Race_if(PM_SCURRIER
) && !Upolyd
) ? "try to tunnel" : (amorphous(youmonst
.data
)) ?
2400 "ooze" : "phase", surface(u
.ux
, u
.uy
));
2402 if(tunnels(youmonst
.data
) && !needspick(youmonst
.data
))
2403 good
= dighole(TRUE
);
2404 else if (Race_if(PM_SCURRIER
) && !Upolyd
)
2405 good
= dighole(TRUE
);
2406 else if (uarmf
&& uarmf
->oartifact
== ART_STONEWALL_CHECKERBOARD_DIS
)
2407 good
= dighole(TRUE
);
2409 if(good
) unearth_you();
2422 if(cansee(otmp
->ox
, otmp
->oy
))
2423 pline_The("objects on the %s tumble into a hole!",
2424 surface(otmp
->ox
, otmp
->oy
));
2426 bury_objs(otmp
->ox
, otmp
->oy
);
2432 wiz_debug_cmd() /* in this case, bury everything at your loc and around */
2436 for (x
= u
.ux
- 1; x
<= u
.ux
+ 1; x
++)
2437 for (y
= u
.uy
- 1; y
<= u
.uy
+ 1; y
++)
2438 if (isok(x
,y
)) bury_objs(x
,y
);