From 1d18c3bfbb1d99ba4b514cee2a78dfeaab86a550 Mon Sep 17 00:00:00 2001 From: "marcins78@gmail.com" Date: Wed, 16 Nov 2011 20:06:58 +0000 Subject: [PATCH] Improving performance of major filterings, etc. --- .../modifiers/CancelKeywordBonusModifier.java | 8 +- .../modifiers/KeywordAffectingModifier.java | 7 + .../logic/modifiers/KeywordModifier.java | 7 +- .../logic/modifiers/LoggingThreadLocal.java | 62 ++- .../lotro/logic/modifiers/ModifiersLogic.java | 385 +++++++++++------- .../modifiers/RemoveKeywordModifier.java | 10 +- .../lotro/logic/timing/DefaultLotroGame.java | 8 +- .../lotro/logic/timing/RuleUtils.java | 32 +- .../lotro/logic/timing/TurnProcedure.java | 17 +- .../logic/timing/actions/SystemAction.java | 6 +- .../logic/timing/rules/EnduringRule.java | 2 +- .../lotro/logic/timing/rules/RoamingRule.java | 2 +- 12 files changed, 357 insertions(+), 189 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/KeywordAffectingModifier.java diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/modifiers/CancelKeywordBonusModifier.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/modifiers/CancelKeywordBonusModifier.java index be3fc5b8a..81e51aad1 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/modifiers/CancelKeywordBonusModifier.java +++ b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/modifiers/CancelKeywordBonusModifier.java @@ -5,10 +5,11 @@ import com.gempukku.lotro.filters.Filter; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.state.GameState; import com.gempukku.lotro.logic.modifiers.AbstractModifier; +import com.gempukku.lotro.logic.modifiers.KeywordAffectingModifier; import com.gempukku.lotro.logic.modifiers.ModifierEffect; import com.gempukku.lotro.logic.modifiers.ModifiersQuerying; -public class CancelKeywordBonusModifier extends AbstractModifier { +public class CancelKeywordBonusModifier extends AbstractModifier implements KeywordAffectingModifier { private Keyword _keyword; public CancelKeywordBonusModifier(PhysicalCard source, Keyword keyword, Filter affectFilter) { @@ -22,4 +23,9 @@ public class CancelKeywordBonusModifier extends AbstractModifier { return false; return true; } + + @Override + public Keyword getKeyword() { + return _keyword; + } } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/KeywordAffectingModifier.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/KeywordAffectingModifier.java new file mode 100644 index 000000000..21f7c20cd --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/KeywordAffectingModifier.java @@ -0,0 +1,7 @@ +package com.gempukku.lotro.logic.modifiers; + +import com.gempukku.lotro.common.Keyword; + +public interface KeywordAffectingModifier { + public Keyword getKeyword(); +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/KeywordModifier.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/KeywordModifier.java index 31fffa508..4f6aec90c 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/KeywordModifier.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/KeywordModifier.java @@ -7,7 +7,7 @@ import com.gempukku.lotro.game.state.GameState; import com.gempukku.lotro.logic.modifiers.evaluator.ConstantEvaluator; import com.gempukku.lotro.logic.modifiers.evaluator.Evaluator; -public class KeywordModifier extends AbstractModifier { +public class KeywordModifier extends AbstractModifier implements KeywordAffectingModifier { private Keyword _keyword; private Evaluator _evaluator; @@ -29,6 +29,11 @@ public class KeywordModifier extends AbstractModifier { _evaluator = evaluator; } + @Override + public Keyword getKeyword() { + return _keyword; + } + @Override public String getText(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard self) { if (_keyword.isMultiples()) { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/LoggingThreadLocal.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/LoggingThreadLocal.java index 5ebffcf1d..07ed6d8da 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/LoggingThreadLocal.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/LoggingThreadLocal.java @@ -3,28 +3,74 @@ package com.gempukku.lotro.logic.modifiers; import com.gempukku.lotro.game.PhysicalCard; import org.apache.log4j.Logger; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + public class LoggingThreadLocal { private static final Logger LOG = Logger.getLogger(LoggingThreadLocal.class); private static ThreadLocal _logLocal = new ThreadLocal(); private static ThreadLocal _start = new ThreadLocal(); + private static ThreadLocal _level = new ThreadLocal(); - public static void start() { - _logLocal.set(new StringBuilder()); - _start.set(System.currentTimeMillis()); + private static FileOutputStream _fos = null; + + private static synchronized void initializeOutputStream() { + if (_fos == null) { + try { + _fos = new FileOutputStream(new File("I:\\dev\\logMethod-2.txt")); + } catch (IOException exp) { + throw new RuntimeException(exp); + } + } } - public static void log(PhysicalCard card, String desc) { + public static void start() { + if (_fos == null) + initializeOutputStream(); + + _logLocal.set(new StringBuilder()); + _start.set(System.currentTimeMillis()); + _level.set(0); + } + + public static void logMethodStart(PhysicalCard card, String desc) { StringBuilder builder = _logLocal.get(); - if (builder != null && card != null) - builder.append(card.getBlueprintId()).append(" ").append(desc).append(" - "); + if (builder != null) { + int level = _level.get(); + for (int i = 0; i < level; i++) + builder.append("\t"); + builder.append(desc); + if (card != null) + builder.append(" ").append(card.getBlueprintId()); + builder.append("\r\n"); + _level.set(level + 1); + } + } + + public static void logMethodEnd() { + StringBuilder builder = _logLocal.get(); + if (builder != null) { + _level.set(_level.get() - 1); + } } public static void stop(boolean writeOperation) { long start = _start.get(); long time = System.currentTimeMillis() - start; - if (time > 100) - LOG.error("Processing took (" + writeOperation + ")" + time + "ms: \n" + _logLocal.get().toString()); + if (time > 10) { + String str = "Processing took (" + writeOperation + ") " + time + "ms: \n" + _logLocal.get().toString(); + try { + synchronized (_fos) { + _fos.write(str.getBytes()); + _fos.flush(); + } + } catch (IOException exp) { + throw new RuntimeException(exp); + } + } _start.set(null); _logLocal.set(null); + _level.set(null); } } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java index 1094a0285..2e81b04ea 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java @@ -188,50 +188,63 @@ public class ModifiersLogic implements ModifiersEnvironment, ModifiersQuerying { @Override public boolean hasKeyword(GameState gameState, PhysicalCard physicalCard, Keyword keyword) { - LoggingThreadLocal.log(physicalCard, "hasKeyword"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.KEYWORD_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) - if (modifier.isKeywordRemoved(gameState, this, physicalCard, keyword)) - return false; - } + LoggingThreadLocal.logMethodStart(physicalCard, "hasKeyword " + keyword.getHumanReadable()); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.KEYWORD_MODIFIER)) { + if (((KeywordAffectingModifier) modifier).getKeyword() == keyword) + if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) + if (modifier.isKeywordRemoved(gameState, this, physicalCard, keyword)) + return false; + } - if (physicalCard.getBlueprint().hasKeyword(keyword)) - return true; + if (physicalCard.getBlueprint().hasKeyword(keyword)) + return true; - for (Modifier modifier : getModifiers(gameState, ModifierEffect.KEYWORD_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, physicalCard, modifier) - && appliesKeywordModifier(gameState, modifier.getSource(), keyword)) - if (modifier.hasKeyword(gameState, this, physicalCard, keyword)) - return true; + for (Modifier modifier : getModifiers(gameState, ModifierEffect.KEYWORD_MODIFIER)) { + if (((KeywordAffectingModifier) modifier).getKeyword() == keyword) + if (affectsCardWithSkipSet(gameState, physicalCard, modifier) + && appliesKeywordModifier(gameState, modifier.getSource(), keyword)) + if (modifier.hasKeyword(gameState, this, physicalCard, keyword)) + return true; + } + return false; + } finally { + LoggingThreadLocal.logMethodEnd(); } - return false; } @Override public int getKeywordCount(GameState gameState, PhysicalCard physicalCard, Keyword keyword) { - LoggingThreadLocal.log(physicalCard, "getKeywordCount"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.KEYWORD_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) - if (modifier.isKeywordRemoved(gameState, this, physicalCard, keyword)) - return 0; - } + LoggingThreadLocal.logMethodStart(physicalCard, "getKeywordCount " + keyword.getHumanReadable()); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.KEYWORD_MODIFIER)) { + if (((KeywordAffectingModifier) modifier).getKeyword() == keyword) + if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) + if (modifier.isKeywordRemoved(gameState, this, physicalCard, keyword)) + return 0; + } - int result = physicalCard.getBlueprint().getKeywordCount(keyword); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.KEYWORD_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, physicalCard, modifier) - && appliesKeywordModifier(gameState, modifier.getSource(), keyword)) - result += modifier.getKeywordCountModifier(gameState, this, physicalCard, keyword); + int result = physicalCard.getBlueprint().getKeywordCount(keyword); + for (Modifier modifier : getModifiers(gameState, ModifierEffect.KEYWORD_MODIFIER)) { + if (((KeywordAffectingModifier) modifier).getKeyword() == keyword) + if (affectsCardWithSkipSet(gameState, physicalCard, modifier) + && appliesKeywordModifier(gameState, modifier.getSource(), keyword)) + result += modifier.getKeywordCountModifier(gameState, this, physicalCard, keyword); + } + return Math.max(0, result); + } finally { + LoggingThreadLocal.logMethodEnd(); } - return Math.max(0, result); } private boolean appliesKeywordModifier(GameState gameState, PhysicalCard modifierSource, Keyword keyword) { if (modifierSource == null) return true; for (Modifier modifier : getModifiers(gameState, ModifierEffect.KEYWORD_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, modifierSource, modifier)) - if (!modifier.appliesKeywordModifier(gameState, this, modifierSource, keyword)) - return false; + if (((KeywordAffectingModifier) modifier).getKeyword() == keyword) + if (affectsCardWithSkipSet(gameState, modifierSource, modifier)) + if (!modifier.appliesKeywordModifier(gameState, this, modifierSource, keyword)) + return false; } return true; } @@ -254,14 +267,18 @@ public class ModifiersLogic implements ModifiersEnvironment, ModifiersQuerying { @Override public int getStrength(GameState gameState, PhysicalCard physicalCard) { - LoggingThreadLocal.log(physicalCard, "getStrength"); - int result = physicalCard.getBlueprint().getStrength(); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.STRENGTH_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, physicalCard, modifier) - && appliesStrengthModifier(gameState, modifier.getSource())) - result += modifier.getStrengthModifier(gameState, this, physicalCard); + LoggingThreadLocal.logMethodStart(physicalCard, "getStrength"); + try { + int result = physicalCard.getBlueprint().getStrength(); + for (Modifier modifier : getModifiers(gameState, ModifierEffect.STRENGTH_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, physicalCard, modifier) + && appliesStrengthModifier(gameState, modifier.getSource())) + result += modifier.getStrengthModifier(gameState, this, physicalCard); + } + return Math.max(0, result); + } finally { + LoggingThreadLocal.logMethodEnd(); } - return Math.max(0, result); } private boolean appliesStrengthModifier(GameState gameState, PhysicalCard modifierSource) { @@ -277,173 +294,233 @@ public class ModifiersLogic implements ModifiersEnvironment, ModifiersQuerying { @Override public int getVitality(GameState gameState, PhysicalCard physicalCard) { - LoggingThreadLocal.log(physicalCard, "getVitality"); - int result = physicalCard.getBlueprint().getVitality() - gameState.getWounds(physicalCard); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.VITALITY_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) - result += modifier.getVitalityModifier(gameState, this, physicalCard); + LoggingThreadLocal.logMethodStart(physicalCard, "getVitality"); + try { + int result = physicalCard.getBlueprint().getVitality() - gameState.getWounds(physicalCard); + for (Modifier modifier : getModifiers(gameState, ModifierEffect.VITALITY_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) + result += modifier.getVitalityModifier(gameState, this, physicalCard); + } + return Math.max(0, result); + } finally { + LoggingThreadLocal.logMethodEnd(); } - return Math.max(0, result); } @Override public int getResistance(GameState gameState, PhysicalCard physicalCard) { - LoggingThreadLocal.log(physicalCard, "getResistance"); - int result = physicalCard.getBlueprint().getResistance() - gameState.getBurdens(); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.RESISTANCE_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) - result += modifier.getResistanceModifier(gameState, this, physicalCard); + LoggingThreadLocal.logMethodStart(physicalCard, "getResistance"); + try { + int result = physicalCard.getBlueprint().getResistance() - gameState.getBurdens(); + for (Modifier modifier : getModifiers(gameState, ModifierEffect.RESISTANCE_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) + result += modifier.getResistanceModifier(gameState, this, physicalCard); + } + return Math.max(0, result); + } finally { + LoggingThreadLocal.logMethodEnd(); } - return Math.max(0, result); } @Override public int getMinionSiteNumber(GameState gameState, PhysicalCard physicalCard) { - LoggingThreadLocal.log(physicalCard, "getMinionSiteNumber"); - int result = physicalCard.getBlueprint().getSiteNumber(); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.SITE_NUMBER_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) - result += modifier.getMinionSiteNumberModifier(gameState, this, physicalCard); + LoggingThreadLocal.logMethodStart(physicalCard, "getMinionSiteNumber"); + try { + int result = physicalCard.getBlueprint().getSiteNumber(); + for (Modifier modifier : getModifiers(gameState, ModifierEffect.SITE_NUMBER_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) + result += modifier.getMinionSiteNumberModifier(gameState, this, physicalCard); + } + return Math.max(0, result); + } finally { + LoggingThreadLocal.logMethodEnd(); } - return Math.max(0, result); } @Override public int getTwilightCost(GameState gameState, PhysicalCard physicalCard, boolean ignoreRoamingPenalty) { - LoggingThreadLocal.log(physicalCard, "getTwilightCost"); - int result = physicalCard.getBlueprint().getTwilightCost(); - result += physicalCard.getBlueprint().getTwilightCostModifier(gameState, this, physicalCard); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.TWILIGHT_COST_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) - result += modifier.getTwilightCostModifier(gameState, this, physicalCard, ignoreRoamingPenalty); + LoggingThreadLocal.logMethodStart(physicalCard, "getTwilightCost"); + try { + int result = physicalCard.getBlueprint().getTwilightCost(); + result += physicalCard.getBlueprint().getTwilightCostModifier(gameState, this, physicalCard); + for (Modifier modifier : getModifiers(gameState, ModifierEffect.TWILIGHT_COST_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) + result += modifier.getTwilightCostModifier(gameState, this, physicalCard, ignoreRoamingPenalty); + } + return Math.max(0, result); + } finally { + LoggingThreadLocal.logMethodEnd(); } - return Math.max(0, result); } @Override public int getPlayOnTwilightCost(GameState gameState, PhysicalCard physicalCard, PhysicalCard target) { - LoggingThreadLocal.log(physicalCard, "getPlayOnTwilightCost"); - int result = getTwilightCost(gameState, physicalCard, false); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.TWILIGHT_COST_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) - result += modifier.getPlayOnTwilightCostModifier(gameState, this, physicalCard, target); + LoggingThreadLocal.logMethodStart(physicalCard, "getPlayOnTwilightCost"); + try { + int result = getTwilightCost(gameState, physicalCard, false); + for (Modifier modifier : getModifiers(gameState, ModifierEffect.TWILIGHT_COST_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) + result += modifier.getPlayOnTwilightCostModifier(gameState, this, physicalCard, target); + } + return Math.max(0, result); + } finally { + LoggingThreadLocal.logMethodEnd(); } - return Math.max(0, result); } @Override public int getRoamingPenalty(GameState gameState, PhysicalCard physicalCard) { - LoggingThreadLocal.log(physicalCard, "getRoamingPenalty"); - int result = 2; - for (Modifier modifier : getModifiers(gameState, ModifierEffect.TWILIGHT_COST_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) - result += modifier.getRoamingPenaltyModifier(gameState, this, physicalCard); + LoggingThreadLocal.logMethodStart(physicalCard, "getRoamingPenalty"); + try { + int result = 2; + for (Modifier modifier : getModifiers(gameState, ModifierEffect.TWILIGHT_COST_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, physicalCard, modifier)) + result += modifier.getRoamingPenaltyModifier(gameState, this, physicalCard); + } + return Math.max(0, result); + } finally { + LoggingThreadLocal.logMethodEnd(); } - return Math.max(0, result); } @Override public int getOverwhelmMultiplier(GameState gameState, PhysicalCard card) { - LoggingThreadLocal.log(card, "getOverwhelmMultiplier"); - int overwhelmMultiplier = 2; - for (Modifier modifier : getModifiers(gameState, ModifierEffect.OVERWHELM_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, card, modifier)) - overwhelmMultiplier = Math.max(overwhelmMultiplier, modifier.getOverwhelmMultiplier(gameState, this, card)); + LoggingThreadLocal.logMethodStart(card, "getOverwhelmMultiplier"); + try { + int overwhelmMultiplier = 2; + for (Modifier modifier : getModifiers(gameState, ModifierEffect.OVERWHELM_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, card, modifier)) + overwhelmMultiplier = Math.max(overwhelmMultiplier, modifier.getOverwhelmMultiplier(gameState, this, card)); + } + return overwhelmMultiplier; + } finally { + LoggingThreadLocal.logMethodEnd(); } - return overwhelmMultiplier; } @Override public boolean canTakeWound(GameState gameState, PhysicalCard card) { - LoggingThreadLocal.log(card, "canTakeWound"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.WOUND_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, card, modifier)) { - Integer woundsTaken = _woundsPerPhaseMap.get(card.getCardId()); - if (woundsTaken == null) - woundsTaken = 0; - if (!modifier.canTakeWound(gameState, this, card, woundsTaken)) - return false; + LoggingThreadLocal.logMethodStart(card, "canTakeWound"); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.WOUND_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, card, modifier)) { + Integer woundsTaken = _woundsPerPhaseMap.get(card.getCardId()); + if (woundsTaken == null) + woundsTaken = 0; + if (!modifier.canTakeWound(gameState, this, card, woundsTaken)) + return false; + } } + return true; + } finally { + LoggingThreadLocal.logMethodEnd(); } - return true; } @Override public boolean canTakeArcheryWound(GameState gameState, PhysicalCard card) { - LoggingThreadLocal.log(card, "canTakeArcheryWound"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.WOUND_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, card, modifier)) { - if (!modifier.canTakeArcheryWound(gameState, this, card)) - return false; + LoggingThreadLocal.logMethodStart(card, "canTakeArcheryWound"); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.WOUND_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, card, modifier)) { + if (!modifier.canTakeArcheryWound(gameState, this, card)) + return false; + } } + return true; + } finally { + LoggingThreadLocal.logMethodEnd(); } - return true; } @Override public boolean canBeExerted(GameState gameState, PhysicalCard source, PhysicalCard card) { - LoggingThreadLocal.log(card, "canBeExerted"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.WOUND_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, card, modifier)) - if (!modifier.canBeExerted(gameState, this, source, card)) - return false; + LoggingThreadLocal.logMethodStart(card, "canBeExerted"); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.WOUND_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, card, modifier)) + if (!modifier.canBeExerted(gameState, this, source, card)) + return false; + } + return true; + } finally { + LoggingThreadLocal.logMethodEnd(); } - return true; } @Override public boolean isAllyAllowedToParticipateInArcheryFire(GameState gameState, PhysicalCard card) { - LoggingThreadLocal.log(card, "isAllyAllowedToParticipateInArcheryFire"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.PRESENCE_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, card, modifier)) - if (modifier.isAllyParticipateInArcheryFire(gameState, this, card)) - return true; + LoggingThreadLocal.logMethodStart(card, "isAllyAllowedToParticipateInArcheryFire"); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.PRESENCE_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, card, modifier)) + if (modifier.isAllyParticipateInArcheryFire(gameState, this, card)) + return true; + } + return false; + } finally { + LoggingThreadLocal.logMethodEnd(); } - return false; } @Override public boolean isAllowedToParticipateInSkirmishes(GameState gameState, Side sidePlayer, PhysicalCard card) { - LoggingThreadLocal.log(card, "isAllowedToParticipateInSkirmished"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.PRESENCE_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, card, modifier)) - if (modifier.isParticipateInSkirmishes(gameState, sidePlayer, this, card)) - return true; + LoggingThreadLocal.logMethodStart(card, "isAllowedToParticipateInSkirmishes"); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.PRESENCE_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, card, modifier)) + if (modifier.isParticipateInSkirmishes(gameState, sidePlayer, this, card)) + return true; + } + return false; + } finally { + LoggingThreadLocal.logMethodEnd(); } - return false; } @Override public boolean isAllyPreventedFromParticipatingInArcheryFire(GameState gameState, PhysicalCard card) { - LoggingThreadLocal.log(card, "isAllyPreventedFromParticipatingInArcheryFire"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.PRESENCE_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, card, modifier)) - if (modifier.isAllyPreventedFromParticipatingInArcheryFire(gameState, this, card)) - return true; + LoggingThreadLocal.logMethodStart(card, "isAllyPreventedFromParticipatingInArcheryFire"); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.PRESENCE_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, card, modifier)) + if (modifier.isAllyPreventedFromParticipatingInArcheryFire(gameState, this, card)) + return true; + } + return false; + } finally { + LoggingThreadLocal.logMethodEnd(); } - return false; } @Override public boolean isAllyPreventedFromParticipatingInSkirmishes(GameState gameState, Side sidePlayer, PhysicalCard card) { - LoggingThreadLocal.log(card, "isAllyPreventedFromParticipatingInSkirmishes"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.PRESENCE_MODIFIER)) { - if (affectsCardWithSkipSet(gameState, card, modifier)) - if (modifier.isAllyPreventedFromParticipatingInSkirmishes(gameState, sidePlayer, this, card)) - return true; + LoggingThreadLocal.logMethodStart(card, "isAllyPreventedFromParticipatingInSkirmishes"); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.PRESENCE_MODIFIER)) { + if (affectsCardWithSkipSet(gameState, card, modifier)) + if (modifier.isAllyPreventedFromParticipatingInSkirmishes(gameState, sidePlayer, this, card)) + return true; + } + return false; + } finally { + LoggingThreadLocal.logMethodEnd(); } - return false; } @Override public boolean addsToArcheryTotal(GameState gameState, PhysicalCard card) { - LoggingThreadLocal.log(card, "addsToArcheryTotal"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.ARCHERY_MODIFIER)) - if (affectsCardWithSkipSet(gameState, card, modifier)) - if (!modifier.addsToArcheryTotal(gameState, this, card)) - return false; + LoggingThreadLocal.logMethodStart(card, "addsToArcheryTotal"); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.ARCHERY_MODIFIER)) + if (affectsCardWithSkipSet(gameState, card, modifier)) + if (!modifier.addsToArcheryTotal(gameState, this, card)) + return false; - return true; + return true; + } finally { + LoggingThreadLocal.logMethodEnd(); + } } @Override @@ -512,32 +589,44 @@ public class ModifiersLogic implements ModifiersEnvironment, ModifiersQuerying { @Override public boolean canBeAssignedToSkirmish(GameState gameState, Side sidePlayer, PhysicalCard card) { - LoggingThreadLocal.log(card, "canBeAssignedToSkirmish"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.ASSIGNMENT_MODIFIER)) - if (affectsCardWithSkipSet(gameState, card, modifier)) - if (!modifier.canBeAssignedToSkirmish(gameState, sidePlayer, this, card)) - return false; - return true; + LoggingThreadLocal.logMethodStart(card, "canBeAssignedToSkirmish"); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.ASSIGNMENT_MODIFIER)) + if (affectsCardWithSkipSet(gameState, card, modifier)) + if (!modifier.canBeAssignedToSkirmish(gameState, sidePlayer, this, card)) + return false; + return true; + } finally { + LoggingThreadLocal.logMethodEnd(); + } } @Override public boolean canBeDiscardedFromPlay(GameState gameState, PhysicalCard card, PhysicalCard source) { - LoggingThreadLocal.log(card, "canBeDiscardedFromPlay"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.DISCARD_FROM_PLAY_MODIFIER)) - if (affectsCardWithSkipSet(gameState, card, modifier)) - if (!modifier.canBeDiscardedFromPlay(gameState, this, card, source)) - return false; - return true; + LoggingThreadLocal.logMethodStart(card, "canBeDiscardedFromPlay"); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.DISCARD_FROM_PLAY_MODIFIER)) + if (affectsCardWithSkipSet(gameState, card, modifier)) + if (!modifier.canBeDiscardedFromPlay(gameState, this, card, source)) + return false; + return true; + } finally { + LoggingThreadLocal.logMethodEnd(); + } } @Override public boolean canBeHealed(GameState gameState, PhysicalCard card) { - LoggingThreadLocal.log(card, "canBeHealed"); - for (Modifier modifier : getModifiers(gameState, ModifierEffect.WOUND_MODIFIER)) - if (affectsCardWithSkipSet(gameState, card, modifier)) - if (!modifier.canBeHealed(gameState, this, card)) - return false; - return true; + LoggingThreadLocal.logMethodStart(card, "canBeHealed"); + try { + for (Modifier modifier : getModifiers(gameState, ModifierEffect.WOUND_MODIFIER)) + if (affectsCardWithSkipSet(gameState, card, modifier)) + if (!modifier.canBeHealed(gameState, this, card)) + return false; + return true; + } finally { + LoggingThreadLocal.logMethodEnd(); + } } @Override diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/RemoveKeywordModifier.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/RemoveKeywordModifier.java index 9c6876769..1be8af0f0 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/RemoveKeywordModifier.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/RemoveKeywordModifier.java @@ -5,12 +5,11 @@ import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.state.GameState; -public class RemoveKeywordModifier extends AbstractModifier { +public class RemoveKeywordModifier extends AbstractModifier implements KeywordAffectingModifier { private Keyword _keyword; public RemoveKeywordModifier(PhysicalCard physicalCard, Filterable affectFilter, Keyword keyword) { - super(physicalCard, "Loses " + keyword.getHumanReadable() + "keyword(s)", affectFilter, ModifierEffect.KEYWORD_MODIFIER); - _keyword = keyword; + this(physicalCard, affectFilter, null, keyword); } public RemoveKeywordModifier(PhysicalCard physicalCard, Filterable affectFilter, Condition condition, Keyword keyword) { @@ -18,6 +17,11 @@ public class RemoveKeywordModifier extends AbstractModifier { _keyword = keyword; } + @Override + public Keyword getKeyword() { + return _keyword; + } + @Override public boolean isKeywordRemoved(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard, Keyword keyword) { return _keyword == keyword; diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java index e9a95ea5f..e51dd057a 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java @@ -1,10 +1,9 @@ package com.gempukku.lotro.logic.timing; -import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.communication.GameStateListener; import com.gempukku.lotro.communication.UserFeedback; -import com.gempukku.lotro.filters.Filters; import com.gempukku.lotro.game.ActionsEnvironment; import com.gempukku.lotro.game.LotroCardBlueprintLibrary; import com.gempukku.lotro.game.LotroFormat; @@ -175,12 +174,13 @@ public class DefaultLotroGame implements LotroGame { GameState gameState = getGameState(); if (gameState != null && gameState.getCurrentPhase() != Phase.PLAY_STARTING_FELLOWSHIP && gameState.getCurrentPhase() != Phase.BETWEEN_TURNS && gameState.getCurrentPhase() != Phase.PUT_RING_BEARER) { // Ring-bearer death - if (!Filters.canSpot(gameState, getModifiersQuerying(), Filters.keyword(Keyword.RING_BEARER))) { + PhysicalCard ringBearer = gameState.getRingBearer(gameState.getCurrentPlayerId()); + Zone zone = ringBearer.getZone(); + if (zone == null || !zone.isInPlay()) { playerLost(getGameState().getCurrentPlayerId(), "The Ring-Bearer is dead"); return; } else { // Ring-bearer corruption - PhysicalCard ringBearer = Filters.findFirstActive(getGameState(), getModifiersQuerying(), Filters.keyword(Keyword.RING_BEARER)); int ringBearerResistance = getModifiersQuerying().getResistance(getGameState(), ringBearer); if (ringBearerResistance <= 0) { playerLost(getGameState().getCurrentPlayerId(), "The Ring-Bearer is corrupted"); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java index f1a972e94..38195c40a 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java @@ -13,13 +13,6 @@ import com.gempukku.lotro.logic.modifiers.ModifiersQuerying; public class RuleUtils { public static int calculateFellowshipArcheryTotal(LotroGame game) { int normalArcheryTotal = Filters.countActive(game.getGameState(), game.getModifiersQuerying(), - Filters.keyword(Keyword.ARCHER), - new Filter() { - @Override - public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { - return modifiersQuerying.addsToArcheryTotal(gameState, physicalCard); - } - }, Filters.or( Filters.type(CardType.COMPANION), Filters.and( @@ -40,21 +33,28 @@ public class RuleUtils { } }) ) - )); - - return game.getModifiersQuerying().getArcheryTotal(game.getGameState(), Side.FREE_PEOPLE, normalArcheryTotal); - } - - public static int calculateShadowArcheryTotal(LotroGame game) { - int normalArcheryTotal = Filters.countActive(game.getGameState(), game.getModifiersQuerying(), + ), Filters.keyword(Keyword.ARCHER), new Filter() { @Override public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { return modifiersQuerying.addsToArcheryTotal(gameState, physicalCard); } - }, - Filters.type(CardType.MINION)); + }); + + return game.getModifiersQuerying().getArcheryTotal(game.getGameState(), Side.FREE_PEOPLE, normalArcheryTotal); + } + + public static int calculateShadowArcheryTotal(LotroGame game) { + int normalArcheryTotal = Filters.countActive(game.getGameState(), game.getModifiersQuerying(), + Filters.type(CardType.MINION), + Filters.keyword(Keyword.ARCHER), + new Filter() { + @Override + public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { + return modifiersQuerying.addsToArcheryTotal(gameState, physicalCard); + } + }); return game.getModifiersQuerying().getArcheryTotal(game.getGameState(), Side.SHADOW, normalArcheryTotal); } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TurnProcedure.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TurnProcedure.java index a877f145d..6afca4506 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TurnProcedure.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TurnProcedure.java @@ -9,6 +9,7 @@ import com.gempukku.lotro.logic.actions.SystemQueueAction; import com.gempukku.lotro.logic.decisions.ActionSelectionDecision; import com.gempukku.lotro.logic.decisions.CardActionSelectionDecision; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.modifiers.LoggingThreadLocal; import com.gempukku.lotro.logic.timing.actions.SystemAction; import com.gempukku.lotro.logic.timing.processes.GameProcess; import com.gempukku.lotro.logic.timing.processes.pregame.BiddingGameProcess; @@ -106,10 +107,20 @@ public class TurnProcedure { Side initiativePreEffect = _game.getModifiersQuerying().hasInitiative(_game.getGameState()); - final Collection effectResults = _effect.playEffect(_game); List results = new LinkedList(); - if (effectResults != null) - results.addAll(effectResults); + + Action topmostAction = _actionStack.getTopmostAction(); + if (topmostAction != null && topmostAction.getActionSource() != null) + LoggingThreadLocal.logMethodStart(topmostAction.getActionSource(), "playEffect"); + + try { + final Collection effectResults = _effect.playEffect(_game); + if (effectResults != null) + results.addAll(effectResults); + } finally { + if (topmostAction != null && topmostAction.getActionSource() != null) + LoggingThreadLocal.logMethodEnd(); + } Side initiativePostEffect = _game.getModifiersQuerying().hasInitiative(_game.getGameState()); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/actions/SystemAction.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/actions/SystemAction.java index 5f5f07f8b..ac5cddda7 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/actions/SystemAction.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/actions/SystemAction.java @@ -8,12 +8,12 @@ import com.gempukku.lotro.logic.timing.Action; public abstract class SystemAction implements Action { @Override public PhysicalCard getActionSource() { - throw new UnsupportedOperationException("System action has no action source"); + return null; } @Override public PhysicalCard getActionAttachedToCard() { - throw new UnsupportedOperationException("System action has no action source"); + return null; } @Override @@ -36,6 +36,6 @@ public abstract class SystemAction implements Action { @Override public String getText(LotroGame game) { - throw new UnsupportedOperationException("System action has no text"); + return null; } } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/EnduringRule.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/EnduringRule.java index 883a308fd..e05831113 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/EnduringRule.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/EnduringRule.java @@ -18,7 +18,7 @@ public class EnduringRule { public void applyRule() { _modifiersLogic.addAlwaysOnModifier( - new StrengthModifier(null, Filters.and(Keyword.ENDURING, Filters.wounded), null, + new StrengthModifier(null, Filters.and(Filters.wounded, Keyword.ENDURING), null, new Evaluator() { @Override public int evaluateExpression(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard self) { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/RoamingRule.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/RoamingRule.java index 5825ea106..e29cca01c 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/RoamingRule.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/RoamingRule.java @@ -27,7 +27,7 @@ public class RoamingRule { new KeywordModifier(null, roamingFilter, Keyword.ROAMING)); _modifiersLogic.addAlwaysOnModifier( - new AbstractModifier(null, null, Keyword.ROAMING, ModifierEffect.TWILIGHT_COST_MODIFIER) { + new AbstractModifier(null, null, Filters.and(CardType.MINION, Keyword.ROAMING), ModifierEffect.TWILIGHT_COST_MODIFIER) { @Override public int getTwilightCostModifier(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard, boolean ignoreRoamingPenalty) { if (ignoreRoamingPenalty)