Add destroyable lighting

This commit is contained in:
jgk
2021-03-27 11:59:34 +01:00
parent 151fa5b6bd
commit 2897c65e9e
7 changed files with 135 additions and 143 deletions
+6 -105
View File
@@ -1,4 +1,8 @@
module Dodge.Creature where
module Dodge.Creature
( module Dodge.Creature
, module Dodge.Creature.Inanimate
)
where
-- imports {{{
import Dodge.Data
import Dodge.AIs
@@ -9,6 +13,7 @@ import Dodge.Item.Weapon
import Dodge.Item.Consumable
import Dodge.WorldEvent.Cloud
import Dodge.Creature.YourControl
import Dodge.Creature.Inanimate
import Picture
import Geometry
@@ -31,42 +36,9 @@ import qualified Data.IntMap.Strict as IM
import qualified Data.Map as M
import Foreign.ForeignPtr
import Control.Concurrent
---}
--colouredEnemy col = pictures [color (greyN 0.8) $ circleSolid 10, color col $ circLine 10]
colouredEnemy col = pictures [color col $ circleSolid 10, circLine 10]
-- armouredSwarmCrit :: Int -> Creature
-- armouredSwarmCrit n = (defaultCreature n)
-- -- { _crUpdate = encircleAI' n
-- { _crUpdate = swarmAI lineOrth n
-- , _crHP = 30
-- , _crPict = equipOnTop goalPict
-- , _crState = defaultState {_goals = [[]], _faction = EncircleFlock}
-- , _crInv = IM.fromList [(0,frontArmour)]
-- }
--
-- swarmCrit :: Int -> Creature
-- swarmCrit n = (defaultCreature n)
-- -- { _crUpdate = encircleAI' n
-- { _crUpdate = swarmAI lineOrth n
-- , _crHP = 30
-- , _crPict = equipOnTop goalPict
-- , _crState = defaultState {_goals = [[]], _faction = EncircleFlock}
-- , _crInv = IM.empty -- IM.fromList [(0,frontArmour)]
-- }
--
-- encircleCrit :: Int -> Creature
-- encircleCrit n = (defaultCreature n)
-- -- { _crUpdate = encircleAI' n
-- { _crUpdate = swarmAI lineOrth n
-- , _crHP = 30
-- , _crPict = equipOnTop goalPict
-- , _crState = defaultState {_goals = [[]], _faction = EncircleFlock}
-- , _crInv = IM.empty -- IM.fromList [(0,frontArmour)]
-- }
--
spawnerCrit :: Creature
spawnerCrit = defaultCreature
{ _crUpdate = stateUpdate $ spawnerAI chaseCrit
@@ -76,22 +48,11 @@ spawnerCrit = defaultCreature
}
, _crInv = IM.empty -- IM.fromList [(0,frontArmour)]
}
--
-- guardMelee :: Int -> Creature
-- guardMelee n = (defaultCreature n)
-- { _crUpdate = meleeAI' n
-- , _crHP = 30
-- , _crPict = equipOnTop goalPict
-- , _crState = defaultState {_goals = [[InitGuard]]
-- ,_faction = ChaseCritters}
-- , _crInv = IM.empty -- IM.fromList [(0,frontArmour)]
-- }
smallChaseCrit :: Creature
smallChaseCrit = defaultCreature
{ _crUpdate = stateUpdate chaseAI
, _crHP = 1
, _crRad = 4
--, _crPict = equipOnTop goalPict
, _crPict = enemyPict green
, _crState = defaultState {_goals = [[Wait]]
,_faction = ChaseCritters}
@@ -102,12 +63,10 @@ chaseCrit :: Creature
chaseCrit = defaultCreature
{ _crUpdate = stateUpdate chaseAI
, _crHP = 300
-- , _crPict = goalPict -- enemyPict green
, _crPict = enemyPict green
, _crState = defaultState {_goals = [[Wait]]
,_faction = ChaseCritters}
, _crInv = IM.empty
-- IM.fromList [(0,frontArmour)]
}
armourChaseCrit :: Creature
armourChaseCrit = defaultCreature
@@ -120,78 +79,60 @@ armourChaseCrit = defaultCreature
miniGunCrit :: Creature
miniGunCrit = defaultCreature
{ _crPict = enemyPict red
--, _crUpdate = checkDeadStopSound n . shooterFootsteps n . makeStateAI autoShooterAI n
, _crUpdate = stateUpdate miniAI
--, _crUpdate = shooterFootsteps n . makeStateAI autoShooterAI n
, _crInv = IM.fromList [(0,miniGun)]
, _crInvSel = 0
, _crRad = 10
--, _crState = ShooterWait
, _crState = defaultState {_goals = [[InitGuard]]}
, _crHP = 500
}
longCrit :: Creature
longCrit = defaultCreature
{ _crPict = enemyPict red
--, _crUpdate = checkDeadStopSound n . shooterFootsteps n . makeStateAI autoShooterAI n
, _crUpdate = stateUpdate sniperAI
--, _crUpdate = shooterFootsteps n . makeStateAI autoShooterAI n
, _crInv = IM.fromList [(0,longGun),(1,medkit 100)]
, _crInvSel = 0
, _crRad = 10
--, _crState = ShooterWait
, _crState = defaultState {_goals = [[InitGuard]]}
, _crHP = 300
}
multGunCrit :: Creature
multGunCrit = defaultCreature
{ _crPict = enemyPict red
--, _crUpdate = checkDeadStopSound n . shooterFootsteps n . makeStateAI autoShooterAI n
, _crUpdate = stateUpdate (twitchMissAI 300 350)
--, _crUpdate = shooterFootsteps n . makeStateAI autoShooterAI n
, _crInv = IM.fromList [(0,multGun),(1,medkit 100)]
, _crInvSel = 0
, _crRad = 10
--, _crState = ShooterWait
, _crState = defaultState {_goals = [[InitGuard]]}
, _crHP = 300
}
launcherCrit :: Creature
launcherCrit = defaultCreature
{ _crPict = enemyPict red
--, _crUpdate = checkDeadStopSound n . shooterFootsteps n . makeStateAI autoShooterAI n
, _crUpdate = stateUpdate (launcherAI 150 200)
--, _crUpdate = shooterFootsteps n . makeStateAI autoShooterAI n
, _crInv = IM.fromList [(0,launcher),(1,medkit 100)]
, _crInvSel = 0
, _crRad = 10
--, _crState = ShooterWait
, _crState = defaultState {_goals = [[Init]]}
, _crHP = 300
}
spreadGunCrit :: Creature
spreadGunCrit = defaultCreature
{ _crPict = enemyPict red
--, _crUpdate = checkDeadStopSound n . shooterFootsteps n . makeStateAI autoShooterAI n
, _crUpdate = stateUpdate chargeAI
--, _crUpdate = shooterFootsteps n . makeStateAI autoShooterAI n
, _crInv = IM.fromList [(0,spreadGun),(1,medkit 100)]
, _crInvSel = 0
, _crRad = 10
--, _crState = ShooterWait
, _crState = defaultState {_goals = [[Init]]}
, _crHP = 300
}
pistolCrit :: Creature
pistolCrit = defaultCreature
{ _crPict = enemyPict red
--, _crUpdate = checkDeadStopSound n . shooterFootsteps n . makeStateAI autoShooterAI n
, _crUpdate = stateUpdate (dodgeAI 150 200)
--, _crUpdate = shooterFootsteps n . makeStateAI autoShooterAI n
, _crInv = IM.fromList [(0,pistol),(1,medkit 100)]
, _crInvSel = 0
, _crRad = 10
--, _crState = ShooterWait
, _crState = defaultState {_goals = [[InitGuard]]}
, _crHP = 500
}
@@ -212,46 +153,6 @@ addArmour :: Creature -> Creature
addArmour = over crInv insarmour
where insarmour xs = IM.insert i frontArmour xs
where i = newKey xs
--closeShooterCrit :: Int -> Creature
--closeShooterCrit n = (defaultCreature n)
-- { _crPos = startPos
-- , _crPict = equipOnTop goalPict
-- , _crUpdate = closeShooterAI n
-- , _crInv = IM.fromList [(0,ltAutoGun)]
-- , _crInvSel = 0
-- , _crRad = 10
-- , _crState = defaultState {_goals = [[InitGuard]]}
-- , _crHP = 50
-- }
-- where startPos = (20*fromIntegral n-550,0)
barrel :: Creature
barrel = defaultCreature
{ _crUpdate = updateBarrel
, _crHP = 500
, _crPict = \ _ -> onLayer CrLayer $ pictures [ color orange $ circleSolid 10
, color (greyN 0.5) $ circleSolid 8
]
, _crState = defaultState {_goals = [[Wait]]
,_faction = ChaseCritters
,_crSpState = Barrel []
}
, _crInv = IM.empty -- IM.fromList [(0,frontArmour)]
}
explosiveBarrel :: Creature
explosiveBarrel = defaultCreature
{ _crUpdate = updateExpBarrel
, _crHP = 400
, _crPict = \ _ -> onLayer CrLayer $ pictures [ color orange $ circleSolid 10
, color red $ circleSolid 8
]
, _crState = defaultState {_goals = [[Wait]]
,_faction = ChaseCritters
,_crSpState = Barrel []
,_crApplyDamage = \_ c -> (id, c)
}
, _crInv = IM.empty -- IM.fromList [(0,frontArmour)]
}
equipOnTop :: (Creature -> Picture) -> Creature -> Picture
--equipOnTop f cr = onLayer CrLayer $ pictures $ fst (drawEquipment cr) ++ [f cr] ++ snd (drawEquipment cr)
+69
View File
@@ -0,0 +1,69 @@
module Dodge.Creature.Inanimate
where
import Dodge.Data
import Dodge.Base
import Dodge.Default
import Dodge.CreatureState
import Dodge.LightSources
import Dodge.Creature.Update hiding (CRUpdate)
import Picture
import qualified Data.IntMap.Strict as IM
import Control.Lens
lamp :: Creature
lamp = defaultCreature
{ _crUpdate = initialiseLamp
, _crHP = 500
, _crPict = \ _ -> onLayer CrLayer $ color white $ circleSolid 10
}
initialiseLamp :: CRUpdate
initialiseLamp w (f,g) cr = ( (addLS . f , g), Just $ cr & crUpdate .~ updateLamp i)
where
i = newKey $ _lightSources $ f w -- to give different lights different keys
addLS = over lightSources (IM.insert i (lightAt (_crPos cr) i))
updateLamp :: Int -> CRUpdate
updateLamp i = unrandUpdate handleLS internalUpdate
where
handleLS cr w
| _crHP cr < 0 = w & lightSources %~ IM.delete i
| otherwise = w & lightSources . ix i . lsPos .~ _crPos cr
internalUpdate cr
| _crHP cr < 0 = Nothing
| otherwise = Just $ doDamage cr
barrel :: Creature
barrel = defaultCreature
{ _crUpdate = updateBarrel
, _crHP = 500
, _crPict = \ _ -> onLayer CrLayer $ pictures
[ color orange $ circleSolid 10
, color (greyN 0.5) $ circleSolid 8
]
, _crState = defaultState
{_goals = [[Wait]]
,_faction = ChaseCritters
,_crSpState = Barrel []
}
, _crInv = IM.empty -- IM.fromList [(0,frontArmour)]
}
explosiveBarrel :: Creature
explosiveBarrel = defaultCreature
{ _crUpdate = updateExpBarrel
, _crHP = 400
, _crPict = \ _ -> onLayer CrLayer $ pictures [ color orange $ circleSolid 10
, color red $ circleSolid 8
]
, _crState = defaultState {_goals = [[Wait]]
,_faction = ChaseCritters
,_crSpState = Barrel []
,_crApplyDamage = \_ c -> (id, c)
}
, _crInv = IM.empty -- IM.fromList [(0,frontArmour)]
}
+12
View File
@@ -0,0 +1,12 @@
module Dodge.Creature.Update
where
import Dodge.Data
import System.Random
-- combinators for helping with dealing with creature update
type CRUpdate = World -> (World -> World,StdGen) -> Creature -> ((World -> World,StdGen), Maybe Creature)
unrandUpdate :: (Creature -> World -> World) -> (Creature -> Maybe Creature)
-> CRUpdate
unrandUpdate h cF w (f,g) cr = ( ( h cr . f , g) , cF cr )
+10 -4
View File
@@ -77,11 +77,8 @@ doDamage cr = set (crState . crDamage) [] $ over (crState . crPastDamage) (+ hpL
where dams = _crDamage $ _crState cr
startHP = _crHP cr
damagedCr = snd $ (_crApplyDamage (_crState cr)) dams cr
-- applyDamage (cr ^. crState . crDamage) cr
afterHP = _crHP damagedCr
hpLost = startHP - afterHP -- note this can be negative
-- applyDamage :: DamageType -> Creature -> Creature
-- applyDamage dt cr = snd $ (cr ^. crState . crApplyDamage) dt cr
sumDamage :: Creature -> DamageType -> Int -> Int
sumDamage cr dm x = x + _dmAmount dm
@@ -184,11 +181,20 @@ decreaseToZero :: Int -> Int
decreaseToZero x | x > 0 = x - 1
| otherwise = 0
--comb :: (StdGen -> Creature -> World -> World) -> (StdGen -> Creature -> Maybe Creature)
-- -> CRUpdate
--comb
onDeath :: (Creature -> World -> World) -> CRUpdate -> CRUpdate
onDeath h u w (f,g) cr
| _crHP cr > 0 = u w (f,g) cr
| otherwise = ( ( h cr . f, g ) , Nothing )
updateBarrel ::
World -> (World -> World,StdGen) -> Creature -> ((World -> World , StdGen), Maybe Creature)
updateBarrel w (f,g) cr | _crHP cr > 0 = ((f, g), newCr)
| otherwise = ((f, g), Nothing)
-- | otherwise = ((makeExplosionAt (_crPos cr) . stopSounds , g'), Nothing)
where damages = _crDamage $ _crState cr
newCr = Just $ doDamage cr
+2 -3
View File
@@ -39,6 +39,7 @@ import qualified Data.Set as S
import qualified Data.Map as M
-- deals with placement of objects within the world
-- after they have had their coordinates set by the layout
placeSpots :: [PlacementSpot] -> World -> World
placeSpots pss w = foldr placeSpot w basicPlacements
@@ -75,9 +76,6 @@ placeSpot ps w = case ps of
PS {_psPos = p, _psRot = rot, _psType = PutBlock (hp:hps) col ps}
-> putBlock (map (shiftPointBy (p,rot)) ps) hp col False hps w
-- PS {_psPos = p, _psRot = rot, _psType = PutBlockWall (hp:hps) col ps}
-- -> putBlockWallPart (map (shiftPointBy (p,rot)) ps) hp col False hps w
PS {_psPos = p, _psRot = rot, _psType = PutBtDoor c bp f a b}
-> addButtonDoor c (shiftPointBy (p,rot) bp) (f + rot)
(shiftPointBy (p,rot) a) (shiftPointBy (p,rot) b) w
@@ -95,6 +93,7 @@ placeSpot ps w = case ps of
_ -> w
-- TODO: remove this typeclass
class Shiftable a where
translateS :: Point2 -> a -> a
rotateS :: Float -> a -> a
+3
View File
@@ -2,11 +2,14 @@ module Dodge.Room.Placement
where
import Dodge.Data
import Picture
import Dodge.Creature.Inanimate
import Geometry
-- module defining helper placements for rooms
putLamp = PutCrit lamp
singleBlock :: Point2 -> [PlacementSpot]
singleBlock a = [PS a 0 $ PutBlock [5,20,20] (greyN 0.5)
$ reverse $ rectNSWE 10 (-10) (-10) 10]
+33 -31
View File
@@ -3,6 +3,7 @@ module Dodge.Rooms where
import Dodge.Data
import Dodge.Item.Weapon
import Dodge.Creature
import Dodge.Creature.Inanimate
import Dodge.LevelGen
import Dodge.Base
import Dodge.RandomHelp
@@ -180,7 +181,7 @@ roomRect' x y a b = Room
{ _rmPolys = [rectNSWE y 0 0 x ]
, _rmLinks = lnks
, _rmPath = concatMap doublePair pth
, _rmPS = [PS (x/2,y/2) 0 $ basicLS]
, _rmPS = [PS (x/2,y/2) 0 $ putLamp]
, _rmBound = rectNSWE (y+5) (-5) (-5) (x+5)
}
where yn,xn :: Int
@@ -255,6 +256,7 @@ glassSwitchBack = do
,blockLine (wth-wllen, 2*hf) ( wth,2*hf)
,blockLine ( 0, 3*hf) (wllen,3*hf)
,blockLine (wth-wllen, 4*hf) ( wth,4*hf)
, PS (wth/2,hgt/2) 0 $ PutCrit lamp
]
return $ set rmPS plmnts $ roomRect' wth hgt 2 6
@@ -273,11 +275,11 @@ glassLesson = do
botplmnts = [PS (0,0) 0 $ PutWindow (rectNSWE (200) 0 (90) (110))
$ withAlpha 0.5 aquamarine
,PS (50,100) 0 $ PutCrit miniGunCrit
,PS (50,50) 0 basicLS
,PS (50,50) 0 putLamp
]
topplmnts = [windowLine (100,200) (100,0)
,PS (50,100) 0 $ PutCrit miniGunCrit
,PS (50,50) 0 basicLS
,PS (50,50) 0 putLamp
]
miniRoom1 :: RandomGen g => State g Room
@@ -297,7 +299,7 @@ miniRoom1 = do
,windowLine (wth-wllen,40+4*hf) (60,40+4*hf)
,PS (crx,cry) 0 $ PutCrit miniGunCrit
,PS (wth-20,hgt/2+40) 0 $ randC
,PS (wth/2,hgt/2) 0 basicLS
,PS (wth/2,hgt/2) 0 putLamp
,blockLine ( 0, 40+1*hf) (wllen,40+1*hf)
,blockLine (wth-wllen, 40+2*hf) ( wth,40+2*hf)
,blockLine ( 0, 40+3*hf) (wllen,40+3*hf)
@@ -337,7 +339,7 @@ miniRoom3 = do
,PS cp (pi/8+5*pi/4) b
,PS cp (pi/8+6*pi/4) b
,PS cp (pi/8+7*pi/4) b
,PS (w/2,h/2) 0 basicLS
,PS (w/2,h/2) 0 putLamp
]
randomiseLinks $ set rmPS plmnts $ roomRect w h
@@ -365,8 +367,8 @@ roomCenterPillar = changeLinkTo ((\p -> dist p (120,0) < 10) . fst)
$ set rmPS plmnts $ roomRect' 240 240 2 2
where plmnts = [ blockLine (110,110) (110,130)
, blockLine (130,110) (130,130)
, PS (40,120) 0 basicLS
, PS (200,120) 0 basicLS
, PS (40,120) 0 putLamp
, PS (200,120) 0 putLamp
]
roomOctogon :: Room
@@ -424,7 +426,7 @@ weaponEmptyRoom = do
let plmnts = [PS (w/2,h-40) 0 $ RandPS randFirstWeapon
,PS (20,20) (pi/2) $ randC1
,PS (w-20,20) (pi/2) $ randC1
,PS (w/2,h/2) 0 $ basicLS
,PS (w/2,h/2) 0 $ putLamp
]
randomiseLinks =<< (changeLinkTo ((\p -> dist p (w/2,0) < 10) . fst)
$ set rmPS plmnts $ roomRect' w h 2 2)
@@ -497,9 +499,9 @@ weaponLongCorridor = do
,PS (-10,40) (-pi/2) $ randC
]
putWp = set rmPS [PS (20,40) 0 $ RandPS randFirstWeapon
,PS (20,60) 0 $ basicLS
,PS (20,60) 0 $ putLamp
]
addLS = id -- set rmPS [PS (0,60) 0 $ basicLS]
addLS = id -- set rmPS [PS (0,60) 0 $ putLamp]
critInDeadEnd :: Room
critInDeadEnd = set rmPS [PS (0,0) 0 $ randC] deadEndRoom
@@ -510,7 +512,7 @@ deadEndRoom = Room
]
, _rmLinks = lnks
, _rmPath = []
, _rmPS = [PS (0,-10) 0 basicLS]
, _rmPS = [PS (0,-10) 0 putLamp]
, _rmBound = rectNSWE 20 (-20) (-30) 30
}
where lnks = [((0,30) ,0)
@@ -561,7 +563,7 @@ slowDoorRoom = do
xs' <- sequence $ replicate 5 $ state $ randomR (10,x-10)
ys' <- sequence $ replicate 5 $ state $ randomR (h+20,y)
let crits = zipWith (\p r -> PS p r randC1) ps rs
lsources = [PS (x/2,30) 0 basicLS, PS (x/2,y-30) 0 basicLS]
lsources = [PS (x/2,30) 0 putLamp, PS (x/2,y-30) 0 putLamp]
let barrels = zipWith (\x y -> PS (x,y) 0 $ PutCrit explosiveBarrel) xs' ys'
let pillarsa = []
let pillarsb = putBlockRect (x/5-20) (x/5+20) (h/2-20) (h/2+20)
@@ -605,8 +607,8 @@ longRoom = do
[PS ( 12.5,h-25) 0 $ PutCrit longCrit
,PS ( 37.5,h-25) 0 $ PutCrit longCrit
,PS ( 62.5,h-25) 0 $ PutCrit longCrit
,PS ( 25, 20) 0 $ basicLS
,PS ( 25, h-10) 0 $ basicLS
,PS ( 25, 20) 0 $ putLamp
,PS ( 25, h-10) 0 $ putLamp
]
)
$ rm
@@ -622,7 +624,7 @@ shooterRoom = do
,PS ( 75,h-60) 0 $ PutCrit explosiveBarrel
,PS ( 85,h-10) 0 $ PutCrit explosiveBarrel
,PS ( 85,h-45) 0 $ PutCrit explosiveBarrel
,PS ( 75,h-80) 0 basicLS
,PS ( 75,h-80) 0 putLamp
]
)
$ roomRect' 100 h 1 1
@@ -644,7 +646,7 @@ shootersRoom1 = do
let blv x y = putBlockV (x+25) (x-25) (y+10) (y)
let plmnts = bln x1 y1 ++ bln x2 y2 ++ bln x3 y3 ++ blv x4 y4
++ [PS p (-pi/2) $ PutCrit autoCrit
,PS (w/2,200) 0 basicLS
,PS (w/2,200) 0 putLamp
]
return $ set rmPS plmnts $ roomRect w 600
@@ -665,7 +667,7 @@ shootersRoom = do
++ [PS (x1,y1-10) (-pi/2) $ PutCrit autoCrit
,PS (x2,y2-10) (-pi/2) $ PutCrit autoCrit
,PS (x3,y3-10) (-pi/2) $ PutCrit autoCrit
,PS (w/2,200) 0 basicLS
,PS (w/2,200) 0 putLamp
]
return $ set rmPS plmnts $ roomRect w 600
@@ -694,19 +696,19 @@ pistolerRoom = do
let plmnts = [PS (ps !! 0) aa $ PutCrit pistolCrit
,PS (ps !! 1) ab $ PutCrit pistolCrit
,PS (ps !! 2) ac $ PutCrit pistolCrit
-- ,PS (w-5,h/2) 0 $ basicLS
-- ,PS (5,h/2) 0 $ basicLS
-- ,PS (w/2,h-5) 0 $ basicLS
-- ,PS (w/2,5) 0 $ basicLS
-- ,PS (w-50,h/2) 0 $ basicLS
-- ,PS (50,h/2) 0 $ basicLS
,PS (w/2,h-50) 0 $ basicLS
,PS (w/2,50) 0 $ basicLS
,PS (w-5,h-5) 0 $ basicLS
,PS (5,h-5) 0 $ basicLS
,PS (w-5,5) 0 $ basicLS
,PS (5,5) 0 $ basicLS
,PS (w/2,h/2) 0 $ basicLS
-- ,PS (w-5,h/2) 0 $ putLamp
-- ,PS (5,h/2) 0 $ putLamp
-- ,PS (w/2,h-5) 0 $ putLamp
-- ,PS (w/2,5) 0 $ putLamp
-- ,PS (w-50,h/2) 0 $ putLamp
-- ,PS (50,h/2) 0 $ putLamp
,PS (w/2,h-50) 0 $ putLamp
,PS (w/2,50) 0 $ putLamp
,PS (w-5,h-5) 0 $ putLamp
,PS (5,h-5) 0 $ putLamp
,PS (w-5,5) 0 $ putLamp
,PS (5,5) 0 $ putLamp
,PS (w/2,h/2) 0 $ putLamp
]
++
-- f (w*0.25) (h*0.5)
@@ -739,7 +741,7 @@ spawnerRoom = do
]
let plmnts = [PS (x/4, y/4) (pi/2) $ PutCrit spawnerCrit
,wl
,PS (x/2, y-10) 0 basicLS
,PS (x/2, y-10) 0 putLamp
]
let f ((lx,_),_) = lx < x/2-5
roomWithSpawner <- randomiseLinks =<< (filterLinks f $ set rmPS plmnts $ roomRect' x y 2 2)