Complete.Org: Mailing Lists: Archives: freeciv-ai: March 2003:
[freeciv-ai] (PR#3574) Cleanup of ai_military_gothere
Home

[freeciv-ai] (PR#3574) Cleanup of ai_military_gothere

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients:;
Subject: [freeciv-ai] (PR#3574) Cleanup of ai_military_gothere
From: "Gregory Berkolaiko" <Gregory.Berkolaiko@xxxxxxxxxxxx>
Date: Sat, 1 Mar 2003 15:57:07 -0800
Reply-to: rt@xxxxxxxxxxxxxx

This is a rather mild cleanup, preserving savegames.  Whenever I was
trying to do a more thorouhg job, the savegames would diverge :(

The code is pretty braindead, but I feel we need to clean it before we
kill it.  Some problems are highlighted by the patch.

The patch incorporates Jasons earlier 3508 patch

G.
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.267
diff -u -r1.267 aiunit.c
--- ai/aiunit.c 2003/02/27 22:28:41     1.267
+++ ai/aiunit.c 2003/03/01 23:52:52
@@ -1302,154 +1302,197 @@
 }
 
 /**************************************************************************
-...
+  A helper function for ai_military_gothere.  Estimates the dangers we will
+  be facing a out destination and tries to find/request a bodyguard if 
+  needed.
 **************************************************************************/
+static void ai_consider_bodyguard(struct unit *punit, int dest_x, int dest_y)
+{
+  int danger;
+  struct city *dcity;
+  struct tile *ptile;
+
+  
+  if (is_barbarian(unit_owner(punit)))  {
+    /* barbarians must have more courage (= less brains) */
+    punit->ai.bodyguard = BODYGUARD_NONE;
+    return;
+  }
+
+  /* Estimate enemy attack power. */
+  danger = stack_attack_value(dest_x, dest_y);
+  if ((dcity = map_get_city(dest_x, dest_y))) {
+    /* Assume enemy will build another defender, add it's attack strength */
+    int d_type = ai_choose_defender_versus(dcity, punit->type);
+    danger += 
+      base_unit_belligerence_primitive(d_type, 
+                                       do_make_unit_veteran(dcity, d_type), 
+                                       SINGLE_MOVE, unit_types[d_type].hp);
+  }
+  danger *= POWER_DIVIDER;
+
+  /* If we are fast, there is less danger. */
+  danger /= (unit_type(punit)->move_rate / SINGLE_MOVE);
+  if (unit_flag(punit, F_IGTER)) {
+    danger /= 1.5;
+  }
+
+  ptile = map_get_tile(punit->x, punit->y);
+  /* We look for the bodyguard where we stand. */
+  if (!unit_list_find(&ptile->units, punit->ai.bodyguard)) {
+    int my_def = (punit->hp * (punit->veteran ? 15 : 10)
+                  * unit_type(punit)->defense_strength);
+    
+    /* FIXME: danger is multiplied by POWER_FACTOR, my_def isn't. */
+    if (danger >= my_def) {
+      UNIT_LOG(LOGLEVEL_BODYGUARD, punit, 
+               "wants a bodyguard, danger=%d, my_def=%d", danger, my_def);
+      punit->ai.bodyguard = BODYGUARD_WANTED;
+    } else {
+      punit->ai.bodyguard = BODYGUARD_NONE;
+    }
+  }
+
+  /* What if we have a bodyguard, but don't need one? */
+}
+
+/**************************************************************************
+  Return values: 
+  -1: died
+  0: didn't move
+  1: moved
+  TODO: Convert to bool.
+**************************************************************************/
 static int ai_military_gothere(struct player *pplayer, struct unit *punit,
                               int dest_x, int dest_y)
 {
-  int id, x, y, boatid = 0, bx = 0, by = 0;
-  struct unit *ferryboat;
+  int id, x, y, boatid = 0, bx = -1, by = -1;
+  struct unit *ferryboat = NULL;
   struct unit *def;
-  struct city *dcity;
+  struct city *dcity = map_get_city(dest_x, dest_y);
   struct tile *ptile;
-  int d_type, d_val;
 
   CHECK_UNIT(punit);
 
   id = punit->id; x = punit->x; y = punit->y;
 
-  if (is_ground_unit(punit)) boatid = find_boat(pplayer, &bx, &by, 2);
-  ferryboat = unit_list_find(&(map_get_tile(x, y)->units), boatid);
+  if (same_pos(dest_x, dest_y, x, y)) {
+    /* Nowhere to go */
+    return 0;
+  }
 
-  if (!same_pos(dest_x, dest_y, x, y)) {
+  if (is_ground_unit(punit)) { 
+    boatid = find_boat(pplayer, &bx, &by, 2);
+    /* NB: ferryboat is set only if the boat is where we are */
+    ferryboat = unit_list_find(&(map_get_tile(x, y)->units), boatid);
+  }
 
-/* do we require protection? */
-    d_val = stack_attack_value(dest_x, dest_y);
-    if ((dcity = map_get_city(dest_x, dest_y))) {
-      d_type = ai_choose_defender_versus(dcity, punit->type);
-      d_val += 
-       base_unit_belligerence_primitive(d_type, 
-                                         do_make_unit_veteran(dcity, d_type), 
-                                         SINGLE_MOVE, unit_types[d_type].hp);
+  ai_consider_bodyguard(punit, dest_x, dest_y);
+  
+  if (!goto_is_sane(punit, dest_x, dest_y, TRUE) 
+      || (ferryboat && goto_is_sane(ferryboat, dest_x, dest_y, TRUE))) {
+    punit->ai.ferryboat = boatid;
+    freelog(LOG_DEBUG, "%s: %d@(%d, %d): Looking for BOAT (id=%d).",
+            pplayer->name, punit->id, punit->x, punit->y, boatid);
+    if (boatid > 0 && !same_pos(x, y, bx, by)) {
+      /* Go to the boat */
+      /* FIXME: this can lose bodyguard */
+      if (!ai_unit_goto(punit, bx, by)) {
+        /* Died. */
+        return -1;
+      }
     }
-    d_val *= POWER_DIVIDER;
-    d_val /= (unit_type(punit)->move_rate / SINGLE_MOVE);
-    if (unit_flag(punit, F_IGTER)) d_val /= 1.5;
-    freelog(LOG_DEBUG,
-           "%s@(%d,%d) looking for bodyguard, d_val=%d, my_val=%d",
-           unit_type(punit)->name, punit->x, punit->y, d_val,
-           (punit->hp * (punit->veteran ? 15 : 10)
-            * unit_type(punit)->defense_strength));
     ptile = map_get_tile(punit->x, punit->y);
-    if (d_val >= punit->hp * (punit->veteran ? 15 : 10) *
-                unit_type(punit)->defense_strength) {
-/*      if (!unit_list_find(&pplayer->units, punit->ai.bodyguard))   Ugggggh */
-      if (!unit_list_find(&ptile->units, punit->ai.bodyguard))
-        punit->ai.bodyguard = -1;
-    } else if (!unit_list_find(&ptile->units, punit->ai.bodyguard))
-      punit->ai.bodyguard = BODYGUARD_NONE;
-
-    if (is_barbarian(pplayer))  /* barbarians must have more courage */
-      punit->ai.bodyguard = BODYGUARD_NONE;
-/* end protection subroutine */
+    ferryboat = unit_list_find(&ptile->units, punit->ai.ferryboat);
 
-    if (!goto_is_sane(punit, dest_x, dest_y, TRUE) ||
-       (ferryboat && goto_is_sane(ferryboat, dest_x, dest_y, TRUE))) { /* 
Important!! */
-      punit->ai.ferryboat = boatid;
-      freelog(LOG_DEBUG, "%s: %d@(%d, %d): Looking for BOAT (id=%d).",
-                   pplayer->name, punit->id, punit->x, punit->y, boatid);
-      if (boatid > 0 && !same_pos(x, y, bx, by)) {
-       if (!ai_unit_goto(punit, bx, by)) {
-         return -1;            /* died */
-       }
-      }
-      ptile = map_get_tile(punit->x, punit->y);
-      ferryboat = unit_list_find(&ptile->units, punit->ai.ferryboat);
-      if (ferryboat && (ferryboat->ai.passenger == 0 ||
-          ferryboat->ai.passenger == punit->id)) {
-       freelog(LOG_DEBUG, "We have FOUND BOAT, %d ABOARD %d@(%d,%d)->(%d, 
%d).",
-               punit->id, ferryboat->id, punit->x, punit->y,
-               dest_x, dest_y);
-        handle_unit_activity_request(punit, ACTIVITY_SENTRY);
-        ferryboat->ai.passenger = punit->id;
-/* the code that worked for settlers wasn't good for piles of cannons */
-        if (find_beachhead(punit, dest_x, dest_y, &ferryboat->goto_dest_x,
-               &ferryboat->goto_dest_y) != 0) {
-          punit->goto_dest_x = dest_x;
-          punit->goto_dest_y = dest_y;
-          handle_unit_activity_request(punit, ACTIVITY_SENTRY);
-         if (ground_unit_transporter_capacity(punit->x, punit->y, pplayer)
-             <= 0) {
-           freelog(LOG_DEBUG, "All aboard!");
-           /* perhaps this should only require two passengers */
-            unit_list_iterate(ptile->units, mypass) {
-              if (mypass->ai.ferryboat == ferryboat->id
-                  && punit->owner == mypass->owner) {
-                handle_unit_activity_request(mypass, ACTIVITY_SENTRY);
-                def = unit_list_find(&ptile->units, mypass->ai.bodyguard);
-                if (def) {
-                  handle_unit_activity_request(def, ACTIVITY_SENTRY);
-                }
+    if (ferryboat && (ferryboat->ai.passenger == 0 
+                      || ferryboat->ai.passenger == punit->id)) {
+      freelog(LOG_DEBUG, "We have FOUND BOAT, %d ABOARD %d@(%d,%d)->(%d, %d).",
+              punit->id, ferryboat->id, punit->x, punit->y, dest_x, dest_y);
+      handle_unit_activity_request(punit, ACTIVITY_SENTRY);
+      ferryboat->ai.passenger = punit->id;
+
+      /* the code that worked for settlers wasn't good for piles of cannons */
+      if (find_beachhead(punit, dest_x, dest_y, &ferryboat->goto_dest_x,
+                         &ferryboat->goto_dest_y) != 0) {
+        punit->goto_dest_x = dest_x;
+        punit->goto_dest_y = dest_y;
+        if (ground_unit_transporter_capacity(punit->x, punit->y, pplayer)
+            <= 0) {
+          /* FIXME: perhaps we should only require only two passengers */
+          freelog(LOG_DEBUG, "All aboard!");
+          unit_list_iterate(ptile->units, mypass) {
+            if (mypass->ai.ferryboat == ferryboat->id
+                && punit->owner == mypass->owner) {
+              handle_unit_activity_request(mypass, ACTIVITY_SENTRY);
+              def = unit_list_find(&ptile->units, mypass->ai.bodyguard);
+              if (def) {
+                handle_unit_activity_request(def, ACTIVITY_SENTRY);
               }
-            } unit_list_iterate_end; /* passengers are safely stowed away */
-           if (!ai_unit_goto(ferryboat, dest_x, dest_y)) {
-             return -1;        /* died */
-           }
-            handle_unit_activity_request(punit, ACTIVITY_IDLE);
-          } /* else wait, we can GOTO later. */
-        }
-      } 
-    }
-    if (goto_is_sane(punit, dest_x, dest_y, TRUE) && punit->moves_left > 0 &&
-       (!ferryboat || 
-       (real_map_distance(punit->x, punit->y, dest_x, dest_y) < 3 &&
-       (punit->ai.bodyguard == BODYGUARD_NONE || 
unit_list_find(&(map_get_tile(punit->x,
-       punit->y)->units), punit->ai.bodyguard) || (dcity &&
-       !has_defense(dcity)))))) {
-/* if we are on a boat, disembark only if we are within two tiles of
-our target, and either 1) we don't need a bodyguard, 2) we have a
-bodyguard, or 3) we are going to an empty city.  Previously, cannons
-would disembark before the cruisers arrived and die. -- Syela */
-
-      punit->goto_dest_x = dest_x;
-      punit->goto_dest_y = dest_y;
-
-/* The following code block is supposed to stop units from running away from 
their
-bodyguards, and not interfere with those that don't have bodyguards nearby -- 
Syela */
-/* The case where the bodyguard has moves left and could meet us en route is 
not
-handled properly.  There should be a way to do it with dir_ok but I'm tired 
now. -- Syela */
-      if (punit->ai.bodyguard < BODYGUARD_NONE) { 
-       adjc_iterate(punit->x, punit->y, i, j) {
-         unit_list_iterate(map_get_tile(i, j)->units, aunit) {
-           if (aunit->ai.charge == punit->id
-                && punit->owner == aunit->owner) {
-             freelog(LOG_DEBUG,
-                     "Bodyguard at (%d, %d) is adjacent to (%d, %d)",
-                     i, j, punit->x, punit->y);
-             if (aunit->moves_left > 0) return(0);
-             else return ai_unit_move(punit, i, j) ? 1 : 0;
-           }
-         } unit_list_iterate_end;
-        } adjc_iterate_end;
-      } /* end if */
-/* end 'short leash' subroutine */
-
-      if (ferryboat) {
-       freelog(LOG_DEBUG, "GOTHERE: %s#%d@(%d,%d)->(%d,%d)", 
-               unit_type(punit)->name, punit->id,
-               punit->x, punit->y, dest_x, dest_y);
+            }
+          } unit_list_iterate_end; /* passengers are safely stowed away */
+          if (!ai_unit_goto(ferryboat, dest_x, dest_y)) {
+            return -1; /* died */
+          }
+          handle_unit_activity_request(punit, ACTIVITY_IDLE);
+        } /* else wait, we can GOTO when more passengers come. */
       }
-      if (!ai_unit_goto(punit, dest_x, dest_y)) {
-       return -1;              /* died */
-      }
-      /* liable to bump into someone that will kill us.  Should avoid? */
-    } else {
-      freelog(LOG_DEBUG, "%s#%d@(%d,%d) not moving -> (%d, %d)",
-                   unit_type(punit)->name, punit->id,
-                   punit->x, punit->y, dest_x, dest_y);
-    }
+    } 
   }
 
+  if (goto_is_sane(punit, dest_x, dest_y, TRUE) && punit->moves_left > 0 
+      && (!ferryboat 
+          || (real_map_distance(punit->x, punit->y, dest_x, dest_y) < 3 
+              && (punit->ai.bodyguard == BODYGUARD_NONE 
+                  || unit_list_find(&(map_get_tile(punit->x, punit->y)->units),
+                                    punit->ai.bodyguard) 
+                  || (dcity && !has_defense(dcity)))))) {
+    /* if we are on a boat, disembark only if we are within two tiles of
+     * our target, and either 1) we don't need a bodyguard, 2) we have a
+     * bodyguard, or 3) we are going to an empty city.  Previously, cannons
+     * would disembark before the cruisers arrived and die. -- Syela */
+    
+    punit->goto_dest_x = dest_x;
+    punit->goto_dest_y = dest_y;
+    
+    /* The following code block is supposed to stop units from running away 
+     * from their bodyguards, and not interfere with those that don't have 
+     * bodyguards nearby -- Syela */
+    /* The case where the bodyguard has moves left and could meet us en route 
+     * is not handled properly.  There should be a way to do it with dir_ok 
+     * but I'm tired now. -- Syela */
+    if (punit->ai.bodyguard == BODYGUARD_WANTED) { 
+      adjc_iterate(punit->x, punit->y, i, j) {
+        unit_list_iterate(map_get_tile(i, j)->units, aunit) {
+          if (aunit->ai.charge != punit->id || punit->owner != aunit->owner) {
+            continue;
+          }
+          freelog(LOG_DEBUG, "Bodyguard at (%d, %d) is adjacent to (%d, %d)",
+                  i, j, punit->x, punit->y);
+          /* FIXME: What is happening here? */
+          if (aunit->moves_left > 0) {
+            return 0;
+          } else {
+            return (ai_unit_move(punit, i, j) ? 1 : 0);
+          }
+        } unit_list_iterate_end;
+      } adjc_iterate_end;
+    }
+    /* end 'short leash' subroutine */
+    
+    freelog(LOG_DEBUG, "GOTHERE: %s#%d@(%d,%d)->(%d,%d)", 
+            unit_type(punit)->name, punit->id,
+            punit->x, punit->y, dest_x, dest_y);
+    if (!ai_unit_goto(punit, dest_x, dest_y)) {
+      return -1;               /* died */
+    }
+    /* liable to bump into someone that will kill us.  Should avoid? */
+  } else {
+    freelog(LOG_DEBUG, "%s#%d@(%d,%d) not moving -> (%d, %d)",
+            unit_type(punit)->name, punit->id,
+            punit->x, punit->y, dest_x, dest_y);
+  }
+  
   /* Dead unit shouldn't reach this point */
   CHECK_UNIT(punit);
   

[Prev in Thread] Current Thread [Next in Thread]
  • [freeciv-ai] (PR#3574) Cleanup of ai_military_gothere, Gregory Berkolaiko <=