Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2001:
[Freeciv-Dev] [PATCH] ai_manage_explorer splitup
Home

[Freeciv-Dev] [PATCH] ai_manage_explorer splitup

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] [PATCH] ai_manage_explorer splitup
From: Markus Linnala <maage@xxxxxxxxx>
Date: 22 Aug 2001 12:09:30 +0300
Reply-to: Markus Linnala <maage@xxxxxxxxx>

With this patch I split up ai_manage_explorer into 4 parts. This
patch is only for code clarity. I tried not to alter code. At
least according to profiler functions are called alike. And
savegames are same.

Before:
------------------------------------------------------------------------
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
 14.68      1.12     1.12      926     1.21     2.82  ai_manage_explorer
  6.42      1.61     0.49  9044747     0.00     0.00  map_get_tile
  6.16      2.08     0.47  2168963     0.00     0.00  map_get_special
  5.37      2.49     0.41  8535883     0.00     0.00  tech_exists
  4.19      2.81     0.32  2048453     0.00     0.00  map_get_terrain
  4.19      3.13     0.32     1435     0.22     0.44  really_generate_warmap
  3.01      3.36     0.23       22    10.45    17.90  check_fow
  2.49      3.55     0.19  1000854     0.00     0.00  food_weighting
  2.23      3.72     0.17    16898     0.01     0.02  find_prerequisites
  1.97      3.87     0.15     1375     0.11     0.31  find_the_shortest_path
  1.83      4.01     0.14  6357317     0.00     0.00  get_player
  1.83      4.15     0.14  2272707     0.00     0.00  map_get_city
  1.70      4.28     0.13   282670     0.00     0.00  myrand
  1.57      4.40     0.12  2760258     0.00     0.00  find_genlist_position
  1.57      4.52     0.12  1943989     0.00     0.00  map_get_player_tile
  1.44      4.63     0.11    43462     0.00     0.01  unfog_area
  1.44      4.74     0.11    26722     0.00     0.02  city_desirability
  1.31      4.84     0.10  3070509     0.00     0.00  get_invention
  1.31      4.94     0.10    11972     0.01     0.03  update_research
  1.18      5.03     0.09    65627     0.00     0.00  unit_win_chance
  1.18      5.12     0.09       10     9.00    13.08  player_save
  1.05      5.20     0.08   448054     0.00     0.00  add_to_mapqueue
  1.05      5.28     0.08      133     0.60     3.23  ai_select_tech

After:
------------------------------------------------------------------------
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
 10.25      0.78     0.78      626     1.25     2.35  ai_manage_explorer_3
  8.41      1.42     0.64  9044747     0.00     0.00  map_get_tile
  5.91      1.87     0.45  2168963     0.00     0.00  map_get_special
  4.60      2.22     0.35  8535883     0.00     0.00  tech_exists
  3.81      2.51     0.29  2048453     0.00     0.00  map_get_terrain
  3.68      2.79     0.28  2272707     0.00     0.00  map_get_city
  3.29      3.04     0.25       22    11.36    21.64  check_fow
  3.02      3.27     0.23     1435     0.16     0.42  really_generate_warmap
  2.50      3.46     0.19      964     0.20     0.74  ai_manage_explorer_1
  2.37      3.64     0.18  6357317     0.00     0.00  get_player
  2.23      3.81     0.17  1943989     0.00     0.00  map_get_player_tile
  1.97      3.96     0.15   282670     0.00     0.00  myrand
  1.97      4.11     0.15    26722     0.01     0.02  city_desirability
  1.84      4.25     0.14    11972     0.01     0.03  update_research
  1.71      4.38     0.13      258     0.50     3.89  evaluate_city_building
  1.58      4.50     0.12  1000854     0.00     0.00  food_weighting
  1.58      4.62     0.12    43462     0.00     0.02  unfog_area
  1.45      4.73     0.11  2759581     0.00     0.00  genlist_iterator_init
  1.45      4.84     0.11   797457     0.00     0.00  map_get_continent
  1.45      4.95     0.11    16898     0.01     0.02  find_prerequisites
  1.45      5.06     0.11     1375     0.08     0.31  find_the_shortest_path
  1.31      5.16     0.10   452222     0.00     0.00  get_from_mapqueue
  1.05      5.24     0.08  3070509     0.00     0.00  get_invention
  1.05      5.32     0.08  1902503     0.00     0.00  map_get_known
  1.05      5.40     0.08    94786     0.00     0.00  shared_vision_change_seen
  1.05      5.48     0.08       10     8.00    13.46  player_save
...
  0.00      7.61     0.00      926     0.00     2.70  ai_manage_explorer
  0.00      7.61     0.00      742     0.00     0.09  ai_manage_explorer_2
  0.00      7.61     0.00      256     0.00     0.01  ai_manage_explorer_4
...
-----------------------------------------------
index % time    self  children    called     name
                0.78    0.69     626/626         ai_manage_explorer [6]
[10]    19.3    0.78    0.69     626         ai_manage_explorer_3 [10]
                0.00    0.24     370/1375        do_unit_goto [13]
                0.18    0.00 2504000/9044747     map_get_tile [18]
                0.00    0.16     626/2487        generate_warmap [20]
                0.03    0.05  746370/1902503     map_get_known [48]
                0.00    0.01   82981/83221       tile_is_accessible [180]
                0.00    0.01   89479/284961      is_non_allied_unit_tile [141]
                0.00    0.00   84427/259566      is_non_allied_city_tile [201]
                0.00    0.00    1925/282670      myrand [57]
                0.00    0.00     429/729         handle_unit_activity_request 
[387]
                0.00    0.00     626/2272707     map_get_city [44]
                0.00    0.00     626/1903        unit_move_rate [389]
                0.00    0.00   23298/609979      is_sailing_unit [555]
                0.00    0.00    3732/344462      is_barbarian [556]
-----------------------------------------------

Produced by:
------------------------------------------------------------------------
set xsize 80
set ysize 50
set maxplayers 30
set aifill 10
set explorer 10
set timeout 1
set randseed 1
set seed 3
set endyear -3500
create maage
hard
start
------------------------------------------------------------------------

-- 
//Markus

--- freeciv-cvs/ai/aiunit.c     Wed Aug 22 10:25:35 2001
+++ freeciv/ai/aiunit.c Wed Aug 22 11:42:45 2001
@@ -53,6 +53,14 @@
 static void ai_manage_barbarian_leader(struct player *pplayer,
                                       struct unit *leader);
 
+static int ai_manage_explorer_1(struct unit *punit, struct player *pplayer);
+static int ai_manage_explorer_2(struct unit *punit, struct player *pplayer,
+                               int con, int range);
+static int ai_manage_explorer_3(struct unit *punit, struct player *pplayer, 
+                               int con, int range);
+static void ai_manage_explorer_4(struct unit *punit, struct player *pplayer, 
+                                int con);
+
 static void ai_military_findjob(struct player *pplayer,struct unit *punit);
 static void ai_military_gohome(struct player *pplayer,struct unit *punit);
 static void ai_military_attack(struct player *pplayer,struct unit *punit);
@@ -178,78 +186,73 @@
 
   return 0;
 }
- 
-/**************************************************************************
-Explores unknown territory, finds huts.
-Returns whether there is any more territory to be explored.
-**************************************************************************/
-int ai_manage_explorer(struct unit *punit)
-{
-  struct player *pplayer = unit_owner(punit);
-  int x, y; /* is the position of the unit; updated inside the function */
-  int con; /* continent the unit is on */
-  struct city *pcity;
-  int id = punit->id; /* we can now die because easy AI may accidently
-                        stumble on huts it fuzzily ignored */
-  int best_x = -1, best_y = -1;
-  int range = get_unit_type(punit->type)->vision_range;
-  int move_rate = unit_move_rate(punit);
 
-  if (punit->activity != ACTIVITY_IDLE)
-    handle_unit_activity_request(punit, ACTIVITY_IDLE);
-
-  x = punit->x; y = punit->y;
-  if (is_ground_unit(punit)) con = map_get_continent(x, y);
-  else con = 0; /* Thanks, Tony */
-
-  /* CPU-expensive but worth it -- Syela */
-  generate_warmap(map_get_city(x, y), punit);
+/**************************************************************************
+  Exploring is split into parts.
 
-  /* BEGIN PART ONE: Look for huts.  Non-Barbarian Ground units ONLY. */
-  if (!is_barbarian(pplayer)
-      && is_ground_unit(punit)) { /* boats don't hunt huts */
-    int maxcost = pplayer->ai.control ? 2 * THRESHOLD : 3;
-    int bestcost = maxcost * SINGLE_MOVE + 1;
-
-    /* Iterating outward so that with two tiles with the same movecost
-       the nearest is used */
-    iterate_outward(x, y, maxcost, x1, y1) {
-      if (map_get_special(x1, y1) & S_HUT
-         && warmap.cost[x1][y1] < bestcost
-         && (!ai_handicap(pplayer, H_HUTS) || map_get_known(x1, y1, pplayer))
-         && tile_is_accessible(punit, x1, y1)
-         && ai_fuzzy(pplayer, 1)) {
-       best_x = x1;
-       best_y = y1;
-       bestcost = warmap.cost[best_x][best_y];
-      }
-    } iterate_outward_end;
-    if (bestcost <= maxcost * SINGLE_MOVE) {
-      punit->goto_dest_x = best_x;
-      punit->goto_dest_y = best_y;
-      set_unit_activity(punit, ACTIVITY_GOTO);
-      do_unit_goto(punit, GOTO_MOVE_ANY, 0);
-      if (!player_find_unit_by_id(pplayer, id))
-       return 0; /* died */
+  First we try to explore near and valuable targets. Later we
+  focus targets at greater distance.
+**************************************************************************/
 
-      if (punit->moves_left) {
-       if (punit->x == best_x && punit->y == best_y) {
-         return ai_manage_explorer(punit);
-       } else {
-         /* Something went wrong; fall through. This should almost never 
happen. */
-         if (punit->x != x || punit->y != y)
-           generate_warmap(map_get_city(punit->x, punit->y), punit);
-         x = punit->x; y = punit->y;
-         /* Fallthough to next fase */
-       }
+/* BEGIN PART ONE: Look for huts. */
+static int ai_manage_explorer_1(struct unit *punit, struct player *pplayer)
+{ 
+  int maxcost = pplayer->ai.control ? 2 * THRESHOLD : 3;
+  int bestcost = maxcost * SINGLE_MOVE + 1;
+  int best_x = -1, best_y = -1, x = punit->x, y = punit->y;
+
+  /* Iterating outward so that with two tiles with the same movecost
+     the nearest is used */
+  iterate_outward(x, y, maxcost, x1, y1) {
+    if (map_get_special(x1, y1) & S_HUT
+       && warmap.cost[x1][y1] < bestcost
+       && (!ai_handicap(pplayer, H_HUTS) || map_get_known(x1, y1, pplayer))
+       && tile_is_accessible(punit, x1, y1)
+       && ai_fuzzy(pplayer, 1)) {
+      best_x = x1;
+      best_y = y1;
+      bestcost = warmap.cost[best_x][best_y];
+    }
+  } iterate_outward_end;
+  if (bestcost <= maxcost * SINGLE_MOVE) {
+    int id = punit->id; /* we can now die because easy AI may accidently
+                          stumble on huts it fuzzily ignored */
+    punit->goto_dest_x = best_x;
+    punit->goto_dest_y = best_y;
+    
+    set_unit_activity(punit, ACTIVITY_GOTO);
+    do_unit_goto(punit, GOTO_MOVE_ANY, 0);
+
+    if (!player_find_unit_by_id(pplayer, id))
+      return 0; /* died */
+   
+    if (punit->moves_left) {
+      /* If we have moves left */
+      if (punit->x == best_x && punit->y == best_y) {
+       /* and reached destination, start again, we call this
+          recursive */
+       return -2;
       } else {
-       return 1;
+       /* Something went wrong; fall through. This should
+          almost never happen. */
+       if (punit->x != x || punit->y != y)
+         generate_warmap(map_get_city(punit->x, punit->y), punit);
       }
+    } else {
+      return 1;
     }
   }
+  return -1;
+}
+
+/* BEGIN PART TWO: Move into unexplored territory */
+/* move the unit as long as moving will unveil unknown territory */
+static int ai_manage_explorer_2(struct unit *punit, struct player *pplayer,
+                               int con, int range)
+{
+  int best_x = -1, best_y = -1, x = punit->x, y = punit->y;
+  struct city *pcity;
 
-  /* BEGIN PART TWO: Move into unexplored territory */
-  /* move the unit as long as moving will unveil unknown territory */
   while (punit->moves_left) {
     int most_unknown = 0;
     int unknown;
@@ -269,7 +272,7 @@
          && (landnear || !unit_flag(punit->type, F_TRIREME))
          && map_get_continent(x1, y1) == con
          && can_unit_move_to_tile(punit, x1, y1, 0)
-         && !((pcity = map_get_city(x1,y1))
+         && !((pcity = map_get_city(x1, y1))
               && (unit_flag(punit->type, F_DIPLOMAT)
                   || unit_flag(punit->type, F_CARAVAN)))
          && !(is_barbarian(pplayer) && map_get_special(x1, y1) & S_HUT)) {
@@ -280,6 +283,8 @@
     } square_iterate_end;
 
     if (most_unknown > 0) { /* a tile have unexplored territory adjacent */
+      int id = punit->id; /* we can now die because easy AI may accidently
+                            stumble on huts it fuzzily ignored */
       int res = handle_unit_move_request(punit, best_x, best_y, FALSE, FALSE);
       if (!res) /* This shouldn't happen */
        break;
@@ -293,74 +298,137 @@
 
   if (!punit->moves_left) return 1;
 
-  /* BEGIN PART THREE: Go towards unexplored territory */
-  /* no adjacent squares help us to explore - really slow part follows */
+  return -1;
+}
+
+/* BEGIN PART THREE: Go towards unexplored territory */
+/* no adjacent squares help us to explore - really slow part follows */
+static int ai_manage_explorer_3(struct unit *punit, struct player *pplayer, 
+                               int con, int range)
+{
+  int best_x = -1, best_y = -1, x = punit->x, y = punit->y;
+  int unknown, most_unknown = 0;
+  int move_rate = unit_move_rate(punit);
+  int threshold = THRESHOLD * move_rate;
+
   generate_warmap(map_get_city(x, y), punit);
 
-  {
-    int unknown, most_unknown = 0;
-    int threshold = THRESHOLD * move_rate;
-    whole_map_iterate(x1, y1) {
-      struct tile *ptile = map_get_tile(x1, y1);
-      unknown = 0;
-      if (ptile->continent == con
-         && !is_non_allied_unit_tile(ptile, punit->owner)
-         && !is_non_allied_city_tile(ptile, punit->owner)
-         && tile_is_accessible(punit, x1, y1)) {
-       square_iterate(x1, y1, range, x2, y2) {
-         if (!map_get_known(x2, y2, pplayer))
-           unknown++;
-       } square_iterate_end;
-       if (unknown) {
-         if (is_sailing_unit(punit))
-           unknown += 9 * (threshold - warmap.seacost[x1][y1]);
-         else
-           unknown += 9 * (threshold - warmap.cost[x1][y1]);
-         if ((unknown > most_unknown || (unknown == most_unknown && myrand(2)))
-             && !(is_barbarian(pplayer) && ptile->special & S_HUT)) {
-           best_x = x1;
-           best_y = y1;
-           most_unknown = unknown;
-         }
+  whole_map_iterate(x1, y1) {
+    struct tile *ptile = map_get_tile(x1, y1);
+    unknown = 0;
+    if (ptile->continent == con
+       && !is_non_allied_unit_tile(ptile, punit->owner)
+       && !is_non_allied_city_tile(ptile, punit->owner)
+       && tile_is_accessible(punit, x1, y1)) {
+      square_iterate(x1, y1, range, x2, y2) {
+       if (!map_get_known(x2, y2, pplayer))
+         unknown++;
+      } square_iterate_end;
+      if (unknown) {
+       if (is_sailing_unit(punit))
+         unknown += 9 * (threshold - warmap.seacost[x1][y1]);
+       else
+         unknown += 9 * (threshold - warmap.cost[x1][y1]);
+       if ((unknown > most_unknown || (unknown == most_unknown && myrand(2)))
+           && !(is_barbarian(pplayer) && ptile->special & S_HUT)) {
+         best_x = x1;
+         best_y = y1;
+         most_unknown = unknown;
        }
       }
-    } whole_map_iterate_end;
+    }
+  } whole_map_iterate_end;
 
-    if (most_unknown > 0) {
-      punit->goto_dest_x = best_x;
-      punit->goto_dest_y = best_y;
-      handle_unit_activity_request(punit, ACTIVITY_GOTO);
-      do_unit_goto(punit, GOTO_MOVE_ANY, 0);
-      if (punit->moves_left) {
-       if (punit->x != best_x || punit->y != best_y) {
-         handle_unit_activity_request(punit, ACTIVITY_IDLE);
-         return 1; /* Something wrong; what to do but return? */
-       } else
-         return ai_manage_explorer(punit);
-      } else {
-       return 1;
-      }
-    } /* no candidates; fall-through */
-  }
+  if (most_unknown > 0) {
+    punit->goto_dest_x = best_x;
+    punit->goto_dest_y = best_y;
+    handle_unit_activity_request(punit, ACTIVITY_GOTO);
+    do_unit_goto(punit, GOTO_MOVE_ANY, 0);
+    if (punit->moves_left) {
+      if (punit->x != best_x || punit->y != best_y) {
+       handle_unit_activity_request(punit, ACTIVITY_IDLE);
+       return 1; /* Something wrong; what to do but return? */
+      } else
+       return -2;
+    } else {
+      return 1;
+    }
+  } /* no candidates; fall-through */
+
+  return -1;
+}
+
+/* BEGIN PART FOUR: maybe go to another continent */
+static void ai_manage_explorer_4(struct unit *punit, struct player *pplayer, 
+                                int con)
+{
+  int x = punit->x, y = punit->y;
+  struct city *pcity;
 
-  /* BEGIN PART FOUR: maybe go to another continent */
   freelog(LOG_DEBUG, "%s's %s at (%d,%d) failed to explore.",
          pplayer->name, unit_types[punit->type].name, punit->x, punit->y);
   handle_unit_activity_request(punit, ACTIVITY_IDLE);
-  if (pplayer->ai.control && is_military_unit(punit)) {
-    pcity = find_city_by_id(punit->homecity);
-    if (pcity && map_get_continent(pcity->x, pcity->y) == con)
-      ai_military_gohome(pplayer, punit);
-    else if (pcity) {
-      if (!find_boat(pplayer, &x, &y, 0)) /* Gilligan's Island */
-        punit->ai.ferryboat = -1;
-      else {
-        punit->goto_dest_x = x;
-        punit->goto_dest_y = y;
-        do_unit_goto(punit, GOTO_MOVE_ANY, 0);
-      }
+  if (!pplayer->ai.control || !is_military_unit(punit))
+    return;
+
+  pcity = find_city_by_id(punit->homecity);
+  if (!pcity) 
+    return;
+
+  if (map_get_continent(pcity->x, pcity->y) == con)
+    ai_military_gohome(pplayer, punit);
+  else {
+    if (!find_boat(pplayer, &x, &y, 0)) /* Gilligan's Island */
+      punit->ai.ferryboat = -1;
+    else {
+      punit->goto_dest_x = x;
+      punit->goto_dest_y = y;
+      do_unit_goto(punit, GOTO_MOVE_ANY, 0);
     }
   }
+}
+
+/**************************************************************************
+Explores unknown territory, finds huts.
+Returns whether there is any more territory to be explored.
+**************************************************************************/
+int ai_manage_explorer(struct unit *punit)
+{
+  struct player *pplayer = unit_owner(punit);
+  int rv;
+  int x, y;
+  int con; /* continent the unit is on */
+  int range;
+
+  if (punit->activity != ACTIVITY_IDLE)
+    handle_unit_activity_request(punit, ACTIVITY_IDLE);
+
+  x = punit->x; y = punit->y;
+  if (is_ground_unit(punit)) con = map_get_continent(x, y);
+  else con = 0; /* Thanks, Tony */
+
+  /* CPU-expensive but worth it -- Syela */
+  generate_warmap(map_get_city(x, y), punit);
+
+  /* Barbarians and boats don't hunt huts */
+  if (!is_barbarian(pplayer) && is_ground_unit(punit))
+  {
+    rv = ai_manage_explorer_1(punit, pplayer);
+    if (rv >= 0) return rv;
+    if (rv == -2) return ai_manage_explorer(punit);
+  }
+
+  range = get_unit_type(punit->type)->vision_range;
+
+  rv = ai_manage_explorer_2(punit, pplayer, con, range);
+  if (rv >= 0) return rv;
+  if (rv == -2) return ai_manage_explorer(punit);
+
+  rv = ai_manage_explorer_3(punit, pplayer, con, range);
+  if (rv >= 0) return rv;
+  if (rv == -2) return ai_manage_explorer(punit);
+
+  ai_manage_explorer_4(punit, pplayer, con);
   return 0;
 }
 




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