/* 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.logic; import java.util.logging.Level; import java.util.logging.Logger; import org.ojim.iface.IClient; import org.ojim.log.OJIMLogger; import org.ojim.logic.accounting.Bank; import org.ojim.logic.accounting.IMoneyPartner; import org.ojim.logic.rules.GameRules; import org.ojim.logic.state.Card; 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.fields.BuyableField; import org.ojim.logic.state.fields.Field; import org.ojim.logic.state.fields.FreeParking; import org.ojim.logic.state.fields.Jail; import org.ojim.logic.state.fields.Street; /** * Acts as logic, but this class informs also the players. * * @author Fabian Neundorf */ @SuppressWarnings("serial") public class ServerLogic extends Logic { // AI private Logger logger; /** * Creates a new ServerLogic which contains Server-specific content * * @param state * The GameState on which the Logic applies * @param rules * The GameRules that apply for this Server */ public ServerLogic(ServerGameState state, GameRules rules) { super(state, rules); logger = OJIMLogger.getLogger(this.getClass().toString()); } public void setPlayerBankrupt(Player player) { player.setBankrupt(); for (BuyableField field : player.getFields()) { if (field instanceof Street) { while(((Street)field).getBuiltLevel() > 0) { this.upgrade((Street)field, -1); } } field.buy(null); } player.transferMoney(-(player.getBalance() + 1)); // Inform All Players that this Player is bankrupt for (Player onePlayer : this.getGameState().getPlayers()) { ((ServerPlayer) onePlayer).getClient().informBankruptcy(); } } int number = 0; /** * Start a new Turn in the Game */ public void startNewTurn() { // AI number++; if ((number % 1000000) == 0) logger.log(Level.INFO, "Starting new turn " + number++); // Get a new Player On Turn this.getNewPlayerOnTurn(); this.getGameState().setActivePlayerNeedsToRoll(true); int id = this.getGameState().getActivePlayer().getId(); // Inform All Player that a new Turn has come for (Player player : this.getGameState().getPlayers()) { if(player != this.getGameState().getActivePlayer()) { ((ServerPlayer) player).getClient().informTurn(id); } } ((ServerPlayer)this.getGameState().getActivePlayer()).getClient().informTurn(id); this.getGameState().setActivePlayerNeedsToRoll(true); } /** * Called when a MoneyPot of a Free-Parking-Field should be emptied * * @param field */ public void getFreeParkingMoney(FreeParking field) { this.exchangeMoney(field, this.getGameState().getActivePlayer(), field.getMoneyInPot()); } /** * Called when a Player should get into Jail * * @param player * The Player who is getting into Jail * @param jail * the specific Jail where the Player goes to */ public void sendPlayerToJail(ServerPlayer player, Jail jail) { player.sendToJail(jail); this.getGameState().setActivePlayerNeedsToRoll(false); for (Player onePlayer : this.getGameState().getPlayers()) { if (onePlayer instanceof ServerPlayer) { ((ServerPlayer) onePlayer).getClient().informMove( player.getId(), player.getSignedPosition()); // TODO Inform Players that this one is in Prison? } } } /** * Start a Game, sets the current Player and informs all Players the Game * has started */ public void startGame() { // Set a random Player to be the StartPlayer int playerCount = this.getGameState().getPlayers().length; int start = 1;//new Random().nextInt(playerCount); this.getGameState().startGame(start); int[] ids = new int[playerCount]; int i = 0; for (Player player : this.getGameState().getPlayers()) { ids[i++] = player.getId(); } // Send all Players notification that the Game has started for (Player player : this.getGameState().getPlayers()) { if (player instanceof ServerPlayer) { // AI IClient client = ((ServerPlayer) player).getClient(); client.informStartGame(ids); } } // AI added logger.log(Level.INFO, "Almost Starting new turn"); startNewTurn(); // while(!this.getGameState().getGameIsWon() && this.getGameState().getActivePlayer() != null) { // startNewTurn(); // } } /** * Exchanges Money and informs all Players if payer or payee is a Player. * * @param payer * The Player paying Money. * @param payee * The Player getting Money. * @param amount * The amount of Money. */ public void exchangeMoney(IMoneyPartner payer, IMoneyPartner payee, int amount) { Bank.exchangeMoney(payer, payee, amount); // Inform other Players that Cash has changed for (Player player : this.getGameState().getPlayers()) { if (player instanceof ServerPlayer) { IClient client = ((ServerPlayer) player).getClient(); if (payer instanceof Player) { client.informCashChange(((Player) payer).getId(), -amount); } if (payee instanceof Player) { client.informCashChange(((Player) payee).getId(), amount); } } } } /** * Called when a Player should use a GetOutOfJail-Card * * @param player * The Player using the Card */ public synchronized void playerUsesGetOutOfJailCard(ServerPlayer player) { for(int i = 0; i < player.getCards().size(); i++) { if (player.getCards().get(i) instanceof GetOutOfJailCard) { player.getCards().get(i).file(true); } } } public void toggleMortgage(BuyableField field) { super.toggleMortgage(field); this.exchangeMoney(field.getOwner(), this.getGameState().getBank(), (field.isMortgaged() ? -1 : +1) * field.getMortgagePrice()); // Inform everyone for (Player player : this.getGameState().getPlayers()) { ((ServerPlayer) player).getClient().informMortgageToogle(field.getPosition()); } } public void playerUsesFineForJail(Player player) { // Lets a Player pay money to get out of Jail this.exchangeMoney(player, this.getGameState().getBank(), player .getJail().getMoneyToPay()); this.sendPlayerOutOfJail(player); } public void sendPlayerOutOfJail(Player player) { player.sendToJail(null); // Inform all Player that the current Player is now out of Jail for (Player onePlayer : this.getGameState().getPlayers()) { if (onePlayer instanceof ServerPlayer) { // TODO Add Language //System.out.println("Player " + player.getName() + " is now out of Jail!"); ((ServerPlayer) onePlayer).getClient().informMessage( "'" + player.getName() + "' is now out of Jail!", -1, false); ((ServerPlayer) onePlayer).getClient().informMove(player.getId(), player.getSignedPosition()); } } } public void getNewPlayerOnTurn() { Player[] players = this.getGameState().getPlayers(); Player currentPlayer = this.getGameState().getActivePlayer(); for (int i = 0; i < players.length; i++) { if (players[i].equals(currentPlayer)) { for (int j = 1; j < players.length; j++) { int playerPos = (j + i) % players.length; if (players[playerPos] != null && !players[playerPos].getIsBankrupt()) { this.getGameState().setActivePlayer(players[playerPos]); this.getGameState().setActivePlayerNeedsToRoll(true); return; } } // When only 1 Player is there and he is not bankrupt, he has not won if(players.length == 1 && !players[0].getIsBankrupt()) { return; } //System.out.println("Player " + this.getGameState().getActivePlayer().getName() + " has won!"); for (Player player : this.getGameState().getPlayers()) { if (player instanceof ServerPlayer) { // TODO add language ((ServerPlayer) player).getClient().informMessage( "Player " + currentPlayer.getName() + " has won!", -1, false); } } this.getGameState().setGameIsWon(true); } } } public void playerRolledOutOfJail(Player player) { this.sendPlayerOutOfJail(player); } public void auctionWithoutResult(BuyableField objective) { //System.out.println("Action without result!"); return; } public void auctionWithResult(BuyableField objective, Player winner, int price) { changeFieldOwner(winner, objective); this.exchangeMoney(winner, this.getGameState().getBank(), price); } public void movePlayerTo(Field field, Player player, boolean secondary, boolean executePasses) { int fieldPos = field.getPosition(); int playerPos = player.getPosition(); while (playerPos != fieldPos) { playerPos = ++playerPos % this.getGameState().getNumberOfFields(); player.setPosition(playerPos); Field currentField = this.getGameState().getFieldAt(playerPos); if (executePasses) { currentField.passThrough(); } } if (field instanceof Jail && secondary) { player.sendToJail((Jail) field); } for (Player onePlayer : this.getGameState().getPlayers()) { if (onePlayer instanceof ServerPlayer) { ((ServerPlayer) onePlayer).getClient().informMove( player.getId(), player.getSignedPosition()); } } } public void payRent(Player player) { Field field = this.getGameState().getFieldAt(player.getPosition()); payRent(player, (BuyableField) field); } public void payRent(Player player, BuyableField field) { Player owner = field.getOwner(); if (owner != null && !player.equals(owner) && !field.isMortgaged()) { this.exchangeMoney(player, owner, field.getRent()); } } public void movePlayerForDice(Player player, int result) { // Do the passthrough-Action for all Fields the Player steps on int position = player.getPosition(); for (int i = 1; i < result; i++) { // Move Player 1 forward player.setPosition((position + i) % this.getGameState().getNumberOfFields()); // Do the passthrough this.getGameState() .getFieldAt( (position + i) % this.getGameState().getNumberOfFields()) .passThrough(); } player.setPosition((position + result) % this.getGameState().getNumberOfFields()); // Inform everyone that the Player has moved for (Player onePlayer : this.getGameState().getPlayers()) { if (onePlayer instanceof ServerPlayer) { ((ServerPlayer) onePlayer).getClient().informMove( player.getId(), player.getSignedPosition()); } } // Do the Execute for the Field the Player is standing on this.getGameState() .getFieldAt( (position + result) % this.getGameState().getNumberOfFields()) .execute(); } public void buyStreet() { Player player = this.getGameState().getActivePlayer(); int position = player.getPosition(); BuyableField field = (BuyableField) this.getGameState().getFieldAt( position); this.exchangeMoney(player, this.getGameState().getBank(), field.getPrice()); changeFieldOwner(player, field); } /** * Changes the owner of a field and informs all players. * @param newOwner New owner of the field. * @param field The trading field. */ public void changeFieldOwner(Player newOwner, BuyableField field) { int newOwnerId = -1; if (newOwner != null) { newOwnerId = newOwner.getId(); } field.buy(newOwner); for (Player player : this.getGameState().getPlayers()) { if (player instanceof ServerPlayer) { ((ServerPlayer) player).getClient().informBuy(newOwnerId, field.getPosition()); } } } public void pullCard(String text, boolean community) { for (Player player : this.getGameState().getPlayers()) { ((ServerPlayer) player).getClient().informCardPull(text, community); } } public void endGame() { for (Player player : this.getGameState().getPlayers()) { ((ServerPlayer) player).getClient().informGameOver(this.getGameState().getActivePlayer().getId()); } } }