Fix simulation AI exception with random effects.

Uses a seeded deterministic random generator when simulating choices, which ensures  the same number of sub-choices are always used, which the code requires. Adds a test.
This commit is contained in:
asvitkine
2022-12-09 16:08:44 -05:00
parent 95167ed675
commit 96b6bafc2b
3 changed files with 66 additions and 3 deletions

View File

@@ -439,4 +439,50 @@ public class SpellAbilityPickerSimulationTest extends SimulationTest {
AssertJUnit.assertEquals("Destroy target nonblack creature.", sa.toString());
AssertJUnit.assertEquals(blocker, sa.getTargetCard());
}
@Test
public void testChoicesResultingFromRandomEffects() {
// Sometimes, the effect of a spell can be random, and as a result of that, new choices
// could be selected during simulation. This test verifies that this doesn't cause problems.
//
// Note: The current implementation works around the issue by setting a consistent random
// seed during choice evaluation, although in the future, it may make sense to handle it
// some other way.
// Run the test 100 times to ensure there's no flakiness.
for (int i = 0; i < 100; i++) {
Game game = initAndCreateGame();
Player p = game.getPlayers().get(1);
Player opponent = game.getPlayers().get(0);
addCardToZone("Chaos Warp", p, ZoneType.Hand);
addCard("Mountain", p);
addCard("Mountain", p);
addCard("Mountain", p);
addCard("Plains", opponent);
addCard("Mountain", opponent);
addCard("Forest", opponent);
// Use a card that is worthwhile to target even if the shuffle ends up choosing it
// again. In this case, life loss on ETB and leaving.
Card expectedTarget = addCard("Raving Oni-Slave", opponent);
addCardToZone("Chaos Warp", opponent, ZoneType.Library);
addCardToZone("Island", opponent, ZoneType.Library);
addCardToZone("Swamp", opponent, ZoneType.Library);
// The presence of Pilgrim's Eye in the library is important for this test, as this
// will result in sub-choices (which land to pick) if this card ends up being the top
// of the library during simulation.
addCardToZone("Pilgrim's Eye", opponent, ZoneType.Library);
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);
SpellAbilityPicker picker = new SpellAbilityPicker(game, p);
SpellAbility sa = picker.chooseSpellAbilityToPlay(null);
AssertJUnit.assertNotNull(sa);
AssertJUnit.assertEquals("Chaos Warp", sa.getHostCard().getName());
AssertJUnit.assertEquals(expectedTarget, sa.getTargetCard());
}
}
}