From f6b7be49f40c101363ae3b6f476c4dd06f30b95e Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Tue, 7 Dec 2021 00:06:17 +0200 Subject: [PATCH] Accessibility: give a message when teleporting a monster Teleporting a monster only updated the map. Give a message so blind players can get the same information. Making a monster invisible gives the same message, if you cannot detect invisible. Several other places where monsters teleported themselves now also give the same message. --- doc/fixes37.0 | 1 + include/extern.h | 7 +++--- include/hack.h | 6 +++++ src/allmain.c | 2 +- src/apply.c | 7 +++--- src/dig.c | 2 +- src/do.c | 6 ++--- src/dog.c | 6 ++--- src/dothrow.c | 2 +- src/hack.c | 2 +- src/mhitm.c | 2 +- src/mhitu.c | 6 ++--- src/minion.c | 2 +- src/mkmaze.c | 10 ++++---- src/mon.c | 26 ++++++++----------- src/monmove.c | 10 ++++---- src/mplayer.c | 2 +- src/muse.c | 4 +-- src/priest.c | 4 +-- src/shk.c | 11 ++++---- src/shknam.c | 2 +- src/steal.c | 8 +++--- src/steed.c | 2 +- src/teleport.c | 65 +++++++++++++++++++++++++++++++++++++++++------- src/uhitm.c | 17 +++++++------ src/vault.c | 14 +++++------ src/wizard.c | 12 ++++----- 27 files changed, 146 insertions(+), 92 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 4e37125ae..bfe6e5fb9 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -710,6 +710,7 @@ extend 3.6.1 fix to explicitly use name of unseen shopkeeper instead of "It" fix some inconsistencies with applied bullwhip vs monster polymorphing while wearing an amulet of strangulation from a form that wasn't vulnerable to one that was gave wrong message ("still constricts") +for accessibility reasons, give a message when monster teleports Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 15652b67b..fe5c2f6f5 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1454,9 +1454,9 @@ extern void killed(struct monst *); extern void xkilled(struct monst *, int); extern void mon_to_stone(struct monst *); extern void m_into_limbo(struct monst *); -extern void mnexto(struct monst *); +extern void mnexto(struct monst *, unsigned); extern void maybe_mnexto(struct monst *); -extern int mnearto(struct monst *, xchar, xchar, boolean); +extern int mnearto(struct monst *, xchar, xchar, boolean, unsigned); extern void m_respond(struct monst *); extern void setmangry(struct monst *, boolean); extern void wakeup(struct monst *, boolean); @@ -2576,7 +2576,8 @@ extern void domagicportal(struct trap *); extern void tele_trap(struct trap *); extern void level_tele_trap(struct trap *, unsigned); extern void rloc_to(struct monst *, int, int); -extern boolean rloc(struct monst *, boolean); +extern void rloc_to_flag(struct monst *, int, int, unsigned); +extern boolean rloc(struct monst *, unsigned); extern boolean tele_restrict(struct monst *); extern void mtele_trap(struct monst *, struct trap *, int); extern int mlevel_tele_trap(struct monst *, struct trap *, boolean, int); diff --git a/include/hack.h b/include/hack.h index 0d90867a3..8d651f211 100644 --- a/include/hack.h +++ b/include/hack.h @@ -442,6 +442,12 @@ typedef struct sortloot_item Loot; #define SUPPRESS_HISTORY 4 #define URGENT_MESSAGE 8 +/* rloc() flags */ +#define RLOC_NONE 0x00 +#define RLOC_ERR 0x01 /* allow impossible() if no rloc */ +#define RLOC_MSG 0x02 /* show vanish/appear msg */ +#define RLOC_NOMSG 0x04 /* prevent appear msg, even for STRAT_APPEARMSG */ + /* Lua callback functions */ enum nhcore_calls { NHCORE_START_NEW_GAME = 0, diff --git a/src/allmain.c b/src/allmain.c index 6b8d45fb8..fc7c7e399 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -690,7 +690,7 @@ newgame(void) check_special_room(FALSE); if (MON_AT(u.ux, u.uy)) - mnexto(m_at(u.ux, u.uy)); + mnexto(m_at(u.ux, u.uy), RLOC_NOMSG); (void) makedog(); docrt(); diff --git a/src/apply.c b/src/apply.c index 048b0536d..5b9c670b6 100644 --- a/src/apply.c +++ b/src/apply.c @@ -507,7 +507,8 @@ use_magic_whistle(struct obj *obj) if (M_AP_TYPE(mtmp)) seemimic(mtmp); omx = mtmp->mx, omy = mtmp->my; - mnexto(mtmp); + if (distu(omx, omy) > 2) + mnexto(mtmp, RLOC_MSG); if (mtmp->mx != omx || mtmp->my != omy) { mtmp->mundetected = 0; /* reveal non-mimic hider */ if (canspotmon(mtmp)) @@ -732,7 +733,7 @@ next_to_u(void) continue; if (mtmp->mleashed) { if (distu(mtmp->mx, mtmp->my) > 2) - mnexto(mtmp); + mnexto(mtmp, RLOC_NOMSG); if (distu(mtmp->mx, mtmp->my) > 2) { for (otmp = g.invent; otmp; otmp = otmp->nobj) if (otmp->otyp == LEASH @@ -994,7 +995,7 @@ use_mirror(struct obj *obj) freeinv(obj); (void) mpickobj(mtmp, obj); if (!tele_restrict(mtmp)) - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); } else if (!is_unicorn(mtmp->data) && !humanoid(mtmp->data) && (!mtmp->minvis || perceives(mtmp->data)) && rn2(5)) { boolean do_react = TRUE; diff --git a/src/dig.c b/src/dig.c index 8cb34e237..357c4d913 100644 --- a/src/dig.c +++ b/src/dig.c @@ -60,7 +60,7 @@ mkcavepos(xchar x, xchar y, int dist, boolean waslit, boolean rockit) return; /* don't cover the portal */ if ((mtmp = m_at(x, y)) != 0) /* make sure crucial monsters survive */ if (!passes_walls(mtmp->data)) - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_NOMSG); } else if (lev->typ == ROOM) return; diff --git a/src/do.c b/src/do.c index d35895bae..cde8a8e45 100644 --- a/src/do.c +++ b/src/do.c @@ -1255,7 +1255,7 @@ u_collide_m(struct monst *mtmp) && distu(cc.x, cc.y) <= 2) u_on_newpos(cc.x, cc.y); /*[maybe give message here?]*/ else - mnexto(mtmp); + mnexto(mtmp, RLOC_NOMSG); if ((mtmp = m_at(u.ux, u.uy)) != 0) { /* there was an unconditional impossible("mnexto failed") @@ -1263,7 +1263,7 @@ u_collide_m(struct monst *mtmp) with the situation, so only say something when debugging */ if (wizard) pline("(monster in hero's way)"); - if (!rloc(mtmp, TRUE) || (mtmp = m_at(u.ux, u.uy)) != 0) + if (!rloc(mtmp, RLOC_NOMSG) || (mtmp = m_at(u.ux, u.uy)) != 0) /* no room to move it; send it away, to return later */ m_into_limbo(mtmp); } @@ -1977,7 +1977,7 @@ revive_mon(anything *arg, long timeout UNUSED) boolean notice_it = canseemon(mtmp); /* before rloc() */ char *monname = Monnam(mtmp); - if (rloc(mtmp, TRUE)) { + if (rloc(mtmp, RLOC_NOMSG)) { if (notice_it && !canseemon(mtmp)) pline("%s vanishes.", monname); else if (!notice_it && canseemon(mtmp)) diff --git a/src/dog.c b/src/dog.c index 8dfcd590b..d41f5987f 100644 --- a/src/dog.c +++ b/src/dog.c @@ -348,7 +348,7 @@ mon_arrive(struct monst *mtmp, boolean with_you) && !rn2(mtmp->mtame ? 10 : mtmp->mpeaceful ? 5 : 2)) rloc_to(mtmp, u.ux, u.uy); else - mnexto(mtmp); + mnexto(mtmp, RLOC_NOMSG); return; } /* @@ -470,9 +470,9 @@ mon_arrive(struct monst *mtmp, boolean with_you) mtmp->mx = 0; /*(already is 0)*/ mtmp->my = xyflags; if (xlocale) - failed_to_place = !mnearto(mtmp, xlocale, ylocale, FALSE); + failed_to_place = !mnearto(mtmp, xlocale, ylocale, FALSE, RLOC_NOMSG); else - failed_to_place = !rloc(mtmp, TRUE); + failed_to_place = !rloc(mtmp, RLOC_NOMSG); if (failed_to_place) m_into_limbo(mtmp); /* try again next time hero comes to this level */ diff --git a/src/dothrow.c b/src/dothrow.c index 14b0c14e8..21af79406 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -2014,7 +2014,7 @@ gem_accept(register struct monst *mon, register struct obj *obj) if (!Blind) pline1(buf); if (!tele_restrict(mon)) - (void) rloc(mon, TRUE); + (void) rloc(mon, RLOC_MSG); return ret; } diff --git a/src/hack.c b/src/hack.c index 7c7dc0609..9b1625a7c 100644 --- a/src/hack.c +++ b/src/hack.c @@ -2497,7 +2497,7 @@ spoteffects(boolean pick) pline("%s attacks you by surprise!", Amonnam(mtmp)); break; } - mnexto(mtmp); /* have to move the monster */ + mnexto(mtmp, RLOC_NOMSG); /* have to move the monster */ } spotdone: if (!--inspoteffects) { diff --git a/src/mhitm.c b/src/mhitm.c index 11787acad..30ab74f37 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -1038,7 +1038,7 @@ mon_poly(struct monst *magr, struct monst *mdef, int dmg) if (magr == &g.youmonst) tele(); else if (!tele_restrict(magr)) - (void) rloc(magr, TRUE); + (void) rloc(magr, RLOC_MSG); } } else { if (g.vis && flags.verbose) diff --git a/src/mhitu.c b/src/mhitu.c index f12efe641..8038cde37 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -233,7 +233,7 @@ expels(struct monst *mtmp, } } unstuck(mtmp); /* ball&chain returned in unstuck() */ - mnexto(mtmp); + mnexto(mtmp, RLOC_NOMSG); newsym(u.ux, u.uy); spoteffects(TRUE); /* to cover for a case where mtmp is not in a next square */ @@ -1885,7 +1885,7 @@ doseduce(struct monst *mon) /* else no regret message if can't see or hear seducer */ if (!tele_restrict(mon)) - (void) rloc(mon, TRUE); + (void) rloc(mon, RLOC_MSG); return 1; } if (u.ualign.type == A_CHAOTIC) @@ -2018,7 +2018,7 @@ doseduce(struct monst *mon) if (!rn2(25)) mon->mcan = 1; /* monster is worn out */ if (!tele_restrict(mon)) - (void) rloc(mon, TRUE); + (void) rloc(mon, RLOC_MSG); return 1; } diff --git a/src/minion.c b/src/minion.c index 94fc3b6c5..50885709b 100644 --- a/src/minion.c +++ b/src/minion.c @@ -299,7 +299,7 @@ demon_talk(register struct monst *mtmp) else if (canseemon(mtmp)) pline("%s says something.", Amonnam(mtmp)); if (!tele_restrict(mtmp)) - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); return 1; } cash = money_cnt(g.invent); diff --git a/src/mkmaze.c b/src/mkmaze.c index c27385d35..32ef3bc9b 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -334,7 +334,7 @@ put_lregion_here( if ((mtmp = m_at(x, y)) != 0) { /* move the monster if no choice, or just try again */ if (oneshot) { - if (!rloc(mtmp, TRUE)) + if (!rloc(mtmp, RLOC_NOMSG)) m_into_limbo(mtmp); } else return FALSE; @@ -431,7 +431,7 @@ baalz_fixup(void) levl[x][y].typ = (levl[x][y].typ == TLWALL) ? BRCORNER : BLCORNER; levl[x][y + 1].typ = HWALL; if ((mtmp = m_at(x, y)) != 0) /* something at temporary pool... */ - (void) rloc(mtmp, FALSE); + (void) rloc(mtmp, RLOC_ERR|RLOC_NOMSG); } x = g.bughack.delarea.x2, y = g.bughack.delarea.y2; @@ -440,7 +440,7 @@ baalz_fixup(void) levl[x][y].typ = (levl[x][y].typ == TLWALL) ? TRCORNER : TLCORNER; levl[x][y - 1].typ = HWALL; if ((mtmp = m_at(x, y)) != 0) /* something at temporary pool... */ - (void) rloc(mtmp, FALSE); + (void) rloc(mtmp, RLOC_ERR|RLOC_NOMSG); } /* reset bughack region; set low end to so that @@ -1867,7 +1867,7 @@ mv_bubble(struct bubble* b, int dx, int dy, boolean ini) /* mnearto() might fail. We can jump right to elemental_clog from here rather than deal_with_overcrowding() */ - if (!mnearto(mon, cons->x, cons->y, TRUE)) + if (!mnearto(mon, cons->x, cons->y, TRUE, RLOC_NOMSG)) elemental_clog(mon); break; } @@ -1880,7 +1880,7 @@ mv_bubble(struct bubble* b, int dx, int dy, boolean ini) newsym(ux0, uy0); /* clean up old position */ if (mtmp) { - mnexto(mtmp); + mnexto(mtmp, RLOC_NOMSG); } break; } diff --git a/src/mon.c b/src/mon.c index a9f01a115..ca19ed4bc 100644 --- a/src/mon.c +++ b/src/mon.c @@ -750,7 +750,7 @@ minliquid_core(struct monst* mtmp) /* not fair...? hero doesn't automatically teleport away from lava, just from water */ if (can_teleport(mtmp->data) && !tele_restrict(mtmp)) { - if (rloc(mtmp, TRUE)) + if (rloc(mtmp, RLOC_MSG)) return 0; } if (!resists_fire(mtmp)) { @@ -783,7 +783,7 @@ minliquid_core(struct monst* mtmp) if (!DEADMONSTER(mtmp)) { (void) fire_damage_chain(mtmp->minvent, FALSE, FALSE, mtmp->mx, mtmp->my); - (void) rloc(mtmp, FALSE); + (void) rloc(mtmp, RLOC_ERR|RLOC_NOMSG); return 0; } return 1; @@ -798,7 +798,7 @@ minliquid_core(struct monst* mtmp) /* like hero with teleport intrinsic or spell, teleport away if possible */ if (can_teleport(mtmp->data) && !tele_restrict(mtmp)) { - if (rloc(mtmp, TRUE)) + if (rloc(mtmp, RLOC_MSG)) return 0; } if (cansee(mtmp->mx, mtmp->my)) { @@ -820,7 +820,7 @@ minliquid_core(struct monst* mtmp) xkilled(mtmp, XKILL_NOMSG); if (!DEADMONSTER(mtmp)) { water_damage_chain(mtmp->minvent, FALSE); - if (!rloc(mtmp, TRUE)) + if (!rloc(mtmp, RLOC_NOMSG)) deal_with_overcrowding(mtmp); return 0; } @@ -3256,10 +3256,9 @@ elemental_clog(struct monst* mon) /* make monster mtmp next to you (if possible); might place monst on far side of a wall or boulder */ void -mnexto(struct monst* mtmp) +mnexto(struct monst* mtmp, unsigned int rlocflags) { coord mm; - boolean couldspot = canspotmon(mtmp); if (mtmp == u.usteed) { /* Keep your steed in sync with you instead */ @@ -3272,13 +3271,7 @@ mnexto(struct monst* mtmp) deal_with_overcrowding(mtmp); return; } - rloc_to(mtmp, mm.x, mm.y); - if (!g.in_mklev && (mtmp->mstrategy & STRAT_APPEARMSG)) { - mtmp->mstrategy &= ~STRAT_APPEARMSG; /* one chance only */ - if (!couldspot && canspotmon(mtmp)) - pline("%s suddenly %s!", Amonnam(mtmp), - !Blind ? "appears" : "arrives"); - } + rloc_to_flag(mtmp, mm.x, mm.y, rlocflags); return; } @@ -3331,7 +3324,8 @@ mnearto( register struct monst *mtmp, xchar x, xchar y, - boolean move_other) /* make sure mtmp gets to x, y! so move m_at(x, y) */ + boolean move_other, /* make sure mtmp gets to x, y! so move m_at(x, y) */ + unsigned int rlocflags) { struct monst *othermon = (struct monst *) 0; xchar newx, newy; @@ -3371,11 +3365,11 @@ mnearto( newx = mm.x; newy = mm.y; } - rloc_to(mtmp, newx, newy); + rloc_to_flag(mtmp, newx, newy, rlocflags); if (move_other && othermon) { res = 2; /* moving another monster out of the way */ - if (!mnearto(othermon, x, y, FALSE)) /* no 'move_other' this time */ + if (!mnearto(othermon, x, y, FALSE, rlocflags)) /* no 'move_other' this time */ deal_with_overcrowding(othermon); } diff --git a/src/monmove.c b/src/monmove.c index 59158224a..c583305ff 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -481,7 +481,7 @@ dochug(register struct monst* mtmp) /* some monsters teleport */ if (mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz && !noteleport_level(mtmp)) { - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); return 0; } if (mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1)) @@ -538,7 +538,7 @@ dochug(register struct monst* mtmp) if (is_demon(g.youmonst.data)) { /* "Good hunting, brother" */ if (!tele_restrict(mtmp)) - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); } else { mtmp->minvis = mtmp->perminvis = 0; /* Why? For the same reason in real demon talk */ @@ -1077,9 +1077,9 @@ m_move(register struct monst* mtmp, register int after) if (ptr == &mons[PM_TENGU] && !rn2(5) && !mtmp->mcan && !tele_restrict(mtmp)) { if (mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2)) - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); else - mnexto(mtmp); + mnexto(mtmp, RLOC_MSG); mmoved = 1; goto postmov; } @@ -1402,7 +1402,7 @@ m_move(register struct monst* mtmp, register int after) mtmp->mtrack[0].y = omy; } else { if (is_unicorn(ptr) && rn2(2) && !tele_restrict(mtmp)) { - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); return 1; } /* for a long worm, shrink it (by discarding end of tail) when diff --git a/src/mplayer.c b/src/mplayer.c index b5e50c005..1cbd56b0a 100644 --- a/src/mplayer.c +++ b/src/mplayer.c @@ -123,7 +123,7 @@ mk_mplayer(struct permonst *ptr, xchar x, xchar y, boolean special) return ((struct monst *) 0); if (MON_AT(x, y)) - (void) rloc(m_at(x, y), FALSE); /* insurance */ + (void) rloc(m_at(x, y), RLOC_ERR|RLOC_NOMSG); /* insurance */ if (!In_endgame(&u.uz)) special = FALSE; diff --git a/src/muse.c b/src/muse.c index 2839dfd0b..9422efd4b 100644 --- a/src/muse.c +++ b/src/muse.c @@ -720,7 +720,7 @@ use_defensive(struct monst* mtmp) } if (oseen && how) makeknown(how); - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); return 2; case MUSE_WAN_TELEPORTATION: g.zap_oseen = oseen; @@ -1395,7 +1395,7 @@ mbhitm(register struct monst* mtmp, register struct obj* otmp) if (cansee(mtmp->mx, mtmp->my)) pline("%s resists the magic!", Monnam(mtmp)); } else if (!tele_restrict(mtmp)) - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); } break; #endif diff --git a/src/priest.c b/src/priest.c index e18e5e7e2..36a8cb984 100644 --- a/src/priest.c +++ b/src/priest.c @@ -232,7 +232,7 @@ priestini(d_level *lvl, struct mkroom *sroom, int sx, int sy, px = sx, py = sy; if (MON_AT(px, py)) - (void) rloc(m_at(px, py), FALSE); /* insurance */ + (void) rloc(m_at(px, py), RLOC_NOMSG); /* insurance */ priest = makemon(prim, px, py, MM_EPRI); if (priest) { @@ -672,7 +672,7 @@ mk_roamer(struct permonst *ptr, aligntyp alignment, xchar x, xchar y, #endif if (MON_AT(x, y)) - (void) rloc(m_at(x, y), FALSE); /* insurance */ + (void) rloc(m_at(x, y), RLOC_NOMSG); /* insurance */ if (!(roamer = makemon(ptr, x, y, MM_ADJACENTOK | MM_EMIN))) return (struct monst *) 0; diff --git a/src/shk.c b/src/shk.c index 1ac2a7926..cae3797ec 100644 --- a/src/shk.c +++ b/src/shk.c @@ -1046,7 +1046,7 @@ home_shk(register struct monst* shkp, register boolean killkops) { register xchar x = ESHK(shkp)->shk.x, y = ESHK(shkp)->shk.y; - (void) mnearto(shkp, x, y, TRUE); + (void) mnearto(shkp, x, y, TRUE, RLOC_MSG); g.level.flags.has_shop = 1; if (killkops) { kops_gone(TRUE); @@ -3440,7 +3440,8 @@ shkcatch(register struct obj* obj, register xchar x, register xchar y) && dist2(shkp->mx, shkp->my, x, y) < 3 /* if it is the shk's pos, you hit and anger him */ && (shkp->mx != x || shkp->my != y)) { - if (mnearto(shkp, x, y, TRUE) == 2 && !Deaf && !muteshk(shkp)) + if (mnearto(shkp, x, y, TRUE, RLOC_NOMSG) == 2 + && !Deaf && !muteshk(shkp)) verbalize("Out of my way, scum!"); if (cansee(x, y)) { pline("%s nimbly%s catches %s.", Shknam(shkp), @@ -4053,7 +4054,7 @@ shopdig(register int fall) #endif } if (distu(shkp->mx, shkp->my) > 2) { - mnexto(shkp); + mnexto(shkp, RLOC_MSG); /* for some reason the shopkeeper can't come next to you */ if (distu(shkp->mx, shkp->my) > 2) { if (lang == 2) @@ -4197,7 +4198,7 @@ pay_for_damage(const char* dmgstr, boolean cant_mollify) if (um_dist(shkp->mx, shkp->my, 1) && !um_dist(shkp->mx, shkp->my, 3)) { pline("%s leaps towards you!", Shknam(shkp)); - mnexto(shkp); + mnexto(shkp, RLOC_NOMSG); } pursue = um_dist(shkp->mx, shkp->my, 1); if (pursue) @@ -4226,7 +4227,7 @@ pay_for_damage(const char* dmgstr, boolean cant_mollify) growl(shkp); } } - (void) mnearto(shkp, x, y, TRUE); + (void) mnearto(shkp, x, y, TRUE, RLOC_MSG); } if ((um_dist(x, y, 1) && !uinshp) || cant_mollify diff --git a/src/shknam.c b/src/shknam.c index 97dcc7a45..2cdf0bf2f 100644 --- a/src/shknam.c +++ b/src/shknam.c @@ -632,7 +632,7 @@ shkinit(const struct shclass* shp, struct mkroom* sroom) } if (MON_AT(sx, sy)) - (void) rloc(m_at(sx, sy), FALSE); /* insurance */ + (void) rloc(m_at(sx, sy), RLOC_NOMSG); /* insurance */ /* now initialize the shopkeeper monster structure */ if (!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, MM_ESHK))) diff --git a/src/steal.c b/src/steal.c index 970f0f8af..b8be4d777 100644 --- a/src/steal.c +++ b/src/steal.c @@ -107,7 +107,7 @@ stealgold(register struct monst* mtmp) (Levitation || Flying) ? "beneath" : "between", whose, what); if (!ygold || !rn2(5)) { if (!tele_restrict(mtmp)) - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); monflee(mtmp, 0, FALSE, FALSE); } } else if (ygold) { @@ -123,7 +123,7 @@ stealgold(register struct monst* mtmp) add_to_minv(mtmp, ygold); Your("purse feels lighter."); if (!tele_restrict(mtmp)) - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); monflee(mtmp, 0, FALSE, FALSE); g.context.botl = 1; } @@ -186,7 +186,7 @@ stealarm(void) so we don't set mavenge bit here. */ monflee(mtmp, 0, FALSE, FALSE); if (!tele_restrict(mtmp)) - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); break; } } @@ -622,7 +622,7 @@ stealamulet(struct monst* mtmp) (void) mpickobj(mtmp, otmp); /* could merge and free otmp but won't */ pline("%s steals %s!", Monnam(mtmp), buf); if (can_teleport(mtmp->data) && !tele_restrict(mtmp)) - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); } } diff --git a/src/steed.c b/src/steed.c index f3b3f2904..f5c345763 100644 --- a/src/steed.c +++ b/src/steed.c @@ -602,7 +602,7 @@ dismount_steed( if (enexto(&cc, u.ux, u.uy, mtmp->data)) rloc_to(mtmp, cc.x, cc.y); else /* evidently no room nearby; move steed elsewhere */ - (void) rloc(mtmp, FALSE); + (void) rloc(mtmp, RLOC_ERR|RLOC_NOMSG); return; } diff --git a/src/teleport.c b/src/teleport.c index a996df016..6a5e99104 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -9,6 +9,7 @@ static boolean tele_jump_ok(int, int, int, int); static boolean teleok(int, int, boolean); static void vault_tele(void); static boolean rloc_pos_ok(int, int, struct monst *); +static void rloc_to_core(struct monst *, int, int, unsigned); static void mvault_tele(struct monst *); /* teleporting is prevented on this level for this monster? */ @@ -1201,16 +1202,31 @@ rloc_pos_ok( * a value because mtmp is a migrating_mon. Worm tails are always * placed randomly around the head of the worm. */ -void -rloc_to(struct monst* mtmp, register int x, register int y) +static void +rloc_to_core(struct monst* mtmp, + int x, int y, + unsigned int rlocflags) { register int oldx = mtmp->mx, oldy = mtmp->my; boolean resident_shk = mtmp->isshk && inhishop(mtmp); + boolean preventmsg = (rlocflags & RLOC_NOMSG) != 0; + boolean vanishmsg = (rlocflags & RLOC_MSG) != 0; + boolean appearmsg = (mtmp->mstrategy & STRAT_APPEARMSG) != 0; + boolean domsg = !g.in_mklev && (vanishmsg || appearmsg) && !preventmsg; + boolean telemsg = FALSE; if (x == mtmp->mx && y == mtmp->my && m_at(x, y) == mtmp) return; /* that was easy */ if (oldx) { /* "pick up" monster */ + if (domsg && canspotmon(mtmp)) { + if (couldsee(x, y) || sensemon(mtmp)) { + telemsg = TRUE; + } else { + pline("%s vanishes!", Monnam(mtmp)); + } + } + if (mtmp->wormno) { remove_worm(mtmp); } else { @@ -1238,6 +1254,24 @@ rloc_to(struct monst* mtmp, register int x, register int y) maybe_unhide_at(x, y); newsym(x, y); /* update new location */ set_apparxy(mtmp); /* orient monster */ + if (domsg && (canspotmon(mtmp) || appearmsg)) { + mtmp->mstrategy &= ~STRAT_APPEARMSG; /* one chance only */ + if (telemsg && (couldsee(x, y) || sensemon(mtmp))) { + pline("%s vanishes and reappears%s.", + Monnam(mtmp), + distu(x, y) <= 2 ? " next to you" + : (distu(x, y) <= (BOLT_LIM * BOLT_LIM)) ? " close by" + : (distu(x, y) < distu(oldx, oldy)) ? " closer to you" + : " further away"); + } else { + pline("%s %s%s%s!", + appearmsg ? Amonnam(mtmp) : Monnam(mtmp), + appearmsg ? "suddenly " : "", + !Blind ? "appears" : "arrives", + distu(x, y) <= 2 ? " next to you" + : (distu(x, y) <= (BOLT_LIM * BOLT_LIM)) ? " close by" : ""); + } + } /* shopkeepers will only teleport if you zap them with a wand of teleportation or if they've been transformed into a jumpy monster; @@ -1250,6 +1284,18 @@ rloc_to(struct monst* mtmp, register int x, register int y) (void) mintrap(mtmp); } +void +rloc_to(struct monst *mtmp, int x, int y) +{ + rloc_to_core(mtmp, x, y, RLOC_NOMSG); +} + +void +rloc_to_flag(struct monst *mtmp, int x, int y, unsigned int rlocflags) +{ + rloc_to_core(mtmp, x, y, rlocflags); +} + static stairway * stairway_find_forwiz(boolean isladder, boolean up) { @@ -1263,10 +1309,11 @@ stairway_find_forwiz(boolean isladder, boolean up) /* place a monster at a random location, typically due to teleport */ /* return TRUE if successful, FALSE if not */ +/* rlocflags is RLOC_foo flags */ boolean rloc( struct monst *mtmp, /* mx==0 implies migrating monster arrival */ - boolean suppress_impossible) + unsigned int rlocflags) { register int x, y, trycount; @@ -1312,12 +1359,12 @@ rloc( goto found_xy; /* level either full of monsters or somehow faulty */ - if (!suppress_impossible) + if ((rlocflags & RLOC_ERR) != 0) impossible("rloc(): couldn't relocate monster"); return FALSE; found_xy: - rloc_to(mtmp, x, y); + rloc_to_core(mtmp, x, y, rlocflags); return TRUE; } @@ -1331,7 +1378,7 @@ mvault_tele(struct monst* mtmp) rloc_to(mtmp, c.x, c.y); return; } - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_NONE); } boolean @@ -1364,7 +1411,7 @@ mtele_trap(struct monst* mtmp, struct trap* trap, int in_sight) if (trap->once) mvault_tele(mtmp); else - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_NONE); if (in_sight) { if (canseemon(mtmp)) @@ -1611,12 +1658,12 @@ u_teleport_mon(struct monst* mtmp, boolean give_feedback) if (give_feedback) You("are no longer inside %s!", mon_nam(mtmp)); unstuck(mtmp); - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); } else if (is_rider(mtmp->data) && rn2(13) && enexto(&cc, u.ux, u.uy, mtmp->data)) rloc_to(mtmp, cc.x, cc.y); else - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); return TRUE; } diff --git a/src/uhitm.c b/src/uhitm.c index 6d2ab7fa3..2d4bd577a 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -2318,7 +2318,8 @@ mhitm_ad_sgld(struct monst *magr, struct attack *mattk, struct monst *mdef, if (!tele_restrict(magr)) { boolean couldspot = canspotmon(magr); - (void) rloc(magr, TRUE); + (void) rloc(magr, RLOC_NOMSG); + /* TODO: use RLOC_MSG instead? */ if (g.vis && couldspot && !canspotmon(magr)) pline("%s suddenly disappears!", buf); } @@ -2412,7 +2413,8 @@ mhitm_ad_tlpt(struct monst *magr, struct attack *mattk, struct monst *mdef, if (g.vis && wasseen) Strcpy(mdef_Monnam, Monnam(mdef)); mdef->mstrategy &= ~STRAT_WAITFORU; - (void) rloc(mdef, TRUE); + (void) rloc(mdef, RLOC_NOMSG); + /* TODO: use RLOC_MSG instead? */ if (g.vis && wasseen && !canspotmon(mdef) && mdef != u.usteed) pline("%s suddenly disappears!", mdef_Monnam); if (mhm->damage >= mdef->mhp) { /* see hitmu(mhitu.c) */ @@ -3687,7 +3689,7 @@ mhitm_ad_heal(struct monst *magr, struct attack *mattk, struct monst *mdef, return; } else if (!rn2(33)) { if (!tele_restrict(magr)) - (void) rloc(magr, TRUE); + (void) rloc(magr, RLOC_MSG); monflee(magr, d(3, 6), TRUE, FALSE); mhm->done = TRUE; mhm->hitflags = MM_HIT | MM_DEF_DIED; /* return 3??? */ @@ -3966,7 +3968,7 @@ mhitm_ad_sedu(struct monst *magr, struct attack *mattk, struct monst *mdef, ? "brags about the goods some dungeon explorer provided" : "makes some remarks about how difficult theft is lately"); if (!tele_restrict(magr)) - (void) rloc(magr, TRUE); + (void) rloc(magr, RLOC_MSG); mhm->hitflags = MM_AGR_DONE; /* return 3??? */ mhm->done = TRUE; return; @@ -3978,7 +3980,7 @@ mhitm_ad_sedu(struct monst *magr, struct attack *mattk, struct monst *mdef, flags.female ? "unaffected" : "uninterested"); if (rn2(3)) { if (!tele_restrict(magr)) - (void) rloc(magr, TRUE); + (void) rloc(magr, RLOC_MSG); mhm->hitflags = MM_AGR_DONE; /* return 3??? */ mhm->done = TRUE; return; @@ -3995,7 +3997,7 @@ mhitm_ad_sedu(struct monst *magr, struct attack *mattk, struct monst *mdef, return; default: if (!is_animal(magr->data) && !tele_restrict(magr)) - (void) rloc(magr, TRUE); + (void) rloc(magr, RLOC_MSG); if (is_animal(magr->data) && *buf) { if (canseemon(magr)) pline("%s tries to %s away with %s.", Monnam(magr), @@ -4050,7 +4052,8 @@ mhitm_ad_sedu(struct monst *magr, struct attack *mattk, struct monst *mdef, if (pa->mlet == S_NYMPH && !tele_restrict(magr)) { boolean couldspot = canspotmon(magr); - (void) rloc(magr, TRUE); + (void) rloc(magr, RLOC_NOMSG); + /* TODO: use RLOC_MSG instead? */ if (g.vis && couldspot && !canspotmon(magr)) pline("%s suddenly disappears!", buf); } diff --git a/src/vault.c b/src/vault.c index 2c3ce3012..2e3300e38 100644 --- a/src/vault.c +++ b/src/vault.c @@ -75,7 +75,7 @@ clear_fcorr(struct monst *grd, boolean forceshow) } else { if (mtmp->mtame) yelp(mtmp); - if (!rloc(mtmp, TRUE)) + if (!rloc(mtmp, RLOC_MSG)) m_into_limbo(mtmp); } } @@ -607,7 +607,7 @@ wallify_vault(struct monst *grd) if ((mon = m_at(x, y)) != 0 && mon != grd) { if (mon->mtame) yelp(mon); - (void) rloc(mon, FALSE); + (void) rloc(mon, RLOC_ERR); } /* move gold at wall locations into the vault */ if ((gold = g_at(x, y)) != 0) { @@ -672,7 +672,7 @@ gd_mv_monaway(struct monst *grd, int nx, int ny) if (MON_AT(nx, ny) && !(nx == grd->mx && ny == grd->my)) { if (!Deaf) verbalize("Out of my way, scum!"); - if (!rloc(m_at(nx, ny), FALSE) || MON_AT(nx, ny)) + if (!rloc(m_at(nx, ny), RLOC_ERR|RLOC_MSG) || MON_AT(nx, ny)) m_into_limbo(m_at(nx, ny)); } } @@ -796,7 +796,7 @@ gd_move(struct monst *grd) if (!u_in_vault && (grd_in_vault || (in_fcorridor(grd, grd->mx, grd->my) && !in_fcorridor(grd, u.ux, u.uy)))) { - (void) rloc(grd, TRUE); + (void) rloc(grd, RLOC_MSG); wallify_vault(grd); if (!in_fcorridor(grd, grd->mx, grd->my)) (void) clear_fcorr(grd, TRUE); @@ -833,7 +833,7 @@ gd_move(struct monst *grd) n = grd->my; if (!Deaf) verbalize("You've been warned, knave!"); - mnexto(grd); + mnexto(grd, RLOC_NOMSG); levl[m][n].typ = egrd->fakecorr[0].ftyp; levl[m][n].flags = egrd->fakecorr[0].flags; newsym(m, n); @@ -850,7 +850,7 @@ gd_move(struct monst *grd) if (u_carry_gold) { /* player teleported */ m = grd->mx; n = grd->my; - (void) rloc(grd, TRUE); + (void) rloc(grd, RLOC_MSG); levl[m][n].typ = egrd->fakecorr[0].ftyp; levl[m][n].flags = egrd->fakecorr[0].flags; newsym(m, n); @@ -1111,7 +1111,7 @@ paygd(boolean silently) if (grd->mpeaceful) /* peaceful guard has no "right" to your gold */ goto remove_guard; - mnexto(grd); + mnexto(grd, RLOC_NOMSG); if (!silently) pline("%s remits your gold to the vault.", Monnam(grd)); gx = g.rooms[EGD(grd)->vroom].lx + rn2(2); diff --git a/src/wizard.c b/src/wizard.c index a82f1784b..5b33ca2b4 100644 --- a/src/wizard.c +++ b/src/wizard.c @@ -361,9 +361,9 @@ tactics(struct monst *mtmp) if (In_W_tower(mx, my, &u.uz) || (mtmp->iswiz && !sx && !mon_has_amulet(mtmp))) { if (!rn2(3 + mtmp->mhp / 10)) - (void) rloc(mtmp, TRUE); + (void) rloc(mtmp, RLOC_MSG); } else if (sx && (mx != sx || my != sy)) { - if (!mnearto(mtmp, sx, sy, TRUE)) { + if (!mnearto(mtmp, sx, sy, TRUE, RLOC_MSG)) { /* couldn't move to the target spot for some reason, so stay where we are (don't actually need rloc_to() because mtmp is still on the map at ... */ @@ -382,7 +382,7 @@ tactics(struct monst *mtmp) case STRAT_NONE: /* harass */ if (!rn2(!mtmp->mflee ? 5 : 33)) - mnexto(mtmp); + mnexto(mtmp, RLOC_MSG); return 0; default: /* kill, maim, pillage! */ @@ -397,7 +397,7 @@ tactics(struct monst *mtmp) } if ((u.ux == tx && u.uy == ty) || where == STRAT_PLAYER) { /* player is standing on it (or has it) */ - mnexto(mtmp); + mnexto(mtmp, RLOC_MSG); return 0; } if (where == STRAT_GROUND) { @@ -419,12 +419,12 @@ tactics(struct monst *mtmp) } else { /* a monster is standing on it - cause some trouble */ if (!rn2(5)) - mnexto(mtmp); + mnexto(mtmp, RLOC_MSG); return 0; } } else { /* a monster has it - 'port beside it. */ mx = mtmp->mx, my = mtmp->my; - if (!mnearto(mtmp, tx, ty, FALSE)) + if (!mnearto(mtmp, tx, ty, FALSE, RLOC_MSG)) rloc_to(mtmp, mx, my); /* no room? stay put */ return 0; }