/* Copyright (C) 2010 - 2011 Fabian Neundorf, Philip Caroli, * Maximilian Madlung, Usman Ghani Ahmed, Jeremias Mechler * * 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 org.ojim.server; import java.rmi.RemoteException; import java.util.LinkedList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.ojim.client.SimpleClient.AuctionState; import org.ojim.client.ai.AIClient; import org.ojim.iface.IClient; import org.ojim.iface.Rules; import org.ojim.log.OJIMLogger; import org.ojim.logic.ServerLogic; import org.ojim.logic.actions.ActionFactory; import org.ojim.logic.actions.ActionPayForBuildings; import org.ojim.logic.actions.ActionTransferMoneyToPlayers; import org.ojim.logic.rules.GameRules; import org.ojim.logic.state.ServerAuction; import org.ojim.logic.state.Card; import org.ojim.logic.state.CardStack; import org.ojim.logic.state.GetOutOfJailCard; import org.ojim.logic.state.Player; import org.ojim.logic.state.ServerGameState; import org.ojim.logic.state.ServerPlayer; import org.ojim.logic.state.Trade; import org.ojim.logic.state.fields.BuyableField; import org.ojim.logic.state.fields.CardField; import org.ojim.logic.state.fields.Field; import org.ojim.logic.state.fields.FieldGroup; import org.ojim.logic.state.fields.FreeParking; import org.ojim.logic.state.fields.GoField; import org.ojim.logic.state.fields.GoToJail; import org.ojim.logic.state.fields.InfrastructureField; import org.ojim.logic.state.fields.InfrastructureFieldGroup; import org.ojim.logic.state.fields.Jail; import org.ojim.logic.state.fields.Station; import org.ojim.logic.state.fields.StationFieldGroup; import org.ojim.logic.state.fields.Street; import org.ojim.logic.state.fields.StreetFieldGroup; import org.ojim.logic.state.fields.TaxField; import org.ojim.rmi.server.ImplNetOjim; import org.ojim.rmi.server.StartNetOjim; import edu.kit.iti.pse.iface.IServer; import edu.kit.iti.pse.iface.IServerAuction; import edu.kit.iti.pse.iface.IServerTrade; /** * * @author Philip * */ public class OjimServer implements IServer, IServerAuction, IServerTrade { private int round; private int maxRound; /** * The name of the Server */ private String name; /** * Can Clients connect to the server? */ private boolean isOpen = false; /** * Is the Game started? */ private boolean gameStarted; /** * The amount of connected Clients */ private int connectedClients; /** * The amount of Clients that can be connected */ private int maxClients; /** * All connected Clients */ private List<IClient> clients; /** * The GameState */ private ServerGameState state; /** * The Logic */ private ServerLogic logic; /** * The Rules */ private GameRules rules; /** * GameCards that need to be accepted/declined */ private List<Card> currentCards; /** * current Auction, if null => no Auction */ private ServerAuction auction; /** * current Trade, if null => no Trade */ private Trade trade; /** * List of all AI-Clients */ private AIClient aiClients[]; /** * the Logger TODO private? */ Logger logger; private boolean initComplete = false; /** * Creates a new Server. Has to be opened by initGame * * @param name * The name of the Server */ public OjimServer(String name) { this.name = name; this.gameStarted = false; this.currentCards = new LinkedList<Card>(); // AI added for AI this.state = new ServerGameState(); this.rules = new GameRules(this.state, new Rules()); this.logic = new ServerLogic(this.state, this.rules); this.logger = OJIMLogger.getLogger(this.getClass().toString()); this.maxRound = 0; } public void setMaxRound(int maxRound) { this.maxRound = maxRound; } @SuppressWarnings("unused") public synchronized boolean initRMIGame(int playerCount, int aiCount, String host) { StartNetOjim starter = new StartNetOjim(); StartNetOjim start = new StartNetOjim(); ImplNetOjim netServer = null; try { netServer = new ImplNetOjim(this); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } start.startServer(1099, host, netServer); return this.initGame(playerCount, aiCount); } /** * Initializes the Server and opens it * * @param playerCount * maximum Player (AI and GUI) count * @param aiCount * Amount of AI-Players * @return successful? */ public synchronized boolean initGame(int playerCount, int aiCount) { this.initComplete = false; if (isOpen) { return false; } // Make sure no negative numbers appear and there are players at all if (playerCount < 2 || aiCount < 0 || aiCount > playerCount) { return false; } // Init the GameFields Field[] fields = new Field[this.logic.getGameState() .getNumberOfFields()]; this.loadDefaultGameStateFields(fields); for (Field field : fields) { this.logic.getGameState().setFieldAt(field, field.getPosition()); } this.connectedClients = 0; this.maxClients = playerCount; clients = new LinkedList<IClient>(); aiClients = new AIClient[aiCount]; // AI Add AIClients to the Game for (int i = 0; i < aiCount; i++) { // AI changed aiClients[i] = new AIClient(this); logger.log(Level.CONFIG, "AI Client " + i + " added!"); aiClients[i].setReady(); } // AI added logger.log(Level.CONFIG, "All AI clients added"); // Open the Game isOpen = true; initComplete = true; this.round = 0; if(aiCount == playerCount) { ServerAuction.setTimeDelay(1); } if (checkAllPlayersReady()) { this.startGame(); } /* * if (playerCount == aiCount) { while (!state.getGameIsWon()) { try { * wait(300); } catch (InterruptedException e) { // TODO Auto-generated * catch block e.printStackTrace(); } } } */ return true; } /** * Ends a Game and prepares the Server for the next Game * * @return successful? */ public synchronized boolean endGame() { // Stops the Game this.gameStarted = false; if (!this.isOpen) { return true; } for(Player player : this.state.getPlayers()) { ((ServerPlayer)player).getClient().informGameOver(this.state.getActivePlayer().getId()); } // Closing the Game isOpen = false; gameStarted = false; this.logic.endGame(); // Disconnecting all Clients while (clients.size() > 0) { IClient client = clients.get(0); disconnect(client); client = null; } this.clients = null; // Setting the Fields to the Standard Values this.connectedClients = 0; this.maxClients = 0; return true; } /** * Disconnects a Client from the Game * * @param client * The Client to disconnect */ private synchronized void disconnect(IClient client) { assert client != null; for (IClient oneClient : this.clients) { // TODO Add Language oneClient.informPlayerLeft(getIdOfClient(client)); oneClient.informMessage("Client has been disconnected!", -1, false); } state.getPlayerById(getIdOfClient(client)).setBankrupt(); this.clients.remove(client); client = null; } private synchronized int getIdOfClient(IClient client) { assert client != null; for (Player player : state.getPlayers()) { assert player instanceof ServerPlayer; if (((ServerPlayer) player).getClient().equals(client)) { return player.getId(); } } return -1; } /** * Displays a String currently on the Console * * @param string * String to display */ private void display(String string) { System.out.println(string); } @Override public synchronized boolean initTrade(int actingPlayer, int partnerPlayer) { // If there is already a Trade in process, dont create a new one display("initializing trade between " + actingPlayer + " and " + partnerPlayer); if (state.getGameIsWon()) { return false; } if (trade != null) { if (trade.getTradeState() < 2) { return false; } } ServerPlayer acting = state.getPlayerById(actingPlayer); ServerPlayer partner = state.getPlayerById(partnerPlayer); if(acting == null || acting != this.state.getActivePlayer()){ return false; } //Trade with bank if (partnerPlayer == -1) { trade = new Trade(acting, state.getBank(), rules); return true; } //Trade with player if (partner != null) { trade = new Trade(acting, partner); return true; } return false; } @Override public synchronized int getTradeState() { if (trade != null) { return trade.getTradeState(); } return -1; } @Override public synchronized int getPartner() { if (trade != null && trade.getPartner() != null) { return trade.getPartner().getId(); } return -1; } @Override public synchronized boolean offerCash(int playerID, int amount) { if (state.getGameIsWon()) { return false; } Player player = state.getPlayerById(playerID); if (trade != null && trade.getTradeState() == 0 && player != null && player.equals(trade.getActing())) { trade.setOfferedCash(amount); return true; } return false; } @Override public synchronized boolean offerGetOutOfJailCard(int playerID) { if (state.getGameIsWon()) { return false; } Player player = state.getPlayerById(playerID); if (trade != null && trade.getTradeState() == 0 && player != null && player.equals(trade.getActing())) { trade.setOfferedNumberOfGetOutOfJailCards(trade .getOfferedNumberOfGetOutOfJailCards() + 1); return true; } return false; } @Override public synchronized boolean offerEstate(int playerID, int position) { if (state.getGameIsWon()) { return false; } Player player = state.getPlayerById(playerID); Field field = state.getFieldAt(position); if (trade != null && trade.getTradeState() == 0 && player != null && player.equals(trade.getActing()) && field != null && field instanceof BuyableField && (!(field instanceof Street) || ((Street) field) .getBuiltLevel() == 0)) { return trade.addOfferedEstate((BuyableField) field); } return false; } @Override public synchronized boolean requireCash(int playerID, int amount) { if (state.getGameIsWon()) { return false; } Player player = state.getPlayerById(playerID); if (trade != null && trade.getTradeState() == 0 && player != null && player.equals(trade.getActing())) { trade.setRequiredCash(amount); return true; } return false; } @Override public synchronized boolean requireGetOutOfJailCard(int playerID) { if (state.getGameIsWon()) { return false; } Player player = state.getPlayerById(playerID); if (trade != null && trade.getTradeState() == 0 && player != null && player.equals(trade.getActing())) { trade.setRequiredNumberOfGetOutOfJailCards(trade .getRequiredNumberOfGetOutOfJailCards() + 1); return true; } return false; } @Override public synchronized boolean requireEstate(int playerID, int position) { if (state.getGameIsWon()) { return false; } Player player = state.getPlayerById(playerID); Field field = state.getFieldAt(position); if (trade != null && trade.getTradeState() == 0 && player != null && player.equals(trade.getActing()) && field != null && field instanceof BuyableField && (!(field instanceof Street) || ((Street) field) .getBuiltLevel() == 0)) { return trade.addRequiredEstate((BuyableField) field); } return false; } @Override public synchronized int[] getOfferedEstates() { if (trade != null) { int[] out = new int[trade.getOfferedEstates().size()]; int i = 0; for (BuyableField field : trade.getOfferedEstates()) { if (i < out.length) { out[i] = field.getPosition(); i++; } } return out; } return new int[0]; } @Override public synchronized int getOfferedCash() { if (trade != null) { return trade.getOfferedCash(); } return -1; } @Override public synchronized int getNumberOfOfferedGetOutOfJailCards() { if (trade != null) { return trade.getOfferedNumberOfGetOutOfJailCards(); } return -1; } @Override public synchronized int[] getRequiredEstates() { if (trade != null) { int[] out = new int[trade.getRequiredEstates().size()]; int i = 0; for (BuyableField field : trade.getRequiredEstates()) { if (i < out.length) { out[i] = field.getPosition(); i++; } } return out; } return new int[0]; } @Override public synchronized int getRequiredCash() { if (trade != null) { return trade.getRequiredCash(); } return -1; } @Override public synchronized int getNumberOfRequiredGetOutOfJailCards() { if (trade != null) { return trade.getRequiredNumberOfGetOutOfJailCards(); } return -1; } @Override public synchronized boolean cancelTrade(int playerID) { display("trade canceled by " + playerID); if (state.getGameIsWon()) { return false; } ServerPlayer player = state.getPlayerById(playerID); if (trade != null && trade.getTradeState() == 0 && player != null && player.equals(trade.getActing())) { trade = null; return true; } return false; } @Override public synchronized boolean proposeTrade(int playerID) { display("trade proposed by " + playerID); if (state.getGameIsWon()) { return false; } ServerPlayer player = state.getPlayerById(playerID); if (trade != null && trade.getTradeState() == 0 && player != null && player.equals(trade.getActing())) { trade.setTradeState(1); if (trade.getPartner() != null) { trade.getPartner().getClient().informTrade(); return true; } else { trade.setTradeState(3); trade.executeTrade(logic); } } return false; } @Override public synchronized int getAuctionState() { if (auction != null) { return auction.getState().value; } return AuctionState.NOT_RUNNING.value; } @Override public synchronized int getAuctionedEstate() { if (auction != null) { return auction.objective.getPosition(); } return 0; } @Override public synchronized int getHighestBid() { if (auction != null) { return auction.getHighestBid(); } return -1; } @Override public synchronized int getBidder() { if (auction != null) { if (auction.getHighestBidder() != null) { return auction.getHighestBidder().getId(); } } return -1; } @Override public synchronized boolean placeBid(int playerID, int amount) { if (state.getGameIsWon()) { return false; } Player player = state.getPlayerById(playerID); if (auction != null && player != null && !player.getIsBankrupt()) { return auction.placeBid(player, amount); } return false; } @Override public synchronized int getPlayerPiecePosition(int playerID) { Player player = state.getPlayerById(playerID); if (player == null) { return -1; } return player.getPosition(); } /** * Adds a GameCard that needs accepting/declining * * @param card * the Card to add */ public synchronized void addCurrentCard(Card card) { if (state.getGameIsWon()) { return; } this.currentCards.add(card); } /** * Gets all GameCards that need accepting/declining * * @return List of Cards that need accept()/decline() */ public synchronized List<Card> getCurrentCards() { return this.currentCards; } @Override public synchronized int addPlayer(IClient client) { for (int i = 0; i < maxClients; i++) { if (state.getPlayerById(i) == null) { this.clients.add(client); Player newPlayer = new ServerPlayer(client.getName(), 0, state.getRules().startMoney, i, i, client); state.setPlayer(newPlayer); this.connectedClients++; client.informCashChange(newPlayer.getId(), newPlayer.getBalance()); // Inform all Players except the new one that a new Player is // there for (Player player : state.getPlayers()) { if (!player.equals(newPlayer)) { ((ServerPlayer) player).getClient().informNewPlayer(i); ((ServerPlayer) player).getClient().informCashChange(newPlayer.getId(), newPlayer.getBalance()); client.informNewPlayer(player.getId()); } } return i; } } return -1; } @Override public synchronized void setPlayerReady(int playerID) { // AI added assert (state != null); if (state.getPlayerById(playerID) == null) { return; } state.getPlayerById(playerID).setIsReady(true); // AI added logger.log(Level.INFO, "Number of connected players = " + connectedClients); // Are all players Ready? then start the game if (checkAllPlayersReady()) { // If all (non-AI) Players are ready, start the Game startGame(); } } private synchronized boolean checkAllPlayersReady() { if (this.connectedClients == this.maxClients && initComplete) { for (Player player : state.getPlayers()) { // Check if the Player is ready if (!player.getIsReady()) { // AI Clients don't need to be set to ready if (player instanceof ServerPlayer && !(((ServerPlayer) player).getClient() instanceof AIClient)) { return false; } } } return true; } else { return false; } } /** * Starts a Game */ private synchronized void startGame() { this.gameStarted = true; logic.startGame(); } @Override public synchronized String getPlayerName(int playerID) { Player player = state.getPlayerById(playerID); if (player != null) { String name = player.getName(); if (name == null || name == "") { name = "Player" + player.getId(); if (player instanceof ServerPlayer) { name = ((ServerPlayer) player).getName(); } } return name; } return ""; } @Override public synchronized int getPlayerColor(int playerID) { Player player = state.getPlayerById(playerID); if (player != null) { return player.getColor(); } return -1; } @Override public synchronized Rules getRules() { if (this.state.getRules() != null) { return state.getRules(); } return null; } @Override public synchronized String getEstateName(int position, int player) { Field field = state.getFieldAt(position); String name = ""; if (field != null) { name = field.getName(); if (field instanceof Street) { name = ((Street) field).getFieldGroup().getName() + ": " + name; } } return name; } @Override public synchronized int getEstateColorGroup(int position) { Field field = state.getFieldAt(position); if (field != null) { return field.getFieldGroup().getColor(); } return 0; } @Override public synchronized int getEstateHouses(int position) { Field field = state.getFieldAt(position); if (field != null && field instanceof Street) { return ((Street) field).getBuiltLevel(); } return -1; } @Override public synchronized int getEstatePrice(int position) { Field field = state.getFieldAt(position); if (field != null && field instanceof BuyableField) { return ((BuyableField) field).getPrice(); } return -1; } @Override public synchronized int getEstateRent(int position, int houses) { Field field = state.getFieldAt(position); if (field != null && field instanceof Street) { return ((Street) field).getRent(houses); } else if (field != null && field instanceof BuyableField) { return ((BuyableField) field).getRent(); } return -1; } @Override public synchronized boolean isMortgaged(int position) { Field field = state.getFieldAt(position); if (field != null && field instanceof BuyableField) { return ((BuyableField) field).isMortgaged(); } return false; } @Override public synchronized int getOwner(int position) { Field field = state.getFieldAt(position); if (field != null && field instanceof BuyableField) { Player owner = ((BuyableField) field).getOwner(); if (owner != null) { return owner.getId(); } } return -1; } @Override public synchronized int getDiceValue() { return state.getDices().getResultSum(); } @Override public synchronized int[] getDiceValues() { return state.getDices().getResult(); } @Override public synchronized int getPlayerCash(int playerID) { Player player = state.getPlayerById(playerID); if (player != null) { return player.getBalance(); } return -1; } @Override public synchronized int getPlayerOnTurn() { if (state.getActivePlayer() != null) { return state.getActivePlayer().getId(); } return -1; } @Override public synchronized int getNumberOfGetOutOfJailCards(int playerID) { Player player = this.state.getPlayerById(playerID); if (player != null) { return player.getNumberOfGetOutOfJailCards(); } return -1; } @Override public synchronized int getNumberOfHousesLeft() { return state.getBank().getHouses(); } public boolean isGameRunning() { return this.state.getGameIsWon(); } @Override public synchronized int getNumberOfHotelsLeft() { return state.getBank().getHotels(); } /** * How many doubles were there in this turn? */ private int doublesChain = 0; private boolean playerNeedsAcceptCancel; @Override public synchronized boolean rollDice(int playerID) { display(playerID + " wants to roll!"); ServerPlayer player = this.state.getPlayerById(playerID); if (player == null || !rules.isPlayerOnTurn(player) || this.gameStarted == false || !this.rules.isRollRequiredByActivePlayer() || this.state.getGameIsWon() || this.playerNeedsAcceptCancel) { return false; } if (player.getJail() != null) { display("he is in jail"); // Roll and Inform everyone state.getDices().roll(); informDiceAll(); // Player has not rolled a Double and stays in jail if (!state.getDices().isDouble()) { state.setActivePlayerNeedsToRoll(false); return true; } else { // Get the Player out of Jail logic.playerRolledOutOfJail(player); // Inform all that the Player is now out of Prison (position // > -1) informMoveAll(player); } } display("He is now rolling"); // Roll and Inform everyone state.getDices().roll(); informDiceAll(); display("He has rolled"); // If the Player has not rolled a double, stop rolling if (!state.getDices().isDouble()) { state.setActivePlayerNeedsToRoll(false); } else { doublesChain++; if (doublesChain >= GameRules.MAX_DOUBLES_ALLOWED) { // Player has to get to jail logic.sendPlayerToJail(player, state.getDefaultJail()); return true; } } display("he is moving"); // Now move the Player forward logic.movePlayerForDice(player, state.getDices().getResultSum()); // Is the Field the Player is standing on buyable? Field field = state.getFieldAt(player.getPosition()); if (field instanceof BuyableField && ((BuyableField) field).getOwner() == null) { playerNeedsAcceptCancel = true; player.getClient().informBuyEvent(player.getId(), player.getPosition()); } else { for(Player onePlayer : this.state.getPlayers()) { ((ServerPlayer)onePlayer).getClient().informCanEndTurn(this.state.getActivePlayer().getId()); } } return true; } /** * Informs all Clients that the Dice has been rolled */ private synchronized void informDiceAll() { for (IClient client : clients) { client.informDiceValues(state.getDices().getResult()); } } /** * Inform all Clients that a move has occured * * @param player * the moving Player */ private synchronized void informMoveAll(Player player) { for (IClient client : clients) { client.informMove(player.getId(), player.getSignedPosition()); } } @Override public synchronized boolean accept(int playerID) { display("accepting"); ServerPlayer player = state.getPlayerById(playerID); // Does a Trade need Confirmation? if (trade != null && player != null && trade.getTradeState() == 1 && player.equals(trade.getPartner())) { display("trade accepted by " + playerID); trade.setTradeState(3); trade.executeTrade(logic); ((ServerPlayer) trade.getActing()).getClient().informTrade(); } if (state.getGameIsWon() || playerID != state.getActivePlayer().getId()) { return false; } if (player == null || !rules.isPlayerOnTurn(player)) { return false; } // First check if a Action needs Confirmation Card card = state.getFirstWaitingCard(); if (card != null) { card.accept(); state.RemoveWaitingCard(card); return true; } Field field = state.getFieldAt(player.getPosition()); if (playerNeedsAcceptCancel && player.getBalance() > ((BuyableField) field).getPrice()) { logic.buyStreet(); playerNeedsAcceptCancel = false; for(Player onePlayer : this.state.getPlayers()) { ((ServerPlayer)onePlayer).getClient().informCanEndTurn(this.state.getActivePlayer().getId()); } return true; } return false; } @Override public synchronized boolean decline(int playerID) { display("decline"); if (state.getGameIsWon()) { System.out.println("Game is won"); return false; } ServerPlayer player = state.getPlayerById(playerID); if (trade != null && player != null && trade.getTradeState() == 1 && player.equals(trade.getPartner())) { System.out.println("trade declined by " + playerID); trade.setTradeState(2); ((ServerPlayer) trade.getActing()).getClient().informTrade(); } if (player == null || playerID != state.getActivePlayer().getId()) { return false; } // First check if a Action needs Confirmation Card card = state.getFirstWaitingCard(); if (card != null) { card.decline(); state.RemoveWaitingCard(card); return true; } // Check if the Buying of a field was declined if (playerNeedsAcceptCancel) { if (!(state.getFieldAt(state.getActivePlayer().getPosition()) instanceof BuyableField)) { } this.auction = new ServerAuction(state, logic, rules, (BuyableField) state.getFieldAt(state.getActivePlayer() .getPosition())); this.auction.setReturnParameters(this, state.getActivePlayer() .getId()); // Do inform here, because before "this.auction" is not initalized! this.auction.informPlayers(); this.playerNeedsAcceptCancel = false; } return false; } @Override public synchronized boolean endTurn(int playerID) { Player player = state.getPlayerById(playerID); //TODO: (xZise → Vikath) Allow endTurn if Trade is ACCEPTED/DECLINED? // Before it was only possible to end a turn, of the state is negative. // BUT you never set the state of the trade to a negative value. if(this.getTradeState() == 0 || this.getTradeState() == 1) { return false; } if (player != null && rules.isPlayerOnTurn(player) && !state.getGameIsWon()) { if (player.getJail() != null) { player.waitInJail(); } if (!rules.isRollRequiredByActivePlayer()) { // Player is bankrupt if (player.getBalance() < 0) { this.logic.setPlayerBankrupt(player); } // Is there an Auction running? if (this.auction != null && this.auction.getState() != AuctionState.THIRD) { return false; } // does the Player have to accept/cancel to buy a field? if (playerNeedsAcceptCancel) { display("auction needs to be started"); return false; } if (this.state.getGameIsWon()) { this.endGame(); return true; } tries = 0; this.doublesChain = 0; this.round++; System.out.println(this.name + "|" + round); if(round == maxRound) { logger.log(Level.INFO, "Game ended because maxRounds was reached"); this.endGame(); } logic.startNewTurn(); return true; } else { ((ServerPlayer) player).getClient().informTurn(player.getId()); } } return false; } @Override public synchronized boolean declareBankruptcy(int playerID) { if (state.getGameIsWon()) { return false; } Player player = state.getPlayerById(playerID); if (player != null) { this.logic.setPlayerBankrupt(player); return true; } return false; } @Override public synchronized boolean construct(int playerID, int position) { if (state.getGameIsWon()) { return false; } if (changeLevel(playerID, position, 1)) { for (IClient client : clients) { client.informConstruct(position); } return true; } return false; } /** * Changes the BuiltLevel of a Field * * @param playerID * the Player that want to change * @param position * The Position of the Field * @param levelChange * the levelChange * @return */ private boolean changeLevel(int playerID, int position, int levelChange) { Player player = state.getPlayerById(playerID); Field field = state.getFieldAt(position); if (player != null) { if (field != null) { if (rules.isFieldUpgradable(player, field, levelChange)) { if (levelChange > 0) { if ((this.getNumberOfHousesLeft() <= 0 && ((Street) field) .getBuiltLevel() + levelChange < getRules().maxNumOfHouses) || (this.getNumberOfHotelsLeft() <= 0 && ((Street) field) .getBuiltLevel() + levelChange >= getRules().maxNumOfHouses)) { return false; } } int level = ((Street) field).getBuiltLevel(); if (level + levelChange < getRules().maxNumOfHouses && level < getRules().maxNumOfHouses) { state.getBank().changeHouses(-levelChange); } else if (level + levelChange >= getRules().maxNumOfHouses) { state.getBank().changeHotels(-1); state.getBank().changeHouses(level); } else if (level + levelChange < getRules().maxNumOfHouses && level >= getRules().maxNumOfHouses) { state.getBank().changeHotels(1); state.getBank().changeHouses(level - 1 - levelChange); } logic.upgrade((Street) field, levelChange); logic.exchangeMoney(player, state.getBank(), ((Street) field).getFieldGroup().getHousePrice() * levelChange); return true; } } } return false; } @Override public synchronized boolean deconstruct(int playerID, int position) { if (state.getGameIsWon()) { return false; } if (changeLevel(playerID, position, -1)) { for (IClient client : clients) { client.informDestruct(position); } return true; } return false; } @Override public synchronized boolean toggleMortgage(int playerID, int position) { if (state.getGameIsWon()) { return false; } Player player = state.getPlayerById(playerID); Field field = state.getFieldAt(position); if (player != null) { if (field != null) { if (rules.isFieldMortgageable(player, field)) { logic.toggleMortgage((BuyableField) field); return true; } } } return false; } @Override public synchronized void sendMessage(String text, int sender) { for (IClient client : this.clients) { client.informMessage(text, sender, false); } } @Override public synchronized void sendPrivateMessage(String text, int sender, int reciever) { if (reciever >= 0 && reciever < this.connectedClients) { Player player = state.getPlayerById(reciever); if (player != null && player instanceof ServerPlayer) { ((ServerPlayer) player).getClient().informMessage(text, sender, true); } } } /** * Gets the Name of the Server * * @return Servername */ public synchronized String getName() { return this.name; } /** * Gets the number of Clients that can connect * * @return maximum Clientconnections */ public synchronized int getMaxClients() { return this.maxClients; } public synchronized int getConnectedClients() { return this.connectedClients; } @Override public synchronized int getTurnsInPrison(int playerID) { Player player = state.getPlayerById(playerID); if (player != null) { if (this.rules.isPlayerInPrison(player)) { return player.getJail().getRoundsToWait(); } else { return 0; } } return -1; } @Override public synchronized boolean useGetOutOfJailCard(int playerID) { if (state.getGameIsWon()) { return false; } ServerPlayer player = state.getPlayerById(playerID); if (player != null && rules.isPlayerInPrison(player)) { if (rules.canPlayerGetOutOfJail(player, true)) { logic.playerUsesGetOutOfJailCard(player); return true; } } return false; } public synchronized List<IClient> getClients() { return this.clients; } private int tries = 0; @Override public synchronized boolean payFine(int playerID) { display("Player tries to use fine to get out of jail!"); if (state.getGameIsWon()) { return false; } tries++; if(tries >= 10) { this.endTurn(playerID); } Player player = state.getPlayerById(playerID); System.out.println("player is on field " + player.getSignedPosition()); if (player != null && rules.isPlayerInPrison(player)) { System.out.println("player is valid!"); if (player.getBalance() >= player.getJail().getMoneyToPay()) { logic.playerUsesFineForJail(player); System.out.println("player is then on field " + player.getSignedPosition()); display("Player has used fine to get out of jail!"); return true; } } return true; } public int getMaximumBuiltLevel() { return 5; } @Override public synchronized int getEstateHousePrice(int position) { Field field = state.getFieldAt(position); if (field != null && field instanceof Street) { StreetFieldGroup group = ((Street) field).getFieldGroup(); if (group != null) { return group.getHousePrice(); } } return -1; } /** * Returns the money the player has to pay to leave the jail. * * @param position * The position of the jail. * @return The money the player has to pay. If there is no money the return * is undefined;. */ public synchronized int getMoneyToPay(int position) { Field field = state.getFieldAt(position); if (field != null && field instanceof Jail) { return ((Jail) field).getMoneyToPay(); } return -1; } /** * Returns the number of rounds the player has to wait if the player is in * jail. * * @param position * The position of the jail. * @return The number of rounds the player has to wait. If this is no jail * it return is undefined. */ public synchronized int getRoundsToWait(int position) { Field field = state.getFieldAt(position); if (field != null && field instanceof Jail) { return ((Jail) field).getRoundsToWait(); } return -1; } private synchronized Field newEventCardField(int position, FieldGroup group) { return group.addField(new CardField("Ereignis- karte", position, false, this.logic)); } private synchronized Field newCommunityCardField(int position, FieldGroup group) { return group.addField(new CardField("Gemein- schafts- karte", position, true, this.logic)); } private void loadDefaultGameStateFields(Field[] fields) { // Initialise field groups StationFieldGroup stations = new StationFieldGroup(); StreetFieldGroup[] streets = new StreetFieldGroup[8]; streets[0] = new StreetFieldGroup(0, "Dagobah", 1000); streets[1] = new StreetFieldGroup(1, "Hoth", 1000); streets[2] = new StreetFieldGroup(2, "Tatooine", 2000); streets[3] = new StreetFieldGroup(3, "Yavin Vier", 2000); streets[4] = new StreetFieldGroup(4, "Wolkenstadt", 3000); streets[5] = new StreetFieldGroup(5, "Todesstern", 3000); streets[6] = new StreetFieldGroup(6, "Endor", 4000); streets[7] = new StreetFieldGroup(7, "Coruscant", 4000); InfrastructureFieldGroup infrastructures = new InfrastructureFieldGroup(); FieldGroup taxGroups = new FieldGroup(FieldGroup.TAX); FieldGroup go = new FieldGroup(FieldGroup.GO); FieldGroup communityCards = new FieldGroup(FieldGroup.COMMUNITY); FieldGroup eventCards = new FieldGroup(FieldGroup.EVENT); FieldGroup jails = new FieldGroup(FieldGroup.JAIL); FieldGroup freeParkings = new FieldGroup(FieldGroup.FREE_PARKING); FieldGroup goToJail = new FieldGroup(FieldGroup.GO_TO_JAIL); FreeParking freeParking; // Add Streets fields[0] = go.addField(new GoField("Los", 0, this.logic)); fields[1] = streets[0].addField(new Street("Sumpf", 1, new int[] { 40, 200, 600, 1800, 3200, 5000 }, 0, 1200, logic)); fields[2] = this.newEventCardField(2, eventCards); fields[3] = streets[0].addField(new Street("Jodas Hütte", 3, new int[] { 80, 400, 1200, 3600, 6400, 9000 }, 0, 1200, logic)); fields[4] = taxGroups.addField(new TaxField("Landungs- steuer", 4, 4000, this.logic)); fields[5] = stations.addField(new Station("TIE-Fighter", 5, 4000)); fields[6] = streets[1].addField(new Street("Echo-Basis", 6, new int[] { 120, 600, 1800, 5400, 8000, 11000 }, 0, 2000, logic)); fields[7] = this.newCommunityCardField(7, communityCards); fields[8] = streets[1].addField(new Street("Eis-Steppen", 8, new int[] { 120, 600, 1800, 5400, 8000, 11000 }, 0, 2000, logic)); fields[9] = streets[1].addField(new Street("Nordgebirge", 9, new int[] { 160, 800, 2000, 6000, 9000, 12000 }, 0, 2400, logic)); fields[10] = jails.addField(new Jail("Gefängnis", 10, 1000, 3)); fields[11] = streets[2].addField(new Street("Lars Heimstatt", 11, new int[] { 200, 1000, 3000, 9000, 12500, 15000 }, 0, 2800, logic)); fields[12] = infrastructures.addField(new InfrastructureField( "Kern-Reaktor", 12, 3000, this.logic)); fields[13] = streets[2].addField(new Street("Mos Eisley", 13, new int[] { 200, 1000, 3000, 9000, 12500, 15000 }, 0, 2800, logic)); fields[14] = streets[2].addField(new Street("Jabbas Palast", 14, new int[] { 240, 1200, 3600, 10000, 14000, 18000 }, 0, 3200, logic)); fields[15] = stations.addField(new Station("Millenium Falke", 15, 4000, this.logic)); fields[16] = streets[3].addField(new Street("Kommandozentrale", 16, new int[] { 280, 1400, 4000, 11000, 15000, 19000 }, 0, 3600, logic)); fields[17] = this.newEventCardField(17, eventCards); fields[18] = streets[3].addField(new Street("Massassi Tempel", 18, new int[] { 280, 1400, 4000, 11000, 15000, 19000 }, 0, 3600, logic)); fields[19] = streets[3].addField(new Street("Tempel-Thronsaal", 19, new int[] { 320, 1600, 4400, 12000, 16000, 20000 }, 0, 4000, logic)); freeParking = new FreeParking("Frei Parken", 20, this.logic); fields[20] = freeParkings.addField(freeParking); fields[21] = streets[4].addField(new Street("Andockbucht", 21, new int[] { 360, 1800, 5000, 14000, 17500, 21000 }, 0, 4400, logic)); fields[22] = this.newCommunityCardField(22, communityCards); fields[23] = streets[4].addField(new Street("Karbon- Gefrierkammer", 23, new int[] { 360, 1800, 5000, 14000, 17500, 21000 }, 0, 4400, logic)); fields[24] = streets[4].addField(new Street("Reaktor- Kontrollraum", 24, new int[] { 400, 2000, 6000, 15000, 18500, 22000 }, 0, 4800, logic)); fields[25] = stations.addField(new Station("X-Wing Fighter", 25, 4000, this.logic)); fields[26] = streets[5].addField(new Street("Lande-Deck", 26, new int[] { 440, 2200, 6600, 16000, 19500, 23000 }, 0, 5200, logic)); fields[27] = streets[5].addField(new Street("Thronsaal", 27, new int[] { 440, 2200, 6600, 16000, 19500, 23000 }, 0, 5200, logic)); fields[28] = infrastructures.addField(new InfrastructureField( "Wasser- Farm", 28, 3000, this.logic)); fields[29] = streets[5].addField(new Street("Hauptreaktor", 29, new int[] { 480, 2400, 7200, 17000, 20500, 24000 }, 0, 5600, logic)); fields[30] = goToJail.addField(new GoToJail("Gehe ins Gefängnis", 30, this.logic, (Jail) fields[10])); // Fabians Strange gelbe Karte wurde hiermit hoch offiziell von Max // entfernt! // fields[30] = streets[5].addField(new Street("foobar", 30, new int[] { // 480, 2400, 7200, 17000, 20500, 240()00 }, 0, 5600, logic)); fields[31] = streets[6].addField(new Street("Wald", 31, new int[] { 520, 2600, 7800, 18000, 22000, 25500 }, 0, 6000, logic)); fields[32] = streets[6].addField(new Street("Schildgenerator", 32, new int[] { 520, 2600, 7800, 18000, 22000, 25500 }, 0, 6000, logic)); fields[33] = this.newEventCardField(33, eventCards); fields[34] = streets[6].addField(new Street("Ewok-Dorf", 34, new int[] { 560, 3000, 9000, 20000, 24000, 28000 }, 0, 6400, logic)); fields[35] = stations .addField(new Station("Stern-Zerstörer", 35, 4000)); fields[36] = this.newCommunityCardField(36, communityCards); fields[37] = streets[7].addField(new Street("Platz des Volkes", 37, new int[] { 700, 3500, 10000, 22000, 16000, 30000 }, 0, 7000, logic)); fields[38] = taxGroups.addField(new TaxField("Kopf-Geld Prämie", 38, 2000)); fields[39] = streets[7].addField(new Street("Imperialer Palast", 39, new int[] { 1000, 4000, 12000, 28000, 34000, 40000 }, 0, 8000, logic)); stations.setRent(new int[] { 500, 1000, 2000, 4000 }); infrastructures.setFactors(new int[] { 80, 200 }); // Add Cards CardStack comm = ((ServerGameState) this.logic.getGameState()) .getCommunityCards(); for (int i = 0; i < 1000; i++) { comm.add(new GetOutOfJailCard("comm jail (" + i + ")", comm, this.logic)); } comm.add(Card.newNormalCard("comm +100 money", comm, ActionFactory.newTransferMoneyToBank(this.logic, -100))); comm.add(Card.newNormalCard("comm 100 m > free", comm, ActionFactory .newTransferMoneyToFreeParking(this.logic, 100, freeParking))); comm.add(Card.newNormalCard("comm 100 m (p. Hou) 1000 (p. Hot)", comm, new ActionPayForBuildings(this.logic, 100, 1000, this.logic .getGameState().getBank()))); comm.add(Card.newNormalCard("comm +100 m (p. Ply)", comm, new ActionTransferMoneyToPlayers(this.logic, 100))); CardStack even = ((ServerGameState) this.logic.getGameState()) .getEventCards(); for (int i = 0; i < 1000; i++) { even.add(new GetOutOfJailCard("even jail (" + i + ")", even, this.logic)); } even.add(Card.newNormalCard("even +100 money", even, ActionFactory.newTransferMoneyToBank(this.logic, -100))); even.add(Card.newNormalCard("even 100 m > free", even, ActionFactory .newTransferMoneyToFreeParking(this.logic, 100, freeParking))); even.add(Card.newNormalCard("even 100 m (p. Hou) 1000 (p. Hot)", even, new ActionPayForBuildings(this.logic, 100, 1000, this.logic .getGameState().getBank()))); even.add(Card.newNormalCard("even +100 m (p. Ply)", even, new ActionTransferMoneyToPlayers(this.logic, 100))); } // TODO remove after testing is complete public ServerGameState getGameState() { return this.state; } // TODO remove after testing is complete public ServerLogic getLogic() { return this.logic; } @Override public int getActing() { if (trade != null && trade.getPartner() != null) { return trade.getPartner().getId(); } return -1; } @Override public int getFreeParkingPot(int position) { Field f = this.getGameState().getFieldAt(position); if (f instanceof FreeParking) { return ((FreeParking) f).getMoneyInPot(); } else { return -1; } } }