void
domove()
{
- register struct monst *mtmp;
- register struct rm *tmpr;
- register xchar x,y;
+ register struct monst *mtmp;
+ register struct rm *tmpr;
+ register xchar x,y;
- struct trap *trap = (struct trap *)0;
+ struct trap *trap = NULL;
- int wtcap;
- boolean on_ice;
- xchar chainx, chainy, ballx, bally; /* ball&chain new positions */
- int bc_control; /* control for ball&chain */
- boolean cause_delay = FALSE; /* dragging ball will skip a move */
-
- u_wipe_engr(rnd(5));
-
- if (context.travel) {
- if (!findtravelpath(FALSE))
- (void) findtravelpath(TRUE);
- context.travel1 = 0;
- }
-
- if(((wtcap = near_capacity()) >= OVERLOADED
- || (wtcap > SLT_ENCUMBER &&
- (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
- : (u.uhp < 10 && u.uhp != u.uhpmax))))
- && !Is_airlevel(&u.uz)) {
- if(wtcap < OVERLOADED) {
- You("don't have enough stamina to move.");
- exercise(A_CON, FALSE);
- } else
- You("collapse under your load.");
- nomul(0);
- return;
- }
- if(u.uswallow) {
- u.dx = u.dy = 0;
- u.ux = x = u.ustuck->mx;
- u.uy = y = u.ustuck->my;
- mtmp = u.ustuck;
- } else {
- if (Is_airlevel(&u.uz) && rn2(4) &&
- !Levitation && !Flying) {
- switch(rn2(3)) {
- case 0:
- You("tumble in place.");
- exercise(A_DEX, FALSE);
- break;
- case 1:
- You_cant("control your movements very well."); break;
- case 2:
- pline("It's hard to walk in thin air.");
- exercise(A_DEX, TRUE);
- break;
- }
- return;
- }
-
- /* check slippery ice */
- on_ice = !Levitation && is_ice(u.ux, u.uy);
- if (on_ice) {
- static int skates = 0;
- if (!skates) skates = find_skates();
- if ((uarmf && uarmf->otyp == skates)
- || resists_cold(&youmonst) || Flying
- || is_floater(youmonst.data) || is_clinger(youmonst.data)
- || is_whirly(youmonst.data))
- on_ice = FALSE;
- else if (!rn2(Cold_resistance ? 3 : 2)) {
- HFumbling |= FROMOUTSIDE;
- HFumbling &= ~TIMEOUT;
- HFumbling += 1; /* slip on next move */
- }
- }
- if (!on_ice && (HFumbling & FROMOUTSIDE))
- HFumbling &= ~FROMOUTSIDE;
-
- x = u.ux + u.dx;
- y = u.uy + u.dy;
- if(Stunned || (Confusion && !rn2(5))) {
- register int tries = 0;
-
- do {
- if(tries++ > 50) {
- nomul(0);
- return;
- }
- confdir();
- x = u.ux + u.dx;
- y = u.uy + u.dy;
- } while(!isok(x, y) || bad_rock(youmonst.data, x, y));
- }
- /* turbulence might alter your actual destination */
- if (u.uinwater) {
- water_friction();
- if (!u.dx && !u.dy) {
- nomul(0);
- return;
- }
- x = u.ux + u.dx;
- y = u.uy + u.dy;
- }
- if(!isok(x, y)) {
- nomul(0);
- return;
- }
- if (((trap = t_at(x, y)) && trap->tseen) ||
- (Blind && !Levitation && !Flying &&
- !is_clinger(youmonst.data) &&
- is_pool_or_lava(x, y) && levl[x][y].seenv)) {
- if(context.run >= 2) {
- nomul(0);
- context.move = 0;
- return;
- } else
- nomul(0);
- }
-
- if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
- if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
- /* perhaps it fled (or was teleported or ... ) */
- u.ustuck = 0;
- } else if (sticks(youmonst.data)) {
- /* When polymorphed into a sticking monster,
- * u.ustuck means it's stuck to you, not you to it.
- */
- You("release %s.", mon_nam(u.ustuck));
- u.ustuck = 0;
- } else {
- /* If holder is asleep or paralyzed:
- * 37.5% chance of getting away,
- * 12.5% chance of waking/releasing it;
- * otherwise:
- * 7.5% chance of getting away.
- * [strength ought to be a factor]
- * If holder is tame and there is no conflict,
- * guaranteed escape.
- */
- switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
- case 0: case 1: case 2:
- pull_free:
- You("pull free from %s.", mon_nam(u.ustuck));
- u.ustuck = 0;
- break;
- case 3:
- if (!u.ustuck->mcanmove) {
- /* it's free to move on next turn */
- u.ustuck->mfrozen = 1;
- u.ustuck->msleeping = 0;
- }
- /*FALLTHRU*/
- default:
- if (u.ustuck->mtame &&
- !Conflict && !u.ustuck->mconf)
- goto pull_free;
- You("cannot escape from %s!", mon_nam(u.ustuck));
- nomul(0);
- return;
- }
- }
- }
-
- mtmp = m_at(x,y);
- if (mtmp) {
- /* Don't attack if you're running, and can see it */
- /* We should never get here if forcefight */
- if (context.run &&
- ((!Blind && mon_visible(mtmp) &&
- ((mtmp->m_ap_type != M_AP_FURNITURE &&
- mtmp->m_ap_type != M_AP_OBJECT) ||
- Protection_from_shape_changers)) ||
- sensemon(mtmp))) {
- nomul(0);
- context.move = 0;
- return;
- }
- }
- }
-
- u.ux0 = u.ux;
- u.uy0 = u.uy;
- bhitpos.x = x;
- bhitpos.y = y;
- tmpr = &levl[x][y];
-
- /* attack monster */
- if(mtmp) {
- nomul(0);
- /* only attack if we know it's there */
- /* or if we used the 'F' command to fight blindly */
- /* or if it hides_under, in which case we call attack() to print
- * the Wait! message.
- * This is different from ceiling hiders, who aren't handled in
- * attack().
- */
-
- /* If they used a 'm' command, trying to move onto a monster
- * prints the below message and wastes a turn. The exception is
- * if the monster is unseen and the player doesn't remember an
- * invisible monster--then, we fall through to attack() and
- * attack_check(), which still wastes a turn, but prints a
- * different message and makes the player remember the monster. */
- if(context.nopick &&
- (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))){
- if(mtmp->m_ap_type && !Protection_from_shape_changers
- && !sensemon(mtmp))
- stumble_onto_mimic(mtmp);
- else if (mtmp->mpeaceful && !Hallucination)
- pline("Pardon me, %s.", m_monnam(mtmp));
- else
- You("move right into %s.", mon_nam(mtmp));
- return;
- }
- if(context.forcefight || !mtmp->mundetected || sensemon(mtmp) ||
- ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL) &&
- !is_safepet(mtmp))){
- /* try to attack; note that it might evade */
- /* also, we don't attack tame when _safepet_ */
- if(attack(mtmp)) return;
- }
- }
-
- /* specifying 'F' with no monster wastes a turn */
- if (context.forcefight ||
- /* remembered an 'I' && didn't use a move command */
- (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
- struct obj *boulder = sobj_at(BOULDER, x, y);
- boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
- solid = !accessible(x, y);
- int glyph = glyph_at(x, y); /* might be monster */
- char buf[BUFSZ];
-
- /* if a statue is displayed at the target location,
- player is attempting to attack it [and boulder
- handlng below is suitable for handling that] */
- if (glyph_is_statue(glyph) ||
- (Hallucination && glyph_is_monster(glyph)))
- boulder = sobj_at(STATUE, x, y);
-
- /* force fight at boulder/statue or wall/door while wielding
- pick: start digging to break the boulder or wall */
- if (context.forcefight &&
- /* can we dig? */
- uwep && dig_typ(uwep, x, y) &&
- /* should we dig? */
- !glyph_is_invisible(glyph) &&
- !glyph_is_monster(glyph)) {
- (void)use_pick_axe2(uwep);
- return;
- }
-
- if (boulder)
- Strcpy(buf, ansimpleoname(boulder));
- else if (solid)
- Strcpy(buf, the(defsyms[glyph_to_cmap(glyph)].explanation));
- else if (!Underwater)
- Strcpy(buf, "thin air");
- else if (is_pool(x, y))
- Strcpy(buf, "empty water");
- else /* Underwater, targetting non-water */
- Sprintf(buf, "a vacant spot on the %s", surface(x,y));
- You("%s%s %s.",
- !(boulder || solid) ? "" :
- !explo ? "harmlessly " : "futilely ",
- explo ? "explode at" : "attack",
- buf);
- unmap_object(x, y); /* known empty -- remove 'I' if present */
- if (boulder) map_object(boulder, TRUE);
- newsym(x, y);
- nomul(0);
- if (explo) {
- wake_nearby();
- u.mh = -1; /* dead in the current form */
- rehumanize();
- }
- return;
- }
- if (glyph_is_invisible(levl[x][y].glyph)) {
- unmap_object(x, y);
- newsym(x, y);
- }
- /* not attacking an animal, so we try to move */
- if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
- nomul(0);
- return;
- }
- if(!youmonst.data->mmove) {
- You("are rooted %s.",
- Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
- "in place" : "to the ground");
- nomul(0);
- return;
- }
- if(u.utrap) {
- if (!trapmove(x, y, trap)) return;
- }
-
- if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, DO_MOVE)) {
- context.move = 0;
- nomul(0);
- return;
- }
-
- /* Move ball and chain. */
- if (Punished)
- if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy,
- &cause_delay, TRUE))
- return;
-
- /* Check regions entering/leaving */
- if (!in_out_region(x,y))
- return;
-
- /* now move the hero */
- mtmp = m_at(x, y);
- u.ux += u.dx;
- u.uy += u.dy;
- /* Move your steed, too */
- if (u.usteed) {
- u.usteed->mx = u.ux;
- u.usteed->my = u.uy;
- exercise_steed();
- }
-
- /*
- * If safepet at destination then move the pet to the hero's
- * previous location using the same conditions as in attack().
- * there are special extenuating circumstances:
- * (1) if the pet dies then your god angers,
- * (2) if the pet gets trapped then your god may disapprove,
- * (3) if the pet was already trapped and you attempt to free it
- * not only do you encounter the trap but you may frighten your
- * pet causing it to go wild! moral: don't abuse this privilege.
- *
- * Ceiling-hiding pets are skipped by this section of code, to
- * be caught by the normal falling-monster code.
- */
- if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
- /* if trapped, there's a chance the pet goes wild */
- if (mtmp->mtrapped) {
- if (!rn2(mtmp->mtame)) {
- mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
- if (mtmp->mleashed) m_unleash(mtmp, TRUE);
- growl(mtmp);
- } else {
- yelp(mtmp);
- }
- }
- mtmp->mundetected = 0;
- if (mtmp->m_ap_type) seemimic(mtmp);
- else if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my);
-
- if (mtmp->mtrapped &&
- (trap = t_at(mtmp->mx, mtmp->my)) != 0 &&
- (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) &&
- sobj_at(BOULDER, trap->tx, trap->ty)) {
- /* can't swap places with pet pinned in a pit by a boulder */
- u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
- } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
- /* can't swap places when pet can't move to your spot */
- u.ux = u.ux0, u.uy = u.uy0;
- You("stop. %s can't move diagonally.",
- upstart(y_monnam(mtmp)));
- } else if (u.ux0 != x && u.uy0 != y &&
- bad_rock(mtmp->data, x, u.uy0) &&
- bad_rock(mtmp->data, u.ux0, y) &&
- (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
- /* can't swap places when pet won't fit thru the opening */
- u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
- You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
- } else {
- char pnambuf[BUFSZ];
-
- /* save its current description in case of polymorph */
- Strcpy(pnambuf, y_monnam(mtmp));
- mtmp->mtrapped = 0;
- remove_monster(x, y);
- place_monster(mtmp, u.ux0, u.uy0);
- newsym(x, y);
- newsym(u.ux0, u.uy0);
-
- You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
- pnambuf);
-
- /* check for displacing it into pools and traps */
- switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
- case 0:
- break;
- case 1: /* trapped */
- case 3: /* changed levels */
- /* there's already been a trap message, reinforce it */
- abuse_dog(mtmp);
- adjalign(-3);
- break;
- case 2:
- /* drowned or died...
- * you killed your pet by direct action, so get experience
- * and possibly penalties;
- * we want the level gain message, if it happens, to occur
- * before the guilt message below
- */
- {
- /* minliquid() and mintrap() call mondead() rather than
- killed() so we duplicate some of the latter here */
- int tmp, mndx;
-
- u.uconduct.killer++;
- mndx = monsndx(mtmp->data);
- tmp = experience(mtmp, (int)mvitals[mndx].died);
- more_experienced(tmp, 0);
- newexplevel(); /* will decide if you go up */
- }
- /* That's no way to treat a pet! Your god gets angry.
- *
- * [This has always been pretty iffy. Why does your
- * patron deity care at all, let alone enough to get mad?]
- */
- if (rn2(4)) {
- You_feel("guilty about losing your pet like this.");
- u.ugangr++;
- adjalign(-15);
- }
- break;
- default:
- pline("that's strange, unknown mintrap result!");
- break;
- }
- }
- }
-
- reset_occupations();
- if (context.run) {
- if ( context.run < 8 )
- if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) ||
- IS_FURNITURE(tmpr->typ))
- nomul(0);
- }
-
- if (hides_under(youmonst.data) || (youmonst.data->mlet == S_EEL) ||
- u.dx || u.dy)
- (void) hideunder(&youmonst);
-
- /*
- * Mimics (or whatever) become noticeable if they move and are
- * imitating something that doesn't move. We could extend this
- * to non-moving monsters...
- */
- if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
- || youmonst.m_ap_type == M_AP_FURNITURE))
- youmonst.m_ap_type = M_AP_NOTHING;
-
- check_leash(u.ux0,u.uy0);
-
- if(u.ux0 != u.ux || u.uy0 != u.uy) {
- u.umoved = TRUE;
- /* Clean old position -- vision_recalc() will print our new one. */
- newsym(u.ux0,u.uy0);
- /* Since the hero has moved, adjust what can be seen/unseen. */
- vision_recalc(1); /* Do the work now in the recover time. */
- invocation_message();
- }
-
- if (Punished) /* put back ball and chain */
- move_bc(0,bc_control,ballx,bally,chainx,chainy);
-
- spoteffects(TRUE);
-
- /* delay next move because of ball dragging */
- /* must come after we finished picking up, in spoteffects() */
- if (cause_delay) {
- nomul(-2);
+ int wtcap;
+ boolean on_ice;
+ xchar chainx, chainy, ballx, bally; /* ball&chain new positions */
+ int bc_control; /* control for ball&chain */
+ boolean cause_delay = FALSE; /* dragging ball will skip a move */
+
+ u_wipe_engr(rnd(5));
+
+ if (context.travel) {
+ if (!findtravelpath(FALSE))
+ (void) findtravelpath(TRUE);
+ context.travel1 = 0;
+ }
+
+ if(((wtcap = near_capacity()) >= OVERLOADED
+ || (wtcap > SLT_ENCUMBER &&
+ (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
+ : (u.uhp < 10 && u.uhp != u.uhpmax))))
+ && !Is_airlevel(&u.uz)) {
+ if(wtcap < OVERLOADED) {
+ You("don't have enough stamina to move.");
+ exercise(A_CON, FALSE);
+ } else
+ You("collapse under your load.");
+ nomul(0);
+ return;
+ }
+ if(u.uswallow) {
+ u.dx = u.dy = 0;
+ u.ux = x = u.ustuck->mx;
+ u.uy = y = u.ustuck->my;
+ mtmp = u.ustuck;
+ } else {
+ if (Is_airlevel(&u.uz) && rn2(4) &&
+ !Levitation && !Flying) {
+ switch(rn2(3)) {
+ case 0:
+ You("tumble in place.");
+ exercise(A_DEX, FALSE);
+ break;
+ case 1:
+ You_cant("control your movements very well."); break;
+ case 2:
+ pline("It's hard to walk in thin air.");
+ exercise(A_DEX, TRUE);
+ break;
+ }
+ return;
+ }
+
+ /* check slippery ice */
+ on_ice = !Levitation && is_ice(u.ux, u.uy);
+ if (on_ice) {
+ static int skates = 0;
+ if (!skates) skates = find_skates();
+ if ((uarmf && uarmf->otyp == skates)
+ || resists_cold(&youmonst) || Flying
+ || is_floater(youmonst.data) || is_clinger(youmonst.data)
+ || is_whirly(youmonst.data))
+ on_ice = FALSE;
+ else if (!rn2(Cold_resistance ? 3 : 2)) {
+ HFumbling |= FROMOUTSIDE;
+ HFumbling &= ~TIMEOUT;
+ HFumbling += 1; /* slip on next move */
+ }
+ }
+ if (!on_ice && (HFumbling & FROMOUTSIDE))
+ HFumbling &= ~FROMOUTSIDE;
+
+ x = u.ux + u.dx;
+ y = u.uy + u.dy;
+ if(Stunned || (Confusion && !rn2(5))) {
+ register int tries = 0;
+
+ do {
+ if(tries++ > 50) {
+ nomul(0);
+ return;
+ }
+ confdir();
+ x = u.ux + u.dx;
+ y = u.uy + u.dy;
+ } while(!isok(x, y) || bad_rock(youmonst.data, x, y));
+ }
+ /* turbulence might alter your actual destination */
+ if (u.uinwater) {
+ water_friction();
+ if (!u.dx && !u.dy) {
+ nomul(0);
+ return;
+ }
+ x = u.ux + u.dx;
+ y = u.uy + u.dy;
+ }
+ if(!isok(x, y)) {
+ nomul(0);
+ return;
+ }
+ if (((trap = t_at(x, y)) && trap->tseen) ||
+ (Blind && !Levitation && !Flying &&
+ !is_clinger(youmonst.data) &&
+ is_pool_or_lava(x, y) && levl[x][y].seenv)) {
+ if(context.run >= 2) {
+ nomul(0);
+ context.move = 0;
+ return;
+ } else
+ nomul(0);
+ }
+
+ if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
+ if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
+ /* perhaps it fled (or was teleported or ... ) */
+ u.ustuck = 0;
+ } else if (sticks(youmonst.data)) {
+ /* When polymorphed into a sticking monster,
+ * u.ustuck means it's stuck to you, not you to it.
+ */
+ You("release %s.", mon_nam(u.ustuck));
+ u.ustuck = 0;
+ } else {
+ /* If holder is asleep or paralyzed:
+ * 37.5% chance of getting away,
+ * 12.5% chance of waking/releasing it;
+ * otherwise:
+ * 7.5% chance of getting away.
+ * [strength ought to be a factor]
+ * If holder is tame and there is no conflict,
+ * guaranteed escape.
+ */
+ switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
+ case 0: case 1: case 2:
+ pull_free:
+ You("pull free from %s.", mon_nam(u.ustuck));
+ u.ustuck = 0;
+ break;
+ case 3:
+ if (!u.ustuck->mcanmove) {
+ /* it's free to move on next turn */
+ u.ustuck->mfrozen = 1;
+ u.ustuck->msleeping = 0;
+ }
+ /*FALLTHRU*/
+ default:
+ if (u.ustuck->mtame &&
+ !Conflict && !u.ustuck->mconf)
+ goto pull_free;
+ You("cannot escape from %s!", mon_nam(u.ustuck));
+ nomul(0);
+ return;
+ }
+ }
+ }
+
+ mtmp = m_at(x,y);
+ if (mtmp) {
+ /* Don't attack if you're running, and can see it */
+ /* We should never get here if forcefight */
+ if (context.run &&
+ ((!Blind && mon_visible(mtmp) &&
+ ((mtmp->m_ap_type != M_AP_FURNITURE &&
+ mtmp->m_ap_type != M_AP_OBJECT) ||
+ Protection_from_shape_changers)) ||
+ sensemon(mtmp))) {
+ nomul(0);
+ context.move = 0;
+ return;
+ }
+ }
+ }
+
+ u.ux0 = u.ux;
+ u.uy0 = u.uy;
+ bhitpos.x = x;
+ bhitpos.y = y;
+ tmpr = &levl[x][y];
+
+ /* attack monster */
+ if(mtmp) {
+ nomul(0);
+ /* only attack if we know it's there */
+ /* or if we used the 'F' command to fight blindly */
+ /* or if it hides_under, in which case we call attack() to print
+ * the Wait! message.
+ * This is different from ceiling hiders, who aren't handled in
+ * attack().
+ */
+
+ /* If they used a 'm' command, trying to move onto a monster
+ * prints the below message and wastes a turn. The exception is
+ * if the monster is unseen and the player doesn't remember an
+ * invisible monster--then, we fall through to attack() and
+ * attack_check(), which still wastes a turn, but prints a
+ * different message and makes the player remember the monster. */
+ if(context.nopick &&
+ (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))){
+ if(mtmp->m_ap_type && !Protection_from_shape_changers
+ && !sensemon(mtmp))
+ stumble_onto_mimic(mtmp);
+ else if (mtmp->mpeaceful && !Hallucination)
+ pline("Pardon me, %s.", m_monnam(mtmp));
+ else
+ You("move right into %s.", mon_nam(mtmp));
+ return;
+ }
+ if(context.forcefight || !mtmp->mundetected || sensemon(mtmp) ||
+ ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL) &&
+ !is_safepet(mtmp))){
+ /* try to attack; note that it might evade */
+ /* also, we don't attack tame when _safepet_ */
+ if(attack(mtmp)) return;
+ }
+ }
+
+ /* specifying 'F' with no monster wastes a turn */
+ if (context.forcefight ||
+ /* remembered an 'I' && didn't use a move command */
+ (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
+ struct obj *boulder = sobj_at(BOULDER, x, y);
+ boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
+ solid = !accessible(x, y);
+ int glyph = glyph_at(x, y); /* might be monster */
+ char buf[BUFSZ];
+
+ /* if a statue is displayed at the target location,
+ player is attempting to attack it [and boulder
+ handlng below is suitable for handling that] */
+ if (glyph_is_statue(glyph) ||
+ (Hallucination && glyph_is_monster(glyph)))
+ boulder = sobj_at(STATUE, x, y);
+
+ /* force fight at boulder/statue or wall/door while wielding
+ pick: start digging to break the boulder or wall */
+ if (context.forcefight &&
+ /* can we dig? */
+ uwep && dig_typ(uwep, x, y) &&
+ /* should we dig? */
+ !glyph_is_invisible(glyph) &&
+ !glyph_is_monster(glyph)) {
+ (void)use_pick_axe2(uwep);
+ return;
+ }
+
+ if (boulder)
+ Strcpy(buf, ansimpleoname(boulder));
+ else if (solid)
+ Strcpy(buf, the(defsyms[glyph_to_cmap(glyph)].explanation));
+ else if (!Underwater)
+ Strcpy(buf, "thin air");
+ else if (is_pool(x, y))
+ Strcpy(buf, "empty water");
+ else /* Underwater, targetting non-water */
+ Sprintf(buf, "a vacant spot on the %s", surface(x,y));
+ You("%s%s %s.",
+ !(boulder || solid) ? "" :
+ !explo ? "harmlessly " : "futilely ",
+ explo ? "explode at" : "attack",
+ buf);
+ unmap_object(x, y); /* known empty -- remove 'I' if present */
+ if (boulder) map_object(boulder, TRUE);
+ newsym(x, y);
+ nomul(0);
+ if (explo) {
+ wake_nearby();
+ u.mh = -1; /* dead in the current form */
+ rehumanize();
+ }
+ return;
+ }
+ if (glyph_is_invisible(levl[x][y].glyph)) {
+ unmap_object(x, y);
+ newsym(x, y);
+ }
+ /* not attacking an animal, so we try to move */
+ if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
+ nomul(0);
+ return;
+ }
+ if(!youmonst.data->mmove) {
+ You("are rooted %s.",
+ Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
+ "in place" : "to the ground");
+ nomul(0);
+ return;
+ }
+ if(u.utrap) {
+ if (!trapmove(x, y, trap)) return;
+ }
+
+ if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, DO_MOVE)) {
+ context.move = 0;
+ nomul(0);
+ return;
+ }
+
+ /* Move ball and chain. */
+ if (Punished)
+ if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy,
+ &cause_delay, TRUE))
+ return;
+
+ /* Check regions entering/leaving */
+ if (!in_out_region(x,y))
+ return;
+
+ /* now move the hero */
+ mtmp = m_at(x, y);
+ u.ux += u.dx;
+ u.uy += u.dy;
+ /* Move your steed, too */
+ if (u.usteed) {
+ u.usteed->mx = u.ux;
+ u.usteed->my = u.uy;
+ exercise_steed();
+ }
+
+ /*
+ * If safepet at destination then move the pet to the hero's
+ * previous location using the same conditions as in attack().
+ * there are special extenuating circumstances:
+ * (1) if the pet dies then your god angers,
+ * (2) if the pet gets trapped then your god may disapprove,
+ * (3) if the pet was already trapped and you attempt to free it
+ * not only do you encounter the trap but you may frighten your
+ * pet causing it to go wild! moral: don't abuse this privilege.
+ *
+ * Ceiling-hiding pets are skipped by this section of code, to
+ * be caught by the normal falling-monster code.
+ */
+ if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
+ /* if trapped, there's a chance the pet goes wild */
+ if (mtmp->mtrapped) {
+ if (!rn2(mtmp->mtame)) {
+ mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
+ if (mtmp->mleashed) m_unleash(mtmp, TRUE);
+ growl(mtmp);
+ } else {
+ yelp(mtmp);
+ }
+ }
+ mtmp->mundetected = 0;
+ if (mtmp->m_ap_type) seemimic(mtmp);
+ else if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my);
+
+ if (mtmp->mtrapped &&
+ (trap = t_at(mtmp->mx, mtmp->my)) != 0 &&
+ (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) &&
+ sobj_at(BOULDER, trap->tx, trap->ty)) {
+ /* can't swap places with pet pinned in a pit by a boulder */
+ u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
+ } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
+ /* can't swap places when pet can't move to your spot */
+ u.ux = u.ux0, u.uy = u.uy0;
+ You("stop. %s can't move diagonally.",
+ upstart(y_monnam(mtmp)));
+ } else if (u.ux0 != x && u.uy0 != y &&
+ bad_rock(mtmp->data, x, u.uy0) &&
+ bad_rock(mtmp->data, u.ux0, y) &&
+ (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
+ /* can't swap places when pet won't fit thru the opening */
+ u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
+ You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
+ } else {
+ char pnambuf[BUFSZ];
+
+ /* save its current description in case of polymorph */
+ Strcpy(pnambuf, y_monnam(mtmp));
+ mtmp->mtrapped = 0;
+ remove_monster(x, y);
+ place_monster(mtmp, u.ux0, u.uy0);
+ newsym(x, y);
+ newsym(u.ux0, u.uy0);
+
+ You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
+ pnambuf);
+
+ /* check for displacing it into pools and traps */
+ switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
+ case 0:
+ break;
+ case 1: /* trapped */
+ case 3: /* changed levels */
+ /* there's already been a trap message, reinforce it */
+ abuse_dog(mtmp);
+ adjalign(-3);
+ break;
+ case 2:
+ /* drowned or died...
+ * you killed your pet by direct action, so get experience
+ * and possibly penalties;
+ * we want the level gain message, if it happens, to occur
+ * before the guilt message below
+ */
+ {
+ /* minliquid() and mintrap() call mondead() rather than
+ killed() so we duplicate some of the latter here */
+ int tmp, mndx;
+
+ u.uconduct.killer++;
+ mndx = monsndx(mtmp->data);
+ tmp = experience(mtmp, (int)mvitals[mndx].died);
+ more_experienced(tmp, 0);
+ newexplevel(); /* will decide if you go up */
+ }
+ /* That's no way to treat a pet! Your god gets angry.
+ *
+ * [This has always been pretty iffy. Why does your
+ * patron deity care at all, let alone enough to get mad?]
+ */
+ if (rn2(4)) {
+ You_feel("guilty about losing your pet like this.");
+ u.ugangr++;
+ adjalign(-15);
+ }
+ break;
+ default:
+ pline("that's strange, unknown mintrap result!");
+ break;
+ }
+ }
+ }
+
+ reset_occupations();
+ if (context.run) {
+ if ( context.run < 8 )
+ if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) ||
+ IS_FURNITURE(tmpr->typ))
+ nomul(0);
+ }
+
+ if (hides_under(youmonst.data) || (youmonst.data->mlet == S_EEL) ||
+ u.dx || u.dy)
+ (void) hideunder(&youmonst);
+
+ /*
+ * Mimics (or whatever) become noticeable if they move and are
+ * imitating something that doesn't move. We could extend this
+ * to non-moving monsters...
+ */
+ if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
+ || youmonst.m_ap_type == M_AP_FURNITURE))
+ youmonst.m_ap_type = M_AP_NOTHING;
+
+ check_leash(u.ux0,u.uy0);
+
+ if(u.ux0 != u.ux || u.uy0 != u.uy) {
+ u.umoved = TRUE;
+ /* Clean old position -- vision_recalc() will print our new one. */
+ newsym(u.ux0,u.uy0);
+ /* Since the hero has moved, adjust what can be seen/unseen. */
+ vision_recalc(1); /* Do the work now in the recover time. */
+ invocation_message();
+ }
+
+ if (Punished) /* put back ball and chain */
+ move_bc(0,bc_control,ballx,bally,chainx,chainy);
+
+ spoteffects(TRUE);
+
+ /* delay next move because of ball dragging */
+ /* must come after we finished picking up, in spoteffects() */
+ if (cause_delay) {
+ nomul(-2);
multi_reason = "dragging an iron ball";
- nomovemsg = "";
- }
-
- if (context.run && flags.runmode != RUN_TPORT) {
- /* display every step or every 7th step depending upon mode */
- if (flags.runmode != RUN_LEAP || !(moves % 7L)) {
- if (flags.time) context.botl = 1;
- curs_on_u();
- delay_output();
- if (flags.runmode == RUN_CRAWL) {
- delay_output();
- delay_output();
- delay_output();
- delay_output();
- }
- }
- }
+ nomovemsg = "";
+ }
+
+ if (context.run && flags.runmode != RUN_TPORT) {
+ /* display every step or every 7th step depending upon mode */
+ if (flags.runmode != RUN_LEAP || !(moves % 7L)) {
+ if (flags.time) context.botl = 1;
+ curs_on_u();
+ delay_output();
+ if (flags.runmode == RUN_CRAWL) {
+ delay_output();
+ delay_output();
+ delay_output();
+ delay_output();
+ }
+ }
+ }
}
/* combat increases metabolism */