Complete.Org: Mailing Lists: Archives: freeciv-ai: May 2004:
[freeciv-ai] (PR#8805) Cleaning up build system
Home

[freeciv-ai] (PR#8805) Cleaning up build system

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [freeciv-ai] (PR#8805) Cleaning up build system
From: "Gregory Berkolaiko" <Gregory.Berkolaiko@xxxxxxxxxxxxx>
Date: Fri, 21 May 2004 23:40:01 -0700
Reply-to: rt@xxxxxxxxxxx

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

To warm-up for the general overhaul and reordering of AI build system I
decided to start small.  I cleaned and documented
ai_city_choose_build and moved establish_city_distances to where it
belongs -- aicity.c  Also added some CITY_LOG calls for future debugging.

Note that these functions don't choose builds themselves, they just call
other functions and trim the results.

And when I say "overhaul" I refer more to the high-level functions.

The building blocks like "choose a building" and "choose settlers" need
to be treated too and some of them are being treated.

Unless there is vehement opposition I will commit it pretty soon.

G.
? core.26681
? settle4.gz
? settle5.gz
? stuck.gz
? ai/aisettler.c
? ai/aisettler.h
? common/aicore/citymap.c
? common/aicore/citymap.h
Index: ai/advmilitary.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advmilitary.c,v
retrieving revision 1.165
diff -u -r1.165 advmilitary.c
--- ai/advmilitary.c    2 May 2004 12:31:05 -0000       1.165
+++ ai/advmilitary.c    22 May 2004 05:51:21 -0000
@@ -1344,45 +1344,3 @@
              improvement_types[choice->choice].name, choice->want);
   }
 }
-
-/************************************************************************** 
-This function computes distances between cities for purpose of building crowds
-of water-consuming Caravans or smoggish Freights which want to add their brick
-to the wonder being built somewhere out there.
-
-At the function entry point, our warmap is intact.  We need to do two things:
-establish faraway for THIS city and establish distance_to_wonder_city for ALL
-cities.
-
-FIXME? I think this just can't work when we have more wonder cities on one
-continent, can it? --pasky
-
-FIXME: This should be definitively somewhere else. And aicity.c sounds like
-fine candidate. --pasky
-**************************************************************************/
-void establish_city_distances(struct player *pplayer, struct city *pcity)
-{
-  int distance, wonder_continent;
-  Unit_Type_id freight = best_role_unit(pcity, F_HELP_WONDER);
-  int moverate = (freight == U_LAST) ? SINGLE_MOVE
-                                     : get_unit_type(freight)->move_rate;
-
-  if (!pcity->is_building_unit && is_wonder(pcity->currently_building)) {
-    wonder_continent = map_get_continent(pcity->x, pcity->y);
-  } else {
-    wonder_continent = 0;
-  }
-
-  pcity->ai.downtown = 0;
-  city_list_iterate(pplayer->cities, othercity) {
-    distance = WARMAP_COST(othercity->x, othercity->y);
-    if (wonder_continent != 0
-        && map_get_continent(othercity->x, othercity->y) == wonder_continent) {
-      othercity->ai.distance_to_wonder_city = distance;
-    }
-
-    /* How many people near enough would help us? */
-    distance += moverate - 1; distance /= moverate;
-    pcity->ai.downtown += MAX(0, 5 - distance);
-  } city_list_iterate_end;
-}
Index: ai/advmilitary.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advmilitary.h,v
retrieving revision 1.18
diff -u -r1.18 advmilitary.h
--- ai/advmilitary.h    18 Dec 2002 17:36:18 -0000      1.18
+++ ai/advmilitary.h    22 May 2004 05:51:21 -0000
@@ -25,7 +25,6 @@
 void  military_advisor_choose_build(struct player *pplayer, struct city *pcity,
                                    struct ai_choice *choice);
 void assess_danger_player(struct player *pplayer);
-void establish_city_distances(struct player *pplayer, struct city *pcity);
 int assess_defense_quadratic(struct city *pcity);
 int assess_defense_unit(struct city *pcity, struct unit *punit, bool igwall);
 int assess_defense(struct city *pcity);
Index: ai/aicity.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.c,v
retrieving revision 1.151
diff -u -r1.151 aicity.c
--- ai/aicity.c 19 May 2004 14:40:15 -0000      1.151
+++ ai/aicity.c 22 May 2004 05:51:24 -0000
@@ -171,15 +171,105 @@
   city_list_iterate_end;
 }
 
+/*************************************************************************** 
+  This function computes distances between cities for purpose of building 
+  crowds of water-consuming Caravans or smoggish Freights which want to add 
+  their brick to the wonder being built in pcity.
+
+  At the function entry point, our warmap is intact.  We need to do two 
+  things: (1) establish "downtown" for THIS city (which is an estimate of 
+  how much help we can expect when building a wonder) and 
+  (2) establish distance to pcity for ALL cities on our continent.
+
+  If there are more than one wondercity, things will get a bit random.
+****************************************************************************/
+static void establish_city_distances(struct player *pplayer, 
+                                    struct city *pcity)
+{
+  int distance, wonder_continent;
+  Unit_Type_id freight = best_role_unit(pcity, F_HELP_WONDER);
+  int moverate = (freight == U_LAST) ? SINGLE_MOVE
+                                     : get_unit_type(freight)->move_rate;
+
+  if (!pcity->is_building_unit && is_wonder(pcity->currently_building)) {
+    wonder_continent = map_get_continent(pcity->x, pcity->y);
+  } else {
+    wonder_continent = 0;
+  }
+
+  pcity->ai.downtown = 0;
+  city_list_iterate(pplayer->cities, othercity) {
+    distance = WARMAP_COST(othercity->x, othercity->y);
+    if (wonder_continent != 0
+        && map_get_continent(othercity->x, othercity->y) == wonder_continent) {
+      othercity->ai.distance_to_wonder_city = distance;
+    }
+
+    /* How many people near enough would help us? */
+    distance += moverate - 1; distance /= moverate;
+    pcity->ai.downtown += MAX(0, 5 - distance);
+  } city_list_iterate_end;
+}
+
+/**************************************************************************
+  Choose a build for the barbarian player.
+
+  TODO: Move this into advmilitary.c
+  TODO: It will be called for each city but doesn't depend on the city,
+  maybe cache it?  Although barbarians don't normally have many cities, 
+  so can be a bigger bother to cache it.
+**************************************************************************/
+static void ai_barbarian_choose_build(struct player *pplayer, 
+                                     struct ai_choice *choice)
+{
+  Unit_Type_id bestunit = -1;
+  int i, bestattack = 0;
+
+  /* Choose the best unit among the basic ones */
+  for(i = 0; i < num_role_units(L_BARBARIAN_BUILD); i++) {
+    Unit_Type_id iunit = get_role_unit(L_BARBARIAN_BUILD, i);
+
+    if (get_unit_type(iunit)->attack_strength > bestattack) {
+      bestunit = iunit;
+      bestattack = get_unit_type(iunit)->attack_strength;
+    }
+  }
+
+  /* Choose among those made available through other civ's research */
+  for(i = 0; i < num_role_units(L_BARBARIAN_BUILD_TECH); i++) {
+    Unit_Type_id iunit = get_role_unit(L_BARBARIAN_BUILD_TECH, i);
+
+    if (game.global_advances[get_unit_type(iunit)->tech_requirement] != 0
+       && get_unit_type(iunit)->attack_strength > bestattack) {
+      bestunit = iunit;
+      bestattack = get_unit_type(iunit)->attack_strength;
+    }
+  }
+
+  /* If found anything, put it into the choice */
+  if (bestunit != -1) {
+    choice->choice = bestunit;
+    /* FIXME: 101 is the "overriding military emergency" indicator */
+    choice->want   = 101;
+    choice->type   = CT_ATTACKER;
+  } else {
+    freelog(LOG_VERBOSE, "Barbarians don't know what to build!");
+  }
+}
+
 /************************************************************************** 
-... change the build order.
+  Chooses what the city will build.  Is called after the military advisor
+  put it's choice into pcity->ai.choice and "settler advisor" put settler
+  want into pcity->founder_*.
+
+  Note that AI cheats -- it suffers no penalty for switching from unit to 
+  improvement, etc.
 **************************************************************************/
 static void ai_city_choose_build(struct player *pplayer, struct city *pcity)
 {
-  struct ai_choice bestchoice, curchoice;
+  struct ai_choice newchoice;
 
-  init_choice(&bestchoice);
-  init_choice(&curchoice);
+  init_choice(&newchoice);
 
   if (ai_handicap(pplayer, H_AWAY)
       && game_next_year(pcity->turn_last_built) != game.year
@@ -188,103 +278,75 @@
     return;
   }
 
-  if( is_barbarian(pplayer) ) {    /* always build best attack unit */
-    Unit_Type_id i, iunit, bestunit = -1;
-    int bestattack = 0;
-    for(i = 0; i < num_role_units(L_BARBARIAN_BUILD); i++) {
-      iunit = get_role_unit(L_BARBARIAN_BUILD, i);
-      if (get_unit_type(iunit)->attack_strength > bestattack) {
-       bestunit = iunit;
-       bestattack = get_unit_type(iunit)->attack_strength;
-      }
-    }
-    for(i = 0; i < num_role_units(L_BARBARIAN_BUILD_TECH); i++) {
-      iunit = get_role_unit(L_BARBARIAN_BUILD_TECH, i);
-      if (game.global_advances[get_unit_type(iunit)->tech_requirement] != 0
-         && get_unit_type(iunit)->attack_strength > bestattack) {
-       bestunit = iunit;
-       bestattack = get_unit_type(iunit)->attack_strength;
-      }
-    }
-    if (bestunit != -1) {
-      bestchoice.choice = bestunit;
-      bestchoice.want   = 101;
-      bestchoice.type   = CT_ATTACKER;
-    }
-    else {
-      freelog(LOG_VERBOSE, "Barbarians don't know what to build!\n");
+  if( is_barbarian(pplayer) ) {
+    ai_barbarian_choose_build(pplayer, &(pcity->ai.choice));
+  } else {
+    /* FIXME: 101 is the "overriding military emergency" indicator */
+    if (pcity->ai.choice.want <= 100 || pcity->ai.urgency == 0) { 
+      domestic_advisor_choose_build(pplayer, pcity, &newchoice);
+      copy_if_better_choice(&newchoice, &(pcity->ai.choice));
     }
   }
-  else {
-    copy_if_better_choice(&pcity->ai.choice, &bestchoice);
 
-    if (bestchoice.want <= 100 || pcity->ai.urgency == 0) { /* soldier at 101 
cannot be denied */
-      domestic_advisor_choose_build(pplayer, pcity, &curchoice);
-      copy_if_better_choice(&curchoice, &bestchoice);
+  /* Fallbacks */
+  if (pcity->ai.choice.want == 0) {
+    /* Fallbacks do happen with techlevel 0, which is now default. -- Per */
+    CITY_LOG(LOG_VERBOSE, pcity, "Falling back - didn't want to build 
soldiers,"
+            " settlers, or buildings");
+    pcity->ai.choice.want = 1;
+    if (best_role_unit(pcity, F_TRADE_ROUTE) != U_LAST) {
+      pcity->ai.choice.choice = best_role_unit(pcity, F_TRADE_ROUTE);
+      pcity->ai.choice.type = CT_NONMIL;
+    } else if (can_build_improvement(pcity, B_CAPITAL)) {
+      pcity->ai.choice.choice = B_CAPITAL;
+      pcity->ai.choice.type = CT_BUILDING;
+    } else if (best_role_unit(pcity, F_SETTLERS) != U_LAST) {
+      pcity->ai.choice.choice = best_role_unit(pcity, F_SETTLERS);
+      pcity->ai.choice.type = CT_NONMIL;
+    } else {
+      CITY_LOG(LOG_VERBOSE, pcity, "Cannot even build a fallback "
+              "(caravan/coinage/settlers). Fix the ruleset!");
+      pcity->ai.choice.want = 0;
     }
-
-    pcity->ai.choice.choice = bestchoice.choice; /* we want to spend gold 
later */
-    pcity->ai.choice.want = bestchoice.want; /* so that we spend it in the 
right city */
-    pcity->ai.choice.type = bestchoice.type; /* instead of the one atop the 
list */
-    pcity->ai.choice.need_boat = bestchoice.need_boat;
   }
 
-  if (bestchoice.want != 0) { /* Note - on fallbacks, will NOT get stopped 
building msg */
+  if (pcity->ai.choice.want != 0) { 
+    ASSERT_REAL_CHOICE_TYPE(pcity->ai.choice.type);
 
-    ASSERT_REAL_CHOICE_TYPE(bestchoice.type);
-
-    freelog(LOG_DEBUG, "%s wants %s with desire %d.", pcity->name,
-                 (is_unit_choice_type(bestchoice.type) ?
-                   unit_name(bestchoice.choice) :
-                  get_improvement_name(bestchoice.choice)),
-                 bestchoice.want);
-    if (!pcity->is_building_unit && is_wonder(pcity->currently_building) &&
-       (is_unit_choice_type(bestchoice.type) ||
-        bestchoice.choice != pcity->currently_building))
+    CITY_LOG(LOG_DEBUG, pcity, "wants %s with desire %d.",
+            (is_unit_choice_type(pcity->ai.choice.type) ?
+             unit_name(pcity->ai.choice.choice) :
+             get_improvement_name(pcity->ai.choice.choice)),
+            pcity->ai.choice.want);
+    
+    if (!pcity->is_building_unit && is_wonder(pcity->currently_building) 
+       && (is_unit_choice_type(pcity->ai.choice.type) 
+           || pcity->ai.choice.choice != pcity->currently_building))
       notify_player_ex(NULL, pcity->x, pcity->y, E_WONDER_STOPPED,
                       _("Game: The %s have stopped building The %s in %s."),
                       get_nation_name_plural(pplayer->nation),
                       get_impr_name_ex(pcity, pcity->currently_building),
                       pcity->name);
-
-    if (bestchoice.type == CT_BUILDING && (pcity->is_building_unit ||
-                 pcity->currently_building != bestchoice.choice) &&
-                 is_wonder(bestchoice.choice)) {
+    
+    if (pcity->ai.choice.type == CT_BUILDING 
+       && is_wonder(pcity->ai.choice.choice)
+       && (pcity->is_building_unit 
+           || pcity->currently_building != pcity->ai.choice.choice)) {
       notify_player_ex(NULL, pcity->x, pcity->y, E_WONDER_STARTED,
                       _("Game: The %s have started building The %s in %s."),
                       get_nation_name_plural(city_owner(pcity)->nation),
-                      get_impr_name_ex(pcity, bestchoice.choice),
+                      get_impr_name_ex(pcity, pcity->ai.choice.choice),
                       pcity->name);
-      pcity->currently_building = bestchoice.choice;
-      pcity->is_building_unit    = is_unit_choice_type(bestchoice.type);
+      pcity->currently_building = pcity->ai.choice.choice;
+      pcity->is_building_unit = is_unit_choice_type(pcity->ai.choice.type);
 
-      /* need to establish distance to wondercity */
+      /* Help other cities to send caravans to us */
       generate_warmap(pcity, NULL);
-
-      establish_city_distances(pplayer, pcity); /* for caravans in other 
cities */
+      establish_city_distances(pplayer, pcity);
     } else {
-      pcity->currently_building = bestchoice.choice;
-      pcity->is_building_unit   = is_unit_choice_type(bestchoice.type);
+      pcity->currently_building = pcity->ai.choice.choice;
+      pcity->is_building_unit   = is_unit_choice_type(pcity->ai.choice.type);
     }
-
-    return;
-  } /* AI cheats -- no penalty for switching from unit to improvement, etc. */
-
-  /* I think fallbacks only happen with techlevel 0, and even then are rare.
-   * I haven't seen them, but I want to somewhat prepare for them anyway. 
-   * -- Syela */ 
-  /* Yes, they do happen with techlevel 0, which is now default. -- Per */
-  freelog(LOG_VERBOSE, "Falling back - %s didn't want soldiers, settlers,"
-                       " or buildings", pcity->name);
-  if (best_role_unit(pcity, F_TRADE_ROUTE) != U_LAST) {
-    pcity->currently_building = best_role_unit(pcity, F_TRADE_ROUTE);
-    pcity->is_building_unit = TRUE;
-  } else if (can_build_improvement(pcity, B_CAPITAL)) {
-    pcity->currently_building = B_CAPITAL;
-    pcity->is_building_unit = FALSE;
-  } else if (best_role_unit(pcity, F_SETTLERS) != U_LAST) {
-    pcity->currently_building = best_role_unit(pcity, F_SETTLERS);
-    pcity->is_building_unit = TRUE;
   }
 }
 

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