mirror of
https://github.com/correl/mage.git
synced 2024-11-14 19:19:32 +00:00
* Fixed attack tap handling - You can no longer attack with a mana producing creature that will be get tapped for attacking and use the creature itself to produce mana to pay for effects like Ghostly Prison if the mana ability has the cost to tap the creature.
This commit is contained in:
parent
28171b3b6a
commit
b2fe13c8c8
20 changed files with 224 additions and 234 deletions
|
@ -347,7 +347,10 @@ public class SimulatedPlayer2 extends ComputerPlayer {
|
|||
}
|
||||
for (int j = 0; j < attackersList.size(); j++) {
|
||||
if (binary.charAt(j) == '1') {
|
||||
sim.getCombat().declareAttacker(attackersList.get(j).getId(), defenderId, sim);
|
||||
setStoredBookmark(sim.bookmarkState()); // makes it possible to UNDO a declared attacker with costs from e.g. Propaganda
|
||||
if(!sim.getCombat().declareAttacker(attackersList.get(j).getId(), defenderId, playerId, sim)) {
|
||||
sim.undo(playerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (engagements.put(sim.getCombat().getValue().hashCode(), sim.getCombat()) != null) {
|
||||
|
|
|
@ -187,7 +187,10 @@ public class SimulatedPlayerMCTS extends MCTSPlayer {
|
|||
}
|
||||
for (int i = 0; i < attackersList.size(); i++) {
|
||||
if (binary.charAt(i) == '1') {
|
||||
game.getCombat().declareAttacker(attackersList.get(i).getId(), defenderId, game);
|
||||
setStoredBookmark(game.bookmarkState()); // makes it possible to UNDO a declared attacker with costs from e.g. Propaganda
|
||||
if (!game.getCombat().declareAttacker(attackersList.get(i).getId(), defenderId, playerId, game)) {
|
||||
game.undo(playerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
actionCount++;
|
||||
|
|
|
@ -177,8 +177,12 @@ public class SimulatedPlayer extends ComputerPlayer {
|
|||
binary.insert(0, "0");
|
||||
}
|
||||
for (int j = 0; j < attackersList.size(); j++) {
|
||||
if (binary.charAt(j) == '1')
|
||||
sim.getCombat().declareAttacker(attackersList.get(j).getId(), defenderId, sim);
|
||||
if (binary.charAt(j) == '1') {
|
||||
setStoredBookmark(sim.bookmarkState()); // makes it possible to UNDO a declared attacker with costs from e.g. Propaganda
|
||||
if (!sim.getCombat().declareAttacker(attackersList.get(j).getId(), defenderId, playerId, sim)) {
|
||||
sim.undo(playerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (engagements.put(sim.getCombat().getValue().hashCode(), sim.getCombat()) != null) {
|
||||
logger.debug("simulating -- found redundant attack combination");
|
||||
|
|
|
@ -58,7 +58,6 @@ public class FloodtideSerpent extends CardImpl {
|
|||
this.expansionSetCode = "BNG";
|
||||
this.subtype.add("Serpent");
|
||||
|
||||
this.color.setBlue(true);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
|
@ -95,11 +94,6 @@ class FloodtideSerpentReplacementEffect extends ReplacementEffectImpl {
|
|||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
|
|
|
@ -80,36 +80,35 @@ class GhostlyPrisonReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARE_ATTACKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
if ( event.getType() == GameEvent.EventType.DECLARE_ATTACKER) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
if ( player != null && event.getTargetId().equals(source.getControllerId())) {
|
||||
ManaCostsImpl attackTax = new ManaCostsImpl("{2}");
|
||||
if ( attackTax.canPay(source, source.getSourceId(), event.getPlayerId(), game) &&
|
||||
player.chooseUse(Outcome.Benefit, "Pay {2} to attack player?", game) ) {
|
||||
if (attackTax.payOrRollback(source, game, this.getId(), event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getTargetId().equals(source.getControllerId()) ) {
|
||||
Player attackedPlayer = game.getPlayer(event.getTargetId());
|
||||
if (attackedPlayer != null) {
|
||||
// only if a player is attacked. Attacking a planeswalker is free
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if ( event.getType() == GameEvent.EventType.DECLARE_ATTACKER && event.getTargetId().equals(source.getControllerId()) ) {
|
||||
Player attackedPlayer = game.getPlayer(event.getTargetId());
|
||||
if (attackedPlayer != null) {
|
||||
// only if a player is attacked. Attacking a planeswalker is free
|
||||
return true;
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
if ( player != null && event.getTargetId().equals(source.getControllerId())) {
|
||||
ManaCostsImpl attackTax = new ManaCostsImpl("{2}");
|
||||
if (attackTax.canPay(source, source.getSourceId(), event.getPlayerId(), game) &&
|
||||
player.chooseUse(Outcome.Benefit, "Pay {2} to attack player?", game) ) {
|
||||
if (attackTax.payOrRollback(source, game, this.getId(), event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ class KaaliaOfTheVastEffect extends OneShotEffect {
|
|||
player.putOntoBattlefieldWithInfo(card, game, Zone.HAND, source.getSourceId(), true);
|
||||
Permanent creature = game.getPermanent(cardId);
|
||||
if (creature != null) {
|
||||
game.getCombat().declareAttacker(card.getId(), defenderId, game);
|
||||
game.getCombat().addAttackerToCombat(card.getId(), defenderId, game);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,8 +65,6 @@ public class MysticBarrier extends CardImpl {
|
|||
super(ownerId, 18, "Mystic Barrier", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}");
|
||||
this.expansionSetCode = "C13";
|
||||
|
||||
this.color.setWhite(true);
|
||||
|
||||
// When Mystic Barrier enters the battlefield or at the beginning of your upkeep, choose left or right.
|
||||
this.addAbility(new MysticBarrierTriggeredAbility());
|
||||
|
||||
|
@ -98,16 +96,19 @@ class MysticBarrierTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public MysticBarrierTriggeredAbility copy() {
|
||||
return new MysticBarrierTriggeredAbility(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType().equals(EventType.ENTERS_THE_BATTLEFIELD) || event.getType().equals(EventType.UPKEEP_STEP_PRE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getType().equals(EventType.ENTERS_THE_BATTLEFIELD) && event.getTargetId().equals(this.getSourceId())) {
|
||||
return true;
|
||||
if (event.getType().equals(EventType.ENTERS_THE_BATTLEFIELD)) {
|
||||
return event.getTargetId().equals(this.getSourceId());
|
||||
} else {
|
||||
return event.getPlayerId().equals(this.getControllerId());
|
||||
}
|
||||
if (event.getType().equals(EventType.UPKEEP_STEP_PRE) && event.getPlayerId().equals(this.getControllerId())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -170,19 +171,19 @@ class MysticBarrierReplacementEffect extends ReplacementEffectImpl {
|
|||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARE_ATTACKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if ( event.getType() == GameEvent.EventType.DECLARE_ATTACKER && game.getPlayers().size() > 2) {
|
||||
if (game.getPlayers().size() > 2) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
if (controller.getInRange().contains(event.getPlayerId())) {
|
||||
|
|
|
@ -64,7 +64,6 @@ public class EvilEyeOfOrmsByGore extends CardImpl {
|
|||
this.expansionSetCode = "5ED";
|
||||
this.subtype.add("Eye");
|
||||
|
||||
this.color.setBlack(true);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(6);
|
||||
|
||||
|
@ -96,33 +95,31 @@ class EvilEyeOfOrmsByGoreEffect extends ReplacementEffectImpl {
|
|||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvilEyeOfOrmsByGoreEffect copy() {
|
||||
return new EvilEyeOfOrmsByGoreEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return true;
|
||||
}
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARE_ATTACKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() == EventType.DECLARE_ATTACKER) {
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (permanent != null) {
|
||||
if (permanent.getControllerId().equals(source.getControllerId())) {
|
||||
if (!permanent.hasSubtype("Eye")) {
|
||||
return true;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (permanent != null) {
|
||||
if (permanent.getControllerId().equals(source.getControllerId())) {
|
||||
if (!permanent.hasSubtype("Eye")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,6 @@ public class OrissSamiteGuardian extends CardImpl {
|
|||
this.subtype.add("Human");
|
||||
this.subtype.add("Cleric");
|
||||
|
||||
this.color.setWhite(true);
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
|
@ -104,19 +103,14 @@ class OrissSamiteGuardianCantCastEffect extends ContinuousRuleModifyingEffectImp
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.CAST_SPELL;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() == EventType.CAST_SPELL) {
|
||||
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (player != null && player.getId().equals(event.getPlayerId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
return player != null && player.getId().equals(event.getPlayerId());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,20 +129,15 @@ class OrissSamiteGuardianCantAttackEffect extends ContinuousRuleModifyingEffectI
|
|||
public OrissSamiteGuardianCantAttackEffect copy() {
|
||||
return new OrissSamiteGuardianCantAttackEffect(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARE_ATTACKER;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() == EventType.DECLARE_ATTACKER) {
|
||||
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (player != null && player.getId().equals(event.getPlayerId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
return player != null && player.getId().equals(event.getPlayerId());
|
||||
}
|
||||
}
|
|
@ -79,30 +79,12 @@ class NornsAnnexReplacementEffect extends ReplacementEffectImpl {
|
|||
NornsAnnexReplacementEffect(NornsAnnexReplacementEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARE_ATTACKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.DECLARE_ATTACKER) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
if (player != null && event.getTargetId().equals(source.getControllerId())) {
|
||||
ManaCostsImpl propagandaTax = new ManaCostsImpl("{WP}");
|
||||
if (propagandaTax.canPay(source, source.getSourceId(), event.getPlayerId(), game) &&
|
||||
player.chooseUse(Outcome.Benefit, "Pay {WP} to declare attacker?", game)) {
|
||||
if (propagandaTax.payOrRollback(source, game, this.getId(), event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.DECLARE_ATTACKER) {
|
||||
|
@ -119,6 +101,24 @@ class NornsAnnexReplacementEffect extends ReplacementEffectImpl {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
if (player != null && event.getTargetId().equals(source.getControllerId())) {
|
||||
ManaCostsImpl propagandaTax = new ManaCostsImpl("{WP}");
|
||||
if (propagandaTax.canPay(source, source.getSourceId(), event.getPlayerId(), game) &&
|
||||
player.chooseUse(Outcome.Benefit, "Pay {WP} to declare attacker?", game)) {
|
||||
if (propagandaTax.payOrRollback(source, game, this.getId(), event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NornsAnnexReplacementEffect copy() {
|
||||
return new NornsAnnexReplacementEffect(this);
|
||||
|
|
|
@ -54,8 +54,6 @@ public class SphereOfSafety extends CardImpl {
|
|||
super(ownerId, 24, "Sphere of Safety", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}");
|
||||
this.expansionSetCode = "RTR";
|
||||
|
||||
this.color.setWhite(true);
|
||||
|
||||
// Creatures can't attack you or a planeswalker you control unless their controller pays {X} for each of those creatures, where X is the number of enchantments you control.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SphereOfSafetyReplacementEffect()));
|
||||
|
||||
|
@ -79,7 +77,7 @@ class SphereOfSafetyReplacementEffect extends ReplacementEffectImpl {
|
|||
static {
|
||||
filter.add(new ControllerPredicate(TargetController.YOU));
|
||||
}
|
||||
private PermanentsOnBattlefieldCount countEnchantments = new PermanentsOnBattlefieldCount(filter);
|
||||
private final PermanentsOnBattlefieldCount countEnchantments = new PermanentsOnBattlefieldCount(filter);
|
||||
|
||||
|
||||
SphereOfSafetyReplacementEffect ( ) {
|
||||
|
@ -90,51 +88,46 @@ class SphereOfSafetyReplacementEffect extends ReplacementEffectImpl {
|
|||
SphereOfSafetyReplacementEffect ( SphereOfSafetyReplacementEffect effect ) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARE_ATTACKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
if ( event.getType() == GameEvent.EventType.DECLARE_ATTACKER) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
if ( player != null ) {
|
||||
int ce = countEnchantments.calculate(game, source, this);
|
||||
ManaCostsImpl safetyCosts = new ManaCostsImpl("{"+ ce +"}");
|
||||
if ( safetyCosts.canPay(source, source.getSourceId(), event.getPlayerId(), game) &&
|
||||
player.chooseUse(Outcome.Benefit, "Pay {"+ ce +"} to declare attacker?", game) )
|
||||
{
|
||||
if (safetyCosts.payOrRollback(source, game, this.getId(), event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getTargetId().equals(source.getControllerId()) ) {
|
||||
return true;
|
||||
}
|
||||
// planeswalker
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null && permanent.getControllerId().equals(source.getControllerId())
|
||||
&& permanent.getCardType().contains(CardType.PLANESWALKER)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if ( event.getType() == GameEvent.EventType.DECLARE_ATTACKER) {
|
||||
if (event.getTargetId().equals(source.getControllerId()) ) {
|
||||
return true;
|
||||
}
|
||||
// planeswalker
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null && permanent.getControllerId().equals(source.getControllerId())
|
||||
&& permanent.getCardType().contains(CardType.PLANESWALKER)) {
|
||||
return true;
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
if ( player != null ) {
|
||||
int ce = countEnchantments.calculate(game, source, this);
|
||||
ManaCostsImpl safetyCosts = new ManaCostsImpl("{"+ ce +"}");
|
||||
if ( safetyCosts.canPay(source, source.getSourceId(), event.getPlayerId(), game) &&
|
||||
player.chooseUse(Outcome.Benefit, "Pay {"+ ce +"} to declare attacker?", game) ) {
|
||||
if (safetyCosts.payOrRollback(source, game, this.getId(), event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SphereOfSafetyReplacementEffect copy() {
|
||||
return new SphereOfSafetyReplacementEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,6 +97,17 @@ class CowedByWisdomEffect extends ReplacementEffectImpl {
|
|||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARE_ATTACKER || event.getType().equals(GameEvent.EventType.DECLARE_BLOCKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
Permanent enchantment = game.getPermanent(event.getSourceId());
|
||||
return enchantment != null && enchantment.getAttachments().contains(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
|
@ -123,20 +134,7 @@ class CowedByWisdomEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType().equals(GameEvent.EventType.DECLARE_ATTACKER)) {
|
||||
Permanent attacker = game.getPermanent(event.getSourceId());
|
||||
return attacker != null && attacker.getAttachments().contains(source.getSourceId());
|
||||
}
|
||||
if (event.getType().equals(GameEvent.EventType.DECLARE_BLOCKER)) {
|
||||
Permanent blocker = game.getPermanent(event.getSourceId());
|
||||
return blocker != null && blocker.getAttachments().contains(source.getSourceId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CowedByWisdomEffect copy() {
|
||||
return new CowedByWisdomEffect(this);
|
||||
|
|
|
@ -81,33 +81,32 @@ class LightOfDayEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
public LightOfDayEffect copy() {
|
||||
return new LightOfDayEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LightOfDayEffect copy() {
|
||||
return new LightOfDayEffect(this);
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.DECLARE_ATTACKER || event.getType() == EventType.DECLARE_BLOCKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (permanent != null) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player.getInRange().contains(permanent.getControllerId())) {
|
||||
if (permanent.getColor().isBlack()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() == EventType.DECLARE_ATTACKER || event.getType() == EventType.DECLARE_BLOCKER) {
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (permanent != null) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player.getInRange().contains(permanent.getControllerId())) {
|
||||
if (permanent.getColor().isBlack()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -81,8 +81,20 @@ class PropagandaReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARE_ATTACKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getTargetId().equals(source.getControllerId())) {
|
||||
Player attackedPlayer = game.getPlayer(event.getTargetId());
|
||||
if (attackedPlayer != null) {
|
||||
// only if a player is attacked. Attacking a planeswalker is free
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -101,19 +113,7 @@ class PropagandaReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if ( event.getType() == GameEvent.EventType.DECLARE_ATTACKER && event.getTargetId().equals(source.getControllerId())) {
|
||||
Player attackedPlayer = game.getPlayer(event.getTargetId());
|
||||
if (attackedPlayer != null) {
|
||||
// only if a player is attacked. Attacking a planeswalker is free
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PropagandaReplacementEffect copy() {
|
||||
return new PropagandaReplacementEffect(this);
|
||||
|
|
|
@ -51,7 +51,6 @@ public class WindbornMuse extends CardImpl {
|
|||
super(ownerId, 60, "Windborn Muse", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{W}");
|
||||
this.expansionSetCode = "10E";
|
||||
this.subtype.add("Spirit");
|
||||
this.color.setWhite(true);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
|
@ -86,32 +85,13 @@ class WindbornMuseReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARE_ATTACKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
if ( event.getType() == GameEvent.EventType.DECLARE_ATTACKER) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
if ( player != null && event.getTargetId().equals(source.getControllerId())) {
|
||||
ManaCostsImpl attackTax = new ManaCostsImpl("{2}");
|
||||
if ( attackTax.canPay(source, source.getSourceId(), event.getPlayerId(), game) &&
|
||||
player.chooseUse(Outcome.Benefit, "Pay {2} to attack player?", game) )
|
||||
{
|
||||
if (attackTax.payOrRollback(source, game, this.getId(), event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if ( event.getType() == GameEvent.EventType.DECLARE_ATTACKER && event.getTargetId().equals(source.getControllerId()) ) {
|
||||
if (event.getTargetId().equals(source.getControllerId()) ) {
|
||||
Player attackedPlayer = game.getPlayer(event.getTargetId());
|
||||
if (attackedPlayer != null) {
|
||||
// only if a player is attacked. Attacking a planeswalker is free
|
||||
|
@ -120,6 +100,23 @@ class WindbornMuseReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
if ( player != null && event.getTargetId().equals(source.getControllerId())) {
|
||||
ManaCostsImpl attackTax = new ManaCostsImpl("{2}");
|
||||
if ( attackTax.canPay(source, source.getSourceId(), event.getPlayerId(), game) &&
|
||||
player.chooseUse(Outcome.Benefit, "Pay {2} to attack player?", game) )
|
||||
{
|
||||
if (attackTax.payOrRollback(source, game, this.getId(), event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindbornMuseReplacementEffect copy() {
|
||||
|
|
|
@ -51,8 +51,6 @@ public class ElephantGrass extends CardImpl {
|
|||
super(ownerId, 54, "Elephant Grass", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{G}");
|
||||
this.expansionSetCode = "VIS";
|
||||
|
||||
this.color.setGreen(true);
|
||||
|
||||
// Cumulative upkeep {1}
|
||||
this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{1}")));
|
||||
// Black creatures can't attack you.
|
||||
|
@ -85,18 +83,13 @@ class ElephantGrassReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return true;
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARE_ATTACKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if ( event.getType() == GameEvent.EventType.DECLARE_ATTACKER && event.getTargetId().equals(source.getControllerId()) ) {
|
||||
if (event.getTargetId().equals(source.getControllerId()) ) {
|
||||
Permanent creature = game.getPermanent(event.getSourceId());
|
||||
if(creature != null && creature.getColor().isBlack()){
|
||||
return true;
|
||||
|
@ -105,6 +98,12 @@ class ElephantGrassReplacementEffect extends ReplacementEffectImpl {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ElephantGrassReplacementEffect copy() {
|
||||
return new ElephantGrassReplacementEffect(this);
|
||||
|
|
|
@ -190,9 +190,13 @@ public class RandomPlayer extends ComputerPlayer {
|
|||
binary.insert(0, "0"); //pad with zeros
|
||||
}
|
||||
for (int i = 0; i < attackersList.size(); i++) {
|
||||
if (binary.charAt(i) == '1')
|
||||
game.getCombat().declareAttacker(attackersList.get(i).getId(), defenderId, game);
|
||||
}
|
||||
if (binary.charAt(i) == '1') {
|
||||
setStoredBookmark(game.bookmarkState()); // makes it possible to UNDO a declared attacker with costs from e.g. Propaganda
|
||||
if (!game.getCombat().declareAttacker(attackersList.get(i).getId(), defenderId, playerId, game)) {
|
||||
game.undo(playerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
actionCount++;
|
||||
}
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ class NinjutsuEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
if (defendingPlayerId != null) {
|
||||
game.getCombat().declareAttacker(permanent.getId(), defendingPlayerId, game);
|
||||
game.getCombat().addAttackerToCombat(permanent.getId(), defendingPlayerId, game);
|
||||
permanent.setTapped(true);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -182,6 +182,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
/**
|
||||
* Add an additional attacker to the combat (e.g. token of Geist of Saint
|
||||
* Traft) This method doesn't trigger ATTACKER_DECLARED event (as intended).
|
||||
* If the creature has to be tapped that won't do this method.
|
||||
*
|
||||
* @param creatureId - creature that shall be added to the combat
|
||||
* @param game
|
||||
|
@ -190,14 +191,14 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
public boolean addAttackingCreature(UUID creatureId, Game game) {
|
||||
Player player = game.getPlayer(attackerId);
|
||||
if (defenders.size() == 1) {
|
||||
declareAttacker(creatureId, defenders.iterator().next(), game);
|
||||
addAttackerToCombat(creatureId, defenders.iterator().next(), game);
|
||||
return true;
|
||||
} else {
|
||||
TargetDefender target = new TargetDefender(defenders, creatureId);
|
||||
target.setRequired(true);
|
||||
player.chooseTarget(Outcome.Damage, target, null, game);
|
||||
if (target.getFirstTarget() != null) {
|
||||
declareAttacker(creatureId, target.getFirstTarget(), game);
|
||||
addAttackerToCombat(creatureId, target.getFirstTarget(), game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -844,7 +845,20 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean declareAttacker(UUID attackerId, UUID defenderId, Game game) {
|
||||
public boolean declareAttacker(UUID attackerId, UUID defenderId, UUID playerId, Game game) {
|
||||
Permanent attacker = game.getPermanent(attackerId);
|
||||
if (!attacker.getAbilities().containsKey(VigilanceAbility.getInstance().getId())) {
|
||||
if (!attacker.isTapped()) {
|
||||
attacker.tap(game);
|
||||
}
|
||||
}
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_ATTACKER, defenderId, attackerId, playerId))) {
|
||||
return addAttackerToCombat(attackerId, defenderId, game);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean addAttackerToCombat(UUID attackerId, UUID defenderId, Game game) {
|
||||
if (!defenders.contains(defenderId)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -853,16 +867,12 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
if (!canDefenderBeAttacked(attackerId, defenderId, game)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CombatGroup newGroup = new CombatGroup(defenderId, defender != null, defender != null ? defender.getControllerId() : defenderId);
|
||||
newGroup.attackers.add(attackerId);
|
||||
Permanent attacker = game.getPermanent(attackerId);
|
||||
if (!attacker.getAbilities().containsKey(VigilanceAbility.getInstance().getId())) {
|
||||
attacker.tap(game);
|
||||
}
|
||||
attacker.setAttacking(true);
|
||||
groups.add(newGroup);
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean canDefenderBeAttacked(UUID attackerId, UUID defenderId, Game game) {
|
||||
|
|
|
@ -1989,8 +1989,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
Permanent attacker = game.getPermanent(attackerId);
|
||||
if (attacker != null && attacker.canAttack(defenderId, game) && attacker.getControllerId().equals(playerId)) {
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_ATTACKER, defenderId, attackerId, playerId))) {
|
||||
game.getCombat().declareAttacker(attackerId, defenderId, game);
|
||||
if(!game.getCombat().declareAttacker(attackerId, defenderId, playerId, game)) {
|
||||
game.undo(playerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue