/* 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.client; import java.io.Serializable; import java.util.Map; import org.ojim.iface.IClient; import org.ojim.log.OJIMLogger; import org.ojim.logic.Logic; import org.ojim.logic.rules.GameRules; import org.ojim.logic.state.Auction; import org.ojim.logic.state.GameState; import org.ojim.logic.state.Player; 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.NetOjim; import edu.kit.iti.pse.iface.IServer; import edu.kit.iti.pse.iface.IServerAuction; import edu.kit.iti.pse.iface.IServerTrade; /** * Simpler client Implementation. This client only wraps the methods of IServer * and checks it with the rules. * * But no “Connection” and “IClient” support. * * @author Fabian Neundorf. */ public class SimpleClient implements Serializable { /** * Different trade states. * * @author Fabian Neundorf. * @see {@link IServerTrade#getTradeState()}. */ public enum TradeState { NOT_RUNNING(-1), WAITING_PROPOSAL(0), WAITING_PROPOSED(1), DECLINED(2), ACCEPTED(3); public final int value; TradeState(int value) { this.value = value; } public static TradeState getState(int state) { for (TradeState tradeState : TradeState.values()) { if (tradeState.value == state) { return tradeState; } } throw new IllegalArgumentException("state is not recognized"); } } public enum AuctionState { NOT_RUNNING(-1), WAITING(0), FIRST(1), SECOND(2), THIRD(3); public final int value; AuctionState(int value) { this.value = value; } public static AuctionState getState(int state) { switch (state) { case -1: return NOT_RUNNING; case 0: return WAITING; case 1: return FIRST; case 2: return SECOND; case 3: return THIRD; default: throw new IllegalArgumentException("state is not recognized"); } } } private IServer server; private Logic logic; private Player me; private int playerId; public SimpleClient() { } public SimpleClient(Logic logic, int playerId, IServer server) { this.setParameters(logic, playerId, server); this.me = this.getGameState().getPlayerById(playerId); } private void setMyPlayer(Player player) { this.me = player; } protected Player getMe() { return this.me; } protected Logic getLogic() { return this.logic; } protected void setPlayerId(int id) { this.playerId = id; } public GameState getGameState() { return this.logic.getGameState(); } protected GameRules getGameRules() { return this.logic.getGameRules(); } protected void setParameters(Logic logic, int playerId, IServer server) { this.logic = logic; this.playerId = playerId; this.server = server; } protected void setParameters(IServer server, IClient client) { this.setParameters(server, client, new GameState()); } protected void setParameters(IServer server, IClient client, GameState state) { this.server = server; this.logic = new Logic(state, server.getRules()); this.playerId = server.addPlayer(client); // Load my data client.informNewPlayer(this.playerId); this.setMyPlayer(state.getPlayerById(this.playerId)); } public final int getPlayerId() { return this.playerId; } /* * GETTER OF ISERVER */ public Field getFieldFromServer(int position, Map<Integer, FieldGroup> groups, Map<Integer, Player> players) { Field field = null; int color = this.server.getEstateColorGroup(position); String name = this.server.getEstateName(position, this.playerId); int price = this.server.getEstatePrice(position); // Groups can be null! // If you need your own group create it at the position. // A normal FieldGroup will be created automatically FieldGroup group = groups.get(color); boolean newGroup = group == null; // Street if (color >= 0) { if (group == null) { int delim = name.indexOf(":"); String groupName = ""; if (delim > 0) { groupName = name.substring(0, delim); } group = new StreetFieldGroup(color, groupName, this.server.getEstateHousePrice(position)); } name = name.substring(name.indexOf(":") + 1).trim(); int[] rentByLevel = new int[Street.MAXMIMUM_BUILT_LEVEL]; for (int builtLevel = 0; builtLevel < rentByLevel.length; builtLevel++) { rentByLevel[builtLevel] = this.server.getEstateRent(position, builtLevel); } Street street = new Street(name, position, rentByLevel, this.server.getEstateHouses(position), price); street.setMortgaged(this.server.isMortgaged(position)); field = street; } else { switch (color) { case FieldGroup.GO: field = new GoField(name, position); break; case FieldGroup.JAIL: field = new Jail(name, position, this.getMoneyToPay(position), this.getRoundsToWait(position)); break; case FieldGroup.FREE_PARKING: field = new FreeParking(name, position); ((FreeParking) field).transferMoney(this.server.getFreeParkingPot(position)); break; case FieldGroup.GO_TO_JAIL: field = new GoToJail(name, position); break; case FieldGroup.EVENT: field = new CardField(name, position, false); break; case FieldGroup.COMMUNITY: field = new CardField(name, position, true); break; case FieldGroup.STATIONS: if (group == null) { group = new StationFieldGroup(); } field = new Station(name, position, price); break; case FieldGroup.INFRASTRUCTURE: if (group == null) { group = new InfrastructureFieldGroup(); } field = new InfrastructureField(name, position, price); break; case FieldGroup.TAX: field = new TaxField(name, position, this.server.getEstateRent(position, 0)); break; default: field = null; break; } } if (field != null) { if (group == null) { group = new FieldGroup(color); } if (field instanceof BuyableField) { this.updateFieldOwner((BuyableField) field, players); } if (newGroup) { groups.put(color, group); } group.addField(field); } else { OJIMLogger.getLogger(this.getClass().toString()).warning("Unknown field color (" + color + ")"); } return field; } public BuyableField updateFieldOwner(BuyableField field, Map<Integer, Player> players) { int playerId = this.server.getOwner(field.getPosition()); Player owner = players.get(playerId); if (owner == null && playerId >= 0) { OJIMLogger.getLogger(this.getClass().toString()).info("Owner doesn't exists (at the moment?)!"); } else { field.buy(owner); } return field; } // Bank public int getNumberOfHousesLeft() { return this.server.getNumberOfHousesLeft(); } public int getNumberOfHotelsLeft() { return this.server.getNumberOfHotelsLeft(); } // Spieler public Player getPlayerFromServer(int playerId) { Player player = new Player(this.server.getPlayerName(playerId), this.server.getPlayerPiecePosition(playerId), this.server.getPlayerCash(playerId), playerId, this.server.getPlayerColor(playerId)); player.setNumberOfGetOutOfJailCards(this.server.getNumberOfGetOutOfJailCards(playerId)); return player; } public Player updatePlayersGetOutOfJailCards(Player player) { player.setNumberOfGetOutOfJailCards(this.server.getNumberOfGetOutOfJailCards(player.getId())); return player; } /* * ADITIONAL GETTER */ /** * 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 int getMoneyToPay(int position) { if (this.server instanceof NetOjim) { // return ((NetOjim) this.server).getMoneyToPay(position); return 1000; } else { return 1000; // TODO: (xZise) Is this the correct value? } } /** * 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 int getRoundsToWait(int position) { if (this.server instanceof NetOjim) { // return ((NetOjim) this.server).getRoundsToWait(position); return 3; } else { return 3; // TODO: (xZise) Is this the correct value? } } /* * ACTION METHODS */ /** * Setzt diesen Spieler auf „bereit“. */ protected final void ready() { this.server.setPlayerReady(this.playerId); } /** * Akzeptiert die Nachricht. * * @see {@link edu.kit.iti.pse.iface.IServer.accept} */ protected final void accept() { this.server.accept(this.playerId); } protected final void decline() { this.server.decline(this.playerId); } protected final boolean rollDice() { if (this.getGameRules().isPlayerOnTurn(this.me)) { return this.server.rollDice(this.playerId); } else { //System.out.println("not on turn"); return false; } } protected final void endTurn() { if (this.getGameRules().isPlayerOnTurn(this.me)) { this.server.endTurn(this.playerId); } else { //System.out.println("not on turn"); } } protected final void declareBankruptcy() { this.server.declareBankruptcy(this.playerId); } protected final void construct(Street street) { if (this.getGameRules().isFieldUpgradable(this.me, street, +1)) { this.server.construct(this.playerId, street.getPosition()); } } protected final void destruct(Street street) { if (this.getGameRules().isFieldUpgradable(this.me, street, -1)) { this.server.deconstruct(this.playerId, street.getPosition()); } } protected final void toggleMortgage(BuyableField street) { if (this.getGameRules().isFieldMortgageable(this.me, street)) { //System.out.println("Field is Mortageable"); this.server.toggleMortgage(this.playerId, street.getPosition()); } } protected final void sendMessage(String text) { this.server.sendMessage(text, this.playerId); } protected final void sendPrivateMessage(String text, Player reciever) { this.server.sendPrivateMessage(text, this.playerId, reciever.getId()); } protected final boolean payFine() { return this.server.payFine(this.playerId); } protected final boolean useGetOutOfJailCard() { return this.server.useGetOutOfJailCard(this.playerId); } /* * RULES */ public final boolean isMyTurn() { return this.getGameRules().isPlayerOnTurn(this.me); } /* * TRADE */ public final boolean initTrade(Player partnerPlayer) { int id = -1; if (partnerPlayer != null) { id = partnerPlayer.getId(); } return ((IServerTrade) this.server).initTrade(this.playerId, id); } public final TradeState getTradeState() { return TradeState.getState(((IServerTrade) this.server).getTradeState()); } public final Player getPartner() { int id = ((IServerTrade) this.server).getPartner(); Player partner = null; if (id >= 0) { partner = this.getGameState().getPlayerById(id); if (partner == null) { OJIMLogger.getLogger(this.getClass().toString()).severe("partner is unkown"); } } return partner; } public final Player getActing() { int id = ((IServerTrade) this.server).getActing(); Player partner = null; if (id >= 0) { partner = this.getGameState().getPlayerById(id); if (partner == null) { OJIMLogger.getLogger(this.getClass().toString()).severe("acting is unkown"); } } return partner; } public final boolean offerCash(int amount) { return ((IServerTrade) this.server).offerCash(playerId, amount); } public final boolean offerGetOutOfJailCard() { return this.offerGetOutOfJailCard(1) == 0; } /** * Offers so often a get out of jail card until, it returns false. * * @param amount * the number of offered cards. * @return false if the offering fails. Then it has offered less than the * given amount. If all cards could be offered it returns true. */ public final int offerGetOutOfJailCard(int amount) { while (amount-- > 0) { if (!((IServerTrade) this.server).offerGetOutOfJailCard(playerId)) { return amount + 1; } } return amount; } public final boolean offerEstate(BuyableField field) { return ((IServerTrade) this.server).offerEstate(playerId, field.getPosition()); } public final boolean requireCash(int amount) { return ((IServerTrade) this.server).requireCash(playerId, amount); } public final boolean requireGetOutOfJailCard() { return this.requireGetOutOfJailCard(1) == 0; } /** * Requires so often a get out of jail card until, it returns false. * * @param amount * the number of required cards. * @return The number of remaining cards which couldn't be required. */ public final int requireGetOutOfJailCard(int amount) { while (amount-- > 0) { if (!((IServerTrade) this.server).requireGetOutOfJailCard(playerId)) { return amount + 1; } } return 0; } public final boolean requireEstate(BuyableField field) { return ((IServerTrade) this.server).requireEstate(playerId, field.getPosition()); } /** * @deprecated Use {@link #getOfferedEstate()} */ public final int[] getOfferedEstatesO() { return ((IServerTrade) this.server).getOfferedEstates(); } public final BuyableField[] getOfferedEstate() { int[] fields = ((IServerTrade) this.server).getOfferedEstates(); BuyableField[] result = new BuyableField[fields.length]; for (int i = 0; i < fields.length; i++) { result[i] = (BuyableField) this.getGameState().getFieldAt(fields[i]); } return result; } public final int getOfferedCash() { return ((IServerTrade) this.server).getOfferedCash(); } public final int getNumberOfOfferedGetOutOfJailCards() { return ((IServerTrade) this.server).getNumberOfOfferedGetOutOfJailCards(); } /** * @deprecated Use {@link #getRequiredEstates()} */ public final int[] getRequiredEstatesO() { return ((IServerTrade) this.server).getRequiredEstates(); } public final BuyableField[] getRequiredEstates() { int[] fields = ((IServerTrade) this.server).getRequiredEstates(); BuyableField[] result = new BuyableField[fields.length]; for (int i = 0; i < fields.length; i++) { result[i] = (BuyableField) this.getGameState().getFieldAt(fields[i]); } return result; } public final int getRequiredCash() { return ((IServerTrade) this.server).getRequiredCash(); } public final int getNumberOfRequiredGetOutOfJailCards() { return ((IServerTrade) this.server).getNumberOfRequiredGetOutOfJailCards(); } public final boolean cancelTrade() { return ((IServerTrade) this.server).cancelTrade(this.playerId); } public final boolean proposeTrade() { return ((IServerTrade) this.server).proposeTrade(this.playerId); } /* * AUCTION */ public Auction getAuctionFromServer() { IServerAuction auctionServer = (IServerAuction) this.server; AuctionState state = AuctionState.getState(auctionServer.getAuctionState()); if (state == AuctionState.NOT_RUNNING) { return null; } BuyableField field = (BuyableField) this.getGameState().getFieldAt(auctionServer.getAuctionedEstate()); Auction auction = new Auction(field, state); Player bidder = this.getGameState().getPlayerById(auctionServer.getBidder()); auction.placeBid(bidder, auctionServer.getHighestBid()); return auction; } public Auction updateAuction(Auction auction) { IServerAuction auctionServer = (IServerAuction) this.server; AuctionState newState = AuctionState.getState(auctionServer.getAuctionState()); // New bid if (newState == AuctionState.WAITING) { Player bidder = this.getGameState().getPlayerById(auctionServer.getBidder()); auction.placeBid(bidder, auctionServer.getHighestBid()); } else { auction.setState(newState); } return auction; } public final boolean placeBid(int amount) { return ((IServerAuction) this.server).placeBid(this.playerId, amount); } }