/** * 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 org.jskat.data.GameAnnouncement; import org.jskat.data.GameSummary; 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.rule.SkatRule; import org.jskat.util.rule.SkatRuleFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Abstract JSkat player implementation */ public abstract class AbstractJSkatPlayer implements JSkatPlayer { protected Logger log = LoggerFactory.getLogger(AbstractJSkatPlayer.class); /** Player name */ protected String playerName; /** Player state */ protected JSkatPlayer.PlayerState playerState; /** Internal player knowledge */ private final PlayerKnowledge internalKnowledge = new PlayerKnowledge(); /** Immutable Player knowledge */ protected ImmutablePlayerKnowledge knowledge = internalKnowledge; /** Skat rules for the current skat series */ protected SkatRule rules; /** Summary of the skat game */ protected GameSummary gameSummary; /** * {@inheritDoc} */ @Override public final void setPlayerName(final String newPlayerName) { playerName = newPlayerName; } /** * {@inheritDoc} */ @Override public final String getPlayerName() { return playerName; } /** * {@inheritDoc} */ @Override public final void setUpBidding() { setState(PlayerState.BIDDING); } /** * {@inheritDoc} */ @Override public final void newGame(final Player newPosition) { playerState = null; rules = null; gameSummary = null; internalKnowledge.resetCurrentGameData(); internalKnowledge.setPlayerPosition(newPosition); preparateForNewGame(); } /** * {@inheritDoc} */ @Override public final void takeCards(final CardList cards) { internalKnowledge.addOwnCards(cards); } /** * {@inheritDoc} */ @Override public final void startGame(final Player newDeclarer, final GameAnnouncement game) { playerState = PlayerState.PLAYING; internalKnowledge.setDeclarer(newDeclarer); internalKnowledge.setGame(game); rules = SkatRuleFactory.getSkatRules(game.getGameType()); if (!GameType.PASSED_IN.equals(game.getGameType())) { log.debug("Starting game for " + getPlayerName() + ": " //$NON-NLS-1$ //$NON-NLS-2$ + game.getGameType() + " (rules=" //$NON-NLS-1$ + rules.getClass() + ")"); //$NON-NLS-1$ } startGame(); } /** * does certain startGame operations * * A method that is called by the abstract player to allow individual * players to implement certain start-up operations */ public abstract void startGame(); /** * {@inheritDoc} */ @Override public final void takeSkat(final CardList skatCards) { log.debug("Skat cards: " + skatCards); //$NON-NLS-1$ internalKnowledge.setSkat(skatCards); internalKnowledge.addOwnCards(skatCards); } /** * Sets the state of the player * * @param newState * State to be set */ protected final void setState(final JSkatPlayer.PlayerState newState) { playerState = newState; } /** * {@inheritDoc} */ @Override public final void bidByPlayer(final Player player, final int bidValue) { internalKnowledge.setHighestBid(player, bidValue); } /** * Gets all playable cards * * @param trick * Current trick * @return List of all playable cards */ public final CardList getPlayableCards(final CardList trick) { boolean isCardAllowed = false; final CardList result = new CardList(); log.debug("game type: " + internalKnowledge.getGameType()); //$NON-NLS-1$ log.debug("player cards (" + internalKnowledge.getOwnCards().size() //$NON-NLS-1$ + "): " + internalKnowledge.getOwnCards()); //$NON-NLS-1$ log.debug("trick size: " + trick.size()); //$NON-NLS-1$ for (final Card card : internalKnowledge.getOwnCards()) { if (trick.size() > 0 && rules.isCardAllowed(internalKnowledge.getGameType(), trick.get(0), internalKnowledge.getOwnCards(), card)) { log.debug("Card: " + card + " is allowed after initial card: " //$NON-NLS-1$ + trick.get(0)); isCardAllowed = true; } else if (trick.size() == 0) { isCardAllowed = true; } else { isCardAllowed = false; } if (isCardAllowed) { result.add(card); } } return result; } /** * {@inheritDoc} */ @Override public final void cardPlayed(final Player player, final Card card) { internalKnowledge.setCardPlayed(player, card); } /** * {@inheritDoc} */ @Override public final void newTrick(final int trickNo, final Player trickForehand) { internalKnowledge.setNextTrick(trickNo, trickForehand); } /** * {@inheritDoc} */ @Override public final void showTrick(final Trick trick) { internalKnowledge.addCompletedTrick(trick); } /** * {@inheritDoc} */ @Override public final Boolean isHumanPlayer() { return !isAIPlayer(); } /** * {@inheritDoc} */ @Override public final Boolean isDeclarer() { boolean result = false; if (GameType.RAMSCH.equals(internalKnowledge.getGameType()) || internalKnowledge.getDeclarer().equals( internalKnowledge.getPlayerPosition())) { result = true; } return result; } /** * {@inheritDoc} */ @Override public final void lookAtOuvertCards(final CardList ouvertCards) { internalKnowledge.getSinglePlayerCards().addAll(ouvertCards); } /** * {@inheritDoc} */ @Override public final CardList discardSkat() { final CardList result = new CardList(); log.debug("Player cards before discarding: " //$NON-NLS-1$ + internalKnowledge.getOwnCards()); result.addAll(getCardsToDiscard()); internalKnowledge.removeOwnCards(result.getImmutableCopy()); log.debug("Player cards after discarding: " //$NON-NLS-1$ + internalKnowledge.getOwnCards()); return result; } protected abstract CardList getCardsToDiscard(); /** * {@inheritDoc} */ @Override public final void setGameSummary(final GameSummary gameSummary) { this.gameSummary = gameSummary; } /** * Sets a new logger for the abstract skat player * * @param newLogger * New logger */ public final void setLogger(final Logger newLogger) { log = newLogger; } }