Re-implement Leonin Arbiter using continuous rule modifying effect. Fix #483

This commit is contained in:
Dustin Conrad 2014-08-19 18:41:17 -04:00
parent 0fc47df5a9
commit 4307b3f01b
2 changed files with 99 additions and 53 deletions

View file

@ -27,31 +27,29 @@
*/ */
package mage.sets.scarsofmirrodin; package mage.sets.scarsofmirrodin;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.UUID; import mage.abilities.SpecialAction;
import mage.constants.CardType; import mage.abilities.common.SimpleStaticAbility;
import mage.constants.Duration; import mage.abilities.effects.*;
import mage.constants.Outcome; import mage.constants.*;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent.EventType;
import mage.players.Player; import mage.game.permanent.Permanent;
/** /**
* *
* @author maurer.it_at_gmail.com * @author maurer.it_at_gmail.com, dustinconrad
*/ */
public class LeoninArbiter extends CardImpl { public class LeoninArbiter extends CardImpl {
private static final String keyString = "_ignoreEffectForTurn";
public LeoninArbiter(UUID ownerId) { public LeoninArbiter(UUID ownerId) {
super(ownerId, 14, "Leonin Arbiter", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{W}"); super(ownerId, 14, "Leonin Arbiter", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.expansionSetCode = "SOM"; this.expansionSetCode = "SOM";
@ -62,8 +60,10 @@ public class LeoninArbiter extends CardImpl {
this.power = new MageInt(2); this.power = new MageInt(2);
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
// Players can't search libraries. Any player may pay {2} for that player to ignore this effect until end of turn. // Players can't search libraries.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LeoninArbiterReplacementEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LeoninArbiterCantSearchEffect(keyString)));
// Any player may pay {2} for that player to ignore this effect until end of turn.
this.addAbility(new LeoninArbiterSpecialAction(keyString));
} }
public LeoninArbiter(final LeoninArbiter card) { public LeoninArbiter(final LeoninArbiter card) {
@ -76,61 +76,103 @@ public class LeoninArbiter extends CardImpl {
} }
} }
class LeoninArbiterReplacementEffect extends ReplacementEffectImpl { class LeoninArbiterSpecialAction extends SpecialAction {
private static final String effectText = "Players can't search libraries. Any player may pay {2} for that player to ignore this effect until end of turn"; public LeoninArbiterSpecialAction(final String keyString) {
private final List<UUID> paidPlayers = new ArrayList<>(); super(Zone.BATTLEFIELD);
this.addCost(new ManaCostsImpl("{2}"));
LeoninArbiterReplacementEffect ( ) { this.addEffect(new LeoninArbiterIgnoreEffect(keyString));
super(Duration.WhileOnBattlefield, Outcome.Neutral); this.setMayActivate(TargetController.ANY);
staticText = effectText;
} }
LeoninArbiterReplacementEffect ( LeoninArbiterReplacementEffect effect ) { public LeoninArbiterSpecialAction(final LeoninArbiterSpecialAction ability) {
super(ability);
}
@Override
public LeoninArbiterSpecialAction copy() {
return new LeoninArbiterSpecialAction(this);
}
}
class LeoninArbiterIgnoreEffect extends OneShotEffect {
private final String keyString;
public LeoninArbiterIgnoreEffect(final String keyString) {
super(Outcome.Benefit);
this.keyString = keyString;
this.staticText = "Any player may pay {2} for that player to ignore this effect until end of turn";
}
public LeoninArbiterIgnoreEffect(final LeoninArbiterIgnoreEffect effect) {
super(effect); super(effect);
this.paidPlayers.addAll(effect.paidPlayers); this.keyString = effect.keyString;
}
@Override
public LeoninArbiterIgnoreEffect copy() {
return new LeoninArbiterIgnoreEffect(this);
} }
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
throw new UnsupportedOperationException("Not supported."); Permanent permanent = game.getPermanent(source.getSourceId());
String key = permanent.getId() + keyString;
// Using a Map.Entry since there is no pair class
long zoneChangeCount = permanent.getZoneChangeCounter();
long turnNum = game.getTurnNum();
Long activationState = zoneChangeCount << 32 | turnNum & 0xFFFFFFFFL;
Map.Entry<Long, Set<UUID>> turnIgnoringPlayersPair = (Map.Entry<Long, Set<UUID>>) game.getState().getValue(key);
if (turnIgnoringPlayersPair == null || !activationState.equals(turnIgnoringPlayersPair.getKey())) {
turnIgnoringPlayersPair = new AbstractMap.SimpleImmutableEntry<Long, Set<UUID>>(activationState, new HashSet<UUID>());
game.getState().setValue(key, turnIgnoringPlayersPair);
} }
@Override turnIgnoringPlayersPair.getValue().add(game.getActivePlayerId());
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
if ( event.getType() == EventType.SEARCH_LIBRARY && !paidPlayers.contains(event.getPlayerId()) ) {
Player player = game.getPlayer(event.getPlayerId());
if ( player != null ) {
ManaCostsImpl arbiterTax = new ManaCostsImpl("{2}");
if ( arbiterTax.canPay(source, source.getSourceId(), event.getPlayerId(), game) &&
player.chooseUse(Outcome.Neutral, "Pay {2} to search your library?", game) )
{
if (arbiterTax.payOrRollback(source, game, source.getSourceId(), event.getPlayerId()) ) {
paidPlayers.add(event.getPlayerId());
return false;
}
}
}
return true; return true;
} }
return false; }
class LeoninArbiterCantSearchEffect extends ContinuousRuleModifiyingEffectImpl {
private final String keyString;
public LeoninArbiterCantSearchEffect(final String keyString) {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
this.staticText = "Players can't search libraries.";
this.keyString = keyString;
}
public LeoninArbiterCantSearchEffect(LeoninArbiterCantSearchEffect effect) {
super(effect);
this.keyString = effect.keyString;
} }
@Override @Override
public boolean applies(GameEvent event, Ability source, Game game) { public boolean applies(GameEvent event, Ability source, Game game) {
if ( event.getType() == EventType.SEARCH_LIBRARY ) { boolean applies = false;
return true; if (EventType.SEARCH_LIBRARY.equals(event.getType())) {
applies = true;
Permanent permanent = game.getPermanent(source.getSourceId());
String key = permanent.getId() + keyString;
Map.Entry<Long, Set<UUID>> turnIgnoringPlayersPair = (Map.Entry<Long, Set<UUID>>) game.getState().getValue(key);
if (turnIgnoringPlayersPair != null) {
long zoneChangeCount = permanent.getZoneChangeCounter();
long turnNum = game.getTurnNum();
Long activationState = zoneChangeCount << 32 | turnNum & 0xFFFFFFFFL;
if (activationState.equals(turnIgnoringPlayersPair.getKey())) {
applies = !turnIgnoringPlayersPair.getValue().contains(event.getPlayerId());
} }
if ( event.getType() == EventType.END_PHASE_POST) {
this.paidPlayers.clear();
} }
return false; }
return applies;
} }
@Override @Override
public LeoninArbiterReplacementEffect copy() { public LeoninArbiterCantSearchEffect copy() {
return new LeoninArbiterReplacementEffect(this); return new LeoninArbiterCantSearchEffect(this);
} }
} }

View file

@ -38,7 +38,11 @@ import mage.constants.Zone;
public abstract class SpecialAction extends ActivatedAbilityImpl { public abstract class SpecialAction extends ActivatedAbilityImpl {
public SpecialAction() { public SpecialAction() {
super(AbilityType.SPECIAL_ACTION, Zone.ALL); this(Zone.ALL);
}
public SpecialAction(Zone zone) {
super(AbilityType.SPECIAL_ACTION, zone);
this.usesStack = false; this.usesStack = false;
} }