* Added early event type check for replacement effects to speed up game execution (not all effects already implement the new check).

This commit is contained in:
LevelX2 2014-12-26 17:28:13 +01:00
parent ba57478149
commit 9039eef0f9
40 changed files with 283 additions and 144 deletions

View file

@ -119,12 +119,18 @@ class PutIntoGraveFromAnywhereEffect extends ReplacementEffectImpl {
baseEffects.add(effect);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (GameEvent.EventType.ZONE_CHANGE.equals(event.getType())
&& ((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD
&& event.getTargetId().equals(source.getSourceId())) {
if (condition == null || condition.apply(game, source)) {
if (((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD
&& event.getTargetId().equals(source.getSourceId()))
{
if (condition == null || condition.apply(game, source))
{
return true;
}
}

View file

@ -119,6 +119,12 @@ public class ConditionalReplacementEffect extends ReplacementEffectImpl {
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return effect.checksEventType(event, game)
|| (otherwiseEffect != null && otherwiseEffect.checksEventType(event, game));
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (!initDone) { // if simpleStaticAbility, init won't be called

View file

@ -61,15 +61,15 @@ public class AsTurnedFaceUpEffect extends ReplacementEffectImpl {
public void addEffect(Effect effect) {
baseEffects.add(effect);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.TURNFACEUP;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.TURNFACEUP) {
if (event.getTargetId().equals(source.getSourceId())) {
return true;
}
}
return false;
return event.getTargetId().equals(source.getSourceId());
}
@Override

View file

@ -163,16 +163,19 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
}
return true;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType().equals(GameEvent.EventType.ZONE_CHANGE)) {
if (((ZoneChangeEvent) event).getToZone().equals(Zone.BATTLEFIELD)
&& !(((ZoneChangeEvent) event).getFromZone().equals(Zone.HAND)) ) {
Card card = game.getCard(event.getTargetId());
if (card != null && card.getCardType().contains(CardType.ENCHANTMENT) && card.hasSubtype("Aura")) {
return true;
}
if (((ZoneChangeEvent) event).getToZone().equals(Zone.BATTLEFIELD)
&& !(((ZoneChangeEvent) event).getFromZone().equals(Zone.HAND)) ) {
Card card = game.getCard(event.getTargetId());
if (card != null && card.getCardType().contains(CardType.ENCHANTMENT) && card.hasSubtype("Aura")) {
return true;
}
}
return false;

View file

@ -324,14 +324,17 @@ public class ContinuousEffects implements Serializable {
*/
private HashMap<ReplacementEffect, HashSet<Ability>> getApplicableReplacementEffects(GameEvent event, Game game) {
HashMap<ReplacementEffect, HashSet<Ability>> replaceEffects = new HashMap<>();
if (planeswalkerRedirectionEffect.applies(event, null, game)) {
if (planeswalkerRedirectionEffect.checksEventType(event, game) && planeswalkerRedirectionEffect.applies(event, null, game)) {
replaceEffects.put(planeswalkerRedirectionEffect, null);
}
if(auraReplacementEffect.applies(event, null, game)){
if(auraReplacementEffect.checksEventType(event, game) && auraReplacementEffect.applies(event, null, game)){
replaceEffects.put(auraReplacementEffect, null);
}
//get all applicable transient Replacement effects
for (ReplacementEffect effect: replacementEffects) {
if (!effect.checksEventType(event, game)) {
continue;
}
if (event.getAppliedEffects() != null && event.getAppliedEffects().contains(effect.getId())) {
// Effect already applied to this event, ignore it
// TODO: Handle also gained effect that are connected to different abilities.
@ -357,6 +360,9 @@ public class ContinuousEffects implements Serializable {
}
}
for (PreventionEffect effect: preventionEffects) {
if (!effect.checksEventType(event, game)) {
continue;
}
if (event.getAppliedEffects() != null && event.getAppliedEffects().contains(effect.getId())) {
// Effect already applied to this event, ignore it
// TODO: Handle also gained effect that are connected to different abilities.

View file

@ -88,6 +88,11 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl {
baseEffects.add(effect);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return EventType.ENTERS_THE_BATTLEFIELD.equals(event.getType());
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD) {

View file

@ -97,16 +97,19 @@ public abstract class PreventionEffectImpl extends ReplacementEffectImpl impleme
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
public boolean checksEventType(GameEvent event, Game game) {
switch (event.getType()) {
case DAMAGE_CREATURE:
case DAMAGE_PLAYER:
case DAMAGE_PLANESWALKER:
// return preventable flag && combatOnly check
return event.getFlag() && (!onlyCombat || ((DamageEvent)event).isCombatDamage());
default:
return false;
return true;
}
return false;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return event.getFlag() && (!onlyCombat || ((DamageEvent)event).isCombatDamage());
}
}

View file

@ -37,11 +37,21 @@ import mage.game.events.GameEvent;
* @author BetaSteward_at_googlemail.com
*/
public interface ReplacementEffect extends ContinuousEffect {
boolean replaceEvent(GameEvent event, Ability source, Game game);
/**
* This check for the relevant events is called at first to prevent further actions if
* the current event is ignored from this effect
* @param event
* @param game
* @return
*/
boolean checksEventType(GameEvent event, Game game);
boolean applies(GameEvent event, Ability source, Game game);
boolean hasSelfScope();
@Override
public ContinuousEffect copy();

View file

@ -28,9 +28,12 @@
package mage.abilities.effects;
import mage.abilities.Ability;
import mage.constants.Duration;
import mage.constants.EffectType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
/**
*
@ -70,4 +73,10 @@ public abstract class ReplacementEffectImpl extends ContinuousEffectImpl impleme
public boolean hasSelfScope() {
return selfScope;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return true;
}
}

View file

@ -106,10 +106,14 @@ public class DevourEffect extends ReplacementEffectImpl {
this.devourFactor = effect.devourFactor;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD
&& event.getTargetId().equals(source.getSourceId())) {
if (event.getTargetId().equals(source.getSourceId())) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
game.getState().setValue(sourcePermanent.getId().toString() + "devoured", null);
return true;

View file

@ -94,9 +94,14 @@ public class EnterBattlefieldPayCostOrPutGraveyardEffect extends ReplacementEffe
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && source.getSourceId().equals(event.getTargetId())) {
if (source.getSourceId().equals(event.getTargetId())) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if(zEvent.getToZone().equals(Zone.BATTLEFIELD)){
return true;

View file

@ -83,6 +83,11 @@ public class RegenerateAttachedEffect extends ReplacementEffectImpl {
return apply(game, source);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DESTROY_PERMANENT;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
//20110204 - 701.11c - event.getAmount() is used to signal if regeneration is allowed
@ -91,7 +96,7 @@ public class RegenerateAttachedEffect extends ReplacementEffectImpl {
Permanent equipped = game.getPermanent(equipment.getAttachedTo());
if (equipped != null) {
UUID equippedID = equipped.getId();
if (event.getType() == EventType.DESTROY_PERMANENT && event.getAmount() == 0 && event.getTargetId().equals(equippedID) && !this.used) {
if (event.getAmount() == 0 && event.getTargetId().equals(equippedID) && !this.used) {
return true;
}
}

View file

@ -72,14 +72,14 @@ public class RegenerateSourceEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
return apply(game, source);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DESTROY_PERMANENT;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
//20110204 - 701.11c - event.getAmount() is used to signal if regeneration is allowed
if (event.getType() == EventType.DESTROY_PERMANENT && event.getAmount() == 0 && event.getTargetId().equals(source.getSourceId()) && !this.used) {
return true;
}
return false;
return event.getAmount() == 0 && event.getTargetId().equals(source.getSourceId()) && !this.used;
}
}

View file

@ -73,10 +73,15 @@ public class RegenerateTargetEffect extends ReplacementEffectImpl {
return apply(game, source);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return EventType.DESTROY_PERMANENT.equals(event.getType());
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
//20110204 - 701.11c - event.getAmount() is used to signal if regeneration is allowed
if (event.getType() == EventType.DESTROY_PERMANENT && event.getAmount() == 0 && event.getTargetId().equals(targetPointer.getFirst(game, source)) && !this.used) {
if (event.getAmount() == 0 && event.getTargetId().equals(targetPointer.getFirst(game, source)) && !this.used) {
return true;
}
return false;

View file

@ -68,9 +68,13 @@ public class SkipDrawStepEffect extends ReplacementEffectImpl {
return true;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DRAW_STEP;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return event.getType() == GameEvent.EventType.DRAW_STEP
&& (event.getPlayerId().equals(source.getControllerId()));
return event.getPlayerId().equals(source.getControllerId());
}
}

View file

@ -70,18 +70,23 @@ public class AssignNoCombatDamageSourceEffect extends ReplacementEffectImpl {
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
public boolean checksEventType(GameEvent event, Game game) {
switch (event.getType()) {
case DAMAGE_CREATURE:
case DAMAGE_PLAYER:
case DAMAGE_PLANESWALKER:
DamageEvent damageEvent = (DamageEvent) event;
return event.getSourceId().equals(source.getSourceId()) && damageEvent.isCombatDamage();
return true;
default:
return false;
}
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
DamageEvent damageEvent = (DamageEvent) event;
return event.getSourceId().equals(source.getSourceId()) && damageEvent.isCombatDamage();
}
private String setText() {
StringBuilder sb = new StringBuilder("{this} assigns no combat damage");
switch(duration) {

View file

@ -51,8 +51,6 @@ import org.apache.log4j.Logger;
*/
public class CommanderManaReplacementEffect extends ReplacementEffectImpl {
private static final transient Logger logger = Logger.getLogger(CommanderManaReplacementEffect.class);
private final UUID playerId;
private final Mana commanderMana;
@ -115,22 +113,14 @@ public class CommanderManaReplacementEffect extends ReplacementEffectImpl {
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ADD_MANA;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.ADD_MANA && event.getPlayerId().equals(playerId)) {
if (logger.isDebugEnabled()) {
if (!game.getGameType().toString().startsWith("Commander")) {
logger.debug("Non Commander game has active CommanderManaReplacementEffect");
Iterator it = game.getState().getCommand().iterator();
while (it.hasNext()) {
Object object = it.next();
logger.debug("Class: " + object.getClass() + " - " + object.toString());
}
}
}
return true;
}
return false;
return event.getPlayerId().equals(playerId);
}
}

View file

@ -114,14 +114,17 @@ public class CommanderReplacementEffect extends ReplacementEffectImpl {
}
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && (
((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD ||
if (((ZoneChangeEvent)event).getToZone() == Zone.GRAVEYARD ||
((ZoneChangeEvent)event).getToZone() == Zone.EXILED ||
(alsoLibrary && ((ZoneChangeEvent)event).getToZone() == Zone.LIBRARY))
) {
{
if (commanderId != null) {
if (((ZoneChangeEvent)event).getFromZone().equals(Zone.STACK)) {
Spell spell = game.getStack().getSpell(event.getTargetId());

View file

@ -84,15 +84,18 @@ public class DealtDamageToCreatureBySourceDies extends ReplacementEffectImpl {
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType().equals(EventType.ZONE_CHANGE)) {
ZoneChangeEvent zce = (ZoneChangeEvent) event;
if (zce.isDiesEvent()) {
DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get("DamagedByWatcher", source.getSourceId());
if (watcher != null) {
return watcher.wasDamaged(zce.getTarget());
}
ZoneChangeEvent zce = (ZoneChangeEvent) event;
if (zce.isDiesEvent()) {
DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get("DamagedByWatcher", source.getSourceId());
if (watcher != null) {
return watcher.wasDamaged(zce.getTarget());
}
}
return false;

View file

@ -178,9 +178,14 @@ class BuybackEffect extends ReplacementEffectImpl {
return new BuybackEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(source.getSourceId())) {
if (event.getTargetId().equals(source.getSourceId())) {
ZoneChangeEvent zEvent = (ZoneChangeEvent)event;
if (zEvent.getFromZone() == Zone.STACK ) {
return true;

View file

@ -36,6 +36,7 @@ import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.players.Player;
/**
@ -109,8 +110,14 @@ class DredgeEffect extends ReplacementEffectImpl {
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == EventType.DRAW_CARD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return event.getType().equals(GameEvent.EventType.DRAW_CARD) && event.getPlayerId().equals(source.getControllerId());
return event.getPlayerId().equals(source.getControllerId());
}
}

View file

@ -98,11 +98,14 @@ class MadnessReplacementEffect extends ReplacementEffectImpl {
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(source.getSourceId()) &&
return event.getTargetId().equals(source.getSourceId()) &&
((ZoneChangeEvent) event).getFromZone() == Zone.HAND && ((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD;
}

View file

@ -96,12 +96,18 @@ class PersistReplacementEffect extends ReplacementEffectImpl {
used = true;
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && event.getTargetId().equals(source.getSourceId())) {
if (event.getTargetId().equals(source.getSourceId()))
{
Object fixedTarget = game.getState().getValue(new StringBuilder("persist").append(source.getSourceId()).toString());
if (fixedTarget instanceof FixedTarget && ((FixedTarget) fixedTarget).getFirst(game, source).equals(source.getSourceId())) {
if (fixedTarget instanceof FixedTarget && ((FixedTarget) fixedTarget).getFirst(game, source).equals(source.getSourceId()))
{
return true;
}
}

View file

@ -226,11 +226,14 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl {
}
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == EventType.ZONE_CHANGE &&
((ZoneChangeEvent) event).getFromZone() == Zone.STACK &&
if (((ZoneChangeEvent) event).getFromZone() == Zone.STACK &&
((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD &&
source.getSourceId() == this.cardId) {
return true;

View file

@ -91,14 +91,16 @@ class TotemArmorEffect extends ReplacementEffectImpl {
}
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DESTROY_PERMANENT;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.DESTROY_PERMANENT) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null && event.getTargetId().equals(sourcePermanent.getAttachedTo())) {
return true;
}
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null && event.getTargetId().equals(sourcePermanent.getAttachedTo())) {
return true;
}
return false;
}

View file

@ -101,9 +101,14 @@ class UndyingReplacementEffect extends ReplacementEffectImpl {
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && event.getTargetId().equals(source.getSourceId())) {
if (event.getTargetId().equals(source.getSourceId())) {
Object fixedTarget = game.getState().getValue(new StringBuilder("undying").append(source.getSourceId()).toString());
if (fixedTarget instanceof FixedTarget && ((FixedTarget) fixedTarget).getFirst(game, source).equals(source.getSourceId())) {
return true;

View file

@ -135,6 +135,11 @@ class UnearthLeavesBattlefieldEffect extends ReplacementEffectImpl {
return new UnearthLeavesBattlefieldEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return EventType.ZONE_CHANGE.equals(event.getType());
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(source.getSourceId())) {

View file

@ -38,6 +38,7 @@ import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
@ -86,13 +87,16 @@ class UnleashReplacementEffect extends ReplacementEffectImpl {
public UnleashReplacementEffect(UnleashReplacementEffect effect) {
super(effect);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == EventType.ENTERS_THE_BATTLEFIELD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
if (event.getTargetId().equals(source.getSourceId())) {
return true;
}
if (event.getTargetId().equals(source.getSourceId())) {
return true;
}
return false;
}