<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Power-of-Two on Games From Within</title><link>https://gamesfromwithin.com/tag/power-of-two/</link><description>Recent content in Power-of-Two on Games From Within</description><generator>Hugo</generator><language>en-us</language><copyright>2004–2026 Noel Llopis</copyright><lastBuildDate>Fri, 19 Sep 2008 00:00:00 +0000</lastBuildDate><atom:link href="https://gamesfromwithin.com/tag/power-of-two/index.xml" rel="self" type="application/rss+xml"/><item><title>Bad News for Scons Fans</title><link>https://gamesfromwithin.com/bad-news-for-scons-fans/</link><pubDate>Fri, 19 Sep 2008 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/bad-news-for-scons-fans/</guid><description>&lt;p&gt;We have been talking a lot about Scons recently at the Power of Two Games World Headquarters. MSBuild has proven to be quite a pain to work with for our asset builds and eventually left us dissatisfied (that&amp;rsquo;s material for a whole other entry). So we kept looking over to Scons as a possible solution.&lt;/p&gt;</description><content:encoded><![CDATA[<p>We have been talking a lot about Scons recently at the Power of Two Games World Headquarters. MSBuild has proven to be quite a pain to work with for our asset builds and eventually left us dissatisfied (that&rsquo;s material for a whole other entry). So we kept looking over to Scons as a possible solution.</p>
<p>On paper it looks great:</p>
<ul>
<li>Built from the ground up for parallel builds</li>
<li>Uses a real programming language (Python) instead of overly-complicated XML files</li>
<li>It allows for discovery of assets to build as other assets are parsed</li>
</ul>
<p>The big question mark hanging over it was whether it was fast enough. I had done <a href="/the-quest-for-the-perfect-build-system-part-2/">some experiments</a> with Scons and other build systems a few years ago, and Scons totally failed by having ridiculously long incremental build times just checking if anything had changed. That was simply not acceptable. If no data has changed, I want the build system to detect it and come back in a second or less.</p>
<p>Since then, I&rsquo;ve been told that Scons had finally fixed its dependency checking and it was much faster now. Music to my ears!</p>
<p>So I resurrected the <a href="/wp-content/uploads/bin/generate_libs.zip">old script I wrote back then</a> to generate a nightmare stress test, downloaded <a href="http://www.scons.org/download.php">the latest stable version of Scons</a> (1.0.1) and fired it up.</p>
<p>I&rsquo;m sorry to report that Scons is still as unusable as it was back then. I generated a codebase like the one I used to measure all the build systems (50 libraries, 100 classes each, 15 internal includes, 5 external includes). I built everything once, then ran it again and it took 49 seconds. I have some pretty nice hardware, including a fast SATA hard drive and a 2.8GHz Core2Duo with plenty of RAM, and 49 seconds to say that nothing needs to be changed just doesn&rsquo;t cut it.</p>
<p>Now to be fair, right now we&rsquo;re looking at Scons to build our assets, not our code. Maybe the nested project configuration is not particularly realistic, so I tried something simpler: 5000 files in a single library without any dependencies among each other at all. This is a very conservative example for an asset build of a large commercial game.</p>
<ul>
<li>It&rsquo;s only 5000 files. A real game can easily have 10 times as many asset files.</li>
<li>All the files are tiny (cpp files in this case). Assets can get very large when dealing with textures, sounds, and animations.</li>
<li>There are zero dependencies among assets in this example. You&rsquo;ll often have models depending on shaders and textures, levels on game entity definitions, etc.</li>
</ul>
<p>Building assets doesn&rsquo;t have to be the instant, no delay kind of build that I require building code. I expect most developers will be building assets locally, tweaking things, rebuilding, and trying them in the game. The faster the build is, the better, but a delay of a few seconds can be acceptable. If Scons can&rsquo;t handle this build in less than 10 seconds, it&rsquo;s certainly doomed in a full-scale game.</p>
<p>The result: 37 seconds!</p>
<p>For purely masochistic reasons, I decided to see how it scales, so I threw 20,000 files at it (again, without any dependencies). Incremental build time without any changes: 3 minutes and 46 seconds. That&rsquo;s over 6 times longer for processing 4 times the number of files, so it doesn&rsquo;t even scale linearly.</p>
<p>Scons is definitely too slow, and MSBuild has its share of problems. What&rsquo;s left out there? Any recommendations for good parallel asset building systems? Hopefully something lightweight and easily configurable through a real language. Anything?</p>]]></content:encoded></item><item><title>The Measure Of Code</title><link>https://gamesfromwithin.com/the-measure-of-code/</link><pubDate>Fri, 13 Jun 2008 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/the-measure-of-code/</guid><description>&lt;p&gt;I&amp;rsquo;ve gotten a lot of questions about how big our codebase is, how fast does it build, how many tests we have&amp;hellip; Fear not, Gentle Reader, all your burning questions will be answered here.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I&rsquo;ve gotten a lot of questions about how big our codebase is, how fast does it build, how many tests we have&hellip; Fear not, Gentle Reader, all your burning questions will be answered here.</p>
<h2 id="size">Size</h2>
<p>Charles and I were priding ourselves in keeping things small and minimal. But truth be told, it&rsquo;s not like we were keeping track of how many lines of code we had written. Were things as small as we hoped they were?</p>
<p>The most convenient way of counting lines of code that I know is <a href="http://cloc.sourceforge.net/">CLOC</a>. It&rsquo;s an extremely easy to use open source program which counts the lines of code in a codebase, gives very detailed information, strips out whitespace, breaks things down by language, and does just about everything you&rsquo;d want from a program like that.</p>
<p>Running it on the latest version of our code (not including any 3rd party libraries) produces this:</p>
<pre tabindex="0"><code>Â Â Â  1621 text files.Â Â Â  1579 unique files.Â Â Â  3721 files ignored.
-------------------------------------------------------------------------------
LanguageÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â filesÂ Â Â Â Â Â Â Â Â  blankÂ Â Â Â Â Â Â  commentÂ Â Â Â Â Â Â Â Â Â code
-------------------------------------------------------------------------------
C++Â Â Â Â Â Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 485Â Â Â Â Â Â Â Â Â  13577Â Â Â Â Â Â Â Â Â Â Â  303Â Â Â Â Â Â Â Â Â  46181
C#Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  324Â Â Â Â Â Â Â Â Â Â  4935Â Â Â Â Â Â Â Â Â Â Â  712Â Â Â Â Â Â Â Â Â  22966
C/C++ HeaderÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  407Â Â Â Â Â Â Â Â Â Â  4153Â Â Â Â Â Â Â Â Â Â Â Â  95Â Â Â Â Â Â Â Â Â  11975
MSBuild scriptsÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  18Â Â Â Â Â Â Â Â Â Â Â Â Â  0Â Â Â Â Â Â Â Â Â Â Â  126Â Â Â Â Â Â Â Â Â Â 1490
-------------------------------------------------------------------------------
SUM:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  1234Â Â Â Â Â Â Â Â Â  22665Â Â Â Â Â Â Â Â Â Â  1236Â Â Â Â Â Â Â Â Â  82612
</code></pre><p>Almost 60K lines of C++ code seemed very high. At first I thought it was because CLOC was counting files twice: once in their regular location and once in the .svn directory, but apparently it&rsquo;s already removing all duplicates, so that wasn&rsquo;t it.</p>
<p>Almost more scary than the amount of C++ code (which is all our runtime and some of our tools) is the amount of C# code. For a language that claims to be of significantly higher level than C++, that&rsquo;s quite a mouthful of code!</p>
<p>Another surprising count in there is the number of lines with comments. Since we make heavy use of <a href="http://www.gamesfromwithin.com/articles/cat_testdriven_development.html">TDD</a>, I really didn&rsquo;t expect more than a couple dozen lines of code in the whole codebase. Still, I&rsquo;m kind of proud that we have less than one line of code per file on average :-)</p>
<p>Here&rsquo;s a more detailed breakdown, with the line count just for our runtime (engine and game):</p>
<pre tabindex="0"><code>1089 text files.    1053 unique files.    2338 files ignored.
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C++                            441          11997            245          40943
C/C++ Header                   385           3964             90          11405
-------------------------------------------------------------------------------
SUM:                           826          15961            335          52348
</code></pre><p>and for our tools:</p>
<pre tabindex="0"><code>532 text files.     531 unique files.    1383 files ignored.
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C#                             324           4935            712          22966
C++                             44           1580             58           5238
MSBuild scripts                 18              0            126           1490
C/C++ Header                    23            199              5            591
-------------------------------------------------------------------------------
SUM:                           409           6714            901          30285
</code></pre><h2 id="tests">Tests</h2>
<p>Then I realized that a good chunk of those were tests. So excluding all directories matching *Tests* gets the following result:</p>
<pre tabindex="0"><code>1206 text files.    1187 unique files.    4199 files ignored.
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C++                            283           6464            150          22464
C#                             213           2636            534          12402
C/C++ Header                   380           3824             94          10782
MSBuild scripts                 12              0             84            978
-------------------------------------------------------------------------------
SUM:                           888          12924            862          46626
</code></pre><p>A bit more than half the C++ code consisted of tests. That&rsquo;s pretty consistent with my experience with TDD. C# seems to follow a similar percentage as well.</p>
<p>As for the exact number of tests, running a grep for TEST shows all the C++ tests:</p>
<pre tabindex="0"><code>C:\pow2&gt;grep -r TEST SweetPea Engine Tools | grep -v svn | wcÂ Â  2163Â Â Â  3620Â  221953
</code></pre><p>And doing the same thing with [Test] brings up all C# tests:</p>
<pre tabindex="0"><code>C:\pow2&gt;grep -r \[Test\] SweetPea Engine Tools | grep -v svn | wcÂ Â  735Â Â Â  1470Â Â 52717
</code></pre><p>That means that our average C++ test is about 11.5 lines long, and C# tests 14.4. Frankly, that sounds rather high. We make heavy use of fixtures whenever possible and each test usually only checks for a single condition (even if it involves a couple check statements). I suppose that number is higher than expected because it probably includes all the lines from #include statements and all the fixtures as part of the average.</p>
<table>
	<thead>
			<tr>
					<th><strong>Language</strong></th>
					<th><strong>Lines</strong></th>
					<th><strong>Non test lines</strong></th>
					<th><strong>Test lines</strong></th>
					<th><strong>% of non test code</strong></th>
					<th><strong>Number of tests</strong></th>
					<th><strong>Lines per test</strong></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>C++</td>
					<td>58156</td>
					<td>33246</td>
					<td>24910</td>
					<td>57% *</td>
					<td>2163</td>
					<td>11.5</td>
			</tr>
			<tr>
					<td>C#</td>
					<td>22966</td>
					<td>12402</td>
					<td>10564</td>
					<td>54%</td>
					<td>735</td>
					<td>14.4</td>
			</tr>
	</tbody>
</table>
<p>* If we only count cpp files, that goes down to 49%</p>
<p>I was curious about that last part of checking a single thing per test, so I ran a grep for the number of CHECK statements in our code:</p>
<pre tabindex="0"><code>C:\pow2&gt;grep -r CHECK SweetPea Engine Tools | grep -v svn | wcÂ Â  3886Â Â  15079Â  399598
</code></pre><h2><img loading="lazy" src="images/tapemeasure.jpg"></h2>
<p>That&rsquo;s 1.8 CHECK statements per TEST, which is about right. Even though we&rsquo;re checking for a single condition, we&rsquo;ll often check a couple things about it (i.e. the camera stopped and it reached its final destination).</p>
<h2 id="build-times">Build Times</h2>
<p>So, given that amount of code, how long does it take to build it? Clearly it depends on your hardware. Since we&rsquo;re not exactly rolling in money, we don&rsquo;t have particularly powerful machines. Here at home, I&rsquo;m using a modest Core 2 Duo E4300 (overclocked to 2.6 GHz) with fast memory and a relatively fast SATA hard drive, so that&rsquo;s what I used for all my timings.</p>
<p>A full build of our game, plus all the libraries, all the tests, and running all the tests takes exactly 1 minute and 10 seconds. That&rsquo;s pretty good for two reasons:</p>
<ul>
<li>When we work with the game we don&rsquo;t build and run the unit tests for the engine. We have a separate solution for that. A full build of just the engine, the game, and the game unit tests only takes 43 seconds.</li>
<li>The game itself is a fairly large project and devenv doesn&rsquo;t know how to paralellize that build, so it&rsquo;s only using half the available CPU power for about half the build time.</li>
</ul>
<p>An incremental build after changing a single cpp file takes <a href="http://powerof2games.com/node/32">slightly over a second</a> (including half a second of unit test execution).</p>
<p>As you can imagine, working with that codebase is a dream come true. Snappy, responsive. Nothing is hard enough that can&rsquo;t be changed.</p>
<p>Unfortunately that&rsquo;s where the fairy tale ends. The tools are another story altogether. Our C# tools, with all their unit tests, build in a mere 18 seconds, and the C++ tools in 1 minute and 10 seconds. That&rsquo;s not too bad, except that it&rsquo;s a surprisingly large amount of time for the C++ tools since there aren&rsquo;t that many of them.</p>
<p>Here&rsquo;s the kicker, doing another build without changing a single thing take 38 seconds. Whoa! We&rsquo;re doing some C++/CLI trickery and apparently dependency checking is totally broken in VS2005 (either that, or we just don&rsquo;t know how to set it up right).</p>
<h2 id="keeping-things-fast">Keeping things fast</h2>
<p>What&rsquo;s the secret of a lighting-fast build? Clearly, keeping the code size down is crucial. If your codebase is 2 million lines of code, builds are going to be painful no matter what. But they can be a little less painful with some gentle care.</p>
<p>One of the main build-time killers that we&rsquo;re avoiding is the use of STL or <a href="http://www.boost.org/">Boost</a>. Those libraries pull in everything and the kitchen sink, and their heavy use of templates make build and link time go through the roof. No thanks.</p>
<p>Our template use is pretty minimal. We have a couple containers (which I love and I&rsquo;ll write about it one of these days) and that&rsquo;s about it.</p>
<p>We&rsquo;re pretty anal when it comes to keeping <a href="/physical-structure-and-c-part-2-build-times/%20">physical dependencies</a> to a minimum. We forward declare aggressively, and we only include the headers that are necessary for each cpp file (<a href="http://www.gimpel.com/">PC Lint</a> is &ldquo;kind&rdquo; of enough to remind us every time we have unnecessary #includes). We&rsquo;re not using external include guards or #pragma once.</p>
<p>Precompiled headers are either not used, or kept to a minimum. I think the only project that uses them is the game and only for Havok headers. We don&rsquo;t even have windows.h in a precompiled header (which would be a really bad idea because you&rsquo;d be putting all the junk in windows.h available to your whole program).</p>
<p>Finally, we are using incremental links whenever possible. I remember a few versions of Visual Studio ago they were pretty broken, but they&rsquo;re not giving us any problems. The only caveat is that if you modify a static library your program is linking with, it will force a full link. So they&rsquo;re really only good for modifying the executable itself.</p>
<p>We&rsquo;re not using any distributed builds. First of all, we don&rsquo;t have enough computers to make it worthwhile. And second, I had horrible experiences with distributed builds in the past. They would help with a badly structured codebase, at the cost of longer incremental builds and mysterious spurious bad builds. Besides, once they&rsquo;re in place, they tend to encourage even further disregard for keeping dependencies to a minimum.</p>
<h2 id="how-about-you">How about you?</h2>
<p>So, that&rsquo;s it for the Power of Two codebase. How about you? Want to share your size, build times, or any other data?</p>]]></content:encoded></item><item><title>What's Your Pain Threshold?</title><link>https://gamesfromwithin.com/whats-your-pain-threshold/</link><pubDate>Tue, 10 Jun 2008 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/whats-your-pain-threshold/</guid><description>&lt;p&gt;Mine is two seconds.&lt;/p&gt;
&lt;p&gt;Here at Power of Two Games, we write all our code with &lt;a href="https://gamesfromwithin.com/backwards-is-forward-making-better-games-with-test-driven-development/"&gt;test-driven development.&lt;/a&gt; C++ tests use the fantastic &lt;a href="http://unittest-cpp.sourceforge.net/"&gt;UnitTest++ framework&lt;/a&gt; (no big surprise there :-) ) and we run all unit tests automatically as the last step of our build process. That means that every time we build anything, the tests for that library or program get executed. Every time. No exceptions.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Mine is two seconds.</p>
<p>Here at Power of Two Games, we write all our code with <a href="/backwards-is-forward-making-better-games-with-test-driven-development/">test-driven development.</a> C++ tests use the fantastic <a href="http://unittest-cpp.sourceforge.net/">UnitTest++ framework</a> (no big surprise there :-) ) and we run all unit tests automatically as the last step of our build process. That means that every time we build anything, the tests for that library or program get executed. Every time. No exceptions.</p>
<p>None of that would be an issue except that TDD creates lots of unit tests and encourages almost constant incremental builds. In the past I&rsquo;ve stressed how important it is to keep them fast. But this week that I was able to really feel what a dramatic difference slow unit tests make.</p>
<p>For many months, our unit tests ran under one second. Each library has its own set of unit tests, and so does the game and each tool. So even though we were writing lots of unit tests, we weren&rsquo;t always running them all at the same time. There was a definite snappiness to coding: write test, compile, fail, write code, compile, pass, move on. Go, go, go.</p>
<p>As the game project got larger, we started accumulating more unit tests and testing times started creeping up into the second range. At the time, I couldn&rsquo;t quite put my finger on what had changed, but there was a definite change in feel. Things weren&rsquo;t quite as snappy.</p>
<p>Then, about a couple of weeks ago, we hit the two second mark and things definitely changed.</p>
<pre tabindex="0"><code>&gt; bin\SweetPea_d.exe -unittestSuccess: 1145 tests passed.Test time: 2.13 seconds.
</code></pre><p>As the tests were running, my mind would wander, thinking about what test I would write next, or whether the code I had just written would be cache-friendly, or whether we&rsquo;d do Honey&rsquo;s or Manhattan for lunch. I would be jerked out of my <a href="http://en.wikipedia.org/wiki/Flow_%28psychology%29">state of flow</a>. It wasn&rsquo;t just me, Charles felt it too. The difference in productivity was huge.</p>
<h2 id="the-zones">The Zones</h2>
<p>For those of you laughing at those times and dismissing them as insignificant, you need to keep in mind that our build times are very short:</p>
<ul>
<li>An incremental build with just a change in a cpp file takes under a second (including link times).</li>
<li>A full build of *all* our runtime code, including libraries, is around 50 seconds in a dual-core machine <a href="#note1">[1]</a>.</li>
</ul>
<p>So adding on 2 seconds to the incremental build time is going from â€œpractically instantâ€ to â€œOK, I&rsquo;m waiting&hellip;â€.<img loading="lazy" src="images/antique-clocks.jpg"></p>
<p>Of course, none of this has anything to do with unit tests in particular. It&rsquo;s total incremental build times (including compiling, linking, and running unit tests) that matter. An incremental build that takes 3 seconds with no unit tests is just as bad as one that is under one second with 3 second unit tests. They both interrupt the flow the same way.</p>
<p>I&rsquo;ve often thought about how a company size affects communication and â€œfeelâ€. It&rsquo;s close to a step function with logarithmic scale: there&rsquo;s a distinct jump from a company of 3 to a company of 10, to one of 35, to one of 100+.</p>
<p>I think something similar applies to build times <a href="#note2">[2]</a></p>
<ul>
<li>0 to 2 seconds. Programmer stays in the flow. Productivity is way high.</li>
<li>2 to 8 seconds. Flow is broken. Definite feel of things being a bit painful and sluggish.</li>
<li>8 to 30 seconds. Attention wanders to other parts of the code, email, etc. Multitasking kicks in and overall productivity plummets.</li>
<li>30+ seconds. Builds seen as batch processing. After each build is started, some other action is started. Maybe even physically get up, get a drink, start a conversation. Full brain reboot between coding tasks.</li>
<li>5+ minutes. Programmers bang their heads against the desk, actively consider the merits of different forms of suicide, or at the very least start polishing their resumes.</li>
</ul>
<h2 id="the-fix">The Fix</h2>
<p>Having been spoiled by sub-second build times, neither one of us wanted to put up with the broken flow of 2+ second builds, so we decided it was time to fix things <a href="#note3">[3]</a>.</p>
<p>The good news is that our slow build times were solely due to running the unit tests. 2.13 seconds to run only about 1100+ tests is really bad, even on a so-so desktop machine like the ones we can afford. That&rsquo;s almost 2ms per test! Remember that these are unit tests, not functional tests. So I expect to be able to run several thousands of these under one second. Something was way off.</p>
<p>Things had gotten much worse in the last couple of weeks, so it wasn&rsquo;t a slow, steady creep up. Chances are we had introduced something very slow recently, which meant it was probably easy to fix.</p>
<p>As a first pass, we turned on the option to fail any test that takes over a certain amount of time in UnitTest++:</p>
<pre tabindex="0"><code>RunAllTests(reporter, UnitTest::Test::GetTestList(), NULL, 5); // fail any test over 5ms
</code></pre><p>That brought about tons of failing test, most of them added recently and creating one particular object in their fixtures. Digging a big deeper, that particular class had an array of 25,000 (yes, that many zeros) objects. Those objects were <a href="http://en.wikipedia.org/wiki/Plain_Old_Data_Structures">plain-old-data structures</a>, but had a default constructor. Even though the constructor was simply initializing its members to zero, that was causing a significant slow down when so many objects were created. To make things worse, some of the code I had written was iterating over the array resetting the entries or shifting them up or down, repeatedly calling the constructor. Ouch!</p>
<p>A few minutes and lots of code hacking later, and the object didn&rsquo;t call a single constructor anymore. Our test times went down by almost half. Victory!</p>
<p>We were already at 1 second, which is in the acceptable range, but since we were here, maybe we could improve things a bit more. After all, 1ms per test is still too slow.</p>
<p>UnitTest++ wasn&rsquo;t reporting failing tests over 1ms very reliably. Different runs would cause very different results. Things were too spread out or other things in the computer were interfering too much.</p>
<p>About a fifth or so of our tests use Havok. Not with mocks, but directly. They each initialize Havok, create a world, and deal with a simple rigid body, constraint, or something of the sort. I suspected all along that the Havok system initialization and shutdown for each test was probably causing quite a slow down, so I changed it to be initialized only once before we ran any tests.</p>
<p>And that did the trick. With that change we were down to 0.16 seconds. Back to snappy, happy land!</p>
<pre tabindex="0"><code>&gt; bin\SweetPea_d.exe -unittestSuccess: 1145 tests passed.Test time: 0.16 seconds.
</code></pre><p>In release mode things are even better, but we do most development in debug mode, so that&rsquo;s the really important one:</p>
<pre tabindex="0"><code>&gt; bin\SweetPea.exe -unittestSuccess: 1145 tests passed.Test time: 0.06 seconds.
</code></pre><p>Perhaps sub-second build times are not realistic for all projects, but I think there&rsquo;s a lot to be gained by keeping compile, link, and test times as short as possible. For tips on how to keep compile times down, check out <a href="/physical-structure-and-c-part-1-a-first-look/%20">these articles</a> <a href="/physical-structure-and-c-part-2-build-times/%20">I wrote a while ago</a>. If your unit tests are slow and you really can&rsquo;t speed them up anymore, consider splitting them into two sets: one that is important or recent ones that runs with every build, and another, more comprehensive one that runs in the build server.</p>
<p>Even if you cut down from 20 seconds down to 10, you&rsquo;ll be making a huge shift in how you&rsquo;re able to work and iterate on your programming.</p>
<p>[1] We&rsquo;d love to keep detailed metrics with each build: executable size, number of lines of code, number of tests, etc, etc. Unfortunately, when the rubber hits the road, that ends up in the â€œnice to have categoryâ€ and we simply have no resources to spare on a two-man startup.</p>
<p>[2] For a whole whooping statistical population of one since I&rsquo;m only talking about my experience. Still, I suspect that the same applies to many other programmers by scaling the function by some constant.</p>
<p>[3] Perfect use of agile mentality. Fix things when you need them fixed, not before. But make sure you do fix them when you need them. Otherwise it&rsquo;s not agile, it&rsquo;s just lazy.</p>]]></content:encoded></item><item><title>Stupid C++ Tricks #2: Better Enums</title><link>https://gamesfromwithin.com/stupid-c-tricks-2-better-enums/</link><pubDate>Mon, 14 Apr 2008 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/stupid-c-tricks-2-better-enums/</guid><description>&lt;p&gt;So much for the new year&amp;rsquo;s resolution to write some sort of an update every week. That went out the window pretty quickly. Especially now that I&amp;rsquo;ve taken over the Inner Product column for Game Developer Magazine and that&amp;rsquo;s taking away some of my writing time (check out the May issue for my first column!).&lt;br&gt;
It turns out that Charles&amp;rsquo; old article &lt;a href="http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/" title="Stupid C++ Tricks: Adventures in Assert"&gt;Stupid C++ Tricks: Adventures in Assert&lt;/a&gt; is one of our most viewed entries, even after all this time. So I figured I&amp;rsquo;d follow it up with a really, really simple C++ trick. It&amp;rsquo;s almost trivial, really, but I&amp;rsquo;ve totally fallen in love with it. At first, when Charles introduced me to it, I was kind of lukewarm. But now I&amp;rsquo;m finding myself going through refactoring rampages in the code changing things to be this way. Intrigued? Read on.&lt;/p&gt;</description><content:encoded><![CDATA[<p>So much for the new year&rsquo;s resolution to write some sort of an update every week. That went out the window pretty quickly. Especially now that I&rsquo;ve taken over the Inner Product column for Game Developer Magazine and that&rsquo;s taking away some of my writing time (check out the May issue for my first column!).<br>
It turns out that Charles&rsquo; old article <a href="http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/" title="Stupid C++ Tricks: Adventures in Assert">Stupid C++ Tricks: Adventures in Assert</a> is one of our most viewed entries, even after all this time. So I figured I&rsquo;d follow it up with a really, really simple C++ trick. It&rsquo;s almost trivial, really, but I&rsquo;ve totally fallen in love with it. At first, when Charles introduced me to it, I was kind of lukewarm. But now I&rsquo;m finding myself going through refactoring rampages in the code changing things to be this way. Intrigued? Read on.</p>
<p>C++ enums are great in practice, but they&rsquo;re a bit lacking once you really start flexing them. Don&rsquo;t get me wrong, they&rsquo;re definitely a step up from #defines, but you can&rsquo;t help but wish for more. Type safety is only so-so (enums get promoted to ints silently), you can&rsquo;t forward declare them so you&rsquo;re forced to have extra includes, you can&rsquo;t split up a declaration of enums across multiple files (the compiler would have to do more work, but it would be awesome to be able to create uids for different classes in their own header files instead of a global one). But the most grating of design decisions is their scoping rules.<br>
Take for example a set of enums describing the game flow:</p>
<pre tabindex="0"><code>enum GameFlowType
{
    Run,
Â    Exit,
   Â Restart,
   Â Restore,
};
</code></pre><p>Now functions can return a GameFlowType to indicate that the main loop should do. So far so good.</p>
<p>Except that, look at how it&rsquo;s used:</p>
<pre tabindex="0"><code>GameFlowType DoMainLoop(bool render)
{
    //...
   Â if (someCondition)
       Â return Exit;
   Â return Run;
}
</code></pre><p>Ouch! We&rsquo;ve managed to pollute the global namespace with totally generic keywords such as Run and Exit. What if I want to have an enum that controls what action an AI is going to take:</p>
<pre tabindex="0"><code>enum AIAction
{
Â Â Â  Enter,
Â Â Â  Exit,
Â Â Â  Stop,
Â Â Â  Walk,
Â Â Â  Run,
};
</code></pre><p>That won&rsquo;t even compile because the symbols conflict with the GameFlowType ones. Even worse, it will compile just fine if they don&rsquo;t happen to be included in the same compilation unit. So you might be fine all along until you write some AI code that has control over the game flow. Oops!<br>
OK, so you can prefix all your enums like this:</p>
<pre tabindex="0"><code>enum GameFlowType
{
    GameFlowTypeRun,
    GameFlowTypeExit,
    GameFlowTypeRestart,
    GameFlowTypeRestore,
};
</code></pre><p>and</p>
<pre tabindex="0"><code>enum AIAction{
    AIActionEnter,
    AIActionExit,
    AIActionStop,
    AIActionWalk,
    AIActionRun,
};
</code></pre><p>That will technically fix the problem, but it&rsquo;s a bit ugly, and we&rsquo;re still polluting the global namespace (what if I wanted to have a class called AIActionEnter?).</p>
<p>Another potential solution is to score the enum inside the class that is using them. So we could have:</p>
<pre tabindex="0"><code>class AIAction{
public:
    enum AIActionType
    {
        Enter,
        Exit,
        Stop,
        Walk,
        Run,
    };
};
</code></pre><p>Much cleaner, do doubt, but also with its share of problems: First of all, it forces you to associate a set of enums with a class, which is not something you always want to do. But the biggest problem is that as soon as you have more than one set of enums per class, they all get promoted to the same scope:</p>
<pre tabindex="0"><code>class AIAction
{
public:
    enum AIActionBehavior
    {
        Enter,
        Exit,
        Stop,
        Walk,
        Run,
    };

    enum AIActionGroup
    {
        None,
        Self,
        Team,
        All,
    };
};
</code></pre><p>When we see one of those enums in code referred to as AIAction::Self, we really have no idea that it&rsquo;s referring to that group the action is applied to, as opposed to AIAction::Enter, which is the type of action.<br>
Our solution? Move all enums into a descriptive namespace.</p>
<pre tabindex="0"><code>namespace GameFlowType
{
    enum Enum
    {
        Invalid,
        Run,
        Exit,
        Restart,
        Restore,
    };
}
</code></pre><p>When you have a variable of that enum type, it&rsquo;s listed as GameFlowType::Enum type, which clearly indicates what it does. And its values are referred to as GameFLowType::Exit. You get the ideal scoping, you&rsquo;re not tied to any particular class, things are explicit but not verbose, you&rsquo;re no polluting the global namespace, and it&rsquo;s doesn&rsquo;t affect the runtime or compilation times.<br>
Sometimes the best solutions are the simplest ones.</p>]]></content:encoded></item><item><title>LeChimp's Secret Weapon: Lint</title><link>https://gamesfromwithin.com/lechimps-secret-weapon-lint/</link><pubDate>Tue, 15 Jan 2008 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/lechimps-secret-weapon-lint/</guid><description>&lt;p&gt;&lt;a href="../../../../node/25"&gt;LeChimp&lt;/a&gt; has been rocking my world lately. I&amp;rsquo;ve been checking in code that passes all the unit tests, confident that everything was fine, just to find out the functional test fails loudly and obnoxiously &lt;a href="#%5B1%5D"&gt;[1]&lt;/a&gt;. The other day it even managed to put the game in an infinite loop (yes, my fault). It might sound annoying, but I love it how LeChimp keeps us honest and makes subtle problems immediately obvious.&lt;/p&gt;
&lt;p&gt;A couple of months ago something unusual happened: The functional test failed but I wasn&amp;rsquo;t able to reproduce the problem right away. The failure was not a crash, but an object in the world ending up in a different state than expected. That&amp;rsquo;s always tougher to track down. To make things even more fun, was object was affected changed depending on whether the game was run from the command line or the debugger. Oh, and did I mention it only happened in release mode? I&amp;rsquo;ve got a baaad feeling about this!&lt;/p&gt;</description><content:encoded><![CDATA[<p><a href="../../../../node/25">LeChimp</a> has been rocking my world lately. I&rsquo;ve been checking in code that passes all the unit tests, confident that everything was fine, just to find out the functional test fails loudly and obnoxiously <a href="#%5B1%5D">[1]</a>. The other day it even managed to put the game in an infinite loop (yes, my fault). It might sound annoying, but I love it how LeChimp keeps us honest and makes subtle problems immediately obvious.</p>
<p>A couple of months ago something unusual happened: The functional test failed but I wasn&rsquo;t able to reproduce the problem right away. The failure was not a crash, but an object in the world ending up in a different state than expected. That&rsquo;s always tougher to track down. To make things even more fun, was object was affected changed depending on whether the game was run from the command line or the debugger. Oh, and did I mention it only happened in release mode? I&rsquo;ve got a baaad feeling about this!</p>
<p>My first instinct was to blame it on <a href="http://www.havok.com/content/view/17/30/">Havok</a>. After some investigating, I narrowed it down to one of the enemies that was in mid-air. Sometimes it would fall down, and other times it would stay hovering, as if not affected by gravity. I knew that Havok was supposed to be deterministic, but it&rsquo;s every programmer&rsquo;s instinct to always mistrust other people&rsquo;s code. I should have known better.</p>
<p>I spent a whole day tracking this down. Adding more and more information to the recorded world state to detect the problem as soon as possible. Slowly circling in; silently creeping up on the unsuspecting bug. Eventually, I had my â€œaha!â€ moment. I had finally found it.</p>
<p>A member variable, m_alive, in the RobotLogical class was never initialized! That was causing the Havok character controller not to be updated sometimes, causing the discrepancy in object state between the recording pass and the playback pass. What made it even more difficult is that m_alive is a boolean, so any bit pattern other than zero, it&rsquo;s going to make it true, which is the initial state I expected for the robots. It never failed in debug mode because unused heap memory is filled with patterns like 0xdeadbeef or (the definitely less fun, but more practical) 0xcdcdcdcd, which all make the variable come up as true. Doh!</p>
<p>Yes, C++ sucks because of time-wasters like that, but it didn&rsquo;t prevent me from feeling really stupid for having sunk a whole day on it.</p>
<p>All the code Charles and I write is done through TDD so we have almost 100% unit-test coverage <a href="#%5B2%5D">[2]</a>. How come Test Driven Development didn&rsquo;t catch that? TDD is not about catching bugs, it&rsquo;s about designing code. This is the type of error that is only triggered once every thousand times, so running one or two unit tests that cover that path probably won&rsquo;t trigger it. That&rsquo;s one of the many reasons end-to-end functional tests are invaluable. Go LeChimp!</p>
<h3 id="help-lechimp-help">Help, LeChimp! Help!</h3>
<p>Detecting there&rsquo;s a problem is good, but if it takes a whole day to fix it, things are going to be pretty painful. The more complicated the game gets, the more difficult life will be.</p>
<p>A good start is to crank up the warning level of your compiler as far as it goes. We&rsquo;re compiling everything with warning level 4 in VC2005, so we&rsquo;re already covered in that end <a href="#%5B3%5D">[3]</a>. Unfortunately, warning level 4 doesn&rsquo;t warn us about uninitialized member variables. We need something else.</p>
<p>Fortunately we have a secret weapon in our arsenal we had been ignoring: <a href="http://en.wikipedia.org/wiki/Lint_(software)">Lint</a>.</p>
<p>Lint performs static analysis of C++ programs and spews out lots and lots of warnings. Think of it as an extremely pedantic warning level on a C++ compiler. And I mean extremely! It will warn you not only of potential errors and dodgy constructs, but of best practices, and sometimes even of recommendations in books like Effective C++.</p>
<p>As you can imagine, with all those things to check against, Lint is going to find lots to complain about. So taming the output into something readable is a definite challenge.</p>
<p>When it comes to Linting your code, there are a few options available.</p>
<p><strong>Team Edition Compiler</strong></p>
<p>My friend Jim Tilander brought up that <a href="http://www.tilander.org/aurora/2006/08/lint-hidden-in-the-psdk.html">there&rsquo;s a Lint-like tool</a> hidden in the bowels of the <a href="http://www.microsoft.com/downloads/details.aspx?familyid=1D7F16B3-D2D5-48F7-9494-6696117EE712&amp;displaylang=en">Microsoft Platform SDK</a>. Boy, he wasn&rsquo;t kidding about the hidden part! It&rsquo;s a whopping 1.4 GB download for a DVD image that then needs to be extracted and installed in order to get to the small free compiler. When will Microsoft adopt a more modular approach?</p>
<p>Once I got past all the installation hurdles, I was pretty excited to give it a test. A free tool is a free tool. And if it has good integration with Visual Studio, so much the better. Strictly speaking, it&rsquo;s not really a Lint tool, but an optimizing compiler with a special /analyze switch, which performs a lot of the same checks as Lint. But as we know, a rose by any other name&hellip;</p>
<p>Right off the bat, it fell flat the moment I started using it. Apparently it doesn&rsquo;t know how to deal with vcproj files. To work on all the files in a project, I had to feed each cpp file separately. That in itself is only a slight annoyance, but it meant that you also need to pass it all the compiler switches set in the vcproj files: include directories, defines, etc. For a Microsoft product, I really would expect it to understand vcproj files. Oh well. It&rsquo;s not the end of the world. I can always write a quick script to do that for me.</p>
<p>Unfortunately, the next problem was more serious. There was no global way to control what warnings I wanted reported. I can disable specific warnings in the command line, but if I only care about a few, it gets really cumbersome.</p>
<p>Finally the killer: It simply doesn&rsquo;t report some of the most important warnings I expect out of Lint, such as uninitialized member variables or variables appearing in incorrect order in the initializer list.</p>
<p>In its defense, it had some decent features I would expect of good Lint tools, like the ability to suppress certain warnings from code or to give extra hits in the code itself. On the other hand, the way to control the behavior of the analyze switch is done with special keywords, which will make other compilers choke, making it harder to write cross-platform code. Somehow, I&rsquo;m not terribly surprised.</p>
<p>LeChimp&rsquo;s recommendation: Even for a free tool, it simply doesn&rsquo;t stand up to any serious use. Skip it.</p>
<p><strong>PC Lint</strong></p>
<p>Discouraged from the few hours I spent in the Team Edition compiler fiasco, I turned to <a href="http://www.gimpel.com/">Gimpel Software</a> <a href="http://www.gimpel.com/">PC Lint</a>.</p>
<p>Don&rsquo;t be put off by PC Lint&rsquo;s archaic web site that seems to be snatched straight out of 1995 <a href="#%5B4%5D">[4]</a>. PC Lint has been around forever and it shows. Not just in their web site, but in the program itself. Don&rsquo;t expect any fancy GUIs, or dialog boxes, or any fancy cyber-amenities developed in the last 20 years.</p>
<p>Still, what it lacks in sophistication and pleasing visuals it more than makes up in functionality: Three minutes, $239, and a 4MB download later, I was ready to go.</p>
<p>In about an hour, I had PC Lint fully integrated with our build server and checking for problems in all of our source code. In just half an hour more, all our code was passing Lint&rsquo;s rigorous inspection.</p>
<p>PC Lint can be quite intimidating out of the (virtual) box. If you run it on a typical codebase (or even a really high-quality one), it will treat you to megabytes of warning spew. Most of it useless, I have to say. So you have to take some time and tame it. Teach it to be a bit more polite, or more relevant. Or at least not to yell so much.</p>
<p>My preference is to start out with no warnings by starting out the options.lnt file with -e* and then add warning messages that I find useful: uninitalized member variables, unreferenced symbols, gotchas with virtual functions, etc..</p>
<p>Even running Lint with a small number warnings enabled, there were a few places in our code that caused PC Lint to complain but we didn&rsquo;t want to change (Vec4 really shouldn&rsquo;t initialize any member variables in its default constructor, or the NonCopyable class shouldn&rsquo;t have a virtual destructor). In those cases, we can add a few discrete comments directly in the code that tell Lint to be quiet. We know what we&rsquo;re doing, Lint. Really.</p>
<p>After we got all the code passing the initial set of checks, Charles dug into the Lint options file with a gleeful glint in his eyes and became the Lint-nazi, adding a good couple dozen extra warnings. It only took a few more minutes to get all the code to pass all the new checks. Frankly, the slowest part of the process is reading the thousands of different checks that PC Lint can do and decipher them (there are a couple of them I&rsquo;m still unsure what exactly they mean).</p>
<p>This is what our options.lnt file looks like today:</p>
<pre tabindex="0"><code>-d__debugbreak()=
-e*

+e539  // Did not expect positive indentation from Location
+e549  // Suspicious cast
+e616  // control flows into case/default
+e744  // switch statement has no default
+e750  // local macro &#39;Symbol&#39; (Location) not referenced
+e751  // local typedef &#39;Symbol&#39; (Location) not referenced
+e752  // local declarator &#39;Symbol&#39; (Location) not referenced
+e753  // local struct, union or enum tag &#39;Symbol&#39; (Location) not referenced
+e764  // switch statement does not have a case
+e766  // Include of header file FileName not used in module String
+e767  // macro &#39;Symbol&#39; was defined differently in another module
+e773  // Expression-like macro &#39;Symbol&#39; not parenthesized
+e777  // Testing floats for equality
+e783  // Line does not end with new-line
+e784  // Nul character truncated from string
+e789  // Assigning address of auto variable &#39;Symbol&#39; to static
+e796  // Conceivable access of out-of-bounds pointer
+e797  // Conceivable creation of out-of-bounds pointer
+e801  // Use of goto is deprecated
+e802  // Conceivably passing a null pointer to function &#39;Symbol&#39;
+e803  // Conceivable data overrun for function &#39;Symbol&#39;
+e804  // Conceivable access beyond array for function &#39;Symbol&#39;
+e806  // Small bit field is signed rather than unsigned
+e814  // useless declaration
+e815  // Arithmetic modification of unsaved pointer
+e817  // Conceivably negative subscript (Integer) in operator &#39;String&#39;
+e818  // Pointer parameter &#39;Symbol&#39; (Location) could be declared ptr to const
+e820  // Boolean test of a parenthesized assignment
+e825  // control flows into case/default without -fallthrough comment
+e940  // omitted braces within an initializer
+e954  // Pointer variable &#39;Symbol&#39; (Location) could be declared as pointing to a const

// TURN THESE ON IF WE CAN FIGURE OUT HOW TO APPLY IT ONLY TO VALUES AND NOT POINTERS!
//+e952  // Parameter &#39;Symbol&#39; (Location) could be declared const
//+e953  // Variable &#39;Symbol&#39; (Location) could be declared as const

+e1401 // member symbol &#39;Symbol&#39; (Location) not initialized by constructor
+e1404 // deleting an object of type &#39;Symbol&#39; before type is defined
+e1411 // Member with different signature hides virtual member &#39;Symbol&#39;
+e1413 // function &#39;Symbol&#39; is returning a temporary via a reference

+e1506 // Call to virtual function &#39;Symbol&#39; within a constructor or destructor
+e1507 // attempting to &#39;delete&#39; an array (not a pointer)
+e1509 // base class destructor for class &#39;Name&#39; is not virtual
+e1511 // Member hides non-virtual member &#39;Symbol&#39; (Location)
+e1512 // destructor for base class &#39;Symbol&#39; (Location) is not virtual
+e1516 // Data member hides inherited member &#39;Symbol&#39; (Location)
+e1520 // Multiple assignment operators for class &#39;Symbol&#39;
+e1521 // Multiple copy constructors for class &#39;Symbol&#39;
+e1534 // static variable &#39;Symbol&#39; found within inline function in header
+e1535 // Exposing low access data through member &#39;Symbol&#39;
+e1537 // const function returns pointer data member &#39;Symbol&#39;
+e1538 // base class &#39;Name&#39; absent from initializer list for copy constructor
+e1539 // member &#39;Symbol&#39; (Location) not assigned by assignment operator
+e1541 // member &#39;Symbol&#39; (Location) possibly not initialized by constructor
+e1542 // member &#39;Symbol&#39; (Location) possibly not initialized
+e1543 // member &#39;Symbol&#39; (Location) possibly not initialized
+e1544 // value of variable &#39;Symbol&#39; (Location) indeterminate (order of initialization)
+e1545 // value of variable &#39;Symbol&#39; used previously to initialize variable &#39;Symbol&#39; (Location)
+e1547 // Assignment of array to pointer to base class (Context)
+e1552 // Converting pointer to array-of-derived to pointer to base
+e1554 // Direct pointer copy of member &#39;Symbol&#39; within copy constructor
+e1555 // Direct pointer copy of member &#39;Symbol&#39; within copy assignment operator
+e1556 // &#39;new Type(integer)&#39; is suspicious
+e1557 // const member &#39;Symbol&#39; is not initialized
+e1561 // Reference initialization causes loss of const/volatile integrity

+e1705 // static class member may be accessed by the scoping operator
+e1706 // Declaration with scope operator is unusual within a class
+e1707 // static assumed for String
+e1710 // An implicit &#39;typename&#39; was assumed
+e1711 // class &#39;Symbol&#39; (Location) has a virtual function but is not inherited
+e1718 // expression within brackets ignored
+e1719 // assignment operator for class &#39;Symbol&#39; has non-reference parameter
+e1720 // assignment operator for class &#39;Symbol&#39; has non-const parameter
+e1724 // Argument to copy constructor for class &#39;Symbol&#39; should be a const reference
+e1726 // taking address of overloaded function name &#39;Symbol&#39;
+e1729 // Initializer inversion detected for member &#39;Symbol&#39;
+e1734 // Had difficulty compiling template function: &#39;Symbol&#39;
+e1736 // Redundant access specifier (String)

+e1931 // Constructor &#39;Symbol&#39; can be used for implicit conversions
</code></pre><p>I originally only had about a dozen warnings enabled, but, as you can see, Charles really went to town with it :-)</p>
<p>To integrate it into our functional test, we just set up a new target in msbuild. For each project, we call it twice: once to generate a lnt file for the project, and once to run it on the files for the project.</p>
<pre tabindex="0"><code>&lt;PropertyGroup&gt;
    &lt;LintDir&gt;..\Bin\Lint\&lt;/LintDir&gt;
    &lt;Lint&gt;$(LintDir)lint-nt.exe&lt;/Lint&gt;
&lt;/PropertyGroup&gt;

&lt;ItemGroup&gt;
    &lt;ProjectFiles Exclude=&#34;..\Engine\**\*Tests.vcproj&#34;
                  Include=&#34;Src\SweetPea.vcproj;..\Engine\**\*.vcproj;&#34;/&gt;
&lt;/ItemGroup&gt;

&lt;Target Name=&#34;Lint&#34; DependsOnTargets=&#34;CleanLint;RunLint&#34;/&gt;

&lt;Target Name=&#34;CleanLint&#34;&gt;
    &lt;Delete Files=&#34;%(ProjectFiles.RelativeDir)%(ProjectFiles.Filename).lnt&#34;/&gt;
&lt;/Target&gt;

&lt;Target Name=&#34;RunLint&#34; Inputs=&#34;@(ProjectFiles)&#34;
        Outputs=&#34;@(ProjectFiles -&gt; %(ProjectFiles.RelativeDir)%(ProjectFiles.Filename).lnt)&#34; &gt;
    &lt;Exec Command=&#34;$(Lint) -v -os(%(ProjectFiles.RelativeDir)%(ProjectFiles.Filename).lnt) %(ProjectFiles.Identity)&#34;/&gt;
    &lt;Exec WorkingDirectory=&#34;%(ProjectFiles.RelativeDir)&#34;
          Command=&#34;$(MSBuildProjectDirectory)\$(Lint) -i$(MSBuildProjectDirectory)\$(LintDir) std.lnt %(ProjectFiles.Filename).lnt&#34;/&gt;
&lt;/Target&gt;
</code></pre><p>Whenever PC Lint detects some code that violates one of its rules, it returns an error message, which fails the msbuild target and the whole build is reported as failed by Cruise Control .Net. I love it when things work exactly like you want them to without doing any extra work. To make it even better, because PC Lint can output errors in VC++ format, they&rsquo;re understood and parsed correctly by msbuild and CCNet, so they show up in the CCNet log like any other error.</p>
<p><img loading="lazy" src="/lechimps-secret-weapon-lint/images/lint.png" title="lint"></p>
<p>PC Lint runs surprisingly fast. It takes about 20 seconds to run on all of our source code. I was almost tempted to add it to the incremental build in the build server, but I really want to keep build times to a minimum there, so it runs once every hour, which seems to be good enough.</p>
<p>If you want to be more hands-on with PC Lint, it&rsquo;s a breeze to integrate with Visual Studio. Just set up a few custom commands in External Tools and you&rsquo;re good to go. The Visual Studio Lint options file even details exactly how to set up those commands.</p>
<p>My only minor complaint with PC Lint is the strange behavior of error 766 (Include of header file not used in module). I don&rsquo;t know what algorithm PC Lint uses to determine that, but it seems not to report some unused headers. That wouldn&rsquo;t be a big deal, but sometimes just rearranging headers or moving some code around will cause it to recognize a header as unused, triggering a failed build. It&rsquo;s <a href="/physical-structure-and-c-part-1-a-first-look/%20">a very useful warning though</a>, so I&rsquo;m willing to live with that quirk.</p>
<p>Working with PC Lint is a pleasure. It&rsquo;s really low level and old school, but that&rsquo;s precisely what made it so easy to integrate with our code and our build system. It doesn&rsquo;t need installation programs, databases, registry entries, dll deployments, or anything like that. Just a good-ol&rsquo; ini file with options and you&rsquo;re good to go. We even have it checked it in version control to make it easier to deploy to our development stations and the build server.</p>
<p>PC Lint has the characteristics I want in a tool: Easy to buy, deploy, and integrate into the way I want to work with it.</p>
<p>LeChimp&rsquo;s recommendation: An absolute must! Worth every penny. Two opposable thumbs up!</p>
<h3 id="other-lint-alternatives">Other Lint Alternatives</h3>
<p>Lint was originally a Unix utility developed in the late 70s. You would expect that lots of different versions would be available for modern compilers and platforms, but there aren&rsquo;t that many. Maybe it&rsquo;s not a really fun project to engage enough Open Source hackers?</p>
<p>I have to admit I haven&rsquo;t looked at any other alternatives to PC Lint and the Team Edition Compiler that work under Windows. A quick Google search reveals there are a few tools out there. Has anybody tried them? I&rsquo;d love to hear your experiences with them.</p>
<ul>
<li><a href="http://www.splint.org/">Splint.</a> Only works on C. Emphasis on security. Open source.</li>
<li><a href="http://www.abxsoft.com/codchk.htm">CodeCheck</a>. Works on C++. Commercial.</li>
<li><a href="http://www.aristeia.com/ddjpaper1_frames.html">A bunch for Linux/Unix</a>. As much as I&rsquo;d like to, the reality is that most game development happens under Windows.</li>
</ul>
<h3 id="conclusion-lechimp-rules-the-day-again">Conclusion: LeChimp Rules The Day (Again)</h3>
<p>PC Lint should be a requirement for any C++ project. The day you set up a build server (which should be the first day), go ahead and spend the extra hour setting up PC Lint as well. Be safe up front and avoid wasting any time down the line. We should have followed our own advice, but sometimes priorities slip a bit in the rush of getting a whole company off the ground.</p>
<p>Now I can finally sleep better knowing that LeChimp is keeping busy linting my code several times a day.</p>
<p>[1] <a href="http://www.siberkat.com/thewavszim/meetdoomz.wav">This</a> is our current broken build sound bite.</p>
<p>[2] There are some things we don&rsquo;t bother TDDing: main functions, super-high level leaf code, etc.</p>
<p>[3] Of course, you need to have a <strong>clean</strong> compile in warning level 4 in order to be worth it. That means builds without any warnings or other spew. Incidentally, I do hate the setting to treat warnings as errors because it means you can&rsquo;t temporarily have warnings while you&rsquo;re refactoring between checkins, which slows things down.</p>
<p>[5] That was just a wild guess, but it seems it really <a href="http://web.archive.org/web/19961222013655/http://gimpel.com/">wasn&rsquo;t that different in 1996</a>.</p>]]></content:encoded></item><item><title>LeChimp vs. Dr. Chaos</title><link>https://gamesfromwithin.com/lechimp-vs-dr-chaos/</link><pubDate>Mon, 24 Dec 2007 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/lechimp-vs-dr-chaos/</guid><description>&lt;p&gt;It&amp;rsquo;s no secret that I&amp;rsquo;m a big fan of unit tests. They provide a huge safety net for refactorings, double check the code logic, and prevent &lt;a href="http://en.wikipedia.org/wiki/Software_rot"&gt;code rot&lt;/a&gt;. In addition, unit tests written through &lt;a href="https://gamesfromwithin.com/backwards-is-forward-making-better-games-with-test-driven-development/"&gt;Test-Driven Development&lt;/a&gt; help define the architecture and keep programmers happy. They&amp;rsquo;ll even catch a bug or two along the way, but if you rely on them as your only way to catch bugs, you&amp;rsquo;re in for a surprise.&lt;/p&gt;</description><content:encoded><![CDATA[<p>It&rsquo;s no secret that I&rsquo;m a big fan of unit tests. They provide a huge safety net for refactorings, double check the code logic, and prevent <a href="http://en.wikipedia.org/wiki/Software_rot">code rot</a>. In addition, unit tests written through <a href="/backwards-is-forward-making-better-games-with-test-driven-development/">Test-Driven Development</a> help define the architecture and keep programmers happy. They&rsquo;ll even catch a bug or two along the way, but if you rely on them as your only way to catch bugs, you&rsquo;re in for a surprise.</p>
<h3 id="bug-hunting">Bug Hunting</h3>
<p>Unit tests, by their very nature, are limited to a single class or function at the time. There are all sorts of complex interactions between objects and systems that they simply can&rsquo;t test. Even if you use <a href="http://en.wikipedia.org/wiki/Mock_object">mock objects</a> and are extremely careful to test all your object interactions, there will be lots of unexpected cases and bugs that crawl out while running the game under real world conditions. Dr. Chaos is alive and well.</p>
<p>Besides, unit tests just test that the code does what you think it should do. So if the algorithm you have in your head is completely wrong, they&rsquo;ll just make sure that the implementation is as broken as you imagined. Bugs like that might only surface once the code is put in the context of the whole game and interacts with other systems.</p>
<p>Traditionally, game companies rely on QA to uncover and squash most of the bugs created by complex interactions. You know, the type of bug that gets only triggered when the player enter the cave while there&rsquo;s a blue moon and he spun around in place a seven times. Not only is this is an expensive process, but it&rsquo;s not even very good at uncovering all the bugs. Most games have millions and millions of combinations of possibilities and interactions, and it&rsquo;s completely impractical to try to run through all of them by hand.</p>
<h3 id="our-hero-lechimp">Our Hero: LeChimp</h3>
<p>At Power of Two Games it&rsquo;s just two of us. So no QA or even interns to play the game endlessly. But, even in preproduction, we can&rsquo;t afford to ignore those types of bugs. Instead, we enlisted the help of our hero: LeChimp.</p>
<p>LeChimp is our functional test server. It tirelessly runs the game every couple of hours and makes sure it loads and runs without any problem. Sure, ideally it should run more frequently, but LeChimp doubles up as our build server, and we don&rsquo;t have another good computer to spare (maybe if y&rsquo;all <a href="http://www.powerof2games.com/product">bought more t-shirts</a> we could afford to buy another cheapo Dell).</p>
<p>Running the game is a good start. It checks that it&rsquo;s possible to load every level and that nothing crashes. Frankly, that&rsquo;s a good percentage of what QA does a lot of the time, and a lot of teams would really benefit from having such a simple test and know as soon as a level stops loading. Still, it we can do much better than that.</p>
<h3 id="monkey-business">Monkey business</h3>
<p><img alt="lechimp" loading="lazy" src="images/monkey.jpg">LeChimp runs the game for a fixed number of frames, and makes sure the game doesn&rsquo;t crash or hits any asserts. But running the game without any action going on is not very useful, so it runs it with the -monkey switch, which feeds pseudo-random input to the game, as if a monkey were playing the game.</p>
<p>Actually, the input from -monkey is not random at all. I first made it truly random by generating new inputs through std::rand() every frame, but it looked more like a monkey on crack was playing the game and the characters shook violently back and forth and never managed to do anything interesting. Instead, now the monkey input holds the controller sticks and the buttons for some varying time interval, and it looks more like a monkey without its ADD medicine, which is clearly a step up.</p>
<p>When I first heard of this technique at a GDC tutorial a few years ago, I thought it would be pretty useless. How many bugs could feeding random input to the game really uncover? Shouldn&rsquo;t we try to be doing something more intelligent to mimic how players interact with the game? But since it was really easy to implement I decided to give it a try. Boy, was I in for a treat! Within a few runs, it uncovered several major bugs that nobody hadn&rsquo;t seen during their runs of the game. Since then, there isn&rsquo;t a game I work on that doesn&rsquo;t get treated with some monkey input love..</p>
<p>It&rsquo;s so simple to implement that if you haven&rsquo;t done it already, I really encourage you to go and do it right away. Do it over your next lunch break even. I guarantee you&rsquo;ll be amazed at what it uncovers (or I&rsquo;ll refund your money for this article :-).</p>
<h3 id="recording-for-posterity">Recording for posterity</h3>
<p>In addition to just trying to crash the game, LeChimp records all the inputs and the state of the game at every frame. Then, after running the game for a while, it runs it again, feeding it the recorded input, and verifies that the game is in the same state as it was during the recording session (every enemy is in the same place, every prop has the same orientation, every player has the same health, etc). This verifies that the game is fully deterministic, that is, given the same inputs, it always produces the same output.</p>
<p>We&rsquo;re planning on some cool features that rely on the game being fully deterministic, so this something very important to us. But even if we weren&rsquo;t planning on doing anything with it, determinism is an extremely useful feature to have when it comes time to track down bugs. Instead of getting lengthy descriptions of a crash from testers (which somehow always seems impossible to reproduce), they can include the playback file that lead to the crash along with the bug report, allowing us to catch it in the debugger in no time. Of course, it&rsquo;s not like we have actual testers, but we affectionately think of LeChimp as one, and he&rsquo;s always very careful to save all his playback files with every functional test run.</p>
<p>Right now we&rsquo;re just recording the inputs to the game: delta time every frame and controller inputs. Just with that, the game runs exactly the same time in and time out (thanks to Havok for being deterministic!). Things get more complicated as soon as multiple threads are involved, since the exact timing of context switches between threads can affect the output. Some tools out there, like <a href="http://www.replaysolutions.com/technology/replay-director-gaming.php">ReplayDirector</a> claim to address this, but I haven&rsquo;t looked into it very much.</p>
<p>Both the input file and the same state file are opened, written to, and closed every frame. That way there is no data loss if the game crashes unexpectedly and you get all the input leading up to that frame.</p>
<p>As far as checking that the world state is the same, it&rsquo;s totally an ad-hoc process. We simply pick some of the obvious state and save them to a file: player positions, enemy position, props transforms, etc. If we ever see something get out of sync, we add it to the game state that gets saved and compared so it doesn&rsquo;t happen in the future.</p>
<h3 id="no-waiting-around">No waiting around</h3>
<p>So far we have LeChimp running the following with every functional test:</p>
<pre tabindex="0"><code>sweetpea -frames=10000 -record=functional_test -monkey -level=level_name
</code></pre><p>followed by</p>
<pre tabindex="0"><code>sweetpea -playback=functional_test -level=level_name
</code></pre><p>At 60 Hz, running 10,000 frames is almost three minutes. 10,000 is just a number we pulled out of a hat. The longer you let the monkey loose with the game, the better the chance of uncovering something. Multiply that by the number of levels and sandboxes, and the functional test now takes quite a while to complete.</p>
<p>A good chunk of the time of the functional test is spent rendering each frame and waiting for the vertical sync signal. But nobody is actually looking at the output <a href="#%5B2%5D">[2]</a>, so why bother?</p>
<p>We added a couple more command line switches to make the game run without rendering or waiting on vsync. To make that really useful, we also added the ability to force the frame time to be a fixed timestep. So we can run the game like this:</p>
<pre tabindex="0"><code>sweetpea -frames=10000 -record=functional_test -monkey -level=level_name -render=no -vsync=no -timestep=0.01566
</code></pre><p>The game will cruise through the simulation as fast as possible, often cramming all three minutes of gameplay into 10 seconds or so. Perfect for poor monitor-less LeChimp.</p>
<h3 id="testing-testing">Testing, testing</h3>
<p>There&rsquo;s even more to LeChimp that just monkeying around. It also runs several other functional tests checking some high-level functionality:</p>
<ul>
<li>
<p>Player attacks. The player character attacks enemies using each different type of attack and verifies that each attack is successful. This is particularly useful when there are a few types of attacks (which themselves are unit tested), but there are many combinations that can be created between attacks and targets.</p>
</li>
<li>
<p>Level restart. LeChimp loads a level and then restarts it hundreds of times, checking for crashes and memory leaks.</p>
</li>
<li>
<p>Torture chamber. A tiny level in which the hero (in god mode) frantically mows down hundreds of enemies that get immediately respawned. This is a perfect stress test for performance and hardcoded limits.</p>
</li>
</ul>
<p>We&rsquo;re writing these tests as we go along. Whenever there&rsquo;s a feature that seems complex enough, or that it relies on other systems, or that it seems to break repeatedly, we take a few minutes, write a new functional test, and throw it to LeChimp to run with all the others.</p>
<p>Functional tests like these are about as high level as it gets. They deal with actions such as &ldquo;move the player to the right&rdquo;, &ldquo;spawn an enemy here&rdquo;, or &ldquo;perform special attack XXX&rdquo;, so it would make sense to implement them in the same way you implement game logic (which in our case is still C++, although we&rsquo;re considering a switch to Lua in some not very distant future).</p>
<h3 id="long-live-lechimp">Long Live LeChimp</h3>
<p>LeChimp has been invaluable battling against Dr. Chaos. Several times I made a refactoring or introduced a new feature, all the unit tests passed, I checked it in, and a little while later LeChimp screams at us that something is wrong. Once we see the functional test fail, it&rsquo;s usually pretty obvious how to fix it: a memory pool is too small, or a combination of events that causes the player to enter some unexpected state. Fixing it is a matter of writing a unit test, fixing the logic, and checking it in, all in a few minutes.</p>
<p>A few times, however, the problem hasn&rsquo;t been that obvious. The world gets out of sync, but only in release mode. Running it from the debugger often results in yet a different state. Sounds like some annoying memory overwrite, or perhaps some uninitialized memory. Any programmer who&rsquo;s had to deal with this before probably has shivers running down his back. Fortunately, LeChimp has a secret weapon in its arsenal to deal with that. But that&rsquo;s another story and shall be told another time.</p>
<p>Until then, happy holidays, everybody!</p>
<p>[1] Don&rsquo;t underestimate the power of keeping programmers happy! At a previous company I used to work for, a manager rewarded one of the programmers by buying him a DVD set of a TV show he was really into. That was only about $40, but they had a huge effect on the programmer&rsquo;s morale and productivity. Talk about well-spent money.</p>
<p>[2] LeChimp doesn&rsquo;t even have a monitor, although that sucks sometimes. RemoteDesktop is pretty cool, but it locks up the DirectX surfaces in some weird way, and then the graphics renderer refuses to initialize correctly. So we&rsquo;re forced to use&hellip; get this&hellip; NetMeeting! With fake phone rings and all! Ring, ring, calling LeChimp&hellip;</p>]]></content:encoded></item><item><title>Office Tools for Starving Startups</title><link>https://gamesfromwithin.com/office-tools-for-starving-startups/</link><pubDate>Mon, 13 Aug 2007 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/office-tools-for-starving-startups/</guid><description>&lt;p&gt;Yes, we&amp;rsquo;re a starving startup. There&amp;rsquo;s nothing wrong with that. It&amp;rsquo;s actually quite good: we don&amp;rsquo;t have any venture capital investment, and we&amp;rsquo;re running purely from savings out of our own pockets. On the flip side, we have full control over our company, and we can decide what do do and how to run it.&lt;/p&gt;
&lt;p&gt;Of course, we&amp;rsquo;re far from loaded with money, so keeping expenses to a minimum is definitely a top priority. It&amp;rsquo;s not coincidence that one of our most popular lunches is sharing a gigantic $5 sub at &lt;a href="http://www.menushark.com/%5Crestaurant.php?id=157&amp;amp;city=Encinitas"&gt;Manhattan Giant Pizza&lt;/a&gt; or the $3.50 &lt;a href="http://mmm-yoso.typepad.com/mmmyoso/2006/07/kealanis.html"&gt;Kealani&amp;rsquo;s&lt;/a&gt; chicken teriyaki sandwich (fortunately, they&amp;rsquo;re actually delicious too!).&lt;/p&gt;
&lt;p&gt;Whenever it makes sense, we&amp;rsquo;ve opted for the most inexpensive options&lt;a href="#%5B1%5D"&gt;[1]&lt;/a&gt;: plastic workbenches from Costco for our desks, lights from Ikea with unpronounceable names, an outdated P3 that became our file server given to us by a friend, or a free scanner/printer donated by my girlfriend.&lt;/p&gt;
&lt;p&gt;So when it came time to set up our office tools, we also looked for the most inexpensive solution that met all our needs.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Yes, we&rsquo;re a starving startup. There&rsquo;s nothing wrong with that. It&rsquo;s actually quite good: we don&rsquo;t have any venture capital investment, and we&rsquo;re running purely from savings out of our own pockets. On the flip side, we have full control over our company, and we can decide what do do and how to run it.</p>
<p>Of course, we&rsquo;re far from loaded with money, so keeping expenses to a minimum is definitely a top priority. It&rsquo;s not coincidence that one of our most popular lunches is sharing a gigantic $5 sub at <a href="http://www.menushark.com/%5Crestaurant.php?id=157&amp;city=Encinitas">Manhattan Giant Pizza</a> or the $3.50 <a href="http://mmm-yoso.typepad.com/mmmyoso/2006/07/kealanis.html">Kealani&rsquo;s</a> chicken teriyaki sandwich (fortunately, they&rsquo;re actually delicious too!).</p>
<p>Whenever it makes sense, we&rsquo;ve opted for the most inexpensive options<a href="#%5B1%5D">[1]</a>: plastic workbenches from Costco for our desks, lights from Ikea with unpronounceable names, an outdated P3 that became our file server given to us by a friend, or a free scanner/printer donated by my girlfriend.</p>
<p>So when it came time to set up our office tools, we also looked for the most inexpensive solution that met all our needs.</p>
<h2 id="email">Email</h2>
<p>Our requirements for our email solution were:</p>
<ul>
<li>
<p>Minimize costs. Not just the software, but the hardware needed to run any severs, support, etc.</p>
</li>
<li>
<p>Minimize maintenance. We&rsquo;re our own IT staff, so the less time we have to spend screwing around with severs and updates, the more time we can spend coding and designing the game.</p>
</li>
<li>
<p>Reliable. This, after all, is going to be used to send company emails, contracts out to outsourcing companies, responses to publishers, etc. We don&rsquo;t want to be missing any emails.</p>
</li>
<li>
<p>Good search capabilities.</p>
</li>
<li>
<p>Available from any location. I guess that implies a web front end.</p>
</li>
<li>
<p>Fully integrated with our domain powerof2games.com.</p>
</li>
</ul>
<p>In the past, the companies we had worked at all used Microsoft Exchange and Outlook or the god-awful Lotus Notes. Apart from having to endure the torture of using these day in and day out, they&rsquo;re quite expensive, so we looked for alternatives.</p>
<p>We could use the email server provided by our web hosting company. It would give us the bare bones functionality that we needed, including some form of <a href="http://www.squirrelmail.org/">web front end</a>. It could work, but after using Gmail for personal email for several years, it felt like a major step backwards.</p>
<p>Since Charles and I were already using Gmail for our personal accounts, we thought of creating a new account for Power of Two Games, but having <a href="mailto:pow2games@gmail.com">pow2games@gmail.com</a> in all our business emails doesn&rsquo;t exactly look very professional.</p>
<p>That&rsquo;s when we found out about <a href="http://www.google.com/a/smallbiz/">Google Apps for small business</a>. It&rsquo;s a free service offered by Google that allows integration of Gmail into your domain and use it as your corporate email. That seemed too good to be true. Gmail is hands down the best email web interface I have ever used, so the thought of using it as the company email was extremely tempting.</p>
<p>Setting up Gmail took a bit of messing around with some DNS advanced settings. All email sent to powerof2games.com had to be routed to Google somehow, so we had to set up a custom MX record in our web host and point it to Google&rsquo;s servers.</p>
<p>We also wanted to access our email through a nice URL like mail.powerof2games.com instead of some long (and hard to remember) default URL going through Google. For that, we had to add a CNAME record pointing the new mail subdomain to ghs.google.com.</p>
<p><img loading="lazy" src="images/gmail_1%5C%281%5C%29.png"></p>
<p>Once all that was set up, Gmail was up and running and fully integrated with our Power of Two domain. Not only that, but it was totally independent of our personal Gmail accounts, so we can even have them both open in different tabs in the same browser. Good job, Google!</p>
<h2 id="calendar">Calendar</h2>
<p>Gmail was just the tip of the iceberg. By going the Google route, we also get <a href="http://www.google.com/googlecalendar/overview.html">Google Calendar</a> for our domain. And Google Calendar totally rules. It&rsquo;s not like we were planning on scheduling company meetings at all hours of the day (although, technically, since we&rsquo;re in the same office I guess we&rsquo;re in a permanent meeting). But Calendar comes in really handy to put down big milestones, remind us to pay the rent, or keep track who we&rsquo;re having lunch with this week.</p>
<p>Calendar works out of the &ldquo;box&rdquo; without any extra set up. The only thing we did was to create a custom subdomain to access it through calendar.powerof2games.com, so we did the same trick as for our mail subdomain with the CNAME entry.</p>
<p>I can even share the Power of Two Calendar with my personal Google Calendar account and see all my events combined in a single place. My whole life in a single web page. Very handy!</p>
<h2 id="extras">Extras</h2>
<p>But wait, there&rsquo;s more. We&rsquo;re not always working at the office at the same time. Sometimes we&rsquo;ll work from home for a few hours in the morning before walking down to the office, or maybe I&rsquo;ll do some work from <a href="http://www.estreetcafe.com/index.jsp">E Street</a> late in the evening with an oatmeal chocolate chip cookie and some live music. At those times, it&rsquo;s very helpful to be within easy reach of communication, and since we&rsquo;re using Gmail, we get Gmail chat for free.</p>
<h2 id="documents">Documents</h2>
<p>I&rsquo;m usually very hesitant of &ldquo;integrated solutions&rdquo;. I always prefer to be able to mix and match programs, components, or whatever instead of going the route of vendor lock-in. And the truth is that the different Google components are totally optional, but it&rsquo;s curious that we&rsquo;re biting, hook, line, and sinker all the way into Google&rsquo;s office suite.</p>
<p>I was thinking we would end up using <a href="http://www.openoffice.org/">OpenOffice.org</a>, which is a great Microsoft Office clone. But we gave a try to Google Documents and Spreadsheets and we were totally impressed.</p>
<p>Not only has Google Documents reached point as far as features and user interface that they&rsquo;re usable for real-world situations, but they offer a lot more functionality.</p>
<ul>
<li>
<p>It&rsquo;s a web-based app, so we can edit the documents from any computer with web access.</p>
</li>
<li>
<p>We can collaborate on the same document at the same time, which came in very handy when we were both working on the Sony Developer Program application document.</p>
</li>
<li>
<p>Because it&rsquo;s a Google product, you can search through the contents of all your documents and spreadsheets very easily.</p>
</li>
<li>
<p>Tagging and sorting. You can tag any document with any set of labels and then sort or filter by them. I&rsquo;m glad the days of hierarchical trees for organizing information are coming to an end.</p>
</li>
<li>
<p>Exporting to a variety of formats (MS Office, pdf, etc) comes in very handy when we need to send a document to somebody else who is not using Google.</p>
</li>
</ul>
<p>There are only a few things we wish it did differently, like being able to upload a pdf document (even if it&rsquo;s just in read-only mode for archiving and searching purposes). The other odd quirk is that we can&rsquo;t make all documents and spreadsheets shared by default between the two of us. Instead, we need to explicitly share them. Oh well. I guess they have bigger companies than us in mind. I don&rsquo;t blame them.</p>
<p>It&rsquo;s very encouraging to see these applications grow and get better week after week. Just a few months ago, Google Spreadsheets couldn&rsquo;t do plots, but they added that functionality since then. They&rsquo;ve also improved the whole front end with the tagging and listing of documents.</p>
<h2 id="voice-communication">Voice communication</h2>
<p>How the times have changed. When we started Power of Two Games, we didn&rsquo;t even bother with a phone. Even though we ended up contracting a DSL Internet connection and getting a voice phone line would have been extremely easy, we simply didn&rsquo;t need it. We were simply using our cell phones for the few times when email communication or chat wasn&rsquo;t good enough.</p>
<p>But as we started outsourcing art and talking to console manufacturers, we started having the need to do voice conferences and calling internationally. After a couple, very uncomfortable, conference calls using the speakerphone on our cellphone, we decided that we really had to look for a better solution.</p>
<p>For once, Google didn&rsquo;t have the solution for us (although wait a couple of years and see). I have been using <a href="http://www.skype.com/">Skype</a> to call internationally for quite a while with great results, so it was natural that we would look at it as our first option. Again, we were pleasantly surprised: not only could we make very inexpensive international calls (with great voice quality), but for a small yearly fee we can get <a href="http://www.skype.com/products/skypein/">SkypeIn</a> and have anybody call us from a regular phone.</p>
<h2 id="conclusion">Conclusion</h2>
<p>We&rsquo;re extremely pleased with how Google Apps and Skype have been working for us so far. They fit our needs perfectly and the cost is right. We were able to set things up in about a morning and never have to fuss with it again. How good is that?</p>
<p>I really don&rsquo;t see why Google Apps wouldn&rsquo;t work for a larger company. But companies seem to be stuck in the Exchange/Microsoft Office (or some other heavyweight and expensive server solution) choice. I wonder if there&rsquo;s a good reason for that other than inertia.</p>
<p>We&rsquo;re certainly happy to have these services available for free and being about to spend our time and money in what really matters: Creating a kick-ass game and getting it out the door.</p>
<p><strong>Notes</strong></p>
<p>[1] There are some things where going rock-bottom cheap doesn&rsquo;t make any sense though. The $7 desktop speakers we bought online were quite the surprise. I wasn&rsquo;t expecting top quality sound, but they sounded like those two way radios that security guards use. I didn&rsquo;t even know they made speakers that bad! Also, we have &ldquo;splurged&rdquo; on 24&quot; LCD monitors and comfortable chairs (and even so, always trying to find the cheapest price point for what we want), because those things make a world of difference when you&rsquo;re using them many hours every day.</p>]]></content:encoded></item><item><title>Prototyping for Fun And Profit</title><link>https://gamesfromwithin.com/prototyping-for-fun-and-profit/</link><pubDate>Tue, 08 May 2007 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/prototyping-for-fun-and-profit/</guid><description>&lt;p&gt;So here we are, ready to start development of our first game. We have the time, the resources, and the game idea itself. Where do we start?&lt;/p&gt;
&lt;p&gt;Since both Charles and I are tech guys, we knew we could implement our game idea without any problem and make it sing and dance at a silky-smooth 60 fps. But would it be fun? Now that we have these brand-new designer hats, finding that always elusive fun factor is a big concern. The idea of waiting for a couple of months before we could tell if our game idea was fun seemed too risky, so we tackled that problem first and head-on by prototyping.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://gamesfromwithin.com/prototyping-for-fun-and-profit/images/stick_1.png" title="stick_1"&gt;We could start at the bottom, write some low-level input handling, some graphics rendering, a basic &lt;a href="https://gamesfromwithin.com/optimizing-the-content-pipeline/" title="asset pipeline"&gt;asset&lt;/a&gt; &lt;a href="https://gamesfromwithin.com/optimizing-the-content-pipeline/" title="asset pipeline"&gt;pipeline&lt;/a&gt;, and all the other usual suspects. The problem is that, even if we try to keep things as simple as possible, it would still be several weeks or even months before we can actually start implementing the game itself. And even when we do, we&amp;rsquo;ll always be running up against incomplete technology and having to spend time fleshing it out as we try to make a game come out of the other end.&lt;/p&gt;
&lt;p&gt;Instead, we decided to start with a prototype. This isn&amp;rsquo;t supposed to be a &amp;ldquo;prototype&amp;rdquo; that eventually morphs into a shipping game, or a prototype that uses the same technology as the production code, or even a prototype that&amp;rsquo;s used to impress the big-wigs to squeeze some money out of them (ha!). No, all that stuff detracts from the ultimate goal of our prototype. Our approach was very similar to what &lt;a href="http://chrishecker.com/Homepage" title="Chris Hecker"&gt;Chris Hecker&lt;/a&gt; and &lt;a href="http://www.slackworks.com/%7Ecog/" title="Chaim Gingold"&gt;Chaim Gingold&lt;/a&gt; described in their &lt;a href="http://www.d6.com/users/checker/gdc06-AdvancedPrototyping.ppt" title="GDC presentation"&gt;GDC presentation&lt;/a&gt;. We had the need to answer one very specific question: &amp;ldquo;Is our game idea fun?&amp;rdquo; And we wanted the answer as quickly and cheaply as possible. Everything else was secondary.&lt;/p&gt;</description><content:encoded><![CDATA[<p>So here we are, ready to start development of our first game. We have the time, the resources, and the game idea itself. Where do we start?</p>
<p>Since both Charles and I are tech guys, we knew we could implement our game idea without any problem and make it sing and dance at a silky-smooth 60 fps. But would it be fun? Now that we have these brand-new designer hats, finding that always elusive fun factor is a big concern. The idea of waiting for a couple of months before we could tell if our game idea was fun seemed too risky, so we tackled that problem first and head-on by prototyping.</p>
<p><img loading="lazy" src="/prototyping-for-fun-and-profit/images/stick_1.png" title="stick_1">We could start at the bottom, write some low-level input handling, some graphics rendering, a basic <a href="/optimizing-the-content-pipeline/" title="asset pipeline">asset</a> <a href="/optimizing-the-content-pipeline/" title="asset pipeline">pipeline</a>, and all the other usual suspects. The problem is that, even if we try to keep things as simple as possible, it would still be several weeks or even months before we can actually start implementing the game itself. And even when we do, we&rsquo;ll always be running up against incomplete technology and having to spend time fleshing it out as we try to make a game come out of the other end.</p>
<p>Instead, we decided to start with a prototype. This isn&rsquo;t supposed to be a &ldquo;prototype&rdquo; that eventually morphs into a shipping game, or a prototype that uses the same technology as the production code, or even a prototype that&rsquo;s used to impress the big-wigs to squeeze some money out of them (ha!). No, all that stuff detracts from the ultimate goal of our prototype. Our approach was very similar to what <a href="http://chrishecker.com/Homepage" title="Chris Hecker">Chris Hecker</a> and <a href="http://www.slackworks.com/%7Ecog/" title="Chaim Gingold">Chaim Gingold</a> described in their <a href="http://www.d6.com/users/checker/gdc06-AdvancedPrototyping.ppt" title="GDC presentation">GDC presentation</a>. We had the need to answer one very specific question: &ldquo;Is our game idea fun?&rdquo; And we wanted the answer as quickly and cheaply as possible. Everything else was secondary.</p>
<p>Prototyping period</p>
<p>And so we dove into a prototyping frenzy. For our first day, we set up shop at the <a href="http://www.estreetcafe.com" title="E Street Cafe">E Street Cafe</a>. We opened up the place, took over a table, hooked up gamepads to our laptops, and hacked away furiously until late in the evening, fueled all the while by cappuccinos, gourmet tea, and pastries <a href="#%5B1%5D" title="[1]">[1]</a>. Yum! By the end of the day, we had the basics of the game implemented and even some of the more advanced features. Heck, we even thought it was kind of fun, but that&rsquo;s because we were tired and we had been staring at Charles&rsquo; horrible programmer art all day long. In all honesty, it really was a pretty sucky game, even if the enemy characters were wearing party hats. But hey, that was just end of day one.</p>
<p>Over the next few days, we had to take a break to deal with all the paperwork and logistics involved with setting up the new company and the office, but we resumed prototyping as soon as possible. The plan was to keep hammering away at the prototype until we saw it was clearly fun, or we decided it was hopeless and we had better think of something new (or go back and beg for our jobs back). Charles took it even further and swore not to shave his beard until the prototype was fun, much to his fiancee&rsquo;s delight (seriously, the only thing the ladies think is hotter than a game programmer is a bearded game programmer).</p>
<p>A week later, things weren&rsquo;t looking too hot. The game hadn&rsquo;t gotten much beyond what we had done the first day. Sure, we had a bunch of advanced features in, but it didn&rsquo;t really make it much more fun. Were we on the wrong path?</p>
<p>The major breakthroughs happened in the last few days. First of all, we removed a key feature that had been there since the very beginning. We really thought it was going to be key to the whole game, but it really made the game too easy and boring. As soon as we removed it, the feel of the game changed completely and things started to look up.</p>
<p>Then, as we were discussing some other advanced moves and features, the idea for a minor feature came up. Since the caffeine hadn&rsquo;t kicked in yet and I didn&rsquo;t have the energy to work on the next big feature, I implemented our little idea in about ten minutes. Charles saw it over my shoulder and he started laughing and begging me to check in the code. It was an instant hit! We ended up liking it so much that we decided to expand on with a few features, and before the end of the day, it&rsquo;s clear that it&rsquo;s going to become a main gameplay mechanic in the final game. That day we went home knowing we were nearing the end of the prototype face. Good thing because Charles&rsquo; beard was starting to look scary!</p>
<p><img loading="lazy" src="/prototyping-for-fun-and-profit/images/stick_2.png" title="stick_2"></p>
<p><em>We tried about seven different captions, but none of them did the sprite justice.</em></p>
<p>One more day of tweaking the prototype and we officially called it done. We knew we had gotten there when we tweaked a small feature, fired up the game to see how it felt, and then spent 10-15 minutes going crazy with the controller because we were having too much fun. Another good sign was when we would start playing and then yell at each other to look at the crazy things we had just accomplished.</p>
<p>Finally, Charles was able to shave. Thank God.</p>
<p>The prototype</p>
<p>The prototype process was supposed to be as quick and cheap as possible. None of the code written was intended to be kept or extended to go into production code, and performance wasn&rsquo;t an issue either. So, with that in mind, what did we use for developing our prototype?</p>
<p>C++ and <a href="http://www.talula.demon.co.uk/allegro/" title="Allegro">Allegro</a>. Yes, you read it right the first time. Let me say that again: C++ and Allegro.</p>
<p>With all the other choices available of higher-level languages and extensive game development libraries and frameworks, why on earth did we make that choice? Wouldn&rsquo;t Python with <a href="http://www.pygame.org" title="PyGame">PyGame</a> or C# and the <a href="http://msdn2.microsoft.com/en-us/directx/aa937794.aspx" title="Game Studio Express">Game Studio Express</a> have been better choices? The honest answer is that I don&rsquo;t think either one of those options would have allowed us to get the prototype done any faster for several reasons:</p>
<ul>
<li>
<p>Small scope. The scope and size of the prototype was quite small, so there wasn&rsquo;t much to be gained by using slightly higher-level language constructs or more complete libraries.</p>
</li>
<li>
<p>Allegro. Even though it might seem like an odd choice and be behind the times, it&rsquo;s precisely the old-school, fully procedural approach that makes Allegro so valuable. There are no frameworks, no enforced class hierarchies&hellip; heck, no classes or private members to get in the way. In Allegro, if you want to do something, you call the function and you&rsquo;re done. Exactly what we needed for the prototype. In retrospect, <a href="http://www.libsdl.org" title="SDL">SDL</a> might have been a better choice since it would have allowed us to use a DirectX surface and do video capture more easily. But Allegro worked like a charm and we have nothing but good things to say about that experience <a href="#%5B2%5D">[2]</a>.</p>
</li>
<li>
<p>Proficiency. Both Charles and I are quite proficient at C++, so even if another language gave slightly faster development time, we more than made up for it by being very familiar with C++ and its libraries. For the prototype we allowed ourselves to use STL recklessly and with wanton disregard for memory access patterns and spurious allocations.Â  We also didn&rsquo;t care about memory leaks at the end, so that helped get things up and running a lot faster.Â  Destructors?Â  Delete?Â  Free?Â  Cache coherency?Â  How do those equate to fun gameplay?!</p>
</li>
</ul>
<p>It&rsquo;s no secret that I&rsquo;m an avid advocate of <a href="http://www.gamesfromwithin.com/articles/cat_software_engineering.html" title="good software engineering practices for game development">good software engineering practices for game development</a>. As with anything, good software engineering practices have some very real and important benefits, but those benefits come with a cost. Because of the small scope of the prototype, and the fact that the code wasn&rsquo;t going to survive more than a week or two, we decided to throw any software engineering practice that would slow us down in the least straight out the window!Â  Forget about accessors and private scoping; skip any unit tests; bye bye factories, loose coupling, and proper physical dependency management. Welcome to hackfest, check your engineering discipline at the door!</p>
<p>One of the things that made the prototype very successful for us was to concentrate on a single gameplay mechanic. We didn&rsquo;t try to prototype the whole game, just the one bit we were most concerned about (and that was going to take 80% of the player&rsquo;s time and attention). That allowed us to deal with a small subset of the game and iterate on it very quickly without getting bogged down by creeping features or dealing with a larger scope.</p>
<p>The prototype shamelessly used the worst programmer art imaginable (Charles + MS Paint == &hellip; you can imagine [edit: Charles] TOTALLY AWESOME SWEET). Yes, it looked horrible, but if the game was so much fun with those graphics, just imagine how it&rsquo;s going to blow people away whenever we add some real art and animations.</p>
<p>Lessons learned</p>
<p>The most valuable lesson we learned was the value of constantly asking ourselves the questions &ldquo;Is this fun?&rdquo; and &ldquo;What can I do now to make it more fun?&ldquo;Â  That was actually really crucial. Having such a specific (even if subjective and nebulous) goal allowed us to remain in the right path. Sometimes it was tempting to add feature X or Y, but when we realized that it wouldn&rsquo;t make the game any more fun, we quickly dropped it and moved to something else.</p>
<p>It&rsquo;s important not to over-intellectualize the idea of &ldquo;fun&rdquo;, though. Sure, most of the fun comes from the choices the player makes and what happens as a result of those choices (even if the choice is to mash the buttons). But don&rsquo;t underestimate the value of &ldquo;fun&rdquo; in having cool, flashy things on the screen, or to have the character jump with a nice ramp-up curve and land with some squishiness to give it that &ldquo;just right&rdquo; feel.</p>
<p>It was also very helpful to run the prototype by somebody else towards the end to make sure we weren&rsquo;t finding it fun because we were simply delirious. Clearly, it has to be someone you can trust and who can understand what the prototype represents and not be put off by the stick figures. It was great to get confirmation from an outside source that it really was getting to be fun. We also got a bunch of feedback that made it a much tighter experience. A lot of it was pretty obvious, but we were too close to the game to be able to see it by ourselves.</p>
<p>As with most prototypes, it&rsquo;s always very tempting to not throw it away and continue hammering at it until it looks like something that could be shipped. We didn&rsquo;t really have a choice because of the technologies we went with (allegro is a fully cpu-based renderer), but we could feel the call of the dark side. It really was a good thing that we didn&rsquo;t even try. Towards the end, the terrible hacked code we&rsquo;d written was starting to slow our productivity. Code that bad builds up an &ldquo;engineering debt&rdquo; that you have to pay off sooner or later or you hit a wall.Â  Our particular wall came in the form of extending a pre-existing player action in what seemed like a trivial way.Â  Something like this would have literally taken about 5 minutes at the beginning of the prototype, but by the point we were at it would have taken closer to an hour. Heck, even having to go on for another week would have started to be painful. So in a way, the prototype came with a built-in self-destruct mechanism, which is a good thing because it discouraged us to continue working on it for too long.</p>
<p>Using existing technology is definitely the way to go. That way there&rsquo;s very little &ldquo;wasted&rdquo; time getting up to speed. The fact that we were able to get most of the core mechanics of the game in the first day goes to show how useful is to hit the ground running instead of getting bogged down in how to load bitmaps or create a window.</p>
<p>Additionally, the procedural, non &ldquo;framework-y&rdquo;, non-object oriented approach of the API we chose made it much easier to bend to our will and make it work the way *we* wanted, and not the way somebody decided for us ahead of time. The fewer restrictions your prototyping API has, the easier it will be to do all the crazy things that come to mind during the prototyping phase.</p>
<p>The game</p>
<p>Unfortunately, we can&rsquo;t really talk about the game right now. Just rest assured that we&rsquo;re working on it at full steam and we&rsquo;ll announce some details as soon as we can. Clearly, we&rsquo;re not going to release the prototype since it has a good chance of scaring away any potential publishers in its current state. But if one day the game sells tons of units, maybe we&rsquo;ll release the prototype as a &ldquo;behind the scenes&rdquo; feature so other people can have a glimpse at how things got started and they can laugh at our artistic skills.</p>
<p>Conclusion</p>
<p>There you have it. Now at least we can be confident that the game is going to be pretty fun. Sure, there are lots of aspects of the game that we haven&rsquo;t prototyped, but we consider those to be lower risk and we&rsquo;ll figure them as we go along. At least the core mechanic has proven to be fun. Now it&rsquo;s just a matter of writing the production code and implementing it all. That simple. What could possibly go wrong? ;-)</p>
<p>[1] Money saving tip #1 for starving startups: If you have to pay for a 24-hour Internet connection in a coffee shop and you need to have several computers with Internet access, connect them with an ethernet cable and share the Internet connection from one of them. Ta-dah! :-)</p>
<p>[2] Actually, I&rsquo;ve been wanting to create a movie of the prototype in action, but I haven&rsquo;t been able to. It seems that <a href="http://www.fraps.com" title="Fraps">Fraps</a> doesn&rsquo;t work because it&rsquo;s not using a DirectX surface, and saving each frame is too slow. Anybody has any suggestions? Don&rsquo;t get your hopes up though, we&rsquo;re not uploading a movie of the prototype any time soon, we&rsquo;re just saving it to show our grandchildren one day.</p>]]></content:encoded></item></channel></rss>