card' abilityGetter cID = to getter
  where getter :: GameState -> Card

        filterFunc (sourceID, Static pred _) = pred sourceID (CardTarget cID)
        filterFunc (sourceID, RecursiveStatic pred _) = pred sourceID (CardTarget cID)

        modFilterFunc (sourceID, Static _ f) = f sourceID cID
        modFilterFunc (sourceID, RecursiveStatic _ f) = f sourceID cID

        modsForCard :: State GameState [CardMod]
        modsForCard = do
          staticAbilities <- abilityGetter
          filtered <- filterM filterFunc staticAbilities
          forM filtered modFilterFunc

        getter state = flip evalState state $ do
          s <- get
          let baseCard = execState applyCounters (s^._card cID)
          mods <- modsForCard
          return $ foldl' (flip applyMod) baseCard mods

        applyCounters :: State Card ()
        applyCounters = do
          card <- get
          forM_ (card^.counters) $ \counter -> case counter of
            (Plus1Plus1, n) -> stats.both += n
            (Minus1Minus1, n) -> stats.both -= n

-- Use this to refer to cards by CardIDs in most cases.
-- It applies all relevant static abilities, until end
-- of turn effects, etc. and then returns the result.
card' abilityGetter cID = to getter
  where getter :: GameState -> Card

        filterFunc (sourceID, Static pred _) = pred sourceID (CardTarget cID)
        filterFunc (sourceID, RecursiveStatic pred _) = pred sourceID (CardTarget cID)

        modFilterFunc (sourceID, Static _ f) = f sourceID cID
        modFilterFunc (sourceID, RecursiveStatic _ f) = f sourceID cID

        modsForCard :: State GameState [CardMod]
        modsForCard = do
          staticAbilities <- abilityGetter
          filtered <- filterM filterFunc staticAbilities
          forM filtered modFilterFunc

        getter state = flip evalState state $ do
          s <- get
          let baseCard = execState applyCounters (s^._card cID)
          mods <- modsForCard
          return $ foldl' (flip applyMod) baseCard mods

        applyCounters :: State Card ()
        applyCounters = do
          card <- get
          forM_ (card^.counters) $ \counter -> case counter of
            (Plus1Plus1, n) -> stats.both += n
            (Minus1Minus1, n) -> stats.both -= n

-- Use this to refer to cards by CardIDs in most cases.
-- It applies all relevant static abilities, until end
-- of turn effects, etc. and then returns the result.
card' abilityGetter cID = to getter
  where getter :: GameState -> Card

        filterFunc (sourceID, Static pred _) = pred sourceID (CardTarget cID)
        filterFunc (sourceID, RecursiveStatic pred _) = pred sourceID (CardTarget cID)

        modFilterFunc (sourceID, Static _ f) = f sourceID cID
        modFilterFunc (sourceID, RecursiveStatic _ f) = f sourceID cID

        modsForCard :: State GameState [CardMod]
        modsForCard = do
          staticAbilities <- abilityGetter
          filtered <- filterM filterFunc staticAbilities
          forM filtered modFilterFunc

        getter state = flip evalState state $ do
          s <- get
          let baseCard = execState applyCounters (s^._card cID)
          mods <- modsForCard
          return $ foldl' (flip applyMod) baseCard mods

        applyCounters :: State Card ()
        applyCounters = do
          card <- get
          forM_ (card^.counters) $ \counter -> case counter of
            (Plus1Plus1, n) -> stats.both += n
            (Minus1Minus1, n) -> stats.both -= n

-- Use this to refer to cards by CardIDs in most cases.
-- It applies all relevant static abilities, until end
-- of turn effects, etc. and then returns the result.