Blindfold removal fix
[slashemextended.git] / src / hack.c
blobeb078d73a9fe781e247160bfc3a4421c1d9b1e8d
1 /* SCCS Id: @(#)hack.c 3.4 2003/04/30 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
6 #include "qtext.h"
8 STATIC_DCL int moverock(void);
9 STATIC_DCL int still_chewing(XCHAR_P,XCHAR_P);
10 STATIC_DCL void dosinkfall(void);
11 STATIC_DCL boolean findtravelpath(BOOLEAN_P);
12 STATIC_DCL boolean monstinroom(struct permonst *,int);
13 STATIC_DCL boolean anymonstinroom(int);
15 STATIC_DCL void move_update(BOOLEAN_P);
16 STATIC_PTR void set_litX(int,int,void *);
18 static boolean door_opened; /* set to true if door was opened during test_move */
21 #define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE)
23 #ifdef OVL2
25 #ifdef DUNGEON_GROWTH
26 void
27 rndmappos(x,y) /* guaranteed to return a valid coord */
28 xchar *x;
29 xchar *y;
31 if (*x >= COLNO) *x = COLNO;
32 else if (*x == -1) *x = rn2(COLNO-1)+1;
33 else if (*x < 1) *x = 1;
35 if (*y >= ROWNO) *y = ROWNO;
36 else if (*y == -1) *y = rn2(ROWNO);
37 else if (*y < 0) *y = 0;
40 #define HERB_GROWTH_LIMIT 3 /* to limit excessive farming */
42 static const struct herb_info {
43 int herb;
44 boolean in_water;
45 } herb_info[] = {
46 { SPRIG_OF_WOLFSBANE, FALSE },
47 { CLOVE_OF_GARLIC, FALSE },
48 { CARROT, FALSE },
49 { KELP_FROND, TRUE }
52 long
53 count_herbs_at(x,y, watery)
54 xchar x,y;
55 boolean watery;
57 register int dd;
58 register long count = 0;
60 if (isok(x,y)) {
61 for (dd = 0; dd < SIZE(herb_info); dd++) {
62 if (watery == herb_info[dd].in_water) {
63 register struct obj *otmp = sobj_at(herb_info[dd].herb, x,y);
64 if (otmp)
65 count += otmp->quan;
69 return count;
72 /* returns TRUE if a herb can grow at (x,y) */
73 boolean
74 herb_can_grow_at(x,y, watery)
75 xchar x,y;
76 boolean watery;
78 register struct rm *lev = &levl[x][y];
79 if (inside_shop(x,y)) return FALSE;
80 if (watery)
81 return (IS_POOL(lev->typ) &&
82 ((count_herbs_at(x,y, watery)) < HERB_GROWTH_LIMIT));
83 return (lev->lit && (lev->typ == ROOM || lev->typ == CORR ||
84 (IS_DOOR(lev->typ) &&
85 ((lev->doormask == D_NODOOR) ||
86 (lev->doormask == D_ISOPEN) ||
87 (lev->doormask == D_BROKEN)))) &&
88 (count_herbs_at(x,y, watery) < HERB_GROWTH_LIMIT));
91 /* grow herbs in water. return true if did something. */
92 boolean
93 grow_water_herbs(herb, x,y)
94 int herb;
95 xchar x,y;
97 struct obj *otmp;
99 rndmappos(&x, &y);
100 otmp = sobj_at(herb, x, y);
101 if (otmp && herb_can_grow_at(x,y, TRUE)) {
102 otmp->quan++;
103 otmp->owt = weight(otmp);
104 return TRUE;
105 /* There's no need to start growing these on the neighboring
106 * mapgrids, as they move around (see water_current())
109 return FALSE;
112 /* grow herb on ground at (x,y), or maybe spread out.
113 return true if did something. */
114 boolean
115 grow_herbs(herb, x,y, showmsg, update)
116 int herb;
117 xchar x,y;
118 boolean showmsg, update;
120 struct obj *otmp;
121 struct rm *lev;
123 rndmappos(&x, &y);
124 lev = &levl[x][y];
125 otmp = sobj_at(herb, x, y);
126 if (otmp && herb_can_grow_at(x,y, FALSE)) {
127 if (otmp->quan <= rn2(HERB_GROWTH_LIMIT)) {
128 otmp->quan++;
129 otmp->owt = weight(otmp);
130 return TRUE;
131 } else {
132 int dd, dofs = rn2(8);
133 /* check surroundings, maybe grow there? */
134 for (dd = 0; dd < 8; dd++) {
135 coord pos;
137 dtoxy(&pos, (dd+dofs) % 8);
138 pos.x += x;
139 pos.y += y;
140 if (isok(pos.x,pos.y) && herb_can_grow_at(pos.x,pos.y, FALSE)) {
141 lev = &levl[pos.x][pos.y];
142 otmp = sobj_at(herb, pos.x, pos.y);
143 if (otmp) {
144 if (otmp->quan <= rn2(HERB_GROWTH_LIMIT)) {
145 otmp->quan++;
146 otmp->owt = weight(otmp);
147 return TRUE;
149 } else {
150 otmp = mksobj(herb, TRUE, FALSE, FALSE);
151 if (otmp) {
152 otmp->quan = 1;
153 otmp->owt = weight(otmp);
154 place_object(otmp, pos.x, pos.y);
155 if (update) newsym(pos.x,pos.y);
156 if (cansee(pos.x,pos.y)) {
157 if (showmsg && flags.verbose) {
158 const char *what;
159 if (herb == CLOVE_OF_GARLIC)
160 what = "some garlic";
161 else
162 what = an(xname(otmp));
163 Norep("Suddenly you notice %s growing on the %s.",
164 what, surface(pos.x,pos.y));
168 return TRUE;
174 return FALSE;
177 /* moves topmost object in water at (x,y) to dir.
178 return true if did something. */
179 boolean
180 water_current(x,y,dir,waterforce, showmsg, update)
181 xchar x,y;
182 int dir;
183 unsigned waterforce; /* strength of the water current */
184 boolean showmsg, update;
186 struct obj *otmp;
187 coord pos;
189 rndmappos(&x,&y);
190 dtoxy(&pos, dir);
191 pos.x += x;
192 pos.y += y;
193 if (isok(pos.x,pos.y) && IS_POOL(levl[x][y].typ) &&
194 IS_POOL(levl[pos.x][pos.y].typ)) {
195 otmp = level.objects[x][y];
196 if (otmp && otmp->where == OBJ_FLOOR) {
197 if (otmp->quan > 1)
198 otmp = splitobj(otmp, otmp->quan - 1);
199 if (otmp->owt <= waterforce) {
200 if (showmsg && Underwater &&
201 (cansee(pos.x,pos.y) || cansee(x,y))) {
202 Norep("%s floats%s in%s the murky water.",
203 An(xname(otmp)),
204 (cansee(x,y) && cansee(pos.x,pos.y)) ? "" :
205 (cansee(x,y) ? " away from you" : " towards you"),
206 flags.verbose ? " the currents of" : "");
208 obj_extract_self(otmp);
209 place_object(otmp, pos.x,pos.y);
210 stackobj(otmp);
211 if (update) {
212 newsym(x,y);
213 newsym(pos.x,pos.y);
215 return TRUE;
216 } else /* the object didn't move, put it back */
217 stackobj(otmp);
220 return FALSE;
223 /* a tree at (x,y) spontaneously drops a ripe fruit */
224 boolean
225 drop_ripe_treefruit(x,y,showmsg, update)
226 xchar x,y;
227 boolean showmsg, update;
229 register struct rm *lev;
231 rndmappos(&x,&y);
232 lev = &levl[x][y];
233 if (IS_TREE(lev->typ) && !(lev->looted & TREE_LOOTED) && may_dig(x,y)) {
234 coord pos;
235 int dir, dofs = rn2(8);
237 /* Amy edit: this shouldn't be a 100% chance, after all kicking isn't either */
238 if (rn2(3)) {
239 levl[x][y].looted |= TREE_LOOTED;
240 return FALSE;
243 for (dir = 0; dir < 8; dir++) {
244 dtoxy(&pos, (dir + dofs) % 8);
245 pos.x += x;
246 pos.y += y;
247 if (!isok(pos.x, pos.y)) return FALSE;
248 lev = &levl[pos.x][pos.y];
249 if (SPACE_POS(lev->typ) || IS_POOL(lev->typ)) {
250 struct obj *otmp;
251 otmp = rnd_treefruit_at(pos.x,pos.y);
252 if (otmp) {
253 otmp->quan = 1;
254 otmp->owt = weight(otmp);
255 obj_extract_self(otmp);
256 if (showmsg) {
257 if ((cansee(pos.x,pos.y) || cansee(x,y))) {
258 Norep("%s falls from %s%s.",
259 cansee(pos.x,pos.y) ? An(xname(otmp)) : Something,
260 cansee(x,y) ? "the tree" : "somewhere",
261 (cansee(x,y) && IS_POOL(lev->typ)) ?
262 " into the water" : "");
263 } else if (distu(pos.x,pos.y) < 9 &&
264 otmp->otyp != EUCALYPTUS_LEAF) {
265 /* a leaf is too light to cause any sound */
266 You_hear("a %s!",
267 (IS_POOL(lev->typ) || IS_FOUNTAIN(lev->typ)) ?
268 "plop" : "splut"); /* rainforesty sounds */
271 place_object(otmp, pos.x,pos.y);
272 stackobj(otmp);
273 if (rn2(6)) levl[x][y].looted |= TREE_LOOTED;
274 if (update) newsym(pos.x,pos.y);
275 return TRUE;
280 return FALSE;
283 /* Tree at (x,y) seeds. returns TRUE if a new tree was created.
284 * Creates a kind of forest, with (hopefully) most places available.
286 boolean
287 seed_tree(x,y)
288 xchar x,y;
290 coord pos, pos2;
291 struct rm *lev;
293 rndmappos(&x,&y);
294 if (IS_TREE(levl[x][y].typ) && may_dig(x,y)) {
295 int dir = rn2(8);
296 dtoxy(&pos, dir);
297 pos.x += x;
298 pos.y += y;
299 if (!rn2(3)) {
300 dtoxy(&pos2, (dir+rn2(2)) % 8);
301 pos.x += pos2.x;
302 pos.y += pos2.y;
304 if (!isok(pos.x,pos.y)) return FALSE;
305 lev = &levl[pos.x][pos.y];
306 if (lev->lit && !cansee(pos.x,pos.y) && !inside_shop(pos.x,pos.y) &&
307 (lev->typ == ROOM || lev->typ == CORR) &&
308 !(u.ux == pos.x && u.uy == pos.y) && !m_at(pos.x,pos.y) &&
309 !t_at(pos.x,pos.y) && !OBJ_AT(pos.x,pos.y)) {
310 int nogrow = 0;
311 int dx,dy;
312 for (dx = pos.x-1; dx <= pos.x+1; dx++) {
313 for (dy = pos.y-1; dy <= pos.y+1; dy++) {
314 if (!isok(dx,dy) ||
315 (isok(dx,dy) && !SPACE_POS(levl[dx][dy].typ)))
316 nogrow++;
319 if (nogrow < 3) {
320 lev->typ = TREE;
321 lev->looted &= ~TREE_LOOTED;
322 block_point(pos.x,pos.y);
323 return TRUE;
327 return FALSE;
330 void
331 dgn_growths(showmsg, update, treesnstuff)
332 boolean showmsg; /* show messages */
333 boolean update; /* do newsym() */
334 boolean treesnstuff;
336 int herbnum = rn2(SIZE(herb_info));
337 int randomx, randomy;
338 int i, j, count, randchance=0;
339 boolean secretcorr = TRUE;
340 /*register struct monst *mtmp;*/
342 /* note by Amy: disabled herb growth and water currents. GDB says that the dreaded savegame error is happening
343 * in this function, and since Paliculo had the savegame error happen in SLASH'EM 0.08, chances are it's something
344 * that was introduced pre-SLEX. That said, the newsym() function was erroring too, and since the dgn_growths
345 * function is being called during saving for every single level that exists, I wouldn't be at all surprised if
346 * that's somehow related. At the very least I'm taking out the minliquid() call below, and that means we don't need
347 * the mtmp anymore either. If it's still somehow crashing then we'll need to look into the GDB output which will
348 * hopefully tell us where exactly in newsym() it's choking...
349 * another note: on levels that the character isn't currently on, only regrow walls, don't drop fruit */
351 /* update: *sigh* apparently the newsym() is really the culprit and I could just have used the update variable! */
353 if (!rn2(100)) (void) seed_tree(-1,-1);
354 /*if (herb_info[herbnum].in_water)
355 (void) grow_water_herbs(herb_info[herbnum].herb, -1,-1);
356 else
357 (void) grow_herbs(herb_info[herbnum].herb, -1,-1, showmsg, update);*/
359 if (treesnstuff && !rn2(isfriday ? 100 : 30)) (void) drop_ripe_treefruit(-1,-1, showmsg, update);
361 /*(void) water_current(-1,-1, rn2(8), Is_waterlevel(&u.uz) ? 200 : 25, showmsg, update);*/
363 trap_of_walls:
365 /* evil patch idea by Amy: occasionally, corridors and room squares will "grow" back into solid rock or walls.
366 * Depending on the # of surrounding squares that are blocked, give a higher or lower chance to place a new wall.
367 * If 6 out of 8 surrounding squares are blocked it most probably means that it's a corridor, which would
368 * completely block progress if it were made into a wall, and since players don't always have a pick-axe, let that
369 * only happen rarely. On the other hand, if all 8 surrounding squares are blocked, there probably isn't much
370 * harm done in closing it.
371 * Why am I such a filthy bitch who even thinks up such bullshit?
372 * Relax! There's a simple reason - after a while, umber hulks and similar monsters might dig out entire levels,
373 * and in vanilla there's absolutely no way to restore them to their previous condition. Not so here,
374 * where the dungeon will gradually "repair" itself, so to speak. Scrolls of lockout can further that repair.*/
375 if (!rn2(iswarper ? 5 : 10) ) {
376 randomx = rn1(COLNO-3,2);
377 randomy = rn2(ROWNO);
379 if ((!rn2(3) || (!In_sokoban(&u.uz)) ) && isok(randomx, randomy) && ((levl[randomx][randomy].wall_info & W_NONDIGGABLE) == 0) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR || (levl[randomx][randomy].typ == DOOR && levl[randomx][randomy].doormask == D_NODOOR) ) ) {
380 count = 0;
381 for (i= -1; i<=1; i++) for(j= -1; j<=1; j++) {
382 if (!i && !j) continue;
383 if (!isok(randomx+i, randomy+j) || IS_WATERTUNNEL(levl[randomx+i][randomy+j].typ) || IS_STWALL(levl[randomx+i][randomy+j].typ) )
384 count++;
386 switch (count) {
388 case 8:
389 randchance = (levl[randomx][randomy].wall_info & W_EASYGROWTH) ? 1 : 10;
390 break;
391 case 7:
392 randchance = (levl[randomx][randomy].wall_info & W_EASYGROWTH) ? 1 : 20;
393 break;
394 case 6:
395 randchance = (levl[randomx][randomy].wall_info & W_EASYGROWTH) ? 10 : 10000;
396 break;
397 case 5:
398 randchance = (levl[randomx][randomy].wall_info & W_EASYGROWTH) ? 5 : 2000;
399 break;
400 case 4:
401 randchance = (levl[randomx][randomy].wall_info & W_EASYGROWTH) ? 2 : 500;
402 break;
403 case 3:
404 randchance = (levl[randomx][randomy].wall_info & W_EASYGROWTH) ? 2 : 100;
405 break;
406 case 2:
407 randchance = (levl[randomx][randomy].wall_info & W_EASYGROWTH) ? 1 : 30;
408 break;
409 case 1:
410 randchance = (levl[randomx][randomy].wall_info & W_EASYGROWTH) ? 1 : 20;
411 break;
412 case 0:
413 default: /* e.g. if it's 9 */
414 randchance = (levl[randomx][randomy].wall_info & W_EASYGROWTH) ? 1 : 10;
415 break;
418 /*pline("coord %d,%d, count %d, chance %d",randomx, randomy, count, randchance);*/
420 /* In Soviet Russia, digging out an entire level should be permanent, like Moscow's Scorched Earth strategy
421 * in World War II. You should have no way of restoring any area to its previous condition, no matter what.
422 * And of course there are no pick-axes either, or any other methods of removing newly created walls. --Amy */
424 if (issoviet) randchance *= 100;
426 if (!rn2(randchance) && (!In_sokoban(&u.uz) || !sobj_at(BOULDER, randomx, randomy) ) ) {
428 if (rn2(3)) {
429 /* Sigh again. I had already given up (see below), and now of course this line was also causing
430 * the savegame error again. One day I will fucking eradicate newsym() entirely. BULLSHIT! */
432 doorlockX(randomx, randomy, update); /* let's hope this "update" will FINALLY fix things ARGH */
433 if (!(levl[randomx][randomy].wall_info & W_EASYGROWTH)) levl[randomx][randomy].wall_info |= W_HARDGROWTH;
435 else if ((levl[randomx][randomy].wall_info & W_NONDIGGABLE) == 0) {
436 if (levl[randomx][randomy].typ != DOOR) {
437 if (secretcorr && !rn2(10)) levl[randomx][randomy].typ = SCORR;
438 else levl[randomx][randomy].typ = ROCKWALL;
440 else {
441 if (secretcorr && !rn2(10)) levl[randomx][randomy].typ = SDOOR;
442 else levl[randomx][randomy].typ = CROSSWALL;
444 if (!(levl[randomx][randomy].wall_info & W_EASYGROWTH)) levl[randomx][randomy].wall_info |= W_HARDGROWTH;
445 blockorunblock_point(randomx,randomy);
446 del_engr_at(randomx, randomy);
448 /*if ((mtmp = m_at(randomx, randomy)) != 0) {
449 (void) minliquid(mtmp);
450 } else {*/
451 if (update) newsym(randomx,randomy);
452 /* this line, without the update variable check, is probably the monument of stupidity that caused savegame errors */
453 /*}*/
462 /* yet another update by Amy: I give up. No fucking idea why the line below is causing the savegame error,
463 * but it is. Apparently, calling this function during saving fucks up the "uwep" or "uswapwep" structures,
464 * even though the safety checks should make sure that it works right. Oh well, have to make the function get called
465 * only during regular play then, even though that is really stupid. */
467 if (update) {
469 if ((u.uprops[WALL_TRAP_EFFECT].extrinsic || WallTrapping || have_wallstone() || (uarmh && uarmh->oartifact == ART_JABONE_S_COLOR_CHANGE) || (uarmg && uarmg->oartifact == ART_STOUT_IMMURRING) || (uarmc && uarmc->oartifact == ART_MOST_CHARISMATIC_PRESIDENT) || (uimplant && uimplant->oartifact == ART_THEY_RE_REALLY_AFTER_ME) || autismweaponcheck(ART_CUDGEL_OF_CUTHBERT) || autismweaponcheck(ART_ONE_THROUGH_FOUR_SCEPTER) ) && rn2(WallRegrowXtra ? 500 : 100)) {
470 secretcorr = FALSE;
471 goto trap_of_walls;
478 /* catch up with growths when returning to a previously visited level */
479 void
480 catchup_dgn_growths(mvs)
481 int mvs;
483 if (mvs < 0) mvs = 0;
484 else if (mvs > LARGEST_INT) mvs = LARGEST_INT;
485 while (mvs-- > 0)
486 dgn_growths(FALSE, FALSE, FALSE);
488 #endif /* DUNGEON_GROWTH */
490 boolean
491 revive_nasty(x, y, msg)
492 int x,y;
493 const char *msg;
495 register struct obj *otmp, *otmp2;
496 struct monst *mtmp;
497 coord cc;
498 boolean revived = FALSE;
500 for(otmp = level.objects[x][y]; otmp; otmp = otmp2) {
501 otmp2 = otmp->nexthere;
502 if (otmp->otyp == CORPSE &&
503 (is_rider(&mons[otmp->corpsenm]) || is_deadlysin(&mons[otmp->corpsenm]) ||
504 otmp->corpsenm == PM_WIZARD_OF_YENDOR)) {
505 /* move any living monster already at that location */
506 if((mtmp = m_at(x,y)) && enexto(&cc, x, y, mtmp->data))
507 rloc_to(mtmp, cc.x, cc.y);
508 if(msg) Norep("%s", msg);
509 revived = revive_corpse(otmp, FALSE);
513 /* this location might not be safe, if not, move revived monster */
514 if (revived) {
515 mtmp = m_at(x,y);
516 if (mtmp && !goodpos(x, y, mtmp, 0) &&
517 enexto(&cc, x, y, mtmp->data)) {
518 rloc_to(mtmp, cc.x, cc.y);
520 /* else impossible? */
523 return (revived);
526 STATIC_OVL int
527 moverock()
529 register xchar rx, ry, sx, sy;
530 register struct obj *otmp;
531 register struct trap *ttmp;
532 register struct monst *mtmp;
534 sx = u.ux + u.dx, sy = u.uy + u.dy; /* boulder starting position */
535 while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) {
536 /* make sure that this boulder is visible as the top object */
537 if (otmp != level.objects[sx][sy]) movobj(otmp, sx, sy);
539 rx = u.ux + 2 * u.dx; /* boulder destination position */
540 ry = u.uy + 2 * u.dy;
541 nomul(0, 0, FALSE);
542 /* if you combine levitator and sokosolver the game shouldn't be unwinnable --Amy */
543 if ((Levitation || Is_airlevel(&u.uz)) && !Race_if(PM_LEVITATOR) ) {
544 if (Blind) feel_location(sx,sy);
545 You("don't have enough leverage to push %s.", the(xname(otmp)));
546 /* Give them a chance to climb over it? */
547 return -1;
549 if (verysmall(youmonst.data) && !Race_if(PM_TRANSFORMER) && !u.usteed ) {
550 if (Blind) feel_location(sx,sy);
551 pline("You're too small to push that %s.", xname(otmp));
552 goto cannot_push;
554 if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
555 levl[rx][ry].typ != IRONBARS &&
556 (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) || (
557 #ifdef REINCARNATION
558 !Is_rogue_level(&u.uz) &&
559 #endif
560 (levl[rx][ry].doormask & ~D_BROKEN) == D_NODOOR)) &&
561 !sobj_at(BOULDER, rx, ry)) {
562 ttmp = t_at(rx, ry);
563 mtmp = m_at(rx, ry);
565 /* KMH -- Sokoban doesn't let you push boulders diagonally */
566 if (In_sokoban(&u.uz) && u.dx && u.dy) {
567 if (Blind) feel_location(sx,sy);
568 pline("%s won't roll diagonally on this %s.",
569 The(xname(otmp)), surface(sx, sy));
570 goto cannot_push;
573 if (revive_nasty(rx, ry, "You sense movement on the other side.")) {
574 pline("The boulder vanishes!");
575 delobj(otmp); /* prevent easy Death farming --Amy */
576 return (-1);
579 if (mtmp && !noncorporeal(mtmp->data) &&
580 (!mtmp->mtrapped ||
581 !(ttmp && ((ttmp->ttyp == PIT) || (ttmp->ttyp == SHIT_PIT) || (ttmp->ttyp == MANA_PIT)
582 || (ttmp->ttyp == ANOXIC_PIT) || (ttmp->ttyp == HYPOXIC_PIT) || (ttmp->ttyp == ACID_PIT) || (ttmp->ttyp == SPIKED_PIT) || (ttmp->ttyp == GIANT_CHASM))))) {
584 if (Blind) feel_location(sx,sy);
585 if (canspotmon(mtmp)) {
586 boolean by_name = (mtmp->data->geno & G_UNIQ ||
587 mtmp->isshk || mtmp->mnamelth);
588 if (by_name && !Hallucination)
589 pline("%s is on the other side.", Monnam(mtmp));
590 else
591 pline("There's %s on the other side.", a_monnam(mtmp));
592 } else {
593 You_hear("a monster behind %s.", the(xname(otmp)));
594 if (!(mtmp->data->msound == MS_DEEPSTATE) && !(mtmp->egotype_deepstatemember)) map_invisible(rx, ry);
596 if (flags.verbose)
597 pline("Perhaps that's why %s cannot move it.", u.usteed ? y_monnam(u.usteed) : "you");
598 goto cannot_push;
601 if (ttmp)
602 switch(ttmp->ttyp) {
603 case LANDMINE:
604 if (rn2(10)) {
605 obj_extract_self(otmp);
606 place_object(otmp, rx, ry);
607 unblock_point(sx, sy);
608 newsym(sx, sy);
609 pline("KAABLAMM!!! %s %s land mine.",
610 Tobjnam(otmp, "trigger"),
611 ttmp->madeby_u ? "your" : "a");
612 blow_up_landmine(ttmp);
613 /* if the boulder remains, it should fill the pit */
614 fill_pit(u.ux, u.uy);
615 if (cansee(rx,ry)) newsym(rx,ry);
616 continue;
618 break;
619 case SPIKED_PIT:
620 case SHIT_PIT:
621 case MANA_PIT:
622 case ANOXIC_PIT:
623 case HYPOXIC_PIT:
624 case ACID_PIT:
625 case PIT:
626 case GIANT_CHASM:
627 obj_extract_self(otmp);
628 /* vision kludge to get messages right;
629 the pit will temporarily be seen even
630 if this is one among multiple boulders */
631 if (!Blind) viz_array[ry][rx] |= IN_SIGHT;
632 if (!flooreffects(otmp, rx, ry, "fall")) {
633 place_object(otmp, rx, ry);
635 if (mtmp && !Blind) newsym(rx, ry);
636 continue;
637 case HOLE:
638 case TRAPDOOR:
639 case SHAFT_TRAP:
640 case CURRENT_SHAFT:
641 if (Blind)
642 pline("Kerplunk! You no longer feel %s.",
643 the(xname(otmp)));
644 else
645 pline("%s%s and %s a %s in the %s!",
646 Tobjnam(otmp,
647 (ttmp->ttyp == TRAPDOOR) ? "trigger" : "fall"),
648 (ttmp->ttyp == TRAPDOOR) ? nul : " into",
649 otense(otmp, "plug"),
650 (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",
651 surface(rx, ry));
652 if (PlayerHearsSoundEffects) pline(issoviet ? "Takim obrazom, vy deystvitel'no dumayete, chto vy dostatochno umny, chtoby reshit' golovolomku bloka. Ya ser'yezno somnevayus' v etom." : "Tchueb!");
653 deltrap(ttmp);
654 delobj(otmp);
655 bury_objs(rx, ry);
656 if (cansee(rx,ry)) newsym(rx,ry);
657 continue;
658 case LEVEL_TELEP:
659 case LEVEL_BEAMER:
660 case TELEP_TRAP:
661 case BEAMER_TRAP:
662 if (u.usteed)
663 pline("%s pushes %s and suddenly it disappears!",
664 upstart(y_monnam(u.usteed)), the(xname(otmp)));
665 else
666 You("push %s and suddenly it disappears!",
667 the(xname(otmp)));
668 if (ttmp->ttyp == TELEP_TRAP)
669 rloco(otmp);
670 else if (ttmp->ttyp == BEAMER_TRAP)
671 rloco(otmp);
672 else {
673 int newlev = random_teleport_level();
674 d_level dest;
676 if (newlev == depth(&u.uz) || In_endgame(&u.uz))
677 continue;
678 obj_extract_self(otmp);
679 add_to_migration(otmp);
680 get_level(&dest, newlev);
681 otmp->ox = dest.dnum;
682 otmp->oy = dest.dlevel;
683 otmp->owornmask = (long)MIGR_RANDOM;
685 seetrap(ttmp);
686 continue;
688 if (closed_door(rx, ry))
689 goto nopushmsg;
690 if (boulder_hits_pool(otmp, rx, ry, TRUE))
691 continue;
693 * Re-link at top of fobj chain so that pile order is preserved
694 * when level is restored.
696 if (otmp != fobj) {
697 remove_object(otmp);
698 place_object(otmp, otmp->ox, otmp->oy);
702 #ifdef LINT /* static long lastmovetime; */
703 long lastmovetime;
704 lastmovetime = 0;
705 #else
706 /* note: reset to zero after save/restore cycle */
707 static NEARDATA long lastmovetime;
708 #endif
709 if (!u.usteed) {
710 if (moves > lastmovetime+2 || moves < lastmovetime)
711 pline("With %s effort you move %s.",
712 (throws_rocks(youmonst.data) || (uarmg && uarmg->oartifact == ART_MOUNTAIN_FISTS)) ? "little" : "great",
713 the(xname(otmp)));
714 if (!rn2(50) || (otmp->oartifact == ART_COOL_DUMBBELL) ) exercise(A_STR, TRUE);
715 } else
716 pline("%s moves %s.",
717 upstart(y_monnam(u.usteed)), the(xname(otmp)));
718 lastmovetime = moves;
720 if (otmp && otmp->oartifact == ART_ENTRAP_THE_UNWARY && !rn2(100)) {
721 if (t_at(u.ux, u.uy) == 0) (void) maketrap(u.ux, u.uy, rndtrap(), 0, FALSE);
724 if (otmp && otmp->oartifact == ART_SIGNAL_TONE) {
725 wake_nearby();
728 if (otmp && otmp->oartifact == ART_WENDYHOLE) {
729 pline("Wendy produces %s farting noises with her sexy butt.", !rn2(3) ? "loud" : !rn2(2) ? "disgusting" : "erogenous");
730 u.cnd_fartingcount++;
731 if (Role_if(PM_CLIMACTERIAL)) climtrainsqueaking(1);
732 if (Role_if(PM_BUTT_LOVER) && !rn2(20)) buttlovertrigger();
733 if (Role_if(PM_SOCIAL_JUSTICE_WARRIOR)) sjwtrigger();
734 if (!extralongsqueak()) badeffect();
738 /* Move the boulder *after* the message. */
739 if (memory_is_invisible(rx, ry))
740 unmap_object(rx, ry);
741 movobj(otmp, rx, ry); /* does newsym(rx,ry) */
742 if (Blind) {
743 feel_location(rx,ry);
744 feel_location(sx,sy);
745 } else {
746 newsym(sx,sy);
748 } else {
749 nopushmsg:
750 if (u.usteed)
751 pline("%s tries to move %s, but cannot.",
752 upstart(y_monnam(u.usteed)), the(xname(otmp)));
753 else
754 You("try to move %s, but in vain.", the(xname(otmp)));
755 if (Blind) feel_location(sx,sy);
756 cannot_push:
757 if (throws_rocks(youmonst.data) || (uarmg && uarmg->oartifact == ART_MOUNTAIN_FISTS) ) {
758 if (u.usteed && !(uwep && uwep->oartifact == ART_SORTIE_A_GAUCHE) && !(powerfulimplants() && uimplant && uimplant->oartifact == ART_READY_FOR_A_RIDE) && !FemtrapActiveKerstin && !(bmwride(ART_DEEPER_LAID_BMW)) && (PlayerCannotUseSkills || P_SKILL(P_RIDING) < P_BASIC) ) {
759 You("aren't skilled enough to %s %s from %s.",
760 (flags.pickup && !In_sokoban(&u.uz))
761 ? "pick up" : "push aside",
762 the(xname(otmp)), y_monnam(u.usteed));
763 } else
765 pline("However, you can easily %s.",
766 (flags.pickup && !In_sokoban(&u.uz))
767 ? "pick it up" : "push it aside");
768 if (yn("Do it?") != 'y')
769 return (-1);
771 if (In_sokoban(&u.uz) && !playercancheatinsoko()) {
772 change_luck(-1);
773 pline("You cheater!");
774 if (evilfriday) u.ugangr++;
776 /* Sokoban guilt */
777 break;
779 break;
782 if (!u.usteed && (((!invent || inv_weight() <= -1500) &&
783 (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][sy].typ)
784 && IS_ROCK(levl[sx][u.uy].typ))))
785 || verysmall(youmonst.data))) {
787 if (yn("However, you can squeeze yourself into a small opening. Do it?") != 'y')
788 return (-1);
789 else {
790 if (In_sokoban(&u.uz) && !playercancheatinsoko()) {
791 change_luck(-1);
792 pline("You cheater!");
793 if (evilfriday) u.ugangr++;
795 /* Sokoban guilt */
796 break;
799 } else
800 return (-1);
803 return (0);
807 * still_chewing()
809 * Chew on a wall, door, or boulder. Returns TRUE if still eating, FALSE
810 * when done.
812 STATIC_OVL int
813 still_chewing(x,y)
814 xchar x, y;
816 struct rm *lev = &levl[x][y];
817 struct obj *boulder = sobj_at(BOULDER,x,y);
818 const char *digtxt = (char *)0, *dmgtxt = (char *)0;
820 if (digging.down) /* not continuing previous dig (w/ pick-axe) */
821 (void) memset((void *)&digging, 0, sizeof digging);
823 if (!boulder && IS_ROCK(lev->typ) && !may_dig(x,y)) {
824 You("hurt your teeth on the %s.",
825 IS_TREE(lev->typ) ? "tree" : "hard stone");
826 nomul(0, 0, FALSE);
827 return 1;
828 } else if (digging.pos.x != x || digging.pos.y != y ||
829 !on_level(&digging.level, &u.uz)) {
830 digging.down = FALSE;
831 digging.chew = TRUE;
832 digging.warned = FALSE;
833 digging.pos.x = x;
834 digging.pos.y = y;
835 assign_level(&digging.level, &u.uz);
836 /* solid rock takes more work & time to dig through */
837 digging.effort =
838 (IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + increase_damage_bonus_value();
839 You("start chewing %s %s.",
840 (boulder || IS_TREE(lev->typ)) ? "on a" : "a hole in the",
841 boulder ? "boulder" :
842 IS_TREE(lev->typ) ? "tree" : IS_WATERTUNNEL(lev->typ) ? "rock above the water" : IS_ROCK(lev->typ) ? "rock" : "door");
843 watch_dig((struct monst *)0, x, y, FALSE);
844 return 1;
845 } else if ((digging.effort += (30 + increase_damage_bonus_value())) <= 100) {
846 if (flags.verbose)
847 You("%s chewing on the %s.",
848 digging.chew ? "continue" : "begin",
849 boulder ? "boulder" :
850 IS_TREE(lev->typ) ? "tree" :
851 IS_ROCK(lev->typ) ? "rock" : "door");
852 digging.chew = TRUE;
853 watch_dig((struct monst *)0, x, y, FALSE);
854 return 1;
857 /* Okay, you've chewed through something */
858 u.uconduct.food++;
859 if (FemtrapActiveNora) {
860 You("vomit.");
861 vomit();
862 morehungry(20);
864 u.uhunger += rnd(20);
866 if (boulder) {
867 delobj(boulder); /* boulder goes bye-bye */
868 You("eat the boulder."); /* yum */
871 * The location could still block because of
872 * 1. More than one boulder
873 * 2. Boulder stuck in a wall/stone/door.
875 * [perhaps use does_block() below (from vision.c)]
877 if (IS_ROCK(lev->typ) || closed_door(x,y) || sobj_at(BOULDER,x,y)) {
878 block_point(x,y); /* delobj will unblock the point */
879 /* reset dig state */
880 (void) memset((void *)&digging, 0, sizeof digging);
881 return 1;
884 } else if (IS_WATERTUNNEL(lev->typ)) {
885 digtxt = "chew away the rock above the water.";
886 lev->typ = MOAT;
887 } else if (IS_WALL(lev->typ)) {
888 if (*in_rooms(x, y, SHOPBASE)) {
889 add_damage(x, y, 10L * ACURRSTR);
890 dmgtxt = "damage";
892 digtxt = "chew a hole in the wall.";
893 if (level.flags.is_maze_lev) {
894 lev->typ = ROOM;
895 if (u.geolysis && !rn2(4)) {
896 lev->typ = !rn2(3) ? WATER : !rn2(2) ? ICE : CLOUD;
898 } else if (level.flags.is_cavernous_lev && !in_town(x, y)) {
899 lev->typ = CORR;
900 if (u.geolysis && !rn2(4)) {
901 lev->typ = !rn2(3) ? WATER : !rn2(2) ? ICE : CLOUD;
903 } else {
904 lev->typ = DOOR;
905 lev->doormask = D_NODOOR;
907 } else if (IS_TREE(lev->typ)) {
908 digtxt = "chew through the tree.";
909 lev->typ = ROOM;
910 } else if (lev->typ == SDOOR) {
911 if (lev->doormask & D_TRAPPED) {
912 lev->doormask = D_NODOOR;
913 b_trapped("secret door", 0);
914 } else {
915 digtxt = "chew through the secret door.";
916 lev->doormask = D_BROKEN;
918 lev->typ = DOOR;
920 } else if (IS_DOOR(lev->typ)) {
921 if (*in_rooms(x, y, SHOPBASE)) {
922 add_damage(x, y, 400L);
923 dmgtxt = "break";
925 if (lev->doormask & D_TRAPPED) {
926 lev->doormask = D_NODOOR;
927 b_trapped("door", 0);
928 } else {
929 digtxt = "chew through the door.";
930 lev->doormask = D_BROKEN;
933 } else { /* STONE or SCORR */
934 digtxt = "chew a passage through the rock.";
935 lev->typ = CORR;
936 if (u.geolysis && !rn2(4)) {
937 lev->typ = !rn2(3) ? WATER : !rn2(2) ? ICE : CLOUD;
941 unblock_point(x, y); /* vision */
942 if (!(levl[x][y].wall_info & W_HARDGROWTH)) levl[x][y].wall_info |= W_EASYGROWTH;
943 newsym(x, y);
944 if (digtxt) You("%s", digtxt); /* after newsym */
945 if (dmgtxt) pay_for_damage(dmgtxt, FALSE);
946 (void) memset((void *)&digging, 0, sizeof digging);
947 return 0;
950 #endif /* OVL2 */
951 #ifdef OVLB
953 void
954 movobj(obj, ox, oy)
955 register struct obj *obj;
956 register xchar ox, oy;
958 /* optimize by leaving on the fobj chain? */
959 remove_object(obj);
960 newsym(obj->ox, obj->oy);
961 place_object(obj, ox, oy);
962 newsym(ox, oy);
965 static NEARDATA const char fell_on_sink[] = "fell onto a sink";
967 STATIC_OVL void
968 dosinkfall()
970 register struct obj *obj;
972 if (is_floater(youmonst.data) || (HLevitation & FROMOUTSIDE)) {
973 You("wobble unsteadily for a moment.");
974 } else {
975 long save_ELev = ELevitation, save_HLev = HLevitation;
977 /* fake removal of levitation in advance so that final
978 disclosure will be right in case this turns out to
979 be fatal; fortunately the fact that rings and boots
980 are really still worn has no effect on bones data */
981 ELevitation = HLevitation = 0L;
982 You("crash to the floor!");
983 losehp(rn1(8, 25 - (int)ACURR(A_CON)),
984 fell_on_sink, NO_KILLER_PREFIX);
985 exercise(A_DEX, FALSE);
986 selftouch("Falling, you");
987 for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
988 if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) {
989 You("fell on %s.", doname(obj));
990 losehp(rnd(3), fell_on_sink, NO_KILLER_PREFIX);
991 exercise(A_CON, FALSE);
993 ELevitation = save_ELev;
994 HLevitation = save_HLev;
997 ELevitation &= ~W_ARTI;
998 HLevitation &= ~(I_SPECIAL|TIMEOUT);
999 HLevitation++;
1000 if(uleft && uleft->otyp == RIN_LEVITATION) {
1001 obj = uleft;
1002 Ring_off(obj);
1003 off_msg(obj);
1005 if(uright && uright->otyp == RIN_LEVITATION) {
1006 obj = uright;
1007 Ring_off(obj);
1008 off_msg(obj);
1010 if(uarmf && uarmf->otyp == LEVITATION_BOOTS) {
1011 obj = uarmf;
1012 (void)Boots_off();
1013 off_msg(obj);
1015 HLevitation--;
1018 boolean
1019 may_dig(x,y)
1020 register xchar x,y;
1021 /* intended to be called only on ROCKs */
1023 return (boolean)(!(IS_STWALL(levl[x][y].typ) && !(IS_DIGGABLEWALL(levl[x][y].typ)) &&
1024 (levl[x][y].wall_info & W_NONDIGGABLE)) && !(IS_FARMLAND(levl[x][y].typ)) && !(IS_GRAVEWALL(levl[x][y].typ)) && !(IS_MOUNTAIN(levl[x][y].typ)) );
1027 boolean
1028 may_passwall(x,y)
1029 register xchar x,y;
1031 return (boolean)(!(IS_STWALL(levl[x][y].typ) && !(IS_DIGGABLEWALL(levl[x][y].typ)) &&
1032 (levl[x][y].wall_info & W_NONPASSWALL)));
1035 #endif /* OVLB */
1036 #ifdef OVL1
1038 /* [ALI] Changed to take monst * as argument to support passwall property */
1039 boolean
1040 bad_rock(mon,x,y)
1041 struct monst *mon;
1042 register xchar x,y;
1044 struct permonst *mdat = mon->data;
1045 boolean passwall = mon == &youmonst ? Passes_walls : ( passes_walls(mdat) || (mon->egotype_wallwalk) );
1046 return((boolean) ((In_sokoban(&u.uz) && sobj_at(BOULDER,x,y)) ||
1047 (IS_ROCKWFL(levl[x][y].typ)
1048 && (!tunnels(mdat) || needspick(mdat) || !may_dig(x,y))
1049 && !(passwall && may_passwall(x,y)))));
1052 boolean
1053 invocation_pos(x, y)
1054 xchar x, y;
1056 return((boolean)(Invocation_lev(&u.uz) && x == inv_pos.x && y == inv_pos.y));
1059 #endif /* OVL1 */
1060 #ifdef OVL3
1061 /* For my clever ending messages... */
1062 int Instant_Death = 0;
1063 int Quick_Death = 0;
1064 int Nibble_Death = 0;
1065 int last_hit = 0;
1066 int second_last_hit = 0;
1067 int third_last_hit = 0;
1069 /* For those tough guys who get carried away... */
1070 int repeat_hit = 0;
1072 /* return TRUE if (dx,dy) is an OK place to move
1073 * mode is one of DO_MOVE, TEST_MOVE or TEST_TRAV
1075 boolean
1076 test_move(ux, uy, dx, dy, mode)
1077 int ux, uy, dx, dy;
1078 int mode;
1080 int x = ux+dx;
1081 int y = uy+dy;
1082 register struct rm *tmpr = &levl[x][y];
1083 register struct rm *ust;
1084 boolean opentry = 0;
1087 * Check for physical obstacles. First, the place we are going.
1089 if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS || (SpellColorPlatinum && (glyph_to_cmap(glyph_at(x,y)) == S_bars) ) || tmpr->typ == WOODENTABLE || tmpr->typ == WATERTUNNEL) {
1090 if (Blind && mode == DO_MOVE) feel_location(x,y);
1091 if (tmpr->typ == IRONBARS || (SpellColorPlatinum && (glyph_to_cmap(glyph_at(x,y)) == S_bars) ) ) {
1092 if (!(Passes_walls || passes_bars(youmonst.data) || (powerfulimplants() && uimplant && uimplant && uimplant->oartifact == ART_SIGNIFICANT_RNG_JITTER) )) {
1093 if (mode == DO_MOVE) {
1094 if (WallsAreHyperBlue) {
1095 You("crash into a set of iron bars! Ouch!");
1097 losehp(rnd(10), "walking into iron bars", KILLED_BY);
1098 if (!rn2(Role_if(PM_COURIER) ? 1000 : uarmh ? 50 : 10)) {
1099 if (rn2(50)) {
1100 adjattrib(rn2(2) ? A_INT : A_WIS, -rno(3), FALSE, TRUE);
1101 if (!rn2(50)) adjattrib(rn2(2) ? A_INT : A_WIS, -rno(2), FALSE, TRUE);
1102 } else {
1103 You_feel("dizzy!");
1104 forget(1 + rn2(5), FALSE);
1108 } else pline("There is a set of iron bars in the way!");
1110 return FALSE;
1112 else if (In_sokoban(&u.uz)) {
1113 if (mode == DO_MOVE)
1114 pline_The("Sokoban bars resist your ability.");
1115 return FALSE;
1117 } else if (Passes_walls && may_passwall(x,y)) {
1118 ; /* do nothing */
1119 } else if (Race_if(PM_HUMANOID_DRYAD) && tmpr->typ == TREE) {
1120 ; /* dryad can walk thru trees --Amy */
1121 } else if (uarmg && uarmg->oartifact == ART_GREEN_THUMB && tmpr->typ == TREE) {
1123 } else if (uarmf && uarmf->oartifact == ART_EVERYTHING_IS_GREEN && tmpr->typ == TREE) {
1124 ; /* special effect of that artifact --Amy */
1125 } else if (uarmf && uarmf->oartifact == ART_SAFARI_ROCKZ && tmpr->typ == TREE) {
1126 ; /* special effect of that artifact --Amy */
1127 } else if (uwep && uwep->oartifact == ART_GIFT_TO_NATURE && tmpr->typ == TREE) {
1128 ; /* special effect of that artifact --Amy */
1130 } else if (tmpr->typ == WOODENTABLE) {
1132 if ( (near_capacity() > UNENCUMBERED) && !Passes_walls) {
1133 if (mode != DO_MOVE) return FALSE;
1134 if (mode == DO_MOVE) {
1135 pline("Climbing the table does not work while you're burdened.");
1136 return FALSE;
1140 } else if (tmpr->typ == MOUNTAIN) {
1141 if (mode != DO_MOVE) return FALSE;
1142 if (mode == DO_MOVE && !(uwep && uwep->oartifact == ART_UNDERIRDIC_) && !(uwep && uwep->oartifact == ART_NOW_GO_AND_CLIMB) && !Passes_walls && !(powerfulimplants() && uimplant && uimplant && uimplant->oartifact == ART_SIGNIFICANT_RNG_JITTER)) {
1143 int climbingchance = 100;
1144 if (uamul && uamul->otyp == AMULET_OF_CLIMBING) climbingchance = ((levl[u.ux][u.uy].typ == MOUNTAIN) ? 3 : 10);
1145 if (ublindf && ublindf->otyp == CLIMBING_SET) climbingchance = ((levl[u.ux][u.uy].typ == MOUNTAIN) ? 3 : 10);
1146 if (uwep && uwep->oartifact == ART_KEY_OF_EREBOR) climbingchance = ((levl[u.ux][u.uy].typ == MOUNTAIN) ? 3 : 10);
1147 if (uarm && uarm->oartifact == ART_GO_TO_THE_HIGH_RANGE) climbingchance = ((levl[u.ux][u.uy].typ == MOUNTAIN) ? 3 : 10);
1148 if (uwep && uwep->otyp == CLIMBING_STICK) climbingchance = ((levl[u.ux][u.uy].typ == MOUNTAIN) ? 3 : 10);
1149 if (uarmf && itemhasappearance(uarmf, APP_CLIMBING_BOOTS)) climbingchance = ((levl[u.ux][u.uy].typ == MOUNTAIN) ? 3 : 10);
1151 if (!(u.usteed) && rn2(climbingchance)) {
1152 TimerunBug += 1; /* ugly hack --Amy */
1153 Norep("You try to scale the mountain. This may take many attempts to succeed.");
1154 /* Note that it is not a bug that you cannot easily walk over the next mountain tile
1155 * even if you're already on one, since they're considered to have different heights :D --Amy
1156 * however, with climbing gear it will indeed help */
1157 return(FALSE);
1159 /* success! */
1160 if (!(u.usteed)) {
1161 You("successfully climb the mountain.");
1162 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
1166 } else if (tmpr->typ == FARMLAND) {
1167 if (mode != DO_MOVE && !Levitation && !Flying && !(uarmf && uarmf->oartifact == ART_PURPLE_JUNGLE) && !(uarmf && uarmf->oartifact == ART_UTE_S_GREENCHANGE) && !(ublindf && ublindf->oartifact == ART_FREEBOUND) && !(uarm && uarm->oartifact == ART_TILLING_FIELDS) && !(uwep && uwep->oartifact == ART_GARY_S_RIVALRY) && !(uwep && uwep->oartifact == ART_REAL_WALKING) && !(u.usteed && u.usteed->data->mlet == S_QUADRUPED) && !(Upolyd && youmonst.data->mlet == S_QUADRUPED)) return FALSE;
1169 if (mode == DO_MOVE && !Levitation && !Flying && !(uarmf && uarmf->oartifact == ART_PURPLE_JUNGLE) && !(uarmf && uarmf->oartifact == ART_UTE_S_GREENCHANGE) && !(ublindf && ublindf->oartifact == ART_FREEBOUND) && !(uarm && uarm->oartifact == ART_TILLING_FIELDS) && !(uwep && uwep->oartifact == ART_UNDERIRDIC_) && !(uwep && uwep->oartifact == ART_GARY_S_RIVALRY) && !(uwep && uwep->oartifact == ART_REAL_WALKING) && !(u.usteed && u.usteed->data->mlet == S_QUADRUPED) && !(Upolyd && youmonst.data->mlet == S_QUADRUPED) && !(powerfulimplants() && uimplant && uimplant && uimplant->oartifact == ART_SIGNIFICANT_RNG_JITTER) ) {
1171 if (WallsAreHyperBlue) {
1172 You("crash into a farmland! Ouch!");
1174 losehp(rnd(10), "walking into a farmland", KILLED_BY);
1175 if (!rn2(Role_if(PM_COURIER) ? 1000 : uarmh ? 50 : 10)) {
1176 if (rn2(50)) {
1177 adjattrib(rn2(2) ? A_INT : A_WIS, -rno(3), FALSE, TRUE);
1178 if (!rn2(50)) adjattrib(rn2(2) ? A_INT : A_WIS, -rno(2), FALSE, TRUE);
1179 } else {
1180 You_feel("dizzy!");
1181 forget(1 + rn2(5), FALSE);
1184 } else {
1185 You("cannot cross the farmland!");
1186 if (FunnyHallu) pline("Nature preservation and all that.");
1187 /* Even passwall does not help here, this is intentional. --Amy */
1190 return FALSE;
1193 } else if (tmpr->typ == TUNNELWALL) {
1194 if (mode != DO_MOVE && !Passes_walls && (Flying || Levitation)) return FALSE;
1195 if (mode == DO_MOVE && !Passes_walls && (Flying || Levitation)) {
1197 if (WallsAreHyperBlue) {
1198 You("crash into a tunnel! Ouch!");
1200 losehp(rnd(10), "walking into a tunnel", KILLED_BY);
1201 if (!rn2(Role_if(PM_COURIER) ? 1000 : uarmh ? 50 : 10)) {
1202 if (rn2(50)) {
1203 adjattrib(rn2(2) ? A_INT : A_WIS, -rno(3), FALSE, TRUE);
1204 if (!rn2(50)) adjattrib(rn2(2) ? A_INT : A_WIS, -rno(2), FALSE, TRUE);
1205 } else {
1206 You_feel("dizzy!");
1207 forget(1 + rn2(5), FALSE);
1210 } else {
1211 if (Levitation) pline("While levitating, you cannot enter the tunnel.");
1212 else pline("While flying, you cannot enter the tunnel.");
1215 return FALSE;
1219 } else if (tmpr->typ == GRAVEWALL) {
1220 /* Once again, passwall intentionally does not help --Amy */
1222 if (u.walscholarpass) goto walscholardone; /* can pass through */
1224 if (mode != DO_MOVE) return FALSE;
1226 if (Role_if(PM_WALSCHOLAR) && (yn("You can move into the grave wall, which will require you to use some nutrition.") == 'y') ) { /* so that you don't get suck having to trash your alignment --Amy */
1227 morehungry(25);
1228 goto walscholardone;
1231 if (Role_if(PM_WALSCHOLAR) && (yn("Do you really want to dig into the grave wall? Doing so would be sinful for a Walscholar.") != 'y') ) return FALSE;
1233 if (rn2(5) && !(uwep && uwep->oartifact == ART_CERULEAN_SMASH) ) {
1234 Norep("You dig into the grave wall.");
1235 TimerunBug += 1; /* ugly hack --Amy */
1236 return FALSE;
1237 } else {
1238 You("dig out the grave wall.");
1239 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
1240 u.cnd_gravewallamount++;
1242 if (Role_if(PM_WALSCHOLAR)) {
1243 You_feel("like a miserably hussy.");
1244 if (FunnyHallu) pline("Maybe you should buy a bottle of drum stint reluctance perfume.");
1245 increasesincounter(1);
1246 u.alignlim--;
1247 adjalign(-10);
1250 tmpr->typ = CORR;
1251 blockorunblock_point(ux+dx,uy+dy);
1252 newsym(ux+dx,uy+dy);
1253 if (FemtrapActiveJana && !rn2(2)) {
1254 if (rn2(2)) {
1255 pline("There was a woman hidden underneath the wall!");
1256 (void) makemon(specialtensmon(111), ux+dx, uy+dy, MM_ANGRY|MM_ADJACENTOK|MM_FRENZIED);
1257 return FALSE;
1258 } else {
1259 if (isstunfish) nomul(-(rnz(30)), "paralyzed by Jana's cursed called", FALSE);
1260 else nomul(-(rn1(15, 15)), "paralyzed by Jana's cursed called", FALSE);
1261 pline("Jana is laughing at you because there was a cursed called hidden underneath the wall.");
1263 } else if (!rn2(20) && isok(ux+dx, uy+dy)) {
1264 maketrap(ux+dx, uy+dy, rndtrap(), 100, TRUE);
1265 } else if (!rn2(20) && isok(ux+dx, uy+dy)) {
1266 pline("There was a monster hidden underneath the wall!");
1267 makemon((struct permonst *)0, ux+dx, uy+dy, MM_ADJACENTOK);
1268 return FALSE;
1271 if (Role_if(PM_HUSSY)) {
1272 You("feel like a proper hussy.");
1273 adjalign(rnd(5));
1274 if (!rn2(10)) {
1275 pline("There was some gold hidden in the grave wall!");
1276 u.ugold += rnz(10);
1278 if (!rn2(1000) && isok(ux+dx, uy+dy)) {
1279 (void) mksobj_at(DIAMOND, ux+dx, uy+dy, TRUE, TRUE, FALSE);
1280 pline("Wow, this was one of the special grave walls where Hans Walt had hidden a diamond!");
1284 if (!Role_if(PM_WALSCHOLAR)) {
1285 more_experienced(Role_if(PM_HUSSY) ? 50 : 5, 0);
1286 newexplevel();
1291 walscholardone:
1294 } else if (tmpr->typ == WATERTUNNEL) {
1295 if (mode != DO_MOVE) return FALSE;
1297 if ( ( ( (tunnels(youmonst.data) && !needspick(youmonst.data)) || (uarmf && uarmf->oartifact == ART_STONEWALL_CHECKERBOARD_DIS) || (Race_if(PM_SCURRIER) && !Upolyd) || u.geolysis) ) && flags.eatingwalls && (Flying || Levitation) ) {
1298 /* can eat the stupid things */
1299 if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
1302 /* if you just ate it, you shouldn't crash into a no-longer-existing rock part above the tunnel */
1303 if (mode == DO_MOVE && !Passes_walls && (Flying || Levitation || Wwalking) && (levl[x][y].typ == WATERTUNNEL) ) {
1305 if (WallsAreHyperBlue) {
1306 You("crash into a water tunnel! Ouch!");
1308 losehp(rnd(10), "walking into a water tunnel", KILLED_BY);
1309 if (!rn2(Role_if(PM_COURIER) ? 1000 : uarmh ? 50 : 10)) {
1310 if (rn2(50)) {
1311 adjattrib(rn2(2) ? A_INT : A_WIS, -rno(3), FALSE, TRUE);
1312 if (!rn2(50)) adjattrib(rn2(2) ? A_INT : A_WIS, -rno(2), FALSE, TRUE);
1313 } else {
1314 You_feel("dizzy!");
1315 forget(1 + rn2(5), FALSE);
1318 } else {
1319 if (Levitation) pline("While levitating, you cannot enter the water tunnel.");
1320 else if (Flying) pline("While flying, you cannot enter the water tunnel.");
1321 else if (Wwalking) You("don't seem to fit into the water tunnel.");
1322 else pline("Something prevents you from entering the water tunnel.");
1325 return FALSE;
1329 } else if ( ( ( (tunnels(youmonst.data) && !needspick(youmonst.data)) || (uarmf && uarmf->oartifact == ART_STONEWALL_CHECKERBOARD_DIS) || (Race_if(PM_SCURRIER) && !Upolyd) || u.geolysis) ) && flags.eatingwalls ) {
1330 /* Eat the rock. */
1331 if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
1333 /* autodig: note by Amy, this needs to interact with all nasty traps that would fire when you apply something.
1334 * For simplicity of coding, I decided to make autodig do nothing if you have such a trap active :P */
1335 } else if (flags.autodig && !(u.powerfailure || (uarmf && uarmf->oartifact == ART_BRITTA_S_MURDER_STORY) || CurseAsYouUse || InterruptEffect || u.uprops[INTERRUPT_EFFECT].extrinsic || have_interruptionstone() || (isselfhybrid && (moves % 3 == 0 && moves % 11 != 0) ) ) && !(WallsAreHyperBlue) && !flags.run && !flags.nopick &&
1336 uwep && is_pick(uwep)) {
1337 /* MRKR: Automatic digging when wielding the appropriate tool */
1338 if (mode == DO_MOVE) {
1339 if (!touch_artifact(uwep, &youmonst)) return FALSE;
1340 (void) use_pick_axe2(uwep);
1342 return FALSE;
1343 } else {
1344 if (mode == DO_MOVE) {
1345 if (Is_stronghold(&u.uz) && is_db_wall(x,y))
1346 pline_The("drawbridge is up!");
1347 if (Passes_walls && !may_passwall(x,y) && In_sokoban(&u.uz))
1348 pline_The("Sokoban walls resist your ability.");
1350 if (!(Is_stronghold(&u.uz) && is_db_wall(x,y)) && !(Passes_walls && !may_passwall(x,y) && In_sokoban(&u.uz))) {
1351 if (tmpr->typ == TREE && mode == DO_MOVE) {
1353 if (WallsAreHyperBlue) {
1354 You("crash into a tree! Ouch!");
1356 losehp(rnd(10), "walking into a tree", KILLED_BY);
1357 if (!rn2(Role_if(PM_COURIER) ? 1000 : uarmh ? 50 : 10)) {
1358 if (rn2(50)) {
1359 adjattrib(rn2(2) ? A_INT : A_WIS, -rno(3), FALSE, TRUE);
1360 if (!rn2(50)) adjattrib(rn2(2) ? A_INT : A_WIS, -rno(2), FALSE, TRUE);
1361 } else {
1362 You_feel("dizzy!");
1363 forget(1 + rn2(5), FALSE);
1366 } else pline("There is a tree in the way!");
1368 } else if (mode == DO_MOVE) {
1370 if (WallsAreNoFun) {
1371 nofunwalltrigger(x, y);
1372 TimerunBug += 1; /* ugly hack --Amy */
1375 if (WallsAreHyperBlue) {
1376 You("crash into a wall! Ouch!");
1378 losehp(rnd(10), "walking into a wall", KILLED_BY);
1379 if (!rn2(Role_if(PM_COURIER) ? 1000 : uarmh ? 50 : 10)) {
1380 if (rn2(50)) {
1381 adjattrib(rn2(2) ? A_INT : A_WIS, -rno(3), FALSE, TRUE);
1382 if (!rn2(50)) adjattrib(rn2(2) ? A_INT : A_WIS, -rno(2), FALSE, TRUE);
1383 } else {
1384 You_feel("dizzy!");
1385 forget(1 + rn2(5), FALSE);
1388 } else pline("There is a wall in the way!");
1392 return FALSE;
1394 } else if (IS_DOOR(tmpr->typ)) {
1395 if (closed_door(x,y)) {
1397 if (Blind && mode == DO_MOVE) feel_location(x,y);
1398 /* ALI - artifact doors */
1399 if (artifact_door(x, y)) {
1400 if (mode == DO_MOVE) {
1401 if (amorphous(youmonst.data))
1402 You("try to ooze under the door, but the gap is too small.");
1403 else if ((tunnels(youmonst.data) && !needspick(youmonst.data)) || (uarmf && uarmf->oartifact == ART_STONEWALL_CHECKERBOARD_DIS) || (Race_if(PM_SCURRIER) && !Upolyd))
1404 You("hurt your teeth on the re-enforced door.");
1405 else if (x == u.ux || y == u.uy) {
1406 if (Blind || Stunned || Numbed || ACURR(A_DEX) < 10 || Fumbling) { pline("Ouch! You bump into a heavy door.");
1407 exercise(A_DEX, FALSE);
1408 } else pline("That door is closed.");
1411 return FALSE;
1412 } else
1413 if (Passes_walls)
1414 ; /* do nothing */
1415 else if (can_ooze(&youmonst) || (uwep && uwep->oartifact == ART_DOORS_ARE_NO_OBSTACLES)) {
1416 if (mode == DO_MOVE) You("ooze under the door.");
1417 } else if (((tunnels(youmonst.data) && !needspick(youmonst.data)) || (uarmf && uarmf->oartifact == ART_STONEWALL_CHECKERBOARD_DIS) || (Race_if(PM_SCURRIER) && !Upolyd)) && flags.eatingdoors ) {
1418 /* Eat the door. */
1419 if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
1420 } else {
1421 if (mode == DO_MOVE) {
1422 if (amorphous(youmonst.data))
1423 You("try to ooze under the door, but can't squeeze your possessions through.");
1424 else if (iflags.autoopen && !Confusion && !Stunned && !Fumbling && levl[ux][uy].seenv && !(RightMouseButtonDoesNotGo || u.totter || (uarms && uarms->oartifact == ART_DOLORES__VIRGINITY) || (uarms && uarms->oartifact == ART_BLUE_SHIRT_OF_DEATH) || u.uprops[TOTTER_EFFECT].extrinsic || TotterTrapEffect || have_directionswapstone() || autismweaponcheck(ART_HOW_IS_THE_CAR_ROWED) || (uimplant && uimplant->oartifact == ART_CORTEX_COPROCESSOR) || ClockwiseSpinBug || u.uprops[CLOCKWISE_SPIN_BUG].extrinsic || have_clockwisestone() || CounterclockwiseSpin || u.uprops[COUNTERCLOCKWISE_SPIN_BUG].extrinsic || have_counterclockwisestone() || InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone() || QuasarVision || u.uprops[QUASAR_BUG].extrinsic || have_quasarstone() || GrayoutBug || u.uprops[GRAYOUT_BUG].extrinsic || have_grayoutstone() || (uarmc && uarmc->oartifact == ART_DOEDOEDOEDOEDOEDOEDOE_TEST) || autismweaponcheck(ART_PWNHAMMER) || GrayCenterBug || u.uprops[GRAY_CENTER_BUG].extrinsic || have_graycenterstone() || Quaversal || u.uprops[QUAVERSAL].extrinsic || have_quaversalstone() || (uimplant && uimplant->oartifact == ART_ND_D___N_NDMNN_ND___NDMN_N) || autismweaponcheck(ART_OMGHAXERETH) || (SpellColorSilver && !u.seesilverspell) || CheckerboardBug || u.uprops[CHECKERBOARD_BUG].extrinsic || have_checkerboardstone() || autismweaponcheck(ART_SAY__CHESS_) || WallsAreHyperBlue ) ) {
1425 door_opened = flags.move = doopen_indir(x, y);
1426 opentry = 1;
1428 else if (x == ux || y == uy) {
1430 if (WallsAreHyperBlue) {
1431 You("crash into a door! Ouch!");
1433 losehp(rnd(10), "walking into a door", KILLED_BY);
1434 if (!rn2(Role_if(PM_COURIER) ? 1000 : uarmh ? 50 : 10)) {
1435 if (rn2(50)) {
1436 adjattrib(rn2(2) ? A_INT : A_WIS, -rno(3), FALSE, TRUE);
1437 if (!rn2(50)) adjattrib(rn2(2) ? A_INT : A_WIS, -rno(2), FALSE, TRUE);
1438 } else {
1439 You_feel("dizzy!");
1440 forget(1 + rn2(5), FALSE);
1444 /* It is not a mistake that the next message will still be displayed,
1445 * since it contains the check for dexterity abuse and hyperbluewalls should not disable that :D --Amy */
1447 if (Blind || Stunned || Numbed || ACURR(A_DEX) < 10 || Fumbling) {
1448 if (u.usteed) {
1449 You_cant("lead %s through that closed door.",
1450 y_monnam(u.usteed));
1451 } else
1453 pline("Ouch! You bump into a door.");
1454 exercise(A_DEX, FALSE);
1456 } else pline("That door is closed.");
1458 return FALSE;
1460 } else if (mode == TEST_TRAV) goto testdiag;
1461 if (mode == DO_MOVE) {
1463 if (WallsAreHyperBlue) {
1464 You("crash into a door! Ouch!");
1466 losehp(rnd(10), "walking into a door", KILLED_BY);
1467 if (!rn2(Role_if(PM_COURIER) ? 1000 : uarmh ? 50 : 10)) {
1468 if (rn2(50)) {
1469 adjattrib(rn2(2) ? A_INT : A_WIS, -rno(3), FALSE, TRUE);
1470 if (!rn2(50)) adjattrib(rn2(2) ? A_INT : A_WIS, -rno(2), FALSE, TRUE);
1471 } else {
1472 You_feel("dizzy!");
1473 forget(1 + rn2(5), FALSE);
1478 /* only print "there is a door in the way" if autoopen didn't try to open it --Amy */
1480 else if (dx && dy && !opentry && !Passes_walls && ((tmpr->doormask & ~D_BROKEN)
1481 #ifdef REINCARNATION
1482 || Is_rogue_level(&u.uz)
1483 #endif
1484 || block_door(x,y))) {
1486 pline("There is a door in the way!");
1490 return FALSE;
1492 } else {
1493 testdiag:
1494 if ((dx && dy && !Passes_walls
1495 && ((tmpr->doormask & ~D_BROKEN)
1496 #ifdef REINCARNATION
1497 || Is_rogue_level(&u.uz)
1498 #endif
1499 || block_door(x,y))) && !can_ooze(&youmonst) && !(uwep && uwep->oartifact == ART_DOORS_ARE_NO_OBSTACLES)) {
1500 /* Diagonal moves into a door are not allowed. */
1501 if (Blind && mode == DO_MOVE)
1502 feel_location(x,y);
1503 if (mode == DO_MOVE) pline("You cannot diagonally move through a door!");
1504 return FALSE;
1508 if (dx && dy
1509 && bad_rock(&youmonst,ux,y) && bad_rock(&youmonst,x,uy)) {
1510 /* Move at a diagonal. */
1511 if (In_sokoban(&u.uz)) {
1512 if (mode == DO_MOVE)
1513 You("cannot pass that way.");
1514 return FALSE;
1516 if ( (bigmonst(youmonst.data) && !Race_if(PM_TRANSFORMER) ) || FemtrapActivePatricia || (!Upolyd && Race_if(PM_HUMANOID_CENTAUR) ) || (!Upolyd && Race_if(PM_URGOTH) ) || (!Upolyd && Race_if(PM_ETHEREALOID) ) || (!Upolyd && Race_if(PM_INCORPOREALOID) ) || (!Upolyd && Race_if(PM_PLAYER_CERBERUS) ) || (!Upolyd && Race_if(PM_CHIROPTERAN) ) || (!Upolyd && Race_if(PM_THUNDERLORD) ) || (uarmf && uarmf->oartifact == ART_ANTJE_S_POWERSTRIDE) || (uarms && uarms->oartifact == ART_FETTIS_SLOT) || (!Upolyd && Race_if(PM_PLAYER_JABBERWOCK) ) ) {
1517 if (mode == DO_MOVE)
1518 Your("body is too large to fit through.");
1519 return FALSE;
1521 if (invent && ((inv_weight() + weight_cap()) > max_carr_cap() )) {
1522 if (mode == DO_MOVE)
1523 if (!Passes_walls)
1524 You("are carrying too much to get through.");
1525 return FALSE;
1528 /* Pick travel path that does not require crossing a trap.
1529 * Avoid water and lava using the usual running rules.
1530 * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
1531 if (flags.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) {
1532 struct trap* t = t_at(x, y);
1534 if ((t && t->tseen) ||
1535 (!Levitation && !Flying &&
1536 !is_clinger(youmonst.data) &&
1537 (is_waterypool(x, y) || is_watertunnel(x,y) || is_moorland(x,y) || is_styxriver(x,y) || is_shiftingsand(x,y) || is_urinelake(x,y) || is_lava(x, y)) && levl[x][y].seenv))
1538 return FALSE;
1541 ust = &levl[ux][uy];
1543 /* Now see if other things block our way . . */
1544 if (dx && dy && !Passes_walls && !can_ooze(&youmonst) && !(uwep && uwep->oartifact == ART_DOORS_ARE_NO_OBSTACLES)
1545 && (IS_DOOR(ust->typ) && ((ust->doormask & ~D_BROKEN)
1546 #ifdef REINCARNATION
1547 || Is_rogue_level(&u.uz)
1548 #endif
1549 || block_entry(x, y))
1550 )) {
1551 /* Can't move at a diagonal out of a doorway with door. */
1552 if (mode == DO_MOVE) pline("You cannot diagonally move out of a door!");
1553 return FALSE;
1556 if (sobj_at(BOULDER,x,y) && (In_sokoban(&u.uz) || !Passes_walls)) {
1557 if (!(Blind || Hallucination) && (flags.run >= 1) && mode != TEST_TRAV)
1558 return FALSE;
1559 if (mode == DO_MOVE) {
1560 /* tunneling monsters will chew before pushing */
1561 if ( (( (tunnels(youmonst.data) && !needspick(youmonst.data)) || (uarmf && uarmf->oartifact == ART_STONEWALL_CHECKERBOARD_DIS) || (Race_if(PM_SCURRIER) && !Upolyd) || u.geolysis) &&
1562 !In_sokoban(&u.uz)) && flags.eatingboulders ) {
1563 if (still_chewing(x,y)) return FALSE;
1564 } else
1565 if (moverock() < 0) return FALSE;
1566 } else if (mode == TEST_TRAV) {
1567 struct obj* obj;
1569 /* don't pick two boulders in a row, unless there's a way thru */
1570 if (sobj_at(BOULDER,ux,uy) && !In_sokoban(&u.uz)) {
1571 if (!Passes_walls &&
1572 !(tunnels(youmonst.data) && !needspick(youmonst.data)) &&
1573 !(Race_if(PM_SCURRIER) && !Upolyd) &&
1574 !(uarmf && uarmf->oartifact == ART_STONEWALL_CHECKERBOARD_DIS) &&
1575 !carrying(PICK_AXE) && !carrying(CONGLOMERATE_PICK) && !carrying(UNWIELDY_PICK) && !carrying(CONUNDRUM_PICK) && !carrying(SHOVEL) && !carrying(MYSTERY_PICK) &&
1576 !carrying(BRONZE_PICK) && !carrying(NANO_PICK) && !carrying(BRICK_PICK) && !carrying(MYSTERIOUS_PICK) && !carrying(DWARVISH_MATTOCK) &&
1577 !((obj = carrying(WAN_DIGGING)) &&
1578 !objects[obj->otyp].oc_name_known))
1579 return FALSE;
1582 /* assume you'll be able to push it when you get there... */
1585 /* OK, it is a legal place to move. */
1586 return TRUE;
1590 * Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy).
1591 * A shortest path is returned. If guess is TRUE, consider various
1592 * inaccessible locations as valid intermediate path points.
1593 * Returns TRUE if a path was found.
1595 static boolean
1596 findtravelpath(guess)
1597 boolean guess;
1599 /* if travel to adjacent, reachable location, use normal movement rules */
1600 if (!guess && iflags.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1 && !(u.ux != u.tx && u.uy != u.ty && (BishopGridbug || u.uprops[BISHOP_GRIDBUG].extrinsic || have_bishopstone() || (uarmg && uarmg->oartifact == ART_LINE_CAN_PLAY_BY_YOURSELF) || autismweaponcheck(ART_KILLER_PIANO) || isgridbug(youmonst.data) || (Race_if(PM_WEAPON_BUG) && !Upolyd)) ) ) {
1601 flags.run = 0;
1602 if (test_move(u.ux, u.uy, u.tx-u.ux, u.ty-u.uy, TEST_MOVE)) {
1603 u.dx = u.tx-u.ux;
1604 u.dy = u.ty-u.uy;
1605 forcenomul(0, 0);
1606 iflags.travelcc.x = iflags.travelcc.y = -1;
1607 return TRUE;
1609 flags.run = 8;
1611 if (u.tx != u.ux || u.ty != u.uy) {
1612 xchar travel[COLNO][ROWNO];
1613 xchar travelstepx[2][COLNO*ROWNO];
1614 xchar travelstepy[2][COLNO*ROWNO];
1615 xchar tx, ty, ux, uy;
1616 int n = 1; /* max offset in travelsteps */
1617 int set = 0; /* two sets current and previous */
1618 int radius = 1; /* search radius */
1619 int i;
1621 /* If guessing, first find an "obvious" goal location. The obvious
1622 * goal is the position the player knows of, or might figure out
1623 * (couldsee) that is closest to the target on a straight path.
1625 if (guess) {
1626 tx = u.ux; ty = u.uy; ux = u.tx; uy = u.ty;
1627 } else {
1628 tx = u.tx; ty = u.ty; ux = u.ux; uy = u.uy;
1631 noguess:
1632 (void) memset((void *)travel, 0, sizeof(travel));
1633 travelstepx[0][0] = tx;
1634 travelstepy[0][0] = ty;
1636 while (n != 0) {
1637 int nn = 0;
1639 for (i = 0; i < n; i++) {
1640 int dir;
1641 int x = travelstepx[set][i];
1642 int y = travelstepy[set][i];
1643 static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
1644 /* no diagonal movement for grid bugs */
1645 int dirmax = (BishopGridbug || u.uprops[BISHOP_GRIDBUG].extrinsic || have_bishopstone() || (uarmg && uarmg->oartifact == ART_LINE_CAN_PLAY_BY_YOURSELF) || autismweaponcheck(ART_KILLER_PIANO) || isgridbug(youmonst.data) || (Race_if(PM_WEAPON_BUG) && !Upolyd))? 4 : 8;
1647 for (dir = 0; dir < dirmax; ++dir) {
1648 int nx = x+xdir[ordered[dir]];
1649 int ny = y+ydir[ordered[dir]];
1651 if (!isok(nx, ny)) continue;
1652 if ((!Passes_walls && !can_ooze(&youmonst) && !(uwep && uwep->oartifact == ART_DOORS_ARE_NO_OBSTACLES) &&
1653 closed_door(x, y)) || sobj_at(BOULDER, x, y)) {
1654 /* closed doors and boulders usually
1655 * cause a delay, so prefer another path */
1656 if (travel[x][y] > radius-3) {
1657 travelstepx[1-set][nn] = x;
1658 travelstepy[1-set][nn] = y;
1659 /* don't change travel matrix! */
1660 nn++;
1661 continue;
1664 if (test_move(x, y, nx-x, ny-y, TEST_TRAV) &&
1665 (levl[nx][ny].seenv || (!Blind && couldsee(nx, ny)))) {
1666 if (nx == ux && ny == uy) {
1667 if (!guess) {
1668 u.dx = x-ux;
1669 u.dy = y-uy;
1670 if (x == u.tx && y == u.ty) {
1671 forcenomul(0, 0);
1672 /* reset run so domove run checks work */
1673 flags.run = 8;
1674 iflags.travelcc.x = iflags.travelcc.y = -1;
1676 return TRUE;
1678 } else if (!travel[nx][ny]) {
1679 travelstepx[1-set][nn] = nx;
1680 travelstepy[1-set][nn] = ny;
1681 travel[nx][ny] = radius;
1682 nn++;
1688 n = nn;
1689 set = 1-set;
1690 radius++;
1693 /* if guessing, find best location in travel matrix and go there */
1694 if (guess) {
1695 int px = tx, py = ty; /* pick location */
1696 int dist, nxtdist, d2, nd2;
1698 dist = distmin(ux, uy, tx, ty);
1699 d2 = dist2(ux, uy, tx, ty);
1700 for (tx = 1; tx < COLNO; ++tx)
1701 for (ty = 0; ty < ROWNO; ++ty)
1702 if (travel[tx][ty]) {
1703 nxtdist = distmin(ux, uy, tx, ty);
1704 if (nxtdist == dist && couldsee(tx, ty)) {
1705 nd2 = dist2(ux, uy, tx, ty);
1706 if (nd2 < d2) {
1707 /* prefer non-zigzag path */
1708 px = tx; py = ty;
1709 d2 = nd2;
1711 } else if (nxtdist < dist && couldsee(tx, ty)) {
1712 px = tx; py = ty;
1713 dist = nxtdist;
1714 d2 = dist2(ux, uy, tx, ty);
1718 if (px == u.ux && py == u.uy) {
1719 /* no guesses, just go in the general direction */
1720 u.dx = sgn(u.tx - u.ux);
1721 u.dy = sgn(u.ty - u.uy);
1722 if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE))
1723 return TRUE;
1724 goto found;
1726 tx = px;
1727 ty = py;
1728 ux = u.ux;
1729 uy = u.uy;
1730 set = 0;
1731 n = radius = 1;
1732 guess = FALSE;
1733 goto noguess;
1735 return FALSE;
1738 found:
1739 u.dx = 0;
1740 u.dy = 0;
1741 forcenomul(0, 0);
1742 return FALSE;
1745 boolean
1746 ask_about_trap(int x, int y)
1749 struct trap *traphere = t_at(x, y);
1751 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1753 if (KnowledgeBug || u.uprops[KNOWLEDGE_BUG].extrinsic || have_trapknowledgestone()) return FALSE;
1755 /* hallu means you cannot tell traps apart, and we used to make it so that you never get any confirmation;
1756 * it's much more fair if you always get one though --Amy
1757 * what we definitely cannot do is make it give the confirmation depending on what trap it is, because that would
1758 * be leaking info */
1759 if (Hallucination && (traphere && traphere->tseen) && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) )) return TRUE;
1761 if (/* is_pool(x, y) || is_lava(x, y) || */ (traphere && traphere->tseen) && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && !Hallucination) {
1763 /* who the heck included this? Maybe the player doesn't really want to use the portal at all! --Amy */
1764 /*if (traphere->ttyp == MAGIC_PORTAL) {
1765 return FALSE;
1768 if (SpellColorBrown && traphere->ttyp == SHIT_TRAP) return FALSE;
1770 if (traphere->ttyp == S_PRESSING_TRAP) {
1771 return FALSE;
1773 if (traphere->ttyp == WRONG_STAIRS) {
1774 return FALSE;
1777 if (Role_if(PM_TOPMODEL) && Is_qlocate(&u.uz)) /* traps on this level do wind damage */
1778 return TRUE;
1779 if (Role_if(PM_FAILED_EXISTENCE) && Is_qlocate(&u.uz))
1780 return TRUE;
1782 if (Levitation || Flying) {
1783 if (!In_sokoban(&u.uz) && traphere->ttyp == PIT) {
1784 return FALSE;
1786 if (!In_sokoban(&u.uz) && traphere->ttyp == SPIKED_PIT) {
1787 return FALSE;
1789 if (!In_sokoban(&u.uz) && traphere->ttyp == GIANT_CHASM) {
1790 return FALSE;
1792 if (!In_sokoban(&u.uz) && traphere->ttyp == SHIT_PIT) {
1793 return FALSE;
1795 if (!In_sokoban(&u.uz) && traphere->ttyp == MANA_PIT) {
1796 return FALSE;
1798 if (!In_sokoban(&u.uz) && traphere->ttyp == ANOXIC_PIT) {
1799 return FALSE;
1801 if (!In_sokoban(&u.uz) && traphere->ttyp == HYPOXIC_PIT) {
1802 return FALSE;
1804 if (!In_sokoban(&u.uz) && traphere->ttyp == ACID_PIT) {
1805 return FALSE;
1807 if (!In_sokoban(&u.uz) && traphere->ttyp == HOLE) {
1808 return FALSE;
1810 if (!In_sokoban(&u.uz) && traphere->ttyp == SHAFT_TRAP) {
1811 return FALSE;
1813 if (!In_sokoban(&u.uz) && traphere->ttyp == TRAPDOOR) {
1814 return FALSE;
1816 if (traphere->ttyp == BEAR_TRAP) {
1817 return FALSE;
1819 if (traphere->ttyp == ACID_POOL) {
1820 return FALSE;
1822 if (traphere->ttyp == WATER_POOL) {
1823 return FALSE;
1825 if (traphere->ttyp == SQKY_BOARD) {
1826 return FALSE;
1828 /* used to ask for shit trap but that one has so many ways to trigger anyway... --Amy */
1830 return TRUE;
1832 return FALSE;
1835 boolean
1836 ask_about_water(int x, int y)
1838 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1840 if (is_pool(u.ux, u.uy)) return FALSE;
1841 if (is_watertunnel(u.ux, u.uy)) return FALSE;
1843 if (is_pool(x, y) && !Levitation && !Flying && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1845 if (is_pool(x, y) && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv && Role_if(PM_TOPMODEL) && Is_qlocate(&u.uz) ) return TRUE;
1846 if (is_pool(x, y) && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv && Role_if(PM_FAILED_EXISTENCE) && Is_qlocate(&u.uz) ) return TRUE;
1848 return FALSE;
1851 boolean
1852 ask_about_lava(int x, int y)
1854 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1856 if (is_lava(u.ux, u.uy)) return FALSE;
1858 if (is_lava(x, y) && !Levitation && !Flying && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1859 return FALSE;
1862 boolean
1863 ask_about_watertunnel(int x, int y)
1865 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1867 if (is_watertunnel(u.ux, u.uy)) return FALSE;
1868 if (is_pool(u.ux, u.uy)) return FALSE;
1870 if (is_watertunnel(x, y) && !Levitation && !Flying && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1871 return FALSE;
1874 boolean
1875 ask_about_crystalwater(int x, int y)
1877 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1879 if (is_crystalwater(u.ux, u.uy)) return FALSE;
1881 if (is_crystalwater(x, y) && (Levitation || Flying) && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1882 return FALSE;
1885 boolean
1886 ask_about_moorland(int x, int y)
1888 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1890 if (is_moorland(u.ux, u.uy)) return FALSE;
1892 if (is_moorland(x, y) && !Levitation && !Flying && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1893 return FALSE;
1896 boolean
1897 ask_about_urinelake(int x, int y)
1899 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1901 if (is_urinelake(u.ux, u.uy)) return FALSE;
1903 if (is_urinelake(x, y) && !Levitation && !Flying && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1904 return FALSE;
1907 boolean
1908 ask_about_shiftingsand(int x, int y)
1910 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1912 if (is_shiftingsand(u.ux, u.uy)) return FALSE;
1914 if (is_shiftingsand(x, y) && !Levitation && !Flying && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1915 return FALSE;
1918 boolean
1919 ask_about_styxriver(int x, int y)
1921 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1923 if (is_styxriver(u.ux, u.uy)) return FALSE;
1925 if (is_styxriver(x, y) && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1926 return FALSE;
1929 boolean
1930 ask_about_burningwagon(int x, int y)
1932 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1934 if (is_burningwagon(u.ux, u.uy)) return FALSE;
1936 if (is_burningwagon(x, y) && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1937 return FALSE;
1940 boolean
1941 ask_about_nethermist(int x, int y)
1943 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1945 if (is_nethermist(u.ux, u.uy)) return FALSE;
1947 if (is_nethermist(x, y) && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1948 return FALSE;
1951 boolean
1952 ask_about_stalactite(int x, int y)
1954 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1956 if (is_stalactite(u.ux, u.uy)) return FALSE;
1958 if (is_stalactite(x, y) && (Flying || Levitation) && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1959 return FALSE;
1962 boolean
1963 ask_about_raincloud(int x, int y)
1965 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1967 if (is_raincloud(u.ux, u.uy)) return FALSE;
1969 if (is_raincloud(x, y) && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1970 return FALSE;
1973 boolean
1974 ask_about_bubble(int x, int y)
1976 if (ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone()) return FALSE;
1978 if (is_bubble(u.ux, u.uy)) return FALSE;
1980 if (is_bubble(x, y) && !(Confusion && !Conf_resist) && !(Stunned && !Stun_resist && !(uarmf && itemhasappearance(uarmf, APP_FLUFFY_SANDALS)) ) && levl[x][y].seenv) return TRUE;
1981 return FALSE;
1984 void
1985 domove()
1987 register struct monst *mtmp;
1988 register struct rm *tmpr;
1989 register xchar x,y;
1990 struct trap *trap;
1991 struct trap *traphere = t_at(x, y);
1992 int wtcap;
1993 boolean on_ice;
1994 xchar chainx, chainy, ballx, bally; /* ball&chain new positions */
1995 int bc_control; /* control for ball&chain */
1996 boolean cause_delay = FALSE; /* dragging ball will skip a move */
1997 const char *predicament;
1998 boolean displacer = FALSE; /* defender attempts to displace you */
1999 boolean peacedisplacer = FALSE;
2000 boolean canexistonsquare = TRUE;
2002 u_wipe_engr(rnd(5));
2004 if (flags.travel) {
2005 if (!findtravelpath(FALSE))
2006 (void) findtravelpath(TRUE);
2007 iflags.travel1 = 0;
2010 if(((wtcap = near_capacity()) >= OVERLOADED
2011 || (wtcap > SLT_ENCUMBER &&
2012 (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
2013 : (u.uhp < 10 && u.uhp != u.uhpmax))))
2014 && !Is_airlevel(&u.uz)) {
2015 if(wtcap < OVERLOADED) {
2016 You("don't have enough stamina to move.");
2017 exercise(A_CON, FALSE);
2018 } else
2019 You("collapse under your load.");
2020 forcenomul(0, 0);
2021 return;
2023 if (Race_if(PM_ELONA_SNAIL) && !flags.forcefight && uarmf && !PlayerInHighHeels) {
2024 pline("In order to move, snails need to be bare-footed or wearing high heels!");
2025 forcenomul(0, 0);
2026 return;
2029 if(u.uswallow) {
2030 u.dx = u.dy = 0;
2031 u.ux = x = u.ustuck->mx;
2032 u.uy = y = u.ustuck->my;
2033 mtmp = u.ustuck;
2034 } else {
2035 if (Is_airlevel(&u.uz) && !flags.forcefight && rn2(2) && /* was rn2(4) - let's make it a bit easier --Amy */
2036 !Levitation && !Flying) {
2037 switch(rn2(3)) {
2038 case 0:
2039 You("tumble in place.");
2040 exercise(A_DEX, FALSE);
2041 break;
2042 case 1:
2043 You_cant("control your movements very well."); break;
2044 case 2:
2045 pline("It's hard to walk in thin air.");
2046 exercise(A_DEX, TRUE);
2047 break;
2049 return;
2052 /* check slippery ice */
2053 on_ice = !Levitation && is_ice(u.ux, u.uy);
2054 if (on_ice) {
2056 if (uarmf && uarmf->oartifact == ART_MERLOT_FUTURE && !(HFast)) {
2057 incr_itimeout(&HFast, rnd(500));
2058 pline("Vrooooom, your ski heels speed up thanks to walking on snow!");
2061 static int skates = 0;
2062 if (!skates) skates = find_skates();
2063 static int skates2 = 0;
2064 if (!skates2) skates2 = find_skates2();
2065 static int skates3 = 0;
2066 if (!skates3) skates3 = find_skates3();
2067 static int skates4 = 0;
2068 if (!skates4) skates4 = find_skates4();
2069 static int skates5 = 0;
2070 if (!skates5) skates5 = find_cyan_sneakers();
2071 if ((uarmf && uarmf->otyp == skates)
2072 || (powerfulimplants() && uimplant && uimplant->oartifact == ART_WHITE_WHALE_HATH_COME)
2073 || (uarmf && uarmf->otyp == skates2)
2074 || (uarmf && uarmf->otyp == skates3)
2075 || (uarmf && uarmf->otyp == skates4)
2076 || (uarmf && uarmf->otyp == skates5)
2077 || (uwep && uwep->oartifact == ART_GLACIERDALE)
2078 || (uarmf && uarmf->oartifact == ART_BRIDGE_SHITTE)
2079 || (uarmf && uarmf->oartifact == ART_THICKER_THAN_THE_HEAD)
2080 || (uarmf && uarmf->oartifact == ART_LITTLE_ICE_BLOCK_WITH_THE_)
2081 || (uarmf && uarmf->oartifact == ART_ONSET_OF_WINTER)
2082 || (uarmf && uarmf->oartifact == ART_MERLOT_FUTURE)
2083 || (uarmf && uarmf->oartifact == ART_IMPOSSIBLE_CATWALK)
2084 || (uarmf && uarmf->oartifact == ART_ANTI_SLIDE)
2085 || (uwep && uwep->oartifact == ART_DAMN_SKI_WEDGE && uarmf)
2086 || resists_cold(&youmonst) || Flying
2087 || is_floater(youmonst.data) || is_clinger(youmonst.data)
2088 || is_whirly(youmonst.data))
2089 on_ice = FALSE;
2090 else if (!rn2(ColdImmunity ? 20 : Cold_resistance ? 3 : 2)) {
2091 HFumbling |= FROMOUTSIDE;
2092 HFumbling &= ~TIMEOUT;
2093 HFumbling += 1; /* slip on next move */
2096 if (!on_ice && !u.fumbleduration && (HFumbling & FROMOUTSIDE))
2097 HFumbling &= ~FROMOUTSIDE;
2099 x = u.ux + u.dx;
2100 y = u.uy + u.dy;
2101 /* Check if your steed can move */
2102 if (u.usteed && !flags.forcefight && (!u.usteed->mcanmove || u.usteed->msleeping)) {
2103 Your("steed doesn't respond!");
2104 forcenomul(0, 0);
2105 return;
2108 /* In Soviet Russia, stunning is a crippling status effect that will fuck you up. You're not supposed to stand
2109 * any chance while stunned, because seriously, players having a chance? That's a no-go! --Amy */
2111 if ((Stunned && !rn2(issoviet ? 1 : StrongStun_resist ? 20 : Stun_resist ? 8 : 2)) || (Confusion && !rn2(issoviet ? 2 : StrongConf_resist ? 200 : Conf_resist ? 40 : 8) || (autismweaponcheck(ART_MISGUIDED_MISSILE) && !rn2(20)) || ((uarmh && itemhasappearance(uarmh, APP_THINKING_HELMET)) && !rn2(8) ) || (uimplant && uimplant->oartifact == ART_IRON_OF_INNERMOST_JOY && ((moves % 13) < 10) ) )
2112 /* toned down so it's less crippling --Amy
2113 * nerf for extremely fast steeds: they cause you to sometimes walk randomly */
2114 || (u.usteed && ((u.usteed->mconf && confsteeddir()) || (u.usteed->data->mmove > 36 && rnd(u.usteed->data->mmove) > 36) ) )
2116 register int tries = 0;
2118 do {
2119 if(tries++ > 50) {
2120 forcenomul(0, 0);
2121 return;
2123 confdir();
2124 x = u.ux + u.dx;
2125 y = u.uy + u.dy;
2126 } while(!isok(x, y) || bad_rock(&youmonst, x, y));
2128 /* turbulence might alter your actual destination */
2129 if (u.uinwater) {
2130 water_friction();
2131 if (!u.dx && !u.dy) {
2132 forcenomul(0, 0);
2133 return;
2135 x = u.ux + u.dx;
2136 y = u.uy + u.dy;
2138 if(!isok(x, y)) {
2139 forcenomul(0, 0);
2140 return;
2142 if (((trap = t_at(x, y)) && trap->tseen) ||
2143 (Blind && !Levitation && !Flying &&
2144 !is_clinger(youmonst.data) &&
2145 (is_waterypool(x, y) || is_watertunnel(x,y) || is_shiftingsand(x,y) || is_moorland(x,y) || is_urinelake(x,y) || is_lava(x, y)) && levl[x][y].seenv)) {
2146 if(flags.run >= 2) {
2147 forcenomul(0, 0);
2148 flags.move = 0;
2149 return;
2150 } else
2151 forcenomul(0, 0);
2154 if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
2155 if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
2156 /* perhaps it fled (or was teleported or ... ) */
2157 setustuck(0);
2158 } else if (sticks(youmonst.data)) {
2159 /* When polymorphed into a sticking monster,
2160 * u.ustuck means it's stuck to you, not you to it.
2162 You("release %s.", mon_nam(u.ustuck));
2163 setustuck(0);
2164 } else {
2165 /* If holder is asleep or paralyzed:
2166 * 37.5% chance of getting away,
2167 * 12.5% chance of waking/releasing it;
2168 * otherwise:
2169 * 7.5% chance of getting away.
2170 * [strength ought to be a factor]
2171 * If holder is tame and there is no conflict,
2172 * guaranteed escape.
2174 switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
2175 case 0: case 1: case 2:
2176 pull_free:
2177 You("pull free from %s.", mon_nam(u.ustuck));
2178 setustuck(0);
2179 break;
2180 case 3:
2181 if (!u.ustuck->mcanmove) {
2182 /* it's free to move on next turn */
2183 u.ustuck->mfrozen = 1;
2184 u.ustuck->msleeping = 0;
2186 /*FALLTHRU*/
2187 default:
2188 if (u.ustuck->mtame &&
2189 !Conflict && !u.ustuck->mconf)
2190 goto pull_free;
2191 You("cannot escape from %s!", mon_nam(u.ustuck));
2192 nomul(0, 0, FALSE);
2193 return;
2198 mtmp = m_at(x,y);
2199 if (mtmp) {
2200 /* Don't attack if you're running, and can see it */
2201 /* We should never get here if forcefight */
2202 if (flags.run &&
2203 ((!Blind && mon_visible(mtmp) &&
2204 ((mtmp->m_ap_type != M_AP_FURNITURE &&
2205 mtmp->m_ap_type != M_AP_OBJECT) ||
2206 Protection_from_shape_changers)) ||
2207 sensemon(mtmp))) {
2208 forcenomul(0, 0);
2209 flags.move = 0;
2210 return;
2214 u.ux0 = u.ux;
2215 u.uy0 = u.uy;
2216 bhitpos.x = x;
2217 bhitpos.y = y;
2218 tmpr = &levl[x][y];
2219 /* attack monster */
2221 if(mtmp) {
2223 forcenomul(0, 0);
2224 /* only attack if we know it's there */
2225 /* or if we used the 'F' command to fight blindly */
2226 /* or if it hides_under, in which case we call attack() to print
2227 * the Wait! message.
2228 * This is different from ceiling hiders, who aren't handled in
2229 * attack().
2232 /* If they used a 'm' command, trying to move onto a monster
2233 * prints the below message and wastes a turn. The exception is
2234 * if the monster is unseen and the player doesn't remember an
2235 * invisible monster--then, we fall through to attack() and
2236 * attack_check(), which still wastes a turn, but prints a
2237 * different message and makes the player remember the monster. */
2238 if(flags.nopick &&
2239 (canspotmon(mtmp) || memory_is_invisible(x, y))){
2240 if(mtmp->m_ap_type && !Protection_from_shape_changers
2241 && !sensemon(mtmp))
2242 stumble_onto_mimic(mtmp);
2243 else if (mtmp->mpeaceful && !Hallucination) {
2244 pline("Pardon me, %s.", m_monnam(mtmp));
2246 /* Amy edit: it makes no fucking sense that Stormbringer doesn't auto-attack in this situation!
2247 * You fucking bumped into a fucking peaceful monster with a fucking Stormbringer for fuck's sake!
2248 * Since it's too annoying to program it so that it does, I'm just making the monster hostile for now */
2249 if (BloodthirstyAttacking || (uwep && weapon_is_bloodthirsty(uwep)) || (u.twoweap && uswapwep && weapon_is_bloodthirsty(uswapwep)) ) {
2250 setmangry(mtmp);
2252 } else {
2253 You("move right into %s.", mon_nam(mtmp));
2254 if (BloodthirstyAttacking || (uwep && weapon_is_bloodthirsty(uwep)) || (u.twoweap && uswapwep && weapon_is_bloodthirsty(uswapwep)) ) {
2255 setmangry(mtmp);
2258 return;
2261 /* If there is ANYthing that might be a remembered monster,
2262 * the player should goddamn ATTACK IT and NOT waste a turn. GRRRR. --Amy */
2263 if(flags.forcefight || memory_is_invisible(x, y) || mon_warning(mtmp) || !mtmp->mundetected || sensemon(mtmp) ||
2264 ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL) &&
2265 !is_safepet(mtmp))){
2266 gethungry();
2267 if(wtcap >= HVY_ENCUMBER && moves%3) {
2268 if (Upolyd && u.mh > 1) {
2269 u.mh--;
2270 } else if (!Upolyd && u.uhp > 1) {
2271 u.uhp--;
2272 } else {
2273 You("pass out from exertion!");
2274 exercise(A_CON, FALSE);
2275 fall_asleep(-10, FALSE);
2278 if(multi < 0) return; /* we just fainted */
2279 /* new displacer beast thingie -- by [Tom] */
2280 /* sometimes, instead of attacking, you displace it. */
2281 /* Good joke, huh? */
2282 if ( (mtmp->data == &mons[PM_DISPLACER_BEAST] || mtmp->data == &mons[PM_HYPER_CAVE_BEAR] || mtmp->data == &mons[PM_KURIKKUSHITEKUDASAI__ANATA_NO_OKANE_WANAKU_NATTE_IMASU] || mtmp->data == &mons[PM_REPLACER_BEAST] || mtmp->data == &mons[PM_MISPLACER_BEAST] || mtmp->data == &mons[PM_ELOCATOR] || mtmp->data == &mons[PM_ANCIENT_OF_THE_BURNING_WASTES] || mtmp->data == &mons[PM_SARTAN_TANNIN] || mtmp->data == &mons[PM_POLYMORPH_CODE] || mtmp->data == &mons[PM_SECRET_POLYMORPH_CODE] || mtmp->data == &mons[PM_FIRST_WRAITHWORM] || mtmp->data == &mons[PM_WRAITHWORM] || mtmp->data == &mons[PM_LILAC_FEMMY] || mtmp->data == &mons[PM_SHARAB_KAMEREL] || mtmp->data == &mons[PM_WUXTINA] || mtmp->data == &mons[PM_IVEL_WUXTINA] || mtmp->data == &mons[PM_FLUTTERBUG] || mtmp->data == &mons[PM_LIPSTICK_HC_GIRL] || mtmp->data == &mons[PM_CREEPY_EVIL_GHOST] || mtmp->data == &mons[PM_ORTHOS] || mtmp->data == &mons[PM_SHIMMERING_DRACONIAN] || mtmp->data == &mons[PM_JUMPING_CHAMPION] || mtmp->data->mlet == S_GRUE || mtmp->data == &mons[PM_QUANTUM_MOLD] || mtmp->data == &mons[PM_QUANTUM_GROWTH] || mtmp->data == &mons[PM_QUANTUM_FUNGUS] || mtmp->data == &mons[PM_QUANTUM_PATCH] || mtmp->data == &mons[PM_QUANTUM_STALK] || mtmp->data == &mons[PM_QUANTUM_MUSHROOM] || mtmp->data == &mons[PM_QUANTUM_SPORE] || mtmp->data == &mons[PM_QUANTUM_COLONY] || mtmp->data == &mons[PM_QUANTUM_FORCE_FUNGUS] || mtmp->data == &mons[PM_QUANTUM_WORT] || mtmp->data == &mons[PM_QUANTUM_FORCE_PATCH] || mtmp->data == &mons[PM_QUANTUM_WARP_FUNGUS] || mtmp->data == &mons[PM_QUANTUM_WARP_PATCH] || mtmp->egotype_displacer) && !rn2(2))
2283 displacer = TRUE; /* grues can also displace the player to make them more annoying --Amy */
2284 else if (mtmp->data == &mons[PM_XXXXXXXXXXXXXXXXXXXX]) displacer = TRUE;
2285 else if (tech_inuse(T_EDDY_WIND)) peacedisplacer = TRUE;
2286 else if (u.swappositioncount) peacedisplacer = TRUE;
2287 else if (uwep && uwep->oartifact == ART_DIZZY_METAL_STORM) peacedisplacer = TRUE;
2288 /* Displacement allows the player to displace peaceful things --Amy */
2289 else if (Displaced && !mtmp->isshk && !mtmp->ispriest && mtmp->mpeaceful) peacedisplacer = TRUE;
2290 else if (Race_if(PM_BABYLONIAN) && mtmp->mpeaceful && mtmp->data->mlet == S_TURRET) peacedisplacer = TRUE;
2291 else
2292 /* try to attack; note that it might evade */
2293 /* also, we don't attack tame when _safepet_ */
2295 if(attack(mtmp)) return;
2297 if (tech_inuse(T_EDDY_WIND) && flags.forcefight) {
2298 if(attack(mtmp)) return;
2300 if (u.swappositioncount && flags.forcefight) {
2301 if(attack(mtmp)) return;
2303 if (uwep && uwep->oartifact == ART_DIZZY_METAL_STORM && flags.forcefight) {
2304 if(attack(mtmp)) return;
2309 /* fucked up bug where we can reach here even when engulfed and waste a turn... --Amy
2310 * This could crash the game if the player is punished, which we'll prevent by just aborting the player's move */
2311 if(u.uswallow) {
2312 pline("Caution: You seem to have encountered the bug where moving into an engulfer wastes a turn. In order to attack the monster, prefix your movement with F (shift-f), please. Sorry for the inconvenience. --Amy");
2313 return;
2316 /* Amy feature: safety question when displacing pets into liquids, impossible to do it to non-pets (too cheesy) */
2317 if (mtmp && (displacer || peacedisplacer || mtmp->mtame)) {
2318 boolean inpool, inlava;
2320 inpool = (is_waterypool(u.ux, u.uy) || is_watertunnel(u.ux, u.uy)) && !is_flyer(mtmp->data) && !(is_urinelake(u.ux, u.uy)) && !(is_moorland(u.ux, u.uy)) && !(is_crystalwater(u.ux, u.uy)) && (!mtmp->egotype_flying) && !is_floater(mtmp->data);
2321 inlava = is_lava(u.ux, u.uy) && !is_flyer(mtmp->data) && (!mtmp->egotype_flying) && !is_floater(mtmp->data);
2323 if (inpool || inlava) canexistonsquare = FALSE;
2326 if (!canexistonsquare) {
2327 if (mtmp && !mtmp->mtame) {
2328 You("cannot displace that monster into a harmful liquid!");
2329 return;
2330 } else if (mtmp && mtmp->mtame) {
2331 if (!(ParanoiaBugEffect || u.uprops[PARANOIA_BUG].extrinsic || have_paranoiastone())) {
2332 if (yn("Really displace the pet into a harmful liquid?") != 'y') {
2333 return;
2339 /* specifying 'F' with no monster wastes a turn */
2340 if (flags.forcefight ||
2341 /* remembered an 'I' && didn't use a move command */
2342 (memory_is_invisible(x, y) && !flags.nopick)) {
2343 boolean expl = (Upolyd && attacktype(youmonst.data, AT_EXPL));
2344 char buf[BUFSZ];
2345 sprintf(buf,"a vacant spot on the %s", surface(x,y));
2346 You("%s %s.",
2347 expl ? "explode at" : "attack",
2348 !Underwater ? "thin air" :
2349 is_waterypool(x,y) ? "empty water" : buf);
2350 unmap_object(x, y); /* known empty -- remove 'I' if present */
2351 newsym(x, y);
2352 forcenomul(0, 0);
2353 if (expl) {
2354 if (!Race_if(PM_UNGENOMOLD)) {
2355 u.mh = -1; /* dead in the current form */
2356 rehumanize();
2357 } else polyself(FALSE);
2359 return;
2361 if (memory_is_invisible(x, y)) {
2362 unmap_object(x, y);
2363 newsym(x, y);
2365 /* not attacking an animal, so we try to move */
2366 if (!displacer) {
2368 if (peacedisplacer) goto peacedisplace;
2370 if (u.usteed && !u.usteed->mcanmove && (u.dx || u.dy)) {
2371 pline("%s won't move!", upstart(y_monnam(u.usteed)));
2372 forcenomul(0, 0);
2373 return;
2374 } else
2375 if( is_nonmoving(youmonst.data) && !Race_if(PM_MISSINGNO) && !(uactivesymbiosis && Upolyd && (u.umonnum == u.usymbiote.mnum)) ) {
2376 /* This catches the moveamt code in hack.c, preventing you from moving as a red mold
2377 * even if you do get some movement points. It's mainly meant to prevent you from being unable to do anything
2378 * until you get knocked out of red mold form, so you can at least sit around and maybe throw some daggers. --Amy */
2379 You("are rooted %s.",
2380 Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
2381 "in place" : "to the ground");
2382 forcenomul(0, 0);
2383 return;
2386 if (trap = t_at(u.ux, u.uy)) {
2387 if (trap->ttyp == VIVISECTION_TRAP) {
2388 if (rn2(4)) {
2389 You("fail to escape the vivisection trap.");
2390 return;
2395 if (StrongInvertedState && rn2(2)) {
2396 You("fail to move in your inverted state!");
2397 return;
2400 if(u.utrap) {
2401 if(u.utraptype == TT_PIT) {
2402 if (!rn2(2) && sobj_at(BOULDER, u.ux, u.uy)) {
2403 Your("%s gets stuck in a crevice.", body_part(LEG));
2404 display_nhwindow(WIN_MESSAGE, FALSE);
2405 clear_nhwindow(WIN_MESSAGE);
2406 You("free your %s.", body_part(LEG));
2407 } else if (Flying && !In_sokoban(&u.uz)) {
2408 /* eg fell in pit, poly'd to a flying monster */
2409 You("fly from the pit.");
2410 u.utrap = 0;
2411 fill_pit(u.ux, u.uy);
2412 vision_full_recalc = 1; /* vision limits change */
2413 } else if (!(--u.utrap)) {
2414 You("%s to the edge of the pit.",
2415 (In_sokoban(&u.uz) && Levitation) ?
2416 "struggle against the air currents and float" :
2417 u.usteed ? "ride" : "crawl");
2418 fill_pit(u.ux, u.uy);
2419 vision_full_recalc = 1; /* vision limits change */
2420 } else if (flags.verbose) {
2421 if (u.usteed)
2422 Norep("%s is still in a pit.",
2423 upstart(y_monnam(u.usteed)));
2424 else
2425 Norep( (FunnyHallu && !rn2(5)) ?
2426 "You've fallen, and you can't get up." :
2427 "You are still in a pit." );
2430 if (FemtrapActiveNatalje) {
2431 u.nataljetrapturns = moves;
2432 u.nataljetrapx = u.ux;
2433 u.nataljetrapy = u.uy;
2436 traphere = t_at(u.ux,u.uy);
2437 if (u.utrap && traphere && traphere->ttyp == SHIT_PIT) {
2438 pline("You splotch into a heap of dog shit!");
2439 int num = 0;
2440 num = d(2, 2) + rnd((monster_difficulty() / 3) + 1);
2441 if (Acid_resistance) { /* let's just assume the stuff is acidic or corrosive --Amy */
2442 shieldeff(u.ux, u.uy);
2443 num = d(1, 2) + rnd((monster_difficulty() / 7) + 1);
2445 if (Stoned) fix_petrification();
2447 if (!rn2(10) || !(uarmf && itemhasappearance(uarmf, APP_PROFILED_BOOTS) ) ) {
2449 if (uarmf && !rn2(5)) (void)rust_dmg(uarmf, xname(uarmf), 0, TRUE, &youmonst);
2450 if (uarmf && !rn2(5)) (void)rust_dmg(uarmf, xname(uarmf), 1, TRUE, &youmonst);
2451 if (uarmf && !rn2(5)) (void)rust_dmg(uarmf, xname(uarmf), 2, TRUE, &youmonst);
2452 if (uarmf && !rn2(5)) (void)rust_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst);
2453 /* Dog shit is extremely aggressive to footwear. Let's give it a chance to do withering damage. --Amy */
2454 if (uarmf && !rn2(25)) (void)wither_dmg(uarmf, xname(uarmf), 0, TRUE, &youmonst);
2455 if (uarmf && !rn2(25)) (void)wither_dmg(uarmf, xname(uarmf), 1, TRUE, &youmonst);
2456 if (uarmf && !rn2(25)) (void)wither_dmg(uarmf, xname(uarmf), 2, TRUE, &youmonst);
2457 if (uarmf && !rn2(25)) (void)wither_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst);
2461 if (!uarmf) {
2462 pline("You slip on the shit with your bare %s.", makeplural(body_part(FOOT)));
2463 num *= 2;
2466 if (uarmf ? !rn2(20) : !rn2(15)) {
2467 HFumbling = FROMOUTSIDE | rnd(5);
2468 incr_itimeout(&HFumbling, rnd(2));
2469 u.fumbleduration += rnz(uarmf ? 30 : 20);
2473 if (uarmf && itemhasappearance(uarmf, APP_PROFILED_BOOTS) ) {
2474 if (!(HFast & INTRINSIC)) {
2475 if (!Fast)
2476 You("speed up.");
2477 else
2478 Your("quickness feels more natural.");
2479 exercise(A_DEX, TRUE);
2481 HFast |= FROMOUTSIDE;
2483 } else if (!rn2(20)) u_slow_down();
2485 if ( !rn2(StrongFree_action ? 1000 : 100) || (!Free_action && !rn2(10))) {
2486 You("inhale the intense smell of shit! The world spins and goes dark.");
2487 nomovemsg = "You are conscious again."; /* default: "you can move again" */
2488 if (isstunfish) nomul(-rnz(10), "unconscious from smelling dog shit", TRUE);
2489 else nomul(-rnd(10), "unconscious from smelling dog shit", TRUE);
2490 exercise(A_DEX, FALSE);
2493 if (uarmf && itemhasappearance(uarmf, APP_PROFILED_BOOTS) ) num /= 4;
2494 if (num) losehp(num, "heap of shit", KILLED_BY_AN);
2498 if (u.utrap && traphere && traphere->ttyp == MANA_PIT) {
2499 drain_en(rnz(monster_difficulty() + 1));
2502 } else if (u.utraptype == TT_LAVA) { /* WHO THE HELL MADE THIS INTO A NOREP GAAAAAAH --Amy */
2504 if (FemtrapActiveNatalje) {
2505 u.nataljetrapturns = moves;
2506 u.nataljetrapx = u.ux;
2507 u.nataljetrapy = u.uy;
2510 if(flags.verbose) {
2511 predicament = "stuck in the lava";
2512 if (u.usteed)
2513 pline("%s is %s.", upstart(y_monnam(u.usteed)),
2514 predicament);
2515 else
2516 pline("You are %s.", predicament);
2518 if(!is_lava(x,y)) {
2519 u.utrap--;
2520 if((u.utrap & 0xff) == 0) {
2521 if (u.usteed)
2522 You("lead %s to the edge of the lava.",
2523 y_monnam(u.usteed));
2524 else
2525 You("pull yourself to the edge of the lava.");
2526 u.utrap = 0;
2529 u.umoved = TRUE;
2530 } else if (u.utraptype == TT_WEB) {
2531 if(uwep && uwep->oartifact == ART_STING) {
2532 u.utrap = 0;
2533 pline("Sting cuts through the web!");
2534 return;
2537 if (FemtrapActiveNatalje) {
2538 u.nataljetrapturns = moves;
2539 u.nataljetrapx = u.ux;
2540 u.nataljetrapy = u.uy;
2543 if(--u.utrap) {
2544 if(flags.verbose) {
2545 predicament = "stuck to the web";
2546 if (u.usteed)
2547 Norep("%s is %s.", upstart(y_monnam(u.usteed)),
2548 predicament);
2549 else
2550 Norep("You are %s.", predicament);
2552 } else {
2553 if (u.usteed)
2554 pline("%s breaks out of the web.",
2555 upstart(y_monnam(u.usteed)));
2556 else
2557 You("disentangle yourself.");
2559 } else if (u.utraptype == TT_GLUE) {
2561 if (FemtrapActiveNatalje) {
2562 u.nataljetrapturns = moves;
2563 u.nataljetrapx = u.ux;
2564 u.nataljetrapy = u.uy;
2567 if(--u.utrap) {
2568 if(flags.verbose) {
2569 predicament = "held in place by the glue";
2570 if (u.usteed)
2571 Norep("%s is %s.", upstart(y_monnam(u.usteed)),
2572 predicament);
2573 else
2574 Norep("You are %s.", predicament);
2576 } else {
2577 if (u.usteed)
2578 pline("%s breaks out of the glue.",
2579 upstart(y_monnam(u.usteed)));
2580 else
2581 You("finally get the sticky glue off.");
2583 } else if (u.utraptype == TT_INFLOOR) {
2585 if (FemtrapActiveNatalje) {
2586 u.nataljetrapturns = moves;
2587 u.nataljetrapx = u.ux;
2588 u.nataljetrapy = u.uy;
2591 if(--u.utrap) {
2592 if(flags.verbose) {
2593 predicament = "stuck in the";
2594 if (u.usteed)
2595 Norep("%s is %s %s.",
2596 upstart(y_monnam(u.usteed)),
2597 predicament, surface(u.ux, u.uy));
2598 else
2599 Norep("You are %s %s.", predicament,
2600 surface(u.ux, u.uy));
2602 } else {
2603 if (u.usteed)
2604 pline("%s finally wiggles free.",
2605 upstart(y_monnam(u.usteed)));
2606 else
2607 You("finally wiggle free.");
2609 } else {
2611 if (FemtrapActiveNatalje) {
2612 u.nataljetrapturns = moves;
2613 u.nataljetrapx = u.ux;
2614 u.nataljetrapy = u.uy;
2617 if(flags.verbose) {
2618 predicament = "caught in a bear trap";
2619 if (u.usteed)
2620 Norep("%s is %s.", upstart(y_monnam(u.usteed)),
2621 predicament);
2622 else
2623 Norep("You are %s.", predicament);
2625 if((u.dx && u.dy) || !rn2(5)) {
2626 u.utrap--;
2627 if (u.utrap == 0) pline("You pull free from the trap.");
2628 else pline("You try to get out of the trap.");}
2630 return;
2633 if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, DO_MOVE)) {
2634 if (!door_opened) {
2635 flags.move = 0;
2636 forcenomul(0, 0);
2637 } else {
2638 door_opened = 0;
2640 return;
2643 if (t_at(x,y)) {
2645 traphere = t_at(x,y);
2646 if (traphere && traphere->ttyp == NUPESELL_TRAP) {
2647 flags.move = 0;
2648 forcenomul(0, 0);
2649 return;
2654 peacedisplace:
2656 /* warn player before walking into known traps */
2657 if (ask_about_trap(x, y)) {
2658 char qbuf[BUFSZ];
2659 trap = t_at(x, y);
2660 sprintf(qbuf,"Do you really want to %s into that %s?",
2661 locomotion(youmonst.data, "step"),
2662 Hallucination ? "trap" : defsyms[trap_to_defsym(trap->ttyp)].explanation);
2663 if (yn(qbuf) != 'y') {
2664 forcenomul(0, 0);
2665 flags.move = 0;
2666 return;
2670 if (ask_about_water(x, y)) {
2672 if (Role_if(PM_TOPMODEL) && Is_qlocate(&u.uz) ) {
2673 if (yn("There is a strong wind above the water. It seems dangerous. Really step there?") != 'y') {
2674 forcenomul(0, 0);
2675 flags.move = 0;
2676 return;
2679 if (Role_if(PM_FAILED_EXISTENCE) && Is_qlocate(&u.uz) ) {
2680 if (yn("There is a strong wind above the water. It seems dangerous. Really step there?") != 'y') {
2681 forcenomul(0, 0);
2682 flags.move = 0;
2683 return;
2687 else {
2688 if (yn("This is a water tile that can cause you to drown. Really step on it?") != 'y') {
2689 forcenomul(0, 0);
2690 flags.move = 0;
2691 return;
2697 if (ask_about_lava(x, y)) {
2699 if (yn("This is a lava tile that can burn you to a crisp. Really step on it?") != 'y') {
2700 forcenomul(0, 0);
2701 flags.move = 0;
2702 return;
2704 char bufX[BUFSZ];
2705 getlin ("Are you really sure [yes/no]?",bufX);
2706 if (strcmp (bufX, "yes")) {
2707 forcenomul(0, 0);
2708 flags.move = 0;
2709 return;
2713 if (ask_about_watertunnel(x, y)) {
2715 if (yn("This is a water tunnel that can cause you to drown. Really dive into it?") != 'y') {
2716 forcenomul(0, 0);
2717 flags.move = 0;
2718 return;
2722 if (ask_about_crystalwater(x, y)) {
2724 if (yn("This is a crystal water tile that can cause you to drown. Really fly into it?") != 'y') {
2725 forcenomul(0, 0);
2726 flags.move = 0;
2727 return;
2731 if (ask_about_moorland(x, y)) {
2733 if (yn("This is moorland; swimming in it will continuously hurt you. Really do it?") != 'y') {
2734 forcenomul(0, 0);
2735 flags.move = 0;
2736 return;
2740 if (ask_about_urinelake(x, y)) {
2742 if (yn("This is a urine lake, which can be detrimental to swim in. Really do it?") != 'y') {
2743 forcenomul(0, 0);
2744 flags.move = 0;
2745 return;
2749 if (ask_about_shiftingsand(x, y)) {
2751 if (yn("This is a shifting sand tile, which will quickly kill you by suffocation. Really step on it?") != 'y') {
2752 forcenomul(0, 0);
2753 flags.move = 0;
2754 return;
2756 char bufX[BUFSZ];
2757 getlin ("Are you really sure [yes/no]?",bufX);
2758 if (strcmp (bufX, "yes")) {
2759 forcenomul(0, 0);
2760 flags.move = 0;
2761 return;
2765 if (ask_about_styxriver(x, y)) {
2767 if (yn("This is a styx river, which will continuously contaminate you. Really step on it?") != 'y') {
2768 forcenomul(0, 0);
2769 flags.move = 0;
2770 return;
2774 if (ask_about_burningwagon(x, y)) {
2776 if (yn("This is a burning wagon, which will burn you. Really step on it?") != 'y') {
2777 forcenomul(0, 0);
2778 flags.move = 0;
2779 return;
2783 if (ask_about_nethermist(x, y)) {
2785 if (yn("This is a nether mist tile, which can drain your experience. Really step on it?") != 'y') {
2786 forcenomul(0, 0);
2787 flags.move = 0;
2788 return;
2792 if (ask_about_stalactite(x, y)) {
2794 if (yn("This is a stalactite, which will hurt you if you fly into it. Really do it?") != 'y') {
2795 forcenomul(0, 0);
2796 flags.move = 0;
2797 return;
2801 if (ask_about_raincloud(x, y)) {
2803 if (yn("This is a rain cloud, which will make you and your entire inventory wet. Really step into it?") != 'y') {
2804 forcenomul(0, 0);
2805 flags.move = 0;
2806 return;
2810 if (ask_about_bubble(x, y)) {
2812 if (yn("This is a bubble, which causes stunning. Really step into it?") != 'y') {
2813 forcenomul(0, 0);
2814 flags.move = 0;
2815 return;
2819 } else if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, TEST_MOVE)) {
2821 * If a monster attempted to displace us but failed
2822 * then we are entitled to our normal attack.
2824 if (!attack(mtmp)) {
2825 flags.move = 0;
2826 forcenomul(0, 0);
2828 return;
2831 /* Move ball and chain. */
2832 if (Punished)
2833 if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy,
2834 &cause_delay, TRUE))
2835 return;
2837 /* Check regions entering/leaving */
2838 if (!in_out_region(x,y)) {
2839 #if 0
2840 /* [ALI] This can't happen at present, but if it did we would
2841 * also need to worry about the call to drag_ball above.
2843 if (displacer) (void)attack(mtmp);
2844 #endif
2845 return;
2848 /* now move the hero */
2849 mtmp = m_at(x, y);
2851 u.ux += u.dx;
2852 u.uy += u.dy;
2854 if (TronEffect || u.uprops[TRON_EFFECT].extrinsic || have_tronstone() || (uarmh && itemhasappearance(uarmh, APP_HARDCORE_CLOTH)) || Race_if(PM_SLYER_ALIEN) ) {
2855 if (u.dx == 1 && !u.dy) u.trontrapdirection = 1; /* east */
2856 else if (u.dx == 1 && u.dy == 1) u.trontrapdirection = 2; /* southeast */
2857 else if (!u.dx && u.dy == -1) u.trontrapdirection = 3; /* north */
2858 else if (u.dx == -1 && u.dy == -1) u.trontrapdirection = 4; /* northwest */
2859 else if (u.dx == -1 && !u.dy) u.trontrapdirection = 5; /* west */
2860 else if (u.dx == -1 && u.dy == 1) u.trontrapdirection = 6; /* southwest */
2861 else if (!u.dx && u.dy == 1) u.trontrapdirection = 7; /* south */
2862 else if (u.dx == 1 && u.dy == -1) u.trontrapdirection = 8; /* northeast */
2863 else u.trontrapdirection = -1;
2865 u.trontrapturn = moves;
2869 /* Move your steed, too */
2870 if (u.usteed) {
2871 u.usteed->mx = u.ux;
2872 u.usteed->my = u.uy;
2873 exercise_steed();
2876 /* exercising high heel skill takes a while... */
2877 if (PlayerInHighHeels && (u.uhighheelturns++ >= 50)) {
2878 u.uhighheelturns = 0;
2879 use_skill(P_HIGH_HEELS, 1);
2882 if (PlayerInColumnarHeels) {
2884 /* an odd one: male characters can train it faster, lacking the high heels skill makes it slower, and if
2885 * you're female without the high heels skill you cannot train it at all --Amy */
2887 int columnarneeded = 150;
2888 boolean cancolumnar = TRUE;
2889 if (flags.female) columnarneeded = 500;
2891 if (P_MAX_SKILL(P_HIGH_HEELS) == P_ISRESTRICTED) {
2892 if (flags.female) cancolumnar = FALSE;
2893 else columnarneeded = 500;
2896 u.columnarturns++;
2897 if (cancolumnar && (u.columnarturns >= columnarneeded)) {
2898 u.columnarturns = 0;
2899 u.columnarskill++;
2900 if (u.columnarskill == 20) You("are now more skilled in type 5: columnar heels.");
2901 if (u.columnarskill == 160) You("are now more skilled in type 5: columnar heels.");
2902 if (u.columnarskill == 540) You("are now more skilled in type 5: columnar heels.");
2903 if (u.columnarskill == 1280) You("are now more skilled in type 5: columnar heels.");
2904 if (u.columnarskill == 2500) You("are now more skilled in type 5: columnar heels.");
2905 if (u.columnarskill == 4320) You("are now most skilled in type 5: columnar heels.");
2909 if (PlayerInStilettoHeels) {
2910 u.ustilettoheelturns++;
2911 if (u.ustilettoheelturns >= ((flags.female || Role_if(PM_TRANSVESTITE) || Role_if(PM_TRANSSYLVANIAN)) ? 350 : 2500) ) {
2912 u.ustilettoheelturns = 0;
2913 use_skill(P_STILETTO_HEELS, 1);
2917 if (PlayerInConeHeels) {
2918 u.uconeheelturns++;
2919 if (u.uconeheelturns >= ((flags.female || Role_if(PM_TRANSVESTITE) || Role_if(PM_TRANSSYLVANIAN)) ? 200 : 500) ) {
2920 u.uconeheelturns = 0;
2921 use_skill(P_CONE_HEELS, 1);
2925 if (PlayerInBlockHeels) {
2926 u.ublockheelturns++;
2927 if (u.ublockheelturns >= 250) {
2928 u.ublockheelturns = 0;
2929 use_skill(P_BLOCK_HEELS, 1);
2933 if (PlayerInWedgeHeels) {
2934 u.uwedgeheelturns++;
2935 if (u.uwedgeheelturns >= 200) {
2936 u.uwedgeheelturns = 0;
2937 use_skill(P_WEDGE_HEELS, 1);
2941 /* exercising sexy flats does too, especially if you're male */
2942 if (PlayerInSexyFlats && (flags.female || !rn2(5)) && (u.usexyflatturns++ >= 50)) {
2943 u.usexyflatturns = 0;
2944 use_skill(P_SEXY_FLATS, 1);
2947 if (displacer || peacedisplacer) {
2948 char pnambuf[BUFSZ];
2950 u.utrap = 0; /* A lucky escape */
2951 /* save its current description in case of polymorph */
2952 strcpy(pnambuf, mon_nam(mtmp));
2954 if (mtmp->data == &mons[PM_KURIKKUSHITEKUDASAI__ANATA_NO_OKANE_WANAKU_NATTE_IMASU]) {
2955 if (u.ugold > 9) {
2956 u.ugold /= 10;
2957 u.ugold *= 9;
2958 pline("Ops, sorry."); /* sic from Elona */
2962 remove_monster(x, y);
2963 place_monster(mtmp, u.ux0, u.uy0);
2965 if (u.swappositioncount) u.swappositioncount = 0;
2967 /* check for displacing it into pools and traps */
2968 switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
2969 case 0:
2970 if (tech_inuse(T_EDDY_WIND)) You("whirl past %s.", pnambuf);
2971 else You("displaced %s.", pnambuf);
2972 break;
2973 case 1:
2974 case 3:
2975 break;
2976 case 2:
2977 u.uconduct.killer++;
2978 break;
2983 * if safepet at destination then move the pet to the hero's
2984 * previous location using the same conditions as in attack().
2985 * there are special extenuating circumstances:
2986 * (1) if the pet dies then your god angers,
2987 * (2) if the pet gets trapped then your god may disapprove,
2988 * (3) if the pet was already trapped and you attempt to free it
2989 * not only do you encounter the trap but you may frighten your
2990 * pet causing it to go wild! moral: don't abuse this privilege.
2992 * Ceiling-hiding pets are skipped by this section of code, to
2993 * be caught by the normal falling-monster code.
2994 * Amy addition: displacement already allows you to displace monsters; don't call the displacing code twice
2996 if (is_safepet(mtmp) && !Displaced && !( (is_hider(mtmp->data) || mtmp->egotype_hide || mtmp->egotype_mimic) && mtmp->mundetected)) {
2997 /* if trapped, there's a chance the pet goes wild */
2998 if (mtmp->mtrapped) {
2999 if (!rn2(mtmp->mtame) && !((rnd(30 - ACURR(A_CHA))) < 4) ) {
3000 mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
3001 if (mtmp->mleashed) m_unleash(mtmp, TRUE);
3002 growl(mtmp);
3003 } else {
3004 yelp(mtmp);
3007 mtmp->mundetected = 0;
3008 if (mtmp->m_ap_type) seemimic(mtmp);
3009 else if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my);
3011 if (mtmp->mtrapped &&
3012 (trap = t_at(mtmp->mx, mtmp->my)) != 0 &&
3013 (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT || trap->ttyp == GIANT_CHASM || trap->ttyp == SHIT_PIT || trap->ttyp == MANA_PIT || trap->ttyp == ANOXIC_PIT || trap->ttyp == HYPOXIC_PIT || trap->ttyp == ACID_PIT) &&
3014 sobj_at(BOULDER, trap->tx, trap->ty)) {
3015 /* can't swap places with pet pinned in a pit by a boulder */
3016 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
3017 } else if (u.ux0 != x && u.uy0 != y &&
3018 bad_rock(mtmp, x, u.uy0) &&
3019 bad_rock(mtmp, u.ux0, y) &&
3020 (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 5000))) {
3021 /* can't swap places when pet won't fit thru the opening */
3022 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
3023 You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
3024 } else {
3025 char pnambuf[BUFSZ];
3027 /* save its current description in case of polymorph */
3028 strcpy(pnambuf, y_monnam(mtmp));
3029 mtmp->mtrapped = 0;
3030 remove_monster(x, y);
3031 place_monster(mtmp, u.ux0, u.uy0);
3033 /* check for displacing it into pools and traps */
3034 switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
3035 case 0:
3036 You("%s %s.", mtmp->mtame ? "displaced" : "frightened",
3037 pnambuf);
3038 break;
3039 case 1: /* trapped */
3040 case 3: /* changed levels */
3041 /* there's already been a trap message, reinforce it */
3042 abuse_dog(mtmp);
3043 adjalign(-10);
3044 break;
3045 case 2:
3046 /* it may have drowned or died. that's no way to
3047 * treat a pet! your god gets angry.
3049 if (rn2(4)) {
3050 You_feel("guilty about losing your pet like this.");
3051 u.ugangr++;
3052 adjalign(-50);
3055 /* you killed your pet by direct action.
3056 * minliquid and mintrap don't know to do this
3058 u.uconduct.killer++;
3059 break;
3060 default:
3061 pline("that's strange, unknown mintrap result!");
3062 break;
3067 reset_occupations();
3068 if (flags.run) {
3069 if ( flags.run < 8 )
3070 if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) ||
3071 IS_FURNITURE(tmpr->typ))
3072 forcenomul(0, 0);
3075 if (hides_under(youmonst.data) || (uarmh && itemhasappearance(uarmh, APP_SECRET_HELMET) ) || (!night() && uarmg && uarmg->oartifact == ART_NIGHTLY_HIGHWAY) || (uarmc && uarmc->oartifact == ART_JANA_S_EXTREME_HIDE_AND_SE) )
3076 u.uundetected = OBJ_AT(u.ux, u.uy);
3077 else if (youmonst.data->mlet == S_EEL)
3078 u.uundetected = is_waterypool(u.ux, u.uy) && !Is_waterlevel(&u.uz);
3079 else if (is_wagon(u.ux, u.uy))
3080 u.uundetected = TRUE;
3081 else if (u.dx || u.dy)
3082 u.uundetected = 0;
3085 * Mimics (or whatever) become noticeable if they move and are
3086 * imitating something that doesn't move. We could extend this
3087 * to non-moving monsters...
3089 if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
3090 || youmonst.m_ap_type == M_AP_FURNITURE))
3091 youmonst.m_ap_type = M_AP_NOTHING;
3093 check_leash(u.ux0,u.uy0);
3095 if(u.ux0 != u.ux || u.uy0 != u.uy) {
3096 u.umoved = TRUE;
3098 /* Clean old position -- vision_recalc() will print our new one. */
3099 newsym(u.ux0,u.uy0);
3100 /* Since the hero has moved, adjust what can be seen/unseen. */
3101 vision_recalc(1); /* Do the work now in the recover time. */
3102 invocation_message();
3105 if (Punished) /* put back ball and chain */
3106 move_bc(0,bc_control,ballx,bally,chainx,chainy);
3108 spoteffects(TRUE);
3110 /* delay next move because of ball dragging */
3111 /* must come after we finished picking up, in spoteffects() */
3112 if (cause_delay) {
3113 nomul(-2, "dragging an iron ball", TRUE);
3114 nomovemsg = "";
3117 if (flags.run && iflags.runmode != RUN_TPORT) {
3118 /* display every step or every 7th step depending upon mode */
3119 if (iflags.runmode != RUN_LEAP || !(moves % 7L)) {
3120 if (flags.time) flags.botl = 1;
3121 curs_on_u();
3122 delay_output();
3123 if (iflags.runmode == RUN_CRAWL) {
3124 delay_output();
3125 delay_output();
3126 delay_output();
3127 delay_output();
3133 void
3134 invocation_message()
3136 /* a special clue-msg when on the Invocation position */
3137 if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
3138 char buf[BUFSZ];
3139 struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
3141 nomul(0, 0, FALSE); /* stop running or travelling */
3142 if (FunnyHallu) {
3143 pline("You're picking up good vibrations!");
3144 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3145 } else {
3146 if (u.usteed) sprintf(buf, "beneath %s", y_monnam(u.usteed));
3147 else
3148 if (Levitation || Flying) strcpy(buf, "beneath you");
3149 else sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
3151 You_feel("a strange vibration %s.", buf);
3152 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3154 if (otmp && otmp->spe == 7 && otmp->lamplit)
3155 pline("%s %s!", The(xname(otmp)),
3156 Blind ? "throbs palpably" : "glows with a strange light");
3158 litroomlite(TRUE);
3160 if (!u.vibratingsquarefind) {
3161 u.vibratingsquarefind = 1;
3162 qt_pager(QT_VIBRATINGSQUARE);
3168 /* Wounds patch gotten from 5lo's SLEX mod --Amy */
3170 static const char * const hallu_adverb[] = { /* 5lo: Wounds patch by L */
3171 "mildly", "mostly", "somewhat", "slightly", "probably", "massively", "extremely",
3172 "flagrantly", "flamboyantly", "supremely", "excessively", "truly", "terribly",
3173 "not at all", "barely", "heavily", "critically", "normally", "nonchalantly", "strangely",
3174 "fleecily", "painfully", "hurtingly", "almost", "nearly", "now", "no longer",
3175 "apparently", "frighteningly", "totally", "awfully", "with difficulty", "secretly",
3176 "immediately", "fatally", "magically", "dreadfully", "superficially", "openly",
3177 "sharply", "in some way", "maybe", "seemingly", "really", "not really", "unremarkably",
3178 "happily", "randomly", "stupidly", "intelligently", "strongly", "weakly", "wisely",
3179 "always", "never", "more", "less", "certainly", "irredeemably", "questionably",
3180 "perhaps", "confused and", "stunned and", "dead or", "hallucinating but not", "more or less",
3181 "incredibly", "unbelievably", "obscenely", "insanely", "amazingly", "absolutely"
3184 void
3185 wounds_message(mon)
3186 struct monst *mon;
3188 if (mon_wounds(mon))
3189 pline("%s is %s.", Monnam(mon), mon_wounds(mon));
3192 char *
3193 mon_wounds(mon)
3194 struct monst *mon;
3196 static char buf[BUFSZ];
3197 boolean wounded = ((!nonliving(mon->data) ||
3198 /* Zombies and mummies (but not skeletons) have flesh */
3199 ((mon->data->mlet == S_ZOMBIE && mon->data != &mons[PM_SKELETON])
3200 || mon->data->mlet == S_MUMMY || mon->data->mlet == S_VAMPIRE
3201 || mon->data == &mons[PM_FLESH_GOLEM]))
3202 && !vegetarian(mon->data)); /* :TODO?: Check and see if some Extended monsters fit the above */
3204 /* Able to detect wounds? */
3205 if (!(canseemon(mon) || (u.ustuck == mon && u.uswallow && !Blind))
3206 || (!Race_if(PM_HERBALIST) && !Role_if(PM_HEALER) && !Role_if(PM_SCIENTIST) && !Role_if(PM_EMPATH) && !Race_if(PM_ALCHEMIST) && !Role_if(PM_NECROMANCER) && !Role_if(PM_UNDERTAKER) && (mon->data->msound != MS_PAIN) ) )
3207 /* 5lo: Expanded for more roles */
3208 return (char *)0;
3209 if (mon->mhp == mon->mhpmax || mon->mhp < 1)
3210 return (char *)0;
3211 if (!Hallucination && mon->mhp <= mon->mhpmax / 6) {
3212 sprintf(buf,"almost ");
3213 strcat(buf, nonliving(mon->data) ? "destroyed" : "dead");
3214 } else {
3215 if (Hallucination) {
3216 sprintf(buf, "%s", hallu_adverb[rn2(SIZE(hallu_adverb))]);
3217 strcat(buf," ");
3219 else if (mon->mhp <= mon->mhpmax / 4)
3220 sprintf(buf,"horribly ");
3221 else if (mon->mhp <= mon->mhpmax / 3)
3222 sprintf(buf,"heavily ");
3223 else if (mon->mhp <= 3 * mon->mhpmax / 4)
3224 sprintf(buf,"moderately ");
3225 else
3226 sprintf(buf,"lightly ");
3227 strcat(buf, wounded || (Hallucination && rn2(2)) ? "wounded" : "damaged");
3229 return buf;
3233 #endif /* OVL3 */
3234 #ifdef OVL2
3236 void
3237 spoteffects(pick)
3238 boolean pick;
3240 register struct monst *mtmp;
3242 if (is_pool(u.ux, u.uy) && (Role_if(PM_TOPMODEL) || Role_if(PM_FAILED_EXISTENCE)) && Is_qlocate(&u.uz) ) {
3244 /* strong winds over the Grand Canyon. Please don't ask me how they can continue working underwater. :-) --Amy */
3246 pline(FunnyHallu ? "This whirl is like the eye of a hurricane, but it tickles!" : "There are scathing winds here! Your skin is scraped off!");
3247 losehp(rnz(u.legscratching), "scathing winds", KILLED_BY);
3249 You("tumble...");
3250 make_stunned(HStun + rnz(u.legscratching), FALSE);
3252 u.legscratching++;
3255 if (t_at(u.ux, u.uy) && (Role_if(PM_TOPMODEL) || Role_if(PM_FAILED_EXISTENCE)) && Is_qlocate(&u.uz) ) {
3257 /* every trap on the Grand Canyon level also has a lesser wind effect. --Amy */
3259 pline(FunnyHallu ? "A twister... or is that a tornado?" : "You are enclosed in a whirlwind!");
3260 losehp(rnd(u.legscratching + 2), "whirlwinds", KILLED_BY);
3264 if (is_crystalwater(u.ux,u.uy) && (Flying || Levitation)) {
3265 crystaldrown();
3268 if(u.uinwater) {
3269 int was_underwater;
3271 if (!is_drowningpool(u.ux,u.uy)) {
3272 if (Is_waterlevel(&u.uz))
3273 You("pop into an air bubble.");
3274 else if (is_lava(u.ux, u.uy))
3275 You("leave the water..."); /* oops! */
3276 else
3277 You("are on solid %s again.",
3278 is_ice(u.ux, u.uy) ? "ice" : "land");
3280 else if (Is_waterlevel(&u.uz))
3281 goto stillinwater;
3282 else if (Levitation && !is_crystalwater(u.ux,u.uy))
3283 You("pop out of the water like a cork!");
3284 /* KMH, balance patch -- new intrinsic */
3285 else if (Flying && !is_crystalwater(u.ux,u.uy))
3286 You("fly out of the water.");
3287 else if (uarmc && itemhasappearance(uarmc, APP_FLIER_CLOAK) && !is_crystalwater(u.ux,u.uy))
3288 You("fly out of the water.");
3289 else if (uarmf && uarmf->oartifact == ART_RUBBER_LOVE && !is_crystalwater(u.ux,u.uy))
3290 You("float on top of the water.");
3291 else if ((Wwalking || Race_if(PM_KORONST)) && !is_crystalwater(u.ux,u.uy))
3292 You("slowly rise above the surface.");
3293 /* else if (Swimming)
3294 You("paddle up to the surface.");*/
3295 else
3296 goto stillinwater;
3297 was_underwater = Underwater && !Is_waterlevel(&u.uz);
3298 u.uinwater = 0; /* leave the water */
3299 if (was_underwater) { /* restore vision */
3300 docrt();
3301 vision_full_recalc = 1;
3304 stillinwater:;
3305 if (!Levitation && !u.ustuck && !Flying && !(uarmf && uarmf->oartifact == ART_RUBBER_LOVE) && !(uarmc && itemhasappearance(uarmc, APP_FLIER_CLOAK)) ) {
3306 /* limit recursive calls through teleds() */
3307 if ((is_drowningpool(u.ux, u.uy) && !(is_crystalwater(u.ux,u.uy))) || is_lava(u.ux, u.uy)) {
3308 if (u.usteed && !is_flyer(u.usteed->data) && (!u.usteed->egotype_flying) &&
3309 !is_swimmer(u.usteed->data) &&
3310 !is_floater(u.usteed->data) &&
3311 !is_clinger(u.usteed->data)) {
3312 dismount_steed(Underwater ?
3313 DISMOUNT_FELL : DISMOUNT_GENERIC);
3314 /* dismount_steed() -> float_down() -> pickup() */
3315 if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz))
3316 pick = FALSE;
3317 } else
3318 if (is_lava(u.ux, u.uy)) {
3319 if (lava_effects()) return;
3320 } else if (!Wwalking && !Race_if(PM_KORONST) && drown())
3321 return;
3324 check_special_room(FALSE);
3325 if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
3326 dosinkfall();
3327 if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
3328 struct trap *trap = t_at(u.ux, u.uy);
3329 boolean pit;
3330 pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT || trap->ttyp == GIANT_CHASM || trap->ttyp == SHIT_PIT || trap->ttyp == MANA_PIT || trap->ttyp == ANOXIC_PIT || trap->ttyp == HYPOXIC_PIT || trap->ttyp == ACID_PIT));
3331 if (trap && pit)
3332 dotrap(trap, 0); /* fall into pit */
3333 /* somehow, being engulfed can sometimes result in "you can't take out blablabla" messages when you very
3334 * obviously just wanted to attack the engulfer, but I can't seem to be able to reproduce it... yet it's
3335 * incredibly annoying whenever it happens; I hope this is the correct line of code to change --Amy */
3336 if (pick && !u.uswallow) (void) pickup(1);
3337 if (trap && !pit)
3338 dotrap(trap, 0); /* fall into arrow trap, etc. */
3340 if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
3341 mtmp->mundetected = mtmp->msleeping = 0;
3342 switch(mtmp->data->mlet) {
3343 case S_PIERCER:
3344 pline("%s suddenly drops from the %s!",
3345 Amonnam(mtmp), ceiling(u.ux,u.uy));
3346 if(mtmp->mtame) /* jumps to greet you, not attack */
3348 else if(uarmh && is_hardmaterial(uarmh))
3349 pline("Its blow glances off your helmet.");
3350 else if (u.uac + 3 <= rnd(20) && rn2(3) ) /* ac no longer gives complete protection --Amy */
3351 You("are almost hit by %s!",
3352 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
3353 else {
3354 int dmg;
3355 int molev;
3356 You("are hit by %s!",
3357 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
3358 /* Amy edit: make it depend on the monster's level */
3359 molev = mtmp->data->mlevel;
3360 if (molev > 5) molev -= ((molev - 4) * 2 / 3);
3361 if (molev < 1) molev = 1;
3362 dmg = d(molev,6);
3363 if(Half_physical_damage && (rn2(2) || (uwep && uwep->oartifact == ART_SOOTHE_)) ) dmg = (dmg+1) / 2;
3364 if(StrongHalf_physical_damage && (rn2(2) || (uwep && uwep->oartifact == ART_SOOTHE_)) ) dmg = (dmg+1) / 2;
3365 mdamageu(mtmp, dmg);
3367 break;
3368 default: /* monster surprises you. */
3369 if(mtmp->mtame)
3370 pline("%s jumps near you from the %s.",
3371 Amonnam(mtmp), ceiling(u.ux,u.uy));
3372 else if(mtmp->mpeaceful) {
3373 You("surprise %s!",
3374 Blind && !sensemon(mtmp) ?
3375 something : a_monnam(mtmp));
3376 mtmp->mpeaceful = 0;
3377 } else if (mtmp->data == &mons[PM_DROPCLONK_BEAR] || mtmp->data == &mons[PM_DROPTREE_BEAR] || mtmp->data == &mons[PM_BONKERS_BEAR]) {
3378 int dmg;
3379 You("are hit by %s!",
3380 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
3381 dmg = d(10, 10);
3382 if(Half_physical_damage && (rn2(2) || (uwep && uwep->oartifact == ART_SOOTHE_)) ) dmg = (dmg+1) / 2;
3383 if(StrongHalf_physical_damage && (rn2(2) || (uwep && uwep->oartifact == ART_SOOTHE_)) ) dmg = (dmg+1) / 2;
3384 if (uarmh) dmg = (dmg+1) / 2;
3385 mdamageu(mtmp, dmg);
3387 } else {
3388 pline("%s attacks you by surprise!", Amonnam(mtmp));
3390 break;
3392 mnexto(mtmp); /* have to move the monster */
3396 STATIC_OVL boolean
3397 monstinroom(mdat,roomno)
3398 struct permonst *mdat;
3399 int roomno;
3401 register struct monst *mtmp;
3403 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
3404 if(!DEADMONSTER(mtmp) && mtmp->data == mdat &&
3405 index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
3406 return(TRUE);
3407 return(FALSE);
3410 STATIC_OVL boolean
3411 anymonstinroom(roomno)
3412 int roomno;
3414 register struct monst *mtmp;
3416 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
3417 if(!DEADMONSTER(mtmp) && index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
3418 return(TRUE);
3419 return(FALSE);
3422 char *
3423 in_rooms(x, y, typewanted)
3424 register xchar x, y;
3425 register int typewanted;
3427 static char buf[5];
3428 char rno, *ptr = &buf[4];
3429 int typefound, min_x, min_y, max_x, max_y_offset, step;
3430 register struct rm *lev;
3432 #define goodtype(rno) (!typewanted || \
3433 ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) || \
3434 ((typewanted == SHOPBASE) && (typefound > SHOPBASE))) \
3436 switch (rno = levl[x][y].roomno) {
3437 case NO_ROOM:
3438 return(ptr);
3439 case SHARED:
3440 step = 2;
3441 break;
3442 case SHARED_PLUS:
3443 step = 1;
3444 break;
3445 default: /* i.e. a regular room # */
3446 if (goodtype(rno))
3447 *(--ptr) = rno;
3448 return(ptr);
3451 min_x = x - 1;
3452 max_x = x + 1;
3453 if (x < 1)
3454 min_x += step;
3455 else
3456 if (x >= COLNO)
3457 max_x -= step;
3459 min_y = y - 1;
3460 max_y_offset = 2;
3461 if (min_y < 0) {
3462 min_y += step;
3463 max_y_offset -= step;
3464 } else
3465 if ((min_y + max_y_offset) >= ROWNO)
3466 max_y_offset -= step;
3468 for (x = min_x; x <= max_x; x += step) {
3469 lev = &levl[x][min_y];
3470 y = 0;
3471 if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
3472 !index(ptr, rno) && goodtype(rno))
3473 *(--ptr) = rno;
3474 y += step;
3475 if (y > max_y_offset)
3476 continue;
3477 if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
3478 !index(ptr, rno) && goodtype(rno))
3479 *(--ptr) = rno;
3480 y += step;
3481 if (y > max_y_offset)
3482 continue;
3483 if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
3484 !index(ptr, rno) && goodtype(rno))
3485 *(--ptr) = rno;
3487 return(ptr);
3490 char *
3491 in_roomscolouur(x, y, typewanted)
3492 register xchar x, y;
3493 register int typewanted;
3495 static char buf[5];
3496 char rno, *ptr = &buf[4];
3497 int typefound, min_x, min_y, max_x, max_y_offset, step;
3498 register struct rm *lev;
3500 #define goodtypeX(rno) (!typewanted || \
3501 ((typefound = rooms[rno - ROOMOFFSET].colouur) == typewanted)) \
3503 switch (rno = levl[x][y].roomno) {
3504 case NO_ROOM:
3505 return(ptr);
3506 case SHARED:
3507 step = 2;
3508 break;
3509 case SHARED_PLUS:
3510 step = 1;
3511 break;
3512 default: /* i.e. a regular room # */
3513 if (goodtypeX(rno))
3514 *(--ptr) = rno;
3515 return(ptr);
3518 min_x = x - 1;
3519 max_x = x + 1;
3520 if (x < 1)
3521 min_x += step;
3522 else
3523 if (x >= COLNO)
3524 max_x -= step;
3526 min_y = y - 1;
3527 max_y_offset = 2;
3528 if (min_y < 0) {
3529 min_y += step;
3530 max_y_offset -= step;
3531 } else
3532 if ((min_y + max_y_offset) >= ROWNO)
3533 max_y_offset -= step;
3535 for (x = min_x; x <= max_x; x += step) {
3536 lev = &levl[x][min_y];
3537 y = 0;
3538 if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
3539 !index(ptr, rno) && goodtypeX(rno))
3540 *(--ptr) = rno;
3541 y += step;
3542 if (y > max_y_offset)
3543 continue;
3544 if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
3545 !index(ptr, rno) && goodtypeX(rno))
3546 *(--ptr) = rno;
3547 y += step;
3548 if (y > max_y_offset)
3549 continue;
3550 if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
3551 !index(ptr, rno) && goodtypeX(rno))
3552 *(--ptr) = rno;
3554 return(ptr);
3558 /* is (x,y) in a town? */
3559 boolean
3560 in_town(x, y)
3561 register int x, y;
3563 s_level *slev = Is_special(&u.uz);
3564 register struct mkroom *sroom;
3565 boolean has_subrooms = FALSE;
3567 if (!slev || !slev->flags.town) return FALSE;
3570 * See if (x,y) is in a room with subrooms, if so, assume it's the
3571 * town. If there are no subrooms, the whole level is in town.
3573 for (sroom = &rooms[0]; sroom->hx > 0; sroom++) {
3574 if (sroom->nsubrooms > 0) {
3575 has_subrooms = TRUE;
3576 if (inside_room(sroom, x, y)) return TRUE;
3580 return !has_subrooms;
3583 STATIC_OVL void
3584 move_update(newlev)
3585 register boolean newlev;
3587 char *ptr1, *ptr2, *ptr3, *ptr4;
3589 strcpy(u.urooms0, u.urooms);
3590 strcpy(u.ushops0, u.ushops);
3591 if (newlev) {
3592 u.urooms[0] = '\0';
3593 u.uentered[0] = '\0';
3594 u.ushops[0] = '\0';
3595 u.ushops_entered[0] = '\0';
3596 strcpy(u.ushops_left, u.ushops0);
3597 return;
3599 strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
3601 for (ptr1 = &u.urooms[0],
3602 ptr2 = &u.uentered[0],
3603 ptr3 = &u.ushops[0],
3604 ptr4 = &u.ushops_entered[0];
3605 *ptr1; ptr1++) {
3606 if (!index(u.urooms0, *ptr1))
3607 *(ptr2++) = *ptr1;
3608 if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
3609 *(ptr3++) = *ptr1;
3610 if (!index(u.ushops0, *ptr1))
3611 *(ptr4++) = *ptr1;
3614 *ptr2 = '\0';
3615 *ptr3 = '\0';
3616 *ptr4 = '\0';
3618 /* filter u.ushops0 -> u.ushops_left */
3619 for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
3620 if (!index(u.ushops, *ptr1))
3621 *(ptr2++) = *ptr1;
3622 *ptr2 = '\0';
3625 void
3626 check_special_room(newlev)
3627 register boolean newlev;
3629 register struct monst *mtmp;
3630 char *ptr;
3632 move_update(newlev);
3634 if (*u.ushops0)
3635 u_left_shop(u.ushops_left, newlev);
3637 if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
3638 return; /* no entrance messages necessary */
3640 /* Did we just enter a shop? */
3641 if (*u.ushops_entered)
3642 u_entered_shop(u.ushops_entered);
3644 for (ptr = &u.uentered[0]; *ptr; ptr++) {
3645 register int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
3647 /* Did we just enter some other special room? */
3648 /* vault.c insists that a vault remain a VAULT,
3649 * and temples should remain TEMPLEs,
3650 * but everything else gives a message only the first time */
3651 /* edit by Amy - removed that stupidity. Why the heck would a swamp turn into an ordinary room???
3652 * Besides, I _like_ ambient level messages! They can be anything from soothing to terrifying!
3653 * There's no reason to get rid of them if you enter a room, and it's OK to get a message every time, too. */
3654 switch (rt) {
3656 /* "Special Room monster change. Entering a special room will no longer awaken all monsters inside of the room, making the behavior the same as Vanilla Nethack and Slash'EM. Removed wake_nearby, gets really annoying" In Soviet Russia, players want to be able to mindlessly slaughter all the denizens of special rooms, because they're somehow unable to handle a game posing an actual challenge. They don't view it as too easy if they can hack up one monster after the other without the remaining ones even reacting or doing anything. But of course we all know that this is not the way it's supposed to be, so for all the other races the monsters will wake up. --Amy
3657 * edit: do the wake_nearby only if there are monsters in the room, because they're the reason why we're
3658 * doing it at all: to make sure that you can't simply kill the sleeping monsters. If there's no monsters
3659 * in the room anyway, we have no need to wake up monsters somewhere else on the level! */
3661 case ZOO:
3662 pline(FunnyHallu ? "Welcome to our Theme Park!" : "Welcome to David's treasure zoo!");
3663 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3664 break;
3665 case SWAMP:
3666 pline("It %s rather %s down here.",
3667 Blind ? "feels" : "looks",
3668 Blind ? "humid" : "muddy");
3669 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3670 break;
3671 case COURT:
3672 You(FunnyHallu ? "enter the Queen's chambers!" : "enter an opulent throne room!");
3673 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3674 break;
3675 case REALZOO:
3676 You(FunnyHallu ? "feel that some extinct species might still live here!" : "enter a smelly zoo!");
3677 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3678 break;
3679 case GIANTCOURT:
3680 You(FunnyHallu ? "enter a real huge hall!" : "enter a giant throne room!");
3681 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3682 break;
3683 case DRAGONLAIR:
3684 You(FunnyHallu ? "enter a fairy lair!" : "enter a dragon lair...");
3685 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3686 break;
3687 case BADFOODSHOP:
3688 You(FunnyHallu ? "enter some sort of market! Perhaps you can buy some weed here?" : "enter an abandoned store...");
3689 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3690 break;
3691 case LEPREHALL:
3692 You(FunnyHallu ? "encounter a Stonehenge replica!" : "enter a leprechaun hall!");
3693 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3694 break;
3695 case MORGUE:
3696 if(midnight()) {
3697 const char *run = locomotion(youmonst.data, "Run");
3698 pline("%s away! %s away!", run, run);
3699 } else
3700 { You("have an uncanny feeling..."); }
3701 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3702 break;
3703 case BEEHIVE:
3704 You(FunnyHallu ? "enter a tracker jacker nest! RUN AWAY!!!" : "enter a giant beehive!");
3705 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3706 break;
3707 case LEMUREPIT:
3708 You(FunnyHallu ? "enter the Devil's Lair!" : "enter a pit of screaming lemures!");
3709 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3710 break;
3711 case MIGOHIVE:
3712 You(FunnyHallu ? "enter some futuristic alien structure!" : "enter a strange hive!");
3713 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3714 break;
3715 case FUNGUSFARM:
3716 You(FunnyHallu ? "enter a sticky, slimy room..." : "enter a room full of fungi!");
3717 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3718 break;
3719 case COCKNEST:
3720 You(FunnyHallu ? "sense the well-known smell of weed as you enter this room!" : "enter a disgusting nest!");
3721 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3722 break;
3723 case ANTHOLE:
3724 You(FunnyHallu ? "enter a room filled with bugs!" : "enter an anthole!");
3725 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3726 break;
3727 case CLINIC:
3728 You(FunnyHallu ? "feel reminded of 'Emergency Room' as you enter this area!" : "enter a modern hospital.");
3729 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3730 break;
3731 case ANGELHALL:
3732 You(FunnyHallu ? "see the gods as you enter! WOW! So that's what they look like..." : "enter a radiating hall of Angels!");
3733 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3734 break;
3735 case TERRORHALL:
3736 You(FunnyHallu ? "feel like you just got detected by a tripwire!" : "enter a terrifying hall.");
3737 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3738 break;
3739 case TENSHALL:
3740 You(FunnyHallu ? "have died. Do you want your possessions identified? [ynq] (n) _" : "enter a killer room! This is actually an ADOM tension room.");
3741 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3742 break;
3743 case ELEMHALL:
3744 You(FunnyHallu ? "get a vision of Mother Nature as you enter!" : "enter a room full of elementals!");
3745 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3746 break;
3747 case NYMPHHALL:
3748 You(FunnyHallu ? "see a picture on the wall of this room. It shows the most beautiful woman you ever saw..." : "enter a beautiful garden!");
3749 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3750 break;
3751 case ARMORY:
3752 You(FunnyHallu ? "enter some old weapon storage chamber! Let's see what weapons are left!" : "enter a dilapidated armory.");
3753 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3754 break;
3755 case COINHALL:
3756 You(FunnyHallu ? "enter a room full of treasure, and it's all going to be yours! YEAH!" : "enter a room filled with money!");
3757 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3758 break;
3759 case TROLLHALL:
3760 You(FunnyHallu ? "feel that this room smells like a public toilet!" : "enter a room full of stinking trolls...");
3761 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3762 break;
3763 case HUMANHALL:
3764 You(FunnyHallu ? "encounter a party room! Let's invite some hot girls!" : "encounter a living room!");
3765 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3766 break;
3767 case SPIDERHALL:
3768 You(FunnyHallu ? "notice spiders of all forms and sizes in this room sitting everywhere!" : "stumble into a nest of spiders...");
3769 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3770 break;
3771 case GOLEMHALL:
3772 You(FunnyHallu ? "encounter some warmeches!" : "enter a room full of golems!");
3773 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3774 break;
3775 case TRAPROOM:
3776 if (wizard) You("enter a trapped room!");
3777 break;
3778 case EMPTYNEST:
3779 if (wizard) You("enter an empty nest!");
3780 break;
3781 case POOLROOM:
3782 if (wizard) You("enter a pool room!");
3783 break;
3784 case STATUEROOM:
3785 if (wizard) You("enter a statue room!");
3786 break;
3787 case NASTYCENTRAL:
3788 if (wizard) You("enter a nasty central!");
3789 break;
3790 case INSIDEROOM:
3791 You(FunnyHallu ? "enter a normal-looking room." : "enter a weird-looking room...");
3792 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3793 break;
3794 case RIVERROOM:
3795 You(FunnyHallu ? "encounter an underground mountain! Wait, what? This makes no sense!" : "encounter an underground river!");
3796 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3797 break;
3798 case GRUEROOM:
3799 pline(FunnyHallu ? "It is radiant bright. You are likely to be eaten by the sun." : "It is pitch black. You are likely to be eaten by a grue.");
3800 do_clear_areaX(u.ux,u.uy, /* extra darkness --Amy */
3801 15, set_litX, (void *)((char *)0));
3802 /* IMHO grue rooms may remove light every time you enter them. --Amy */
3803 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3804 break;
3805 case CRYPTROOM:
3806 You(FunnyHallu ? "forgot to bring your light source and can't see anything in this room." : "enter the dark crypts!");
3807 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3808 break;
3809 case TROUBLEZONE:
3810 You(FunnyHallu ? "got tons of trouble, baby!" : "enter the trouble zone!");
3811 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3812 break;
3813 case WEAPONCHAMBER:
3814 You(FunnyHallu ? "see people with long pointy sticks who want to impale you!" : "enter a weapons chamber!");
3815 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3816 break;
3817 case HELLPIT:
3818 pline(FunnyHallu ? "Gee, this looks exactly like the realms of Oblivion!" : "You enter the fiery pits of Hell!");
3819 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3820 break;
3821 case FEMINISMROOM:
3822 You(FunnyHallu ? "enter a room full of girls in sexy bikinis and high-heeled leather boots! WOW!" : "enter a feminist meeting room!");
3823 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3824 break;
3825 case MEADOWROOM:
3826 You(FunnyHallu ? "stumble into a ranch! Where's the cowboys and horses?" : "encounter a cattle meadow!");
3827 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3828 break;
3829 case COOLINGCHAMBER:
3830 You(FunnyHallu ? "entered the radiator area!" : "freeze as you enter the cooling chamber.");
3831 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3832 break;
3833 case VOIDROOM:
3834 pline(FunnyHallu ? "Your body warps strangely and you cease to exist... Do you want your possessions identified? [ynq] (n) _" : "You entered the Void!");
3835 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3836 break;
3837 case HAMLETROOM:
3838 pline(FunnyHallu ? "This room looks not dangerous at all." : "You've stumbled over a tiny hamlet!");
3839 if (Role_if(PM_SPACEWARS_FIGHTER) || Role_if(PM_CAMPERSTRIKER)) {
3840 pline(FunnyHallu ? "You feel that you've seen this before... it reminds you of the Woodstock Festival!" : "It looks familiar... didn't your adventures usually start in a similar place?");
3843 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3844 break;
3845 case KOPSTATION:
3846 pline(FunnyHallu ? "As you enter the heavily guarded army base, bullets start flying in your direction! TAKE COVER!" : "You've entered the local police station!");
3847 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3848 break;
3849 case BOSSROOM:
3850 You(FunnyHallu ? "were fated to die here. DIE!" : "feel that you will meet your fate here.");
3851 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3852 break;
3853 case RNGCENTER:
3854 You(FunnyHallu ? "enter a room that looks like it was designed by God Himself!" : "enter the Random Number Generator central!");
3855 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3856 break;
3857 case WIZARDSDORM:
3858 You(FunnyHallu ? "disturbed some old wizened fool that lives here, and now you have to kill that stupid git!" : "entered a wizard's dormitory!");
3859 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3860 break;
3861 case DOOMEDBARRACKS:
3862 You(FunnyHallu ? "realize that the game has turned into DoomRL! Quick, ready your kalashnikov and BFG!" : "enter an alien barracks!");
3863 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3864 break;
3865 case SLEEPINGROOM:
3866 pline(FunnyHallu ? "I heard you were sleeping there." : "You stumble into a sleeping room!");
3867 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3868 break;
3869 case DIVERPARADISE:
3870 You(FunnyHallu ? "enter a huge swimming pool, and the entrance is free! YEAH! Now you can splash around in the water and have many hours of pure FUN!" : "encounter the diver's paradise!");
3871 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3872 break;
3873 case MENAGERIE:
3874 You(FunnyHallu ? "enter a zoo filled with prehistoric animals! Err... I really hope they're peaceful!" : "enter a menagerie!");
3875 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3876 break;
3877 case EMPTYDESERT:
3878 pline(FunnyHallu ? "This looks like the Shifting Sand Land from Super Mario 64!" : "The air in this room is hot and arid.");
3879 break;
3880 case RARITYROOM:
3881 pline(FunnyHallu ? "It's the dungeon master's rarity collection! Quick, steal it before he turns up!" : "You enter a room filled with rare creatures!");
3882 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3883 break;
3884 case EXHIBITROOM:
3885 pline(FunnyHallu ? "Oh, look at all the zoo exhibits! Can I feed them? Can I pet them? Mind if I incinerate them?" : "You encounter an exhibit of strange creatures!");
3886 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3887 break;
3888 case PRISONCHAMBER:
3889 pline(FunnyHallu ? "Go directly to jail. Do not pass go. Do not collect 200 zorkmids." : "You enter a prison!");
3890 if (FunnyHallu) pline("Do you want your possessions identified? [ynq] (n) _");
3891 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3892 break;
3893 case NUCLEARCHAMBER:
3894 pline(FunnyHallu ? "It's where the government is researching weaponized uranium! If you can steal their technology, you can nuke the entire dungeon and ascend prematurely!" : "You encounter a nuclear power plant!");
3895 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3896 break;
3897 case PLAYERCENTRAL:
3898 pline(FunnyHallu ? "Are the people in here celebrating a corona party? Call the police! They're spreading the virus!" : "Apparently a rival gang of adventurers has set up camp here!");
3899 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3900 break;
3901 case LEVELSEVENTYROOM: /* no message but still wake_nearby --Amy */
3902 if (wizard) You("enter a level 70 room!");
3903 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3904 break;
3905 case VARIANTROOM:
3906 pline(FunnyHallu ? "The game suddenly turned into dnethack. The elder priest tentacles to tentacle you! Your cloak of magic resistance disintegrates!" : "You encounter a room from another variant!");
3907 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3908 break;
3909 case ROBBERCAVE:
3910 pline(FunnyHallu ? "Oh my god, Amy's fanfics have come true!" : "You enter the robbers' hideout!");
3911 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3912 break;
3913 case CASINOROOM:
3914 pline(FunnyHallu ? "As you enter the room, your head starts to ring like a slot machine!" : "You enter a casino!");
3915 break;
3916 case SANITATIONCENTRAL:
3917 pline(FunnyHallu ? "Muahahahahaha, you feel like focusing your gaze on a great race of yith because who needs sanity anyway?" : "Something seems to focus on your mind as you enter this room.");
3918 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3919 break;
3921 case BARRACKS:
3922 if(anymonstinroom(roomno)) {
3923 You("enter a military barracks!");
3924 } else {
3925 You("enter an abandoned barracks.");
3927 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3928 break;
3929 case DELPHI:
3930 if(monstinroom(&mons[PM_ORACLE], roomno))
3931 verbalize("%s, %s, welcome to Delphi!", Hello((struct monst *) 0), playeraliasname);
3932 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3933 break;
3934 case DOUGROOM:
3935 You_feel("42.");
3936 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3937 break;
3938 case EVILROOM:
3939 pline(FunnyHallu ? "Eek, you've stumbled into a SJW meeting!" : "The feel of this room is giving you the creeps.");
3940 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3941 break;
3942 case RELIGIONCENTER:
3943 pline(FunnyHallu ? "Ugh, an overwhelming cancerous stench floods your nostrils as you enter this room!" : "This room smells like rotten holy water.");
3944 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3945 break;
3946 case CURSEDMUMMYROOM:
3947 pline(FunnyHallu ? "You entered the Pharao's chambers!" : "Things that should be dead are walking this room.");
3948 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3949 break;
3950 case ARDUOUSMOUNTAIN:
3951 pline(FunnyHallu ? "You encounter an underground mountain. Wait, why the hell is there a mountain in the dungeon???" : "You encounter an underground mountain.");
3952 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3953 break;
3954 case THE_AREA_ROOM:
3955 pline(FunnyHallu ? "Boah, it's THE area! And there's a pentagram in the center!" : "This room reminds you of your heritage.");
3956 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3957 break;
3958 case CHANGINGROOM:
3959 pline(FunnyHallu ? "It's the womens locker room! Quick, quaff a potion of make invisible!" : "Seems like you entered a changing room.");
3960 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3961 break;
3962 case QUESTORROOM:
3963 pline(FunnyHallu ? "You entered your insufferable boss's office! Make sure that he doesn't see the knife you're holding in one hand behind your back." : "Uh-oh, your superiors are waiting for you in this room, and they don't seem to be pleased with your work.");
3964 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3965 break;
3966 case LEVELFFROOM:
3967 pline(FunnyHallu ? "Hey, this room looks just like your own living room!" : "This room looks familiar, but somehow different too.");
3968 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3969 break;
3970 case VERMINROOM:
3971 pline(FunnyHallu ? "Oh great, you entered a room full of shit." : "The air in this room is rank with mildew.");
3972 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3973 break;
3974 case CHAOSROOM:
3975 if (wizard) pline("You enter a chaos room!");
3976 break;
3977 case LETTERSALADROOM:
3978 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3979 if (wizard) pline("You enter a letter salad room!");
3980 break;
3981 case FULLROOM:
3982 if (wizard) pline("You enter a full room!");
3983 break;
3984 case RAMPAGEROOM:
3985 if (wizard) pline("You enter a rampage room!");
3986 break;
3987 case MIXEDPOOL:
3988 if (wizard) pline("You enter a mixed pool!");
3989 break;
3990 case MIRASPA:
3991 pline(FunnyHallu ? "Whoa, this room totally smells of ammonia!" : "As you enter the room, you can hear Mira inviting you for a swim.");
3992 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
3993 break;
3994 case MACHINEROOM:
3995 pline(FunnyHallu ? "It's the inside of the Space Shuttle!" : "You enter a machinery room.");
3996 if (uarmf && itemhasappearance(uarmf, APP_MACHINERY_BOOTS) && !u.uspellprot) {
3997 u.uspellprot = 4;
3998 u.uspmtime = 10;
3999 if (!u.usptime) u.usptime = u.uspmtime;
4000 find_ac();
4001 flags.botl = TRUE;
4002 You_feel("at home here, thanks to your machinery boots!");
4004 if (uarmf && uarmf->oartifact == ART_PERMINANT_INCREASE && u.ublessed < 4) {
4005 if (!(HProtection & INTRINSIC)) HProtection |= FROMOUTSIDE;
4006 u.ublessed = 4;
4007 find_ac();
4008 flags.botl = TRUE;
4009 pline("A holy aura of protection surrounds you!");
4011 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
4012 break;
4013 case SHOWERROOM:
4014 pline(FunnyHallu ? "Wow! You seem to have found the Niagara Falls!" : "You enter the shower.");
4015 break;
4016 case GREENCROSSROOM:
4017 pline(FunnyHallu ? "Entering this room feels like being put in headlock by your wonderful fleecy roommate!" : "This room has a very peaceful atmosphere.");
4018 break;
4019 case RUINEDCHURCH:
4020 pline(FunnyHallu ? "You enter Satan's chamber! Quick, ask him what is inferior to SLEX!" : "You enter a desecrated church.");
4021 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
4022 break;
4023 case GAMECORNER:
4024 pline(FunnyHallu ? "You've entered the local Game Stop store! The storeclerk says: 'Hello sir or miss, what can I do for you? I have GTA 5, the newest Call of Duty and of course also the latest Pokemon generation games available!'" : "You encounter a game corner!");
4025 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
4026 break;
4027 case ILLUSIONROOM:
4028 pline(FunnyHallu ? "This room is an illusion and a trap devisut by Satan. Go ahead dauntlessly! Make rapid progres!" : "Somehow, this room doesn't seem to be what it looks like.");
4029 if (!issoviet && anymonstinroom(roomno)) wake_nearby();
4030 break;
4031 case CENTRALTEDIUM:
4032 pline(FunnyHallu ? "It's the Straight Road! In order to get through this room, you need to stay on the road at all times and be fast or the Straight Road will weaken and ultimately be destroyed!" : "You encounter a highway to the left.");
4033 break;
4034 case TEMPLE:
4035 intemple(roomno + ROOMOFFSET);
4036 /* fall through */
4037 default:
4038 rt = 0;
4041 if (rt != 0) {
4042 /*rooms[roomno].rtype = OROOM;*/
4043 /*if (!search_special(rt)) {*/
4044 /* No more room of that type */
4045 /*switch(rt) {
4046 case COURT:
4047 case GIANTCOURT:
4048 level.flags.has_court = 0;
4049 break;
4050 case SWAMP:
4051 level.flags.has_swamp = 0;
4052 break;
4053 case MORGUE:
4054 level.flags.has_morgue = 0;
4055 break;
4056 case ZOO:
4057 case REALZOO:
4058 level.flags.has_zoo = 0;
4059 break;
4060 case BARRACKS:
4061 level.flags.has_barracks = 0;
4062 break;
4063 case CLINIC:
4064 level.flags.has_clinic = 0;
4065 break;
4066 case MIMICHALL:
4067 level.flags.has_mimichall = 0;
4068 break;
4069 case ANGELHALL:
4070 level.flags.has_angelhall = 0;
4071 break;
4072 case TERRORHALL:
4073 level.flags.has_terrorhall = 0;
4074 break;
4075 case TENSHALL:
4076 level.flags.has_tenshall = 0;
4077 break;
4078 case ELEMHALL:
4079 level.flags.has_elemhall = 0;
4080 break;
4081 case NYMPHHALL:
4082 level.flags.has_nymphhall = 0;
4083 break;
4084 case GOLEMHALL:
4085 level.flags.has_golemhall = 0;
4086 break;
4087 case TRAPROOM:
4088 level.flags.has_traproom = 0;
4089 break;
4090 case GRUEROOM:
4091 level.flags.has_grueroom = 0;
4092 break;
4093 case CRYPTROOM:
4094 level.flags.has_cryptroom = 0;
4095 break;
4096 case TROUBLEZONE:
4097 level.flags.has_troublezone = 0;
4098 break;
4099 case WEAPONCHAMBER:
4100 level.flags.has_weaponchamber = 0;
4101 break;
4102 case HELLPIT:
4103 level.flags.has_hellpit = 0;
4104 break;
4105 case ROBBERCAVE:
4106 level.flags.has_robbercave = 0;
4107 break;
4108 case CASINOROOM:
4109 level.flags.has_casinoroom = 0;
4110 break;
4111 case SANITATIONCENTRAL:
4112 level.flags.has_sanitationcentral = 0;
4113 break;
4114 case FEMINISMROOM:
4115 level.flags.has_feminismroom = 0;
4116 break;
4117 case MEADOWROOM:
4118 level.flags.has_meadowroom = 0;
4119 break;
4120 case COOLINGCHAMBER:
4121 level.flags.has_coolingchamber = 0;
4122 break;
4123 case VOIDROOM:
4124 level.flags.has_voidroom = 0;
4125 break;
4126 case ARMORY:
4127 level.flags.has_armory = 0;
4128 break;
4129 case HAMLETROOM:
4130 level.flags.has_hamletroom = 0;
4131 break;
4132 case KOPSTATION:
4133 level.flags.has_kopstation = 0;
4134 break;
4135 case BOSSROOM:
4136 level.flags.has_bossroom = 0;
4137 break;
4138 case RNGCENTER:
4139 level.flags.has_rngcenter = 0;
4140 break;
4141 case WIZARDSDORM:
4142 level.flags.has_wizardsdorm = 0;
4143 break;
4144 case DOOMEDBARRACKS:
4145 level.flags.has_doomedbarracks = 0;
4146 break;
4147 case SLEEPINGROOM:
4148 level.flags.has_sleepingroom = 0;
4149 break;
4150 case DIVERPARADISE:
4151 level.flags.has_diverparadise = 0;
4152 break;
4153 case MENAGERIE:
4154 level.flags.has_menagerie = 0;
4155 break;
4156 case NASTYCENTRAL:
4157 level.flags.has_nastycentral = 0;
4158 break;
4159 case EMPTYDESERT:
4160 level.flags.has_emptydesert = 0;
4161 break;
4162 case RARITYROOM:
4163 level.flags.has_rarityroom = 0;
4164 break;
4165 case EXHIBITROOM:
4166 level.flags.has_exhibitroom = 0;
4167 break;
4168 case PRISONCHAMBER:
4169 level.flags.has_prisonchamber = 0;
4170 break;
4171 case NUCLEARCHAMBER:
4172 level.flags.has_nuclearchamber = 0;
4173 break;
4174 case LEVELSEVENTYROOM:
4175 level.flags.has_levelseventyroom = 0;
4176 break;
4177 case PLAYERCENTRAL:
4178 level.flags.has_playercentral = 0;
4179 break;
4180 case VARIANTROOM:
4181 level.flags.has_variantroom = 0;
4182 break;
4183 case POOLROOM:
4184 level.flags.has_poolroom = 0;
4185 break;
4186 case STATUEROOM:
4187 level.flags.has_statueroom = 0;
4188 break;
4189 case INSIDEROOM:
4190 level.flags.has_insideroom = 0;
4191 break;
4192 case RIVERROOM:
4193 level.flags.has_riverroom = 0;
4194 break;
4195 case HUMANHALL:
4196 level.flags.has_humanhall = 0;
4197 break;
4198 case COINHALL:
4199 level.flags.has_coinhall = 0;
4200 break;
4201 case TROLLHALL:
4202 level.flags.has_trollhall = 0;
4203 break;
4204 case SPIDERHALL:
4205 level.flags.has_spiderhall = 0;
4206 break;
4207 case TEMPLE:
4208 level.flags.has_temple = 0;
4209 break;
4210 case BEEHIVE:
4211 level.flags.has_beehive = 0;
4212 break;
4213 case LEMUREPIT:
4214 level.flags.has_lemurepit = 0;
4215 break;
4216 case MIGOHIVE:
4217 level.flags.has_migohive = 0;
4218 break;
4219 case FUNGUSFARM:
4220 level.flags.has_fungusfarm = 0;
4221 break;
4222 case EVILROOM:
4223 level.flags.has_evilroom = 0;
4224 break;
4225 case RELIGIONCENTER:
4226 level.flags.has_religioncenter = 0;
4227 break;
4228 case CURSEDMUMMYROOM:
4229 level.flags.has_cursedmummyroom = 0;
4230 break;
4231 case ARDUOUSMOUNTAIN:
4232 level.flags.has_arduousmountain = 0;
4233 break;
4234 case LEVELFFROOM:
4235 level.flags.has_levelffroom = 0;
4236 break;
4237 case VERMINROOM:
4238 level.flags.has_verminroom = 0;
4239 break;
4240 case MIRASPA:
4241 level.flags.has_miraspa = 0;
4242 break;
4243 case MACHINEROOM:
4244 level.flags.has_machineroom = 0;
4245 break;
4246 case SHOWERROOM:
4247 level.flags.has_showerroom = 0;
4248 break;
4249 case GREENCROSSROOM:
4250 level.flags.has_greencrossroom = 0;
4251 break;
4252 case RUINEDCHURCH:
4253 level.flags.has_ruinedchurch = 0;
4254 break;
4255 case GAMECORNER:
4256 level.flags.has_gamecorner = 0;
4257 break;
4258 case ILLUSIONROOM:
4259 level.flags.has_illusionroom = 0;
4260 break;
4263 if(rt==COURT || rt==SWAMP || rt==MORGUE || rt==ZOO || (rt && !rn2(10)) )
4264 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
4265 if (!DEADMONSTER(mtmp) && (!Stealth || Aggravate_monster) && !rn2(3)) mtmp->msleeping = 0;
4269 return;
4272 #endif /* OVL2 */
4273 #ifdef OVLB
4276 dopickup()
4278 int count;
4279 struct trap *traphere = t_at(u.ux, u.uy);
4280 /* awful kludge to work around parse()'s pre-decrement */
4281 count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
4282 multi = 0; /* always reset */
4283 /* uswallow case added by GAN 01/29/87 */
4284 if(u.uswallow) {
4285 if (!u.ustuck->minvent) {
4286 if (is_animal(u.ustuck->data)) {
4287 You("pick up %s tongue.",
4288 s_suffix(mon_nam(u.ustuck)));
4289 pline("But it's kind of slimy, so you drop it.");
4290 } else
4291 You("don't %s anything in here to pick up.",
4292 Blind ? "feel" : "see");
4293 return(0);
4294 } else {
4295 int tmpcount = -count;
4296 return loot_mon(u.ustuck, &tmpcount, (boolean *)0);
4299 if((is_waterypool(u.ux, u.uy) || is_watertunnel(u.ux, u.uy) || is_moorland(u.ux, u.uy) || is_urinelake(u.ux, u.uy)) && !(is_crystalwater(u.ux, u.uy)) ) {
4300 if (Wwalking || Race_if(PM_KORONST) || is_floater(youmonst.data) || is_clinger(youmonst.data)
4301 || (Flying && !(uarmf && uarmf->oartifact == ART_DIP_DIVE) && !StrongFlying && !Breathless && !Swimming)) {
4302 You("cannot dive into the water to pick things up.");
4303 return(0);
4304 } else if (!Underwater && !(uarmf && uarmf->oartifact == ART_DIP_DIVE) && !Swimming && !StrongFlying) {
4305 You_cant("even see the bottom, let alone pick up %s.",
4306 something);
4307 return(0);
4310 if (is_lava(u.ux, u.uy)) {
4311 if (Wwalking || Race_if(PM_KORONST) || is_floater(youmonst.data) || is_clinger(youmonst.data)
4312 || (Flying && !(uarmf && uarmf->oartifact == ART_DIP_DIVE) && !StrongFlying && !Breathless)) {
4313 You_cant("reach the bottom to pick things up.");
4314 return(0);
4315 } else if (!likes_lava(youmonst.data) && !FireImmunity && !(uarmf && itemhasappearance(uarmf, APP_HOT_BOOTS) ) && !(uwep && uwep->oartifact == ART_EVERYTHING_MUST_BURN) && !(uamul && uamul->otyp == AMULET_OF_D_TYPE_EQUIPMENT) && !(uarmf && uarmf->oartifact == ART_DIP_DIVE) && !Race_if(PM_PLAYER_SALAMANDER) && !(uwep && uwep->oartifact == ART_MANUELA_S_PRACTICANT_TERRO) && !(powerfulimplants() && uimplant && uimplant->oartifact == ART_RUBBER_SHOALS) && !(uarm && uarm->oartifact == ART_LAURA_CROFT_S_BATTLEWEAR) && !(uarmc && uarmc->oartifact == ART_SCOOBA_COOBA) && !(uarm && uarm->oartifact == ART_D_TYPE_EQUIPMENT) && !(uarmf && uarmf->oartifact == ART_JOHANNA_S_RED_CHARM) ) {
4316 You("would burn to a crisp trying to pick things up.");
4317 return(0);
4320 if(!OBJ_AT(u.ux, u.uy)) {
4321 There("is nothing here to pick up.");
4322 return(0);
4324 if (!can_reach_floor()) {
4325 if (u.usteed && !(uwep && uwep->oartifact == ART_SORTIE_A_GAUCHE) && !(powerfulimplants() && uimplant && uimplant->oartifact == ART_READY_FOR_A_RIDE) && !FemtrapActiveKerstin && !(bmwride(ART_DEEPER_LAID_BMW)) && (PlayerCannotUseSkills || P_SKILL(P_RIDING) < P_BASIC) )
4326 You("aren't skilled enough to reach from %s.",
4327 y_monnam(u.usteed));
4328 else
4329 You("cannot reach the %s.", surface(u.ux,u.uy));
4330 return(0);
4333 if (traphere && traphere->tseen) {
4334 /* Allow pickup from holes and trap doors that you escaped from
4335 * because that stuff is teetering on the edge just like you, but
4336 * not pits, because there is an elevation discrepancy with stuff
4337 * in pits.
4339 /* [BarclayII] phasing or flying players can phase/fly into the pit */
4340 if ((traphere->ttyp == PIT || traphere->ttyp == SPIKED_PIT || traphere->ttyp == GIANT_CHASM || traphere->ttyp == SHIT_PIT || traphere->ttyp == MANA_PIT || traphere->ttyp == ANOXIC_PIT || traphere->ttyp == HYPOXIC_PIT || traphere->ttyp == ACID_PIT) &&
4341 (!u.utrap || (u.utrap && u.utraptype != TT_PIT)) && !Passes_walls && !Flying) {
4342 You("cannot reach the bottom of the pit.");
4343 return(0);
4347 return (pickup(-count));
4350 #endif /* OVLB */
4351 #ifdef OVL2
4353 /* stop running if we see something interesting */
4354 /* turn around a corner if that is the only way we can proceed */
4355 /* do not turn left or right twice */
4356 void
4357 lookaround()
4359 register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
4360 register int corrct = 0, noturn = 0;
4361 register struct monst *mtmp;
4362 register struct trap *trap;
4364 /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */
4365 /* they polymorphed while in the middle of a long move. */
4366 if ((BishopGridbug || u.uprops[BISHOP_GRIDBUG].extrinsic || have_bishopstone() || (uarmg && uarmg->oartifact == ART_LINE_CAN_PLAY_BY_YOURSELF) || autismweaponcheck(ART_KILLER_PIANO) || isgridbug(youmonst.data) || (Race_if(PM_WEAPON_BUG) && !Upolyd))&& u.dx && u.dy) {
4367 forcenomul(0, 0);
4368 return;
4371 if(Blind || flags.run == 0) return;
4372 for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) {
4373 if(!isok(x,y)) continue;
4375 if((BishopGridbug || u.uprops[BISHOP_GRIDBUG].extrinsic || have_bishopstone() || (uarmg && uarmg->oartifact == ART_LINE_CAN_PLAY_BY_YOURSELF) || autismweaponcheck(ART_KILLER_PIANO) || isgridbug(youmonst.data) || (Race_if(PM_WEAPON_BUG) && !Upolyd)) && x != u.ux && y != u.uy) continue;
4377 if(x == u.ux && y == u.uy) continue;
4379 if((mtmp = m_at(x,y)) &&
4380 mtmp->m_ap_type != M_AP_FURNITURE &&
4381 mtmp->m_ap_type != M_AP_OBJECT &&
4382 (!mtmp->minvis || (See_invisible && (StrongSee_invisible || mtmp->seeinvisble) ) ) && !mtmp->minvisreal && !mtmp->mundetected) {
4383 if((flags.run != 1 && !mtmp->mtame)
4384 || (x == u.ux+u.dx && y == u.uy+u.dy))
4385 goto stop;
4388 if (levl[x][y].typ == STONE) continue;
4389 if (x == u.ux-u.dx && y == u.uy-u.dy) continue;
4391 if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) ||
4392 IS_AIR(levl[x][y].typ))
4393 continue;
4394 else if (closed_door(x,y) ||
4395 (mtmp && mtmp->m_ap_type == M_AP_FURNITURE &&
4396 (mtmp->mappearance == S_hcdoor ||
4397 mtmp->mappearance == S_vcdoor))) {
4398 if(x != u.ux && y != u.uy) continue;
4399 if(flags.run != 1) goto stop;
4400 goto bcorr;
4401 } else if (levl[x][y].typ == CORR) {
4402 bcorr:
4403 if(levl[u.ux][u.uy].typ != ROOM) {
4404 if(flags.run == 1 || flags.run == 3 || flags.run == 8) {
4405 i = dist2(x,y,u.ux+u.dx,u.uy+u.dy);
4406 if(i > 2) continue;
4407 if(corrct == 1 && dist2(x,y,x0,y0) != 1)
4408 noturn = 1;
4409 if(i < i0) {
4410 i0 = i;
4411 x0 = x;
4412 y0 = y;
4413 m0 = mtmp ? 1 : 0;
4416 corrct++;
4418 continue;
4419 } else if ((trap = t_at(x,y)) && trap->tseen) {
4420 if(flags.run == 1) goto bcorr; /* if you must */
4421 if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
4422 continue;
4423 } else if (is_waterypool(x,y) || is_watertunnel(x,y) || is_urinelake(x,y) || is_shiftingsand(x,y) || is_moorland(x,y) || is_lava(x,y)) {
4424 /* water and lava only stop you if directly in front, and stop
4425 * you even if you are running
4427 /* KMH, balance patch -- new intrinsic */
4428 if(!Levitation && !Flying && !is_clinger(youmonst.data) &&
4429 x == u.ux+u.dx && y == u.uy+u.dy)
4430 /* No Wwalking check; otherwise they'd be able
4431 * to test boots by trying to SHIFT-direction
4432 * into a pool and seeing if the game allowed it
4434 goto stop;
4435 continue;
4436 } else { /* e.g. objects or trap or stairs */
4437 if(flags.run == 1) goto bcorr;
4438 if(flags.run == 8) continue;
4439 if(mtmp) continue; /* d */
4440 if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) ||
4441 ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
4442 continue;
4444 stop:
4445 nomul(0, 0, FALSE);
4446 return;
4447 } /* end for loops */
4449 if(corrct > 1 && flags.run == 2) goto stop;
4450 if((flags.run == 1 || flags.run == 3 || flags.run == 8) &&
4451 !noturn && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1)))
4453 /* make sure that we do not turn too far */
4454 if(i0 == 2) {
4455 if(u.dx == y0-u.uy && u.dy == u.ux-x0)
4456 i = 2; /* straight turn right */
4457 else
4458 i = -2; /* straight turn left */
4459 } else if(u.dx && u.dy) {
4460 if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
4461 i = -1; /* half turn left */
4462 else
4463 i = 1; /* half turn right */
4464 } else {
4465 if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy))
4466 i = 1; /* half turn right */
4467 else
4468 i = -1; /* half turn left */
4471 i += u.last_str_turn;
4472 if(i <= 2 && i >= -2) {
4473 u.last_str_turn = i;
4474 u.dx = x0-u.ux;
4475 u.dy = y0-u.uy;
4480 /* something like lookaround, but we are not running */
4481 /* react only to monsters that might hit us */
4483 monster_nearby()
4485 register int x,y;
4486 register struct monst *mtmp;
4488 /* Also see the similar check in dochugw() in monmove.c */
4489 for(x = u.ux-1; x <= u.ux+1; x++)
4490 for(y = u.uy-1; y <= u.uy+1; y++) {
4491 if(!isok(x,y)) continue;
4492 if(x == u.ux && y == u.uy) continue;
4493 if((mtmp = m_at(x,y)) &&
4494 mtmp->m_ap_type != M_AP_FURNITURE &&
4495 mtmp->m_ap_type != M_AP_OBJECT &&
4496 (!mtmp->mpeaceful || Hallucination) &&
4497 ( (!is_hider(mtmp->data) && (!mtmp->egotype_hide) && (!mtmp->egotype_mimic) ) || !mtmp->mundetected) &&
4498 !noattacks(mtmp->data) &&
4499 mtmp->mcanmove && !mtmp->msleeping && /* aplvax!jcn */
4500 !onscary(u.ux, u.uy, mtmp) &&
4501 canspotmon(mtmp))
4502 return(1);
4504 return(0);
4507 void
4508 maybe_scream()
4510 /* from Elona: maybe emit a sound when you're hurt; this is especially useful if you have display loss --Amy
4511 * known issue: you might be in a form that cannot "scream", I decided that I don't care and you scream anyway :P */
4512 int painchance = 10;
4513 int distresslevel = 0;
4515 if (Upolyd) {
4516 if (u.mh < (u.mhmax / 4)) distresslevel = 3;
4517 else if (u.mh < (u.mhmax / 2)) distresslevel = 2;
4518 else if (u.mh < (u.mhmax * 3 / 4)) distresslevel = 1;
4520 } else {
4521 if (u.uhp < (u.uhpmax / 4)) distresslevel = 3;
4522 else if (u.uhp < (u.uhpmax / 2)) distresslevel = 2;
4523 else if (u.uhp < (u.uhpmax * 3 / 4)) distresslevel = 1;
4526 if ( (PainSense && !rn2(10)) || (StrongPainSense && !rn2(5)) || (painchance < rnd(11)) ) {
4527 if (distresslevel == 3) You("are severely hurt!");
4528 else if (distresslevel == 2) You("writhe in pain.");
4529 else if (distresslevel == 1) You("scream.");
4530 /* otherwise you haven't lost enough health yet */
4535 void
4536 maybe_wail()
4538 static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES,
4539 SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES,
4540 TELEPORT_CONTROL, STEALTH, FAST, INVIS };
4542 if (moves <= wailmsg + 50) return;
4544 wailmsg = moves;
4545 if (Role_if(PM_WIZARD) || Role_if(PM_CONVICT) || Role_if(PM_COURIER) || Role_if(PM_CAMPERSTRIKER) || Role_if(PM_SPACEWARS_FIGHTER) || Role_if(PM_WARRIOR) || Role_if(PM_ELPH) || Role_if(PM_TWELPH) || Race_if(PM_ELF) || Race_if(PM_ASGARDIAN) || Race_if(PM_RODNEYAN) || ishaxor || isheretic || Race_if(PM_ALBAE) || Role_if(PM_VALKYRIE) || Role_if(PM_VANILLA_VALK)) {
4546 const char *who;
4547 int i, powercnt;
4549 who = (!rn2(10)) ? urace.noun :(Role_if(PM_WIZARD) || Role_if(PM_CONVICT) || Role_if(PM_COURIER) || Role_if(PM_CAMPERSTRIKER) || Role_if(PM_SPACEWARS_FIGHTER) || Role_if(PM_WARRIOR) || Role_if(PM_ELPH) || Role_if(PM_TWELPH) || Race_if(PM_ASGARDIAN) || ishaxor || isheretic || Race_if(PM_ALBAE) || Role_if(PM_VALKYRIE) || Role_if(PM_VANILLA_VALK)) ?
4550 urole.name.m : Race_if(PM_RODNEYAN) ? "Wizard of Yendor" : "Elf";
4551 if (u.uhp == 1) {
4552 pline("%s is about to die.", who);
4553 } else {
4554 for (i = 0, powercnt = 0; i < SIZE(powers); ++i)
4555 if (u.uprops[powers[i]].intrinsic & INTRINSIC) ++powercnt;
4557 pline(powercnt >= 4 ? "%s, all your powers will be lost..."
4558 : "%s, your life force is running out.", who);
4560 } else {
4561 You_hear(u.uhp == 1 ? "the wailing of the Banshee..."
4562 : "the howling of the CwnAnnwn...");
4563 if (u.uhp == 1 && (PlayerHearsSoundEffects)) pline(issoviet ? "Da! Umri, pozhaluysta! Ya nenavizhu tebya! Nadeyus', vy nastol'ko glupy, chtoby pozvolit' vse, chto chudovishche privelo vas k blizkoy smerti, chtoby snova udarit' tebya, a potom eto igra zakonchena GA GA GA!" : "SKRIIIIE-IIIIE-IIIIE-IIIIE-IIIIE!");
4564 else if (PlayerHearsSoundEffects) pline(issoviet ? "Nadeyus', vy prodolzhat' deystvovat' tak glupo, potomu chto togda vy budete umirat' i pridetsya svernut' novyy kharakter. Eto budet sluzhit' vam pravil'no, vy plokhoy igrok!" : "Wueueueue-oooooooh!");
4567 if (u.uhp == 1) {
4568 u.cnd_bansheecount++;
4569 if (autismweaponcheck(ART_P_WING)) {
4570 if (uwep && uwep->spe > -10) {
4571 uwep->spe = -10;
4572 pline("Powerup lost.");
4574 if (u.twoweap && uswapwep && uswapwep->oartifact == ART_P_WING && uswapwep->spe > -10) uswapwep->spe = -10;
4576 } else {
4577 u.cnd_cwnannwncount++;
4578 if (autismweaponcheck(ART_P_WING)) {
4579 if (uwep) {
4580 curse(uwep);
4581 pline("Powerup degraded.");
4583 if (u.twoweap && uswapwep && uswapwep->oartifact == ART_P_WING) curse(uswapwep);
4587 if (practicantterror && ((u.cnd_bansheecount + u.cnd_cwnannwncount) >= 5)) {
4588 if (!u.pract_cwnannwn) {
4589 u.pract_cwnannwn = TRUE;
4590 pline("%s rings out: 'It seems that you have a habit of getting into trouble. This is not how things run in this lab, maggot. Stop it or there'll be sanctions.'", noroelaname());
4591 } else {
4592 int cwnannwnfine = (u.cnd_bansheecount + u.cnd_cwnannwncount) * 100;
4593 pline("%s thunders: 'I told you to stay away from trouble! That costs %d zorkmids.'", noroelaname(), cwnannwnfine);
4594 fineforpracticant(cwnannwnfine, 0, 0);
4601 void
4602 nomul(nval, txt, discountpossible)
4603 register int nval;
4604 const char *txt;
4605 boolean discountpossible;
4607 if (uarmc && uarmc->oartifact == ART_LIGHTSPEED_TRAVEL && nval == 0) return;
4609 if (uarmf && nval == 0 && itemhasappearance(uarmf, APP_TURBO_BOOTS) ) return;
4611 if (u.katitrapocc && nval == 0) {
4612 pline("Something tries to interrupt your attempt to clean the Kati shoes! If you stop now, the sexy girl will hate you!");
4613 if (yn("Really stop cleaning them?") == 'y') {
4614 register struct monst *mtmp2;
4616 for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
4618 if (!mtmp2->mtame && !is_infrastructure_monster(mtmp2) ) {
4619 mtmp2->mpeaceful = 0;
4620 mtmp2->mfrenzied = 1;
4621 mtmp2->mhp = mtmp2->mhpmax;
4624 u.katitrapocc = FALSE;
4625 pline("The beautiful girl in the sexy Kati shoes is very sad that you didn't finish cleaning her lovely boots, and urges everyone in her vicinity to bludgeon you.");
4627 } else return;
4630 if (u.singtrapocc && nval == 0) {
4631 pline("Something tries to interrupt your attempt to clean the female shoes! If you stop now, the sexy girl will hate you!");
4632 if (yn("Really stop cleaning them?") == 'y') {
4633 register struct monst *mtmp2;
4635 for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
4637 if (!mtmp2->mtame && !is_infrastructure_monster(mtmp2) ) {
4638 mtmp2->mpeaceful = 0;
4639 mtmp2->mfrenzied = 1;
4640 mtmp2->mhp = mtmp2->mhpmax;
4643 u.cnd_singrefused++;
4644 u.singtrapocc = FALSE;
4645 u.singtraptreaded = FALSE;
4646 u.singtraphighheel = FALSE;
4647 u.singtrapcowdung = FALSE;
4648 pline("The beautiful girl in the sexy female shoes is very sad that you didn't finish cleaning her lovely footwear, and urges everyone in her vicinity to bludgeon you.");
4650 } else return;
4654 if(multi < nval) return; /* This is a bug fix by ab@unido */
4655 u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
4656 u.usleep = 0;
4658 if (PlayerInWedgeHeels && discountpossible && (nval < -1)) {
4659 register int dmgreductor = 90;
4660 if (!(PlayerCannotUseSkills)) switch (P_SKILL(P_HIGH_HEELS)) {
4661 case P_BASIC: dmgreductor = 88; break;
4662 case P_SKILLED: dmgreductor = 86; break;
4663 case P_EXPERT: dmgreductor = 84; break;
4664 case P_MASTER: dmgreductor = 82; break;
4665 case P_GRAND_MASTER: dmgreductor = 80; break;
4666 case P_SUPREME_MASTER: dmgreductor = 78; break;
4668 nval *= dmgreductor;
4669 nval /= 100;
4671 if (nval > -2) nval = -2;
4674 if (PlayerInColumnarHeels && discountpossible && (nval < -1)) {
4675 register int dmgreductor = 100;
4676 if (u.columnarskill >= 20) dmgreductor -= 10;
4677 if (u.columnarskill >= 160) dmgreductor -= 10;
4678 if (u.columnarskill >= 540) dmgreductor -= 10;
4679 if (u.columnarskill >= 1280) dmgreductor -= 10;
4680 if (u.columnarskill >= 2500) dmgreductor -= 10;
4681 if (u.columnarskill >= 4320) dmgreductor -= 10;
4683 nval *= dmgreductor;
4684 nval /= 100;
4686 if (nval > -2) nval = -2;
4690 if (irisartiboost() && discountpossible && (nval < -1)) {
4691 register int dmgreductor = 10;
4692 dmgreductor -= irisartiboost();
4694 nval *= dmgreductor;
4695 nval /= 10;
4697 if (nval > -2) nval = -2;
4700 if (discountpossible && (nval < -2) && !rn2(10) && uarmf && itemhasappearance(uarmf, APP_PLOF_HEELS) ) {
4701 nval /= 5;
4702 if (nval > -2) nval = -2;
4705 if (nval < 0 && FemtrapActiveLara && !u.laratraptimer) {
4707 struct permonst *pm = 0;
4708 int attempts = 0;
4709 register struct monst *laramon;
4711 if (Aggravate_monster) {
4712 u.aggravation = 1;
4713 reset_rndmonst(NON_PM);
4716 newbossLARA:
4717 do {
4718 pm = rndmonst();
4719 attempts++;
4720 if (attempts && (attempts % 10000 == 0)) u.mondiffhack++;
4721 if (!rn2(2000)) reset_rndmonst(NON_PM);
4723 } while ( (!pm || (pm && !(treadedshoemonster(pm) && highheeledshoemonster(pm)) )) && attempts < 50000);
4725 if (!pm && rn2(50) ) {
4726 attempts = 0;
4727 goto newbossLARA;
4729 if (pm && !(treadedshoemonster(pm) && highheeledshoemonster(pm)) && rn2(50) ) {
4730 attempts = 0;
4731 goto newbossLARA;
4734 if (pm) (laramon = makemon(pm, u.ux, u.uy, MM_ANGRY|MM_ADJACENTOK));
4736 if (laramon) {
4737 laramon->laramonst = TRUE;
4738 u.laratraptimer = (SuperFemtrapLara ? 200 : 1000);
4741 u.aggravation = 0;
4742 u.mondiffhack = 0;
4746 /* Discount action will halve paralysis duration, but some paralysis sources ignore it --Amy */
4747 if (Discount_action && discountpossible && (nval < -1)) nval /= 2;
4748 if (StrongDiscount_action && discountpossible && (nval < -1)) nval /= 2;
4750 /* at most 2 turns with sexy stand tech, as long as it's a resistable kind of paralysis --Amy */
4751 if (tech_inuse(T_SEXY_STAND) && PlayerInBlockHeels && discountpossible && (nval < -2)) nval = -2;
4753 if (uarmg && uarmg->otyp == GAUNTLETS_OF_PARALYSIS_ANNOUNC && nval < 0) {
4754 pline("You've been paralyzed for %d turns.", abs(nval));
4757 if (uarmg && uarmg->oartifact == ART_NOPE_OUT_OF_PARA && nval < 0 && discountpossible && (uarmg->invoketimer <= monstermoves) ) {
4758 if (yn("Nope out of the paralysis?") == 'y') {
4760 int artitimeout = rnz(2000);
4761 if (!rn2(5)) artitimeout = rnz(20000); /* squeaking does not help here, as it's not an actual invoke --Amy */
4762 uarmg->invoketimer = (monstermoves + artitimeout);
4763 return;
4767 multi = nval;
4768 if (multi < 0) flags.botl = 1;
4769 if (txt && txt[0])
4770 (void) strncpy(multi_txt, txt, BUFSZ);
4771 else
4772 (void) memset(multi_txt, 0, BUFSZ);
4773 flags.travel = iflags.travel1 = flags.mv = flags.run = 0;
4776 void
4777 forcenomul(nval, txt)
4778 register int nval;
4779 const char *txt;
4781 if(multi < nval) return; /* This is a bug fix by ab@unido */
4782 u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
4783 u.usleep = 0;
4784 multi = nval;
4785 if (multi < 0) flags.botl = 1;
4786 if (txt && txt[0])
4787 (void) strncpy(multi_txt, txt, BUFSZ);
4788 else
4789 (void) memset(multi_txt, 0, BUFSZ);
4790 flags.travel = iflags.travel1 = flags.mv = flags.run = 0;
4793 /* called when a non-movement, multi-turn action has completed */
4794 void
4795 unmul(msg_override)
4796 const char *msg_override;
4798 struct monst *mtmp;
4800 multi = 0; /* caller will usually have done this already */
4801 (void) memset(multi_txt, 0, BUFSZ);
4802 if (msg_override) nomovemsg = msg_override;
4803 else if (!nomovemsg) nomovemsg = You_can_move_again;
4804 if (*nomovemsg) pline("%s", nomovemsg);
4805 nomovemsg = 0;
4806 u.usleep = 0;
4807 if (afternmv) (*afternmv)();
4808 afternmv = 0;
4809 flags.botl = 1;
4811 /* lara trap effect: specially spawned monsters should banish themselves when you're unparalyzed --Amy */
4812 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
4813 if (mtmp->laramonst) {
4814 mtmp->laramonst = 0;
4816 d_level flev;
4818 if (mon_has_amulet(mtmp) || In_endgame(&u.uz)) {
4819 break;
4821 flev = random_banishment_level();
4822 migrate_to_level(mtmp, ledger_no(&flev), MIGR_RANDOM, (coord *)0);
4824 break;
4830 #endif /* OVL2 */
4831 #ifdef OVL1
4834 #ifdef SHOW_DMG
4835 /* Print the amount of damage inflicted */
4836 /* KMH -- Centralized to one function */
4837 void
4838 showdmg(n)
4839 register int n;
4841 int lev;
4843 if (DamageMeterBug || u.uprops[DAMAGE_METER_BUG].extrinsic || have_damagemeterstone()) return;
4844 if (Role_if(PM_NOOB_MODE_BARB)) return; /* sorry --Amy */
4846 if (flags.showdmg && n > 1) {
4847 switch (Role_switch) {
4848 case PM_BARBARIAN: case PM_MONK: lev = 10; break;
4849 case PM_CAVEMAN: case PM_VALKYRIE: lev = 12; break;
4850 /* vanilla valk doesn't get this because showdmg isn't even a thing in vanilla --Amy */
4851 case PM_SAMURAI: case PM_KNIGHT: case PM_CHEVALIER: case PM_GOLDMINER: lev = 14; break;
4852 default: lev = 17; break;
4854 switch (Race_switch) {
4855 case PM_GNOME: if (lev > 14) lev = 14; break;
4856 case PM_VEELA: if (lev > 1) lev = 1; break;
4858 #ifdef WIZARD
4859 if (wizard) lev = 1;
4860 #endif
4861 if(GushLevel >= lev)
4862 pline("(%d pts.)", n);
4864 return;
4866 #endif
4868 /* dnethack weeping angel contamination. Unlike dnethack, we have many sources of contamination, which is why I
4869 * don't call it "weeping angel" contamination; it's more like nuclear radiation or something. There will be certain
4870 * weeping angel types that use it as an attack, but the effect is just a generic "contamination". --Amy */
4871 void
4872 contaminate(amount, tellplayer)
4873 register int amount;
4874 boolean tellplayer;
4876 int precheckamount;
4878 if (flags.female) {
4879 while (!rn2(5)) amount *= 2;
4881 /* Yes I totally know this will call the SJWs and they will whine and bitch like mad, but there is an actual reason
4882 * for this: female characters are much more resistant to most item-stealers (since almost all nymphs are female),
4883 * and mhitu.c also specifically makes females more resistant to certain shoes when they are used by monsters.
4884 * Some players have even asserted that there is basically no advantage to playing a male character, and so I
4885 * decided to make females a little bit more susceptible to contamination.
4886 * THIS DOES NOT MEAN I HATE WOMEN, SO YOU SJWS CAN JUST BUGGER OFF KTHX --Amy */
4888 if (Race_if(PM_HUMANOID_ANGEL)) amount *= 2;
4889 /* It is also widely known that the angel race is teh uber pwnz0r and has almost no downsides, so I added one here */
4891 if (FalloutEffectXtra) amount *= 2;
4893 /* Contamination resistance divides incoming contamination by 5, but not below 1 */
4894 if (Cont_resist && amount > 1) {
4895 amount /= 5;
4896 if (amount < 1) amount = 1;
4898 if (StrongCont_resist) {
4899 amount /= 2;
4900 if (amount < 1 && rn2(2)) amount = 1;
4901 if (amount < 1) {
4902 if (tellplayer) pline("Somehow, the contamination doesn't affect you.");
4903 return;
4907 if (isfriday && !rn2(5)) amount *= 2;
4909 if (u.extracontres && !rn2(5)) {
4910 if (tellplayer) pline("The contamination doesn't seem to affect you.");
4911 return;
4914 if (uarmc && itemhasappearance(uarmc, APP_VINDALE_CLOAK) && rn2(2)) {
4915 if (tellplayer) pline("The contamination is absorbed by the cloak!");
4916 return;
4919 /* Mercury amulets in particular offer a bit of protection, but not other mercury equipment --Amy */
4920 if (uamul && objects[uamul->otyp].oc_material == MT_MERCURIAL && !rn2(10)) {
4921 if (tellplayer) pline("Your mercury amulet prevents you from being contaminated!");
4922 return;
4925 /* Platinum is supposed to be a material that shields you against contamination --Amy */
4926 if (uwep && objects[uwep->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4927 if (tellplayer) pline("Your platinum weapon prevents you from being contaminated!");
4928 return;
4930 if (u.twoweap && uswapwep && objects[uswapwep->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4931 if (tellplayer) pline("Your platinum off-hand weapon prevents you from being contaminated!");
4932 return;
4934 if (uarm && objects[uarm->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4935 if (tellplayer) pline("Your platinum armor prevents you from being contaminated!");
4936 return;
4938 if (uarmc && objects[uarmc->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4939 if (tellplayer) pline("Your platinum cloak prevents you from being contaminated!");
4940 return;
4942 if (uarmh && objects[uarmh->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4943 if (tellplayer) pline("Your platinum helmet prevents you from being contaminated!");
4944 return;
4946 if (uarms && objects[uarms->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4947 if (tellplayer) pline("Your platinum shield prevents you from being contaminated!");
4948 return;
4950 if (uarmg && objects[uarmg->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4951 if (tellplayer) pline("Your platinum pair of gauntlets prevents you from being contaminated!");
4952 return;
4954 if (uarmf && objects[uarmf->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4955 if (tellplayer) pline("Your platinum pair of boots prevents you from being contaminated!");
4956 return;
4958 if (uarmu && objects[uarmu->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4959 if (tellplayer) pline("Your platinum shirt prevents you from being contaminated!");
4960 return;
4962 if (uamul && objects[uamul->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4963 if (tellplayer) pline("Your platinum amulet prevents you from being contaminated!");
4964 return;
4966 if (uimplant && objects[uimplant->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4967 if (tellplayer) pline("Your platinum implant prevents you from being contaminated!");
4968 return;
4970 if (uleft && objects[uleft->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4971 if (tellplayer) pline("Your platinum left ring prevents you from being contaminated!");
4972 return;
4974 if (uright && objects[uright->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4975 if (tellplayer) pline("Your platinum right ring prevents you from being contaminated!");
4976 return;
4978 if (ublindf && objects[ublindf->otyp].oc_material == MT_PLATINUM && !rn2(10)) {
4979 if (tellplayer) pline("Your platinum blindfold prevents you from being contaminated!");
4980 return;
4983 /* lead shields against contamination even more --Amy */
4984 if (uwep && objects[uwep->otyp].oc_material == MT_LEAD && !rn2(5)) {
4985 if (tellplayer) pline("Your lead weapon prevents you from being contaminated!");
4986 return;
4988 if (u.twoweap && uswapwep && objects[uswapwep->otyp].oc_material == MT_LEAD && !rn2(5)) {
4989 if (tellplayer) pline("Your lead off-hand weapon prevents you from being contaminated!");
4990 return;
4992 if (uarm && objects[uarm->otyp].oc_material == MT_LEAD && !rn2(5)) {
4993 if (tellplayer) pline("Your lead armor prevents you from being contaminated!");
4994 return;
4996 if (uarmc && objects[uarmc->otyp].oc_material == MT_LEAD && !rn2(5)) {
4997 if (tellplayer) pline("Your lead cloak prevents you from being contaminated!");
4998 return;
5000 if (uarmh && objects[uarmh->otyp].oc_material == MT_LEAD && !rn2(5)) {
5001 if (tellplayer) pline("Your lead helmet prevents you from being contaminated!");
5002 return;
5004 if (uarms && objects[uarms->otyp].oc_material == MT_LEAD && !rn2(5)) {
5005 if (tellplayer) pline("Your lead shield prevents you from being contaminated!");
5006 return;
5008 if (uarmg && objects[uarmg->otyp].oc_material == MT_LEAD && !rn2(5)) {
5009 if (tellplayer) pline("Your lead pair of gauntlets prevents you from being contaminated!");
5010 return;
5012 if (uarmf && objects[uarmf->otyp].oc_material == MT_LEAD && !rn2(5)) {
5013 if (tellplayer) pline("Your lead pair of boots prevents you from being contaminated!");
5014 return;
5016 if (uarmu && objects[uarmu->otyp].oc_material == MT_LEAD && !rn2(5)) {
5017 if (tellplayer) pline("Your lead shirt prevents you from being contaminated!");
5018 return;
5020 if (uamul && objects[uamul->otyp].oc_material == MT_LEAD && !rn2(5)) {
5021 if (tellplayer) pline("Your lead amulet prevents you from being contaminated!");
5022 return;
5024 if (uimplant && objects[uimplant->otyp].oc_material == MT_LEAD && !rn2(5)) {
5025 if (tellplayer) pline("Your lead implant prevents you from being contaminated!");
5026 return;
5028 if (uleft && objects[uleft->otyp].oc_material == MT_LEAD && !rn2(5)) {
5029 if (tellplayer) pline("Your lead left ring prevents you from being contaminated!");
5030 return;
5032 if (uright && objects[uright->otyp].oc_material == MT_LEAD && !rn2(5)) {
5033 if (tellplayer) pline("Your lead right ring prevents you from being contaminated!");
5034 return;
5036 if (ublindf && objects[ublindf->otyp].oc_material == MT_LEAD && !rn2(5)) {
5037 if (tellplayer) pline("Your lead blindfold prevents you from being contaminated!");
5038 return;
5041 precheckamount = u.contamination;
5043 u.contamination += amount;
5045 if (u.contamination >= 100 && u.contamination < 200 && precheckamount < 100) pline(FunnyHallu ? "Your body itches comfortably." : "You are now afflicted with minor contamination.");
5046 if (u.contamination >= 200 && u.contamination < 400 && precheckamount < 200) pline(FunnyHallu ? "The itching on your body increases." : "You are now afflicted with light contamination.");
5047 if (u.contamination >= 400 && u.contamination < 600 && precheckamount < 400) pline(FunnyHallu ? "You seem to be developing ulcers." : "You are now afflicted with contamination.");
5048 if (u.contamination >= 600 && u.contamination < 800 && precheckamount < 600) pline(FunnyHallu ? "You feel like your digestive tract started to digest itself." : "You are now afflicted with severe contamination.");
5049 if (u.contamination >= 800 && u.contamination < 1000 && precheckamount < 800) pline(FunnyHallu ? "You feel that your body is consuming itself from within." : "You are now afflicted with lethal contamination.");
5050 if (u.contamination >= 1000 && precheckamount < 1000) pline(FunnyHallu ? "You feel terminally ill. Something tells you that you only have three days to live." : "You are now afflicted with fatal contamination. Seek medical attention immediately.");
5052 /* if you got told that you were contaminated, and wisdom is low, give a warning --Amy */
5053 if (tellplayer) {
5054 if (ABASE(A_WIS) < 2) {
5055 pline("DANGER!!! Your wisdom is critically low and you're very likely to die from the contamination! You can cure it by using a scroll or wand of remove curse, or by successfully praying on a coaligned altar. Amnesia may also help in a pinch, or you may buy a decontamination service from a nurse.");
5056 } else if (ABASE(A_WIS) < 4) {
5057 pline("Watch out!! Your wisdom is very low, the contamination may well reduce it below 1 and then you die! You can cure it by using a scroll or wand of remove curse, or by successfully praying on a coaligned altar. Amnesia may also help in a pinch, or you may buy a decontamination service from a nurse.");
5058 } else if (ABASE(A_WIS) < 6) {
5059 pline("Warning! Your wisdom is low and if the contamination causes it to fall below 1, you die! You can cure it by using a scroll or wand of remove curse, or by successfully praying on a coaligned altar. Amnesia may also help in a pinch, or you may buy a decontamination service from a nurse.");
5063 /* Actual contamination effects are handled in attrib.c */
5066 void
5067 decontaminate(amount)
5068 register int amount;
5070 int precheckamount;
5072 precheckamount = u.contamination;
5074 u.contamination -= amount;
5075 if (u.contamination < 0) u.contamination = 0;
5077 if (u.contamination == 0 && precheckamount >= 1) pline(FunnyHallu ? "Your body feels completely normal again." : "Your contamination has faded away completely.");
5078 if (u.contamination < 100 && u.contamination >= 1 && precheckamount >= 100) pline(FunnyHallu ? "Your body no longer itches." : "You are only very slightly contaminated now.");
5079 if (u.contamination < 200 && u.contamination >= 100 && precheckamount >= 200) pline(FunnyHallu ? "The itching on your body decreases." : "Your contamination decreased to a low level.");
5080 if (u.contamination < 400 && u.contamination >= 200 && precheckamount >= 400) pline(FunnyHallu ? "Your ulcers disappear." : "You are only lightly contaminated now.");
5081 if (u.contamination < 600 && u.contamination >= 400 && precheckamount >= 600) pline(FunnyHallu ? "Your digestive tract seems okay now." : "Your contamination is no longer severe.");
5082 if (u.contamination < 800 && u.contamination >= 600 && precheckamount >= 800) pline(FunnyHallu ? "Your body no longer tries to consume itself." : "You are only severely contaminated now.");
5083 if (u.contamination < 1000 && u.contamination >= 800 && precheckamount >= 1000) pline(FunnyHallu ? "Your terminal illness has passed and you may actually survive." : "You are only lethally contaminated now.");
5087 void
5088 reducesanity(amount)
5089 register int amount;
5091 if (!(u.usanity)) return;
5093 u.usanity -= amount;
5094 if (u.usanity < 0) u.usanity = 0;
5095 if (u.usanity == 0) pline("Your sanity was cured completely.");
5096 else if (amount < 10) pline("Your sanity was reduced.");
5097 else if (amount < 100) pline("Your sanity was reduced greatly.");
5098 else if (amount < 1000) pline("Your sanity was reduced enormously.");
5099 else pline("Your sanity was reduced by a really huge amount but is still not cured.");
5102 void
5103 losehp(n, knam, k_format)
5104 register int n;
5105 register const char *knam;
5106 int k_format; /* WAC k_format is an int */
5108 if (flags.iwbtg) {
5109 u.youaredead = 1;
5110 killer_format = k_format;
5111 killer = knam; /* the thing that killed you */
5112 You("explode in a fountain of red pixels!");
5113 pline("GAME OVER - press R to try again");
5114 done(DIED);
5115 u.youaredead = 0;
5119 if (youmonst.m_ap_type == M_AP_OBJECT && (multi < 0)) { /* bullshit! you should stop mimicking in that case! --Amy */
5120 You("took damage, and therefore stopped mimicking an object!");
5121 unmul((char *)0); /* immediately stop mimicking */
5122 youmonst.m_ap_type = M_AP_NOTHING;
5123 youmonst.mappearance = 0;
5124 /* after all, you just took damage, so no sense in continuing to pretend that you're a stupid orange */
5127 if (uarms && uarms->oartifact == ART_OF_VOIDING && n > 0) {
5128 n -= rnd(2);
5129 if (n < 1) n = 1;
5131 if (uarms && uarms->oartifact == ART_OF_NULLING && n > 0) {
5132 n -= rnd(4);
5133 if (n < 1) n = 1;
5136 /* let's allow the player to deflect some damage if he's lucky (higher chance with good constitution). --Amy */
5137 if (rn2(ABASE(A_CON))) {
5138 if (!rn2(3) && n >= 1) {n++; n = n / 2; if (n < 1) n = 1;}
5139 if (!rn2(10) && rn2(ABASE(A_CON)) && n >= 1 && GushLevel >= 10) {n++; n = n / 3; if (n < 1) n = 1;}
5140 if (!rn2(15) && rn2(ABASE(A_CON)) && rn2(ABASE(A_CON)) && n >= 1 && GushLevel >= 14) {n++; n = n / 4; if (n < 1) n = 1;}
5141 if (!rn2(20) && rn2(ABASE(A_CON)) && rn2(ABASE(A_CON)) && rn2(ABASE(A_CON)) && n >= 1 && GushLevel >= 20) {n++; n = n / 5; if (n < 1) n = 1;}
5142 if (!rn2(50) && rn2(ABASE(A_CON)) && rn2(ABASE(A_CON)) && rn2(ABASE(A_CON)) && rn2(ABASE(A_CON)) && n >= 1 && GushLevel >= 30) {n++; n = n / 10; if (n < 1) n = 1;}
5145 if (PlayerInConeHeels && n > 0) {
5146 register int dmgreductor = 95;
5147 if (!(PlayerCannotUseSkills)) switch (P_SKILL(P_HIGH_HEELS)) {
5148 case P_BASIC: dmgreductor = 92; break;
5149 case P_SKILLED: dmgreductor = 89; break;
5150 case P_EXPERT: dmgreductor = 86; break;
5151 case P_MASTER: dmgreductor = 83; break;
5152 case P_GRAND_MASTER: dmgreductor = 80; break;
5153 case P_SUPREME_MASTER: dmgreductor = 77; break;
5155 n++;
5156 n *= dmgreductor;
5157 n /= 100;
5158 if (n < 1) n = 1;
5161 if (n > 0 && StrongDetect_monsters) {
5162 n++;
5163 n *= 9;
5164 n /= 10;
5165 if (n < 1) n = 1;
5168 if (Race_if(PM_ITAQUE) && n > 0) {
5169 n++;
5170 n *= (100 - u.ulevel);
5171 n /= 100;
5172 if (n < 1) n = 1;
5175 if (Race_if(PM_CARTHAGE) && u.usteed && (mcalcmove(u.usteed) < 12) && n > 0) {
5176 n++;
5177 n *= 4;
5178 n /= 5;
5179 if (n < 1) n = 1;
5182 if (is_sand(u.ux,u.uy) && n > 0) {
5183 n++;
5184 n *= 4;
5185 n /= 5;
5186 if (n < 1) n = 1;
5189 if (Race_if(PM_VIKING) && n > 0) {
5190 n *= 5;
5191 n /= 4;
5194 if (Race_if(PM_SPARD) && n > 0) {
5195 n *= 5;
5196 n /= 4;
5199 if (Race_if(PM_MAYMES) && uwep && weapon_type(uwep) == P_FIREARM && n > 0) {
5200 n++;
5201 n *= 4;
5202 n /= 5;
5203 if (n < 1) n = 1;
5206 if (n > 0 && uarmf && itemhasappearance(uarmf, APP_MARJI_SHOES) ) {
5207 n++;
5208 n *= 9;
5209 n /= 10;
5210 if (n < 1) n = 1;
5213 if (n > 0 && uarm && uarm->oartifact == ART_KRAH_HOOOOO) {
5214 n++;
5215 n *= 9;
5216 n /= 10;
5217 if (n < 1) n = 1;
5220 if (n > 0 && uarms && uarms->oartifact == ART_AL_UD) {
5221 n++;
5222 n *= 9;
5223 n /= 10;
5224 if (n < 1) n = 1;
5227 /* very early on, low-level characters should be more survivable
5228 * this can certainly be exploited in some way; if players start exploiting it I'll have to fix it
5229 * but it should fix the annoying problem where you often instadie to a trap while your max HP are bad --Amy */
5230 if (depth(&u.uz) == 1 && u.ulevel == 1 && moves < 1000 && In_dod(&u.uz) && n > 1) { n /= 2; }
5231 if (depth(&u.uz) == 1 && u.ulevel == 2 && moves < 1000 && In_dod(&u.uz) && n > 1) { n *= 2; n /= 3; }
5233 if (n && Race_if(PM_YUKI_PLAYA)) n += rnd(5);
5234 if (Role_if(PM_BLEEDER)) n = n * 2; /* bleeders are harder than hard mode */
5235 if (!rn2(10) && (uarmf && uarmf->oartifact == ART_XTRA_CUTENESS)) n = n * 2;
5236 if (have_cursedmagicresstone()) n = n * 2;
5237 if (WinceState) {
5238 int damutemp = n;
5239 n *= 11;
5240 n /= 10;
5241 if (StrongWinceState) {
5242 n *= 11;
5243 n /= 10;
5245 if (n <= damutemp) n++;
5247 if (ACURR(A_CON) == 2) {
5248 n *= 11;
5249 n /= 10;
5251 if (ACURR(A_CON) == 1) {
5252 n *= 12;
5253 n /= 10;
5255 if (uarmh && uarmh->oartifact == ART_HEAD_W) {
5256 n *= 11;
5257 n /= 10;
5259 if (Role_if(PM_DANCER) && !rn2(3)) n = n * 2;
5260 if (Race_if(PM_METAL)) n *= rnd(10);
5261 if (HardModeEffect || u.uprops[HARD_MODE_EFFECT].extrinsic || have_hardmodestone() || autismringcheck(ART_RING_OF_FAST_LIVING) || autismweaponcheck(ART_PAINBOWSWANDIR) || autismweaponcheck(ART_RAISING_HEART) || (uimplant && uimplant->oartifact == ART_IME_SPEW) || (uarm && uarm->oartifact == ART_CHEST_TANK)) n = n * 2;
5262 if (uamul && uamul->otyp == AMULET_OF_VULNERABILITY) n *= rnd(4);
5263 if (RngeFrailness) n = n * 2;
5265 if (Race_if(PM_SHELL) && !Upolyd && n > 1) n /= 2;
5267 if (u.martialstyle == MARTIALSTYLE_SILAT && !rn2(5) && !uwep && (!u.twoweap || !uswapwep) && n > 1) n /= 2;
5269 if (isfriday && !rn2(50)) n += rnd(n);
5271 /* [max] Invulnerable no dmg */
5272 if (Invulnerable || (uarmf && uarmf->oartifact == ART_GODLY_POSTMAN && !rn2(10)) || ((PlayerInBlockHeels || PlayerInWedgeHeels) && tech_inuse(T_EXTREME_STURDINESS) && !rn2(2) ) || (Stoned_chiller && Stoned && !(u.stonedchilltimer) && !rn2(3)) ) {
5273 n = 0;
5274 pline("You are unharmed!");
5275 /* NOTE: DO NOT RETURN - losehp is also called to check for death
5276 * via u.uhp < 1
5278 } else if (StrongWonderlegs && !rn2(10) && Wounded_legs) {
5279 n = 0;
5280 pline("You are unharmed!");
5281 } else if (uarms && uarms->otyp == NULLIFICATION_SHIELD && !rn2(20) ) {
5282 n = 0;
5283 Your("shield nullifies the damage!");
5284 } else if (uimplant && uimplant->oartifact == ART_GLEN_HOSPITAL && !rn2(10)) {
5285 n = 0;
5286 Your("implant nullifies the damage!");
5287 } else if (PlayerInConeHeels && !PlayerCannotUseSkills && P_SKILL(P_CONE_HEELS) >= P_BASIC && (rnd(100) < P_SKILL(P_CONE_HEELS)) ) {
5288 n = 0;
5289 Your("cone heels nullify the damage!");
5290 } else if (u.twoweap && uswapwep && uswapwep->oartifact == ART_SHIELD_TONFA && !rn2(10)) {
5291 n = 0;
5292 Your("tonfa nullifies the damage!");
5293 } else if (uarm && uarm->oartifact == ART_SUSA_MAIL && !rn2(10)) {
5294 n = 0;
5295 Your("armor nullifies the damage!");
5296 } else if (uarmf && uarmf->oartifact == ART_ELENA_S_EPITOME && !rn2(10)) {
5297 n = 0;
5298 Your("pair of heels nullifies the damage!");
5299 } else if (uarmf && uarmf->oartifact == ART_IRMA_S_CHOICE && !rn2(10)) {
5300 n = 0;
5301 Your("pair of heels nullifies the damage!");
5302 } else if (uarms && uarms->oartifact == ART_PLANK_OF_CARNEADES && !rn2(10)) {
5303 n = 0;
5304 Your("shield nullifies the damage!");
5305 } else if (uarms && uarms->oartifact == ART_AL_UD && !rn2(10)) {
5306 n = 0;
5307 Your("shield nullifies the damage!");
5308 } else if (uarms && uarms->oartifact == ART_DOUBLEBLANK && !rn2(10)) {
5309 n = 0;
5310 Your("shield nullifies the damage!");
5311 } else if (uwep && uwep->oartifact == ART_ETERNAL_LONGING && !rn2(10)) {
5312 n = 0;
5313 Your("soft lady shoe nullifies the damage!");
5314 } else if (u.metalguard) {
5315 u.metalguard = 0;
5316 n = 0;
5317 Your("metal guard prevents the damage!");
5320 if (uactivesymbiosis && !u.symbiotedmghack && (rn2(100) < u.symbioteaggressivity) && !(u.usymbiote.mhpmax >= 5 && u.usymbiote.mhp <= (u.usymbiote.mhpmax / 5) && rn2(5))) {
5321 if (tech_inuse(T_POWERBIOSIS) && n > 1) n /= 2;
5322 if (tech_inuse(T_IMPLANTED_SYMBIOSIS) && uimplant && objects[uimplant->otyp].oc_charged && uimplant->spe > 0) {
5323 int imbiophases = uimplant->spe;
5324 while ((imbiophases > 0) && n > 1) {
5325 imbiophases--;
5326 n *= 10;
5327 n /= 11;
5330 u.usymbiote.mhp -= n;
5331 Your("%s symbiote takes the damage for you.", mons[u.usymbiote.mnum].mname);
5332 if (u.usymbiote.mhp <= 0) {
5334 if (uarmf && itemhasappearance(uarmf, APP_REMORA_HEELS) && u.usymbiote.mnum == PM_REMORA) {
5335 if (uarmf->spe > -1) uarmf->spe = -1;
5338 if (uamul && uamul->otyp == AMULET_OF_SYMBIOTE_SAVING) {
5339 makeknown(AMULET_OF_SYMBIOTE_SAVING);
5340 useup(uamul);
5341 u.usymbiote.mhp = u.usymbiote.mhpmax;
5342 Your("symbiote glows, and your amulet crumbles to dust!");
5343 } else {
5344 u.usymbiote.active = 0;
5345 u.usymbiote.mnum = PM_PLAYERMON;
5346 u.usymbiote.mhp = 0;
5347 u.usymbiote.mhpmax = 0;
5348 u.usymbiote.cursed = u.usymbiote.hvycurse = u.usymbiote.prmcurse = u.usymbiote.bbcurse = u.usymbiote.morgcurse = u.usymbiote.evilcurse = u.usymbiote.stckcurse = 0;
5349 u.cnd_symbiotesdied++;
5350 if (FunnyHallu) pline("Ack! You feel like you quaffed aqua pura by mistake, and feel like something inside you has been flushed away!");
5351 else Your("symbiote dies from protecting you, and you feel very sad...");
5354 if (flags.showsymbiotehp) flags.botl = TRUE;
5355 } else if (u.disruptionshield && u.uen >= n) {
5356 u.uen -= n;
5357 pline("Your mana shield takes the damage for you!");
5358 flags.botl = 1;
5360 } else if (Upolyd) {
5361 u.mh -= n;
5362 if (u.mhmax < u.mh) u.mhmax = u.mh;
5364 if (u.mh > 0) maybe_scream();
5366 if (u.mh < 1) {
5368 rehumanize();
5370 } else if (n > 0 && u.mh*10 < u.mhmax && Unchanging)
5371 maybe_wail();
5373 #ifdef SHOW_DMG
5374 if (flags.showdmg && !(DamageMeterBug || u.uprops[DAMAGE_METER_BUG].extrinsic || have_damagemeterstone()) && !DisplayDoesNotGoAtAll && n > 0) {
5375 pline("[-%d -> %d]", n, (Upolyd ? (u.mh) : (u.uhp) ) ); /* WAC see damage */
5377 #endif
5378 return;
5379 } else {
5380 u.uhplast = u.uhp;
5381 u.uhp -= n;
5382 if(u.uhp > u.uhpmax)
5383 u.uhpmax = u.uhp; /* perhaps n was negative */
5386 flags.botl = 1; /* Update status bar */
5388 if (u.uhp > 0) maybe_scream();
5390 if(u.uhp < 1) {
5391 u.youaredead = 1;
5392 killer_format = k_format;
5393 killer = knam; /* the thing that killed you */
5394 You(isangbander ? "have died." : "die...");
5395 done(DIED);
5396 u.youaredead = 0;
5397 } else if (n > 0 && u.uhp*10 < u.uhpmax) {
5398 maybe_wail();
5401 #ifdef SHOW_DMG
5402 if (flags.showdmg && !(DamageMeterBug || u.uprops[DAMAGE_METER_BUG].extrinsic || have_damagemeterstone()) && !DisplayDoesNotGoAtAll && n > 0) {
5404 pline("[-%d -> %d]", n, (Upolyd ? (u.mh) : (u.uhp) ) ); /* WAC see damage */
5405 if (!Upolyd && (( (u.uhp) * 5) < u.uhpmax)) pline(isangbander ? "***LOW HITPOINT WARNING***" : "Warning: HP low!");
5406 if (isangbander && (!Upolyd && (( (u.uhp) * 5) < u.uhpmax)) && (PlayerHearsSoundEffects)) pline(issoviet ? "Umeret' glupyy igrok ublyudka!" : "TSCHINGTSCHINGTSCHINGTSCHING!");
5409 #endif
5411 if (u.uprops[TURNLIMITATION].extrinsic || (uarmh && uarmh->oartifact == ART_TEJUS__VACANCY) || (uarmf && uarmf->oartifact == ART_OUT_OF_TIME) || (uarmu && uarmu->oartifact == ART_THERMAL_BATH) || TurnLimitation || have_limitationstone() || (uarm && uarm->oartifact == ART_AMMY_S_EASYMODE) ) {
5413 if (LimitationXtra && (n > 0)) u.ascensiontimelimit -= (n * 10);
5414 else if (n > 0) u.ascensiontimelimit -= n;
5415 if (u.ascensiontimelimit < 1) u.ascensiontimelimit = 1;
5418 if (Race_if(PM_CELTIC) && !rn2(100)) {
5419 if (u.berserktime) {
5420 if (!obsidianprotection()) switch (rn2(11)) {
5421 case 0:
5422 make_sick(Sick ? Sick/2L + 1L : (long)rn1(ACURR(A_CON),20), "celtic sickness", TRUE, SICK_NONVOMITABLE);
5423 break;
5424 case 1: make_blinded(Blinded + 25, TRUE);
5425 break;
5426 case 2: if (!Confusion)
5427 You("suddenly feel %s.", FunnyHallu ? "trippy" : "confused");
5428 make_confused(HConfusion + 25, TRUE);
5429 break;
5430 case 3: make_stunned(HStun + 25, TRUE);
5431 break;
5432 case 4: make_numbed(HNumbed + 25, TRUE);
5433 break;
5434 case 5: make_frozen(HFrozen + 25, TRUE);
5435 break;
5436 case 6: make_burned(HBurned + 25, TRUE);
5437 break;
5438 case 7: (void) adjattrib(rn2(A_MAX), -1, FALSE, TRUE);
5439 break;
5440 case 8: (void) make_hallucinated(HHallucination + 25, TRUE, 0L);
5441 break;
5442 case 9: make_feared(HFeared + 25, TRUE);
5443 break;
5444 case 10: make_dimmed(HDimmed + 25, TRUE);
5445 break;
5448 } else u.berserktime = 25;
5454 max_carr_cap()
5456 int maxcarrcap = 5000;
5458 if (tech_inuse(T_LIGHTER_BALLS)) {
5459 if (uwep && uwep->oclass == BALL_CLASS) maxcarrcap += (uwep->owt / 2);
5460 if (u.twoweap && uswapwep && uswapwep->oclass == BALL_CLASS) maxcarrcap += (uswapwep->owt / 2);
5462 if (have_daisybag()) maxcarrcap += 500;
5463 if (uarm && uarm->oartifact == ART_COLLECTING_EXPANSION) maxcarrcap += 5000;
5464 if (uwep && uwep->oartifact == ART_FIRST_CARRYING_BOX) maxcarrcap += 1000;
5465 if (uarm && uarm->oartifact == ART_SCHOOL_SATCHEL) maxcarrcap += 2000;
5466 if (uarmc && uarmc->oartifact == ART_STRIPED_SHIRT_OF_THE_MURDE) maxcarrcap += 1000;
5467 if (uarm && uarm->oartifact == ART_STACHEL_SATCHEL) maxcarrcap += 500;
5468 if (uarm && uarm->oartifact == ART_COMPLETELY_LIGHT) maxcarrcap += 500;
5469 if (uarm && uarm->oartifact == ART_AND_LONGITUDE) maxcarrcap += 1000;
5470 if (uarm && uarm->oartifact == ART_NATAS_IS_BACK) maxcarrcap += 2000;
5471 if (uarmc && uarmc->otyp == TORNISTER_CLOAK) maxcarrcap += 500;
5472 if (uamul && uamul->oartifact == ART_ATLAS_WEIGHT_CRUNCH) maxcarrcap += 2000;
5473 if (uarm && uarm->oartifact == ART_TRIANGLE_GIRL) {
5474 maxcarrcap += 1000;
5475 if (flags.female && u.ulevel < 10) maxcarrcap += 4000;
5477 if (uwep && uwep->otyp == BAGGY_SLING) maxcarrcap += 100;
5478 if (uwep && uwep->oartifact == ART_USEFUL_BINDLE) maxcarrcap += 1000;
5479 if (uarmc && uarmc->oartifact == ART_NEUTRINO) maxcarrcap += 1000;
5480 if (RngeCarryingBoost) maxcarrcap += 1000;
5481 if (u.xtralevelmult > 1) maxcarrcap += ((u.xtralevelmult - 1) * 10);
5483 if (uarmh && uarmh->oartifact == ART_LIVIN__IT_UP) maxcarrcap *= 2;
5485 return maxcarrcap;
5489 weight_cap()
5491 register long carrcap;
5493 carrcap = 50*(ACURRSTR + ACURR(A_CON)) + 50 + 50*(u.ulevel);
5494 if (Upolyd) {
5495 /* consistent with can_carry() in mon.c */
5496 if (youmonst.data->mlet == S_NYMPH || youmonst.data == &mons[PM_GOLDEN_KNIGHT] || youmonst.data == &mons[PM_GOLDEN_HOLY_KNIGHT] || youmonst.data == &mons[PM_URCAGUARY])
5497 carrcap = max_carr_cap();
5498 else if (!youmonst.data->cwt)
5499 carrcap = ((carrcap * (long)youmonst.data->msize) / MZ_HUMAN) + 50*(u.ulevel);
5500 else if (!strongmonst(youmonst.data)
5501 || (strongmonst(youmonst.data) && (youmonst.data->cwt > WT_HUMAN)))
5502 carrcap = ((carrcap * (long)youmonst.data->cwt / WT_HUMAN)) + 50*(u.ulevel);
5503 if (carrcap < 500) carrcap = 500;
5506 /* Intelligence increases carrying capacity, because a smarter character is able to organize and balance their pack
5507 * more evenly. (I don't remember who had this idea, maybe aosdict? --Amy) */
5508 carrcap += 10*(ACURR(A_INT));
5510 if (u.menoraget) carrcap += 200;
5511 if (u.bookofthedeadget) carrcap += 250;
5512 if (u.silverbellget) carrcap += 150;
5513 if (u.chaoskeyget) carrcap += 50;
5514 if (u.neutralkeyget) carrcap += 50;
5515 if (u.lawfulkeyget) carrcap += 50;
5516 if (u.medusaremoved) carrcap += 150;
5517 if (u.luckstoneget) carrcap += 50;
5518 if (u.sokobanfinished) carrcap += 50;
5519 if (u.deepminefinished) carrcap += 50;
5520 if (uarm && uarm->oartifact == ART_DRAGON_PLATE) carrcap -= 250;
5521 if (ACURR(A_STR) == 1) carrcap -= 200;
5522 if (ACURR(A_STR) == 2) carrcap -= 100;
5523 if (uarmg && uarmg->oartifact == ART_HANDBOXED) carrcap += 1000;
5524 if (uwep && uwep->oartifact == ART_GIRLFUL_BONKING) carrcap -= 500;
5525 if (u.twoweap && uswapwep && uswapwep->oartifact == ART_GIRLFUL_BONKING) carrcap -= 500;
5526 if (uleft && uleft->oartifact == ART_CORGON_S_RING) carrcap += 100;
5527 if (uright && uright->oartifact == ART_CORGON_S_RING) carrcap += 100;
5528 if (have_daisybag()) carrcap += 1000;
5529 if (uarm && uarm->oartifact == ART_COLLECTING_EXPANSION) carrcap += 2000;
5530 if (uarm && uarm->oartifact == ART_SCHOOL_SATCHEL) carrcap += 2000;
5531 if (uarm && uarm->oartifact == ART_NATAS_IS_BACK) carrcap += 2000;
5532 if (uamul && uamul->oartifact == ART_ATLAS_WEIGHT_CRUNCH) carrcap += 1000;
5533 if (uarm && uarm->oartifact == ART_TRIANGLE_GIRL) {
5534 carrcap += 1000;
5535 if (flags.female && u.ulevel < 10) carrcap += 4000;
5537 if (uleft && uleft->oartifact == ART_RING_OF_STEEL_DRAGON) carrcap += 100;
5538 if (uright && uright->oartifact == ART_RING_OF_STEEL_DRAGON) carrcap += 100;
5539 if (uarmc && uarmc->oartifact == ART_STRIPED_SHIRT_OF_THE_MURDE) carrcap += 1000;
5540 if (uarm && uarm->oartifact == ART_COMPLETELY_LIGHT) carrcap += 500;
5541 if (uarm && uarm->oartifact == ART_STACHEL_SATCHEL) carrcap += 2000;
5542 if (uarmc && uarmc->otyp == TORNISTER_CLOAK) carrcap += 500;
5543 if (uwep && uwep->oartifact == ART_FIRST_CARRYING_BOX) carrcap += 1000;
5544 if (uarm && uarm->oartifact == ART_AND_LONGITUDE) carrcap += 500;
5545 if (uarmc && uarmc->oartifact == ART_NEUTRINO) carrcap += 1000;
5546 if (RngeCarryingBoost) carrcap += 1000;
5547 if (u.cnd_trophiesobtained) carrcap += (u.cnd_trophiesobtained * 50);
5548 if (u.xtralevelmult > 1) carrcap += ((u.xtralevelmult - 1) * 50);
5549 if (uarmc && uarmc->oartifact == ART_OH_MY_GOD_SPANDEX) carrcap += 200;
5550 if (uwep && uwep->otyp == BAGGY_SLING) carrcap += 250;
5551 if (uwep && uwep->oartifact == ART_USEFUL_BINDLE) carrcap += 1000;
5553 if (!PlayerCannotUseSkills && uarm && (uarm->otyp >= ROBE && uarm->otyp <= ROBE_OF_WEAKNESS)) {
5555 switch (P_SKILL(P_SORESU)) {
5556 case P_BASIC: carrcap += 200; break;
5557 case P_SKILLED: carrcap += 400; break;
5558 case P_EXPERT: carrcap += 600; break;
5559 case P_MASTER: carrcap += 800; break;
5560 case P_GRAND_MASTER: carrcap += 1000; break;
5561 case P_SUPREME_MASTER: carrcap += 1200; break;
5567 if (Race_if(PM_CHIROPTERAN)) carrcap += 2000;
5568 if (Race_if(PM_PLAYER_SHEEP) && u.ulevel >= 20) carrcap += 2000;
5570 if (tech_inuse(T_LIGHTER_BALLS)) {
5571 if (uwep && uwep->oclass == BALL_CLASS) carrcap += (uwep->owt / 2);
5572 if (u.twoweap && uswapwep && uswapwep->oclass == BALL_CLASS) carrcap += (uswapwep->owt / 2);
5575 if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
5576 || (u.usteed && strongmonst(u.usteed->data)) ) {
5577 carrcap += 2000;
5578 } else if (!Flying) {
5579 if (HWounded_legs) carrcap -= 250;
5580 if (EWounded_legs) carrcap -= 250;
5583 /* multipliers go here */
5585 if (Race_if(PM_HAXOR)) carrcap *= 2;
5586 if (Race_if(PM_HUMANOID_CENTAUR)) carrcap /= 2;
5588 if (Upolyd && !PlayerCannotUseSkills) {
5589 switch (P_SKILL(P_POLYMORPHING)) {
5590 case P_BASIC: carrcap *= 6; carrcap /= 5; break;
5591 case P_SKILLED: carrcap *= 7; carrcap /= 5; break;
5592 case P_EXPERT: carrcap *= 8; carrcap /= 5; break;
5593 case P_MASTER: carrcap *= 9; carrcap /= 5; break;
5594 case P_GRAND_MASTER: carrcap *= 10; carrcap /= 5; break;
5595 case P_SUPREME_MASTER: carrcap *= 11; carrcap /= 5; break;
5599 if (uarmf && uarmf->oartifact == ART_A_SPOONFUL_OF_FO_U_RK) {
5600 carrcap = max_carr_cap();
5603 /* absolute minimum and maximum values --Amy */
5604 if (carrcap < 500) carrcap = 500;
5605 if(carrcap > (max_carr_cap())) carrcap = max_carr_cap();
5607 /* the "fuck you Amy, your weight limits are as shitty as vanilla nethack's" effect :-P */
5608 if (CarrcapEffect || u.uprops[CARRCAP_EFFECT].extrinsic || have_carrcapstone() || (uamul && uamul->oartifact == ART_ARVIAT_S_LOAD) || have_minimejewel() ) {
5609 if (carrcap > 500) carrcap = 500;
5612 return((int) carrcap);
5615 static int wc; /* current weight_cap(); valid after call to inv_weight() */
5617 /* returns how far beyond the normal capacity the player is currently. */
5618 /* inv_weight() is negative if the player is below normal capacity. */
5620 inv_weight()
5622 register struct obj *otmp = invent;
5623 register int wt = 0;
5625 #ifndef GOLDOBJ
5626 /* when putting stuff into containers, gold is inserted at the head
5627 of invent for easier manipulation by askchain & co, but it's also
5628 retained in u.ugold in order to keep the status line accurate; we
5629 mustn't add its weight in twice under that circumstance */
5630 /* tried to make gold lighter --Amy */
5631 wt = (otmp && otmp->oclass == COIN_CLASS) ? 0 :
5632 (int)((u.ugold + 50L) / /*100L*/1000000L);
5633 #endif
5634 while (otmp) {
5635 #ifndef GOLDOBJ
5636 if ( (otmp->otyp != BOULDER && otmp->otyp != LOADBOULDER) || (!throws_rocks(youmonst.data) && !(uarmg && uarmg->oartifact == ART_MOUNTAIN_FISTS)) )
5637 #else
5638 if (otmp->oclass == COIN_CLASS)
5639 wt += (int)(((long)otmp->quan + 50L) / /*100L*/10000L);
5640 else if ( (otmp->otyp != BOULDER && otmp->otyp != LOADBOULDER) || !throws_rocks(youmonst.data))
5641 #endif
5642 wt += otmp->owt;
5644 /* boulders shouldn't be completely weightless as a giant! --Amy */
5645 if ( (throws_rocks(youmonst.data) || (uarmg && uarmg->oartifact == ART_MOUNTAIN_FISTS)) && (otmp->otyp == BOULDER)) {
5646 wt += 500;
5648 if ( (throws_rocks(youmonst.data) || (uarmg && uarmg->oartifact == ART_MOUNTAIN_FISTS)) && (otmp->otyp == LOADBOULDER)) {
5649 wt += 5000;
5652 otmp = otmp->nobj;
5654 if (IncreasedGravity) wt += IncreasedGravity;
5655 if (u.graundweight) wt += u.graundweight;
5656 if (uarmh && itemhasappearance(uarmh, APP_LEAD_HELMET)) wt += 50;
5657 if (uarmf && itemhasappearance(uarmf, APP_LEAD_BOOTS)) wt += 100;
5658 if (uarm && uarm->oartifact == ART_SUPERHEAVY_GARBO) wt += 250;
5659 if (uarmf && itemhasappearance(uarmf, APP_WEIGHT_ATTACHMENT_BOOTS)) wt += 500;
5660 if (have_stashitcontainer()) wt += 1000;
5661 if (uwep && uwep->oartifact == ART_MJOLLNIR) wt += 500;
5662 if (u.twoweap && uswapwep && uswapwep->oartifact == ART_MJOLLNIR) wt += 500;
5663 if (uwep && uwep->oartifact == ART_FRISIA_S_TAIL) wt += 500;
5664 if (u.twoweap && uswapwep && uswapwep->oartifact == ART_FRISIA_S_TAIL) wt += 500;
5665 if (uwep && uwep->oartifact == ART_CAT_S_TAIL) wt += 500;
5666 if (u.twoweap && uswapwep && uswapwep->oartifact == ART_CAT_S_TAIL) wt += 500;
5667 if (uwep && uwep->oartifact == ART_OTHER_MJOLLNIR) wt += 500;
5668 if (u.twoweap && uswapwep && uswapwep->oartifact == ART_OTHER_MJOLLNIR) wt += 500;
5669 if (uwep && uwep->oartifact == ART_UNWIELDYTINE) wt += 200;
5670 if (u.twoweap && uswapwep && uswapwep->oartifact == ART_UNWIELDYTINE) wt += 200;
5672 /* Symbiotes can have a weight. If you're a symbiant, the weight is considerably lower; everyone else will get
5673 * a skill-dependant amount of weight added. At master and above, the weight no longer gets a multiplier --Amy
5674 * climacterial role has zero symbiote weight starting at XL5 */
5676 if (uinsymbiosis) wt += symbioteweight(u.usymbiote.mnum);
5678 if (u.martialstyle == MARTIALSTYLE_SILAT) {
5679 wt *= 3;
5680 wt /= 2;
5683 if (BurdenedState) wt *= 2;
5684 if (StrongBurdenedState) {
5685 /* add 2000 more, unless you have a low cap because being insta-overloaded with no way to fix it ain't fun --Amy */
5686 if (weight_cap() < 1000) wt += (weight_cap() * 2);
5687 else wt += 2000;
5690 wc = weight_cap();
5692 if ( (MeanBurdenEffect || u.uprops[MEAN_BURDEN_EFFECT].extrinsic || have_meanburdenstone() || autismringcheck(ART_KRATSCHEM_HARD) ) && (wt <= wc)) wt = (wc + 1);
5694 return (wt - wc);
5698 symbioteweight(symbiotetype)
5699 int symbiotetype;
5701 int xtraweight = 0;
5703 if (uinsymbiosis && !(Role_if(PM_CLIMACTERIAL) && u.ulevel >= 5)) {
5705 if (Role_if(PM_SYMBIANT)) {
5707 int symweight = 0;
5709 if (mons[symbiotetype].msize >= MZ_GIGANTIC) symweight += 100;
5710 else if (mons[symbiotetype].msize >= MZ_HUGE) symweight += 30;
5711 else if (mons[symbiotetype].msize >= MZ_LARGE) symweight += 10;
5712 if ((int) mons[symbiotetype].cwt > 99) symweight += ((int) mons[symbiotetype].cwt / 100);
5714 if (Race_if(PM_BABYLONIAN) && mons[symbiotetype].mlet == S_TURRET) symweight = 0;
5715 if (uarmf && itemhasappearance(uarmf, APP_REMORA_HEELS) && symbiotetype == PM_REMORA) symweight = 0;
5717 if (symweight < 0) symweight = 0; /* fail safe */
5718 xtraweight += symweight;
5720 } else {
5722 int symweight = 50; /* base weight even for weightless one */
5724 if (mons[symbiotetype].msize >= MZ_GIGANTIC) symweight += 1000;
5725 else if (mons[symbiotetype].msize >= MZ_HUGE) symweight += 300;
5726 else if (mons[symbiotetype].msize >= MZ_LARGE) symweight += 100;
5727 if ((int) mons[symbiotetype].cwt > 9) symweight += ((int) mons[symbiotetype].cwt / 10);
5729 /* goauld is special: they don't get a multiplier */
5730 if (Race_if(PM_GOAULD)) ;
5731 else if (!(PlayerCannotUseSkills)) {
5732 switch (P_SKILL(P_SYMBIOSIS)) {
5733 default: symweight *= 5; break;
5734 case P_BASIC: symweight *= 4; break;
5735 case P_SKILLED: symweight *= 3; break;
5736 case P_EXPERT: symweight *= 2; break;
5737 case P_MASTER: break;
5738 case P_GRAND_MASTER: break;
5739 case P_SUPREME_MASTER: break;
5741 } else symweight *= 5;
5743 if (Race_if(PM_BABYLONIAN) && mons[symbiotetype].mlet == S_TURRET) symweight = 0;
5744 if (uarmf && itemhasappearance(uarmf, APP_REMORA_HEELS) && symbiotetype == PM_REMORA) symweight = 0;
5746 if (symweight < 0) symweight = 0; /* fail safe */
5747 xtraweight += symweight;
5751 return xtraweight;
5756 * Returns 0 if below normal capacity, or the number of "capacity units"
5757 * over the normal capacity the player is loaded. Max is 5.
5760 calc_capacity(xtra_wt)
5761 int xtra_wt;
5763 int cap, wt = inv_weight() + xtra_wt;
5765 if (wt <= 0) return UNENCUMBERED;
5766 if (wc <= 1) return OVERLOADED;
5767 /* cap = (wt*2 / wc) + 1;*/
5768 cap = (wt / wc) + 1;
5769 return min(cap, OVERLOADED);
5773 near_capacity()
5775 return calc_capacity(0);
5779 max_capacity()
5781 int wt = inv_weight();
5783 /* return (wt - (2 * wc)); */
5784 return (wt - (4 * wc));
5787 boolean
5788 check_capacity(str)
5789 const char *str;
5791 if(near_capacity() >= EXT_ENCUMBER) {
5792 if(str)
5793 pline("%s", str);
5794 else
5795 You_cant("do that while carrying so much stuff.");
5797 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
5799 return 1;
5801 return 0;
5804 #endif /* OVL1 */
5805 #ifdef OVLB
5808 inv_cnt()
5810 register struct obj *otmp = invent;
5811 register int ct = 0;
5813 while(otmp){
5814 ct++;
5815 otmp = otmp->nobj;
5817 return(ct);
5820 #ifdef GOLDOBJ
5821 /* Counts the money in an object chain. */
5822 /* Intended use is for your or some monsters inventory, */
5823 /* now that u.gold/m.gold is gone.*/
5824 /* Counting money in a container might be possible too. */
5825 long
5826 money_cnt(otmp)
5827 struct obj *otmp;
5829 while(otmp) {
5830 /* Must change when silver & copper is implemented: */
5831 if (otmp->oclass == COIN_CLASS) return otmp->quan;
5832 otmp = otmp->nobj;
5834 return 0;
5836 #endif
5837 #endif /* OVLB */
5839 /*hack.c*/
5841 STATIC_PTR void
5842 set_litX(x,y,val)
5843 int x, y;
5844 void * val;
5846 if (val)
5847 levl[x][y].lit = 1;
5848 else {
5849 levl[x][y].lit = 0;
5850 snuff_light_source(x, y);
5854 /* will zorkmids be renamed to buckazoids? */
5855 boolean
5856 zapmrename()
5858 if (In_ZAPM(&u.uz) || Role_if(PM_SOFTWARE_ENGINEER) || Role_if(PM_CRACKER) || Role_if(PM_JANITOR) || Role_if(PM_SPACE_MARINE) || Role_if(PM_STORMBOY) || Role_if(PM_YAUTJA) || Role_if(PM_QUARTERBACK) || Role_if(PM_PSYKER) || Role_if(PM_EMPATH) || Role_if(PM_MASTERMIND) || Role_if(PM_WEIRDBOY) || Role_if(PM_ASTRONAUT) || Role_if(PM_CYBERNINJA) || Role_if(PM_DISSIDENT) || Race_if(PM_RETICULAN) || Race_if(PM_OUTSIDER) || Role_if(PM_XELNAGA)) return TRUE;
5860 return FALSE;