Last November, there was a scandal when confidential documents about offshore investments were leaked to over 400 journalists all around the world. This crisis, called the ‘Paradise Papers’, resulted in an on-going investigation from the International Consortium of Investigative Journalists (ICIJ) about tax havens and some of the world’s most powerful people and companies’ fortunes.
It also inspired my teachers at Polytech a topic for our C++ project: we were asked to design an application related to this matter – even remotely. I decided I would answer with a cynical game in which you take the side of ‘a poor rich businessman, hunted by the cruel media’…
[projectinfo languages=”c/c++” team=”1″ duration=”3 months”]
Paradise Man: help Bobby find his way
The game is a maze: you have to guide Bobby the Businessman from his villa to the exit on Paradise Isle. Several obstacles will be placed on his path in the form of journalists, judges and whistleblowers trying to discredit Bobby and send him to jail. You need to bring him to the Isle before it is too late and he has lost all his money, otherwise the good businessman will be caught and you will lose!
You play on a randomly created board (as explained later in the article) that contains an entry point, an exit point, some enemies here and there and a few ‘special tiles’. When you walk on them, these cells can give you extra money or reduce the remaining time.
You also have a limited number of lives and, whenever enemies hit you, you lose some depending on the type of opponent. If you reach 0 health points, that’s it!
How to give the player a rich user experience?
To make Paradise Man an interesting and re-playable game (meaning, with some lifetime), we need to give a new experience to the player each time. Of course, random is key for this, thus the board is generated procedurally for every new game.
The process relies on an algorithm in the spirit of the union-find paradigm inspired by this tutorial of Yann Langlais. Basically, you start with a grid of isolated cells and you gradually open walls to make a few paths. Then, to choose which ‘door’ to create, you consider that cells are in sets with specific identifiers and you only join them if they are not in the same group; if you do join them, they are now in the same set. Here is a schematic representation of the process:
This gives us relatively balanced mazes with plenty of roads and crossings, rather than one big path with only sporadic blobs, which is way better for the player.
One thread, two threads… multi-threads!
Because the game requires visual updates at the same time as game updates, we needed a multi-threading system so both processes could execute in parallel.
In our game, one main thread is dedicated to the input/output management and the other takes care of the timer. The two threads share resources, so we implemented ‘mutex’ (for ‘mutual exclusion’) to avoid concurrent access that are handled by the GameManager. This way, if for instance the player walks on a trapped tile and loses time, the global clock that is usually updated by the timer thread is temporarily accessed by the main thread just to reduce the remaining time, before being given back.