package ch.bfh.jass.game;
import ch.bfh.jass.game.JassCardSet.CardColor;
import ch.bfh.jass.game.JassCardSet.CardRank;
import ch.bfh.jass.interfaces.ICardSet;
import ch.bfh.jass.interfaces.IPlayer;
import ch.bfh.jass.interfaces.IRule;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
/**
* @author David Baumgartner <baumd9@bfh.ch>, Fabian Schneider <schnf6@bfh.ch>
* @version 1.0
*/
public class JassRule implements IRule {
/**
* The cardset of the rule
*/
private ICardSet cardSet;
/**
* The holder of this card, is able to begin to play
*/
private final static Card START_CARD = new Card(CardColor.ECKE, CardRank.SIEBEN);
/**
* Number of allowed players
*/
private final static int NUMBER_OF_PLAYERS = 4;
/**
* Number of allowed teams
*/
private final static int NUMBER_OF_TEAMS = 2;
/**
* Number of cards on the table
*/
private final static int NUMBER_OF_TABLE_CARDS = 4;
/**
* Number of cards in the hand of a player
*/
private final static int NUMBER_OF_HANDCARDS = 9;
/**
* Points for the last trick
*/
private final static int LAST_TRICK = 5;
/**
* The color of trumpf
*/
private CardColor trumpf;
/**
* How many points a team has to achiev
*/
private int endPoints;
private Map<CardRank, Integer> trumpfCardWorth = new EnumMap<CardRank, Integer>(CardRank.class);
private Map<CardRank, Integer> trumpfCardPoints = new EnumMap<CardRank, Integer>(CardRank.class);
private Map<CardRank, Integer> cardPoints = new EnumMap<CardRank, Integer>(CardRank.class);
/**
* The starting player
*/
private IPlayer starter;
/**
* True if the trumpf has moved
*/
private boolean trumpfMoved = false;
/**
* Class Constructor
*/
public JassRule() {
this.cardSet = new JassCardSet();
this.endPoints = 500;
trumpfCardWorth.put(CardRank.SECHS, 1);
trumpfCardWorth.put(CardRank.SIEBEN, 2);
trumpfCardWorth.put(CardRank.ACHT, 3);
trumpfCardWorth.put(CardRank.NEUN, 8);
trumpfCardWorth.put(CardRank.ZEHN, 4);
trumpfCardWorth.put(CardRank.BUBE, 9);
trumpfCardWorth.put(CardRank.DAME, 5);
trumpfCardWorth.put(CardRank.KOENIG, 6);
trumpfCardWorth.put(CardRank.ASS, 7);
trumpfCardPoints.put(CardRank.SECHS, 0);
trumpfCardPoints.put(CardRank.SIEBEN, 0);
trumpfCardPoints.put(CardRank.ACHT, 0);
trumpfCardPoints.put(CardRank.NEUN, 14);
trumpfCardPoints.put(CardRank.ZEHN, 10);
trumpfCardPoints.put(CardRank.BUBE, 20);
trumpfCardPoints.put(CardRank.DAME, 3);
trumpfCardPoints.put(CardRank.KOENIG, 4);
trumpfCardPoints.put(CardRank.ASS, 11);
cardPoints.put(CardRank.SECHS, 0);
cardPoints.put(CardRank.SIEBEN, 0);
cardPoints.put(CardRank.ACHT, 0);
cardPoints.put(CardRank.NEUN, 0);
cardPoints.put(CardRank.ZEHN, 10);
cardPoints.put(CardRank.BUBE, 2);
cardPoints.put(CardRank.DAME, 3);
cardPoints.put(CardRank.KOENIG, 4);
cardPoints.put(CardRank.ASS, 11);
}
public static Card getStartCard() {
return START_CARD;
}
@Override
public ICardSet getCardSet() {
return this.cardSet;
}
@Override
public void resetCardSet() {
this.cardSet.resetCardSet();
}
/**
* *
* For testing
*
* @return
*/
@Override
public List<Card> getAllCards() {
return this.cardSet.getAllCards();
}
@Override
public Hand getHand() {
return new Hand(this.sortCards(this.cardSet.getCards(NUMBER_OF_HANDCARDS)));
}
@Override
public int getNumberOfPlayers() {
return NUMBER_OF_PLAYERS;
}
@Override
public int getNumberOfTableCards() {
return NUMBER_OF_TABLE_CARDS;
}
@Override
public int getNumberOfTeams() {
return NUMBER_OF_TEAMS;
}
@Override
public IPlayer getStartPlayer() {
List<Card> cards = (List) this.cardSet.getAllCards();
this.starter = cards.get(cards.indexOf(START_CARD)).getHolder();
return this.starter;
}
/**
* Verifies if a card is playable.
*
* @param card
* @param table
* @return boolean
*/
@Override
public boolean isPlayable(Card card, Table table) {
CardColor tableColor;
if (table.getSize() <= 0) {
return true;
} else if ((tableColor = table.getCard(table.getFirstCardPlace()).getColor()) == card.getColor()) {
return true;
} else if (card.getColor() == this.trumpf) {
return true;
} else if (!card.getHolder().hasColorInHand(tableColor)) {
return true;
} else {
if (tableColor == this.trumpf) {
List<Card> cards = card.getHolder().getCardsByColor(this.trumpf);
if (cards.size() == 1) {
cards.get(0).equals(new Card(this.trumpf, CardRank.SECHS));
}
}
return false;
}
}
/**
* Returns the winner card on the table.
*
* @param table
* @return
*/
@Override
public Card winnerCard(Table table) {
if (table.hasColor(this.trumpf)) {
return this.getHighestCard(table.getCardsByColor(this.trumpf));
} else {
return this.getHighestCard(table.getCardsByColor(table.getCard(table.getFirstCardPlace()).getColor()));
}
}
/**
* Returns the highest card oh a list.
*
* @param cards
* @return
*/
public Card getHighestCard(List<Card> cards) {
Card highestCard = cards.get(0);
for (Card card : cards) {
if (this.getWorth(card) > this.getWorth(highestCard)) {
highestCard = card;
}
}
return highestCard;
}
public CardColor getTrumpf() {
return trumpf;
}
public void setTrumpf(CardColor trumpf) {
if (trumpf == null) {
this.trumpfMoved = false;
}
this.trumpf = trumpf;
}
/**
* Moves trumpf.
*/
public void moveTrumpf() {
this.trumpfMoved = true;
}
public boolean isTrumpfMoved() {
return this.trumpfMoved;
}
/**
* Returns the worth of a card.
*
* @param card
* @return
*/
private int getWorth(Card card) {
if (card.getColor() == this.trumpf) {
return this.trumpfCardWorth.get(card.getRank());
} else {
return card.getRank().ordinal() + 1;
}
}
/**
* Returns the points of a card.
*
* @param card
* @return
*/
@Override
public int getPoints(Card card) {
if (card.getColor() == this.trumpf) {
return this.trumpfCardPoints.get(card.getRank());
} else {
return this.cardPoints.get(card.getRank());
}
}
@Override
public IPlayer getStarter() {
return starter;
}
@Override
public void setStarter(IPlayer starter) {
this.starter = starter;
}
/**
* Returns the winning team as a list of players.
*
* @param teams
* @return
*/
@Override
public List<IPlayer> getWinner(List<List<IPlayer>> teams) {
int[] teamPoints = this.countPoints(teams);
int winnerTeam = 0;
int winnerPoints = 0;
for (int i = 0; i < NUMBER_OF_TEAMS; i++) {
if (teamPoints[i] > winnerPoints) {
winnerTeam = i;
winnerPoints = teamPoints[i];
}
}
return teams.get(winnerTeam);
}
/**
* Verifies if one of the team has won the game.
*
* @param teams
* @return
*/
@Override
public boolean hasWinner(List<List<IPlayer>> teams) {
int[] teamPoints = this.countPoints(teams);
for (int points : teamPoints) {
if (points >= this.endPoints) {
return true;
}
}
return false;
}
/**
* Count the points of a team.
*
* @param teams
* @return
*/
@Override
public int[] countPoints(List<List<IPlayer>> teams) {
int[] teamPoints = new int[NUMBER_OF_TEAMS];
for (int i = 0; i < teams.size(); i++) {
for (IPlayer player : teams.get(i)) {
teamPoints[i] += player.getPoints();
}
}
return teamPoints;
}
/**
* Sorts the cards of a list.
* @param cards
* @return
*/
private List<Card> sortCards(List<Card> cards) {
for (int i = 1; i < cards.size(); i++) {
Card toInsert = cards.get(i);
int j = i;
while (j > 1 && this.cardPoints.get(cards.get(j - 1).getRank()) < this.cardPoints.get(toInsert.getRank())) {
cards.set(j, cards.get(j - 1));
j--;
}
cards.set(j, toInsert);
}
return cards;
}
@Override
public int getLastTrickPoints() {
return LAST_TRICK;
}
}