Add source files, commit before reverting pictures to lists
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
module Dodge.Layout where
|
||||
-- imports {{{
|
||||
import Dodge.Data
|
||||
import Dodge.Weapons
|
||||
import Dodge.Critters
|
||||
import Dodge.LevelGen
|
||||
import Dodge.Base
|
||||
import Dodge.RandomHelp
|
||||
import Dodge.Prototypes
|
||||
import Dodge.Path
|
||||
|
||||
import Geometry
|
||||
--
|
||||
--import Graphics.Gloss
|
||||
--import Graphics.Gloss.Data.Vector
|
||||
--import Graphics.Gloss.Geometry.Line
|
||||
--import Graphics.Gloss.Geometry.Angle
|
||||
--
|
||||
import Control.Monad.State
|
||||
--import Control.Monad.Loops
|
||||
import Control.Lens
|
||||
import System.Random
|
||||
|
||||
import Data.List
|
||||
import Data.Maybe
|
||||
import Data.Tree
|
||||
import Data.Either
|
||||
import Data.Function
|
||||
import qualified Data.Map as M
|
||||
|
||||
import Data.Graph.Inductive.Graph
|
||||
import Data.Graph.Inductive.Basic
|
||||
import Data.Graph.Inductive.PatriciaTree
|
||||
import Data.Graph.Inductive.NodeMap
|
||||
|
||||
import qualified Data.IntMap.Strict as IM
|
||||
-- }}}
|
||||
|
||||
generateFromTree :: State StdGen (Tree Room) -> World -> World
|
||||
generateFromTree t w = zoning $ placeSpots plmnts
|
||||
$ w {_walls = wallsFromTree tr, _randGen = g
|
||||
-- ,_loadedSounds = lSounds
|
||||
,_pathGraph = path
|
||||
,_pathGraph' = pairGraph
|
||||
,_pathPoints = foldr insertPoint IM.empty (labNodes path)
|
||||
,_pathInc = pinc}
|
||||
where tr = evalState t $ _randGen w
|
||||
plmnts = concatMap _rmPS $ flatten tr
|
||||
g = _randGen w
|
||||
-- lSounds = _loadedSounds w
|
||||
path = pairsToGraph dist pairGraph
|
||||
pairGraph = makePath tr
|
||||
insertPoint pp@(_,(x,y)) = insertInZoneWith (floorHun x) (floorHun y) (++) [pp]
|
||||
pinc = M.fromList $ pairsToIncidence pairGraph
|
||||
zoning w = set wallsZone (IM.foldr wallInZone IM.empty (_walls w))
|
||||
w
|
||||
wallInZone wl | dist (_wlLine wl !! 0) (_wlLine wl !! 1) <= 2*zoneSize
|
||||
= insertIMInZone x y wlid wl
|
||||
| otherwise = flip (foldr (\(a,b) -> insertIMInZone a b wlid wl)) ips
|
||||
where (x,y) = zoneOfPoint $ (pHalf (_wlLine wl !! 0) (_wlLine wl !! 1))
|
||||
wlid = _wlID wl
|
||||
ips = map zoneOfPoint $ divideLine (2*zoneSize) (_wlLine wl !! 0) (_wlLine wl !! 1)
|
||||
|
||||
makePath :: Tree Room -> [(Point2,Point2)]
|
||||
makePath = concat . map _rmPath . flatten
|
||||
|
||||
wallsFromTree :: Tree Room -> IM.IntMap Wall
|
||||
wallsFromTree t = divideWalls $ foldr cutWalls IM.empty (concatMap _rmPolys $ flatten t)
|
||||
|
||||
divideWall :: Wall -> [Wall]
|
||||
divideWall wl
|
||||
= let (a:b:_) = _wlLine wl
|
||||
--ps = divideLine (zoneSize * 2) a b
|
||||
ps = divideLine (zoneSize * 2) a b
|
||||
in map (\(x,y) -> wl {_wlLine = [x,y]}) $ zip (init ps) (tail ps)
|
||||
|
||||
divideWallIn :: Wall -> IM.IntMap Wall -> IM.IntMap Wall
|
||||
divideWallIn wl wls =
|
||||
let (wl':newWls) = divideWall wl
|
||||
k = newKey wls
|
||||
newWls' = zipWith (\i w -> w {_wlID = i}) [k..] newWls
|
||||
in foldr (\w -> IM.insert (_wlID w) w) wls (wl':newWls')
|
||||
|
||||
divideWalls :: IM.IntMap Wall -> IM.IntMap Wall
|
||||
divideWalls wls = IM.foldr divideWallIn wls wls
|
||||
|
||||
collapseTree :: Tree (Tree (Either Room Room)) -> Tree (Either Room Room)
|
||||
collapseTree = g . expandTreeBy f
|
||||
where f (Node (Right x) xs) = Node (Right (Right x)) $ map f xs
|
||||
f (Node (Left x) xs) = Node (Left (Left x)) $ map f xs
|
||||
g (Node (Right x) []) = Node (Right x) []
|
||||
g (Node (Right x) xs) = Node (Left x) $ map g xs
|
||||
g (Node y ys) = Node y $ map g ys
|
||||
|
||||
|
||||
insertInZone :: Int -> Int -> a -> IM.IntMap (IM.IntMap a) -> IM.IntMap (IM.IntMap a)
|
||||
insertInZone x y obj = IM.insertWith f x $ IM.singleton y obj
|
||||
where f _ = IM.insert y obj
|
||||
|
||||
allPairs :: Eq a => [a] -> [(a,a)]
|
||||
allPairs xs = [(x,y) | x <- xs, y <- xs, x /= y]
|
||||
|
||||
treePost :: [a] -> a -> Tree a
|
||||
treePost [] y = Node y []
|
||||
treePost (x:xs) y = Node x [treePost xs y]
|
||||
|
||||
randomiseLinks :: RandomGen g => Room -> State g (Tree (Either Room Room))
|
||||
randomiseLinks r = do
|
||||
newLinks <- shuffle $ init $ _rmLinks r
|
||||
return $ connectRoom $ r {_rmLinks = newLinks ++ [last $ _rmLinks r]}
|
||||
randLinks :: RandomGen g => Room -> State g Room
|
||||
randLinks r = do
|
||||
newLinks <- shuffle $ init $ _rmLinks r
|
||||
return $ r {_rmLinks = newLinks ++ [last $ _rmLinks r]}
|
||||
|
||||
filterLinks :: RandomGen g => ((Point2,Float) -> Bool) -> Room -> State g Room
|
||||
filterLinks cond r = do
|
||||
newLinks <- shuffle $ filter cond $ init $ _rmLinks r
|
||||
return $ r {_rmLinks = newLinks ++ [last $ _rmLinks r]}
|
||||
|
||||
changeLinkTo :: RandomGen g => ((Point2,Float) -> Bool) -> Room -> State g Room
|
||||
changeLinkTo cond r = do
|
||||
l <- takeOne $ filter cond $ _rmLinks r
|
||||
let newLinks = delete l (_rmLinks r) ++ [l]
|
||||
return $ r {_rmLinks = newLinks}
|
||||
|
||||
|
||||
-- Left elements get new children, Right elements inherit the children from the
|
||||
-- mapped over node
|
||||
composeTreeWith :: (a -> Tree (Either b b)) -> Tree a -> Tree (Either b b)
|
||||
composeTreeWith f (Node x []) = f x
|
||||
composeTreeWith f (Node x xs) = paste xs $ f x
|
||||
where paste xs (Node (Right y) _) = Node (Left y) (map (composeTreeWith f) xs)
|
||||
paste xs (Node (Left y) ys) = Node (Left y) (map (paste xs) ys)
|
||||
|
||||
doPolysIntersect :: [Point2] -> [Point2] -> Bool
|
||||
doPolysIntersect (p:ps) (q:qs)
|
||||
= any isJust $ (\(a,b) (c,d) -> intersectSegSeg' a b c d) <$> pair1s <*> pair2s
|
||||
where pair1s = zip (p:ps) (ps++[p])
|
||||
pair2s = zip (q:qs) (qs++[q])
|
||||
doPolysIntersect [] _ = False
|
||||
doPolysIntersect _ [] = False
|
||||
|
||||
boundClip :: Tree Room -> Bool
|
||||
boundClip t = or $ map (uncurry doPolysIntersect) [(x,y) | x<- xs, y<-xs, x>y]
|
||||
++ map f [(ps,qs) | ps <- xs, qs <-xs, ps/=qs]
|
||||
where xs = map _rmBound $ flatten t
|
||||
f ([],qs) = False
|
||||
f ((p:_),qs) = pointInPolygon p qs
|
||||
|
||||
noBoundClip :: Tree Room -> Bool
|
||||
noBoundClip = not . boundClip
|
||||
|
||||
connectRoom :: a -> Tree (Either a a)
|
||||
connectRoom r = Node (Right r) []
|
||||
deadRoom :: a -> Tree (Either a a)
|
||||
deadRoom r = Node (Left r) []
|
||||
|
||||
onRoot :: (a -> a) -> Tree a -> Tree a
|
||||
onRoot f (Node t ts) = Node (f t) ts
|
||||
|
||||
shiftRoomTree :: Tree Room -> Tree Room
|
||||
shiftRoomTree (Node t []) = Node t []
|
||||
shiftRoomTree (Node t ts) = Node t $ zipWith (\l -> shiftRoomTree . onRoot (shiftRoomBy l . f))
|
||||
(_rmLinks t)
|
||||
ts
|
||||
where f r = shiftRoomBy ((0,0) -.- (rotateV (pi-a) p),0) $ shiftRoomBy ((0,0),pi-a) r
|
||||
where (p,a) = last $ _rmLinks r
|
||||
|
||||
shiftRoomBy :: (Point2,Float) -> Room -> Room
|
||||
shiftRoomBy shift@(pos,rot) r =
|
||||
over rmPolys (fmap (map (shiftPointBy shift)))
|
||||
$ over rmLinks (fmap (shiftLinkBy shift))
|
||||
$ over rmPath (map (shiftPathPointBy shift))
|
||||
$ over rmPS (fmap (shiftPSBy shift))
|
||||
$ over rmBound (map (shiftPointBy shift))
|
||||
r
|
||||
|
||||
shiftPathPointBy s (p1,p2) = (shiftPointBy s p1, shiftPointBy s p2)
|
||||
|
||||
shiftLinkBy (pos,rot) (p,r) = (shiftPointBy (pos,rot) p, r + rot)
|
||||
shiftPSBy (pos,rot) ps = case ps of
|
||||
PS {} -> over psPos (shiftPointBy (pos,rot))
|
||||
$ over psRot (+rot)
|
||||
ps
|
||||
|
||||
|
||||
Reference in New Issue
Block a user