Package ch.bfh.jass.game

Source Code of ch.bfh.jass.game.Game

package ch.bfh.jass.game;

import ch.bfh.jass.exceptions.*;
import ch.bfh.jass.game.JassCardSet.CardColor;
import ch.bfh.jass.interfaces.IPlayer;
import ch.bfh.jass.interfaces.IRule;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* @author David Baumgartner <baumd9@bfh.ch>, Fabian Schneider <schnf6@bfh.ch>
* @version 1.0
*/
public class Game {

    /**
     * Unique ID of the game.
     */
    private String gameID;
    /**
     * Rule with the game logic.
     */
    private JassRule rule;
    /**
     * The table where the game takes place.
     */
    private Table table;
    /**
     * List of all players in the game.
     */
    private PlayerList<IPlayer> players;
    /**
     * List of the points of each team.
     */
    private List<int[]> teamPoints = new ArrayList<int[]>();
    /**
     * List of the teams in the game.
     */
    private List<List<IPlayer>> teams = new ArrayList<List<IPlayer>>();
    /**
     * List of winning players.
     */
    private List<IPlayer> winnerList;
    /**
     * Player, who is the admin of the game.
     */
    private IPlayer gameAdmin;
    /**
     * Shows if the game is started.
     */
    private boolean started = false;
    /**
     * Shows if the game is finished.
     */
    private boolean gameFinished = false;

    /**
     * Class Constructor
     *
     * @param gameFounder
     * @throws PlayerAlreadyInGameException
     * @throws PlaceTakenException
     * @throws PlaceDoesNotExistException
     */
    public Game(IPlayer gameFounder) throws PlayerAlreadyInGameException, PlaceTakenException, PlaceDoesNotExistException {
        this.rule = new JassRule();
        this.table = new Table(this.rule.getNumberOfTableCards());
        this.players = new PlayerList<IPlayer>(this.rule.getNumberOfPlayers());
        this.initGame(gameFounder);
    }

    /**
     * Class Constructor
     *
     * @param gameFounder
     * @param rule
     * @throws PlayerAlreadyInGameException
     * @throws PlaceTakenException
     * @throws PlaceDoesNotExistException
     */
    public Game(IPlayer gameFounder, JassRule rule) throws PlayerAlreadyInGameException, PlaceTakenException, PlaceDoesNotExistException {
        this.rule = rule;
        this.table = new Table(this.rule.getNumberOfTableCards());
        this.players = new PlayerList<IPlayer>(this.rule.getNumberOfPlayers());
        this.initGame(gameFounder);
    }

    /**
     * Initialize the game and sets a game founder.
     *
     * @param gameFounder
     * @throws PlayerAlreadyInGameException
     * @throws PlaceTakenException
     * @throws PlaceDoesNotExistException
     */
    private void initGame(IPlayer gameFounder) throws PlayerAlreadyInGameException, PlaceTakenException, PlaceDoesNotExistException {
        this.gameAdmin = gameFounder;
        this.players.addPlayer(0, gameFounder);
        this.gameAdmin.setPlace(0);
    }

    /**
     * Starts the game.
     *
     * Fills the game with bots, if necessary, and initialize the teams.
     * Initialize the Hands and Cards of all Players and sets the current
     * player.
     *
     * @param player
     * @throws YouMustNotException
     */
    public void start(IPlayer player) throws YouMustNotException {
        if (player.equals(this.gameAdmin)) {
            if (this.players.getNumberOfTakenPlaces() < 4) {
                this.fillBots();
            }
            this.initTeams();
            this.initPlayerHands();
            this.players.setCurrent(this.rule.getStartPlayer());
            this.rule.setStarter(this.players.getCurrent());
            this.started = true;
        } else {
            throw new YouMustNotException("You may not start the game!");
        }
    }

    /**
     * Initilaizes the teams of the game according to the rule.
     */
    private void initTeams() {
        for (int i = 0; i < this.rule.getNumberOfTeams(); i++) {
            this.teams.add(new ArrayList<IPlayer>());
        }

        int team = 0;
        for (int i = 0; i < this.players.size(); i++) {

            this.teams.get(team).add(this.players.get(i));

            if (team < this.rule.getNumberOfTeams() - 1) {
                team++;
            } else {
                team = 0;
            }
        }
    }

    /**
     * @return the teams of the game
     */
    public List<List<IPlayer>> getTeams() {
        return this.teams;
    }

    /**
     * Fills the free places in the game with AIPlayers.
     */
    private void fillBots() {
        for (int i : this.players.getFreePlaces()) {
            try {
                AIJassPlayer aiPlayer = new AIJassPlayer();
                this.players.addPlayer(i, aiPlayer);
                aiPlayer.setUsername("Bot_" + i);
            } catch (Exception ex) {
                throw new RuntimeException("Something went really wrong!");
            }
        }
    }

    /**
     * Initializes the hands of all players in the game.
     */
    private void initPlayerHands() {
        for (IPlayer player : this.players) {
            player.initHand(this.rule);
        }
    }

    /**
     * Initializes a new round.
     *
     * @throws GameOverException
     */
    private void initNewRound() throws GameOverException {
        if (!this.hasWinner()) {
            this.rule.setTrumpf(null);
            this.rule.resetCardSet();
            this.initPlayerHands();
        } else {
            this.winnerList = this.rule.getWinner(this.teams);
            throw new GameOverException(this.winnerList.toString());
        }
    }

    /**
     * Plays a specified card.
     *
     * @param card
     * @throws NotYourCardException
     * @throws IsNotPlayableException
     * @throws GameOverException
     * @throws NoTrumpfSetException
     */
    public void play(Card card) throws NotYourCardException, IsNotPlayableException, GameOverException, NoTrumpfSetException {
        if (this.checkTrumpfIsSet() && !this.hasWinner()) {
            card = this.players.getCurrent().getCard(card);

            if (this.rule.isPlayable(card, table)) {
                this.players.getCurrent().playCard(card);
                this.table.addCard(this.players.indexOf(card.getHolder()), card);
                this.nextPlayer();
            } else {
                throw new IsNotPlayableException("Card not playable!");
            }
        }
    }

    /**
     * Plays a cord for an AIPlayer.
     *
     * @throws GameOverException
     */
    public void playAI() throws GameOverException {
        if (this.players.getCurrent().isAI()) {
            try {
                if (this.rule.getTrumpf() == null) {
                    this.setTrumpf(this.players.getCurrent().chooseTrumpf(), this.players.getCurrent());
                }
                this.play(this.players.getCurrent().chooseCard(this.rule, this.table));
            } catch (NotYourCardException ex) {
                throw new RuntimeException("Something went really wrong! Bot played wrong card.");
            } catch (IsNotPlayableException ex) {
                throw new RuntimeException("Something went really wrong! Bot has card which is not playable.");
            } catch (NoTrumpfSetException ex) {
                throw new RuntimeException("Something went really wrong! Bot not set a Trumpf.");
            } catch (YouMustNotSetTrumpfException ex) {
                throw new RuntimeException("Something went really wrong! Bot not set a Trumpf.");
            }

        }
    }

    /**
     * Adds a player on a specified place in the game.
     *
     * @param player
     * @param place
     * @throws PlayerAlreadyInGameException
     * @throws PlaceTakenException
     * @throws PlaceDoesNotExistException
     */
    public void addPlayer(IPlayer player, int place) throws PlayerAlreadyInGameException, PlaceTakenException, PlaceDoesNotExistException {
        this.players.addPlayer(place, player);
        player.setPlace(place);
    }

    /**
     * @return the table of the game
     */
    public Table getTable() {
        return this.table;
    }

    /**
     * Verifies if a specified player is in the game.
     *
     * @param player
     * @return true if player is in the game, otherwise false
     */
    public boolean hasPlayer(Player player) {
        return this.players.contains(player);
    }

    /**
     * @return the players in the game
     */
    public List<IPlayer> getPlayers() {
        return Collections.unmodifiableList(this.players);
    }

    /**
     * @return the game admin
     */
    public IPlayer getAdmin() {
        return this.gameAdmin;
    }

    /**
     * @return the rule object with the game logic
     */
    public IRule getRule() {
        return this.rule;
    }

    /**
     * @return the current player
     */
    public IPlayer getCurrentPlayer() {
        return this.players.getCurrent();
    }

    /**
     * Change the turn to the next player.
     *
     * @throws GameOverException
     */
    private void nextPlayer() throws GameOverException {
        if (this.table.getSize() < this.rule.getNumberOfTableCards()) {
            this.players.next();
        } else {
            IPlayer turnWinner = this.getTurnWinner();
            this.players.setCurrent(turnWinner);
            this.clearTable();
            if (!this.players.getCurrent().hasCards()) {
                this.players.setCurrent(this.rule.getStarter());
                this.rule.setStarter(this.players.next());
                this.evaluatePoints(turnWinner);
                this.initNewRound();
            }
        }
    }

    /**
     * Verifies if the game has a winner.
     *
     * @return true if the game has a winner, otherwise false
     * @throws GameOverException
     */
    public boolean hasWinner() throws GameOverException {
        if (this.gameFinished) {
            if (this.started) {
                this.winnerList = this.rule.getWinner(this.teams);
            }
            throw new GameOverException("GameOver");
        } else if (this.rule.hasWinner(this.teams)) {
            this.gameFinished = true;
        }
        return this.rule.hasWinner(this.teams);
    }

    /**
     * Evaluates the points of each player and adds the points to the teams.
     */
    private void evaluatePoints(IPlayer turnWinner) {
       
        turnWinner.lastTrick(this.rule);
       
        for (IPlayer player : this.players) {
            player.evaluateWinnerStock(this.rule);
        }

        int[] points = this.rule.countPoints(this.teams);

        for (int[] pastPoints : this.teamPoints) {
            for (int i = 0; i < points.length; i++) {
                points[i] = points[i] - pastPoints[i];
            }
        }
        this.teamPoints.add(points);
    }

    /**
     * @return the winner of a turn
     */
    private IPlayer getTurnWinner() {
        return this.rule.winnerCard(this.table).getHolder();
    }

    /**
     * Clears the table an prepares it for a next round.
     */
    private void clearTable() {
        this.players.getCurrent().addToWinnerStock(this.table.getTableCards());
        for (Card card : this.table.clearTable()) {
            card.setHolder(this.players.getCurrent());
        }
    }

    /**
     * @return true if a trumpf is set, otherwise throws an exception
     * @throws NoTrumpfSetException
     */
    private boolean checkTrumpfIsSet() throws NoTrumpfSetException {
        if (this.rule.getTrumpf() == null) {
            throw new NoTrumpfSetException("No Trumpf is set!");
        }
        return true;
    }

    /**
     * Sets the trumpf for the turn
     *
     * @param trumpf
     * @param player
     * @throws YouMustNotSetTrumpfException
     */
    public void setTrumpf(CardColor trumpf, IPlayer player) throws YouMustNotSetTrumpfException {
        if (this.rule.isTrumpfMoved()) {
            if (this.getCurrentPlayer().equals(this.getTeamPlayer(player))) {
                this.rule.setTrumpf(trumpf);
            } else {
                throw new YouMustNotSetTrumpfException("You must not set the trumpf!");
            }
        } else {
            if (this.getCurrentPlayer().equals(player)) {
                this.rule.setTrumpf(trumpf);
            } else {
                throw new YouMustNotSetTrumpfException("You must not set the trumpf!");
            }
        }
    }

    /**
     * @return the trumpf color
     */
    public CardColor getTrumpf() {
        return this.rule.getTrumpf();
    }

    /**
     * Moves the responsibility, to set the trumpf, to the other team member.
     *
     * @throws YouMustNotSetTrumpfException
     */
    public void moveTrumpf() throws YouMustNotSetTrumpfException {
        this.rule.moveTrumpf();
        IPlayer teamPlayer = this.getTeamPlayer(this.players.getCurrent());
        if (teamPlayer.isAI()) {
            this.setTrumpf(teamPlayer.chooseTrumpf(), teamPlayer);
        }
    }

    /**
     * @return true if the trumpf is already moved, otherwise false
     */
    public boolean isTrumpfMoved() {
        return this.rule.isTrumpfMoved();
    }

    /**
     * @return the unique game ID
     */
    public String getGameID() {
        return this.gameID;
    }

    /**
     * Sets the unique game ID
     *
     * @param gameID
     */
    public void setGameID(String gameID) {
        this.gameID = gameID;
    }

    /**
     * @return the number of taken places
     */
    public int getPlayerCount() {
        return this.players.getNumberOfTakenPlaces();
    }

    /**
     * @return the number of allowed players in the game
     */
    public int getMaxPlayerCount() {
        return this.rule.getNumberOfPlayers();
    }

    /**
     * @return the points of each team
     */
    public List<int[]> getTeamPoints() {
        return Collections.unmodifiableList(this.teamPoints);
    }

    /**
     * @return true if the games is started, otherwise false
     */
    public boolean isStarted() {
        return this.started;
    }

    /**
     * Marks the game as started
     *
     * @param started
     */
    public void setStarted(boolean started) {
        this.started = started;
    }

    /**
     * @return the list of winners
     */
    public List<IPlayer> getWinnerList() {
        return winnerList;
    }

    /**
     * Returns other team players.
     * @param player
     * @return player
     */
    public IPlayer getTeamPlayer(IPlayer player) {
        int position = this.players.indexOf(player);
        return this.players.get((position + this.rule.getNumberOfTeams()) % this.rule.getNumberOfPlayers());
    }
   
    /**
     * Force to finish the game.
     */
    public void forceGameEnd() {
        this.gameFinished = true;
        this.table.clearTable();
        for (IPlayer player : this.players) {
            if (player != null) {
                player.clearHand();
            }
        }
    }
    /**
     * Verifies if the game is finished.
     * @return true if the game is finished, otherwise false
     */
    public boolean isFinished() {
        return this.gameFinished;
    }
}
TOP

Related Classes of ch.bfh.jass.game.Game

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.