-- This module keeps track of the complete game state. module World ( World(..), Action, Keymap, UserMode(..), new_world, with_landscape, -- Note: message and clear_messages are Actions, to make them more -- convenient to use from other Actions, but they do not transform -- the world so they are safe to run with evalStateT. message, clear_messages, set_language, set_user_mode, move_you, kill_monster ) where import Control.Monad.State import qualified Data.Map as M (Map, delete) import System.Random import Util.Grid import Language import LanguageSelect import Keys import Landscape import Monsters import Body import Glyph import Window import MessageWindow import Curses import LevelGen -- These types are defined here in order to avoid a mutual module -- dependency between World and Keymap. type Keymap = M.Map Key Action type DirKeymap = M.Map Key Direction type Action = StateT World IO () data UserMode = Mode_game | Mode_bigmap Position -- position is center of view data World = World { -- Metadata levelseed :: StdGen, game_over :: Bool, user_mode :: UserMode, -- User interface keymap :: Keymap, dir_keymap :: DirKeymap, msgwin :: MessageWindow CursesWindow, mapwin :: CursesWindow, bigwin :: CursesWindow, -- Options language :: Language, -- Current level landscape :: Landscape, monsters :: Monsters, -- Where our player hangs out you_pos :: Position } new_world :: StdGen -> Keymap -> DirKeymap -> MessageWindow CursesWindow -> CursesWindow -> CursesWindow -> World new_world seed kmap dirkmap msgw mapw bigw = World { levelseed = seed, game_over = False, user_mode = Mode_game, keymap = kmap, dir_keymap = dirkmap, msgwin = msgw, mapwin = mapw, bigwin = bigw, language = English, landscape = cave, monsters = add_monster you_mons start_pos mons, you_pos = start_pos } where start_pos = (5, 4) you_mons = Monster { monster_desc = you, monster_body = human_body, monster_glyph = you_glyph } (cave, mons) = gen_cave seed set_language :: Language -> World -> World set_language l world = world { language = l } set_user_mode :: UserMode -> World -> World set_user_mode mode world = world { user_mode = mode } with_landscape :: (Landscape -> Landscape) -> World -> World with_landscape f world = world { landscape = f (landscape world) } -- Raw player move, no checks. move_you :: Position -> World -> World move_you newpos world = world { monsters = move_monster (monsters world) (you_pos world) newpos, you_pos = newpos } message :: Sentence -> Action message s = do msgw <- gets msgwin mapw <- gets mapwin lang <- gets language let msg = transSentence lang s let place_cursor = refresh_window mapw lift $ write_msg msgw place_cursor msg clear_messages :: Action clear_messages = do msgw <- gets msgwin mapw <- gets mapwin let place_cursor = refresh_window mapw lift $ clear_msgwin msgw place_cursor kill_monster :: Position -> Action kill_monster pos = do world <- get put world { monsters = (flip M.delete) (monsters world) pos }