Difference between revisions of "AI Recruitment"
(→Combat Analysis) |
(→Combat Analysis) |
||
Line 21: | Line 21: | ||
''Implementation details for interested readers:'' | ''Implementation details for interested readers:'' | ||
− | Combat Analysis will use the function <code>compare_unit_types(a, b)</code>. It takes two unit-types and returns a positive value if unit-type a is better then b and a negative value if unit-type b is better then a. If the return value is 2.0 it means that unit-type a is twice as good as unit-type b. | + | Combat Analysis will use the function <code>compare_unit_types(a, b)</code>. It takes two unit-types, simulates a fight (it uses a cache, because simulation is expensive) and returns a positive value if unit-type <code>a</code> is better then <code>b</code> and a negative value if unit-type <code>b</code> is better then <code>a</code>. If the return value is 2.0 it means that unit-type a is twice as good as unit-type b. |
Here is a important code-snipped of <code>compare_unit_types()</code>: | Here is a important code-snipped of <code>compare_unit_types()</code>: | ||
Line 34: | Line 34: | ||
return 0.; | return 0.; | ||
} | } | ||
+ | |||
+ | The return-value of <code>compare_unit_types()</code> will be multiplied by the enemies current hp and added to the score map. | ||
+ | |||
+ | At this point the scores could be quite unhandy. They could all be negative, very high or to similar. So the scores will be transformed linear. The resulting scores are between 0.0 and 100.0. | ||
+ | |||
+ | Simplified code-snipped: | ||
+ | double new_100 = max_score; | ||
+ | double new_0 = max_score - (1.5 * (max_score - average_score)); | ||
+ | |||
+ | for all scores: | ||
+ | double new_score = 100 * ((score - new_0) / (new_100 - new_0)); // linear transformation | ||
+ | end for; | ||
=Aspect recruitment_instruction= | =Aspect recruitment_instruction= |
Revision as of 12:44, 12 September 2013
This page is work in progress
The new Recruitment Candidate Action is highly configurable and supports multiple leader recruiting...
Contents
How it works
Map analyis
In a first step the CA will analyse the map and try to find "important hexes". Those are locations on the map where a fight will occur with high probability. The important hexes are used later in combat simulations to calculate a average defense for the combatants.
If the game runs in debug mode the important hexes will be displayed with a white circle on them.
Implementation details for interested readers: [...]
Score Map
For all leaders which are available for recruiting a score map will be created including all unit-types from the recruit- and recall lists. Then the scores are filled with values coming from different functions (see below).
Combat Analysis
For each unit-type our leaders can recruit the CA will simulate a fight with all enemy units on the map (If there are less then 5 enemy units, the enemies recruitment list(s) will be taken into account)
Implementation details for interested readers:
Combat Analysis will use the function compare_unit_types(a, b)
. It takes two unit-types, simulates a fight (it uses a cache, because simulation is expensive) and returns a positive value if unit-type a
is better then b
and a negative value if unit-type b
is better then a
. If the return value is 2.0 it means that unit-type a is twice as good as unit-type b.
Here is a important code-snipped of compare_unit_types()
:
double value_of_a = damage_to_b / (b_max_hp * a_cost); double value_of_b = damage_to_a / (a_max_hp * b_cost); if (value_of_a > value_of_b) { return value_of_a / value_of_b; } else if (value_of_a < value_of_b) { return -value_of_b / value_of_a; } else { return 0.; }
The return-value of compare_unit_types()
will be multiplied by the enemies current hp and added to the score map.
At this point the scores could be quite unhandy. They could all be negative, very high or to similar. So the scores will be transformed linear. The resulting scores are between 0.0 and 100.0.
Simplified code-snipped:
double new_100 = max_score; double new_0 = max_score - (1.5 * (max_score - average_score)); for all scores: double new_score = 100 * ((score - new_0) / (new_100 - new_0)); // linear transformation end for;
Aspect recruitment_instruction
Examples
Recruit 3 Grunts (and nothing more) in turn 3-5.
[ai] [aspect] id=recruitment-instructions [facet] turns=3-5 [value] [recruit] type=Orcish Grunt number=3 [/recruit] [/value] [/facet] [/aspect] [/ai]
Recruit so, that there are at least 4 scouts in total and then recruit other units.
[ai] [aspect] id=recruitment-instructions [facet] [value] [recruit] type=scout number=4 total=yes importance=1 [/recruit] [recruit] importance=0 [/recruit] [/value] [/facet] [/aspect] [/ai]
Recruit 6 Grunts or level 2 units (whatever seems better for the AI) and nothing more.
[ai] [aspect] id=recruitment-instructions [facet] [value] [recruit] type=Orcish Grunt, 2 number=6 [/recruit] [/value] [/facet] [/aspect] [/ai]
Recruit 5 scouts with leader1 and 5 Grunts with leader 2. Do even try to recruit the Grunts if leader1 can not recruit all of the scouts.
[ai] [aspect] id=recruitment-instructions [facet] [value] [recruit] type=scout number=5 importance=2 leader_id=leader1 blocker=no [/recruit] [recruit] type=Orcish Grunt number=5 importance=1 leader_id=leader2 [/recruit] [/value] [/facet] [/aspect] [/ai]
Do not recruit in turn 4.
[ai] [aspect] id=recruitment-instructions [facet] turns=4 [value] [recruit] importance=1 number=0 [/recruit] [/value] [/facet] [/aspect] [/ai]
This will not work. Only one facet can be active.
[ai] [aspect] id=recruitment-instructions [facet] turns=1-10 [value] [recruit] type=scout number=5 importance=1 [/recruit] [/value] [/facet] [facet] turns=3 [value] [recruit] type=Orcish Grunt number=3 importance=2 [/recruit] [/value] [/facet] [/aspect] [/ai]
To achieve this behavior one have to create a facet for turn 1-2, a facet for turn 3 and another facet for turn 4-10.