combatDamage :: StateT GameState IO ()
combatDamage = do
  s <- get
  blockerList <- mapM lookupCardPair (s^.blockers)
  let damageCreatures :: StateT GameState IO ()
      damageCreatures =
        mapM_ damageCreature (s^.blockers)
--        foldl (\s stats -> execState (damageCreature stats) s) state (s^.blockers)
      damageDefender defender state = foldM (damageDefender' defender) state attackerList
      damageDefender' :: PlayerID -> GameState -> Card -> IO GameState
      damageDefender' defender state attacker = flip execStateT state $
        when (attacker^.cardID `notElem` state^..blockers.traversed._2) $ do
          when (attacker^.dealsCombatDamage) $
            damagePlayer defender (attacker^.stats._1)
          when (Lifelink `elem` attacker^.attributes) $
            gainLife (s^.currentPlayerID) (attacker^.stats._1)
      attackerID = s^.currentPlayerID
      attackerList = map (\c->s^.card c) (s^.attackers)
  damageCreatures
  state' <- get >>= (liftIO . damageDefender (1-attackerID))
  put state'
  removeDeadCreatures
  blockers .= []
  attackers .= []
combatDamage :: StateT GameState IO ()
combatDamage = do
  s <- get
  blockerList <- mapM lookupCardPair (s^.blockers)
  let damageCreatures :: StateT GameState IO ()
      damageCreatures =
        mapM_ damageCreature (s^.blockers)
--        foldl (\s stats -> execState (damageCreature stats) s) state (s^.blockers)
      damageDefender defender state = foldM (damageDefender' defender) state attackerList
      damageDefender' :: PlayerID -> GameState -> Card -> IO GameState
      damageDefender' defender state attacker = flip execStateT state $
        when (attacker^.cardID `notElem` state^..blockers.traversed._2) $ do
          when (attacker^.dealsCombatDamage) $
            damagePlayer defender (attacker^.stats._1)
          when (Lifelink `elem` attacker^.attributes) $
            gainLife (s^.currentPlayerID) (attacker^.stats._1)
      attackerID = s^.currentPlayerID
      attackerList = map (\c->s^.card c) (s^.attackers)
  damageCreatures
  state' <- get >>= (liftIO . damageDefender (1-attackerID))
  put state'
  removeDeadCreatures
  blockers .= []
  attackers .= []
combatDamage = do
  s <- get
  blockerList <- mapM lookupCardPair (s^.blockers)
  let damageCreatures :: StateT GameState IO ()
      damageCreatures =
        mapM_ damageCreature (s^.blockers)
--        foldl (\s stats -> execState (damageCreature stats) s) state (s^.blockers)
      damageDefender defender state = foldM (damageDefender' defender) state attackerList
      damageDefender' :: PlayerID -> GameState -> Card -> IO GameState
      damageDefender' defender state attacker = flip execStateT state $
        when (attacker^.cardID `notElem` state^..blockers.traversed._2) $ do
          when (attacker^.dealsCombatDamage) $
            damagePlayer defender (attacker^.stats._1)
          when (Lifelink `elem` attacker^.attributes) $
            gainLife (s^.currentPlayerID) (attacker^.stats._1)
      attackerID = s^.currentPlayerID
      attackerList = map (\c->s^.card c) (s^.attackers)
  damageCreatures
  state' <- get >>= (liftIO . damageDefender (1-attackerID))
  put state'
  removeDeadCreatures
  blockers .= []
  attackers .= []