157 lines
5.6 KiB
Haskell
157 lines
5.6 KiB
Haskell
{- | Given a tree of rooms, tries to shift them into place in such a way that their
|
|
links connect and that none of them clip.
|
|
Creates a list of rooms; after this step the structure is determined by the actual positions of rooms. -}
|
|
{-# LANGUAGE TemplateHaskell #-}
|
|
{-# LANGUAGE StrictData #-}
|
|
module Dodge.Tree.Shift
|
|
( positionRoomsFromTree
|
|
, PosRooms (..)
|
|
) where
|
|
--import Dodge.LevelGen.Data
|
|
import Dodge.Data
|
|
import Dodge.Room.Link
|
|
import TreeHelp
|
|
import Dodge.RoomLink
|
|
import Geometry.ConvexPoly
|
|
--import Geometry.Data
|
|
import Padding
|
|
import LensHelp hiding (Empty, (<|) , (|>))
|
|
--import Control.Lens hiding (Empty, (<|) , (|>))
|
|
|
|
import qualified Data.Set as S
|
|
import qualified Data.Sequence as Seq
|
|
import Data.List (delete)
|
|
import Data.Bifunctor
|
|
import Control.Lens
|
|
|
|
type RoomInt = (Room,Int)
|
|
|
|
data PosRooms = PosRooms
|
|
{ _prBounds :: [ConvexPoly]
|
|
, _prRooms :: [RoomInt]
|
|
}
|
|
makeLenses ''PosRooms
|
|
|
|
|
|
positionRoomsFromTree :: Tree RoomInt -> IO (Maybe PosRooms)
|
|
positionRoomsFromTree (Node (r,i) ts) = printColumnTitles
|
|
>> fmap (fmap (prRooms %~ map (first createUnusedLinkPos)))
|
|
(posRms (PosRooms (map pointsToPoly $ _rmBound r') []) (r',i) (zipCount ts) Empty)
|
|
where
|
|
r' = r & rmMID ?~ 0
|
|
|
|
posRms :: PosRooms
|
|
-> RoomInt
|
|
-> [(Int,Tree RoomInt)] -- the list of children, with indices
|
|
-> Seq.Seq (Tree RoomInt)
|
|
-> IO (Maybe PosRooms)
|
|
posRms prs roomi [] st = case st of
|
|
Empty -> return $ Just $ prs & prRooms .:~ roomi
|
|
Node nextroomi ts Seq.:<| tseq -> posRms (prs & prRooms .:~ roomi) nextroomi (zipCount ts) tseq
|
|
_ -> error "unexpected outcome in posRms"
|
|
posRms prs parenti@(parent,_) ( (numChild,t@(Node childi _) ):its) tseq = do
|
|
printInfoCheckNum parenti numChild childi
|
|
tryParentLinks outlinks
|
|
where
|
|
child = fst childi
|
|
outlinks = zipCount
|
|
. Prelude.filter (_rmConnectsTo child . _rlType)
|
|
$ _rmLinks parent
|
|
tryParentLinks [] = putStrLn "no viable link pairs, backtrack" >> return Nothing
|
|
tryParentLinks ((j,outlnk):ls) = tryChildLinks . zipCount . rmInLinks $ fst childi
|
|
where
|
|
tryChildLinks [] = tryParentLinks ls
|
|
tryChildLinks ((numinlink,il):ils)
|
|
| clipping = tryChildLinks ils
|
|
| otherwise = do
|
|
putStrLn $ show j ++ "-" ++ show numinlink
|
|
mayrs <- posRms
|
|
(prs & prBounds .++~ newBounds)
|
|
(first updateparent parenti)
|
|
its
|
|
(tseq |> shiftedt)
|
|
case mayrs of
|
|
Just rms -> return $ Just rms
|
|
Nothing -> printInfo parenti numChild childi
|
|
>> tryChildLinks ils
|
|
where
|
|
newBounds = map pointsToPoly . _rmBound . doRoomShift . fst $ rootLabel shiftedt
|
|
clipping = or (convexPolysOverlap <$> newBounds <*> _prBounds prs)
|
|
updateparent rm = _rmLinkEff rm il child numChild outlnk rm
|
|
& rmLinks %~ delete outlnk
|
|
& rmPos .:~ RoomPos
|
|
{ _rpPos = fst (lnkPosDir outlnk)
|
|
, _rpDir = snd (lnkPosDir outlnk)
|
|
, _rpType = S.empty
|
|
, _rpLinkStatus = UsedOutLink (_rlType outlnk) numChild (snd childi)
|
|
, _rpPlacementUse = 0
|
|
}
|
|
& rmChildren .:~ snd childi
|
|
shiftedoutlink = shiftLinkBy (_rmShift parent) outlnk
|
|
updatechild rm = rm
|
|
& rmMParent ?~ snd parenti
|
|
& rmMID ?~ snd childi
|
|
& rmLinks %~ delete il
|
|
& rmPos .:~ RoomPos
|
|
{ _rpPos = fst (lnkPosDir il)
|
|
, _rpDir = snd (lnkPosDir il)
|
|
, _rpType = S.empty
|
|
, _rpLinkStatus = UsedInLink (_rlType il) (snd parenti)
|
|
, _rpPlacementUse = 0
|
|
}
|
|
shiftedt = over root
|
|
(first $ updatechild . shiftRoomShiftToLink (lnkPosDir shiftedoutlink) (lnkPosDir il))
|
|
t
|
|
|
|
createUnusedLinkPos :: Room -> Room
|
|
createUnusedLinkPos rm = rm & rmPos .++~ map f (_rmLinks rm)
|
|
where
|
|
f rl = RoomPos
|
|
{ _rpPos = _rlPos rl
|
|
, _rpDir = _rlDir rl
|
|
, _rpType = S.empty
|
|
, _rpLinkStatus = UnusedLink $ _rlType rl
|
|
, _rpPlacementUse = 0
|
|
}
|
|
|
|
zipCount :: [a] -> [(Int,a)]
|
|
zipCount = Prelude.zip [0..]
|
|
|
|
printColumns :: [Int] -> [String] -> IO ()
|
|
printColumns is ss = printPartialColumns is ss >> putStrLn ""
|
|
|
|
printPartialColumns :: [Int] -> [String] -> IO ()
|
|
printPartialColumns (i:is) (s:strs) = putStr (rightPad i ' ' s) >> printPartialColumns is strs
|
|
printPartialColumns _ strs = putStr $ concat strs
|
|
|
|
theColumns :: [String] -> IO ()
|
|
theColumns = printColumns [20,5,20,20]
|
|
|
|
printColumnTitles :: IO ()
|
|
printColumnTitles = theColumns ["Parent","Cnum","Child","Link pair"]
|
|
|
|
printInfo :: (Show a) => RoomInt -> a -> RoomInt -> IO ()
|
|
printInfo (parentrm,parenti) childn (childrm,childi) = printPartialColumns
|
|
[20,5,20]
|
|
[_rmName parentrm ++ "-" ++ show parenti
|
|
,show childn ++ " "
|
|
,_rmName childrm ++ "-" ++ show childi
|
|
]
|
|
|
|
printInfoCheckNum :: (Show a, Eq a, Num a) => RoomInt -> a -> RoomInt -> IO ()
|
|
printInfoCheckNum (parentrm,parenti) childn (childrm,childi) = printPartialColumns
|
|
[20,5,20]
|
|
[rname
|
|
,show childn
|
|
,_rmName childrm ++ "-" ++ show childi
|
|
]
|
|
where
|
|
rname = case childn of
|
|
0 -> _rmName parentrm ++ "-" ++ show parenti
|
|
_ -> ""
|
|
|
|
--doLnkEff :: RoomLink -> Room -> Room
|
|
--doLnkEff x rm = case _rmLinkEff rm of
|
|
-- (eff:effs) -> eff x $ rm & rmLinkEff .~ effs
|
|
-- _ -> rm
|