Brain

From AI Product Manuals
Jump to navigationJump to search
This page is part of the IAUS Manual.BrainBehaviorBehavior TypeDecisionAI Entity

Concept

IAUS Structure

A Brain is the top level component that is assigned to an agent in the game. From a data standpoint, a Brain is simply a collection of behavior packs and ability packs. However, the Brain class contains most of the data for the agent's thinking and does most of the work of scoring behaviors and keeping track of the history of the behavior usage.

It is the Brain class that is ticked on a regular basis by the game code. However, the think cycle is controlled by the brain itself. That means that while the brain might be ticked every frame of game loop, the brain may only think perhaps every 250ms.

During this process, the Brain assembles a list of potential neighbors and combines them as necessary with behaviors to arrive at a combined list of decisions to be scored and selected from. It then proceeds to score all those Decisions to arrive at the one with the greatest utility at the time.

If a new Decision is selected, the related behavior type is executed. Additionally, data is adjusted in the brain to make note of what the brain is currently doing, the history of behaviors, etc.

Implementation

Code

The code for the Brain is held in Brain.cpp in the class of the same name.

There will be one instance of the Brain object for each character that has a brain. This is because it holds the information about the current state and history of this character's "thought process".

Typedefs

For readability, there are many typedefs at the top of the Brain file. Most of these are lists, sparse data structures, or defined pairs. In the case of the pairs, they are most often used for passing around the key/value combinations of the sparse structures but are also used as the key itself.

//////////////////////////////////////////////////////////////////////////
// Convenience types
typedef std::unordered_map<unsigned int, BrainSeed*> BrainMap;
typedef std::pair<unsigned int, BrainSeed*> BrainPair;

typedef std::unordered_map<unsigned int, Behavior*> BehaviorMap;
typedef std::unordered_map<unsigned int, BehaviorAbilityPair*> AbilityMap;
typedef std::pair<unsigned int, Behavior*> BehaviorPair;

typedef std::list<Behavior*> BehaviorList;
typedef std::list<Decision> DecisionList;
typedef std::list<BehaviorAbilityPair*> AbilityList;

typedef std::list<BehaviorPackage*> BehaviorPackageList;
typedef std::unordered_map<unsigned int, BehaviorPackage*> BehaviorPackageMap;
typedef std::pair<unsigned int, BehaviorPackage*> BehaviorPackagePair;

typedef std::list<AbilityPackage*> AbilityPackageList;
typedef std::unordered_map<unsigned int, AbilityPackage*> AbilityPackageMap;

typedef std::unordered_map<unsigned int, AbilityPackage*> AbilityToAPMap;
typedef std::pair<unsigned int, AbilityPackage*> AbilityToAPPair;
typedef std::unordered_map<unsigned int, BehaviorPackage*> AbilityToBPMap;
typedef std::pair<unsigned int, BehaviorPackage*> AbilityToBPPair;

typedef std::pair<InputParameter, float> ParameterPair;

typedef std::unordered_map<unsigned int, float> BehaviorHistoryMap;
typedef std::pair<unsigned int, float> BehaviorHistoryIdAndTime;

typedef std::unordered_map<ContextEntry, float> ContextHistoryMap;
typedef std::pair<ContextEntry, float> ContextHistoryIdAndTime;

typedef std::unordered_map<BehaviorType, float> BehaviorTypeHistoryMap;
typedef std::pair<BehaviorType, float> BehaviorTypeIdAndTime;

//////////////////////////////////////////////////////////////////////////
// Entity for keeping track of relevant neighbors while making decisions 
// so that they don't need to be reacquired by the engine

typedef AiEntityWP NeighborEntity;
typedef std::list<NeighborEntity> NeighborList;

Static Members

However, there are a number of static members in Brain.cpp that hold all the original versions of brains, behaviors, abilities, behavior packs and ability packs, and Animation Mappings. These are all held in sparse containers (unordered maps in C++ and dictionaries in C#). Additionally, for readability, these are all typedef'd at the top of the Brain file.

//////////////////////////////////////////////////////////////////////////
// Brain Data Initialization
// This is not part of individual brains -- only one copy of each is necessary

public:
	static BrainMap Brains;								// All brain definitions
	static BehaviorMap Behaviors;						// All behavior definitions
	static AbilityMap Abilities;						// All ability definitions
	static BehaviorPackageMap BehaviorPackages;			// All behavior package definitions
	static AbilityPackageMap AbilityPackages;			// All ability package definitions
	static ObjectAnimationMappings ObjectAnimations;	// All animation names for objects

In the case of the package lists, the ones in the static objects may not match up with the one that is contained in an active Brain itself. This is because packages can be pushed on and off the brain dynamically through events in gameplay. Therefore, the static versions are indicative of what the brain is "born with".

Brain Seed

Additionally, this file holds the class BrainSeed which is a way of storing the information for raw brain data that comes from the database. There will be one BrainSeed object for each brain. It merely holds the name, description, a list of the Behavior Packs and a list of the Ability Packs that are associated with this brain. On load, it is unpacked into the static members of the Brain class.

Data

From a data standpoint, other than a unique ID, name, and a description, a Brain is simply a collection of Behavior Packs and Ability Packs.

Export

Exporting a Brain is merely exporting the Brain's ID and the Behavior Packs and Ability Packs it contains. These end up creating Brain Seeds.


Website, Manuals wiki, and Product Code ©2021, Intrinsic Algorithm LLC