Created
January 17, 2023 16:17
-
-
Save patrl/9f013f6ac3270d4fc75dfe9ef25e7df3 to your computer and use it in GitHub Desktop.
Recursive symmetric shadowcasting by quadrant in Haskell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
computeQ :: TileMap -> Transform -> Slope -> Slope -> Int -> Visible () | |
computeQ m t s e y = do | |
let xmin = roundTiesUp (fromIntegral y * s) -- compute the initial x coordinate bounded by the starting slope | |
let xmax = roundTiesDown (fromIntegral y * e) -- compute the ending x coordinate bounded by the ending slope | |
let xys = (coord . (,y)) <$> [xmin..xmax] -- create a list of coordinates to recurse through by pairing xs with the depth | |
-- a helper function to recurse through a list of coordinates, and potentially create branching row computations | |
-- the first argument is a Maybe Bool which tracks whether the previous coordinate was a wall | |
-- Nothing indicates that there was no previous coordinate (we're at the beginning of the list) | |
-- s indicates the starting slope; this can change as the recursion proceeds. | |
-- xys indicates the list of coordinates | |
go Nothing s xys where | |
----------------------------------------- | |
-- definition of row recursion follows -- | |
----------------------------------------- | |
-- if the last tile in the row is visible, then continue onto the next row, otherwise break the recursion | |
go final s' [] = unless (final == Just True) $ do | |
computeQ m t s' e (y + 1) | |
-- case 1: no previous tile. | |
-- this indicates that we're at the beginning of a row recursion | |
go Nothing s' (c:cs) = do | |
let w = isWall m (t c) -- w is a boolean which indicates whether the current focus is a wall (and therefore invisible) | |
when (w || isSymmetric s' e c) $ do -- when the current tile is a wall or symmetric... | |
addToVis (t c) -- ...add the tranformed coordinate it to the visible coordinates | |
go (Just w) s' cs -- now, recurse through the remainder of the wall, setting the Maybe Bool to depend on whether the focus is a wall | |
-- case 2: there is a previous tile, whether it was a wall or not is indicated by w' | |
go (Just w') s' (c:cs) = do | |
let w = isWall m (t c) -- let w indicate the wallhood os te current focus | |
when (w || isSymmetric s' e c) $ do -- when the current tile is a wall or symmetric... | |
addToVis (t c) -- ...add the transformed coordinate to the visible coordinates | |
if -- the next action depends on wallhood of the current and previous tiles | |
| (w' && not w) -> -- if the previous tile is a wall, and the current tile isn't a wall... | |
go (Just w) (slope c) cs -- continue the recursion through the row, but adjust the start slope to brush the prev tile | |
| (not w' && w) -> do -- if the previous tile isn't a wall, but the current tile is a wall | |
computeQ m t s' (slope c) (y + 1) -- start a new branching computation on the next row, with an adjusted end slope | |
go (Just w) s' cs -- continue recursing through the row | |
| otherwise -> | |
go (Just w) s' cs -- in other circumstances, continue recursing through the row | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment