From: Erik V. <ev...@us...> - 2011-07-29 15:59:40
|
data/1826/Game.xml | 3 + data/1830/Game.xml | 3 + data/1835/Game.xml | 4 + data/1851/Game.xml | 3 + data/1856/Game.xml | 4 + data/1870/Game.xml | 3 + data/1880/Game.xml | 4 + data/1889/Game.xml | 4 + data/18AL/Game.xml | 3 + data/18EU/Game.xml | 4 + data/18GA/Game.xml | 3 + data/18Kaas/Game.xml | 3 + data/18Scan/Game.xml | 3 + data/18TN/Game.xml | 4 + data/18VA/Game.xml | 3 + rails/game/GameDef.java | 5 +- rails/game/GameManager.java | 16 +++++- rails/game/OperatingRound.java | 100 +++++++++++++++++++++++++++------------- rails/game/action/BuyTrain.java | 4 - 19 files changed, 134 insertions(+), 42 deletions(-) New commits: commit c0f2c89243a2a47b50ae4e494ab53c8abf71ec49 Author: Erik Vos <eri...@xs...> Date: Fri Jul 29 17:49:02 2011 +0200 Configured emergency train buying rules in all remaining games. diff --git a/data/1826/Game.xml b/data/1826/Game.xml index b757188..9877cbc 100644 --- a/data/1826/Game.xml +++ b/data/1826/Game.xml @@ -22,6 +22,9 @@ <StockRound> <NoSaleInFirstSR/> </StockRound> + <OperatingRound> + <EmergencyTrainBuying mustBuyCheapestTrain="yes" mayBuyFromCompany="yes"/> + </OperatingRound> </GameParameters> <GuiClasses> </GuiClasses> diff --git a/data/1851/Game.xml b/data/1851/Game.xml index 7c2ba99..282329d 100644 --- a/data/1851/Game.xml +++ b/data/1851/Game.xml @@ -15,6 +15,9 @@ <StockRound sequence="SellBuy"> <NoSaleIfNotOperated/> </StockRound> + <OperatingRound> + <EmergencyTrainBuying mustBuyCheapestTrain="yes" mayBuyFromCompany="yes"/> + </OperatingRound> </GameParameters> <EndOfGame> <Bankruptcy/> diff --git a/data/1870/Game.xml b/data/1870/Game.xml old mode 100755 new mode 100644 index dd7f49b..bd7a6dc --- a/data/1870/Game.xml +++ b/data/1870/Game.xml @@ -14,6 +14,9 @@ <StockRound> <NoSaleInFirstSR/> </StockRound> + <OperatingRound> + <EmergencyTrainBuying mustBuyCheapestTrain="yes" mayBuyFromCompany="no"/> + </OperatingRound> </GameParameters> <EndOfGame> <Bankruptcy/> diff --git a/data/1880/Game.xml b/data/1880/Game.xml index a0e5e04..d451ad6 100644 --- a/data/1880/Game.xml +++ b/data/1880/Game.xml @@ -11,7 +11,9 @@ <StockRound class="rails.game.specific._1880.StockRound_1880" sequence="SellBuy"> <NoSaleInFirstSR/> </StockRound> - <OperatingRound class="rails.game.specific._1880.OperatingRound_1880"/> + <OperatingRound class="rails.game.specific._1880.OperatingRound_1880"> + <EmergencyTrainBuying mayBuyFromCompany="no"/> + </OperatingRound> </GameParameters> <GuiClasses> <StatusWindow class="rails.ui.swing.StatusWindow"/> diff --git a/data/1889/Game.xml b/data/1889/Game.xml index f3e70d9..71ed798 100644 --- a/data/1889/Game.xml +++ b/data/1889/Game.xml @@ -36,7 +36,9 @@ <StockRound sequence="SellBuyOrBuySell"> <NoSaleInFirstSR/> </StockRound> - <OperatingRound class="rails.game.specific._1889.OperatingRound_1889"/> + <OperatingRound class="rails.game.specific._1889.OperatingRound_1889"> + <EmergencyTrainBuying mustBuyCheapestTrain="yes" mayBuyFromCompany="no"/> + </OperatingRound> </GameParameters> <EndOfGame> <ForcedSelling CompanyDump="no"/> diff --git a/data/18AL/Game.xml b/data/18AL/Game.xml old mode 100755 new mode 100644 index 6e4b89a..fff9d7c --- a/data/18AL/Game.xml +++ b/data/18AL/Game.xml @@ -18,6 +18,9 @@ <StockRound> <NoSaleInFirstSR/> </StockRound> + <OperatingRound> + <EmergencyTrainBuying mustBuyCheapestTrain="yes" mayBuyFromCompany="no"/> + </OperatingRound> </GameParameters> <GuiClasses> <ORUIManager class="rails.ui.swing.gamespecific._18AL.ORUIManager_18AL"/> diff --git a/data/18EU/Game.xml b/data/18EU/Game.xml index 652f382..682d668 100644 --- a/data/18EU/Game.xml +++ b/data/18EU/Game.xml @@ -16,7 +16,9 @@ <NoSaleInFirstSR/> <NoSaleIfNotOperated/> </StockRound> - <OperatingRound class="rails.game.specific._18EU.OperatingRound_18EU"/> + <OperatingRound class="rails.game.specific._18EU.OperatingRound_18EU"> + <EmergencyTrainBuying mustBuyCheapestTrain="no" mayBuyFromCompany="yes"/> + </OperatingRound> <PlayerShareLimit percentage="60"/> <BankPoolLimit percentage="50"/> <TreasuryShareLimit percentage="80"/> diff --git a/data/18GA/Game.xml b/data/18GA/Game.xml index 9611fa8..2335f43 100644 --- a/data/18GA/Game.xml +++ b/data/18GA/Game.xml @@ -23,6 +23,9 @@ <StockRound> <NoSaleInFirstSR/> </StockRound> + <OperatingRound> + <EmergencyTrainBuying mustBuyCheapestTrain="yes" mayBuyFromCompany="no"/> + </OperatingRound> </GameParameters> <GuiClasses> </GuiClasses> diff --git a/data/18Kaas/Game.xml b/data/18Kaas/Game.xml index 086dd36..bb269d6 100644 --- a/data/18Kaas/Game.xml +++ b/data/18Kaas/Game.xml @@ -17,6 +17,9 @@ <StockRound> <NoSaleInFirstSR/> </StockRound> + <OperatingRound> + <EmergencyTrainBuying mustBuyCheapestTrain="yes" mayBuyFromCompany="yes"/> + </OperatingRound> </GameParameters> <EndOfGame> <Bankruptcy/> diff --git a/data/18Scan/Game.xml b/data/18Scan/Game.xml index 05de9dd..735d96e 100644 --- a/data/18Scan/Game.xml +++ b/data/18Scan/Game.xml @@ -14,6 +14,9 @@ <StockRound sequence="SellBuy"> <NoSaleIfNotOperated/> </StockRound> + <OperatingRound> + <EmergencyTrainBuying mustBuyCheapestTrain="no" mayBuyFromCompany="yes"/> + </OperatingRound> </GameParameters> <GuiClasses> </GuiClasses> diff --git a/data/18TN/Game.xml b/data/18TN/Game.xml index 7ead0ad..31ddc16 100644 --- a/data/18TN/Game.xml +++ b/data/18TN/Game.xml @@ -23,7 +23,9 @@ <StockRound> <NoSaleInFirstSR/> </StockRound> - <OperatingRound class="rails.game.specific._18TN.OperatingRound_18TN"/> + <OperatingRound class="rails.game.specific._18TN.OperatingRound_18TN"> + <EmergencyTrainBuying mustBuyCheapestTrain="yes" mayBuyFromCompany="no"/> + </OperatingRound> </GameParameters> <EndOfGame> <Bankruptcy/> diff --git a/data/18VA/Game.xml b/data/18VA/Game.xml index cd53d42..0beb1ee 100644 --- a/data/18VA/Game.xml +++ b/data/18VA/Game.xml @@ -29,6 +29,9 @@ <StockRound> <NoSaleInFirstSR/> </StockRound> + <OperatingRound> + <EmergencyTrainBuying mustBuyCheapestTrain="no" mayBuyFromCompany="yes"/> + </OperatingRound> </GameParameters> <EndOfGame> <Bankruptcy/> commit b5441119c92dc9d9efed4310d618cab5671627e1 Author: Erik Vos <eri...@xs...> Date: Fri Jul 29 15:38:30 2011 +0200 Added configuration options for train emergency buying. Until now, all games followed the 1830 rules to determine what trains can be bought if a company has no trains and insufficient cash, and for what price. Three configuration options have been added in a new <EmergencyTrainBuying> tag under <OperatingRound>, all having valid values "yes" and "no". All cases only apply to train buys needing additional president cash. (Buys with own company cash are allowed according to the standard train buying rules.) 1. mustBuyCheapestTrain [from the Bank, with president cash]: Yes (default): 1830/Kaas, 1856/70, 18AL/GA/TN, 1826 No: 1835, 18EU/VA/Scan. 2. mayAlwaysBuyNewTrain [if not enough cash for a new train but enough for a used train]: Yes: 1835 [Disputed; disapproving players are advised to ignore the new train offer] No (default): all other games 3. mayBuyFromCompany [up to list price]: Yes (default): 1830/Kaas, 1835, 18EU/VA/Scan, 1826 No: 1856/70, 18AL/GA/TN Only 1830, 1835 and 1856 have been updated so far. diff --git a/data/1830/Game.xml b/data/1830/Game.xml old mode 100755 new mode 100644 index 521f2cd..ecdb701 --- a/data/1830/Game.xml +++ b/data/1830/Game.xml @@ -42,6 +42,9 @@ <StockRound> <NoSaleInFirstSR/> </StockRound> + <OperatingRound> + <EmergencyTrainBuying mustBuyCheapestTrain="no" mayBuyFromCompany="yes"/> + </OperatingRound> </GameParameters> <EndOfGame> <Bankruptcy/> diff --git a/data/1835/Game.xml b/data/1835/Game.xml index 8b11f9f..cc54f5b 100644 --- a/data/1835/Game.xml +++ b/data/1835/Game.xml @@ -19,7 +19,9 @@ <NoSaleInFirstSR/> <NoSaleIfNotOperated/> </StockRound> - <OperatingRound class="rails.game.specific._1835.OperatingRound_1835"/> + <OperatingRound class="rails.game.specific._1835.OperatingRound_1835"> + <EmergencyTrainBuying mustBuyCheapestTrain="no" mayAlwaysBuyNewTrain="yes" mayBuyFromCompany="yes"/> + </OperatingRound> </GameParameters> <GuiClasses> <StatusWindow class="rails.ui.swing.gamespecific._1835.StatusWindow_1835"/> diff --git a/data/1856/Game.xml b/data/1856/Game.xml old mode 100755 new mode 100644 index b89892a..87706d8 --- a/data/1856/Game.xml +++ b/data/1856/Game.xml @@ -16,7 +16,9 @@ <NoSaleInFirstSR/> <NoSaleOfJustBoughtShare/> </StockRound> - <OperatingRound class="rails.game.specific._1856.OperatingRound_1856"/> + <OperatingRound class="rails.game.specific._1856.OperatingRound_1856"> + <EmergencyTrainBuying mustBuyCheapestTrain="yes" mayBuyFromCompany="no"/> + </OperatingRound> <ShareSellingRound class="rails.game.specific._1856.ShareSellingRound_1856"/> <PlayerShareLimit percentage="60"/> <BankPoolLimit percentage="50"/> diff --git a/rails/game/GameDef.java b/rails/game/GameDef.java index 485d5a8..18dff88 100644 --- a/rails/game/GameDef.java +++ b/rails/game/GameDef.java @@ -19,7 +19,10 @@ public class GameDef { FIXED_PRICE_TRAINS_BETWEEN_PRESIDENTS(false), SKIP_FIRST_STOCK_ROUND(false), NO_SALE_OF_JUST_BOUGHT_CERT(false), - REMOVE_TRAIN_BEFORE_SR(false); + REMOVE_TRAIN_BEFORE_SR(false), + EMERGENCY_MUST_BUY_CHEAPEST_TRAIN (true), + EMERGENCY_MAY_ALWAYS_BUY_NEW_TRAIN (false), + EMERGENCY_MAY_BUY_FROM_COMPANY (true); private Object defaultValue; diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java index 7c5a11a..d476d79 100644 --- a/rails/game/GameManager.java +++ b/rails/game/GameManager.java @@ -352,8 +352,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { Tag orTag = gameParmTag.getChild("OperatingRound"); if (orTag != null) { String orClassName = - orTag.getAttributeAsString("class", - "rails.game.OperatingRound"); + orTag.getAttributeAsString("class", "rails.game.OperatingRound"); try { operatingRoundClass = Class.forName(orClassName).asSubclass( @@ -368,6 +367,19 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { dynamicOperatingOrder = orderTag.getAttributeAsBoolean("dynamic", dynamicOperatingOrder); } + + Tag emergencyTag = orTag.getChild("EmergencyTrainBuying"); + if (emergencyTag != null) { + setGameParameter (GameDef.Parm.EMERGENCY_MUST_BUY_CHEAPEST_TRAIN, + emergencyTag.getAttributeAsBoolean("mustBuyCheapestTrain", + GameDef.Parm.EMERGENCY_MUST_BUY_CHEAPEST_TRAIN.defaultValueAsBoolean())); + setGameParameter (GameDef.Parm.EMERGENCY_MAY_ALWAYS_BUY_NEW_TRAIN, + emergencyTag.getAttributeAsBoolean("mayAlwaysBuyNewTrain", + GameDef.Parm.EMERGENCY_MAY_ALWAYS_BUY_NEW_TRAIN.defaultValueAsBoolean())); + setGameParameter (GameDef.Parm.EMERGENCY_MAY_BUY_FROM_COMPANY, + emergencyTag.getAttributeAsBoolean("mayBuyFromCompany", + GameDef.Parm.EMERGENCY_MAY_BUY_FROM_COMPANY.defaultValueAsBoolean())); + } } // ShareSellingRound class diff --git a/rails/game/OperatingRound.java b/rails/game/OperatingRound.java index 6c80717..59c1058 100644 --- a/rails/game/OperatingRound.java +++ b/rails/game/OperatingRound.java @@ -2684,9 +2684,11 @@ public class OperatingRound extends Round implements Observer { if (cash == 0 && hasTrains) return; boolean canBuyTrainNow = canBuyTrainNow(); - boolean presidentMayHelp = !hasTrains && operatingCompany.get().mustOwnATrain(); - TrainI cheapestTrain = null; - int costOfCheapestTrain = 0; + boolean mustBuyTrain = !hasTrains && operatingCompany.get().mustOwnATrain(); + boolean emergency = false; + + SortedMap<Integer, TrainI> newEmergencyTrains = new TreeMap<Integer, TrainI>(); + SortedMap<Integer, TrainI> usedEmergencyTrains = new TreeMap<Integer, TrainI>(); TrainManager trainMgr = gameManager.getTrainManager(); // First check if any more trains may be bought from the Bank @@ -2712,13 +2714,11 @@ public class OperatingRound extends Round implements Observer { if (cost <= cash) { if (canBuyTrainNow) { BuyTrain action = new BuyTrain(train, type, ipo, cost); - action.setForcedBuyIfNoRoute(presidentMayHelp); // TEMPORARY + action.setForcedBuyIfNoRoute(mustBuyTrain); // TEMPORARY possibleActions.add(action); } - } else if (costOfCheapestTrain == 0 - || cost < costOfCheapestTrain) { - cheapestTrain = train; - costOfCheapestTrain = cost; + } else if (mustBuyTrain) { + newEmergencyTrains.put(cost, train); } } @@ -2747,7 +2747,7 @@ public class OperatingRound extends Round implements Observer { if (reducedPrice > cash) continue; BuyTrain bt = new BuyTrain(train, ipo, reducedPrice); bt.setSpecialProperty(stb); - bt.setForcedBuyIfNoRoute(presidentMayHelp); // TEMPORARY + bt.setForcedBuyIfNoRoute(mustBuyTrain); // TEMPORARY possibleActions.add(bt); } @@ -2764,21 +2764,52 @@ public class OperatingRound extends Round implements Observer { cost = train.getCost(); if (cost <= cash) { BuyTrain bt = new BuyTrain(train, pool, cost); - bt.setForcedBuyIfNoRoute(presidentMayHelp); // TEMPORARY + bt.setForcedBuyIfNoRoute(mustBuyTrain); // TEMPORARY possibleActions.add(bt); - } else if (costOfCheapestTrain == 0 - || cost < costOfCheapestTrain) { - cheapestTrain = train; - costOfCheapestTrain = cost; + } else if (mustBuyTrain) { + usedEmergencyTrains.put(cost, train); } } - if (!hasTrains && possibleActions.getType(BuyTrain.class).isEmpty() - && cheapestTrain != null && presidentMayHelp) { - BuyTrain bt = new BuyTrain(cheapestTrain, - cheapestTrain.getHolder(), costOfCheapestTrain); - bt.setPresidentMustAddCash(costOfCheapestTrain - cash); - bt.setForcedBuyIfNoRoute(presidentMayHelp); // TODO TEMPORARY - possibleActions.add(bt); + + emergency = mustBuyTrain && possibleActions.getType(BuyTrain.class).isEmpty(); + + // If we must buy a train and haven't found one yet, the president must add cash. + if (emergency + // Some people think it's allowed in 1835 to buy a new train with president cash + // even if the company has enough cash to buy a used train. + // Players who think differently can ignore that extra option. + || getGameParameterAsBoolean (GameDef.Parm.EMERGENCY_MAY_ALWAYS_BUY_NEW_TRAIN) + && !newEmergencyTrains.isEmpty()) { + if (getGameParameterAsBoolean (GameDef.Parm.EMERGENCY_MUST_BUY_CHEAPEST_TRAIN)) { + // Find the cheapest one + // Assume there is always one available from IPO + int cheapestTrainCost = newEmergencyTrains.firstKey(); + TrainI cheapestTrain = newEmergencyTrains.get(cheapestTrainCost); + if (!usedEmergencyTrains.isEmpty() + && usedEmergencyTrains.firstKey() < cheapestTrainCost) { + cheapestTrainCost = usedEmergencyTrains.firstKey(); + cheapestTrain = usedEmergencyTrains.get(cheapestTrainCost); + } + BuyTrain bt = new BuyTrain(cheapestTrain, + cheapestTrain.getHolder(), cheapestTrainCost); + bt.setPresidentMustAddCash(cheapestTrainCost - cash); + bt.setForcedBuyIfNoRoute(mustBuyTrain); // TODO TEMPORARY + possibleActions.add(bt); + } else { + // All possible bank trains are buyable + for (TrainI train : newEmergencyTrains.values()) { + BuyTrain bt = new BuyTrain(train, ipo, train.getCost()); + bt.setPresidentMustAddCash(train.getCost() - cash); + bt.setForcedBuyIfNoRoute(mustBuyTrain); // TODO TEMPORARY + possibleActions.add(bt); + } + for (TrainI train : usedEmergencyTrains.values()) { + BuyTrain bt = new BuyTrain(train, pool, train.getCost()); + bt.setPresidentMustAddCash(train.getCost() - cash); + bt.setForcedBuyIfNoRoute(mustBuyTrain); // TODO TEMPORARY + possibleActions.add(bt); + } + } } } @@ -2791,6 +2822,7 @@ public class OperatingRound extends Round implements Observer { Portfolio pf; int index; int numberOfPlayers = getNumberOfPlayers(); + int presidentCash = operatingCompany.get().getPresident().getCash(); // Set up a list per player of presided companies List<List<PublicCompanyI>> companiesPerPlayer = @@ -2809,7 +2841,7 @@ public class OperatingRound extends Round implements Observer { // first int currentPlayerIndex = getCurrentPlayer().getIndex(); for (int i = currentPlayerIndex; i < currentPlayerIndex - + numberOfPlayers; i++) { + + numberOfPlayers; i++) { companies = companiesPerPlayer.get(i % numberOfPlayers); for (PublicCompanyI company : companies) { pf = company.getPortfolio(); @@ -2817,23 +2849,29 @@ public class OperatingRound extends Round implements Observer { for (TrainI train : trains) { if (train.isObsolete() || !train.isTradeable()) continue; + bt = null; if (i != currentPlayerIndex - //&& trainMgr.buyAtFaceValueBetweenDifferentPresidents() - && getGameParameterAsBoolean(GameDef.Parm.FIXED_PRICE_TRAINS_BETWEEN_PRESIDENTS) + && getGameParameterAsBoolean(GameDef.Parm.FIXED_PRICE_TRAINS_BETWEEN_PRESIDENTS) || operatingCompany.get().mustTradeTrainsAtFixedPrice() || company.mustTradeTrainsAtFixedPrice()) { + // Fixed price if ((cash >= train.getCost()) && (operatingCompany.get().mayBuyTrainType(train))) { bt = new BuyTrain(train, pf, train.getCost()); } else { continue; } - } else { + } else if (cash > 0 + || emergency + && getGameParameterAsBoolean (GameDef.Parm.EMERGENCY_MAY_BUY_FROM_COMPANY)) { bt = new BuyTrain(train, pf, 0); + + // In some games the president may add extra cash up to the list price + if (emergency && cash < train.getCost()) { + bt.setPresidentMayAddCash(Math.min(train.getCost() - cash, + presidentCash)); + } } - if (presidentMayHelp && cash < train.getCost()) { - bt.setPresidentMayAddCash(train.getCost() - cash); - } - possibleActions.add(bt); + if (bt != null) possibleActions.add(bt); } } } @@ -2857,7 +2895,7 @@ public class OperatingRound extends Round implements Observer { /** Reports if a tile lay is allowed by a certain company on a certain hex * <p> - * This method can be used both in retricting possible actions + * This method can be used both in restricting possible actions * and in validating submitted actions. * <p> Currently, only a few standard checks are included. * This method can be extended to perform other generic checks, @@ -2874,7 +2912,7 @@ public class OperatingRound extends Round implements Observer { /** Reports if a token lay is allowed by a certain company on a certain hex and city * <p> - * This method can be used both in retricting possible actions + * This method can be used both in restricting possible actions * and in validating submitted actions. * <p> Currently, only a few standard checks are included. * This method can be extended to perform other generic checks, diff --git a/rails/game/action/BuyTrain.java b/rails/game/action/BuyTrain.java index 59bdc80..f63641f 100644 --- a/rails/game/action/BuyTrain.java +++ b/rails/game/action/BuyTrain.java @@ -33,8 +33,8 @@ public class BuyTrain extends PossibleORAction { /** Obsolete, but left in for backwards compatibility of saved files */ private boolean forcedExchange = false; - private boolean presidentMustAddCash = false; - private boolean presidentMayAddCash = false; + private boolean presidentMustAddCash = false; // If buying from the bank + private boolean presidentMayAddCash = false; // If buying from a company private int presidentCashToAdd = 0; transient private SpecialTrainBuy specialProperty = null; |