haskellscrabble-0.1.0.0: src/Wordify/Rules/Game/Internal.hs
module Wordify.Rules.Game.Internal (updateGame, Game(Game),
GameStatus(InProgress, Finished),
moveNumber,
playerNumber,
currentPlayer,
passes,
nextPlayer,
player1,
player2,
optionalPlayers,
gameStatus,
board,
bag,
pass,
dictionary,
updateHistory,
Move(PlaceTiles, Exchange, Pass),
History(History),
history) where
import Wordify.Rules.Player
import Wordify.Rules.Board
import Wordify.Rules.LetterBag
import Wordify.Rules.Dictionary
import Control.Applicative
import Data.Map
import Wordify.Rules.Pos
import Wordify.Rules.Tile
import Data.Sequence
data Move = PlaceTiles (Map Pos Tile) | Exchange [Tile] | Pass deriving (Eq, Show)
data History = History LetterBag (Seq Move) deriving (Eq, Show)
data GameStatus = InProgress | Finished deriving (Eq, Show)
data Game = Game { player1 :: Player
, player2 :: Player
, optionalPlayers :: Maybe (Player, Maybe Player)
, board :: Board
, bag :: LetterBag
, dictionary :: Dictionary
, currentPlayer :: Player
, playerNumber :: Int
, moveNumber :: Int
, passes :: Int
, gameStatus :: GameStatus
, history :: History }
{-
Updates the game with the new board and letter bag state, and the last player to play's state after replacing their played
tiles with new tiles from the letter bag.
Yields the next game state.
-}
updateGame :: Game -> Player -> Board -> LetterBag -> Game
updateGame game player newBoard newBag =
updatedPlayerGame {board = newBoard, bag = newBag, currentPlayer = newPlayer, playerNumber = newPlayerNum, moveNumber = succ moveNo, passes = 0}
where
updatedPlayerGame = updateCurrentPlayer game player
(newPlayerNum, newPlayer) = nextPlayer game
moveNo = moveNumber game
updateCurrentPlayer :: Game -> Player -> Game
updateCurrentPlayer game player =
case playing of
1 -> game {player1 = player}
2 -> game {player2 = player}
3 -> game {optionalPlayers = (\(_, player4) -> (player, player4)) <$> maybePlayers }
_ -> game {optionalPlayers = (\(player3, _) -> (player3, (Just player))) <$> maybePlayers }
where
playing = playerNumber game
maybePlayers = optionalPlayers game
{- Returns the next player to play. If there are optional players, loops back round to 'player 1' where appropriate. -}
nextPlayer :: Game -> (Int, Player)
nextPlayer game
| (playing == 1) = (2, playr2)
| (playing == 2 || playing == 3) =
maybe ( (1, playr1) ) (\(player3, player4) ->
if (playing == 2) then (3, player3 )
else
case player4 of
Just playr4 -> (4, playr4)
Nothing -> (1, playr1)
) $ maybePlayers
| otherwise = (1, playr1)
where
playing = playerNumber game
playr2 = player2 game
playr1 = player1 game
maybePlayers = optionalPlayers game
pass :: Game -> Game
pass game = game {moveNumber = succ moveNo, playerNumber = playerNo, currentPlayer = player, passes = succ numPasses}
where
(playerNo, player) = nextPlayer game
numPasses = passes game
moveNo = moveNumber game
updateHistory :: Game -> Move -> Game
updateHistory game move = game {history = History originalBag (moveList |> move) }
where
History originalBag moveList = history game