module RPGEngine.Data.Level -- Everything is exported where import GHC.IO (unsafePerformIO) import System.Directory (getDirectoryContents) import RPGEngine.Input.Core (ListSelector(..)) import RPGEngine.Data (Action(..), Level (..), Physical (..), Direction (..), Entity (..), Game (..), Item (..), Player (..), State (..), X, Y, Layout, Condition (InventoryFull, InventoryContains, Not, AlwaysFalse)) import RPGEngine.Config (levelFolder) import Data.Foldable (find) ------------------------------ Exported ------------------------------ -- Find first position of a Physical -- Graceful exit by giving Nothing if there is nothing found. findFirstOf :: Level -> Physical -> Maybe (X, Y) findFirstOf l@Level{ index = index } physical = try where matches = filter (\(x, y, v) -> v == physical) index try | not (null matches) = Just $ (\(x, y, _) -> (x, y)) $ head matches | otherwise = Nothing -- What is located at a given position in the level? findAt :: (X, Y) -> Level -> Physical findAt pos lvl@Level{ index = index } = try where matches = map (\(_, _, v) -> v) $ filter (\(x, y, v) -> (x, y) == pos) index try | not (null matches) = head matches | otherwise = Void hasAt :: (X, Y) -> Level -> Maybe (Either Item Entity) hasAt pos level = match firstItem firstEntity where match :: Maybe Item -> Maybe Entity -> Maybe (Either Item Entity) match (Just a) _ = Just $ Left a match _ (Just a) = Just $ Right a match _ _ = Nothing firstEntity = find ((== pos) . getECoord) $ entities level getECoord e = (entityX e, entityY e) firstItem = find ((== pos) . getICoord) $ items level getICoord i = (itemX i, itemY i) directionOffsets :: Direction -> (X, Y) directionOffsets North = ( 0, 1) directionOffsets East = ( 1, 0) directionOffsets South = ( 0, -1) directionOffsets West = (-1, 0) directionOffsets Stay = ( 0, 0) getLevelList :: [FilePath] getLevelList = drop 2 $ unsafePerformIO $ getDirectoryContents levelFolder -- Get the actions of either an entity or an item getActions :: Either Item Entity -> [([Condition], Action)] getActions (Left item) = itemActions item getActions (Right entity) = entityActions entity getActionText :: Action -> String getActionText Leave = "Leave" getActionText (RetrieveItem _) = "Pick up" getActionText (UseItem _) = "Use item" getActionText _ = "ERROR" -- TODO Check conditions -- Filter based on the conditions, keep only the actions of which the -- conditions are met. filterActions :: [([Condition], Action)] -> [Action] filterActions [] = [] filterActions ((conditions, action):others) = action:filterActions others -- Check if a condition is met or not. meetsCondition :: Condition -> Bool meetsCondition InventoryFull = False -- TODO meetsCondition (InventoryContains id) = True -- TODO meetsCondition (Not condition) = not $ meetsCondition condition meetsCondition AlwaysFalse = False