-- | Types and functions for manipulating tiles.
module Hs2048.Tile
    ( Tile
    , empty
    , parse
    , rank
    , render
    , score
    ) where

{- |
    Represents a tile on the game board. Can be empty (@Nothing@) or can have a
    value (@Just n@). By convention, a tile's value is always a power of 2.
-}
type Tile = Maybe Int

{- |
    Returns the empty tile.

    >>> empty
    Nothing
-}
empty :: Tile
empty = Nothing

{- |
    Parses a string as a tile. This is the inverse of 'render'.

    >>> parse "-"
    Nothing
    >>> parse "2"
    Just 2
-}
parse :: String -> Tile
parse "-" = Nothing
parse s = Just (read s)

{- |
    Calculates the rank of a tile.

    >>> rank Nothing
    0
    >>> rank (Just 2)
    1
    >>> rank (Just 2048)
    11
-}
rank :: Tile -> Int
rank Nothing = 0
rank (Just n) = floor (logBase b n')
  where
    b = 2 :: Double
    n' = fromIntegral n

{- |
    Renders a tile as a string. This is the inverse of 'parse'.

    >>> render Nothing
    "-"
    >>> render (Just 2)
    "2"
-}
render :: Tile -> String
render Nothing = "-"
render (Just n) = show n

{- |
    Calculates the score of a tile.

    >>> score Nothing
    0
    >>> score (Just 2)
    0
    >>> score (Just 2048)
    20480
-}
score :: Tile -> Int
score Nothing = 0
score t@(Just n) = n * (rank t - 1)