-- | Common interface between the game and the various user interfaces modules module GameInterface where import Shapes(Shape) -- | Bookkeeping data Book = Book { score,rowCount::Int } updateBook :: Int -> Book -> Book updateBook rows (Book score rowCount) = Book score' (rowCount+rows) where score' = score + 100*rows*rows -- * User interface -- | Interface to the game implementation data Game state = Game { startGame :: [Double] -> state, -- ^ Initial state stepGame :: Action -> state -> Maybe (Int,state), -- ^ @Nothing@ ends the game, @Just@ continues. -- The @Int@ is the number of rows that were cleared drawGame :: state -> Shape, -- ^ Visualize the game state gameInfo :: state -> Book -> [String], -- ^ Extra info to show to the user tickDelay :: state -> Book -> Int, -- ^ Delay between @Tick@ steps gameInvariant :: state -> Bool -- ^ for run-time verification } -- | A type for the actions that advances the game (user input and timer ticks) data Action = Tick | MoveLeft | MoveRight | MoveDown | Rotate deriving (Eq,Read,Show,Bounded,Enum) -- | Extra info that the user interface may display defaultGameInfo invariant t b = [show (score b)++" points", show (rowCount b)++" rows", --if rowCount t>0 then show (score t `div` rowCount t)++" ppr" else "", if invariant t then " " else "TETRIS INVARIANT VIOLATION"] -- | The delay between ticks (in milliseconds) as a function of -- of current game state defaultDelay :: state -> Book -> Int defaultDelay t b = round (500*0.8^(rowCount b `div` 10)) `max` 100