From 72d623784a654ca43474ec44f4803dc99395c5eb Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 14 May 2019 08:38:24 +0300 Subject: [PATCH 1/3] - Added Ashiok, Dream Render. --- .../game/ability/effects/ChangeZoneAllEffect.java | 5 +++++ .../forge/game/ability/effects/ChangeZoneEffect.java | 2 +- .../src/main/java/forge/game/player/Player.java | 12 ++++++++++++ forge-gui/res/cardsfolder/a/ashiok_dream_render.txt | 8 ++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 forge-gui/res/cardsfolder/a/ashiok_dream_render.txt diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java index ab5e1eea5eb..69f1e42d6a1 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java @@ -48,6 +48,11 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect { cards = new CardCollection(); for (final Player p : tgtPlayers) { cards.addAll(p.getCardsIn(origin)); + + if (origin.contains(ZoneType.Library) && sa.hasParam("Search") && !sa.getActivatingPlayer().canSearchOwnLibraryWith(sa, p)) { + cards.removeAll(p.getCardsIn(ZoneType.Library)); + } + } if (origin.contains(ZoneType.Library) && sa.hasParam("Search")) { // Search library using changezoneall effect need a param "Search" diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index fdcab6ed8dd..050a005589f 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -767,7 +767,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { fetchList.addAll(player.getCardsIn(ZoneType.Library, fetchNum)); } } - if (decider.hasKeyword("CantSearchLibrary")) { + if (decider.hasKeyword("CantSearchLibrary") || !decider.canSearchOwnLibraryWith(sa, player)) { fetchList.removeAll(player.getCardsIn(ZoneType.Library)); // "if you do/sb does, shuffle" is not mandatory (usually a triggered ability), should has this param. // "then shuffle" is mandatory 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 79670788306..cf9d8a4e36c 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -2965,4 +2965,16 @@ public class Player extends GameEntity implements Comparable { return true; } + + public boolean canSearchOwnLibraryWith(SpellAbility sa, Player targetPlayer) { + if (sa == null) { + return true; + } + + if (targetPlayer.equals(sa.getActivatingPlayer()) && hasKeyword("Spells and abilities you control can't cause you to search your library.")) { + return false; + } + + return true; + } } diff --git a/forge-gui/res/cardsfolder/a/ashiok_dream_render.txt b/forge-gui/res/cardsfolder/a/ashiok_dream_render.txt new file mode 100644 index 00000000000..34ef0b5e471 --- /dev/null +++ b/forge-gui/res/cardsfolder/a/ashiok_dream_render.txt @@ -0,0 +1,8 @@ +Name:Ashiok, Dream Render +ManaCost:1 UB UB +Types:Legendary Planeswalker Ashiok +Loyalty:5 +S:Mode$ Continuous | Affected$ Opponent | AddKeyword$ Spells and abilities you control can't cause you to search your library. | Description$ Spells and abilities your opponents control can't cause their controller to search their library. +A:AB$ Mill | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | NumCards$ 4 | ValidTgts$ Player | TgtPrompt$ Choose a player | SubAbility$ DBExileGrave | SpellDescription$ Target player puts the top four cards of their library into their graveyard. Then exile each opponent's graveyard. +SVar:DBExileGrave:DB$ ChangeZoneAll | Origin$ Graveyard | Destination$ Exile | Defined$ Opponent | ChangeType$ Card +Oracle:Spells and abilities your opponents control can't cause their controller to search their library.\n[-1]: Target player puts the top four cards of their library into their graveyard. Then exile each opponent's graveyard. From 3913f7661f3759382aa9af25e50a3ed3840c2640 Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 14 May 2019 12:13:10 +0300 Subject: [PATCH 2/3] - Some AI support for CantSearchLibrary / Ashiok effect. --- forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java | 5 +++++ .../src/main/java/forge/ai/ability/ChangeZoneAllAi.java | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java index e5c52128bef..afb10ff753f 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java @@ -316,6 +316,11 @@ public class ChangeZoneAi extends SpellAbilityAi { for (final Player p : pDefined) { CardCollectionView list = p.getCardsIn(origin); + // remove cards that won't be seen if library can't be searched + if (ai.hasKeyword("CantSearchLibrary") || (ai.hasKeyword("Spells and abilities you control can't cause you to search your library.") && !ai.canSearchOwnLibraryWith(sa, p))) { + list = CardLists.filter(list, Predicates.not(CardPredicates.inZone(ZoneType.Library))); + } + if (type != null && p == ai) { // AI only "knows" about his information list = CardLists.getValidCards(list, type, source.getController(), source); diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java index 87f87ccf8a8..e7ae4d9ed99 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java @@ -1,5 +1,6 @@ package forge.ai.ability; +import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import forge.ai.*; @@ -57,6 +58,11 @@ public class ChangeZoneAllAi extends SpellAbilityAi { CardCollectionView oppType = CardLists.filterControlledBy(game.getCardsIn(origin), ai.getOpponents()); CardCollectionView computerType = ai.getCardsIn(origin); + // remove cards that won't be seen in AI's own library if it can't be searched + if (ai.hasKeyword("CantSearchLibrary") || (ai.hasKeyword("Spells and abilities you control can't cause you to search your library.") && !ai.canSearchOwnLibraryWith(sa, ai))) { + computerType = CardLists.filter(computerType, Predicates.not(CardPredicates.inZone(ZoneType.Library))); + } + // Ugin check need to be done before filterListByType because of ChosenX // Ugin AI: always try to sweep before considering +1 if (sourceName.equals("Ugin, the Spirit Dragon")) { From 31d9a1e6b3e8fe3db02379d667935eac8900c783 Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 14 May 2019 16:33:09 +0300 Subject: [PATCH 3/3] - Attempting to consolidate the implementation for "can't search library". --- forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java | 2 +- .../src/main/java/forge/ai/ability/ChangeZoneAllAi.java | 2 +- .../forge/game/ability/effects/ChangeZoneAllEffect.java | 6 +++--- .../java/forge/game/ability/effects/ChangeZoneEffect.java | 2 +- forge-game/src/main/java/forge/game/player/Player.java | 7 +++++-- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java index afb10ff753f..69d55bb9281 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java @@ -317,7 +317,7 @@ public class ChangeZoneAi extends SpellAbilityAi { CardCollectionView list = p.getCardsIn(origin); // remove cards that won't be seen if library can't be searched - if (ai.hasKeyword("CantSearchLibrary") || (ai.hasKeyword("Spells and abilities you control can't cause you to search your library.") && !ai.canSearchOwnLibraryWith(sa, p))) { + if (!ai.canSearchLibraryWith(sa, p)) { list = CardLists.filter(list, Predicates.not(CardPredicates.inZone(ZoneType.Library))); } diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java index e7ae4d9ed99..c17506d37b2 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java @@ -59,7 +59,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi { CardCollectionView computerType = ai.getCardsIn(origin); // remove cards that won't be seen in AI's own library if it can't be searched - if (ai.hasKeyword("CantSearchLibrary") || (ai.hasKeyword("Spells and abilities you control can't cause you to search your library.") && !ai.canSearchOwnLibraryWith(sa, ai))) { + if (!ai.canSearchLibraryWith(sa, ai)) { computerType = CardLists.filter(computerType, Predicates.not(CardPredicates.inZone(ZoneType.Library))); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java index 69f1e42d6a1..72ae0a53850 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java @@ -49,7 +49,7 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect { for (final Player p : tgtPlayers) { cards.addAll(p.getCardsIn(origin)); - if (origin.contains(ZoneType.Library) && sa.hasParam("Search") && !sa.getActivatingPlayer().canSearchOwnLibraryWith(sa, p)) { + if (origin.contains(ZoneType.Library) && sa.hasParam("Search") && !sa.getActivatingPlayer().canSearchLibraryWith(sa, p)) { cards.removeAll(p.getCardsIn(ZoneType.Library)); } @@ -63,14 +63,14 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect { cards.addAll(p.getCardsIn(ZoneType.Library, fetchNum)); } } - if (sa.getActivatingPlayer().hasKeyword("CantSearchLibrary")) { + if (!sa.getActivatingPlayer().canSearchLibraryWith(sa, null)) { // all these cards have "then that player shuffles", mandatory shuffle cards.removeAll(game.getCardsIn(ZoneType.Library)); } } } - if (origin.contains(ZoneType.Library) && sa.hasParam("Search") && !sa.getActivatingPlayer().hasKeyword("CantSearchLibrary")) { + if (origin.contains(ZoneType.Library) && sa.hasParam("Search") && sa.getActivatingPlayer().canSearchLibraryWith(sa, null)) { CardCollection libCards = CardLists.getValidCards(cards, "Card.inZoneLibrary", sa.getActivatingPlayer(), source); CardCollection libCardsYouOwn = CardLists.filterControlledBy(libCards, sa.getActivatingPlayer()); if (!libCardsYouOwn.isEmpty()) { // Only searching one's own library would fire Archive Trap's altcost diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index 050a005589f..04b2e5b66da 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -767,7 +767,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { fetchList.addAll(player.getCardsIn(ZoneType.Library, fetchNum)); } } - if (decider.hasKeyword("CantSearchLibrary") || !decider.canSearchOwnLibraryWith(sa, player)) { + if (!decider.canSearchLibraryWith(sa, player)) { fetchList.removeAll(player.getCardsIn(ZoneType.Library)); // "if you do/sb does, shuffle" is not mandatory (usually a triggered ability), should has this param. // "then shuffle" is mandatory 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 cf9d8a4e36c..9a8fe794d1e 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -2966,12 +2966,15 @@ public class Player extends GameEntity implements Comparable { return true; } - public boolean canSearchOwnLibraryWith(SpellAbility sa, Player targetPlayer) { + public boolean canSearchLibraryWith(SpellAbility sa, Player targetPlayer) { if (sa == null) { return true; } - if (targetPlayer.equals(sa.getActivatingPlayer()) && hasKeyword("Spells and abilities you control can't cause you to search your library.")) { + if (this.hasKeyword("CantSearchLibrary")) { + return false; + } else if (targetPlayer != null && targetPlayer.equals(sa.getActivatingPlayer()) + && hasKeyword("Spells and abilities you control can't cause you to search your library.")) { return false; }