From UBC Wiki


Authors: Daniel Hsiao, Vishav Kandola

What is the problem?

The focus of our project will to be implement the puzzle game Inertia from Simon Tatham’s Portable Puzzle Collection and extend it in an simple but challenging manner. Inertia is originally a single player board game where a two dimensional board is littered with blocks, diamonds and mines. The objective of the game is to maneuver the player’s character, thereby picking up the diamonds for score, whilst maneuvering in the 8 directions allowed (up/down,left/right, diagonals, etc) and to avoid the mines whilst gaining score. A special restriction is placed on movement where any movement is carried on until the player hits a Block tile or a mine (and loses the game). Block tiles that are apart of the map help and hurt the player in positioning his or her character. The game ends when the player collects all the diamonds or the character meets their untimely end in a mine tile.

What is the something extra?

The original Inertia game consist of only one player. We will introduce multiplayer aspect to the game. The game can then be played by two players or one player vs AI. Now, instead of collecting all diamonds in the game, there will be an extra objective to the game: consume the opponent. The opponent will either be introduced as an AI or as a second player. The endgame will either be all diamonds being collected or one of the players has been consumed.

Additionally, we’ll provide a pretty GUI frontend for playing the game instead of a terminal prompt, and allow 2 player games without any AI to be played also.

What did we learn from doing this?

We learned that Haskell is a powerful tool in designing data models via type polymorphism and the usage of first class functions. We were able to implement a GUI using a library that provided an API which consumed functions we designed. Due to that side effect free nature of Haskell, we encapsulated our state as data that was threaded through the execution of our program.

This allowed us to write functions that converted the data model of our choosing into a displayable picture, functions to handle keyboard and mouse updates to the data model, and functions that executed on every frame. We provided functions that plugged into the bindings the GUI library we chose provided, easily extending it for our needs. The lack of side effects also enabled us to focus on these abstractions one at a time, in the context of the inputs provided and the output needed. This made it easy to test the functions independently, but we found difficulty in testing the whole system interaction comparatively, due to the threaded nature of the data model. This was particularly so as our feature set increased, and functions were doing more and more complicated things.

Additionally we found that purely functional languages cannot escape side effects entirely. In our early stages we attempted to load image assets from the file once and never access the file system throughout the remainder of the program again. We found this forced us to thread IO throughout our entire program. We later abandoned this in favor of a purely functional drawing algorithm that converts coordinates from our data model to pixels on a viewport. We also had similar challenges with randomization, and ended up making a compromise in order to make our computer player more challenging.

As a minor side note we also learned the Cabal package system, and have included a .cabal file to setup a project and have included instructions to compile the game executable.