New way of copying permanents - supports copies of copies. +1 test pass.

This commit is contained in:
magenoxx 2012-05-23 20:41:51 +04:00
parent e5b6807d91
commit 0d732e8f86
11 changed files with 149 additions and 49 deletions

View file

@ -27,8 +27,6 @@
*/
package mage.sets.magic2012;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Outcome;
import mage.Constants.Rarity;
@ -38,7 +36,6 @@ import mage.abilities.common.BecomesTargetTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.EntersBattlefieldEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CopyEffect;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.cards.CardImpl;
import mage.filter.common.FilterCreaturePermanent;
@ -47,6 +44,9 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.util.functions.ApplyToPermanent;
import java.util.UUID;
/**
*
@ -98,15 +98,17 @@ class PhantasmalImageCopyEffect extends OneShotEffect<PhantasmalImageCopyEffect>
target.setRequired(true);
target.setNotTarget(true);
player.choose(Outcome.Copy, target, source.getSourceId(), game);
Permanent permanent = game.getPermanent(target.getFirstTarget());
UUID targetId = target.getFirstTarget();
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
permanent = permanent.copy();
permanent.reset(game);
permanent.assignNewId();
permanent.getSubtype().add("Illusion");
permanent.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect()), game);
game.addEffect(new CopyEffect(permanent), source);
game.copyPermanent(permanent, source, new ApplyToPermanent() {
@Override
public Boolean apply(Game game, Permanent permanent) {
permanent.getSubtype().add("Illusion");
permanent.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect()), game);
return true;
}
});
return true;
}

View file

@ -28,8 +28,6 @@
package mage.sets.newphyrexia;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Outcome;
import mage.Constants.Rarity;
@ -38,7 +36,6 @@ import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.EntersBattlefieldEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CopyEffect;
import mage.cards.CardImpl;
import mage.filter.Filter;
import mage.filter.FilterPermanent;
@ -47,6 +44,9 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.util.functions.ApplyToPermanent;
import java.util.UUID;
/**
*
@ -96,7 +96,6 @@ class PhyrexianMetamorphEffect extends OneShotEffect<PhyrexianMetamorphEffect> {
@Override
public boolean apply(Game game, Ability source) {
//TODO: handle copying copies
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
Target target = new TargetPermanent(filter);
@ -104,12 +103,16 @@ class PhyrexianMetamorphEffect extends OneShotEffect<PhyrexianMetamorphEffect> {
player.choose(Outcome.Copy, target, source.getSourceId(), game);
Permanent perm = game.getPermanent(target.getFirstTarget());
if (perm != null) {
perm = perm.copy();
perm.reset(game);
perm.assignNewId();
if (!perm.getCardType().contains(CardType.ARTIFACT))
perm.getCardType().add(CardType.ARTIFACT);
game.addEffect(new CopyEffect(perm), source);
game.copyPermanent(perm, source, new ApplyToPermanent() {
@Override
public Boolean apply(Game game, Permanent permanent) {
if (!permanent.getCardType().contains(CardType.ARTIFACT)) {
permanent.getCardType().add(CardType.ARTIFACT);
}
return true;
}
});
return true;
}
}

View file

@ -103,7 +103,7 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
addCard(Constants.Zone.BATTLEFIELD, playerA, "Illusionary Servant");
setChoice(playerA, "Illusionary Servant");
setChoice(playerA, "Phantasmal Image");
setChoice(playerA, "Illusionary Servant-M12");
castSpell(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "Phantasmal Image");
castSpell(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "Phantasmal Image");

View file

@ -189,6 +189,12 @@ public class TestPlayer extends ComputerPlayer<TestPlayer> {
choices.remove(choose2);
return true;
}
} else if ((permanent.getName()+"-"+permanent.getExpansionSetCode()).equals(choose2)) {
if (((TargetPermanent)target).canTarget(playerId, permanent.getId(), null, game) && !target.getTargets().contains(permanent.getId())) {
target.add(permanent.getId(), game);
choices.remove(choose2);
return true;
}
}
}
}

View file

@ -131,7 +131,7 @@ public class ContinuousEffects implements Serializable {
}
private List<ContinuousEffect> getLayeredEffects(Game game) {
public List<ContinuousEffect> getLayeredEffects(Game game) {
List<ContinuousEffect> layerEffects = new ArrayList<ContinuousEffect>();
for (ContinuousEffect effect: layeredEffects) {
switch (effect.getDuration()) {

View file

@ -39,6 +39,8 @@ import mage.abilities.effects.ContinuousEffectImpl;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
@ -46,15 +48,18 @@ import mage.game.permanent.Permanent;
public class CopyEffect extends ContinuousEffectImpl<CopyEffect> {
private MageObject target;
private UUID sourceId;
public CopyEffect(MageObject target) {
public CopyEffect(Permanent target, UUID sourceId) {
super(Duration.WhileOnBattlefield, Layer.CopyEffects_1, SubLayer.NA, Outcome.BecomeCreature);
this.target = target;
this.sourceId = sourceId;
}
public CopyEffect(final CopyEffect effect) {
super(effect);
this.target = effect.target.copy();
this.sourceId = effect.sourceId;
}
@Override
@ -63,7 +68,7 @@ public class CopyEffect extends ContinuousEffectImpl<CopyEffect> {
if (permanent == null) {
return false;
}
permanent.setName(target.getName());
permanent.getColor().setColor(target.getColor());
permanent.getManaCost().clear();
@ -95,4 +100,15 @@ public class CopyEffect extends ContinuousEffectImpl<CopyEffect> {
return new CopyEffect(this);
}
public MageObject getTarget() {
return target;
}
public void setTarget(MageObject target) {
this.target = target;
}
public UUID getSourceId() {
return sourceId;
}
}

View file

@ -27,6 +27,7 @@
*/
package mage.abilities.effects.common;
import mage.Constants;
import mage.Constants.Outcome;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@ -37,6 +38,7 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.util.functions.ApplyToPermanent;
/**
*
@ -63,7 +65,6 @@ public class CopyPermanentEffect extends OneShotEffect<CopyPermanentEffect> {
@Override
public boolean apply(Game game, Ability source) {
//TODO: handle copying copies
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
Target target = new TargetPermanent(filter);
@ -71,11 +72,16 @@ public class CopyPermanentEffect extends OneShotEffect<CopyPermanentEffect> {
player.choose(Outcome.Copy, target, source.getSourceId(), game);
Permanent perm = game.getPermanent(target.getFirstTarget());
if (perm != null) {
perm = perm.copy();
game.getState().addCard(perm);
perm.reset(game);
perm.assignNewId();
game.addEffect(new CopyEffect(perm), source);
game.copyPermanent(perm, source, new ApplyToPermanent() {
@Override
public Boolean apply(Game game, Permanent permanent) {
if (!permanent.getCardType().contains(Constants.CardType.ARTIFACT)) {
permanent.getCardType().add(Constants.CardType.ARTIFACT);
}
return true;
}
});
return true;
}
}

View file

@ -28,42 +28,42 @@
package mage.game;
import mage.actions.impl.MageAction;
import mage.game.match.MatchType;
import mage.cards.Card;
import mage.game.stack.SpellStack;
import mage.MageObject;
import java.io.Serializable;
import java.util.*;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.Constants.Zone;
import mage.MageItem;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.TriggeredAbilities;
import mage.abilities.TriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffects;
import mage.actions.impl.MageAction;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.decks.Deck;
import mage.choices.Choice;
import mage.game.combat.Combat;
import mage.game.events.GameEvent;
import mage.game.events.TableEvent;
import mage.game.events.Listener;
import mage.game.events.PlayerQueryEvent;
import mage.game.events.TableEvent;
import mage.game.match.MatchType;
import mage.game.permanent.Battlefield;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import mage.game.stack.SpellStack;
import mage.game.turn.Phase;
import mage.game.turn.Step;
import mage.game.turn.Turn;
import mage.players.Player;
import mage.players.PlayerList;
import mage.players.Players;
import mage.util.functions.ApplyToPermanent;
import java.io.Serializable;
import java.util.*;
public interface Game extends MageItem, Serializable {
@ -160,7 +160,17 @@ public interface Game extends MageItem, Serializable {
public void concede(UUID playerId);
public void emptyManaPools();
public void addEffect(ContinuousEffect continuousEffect, Ability source);
public void addTriggeredAbility(TriggeredAbility ability);
/**
* This version supports copying of copies of any depth.
*
* @param targetPermanent
* @param source
* @param applier
*/
public void copyPermanent(Permanent targetPermanent, Ability source, ApplyToPermanent applier);
public void addTriggeredAbility(TriggeredAbility ability);
public void addDelayedTriggeredAbility(DelayedTriggeredAbility delayedAbility);
public void applyEffects();
public boolean checkStateAndTriggered();

View file

@ -37,6 +37,8 @@ import mage.abilities.TriggeredAbility;
import mage.abilities.common.ChancellorAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffects;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CopyEffect;
import mage.abilities.keyword.LeylineAbility;
import mage.abilities.mana.TriggeredManaAbility;
import mage.actions.impl.MageAction;
@ -67,6 +69,7 @@ import mage.players.Players;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.TargetPlayer;
import mage.util.functions.ApplyToPermanent;
import mage.watchers.common.*;
import org.apache.log4j.Logger;
@ -649,15 +652,17 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
if (isPaused() || isGameOver()) return;
if (allPassed()) {
if (!state.getStack().isEmpty()) {
//20091005 - 115.4
//20091005 - 115.4
resolve();
applyEffects();
state.getPlayers().resetPassed();
fireUpdatePlayersEvent();
state.getRevealed().reset();
resetLKI();
break;
} else {
//removeBookmark(bookmark);
resetLKI();
return;
}
}
@ -718,14 +723,53 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
@Override
public void addEffect(ContinuousEffect continuousEffect, Ability source) {
ContinuousEffect newEffect = (ContinuousEffect)continuousEffect.copy();
Ability newAbility = source.copy();
Ability newAbility = source.copy();
ContinuousEffect newEffect = (ContinuousEffect)continuousEffect.copy();
newEffect.newId();
newEffect.setTimestamp();
newEffect.init(newAbility, this);
state.addEffect(newEffect, newAbility);
state.addEffect(newEffect, newAbility);
}
@Override
public void copyPermanent(Permanent targetPermanent, Ability source, ApplyToPermanent applier) {
Permanent permanent = targetPermanent.copy();
//getState().addCard(permanent);
permanent.reset(this);
permanent.assignNewId();
applier.apply(this, permanent);
Ability newAbility = source.copy();
CopyEffect newEffect = new CopyEffect(permanent, source.getSourceId());
newEffect.newId();
newEffect.setTimestamp();
newEffect.init(newAbility, this);
// handle copies of copies
for (Effect effect : getState().getContinuousEffects().getLayeredEffects(this)) {
if (effect instanceof CopyEffect) {
CopyEffect copyEffect = (CopyEffect) effect;
// there is another copy effect that our targetPermanent copies stats from
if (copyEffect.getSourceId().equals(targetPermanent.getId())) {
MageObject object = ((CopyEffect) effect).getTarget();
if (object instanceof Permanent) {
// so we will use original card instead of target
Permanent original = (Permanent)object;
// copy it and apply changes we need
original = original.copy();
applier.apply(this, original);
newEffect.setTarget(object);
}
}
}
}
state.addEffect(newEffect, newAbility);
}
@Override
public void addTriggeredAbility(TriggeredAbility ability) {
if (ability instanceof TriggeredManaAbility) {
@ -758,7 +802,6 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
}
somethingHappened = true;
}
resetLKI();
return somethingHappened;
}

View file

@ -506,8 +506,10 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
}
@Override
public void clearConnectedCards() {
this.connectedCards.clear();
public void clearConnectedCards(String key) {
if (this.connectedCards.containsKey(key)) {
this.connectedCards.get(key).clear();
}
}
@Override

View file

@ -0,0 +1,12 @@
package mage.util.functions;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
* @author noxx
*/
public abstract class ApplyToPermanent {
public abstract Boolean apply(Game game, Permanent permanent);
}