module Datatypes.Unit (Unit(..), map, centeredIn, collidesWith, isOutsideOf, mergeWith) where import Prelude hiding (map) import Data.Hashable (Hashable(..)) import qualified Data.List as List import Data.Set (Set) import qualified Data.Set as Set import Datatypes.Cell (Cell) import Datatypes.Board (Board(..)) import qualified Datatypes.Board as Board data Unit = Unit { pivot :: Cell, members :: Set Cell } deriving Show instance Hashable Unit where hashWithSalt salt unit = hashWithSalt salt (sortedMembers, pivot unit) where sortedMembers = (List.sort . Set.toList . members) unit map :: (Cell -> Cell) -> Unit -> Unit map f (Unit p ms) = Unit (f p) (Set.map f ms) centeredIn :: Unit -> Board -> Unit centeredIn u@(Unit _ ms) b = map (\(x, y) -> (x + deltaX, y - unitTop)) u where yCoords = Set.map (\(x, y) -> y) ms xCoords = Set.map (\(x, y) -> x) ms unitTop = Set.findMin yCoords unitLeft = Set.findMin xCoords unitRight = Set.findMax xCoords deltaX = (unitLeft + (Board.width b - unitRight - 1)) `div` 2 - unitLeft collidesWith :: Unit -> Board -> Bool collidesWith u b = not . Set.null $ Set.intersection (members u) (Board.filled b) isOutsideOf :: Unit -> Board -> Bool isOutsideOf u@(Unit _ ms) b = any isOutside (Set.toList ms) where isOutside (x, y) = x < 0 || x >= Board.width b || y < 0 || y >= Board.height b mergeWith :: Unit -> Board -> Board mergeWith unit board = board { filled = Set.union unitMembers boardFilled } where unitMembers = members unit boardFilled = Board.filled board