Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ai battle tests + ai logic fixes #3361

Merged
merged 27 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b1a696b
ai battle tests
DizzyEggg Sep 27, 2023
df2d787
expected moves in ai tests
DizzyEggg Sep 27, 2023
632f2e1
Some Ai Tests
DizzyEggg Sep 27, 2023
25d536e
more ai tests and record message for all controllers
DizzyEggg Sep 29, 2023
1054029
recorded player print string moved to controllers
DizzyEggg Sep 29, 2023
0f9f30d
ai tests
DizzyEggg Sep 29, 2023
6712874
ai double tests + weather ai test+fix
DizzyEggg Sep 29, 2023
feb1ef6
ai send out test EXPECTED_SEND_OUT
DizzyEggg Sep 30, 2023
c081ff1
known failings
DizzyEggg Sep 30, 2023
8074bd1
Add expected switch
DizzyEggg Sep 30, 2023
c1354a2
Merge branch 'upcoming' of https://github.com/rh-hideout/pokeemerald-…
DizzyEggg Oct 2, 2023
e59e4c6
ai log functionality part 1
DizzyEggg Oct 2, 2023
743f6b3
ai tests score logs and various fixes
DizzyEggg Oct 2, 2023
0feba7d
ai tests final touches
DizzyEggg Oct 3, 2023
72dd197
fix getbattlerability
DizzyEggg Oct 3, 2023
276c4f3
Update test/test_runner_battle.c
DizzyEggg Oct 3, 2023
1846c99
Update test/test_runner_battle.c
DizzyEggg Oct 3, 2023
6dfc423
Update test/test_runner_battle.c
DizzyEggg Oct 3, 2023
f28bfda
Update include/test/battle.h
DizzyEggg Oct 3, 2023
6746ddb
Update test/test_runner_battle.c
DizzyEggg Oct 3, 2023
5fb0819
Update include/test/battle.h
DizzyEggg Oct 3, 2023
a461243
Update include/test/battle.h
DizzyEggg Oct 3, 2023
2bc1018
Update test/battle/ai.c
DizzyEggg Oct 3, 2023
3f3e77f
a
DizzyEggg Oct 3, 2023
c73163b
Merge branch 'ai_battle_tests' of https://github.com/DizzyEggg/pokeem…
DizzyEggg Oct 3, 2023
3707115
review changes 1
DizzyEggg Oct 3, 2023
3825fad
ai review changes part 2
DizzyEggg Oct 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions include/battle_ai_main.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,38 @@
#ifndef GUARD_BATTLE_AI_MAIN_H
#define GUARD_BATTLE_AI_MAIN_H

// return values for BattleAI_ChooseMoveOrAction
// return vals for BattleAI_ChooseMoveOrAction
// 0 - 3 are move idx
#define AI_CHOICE_FLEE 4
#define AI_CHOICE_WATCH 5
#define AI_CHOICE_SWITCH 7

#include "test_runner.h"

// Logs for debugging AI tests.
#define SET_SCORE(battler, movesetIndex, val) \
do \
{ \
TestRunner_Battle_AISetScore(__FILE__, __LINE__, battler, movesetIndex, val); \
AI_THINKING_STRUCT->score[movesetIndex] = val; \
} while (0) \

#define ADJUST_SCORE(val) \
do \
{ \
TestRunner_Battle_AIAdjustScore(__FILE__, __LINE__, sBattler_AI, AI_THINKING_STRUCT->movesetIndex, val); \
score += val; \
} while (0) \

#define RETURN_SCORE_PLUS(val) \
{ \
score += val; \
ADJUST_SCORE(val); \
return score; \
}

#define RETURN_SCORE_MINUS(val) \
{ \
score -= val; \
ADJUST_SCORE(-val); \
return score; \
}

Expand Down
5 changes: 2 additions & 3 deletions include/battle_ai_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ bool32 CanTargetMoveFaintAi(u32 move, u32 battlerDef, u32 battlerAtk, u32 nHits)
bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dmgMod);
s32 AI_DecideKnownAbilityForTurn(u32 battlerId);
u32 AI_DecideHoldEffectForTurn(u32 battlerId);
u32 AI_GetMoveAccuracy(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 DoesBattlerIgnoreAbilityChecks(u32 atkAbility, u32 move);
u32 AI_GetWeather(struct AiLogicData *aiData);
bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits);
Expand Down Expand Up @@ -85,7 +84,7 @@ bool32 ShouldLowerEvasion(u32 battlerAtk, u32 battlerDef, u32 defAbility);
// move checks
bool32 IsAffectedByPowder(u32 battler, u32 ability, u32 holdEffect);
bool32 MovesWithSplitUnusable(u32 attacker, u32 target, u32 split);
u32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef);
u32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo);
s32 AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower);
s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, u32 weather);
bool32 AI_IsDamagedByRecoil(u32 battler);
Expand Down Expand Up @@ -169,7 +168,7 @@ bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef);
bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove);
bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove);
bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef, u32 partnerMove);
bool32 PartnerMoveEffectIsWeather(u32 battlerAtkPartner, u32 partnerMove);
bool32 IsMoveEffectWeather(u32 move);
bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove);
bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck);
bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove);
Expand Down
1 change: 1 addition & 0 deletions include/battle_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility)
u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg);
bool32 TryPrimalReversion(u32 battler);
bool32 IsNeutralizingGasOnField(void);
bool32 IsMoldBreakerTypeAbility(u32 ability);
u32 GetBattlerAbility(u32 battler);
u32 IsAbilityOnSide(u32 battler, u32 ability);
u32 IsAbilityOnOpposingSide(u32 battler, u32 ability);
Expand Down
10 changes: 2 additions & 8 deletions include/constants/battle_ai.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@
#define AI_EFFECTIVENESS_x0_125 1
#define AI_EFFECTIVENESS_x0 0

// ai weather
#define AI_WEATHER_NONE 0
#define AI_WEATHER_SUN 1
#define AI_WEATHER_RAIN 2
#define AI_WEATHER_SANDSTORM 3
#define AI_WEATHER_HAIL 4
#define AI_WEATHER_SNOW 5

// get_how_powerful_move_is
#define MOVE_POWER_OTHER 0
#define MOVE_POWER_BEST 1
Expand Down Expand Up @@ -67,4 +59,6 @@
#define AI_FLAG_SAFARI (1 << 30)
#define AI_FLAG_FIRST_BATTLE (1 << 31)

#define AI_SCORE_DEFAULT 100 // Default score for all AI moves.

#endif // GUARD_CONSTANTS_BATTLE_AI_H
151 changes: 123 additions & 28 deletions include/test/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,17 @@
* - Instead of player and opponent there is playerLeft, playerRight,
* opponentLeft, and opponentRight.
*
* AI_SINGLE_BATTLE_TEST(name, results...) and AI_DOUBLE_BATTLE_TEST(name, results...)
* Define battles where opponent mons are controlled by AI, the same that runs
* when battling regular Trainers. The flags for AI should be specified by
* the AI_FLAGS command.
* The rules remain the same as with the SINGLE and DOUBLE battle tests
* with some differences:
* - opponent's action is specified by the EXPECT_MOVE(s) / EXPECT_SEND_OUT / EXPECT_SWITCH commands
* - we don't control what opponent actually does, instead we make sure the opponent does what we expect it to do
* - we still control the player's action the same way
* - apart from the EXPECTED commands, there's also a new SCORE_ and SCORE__VAL commands
*
* KNOWN_FAILING
* Marks a test as not passing due to a bug. If there is an issue number
* associated with the bug it should be included in a comment. If the
Expand Down Expand Up @@ -289,6 +300,11 @@
* Note if Moves is specified then MOVE will not automatically add moves
* to the moveset.
*
* AI_FLAGS
* Specifies which AI flags are run during the test. Has use only for AI tests.
* The most common combination is AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT)
* which is the general 'smart' AI.
*
* WHEN
* Contains the choices that battlers make during the battle.
*
Expand Down Expand Up @@ -470,6 +486,7 @@
#include "recorded_battle.h"
#include "util.h"
#include "constants/abilities.h"
#include "constants/battle_ai.h"
#include "constants/battle_anim.h"
#include "constants/battle_move_effects.h"
#include "constants/hold_effects.h"
Expand All @@ -483,8 +500,9 @@
#define BATTLE_TEST_STACK_SIZE 1024
#define MAX_TURNS 16
#define MAX_QUEUED_EVENTS 25
#define MAX_EXPECTED_ACTIONS 10

enum { BATTLE_TEST_SINGLES, BATTLE_TEST_DOUBLES, BATTLE_TEST_WILD };
enum { BATTLE_TEST_SINGLES, BATTLE_TEST_DOUBLES, BATTLE_TEST_WILD, BATTLE_TEST_AI_SINGLES, BATTLE_TEST_AI_DOUBLES };

typedef void (*SingleBattleTestFunction)(void *, u32, struct BattlePokemon *, struct BattlePokemon *);
typedef void (*DoubleBattleTestFunction)(void *, u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *);
Expand Down Expand Up @@ -584,6 +602,42 @@ struct BattlerTurn
struct TurnRNG rng;
};

struct ExpectedAIAction
{
u16 sourceLine;
u8 type:4; // which action
u8 moveSlots:4; // Expected move(s) to be chosen or not, marked as bits.
u8 target:4; // move target or id of mon which gets sent out
u8 explicitTarget:1; // For double battles, if it's set it requires the move to hit a specific target, otherwise any target is fine.
u8 pass:1; // No matter what AI does, it always passes.
u8 notMove:1; // We're expecting AI to choose any move EXCEPT the specified one.
u8 actionSet:1; // Action was set and is expected to happen. Set only for battlers controlled by AI.
};

#define MAX_AI_SCORE_COMPARISION_PER_TURN 4
#define MAX_AI_LOG_LINES 10

struct ExpectedAiScore
{
// We can compare AI's move score to a value or to another move's score.
u8 moveSlot1:2;
u8 moveSlot2:2;
u8 target:2;
s8 value; // value
u8 cmp:3; // Uses battle script command's CMP_ macros
u8 toValue:1; // compare to value, not to move
u8 set:1;
u16 sourceLine;
};

struct AILogLine
{
const char *file;
u16 line:15;
u16 set:1; // Whether score was set, or added/subtracted
s16 score;
};

struct BattleTestData
{
u8 stack[BATTLE_TEST_STACK_SIZE];
Expand All @@ -606,6 +660,8 @@ struct BattleTestData
u8 turns;
u8 actionBattlers;
u8 moveBattlers;
bool8 hasAI:1;
bool8 logAI:1;

struct RecordedBattleSave recordedBattle;
u8 battleRecordTypes[MAX_BATTLERS_COUNT][BATTLER_RECORD_SIZE];
Expand All @@ -619,14 +675,20 @@ struct BattleTestData
u8 queueGroupStart;
u8 queuedEvent;
struct QueuedEvent queuedEvents[MAX_QUEUED_EVENTS];
u8 expectedAiActionIndex[MAX_BATTLERS_COUNT];
u8 aiActionsPlayed[MAX_BATTLERS_COUNT];
struct ExpectedAIAction expectedAiActions[MAX_BATTLERS_COUNT][MAX_EXPECTED_ACTIONS];
struct ExpectedAiScore expectedAiScores[MAX_BATTLERS_COUNT][MAX_TURNS][MAX_AI_SCORE_COMPARISION_PER_TURN]; // Max 4 comparisions per turn
struct AILogLine aiLogLines[MAX_BATTLERS_COUNT][MAX_MON_MOVES][MAX_AI_LOG_LINES];
u8 aiLogPrintedForMove[MAX_BATTLERS_COUNT]; // Marks ai score log as printed for move, so the same log isn't displayed multiple times.
};

struct BattleTestRunnerState
{
u8 battlersCount;
u8 parametersCount; // Valid only in BattleTest_Setup.
u8 parameters;
u8 runParameter;
u16 parametersCount; // Valid only in BattleTest_Setup.
u16 parameters;
u16 runParameter;
u16 rngTag;
u16 rngTrialOffset;
u16 trials;
Expand Down Expand Up @@ -682,7 +744,7 @@ extern struct BattleTestRunnerState *gBattleTestRunnerState;
TO_DO; \
}

#define SINGLE_BATTLE_TEST(_name, ...) \
#define BATTLE_TEST_ARGS_SINGLE(_name, _type, ...) \
struct CAT(Result, __LINE__) { MEMBERS(__VA_ARGS__) }; \
static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, u32, struct BattlePokemon *, struct BattlePokemon *); \
__attribute__((section(".tests"))) static const struct Test CAT(sTest, __LINE__) = \
Expand All @@ -692,33 +754,15 @@ extern struct BattleTestRunnerState *gBattleTestRunnerState;
.runner = &gBattleTestRunner, \
.data = (void *)&(const struct BattleTest) \
{ \
.type = BATTLE_TEST_SINGLES, \
.type = _type, \
.sourceLine = __LINE__, \
.function = { .singles = (SingleBattleTestFunction)CAT(Test, __LINE__) }, \
.resultsSize = sizeof(struct CAT(Result, __LINE__)), \
}, \
}; \
static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, u32 i, struct BattlePokemon *player, struct BattlePokemon *opponent)

#define WILD_BATTLE_TEST(_name, ...) \
struct CAT(Result, __LINE__) { MEMBERS(__VA_ARGS__) }; \
static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, u32, struct BattlePokemon *, struct BattlePokemon *); \
__attribute__((section(".tests"))) static const struct Test CAT(sTest, __LINE__) = \
{ \
.name = _name, \
.filename = __FILE__, \
.runner = &gBattleTestRunner, \
.data = (void *)&(const struct BattleTest) \
{ \
.type = BATTLE_TEST_WILD, \
.sourceLine = __LINE__, \
.function = { .singles = (SingleBattleTestFunction)CAT(Test, __LINE__) }, \
.resultsSize = sizeof(struct CAT(Result, __LINE__)), \
}, \
}; \
static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, u32 i, struct BattlePokemon *player, struct BattlePokemon *opponent)

#define DOUBLE_BATTLE_TEST(_name, ...) \
#define BATTLE_TEST_ARGS_DOUBLE(_name, _type, ...) \
struct CAT(Result, __LINE__) { MEMBERS(__VA_ARGS__) }; \
static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); \
__attribute__((section(".tests"))) static const struct Test CAT(sTest, __LINE__) = \
Expand All @@ -728,14 +772,22 @@ extern struct BattleTestRunnerState *gBattleTestRunnerState;
.runner = &gBattleTestRunner, \
.data = (void *)&(const struct BattleTest) \
{ \
.type = BATTLE_TEST_DOUBLES, \
.type = _type, \
.sourceLine = __LINE__, \
.function = { .doubles = (DoubleBattleTestFunction)CAT(Test, __LINE__) }, \
.resultsSize = sizeof(struct CAT(Result, __LINE__)), \
}, \
}; \
static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight)


#define SINGLE_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_SINGLE(_name, BATTLE_TEST_SINGLES, __VA_ARGS__)
#define WILD_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_SINGLE(_name, BATTLE_TEST_WILD, __VA_ARGS__)
#define AI_SINGLE_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_SINGLE(_name, BATTLE_TEST_AI_SINGLES, __VA_ARGS__)

#define DOUBLE_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_DOUBLE(_name, BATTLE_TEST_DOUBLES, __VA_ARGS__)
#define AI_DOUBLE_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_DOUBLE(_name, BATTLE_TEST_AI_DOUBLES, __VA_ARGS__)

/* Parametrize */

#undef PARAMETRIZE // Override test/test.h's implementation.
Expand Down Expand Up @@ -763,6 +815,8 @@ struct moveWithPP {
#define GIVEN for (; gBattleTestRunnerState->runGiven; gBattleTestRunnerState->runGiven = FALSE)

#define RNGSeed(seed) RNGSeed_(__LINE__, seed)
#define AI_FLAGS(flags) AIFlags_(__LINE__, flags)
#define AI_LOG AILogScores(__LINE__)

#define PLAYER(species) for (OpenPokemon(__LINE__, B_SIDE_PLAYER, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__))
#define OPPONENT(species) for (OpenPokemon(__LINE__, B_SIDE_OPPONENT, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__))
Expand All @@ -779,7 +833,7 @@ struct moveWithPP {
#define SpDefense(spDefense) SpDefense_(__LINE__, spDefense)
#define Speed(speed) Speed_(__LINE__, speed)
#define Item(item) Item_(__LINE__, item)
#define Moves(move1, ...) Moves_(__LINE__, (const u16 [MAX_MON_MOVES]) { move1, __VA_ARGS__ })
#define Moves(move1, ...) do { u16 moves_[MAX_MON_MOVES] = {move1, __VA_ARGS__}; Moves_(__LINE__, moves_); } while(0)
#define MovesWithPP(movewithpp1, ...) MovesWithPP_(__LINE__, (struct moveWithPP[MAX_MON_MOVES]) {movewithpp1, __VA_ARGS__})
#define Friendship(friendship) Friendship_(__LINE__, friendship)
#define Status1(status1) Status1_(__LINE__, status1)
Expand All @@ -789,6 +843,8 @@ void OpenPokemon(u32 sourceLine, u32 side, u32 species);
void ClosePokemon(u32 sourceLine);

void RNGSeed_(u32 sourceLine, u32 seed);
void AIFlags_(u32 sourceLine, u32 flags);
void AILogScores(u32 sourceLine);
void Gender_(u32 sourceLine, u32 gender);
void Nature_(u32 sourceLine, u32 nature);
void Ability_(u32 sourceLine, u32 ability);
Expand All @@ -801,12 +857,28 @@ void SpAttack_(u32 sourceLine, u32 spAttack);
void SpDefense_(u32 sourceLine, u32 spDefense);
void Speed_(u32 sourceLine, u32 speed);
void Item_(u32 sourceLine, u32 item);
void Moves_(u32 sourceLine, const u16 moves[MAX_MON_MOVES]);
void Moves_(u32 sourceLine, u16 moves[MAX_MON_MOVES]);
void MovesWithPP_(u32 sourceLine, struct moveWithPP moveWithPP[MAX_MON_MOVES]);
void Friendship_(u32 sourceLine, u32 friendship);
void Status1_(u32 sourceLine, u32 status1);
void OTName_(u32 sourceLine, const u8 *otName);

// Created for easy use of EXPECT_MOVES, so the user can provide 1, 2, 3 or 4 moves for AI which can pass the test.
struct FourMoves
{
u16 moves[MAX_MON_MOVES];
};

struct TestAIScoreStruct
{
u32 move1;
bool8 explicitMove1;
u32 valueOrMoveId2;
bool8 explicitValueOrMoveId2;
struct BattlePokemon *target;
bool8 explicitTarget;
};

#define PLAYER_PARTY (gBattleTestRunnerState->data.recordedBattle.playerParty)
#define OPPONENT_PARTY (gBattleTestRunnerState->data.recordedBattle.opponentParty)

Expand All @@ -819,6 +891,22 @@ enum { TURN_CLOSED, TURN_OPEN, TURN_CLOSING };
#define TURN for (OpenTurn(__LINE__); gBattleTestRunnerState->data.turnState == TURN_OPEN; CloseTurn(__LINE__))

#define MOVE(battler, ...) Move(__LINE__, battler, (struct MoveContext) { APPEND_TRUE(__VA_ARGS__) })

#define EXPECT_MOVE(battler, ...) ExpectMove(__LINE__, battler, (struct MoveContext) { APPEND_TRUE(__VA_ARGS__) })
#define NOT_EXPECT_MOVE(battler, _move) ExpectMove(__LINE__, battler, (struct MoveContext) { .move = _move, .explicitMove = TRUE, .notExpected = TRUE, .explicitNotExpected = TRUE, })
#define EXPECT_MOVES(battler, ...) ExpectMoves(__LINE__, battler, FALSE, (struct FourMoves) { __VA_ARGS__ })
#define NOT_EXPECT_MOVES(battler, ...) ExpectMoves(__LINE__, battler, TRUE, (struct FourMoves) { __VA_ARGS__ })
#define EXPECT_SEND_OUT(battler, partyIndex) ExpectSendOut(__LINE__, battler, partyIndex)
#define EXPECT_SWITCH(battler, partyIndex) ExpectSwitch(__LINE__, battler, partyIndex)
#define SCORE_EQ(battler, ...) Score(__LINE__, battler, CMP_EQUAL, FALSE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } )
#define SCORE_NE(battler, ...) Score(__LINE__, battler, CMP_NOT_EQUAL, FALSE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } )
#define SCORE_GT(battler, ...) Score(__LINE__, battler, CMP_GREATER_THAN, FALSE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } )
#define SCORE_LT(battler, ...) Score(__LINE__, battler, CMP_LESS_THAN, FALSE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } )
#define SCORE_EQ_VAL(battler, ...) Score(__LINE__, battler, CMP_EQUAL, TRUE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } )
#define SCORE_NE_VAL(battler, ...) Score(__LINE__, battler, CMP_NOT_EQUAL, TRUE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } )
#define SCORE_GT_VAL(battler, ...) Score(__LINE__, battler, CMP_GREATER_THAN, TRUE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } )
#define SCORE_LT_VAL(battler, ...) Score(__LINE__, battler, CMP_LESS_THAN, TRUE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } )

#define FORCED_MOVE(battler) ForcedMove(__LINE__, battler)
#define SWITCH(battler, partyIndex) Switch(__LINE__, battler, partyIndex)
#define SKIP_TURN(battler) SkipTurn(__LINE__, battler)
Expand All @@ -845,6 +933,8 @@ struct MoveContext
// TODO: u8 zMove:1;
u16 allowed:1;
u16 explicitAllowed:1;
u16 notExpected:1; // Has effect only with EXPECT_MOVE
u16 explicitNotExpected:1;
struct BattlePokemon *target;
bool8 explicitTarget;
struct TurnRNG rng;
Expand All @@ -864,6 +954,11 @@ struct ItemContext
void OpenTurn(u32 sourceLine);
void CloseTurn(u32 sourceLine);
void Move(u32 sourceLine, struct BattlePokemon *, struct MoveContext);
void ExpectMove(u32 sourceLine, struct BattlePokemon *, struct MoveContext);
void ExpectMoves(u32 sourceLine, struct BattlePokemon *battler, bool32 notExpected, struct FourMoves moves);
void ExpectSendOut(u32 sourceLine, struct BattlePokemon *battler, u32 partyIndex);
void ExpectSwitch(u32 sourceLine, struct BattlePokemon *battler, u32 partyIndex);
void Score(u32 sourceLine, struct BattlePokemon *battler, u32 cmp, bool32 toValue, struct TestAIScoreStruct cmpCtx);
void ForcedMove(u32 sourceLine, struct BattlePokemon *);
void Switch(u32 sourceLine, struct BattlePokemon *, u32 partyIndex);
void SkipTurn(u32 sourceLine, struct BattlePokemon *);
Expand Down
Loading
Loading