In my previous article I’ve suggested a few scripting statements that could be used to specify interactions between actors and the board. In this post I am investigating a solution to bind these statements to the action graph in my underlying API.
Implementing interactions
If you followed the previous articles, you already know how ‘pseudo-scripted’ statements get into the action graph. First an object tree representing the script is created. I have added the following classes to support this:
- InteractionDef – Defines an interaction as associating an EventDef with several responses.
- EventDef – Base class for interaction events
- ActorEventDef – Occurs when an occur performs a specified action.
- EnvironmentEventDef – Occurs when an actor occupies/enters a given tile
- CollisionEventDef – Occurs when an actor collides with an actor or prop.
- ActorResponseDef – A passive reaction (typically rendered as an actor animation)
- CapacityModifierDef – Used to capture disabling/enabling a capacity
- RoleModifierDef – Used to capture disabling/enabling a role
- PropertyModifierDef – Used to capture an increase/decrease to a property
The class hierarchy could be a little more structured. Also, it seems that we may easily compress the same hierarchy later by considering similar node types. However, this is enough to render the current set of scripting statements provided by the Script class.
The next step is to feed those into the Interpreter class that will actually setup the action graph. I decided to provide ad-hoc classes to render interactions to the action graph. Compared to the design I earlier produced to model actor decisions, classes for interaction are more specialized – many of these nodes just can’t be put anywhere in the graph. This is more a change in the design than something that is specific to the problem being solved, so I guess I would take an opportunity to clean the overall design of the action graph API a little later on – it seems that using more particular types helps keep the action graph small and simplifies some of the design while offering straightforward optimization hooks. On the other hand, large, structured nodes offer less opportunities for reuse.
The class hiearchy for this looks like this:
- AffectMap – a list of affect bindings, i.e. event/response pairs (subclass of Action)
- AffectBinding – a list of event/response pairs
- AffectCondition – specialized subclasses implement interaction events
- Affect – specialized subclasses realize actor responses.
All reflex maps (see previous articles) should be processed before affect maps. Notwithstanding, it’s OK to use several reflex maps, either for each actor or for the same actor.
Unlike with ReflexMap, I decided to hold an Actor instance directly in the map and pass it to binding, condition and affect method calls, this prevents these ‘support classes’ from implementing Action, but saves memory (no need to store Actor pointers in each node) and seems, overall, a better choice.
With this, my original draft for a behavior programming API and pseudo scripting interface is complete. Next time I’ll write a small test suite for this and hopefully I’ll then find time to discuss the overall design.

