Before implementing these behaviors, it's necessary to define world interfaces. At this point, more than halfway through this book, we are relying on many interfaces to improve our animat's behaviors. This section mostly extends existing interfaces, so the usual sketching, rationalizing, and formalizing phases are dealt with quickly.
Our existing world interface for movement currently supports turning and moving. There's a lot of flexibility in this specification; the AI can stop, walk, and run by providing movement vectors of different magnitude. It's also possible to look in any direction.
However, the AI has little control over the body's stance. The animat cannot crawl, for instance, or leap in any direction. Two additional modifier functions can be added, allowing the AI to achieve things such as rocket jumping or dodging fire:
void Jump(); void Duck();
The Jump command corresponds to the same action that human players can perform. Combined with a Move command, this produces a directed leap. The Duck command makes the animat crouch, and combined with a move command allows the animat to crawl.
void ItemsAvailable(vector<Entity>& items, const Entity::Type& unifier = 0);
The weapon interface is used quite often, so keeping this query separate makes it more convenient to use, and less code is required to interpret the result. To actually activate an item in the game, we can use the identifier symbol stored by an entity and call another function:
bool UseItem( Symbol& item );
Items such as the silencer, quad damage, or even keys can be used by the animats this way, if they are not activated automatically.
No functional extensions are needed for the vision interface; only additional data is passed through it. For example, doors and platforms also can be handled as entities, so a similar call to VisibleEntities() would suffice. The platform must guarantee to provide this information; ladders, for example, are not entities in the Quake 2 engine, so the framework needs to deal with them.
Entities such as doors carry some additional information indicating whether they are open, closed, or locked. We can understand this as an inheritance of entities in the game. (That is, a door is a kind of object.) The simplest C-like way to handle this is to provide a custom data pointer with each entity, which the AI would have to interpret depending on its type. Alternatively, each entity could be inherited from the base class, passed through the interface by typecasting. Either approach is similar in means, although the C++ inheritance approach is safer.
The message-passing mechanism also needs to handle doors and platforms. For example, events must signal that a door is open or that a platform has stopped after reaching its destination. Callback functions also can be used to alert the animat of these events.
void OnDoorOpen( const Event& event );
Finally, we want to extend the physical interface to return information about the state of the animat. This includes queries such as holding on to a ladder, standing on a platform, or even the type of medium (for instance, air or water).
bool isPlatform(); bool isLadder(); bool isWater(); bool isAir();