Complete.Org: Mailing Lists: Archives: freeciv-ai: September 2004:
[freeciv-ai] Re: [Freeciv-Dev] Re: (PR#9887) AI defense code
Home

[freeciv-ai] Re: [Freeciv-Dev] Re: (PR#9887) AI defense code

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [freeciv-ai] Re: [Freeciv-Dev] Re: (PR#9887) AI defense code
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Thu, 2 Sep 2004 09:34:31 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=9887 >

Attached is a patch that makes ai_choose_defender_versus() use
unit_win_chance() instead of the usual multiply-unit-values-together
defense code. It works reasonably well for choosing defender, except that
it is now back to sometimes building Stealth Fighter as defender ;)

However, it is very slow. It also fails to understand that defenders
sometimes should not kill the attacker, but merely wound it as much as
economically rational.

I tried to change win chance with this formula:

    unit_build_shield_cost(defender->type) * MAX(chance, 0.001)

(lower values are better)

This was meant to encourage building cheaper defenders when there was
little difference between defenders, ie no Stealth Fighters. It worked
reasonably, until the AI encountered Howitzers. Suddenly, the AI wanted
to build Spy for defense! The logic is impeccable - the change in win
chance between a Mech Inf and a Spy is a mere 4%, and the Spy is much
cheaper... so why waste shields on a Mech Inf?

Of course, this ignores the important fact that defenders should not
always aim to win every time, but also wound the attacking unit
sufficiently that it cannot attack again, and we can destroy it next turn.

So is there a fast way to compute a "damage ratio" between an attacker and
a defender, similar to unit_win_chance()? Greg, this is your area of
expertise :-)

  - Per

Index: ai/advmilitary.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advmilitary.c,v
retrieving revision 1.172
diff -u -r1.172 advmilitary.c
--- ai/advmilitary.c    2 Sep 2004 14:53:08 -0000       1.172
+++ ai/advmilitary.c    2 Sep 2004 16:23:17 -0000
@@ -45,24 +45,28 @@
 
 /**************************************************************************
   Choose the best unit the city can build to defend against attacker v.
+  If we are unable to find a decent defender, we will return -1. Catch
+  this.
 **************************************************************************/
-Unit_Type_id ai_choose_defender_versus(struct city *pcity, Unit_Type_id v)
+Unit_Type_id ai_choose_defender_versus(struct city *pcity,
+                                       struct unit *attacker)
 {
-  Unit_Type_id bestid = 0; /* ??? Zero is legal value! (Settlers by default) */
-  int j, m;
-  int best = 0;
+  struct player *pplayer = city_owner(pcity);
+  Unit_Type_id bestid = -1;
+  double best = 1;
 
-  simple_ai_unit_type_iterate(i) {
-    m = unit_types[i].move_type;
-    if (can_build_unit(pcity, i) && (m == LAND_MOVING || m == SEA_MOVING)) {
-      j = get_virtual_defense_power(v, i, pcity->x, pcity->y, FALSE, FALSE);
-      if (j > best || (j == best && unit_build_shield_cost(i) <=
-                                    unit_build_shield_cost(bestid))) {
-        best = j;
+  unit_type_iterate(i) {
+    if (can_build_unit(pcity, i)) {
+      struct unit *defender = create_unit_virtual(pplayer, pcity, i, TRUE);
+
+      double chance = unit_win_chance(attacker, defender);
+      if (chance < best) {
+        best = chance;
         bestid = i;
       }
+      destroy_unit_virtual(defender);
     }
-  } simple_ai_unit_type_iterate_end;
+  } unit_type_iterate_end;
 
   return bestid;
 }
@@ -1041,8 +1045,8 @@
     move_time = turns_to_enemy_city(myunit->type, acity, move_rate, 
                                     go_by_boat, ferryboat, boattype);
 
-    def_type = ai_choose_defender_versus(acity, myunit->type);
-    if (move_time > 1) {
+    def_type = ai_choose_defender_versus(acity, myunit);
+    if (move_time > 1 && def_type != -1) {
       def_vet = do_make_unit_veteran(acity, def_type);
       vuln = unittype_def_rating_sq(myunit->type, def_type,
                                     x, y, FALSE, def_vet);
@@ -1051,6 +1055,7 @@
       vuln = 0;
       benefit = 0;
       def_vet = 0;
+      def_type = 0; /* bad, bad, bad... but necessary kludge */
     }
 
     pdef = get_defender(myunit, x, y);
Index: ai/advmilitary.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advmilitary.h,v
retrieving revision 1.20
diff -u -r1.20 advmilitary.h
--- ai/advmilitary.h    2 Sep 2004 14:58:23 -0000       1.20
+++ ai/advmilitary.h    2 Sep 2004 16:23:17 -0000
@@ -20,7 +20,8 @@
 struct unit;
 struct ai_choice;
 
-Unit_Type_id ai_choose_defender_versus(struct city *pcity, Unit_Type_id v);
+Unit_Type_id ai_choose_defender_versus(struct city *pcity,
+                                       struct unit *attacker);
 void military_advisor_choose_tech(struct player *pplayer,
                                  struct ai_choice *choice);
 void  military_advisor_choose_build(struct player *pplayer, struct city *pcity,
Index: ai/aitools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitools.c,v
retrieving revision 1.122
diff -u -r1.122 aitools.c
--- ai/aitools.c        2 Sep 2004 14:58:23 -0000       1.122
+++ ai/aitools.c        2 Sep 2004 16:23:18 -0000
@@ -166,10 +166,13 @@
   dcity = map_get_city(dest_x, dest_y);
   if (dcity && HOSTILE_PLAYER(pplayer, ai, city_owner(dcity))) {
     /* Assume enemy will build another defender, add it's attack strength */
-    int d_type = ai_choose_defender_versus(dcity, punit->type);
-    danger += 
-      unittype_att_rating(d_type, do_make_unit_veteran(dcity, d_type), 
-                          SINGLE_MOVE, unit_types[d_type].hp);
+    int d_type = ai_choose_defender_versus(dcity, punit);
+
+    if (d_type != -1) {
+      danger += 
+        unittype_att_rating(d_type, do_make_unit_veteran(dcity, d_type), 
+                            SINGLE_MOVE, unit_types[d_type].hp);
+    }
   }
   danger *= POWER_DIVIDER;
 
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.334
diff -u -r1.334 aiunit.c
--- ai/aiunit.c 1 Sep 2004 11:47:25 -0000       1.334
+++ ai/aiunit.c 2 Sep 2004 16:23:19 -0000
@@ -1522,14 +1522,18 @@
                                       go_by_boat, ferryboat, boattype);
 
       if (move_time > 1) {
-        Unit_Type_id def_type = ai_choose_defender_versus(acity, punit->type);
-        int v = unittype_def_rating_sq(punit->type, def_type,
-                                       acity->x, acity->y, FALSE,
-                                       do_make_unit_veteran(acity, def_type));
-        if (v > vuln) {
-          /* They can build a better defender! */ 
-          vuln = v; 
-          benefit = unit_build_shield_cost(def_type); 
+        Unit_Type_id def_type = ai_choose_defender_versus(acity, punit);
+        int v;
+
+        if (def_type != -1) {
+          v = unittype_def_rating_sq(punit->type, def_type,
+                                     acity->x, acity->y, FALSE,
+                                     do_make_unit_veteran(acity, def_type));
+          if (v > vuln) {
+            /* They can build a better defender! */ 
+            vuln = v; 
+            benefit = unit_build_shield_cost(def_type); 
+          }
         }
       }
 

[Prev in Thread] Current Thread [Next in Thread]