AI_CompareDamagingMoves changes to increase the score by 1 for best moves (#3382)
* Further optimizes AI_CompareDamagingMoves * viableMove name change + 2 tests * some issues --------- Co-authored-by: DizzyEggg <jajkodizzy@wp.pl>
This commit is contained in:
parent
1467ffa3d8
commit
f461bc3256
@ -3149,6 +3149,8 @@ static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId)
|
||||
{
|
||||
u32 i;
|
||||
bool32 multipleBestMoves = FALSE;
|
||||
s32 viableMoveScores[MAX_MON_MOVES];
|
||||
s32 bestViableMoveScore;
|
||||
s32 noOfHits[MAX_MON_MOVES];
|
||||
s32 score = 0;
|
||||
s32 leastHits = 1000;
|
||||
@ -3164,11 +3166,13 @@ static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId)
|
||||
{
|
||||
leastHits = noOfHits[i];
|
||||
}
|
||||
viableMoveScores[i] = AI_SCORE_DEFAULT;
|
||||
isPowerfulIgnoredEffect[i] = IsInIgnoredPowerfulMoveEffects(gBattleMoves[moves[i]].effect);
|
||||
}
|
||||
else
|
||||
{
|
||||
noOfHits[i] = -1;
|
||||
viableMoveScores[i] = 0;
|
||||
isPowerfulIgnoredEffect[i] = FALSE;
|
||||
}
|
||||
/*
|
||||
@ -3194,19 +3198,45 @@ static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId)
|
||||
multipleBestMoves = TRUE;
|
||||
// We need to make sure it's the current move which is objectively better.
|
||||
if (isPowerfulIgnoredEffect[i] && !isPowerfulIgnoredEffect[currId])
|
||||
ADJUST_SCORE(3);
|
||||
else if (CompareMoveAccuracies(battlerAtk, battlerDef, currId, i) == 0)
|
||||
ADJUST_SCORE(2);
|
||||
else if (AI_WhichMoveBetter(moves[currId], moves[i], battlerAtk, battlerDef, noOfHits[currId]) == 0)
|
||||
viableMoveScores[i] -= 3;
|
||||
else if (!isPowerfulIgnoredEffect[i] && isPowerfulIgnoredEffect[currId])
|
||||
viableMoveScores[currId] -= 3;
|
||||
|
||||
switch (CompareMoveAccuracies(battlerAtk, battlerDef, currId, i))
|
||||
{
|
||||
// MgbaPrintf_("%S better than %S", gMoveNames[moves[currId]], gMoveNames[moves[i]]);
|
||||
ADJUST_SCORE(1);
|
||||
case 0:
|
||||
viableMoveScores[i] -= 2;
|
||||
break;
|
||||
case 1:
|
||||
viableMoveScores[currId] -= 2;
|
||||
break;
|
||||
}
|
||||
switch (AI_WhichMoveBetter(moves[currId], moves[i], battlerAtk, battlerDef, noOfHits[currId]))
|
||||
{
|
||||
case 0:
|
||||
viableMoveScores[i] -= 1;
|
||||
break;
|
||||
case 1:
|
||||
viableMoveScores[currId] -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Turns out the current move deals the most dmg compared to the other 3.
|
||||
if (!multipleBestMoves)
|
||||
ADJUST_SCORE(1);
|
||||
else
|
||||
{
|
||||
bestViableMoveScore = 0;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (viableMoveScores[i] > bestViableMoveScore)
|
||||
bestViableMoveScore = viableMoveScores[i];
|
||||
}
|
||||
// Unless a better move was found increase score of current move
|
||||
if (viableMoveScores[currId] == bestViableMoveScore)
|
||||
ADJUST_SCORE(1);
|
||||
}
|
||||
}
|
||||
|
||||
return score;
|
||||
|
||||
@ -2063,7 +2063,6 @@ bool32 HasMoveWithSplit(u32 battler, u32 split)
|
||||
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && GetBattleMoveSplit(moves[i]) == split)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -93,6 +93,9 @@ AI_SINGLE_BATTLE_TEST("AI prefers moves with better accuracy, but only if they b
|
||||
PARAMETRIZE { move1 = MOVE_MEGA_KICK; move2 = MOVE_SLAM; move3 = MOVE_TACKLE; move4 = MOVE_GUST; hp = 5; expectedMove = MOVE_GUST; expectedMove2 = MOVE_TACKLE; turns = 1; }
|
||||
// All moves hit with No guard ability
|
||||
PARAMETRIZE { move1 = MOVE_MEGA_KICK; move2 = MOVE_GUST; hp = 5; expectedMove = MOVE_MEGA_KICK; expectedMove2 = MOVE_GUST; turns = 1; }
|
||||
// Tests to compare move that always hits and a beneficial effect. A move with higher acc should be chosen in this case.
|
||||
PARAMETRIZE { move1 = MOVE_SHOCK_WAVE; move2 = MOVE_ICY_WIND; hp = 5; expectedMove = MOVE_SHOCK_WAVE; turns = 1; }
|
||||
PARAMETRIZE { move1 = MOVE_SHOCK_WAVE; move2 = MOVE_ICY_WIND; move3 = MOVE_THUNDERBOLT; hp = 5; expectedMove = MOVE_SHOCK_WAVE; expectedMove2 = MOVE_THUNDERBOLT; turns = 1; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
@ -105,6 +108,9 @@ AI_SINGLE_BATTLE_TEST("AI prefers moves with better accuracy, but only if they b
|
||||
ASSUME(gBattleMoves[MOVE_MEGA_KICK].accuracy < gBattleMoves[MOVE_STRENGTH].accuracy);
|
||||
ASSUME(gBattleMoves[MOVE_TACKLE].accuracy == 100);
|
||||
ASSUME(gBattleMoves[MOVE_GUST].accuracy == 100);
|
||||
ASSUME(gBattleMoves[MOVE_SHOCK_WAVE].accuracy == 0);
|
||||
ASSUME(gBattleMoves[MOVE_THUNDERBOLT].accuracy == 100);
|
||||
ASSUME(gBattleMoves[MOVE_ICY_WIND].accuracy != 100);
|
||||
OPPONENT(SPECIES_EXPLOUD) { Moves(move1, move2, move3, move4); Ability(abilityAtk); SpAttack(50); } // Low Sp.Atk, so Swift deals less damage than Strength.
|
||||
} WHEN {
|
||||
switch (turns)
|
||||
@ -191,6 +197,66 @@ AI_SINGLE_BATTLE_TEST("AI prefers Earthquake over Drill Run if both require the
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI prefers a weaker move over a one with a downside effect if both require the same number of hits to ko")
|
||||
{
|
||||
u16 move1 = MOVE_NONE, move2 = MOVE_NONE, move3 = MOVE_NONE, move4 = MOVE_NONE;
|
||||
u16 hp, expectedMove, turns;
|
||||
|
||||
// Both moves require the same number of turns but Flamethrower will be chosen over Overheat (powerful effect)
|
||||
PARAMETRIZE { move1 = MOVE_OVERHEAT; move2 = MOVE_FLAMETHROWER; hp = 300; expectedMove = MOVE_FLAMETHROWER; turns = 2; }
|
||||
// Overheat kill in least amount of turns
|
||||
PARAMETRIZE { move1 = MOVE_OVERHEAT; move2 = MOVE_FLAMETHROWER; hp = 250; expectedMove = MOVE_OVERHEAT; turns = 1; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(hp); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_TYPHLOSION) { Moves(move1, move2); }
|
||||
} WHEN {
|
||||
switch (turns)
|
||||
{
|
||||
case 1:
|
||||
TURN { EXPECT_MOVE(opponent, expectedMove); SEND_OUT(player, 1); }
|
||||
break;
|
||||
case 2:
|
||||
TURN { EXPECT_MOVE(opponent, expectedMove); }
|
||||
TURN { EXPECT_MOVE(opponent, expectedMove); SEND_OUT(player, 1); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
SCENE {
|
||||
MESSAGE("Wobbuffet fainted!");
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI prefers moves with the best possible score, chosen randomly if tied")
|
||||
{
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(5); };
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_THUNDERBOLT, MOVE_SLUDGE_BOMB, MOVE_TAKE_DOWN); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVES(opponent, MOVE_THUNDERBOLT, MOVE_SLUDGE_BOMB); SEND_OUT(player, 1); }
|
||||
}
|
||||
SCENE {
|
||||
MESSAGE("Wobbuffet fainted!");
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI can choose a status move that boosts the attack by two")
|
||||
{
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(250); };
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_KANGASKHAN) { Moves(MOVE_STRENGTH, MOVE_HORN_ATTACK, MOVE_SWORDS_DANCE); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVES(opponent, MOVE_STRENGTH, MOVE_SWORDS_DANCE); }
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_STRENGTH); SEND_OUT(player, 1); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI chooses the safest option to faint the target, taking into account accuracy and move effect")
|
||||
{
|
||||
u16 move1 = MOVE_NONE, move2 = MOVE_NONE, move3 = MOVE_NONE, move4 = MOVE_NONE;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user