Nametags for NAC3

The year 2020 started with a bang: Nili’s Apartment Cup 3 (NAC3) was the first major Age of Empires 2 tournament that was played on the new Definitive Edition, with a prize pool of over 30.000 dollars. It took place over the second week of January in Nili‘s apartment (hence the name) in Hamburg.

The weekend of the finals was to be accompanied by a public viewing event at a location in Hamburg. There was also a meet and greet event for the community, players, and casters on saturday evening at said location.

Community meetups are a great way to assign real faces to the names you meet online in Twitch chats and Discord servers. I am regularly astonished by the huge amount of good-looking people in the Age of Empires 2 community. From the way they act online, you would expect a horde of literal trolls to show up. But no!

In order to facilitate matching names to faces, I offered to provide nametags for everyone attending. The technical setup for this was rather simple: I borrowed a Dymo-450 label printer from my mother1, ordered some rolls of sticky labels on the internet, and brought my laptop to connect to the printer and print the labels from it.

My main concern was to avoid long wait times for people longing for nametags. The location was open to the public with no entry fee and no pre-registration required, so we did not know how many people would attend the event in the end. From the activity in the dedicated meet and greet Discord server I expected a few hundred people to show up at least.

The absolute worst-case scenario that I calculated with would have been around a hundred people showing up at the same time, right as the printer breaks down. Such a situation should be handled as smoothly as possible.

In case the printer decided to refuse further printing, I brought ten felt markers with which people would have been able to write their names onto the printer labels by hand. It would not have been as pretty, but the main goal of the nametags, telling people who you are without having to spell out your name all night long, would still be achieved. Problem solved!

Avoiding long queues while still printing beautiful name tags required a bit more preparation. We decided on a label design which included the name in bold at the top, a set of spoken languages in smaller print below (so you could decide in which language to address a person), a tagline in italics, also in small print, below that, which you could use to tell everyone your favourite joke or whatever you liked (as long as it still fit on the label), and finally a small bootleg NAC3 logo at the bottom right.

Nametags for NAC3
A sample nametag.

The absolute minimal amount of time needed to create one label is the time it takes to print and tear the label, which is about five seconds.
The things that take significantly longer are:

  • Having people think of a name they want to wear
  • Having people remember all the languages they can speak
  • Having people decide on a funny tagline (or decide they don’t want one)
  • Explaining to people all the textual elements of the nametag
  • Waiting for people to type everything into the computer to create the label

As you can easily see, people are the main issue. As usual.

A few points made my job easier on the technical level:

  • Using a library provided by, we can take inputs from a html form and create a pdf file
  • Modern web browsers allow embedding pdf files in websites
  • Modern web browsers allow printing those embedded pdf files directly from the browser
  • You can print pdf files in the right format on the label printer, so I did not have to use dedicated label printing software

So I created just that: A html page where you can input your username, languages and tagline into a form. The page then creates a nametag pdf file that you can directly print if you have the right printer. Which I coincidentally2 had!

Not all usernames are equal though: Some are longer than others. Which makes them break onto two lines, and suddenly all that text on your nametag does not fit onto one single label anymore.

Nametags for NAC3
Poor platypus: One character too much! The little logo has been pushed down even further.

So I added an option to adjust the name’s text size. Easy fix!

Nametags for NAC3

One 1,80 m tall participant3 informed me that he mistook the “Size” input for a prompt to input the body height in centimeters. An interesting interpretation that I did not think of before. Remember, kids: Always label your input fields precisely!

Now on to the people issues we noticed earlier.

If we had a way to let people fill out the form somewhere else – at home, on a train, on the loo – and could just load them up and print them directly, that would solve all of our time problems.

In order to achieve this I wrote a small php script that did nothing else than take a json representation of a person’s nametag, generate a random five-digit number, store the json in a file with that number as the filename, and return the number. I also added a Save button to the html page that collected the data from the form, sent it to the php script, and displayed the number that it got as a response.

The second part was an input field where I could enter such a number and it would load the stored nametag information and put it back into the form fields and generate the nametag.

Aaaand we are basically done! Just get all the people to create their nametags in advance and write down their number, and I could use that number at the location to print their personal nametag. People could even just create another one and write down the new number if they wanted to change something.

Ok, maybe we are not done yet. Have you ever tried to make hundreds of people do what you want them to do?

I tried my best at least. I added the instructions at the top of the page. Tried to formulate them as simple and clear as possible. Then I put the thing online and advertised it in the meet and greet discord server multiple times.

And it kind of worked: We ended up with around 170 preconfigured nametags (some of which were duplicates).

There were obviously going to be people at the meetup who did not configure their nametag in advance. Still fearful of long queues, I decided they would be asked to fill out the form on their mobile device at the location and could then print it with the code they would get. The little issue with that: The location did not provide wifi. This means I could only ask that from people from the EU who have data roaming on their mobile devices. Luckily, the majority of attendees would match that criterion. In order to get their nametag data from the server I would have to get my laptop connected to the internet somehow as well. Opening a wifi hotspot on my mobile phone turned out to be sufficient for that task. Otherwise we would really have had to ask people to type their stuff directly on the laptop, since I would have had no way to get their nametag from the internet onto the label printer.

Days of truth

I arrived early at the public viewing location and successfully managed to procure a table for my setup pretty quickly. The internet connection for my laptop via wifi hotspot from my phone worked flawlessly.

Nametags for NAC3
The nametag printing station.

The longest queue I remember was maybe five to six people, and it was less a queue and more a group of friends getting their nametag printed one after the other.

Amazingly, most people had a number ready for me. It turned out I should have made that thing not just a javascript alert();, but actually a bit bigger. It was hard to read those tiny numbers on various variants of screenshots that people showed me. But those Age of Empires 2 fans seem to be a well organised bunch!

The people who did not have a number for me usually just ended up filling out the form on my laptop directly, since there was basically never a rush. This went against all of my concerns for which I planned, but I guess just being afraid of a horde of angry people is in this case better than actually being run over by a horde of angry people.

The biggest issue turned out to be the printer. Sometimes it was a little bit too generous, and did not only spit out one label, but then another blank label, and another blank label, and then another blank half label. Which is a bit annoying when you’re trying to run a free printed label business. Customers do not want their printing be distributed over two labels! So I spent a lot of time trying to fix the printer.

In the end I feeded it the single blank labels from previous “misprints”, which worked fine I guess. But in general you want a printer that prints just what you tell it to print. Dymo 450, you let me down.

And the people? They were happy with the nametags. Many told me it was a “cool idea” and thanked me for doing it. Which is all that counts, really ❤

The whole nametag website thing is free to re-use and can be found over on GitHub.

  1. Shoutout to my mother! Without her, this would not have been possible!
  2. Very coincidence. Much wow.
  3. No, I did not verify that information. But you thought I did, didn’t you.

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.

ESC-Plotmania 2019

Die finalen Punkte des Eurovision Song Contest 2019 sind da, und meine Plotgenerierskripte funktionieren noch. Hurra! Nachdem ich also wieder einmal zahlreiche Tabellen von Hand von der Eurovision-Webseite kopiert habe, können wir auf farbenfrohe Resultate blicken, von denen ich die interessantesten vorstellen werde.

Wer hat eigentlich gewonnen?

ESC-Plotmania 2019
Ach Gottchen.

Wenn das letztes Jahr schon eine “bloody mess” war, dann ist das diesjährige Ergebnis wohl “fine“. Der mit den meisten Publikumspunkten bedachte Joik-Beitrag aus Norwegen hat nur relativ wenige Jurypunkte bekommen und wurde somit seines Sieges beraubt. Auch bei einigen anderen Beiträgen gehen die Meinungen offenbar auseinander.

Die Niederlande sind übrigens die einzigen Lande1 im Finale, die von allen anderen Ländern Punkte bekommen haben.

ESC-Plotmania 2019

Doch was interessieren uns die Gewinner, eigentlich sind wir doch für die unteren Punkteränge hier. Die sind auch viel übersichtlicher. Nehmen wir zum Beispiel San Marino, Spanien und das Vereinigte Königreich im Finale:

Kein Land hat diesen Beiträgen sowohl Jury- als auch Publikumspunkte gegeben. Da gehen die Geschmäcker von “Fach”-Jury und Publikum offenbar stark auseinander.

Wunderbar ergänzen sich hingegen Deutschland und Israel:

Apropos ergänzen: Auch die Publikumspunkte Deutschland im Finale und Österreich im zweiten Halbfinale geben ein nettes Pärchen ab:

Doch wie knapp war es? Blicken wir unter die magische Linie zwischen dem 10. und dem 11. Rang, ab der es Punkte gibt.

Die Schweiz! Nur ein Rang besser, und Deutschland hätte im Finale einen Publikumspunkt bekommen. Die übrigen Länder waren sich einig: Keine Punkte für die S!sters.

Auch für Österreich im zweiten Halbfinale hätte die Schweiz es richten können, hier hätte das Publikum Österreich aber schon zwei Ränge besser voten müssen. Schad.

Jede Länderjury stimmt für einige Länder zweimal ab: Einmal im Halbfinale, für das sie stimmberechtigt ist, und dann nochmal im Finale. Für jedes Jurymitglied können wir nun vergleichen, wie sich die Bewertung der zweimal bewerteten Beiträge vom Halbfinale zum Finale ändert.

Hier gibt es dieses Jahr eine kleine Überraschung: Ich konnte kein Jurymitglied finden, das die persönliche Sortierung der Beiträge zwischen Halbfinale und Finale nicht verändert hätte. Die Performance scheint doch einen Unterschied zu machen. Oder die Gedächtnisse sind schlechter geworden.

Man kann auch gut ablesen, wie sich die Bewertung eines Beitrags durch die Jurys zwischen Halbfinale und Finale verändert hat. Slowenien zum Beispiel – ein Song, den man offenbar zweimal sehen muss:

ESC-Plotmania 2019
Sehr linkslastig, also viele Verbesserungen im Ranking

San-Marino-Serhat hingegen fiel in der Gunst der Jurys, obwohl er im Finale besser gesungen hat als im Halbfinale:

ESC-Plotmania 2019
Sehr rechtslastig, also viele Verschlechterungen im Ranking

Doch halt. Was war denn da in Montenegro los? Waren die zu blöd zum Abstimmen? Zum Vergleich:

ESC-Plotmania 2019
Bewertung der Jury aus Montenegro im Halbfinale. Viele vordere Ränge.
ESC-Plotmania 2019
Bewertung der Jury aus Montenegro im Finale. Viermal auf dem letzten Rang. WTF?

Haben die Serhat auf dem Gang getroffen und er hat sie beleidigt oder was?

Alle alle Plots gibt es wie üblich zum Download:

Viel Spaß!

  1. Badumm-tss.