New PBEM

I’ve been hacking away at a part-time project for the last few days. It’s an implementation of a tabletop game we used to play as teenagers called Armageddon (aka Das Ewige Spiel). It probably needs to be adapted a little for PBEM play.

The idea is to make a PBEM version of it, and try to come up with some new programming techniques if I can. Also, I’m using boost a lot more than I usually would, and dipping into more of their libraries.

The game will have a separate server and client, which exchange their data as xml files (orders going one way, a status report going the other way). I currently have no plans for the client (I write input files by hand), except that I want it to either be portable (Java or C++ with a portable graphics library) or a web interface, which would make it a web game rather than a PBEM. Or all of the above.

The server is written in C++, with libxml2, boost and luabind. The latter is mostly used for setting up the game and modifying the game state – I like having scriptable access to the game world, and I’ve had very positive experiences with lua for Eressea.

Currently, the server knows factions, simple units, regions (but no terrain or levels) and has two commands: one to move a unit and one to swap two units’ places. It can save and load the gameworld, and read orders from an XML file as well as write a simple XML report. That does not sound like a lot, but I’ve built the foundation on which I can build to add more features fast. My short-term TODO list contains terrain types (especially ocean), terrain levels, buildings, more unit types and recruitment/construction orders. It all depends on the weather this weekend, I’d say.

I’ll try to keep track of my progress and the stuff I learn on the blog, if I have the patience for it.

Eressea und luabind

Für die neue Vinyambar-Partie habe ich mir den Spaß gemacht, Lua-bindings für Eresseas wichtigste Funktionen zu machen. Das bedeutet, ass man jetzt den Server aus lua heraus skripten kann. Der Server ist in dem Sinne nicht mal mehr strikt ein Server, er kann auch für programmatische Änderungen am Datenfile benutzt werden. Das ist cool, und sieht z.B. so aus:

function process(infile, outfile, orders) if read_game(infile)~=0 then print("could not read game") return -1 end read_orders(orders) process_orders() write_passwords() write_reports() if write_game(outfile)~=0 then print("could not write game") return -1 end end

Das ist eine normale Auswertung: Datenfile laden, Befehle lesen, Befehle abarbeiten, Passworte schreiben, Reports schreiben, Datenfile wieder speichern.

Für WdW müssen wir haufenweise Parteien in Allianzen einordnen, Aussetzen, und eine Menge Einheiten mit Startitems für jede der Parteien machen. Da die Daten dafür in der Datenbank stecken, generiere ich mir einfach ein kleines lua-skript daraus:

alliance = add_alliance(13, "Einwohner von Lummerland") position = get_position(13) faction = make_faction(position, alliance, 5, "bla@fasel.de", "Dämonen") ... for faction in factions() do local u = add_unit(faction, position) u:set_skill("magic", 3) u:add_item("money", 1000) end

Das ist nur beispielhaft, das wirkliche Skript ist 200 Zeilen lang.

Das schöne ist, sowas kann ich beliebig weitertreiben. Ich brauche eine Datei, in der der aktuelle Spielstand steht? Kein Problem, einfach eine lua-funktion gemacht, die den in eine Datei rausschriebt.

Das gute daran ist, dass man verschiedene Skripte für verschiedene Vinyambars (oder Eressea) benutzen kann, aber alles den gleichen Server benutzt. Der spielbezogene Teil muss nicht neu kompiliert werden, weil die Skripte zur Laufzeit interpretiert werden.

Das ist toll. Ich kann jedem, der ein eigenes PBEM schreibt, nur empfehlen sich einer Skriptsprache zu bedienen, zumindest um die Kern-Funktionen seines Programmes steuern zu können.

Als Tool benutze ich dazu [url=http://luabind.sf.net]luabind[/url], das erlaubt es sehr einfach, C und C++ Code nach lua zu binden. Dafür ist der ganze Eressea-Server jetzt C++-verträglich geworden (schon vor einer Weile). Der luabind-code sieht in etwa so aus:

void bind_region(lua_State * L) { module(L)[ def("regions", &get_regions, return_stl_iterator), def("get_region", &findregion), class_<struct region>("region") .property("name", &region_getname, &region_setname) .property("info", &region_getinfo, &region_setinfo) .property("terrain", &region_getterrain) .def_readonly("x", &region::x) .def_readonly("y", &region::y) .def_readwrite("age", &region::age) .property("units", &region_units, return_stl_iterator) .property("buildings", &region_buildings, return_stl_iterator) .property("ships", &region_ships, return_stl_iterator) ]; }

Ja, das ist [b]wirklich[/b] reines C++, auch wenn es nicht so ausschaut. Habe ich auch erst nicht glauben können 🙂

lua bindings for eressea

I’ve always wanted to have a scripting language in Eressea, for all kinds of reasons. The GM tool could really do with a console, for example. And monsters could be scripted without having to change the C code every time. Eressea is really pretty backwards in terms of technology.

So today, I made the old C code C++-clean (added a lot of extern “C” around them), and made lua bindings with luabind and I’m exposing a subset of the region and unit classes to lua. First script (apart from Hello world) listed all the regions by name and coordinates, it’s not much, but it’s a start.

It was actually easier to write small C++ wrapper functions (especially a wrapper template for the Eressea linked lists) and then use luabind (which is a C++ library) than to export the C structures directly though lua’s API. I really like luabind. I found 2 small bugs while I was working on this, but if they haven’t been fixed already, I’m sure they will be soon. The iterator support is rather fresh, after all.