package net.sf.colossus.client; import java.util.ArrayList; import java.util.List; import net.sf.colossus.game.BattlePhase; import net.sf.colossus.game.BattleUnit; import net.sf.colossus.game.Game; import net.sf.colossus.game.Legion; import net.sf.colossus.game.Player; import net.sf.colossus.util.Split; import net.sf.colossus.variant.MasterHex; import net.sf.colossus.variant.Variant; public class GameClientSide extends Game implements IOracle { private Client client; /** * This is used as a placeholder for activePlayer and battleActivePlayer since they * are sometimes accessed when they are not available. * * TODO this is a hack. Those members should just not be accessed at times where they * are not available. It seems to happen during startup (the not yet set case) and in * some GUI parts after battles, when battleActivePlayer has been reset already. */ private final PlayerClientSide noone; private Player activePlayer; public GameClientSide(Variant variant, String[] playerNames) { super(variant, playerNames); // TODO fix this dummy constructor args this.noone = new PlayerClientSide(this, "", 0); this.activePlayer = noone; } public void setClient(Client client) { this.client = client; } public PlayerClientSide initPlayerInfo(List<String> infoStrings, String searchedName) { int numPlayers = infoStrings.size(); PlayerClientSide owningPlayer = null; // first time we get the player infos, store them locally and set our // own, too -- which has been a fake until now for (int i = 0; i < numPlayers; i++) { List<String> data = Split.split(":", infoStrings.get(i)); String playerName = data.get(1); PlayerClientSide player = new PlayerClientSide(this, playerName, i); addPlayer(player); if (playerName.equals(searchedName)) { owningPlayer = player; } } return owningPlayer; } public Player getNoonePlayer() { return noone; } public void updatePlayerInfo(List<String> infoStrings) { for (int i = 0; i < infoStrings.size(); i++) { PlayerClientSide player = (PlayerClientSide)players.get(i); player.update(infoStrings.get(i)); } } /** * * String is in form: * name:isDead:eliminatedPlayers:score:mulligans:mk01,mk01,...mk12 * @param valuesString */ public void updatePlayerValues(String valuesString) { List<String> values = Split.split(":", valuesString); String playerName = values.remove(0); boolean isDead = Boolean.valueOf(values.remove(0)).booleanValue(); String eliminatedPlayers = values.remove(0); int score = Integer.parseInt(values.remove(0)); int mulligansLeft = Integer.parseInt(values.remove(0)); String freeMarkers = values.remove(0); Player player = getPlayerByName(playerName); ((PlayerClientSide)player).updateValues(isDead, eliminatedPlayers, score, mulligansLeft, freeMarkers); } // TODO not needed right now on client side - SCT compares to // "null" instead. Check whether to remove when pulling up? /** * Resolve playerName into Player object. Name might be null, * then returns null. * @param playerName * @return The player object for given player name, null if name was null */ Player getPlayerByNameIgnoreNull(String playerName) { if (playerName == null) { return null; } else { return getPlayerByName(playerName); } } /** * Resolve playerName into Player object. * Name must not be null. If no player for given name found, * it would throw IllegalArgumentException * @param playerName * @return Player object for given name. */ Player getPlayerByName(String playerName) { assert playerName != null : "Name for player to find must not be null!"; /* System.out.println("*****\nsearching player for " + playerName); for (Player player : players) { System.out.println("compare with " + player.getName()); } System.out.println("Now really searching player for " + playerName); */ for (Player player : players) { if (player.getName().equals(playerName)) { return player; } } throw new IllegalArgumentException("No player object found for name '" + playerName + "'"); } public Player getPlayerByTag(int tag) { BattleUnit battleUnit = getBattleCS().getBattleUnit(tag); assert battleUnit != null : "Illegal value for tag parameter"; return battleUnit.getLegion().getPlayer(); } private Player getPlayerUsingColor(String shortColor) { assert this.players.size() > 0 : "Client side player list not yet initialized"; assert shortColor != null : "Parameter must not be null"; // Stage 1: See if the player who started with this color is alive. for (Player info : players) { if (shortColor.equals(info.getShortColor()) && !info.isDead()) { return info; } } // Stage 2: He's dead. Find who killed him and see if he's alive. for (Player info : players) { if (info.getPlayersElim().indexOf(shortColor) != -1) { // We have the killer. if (!info.isDead()) { return info; } else { return getPlayerUsingColor(info.getShortColor()); } } } return null; } public Player getPlayerByMarkerId(String markerId) { assert markerId != null : "Parameter must not be null"; String shortColor = markerId.substring(0, 2); return getPlayerUsingColor(shortColor); } /** Return the average point value of all legions in the game. */ public int getAverageLegionPointValue() { int totalValue = 0; int totalLegions = 0; for (Player player : players) { totalLegions += player.getLegions().size(); totalValue += player.getTotalPointValue(); } return (int)(Math.round((double)totalValue / totalLegions)); } // TODO: move method from Client to here, or even to game.Game? @Override public Legion getLegionByMarkerId(String markerId) { return client.getLegion(markerId); } public void setActivePlayer(Player player) { activePlayer = player; } public Player getActivePlayer() { return activePlayer; } /** * ActivePlayer is set first time to something different than "noone" * when setupTurnState is called first time. * @return true if activePlayer is still "noone". */ public boolean isTurnStateStillUninitialized() { return activePlayer.equals(noone); } public void initBattle(MasterHex hex, int battleTurnNumber, Player battleActivePlayer, BattlePhase battlePhase, Legion attacker, Legion defender) { this.battle = new BattleClientSide(this, attacker, defender, hex); getBattleCS().init(battleTurnNumber, battleActivePlayer, battlePhase); } public BattleClientSide getBattleCS() { return (BattleClientSide)battle; } public boolean isBattleOngoing() { return battle != null; } public BattlePhase getBattlePhase() { assert battle != null : "No battle phase if there is no battle!"; return getBattleCS().getBattlePhase(); } public void setBattlePhase(BattlePhase battlePhase) { getBattleCS().setBattlePhase(battlePhase); } public boolean isBattlePhase(BattlePhase phase) { return getBattleCS().getBattlePhase() == phase; } public void setBattleActivePlayer(Player battleActivePlayer) { getBattleCS().setBattleActivePlayer(battleActivePlayer); } public void setBattleTurnNumber(int battleTurnNumber) { getBattleCS().setBattleTurnNumber(battleTurnNumber); } @Override public int getBattleTurnNumber() { return getBattleCS().getBattleTurnNumber(); } public Player getBattleActivePlayer() { if (battle == null) { return null; } return getBattleCS().getBattleActivePlayer(); } public void cleanupBattle() { if (battle != null) { getBattleCS().cleanupBattle(); battle = null; } } /** Return a list of Strings. Use the proper string for titans and * unknown creatures. */ // public for IOracle public List<String> getLegionImageNames(Legion legion) { LegionClientSide info = (LegionClientSide)legion; if (info != null) { return info.getImageNames(); } return new ArrayList<String>(); } /** Return a list of Booleans */ // public for IOracle public List<Boolean> getLegionCreatureCertainties(Legion legion) { LegionClientSide info = (LegionClientSide)legion; if (info != null) { return info.getCertainties(); } else { // TODO: is this the right thing? List<Boolean> l = new ArrayList<Boolean>(10); // just longer then max for (int idx = 0; idx < 10; idx++) { l.add(Boolean.valueOf(true)); // all true } return l; } } }