module Wordify.Rules.Board(Board, allSquares, emptyBoard, placeTile, occupiedSquareAt,
lettersAbove, lettersBelow, lettersLeft, lettersRight, unoccupiedSquareAt) where
import Wordify.Rules.Square
import Wordify.Rules.Pos
import Data.Maybe
import Wordify.Rules.Tile
import qualified Data.Map as Map
import Control.Monad
import Data.Sequence as Seq
import Wordify.Rules.Board.Internal
import Control.Applicative
allSquares :: Board -> [(Pos, Square)]
allSquares (Board squares) = Map.toList squares
placeTile :: Board -> Tile -> Pos -> Maybe Board
placeTile board tile pos =
(\sq -> insertSquare board pos (putTileOn sq tile)) <$> unoccupiedSquareAt board pos
insertSquare :: Board -> Pos -> Square -> Board
insertSquare (Board squares) pos square = Board $ Map.insert pos square squares
squareAt :: Board -> Pos -> Maybe Square
squareAt (Board squares) = flip Map.lookup squares
unoccupiedSquareAt :: Board -> Pos -> Maybe Square
unoccupiedSquareAt board pos =
squareAt board pos >>= (\sq -> if isOccupied sq then Nothing else Just sq)
occupiedSquareAt :: Board -> Pos -> Maybe Square
occupiedSquareAt board pos = squareAt board pos >>= squareIfOccupied
lettersAbove :: Board -> Pos -> Seq (Pos,Square)
lettersAbove board pos = walkFrom board pos above
lettersBelow :: Board -> Pos -> Seq (Pos,Square)
lettersBelow board pos = Seq.reverse $ walkFrom board pos below
lettersLeft :: Board -> Pos -> Seq (Pos,Square)
lettersLeft board pos = Seq.reverse $ walkFrom board pos left
lettersRight :: Board -> Pos -> Seq (Pos,Square)
lettersRight board pos = walkFrom board pos right
walkFrom :: Board -> Pos -> (Pos -> Maybe Pos) -> Seq (Pos,Square)
walkFrom board pos direction = maybe mzero (\(next,sq) ->
(next, sq) <| walkFrom board next direction) neighbourPos
where
neighbourPos = direction pos >>= \nextPos -> occupiedSquareAt board nextPos >>=
\sq -> return (nextPos, sq)
emptyBoard :: Board
emptyBoard = Board (Map.fromList posSquares)
where
layout =
[["TW","N","N","DL","N","N","N","TW","N","N","N","DL","N","N","TW"]
,["N","DW","N","N","N","TL","N","N","N","TL","N","N","N","DW","N"]
,["N","N","DW","N","N","N","DL","N","DL","N","N","N","DW","N","N"]
,["DL","N","N","DW","N","N","N","DL","N","N","N","DW","N","N","DL"]
,["N","N","N","N","DW","N","N","N","N","N","DW","N","N","N","N"]
,["N","TL","N","N","N","TL","N","N","N","TL","N","N","N","TL","N"]
,["N","N","DL","N","N","N","DL","N","DL","N","N","N","DL","N","N"]
,["TW","N","N","DL","N","N","N","DW","N","N","N","DL","N","N","TW"]
,["N","N","DL","N","N","N","DL","N","DL","N","N","N","DL","N","N"]
,["N","TL","N","N","N","TL","N","N","N","TL","N","N","N","TL","N"]
,["N","N","N","N","DW","N","N","N","N","N","DW","N","N","N","N"]
,["DL","N","N","DW","N","N","N","DL","N","N","N","DW","N","N","DL"]
,["N","N","DW","N","N","N","DL","N","DL","N","N","N","DW","N","N"]
,["N","DW","N","N","N","TL","N","N","N","TL","N","N","N","DW","N"]
,["TW","N","N","DL","N","N","N","TW","N","N","N","DL","N","N","TW"]]
squares = (map . map) toSquare layout
columns = Prelude.zip [1..15] squares
labeledSquares= concatMap (uncurry columnToMapping) columns
columnToMapping columnNo columnSquares = Prelude.zipWith (\sq y -> ((columnNo,y),sq)) columnSquares [1..15]
posSquares = mapMaybe (\((x,y), sq) -> fmap (\pos -> (pos, sq)) (posAt (x,y))) labeledSquares
toSquare :: String -> Square
toSquare "DL" = DoubleLetter Nothing
toSquare "TL" = TripleLetter Nothing
toSquare "DW" = DoubleWord Nothing
toSquare "TW" = TripleWord Nothing
toSquare _ = Normal Nothing