mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
Teysa and Gitrog fixes
This commit is contained in:
@@ -11,6 +11,7 @@ import com.google.common.collect.Maps;
|
|||||||
import com.google.common.collect.Table;
|
import com.google.common.collect.Table;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
@@ -45,4 +46,39 @@ public class CardZoneTable extends ForwardingTable<ZoneType, ZoneType, CardColle
|
|||||||
game.getTriggerHandler().runTrigger(TriggerType.ChangesZoneAll, runParams, false);
|
game.getTriggerHandler().runTrigger(TriggerType.ChangesZoneAll, runParams, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CardCollection filterCards(Iterable<ZoneType> origin, ZoneType destination, String valid, Card host, SpellAbility sa) {
|
||||||
|
CardCollection allCards = new CardCollection();
|
||||||
|
if (destination != null) {
|
||||||
|
if (!containsColumn(destination)) {
|
||||||
|
return allCards;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (origin != null) {
|
||||||
|
for (ZoneType z : origin) {
|
||||||
|
if (containsRow(z)) {
|
||||||
|
if (destination != null) {
|
||||||
|
allCards.addAll(row(z).get(destination));
|
||||||
|
} else {
|
||||||
|
for (CardCollection c : row(z).values()) {
|
||||||
|
allCards.addAll(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (destination != null) {
|
||||||
|
for (CardCollection c : column(destination).values()) {
|
||||||
|
allCards.addAll(c);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (CardCollection c : values()) {
|
||||||
|
allCards.addAll(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid != null) {
|
||||||
|
allCards = CardLists.getValidCards(allCards, valid.split(","), host.getController(), host, sa);
|
||||||
|
}
|
||||||
|
return allCards;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,48 +42,19 @@ public class TriggerChangesZoneAll extends Trigger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CardCollection filterCards(CardZoneTable table) {
|
private CardCollection filterCards(CardZoneTable table) {
|
||||||
CardCollection allCards = new CardCollection();
|
|
||||||
ZoneType destination = null;
|
ZoneType destination = null;
|
||||||
|
List<ZoneType> origin = null;
|
||||||
|
|
||||||
if (hasParam("Destination")) {
|
if (hasParam("Destination") && !getParam("Destination").equals("Any")) {
|
||||||
if (!getParam("Destination").equals("Any")) {
|
destination = ZoneType.valueOf(getParam("Destination"));
|
||||||
destination = ZoneType.valueOf(getParam("Destination"));
|
|
||||||
if (!table.containsColumn(destination)) {
|
|
||||||
return allCards;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasParam("Origin") && !getParam("Origin").equals("Any")) {
|
if (hasParam("Origin") && !getParam("Origin").equals("Any")) {
|
||||||
if (getParam("Origin") == null) {
|
origin = ZoneType.listValueOf(getParam("Origin"));
|
||||||
return allCards;
|
|
||||||
}
|
|
||||||
final List<ZoneType> origin = ZoneType.listValueOf(getParam("Origin"));
|
|
||||||
for (ZoneType z : origin) {
|
|
||||||
if (table.containsRow(z)) {
|
|
||||||
if (destination != null) {
|
|
||||||
allCards.addAll(table.row(z).get(destination));
|
|
||||||
} else {
|
|
||||||
for (CardCollection c : table.row(z).values()) {
|
|
||||||
allCards.addAll(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (destination != null) {
|
|
||||||
for (CardCollection c : table.column(destination).values()) {
|
|
||||||
allCards.addAll(c);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (CardCollection c : table.values()) {
|
|
||||||
allCards.addAll(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasParam("ValidCards")) {
|
final String valid = this.getParamOrDefault("ValidCards", null);
|
||||||
allCards = CardLists.getValidCards(allCards, getParam("ValidCards").split(","),
|
|
||||||
getHostCard().getController(), getHostCard(), null);
|
return table.filterCards(origin, destination, valid, getHostCard(), null);
|
||||||
}
|
|
||||||
return allCards;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import forge.game.ability.effects.CharmEffect;
|
|||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardUtil;
|
import forge.game.card.CardUtil;
|
||||||
|
import forge.game.card.CardZoneTable;
|
||||||
import forge.game.keyword.KeywordInterface;
|
import forge.game.keyword.KeywordInterface;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -44,6 +45,7 @@ import io.sentry.event.BreadcrumbBuilder;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ListMultimap;
|
import com.google.common.collect.ListMultimap;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
@@ -693,13 +695,14 @@ public class TriggerHandler {
|
|||||||
private int handlePanharmonicon(final Trigger t, final Map<String, Object> runParams, final Player p) {
|
private int handlePanharmonicon(final Trigger t, final Map<String, Object> runParams, final Player p) {
|
||||||
Card host = t.getHostCard();
|
Card host = t.getHostCard();
|
||||||
|
|
||||||
// not a changesZone trigger
|
// not a changesZone trigger or changesZoneAll
|
||||||
if (t.getMode() != TriggerType.ChangesZone) {
|
if (t.getMode() != TriggerType.ChangesZone && t.getMode() != TriggerType.ChangesZoneAll) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// leave battlefield trigger, might be dying
|
// leave battlefield trigger, might be dying
|
||||||
if ("Battlefield".equals(t.getParam("Origin"))) {
|
// only real changeszone look back for this
|
||||||
|
if (t.getMode() == TriggerType.ChangesZone && "Battlefield".equals(t.getParam("Origin"))) {
|
||||||
// Need to get the last info from the trigger host
|
// Need to get the last info from the trigger host
|
||||||
host = game.getChangeZoneLKIInfo(host);
|
host = game.getChangeZoneLKIInfo(host);
|
||||||
}
|
}
|
||||||
@@ -710,30 +713,17 @@ public class TriggerHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
// iterate over all cards
|
if (t.getMode() == TriggerType.ChangesZone) {
|
||||||
final List<Card> lastCards = CardLists.filterControlledBy(p.getGame().getLastStateBattlefield(), p);
|
// iterate over all cards
|
||||||
for (final Card ck : lastCards) {
|
final List<Card> lastCards = CardLists.filterControlledBy(p.getGame().getLastStateBattlefield(), p);
|
||||||
for (final KeywordInterface ki : ck.getKeywords()) {
|
for (final Card ck : lastCards) {
|
||||||
final String kw = ki.getOriginal();
|
for (final KeywordInterface ki : ck.getKeywords()) {
|
||||||
if (kw.startsWith("Panharmonicon")) {
|
final String kw = ki.getOriginal();
|
||||||
// Enter the Battlefield Trigger
|
if (kw.startsWith("Panharmonicon")) {
|
||||||
if (runParams.get("Destination") instanceof String) {
|
// Enter the Battlefield Trigger
|
||||||
final String dest = (String) runParams.get("Destination");
|
if (runParams.get("Destination") instanceof String) {
|
||||||
if ("Battlefield".equals(dest) && runParams.get("Card") instanceof Card) {
|
|
||||||
final Card card = (Card) runParams.get("Card");
|
|
||||||
final String valid = kw.split(":")[1];
|
|
||||||
if (card.isValid(valid.split(","), p, ck, null)) {
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (kw.startsWith("Dieharmonicon")) {
|
|
||||||
// 700.4. The term dies means “is put into a graveyard from the battlefield.”
|
|
||||||
if (runParams.get("Origin") instanceof String) {
|
|
||||||
final String origin = (String) runParams.get("Origin");
|
|
||||||
if ("Battlefield".equals(origin) && runParams.get("Destination") instanceof String) {
|
|
||||||
final String dest = (String) runParams.get("Destination");
|
final String dest = (String) runParams.get("Destination");
|
||||||
if ("Graveyard".equals(dest) && runParams.get("Card") instanceof Card) {
|
if ("Battlefield".equals(dest) && runParams.get("Card") instanceof Card) {
|
||||||
final Card card = (Card) runParams.get("Card");
|
final Card card = (Card) runParams.get("Card");
|
||||||
final String valid = kw.split(":")[1];
|
final String valid = kw.split(":")[1];
|
||||||
if (card.isValid(valid.split(","), p, ck, null)) {
|
if (card.isValid(valid.split(","), p, ck, null)) {
|
||||||
@@ -741,6 +731,43 @@ public class TriggerHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (kw.startsWith("Dieharmonicon")) {
|
||||||
|
// 700.4. The term dies means “is put into a graveyard from the battlefield.”
|
||||||
|
if (runParams.get("Origin") instanceof String) {
|
||||||
|
final String origin = (String) runParams.get("Origin");
|
||||||
|
if ("Battlefield".equals(origin) && runParams.get("Destination") instanceof String) {
|
||||||
|
final String dest = (String) runParams.get("Destination");
|
||||||
|
if ("Graveyard".equals(dest) && runParams.get("Card") instanceof Card) {
|
||||||
|
final Card card = (Card) runParams.get("Card");
|
||||||
|
final String valid = kw.split(":")[1];
|
||||||
|
if (card.isValid(valid.split(","), p, ck, null)) {
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (t.getMode() == TriggerType.ChangesZoneAll) {
|
||||||
|
final CardZoneTable table = (CardZoneTable) runParams.get("Cards");
|
||||||
|
// iterate over all cards
|
||||||
|
for (final Card ck : p.getCardsIn(ZoneType.Battlefield)) {
|
||||||
|
for (final KeywordInterface ki : ck.getKeywords()) {
|
||||||
|
final String kw = ki.getOriginal();
|
||||||
|
if (kw.startsWith("Panharmonicon")) {
|
||||||
|
// currently there is no ChangesZoneAll that would trigger on etb
|
||||||
|
final String valid = kw.split(":")[1];
|
||||||
|
if (!table.filterCards(null, ZoneType.Battlefield, valid, ck, null).isEmpty()) {
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
} else if (kw.startsWith("Dieharmonicon")) {
|
||||||
|
// 700.4. The term dies means “is put into a graveyard from the battlefield.”
|
||||||
|
final String valid = kw.split(":")[1];
|
||||||
|
if (!table.filterCards(ImmutableList.of(ZoneType.Battlefield), ZoneType.Graveyard,
|
||||||
|
valid, ck, null).isEmpty()) {
|
||||||
|
n++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1589,4 +1589,111 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
int numZombies = countCardsWithName(simGame, "Zombie");
|
int numZombies = countCardsWithName(simGame, "Zombie");
|
||||||
assertTrue(numZombies == 3);
|
assertTrue(numZombies == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testTeysaKarlovGitrogMonster() {
|
||||||
|
|
||||||
|
Game game = initAndCreateGame();
|
||||||
|
Player p = game.getPlayers().get(0);
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||||
|
|
||||||
|
addCard("Teysa Karlov", p);
|
||||||
|
addCard("The Gitrog Monster", p);
|
||||||
|
addCard("Dryad Arbor", p);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
addCard("Plains", p);
|
||||||
|
addCardToZone("Plains", p, ZoneType.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
Card armageddon = addCardToZone("Armageddon", p, ZoneType.Hand);
|
||||||
|
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||||
|
|
||||||
|
SpellAbility armageddonSA = armageddon.getFirstSpellAbility();
|
||||||
|
|
||||||
|
GameSimulator sim = createSimulator(game, p);
|
||||||
|
int score = sim.simulateSpellAbility(armageddonSA).value;
|
||||||
|
assertTrue(score > 0);
|
||||||
|
Game simGame = sim.getSimulatedGameState();
|
||||||
|
|
||||||
|
// Two cards drawn
|
||||||
|
assertTrue(simGame.getPlayers().get(0).getZone(ZoneType.Hand).size() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTeysaKarlovGitrogMonsterGitrogDies() {
|
||||||
|
|
||||||
|
Game game = initAndCreateGame();
|
||||||
|
Player p = game.getPlayers().get(0);
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||||
|
|
||||||
|
Card teysa = addCard("Teysa Karlov", p);
|
||||||
|
addCard("The Gitrog Monster", p);
|
||||||
|
addCard("Dryad Arbor", p);
|
||||||
|
|
||||||
|
String indestructibilityName = "Indestructibility";
|
||||||
|
Card indestructibility = addCard(indestructibilityName, p);
|
||||||
|
|
||||||
|
indestructibility.attachToEntity(teysa);
|
||||||
|
|
||||||
|
// update Indestructible state
|
||||||
|
game.getAction().checkStateEffects(true);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
addCard("Plains", p);
|
||||||
|
addCardToZone("Plains", p, ZoneType.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
Card armageddon = addCardToZone("Wrath of God", p, ZoneType.Hand);
|
||||||
|
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||||
|
|
||||||
|
SpellAbility armageddonSA = armageddon.getFirstSpellAbility();
|
||||||
|
|
||||||
|
GameSimulator sim = createSimulator(game, p);
|
||||||
|
int score = sim.simulateSpellAbility(armageddonSA).value;
|
||||||
|
assertTrue(score > 0);
|
||||||
|
Game simGame = sim.getSimulatedGameState();
|
||||||
|
|
||||||
|
// One cards drawn
|
||||||
|
assertTrue(simGame.getPlayers().get(0).getZone(ZoneType.Hand).size() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTeysaKarlovGitrogMonsterTeysaDies() {
|
||||||
|
|
||||||
|
Game game = initAndCreateGame();
|
||||||
|
Player p = game.getPlayers().get(0);
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||||
|
|
||||||
|
addCard("Teysa Karlov", p);
|
||||||
|
Card gitrog = addCard("The Gitrog Monster", p);
|
||||||
|
addCard("Dryad Arbor", p);
|
||||||
|
|
||||||
|
String indestructibilityName = "Indestructibility";
|
||||||
|
Card indestructibility = addCard(indestructibilityName, p);
|
||||||
|
|
||||||
|
indestructibility.attachToEntity(gitrog);
|
||||||
|
|
||||||
|
// update Indestructible state
|
||||||
|
game.getAction().checkStateEffects(true);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
addCard("Plains", p);
|
||||||
|
addCardToZone("Plains", p, ZoneType.Library);
|
||||||
|
}
|
||||||
|
|
||||||
|
Card armageddon = addCardToZone("Wrath of God", p, ZoneType.Hand);
|
||||||
|
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||||
|
|
||||||
|
SpellAbility armageddonSA = armageddon.getFirstSpellAbility();
|
||||||
|
|
||||||
|
GameSimulator sim = createSimulator(game, p);
|
||||||
|
int score = sim.simulateSpellAbility(armageddonSA).value;
|
||||||
|
assertTrue(score > 0);
|
||||||
|
Game simGame = sim.getSimulatedGameState();
|
||||||
|
|
||||||
|
// One cards drawn
|
||||||
|
assertTrue(simGame.getPlayers().get(0).getZone(ZoneType.Hand).size() == 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user