boardgame-0.0.0.1: executable/Y.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Y where
import Prelude hiding (lookup)
import Data.Map (
Map
, elems
, keys
, lookup
, member
, adjust
)
import Boardgame (
Player(..)
, Position(..)
, PositionalGame(..)
, mapPosition
, takeEmptyMakeMove
, nextPlayer
, symmetric
, player1WinsWhen
)
import Boardgame.ColoredGraph (
ColoredGraph
, values
, anyConnections
, mapValues
, filterValues
, filterG
, triHexGraph
)
#ifdef WASM
import Data.Aeson (ToJSON(..))
#endif
-------------------------------------------------------------------------------
-- * Y
-------------------------------------------------------------------------------
newtype Y = Y (ColoredGraph (Int, Int) Position (Int, Int))
instance Show Y where
show (Y b) = show b
#ifdef WASM
instance ToJSON Y where
toJSON (Y b) = toJSON b
#endif
instance PositionalGame Y (Int, Int) where
positions (Y b) = values b
getPosition (Y b) c = fst <$> lookup c b
setPosition (Y b) c p = if member c b
then Just $ Y $ adjust (\(_, xs) -> (p, xs)) c b
else Nothing
makeMove = takeEmptyMakeMove
gameOver (Y b) = criterion b
where
criterion =
-- Here we say that in any position where one player wins,
-- the other player would win instead if the pieces were swapped.
symmetric (mapValues $ mapPosition nextPlayer) $
player1WinsWhen $ anyConnections (==3) [side1, side2, side3] . filterValues (== Occupied Player1)
dirs :: [(Int, Int)]
dirs =
[ (1, 0)
, (1, -1)
, (0, -1)
, (-1, 0)
, (-1, 1)
, (0, 1)
]
emptyNeighbour x = keys $ filterG (notElem x . elems . snd) b
side1 = emptyNeighbour $ dirs !! 0
side2 = emptyNeighbour $ dirs !! 2
side3 = emptyNeighbour $ dirs !! 4
emptyY :: Int -> Y
emptyY = Y . triHexGraph