Wednesday, November 2, 2016

Cache Friendly

In my upcoming title Children of Orc the largest computational load is from the GOAP action planner that the NPCs use. I found that simple plans would be found in a millisecond. But larger plans would really tax the CPU. Especially if no plan exists to reach the goal state, a lot of cycles would be consumed. Typically a few seconds on a mid range corei5 CPU. This means it would be prohibitively expensive to do on a mobile device, if I were to port the game to iOS or Android.

I profiled it with linux command line tools, as well with Xcode's Instruments tool. Both showed that the cycles were spent in a linear search for the lowest cost node. The search would iterate though up to 32K nodes to find the lowest 'f' value in an array of these structures:


struct astarnode
{
        worldstate_t ws;                //!< The state of the world at this node.
        int g;                          //!< The cost so far.
        int h;                          //!< The heuristic for remaining cost (don't overestimate!)
        int f;                          //!< g+h combined.
        const char* actionname;         //!< How did we get to this node?
        worldstate_t parentws;          //!< Where did we come from?
};

Examining the assembly output of the linear search, I could not find anything wrong with the compiler's code. The only bothersome issue was that all the 'f' values that were being compared were lying 160 bytes apart.

To give the CPU cache an easier time, I decided to store the data as a structure of arrays instead. So now the search is performed on an array of ints, tightly packed, and no longer on an array of structures.

The result of this little exercise? A speed up of 2.7× which pleased me very much. If in the future, more speed ups would be required, I could possibly store the values in a priority queue instead. But for now, this will do nicely.

Note that in my GOAP implementation I search with A* and the most common operations are testing for presence in CLOSED and OPEN sets. These have already been accelerated with hash sets, shifting the bottleneck of the search to the finding of the lowest cost node.

Saturday, September 24, 2016

Debugging Software

I've always found Rob Pike's debugging story about Ken Thompson very powerful.

Ken would just stand and think, ignoring me and the code we'd just written. After a while I noticed a pattern: Ken would often understand the problem before I would, and would suddenly announce, "I know what's wrong." He was usually correct. -- Rob Pike.

This resonates with me, and I've always regarded debugging tools overrated. In many cases, you can do without those. My debugging method is typically a liberal use of assert() and fprintf(stderr,..) calls. But even those are not always a substitute of clear and deep thought, as I experienced again today.

Yesterday and today I was chasing a bug in my C code. The code generates topology and geometry of planets for my Children of Orc game. The visual and logical representations of the planet would not match up, and the Orcs would sink into the planet's surface. I spent a lot of time going over the code, over and over again. I even had a working Python version to compare with. But no matter how long I was staring at the code, I couldn't find the culprit.*)

I eventually solved the issue far away from the keyboard, when at the play ground with my toddler son. Just forming a mental picture of the processes, and some deep thinking on what could cause the observed behaviour of the code. It turned out to be a case of miss-used vertex indices. I keep two versions of the planet mesh, one where the polygons share vertices via indexing. The other where polygons are flattened out, and do not share vertices. I was using the indices of the former one to index the mesh of the latter. Going over the code, adding printf statements, did little good. Stepping away from the keyboard helped a lot. When back home again, finding and fixing the bug took seconds.

I also learned that in this case, the C code was double the size of the Python code. Before I ported it, my estimate was that C would require almost 10 times the lines of code. Even though Python is much more concise and powerful than the low level C, in this case it came down to a factor 2.

*) Comparing the outputs of Python and C versions was of little use, as both versions used different Simplex-Noise implementations. Also, the output was binary, not ascii. This made it hard to understand what specific part of the data was incorrect.

Friday, September 23, 2016

New Game: Children of Orc.

I have just introduced my new game to the world. It is called Children of Orc.

Children of Orc is a real-time third-person strategy game that is set on a procedurally generated hex-planet. Check out the trailer video:

To get published on Steam, it can use a little help with green light votes.

Tuesday, September 20, 2016

Blender Gotchas

There are many nooks and crannies in Blender that can catch you off guard. Here I will document them for reference by my future self, lest I would forget.

By default, Blender uses CPU, to use GPU on Linux, you have to, once as root, start blender -> User Preferences -> System -> Cuda. Quit blender, and then start as regular user, and do the same. Then select Cycles renderer, and under Render properties, Device: GPU Compute.

By default, Blender add ambient light. Why would you if you do Path Tracing? So disable it with: Properties World -> Surface Color black.

By default, Blender does not generate transparent PNGs. Render properties -> Film -> Transparent.

For high quality rendering with less noise, Render properties -> Sampling -> Samples Render: 100+

When importing let's say Wave front OBJ, the colour space is presumed linear, for vertex colours. This typically is not the case in OBJ files, so you need to fix those. Use this script. Extract the .py file and paste that in a text panel, then run the script.

Friday, April 15, 2016

Imhotep Progress - WEEK 06

I'm working towards the release of my new game Imhotep, Pyramid Builder on Steam. As I did for my previous game, I will report on the progress each and every week. Even if there is no progress, the report will be made. This is the best way to keep on track, and fight procrastination.

The game is finished and we have a release data! On May 6th, 2016, Imhotep, Pyramid Builder will launch on Steam.

This week, I added stack frame capture on crashes. I tuned the game. I added a difficulty settings BABY/NORMAL/LEGEND. I added a window icon. And I added price labels for the building types.

A big thank you to the people helping me do the beta test. There is still room to get into the beta test if you want. Just drop me an email if you want to help out.

Saturday, April 9, 2016

Imhotep Progress - WEEK 05

I'm working towards the release of my new game Imhotep, Pyramid Builder on Steam. As I did for my previous game, I will report on the progress each and every week. Even if there is no progress, the report will be made. This is the best way to keep on track, and fight procrastination.

Getting real close to a ship-able product now. As a matter of fact, the first play tester is now playing it, and finding bugs. For the first time, someone else than myself or my little 5 yo girl is playing the game.

Added cats to the game! They follow around humans, and sit and observe every now and then. When you pick them up, they meow!

I added file versioning for saved games. I now adapt the game speed to the display speed, so that running on a 144Hz gamer panel will work properly. I fixed some delta-time inaccuracies, as I was storing game time in a 32bit float, not a double precision float! I wrote a blog posting on why you should use a 4⅙ ms simulation time step.

If you are interested in helping out play testing, send me an email and I will give you a Steam code. Currently I have windows64 and linux64 binaries. OSX64 will be added at some time.

Saturday, April 2, 2016

Imhotep Progress - WEEK 04

I'm working towards the release of my new game Imhotep, Pyramid Builder on Steam. As I did for my previous game, I will report on the progress each and every week. Even if there is no progress, the report will be made. This is the best way to keep on track, and fight procrastination.

I added the restocking of the building stones if a user stops the build at a cell. Improved the initial spawn so that all four characters are visible. Added menu highlighting. Hooked up leader boards for fastest build, largest population, and most silver. Implemented button highlighting. Moved save files to steam directory. I ported the game from Linux to Windows using visual Studio. Upgraded to latest steam API. Auto load on launch, and auto save on exit. Fixed the OSX build. And lastly, I modelled a cat, because my good friend Matt told me a game on ancient Egypt needs cats in it.