Final Form Games, Year One: WHERE WE’RE AT

Wed, June 30, 2010 -- 17:49 UTC

On July 1st, a mere earth-rotation from now, Final Form Games will celebrate its very first birthday. To commemorate this milestone, we decided to break our customary silence to talk about where we’ve been, where we’re at, and where we’re going.

finalform_officepanorama

Day one.

WHERE WE ARE AT
or
THREE FACTS WE HANG OUR HATS UPON:

0511101929

Tim, hacking the encryptions. And yes, he is using three mice at the same time in this photo.

ONE: For prototyping, our goal/dream was to write games in a way that was as rapid, straightforward, and fun as tools like Flash.  Tim told us he had a vision, and that though the path would be a risky one, he knew it would take us where we wanted to go. When Tim finally emerged from his 5-month journey into code, drenched in gore and using a walking-stick that appeared to have been hewn from the claw of some long-forgotten subterranean insect, we looked upon the spoils and knew that we had found what we were looking for.

0306101557

Hal, playing our game in the Traditional Manner.

TWO: We realized that we needed two programmers, and had but one. This led to a conversation that basically went like this:

Tim: “Hal, we’re going to need you to become a programmer now.”

Hal: “Okay.”

And so he did.  It’s easy to say, but much harder to imagine actually doing: Hal bootstrapped himself the bulk of the distance between occasional-web-tinkerer and full-blown-gameplay-programmer in less than a year.  Working closely with Tim brought him the rest of the way there, and now almost all of our actual gamecode is the result of Hal’s skilled handiwork.

THREE: People routinely compare our art to the art in Metal Slug. The rest of Mike’s life is more or less guaranteed to be downhill.

ALSO!
or
OTHER TRUE FACTS THAT WARM OUR HEARTS WHEN ALL IS COLD AND DARK:

- We are active members of the small-but-scrappy Philadelphia game developer community, and are thrilled to be a part of its establishment and continued growth.

Our playtests... are getting a little crazy.

Our playtests... are getting a little crazy.

- We’ve given a few talks and round-tables about what we do at some local colleges and universities, along with our BFFs over at Cipher Prime and Merit. We’ve enjoyed dipping our toes into these kinds of education initiatives, and hope to wade in much deeper during the coming year.

Crunch dinner, courtesy Hal's then-fiancée-now-wife Jenn.

Crunch-time dinner, courtesy Hal's then-fiancée-now-wife Jenn. It was delicious. And TIMELY!

- Our friends and family have been hugely supportive of our endeavor, contributing everything from kind words to sage advice to crunch-time donuts. Two particular people (one of whom was Mike/Tim’s mother) went so far as to teach themselves how to pixel, and contributed much-needed art assets during our darkest hour.

- Finally: we are doing what we came here to do. We are spending our days making games of our own devising, learning all we can, and enjoying it ever so much. Year One was a great, tumultuous adventure. Join us on our birthday tomorrow, and we’ll tell you about why we’re so excited about Year Two.


Something Very Special

by Tim
Mon, September 28, 2009 -- 17:34 UTC

The following is a fairly technical post about something that came up during our programming efforts. It assumes a certain amount of experience with the intricacies of C++, so if that’s not your cup of tea, don’t pay this post any mind.

I spent some time yesterday integrating my C++ math library with Lua. I have a pretty robust Lua integration library at this point, but it heavily leverages template partial specialization to achieve the ease-of-extensibility that I want. While I have become rather adept in the past few months at dissecting and making use of template error messages, I ran into a confounding error that I simply had to share*.

Here is a C++ program that represents the kind of task I was attempting to implement. The original code was implementing C++-side templated generation of Lua userdata metatables for my templated mathematical primitive classes. The following code snippet, while contrived, should serve as a more digestible demonstrative example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
using namespace std;
 
// A few generic templates
template <int N>
struct Foo
{
};
template <>
struct Foo<1>
{
};
template <int N>
struct Printer
{
  static void Print()
  {
    cout<< "You have " << N << " " << Texter<Foo<N> >::GetText() <<endl;
  }
};
template <typename T>
struct Texter
{
  static const char* GetText() { return "apples"; }
};
 
// Let's call this next specialization "A"
template <>
struct Printer<1>
{
  static void Print()
  {
    cout<< "You have just one " << Texter<Foo<1> >::GetText() <<endl;
  }
};
 
// And let's call this next specialization "B"
template <int N>
struct Texter<Foo<N> >
{
  static void Test() { Printer<N>::Print(); }
  static const char* GetText() { return "apple"; }
};
 
int main(int argc, char** argv)
{
  Texter<Foo<1> >::Test();
}

So, what would you expect to happen when you run this program? I would have expected it to print out, “You have just one apple” and terminate. What I would NOT have expected is for it to spit out this error:

1
2
3
4
5
6
7
8
9
10
11
12
1>------ Build started: Project: TrickyTemplates, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>c:\finalformgames\trickytemplates\trickytemplates\main.cpp(40) : error C2039: 'Test' : is not a member of 'Texter<T>'
1>        with
1>        [
1>            T=Foo<1>
1>        ]
1>c:\finalformgames\trickytemplates\trickytemplates\main.cpp(40) : error C3861: 'Test': identifier not found
1>Build log was saved at "file://c:\FinalFormGames\TrickyTemplates\TrickyTemplates\Debug\BuildLog.htm"
1>TrickyTemplates - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

It was telling me that Texter<Foo<1>> does not have a method named Test in it. But there Test is, right above the call to it! All my efforts to statically analyze the program for the problem were fruitless (in part because the actual code was vastly more complex than this example). So, I did what anyone would do in my shoes, and started poking at it with a stick.

One surprising result: if I changed Printer to take in an additional template parameter, typename T, the error went away.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
template <typename T, int N>
struct Printer
{
  static void Print()
  {
    cout<< "You have " << N << " " << Texter<Foo<N> >::GetText() <<endl;
  }
};
...
template <typename T>
struct Printer<T, 1>
{
  static void Print()
  {
    cout<< "You have just one " << Texter<Foo<1> >::GetText() <<endl;
  }
};
...

Well, that’s pretty strange. Needless to say, this did little to allay my worry.

So, I rolled it back and broke out an old tried-and-true technique I picked up while working with the Metrowerks Codewarrior debugger: try moving blocks of code around. Sometimes this is illuminating, and, in fact, I found that by swapping the order of specializations “A” and “B” (see above code snippets), the error went away. Again, not too reassuring, but it gave me a lead by suggesting that something about this bug must relate to the order in which things are defined.

I searched online for all manner of permutations of keywords relating to the situation, and finally found this post on a site about the programming language D (which has many similarities to C++):

“If two template specialization refer to each other, there is the possibility that one of them will try to instance the other before the specialization for the other is created. The result would be either a compile error or an attempt to instance the wrong template. On the other hand, if I’m not missing something, a compiler would also be correct to lazy evaluate specializations, in which case this problem may well not occur. Some way to ensure the desired behavior here would be needed.”

So, my current understanding as to what was going on is as follows: The Printer<1> specialization is instantiating the Texter<Foo<1>> specialization before the Texter<Foo<N>> specialization is defined. This is because the correct order cannot be determined due to two specializations cyclically referring to each other. As a result, it is masking out the later definition of the Texter<Foo<N>> specialization. When we call Texter<Foo<1>>::Test() in main(), it uses the incorrect specialization, which does not define the a member named Test. This may be inaccurate, but it seems to line up best with the symptoms from what I have figured out. That being said, if you are familiar with this bug, or have a contrasting theory, please share with us below in the comments.

What’s especially surprising about this error is that there is supposed to be an error message you get when it happens! It’s not hard to invoke it, either:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// This compiles just fine:
template <int N> struct X
{
  static void A() { Y<N>::B(); }
  static void C() { }
};
template <int N> struct Y
{
  static void B() { X<N>::C(); }
};
int main(int argc, char** argv)
{
  X<1>::A();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// This, however, throws a C2908!
template <int N> struct X {};
template <int N> struct Y {};
template <>
struct X<1>
{
  static void A() { Y<1>::B(); }
  static void C() { }
};
template <>
struct Y<1>
{
  static void B() { X<1>::C(); }
};
int main(int argc, char** argv)
{
  X<1>::A();
}

I do not mean to fault Microsoft for their failure to throw this error at me. It’s one hell of an edge case, and if you’re in this deep, you really ought not to rely on your compiler to bail you out when you do Bad Things. That being said, it’s nice to be able to trust that your compiler is Always Right, and experiences like this make that trust feel tenuous and uncertain.

In conclusion, do not let your template specializations refer to each other cyclically, or you may find yourself a sad, sad panda.

*Please note that this post refers specifically to behavior I experienced using Visual Studio 2008 9.0.21022.8 RTM on a machine running Windows XP. If you are on a different platform, you may or may not experience the same behavior.


Welcome to Final Form Games! Dot com!

by Mike
Wed, August 19, 2009 -- 14:07 UTC

As I type this, Hal and Tim are muttering arcane strings of code sigils. Ostensibly, this constitutes some form of back-and-forth communication between the two of them. The frequency of these little gobbledygook salvos has been rising steadily for the past two hours or so. A good chunk of it is over my head, but I have pieced together the following through context clues:

  • This website is almost done. Indeed, it is very possible that we could go live before C.O.B. today.
  • Doing so will require that several annoying bugs in the category Tim refers to as “survivors” be squashed with extreme prejudice.
  • Going live before C.O.B. today would be desirable in the extreme.
  • Having some actual content on the blog when we go live (for our “readers”) wouldn’t get kicked out of bed either.

So our two alpha coders put their heads down and started speaking in tongues. As a result, I have been charged with producing our very first message to the world at large. I’ve decided to talk about the big picture of what this year is about for us.

Put simply, this year is about starting up. It’s about paying what it costs to spin up a studio, a technology core, and a decent understanding of what 3 guys making an entire game in a reasonable amount of time really looks like. Most importantly, it’s about setting up a webcam. Because you gotta have a webcam.

We’re 2.5 months in now, and things are going pretty well! In keeping with our goal of contributing to the Dialogue At Large, we’ll be expanding on the how and the why of our emergence from the primordial bog in subsequent posts. For now, suffice to say that we have the studio, the technology that will underpin our games is well underway, and we’ve been evolving our development processes steadily over the course of these initial efforts. We also (improbably) have a webcam. On a webSITE! Not using capital letters and italics to convey our excitement is becoming increasingly difficult.

Which brings us to today. With the website done, there’s not much left to do around here except our JOBS. To wit:

  • We will make fun, handcrafted games that explore the themes and mechanics which have always resonated with us.
  • We will sell those games to you. For cashy money!
  • We will use that money to repeat this process.
  • We will drive the minions of evil to the world’s jagged edge, and pitch them into the chasm so that the bell of peace can ring in our land once more.

Alright. Back to it. Join us! Explore! Check back often! There will be new stuff!