Building the maps for Regicide Rumble 3

Last weekend, Regicide Rumble 3 happened. Regicide Rumble 3 (abbreviated RR3) was an Age of Empires 2 event organized and casted by T90Official on Twitch that had players of different skill levels compete for some prize money over three days in Regicide games1 of Age of Empires 2.

In this blog post, we will not focus too much on the (amazing) event, but on how we built the maps that have been used in that event.

The Task

About one month ago T90Official gathered a bunch of channel moderators and map makers and laid out his plans for the event: There should be multiple games over three days on different maps. Since the focus should be on Regicide, anything that makes sniping Kings easier should be done. That included removing HP bonuses and technologies for buildings that could protect the King, as well as disabling alternative win conditions like Relic or Wonder victory.

In the Regicide Rumble 1 and 2 events, there have been matches that took multiple hours to finish and that blew up the planned schedule for the games. To prevent this from happening again this time, a weakened version of a Battle Royale storm should push out players from the edges of the maps towards the center after a certain amount of time.

Battle Royale in Age of Empires 2 is not a novel idea, a few maps have been created already (mainly by HenkDeSuperNerd) that contain an area effect which damages units and buildings and grows over time, forcing players towards the middle of the map. We will not go into the details of the actual mechanism that creates the “storm” in this article – the relavant part is that the mechanic is based on chains of decaying animals which are placed around the edges of the map. Once the initial animal fully decays, it spawns a loop of other units that repeatedly cause blast damage to an area around them. Having all the edges full of these animals with different decay times creates “storm zones” that get activated one after another.

Slide 1
You can clearly see the storm zones in this screenshot of the Battle Royale Land Nomad map.

Those existing Battle Royale map scripts are highly specialized and a lot of work went into their creation. Creating and testing ten new map scripts with a similar but weaker version of the storm within a month and out of thin air2 would be totally unfeasible, as much was clear from the beginning.

Now we had to decide between two alternatives: Create a generic snippet that we can add to an existing random map script which turns it into a Battle Royale like map (with our custom weak storm). Or create ZR maps and place the animals that spawn the storm directly in the scenario file.

Excursus: ZR maps

Regular random map scripts are just text – in a strange markup format, yes, but still just text. They define everything about how the map shall look in vague generic terms. Their goal is to procedurally generate maps that look similar, but not the same.

ZR maps are different: They usually contain a scenario file that exactly defines the positions of terrains, possibly some other objects, and the starting positions of players, and a slimmed down random map script that defines all the rest in the usual vague terms, bringing variation onto the scenario. Unlike in regular scenarios, Triggers are ignored in ZR maps, so we can’t do shenanigans with those unfortunately.

Automation Is King3

The first option we had was tempting: The grandmaster of Age of Empires 2 Battle Royale maps, HenkDeSuperNerd, already had a snippet ready that could supposedly add the Battle Royale ring of decaying animals around any map. It was largely untested though and the effects it could have on the map generation were not investigated yet.

In contrast, the mechanics of ZR maps are well understood and controllable. For this reason, we went with the second option, which seemed to be the safer one regarding the time frame of less than a month.

Our process looked as follows:

  1. Select maps
  2. Adapt maps (like removing some spawn conditions for certain resources or removing animals)
  3. Add features: Custom regicide, Nerfs (for defensive buildings and civilisations), Storm constants
  4. Split script into Scenario and RMS part (one script to generate the scenario file from, one script to put into the final ZR map)
  5. Generate scenario file
  6. Add storm to scenario
  7. Create ZR map from scenario and RMS part

Having to do that for ten or more maps is tedious work. Also, at the time we did not even know which maps would be selected in the end. Without automation, that would have been a few unhappy hours of monotonous error-prone work for a few of us. And if we wanted to change something, we would have to do many of the steps again.

We had to change a lot of things. More on that in a bit.

Going through the above steps with each new iteration would have been an absolute pain. Luckily, we were able to automate some steps:

Building the maps for Regicide Rumble 3
M: manual work, A: automatable

I created a python script that automatically patched the code for our desired custom features into the maps that we had selected and adapted manually beforehand. The script also separated the sections of the rms that were needed for the scenario generation from the sections that were to be put into the ZR map.

The scenario generation had to be done by hand unfortunately. Since the scenario files are static and we desire fair starting positions for all players, a manual review would be needed anyway before continuing. Luckily, the rms part for generating scenarios does usually not change at all while testing custom map features, so we could generate those once and then use them again and again in the final steps.

Adding the storm spawners to the scenarios was a bit tricky. Our first approach was to manually “paint” a zone of terrain around the generated scenarios on which the map script would then place the storm spawners, like it is done in the existing Battle Royale maps. That would have meant monotonous repetetive work.

Luckily though, we had a breakthrough after a few days: I was able to use the agescx python library to modify the generated scenario programmatically! What would have taken at least multiple minutes per map before was now a matter of seconds. And not only that: We were suddenly able to place arbitrary objects at arbitrary positions on the map. Something that can hardly be achieved in random map scripts alone. We basically had full control. I wrote a second python script that created copies of our scenarios and modified them to our specifications. Mainly: placing the storm spawners precisely at the edges, with a specific distance to each other.

The last part, combining the scenario and the RMS file, is also easily automated, since ZR maps are just zip files without compression that contain the scenario file and the rms file.

We finally had a semi-automated pipeline in which we could tweak a script and and produce 17 new versions of our maps within seconds. Now it was just a matter of making it all work.

It Would Be A Lot Of Fun, Were It Not For The Players

During testing on community games friday, we found out that the features we initially used had some issues. For example we tried to disable Relic victory by spawning in the Relics after the game start, by placing Priests with 0 HP that hold a relic. When the priest dies (which he does immediately), he drops the relic, and it looks like it has been there all along. Turns out that Burmese can see the locations of the relics on the map, and they converted the dead priests while they died. Due to a bug in the game, this led to the dead priests taking up population space for the Burmese player, who had to build a few extra houses at the start of the game in order to produce own units. A similar thing happened when the storm was active and players converted some of the Gaia units on the edge which we used to deal the damage. The dead units took up population space, and CaptureAge showed us the discrepancy between units and used up population space clear as day, making us wonder if we were suddenly unable to do simple maths.

The relic issue was simply fixed by disabling Relic victory in a differenty way: By just placing 504 relics into an inaccessible corner. Can’t get all relics if you can’t get to all relics! The storm however we had to revamp multiple times until we had a conversion resistant version that worked reliably.

Tweaks, Tweaks, Tweaks

To understand why the final maps look like they look, we have to dive into the issues we had along the way. Our biggest concern has always been players messing with the storm mechanic. They could disable or speed up storm spawners, intentionally or unintentionally, or break a whole lot of other things. So we put a ring on it. Or rather around it. To prevent players from accessing the storm spawners with units.

Building the maps for Regicide Rumble 3
An early iteration. The jesus deer are storm spawners, the rocks prevent players from accessing the deer.

The first iteration of our storm had six waves, but did unfortunately not reliably damage units. So we switched up the storm units a bit and got it to do damage reliably, but only with three waves.

This also brought a new issue: Players were suddenly able to convert one of the gaia towers (wtf) used in the storm cycle. This led to deforestation on the map and annoying “Tower built!” noises and chat spam, making it impossible for the unfortunate player to read chat messages from the other players. That would be deadly in a game mode where communication with the players to plot against others is essential for success.

Our first attempt to solve this new issue was to move the barrier further away from the storm spawners, so that players could not get close enough to convert them anymore. Taking away more space from the already crammed map would shrink it way to much, so instead we increased the map size by ten tiles in each direction and moved the storm spawners outwards, effectively turning a “Large”map (220×220 tiles) into a “Giant” map (240×240 tiles). The resulting empty space was filled with deep water (to prevent resources like gold, stone, wood, or relics from spawning there) and stone heads on top (just for looks). I also had to fix “holes” in the map that resulted from moving the whole map down and to the right by ten tiles after increasing the map size. Looking at those “holes” for more than one second would reliably crash the game – not a good thing in general, and especially if you want to stream to an audience of 2000+ people around the world. The fix led to hills in the water, but it worked. Good enough for me!

Building the maps for Regicide Rumble 3
The water has hills, but at least the hills don’t have eyes.
The flying panthers are part of the storm spawners.

Now that we had that “dead space” around the outside, we could also have some fun with it, and write the name of the event with haystacks or something silly like that. We also placed three rings of torches on the map that indicated how far each “storm wave” would reach, since the storm currently lacks a visual indicator (apart from slowly killing units I guess).

Sadly, ten tiles is not enough to prevent for example a Cannon Galleon with a line of sight of 15 or a Trebuchet with a line of sight of 18 from converting those damn towers. In the end, we managed to fix the issue by replacing the bear in the damage cycle with a macaw. Nobody knows exactly why that worked, but it worked! Good enough for me.

The last week before the event was spent fixing small issues in the map scripts (our step 2), like resources not spawning in the center island on Migration, and adding a large patch of wood in the center of the scenario files of Grand Bara, Chaos Pit, Steppe, and King of Kings, to prevent players from running out of wood if the game goes long. We even managed to fit Pilgrims with a custom storm layout that only storms from two of the four sides, and has storm spawners on the eight starting islands in the corner of the map.

The morning before the start of the event, somebody noticed that players start with five out of five population after we had removed the spawns of extra villagers and houses the night before. This meant that players cannot start creating villagers right away, but would have to build a house first – a big deviation from the usual build order at the start of the game. That issue could luckily be fixed manually by replacing the scout with a horse, which does not take up population space, bringing it down to four out of five with room for one more. That was a (preventable) close call, but it worked out in the end.

Thank You

Before we go into what could be done better I would like to thank the whole team of Regicide Rumble 3. It was a pleasure working with so many motivated people of different skill levels across time zones. It’s quite funny when you wake up at eight in the morning to a new storm mechanic suggestion and reply with “I will try that out after work in about 10-12 hours, thanks”. Together, we did things I think had never been done before. Certainly, somebody will prove me wrong about that in the comments.

Light And Shadow

I used a git repository on GitHub for managing the scripts that were used. Sadly, not many in the map making community are proficient with git, so we could not use that directly to collaborate. Also, the python scripts were probably not usable for non-programmers. Making the whole process more accessible for non-programmers would be desirable.

During the whole time, I was the only one to have access to the unpatched scenario files since they were in the non-versioned output folder. That turned out to bite us when we added the clumps of wood in the centers of some scenario files. Motivated team members edited what they had access to – the patched scenario files from the ZR maps. Those were then not suitable to use in the pipeline because they already contained the storm spawners and torches. The work and had to be redone with the plain scenario files. The unpatched scenarios should definitely have been versioned and published in the git repository.

Also, due to my shallow understanding of what to look for when generating the scenario files, some maps had generations that were let’s say not ideal in the end.

Finally, it would probably have been sufficient to only place the storm spawners and torches in the scenario files, since we got the storm pretty tamper-proof. No stone barriers needed, no extra large maps with pixelated text on the border necessary.

You live and you learn. The Kings are dead, long live the Snipers!

  1. Regicide is the game mode where you lose the game if your King unit dies. See also.
  2. not thin air exactly, since the base scripts are there already, but still a lot of work to be done
  3. An obvious pun to make when writing about Regicide.
  4. In this case, 50 was an arbitrarily selected “high enough” number.

How to compile the Advanced Genie Editor on Linux (Ubuntu 18.04)

The Advanced Genie Editor is an excellent software to inspect and modify the core game files of games that use the Genie format – that includes Age of Empires II in particular. It is written in C++ and licensed under an open source license1, which makes the whole thing twice as nice (the open source part, not the fact that it is written in C++).

While the Advanced Genie Editor is just available for download as a Windows executable, it can also be compiled and run on Linux systems.

As I happen to play my Age of Empires II on my Linux as well (using Wine/PlayOnLinux), this is what I desire, to be able to look up stuff easily when developing other Age of Empires II related tools.

Unfortunately, being rather inexperienced with the whole C++ build chain, I never really got it to compile. Which sucked, because I would either have to reboot into Windows or use my windows laptop next to my main PC to run the precompiled windows version. This also meant no copy-pasting.

But after some more hours of trial and error, I finally got it to work!

HowTo

On a freshly installed Ubuntu 18.04, run the following commands:

sudo apt install git build-essential cmake libwxgtk3.0-dev libboost-all-dev libsfml-dev
git clone https://github.com/Tapsa/AGE.git
cd AGE
mkdir extern
cd extern
git clone https://github.com/Tapsa/genieutils.git
git clone https://github.com/Tapsa/pcrio.git
cd ..
cp "Misc Files"/zlib.cpp extern/genieutils
cp /usr/share/SFML/cmake/Modules/FindSFML.cmake cmake/
mkdir build
cd build
cmake .. -DEXTERN_DIR=extern
make

The make step will take some time.

Finally, you will have an AdvancedGenieEditor3 executable in AGE/build/! Happy modding.

(You cannot change the (absolute) location of the AGE/build/extern/genieutils/libgenieutils.so library though. Otherwise, the program will not work anymore, as it will be unable to locate the library.)

  1. GPLv3

The Age of Empires II Technology Trees In Your Web Browser

Age of Empires II currently offers 31 unique civilization to play as. Compared to, for example, the three races that players can choose from in StarCraft 2, that might seem overwhelming at first. However, all Age of Empires II civilizations share a common pool of units, buildings and technologies, with only a few unique elements to each civilization. This lowers the bar for newer players significantly.

A civilization’s technology tree shows which units, buildings and technologies are available to that civilization in which age. This follows some general rules, like that mesoamerican civilizations do not have access to cavalry, and further civilization-specific rules that disable certain units and technologies for a civilization. Due to the common pool, all technology trees look similar, albeit not identical.

The Age of Empires II Technology Trees In Your Web Browser

The leftmost part of the Japanese technology tree

Sometimes, players wish to access the technology tree for one or more civilizations without having the game open, to see which units, buildings or technologies are available to a civilization.

Let’s build an online technology tree!

We start by analyzing the layout of the in-game technology tree:

  • There are eight rows, two per age.
  • Squares are connected  by exclusively horizontal and vertical lines.
  • Elements of one upgrade line are all within the same column.
  • Buildings are centered on their immediate unit and technology children.

Sounds doable!

Our next step is to collect all available building, unit and technology names. We devise a clever algorithm to recreate the desired layout that contains the data we collected before.

Next we notice that some civilizations have unique units, which move parts of the tree around when they are inserted.

Crestfallen, we exclaim “Oh no!” and scrap the idea of an accurate representation of the in-game tech tree, because while we are rather motivated, we are first and foremost lazy programmers.

Instead, we create a “master” technology tree which contains the elements of all technology trees in the game. Unfortunately, this means that it gets even wider than the original version(s). Also, some squares will be disabled for 30 out of 31 civilizations, but whatever. At this point, we don’t care.

Speaking of disabling: We add a the functionality to display big red crosses when an item is disabled. Hereafter, we spend two hours scrolling through the tech tree of every civilization and adding the information which buildings, units and technologies are disabled to our application.

As a finishing touch, we add all the icons, and we are basically done!

The Age of Empires II Technology Trees In Your Web Browser

Add dank memes to your blog posts to boost your reach among adolescent audiences.

We present: A bland online version of the Age of Empires II technology tree. In your browser, even kind of mobile-friendly, MIT-Licensed (except the icons).

Unfortunately this version is currently without the civilization bonuses that are usually displayed below the civilization selection box, as we could also not be bothered to manually type them all. Fixed! omg