From e0fb373b3d8a46dc16c7c811801d1176f9739eb2 Mon Sep 17 00:00:00 2001 From: Alexei Svitkine Date: Thu, 19 Dec 2019 20:48:01 -0500 Subject: [PATCH 01/12] Use Java 8's getOrDefault() --- forge-game/src/main/java/forge/game/CardTraitBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-game/src/main/java/forge/game/CardTraitBase.java b/forge-game/src/main/java/forge/game/CardTraitBase.java index 34c2a77edf5..a17f64007ae 100644 --- a/forge-game/src/main/java/forge/game/CardTraitBase.java +++ b/forge-game/src/main/java/forge/game/CardTraitBase.java @@ -73,7 +73,7 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView { } public final String getParamOrDefault(String key, String defaultValue) { - return hasParam(key) ? getParam(key) : defaultValue; + return mapParams.getOrDefault(key, defaultValue); } public String getParam(String key) { From 3d59118b94216f6c924a81942a8518267c3490b8 Mon Sep 17 00:00:00 2001 From: Alexei Svitkine Date: Thu, 19 Dec 2019 20:49:29 -0500 Subject: [PATCH 02/12] Use Sets instead of Lists for card types to avoid slow lookups. --- .../main/java/forge/ai/ComputerUtilCard.java | 2 +- .../java/forge/ai/PlayerControllerAi.java | 9 ++++---- .../src/main/java/forge/card/CardType.java | 22 +++++++++--------- .../forge/game/player/PlayerController.java | 4 ++-- .../util/PlayerControllerForTests.java | 2 +- .../src/main/java/forge/model/FModel.java | 23 ++++++++++--------- .../forge/player/PlayerControllerHuman.java | 2 +- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 13e558ea7a9..61891b7ad87 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -643,7 +643,7 @@ public class ComputerUtilCard { return getMostProminentType(list, CardType.getAllCreatureTypes()); } - public static String getMostProminentType(final CardCollectionView list, final List valid) { + public static String getMostProminentType(final CardCollectionView list, final Collection valid) { if (list.size() == 0) { return ""; } diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index f0d1250cb58..04a9f303832 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -502,12 +502,11 @@ public class PlayerControllerAi extends PlayerController { } @Override - public String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes, boolean isOptional) { + public String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes, boolean isOptional) { String chosen = ComputerUtil.chooseSomeType(player, kindOfType, sa.getParam("AILogic"), invalidTypes); - if (StringUtils.isBlank(chosen) && !validTypes.isEmpty()) - { - chosen = validTypes.get(0); - System.err.println("AI has no idea how to choose " + kindOfType +", defaulting to 1st element: chosen"); + if (StringUtils.isBlank(chosen) && !validTypes.isEmpty()) { + chosen = validTypes.iterator().next(); + System.err.println("AI has no idea how to choose " + kindOfType +", defaulting to arbitrary element: chosen"); } game.getAction().nofityOfValue(sa, player, chosen, player); return chosen; diff --git a/forge-core/src/main/java/forge/card/CardType.java b/forge-core/src/main/java/forge/card/CardType.java index 21cd142f63a..fbc16fe6ad3 100644 --- a/forge-core/src/main/java/forge/card/CardType.java +++ b/forge-core/src/main/java/forge/card/CardType.java @@ -606,13 +606,13 @@ public final class CardType implements Comparable, CardTypeView { public static class Constant { public static final Settable LOADED = new Settable(); - public static final List BASIC_TYPES = Lists.newArrayList(); - public static final List LAND_TYPES = Lists.newArrayList(); - public static final List CREATURE_TYPES = Lists.newArrayList(); - public static final List SPELL_TYPES = Lists.newArrayList(); - public static final List ENCHANTMENT_TYPES = Lists.newArrayList(); - public static final List ARTIFACT_TYPES = Lists.newArrayList(); - public static final List WALKER_TYPES = Lists.newArrayList(); + public static final Set BASIC_TYPES = Sets.newHashSet(); + public static final Set LAND_TYPES = Sets.newHashSet(); + public static final Set CREATURE_TYPES = Sets.newHashSet(); + public static final Set SPELL_TYPES = Sets.newHashSet(); + public static final Set ENCHANTMENT_TYPES = Sets.newHashSet(); + public static final Set ARTIFACT_TYPES = Sets.newHashSet(); + public static final Set WALKER_TYPES = Sets.newHashSet(); // singular -> plural public static final BiMap pluralTypes = HashBiMap.create(); @@ -699,12 +699,12 @@ public final class CardType implements Comparable, CardTypeView { return sortedSubTypes; } - public static List getBasicTypes() { - return Collections.unmodifiableList(Constant.BASIC_TYPES); + public static Collection getBasicTypes() { + return Collections.unmodifiableCollection(Constant.BASIC_TYPES); } - public static List getAllCreatureTypes() { - return Collections.unmodifiableList(Constant.CREATURE_TYPES); + public static Collection getAllCreatureTypes() { + return Collections.unmodifiableCollection(Constant.CREATURE_TYPES); } public static List getAllLandTypes() { return ImmutableList.builder() diff --git a/forge-game/src/main/java/forge/game/player/PlayerController.java b/forge-game/src/main/java/forge/game/player/PlayerController.java index d5cef95818b..62d57539212 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -161,8 +161,8 @@ public abstract class PlayerController { public abstract List chooseSaToActivateFromOpeningHand(List usableFromOpeningHand); public abstract Mana chooseManaFromPool(List manaChoices); - public abstract String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes, boolean isOptional); - public final String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes) { + public abstract String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes, boolean isOptional); + public final String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes) { return chooseSomeType(kindOfType, sa, validTypes, invalidTypes, false); } diff --git a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java index f1906ebdb0f..c9ee0f75d17 100644 --- a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java +++ b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java @@ -481,7 +481,7 @@ public class PlayerControllerForTests extends PlayerController { } @Override - public String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes, boolean isOptional) { + public String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes, boolean isOptional) { return chooseItem(validTypes); } diff --git a/forge-gui/src/main/java/forge/model/FModel.java b/forge-gui/src/main/java/forge/model/FModel.java index 27d0060413c..d0c182e890c 100644 --- a/forge-gui/src/main/java/forge/model/FModel.java +++ b/forge-gui/src/main/java/forge/model/FModel.java @@ -57,6 +57,7 @@ import forge.util.storage.StorageBase; import java.io.File; import java.util.List; import java.util.Map; +import java.util.Set; /** * The default Model implementation for Forge. @@ -259,31 +260,31 @@ public final class FModel { if (!CardType.Constant.LOADED.isSet()) { final List typeListFile = FileUtil.readFile(ForgeConstants.TYPE_LIST_FILE); - List tList = null; + Set addTo = null; for (final String s : typeListFile) { if (s.equals("[BasicTypes]")) { - tList = CardType.Constant.BASIC_TYPES; + addTo = CardType.Constant.BASIC_TYPES; } else if (s.equals("[LandTypes]")) { - tList = CardType.Constant.LAND_TYPES; + addTo = CardType.Constant.LAND_TYPES; } else if (s.equals("[CreatureTypes]")) { - tList = CardType.Constant.CREATURE_TYPES; + addTo = CardType.Constant.CREATURE_TYPES; } else if (s.equals("[SpellTypes]")) { - tList = CardType.Constant.SPELL_TYPES; + addTo = CardType.Constant.SPELL_TYPES; } else if (s.equals("[EnchantmentTypes]")) { - tList = CardType.Constant.ENCHANTMENT_TYPES; + addTo = CardType.Constant.ENCHANTMENT_TYPES; } else if (s.equals("[ArtifactTypes]")) { - tList = CardType.Constant.ARTIFACT_TYPES; + addTo = CardType.Constant.ARTIFACT_TYPES; } else if (s.equals("[WalkerTypes]")) { - tList = CardType.Constant.WALKER_TYPES; + addTo = CardType.Constant.WALKER_TYPES; } else if (s.length() > 1) { - if (tList != null) { + if (addTo != null) { if (s.contains(":")) { String[] k = s.split(":"); - tList.add(k[0]); + addTo.add(k[0]); CardType.Constant.pluralTypes.put(k[0], k[1]); } else { - tList.add(s); + addTo.add(s); } } } diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 37bcafa370d..e001be3e2bc 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1034,7 +1034,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont * java.lang.String, java.util.List, java.util.List, java.lang.String) */ @Override - public String chooseSomeType(final String kindOfType, final SpellAbility sa, final List validTypes, + public String chooseSomeType(final String kindOfType, final SpellAbility sa, final Collection validTypes, final List invalidTypes, final boolean isOptional) { final List types = Lists.newArrayList(validTypes); if (invalidTypes != null && !invalidTypes.isEmpty()) { From 8409a7e6d1685e6f667c5dd128533d9b92ae3314 Mon Sep 17 00:00:00 2001 From: friarsol Date: Thu, 19 Dec 2019 22:43:33 -0500 Subject: [PATCH 03/12] Sort coing flips for Krark's Thumb --- .../java/forge/player/PlayerControllerHuman.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 37bcafa370d..053e152fd11 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1409,11 +1409,16 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont final boolean call) { final String[] labelsSrc = call ? new String[] { "heads", "tails" } : new String[] { "win the flip", "lose the flip" }; - final ImmutableList.Builder strResults = ImmutableList.builder(); - for (int i = 0; i < results.length; i++) { - strResults.add(labelsSrc[results[i] ? 0 : 1]); + final List sortedResults = new ArrayList(); + for (boolean result : results) { + sortedResults.add(labelsSrc[result ? 0 : 1]); } - return getGui().one(sa.getHostCard().getName() + " - Choose a result", strResults.build()).equals(labelsSrc[0]); + + Collections.sort(sortedResults); + if (!call) { + Collections.reverse(sortedResults); + } + return getGui().one(sa.getHostCard().getName() + " - Choose a result", sortedResults).equals(labelsSrc[0]); } @Override From c20b0c3620b4076984dcd4110b46627a5c9b7160 Mon Sep 17 00:00:00 2001 From: friarsol Date: Thu, 19 Dec 2019 23:23:39 -0500 Subject: [PATCH 04/12] Fix Vanguards etc not displaying abilities --- forge-game/src/main/java/forge/game/card/Card.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index e7fac44ec75..f2f4a7ce8e3 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1983,8 +1983,8 @@ public class Card extends GameEntity implements Comparable { boolean isNonAura = !type.hasSubtype("Aura"); for (final SpellAbility sa : state.getSpellAbilities()) { - // only add abilities not Spell portions of cards - if (sa == null || sa.isSecondary() || !state.getType().isPermanent()) { + // This code block is not shared by instants or sorceries. We don't need to check for permanence. + if (sa == null || sa.isSecondary()) { continue; } @@ -4321,8 +4321,6 @@ public class Card extends GameEntity implements Comparable { /** * use it only for real keywords and not with hidden ones * - * @param Keyword k - * @param CardState state * @return Int */ public final int getKeywordMagnitude(final Keyword k, CardState state) { From 5cb85025663a9b2743f2d231eb5a8fdca362e757 Mon Sep 17 00:00:00 2001 From: Myrd Date: Fri, 20 Dec 2019 15:48:04 +0000 Subject: [PATCH 05/12] Revert "Merge branch 'master' into 'master'" This reverts merge request !2334 --- .../main/java/forge/ai/ComputerUtilCard.java | 2 +- .../java/forge/ai/PlayerControllerAi.java | 9 ++++---- .../src/main/java/forge/card/CardType.java | 22 +++++++++--------- .../main/java/forge/game/CardTraitBase.java | 2 +- .../forge/game/player/PlayerController.java | 4 ++-- .../util/PlayerControllerForTests.java | 2 +- .../src/main/java/forge/model/FModel.java | 23 +++++++++---------- .../forge/player/PlayerControllerHuman.java | 2 +- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 61891b7ad87..13e558ea7a9 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -643,7 +643,7 @@ public class ComputerUtilCard { return getMostProminentType(list, CardType.getAllCreatureTypes()); } - public static String getMostProminentType(final CardCollectionView list, final Collection valid) { + public static String getMostProminentType(final CardCollectionView list, final List valid) { if (list.size() == 0) { return ""; } diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index 04a9f303832..f0d1250cb58 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -502,11 +502,12 @@ public class PlayerControllerAi extends PlayerController { } @Override - public String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes, boolean isOptional) { + public String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes, boolean isOptional) { String chosen = ComputerUtil.chooseSomeType(player, kindOfType, sa.getParam("AILogic"), invalidTypes); - if (StringUtils.isBlank(chosen) && !validTypes.isEmpty()) { - chosen = validTypes.iterator().next(); - System.err.println("AI has no idea how to choose " + kindOfType +", defaulting to arbitrary element: chosen"); + if (StringUtils.isBlank(chosen) && !validTypes.isEmpty()) + { + chosen = validTypes.get(0); + System.err.println("AI has no idea how to choose " + kindOfType +", defaulting to 1st element: chosen"); } game.getAction().nofityOfValue(sa, player, chosen, player); return chosen; diff --git a/forge-core/src/main/java/forge/card/CardType.java b/forge-core/src/main/java/forge/card/CardType.java index fbc16fe6ad3..21cd142f63a 100644 --- a/forge-core/src/main/java/forge/card/CardType.java +++ b/forge-core/src/main/java/forge/card/CardType.java @@ -606,13 +606,13 @@ public final class CardType implements Comparable, CardTypeView { public static class Constant { public static final Settable LOADED = new Settable(); - public static final Set BASIC_TYPES = Sets.newHashSet(); - public static final Set LAND_TYPES = Sets.newHashSet(); - public static final Set CREATURE_TYPES = Sets.newHashSet(); - public static final Set SPELL_TYPES = Sets.newHashSet(); - public static final Set ENCHANTMENT_TYPES = Sets.newHashSet(); - public static final Set ARTIFACT_TYPES = Sets.newHashSet(); - public static final Set WALKER_TYPES = Sets.newHashSet(); + public static final List BASIC_TYPES = Lists.newArrayList(); + public static final List LAND_TYPES = Lists.newArrayList(); + public static final List CREATURE_TYPES = Lists.newArrayList(); + public static final List SPELL_TYPES = Lists.newArrayList(); + public static final List ENCHANTMENT_TYPES = Lists.newArrayList(); + public static final List ARTIFACT_TYPES = Lists.newArrayList(); + public static final List WALKER_TYPES = Lists.newArrayList(); // singular -> plural public static final BiMap pluralTypes = HashBiMap.create(); @@ -699,12 +699,12 @@ public final class CardType implements Comparable, CardTypeView { return sortedSubTypes; } - public static Collection getBasicTypes() { - return Collections.unmodifiableCollection(Constant.BASIC_TYPES); + public static List getBasicTypes() { + return Collections.unmodifiableList(Constant.BASIC_TYPES); } - public static Collection getAllCreatureTypes() { - return Collections.unmodifiableCollection(Constant.CREATURE_TYPES); + public static List getAllCreatureTypes() { + return Collections.unmodifiableList(Constant.CREATURE_TYPES); } public static List getAllLandTypes() { return ImmutableList.builder() diff --git a/forge-game/src/main/java/forge/game/CardTraitBase.java b/forge-game/src/main/java/forge/game/CardTraitBase.java index a17f64007ae..34c2a77edf5 100644 --- a/forge-game/src/main/java/forge/game/CardTraitBase.java +++ b/forge-game/src/main/java/forge/game/CardTraitBase.java @@ -73,7 +73,7 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView { } public final String getParamOrDefault(String key, String defaultValue) { - return mapParams.getOrDefault(key, defaultValue); + return hasParam(key) ? getParam(key) : defaultValue; } public String getParam(String key) { diff --git a/forge-game/src/main/java/forge/game/player/PlayerController.java b/forge-game/src/main/java/forge/game/player/PlayerController.java index 62d57539212..d5cef95818b 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -161,8 +161,8 @@ public abstract class PlayerController { public abstract List chooseSaToActivateFromOpeningHand(List usableFromOpeningHand); public abstract Mana chooseManaFromPool(List manaChoices); - public abstract String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes, boolean isOptional); - public final String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes) { + public abstract String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes, boolean isOptional); + public final String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes) { return chooseSomeType(kindOfType, sa, validTypes, invalidTypes, false); } diff --git a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java index c9ee0f75d17..f1906ebdb0f 100644 --- a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java +++ b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java @@ -481,7 +481,7 @@ public class PlayerControllerForTests extends PlayerController { } @Override - public String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes, boolean isOptional) { + public String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes, boolean isOptional) { return chooseItem(validTypes); } diff --git a/forge-gui/src/main/java/forge/model/FModel.java b/forge-gui/src/main/java/forge/model/FModel.java index d0c182e890c..27d0060413c 100644 --- a/forge-gui/src/main/java/forge/model/FModel.java +++ b/forge-gui/src/main/java/forge/model/FModel.java @@ -57,7 +57,6 @@ import forge.util.storage.StorageBase; import java.io.File; import java.util.List; import java.util.Map; -import java.util.Set; /** * The default Model implementation for Forge. @@ -260,31 +259,31 @@ public final class FModel { if (!CardType.Constant.LOADED.isSet()) { final List typeListFile = FileUtil.readFile(ForgeConstants.TYPE_LIST_FILE); - Set addTo = null; + List tList = null; for (final String s : typeListFile) { if (s.equals("[BasicTypes]")) { - addTo = CardType.Constant.BASIC_TYPES; + tList = CardType.Constant.BASIC_TYPES; } else if (s.equals("[LandTypes]")) { - addTo = CardType.Constant.LAND_TYPES; + tList = CardType.Constant.LAND_TYPES; } else if (s.equals("[CreatureTypes]")) { - addTo = CardType.Constant.CREATURE_TYPES; + tList = CardType.Constant.CREATURE_TYPES; } else if (s.equals("[SpellTypes]")) { - addTo = CardType.Constant.SPELL_TYPES; + tList = CardType.Constant.SPELL_TYPES; } else if (s.equals("[EnchantmentTypes]")) { - addTo = CardType.Constant.ENCHANTMENT_TYPES; + tList = CardType.Constant.ENCHANTMENT_TYPES; } else if (s.equals("[ArtifactTypes]")) { - addTo = CardType.Constant.ARTIFACT_TYPES; + tList = CardType.Constant.ARTIFACT_TYPES; } else if (s.equals("[WalkerTypes]")) { - addTo = CardType.Constant.WALKER_TYPES; + tList = CardType.Constant.WALKER_TYPES; } else if (s.length() > 1) { - if (addTo != null) { + if (tList != null) { if (s.contains(":")) { String[] k = s.split(":"); - addTo.add(k[0]); + tList.add(k[0]); CardType.Constant.pluralTypes.put(k[0], k[1]); } else { - addTo.add(s); + tList.add(s); } } } diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 45361909b01..053e152fd11 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1034,7 +1034,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont * java.lang.String, java.util.List, java.util.List, java.lang.String) */ @Override - public String chooseSomeType(final String kindOfType, final SpellAbility sa, final Collection validTypes, + public String chooseSomeType(final String kindOfType, final SpellAbility sa, final List validTypes, final List invalidTypes, final boolean isOptional) { final List types = Lists.newArrayList(validTypes); if (invalidTypes != null && !invalidTypes.isEmpty()) { From 4384b1621b99c121f6f85605c37380a427780912 Mon Sep 17 00:00:00 2001 From: Alexei Svitkine Date: Fri, 20 Dec 2019 11:15:38 -0500 Subject: [PATCH 06/12] Switch card types lists to sets to avoid costly look ups and optimize getParamOrDefault() to do a single look up, instead of two. These were showing up in profiles when using simulation AI. --- .../main/java/forge/ai/ComputerUtilCard.java | 2 +- .../java/forge/ai/PlayerControllerAi.java | 9 ++++---- .../src/main/java/forge/card/CardType.java | 22 +++++++++--------- .../main/java/forge/game/CardTraitBase.java | 3 ++- .../forge/game/player/PlayerController.java | 4 ++-- .../util/PlayerControllerForTests.java | 2 +- .../src/main/java/forge/model/FModel.java | 23 ++++++++++--------- .../forge/player/PlayerControllerHuman.java | 2 +- 8 files changed, 34 insertions(+), 33 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 13e558ea7a9..61891b7ad87 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -643,7 +643,7 @@ public class ComputerUtilCard { return getMostProminentType(list, CardType.getAllCreatureTypes()); } - public static String getMostProminentType(final CardCollectionView list, final List valid) { + public static String getMostProminentType(final CardCollectionView list, final Collection valid) { if (list.size() == 0) { return ""; } diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index f0d1250cb58..04a9f303832 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -502,12 +502,11 @@ public class PlayerControllerAi extends PlayerController { } @Override - public String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes, boolean isOptional) { + public String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes, boolean isOptional) { String chosen = ComputerUtil.chooseSomeType(player, kindOfType, sa.getParam("AILogic"), invalidTypes); - if (StringUtils.isBlank(chosen) && !validTypes.isEmpty()) - { - chosen = validTypes.get(0); - System.err.println("AI has no idea how to choose " + kindOfType +", defaulting to 1st element: chosen"); + if (StringUtils.isBlank(chosen) && !validTypes.isEmpty()) { + chosen = validTypes.iterator().next(); + System.err.println("AI has no idea how to choose " + kindOfType +", defaulting to arbitrary element: chosen"); } game.getAction().nofityOfValue(sa, player, chosen, player); return chosen; diff --git a/forge-core/src/main/java/forge/card/CardType.java b/forge-core/src/main/java/forge/card/CardType.java index 21cd142f63a..fbc16fe6ad3 100644 --- a/forge-core/src/main/java/forge/card/CardType.java +++ b/forge-core/src/main/java/forge/card/CardType.java @@ -606,13 +606,13 @@ public final class CardType implements Comparable, CardTypeView { public static class Constant { public static final Settable LOADED = new Settable(); - public static final List BASIC_TYPES = Lists.newArrayList(); - public static final List LAND_TYPES = Lists.newArrayList(); - public static final List CREATURE_TYPES = Lists.newArrayList(); - public static final List SPELL_TYPES = Lists.newArrayList(); - public static final List ENCHANTMENT_TYPES = Lists.newArrayList(); - public static final List ARTIFACT_TYPES = Lists.newArrayList(); - public static final List WALKER_TYPES = Lists.newArrayList(); + public static final Set BASIC_TYPES = Sets.newHashSet(); + public static final Set LAND_TYPES = Sets.newHashSet(); + public static final Set CREATURE_TYPES = Sets.newHashSet(); + public static final Set SPELL_TYPES = Sets.newHashSet(); + public static final Set ENCHANTMENT_TYPES = Sets.newHashSet(); + public static final Set ARTIFACT_TYPES = Sets.newHashSet(); + public static final Set WALKER_TYPES = Sets.newHashSet(); // singular -> plural public static final BiMap pluralTypes = HashBiMap.create(); @@ -699,12 +699,12 @@ public final class CardType implements Comparable, CardTypeView { return sortedSubTypes; } - public static List getBasicTypes() { - return Collections.unmodifiableList(Constant.BASIC_TYPES); + public static Collection getBasicTypes() { + return Collections.unmodifiableCollection(Constant.BASIC_TYPES); } - public static List getAllCreatureTypes() { - return Collections.unmodifiableList(Constant.CREATURE_TYPES); + public static Collection getAllCreatureTypes() { + return Collections.unmodifiableCollection(Constant.CREATURE_TYPES); } public static List getAllLandTypes() { return ImmutableList.builder() diff --git a/forge-game/src/main/java/forge/game/CardTraitBase.java b/forge-game/src/main/java/forge/game/CardTraitBase.java index 34c2a77edf5..9cd20815539 100644 --- a/forge-game/src/main/java/forge/game/CardTraitBase.java +++ b/forge-game/src/main/java/forge/game/CardTraitBase.java @@ -73,7 +73,8 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView { } public final String getParamOrDefault(String key, String defaultValue) { - return hasParam(key) ? getParam(key) : defaultValue; + String param = mapParams.get(key); + return param != null ? param : defaultValue; } public String getParam(String key) { diff --git a/forge-game/src/main/java/forge/game/player/PlayerController.java b/forge-game/src/main/java/forge/game/player/PlayerController.java index d5cef95818b..62d57539212 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -161,8 +161,8 @@ public abstract class PlayerController { public abstract List chooseSaToActivateFromOpeningHand(List usableFromOpeningHand); public abstract Mana chooseManaFromPool(List manaChoices); - public abstract String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes, boolean isOptional); - public final String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes) { + public abstract String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes, boolean isOptional); + public final String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes) { return chooseSomeType(kindOfType, sa, validTypes, invalidTypes, false); } diff --git a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java index f1906ebdb0f..c9ee0f75d17 100644 --- a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java +++ b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java @@ -481,7 +481,7 @@ public class PlayerControllerForTests extends PlayerController { } @Override - public String chooseSomeType(String kindOfType, SpellAbility sa, List validTypes, List invalidTypes, boolean isOptional) { + public String chooseSomeType(String kindOfType, SpellAbility sa, Collection validTypes, List invalidTypes, boolean isOptional) { return chooseItem(validTypes); } diff --git a/forge-gui/src/main/java/forge/model/FModel.java b/forge-gui/src/main/java/forge/model/FModel.java index 27d0060413c..d0c182e890c 100644 --- a/forge-gui/src/main/java/forge/model/FModel.java +++ b/forge-gui/src/main/java/forge/model/FModel.java @@ -57,6 +57,7 @@ import forge.util.storage.StorageBase; import java.io.File; import java.util.List; import java.util.Map; +import java.util.Set; /** * The default Model implementation for Forge. @@ -259,31 +260,31 @@ public final class FModel { if (!CardType.Constant.LOADED.isSet()) { final List typeListFile = FileUtil.readFile(ForgeConstants.TYPE_LIST_FILE); - List tList = null; + Set addTo = null; for (final String s : typeListFile) { if (s.equals("[BasicTypes]")) { - tList = CardType.Constant.BASIC_TYPES; + addTo = CardType.Constant.BASIC_TYPES; } else if (s.equals("[LandTypes]")) { - tList = CardType.Constant.LAND_TYPES; + addTo = CardType.Constant.LAND_TYPES; } else if (s.equals("[CreatureTypes]")) { - tList = CardType.Constant.CREATURE_TYPES; + addTo = CardType.Constant.CREATURE_TYPES; } else if (s.equals("[SpellTypes]")) { - tList = CardType.Constant.SPELL_TYPES; + addTo = CardType.Constant.SPELL_TYPES; } else if (s.equals("[EnchantmentTypes]")) { - tList = CardType.Constant.ENCHANTMENT_TYPES; + addTo = CardType.Constant.ENCHANTMENT_TYPES; } else if (s.equals("[ArtifactTypes]")) { - tList = CardType.Constant.ARTIFACT_TYPES; + addTo = CardType.Constant.ARTIFACT_TYPES; } else if (s.equals("[WalkerTypes]")) { - tList = CardType.Constant.WALKER_TYPES; + addTo = CardType.Constant.WALKER_TYPES; } else if (s.length() > 1) { - if (tList != null) { + if (addTo != null) { if (s.contains(":")) { String[] k = s.split(":"); - tList.add(k[0]); + addTo.add(k[0]); CardType.Constant.pluralTypes.put(k[0], k[1]); } else { - tList.add(s); + addTo.add(s); } } } diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 053e152fd11..45361909b01 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1034,7 +1034,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont * java.lang.String, java.util.List, java.util.List, java.lang.String) */ @Override - public String chooseSomeType(final String kindOfType, final SpellAbility sa, final List validTypes, + public String chooseSomeType(final String kindOfType, final SpellAbility sa, final Collection validTypes, final List invalidTypes, final boolean isOptional) { final List types = Lists.newArrayList(validTypes); if (invalidTypes != null && !invalidTypes.isEmpty()) { From dd4df9baaa70ef5a2eea44bfaeea5393b68cb4a8 Mon Sep 17 00:00:00 2001 From: Alexei Svitkine Date: Fri, 20 Dec 2019 11:22:06 -0500 Subject: [PATCH 07/12] Optimize FileSection.parse()/parseMap(). This was showing up in profiles with simulation AI. The change makes constants for the patterns used, so they don't have to be "compiled" each time and also introduces a cache for these. With this change, a GameCopier operation is sped up by about 30% from my local measurement (I tried with a modern deck I have). --- .../java/forge/ai/simulation/GameCopier.java | 13 +++- .../src/main/java/forge/card/CardEdition.java | 2 +- .../java/forge/deck/io/DeckSerializer.java | 2 +- .../src/main/java/forge/item/PreconDeck.java | 2 +- .../src/main/java/forge/util/FileSection.java | 62 +++++++++++-------- .../src/main/java/forge/game/GameFormat.java | 2 +- .../forge/game/ability/AbilityFactory.java | 2 +- .../src/main/java/forge/game/card/Card.java | 19 +++--- .../main/java/forge/game/card/CardState.java | 4 +- .../game/replacement/ReplacementHandler.java | 2 +- .../java/forge/limited/CustomLimited.java | 2 +- .../properties/ForgeProfileProperties.java | 2 +- .../src/main/java/forge/quest/SellRules.java | 2 +- .../forge/quest/io/QuestChallengeReader.java | 4 +- .../java/forge/quest/io/QuestDuelReader.java | 2 +- 15 files changed, 69 insertions(+), 53 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java index cd99a5a6d94..fc574542bc5 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -58,7 +58,11 @@ public class GameCopier { public Game makeCopy() { return makeCopy(null); } + + static int copies; + static double totalTime; public Game makeCopy(PhaseType advanceToPhase) { + long t = System.currentTimeMillis(); List origPlayers = origGame.getMatch().getPlayers(); List newPlayers = new ArrayList<>(); for (RegisteredPlayer p : origPlayers) { @@ -146,7 +150,14 @@ public class GameCopier { if (advanceToPhase != null) { newGame.getPhaseHandler().devAdvanceToPhase(advanceToPhase); } - + + totalTime += (System.currentTimeMillis()-t) * 1000; + if ((copies++ % 100) == 0) { + System.out.println("Time per copy: " + totalTime/copies); + if (copies >= 10000) { + System.exit(-1); + } + } return newGame; } diff --git a/forge-core/src/main/java/forge/card/CardEdition.java b/forge-core/src/main/java/forge/card/CardEdition.java index b9b88687d97..15fbaa7ec8f 100644 --- a/forge-core/src/main/java/forge/card/CardEdition.java +++ b/forge-core/src/main/java/forge/card/CardEdition.java @@ -303,7 +303,7 @@ public final class CardEdition implements Comparable { // immutable tokenNormalized ); - FileSection section = FileSection.parse(contents.get("metadata"), "="); + FileSection section = FileSection.parse(contents.get("metadata"), FileSection.EQUALS_KV_SEPARATOR); res.name = section.get("name"); res.date = parseDate(section.get("date")); res.code = section.get("code"); diff --git a/forge-core/src/main/java/forge/deck/io/DeckSerializer.java b/forge-core/src/main/java/forge/deck/io/DeckSerializer.java index 8b59c4e8dd2..4df2b493f1a 100644 --- a/forge-core/src/main/java/forge/deck/io/DeckSerializer.java +++ b/forge-core/src/main/java/forge/deck/io/DeckSerializer.java @@ -27,7 +27,7 @@ public class DeckSerializer { } final List metadata = map.get("metadata"); if (metadata != null) { - return new DeckFileHeader(FileSection.parse(metadata, "=")); + return new DeckFileHeader(FileSection.parse(metadata, FileSection.EQUALS_KV_SEPARATOR)); } final List general = map.get("general"); if (general != null) { diff --git a/forge-core/src/main/java/forge/item/PreconDeck.java b/forge-core/src/main/java/forge/item/PreconDeck.java index c7ee708b59a..bde7a829c9b 100644 --- a/forge-core/src/main/java/forge/item/PreconDeck.java +++ b/forge-core/src/main/java/forge/item/PreconDeck.java @@ -108,7 +108,7 @@ public class PreconDeck implements InventoryItemFromSet { // To be able to read "shops" section in overloads protected PreconDeck getPreconDeckFromSections(final Map> sections) { - FileSection kv = FileSection.parse(sections.get("metadata"), "="); + FileSection kv = FileSection.parse(sections.get("metadata"), FileSection.EQUALS_KV_SEPARATOR); String imageFilename = kv.get("Image"); String description = kv.get("Description"); String deckEdition = kv.get("set"); diff --git a/forge-core/src/main/java/forge/util/FileSection.java b/forge-core/src/main/java/forge/util/FileSection.java index 53a5f140d06..d706be82938 100644 --- a/forge-core/src/main/java/forge/util/FileSection.java +++ b/forge-core/src/main/java/forge/util/FileSection.java @@ -17,9 +17,12 @@ */ package forge.util; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; import java.text.NumberFormat; import java.text.ParseException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; @@ -56,34 +59,40 @@ public class FileSection { protected FileSection(Map lines0) { lines = lines0; } - - /** - * Parses the. - * - * @param line the line - * @param kvSeparator the kv separator - * @param pairSeparator the pair separator - * @return the file section - */ - public static FileSection parse(final String line, final String kvSeparator, final String pairSeparator) { - Map map = parseToMap(line, kvSeparator, pairSeparator); - return new FileSection(map); - } - - public static Map parseToMap(final String line, final String kvSeparator, final String pairSeparator) { - Map result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - if (!StringUtils.isEmpty(line)) { - final String[] pairs = line.split(Pattern.quote(pairSeparator)); - final Pattern splitter = Pattern.compile(Pattern.quote(kvSeparator)); - - for (final String dd : pairs) { - final String[] v = splitter.split(dd, 2); - result.put(v[0].trim(), v.length > 1 ? v[1].trim() : ""); - } + + public static final Pattern DOLLAR_SIGN_KV_SEPARATOR = Pattern.compile(Pattern.quote("$")); + public static final Pattern ARROW_KV_SEPARATOR = Pattern.compile(Pattern.quote("->")); + public static final Pattern EQUALS_KV_SEPARATOR = Pattern.compile(Pattern.quote("=")); + public static final Pattern COLON_KV_SEPARATOR = Pattern.compile(Pattern.quote(":")); + + private static final String BAR_PAIR_SPLITTER = Pattern.quote("|"); + + private static Table> parseToMapCache = HashBasedTable.create(); + + public static Map parseToMap(final String line, final Pattern kvSeparator) { + Map result = parseToMapCache.get(line, kvSeparator); + if (result != null) { + return result; } + result = parseToMapImpl(line, kvSeparator); + parseToMapCache.put(line, kvSeparator, result); return result; } + private static Map parseToMapImpl(final String line, final Pattern kvSeparator) { + if (StringUtils.isEmpty(line)) { + return Collections.emptyMap(); + } + + final Map result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + final String[] pairs = line.split(BAR_PAIR_SPLITTER); + for (final String dd : pairs) { + final String[] v = kvSeparator.split(dd, 2); + result.put(v[0].trim(), v.length > 1 ? v[1].trim() : ""); + } + return Collections.unmodifiableMap(result); + } + /** * Parses the. * @@ -91,11 +100,10 @@ public class FileSection { * @param kvSeparator the kv separator * @return the file section */ - public static FileSection parse(final Iterable lines, final String kvSeparator) { + public static FileSection parse(final Iterable lines, final Pattern kvSeparator) { final FileSection result = new FileSection(); - final Pattern splitter = Pattern.compile(Pattern.quote(kvSeparator)); for (final String dd : lines) { - final String[] v = splitter.split(dd, 2); + final String[] v = kvSeparator.split(dd, 2); result.lines.put(v[0].trim(), v.length > 1 ? v[1].trim() : ""); } diff --git a/forge-game/src/main/java/forge/game/GameFormat.java b/forge-game/src/main/java/forge/game/GameFormat.java index 9eb259404ea..e4efda21fb6 100644 --- a/forge-game/src/main/java/forge/game/GameFormat.java +++ b/forge-game/src/main/java/forge/game/GameFormat.java @@ -321,7 +321,7 @@ public class GameFormat implements Comparable { if (formatStrings == null){ return null; } - FileSection section = FileSection.parse(formatStrings, ":"); + FileSection section = FileSection.parse(formatStrings, FileSection.COLON_KV_SEPARATOR); String title = section.get("name"); FormatType formatType; try { diff --git a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java index 1e770f1fce9..9ff6c8d5dc8 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java @@ -449,7 +449,7 @@ public final class AbilityFactory { } public static final Map getMapParams(final String abString) { - return FileSection.parseToMap(abString, "$", "|"); + return FileSection.parseToMap(abString, FileSection.DOLLAR_SIGN_KV_SEPARATOR); } public static final void adjustChangeZoneTarget(final Map params, final SpellAbility sa) { diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index f2f4a7ce8e3..440c1ce9606 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1893,11 +1893,11 @@ public class Card extends GameEntity implements Comparable { sb.append("\r\n"); } - while (sb.toString().endsWith("\r\n")) { - sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n") + 3); + String result = sb.toString(); + while (result.endsWith("\r\n")) { + result = sb.substring(0, sb.length() - 2); } - - return TextUtil.fastReplace(sb.toString(), "CARDNAME", state.getName()); + return TextUtil.fastReplace(result, "CARDNAME", state.getName()); } if (monstrous) { @@ -2071,14 +2071,11 @@ public class Card extends GameEntity implements Comparable { } // replace triple line feeds with double line feeds - int start; final String s = "\r\n\r\n\r\n"; - while (sb.toString().contains(s)) { - start = sb.lastIndexOf(s); - if ((start < 0) || (start >= sb.length())) { - break; - } + int start = sb.lastIndexOf(s); + while (start != -1) { sb.replace(start, start + 4, "\r\n"); + start = sb.lastIndexOf(s); } String desc = TextUtil.fastReplace(sb.toString(), "CARDNAME", state.getName()); @@ -2503,7 +2500,7 @@ public class Card extends GameEntity implements Comparable { } } - public final FCollectionView getIntrinsicSpellAbilities() { + public final Iterable getIntrinsicSpellAbilities() { return currentState.getIntrinsicSpellAbilities(); } diff --git a/forge-game/src/main/java/forge/game/card/CardState.java b/forge-game/src/main/java/forge/game/card/CardState.java index 1fafb514335..ba50c919a0b 100644 --- a/forge-game/src/main/java/forge/game/card/CardState.java +++ b/forge-game/src/main/java/forge/game/card/CardState.java @@ -273,8 +273,8 @@ public class CardState extends GameObject { return newCol; } - public final FCollectionView getIntrinsicSpellAbilities() { - return new FCollection<>(Iterables.filter(getSpellAbilities(), SpellAbilityPredicates.isIntrinsic())); + public final Iterable getIntrinsicSpellAbilities() { + return Iterables.filter(getSpellAbilities(), SpellAbilityPredicates.isIntrinsic()); } public final boolean hasSpellAbility(final SpellAbility sa) { diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java index cba94673457..adeeec09355 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java @@ -389,7 +389,7 @@ public class ReplacementHandler { } public static Map parseParams(final String repParse) { - return FileSection.parseToMap(repParse, "$", "|"); + return FileSection.parseToMap(repParse, FileSection.DOLLAR_SIGN_KV_SEPARATOR); } /** diff --git a/forge-gui/src/main/java/forge/limited/CustomLimited.java b/forge-gui/src/main/java/forge/limited/CustomLimited.java index b87b0b8bfbc..cd908d5f59e 100644 --- a/forge-gui/src/main/java/forge/limited/CustomLimited.java +++ b/forge-gui/src/main/java/forge/limited/CustomLimited.java @@ -96,7 +96,7 @@ public class CustomLimited extends DeckBase { * @return the custom limited */ public static CustomLimited parse(final List dfData, final IStorage cubes) { - final FileSection data = FileSection.parse(dfData, ":"); + final FileSection data = FileSection.parse(dfData, FileSection.COLON_KV_SEPARATOR); List> slots = new ArrayList<>(); String boosterData = data.get("Booster"); diff --git a/forge-gui/src/main/java/forge/properties/ForgeProfileProperties.java b/forge-gui/src/main/java/forge/properties/ForgeProfileProperties.java index 78cd5278860..8ad8dff029e 100644 --- a/forge-gui/src/main/java/forge/properties/ForgeProfileProperties.java +++ b/forge-gui/src/main/java/forge/properties/ForgeProfileProperties.java @@ -133,7 +133,7 @@ public class ForgeProfileProperties { private static Map getMap(final Properties props, final String propertyKey) { final String strMap = props.getProperty(propertyKey, "").trim(); - return FileSection.parseToMap(strMap, "->", "|"); + return FileSection.parseToMap(strMap, FileSection.ARROW_KV_SEPARATOR); } private static int getInt(final Properties props, final String propertyKey, final int defaultValue) { diff --git a/forge-gui/src/main/java/forge/quest/SellRules.java b/forge-gui/src/main/java/forge/quest/SellRules.java index 36de28da65f..614cf576fe5 100644 --- a/forge-gui/src/main/java/forge/quest/SellRules.java +++ b/forge-gui/src/main/java/forge/quest/SellRules.java @@ -43,7 +43,7 @@ public class SellRules { return; } - FileSection section = FileSection.parse(questShop, "="); + FileSection section = FileSection.parse(questShop, FileSection.EQUALS_KV_SEPARATOR); minWins = section.getInt("WinsToUnlock"); cost = section.getInt("Credits", 250); maxDifficulty = section.getInt("MaxDifficulty", 5); diff --git a/forge-gui/src/main/java/forge/quest/io/QuestChallengeReader.java b/forge-gui/src/main/java/forge/quest/io/QuestChallengeReader.java index 54d86894784..9e31616491d 100644 --- a/forge-gui/src/main/java/forge/quest/io/QuestChallengeReader.java +++ b/forge-gui/src/main/java/forge/quest/io/QuestChallengeReader.java @@ -28,7 +28,7 @@ public class QuestChallengeReader extends StorageReaderFolder { final QuestEventDuel qc = new QuestEventDuel(); // Common properties - FileSection sectionMeta = FileSection.parse(contents.get("metadata"), "="); + FileSection sectionMeta = FileSection.parse(contents.get("metadata"), FileSection.EQUALS_KV_SEPARATOR); qc.setTitle(sectionMeta.get("Title")); qc.setName(sectionMeta.get("Name")); // Challenges have unique titles qc.setDifficulty(QuestEventDifficulty.fromString(sectionMeta.get("Difficulty"))); From ed3c5194047971fe884ada05cd59151bffe7cef4 Mon Sep 17 00:00:00 2001 From: Alexei Svitkine Date: Fri, 20 Dec 2019 11:25:43 -0500 Subject: [PATCH 08/12] Remove game copier logging code. --- .../src/main/java/forge/ai/simulation/GameCopier.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java index fc574542bc5..1cc4c6d88b2 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -59,10 +59,7 @@ public class GameCopier { return makeCopy(null); } - static int copies; - static double totalTime; public Game makeCopy(PhaseType advanceToPhase) { - long t = System.currentTimeMillis(); List origPlayers = origGame.getMatch().getPlayers(); List newPlayers = new ArrayList<>(); for (RegisteredPlayer p : origPlayers) { @@ -151,13 +148,6 @@ public class GameCopier { newGame.getPhaseHandler().devAdvanceToPhase(advanceToPhase); } - totalTime += (System.currentTimeMillis()-t) * 1000; - if ((copies++ % 100) == 0) { - System.out.println("Time per copy: " + totalTime/copies); - if (copies >= 10000) { - System.exit(-1); - } - } return newGame; } From 77ed24a20332712a878530310e9293726bd82301 Mon Sep 17 00:00:00 2001 From: Alexei Svitkine Date: Fri, 20 Dec 2019 11:28:11 -0500 Subject: [PATCH 09/12] Revert changes to GameCopier. --- forge-ai/src/main/java/forge/ai/simulation/GameCopier.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java index 1cc4c6d88b2..cd99a5a6d94 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -58,7 +58,6 @@ public class GameCopier { public Game makeCopy() { return makeCopy(null); } - public Game makeCopy(PhaseType advanceToPhase) { List origPlayers = origGame.getMatch().getPlayers(); List newPlayers = new ArrayList<>(); @@ -147,7 +146,7 @@ public class GameCopier { if (advanceToPhase != null) { newGame.getPhaseHandler().devAdvanceToPhase(advanceToPhase); } - + return newGame; } From 267c8c6b0d4e7e09225ac49843285f9075f31f65 Mon Sep 17 00:00:00 2001 From: Myrd Date: Fri, 20 Dec 2019 16:57:14 +0000 Subject: [PATCH 10/12] Avoid combat simulation if the current player has no creatures in play. --- .../main/java/forge/ai/simulation/GameStateEvaluator.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java b/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java index 3ee4521d4ba..f2d0f01bf85 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java @@ -29,6 +29,13 @@ public class GameStateEvaluator { if (phase.isAfter(PhaseType.COMBAT_DAMAGE) || evalGame.isGameOver()) { return null; } + // If the current player has no creatures in play, there won't be any combat. This avoids + // an expensive game copy operation. + // Note: This is is safe to do because the simulation is based on the current game state, + // so there isn't a chance to play creatures in between. + if (evalGame.getPhaseHandler().getPlayerTurn().getCreaturesInPlay().isEmpty()) { + return null; + } GameCopier copier = new GameCopier(evalGame); Game gameCopy = copier.makeCopy(); gameCopy.getPhaseHandler().devAdvanceToPhase(PhaseType.COMBAT_DAMAGE); From a4bd13d0502970ab8dad004c09a871ddb192d884 Mon Sep 17 00:00:00 2001 From: Myrd Date: Fri, 20 Dec 2019 17:56:37 +0000 Subject: [PATCH 11/12] Fix dumping state with cards with non-matching owner/controllers. --- forge-ai/src/main/java/forge/ai/GameState.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/forge-ai/src/main/java/forge/ai/GameState.java b/forge-ai/src/main/java/forge/ai/GameState.java index 3d0c81eda1c..2156d3f8910 100644 --- a/forge-ai/src/main/java/forge/ai/GameState.java +++ b/forge-ai/src/main/java/forge/ai/GameState.java @@ -242,7 +242,7 @@ public abstract class GameState { if (card instanceof DetachedCardEffect) { continue; } - addCard(zone, card.getOwner() == ai ? aiCardTexts : humanCardTexts, card); + addCard(zone, card.getController() == ai ? aiCardTexts : humanCardTexts, card); } } } @@ -269,6 +269,10 @@ public abstract class GameState { } if (zoneType == ZoneType.Battlefield) { + if (c.getOwner() != c.getController()) { + // TODO: Handle more than 2-player games. + newText.append("|Owner:" + (c.getOwner().isAI() ? "AI" : "Human")); + } if (c.isTapped()) { newText.append("|Tapped"); } From d68c740e1d2390280161c95eda858e5c708121b8 Mon Sep 17 00:00:00 2001 From: Myrd Date: Fri, 20 Dec 2019 22:18:00 +0000 Subject: [PATCH 12/12] Use FileSection.parseToMap() from TriggerHandler. --- .../forge/game/trigger/TriggerHandler.java | 28 ++----------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index 720e7301910..9696848bbce 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -39,6 +39,7 @@ import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.TargetRestrictions; import forge.game.zone.Zone; import forge.game.zone.ZoneType; +import forge.util.FileSection; import forge.util.Visitor; import io.sentry.Sentry; import io.sentry.event.BreadcrumbBuilder; @@ -49,7 +50,6 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.google.common.collect.Multimaps; public class TriggerHandler { @@ -172,35 +172,11 @@ public class TriggerHandler { } private static Map parseParams(final String trigParse) { - final Map mapParams = Maps.newHashMap(); - if (trigParse.length() == 0) { throw new RuntimeException("TriggerFactory : registerTrigger -- trigParse too short"); } - final String[] params = trigParse.split("\\|"); - - for (int i = 0; i < params.length; i++) { - params[i] = params[i].trim(); - } - - for (final String param : params) { - final String[] splitParam = param.split("\\$"); - for (int i = 0; i < splitParam.length; i++) { - splitParam[i] = splitParam[i].trim(); - } - - if (splitParam.length != 2) { - final StringBuilder sb = new StringBuilder(); - sb.append("TriggerFactory Parsing Error in registerTrigger() : Split length of "); - sb.append(param).append(" is not 2."); - throw new RuntimeException(sb.toString()); - } - - mapParams.put(splitParam[0], splitParam[1]); - } - - return mapParams; + return FileSection.parseToMap(trigParse, FileSection.DOLLAR_SIGN_KV_SEPARATOR); } private void collectTriggerForWaiting() {