From UBC Wiki


Authors: Zhihang (George) Zhang, Spencer Yao

What is the problem?

We will be implementing the game Mancala in Haskell. Mancala is a two player, turn-based strategy game dating as far back as the 7th century, where players try to collect as many beads in their Mancala as possible.

There are many variations of this game, and we will be implementing this version

What is the something extra?

We will be creating an opponent capable of determining good moves through strategies such as gaining an extra turn if the last bead was deposited in its own mancala and recognizing potential capture opportunities.

What did we learn from doing this?

The biggest takeaway we had from making Mancala in Haskell was that Haskell worked quite well for implementing the game, though some creative measures had to be taken in order to circumvent the limitations of functional programming. For instance, in a direct programming language, we would've been able to create a wide variety of variables to represent things like who's turn it is or how many points a player has. With Haskell, we had to get creative and find ways to represent the game as a state such that we were able to perform operations on the board (like moving pieces and checking for captures) without being able to directly assign values to variables. Conversely, a lot of potentially useful operations that could've been done via an object-oriented programming language like implementing a capture in 3 simple moves had to be approached from a different angle.

One of the challenges we had to overcome was implementing the opponent player in a way such that they would make good moves. The implementations of minimax and minimax with memory as discussed in the lectures were not enough to stop ghci from returning a stack overflow due to the huge amounts of potential moves a mancala game could have. In order to address this issue, we adopted argmax with maxas a method of allowing the computations to terminate after quickly calculating a small set of immediate moves, while still picking the best sequence of moves possible. Through this process, we also discovered that Haskell is surprisingly simple when it comes to implementing bot players such as the aforementioned - by simply passing states on and using argmax, we didn't have to explicitly implement a lot of different situations (like trying to get as many turns as possible) as we would've had to do in a direct programming language, as the functional programming approach would've returned the same answer just by computing that it was the best result. Because the bot only needed to know the game and state in order to play well, this simplified much of the bot player and showed that Haskell was great for this task.

In terms of implementing the game itself, one of the challenges we faced was not being able to do simple operations as we would in a direct programming language. For example, in Mancala, when you move pieces on your turn, you must deposit a bead in your own Mancala while skipping over your opponent's. In a language like Java, we could've implemented this fairly easily by creating two arrays and guarding for the player's turn with an if statement. In Haskell, however, we had to approach the problem a different way. By concatenating the current player's side of the board, their Mancala, and the opponent's side of the board without their Mancala, we created a circular map when pieces were moved in order to circumvent this issue. Aside from having to rethink these operations, however, Haskell proved to be relatively simple when developing games such as Mancala, as the syntax was easy to read and digest.

Haskell proved to be quite well-suited to making simple games. However, some of the limitations of Haskell were exhibited through being unable to directly modify a state and having to pass it through different functions in order to do so and the lack of easily modifiable global variables. In addition, because Haskell has to reconstruct states and games after every action, it proved to be slow in a couple circumstances, which meant that we had to "cut-corners" in order to ensure the functionality of the program. Our final conclusion is that while it may struggle with more complicated games with convoluted states, Haskell is very well suited for making simple games with relatively simple states like Mancala.

Link to Github Repository