Thursday, February 2, 2012

Refactor all things!

When I began this project almost a year ago, I had never written anything larger then a couple 100 lines in python. My main experience with django was with a small app I wrote for work to scrape emails for a particular failure case we had. Nothing I had done really quite prepared me for attempting to assemble all the game systems needed for a robust, state of the art, and more importantly; modern mud. This is evident in the code I wrote at that time, and so I have spent the past few days combing through it all and re-factoring the horrible parts, taking note from the clean, well designed parts.

This brings me to the next topic: How to make a huge, giant, game world tick without destroying the computer running it. Thankfully with the help of the Evennia devs, the solution is almost so simple it hurts to think I didnt realize it on my own, but you live and you learn.

The method is what is called a 'global tick' or 'global runner' system, and within Evennia at least, it is very easy. Just take a look at the following code:

class MobRunner(Script):
Controls when the update functions for mobs are called. Holds
a list of dbref's for subscribing objects (Mobs)

def at_script_creation(self):
self.key = 'mob_runner'
self.interval = 30
self.persistent = True
self.desc = 'controls the subscribing mobs'
self.db.mobs = []

def at_start(self):
self.ndb.mobs = [ search.objects(dbref) for dbref in self.db.mobs ]

def at_repeat(self):
self.ndb.mobs = search.objects('mob_runner')
[mob.update() for mob in self.ndb.mobs if mob.db.should_update ]

def at_stop(self):
self.db.mobs = [mob.dbref for mob in self.ndb.mobs]

So what is that doing? It's basically keeping a list full of subscribing object id's. On start it reads these into memory (say after a server restart), then when the script rolls around and repeats it does two things: update the memory stored list of mobs subscribing to it, and then running the update function on each subscriber, if it is set to update. This particular script runs every 30 seconds and is what controls a lot of random upkeep for the mobs in Avaloria. This approach can be used with multiple scenarios where EVERYTHING in the world needs to have something done to it. The resource usage is minimal and everything runs fantastically so far, even when jammed full of objects all needing updates.

Thanks to the guys at the Evennia project for setting me straight and not allowing me to run my server to an early grave :)


  1. wow! I worked a tiny bit on Evennia a long time ago, so I saw your email to the list the other day. Then, I see this today. Amazing code, simple, pythonic - perfect!

    1. Thanks...well really thanks to griatch, it's his code basically :) Keep an eye on this blog and my project page for an alpha release of Avaloria.