Improve diagnostics for level generation
This commit is contained in:
+5
-9
@@ -2,8 +2,7 @@
|
|||||||
{- |
|
{- |
|
||||||
The tree of rooms that make up a level. -}
|
The tree of rooms that make up a level. -}
|
||||||
module Dodge.Floor
|
module Dodge.Floor
|
||||||
( levx
|
( layoutLevelFromSeed
|
||||||
, layoutLevel
|
|
||||||
) where
|
) where
|
||||||
import Geometry.Data
|
import Geometry.Data
|
||||||
import Dodge.Data
|
import Dodge.Data
|
||||||
@@ -104,21 +103,18 @@ initialRoomTree :: RandomGen g => State g (Tree Room)
|
|||||||
initialRoomTree = do
|
initialRoomTree = do
|
||||||
expandTreeBy id <$> mapM annoToRoomTree initialAnoTree
|
expandTreeBy id <$> mapM annoToRoomTree initialAnoTree
|
||||||
|
|
||||||
levx :: RandomGen g => Int -> State g ([Room] , Int)
|
layoutLevelFromSeed :: Int -> IO [Room]
|
||||||
levx _ = untilJustCount $ shiftExpandTree <$> initialRoomTree
|
layoutLevelFromSeed seed = do
|
||||||
|
|
||||||
layoutLevel :: Int -> IO [Room]
|
|
||||||
layoutLevel seed = do
|
|
||||||
putStrLn $ "Generating level with seed: " ++ show seed
|
putStrLn $ "Generating level with seed: " ++ show seed
|
||||||
let g = mkStdGen seed
|
let g = mkStdGen seed
|
||||||
let rmtree = evalState initialRoomTree g
|
let rmtree = evalState initialRoomTree g
|
||||||
mrs <- shiftRoomSearchIO [] (singleton rmtree)
|
mrs <- positionRooms rmtree
|
||||||
case mrs of
|
case mrs of
|
||||||
Just rs -> return (fmap setLastLinkToUsed rs)
|
Just rs -> return (fmap setLastLinkToUsed rs)
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
putStrLn "Level generation failed"
|
putStrLn "Level generation failed"
|
||||||
let (seed',_) = random g
|
let (seed',_) = random g
|
||||||
layoutLevel seed'
|
layoutLevelFromSeed seed'
|
||||||
where
|
where
|
||||||
setLastLinkToUsed rm = case _rmLinks rm of
|
setLastLinkToUsed rm = case _rmLinks rm of
|
||||||
(_:_) -> rm
|
(_:_) -> rm
|
||||||
|
|||||||
@@ -11,14 +11,11 @@ import Dodge.WorldEvent.Cloud
|
|||||||
import Dodge.SoundLogic
|
import Dodge.SoundLogic
|
||||||
import Dodge.SoundLogic.LoadSound
|
import Dodge.SoundLogic.LoadSound
|
||||||
import Geometry.Data
|
import Geometry.Data
|
||||||
import Dodge.Room.Data
|
|
||||||
|
|
||||||
import System.Random
|
import System.Random
|
||||||
import System.Timeout
|
|
||||||
import qualified Data.Set as S
|
import qualified Data.Set as S
|
||||||
import qualified Data.IntMap.Strict as IM
|
import qualified Data.IntMap.Strict as IM
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Control.Monad.State
|
|
||||||
|
|
||||||
firstWorld :: IO World
|
firstWorld :: IO World
|
||||||
firstWorld = do
|
firstWorld = do
|
||||||
@@ -28,18 +25,9 @@ firstWorld = do
|
|||||||
-- let g = mkStdGen i
|
-- let g = mkStdGen i
|
||||||
-- (roomList,n) <- f g
|
-- (roomList,n) <- f g
|
||||||
-- putStrLn $ "Had to go through "++ show n ++ " random generators"
|
-- putStrLn $ "Had to go through "++ show n ++ " random generators"
|
||||||
roomList <- layoutLevel i
|
roomList <- layoutLevelFromSeed i
|
||||||
return $ generateLevelFromRoomList roomList $ initialWorld -- note this uses a random generator defined elsewhere
|
return $ generateLevelFromRoomList roomList
|
||||||
where
|
$ initialWorld -- note this uses a random generator defined elsewhere
|
||||||
f :: StdGen -> IO ([Room],Int)
|
|
||||||
f g = do
|
|
||||||
mayrs <- timeout 10000000 . return $ evalState (levx 1) g
|
|
||||||
case mayrs of
|
|
||||||
Nothing -> do
|
|
||||||
let i = fst $ random g
|
|
||||||
putStrLn $ "Timeout; trying new seed: " ++ show i
|
|
||||||
f (mkStdGen i)
|
|
||||||
Just rs -> return rs
|
|
||||||
|
|
||||||
initialWorld :: World
|
initialWorld :: World
|
||||||
initialWorld = defaultWorld
|
initialWorld = defaultWorld
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ module Dodge.Layout.Tree.Polymorphic
|
|||||||
, splitTrunk
|
, splitTrunk
|
||||||
, applyToRandomNode
|
, applyToRandomNode
|
||||||
, addToTrunk
|
, addToTrunk
|
||||||
|
, bfnumberTree
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
import Dodge.RandomHelp
|
import Dodge.RandomHelp
|
||||||
@@ -142,3 +143,16 @@ splitTrunk :: RandomGen g => Tree a -> State g (Tree a, [Tree a])
|
|||||||
splitTrunk t = do
|
splitTrunk t = do
|
||||||
i <- state $ randomR (0, trunkDepth t)
|
i <- state $ randomR (0, trunkDepth t)
|
||||||
return $ splitTrunkAt i t
|
return $ splitTrunkAt i t
|
||||||
|
|
||||||
|
-- untested
|
||||||
|
bfnumberTree :: Tree a -> Tree (a,Int)
|
||||||
|
bfnumberTree = fst . f 0
|
||||||
|
where
|
||||||
|
f i (Node x ts) =
|
||||||
|
let (ts',i') = g (i+1) ts
|
||||||
|
in (Node (x,i) ts', i')
|
||||||
|
g i (t:ts) =
|
||||||
|
let (t',i') = f i t
|
||||||
|
(ts',i'') = g i' ts
|
||||||
|
in ((t': ts'), i'')
|
||||||
|
g i [] = ([], i)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Returns a list; after this step the structure is determined by the actual positi
|
|||||||
module Dodge.Layout.Tree.Shift
|
module Dodge.Layout.Tree.Shift
|
||||||
( shiftRoomTreeSearchAll
|
( shiftRoomTreeSearchAll
|
||||||
, shiftExpandTree
|
, shiftExpandTree
|
||||||
, shiftRoomSearchIO
|
, positionRooms
|
||||||
) where
|
) where
|
||||||
import Dodge.Room.Data
|
import Dodge.Room.Data
|
||||||
import Dodge.Room.Link
|
import Dodge.Room.Link
|
||||||
@@ -18,6 +18,7 @@ import Data.Tree
|
|||||||
import Data.Sequence hiding (zipWith)
|
import Data.Sequence hiding (zipWith)
|
||||||
import Data.List (delete)
|
import Data.List (delete)
|
||||||
import Data.Maybe (listToMaybe)
|
import Data.Maybe (listToMaybe)
|
||||||
|
import Data.Bifunctor
|
||||||
import Control.Lens hiding (Empty, (<|) , (|>))
|
import Control.Lens hiding (Empty, (<|) , (|>))
|
||||||
|
|
||||||
{- | All: Depth first search of trees of rooms, produces a list of lists of rooms that are not clipping. -}
|
{- | All: Depth first search of trees of rooms, produces a list of lists of rooms that are not clipping. -}
|
||||||
@@ -43,37 +44,77 @@ shiftRoomTreeSearchAll bs (Node r ts :<| tseq)
|
|||||||
useLink l = r & rmLinks %~ delete l
|
useLink l = r & rmLinks %~ delete l
|
||||||
& rmUsedLinks %~ (l :)
|
& rmUsedLinks %~ (l :)
|
||||||
f l = applyToRoot (shiftRoomToLink l)
|
f l = applyToRoot (shiftRoomToLink l)
|
||||||
shiftRoomSearchIO
|
|
||||||
|
positionRooms :: Tree Room -> IO (Maybe [Room])
|
||||||
|
--positionRooms = shiftRoomSearchIO 0 [] . singleton
|
||||||
|
positionRooms t =
|
||||||
|
let (Node (r,i) ts) = bfnumberTree t
|
||||||
|
in posRms (map pointsToPoly $ _rmBound r) (r,i) ts Empty
|
||||||
|
|
||||||
|
type RoomInt = (Room,Int)
|
||||||
|
|
||||||
|
posRms
|
||||||
:: [ConvexPoly]
|
:: [ConvexPoly]
|
||||||
|
-> RoomInt
|
||||||
|
-> [Tree RoomInt]
|
||||||
|
-> Seq (Tree RoomInt)
|
||||||
|
-> IO (Maybe [Room])
|
||||||
|
posRms _ _ [] Empty = return $ Just []
|
||||||
|
posRms bounds (rtoadd,_) [] (Node (r,i) ts :<| tseq) = fmap (fmap (rtoadd:)) $ posRms bounds (r,i) ts tseq
|
||||||
|
posRms bounds (r,i) (t:ts) tseq = tryLinks' (_rmLinks r)
|
||||||
|
where
|
||||||
|
tryLinks' [] = do
|
||||||
|
putStrLn "All links tried"
|
||||||
|
return Nothing
|
||||||
|
tryLinks' (l:ls)
|
||||||
|
| clipping = tryLinks' ls
|
||||||
|
| otherwise = do
|
||||||
|
putStrLn $ "Trying link from " ++ show i ++ " to " ++ show i'
|
||||||
|
mayrs <- posRms (convexBounds ++ bounds) useLink ts (tseq |> shiftedt)
|
||||||
|
case mayrs of
|
||||||
|
Nothing -> do putStrLn ("Backtracking to " ++ show i) >> tryLinks' ls
|
||||||
|
Just rs -> return (Just rs)
|
||||||
|
where
|
||||||
|
convexBounds = map pointsToPoly $ _rmBound r'
|
||||||
|
clipping = or (convexPolysOverlap <$> convexBounds <*> bounds)
|
||||||
|
useLink = (r & rmLinks %~ delete l & rmUsedLinks %~ (l :)
|
||||||
|
, i)
|
||||||
|
shiftedt@(Node (r',i') _) = applyToRoot (first $ shiftRoomToLink l) t
|
||||||
|
|
||||||
|
|
||||||
|
shiftRoomSearchIO
|
||||||
|
:: Int
|
||||||
|
-> [ConvexPoly]
|
||||||
-> Seq (Tree Room)
|
-> Seq (Tree Room)
|
||||||
-> IO (Maybe [Room])
|
-> IO (Maybe [Room])
|
||||||
shiftRoomSearchIO _ Empty = return (Just [])
|
shiftRoomSearchIO _ _ Empty = return (Just [])
|
||||||
shiftRoomSearchIO bs (Node r ts :<| tseq)
|
shiftRoomSearchIO i bs (Node r ts :<| tseq)
|
||||||
| roomIsClipping = do
|
| roomIsClipping = do
|
||||||
putStrLn "Room clipping"
|
putStrLn $ "Room " ++ show i ++ " clipping"
|
||||||
return Nothing
|
return Nothing
|
||||||
| otherwise = fmap (fmap (r:)) $ placeLinkedRooms newBounds r ts tseq
|
| otherwise = fmap (fmap (r:)) $ placeLinkedRooms i newBounds r ts tseq
|
||||||
where
|
where
|
||||||
convexBounds = map pointsToPoly $ _rmBound r
|
convexBounds = map pointsToPoly $ _rmBound r
|
||||||
newBounds = convexBounds ++ bs
|
newBounds = convexBounds ++ bs
|
||||||
roomIsClipping = or (convexPolysOverlap <$> convexBounds <*> bs)
|
roomIsClipping = or (convexPolysOverlap <$> convexBounds <*> bs)
|
||||||
placeLinkedRooms :: [ConvexPoly] -> Room -> [Tree Room] -> (Seq (Tree Room)) -> IO (Maybe [Room])
|
placeLinkedRooms :: Int -> [ConvexPoly] -> Room -> [Tree Room] -> (Seq (Tree Room)) -> IO (Maybe [Room])
|
||||||
placeLinkedRooms bs _ [] tseq
|
placeLinkedRooms i bs _ [] tseq
|
||||||
= shiftRoomSearchIO bs tseq
|
= shiftRoomSearchIO (i+1) bs tseq
|
||||||
placeLinkedRooms bs r (t:ts) tseq
|
placeLinkedRooms i bs r (t:ts) tseq
|
||||||
= tryLinks ls bs r t ts tseq
|
= tryLinks i ls bs r t ts tseq
|
||||||
where
|
where
|
||||||
ls = init $ _rmLinks r
|
ls = init $ _rmLinks r
|
||||||
|
|
||||||
tryLinks :: [(Point2,Float)] -> [ConvexPoly] -> Room -> Tree Room -> [Tree Room] -> (Seq (Tree Room))
|
tryLinks :: Int
|
||||||
|
-> [(Point2,Float)] -> [ConvexPoly] -> Room -> Tree Room -> [Tree Room] -> (Seq (Tree Room))
|
||||||
-> IO (Maybe [Room])
|
-> IO (Maybe [Room])
|
||||||
tryLinks [] _ _ _ _ _ = do
|
tryLinks i [] _ _ _ _ _ = do
|
||||||
putStrLn "Tried all links"
|
putStrLn $ "Tried all links for room " ++ show i
|
||||||
return Nothing
|
return Nothing
|
||||||
tryLinks (l:ls) bs r t ts tseq = do
|
tryLinks i (l:ls) bs r t ts tseq = do
|
||||||
branch <- placeLinkedRooms bs useLink ts (tseq |> shiftedt)
|
branch <- placeLinkedRooms i bs useLink ts (tseq |> shiftedt)
|
||||||
case branch of
|
case branch of
|
||||||
Nothing -> tryLinks ls bs r t ts tseq
|
Nothing -> tryLinks i ls bs r t ts tseq
|
||||||
Just rs -> return $ Just rs
|
Just rs -> return $ Just rs
|
||||||
where
|
where
|
||||||
useLink = r & rmLinks %~ delete l
|
useLink = r & rmLinks %~ delete l
|
||||||
|
|||||||
Reference in New Issue
Block a user