From 46e667ba6fb8a67f69667dd9d445dd6136e1f8e8 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sun, 27 Sep 2020 11:53:50 +0200 Subject: [PATCH] Game: store counters put on cards this turn --- forge-game/src/main/java/forge/game/Game.java | 49 +++++++++++++++++++ .../java/forge/game/ability/AbilityUtils.java | 9 ++++ .../src/main/java/forge/game/card/Card.java | 5 +- .../java/forge/game/card/CardFactoryUtil.java | 8 --- .../java/forge/game/phase/PhaseHandler.java | 4 +- .../main/java/forge/game/player/Player.java | 17 ------- .../cardsfolder/f/fairgrounds_trumpeter.txt | 4 +- .../cardsfolder/i/iridescent_hornbeetle.txt | 11 +++++ 8 files changed, 75 insertions(+), 32 deletions(-) create mode 100644 forge-gui/res/cardsfolder/i/iridescent_hornbeetle.txt diff --git a/forge-game/src/main/java/forge/game/Game.java b/forge-game/src/main/java/forge/game/Game.java index 47997c1b8bc..ec4f8aa927d 100644 --- a/forge-game/src/main/java/forge/game/Game.java +++ b/forge-game/src/main/java/forge/game/Game.java @@ -20,9 +20,12 @@ package forge.game; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.HashBasedTable; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; +import com.google.common.collect.Table; import com.google.common.eventbus.EventBus; import forge.card.CardRarity; import forge.card.CardStateName; @@ -53,6 +56,8 @@ import forge.util.Visitor; import java.util.*; +import org.apache.commons.lang3.tuple.Pair; + /** * Represents the state of a single game, a new instance is created for each game. */ @@ -86,6 +91,8 @@ public class Game { private Map attackedThisTurn = Maps.newHashMap(); private Map attackedLastTurn = Maps.newHashMap(); + private Table>> countersAddedThisTurn = HashBasedTable.create(); + private Player monarch = null; private Player monarchBeginTurn = null; @@ -939,4 +946,46 @@ public class Game { } return result; } + + public void onCleanupPhase() { + clearCounterAddedThisTurn(); + for (Player player : getPlayers()) { + player.onCleanupPhase(); + } + } + + public void addCounterAddedThisTurn(Player putter, CounterType cType, Card card, Integer value) { + if (putter == null || card == null || value <= 0) { + return; + } + List> result = countersAddedThisTurn.get(cType, putter); + if (result == null) { + result = Lists.newArrayList(); + } + result.add(Pair.of(CardUtil.getLKICopy(card), value)); + if (!countersAddedThisTurn.contains(cType, putter)) { + countersAddedThisTurn.put(cType, putter, result); + } + } + + public int getCounterAddedThisTurn(CounterType cType, String validPlayer, String validCard, Card source, Player sourceController, SpellAbility spellAbility) { + int result = 0; + if (!countersAddedThisTurn.containsRow(cType)) { + return result; + } + for (Map.Entry>> e : countersAddedThisTurn.row(cType).entrySet()) { + if (e.getKey().isValid(validPlayer.split(","), sourceController, source, spellAbility)) { + for (Pair p : e.getValue()) { + if (p.getKey().isValid(validCard.split(","), sourceController, source, spellAbility)) { + result += p.getValue(); + } + } + } + } + return result; + } + + public void clearCounterAddedThisTurn() { + countersAddedThisTurn.clear(); + } } diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 939d23a9e35..3cba6e96b75 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -1593,6 +1593,8 @@ public class AbilityUtils { final String[] sq; sq = l[0].split("\\."); + final Game game = c.getGame(); + if (ctb != null) { // Count$Compare .. if (sq[0].startsWith("Compare")) { @@ -1776,6 +1778,13 @@ public class AbilityUtils { } } } + + if (l[0].startsWith("CountersAddedThisTurn")) { + final String[] parts = l[0].split(" "); + CounterType cType = CounterType.getType(parts[1]); + + return CardFactoryUtil.doXMath(game.getCounterAddedThisTurn(cType, parts[2], parts[3], c, sa.getActivatingPlayer(), sa), expr, c); + } } } return CardFactoryUtil.xCount(c, s2); diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index d26f2fc876f..53513d27e4d 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1239,7 +1239,7 @@ public class Card extends GameEntity implements Comparable { final int loyaltyBefore = getCurrentLoyalty(); setCounters(counterType, newValue); - getController().addCounterToPermThisTurn(counterType, addAmount); + getGame().addCounterAddedThisTurn(source, counterType, this, addAmount); view.updateCounters(this); //fire card stats changed event if p/t bonuses or loyalty changed from added counters @@ -1267,7 +1267,8 @@ public class Card extends GameEntity implements Comparable { } } else { setCounters(counterType, newValue); - getController().addCounterToPermThisTurn(counterType, addAmount); + + getGame().addCounterAddedThisTurn(source, counterType, this, addAmount); view.updateCounters(this); } if (newValue <= 0) { diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index d1f5edd6eef..02ceebfc0d1 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -841,14 +841,6 @@ public class CardFactoryUtil { return doXMath(maxNum, m, c); } - // Count$CountersAddedToPermYouCtrl - if (l[0].startsWith("CountersAddedToPermYouCtrl")) { - final String[] components = l[0].split(" ", 2); - final CounterType counterType = CounterType.getType(components[1]); - int n = cc.getCounterToPermThisTurn(counterType); - return doXMath(n, m, c); - } - if (l[0].startsWith("CommanderCastFromCommandZone")) { // only used by Opal Palace, and it does add the trigger to the card return doXMath(cc.getCommanderCast(c), m, c); diff --git a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java index 85d5c500d95..42a01547121 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java @@ -501,9 +501,7 @@ public class PhaseHandler implements java.io.Serializable { bPreventCombatDamageThisTurn = false; if (!bRepeatCleanup) { // only call onCleanupPhase when Cleanup is not repeated - for (Player player : game.getPlayers()) { - player.onCleanupPhase(); - } + game.onCleanupPhase(); setPlayerTurn(handleNextTurn()); // "Trigger" for begin turn to get around a phase skipping final Map runParams = AbilityKey.newMap(); diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 3637fc98ca2..322c564b284 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -114,8 +114,6 @@ public class Player extends GameEntity implements Comparable { private CardCollection sacrificedThisTurn = new CardCollection(); - private Map countersAddedtoPermThisTurn = Maps.newHashMap(); - /** A list of tokens not in play, but on their way. * This list is kept in order to not break ETB-replacement * on tokens. */ @@ -2289,20 +2287,6 @@ public class Player extends GameEntity implements Comparable { sacrificedThisTurn.clear(); } - public final void addCounterToPermThisTurn(final CounterType type, final int x) { - countersAddedtoPermThisTurn.put(type, getCounterToPermThisTurn(type) + x); - } - - public final Integer getCounterToPermThisTurn(final CounterType type) { - if (countersAddedtoPermThisTurn.containsKey(type)) - return countersAddedtoPermThisTurn.get(type); - return 0; - } - - public final void resetCounterToPermThisTurn() { - countersAddedtoPermThisTurn.clear(); - } - public final int getSpellsCastThisTurn() { return spellsCastThisTurn; } @@ -2521,7 +2505,6 @@ public class Player extends GameEntity implements Comparable { resetSurveilThisTurn(); resetCycledThisTurn(); resetSacrificedThisTurn(); - resetCounterToPermThisTurn(); clearAssignedDamage(); resetAttackersDeclaredThisTurn(); resetAttackedOpponentsThisTurn(); diff --git a/forge-gui/res/cardsfolder/f/fairgrounds_trumpeter.txt b/forge-gui/res/cardsfolder/f/fairgrounds_trumpeter.txt index b555b2fd221..d2c27378cd3 100644 --- a/forge-gui/res/cardsfolder/f/fairgrounds_trumpeter.txt +++ b/forge-gui/res/cardsfolder/f/fairgrounds_trumpeter.txt @@ -5,6 +5,6 @@ PT:2/2 T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | CheckSVar$ X | Execute$ TrigPutCounter | TriggerDescription$ At the beginning of each end step, if a +1/+1 counter was put on a permanent under your control this turn, put a +1/+1 counter on CARDNAME. SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 DeckHints:Ability$Counters -SVar:X:Count$CountersAddedToPermYouCtrl P1P1 -SVar:Picture:http://www.wizards.com/global/images/magic/general/fairgrounds_trumpeter.jpg +DeckHas:Ability$Counters +SVar:X:Count$CountersAddedThisTurn P1P1 Player Permanent.YouCtrl Oracle:At the beginning of each end step, if a +1/+1 counter was put on a permanent under your control this turn, put a +1/+1 counter on Fairgrounds Trumpeter. diff --git a/forge-gui/res/cardsfolder/i/iridescent_hornbeetle.txt b/forge-gui/res/cardsfolder/i/iridescent_hornbeetle.txt new file mode 100644 index 00000000000..9f93bfe7635 --- /dev/null +++ b/forge-gui/res/cardsfolder/i/iridescent_hornbeetle.txt @@ -0,0 +1,11 @@ +Name:Iridescent Hornbeetle +ManaCost:4 G +Types:Creature Insect +PT:3/4 +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ At the beginning of your end step, create a 1/1 green Insect creature token for each +1/+1 counter you've put on creatures under your control this turn. +SVar:TrigToken:DB$ Token | TokenAmount$ X | References$ X | TokenOwner$ You | TokenScript$ g_1_1_insect +SVar:X:Count$CountersAddedThisTurn P1P1 You Creature.YouCtrl +DeckNeeds:Ability$Counters +DeckHas:Ability$Counters +Oracle:At the beginning of your end step, create a 1/1 green Insect creature token for each +1/+1 counter you've put on creatures under your control this turn. +