-- | Rectangular areas of levels and their basic operations. module Game.LambdaHack.Server.DungeonGen.Area ( Area, toArea, fromArea, trivialArea, grid, shrink ) where import Data.Binary import Game.LambdaHack.Common.Point -- | The type of areas. The bottom left and the top right points. data Area = Area !X !Y !X !Y deriving Show -- | Checks if it's an area with at least one field. toArea :: (X, Y, X, Y) -> Maybe Area toArea (x0, y0, x1, y1) = if x0 <= x1 && y0 <= y1 then Just $ Area x0 y0 x1 y1 else Nothing fromArea :: Area -> (X, Y, X, Y) fromArea (Area x0 y0 x1 y1) = (x0, y0, x1, y1) trivialArea :: Point -> Area trivialArea (Point x y) = Area x y x y -- | Divide uniformly a larger area into the given number of smaller areas -- overlapping at the edges. grid :: (X, Y) -> Area -> [(Point, Area)] grid (nx, ny) (Area x0 y0 x1 y1) = let xd = x1 - x0 -- not +1, because we need overlap yd = y1 - y0 in [ (Point x y, Area (x0 + xd * x `div` nx) (y0 + yd * y `div` ny) (x0 + xd * (x + 1) `div` nx) (y0 + yd * (y + 1) `div` ny)) | x <- [0..nx-1], y <- [0..ny-1] ] -- | Enlarge (or shrink) the given area on all fours sides by the amount. shrink :: Area -> Maybe Area shrink (Area x0 y0 x1 y1) = toArea (x0 + 1, y0 + 1, x1 - 1, y1 - 1) instance Binary Area where put (Area x0 y0 x1 y1) = do put x0 put y0 put x1 put y1 get = do x0 <- get y0 <- get x1 <- get y1 <- get return (Area x0 y0 x1 y1)