Difference between revisions of "Formula AI Howto"

From The Battle for Wesnoth Wiki
(Testing Setup)
(Testing Setup)
Line 22: Line 22:
 
==Testing Setup==
 
==Testing Setup==
  
Testing Formula AI code is, in principle, very easy.  Simply type 'f' in the Wesnoth window and then enter the code to be executed.  That's a lot of typing, it is easier to put the code into a file (say '~add-ons/FAI_tests/fai_manual.fai') and run it by typing
+
Testing Formula AI code is, in principle, very easy.  Simply type 'f' in the Wesnoth window (which accesses the Formula AI command line) and then enter the code to be executed.  That's a lot of typing, however.  It is easier to put the code into a file (say '~add-ons/FAI_tests/fai_manual.fai') and run it by typing
 
  run_file('~add-ons/FAI_tests/fai_manual.fai')
 
  run_file('~add-ons/FAI_tests/fai_manual.fai')
  
Still easier is to include that line as a comment in the file itself and copy it.  Then we can simply type 'f' and 'cmd-v' (or whatever the paste keyboard shortcut is) to execute our test code.  As an example, consider this file:
+
Still easier is to include that line as a comment in the file itself and copy it to the Formula AI command line.  Then we can simply type 'f' and 'cmd-v' (or whatever the paste keyboard shortcut is) to execute our test code.  As an example, consider this file:
  
 
  fai 'fai_manual.fai'
 
  fai 'fai_manual.fai'
Line 36: Line 36:
 
  faiend
 
  faiend
  
Here, the first and last line are technically unnecessary, but it is good practice to include them in all Formula AI files as they can be useful for debugging purposes.  The second line is the ''run_file'' command mentioned above, that can now be easily copy-pasted into the Formula AI command line.  Note that comments in Formula AI require the '#' symbol both at the beginning and end of the line.
+
Here, the first and last line are technically unnecessary, but it is good practice to include them in all Formula AI files as they can be useful for debugging purposes.  The second line is the 'run_file' command mentioned above, that can now be easily copy-pasted into the Formula AI command line.  Note that comments in Formula AI require the '#' symbol both at the beginning and end of the line.
  
The body of this example is a very simple, but powerful command: ''dir(self)''.  It displays all available Formula AI variables.  Its output shows that there is a variable ''my_units''.  If we want to see the structure and content of this variable, we replace the body of the file above with
+
The body of this example is a very simple, but powerful command: 'dir(self)'.  It displays all available Formula AI variables.  Its output shows that there is a variable ''my_units''.  If we want to see the structure and content of this variable, we replace the body of the file above with
 
  my_units
 
  my_units
 
or type that at the command line, since it is so short.  In order to get the first of these unit, use
 
or type that at the command line, since it is so short.  In order to get the first of these unit, use
Line 51: Line 51:
 
   
 
   
 
  get_unit(self, 'Rark')
 
  get_unit(self, 'Rark')
 +
 +
In the function call, 'self' passes the set of Formula AI variables to the function, the same set that was queried with 'dir(self)' above.  It is put into variable ''ai'' in the function, with the '*' denoting ''ai'' as an implicit variable (meaning the variable holding the units can be accessed with ''my_units'' instead of ''ai.my_units).
  
 
So much for some very simple examples.  For full documentation of the Formula AI language see [[FormulaAI]] and [[FormulaAI Functions]].  We are now ready for testing AI behavior.  Let's assume that we have set up a test situation with one of our units (id = "Rark") and an enemy unit (id = "Krar") within reach of Rark.  We want to test how to move Rark to the hex south of Krar.  The body of '~add-ons/FAI_tests/fai_manual.fai' is now
 
So much for some very simple examples.  For full documentation of the Formula AI language see [[FormulaAI]] and [[FormulaAI Functions]].  We are now ready for testing AI behavior.  Let's assume that we have set up a test situation with one of our units (id = "Rark") and an enemy unit (id = "Krar") within reach of Rark.  We want to test how to move Rark to the hex south of Krar.  The body of '~add-ons/FAI_tests/fai_manual.fai' is now
 +
 +
move(me.loc, loc(target.loc.x, target.loc.y+1) )
 +
 +
where me = filter(my_units, id = 'Rark')[0]
 +
 +
where target = filter(enemy_units, id = 'Krar')[0]
 +
 +
The important thing here is that we have now set up a mechanism that creates the ''me'' and ''target'' variables as they are used in the stages described above.  We can therefore replace the simple move used here with whatever AI behavior we want to test.  Once we are done with testing, we can simply copy the code above the two 'where' lines into the AI stages or candidate actions.
 +
 +
Note that the Formula AI functions and variables do not need to be initialized.  They are available at every turn for each side.  Thus, we do not need to go through the tricks described for testing [[Lua_AI_Howto#Testing_setup|Lua AI]], but can simply set up Side 1 with 'controller=human' and start with the testing.
  
 
== Adding / Deleting Stages and Candidate Actions ==
 
== Adding / Deleting Stages and Candidate Actions ==

Revision as of 21:09, 21 November 2011

This page is meant as a practical guide for setting up and testing Formula AI functionality in a scenario. It does not give a complete description of the Formula AI language. See FormulaAI and FormulaAI Functions for that. Make sure you have read the General RCA AI Howto as a basic understanding of the purpose of AI engines, stages and candidate actions is assumed here.

Also note that we do not explain all the different ways of setting things up here. Instead, we focus on one specific method that works reasonably well. Using variations thereof will hopefully be straightforward once the principles are understood.

Formula AI Setup

Unlike Lua AI, Formula AI does not require an engine to be set up, and (usually) no global variables need to be defined up front either. Thus, only one component needs to be set up, the stage, or stages, controlling Formula AI behavior. Three different stages are available for Formula AI code:

The stages are executed in this order. That is, first all unit moves are executed, then all side-wide moves are played out, and finally all candidate actions are evaluated and executed based on their evaluation scores. Then the turn ends.

Note: The AI Module module page mentions another Formula AI stage called 'rca_formulas'. However, that stage does not exist in the current version. [Todo: test whether [register_candidate_actions] works with the RCA AI stage.]

Setting up the Formula AI Unit Formulas Stage

Setting up the Formula AI Side Formulas Stage

Setting up the RCA main_loop Stage and Candidate Actions

Testing Setup

Testing Formula AI code is, in principle, very easy. Simply type 'f' in the Wesnoth window (which accesses the Formula AI command line) and then enter the code to be executed. That's a lot of typing, however. It is easier to put the code into a file (say '~add-ons/FAI_tests/fai_manual.fai') and run it by typing

run_file('~add-ons/FAI_tests/fai_manual.fai')

Still easier is to include that line as a comment in the file itself and copy it to the Formula AI command line. Then we can simply type 'f' and 'cmd-v' (or whatever the paste keyboard shortcut is) to execute our test code. As an example, consider this file:

fai 'fai_manual.fai'
# run_file('~add-ons/FAI_tests/fai_manual.fai') #
# ---- Place test code below ----- #

dir(self)

# ---- Place test code above ----- #
faiend

Here, the first and last line are technically unnecessary, but it is good practice to include them in all Formula AI files as they can be useful for debugging purposes. The second line is the 'run_file' command mentioned above, that can now be easily copy-pasted into the Formula AI command line. Note that comments in Formula AI require the '#' symbol both at the beginning and end of the line.

The body of this example is a very simple, but powerful command: 'dir(self)'. It displays all available Formula AI variables. Its output shows that there is a variable my_units. If we want to see the structure and content of this variable, we replace the body of the file above with

my_units

or type that at the command line, since it is so short. In order to get the first of these unit, use

my_units[0]

and for its location (many Formula AI functions use the unit location)

my_units[0].loc

To select the unit with id "Rark", we type

filter(my_units, id='Rark')[0]

and if we wanted to do this using a function

def get_unit(ai*, unit_id)
    filter(my_units, id = unit_id)[0];

get_unit(self, 'Rark')

In the function call, 'self' passes the set of Formula AI variables to the function, the same set that was queried with 'dir(self)' above. It is put into variable ai in the function, with the '*' denoting ai as an implicit variable (meaning the variable holding the units can be accessed with my_units instead of ai.my_units).

So much for some very simple examples. For full documentation of the Formula AI language see FormulaAI and FormulaAI Functions. We are now ready for testing AI behavior. Let's assume that we have set up a test situation with one of our units (id = "Rark") and an enemy unit (id = "Krar") within reach of Rark. We want to test how to move Rark to the hex south of Krar. The body of '~add-ons/FAI_tests/fai_manual.fai' is now

move(me.loc, loc(target.loc.x, target.loc.y+1) )

where me = filter(my_units, id = 'Rark')[0]

where target = filter(enemy_units, id = 'Krar')[0]

The important thing here is that we have now set up a mechanism that creates the me and target variables as they are used in the stages described above. We can therefore replace the simple move used here with whatever AI behavior we want to test. Once we are done with testing, we can simply copy the code above the two 'where' lines into the AI stages or candidate actions.

Note that the Formula AI functions and variables do not need to be initialized. They are available at every turn for each side. Thus, we do not need to go through the tricks described for testing Lua AI, but can simply set up Side 1 with 'controller=human' and start with the testing.

Adding / Deleting Stages and Candidate Actions

Stages and candidate actions can be added and removed at any time in the scenario. A large number of macros are available in core/macros/ca.cfg for this purpose.

Here are two code examples of deleting candidate actions from the default RCA AI stage taken from Customizing_AI_in_Wesnoth_1.8. The first is done right at the beginning during the side definition:

[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]

The second is done in an event:

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

Examples: Formula AI Code Library

Many examples of Formula AI code can be found found in the Formula AI Code Library page and in this forum thread.

A Few More Useful Tidbits

  • dir(self): ...