mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-13 17:27:46 +00:00
Added test that ensures all lands can be played
This commit is contained in:
@@ -8,6 +8,7 @@ import forge.game.phase.PhaseType;
|
|||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilityManaPart;
|
import forge.game.spellability.AbilityManaPart;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -173,9 +174,9 @@ public class GameStateEvaluator {
|
|||||||
colors_produced.addAll(Arrays.asList(mp.mana(m).split(" ")));
|
colors_produced.addAll(Arrays.asList(mp.mana(m).split(" ")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value = 100 * max_produced;
|
value += 100 * max_produced;
|
||||||
int size = max(colors_produced.size(), colors_produced.contains("Any") ? 5 : 0);
|
int size = max(colors_produced.size(), colors_produced.contains("Any") ? 5 : 0);
|
||||||
value += size * 2;
|
value += size * 6;
|
||||||
|
|
||||||
// add a value for each activated ability that the land has that's not an activated ability.
|
// add a value for each activated ability that the land has that's not an activated ability.
|
||||||
for (SpellAbility m: c.getNonManaAbilities()) {
|
for (SpellAbility m: c.getNonManaAbilities()) {
|
||||||
@@ -184,6 +185,12 @@ public class GameStateEvaluator {
|
|||||||
value += 6;
|
value += 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a value for each static ability that the land has
|
||||||
|
for (StaticAbility s : c.getStaticAbilities()) {
|
||||||
|
// More than the value of having a card in hand. See comment above
|
||||||
|
value += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
} else if (c.isEnchantingCard()) {
|
} else if (c.isEnchantingCard()) {
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class SpellAbilityPicker {
|
|||||||
print("---- choose ability (phase = " + phaseStr + ")");
|
print("---- choose ability (phase = " + phaseStr + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SpellAbility> getCandidateSpellsAndAbilities() {
|
public List<SpellAbility> getCandidateSpellsAndAbilities() {
|
||||||
CardCollection cards = ComputerUtilAbility.getAvailableCards(game, player);
|
CardCollection cards = ComputerUtilAbility.getAvailableCards(game, player);
|
||||||
cards = ComputerUtilCard.dedupeCards(cards);
|
cards = ComputerUtilCard.dedupeCards(cards);
|
||||||
List<SpellAbility> all = ComputerUtilAbility.getSpellAbilities(cards, player);
|
List<SpellAbility> all = ComputerUtilAbility.getSpellAbilities(cards, player);
|
||||||
@@ -351,7 +351,7 @@ public class SpellAbilityPicker {
|
|||||||
return AiPlayDecision.WillPlay;
|
return AiPlayDecision.WillPlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Score evaluateSa(final SimulationController controller, PhaseType phase, List<SpellAbility> saList, int saIndex) {
|
public Score evaluateSa(final SimulationController controller, PhaseType phase, List<SpellAbility> saList, int saIndex) {
|
||||||
controller.evaluateSpellAbility(saList, saIndex);
|
controller.evaluateSpellAbility(saList, saIndex);
|
||||||
SpellAbility sa = saList.get(saIndex);
|
SpellAbility sa = saList.get(saIndex);
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,22 @@ import forge.model.FModel;
|
|||||||
public class SimulationTest {
|
public class SimulationTest {
|
||||||
private static boolean initialized = false;
|
private static boolean initialized = false;
|
||||||
|
|
||||||
|
public Game resetGame() {
|
||||||
|
// need to be done after FModel.initialize, or the Localizer isn't loaded yet
|
||||||
|
List<RegisteredPlayer> players = Lists.newArrayList();
|
||||||
|
Deck d1 = new Deck();
|
||||||
|
players.add(new RegisteredPlayer(d1).setPlayer(new LobbyPlayerAi("p2", null)));
|
||||||
|
Set<AIOption> options = new HashSet<>();
|
||||||
|
options.add(AIOption.USE_SIMULATION);
|
||||||
|
players.add(new RegisteredPlayer(d1).setPlayer(new LobbyPlayerAi("p1", options)));
|
||||||
|
GameRules rules = new GameRules(GameType.Constructed);
|
||||||
|
Match match = new Match(rules, players, "Test");
|
||||||
|
Game game = new Game(players, rules, match);
|
||||||
|
game.setAge(GameStage.Play);
|
||||||
|
|
||||||
|
return game;
|
||||||
|
}
|
||||||
|
|
||||||
protected Game initAndCreateGame() {
|
protected Game initAndCreateGame() {
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
GuiBase.setInterface(new GuiDesktop());
|
GuiBase.setInterface(new GuiDesktop());
|
||||||
@@ -47,19 +63,7 @@ public class SimulationTest {
|
|||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to be done after FModel.initialize, or the Localizer isn't loaded yet
|
return resetGame();
|
||||||
List<RegisteredPlayer> players = Lists.newArrayList();
|
|
||||||
Deck d1 = new Deck();
|
|
||||||
players.add(new RegisteredPlayer(d1).setPlayer(new LobbyPlayerAi("p2", null)));
|
|
||||||
Set<AIOption> options = new HashSet<>();
|
|
||||||
options.add(AIOption.USE_SIMULATION);
|
|
||||||
players.add(new RegisteredPlayer(d1).setPlayer(new LobbyPlayerAi("p1", options)));
|
|
||||||
GameRules rules = new GameRules(GameType.Constructed);
|
|
||||||
Match match = new Match(rules, players, "Test");
|
|
||||||
Game game = new Game(players, rules, match);
|
|
||||||
game.setAge(GameStage.Play);
|
|
||||||
|
|
||||||
return game;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected GameSimulator createSimulator(Game game, Player p) {
|
protected GameSimulator createSimulator(Game game, Player p) {
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
package forge.ai.simulation;
|
package forge.ai.simulation;
|
||||||
|
|
||||||
import forge.game.spellability.LandAbility;
|
import forge.game.spellability.LandAbility;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.model.FModel;
|
||||||
import org.testng.AssertJUnit;
|
import org.testng.AssertJUnit;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
@@ -371,6 +375,84 @@ public class SpellAbilityPickerSimulationTest extends SimulationTest {
|
|||||||
AssertJUnit.assertEquals(desired, sa.getTargetCard());
|
AssertJUnit.assertEquals(desired, sa.getTargetCard());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ensureAllLandsArePlayable() {
|
||||||
|
initAndCreateGame();
|
||||||
|
|
||||||
|
System.out.println("Adding lands to hand");
|
||||||
|
|
||||||
|
// add every land to the player's hand
|
||||||
|
// SimulationController.MAX_DEPTH = 0;
|
||||||
|
List<Card> funky = new ArrayList<>();
|
||||||
|
String previous = "";
|
||||||
|
for (PaperCard c : FModel.getMagicDb().getCommonCards().getAllCards()) {
|
||||||
|
// reset the game
|
||||||
|
Game game = resetGame();
|
||||||
|
Player p = game.getPlayers().get(1);
|
||||||
|
Player opponent = game.getPlayers().get(0);
|
||||||
|
opponent.setLife(20, null);
|
||||||
|
|
||||||
|
// add one of each basic to the battlefield so that bouncelands and similar work
|
||||||
|
addCard("Plains", p);
|
||||||
|
addCard("Island", p);
|
||||||
|
addCard("Swamp", p);
|
||||||
|
addCard("Mountain", p);
|
||||||
|
addCard("Forest", p);
|
||||||
|
// Add basics to library to ensure fetches work
|
||||||
|
addCardToZone("Plains", p, ZoneType.Library);
|
||||||
|
addCardToZone("Island", p, ZoneType.Library);
|
||||||
|
addCardToZone("Swamp", p, ZoneType.Library);
|
||||||
|
addCardToZone("Mountain", p, ZoneType.Library);
|
||||||
|
addCardToZone("Forest", p, ZoneType.Library);
|
||||||
|
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||||
|
game.getAction().checkStateEffects(true);
|
||||||
|
|
||||||
|
// Only add one version at a time
|
||||||
|
if (c.getName().equals(previous)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
previous = c.getName();
|
||||||
|
if (c.getRules().getType().isLand()) {
|
||||||
|
// Skip glacial chasm, it's really weird.
|
||||||
|
if (c.getName().equals("Glacial Chasm")) {
|
||||||
|
System.out.println("Skipping " + c.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addCardToZone(c.getName(), p, ZoneType.Hand);
|
||||||
|
|
||||||
|
// Once the card has been added to the hand, test it
|
||||||
|
|
||||||
|
GameStateEvaluator.Score s = new GameStateEvaluator().getScoreForGameState(game, p);
|
||||||
|
System.out.println("Starting score: " + s);
|
||||||
|
SpellAbilityPicker picker = new SpellAbilityPicker(game, p);
|
||||||
|
List<SpellAbility> candidateSAs = picker.getCandidateSpellsAndAbilities();
|
||||||
|
for (int i = 0; i < candidateSAs.size(); i++) {
|
||||||
|
SpellAbility sa = candidateSAs.get(i);
|
||||||
|
if (sa.isActivatedAbility()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
GameStateEvaluator.Score value = picker.evaluateSa(new SimulationController(s), game.getPhaseHandler().getPhase(), candidateSAs, i);
|
||||||
|
System.out.println("sa: " + sa.getHostCard() + ", value: " + value);
|
||||||
|
if (!(value.value > s.value)) {
|
||||||
|
funky.add(sa.getHostCard());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure that every land play has a higher evaluation than doing nothing
|
||||||
|
System.out.println(funky);
|
||||||
|
for (Card c : funky) {
|
||||||
|
GameStateEvaluator gse = new GameStateEvaluator();
|
||||||
|
Game game = resetGame();
|
||||||
|
System.out.println(c.getName() + ": " + gse.evalCard(game, game.getStartingPlayer(), c));
|
||||||
|
}
|
||||||
|
AssertJUnit.assertEquals(0, funky.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPlayRememberedCardsLand() {
|
public void testPlayRememberedCardsLand() {
|
||||||
Game game = initAndCreateGame();
|
Game game = initAndCreateGame();
|
||||||
|
|||||||
Reference in New Issue
Block a user