{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ConstraintKinds #-} module Hanafuda.KoiKoi.Game ( Action(..) , Game(..) , Environment , Mode(..) , Move(..) , On(..) , Over(..) , Source(..) , Step(..) , end , setPlayer , stop ) where import Control.Monad.Except (MonadError) import Control.Monad.IO.Class (MonadIO) import Control.Monad.Writer (MonadWriter) import Hanafuda (Card, Flower, Pack) import Hanafuda.Player (Players, Player, Scores, set) import Hanafuda.KoiKoi.Yaku (Score) data Mode = FirstAt Int | WholeYear deriving (Show) data Move = Play Card | Capture (Card, Card) | Choose Card | KoiKoi Bool data Step = ToPlay | Turned Card | Scored deriving (Show) data Source = Hand | Deck deriving (Show) data Action = Action { source :: Source , played :: Card , captures :: Maybe Card } deriving (Show) type Environment m = (MonadIO m, MonadError String m, MonadWriter [Action] m) data On player = On_ { mode :: Mode , scores :: Scores player , month :: Flower , players :: Players player Score , playing :: player , winning :: player , oyake :: player , deck :: [Card] , river :: Pack , step :: Step , trick :: [Card] } deriving (Show) data Over player = Over_ { finalScores :: Scores player } deriving (Show) data Game player = Over (Over player) | On (On player) deriving (Show) setPlayer :: Ord player => On player -> Player player Score -> On player setPlayer on@(On_ {players, playing}) player = on {players = set playing player players} end :: Monad m => On player -> m (Game player) end (On_ {scores}) = return . Over $ Over_ {finalScores = scores} stop :: Monad m => On player -> m (Game player) stop = return . On