Authors: Jason Dien, Kuanmin Huang, Maria Sottile
What is the problem?
We want to know if it is possible to use Haskell to implement a game called Gomoku, an abstract strategy board game played with Go pieces. More details can be found here: https://en.wikipedia.org/wiki/Gomoku.
The game is very similar to Connect Four but more complex: in order to win the game you need to connect 5 pieces together in a Go board and instead of dropping a piece down a column. Each player takes runs placing a piece on the board. The game will be implemented with a 15x15 board as the representation of the game and will be made for 2 players.
What is the something extra?
We plan to add:
- Save/Load functionality
- Player vs Computer with an AI algorithm we implement ourselves
- Player vs Player
What did we learn from doing this?
Ultimately, we all got a lot more comfortable using Haskell, and we were able to implement all the features we wanted to acomplish for this game. Specifically,
- We learned that task requiring making large uniform changes (such as updating the state of the board or switching between [[Tile]] and String representations of the board) were easily done with Haskell and very intuitive to understand. For example, our AI algorithm does a lot of board manipulations where determining the best action to take. This was very efficient to accomplish with a lot of map and filter functions.
- Similarly tasks requiring lots of calculations are simple to perform as we don't have to keep track of changing variables, and it is easy to keep track of types through type checks.
- On the other hand, tasks that require some level of global awareness (such as knowing what position on the board we are currently looking at) are not very intuitive in Haskell due to the lack of iteration. For example, iterating through the board and looking at the neighbors of each tile is tricky since there is not an intuitive way to keep track of the 2d array indices. We ended up creating a separate position array that gets passed around to do this.
- We also learned that some more complicated IO tasks (such and reading and writing lots of different types of data to a file) are less straight forward in Haskell. In our save and load functions, we ended up creating three separate save files since keeping track of what data should be stored in each line of a file would have been a lot less simple to code.