-/* NetHack 3.6 dogmove.c $NHDT-Date: 1446604109 2015/11/04 02:28:29 $ $NHDT-Branch: master $:$NHDT-Revision: 1.56 $ */
+/* NetHack 3.6 dogmove.c $NHDT-Date: 1557094801 2019/05/05 22:20:01 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.74 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
+/* JNetHack Copyright */
+/* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020 */
+/* JNetHack may be freely redistributed. See license for details. */
+
#include "hack.h"
#include "mfndpos.h"
STATIC_DCL boolean FDECL(dog_hunger, (struct monst *, struct edog *));
STATIC_DCL int FDECL(dog_invent, (struct monst *, struct edog *, int));
STATIC_DCL int FDECL(dog_goal, (struct monst *, struct edog *, int, int, int));
+STATIC_DCL struct monst *FDECL(find_targ, (struct monst *, int, int, int));
+STATIC_OVL int FDECL(find_friends, (struct monst *, struct monst *, int));
+STATIC_DCL struct monst *FDECL(best_target, (struct monst *));
+STATIC_DCL long FDECL(score_targ, (struct monst *, struct monst *));
STATIC_DCL boolean FDECL(can_reach_location, (struct monst *, XCHAR_P,
XCHAR_P, XCHAR_P, XCHAR_P));
STATIC_DCL boolean FDECL(could_reach_item, (struct monst *, XCHAR_P, XCHAR_P));
boolean devour;
{
register struct edog *edog = EDOG(mtmp);
- boolean poly, grow, heal, slimer, deadmimic;
+ boolean poly, grow, heal, eyes, slimer, deadmimic;
int nutrit;
long oprice;
char objnambuf[BUFSZ];
poly = polyfodder(obj);
grow = mlevelgain(obj);
heal = mhealup(obj);
+ eyes = (obj->otyp == CARROT);
if (devour) {
if (mtmp->meating > 1)
pet eats visible food. */
if (sawpet || (seeobj && canspotmon(mtmp))) {
if (tunnels(mtmp->data))
+/*JP
pline("%s digs in.", noit_Monnam(mtmp));
+*/
+ pline("%s\82Í\8c@\82Á\82Ä\82¢\82é\81D", noit_Monnam(mtmp));
else
+#if 0 /*JP:T*/
pline("%s %s %s.", noit_Monnam(mtmp),
devour ? "devours" : "eats", distant_name(obj, doname));
+#else
+ pline("%s\82Í%s\82ð%s\82¢\82é\81D", noit_Monnam(mtmp),
+ distant_name(obj, doname), devour ? "\88ù\82Ý\8d\9e\82ñ\82Å" : "\90H\82×\82Ä");
+#endif
} else if (seeobj)
+#if 0 /*JP:T*/
pline("It %s %s.", devour ? "devours" : "eats",
distant_name(obj, doname));
+#else
+ pline("\82»\82ê\82Í%s\82ð%s\82¢\82é\81D", distant_name(obj, doname),
+ devour ? "\88ù\82Ý\8d\9e\82ñ\82Å" : "\90H\82×\82Ä");
+#endif
}
if (obj->unpaid) {
Strcpy(objnambuf, xname(obj));
iflags.suppress_price--;
}
- /* It's a reward if it's DOGFOOD and the player dropped/threw it. */
- /* We know the player had it if invlet is set -dlc */
+ /* It's a reward if it's DOGFOOD and the player dropped/threw it.
+ We know the player had it if invlet is set. -dlc */
if (dogfood(mtmp, obj) == DOGFOOD && obj->invlet)
#ifdef LINT
edog->apport = 0;
obj->oerodeproof = 0;
mtmp->mstun = 1;
if (canseemon(mtmp) && flags.verbose) {
+#if 0 /*JP:T*/
pline("%s spits %s out in disgust!", Monnam(mtmp),
distant_name(obj, doname));
+#else
+ pline("%s\82Í%s\82ð\83y\83b\82Æ\93f\82«\8fo\82µ\82½\81I", Monnam(mtmp),
+ distant_name(obj,doname));
+#endif
}
} else if (obj == uball) {
unpunish();
/* edible item owned by shop has been thrown or kicked
by hero and caught by tame or food-tameable monst */
oprice = unpaid_cost(obj, TRUE);
+#if 0 /*JP:T*/
pline("That %s will cost you %ld %s.", objnambuf, oprice,
currency(oprice));
+#else
+ pline("\82 \82Ì%s\82Í%ld%s\82¾\81D", objnambuf, oprice,
+ currency(oprice));
+#endif
/* delobj->obfree will handle actual shop billing update */
}
delobj(obj);
/* turning into slime might be cureable */
if (slimer && munslime(mtmp, FALSE)) {
/* but the cure (fire directed at self) might be fatal */
- if (mtmp->mhp < 1)
+ if (DEADMONSTER(mtmp))
return 2;
slimer = FALSE; /* sliming is avoided, skip polymorph */
}
}
if (heal)
mtmp->mhp = mtmp->mhpmax;
+ if ((eyes || heal) && !mtmp->mcansee)
+ mcureblindness(mtmp, canseemon(mtmp));
if (deadmimic)
quickmimic(mtmp);
return 1;
/* hunger effects -- returns TRUE on starvation */
STATIC_OVL boolean
dog_hunger(mtmp, edog)
-register struct monst *mtmp;
-register struct edog *edog;
+struct monst *mtmp;
+struct edog *edog;
{
if (monstermoves > edog->hungrytime + 500) {
if (!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) {
mtmp->mhpmax = newmhpmax;
if (mtmp->mhp > mtmp->mhpmax)
mtmp->mhp = mtmp->mhpmax;
- if (mtmp->mhp < 1)
+ if (DEADMONSTER(mtmp))
goto dog_died;
if (cansee(mtmp->mx, mtmp->my))
+/*JP
pline("%s is confused from hunger.", Monnam(mtmp));
+*/
+ pline("%s\82Í\8bó\95 \82Ì\82½\82ß\8d¬\97\90\82µ\82Ä\82¢\82é\81D", Monnam(mtmp));
else if (couldsee(mtmp->mx, mtmp->my))
beg(mtmp);
else
+/*JP
You_feel("worried about %s.", y_monnam(mtmp));
+*/
+ You("%s\82ª\90S\94z\82É\82È\82Á\82½\81D", y_monnam(mtmp));
stop_occupation();
- } else if (monstermoves > edog->hungrytime + 750 || mtmp->mhp < 1) {
- dog_died:
+ } else if (monstermoves > edog->hungrytime + 750
+ || DEADMONSTER(mtmp)) {
+ dog_died:
if (mtmp->mleashed && mtmp != u.usteed)
+/*JP
Your("leash goes slack.");
+*/
+ Your("\95R\82Í\82½\82é\82ñ\82¾\81D");
else if (cansee(mtmp->mx, mtmp->my))
+/*JP
pline("%s starves.", Monnam(mtmp));
+*/
+ pline("%s\82Í\8bQ\82¦\82Å\8e\80\82ñ\82¾\81D", Monnam(mtmp));
else
+#if 0 /*JP:T*/
You_feel("%s for a moment.",
Hallucination ? "bummed" : "sad");
+#else
+ You("%s\8bC\95ª\82É\82¨\82»\82í\82ê\82½\81D",
+ Hallucination ? "\82ª\82Á\82©\82è\82µ\82½" : "\94ß\82µ\82¢");
+#endif
mondied(mtmp);
return TRUE;
}
omx = mtmp->mx;
omy = mtmp->my;
- /* if we are carrying something then we drop it (perhaps near @) */
- /* Note: if apport == 1 then our behaviour is independent of udist */
- /* Use udist+1 so steed won't cause divide by zero */
+ /* If we are carrying something then we drop it (perhaps near @).
+ * Note: if apport == 1 then our behaviour is independent of udist.
+ * Use udist+1 so steed won't cause divide by zero.
+ */
if (droppables(mtmp)) {
if (!rn2(udist + 1) || !rn2(edog->apport))
if (rn2(10) < edog->apport) {
edog->droptime = monstermoves;
}
} else {
- if ((obj = level.objects[omx][omy]) && !index(nofetch, obj->oclass)
+ if ((obj = level.objects[omx][omy]) != 0
+ && !index(nofetch, obj->oclass)
#ifdef MAIL
&& obj->otyp != SCR_MAIL
#endif
if (carryamt != obj->quan)
otmp = splitobj(obj, carryamt);
if (cansee(omx, omy) && flags.verbose)
+#if 0 /*JP:T*/
pline("%s picks up %s.", Monnam(mtmp),
distant_name(otmp, doname));
+#else
+ pline("%s\82Í%s\82ð\8fE\82Á\82½\81D", Monnam(mtmp),
+ distant_name(obj, doname));
+#endif
obj_extract_self(otmp);
newsym(omx, omy);
(void) mpickobj(mtmp, otmp);
return 0;
}
-/* set dog's goal -- gtyp, gx, gy
+/* set dog's goal -- gtyp, gx, gy;
returns -1/0/1 (dog's desire to approach player) or -2 (abort move) */
STATIC_OVL int
dog_goal(mtmp, edog, after, udist, whappr)
appr = 1;
}
/* if you have dog food it'll follow you more closely */
- if (appr == 0) {
- obj = invent;
- while (obj) {
+ if (appr == 0)
+ for (obj = invent; obj; obj = obj->nobj)
if (dogfood(mtmp, obj) == DOGFOOD) {
appr = 1;
break;
}
- obj = obj->nobj;
- }
- }
} else
appr = 1; /* gtyp != UNDEF */
if (mtmp->mconf)
} else {
/* assume master hasn't moved far, and reuse previous goal */
if (edog && edog->ogoal.x
- && ((edog->ogoal.x != omx) || (edog->ogoal.y != omy))) {
+ && (edog->ogoal.x != omx || edog->ogoal.y != omy)) {
gx = edog->ogoal.x;
gy = edog->ogoal.y;
edog->ogoal.x = 0;
return appr;
}
+STATIC_OVL struct monst *
+find_targ(mtmp, dx, dy, maxdist)
+register struct monst *mtmp;
+int dx, dy;
+int maxdist;
+{
+ struct monst *targ = 0;
+ int curx = mtmp->mx, cury = mtmp->my;
+ int dist = 0;
+
+ /* Walk outwards */
+ for ( ; dist < maxdist; ++dist) {
+ curx += dx;
+ cury += dy;
+ if (!isok(curx, cury))
+ break;
+
+ /* FIXME: Check if we hit a wall/door/boulder to
+ * short-circuit unnecessary subsequent checks
+ */
+
+ /* If we can't see up to here, forget it - will this
+ * mean pets in corridors don't breathe at monsters
+ * in rooms? If so, is that necessarily bad?
+ */
+ if (!m_cansee(mtmp, curx, cury))
+ break;
+
+ if (curx == mtmp->mux && cury == mtmp->muy)
+ return &youmonst;
+
+ if ((targ = m_at(curx, cury)) != 0) {
+ /* Is the monster visible to the pet? */
+ if ((!targ->minvis || perceives(mtmp->data))
+ && !targ->mundetected)
+ break;
+ /* If the pet can't see it, it assumes it aint there */
+ targ = 0;
+ }
+ }
+ return targ;
+}
+
+STATIC_OVL int
+find_friends(mtmp, mtarg, maxdist)
+struct monst *mtmp, *mtarg;
+int maxdist;
+{
+ struct monst *pal;
+ int dx = sgn(mtarg->mx - mtmp->mx),
+ dy = sgn(mtarg->my - mtmp->my);
+ int curx = mtarg->mx, cury = mtarg->my;
+ int dist = distmin(mtarg->mx, mtarg->my, mtmp->mx, mtmp->my);
+
+ for ( ; dist <= maxdist; ++dist) {
+ curx += dx;
+ cury += dy;
+
+ if (!isok(curx, cury))
+ return 0;
+
+ /* If the pet can't see beyond this point, don't
+ * check any farther
+ */
+ if (!m_cansee(mtmp, curx, cury))
+ return 0;
+
+ /* Does pet think you're here? */
+ if (mtmp->mux == curx && mtmp->muy == cury)
+ return 1;
+
+ pal = m_at(curx, cury);
+
+ if (pal) {
+ if (pal->mtame) {
+ /* Pet won't notice invisible pets */
+ if (!pal->minvis || perceives(mtmp->data))
+ return 1;
+ } else {
+ /* Quest leaders and guardians are always seen */
+ if (pal->data->msound == MS_LEADER
+ || pal->data->msound == MS_GUARDIAN)
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+STATIC_OVL long
+score_targ(mtmp, mtarg)
+struct monst *mtmp, *mtarg;
+{
+ long score = 0L;
+
+ /* If the monster is confused, normal scoring is disrupted -
+ * anything may happen
+ */
+
+ /* Give 1 in 3 chance of safe breathing even if pet is confused or
+ * if you're on the quest start level */
+ if (!mtmp->mconf || !rn2(3) || Is_qstart(&u.uz)) {
+ int mtmp_lev;
+ aligntyp align1 = A_NONE, align2 = A_NONE; /* For priests, minions */
+ boolean faith1 = TRUE, faith2 = TRUE;
+
+ if (mtmp->isminion)
+ align1 = EMIN(mtmp)->min_align;
+ else if (mtmp->ispriest)
+ align1 = EPRI(mtmp)->shralign;
+ else
+ faith1 = FALSE;
+ if (mtarg->isminion)
+ align2 = EMIN(mtarg)->min_align; /* MAR */
+ else if (mtarg->ispriest)
+ align2 = EPRI(mtarg)->shralign; /* MAR */
+ else
+ faith2 = FALSE;
+
+ /* Never target quest friendlies */
+ if (mtarg->data->msound == MS_LEADER
+ || mtarg->data->msound == MS_GUARDIAN)
+ return -5000L;
+ /* D: Fixed angelic beings using gaze attacks on coaligned priests */
+ if (faith1 && faith2 && align1 == align2 && mtarg->mpeaceful) {
+ score -= 5000L;
+ return score;
+ }
+ /* Is monster adjacent? */
+ if (distmin(mtmp->mx, mtmp->my, mtarg->mx, mtarg->my) <= 1) {
+ score -= 3000L;
+ return score;
+ }
+ /* Is the monster peaceful or tame? */
+ if (/*mtarg->mpeaceful ||*/ mtarg->mtame || mtarg == &youmonst) {
+ /* Pets will never be targeted */
+ score -= 3000L;
+ return score;
+ }
+ /* Is master/pet behind monster? Check up to 15 squares beyond pet. */
+ if (find_friends(mtmp, mtarg, 15)) {
+ score -= 3000L;
+ return score;
+ }
+ /* Target hostile monsters in preference to peaceful ones */
+ if (!mtarg->mpeaceful)
+ score += 10;
+ /* Is the monster passive? Don't waste energy on it, if so */
+ if (mtarg->data->mattk[0].aatyp == AT_NONE)
+ score -= 1000;
+ /* Even weak pets with breath attacks shouldn't take on very
+ low-level monsters. Wasting breath on lichens is ridiculous. */
+ if ((mtarg->m_lev < 2 && mtmp->m_lev > 5)
+ || (mtmp->m_lev > 12 && mtarg->m_lev < mtmp->m_lev - 9
+ && u.ulevel > 8 && mtarg->m_lev < u.ulevel - 7))
+ score -= 25;
+ /* for strength purposes, a vampshifter in weak form (vampire bat,
+ fog cloud, maybe wolf) will attack as if in vampire form;
+ otherwise if won't do much and usually wouldn't suffer enough
+ damage (from counterattacks) to switch back to vampire form;
+ make it be more aggressive by behaving as if stronger */
+ mtmp_lev = mtmp->m_lev;
+ if (is_vampshifter(mtmp) && mtmp->data->mlet != S_VAMPIRE) {
+ /* is_vampshifter() implies (mtmp->cham >= LOW_PM) */
+ mtmp_lev = mons[mtmp->cham].mlevel;
+ /* actual vampire level would range from 1.0*mlvl to 1.5*mlvl */
+ mtmp_lev += rn2(mtmp_lev / 2 + 1);
+ /* we don't expect actual level in weak form to exceed
+ base level of strong form, but handle that if it happens */
+ if (mtmp->m_lev > mtmp_lev)
+ mtmp_lev = mtmp->m_lev;
+ }
+ /* And pets will hesitate to attack vastly stronger foes.
+ This penalty will be discarded if master's in trouble. */
+ if (mtarg->m_lev > mtmp_lev + 4L)
+ score -= (mtarg->m_lev - mtmp_lev) * 20L;
+ /* All things being the same, go for the beefiest monster. This
+ bonus should not be large enough to override the pet's aversion
+ to attacking much stronger monsters. */
+ score += mtarg->m_lev * 2 + mtarg->mhp / 3;
+ }
+ /* Fuzz factor to make things less predictable when very
+ similar targets are abundant. */
+ score += rnd(5);
+ /* Pet may decide not to use ranged attack when confused */
+ if (mtmp->mconf && !rn2(3))
+ score -= 1000;
+ return score;
+}
+
+STATIC_OVL struct monst *
+best_target(mtmp)
+struct monst *mtmp; /* Pet */
+{
+ int dx, dy;
+ long bestscore = -40000L, currscore;
+ struct monst *best_targ = 0, *temp_targ = 0;
+
+ /* Help! */
+ if (!mtmp)
+ return 0;
+
+ /* If the pet is blind, it's not going to see any target */
+ if (!mtmp->mcansee)
+ return 0;
+
+ /* Search for any monsters lined up with the pet, within an arbitrary
+ * distance from the pet (7 squares, even along diagonals). Monsters
+ * are assigned scores and the best score is chosen.
+ */
+ for (dy = -1; dy < 2; ++dy) {
+ for (dx = -1; dx < 2; ++dx) {
+ if (!dx && !dy)
+ continue;
+ /* Traverse the line to find the first monster within 7
+ * squares. Invisible monsters are skipped (if the
+ * pet doesn't have see invisible).
+ */
+ temp_targ = find_targ(mtmp, dx, dy, 7);
+
+ /* Nothing in this line? */
+ if (!temp_targ)
+ continue;
+
+ /* Decide how attractive the target is */
+ currscore = score_targ(mtmp, temp_targ);
+
+ if (currscore > bestscore) {
+ bestscore = currscore;
+ best_targ = temp_targ;
+ }
+ }
+ }
+
+ /* Filter out targets the pet doesn't like */
+ if (bestscore < 0L)
+ best_targ = 0;
+
+ return best_targ;
+}
+
/* return 0 (no move), 1 (move) or 2 (dead) */
int
dog_move(mtmp, after)
register struct monst *mtmp;
-register int after; /* this is extra fast monster movement */
+int after; /* this is extra fast monster movement */
{
int omx, omy; /* original mtmp position */
int appr, whappr, udist;
if (!Conflict && !mtmp->mconf
&& mtmp == u.ustuck && !sticks(youmonst.data)) {
unstuck(mtmp); /* swallowed case handled above */
+/*JP
You("get released!");
+*/
+ You("\93®\82¯\82é\82æ\82¤\82É\82È\82Á\82½\81I");
}
#endif
if (!nohands(mtmp->data) && !verysmall(mtmp->data)) {
&& better_with_displacing && !undesirable_disp(mtmp, nx, ny)) {
int mstatus;
register struct monst *mtmp2 = m_at(nx, ny);
+
mstatus = mdisplacem(mtmp, mtmp2, FALSE); /* displace monster */
if (mstatus & MM_DEF_DIED)
return 2;
if (mtmp->mleashed) {
if (!Deaf)
whimper(mtmp);
- } else
+ } else {
/* 1/40 chance of stepping on it anyway, in case
* it has to pass one to follow the player...
*/
if (trap->tseen && rn2(40))
- continue;
+ continue;
+ }
}
}
/* (minion isn't interested; `cursemsg' stays FALSE) */
if (has_edog)
for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere) {
- if (obj->cursed)
+ if (obj->cursed) {
cursemsg[i] = TRUE;
- else if ((otyp = dogfood(mtmp, obj)) < MANFOOD
+ } else if ((otyp = dogfood(mtmp, obj)) < MANFOOD
&& (otyp < ACCFOOD
|| edog->hungrytime <= monstermoves)) {
/* Note: our dog likes the food so much that he
continue;
/* lessen the chance of backtracking to previous position(s) */
- k = has_edog ? uncursedcnt : cnt;
- for (j = 0; j < MTSZ && j < k - 1; j++)
- if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
- if (rn2(MTSZ * (k - j)))
- goto nxti;
+ /* This causes unintended issues for pets trying to follow
+ the hero. Thus, only run it if not leashed and >5 tiles
+ away. */
+ if (!mtmp->mleashed && distmin(mtmp->mx, mtmp->my, u.ux, u.uy) > 5) {
+ k = has_edog ? uncursedcnt : cnt;
+ for (j = 0; j < MTSZ && j < k - 1; j++)
+ if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
+ if (rn2(MTSZ * (k - j)))
+ goto nxti;
+ }
j = ((ndist = GDIST(nx, ny)) - nidist) * appr;
if ((j == 0 && !rn2(++chcnt)) || j < 0
chcnt = 0;
chi = i;
}
- nxti:
+ nxti:
;
}
-newdogpos:
+
+ /* Pet hasn't attacked anything but is considering moving -
+ * now's the time for ranged attacks. Note that the pet can move
+ * after it performs its ranged attack. Should this be changed?
+ */
+ {
+ struct monst *mtarg;
+ int hungry = 0;
+
+ /* How hungry is the pet? */
+ if (!mtmp->isminion) {
+ struct edog *dog = EDOG(mtmp);
+
+ hungry = (monstermoves > (dog->hungrytime + 300));
+ }
+
+ /* Identify the best target in a straight line from the pet;
+ * if there is such a target, we'll let the pet attempt an
+ * attack.
+ */
+ mtarg = best_target(mtmp);
+
+ /* Hungry pets are unlikely to use breath/spit attacks */
+ if (mtarg && (!hungry || !rn2(5))) {
+ int mstatus;
+
+ if (mtarg == &youmonst) {
+ if (mattacku(mtmp))
+ return 2;
+ } else {
+ mstatus = mattackm(mtmp, mtarg);
+
+ /* Shouldn't happen, really */
+ if (mstatus & MM_AGR_DIED)
+ return 2;
+
+ /* Allow the targeted nasty to strike back - if
+ * the targeted beast doesn't have a ranged attack,
+ * nothing will happen.
+ */
+ if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED)
+ && rn2(4) && mtarg != &youmonst) {
+
+ /* Can monster see? If it can, it can retaliate
+ * even if the pet is invisible, since it'll see
+ * the direction from which the ranged attack came;
+ * if it's blind or unseeing, it can't retaliate
+ */
+ if (mtarg->mcansee && haseyes(mtarg->data)) {
+ mstatus = mattackm(mtarg, mtmp);
+ if (mstatus & MM_DEF_DIED)
+ return 2;
+ }
+ }
+ }
+ }
+ }
+
+ newdogpos:
if (nix != omx || niy != omy) {
- struct obj *mw_tmp;
boolean wasseen;
if (info[chi] & ALLOW_U) {
if (mtmp->mleashed) { /* play it safe */
+#if 0 /*JP:T*/
pline("%s breaks loose of %s leash!", Monnam(mtmp),
mhis(mtmp));
+#else
+ pline("%s\82Í\8e©\95ª\82É\82Â\82¢\82Ä\82¢\82é\95R\82ð\82Í\82¸\82µ\82½\81I",
+ Monnam(mtmp));
+#endif
m_unleash(mtmp, FALSE);
}
(void) mattacku(mtmp);
}
if (!m_in_out_region(mtmp, nix, niy))
return 1;
- if (((IS_ROCK(levl[nix][niy].typ) && may_dig(nix, niy))
- || closed_door(nix, niy))
- && mtmp->weapon_check != NO_WEAPON_WANTED
- && tunnels(mtmp->data) && needspick(mtmp->data)) {
- if (closed_door(nix, niy)) {
- if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)
- || !is_axe(mw_tmp))
- mtmp->weapon_check = NEED_PICK_OR_AXE;
- } else if (IS_TREE(levl[nix][niy].typ)) {
- if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
- mtmp->weapon_check = NEED_AXE;
- } else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
- mtmp->weapon_check = NEED_PICK_AXE;
- }
- if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp))
- return 0;
- }
+ if (m_digweapon_check(mtmp, nix,niy))
+ return 0;
+
/* insert a worm_move() if worms ever begin to eat things */
wasseen = canseemon(mtmp);
remove_monster(omx, omy);
place_monster(mtmp, nix, niy);
- if (cursemsg[chi] && (wasseen || canseemon(mtmp)))
- pline("%s moves only reluctantly.", noit_Monnam(mtmp));
+ if (cursemsg[chi] && (wasseen || canseemon(mtmp))) {
+ /* describe top item of pile, not necessarily cursed item itself;
+ don't use glyph_at() here--it would return the pet but we want
+ to know whether an object is remembered at this map location */
+ struct obj *o = (!Hallucination && level.flags.hero_memory
+ && glyph_is_object(levl[nix][niy].glyph))
+ ? vobj_at(nix, niy) : 0;
+ const char *what = o ? distant_name(o, doname) : something;
+
+#if 0 /*JP:T*/
+ pline("%s %s reluctantly over %s.", noit_Monnam(mtmp),
+ vtense((char *) 0, locomotion(mtmp->data, "step")), what);
+#else
+ pline("%s\82Í%s\82Ì\8fã\82É\82¢\82â\82¢\82â\93®\82¢\82½\81D", noit_Monnam(mtmp), what);
+#endif
+ }
for (j = MTSZ - 1; j > 0; j--)
mtmp->mtrack[j] = mtmp->mtrack[j - 1];
mtmp->mtrack[0].x = omx;
mtmp->mtrack[0].y = omy;
- /* We have to know if the pet's gonna do a combined eat and
+ /* We have to know if the pet's going to do a combined eat and
* move before moving it, but it can't eat until after being
* moved. Thus the do_eat flag.
*/
}
cc.x = mtmp->mx;
cc.y = mtmp->my;
- dognext:
+ dognext:
if (!m_in_out_region(mtmp, nix, niy))
return 1;
remove_monster(mtmp->mx, mtmp->my);
return FALSE;
}
-/*ARGSUSED*/ /* do_clear_area client */
+/* do_clear_area client */
STATIC_PTR void
wantdoor(x, y, distance)
int x, y;
genericptr_t distance;
{
- int ndist;
+ int ndist, *dist_ptr = (int *) distance;
- if (*(int *) distance > (ndist = distu(x, y))) {
+ if (*dist_ptr > (ndist = distu(x, y))) {
gx = x;
gy = y;
- *(int *) distance = ndist;
+ *dist_ptr = ndist;
}
}
struct monst *mtmp;
{
mtmp->meating = 0;
- if (mtmp->m_ap_type && mtmp->mappearance && mtmp->cham == NON_PM) {
+ if (M_AP_TYPE(mtmp) && mtmp->mappearance && mtmp->cham == NON_PM) {
/* was eating a mimic and now appearance needs resetting */
mtmp->m_ap_type = 0;
mtmp->mappearance = 0;
if (Protection_from_shape_changers || !mtmp->meating)
return;
+ /* with polymorph, the steed's equipment would be re-checked and its
+ saddle would come off, triggering DISMOUNT_FELL, but mimicking
+ doesn't impact monster's equipment; normally DISMOUNT_POLY is for
+ rider taking on an unsuitable shape, but its message works fine
+ for this and also avoids inflicting damage during forced dismount;
+ do this before changing so that dismount refers to original shape */
+ if (mtmp == u.usteed)
+ dismount_steed(DISMOUNT_POLY);
+
do {
idx = rn2(SIZE(qm));
if (qm[idx].mndx != 0 && monsndx(mtmp->data) == qm[idx].mndx)
(on the other hand, perhaps you're sensing a brief glimpse
of its mind as it changes form) */
newsym(mtmp->mx, mtmp->my);
- You("%s %s appear where %s was!",
- cansee(mtmp->mx, mtmp->my) ? "see" : "sense",
+#if 0 /*JP:T*/
+ You("%s %s %sappear%s where %s was!",
+ cansee(mtmp->mx, mtmp->my) ? "see" : "sense that",
+ (M_AP_TYPE(mtmp) == M_AP_FURNITURE)
+ ? an(defsyms[mtmp->mappearance].explanation)
+ : (M_AP_TYPE(mtmp) == M_AP_OBJECT
+ && OBJ_DESCR(objects[mtmp->mappearance]))
+ ? an(OBJ_DESCR(objects[mtmp->mappearance]))
+ : (M_AP_TYPE(mtmp) == M_AP_OBJECT
+ && OBJ_NAME(objects[mtmp->mappearance]))
+ ? an(OBJ_NAME(objects[mtmp->mappearance]))
+ : (M_AP_TYPE(mtmp) == M_AP_MONSTER)
+ ? an(mons[mtmp->mappearance].mname)
+ : something,
+ cansee(mtmp->mx, mtmp->my) ? "" : "has ",
+ cansee(mtmp->mx, mtmp->my) ? "" : "ed",
+ buf);
+#else
+ You("%s\82ª\82 \82Á\82½\82Æ\82±\82ë\82É%s\82ª\8c»\82ê\82½\82Ì%s\81I",
+ buf,
(mtmp->m_ap_type == M_AP_FURNITURE)
? an(defsyms[mtmp->mappearance].explanation)
: (mtmp->m_ap_type == M_AP_OBJECT
: (mtmp->m_ap_type == M_AP_MONSTER)
? an(mons[mtmp->mappearance].mname)
: something,
- buf);
+ cansee(mtmp->mx, mtmp->my) ? "\82ð\8c©\82½" : "\82É\8bC\82Ã\82¢\82½");
+#endif
display_nhwindow(WIN_MAP, TRUE);
}
}