From: Erik V. <ev...@us...> - 2011-12-06 21:01:50
|
data/1835/CompanyManager.xml | 6 rails/game/OperatingRound.java | 154 ++++++++++++--------- rails/game/specific/_1835/OperatingRound_1835.java | 42 +---- 3 files changed, 102 insertions(+), 100 deletions(-) New commits: commit 8912fbffa6d8f12e9067da0d497eebc949e17f1c Merge: 96ae931 31d0618 Author: Erik Vos <eri...@xs...> Date: Tue Dec 6 21:58:11 2011 +0100 Merge branch 'master' of ssh://rails.git.sourceforge.net/gitroot/rails/rails Conflicts: rails/game/OperatingRound.java commit 96ae93123cd0273ad7681345928a7aac2889b8e0 Author: Erik Vos <eri...@xs...> Date: Fri Dec 2 23:14:24 2011 +0100 1825 minors have 10%, not 20% shares diff --git a/data/1825/CompanyManager.xml b/data/1825/CompanyManager.xml index 2ae65c9..7be3e79 100644 --- a/data/1825/CompanyManager.xml +++ b/data/1825/CompanyManager.xml @@ -23,14 +23,14 @@ <CompanyType name="Minor" class="rails.game.specific._1825.PublicCompany_1825"> <Float percentage="40"/> <StockPrice par="no"/> - <ShareUnit percentage="20"/> + <ShareUnit percentage="10"/> <BaseTokens> <!-- HomeBase lay options: "whenStarted", "whenFloated", "firstOR" (default) --> <HomeBase lay="firstOR"/> <LayCost method="sequence" cost="0"/> </BaseTokens> - <Certificate type="President" shares="2"/> - <Certificate shares="1" number="3"/> + <Certificate type="President" shares="4"/> + <Certificate shares="2" number="3"/> <Trains limit="4,3"/> <!--TileLays> <Number colour="yellow" number="2" phase="1,2,3,4"></Number></TileLays--> commit 5c7069a25a41a974fb25001ed3145cce979f0832 Author: Erik Vos <eri...@xs...> Date: Tue Dec 6 21:20:37 2011 +0100 Further changes to fix special tile lays. Special tile lay prevalidation has been factored out into a separate method to allow OperatingRound subclasses to add game-specific checks. diff --git a/data/1830/CompanyManager.xml b/data/1830/CompanyManager.xml index 3623f7f..5c2fe0e 100644 --- a/data/1830/CompanyManager.xml +++ b/data/1830/CompanyManager.xml @@ -40,7 +40,7 @@ <Blocking hex="B20"/> <SpecialProperties> <SpecialProperty condition="ifOwnedByCompany" when="tileLayingStep" class="rails.game.special.SpecialTileLay"> - <SpecialTileLay location="B20" extra="yes" free="yes"/> + <SpecialTileLay colour="yellow" location="B20" extra="yes" free="yes"/> </SpecialProperty> </SpecialProperties> </Company> diff --git a/data/1835/CompanyManager.xml b/data/1835/CompanyManager.xml index 7127047..58db0e2 100644 --- a/data/1835/CompanyManager.xml +++ b/data/1835/CompanyManager.xml @@ -46,10 +46,10 @@ <Company name="OBB" longname="Ostbayerische Bahn" type="Private" basePrice="120" revenue="10"> <SpecialProperties> <SpecialProperty condition="ifOwnedByPlayer" when="tileLayingStep" class="rails.game.special.SpecialTileLay"> - <SpecialTileLay location="M15" extra="yes" free="yes" /> + <SpecialTileLay location="M15" colour="yellow" extra="yes" free="yes" /> </SpecialProperty> <SpecialProperty condition="ifOwnedByPlayer" when="tileLayingStep" class="rails.game.special.SpecialTileLay"> - <SpecialTileLay location="M17" extra="yes" free="yes" /> + <SpecialTileLay location="M17" colour="yellow" extra="yes" free="yes" /> </SpecialProperty> </SpecialProperties> <ClosingConditions> @@ -61,7 +61,7 @@ <Company name="PfB" longname="Pfalzbahnen" type="Private" basePrice="150" revenue="15"> <SpecialProperties> <SpecialProperty condition="ifOwnedByPlayer" when="tileLayingStep" class="rails.game.special.SpecialTileLay"> - <SpecialTileLay location="L6" extra="yes" free="yes" /> + <SpecialTileLay location="L6" colour="green" extra="yes" free="yes" /> </SpecialProperty> <SpecialProperty condition="ifOwnedByPlayer" when="orTurn" class="rails.game.special.SpecialTokenLay"> <SpecialTokenLay location="L6" extra="yes" free="yes"/> diff --git a/rails/game/OperatingRound.java b/rails/game/OperatingRound.java index f754fa8..d799ad9 100644 --- a/rails/game/OperatingRound.java +++ b/rails/game/OperatingRound.java @@ -1688,56 +1688,10 @@ public class OperatingRound extends Round implements Observer { if (operatingCompany.get().canUseSpecialProperties()) { - // What colours can be laid in the current phase? - List<String> phaseColours = getCurrentPhase().getTileColours(); - for (SpecialTileLay stl : getSpecialProperties(SpecialTileLay.class)) { - if (stl.isExtra() - // If the special tile lay is not extra, it is only allowed if - // normal tile lays are also (still) allowed - || checkNormalTileLay(stl.getTile(), false)) { - LayTile lt = new LayTile(stl); - TileI tile = stl.getTile(); - - // Which tile colour(s) are specified explicitly... - String[] stlc = stl.getTileColours(); - if ((stlc == null || stlc.length == 0) && tile != null) { - // ... or implicitly - stlc = new String[] {tile.getColourName()}; - } - - // Which of the specified tile colours can really be laid now? - List<String> layableColours; - if (stlc == null) { - layableColours = phaseColours; - } else { - layableColours = new ArrayList<String>(); - for (String colour : stlc) { - if (phaseColours.contains(colour)) layableColours.add(colour); - } - } - // If any locations are specified, check if tile or colour(s) can be laid there. - Map<String, Integer> tc = new HashMap<String, Integer>(); - List<MapHex> hexes = stl.getLocations(); - for (String colour : layableColours) { - if (hexes != null) { - for (MapHex hex : hexes) { - // At least one hex does not have that colour yet - if (hex.getCurrentTile().getColourNumber() + 1 - == Tile.getColourNumberForName(colour)) { - tc.put(colour, 1); - continue; - } - } - } else { - tc.put(colour, 1); - } - } - - if (!tc.isEmpty()) lt.setTileColours(tc); - if (!tc.isEmpty() || hexes == null) currentSpecialTileLays.add(lt); - } + LayTile layTile = new LayTile(stl); + if (validateSpecialTileLay (layTile)) currentSpecialTileLays.add(layTile); } } @@ -1755,6 +1709,94 @@ public class OperatingRound extends Round implements Observer { return currentSpecialTileLays; } + /** Prevalidate a special tile lay. + * <p>During prevalidation, the action may be updated (i.e. restricted). + * TODO <p>Note: The name of this method may suggest that it can also be used for postvalidation + * (i.e. to validate the action after the player has selected it). This is not yet the case, + * but it is conceivable that this method can be extended to cover postvalidation as well. + * Postvalidation is really a different process, which in this context has not yet been considered in detail. + * @param layTile A LayTile object embedding a SpecialTileLay property. + * Any other LayTile objects are rejected. The object may be changed by this method. + * @return TRUE if allowed. + */ + protected boolean validateSpecialTileLay (LayTile layTile) { + + if (layTile == null) return false; + + SpecialProperty sp = layTile.getSpecialProperty(); + if (sp == null || !(sp instanceof SpecialTileLay)) return false; + + SpecialTileLay stl = (SpecialTileLay) sp; + + if (!stl.isExtra() + // If the special tile lay is not extra, it is only allowed if + // normal tile lays are also (still) allowed + && !checkNormalTileLay(stl.getTile(), false)) return false; + + TileI tile = stl.getTile(); + + // What colours can be laid in the current phase? + List<String> phaseColours = getCurrentPhase().getTileColours(); + + // Which tile colour(s) are specified explicitly... + String[] stlc = stl.getTileColours(); + if ((stlc == null || stlc.length == 0) && tile != null) { + // ... or implicitly + stlc = new String[] {tile.getColourName()}; + } + + // Which of the specified tile colours can really be laid now? + List<String> layableColours; + if (stlc == null) { + layableColours = phaseColours; + } else { + layableColours = new ArrayList<String>(); + for (String colour : stlc) { + if (phaseColours.contains(colour)) layableColours.add(colour); + } + if (layableColours.isEmpty()) return false; + } + + // If any locations are specified, check if tile or colour(s) can be laid there. + Map<String, Integer> tc = new HashMap<String, Integer>(); + List<MapHex> hexes = stl.getLocations(); + List<MapHex> remainingHexes = null; + List<String> remainingColours = null; + int cash = operatingCompany.get().getCash(); + + if (hexes != null) { + remainingHexes = new ArrayList<MapHex> (); + remainingColours = new ArrayList<String>(); + } + for (String colour : layableColours) { + if (hexes != null) { + for (MapHex hex : hexes) { + // Check if the company can pay any costs + if (cash < hex.getTileCost()) continue; + + // At least one hex does not have that colour yet + if (hex.getCurrentTile().getColourNumber() + 1 + == Tile.getColourNumberForName(colour)) { + tc.put(colour, 1); + remainingColours.add(colour); + remainingHexes.add(hex); + continue; + } + } + } else { + tc.put(colour, 1); + } + } + if (!tc.isEmpty()) layTile.setTileColours(tc); + + if (hexes != null) { + if (remainingHexes.isEmpty()) return false; + layTile.setLocations(remainingHexes); + } + + return true; + } + protected boolean areTileLaysPossible() { return !tileLaysPerColour.isEmpty() || !getSpecialTileLays(false).isEmpty(); diff --git a/rails/game/action/LayTile.java b/rails/game/action/LayTile.java index a5d0ad2..074e0ea 100644 --- a/rails/game/action/LayTile.java +++ b/rails/game/action/LayTile.java @@ -181,6 +181,11 @@ public class LayTile extends PossibleORAction { return locations; } + public void setLocations(List<MapHex> locations) { + this.locations = locations; + if (locations != null) buildLocationNameString(); + } + public int getType() { return type; } diff --git a/rails/game/special/SpecialTileLay.java b/rails/game/special/SpecialTileLay.java index b7fd63a..3e1dea6 100644 --- a/rails/game/special/SpecialTileLay.java +++ b/rails/game/special/SpecialTileLay.java @@ -8,7 +8,7 @@ import rails.common.LocalText; import rails.common.parser.ConfigurationException; import rails.common.parser.Tag; import rails.game.*; -import rails.util.*; +import rails.util.Util; public class SpecialTileLay extends SpecialProperty { @@ -25,9 +25,9 @@ public class SpecialTileLay extends SpecialProperty { * Default is same colours as is allowed in a a normal tile lay. * Don't use if specific tiles are specified! */ protected String[] tileColours = null; - + @Override - public void configureFromXML(Tag tag) throws ConfigurationException { + public void configureFromXML(Tag tag) throws ConfigurationException { super.configureFromXML(tag); Tag tileLayTag = tag.getChild("SpecialTileLay"); @@ -41,43 +41,43 @@ public class SpecialTileLay extends SpecialProperty { tileNumber = tileLayTag.getAttributeAsInteger("tile", 0); - String coloursString = tag.getAttributeAsString("colour"); + String coloursString = tileLayTag.getAttributeAsString("colour"); if (Util.hasValue(coloursString)) { tileColours = coloursString.split(","); } - + name = tileLayTag.getAttributeAsString("name"); extra = tileLayTag.getAttributeAsBoolean("extra", extra); free = tileLayTag.getAttributeAsBoolean("free", free); connected = tileLayTag.getAttributeAsBoolean("connected", connected); /* sfy 1889 extension */ closingValue = - tileLayTag.getAttributeAsInteger("closingValue", closingValue); + tileLayTag.getAttributeAsInteger("closingValue", closingValue); if (tileNumber > 0) { - description = LocalText.getText("LayNamedTileInfo", - tileNumber, - name != null ? name : "", - locationCodes, - (extra ? LocalText.getText("extra"):LocalText.getText("notExtra")), - (free ? LocalText.getText("noCost") : LocalText.getText("normalCost")), - (connected ? LocalText.getText("connected") : LocalText.getText("unconnected")) - /* sfy 1889 extension */ - ); + description = LocalText.getText("LayNamedTileInfo", + tileNumber, + name != null ? name : "", + locationCodes, + (extra ? LocalText.getText("extra"):LocalText.getText("notExtra")), + (free ? LocalText.getText("noCost") : LocalText.getText("normalCost")), + (connected ? LocalText.getText("connected") : LocalText.getText("unconnected")) + /* sfy 1889 extension */ + ); } else { - description = LocalText.getText("LayTileInfo", - locationCodes, - (extra ? LocalText.getText("extra"):LocalText.getText("notExtra")), - (free ? LocalText.getText("noCost") : LocalText.getText("normalCost")), + description = LocalText.getText("LayTileInfo", + locationCodes, + (extra ? LocalText.getText("extra"):LocalText.getText("notExtra")), + (free ? LocalText.getText("noCost") : LocalText.getText("normalCost")), (connected ? LocalText.getText("connected") : LocalText.getText("unconnected")) /* sfy 1889 extension */ - ); + ); } } @Override - public void finishConfiguration (GameManagerI gameManager) + public void finishConfiguration (GameManagerI gameManager) throws ConfigurationException { TileManager tmgr = gameManager.getTileManager(); @@ -93,7 +93,7 @@ public class SpecialTileLay extends SpecialProperty { hex = mmgr.getHex(hexName); if (hex == null) throw new ConfigurationException("Location " + hexName - + " does not exist"); + + " does not exist"); locations.add(hex); } @@ -140,18 +140,20 @@ public class SpecialTileLay extends SpecialProperty { } @Override - public String toString() { - return "SpecialTileLay comp=" + originalCompany.getName() + " hex=" - + locationCodes + " extra=" + extra + " cost=" + free + " connected=" + connected; + public String toString() { + return "SpecialTileLay comp=" + originalCompany.getName() + + " hex=" + locationCodes + + " colour="+tileColours + + " extra=" + extra + " cost=" + free + " connected=" + connected; } @Override - public String toMenu() { - return description; + public String toMenu() { + return description; } @Override - public String getInfo() { - return description; + public String getInfo() { + return description; } } diff --git a/rails/game/specific/_1835/OperatingRound_1835.java b/rails/game/specific/_1835/OperatingRound_1835.java index 6f4d312..4513f32 100644 --- a/rails/game/specific/_1835/OperatingRound_1835.java +++ b/rails/game/specific/_1835/OperatingRound_1835.java @@ -10,7 +10,8 @@ import rails.game.action.DiscardTrain; import rails.game.action.LayTile; import rails.game.move.CashMove; import rails.game.move.MapChange; -import rails.game.special.*; +import rails.game.special.ExchangeForShare; +import rails.game.special.SpecialPropertyI; import rails.game.state.BooleanState; public class OperatingRound_1835 extends OperatingRound { @@ -183,42 +184,17 @@ public class OperatingRound_1835 extends OperatingRound { } @Override - protected List<LayTile> getSpecialTileLays(boolean display) { + protected boolean validateSpecialTileLay (LayTile layTile) { - /* Special-property tile lays */ - List<LayTile> currentSpecialTileLays = new ArrayList<LayTile>(); + if (!super.validateSpecialTileLay(layTile)) return false; - if (operatingCompany.get().canUseSpecialProperties()) { + // Exclude the second OBB free tile if the first was laid in this round + if (layTile.getSpecialProperty().getLocationNameString().matches("M1(7|9)") + && hasLaidExtraOBBTile.booleanValue()) return false; - for (SpecialTileLay stl : getSpecialProperties(SpecialTileLay.class)) { - if (stl.isExtra() - // If the special tile lay is not extra, it is only allowed if - // normal tile lays are also (still) allowed - || stl.getTile() != null - && getCurrentPhase().isTileColourAllowed(stl.getTile().getColourName())) { - - // Exclude the second OBB free tile if the first was laid in this round - if (stl.getLocationNameString().matches("M1(7|9)") - && hasLaidExtraOBBTile.booleanValue()) continue; - - currentSpecialTileLays.add(new LayTile(stl)); - } - } - } - - if (display) { - int size = currentSpecialTileLays.size(); - if (size == 0) { - log.debug("No special tile lays"); - } else { - for (LayTile tileLay : currentSpecialTileLays) { - log.debug("Special tile lay: " + tileLay.toString()); - } - } - } - - return currentSpecialTileLays; + return true; } + @Override public boolean layTile(LayTile action) { |