From: Erik V. <ev...@us...> - 2011-08-09 20:54:08
|
data/18TN/CompanyManager.xml | 2 data/18TN/Game.xml | 1 rails/game/GameManager.java | 188 ++++++++++----------- rails/game/GameManagerI.java | 3 rails/game/OperatingRound.java | 8 rails/game/Phase.java | 94 ++++++---- rails/game/PublicCompany.java | 6 rails/game/PublicCompanyI.java | 3 rails/game/Round.java | 67 ++++--- rails/game/RoundI.java | 2 rails/game/specific/_18TN/OperatingRound_18TN.java | 69 +++++-- rails/game/specific/_18TN/PublicCompany_18TN.java | 45 +++++ 12 files changed, 298 insertions(+), 190 deletions(-) New commits: commit cee06b8d1fde54e05bc1f981894d841c1398e926 Author: Erik Vos <eri...@xs...> Date: Tue Aug 9 22:22:09 2011 +0200 Phase management step 4 and application to 18TN Civil War <Phase> can now have an <Action> child with (required) name and (optional) value attributes. Each action caused gameManager.processPhaseAction (name, value) to be called when that phase is activated. GameManager in turn calls processPhaseAction(name, value) in the current round. This new feature is used to implement 18TN Civil War (except the revenue calculation). Updated OperatingRound_18TN and created new PublicCompany_18TN. Added stub hasRoute() to PublicCompany (currently always returns true). diff --git a/data/18TN/CompanyManager.xml b/data/18TN/CompanyManager.xml index 8268cc4..282fe15 100644 --- a/data/18TN/CompanyManager.xml +++ b/data/18TN/CompanyManager.xml @@ -7,7 +7,7 @@ <Tradeable toCompany="yes" lowerPriceFactor="0.5" upperPriceFactor="2.0"/> <Tradeable toPlayer="yes"/> </CompanyType> - <CompanyType name="Public" class="rails.game.PublicCompany"> + <CompanyType name="Public" class="rails.game.specific._18TN.PublicCompany_18TN"> <CanBuyPrivates/> <PoolPaysOut/> <Float percentage="60"/> diff --git a/data/18TN/Game.xml b/data/18TN/Game.xml index 1cddd70..8e971cd 100644 --- a/data/18TN/Game.xml +++ b/data/18TN/Game.xml @@ -101,6 +101,7 @@ <OperatingRounds number="2"/> </Phase> <Phase name="3½"> + <Action name="CivilWar"/><!-- No value needed --> </Phase> <Phase name="4"> <Trains rusted="2" limitStep="2"/> diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java index 4973f4b..eac056d 100644 --- a/rails/game/GameManager.java +++ b/rails/game/GameManager.java @@ -3,30 +3,22 @@ package rails.game; import java.io.*; import java.lang.reflect.Constructor; -import java.text.SimpleDateFormat; import java.util.*; import org.apache.log4j.Logger; import org.apache.log4j.NDC; import rails.algorithms.RevenueManager; -import rails.common.DisplayBuffer; -import rails.common.GuiDef; -import rails.common.GuiHints; -import rails.common.LocalText; -import rails.common.parser.Config; -import rails.common.parser.ConfigurableComponentI; -import rails.common.parser.ConfigurationException; -import rails.common.parser.GameOption; -import rails.common.parser.Tag; +import rails.common.*; +import rails.common.parser.*; import rails.game.action.*; import rails.game.correct.*; import rails.game.move.*; import rails.game.special.SpecialPropertyI; import rails.game.special.SpecialTokenLay; -import rails.game.specific._1856.CGRFormationRound; import rails.game.state.*; -import rails.util.*; +import rails.util.GameFileIO; +import rails.util.Util; /** * This class manages the playing rounds by supervising all implementations of @@ -46,7 +38,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { protected Class<? extends OperatingRound> operatingRoundClass = OperatingRound.class; protected Class<? extends ShareSellingRound> shareSellingRoundClass - = ShareSellingRound.class; + = ShareSellingRound.class; // Variable UI Class names protected String gameUIManagerClassName = GuiDef.getDefaultClassName(GuiDef.ClassName.GAME_UI_MANAGER); @@ -68,7 +60,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { // map of correctionManagers protected Map<CorrectionType, CorrectionManagerI> correctionManagers = new HashMap<CorrectionType, CorrectionManagerI>(); - + protected String gameName; protected Map<String, String> gameOptions; @@ -87,7 +79,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { new HashMap<String, Portfolio> (); protected IntegerState playerCertificateLimit - = new IntegerState ("PlayerCertificateLimit", 0); + = new IntegerState ("PlayerCertificateLimit", 0); protected int currentNumberOfOperatingRounds = 1; protected boolean skipFirstStockRound = false; protected boolean showCompositeORNumber = true; @@ -103,7 +95,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { protected boolean reloading = false; protected EnumMap<GameDef.Parm, Object> gameParameters - = new EnumMap<GameDef.Parm, Object>(GameDef.Parm.class); + = new EnumMap<GameDef.Parm, Object>(GameDef.Parm.class); /** * Current round should not be set here but from within the Round classes. @@ -228,7 +220,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { // TODO: Move that to a better place protected Map<String, Object> objectStorage = new HashMap<String, Object>(); protected Map<String, Integer> storageIds = new HashMap<String, Integer>(); - + protected static Logger log = Logger.getLogger(GameManager.class.getPackage().getName()); @@ -276,11 +268,11 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { optionParameters = null; optionNameParameters = optionTag.getAttributeAsString("parm"); - if (optionNameParameters != null) { - optionParameters = optionNameParameters.split(","); - } + if (optionNameParameters != null) { + optionParameters = optionNameParameters.split(","); + } optionName = GameOption.constructParametrisedName ( - optionName, optionParameters); + optionName, optionParameters); if (gameOptions.containsKey(optionName)) continue; @@ -365,20 +357,20 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { Tag orderTag = orTag.getChild("OperatingOrder"); if (orderTag != null) { - dynamicOperatingOrder = orderTag.getAttributeAsBoolean("dynamic", - dynamicOperatingOrder); + dynamicOperatingOrder = orderTag.getAttributeAsBoolean("dynamic", + dynamicOperatingOrder); } - + Tag emergencyTag = orTag.getChild("EmergencyTrainBuying"); if (emergencyTag != null) { setGameParameter (GameDef.Parm.EMERGENCY_MUST_BUY_CHEAPEST_TRAIN, - emergencyTag.getAttributeAsBoolean("mustBuyCheapestTrain", + emergencyTag.getAttributeAsBoolean("mustBuyCheapestTrain", GameDef.Parm.EMERGENCY_MUST_BUY_CHEAPEST_TRAIN.defaultValueAsBoolean())); setGameParameter (GameDef.Parm.EMERGENCY_MAY_ALWAYS_BUY_NEW_TRAIN, - emergencyTag.getAttributeAsBoolean("mayAlwaysBuyNewTrain", + emergencyTag.getAttributeAsBoolean("mayAlwaysBuyNewTrain", GameDef.Parm.EMERGENCY_MAY_ALWAYS_BUY_NEW_TRAIN.defaultValueAsBoolean())); setGameParameter (GameDef.Parm.EMERGENCY_MAY_BUY_FROM_COMPANY, - emergencyTag.getAttributeAsBoolean("mayBuyFromCompany", + emergencyTag.getAttributeAsBoolean("mayBuyFromCompany", GameDef.Parm.EMERGENCY_MAY_BUY_FROM_COMPANY.defaultValueAsBoolean())); } } @@ -396,7 +388,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { + ssrClassName, e); } } - + /* Max. % of shares of one company that a player may hold */ Tag shareLimitTag = gameParmTag.getChild("PlayerShareLimit"); if (shareLimitTag != null) { @@ -765,7 +757,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { return String.valueOf(absoluteORNumber.intValue()); } } - + public int getAbsoluteORNumber () { return absoluteORNumber.intValue(); } @@ -802,8 +794,8 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { // check if other companies can be dumped createRound (shareSellingRoundClass, interruptedRound) - .start(player, cashToRaise, cashNeedingCompany, - !problemDumpOtherCompanies || forcedSellingCompanyDump); + .start(player, cashToRaise, cashNeedingCompany, + !problemDumpOtherCompanies || forcedSellingCompanyDump); // the last parameter indicates if the dump of other companies is allowed, either this is explicit or // the action does not require that check } @@ -1009,8 +1001,8 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { //&& currentRound.get().getClass() != CGRFormationRound.class && possibleActions.contains(RepayLoans.class) && (!possibleActions.contains(action.getClass()) - || (action.getClass() == NullAction.class - && ((NullAction)action).getMode() != NullAction.DONE))) { + || (action.getClass() == NullAction.class + && ((NullAction)action).getMode() != NullAction.DONE))) { // Insert "Done" log.debug("Action DONE inserted"); getCurrentRound().process(new NullAction (NullAction.DONE)); @@ -1025,13 +1017,13 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { // FOR BACKWARDS COMPATIBILITY boolean doProcess = true; if (skipNextDone) { - if (action instanceof NullAction - && ((NullAction)action).getMode() == NullAction.DONE) { - if (currentRound.get() instanceof OperatingRound - && ((OperatingRound)currentRound.get()).getStep() == skippedStep) { - doProcess = false; - } - } + if (action instanceof NullAction + && ((NullAction)action).getMode() == NullAction.DONE) { + if (currentRound.get() instanceof OperatingRound + && ((OperatingRound)currentRound.get()).getStep() == skippedStep) { + doProcess = false; + } + } } skipNextDone = false; skippedStep = null; @@ -1141,17 +1133,17 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { return gameSaver.saveGame(file, displayErrorMessage, errorMessageKey); } /** - * tries to reload the current game + * tries to reload the current game * executes the additional action(s) - */ + */ protected boolean reload(GameAction reloadAction) { log.info("Reloading started"); - + /* Use gameLoader to load the game data */ GameFileIO gameLoader = new GameFileIO(); String filepath = reloadAction.getFilepath(); gameLoader.loadGameData(filepath); - + /* followed by actions and comments */ try{ gameLoader.loadActionsAndComments(); @@ -1161,19 +1153,19 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { } log.debug("Starting to compare loaded actions"); - + /* gameLoader actions get compared to the executed actions of the current game */ List<PossibleAction> savedActions = gameLoader.getActions(); - + setReloading(true); - + // Check size if (savedActions.size() < executedActions.size()) { DisplayBuffer.add(LocalText.getText("LoadFailed", - "loaded file has less actions than current game")); + "loaded file has less actions than current game")); return true; } - + // Check action identity int index = 0; PossibleAction executedAction; @@ -1201,14 +1193,14 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { } } index++; - } + } } catch (Exception e) { log.error("Reload failed", e); DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); return true; } - - + + setReloading(false); finishLoading(); @@ -1320,7 +1312,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { msgContinue = LocalText.getText("gameOverPlaySetOfORs"); else msgContinue = LocalText.getText("gameOverPlayOnlyOR"); - String msg = LocalText.getText("MaxedSharePriceDisplayText", + String msg = LocalText.getText("MaxedSharePriceDisplayText", company.getName(), Bank.format(space.getPrice()), msgContinue); @@ -1349,10 +1341,10 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { public boolean isDynamicOperatingOrder() { - return dynamicOperatingOrder; - } + return dynamicOperatingOrder; + } - /* (non-Javadoc) + /* (non-Javadoc) * @see rails.game.GameManagerI#isGameOver() */ public boolean isGameOver() { @@ -1666,7 +1658,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { return false; } } - + public void setGuiParameter (GuiDef.Parm key, boolean value) { guiParameters.put (key, value); } @@ -1848,43 +1840,43 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { return new ArrayList<PublicCompanyI>(operatingCompanies.values()); } - public boolean isReloading() { - return reloading; - } - - public void setReloading(boolean reloading) { - this.reloading = reloading; - } - - public void setSkipDone (GameDef.OrStep step) { - skipNextDone = true; - skippedStep = step; - } - - /** - * - *@param ascending Boolean to determine if the playerlist will be sorted in ascending or descending order based on their cash - *@return Returns the player at index position 0 that is either the player with the most or least cash depending on sort order. - */ - public Player reorderPlayersByCash (boolean ascending) { - - final boolean _ascending = ascending; - Collections.sort (players, new Comparator<Player>() { - public int compare (Player p1, Player p2) { - return _ascending ? p1.getCash() - p2.getCash() : p2.getCash() - p1.getCash(); - } - }); - - Player player; - for (int i=0; i<players.size(); i++) { - player = players.get(i); - player.setIndex (i); - playerNames.set (i, player.getName()); - log.debug("New player "+i+" is "+player.getName() +" (cash="+Bank.format(player.getCash())+")"); - } - - return players.get(0); - } + public boolean isReloading() { + return reloading; + } + + public void setReloading(boolean reloading) { + this.reloading = reloading; + } + + public void setSkipDone (GameDef.OrStep step) { + skipNextDone = true; + skippedStep = step; + } + + /** + * + *@param ascending Boolean to determine if the playerlist will be sorted in ascending or descending order based on their cash + *@return Returns the player at index position 0 that is either the player with the most or least cash depending on sort order. + */ + public Player reorderPlayersByCash (boolean ascending) { + + final boolean _ascending = ascending; + Collections.sort (players, new Comparator<Player>() { + public int compare (Player p1, Player p2) { + return _ascending ? p1.getCash() - p2.getCash() : p2.getCash() - p1.getCash(); + } + }); + + Player player; + for (int i=0; i<players.size(); i++) { + player = players.get(i); + player.setIndex (i); + playerNames.set (i, player.getName()); + log.debug("New player "+i+" is "+player.getName() +" (cash="+Bank.format(player.getCash())+")"); + } + + return players.get(0); + } public void resetStorage() { objectStorage = new HashMap<String, Object>(); @@ -1898,10 +1890,14 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { storageIds.put(typeName, id + 1); // store next id return id; } - + public Object retrieveObject(String typeName, int id) { return objectStorage.get(typeName + id); } - + + /** Process an action triggered by a phase change. */ + public void processPhaseAction (String name, String value) { + getCurrentRound().processPhaseAction(name, value); + } } diff --git a/rails/game/GameManagerI.java b/rails/game/GameManagerI.java index e9d5936..01253a0 100644 --- a/rails/game/GameManagerI.java +++ b/rails/game/GameManagerI.java @@ -241,7 +241,8 @@ public interface GameManagerI extends MoveableHolder, ConfigurableComponentI { */ public Object retrieveObject(String typeName, int id); - + /** Process an action triggered by a phase change. */ + public void processPhaseAction (String name, String value); } \ No newline at end of file diff --git a/rails/game/OperatingRound.java b/rails/game/OperatingRound.java index 59c1058..957203e 100644 --- a/rails/game/OperatingRound.java +++ b/rails/game/OperatingRound.java @@ -914,14 +914,6 @@ public class OperatingRound extends Round implements Observer { operatingCompany.get().setLastRevenue(amount); operatingCompany.get().setLastRevenueAllocation(revenueAllocation); - /* Seems people don't like this popup... - if (amount == 0 && operatingCompany.get().getNumberOfTrains() == 0) { - DisplayBuffer.add(LocalText.getText("RevenueWithNoTrains", - operatingCompany.get().getName(), - Bank.format(0) )); - } - */ - // Pay any debts from treasury, revenue and/or president's cash // The remaining dividend may be less that the original income amount = executeDeductions (action); diff --git a/rails/game/Phase.java b/rails/game/Phase.java index 448bb51..e509507 100644 --- a/rails/game/Phase.java +++ b/rails/game/Phase.java @@ -8,13 +8,14 @@ import org.apache.log4j.Logger; import rails.common.LocalText; import rails.common.parser.ConfigurationException; import rails.common.parser.Tag; +import rails.util.Util; public class Phase implements PhaseI { protected int index; protected String name; - + protected String realName; protected String colourList = ""; @@ -28,11 +29,11 @@ public class Phase implements PhaseI { protected int numberOfOperatingRounds = 1; protected int offBoardRevenueStep = 1; - + /** New style train limit configuration. */ protected int trainLimitStep = 1; - + protected int privatesRevenueStep = 1; // sfy 1889 protected boolean trainTradingAllowed = false; @@ -51,27 +52,34 @@ public class Phase implements PhaseI { /** Items to close if a phase gets activated */ protected List<Closeable> closedObjects = null; - + /** Train types to rust or obsolete if a phase gets activated */ protected List<TrainCertificateType> rustedTrains; String rustedTrainNames; - + /** Train types to release (make available for buying) if a phase gets activated */ protected List<TrainCertificateType> releasedTrains; String releasedTrainNames; - - private TrainManager trainManager; + + /** Actions for this phase. + * When this phase is activated, the GameManager method phaseAction() will be called, + * which in turn will call the current Round, which is responsible to handle the action. + * <p> + * Set actions have a name and may have a value. */ + protected Map<String, String> actions; + + private GameManagerI gameManager; private Portfolio lastTrainBuyer; protected String extraInfo = ""; - + /** A HashMap to contain phase-dependent parameters * by name and value. */ protected Map<String, String> parameters = null; protected static Logger log = - Logger.getLogger(Phase.class.getPackage().getName()); + Logger.getLogger(Phase.class.getPackage().getName()); public Phase(int index, String name, Phase previousPhase) { this.index = index; @@ -98,7 +106,7 @@ public class Phase implements PhaseI { } } } - + // Real name (as in the printed game) realName = tag.getAttributeAsString("realName", null); @@ -120,8 +128,8 @@ public class Phase implements PhaseI { Tag privatesTag = tag.getChild("Privates"); if (privatesTag != null) { privateSellingAllowed = - privatesTag.getAttributeAsBoolean("sellingAllowed", - privateSellingAllowed); + privatesTag.getAttributeAsBoolean("sellingAllowed", + privateSellingAllowed); privatesClose = privatesTag.getAttributeAsBoolean("close", false); privatesRevenueStep = privatesTag.getAttributeAsInteger("revenueStep", privatesRevenueStep); // sfy 1889 } @@ -130,32 +138,32 @@ public class Phase implements PhaseI { Tag orTag = tag.getChild("OperatingRounds"); if (orTag != null) { numberOfOperatingRounds = - orTag.getAttributeAsInteger("number", - numberOfOperatingRounds); + orTag.getAttributeAsInteger("number", + numberOfOperatingRounds); } // Off-board revenue steps (starts at 1) Tag offBoardTag = tag.getChild("OffBoardRevenue"); if (offBoardTag != null) { offBoardRevenueStep = - offBoardTag.getAttributeAsInteger("step", - offBoardRevenueStep); + offBoardTag.getAttributeAsInteger("step", + offBoardRevenueStep); } - + Tag trainsTag = tag.getChild("Trains"); if (trainsTag != null) { trainLimitStep = trainsTag.getAttributeAsInteger("limitStep", trainLimitStep); rustedTrainNames = trainsTag.getAttributeAsString("rusted", null); releasedTrainNames = trainsTag.getAttributeAsString("released", null); trainTradingAllowed = - trainsTag.getAttributeAsBoolean("tradingAllowed", - trainTradingAllowed); + trainsTag.getAttributeAsBoolean("tradingAllowed", + trainTradingAllowed); oneTrainPerTurn = - trainsTag.getAttributeAsBoolean("onePerTurn", - oneTrainPerTurn); + trainsTag.getAttributeAsBoolean("onePerTurn", + oneTrainPerTurn); oneTrainPerTypePerTurn = - trainsTag.getAttributeAsBoolean("onePerTypePerTurn", - oneTrainPerTypePerTurn); + trainsTag.getAttributeAsBoolean("onePerTypePerTurn", + oneTrainPerTypePerTurn); } Tag loansTag = tag.getChild("Loans"); @@ -173,6 +181,17 @@ public class Phase implements PhaseI { } } + Tag setTag = tag.getChild("Action"); + if (setTag != null) { + if (actions == null) actions = new HashMap<String, String>(); + String key = setTag.getAttributeAsString("name"); + if (!Util.hasValue(key)) { + throw new ConfigurationException ("Phase "+name+": <Set> without action name"); + } + String value = setTag.getAttributeAsString("value", null); + actions.put (key, value); + } + // Extra info text(usually related to extra-share special properties) Tag infoTag = tag.getChild("Info"); if (infoTag != null) { @@ -185,16 +204,17 @@ public class Phase implements PhaseI { public void finishConfiguration (GameManagerI gameManager) throws ConfigurationException { - - trainManager = gameManager.getTrainManager(); + + this.gameManager = gameManager; + TrainManager trainManager = gameManager.getTrainManager(); TrainCertificateType type; - + if (rustedTrainNames != null) { rustedTrains = new ArrayList<TrainCertificateType>(2); for (String typeName : rustedTrainNames.split(",")) { type = trainManager.getCertTypeByName(typeName); if (type == null) { - throw new ConfigurationException (" Unknown rusted train type '"+typeName+"' for phase '"+name+"'"); + throw new ConfigurationException (" Unknown rusted train type '"+typeName+"' for phase '"+name+"'"); } rustedTrains.add(type); type.setPermanent(false); @@ -206,7 +226,7 @@ public class Phase implements PhaseI { for (String typeName : releasedTrainNames.split(",")) { type = trainManager.getCertTypeByName(typeName); if (type == null) { - throw new ConfigurationException (" Unknown released train type '"+typeName+"' for phase '"+name+"'"); + throw new ConfigurationException (" Unknown released train type '"+typeName+"' for phase '"+name+"'"); } releasedTrains.add(type); } @@ -222,20 +242,28 @@ public class Phase implements PhaseI { object.close(); } } - + + TrainManager trainManager = gameManager.getTrainManager(); + if (rustedTrains != null && !rustedTrains.isEmpty()) { for (TrainCertificateType type : rustedTrains) { - trainManager.rustTrainType(type, lastTrainBuyer); + trainManager.rustTrainType(type, lastTrainBuyer); } } - + if (releasedTrains != null && !releasedTrains.isEmpty()) { for (TrainCertificateType type : releasedTrains) { trainManager.makeTrainAvailable(type); } } + + if (actions != null && !actions.isEmpty()) { + for (String actionName : actions.keySet()) { + gameManager.processPhaseAction (actionName, actions.get(actionName)); + } + } } - + public void setLastTrainBuyer(Portfolio lastTrainBuyer) { this.lastTrainBuyer = lastTrainBuyer; } @@ -259,7 +287,7 @@ public class Phase implements PhaseI { public int getTrainLimitStep() { return trainLimitStep; } - + public int getTrainLimitIndex() { return trainLimitStep - 1; } diff --git a/rails/game/PublicCompany.java b/rails/game/PublicCompany.java index 2a9cad6..7c1a3ca 100644 --- a/rails/game/PublicCompany.java +++ b/rails/game/PublicCompany.java @@ -2068,4 +2068,10 @@ public class PublicCompany extends Company implements PublicCompanyI { return ""; } + /** Does the company has a route? + * Currently this is a stub that always returns true. + */ + public boolean hasRoute() { + return true; + } } diff --git a/rails/game/PublicCompanyI.java b/rails/game/PublicCompanyI.java index 63ad78b..71fbd1f 100644 --- a/rails/game/PublicCompanyI.java +++ b/rails/game/PublicCompanyI.java @@ -352,4 +352,7 @@ public interface PublicCompanyI extends CompanyI, CashHolder, TokenHolder { public ModelObject getInGameModel (); public ModelObject getIsClosedModel (); + /** Does the company has a route? */ + public boolean hasRoute(); + } diff --git a/rails/game/Round.java b/rails/game/Round.java index 2358579..9789cef 100644 --- a/rails/game/Round.java +++ b/rails/game/Round.java @@ -9,9 +9,7 @@ import java.util.*; import org.apache.log4j.Logger; -import rails.common.DisplayBuffer; -import rails.common.GuiHints; -import rails.common.LocalText; +import rails.common.*; import rails.game.action.*; import rails.game.move.*; import rails.game.special.SpecialPropertyI; @@ -26,7 +24,7 @@ public abstract class Round implements RoundI { protected GuiHints guiHints = null; protected static Logger log = - Logger.getLogger(Round.class.getPackage().getName()); + Logger.getLogger(Round.class.getPackage().getName()); protected GameManagerI gameManager = null; protected CompanyManagerI companyManager = null; @@ -144,7 +142,7 @@ public abstract class Round implements RoundI { public String getGameOption (String name) { return gameManager.getGameOption(name); } - /* + /* * (non-Javadoc) * * @see rails.game.RoundI#getHelp() @@ -268,13 +266,13 @@ public abstract class Round implements RoundI { PublicCompanyI lastOperatingCompany) { Map<Integer, PublicCompanyI> operatingCompanies = - new TreeMap<Integer, PublicCompanyI>(); + new TreeMap<Integer, PublicCompanyI>(); List<PublicCompanyI> newOperatingCompanies; StockSpaceI space; int key; int minorNo = 0; boolean reorder = gameManager.isDynamicOperatingOrder() - && oldOperatingCompanies != null && lastOperatingCompany != null; + && oldOperatingCompanies != null && lastOperatingCompany != null; int lastOperatingCompanyIndex; if (reorder) { @@ -297,9 +295,9 @@ public abstract class Round implements RoundI { // is ascending. space = company.getCurrentSpace(); key = 1000000 * (999 - space.getPrice()) - + 10000 * (99 - space.getColumn()) - + 100 * (space.getRow()+1) - + space.getStackPosition(company); + + 10000 * (99 - space.getColumn()) + + 100 * (space.getRow()+1) + + space.getStackPosition(company); } else { key = 50 + ++minorNo; } @@ -333,21 +331,21 @@ public abstract class Round implements RoundI { /** Determine sold percentage for floating purposes */ protected int getSoldPercentage (PublicCompanyI company) { - int soldPercentage = 0; - for (PublicCertificateI cert : company.getCertificates()) { - if (certCountsAsSold(cert)) { - soldPercentage += cert.getShare(); - } - } - return soldPercentage; + int soldPercentage = 0; + for (PublicCertificateI cert : company.getCertificates()) { + if (certCountsAsSold(cert)) { + soldPercentage += cert.getShare(); + } + } + return soldPercentage; } /** Can be subclassed for games with special rules */ protected boolean certCountsAsSold (PublicCertificateI cert) { - Portfolio holder = cert.getPortfolio(); - CashHolder owner = holder.getOwner(); - return owner instanceof Player - || holder == pool; + Portfolio holder = cert.getPortfolio(); + CashHolder owner = holder.getOwner(); + return owner instanceof Player + || holder == pool; } /** @@ -391,15 +389,15 @@ public abstract class Round implements RoundI { if (cash > 0) { new CashMove(bank, company, cash); ReportBuffer.add(LocalText.getText("FloatsWithCash", - company.getName(), - Bank.format(cash) )); + company.getName(), + Bank.format(cash) )); } else { ReportBuffer.add(LocalText.getText("Floats", company.getName())); } if (capitalisationMode == PublicCompanyI.CAPITALISE_INCREMENTAL - && company.canHoldOwnShares()) { + && company.canHoldOwnShares()) { List<Certificate> moving = new ArrayList<Certificate>(); for (Certificate ipoCert : ipo.getCertificatesPerCompany( company.getName())) { @@ -413,7 +411,7 @@ public abstract class Round implements RoundI { protected void finishRound() { // Report financials - ReportBuffer.add(""); + ReportBuffer.add(""); for (PublicCompanyI c : companyManager.getAllPublicCompanies()) { if (c.hasFloated() && !c.isClosed()) { ReportBuffer.add(LocalText.getText("Has", c.getName(), @@ -452,13 +450,13 @@ public abstract class Round implements RoundI { // Note: all transferred shares must come from the same old shareholder. protected void transferCertificates(List<? extends Certificate> certs, - Portfolio newHolder) { + Portfolio newHolder) { - for (Certificate cert : certs) { - if (cert != null) { - cert.moveTo(newHolder); - } - } + for (Certificate cert : certs) { + if (cert != null) { + cert.moveTo(newHolder); + } + } } protected void pay (CashHolder from, CashHolder to, int amount) { @@ -540,5 +538,12 @@ public abstract class Round implements RoundI { return autopasses; } + /** A stub for processing actions triggered by a phase change. + * Must be overridden by subclasses that need to process such actions. + * @param name (required) The name of the action to be executed + * @param value (optional) The value of the action to be executed, if applicable + */ + public void processPhaseAction (String name, String value) { + } } diff --git a/rails/game/RoundI.java b/rails/game/RoundI.java index 95fa769..0fdfb07 100644 --- a/rails/game/RoundI.java +++ b/rails/game/RoundI.java @@ -30,5 +30,5 @@ public interface RoundI { public String getRoundName(); - + public void processPhaseAction (String name, String value); } diff --git a/rails/game/specific/_18TN/OperatingRound_18TN.java b/rails/game/specific/_18TN/OperatingRound_18TN.java index f0c682e..f5a3b55 100644 --- a/rails/game/specific/_18TN/OperatingRound_18TN.java +++ b/rails/game/specific/_18TN/OperatingRound_18TN.java @@ -1,26 +1,29 @@ package rails.game.specific._18TN; -import java.util.*; +import java.util.List; import rails.game.*; import rails.game.action.BuyPrivate; +import rails.game.action.SetDividend; import rails.game.state.ArrayListState; public class OperatingRound_18TN extends OperatingRound { - + private ArrayListState<Player> playersSoldInOR1; - + public OperatingRound_18TN (GameManagerI gameManager) { super (gameManager); } + @Override protected boolean isPrivateSellingAllowed() { - return super.isPrivateSellingAllowed() - // 18TN special - || gameManager.getAbsoluteORNumber() == 1 - && !ownsPrivate(operatingCompany.get()); + return super.isPrivateSellingAllowed() + // 18TN special + || gameManager.getAbsoluteORNumber() == 1 + && !ownsPrivate(operatingCompany.get()); } - + + @Override protected int getPrivateMinimumPrice (PrivateCompanyI privComp) { if (gameManager.getAbsoluteORNumber() == 1 && !getCurrentPhase().isPrivateSellingAllowed()) { @@ -30,7 +33,8 @@ public class OperatingRound_18TN extends OperatingRound { return super.getPrivateMinimumPrice(privComp); } } - + + @Override protected int getPrivateMaximumPrice (PrivateCompanyI privComp) { if (gameManager.getAbsoluteORNumber() == 1 && !getCurrentPhase().isPrivateSellingAllowed()) { @@ -40,38 +44,65 @@ public class OperatingRound_18TN extends OperatingRound { return super.getPrivateMaximumPrice(privComp); } } - + private boolean ownsPrivate (PublicCompanyI company) { List<PrivateCompanyI> privates = company.getPortfolio().getPrivateCompanies(); return privates != null && !privates.isEmpty(); } - + + @Override protected boolean maySellPrivate (Player player) { - return gameManager.getAbsoluteORNumber() != 1 - || !hasPlayerSoldInOR1(player); + return gameManager.getAbsoluteORNumber() != 1 + || !hasPlayerSoldInOR1(player); } - + private boolean hasPlayerSoldInOR1 (Player player) { return playersSoldInOR1 != null && playersSoldInOR1.contains(player); } + @Override public boolean buyPrivate(BuyPrivate action) { - + Player sellingPlayer = null; - + if (gameManager.getAbsoluteORNumber() == 1) { sellingPlayer = (Player)((Portfolio)action.getPrivateCompany().getHolder()).getOwner(); } - + boolean result = super.buyPrivate(action); - + if (result && gameManager.getAbsoluteORNumber() == 1) { if (playersSoldInOR1 == null) playersSoldInOR1 = new ArrayListState<Player>("PlayersSoldPrivateInOR1"); if (!playersSoldInOR1.contains(sellingPlayer)) { playersSoldInOR1.add(sellingPlayer); } } - + return result; } + + @Override + public void processPhaseAction (String name, String value) { + if (name.equalsIgnoreCase("CivilWar")) { + for (PublicCompanyI company : getOperatingCompanies()) { + if (company.hasFloated() && company.getPortfolio().getNumberOfTrains() > 0 + && company.hasRoute()) { + ((PublicCompany_18TN)company).setCivilWar(true); + } + } + } + } + + + @Override + protected void executeSetRevenueAndDividend (SetDividend action) { + + // Save operating company (it may change) + PublicCompany_18TN company = (PublicCompany_18TN) operatingCompany.get(); + + super.executeSetRevenueAndDividend(action); + + // Reset Civil War condition + if (company.isCivilWar()) company.setCivilWar(false); + } } diff --git a/rails/game/specific/_18TN/PublicCompany_18TN.java b/rails/game/specific/_18TN/PublicCompany_18TN.java new file mode 100644 index 0000000..738200c --- /dev/null +++ b/rails/game/specific/_18TN/PublicCompany_18TN.java @@ -0,0 +1,45 @@ +package rails.game.specific._18TN; + +import rails.common.parser.ConfigurationException; +import rails.game.GameManagerI; +import rails.game.PublicCompany; +import rails.game.model.ModelObject; +import rails.game.state.BooleanState; + +public class PublicCompany_18TN extends PublicCompany { + + private BooleanState civilWar; + + + public ModelObject getCivilWar() { + return civilWar; + } + + @Override + public void finishConfiguration(GameManagerI gameManager) + throws ConfigurationException { + + super.finishConfiguration(gameManager); + + civilWar = new BooleanState (name+"_CivilWar", false); + } + + public boolean isCivilWar() { + return civilWar.booleanValue(); + } + + public void setCivilWar(boolean value) { + civilWar.set(value); + } + + /** Don't move the space if the company has one train in the civil war + * (the revenue amount must then be zero) + */ + @Override + public void withhold(int amount) { + if (isCivilWar() && portfolio.getNumberOfTrains() == 1) return; + stockMarket.withhold(this); + } + + +} |