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

This patch implements Greg's brilliant defense calculation algorithm
which is explained in this ticket. Unlike the current code, it takes
into account unit cost, firepower and hitpoints. The downside is that it
is more CPU intensive.

The biggest problem is still, I see, that it builds way too many city
walls and coastal defenses. The next biggest problem is that it builds
too many defenders, and not enough (counter-)attackers. But this patch
should improve matters anyway, I think.

  - Per
Index: ai/aitools.c
===================================================================
--- ai/aitools.c	(revision 12634)
+++ ai/aitools.c	(working copy)
@@ -236,7 +236,7 @@
   dcity = tile_get_city(dest_tile);
   if (dcity && HOSTILE_PLAYER(pplayer, ai, city_owner(dcity))) {
     /* Assume enemy will build another defender, add it's attack strength */
-    struct unit_type *d_type = ai_choose_defender_versus(dcity, punit->type);
+    struct unit_type *d_type = ai_choose_defender_versus(dcity, punit);
 
     danger += 
       unittype_att_rating(d_type, do_make_unit_veteran(dcity, d_type), 
Index: ai/advmilitary.c
===================================================================
--- ai/advmilitary.c	(revision 12634)
+++ ai/advmilitary.c	(working copy)
@@ -52,27 +52,47 @@
   Choose the best unit the city can build to defend against attacker v.
 **************************************************************************/
 struct unit_type *ai_choose_defender_versus(struct city *pcity,
-					    const struct unit_type *v)
+					    struct unit *attacker)
 {
   struct unit_type *bestunit = NULL;
-  int best = 0;
+  double best = 0;
+  int best_cost = FC_INFINITY;
+  struct player *pplayer = city_owner(pcity);
 
   simple_ai_unit_type_iterate(punittype) {
     const int move_type = get_unit_move_type(punittype);
 
     if (can_build_unit(pcity, punittype)
 	&& (move_type == LAND_MOVING || move_type == SEA_MOVING)) {
-      const int defense = get_virtual_defense_power(v, punittype,
-						    pcity->owner,
-						    pcity->tile,
-						    FALSE, FALSE);
+      int fpatt, fpdef, defense, attack;
+      double want, loss, cost = unit_build_shield_cost(punittype);
+      struct unit *defender;
+      int veteran = get_unittype_bonus(pcity->owner, pcity->tile, punittype,
+                                       EFT_VETERAN_BUILD);
 
-      if (defense > best || (defense == best
-			     && unit_build_shield_cost(punittype) <=
-			     unit_build_shield_cost(bestunit))) {
-        best = defense;
+      defender = create_unit_virtual(pplayer, pcity, punittype, veteran);
+      defense = get_total_defense_power(attacker, defender);
+      attack = get_total_attack_power(attacker, defender);
+      get_modified_firepower(attacker, defender, &fpatt, &fpdef);
+
+      /* Greg's algorithm. loss is the average number of health lost by
+       * defender. If loss > attacker's hp then we should win the fight,
+       * which is always a good thing, since we avoid shield loss. */
+      loss = (double) defense * punittype->hp * fpdef / (attack * fpatt);
+      want = (loss + MAX(0, loss - attacker->hp)) / cost;
+
+#ifdef NEVER
+      CITY_LOG(LOG_DEBUG, pcity, "desire for %s against %s(%d,%d) is %.2f",
+               unit_name_orig(punittype), unit_name_orig(attacker->type), 
+               TILE_XY(attacker->tile), want);
+#endif
+
+      if (want > best || (want == best && cost <= best_cost)) {
+        best = want;
         bestunit = punittype;
+        best_cost = cost;
       }
+      destroy_unit_virtual(defender);
     }
   } simple_ai_unit_type_iterate_end;
 
@@ -1114,7 +1134,7 @@
     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);
+    def_type = ai_choose_defender_versus(acity, myunit);
     def_owner = acity->owner;
     if (move_time > 1) {
       def_vet = do_make_unit_veteran(acity, def_type);
Index: ai/advmilitary.h
===================================================================
--- ai/advmilitary.h	(revision 12634)
+++ ai/advmilitary.h	(working copy)
@@ -19,7 +19,7 @@
 struct ai_choice;
 
 struct unit_type *ai_choose_defender_versus(struct city *pcity,
-					    const struct unit_type *versus);
+                                            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/aiunit.c
===================================================================
--- ai/aiunit.c	(revision 12634)
+++ ai/aiunit.c	(working copy)
@@ -1403,7 +1403,8 @@
 
       if (move_time > 1) {
         struct unit_type *def_type
-	  = ai_choose_defender_versus(acity, punit->type);
+	  = ai_choose_defender_versus(acity, punit);
+
         int v = unittype_def_rating_sq(punit->type, def_type,
                                        acity->owner, acity->tile, FALSE,
                                        do_make_unit_veteran(acity, def_type));
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to