packages feed

deterministic-game-engine 0.1.0.0 → 0.2.0

raw patch · 6 files changed

+137/−42 lines, 6 filesdep +mtldep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: mtl

Dependency ranges changed: base

API changes (from Hackage documentation)

- GameEngine: gameActions :: GameEngine a b -> GameActions a b
- GameEngine: getMoves :: GameActions a b -> GameState a -> [Move b]
+ GameEngine: actions :: GameEngine a b -> GameActions a b
+ GameEngine: getMove :: GameActions a b -> GameState a -> Move b
+ GameEngine: playIO :: (GameState a -> IO ()) -> GameEngine a b -> IO Int
+ GameEngine: playSimple :: GameEngine a b -> Int
- GameEngine: GameActions :: (GameState a -> Player) -> (GameState a -> [Move b]) -> (GameState a -> Move b -> GameState a) -> (GameState a -> Bool) -> (GameState a -> Player -> Int) -> GameActions a b
+ GameEngine: GameActions :: (GameState a -> Player) -> (GameState a -> Move b) -> (GameState a -> Move b -> GameState a) -> (GameState a -> Bool) -> (GameState a -> Player -> Int) -> GameActions a b
- GameEngine: Player :: Char -> Player
+ GameEngine: Player :: Symbol -> Player
- GameEngine: play :: GameEngine a b -> Int
+ GameEngine: play :: Monad m => (GameState a -> m (GameState a)) -> GameEngine a b -> m Int

Files

Src/GameEngine.hs view
@@ -1,3 +1,37 @@+{- |++Haskell library for creating simple deterministic games,+such as tic-tac-toe. The engine requires a minimal set of+actions related to the game, and then will run the game+until a terminal state is reached.++Simple generic example below. See the specs for a more detailed example.++> import GameEngine+>+> game :: GameEngine Int Int+> game = GameEngine gameActions initialState+>+> gameActions :: GameActions Int Int+> gameActions = GameActions {+>    getPlayer  = -- find the next player from a game state,+>    getMove    = -- find a move from the game state,+>    getResult  = -- transitions from a state to another state,+>    isTerminal = -- determines if the game is terminal,+>    getScore   = -- get score from a terminal state+>  }+>+> initialState :: GameState Int+> initialState = GameState 0+>+> -- run the game engine until a terminal state is reached+> playSimple game++-}++{-# LANGUAGE RankNTypes #-}++ module GameEngine (     Symbol,     GameState(..),@@ -5,46 +39,52 @@     Move(..),     GameActions(..),     GameEngine(..),-    play+    play,+    playSimple,+    playIO   ) where  -type Symbol = Char---data GameState a = GameState a+import Control.Monad.Identity+import GameEngine.GameState+import GameEngine.GameActions+import GameEngine.Move+import GameEngine.Player  -data Player = Player Char-+data GameEngine a b = GameEngine {+    actions :: GameActions a b,+    -- ^ Defines how the game will be played -data Move a = Move a+    state   :: GameState a+    -- ^ The current state of the game+  }+-- ^ Holds information about how the game is played, and the current state of the game.  -data GameActions a b = GameActions {-    getPlayer  :: GameState a -> Player,-    getMoves   :: GameState a -> [Move b],-    getResult  :: GameState a -> Move b -> GameState a,-    isTerminal :: GameState a -> Bool,-    getScore   :: GameState a -> Player -> Int-  }+-- TODO: provided function should be forced to be an identity only function+-- forall a. a -> m a+play :: Monad m => (GameState a -> m (GameState a)) -> GameEngine a b -> m Int+-- ^ Run the provided game engine under a monadic context until a terminal state is reached.+-- Note: provided function should act as an identity only, and should not modify the game state.+play f engine+  | performWithState isTerminal engine = return . performWithState getScore engine $ performWithState getPlayer engine+  | otherwise = f (getNextState engine) >>= play f . GameEngine (actions engine)  -data GameEngine a b = GameEngine {-    gameActions :: GameActions a b,-    state       :: GameState a-  }+playSimple :: GameEngine a b -> Int+-- ^ Run the provided game engine without a context until a terminal state is reached.+playSimple = runIdentity . play Identity  -play :: GameEngine a b -> Int-play engine-  | performWithState isTerminal engine = performWithState getScore engine $ performWithState getPlayer engine-  | otherwise = play $ GameEngine (gameActions engine) (getNextState engine)+playIO :: (GameState a -> IO ()) -> GameEngine a b -> IO Int+-- ^ Run the provided game engine within an IO context until a terminal state is reached.+playIO f = play (f >> return)   getNextState :: GameEngine a b -> GameState a-getNextState engine = performWithState getResult engine . head $ performWithState getMoves engine+getNextState engine = performWithState getResult engine $ performWithState getMove engine   performWithState :: (GameActions a b -> GameState a -> c) -> GameEngine a b -> c-performWithState f engine = f (gameActions engine) $ state engine+performWithState f engine = f (actions engine) $ state engine
+ Src/GameEngine/GameActions.hs view
@@ -0,0 +1,27 @@+module GameEngine.GameActions (+    GameActions(..)+  ) where+++import GameEngine.Player+import GameEngine.Move+import GameEngine.GameState+++data GameActions a b = GameActions {+    getPlayer  :: GameState a -> Player,+    -- ^ Specifies which player has the move in the state++    getMove    :: GameState a -> Move b,+    -- ^ Returns a legal move in the state++    getResult  :: GameState a -> Move b -> GameState a,+    -- ^ The transition model, which determines the result of a move++    isTerminal :: GameState a -> Bool,+    -- ^ True if game is over, False otherwise++    getScore   :: GameState a -> Player -> Int+    -- ^ A utility function to determine the numeric value for a game that ends in a terminal state+  }+-- ^ Set of actions that defines how the game will be played
+ Src/GameEngine/GameState.hs view
@@ -0,0 +1,6 @@+module GameEngine.GameState (+    GameState(..)+  ) where+++data GameState a = GameState a deriving (Eq, Show)
+ Src/GameEngine/Move.hs view
@@ -0,0 +1,6 @@+module GameEngine.Move (+    Move(..)+  ) where+++data Move a = Move a deriving (Eq, Show)
+ Src/GameEngine/Player.hs view
@@ -0,0 +1,10 @@+module GameEngine.Player (+    Symbol,+    Player(..)+  ) where+++type Symbol = Char+++data Player = Player Symbol deriving (Eq, Show)
deterministic-game-engine.cabal view
@@ -1,22 +1,21 @@--- Initial deterministic-game-engine.cabal generated by cabal init.  For--- further documentation, see http://haskell.org/cabal/users-guide/- name:                deterministic-game-engine-version:             0.1.0.0+version:             0.2.0 synopsis:            Simple deterministic game engine-description:         Game engine for creating deterministic games.+description:         Haskell library for creating simple deterministic games,+                     such as tic-tac-toe. The engine requires a minimal set of+                     actions related to the game, and then will run the game+                     until a terminal state is reached. license:             MIT license-file:        LICENSE author:              Tyler Olson maintainer:          tydotg@gmail.com homepage:            https://github.com/TGOlson/deterministic-game-engine bug-reports:         https://github.com/TGOlson/deterministic-game-engine/issues--- copyright: category:            Game Engine build-type:          Simple--- extra-source-files: cabal-version:       >=1.10 + Source-repository head     Type:     git     Location: https://github.com/TGOlson/deterministic-game-engine@@ -25,17 +24,24 @@ library   hs-source-dirs:      Src   exposed-modules:     GameEngine+  other-modules:       GameEngine.GameActions,+                       GameEngine.GameState,+                       GameEngine.Move,+                       GameEngine.Player -  -- other-modules:-  -- other-extensions:-  build-depends:       base >=4.0 && <5.0+  build-depends:       base <5.0,+                       mtl+   default-language:    Haskell2010 + test-suite test-  hs-source-dirs:   Spec-  main-is:          Spec.hs-  ghc-options:      -Wall-  type:             exitcode-stdio-1.0-  build-depends:    base >=4.0 && <5.0,-                    hspec >=2.1 && <2.2,-                    deterministic-game-engine+  hs-source-dirs:      Spec+  main-is:             Spec.hs+  ghc-options:         -Wall+  type:                exitcode-stdio-1.0+  build-depends:       base <5.0,+                       hspec >=2.1 && <2.2,+                       deterministic-game-engine++  default-language:    Haskell2010