This provides a front-end for a checkers game written in Haskell using the Brick library. It is meant for UCalgary CPSC449 course in programming paradigms. This is a TUI (a textual user interface), and should work over SSH or PuTTY.
To set up the program, you must have stack installed (click on the above link to download and install stack). The following set of bash commands will clone the git repository and build the stack project.
git clone https://github.com/benjamin-macadam/Haskell-Checkers-Frontend.git
cd Haskell-Checkers-Frontend
stack build
You can also download the project as a zip file from the github page and run stack build once you've entered the Haskell-Checkers-Frontend. Once you've run the build command, stack will then setup an appropriate environment to run this project. This may take 20 minutes your first time as stack will need to download and install a sandboxed GHC compiler and all of the necessary packages. To run this program, enter
stack run
and the program will run (note that at this point, all that will happen is a simple human vs. human game will be initiated). To debug the program, you will want to use the stack environments ghci.
stack ghci run
The game loop is split into two parts, human and AI.
The human controls the cursor and builds a move. This is activated when the gamestate has a "Human" player making a move.
- pressing the arrow keys navigates the board
- pressing the space key adds the current square to the move.
- pressing enter "applies the move".
- if the move is legal, then the move should be applied and the next players turn begins.
- if the move is illegal, then the game must tell them they made an illegal move and ask them to try again.
When AI's move will be displayed in the "move" bracket of the game status menu. The user must press enter for the move to be applied.
Here is a list of important types to build the checkers game.
type Coord = (Int, Int)
type Move = [Coord]
data Status = Red | Black | GameOver
deriving (Show, Eq)
Each square of the checkers board is represented by a pair of integers, and a move is represented by a list of coordinates. The status determines whose turn it is (or if the game has already been won).
data GameState =
GameState { _blackPieces :: [Coord]
, _redPieces :: [Coord]
, _blackKings :: [Coord]
, _redKings :: [Coord]
, _status :: Status
, _message :: String}
deriving (Show, Eq)
In the gamestate, the coordinates of red and black pieces are recorded in the pieces and kings lists. The status determines whose turn it is (or if it is game over). The message instructs the player on what to do (i.e. if they made an illegal move they must try again).
You may manipulat the game state using record syntax or by using the set, view, and over functions.
g{_blackpieces = []} -- update using record notation
_blackpieces g -- view using record notation
Here are some examples on how the different syntaxes are used for basic commands. We recommend you pick one and stay consistent throughout your code!
type ApplyMove = Move -> GameState -> GameState
type AiMove = GameState -> Move
The applymove and AiMove types are very important - an ApplyMove will provide "gamelogic" for your checkers game, and a AiMove will be an AI player.
In haskell, the main function has type IO(). We provide four functions:
human :: ApplyMove -> GameState -> IO ()
redAi :: AiMove -> ApplyMove -> GameState -> IO ()
blackAi :: AiMove -> ApplyMove -> GameState -> IO ()
aiTest :: AiMove -> AiMove -> ApplyMove -> GameState -> IO ()
To run the program, you will need to go to Main.hs and set
main = human your_apply_move your_game_state
You will need to hand the program the AI programs, game logic function, and the gamestate you wish to begin the game from (you may hand the game state to more easily test your code). We have included the convenience function providing the initial game state.
initialGameState :: GameState
initialGameState =
GameState { _blackPieces = blackInit
, _redPieces = redInit
, _blackKings = []
, _redKings = []
, _status = Red
, _message = ""}