GGZ: Writing KDE game modules


Josef Spillner <dr_maux@users.sourceforge.net>, May 2001


Please note that this is only an alpha-version, released due to some

discussion on kde-games-devel. The "real" one with coding examples and

library documentation, in HTML format, will come around June 8, 2001.


- Introduction -

Right now we have 13 game types available for GGZ; some of them come with

different frontends, that makes a total of around 20 games. The game clients

are compatible to each other if they use the same server, which is currently

the case for all of them. There could, however, be different implementations

even on the server side - for example, two different card games which deal with

the same game type like Spades or Skat.

The first game I wrote was Hastings1066, just to get into the feeling on how to

write a GGZ game. At this time (...the good old times :)) everything was coded

byte by byte, there were only plans for game module support via libraries.

Soon after I realized that the whole project would benefit from not only having

Gtk+ games but also KDE ones. This is how it all started (must have been around

October 2000 or so).

- The KDE games within GGZ -

Apart from KGGZ (the Core Client used to launch games) my other primary task

was to port at least some games to KDE, or invent new ones. Ismael Orenstein,

author of GGZ-KReversi, was faster than me and placed his game in CVS first.

He has used KDE Studio to achieve a port of the user interface, and a C++

protocol class (reversiprotocol.cpp) which uses a list of opcodes and data for

communication with the server. The data exchange itself is typically handled with

a QSocketNotifier, which is currently used in all of our KDE games.

Both KTicTacTux and KDots use a similar technique, albeit there are some

differences in their proto objects.

Finally, there is Krosswater (ported from the Java game Crosswater), which uses

the MindX Zone library, which exists as ZoneServer and ZoneClient classes.

Unfortunately this isn't ready yet, but it will be for 0.0.5. (Right now there

is a lot of C code used in C++ wrapper classes.)

This gives a total amount of 4 KDE games, and that's a good start for this

release. In order to keep balance between the widget sets there is still need

for more KDE games. To avoid unnecessary duplicate work, the best choice are

always new game types.

- How to start -

A GGZ KDE game is basically a normal KApplication which should have a menu bar

and a status bar - displaying the status is essential in turn-based games to

avoid unnecessary server error messages if it's not the player's turn, for


The main view consists of the game board (in case it's a board game), or

whatever is appropriate for this type of game. Ideally it provides some Qt

signals which are emitted whenever the player does an action, and some slots in

case there is network input from other players or the server-side AI. If the

game is intended to run both stand-alone and as a GGZ game module (for which a

standard command line option named --ggz exists), it is possible to have

client-side AI as well. This has for example been implemented in KTicTacTux,

and as it shows up some more issues I'll give a further explanation later in

this document.

The KApplication needs to be fed with command line arguments (use KCmdLine for

that purpose). That is:

-ggz (optionally; used to indicate a difference between direct and core

client launch)

-o (historycally; some old games need this and the KApplication would

refuse to start otherwise if it receives this flag from the GGZ Core Client)

- Connecting to the server -

On startup, the connection must be established. The method doing this isn't

that long, so I can include it here directly:

void CLASSNAME::connect()


char fd_name[64];

struct sockaddr_un addr;

sprintf(fd_name, "/tmp/GAMETYPENAME.%d", getpid());

if((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) exit(-1);

bzero(&addr, sizeof(addr));

addr.sun_family = AF_LOCAL;

strcpy(addr.sun_path, fd_name);

if(::connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) exit(-1);


Instead of quitting on connection failure you can of course provide a fallback

or just pop up a KMessageBox::information saying that there is something wrong,

e.g. the tmp/ directory is write-protected or another weird thing which might

have happened.

Please note that the given socket name must match the game type specified in

the game module description file (more on that later).

If the connection is established, the server will send you your seat number and

the seat assignments. For example, if you decided to play a Monopoly game (which

has a maximum of 8 players) with 4 players only, where 2 of them are AI's and

the third one is open for another real player to join, you'll get the following


(int) seat number = 0

(int) seat 0 assignment = PLAYER

(char) player 0 name = Hans

(int) seat 1 assignment = BOT

(char) player 1 name = bot

(int) seat 2 assignment = BOT

(char) player 2 name = bot

(int) seat 3 assignment = OPEN

Bots are typically named "bot", and open seats don't contain any name. The

function reading this information must be called whenever there are seat

updates (players joining and leaving), so make sure you don't mess up anything.

As an example, if in the above case the player Rudi joins the open seat, Hans

gets the information updated:


(int) seat 3 assignment = PLAYER

(char) player 3 name = Rudi

And Rudi gets the same one too, except his seat number is 3.

The game client is responsible to indicate that the game starts. This can be

done by checking the number of open seats. If none are open, it's the turn of

the player (or bot) at seat 0, displayed (if player) on the status bar with a

message like "Game started, please do your move", whereas all other player

should read something like "Waiting for opponent".

- Game play -

In the shown case of turn-based games, whenever the active player is ready with

his move, the result must be sent to the server. The GGZ standard way of doing

so is using the easysocket library for writing/reading the socket, but it can

be done with the Qt library functions as well. However, when using easysock,

you're not on the wrong side, as issues like IPv6, UDP and optimized support

for real time games are already in progress, mostly available as patches.

If the move is accepted by the server, it sends out the results to all players,

and requests the next move from the player who's turn is next. If the game is

over, the results are broadcasted as well, typically this message does only

contain the winner's seat number to save band-width.

That's it. Easy, isn't it? The whole behaviour can be fine-tuned by changing

the implementation of the game servers (which are always launched by the GGZ

Gaming Zone server, ggzd).

- Hints, options, pitfalls -

I have left open the discussion on two topics until now:

First: If any game is also playable without GGZ, it might have to show a

different behaviour depending on how it is launched. If a game is designed to

quit after the server says so, it shouldn't quit in single-player mode, but

instead show a dialog box asking for another game or something. This should in

this case of course be avoided when playing over GGZ as the dialog box would

disappear with the game itself on exit, and this gives an ugly visual effect.

Second: Every game module must provide accurate information about itself during

the installation process. This is done by providing a module.dsc.in file, which

is then transformed into a module.dsc file by autoconf, and installed by

ggz-config. There is a special file (named acinclude.ggz) for that purpose

available within the GGZ kde-games module. Please look at the existing games on

how to include standard command line options.

Josef Spillner


The MindX Open Source Project - Relieving the world from proprietary games


The GGZ Gaming Zone - Open Source Online Gaming


The KDE Project - The most powerful Desktop available world-wide