From bec4c4cb5354dd07233e1ac062b2e4d1ba1cd0d3 Mon Sep 17 00:00:00 2001 From: Michael Kamensky Date: Fri, 20 Jan 2023 10:01:55 +0300 Subject: [PATCH 1/4] - Added puzzles PS_BRO1 - PS_BRO3. - Added a way to add tokens by script from GameState. - Fixed u_2_2_spirit_vigilance_drawcounter token name capitalization. --- .../src/main/java/forge/ai/GameState.java | 40 +++++++++++-------- forge-gui/res/puzzle/PS_BRO1.pzl | 18 +++++++++ forge-gui/res/puzzle/PS_BRO2.pzl | 16 ++++++++ forge-gui/res/puzzle/PS_BRO3.pzl | 17 ++++++++ .../u_2_2_spirit_vigilance_drawcounter.txt | 2 +- 5 files changed, 76 insertions(+), 17 deletions(-) create mode 100644 forge-gui/res/puzzle/PS_BRO1.pzl create mode 100644 forge-gui/res/puzzle/PS_BRO2.pzl create mode 100644 forge-gui/res/puzzle/PS_BRO3.pzl diff --git a/forge-ai/src/main/java/forge/ai/GameState.java b/forge-ai/src/main/java/forge/ai/GameState.java index 7ad1fd3632a..56dc02ed8c7 100644 --- a/forge-ai/src/main/java/forge/ai/GameState.java +++ b/forge-ai/src/main/java/forge/ai/GameState.java @@ -1,16 +1,11 @@ package forge.ai; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.*; -import java.util.Map.Entry; - -import com.google.common.collect.*; -import java.util.stream.Stream; -import org.apache.commons.lang3.StringUtils; - +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import forge.StaticData; +import forge.card.CardEdition; import forge.card.CardStateName; import forge.card.MagicColor; import forge.card.mana.ManaAtom; @@ -18,12 +13,7 @@ import forge.game.Game; import forge.game.GameEntity; import forge.game.ability.AbilityFactory; import forge.game.ability.effects.DetachedCardEffect; -import forge.game.card.Card; -import forge.game.card.CardCloneStates; -import forge.game.card.CardCollection; -import forge.game.card.CardCollectionView; -import forge.game.card.CardFactory; -import forge.game.card.CounterType; +import forge.game.card.*; import forge.game.card.token.TokenInfo; import forge.game.combat.Combat; import forge.game.combat.CombatUtil; @@ -38,8 +28,17 @@ import forge.game.zone.PlayerZone; import forge.game.zone.ZoneType; import forge.item.IPaperCard; import forge.item.PaperCard; +import forge.item.PaperToken; import forge.util.TextUtil; import forge.util.collect.FCollectionView; +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.*; +import java.util.Map.Entry; +import java.util.stream.Stream; public abstract class GameState { private static final Map ZONES = new HashMap<>(); @@ -1201,6 +1200,15 @@ public abstract class GameState { // TODO Make sure Game State conversion works with new tokens String tokenStr = cardinfo[0].substring(2); c = new TokenInfo(tokenStr).makeOneToken(player); + } else if (cardinfo[0].startsWith("T:")) { + String tokenStr = cardinfo[0].substring(2); + PaperToken token = StaticData.instance().getAllTokens().getToken(tokenStr, + setCode != null ? setCode : CardEdition.UNKNOWN.getName()); + if (token == null) { + System.err.println("ERROR: Tried to create a non-existent token named " + cardinfo[0] + " when loading game state!"); + continue; + } + c = Card.fromPaperCard(token, player, player.getGame()); } else { PaperCard pc = StaticData.instance().getCommonCards().getCard(cardinfo[0], setCode); if (pc == null) { diff --git a/forge-gui/res/puzzle/PS_BRO1.pzl b/forge-gui/res/puzzle/PS_BRO1.pzl new file mode 100644 index 00000000000..95ecd4612ca --- /dev/null +++ b/forge-gui/res/puzzle/PS_BRO1.pzl @@ -0,0 +1,18 @@ +[metadata] +Name:Possibility Storm - The Brothers' War #01 +URL:https://www.patreon.com/mtgpuzzles +Goal:Win +Turns:1 +Difficulty:Mythic +Description:Win this turn. Start in your upkeep while resolving The Temporal Anchor's Scry 2 trigger. Assume that, in your library, you have additional copies of each card under your control and in your hand. Both graveyards start empty. Remember that your solution must satisfy all possible blocking decisions. +[state] +turn=1 +activeplayer=p1 +activephase=CLEANUP +activephaseadvance=UPKEEP +p0life=20 +p0hand=Defenestrate;Carrion Locust;Dreadhound +p0library=Haywire Mite;Bushwhack;Defenestrate;Forest;Swamp;Island;The Temporal Anchor;Rona, Sheoldred's Faithful;Hoarding Recluse;Fauna Shaman;Island;Swamp;Forest;Carrion Locust;Dreadhound +p0battlefield=The Temporal Anchor;Rona, Sheoldred's Faithful;Hoarding Recluse;Fauna Shaman;Island;Island;Swamp;Swamp;Forest;Forest +p1life=3 +p1battlefield=The Stasis Coffin;Glittering Stockpile|Counters:STASH=3;Patchwork Crawler;Patchwork Crawler;Cradle Clearcutter diff --git a/forge-gui/res/puzzle/PS_BRO2.pzl b/forge-gui/res/puzzle/PS_BRO2.pzl new file mode 100644 index 00000000000..fc54e74508c --- /dev/null +++ b/forge-gui/res/puzzle/PS_BRO2.pzl @@ -0,0 +1,16 @@ +[metadata] +Name:Possibility Storm - The Brothers' War #02 +URL:https://i2.wp.com/www.possibilitystorm.com/wp-content/uploads/2022/12/213.-BRO2-scaled.jpg?ssl=1 +Goal:Win +Turns:1 +Difficulty:Rare +Description:Win this turn. Assume your opponent has no mana available. Remember that your solution must satisfy all possible blocking decisions. +[state] +turn=1 +activeplayer=p0 +activephase=MAIN1 +p0life=20 +p0hand=Giant Growth;Mishra's Command;Audacity;Sibling Rivalry +p0battlefield=Rootwire Amalgam;Cradle Clearcutter;Hurler Cyclops;Rockfall Vale;Rockfall Vale;Mountain;Mountain;Forest +p1life=26 +p1battlefield=Ivy, Gleeful Spellthief|Counters:P1P1=1 diff --git a/forge-gui/res/puzzle/PS_BRO3.pzl b/forge-gui/res/puzzle/PS_BRO3.pzl new file mode 100644 index 00000000000..d1ce36a3586 --- /dev/null +++ b/forge-gui/res/puzzle/PS_BRO3.pzl @@ -0,0 +1,17 @@ +[metadata] +Name:Possibility Storm - The Brothers' War #03 +URL:https://i2.wp.com/www.possibilitystorm.com/wp-content/uploads/2023/01/latest-scaled.jpg?ssl=1 +Goal:Win +Turns:1 +Difficulty:Uncommon +Description:Win this turn. Assume that any unknown cards you could draw are not relevant to the puzzle. Remember that your solution must satisfy all possible blocking decisions. +[state] +turn=1 +activeplayer=p0 +activephase=MAIN1 +p0life=20 +p0hand=Planar Incision;Fateful Handoff;Energy Refractor;Grafted Identity +p0library=Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt +p0battlefield=Phyrexian Fleshgorger;Teferi, Temporal Pilgrim|Counters:LOYALTY=5;Island;Island;Island;Swamp;Swamp;Swamp;T:u_2_2_spirit_vigilance_drawcounter|Counters:P1P1=1 +p1life=10 +p1battlefield=Devilish Valet diff --git a/forge-gui/res/tokenscripts/u_2_2_spirit_vigilance_drawcounter.txt b/forge-gui/res/tokenscripts/u_2_2_spirit_vigilance_drawcounter.txt index 284e5b3cab0..ab6000bc60d 100644 --- a/forge-gui/res/tokenscripts/u_2_2_spirit_vigilance_drawcounter.txt +++ b/forge-gui/res/tokenscripts/u_2_2_spirit_vigilance_drawcounter.txt @@ -1,4 +1,4 @@ -Name:Spirit token +Name:Spirit Token ManaCost:no cost Types:Creature Spirit Colors:blue From 8ddd84e829ac07e952162b6c2c3cd6a39de36984 Mon Sep 17 00:00:00 2001 From: Michael Kamensky Date: Thu, 26 Jan 2023 08:07:15 +0300 Subject: [PATCH 2/4] - Added puzzle PS_J221 --- forge-gui/res/puzzle/PS_J221.pzl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 forge-gui/res/puzzle/PS_J221.pzl diff --git a/forge-gui/res/puzzle/PS_J221.pzl b/forge-gui/res/puzzle/PS_J221.pzl new file mode 100644 index 00000000000..c4746bacb6a --- /dev/null +++ b/forge-gui/res/puzzle/PS_J221.pzl @@ -0,0 +1,16 @@ +[metadata] +Name:Possibility Storm - Jumpstart 2022 #01 +URL:https://i1.wp.com/www.possibilitystorm.com/wp-content/uploads/2023/01/215.-J22_1-scaled.jpg?ssl=1 +Goal:Win +Turns:1 +Difficulty:Easy +Description:Win this turn. Remember that your solution must satisfy all possible blocking decisions. +[state] +turn=1 +activeplayer=p0 +activephase=MAIN1 +p0life=20 +p0hand=Flicker of Fate;Wicked Wolf;Duskshell Crawler;Kami of Ancient Law;Goldnight Commander +p0battlefield=Magnanimous Magistrate|Counters:REPRIEVE=5;Fierce Witchstalker;Alseid of Life's Bounty;Plains;Plains;Plains;Forest;Forest;Forest +p1life=11 +p1battlefield=Mizzix, Replica Rider;Transcendent Envoy From 4fff3c43b63860b51b78b2f4fbd296f83da0ec44 Mon Sep 17 00:00:00 2001 From: Michael Kamensky Date: Sun, 29 Jan 2023 17:00:23 +0300 Subject: [PATCH 3/4] - Added ONE/ONC achievements by Marek14. --- forge-gui/res/lists/altwin-achievements.txt | 1 + forge-gui/res/lists/planeswalker-achievements.txt | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/forge-gui/res/lists/altwin-achievements.txt b/forge-gui/res/lists/altwin-achievements.txt index 5200f10470f..d0e398740ef 100644 --- a/forge-gui/res/lists/altwin-achievements.txt +++ b/forge-gui/res/lists/altwin-achievements.txt @@ -1,5 +1,6 @@ Angel of Destiny|Outlive Long and Prosper|Life eternal thanks to one weird trick! Approach of the Second Sun|The God-Pharaoh's Return|I'm back! Did you miss me? +Archfiend of the Dross|The Oil Clock|Too bad! You're out of fuel! Azor's Elocutors|The Filibuster|Talk might be cheap, but it can buy you victory! Barren Glory|The Clean Slate|When you have nothing, you can lose nothing... so you can win everything! Battle of Wits|The Great Library|So many answers, so little time to look through them... diff --git a/forge-gui/res/lists/planeswalker-achievements.txt b/forge-gui/res/lists/planeswalker-achievements.txt index 685929f2c84..496b2c9fc90 100644 --- a/forge-gui/res/lists/planeswalker-achievements.txt +++ b/forge-gui/res/lists/planeswalker-achievements.txt @@ -87,6 +87,7 @@ Jace, Mirror Mage|Jace the Bob|Really not much of an achievement at all, but wha Jace, Telepath Unbound|Jace's Erasure|First empty your mind and then... nope, that's it. Jace, the Living Guildpact|Jace's Timetwister|Symmetry? What symmetry? Jace, the Mind Sculptor|Jace's Lobotomy|What do you mean, "overpowered"? +Jace, the Perfected Mind|Jace's Keening Insight|I'll tear down your mind, so it can be rebuilt. Jace, Unraveler of Secrets|Jace's Perfect Plan|So, I've read about this neat guy named Erayo... Jace, Wielder of Mysteries|Jace's Neat Solution|Everything is solved. No loose ends. Jared Carthalion|Jared's Rainbow Recycling|No matter what you believe in, I still need your help. @@ -103,6 +104,7 @@ Kaya, Orzhov Usurper|Kaya's Revenge of Emptiness|Nothing I do can hurt you. Lite Kiora, Master of the Depths|Kiora's Fight Club|First rule is not to talk about the sucker punches Kiora, the Crashing Wave|Kiora's Kraken|Say hello to Cthulhu for me! Koth of the Hammer|Koth's Eruption|You won't like the mountains when they are angry! +Koth, Fire of Resistance|Koth's Molten Pinnacle|I learned this one at Valakut. Liliana Vess|Liliana's Bidding|Stop being lazy and go to work! Liliana of the Dark Realms|Liliana's Ritual|What do you mean, "out of character"? Liliana of the Veil|Liliana's Choice|Which one of your children do you love best? @@ -117,6 +119,7 @@ Liliana, Untouched by Death|Liliana's Graveyard Party|What? I'm not touching you Liliana, Waker of the Dead|Liliana's Rotten Reserves|They awaken, feeling well-rested. Lord Windgrace|Windgrace's Hunting Party|Let me show you a true cat-astrophe. Lolth, Spider Queen|Lolth's Eight-legged Strike|I eight all my opponents alive. +Lukka, Bound to Ruin|Lukka's Command of Ruin|Fetch. Roll. Spit acid. Lukka, Coppercoat Outcast|Lukka's Ultimatum|Get them. Lukka, Wayward Bonder|Lukka's Pandemonium|At them, girl! Mordenkainen|Mordenkainen's Library|All the manuals you could ever need. @@ -132,6 +135,7 @@ Nicol Bolas, the Arisen|Bolas's Mind Wipe|Anything Jace can do, I can do better. Nicol Bolas, the Deceiver|Bolas's Cunning Hit|I know exactly how to hurt you. Nissa of Shadowed Boughs|Nissa's Reanimation|Every land hides some secrets deep down. Nissa Revane|Nissa's Summoning|The whole village is here! +Nissa, Ascended Animist|Nissa's Overgrown Overrun|Small creatures hide in the woods. Large use them as a weapon. Nissa, Genesis Mage|Nissa's Genesis Wave|Let's see who shows up. Nissa, Nature's Artisan|Nissa's Stampede|Big enough for you? Nissa, Sage Animist|Nissa's Wake-Up Call|Wake up! Time to work! @@ -201,6 +205,7 @@ Vivien, Arkbow Ranger|Vivien's Wish|Welcome, old friend. I was afraid I lost you Vivien, Monsters' Advocate|Vivien's Nature Documentary|Awww, look! He has a little buddy! Vivien, Nature's Avenger|Vivien's Magnification|Magnificent! Vraska the Unseen|Vraska's Crew|Say hello to my little friends! +Vraska, Betrayal's Sting|Vraska's Near-Death Experience|Taste your penultimate pain! Vraska, Golgari Queen|Vraska's Training Regime|Step one - give them a scratch. There's no step two. Vraska, Regal Gorgon|Vraska's Scavenger Hunt|Death is not the opposite of life - it's its complement. Vraska, Relic Seeker|Vraska's Mark|Never play hide and seek with a Gorgon. From 8df876eb3d4f8e99947b576c4976191efdfca533 Mon Sep 17 00:00:00 2001 From: Michael Kamensky Date: Sun, 29 Jan 2023 17:50:20 +0300 Subject: [PATCH 4/4] - Fix Enlist description during cost payment. --- forge-game/src/main/java/forge/game/card/CardFactoryUtil.java | 2 +- forge-gui/res/languages/en-US.properties | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) 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 8dff735a913..6535fb92b37 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -3707,7 +3707,7 @@ public class CardFactoryUtil { + " | Description$ " + sb.toString() + " (" + inst.getReminderText() + ")"; inst.addStaticAbility(StaticAbility.create(effect, state.getCard(), state, intrinsic)); } else if (keyword.equals("Enlist")) { - String effect = "Mode$ OptionalAttackCost | ValidCard$ Card.Self | Cost$ Enlist<1/CARDNAME> | Secondary$ True" + + String effect = "Mode$ OptionalAttackCost | ValidCard$ Card.Self | Cost$ Enlist<1/CARDNAME/creature> | Secondary$ True" + "| Trigger$ TrigEnlist | Description$ Enlist ( " + inst.getReminderText() + ")"; StaticAbility st = StaticAbility.create(effect, state.getCard(), state, intrinsic); st.setSVar("TrigEnlist", "DB$ Pump | NumAtt$ TriggerRemembered$CardPower" + diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 675da5849e8..2ada67edb4c 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -1349,6 +1349,7 @@ lblUseTriggeredAbilityOf=Use triggered ability of lblExertAttackersConfirm=Exert Attackers? lblEnlistAttackersConfirm=Enlist Attackers? lblEnlisted=Enlisted +lblSelectACostToEnlist=Select a {0} to enlist ({1} left) lblThereNoCardInPlayerZone=There are no cards in {0} {1} lblPutCardsOnTheTopLibraryOrGraveyard=Put {0} on the top of library or graveyard? lblLibrary=Library