2018-03-05 16:29:10 +01:00
|
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
|
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
|
|
|
{-# LANGUAGE FlexibleInstances #-}
|
|
|
|
module Hanafuda.Year where
|
|
|
|
|
|
|
|
import Hanafuda.Card (Flower(Paulownia), cards, shuffle)
|
2018-03-07 17:32:28 +01:00
|
|
|
import Hanafuda.Month (Month(..), flower, next, score, winner)
|
2018-03-05 16:29:10 +01:00
|
|
|
import qualified Hanafuda.Month as Month (On(..), Over(..), new)
|
2018-03-07 17:32:28 +01:00
|
|
|
import Hanafuda.Game (Game(..), Player(Player1), Scores, deal)
|
|
|
|
import Data.Map (Map, insert, (!))
|
2018-03-05 16:29:10 +01:00
|
|
|
import System.Random (StdGen)
|
|
|
|
|
|
|
|
data Mode = FirstAt Int | WholeYear
|
|
|
|
|
|
|
|
data On = On {
|
|
|
|
mode :: Mode
|
|
|
|
, month :: Month.On
|
|
|
|
, scores :: Scores
|
|
|
|
}
|
|
|
|
data Over = Over {
|
|
|
|
finalScores :: Scores
|
|
|
|
}
|
|
|
|
|
2018-03-07 17:32:28 +01:00
|
|
|
newtype Year = Year (Either Over On)
|
2018-03-05 16:29:10 +01:00
|
|
|
|
2018-03-07 17:32:28 +01:00
|
|
|
go :: On -> IO Year
|
|
|
|
go = return . Year . Right
|
|
|
|
|
|
|
|
new :: Mode -> IO Year
|
2018-03-05 16:29:10 +01:00
|
|
|
new mode = do
|
|
|
|
shuffled <- shuffle cards
|
2018-03-07 17:32:28 +01:00
|
|
|
go $ On {
|
2018-03-05 16:29:10 +01:00
|
|
|
mode
|
|
|
|
, month = Month.new Player1 shuffled
|
2018-03-07 17:32:28 +01:00
|
|
|
, scores = deal $ cycle [0]
|
2018-03-05 16:29:10 +01:00
|
|
|
}
|
|
|
|
|
2018-03-07 17:32:28 +01:00
|
|
|
consolidate :: On -> Player -> Int -> IO Year
|
|
|
|
consolidate on@(On {mode, month, scores}) winner score =
|
2018-03-05 16:29:10 +01:00
|
|
|
case mode of
|
2018-03-07 17:32:28 +01:00
|
|
|
FirstAt n | n <= newScore -> stop
|
2018-03-05 16:29:10 +01:00
|
|
|
FirstAt n -> continue
|
2018-03-07 17:32:28 +01:00
|
|
|
WholeYear | flower month == Paulownia -> stop
|
2018-03-05 16:29:10 +01:00
|
|
|
WholeYear -> continue
|
|
|
|
where
|
|
|
|
newScore = scores ! winner + score
|
|
|
|
newScores = insert winner newScore scores
|
2018-03-07 17:32:28 +01:00
|
|
|
stop = return . Year . Left $ Over {finalScores = newScores}
|
2018-03-05 16:29:10 +01:00
|
|
|
continue = do
|
|
|
|
nextMonth <- next month
|
2018-03-07 17:32:28 +01:00
|
|
|
go $ on {scores = newScores, month = nextMonth}
|
2018-03-05 16:29:10 +01:00
|
|
|
|
2018-03-07 17:32:28 +01:00
|
|
|
instance Game On (IO Year) where
|
|
|
|
play on@(On {mode, month}) move =
|
2018-03-05 16:29:10 +01:00
|
|
|
fmap after $ play month move
|
|
|
|
where
|
2018-03-07 17:32:28 +01:00
|
|
|
after (Month (Left (Month.Over {winner, score}))) = consolidate on winner score
|
|
|
|
after (Month (Right newMonth)) = go $ on {month = newMonth}
|