snorkels-0.2.0.0: src/Snorkels/Types.hs
module Snorkels.Types ( Position
, Snorkel (..)
, Player
, Group (..)
, Piece (..)
, Game (..)
, isSnorkel
, getPlayer
, isBlocking
, PlayerType (..)
) where
import qualified Data.Bimap as Bimap
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
-- | Some (x, y) coordinate on the board
type Position = (Int, Int)
-- | Some player's pieces' color
data Snorkel = Green | Purple | Red | Yellow | Cyan
deriving (Show, Eq, Ord, Enum, Read)
-- | Each player has a distinctive color
type Player = Snorkel
-- |
-- An horizontally or vertically connected group of 'Snorkel's that belong to
-- the same 'Player'
data Group = Group { positions :: Set.Set Position
, player :: Player
} deriving (Show, Eq, Ord)
-- |
-- Any type of piece on the board: either a 'Snorkel' or a 'Stone'
data Piece = Snorkel Snorkel | Stone
deriving (Show, Eq)
-- This is just a shortcut for (isJust . getPlayer)
-- | Check whether the 'Piece' is a 'Snorkel'
isSnorkel :: Piece -> Bool
isSnorkel Stone = False
isSnorkel _ = True
-- | Get the player owning the 'Piece' or 'Nothing' if the piece is a 'Stone'
getPlayer :: Piece -> Maybe Player
getPlayer Stone = Nothing
getPlayer (Snorkel p) = Just p
-- |
-- Check whether the contents of a given 'Position' on the board suppose a block
-- for a given 'Player'. Only 'Stone's and 'Snorkel's from a different 'Player'
-- suppose a block.
isBlocking :: Player -> Maybe Piece -> Bool
isBlocking _ Nothing = False
isBlocking player (Just piece) = maybe True (/= player) (getPlayer piece)
data PlayerType = PlayerType {
-- | Maybe print an error message and get a position to move to or a quit.
getMove :: Game -> Maybe String -> IO (Maybe Position)
-- | Maybe print an error message and get a player to switch to.
, getSwitch :: Game -> Maybe String -> IO Player
-- | Report the player about the winner of the game
, reportWinner :: Game -> Player -> IO ()
-- | Only one of the playertypes marked as local is notified about the
-- winner. FIXME: There must be a cleverer way of doing this.
, isLocal :: Bool
}
data Game = Game {
-- | Only 'Position's occupied by 'Piece's are here
pieces :: Map.Map Position Piece
-- | Width and height limits of the board
, boardSize :: (Int, Int)
-- | List of 'Player's that didn't 'Quit'
, playerTypes :: Map.Map Player PlayerType
-- | 'Player' that plays next
, currentPlayer :: Player
-- | Map of what each player chooses to be when asked to switch
, switches :: Bimap.Bimap Player Player
}