Initialize move scores

This commit is contained in:
Pawkkie 2025-04-07 23:22:01 -04:00
parent bbe8bbc45b
commit d7a6e0bea8
5 changed files with 43 additions and 3 deletions

View File

@ -360,6 +360,7 @@ struct AI_ThinkingStruct
u8 movesetIndex;
u16 moveConsidered;
s32 score[MAX_MON_MOVES];
s32 predictedScore[MAX_MON_MOVES][MAX_BATTLERS_COUNT];
u32 funcResult;
u32 aiFlags[MAX_BATTLERS_COUNT];
u8 aiAction;

View File

@ -64,6 +64,12 @@ typedef s32 (*AiScoreFunc)(u32, u32, u32, s32);
AI_THINKING_STRUCT->score[movesetIndex] = val; \
} while (0) \
#define SET_PREDICTED_SCORE(battler, movesetIndex, val) \
do \
{ \
AI_THINKING_STRUCT->predictedScore[movesetIndex][battler] = val; \
} while (0) \
#define ADJUST_SCORE(val) \
do \
{ \

View File

@ -43,13 +43,14 @@
#define AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE (1 << 22) // AI adds score to highest damage move regardless of accuracy or secondary effect
#define AI_FLAG_PREDICT_SWITCH (1 << 23) // AI will predict the player's switches and switchins based on how it would handle the situation. Recommend using AI_FLAG_OMNISCIENT
#define AI_FLAG_PREDICT_INCOMING_MON (1 << 24) // AI will score against the predicting incoming mon if it predicts the player to switch. Requires AI_FLAG_PREDICT_SWITCH
#define AI_FLAG_PREDICT_MOVES (1 << 25) //
#define AI_FLAG_COUNT 25
// The following options are enough to have a basic/smart trainer. Any other addtion could make the trainer worse/better depending on the flag
#define AI_FLAG_BASIC_TRAINER (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY)
#define AI_FLAG_SMART_TRAINER (AI_FLAG_BASIC_TRAINER | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_WEIGH_ABILITY_PREDICTION)
#define AI_FLAG_PREDICTION (AI_FLAG_PREDICT_SWITCH | AI_FLAG_PREDICT_INCOMING_MON)
#define AI_FLAG_PREDICTION (AI_FLAG_PREDICT_SWITCH | AI_FLAG_PREDICT_INCOMING_MON | AI_FLAG_PREDICT_MOVES)
// 'other' ai logic flags
#define AI_FLAG_DYNAMIC_FUNC (1 << 28) // Create custom AI functions for specific battles via "setdynamicaifunc" cmd

View File

@ -238,8 +238,9 @@ void BattleAI_SetupFlags(void)
void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler)
{
u32 moveLimitations;
u32 moveLimitations, moveLimitationsTarget;
u32 flags[MAX_BATTLERS_COUNT];
u32 moveIndex;
// Clear AI data but preserve the flags.
memcpy(&flags[0], &AI_THINKING_STRUCT->aiFlags[0], sizeof(u32) * MAX_BATTLERS_COUNT);
@ -249,7 +250,7 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler)
moveLimitations = AI_DATA->moveLimitations[battler];
// Conditional score reset, unlike Ruby.
for (u32 moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
if (moveLimitations & (1u << moveIndex))
SET_SCORE(battler, moveIndex, 0);
@ -263,6 +264,22 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler)
gBattlerTarget = SetRandomTarget(battler);
gAiBattleData->chosenTarget[battler] = gBattlerTarget;
// Initialize move prediction scores
if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_PREDICT_MOVES)
{
moveLimitationsTarget = AI_DATA->moveLimitations[gBattlerTarget];
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
if (moveLimitations & (1u << moveIndex))
SET_PREDICTED_SCORE(gBattlerTarget, moveIndex, 0);
if (defaultScoreMoves & 1)
SET_PREDICTED_SCORE(gBattlerTarget, moveIndex, AI_SCORE_DEFAULT);
else
SET_PREDICTED_SCORE(gBattlerTarget, moveIndex, 0);
}
}
}
u32 BattleAI_ChooseMoveOrAction(u32 battler)

View File

@ -0,0 +1,15 @@
#include "global.h"
#include "test/battle.h"
#include "battle_ai_util.h"
AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_MOVE: AI will predict player's move")
{
GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PREDICT_MOVE);
PLAYER(SPECIES_VAPOREON) { Moves(MOVE_SURF, MOVE_TACKLE); }
OPPONENT(SPECIES_NUMEL) { Moves(MOVE_TACKLE); }
OPPONENT(SPECIES_VAPOREON) { Ability(ABILITY_WATER_ABSORB); Moves(MOVE_TACKLE); }
} WHEN {
TURN { MOVE(player, MOVE_SURF); EXPECT_SWITCH(opponent, 1); }
}
}