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:
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user