packages feed

swarm-0.4: src/Swarm/Game/Scenario/Topography/Area.hs

{-# LANGUAGE OverloadedStrings #-}

module Swarm.Game.Scenario.Topography.Area where

import Data.Int (Int32)
import Data.List qualified as L
import Data.Maybe (listToMaybe)
import Linear (V2 (..))
import Swarm.Game.Location

data AreaDimensions = AreaDimensions
  { rectWidth :: Int32
  , rectHeight :: Int32
  }

renderRectDimensions :: AreaDimensions -> String
renderRectDimensions (AreaDimensions w h) =
  L.intercalate "x" $ map show [w, h]

invertY :: V2 Int32 -> V2 Int32
invertY (V2 x y) = V2 x (-y)

-- | Incorporates an offset by -1, since the area is
-- "inclusive" of the lower-right coordinate.
-- Inverse of "cornersToArea".
upperLeftToBottomRight :: AreaDimensions -> Location -> Location
upperLeftToBottomRight (AreaDimensions w h) upperLeft =
  upperLeft .+^ displacement
 where
  displacement = invertY $ subtract 1 <$> V2 w h

-- | Converts the displacement vector between the two
-- diagonal corners of the rectangle into an "AreaDimensions" record.
-- Adds one to both dimensions since the corner coordinates are "inclusive".
-- Inverse of "upperLeftToBottomRight".
cornersToArea :: Location -> Location -> AreaDimensions
cornersToArea upperLeft lowerRight =
  AreaDimensions x y
 where
  V2 x y = (+ 1) <$> invertY (lowerRight .-. upperLeft)

isEmpty :: AreaDimensions -> Bool
isEmpty (AreaDimensions w h) = w == 0 || h == 0

getAreaDimensions :: [[a]] -> AreaDimensions
getAreaDimensions cellGrid =
  AreaDimensions w h
 where
  w = fromIntegral $ maybe 0 length $ listToMaybe cellGrid -- column count
  h = fromIntegral $ length cellGrid -- row count