From: <ev...@us...> - 2011-02-03 23:22:56
|
Revision: 1479 http://rails.svn.sourceforge.net/rails/?rev=1479&view=rev Author: evos Date: 2011-02-03 23:22:49 +0000 (Thu, 03 Feb 2011) Log Message: ----------- Fixed bug #3165621: 1889 port token could not be laid. Tile laying code has been generally cleaned up and simplified. Cases where a regular and a special property-originating tile can be laid on the same hex now work correctly (such as in 1899 hex G10 in the saved file provided with the above bug). Modified Paths: -------------- trunk/18xx/rails/game/OperatingRound.java trunk/18xx/rails/game/action/LayTile.java trunk/18xx/rails/game/move/MapChange.java trunk/18xx/rails/game/move/RemoveFromMap.java trunk/18xx/rails/game/specific/_1835/OperatingRound_1835.java trunk/18xx/rails/game/state/HashMapState.java trunk/18xx/rails/ui/swing/ORUIManager.java trunk/18xx/rails/ui/swing/UpgradesPanel.java trunk/18xx/rails/ui/swing/hexmap/GUIHex.java Modified: trunk/18xx/rails/game/OperatingRound.java =================================================================== --- trunk/18xx/rails/game/OperatingRound.java 2011-02-01 17:27:05 UTC (rev 1478) +++ trunk/18xx/rails/game/OperatingRound.java 2011-02-03 23:22:49 UTC (rev 1479) @@ -43,9 +43,9 @@ // Non-persistent lists (are recreated after each user action) protected List<SpecialPropertyI> currentSpecialProperties = null; - protected List<LayTile> currentSpecialTileLays = new ArrayList<LayTile>(); + //protected List<LayTile> currentSpecialTileLays = new ArrayList<LayTile>(); - protected List<LayTile> currentNormalTileLays = new ArrayList<LayTile>(); + //protected List<LayTile> currentNormalTileLays = new ArrayList<LayTile>(); protected HashMapState<String, Integer> tileLaysPerColour = new HashMapState<String, Integer>("tileLaysPerColour"); @@ -419,7 +419,7 @@ // Was a special property used? if (stl != null) { stl.setExercised(); - currentSpecialTileLays.remove(action); + //currentSpecialTileLays.remove(action); log.debug("This was a special tile lay, " + (extra ? "" : " not") + " extra"); @@ -428,14 +428,9 @@ log.debug("This was a normal tile lay"); registerNormalTileLay(tile); } - - setSpecialTileLays(); - log.debug("There are now " + currentSpecialTileLays.size() - + " special tile lay objects"); } - if (tile == null || currentNormalTileLays.isEmpty() - && currentSpecialTileLays.isEmpty()) { + if (tile == null || !areTileLaysPossible()) { nextStep(); } @@ -460,33 +455,34 @@ int oldAllowedNumber = oldAllowedNumberObject.intValue(); if (oldAllowedNumber <= 0) return false; - if (!update) return true; + if (update) updateAllowedTileColours(colour, oldAllowedNumber); + return true; + } - /* - * We will assume that in all cases the following assertions hold: 1. If - * the allowed number for the colour of the just laid tile reaches zero, - * all normal tile lays have been consumed. 2. If any colour is laid, no - * different colours may be laid. THIS MAY NOT BE TRUE FOR ALL GAMES! - */ + /* + * We will assume that in all cases the following assertions hold: 1. If + * the allowed number for the colour of the just laid tile reaches zero, + * all normal tile lays have been consumed. 2. If any colour is laid, no + * different colours may be laid. THIS MAY NOT BE TRUE FOR ALL GAMES! + */ + protected void updateAllowedTileColours (String colour, int oldAllowedNumber) { + if (oldAllowedNumber <= 1) { - for (String key:tileLaysPerColour.viewKeySet()) { - tileLaysPerColour.put(key, new Integer(0)); - } + tileLaysPerColour.clear(); log.debug("No more normal tile lays allowed"); - currentNormalTileLays.clear(); + //currentNormalTileLays.clear();// Shouldn't be needed anymore ?? } else { for (String key:tileLaysPerColour.viewKeySet()) { if (colour.equals(key)) { - tileLaysPerColour.put(colour, new Integer(oldAllowedNumber-1)); + tileLaysPerColour.put(colour, oldAllowedNumber-1); } else { - tileLaysPerColour.put(key, new Integer(0)); + tileLaysPerColour.remove(colour); } } - log.debug((oldAllowedNumber - 1) + " more " + colour - + " tile lays allowed"); + log.debug((oldAllowedNumber - 1) + " additional " + colour + + " tile lays allowed; no other colours"); } - return true; } public boolean layBaseToken(LayBaseToken action) { @@ -1351,7 +1347,7 @@ * method should be called only once per company turn in an OR: at the start * of the tile laying step. */ - protected void getNormalTileLays() { + protected void initNormalTileLays() { // duplicate the phase colours Map<String, Integer> newTileColours = new HashMap<String, Integer>(getCurrentPhase().getTileColours()); @@ -1364,46 +1360,80 @@ tileLaysPerColour.initFromMap(newTileColours); } - protected void setNormalTileLays() { + protected List<LayTile> getNormalTileLays(boolean display) { /* Normal tile lays */ - currentNormalTileLays.clear(); + List<LayTile> currentNormalTileLays = new ArrayList<LayTile>(); + + // Check which colours can still be laid + Map <String, Integer> remainingTileLaysPerColour = new HashMap<String, Integer>(); - // Map<String,Integer> tileLaysPerColour = (Map<String,Integer>)(tileLaysPerColourState.getObject()); - - int sumLays = 0; - for (Integer i: tileLaysPerColour.viewValues()) - sumLays = sumLays + i; - if (sumLays != 0) { - // if (!tileLaysPerColour.isEmpty()) { - currentNormalTileLays.add(new LayTile(tileLaysPerColour.viewMap())); + int lays = 0; + for (String colourName: tileLaysPerColour.viewKeySet()) { + lays = tileLaysPerColour.get(colourName); + if (lays != 0) { + remainingTileLaysPerColour.put(colourName, lays); + } } - + if (!remainingTileLaysPerColour.isEmpty()) { + currentNormalTileLays.add(new LayTile(remainingTileLaysPerColour)); + } + + // NOTE: in a later stage tile lays will be specified per hex or set of hexes. + + if (display) { + int size = currentNormalTileLays.size(); + if (size == 0) { + log.debug("No normal tile lays"); + } else { + for (LayTile tileLay : currentNormalTileLays) { + log.debug("Normal tile lay: " + tileLay.toString()); + } + } + } + return currentNormalTileLays; } /** * Create a List of allowed special tile lays (see LayTile class). This * method should be called before each user action in the tile laying step. */ - protected void setSpecialTileLays() { + protected List<LayTile> getSpecialTileLays(boolean display) { /* Special-property tile lays */ - currentSpecialTileLays.clear(); + List<LayTile> currentSpecialTileLays = new ArrayList<LayTile>(); - if (!operatingCompany.get().canUseSpecialProperties()) return; + if (operatingCompany.get().canUseSpecialProperties()) { - for (SpecialTileLay stl : getSpecialProperties(SpecialTileLay.class)) { - if ( -// stl.getTile() != null && getCurrentPhase().isTileColourAllowed(stl.getTile().getColourName()) && - // if a tile is specified it must have a tile colour currently available - // commented out as it is not required and makes 1856 save files invalid - (stl.isExtra() || !currentNormalTileLays.isEmpty())) { - // If the special tile lay is not extra, it is only allowed if - // normal tile lays are also (still) allowed - currentSpecialTileLays.add(new LayTile(stl)); + 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 + && checkNormalTileLay(stl.getTile(), false)) { + 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; } + + protected boolean areTileLaysPossible() { + return !tileLaysPerColour.isEmpty() + || !getSpecialTileLays(false).isEmpty(); + } protected void setNormalTokenLays() { @@ -2307,7 +2337,7 @@ if (noMapMode) { nextStep (GameDef.OrStep.LAY_TOKEN); } else { - getNormalTileLays(); // new: only called once per turn ? + initNormalTileLays(); // new: only called once per turn ? setStep (GameDef.OrStep.LAY_TRACK); } } @@ -2321,13 +2351,8 @@ possibleActions.add(new LayBaseToken (operatingCompany.get().getHomeHex())); forced = true; } else { - setNormalTileLays(); - setSpecialTileLays(); - log.debug("Normal tile lays: " + currentNormalTileLays.size()); - log.debug("Special tile lays: " + currentSpecialTileLays.size()); - - possibleActions.addAll(currentNormalTileLays); - possibleActions.addAll(currentSpecialTileLays); + possibleActions.addAll(getNormalTileLays(true)); + possibleActions.addAll(getSpecialTileLays(true)); possibleActions.add(new NullAction(NullAction.SKIP)); } Modified: trunk/18xx/rails/game/action/LayTile.java =================================================================== --- trunk/18xx/rails/game/action/LayTile.java 2011-02-01 17:27:05 UTC (rev 1478) +++ trunk/18xx/rails/game/action/LayTile.java 2011-02-03 23:22:49 UTC (rev 1479) @@ -85,6 +85,7 @@ public LayTile(Map<String, Integer> tileColours) { type = GENERIC; setTileColours (tileColours); + // NOTE: tileColours is currently only used for Help purposes. } public LayTile(SpecialTileLay specialProperty) { @@ -100,6 +101,8 @@ tiles.add(tile); } } + + } /** @@ -199,8 +202,10 @@ // Check the map. Sometimes 0 values creep in, and these can't easily // be intercepted in the UI code (see comment at previous method). // TODO This is a dirty fix, but the quickest one too. - for (String colourName : map.keySet()) { - if (map.get(colourName) > 0) tileColours.put(colourName, map.get(colourName)); + if (map != null) { + for (String colourName : map.keySet()) { + if (map.get(colourName) > 0) tileColours.put(colourName, map.get(colourName)); + } } } Modified: trunk/18xx/rails/game/move/MapChange.java =================================================================== --- trunk/18xx/rails/game/move/MapChange.java 2011-02-01 17:27:05 UTC (rev 1478) +++ trunk/18xx/rails/game/move/MapChange.java 2011-02-03 23:22:49 UTC (rev 1479) @@ -45,6 +45,8 @@ public boolean undo() { if (keyExisted) { map.put (key, oldValue); + } else { + map.remove(key); } return true; } Modified: trunk/18xx/rails/game/move/RemoveFromMap.java =================================================================== --- trunk/18xx/rails/game/move/RemoveFromMap.java 2011-02-01 17:27:05 UTC (rev 1478) +++ trunk/18xx/rails/game/move/RemoveFromMap.java 2011-02-03 23:22:49 UTC (rev 1479) @@ -25,9 +25,11 @@ public RemoveFromMap (Map<K, V> map, K key) { + keyExisted = map.containsKey(key); + if (!keyExisted) return; // Nothing to do this.map = map; this.key = key; - this.keyExisted = map.containsKey(key); + this.oldValue = map.get(key); MoveSet.add(this); } @@ -49,7 +51,7 @@ } public String toString() { - return "RemoveFromMap: remove key="+key+" from map"; + return "RemoveFromMap: remove key="+key+" value="+oldValue+" from map"; } } Modified: trunk/18xx/rails/game/specific/_1835/OperatingRound_1835.java =================================================================== --- trunk/18xx/rails/game/specific/_1835/OperatingRound_1835.java 2011-02-01 17:27:05 UTC (rev 1478) +++ trunk/18xx/rails/game/specific/_1835/OperatingRound_1835.java 2011-02-03 23:22:49 UTC (rev 1479) @@ -182,25 +182,42 @@ } @Override - protected void setSpecialTileLays() { + protected List<LayTile> getSpecialTileLays(boolean display) { /* Special-property tile lays */ - currentSpecialTileLays.clear(); + List<LayTile> currentSpecialTileLays = new ArrayList<LayTile>(); - if (!operatingCompany.get().canUseSpecialProperties()) return; + if (operatingCompany.get().canUseSpecialProperties()) { - for (SpecialTileLay stl : getSpecialProperties(SpecialTileLay.class)) { - if (stl.isExtra() || !currentNormalTileLays.isEmpty()) { + 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; + // 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)); + 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; } - @Override public boolean layTile(LayTile action) { Modified: trunk/18xx/rails/game/state/HashMapState.java =================================================================== --- trunk/18xx/rails/game/state/HashMapState.java 2011-02-01 17:27:05 UTC (rev 1478) +++ trunk/18xx/rails/game/state/HashMapState.java 2011-02-03 23:22:49 UTC (rev 1479) @@ -1,8 +1,10 @@ package rails.game.state; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; @@ -58,9 +60,14 @@ } public void clear() { - for (K key:map.keySet()) { - remove(key); + // Two-step process to avoid concurrent modification exception + List<K> keys = new ArrayList<K>(); + for (K key : map.keySet()) { + keys.add(key); } + for (K key : keys) { + remove (key); + } } /** @@ -100,4 +107,8 @@ public Collection<V> viewValues() { return Collections.unmodifiableCollection(map.values()); } + + public boolean isEmpty() { + return map.isEmpty(); + } } Modified: trunk/18xx/rails/ui/swing/ORUIManager.java =================================================================== --- trunk/18xx/rails/ui/swing/ORUIManager.java 2011-02-01 17:27:05 UTC (rev 1478) +++ trunk/18xx/rails/ui/swing/ORUIManager.java 2011-02-03 23:22:49 UTC (rev 1479) @@ -748,13 +748,48 @@ if (selectedHex != null && selectedHex.canFixTile()) { List<LayTile> allowances = map.getTileAllowancesForHex(selectedHex.getHexModel()); - LayTile allowance = allowances.get(0); // TODO Wrong if we have an - // additional special - // property (18AL Lumber - // Terminal) + LayTile allowance = null; + TileI tile = selectedHex.getProvisionalTile(); + if (allowances.size() == 1) { + allowance = allowances.get(0); + } else { + // Check which allowance applies + // We'll restrict to cases where we have both a special property + // and a normal 'blanket' allowance. + // First check which is which. + List<TileI> sp_tiles; + List<MapHex> sp_hexes; + LayTile gen_lt = null; + for (LayTile lt : allowances) { + if (lt.getType() == LayTile.SPECIAL_PROPERTY) { + // Cases where a special property is used include: + // 1. SP refers to specified tiles, (one of) which is chosen: + // (examples: 18AL Lumber Terminal, 1889 Port) + if ((((sp_tiles = lt.getTiles()) != null + && sp_tiles.contains(tile)) + // 2. SP does not refer to specific tiles but it does refer to + // specified hexes, (one of) which is chosen: + // (example: 1830 hex B20) + || (sp_tiles == null + && (sp_hexes = lt.getLocations()) != null) + && sp_hexes.contains(selectedHex.getModel()))) { + allowance = lt; + break; + } + } else { + gen_lt = lt; + } + } + + // Default case: the generic allowance + // TODO It is not clear that all possible cases have been covered yet. + // But at least this works for 1830, 1889 + if (allowance == null) allowance = gen_lt; + + } allowance.setChosenHex(selectedHex.getHexModel()); allowance.setOrientation(selectedHex.getProvisionalTileRotation()); - allowance.setLaidTile(selectedHex.getProvisionalTile()); + allowance.setLaidTile(tile); relayBaseTokens (allowance); @@ -1726,7 +1761,7 @@ upgradePanel.setCancelEnabled(true); break; case SELECT_TILE: - upgradePanel.populate(); + upgradePanel.populate(gameUIManager.getCurrentPhase()); upgradePanel.setDoneEnabled(false); break; case ROTATE_OR_CONFIRM_TILE: Modified: trunk/18xx/rails/ui/swing/UpgradesPanel.java =================================================================== --- trunk/18xx/rails/ui/swing/UpgradesPanel.java 2011-02-01 17:27:05 UTC (rev 1478) +++ trunk/18xx/rails/ui/swing/UpgradesPanel.java 2011-02-03 23:22:49 UTC (rev 1479) @@ -6,6 +6,7 @@ import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; +import java.util.Set; import javax.swing.*; import javax.swing.border.Border; @@ -81,13 +82,14 @@ add(scrollPane); } - public void populate() { + public void populate(PhaseI currentPhase) { if (hexMap == null) hexMap = orUIManager.getMapPanel().getMap(); GUIHex uiHex = hexMap.getSelectedHex(); MapHex hex = uiHex.getHexModel(); orUIManager.tileUpgrades = new ArrayList<TileI>(); List<TileI> tiles; + Set<String> allowedColours = currentPhase.getTileColours().keySet(); for (LayTile layTile : hexMap.getTileAllowancesForHex(hex)) { tiles = layTile.getTiles(); @@ -95,21 +97,16 @@ for (TileI tile : uiHex.getCurrentTile().getValidUpgrades(hex, orUIManager.gameUIManager.getCurrentPhase())) { // Skip if not allowed in LayTile - if (!layTile.isTileColourAllowed(tile.getColourName())) continue; - + //if (!layTile.isTileColourAllowed(tile.getColourName())) continue; + if (!orUIManager.tileUpgrades.contains(tile)) orUIManager.tileUpgrades.add(tile); } } else { for (TileI tile : tiles) { - // Skip if not allowed in LayTile - if (layTile.getTileColours().get(tile.getColourName()) < 1) continue; + // Skip if colour is not allowed yet + if (!allowedColours.contains(tile.getColourName())) continue; - // special check: does the tile increase the colour number? - // this avoids that a special tile lay down or equalgrades existing tiles - // TODO EV: I'm not sure if this is a necessary precaution. - if (!layTile.isTileColourAllowed(tile.getColourName())) continue; - if (!orUIManager.tileUpgrades.contains(tile)) orUIManager.tileUpgrades.add(tile); } @@ -327,6 +324,7 @@ } } + // NOTE: NOT USED private void setSelectedCorrectionToken() { if (correctionTokenLabels == null || correctionTokenLabels.isEmpty()) return; int index = -1; @@ -475,7 +473,8 @@ super(tokenIcon); this.token = token; } - + + // NOTE: NOT USED TokenI getToken() { return token; } Modified: trunk/18xx/rails/ui/swing/hexmap/GUIHex.java =================================================================== --- trunk/18xx/rails/ui/swing/hexmap/GUIHex.java 2011-02-01 17:27:05 UTC (rev 1478) +++ trunk/18xx/rails/ui/swing/hexmap/GUIHex.java 2011-02-03 23:22:49 UTC (rev 1479) @@ -871,5 +871,9 @@ hexMap.repaint(getBounds()); } } + + public String toString () { + return getName() + " (" + currentTile.getName() + ")"; + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |