-- 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 Data.FiniteMap 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 = FiniteMap Key Action type DirKeymap = FiniteMap 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 = delFromFM (monsters world) pos }