packages feed

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
                               }