on master help sign in
make the start of a silly rouge like game
0620fdcCorey O'Connor
test/Rouge.hsnew file+108
@@ -0,0 +1,108 @@
1+module Main where
2+
3+import Graphics.Vty
4+
5+import Data.Array
6+import qualified Data.ByteString as B
7+import Data.Word
8+
9+import Control.Applicative
10+import Control.Monad
11+import Control.Monad.RWS
12+import Control.Monad.Writer
13+
14+import System.IO
15+import System.Random
16+
17+data Dude = Dude Int Int
18+ deriving (Show,Eq)
19+
20+data World = World
21+ { dude :: Dude
22+ , level :: Level
23+ }
24+ deriving (Show,Eq)
25+
26+data Level = Level
27+ { start :: (Int, Int)
28+ , end :: (Int, Int)
29+ , geo :: Array (Int, Int) LevelPiece
30+ }
31+ deriving (Show,Eq)
32+
33+data LevelPiece
34+ = EmptySpace
35+ | Rock
36+ deriving (Show, Eq)
37+
38+type Game = RWST Vty () World IO
39+
40+main = do
41+ vty <- mkVty
42+ level_0 <- mkLevel 0
43+ let world_0 = World (Dude (fst $ start level_0) (snd $ start level_0)) level_0
44+ (_final_world, ()) <- execRWST (play >> view_world) vty world_0
45+ shutdown vty
46+
47+mkLevel _difficulty = do
48+ level_width <- randomRIO (10,15)
49+ level_height <- randomRIO (10,15)
50+ start <- (,) <$> randomRIO (2, level_width-3) <*> randomRIO (2, level_height-3)
51+ end <- (,) <$> randomRIO (2, level_width-3) <*> randomRIO (2, level_height-3)
52+ let geo = array ((0,0), (level_width, level_height))
53+ [((x,y),p) | x <- [0..level_width-1], y <- [0..level_height-1],
54+ let p = if (x == 0 || x == level_width-1) || (y==0 || y==level_height-1)
55+ then Rock
56+ else EmptySpace
57+ ]
58+ return $ Level start end geo
59+
60+image_for_geo EmptySpace = char (def_attr `with_back_color` green) ' '
61+image_for_geo Rock = char (def_attr `with_fore_color` white) 'X'
62+
63+pieceA = def_attr `with_fore_color` red
64+dumpA = def_attr `with_style` reverse_video
65+
66+play = do
67+ view_world
68+ done <- process_event
69+ unless done play
70+
71+process_event = do
72+ k <- ask >>= liftIO . next_event
73+ if k == EvKey KEsc []
74+ then return True
75+ else do
76+ case k of
77+ EvKey (KASCII 'r') [MCtrl] -> ask >>= liftIO . refresh
78+ EvKey KLeft [] -> move_dude (-1) 0
79+ EvKey KRight [] -> move_dude 1 0
80+ EvKey KUp [] -> move_dude 0 (-1)
81+ EvKey KDown [] -> move_dude 0 1
82+ _ -> return ()
83+ return False
84+
85+move_dude dx dy = do
86+ vty <- ask
87+ world <- get
88+ let Dude x y = dude world
89+ (w, h) <- gets (snd . bounds . geo . level)
90+ put $ world { dude = Dude (min (w - 2) $ max 1 (x + dx))
91+ (min (h - 2) $ max 1 (y + dy))
92+ }
93+
94+view_world :: Game ()
95+view_world = do
96+ Dude x y <- gets dude
97+ the_level <- gets level
98+ let dude_image = translate x y (char pieceA '@')
99+ let (geo_width, geo_height) = snd $ bounds (geo the_level)
100+ geo_image = vert_cat [ geo_row | y <- [0..geo_height-1],
101+ let geo_row = horiz_cat [ i | x <- [0..geo_width-1],
102+ let i = image_for_geo (geo the_level ! (x,y))
103+ ]
104+ ]
105+ info = string def_attr "Move with the arrows keys. Press ESC to exit."
106+ let pic = pic_for_layers [info, translate 0 1 dude_image,translate 0 1 geo_image]
107+ vty <- ask
108+ liftIO $ update vty pic
test/Test.hsdeleted−43
@@ -1,43 +0,0 @@
1−module Main where
2−
3−import Graphics.Vty
4−
5−import qualified Data.ByteString as B
6−import Data.Word
7−
8−import System.IO
9−
10−
11−main = do
12− vt <- mkVty
13− DisplayRegion w h <- display_bounds $ terminal vt
14− putStrLn $ show $ DisplayRegion w h
15− play vt 0 1 w h ""
16−
17−pieceA = def_attr `with_fore_color` red
18−dumpA = def_attr `with_style` reverse_video
19−
20−play :: Vty -> Int -> Int -> Int -> Int -> String -> IO ()
21−play vt x y sx sy btl = do update vt (current_pic x y sx sy btl)
22− k <- next_event vt
23− case k of EvKey (KASCII 'r') [MCtrl] -> refresh vt >> play vt x y sx sy btl
24− EvKey KLeft [] | x /= 0 -> play vt (x-1) y sx sy btl
25− EvKey KRight [] | x /= (sx-1) -> play vt (x+1) y sx sy btl
26− EvKey KUp [] | y /= 1 -> play vt x (y-1) sx sy btl
27− EvKey KDown [] | y /= (sy-2) -> play vt x (y+1) sx sy btl
28− EvKey KEsc [] -> shutdown vt >> return ()
29− EvResize nx ny -> play vt (min x (nx - 1))
30− (min y (ny - 2))
31− nx
32− ny
33− btl
34− _ -> play vt x y sx sy (take sx (show k ++ btl))
35−
36−
37−current_pic :: Int -> Int -> Int -> Int -> String -> Picture
38−current_pic x y sx sy btl = pic_for_image i
39− where i = string def_attr "Move the @ character around with the arrow keys. Escape exits."
40− <-> char_fill pieceA ' ' sx (y - 1)
41− <-> char_fill pieceA ' ' x 1 <|> char pieceA '@' <|> char_fill pieceA ' ' (sx - x - 1) 1
42− <-> char_fill pieceA ' ' sx (sy - y - 2)
43− <-> iso_10646_string dumpA btl
test/VerifyUsingMockInput.hs+22−17
@@ -33,6 +33,9 @@ import Test.SmallCheck.Series
33max_block_size :: Int
33max_block_size :: Int
34max_block_size = 16
34max_block_size = 16
35
35
36+forEachOf :: (Show a, Testable m b) => [a] -> (a -> b) -> Property m
37+forEachOf l = over (generate (\n -> take n l))
38+
36data InputEvent
39data InputEvent
37 = Bytes String -- | input sequence encoded as a string. Regardless, the input is read a byte at a time.
40 = Bytes String -- | input sequence encoded as a string. Regardless, the input is read a byte at a time.
38 | Delay Int -- | millisecond delay
41 | Delay Int -- | millisecond delay
@@ -78,34 +81,36 @@ write_input_spec_to_chan chan (Delay _t : input_spec') = do
78 writeChan chan '\xFFFE'
81 writeChan chan '\xFFFE'
79 write_input_spec_to_chan chan input_spec'
82 write_input_spec_to_chan chan input_spec'
80
83
84+newtype InputBlocksUsingTable event
81−newtype EventBlock event = EventBlock ([(String,event)] -> [(String, event)])
85+ = InputBlocksUsingTable ([(String,event)] -> [(String, event)])
82
86
83−instance Show (EventBlock event) where
87+instance Show (InputBlocksUsingTable event) where
84− show (EventBlock g) = "EventBlock(*->*)"
88+ show (InputBlocksUsingTable _g) = "InputBlocksUsingTable"
85
89
86−instance Monad m => Serial m (EventBlock event) where
90+instance Monad m => Serial m (InputBlocksUsingTable event) where
87 series = do
91 series = do
88 n :: Int <- localDepth (max max_block_size) series -- what elements to select from the table
92 n :: Int <- localDepth (max max_block_size) series -- what elements to select from the table
89− return $ EventBlock $ \table -> concat (take n (permutations table))
93+ return $ InputBlocksUsingTable $ \table -> concat (take n (permutations table))
90
94
91verify_simple_input_block_to_event :: Property IO
95verify_simple_input_block_to_event :: Property IO
92−verify_simple_input_block_to_event = forAll $ \(EventBlock block_gen) -> do
96+verify_simple_input_block_to_event = forAll $ \(InputBlocksUsingTable gen) -> do
93− let simple_input_seq = block_gen simple_chars
97+ let input_seq = gen simple_chars
94− input = Bytes $ concat [s | (s,_) <- simple_input_seq]
98+ input = Bytes $ concat [s | (s,_) <- input_seq]
95− events = [e | (_,(k,ms)) <- simple_input_seq, let e = EvKey k ms]
99+ events = [e | (_,(k,ms)) <- input_seq, let e = EvKey k ms]
96 monadic $ assert_events_from_input_block simple_chars [input] events
100 monadic $ assert_events_from_input_block simple_chars [input] events
97
101
98verify_keys_from_caps_table_block_to_event :: Property IO
102verify_keys_from_caps_table_block_to_event :: Property IO
99−verify_keys_from_caps_table_block_to_event = forAll $ \(EventBlock block_gen) ->
103+verify_keys_from_caps_table_block_to_event = forAll $ \(InputBlocksUsingTable gen) ->
100− over (generate (\n -> take n terminals_of_interest)) $ \term_name -> monadic $ do
104+ forEachOf terminals_of_interest $ \term_name -> monadic $ do
101− terminal <- setupTerm term_name
105+ term <- setupTerm term_name
102− let table = caps_classify_table terminal keys_from_caps_table
106+ let table = caps_classify_table term keys_from_caps_table
103− input_seq :: [(String, Event)] = block_gen table
107+ input_seq = gen table
108+ events = [e | (_,e) <- input_seq]
104− input_bytes = [Bytes s | (s,_) <- input_seq]
109+ keydowns = [Bytes s | (s,_) <- input_seq]
105− input = intersperse (Delay defaultEscDelay) input_bytes
110+ input = intersperse (Delay defaultEscDelay) keydowns
106− events = [e | (_,e) <- input_seq]
107 assert_events_from_input_block (map_to_legacy_table table) input events
111 assert_events_from_input_block (map_to_legacy_table table) input events
108
112
113+main :: IO ()
109main = defaultMain
114main = defaultMain
110 [ testProperty "basic block generated from a single ansi chars to event translation"
115 [ testProperty "basic block generated from a single ansi chars to event translation"
111 verify_simple_input_block_to_event
116 verify_simple_input_block_to_event
vty.cabal+18
@@ -561,6 +561,24 @@ executable vty-interactive-terminal-test
561 utf8-string >= 0.3 && < 0.4,
561 utf8-string >= 0.3 && < 0.4,
562 vector >= 0.7
562 vector >= 0.7
563
563
564+executable vty-rouge
565+ main-is: Rouge.hs
566+ hs-source-dirs: test
567+
568+ default-language: Haskell2010
569+ default-extensions: ScopedTypeVariables
570+
571+ build-depends: vty,
572+ base >= 4 && < 5,
573+ bytestring,
574+ containers,
575+ lens,
576+ mtl >= 1.1.1.0 && < 2.2,
577+ parallel >= 2.2 && < 3.3,
578+ text >= 0.11.3,
579+ utf8-string >= 0.3 && < 0.4,
580+ vector >= 0.7
581+
564executable vty-benchmark
582executable vty-benchmark
565 main-is: benchmark.hs
583 main-is: benchmark.hs
566
584