{-# Language ScopedTypeVariables #-} module Screen ( module Screen, module Screen.Primitives, module Screen.ProcessKeys, module Screen.Check ) where import Input import Meeple.Operate import Room import Plant import Screen.Check import Screen.Decide import Screen.Move import Screen.Primitives import Screen.ProcessKeys import Lens.Micro.Platform import Terminal.Game import qualified Data.List as L ----------- -- LOGIC -- ----------- screenLogic :: (Show s, HasScreen s) => Input -> s -> s screenLogic k s -- key processing | isMovKey k = s & player %~ fmap (processMovKeys k s) | isMenuKey k = playerDie s -- logic | otherwise = L.foldl' (flip ($)) s [ -- I decide where to move mappedScreen cogitate, -- II actually move (and collision) moveCollideGeneral, -- III spawn phase (for projectile-launching -- enemies spawnProjectiles, -- IV clean-up (reset + mark deads) cleanUp ] where mappedScreen :: HasScreen s => (s -> Meeple -> Meeple) -> s -> s mappedScreen f sw = sw & meeples . each %~ f sw cleanUp :: HasScreen s => s -> s cleanUp s = s & room . plant %~ tickPlant & meeples . each %~ (resetClimb s . (\m -> m & draw %~ tick) . oobDead . uselessLock . oldMPlayer) where oobDead :: Meeple -> Meeple oobDead m@(MDead _) = m oobDead m = let (tr, tc) = s ^. room . to boundaries (mr, mc) = m ^. position in if mr < -5 || mc < -10 || mr > (tr + 5) || mc > (tc + 5) then MDead None else m uselessLock :: Meeple -> Meeple uselessLock m@(MLock l) | l ^. currNumeral <= 0 && l ^. draw . to isExpired = MDead None | otherwise = m uselessLock m = m oldMPlayer :: Meeple -> Meeple oldMPlayer (MPlayer p) = MPlayer $ oldPlayer p oldMPlayer m = m resetClimb :: HasScreen s => s -> Meeple -> Meeple resetClimb _ m@(MDead _) = m resetClimb s m | amOutOfBounds s m = m | not (canClimb s m) = noClimb m | otherwise = m where noClimb (MPlayer p) = MPlayer $ p & isClimbing .~ False noClimb mw = mw spawnProjectiles :: HasScreen s => s -> s spawnProjectiles s = let s' = s & meeples . each %~ genProj sp :: [Meeple] sp = concat $ s ^.. meeples . each . to fetchProj . _Just in s' & meeples %~ (++ sp) where fetchProj :: Meeple -> Maybe [Meeple] fetchProj (MBird b) = creaRef <$> b ^. ready fetchProj (MKram k) = creaRef <$> k ^. ready fetchProj MDead {} = Nothing fetchProj MDumb {} = Nothing fetchProj MLock {} = Nothing fetchProj MNettle {} = Nothing fetchProj MPlayer {} = Nothing fetchProj MSave {} = Nothing fetchProj MSmart {} = Nothing fetchProj MSickle {} = Nothing fetchProj MStar {} = Nothing fetchProj MStone {} = Nothing fetchProj MWin {} = Nothing fetchProj MWitch {} = Nothing ---------- -- DRAW -- ---------- drawScreen :: HasScreen s => s -> Plane drawScreen s = blankPlane 80 24 & (r, c) % mergePlanes (drawRoom (s ^. room)) pcs where (r, c) = let (aw, ah) = planeSize actionPlane in (div (24-ah) 2 + 1, div (80-aw) 2 + 1) actionPlane = mergePlanes (drawRoom (s ^. room)) pcs meepOrd :: [Meeple] meepOrd = let ms = (s ^.. meeples . each . filtered (not . isDead)) in L.sort ms pcs :: [(Coords, Plane)] pcs = map f meepOrd f :: Meeple -> (Coords, Plane) f m = (m ^. position, m ^. draw . to fetchFrame)