Fix saga first chapter zcc (#13710)

* Enable disabled tests

* Enable zcc Saga fix

* Remove existing zcc hacks
This commit is contained in:
ssk97 2025-07-06 22:49:51 -07:00 committed by GitHub
parent 6b7ae89479
commit 19f980c2ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 15 additions and 74 deletions

View file

@ -2,8 +2,7 @@ package mage.cards.g;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SagaAbility; import mage.abilities.common.SagaAbility;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.effects.common.DestroyAllEffect;
@ -19,7 +18,6 @@ import mage.filter.predicate.Predicates;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent; import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.DalekToken; import mage.game.permanent.token.DalekToken;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetOpponent; import mage.target.common.TargetOpponent;
@ -44,7 +42,7 @@ public final class GenesisOfTheDaleks extends CardImpl {
// I, II, III -- Create a 3/3 black Dalek artifact creature token with menace for each lore counter on Genesis of the Daleks. // I, II, III -- Create a 3/3 black Dalek artifact creature token with menace for each lore counter on Genesis of the Daleks.
sagaAbility.addChapterEffect( sagaAbility.addChapterEffect(
this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_III, this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_III,
new CreateTokenEffect(new DalekToken(), GenesisOfTheDaleksValue.instance) new CreateTokenEffect(new DalekToken(), new CountersSourceCount(CounterType.LORE))
); );
// IV -- Target opponent faces a villainous choice -- Destroy all Dalek creatures and each of your opponents loses life equal to the total power of Daleks that died this turn, or destroy all non-Dalek creatures. // IV -- Target opponent faces a villainous choice -- Destroy all Dalek creatures and each of your opponents loses life equal to the total power of Daleks that died this turn, or destroy all non-Dalek creatures.
@ -65,41 +63,6 @@ public final class GenesisOfTheDaleks extends CardImpl {
} }
} }
enum GenesisOfTheDaleksValue implements DynamicValue {
instance;
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
Permanent permanent = sourceAbility.getSourcePermanentOrLKI(game);
if (permanent != null) {
return permanent
.getCounters(game)
.getCount(CounterType.LORE);
}
return Optional
.ofNullable(sourceAbility)
.map(Ability::getSourceId)
.map(game::getPermanentOrLKIBattlefield)
.map(p -> p.getCounters(game).getCount(CounterType.LORE))
.orElse(0);
}
@Override
public GenesisOfTheDaleksValue copy() {
return this;
}
@Override
public String getMessage() {
return "lore counter on {this}";
}
@Override
public String toString() {
return "1";
}
}
class GenesisOfTheDaleksEffect extends OneShotEffect { class GenesisOfTheDaleksEffect extends OneShotEffect {
private static final FaceVillainousChoice choice = new FaceVillainousChoice( private static final FaceVillainousChoice choice = new FaceVillainousChoice(

View file

@ -53,8 +53,8 @@ public final class LongListOfTheEnts extends CardImpl {
return new LongListOfTheEnts(this); return new LongListOfTheEnts(this);
} }
static String getKey(Game game, Ability source, int offset) { static String getKey(Game game, Ability source) {
return "EntList_" + source.getSourceId() + "_" + (offset + CardUtil.getActualSourceObjectZoneChangeCounter(game, source)); return "EntList_" + source.getSourceId() + "_" + CardUtil.getActualSourceObjectZoneChangeCounter(game, source);
} }
} }
@ -67,7 +67,7 @@ enum LongListOfTheEntsHint implements Hint {
if (ability.getSourcePermanentIfItStillExists(game) == null) { if (ability.getSourcePermanentIfItStillExists(game) == null) {
return null; return null;
} }
Set<SubType> subTypes = (Set<SubType>) game.getState().getValue(LongListOfTheEnts.getKey(game, ability, 0)); Set<SubType> subTypes = (Set<SubType>) game.getState().getValue(LongListOfTheEnts.getKey(game, ability));
if (subTypes == null || subTypes.isEmpty()) { if (subTypes == null || subTypes.isEmpty()) {
return "No creature types have been noted yet."; return "No creature types have been noted yet.";
} }
@ -109,14 +109,11 @@ class LongListOfTheEntsEffect extends OneShotEffect {
return false; return false;
} }
Object existingEntList = game.getState().getValue(LongListOfTheEnts.getKey(game, source, 0)); Object existingEntList = game.getState().getValue(LongListOfTheEnts.getKey(game, source));
int offset;
Set<SubType> newEntList; Set<SubType> newEntList;
if (existingEntList == null) { if (existingEntList == null) {
offset = 1; // zcc is off-by-one due to still entering battlefield
newEntList = new LinkedHashSet<>(); newEntList = new LinkedHashSet<>();
} else { } else {
offset = 0;
newEntList = new LinkedHashSet<>((Set<SubType>) existingEntList); newEntList = new LinkedHashSet<>((Set<SubType>) existingEntList);
} }
Set<String> chosenTypes = newEntList Set<String> chosenTypes = newEntList
@ -132,7 +129,7 @@ class LongListOfTheEntsEffect extends OneShotEffect {
SubType subType = SubType.byDescription(choice.getChoiceKey()); SubType subType = SubType.byDescription(choice.getChoiceKey());
game.informPlayers(player.getLogName() + " notes the creature type " + subType); game.informPlayers(player.getLogName() + " notes the creature type " + subType);
newEntList.add(subType); newEntList.add(subType);
game.getState().setValue(LongListOfTheEnts.getKey(game, source, offset), newEntList); game.getState().setValue(LongListOfTheEnts.getKey(game, source), newEntList);
FilterSpell filter = new FilterCreatureSpell("a creature spell of that type"); FilterSpell filter = new FilterCreatureSpell("a creature spell of that type");
filter.add(subType.getPredicate()); filter.add(subType.getPredicate());
game.addDelayedTriggeredAbility(new AddCounterNextSpellDelayedTriggeredAbility(filter), source); game.addDelayedTriggeredAbility(new AddCounterNextSpellDelayedTriggeredAbility(filter), source);

View file

@ -107,7 +107,7 @@ class SummonEsperValigarmandaExileEffect extends OneShotEffect {
return !cards.isEmpty() return !cards.isEmpty()
&& controller.moveCardsToExile( && controller.moveCardsToExile(
cards.getCards(game), source, game, true, cards.getCards(game), source, game, true,
CardUtil.getExileZoneId(game, source, 1), CardUtil.getExileZoneId(game, source),
CardUtil.getSourceName(game, source) CardUtil.getSourceName(game, source)
); );
} }

View file

@ -1,15 +1,13 @@
package mage.cards.t; package mage.cards.t;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SagaAbility; import mage.abilities.common.SagaAbility;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.constants.*;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.game.ExileZone; import mage.game.ExileZone;
@ -20,6 +18,8 @@ import mage.target.common.TargetCardInGraveyard;
import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.UUID;
/** /**
* *
* @author Grath * @author Grath
@ -83,7 +83,7 @@ class TheAesirEscapeValhallaOneEffect extends OneShotEffect {
controller.choose(outcome, target, source, game); controller.choose(outcome, target, source, game);
Card card = game.getCard(target.getFirstTarget()); Card card = game.getCard(target.getFirstTarget());
if (card != null) { if (card != null) {
UUID exileId = CardUtil.getExileZoneId(game, source, 1); UUID exileId = CardUtil.getExileZoneId(game, source);
MageObject sourceObject = source.getSourceObject(game); MageObject sourceObject = source.getSourceObject(game);
String exileName = sourceObject != null ? sourceObject.getName() : ""; String exileName = sourceObject != null ? sourceObject.getName() : "";
controller.moveCardsToExile(card, source, game, false, exileId, exileName); controller.moveCardsToExile(card, source, game, false, exileId, exileName);

View file

@ -81,7 +81,7 @@ class TheCreationOfAvacynOneEffect extends OneShotEffect {
if (card != null) { if (card != null) {
// exile it face down // exile it face down
card.setFaceDown(true, game); card.setFaceDown(true, game);
UUID exileId = CardUtil.getExileZoneId(game, source, 1); UUID exileId = CardUtil.getExileZoneId(game, source);
MageObject sourceObject = source.getSourceObject(game); MageObject sourceObject = source.getSourceObject(game);
String exileName = sourceObject != null ? sourceObject.getName() : ""; String exileName = sourceObject != null ? sourceObject.getName() : "";
controller.moveCardsToExile(card, source, game, false, exileId, exileName); controller.moveCardsToExile(card, source, game, false, exileId, exileName);

View file

@ -2,7 +2,6 @@ package org.mage.test.cards.single.cmm;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -19,7 +18,6 @@ public class BattleAtTheHelvaultTest extends CardTestPlayerBase {
*/ */
private static final String battle = "Battle at the Helvault"; private static final String battle = "Battle at the Helvault";
@Ignore // TODO: goal of #11619 is to fix this nicely
@Test @Test
public void test_SimplePlay() { public void test_SimplePlay() {
addCard(Zone.HAND, playerA, battle, 1); addCard(Zone.HAND, playerA, battle, 1);

View file

@ -3,7 +3,6 @@ package org.mage.test.cards.single.fic;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.mage.test.player.TestPlayer; import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -23,7 +22,6 @@ public class SummonIxionTest extends CardTestPlayerBase {
*/ */
private static final String ixion = "Summon: Ixion"; private static final String ixion = "Summon: Ixion";
@Ignore // TODO: goal of #11619 is to fix this nicely
@Test @Test
public void test_SimplePlay() { public void test_SimplePlay() {
addCard(Zone.HAND, playerA, ixion, 1); addCard(Zone.HAND, playerA, ixion, 1);

View file

@ -2,7 +2,6 @@ package org.mage.test.cards.single.pip;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.mage.test.player.TestPlayer; import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -21,7 +20,6 @@ public class Vault13DwellersJourneyTest extends CardTestPlayerBase {
*/ */
private static final String vault = "Vault 13: Dweller's Journey"; private static final String vault = "Vault 13: Dweller's Journey";
@Ignore // TODO: goal of #11619 is to fix this nicely
@Test @Test
public void test_SimplePlay_ReturnOne() { public void test_SimplePlay_ReturnOne() {
addCard(Zone.HAND, playerA, vault, 1); addCard(Zone.HAND, playerA, vault, 1);
@ -49,7 +47,6 @@ public class Vault13DwellersJourneyTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Memnite", 1); assertPermanentCount(playerA, "Memnite", 1);
assertLife(playerA, 20 + 2); assertLife(playerA, 20 + 2);
} }
@Ignore // TODO: goal of #11619 is to fix this nicely
@Test @Test
public void test_SimplePlay_Return() { public void test_SimplePlay_Return() {
addCard(Zone.HAND, playerA, vault, 1); addCard(Zone.HAND, playerA, vault, 1);
@ -81,7 +78,6 @@ public class Vault13DwellersJourneyTest extends CardTestPlayerBase {
assertLife(playerA, 20 + 2); assertLife(playerA, 20 + 2);
} }
@Ignore // TODO: goal of #11619 is to fix this nicely
@Test @Test
public void test_SimplePlay_NoReturn() { public void test_SimplePlay_NoReturn() {
addCard(Zone.HAND, playerA, vault, 1); addCard(Zone.HAND, playerA, vault, 1);

View file

@ -2,7 +2,6 @@ package org.mage.test.cards.single.who;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -18,7 +17,6 @@ public class DayOfTheMoonTest extends CardTestPlayerBase {
*/ */
private static final String day = "Day of the Moon"; private static final String day = "Day of the Moon";
@Ignore // TODO: goal of #11619 is to fix this nicely
@Test @Test
public void test_SimplePlay() { public void test_SimplePlay() {
addCard(Zone.HAND, playerA, day, 1); addCard(Zone.HAND, playerA, day, 1);

View file

@ -2,7 +2,6 @@ package org.mage.test.cards.single.who;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -20,7 +19,6 @@ public class TheWarGamesTest extends CardTestPlayerBase {
*/ */
private static final String war = "The War Games"; private static final String war = "The War Games";
@Ignore // TODO: goal of #11619 is to fix this nicely
@Test @Test
public void test_SimplePlay_NoExile() { public void test_SimplePlay_NoExile() {
addCard(Zone.HAND, playerA, war, 1); addCard(Zone.HAND, playerA, war, 1);
@ -63,7 +61,6 @@ public class TheWarGamesTest extends CardTestPlayerBase {
assertLife(playerB, 20 - 6 - 9); assertLife(playerB, 20 - 6 - 9);
} }
@Ignore // TODO: goal of #11619 is to fix this nicely
@Test @Test
public void test_SimplePlay_Exile() { public void test_SimplePlay_Exile() {
addCard(Zone.HAND, playerA, war, 1); addCard(Zone.HAND, playerA, war, 1);

View file

@ -2,7 +2,6 @@ package org.mage.test.cards.single.who;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -20,7 +19,6 @@ public class TrialOfATimeLordTest extends CardTestPlayerBase {
*/ */
private static final String trial = "Trial of a Time Lord"; private static final String trial = "Trial of a Time Lord";
@Ignore // TODO: goal of #11619 is to fix this nicely
@Test @Test
public void test_SimplePlay() { public void test_SimplePlay() {
addCard(Zone.HAND, playerA, trial, 1); addCard(Zone.HAND, playerA, trial, 1);

View file

@ -3,7 +3,6 @@ package org.mage.test.cards.single.woe;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -21,7 +20,6 @@ public class ThePrincessTakesFlightTest extends CardTestPlayerBase {
*/ */
private static final String flight = "The Princess Takes Flight"; private static final String flight = "The Princess Takes Flight";
@Ignore // TODO: goal of #11619 is to fix this nicely
@Test @Test
public void test_SimplePlay() { public void test_SimplePlay() {
addCard(Zone.HAND, playerA, flight, 1); addCard(Zone.HAND, playerA, flight, 1);
@ -54,7 +52,6 @@ public class ThePrincessTakesFlightTest extends CardTestPlayerBase {
assertExileCount(playerB, "Memnite", 0); assertExileCount(playerB, "Memnite", 0);
assertPermanentCount(playerB, "Memnite", 1); assertPermanentCount(playerB, "Memnite", 1);
} }
@Ignore // TODO: goal of #11619 is to fix this nicely
@Test @Test
public void testFlicker() { public void testFlicker() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);

View file

@ -1707,15 +1707,14 @@ public abstract class AbilityImpl implements Ability {
private int getCurrentSourceObjectZoneChangeCounter(Game game){ private int getCurrentSourceObjectZoneChangeCounter(Game game){
int zcc = game.getState().getZoneChangeCounter(getSourceId()); int zcc = game.getState().getZoneChangeCounter(getSourceId());
// TODO: Enable this, #13710 if (game.getPermanentEntering(getSourceId()) != null){
/*if (game.getPermanentEntering(getSourceId()) != null){
// If the triggered ability triggered while the permanent is entering the battlefield // If the triggered ability triggered while the permanent is entering the battlefield
// then add 1 zcc so that it triggers as if the permanent was already on the battlefield // then add 1 zcc so that it triggers as if the permanent was already on the battlefield
// So "Enters with counters" causes "Whenever counters are placed" to trigger with battlefield zcc // So "Enters with counters" causes "Whenever counters are placed" to trigger with battlefield zcc
// Particularly relevant for Sagas, which always involve both // Particularly relevant for Sagas, which always involve both
// Note that this does NOT apply to "As ~ ETB" effects, those still use the stack zcc // Note that this does NOT apply to "As ~ ETB" effects, those still use the stack zcc
zcc += 1; zcc += 1;
}*/ }
return zcc; return zcc;
} }