lib/src/Hanafuda/Month.hs

68 lines
2.0 KiB
Haskell

{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Hanafuda.Month where
import Hanafuda.Card (Card, Flower(Pine), cards, shuffle, packOfCards)
import Hanafuda.Day (Day(..))
import qualified Hanafuda.Day as Day (Step(Over), next, new)
import Hanafuda.Game (Game(..), Move, Player, Players, PlayerState(..), initPlayers)
import qualified Hanafuda.Game as Game (next)
import Data.Map ((!), insert)
import Control.Monad.State (replicateM, runState, state)
data On = On {
flower :: Flower
, players :: Players
, day :: Day
, playing :: Player
, lastScored :: Player
, oyake :: Player
, stock :: [Card]
}
data Over = Over {
winner :: Player
, score :: Int
}
newtype Month = Month (Either Over On)
go :: On -> Month
go = Month . Right
new :: Player -> [Card] -> On
new playing shuffled =
On {
flower = Pine
, players
, day = Day.new (packOfCards river) (players ! playing) next
, playing
, lastScored = playing
, oyake = playing
, stock
}
where
take8 = state $ splitAt 8
([hand1, hand2, river], next:stock) = runState (replicateM 3 take8) shuffled
players = initPlayers [hand1, hand2]
next :: On -> IO On
next (On {flower, oyake}) = do
shuffled <- shuffle cards
return $ (new (Game.next oyake) shuffled) {flower = succ flower}
instance Game On Month where
play on@(On {flower, day, playing, players, stock = next : moreStock}) move =
fmap after $ play day move
where
after (Day {step = Day.Over True, player = PlayerState {yakus}}) =
Month . Left $ Over {winner = playing, score = foldl (+) 0 yakus}
after (Day {step = Day.Over False, player, river}) =
let otherPlayer = Game.next playing in
go $ on {
players = insert playing player players
, playing = otherPlayer
, day = (Day.new river (players ! otherPlayer) next) { month = flower }
, stock = moreStock
}
after newDay = go $ on {day = newDay}