• entries
99
279
• views
154477

# Achilles + Screenshot Saturday 208

1549 views

This past weekend I participated in the CivicHacks "Game Jam for Good". The goal was to raise awareness of the global water crisis and ultimately promote PackH2O, a Columbus-based startup that designs water backpacks for developing water-stressed regions.

The jam lasted 48 hours. My entry is called "Achilles".

Achilles is a multiplayer text-based simulation. You the player must manage a village in a third-world country experiencing a water crisis. You can play it here (bit.ly/waterjamachilles) assuming I haven't stopped paying for the cloud server.

It's incredibly depressing. Really, only bad things can happen. I had plans to add pregnancy and childbirth, but ran out of time. Here's a video of it in action:

The core idea was this: to convince people of the effectiveness of the PackH2O backpack, a promotional game should put players in the shoes of the people who will use it. And I think I accomplished that. In the game, the backpack allows people to carry twice as much water. The player experiences first-hand through gameplay how useful the backpack is.

Despite the game's inherent awfulness, it won an "honorable mention", which actually turned out to be good for a \$500 gift card. You can check out the other winning games on the CivicHacks website.

Technology
On the backend, I wrote Achilles in Python using Flask as a web server framework (highly recommended).
I used gevent for greenlets, which made it very easy to write time-based procedures for each character. For example, here's how a man builds a hut:if village['build_material'] > 0: village['build_material'] -= 1 notify(world, village['id']) state['state'] = 'building' notify(world, man['id']) gevent.sleep(world_seconds(world, 60 * 60 * 17)) village['huts'] += 1 notify(world, village['id']) man['state'] = None notify(world, man['id']) send(village['id'], { 'event': '{0} finished building a hut.'.format(man['name']) })else: send(village['id'], { 'event': 'Not enough build material for a hut.' })
The "notify" and "send" functions send JSON objects to the relevant clients over WebSockets.
On the frontend, I only used jQuery (no plugins) and Mustache.js for templating.
If you're interested, check out the code here on Github.

Compression-based programming
I used this game jam as an opportunity to try out compression-based programming as advocated by the excellent Casey Muratori. The idea is, instead of spending time upfront designing a complex cathedral-like architecture, you should write straightforward, ugly, even repetitive code (copying and pasting). When it's done, you go back and "compress" the code into something nicer via refactoring.
Of course, some things are straightforward enough that you can compress them as you go. For example I always knew there would be a "send" function.
Casey says one of the big problems with "normal" programming is that you assume you know everything at the beginning of a project, when in reality, you often don't. Compression-based programming has you architecting things only after you've seen the whole picture.
After a weekend of experimentation, I think this pattern of coding results in plain, boring, easy to understand code, which is definitely a good thing. Normally I come up with some super fancy way to write everything very elegantly, which creates more work than it's worth in the end.
Another paradigm Casey rails against is object-oriented programming, so I also tried writing everything procedurally. The result was again boring but simple and easy.
The biggest win was separating state from behavior. On both the client and server, all the state lived in a single object, parts of which were operated on by various procedures.
Normally, I often link state and behavior so closely that they're impossible to separate. Every time I write a closure (probably my favorite bad habit), I squirrel away an opaque bit of state inextricably tied to an anonymous bit of behavior.
Time to wrap this up: you should try coding in a boring, straightforward, state-separated-from-behavior, procedural style. The result is a breath of fresh air in a world of increasingly clever object models and cathedral architectures.

Screenshot Saturday 208

This week's level is not quite done yet, but I have an excuse! Power was out at the incubator for two days, and the internet didn't come up fully until just yesterday.

Still, the level should be done some time this weekend and is already looking pretty good.

I finalized the promotional graphics and published the game to Steam in "coming soon" mode. I'm incredibly grateful to Sam Gebhardt for contributing his Hollywood artistic talent!

I updated the website to feature Sam's artwork and shot a brand new trailer:

The 5 second cuts didn't turn out to be as good of an idea as I hoped, but it works for now.

Progress continues. Lord willing I will finish this game with or without power!

Mirrored on my blog: Achilles

Mirrored on my blog: Screenshot Saturday 208

Looking awesome as ever. I read that Casey article too. I get where he is coming from but I find his arguments a bit strawman to be honest. He seems to blame OO for bad programmers. I think it is the education system that is at fault personally.

I think I slightly mis-characterized him as a total OO hater, he mostly just recognizes that OO lends itself to sloppy programming. Ultimately the idea is to use the right tool for the right job, and secondarily, to use the tools you're comfortable with. There's always a time and place for a bit of well-designed OO.

But you're absolutely right, CS education is abysmal.

Yeah, I just feel OO takes a lot of the grief for things that are due to bad use of it rather than the approach itself. If you look at the kind of approaches that were taught before the world went object-mad, we were in bad shape then too, but nobody seemed to blame procedural programming for it, just bad design.

I think his point is that objects simply emerge as pieces of reusable code. He simply does not see programming in terms of 'objects' because compressing reusable code should be second nature.

## Create an account

Register a new account