Add source files, commit before reverting pictures to lists
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
module Dodge.Path where
|
||||
import Dodge.Data
|
||||
import Dodge.Base
|
||||
|
||||
import Geometry
|
||||
|
||||
import Control.Monad
|
||||
|
||||
import Data.List
|
||||
import Data.Maybe
|
||||
import Data.Function
|
||||
import Data.Graph.Inductive.Graph
|
||||
import qualified Data.HashSet as HS
|
||||
import qualified Data.Heap as HP
|
||||
|
||||
import qualified Data.Map as M
|
||||
|
||||
import Data.Graph.Inductive.Graph
|
||||
import Data.Graph.Inductive.PatriciaTree
|
||||
import Data.Graph.Inductive.Query.SP
|
||||
|
||||
worldGraph :: World -> Point2 -> HS.HashSet Point2
|
||||
worldGraph w p = HS.unions $ fmap (\q -> HS.fromList $ pointsAlong w p (p +.+ q))
|
||||
[(200,0),(-200,0),(0,200),(0,-200)]
|
||||
|
||||
pointsAlong :: World -> Point2 -> Point2 -> [Point2]
|
||||
pointsAlong w p q = divideLineFixed 50 p p'
|
||||
where p' = furthestPointWalkable p q $ wallsAlongLine p q w
|
||||
|
||||
divideLineFixed :: Float -> Point2 -> Point2 -> [Point2]
|
||||
divideLineFixed x a b = fmap (\i -> a +.+ i * x *.* normalizeV (b -.- a))
|
||||
$ fmap fromIntegral ns
|
||||
where numPoints = floor $ dist a b / x
|
||||
ns = [1 .. numPoints]
|
||||
|
||||
-- ok, astar or something like it
|
||||
|
||||
type SearchedNodes = (HP.MinHeap (Float,(Float,[Point2])), [Point2])
|
||||
|
||||
stripRight :: Either a b -> b
|
||||
stripRight (Right x) = x
|
||||
|
||||
stepPath :: (Point2 -> [Point2]) -> Point2
|
||||
-> SearchedNodes -> Either [Point2] SearchedNodes
|
||||
stepPath f p (nextNodes, seenNodes)
|
||||
= case HP.view nextNodes of
|
||||
Nothing -> Left []
|
||||
Just ((_,(cost,(q:qs))), nextNodes')
|
||||
| q == p -> Left (q:qs)
|
||||
| otherwise -> let rs' = f q
|
||||
rs = rs' \\ seenNodes
|
||||
newNodes = map (\r -> (cost + dist q r + dist r p
|
||||
, (cost + dist q r
|
||||
, (r:q:qs)
|
||||
)
|
||||
)
|
||||
) rs
|
||||
in Right $ (foldr HP.insert nextNodes' newNodes
|
||||
, rs ++ seenNodes
|
||||
)
|
||||
stepPath' :: (Point2 -> [Point2]) -> Point2
|
||||
-> SearchedNodes -> [Point2]
|
||||
stepPath' f p s = case stepPath f p s of Left ps -> ps
|
||||
Right s' -> stepPath' f p s'
|
||||
|
||||
makePath' :: (Point2 -> [Point2]) -> Point2 -> Point2 -> [Point2]
|
||||
makePath' f s e = stepPath' f e $ (HP.singleton (0,(0,[s])) , [])
|
||||
|
||||
makeNode :: Point2 -> SearchedNodes
|
||||
makeNode e = (HP.singleton (0,(0,[e])) , [])
|
||||
|
||||
|
||||
tp1,tp2,tp3 :: Point2
|
||||
tp1 = (0,1)
|
||||
tp2 = (0,20)
|
||||
tp3 = (30,40)
|
||||
|
||||
f = incidenceToFunction $ pairsToIncidence [(tp1,tp2),(tp2,tp3)
|
||||
,(tp2,tp1)
|
||||
,(tp1,tp3)]
|
||||
g = pairsToIncidence [(tp1,tp2),(tp2,tp3)
|
||||
,(tp2,tp1)
|
||||
,(tp1,tp3)]
|
||||
|
||||
pathBetween :: Point2 -> Point2 -> World -> Maybe [Point2]
|
||||
pathBetween a b w = makePath' <$> return (\p -> _pathInc w M.! p) <*> a' <*> b'
|
||||
where
|
||||
nsa :: [Point2]
|
||||
nsa = map snd $ concat $ lookLookups (zoneAroundPoint a) (_pathPoints w)
|
||||
nsb = map snd $ concat $ lookLookups (zoneAroundPoint b) (_pathPoints w)
|
||||
--a' = listToMaybe $ sortBy (compare `on` dist a) $ ns
|
||||
--b' = listToMaybe $ sortBy (compare `on` dist b) $ ns
|
||||
a' = listToMaybe $ filter (flip (isWalkable a) w) nsa
|
||||
b' = listToMaybe $ filter (flip (isWalkable b) w) nsb
|
||||
|
||||
|
||||
|
||||
----
|
||||
|
||||
makePathBetween :: Point2 -> Point2 -> World -> Maybe [Int]
|
||||
makePathBetween a b w = join $ sp <$> fmap fst a' <*> fmap fst b' <*> return g
|
||||
where g = _pathGraph w
|
||||
nsa = concat $ lookLookups (zoneAroundPoint a) (_pathPoints w)
|
||||
nsb = concat $ lookLookups (zoneAroundPoint b) (_pathPoints w)
|
||||
-- a' = listToMaybe $ sortBy (compare `on` dist a . snd) $ filter (flip (isWalkable a) w . snd) ns
|
||||
-- b' = listToMaybe $ sortBy (compare `on` dist b . snd) $ filter (flip (isWalkable b) w . snd) ns
|
||||
a' = listToMaybe $ filter (flip (isWalkable a) w . snd) nsa
|
||||
b' = listToMaybe $ filter (flip (isWalkable b) w . snd) nsb
|
||||
|
||||
|
||||
|
||||
ezipWith :: Monoid a => (b -> c -> d) -> Either a b -> Either a c -> Either a d
|
||||
ezipWith f (Right x) (Right y) = Right (f x y)
|
||||
ezipWith f (Left x) (Right _) = Left x
|
||||
ezipWith f (Right _) (Left y) = Left y
|
||||
ezipWith f (Left x) (Left y) = Left (mappend x y)
|
||||
|
||||
|
||||
makePathBetween' :: Point2 -> Point2 -> World -> Either String [Int]
|
||||
makePathBetween' a b w = let g = _pathGraph w
|
||||
ns = labNodes g
|
||||
nsa = (_pathPoints w) `ixNZ` a
|
||||
nsb = (_pathPoints w) `ixNZ` b
|
||||
a' = case listToMaybe $ sortBy (compare `on` dist a . snd)
|
||||
-- a' = case listToMaybe
|
||||
$ filter (flip (isWalkable a) w . snd) ns of
|
||||
Just p -> Right $ fst p
|
||||
_ -> Left "FIRST POINT UNSEEN"
|
||||
b' = case listToMaybe $ sortBy (compare `on` dist b . snd)
|
||||
-- b' = case listToMaybe
|
||||
$ filter (flip (isWalkable b) w . snd) ns of
|
||||
Just p -> Right $ fst p
|
||||
_ -> Left $ "SECOND POINT UNSEEN" ++ show b
|
||||
in case ezipWith (\x y -> sp x y g) a' b' of
|
||||
Right (Just xs) -> Right xs
|
||||
Right (Nothing) -> Left $ "NO PATH" ++ show a ++ show b ++ show a' ++ show b'
|
||||
Left m -> Left m
|
||||
|
||||
makePathBetweenPs :: Point2 -> Point2 -> World -> Maybe [Point2]
|
||||
--makePathBetweenPs a b = pathBetween a b
|
||||
makePathBetweenPs a b w = fmap (mapMaybe (lab g)) $ makePathBetween b a w
|
||||
where g = _pathGraph w
|
||||
|
||||
makePathBetweenPs' :: Point2 -> Point2 -> World -> Either String [Point2]
|
||||
makePathBetweenPs' a b w = fmap (mapMaybe (lab g)) $ makePathBetween' a b w
|
||||
where g = _pathGraph w
|
||||
|
||||
|
||||
pointTowardsGoal :: Point2 -> Point2 -> World -> Maybe Point2
|
||||
pointTowardsGoal a b w = join $ fmap (listToMaybe . filter (flip (isWalkable a) w))
|
||||
-- $ pathBetween a b w
|
||||
$ makePathBetweenPs a b w
|
||||
--
|
||||
|
||||
pointTowardsGoal' :: Point2 -> Point2 -> World -> Either String Point2
|
||||
pointTowardsGoal' a b w = join $ fmap (maybeToEither "NOSEEPATH" . listToMaybe . filter (flip (isWalkable a) w))
|
||||
$ makePathBetweenPs' b a w
|
||||
|
||||
maybeToEither :: a -> Maybe b -> Either a b
|
||||
maybeToEither _ (Just x) = Right x
|
||||
maybeToEither y Nothing = Left y
|
||||
|
||||
pairsToIncidence :: (Eq a,Ord a) => [(a,a)] -> [(a,[a])]
|
||||
pairsToIncidence = map ((\(xs,ys) -> (head xs,ys)) . unzip)
|
||||
. groupBy ( (==) `on` fst)
|
||||
. sort
|
||||
|
||||
incidenceToFunction :: Eq a => [(a,[a])] -> a -> [a]
|
||||
incidenceToFunction xs a = case lookup a xs of Just ys -> ys
|
||||
Nothing -> []
|
||||
|
||||
Reference in New Issue
Block a user