140 lines
4.4 KiB
Haskell
140 lines
4.4 KiB
Haskell
module Dodge.Layout
|
|
( module Dodge.Layout
|
|
, module Dodge.Layout.Tree
|
|
)
|
|
where
|
|
import Dodge.Data
|
|
import Dodge.LevelGen
|
|
import Dodge.LevelGen.StaticWalls
|
|
import Dodge.LevelGen.Data
|
|
import Dodge.Base
|
|
import Dodge.RandomHelp
|
|
import Dodge.Graph
|
|
import Dodge.Layout.Tree
|
|
import Dodge.Layout.Tree.Polymorphic (applyToRoot)
|
|
import Dodge.Room.Data
|
|
import Dodge.Default
|
|
import Geometry
|
|
import Dodge.Room.Link
|
|
|
|
import Control.Monad.State
|
|
import Control.Lens
|
|
import System.Random
|
|
import Data.List
|
|
import Data.Maybe
|
|
import Data.Tree
|
|
import Data.Either
|
|
import Data.Function
|
|
import Data.Graph.Inductive.Graph
|
|
import Data.Graph.Inductive.Basic
|
|
import Data.Graph.Inductive.PatriciaTree
|
|
import Data.Graph.Inductive.NodeMap
|
|
import qualified Data.Map as M
|
|
import qualified Data.IntMap.Strict as IM
|
|
|
|
generateFromList :: State StdGen [Room] -> World -> World
|
|
generateFromList gr w = updateWallZoning
|
|
. placeSpots plmnts
|
|
$ w { _walls = wallsFromRooms rs
|
|
}
|
|
where
|
|
plmnts = concatMap _rmPS rs
|
|
rs = evalState gr $ _randGen w
|
|
|
|
-- | connects a collection (tree) of rooms together
|
|
generateFromTree :: State StdGen (Tree Room) -> World -> World
|
|
generateFromTree t w = updateWallZoning $ placeSpots plmnts
|
|
$ w {_walls = wallsFromTree tr
|
|
,_pathGraph = path
|
|
,_pathGraph' = pairGraph
|
|
,_pathPoints = foldr insertPoint IM.empty (labNodes path)
|
|
,_pathInc = pinc
|
|
}
|
|
where
|
|
tr = evalState t $ _randGen w
|
|
plmnts = concatMap _rmPS $ flatten tr
|
|
path = pairsToGraph dist pairGraph
|
|
pairGraph = makePath tr
|
|
insertPoint pp@(_,(x,y)) = insertInZoneWith (floorHun x) (floorHun y) (++) [pp]
|
|
pinc = M.fromList $ pairsToIncidence pairGraph
|
|
|
|
updateWallZoning :: World -> World
|
|
updateWallZoning w = set wallsZone (IM.foldr wallInZone IM.empty (_walls w)) w
|
|
where
|
|
wallInZone wl | uncurry dist (_wlLine wl) <= 2*zoneSize
|
|
= insertIMInZone x y wlid wl
|
|
| otherwise = flip (foldr (\(a,b) -> insertIMInZone a b wlid wl)) ips
|
|
where (x,y) = zoneOfPoint $ (uncurry pHalf (_wlLine wl))
|
|
wlid = _wlID wl
|
|
ips = map zoneOfPoint $ uncurry (divideLine (2*zoneSize)) (_wlLine wl)
|
|
|
|
|
|
makePath :: Tree Room -> [(Point2,Point2)]
|
|
makePath = concat . map _rmPath . flatten
|
|
|
|
-- consider nubbing walls after dividing them
|
|
wallsFromTree :: Tree Room -> IM.IntMap Wall
|
|
wallsFromTree t =
|
|
-- createInnerWalls
|
|
divideWalls
|
|
. assignKeys
|
|
. removeInverseWalls
|
|
. foldr cutWalls [] -- map (map (g . roundPoint2))
|
|
-- . map (map roundPoint2)
|
|
$ (concatMap _rmPolys $ flatten t)
|
|
where
|
|
assignKeys = IM.fromList . zip [0..] . zipWith f [0..]
|
|
f i (x,y) = defaultWall {_wlLine = (x,y) , _wlID = i}
|
|
g (x,y) = (x-3855,y - 2613)
|
|
|
|
wallsFromRooms :: [Room] -> IM.IntMap Wall
|
|
wallsFromRooms =
|
|
-- divideWalls .
|
|
IM.fromList . zip [0..] . zipWith f [0..] . removeInverseWalls
|
|
. foldr cutWalls [] . concatMap _rmPolys
|
|
where
|
|
f i (x,y) = defaultWall {_wlLine = (x,y) , _wlID = i}
|
|
|
|
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
|
|
|
|
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
|
|
|
|
shiftRoomTree :: Tree Room -> Tree Room
|
|
shiftRoomTree (Node t []) = Node t []
|
|
shiftRoomTree (Node t ts) = Node t
|
|
$ zipWith (\l -> shiftRoomTree . applyToRoot (shiftRoomToLink l))
|
|
(_rmLinks t)
|
|
ts
|
|
|
|
shiftRoomTreeConstruction :: Tree Room -> [Tree Room]
|
|
shiftRoomTreeConstruction (Node t []) = [Node t []]
|
|
shiftRoomTreeConstruction (Node t ts) = (Node t [] :) $ concat $
|
|
zipWith (\l -> shiftRoomTreeConstruction . applyToRoot (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
|
|
|
|
|
|
|
|
|