[Misc][AI] Fix KO filter not accounting for move conditions (#4245)
* Only filter KO moves that won't fail * Add Last Resort enemy command test
This commit is contained in:
parent
39a1963941
commit
bdc7c95c1c
|
@ -4410,7 +4410,10 @@ export class EnemyPokemon extends Pokemon {
|
||||||
const isCritical = move.hasAttr(CritOnlyAttr) || !!this.getTag(BattlerTagType.ALWAYS_CRIT);
|
const isCritical = move.hasAttr(CritOnlyAttr) || !!this.getTag(BattlerTagType.ALWAYS_CRIT);
|
||||||
|
|
||||||
return move.category !== MoveCategory.STATUS
|
return move.category !== MoveCategory.STATUS
|
||||||
&& moveTargets.some(p => p.getAttackDamage(this, move, !p.battleData.abilityRevealed, false, isCritical).damage >= p.hp);
|
&& moveTargets.some(p => {
|
||||||
|
const doesNotFail = move.applyConditions(this, p, move) || [Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP].includes(move.id);
|
||||||
|
return doesNotFail && p.getAttackDamage(this, move, !p.battleData.abilityRevealed, false, isCritical).damage >= p.hp;
|
||||||
|
});
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
if (koMoves.length > 0) {
|
if (koMoves.length > 0) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { AiType, EnemyPokemon } from "#app/field/pokemon";
|
||||||
import { randSeedInt } from "#app/utils";
|
import { randSeedInt } from "#app/utils";
|
||||||
import GameManager from "#test/utils/gameManager";
|
import GameManager from "#test/utils/gameManager";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const TIMEOUT = 20 * 1000;
|
const TIMEOUT = 20 * 1000;
|
||||||
const NUM_TRIALS = 300;
|
const NUM_TRIALS = 300;
|
||||||
|
@ -36,22 +36,26 @@ describe("Enemy Commands - Move Selection", () => {
|
||||||
phaserGame = new Phaser.Game({
|
phaserGame = new Phaser.Game({
|
||||||
type: Phaser.HEADLESS,
|
type: Phaser.HEADLESS,
|
||||||
});
|
});
|
||||||
game = new GameManager(phaserGame);
|
|
||||||
game.override.ability(Abilities.BALL_FETCH);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
game.phaseInterceptor.restoreOg();
|
game.phaseInterceptor.restoreOg();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
|
||||||
|
game.override
|
||||||
|
.ability(Abilities.BALL_FETCH)
|
||||||
|
.enemyAbility(Abilities.BALL_FETCH);
|
||||||
|
});
|
||||||
|
|
||||||
it(
|
it(
|
||||||
"should never use Status moves if an attack can KO",
|
"should never use Status moves if an attack can KO",
|
||||||
async () => {
|
async () => {
|
||||||
game.override
|
game.override
|
||||||
.enemySpecies(Species.ETERNATUS)
|
.enemySpecies(Species.ETERNATUS)
|
||||||
.enemyMoveset([Moves.ETERNABEAM, Moves.SLUDGE_BOMB, Moves.DRAGON_DANCE, Moves.COSMIC_POWER])
|
.enemyMoveset([Moves.ETERNABEAM, Moves.SLUDGE_BOMB, Moves.DRAGON_DANCE, Moves.COSMIC_POWER])
|
||||||
.enemyAbility(Abilities.BALL_FETCH)
|
|
||||||
.ability(Abilities.BALL_FETCH)
|
|
||||||
.startingLevel(1)
|
.startingLevel(1)
|
||||||
.enemyLevel(100);
|
.enemyLevel(100);
|
||||||
|
|
||||||
|
@ -72,4 +76,31 @@ describe("Enemy Commands - Move Selection", () => {
|
||||||
});
|
});
|
||||||
}, TIMEOUT
|
}, TIMEOUT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should not select Last Resort if it would fail, even if the move KOs otherwise",
|
||||||
|
async () => {
|
||||||
|
game.override
|
||||||
|
.enemySpecies(Species.KANGASKHAN)
|
||||||
|
.enemyMoveset([Moves.LAST_RESORT, Moves.GIGA_IMPACT, Moves.SPLASH, Moves.SWORDS_DANCE])
|
||||||
|
.startingLevel(1)
|
||||||
|
.enemyLevel(100);
|
||||||
|
|
||||||
|
await game.classicMode.startBattle([Species.MAGIKARP]);
|
||||||
|
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
enemyPokemon.aiType = AiType.SMART_RANDOM;
|
||||||
|
|
||||||
|
const moveChoices: MoveChoiceSet = {};
|
||||||
|
const enemyMoveset = enemyPokemon.getMoveset();
|
||||||
|
enemyMoveset.forEach(mv => moveChoices[mv!.moveId] = 0);
|
||||||
|
getEnemyMoveChoices(enemyPokemon, moveChoices);
|
||||||
|
|
||||||
|
enemyMoveset.forEach(mv => {
|
||||||
|
if (mv?.getMove().category === MoveCategory.STATUS || mv?.moveId === Moves.LAST_RESORT) {
|
||||||
|
expect(moveChoices[mv.moveId]).toBe(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue