Document Battle Arcade fitness score (#1225)
Some checks failed
build / build (push) Has been cancelled

This commit is contained in:
abaresk
2026-07-02 17:09:28 -04:00
committed by GitHub
parent d229b20f28
commit 2b967480e0
6 changed files with 86 additions and 82 deletions

View File

@@ -9,7 +9,7 @@ typedef struct BattleArcadeAppArgs {
SaveData *saveData;
u8 challengeType;
u8 padding_05[2];
u8 unk_07;
u8 fitnessScore;
int *unk_08;
u8 *rouletteSpeed;
u8 *selectedEffect;

View File

@@ -21,7 +21,7 @@ void ov104_022384A8(BattleArcade *param0);
void ov104_022384B4(BattleArcade *param0);
void ov104_022384D4(BattleArcade *param0);
void ov104_022384DC(BattleArcade *param0);
int ov104_02238538(BattleArcade *param0, Party *param1, Party *param2, int param3);
int BattleArcade_FitnessScore(BattleArcade *battleArcade, Party *party1, Party *party2, int totalTurnsElapsed);
void ov104_02238658(void *param0, FrontierGraphics *param1);
void ov104_02238728(void *param0, FrontierGraphics *param1);
void ov104_02238764(BattleArcade *param0, FrontierGraphics *param1, u16 param2);

View File

@@ -23,7 +23,7 @@ typedef struct BattleArcade {
u16 currentStreak;
u16 unk_1A;
u8 unk_1C;
u8 unk_1D;
u8 fitnessScore;
u8 unk_1E;
u8 unk_1F;
u16 unk_20;

View File

@@ -153,15 +153,17 @@ static const struct {
{ 0, 1, 0, 1, 0, 1, 0 }, // ARCADE_EFFECT_GET_3_BP
};
// Columns: Foe, Ally, Env, Bonus effect weights.
// Rows: categoryTier, derived from fitness
static const u8 sCategoryWeights[][NUM_ARCADE_EFFECT_CATEGORIES] = {
{ 15, 15, 40, 30 },
{ 35, 20, 30, 15 },
{ 30, 30, 35, 5 },
{ 25, 40, 30, 5 },
{ 10, 75, 10, 5 }
{ 15, 15, 40, 30 }, // tier 0
{ 35, 20, 30, 15 }, // tier 1
{ 30, 30, 35, 5 }, // tier 2
{ 25, 40, 30, 5 }, // tier 3
{ 10, 75, 10, 5 }, // tier 4
};
static const u8 Unk_ov108_0224367C[] = {
static const u8 sCategoryTierFitnessThresholds[] = {
21,
16,
10,
@@ -180,8 +182,13 @@ typedef struct BattleArcadeApp {
u8 cursorPosID;
u8 numReceivedMsgs;
u8 cursorUpdateTimer;
u8 categoryWeightTier;
u8 unk_12;
u8 categoryTier;
// How well you did in the previous battle, based on mons fainted, status conditions, and turns
// elapsed.
//
// Higher fitness scores are more likely to yield environmental and bonus effects. Lower
// fitness scores are more likely to yield ally effects.
u8 fitnessScore;
u8 unusedFlag : 1;
u8 pointlessTimer : 7;
u8 resultCursorPos;
@@ -303,7 +310,7 @@ BOOL BattleArcadeApp_Init(ApplicationManager *appMan, int *state)
app->round = args->round;
app->battleStreak = args->currentStreak;
app->partnerBattleStreak = args->partnersStreak;
app->unk_12 = args->unk_07;
app->fitnessScore = args->fitnessScore;
app->cursorPosPtr = &args->cursorPos;
app->options = SaveData_GetOptions(app->saveData);
app->party = args->party;
@@ -1326,13 +1333,13 @@ static void GetAvailableEffects(BattleArcadeApp *app)
static void GetEffectCategoryCounts(BattleArcadeApp *app)
{
int i;
for (i = 0; i < NELEMS(Unk_ov108_0224367C); i++) {
if (app->unk_12 >= Unk_ov108_0224367C[i]) {
for (i = 0; i < NELEMS(sCategoryTierFitnessThresholds); i++) {
if (app->fitnessScore >= sCategoryTierFitnessThresholds[i]) {
break;
}
}
app->categoryWeightTier = i;
app->categoryTier = i;
for (i = 0; i < app->numAvailableEffects; i++) {
if (BattleArcade_GetCategoryFromEffect(app->availableEffects[i]) == ARCADE_EFFECT_CATEGORY_FOE) {
@@ -1352,7 +1359,7 @@ static void AssignEffectsToGrid(BattleArcadeApp *app)
u8 effectsIndex = 0;
for (int i = 0; i < GRID_SIZE; i++) {
u8 category = GetRandomCategory(app, app->categoryWeightTier);
u8 category = GetRandomCategory(app, app->categoryTier);
int numEffectsInCategory = app->availableEffectsPerCategory[category];
int startOffset = 0;
@@ -1406,14 +1413,14 @@ static void AssignEffectsToGrid(BattleArcadeApp *app)
}
}
static u8 GetRandomCategory(BattleArcadeApp *app, u8 weightsIndex)
static u8 GetRandomCategory(BattleArcadeApp *app, u8 categoryTier)
{
u8 category;
u8 sum = 0;
u16 rand = LCRNG_Next() % 100;
for (category = ARCADE_EFFECT_CATEGORY_FOE; category < NUM_ARCADE_EFFECT_CATEGORIES; category++) {
sum += sCategoryWeights[weightsIndex][category];
sum += sCategoryWeights[categoryTier][category];
if (rand < sum) {
break;

View File

@@ -119,7 +119,7 @@ BOOL FrontierScrCmd_BattleArcade_CleanupBattle(FrontierScriptContext *ctx)
BattleArcade *battleArcade = BattleFrontier_GetFacilityStruct(ctx->scriptMan->frontier);
FieldBattleDTO *dto = battleArcade->dto;
battleArcade->unk_1D = ov104_02238538(battleArcade, dto->parties[0], dto->parties[2], dto->totalTurnsElapsed);
battleArcade->fitnessScore = BattleArcade_FitnessScore(battleArcade, dto->parties[0], dto->parties[2], dto->totalTurnsElapsed);
battleArcade->wonBattle = CheckPlayerWonBattle(dto->resultMask);
if (battleArcade->activeEffect == ARCADE_EFFECT_SWAP_MONS) {
@@ -200,7 +200,7 @@ static void SetupBattleArcadeAppArgs(BattleArcadeAppArgs *args, BattleArcade *ba
args->round = ov104_0223C124(battleArcade);
args->unk_14 = &battleArcade->unk_20;
args->selectedEffect = &battleArcade->activeEffect;
args->unk_07 = battleArcade->unk_1D;
args->fitnessScore = battleArcade->fitnessScore;
args->currentStreak = battleArcade->currentStreak;
args->partnersStreak = battleArcade->unk_A78;
args->rouletteSpeed = &battleArcade->unk_1C;

View File

@@ -48,8 +48,8 @@ void ov104_02238210(BattleArcade *param0);
static u16 ov104_02238264(BattleArcadeAppArgs *param0, u8 param1);
void ov104_022384D4(BattleArcade *param0);
void ov104_022384DC(BattleArcade *param0);
int ov104_02238538(BattleArcade *param0, Party *param1, Party *param2, int param3);
static int ov104_02238584(BattleArcade *param0, Party *param1, Party *param2, u8 param3);
int BattleArcade_FitnessScore(BattleArcade *battleArcade, Party *party1, Party *party2, int totalTurnsElapsed);
static int BattleArcade_BaseFitnessScore(BattleArcade *battleArcade, Party *party1, Party *party2, u8 partySize);
void ov104_02238658(void *param0, FrontierGraphics *param1);
void ov104_02238728(void *param0, FrontierGraphics *param1);
void ov104_02238764(BattleArcade *param0, FrontierGraphics *param1, u16 param2);
@@ -489,104 +489,101 @@ void ov104_022384DC(BattleArcade *param0)
return;
}
static const u8 Unk_ov104_0223FAF0[5] = {
0x8,
0x6,
0x4,
0x0,
0x0
static const u8 sStatusConditionFitness[5] = {
8,
6,
4,
0,
0
};
static const u8 Unk_ov104_0223FAE8[5] = {
0x6,
0x4,
0x2,
0x0,
0x0
static const u8 sFaintedMonsFitness[5] = {
6,
4,
2,
0,
0
};
static const u8 Unk_ov104_0223FAFE[5][2] = {
{ 0x3, 0xA },
{ 0x5, 0x6 },
{ 0x7, 0x4 },
{ 0x9, 0x2 },
{ 0xA, 0x0 }
static const struct {
u8 turns;
u8 score;
} sTurnsElapsedFitness[5] = {
{ 3, 10 },
{ 5, 6 },
{ 7, 4 },
{ 9, 2 },
{ 10, 0 }
};
int ov104_02238538(BattleArcade *param0, Party *param1, Party *param2, int param3)
int BattleArcade_FitnessScore(BattleArcade *battleArcade, Party *party1, Party *party2, int totalTurnsElapsed)
{
u8 v0;
int v1;
Pokemon *v2;
int v3 = 0;
v0 = BattleArcade_GetPlayerPartySize(param0->challengeType, 0);
u8 partySize;
int i;
int fitness = 0;
partySize = BattleArcade_GetPlayerPartySize(battleArcade->challengeType, FALSE);
v3 += ov104_02238584(param0, param1, param2, v0);
fitness += BattleArcade_BaseFitnessScore(battleArcade, party1, party2, partySize);
for (v1 = 0; v1 < 5; v1++) {
if (param3 < Unk_ov104_0223FAFE[v1][0]) {
v3 += Unk_ov104_0223FAFE[v1][1];
for (i = 0; i < 5; i++) {
if (totalTurnsElapsed < sTurnsElapsedFitness[i].turns) {
fitness += sTurnsElapsedFitness[i].score;
break;
}
}
return v3;
return fitness;
}
static int ov104_02238584(BattleArcade *param0, Party *param1, Party *param2, u8 param3)
static int BattleArcade_BaseFitnessScore(BattleArcade *battleArcade, Party *party1, Party *party2, u8 partySize)
{
u32 v0;
u8 v1;
u8 v2;
int v3, v4;
Pokemon *v5;
u8 faintedMons;
u8 monsWithStatusCondition;
int i, fitness;
Pokemon *mon;
v4 = 0;
v1 = 0;
v2 = 0;
fitness = 0;
faintedMons = 0;
monsWithStatusCondition = 0;
for (v3 = 0; v3 < param3; v3++) {
v5 = Party_GetPokemonBySlotIndex(param1, v3);
for (i = 0; i < partySize; i++) {
mon = Party_GetPokemonBySlotIndex(party1, i);
if (Pokemon_GetValue(v5, MON_DATA_SPECIES_EXISTS, NULL) == 0) {
if (Pokemon_GetValue(mon, MON_DATA_SPECIES_EXISTS, NULL) == 0) {
continue;
}
v0 = Pokemon_GetValue(v5, MON_DATA_HP, NULL);
if (v0 == 0) {
v1++;
if (Pokemon_GetValue(mon, MON_DATA_HP, NULL) == 0) {
faintedMons++;
}
if (Pokemon_GetValue(v5, MON_DATA_STATUS, NULL) != 0) {
v2++;
if (Pokemon_GetValue(mon, MON_DATA_STATUS, NULL) != 0) {
monsWithStatusCondition++;
}
}
if (BattleArcade_IsMultiPlayerChallenge(param0->challengeType) == 1) {
for (v3 = 0; v3 < param3; v3++) {
v5 = Party_GetPokemonBySlotIndex(param2, v3);
if (BattleArcade_IsMultiPlayerChallenge(battleArcade->challengeType) == TRUE) {
for (i = 0; i < partySize; i++) {
mon = Party_GetPokemonBySlotIndex(party2, i);
if (Pokemon_GetValue(v5, MON_DATA_SPECIES_EXISTS, NULL) == 0) {
if (Pokemon_GetValue(mon, MON_DATA_SPECIES_EXISTS, NULL) == 0) {
continue;
}
v0 = Pokemon_GetValue(v5, MON_DATA_HP, NULL);
if (v0 == 0) {
v1++;
if (Pokemon_GetValue(mon, MON_DATA_HP, NULL) == 0) {
faintedMons++;
}
if (Pokemon_GetValue(v5, MON_DATA_STATUS, NULL) != 0) {
v2++;
if (Pokemon_GetValue(mon, MON_DATA_STATUS, NULL) != 0) {
monsWithStatusCondition++;
}
}
}
v4 += Unk_ov104_0223FAF0[v2];
v4 += Unk_ov104_0223FAE8[v1];
fitness += sStatusConditionFitness[monsWithStatusCondition];
fitness += sFaintedMonsFitness[faintedMons];
return v4;
return fitness;
}
void ov104_02238658(void *param0, FrontierGraphics *param1)