Author: dragonking
Date: Wed Jul 30 16:47:14 2008
New Revision: 28267
URL: http://svn.gna.org/viewcvs/wesnoth?rev=28267&view=rev
Log:
Some improvements to formula recruitment
Modified:
trunk/data/recruitment.fai
Modified: trunk/data/recruitment.fai
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/data/recruitment.fai?rev=28267&r1=28266&r2=28267&view=diff
==============================================================================
--- trunk/data/recruitment.fai (original)
+++ trunk/data/recruitment.fai Wed Jul 30 16:47:14 2008
@@ -1,7 +1,9 @@
# ===== Some general functions used later ==== #
def sumarize_values( input_map )
- sum(values(input_map));
+ sum(
+ values(input_map)
+ );
def lowest_value( input_map )
choose( input_map, -value ).value;
@@ -20,6 +22,7 @@
);
#make sure we have only positive values in a map #
+
def make_positive_only( input_map )
if( lowest_value( input_map ) < 0,
add_number_to_values(
@@ -38,20 +41,64 @@
# ==1== evaluate average defense #
#gives map where key is id of terrain, and value is number of hexes of that
terrain on a gamemap#
+
def locations_map(ai*)
- tomap( map( map.terrain, id ) );
+ tomap(
+ map(
+ map.terrain,
+ id
+ )
+ );
#filters terrain map, min_percent it minimal % of map that terrain has to
occupy to be considered in later evaluations#
+
def filtered_locations_map(ai*, min_percent)
- filter( locations_map(ai) , value > (map.w * map.h)/(100/min_percent) );
+ filter(
+ locations_map(ai) ,
+ value > (map.w * map.h) / ( 100 / min_percent )
+ );
#returns average defense of the unit #
+
def unit_average_defense(ai*, unit, terrain_min_percent )
- sum( values( map(filtered_locations_map(ai,terrain_min_percent),
defense_on(unit, find(map.terrain,id=key).loc)*value) ) ) /
sum(values(filtered_locations_map(ai,terrain_min_percent)));
+ sum(
+ values(
+ map(
+ filtered_locations_map(ai,terrain_min_percent),
+ defense_on(
+ unit,
+ find(map.terrain,id=key).loc
+ ) *
+ value
+ )
+ )
+ ) /
+ sum(
+ values(
+ filtered_locations_map(
+ ai,
+ terrain_min_percent
+ )
+ )
+ );
#returns map of units from units_list and their average defense (more ->
better) #
+
def map_units_average_defense(ai*, units_list, terrain_min_percent)
- tomap(map( units_list, id ), map( units_list, 'unit',
unit_average_defense(ai, unit, terrain_min_percent ) ) );
+ tomap(
+ map(
+ units_list,
+ id
+ ),
+ map(
+ units_list, 'unit',
+ unit_average_defense(
+ ai,
+ unit,
+ terrain_min_percent
+ )
+ )
+ );
# ==2== TODO: evaluate unit effectivness based on movement points and movement
cost#
@@ -60,55 +107,230 @@
# ==1== based on unit cost and current amount of gold #
# returns number between 0 and 100 where: 0 we are losing, 100 we are winning #
+
def units_cost_gold_eval(ai*)
- min([((sum(map(allies, 'team', sum(map(units_of_side[team], cost)) +
teams[team].gold )) * 100) / sum(map(enemies, 'team',
sum(map(units_of_side[team], cost)) + max([teams[team].gold, 0]) )))/2, 100]);
+ min(
+ [
+ (
+ (
+ sum(
+ map(
+ allies, 'team',
+ sum(
+ map(
+
units_of_side[team],
+ cost
+ )
+ ) +
+ teams[team].gold
+ )
+ ) *
+ 100
+ ) /
+ sum(
+ map(
+ enemies, 'team',
+ sum(
+ map(
+
units_of_side[team],
+ cost
+ )
+ ) +
+ max(
+ [teams[team].gold, 0]
+ )
+ )
+ )
+ ) / 2,
+ 100
+ ]
+ );
# ==2== based on village possession #
def count_allied_villages(ai*)
- sum(map(allies, 'side', size(villages_of_side[side]) ));
+ sum(
+ map(
+ allies, 'side',
+ size(
+ villages_of_side[side]
+ )
+ )
+ );
def count_enemy_villages(ai*)
- sum(map(enemies, 'side', size(villages_of_side[side]) ));
+ sum(
+ map(
+ enemies, 'side',
+ size(
+ villages_of_side[side]
+ )
+ )
+ );
# multipled by 1000 to increase precision #
+
def village_evaluation(ai*)
- (50000 + (count_allied_villages(ai) - count_enemy_villages(ai)) *
(50000/size(villages)))/1000;
+ (
+ 50000 +
+ (
+ count_allied_villages(ai) -
+ count_enemy_villages(ai)
+ ) *
+ (
+ 50000 /
+ size(
+ villages
+ )
+ )
+ ) /
+ 1000;
# ==3== combined 2 of the above #
def eval(ai*)
- ( units_cost_gold_eval(ai) + village_evaluation(ai) ) / 2;
+ (
+ units_cost_gold_eval(ai) +
+ village_evaluation(ai)
+ ) /
+ 2;
#===== Evaluation how effective my units are against the enemy
===== #
#==1== basic evaluation #
# evaluate how much damage unit can inflict - how much damage unit can get#
+
def evaluate_attacker_against_opponents(ai*, unit, enemy_units)
- sum( map( enemy_units, 'enemy_unit',
sum(map([max_possible_damage_with_retaliation( unit, enemy_unit )], self[0] -
self[1]) )) );
+ sum(
+ map(
+ enemy_units, 'enemy_unit',
+ sum(
+ map(
+ [
+
max_possible_damage_with_retaliation( unit, enemy_unit )
+ ],
+ self[0] - self[1]
+ )
+ )
+ )
+ );
def evaluate_defender_against_opponents(ai*, unit, enemy_units)
- sum( map( enemy_units, 'enemy_unit',
sum(map([max_possible_damage_with_retaliation( enemy_unit, unit )], self[1] -
self[0]) )) );
+ sum(
+ map(
+ enemy_units, 'enemy_unit',
+ sum(
+ map(
+ [
+
max_possible_damage_with_retaliation( enemy_unit, unit )
+ ],
+ self[1] - self[0]
+ )
+ )
+ )
+ );
def units_hp_map(ai*, units)
- tomap( map(units, id), map( units, hitpoints));
+ tomap(
+ map(
+ units,
+ id
+ ),
+ map(
+ units,
+ hitpoints
+ )
+ );
#in case side's gold is more than 50, add units that side can recruit to the
side's unit list#
+
def create_side_unit_list(ai*, side)
- if( teams[side].gold > 50, recruits_of_side[side], []) +
units_of_side[side];
+ if(
+ teams[side].gold > 50,
+ recruits_of_side[side],
+ []
+ ) +
+ units_of_side[side];
def evaluate_my_recruits_as_attackers(ai*)
- tomap( map(my_recruits, id), map( my_recruits, 'my_unit', sum(map(
enemies, 'enemy_side', evaluate_attacker_against_opponents(ai, my_unit,
create_side_unit_list(ai, enemy_side))))));
+ tomap(
+ map(
+ my_recruits,
+ id
+ ),
+ map(
+ my_recruits, 'my_unit',
+ sum(
+ map(
+ enemies, 'enemy_side',
+ evaluate_attacker_against_opponents(
+ ai,
+ my_unit,
+ create_side_unit_list(
+ ai,
+ enemy_side
+ )
+ )
+ )
+ )
+ )
+ );
def evaluate_attackers(ai*)
- change_numbers_to_percents(
make_positive_only(evaluate_my_recruits_as_attackers(ai)) );
+ change_numbers_to_percents(
+ make_positive_only(
+ evaluate_my_recruits_as_attackers( ai )
+ )
+ );
def evaluate_my_recruits_as_defenders(ai*)
- tomap( map(my_recruits, id), map( my_recruits, 'my_unit', sum(map(
enemies, 'enemy_side', evaluate_defender_against_opponents(ai, my_unit,
create_side_unit_list(ai, enemy_side))))));
+ tomap(
+ map(
+ my_recruits,
+ id
+ ),
+ map(
+ my_recruits, 'my_unit',
+ sum(
+ map(
+ enemies, 'enemy_side',
+ evaluate_defender_against_opponents(
+ ai,
+ my_unit,
+ create_side_unit_list(
+ ai,
+ enemy_side
+ )
+ )
+ )
+ )
+ )
+ );
def evaluate_defenders(ai*)
- map(map( change_numbers_to_percents(
make_positive_only(evaluate_my_recruits_as_defenders(ai) )), (value *2)/3 ),
value + map(change_numbers_to_percents(units_hp_map(ai, my_recruits)),
value/3)[key] );
+ map(
+ map(
+ change_numbers_to_percents(
+ make_positive_only(
+ evaluate_my_recruits_as_defenders(ai)
+ )
+ ),
+ (
+ value * 2
+ ) / 3
+ ),
+ value +
+ map(
+ change_numbers_to_percents(
+ units_hp_map(
+ ai,
+ my_recruits
+ )
+ ),
+ value / 3
+ )[key]
+ );
# === 2 === now consider abilities and weapon specials #
@@ -119,34 +341,126 @@
[ 'backstab' -> 20 ,'slow' -> 10 ,'berserk' -> 20 ,'stones' -> 60
,'plague' -> 10 ,'marksman' -> 30 ,'magical' -> 50 ,'charge' -> 30 ,'drains' ->
30, 'firststrike' -> 10, 'poison' -> 25 ];
def apply_abilities_weights( units_map )
- map( units_map, value + (value*max(map( get_unit_type( key ).abilities,
'ability', abilities_weights()[ability] )))/100 );
+ map(
+ units_map,
+ value +
+ (
+ value *
+ max(
+ map(
+ get_unit_type( key ).abilities,
'ability',
+ abilities_weights()[ability]
+ )
+ )
+ ) / 100
+ );
def apply_weapon_specials_weights( units_map )
- map( units_map, value + (value*max(map( get_unit_type( key ).attacks,
'attack', weapon_specials_weights()[attack.special] )))/100 );
+ map(
+ units_map,
+ value +
+ (
+ value *
+ max(
+ map(
+ get_unit_type( key ).attacks, 'attack',
+
weapon_specials_weights()[attack.special]
+ )
+ )
+ ) / 100
+ );
# since undead units don't get random traits and are balanced with that, we
need to lower their evaluation a bit to match fairly the living units #
+
def undead_malus( units_map )
- map( units_map, if( get_unit_type( key ).undead, (value*90)/100, value
));
+ map(
+ units_map,
+ if(
+ get_unit_type(key).undead,
+ ( value * 90 ) / 100,
+ value
+ )
+ );
#=========== we have evaluation of game state and units, time to
combine them: ==========#
#========= recruitment_list_builder =========#
def rlb_apply_eval(eval, attackers_map, defenders_map)
- map(sumarize_maps_values(map(attackers_map, value*eval),
map(defenders_map, value*(100-eval) )), value/100);
-
-def rlb_remove_lowest( map, percent)
- filter( map, value > (percent*sumarize_values(map))/100);
+ map(
+ sumarize_maps_values(
+ map(
+ attackers_map,
+ value * eval
+ ),
+ map(
+ defenders_map,
+ value * ( 100 - eval )
+ )
+ ),
+ value / 100
+ );
+
+def rlb_remove_lowest( input_map, percent)
+ filter(
+ input_map,
+ value >
+ (
+ (
+ percent * sumarize_values(input_map)
+ ) / 100
+ )
+ );
def rlb_first_step(eval, attackers_map, defenders_map)
- rlb_remove_lowest(rlb_apply_eval(eval, attackers_map,
defenders_map),10);
+ rlb_remove_lowest(
+ rlb_apply_eval(
+ eval,
+ attackers_map,
+ defenders_map
+ ),
+ 10
+ );
def recruitment_list_builder(eval, attackers_map, defenders_map)
- map(rlb_first_step(eval, attackers_map, defenders_map), (value * 100)/
sumarize_values(rlb_first_step(eval, attackers_map, defenders_map)));
+ map(
+ rlb_first_step(
+ eval,
+ attackers_map,
+ defenders_map
+ ),
+ (
+ (
+ value * 100
+ ) /
+ sumarize_values(
+ rlb_first_step(
+ eval,
+ attackers_map,
+ defenders_map
+ )
+ )
+ )
+ );
# ========== choose the unit to recruit now ========= #
def unit_chooser(ai*,unit_map)
- choose(keys(unit_map), 'unit_type', unit_map[unit_type] -
((100*size(filter(my_units, type = unit_type))) / size(my_units)));
+ choose(
+ keys(unit_map), 'unit_type',
+ unit_map[unit_type] -
+ (
+ (
+ 100 *
+ size(
+ filter(
+ my_units,
+ type = unit_type
+ )
+ )
+ ) /
+ size(my_units)
+ )
+ );
# ========== Main formula section ========== #
@@ -154,8 +468,8 @@
if(my_leader.loc = loc(11,23),
if( teams[my_side].gold>20,
recruit(unit_chooser(self,recruitment_list_builder(eval(self),apply_abilities_weights(apply_weapon_specials_weights(evaluate_attackers(self))),apply_abilities_weights(apply_weapon_specials_weights(evaluate_defenders(self)))))),
- fallback('default') ),
+ fallback('') ),
if(vars.check = turn,
- [set_var('check', 0), fallback('default')],
+ [set_var('check', 0), fallback('')],
[set_var('check', turn), move(my_leader.loc,
nearest_keep(my_leader.loc))])
)
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits