From: Alex Smith Date: Wed, 1 Nov 2017 14:55:40 +0000 (+0000) Subject: It's OK for pets to oscillate near the player X-Git-Tag: NetHack-3.6.1_RC01~224 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e4db58bdf3376eddf9ad6416c0664975e7787035;p=nethack 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!".) --- diff --git a/src/dogmove.c b/src/dogmove.c index 5a385b6aa..200779ea3 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -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 diff --git a/src/mon.c b/src/mon.c index d01a79c95..a872b93a9 100644 --- a/src/mon.c +++ b/src/mon.c @@ -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)); + } } } }