Difference between revisions of "Modifying AI Components"

From The Battle for Wesnoth Wiki
(Modifying AI Component Examples: start cleaning up examples)
(Modifying Standard Aspects: add two more macro examples)
Line 148: Line 148:
 
     path=aspect[aggression].facet[my_custom_aggression]
 
     path=aspect[aggression].facet[my_custom_aggression]
 
  [/modify_ai]
 
  [/modify_ai]
 +
 +
The macro versions of this are
 +
{MODIFY_AI_ADD_ASPECT 1 aggression (       
 +
    [facet]
 +
        id=my_custom_aggression
 +
        value=0.765
 +
    [/facet]
 +
)}
 +
and
 +
{MODIFY_AI_DELETE_ASPECT 1 aggression my_custom_aggression}
  
 
'''Notes:'''  
 
'''Notes:'''  

Revision as of 21:03, 22 February 2016

This page is currently under construction (Feb 2016)

Methods for Modifying the AI Mid Scenario

The AI and its parameters are usually set up at the beginning of a scenario and often left unchanged for the entire scenario. See AiWML and Creating_Custom_AIs for instructions on how to do this, or the complete list of AI resources at Wesnoth_AI.

Sometimes it is, however, desirable to modify parts or all of the AI mid-scenario. Wesnoth provides different tools to accomplish this:

  • Standard aspects can be modified mid scenario using the [modify_side] tag
  • Micro AIs can be modified mid scenario using the [micro_ai] tag
  • Composite aspects, goals and all other AI components can be modified mid scenario using the [modify_ai] tag.
  • There are also a large number of helper macros available for these tasks.

This page contains instructions for all these tasks together with a large number of examples.

Using [modify_side] to Change Aspects Mid Scenario

The [modify_side] tag can contain an [ai] tag for modifying aspects while a game is in progress. This works, however, only for standard aspects. An example is

[modify_side]
    side=2
    [ai]
        aggression=0.999
    [/ai]
[/modify_side]

Composite aspects and all other AI components cannot be modified in this way. Use the [modify_ai] tag described below for these tasks.

Note that modifying an aspect in this fashion does not replace the facet used to define the aspect in the AI configuration. It simply adds another facet that then takes preference over the already existing ones. In most situations, this does not make a difference, but there might be some cases (for example when aspects are only defined for certain times of day or turns), when it might be necessary to replace the existing facet rather than adding a new one. This can also be done using the [modify_ai] tag.

Using the [micro_ai] Tag to Add or Modify Micro AIs Mid Scenario

The [micro_ai] tag is always used in an event. There is no difference between using it at the beginning of the scenario, that is, in a prestart or start event, or in any other event. See Micro_AIs for details.


The [modify_ai] Tag

The [modify_ai] tag is a tool for modifying stages, candidate actions, ascpects and goals of the active AI on the fly at any time during a scenario. Since all this functionality is packed into a single tag, its syntax is a bit more complex than that of other tags, but it is well worth spending a little time trying to understand how it works. If you do not want to bother with that, Wesnoth also provides a large variety of helper macros. These are described farther below on this page.

Note that the [modify_ai] tag can be used both in [event] tags and in [side][ai] tags.

[modify_ai] Tag Syntax

The [modify_ai] tag takes the following keys:

  • side: The side of the AI to be modified if used in an event. This key is not needed if used in [side][ai]. In fact, it is ignored in that case, if given.
  • action (string): The action to take concerning the component. The following values are allowed:
    • add: Add a component.
    • change: Change an existing component.
    • delete: Delete an existing component.
    • try_delete: Delete a component if it exists. This does not produce a warning if [modify_ai] fails to change the AI.
  • path (string): Defines the component of the AI to be modified. More on this below.
  • value (key or tag): Defines the new value(s) of the component. See below for details

Possible values for [modify_ai]path

Depending on the AI component one wants to modify, the path key can take on different values:

  • aspect[aspect_id].facet[facet_id]
  • goal[goal_id]
  • stage[stage_id]
  • stage[CA_avaluation_loop_stage_id].candidate_action[CA_id]

Notes on the different ids:

  • aspect_id: name of the aspect, such as aggression
  • CA_avaluation_loop_stage_id: usually this will be main_loop, although it is in principle possible to assign a different id to this stage
  • CA_id: takes on the value described here
  • facet_id, goal_id and stage_id: these can take on a variety of different formats:
    • When adding one of these components, these ids are meaningless. In fact, they do not define the actual ids and can therefore simply be left empty. Instead, the ids are either assigned automatically or can be defined in the value key/tag of [modify_ai]. More on that below.
    • By contrast, when deleting or changing a component, these ids need to be given. The following values are possible:
      • A string identifying the id used when defining the component
      • An integer, starting at 0, defining the number of the aspect in the order in which they were set up
      • *: All components of this type

Possible values for [modify_ai]value

This depends on the type of component and needs to be in the same format as these are added to the AI configuration. A summary of these is given here. The syntax can also be seen using the in-game gamestate inspector dialog, by typing ':inspect' in debug mode and selecting 'ai config full'.

[Todo: not sure yet whether to add examples for all component types here, or simply to go with the examples below.]

If all this seemed a bit theoretical, don't worry. We provide many examples how to do this in practice below.

Modifying AI Components Helper Macros

A large number of helper macros are available to simplify the WML needed for modifying AI components. These macros are defined in file 'data/core/macros/ai.cfg', see the list of available macros or the full definitions.

We do not describe the individual macros here. Instead, a variety of examples are given in the next section. If in doubt how to use a macro, check out its definition at the link above. That will also give you a template for the WML code if you do not want to use macros.

Modifying AI Component Examples

WARNING: Currently this is just a collection of code snippets from all over the place, so that they don't get lost. This will be organized and cleaned up shortly.’’’

Modifying Standard Aspects

Standard aspects, and only standard aspects, can be modified using [modify_side]. A simple example is

[modify_side]
    side=1
    [ai]
        aggression=0.765
    [/ai]
[/modify_side]

This is the simplest syntax for modifying standard aspects (without using macros). Nevertheless, [modify_ai] and composite aspect syntax can also be used

[modify_ai]
    side=1
    action=add
    path=aspect[aggression].facet[]
    [facet]
        value=0.765
    [/facet]
[/modify_ai]

The same can be accomplished with a single line using one of the helper macros

{MODIFY_AI_ADD_SIMPLE_ASPECT 1 aggression 0.765}

This custom setting of the aggression aspect can then be deleted using

[modify_ai]
    side=1
    action=delete  # or try_delete
    path=aspect[aggression].facet[0]
[/modify_ai]

if we know that it is the first non-default facet of the aggression aspect that needs to be removed. If, instead, we want to remove all custom definitions of aggression, we use

[modify_ai]
    side=1
    action=delete  # or try_delete
    path=aspect[aggression].facet[*]
[/modify_ai]

Using macros, this is done with

{MODIFY_AI_DELETE_ASPECT 1 aggression 0}

and

{MODIFY_AI_DELETE_ASPECT 1 aggression "*"}

If we don't know the number of the facet and do not want to remove all of them, we need to assign an id to the facet defining the aspect (the simple syntax of the very first example cannot be used in that case) and use that id for selective removal. For example, the definition could look like this

[modify_ai]
    side=1
    action=add
    path=aspect[aggression].facet[]
    [facet]
        id=my_custom_aggression
        value=0.765
    [/facet]
[/modify_ai]

and removal like this

[modify_ai]
    side=1
    action=delete  # or try_delete
    path=aspect[aggression].facet[my_custom_aggression]
[/modify_ai]

The macro versions of this are

{MODIFY_AI_ADD_ASPECT 1 aggression (        
    [facet]
        id=my_custom_aggression
        value=0.765
    [/facet]
)}

and

{MODIFY_AI_DELETE_ASPECT 1 aggression my_custom_aggression}

Notes:

  • The aspect itself and its default facet cannot be deleted, only the custom facets.
  • For standard aspects, it is generally not necessary to delete custom facets. One can simply overwrite the current value with a new one. The only times when one might have to remove a standard aspect is when it is defined for specific times of day or turns, or when it is defined so many times that it might bloat the AI configuration (and therefore the savefile).
  • We can also use action=change to delete an existing facet and overwrite it with a new definition. If * is used as facet_id, this deletes all existing facets of this aspect and replace them by a single facet with the new definition. Adding a facet with the same id as an existing facet overwrites the previous occurrence, making this equivalent to changing that facet.

Modifying Composite Aspects

[modify_ai]
    side=2
    action=add
    path=aspect[attacks].facet[]
    [facet]
        invalidate_on_gamestate_change=yes
        [filter_own]
            type=Elvish Sorceress,Elvish Enchantress,Elvish Sylph
        [/filter_own]
        [filter_enemy]
            race=undead
        [/filter_enemy]
    [/facet]
[/modify_ai]

Sometimes we might want to define several facets of the same aspect, but don't know in advance in which order they will be created. If we then only want to delete some of them selectively, we need to use facets with specific id's, such as

[modify_ai]
    side=1
    action=add
    path=aspect[aggression].facet[]
    [facet]
        id=aggression_dusk
        time_of_day=dusk
        value=0.765
    [/facet]
[/modify_ai]

This can also be done using macros

{MODIFY_AI_ADD_ASPECT 1 aggression (        
    [facet]
        id=aggression_dusk
        time_of_day=dusk
        value=0.765
    [/facet]
)}

This can be deleted by referencing that id

[modify_ai]
    side=1
    action=delete  # or try_delete
    path=aspect[aggression].facet[aggression_dusk]
[/modify_ai]

or

{MODIFY_AI_DELETE_ASPECT 1 aggression aggression_dusk}

A large number of other helper macros for AI modifications is available in data/core/macros/ai.cfg. An example of setting/changing a complex aspect using these macros is:

{MODIFY_AI_ADD_ASPECT 1 recruitment_instructions (
    [facet]
        [value]
            [recruit]
                type=2
                number=2
                total=yes
                importance=1
            [/recruit]
            [recruit]
                type=1
                importance=0
            [/recruit]
        [/value]
    [/facet]
)}

Note that here [value] is a tag not a key (value=) as in the examples used for 'aggression' above, since the content of the tag is more than a single number. If in doubt what syntax to use, go into the gamestate inspector but typing :inspect in-game and check out the [default] tag for the respective aspect under 'ai config full'.

{AI_SIMPLE_ALWAYS_ASPECT recruitment_pattern "fighter,fighter,archer,healer"}
{AI_SIMPLE_ALWAYS_ASPECT_VALUE aggression "0.7"}


Example:

{AI_SIMPLE_ALWAYS_ASPECT_VALUE avoid
(
    [not]
        x,y=20,16
        radius=6
    [/not]
)}
{MODIFY_AI_ADD_ASPECT 2 avoid (
    [facet]
        id="stay_in_own_land"
        [value]
            [not]
                x=20-24,19-30
                y=10,11
            [/not]
        [/value]
    [/facet]
)}


To modify goals from WML events, use these helper macros (don't forget to give your [goal]s unique ids):

 {MODIFY_AI_ADD_GOAL SIDE GOAL_CONFIG}
 {MODIFY_AI_DELETE_GOAL SIDE GOAL_ID}
 {MODIFY_AI_TRY_DELETE_GOAL SIDE GOAL_ID}


To work with this stage, we can either add or delete candidate actions. To do this, there are macroses, {MODIFY_AI_ADD_CANDIDATE_ACTION SIDE STAGE_ID CANDIDATE_ACTION} and {MODIFY_AI_DELETE_CANDIDATE_ACTION SIDE STAGE_ID CANDIDATE_ACTION_ID}. Internally, these are simple macroses which use the [modify_ai] tag. Those macroses can be used either in [side][ai] or in [event] - so, it is possible to modify the AI at any moment of the game, from a WML event handler.

Example: making the AI of side 2, which does not recruit (by removing recruitment-related candidate actions)

[side]
  side=2
  {ai/aliases/stable_singleplayer.cfg}
  [ai]
     {MODIFY_AI_DELETE_CANDIDATE_ACTION 2 main_loop recruitment}
     {MODIFY_AI_DELETE_CANDIDATE_ACTION 2 main_loop move_leader_to_keep}
  [/ai]
[/side]

Example: same things as above, but from an arbitrary [event] (this is recommended way to do things, since it's easier to test if it's in standalone event handler)

[side]
  side=2
  {ai/aliases/stable_singleplayer.cfg}
[/side]
[event]
  name=ai_2_stop_recruiting
  {MODIFY_AI_DELETE_CANDIDATE_ACTION 2 main_loop recruitment}
  {MODIFY_AI_DELETE_CANDIDATE_ACTION 2 main_loop move_leader_to_keep}
[/event]

Finally note that [modify_ai] in [side][ai] is activated when the AI is first initialized. It is guaranteed to happen before the AI acts for the first time, but otherwise it can happen at any time, for example, when the game is saved. So, for example, you might see the uninitialized version of the config (with unapplied [modify_ai] tags) if using ':inspect' right after the scenario start.