starter-snake-haskell 1.0.0 → 1.1.0
raw patch · 16 files changed
+296/−80 lines, 16 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Battlesnake.API.InfoResponse: APIVersion1 :: APIVersion
+ Battlesnake.API.InfoResponse: data APIVersion
+ Battlesnake.API.InfoResponse: instance Data.Aeson.Types.ToJSON.ToJSON Battlesnake.API.InfoResponse.APIVersion
+ Battlesnake.API.InfoResponse: instance GHC.Show.Show Battlesnake.API.InfoResponse.APIVersion
+ Battlesnake.Core.Battlesnake: [customizations] :: Battlesnake -> Customizations
+ Battlesnake.Core.Customizations: Customizations :: Text -> Text -> Text -> Customizations
+ Battlesnake.Core.Customizations: [color] :: Customizations -> Text
+ Battlesnake.Core.Customizations: [head] :: Customizations -> Text
+ Battlesnake.Core.Customizations: [tail] :: Customizations -> Text
+ Battlesnake.Core.Customizations: data Customizations
+ Battlesnake.Core.Customizations: instance Data.Aeson.Types.FromJSON.FromJSON Battlesnake.Core.Customizations.Customizations
+ Battlesnake.Core.Customizations: instance Data.Aeson.Types.ToJSON.ToJSON Battlesnake.Core.Customizations.Customizations
+ Battlesnake.Core.Customizations: instance GHC.Generics.Generic Battlesnake.Core.Customizations.Customizations
+ Battlesnake.Core.Customizations: instance GHC.Show.Show Battlesnake.Core.Customizations.Customizations
+ Battlesnake.Core.Game: [map] :: Game -> Text
+ Battlesnake.Core.Game: [source] :: Game -> Text
+ Battlesnake.Core.Ruleset: [settings] :: Ruleset -> RulesetSettings
+ Battlesnake.Core.RulesetSettings: RoyaleModeSettings :: Int -> RoyaleModeSettings
+ Battlesnake.Core.RulesetSettings: RulesetSettings :: Int -> Int -> Int -> RoyaleModeSettings -> SquadModeSettings -> RulesetSettings
+ Battlesnake.Core.RulesetSettings: SquadModeSettings :: Bool -> Bool -> Bool -> Bool -> SquadModeSettings
+ Battlesnake.Core.RulesetSettings: [allowBodyCollisions] :: SquadModeSettings -> Bool
+ Battlesnake.Core.RulesetSettings: [foodSpawnChance] :: RulesetSettings -> Int
+ Battlesnake.Core.RulesetSettings: [hazardDamagePerTurn] :: RulesetSettings -> Int
+ Battlesnake.Core.RulesetSettings: [minimumFood] :: RulesetSettings -> Int
+ Battlesnake.Core.RulesetSettings: [royale] :: RulesetSettings -> RoyaleModeSettings
+ Battlesnake.Core.RulesetSettings: [sharedElimination] :: SquadModeSettings -> Bool
+ Battlesnake.Core.RulesetSettings: [sharedHealth] :: SquadModeSettings -> Bool
+ Battlesnake.Core.RulesetSettings: [sharedLength] :: SquadModeSettings -> Bool
+ Battlesnake.Core.RulesetSettings: [shrinkEveryNTurns] :: RoyaleModeSettings -> Int
+ Battlesnake.Core.RulesetSettings: [squad] :: RulesetSettings -> SquadModeSettings
+ Battlesnake.Core.RulesetSettings: data RulesetSettings
+ Battlesnake.Core.RulesetSettings: data SquadModeSettings
+ Battlesnake.Core.RulesetSettings: instance Data.Aeson.Types.FromJSON.FromJSON Battlesnake.Core.RulesetSettings.RoyaleModeSettings
+ Battlesnake.Core.RulesetSettings: instance Data.Aeson.Types.FromJSON.FromJSON Battlesnake.Core.RulesetSettings.RulesetSettings
+ Battlesnake.Core.RulesetSettings: instance Data.Aeson.Types.FromJSON.FromJSON Battlesnake.Core.RulesetSettings.SquadModeSettings
+ Battlesnake.Core.RulesetSettings: instance GHC.Classes.Eq Battlesnake.Core.RulesetSettings.RoyaleModeSettings
+ Battlesnake.Core.RulesetSettings: instance GHC.Classes.Eq Battlesnake.Core.RulesetSettings.RulesetSettings
+ Battlesnake.Core.RulesetSettings: instance GHC.Classes.Eq Battlesnake.Core.RulesetSettings.SquadModeSettings
+ Battlesnake.Core.RulesetSettings: instance GHC.Generics.Generic Battlesnake.Core.RulesetSettings.RoyaleModeSettings
+ Battlesnake.Core.RulesetSettings: instance GHC.Generics.Generic Battlesnake.Core.RulesetSettings.RulesetSettings
+ Battlesnake.Core.RulesetSettings: instance GHC.Generics.Generic Battlesnake.Core.RulesetSettings.SquadModeSettings
+ Battlesnake.Core.RulesetSettings: instance GHC.Show.Show Battlesnake.Core.RulesetSettings.RoyaleModeSettings
+ Battlesnake.Core.RulesetSettings: instance GHC.Show.Show Battlesnake.Core.RulesetSettings.RulesetSettings
+ Battlesnake.Core.RulesetSettings: instance GHC.Show.Show Battlesnake.Core.RulesetSettings.SquadModeSettings
+ Battlesnake.Core.RulesetSettings: newtype RoyaleModeSettings
- Battlesnake.API.InfoResponse: InfoResponse :: Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> InfoResponse
+ Battlesnake.API.InfoResponse: InfoResponse :: APIVersion -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> InfoResponse
- Battlesnake.API.InfoResponse: [apiversion] :: InfoResponse -> Text
+ Battlesnake.API.InfoResponse: [apiversion] :: InfoResponse -> APIVersion
- Battlesnake.Core.Battlesnake: Battlesnake :: Text -> Text -> Integer -> [Coordinate] -> Text -> Coordinate -> Integer -> Text -> Maybe Text -> Battlesnake
+ Battlesnake.Core.Battlesnake: Battlesnake :: Text -> Text -> Integer -> [Coordinate] -> Text -> Coordinate -> Integer -> Text -> Maybe Text -> Customizations -> Battlesnake
- Battlesnake.Core.Game: Game :: Text -> Ruleset -> Integer -> Game
+ Battlesnake.Core.Game: Game :: Text -> Ruleset -> Text -> Integer -> Text -> Game
- Battlesnake.Core.Ruleset: Ruleset :: Text -> Text -> Ruleset
+ Battlesnake.Core.Ruleset: Ruleset :: Text -> Text -> RulesetSettings -> Ruleset
- Battlesnake.Server: runBattlesnakeServer :: InfoResponse -> GameRequestHandler () -> GameRequestHandler MoveResponse -> GameRequestHandler () -> IO ()
+ Battlesnake.Server: runBattlesnakeServer :: IO InfoResponse -> GameRequestHandler () -> GameRequestHandler MoveResponse -> GameRequestHandler () -> IO ()
Files
- CHANGELOG.md +16/−0
- README.md +72/−7
- app/Main.hs +11/−10
- src/Battlesnake/API/GameRequest.hs +8/−4
- src/Battlesnake/API/InfoResponse.hs +20/−7
- src/Battlesnake/API/MoveResponse.hs +4/−2
- src/Battlesnake/Core/Battlesnake.hs +21/−10
- src/Battlesnake/Core/Board.hs +10/−5
- src/Battlesnake/Core/Coordinate.hs +10/−8
- src/Battlesnake/Core/Customizations.hs +26/−0
- src/Battlesnake/Core/Direction.hs +2/−2
- src/Battlesnake/Core/Game.hs +12/−3
- src/Battlesnake/Core/Ruleset.hs +7/−3
- src/Battlesnake/Core/RulesetSettings.hs +53/−0
- src/Battlesnake/Server.hs +21/−18
- starter-snake-haskell.cabal +3/−1
CHANGELOG.md view
@@ -5,6 +5,22 @@ This project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/). +## 1.1.0 (2023-08-26)++Synced with latest Battlesnake API spec and improved documentation.++### Added++- `map` and `source` fields added to `Game`+- `rulesetSettings` field added to `Ruleset`+- `customizations` field added to `Battlesnake`++### Changed++- the `info` handler passed to `runBattlesnakeServer` must be an IO action now+- `InfoResponse.apiversion` was changed from `Text` to the new `APIVersion` type+ to prevent invalid api version+ ## 1.0.0 (2023-08-22) ### Added
README.md view
@@ -7,13 +7,78 @@ This starter repo can be used in two different ways -1. Installed as a hackage library in your haskell project 1. As a fork that is subsequently modified to your needs+1. Installed as a hackage library in your haskell project -# Deployment+## As a fork -To deploy on Heroku you can use the provided `Procfile` when using the template-as a fork. Otherwise you will need to define your own `Procfile`.-Addtionally the-[heroku-buildpack-stack](https://github.com/mfine/heroku-buildpack-stack)-buildpack is required for the application to run on heroku+First clone this repo or create a fork by pushing the fork button and clone your+fork.++You can then start implementing your game logic in `app/Main.hs`.++This template uses [Stack](https://docs.haskellstack.org/en/stable/) to build+and run the project.++To start the server locally run `stack run` which will start a development+webserver on port 3000. (The port can be changed by setting the `PORT`+environment variable)++## As hackage dependency++### With cabal++Add the dependency to `your-app.cabal`++```+executable myfirstapp+ main-is: Main.hs+ build-depends:+ ...+ starter-snake-haskell ^>=1.1.0+```++### With stack++Add the dependency as `extra-dep` in your `stack.yaml`++```+resolver: lts-20.26+packages:+ - .++extra-deps:+- starter-snake-haskell-1.1.0+```++### Implementation++You can now start implementing your battlesnake logic in your project. You can+use the [Main](app/Main.hs) from this repo as a starting point.++# Deploy to Heroku++When using the repo as a fork you can use the provided [`Procfile`](Procfile) to+deploy it to heroku. Otherwise you will need to provide your own.++Afterwards you can use the [Heroku+CLI](https://devcenter.heroku.com/articles/heroku-cli#install-the-heroku-cli) to+deploy your project.++First, login to your account:++```+heroku login -i+```++Afterwards you can create a new deployment in heroku using the [heroku-buildpack-stack](https://github.com/mfine/heroku-buildpack-stack).++```+heroku create your-battlesnake-name --buildpack https://github.com/mfine/heroku-buildpack-stack+```++You can then push your code to heroku with git where it will be build and deployed:++```+git push heroku master+```
app/Main.hs view
@@ -14,17 +14,18 @@ moveHandler endHandler -snakeInfo :: Info.InfoResponse+snakeInfo :: IO Info.InfoResponse snakeInfo =- Info.InfoResponse- { Info.apiversion = "1",- -- Optional Customization:- Info.author = Nothing, -- TODO: Your Battlsnake username here- Info.color = Nothing, -- TODO: pesonalize- Info.head = Nothing, -- TODO: pesonalize- Info.tail = Nothing, -- TODO: pesonalize- Info.version = Nothing -- TODO: Version number or tag for your battlesnake- }+ return+ Info.InfoResponse+ { Info.apiversion = Info.APIVersion1+ , -- Optional Customization:+ Info.author = Nothing -- TODO: Your Battlsnake username here+ , Info.color = Nothing -- TODO: pesonalize+ , Info.head = Nothing -- TODO: pesonalize+ , Info.tail = Nothing -- TODO: pesonalize+ , Info.version = Nothing -- TODO: Version number or tag for your battlesnake+ } -- TODO: -- implement start handler if you need to allocate ressources or data at the
src/Battlesnake/API/GameRequest.hs view
@@ -13,10 +13,14 @@ This contains all the information you need to determine your snakes next move.} -} data GameRequest = GameRequest- { game :: Game, -- ^ Information about the current game. (See "Battlesnake.Core.Game")- turn :: Integer, -- ^ The turn beeing played.- board :: Board, -- ^ The game board. (See "Battlesnake.Core.Board")- you :: Battlesnake -- ^ Your snake. (See "Battlesnake.Core.Battlesnake"")+ { game :: Game+ -- ^ Information about the current game. (See "Battlesnake.Core.Game")+ , turn :: Integer+ -- ^ The turn beeing played.+ , board :: Board+ -- ^ The game board. (See "Battlesnake.Core.Board")+ , you :: Battlesnake+ -- ^ Your snake. (See "Battlesnake.Core.Battlesnake"") } deriving (Show, Generic)
src/Battlesnake/API/InfoResponse.hs view
@@ -1,22 +1,35 @@ {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-} module Battlesnake.API.InfoResponse where -import Data.Aeson (ToJSON)+import Data.Aeson (ToJSON, Value (String), toJSON) import Data.Text import GHC.Generics +-- | Supported versions of the Battlesnake API+data APIVersion = APIVersion1 deriving (Show)++instance ToJSON APIVersion where+ toJSON APIVersion1 = String "1"+ {-| The response to an info request. This can be used to modify the appearance of your snake on the game board. -} data InfoResponse = InfoResponse- { apiversion :: Text, -- ^ The API version supported by the battlesnake server (currently 1).- author :: Maybe Text, -- ^ The username of the author of the snake.- color :: Maybe Text, -- ^ A color code used to set the color of the snake.- head :: Maybe Text, -- ^ A custom head to use for the snake. (See https://play.battlesnake.com/customizations for options.)- tail :: Maybe Text, -- ^ A custom tail to use for the snake. (See https://play.battlesnake.com/customizations for options.)- version :: Maybe Text -- ^ The version of the snake.+ { apiversion :: APIVersion+ -- ^ The API version supported by the battlesnake server (currently 1).+ , author :: Maybe Text+ -- ^ The username of the author of the snake.+ , color :: Maybe Text+ -- ^ A color code used to set the color of the snake.+ , head :: Maybe Text+ -- ^ A custom head to use for the snake. (See https://play.battlesnake.com/customizations for options.)+ , tail :: Maybe Text+ -- ^ A custom tail to use for the snake. (See https://play.battlesnake.com/customizations for options.)+ , version :: Maybe Text+ -- ^ The version of the snake. } deriving (Show, Generic)
src/Battlesnake/API/MoveResponse.hs view
@@ -9,8 +9,10 @@ -- | The response to a move request. data MoveResponse = MoveResponse- { move :: Direction, -- ^ The direction for the next move.- shout :: Maybe Text -- ^ An optional shout to be displayed with the move.+ { move :: Direction+ -- ^ The direction for the next move.+ , shout :: Maybe Text+ -- ^ An optional shout to be displayed with the move. } deriving (Show, Generic)
src/Battlesnake/Core/Battlesnake.hs view
@@ -3,25 +3,36 @@ module Battlesnake.Core.Battlesnake where import Battlesnake.Core.Coordinate (Coordinate)+import Battlesnake.Core.Customizations (Customizations) import Data.Aeson (FromJSON, ToJSON) import Data.Text import GHC.Generics - {-| A snake in the game. See: https://docs.battlesnake.com/api/objects/battlesnake -} data Battlesnake = Battlesnake- { id :: Text, -- ^ The ID of the snake.- name :: Text, -- ^ The name of the snake.- health :: Integer, -- ^ Current health of the snake (0-100).- body :: [Coordinate], -- ^ A list of coordinates representing the snake's body.- latency :: Text, -- ^ The snake's latency.- head :: Coordinate, -- ^ The position of the snakes head- length :: Integer, -- ^ The length of the snake.- shout :: Text, -- ^ The snake's last moves shout.- squad :: Maybe Text -- ^ The squad the snake is a part of (In squad mode).+ { id :: Text+ -- ^ The ID of the snake.+ , name :: Text+ -- ^ The name of the snake.+ , health :: Integer+ -- ^ Current health of the snake (0-100).+ , body :: [Coordinate]+ -- ^ A list of coordinates representing the snake's body.+ , latency :: Text+ -- ^ The snake's latency.+ , head :: Coordinate+ -- ^ The position of the snakes head+ , length :: Integer+ -- ^ The length of the snake.+ , shout :: Text+ -- ^ The snake's last moves shout.+ , squad :: Maybe Text+ -- ^ The squad the snake is a part of (In squad mode).+ , customizations :: Customizations+ -- ^ The customizations of the snake } deriving (Show, Generic)
src/Battlesnake/Core/Board.hs view
@@ -12,11 +12,16 @@ See: https://docs.battlesnake.com/api/objects/board -} data Board = Board- { height :: Integer, -- ^ The height of the board- width :: Integer, -- ^ The width of the board- food :: [Coordinate], -- ^ A list of coordinates representing food locations- hazards :: [Coordinate], -- ^ A list of coordinates representing hazard locations- snakes :: [Battlesnake] -- ^ A list of all snakes on the board+ { height :: Integer+ -- ^ The height of the board+ , width :: Integer+ -- ^ The width of the board+ , food :: [Coordinate]+ -- ^ A list of coordinates representing food locations+ , hazards :: [Coordinate]+ -- ^ A list of coordinates representing hazard locations+ , snakes :: [Battlesnake]+ -- ^ A list of all snakes on the board } deriving (Show, Generic)
src/Battlesnake/Core/Coordinate.hs view
@@ -3,19 +3,21 @@ module Battlesnake.Core.Coordinate where import Data.Aeson- ( FromJSON (parseJSON),- KeyValue ((.=)),- ToJSON (toEncoding),- pairs,- withObject,- (.:),+ ( FromJSON (parseJSON)+ , KeyValue ((.=))+ , ToJSON (toEncoding)+ , pairs+ , withObject+ , (.:) ) import GHC.Generics -- | Represents a coordinate on the game board. data Coordinate = Coordinate- { coordX :: Integer, -- ^ The X coordinate (0 indexed, from left to right)- coordY :: Integer -- ^ The Y coordinate (0 indexed, from bottom to top)+ { coordX :: Integer+ -- ^ The X coordinate (0 indexed, from left to right)+ , coordY :: Integer+ -- ^ The Y coordinate (0 indexed, from bottom to top) } deriving (Show, Eq, Generic)
+ src/Battlesnake/Core/Customizations.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE DeriveGeneric #-}+module Battlesnake.Core.Customizations where++import Data.Aeson (FromJSON, ToJSON)+import Data.Text+import GHC.Generics++{-|+ Battlesnake customizations object+ See: https://docs.battlesnake.com/api/objects/battlesnake+-}+data Customizations = Customizations+ { color :: Text+ -- ^ A hex color code used to display the snake+ , head :: Text+ -- ^ Displayed head of the battlesnake. See+ -- https://docs.battlesnake.com/guides/customizations for available options+ , tail :: Text+ -- ^ Displayed tail of the battlesnake. See+ -- https://docs.battlesnake.com/guides/customizations for available options+ }+ deriving (Show, Generic)++instance ToJSON Customizations++instance FromJSON Customizations
src/Battlesnake/Core/Direction.hs view
@@ -3,10 +3,10 @@ import Data.Aeson (ToJSON, Value (String), toJSON) import Data.Text -{- |+{-| The possible directions your snake can move in. See: https://docs.battlesnake.com/api/requests/move- -}+-} data Direction = UP | DOWN | LEFT | RIGHT deriving (Ord, Eq, Show) instance ToJSON Direction where
src/Battlesnake/Core/Game.hs view
@@ -12,9 +12,18 @@ See: https://docs.battlesnake.com/api/objects/game -} data Game = Game- { id :: Text, -- ^ The ID of the game.- ruleset :: Ruleset, -- ^ The ruleset used in the game.- timeout :: Integer -- ^ The maximum time in milliseconds the server will wait for a response from your server.+ { id :: Text+ -- ^ The ID of the game.+ , ruleset :: Ruleset+ -- ^ The ruleset used in the game.+ , map :: Text+ -- ^ The name of the map used to create the game. (See+ -- https://docs.battlesnake.com/api/objects/game-maps for possible values.)+ , timeout :: Integer+ -- ^ The maximum time in milliseconds the server will wait for a response from+ -- your server.+ , source :: Text+ -- ^ The source of the game. } deriving (Show, Eq, Generic)
src/Battlesnake/Core/Ruleset.hs view
@@ -2,17 +2,21 @@ module Battlesnake.Core.Ruleset where +import Battlesnake.Core.RulesetSettings (RulesetSettings) import Data.Aeson (FromJSON) import Data.Text import GHC.Generics {-| Information about the ruleset used in the game.- See: https://docs.battlesnake.com/api/objects/game+ See: https://docs.battlesnake.com/api/objects/ruleset -} data Ruleset = Ruleset- { name :: Text, -- ^ The name of the ruleset.- version :: Text -- ^ The version of the ruleset.+ { name :: Text+ -- ^ The name of the ruleset.+ , version :: Text+ -- ^ The version of the ruleset.+ , settings :: RulesetSettings } deriving (Show, Eq, Generic)
+ src/Battlesnake/Core/RulesetSettings.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE DeriveGeneric #-}++module Battlesnake.Core.RulesetSettings where++import Data.Aeson (FromJSON)+import GHC.Generics++{-|+ Information about the ruleset settings used in the game.+ See: https://docs.battlesnake.com/api/objects/ruleset-settings+-}+data RulesetSettings = RulesetSettings+ { foodSpawnChance :: Int+ -- ^ The chance of a food spawning on a new round (0-100).+ , minimumFood :: Int+ -- ^ The minimum number of food that must be kept on the board+ , hazardDamagePerTurn :: Int+ -- ^ The amount of damage snakes take each turn they are in contact with a+ -- hazard. This stacks on top of the base damage of 1 that each snake takes+ -- per turn+ , royale :: RoyaleModeSettings+ -- ^ Settings uses in 'royale' mode+ , squad :: SquadModeSettings+ -- ^ Settings used in 'squad' mode+ }+ deriving (Show, Eq, Generic)++instance FromJSON RulesetSettings++-- | Settings used in `royale` mode+newtype RoyaleModeSettings = RoyaleModeSettings+ { shrinkEveryNTurns :: Int+ -- ^ The number of turns between shrinking the safe board area+ }+ deriving (Show, Eq, Generic)++instance FromJSON RoyaleModeSettings++-- | Settings used in 'squad' mode+data SquadModeSettings = SquadModeSettings+ { allowBodyCollisions :: Bool+ -- ^ Whether or not snakes on the same squad can collide with each other+ -- without diyng+ , sharedElimination :: Bool+ -- ^ Whether or not snakes on the same squad are eliminated together+ , sharedHealth :: Bool+ -- ^ Whether or not snakes on the same squad share health+ , sharedLength :: Bool+ -- ^ Whether or not snakes on the same squad share length+ }+ deriving (Show, Eq, Generic)++instance FromJSON SquadModeSettings
src/Battlesnake/Server.hs view
@@ -7,27 +7,30 @@ import Data.Functor ((<&>)) import Data.Maybe (fromMaybe) import System.Environment (lookupEnv)-import System.IO (BufferMode(LineBuffering), hSetBuffering, stdout)+import System.IO (BufferMode (LineBuffering), hSetBuffering, stdout) import Text.Read (readMaybe) import Web.Scotty - -- | A handler for a battlesnake server request. type GameRequestHandler a = GameRequest -> IO a -{- |+{-| Run a battlesnake server. Runs the server on the port specified by the environment variable "PORT" or port 3000 if the variable is not set.- * A "Battlesnake.API.InfoResponse" to be returned when the server receives an info request.++ * An IO action that returns a "Battlesnake.API.InfoResponse" which is run on info requests.+ * A 'GameRequestHandler' to be called when the server receives a start request.+ * A 'GameRequestHandler' to be called when the server receives a move request.+ * A 'GameRequestHandler' to be called when the server receives an end request. -}-runBattlesnakeServer ::- Info.InfoResponse ->- GameRequestHandler () ->- GameRequestHandler MoveResponse ->- GameRequestHandler () ->- IO ()+runBattlesnakeServer+ :: IO Info.InfoResponse+ -> GameRequestHandler ()+ -> GameRequestHandler MoveResponse+ -> GameRequestHandler ()+ -> IO () runBattlesnakeServer info startHandler moveHandler endHandler = do hSetBuffering stdout LineBuffering envPort <- lookupEnv "PORT" <&> (readMaybe =<<)@@ -38,20 +41,20 @@ moveHandler endHandler -routes ::- Info.InfoResponse ->- GameRequestHandler () ->- GameRequestHandler MoveResponse ->- GameRequestHandler () ->- ScottyM ()+routes+ :: IO Info.InfoResponse+ -> GameRequestHandler ()+ -> GameRequestHandler MoveResponse+ -> GameRequestHandler ()+ -> ScottyM () routes info startHandler moveHandler endHandler = do get "/" $ handleInfoRequest info post "/start" $ handleStartRequest startHandler post "/move" $ handleMoveRequest moveHandler post "/end" $ handleEndRequest endHandler -handleInfoRequest :: Info.InfoResponse -> ActionM ()-handleInfoRequest = json+handleInfoRequest :: IO Info.InfoResponse -> ActionM ()+handleInfoRequest info = liftIO info >>= json handleStartRequest :: GameRequestHandler () -> ActionM () handleStartRequest handler = do
starter-snake-haskell.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: starter-snake-haskell-version: 1.0.0+version: 1.1.0 synopsis: A Haskell Battlesnake starter description: See README at <https://github.com/ccntrq/starter-snake-haskell> category: Game, Web@@ -34,9 +34,11 @@ Battlesnake.Core.Battlesnake Battlesnake.Core.Board Battlesnake.Core.Coordinate+ Battlesnake.Core.Customizations Battlesnake.Core.Direction Battlesnake.Core.Game Battlesnake.Core.Ruleset+ Battlesnake.Core.RulesetSettings Battlesnake.Server other-modules: Paths_starter_snake_haskell