It's OK for pets to oscillate near the player

This change was coded by FIQ, who suggested it by email.

The main change here is related to monster anti-oscillation code.
When a monster believes it's stuck in an AI loop, it looks for an
alternative strategy. That applies to pets too. However, if the
pet is currently near the player, we can typically assume that it's
there because it wants to be there, and an oscillation is not
because it's stuck but because it's already in the best possible
place. This commit causes pets to be "allowed" to stay near the
player, rather than running the wrong way down a corridor because
it's the only way to do something different than what they're
currently doing.

If the pet is far from the player, we use the old behaviour unless
the pet is leashed or the player tried to call it with a whistle
or the like, in order to avoid the risk of a genuine AI loop trying
to get back to the player. (Whistling happens rarely enough that it
won't cause AI loops of its own - the player isn't going to whistle
every turn - and it makes flavour sense that a pet might interpret
it as "you're going in the wrong direction!".)
This commit is contained in:
Alex Smith
2017-11-01 14:55:40 +00:00
parent f2765c573f
commit e4db58bdf3
2 changed files with 19 additions and 7 deletions

View File

@@ -1086,11 +1086,18 @@ int after; /* this is extra fast monster movement */
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

View File

@@ -2787,8 +2787,13 @@ wake_nearby()
mtmp->msleeping = 0;
if (!unique_corpstat(mtmp->data))
mtmp->mstrategy &= ~STRAT_WAITMASK;
if (mtmp->mtame && !mtmp->isminion)
EDOG(mtmp)->whistletime = moves;
if (mtmp->mtame) {
if (!mtmp->isminion)
EDOG(mtmp)->whistletime = moves;
/* Clear mtrack. This is to fix up a pet who is
stuck "fleeing" its master. */
memset(mtmp->mtrack, 0, sizeof(mtmp->mtrack));
}
}
}
}