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

Added test support for 5 battle configs #5914

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
5 changes: 5 additions & 0 deletions include/constants/generational_changes.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

enum GenConfigTag
{
GEN_CONFIG_CRIT_CHANCE,
GEN_CONFIG_CRIT_MULTIPLIER,
GEN_CONFIG_PARALYSIS_SPEED,
GEN_CONFIG_CONFUSION_SELF_DMG_CHANCE,
GEN_CONFIG_MULTI_HIT_CHANCE,
GEN_CONFIG_GALE_WINGS,
GEN_CONFIG_COUNT
};
Expand Down
7 changes: 6 additions & 1 deletion include/generational_changes.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@

static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] =
{
[GEN_CONFIG_GALE_WINGS] = B_GALE_WINGS,
[GEN_CONFIG_CRIT_CHANCE] = B_CRIT_CHANCE,
[GEN_CONFIG_CRIT_MULTIPLIER] = B_CRIT_MULTIPLIER,
[GEN_CONFIG_PARALYSIS_SPEED] = B_PARALYSIS_SPEED,
[GEN_CONFIG_CONFUSION_SELF_DMG_CHANCE] = B_CONFUSION_SELF_DMG_CHANCE,
[GEN_CONFIG_MULTI_HIT_CHANCE] = B_MULTI_HIT_CHANCE,
[GEN_CONFIG_GALE_WINGS] = B_GALE_WINGS,
};

#if TESTING
Expand Down
2 changes: 1 addition & 1 deletion src/battle_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4809,7 +4809,7 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect)

// paralysis drop
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && ability != ABILITY_QUICK_FEET)
speed /= B_PARALYSIS_SPEED >= GEN_7 ? 2 : 4;
speed /= GetGenConfig(GEN_CONFIG_PARALYSIS_SPEED) >= GEN_7 ? 2 : 4;

if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SWAMP)
speed /= 4;
Expand Down
11 changes: 5 additions & 6 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
#include "battle_ai_util.h"
#include "battle_scripts.h"
#include "battle_z_move.h"
#include "constants/moves.h"
#include "constants/abilities.h"
#include "item.h"
#include "util.h"
#include "pokemon.h"
Expand Down Expand Up @@ -47,6 +45,7 @@
#include "pokenav.h"
#include "menu_specialized.h"
#include "data.h"
#include "generational_changes.h"
#include "constants/abilities.h"
#include "constants/battle_anim.h"
#include "constants/battle_move_effects.h"
Expand Down Expand Up @@ -1825,9 +1824,9 @@ static const u32 sCriticalHitOdds[] = {16, 8, 4, 3, 2}; // Gens 2,3,4,5

static inline u32 GetCriticalHitOdds(u32 critChance)
{
if (B_CRIT_CHANCE >= GEN_7)
if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) >= GEN_7)
return sGen7CriticalHitOdds[critChance];
if (B_CRIT_CHANCE == GEN_6)
if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_6)
return sGen6CriticalHitOdds[critChance];

return sCriticalHitOdds[critChance];
Expand Down Expand Up @@ -2010,7 +2009,7 @@ static void Cmd_critcalc(void)
u16 partySlot;
s32 critChance;

if (B_CRIT_CHANCE == GEN_1)
if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_1)
critChance = CalcCritChanceStageGen1(gBattlerAttacker, gBattlerTarget, gCurrentMove, TRUE);
else
critChance = CalcCritChanceStage(gBattlerAttacker, gBattlerTarget, gCurrentMove, TRUE);
Expand All @@ -2025,7 +2024,7 @@ static void Cmd_critcalc(void)
gIsCriticalHit = TRUE;
else
{
if (B_CRIT_CHANCE == GEN_1)
if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_1)
{
u8 critRoll = RandomUniform(RNG_CRITICAL_HIT, 1, 256);
if (critRoll <= critChance)
Expand Down
7 changes: 4 additions & 3 deletions src/battle_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "battle_setup.h"
#include "battle_z_move.h"
#include "battle_gimmick.h"
#include "generational_changes.h"
#include "party_menu.h"
#include "pokemon.h"
#include "international_string_util.h"
Expand Down Expand Up @@ -3470,7 +3471,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION)
{
// confusion dmg
if (RandomPercentage(RNG_CONFUSION, (B_CONFUSION_SELF_DMG_CHANCE >= GEN_7 ? 33 : 50)))
if (RandomPercentage(RNG_CONFUSION, (GetGenConfig(GEN_CONFIG_CONFUSION_SELF_DMG_CHANCE) >= GEN_7 ? 33 : 50)))
{
gBattleCommunication[MULTISTRING_CHOOSER] = TRUE;
gBattlerTarget = gBattlerAttacker;
Expand Down Expand Up @@ -10068,7 +10069,7 @@ static inline uq4_12_t GetBurnOrFrostBiteModifier(struct DamageCalculationData *
static inline uq4_12_t GetCriticalModifier(bool32 isCrit)
{
if (isCrit)
return B_CRIT_MULTIPLIER >= GEN_6 ? UQ_4_12(1.5) : UQ_4_12(2.0);
return GetGenConfig(GEN_CONFIG_CRIT_MULTIPLIER) >= GEN_6 ? UQ_4_12(1.5) : UQ_4_12(2.0);
return UQ_4_12(1.0);
}

Expand Down Expand Up @@ -11654,7 +11655,7 @@ static void SetRandomMultiHitCounter()
{
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LOADED_DICE)
gMultiHitCounter = RandomUniform(RNG_LOADED_DICE, 4, 5);
else if (B_MULTI_HIT_CHANCE >= GEN_5)
else if (GetGenConfig(GEN_CONFIG_MULTI_HIT_CHANCE) >= GEN_5)
gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 7, 7, 3, 3); // 35%: 2 hits, 35%: 3 hits, 15% 4 hits, 15% 5 hits.
else
gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 3, 3, 1, 1); // 37.5%: 2 hits, 37.5%: 3 hits, 12.5% 4 hits, 12.5% 5 hits.
Expand Down
49 changes: 49 additions & 0 deletions test/battle/ability/battle_armor.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "global.h"
#include "test/battle.h"

SINGLE_BATTLE_TEST("Battle Armor and Shell Armor block critical hits")
{
u32 species;
u32 ability;

PARAMETRIZE { species = SPECIES_KINGLER; ability = ABILITY_SHELL_ARMOR; }
PARAMETRIZE { species = SPECIES_ARMALDO; ability = ABILITY_BATTLE_ARMOR; }

GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { MOVE(player, MOVE_TACKLE, criticalHit: TRUE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
NOT MESSAGE("A critical hit!");
}
}

SINGLE_BATTLE_TEST("Mold Breaker, Teravolt and Turboblaze ignore Battle Armor and Shell Armor")
{
u32 j;
u32 species1, species2, ability1, ability2;
static const u32 breakerData[][2] =
{
{SPECIES_PINSIR, ABILITY_MOLD_BREAKER},
{SPECIES_ZEKROM, ABILITY_TERAVOLT},
{SPECIES_RESHIRAM, ABILITY_TURBOBLAZE},
};

for (j = 0; j < ARRAY_COUNT(breakerData); j++)
{
PARAMETRIZE { species1 = breakerData[j][0]; ability1 = breakerData[j][1]; species2 = SPECIES_KINGLER; ability2 = ABILITY_SHELL_ARMOR; }
PARAMETRIZE { species1 = breakerData[j][0]; ability1 = breakerData[j][1]; species2 = SPECIES_ARMALDO; ability2 = ABILITY_BATTLE_ARMOR; }
}

GIVEN {
PLAYER(species1) { Ability(ability1); }
OPPONENT(species2) { Ability(ability2); }
} WHEN {
TURN { MOVE(player, MOVE_TACKLE, criticalHit: TRUE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
MESSAGE("A critical hit!");
}
}
2 changes: 1 addition & 1 deletion test/battle/ability/inner_focus.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ SINGLE_BATTLE_TEST("Inner Focus prevents flinching")
}
}

SINGLE_BATTLE_TEST("Inner Focus is ignored by Mold Breaker")
SINGLE_BATTLE_TEST("Mold Breaker ignores Inner Focus")
{
GIVEN {
PLAYER(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); };
Expand Down
16 changes: 16 additions & 0 deletions test/battle/ability/merciless.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "global.h"
#include "test/battle.h"

SINGLE_BATTLE_TEST("Merciless causes a move to result in a critical hit if the target is poisoned")
{
PASSES_RANDOMLY(1, 1, RNG_CRITICAL_HIT);
GIVEN {
PLAYER(SPECIES_MAREANIE) { Ability(ABILITY_MERCILESS); }
OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); }
} WHEN {
TURN { MOVE(player, MOVE_TACKLE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
MESSAGE("A critical hit!");
}
}
4 changes: 2 additions & 2 deletions test/battle/ability/own_tempo.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ SINGLE_BATTLE_TEST("Own Tempo prevents confusion from moves by the user")
}
}

SINGLE_BATTLE_TEST("Own Tempo is ignored by Mold Breaker")
SINGLE_BATTLE_TEST("Mold Breaker ignores Own Tempo")
{
KNOWN_FAILING; // Ideally the func CanBeConfused should be split into AttackerCanBeConfused and TargetCanBeConfused or we do it in the same func but have a check for when battlerAtk == battlerDef
GIVEN {
Expand All @@ -73,7 +73,7 @@ SINGLE_BATTLE_TEST("Own Tempo is ignored by Mold Breaker")
}
}

SINGLE_BATTLE_TEST("Own Tempo cures confusion obtained from an opponent with Mold Breaker")
SINGLE_BATTLE_TEST("Mold Breaker does not prevent Own Tempo from curing confusion right after")
{
KNOWN_FAILING;
GIVEN {
Expand Down
36 changes: 24 additions & 12 deletions test/battle/ability/parental_bond.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,15 @@ SINGLE_BATTLE_TEST("Parental Bond-converted moves only hit once on Lightning Rod
}
}

SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they still hit twice 35% of the time")
SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they still hit twice 37.5/35% of the time")
{
PASSES_RANDOMLY(35, 100, RNG_HITS);
u32 genConfig, passes, trials;
PARAMETRIZE { genConfig = GEN_4; passes = 3; trials = 8; }
PARAMETRIZE { genConfig = GEN_5; passes = 7; trials = 20; }
PASSES_RANDOMLY(passes, trials, RNG_HITS);

GIVEN {
ASSUME(B_MULTI_HIT_CHANCE >= GEN_5);
WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig);
ASSUME(gMovesInfo[MOVE_COMET_PUNCH].category != DAMAGE_CATEGORY_STATUS);
ASSUME(gMovesInfo[MOVE_COMET_PUNCH].effect == EFFECT_MULTI_HIT);
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
Expand All @@ -157,12 +160,15 @@ SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they stil
}
}

SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they still hit thrice 35% of the time")
SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they still hit thrice 37.5/35% of the time")
{
PASSES_RANDOMLY(35, 100, RNG_HITS);
u32 genConfig, passes, trials;
PARAMETRIZE { genConfig = GEN_4; passes = 3; trials = 8; }
PARAMETRIZE { genConfig = GEN_5; passes = 7; trials = 20; }
PASSES_RANDOMLY(passes, trials, RNG_HITS);

GIVEN {
ASSUME(B_MULTI_HIT_CHANCE >= GEN_5);
WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig);
ASSUME(gMovesInfo[MOVE_COMET_PUNCH].category != DAMAGE_CATEGORY_STATUS);
ASSUME(gMovesInfo[MOVE_COMET_PUNCH].effect == EFFECT_MULTI_HIT);
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
Expand All @@ -184,12 +190,15 @@ SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they stil
}
}

SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they still hit four times 15% of the time")
SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they still hit four times 12.5/15% of the time")
{
PASSES_RANDOMLY(15, 100, RNG_HITS);
u32 genConfig, passes, trials;
PARAMETRIZE { genConfig = GEN_4; passes = 1; trials = 8; }
PARAMETRIZE { genConfig = GEN_5; passes = 3; trials = 20; }
PASSES_RANDOMLY(passes, trials, RNG_HITS);

GIVEN {
ASSUME(B_MULTI_HIT_CHANCE >= GEN_5);
WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig);
ASSUME(gMovesInfo[MOVE_COMET_PUNCH].category != DAMAGE_CATEGORY_STATUS);
ASSUME(gMovesInfo[MOVE_COMET_PUNCH].effect == EFFECT_MULTI_HIT);
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
Expand All @@ -212,12 +221,15 @@ SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they stil
}
}

SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they still hit five times 15% of the time")
SINGLE_BATTLE_TEST("Parental Bond has no affect on multi hit moves and they still hit five times 12.5/15% of the time")
{
PASSES_RANDOMLY(15, 100, RNG_HITS);
u32 genConfig, passes, trials;
PARAMETRIZE { genConfig = GEN_4; passes = 1; trials = 8; }
PARAMETRIZE { genConfig = GEN_5; passes = 3; trials = 20; }
PASSES_RANDOMLY(passes, trials, RNG_HITS);

GIVEN {
ASSUME(B_MULTI_HIT_CHANCE >= GEN_5);
WITH_CONFIG(GEN_CONFIG_MULTI_HIT_CHANCE, genConfig);
ASSUME(gMovesInfo[MOVE_COMET_PUNCH].category != DAMAGE_CATEGORY_STATUS);
ASSUME(gMovesInfo[MOVE_COMET_PUNCH].effect == EFFECT_MULTI_HIT);
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
Expand Down
4 changes: 4 additions & 0 deletions test/battle/ability/shell_armor.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include "global.h"
#include "test/battle.h"

// Tests for Shell Armor are handled in test/battle/ability/battle_armor.c
22 changes: 22 additions & 0 deletions test/battle/ability/super_luck.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "global.h"
#include "test/battle.h"

SINGLE_BATTLE_TEST("Super Luck increases the critical hit ratio by 1 stage")
{
u32 genConfig = 0;
for (u32 j = GEN_2; j < GEN_LATEST + 1; j++)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do these for loops start at Gen 2 if Gen 1 configs exist?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, right. I need to make Gen 1 crit mechanic tests. Time to hit the books! xD

PARAMETRIZE { genConfig = j; }
PASSES_RANDOMLY(1, 8, RNG_CRITICAL_HIT);
GIVEN {
WITH_CONFIG(GEN_CONFIG_CRIT_CHANCE, genConfig);
PLAYER(SPECIES_TOGEPI) { Ability(ABILITY_SUPER_LUCK); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TACKLE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
MESSAGE("A critical hit!");
}
}

TO_DO_BATTLE_TEST("Super Luck increases the chances of wild Pokémon holding items (Gen8+)");
Loading
Loading