/*******************************************************************************
* Solitaire
*
* Copyright (C) 2016 by Martin P. Robillard
*
* See: https://github.com/prmr/Solitaire
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package ca.mcgill.cs.stg.solitaire.model;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Field;
import org.junit.Before;
import org.junit.Test;
import ca.mcgill.cs.stg.solitaire.cards.Card;
import ca.mcgill.cs.stg.solitaire.cards.Card.Rank;
import ca.mcgill.cs.stg.solitaire.cards.Card.Suit;
import ca.mcgill.cs.stg.solitaire.model.GameModel.StackIndex;
import ca.mcgill.cs.stg.solitaire.model.GameModel.SuitStackIndex;
public class TestGameModel
{
@Before
public void setup() throws Exception
{
Field deckField = GameModel.class.getDeclaredField("aDeck");
deckField.setAccessible(true);
deckField.set(GameModel.instance(), new TestDeck());
GameModel.instance().reset();
}
@Test
public void testListeners()
{
final boolean[] test = {false};
class ListenerStub implements GameModelListener
{
@Override
public void gameStateChanged()
{
test[0] = true;
}
};
// Test no crash
GameModel.instance().getDiscardMove().perform();
GameModel.instance().addListener(new ListenerStub());
GameModel.instance().getDiscardMove().perform();
assertTrue(test[0]);
}
@Test
public void testDiscard()
{
assertTrue(GameModel.instance().isEmptyDiscardPile());
assertFalse(GameModel.instance().isEmptyDeck());// 3 of hearts
for( int i = 0; i < 24; i++ )
{
assertFalse(GameModel.instance().isEmptyDeck());
GameModel.instance().getDiscardMove().perform();
// Test a few cards
if( i == 0 )
{
assertEquals(Card.get(Rank.JACK, Suit.DIAMONDS), GameModel.instance().peekDiscardPile());
}
if( i == 1 )
{
assertEquals(Card.get(Rank.TEN, Suit.DIAMONDS), GameModel.instance().peekDiscardPile());
}
assertFalse(GameModel.instance().isEmptyDiscardPile());
}
assertTrue(GameModel.instance().isEmptyDeck());
}
@Test
public void testGetStack()
{
GameModel model = GameModel.instance();
Card[] stack = model.getStack(StackIndex.FIRST);
assertEquals(Card.get(Rank.KING, Suit.SPADES), stack[0]);
assertEquals(1, stack.length);
// Test that the method returns a clone
stack[0] =Card.get(Rank.QUEEN, Suit.CLUBS);
stack = model.getStack(StackIndex.FIRST);
assertEquals(Card.get(Rank.KING, Suit.SPADES), stack[0]);
assertEquals(1, stack.length);
stack = model.getStack(StackIndex.SECOND);
assertEquals(2, stack.length);
assertEquals(Card.get(Rank.QUEEN, Suit.SPADES), stack[0]);
assertEquals(Card.get(Rank.JACK, Suit.SPADES), stack[1]);
}
@Test
public void testGetSubStack()
{
GameModel model = GameModel.instance();
Card[] stack = model.getSubStack(Card.get(Rank.KING, Suit.SPADES), StackIndex.FIRST);
assertEquals(Card.get(Rank.KING, Suit.SPADES), stack[0]);
assertEquals(1, stack.length);
// Test that the method returns a clone
stack[0] = Card.get(Rank.QUEEN, Suit.CLUBS);
stack = model.getSubStack(Card.get(Rank.KING, Suit.SPADES), StackIndex.FIRST);
assertEquals(Card.get(Rank.KING, Suit.SPADES), stack[0]);
assertEquals(1, stack.length);
stack = model.getSubStack(Card.get(Rank.TEN, Suit.SPADES), StackIndex.THIRD);
assertEquals(3, stack.length);
stack = model.getSubStack(Card.get(Rank.NINE, Suit.SPADES), StackIndex.THIRD);
assertEquals(2, stack.length);
stack = model.getSubStack(Card.get(Rank.EIGHT, Suit.SPADES), StackIndex.THIRD);
assertEquals(1, stack.length);
}
@Test
public void testMoves()
{
GameModel model = GameModel.instance();
assertTrue(model.isEmptySuitStack(SuitStackIndex.FIRST));
assertFalse(model.isLegalMove(Card.get(Rank.THREE, Suit.CLUBS), SuitStackIndex.SECOND));
assertFalse(model.isLegalMove(Card.get(Rank.THREE, Suit.CLUBS), SuitStackIndex.FIRST));
assertFalse(model.isLegalMove(Card.get(Rank.TWO, Suit.CLUBS), SuitStackIndex.FIRST));
assertTrue(model.isLegalMove(Card.get(Rank.ACE, Suit.CLUBS), SuitStackIndex.FIRST));
model.getDiscardMove().perform(); // Jack of diamond
model.getDiscardMove().perform(); // Ten of diamond
assertTrue(model.isLegalMove(model.peekDiscardPile(), StackIndex.SECOND));
model.getCardMove(model.peekDiscardPile(), StackIndex.SECOND).perform();
model.getDiscardMove().perform();
assertFalse(model.isLegalMove(model.peekDiscardPile(), StackIndex.SECOND));
model.getDiscardMove().perform();
assertEquals(Card.get(Rank.EIGHT, Suit.DIAMONDS), model.peekDiscardPile());
model.getDiscardMove().perform();
assertTrue(model.isLegalMove(model.peekDiscardPile(), StackIndex.THIRD));
model.getCardMove(model.peekDiscardPile(), StackIndex.THIRD).perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
assertEquals(Card.get(Rank.FIVE, Suit.DIAMONDS), model.peekDiscardPile());
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
assertEquals(Card.get(Rank.ACE, Suit.DIAMONDS), model.peekDiscardPile());
assertTrue(model.isLegalMove(model.peekDiscardPile(), SuitStackIndex.SECOND));
model.getCardMove(model.peekDiscardPile(), SuitStackIndex.SECOND).perform();
assertEquals(Card.get(Rank.ACE, Suit.DIAMONDS), model.peekSuitStack(SuitStackIndex.SECOND));
assertEquals(Card.get(Rank.TWO, Suit.DIAMONDS), model.peekDiscardPile());
model.getCardMove(model.peekDiscardPile(), SuitStackIndex.SECOND).perform();
assertEquals(Card.get(Rank.TWO, Suit.DIAMONDS), model.peekSuitStack(SuitStackIndex.SECOND));
model.getCardMove(model.peekDiscardPile(), SuitStackIndex.SECOND).perform();
model.getCardMove(model.peekDiscardPile(), SuitStackIndex.SECOND).perform();
model.getCardMove(model.peekDiscardPile(), SuitStackIndex.SECOND).perform();
model.getCardMove(model.peekDiscardPile(), SuitStackIndex.SECOND).perform();
// 8th of diamond is on top of the discard pile
assertFalse(model.isLegalMove(model.peekDiscardPile(), SuitStackIndex.SECOND));
model.getCardMove(Card.get(Rank.SEVEN, Suit.DIAMONDS), SuitStackIndex.SECOND).perform();
// move the 7th back to the working stack
model.getCardMove(Card.get(Rank.SEVEN, Suit.DIAMONDS), StackIndex.THIRD).perform();
}
@Test
public void testMoves2()
{
GameModel model = GameModel.instance();
model.getDiscardMove().perform();
model.getDiscardMove().perform(); // 10D on discard pile
model.getCardMove(model.peekDiscardPile(), StackIndex.SECOND).perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform();
model.getDiscardMove().perform(); // 9C on discard pile
assertEquals(Card.get(Rank.NINE, Suit.CLUBS), model.peekDiscardPile());
model.getCardMove(model.peekDiscardPile(), StackIndex.SECOND).perform();
// move three card sequence to pile 7
Card[] stack = model.getSubStack(Card.get(Rank.JACK, Suit.SPADES), StackIndex.SECOND);
assertEquals(3, stack.length);
assertEquals(Card.get(Rank.JACK, Suit.SPADES), stack[0]);
assertEquals(Card.get(Rank.TEN, Suit.DIAMONDS), stack[1]);
assertEquals(Card.get(Rank.NINE, Suit.CLUBS), stack[2]);
model.getCardMove(stack[0], StackIndex.SEVENTH).perform();
assertEquals(1, model.getStack(StackIndex.SECOND).length);
stack = model.getSubStack(Card.get(Rank.JACK, Suit.SPADES), StackIndex.SEVENTH);
assertEquals(10, model.getStack(StackIndex.SEVENTH).length);
model.getCardMove(model.getSubStack(Card.get(Rank.QUEEN, Suit.DIAMONDS), StackIndex.SEVENTH)[0], StackIndex.FIRST).perform();
Card[] stack2 = model.getStack(StackIndex.FIRST);
assertEquals(5, stack2.length);
}
@Test
public void testMoves3()
{
GameModel model = GameModel.instance();
for( int i = 0; i < 14; i++ )
{
model.getDiscardMove().perform();
}
assertEquals(Card.get(Rank.JACK, Suit.CLUBS), model.peekDiscardPile());
model.getCardMove(model.peekDiscardPile(), StackIndex.FIFTH).perform();
assertEquals(6, model.getStack(StackIndex.FIFTH).length);
model.getCardMove(model.getSubStack(Card.get(Rank.JACK, Suit.CLUBS), StackIndex.FIFTH)[0], StackIndex.SEVENTH).perform();
assertEquals(5, model.getStack(StackIndex.FIFTH).length);
assertEquals(8, model.getStack(StackIndex.SEVENTH).length);
}
@Test
public void testNullMove()
{
GameModel model = GameModel.instance();
Move nullMove = model.getNullMove();
assertTrue(nullMove.isNull());
// Only really tests that nothing crashes
nullMove.perform();
nullMove.undo();
}
@Test
public void testUndo1()
{
// Tests undoing discard moves
GameModel model = GameModel.instance();
assertTrue(model.isEmptyDiscardPile());
assertFalse(model.canUndo());
Move discard = model.getDiscardMove();
assertFalse(discard.isNull());
discard.perform();
assertTrue(model.canUndo());
Card card = model.peekDiscardPile();
model.undoLast();
assertFalse(model.canUndo());
assertTrue(model.isEmptyDiscardPile());
model.getDiscardMove().perform();
assertEquals(card, model.peekDiscardPile());
}
@Test
public void testGetScore()
{
GameModel model = GameModel.instance();
assertEquals( 0, model.getScore());
assertFalse(model.isCompleted());
}
}