Grail Overview
This is a general overview of the Grail system.
You might also consult the manual overview that explains how to navigate effectively through documentation.
What is in the package
Grail is a multi-platform library for creating Artificial Intelligence
in computer games.
The library is distributed in the following four forms:
-
Native
C++
library -
Native
C#
library -
Unreal Engine
plugin (C++
library with some additionalUE
integration) -
Unity3D
plugin (C#
library with some additionalU3D
integration)
You can use Grail if your game is written in C++ or C# - that is basically the only requirement!
When working with Unity3D
or Unreal Engine
, you can either use the dedicated plugin (preferred) or the respective native library. In addition, we provide a set of helper GUI-based tools, that you can use with any of the libraries:
What Grail provides
The system provides functionalities in the following areas:
Defining behaviors
Many traditional approaches to AI are implemented in the form of if condition
then do something
.
You can think of this workflow as declarative AI, because you explicitly declare what a bot should do.
In Grail, however, the underpinning idea is to equip a bot with options and let a reasoning mechanism choose one of them at a particular moment.
A behavior represents the notion of a generalized action performed in the game. Any interaction of the bots in the game, which are controlled by Grail, should be implemented using the Behavior class. By interaction we mean things bot really does and how it affects (changes) the game environment, e.g., running or shooting in an FPS game. Once the logic is implemented as Behaviors, you can use the Grail intelligent reasoning capabilities. Behaviors can be dynamically instantiated or reused from a common pool.
We recommend thinking about the possible options first and then design behaviors. The more modular/generic the behaviors are, the more flexibility you get in terms of testing various approaches to AI. For instance, you may tinker with various Utility Systems, Planners and Abstract Games and all of them may use the same behavior classes as output.
Intelligent reasoning (selecting what to do)
In the previous section we introduced Behaviors - things bots can do. Grail comes with mechanisms that define logic of selecting the most appropriate behavior at particular moment in a game. Let us call this logic of computing the right behavior (the behavior selection) as an AI algorithm. The AI algorithms are wrapped inside specializations of a class Reasoner. A Reasoner is an easier-to-use component on top of an algorithm that can be assigned to entity (described in the next section).
Reasoner provides a common interface for selecting behaviors and it is seamlessly integrated into the Grail update loop. However, you may use the algorithms directly by their interface classes, if you prefer so as well as creating custom Reasoner.
Reasoner specializations:
Interfaces of the algorithms:
Communication and Hierarchy
Reasoners are assigned to AIEntity. You can think of the AIEntity as a separate thing that executes a single behavior at any given time from a number of possible behaviors.
Grail provides a built-in mechanism for exchanging data between entities based on blackboards. Each entity manages one private Blackboard and may share any number of Blackboards with other entities.
Additional features
-
Rich logging.
-
Multi-threading.
-
Update loop; control over the order in which bots take actions (see AI Manager).
-
Serialization of most configurable objects into human-friendly YAML files, that can be edited in a text editor.
-
Choosing and optimization of parameters using Evolutionary Algorithm running in your game.
-
GUI-based configuration and debugging tools.
The AI algorithms
Utility AI
Allows for context-dependent behavior selection that is managable even when dealing with many possible options. The system uses an instanced behavior approach, which allows it to distinguish betweet differently parametrized versions of the same behavior. The system comes with many predefined mathematical curves, but also allows the user to define his own - either in code or using hand-crafted cubic splines.
Features:
-
high run-time performance - this method is faster than Planner and Abstract Games
-
relatively design friendly - as a designer you modify curves that define relations (e.g. utility of fleeing based on HP)
-
you can combine outputs from many curves
-
you can use various evaluators (ways of combining utilities) and selectors (ways of choosing the final behavior)
Particularly useful for
-
preference modelling
-
goal prioritization
-
persona systems based on levels (e.g. aggressiveness, curiosity)
-
local tactical reasoning in the context of a single unit (without complex coordination or planning)
-
games, in which usefulness of an action is visibly based on some measurable conditions
Planner
It is based on the GOAP approach (Goal Oriented Action Planning). Planner lets your AI agents devise long term behavior sequences to achieve various goals, instead of relying only on current world state and performing only reactive actions. Flexible state and action representation structures enable the planning algorithm to take into account any number of parameters and interdependencies of world objects and allows for easy translation from game-space to plan-space and the other way around. This method has been used in games such as F.E.A.R.® or Killzone 2®.
Features:
-
goal-driven
-
long-term planning (as the name implies) - not only locally best behavior
-
the AI can explain itself: there is sequence of behaviors and causal relationships between them (what the bot wanted to achieve)
-
can be fast for smaller planning spaces
Particularly useful for
-
games where you can model requirements and effects of actions
-
crafting
-
resource planning and build orders
-
games that require logical reasoning
-
games where behaviors do not to need to be chosen very often (or continuously)
-
complex environments, which are relatively static apart from the planning bot’s actions effects
Simulated Games
This is a simulation-based technique that relies on stochastic exploration of the game tree to choose actions that have the highest probability of reaching the goal. Thanks to the possibility of simulating decisions of other agents, it lets your AI predict player behavior and act accordingly. This method requires a simulation model, which is is done in code and it is usually either a simplified version of the actual game or a subset of it.
In addition, Grail is equipped with tools that allow to run the simulations (offline) as time-consuming task and save the results as a Decision Tree. Such a tree is rapidly fast to use in the game.
Features:
-
goal-driven
-
long-term planning
-
high quality if given enough time - can be used for really demanding bots
-
relatively high computational demand - not to be used continuously
-
option to train offline and convert to a simpler Decision Tree (knowledge compression)
-
very precise behavior selection in a dynamic environment, even nuances count
-
it is possible to detect optimal strategy, including situations that there is one obvious winning strategy and should be nerfed
Particularly useful for
-
strategy games
-
tactical games
-
coordination between bots
-
games, in which it is possible to derive simplified subgames
-
strategic actions that need to be chosen from time to time
-
games with turn-based nature
Evolutionary Algorithms for Supporting Game Design
Within Grail, you will find a comprehensive implementation of an evolutionary algorithm. This component can assist you in game design by optimizing specific parameters based on empirical data.
Imagine a multiplayer online game, such as a MOBA, where players choose from a roster of characters or a real-time strategy game with various unit types players can recruit from. It is exceptionally challenging and tedious to balance the classes or units, so no single strategy becomes overwhelmingly dominant or completely useless. However, the objective of having properly balanced parameters in a game is crucial to make it engaging, with diverse gameplay and — ultimately — successful. Not to mention that properly balanced online multiplayer games have the potential to be played in competitive or even e-sport settings.
Imagine a battle encounter in an RPG game, in which you want experienced players to win by a narrow margin. This can be a design goal to create suspense as the outcome remains uncertain until the very end. As the previous one, this task also requires finding the correct set of parameters from a vast, multi-dimensional space of possible values.
In both examples, properly used evolutionary algorithms can support you.
To utilize it, you simply need to:
-
Specify which parameters can be optimized and provide their allowed values.
-
Distill some simulated episodes in your game, initialized at the start based on the current set of parameters, with a clear termination condition.
-
Define a fitness function that will provide a numerical assessment of how well the particular set of parameters fulfilled the expectations in the simulated episode.
Features:
-
A fully operational evolutionary algorithm maintaining a population of individuals that undergoes mutation, crossover, elitism, and selection.
-
Default hyperparameters of the algorithm, which you can use out of the box or customize as you see fit.
-
A save and load system enabling you to serialize the current state of the algorithm to the disk and resume it in another session.
-
A diagnostic log of the current population including its diversity and the currently best solution.
Best used for:
-
Balancing parameters of the game.
-
Procedural generation and optimization of map layouts that are based on building blocks.
-
Fine-tuning behaviors.
-
Automatic testing through repeated simulated episodes.
-
Choosing parameterizations of enemies for various difficulty levels.