/projects/freecol-0.10.3/src/net/sf/freecol/server/model/ServerGame.java
Java | 329 lines | 211 code | 31 blank | 87 comment | 58 complexity | 4850113fa0d9bda34105a9e393dc4c31 MD5 | raw file
- /**
- * Copyright (C) 2002-2011 The FreeCol Team
- *
- * This file is part of FreeCol.
- *
- * FreeCol 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 2 of the License, or
- * (at your option) any later version.
- *
- * FreeCol 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 FreeCol. If not, see <http://www.gnu.org/licenses/>.
- */
- package net.sf.freecol.server.model;
- import java.lang.reflect.InvocationTargetException;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Random;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- import javax.xml.stream.XMLStreamException;
- import javax.xml.stream.XMLStreamReader;
- import net.sf.freecol.common.model.Colony;
- import net.sf.freecol.common.model.Europe;
- import net.sf.freecol.common.model.Event;
- import net.sf.freecol.common.model.FreeColGameObjectListener;
- import net.sf.freecol.common.model.Game;
- import net.sf.freecol.common.model.GameOptions;
- import net.sf.freecol.common.model.HistoryEvent;
- import net.sf.freecol.common.model.IndianSettlement;
- import net.sf.freecol.common.model.Limit;
- import net.sf.freecol.common.model.ModelMessage;
- import net.sf.freecol.common.model.Player;
- import net.sf.freecol.common.model.SimpleCombatModel;
- import net.sf.freecol.common.model.Specification;
- import net.sf.freecol.common.model.StringTemplate;
- import net.sf.freecol.common.model.Tile;
- import net.sf.freecol.common.model.Unit;
- import net.sf.freecol.server.control.ChangeSet;
- import net.sf.freecol.server.control.ChangeSet.ChangePriority;
- import net.sf.freecol.server.control.ChangeSet.See;
- /**
- * The server representation of the game.
- */
- public class ServerGame extends Game implements ServerModelObject {
- private static final Logger logger = Logger.getLogger(ServerGame.class.getName());
- /**
- * Creates a new game model.
- *
- * @param specification The <code>Specification</code> to use in this game.
- * @see net.sf.freecol.server.FreeColServer
- */
- public ServerGame(Specification specification) {
- super(specification);
- this.combatModel = new SimpleCombatModel();
- currentPlayer = null;
- }
- /**
- * Initiate a new <code>ServerGame</code> with information from a
- * saved game.
- *
- * @param freeColGameObjectListener A listener that should be monitoring
- * this <code>Game</code>.
- * @param in The input stream containing the XML.
- * @param serverStrings A list of server object type,ID pairs to create.
- * in this <code>Game</code>.
- * @param specification The <code>Specification</code> to use in this game.
- * @throws XMLStreamException if an error occurred during parsing.
- * @see net.sf.freecol.server.FreeColServer#loadGame
- */
- public ServerGame(FreeColGameObjectListener freeColGameObjectListener,
- XMLStreamReader in, List<String> serverStrings,
- Specification specification)
- throws XMLStreamException {
- super(specification);
- setFreeColGameObjectListener(freeColGameObjectListener);
- this.combatModel = new SimpleCombatModel();
- this.viewOwner = null;
- this.setGame(this);
- // Need a container to hold a reference to all the server
- // objects until the rest of the game is read. Without this,
- // because the server objects are just placeholders with no
- // real references to them, the WeakReferences in the Game are
- // insufficient to preserve them across garbage collections.
- List<Object> serverObjects = new ArrayList<Object>();
- // Create trivial instantiations of all the server objects.
- while (!serverStrings.isEmpty()) {
- String type = serverStrings.remove(0);
- String id = serverStrings.remove(0);
- try {
- Object o = makeServerObject(type, id);
- serverObjects.add(o);
- } catch (Exception e) {
- logger.log(Level.WARNING, "Build " + type + " failed", e);
- }
- }
- readFromXML(in);
- // Initialize players.
- for (Object o : serverObjects) {
- if (o instanceof Player) {
- Player player = (Player)o;
- if (player.isUnknownEnemy()) {
- setUnknownEnemy(player);
- } else {
- players.add(player);
- }
- }
- }
- }
- /**
- * Makes a trivial server object in this game given a server object tag
- * and an id.
- *
- * @param type The server object tag.
- * @param id The id.
- * @return A trivial server object.
- */
- private Object makeServerObject(String type, String id)
- throws ClassNotFoundException, IllegalAccessException,
- InstantiationException, InvocationTargetException,
- NoSuchMethodException {
- type = "net.sf.freecol.server.model."
- + type.substring(0,1).toUpperCase() + type.substring(1);
- Class<?> c = Class.forName(type);
- return c.getConstructor(Game.class, String.class)
- .newInstance(this, id);
- }
- /**
- * Get a unique ID to identify a <code>FreeColGameObject</code>.
- *
- * @return A unique ID.
- */
- public String getNextID() {
- String id = Integer.toString(nextId);
- nextId++;
- return id;
- }
- /**
- * Checks if anybody has won this game.
- *
- * @return The <code>Player</code> who has won the game or null if none.
- */
- public Player checkForWinner() {
- Specification spec = getSpecification();
- if (spec.getBoolean(GameOptions.VICTORY_DEFEAT_REF)) {
- for (Player player : getLiveEuropeanPlayers()) {
- if (player.getPlayerType() == Player.PlayerType.INDEPENDENT) {
- return player;
- }
- }
- }
- if (spec.getBoolean(GameOptions.VICTORY_DEFEAT_EUROPEANS)) {
- Player winner = null;
- for (Player player : getLiveEuropeanPlayers()) {
- if (!player.isREF()) {
- if (winner != null) { // A live European player
- winner = null;
- break;
- }
- winner = player;
- }
- }
- if (winner != null) return winner;
- }
- if (spec.getBoolean(GameOptions.VICTORY_DEFEAT_HUMANS)) {
- Player winner = null;
- for (Player player : getLiveEuropeanPlayers()) {
- if (!player.isAI()) {
- if (winner != null) { // A live human player
- winner = null;
- break;
- }
- winner = player;
- }
- }
- if (winner != null) return winner;
- }
- return null;
- }
- /**
- * Is the next player in a new turn?
- */
- public boolean isNextPlayerInNewTurn() {
- Player nextPlayer = getNextPlayer();
- return players.indexOf(currentPlayer) > players.indexOf(nextPlayer)
- || currentPlayer == nextPlayer;
- }
- /**
- * New turn for this game.
- *
- * @param random A <code>Random</code> number source.
- * @param cs A <code>ChangeSet</code> to update.
- */
- public void csNewTurn(Random random, ChangeSet cs) {
- TransactionSession.completeAll(cs);
- setTurn(getTurn().next());
- cs.addTrivial(See.all(), "newTurn", ChangePriority.CHANGE_NORMAL,
- "turn", Integer.toString(getTurn().getNumber()));
- logger.info("ServerGame.csNewTurn, turn is " + getTurn().toString());
- for (Player player : getPlayers()) {
- if (!player.isUnknownEnemy()) {
- ((ServerPlayer) player).csNewTurn(random, cs);
- }
- }
- Event spanishSuccession = getSpecification().getEvent("model.event.spanishSuccession");
- if (spanishSuccession != null && !getSpanishSuccession()) {
- Limit yearLimit = spanishSuccession.getLimit("model.limit.spanishSuccession.year");
- if (yearLimit.evaluate(this)) {
- csSpanishSuccession(cs, spanishSuccession);
- }
- }
- }
- /**
- * Checks for and if necessary performs the War of Spanish
- * Succession changes.
- *
- * @param cs A <code>ChangeSet</code> to update.
- * @param spanishSuccession an <code>Event</code> value
- */
- private void csSpanishSuccession(ChangeSet cs, Event spanishSuccession) {
- Player weakestAIPlayer = null;
- Player strongestAIPlayer = null;
- for (Player player : getLiveEuropeanPlayers()) {
- if (player.isREF() || !player.isAI()) continue;
- if (weakestAIPlayer == null
- || weakestAIPlayer.getScore() > player.getScore()) {
- weakestAIPlayer = player;
- }
- if (strongestAIPlayer == null
- || strongestAIPlayer.getScore() < player.getScore()) {
- strongestAIPlayer = player;
- }
- }
- // Only eliminate the weakest AI if limits are met
- Limit weakestPlayerLimit;
- Limit strongestPlayerLimit;
- if (weakestAIPlayer != null
- && strongestAIPlayer != null
- && weakestAIPlayer != strongestAIPlayer
- && ((weakestPlayerLimit = spanishSuccession.getLimit("model.limit.spanishSuccession.weakestPlayer")) == null
- || weakestPlayerLimit.evaluate(weakestAIPlayer))
- && ((strongestPlayerLimit = spanishSuccession.getLimit("model.limit.spanishSuccession.strongestPlayer")) == null
- || strongestPlayerLimit.evaluate(strongestAIPlayer))) {
- for (Player player : getPlayers()) {
- for (IndianSettlement settlement
- : player.getIndianSettlementsWithMission(weakestAIPlayer)) {
- Unit missionary = settlement.getMissionary();
- missionary.setOwner(strongestAIPlayer);
- settlement.getTile().updatePlayerExploredTiles();
- cs.add(See.perhaps().always((ServerPlayer)strongestAIPlayer),
- settlement);
- }
- }
- for (Colony colony : weakestAIPlayer.getColonies()) {
- colony.changeOwner(strongestAIPlayer);
- for (Tile tile : colony.getOwnedTiles()) {
- cs.add(See.perhaps(), tile);
- }
- }
- for (Unit unit : weakestAIPlayer.getUnits()) {
- unit.setOwner(strongestAIPlayer);
- if (unit.getLocation() instanceof Europe) {
- unit.setLocation(strongestAIPlayer.getEurope());
- }
- cs.add(See.perhaps(), unit);
- }
- StringTemplate loser = weakestAIPlayer.getNationName();
- StringTemplate winner = strongestAIPlayer.getNationName();
- cs.addMessage(See.all(),
- new ModelMessage(ModelMessage.MessageType.FOREIGN_DIPLOMACY,
- "model.diplomacy.spanishSuccession",
- strongestAIPlayer)
- .addStringTemplate("%loserNation%", loser)
- .addStringTemplate("%nation%", winner));
- cs.addGlobalHistory(this,
- new HistoryEvent(getTurn(),
- HistoryEvent.EventType.SPANISH_SUCCESSION)
- .addStringTemplate("%loserNation%", loser)
- .addStringTemplate("%nation%", winner));
- setSpanishSuccession(true);
- cs.addPartial(See.all(), this, "spanishSuccession");
- ((ServerPlayer) weakestAIPlayer).csKill(cs);
- }
- }
- /**
- * Returns the tag name of the root element representing this object.
- *
- * @return "serverGame".
- */
- public String getServerXMLElementTagName() {
- return "serverGame";
- }
- }