module Actions ( do_big_map, do_close_door, do_move, do_quit ) where import Control.Monad.State import qualified Data.Map as M (lookup) import Util.Grid import Landscape import Monsters import Language import World import Messages import Curses -- Get a direction argument from the player and supply it to an action. -- Don't run the action at all if the player gives an invalid direction. with_dir :: Message -> (Direction -> Action) -> Action with_dir msg diract = do message msg -- Wait for a keystroke. key <- lift get_key clear_messages -- Look up which direction the player wants, then act on it. dirmap <- gets dir_keymap case (flip M.lookup) dirmap key of Nothing -> message msg_strange_direction Just dir -> diract dir do_big_map :: Action do_big_map = do pos <- gets you_pos modify $ set_user_mode (Mode_bigmap pos) -- Main loop takes care of the rest do_close_door :: Action do_close_door = with_dir msg_where_close_door do_close_door_dir do_close_door_dir :: Direction -> Action do_close_door_dir dir = do pos <- gets you_pos land <- gets landscape let doorpos = pos `addpos` dir case get_feature_type land doorpos of OpenDoor -> modify $ with_landscape $ close_door doorpos ClosedDoor -> message msg_door_already_closed LockedDoor -> message msg_door_already_closed BrokenDoor -> message msg_door_is_broken Doorway -> message msg_empty_doorway Floor -> message msg_no_door_there Wall -> message msg_no_door_there do_move :: Direction -> Action do_move dir = do pos <- gets you_pos mons <- gets monsters let newpos = pos `addpos` dir case (flip M.lookup) mons newpos of Just monster -> do message $ BasicSentence you (verb V_kill) (monster_desc monster) kill_monster newpos Nothing -> do land <- gets landscape let okay = modify $ move_you newpos case get_feature_type land newpos of Floor -> okay Wall -> return () ClosedDoor -> do message msg_opening_door modify $ with_landscape $ open_door newpos LockedDoor -> message msg_door_locked OpenDoor -> okay BrokenDoor -> okay Doorway -> okay do_quit :: Action do_quit = do modify $ \world -> world { game_over = True }