PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/freecol-0.10.3/src/net/sf/freecol/server/model/ServerGame.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 329 lines | 211 code | 31 blank | 87 comment | 58 complexity | 4850113fa0d9bda34105a9e393dc4c31 MD5 | raw file
  1. /**
  2. * Copyright (C) 2002-2011 The FreeCol Team
  3. *
  4. * This file is part of FreeCol.
  5. *
  6. * FreeCol is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * FreeCol is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package net.sf.freecol.server.model;
  20. import java.lang.reflect.InvocationTargetException;
  21. import java.util.ArrayList;
  22. import java.util.List;
  23. import java.util.Random;
  24. import java.util.logging.Level;
  25. import java.util.logging.Logger;
  26. import javax.xml.stream.XMLStreamException;
  27. import javax.xml.stream.XMLStreamReader;
  28. import net.sf.freecol.common.model.Colony;
  29. import net.sf.freecol.common.model.Europe;
  30. import net.sf.freecol.common.model.Event;
  31. import net.sf.freecol.common.model.FreeColGameObjectListener;
  32. import net.sf.freecol.common.model.Game;
  33. import net.sf.freecol.common.model.GameOptions;
  34. import net.sf.freecol.common.model.HistoryEvent;
  35. import net.sf.freecol.common.model.IndianSettlement;
  36. import net.sf.freecol.common.model.Limit;
  37. import net.sf.freecol.common.model.ModelMessage;
  38. import net.sf.freecol.common.model.Player;
  39. import net.sf.freecol.common.model.SimpleCombatModel;
  40. import net.sf.freecol.common.model.Specification;
  41. import net.sf.freecol.common.model.StringTemplate;
  42. import net.sf.freecol.common.model.Tile;
  43. import net.sf.freecol.common.model.Unit;
  44. import net.sf.freecol.server.control.ChangeSet;
  45. import net.sf.freecol.server.control.ChangeSet.ChangePriority;
  46. import net.sf.freecol.server.control.ChangeSet.See;
  47. /**
  48. * The server representation of the game.
  49. */
  50. public class ServerGame extends Game implements ServerModelObject {
  51. private static final Logger logger = Logger.getLogger(ServerGame.class.getName());
  52. /**
  53. * Creates a new game model.
  54. *
  55. * @param specification The <code>Specification</code> to use in this game.
  56. * @see net.sf.freecol.server.FreeColServer
  57. */
  58. public ServerGame(Specification specification) {
  59. super(specification);
  60. this.combatModel = new SimpleCombatModel();
  61. currentPlayer = null;
  62. }
  63. /**
  64. * Initiate a new <code>ServerGame</code> with information from a
  65. * saved game.
  66. *
  67. * @param freeColGameObjectListener A listener that should be monitoring
  68. * this <code>Game</code>.
  69. * @param in The input stream containing the XML.
  70. * @param serverStrings A list of server object type,ID pairs to create.
  71. * in this <code>Game</code>.
  72. * @param specification The <code>Specification</code> to use in this game.
  73. * @throws XMLStreamException if an error occurred during parsing.
  74. * @see net.sf.freecol.server.FreeColServer#loadGame
  75. */
  76. public ServerGame(FreeColGameObjectListener freeColGameObjectListener,
  77. XMLStreamReader in, List<String> serverStrings,
  78. Specification specification)
  79. throws XMLStreamException {
  80. super(specification);
  81. setFreeColGameObjectListener(freeColGameObjectListener);
  82. this.combatModel = new SimpleCombatModel();
  83. this.viewOwner = null;
  84. this.setGame(this);
  85. // Need a container to hold a reference to all the server
  86. // objects until the rest of the game is read. Without this,
  87. // because the server objects are just placeholders with no
  88. // real references to them, the WeakReferences in the Game are
  89. // insufficient to preserve them across garbage collections.
  90. List<Object> serverObjects = new ArrayList<Object>();
  91. // Create trivial instantiations of all the server objects.
  92. while (!serverStrings.isEmpty()) {
  93. String type = serverStrings.remove(0);
  94. String id = serverStrings.remove(0);
  95. try {
  96. Object o = makeServerObject(type, id);
  97. serverObjects.add(o);
  98. } catch (Exception e) {
  99. logger.log(Level.WARNING, "Build " + type + " failed", e);
  100. }
  101. }
  102. readFromXML(in);
  103. // Initialize players.
  104. for (Object o : serverObjects) {
  105. if (o instanceof Player) {
  106. Player player = (Player)o;
  107. if (player.isUnknownEnemy()) {
  108. setUnknownEnemy(player);
  109. } else {
  110. players.add(player);
  111. }
  112. }
  113. }
  114. }
  115. /**
  116. * Makes a trivial server object in this game given a server object tag
  117. * and an id.
  118. *
  119. * @param type The server object tag.
  120. * @param id The id.
  121. * @return A trivial server object.
  122. */
  123. private Object makeServerObject(String type, String id)
  124. throws ClassNotFoundException, IllegalAccessException,
  125. InstantiationException, InvocationTargetException,
  126. NoSuchMethodException {
  127. type = "net.sf.freecol.server.model."
  128. + type.substring(0,1).toUpperCase() + type.substring(1);
  129. Class<?> c = Class.forName(type);
  130. return c.getConstructor(Game.class, String.class)
  131. .newInstance(this, id);
  132. }
  133. /**
  134. * Get a unique ID to identify a <code>FreeColGameObject</code>.
  135. *
  136. * @return A unique ID.
  137. */
  138. public String getNextID() {
  139. String id = Integer.toString(nextId);
  140. nextId++;
  141. return id;
  142. }
  143. /**
  144. * Checks if anybody has won this game.
  145. *
  146. * @return The <code>Player</code> who has won the game or null if none.
  147. */
  148. public Player checkForWinner() {
  149. Specification spec = getSpecification();
  150. if (spec.getBoolean(GameOptions.VICTORY_DEFEAT_REF)) {
  151. for (Player player : getLiveEuropeanPlayers()) {
  152. if (player.getPlayerType() == Player.PlayerType.INDEPENDENT) {
  153. return player;
  154. }
  155. }
  156. }
  157. if (spec.getBoolean(GameOptions.VICTORY_DEFEAT_EUROPEANS)) {
  158. Player winner = null;
  159. for (Player player : getLiveEuropeanPlayers()) {
  160. if (!player.isREF()) {
  161. if (winner != null) { // A live European player
  162. winner = null;
  163. break;
  164. }
  165. winner = player;
  166. }
  167. }
  168. if (winner != null) return winner;
  169. }
  170. if (spec.getBoolean(GameOptions.VICTORY_DEFEAT_HUMANS)) {
  171. Player winner = null;
  172. for (Player player : getLiveEuropeanPlayers()) {
  173. if (!player.isAI()) {
  174. if (winner != null) { // A live human player
  175. winner = null;
  176. break;
  177. }
  178. winner = player;
  179. }
  180. }
  181. if (winner != null) return winner;
  182. }
  183. return null;
  184. }
  185. /**
  186. * Is the next player in a new turn?
  187. */
  188. public boolean isNextPlayerInNewTurn() {
  189. Player nextPlayer = getNextPlayer();
  190. return players.indexOf(currentPlayer) > players.indexOf(nextPlayer)
  191. || currentPlayer == nextPlayer;
  192. }
  193. /**
  194. * New turn for this game.
  195. *
  196. * @param random A <code>Random</code> number source.
  197. * @param cs A <code>ChangeSet</code> to update.
  198. */
  199. public void csNewTurn(Random random, ChangeSet cs) {
  200. TransactionSession.completeAll(cs);
  201. setTurn(getTurn().next());
  202. cs.addTrivial(See.all(), "newTurn", ChangePriority.CHANGE_NORMAL,
  203. "turn", Integer.toString(getTurn().getNumber()));
  204. logger.info("ServerGame.csNewTurn, turn is " + getTurn().toString());
  205. for (Player player : getPlayers()) {
  206. if (!player.isUnknownEnemy()) {
  207. ((ServerPlayer) player).csNewTurn(random, cs);
  208. }
  209. }
  210. Event spanishSuccession = getSpecification().getEvent("model.event.spanishSuccession");
  211. if (spanishSuccession != null && !getSpanishSuccession()) {
  212. Limit yearLimit = spanishSuccession.getLimit("model.limit.spanishSuccession.year");
  213. if (yearLimit.evaluate(this)) {
  214. csSpanishSuccession(cs, spanishSuccession);
  215. }
  216. }
  217. }
  218. /**
  219. * Checks for and if necessary performs the War of Spanish
  220. * Succession changes.
  221. *
  222. * @param cs A <code>ChangeSet</code> to update.
  223. * @param spanishSuccession an <code>Event</code> value
  224. */
  225. private void csSpanishSuccession(ChangeSet cs, Event spanishSuccession) {
  226. Player weakestAIPlayer = null;
  227. Player strongestAIPlayer = null;
  228. for (Player player : getLiveEuropeanPlayers()) {
  229. if (player.isREF() || !player.isAI()) continue;
  230. if (weakestAIPlayer == null
  231. || weakestAIPlayer.getScore() > player.getScore()) {
  232. weakestAIPlayer = player;
  233. }
  234. if (strongestAIPlayer == null
  235. || strongestAIPlayer.getScore() < player.getScore()) {
  236. strongestAIPlayer = player;
  237. }
  238. }
  239. // Only eliminate the weakest AI if limits are met
  240. Limit weakestPlayerLimit;
  241. Limit strongestPlayerLimit;
  242. if (weakestAIPlayer != null
  243. && strongestAIPlayer != null
  244. && weakestAIPlayer != strongestAIPlayer
  245. && ((weakestPlayerLimit = spanishSuccession.getLimit("model.limit.spanishSuccession.weakestPlayer")) == null
  246. || weakestPlayerLimit.evaluate(weakestAIPlayer))
  247. && ((strongestPlayerLimit = spanishSuccession.getLimit("model.limit.spanishSuccession.strongestPlayer")) == null
  248. || strongestPlayerLimit.evaluate(strongestAIPlayer))) {
  249. for (Player player : getPlayers()) {
  250. for (IndianSettlement settlement
  251. : player.getIndianSettlementsWithMission(weakestAIPlayer)) {
  252. Unit missionary = settlement.getMissionary();
  253. missionary.setOwner(strongestAIPlayer);
  254. settlement.getTile().updatePlayerExploredTiles();
  255. cs.add(See.perhaps().always((ServerPlayer)strongestAIPlayer),
  256. settlement);
  257. }
  258. }
  259. for (Colony colony : weakestAIPlayer.getColonies()) {
  260. colony.changeOwner(strongestAIPlayer);
  261. for (Tile tile : colony.getOwnedTiles()) {
  262. cs.add(See.perhaps(), tile);
  263. }
  264. }
  265. for (Unit unit : weakestAIPlayer.getUnits()) {
  266. unit.setOwner(strongestAIPlayer);
  267. if (unit.getLocation() instanceof Europe) {
  268. unit.setLocation(strongestAIPlayer.getEurope());
  269. }
  270. cs.add(See.perhaps(), unit);
  271. }
  272. StringTemplate loser = weakestAIPlayer.getNationName();
  273. StringTemplate winner = strongestAIPlayer.getNationName();
  274. cs.addMessage(See.all(),
  275. new ModelMessage(ModelMessage.MessageType.FOREIGN_DIPLOMACY,
  276. "model.diplomacy.spanishSuccession",
  277. strongestAIPlayer)
  278. .addStringTemplate("%loserNation%", loser)
  279. .addStringTemplate("%nation%", winner));
  280. cs.addGlobalHistory(this,
  281. new HistoryEvent(getTurn(),
  282. HistoryEvent.EventType.SPANISH_SUCCESSION)
  283. .addStringTemplate("%loserNation%", loser)
  284. .addStringTemplate("%nation%", winner));
  285. setSpanishSuccession(true);
  286. cs.addPartial(See.all(), this, "spanishSuccession");
  287. ((ServerPlayer) weakestAIPlayer).csKill(cs);
  288. }
  289. }
  290. /**
  291. * Returns the tag name of the root element representing this object.
  292. *
  293. * @return "serverGame".
  294. */
  295. public String getServerXMLElementTagName() {
  296. return "serverGame";
  297. }
  298. }