Reminder: in October 2018, I’m pygame.org’s artist in residence. You can ask me questions about Trosnoth, support me in my Trosnoth development, join in online alpha testing, and follow this blog for articles about Trosnoth and what I’m working on.
What’s under the bonnet?
In my previous article, I wrote about what makes Trosnoth Trosnoth. But what powers Trosnoth, and why did we choose those building blocks? In this article I’ll try to answer that question.
There are three main reasons why Python was an appealing option when we started the Trosnoth project. Firstly, it’s easy to learn. We wanted to make it easy for new programmers to contribute to Trosnoth—or even to learn programming by hacking Trosnoth. Any language that was difficult to learn would make it harder from Trosnoth to be helpful for new programmers.
Secondly, Python allows rapid development. In my experience good developers can do things with Python to the same level of quality in much less time than with many other languages. (Though I do think the difference between languages by this measure has lessened somewhat over the years with the availability of free IDEs containing high quality tools.) This advantage is of great help to an open source project like Trosnoth because developers are usually writing code in their spare time. A developer doesn’t want to spend 50% of their time writing boilerplate code when they only have limited time to spend on Trosnoth.
Thirdly, Python makes it easy to write maintainable code. This is a benefit to any software project, but particularly one where developers are strapped for time. Hunting bugs is much harder when it takes several hours to understand what the code in question was trying to do in the first place.
await on the task/promise. This is all cooperative multitasking because it’s the programmer, not the operating system, that decides when one task should pass control to another.
When compared with shared-memory thread-based multitasking, cooperative multitasking eliminates a whole class of synchronisation bugs. Since Trosnoth aims to be welcoming to new programmers this seemed like a good idea. Back in the days of Python 2, you needed a third-party library in order to do cooperative multitasking. Twisted was one of the prominent options, and one of our original contributors had lots of experience using Twisted. So it was an obvious choice to make.
These days, Python has built-in primitives for cooperative multitasking:
async for etc.. It also has
asyncio in the standard library. If we’d started the Trosnoth project today, perhaps we would not have chosen to use Twisted. Having said that, Twisted also provides a whole raft of network protocols straight out of the box, which have proven useful at times. For instance, we can run a network-bound interactive Python REPL in a Trosnoth process using Twisted’s manhole module.
Trosnoth uses pygame for its graphics and audio. When we started working on Trosnoth, pygame and pyglet were the two main contenders for 2D Python audiovisual libraries. Pyglet was relatively young and had only a small community around it. Pygame was mature and had a large community. We chose the safe option and went with pygame. Even though development on pygame stalled from 2009 until late 2016, it continued to serve our needs.
During recent years we’ve toyed with the idea of moving Trosnoth to 2.5D graphics. That is, using a 3D game engine but keeping the gameplay all in a single 2D plane. To this end, we experimented with Panda3D. We even had a working (feature-incomplete) prototype that used the same network protocol and backend code but used Panda3D for the front-end. But sadly, when we updated our codebase to Python 3, the prototype broke. The development version of Panda3D, version 1.10, does support Python 3, but the latest stable release at time of writing does not. Until Panda3D 1.10 is released, any experimenting on this front has stalled.
4. Django (server-only)
The Trosnoth server has a web interface, mostly for displaying statistics from past games. When we first set up the web interface we just used
twisted.web. (Yes of course Twisted comes with HTTP support built in!) But
twisted.web is very rudimentary and the more information we wanted to display on the interface the more it made sense to move to a more complete web framework.
Django is a widely used and mature web framework so it was an obvious candidate: we wanted to be friendly to new programmers, and Django has lots of documentation and a supportive community. There was just one hassle: some elements of the web interface could interact with a running game. This meant that if we used Django we’d need to establish some communication between the web service and the game server. Or… we could run Django inside a Twisted main loop. This last idea sounds like it would never work. But I read a blog post explaining that actually it works pretty well, if you write code that plays nicely. Doing things this way actually made the transition to Django fairly simple. But talking about it does earn me looks of horrified admiration from certain other Python developers. (These days we actually run the web server in a separate process from the main game server, but there’s still some Twisted-y things going on in the web server.)
And that’s how Trosnoth works
…well that’s what Trosnoth’s built on anyway. There are some other very interesting technical details in how Trosnoth itself works: like where we hide network lag and how bots navigate the map. But those are stories for another day.
Keep an eye out for more articles about Trosnoth here on this blog throughout October.
2 If you followed the link, I’m sure you saw what I did there.
3 CPython is the reference implementation of the Python language, available from python.org.