{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE MultiParamTypeClasses #-} module Hanafuda.Game where import Data.Map (Map, empty, fromList) import Hanafuda.Card (Card, Pack, contains, packOfCards, remove) import Hanafuda.Yaku (Score, Points) data Player = Player1 | Player2 deriving (Eq, Ord) next :: Player -> Player next Player1 = Player2 next _ = Player1 data PlayerState = PlayerState { hand :: Pack , meld :: Pack , yakus :: Score } type Players = Map Player PlayerState players :: [Player] players = [Player1, Player2] deal :: [a] -> Map Player a deal = fromList . zip players initPlayers :: [[Card]] -> Players initPlayers = deal . map player where player cards = PlayerState { hand = packOfCards cards , meld = packOfCards [] , yakus = empty } plays :: PlayerState -> Card -> Either String PlayerState plays player@(PlayerState {hand}) card = if hand `contains` card then Right $ player {hand = remove hand card} else Left "You don't have this card" data Move = Play Card | Capture (Card, Card) | Choose Card | KoiKoi Bool type Scores = Map Player Points class Game a b where play :: a -> Move -> Either String b