From UBC Wiki

Authors: Cormac Mollitor, Luce Liu, Matthew Ridderikhoff

What is the problem?

We play to make a recreation of Reigns ( with a student flavour, where you’re managing 4 resources: Sleep, Grades, Money, and Social Life. The goal of the game is to make it from September to May without running out of any of your resources. A score is given by how many weeks the user survived, or a victory screen if they make it through the spring exams.

Gameplay: Player is presented with a series of cards that present yes/no decisions, where each decision impacts at least one aspect of your state (sleep, money, school, friends) positively or negatively. Upon making a decision, the player’s state updates accordingly.

It will feature a dynamic deck, where some cards are added/removed based on the decisions you’ve made. E.g. you've selected a “spend the night drinking with friends” card 3 times in the game, so a liver failure card is inserted into the deck, which if you happen to draw it, will drain a lot of money and time resources

What is the something extra?

As an extra part, we will develop a GUI for the game using Gloss. The GUI will feature cards and current health values for each resource. For user interactions, we will implement a variation of swipe left/right gestures. Since our version will be played on PC, we will substitute the left and right arrow keys for left and right swipes respectively. On a single left/right arrow press, it will show the effect this card will have on the 4 resources from that decision. On a double left/right arrow press, it will make the corresponding decision (left = no, right = yes).

What did we learn from doing this?

Functional Programming for a turn-based game: Overall, we conclude it is very feasible to implement a turn-based game with functional programming. Due to Haskell’s strongly typed nature, we were able to concisely create types without worrying about implementing full classes like we would have had to in OO, and of course we never had to worry about runtime errors. Furthermore, with a functional approach, we found that our concerns—managing the game state, updating it and reflecting those changes in the UI—were very well separated and it was easy to make our game congruent with MVC.

Using Gloss for a UI-based game: Using Gloss for this game was definitely a mixed experience. On one hand, it provided a very clean interface for drawing the state and handling input. On the other hand, it was not great for rendering text, and we had a lot of issues aligning UI elements (e.g. text’s position is measured from the left, so center-aligning text would have been extremely complicated). Gloss also abstracts away the IO workflow from you, which was great initially, but as we discussed earlier, it made using a random number generator more difficult, as we were detached from the IO workflow.

Overall, the biggest hurdle was utilizing the Gloss play function, which abstracted out IO, with a random number generator in Haskell, that required IO. This made for some redundant code, as we had to wrap some of our functions with returns and do, which defeated the purpose of this abstraction. We didn’t initially account for this, because in other languages we’ve worked with (Java, JavaScript, Python, etc.), random number generation—an important component of many games—is usually as simple as calling a utility function from a standard library and immediately being able to integrate it into the existing codebase. At the beginning of the project, we designed the game at assuming that we wouldn’t have to deal with IO, as Gloss handled this for us. Once we incorporated random number generation to select random cards, we had to refactor a majority of our existing codebase to behave with IO. While it is very feasible to incorporate randomness into games developed in Haskell, it is important to note that developers won’t be able to escape IO and will have to write code that can accommodate it, which devalues the Gloss IO abstraction.

Links to code, etc