1. icon for News
  2. icon for TCHOW


Wednesday, July 3, 2013

Keeping Rktcr Honest

One of the important tenants of Rktcr is that -- while it is very hard -- it isn't impossible. So how do I keep the game possible, given the hundreds of generated worlds and tens of levels? As expected, the answer is extensive (semi-automatic) testing.

The core of this testing revolves around a database of paths -- recordings of player input that take the vehicle from portal [to gem] to portal, under different gravity directions and mirrorings, in each level. As of this writing, there are 1093 paths in the database. That's a lot of gameplay (in fact, it's all the gameplay I think is possible).

These paths have a few functions, but the most important is to make sure that any changes I make to the game don't (unintentionally) change what is possible in the game. I have a helper program test_paths that runs every path in the database and prints a hash of the game states along each path. The output of test_paths gets stored in my main git repository; before releasing a build (and, generally, after any change that I think might have messed with the physics), I run test_paths and compare to the stored output. If there are any differences, I know there is trouble afoot.

Of course, the paths aren't just for testing. They also get converted into par times for the levels; for this I have a pair of utility modes -- rktcr update-claims updates the par times to reflect the current paths database, while rktcr check-claims check the current par times against the paths database to make sure they are consistent (this comes in handy when I change level geometry or physics, invalidating existing paths, as it lets me know what paths I need to recreate).

Aside: why not distribute paths instead of par times? Philosophical reasons, mainly. I prefer that games not know the answers they are asking you to provide.

These par times, in turn, are used by the aptly named world_gen to generate worlds (groups of connected levels). Of course, I want to hedge against the possibility that a world becomes unwinnable owing to new paths and par times. For this, I have yet another utility program, world_test, which loads each world in turn and makes sure that it is solvable in a reasonable time, given the current par times.

And that's how I keep Rktcr honest.