use StaticAbility for Topsy Turvy (#7143)

This commit is contained in:
Hans Mackowiak
2025-03-12 09:24:53 +01:00
committed by GitHub
parent fbff1fe10a
commit 137d87c3df
8 changed files with 68 additions and 18 deletions

View File

@@ -522,7 +522,7 @@ public class Game {
* The Direction in which the turn order of this Game currently proceeds.
*/
public final Direction getTurnOrder() {
if (phaseHandler.getPlayerTurn() != null && phaseHandler.getPlayerTurn().getAmountOfKeyword("The turn order is reversed.") % 2 == 1) {
if (phaseHandler.getPlayerTurn() != null && phaseHandler.getPlayerTurn().isTurnOrderReversed()) {
return turnOrder.getOtherDirection();
}
return turnOrder;

View File

@@ -25,7 +25,7 @@ public class AddPhaseEffect extends SpellAbilityEffect {
public void resolve(SpellAbility sa) {
final Card host = sa.getHostCard();
final Player activator = sa.getActivatingPlayer();
boolean isTopsy = activator.getAmountOfKeyword("The phases of your turn are reversed.") % 2 == 1;
boolean isTopsy = activator.isPhasesReversed();
PhaseHandler phaseHandler = activator.getGame().getPhaseHandler();
PhaseType currentPhase = phaseHandler.getPhase();

View File

@@ -303,6 +303,6 @@ public class FlipCoinEffect extends SpellAbilityEffect {
public static int getFlipMultiplier(final Player flipper) {
String str = "If you would flip a coin, instead flip two coins and ignore one.";
return 1 << flipper.getKeywords().getAmount(str);
return 1 << flipper.getAmountOfKeyword(str);
}
}

View File

@@ -142,7 +142,7 @@ public class PhaseHandler implements java.io.Serializable {
private void advanceToNextPhase() {
PhaseType oldPhase = phase;
boolean isTopsy = playerTurn.getAmountOfKeyword("The phases of your turn are reversed.") % 2 == 1;
boolean isTopsy = playerTurn.isPhasesReversed();
boolean turnEnded = false;
game.getStack().clearUndoStack(); //can't undo action from previous phase
@@ -1165,7 +1165,7 @@ public class PhaseHandler implements java.io.Serializable {
return devAdvanceToPhase(targetPhase, null);
}
public final boolean devAdvanceToPhase(PhaseType targetPhase, Runnable resolver) {
boolean isTopsy = playerTurn.getAmountOfKeyword("The phases of your turn are reversed.") % 2 == 1;
boolean isTopsy = playerTurn.isPhasesReversed();
while (phase.isBefore(targetPhase, isTopsy)) {
if (checkStateBasedEffects()) {
return false;

View File

@@ -2232,7 +2232,7 @@ public class Player extends GameEntity implements Comparable<Player> {
numManaConversion = l;
}
public final boolean hasManaConversion() {
return numManaConversion < keywords.getAmount("You may spend mana as though"
return numManaConversion < getAmountOfKeyword("You may spend mana as though"
+ " it were mana of any type to cast a spell this turn.");
}
public final void incNumManaConversion() {
@@ -2547,6 +2547,13 @@ public class Player extends GameEntity implements Comparable<Player> {
return keywords.getAmount(k);
}
public boolean isTurnOrderReversed() {
return StaticAbilityTurnPhaseReversed.isTurnReversed(this);
}
public boolean isPhasesReversed() {
return StaticAbilityTurnPhaseReversed.isPhaseReversed(this);
}
public void onCleanupPhase() {
for (Card c : getCardsIn(ZoneType.Hand)) {
c.setDrawnThisTurn(false);

View File

@@ -0,0 +1,43 @@
package forge.game.staticability;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
public class StaticAbilityTurnPhaseReversed {
static String TURN_MODE = "TurnReversed";
static String PHASE_MODE = "PhaseReversed";
public static boolean isTurnReversed(Player player) {
return anyTurnPhaseReversed(player, TURN_MODE);
}
public static boolean isPhaseReversed(Player player) {
return anyTurnPhaseReversed(player, PHASE_MODE);
}
protected static boolean anyTurnPhaseReversed(Player player, final String mode)
{
boolean result = false;
final Game game = player.getGame();
for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) {
for (final StaticAbility stAb : ca.getStaticAbilities()) {
if (!stAb.checkConditions(mode)) {
continue;
}
if (applyTurnPhaseReversed(stAb, player)) {
result = !result;
}
}
}
return result;
}
protected static boolean applyTurnPhaseReversed(StaticAbility stAb, Player player) {
if (!stAb.matchesValidParam("ValidPlayer", player)) {
return false;
}
return true;
}
}

View File

@@ -75,7 +75,7 @@ public class GameSimulationTest extends SimulationTest {
game.getAction().checkStateEffects(true);
game.getAction().checkStateEffects(true);
AssertJUnit.assertEquals(1, sliver.getAmountOfKeyword("Flanking"));
AssertJUnit.assertEquals(1, sliver.getAmountOfKeyword(Keyword.FLANKING));
AssertJUnit.assertEquals(2, sliver.getNetPower());
AssertJUnit.assertEquals(2, sliver.getNetToughness());
@@ -87,7 +87,7 @@ public class GameSimulationTest extends SimulationTest {
AssertJUnit.assertTrue(score > 0);
Game simGame = sim.getSimulatedGameState();
Card sliverCopy = findCardWithName(simGame, sliverCardName);
AssertJUnit.assertEquals(1, sliverCopy.getAmountOfKeyword("Flanking"));
AssertJUnit.assertEquals(1, sliverCopy.getAmountOfKeyword(Keyword.FLANKING));
AssertJUnit.assertEquals(2, sliver.getNetPower());
AssertJUnit.assertEquals(2, sliver.getNetToughness());
}
@@ -103,15 +103,15 @@ public class GameSimulationTest extends SimulationTest {
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
game.getAction().checkStateEffects(true);
AssertJUnit.assertTrue(lion.isMonstrous());
AssertJUnit.assertEquals(1, lion.getAmountOfKeyword("Hexproof"));
AssertJUnit.assertEquals(1, lion.getAmountOfKeyword("Indestructible"));
AssertJUnit.assertEquals(1, lion.getAmountOfKeyword(Keyword.HEXPROOF));
AssertJUnit.assertEquals(1, lion.getAmountOfKeyword(Keyword.INDESTRUCTIBLE));
GameSimulator sim = createSimulator(game, p);
Game simGame = sim.getSimulatedGameState();
Card lionCopy = findCardWithName(simGame, lionCardName);
AssertJUnit.assertTrue(lionCopy.isMonstrous());
AssertJUnit.assertEquals(1, lionCopy.getAmountOfKeyword("Hexproof"));
AssertJUnit.assertEquals(1, lionCopy.getAmountOfKeyword("Indestructible"));
AssertJUnit.assertEquals(1, lionCopy.getAmountOfKeyword(Keyword.HEXPROOF));
AssertJUnit.assertEquals(1, lionCopy.getAmountOfKeyword(Keyword.INDESTRUCTIBLE));
}
@Test
@@ -125,12 +125,12 @@ public class GameSimulationTest extends SimulationTest {
cloak.attachToEntity(bear, null);
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
game.getAction().checkStateEffects(true);
AssertJUnit.assertEquals(1, bear.getAmountOfKeyword("Shroud"));
AssertJUnit.assertEquals(1, bear.getAmountOfKeyword(Keyword.SHROUD));
GameSimulator sim = createSimulator(game, p);
Game simGame = sim.getSimulatedGameState();
Card bearCopy = findCardWithName(simGame, bearCardName);
AssertJUnit.assertEquals(1, bearCopy.getAmountOfKeyword("Shroud"));
AssertJUnit.assertEquals(1, bearCopy.getAmountOfKeyword(Keyword.SHROUD));
}
@Test
@@ -144,12 +144,12 @@ public class GameSimulationTest extends SimulationTest {
lifelink.attachToEntity(bear, null);
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
game.getAction().checkStateEffects(true);
AssertJUnit.assertEquals(1, bear.getAmountOfKeyword("Lifelink"));
AssertJUnit.assertEquals(1, bear.getAmountOfKeyword(Keyword.LIFELINK));
GameSimulator sim = createSimulator(game, p);
Game simGame = sim.getSimulatedGameState();
Card bearCopy = findCardWithName(simGame, bearCardName);
AssertJUnit.assertEquals(1, bearCopy.getAmountOfKeyword("Lifelink"));
AssertJUnit.assertEquals(1, bearCopy.getAmountOfKeyword(Keyword.LIFELINK));
}
@Test

View File

@@ -1,7 +1,7 @@
Name:Topsy Turvy
ManaCost:2 U
Types:Enchantment
S:Mode$ Continuous | Affected$ Player | AddKeyword$ The phases of your turn are reversed. | Description$ The phases of each player's turn are reversed. (The phases are, in reverse order, ending, postcombat main, combat, precombat main, and beginning.)
S:Mode$ Continuous | Affected$ Player | AddKeyword$ The turn order is reversed. | CheckSVar$ X | SVarCompare$ GT2 | Description$ As long as there are more than two players in the game, the turn order is reversed.
S:Mode$ PhaseReversed | ValidPlayer$ Player | Description$ The phases of each player's turn are reversed. (The phases are, in reverse order, ending, postcombat main, combat, precombat main, and beginning.)
S:Mode$ TurnReversed | ValidPlayer$ Player | CheckSVar$ X | SVarCompare$ GT2 | Description$ As long as there are more than two players in the game, the turn order is reversed.
SVar:X:PlayerCountPlayers$Amount
Oracle:The phases of each player's turn are reversed. (The phases are, in reverse order, ending, postcombat main, combat, precombat main, and beginning.)\nAs long as there are more than two players in the game, the turn order is reversed.