From 9f67e06279c98811d73c07a8e7cd48496e529300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilde=20Sim=C3=B5es?= Date: Fri, 20 Jun 2025 22:06:37 +0100 Subject: [PATCH] =?UTF-8?q?=20[Balance]=20[AI]=20Trainer=20Pok=C3=A9mon=20?= =?UTF-8?q?will=20be=20less=20likely=20to=20switch=20out=20on=20low=20heal?= =?UTF-8?q?th=20(#5981)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implemented AI improvements: The changes in the game AI were as follows ("pokemon.ts"): - More accurately accounts for the Pokémon's actual moves and their effectiveness against the player instead of only the pokemon type - Introduced logic to decide when a Pokémon should be sacrificed or switched based on its HP and speed. Signed-off-by: Matilde Simões Co-authored-by: Fuad Ali * Corrected grammar error in variable declaration in getMatchupScore Signed-off-by: Fuad Ali Co-authored-by: Matilde Simões --------- Signed-off-by: Matilde Simões Co-authored-by: Fuad Ali Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Co-authored-by: damocleas Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- src/field/pokemon.ts | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index e9cc4f70d70..0c3dac195f3 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2498,14 +2498,39 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { defScore *= 1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[1], opponent, false, false, undefined, true), 0.25); } + atkScore *= 1.25; //give more value for the pokemon's typing + const moveset = this.moveset; + let moveAtkScoreLength = 0; + for (const move of moveset) { + if (move.getMove().category === MoveCategory.SPECIAL || move.getMove().category === MoveCategory.PHYSICAL) { + atkScore += opponent.getAttackTypeEffectiveness(move.getMove().type, this, false, true, undefined, true); + moveAtkScoreLength++; + } + } + atkScore = atkScore / (moveAtkScoreLength + 1); //calculate the median for the attack score /** * Based on this Pokemon's HP ratio compared to that of the opponent. * This ratio is multiplied by 1.5 if this Pokemon outspeeds the opponent; * however, the final ratio cannot be higher than 1. */ - let hpDiffRatio = this.getHpRatio() + (1 - opponent.getHpRatio()); - if (outspeed) { - hpDiffRatio = Math.min(hpDiffRatio * 1.5, 1); + const hpRatio = this.getHpRatio(); + const oppHpRatio = opponent.getHpRatio(); + const isDying = hpRatio <= 0.2; + let hpDiffRatio = hpRatio + (1 - oppHpRatio); + if (isDying && this.isActive(true)) { + //It might be a sacrifice candidate if hp under 20% + const badMatchup = atkScore < 1.5 && defScore < 1.5; + if (!outspeed && badMatchup) { + //It might not be a worthy sacrifice if it doesn't outspeed or doesn't do enough damage + hpDiffRatio *= 0.85; + } else { + hpDiffRatio = Math.min(1 - hpRatio + (outspeed ? 0.2 : 0.1), 1); + } + } else if (outspeed) { + hpDiffRatio = Math.min(hpDiffRatio * 1.25, 1); + } else if (hpRatio > 0.2 && hpRatio <= 0.4) { + //Might be considered to be switched because it's not in low enough health + hpDiffRatio = Math.min(hpDiffRatio * 0.5, 1); } return (atkScore + defScore) * hpDiffRatio; }