/*******************************************************************************
* 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 java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import ca.mcgill.cs.stg.solitaire.cards.Card;
import ca.mcgill.cs.stg.solitaire.cards.Card.Rank;
import ca.mcgill.cs.stg.solitaire.model.GameModel.SuitStackIndex;
/**
* Manages the state of the four stacks where completed
* suits are accumulated.
*/
class SuitStackManager
{
private Map<SuitStackIndex, Stack<Card>> aStacks = new HashMap<>();
/**
* Creates an initialized suit stack manager.
*/
SuitStackManager()
{
initialize();
}
/**
* @return The number of cards in the suit stacks.
*/
int getScore()
{
int total = 0;
for( Stack<Card> stack : aStacks.values())
{
total += stack.size();
}
return total;
}
/**
* Initialize the internal data structures.
*/
void initialize()
{
for( SuitStackIndex index : SuitStackIndex.values() )
{
aStacks.put(index, new Stack<Card>());
}
}
/**
* @param pSuit
* @return True if the stack at index pIndex is empty
*/
boolean isEmpty(SuitStackIndex pIndex)
{
return aStacks.get(pIndex).isEmpty();
}
/**
* @param pCard The card to test
* @param pIndex The suitstack to test
* @return True if pCard can be moved to the top of its suit stack.
* This is only possible if its rank is immediately superior
* to that of the card currently on top of the suit stack.
*/
boolean canMoveTo(Card pCard, SuitStackIndex pIndex )
{
assert pCard != null && pIndex != null;
if( isEmpty(pIndex))
{
return pCard.getRank() == Rank.ACE;
}
else
{
return pCard.getSuit() == peek(pIndex).getSuit() && pCard.getRank().ordinal() == peek(pIndex).getRank().ordinal()+1;
}
}
/**
* @param pIndex The index of the stack to peek
* @return The card on top of the stack at index pIndex
*/
Card peek(SuitStackIndex pIndex)
{
assert !aStacks.get(pIndex).isEmpty();
return aStacks.get(pIndex).peek();
}
/**
* Push pCard onto the stack corresponding to its
* index.
* @param pCard The card to push.
* @param pIndex The index where to push the card.
*/
void push(Card pCard, SuitStackIndex pIndex)
{
aStacks.get(pIndex).push(pCard);
}
/**
* Pop the top card of the stack.
* @param pIndex the index of the stack to pop
* @pre !isEmpty(pSuit)
*/
Card pop(SuitStackIndex pIndex)
{
assert !isEmpty(pIndex);
return aStacks.get(pIndex).pop();
}
}