{- | 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