Skip to content

Commit

Permalink
switch type enum
Browse files Browse the repository at this point in the history
  • Loading branch information
Pawkkie committed Feb 4, 2025
1 parent a642759 commit 91fc8f5
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 14 deletions.
8 changes: 7 additions & 1 deletion include/battle_ai_switch_items.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#ifndef GUARD_BATTLE_AI_SWITCH_ITEMS_H
#define GUARD_BATTLE_AI_SWITCH_ITEMS_H

enum SwitchType
{
SWITCH_AFTER_KO,
SWITCH_MID_BATTLE,
};

void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId);
void AI_TrySwitchOrUseItem(u32 battler);
u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd);
u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType);
bool32 ShouldSwitch(u32 battler);
bool32 IsMonGrounded(u16 heldItemEffect, u32 ability, u8 type1, u8 type2);

Expand Down
12 changes: 6 additions & 6 deletions src/battle_ai_switch_items.c
Original file line number Diff line number Diff line change
Expand Up @@ -1732,7 +1732,7 @@ static bool32 CanAbilityTrapOpponent(u16 ability, u32 opponent)
return FALSE;
}

static inline bool32 IsFreeSwitch(bool32 isSwitchAfterKO, u32 battlerSwitchingOut, u32 opposingBattler)
static inline bool32 IsFreeSwitch(enum SwitchType switchType, u32 battlerSwitchingOut, u32 opposingBattler)
{
bool32 movedSecond = GetBattlerTurnOrderNum(battlerSwitchingOut) > GetBattlerTurnOrderNum(opposingBattler) ? TRUE : FALSE;

Expand All @@ -1755,7 +1755,7 @@ static inline bool32 IsFreeSwitch(bool32 isSwitchAfterKO, u32 battlerSwitchingOu
}

// Post KO check has to be last because the GetMostSuitableMonToSwitchInto call in OpponentHandleChoosePokemon assumes a KO rather than a forced switch choice
if (isSwitchAfterKO)
if (switchType == SWITCH_AFTER_KO)
return TRUE;
else
return FALSE;
Expand All @@ -1777,7 +1777,7 @@ static inline bool32 CanSwitchinWin1v1(u32 hitsToKOAI, u32 hitsToKOPlayer, bool3

// This function splits switching behaviour depending on whether the switch is free.
// Everything runs in the same loop to minimize computation time. This makes it harder to read, but hopefully the comments can guide you!
static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, u32 battler, u32 opposingBattler, u32 battlerIn1, u32 battlerIn2, bool32 isSwitchAfterKO)
static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, u32 battler, u32 opposingBattler, u32 battlerIn1, u32 battlerIn2, enum SwitchType switchType)
{
int revengeKillerId = PARTY_SIZE, slowRevengeKillerId = PARTY_SIZE, fastThreatenId = PARTY_SIZE, slowThreatenId = PARTY_SIZE, damageMonId = PARTY_SIZE;
int batonPassId = PARTY_SIZE, typeMatchupId = PARTY_SIZE, typeMatchupEffectiveId = PARTY_SIZE, defensiveMonId = PARTY_SIZE, aceMonId = PARTY_SIZE, trapperId = PARTY_SIZE;
Expand All @@ -1786,7 +1786,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
s32 playerMonHP = gBattleMons[opposingBattler].hp, maxDamageDealt = 0, damageDealt = 0;
u32 aiMove, hitsToKOAI, maxHitsToKO = 0;
u16 bestResist = UQ_4_12(1.0), bestResistEffective = UQ_4_12(1.0), typeMatchup;
bool32 isFreeSwitch = IsFreeSwitch(isSwitchAfterKO, battlerIn1, opposingBattler), isSwitchinFirst, canSwitchinWin1v1;
bool32 isFreeSwitch = IsFreeSwitch(switchType, battlerIn1, opposingBattler), isSwitchinFirst, canSwitchinWin1v1;

// Iterate through mons
for (i = firstId; i < lastId; i++)
Expand Down Expand Up @@ -1979,7 +1979,7 @@ static u32 GetNextMonInParty(struct Pokemon *party, int firstId, int lastId, u32
return PARTY_SIZE;
}

u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd)
u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType)
{
u32 opposingBattler = 0;
u32 bestMonId = PARTY_SIZE;
Expand Down Expand Up @@ -2024,7 +2024,7 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd)
// Only use better mon selection if AI_FLAG_SMART_MON_CHOICES is set for the trainer.
if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_MON_CHOICES && !IsDoubleBattle()) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic
{
bestMonId = GetBestMonIntegrated(party, firstId, lastId, battler, opposingBattler, battlerIn1, battlerIn2, switchAfterMonKOd);
bestMonId = GetBestMonIntegrated(party, firstId, lastId, battler, opposingBattler, battlerIn1, battlerIn2, switchType);
return bestMonId;
}

Expand Down
2 changes: 1 addition & 1 deletion src/battle_controller_opponent.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ static void OpponentHandleChoosePokemon(u32 battler)
// Switching out
else if (gBattleStruct->AI_monToSwitchIntoId[battler] == PARTY_SIZE)
{
chosenMonId = GetMostSuitableMonToSwitchInto(battler, TRUE);
chosenMonId = GetMostSuitableMonToSwitchInto(battler, SWITCH_AFTER_KO);
if (chosenMonId == PARTY_SIZE)
{
s32 battler1, battler2, firstId, lastId;
Expand Down
2 changes: 1 addition & 1 deletion src/battle_controller_player_partner.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ static void PlayerPartnerHandleChoosePokemon(u32 battler)
// Switching out
else if (gBattleStruct->monToSwitchIntoId[battler] >= PARTY_SIZE || !IsValidForBattle(&gPlayerParty[gBattleStruct->monToSwitchIntoId[battler]]))
{
chosenMonId = GetMostSuitableMonToSwitchInto(battler, TRUE);
chosenMonId = GetMostSuitableMonToSwitchInto(battler, SWITCH_AFTER_KO);

if (chosenMonId == PARTY_SIZE || !IsValidForBattle(&gPlayerParty[chosenMonId])) // just switch to the next mon
{
Expand Down
10 changes: 5 additions & 5 deletions src/battle_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4145,7 +4145,7 @@ enum
STATE_SELECTION_SCRIPT_MAY_RUN
};

void SetupAISwitchingData(u32 battler, bool32 isAiRisky)
void SetupAISwitchingData(u32 battler, enum SwitchType switchType)
{
s32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));

Expand All @@ -4154,7 +4154,7 @@ void SetupAISwitchingData(u32 battler, bool32 isAiRisky)
{
AI_DATA->aiSwitchPredictionInProgress = TRUE;
AI_DATA->battlerDoingPrediction = battler;
AI_DATA->mostSuitableMonId[opposingBattler] = GetMostSuitableMonToSwitchInto(opposingBattler, isAiRisky);
AI_DATA->mostSuitableMonId[opposingBattler] = GetMostSuitableMonToSwitchInto(opposingBattler, switchType);
if (ShouldSwitch(opposingBattler))
AI_DATA->shouldSwitch |= (1u << opposingBattler);
AI_DATA->aiSwitchPredictionInProgress = FALSE;
Expand All @@ -4164,7 +4164,7 @@ void SetupAISwitchingData(u32 battler, bool32 isAiRisky)
}

// AI's data
AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, isAiRisky);
AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, switchType);
if (ShouldSwitch(battler))
AI_DATA->shouldSwitch |= (1u << battler);
}
Expand All @@ -4182,7 +4182,7 @@ static void HandleTurnActionSelectionState(void)
case STATE_TURN_START_RECORD: // Recorded battle related action on start of every turn.
RecordedBattle_CopyBattlerMoves(battler);
gBattleCommunication[battler] = STATE_BEFORE_ACTION_CHOSEN;
u32 isAiRisky = AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_RISKY; // Risky AI switches aggressively even mid battle
enum SwitchType switchType = (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_RISKY) ? SWITCH_AFTER_KO : SWITCH_MID_BATTLE; // Risky AI switches aggressively even mid battle

// Do AI score computations here so we can use them in AI_TrySwitchOrUseItem
if ((gBattleTypeFlags & BATTLE_TYPE_HAS_AI || IsWildMonSmart())
Expand All @@ -4192,7 +4192,7 @@ static void HandleTurnActionSelectionState(void)

// Setup battler data
BattleAI_SetupAIData(0xF, battler);
SetupAISwitchingData(battler, isAiRisky);
SetupAISwitchingData(battler, switchType);

// Do scoring
gBattleStruct->aiMoveOrAction[battler] = BattleAI_ChooseMoveOrAction(battler);
Expand Down

0 comments on commit 91fc8f5

Please sign in to comment.