dovin 0.1.0.0 → 0.1.0.1
raw patch · 5 files changed
+362/−361 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Solutions.Channel: aetherfluxTriggerName :: Show a => a -> [Char]
- Solutions.Channel: attributes :: Formatter
- Solutions.Channel: flashbackSnapped :: ManaPool -> CardName -> ExceptT String (ReaderT Env (StateT Board (WriterT [(String, Board)] Identity))) ()
- Solutions.Channel: formatter :: (Eq a, Num a) => a -> Formatter
- Solutions.Channel: highTideCounter :: Lens' Board Int
- Solutions.Channel: playExLandFormatter :: Formatter
- Solutions.Channel: resolveAetherflux :: Show a => a -> ExceptT String (ReaderT Env (StateT Board (WriterT [(String, Board)] Identity))) ()
- Solutions.Channel: snapped :: [Char]
- Solutions.Channel: solution :: GameMonad ()
- Solutions.Channel: spellCounter :: Lens' Board Int
- Solutions.Channel: tapForManaWithTide :: ManaString -> CardName -> ExceptT String (ReaderT Env (StateT Board (WriterT [(String, Board)] Identity))) ()
- Solutions.Channel: withTriggers :: () => (t -> ExceptT String (ReaderT Env (StateT Board (WriterT [(String, Board)] Identity))) a) -> t -> ExceptT String (ReaderT Env (StateT Board (WriterT [(String, Board)] Identity))) ()
+ Solutions.ChannelFireball: aetherfluxTriggerName :: Show a => a -> [Char]
+ Solutions.ChannelFireball: attributes :: Formatter
+ Solutions.ChannelFireball: flashbackSnapped :: ManaPool -> CardName -> ExceptT String (ReaderT Env (StateT Board (WriterT [(String, Board)] Identity))) ()
+ Solutions.ChannelFireball: formatter :: (Eq a, Num a) => a -> Formatter
+ Solutions.ChannelFireball: highTideCounter :: Lens' Board Int
+ Solutions.ChannelFireball: playExLandFormatter :: Formatter
+ Solutions.ChannelFireball: resolveAetherflux :: Show a => a -> ExceptT String (ReaderT Env (StateT Board (WriterT [(String, Board)] Identity))) ()
+ Solutions.ChannelFireball: snapped :: [Char]
+ Solutions.ChannelFireball: solution :: GameMonad ()
+ Solutions.ChannelFireball: spellCounter :: Lens' Board Int
+ Solutions.ChannelFireball: tapForManaWithTide :: ManaString -> CardName -> ExceptT String (ReaderT Env (StateT Board (WriterT [(String, Board)] Identity))) ()
+ Solutions.ChannelFireball: withTriggers :: () => (t -> ExceptT String (ReaderT Env (StateT Board (WriterT [(String, Board)] Identity))) a) -> t -> ExceptT String (ReaderT Env (StateT Board (WriterT [(String, Board)] Identity))) ()
Files
- README.md +1/−0
- dovin.cabal +4/−4
- src/Solutions.hs +2/−2
- src/Solutions/Channel.hs +0/−355
- src/Solutions/ChannelFireball.hs +355/−0
README.md view
@@ -111,6 +111,7 @@ * `ExplorersOfIxalanContest` handles some pretty weird damage interactions. * `UltimateMasters` shows how to track opponent actions.+* `ChannelFireball` automatically calculates High Tide mana. ## Development
dovin.cabal view
@@ -4,12 +4,12 @@ -- -- see: https://github.com/sol/hpack ----- hash: 64287929507673044e7103b8e99c63a3a57295a03eadbdd2273ea38a6655949d+-- hash: 23abec652853b2a8c66c2399750bd96d11e7232610506070a3b870a252bee00d name: dovin-version: 0.1.0.0+version: 0.1.0.1 synopsis: A proof assistant for Magic: The Gathering puzzles.-description: Please see the README on GitHub at <https://github.com/githubuser/dovin#readme>+description: Please see the README on GitHub at <https://github.com/xaviershay/dovin#dovin> category: Games homepage: https://github.com/xaviershay/dovin#readme bug-reports: https://github.com/xaviershay/dovin/issues@@ -49,7 +49,7 @@ Dovin.V2 Lib Solutions- Solutions.Channel+ Solutions.ChannelFireball Solutions.Core19_9 Solutions.Dominaria5 Solutions.Example
src/Solutions.hs view
@@ -1,5 +1,5 @@ module Solutions where-import qualified Solutions.Channel+import qualified Solutions.ChannelFireball import qualified Solutions.Core19_9 import qualified Solutions.Dominaria5 import qualified Solutions.Example@@ -13,7 +13,7 @@ import qualified Solutions.UltimateMasters all = [- ("Channel", Solutions.Channel.solution, Solutions.Channel.formatter),+ ("ChannelFireball", Solutions.ChannelFireball.solution, Solutions.ChannelFireball.formatter), ("Core19_9", Solutions.Core19_9.solution, Solutions.Core19_9.formatter), ("Dominaria5", Solutions.Dominaria5.solution, Solutions.Dominaria5.formatter), ("Example", Solutions.Example.solution, Solutions.Example.formatter),
− src/Solutions/Channel.hs
@@ -1,355 +0,0 @@-module Solutions.Channel where--import Dovin.V2-import Dovin.Prelude--import Data.List (delete)-import Control.Lens-import Debug.Trace--solution :: GameMonad ()-solution = do- step "Initial state" $ do- setLife Active 1-- withLocation Play $ do- addLands 4 "Steam Vents"- addLands 4 "Breeding Pool"- addArtifact "Aetherflux Reservoir"- addCreature (2, 2) "Beamsplitter Mage"- addCreature (2, 2) "Man-o'-War"-- withLocation Hand $ do- addInstant "High Tide"- addInstant "Snap"- addInstant "Rewind"- addSorcery "Baral's Expertise"- addSorcery "Channel"- addSorcery "Fireball"- withAttribute flash $ addCreature (2, 1) "Snapcaster Mage"- addCreature (0, 0) "Walking Ballista"-- step "Cast High Tide with a Steam Vents" $ do- tapForManaWithTide "U" "Steam Vents 1"- withTriggers (cast "U") "High Tide"- resolveAetherflux 1- resolve "High Tide"-- modifying- highTideCounter- (+ 1)-- step "Cast Snapcaster, targeting High Tide, with second Steam Vents" $ do- tapForManaWithTide "U" "Steam Vents 2"- withTriggers (cast "1U") "Snapcaster Mage"-- resolveAetherflux 2- resolve "Snapcaster Mage"- targetInLocation (Active, Graveyard) "High Tide"- gainAttribute snapped "High Tide"-- step "Flashback High Tide with third Steam Vents" $ do- tapForManaWithTide "U" "Steam Vents 3"- withTriggers (flashbackSnapped "U") "High Tide"-- resolveAetherflux 3- resolve "High Tide"-- modifying- highTideCounter- (+ 1)-- step "Tap five remaining lands for 3 mana each" $ do- tapForManaWithTide "R" "Steam Vents 4"- tapForManaWithTide "G" "Breeding Pool 1"- tapForManaWithTide "G" "Breeding Pool 2"- tapForManaWithTide "U" "Breeding Pool 3"- tapForManaWithTide "U" "Breeding Pool 4"-- step "Cast Walking Ballista for 1, leave on stack" $ do- withTriggers (cast "") "Walking Ballista"-- step "Stack Snap, targeting Beamsplitter then copying to Snapcaster" $ do- withTriggers (cast "1U") "Snap"- target "Beamsplitter Mage"- trigger "Copied Snap" "Beamsplitter Mage" >> resolveTop- copySpell "Snap" "Snap Copy (Snapcaster Mage)"- target "Snapcaster Mage"-- step "Counter Walking Ballista with Rewind, untapping Steam Vents" $ do- withTriggers (cast "2UU") "Rewind"- counter "Walking Ballista"- resolveAetherflux 6- resolve "Rewind"- untap "Steam Vents 1"- untap "Steam Vents 2"- untap "Steam Vents 3"- untap "Steam Vents 4"-- step "Resolve Snap copy, returning Snapcaster, untapping Breeding Pools" $ do- resolve "Snap Copy (Snapcaster Mage)"-- move (Active, Play) (Active, Hand) "Snapcaster Mage"- untap "Breeding Pool 1"- untap "Breeding Pool 2"-- step "Resolve Snap, returning Beamsplitter, untapping Breeding Pools" $ do- resolveAetherflux 5- resolve "Snap"- move (Active, Play) (Active, Hand) "Beamsplitter Mage"- untap "Breeding Pool 3"- untap "Breeding Pool 4"- resolveAetherflux 4-- step "Recast Beamsplitter, stacking Snapcaster targeting Snap" $ do- withTriggers (cast "RU") "Beamsplitter Mage"- withTriggers (cast "1U") "Snapcaster Mage"-- resolveAetherflux 8- resolve "Snapcaster Mage"- resolveAetherflux 7- resolve "Beamsplitter Mage"-- targetInLocation (Active, Graveyard) "Snap"- gainAttribute snapped "Snap"-- step "Tap all lands for 3 mana each" $ do- tapForManaWithTide "U" "Steam Vents 1"- tapForManaWithTide "U" "Steam Vents 2"- tapForManaWithTide "R" "Steam Vents 3"- tapForManaWithTide "R" "Steam Vents 4"- tapForManaWithTide "G" "Breeding Pool 1"- tapForManaWithTide "G" "Breeding Pool 2"- tapForManaWithTide "U" "Breeding Pool 3"- tapForManaWithTide "U" "Breeding Pool 4"-- step "Stack flashbacked Snap, targeting Beamsplitter then copy to Snapcaster" $ do- withTriggers (flashbackSnapped "1U") "Snap"- target "Beamsplitter Mage"- trigger "Copied Snap" "Beamsplitter Mage" >> resolveTop- copySpell "Snap" "Snap Copy (Snapcaster Mage)"- target "Snapcaster Mage"-- step "Resolve Snap copy, returning Snapcaster, untap Breeding Pools" $ do- resolve "Snap Copy (Snapcaster Mage)"-- move (Active, Play) (Active, Hand) "Snapcaster Mage"- untap "Breeding Pool 1"- untap "Breeding Pool 2"-- step "Replay Snapcaster, targeting Rewind" $ do- withTriggers (cast "1U") "Snapcaster Mage"- resolveAetherflux 10- resolve "Snapcaster Mage"- targetInLocation (Active, Graveyard) "Rewind"- gainAttribute snapped "Rewind"-- step "Resolve Snap on Beamsplitter, untap Steam Vents" $ do- resolveAetherflux 9- resolve "Snap"- move (Active, Play) (Active, Hand) "Beamsplitter Mage"- untap "Steam Vents 3"- untap "Steam Vents 4"-- step "Cast Baral's Expertise for all 3 in play, replaying Aetherflux for free" $ do- withTriggers (cast "3UU") "Baral's Expertise"- resolveAetherflux 11- resolve "Baral's Expertise"-- move (Active, Play) (Active, Hand) "Aetherflux Reservoir"- move (Active, Play) (Active, Hand) "Man-o'-War"- move (Active, Play) (Active, Hand) "Snapcaster Mage"-- withTriggers (cast "") "Aetherflux Reservoir"- resolve "Aetherflux Reservoir"-- step "Cast Beamsplitter Mage, stacking Snapcaster targeting Baral's" $ do- withTriggers (cast "UR") "Beamsplitter Mage"- withTriggers (cast "1U") "Snapcaster Mage"- resolveAetherflux 14- resolve "Snapcaster Mage"- resolveAetherflux 13- resolve "Beamsplitter Mage"-- targetInLocation (Active, Graveyard) "Baral's Expertise"- gainAttribute snapped "Baral's Expertise"-- step "Flashback Baral's Expertise targeting all 3 in play, replaying Aetherflux" $ do- withTriggers (flashbackSnapped "3UU") "Baral's Expertise"- resolveAetherflux 15- resolve "Baral's Expertise"-- move (Active, Play) (Active, Hand) "Aetherflux Reservoir"- move (Active, Play) (Active, Hand) "Beamsplitter Mage"- move (Active, Play) (Active, Hand) "Snapcaster Mage"-- withTriggers (cast "") "Aetherflux Reservoir"- resolve "Aetherflux Reservoir"-- step "Tap remaining lands for 3 mana each" $ do- tapForManaWithTide "G" "Breeding Pool 1"- tapForManaWithTide "G" "Breeding Pool 2"- tapForManaWithTide "R" "Steam Vents 3"- tapForManaWithTide "R" "Steam Vents 4"-- step "Cast Channel and Fireball for life only" $ do- withTriggers (cast "GG") "Channel"- resolveAetherflux 17- resolve "Channel"-- l <- (-) <$> countLife Active <*> pure 1-- let payment = show l <> "R"-- loseLife Active l- addMana $ show l-- withTriggers (cast payment) "Fireball"- resolveAetherflux 18- resolve "Fireball"-- damage (const l) (targetPlayer Opponent) "Fireball"-- step "Cast Beamsplitter Mage, stacking Snapcaster targeting Fireball" $ do- withTriggers (cast "UR") "Beamsplitter Mage"- withTriggers (cast "1U") "Snapcaster Mage"- resolveAetherflux 20- resolve "Snapcaster Mage"- resolveAetherflux 19- resolve "Beamsplitter Mage"-- targetInLocation (Active, Graveyard) "Fireball"- gainAttribute snapped "Fireball"-- step "Cast Man-'o-War, returning Snapcaster Mage" $ do- withTriggers (cast "2U") "Man-o'-War"- resolveAetherflux 21- resolve "Man-o'-War"-- target "Snapcaster Mage"- move (Active, Play) (Active, Hand) "Snapcaster Mage"-- step "Cast Snapcaster, counter with flashback Rewind" $ do- withTriggers (cast "1U") "Snapcaster Mage"- withTriggers (flashbackSnapped "2UU") "Rewind"- resolveAetherflux 23- resolve "Rewind"- counter "Snapcaster Mage"- resolveAetherflux 22-- untap "Breeding Pool 1"- untap "Breeding Pool 2"- untap "Steam Vents 3"- untap "Steam Vents 4"-- step "Flashback Fireball with all remaining mana and life" $ do- tapForManaWithTide "U" "Breeding Pool 1"- tapForManaWithTide "U" "Breeding Pool 2"- tapForManaWithTide "R" "Steam Vents 3"- tapForManaWithTide "R" "Steam Vents 4"-- life <- countLife Active- mana <- countManaPool Active- let dmg = (life - 1) + (mana - 1)- let payment = show dmg <> "R"-- loseLife Active (life - 1)- addMana $ show (life - 1)-- withTriggers (flashbackSnapped payment) "Fireball"- resolveAetherflux 24- resolve "Fireball"-- damage (const life) (targetPlayer Opponent) "Fireball"--attributes = attributeFormatter $ do- attribute "life" $ countLife Active- attribute "pool" $ countManaPool Active- attribute "spells" $ use spellCounter--playExLandFormatter = cardFormatter "Play (ex. Land)"- (matchLocation (Active, Play) <> invert (matchAttribute land))-formatter 1 = attributes <> boardFormatter-formatter 3 = attributes- <> cardFormatter "Play" (matchLocation (Active, Play))- <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))-formatter 6 = attributes <> stackFormatter-formatter 7 = attributes <> stackFormatter-formatter 8 = attributes <> stackFormatter- <> cardFormatter "Play" (matchLocation (Active, Play))-formatter 9 = attributes <> stackFormatter-formatter 10 = attributes <> stackFormatter- <> cardFormatter "Hand" (matchLocation (Active, Hand))- <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))-formatter 11 = attributes- <> cardFormatter "Play" (matchLocation (Active, Play))- <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))-formatter 13 = attributes <> stackFormatter-formatter 14 = attributes <> stackFormatter- <> cardFormatter "Hand" (matchLocation (Active, Hand))- <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))-formatter 15 = attributes <> stackFormatter- <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))-formatter 16 = attributes- <> cardFormatter "Hand" (matchLocation (Active, Hand))- <> cardFormatter "Play" (matchLocation (Active, Play))-formatter 17 = attributes- <> cardFormatter "Hand" (matchLocation (Active, Hand))- <> playExLandFormatter-formatter 18 = attributes- <> playExLandFormatter- <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))-formatter 19 = attributes- <> cardFormatter "Hand" (matchLocation (Active, Hand))- <> playExLandFormatter-formatter 21 = attributeFormatter (attribute "opponent" $ countLife Opponent) <> attributes-formatter 22 = attributes- <> cardFormatter "Hand" (matchLocation (Active, Hand))- <> playExLandFormatter- <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))-formatter 23 = attributes- <> cardFormatter "Hand" (matchLocation (Active, Hand))- <> playExLandFormatter-formatter 25 = attributeFormatter (attribute "opponent" $ countLife Opponent) <> attributes-formatter _ = attributes--spellCounter :: Lens' Board Int-spellCounter = counters . at "spell-count" . non 0--highTideCounter :: Lens' Board Int-highTideCounter = counters . at "high-tide-count" . non 0--aetherfluxTriggerName n = "Aetherflux Trigger #" <> show n-snapped = "snapped"---- Keeps track of number of spells cast, and if Aetherflux Reservoir is in play--- triggers it.-withTriggers fn name = do- fn name-- modifying- spellCounter- (+ 1)-- forCards- (matchInPlay <> matchName "Aetherflux Reservoir")- $ const $ do- x <- use spellCounter- trigger (aetherfluxTriggerName x) "Aetherflux Reservoir"--tapForManaWithTide pool cn = do- tapForMana pool cn- x <- use highTideCounter-- addMana (replicate x 'U')--resolveAetherflux n = do- resolve $ aetherfluxTriggerName n-- x <- use spellCounter- gainLife Active x--flashbackSnapped mana castName = do- validate (matchAttribute snapped) castName- flashback mana castName-
+ src/Solutions/ChannelFireball.hs view
@@ -0,0 +1,355 @@+module Solutions.ChannelFireball where++import Dovin.V2+import Dovin.Prelude++import Data.List (delete)+import Control.Lens+import Debug.Trace++solution :: GameMonad ()+solution = do+ step "Initial state" $ do+ setLife Active 1++ withLocation Play $ do+ addLands 4 "Steam Vents"+ addLands 4 "Breeding Pool"+ addArtifact "Aetherflux Reservoir"+ addCreature (2, 2) "Beamsplitter Mage"+ addCreature (2, 2) "Man-o'-War"++ withLocation Hand $ do+ addInstant "High Tide"+ addInstant "Snap"+ addInstant "Rewind"+ addSorcery "Baral's Expertise"+ addSorcery "Channel"+ addSorcery "Fireball"+ withAttribute flash $ addCreature (2, 1) "Snapcaster Mage"+ addCreature (0, 0) "Walking Ballista"++ step "Cast High Tide with a Steam Vents" $ do+ tapForManaWithTide "U" "Steam Vents 1"+ withTriggers (cast "U") "High Tide"+ resolveAetherflux 1+ resolve "High Tide"++ modifying+ highTideCounter+ (+ 1)++ step "Cast Snapcaster, targeting High Tide, with second Steam Vents" $ do+ tapForManaWithTide "U" "Steam Vents 2"+ withTriggers (cast "1U") "Snapcaster Mage"++ resolveAetherflux 2+ resolve "Snapcaster Mage"+ targetInLocation (Active, Graveyard) "High Tide"+ gainAttribute snapped "High Tide"++ step "Flashback High Tide with third Steam Vents" $ do+ tapForManaWithTide "U" "Steam Vents 3"+ withTriggers (flashbackSnapped "U") "High Tide"++ resolveAetherflux 3+ resolve "High Tide"++ modifying+ highTideCounter+ (+ 1)++ step "Tap five remaining lands for 3 mana each" $ do+ tapForManaWithTide "R" "Steam Vents 4"+ tapForManaWithTide "G" "Breeding Pool 1"+ tapForManaWithTide "G" "Breeding Pool 2"+ tapForManaWithTide "U" "Breeding Pool 3"+ tapForManaWithTide "U" "Breeding Pool 4"++ step "Cast Walking Ballista for 1, leave on stack" $ do+ withTriggers (cast "") "Walking Ballista"++ step "Stack Snap, targeting Beamsplitter then copying to Snapcaster" $ do+ withTriggers (cast "1U") "Snap"+ target "Beamsplitter Mage"+ trigger "Copied Snap" "Beamsplitter Mage" >> resolveTop+ copySpell "Snap" "Snap Copy (Snapcaster Mage)"+ target "Snapcaster Mage"++ step "Counter Walking Ballista with Rewind, untapping Steam Vents" $ do+ withTriggers (cast "2UU") "Rewind"+ counter "Walking Ballista"+ resolveAetherflux 6+ resolve "Rewind"+ untap "Steam Vents 1"+ untap "Steam Vents 2"+ untap "Steam Vents 3"+ untap "Steam Vents 4"++ step "Resolve Snap copy, returning Snapcaster, untapping Breeding Pools" $ do+ resolve "Snap Copy (Snapcaster Mage)"++ move (Active, Play) (Active, Hand) "Snapcaster Mage"+ untap "Breeding Pool 1"+ untap "Breeding Pool 2"++ step "Resolve Snap, returning Beamsplitter, untapping Breeding Pools" $ do+ resolveAetherflux 5+ resolve "Snap"+ move (Active, Play) (Active, Hand) "Beamsplitter Mage"+ untap "Breeding Pool 3"+ untap "Breeding Pool 4"+ resolveAetherflux 4++ step "Recast Beamsplitter, stacking Snapcaster targeting Snap" $ do+ withTriggers (cast "RU") "Beamsplitter Mage"+ withTriggers (cast "1U") "Snapcaster Mage"++ resolveAetherflux 8+ resolve "Snapcaster Mage"+ resolveAetherflux 7+ resolve "Beamsplitter Mage"++ targetInLocation (Active, Graveyard) "Snap"+ gainAttribute snapped "Snap"++ step "Tap all lands for 3 mana each" $ do+ tapForManaWithTide "U" "Steam Vents 1"+ tapForManaWithTide "U" "Steam Vents 2"+ tapForManaWithTide "R" "Steam Vents 3"+ tapForManaWithTide "R" "Steam Vents 4"+ tapForManaWithTide "G" "Breeding Pool 1"+ tapForManaWithTide "G" "Breeding Pool 2"+ tapForManaWithTide "U" "Breeding Pool 3"+ tapForManaWithTide "U" "Breeding Pool 4"++ step "Stack flashbacked Snap, targeting Beamsplitter then copy to Snapcaster" $ do+ withTriggers (flashbackSnapped "1U") "Snap"+ target "Beamsplitter Mage"+ trigger "Copied Snap" "Beamsplitter Mage" >> resolveTop+ copySpell "Snap" "Snap Copy (Snapcaster Mage)"+ target "Snapcaster Mage"++ step "Resolve Snap copy, returning Snapcaster, untap Breeding Pools" $ do+ resolve "Snap Copy (Snapcaster Mage)"++ move (Active, Play) (Active, Hand) "Snapcaster Mage"+ untap "Breeding Pool 1"+ untap "Breeding Pool 2"++ step "Replay Snapcaster, targeting Rewind" $ do+ withTriggers (cast "1U") "Snapcaster Mage"+ resolveAetherflux 10+ resolve "Snapcaster Mage"+ targetInLocation (Active, Graveyard) "Rewind"+ gainAttribute snapped "Rewind"++ step "Resolve Snap on Beamsplitter, untap Steam Vents" $ do+ resolveAetherflux 9+ resolve "Snap"+ move (Active, Play) (Active, Hand) "Beamsplitter Mage"+ untap "Steam Vents 3"+ untap "Steam Vents 4"++ step "Cast Baral's Expertise for all 3 in play, replaying Aetherflux for free" $ do+ withTriggers (cast "3UU") "Baral's Expertise"+ resolveAetherflux 11+ resolve "Baral's Expertise"++ move (Active, Play) (Active, Hand) "Aetherflux Reservoir"+ move (Active, Play) (Active, Hand) "Man-o'-War"+ move (Active, Play) (Active, Hand) "Snapcaster Mage"++ withTriggers (cast "") "Aetherflux Reservoir"+ resolve "Aetherflux Reservoir"++ step "Cast Beamsplitter Mage, stacking Snapcaster targeting Baral's" $ do+ withTriggers (cast "UR") "Beamsplitter Mage"+ withTriggers (cast "1U") "Snapcaster Mage"+ resolveAetherflux 14+ resolve "Snapcaster Mage"+ resolveAetherflux 13+ resolve "Beamsplitter Mage"++ targetInLocation (Active, Graveyard) "Baral's Expertise"+ gainAttribute snapped "Baral's Expertise"++ step "Flashback Baral's Expertise targeting all 3 in play, replaying Aetherflux" $ do+ withTriggers (flashbackSnapped "3UU") "Baral's Expertise"+ resolveAetherflux 15+ resolve "Baral's Expertise"++ move (Active, Play) (Active, Hand) "Aetherflux Reservoir"+ move (Active, Play) (Active, Hand) "Beamsplitter Mage"+ move (Active, Play) (Active, Hand) "Snapcaster Mage"++ withTriggers (cast "") "Aetherflux Reservoir"+ resolve "Aetherflux Reservoir"++ step "Tap remaining lands for 3 mana each" $ do+ tapForManaWithTide "G" "Breeding Pool 1"+ tapForManaWithTide "G" "Breeding Pool 2"+ tapForManaWithTide "R" "Steam Vents 3"+ tapForManaWithTide "R" "Steam Vents 4"++ step "Cast Channel and Fireball for life only" $ do+ withTriggers (cast "GG") "Channel"+ resolveAetherflux 17+ resolve "Channel"++ l <- (-) <$> countLife Active <*> pure 1++ let payment = show l <> "R"++ loseLife Active l+ addMana $ show l++ withTriggers (cast payment) "Fireball"+ resolveAetherflux 18+ resolve "Fireball"++ damage (const l) (targetPlayer Opponent) "Fireball"++ step "Cast Beamsplitter Mage, stacking Snapcaster targeting Fireball" $ do+ withTriggers (cast "UR") "Beamsplitter Mage"+ withTriggers (cast "1U") "Snapcaster Mage"+ resolveAetherflux 20+ resolve "Snapcaster Mage"+ resolveAetherflux 19+ resolve "Beamsplitter Mage"++ targetInLocation (Active, Graveyard) "Fireball"+ gainAttribute snapped "Fireball"++ step "Cast Man-'o-War, returning Snapcaster Mage" $ do+ withTriggers (cast "2U") "Man-o'-War"+ resolveAetherflux 21+ resolve "Man-o'-War"++ target "Snapcaster Mage"+ move (Active, Play) (Active, Hand) "Snapcaster Mage"++ step "Cast Snapcaster, counter with flashback Rewind" $ do+ withTriggers (cast "1U") "Snapcaster Mage"+ withTriggers (flashbackSnapped "2UU") "Rewind"+ resolveAetherflux 23+ resolve "Rewind"+ counter "Snapcaster Mage"+ resolveAetherflux 22++ untap "Breeding Pool 1"+ untap "Breeding Pool 2"+ untap "Steam Vents 3"+ untap "Steam Vents 4"++ step "Flashback Fireball with all remaining mana and life" $ do+ tapForManaWithTide "U" "Breeding Pool 1"+ tapForManaWithTide "U" "Breeding Pool 2"+ tapForManaWithTide "R" "Steam Vents 3"+ tapForManaWithTide "R" "Steam Vents 4"++ life <- countLife Active+ mana <- countManaPool Active+ let dmg = (life - 1) + (mana - 1)+ let payment = show dmg <> "R"++ loseLife Active (life - 1)+ addMana $ show (life - 1)++ withTriggers (flashbackSnapped payment) "Fireball"+ resolveAetherflux 24+ resolve "Fireball"++ damage (const life) (targetPlayer Opponent) "Fireball"++attributes = attributeFormatter $ do+ attribute "life" $ countLife Active+ attribute "pool" $ countManaPool Active+ attribute "spells" $ use spellCounter++playExLandFormatter = cardFormatter "Play (ex. Land)"+ (matchLocation (Active, Play) <> invert (matchAttribute land))+formatter 1 = attributes <> boardFormatter+formatter 3 = attributes+ <> cardFormatter "Play" (matchLocation (Active, Play))+ <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))+formatter 6 = attributes <> stackFormatter+formatter 7 = attributes <> stackFormatter+formatter 8 = attributes <> stackFormatter+ <> cardFormatter "Play" (matchLocation (Active, Play))+formatter 9 = attributes <> stackFormatter+formatter 10 = attributes <> stackFormatter+ <> cardFormatter "Hand" (matchLocation (Active, Hand))+ <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))+formatter 11 = attributes+ <> cardFormatter "Play" (matchLocation (Active, Play))+ <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))+formatter 13 = attributes <> stackFormatter+formatter 14 = attributes <> stackFormatter+ <> cardFormatter "Hand" (matchLocation (Active, Hand))+ <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))+formatter 15 = attributes <> stackFormatter+ <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))+formatter 16 = attributes+ <> cardFormatter "Hand" (matchLocation (Active, Hand))+ <> cardFormatter "Play" (matchLocation (Active, Play))+formatter 17 = attributes+ <> cardFormatter "Hand" (matchLocation (Active, Hand))+ <> playExLandFormatter+formatter 18 = attributes+ <> playExLandFormatter+ <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))+formatter 19 = attributes+ <> cardFormatter "Hand" (matchLocation (Active, Hand))+ <> playExLandFormatter+formatter 21 = attributeFormatter (attribute "opponent" $ countLife Opponent) <> attributes+formatter 22 = attributes+ <> cardFormatter "Hand" (matchLocation (Active, Hand))+ <> playExLandFormatter+ <> cardFormatter "Graveyard" (matchLocation (Active, Graveyard))+formatter 23 = attributes+ <> cardFormatter "Hand" (matchLocation (Active, Hand))+ <> playExLandFormatter+formatter 25 = attributeFormatter (attribute "opponent" $ countLife Opponent) <> attributes+formatter _ = attributes++spellCounter :: Lens' Board Int+spellCounter = counters . at "spell-count" . non 0++highTideCounter :: Lens' Board Int+highTideCounter = counters . at "high-tide-count" . non 0++aetherfluxTriggerName n = "Aetherflux Trigger #" <> show n+snapped = "snapped"++-- Keeps track of number of spells cast, and if Aetherflux Reservoir is in play+-- triggers it.+withTriggers fn name = do+ fn name++ modifying+ spellCounter+ (+ 1)++ forCards+ (matchInPlay <> matchName "Aetherflux Reservoir")+ $ const $ do+ x <- use spellCounter+ trigger (aetherfluxTriggerName x) "Aetherflux Reservoir"++tapForManaWithTide pool cn = do+ tapForMana pool cn+ x <- use highTideCounter++ addMana (replicate x 'U')++resolveAetherflux n = do+ resolve $ aetherfluxTriggerName n++ x <- use spellCounter+ gainLife Active x++flashbackSnapped mana castName = do+ validate (matchAttribute snapped) castName+ flashback mana castName+