Since I’ve spent a lot of time figuring this stuff out, I thought I’d share my findings on how to setup an Eclipse Project for the AT91SAM7. There are tons of examples out there, and no individual bit of information gathered here is something that you couldn’t have found on the web already. However, I feel that the combination of features I was looking for was worth sharing.

So in a nutshell, this list of articles will let you:

  • Set up a proper Eclipse project, without the need for a makefile.
  • Set up the compiler toolchain for full C++ projects, mainly, the proper handling of static data construction.
  • Use OpenOCD for programming and debugging the chip (using a parallel port JTAG cable in my case)
  • Debugging in Eclipse

The articles are here:

  1. The Required Software
  2. Setting up an Eclipse Project
  3. Configuring OpenOCD and the AT91SAM7 for flash programming and booting
  4. Setting up GDB in Eclipse

Good luck!

January 4th, 2009 | Tags:

I would like to present a simple trick I like to use to implement a more coder-friendly safe delete. In case you don’t know what a safe delete is, it usually is a simple macro designed to NULL out pointer when they are deleted, so that a second attempt to delete them doesn’t crash your game. In it’s most common form, safe delete will look like this:


#define safe_delete(x) { delete (x); (x) = NULL; }

Notice the curly braces, which are here to prevent code like


if (condition)
safe_delete(myPointer);

from generating unexpected results.

The problem with this is that the syntax of safe_delete is different that that of a regular delete, programmers have to remember and use it as a function. Usually, this results in the programmers not using the safe delete feature and all your efforts are lost. Of course, there is always the argument that code should never attempt to delete an object twice, but that is a different subject. If nothing else, it is a nice safety feature when you get ready to release your software.

The first improvement to the safe_delete macro is, as a matter of fact, to warn programmers that they are attempting to delete an object twice:


#define DELETED_PTR 0xFFEEFFEE
#define safe_delete(x) \
{ \
if ((x) == DELETED_PTR) \
{ \
OutputDebugString("Pointer \'" #x "\' is being deleted twice\n"); \
OutputDebugString(#__FILE__ " (" #__LINE__ ")\n"); \
} \
delete (x); \
(x) = DELETED_PTR; \
}

If you have a stack trace mechanism in your code base, you could replace the warning with a full-on back trace.

But still, this doesn’t make our safe_delete macro any more coder-friendly. We some way to be able to type:safe_delete myPointer;Introducing operator=(). The trick I am proposing is to use an overload of operator=(). You could technically use any operator for this, but = is the most obvious.
When you override operator=, an expression like:

a = b;

becomes

a.operator=(b);

So the idea is to create a bogus type with an operator=() override that will change the parameter passed in. That means, of course that in the case of our delete, we don’t want to pass in a copy of the pointer to delete, but a reference (or a pointer, whichever you like best) to it. That is, we’ll define safe_delete to the following:


struct _SafeDelete
{
void operator= (void** t)
{
delete *t;
*t = NULL;
}
static _SafeDelete theDeleteObj;
};

_SafeDelete _SafeDelete::theDeleteObj;

#define safe_delete _SafeDelete::_SafeDeleteObject = (void**)

And somewhere in a .cpp file


_SafeDelete _SafeDelete::_SafeDeleteObject;

Of course, if you’re like me, seeing this trailing & operator scares the crap out of you, and you can’t help but think that it’s just begging for trouble. It is true that there is something a lot more reassuring about writing:

&(myVectorOfObjects.GetAt(5).PointerToObject)

than:

&myVectorOfObjects->GetAt(5).PointerToObject

But according to operator precedence, everything should be fine. The & operator is the lowest on the list, except for assignment operators.
So now you can use safe delete just like you would delete.

safe_delete myPointer;
January 4th, 2009 | Tags:

Finite State machines (or FSM) are an integral part of Game AI, often times making its entirety. Such is the case where I work; we use hierarchical state machines to control our NPC behavior just like everybody else. State machines are a widespread concept among AI programmers. Why? Probably because they are the easiest AI concept to implement; after all, you only need a variable to represent your state and a conditional statement. But states machines in games rapidly grow to unmanageable proportions; any programmer can certainly relate to the headache of skimming through tons and tons of conditional statements to find the one that breaks the entire logic. As the code becomes more dense, the logic becomes more difficult to understand and the time spent tracking bugs grows to unreasonable proportions.

A couple of days ago, I ran across this quote in the 2005 AI Interface Standards Committee Report:

One of the most significant problems in NPC behavior control construction is that procedural programming languages such as C, C++ and Java [...] are not suitable for implementing large sets of complex behavioral rules. Attempting to construct complex behavioral rules in a language such as C++ tends to result in an impenetrable code involving large numbers of if-then-else constructs, switch, case and loop statements. [...] In general, the result of attempting to construct complex NPC behavior using procedural programming techniques will be complex code which is incomprehensible and difficult to maintain, leading to an unavoidable increase in development time and requirements for large memory space and processing power.


The report then goes on to talk about the advantages of a Rule Based System, but I will leave that part out for another post. The point I am interested in is the suggestion that traditional languages like C++, and their most straight forward constructs (when it comes to AI) are inherently unfit for developing complex, evolving systems. No matter how well you initially plan your state machine, when the rules change and new behaviors/states are added or - even worse - others parts of the code start interfering, your simple design falls apart and you are forced to create exceptions and special cases. Before you know it, your initially well-organized code becomes a bowl of spaghetti.

Does this mean we should move away from state machines altogether? Certainly not. State machines are incredibly useful, and that is in big part because of their simplicity. No one will argue that they are perfect to model simple mechanisms like doors, progression stages or even insects. However; there has to be a cut off point, a moment when the AI programmer should realize that a state machine just isn’t going to be enough.

As a general rule, any outside interaction with your state machine is a catastrophe waiting to happen. In an ideal environment, the only piece of code that should be allowed to touch the state machine is the machine itself. That is, the machine queries the game world on its own and does not offer any interface for outside code to explicitly modify its state.

Unfortunately, as designs get bigger, the AI programmer is quickly tempted to add shortcuts into his state machine code. After all, adding a simple KillNPC() function certainly seems like a harmless thing (well maybe not for the NPC), and it’s easy enough to figure out what state variables it needs to affect. Unfortunately, this creates additional dependencies and requires more bookkeeping later on. If the programmer decides to add another state variable to the NPC, he needs to remember and update the KillNPC() function to modify the new variable as well. It can quickly get out of hand, especially when multiple people are involved with the same code.

If possible, outside code should never be given an opportunity to change the internal state of the machine directly. Rather, events should be queued and the machine should be able to read those events on its own agenda. First, because it is a reasonable assumption that some state changes may not be allowed at certain times (for instance, one can not kill the NPC until it has finished playing it’s current animation) and forcing outside code to check for such conditions is impractical. Secondly, this makes it obvious that the programmer has to consciously edit the state machine logic to respond to those events, ensuring a certain margin of safety.

The AIISC report suggests that Rule Based Systems be more suited for large sets of conditions and states. As much as I believe this to be true, I also believe that simpler constructs can achieve a great number of the behaviors we expect and that it is only a matter of the AI Programmer not setting himself up for faillure.

TOP