Generalise pathing, usable with flying creatures

This commit is contained in:
2026-04-02 19:30:44 +01:00
parent c2de804fa9
commit ff903bfb3b
19 changed files with 322 additions and 215 deletions
+33
View File
@@ -2,6 +2,7 @@
module Dodge.Path (
nodesNear,
pointTowardsImpulse,
pointTowardsImpulse',
makePathBetween,
makePathBetweenPs,
obstructPathsCrossing,
@@ -10,6 +11,7 @@ module Dodge.Path (
snapToGrid,
pairsToIncGraph,
getEdgesCrossing,
pathEdgeObstructed,
) where
import Dodge.WorldEvent.ThingsHit
@@ -60,15 +62,38 @@ makePathUsing t s e w = do
. IM.filter (^. seObstacles . to t) $ w ^?! cWorld . incGraph . ix i
getn i = w ^?! cWorld . incNode . ix i
makePathUsing' :: (Point2 -> Point2 -> World -> Bool)
-> (Set.Set EdgeObstacle -> Bool) -> Point2 -> Point2 -> World -> Maybe [Int]
makePathUsing' t1 t2 s e w = do
na <- nodeNear t1 w s
nb <- nodeNear t1 w e
let h i = distance (getn nb) (getn i)
(na :) . snd <$> AS.aStarAssoc getes h (== nb) na
where
getes i = IM.toList
. IM.map (^. seDist)
. IM.filter (^. seObstacles . to t2) $ w ^?! cWorld . incGraph . ix i
getn i = w ^?! cWorld . incNode . ix i
makePathBetween :: Point2 -> Point2 -> World -> Maybe [Int]
makePathBetween = makePathUsing $ not . pathEdgeObstructed
makePathBetween' :: (Point2 -> Point2 -> World -> Bool) -> (Set.Set EdgeObstacle -> Bool)
-> Point2 -> Point2 -> World -> Maybe [Int]
makePathBetween' t1 t2 = makePathUsing' t1 $ t2
pathEdgeObstructed :: Set.Set EdgeObstacle -> Bool
pathEdgeObstructed pe = any (`Set.member` pe) [WallObstacle WallNotAutoOpen, ChasmObstacle]
walkableNodeNear :: World -> Point2 -> Maybe Int
{-# INLINE walkableNodeNear #-}
walkableNodeNear w p = fmap fst . find (flip (isWalkable p) w . snd) $ nodesNear w p
nodeNear :: (Point2 -> Point2 -> World -> Bool) -> World -> Point2 -> Maybe Int
{-# INLINE nodeNear #-}
nodeNear t w p = fmap fst . find (flip (t p) w . snd) $ nodesNear w p
-- where
-- nodesNear = zonesExtract (w ^. incNodeZoning) . snailAround $ zoneOfPoint pnZoneSize p
@@ -87,10 +112,18 @@ smallSnailInt2 =
makePathBetweenPs :: Point2 -> Point2 -> World -> Maybe [Point2]
makePathBetweenPs a b w = fmap (`getNodePos` w) <$> makePathBetween a b w
makePathBetweenPs' :: (Point2 -> Point2 -> World -> Bool) -> (Set.Set EdgeObstacle -> Bool)
->Point2 -> Point2 -> World -> Maybe [Point2]
makePathBetweenPs' t1 t2 a b w = fmap (`getNodePos` w) <$> makePathBetween' t1 t2 a b w
-- assumes that pathfinding is symmetric
pointTowardsImpulse :: Point2 -> Point2 -> World -> Maybe Point2
pointTowardsImpulse a b w = find (flip (isWalkable a) w) =<< makePathBetweenPs b a w
pointTowardsImpulse' :: (Point2 -> Point2 -> World -> Bool) -> (Set.Set EdgeObstacle -> Bool)
-> Point2 -> Point2 -> World -> Maybe Point2
pointTowardsImpulse' t1 t2 a b w = find (flip (t1 a) w) =<< makePathBetweenPs' t1 t2 b a w
pairsToIncGraph ::
Set.Set (Point2, Point2) ->
( UV.Vector Point2