With the first competition entry behind us, it's time to start developing the project - and what better to begin with, than a general draft of the architecture. Speaking from experience, although starting coding right away without any plans can lead to some working code quickly, it usually makes it much harder to develop it further. I wouldn't want to get stuck halfway through the project having to start from scratch, so I'll first think a bit about how to structure it well.
Firstly, the main purpose of the project is making it possible to play Ktulu over the internet - so we will be dealing with some kind of a network app. One of the players will start a server, and the others will connect to it as clients. It will probably be the most convenient to put both the server and the client into a single executable (so that the host won't have to start multiple programs), but it's just a detail. What's important is how to divide responsibility between the server and the clients.
[Update: Before further reading, I recommend checking out the rules of the game.]
The roles of the server and clients
In the original game we have the game master (called "Manitou"), who controls everything - he knows who is who, who has the statue (unlike in Mafia, where one cares only about killing all the opponents, in Ktulu the majority of goals revolves around "the statue", being initially in the possession of Bandits), he tells the players to open or close their eyes and counts the votes during votings. The server will play this role - it will remember the full state of the game and issue appropriate commands to the clients. The only thing the clients will do is telling the server about the decisions made by the players.
The communication between Manitou and the players actually boils down to a few simple things. Manitou can:
- (as I already mentioned) tell the player to open/close their eyes (in the game language: go to sleep/wake up)
- ask the players about their choice regarding their special abilities, which for all characters means just pointing out another player (if the player wants to use the ability)
- ask the players to vote (in a duel or in a vote at the end of the day, about searching and possibly killing someone)
And that is pretty much all. In the case of some abilities it's necessary to pass some information back to the player, but this will be handled by player requests (more about it below).
The players, on the other hand, can:
- talk, if they are awake and it's daytime - at night the communication between awake players will be limited in order to reflect the necessity of being silent during the real game
- make choices they are asked about by Manitou, ie. use their abilities (and possibly receive some information back) or vote
And... looks like that's it. It doesn't look too complex, but it's sufficient for a really interesting game.
An example flow of the beginning of the game would then look like this:
- Manitou tells everyone to go to sleep.
- Manitou wakes up the Prostitute and asks her to use her ability (she can't abstain from using it).
- The Prostitute tells Manitou which person she wants to check and receives their identity in response.
- Manitou tells the Prostitute to fall asleep (optionally: he allows the Sheriff and the Pastor to similarly use their abilities) and wakes up the Bandits.
- The Bandits get to know each other, as they are all awake. Manitou asks the Boss to choose the person that will hold the statue and receives the choice in response.
- Manitou tells the Bandits to go to sleep and wakes up the Indians.
- The Indians get to know each other and go to sleep.
- Manitou wakes up the Aliens (if they are in the game), lets them get to know each other and orders them back to sleep.
- Manitou announces the first day and wakes up everyone.
- The players start the discussion.
It's apparent that those few simple messages would allow for a full simulation of the zeroth night and beginning of the first day.
A natural way of implementing this is a set of two traits - for those that don't know Rust, it's something similar to Java's or C#'s interfaces, but different in a few details: for example, a trait method can have a default implementation and traits can contain methods that would be called "static" in Java/C#. Back to the point, the trait would correspond to a player and Manitou - the player trait would contain methods to be called by Manitou (like
use_ability()), and the Manitou trait would provide methods to be called by the player (
Both those traits would be implemented for a pair of structs: one representing a player/Manitou and another, being a proxy object for Remote Procedure Calls (RPCs) through the network.
This architecture would let both the player and Manitou objects not care whether they are communicating with the other side directly or via the network. It would thus allow for using a single implementation of those objects both in the proper application and in the automatic tests, which is a big advantage.
As for the RPC themselves, it could be possible to utilize a ready-made library. It looks like Google created an interesting one (tarpc). There is a good chance that using it will let me develop the project much more quickly.
I haven't said a word about the interface here, but it was on purpose. I want to focus on the implementation of the rules and client-server communication as a standalone library first. When it is ready, it will be possible to use it in the actual application, which will give some sort of interface to the player. This is a task for later, though.
The code of the project is slowly being written on GitHub - I encourage you to watch the progress :)