Blueprint

To make use of behavior instantiation, users should acquaint themselves with the Blueprint helper class.

In a simple — non-Grail — Utility AI system, each evaluator would be paired with a specific instance of action/behavior (or any object, in a general case, that we want to calculate utility for). Let’s assume the typical case of calculating the utility of behaviors. This forces a workflow, where the user needs to first create all behavior objects and then pair evaluators to them. However, typically we want to define an evaluator for a type of behavior (e.g. the attack behavior) and use the same logic for many instances of them (e.g. different parameterizations). This is where blueprints come in handy. Blueprints can be viewed as templates for behaviors, which share the same evaluator in Utility AI. They are responsible for (1) producing contexts, which represent all game data required for the behavior (or a different object) generation and evaluation, as well as (2) the behavior (or a different object) instantiation based on the context.

Blueprints are used in Utility Reasoner to identify which evaluators should be taken into consideration for each Context.

Blueprint is a template class so a user should provide the following template parameters:
  • InstanceType - Type of instantiated object (usually Behavior).

  • ContextType - Context type. It identifies what data should be used during utility selection. It is also used as parameter during object instantiation.

  • DataType - Type of data containing a subset of game state which can be used to generate valid Contexts.

Each blueprint needs to be passed 3 parameters during construction:
  1. name - Used mostly to identify the blueprint during debugging.

  2. contextProducer - Callable returning container of ContextType and taking DataType as an argument. This abstraction should generate Contexts valid at given moment, so that they can be used in Selector to determine which object should be instantiated.

  3. instanceProducer - Callable returning instance of InstanceType and taking ContextType as an argument. This abstraction should instantiate proper object of type InstanceType given Context properly returned from Selector.

Usage Example

  • C++

  • C#

grail::utility::Blueprint<grail::Behavior, grail::EntityBlackboardPair, grail::AIEntity> blueprint{"attack", Attack::ProduceContexts, [](const grail::EntityBlackboardPair& pair} { std::make_unique<Attack>(pair.second.GetValue<Enemy>("enemy")); }
using EntityBlackboardPair = ValueTuple<AIEntity, Blackboard>;
...

var blueprint = new Blueprint<Behavior, EntityBlackboardPair, AIEntity>("attack", Attack.ProduceContexts, (in EntityBlackboardPair pair) => { return new Attack(pair.Item2.GetValue<Enemy>("enemy"); });

API Reference