snorkels-0.2.0.0: src/Snorkels/Play.hs
module Snorkels.Play ( play ) where
import Control.Monad.Loops (iterateUntilM)
import Data.Function
import qualified Data.Map.Strict as Map
import Data.Maybe
import Data.List (partition)
import Snorkels.Types
import qualified Snorkels.Game as G
getCurrentPlayerType :: Game -> PlayerType
getCurrentPlayerType game = (game&playerTypes) Map.! (game¤tPlayer)
playMove :: Game -> Maybe String -> IO Game
playMove game errorMessage = do move <- getMove pt game errorMessage
case move of
Nothing -> return $ G.quit game
Just pos -> case G.move pos game of
Left message -> playMove game $ Just message
Right game -> return game
where pt = getCurrentPlayerType game
playSwitch :: Game -> Maybe String -> IO Game
playSwitch game errorMessage = do pos <- getSwitch pt game errorMessage
case G.switch pos game of
Left message -> playSwitch game $ Just message
Right game -> return game
where pt = getCurrentPlayerType game
playRound :: (Game -> Maybe String -> IO Game) -> Game -> IO Game
playRound playFunc game = do g <- playFunc game Nothing
if G.hasFinished g || ((game¤tPlayer) > (g¤tPlayer))
then return g
else playRound playFunc g
reportWinnerAround :: Game -> IO ()
reportWinnerAround game = case G.getWinner game of
Just winner -> do mapM_ (reportToPT winner) nonlocals
maybe (return ()) (reportToPT winner) (listToMaybe locals)
Nothing -> return ()
where pts = Map.elems $ game&playerTypes
(locals, nonlocals) = partition isLocal pts
reportToPT winner pt = reportWinner pt game winner
play :: Game -> IO Game
play game = do g <- playRound playMove game
-- The first moving round is over, ask for switches
g <- G.makeSwitches <$> playRound playSwitch g
-- Continue until finished
g <- iterateUntilM G.hasFinished (playRound playMove) g
-- The game has now finished
reportWinnerAround g
return g