"Treebeard"

And Unhasty keyword.
This commit is contained in:
marcins78@gmail.com
2011-10-08 00:41:44 +00:00
parent 3a8c46cfef
commit 4a171d27a9
15 changed files with 151 additions and 37 deletions

View File

@@ -14,7 +14,7 @@ import java.util.List;
public class AbstractAlly extends AbstractPermanent {
private Block _siteBlock;
private int _siteNumber;
private int[] _siteNumbers;
private int _strength;
private int _vitality;
private Race _race;
@@ -24,9 +24,17 @@ public class AbstractAlly extends AbstractPermanent {
}
public AbstractAlly(int twilight, Block siteBlock, int siteNumber, int strength, int vitality, Race race, Culture culture, String name, boolean unique) {
this(twilight, siteBlock, new int[]{siteNumber}, strength, vitality, race, culture, name, unique);
}
public AbstractAlly(int twilight, Block siteBlock, int[] siteNumbers, int strength, int vitality, Race race, Culture culture, String name) {
this(twilight, siteBlock, siteNumbers, strength, vitality, race, culture, name, false);
}
public AbstractAlly(int twilight, Block siteBlock, int[] siteNumbers, int strength, int vitality, Race race, Culture culture, String name, boolean unique) {
super(Side.FREE_PEOPLE, twilight, CardType.ALLY, culture, Zone.SUPPORT, name, unique);
_siteBlock = siteBlock;
_siteNumber = siteNumber;
_siteNumbers = siteNumbers;
_strength = strength;
_vitality = vitality;
_race = race;
@@ -55,13 +63,13 @@ public class AbstractAlly extends AbstractPermanent {
}
@Override
public Block getSiteBlock() {
return _siteBlock;
}
@Override
public final int getSiteNumber() {
return _siteNumber;
public final boolean isAllyAtHome(int siteNumber, Block block) {
if (block != _siteBlock)
return false;
for (int number : _siteNumbers)
if (number == siteNumber)
return true;
return false;
}
@Override

View File

@@ -48,16 +48,15 @@ public abstract class AbstractAttachableFPPossession extends AbstractAttachable
validTransferFilter = Filters.and(validTargetFilter,
Filters.or(
Filters.type(CardType.COMPANION),
Filters.allyOnHomeSite()));
} else if (attachedTo.getSiteNumber() == gameState.getCurrentSiteNumber()
&& attachedTo.getSiteBlock() == gameState.getCurrentSite().getBlueprint().getSiteBlock()) {
Filters.isAllyAtHome()));
} else if (attachedTo.isAllyAtHome(gameState.getCurrentSiteNumber(), gameState.getCurrentSite().getBlueprint().getSiteBlock())) {
validTransferFilter = Filters.and(validTargetFilter,
Filters.or(
Filters.type(CardType.COMPANION),
Filters.allyOnHomeSite()));
Filters.isAllyAtHome()));
} else {
validTransferFilter = Filters.and(validTargetFilter,
Filters.type(CardType.ALLY), Filters.siteNumber(attachedTo.getSiteNumber()), Filters.siteBlock(attachedTo.getSiteBlock())
Filters.type(CardType.ALLY), Filters.isAllyAtHome()
);
}

View File

@@ -115,6 +115,11 @@ public abstract class AbstractLotroCardBlueprint implements LotroCardBlueprint {
throw new UnsupportedOperationException("This method should not be called on this card");
}
@Override
public boolean isAllyAtHome(int siteNumber, Block siteBlock) {
throw new UnsupportedOperationException("This method should not be called on this card");
}
@Override
public Block getSiteBlock() {
throw new UnsupportedOperationException("This method should not be called on this card");

View File

@@ -1,5 +1,8 @@
package com.gempukku.lotro.cards.modifiers;
import com.gempukku.lotro.common.Culture;
import com.gempukku.lotro.common.Keyword;
import com.gempukku.lotro.common.Side;
import com.gempukku.lotro.filters.Filter;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.GameState;
@@ -8,8 +11,11 @@ import com.gempukku.lotro.logic.modifiers.ModifierEffect;
import com.gempukku.lotro.logic.modifiers.ModifiersQuerying;
public class AllyParticipatesInArcheryFireAndSkirmishesModifier extends AbstractModifier {
private PhysicalCard _source;
public AllyParticipatesInArcheryFireAndSkirmishesModifier(PhysicalCard source, Filter affectFilter) {
super(source, "Can participate in archery and skirmishes", affectFilter, new ModifierEffect[]{ModifierEffect.PRESENCE_MODIFIER});
_source = source;
}
@Override
@@ -18,7 +24,9 @@ public class AllyParticipatesInArcheryFireAndSkirmishesModifier extends Abstract
}
@Override
public boolean isAllyParticipateInSkirmishes(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard card) {
return true;
public boolean isAllyParticipateInSkirmishes(GameState gameState, Side sidePlayer, ModifiersQuerying modifiersQuerying, PhysicalCard card) {
boolean unhasty = modifiersQuerying.hasKeyword(gameState, card, Keyword.UNHASTY);
return sidePlayer == Side.SHADOW
|| !unhasty || _source.getBlueprint().getCulture() == Culture.GANDALF;
}
}

View File

@@ -44,6 +44,11 @@ public class SimpleLotroCardBlueprint implements LotroCardBlueprint {
return null;
}
@Override
public boolean isAllyAtHome(int siteNumber, Block siteBlock) {
return false;
}
@Override
public List<? extends Action> getOptionalAfterActions(String playerId, LotroGame game, EffectResult effectResult, PhysicalCard self) {
return null;

View File

@@ -0,0 +1,88 @@
package com.gempukku.lotro.cards.set4.gandalf;
import com.gempukku.lotro.cards.AbstractAlly;
import com.gempukku.lotro.cards.PlayConditions;
import com.gempukku.lotro.cards.effects.AddTwilightEffect;
import com.gempukku.lotro.cards.effects.ChooseArbitraryCardsEffect;
import com.gempukku.lotro.cards.effects.ExertCharactersEffect;
import com.gempukku.lotro.cards.effects.StackCardFromPlayEffect;
import com.gempukku.lotro.common.*;
import com.gempukku.lotro.filters.Filters;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.actions.ActivateCardAction;
import com.gempukku.lotro.logic.effects.ChooseActiveCardEffect;
import com.gempukku.lotro.logic.effects.DiscardCardsFromPlayEffect;
import com.gempukku.lotro.logic.timing.Action;
import com.gempukku.lotro.logic.timing.Effect;
import com.gempukku.lotro.logic.timing.EffectResult;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Set: The Two Towers
* Side: Free
* Culture: Gandalf
* Twilight Cost: 4
* Type: Ally • Home 2T & 8T • Ent
* Strength: 12
* Vitality: 4
* Site: 2T, 8T
* Game Text: Unhasty. Response: If an unbound Hobbit is about to be discarded, stack him here instead.
* Fellowship: Exert Treebeard and add(1) to play an unbound Hobbit stacked here.
*/
public class Card4_103 extends AbstractAlly {
public Card4_103() {
super(4, Block.TWO_TOWERS, new int[]{2, 8}, 12, 4, Race.ENT, Culture.GANDALF, "Treebeard", true);
addKeyword(Keyword.UNHASTY);
}
@Override
public List<? extends Action> getOptionalBeforeActions(String playerId, LotroGame game, Effect effect, final PhysicalCard self) {
if (effect.getType() == EffectResult.Type.DISCARD_FROM_PLAY
&& PlayConditions.canUseFPCardDuringPhase(game.getGameState(), null, self)) {
DiscardCardsFromPlayEffect discardEffect = (DiscardCardsFromPlayEffect) effect;
Collection<PhysicalCard> discardedHobbits = Filters.filter(discardEffect.getAffectedCardsMinusPrevented(game), game.getGameState(), game.getModifiersQuerying(), Filters.unboundCompanion(), Filters.race(Race.HOBBIT));
if (discardedHobbits.size() > 0) {
final ActivateCardAction action = new ActivateCardAction(self, Keyword.RESPONSE);
action.appendEffect(
new ChooseActiveCardEffect(self, playerId, "Choose unbound hobbit", Filters.in(discardedHobbits)) {
@Override
protected void cardSelected(PhysicalCard card) {
action.insertEffect(
new StackCardFromPlayEffect(card, self));
}
});
return Collections.singletonList(action);
}
}
return null;
}
@Override
protected List<? extends Action> getExtraInPlayPhaseActions(final String playerId, LotroGame game, PhysicalCard self) {
if (PlayConditions.canUseFPCardDuringPhase(game.getGameState(), Phase.FELLOWSHIP, self)
&& PlayConditions.canExert(self, game.getGameState(), game.getModifiersQuerying(), self)
&& Filters.filter(game.getGameState().getStackedCards(self), game.getGameState(), game.getModifiersQuerying(), Filters.unboundCompanion(), Filters.race(Race.HOBBIT), Filters.playable(game)).size() > 0) {
ActivateCardAction action = new ActivateCardAction(self, Keyword.FELLOWSHIP);
action.appendCost(
new ExertCharactersEffect(self, self));
action.appendCost(
new AddTwilightEffect(self, 1));
action.appendEffect(
new ChooseArbitraryCardsEffect(playerId, "Choose an Orc to play", game.getGameState().getStackedCards(self), Filters.playable(game), 1, 1) {
@Override
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> stackedHobbits) {
if (stackedHobbits.size() > 0) {
PhysicalCard stackedHobbit = stackedHobbits.iterator().next();
game.getActionsEnvironment().addActionToStack(stackedHobbit.getBlueprint().getPlayCardAction(playerId, game, stackedHobbit, 0));
}
}
});
return Collections.singletonList(action);
}
return null;
}
}

View File

@@ -14,7 +14,8 @@ public enum Keyword {
RIVER("River", true), PLAINS("Plains", true), UNDERGROUND("Underground", true), SANCTUARY("Sanctuary", true), FOREST("Forest", true), MARSH("Marsh", true), MOUNTAIN("Mountain", true),
BATTLEGROUND("Battleground", true),
DAMAGE("Damage", true, true), DEFENDER("Defender", true, true), FIERCE("Fierce", true), ARCHER("Archer", true), RANGER("Ranger", true), TRACKER("Tracker", true),
DAMAGE("Damage", true, true), DEFENDER("Defender", true, true), FIERCE("Fierce", true), ARCHER("Archer", true), UNHASTY("Unhasty", true),
RANGER("Ranger", true), TRACKER("Tracker", true),
HAND_WEAPON("Hand Weapon"), ARMOR("Armor"), HELM("Helm"), MOUNT("Mount"), RANGED_WEAPON("Ranged Weapon"),
CLOAK("Cloak"), PIPE("Pipe"), PIPEWEED("Pipeweed"), SHIELD("Shield"), BRACERS("Bracers"), STAFF("Staff"), RING("Ring"),

View File

@@ -82,19 +82,6 @@ public class Filters {
};
}
public static Filter allyOnHomeSite() {
return Filters.and(
Filters.type(CardType.ALLY),
new Filter() {
@Override
public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) {
return physicalCard.getBlueprint().getSiteNumber() == gameState.getCurrentSiteNumber()
&& physicalCard.getBlueprint().getSiteBlock() == gameState.getCurrentSite().getBlueprint().getSiteBlock();
}
}
);
}
public static Filter siteBlock(final Block block) {
return new Filter() {
@Override
@@ -259,6 +246,17 @@ public class Filters {
};
}
public static Filter isAllyAtHome() {
return Filters.and(
Filters.type(CardType.ALLY),
new Filter() {
@Override
public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) {
return physicalCard.getBlueprint().isAllyAtHome(gameState.getCurrentSiteNumber(), gameState.getCurrentSiteBlock());
}
});
}
public static Filter siteNumber(final int siteNumber) {
return new Filter() {
@Override

View File

@@ -38,6 +38,8 @@ public interface LotroCardBlueprint {
public int getResistance();
public boolean isAllyAtHome(int siteNumber, Block siteBlock);
public List<? extends Modifier> getAlwaysOnModifiers(PhysicalCard self);
public boolean checkPlayRequirements(String playerId, LotroGame game, PhysicalCard self, int twilightModifier);

View File

@@ -121,7 +121,7 @@ public abstract class AbstractModifier implements Modifier {
}
@Override
public boolean isAllyParticipateInSkirmishes(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard card) {
public boolean isAllyParticipateInSkirmishes(GameState gameState, Side sidePlayer, ModifiersQuerying modifiersQuerying, PhysicalCard card) {
return false;
}

View File

@@ -50,7 +50,7 @@ public interface Modifier {
public boolean isAllyParticipateInArcheryFire(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard card);
public boolean isAllyParticipateInSkirmishes(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard card);
public boolean isAllyParticipateInSkirmishes(GameState gameState, Side sidePlayer, ModifiersQuerying modifiersQuerying, PhysicalCard card);
public int getArcheryTotal(GameState gameState, ModifiersQuerying modifiersQuerying, Side side, int result);

View File

@@ -328,10 +328,10 @@ public class ModifiersLogic implements ModifiersEnvironment, ModifiersQuerying {
}
@Override
public boolean isAllyParticipateInSkirmishes(GameState gameState, PhysicalCard card) {
public boolean isAllyParticipateInSkirmishes(GameState gameState, Side sidePlayer, PhysicalCard card) {
for (Modifier modifier : getModifiers(ModifierEffect.PRESENCE_MODIFIER)) {
if (affectsCardWithSkipSet(gameState, card, modifier))
if (modifier.isAllyParticipateInSkirmishes(gameState, this, card))
if (modifier.isAllyParticipateInSkirmishes(gameState, sidePlayer, this, card))
return true;
}
return false;

View File

@@ -54,7 +54,7 @@ public interface ModifiersQuerying {
// Assignments
public boolean canBeAssignedToSkirmish(GameState gameState, Side playerSide, PhysicalCard card);
public boolean isAllyParticipateInSkirmishes(GameState gameState, PhysicalCard card);
public boolean isAllyParticipateInSkirmishes(GameState gameState, Side sidePlayer, PhysicalCard card);
public boolean isAllyParticipateInArcheryFire(GameState gameState, PhysicalCard card);

View File

@@ -54,7 +54,7 @@ public class FreePeoplePlayerAssignsMinionsGameProcess implements GameProcess {
new Filter() {
@Override
public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) {
return modifiersQuerying.isAllyParticipateInSkirmishes(gameState, physicalCard);
return modifiersQuerying.isAllyParticipateInSkirmishes(gameState, Side.FREE_PEOPLE, physicalCard);
}
}
)

View File

@@ -57,7 +57,7 @@ public class ShadowPlayerAssignsHisMinionsGameProcess implements GameProcess {
new Filter() {
@Override
public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) {
return modifiersQuerying.isAllyParticipateInSkirmishes(gameState, physicalCard);
return modifiersQuerying.isAllyParticipateInSkirmishes(gameState, Side.SHADOW, physicalCard);
}
}
)