From 1789a3785dbb29701beed323119de437958d8f7b Mon Sep 17 00:00:00 2001 From: justin Date: Thu, 9 Jun 2022 11:24:13 +0100 Subject: [PATCH] Allow for random composition of trees --- src/Dodge/Annotation.hs | 1 - src/Dodge/Default/Prop.hs | 21 +++++ src/Dodge/Floor.hs | 1 - src/Dodge/LevelGen.hs | 1 - src/Dodge/Room/Boss.hs | 1 - src/Dodge/Room/Branch.hs | 5 +- src/Dodge/Room/GlassLesson.hs | 1 - src/Dodge/Room/LasTurret.hs | 1 - src/Dodge/Room/LongDoor.hs | 1 - src/Dodge/Room/LongRoom.hs | 2 - src/Dodge/Room/RezBox.hs | 1 - src/Dodge/Room/Room.hs | 5 +- src/Dodge/Room/RunPast.hs | 1 - src/Dodge/Tree.hs | 4 +- src/Dodge/Tree/Compose.hs | 83 +++++++++++-------- src/Dodge/Tree/Shift.hs | 5 +- .../Tree/Polymorphic.hs => TreeHelp.hs} | 57 ++++++------- 17 files changed, 103 insertions(+), 88 deletions(-) create mode 100644 src/Dodge/Default/Prop.hs rename src/{Dodge/Tree/Polymorphic.hs => TreeHelp.hs} (78%) diff --git a/src/Dodge/Annotation.hs b/src/Dodge/Annotation.hs index 204429a63..3e8928a96 100644 --- a/src/Dodge/Annotation.hs +++ b/src/Dodge/Annotation.hs @@ -11,7 +11,6 @@ import Dodge.Data import Dodge.Annotation.Data --import LensHelp -import Data.Tree import Control.Monad.State import System.Random --import Control.Lens diff --git a/src/Dodge/Default/Prop.hs b/src/Dodge/Default/Prop.hs new file mode 100644 index 000000000..97fdcfc44 --- /dev/null +++ b/src/Dodge/Default/Prop.hs @@ -0,0 +1,21 @@ +module Dodge.Default.Prop where +import Dodge.Data +import Geometry +defaultProp :: Prop +defaultProp = Projectile + { _prPos = V2 0 0 + , _pjStartPos = V2 0 0 + , _pjVel = V2 0 0 + , _prDraw = const mempty + , _pjID = 0 + , _pjUpdate = const id + } +defaultShapeProp :: Prop +defaultShapeProp = ShapeProp + { _prPos = 0 + , _pjID = 0 + , _pjRot = 0 + , _pjUpdate = const id + , _prDraw = const mempty + , _prToggle = True + } diff --git a/src/Dodge/Floor.hs b/src/Dodge/Floor.hs index 545caf258..b00f4a30d 100644 --- a/src/Dodge/Floor.hs +++ b/src/Dodge/Floor.hs @@ -25,7 +25,6 @@ import Dodge.Data --import Dodge.RoomPos --import Dodge.Room.RunPast --import MonadHelp -import Data.Tree import LensHelp import Dodge.RandomHelp --import Color diff --git a/src/Dodge/LevelGen.hs b/src/Dodge/LevelGen.hs index 85dd48a90..f2c93c092 100644 --- a/src/Dodge/LevelGen.hs +++ b/src/Dodge/LevelGen.hs @@ -12,7 +12,6 @@ import Dodge.Tree import Geometry.ConvexPoly --import Dodge.LevelGen.LevelStructure -import Data.Tree import System.Random import Control.Lens import Control.Monad.State diff --git a/src/Dodge/Room/Boss.hs b/src/Dodge/Room/Boss.hs index ef62f11f0..203edf074 100644 --- a/src/Dodge/Room/Boss.hs +++ b/src/Dodge/Room/Boss.hs @@ -18,7 +18,6 @@ import Dodge.LevelGen.StaticWalls import Geometry import LensHelp -import Data.Tree import Control.Monad.State import System.Random roomGlassOctogon diff --git a/src/Dodge/Room/Branch.hs b/src/Dodge/Room/Branch.hs index bf14c9cf6..7195b5333 100644 --- a/src/Dodge/Room/Branch.hs +++ b/src/Dodge/Room/Branch.hs @@ -14,15 +14,14 @@ import Dodge.Tree import Control.Monad.State import System.Random -import Data.Tree branchRectWith :: RandomGen g => State g (SubCompTree Room) -> State g (SubCompTree Room) branchRectWith t = do x <- state $ randomR (100,200) y <- state $ randomR (100,200) b <- t - root <- shuffleLinks $ roomRectAutoLinks x y - return $ Node (PassDown root) + rt <- shuffleLinks $ roomRectAutoLinks x y + return $ Node (PassDown rt) [ Node (UseAll door) [] , changeToPassDown <$> treeFromTrunk [PassDown door] b ] diff --git a/src/Dodge/Room/GlassLesson.hs b/src/Dodge/Room/GlassLesson.hs index 61a3724f4..a0147e5af 100644 --- a/src/Dodge/Room/GlassLesson.hs +++ b/src/Dodge/Room/GlassLesson.hs @@ -20,7 +20,6 @@ import qualified Data.Set as S import Control.Monad.State --import Control.Monad.Loops import System.Random -import Data.Tree glassLesson :: RandomGen g => State g (SubCompTree Room) glassLesson = do i <- takeOne [1,2,3] diff --git a/src/Dodge/Room/LasTurret.hs b/src/Dodge/Room/LasTurret.hs index 203471e02..c4422838b 100644 --- a/src/Dodge/Room/LasTurret.hs +++ b/src/Dodge/Room/LasTurret.hs @@ -30,7 +30,6 @@ import Dodge.RandomHelp import qualified Data.Set as S import Data.Maybe -import Data.Tree import Control.Monad.State import System.Random diff --git a/src/Dodge/Room/LongDoor.hs b/src/Dodge/Room/LongDoor.hs index 7d66627c0..0421d4cd4 100644 --- a/src/Dodge/Room/LongDoor.hs +++ b/src/Dodge/Room/LongDoor.hs @@ -26,7 +26,6 @@ import LensHelp --import Shape import qualified Data.Set as S -import Data.Tree import System.Random import Control.Monad.State import Data.Maybe diff --git a/src/Dodge/Room/LongRoom.hs b/src/Dodge/Room/LongRoom.hs index 72a92c7a4..fbace8d8e 100644 --- a/src/Dodge/Room/LongRoom.hs +++ b/src/Dodge/Room/LongRoom.hs @@ -24,10 +24,8 @@ import LensHelp import Data.Tile import qualified Data.Set as S -import Data.Tree import System.Random import Control.Monad.State ---import Data.Tree --import qualified Data.IntMap as IM longRoom :: RandomGen g => State g Room diff --git a/src/Dodge/Room/RezBox.hs b/src/Dodge/Room/RezBox.hs index 8b9da4ea6..1fce42b1c 100644 --- a/src/Dodge/Room/RezBox.hs +++ b/src/Dodge/Room/RezBox.hs @@ -31,7 +31,6 @@ import LensHelp import qualified Data.Set as S --import Data.Maybe -import Data.Tree import Control.Monad.State import System.Random diff --git a/src/Dodge/Room/Room.hs b/src/Dodge/Room/Room.hs index 98e45d60b..243a92ad6 100644 --- a/src/Dodge/Room/Room.hs +++ b/src/Dodge/Room/Room.hs @@ -30,7 +30,6 @@ import qualified Data.Set as S import Control.Monad.State --import Control.Monad.Loops import System.Random -import Data.Tree import Data.Bifunctor roomC :: RandomGen g => Float -> Float -> State g Room @@ -278,7 +277,7 @@ weaponBetweenPillars = do weaponLongCorridor :: RandomGen g => State g (SubCompTree Room) weaponLongCorridor = do - root <- takeOne [tEast, tWest] + rt <- takeOne [tEast, tWest] connectingRoom <- takeOne [tEast & rmPmnts .~ [spanLightI (V2 (-30) 40) (V2 (-30) 80)] ] @@ -286,7 +285,7 @@ weaponLongCorridor = do i2 <- state $ randomR (2,5) let branch1 = treeFromTrunk (replicate i1 $ PassDown corridorN) (singleUseAll $ putCrs connectingRoom) let branch2 = treeFromTrunk (replicate i2 $ PassDown corridorN) (singleUseNone $ putWp corridor) - return $ Node (PassDown root) [branch1,branch2] + return $ Node (PassDown rt) [branch1,branch2] where putCrs = over rmPmnts (++ [sPS (V2 10 40) (-pi/2) randC1 ,sPS (V2 (-10) 40) (-pi/2) randC1 ]) putWp = set rmPmnts [sPS (V2 20 60) 0 $ RandPS randFirstWeapon ,spanLightI (V2 0 40) (V2 40 40)] diff --git a/src/Dodge/Room/RunPast.hs b/src/Dodge/Room/RunPast.hs index e4ec8aadd..c89638c0d 100644 --- a/src/Dodge/Room/RunPast.hs +++ b/src/Dodge/Room/RunPast.hs @@ -26,7 +26,6 @@ import Color import LensHelp import qualified Data.Set as S -import Data.Tree import Control.Monad.State import System.Random --import qualified Data.IntMap.Strict as IM diff --git a/src/Dodge/Tree.hs b/src/Dodge/Tree.hs index 0eee9bfc7..d9d9d589e 100644 --- a/src/Dodge/Tree.hs +++ b/src/Dodge/Tree.hs @@ -2,12 +2,12 @@ module Dodge.Tree ( module Dodge.Tree.Shift , module Dodge.Tree.GenerateStructure - , module Dodge.Tree.Polymorphic + , module TreeHelp , module Dodge.Tree.Compose , module Dodge.Tree.Compose.Data ) where import Dodge.Tree.Shift import Dodge.Tree.GenerateStructure -import Dodge.Tree.Polymorphic +import TreeHelp import Dodge.Tree.Compose import Dodge.Tree.Compose.Data diff --git a/src/Dodge/Tree/Compose.hs b/src/Dodge/Tree/Compose.hs index 80a94cb2f..7243731de 100644 --- a/src/Dodge/Tree/Compose.hs +++ b/src/Dodge/Tree/Compose.hs @@ -10,16 +10,19 @@ module Dodge.Tree.Compose , changeToPassDown , overwriteLabel , applyToCompRoot + , composeTree + , composeTreeRand +-- , compTree ) where import Dodge.Tree.Compose.Data -import Dodge.Tree.Polymorphic +import TreeHelp import Dodge.Base import LensHelp +import Control.Monad.State +import Data.Foldable +import System.Random import Data.Maybe -import Data.Tree -import Data.Tree.Lens ---import Data.Bifunctor expandTree :: CompTree a -> Tree a expandTree (Node rt extChildren) = case rt of @@ -32,11 +35,11 @@ expandTree (Node rt extChildren) = case rt of $ map (:[]) extChildren ++ repeat [] applyToCompRoot :: (a -> a) -> SubCompTree a -> SubCompTree a -applyToCompRoot f = applyToRoot (unCompose %~ f) +applyToCompRoot f = over root (unCompose %~ f) overwriteLabel :: Int -> (a -> ComposingNode a) -> SubCompTree a -> [SubCompTree a] -> SubCompTree a overwriteLabel i f t ts = errorHead ("tried to overwriteLabel " ++ show i) - $ updateSingleNode islabel update t + $ updateSingleNodes islabel update t where islabel (UseLabel j _) | i == j = True islabel _ = False @@ -65,17 +68,27 @@ singleUseNone x = Node (UseNone x) [] changeToPassDown :: ComposingNode a -> ComposingNode a changeToPassDown x = PassDown (_unCompose x) ---cTree :: Tree (a -> Maybe a, Tree a) -> Tree a ---cTree (Node (_,t) ch) = shiftChildren $ foldr g' (fdsa t) (map cTree ch) +composeTreeRand :: RandomGen g => Tree (a -> Maybe a, Tree a) -> State g (Tree a) +composeTreeRand (Node (_,t) ts) = attachListR t ts -cTree' :: Tree (a -> Maybe a, Tree a) -> Tree a -cTree' (Node (_,t) ts) = cTree t ts +attachListR :: RandomGen g => Tree a -> [Tree (a -> Maybe a, Tree a)] -> State g (Tree a) +attachListR t xs = fmap shiftChildren $ foldrM newfRand (fmap ([],) t) xs -cTree :: Tree a -> [Tree (a -> Maybe a, Tree a)] -> Tree a -cTree t xs = shiftChildren $ foldr newf (fmap ([],) t) xs +newfRand :: RandomGen g => Tree (a -> Maybe a,Tree a) -> Tree ([Tree a],a) + -> State g (Tree ([Tree a],a)) +newfRand t = updateRandNode (isJust . upf . snd) ( (root . _2 %~ g) . (root . _1 .:~ composeTree t ) ) + where + upf = (t ^?! root . _1) + g x = fromMaybe x (upf x) + +composeTree :: Tree (a -> Maybe a, Tree a) -> Tree a +composeTree (Node (_,t) ts) = attachList t ts + +attachList :: Tree a -> [Tree (a -> Maybe a, Tree a)] -> Tree a +attachList t xs = shiftChildren $ foldr newf (fmap ([],) t) xs newf :: Tree (a -> Maybe a,Tree a) -> Tree ([Tree a],a) -> Tree ([Tree a],a) -newf t = safeUpdateSingleNode (isJust . upf . snd) ( (root . _2 %~ g) . (root . _1 .:~ cTree' t ) ) +newf t = safeUpdateSingleNode (isJust . upf . snd) ( (root . _2 %~ g) . (root . _1 .:~ composeTree t ) ) where upf = (t ^?! root . _1) g x = fromMaybe x (upf x) @@ -83,25 +96,25 @@ newf t = safeUpdateSingleNode (isJust . upf . snd) ( (root . _2 %~ g) . (root . shiftChildren :: Tree ([Tree a],a) -> Tree a shiftChildren (Node (ts,x) ts') = Node x (ts ++ map shiftChildren ts') --- hideous, but it should work --- the idea is that the fst argument selects (and edits) a node to which all the --- children are attached --- the tree is thus built up recursively -compTree :: Tree (a -> Maybe a, Tree (a,b)) -> Tree b -compTree (Node (_,t) ch) = attachChildren t $ map (\t' -> (fst $ rootLabel t',compTree t')) ch - -chooseAttachNodes :: (a -> Maybe a,c) -> Tree (a,b,[c]) -> [Tree (a,b,[c])] -chooseAttachNodes (t,z) (Node (x,y,zs) ch) = case t x of - Just x' -> Node (x',y,(z:zs)) ch : concatMap (chooseAttachNodes (t,z)) ch - Nothing -> concatMap (chooseAttachNodes (t,z)) ch - -mAttachToNode :: (a -> Maybe a,c) -> Tree (a,b,[c]) -> Tree (a,b,[c]) -mAttachToNode p t = fromMaybe t $ listToMaybe $ chooseAttachNodes p t - -moveToChildren :: Tree (a,b,[Tree b]) -> Tree b -moveToChildren (Node (_,x,ts) ts') = Node x (map moveToChildren ts' ++ ts) - -attachChildren :: Tree (a,b) -> [(a->Maybe a,Tree b)] -> Tree b -attachChildren t = moveToChildren . foldr mAttachToNode t' - where - t' = fmap (\(x,y) -> (x,y,[])) t +---- hideous, but it should work +---- the idea is that the fst argument selects (and edits) a node to which all the +---- children are attached +---- the tree is thus built up recursively +--compTree :: Tree (a -> Maybe a, Tree (a,b)) -> Tree b +--compTree (Node (_,t) ch) = attachChildren t $ map (\t' -> (fst $ rootLabel t',compTree t')) ch +-- +--chooseAttachNodes :: (a -> Maybe a,c) -> Tree (a,b,[c]) -> [Tree (a,b,[c])] +--chooseAttachNodes (t,z) (Node (x,y,zs) ch) = case t x of +-- Just x' -> Node (x',y,(z:zs)) ch : concatMap (chooseAttachNodes (t,z)) ch +-- Nothing -> concatMap (chooseAttachNodes (t,z)) ch +-- +--mAttachToNode :: (a -> Maybe a,c) -> Tree (a,b,[c]) -> Tree (a,b,[c]) +--mAttachToNode p t = fromMaybe t $ listToMaybe $ chooseAttachNodes p t +-- +--moveToChildren :: Tree (a,b,[Tree b]) -> Tree b +--moveToChildren (Node (_,x,ts) ts') = Node x (map moveToChildren ts' ++ ts) +-- +--attachChildren :: Tree (a,b) -> [(a->Maybe a,Tree b)] -> Tree b +--attachChildren t = moveToChildren . foldr mAttachToNode t' +-- where +-- t' = fmap (\(x,y) -> (x,y,[])) t diff --git a/src/Dodge/Tree/Shift.hs b/src/Dodge/Tree/Shift.hs index 4ef378c33..f3bb4408a 100644 --- a/src/Dodge/Tree/Shift.hs +++ b/src/Dodge/Tree/Shift.hs @@ -10,7 +10,7 @@ module Dodge.Tree.Shift --import Dodge.LevelGen.Data import Dodge.Data import Dodge.Room.Link -import Dodge.Tree.Polymorphic +import TreeHelp import Dodge.RoomLink import Geometry.ConvexPoly --import Geometry.Data @@ -19,7 +19,6 @@ import LensHelp hiding (Empty, (<|) , (|>)) --import Control.Lens hiding (Empty, (<|) , (|>)) import qualified Data.Set as S -import Data.Tree import qualified Data.Sequence as Seq import Data.List (delete) import Data.Bifunctor @@ -100,7 +99,7 @@ posRms prs parenti@(parent,_) ( (numChild,t@(Node childi _) ):its) tseq = do , _rpLinkStatus = UsedInLink (_rlType il) (snd parenti) , _rpPlacementUse = 0 } - shiftedt = applyToRoot + shiftedt = over root (first $ updatechild . shiftRoomShiftToLink (lnkPosDir shiftedoutlink) (lnkPosDir il)) t diff --git a/src/Dodge/Tree/Polymorphic.hs b/src/TreeHelp.hs similarity index 78% rename from src/Dodge/Tree/Polymorphic.hs rename to src/TreeHelp.hs index 116b70794..8ad31c84c 100644 --- a/src/Dodge/Tree/Polymorphic.hs +++ b/src/TreeHelp.hs @@ -5,10 +5,11 @@ For example, in the tree > Node a [ Node b [], Node c [Node d []] ] -the nodes in the trunk are [a,b] (note that d is not the first child of b). +the nodes in the trunk are [a,b]. -} -module Dodge.Tree.Polymorphic - ( applyToRoot +module TreeHelp + ( module Data.Tree + , module Data.Tree.Lens , applyToSubtree , applyToSubforest , treeFromPost @@ -17,7 +18,8 @@ module Dodge.Tree.Polymorphic , applyToRandomNode , addToTrunk , inorderNumberTree - , updateSingleNode + , updateSingleNodes + , updateRandNode , safeUpdateSingleNode ) where import Dodge.RandomHelp @@ -32,8 +34,7 @@ import Control.Lens {- | Creates a linear tree. Safe. -} treeFromPost :: [a] -> a -> Tree a -treeFromPost [] y = Node y [] -treeFromPost (x:xs) y = Node x [treeFromPost xs y] +treeFromPost xs = treeFromTrunk xs . pure {- | Creates a tree with one trunk branch, input as a list, that ends in another tree. -} @@ -41,12 +42,9 @@ treeFromTrunk :: [a] -- ^ The trunk -> Tree a -- ^ The end of the tree -> Tree a -treeFromTrunk [] t = t -treeFromTrunk (x:xs) t = Node x [treeFromTrunk xs t] - -{- | Applies a function to the root of a tree. -} -applyToRoot :: (a -> a) -> Tree a -> Tree a -applyToRoot f (Node t ts) = Node (f t) ts +treeFromTrunk = flip $ foldr f + where + f x t = Node x [t] -- find use for? ---- | Consider defining this using generalised recursion patterns @@ -56,26 +54,22 @@ applyToRoot f (Node t ts) = Node (f t) ts {- | Applies a function to a specific node determined by a list of indices. Unsafe (partial function). -} applyToNode :: [Int] -> (a -> a) -> Tree a -> Tree a -applyToNode [] f t = applyToRoot f t -applyToNode (i:is) f (Node x xs) = Node x (ys ++ [applyToNode is f z] ++ zs) - where - (ys, z:zs) = splitAt i xs +applyToNode is = applyToSubtree is . over root {- | Applies a function to a specific subtree determined by a list of indices. Unsafe (partial function). -} applyToSubtree :: [Int] -> (Tree a -> Tree a) -> Tree a -> Tree a applyToSubtree [] f t = f t -applyToSubtree (i:is) f (Node x xs) = Node x (ys ++ [applyToSubtree is f z] ++ zs) - where - (ys, z:zs) = splitAt i xs +applyToSubtree (i:is) f (Node x xs) = Node x (xs & ix i %~ applyToSubtree is f) {- | Applies a function to a specific subforest determined by a list of indices. Unsafe (partial function). -} applyToSubforest :: [Int] -> ([Tree a] -> [Tree a]) -> Tree a -> Tree a -applyToSubforest [] f (Node p cs) = Node p (f cs) -applyToSubforest (i:is) f (Node x xs) = Node x (ys ++ [applyToSubforest is f z] ++ zs) - where - (ys, z:zs) = splitAt i xs +applyToSubforest is = applyToSubtree is . over branches +--applyToSubforest [] f (Node p cs) = Node p (f cs) +--applyToSubforest (i:is) f (Node x xs) = Node x (ys ++ [applyToSubforest is f z] ++ zs) +-- where +-- (ys, z:zs) = splitAt i xs -- do not delete: find use for --{- | @@ -88,24 +82,25 @@ applyToSubforest (i:is) f (Node x xs) = Node x (ys ++ [applyToSubforest is f z] --applyToSubTrunkBy _ _ t = t -- gives the list of all updates to a single node -updateSingleNode :: (a -> Bool) -> (Tree a -> Tree a) -> Tree a -> [Tree a] -updateSingleNode f update t@(Node x ts) +-- there must be a better way of doing something like this +updateSingleNodes :: (a -> Bool) -> (Tree a -> Tree a) -> Tree a -> [Tree a] +updateSingleNodes f update t@(Node x ts) | f x = update t : updateChildren | otherwise = updateChildren where - updateChildren = map (Node x) (subMap (updateSingleNode f update) ts) + updateChildren = map (Node x) (subMap (updateSingleNodes f update) ts) + +updateRandNode :: RandomGen g => (a -> Bool) -> (Tree a -> Tree a) -> Tree a -> State g (Tree a) +updateRandNode t f = takeOne . updateSingleNodes t f + safeUpdateSingleNode :: (a -> Bool) -> (Tree a -> Tree a) -> Tree a -> Tree a -safeUpdateSingleNode f g t = fromMaybe t $ listToMaybe $ updateSingleNode f g t +safeUpdateSingleNode f g t = fromMaybe t $ listToMaybe $ updateSingleNodes f g t subMap :: (a -> [a]) -> [a] -> [[a]] subMap f (x:xs) = (f x <&> (: xs)) ++ ( (x :) <$> subMap f xs ) subMap _ [] = [] ---subMap' :: Monad m => (a -> m a) -> [a] -> m [a] ---subMap' f (x:xs) = (f x <&> (: xs)) ++ ( (x :) <$> (subMap f xs) ) ---subMap' f [] = - -- find use for? --zipTree :: Tree a -> Tree b -> Tree (a,b) --zipTree (Node x xs) (Node y ys) = Node (x,y) $ zipWith zipTree xs ys