Split swapping places with pet code out of domove

This commit is contained in:
Pasi Kallinen
2022-02-25 15:09:56 +02:00
parent f44a4b0485
commit 48cd81dbfd

View File

@@ -18,6 +18,7 @@ static boolean swim_move_danger(xchar, xchar);
static boolean domove_bump_mon(struct monst *, int);
static boolean domove_attackmon_at(struct monst *, xchar, xchar, boolean *);
static boolean domove_fight_ironbars(xchar, xchar);
static boolean domove_swap_with_pet(struct monst *, xchar, xchar);
static void domove_core(void);
static void maybe_smudge_engr(int, int, int, int);
static struct monst *monstinroom(struct permonst *, int);
@@ -1683,6 +1684,125 @@ domove_fight_ironbars(xchar x, xchar y)
return FALSE;
}
/* maybe swap places with a pet? returns TRUE if swapped places */
static boolean
domove_swap_with_pet(struct monst *mtmp, xchar x, xchar y)
{
struct trap *trap;
/* if it turns out we can't actually move */
boolean didnt_move = FALSE;
boolean u_with_boulder = (sobj_at(BOULDER, u.ux, u.uy) != 0);
/* seemimic/newsym should be done before moving hero, otherwise
the display code will draw the hero here before we possibly
cancel the swap below (we can ignore steed mx,my here) */
u.ux = u.ux0, u.uy = u.uy0;
mtmp->mundetected = 0;
if (M_AP_TYPE(mtmp))
seemimic(mtmp);
u.ux = mtmp->mx, u.uy = mtmp->my; /* resume swapping positions */
if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
&& is_pit(trap->ttyp)
&& sobj_at(BOULDER, trap->tx, trap->ty)) {
/* can't swap places with pet pinned in a pit by a boulder */
didnt_move = TRUE;
} else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
/* can't swap places when pet can't move to your spot */
You("stop. %s can't move diagonally.", upstart(y_monnam(mtmp)));
didnt_move = TRUE;
} else if (u_with_boulder
&& !(verysmall(mtmp->data)
&& (!mtmp->minvent || curr_mon_load(mtmp) <= 600))) {
/* can't swap places when pet won't fit there with the boulder */
You("stop. %s won't fit into the same spot that you're at.",
upstart(y_monnam(mtmp)));
didnt_move = TRUE;
} 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 */
You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
didnt_move = TRUE;
} else if (mtmp->mpeaceful && mtmp->mtrapped) {
/* all mtame are also mpeaceful, so this affects pets too */
You("stop. %s can't move out of that trap.",
upstart(y_monnam(mtmp)));
didnt_move = TRUE;
} else if (mtmp->mpeaceful
&& (!goodpos(u.ux0, u.uy0, mtmp, 0)
|| t_at(u.ux0, u.uy0) != NULL
|| mundisplaceable(mtmp))) {
/* displacing peaceful into unsafe or trapped space, or trying to
* displace quest leader, Oracle, shopkeeper, or priest */
You("stop. %s doesn't want to swap places.",
upstart(y_monnam(mtmp)));
didnt_move = TRUE;
} else {
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->mpeaceful ? "swap places with" : "frighten",
x_monnam(mtmp,
mtmp->mtame ? ARTICLE_YOUR
: (!has_mgivenname(mtmp)
&& !type_is_pname(mtmp->data)) ? ARTICLE_THE
: ARTICLE_NONE,
(mtmp->mpeaceful && !mtmp->mtame) ? "peaceful" : 0,
has_mgivenname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE));
/* check for displacing it into pools and traps */
switch (minliquid(mtmp) ? Trap_Killed_Mon
: mintrap(mtmp, NO_TRAP_FLAGS)) {
case Trap_Effect_Finished:
break;
case Trap_Caught_Mon: /* trapped */
case Trap_Moved_Mon: /* changed levels */
/* there's already been a trap message, reinforce it */
abuse_dog(mtmp);
adjalign(-3);
break;
case Trap_Killed_Mon:
/* 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;
if (!u.uconduct.killer++)
livelog_printf(LL_CONDUCT, "killed for the first time");
mndx = monsndx(mtmp->data);
tmp = experience(mtmp, (int) g.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:
impossible("that's strange, unknown mintrap result!");
break;
}
}
return !didnt_move;
}
void
domove(void)
{
@@ -1709,8 +1829,7 @@ domove_core(void)
ballx = 0, bally = 0; /* ball&chain new positions */
int bc_control = 0; /* control for ball&chain */
boolean cause_delay = FALSE, /* dragging ball will skip a move */
displaceu = FALSE, /* involuntary swap */
u_with_boulder = (sobj_at(BOULDER, u.ux, u.uy) != 0);
displaceu = FALSE; /* involuntary swap */
if (g.context.travel) {
if (!findtravelpath(FALSE))
@@ -2107,118 +2226,7 @@ domove_core(void)
*/
} else if (is_safemon(mtmp)
&& !(is_hider(mtmp->data) && mtmp->mundetected)) {
/* if it turns out we can't actually move */
boolean didnt_move = FALSE;
/* seemimic/newsym should be done before moving hero, otherwise
the display code will draw the hero here before we possibly
cancel the swap below (we can ignore steed mx,my here) */
u.ux = u.ux0, u.uy = u.uy0;
mtmp->mundetected = 0;
if (M_AP_TYPE(mtmp))
seemimic(mtmp);
u.ux = mtmp->mx, u.uy = mtmp->my; /* resume swapping positions */
if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
&& is_pit(trap->ttyp)
&& sobj_at(BOULDER, trap->tx, trap->ty)) {
/* can't swap places with pet pinned in a pit by a boulder */
didnt_move = TRUE;
} else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
/* can't swap places when pet can't move to your spot */
You("stop. %s can't move diagonally.", upstart(y_monnam(mtmp)));
didnt_move = TRUE;
} else if (u_with_boulder
&& !(verysmall(mtmp->data)
&& (!mtmp->minvent || curr_mon_load(mtmp) <= 600))) {
/* can't swap places when pet won't fit there with the boulder */
You("stop. %s won't fit into the same spot that you're at.",
upstart(y_monnam(mtmp)));
didnt_move = TRUE;
} 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 */
You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
didnt_move = TRUE;
} else if (mtmp->mpeaceful && mtmp->mtrapped) {
/* all mtame are also mpeaceful, so this affects pets too */
You("stop. %s can't move out of that trap.",
upstart(y_monnam(mtmp)));
didnt_move = TRUE;
} else if (mtmp->mpeaceful
&& (!goodpos(u.ux0, u.uy0, mtmp, 0)
|| t_at(u.ux0, u.uy0) != NULL
|| mundisplaceable(mtmp))) {
/* displacing peaceful into unsafe or trapped space, or trying to
* displace quest leader, Oracle, shopkeeper, or priest */
You("stop. %s doesn't want to swap places.",
upstart(y_monnam(mtmp)));
didnt_move = TRUE;
} else {
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->mpeaceful ? "swap places with" : "frighten",
x_monnam(mtmp,
mtmp->mtame ? ARTICLE_YOUR
: (!has_mgivenname(mtmp)
&& !type_is_pname(mtmp->data)) ? ARTICLE_THE
: ARTICLE_NONE,
(mtmp->mpeaceful && !mtmp->mtame) ? "peaceful" : 0,
has_mgivenname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE));
/* check for displacing it into pools and traps */
switch (minliquid(mtmp) ? Trap_Killed_Mon
: mintrap(mtmp, NO_TRAP_FLAGS)) {
case Trap_Effect_Finished:
break;
case Trap_Caught_Mon: /* trapped */
case Trap_Moved_Mon: /* changed levels */
/* there's already been a trap message, reinforce it */
abuse_dog(mtmp);
adjalign(-3);
break;
case Trap_Killed_Mon:
/* 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;
if (!u.uconduct.killer++)
livelog_printf(LL_CONDUCT, "killed for the first time");
mndx = monsndx(mtmp->data);
tmp = experience(mtmp, (int) g.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:
impossible("that's strange, unknown mintrap result!");
break;
}
}
if (didnt_move) {
if (!domove_swap_with_pet(mtmp, x, y)) {
u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
/* could skip this bit since we're about to call u_on_newpos() */
if (u.usteed)