2018-03-05 16:29:10 +01:00
|
|
|
{-# 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
|
|
|
|
}
|
|
|
|
|
2018-03-07 17:32:28 +01:00
|
|
|
newtype Month = Month (Either Over On)
|
|
|
|
|
|
|
|
go :: On -> Month
|
|
|
|
go = Month . Right
|
2018-03-05 16:29:10 +01:00
|
|
|
|
|
|
|
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
|
2018-03-07 17:32:28 +01:00
|
|
|
players = initPlayers [hand1, hand2]
|
2018-03-05 16:29:10 +01:00
|
|
|
|
|
|
|
next :: On -> IO On
|
2018-03-07 17:32:28 +01:00
|
|
|
next (On {flower, oyake}) = do
|
2018-03-05 16:29:10 +01:00
|
|
|
shuffled <- shuffle cards
|
2018-03-07 17:32:28 +01:00
|
|
|
return $ (new (Game.next oyake) shuffled) {flower = succ flower}
|
2018-03-05 16:29:10 +01:00
|
|
|
|
|
|
|
instance Game On Month where
|
2018-03-07 17:32:28 +01:00
|
|
|
play on@(On {flower, day, playing, players, stock = next : moreStock}) move =
|
2018-03-05 16:29:10 +01:00
|
|
|
fmap after $ play day move
|
|
|
|
where
|
|
|
|
after (Day {step = Day.Over True, player = PlayerState {yakus}}) =
|
2018-03-07 17:32:28 +01:00
|
|
|
Month . Left $ Over {winner = playing, score = foldl (+) 0 yakus}
|
2018-03-05 16:29:10 +01:00
|
|
|
after (Day {step = Day.Over False, player, river}) =
|
|
|
|
let otherPlayer = Game.next playing in
|
2018-03-07 17:32:28 +01:00
|
|
|
go $ on {
|
2018-03-05 16:29:10 +01:00
|
|
|
players = insert playing player players
|
|
|
|
, playing = otherPlayer
|
|
|
|
, day = (Day.new river (players ! otherPlayer) next) { month = flower }
|
|
|
|
, stock = moreStock
|
|
|
|
}
|
2018-03-07 17:32:28 +01:00
|
|
|
after newDay = go $ on {day = newDay}
|