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

  1. module Datatypes.Unit (Unit(..), map, centeredIn, collidesWith, isOutsideOf, mergeWith) where
  2. import Prelude hiding (map)
  3. import Data.Hashable (Hashable(..))
  4. import qualified Data.List as List
  5. import Data.Set (Set)
  6. import qualified Data.Set as Set
  7. import Datatypes.Cell (Cell)
  8. import Datatypes.Board (Board(..))
  9. import qualified Datatypes.Board as Board
  10. data Unit = Unit { pivot :: Cell, members :: Set Cell } deriving Show
  11. instance Hashable Unit where
  12. hashWithSalt salt unit = hashWithSalt salt (sortedMembers, pivot unit) where
  13. sortedMembers = (List.sort . Set.toList . members) unit
  14. map :: (Cell -> Cell) -> Unit -> Unit
  15. map f (Unit p ms) = Unit (f p) (Set.map f ms)
  16. centeredIn :: Unit -> Board -> Unit
  17. centeredIn u@(Unit _ ms) b = map (\(x, y) -> (x + deltaX, y - unitTop)) u where
  18. yCoords = Set.map (\(x, y) -> y) ms
  19. xCoords = Set.map (\(x, y) -> x) ms
  20. unitTop = Set.findMin yCoords
  21. unitLeft = Set.findMin xCoords
  22. unitRight = Set.findMax xCoords
  23. deltaX = (unitLeft + (Board.width b - unitRight - 1)) `div` 2 - unitLeft
  24. collidesWith :: Unit -> Board -> Bool
  25. collidesWith u b = not . Set.null $ Set.intersection (members u) (Board.filled b)
  26. isOutsideOf :: Unit -> Board -> Bool
  27. isOutsideOf u@(Unit _ ms) b = any isOutside (Set.toList ms) where
  28. isOutside (x, y) = x < 0 || x >= Board.width b || y < 0 || y >= Board.height b
  29. mergeWith :: Unit -> Board -> Board
  30. mergeWith unit board = board { filled = Set.union unitMembers boardFilled } where
  31. unitMembers = members unit
  32. boardFilled = Board.filled board