M_AP_MONSTER = 3 /* a monster; mostly used for cloned Wizard */
};
+ #define MON_FLOOR 0x00
+ #define MON_OFFMAP 0x01
+ #define MON_DETACH 0x02
+ #define MON_MIGRATING 0x04
+ #define MON_LIMBO 0x08
+ #define MON_BUBBLEMOVE 0x10
+ #define MON_ENDGAME_FREE 0x20
+ #define MON_ENDGAME_MIGR 0x40
+ #define MON_OBLITERATE 0x80
+ #define MSTATE_MASK 0xFF
+
#define M_AP_TYPMASK 0x7
#define M_AP_F_DKNOWN 0x8
-#define U_AP_TYPE (youmonst.m_ap_type & M_AP_TYPMASK)
-#define U_AP_FLAG (youmonst.m_ap_type & ~M_AP_TYPMASK)
+#define U_AP_TYPE (g.youmonst.m_ap_type & M_AP_TYPMASK)
+#define U_AP_FLAG (g.youmonst.m_ap_type & ~M_AP_TYPMASK)
#define M_AP_TYPE(m) ((m)->m_ap_type & M_AP_TYPMASK)
#define M_AP_FLAG(m) ((m)->m_ap_type & ~M_AP_TYPMASK)
key2extcmddesc(key)
uchar key;
{
- if (g.Cmd.commands[key] && g.Cmd.commands[key]->ef_txt)
- return g.Cmd.commands[key]->ef_desc;
+ static char key2cmdbuf[48];
+ const struct movcmd *mov;
+ int k, c;
+ uchar M_5 = (uchar) M('5'), M_0 = (uchar) M('0');
+
+ /* need to check for movement commands before checking the extended
+ commands table because it contains entries for number_pad commands
+ that match !number_pad movement (like 'j' for "jump") */
+ key2cmdbuf[0] = '\0';
+ if (movecmd(k = key))
+ Strcpy(key2cmdbuf, "move"); /* "move or attack"? */
+ else if (movecmd(k = unctrl(key)))
+ Strcpy(key2cmdbuf, "rush");
- else if (movecmd(k = (Cmd.num_pad ? unmeta(key) : lowc(key))))
++ else if (movecmd(k = (g.Cmd.num_pad ? unmeta(key) : lowc(key))))
+ Strcpy(key2cmdbuf, "run");
+ if (*key2cmdbuf) {
+ for (mov = &movtab[0]; mov->k1; ++mov) {
- c = !Cmd.num_pad ? (!Cmd.swap_yz ? mov->k1 : mov->k2)
- : (!Cmd.phone_layout ? mov->k3 : mov->k4);
++ c = !g.Cmd.num_pad ? (!g.Cmd.swap_yz ? mov->k1 : mov->k2)
++ : (!g.Cmd.phone_layout ? mov->k3 : mov->k4);
+ if (c == k) {
+ Sprintf(eos(key2cmdbuf), " %s (screen %s)",
+ mov->txt, mov->alt);
+ return key2cmdbuf;
+ }
+ }
- } else if (digit(key) || (Cmd.num_pad && digit(unmeta(key)))) {
++ } else if (digit(key) || (g.Cmd.num_pad && digit(unmeta(key)))) {
+ key2cmdbuf[0] = '\0';
- if (!Cmd.num_pad)
++ if (!g.Cmd.num_pad)
+ Strcpy(key2cmdbuf, "start of, or continuation of, a count");
+ else if (key == '5' || key == M_5)
+ Sprintf(key2cmdbuf, "%s prefix",
- (!!Cmd.pcHack_compat ^ (key == M_5)) ? "run" : "rush");
- else if (key == '0' || (Cmd.pcHack_compat && key == M_0))
++ (!!g.Cmd.pcHack_compat ^ (key == M_5)) ? "run" : "rush");
++ else if (key == '0' || (g.Cmd.pcHack_compat && key == M_0))
+ Strcpy(key2cmdbuf, "synonym for 'i'");
+ if (*key2cmdbuf)
+ return key2cmdbuf;
+ }
- if (Cmd.commands[key]) {
- if (Cmd.commands[key]->ef_txt)
- return Cmd.commands[key]->ef_desc;
++ if (g.Cmd.commands[key]) {
++ if (g.Cmd.commands[key]->ef_txt)
++ return g.Cmd.commands[key]->ef_desc;
+
+ }
return (char *) 0;
}
{
unstuck(mtmp);
mdrop_special_objs(mtmp);
- migrate_to_level(mtmp, ledger_no(&u.uz), MIGR_APPROX_XY, (coord *) 0);
+ migrate_to_level(mtmp, target_lev, xyloc, (coord *) 0);
+ mtmp->mstate |= MON_MIGRATING;
+ }
+
+ STATIC_OVL boolean
+ ok_to_obliterate(mtmp)
+ struct monst *mtmp;
+ {
+ /*
+ * Add checks for monsters that should not be obliterated
+ * here (return FALSE).
+ */
+ if (mtmp->data == &mons[PM_WIZARD_OF_YENDOR] || is_rider(mtmp->data)
+ || has_emin(mtmp) || has_epri(mtmp) || has_eshk(mtmp))
+ return FALSE;
+ return TRUE;
+ }
+
+ void
+ elemental_clog(mon)
+ struct monst *mon;
+ {
+ int m_lev = 0;
+ static long msgmv = 0L;
+ struct monst *mtmp, *m1, *m2, *m3, *m4, *m5, *zm;
+
+ if (In_endgame(&u.uz)) {
+ m1 = m2 = m3 = m4 = m5 = zm = (struct monst *) 0;
- if (!msgmv || (moves - msgmv) > 200L) {
++ if (!msgmv || (g.moves - msgmv) > 200L) {
+ if (!msgmv || rn2(2))
+ You("feel besieged.");
- msgmv = moves;
++ msgmv = g.moves;
+ }
+ /*
+ * m1 an elemental from another plane.
+ * m2 an elemental from this plane.
+ * m3 the least powerful monst encountered in loop so far.
+ * m4 some other non-tame monster.
+ * m5 a pet.
+ */
+ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp))
+ continue;
+ if (mtmp->mx == 0 && mtmp->my == 0)
+ continue;
+ if (mon_has_amulet(mtmp) || !ok_to_obliterate(mtmp))
+ continue;
+ if (mtmp->data->mlet == S_ELEMENTAL) {
+ if (!is_home_elemental(mtmp->data)) {
+ if (!m1)
+ m1 = mtmp;
+ } else {
+ if (!m2)
+ m2 = mtmp;
+ }
+ } else {
+ if (!mtmp->mtame) {
+ if (!m_lev || mtmp->m_lev < m_lev) {
+ m_lev = mtmp->m_lev;
+ m3 = mtmp;
+ } else if (!m4) {
+ m4 = mtmp;
+ }
+ } else {
+ if (!m5)
+ m5 = mtmp;
+ break;
+ }
+ }
+ }
+ mtmp = m1 ? m1 : m2 ? m2 : m3 ? m3 : m4 ? m4 : m5 ? m5 : zm;
+ if (mtmp) {
+ int mx = mtmp->mx, my = mtmp->my;
+
+ mtmp->mstate |= MON_OBLITERATE;
+ mongone(mtmp);
+ mtmp->mx = mtmp->my = 0;
+ rloc_to(mon, mx, my);
+ } else {
+ /* last resort - migrate mon to the next plane */
+ if (Is_waterlevel(&u.uz) || Is_firelevel(&u.uz) || Is_earthlevel(&u.uz)) {
+ /* try sending mon on to the next plane */
+ xchar target_lev = 0, xyloc = 0;
- struct trap *trap = ftrap;
++ struct trap *trap = g.ftrap;
+
+ while (trap) {
+ if (trap->ttyp == MAGIC_PORTAL)
+ break;
+ trap = trap->ntrap;
+ }
+ if (trap) {
+ target_lev = ledger_no(&trap->dst);
+ xyloc = MIGR_RANDOM;
+ }
+ if (target_lev) {
+ mon->mstate |= MON_ENDGAME_MIGR;
+ migrate_mon(mon, target_lev, xyloc);
+ }
+ }
+ }
+ }
}
/* make monster mtmp next to you (if possible);
if (mon == u.usteed
/* special case is for convoluted vault guard handling */
|| (DEADMONSTER(mon) && !(mon->isgd && x == 0 && y == 0))) {
- impossible("placing %s onto map?",
- (mon == u.usteed) ? "steed" : "defunct monster");
+ describe_level(buf);
+ impossible("placing %s onto map, mstate:%lx, on %s?",
+ (mon == u.usteed) ? "steed" : "defunct monster",
+ mon->mstate, buf);
return;
}
- if (g.level.monsters[x][y])
- impossible("placing monster over another at <%d,%d>?", x, y);
- if (level.monsters[x][y]) {
++ if (g.level.monsters[x][y]) {
+ describe_level(buf);
+ impossible("placing monster over another at <%d,%d>, mstates:%lx %lx on %s?",
- x, y, level.monsters[x][y]->mstate, mon->mstate, buf);
++ x, y, g.level.monsters[x][y]->mstate, mon->mstate, buf);
+ }
mon->mx = x, mon->my = y;
- level.monsters[x][y] = mon;
+ g.level.monsters[x][y] = mon;
+ mon->mstate &= ~(MON_OFFMAP | MON_MIGRATING | MON_LIMBO | MON_BUBBLEMOVE
+ | MON_ENDGAME_FREE | MON_ENDGAME_MIGR);
}
/*steed.c*/