mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
New testing frameworks for cards. BurntheImpure test.
This commit is contained in:
parent
196f7a32d8
commit
99735b368b
25 changed files with 1297 additions and 119 deletions
|
@ -126,7 +126,7 @@ public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> i
|
||||||
@Override
|
@Override
|
||||||
public boolean chooseMulligan(Game game) {
|
public boolean chooseMulligan(Game game) {
|
||||||
logger.debug("chooseMulligan");
|
logger.debug("chooseMulligan");
|
||||||
if (hand.size() < 6)
|
if (hand.size() < 6 || isTestMode())
|
||||||
return false;
|
return false;
|
||||||
Set<Card> lands = hand.getCards(new FilterLandCard(), game);
|
Set<Card> lands = hand.getCards(new FilterLandCard(), game);
|
||||||
if (lands.size() < 2 || lands.size() > hand.size() - 2)
|
if (lands.size() < 2 || lands.size() > hand.size() - 2)
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -5,6 +5,7 @@ import mage.cards.Card;
|
||||||
import mage.cards.decks.Deck;
|
import mage.cards.decks.Deck;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.GameException;
|
import mage.game.GameException;
|
||||||
|
import mage.game.GameOptions;
|
||||||
import mage.game.TwoPlayerDuel;
|
import mage.game.TwoPlayerDuel;
|
||||||
import mage.game.permanent.PermanentCard;
|
import mage.game.permanent.PermanentCard;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
@ -23,18 +24,6 @@ import java.util.regex.Matcher;
|
||||||
*/
|
*/
|
||||||
public class PlayGameTest extends MageTestBase {
|
public class PlayGameTest extends MageTestBase {
|
||||||
|
|
||||||
private List<Card> handCardsA = new ArrayList<Card>();
|
|
||||||
private List<Card> handCardsB = new ArrayList<Card>();
|
|
||||||
private List<PermanentCard> battlefieldCardsA = new ArrayList<PermanentCard>();
|
|
||||||
private List<PermanentCard> battlefieldCardsB = new ArrayList<PermanentCard>();
|
|
||||||
private List<Card> graveyardCardsA = new ArrayList<Card>();
|
|
||||||
private List<Card> graveyardCardsB = new ArrayList<Card>();
|
|
||||||
private List<Card> libraryCardsA = new ArrayList<Card>();
|
|
||||||
private List<Card> libraryCardsB = new ArrayList<Card>();
|
|
||||||
|
|
||||||
private Map<Constants.Zone, String> commandsA = new HashMap<Constants.Zone, String>();
|
|
||||||
private Map<Constants.Zone, String> commandsB = new HashMap<Constants.Zone, String>();
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void playOneGame() throws GameException, FileNotFoundException, IllegalArgumentException {
|
public void playOneGame() throws GameException, FileNotFoundException, IllegalArgumentException {
|
||||||
Game game = new TwoPlayerDuel(Constants.MultiplayerAttackOption.LEFT, Constants.RangeOfInfluence.ALL);
|
Game game = new TwoPlayerDuel(Constants.MultiplayerAttackOption.LEFT, Constants.RangeOfInfluence.ALL);
|
||||||
|
@ -68,7 +57,9 @@ public class PlayGameTest extends MageTestBase {
|
||||||
boolean testMode = true;
|
boolean testMode = true;
|
||||||
|
|
||||||
long t1 = System.nanoTime();
|
long t1 = System.nanoTime();
|
||||||
game.start(computerA.getId(), testMode);
|
GameOptions options = new GameOptions();
|
||||||
|
options.testMode = true;
|
||||||
|
game.start(computerA.getId(), options);
|
||||||
long t2 = System.nanoTime();
|
long t2 = System.nanoTime();
|
||||||
|
|
||||||
logger.info("Winner: " + game.getWinner());
|
logger.info("Winner: " + game.getWinner());
|
||||||
|
@ -77,100 +68,4 @@ public class PlayGameTest extends MageTestBase {
|
||||||
throw new RuntimeException("Lost :(");
|
throw new RuntimeException("Lost :(");
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCard(List<Card> cards, String name, int count) {
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
Card card = Sets.findCard(name, true);
|
|
||||||
if (card == null) {
|
|
||||||
throw new IllegalArgumentException("Couldn't find a card for test: " + name);
|
|
||||||
}
|
|
||||||
cards.add(card);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseScenario(String filename) throws FileNotFoundException {
|
|
||||||
File f = new File(filename);
|
|
||||||
Scanner scanner = new Scanner(f);
|
|
||||||
try {
|
|
||||||
while (scanner.hasNextLine()) {
|
|
||||||
String line = scanner.nextLine().trim();
|
|
||||||
if (line == null || line.isEmpty() || line.startsWith("#")) continue;
|
|
||||||
Matcher m = pattern.matcher(line);
|
|
||||||
if (m.matches()) {
|
|
||||||
|
|
||||||
String zone = m.group(1);
|
|
||||||
String nickname = m.group(2);
|
|
||||||
|
|
||||||
if (nickname.equals("ComputerA") || nickname.equals("ComputerB")) {
|
|
||||||
List<Card> cards = null;
|
|
||||||
List<PermanentCard> perms = null;
|
|
||||||
Constants.Zone gameZone;
|
|
||||||
if ("hand".equalsIgnoreCase(zone)) {
|
|
||||||
gameZone = Constants.Zone.HAND;
|
|
||||||
cards = nickname.equals("ComputerA") ? handCardsA : handCardsB;
|
|
||||||
} else if ("battlefield".equalsIgnoreCase(zone)) {
|
|
||||||
gameZone = Constants.Zone.BATTLEFIELD;
|
|
||||||
perms = nickname.equals("ComputerA") ? battlefieldCardsA : battlefieldCardsB;
|
|
||||||
} else if ("graveyard".equalsIgnoreCase(zone)) {
|
|
||||||
gameZone = Constants.Zone.GRAVEYARD;
|
|
||||||
cards = nickname.equals("ComputerA") ? graveyardCardsA : graveyardCardsB;
|
|
||||||
} else if ("library".equalsIgnoreCase(zone)) {
|
|
||||||
gameZone = Constants.Zone.LIBRARY;
|
|
||||||
cards = nickname.equals("ComputerA") ? libraryCardsA : libraryCardsB;
|
|
||||||
} else if ("player".equalsIgnoreCase(zone)) {
|
|
||||||
String command = m.group(3);
|
|
||||||
if ("life".equals(command)) {
|
|
||||||
if (nickname.equals("ComputerA")) {
|
|
||||||
commandsA.put(Constants.Zone.OUTSIDE, "life:" + m.group(4));
|
|
||||||
} else {
|
|
||||||
commandsB.put(Constants.Zone.OUTSIDE, "life:" + m.group(4));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
continue; // go parse next line
|
|
||||||
}
|
|
||||||
|
|
||||||
String cardName = m.group(3);
|
|
||||||
Integer amount = Integer.parseInt(m.group(4));
|
|
||||||
boolean tapped = m.group(5) != null && m.group(5).equals(":{tapped}");
|
|
||||||
|
|
||||||
if (cardName.equals("clear")) {
|
|
||||||
if (nickname.equals("ComputerA")) {
|
|
||||||
commandsA.put(gameZone, "clear");
|
|
||||||
} else {
|
|
||||||
commandsB.put(gameZone, "clear");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < amount; i++) {
|
|
||||||
Card card = Sets.findCard(cardName, true);
|
|
||||||
if (card != null) {
|
|
||||||
if (gameZone.equals(Constants.Zone.BATTLEFIELD)) {
|
|
||||||
PermanentCard p = new PermanentCard(card, null);
|
|
||||||
p.setTapped(tapped);
|
|
||||||
perms.add(p);
|
|
||||||
} else {
|
|
||||||
cards.add(card);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.fatal("Couldn't find a card: " + cardName);
|
|
||||||
logger.fatal("line: " + line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.warn("Unknown player: " + nickname);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.warn("Init string wasn't parsed: " + line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
scanner.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Player createPlayer(String name, String playerType) {
|
|
||||||
return PlayerFactory.getInstance().createPlayer(playerType, name, Constants.RangeOfInfluence.ALL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
package org.mage.test.serverside.base;
|
||||||
|
|
||||||
|
import mage.Constants;
|
||||||
|
import mage.filter.Filter;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for all test initialization and assertion operations.
|
||||||
|
*/
|
||||||
|
public interface CardTestAPI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of game result.
|
||||||
|
*/
|
||||||
|
public enum GameResult {
|
||||||
|
WON,
|
||||||
|
LOST,
|
||||||
|
DRAW
|
||||||
|
}
|
||||||
|
|
||||||
|
//******* INITIALIZATION METHODS *******/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default game initialization params for red player (that plays with Mountains)
|
||||||
|
*/
|
||||||
|
void useRedDefault();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all cards from player's library from the game.
|
||||||
|
* Usually this should be used once before initialization to form the library in certain order.
|
||||||
|
*
|
||||||
|
* @param player {@link Player} to remove all library cards from.
|
||||||
|
*/
|
||||||
|
void removeAllCardsFromLibrary(Player player);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a card to specified zone of specified player.
|
||||||
|
*
|
||||||
|
* @param gameZone {@link Constants.Zone} to add cards to.
|
||||||
|
* @param player {@link Player} to add cards for. Use either computerA or computerB.
|
||||||
|
* @param cardName Card name in string format.
|
||||||
|
*/
|
||||||
|
void addCard(Constants.Zone gameZone, Player player, String cardName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add any amount of cards to specified zone of specified player.
|
||||||
|
*
|
||||||
|
* @param gameZone {@link Constants.Zone} to add cards to.
|
||||||
|
* @param player {@link Player} to add cards for. Use either computerA or computerB.
|
||||||
|
* @param cardName Card name in string format.
|
||||||
|
* @param count Amount of cards to be added.
|
||||||
|
*/
|
||||||
|
void addCard(Constants.Zone gameZone, Player player, String cardName, int count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add any amount of cards to specified zone of specified player.
|
||||||
|
*
|
||||||
|
* @param gameZone {@link Constants.Zone} to add cards to.
|
||||||
|
* @param player {@link Player} to add cards for. Use either computerA or computerB.
|
||||||
|
* @param cardName Card name in string format.
|
||||||
|
* @param count Amount of cards to be added.
|
||||||
|
* @param tapped In case gameZone is Battlefield, determines whether permanent should be tapped.
|
||||||
|
* In case gameZone is other than Battlefield, {@link IllegalArgumentException} is thrown
|
||||||
|
*/
|
||||||
|
void addCard(Constants.Zone gameZone, Player player, String cardName, int count, boolean tapped);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set player's initial life count.
|
||||||
|
*
|
||||||
|
* @param player {@link Player} to set life count for.
|
||||||
|
* @param life Life count to set.
|
||||||
|
*/
|
||||||
|
void setLife(Player player, int life);
|
||||||
|
|
||||||
|
//******* GAME OPTIONS *******/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define turn number to stop the game on.
|
||||||
|
*/
|
||||||
|
void setStopOnTurn(int turn);
|
||||||
|
|
||||||
|
//******* ASSERT METHODS *******/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert turn number after test execution.
|
||||||
|
*
|
||||||
|
* @param turn Expected turn number to compare with.
|
||||||
|
*/
|
||||||
|
void assertTurn(int turn) throws AssertionError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert game result for the player after test execution.
|
||||||
|
*
|
||||||
|
* @param player {@link Player} to get game result for.
|
||||||
|
* @param result Expected {@link GameResult} to compare with.
|
||||||
|
*/
|
||||||
|
void assertResult(Player player, GameResult result) throws AssertionError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert player's life count after test execution.
|
||||||
|
*
|
||||||
|
* @param player {@link Player} to get life for comparison.
|
||||||
|
* @param life Expected player's life to compare with.
|
||||||
|
*/
|
||||||
|
void assertLife(Player player, int life) throws AssertionError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert creature's power and toughness by card name.
|
||||||
|
* <p/>
|
||||||
|
* Throws {@link AssertionError} in the following cases:
|
||||||
|
* 1. no such player
|
||||||
|
* 2. no such creature under player's control
|
||||||
|
* 3. depending on comparison scope:
|
||||||
|
* 3a. any: no creature under player's control with the specified p\t params
|
||||||
|
* 3b. all: there is at least one creature with the cardName with the different p\t params
|
||||||
|
*
|
||||||
|
* @param player {@link Player} to get creatures for comparison.
|
||||||
|
* @param cardName Card name to compare with.
|
||||||
|
* @param power Expected power to compare with.
|
||||||
|
* @param toughness Expected toughness to compare with.
|
||||||
|
* @param scope {@link Filter.ComparisonScope} Use ANY, if you want "at least one creature with given name should have specified p\t"
|
||||||
|
* Use ALL, if you want "all creature with gived name should have specified p\t"
|
||||||
|
*/
|
||||||
|
void assertPowerToughness(Player player, String cardName, int power, int toughness, Filter.ComparisonScope scope)
|
||||||
|
throws AssertionError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert permanent count under player's control.
|
||||||
|
*
|
||||||
|
* @param player {@link Player} which permanents should be counted.
|
||||||
|
* @param count Expected count.
|
||||||
|
*/
|
||||||
|
void assertPermanentCount(Player player, int count) throws AssertionError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert permanent count under player's control.
|
||||||
|
*
|
||||||
|
* @param player {@link Player} which permanents should be counted.
|
||||||
|
* @param cardName Name of the cards that should be counted.
|
||||||
|
* @param count Expected count.
|
||||||
|
*/
|
||||||
|
void assertPermanentCount(Player player, String cardName, int count) throws AssertionError;
|
||||||
|
}
|
|
@ -0,0 +1,335 @@
|
||||||
|
package org.mage.test.serverside.base;
|
||||||
|
|
||||||
|
import mage.Constants;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.cards.decks.Deck;
|
||||||
|
import mage.filter.Filter;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.GameException;
|
||||||
|
import mage.game.GameOptions;
|
||||||
|
import mage.game.TwoPlayerDuel;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.sets.Sets;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.mage.test.serverside.base.impl.CardTestAPIImpl;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for testing single cards and effects.
|
||||||
|
*
|
||||||
|
* @author ayratn
|
||||||
|
*/
|
||||||
|
public abstract class CardTestBase extends CardTestAPIImpl {
|
||||||
|
|
||||||
|
protected enum AIType {
|
||||||
|
MinimaxHybrid,
|
||||||
|
MAD
|
||||||
|
}
|
||||||
|
|
||||||
|
protected enum ExpectedType {
|
||||||
|
TURN_NUMBER,
|
||||||
|
RESULT,
|
||||||
|
LIFE,
|
||||||
|
BATTLEFIELD,
|
||||||
|
GRAVEYARD,
|
||||||
|
UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computer types used to test cards.
|
||||||
|
* By default: MAD.
|
||||||
|
*/
|
||||||
|
private AIType aiTypeA, aiTypeB;
|
||||||
|
|
||||||
|
public CardTestBase() {
|
||||||
|
aiTypeA = CardTestBase.AIType.MAD;
|
||||||
|
aiTypeB = CardTestBase.AIType.MAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CardTestBase(AIType aiTypeA, AIType aiTypeB) {
|
||||||
|
this.aiTypeA = aiTypeA;
|
||||||
|
this.aiTypeB = aiTypeB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void reset() throws GameException, FileNotFoundException {
|
||||||
|
if (currentGame != null) {
|
||||||
|
logger.info("Resetting previous game and creating new one!");
|
||||||
|
currentGame = null;
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
Game game = new TwoPlayerDuel(Constants.MultiplayerAttackOption.LEFT, Constants.RangeOfInfluence.ALL);
|
||||||
|
|
||||||
|
computerA = aiTypeA.equals(CardTestBase.AIType.MinimaxHybrid) ?
|
||||||
|
createPlayer("ComputerA", "Computer - minimax hybrid") :
|
||||||
|
createPlayer("ComputerA", "Computer - mad");
|
||||||
|
computerA.setTestMode(true);
|
||||||
|
Deck deck = Deck.load(Sets.loadDeck("RB Aggro.dck"));
|
||||||
|
if (deck.getCards().size() < 40) {
|
||||||
|
throw new IllegalArgumentException("Couldn't load deck, deck size=" + deck.getCards().size());
|
||||||
|
}
|
||||||
|
game.addPlayer(computerA, deck);
|
||||||
|
game.loadCards(deck.getCards(), computerA.getId());
|
||||||
|
|
||||||
|
computerB = aiTypeB.equals(CardTestBase.AIType.MinimaxHybrid) ?
|
||||||
|
createPlayer("ComputerB", "Computer - minimax hybrid") :
|
||||||
|
createPlayer("ComputerB", "Computer - mad");
|
||||||
|
computerB.setTestMode(true);
|
||||||
|
Deck deck2 = Deck.load(Sets.loadDeck("RB Aggro.dck"));
|
||||||
|
if (deck2.getCards().size() < 40) {
|
||||||
|
throw new IllegalArgumentException("Couldn't load deck, deck size=" + deck2.getCards().size());
|
||||||
|
}
|
||||||
|
game.addPlayer(computerB, deck2);
|
||||||
|
game.loadCards(deck2.getCards(), computerB.getId());
|
||||||
|
activePlayer = computerA;
|
||||||
|
currentGame = game;
|
||||||
|
|
||||||
|
stopOnTurn = null;
|
||||||
|
handCardsA.clear();
|
||||||
|
handCardsB.clear();
|
||||||
|
battlefieldCardsA.clear();
|
||||||
|
battlefieldCardsB.clear();
|
||||||
|
graveyardCardsA.clear();
|
||||||
|
graveyardCardsB.clear();
|
||||||
|
libraryCardsA.clear();
|
||||||
|
libraryCardsB.clear();
|
||||||
|
commandsA.clear();
|
||||||
|
commandsB.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(String path) throws FileNotFoundException, GameException {
|
||||||
|
load(path, AIType.MAD, AIType.MAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(String path, AIType aiTypeA, AIType aiTypeB) throws FileNotFoundException, GameException {
|
||||||
|
String cardPath = TESTS_PATH + path;
|
||||||
|
File checkFile = new File(cardPath);
|
||||||
|
if (!checkFile.exists()) {
|
||||||
|
throw new FileNotFoundException("Couldn't find test file: " + cardPath);
|
||||||
|
}
|
||||||
|
if (checkFile.isDirectory()) {
|
||||||
|
throw new FileNotFoundException("Couldn't find test file: " + cardPath + ". It is directory.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentGame != null) {
|
||||||
|
logger.info("Resetting previous game and creating new one!");
|
||||||
|
currentGame = null;
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
Game game = new TwoPlayerDuel(Constants.MultiplayerAttackOption.LEFT, Constants.RangeOfInfluence.ALL);
|
||||||
|
|
||||||
|
computerA = aiTypeA.equals(CardTestBase.AIType.MinimaxHybrid) ?
|
||||||
|
createPlayer("ComputerA", "Computer - minimax hybrid") :
|
||||||
|
createPlayer("ComputerA", "Computer - mad");
|
||||||
|
computerA.setTestMode(true);
|
||||||
|
|
||||||
|
Deck deck = Deck.load(Sets.loadDeck("RB Aggro.dck"));
|
||||||
|
|
||||||
|
if (deck.getCards().size() < 40) {
|
||||||
|
throw new IllegalArgumentException("Couldn't load deck, deck size=" + deck.getCards().size());
|
||||||
|
}
|
||||||
|
game.addPlayer(computerA, deck);
|
||||||
|
game.loadCards(deck.getCards(), computerA.getId());
|
||||||
|
|
||||||
|
computerB = aiTypeB.equals(CardTestBase.AIType.MinimaxHybrid) ?
|
||||||
|
createPlayer("ComputerB", "Computer - minimax hybrid") :
|
||||||
|
createPlayer("ComputerB", "Computer - mad");
|
||||||
|
computerB.setTestMode(true);
|
||||||
|
Deck deck2 = Deck.load(Sets.loadDeck("RB Aggro.dck"));
|
||||||
|
if (deck2.getCards().size() < 40) {
|
||||||
|
throw new IllegalArgumentException("Couldn't load deck, deck size=" + deck2.getCards().size());
|
||||||
|
}
|
||||||
|
game.addPlayer(computerB, deck2);
|
||||||
|
game.loadCards(deck2.getCards(), computerB.getId());
|
||||||
|
|
||||||
|
parseScenario(cardPath);
|
||||||
|
|
||||||
|
activePlayer = computerA;
|
||||||
|
currentGame = game;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts testing card by starting current game.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException In case game wasn't created previously. Use {@link #load} method to initialize the game.
|
||||||
|
*/
|
||||||
|
public void execute() throws IllegalStateException {
|
||||||
|
if (currentGame == null || activePlayer == null) {
|
||||||
|
throw new IllegalStateException("Game is not initialized. Use load method to load a test case and initialize a game.");
|
||||||
|
}
|
||||||
|
|
||||||
|
currentGame.cheat(computerA.getId(), commandsA);
|
||||||
|
currentGame.cheat(computerA.getId(), libraryCardsA, handCardsA, battlefieldCardsA, graveyardCardsA);
|
||||||
|
currentGame.cheat(computerB.getId(), commandsB);
|
||||||
|
currentGame.cheat(computerB.getId(), libraryCardsB, handCardsB, battlefieldCardsB, graveyardCardsB);
|
||||||
|
|
||||||
|
boolean testMode = true;
|
||||||
|
long t1 = System.nanoTime();
|
||||||
|
GameOptions gameOptions = new GameOptions();
|
||||||
|
gameOptions.testMode = true;
|
||||||
|
gameOptions.stopOnTurn = stopOnTurn;
|
||||||
|
currentGame.start(activePlayer.getId(), gameOptions);
|
||||||
|
long t2 = System.nanoTime();
|
||||||
|
logger.info("Winner: " + currentGame.getWinner());
|
||||||
|
logger.info("Time: " + (t2 - t1) / 1000000 + " ms");
|
||||||
|
|
||||||
|
assertTheResults();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert expected and actual results.
|
||||||
|
*/
|
||||||
|
private void assertTheResults() {
|
||||||
|
logger.info("Matching expected results:");
|
||||||
|
for (String line : expectedResults) {
|
||||||
|
boolean ok = false;
|
||||||
|
try {
|
||||||
|
ExpectedType type = getExpectedType(line);
|
||||||
|
if (type.equals(CardTestBase.ExpectedType.UNKNOWN)) {
|
||||||
|
throw new AssertionError("Unknown expected type, check the line in $expected section=" + line);
|
||||||
|
}
|
||||||
|
parseType(type, line);
|
||||||
|
ok = true;
|
||||||
|
} finally {
|
||||||
|
logger.info(" " + line + " - " + (ok ? "OK" : "ERROR"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ExpectedType getExpectedType(String line) {
|
||||||
|
if (line.startsWith("turn:")) {
|
||||||
|
return CardTestBase.ExpectedType.TURN_NUMBER;
|
||||||
|
}
|
||||||
|
if (line.startsWith("result:")) {
|
||||||
|
return CardTestBase.ExpectedType.RESULT;
|
||||||
|
}
|
||||||
|
if (line.startsWith("life:")) {
|
||||||
|
return CardTestBase.ExpectedType.LIFE;
|
||||||
|
}
|
||||||
|
if (line.startsWith("battlefield:")) {
|
||||||
|
return CardTestBase.ExpectedType.BATTLEFIELD;
|
||||||
|
}
|
||||||
|
if (line.startsWith("graveyard:")) {
|
||||||
|
return CardTestBase.ExpectedType.GRAVEYARD;
|
||||||
|
}
|
||||||
|
return CardTestBase.ExpectedType.UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseType(ExpectedType type, String line) {
|
||||||
|
if (type.equals(CardTestBase.ExpectedType.TURN_NUMBER)) {
|
||||||
|
int turn = getIntParam(line, 1);
|
||||||
|
Assert.assertEquals("Turn numbers are not equal", turn, currentGame.getTurnNum());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type.equals(CardTestBase.ExpectedType.RESULT)) {
|
||||||
|
String expected = getStringParam(line, 1);
|
||||||
|
String actual = "draw";
|
||||||
|
if (currentGame.getWinner().equals("Player ComputerA is the winner")) {
|
||||||
|
actual = "won";
|
||||||
|
} else if (currentGame.getWinner().equals("Player ComputerB is the winner")) {
|
||||||
|
actual = "lost";
|
||||||
|
}
|
||||||
|
Assert.assertEquals("Game results are not equal", expected, actual);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type.equals(CardTestBase.ExpectedType.LIFE)) {
|
||||||
|
String player = getStringParam(line, 1);
|
||||||
|
int expected = getIntParam(line, 2);
|
||||||
|
if (player.equals("ComputerA")) {
|
||||||
|
int actual = currentGame.getPlayer(computerA.getId()).getLife();
|
||||||
|
Assert.assertEquals("Life amounts are not equal", expected, actual);
|
||||||
|
} else if (player.equals("ComputerB")) {
|
||||||
|
int actual = currentGame.getPlayer(computerB.getId()).getLife();
|
||||||
|
Assert.assertEquals("Life amounts are not equal", expected, actual);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Wrong player in 'life' line, player=" + player + ", line=" + line);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type.equals(CardTestBase.ExpectedType.BATTLEFIELD)) {
|
||||||
|
String playerName = getStringParam(line, 1);
|
||||||
|
String cardName = getStringParam(line, 2);
|
||||||
|
int expectedCount = getIntParam(line, 3);
|
||||||
|
Player player = null;
|
||||||
|
if (playerName.equals("ComputerA")) {
|
||||||
|
player = currentGame.getPlayer(computerA.getId());
|
||||||
|
} else if (playerName.equals("ComputerB")) {
|
||||||
|
player = currentGame.getPlayer(computerB.getId());
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Wrong player in 'battlefield' line, player=" + player + ", line=" + line);
|
||||||
|
}
|
||||||
|
int actualCount = 0;
|
||||||
|
for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) {
|
||||||
|
if (permanent.getControllerId().equals(player.getId())) {
|
||||||
|
if (permanent.getName().equals(cardName)) {
|
||||||
|
actualCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.assertEquals("(Battlefield) Card counts are not equal (" + cardName + ")", expectedCount, actualCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type.equals(CardTestBase.ExpectedType.GRAVEYARD)) {
|
||||||
|
String playerName = getStringParam(line, 1);
|
||||||
|
String cardName = getStringParam(line, 2);
|
||||||
|
int expectedCount = getIntParam(line, 3);
|
||||||
|
Player player = null;
|
||||||
|
if (playerName.equals("ComputerA")) {
|
||||||
|
player = currentGame.getPlayer(computerA.getId());
|
||||||
|
} else if (playerName.equals("ComputerB")) {
|
||||||
|
player = currentGame.getPlayer(computerB.getId());
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Wrong player in 'graveyard' line, player=" + player + ", line=" + line);
|
||||||
|
}
|
||||||
|
int actualCount = 0;
|
||||||
|
for (Card card : player.getGraveyard().getCards(currentGame)) {
|
||||||
|
if (card.getName().equals(cardName)) {
|
||||||
|
actualCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.assertEquals("(Graveyard) Card counts are not equal (" + cardName + ")", expectedCount, actualCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIntParam(String line, int index) {
|
||||||
|
String[] params = line.split(":");
|
||||||
|
if (index > params.length - 1) {
|
||||||
|
throw new IllegalArgumentException("Not correct line: " + line);
|
||||||
|
}
|
||||||
|
return Integer.parseInt(params[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getStringParam(String line, int index) {
|
||||||
|
String[] params = line.split(":");
|
||||||
|
if (index > params.length - 1) {
|
||||||
|
throw new IllegalArgumentException("Not correct line: " + line);
|
||||||
|
}
|
||||||
|
return params[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkPermanentPT(Player player, String cardName, int power, int toughness, Filter.ComparisonScope scope) {
|
||||||
|
if (currentGame == null) {
|
||||||
|
throw new IllegalStateException("Current game is null");
|
||||||
|
}
|
||||||
|
if (scope.equals(Filter.ComparisonScope.All)) {
|
||||||
|
throw new UnsupportedOperationException("ComparisonScope.All is not implemented.");
|
||||||
|
}
|
||||||
|
int count = 0;
|
||||||
|
int fit = 0;
|
||||||
|
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents(player.getId())) {
|
||||||
|
if (permanent.getName().equals(cardName)) {
|
||||||
|
Assert.assertEquals("Power is not the same", power, permanent.getPower().getValue());
|
||||||
|
Assert.assertEquals("Toughness is not the same", toughness, permanent.getToughness().getValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,12 @@
|
||||||
package org.mage.test.serverside.base;
|
package org.mage.test.serverside.base;
|
||||||
|
|
||||||
|
import mage.Constants;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.game.Game;
|
||||||
import mage.game.match.MatchType;
|
import mage.game.match.MatchType;
|
||||||
|
import mage.game.permanent.PermanentCard;
|
||||||
import mage.game.tournament.TournamentType;
|
import mage.game.tournament.TournamentType;
|
||||||
|
import mage.players.Player;
|
||||||
import mage.server.game.DeckValidatorFactory;
|
import mage.server.game.DeckValidatorFactory;
|
||||||
import mage.server.game.GameFactory;
|
import mage.server.game.GameFactory;
|
||||||
import mage.server.game.PlayerFactory;
|
import mage.server.game.PlayerFactory;
|
||||||
|
@ -10,19 +15,25 @@ import mage.server.util.ConfigSettings;
|
||||||
import mage.server.util.PluginClassLoader;
|
import mage.server.util.PluginClassLoader;
|
||||||
import mage.server.util.config.GamePlugin;
|
import mage.server.util.config.GamePlugin;
|
||||||
import mage.server.util.config.Plugin;
|
import mage.server.util.config.Plugin;
|
||||||
|
import mage.sets.Sets;
|
||||||
import mage.util.Copier;
|
import mage.util.Copier;
|
||||||
|
import org.apache.log4j.Level;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import org.apache.log4j.Level;
|
import java.util.*;
|
||||||
import org.apache.log4j.Logger;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Base class for all tests.
|
||||||
|
*
|
||||||
* @author ayratn
|
* @author ayratn
|
||||||
*/
|
*/
|
||||||
public class MageTestBase {
|
public abstract class MageTestBase {
|
||||||
protected static Logger logger = Logger.getLogger(MageTestBase.class);
|
protected static Logger logger = Logger.getLogger(MageTestBase.class);
|
||||||
|
|
||||||
public static PluginClassLoader classLoader = new PluginClassLoader();
|
public static PluginClassLoader classLoader = new PluginClassLoader();
|
||||||
|
@ -31,6 +42,58 @@ public class MageTestBase {
|
||||||
|
|
||||||
protected Pattern pattern = Pattern.compile("([a-zA-Z]*):([\\w]*):([a-zA-Z ,\\-.!'\\d]*):([\\d]*)(:\\{tapped\\})?");
|
protected Pattern pattern = Pattern.compile("([a-zA-Z]*):([\\w]*):([a-zA-Z ,\\-.!'\\d]*):([\\d]*)(:\\{tapped\\})?");
|
||||||
|
|
||||||
|
protected List<Card> handCardsA = new ArrayList<Card>();
|
||||||
|
protected List<Card> handCardsB = new ArrayList<Card>();
|
||||||
|
protected List<PermanentCard> battlefieldCardsA = new ArrayList<PermanentCard>();
|
||||||
|
protected List<PermanentCard> battlefieldCardsB = new ArrayList<PermanentCard>();
|
||||||
|
protected List<Card> graveyardCardsA = new ArrayList<Card>();
|
||||||
|
protected List<Card> graveyardCardsB = new ArrayList<Card>();
|
||||||
|
protected List<Card> libraryCardsA = new ArrayList<Card>();
|
||||||
|
protected List<Card> libraryCardsB = new ArrayList<Card>();
|
||||||
|
|
||||||
|
protected Map<Constants.Zone, String> commandsA = new HashMap<Constants.Zone, String>();
|
||||||
|
protected Map<Constants.Zone, String> commandsB = new HashMap<Constants.Zone, String>();
|
||||||
|
|
||||||
|
protected Player computerA;
|
||||||
|
protected Player computerB;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Game instance initialized in load method.
|
||||||
|
*/
|
||||||
|
protected static Game currentGame = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player thats starts the game first.
|
||||||
|
* By default, it is ComputerA.
|
||||||
|
*/
|
||||||
|
protected static Player activePlayer = null;
|
||||||
|
|
||||||
|
protected Integer stopOnTurn;
|
||||||
|
|
||||||
|
protected enum ParserState {
|
||||||
|
INIT,
|
||||||
|
OPTIONS,
|
||||||
|
EXPECTED
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ParserState parserState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected results of the test.
|
||||||
|
* Read from test case in {@link String} based format:
|
||||||
|
* <p/>
|
||||||
|
* Example:
|
||||||
|
* turn:1
|
||||||
|
* result:won:ComputerA
|
||||||
|
* life:ComputerA:20
|
||||||
|
* life:ComputerB:0
|
||||||
|
* battlefield:ComputerB:Tine Shrike:0
|
||||||
|
* graveyard:ComputerB:Tine Shrike:1
|
||||||
|
*/
|
||||||
|
protected List<String> expectedResults = new ArrayList<String>();
|
||||||
|
|
||||||
|
protected static final String TESTS_PATH = "tests" + File.separator;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void init() {
|
public static void init() {
|
||||||
Logger.getRootLogger().setLevel(Level.DEBUG);
|
Logger.getRootLogger().setLevel(Level.DEBUG);
|
||||||
|
@ -108,4 +171,128 @@ public class MageTestBase {
|
||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void parseScenario(String filename) throws FileNotFoundException {
|
||||||
|
parserState = ParserState.INIT;
|
||||||
|
File f = new File(filename);
|
||||||
|
Scanner scanner = new Scanner(f);
|
||||||
|
try {
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
String line = scanner.nextLine().trim();
|
||||||
|
if (line == null || line.isEmpty() || line.startsWith("#")) continue;
|
||||||
|
if (line.startsWith("$include")) {
|
||||||
|
includeFrom(line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (line.startsWith("$expected")) {
|
||||||
|
parserState = ParserState.EXPECTED;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parseLine(line);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
scanner.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseLine(String line) {
|
||||||
|
if (parserState.equals(ParserState.EXPECTED)) {
|
||||||
|
expectedResults.add(line); // just remember for future use
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher m = pattern.matcher(line);
|
||||||
|
if (m.matches()) {
|
||||||
|
|
||||||
|
String zone = m.group(1);
|
||||||
|
String nickname = m.group(2);
|
||||||
|
|
||||||
|
if (nickname.equals("ComputerA") || nickname.equals("ComputerB")) {
|
||||||
|
List<Card> cards = null;
|
||||||
|
List<PermanentCard> perms = null;
|
||||||
|
Constants.Zone gameZone;
|
||||||
|
if ("hand".equalsIgnoreCase(zone)) {
|
||||||
|
gameZone = Constants.Zone.HAND;
|
||||||
|
cards = nickname.equals("ComputerA") ? handCardsA : handCardsB;
|
||||||
|
} else if ("battlefield".equalsIgnoreCase(zone)) {
|
||||||
|
gameZone = Constants.Zone.BATTLEFIELD;
|
||||||
|
perms = nickname.equals("ComputerA") ? battlefieldCardsA : battlefieldCardsB;
|
||||||
|
} else if ("graveyard".equalsIgnoreCase(zone)) {
|
||||||
|
gameZone = Constants.Zone.GRAVEYARD;
|
||||||
|
cards = nickname.equals("ComputerA") ? graveyardCardsA : graveyardCardsB;
|
||||||
|
} else if ("library".equalsIgnoreCase(zone)) {
|
||||||
|
gameZone = Constants.Zone.LIBRARY;
|
||||||
|
cards = nickname.equals("ComputerA") ? libraryCardsA : libraryCardsB;
|
||||||
|
} else if ("player".equalsIgnoreCase(zone)) {
|
||||||
|
String command = m.group(3);
|
||||||
|
if ("life".equals(command)) {
|
||||||
|
if (nickname.equals("ComputerA")) {
|
||||||
|
commandsA.put(Constants.Zone.OUTSIDE, "life:" + m.group(4));
|
||||||
|
} else {
|
||||||
|
commandsB.put(Constants.Zone.OUTSIDE, "life:" + m.group(4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
return; // go parse next line
|
||||||
|
}
|
||||||
|
|
||||||
|
String cardName = m.group(3);
|
||||||
|
Integer amount = Integer.parseInt(m.group(4));
|
||||||
|
boolean tapped = m.group(5) != null && m.group(5).equals(":{tapped}");
|
||||||
|
|
||||||
|
if (cardName.equals("clear")) {
|
||||||
|
if (nickname.equals("ComputerA")) {
|
||||||
|
commandsA.put(gameZone, "clear");
|
||||||
|
} else {
|
||||||
|
commandsB.put(gameZone, "clear");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < amount; i++) {
|
||||||
|
Card card = Sets.findCard(cardName, true);
|
||||||
|
if (card != null) {
|
||||||
|
if (gameZone.equals(Constants.Zone.BATTLEFIELD)) {
|
||||||
|
PermanentCard p = new PermanentCard(card, null);
|
||||||
|
p.setTapped(tapped);
|
||||||
|
perms.add(p);
|
||||||
|
} else {
|
||||||
|
cards.add(card);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.fatal("Couldn't find a card: " + cardName);
|
||||||
|
logger.fatal("line: " + line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warn("Unknown player: " + nickname);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warn("Init string wasn't parsed: " + line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void includeFrom(String line) throws FileNotFoundException {
|
||||||
|
String[] params = line.split(" ");
|
||||||
|
if (params.length == 2) {
|
||||||
|
String paramName = params[1];
|
||||||
|
if (!paramName.contains("..")) {
|
||||||
|
String includePath = TESTS_PATH + paramName;
|
||||||
|
File f = new File(includePath);
|
||||||
|
if (f.exists()) {
|
||||||
|
parseScenario(includePath);
|
||||||
|
} else {
|
||||||
|
logger.warn("Ignored (file doesn't exist): " + line);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warn("Ignored (wrong charactres): " + line);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warn("Ignored (wrong size): " + line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Player createPlayer(String name, String playerType) {
|
||||||
|
return PlayerFactory.getInstance().createPlayer(playerType, name, Constants.RangeOfInfluence.ALL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,296 @@
|
||||||
|
package org.mage.test.serverside.base.impl;
|
||||||
|
|
||||||
|
import mage.Constants;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.filter.Filter;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.game.permanent.PermanentCard;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.sets.Sets;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.mage.test.serverside.base.CardTestAPI;
|
||||||
|
import org.mage.test.serverside.base.MageTestBase;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API for test initialization and asserting the test results.
|
||||||
|
*
|
||||||
|
* @author ayratn
|
||||||
|
*/
|
||||||
|
public abstract class CardTestAPIImpl extends MageTestBase implements CardTestAPI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default game initialization params for red player (that plays with Mountains)
|
||||||
|
*/
|
||||||
|
public void useRedDefault() {
|
||||||
|
// *** ComputerA ***
|
||||||
|
// battlefield:ComputerA:Mountain:5
|
||||||
|
addCard(Constants.Zone.BATTLEFIELD, computerA, "Mountain", 5);
|
||||||
|
// hand:ComputerA:Mountain:4
|
||||||
|
addCard(Constants.Zone.HAND, computerA, "Mountain", 5);
|
||||||
|
// library:ComputerA:clear:0
|
||||||
|
removeAllCardsFromLibrary(computerA);
|
||||||
|
// library:ComputerA:Mountain:10
|
||||||
|
addCard(Constants.Zone.LIBRARY, computerA, "Mountain", 10);
|
||||||
|
|
||||||
|
// *** ComputerB ***
|
||||||
|
// battlefield:ComputerB:Plains:2
|
||||||
|
addCard(Constants.Zone.BATTLEFIELD, computerB, "Plains", 2);
|
||||||
|
// hand:ComputerB:Plains:2
|
||||||
|
addCard(Constants.Zone.HAND, computerB, "Plains", 2);
|
||||||
|
// library:ComputerB:clear:0
|
||||||
|
removeAllCardsFromLibrary(computerB);
|
||||||
|
// library:ComputerB:Plains:10
|
||||||
|
addCard(Constants.Zone.LIBRARY, computerB, "Plains", 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all cards from player's library from the game.
|
||||||
|
* Usually this should be used once before initialization to form the library in certain order.
|
||||||
|
*
|
||||||
|
* @param player {@link Player} to remove all library cards from.
|
||||||
|
*/
|
||||||
|
public void removeAllCardsFromLibrary(Player player) {
|
||||||
|
if (player.equals(computerA)) {
|
||||||
|
commandsA.put(Constants.Zone.LIBRARY, "clear");
|
||||||
|
} else if (player.equals(computerB)) {
|
||||||
|
commandsB.put(Constants.Zone.LIBRARY, "clear");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a card to specified zone of specified player.
|
||||||
|
*
|
||||||
|
* @param gameZone {@link Constants.Zone} to add cards to.
|
||||||
|
* @param player {@link Player} to add cards for. Use either computerA or computerB.
|
||||||
|
* @param cardName Card name in string format.
|
||||||
|
*/
|
||||||
|
public void addCard(Constants.Zone gameZone, Player player, String cardName) {
|
||||||
|
addCard(gameZone, player, cardName, 1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add any amount of cards to specified zone of specified player.
|
||||||
|
*
|
||||||
|
* @param gameZone {@link Constants.Zone} to add cards to.
|
||||||
|
* @param player {@link Player} to add cards for. Use either computerA or computerB.
|
||||||
|
* @param cardName Card name in string format.
|
||||||
|
* @param count Amount of cards to be added.
|
||||||
|
*/
|
||||||
|
public void addCard(Constants.Zone gameZone, Player player, String cardName, int count) {
|
||||||
|
addCard(gameZone, player, cardName, count, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add any amount of cards to specified zone of specified player.
|
||||||
|
*
|
||||||
|
* @param gameZone {@link Constants.Zone} to add cards to.
|
||||||
|
* @param player {@link Player} to add cards for. Use either computerA or computerB.
|
||||||
|
* @param cardName Card name in string format.
|
||||||
|
* @param count Amount of cards to be added.
|
||||||
|
* @param tapped In case gameZone is Battlefield, determines whether permanent should be tapped.
|
||||||
|
* In case gameZone is other than Battlefield, {@link IllegalArgumentException} is thrown
|
||||||
|
*/
|
||||||
|
public void addCard(Constants.Zone gameZone, Player player, String cardName, int count, boolean tapped) {
|
||||||
|
|
||||||
|
|
||||||
|
if (gameZone.equals(Constants.Zone.BATTLEFIELD)) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
Card card = Sets.findCard(cardName, true);
|
||||||
|
PermanentCard p = new PermanentCard(card, null);
|
||||||
|
p.setTapped(tapped);
|
||||||
|
if (player.equals(computerA)) {
|
||||||
|
battlefieldCardsA.add(p);
|
||||||
|
} else if (player.equals(computerB)) {
|
||||||
|
battlefieldCardsB.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (tapped) {
|
||||||
|
throw new IllegalArgumentException("Parameter tapped=true can be used only for Zone.BATTLEFIELD.");
|
||||||
|
}
|
||||||
|
List<Card> cards = getCardList(gameZone, player);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
Card card = Sets.findCard(cardName, true);
|
||||||
|
cards.add(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns card list containter for specified game zone and player.
|
||||||
|
*
|
||||||
|
* @param gameZone
|
||||||
|
* @param player
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<Card> getCardList(Constants.Zone gameZone, Player player) {
|
||||||
|
if (player.equals(computerA)) {
|
||||||
|
if (gameZone.equals(Constants.Zone.HAND)) {
|
||||||
|
return handCardsA;
|
||||||
|
} else if (gameZone.equals(Constants.Zone.GRAVEYARD)) {
|
||||||
|
return graveyardCardsA;
|
||||||
|
} else if (gameZone.equals(Constants.Zone.LIBRARY)) {
|
||||||
|
return libraryCardsA;
|
||||||
|
}
|
||||||
|
} else if (player.equals(computerB)) {
|
||||||
|
if (gameZone.equals(Constants.Zone.HAND)) {
|
||||||
|
return handCardsB;
|
||||||
|
} else if (gameZone.equals(Constants.Zone.GRAVEYARD)) {
|
||||||
|
return graveyardCardsB;
|
||||||
|
} else if (gameZone.equals(Constants.Zone.LIBRARY)) {
|
||||||
|
return libraryCardsB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set player's initial life count.
|
||||||
|
*
|
||||||
|
* @param player {@link Player} to set life count for.
|
||||||
|
* @param life Life count to set.
|
||||||
|
*/
|
||||||
|
public void setLife(Player player, int life) {
|
||||||
|
if (player.equals(computerA)) {
|
||||||
|
commandsA.put(Constants.Zone.OUTSIDE, "life:" + String.valueOf(life));
|
||||||
|
} else if (player.equals(computerB)) {
|
||||||
|
commandsB.put(Constants.Zone.OUTSIDE, "life:" + String.valueOf(life));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define turn number to stop the game on.
|
||||||
|
*/
|
||||||
|
public void setStopOnTurn(int turn) {
|
||||||
|
stopOnTurn = turn == -1 ? null : Integer.valueOf(turn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert turn number after test execution.
|
||||||
|
*
|
||||||
|
* @param turn Expected turn number to compare with. 1-based.
|
||||||
|
*/
|
||||||
|
public void assertTurn(int turn) throws AssertionError {
|
||||||
|
Assert.assertEquals("Turn numbers are not equal", turn, currentGame.getTurnNum());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert game result after test execution.
|
||||||
|
*
|
||||||
|
* @param result Expected {@link GameResult} to compare with.
|
||||||
|
*/
|
||||||
|
public void assertResult(Player player, GameResult result) throws AssertionError {
|
||||||
|
if (player.equals(computerA)) {
|
||||||
|
GameResult actual = CardTestAPI.GameResult.DRAW;
|
||||||
|
if (currentGame.getWinner().equals("Player ComputerA is the winner")) {
|
||||||
|
actual = CardTestAPI.GameResult.WON;
|
||||||
|
} else if (currentGame.getWinner().equals("Player ComputerB is the winner")) {
|
||||||
|
actual = CardTestAPI.GameResult.LOST;
|
||||||
|
}
|
||||||
|
Assert.assertEquals("Game results are not equal", result, actual);
|
||||||
|
} else if (player.equals(computerB)) {
|
||||||
|
GameResult actual = CardTestAPI.GameResult.DRAW;
|
||||||
|
if (currentGame.getWinner().equals("Player ComputerB is the winner")) {
|
||||||
|
actual = CardTestAPI.GameResult.WON;
|
||||||
|
} else if (currentGame.getWinner().equals("Player ComputerA is the winner")) {
|
||||||
|
actual = CardTestAPI.GameResult.LOST;
|
||||||
|
}
|
||||||
|
Assert.assertEquals("Game results are not equal", result, actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert player's life count after test execution.
|
||||||
|
*
|
||||||
|
* @param player {@link Player} to get life for comparison.
|
||||||
|
* @param life Expected player's life to compare with.
|
||||||
|
*/
|
||||||
|
public void assertLife(Player player, int life) throws AssertionError {
|
||||||
|
int actual = currentGame.getPlayer(player.getId()).getLife();
|
||||||
|
Assert.assertEquals("Life amounts are not equal", life, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert creature's power and toughness by card name.
|
||||||
|
* <p/>
|
||||||
|
* Throws {@link AssertionError} in the following cases:
|
||||||
|
* 1. no such player
|
||||||
|
* 2. no such creature under player's control
|
||||||
|
* 3. depending on comparison scope:
|
||||||
|
* 3a. any: no creature under player's control with the specified p\t params
|
||||||
|
* 3b. all: there is at least one creature with the cardName with the different p\t params
|
||||||
|
*
|
||||||
|
* @param player {@link Player} to get creatures for comparison.
|
||||||
|
* @param cardName Card name to compare with.
|
||||||
|
* @param power Expected power to compare with.
|
||||||
|
* @param toughness Expected toughness to compare with.
|
||||||
|
* @param scope {@link mage.filter.Filter.ComparisonScope} Use ANY, if you want "at least one creature with given name should have specified p\t"
|
||||||
|
* Use ALL, if you want "all creature with gived name should have specified p\t"
|
||||||
|
*/
|
||||||
|
public void assertPowerToughness(Player player, String cardName, int power, int toughness, Filter.ComparisonScope scope)
|
||||||
|
throws AssertionError {
|
||||||
|
int count = 0;
|
||||||
|
int fit = 0;
|
||||||
|
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents(player.getId())) {
|
||||||
|
if (permanent.getName().equals(cardName)) {
|
||||||
|
count++;
|
||||||
|
if (scope.equals(Filter.ComparisonScope.All)) {
|
||||||
|
Assert.assertEquals("Power is not the same (" + power + " vs. " + permanent.getPower().getValue() + ")",
|
||||||
|
power, permanent.getPower().getValue());
|
||||||
|
Assert.assertEquals("Toughness is not the same (" + toughness + " vs. " + permanent.getToughness().getValue() + ")",
|
||||||
|
toughness, permanent.getToughness().getValue());
|
||||||
|
} else if (scope.equals(Filter.ComparisonScope.Any)) {
|
||||||
|
if (power == permanent.getPower().getValue() && toughness == permanent.getToughness().getValue()) {
|
||||||
|
fit++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.assertTrue("There is no such permanent under player's control, player=" + player.getName() +
|
||||||
|
", cardName=" + cardName, count > 0);
|
||||||
|
|
||||||
|
if (scope.equals(Filter.ComparisonScope.Any)) {
|
||||||
|
Assert.assertTrue("There is no such creature under player's control with specified power&toughness, player=" + player.getName() +
|
||||||
|
", cardName=" + cardName, fit > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert permanent count under player's control.
|
||||||
|
*
|
||||||
|
* @param player {@link Player} which permanents should be counted.
|
||||||
|
* @param count Expected count.
|
||||||
|
*/
|
||||||
|
public void assertPermanentCount(Player player, int count) throws AssertionError {
|
||||||
|
int actualCount = 0;
|
||||||
|
for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) {
|
||||||
|
if (permanent.getControllerId().equals(player.getId())) {
|
||||||
|
actualCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.assertEquals("(Battlefield) Card counts are not equal ", count, actualCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert permanent count under player's control.
|
||||||
|
*
|
||||||
|
* @param player {@link Player} which permanents should be counted.
|
||||||
|
* @param cardName Name of the cards that should be counted.
|
||||||
|
* @param count Expected count.
|
||||||
|
*/
|
||||||
|
public void assertPermanentCount(Player player, String cardName, int count) throws AssertionError {
|
||||||
|
int actualCount = 0;
|
||||||
|
for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) {
|
||||||
|
if (permanent.getControllerId().equals(player.getId())) {
|
||||||
|
if (permanent.getName().equals(cardName)) {
|
||||||
|
actualCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.assertEquals("(Battlefield) Card counts are not equal (" + cardName + ")", count, actualCount);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package org.mage.test.serverside.cards.effects;
|
||||||
|
|
||||||
|
import com.sun.xml.bind.v2.schemagen.xmlschema.Any;
|
||||||
|
import mage.filter.Filter;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests continuous boost effect like "White creatures you control get +1/+1".
|
||||||
|
*
|
||||||
|
* @author ayratn
|
||||||
|
*/
|
||||||
|
public class BoostContinuousEffectTest extends CardTestBase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHonorOfThePoor() throws Exception {
|
||||||
|
load("M11/Honor of the Pure.test");
|
||||||
|
execute();
|
||||||
|
|
||||||
|
checkPermanentPT(computerA, "Tine Shrike", 3, 2, Filter.ComparisonScope.Any);
|
||||||
|
checkPermanentPT(computerA, "Runeclaw Bear", 2, 2, Filter.ComparisonScope.Any);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package org.mage.test.serverside.cards.single.mbs;
|
||||||
|
|
||||||
|
import mage.Constants;
|
||||||
|
import mage.filter.Filter;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestAPI;
|
||||||
|
import org.mage.test.serverside.base.CardTestBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First JUnit tests for Mage card.
|
||||||
|
*
|
||||||
|
* @ayratn
|
||||||
|
*/
|
||||||
|
public class BurntheImpureTest extends CardTestBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reproduces the test written in MBS/Burn the Impure.test
|
||||||
|
*
|
||||||
|
* Actually it can be tested with one java line that loads all test metadata from text file:
|
||||||
|
* load("MBS/Burn the Impure.test");
|
||||||
|
*
|
||||||
|
* But it was decided to use java code only.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testVersusInfectCreature() throws Exception {
|
||||||
|
// $include red.default
|
||||||
|
useRedDefault();
|
||||||
|
// hand:ComputerA:Burn the Impure:1
|
||||||
|
addCard(Constants.Zone.HAND, computerA, "Burn the Impure");
|
||||||
|
// battlefield:ComputerB:Tine Shrike:1
|
||||||
|
addCard(Constants.Zone.BATTLEFIELD, computerB, "Tine Shrike");
|
||||||
|
// player:ComputerB:life:3
|
||||||
|
setLife(computerB, 3);
|
||||||
|
|
||||||
|
setStopOnTurn(2);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
// turn:1
|
||||||
|
assertTurn(1);
|
||||||
|
// result:won
|
||||||
|
assertResult(computerA, CardTestAPI.GameResult.WON);
|
||||||
|
// life:ComputerA:20
|
||||||
|
assertLife(computerA, 20);
|
||||||
|
// life:ComputerB:0
|
||||||
|
assertLife(computerB, 0);
|
||||||
|
// assert Tine Shrike has been killed
|
||||||
|
assertPermanentCount(computerB, "Tine Shrike", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load("MBS/Burn the Impure - no infect.test");
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testVersusNonInfectCreature() throws Exception {
|
||||||
|
useRedDefault();
|
||||||
|
addCard(Constants.Zone.HAND, computerA, "Burn the Impure");
|
||||||
|
addCard(Constants.Zone.BATTLEFIELD, computerB, "Runeclaw Bear", 3);
|
||||||
|
setLife(computerB, 3);
|
||||||
|
|
||||||
|
setStopOnTurn(2);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertTurn(2);
|
||||||
|
assertResult(computerA, CardTestAPI.GameResult.DRAW);
|
||||||
|
assertLife(computerA, 20);
|
||||||
|
assertLife(computerB, 3);
|
||||||
|
assertPermanentCount(computerB, "Runeclaw Bear", 2);
|
||||||
|
assertPowerToughness(computerB, "Runeclaw Bear", 2, 2, Filter.ComparisonScope.Any);
|
||||||
|
assertPowerToughness(computerB, "Runeclaw Bear", 2, 2, Filter.ComparisonScope.All);
|
||||||
|
}
|
||||||
|
}
|
29
Mage.Tests/tests/M11/Honor of the Pure.test
Normal file
29
Mage.Tests/tests/M11/Honor of the Pure.test
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
### Test playing Honor of the Pure ###
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
$include green.white.default
|
||||||
|
|
||||||
|
### ComputerA ###
|
||||||
|
# Hand
|
||||||
|
hand:ComputerA:Honor of the Pure:1
|
||||||
|
# Battlefield
|
||||||
|
battlefield:ComputerB:Tine Shrike:1
|
||||||
|
battlefield:ComputerB:Runeclaw Bear:1
|
||||||
|
|
||||||
|
|
||||||
|
### ComputerB ###
|
||||||
|
# nothing
|
||||||
|
|
||||||
|
$options
|
||||||
|
|
||||||
|
exit_on_turn:2
|
||||||
|
|
||||||
|
$expected
|
||||||
|
|
||||||
|
turn:1
|
||||||
|
result:draw
|
||||||
|
life:ComputerA:20
|
||||||
|
life:ComputerB:20
|
||||||
|
battlefield:ComputerA:Tine Shrike:1
|
||||||
|
battlefield:ComputerA:Runeclaw Bear:1
|
||||||
|
# note: abilities are tested in code
|
30
Mage.Tests/tests/MBS/Burn the Impure - no infect.test
Normal file
30
Mage.Tests/tests/MBS/Burn the Impure - no infect.test
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
### Test playing Burn the Impure ###
|
||||||
|
### Target: creature with no Infect ###
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
$include red.default
|
||||||
|
|
||||||
|
### ComputerA ###
|
||||||
|
# Hand
|
||||||
|
hand:ComputerA:Burn the Impure:1
|
||||||
|
|
||||||
|
### ComputerB ###
|
||||||
|
# Battlefield
|
||||||
|
battlefield:ComputerB:Runeclaw Bear:1
|
||||||
|
# Life
|
||||||
|
player:ComputerB:life:3
|
||||||
|
|
||||||
|
$options
|
||||||
|
|
||||||
|
exit_on_turn:2
|
||||||
|
|
||||||
|
$expected
|
||||||
|
|
||||||
|
turn:1
|
||||||
|
result:draw
|
||||||
|
life:ComputerA:20
|
||||||
|
life:ComputerB:3
|
||||||
|
#battlefield:ComputerB:Runeclaw Bear:0
|
||||||
|
#graveyard:ComputerB:Runeclaw Bear:1
|
||||||
|
|
||||||
|
|
29
Mage.Tests/tests/MBS/Burn the Impure.test
Normal file
29
Mage.Tests/tests/MBS/Burn the Impure.test
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
### Test playing Burn the Impure ###
|
||||||
|
### Target: creature with Infect ###
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
$include red.default
|
||||||
|
|
||||||
|
### ComputerA ###
|
||||||
|
# Hand
|
||||||
|
hand:ComputerA:Burn the Impure:1
|
||||||
|
|
||||||
|
### ComputerB ###
|
||||||
|
# Battlefield
|
||||||
|
battlefield:ComputerB:Tine Shrike:1
|
||||||
|
# Life
|
||||||
|
player:ComputerB:life:3
|
||||||
|
|
||||||
|
$options
|
||||||
|
|
||||||
|
exit_on_turn:2
|
||||||
|
|
||||||
|
$expected
|
||||||
|
|
||||||
|
turn:1
|
||||||
|
result:won
|
||||||
|
life:ComputerA:20
|
||||||
|
life:ComputerB:0
|
||||||
|
#battlefield:ComputerB:Tine Shrike:0
|
||||||
|
#graveyard:ComputerB:Tine Shrike:1
|
||||||
|
|
31
Mage.Tests/tests/green.white.default
Normal file
31
Mage.Tests/tests/green.white.default
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Default init game state for white player (that plays with Plains)
|
||||||
|
|
||||||
|
### ComputerA ###
|
||||||
|
|
||||||
|
# Battlefield
|
||||||
|
battlefield:ComputerA:Plains:5
|
||||||
|
battlefield:ComputerA:Forest:5
|
||||||
|
|
||||||
|
# Hand
|
||||||
|
hand:ComputerA:Plains:2
|
||||||
|
hand:ComputerA:Forest:2
|
||||||
|
|
||||||
|
# Library
|
||||||
|
# from down to top
|
||||||
|
library:ComputerA:clear:0
|
||||||
|
library:ComputerA:Plains:5
|
||||||
|
library:ComputerA:Forest:5
|
||||||
|
|
||||||
|
### ComputerB ###
|
||||||
|
|
||||||
|
# Battlefield
|
||||||
|
battlefield:ComputerB:Mountain:2
|
||||||
|
|
||||||
|
# Hand
|
||||||
|
hand:ComputerB:Mountain:2
|
||||||
|
|
||||||
|
# Library
|
||||||
|
# from down to top
|
||||||
|
library:ComputerB:clear:0
|
||||||
|
library:ComputerB:Mountain:10
|
||||||
|
|
28
Mage.Tests/tests/red.default
Normal file
28
Mage.Tests/tests/red.default
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Default init game state for red player (that plays with Mountains)
|
||||||
|
|
||||||
|
### ComputerA ###
|
||||||
|
|
||||||
|
# Battlefield
|
||||||
|
battlefield:ComputerA:Mountain:5
|
||||||
|
|
||||||
|
# Hand
|
||||||
|
hand:ComputerA:Mountain:4
|
||||||
|
|
||||||
|
# Library
|
||||||
|
# from down to top
|
||||||
|
library:ComputerA:clear:0
|
||||||
|
library:ComputerA:Mountain:10
|
||||||
|
|
||||||
|
### ComputerB ###
|
||||||
|
|
||||||
|
# Battlefield
|
||||||
|
battlefield:ComputerB:Plains:2
|
||||||
|
|
||||||
|
# Hand
|
||||||
|
hand:ComputerB:Plains:2
|
||||||
|
|
||||||
|
# Library
|
||||||
|
# from down to top
|
||||||
|
library:ComputerB:clear:0
|
||||||
|
library:ComputerB:Plains:10
|
||||||
|
|
28
Mage.Tests/tests/white.default
Normal file
28
Mage.Tests/tests/white.default
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Default init game state for white player (that plays with Plains)
|
||||||
|
|
||||||
|
### ComputerA ###
|
||||||
|
|
||||||
|
# Battlefield
|
||||||
|
battlefield:ComputerA:Plains:5
|
||||||
|
|
||||||
|
# Hand
|
||||||
|
hand:ComputerA:Plains:4
|
||||||
|
|
||||||
|
# Library
|
||||||
|
# from down to top
|
||||||
|
library:ComputerA:clear:0
|
||||||
|
library:ComputerA:Plains:10
|
||||||
|
|
||||||
|
### ComputerB ###
|
||||||
|
|
||||||
|
# Battlefield
|
||||||
|
battlefield:ComputerB:Mountain:2
|
||||||
|
|
||||||
|
# Hand
|
||||||
|
hand:ComputerB:Mountain:2
|
||||||
|
|
||||||
|
# Library
|
||||||
|
# from down to top
|
||||||
|
library:ComputerB:clear:0
|
||||||
|
library:ComputerB:Mountain:10
|
||||||
|
|
|
@ -139,7 +139,7 @@ public interface Game extends MageItem, Serializable {
|
||||||
//game play methods
|
//game play methods
|
||||||
//public void init(UUID choosingPlayerId);
|
//public void init(UUID choosingPlayerId);
|
||||||
public void start(UUID choosingPlayerId);
|
public void start(UUID choosingPlayerId);
|
||||||
public void start(UUID choosingPlayerId, boolean testMode);
|
public void start(UUID choosingPlayerId, GameOptions options);
|
||||||
public void end();
|
public void end();
|
||||||
public void mulligan(UUID playerId);
|
public void mulligan(UUID playerId);
|
||||||
public void quit(UUID playerId);
|
public void quit(UUID playerId);
|
||||||
|
|
|
@ -292,19 +292,20 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(UUID choosingPlayerId) {
|
public void start(UUID choosingPlayerId) {
|
||||||
start(choosingPlayerId, false);
|
start(choosingPlayerId, GameOptions.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(UUID choosingPlayerId, boolean testMode) {
|
public void start(UUID choosingPlayerId, GameOptions options) {
|
||||||
init(choosingPlayerId, testMode);
|
init(choosingPlayerId, options.testMode);
|
||||||
PlayerList players = state.getPlayerList(startingPlayerId);
|
PlayerList players = state.getPlayerList(startingPlayerId);
|
||||||
Player player = getPlayer(players.get());
|
Player player = getPlayer(players.get());
|
||||||
while (!isGameOver()) {
|
while (!isGameOver()) {
|
||||||
if (player.getId().equals(startingPlayerId)) {
|
//if (player.getId().equals(startingPlayerId)) {
|
||||||
state.setTurnNum(state.getTurnNum() + 1);
|
state.setTurnNum(state.getTurnNum() + 1);
|
||||||
fireInformEvent("Turn " + Integer.toString(state.getTurnNum()));
|
fireInformEvent("Turn " + Integer.toString(state.getTurnNum()));
|
||||||
}
|
//}
|
||||||
|
if (checkStopOnTurnOption(options)) return;
|
||||||
state.setActivePlayerId(player.getId());
|
state.setActivePlayerId(player.getId());
|
||||||
state.getTurn().play(this, player.getId());
|
state.getTurn().play(this, player.getId());
|
||||||
if (isGameOver())
|
if (isGameOver())
|
||||||
|
@ -318,6 +319,17 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
|
||||||
saveState();
|
saveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkStopOnTurnOption(GameOptions options) {
|
||||||
|
if (options.stopOnTurn != null) {
|
||||||
|
if (options.stopOnTurn.equals(state.getTurnNum())) {
|
||||||
|
winnerId = null; //DRAW
|
||||||
|
saveState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected void init(UUID choosingPlayerId, boolean testMode) {
|
protected void init(UUID choosingPlayerId, boolean testMode) {
|
||||||
for (Player player: state.getPlayers().values()) {
|
for (Player player: state.getPlayers().values()) {
|
||||||
player.beginTurn(this);
|
player.beginTurn(this);
|
||||||
|
|
27
Mage/src/mage/game/GameOptions.java
Normal file
27
Mage/src/mage/game/GameOptions.java
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package mage.game;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Game options for Mage game.
|
||||||
|
* Mainly used in tests to configure {@link GameImpl} with specific params.
|
||||||
|
*
|
||||||
|
* @author ayratn
|
||||||
|
*/
|
||||||
|
public class GameOptions {
|
||||||
|
|
||||||
|
private static GameOptions defInstance = new GameOptions();
|
||||||
|
|
||||||
|
public static GameOptions getDefault() {
|
||||||
|
return defInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the running mode. There are some exclusions made for test mode.
|
||||||
|
*/
|
||||||
|
public boolean testMode = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the turn number game should stop on.
|
||||||
|
* By default, is null meaning that game shouldn't stop on any specific turn.
|
||||||
|
*/
|
||||||
|
public Integer stopOnTurn = null;
|
||||||
|
}
|
|
@ -96,6 +96,9 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
public boolean hasLeft();
|
public boolean hasLeft();
|
||||||
public ManaPool getManaPool();
|
public ManaPool getManaPool();
|
||||||
public Set<UUID> getInRange();
|
public Set<UUID> getInRange();
|
||||||
|
|
||||||
|
public boolean isTestMode();
|
||||||
|
public void setTestMode(boolean value);
|
||||||
|
|
||||||
public void init(Game game);
|
public void init(Game game);
|
||||||
public void init(Game game, boolean testMode);
|
public void init(Game game, boolean testMode);
|
||||||
|
|
|
@ -98,6 +98,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
|
||||||
protected boolean left;
|
protected boolean left;
|
||||||
protected RangeOfInfluence range;
|
protected RangeOfInfluence range;
|
||||||
protected Set<UUID> inRange = new HashSet<UUID>();
|
protected Set<UUID> inRange = new HashSet<UUID>();
|
||||||
|
protected boolean isTestMode = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract T copy();
|
public abstract T copy();
|
||||||
|
@ -1013,4 +1014,11 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTestMode() {
|
||||||
|
return isTestMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTestMode(boolean value) {
|
||||||
|
this.isTestMode = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue