Files
loop/src/Dodge/Tree/Shift.hs
T

183 lines
6.5 KiB
Haskell

{-# LANGUAGE StrictData #-}
{-# LANGUAGE TemplateHaskell #-}
{- | 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.
-}
module Dodge.Tree.Shift (
positionRoomsFromTree,
PosRooms (..),
) where
--import Data.Monoid
import Control.Lens
import Data.Bifunctor
import Data.List (delete)
import qualified Data.Sequence as Seq
import qualified Data.Set as S
import Dodge.Data.GenWorld
import Dodge.Room.Link
import Dodge.RoomLink
import Geometry.ConvexPoly
import LensHelp hiding (Empty, (<|), (|>))
import Padding
import TreeHelp
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 ?~ i
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)
-- | Just xs <- clipping' = do
-- putStrLn $ show xs
-- tryChildLinks 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)
-- clipping' = getFirst . foldMap First $ convexPolysOverlapWitness <$> 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)
{ _rpPos = outlnk ^. rlPos
, _rpDir = outlnk ^. rlDir
, _rpFlags = S.empty
, _rpType = UsedOutLink (_rlType outlnk) numChild (snd childi)
, _rpPlacementUse = mempty
}
& 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 outlnk)
--, _rpDir = snd (lnkPosDir outlnk)
{ _rpPos = il ^. rlPos
, _rpDir = il ^. rlDir
, _rpFlags = mempty
, _rpType = UsedInLink (_rlType il) (snd parenti)
, _rpPlacementUse = mempty
}
shiftedt =
over
root
(first $ updatechild . shiftRoomShiftToLink
(shiftedoutlink ^. rlPos, shiftedoutlink ^. rlDir)
(il ^. rlPos, il ^. rlDir))
t
createUnusedLinkPos :: Room -> Room
createUnusedLinkPos rm = rm & rmPos .++~ map f (_rmLinks rm)
where
f rl =
RoomPos
{ _rpPos = _rlPos rl
, _rpDir = _rlDir rl
, _rpFlags = mempty
, _rpType = UnusedLink $ _rlType rl
, _rpPlacementUse = mempty
}
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