Difference between revisions of "Wesnoth AI Framework"
m (→AI Configuration) |
(→The [ai] Tag — Stages: add this section) |
||
Line 69: | Line 69: | ||
*'''formula'''="": (string) Formula AI code to be executed by the AI. We recommend not using this any more except for extremely simple AIs. See [[legacy documentation]] for more information. | *'''formula'''="": (string) Formula AI code to be executed by the AI. We recommend not using this any more except for extremely simple AIs. See [[legacy documentation]] for more information. | ||
− | == | + | == The [ai] Tag — Stages == |
− | + | The [ai] tag can contain one or several stages defined in [stage] tags. If the AI configuration contains several stages, they are executed in the order in which they are put into the [ai] tag. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | While there are six different types of stages available, all AI functionality possible in Wesnoth can be achieved using only a single one, the candidate action evaluation loop stage. In the default setup, this stage has id ''main_loop'' and we generally simply refer to it as the ''main_loop'' stage. | |
− | ''' | + | Other stages exist mostly for legacy reasons from the times in the AI development when the ''main_loop'' stage did not exist yet. They are currently still functional and kept for backward compatibility reasons, but they are not maintained any more and might be removed in a future Wesnoth release cycle. We therefore recommend that all custom AI development is done using the ''main_loop'' stage only. |
+ | |||
+ | === ''main_loop'' Stage Configuration === | ||
+ | |||
+ | For the ''main_loop'' stage, the [ai] tag contains the following elements: | ||
+ | |||
+ | *'''name''': This must be set to 'testing_ai_default::candidate_action_evaluation_loop', so that the AI knows that this is the ''main_loop'' stage. | ||
+ | *'''id''': (string) This is the identifier of the AI. It is usually set to 'main_loop', but can take on any value. It only matters if you are planning to remove or modify the stage during a scenario. | ||
+ | *'''engine'''=cpp: (string) This must be set to 'cpp', which is also the default value. It can therefore be omitted. | ||
+ | *'''[candidate_action]''': Candidate action configuration tags. See [[below]] for details. | ||
+ | |||
+ | '''Notes:''' | ||
+ | * As an example, the configuration of the ''main_loop'' stage in the default AI is shown [[RCA_AI#RCA_AI_Stage_Configuration|here]]. | ||
+ | * Candidate actions can be using any of the three available engines. Just because the stage uses the ''cpp'' engine does not mean that the CAs need to do so as well. See [[below]] for an example. | ||
+ | * While that should rarely ever be necessary, it is possible to include several ''main_loop'' stage definitions in the same [ai] tag. | ||
+ | ** This is done by putting several [stage] tags into the same [ai] tag | ||
+ | ** The AI engine then evaluates the CAs of the first stage in the usual way, until no CA returns a valid score any more. | ||
+ | ** After the first stage is finished, it moves on to the second stage and repeats the process, until all stages have finished. This ends the AI turn. | ||
+ | ** Obviously, this only makes sense if the sets of CAs of the different stages are not identical (although individual CAs might appear in several stages). | ||
+ | |||
+ | === Recruitment Stage === | ||
+ | |||
+ | A recruitment stage exists. However, this stage is also used by the ''recruitment_instruction'' aspect. Anything that can be done with this stage can also be done with the ''recruitment'' candidate action using the ''recruitment_instruction'' aspect. It should therefore never be necessary to use this stage and we not describe it here. | ||
+ | |||
+ | === Legacy Stages === | ||
+ | |||
+ | Four other stages are also available. They do, however, not provide any new functionality any more these days, only different ways of achieving the same functionality that is also possible with the ''main_loop'' stage. We therefore only list them here for completeness, with brief examples and links to old documentation. | ||
+ | |||
+ | Note that both this documentation and the stages themselves might be removed at some point. | ||
==== Lua stage ==== | ==== Lua stage ==== | ||
− | + | ||
+ | Executes Lua code by calling a function created inside a Lua engine. Whatever element is returned by the code in lua [engine], is accessible here as an upvalue. | ||
So, for example, ''(...):execute()'' calls ''whatever_is_returned_by_lua_engine:execute()'' | So, for example, ''(...):execute()'' calls ''whatever_is_returned_by_lua_engine:execute()'' | ||
− | + | Example: | |
[stage] | [stage] | ||
− | + | engine="lua" | |
− | + | code= "(...):execute()" | |
[/stage] | [/stage] | ||
− | ==== | + | See [[legacy documentation]]. |
− | + | ||
+ | ==== Formula AI Side Formulas Stage ==== | ||
− | + | This stage executes a given Formula AI side formula. | |
+ | Example: | ||
[stage] | [stage] | ||
− | + | engine=fai | |
− | + | name=side_formulas | |
− | + | move="write_your_formula_here" | |
[/stage] | [/stage] | ||
− | + | See [[legacy documentation]]. | |
− | |||
− | + | ==== Formula AI Unit Formulas Stage ==== | |
+ | This stage takes no parameters and executes all Formula AI formulas which are attached to units. | ||
+ | |||
+ | Example: | ||
[stage] | [stage] | ||
− | + | engine=fai | |
− | + | name=unit_formulas | |
[/stage] | [/stage] | ||
+ | |||
+ | See [[legacy documentation]]. | ||
==== Fallback stage ==== | ==== Fallback stage ==== | ||
− | |||
− | + | Fall back to other, older AI. | |
+ | |||
+ | Example: | ||
[stage] | [stage] | ||
− | + | id=fallback | |
− | + | name=testing_ai_default::fallback | |
− | + | [ai] | |
− | + | ai_algorithm=default_ai | |
− | + | [/ai] | |
[/stage] | [/stage] | ||
− | + | This example shows how to set up a stage to fall back to the old default AI (the one used before the current default was introduced). This was useful when it was not clear yet how well the RCA AI would work and whether it would suddenly abandon the CA evaluation loop. There is really no reason to use a fallback stage any more these days. | |
− | |||
==Available Engines== | ==Available Engines== |
Revision as of 15:26, 18 February 2016
This page is currently under construction (Feb 2016) |
Contents
Wesnoth AI Framework: A Composite AI
The Wesnoth AI framework is that of a composite AI. In other words, rather than the AI being one huge monolithic block, it is composed of a variety of different components which can be combined in a modular fashion (almost) at will.
In its default configuration, Wesnoth provides a predefined combination of these components in the RCA_AI. This configuration can be modified in a multitude of different ways. Due to the modular setup, it is not only possible to add new AI behavior to the beginning or end of the default AI or replace it entirely, but to insert new bits and pieces in between existing components. This can be done either in addition to or as substitutes for existing components.
This page describes the AI components in a general sense. Check out RCA_AI for how these are assembled into the default AI and Wesnoth_AI for a collection of links to pages explaining how to configure and modify the existing AI or write a completely new AI.
Types of AI Components
The Wesnoth AI framework consists of the following types of components:
Stages
These are the fundamental building blocks of the AI. The AI is set up as a series of stages which are executed in the order in which they are put into the AI configuration. In other words, all actions of the first stage are executed first, then all actions of the second stage, etc.
While there are five different types of stages, only one of them, called the main_loop stage, is used in the default AI. In fact, this stage is sufficient for the vast majority of custom AI applications as well. We therefore postpone the description of the other stages and describe how the main_loop stage and its sub-components work first.
The Candidate Actions of the main_loop Stage
The main_loop stage consists of a number of candidate actions (CAs). For each AI move, all CAs are evaluated and assigned a score. The CA with the highest score is executed. Then all of them are evaluated again (including the one that was just executed) and the highest scoring CA is executed until no CA returns a valid score any more.
Using individual candidate actions which fulfill very specific tasks, it is possible to assemble entire AIs in a modular fashion. The CAs can be put together in whatever order and combination best suits the needs of a scenario. They do not need to be sorted in order of their evaluations scores and can even have variable evaluation scores, so that CA A will sometimes have a score higher than CA B and sometimes a lower score, depending on the situation on the map.
For a summary of the candidate actions of the default AI, click here. For more technical details, see XXX.
Aspects and Goals
Aspects are simply the return values of certain functions that can be read by the candidate actions. They thus serve as configurable input parameters to modify a CA's behavior. The return values of the aspect functions can be defined using both WML or Lua.
A goal is a special type of aspect that determines the directions into which the default AI moves its units. See here.
Engines
Engines execute the code provided for the individual components of the AI. In recent Wesnoth versions, you do not need to worry about the engines any more, they are always defined and active. It is sufficient to know that the components can be written in three different languages, C++, Lua and Formula AI (FAI). Information on how to do this is provided in the links of the Wesnoth_AI page.
It is worth noting that some stages are only set up for specific engines (see below), while the candidate actions, aspects and goals (todo: confirm the latter) of the main_loop stage can be written in any of the three languages and can be combined arbitrarily.
AI Configuration
The Wesnoth AIs are assembled from configurations provided in several different places:
- The default AI parameters in a variety of configuration files in the 'data/ai/' directory
- Optional [ai] or [modify_ai] tags in era configurations
- Optional [ai] or [modify_ai] tags in multiplayer faction configurations
- Optional [ai] or [modify_ai] tags in scenario configurations
When the game is created, all these config snippets are merged into a single configuration stored in form of an [ai] tag. Then, aspects with the same ids are merged. Furthermore, whenever a [modify_ai] tag is acted upon (for example in an event), it is added into the existing AI configuration in the same way.
In the following, we describe the syntax of the [ai] tag. We first show the top-level keys and tags that can be used. Details on the use of the tags for the individual components follow below, together with examples and links to the available types of each component.
The [ai] Tag — Top-level Elements
AI configurations are set up and stored using the [ai] tag. It has the following top-level elements:
- description="": (translatable string) This is the text displayed in the MP setup menu when choosing an AI for a computer player.
- id="": (string) The id of the [ai] config snippet. This was originally meant to make it possible to remove [ai] configurations during a game. However, due to the merging process described above, this information is lost. The id is therefore meaningless in the current implementation of the AI.
- version="": (string) [ Todo: Need to look into the C++ code for complete explanation ]
- [stage]: Configuration of the stage(s) used in the AI. Several [stage] tags can be used, even several stages of the same type. They are executed in the order in which they are put into the [ai] tag.
- [aspect]: Configuration of the aspects to be used by the AI. These are in composite aspect format.
- Most aspects can also be provided using the simpler syntax explained at AiWML.
- [goal]: Configuration of the goals to be used by the AI. These are in composite aspect format.
- [engine]: This tag used to be needed for the Lua AI engine to set up the AI code. It is not needed any more.
- formula="": (string) Formula AI code to be executed by the AI. We recommend not using this any more except for extremely simple AIs. See legacy documentation for more information.
The [ai] Tag — Stages
The [ai] tag can contain one or several stages defined in [stage] tags. If the AI configuration contains several stages, they are executed in the order in which they are put into the [ai] tag.
While there are six different types of stages available, all AI functionality possible in Wesnoth can be achieved using only a single one, the candidate action evaluation loop stage. In the default setup, this stage has id main_loop and we generally simply refer to it as the main_loop stage.
Other stages exist mostly for legacy reasons from the times in the AI development when the main_loop stage did not exist yet. They are currently still functional and kept for backward compatibility reasons, but they are not maintained any more and might be removed in a future Wesnoth release cycle. We therefore recommend that all custom AI development is done using the main_loop stage only.
main_loop Stage Configuration
For the main_loop stage, the [ai] tag contains the following elements:
- name: This must be set to 'testing_ai_default::candidate_action_evaluation_loop', so that the AI knows that this is the main_loop stage.
- id: (string) This is the identifier of the AI. It is usually set to 'main_loop', but can take on any value. It only matters if you are planning to remove or modify the stage during a scenario.
- engine=cpp: (string) This must be set to 'cpp', which is also the default value. It can therefore be omitted.
- [candidate_action]: Candidate action configuration tags. See below for details.
Notes:
- As an example, the configuration of the main_loop stage in the default AI is shown here.
- Candidate actions can be using any of the three available engines. Just because the stage uses the cpp engine does not mean that the CAs need to do so as well. See below for an example.
- While that should rarely ever be necessary, it is possible to include several main_loop stage definitions in the same [ai] tag.
- This is done by putting several [stage] tags into the same [ai] tag
- The AI engine then evaluates the CAs of the first stage in the usual way, until no CA returns a valid score any more.
- After the first stage is finished, it moves on to the second stage and repeats the process, until all stages have finished. This ends the AI turn.
- Obviously, this only makes sense if the sets of CAs of the different stages are not identical (although individual CAs might appear in several stages).
Recruitment Stage
A recruitment stage exists. However, this stage is also used by the recruitment_instruction aspect. Anything that can be done with this stage can also be done with the recruitment candidate action using the recruitment_instruction aspect. It should therefore never be necessary to use this stage and we not describe it here.
Legacy Stages
Four other stages are also available. They do, however, not provide any new functionality any more these days, only different ways of achieving the same functionality that is also possible with the main_loop stage. We therefore only list them here for completeness, with brief examples and links to old documentation.
Note that both this documentation and the stages themselves might be removed at some point.
Lua stage
Executes Lua code by calling a function created inside a Lua engine. Whatever element is returned by the code in lua [engine], is accessible here as an upvalue. So, for example, (...):execute() calls whatever_is_returned_by_lua_engine:execute()
Example:
[stage] engine="lua" code= "(...):execute()" [/stage]
See legacy documentation.
Formula AI Side Formulas Stage
This stage executes a given Formula AI side formula.
Example:
[stage] engine=fai name=side_formulas move="write_your_formula_here" [/stage]
See legacy documentation.
Formula AI Unit Formulas Stage
This stage takes no parameters and executes all Formula AI formulas which are attached to units.
Example:
[stage] engine=fai name=unit_formulas [/stage]
See legacy documentation.
Fallback stage
Fall back to other, older AI.
Example:
[stage] id=fallback name=testing_ai_default::fallback [ai] ai_algorithm=default_ai [/ai] [/stage]
This example shows how to set up a stage to fall back to the old default AI (the one used before the current default was introduced). This was useful when it was not clear yet how well the RCA AI would work and whether it would suddenly abandon the CA evaluation loop. There is really no reason to use a fallback stage any more these days.
Available Engines
cpp
This is a default c++-based engine. It parses config snippets by finding a suitable factory by name and using that factory to get a new instance of the object.
no config parameters available
fai
This is a formula ai engine, backed by formula ai. It parses config snippets by parsing formula defined in them.
no config parameters available
lua
This is a lua ai engine. It is still under development with some minor bugs, but works for the most part.
Candidate actions
The [candidate_action] Tag
Candidate actions can be added to the [stage] tag of the main_loop stage using the [candidate_action] tag with the following keys:
- engine: This key is required for Wesnoth to know with which engine the CA is to be processed. Possible values are 'cpp', 'lua' and 'fai'.
- id: The id of the CA is, in principle, optional. However, it is needed if you want to remove or change the CA after its initial definition.
- name: The CAs of the default AI are identified by their name, making this a required key for the cpp engine. The key is optional for other engines.
- max_score: The maximum score the CA evaluation function might return. This parameter is optional, but it is useful to reduce the AI move evaluation time. During each iteration through the evaluation loop, the main_loop stage only evaluates CAs with max_score larger than that of the highest-scoring CA found so far during this iteration. For that same reason, it also makes sense to order CAs by decreasing max_score in the [stage] tag, even though that is not technically necessary.
- score: The score returned by the CA. If this parameter is given, the score of the CA is fixed to this value.
In addition, Lua CAs also contain the following keys:
- location: File name, including path, of the AI code for the CA.
- eval_parms, exec_parms: The parameters to be passed to the evaluation and execution functions of the AI. These need to be in form of a Lua table, without the outer curly brackets. They are passed to these functions as the second argument, cfg. (add link)
Here are examples of [candidate_action] tag uses:
Combat CA of the default AI:
[candidate_action] id=combat engine=cpp name=ai_default_rca::combat_phase max_score=100000 score=100000 [/candidate_action]
Lua AI CA:
[candidate_action] engine=lua name=return_guardian_bob id=return_guardian_bob max_score=100010 location="~add-ons/my_addon/lua/return_guardian.lua" eval_parms="id = 'Bob', return_x = 10, return_y = 15" exec_parms="id = 'Bob', return_x = 10, return_y = 15" [/candidate_action]
Available Candidate Actions
- cpp engine: The available CAs of the default AI are given here.
- lua engine: The Micro_AIs are written using Lua CAs. They can be found here.
- fai engine: A few simple Formula AI CAs can be found in the Wesnoth repository. (add examples)
Aspects and Goals
As far as defining aspect with WML is concerned, aspects can be either simple or composite. Simple aspects are those that take on a single (scalar) value. They can be defined in WML with a single line of code inside an [ai] tag. For example
[ai] aggression=0.765 [/ai]
By contrast, composite aspects are those that do not simply consist of a single key=value pair, either because their structure is more complex (such as a tag) or because additional information is included (such as an aspect id or information as to under what conditions the aspect is applied.
This distinction is only on the scenario creator side though. Internally, the engine treats all aspects as composite and translates the simple aspect definition into a configuration snippet for the aspect component. For the example above, the relevant parts of the configuration look like this:
[aspect] engine=cpp id=aggression [facet] engine=cpp name=standard_aspect value=0.765 [/facet] [default] engine=cpp name=standard_aspect value=0.4 [/default] [/aspect]
This shows the [aspect] tag containing information on which engine should be used to interpret it and its id. The follow the so-called ‘facet’ tags, which define the values the engine returns for the aspect. There is always a [default] facet, which returns the default value of the aspect (0.4 in the case of aggression). In addition, one or several custom facets can be included. In our example, we see how the new value of 0.765 defined above is included in the config.
That’s it for the most part, but even that it is actually not the full aspect config yet. That looks like this:
[aspect] engine=cpp id=aggression invalidate_on_gamestate_change=no invalidate_on_minor_gamestate_change=no invalidate_on_tod_change_change=yes invalidate_on_turn_start=yes name=composite_aspect [facet] engine=cpp id= invalidate_on_gamestate_change=no invalidate_on_minor_gamestate_change=no invalidate_on_tod_change_change=yes invalidate_on_turn_start=yes name=standard_aspect time_of_day= turns= value=0.765 [/facet] [default] ... (omitted for brevity, same as above) value=0.4 [/default] [/aspect]
Thus, we see, that a facet may also contain an id (important if one wants to delete it selectively), the time of day and turns for which it is valid, and several invalidate_on_... keys. The AI code stores information derived from the aspects in C++ objects. This information can simply be the aspect value for some aspects (such as aggression) or it can contain a significant amount of additional information. For example, for the attacks aspect, it contains a list of all possible attacks of the filtered attacker/target unit pairs. This list, originally established at the beginning of the AI turn, is not valid any more after the first attack has been performed and needs to be reset. The AI does this by 'invalidating' the aspect, after which the aspect information is read anew from the [ai] tags and the stored information (the list of attacks, in this case) is reevaluated.
There are 4 levels of invalidation keys:
- invalidate_on_turn_start="yes": (boolean) If "yes", the value of this aspect is invalidated at the start of each AI turn.
- invalidate_on_tod_change="yes": (boolean) If "yes", the value of this aspect is invalidated when the time of day changes (not working at the moment). This implies invalidate_on_turn_start.
- invalidate_on_gamestate_change="no": (boolean) If "yes", the value of this aspect is invalidated on each game state change (on turn start, move, attack, recruit, etc.). This implies invalidate_on_turn_start.
- invalidate_on_minor_gamestate_change="no": (boolean) If "yes", the value of this aspect is invalidated on each minor game state change (on set unit variable, etc). This implies invalidate_on_gamestate_change.
Thus, information stored about aspects is reevaluated by default at each AI turn and when the time of day changes. It is not reevaluated after the game state changes (such as after an attack), which explains why 'invalidate_on_gamestate_change=yes' needs to be set explicitly for the attacks aspect.
Hint: If unsure, the easiest way to see the full config for any given aspect (or any other AI component, in fact) is either in savefiles, or in-game by typing :inspect in debug mode and choosing 'ai config full' for a team.
Goals
Goals are simply a special type of aspect, so they are stored in configs in exactly the same way as shown above. The only difference from many of the other aspects is that they can never be defined by a single key=value pair. Thus, they are always composite aspects.