ONE: The Eternal Wanderer + support + tidy related cards

This commit is contained in:
Northmoc
2023-02-03 13:53:31 -05:00
parent d99e43209a
commit 24e9f6505a
13 changed files with 85 additions and 62 deletions

View File

@@ -26,8 +26,6 @@ public enum GlobalRuleChange {
attackerChoosesBlockers ("The attacking player chooses how each creature blocks each combat."), attackerChoosesBlockers ("The attacking player chooses how each creature blocks each combat."),
manaBurn ("A player losing unspent mana causes that player to lose that much life."), manaBurn ("A player losing unspent mana causes that player to lose that much life."),
noNight ("It can't become night."), noNight ("It can't become night."),
/* onlyOneAttackerATurn ("No more than one creature can attack each turn."), */
onlyOneAttackerACombat ("No more than one creature can attack each combat."),
onlyOneBlocker ("No more than one creature can block each combat."), onlyOneBlocker ("No more than one creature can block each combat."),
onlyOneBlockerPerOpponent ("Each opponent can't block with more than one creature."), onlyOneBlockerPerOpponent ("Each opponent can't block with more than one creature."),
onlyTwoBlockers ("No more than two creatures can block each combat."), onlyTwoBlockers ("No more than two creatures can block each combat."),

View File

@@ -7,10 +7,9 @@ import com.google.common.primitives.Ints;
import forge.game.Game; import forge.game.Game;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.GlobalRuleChange;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.staticability.StaticAbilityAttackRestrict;
import forge.util.collect.FCollectionView; import forge.util.collect.FCollectionView;
import forge.util.maps.LinkedHashMapToAmount; import forge.util.maps.LinkedHashMapToAmount;
import forge.util.maps.MapToAmount; import forge.util.maps.MapToAmount;
@@ -107,33 +106,13 @@ public class GlobalAttackRestrictions {
* @return a {@link GlobalAttackRestrictions} object. * @return a {@link GlobalAttackRestrictions} object.
*/ */
public static GlobalAttackRestrictions getGlobalRestrictions(final Player attackingPlayer, final FCollectionView<GameEntity> possibleDefenders) { public static GlobalAttackRestrictions getGlobalRestrictions(final Player attackingPlayer, final FCollectionView<GameEntity> possibleDefenders) {
int max = -1;
final MapToAmount<GameEntity> defenderMax = new LinkedHashMapToAmount<>(possibleDefenders.size()); final MapToAmount<GameEntity> defenderMax = new LinkedHashMapToAmount<>(possibleDefenders.size());
final Game game = attackingPlayer.getGame(); final Game game = attackingPlayer.getGame();
/* if (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyOneAttackerATurn)) { int max = StaticAbilityAttackRestrict.globalAttackRestrict(game);
if (!attackingPlayer.getAttackedWithCreatureThisTurn().isEmpty()) {
max = 0;
} else {
max = 1;
}
} */
if (max == -1 && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyOneAttackerACombat)) {
max = 1;
}
if (max == -1) {
for (final Card card : game.getCardsIn(ZoneType.Battlefield)) {
if (card.hasKeyword("No more than two creatures can attack each combat.")) {
max = 2;
break;
}
}
}
for (final GameEntity defender : possibleDefenders) { for (final GameEntity defender : possibleDefenders) {
final int defMax = getMaxAttackTo(defender); final int defMax = StaticAbilityAttackRestrict.attackRestrictNum(defender);
if (defMax != -1) { if (defMax != -1) {
defenderMax.add(defender, defMax); defenderMax.add(defender, defMax);
} }
@@ -145,27 +124,4 @@ public class GlobalAttackRestrictions {
return new GlobalAttackRestrictions(max, defenderMax); return new GlobalAttackRestrictions(max, defenderMax);
} }
/**
* <p>
* Get the maximum number of creatures allowed to attack a certain defender.
* </p>
*
* @param defender
* the defending {@link GameEntity}.
* @return the maximum number of creatures, or -1 if it is unlimited.
*/
private static int getMaxAttackTo(final GameEntity defender) {
if (defender instanceof Player) {
for (final Card card : ((Player) defender).getCardsIn(ZoneType.Battlefield)) {
if (card.hasKeyword("No more than one creature can attack you each combat.")) {
return 1;
} else if (card.hasKeyword("No more than two creatures can attack you each combat.")) {
return 2;
}
}
}
return -1;
}
} }

View File

@@ -0,0 +1,53 @@
package forge.game.staticability;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.zone.ZoneType;
public class StaticAbilityAttackRestrict {
static String MODE = "AttackRestrict";
static public int globalAttackRestrict(Game game) {
int max = Integer.MAX_VALUE;
for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) {
for (final StaticAbility stAb : ca.getStaticAbilities()) {
if (!stAb.getParam("Mode").equals(MODE) || stAb.isSuppressed() || !stAb.checkConditions()
|| stAb.hasParam("ValidDefender")) {
continue;
}
int stMax = AbilityUtils.calculateAmount(stAb.getHostCard(),
stAb.getParamOrDefault("MaxAttackers", "1"), stAb);
if (stMax < max) {
max = stMax;
}
}
}
return max < Integer.MAX_VALUE ? max : -1;
}
static public int attackRestrictNum(GameEntity defender) {
final Game game = defender.getGame();
for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) {
for (final StaticAbility stAb : ca.getStaticAbilities()) {
if (!stAb.getParam("Mode").equals(MODE) || stAb.isSuppressed() || !stAb.checkConditions()) {
continue;
}
if (attackRestrict(stAb, defender)) {
return AbilityUtils.calculateAmount(stAb.getHostCard(),
stAb.getParamOrDefault("MaxAttackers", "1"), stAb);
}
}
}
return -1;
}
static public boolean attackRestrict(StaticAbility stAb, GameEntity defender) {
if (!stAb.matchesValidParam("ValidDefender", defender)) {
return false;
}
return true;
}
}

View File

@@ -1,7 +1,7 @@
Name:Astral Arena Name:Astral Arena
ManaCost:no cost ManaCost:no cost
Types:Plane Kolbahan Types:Plane Kolbahan
S:Mode$ Continuous | EffectZone$ Command | GlobalRule$ No more than one creature can attack each combat. | Description$ No more than one creature can attack each combat. S:Mode$ AttackRestrict | EffectZone$ Command | MaxAttackers$ 1 | Description$ No more than one creature can attack each combat.
S:Mode$ Continuous | EffectZone$ Command | GlobalRule$ No more than one creature can block each combat. | Description$ No more than one creature can block each combat. S:Mode$ Continuous | EffectZone$ Command | GlobalRule$ No more than one creature can block each combat. | Description$ No more than one creature can block each combat.
T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll {CHAOS}, CARDNAME deals 2 damage to each creature. T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll {CHAOS}, CARDNAME deals 2 damage to each creature.
SVar:RolledChaos:DB$ DamageAll | NumDmg$ 2 | ValidCards$ Creature | ValidDescription$ each creature. SVar:RolledChaos:DB$ DamageAll | NumDmg$ 2 | ValidCards$ Creature | ValidDescription$ each creature.

View File

@@ -1,7 +1,7 @@
Name:Caverns of Despair Name:Caverns of Despair
ManaCost:2 R R ManaCost:2 R R
Types:World Enchantment Types:World Enchantment
K:No more than two creatures can attack each combat. S:Mode$ AttackRestrict | MaxAttackers$ 2 | Description$ No more than two creatures can attack each combat.
S:Mode$ Continuous | GlobalRule$ No more than two creatures can block each combat. | Description$ No more than two creatures can block each combat. S:Mode$ Continuous | GlobalRule$ No more than two creatures can block each combat. | Description$ No more than two creatures can block each combat.
SVar:NonStackingEffect:True SVar:NonStackingEffect:True
AI:RemoveDeck:Random AI:RemoveDeck:Random

View File

@@ -1,7 +1,6 @@
Name:Crawlspace Name:Crawlspace
ManaCost:3 ManaCost:3
Types:Artifact Types:Artifact
K:No more than two creatures can attack you each combat. S:Mode$ AttackRestrict | MaxAttackers$ 2 | ValidDefender$ You | Description$ No more than two creatures can attack you each combat.
SVar:NonStackingEffect:True SVar:NonStackingEffect:True
AI:RemoveDeck:Random
Oracle:No more than two creatures can attack you each combat. Oracle:No more than two creatures can attack you each combat.

View File

@@ -1,7 +1,7 @@
Name:Dueling Grounds Name:Dueling Grounds
ManaCost:1 G W ManaCost:1 G W
Types:Enchantment Types:Enchantment
S:Mode$ Continuous | GlobalRule$ No more than one creature can attack each combat. | Description$ No more than one creature can attack each combat. S:Mode$ AttackRestrict | MaxAttackers$ 1 | Description$ No more than one creature can attack each combat.
S:Mode$ Continuous | GlobalRule$ No more than one creature can block each combat. | Description$ No more than one creature can block each combat. S:Mode$ Continuous | GlobalRule$ No more than one creature can block each combat. | Description$ No more than one creature can block each combat.
AI:RemoveDeck:Random AI:RemoveDeck:Random
Oracle:No more than one creature can attack each combat.\nNo more than one creature can block each combat. Oracle:No more than one creature can attack each combat.\nNo more than one creature can block each combat.

View File

@@ -5,7 +5,7 @@ PT:5/5
K:Kicker:3 K:Kicker:3
K:etbCounter:P1P1:5:CheckSVar$ WasKicked:If CARDNAME was kicked, it enters the battlefield with five +1/+1 counters on it. K:etbCounter:P1P1:5:CheckSVar$ WasKicked:If CARDNAME was kicked, it enters the battlefield with five +1/+1 counters on it.
SVar:WasKicked:Count$Kicked.1.0 SVar:WasKicked:Count$Kicked.1.0
T:Mode$ Attacks | ValidCard$ Card.Self | Alone$ True | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAME attacks alone, double its power and toughness until end of turn. T:Mode$ Attacks | ValidCard$ Card.Self | Alone$ True | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever NICKNAME attacks alone, double its power and toughness until end of turn.
SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ +X | NumDef$ +Y | Double$ True SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ +X | NumDef$ +Y | Double$ True
SVar:X:Count$CardPower SVar:X:Count$CardPower
SVar:Y:Count$CardToughness SVar:Y:Count$CardToughness

View File

@@ -3,8 +3,8 @@ ManaCost:1 G W
Types:Legendary Creature Cat Warrior Types:Legendary Creature Cat Warrior
PT:3/2 PT:3/2
K:First Strike K:First Strike
S:Mode$ Continuous | EffectZone$ Battlefield | Affected$ Card.Self+tapped | AddKeyword$ No more than one creature can attack you each combat. | Description$ As long as CARDNAME is tapped, no more than one creature can attack you each combat. S:Mode$ AttackRestrict | IsPresent$ Card.Self+tapped | MaxAttackers$ 1 | ValidDefender$ You | Description$ As long as CARDNAME is tapped, no more than one creature can attack you each combat.
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigLimitBlock | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, each opponent can't block with more than one creature this combat. T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigLimitBlock | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, each opponent can't block with more than one creature this combat.
SVar:TrigLimitBlock:DB$ Effect | Name$ Mirri, Weatherlight Duelist Effect | StaticAbilities$ STLimitBlock | Duration$ UntilEndOfCombat SVar:TrigLimitBlock:DB$ Effect | StaticAbilities$ STLimitBlock | Duration$ UntilEndOfCombat
SVar:STLimitBlock:Mode$ Continuous | EffectZone$ Command | GlobalRule$ Each opponent can't block with more than one creature. | Description$ Each opponent can't block with more than one creature this combat. SVar:STLimitBlock:Mode$ Continuous | EffectZone$ Command | GlobalRule$ Each opponent can't block with more than one creature. | Description$ Each opponent can't block with more than one creature this combat.
Oracle:First strike\nWhenever Mirri, Weatherlight Duelist attacks, each opponent can't block with more than one creature this combat.\nAs long as Mirri, Weatherlight Duelist is tapped, no more than one creature can attack you each combat. Oracle:First strike\nWhenever Mirri, Weatherlight Duelist attacks, each opponent can't block with more than one creature this combat.\nAs long as Mirri, Weatherlight Duelist is tapped, no more than one creature can attack you each combat.

View File

@@ -2,6 +2,6 @@ Name:Silent Arbiter
ManaCost:4 ManaCost:4
Types:Artifact Creature Construct Types:Artifact Creature Construct
PT:1/5 PT:1/5
S:Mode$ Continuous | GlobalRule$ No more than one creature can attack each combat. | Description$ No more than one creature can attack each combat. S:Mode$ AttackRestrict | MaxAttackers$ 1 | Description$ No more than one creature can attack each combat.
S:Mode$ Continuous | GlobalRule$ No more than one creature can block each combat. | Description$ No more than one creature can block each combat. S:Mode$ Continuous | GlobalRule$ No more than one creature can block each combat. | Description$ No more than one creature can block each combat.
Oracle:No more than one creature can attack each combat.\nNo more than one creature can block each combat. Oracle:No more than one creature can attack each combat.\nNo more than one creature can block each combat.

View File

@@ -1,9 +1,9 @@
Name:Suppress Name:Suppress
ManaCost:2 B ManaCost:2 B
Types:Sorcery Types:Sorcery
A:SP$ ChangeZoneAll | Cost$ 2 B | ValidTgts$ Player | TgtPrompt$ Select target player | ChangeType$ Card | Origin$ Hand | Destination$ Exile | Hidden$ True | ExileFaceDown$ True | RememberTargets$ True | RememberChanged$ True | Reveal$ False | SubAbility$ DelTrig | SpellDescription$ Target player exiles all cards from their hand face down. At the beginning of the end step of that player's next turn, that player returns those cards to their hand. A:SP$ ChangeZoneAll | ValidTgts$ Player | ChangeType$ Card | Origin$ Hand | Destination$ Exile | Hidden$ True | ExileFaceDown$ True | RememberChanged$ True | Reveal$ False | SubAbility$ DelTrig | StackDescription$ {p:Targeted} exiles all cards from their hand face down. | SpellDescription$ Target player exiles all cards from their hand face down. At the beginning of the end step of that player's next turn, that player returns those cards to their hand.
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | ValidPlayer$ Player.IsRemembered | Execute$ TrigReturn | Secondary$ True | TriggerDescription$ Return exiled cards to targeted player's hand. SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | DelayedTriggerDefinedPlayer$ Targeted | ThisTurn$ True | RememberObjects$ Remembered | Execute$ TrigReturn | Secondary$ True | SubAbility$ DBCleanup | TriggerDescription$ At the beginning of the end step of that player's next turn, that player returns those cards to their hand. | StackDescription$ At the beginning of the end step of that player's next turn, that player returns those cards to their hand.
SVar:TrigReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Hand | SubAbility$ DBCleanup SVar:TrigReturn:DB$ ChangeZone | Defined$ DelayTriggerRememberedLKI | Origin$ Exile | Destination$ Hand
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
AI:RemoveDeck:All AI:RemoveDeck:All
Oracle:Target player exiles all cards from their hand face down. At the beginning of the end step of that player's next turn, that player returns those cards to their hand. Oracle:Target player exiles all cards from their hand face down. At the beginning of the end step of that player's next turn, that player returns those cards to their hand.

View File

@@ -2,7 +2,7 @@ Name:Teleportation Circle
ManaCost:3 W ManaCost:3 W
Types:Enchantment Types:Enchantment
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigExile | TriggerDescription$ At the beginning of your end step, exile up to one target artifact or creature you control, then return that card to the battlefield under its owner's control. T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigExile | TriggerDescription$ At the beginning of your end step, exile up to one target artifact or creature you control, then return that card to the battlefield under its owner's control.
SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | ValidTgts$ Artifact.YouCtrl,Creature.YouCtrl | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select target artifact or creature | SubAbility$ DBReturn SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | ValidTgts$ Artifact.YouCtrl,Creature.YouCtrl | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select up to one target artifact or creature you control | SubAbility$ DBReturn
SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ All | Destination$ Battlefield | SubAbility$ DBCleanup SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ All | Destination$ Battlefield | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
Oracle:At the beginning of your end step, exile up to one target artifact or creature you control, then return that card to the battlefield under its owner's control. Oracle:At the beginning of your end step, exile up to one target artifact or creature you control, then return that card to the battlefield under its owner's control.

View File

@@ -0,0 +1,17 @@
Name:The Eternal Wanderer
ManaCost:4 W W
Types:Legendary Planeswalker
Loyalty:5
S:Mode$ AttackRestrict | MaxAttackers$ 1 | ValidDefender$ Card.Self | Description$ No more than one creature can attack CARDNAME each combat.
A:AB$ ChangeZone | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Artifact,Creature | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select up to one target artifact or creature | RememberChanged$ True | SubAbility$ DBDelTrig | SpellDescription$ Exile up to one target artifact or creature. Return that card to the battlefield under its owner's control at the beginning of that player's next end step.
SVar:DBDelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | ValidPlayer$ Player.IsTriggerRemembered | Execute$ TrigReturn | RememberObjects$ TargetedOwner,RememberedLKI | SubAbility$ DBCleanup | TriggerDescription$ Return that card to the battlefield under its owner's control at the beginning of that player's next end step. | StackDescription$ Return that card to the battlefield under its owner's control at the beginning of that player's next end step.
SVar:TrigReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
A:AB$ Token | Cost$ AddCounter<0/LOYALTY> | Planeswalker$ True | TokenScript$ w_2_2_samurai_double_strike | SpellDescription$ Create a 2/2 white Samurai creature token with double strike.
A:AB$ RepeatEach | Cost$ SubCounter<4/LOYALTY> | Planeswalker$ True | RepeatPlayers$ Player | RepeatSubAbility$ DBChoose | SubAbility$ DBSacAll | StackDescription$ SpellDescription | SpellDescription$ For each player, choose a creature that player controls. Each player sacrifices all creatures they control not chosen this way.
SVar:DBChoose:DB$ ChooseCard | Defined$ You | Choices$ Creature.RememberedPlayerCtrl | Mandatory$ True | Amount$ 1 | ChoiceTitle$ Choose a creature this player controls | ImprintChosen$ True
SVar:DBSacAll:DB$ SacrificeAll | ValidCards$ Creature.IsNotImprinted | SubAbility$ DBCleanup2 | StackDescription$ None
SVar:DBCleanup2:DB$ Cleanup | ClearChosenCard$ True | ClearImprinted$ True
DeckHas:Ability$Token|Sacrifice & Type$Samurai
DeckHints:Keyword$Exalted
Oracle:No more than one creature can attack The Eternal Wanderer each combat.\n[+1]: Exile up to one target artifact or creature. Return that card to the battlefield under its owner's control at the beginning of that player's next end step.\n[0]: Create a 2/2 white Samurai creature token with double strike.\n[4]: For each player, choose a creature that player controls. Each player sacrifices all creatures they control not chosen this way.