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

Readd missing RNG tiebreakers for speed and priority ties #4772

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 13 additions & 4 deletions src/battle_ai_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2649,8 +2649,12 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
ADJUST_SCORE(SLOW_KILL);
}
else if (CanTargetFaintAi(battlerDef, battlerAtk)
&& GetWhichBattlerFaster(battlerAtk, battlerDef, TRUE) != AI_IS_FASTER
&& GetMovePriority(battlerAtk, move) > 0)
&& GetWhichBattlerFasterArgs(battlerAtk, battlerDef, TRUE,
AI_DATA->abilities[battlerAtk], AI_DATA->abilities[battlerDef],
AI_DATA->holdEffects[battlerAtk], AI_DATA->holdEffects[battlerDef],
AI_DATA->speedStats[battlerAtk], AI_DATA->speedStats[battlerDef],
0, 0) != AI_IS_FASTER
&& GetMovePriority(battlerAtk, move) > 0)
{
ADJUST_SCORE(LAST_CHANCE);
}
Expand Down Expand Up @@ -4037,8 +4041,13 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
if (IsStatBoostingBerry(item) && aiData->hpPercents[battlerAtk] > 60)
ADJUST_SCORE(WEAK_EFFECT);
else if (ShouldRestoreHpBerry(battlerAtk, item) && !CanAIFaintTarget(battlerAtk, battlerDef, 0)
&& ((GetWhichBattlerFaster(battlerAtk, battlerDef, TRUE) == 1 && CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 0))
|| !CanTargetFaintAiWithMod(battlerDef, battlerAtk, toHeal, 0)))
&& ((GetWhichBattlerFasterArgs(battlerAtk, battlerDef, TRUE,
AI_DATA->abilities[battlerAtk], AI_DATA->abilities[battlerDef],
AI_DATA->holdEffects[battlerAtk], AI_DATA->holdEffects[battlerDef],
AI_DATA->speedStats[battlerAtk], AI_DATA->speedStats[battlerDef],
0, 0) != AI_IS_FASTER
&& CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 0))
|| !CanTargetFaintAiWithMod(battlerDef, battlerAtk, toHeal, 0)))
ADJUST_SCORE(WEAK_EFFECT); // Recycle healing berry if we can't otherwise faint the target and the target wont kill us after we activate the berry
}
break;
Expand Down
6 changes: 5 additions & 1 deletion src/battle_ai_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -3419,7 +3419,11 @@ bool32 IsRecycleEncouragedItem(u32 item)
static void IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score, bool32 considerContrary)
{
u32 noOfHitsToFaint = NoOfHitsForTargetToFaintAI(battlerDef, battlerAtk);
u32 aiIsFaster = GetWhichBattlerFaster(battlerAtk, battlerDef, TRUE) == AI_IS_FASTER;
u32 aiIsFaster = GetWhichBattlerFasterArgs(battlerAtk, battlerDef, TRUE,
AI_DATA->abilities[battlerAtk], AI_DATA->abilities[battlerDef],
AI_DATA->holdEffects[battlerAtk], AI_DATA->holdEffects[battlerDef],
AI_DATA->speedStats[battlerAtk], AI_DATA->speedStats[battlerDef],
0, 0) == AI_IS_FASTER;
u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS);

if (considerContrary && AI_DATA->abilities[battlerAtk] == ABILITY_CONTRARY)
Expand Down
39 changes: 18 additions & 21 deletions src/battle_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5071,7 +5071,7 @@ s8 GetMovePriority(u32 battler, u16 move)
s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2,
u32 holdEffectBattler1, u32 holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2)
{
u32 strikesFirst = 0;
s32 strikesFirst = 0;

if (priority1 == priority2)
{
Expand All @@ -5097,26 +5097,12 @@ s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov
strikesFirst = 1;
else
{
if (speedBattler1 == speedBattler2 && Random() & 1)
{
strikesFirst = 0; // same speeds, same priorities
}
if (speedBattler1 > speedBattler2)
strikesFirst = 1;
else if (speedBattler1 < speedBattler2)
{
// battler2 has more speed
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM)
strikesFirst = 1;
else
strikesFirst = -1;
}
else
{
// battler1 has more speed
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM)
strikesFirst = -1;
else
strikesFirst = 1;
}
strikesFirst = -1;
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM)
strikesFirst = -strikesFirst;
}
}
else if (priority1 < priority2)
Expand All @@ -5139,6 +5125,7 @@ s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves)
u32 speedBattler2 = GetBattlerTotalSpeedStat(battler2);
u32 holdEffectBattler2 = GetBattlerHoldEffect(battler2, TRUE);
u32 ability2 = GetBattlerAbility(battler2);
s32 whichFaster;

if (!ignoreChosenMoves)
{
Expand All @@ -5148,8 +5135,18 @@ s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves)
priority2 = GetChosenMovePriority(battler2);
}

return GetWhichBattlerFasterArgs(battler1, battler2, ignoreChosenMoves, ability1, ability2,
whichFaster = GetWhichBattlerFasterArgs(battler1, battler2, ignoreChosenMoves, ability1, ability2,
holdEffectBattler1, holdEffectBattler2, speedBattler1, speedBattler2, priority1, priority2);

if (whichFaster == 0)
{
if (RandomWeighted(RNG_SPEED_TIE, 1, 1))
whichFaster = 1;
else
whichFaster = -1;
}

return whichFaster;
}

static void SetActionsAndBattlersTurnOrder(void)
Expand Down
4 changes: 2 additions & 2 deletions test/battle/move.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ SINGLE_BATTLE_TEST("Turn order is determined by Speed if priority ties")

SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie")
{
KNOWN_FAILING; // The algorithm is significantly biased.
PASSES_RANDOMLY(1, 2);
KNOWN_FAILING; // The RNG is used an even amount of times, so the order is always swapped back to the original.
PASSES_RANDOMLY(1, 2, RNG_SPEED_TIE);
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(1); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }
Expand Down
Loading