module Solutions.GuildsOfRavnica9 where import Control.Lens import Control.Monad import Control.Monad.Except (throwError) import Dovin.V1 solution :: GameMonad () solution = do -- This puzzle relies heavily on casting triggers, so wrap the relevant ones -- up in this helper. -- -- For ease of use, spells that will be copied are named with a trailing " 1" -- and subsequent copies increment this number. let withTriggers = \action name -> do action name trigger "Thousand-Year Storm" triggerStorm $ \n -> copySpell (numbered (n + 1) (zipWith const name (drop 2 name))) name trigger "Adeliz, the Cinder Wind" modifyStrength (1, 1) "Adeliz, the Cinder Wind" -- We'll be making a lot of archers... let addArcherCopy name = do withLocation (Active, Play) $ withAttributes [token, summoned] $ addCreature (1, 4) name let angel = "angel" let merfolk = "merfolk" step "Initial state" $ do setLife Opponent 12 withLocation (Active, Hand) $ do addSorcery "Undercity Uprising" addSorcery "Doublecast 1" addInstant "Plummet 1" addSorcery "Quasiduplicate 1" withAttribute flying $ addCreature (7, 6) "Torgaar, Famine Incarnate" addAura "Waterknot" withLocation (Active, Play) $ do addEnchantment "Thousand-Year Storm" -- Has +2/+2 from Maniacal Rage aura withAttribute flying $ addCreature (4, 4) "Adeliz, the Cinder Wind" addCreature (1, 4) "Afzocan Archer" addLands 4 "Timber Gorge" addLands 4 "Submerged Boneyard" addLands 4 "Highland Lake" withLocation (Opponent, Play) $ do withAttribute "merfolk" $ addCreature (2, 2) "Kopala, Warden of Waves" withAttributes [flying, token] $ addCreature (4, 4) "Angel 1" withAttributes [flying, token] $ addCreature (4, 4) "Angel 2" withAttributes [flying, token] $ addCreature (4, 4) "Angel 3" withAttributes [flying, angel] $ withEffect matchInPlay matchOtherCreatures (pure . setAttribute hexproof) $ addCreature (3, 4) "Shalai, Voice of Plenty" withAttributes [flying, lifelink, angel] $ withEffect matchInPlay (matchOtherCreatures <> (const $ matchAttribute angel)) (pure . over cardStrength (mkStrength (1, 1) <>) . setAttribute lifelink) $ addCreature (4, 4) "Lyra Dawnbringer" withAttribute merfolk $ withEffect matchInPlay (matchOtherCreatures <> (const $ matchAttribute merfolk)) (pure . over cardStrength (mkStrength (1, 1) <>)) $ addCreature (2, 2) "Merfolk Mistbinder 1" withAttribute merfolk $ withEffect matchInPlay (matchOtherCreatures <> (const $ matchAttribute merfolk)) (pure . over cardStrength (mkStrength (1, 1) <>)) $ addCreature (3, 3) "Merfolk Mistbinder 2" step "Use Undercity Uprising on Adeliz to destroy Shalai" $ do tapForMana "G" (numbered 1 "Timber Gorge") tapForMana "B" (numbered 1 "Submerged Boneyard") tapForMana "B" (numbered 2 "Submerged Boneyard") withTriggers (cast "1GB") "Undercity Uprising" resolve "Undercity Uprising" forCards (matchAttribute creature <> matchLocation (Active, Play)) (gainAttribute deathtouch) with "Shalai, Voice of Plenty" $ \enemy -> do withStateBasedActions $ fight "Adeliz, the Cinder Wind" enemy validate enemy $ matchLocation (Opponent, Graveyard) step "Cast Doublecast" $ do tapForMana "R" (numbered 2 "Timber Gorge") tapForMana "R" (numbered 3 "Timber Gorge") withTriggers (cast "RR") "Doublecast 1" resolve "Doublecast 2" resolve "Doublecast 1" step "Cast Plummet to destroy all fliers" $ do tapForMana "G" "Timber Gorge 4" withTriggers (cast "G") "Plummet 1" -- From double doublecast earlier copySpell "Plummet 4" "Plummet 1" copySpell "Plummet 5" "Plummet 1" resolve "Plummet 5" with "Lyra Dawnbringer" $ \enemy -> do target enemy validate enemy $ matchAttribute flying destroy enemy validate enemy $ matchLocation (Opponent, Graveyard) forM_ [1..3] $ \n -> do resolve (numbered (5 - n) "Plummet") with (numbered n "Angel") $ \enemy -> do target enemy validate enemy $ matchAttribute flying destroy enemy resolve "Plummet 1" -- No target step "Quasiduplicate on archer, destroy one of the Mistbinders" $ do tapForMana "U" (numbered 1 "Highland Lake") tapForMana "U" (numbered 2 "Highland Lake") withTriggers (cast "UU") "Quasiduplicate 1" with ("Merfolk Mistbinder 2") $ \enemy -> do withStateBasedActions $ forM_ [1..4] $ \n -> do let tokenName = ("Afzocan Archer " <> show n) resolve $ numbered (5 - n) "Quasiduplicate" addArcherCopy tokenName fight tokenName enemy validate enemy $ matchLocation (Opponent, Graveyard) step "Jump-start Quasiduplicate again (w/ Waterknot), destroy merfolk" $ do tapForMana "U" (numbered 3 "Highland Lake") tapForMana "U" (numbered 4 "Highland Lake") withTriggers (jumpstart "UU" "Waterknot") "Quasiduplicate 1" with (numbered 1 "Merfolk Mistbinder") $ \enemy -> do withStateBasedActions $ forM_ [1..2] $ \n -> do let tokenName = ("Afzocan Archer " <> show n) resolve $ numbered (6 - n) "Quasiduplicate" addArcherCopy tokenName fight tokenName enemy validate enemy $ matchLocation (Opponent, Graveyard) with "Kopala, Warden of Waves" $ \enemy -> do withStateBasedActions $ forM_ [3..4] $ \n -> do let tokenName = numbered n "Afzocan Archer" resolve $ numbered (6 - n) "Quasiduplicate" addArcherCopy tokenName fight tokenName enemy validate enemy $ matchLocation (Opponent, Graveyard) forM_ [5] $ \n -> do let tokenName = numbered n "Afzocan Archer" resolve $ numbered (6 - n) "Quasiduplicate" addArcherCopy tokenName step "Torgaar, sacrificing archers to reduce cost" $ do tapForMana "B" (numbered 3 "Submerged Boneyard") tapForMana "B" (numbered 4 "Submerged Boneyard") sacrifice $ numbered 1 "Afzocan Archer" sacrifice $ numbered 2 "Afzocan Archer" sacrifice $ numbered 3 "Afzocan Archer" cast "BB" "Torgaar, Famine Incarnate" resolve "Torgaar, Famine Incarnate" setLife Opponent 10 step "Attack with Adeliz and initial archer for lethal" $ do attackWith ["Adeliz, the Cinder Wind", "Afzocan Archer"] combatDamage [] "Adeliz, the Cinder Wind" combatDamage [] "Afzocan Archer" validateLife Opponent 0 formatter :: Int -> Formatter formatter _ = attributeFormatter $ do attribute "mana" $ countCards (matchAttribute "land" <> missingAttribute "tapped") attribute "storm" $ countValue "storm" attribute "adeliz" $ view cardStrength <$> requireCard "Adeliz, the Cinder Wind" mempty attribute "enemies" $ countCards (matchLocation (Opponent, Play)) triggerStorm :: (Int -> GameMonad ()) -> GameMonad () triggerStorm action = do maybeStorm <- use $ counters . at "storm" case maybeStorm of Nothing -> throwError "No counter in state: storm" Just c -> forM [1..c-1] $ \n -> action n return ()