From 82a5250ac9243f40c376cadfce43aa7bfd55030c Mon Sep 17 00:00:00 2001 From: marcins78 Date: Fri, 25 Jul 2014 15:05:58 +0000 Subject: [PATCH] Introducing adventures. --- .../lotro/cards/AbstractAdventure.java | 22 +++++ .../com/gempukku/lotro/common/CardType.java | 2 +- .../game/adventure/DefaultSoloAdventure.java | 94 +++++++++++++++++++ .../lotro/game/adventure/ShadowAI.java | 8 ++ .../lotro/game/adventure/SiteSelection.java | 7 ++ .../lotro/game/adventure/SoloAdventure.java | 20 ++++ .../gempukku/lotro/game/state/GameState.java | 37 ++++++-- .../gempukku/lotro/game/state/LotroGame.java | 3 + .../modifiers/CantReturnToHandModifier.java | 6 +- .../lotro/logic/timing/DefaultLotroGame.java | 9 ++ .../SetupSoloAdventureGameProcess.java | 50 ++++++++++ .../ShadowPhaseOfAIPlayerGameProcess.java | 34 +++++++ ...IPlayerAssignsArcheryTotalGameProcess.java | 89 ++++++++++++++++++ ...PlayAdventureShadowActionsGameProcess.java | 34 +++++++ ...PlayerAssignsArcheryDamageGameProcess.java | 5 +- 15 files changed, 406 insertions(+), 14 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/AbstractAdventure.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/DefaultSoloAdventure.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/ShadowAI.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/SiteSelection.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/SoloAdventure.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/pregame/SetupSoloAdventureGameProcess.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ShadowPhaseOfAIPlayerGameProcess.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ai/AIPlayerAssignsArcheryTotalGameProcess.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ai/PlayAdventureShadowActionsGameProcess.java diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/AbstractAdventure.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/AbstractAdventure.java new file mode 100644 index 000000000..80f3705ad --- /dev/null +++ b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/AbstractAdventure.java @@ -0,0 +1,22 @@ +package com.gempukku.lotro.cards; + +import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.actions.CostToEffectAction; + +public class AbstractAdventure extends AbstractLotroCardBlueprint { + public AbstractAdventure(String name, String subTitle) { + super(null, CardType.ADVENTURE, null, name, subTitle, true); + } + + @Override + public CostToEffectAction getPlayCardAction(String playerId, LotroGame game, PhysicalCard self, int twilightModifier, boolean ignoreRoamingPenalty) { + return null; + } + + @Override + public int getTwilightCost() { + return 0; + } +} diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/CardType.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/CardType.java index 9d825131f..7579e4b7e 100644 --- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/CardType.java +++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/CardType.java @@ -1,5 +1,5 @@ package com.gempukku.lotro.common; public enum CardType implements Filterable { - THE_ONE_RING, SITE, COMPANION, ALLY, MINION, POSSESSION, ARTIFACT, EVENT, CONDITION, FOLLOWER + THE_ONE_RING, SITE, COMPANION, ALLY, MINION, POSSESSION, ARTIFACT, EVENT, CONDITION, FOLLOWER, ADVENTURE } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/DefaultSoloAdventure.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/DefaultSoloAdventure.java new file mode 100644 index 000000000..cce992677 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/DefaultSoloAdventure.java @@ -0,0 +1,94 @@ +package com.gempukku.lotro.game.adventure; + +import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.LotroCardBlueprintLibrary; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.game.state.GameState; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.GameUtils; +import com.gempukku.lotro.logic.actions.SystemQueueAction; +import com.gempukku.lotro.logic.timing.PlayerOrderFeedback; +import com.gempukku.lotro.logic.timing.UnrespondableEffect; +import com.gempukku.lotro.logic.timing.processes.GameProcess; +import com.gempukku.lotro.logic.timing.processes.pregame.SetupSoloAdventureGameProcess; +import com.gempukku.lotro.logic.timing.processes.turn.ShadowPhaseOfAIPlayerGameProcess; +import com.gempukku.lotro.logic.timing.processes.turn.ai.AIPlayerAssignsArcheryTotalGameProcess; +import com.gempukku.lotro.logic.timing.results.PlayCardResult; + +import java.util.Set; + +public class DefaultSoloAdventure extends SoloAdventure { + private LotroCardBlueprintLibrary _library; + private SiteSelection _siteSelection; + private ShadowAI _shadowAI; + private String _adventureCard; + private String _startingSite; + + public DefaultSoloAdventure(LotroCardBlueprintLibrary library, + SiteSelection siteSelection, ShadowAI shadowAI, + String adventureCard, String startingSite) { + _library = library; + _siteSelection = siteSelection; + _shadowAI = shadowAI; + _adventureCard = adventureCard; + _startingSite = startingSite; + } + + @Override + public void appendNextSiteAction(SystemQueueAction action) { + action.appendEffect( + new UnrespondableEffect() { + @Override + protected void doPlayEffect(LotroGame game) { + final GameState gameState = game.getGameState(); + try { + PhysicalCard newSite = gameState.createPhysicalCard("AI", _library, _siteSelection.getNextSite(game)); + newSite.setSiteNumber(gameState.getCurrentSiteNumber() + 1); + gameState.addCardToZone(game, newSite, Zone.ADVENTURE_PATH); + gameState.sendMessage(newSite.getOwner() + " plays " + GameUtils.getCardLink(newSite)); + + game.getActionsEnvironment().emitEffectResult(new PlayCardResult(Zone.ADVENTURE_DECK, newSite, null, null, false)); + } catch (CardNotFoundException exp) { + throw new RuntimeException("Unable to create a requested card", exp); + } + } + }); + } + + @Override + public GameProcess getStartingGameProcess(Set players, PlayerOrderFeedback playerOrderFeedback) { + final String player = players.iterator().next(); + return new SetupSoloAdventureGameProcess(_adventureCard, _startingSite, player, playerOrderFeedback); + } + + @Override + public GameProcess getAfterFellowshipPhaseGameProcess() { + return new ShadowPhaseOfAIPlayerGameProcess(_shadowAI); + } + + @Override + public GameProcess getAfterFellowshipArcheryGameProcess(int fellowshipArcheryTotal, GameProcess followingProcess) { + return new AIPlayerAssignsArcheryTotalGameProcess(fellowshipArcheryTotal, followingProcess); + } + + @Override + public GameProcess getAfterFellowshipAssignmentGameProcess(Set leftoverMinions, GameProcess followingProcess) { + return null; + } + + @Override + public GameProcess getBeforeFellowshipChooseToMoveGameProcess(GameProcess followingProcess) { + return null; + } + + @Override + public GameProcess getPlayerStaysGameProcess(LotroGame game, GameProcess followingProcess) { + return null; + } + + @Override + public boolean isSolo() { + return false; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/ShadowAI.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/ShadowAI.java new file mode 100644 index 000000000..c6a3d8961 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/ShadowAI.java @@ -0,0 +1,8 @@ +package com.gempukku.lotro.game.adventure; + +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.timing.Action; + +public interface ShadowAI { + public Action getNextShadowAction(LotroGame game); +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/SiteSelection.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/SiteSelection.java new file mode 100644 index 000000000..6072d756a --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/SiteSelection.java @@ -0,0 +1,7 @@ +package com.gempukku.lotro.game.adventure; + +import com.gempukku.lotro.game.state.LotroGame; + +public interface SiteSelection { + public String getNextSite(LotroGame game); +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/SoloAdventure.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/SoloAdventure.java new file mode 100644 index 000000000..505e6a08f --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/adventure/SoloAdventure.java @@ -0,0 +1,20 @@ +package com.gempukku.lotro.game.adventure; + +import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.filters.Filters; +import com.gempukku.lotro.game.Adventure; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.game.state.actions.DefaultActionsEnvironment; +import com.gempukku.lotro.logic.modifiers.CantDiscardFromPlayModifier; +import com.gempukku.lotro.logic.modifiers.CantReturnToHandModifier; +import com.gempukku.lotro.logic.modifiers.ModifiersLogic; + +public abstract class SoloAdventure implements Adventure { + @Override + public void applyAdventureRules(LotroGame game, DefaultActionsEnvironment actionsEnvironment, ModifiersLogic modifiersLogic) { + modifiersLogic.addAlwaysOnModifier( + new CantDiscardFromPlayModifier(null, "Can't be discarded from play", CardType.ADVENTURE, Filters.any)); + modifiersLogic.addAlwaysOnModifier( + new CantReturnToHandModifier(null, "Can't be returned to hand", CardType.ADVENTURE, Filters.any)); + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java index f874703c5..b4112fd2f 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java @@ -1,15 +1,34 @@ package com.gempukku.lotro.game.state; -import com.gempukku.lotro.common.*; +import com.gempukku.lotro.common.Block; +import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Side; +import com.gempukku.lotro.common.Token; +import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.communication.GameStateListener; -import com.gempukku.lotro.game.*; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.LotroCardBlueprint; +import com.gempukku.lotro.game.LotroCardBlueprintLibrary; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.game.PhysicalCardVisitor; import com.gempukku.lotro.logic.PlayerOrder; import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.modifiers.ModifierFlag; import com.gempukku.lotro.logic.timing.GameStats; import org.apache.log4j.Logger; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; public class GameState { private static Logger _log = Logger.getLogger(GameState.class); @@ -85,8 +104,8 @@ public class GameState { addPlayerCards(playerId, decks, library); try { - _ringBearers.put(playerId, createPhysicalCard(playerId, library, ringBearers.get(playerId))); - _rings.put(playerId, createPhysicalCard(playerId, library, rings.get(playerId))); + _ringBearers.put(playerId, createPhysicalCardImpl(playerId, library, ringBearers.get(playerId))); + _rings.put(playerId, createPhysicalCardImpl(playerId, library, rings.get(playerId))); } catch (CardNotFoundException exp) { throw new RuntimeException("Unable to create game, due to either ring-bearer or ring being invalid cards"); } @@ -110,7 +129,7 @@ public class GameState { private void addPlayerCards(String playerId, List cards, LotroCardBlueprintLibrary library) { for (String blueprintId : cards) { try { - PhysicalCardImpl physicalCard = createPhysicalCard(playerId, library, blueprintId); + PhysicalCardImpl physicalCard = createPhysicalCardImpl(playerId, library, blueprintId); if (physicalCard.getBlueprint().getCardType() == CardType.SITE) { physicalCard.setZone(Zone.ADVENTURE_DECK); _adventureDecks.get(playerId).add(physicalCard); @@ -124,7 +143,11 @@ public class GameState { } } - private PhysicalCardImpl createPhysicalCard(String playerId, LotroCardBlueprintLibrary library, String blueprintId) throws CardNotFoundException { + public PhysicalCard createPhysicalCard(String ownerPlayerId, LotroCardBlueprintLibrary library, String blueprintId) throws CardNotFoundException { + return createPhysicalCardImpl(ownerPlayerId, library, blueprintId); + } + + private PhysicalCardImpl createPhysicalCardImpl(String playerId, LotroCardBlueprintLibrary library, String blueprintId) throws CardNotFoundException { LotroCardBlueprint card = library.getLotroCardBlueprint(blueprintId); int cardId = nextCardId(); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/LotroGame.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/LotroGame.java index 892fdaaf2..d0b5cf5a5 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/LotroGame.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/LotroGame.java @@ -3,6 +3,7 @@ package com.gempukku.lotro.game.state; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.communication.UserFeedback; import com.gempukku.lotro.game.ActionsEnvironment; +import com.gempukku.lotro.game.LotroCardBlueprintLibrary; import com.gempukku.lotro.game.LotroFormat; import com.gempukku.lotro.logic.modifiers.ModifiersEnvironment; import com.gempukku.lotro.logic.modifiers.ModifiersQuerying; @@ -10,6 +11,8 @@ import com.gempukku.lotro.logic.modifiers.ModifiersQuerying; public interface LotroGame { public GameState getGameState(); + public LotroCardBlueprintLibrary getLotroCardBlueprintLibrary(); + public ModifiersEnvironment getModifiersEnvironment(); public ModifiersQuerying getModifiersQuerying(); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/CantReturnToHandModifier.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/CantReturnToHandModifier.java index e55e1c85b..e829762c3 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/CantReturnToHandModifier.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/CantReturnToHandModifier.java @@ -1,15 +1,17 @@ package com.gempukku.lotro.logic.modifiers; +import com.gempukku.lotro.common.Filterable; import com.gempukku.lotro.filters.Filter; +import com.gempukku.lotro.filters.Filters; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.state.GameState; public class CantReturnToHandModifier extends AbstractModifier { private Filter _sourceFilter; - public CantReturnToHandModifier(PhysicalCard source, String text, Filter affectFilter, Filter sourceFilter) { + public CantReturnToHandModifier(PhysicalCard source, String text, Filterable affectFilter, Filterable sourceFilter) { super(source, text, affectFilter, ModifierEffect.RETURN_TO_HAND_MODIFIER); - _sourceFilter = sourceFilter; + _sourceFilter = Filters.and(sourceFilter); } @Override 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 36fd3d921..c267da2ce 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 @@ -51,8 +51,10 @@ public class DefaultLotroGame implements LotroGame { private Set _gameResultListeners = new HashSet(); private Set _requestedCancel = new HashSet(); + private LotroCardBlueprintLibrary _library; public DefaultLotroGame(LotroFormat format, Map decks, UserFeedback userFeedback, final LotroCardBlueprintLibrary library) { + _library = library; _adventure = format.getAdventure(); _format = format; _actionStack = new ActionStack(); @@ -97,6 +99,8 @@ public class DefaultLotroGame implements LotroGame { _adventure.applyAdventureRules(this, _actionsEnvironment, _modifiersLogic); } + + @Override public boolean shouldAutoPass(String playerId, Phase phase) { final Set passablePhases = _autoPassConfiguration.get(playerId); @@ -231,6 +235,11 @@ public class DefaultLotroGame implements LotroGame { return _gameState; } + @Override + public LotroCardBlueprintLibrary getLotroCardBlueprintLibrary() { + return _library; + } + @Override public ActionsEnvironment getActionsEnvironment() { return _actionsEnvironment; diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/pregame/SetupSoloAdventureGameProcess.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/pregame/SetupSoloAdventureGameProcess.java new file mode 100644 index 000000000..5ae6294d1 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/pregame/SetupSoloAdventureGameProcess.java @@ -0,0 +1,50 @@ +package com.gempukku.lotro.logic.timing.processes.pregame; + +import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.game.state.GameState; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.PlayerOrder; +import com.gempukku.lotro.logic.timing.PlayerOrderFeedback; +import com.gempukku.lotro.logic.timing.processes.GameProcess; + +import java.util.Arrays; +import java.util.Collections; + +public class SetupSoloAdventureGameProcess implements GameProcess { + private String _startingSite; + private String _player; + private PlayerOrderFeedback _playerOrderFeedback; + private String _adventureCard; + + public SetupSoloAdventureGameProcess(String adventureCard, String startingSite, String player, PlayerOrderFeedback playerOrderFeedback) { + _adventureCard = adventureCard; + _startingSite = startingSite; + _player = player; + _playerOrderFeedback = playerOrderFeedback; + } + + @Override + public void process(LotroGame game) { + _playerOrderFeedback.setPlayerOrder(new PlayerOrder(Arrays.asList(_player)), _player); + final GameState gameState = game.getGameState(); + try { + final PhysicalCard adventureCard = gameState.createPhysicalCard(_player, game.getLotroCardBlueprintLibrary(), _adventureCard); + gameState.addCardToZone(game, adventureCard, Zone.SUPPORT); + + final PhysicalCard startingSite = gameState.createPhysicalCard("AI", game.getLotroCardBlueprintLibrary(), _startingSite); + startingSite.setSiteNumber(1); + gameState.addCardToZone(game, startingSite, Zone.ADVENTURE_PATH); + + game.getGameState().setPlayerPosition(_player, 1); + } catch (CardNotFoundException exp) { + // Ignore + } + } + + @Override + public GameProcess getNextProcess() { + return new PlayRingBearerRingAndAddBurdersGameProcess(Collections.singletonMap(_player, 0), _player); + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ShadowPhaseOfAIPlayerGameProcess.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ShadowPhaseOfAIPlayerGameProcess.java new file mode 100644 index 000000000..9146886ed --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ShadowPhaseOfAIPlayerGameProcess.java @@ -0,0 +1,34 @@ +package com.gempukku.lotro.logic.timing.processes.turn; + +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.adventure.ShadowAI; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.timing.processes.GameProcess; +import com.gempukku.lotro.logic.timing.processes.turn.ai.PlayAdventureShadowActionsGameProcess; +import com.gempukku.lotro.logic.timing.processes.turn.general.EndOfPhaseGameProcess; +import com.gempukku.lotro.logic.timing.processes.turn.general.StartOfPhaseGameProcess; + +public class ShadowPhaseOfAIPlayerGameProcess implements GameProcess { + private GameProcess _followingGameProcess; + private ShadowAI _shadowAI; + + public ShadowPhaseOfAIPlayerGameProcess(ShadowAI shadowAI) { + _shadowAI = shadowAI; + } + + @Override + public void process(LotroGame game) { + if (game.getModifiersQuerying().shouldSkipPhase(game.getGameState(), Phase.SHADOW, "AI")) + _followingGameProcess = new ManeuverGameProcess(); + else + _followingGameProcess = new StartOfPhaseGameProcess(Phase.SHADOW, "AI", + new PlayAdventureShadowActionsGameProcess(_shadowAI, + new EndOfPhaseGameProcess(Phase.SHADOW, + new ManeuverGameProcess()))); + } + + @Override + public GameProcess getNextProcess() { + return _followingGameProcess; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ai/AIPlayerAssignsArcheryTotalGameProcess.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ai/AIPlayerAssignsArcheryTotalGameProcess.java new file mode 100644 index 000000000..91d02cfc6 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ai/AIPlayerAssignsArcheryTotalGameProcess.java @@ -0,0 +1,89 @@ +package com.gempukku.lotro.logic.timing.processes.turn.ai; + +import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.filters.Filter; +import com.gempukku.lotro.filters.Filters; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.game.state.GameState; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.actions.SubAction; +import com.gempukku.lotro.logic.actions.SystemQueueAction; +import com.gempukku.lotro.logic.effects.WoundCharactersEffect; +import com.gempukku.lotro.logic.modifiers.ModifiersQuerying; +import com.gempukku.lotro.logic.timing.UnrespondableEffect; +import com.gempukku.lotro.logic.timing.processes.GameProcess; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Random; + +public class AIPlayerAssignsArcheryTotalGameProcess implements GameProcess { + private int _woundsToAssign; + private GameProcess _followingProcess; + + public AIPlayerAssignsArcheryTotalGameProcess(int woundsToAssign, GameProcess followingProcess) { + _woundsToAssign = woundsToAssign; + _followingProcess = followingProcess; + } + + @Override + public void process(LotroGame game) { + if (_woundsToAssign > 0) { + final Filter filterPriority = + Filters.and( + CardType.MINION, + Filters.owner("AI"), + new Filter() { + @Override + public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { + return modifiersQuerying.canTakeArcheryWound(gameState, physicalCard) + && gameState.getWounds(physicalCard) < modifiersQuerying.getVitality(gameState, physicalCard) - 1; + } + }); + + final Filter filterFallback = + Filters.and( + CardType.MINION, + Filters.owner("AI"), + new Filter() { + @Override + public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) { + return modifiersQuerying.canTakeArcheryWound(gameState, physicalCard); + } + } + ); + + final SystemQueueAction action = new SystemQueueAction(); + for (int i = 0; i < _woundsToAssign; i++) { + UnrespondableEffect chooseRandomMinionAndWound = new UnrespondableEffect() { + @Override + protected void doPlayEffect(LotroGame game) { + Collection acceptableCards = Filters.filterActive(game.getGameState(), game.getModifiersQuerying(), filterPriority); + if (acceptableCards.size() == 0) + acceptableCards = Filters.filterActive(game.getGameState(), game.getModifiersQuerying(), filterFallback); + + List possibleChoices = new ArrayList(acceptableCards); + if (possibleChoices.size()>0) { + SubAction subAction = new SubAction(action); + Random rnd = new Random(); + final int randomIndex = rnd.nextInt(possibleChoices.size()); + WoundCharactersEffect woundCharacter = new WoundCharactersEffect((PhysicalCard) null, possibleChoices.get(randomIndex)); + woundCharacter.setSourceText("Archery Fire"); + subAction.appendEffect(woundCharacter); + game.getActionsEnvironment().addActionToStack(subAction); + } + } + }; + action.appendEffect(chooseRandomMinionAndWound); + } + + game.getActionsEnvironment().addActionToStack(action); + } + } + + @Override + public GameProcess getNextProcess() { + return _followingProcess; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ai/PlayAdventureShadowActionsGameProcess.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ai/PlayAdventureShadowActionsGameProcess.java new file mode 100644 index 000000000..8a5a43c13 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/ai/PlayAdventureShadowActionsGameProcess.java @@ -0,0 +1,34 @@ +package com.gempukku.lotro.logic.timing.processes.turn.ai; + +import com.gempukku.lotro.game.adventure.ShadowAI; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.timing.Action; +import com.gempukku.lotro.logic.timing.processes.GameProcess; + +public class PlayAdventureShadowActionsGameProcess implements GameProcess { + private ShadowAI _shadowAI; + private GameProcess _followingGameProcess; + + private GameProcess _nextProcess; + + public PlayAdventureShadowActionsGameProcess(ShadowAI shadowAI, GameProcess followingGameProcess) { + _shadowAI = shadowAI; + _followingGameProcess = followingGameProcess; + } + + @Override + public void process(LotroGame game) { + Action action = _shadowAI.getNextShadowAction(game); + if (action != null) { + game.getActionsEnvironment().addActionToStack(action); + _nextProcess = new PlayAdventureShadowActionsGameProcess(_shadowAI, _followingGameProcess); + } else { + _nextProcess = _followingGameProcess; + } + } + + @Override + public GameProcess getNextProcess() { + return _nextProcess; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/archery/ShadowPlayerAssignsArcheryDamageGameProcess.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/archery/ShadowPlayerAssignsArcheryDamageGameProcess.java index 774fffa67..ff990ecf9 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/archery/ShadowPlayerAssignsArcheryDamageGameProcess.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/archery/ShadowPlayerAssignsArcheryDamageGameProcess.java @@ -16,8 +16,6 @@ public class ShadowPlayerAssignsArcheryDamageGameProcess implements GameProcess private int _woundsToAssign; private GameProcess _followingGameProcess; - private GameProcess _nextProcess; - public ShadowPlayerAssignsArcheryDamageGameProcess(String playerId, int woundsToAssign, GameProcess followingGameProcess) { _playerId = playerId; _woundsToAssign = woundsToAssign; @@ -49,11 +47,10 @@ public class ShadowPlayerAssignsArcheryDamageGameProcess implements GameProcess game.getActionsEnvironment().addActionToStack(action); } - _nextProcess = _followingGameProcess; } @Override public GameProcess getNextProcess() { - return _nextProcess; + return _followingGameProcess; } }