diff -ruN -X freeciv/diff_ignore freeciv-cvs-May-01/ai/advmilitary.c freeciv/ai/advmilitary.c --- freeciv-cvs-May-01/ai/advmilitary.c 2003-04-30 06:58:07.000000000 +0200 +++ freeciv/ai/advmilitary.c 2003-05-04 17:25:37.000000000 +0200 @@ -17,6 +17,7 @@ #include #include +#include /* Added by Olivier DAVY, using ceil */ #include "combat.h" #include "game.h" @@ -55,35 +56,99 @@ init_choice(choice); } + /************************************************************************** Choose best attacker based on movement type. It chooses based on unit desirability without regard to cost, unless costs are equal. This is very wrong. FIXME, use amortize on time to build. + FIXED by Olivier DAVY , 03 May 2003 + The result can be -1 if no attacker was found. **************************************************************************/ -static Unit_Type_id ai_choose_attacker(struct city *pcity, +static Unit_Type_id simple_ai_choose_attacker(struct city *pcity, enum unit_move_type which) { Unit_Type_id bestid = -1; - int best = 0; - int cur; + int current, best = 0; simple_ai_unit_type_iterate(i) { - cur = ai_unit_attack_desirability(i); + current = ai_unit_attack_desirability(i); if (which == unit_types[i].move_type) { if (can_build_unit(pcity, i) - && (cur > best - || (cur == best - && get_unit_type(i)->build_cost - <= get_unit_type(bestid)->build_cost))) { - best = cur; + && ( + (bestid == -1) + || + (current > best) + || + ( + (current == best) + && ( (get_unit_type(i)->build_cost) + <= (get_unit_type(bestid)->build_cost) + ) + ) + ) + ) + { + best = current; bestid = i; } - } + } } simple_ai_unit_type_iterate_end; + return bestid; +} + +/************************************************************************** + Choose best attacker based on movement type. It chooses based on unit + desirability without regard to cost, unless costs are equal. + It amortizes on time to build. + FIXED by Olivier DAVY , 03 May 2003 + The result can be -1 if no attacker was found. +**************************************************************************/ +static Unit_Type_id ai_choose_attacker(struct city *pcity, + enum unit_move_type which) +{ + Unit_Type_id bestid = -1; + int current, best = 0; + int time_to_build; + int surplus = pcity->shield_surplus; + /* First case : the city can build */ + if ( surplus > 0) { + simple_ai_unit_type_iterate(i) { + /* We compute the time to build */ + time_to_build = ceil((float)get_unit_type(i)->build_cost) / ((float)surplus); + /* We amortize on time to build */ + current = amortize(ai_unit_attack_desirability(i),time_to_build); + if (which == unit_types[i].move_type) { + if (can_build_unit(pcity, i) + && ( + (bestid == -1) + || + (current > best) + || + ( + (current == best) + && ( (get_unit_type(i)->build_cost) + <= (get_unit_type(bestid)->build_cost) + ) + ) + ) + ) + { + best = current; + bestid = i; + } + } + } simple_ai_unit_type_iterate_end; + } + /* Second case : the city can not produce anything for the moment, + so we can not amortize on time to build */ + else + bestid = simple_ai_choose_attacker(pcity, which); return bestid; } + + /************************************************************************** Choose best defender based on movement type. It chooses based on unit desirability without regard to cost, unless costs are equal. This is @@ -91,13 +156,16 @@ We should only be passed with L_DEFEND_GOOD role for now, since this is the only role being considered worthy of bodyguarding in findjob. + + FIXED by Olivier DAVY , 03 May 2003 + The result can be -1 if no attacker was found. **************************************************************************/ -static Unit_Type_id ai_choose_bodyguard(struct city *pcity, +static Unit_Type_id simple_ai_choose_bodyguard(struct city *pcity, enum unit_move_type move_type, enum unit_role_id role) { Unit_Type_id bestid = -1; - int j, best = 0; + int current, best = 0; simple_ai_unit_type_iterate(i) { /* Only consider units of given role, or any if L_LAST */ @@ -114,10 +182,14 @@ /* Now find best */ if (can_build_unit(pcity, i)) { - j = ai_unit_defence_desirability(i); - if (j > best || (j == best && get_unit_type(i)->build_cost <= - get_unit_type(bestid)->build_cost)) { - best = j; + current = ai_unit_defence_desirability(i); + if ( + (bestid==-1) + || + (current > best || (current == best && get_unit_type(i)->build_cost <= + get_unit_type(bestid)->build_cost)) + ) { + best = current; bestid = i; } } @@ -125,6 +197,63 @@ return bestid; } + +/************************************************************************** + Choose best defender based on movement type. It chooses based on unit + desirability without regard to cost, unless costs are equal. This is + very wrong. FIXME, use amortize on time to build. + + We should only be passed with L_DEFEND_GOOD role for now, since this + + FIXED by Olivier DAVY , 03 May 2003 + The result can be -1 if no attacker was found. +**************************************************************************/ +static Unit_Type_id ai_choose_bodyguard(struct city *pcity, + enum unit_move_type move_type, + enum unit_role_id role) +{ + Unit_Type_id bestid = -1; + int current, best = 0; + int time_to_build; + int surplus = pcity->shield_surplus; + /* First case : the city can build */ + if ( surplus > 0) { + simple_ai_unit_type_iterate(i) { + /* Only consider units of given role, or any if L_LAST */ + if (role != L_LAST) { + if (!unit_has_role(i, role)) { + continue; + } + } + + /* Only consider units of same move type */ + if (unit_types[i].move_type != move_type) { + continue; + } + + /* Now find best */ + if (can_build_unit(pcity, i)) { + time_to_build = ceil((float)get_unit_type(i)->build_cost) / ((float)surplus); + /* We amortize on the time to build */ + current = amortize(ai_unit_defence_desirability(i), time_to_build); + if ( + (bestid==-1) + || + (current > best || (current == best && get_unit_type(i)->build_cost <= + get_unit_type(bestid)->build_cost)) + ) { + best = current; + bestid = i; + } + } + } simple_ai_unit_type_iterate_end; + } + /* Second case : the city can not produce anything for the moment, so we can not amortize on time to build */ + else + bestid = simple_ai_choose_bodyguard(pcity, move_type, role); + return bestid; +} + /********************************************************************** Helper for assess_defense_quadratic and assess_defense_unit. ***********************************************************************/ @@ -745,9 +874,12 @@ needferry = unit_types[boattype].build_cost; } - if (acity) { + if (!is_stack_vulnerable(x,y)){ /* If it is a city, we may have to whack it many times */ /* FIXME: Also valid for fortresses! */ + /* odavy : "and also for air bases. */ + /* Using is_stack_vulnerable of aitools instead." */ + /* FIXED by Olivier DAVY ,03 May 2003 */ victim_count += unit_list_size(&(map_get_tile(x, y)->units)); } @@ -789,6 +921,7 @@ int desire, want; /* Take into account reinforcements strength */ + /* FIXME : odavy : "should we test also if (x,y) is a n air base ? */ if (acity) attack += acity->ai.attack; attack *= attack; @@ -1204,7 +1337,7 @@ danger = 0; } - /* FIXME: 1. Will tend to build walls beofre coastal irrespectfully what + /* FIXME: 1. Will tend to build walls before coastal irrespectfully what * type of danger we are facing * 2. (80 - pcity->shield_stock) * 2 below is hardcoded price of walls */ /* We will build walls if we can and want and (have "enough" defenders or diff -ruN -X freeciv/diff_ignore freeciv-cvs-May-01/ai/aitools.c freeciv/ai/aitools.c --- freeciv-cvs-May-01/ai/aitools.c 2003-04-21 06:56:58.000000000 +0200 +++ freeciv/ai/aitools.c 2003-05-04 17:15:27.000000000 +0200 @@ -472,8 +472,10 @@ /************************************************************************** Is it a city/fortress or will the whole stack die in an attack TODO: use new killstack thing + Olivier DAVY : + changed from static to non static, since used in advmilitary.c **************************************************************************/ -static bool is_stack_vulnerable(int x, int y) +bool is_stack_vulnerable(int x, int y) { return !(map_get_city(x, y) != NULL || map_has_special(x, y, S_FORTRESS) || diff -ruN -X freeciv/diff_ignore freeciv-cvs-May-01/ai/aitools.h freeciv/ai/aitools.h --- freeciv-cvs-May-01/ai/aitools.h 2003-04-21 06:56:58.000000000 +0200 +++ freeciv/ai/aitools.h 2003-05-04 17:15:48.000000000 +0200 @@ -55,6 +55,10 @@ struct city *dist_nearest_city(struct player *pplayer, int x, int y, bool everywhere, bool enemy); +/* Added by Olivier DAVY , + since used in advmilitary.c */ +bool is_stack_vulnerable(int x, int y); + void ai_government_change(struct player *pplayer, int gov); int ai_gold_reserve(struct player *pplayer);