Mediaeval: A developer diary.


No ROM battery
Some months ago I discussed on these forums the possibility of developing a strategy game. Well, that time has come. For a little over a month I've been developing Mediaeval, a multiplayer-only grand strategy game where each player takes control of a nation and tries to see it through.

This thread will serve as a developer diary of all efforts going into the development of this project. Let's start:

Project Name

A multiplayer grand strategy game paying an homage to old PBeM games.

Players take control of one of over 100 nations in a medieval-like scenery. They manage the nation production, population/clergy/nobility satisfaction levels, armies and fleet, diplomacy. Nations don't all start equal. They all start the game in pre-define arrangement of Empires, Kingdoms, Duchies, Counties, and Independent nations. Some players will be independent, some will be vassals of others, some will be lords of others. Nations power may or may not be related to this arrangement. But they will all have different power levels and players do not start the game on equal footing.

None in sight. Play the game. While it will be impossible the win the game (there aren't winning conditions, neither it will ever be possible for anyone to take over the world), there will be the possibility of losing the game by being removed of it through either conquest or internal revolt. Essentially players will want to concentrate on becoming more powerful and respected. Or maybe not. Some may be just happy about going with the flow.

- Play By Email emulation
- Game client
- Over 100 nations
- 4 different races: Humans, Elves, Dwarves, Orcs
- 3 different government types: Empire, Feudal, Barbarian
- Complex Diplomacy options and free diplomacy
- Religion
- World and Local economy
- Armies and fleets.
- Tons of statistical data and nations ranks

Programmed in C# against WPF and XNA.
Ports: Windows, Linux


No ROM battery
For the past month I've been working on the game map editor. An essential part of the backend of the game. Players won't use this, But I will, to set up new worlds.

Game Map Editor main window

Minimap detail. The minimap is automatically generated every time changes are made to the main map. This is made fast by making use of the WriteableBitmap class. What I do here is map hexagons to pixels. So one hexagon on the main map is 1 pixel on the minimap. This also gives me a scale ratio that I then use to enable minimap clicking. So, clicking on the minimap places scrolls the main map to the right position.

The main map is drawn by making use of Visuals.

internal sealed class DrawingMap : Canvas

DrawingMap is an heavily modified Canvas class that contains all the logic for the map drawing. That map contains around 18,000 visuals between the hexagons, grid, coastline and terrain features. Yet it takes just 2 seconds to render on a i5 3000 MHZ and GTX560 Ti. I should discuss this class in greater detail on later posts.

The map currently can be rotated, flipped, zoomed and hexagons can be selected.
Last edited:


Partition Master
Congratulations on taking the step Marfig. I myself have been on the edge of starting one myself but as all my little projects have proven. There is rarely the time to commit myself to actually starting it yet.


No ROM battery
Yeah. And the biggest hurdle isn't even starting. The greatest challenge is getting them finished. The barriers to staying motivated are many, when it comes to personal pet projects. Many extremely successful in-their-career developers and whom I admire greatly, nonetheless can't to be able to stay focused on a personal project for more than one month. It's almost ironic.

We shall see how this goes. There's no reason to believe it shouldn't come to an end. It's a very old desire of mine. It's around 20 years old.

However, I've been through many, many, failed attempts at taking a personal project from start to finish to know better. During that time I've learned a few tricks. Perhaps the most important one is to not cave in to sudden bursts of energy. That's the best way to burn out (coincidentally enough, was having this conversation with Rob just yesterday). Always stick to a work plan that gives room to do other things during the day and never allocated time units to your personal project that you wouldn't if this was your daily job.


No ROM battery
The actual map is saved to disk as a binary file in my own defined format. I decided not to use the .Net object serialization features because, quite frankly, it introduces a lot of bloat to the resulting binary file. I have no use for assembly and class descriptions and such. Once you go through the effort of creating the necessary code to persist objects to disk in your own chosen format, you'll appreciate the much more streamlined and smaller file size. Unless there's an heavy price to pay in terms of code maintenance I don't suggest anyone to make use of the serialization facilities under the System.IO namespace.

The map is saved, as I said, as a binary file. I defined its format as such:

The file has an header section that describes the map properties. Any textual data such as Map Name and Map Description is encoded as an UTF-7 string. I could have used null-terminated strings. But I prefer to take advantage of the already existing support for UTF-7 encoding in .Net. This is the header at the top of every map file:

struct FileHeader {
    byte AuthorSize;			      // size of the Author string
    char[AuthorSize] Author;                  // map Author
    byte NameSize;                            // size of the Name string
    char[NameSize] Name;                      // map Name
    byte DescriptionSize;		      // size of the description string
    char[DescriptionSize] Description;        // map Description
    uint RevisionMajor;                       // map version major
    uint RevisionMinor;                       // map version minor
    ubyte MapSizeX;                           // map horizontal size in hexagons
    ubyte MapSizeY;                           // map vertical size in hexagons
    ubyte[16] Hash;   			      // md5 hash of the map body

This format allows me to extract the header section from the file, knowing exactly its size. With it I can start the preliminary steps of loading the map into the editor, like setting up its name, or description. Likewise I can already start doing some basic file validation in an attempt to detect file corruption. For instance, I can compare the two map size values above against the map body section.

Before I discuss what's that md5 hash value is doing, let's first take a look at the map body.

The map body is a simple array of bytes describing every and each hexagon on the map. This is the map proper. It starts immediately after the 16-byte hash. I put the image below to help you see the format I chose to describe each hexagon:


As you can see, each hexagon takes 4 bytes to be fully described. With this I can store the maximum map size supported by the game (255 x 255, representing a total of 65,000 hexagons) in just 255 * 255 * 4 = 260100 bytes. Or ~254 Kb. That's a lean file size.

You may noticed that I don't do a detailed description of each hexagon. I don't define for instance what type of settlement it has, or if there is an army or fleet stationed there. The map simply describes immutable features of the landscape (players will be able to build roads, but they can never be destroyed and the game starts with a basic road network). All mutable data is going to be defined in the game database.

So, the md5 hash presented on the file header is in fact an hash of this entire body section. It is calculated every time the map is saved and stored in the file header section. When loading the map, I recalculate the hash and check it against the one in the file. If both are equal there's a very likely chance the map isn't corrupted. This allows me to save a lot of code logic during map loading trying to make sure the map is in the correct format.

Brett Thomas

Senior Editor
I'm greatly looking forward to following this, Mario. I've had my own game project sitting on the back burner for far too long, as a reason for me to get inspired enough to learn PyQT...