--------------------------------------------------------
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
example.
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
results:
(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
dr_maux@users.sourceforge.net
The MindX Open Source Project -
Relieving the world from proprietary games
http://mindx.sourceforge.net
The GGZ Gaming Zone - Open Source
Online Gaming
http://ggz.sourceforge.net
The KDE Project - The most powerful
Desktop available world-wide
http://www.kde.org