diff --git a/.travis.yml b/.travis.yml index 2139c98771c..0062790f77c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,8 @@ before_deploy: - chmod +x ./.travis/setup && ./.travis/setup ## Add the travis build number to the game engine version - GAME_CONFIG=game_engine.properties -- ENGINE_VERSION=$(grep "engine_version" $GAME_CONFIG | sed 's/.*= *//g') +- VERSION_SOURCE=src/main/java/games/strategy/engine/config/GameEnginePropertyFileReader.java +- ENGINE_VERSION=$(grep "public static final String GAME_ENGINE_VERSION *=" $VERSION_SOURCE | sed 's/.*="//g' | cut -d\" -f2) - export TAGGED_VERSION="$ENGINE_VERSION.$TRAVIS_BUILD_NUMBER" - sed -i "s/engine_version.*/engine_version = $TAGGED_VERSION/" $GAME_CONFIG ## Run the gradle release build process - creates the installers diff --git a/game_engine.properties b/game_engine.properties index 09039fbb576..7b46bbb9384 100644 --- a/game_engine.properties +++ b/game_engine.properties @@ -1,4 +1,4 @@ -engine_version = 1.9.0.0 +engine_version = 1.9.1.0 ## Map_List_File # URL if the value begins with http, otherwise assumed to be a file. This file lists which maps are available diff --git a/old/triplea_1_9_0_0.jar b/old/triplea_1_9_0_0.jar new file mode 100644 index 00000000000..919e3690f1c Binary files /dev/null and b/old/triplea_1_9_0_0.jar differ diff --git a/src/main/java/games/strategy/engine/ClientFileSystemHelper.java b/src/main/java/games/strategy/engine/ClientFileSystemHelper.java index 1fac99418ba..b24e9f22082 100644 --- a/src/main/java/games/strategy/engine/ClientFileSystemHelper.java +++ b/src/main/java/games/strategy/engine/ClientFileSystemHelper.java @@ -34,8 +34,9 @@ public static File getRootFolder() { } final String tripleaJarNameWithEngineVersion = getTripleaJarWithEngineVersionStringPath(); - if (fileName.contains("triplea_" + tripleaJarNameWithEngineVersion + ".jar!")) { - return getRootFolderRelativeToJar(fileName, tripleaJarNameWithEngineVersion); + final int locn = fileName.indexOf("triplea_" + tripleaJarNameWithEngineVersion + ".jar!"); + if (locn >= 0) { + return new File(fileName.substring(0, locn - 1)); } return getRootRelativeToClassFile(fileName); @@ -68,7 +69,8 @@ private static String getTripleaJarWithEngineVersionStringPath() { private static File getRootFolderRelativeToJar(final String fileName, final String tripleaJarName) { final String subString = - fileName.substring("file:/".length() - (SystemProperties.isWindows() ? 0 : 1), fileName.indexOf(tripleaJarName) - 1); + fileName.substring("file:/".length() - (SystemProperties.isWindows() ? 0 : 1), + fileName.indexOf(tripleaJarName) - 1); final File f = new File(subString).getParentFile(); if (!f.exists()) { throw new IllegalStateException("File not found:" + f); @@ -97,7 +99,10 @@ private static File getRootRelativeToClassFile(final String fileName) { return f; } - private static boolean folderContainsGamePropsFile(final File folder) { + private static boolean folderContainsGamePropsFile(File folder) { + if (!folder.isDirectory()) { + folder = new File(folder.toString().substring(5)); + } final File[] files = folder.listFiles(); final List fileNames = Arrays.asList(files).stream().map(file -> file.getName()).collect(Collectors.toList()); diff --git a/src/main/java/games/strategy/engine/config/GameEnginePropertyFileReader.java b/src/main/java/games/strategy/engine/config/GameEnginePropertyFileReader.java index 28952271bcc..cc943598e47 100644 --- a/src/main/java/games/strategy/engine/config/GameEnginePropertyFileReader.java +++ b/src/main/java/games/strategy/engine/config/GameEnginePropertyFileReader.java @@ -18,19 +18,23 @@ public class GameEnginePropertyFileReader implements PropertyReader { public static final String GAME_ENGINE_PROPERTY_FILE = "game_engine.properties"; + public static final String GAME_ENGINE_VERSION = "1.9.1"; private final File propertyFile; public GameEnginePropertyFileReader() { this(new File(GAME_ENGINE_PROPERTY_FILE)); } - /** This constructor here for testing purposes, use the simple no-arg constructor instead */ + /* This constructor here for testing purposes, use the simple no-arg constructor instead. */ protected GameEnginePropertyFileReader(final File propertyFile) { this.propertyFile = propertyFile; } @Override public String readProperty(final GameEngineProperty propertyKey) { + if (propertyKey == GameEngineProperty.ENGINE_VERSION) { + return GAME_ENGINE_VERSION; + } try (FileInputStream inputStream = new FileInputStream(propertyFile)) { final Properties props = new Properties(); props.load(inputStream); diff --git a/src/main/java/games/strategy/engine/framework/EngineVersionProperties.java b/src/main/java/games/strategy/engine/framework/EngineVersionProperties.java index 2847d4cf69d..d2874195b17 100644 --- a/src/main/java/games/strategy/engine/framework/EngineVersionProperties.java +++ b/src/main/java/games/strategy/engine/framework/EngineVersionProperties.java @@ -99,7 +99,8 @@ private String getOutOfDateMessage() { text.append("

A new version of TripleA is out. Please Update TripleA!

"); text.append("
Your current version: ").append(ClientContext.engineVersion().getFullVersion()); text.append("
Latest version available for download: ").append(getLatestVersionOut()); - text.append("

Click to download:
Click to download:
").append(getLinkToDownloadLatestVersion()).append(""); text.append("
Backup Mirror: ").append(getLinkAltToDownloadLatestVersion()).append(""); diff --git a/src/main/java/games/strategy/triplea/attachments/UnitAttachment.java b/src/main/java/games/strategy/triplea/attachments/UnitAttachment.java index 7ecf664cdc9..51c043c5592 100644 --- a/src/main/java/games/strategy/triplea/attachments/UnitAttachment.java +++ b/src/main/java/games/strategy/triplea/attachments/UnitAttachment.java @@ -444,8 +444,8 @@ public void resetCanBeCapturedOnEnteringBy() { public void setWhenCapturedChangesInto(final String value) throws GameParseException { final String[] s = value.split(":"); if (s.length < 5 || (s.length - 1) % 2 != 0) { - throw new GameParseException("whenCapturedChangesInto must have 5 or more values, " - + "playerFrom:playerTo:keepAttributes:unitType:howMany (you may have additional unitType:howMany:unitType:howMany, etc" + throw new GameParseException("whenCapturedChangesInto must have 5 or more values, playerFrom:playerTo:" + + "keepAttributes:unitType:howMany (you may have additional unitType:howMany:unitType:howMany, etc" + thisErrorMsg()); } final PlayerID pfrom = getData().getPlayerList().getPlayerID(s[0]); diff --git a/src/main/java/games/strategy/triplea/delegate/MustFightBattle.java b/src/main/java/games/strategy/triplea/delegate/MustFightBattle.java index 081b61d7bfb..7bdd8155b62 100644 --- a/src/main/java/games/strategy/triplea/delegate/MustFightBattle.java +++ b/src/main/java/games/strategy/triplea/delegate/MustFightBattle.java @@ -513,6 +513,21 @@ public List determineStepStrings(final boolean showFirstRun, final IDele } } } + // See if there any unescorted trns + if (m_battleSite.isWater() && isTransportCasualtiesRestricted()) { + if (Match.someMatch(m_attackingUnits, Matches.UnitIsTransport) + || Match.someMatch(m_defendingUnits, Matches.UnitIsTransport)) { + steps.add(REMOVE_UNESCORTED_TRANSPORTS); + } + } + } + // Air only Units can't attack subs without Destroyers present + if (isAirAttackSubRestricted()) { + final Collection units = new ArrayList<>(m_attackingUnits.size() + m_attackingWaitingToDie.size()); + units.addAll(m_attackingUnits); + if (Match.someMatch(m_attackingUnits, Matches.UnitIsAir) && !canAirAttackSubs(m_defendingUnits, units)) { + steps.add(SUBMERGE_SUBS_VS_AIR_ONLY); + } } // Check if defending subs can submerge before battle if (isSubRetreatBeforeBattle()) { @@ -525,13 +540,6 @@ public List determineStepStrings(final boolean showFirstRun, final IDele steps.add(m_defender.getName() + SUBS_SUBMERGE); } } - // See if there any unescorted trns - if (m_battleSite.isWater() && isTransportCasualtiesRestricted()) { - if (Match.someMatch(m_attackingUnits, Matches.UnitIsTransport) - || Match.someMatch(m_defendingUnits, Matches.UnitIsTransport)) { - steps.add(REMOVE_UNESCORTED_TRANSPORTS); - } - } // if attacker has no sneak attack subs, then defendering sneak attack subs fire first and remove casualties final boolean defenderSubsFireFirst = defenderSubsFireFirst(); if (defenderSubsFireFirst && Match.someMatch(m_defendingUnits, Matches.UnitIsSub)) { @@ -569,16 +577,6 @@ public List determineStepStrings(final boolean showFirstRun, final IDele && (returnFireAgainstDefendingSubs() != ReturnFire.ALL || returnFireAgainstAttackingSubs() != ReturnFire.ALL)) { steps.add(REMOVE_SNEAK_ATTACK_CASUALTIES); } - // Air only Units can't attack subs without Destroyers present - if (isAirAttackSubRestricted()) { - final Collection units = new ArrayList<>(m_attackingUnits.size() + m_attackingWaitingToDie.size()); - units.addAll(m_attackingUnits); - // if(!Match.someMatch(m_attackingUnits, Matches.UnitIsDestroyer) && Match.allMatch(m_attackingUnits, - // Matches.UnitIsAir)) - if (Match.someMatch(m_attackingUnits, Matches.UnitIsAir) && !canAirAttackSubs(m_defendingUnits, units)) { - steps.add(SUBMERGE_SUBS_VS_AIR_ONLY); - } - } // Air Units can't attack subs without Destroyers present if (m_battleSite.isWater() && isAirAttackSubRestricted()) { final Collection units = new ArrayList<>(m_attackingUnits.size() + m_attackingWaitingToDie.size()); @@ -611,9 +609,6 @@ public List determineStepStrings(final boolean showFirstRun, final IDele final Collection units = new ArrayList<>(m_defendingUnits.size() + m_defendingWaitingToDie.size()); units.addAll(m_defendingUnits); units.addAll(m_defendingWaitingToDie); - // if(!Match.someMatch(m_defendingUnits, Matches.UnitIsDestroyer) && Match.someMatch(m_defendingUnits, - // Matches.UnitIsAir) && - // Match.someMatch(m_attackingUnits, Matches.UnitIsSub)) if (Match.someMatch(m_defendingUnits, Matches.UnitIsAir) && !canAirAttackSubs(m_attackingUnits, units)) { steps.add(AIR_DEFEND_NON_SUBS); } @@ -648,6 +643,13 @@ public List determineStepStrings(final boolean showFirstRun, final IDele } } } + // See if there any unescorted trns + if (m_battleSite.isWater() && isTransportCasualtiesRestricted()) { + if (Match.someMatch(m_attackingUnits, Matches.UnitIsTransport) + || Match.someMatch(m_defendingUnits, Matches.UnitIsTransport)) { + steps.add(REMOVE_UNESCORTED_TRANSPORTS); + } + } // if we are a sea zone, then we may not be able to retreat // (ie a sub travelled under another unit to get to the battle site) // or an enemy sub retreated to our sea zone @@ -715,6 +717,22 @@ public void execute(final ExecutionStack stack, final IDelegateBridge bridge) { }); } if (firstRun) { + /** Remove undefended trns */ + if (isTransportCasualtiesRestricted()) { + steps.add(new IExecutable() { + private static final long serialVersionUID = 99989L; + + @Override + public void execute(final ExecutionStack stack, final IDelegateBridge bridge) { + checkUndefendedTransports(bridge, m_defender); + checkUndefendedTransports(bridge, m_attacker); + checkForUnitsThatCanRollLeft(bridge, true); + checkForUnitsThatCanRollLeft(bridge, false); + clearWaitingToDie(bridge); + // ?? This appears to remove both sides undefended transports twice + } + }); + } steps.add(new IExecutable() { private static final long serialVersionUID = -2255284529092427441L; @@ -815,9 +833,24 @@ List getBattleExecutables(final boolean firstRun) { @Override public void execute(final ExecutionStack stack, final IDelegateBridge bridge) { + if (Match.someMatch(m_attackingUnits, Matches.unitHasAttackValueOfAtLeast(1)) + && Match.allMatch(m_defendingUnits, Matches.unitHasDefenseThatIsMoreThanOrEqualTo(1).invert())) { + remove(m_defendingUnits, bridge, m_battleSite, true); + } clearWaitingToDie(bridge); } }); + /** Submerge subs if -vs air only & air restricted from attacking subs */ + if (isAirAttackSubRestricted()) { + steps.add(new IExecutable() { + private static final long serialVersionUID = 99990L; + + @Override + public void execute(final ExecutionStack stack, final IDelegateBridge bridge) { + submergeSubsVsOnlyAir(bridge); + } + }); + } steps.add(new IExecutable() { // not compatible with 0.9.0.2 saved games. this is new for 1.2.6.0 private static final long serialVersionUID = 6387198382888361848L; @@ -865,15 +898,10 @@ public void execute(final ExecutionStack stack, final IDelegateBridge bridge) { // changed to only look at units that can be destroyed in combat, and therefore not include factories, aaguns, // and infrastructure. else if (Match.getMatches(m_defendingUnits, Matches.UnitIsNotInfrastructure).size() == 0) { - if (isTransportCasualtiesRestricted()) { - // If there are undefended attacking transports, determine if they automatically die - checkUndefendedTransports(bridge, m_defender); - } - checkForUnitsThatCanRollLeft(bridge, false); endBattle(bridge); attackerWins(bridge); - } else if (shouldEndBattleDueToMaxRounds() - || (Match.allMatch(m_attackingUnits, Matches.unitHasAttackValueOfAtLeast(1).invert()) + } else if (shouldEndBattleDueToMaxRounds() || + (Match.allMatch(m_attackingUnits, Matches.unitHasAttackValueOfAtLeast(1).invert()) && Match.allMatch(m_defendingUnits, Matches.unitHasDefendValueOfAtLeast(1).invert()))) { endBattle(bridge); nobodyWins(bridge); @@ -1017,31 +1045,6 @@ public void execute(final ExecutionStack stack, final IDelegateBridge bridge) { checkSuicideUnits(bridge); } }); - /** Remove undefended trns */ - if (isTransportCasualtiesRestricted()) { - steps.add(new IExecutable() { - private static final long serialVersionUID = 99989L; - - @Override - public void execute(final ExecutionStack stack, final IDelegateBridge bridge) { - checkUndefendedTransports(bridge, m_defender); - checkUndefendedTransports(bridge, m_attacker); - checkForUnitsThatCanRollLeft(bridge, true); - checkForUnitsThatCanRollLeft(bridge, false); - } - }); - } - /** Submerge subs if -vs air only & air restricted from attacking subs */ - if (isAirAttackSubRestricted()) { - steps.add(new IExecutable() { - private static final long serialVersionUID = 99990L; - - @Override - public void execute(final ExecutionStack stack, final IDelegateBridge bridge) { - submergeSubsVsOnlyAir(bridge); - } - }); - } final ReturnFire returnFireAgainstAttackingSubs = returnFireAgainstAttackingSubs(); final ReturnFire returnFireAgainstDefendingSubs = returnFireAgainstDefendingSubs(); if (defenderSubsFireFirst()) { diff --git a/src/main/java/games/strategy/triplea/delegate/NonFightingBattle.java b/src/main/java/games/strategy/triplea/delegate/NonFightingBattle.java index 15ba6de1cfd..59014fe6870 100644 --- a/src/main/java/games/strategy/triplea/delegate/NonFightingBattle.java +++ b/src/main/java/games/strategy/triplea/delegate/NonFightingBattle.java @@ -25,7 +25,7 @@ import games.strategy.util.Util; /** - * Battle in which no fighting occurs. + * Battle in which no fighting occurs. * Example is a naval invasion into an empty country, * but the battle cannot be fought until a naval battle * occurs. @@ -161,6 +161,9 @@ public void unitsLostInPrecedingBattle(final IBattle battle, final Collection> dependencies) { for (final Unit holder : dependencies.keySet()) { final Collection transporting = dependencies.get(holder); diff --git a/src/main/java/games/strategy/triplea/delegate/PlaceDelegate.java b/src/main/java/games/strategy/triplea/delegate/PlaceDelegate.java index 4494c44c083..6eb7bcae685 100644 --- a/src/main/java/games/strategy/triplea/delegate/PlaceDelegate.java +++ b/src/main/java/games/strategy/triplea/delegate/PlaceDelegate.java @@ -6,7 +6,7 @@ /** * Logic for placing units. - *

+ * * Known limitations. * Doesnt take into account limits on number of factories that can be produced. * The situation where one has two non original factories a,b each with production 2. diff --git a/src/main/java/games/strategy/triplea/ui/BattleDisplay.java b/src/main/java/games/strategy/triplea/ui/BattleDisplay.java index 5eba0d909ca..e547b7a03a4 100644 --- a/src/main/java/games/strategy/triplea/ui/BattleDisplay.java +++ b/src/main/java/games/strategy/triplea/ui/BattleDisplay.java @@ -95,7 +95,7 @@ public class BattleDisplay extends JPanel { private final PlayerID m_attacker; private final Territory m_location; private final GameData m_data; - private final JButton m_actionButton = new JButton(""); + private final JButton actionButton = new JButton(""); private final BattleModel m_defenderModel; private final BattleModel m_attackerModel; private BattleStepsPanel m_steps; @@ -153,7 +153,7 @@ public BattleDisplay(final GameData data, final Territory territory, final Playe } public void cleanUp() { - m_actionButton.setAction(m_nullAction); + actionButton.setAction(m_nullAction); m_steps.deactivate(); m_mapPanel.getUIContext().removeActive(m_steps); m_steps = null; @@ -163,7 +163,7 @@ void takeFocus() { // we want a component on this frame to take focus // so that pressing space will work (since it requires in focused // window). Only seems to be an issue on windows - m_actionButton.requestFocus(); + actionButton.requestFocus(); } public Territory getBattleLocation() { @@ -305,7 +305,7 @@ protected void waitForConfirmation(final String message) { final CountDownLatch continueLatch = new CountDownLatch(1); final AbstractAction buttonAction = SwingAction.of(message, e -> continueLatch.countDown()); - SwingUtilities.invokeLater(() -> m_actionButton.setAction(buttonAction)); + SwingUtilities.invokeLater(() -> actionButton.setAction(buttonAction)); m_mapPanel.getUIContext().addShutdownLatch(continueLatch); // Set a auto-wait expiration if the option is set. @@ -317,7 +317,7 @@ protected void waitForConfirmation(final String message) { public void run() { continueLatch.countDown(); if (continueLatch.getCount() > 0) { - SwingUtilities.invokeLater(() -> m_actionButton.setAction(m_nullAction)); + SwingUtilities.invokeLater(() -> actionButton.setAction(m_nullAction)); } } }, maxWaitTime); @@ -330,14 +330,14 @@ public void run() { } finally { m_mapPanel.getUIContext().removeShutdownLatch(continueLatch); } - SwingUtilities.invokeLater(() -> m_actionButton.setAction(m_nullAction)); + SwingUtilities.invokeLater(() -> actionButton.setAction(m_nullAction)); } public void endBattle(final String message, final Window enclosingFrame) { m_steps.walkToLastStep(); final Action close = SwingAction.of(message + " : (Press Space to Close)", e -> enclosingFrame.setVisible(false)); - SwingUtilities.invokeLater(() -> m_actionButton.setAction(close)); + SwingUtilities.invokeLater(() -> actionButton.setAction(close)); } public void notifyRetreat(final Collection retreating) { @@ -383,7 +383,7 @@ private Territory getSubmerge(final String message) { retreatTo[0] = m_location; latch.countDown(); }); - SwingUtilities.invokeLater(() -> m_actionButton.setAction(action)); + SwingUtilities.invokeLater(() -> actionButton.setAction(action)); SwingUtilities.invokeLater(() -> action.actionPerformed(null)); m_mapPanel.getUIContext().addShutdownLatch(latch); try { @@ -392,7 +392,7 @@ private Territory getSubmerge(final String message) { } finally { m_mapPanel.getUIContext().removeShutdownLatch(latch); } - SwingUtilities.invokeLater(() -> m_actionButton.setAction(m_nullAction)); + SwingUtilities.invokeLater(() -> actionButton.setAction(m_nullAction)); return retreatTo[0]; } @@ -425,17 +425,22 @@ private Territory getRetreatInternal(final String message, final Collection m_actionButton.setAction(action)); + SwingUtilities.invokeLater(() -> actionButton.setAction(action)); SwingUtilities.invokeLater(() -> action.actionPerformed(null)); m_mapPanel.getUIContext().addShutdownLatch(latch); try { @@ -445,7 +450,7 @@ private Territory getRetreatInternal(final String message, final Collection m_actionButton.setAction(m_nullAction)); + SwingUtilities.invokeLater(() -> actionButton.setAction(m_nullAction)); return retreatTo[0]; } @@ -511,7 +516,7 @@ public CasualtyDetails getCasualties(final Collection selectFrom, final Ma final String countStr = isEditMode ? "" : "" + count; final String btnText = hit.getName() + ", press space to select " + countStr + (plural ? " casualties" : " casualty"); - m_actionButton.setAction(new AbstractAction(btnText) { + actionButton.setAction(new AbstractAction(btnText) { private static final long serialVersionUID = -2156028313292233568L; private UnitChooser chooser; private JScrollPane chooserScrollPane; @@ -559,8 +564,8 @@ public void actionPerformed(final ActionEvent e) { final CasualtyDetails response = new CasualtyDetails(killed, damaged, false); casualtyDetails.set(response); m_dicePanel.clear(); - m_actionButton.setEnabled(false); - m_actionButton.setAction(m_nullAction); + actionButton.setEnabled(false); + actionButton.setAction(m_nullAction); continueLatch.countDown(); } } @@ -633,16 +638,16 @@ private void initLayout() { setLayout(new BorderLayout()); add(north, BorderLayout.NORTH); add(diceAndSteps, BorderLayout.CENTER); - add(m_actionButton, BorderLayout.SOUTH); - m_actionButton.setEnabled(false); + add(actionButton, BorderLayout.SOUTH); + actionButton.setEnabled(false); if (!SystemProperties.isMac()) { - m_actionButton.setBackground(Color.lightGray.darker()); - m_actionButton.setForeground(Color.white); + actionButton.setBackground(Color.lightGray.darker()); + actionButton.setForeground(Color.white); } setDefaultWidths(defenderTable); setDefaultWidths(attackerTable); final Action continueAction = SwingAction.of(e -> { - final Action a = m_actionButton.getAction(); + final Action a = actionButton.getAction(); if (a != null) { a.actionPerformed(null); } diff --git a/src/test/java/games/strategy/triplea/delegate/WW2V3_41_Test.java b/src/test/java/games/strategy/triplea/delegate/WW2V3_41_Test.java index f55f14f70a9..885804c133b 100644 --- a/src/test/java/games/strategy/triplea/delegate/WW2V3_41_Test.java +++ b/src/test/java/games/strategy/triplea/delegate/WW2V3_41_Test.java @@ -1005,14 +1005,13 @@ public void testLimitBombardtoNumberOfUnloaded() { assertEquals(2, mfb.getBombardingUnits().size()); // Show that bombard casualties can return fire // Note- the 3 & 2 hits below show default behavior of bombarding at attack strength - // 3= Battleship hitting a 4, 2=Cruiser hitting a 3, 5555=italian infantry missing on 6s, 00= british getting return - // fire on 1. - bridge.setRandomSource(new ScriptedRandomSource(3, 2, 5, 5, 5, 5, 0, 0)); + // 2= Battleship hitting a 3, 2=Cruiser hitting a 3, 15=British infantry hitting once + bridge.setRandomSource(new ScriptedRandomSource(2, 2, 1, 5, 5, 5, 5, 5)); battleDelegate(m_data).setDelegateBridgeAndPlayer(bridge); battleDelegate(m_data).start(); fight(battleDelegate(m_data), eg); // end result should be 2 italian infantry. - assertEquals(2, eg.getUnits().size()); + assertEquals(3, eg.getUnits().size()); } @Test