mirror of
https://github.com/correl/mage.git
synced 2025-03-07 20:53:18 -10:00
* Progenitor Mimic - Fixed that the copy effect did not work correctly (fixes #958).
This commit is contained in:
parent
2b719f1dba
commit
5c041753a6
4 changed files with 126 additions and 99 deletions
|
@ -66,8 +66,6 @@ public class ProgenitorMimic extends CardImpl {
|
|||
this.expansionSetCode = "DGM";
|
||||
this.subtype.add("Shapeshifter");
|
||||
|
||||
this.color.setBlue(true);
|
||||
this.color.setGreen(true);
|
||||
this.power = new MageInt(0);
|
||||
this.toughness = new MageInt(0);
|
||||
|
||||
|
@ -97,6 +95,7 @@ class ProgenitorMimicApplyToPermanent extends ApplyToPermanent {
|
|||
static {
|
||||
filter.add(Predicates.not(new TokenPredicate()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Game game, Permanent permanent) {
|
||||
Ability ability = new ConditionalTriggeredAbility(
|
||||
|
@ -127,26 +126,32 @@ class ProgenitorMimicCopyEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent copyFromPermanent = null;
|
||||
// retrieve the copied permanent of Progenitor Mimic
|
||||
// handle copies of copies
|
||||
for (Effect effect : game.getState().getContinuousEffects().getLayeredEffects(game)) {
|
||||
if (effect instanceof CopyEffect) {
|
||||
CopyEffect copyEffect = (CopyEffect) effect;
|
||||
// take the exiting copy effect of Progenitor Mimic
|
||||
// there is another copy effect that our targetPermanent copies stats from
|
||||
if (copyEffect.getSourceId().equals(source.getSourceId())) {
|
||||
MageObject object = ((CopyEffect) effect).getTarget();
|
||||
if (object instanceof Permanent) {
|
||||
copyFromPermanent = (Permanent)object;
|
||||
MageObject oldBluePrint = ((CopyEffect) effect).getTarget();
|
||||
if (oldBluePrint instanceof Permanent) {
|
||||
// copy it and apply the applier if any
|
||||
copyFromPermanent = (Permanent) oldBluePrint;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (copyFromPermanent != null) {
|
||||
EmptyToken token = new EmptyToken();
|
||||
if (copyFromPermanent == null) {
|
||||
// if it was no copy of copy take the target itself
|
||||
copyFromPermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
}
|
||||
|
||||
if (copyFromPermanent != null) {
|
||||
EmptyToken token = new EmptyToken();
|
||||
CardUtil.copyTo(token).from(copyFromPermanent); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
||||
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
|
||||
Permanent sourcePermanent = game.getPermanent(token.getLastAddedToken());
|
||||
if (sourcePermanent != null) {
|
||||
game.copyPermanent(copyFromPermanent, sourcePermanent, source, new ProgenitorMimicApplyToPermanent());
|
||||
Permanent newPermanentToken = game.getPermanent(token.getLastAddedToken());
|
||||
if (newPermanentToken != null) {
|
||||
game.copyPermanent(copyFromPermanent, newPermanentToken, source, null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,6 @@ public class ProgenitorMimicTest extends CardTestPlayerBase {
|
|||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Progenitor Mimic");
|
||||
|
||||
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Anaconda");
|
||||
|
||||
setStopAt(4, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
|
@ -55,59 +53,81 @@ public class ProgenitorMimicTest extends CardTestPlayerBase {
|
|||
|
||||
Assert.assertEquals("Only one non token permanent ",1, nonTokens);
|
||||
Assert.assertEquals("Only one token permanent ",1, tokens);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If you have Progenitor Mimic copy a creature it gets all of the abilities plus "At the beginning of upkeep
|
||||
* if this creature isn't a token, put a token that's a copy of this creature".
|
||||
* Up to this point everything works correctly.
|
||||
*
|
||||
* If you then summon another mimic and have it be a copy of the first mimic it should have "At the beginning of
|
||||
* upkeep if this creature isn't a token, put a token that's a copy of this creature" two times. The second mimic
|
||||
* would then make two copies and the first mimic would make one copy every turn. Right now the second mimc only
|
||||
* makes one copy per turn.
|
||||
*
|
||||
* 706.9a Some copy effects cause the copy to gain an ability as part of the copying process. This ability becomes
|
||||
* part of the copiable values for the copy, along with any other abilities that were copied.
|
||||
* Example: Quirion Elves enters the battlefield and an Unstable Shapeshifter copies it. The copiable values of the
|
||||
* Shapeshifter now match those of the Elves, except that the Shapeshifter also has the ability “Whenever a creature
|
||||
* enters the battlefield, Unstable Shapeshifter becomes a copy of that creature and gains this ability.” Then a Clone
|
||||
* enters the battlefield as a copy of the Unstable Shapeshifter. The Clone copies the new copiable values of the
|
||||
* Shapeshifter, including the ability that the Shapeshifter gave itself when it copied the Elves.
|
||||
|
||||
// /**
|
||||
// * Tests Clone is sacrificed and only one effect is turned on
|
||||
// */
|
||||
// @Test
|
||||
// public void testCloneSacrifice() {
|
||||
// addCard(Zone.BATTLEFIELD, playerA, "Bloodgift Demon", 1);
|
||||
//
|
||||
// addCard(Zone.HAND, playerA, "Diabolic Edict");
|
||||
// addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
//
|
||||
// addCard(Zone.HAND, playerB, "Clone");
|
||||
// addCard(Zone.BATTLEFIELD, playerB, "Island", 4);
|
||||
//
|
||||
// castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Clone");
|
||||
// castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Diabolic Edict", playerB);
|
||||
//
|
||||
// setStopAt(4, PhaseStep.END_TURN);
|
||||
// execute();
|
||||
//
|
||||
// assertPermanentCount(playerA, "Bloodgift Demon", 1);
|
||||
// assertGraveyardCount(playerA, "Diabolic Edict", 1);
|
||||
// assertPermanentCount(playerB, "Bloodgift Demon", 0);
|
||||
// assertGraveyardCount(playerB, "Clone", 1);
|
||||
//
|
||||
// // 1 from draw steps + 2 from Demon
|
||||
// assertHandCount(playerA, 3);
|
||||
// // 2 from draw steps + no from Demon (should be sacrificed)
|
||||
// assertHandCount(playerB, 2);
|
||||
//
|
||||
// assertLife(playerA, 18);
|
||||
// assertLife(playerB, 20);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testCard3() {
|
||||
// addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
|
||||
// addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
|
||||
// addCard(Zone.HAND, playerA, "Public Execution");
|
||||
// addCard(Zone.HAND, playerA, "Clone");
|
||||
//
|
||||
// addCard(Zone.BATTLEFIELD, playerB, "Llanowar Elves");
|
||||
// addCard(Zone.BATTLEFIELD, playerB, "Craw Wurm");
|
||||
//
|
||||
// castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Executio", "Llanowar Elves");
|
||||
// castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Clone");
|
||||
//
|
||||
// setStopAt(1, PhaseStep.END_TURN);
|
||||
// execute();
|
||||
//
|
||||
// assertPermanentCount(playerB, "Llanowar Elves", 0);
|
||||
// assertPowerToughness(playerB, "Craw Wurm", 4, 4);
|
||||
// assertPowerToughness(playerA, "Craw Wurm", 6, 4);
|
||||
// }
|
||||
*/
|
||||
@Test
|
||||
public void testTwoMimic() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Runeclaw Bear", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
// Return target permanent you control to its owner's hand. You gain 4 life.
|
||||
addCard(Zone.HAND, playerA, "Narrow Escape");
|
||||
|
||||
// You may have Progenitor Mimic enter the battlefield as a copy of any creature on the battlefield except
|
||||
// it gains "At the beginning of your upkeep, if this creature isn't a token, put a token onto the battlefield
|
||||
// that's a copy of this creature."
|
||||
addCard(Zone.HAND, playerB, "Progenitor Mimic", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Forest", 3);
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Progenitor Mimic");
|
||||
setChoice(playerB, "Runeclaw Bear");
|
||||
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Narrow Escape", "Runeclaw Bear");
|
||||
|
||||
// Begin of upkeep 1 token added
|
||||
castSpell(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Progenitor Mimic");
|
||||
setChoice(playerB, "Runeclaw Bear");
|
||||
|
||||
// Begin of upkeep 3 tokens added
|
||||
setStopAt(6, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 24);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
assertGraveyardCount(playerA, "Narrow Escape", 1);
|
||||
assertPermanentCount(playerA, "Runeclaw Bear", 0);
|
||||
assertHandCount(playerA, "Runeclaw Bear", 1);
|
||||
|
||||
assertPermanentCount(playerB, "Runeclaw Bear", 6);
|
||||
|
||||
int tokens = 0;
|
||||
int nonTokens = 0;
|
||||
for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) {
|
||||
if (permanent.getControllerId().equals(playerB.getId())) {
|
||||
if (permanent.getCardType().contains(CardType.CREATURE)) {
|
||||
if (permanent instanceof PermanentToken) {
|
||||
tokens++;
|
||||
} else {
|
||||
nonTokens++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert.assertEquals("Two non token permanents ",2, nonTokens);
|
||||
Assert.assertEquals("Four token permanents",4, tokens);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1285,46 +1285,47 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
|
||||
@Override
|
||||
public Permanent copyPermanent(Duration duration, Permanent copyFromPermanent, Permanent copyToPermanent, Ability source, ApplyToPermanent applier) {
|
||||
Permanent permanent = copyFromPermanent.copy();
|
||||
|
||||
//getState().addCard(permanent);
|
||||
permanent.reset(this);
|
||||
if (copyFromPermanent.isMorphed() || copyFromPermanent.isManifested()) {
|
||||
MorphAbility.setPermanentToFaceDownCreature(permanent);
|
||||
}
|
||||
permanent.assignNewId();
|
||||
if (copyFromPermanent.isTransformed()) {
|
||||
TransformAbility.transform(permanent, copyFromPermanent.getSecondCardFace(), this);
|
||||
}
|
||||
applier.apply(this, permanent);
|
||||
|
||||
CopyEffect newEffect = new CopyEffect(duration, permanent, copyToPermanent.getId());
|
||||
newEffect.newId();
|
||||
newEffect.setApplier(applier);
|
||||
Ability newAbility = source.copy();
|
||||
newEffect.init(newAbility, this);
|
||||
|
||||
Permanent newBluePrint = null;
|
||||
// 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(copyFromPermanent.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);
|
||||
MageObject oldBluePrint = ((CopyEffect) effect).getTarget();
|
||||
if (oldBluePrint instanceof Permanent) {
|
||||
// copy it and apply the applier if any
|
||||
newBluePrint = ((Permanent)oldBluePrint).copy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if it was no copy of copy take the target itself
|
||||
if (newBluePrint == null) {
|
||||
newBluePrint = copyFromPermanent.copy();
|
||||
newBluePrint.reset(this);
|
||||
//getState().addCard(permanent);
|
||||
if (copyFromPermanent.isMorphed() || copyFromPermanent.isManifested()) {
|
||||
MorphAbility.setPermanentToFaceDownCreature(newBluePrint);
|
||||
}
|
||||
newBluePrint.assignNewId();
|
||||
if (copyFromPermanent.isTransformed()) {
|
||||
TransformAbility.transform(newBluePrint, copyFromPermanent.getSecondCardFace(), this);
|
||||
}
|
||||
}
|
||||
if (applier != null) {
|
||||
applier.apply(this, newBluePrint);
|
||||
}
|
||||
|
||||
CopyEffect newEffect = new CopyEffect(duration, newBluePrint, copyToPermanent.getId());
|
||||
newEffect.newId();
|
||||
newEffect.setApplier(applier);
|
||||
Ability newAbility = source.copy();
|
||||
newEffect.init(newAbility, this);
|
||||
|
||||
|
||||
state.addEffect(newEffect, newAbility);
|
||||
return permanent;
|
||||
return newBluePrint;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -209,7 +209,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
this.maxBlockedBy = 0;
|
||||
this.copy = false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
StringBuilder sb = threadLocalBuilder.get();
|
||||
|
@ -516,8 +516,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
if (!phasedIn) {
|
||||
if (!replaceEvent(EventType.PHASE_IN, game)) {
|
||||
this.phasedIn = true;
|
||||
if (!game.isSimulation())
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(getLogName() + " phased in");
|
||||
}
|
||||
fireEvent(EventType.PHASED_IN, game);
|
||||
return true;
|
||||
}
|
||||
|
@ -1345,4 +1346,4 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
fightTarget.damage(getPower().getValue(), getId(), game, false, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue