LKICopy Transform and flip (#3146)

* LKICopy Transform and flip

* Update CardUtil.java

Fix newCopy state when flipped or transformed

* Update CardUtil.java

fix backside

* Update CardUtil.java

add EffectSource

* CardStateName.Transformed needs to be copied

* Fixes #3201 somewhat

* Fix CardState for Fused Spells

* GameSimulationTest: Add Ratadrabik + TDFC token test
This commit is contained in:
Hans Mackowiak
2023-06-06 12:43:40 +02:00
committed by GitHub
parent f8814df5fb
commit a7c0d41064
4 changed files with 94 additions and 20 deletions

View File

@@ -511,6 +511,7 @@ public final class AbilityFactory {
totalCost.add(parseAbilityCost(rightState, rightMap, rightType));
final SpellAbility left = getAbility(leftType, leftApi, leftMap, totalCost, leftState, leftState);
left.setCardState(card.getState(CardStateName.Original));
final AbilitySub right = (AbilitySub) getAbility(AbilityRecordType.SubAbility, rightApi, rightMap, null, rightState, rightState);
left.appendSubAbility(right);
return left;

View File

@@ -753,6 +753,19 @@ public class CardFactory {
final CardState ret2 = new CardState(out, CardStateName.Transformed);
ret2.copyFrom(in.getState(CardStateName.Transformed), false, sa);
result.put(CardStateName.Transformed, ret2);
} else if (in.isSplitCard()) {
// for split cards, copy all three states
final CardState ret1 = new CardState(out, CardStateName.Original);
ret1.copyFrom(in.getState(CardStateName.Original), false, sa);
result.put(CardStateName.Original, ret1);
final CardState ret2 = new CardState(out, CardStateName.LeftSplit);
ret2.copyFrom(in.getState(CardStateName.LeftSplit), false, sa);
result.put(CardStateName.LeftSplit, ret2);
final CardState ret3 = new CardState(out, CardStateName.RightSplit);
ret3.copyFrom(in.getState(CardStateName.RightSplit), false, sa);
result.put(CardStateName.RightSplit, ret3);
} else {
// in all other cases just copy the current state to original
final CardState ret = new CardState(out, CardStateName.Original);

View File

@@ -194,24 +194,49 @@ public final class CardUtil {
newCopy.setController(in.getController(), 0);
newCopy.setCommander(in.isCommander());
newCopy.setRules(in.getRules());
// needed to ensure that the LKI object has correct CMC info no matter what state the original card was in
// (e.g. Scrap Trawler + transformed Harvest Hand)
newCopy.setLKICMC(in.getCMC());
// used for the purpose of cards that care about the zone the card was known to be in last
newCopy.setLastKnownZone(in.getLastKnownZone());
// copy EffectSource for description
newCopy.setEffectSource(getLKICopy(in.getEffectSource(), cachedMap));
newCopy.getCurrentState().copyFrom(in.getState(in.getFaceupCardStateName()), true);
if (in.isFlipCard()) {
newCopy.getState(CardStateName.Original).copyFrom(in.getState(CardStateName.Original), true);
newCopy.addAlternateState(CardStateName.Flipped, false);
newCopy.getState(CardStateName.Flipped).copyFrom(in.getState(CardStateName.Flipped), true);
} else if (in.isTransformable()) {
newCopy.getState(CardStateName.Original).copyFrom(in.getState(CardStateName.Original), true);
newCopy.addAlternateState(CardStateName.Transformed, false);
newCopy.getState(CardStateName.Transformed).copyFrom(in.getState(CardStateName.Transformed), true);
} else if (in.isAdventureCard()) {
newCopy.getState(CardStateName.Original).copyFrom(in.getState(CardStateName.Original), true);
newCopy.addAlternateState(CardStateName.Adventure, false);
newCopy.getState(CardStateName.Adventure).copyFrom(in.getState(CardStateName.Adventure), true);
} else if (in.isSplitCard()) {
newCopy.getState(CardStateName.Original).copyFrom(in.getState(CardStateName.Original), true);
newCopy.addAlternateState(CardStateName.LeftSplit, false);
newCopy.getState(CardStateName.LeftSplit).copyFrom(in.getState(CardStateName.LeftSplit), true);
newCopy.addAlternateState(CardStateName.RightSplit, false);
newCopy.getState(CardStateName.RightSplit).copyFrom(in.getState(CardStateName.RightSplit), true);
} else {
newCopy.getCurrentState().copyFrom(in.getState(in.getFaceupCardStateName()), true);
}
newCopy.setFlipped(in.isFlipped());
newCopy.setBackSide(in.isBackSide());
if (in.isTransformed()) {
newCopy.incrementTransformedTimestamp();
}
newCopy.setState(newCopy.getFaceupCardStateName(), false, true);
if (in.isFaceDown()) {
newCopy.turnFaceDownNoUpdate();
newCopy.setType(new CardType(in.getFaceDownState().getType()));
// prevent StackDescription from revealing face
newCopy.updateStateForView();
}
if (in.isAdventureCard() && in.getFaceupCardStateName().equals(CardStateName.Original)) {
newCopy.addAlternateState(CardStateName.Adventure, false);
newCopy.getState(CardStateName.Adventure).copyFrom(in.getState(CardStateName.Adventure), true);
}
// prevent StackDescription from revealing face
newCopy.updateStateForView();
/*
if (in.isCloned()) {
@@ -300,9 +325,6 @@ public final class CardUtil {
newCopy.setTimestamp(in.getTimestamp());
newCopy.setBestowTimestamp(in.getBestowTimestamp());
if (in.isTransformed()) {
newCopy.incrementTransformedTimestamp();
}
newCopy.setForetold(in.isForetold());
newCopy.setForetoldThisTurn(in.isForetoldThisTurn());

View File

@@ -1779,7 +1779,7 @@ public class GameSimulationTest extends SimulationTest {
AssertJUnit.assertTrue(clonedOutLaw.isCloned());
AssertJUnit.assertTrue(clonedOutLaw.isTransformable());
AssertJUnit.assertFalse(clonedOutLaw.hasState(CardStateName.Transformed));
AssertJUnit.assertTrue(clonedOutLaw.hasState(CardStateName.Transformed));
AssertJUnit.assertTrue(clonedOutLaw.canTransform(null));
AssertJUnit.assertFalse(clonedOutLaw.isBackSide());
@@ -1800,7 +1800,7 @@ public class GameSimulationTest extends SimulationTest {
AssertJUnit.assertTrue(transformOutLaw.isCloned());
AssertJUnit.assertTrue(transformOutLaw.isTransformable());
AssertJUnit.assertFalse(transformOutLaw.hasState(CardStateName.Transformed));
AssertJUnit.assertTrue(transformOutLaw.hasState(CardStateName.Transformed));
AssertJUnit.assertTrue(transformOutLaw.canTransform(null));
AssertJUnit.assertTrue(transformOutLaw.isBackSide());
@@ -2451,13 +2451,9 @@ public class GameSimulationTest extends SimulationTest {
// whereas Naban doesn't see Memnarch to double the trigger
addCardToZone("Memnarch", p, ZoneType.Library);
addCard("Forest", p);
addCard("Forest", p);
addCard("Island", p);
addCard("Island", p);
addCard("Island", p);
addCard("Mountain", p);
addCard("Mountain", p);
addCards("Forest", 2, p);
addCards("Island", 3, p);
addCards("Mountain", 2, p);
Card genesis = addCardToZone("Genesis Ultimatum", p, ZoneType.Hand);
@@ -2473,4 +2469,46 @@ public class GameSimulationTest extends SimulationTest {
// 2 damage dealt for 2 artifacts
AssertJUnit.assertEquals(18, simGame.getPlayers().get(1).getLife());
}
@Test
public void testLKITransformableTokenCopy() {
Game game = initAndCreateGame();
Player p = game.getPlayers().get(0);
String untransformedName = "Heliod, the Radiant Dawn";
String transformedName = "Heliod, the Warped Eclipse";
addCard("Ratadrabik of Urborg", p);
Card heliod = addCard(untransformedName, p);
addCards("Island", 4, p);
addCards("Swamp", 3, p);
Card murder = addCardToZone("Murder", p, ZoneType.Hand);
SpellAbility murderSA = murder.getFirstSpellAbility();
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
game.getAction().checkStateEffects(true);
SpellAbility transformSA = findSAWithPrefix(heliod, "{3}{U/P}: Transform");
GameSimulator sim = createSimulator(game, p);
AssertJUnit.assertNotNull(transformSA);
sim.simulateSpellAbility(transformSA);
Game simGame = sim.getSimulatedGameState();
Card transformedHeliod = findCardWithName(simGame, transformedName);
AssertJUnit.assertNotNull(transformedHeliod);
murderSA.getTargets().add(transformedHeliod);
sim.simulateSpellAbility(murderSA);
simGame = sim.getSimulatedGameState();
Card transformedHeliodToken = findCardWithName(simGame, transformedName);
AssertJUnit.assertNotNull(transformedHeliodToken);
AssertJUnit.assertTrue(transformedHeliodToken.isToken());
AssertJUnit.assertTrue(transformedHeliodToken.isTransformable());
AssertJUnit.assertTrue(transformedHeliodToken.isTransformed());
AssertJUnit.assertTrue(transformedHeliodToken.isBackSide());
}
}