75 lines
1.9 KiB
Haskell
75 lines
1.9 KiB
Haskell
module KoiKoi where
|
|
|
|
import CCard
|
|
import Data.Bits (popCount, (.&.), shift, testBit)
|
|
import Data.Map (Map, empty, insert, unionWith)
|
|
|
|
data Yaku =
|
|
Goko
|
|
| Shiko
|
|
| AmeShiko
|
|
| Sanko
|
|
| InoShikaCho
|
|
| Tane
|
|
| Akatan
|
|
| Aotan
|
|
| Tan
|
|
| Kasu
|
|
| TsukimiZake
|
|
| HanamiZake
|
|
| TsukiFuda
|
|
deriving (Show)
|
|
type Points = Int
|
|
type Score = Pack -> Maybe (Yaku, Points)
|
|
|
|
data Player = Player {
|
|
hand :: Pack
|
|
, captured :: Pack
|
|
, scored :: Map Yaku Points
|
|
}
|
|
|
|
data State = State {
|
|
players :: (Player, Player)
|
|
, river :: Pack
|
|
, deck :: [ Card ]
|
|
, month :: Flower
|
|
, turn :: Bool
|
|
}
|
|
|
|
has :: Pack -> (Yaku, Points) -> (Pack, Score)
|
|
has pack points =
|
|
(pack, \p -> if p == pack then Just points else Nothing)
|
|
|
|
moreThan :: Int -> Pack -> Yaku -> (Pack, Score)
|
|
moreThan count pack yaku =
|
|
(pack, (\n -> if n > 0 then Just (yaku, n) else Nothing) . ($count) . (-) . popCount)
|
|
|
|
hikari :: (Pack, Score)
|
|
hikari = (lights, \p -> rate (popCount p) (p `contains` RainMan))
|
|
where
|
|
rate 5 _ = Just (Goko, 10)
|
|
rate 4 hasRainMan = if hasRainMan then Just (AmeShiko, 7) else Just (Shiko, 8)
|
|
rate n hasRainMan = if not hasRainMan && n > 2 then Just (Sanko, 5) else Nothing
|
|
|
|
tsukiFuda :: Flower -> (Pack, Score)
|
|
tsukiFuda flower = has (0xf `shift` (fromEnum flower * 4)) (TsukiFuda, 8)
|
|
|
|
index :: (Pack, Score) -> Map Card [Score]
|
|
index (pack, score) =
|
|
foldl (\map card ->
|
|
if testBit pack $ fromEnum card then insert card [score . (.&.) pack] map else map
|
|
) empty cards
|
|
|
|
yakus :: Map Card [Score]
|
|
yakus = foldl (\map -> unionWith (++) map . index) empty [
|
|
hikari
|
|
, has inoshikacho (InoShikaCho, 5)
|
|
, moreThan 4 animals Tane
|
|
, has poetry (Akatan, 5)
|
|
, has blue (Aotan, 5)
|
|
, moreThan 4 ribbons Tan
|
|
, moreThan 9 plain Kasu
|
|
, has (set [SakeCup, FullMoon]) (TsukimiZake, 5)
|
|
, has (set [SakeCup, CampCurtain]) (HanamiZake, 5)
|
|
]
|