module Board where {- Really only want to export Board, newBoard, copyBlockToBoard, removeCompleteRows, isMoveValid -} import Helpers import qualified Data.Map as M import Data.Maybe (fromJust, isJust, isNothing) import Shape -- A board has a map of Position to Color data Board = Bd { m :: M.Map Position Color, ncol:: Int, nrow:: Int} deriving (Show, Eq) newBoard :: Int -> Int -> Board newBoard x y = Bd M.empty x y copyBlockToBoard :: Block -> Board -> Board copyBlockToBoard block = copySquares (blockPositions block) (typeColor (blockType block)) --See about changing this to a foldl copySquares :: [Position] -> Color -> Board -> Board copySquares [] _ b = b copySquares (p:ps) c b = copySquares ps c (insert p c b) insert :: Position -> Color -> Board -> Board insert p c (Bd m x y) = Bd (M.insert p c m) x y --Returns board and number of lines cleared removeCompleteRows :: Board -> (Board, Int) removeCompleteRows board = foldl removeFullRow (board, 0) [0 .. (nrow board)] removeFullRow :: (Board, Int) -> Int -> (Board, Int) removeFullRow (b, ls) row = if rowIsFull b row then removeFullRow (moveEverythingDown, ls + 1) row else (b, ls) where moveEverythingDown = foldl (moveColumnDown row) b [0 .. (ncol b)] moveColumnDown :: Int -> Board -> Int -> Board moveColumnDown row board col | row <= (nrow board) = moveColumnDown (row + 1) (moveSquare col board row) col | otherwise = board moveSquare :: Int -> Board -> Int -> Board moveSquare x b y = mdelete (x, y + 1) newboard where abvSquare = doLookup (x, y + 1) b :: Maybe Color newboard = if isNothing abvSquare then mdelete (x, y) b else insert (x, y) (fromJust abvSquare) b mdelete :: Position -> Board -> Board mdelete p (Bd m x y) = Bd (M.delete p m) x y rowIsFull :: Board -> Int -> Bool rowIsFull b row = and (map test [0 .. (ncol b)]) where test col = isJust $ doLookup (col, row) b isMoveValid :: Block -> Board -> Bool isMoveValid block board = and (map test blks) where blks = blockPositions block test pos@(x, y) = x >= 0 && x <= (ncol board) && isFree pos isFree pos = Nothing == doLookup pos board checkBelow :: Block -> Board -> Bool checkBelow block board = or (map (stopBelow board) (blockPositions block)) stopBelow :: Board -> Position -> Bool stopBelow b (x, y) = y == 0 || Nothing /= doLookup (x, y - 1) b doLookup :: Position -> Board -> Maybe Color doLookup p@(x,y) (Bd b nc nr) = if x<0 || y <0 || x>nc then error ("Tried to look up " ++ show x ++ "," ++ show y) else M.lookup p b --test :: M.Map (Int, Int) Color --test = M.insert (0,0) Blue $ M.insert (1,0) Blue $ M.empty typeColor :: ShapeType -> Color typeColor O = Red typeColor I = Blue typeColor S = Yellow typeColor Z = Green typeColor L = Purple typeColor J = Cyan typeColor T = Orange