Duo Wiki

A crazy eight card game


Filed in: Blueprints.CodeRefactoring · Modified on : Mon, 08 Jun 09

Title: Code Refactoring and Module Break up for v0.9 and following versions
Version: 2008-12-02
Prerequisites: -
Status: Implemented
Maintainer: d_rol
Contributors: d_rol


This blueprint describes the code refactoring needed to support future features in the next releases. Features which are foreseen are multi player game, more artificial player behaviours, user management of the game rules, or user interface substitution.

It should be stressed that this list of features is not all-comprehensive. Neither is this list limiting for the present refactoring.


One of the Duo's historical features is that it is simple to install. Actually, up to version 0.8.1, Duo is made of a unique Python module.

The program was written by Camille Roux as an exercise to learn the language, and though it is running well, it is not possible to build new features on top of the existing code base. As of version 0.8.1, all the game engine (rules checking and player's turn ordering) is mixed up with the Tk interface code. All the program relies on some global variables. And variable and function naming is made of an English and French combination.


This development impacts the whole code base.


Proposed rewriting plan

Game core
This is the game main engine. It is essentially composed of a Referee class which is responsible of the game organization: accepting players for a round, distributing the cards, announcing the cards played or taken from the deck, the card on the heap and the winner. Actually, all the players only communicate with the Referee, and in return the Referee can send a reponse to the player or broadcast a message to all the players in the game.
The Referee is also the object which validates all the game events. Thus, the Referee checks if a player can draw or pass, and specially if the card he's playing is correct. To achieve that, it relies on a set of rules, each rule having conditions and possibly some action if checked (think pass or +2 cards for example).
The Referee assumes nothing about the players of a game. They can be human or not, they can be from the same process, on the same machine or anywhere on the net. The Referee and players only communicate through a dedicated protocol, and this communication is endorsed by the Duo Protocol Stack. This stack is made of two layers, which are described below.
Protocol Layer
This is the top layer of the Duo Protocol Stack. It provides the vocabulary to allow all the players in a game (no matter they may be human or artificial) to communicate, with the help of a referee. It is composed of messages, one for each event in the game. These messages have a direction: some can only be emitted by the referee, some only by the players. They also have well defined recipients: some may be sent to the referee, some to one player, and some to every player.
The protocol also defines the ProtocolAdapter class which provides a high-level way to use the protocol for any entity. The class Player specializes the ProtocolAdapter to provide everything a regular player may need.
Note that the protocol does not cover the media used by communication. May the messages be carried using a raw TCP connection, an instant messaging protocol or even mail, there would be no other impact on the game than the media speed. Of course, the faster the media, the better the game.
Transport Layer
The bottom layer of the Duo Protocol Stack and the one responsible for the media used for the communication. It doesn't assume anything about the messages it carries.
Duo transport relies on endpoints and contexts. Endpoints are the entities (usually the players and the referee) connected on the transport layer. Each one is identified by a unique identifier. A context is an environment which constrains the communication to the endpoints that belong to it: usual application should be a game or a chat room. An endpoint can belong to only one context at any time.
The Transport Layer is responsible to forward messages from one endpoint to another one, or from one endpoint to all the other ones in the same context. The layer implementation is interchangeable as long as it is reliable and ordered. In other words, it should check that all the messages reach the endpoint(s) to which they were destined. Additionally, it should forward the messages in the same order it has received them.
Artificial Intelligence (AI)
This pompously named component gathers the coded behaviours which are used by computer controlled players.
User Interface (UI)
The interface between the program and the user. This component fulfils the following roles:
  • Providing a view of the game which is presented to the player and any mean to interact with it. In general, the quicker the player can interact the better the interface, but this should not be limiting.
    This role relies on the use of objects provided by the Protocol Layer and the AI components, and there should be no other needs to achieve it correctly.
  • Providing customization items, elements to interact with game configuration or other players, or any other mean of interaction which is out of scope of the game. This role could optionally make use of other modules, like a direct connection on the Transport Layer. Since it brings nothing in direct relation with the game, it doesn't have to be described here.

This document does not enforce the way the main program is written and how these components interact, other than said above. For example, the choice of an interface or of an AI can be implemented in many ways and limiting this is not in the scope of this blueprint.

Further evolutions

The rewriting exposed here remains opened enough to authorize further add-ons or minor break ups. For example, allowing the user to tweak the game rules could be achieved in (at least) two ways:

  • Breaking up the Game Core component to create a special module for rules management.
  • Upgrading the protocol to communicate options to the game referee.

Actually, the correct solution probably lies somewhere between both of these approaches, and may require minor modification to the protocol, the game core, obviously the UI and perhaps other components.

This document implies no choice for the future, but only tries to narrow well defined components that communicate well with each other, and that can be tailored easily individually or together for further features.


duo is now a package which provides sub-packages or modules for the components identified above.


duo.referee contains the Referee class and supporting tools, like the rules definition. The game module provides additional tools like the game and cards abstraction.

duo.protocol is the implementation of the 'Protocol Layer component, which provides especially the ProtocolAdapter class.


duo.ai contains the AI stuff. All coded behaviours inherit duo.ai.AbstractAI which provides the interface to the other components as well as all the callbacks useful for artificial player programming.

duo.transport contains the Transport Layer implementations. Main interaction with the upper layer of the protocol is achieved through duo.transport.Endpoint and duo.transport.Context. Transport implementations shall redefine Endpoint to access network or any other mean to communicate.

At last, duo.ui contains UI implementations.


This space is for User-contributed commentary and notes. Please include your name and a date (eg 2008-12-19) along with your comment.

Powered by PmWiki