Empire of the Petri Dish – Post Mortem

Posted by
September 17th, 2012 9:22 pm

I’ve been waiting to post this until after judging was over so that I could post some hopefully interesting charts derived from my server’s access logs.

This was my fifth LD48 entry. I’ve entered every LD48 since LD20. I probably slacked off more this time then on previous ones, but that was largely intentional, as I tried to come up with a design simple enough that I didn’t have to rush too much. I think it worked out well, as I actually managed to add in music this time.

What Went Well


Since the game was implemented in HTML5, all resources were loaded on demand using separate HTTP requests. While this would slow it down for a big game, this one didn’t need too many assets. This also had the advantage that I see in my server access logs when a resource is loaded, like the win screen. See below.


Against my better judgement, I decided to use PlayN again even though last time I got burned when I discovered compatibility problems late in development. Specifically, I’d been testing using native Java, and when I switched over to HTML5 compilation I discovered that transformation matrices weren’t compatible with hardware accelerated WebGL at all, and I had to largely abandon the HTML5 version due to time.

This time, I carefully tested the HTML5 version before the very end, and I avoided transformation matrices altogether. The HTML5 version works as well as you could expect, even in IE9, although of course it is extremely slow compared to the native Java version.


Compared to my previous efforts, I think this one’s UI turned out fairly well. It has better highlighting and visual/audio cues as to what will happen if the user performs some action. I also mostly managed to keep it simple, and avoided huge help pages with dozens of controls (unlike some of my previous entries).


Ah, the most important thing, right? The way the bacterium’s genes work is this:

  • Each creature has a set number of arms (which is actually a floating point, however a creature with 2.3 arms will just have 2 for gameplay purposes).
  • Each creature has a genome, consisting of an arbitrary number of genes, each one representing one “segment” on its arms. Each gene has 5 attributes, each itself a floating point:
    • Length
    • Width
    • Type: A number, usually from 0 to 5. It is rounded to the nearest whole number, determining the piece type:
      • 0 (Or anything outside the range): Structure
      • 1: Engine
      • 2: Solar Cell
      • 3: Armor
      • 4: Weak Structure
      • 5: Weapon
    • Angle: The angle of this piece relative to its parent’s angle
    • Backtrack: Allows branching by causing this piece to move its base toward the center by this many segments before branching off. So for example backtrack 1 would create a Y shape.
  • When a new creature is created, its stats like arm length and number of arms are just averaged from its parents. Gaussian (bell curve shaped) random numbers are added to these averages. Then for each segment it gets a random one from all its possible parents. The inherited segment’s genes are also altered by Gaussian randomness.
  • The damage, health, solar collection, engine power etc. of each component is determined by its mass, which is close to width*length.

The end result gave a lot of variety in the creature types, and I’m pretty happy with it.


Considering that it was randomly generated by Wolfram Tones, I’m pretty happy with how the music turned out. The only small thing is that the music can seem a bit dissonant with the tone of the rest of the game at times. Another oddity was that the 64-bit JRE refused to load the music file, saying it was too big. The 32-bit JRE had no trouble, though.

What Went… Less Well


Again, PlayN was something of a mixed bag, especially because of its default build system, Maven. When Maven works, it works really well but its error messages can be a bit incomprehensible when it fails.

Additionally, PlayN’s severe performance problems in HTML5 mode forced me to repeatedly scale back the size of the game world. I suspect this has a lot to do with JavaScript being slow.


The game’s AI isn’t very good, although creating good AI for a game where the structures of creatures is so random would be a bit difficult. Still, I would have liked to make better AI for both enemies and player controlled bacteriums.

The Name

This was the first LD48 entry I had trouble naming. Originally, it was going to be called “Petri Dish Empire”. You can still see this name in some of the source code, and in the URL on my site “/pde/”. Eventually, I decided this sounded uninspired and I switched to “Empire of the Petri Dish”, which while sounding a bit better is a mouthful. It was only after the compo was over that I realized I should have named it “Bacterium Imperium”.

Testing and Balance

I noticed partway through development that weapon pieces were overpowered, so I made them more expensive, but it wasn’t really enough.

Another problem was that if the player wasn’t aggressive enough, the enemy bacteria could grow out of control and make the game very slow. This is why I added the solar cell cap, but it was a kind of rough change that I added late in development.

Late in development, I discovered a nasty exploit where you could use the fact that you can create a bacterium anywhere to put a small, heavily armed but immobile bacterium right in the core of an enemy, killing them quickly and easily. To fix this, I made it so that if on creation a bacterium intersected another, it was pushed away from the other one. If it still intersected others, it was pushed away until it did not, moving farther each time. The problem was that I just normalized the difference vector between their positions and then multiplied it by an increasing multiplier. Thus, in the degenerate case where they were right on top of each-other, it would enter an infinite loop. The issue was only discovered after the compo was over, so I couldn’t fix it in the compo version. Judging from the comments, it doesn’t look like a lot of people hit this issue, luckily.


I went back through my server access logs to see if I could make some interesting graphs of how people played the game. Here’s what I found:

Here’s how people downloaded the two versions (The native Java one, and the HTML5 one). It shows both which ones they downloaded and in what order they did:

In total, 90 people viewed the HTML5 version. However, 16 of them went on to download the Java version, so I suspect the HTML5 version didn’t work for them. Of the remaining 74:

Of the 9 people who won the HTML5 version, I measured the time from when they first requested the Javascript (the first thing that happens when you load the game in a browser) to when they won:

Finally, the game lets users select their screen size. While users can select any size, they’re encouraged to select a size just under the viewable area of their browser. Here are the sizes people used (The size of the bubble indicates the number at that size):


All in all, I’m pretty happy with how it turned out, and I hope you all enjoyed playing it!

For the curious, there is also a post-compo version with some alterations.


Leave a Reply

You must be logged in to post a comment.

[cache: storing page]