--{-# LANGUAGE TupleSections #-} module Dodge.Room.Room ( shootingRange , weaponRoom , roomMiniIntro , roomCCrits , doubleCorridorBarrels , pistolerRoom , spawnerRoom , corDoor ) where import Dodge.Cleat import Dodge.Data import Dodge.PlacementSpot import Dodge.RoomLink import Dodge.Default.Room import Dodge.Item.Weapon import Dodge.Creature import Dodge.Room.Pillar import Dodge.Room.Girder import Dodge.Room.Modify.Girder import Dodge.LevelGen.Data import RandomHelp import Dodge.Tree import Dodge.Placement.Instance --import Dodge.LevelGen.Data import Dodge.Room.Procedural import Dodge.Room.Corridor import Dodge.Room.Tanks import Dodge.Room.Link import Dodge.Room.Door import Dodge.Room.Airlock import Geometry import MonadHelp import LensHelp import qualified Data.Set as S roomC :: RandomGen g => Float -> Float -> State g Room roomC w h = do wallf <- takeOne [ crystalLine , windowLine ] ntanks <- takeOne [0,0,0,0,0,1,1,1,1,2,3,4] thetank <- randomTank <&> plSpot .~ rprBool (\rp _ -> _rpPlacementUse rp == 0 && rpIsOffPath rp && (xV2 (_rpPos rp) > w / 2 + 5 || xV2 (_rpPos rp) < w / 2 - 5 )) maybeaddgird <- takeOne [return, addRandomGirderFrom West 0, addRandomGirderFrom North 0] maybeaddgird =<< shuffleLinks (roomRectAutoLinks w h & rmLinks %~ ( setInLinks (\rl -> S.fromList [FromEdge East 0,OnEdge South] `S.isSubsetOf` _rlType rl) . setOutLinks (\rl -> OnEdge West `S.member` _rlType rl) ) & rmPmnts .++~ (wallf (V2 (w/2) 0) (V2 (w/2) (h-60)) : replicate ntanks thetank) & rmRandPSs .~ [farside] ) where farside = do x <- state $ randomR (5, w/2 - 20) y <- state $ randomR (5, h - 70) a <- state $ randomR (0, 2*pi) return (V2 x y,a) roomPadCut :: [Point2] -> Point2 -> Room roomPadCut ps p = defaultRoom { _rmPolys = [ps] , _rmLinks = muout [(p,0)] ++ muin [(V2 0 0,pi)] , _rmPath = [(V2 0 0,p)] } branchWith :: Room -> [Tree Room] -> Tree Room branchWith r = Node r . (return (cleatOnward door) :) glassSwitchBack :: RandomGen g => State g Room glassSwitchBack = do wth <- state $ randomR (200,400) hgt <- state $ randomR (400,600) wllen <- state $ randomR (60,wth/2-40) let hf = hgt/5 awindow h xl xr = windowLine (V2 xl h) (V2 xr h) plmnts = [awindow hf (wth-60) wllen ,awindow (2*hf) (wth-wllen) 60 ,awindow (3*hf) (wth-60) wllen ,awindow (4*hf) (wth-wllen) 60 ,blockLine (V2 0 (1*hf)) (V2 wllen (1*hf)) ,blockLine (V2 (wth-wllen) (2*hf)) (V2 wth (2*hf)) ,blockLine (V2 0 (3*hf)) (V2 wllen (3*hf)) ,blockLine (V2 (wth-wllen) (4*hf)) (V2 wth (4*hf)) , sPS (V2 (wth/2) (hgt/2)) 0 putLamp ] let northPSs = do cry <- randomRanges [3*hf+10,4*hf-10 ,4*hf+10,5*hf-10 ] crx <- state $ randomR (wllen,wth-(wllen+40)) return (V2 crx cry,1.5*pi) midPS = return (V2 (wth-20) (hgt/2+40), pi) return $ roomRect wth hgt 2 4 & rmPmnts .~ plmnts & rmRandPSs .~ [northPSs,midPS] & rmName .~ "glassSwitchBack" glassSwitchBackCrits :: RandomGen g => State g Room glassSwitchBackCrits = glassSwitchBack <&> rmPmnts .++~ [ spNoID (PSRoomRand 0 (uncurry PS)) (PutCrit miniGunCrit) , spNoID (PSRoomRand 1 (uncurry PS)) randC1 ] miniTree2 :: RandomGen g => State g (Tree Room) miniTree2 = do rm <- glassSwitchBackCrits >>= shuffleLinks . restrictInLinks (\p -> (sndV2 . fst) p < 70) return $ branchWith rm (replicate 3 $ treePost [door,corridor,critInDeadEnd]) -- So, the idea is to attach outer children to the bottommost right nodes -- inside an inner tree -- no idea what was going on here... roomMiniIntro :: RandomGen g => State g (MetaTree Room String) roomMiniIntro = do midroom <- join $ takeOne [miniTree2] --,glassLesson] rToOnward "roomMiniIntro" midroom roomCenterPillar :: RandomGen g => State g Room roomCenterPillar = do addHighGirder' =<< (shuffleLinks . restrictInLinks ((\p -> dist p (V2 120 0) < 10) . fst) $ cleatSide $ set rmPmnts plmnts $ set rmName "roomCenterPillar" $ roomRect 240 240 2 2 ) where plmnts = [ blockLine (V2 115 115) (V2 115 125) , blockLine (V2 125 115) (V2 125 125) -- , mntLightLnkCond useUnusedLnk , mntLightLnkCond (resetPLUse $ rprBool $ \rp _ -> isInLnk rp) , mntLightLnkCond (resetPLUse $ rprBool $ \rp _ -> isOutLnk rp) ] {- Probabilites of the type of the first floor weapon. -} randFirstWeapon :: State StdGen PSType randFirstWeapon = takeOne $ map PutFlIt $ replicate 10 pistol ++ replicate 5 (bangStick 4) ++ replicate 5 (bangCaneX 3) ++ replicate 5 bangCone ++ [lasGun] weaponEmptyRoom :: RandomGen g => State g (Tree Room) weaponEmptyRoom = do w <- state $ randomR (220,300) h <- state $ randomR (220,300) let plmnts = [sPS (V2 (w/2) (h-40)) 0 $ RandPS randFirstWeapon ,sPS (V2 20 20) (pi/2) randC1 ,sPS (V2 (w-20) 20) (pi/2) randC1 ,mntLightLnkCond useUnusedLnk ] f (V2 x y,a) = (a == pi && x > 25 && x < w - 25) || (a /= 0 && y > w - 30) rm <- addHighGirder >=> shuffleLinks $ restrictRMInLinksPD f (roomRect w h 2 2 & rmPmnts .~ plmnts) return $ treePost [ corridor, cleatSide $ cleatOnward rm ] weaponUnderCrits :: RandomGen g => Int -> State g (MetaTree Room String) weaponUnderCrits i = do let addwpat p = rmPmnts .:~ PickOnePlacement i (sPS p 0 $ RandPS randFirstWeapon) continuationRoom = treePost [ addwpat (V2 20 0) corridorN , addwpat (V2 20 0) corridorN , cleatOnward $ corridorN & rmPmnts .~ [ sPS (V2 20 0) (negate $ pi/2) randC1 , sPS (V2 20 20) ( pi/2) randC1 ] ] rcp <- roomCenterPillar rmpils <- roomPillars 30 240 240 2 2 deadEndRoom' <- takeOne [ addwpat (V2 120 20) rmpils , addwpat (V2 120 20) $ cleatSide rcp] junctionRoom <- takeOne [ tEast, tWest] rToOnward "weaponUnderCrits" $ treeFromTrunk [ corridorN , corridorN] $ Node junctionRoom [continuationRoom ,pure deadEndRoom' ] weaponBehindPillar :: RandomGen g => State g (Tree Room) weaponBehindPillar = do wpa <- state $ randomR (0,pi) wpos <- takeOne [V2 120 160,V2 80 40,V2 160 40,V2 220 200,V2 40 200,V2 120 35] cpos <- takeOne $ [V2 x y | x <- [20,220], y <- [20,40]] ++ [V2 120 160,V2 120 200] rcp <- roomCenterPillar return $ treePost [ corridor , rcp & rmPmnts ++.~ [sPS wpos wpa $ RandPS randFirstWeapon ,sPS cpos (argV $ V2 120 80 -.- cpos) randC1 ] , cleatOnward $ set rmPmnts [sPS (V2 20 60) (negate $ pi/2) randC1] corridorN ] weaponBetweenPillars :: RandomGen g => State g (Tree Room) weaponBetweenPillars = do (w,wn) <- takeOne [(240,2),(340,3)] (h,hn) <- takeOne [(240,2),(340,3)] let wpPos = rprBool $ \rp r -> and [ rpIsOnPath rp , _rpPlacementUse rp == 0 , _rpLinkStatus rp == NotLink , any ((<100) . dist (_rpPos rp)) (usedRoomInLinkPoss r) ] ncrits <- state $ randomR (1,3) critPlacementSpots <- replicateM ncrits $ randDirPS $ rprBool $ \rp r -> rpIsOnPath rp && _rpPlacementUse rp == 0 && all ((>100) . dist (_rpPos rp)) (usedRoomLinkPoss r) fmap pure $ roomPillars 30 w h wn hn <&> rmPmnts .++~ sps wpPos (RandPS randFirstWeapon) : map (`sps` randC1) critPlacementSpots <&> cleatOnward weaponLongCorridor :: RandomGen g => State g (Tree Room) weaponLongCorridor = do rt <- takeOne [tEast, tWest] connectingRoom <- takeOne [tEast & rmPmnts .~ [spanLightI (V2 (-30) 40) (V2 (-30) 80)] ] i1 <- state $ randomR (2,5) i2 <- state $ randomR (2,5) let branch1 = treeFromTrunk (replicate i1 corridorN) (pure . cleatSide . cleatOnward $ putCrs connectingRoom) let branch2 = treeFromTrunk (replicate i2 corridorN) (pure . cleatSide $ putWp corridor) return $ Node rt [branch1,branch2] where putCrs = rmPmnts .++~ [sPS (V2 10 40) (-pi/2) randC1 ,sPS (V2 (-10) 40) (-pi/2) randC1 ] putWp = rmPmnts .~ [sPS (V2 20 60) 0 $ RandPS randFirstWeapon ,spanLightI (V2 0 40) (V2 40 40)] critInDeadEnd :: Room critInDeadEnd = deadEndRoom & rmPmnts .~ [sPS (V2 0 0) 0 randC1] deadEndRoom :: Room deadEndRoom = defaultRoom { _rmPolys = [rectNSWE 40 (-20) (-20) 20 ] , _rmLinks = muout (init lnks) ++ muin [last lnks] , _rmPath = [] , _rmPmnts = [sPS (V2 0 (-10)) 0 putLamp] , _rmBound = [rectNSWE 20 (-20) (-30) 30] , _rmName = "deadEndRoom" } where lnks = [(V2 0 30 ,0) ] {- A random Either tree with a weapon and melee monster challenge. -} weaponRoom :: RandomGen g => Int -> State g (MetaTree Room String) weaponRoom i = join $ takeOne [ weaponEmptyRoom >>= rToOnward "weaponEmptyRoom" , weaponUnderCrits i -- this int is used for PickOnePlacement , weaponBehindPillar >>= rToOnward "weaponBehindPillar" , weaponBetweenPillars >>= rToOnward "weaponBetweenPillars" , weaponLongCorridor >>= rToOnward "weaponLongCorridor" ] roomCCrits :: RandomGen g => Int -> State g Room roomCCrits i = roomC 200 200 <&> rmPmnts .++~ replicate i (spNoID (PSRoomRand 0 (uncurry PS)) randC1) doubleCorridorBarrels :: RandomGen g => State g Room doubleCorridorBarrels = do h <- state $ randomR (200,300) let cond x = (sndV2 . fst) x < h - 40 return $ restrictInLinks cond $ roomRect 100 h 1 1 & rmPmnts .~ [blockLine (V2 50 50) (V2 50 h) ,sPS (V2 25 (h-25)) (negate pi/2) $ PutCrit $ addArmour autoCrit ,sPS (V2 75 (h-80)) 0 putLamp ] ++ [sPS p 0 $ PutCrit explosiveBarrel | p <- [ V2 75 (h-30) ,V2 75 (h-60) ,V2 85 (h-10) ,V2 85 (h-45) ] ] shootersRoom' :: RandomGen g => State g Room shootersRoom' = do w <- state $ randomR (200,300) x1 <- state $ randomR (20,w/3-20) x2 <- state $ randomR (w/3+20,2*w/3-20) x3 <- state $ randomR (2*w/3+20,w-20) y1 <- state $ randomR (280,550) y2 <- state $ randomR (280,550) y3 <- iterateWhile (\y' -> abs (y1 - y2) < 60 && abs (y2 - y') < 60) $ state $ randomR (280,560) x4 <- state $ randomR (60,w-60) y4 <- state $ randomR (40,150) let bln x y = putBlockN (x+25) (x-25) (y+20) (y+10) blv x y = putBlockV (x+25) (x-25) (y+20) (y+10) plmnts = bln x1 y1 ++ bln x2 y2 ++ bln x3 y3 ++ blv x4 y4 ++ [spanLightI (V2 (-10) 200) (V2 (w/2) 200) ,spanLightI (V2 (w/2) 200) (V2 (w+10) 200) ] toPS x y = return (V2 x y,-0.5*pi) return $ set rmPmnts plmnts $ roomRectAutoLinks w 600 & rmPmnts .~ plmnts & rmRandPSs .~ [toPS x1 y1,toPS x2 y2,toPS x3 y3] shootersRoom1 :: RandomGen g => State g Room shootersRoom1 = shootersRoom' <&> rmPmnts .:~ RandomPlacement (takeOne $ map (\i -> spNoID (PSRoomRand i (uncurry PS)) (PutCrit autoCrit)) [0,1,2]) shootersRoom :: RandomGen g => State g Room shootersRoom = shootersRoom' <&> rmPmnts .++~ map (\i -> spNoID (PSRoomRand i (uncurry PS)) (PutCrit autoCrit)) [0,1,2] -- TODO stop from spawning on inlinks fromedge pistolerRoom :: RandomGen g => State g Room pistolerRoom = do (w,wn) <- takeOne [(200,3),(255,4)] roomPillars 10 w 200 wn 3 <&> rmPmnts .++~ replicate 3 (spNoID (rprBool $ \rp _ -> _rpPlacementUse rp == 0 && rpIsOnPath rp) (PutCrit pistolCrit)) shootingRange :: RandomGen g => State g (MetaTree Room String) shootingRange = do rm1 <- shootersRoom1 >>= shuffleLinks . restrictInLinks (\(V2 _ y,_) -> y < 40) . restrictOutLinks (\(V2 _ y,r) -> y > 200 && r /= 0) rm2 <- shootersRoom >>= shuffleLinks . restrictInLinks (\(V2 x y,_) -> y < 10 && x > 20 && x < 180) . restrictOutLinks (\(V2 _ y,r) -> y > 200 && r /= 0) rm3 <- shootersRoom >>= shuffleLinks . restrictInLinks (\(V2 x y,_) -> y < 10 && x > 20 && x < 180) . restrictOutLinks (\(_,r) -> r == 0) let padcutroom = roomPadCut (rectNSWE 40 (-40) (-80) 80) (V2 0 20) & rmPmnts .:~ spanLightI (V2 (-80) 10) (V2 80 10) rToOnward "shootingRange" $ treePost [ rm1 , padcutroom , rm2 , padcutroom , cleatOnward rm3 ] spawnerRoom :: RandomGen g => State g (Tree Room) spawnerRoom = do x <- state $ randomR (250,300) y <- state $ randomR (300,400) roomWithSpawner <- roomC x y <&> rmPmnts .:~ spNoID (rprBool $ \rp _ -> _rpPlacementUse rp == 0 && rpIsOnPath rp && xV2 (_rpPos rp) < x/2 && yV2 (_rpPos rp) < y/2 ) (PutCrit spawnerCrit) aRoom <- airlock return $ treeFromTrunk [ aRoom, corridor] $ pure $ cleatOnward roomWithSpawner corDoor :: State StdGen (MetaTree Room String) corDoor = do cor <- shuffleLinks $ cleatOnward corridor return $ tToBTree "corDoor" $ treePost [door,cor]