module Main where import Prelude hiding (lookup) import Control.Monad.State import Data.Char import qualified Data.Map as M (lookup) import Data.Ix import Data.List import System.Random import System.Environment import Util.Grid import Color import LanguageSelect import Curses import World import Keymap import Vision import Window start :: IO () start = do init_curses raw_mode finish :: IO () finish = do cooked_mode exit_curses -- These are odd numbers, so that the view extends the same distance -- from the midpoint on all sides. view_hsize :: Int view_hsize = 39 view_vsize :: Int view_vsize = 19 draw_map :: (GlyphWindow w) => w -> Position -> World -> IO () draw_map w center world = do sequence_ (map draw_glyph locs) if inRange (window_bounds w) you_loc then move_cursor w you_loc else return () where (hsize, vsize) = window_size w wcenter = (hsize `div` 2, vsize `div` 2) ulcorner = center `subpos` wcenter land = landscape world mons = monsters world locs = range (window_bounds w) you_loc = (you_pos world) `subpos` ulcorner draw_glyph (h, v) = write_glyph w (h, v) (glyph_at land mons (ulcorner `addpos` (h, v))) draw_game_map :: (GlyphWindow w) => w -> World -> IO () draw_game_map w world = draw_map w (you_pos world) world draw_bigmap :: (GlyphWindow w) => w -> Position -> World -> IO () draw_bigmap w center world = do draw_map w center world main_loop :: World -> IO World main_loop world | game_over world = return world main_loop world = do let mode = user_mode world case mode of Mode_game -> do let mapw = mapwin world draw_game_map mapw world refresh_window mapw key <- get_key evalStateT clear_messages world case (flip M.lookup) (keymap world) key of Nothing -> do flash main_loop world Just action -> do world' <- execStateT action world main_loop world' Mode_bigmap center -> do let bigw = bigwin world draw_bigmap bigw center world refresh_window bigw key <- get_key case (flip M.lookup) (dir_keymap world) key of Nothing -> do -- Make sure the areas not covered by other windows are blanked clear_window bigw refresh_window bigw -- Do this by clearing the screen clear_screen refresh_window (mapwin world) refresh_window (msgwin world) main_loop world { user_mode = Mode_game } Just (dx, dy) -> do main_loop world { user_mode = Mode_bigmap (center `addpos` (10 * dx, 10 * dy)) } get_seed :: IO StdGen get_seed = do args <- getArgs case args of ((a : _) : _) -> return $ mkStdGen $ digitToInt a _ -> getStdGen main :: IO () main = do start msgw <- new_window (0, 0) (79, 0) mapw <- new_window (0, 1) (view_hsize-1, view_vsize) (hsize, vsize) <- screen_size bigw <- new_window (0, 0) (hsize-1, vsize-1) seed <- get_seed write_string mapw Text "Generating world..." refresh_window mapw update_screen let world = set_language English $ new_world seed default_keymap default_dir_keymap msgw mapw bigw main_loop world destroy_window bigw destroy_window mapw destroy_window msgw finish