Port the Smart AI effect handlers (#28)
Translate every AI_Smart_EffectHandlers entry, so trainers with the Smart layer are no longer refused. The AI's type checks keep the CheckTypeMatchup bug: they read the move type and Foresight flag through hBattleTurn, and Conversion2's write to the player's move type persists. The reference emulator runs the unmodified AI_Smart routine over 6,024 states per browser, comparing scores, Random consumption, hBattleTurn and the player's move type. Validated with 579 unit tests, 151 browser tests, native/reference builds and reference/vendor/release checks. Kurt's balls, Park and Safari balls and special battle types remain on #28. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
32d736ecae
commit
77704fe848
11 files changed
+682
-71
No files matched your search
@@ -1036,11 +1036,23 @@ export class Battle {
|
||||
player: this.player, enemy: this.enemy,
|
||||
data: this.options.data, battleData: this.data, weather: this.weather,
|
||||
random: () => this.random(),
|
||||
turn: this.turn ? 1 : 0,
|
||||
damage: (move) => this.enemyAIDamage(move),
|
||||
playerUsedMoves: this.playerUsedMoves,
|
||||
playerHasReserve: this.options.party.some((mon, i) => i !== this.curBattleMon && mon.hp > 0),
|
||||
enemyHasReserve: this.options.trainer.party.some((mon, i) => i !== this.curOTMon && mon.hp > 0),
|
||||
enemyParty: this.options.trainer.party,
|
||||
switchScore: (type, identified) => this.checkPlayerMoveTypeMatchups(type, identified),
|
||||
conversion2Type: this.reader.byte(SYMBOLS.moves + 255 * 7 + 3),
|
||||
genders: [
|
||||
this.options.data.gender(this.partyMon.species, this.partyMon.dvs),
|
||||
this.options.data.gender(this.enemySpecies, this.enemy.has(SUB5, C.SUBSTATUS_TRANSFORMED) ? this.enemy.backupDvs : this.enemy.mon.dvs),
|
||||
].map((gender) => gender === undefined ? -1 : gender === "male" ? 1 : 0) as [number, number],
|
||||
});
|
||||
this.enemy.moveNum = choice.index;
|
||||
this.enemy.curMove = choice.move;
|
||||
if (choice.enemyTurn) this.turn = 1;
|
||||
else if (choice.playerTurn) this.turn = 0;
|
||||
}
|
||||
if (!this.checkPlayerLockedIn()) {
|
||||
for (;;) {
|
||||
@@ -5578,12 +5590,14 @@ export class Battle {
|
||||
return e === 2 ? score + 0x10 : 0;
|
||||
}
|
||||
/** CheckPlayerMoveTypeMatchups: wEnemyAISwitchScore from BASE_AI_SWITCH_SCORE
|
||||
* (10); lower means the enemy is worse off. Matchups use the enemy's move
|
||||
* type (see checkAbleToSwitch). */
|
||||
private checkPlayerMoveTypeMatchups(): number {
|
||||
const data = this.options.data,
|
||||
identified = this.player.has(SUB1, C.SUBSTATUS_IDENTIFIED),
|
||||
type = this.enemy.move.type;
|
||||
* (10); lower means the enemy is worse off. CheckTypeMatchup reads the move
|
||||
* type and Foresight flag through hBattleTurn; switching runs on the
|
||||
* enemy's turn (see checkAbleToSwitch), Smart AI on either. */
|
||||
private checkPlayerMoveTypeMatchups(
|
||||
type = this.enemy.move.type,
|
||||
identified = this.player.has(SUB1, C.SUBSTATUS_IDENTIFIED),
|
||||
): number {
|
||||
const data = this.options.data;
|
||||
const vsEnemy = () => this.typeMatchup(type, this.enemy.mon.types, identified),
|
||||
vsPlayer = () => this.typeMatchup(type, this.player.mon.types, identified);
|
||||
let score = 10;
|
||||
|
||||
Reference in new issue
Block a user