yampa2048-0.1.0.0: src/GameModel.hs
module GameModel ( emptyBoard
, initialGameState
, rotateBoard
, setTile
, tileToInt
, intToTile
, tilesWithCoordinates
, readTile
) where
import System.Random (StdGen)
import Data.List (transpose)
import Control.Applicative ((<$>))
import Types
-- | Given a Board we return a tile which can be found on a given row and
-- column
readTile :: (Row, Column) -> Board -> Tile
readTile (row, column) (Board b) = (b !! row) !! column
-- | Set tile on a given board to a given row and column
setTile :: (Row, Column) -> Board -> Tile -> Board
setTile (row, column) (Board b) tile =
let r = b !! row
nr = take column r ++ [tile] ++ drop (column + 1) r
in Board $ take row b ++ [nr] ++ drop (row + 1) b
-- | Convert a tile to the int it represents. Empty tile is treated like 0
tileToInt :: Tile -> Int
tileToInt tile = case tile of
Number v -> v
Empty -> 0
-- | Convert an int into a tile representing it. 0 is treated like Empty
-- tile
intToTile :: Int -> Tile
intToTile n = case n of
0 -> Empty
_ -> Number n
-- | Convert a board into a list of all tiles with their respective
-- coordinates
tilesWithCoordinates :: Board -> [(Tile, Row, Column)]
tilesWithCoordinates (Board b) = concat
$ zipWith (\rowIndex row -> fmap (\(tile, columnIndex) -> (tile, rowIndex, columnIndex)) row) [0..]
$ fmap (\row -> zip row [0..])
b
-- | Rotate given board clockwise by 90 degrees
rotateBoard :: Board -> Board
rotateBoard (Board b) = Board $ reverse <$> transpose b
-- | A board of empty tiles
emptyBoard :: Board
emptyBoard = Board $ replicate 4 $ replicate 4 Empty
-- | Default starting game state without 2 initial tiles
initialGameState :: StdGen -> GameState
initialGameState g = GameState { board = emptyBoard
, score = 0
, status = InProgress
, gen = g
}