You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

42 lines
1.5 KiB

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