[Freeciv-Dev] [Bug][RFC] Stupid attack behaviour by AI (PR#1340)
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Raahul Kumar drew my attention to this phenomenon: if you park your, say,
phalanx on a wee mountain outside an AI city then from time to time the
city's gates will burst open and AI will attack you with few phalanxes or
similarly inefficient units. Seemingly without any real desire to kill you...
For a long time we were inclined to believe that it's server/autoattack.c
fault. Indeed server/autoattack.c selects it's targets on a very dodgy
basis. But the problem is elsewhere.
First discovery: AI autoattack is (almost) never activated:
==================================================
193 static void auto_attack_city(struct player *pplayer, struct city *pcity)
194 {
195 unit_list_iterate(map_get_tile(pcity->x, pcity->y)->units, punit) {
196 if (punit->ai.control
197 && punit->activity == ACTIVITY_IDLE
198 && is_military_unit(punit)) {
199 auto_attack_with_unit(pplayer, pcity, punit);
200 }
201 }
202 unit_list_iterate_end;
203 }
==================================================
because by the time the control is passed to autoattack, all AI units are
fortifying (i.e. not IDLE)
Second discovery: The culprit is ai_military_vindvictim (ai/aiunit.c).
(It's not fault of Petr, who only cleaned it up and acually facilitated my
discovery). The problem lies in the lines:
==================================================
910 int vuln = unit_vulnerability(punit, pdef);
911 int attack = reinforcements_value(punit, pdef->x, pdef->y)
+ unit_belligerence_primitive(punit);
912 int benefit = unit_type(pdef)->build_cost;
913 int loss = unit_type(punit)->build_cost;
==================================================
because reinforcements are counted in the attack but _not_ counted in the
loss.
So what happens is:
AI accumulates quite a few defensive units. Then it thinks that it has
real chance of defeating you with all those defensive units (which might
well be right). What is not taken into account is the cost at which this
victory will come: it thinks that only the first attacking unit will die
in the worst-case scenario.
How can we fix that:
The easiest solution is to add currently UNUSED
int reinforcements_cost(struct unit *punit, int x, int y)
to "loss". This will still encourage expensive attacks: AI will think
that
--if after all N units attack the enemy still survives, it will lose
"loss" shields (which is right)
--if after all N units attack the enemy at last dies, it will lose 0
shields (which is wrong: N-1 units will die too).
However, making more mathematically exact computation is quite hard and, I
am afraid, will discourage AI from ever attacking enemy cities. Unless
city_attack_bonus which is now represented by magic number 40 (or
misrepresented by unit_value(get_role_unit(F_CITIES, 0)) ) is bumped up
significantly.
G.
|
|