/** * Copyright (C) 2017 Jan Schäfer (jansch@users.sourceforge.net) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jskat.player; import java.util.EnumSet; import org.jskat.data.GameAnnouncement; import org.jskat.data.Trick; import org.jskat.util.Card; import org.jskat.util.CardList; import org.jskat.util.GameType; import org.jskat.util.Player; import org.jskat.util.Rank; import org.jskat.util.Suit; import org.jskat.util.rule.SkatRule; import org.jskat.util.rule.SkatRuleFactory; public final class PlayerKnowledge extends ImmutablePlayerKnowledge { public PlayerKnowledge() { initializeVariables(); } private void addOwnCard(final Card card) { if (ownCards.add(card)) { possiblePlayerCards.get(playerPosition.getLeftNeighbor()) .remove(card); possiblePlayerCards.get(playerPosition.getRightNeighbor()) .remove(card); possibleSkatCards.remove(card); } } /** * Adds cards to the own cards and the suit/point counter * * @param cards * Card to be added */ public void addOwnCards(final Iterable<Card> cards) { for (Card card : cards) { addOwnCard(card); } for (Card card : Card.values()) { if (!ownCards.contains(card)) { possiblePlayerCards.get(playerPosition).remove(card); } } } /** * Adds a trick to the knowledge * * @param trick * Trick to be added */ public void addCompletedTrick(final Trick trick) { tricks.add(trick); } /** * Clears the cards played in the trick */ private void clearTrickCards() { leftPlayerTrickCard = null; rightPlayerTrickCard = null; } /** * Initializes all parameters */ private void initializeVariables() { resetCurrentGameData(); } public void removeOwnCard(final Card card) { ownCards.remove(card); } public void removeOwnCards(final CardList cards) { for (Card card : cards) { removeOwnCard(card); } } /** * Resets the data of the current game */ public void resetCurrentGameData() { ownCards.clear(); skat.clear(); singlePlayerCards.clear(); schneiderAnnounced = false; schwarzAnnounced = false; handGame = false; ouvertGame = false; for (Player player : Player.values()) { highestBid.put(player, Integer.valueOf(0)); playedCards.put(player, EnumSet.noneOf(Card.class)); possiblePlayerCards.put(player, EnumSet.allOf(Card.class)); } possibleSkatCards.clear(); possibleSkatCards.addAll(EnumSet.allOf(Card.class)); leftPlayerTrickCard = null; rightPlayerTrickCard = null; trumpCount = 0; tricks.clear(); } /** * Sets a card played * * @param player * Player ID * @param card * Card */ public void setCardPlayed(final Player player, final Card card) { playedCards.get(player).add(card); if (playerPosition.equals(player)) { removeOwnCard(card); if (card.isTrump(getGameType())) { trumpCount--; } } setTrickCard(player, card); } /** * Sets the current trick * * @param trickNo * Trick no in game * @param trickForehand * Forehand player for the trick */ public void setNextTrick(int trickNo, Player trickForehand) { this.currentTrick = new Trick(trickNo, trickForehand); clearTrickCards(); } /** * Set the declarer position * * @param newDeclarer * Declarer position */ public void setDeclarer(final Player newDeclarer) { declarer = newDeclarer; } /** * Sets the game announcement * * @param gameAnn * Game announcement to set */ public void setGame(final GameAnnouncement gameAnn) { announcement = gameAnn; trumpCount = 0; if (!GameType.PASSED_IN.equals(getGameType())) { for (Card c : ownCards) { // FIXME (jansch 21.09.2011) Cards shouldn't check whether they // are trump or not, let skat rules do the job if (c.isTrump(getGameType())) { trumpCount++; } } } } /** * @param handGame * the handGame to set */ public void setHandGame(final boolean handGame) { this.handGame = handGame; } /** * Sets the highest bid for a player * * @param player * Player ID * @param bidValue * Highest bid for the player */ public void setHighestBid(final Player player, final Integer bidValue) { highestBid.put(player, bidValue); } /** * Adjusts the knowledge when a player has not followed a suit * * @param player * Player ID * @param suit * Suit that the player didn't follow */ public void setMissingSuit(final Player player, final Suit suit) { for (Rank rank : Rank.values()) { if (rank != Rank.JACK || GameType.NULL.equals(getGameType()) || GameType.RAMSCH.equals(getGameType())) { possiblePlayerCards.get(player) .remove(Card.getCard(suit, rank)); } } } /** * @param ouvertGame * the ouvertGame to set */ public void setOuvertGame(final boolean ouvertGame) { this.ouvertGame = ouvertGame; } /** * Sets the player position * * @param newPlayerPosition * Player position */ public void setPlayerPosition(final Player newPlayerPosition) { playerPosition = newPlayerPosition; } /** * @param schneiderAnnounced * the schneiderAnnounced to set */ public void setSchneiderAnnounced(final boolean schneiderAnnounced) { this.schneiderAnnounced = schneiderAnnounced; } /** * @param schwarzAnnounced * the schwarzAnnounced to set */ public void setSchwarzAnnounced(final boolean schwarzAnnounced) { this.schwarzAnnounced = schwarzAnnounced; } /** * @param singlePlayerCards * the singlePlayerCards to set */ public void setSinglePlayerCards(final CardList singlePlayerCards) { this.singlePlayerCards.clear(); for (Card card : singlePlayerCards) { this.singlePlayerCards.add(card); } } /** * @param newSkat * the skat to set */ public void setSkat(final CardList newSkat) { skat.clear(); for (Card card : newSkat) { skat.add(card); } } /** * Sets a card played by another player * * @param otherPlayer * Player position of other player * @param playedCard * Card played */ private void setTrickCard(final Player otherPlayer, final Card playedCard) { if (getPlayerPosition().getLeftNeighbor() == otherPlayer) { leftPlayerTrickCard = playedCard; } else if (getPlayerPosition().getRightNeighbor() == otherPlayer) { rightPlayerTrickCard = playedCard; } for (Player currPlayer : Player.values()) { possiblePlayerCards.get(currPlayer).remove(playedCard); } possibleSkatCards.remove(playedCard); currentTrick.addCard(playedCard); // adjust the knowledge about "could have" cards Card firstCard = currentTrick.getFirstCard(); Card secondCard = currentTrick.getSecondCard(); Card thirdCard = currentTrick.getThirdCard(); if (firstCard != null && (secondCard != null || thirdCard != null)) { Card cardToCheck = null; if (thirdCard == null) { cardToCheck = secondCard; } else { cardToCheck = thirdCard; } adjustPossibleCards(otherPlayer, firstCard, cardToCheck); } } private void adjustPossibleCards(final Player otherPlayer, Card firstTrickCard, Card cardPlayed) { if (GameType.NULL.equals(getGameType())) { if (!firstTrickCard.isSameSuit(cardPlayed)) { // player has not followed suit // this means he has no cards with this suit // remove all cards from same suit from "could have" cards for (Card currCard : Card.values()) { if (currCard.isSameSuit(firstTrickCard)) { possiblePlayerCards.get(otherPlayer) .remove(currCard); } } } } else { SkatRule skatRules = SkatRuleFactory .getSkatRules(getGameType()); if (firstTrickCard.isTrump(getGameType())) { if (!cardPlayed.isTrump(getGameType())) { // first card was a trump card, player card was not // remove jacks from the "could have" cards possiblePlayerCards.get(otherPlayer).remove(Card.CJ); possiblePlayerCards.get(otherPlayer).remove(Card.SJ); possiblePlayerCards.get(otherPlayer).remove(Card.HJ); possiblePlayerCards.get(otherPlayer).remove(Card.DJ); // remove other trump cards for suit games if (GameType.CLUBS.equals(getGameType()) || GameType.SPADES.equals(getGameType()) || GameType.HEARTS.equals(getGameType()) || GameType.DIAMONDS.equals(getGameType())) { for (Card currCard : Card.values()) { if (getGameType().getTrumpSuit() .equals(currCard.getSuit())) { possiblePlayerCards.get(otherPlayer) .remove(currCard); } } } } } else { // first card was not a trump card if (!firstTrickCard.isSameSuit(cardPlayed)) { // player has not followed suit // this means he has no cards with this suit // remove all cards for that suit in "could have" // cards, except of the jacks for (Card currCard : Card.values()) { if (currCard.isSameSuit(firstTrickCard) && currCard.getRank() != Rank.JACK) { possiblePlayerCards.get(otherPlayer) .remove(currCard); } } } } } } }