{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeFamilies #-} module Types.GameMode where import Data.Bifunctor (Bifunctor (first)) import Data.Kind (Type) import Display import System.Random.Stateful (Random (randomR), RandomGen) {- | The type of game that is being played. This typeclass carries information about how to check whether a set of elements satisfies the condition for a valid move. For example, in the 'SumTo n' mode, a valid move is a set of elements (Ints) that sums up to 'n'. -} class (Display (Tile t), Show (Tile t), Eq (Tile t), Eq t, Show t) => GameMode t where data Tile t :: Type check :: t -> [Tile t] -> Maybe Int gen :: (RandomGen g) => t -> g -> (Tile t, g) data SumTo = MkSumTo Int deriving (Show, Eq) instance GameMode SumTo where data Tile SumTo = IntTile Int deriving (Eq, Show) check (MkSumTo n) [] = if n == 0 then Just 0 else Nothing check (MkSumTo n) lst = if n == sum (map toInt lst) then Just (length lst) else Nothing where toInt (IntTile a) = a gen (MkSumTo n) = first IntTile . randomR (1, n) instance Display (Tile SumTo) where display (IntTile x) = display x