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

 This patch makes buildings returned by ai_find_source_building() more
sane in a number of ways.

 - It takes city instead of player as parameter. It returns buildings
this particular city can build
 - It returns best (as greatest effect value) building instead of first match
 - It can take unit class or move type building should affect. No
longer building Airport when veteran land units wanted or Coastal
defense when afraid of missiles. On the negative side this means that
some buildings are no longer built at all as AI has been building them
only 'by accident'.

 Callers take advantage of these improvements.


 - ML

diff -Nurd -X.diff_ignore freeciv/ai/advmilitary.c freeciv/ai/advmilitary.c
--- freeciv/ai/advmilitary.c    2008-06-18 17:45:25.000000000 +0300
+++ freeciv/ai/advmilitary.c    2008-07-21 23:59:23.000000000 +0300
@@ -635,8 +635,10 @@
   /* HACK: This needs changing if multiple improvements provide
    * this effect. */
   /* FIXME: Check attacker type and protect against that. Now
-   * always assess land danger and builds any defend bonus as result. */
-  defender = ai_find_source_building(pplayer, EFT_DEFEND_BONUS);
+   * always assess land danger. */
+  /* FIXME: Accept only buildings helping unit classes we actually use.
+   *        Now we consider any land mover helper suitable. */
+  defender = ai_find_source_building(pcity, EFT_DEFEND_BONUS, NULL, 
LAND_MOVING);
 
   if (defender != B_LAST) {
     ai_reevaluate_building(pcity, &pcity->ai.building_want[defender],
@@ -922,9 +924,9 @@
       int move_time;
       int vuln;
 
-      /* TODO: check for the right _type_ of building. */
       int will_be_veteran
-       = (ai_find_source_building(pplayer, EFT_VETERAN_BUILD) != B_LAST);
+       = (ai_find_source_building(pcity, EFT_VETERAN_BUILD,
+                                   utype_class(punittype), MOVETYPE_LAST) != 
B_LAST);
       /* Cost (shield equivalent) of gaining these techs. */
       /* FIXME? Katvrr advises that this should be weighted more heavily in big
        * danger. */
@@ -1309,7 +1311,6 @@
                                   struct ai_choice *choice)
 {
   enum unit_move_type move_type;
-  struct player *pplayer = city_owner(pcity);
   Impr_type_id id;
 
   /* Sanity */
@@ -1321,9 +1322,10 @@
 
   move_type = utype_move_type(choice->value.utype);
 
-  /* TODO: separate checks based on other requirements (e.g., unit class) 
-   *  N.B.: have to check that we haven't already built the building --mck */
-  if ((id = ai_find_source_building(pplayer, EFT_VETERAN_BUILD)) != B_LAST
+  /*  N.B.: have to check that we haven't already built the building --mck */
+  if ((id = ai_find_source_building(pcity, EFT_VETERAN_BUILD,
+                                    utype_class(choice->value.utype),
+                                    MOVETYPE_LAST)) != B_LAST
        && !city_has_building(pcity, improvement_by_number(id))) {
     choice->value.building = improvement_by_number(id);
     choice->type = CT_BUILDING;
@@ -1387,14 +1389,14 @@
     CITY_LOG(LOG_DEBUG, pcity, "m_a_c_d urgency=%d danger=%d num_def=%d "
              "our_def=%d", urgency, danger, num_defenders, our_def);
 
-    /* FIXME: 1. Will tend to build walls beofre coastal irrespectfully what
+    /* FIXME: 1. Will tend to build walls before coastal irrespectfully what
      * type of danger we are facing */
     /* We will build walls if we can and want and (have "enough" defenders or
      * can just buy the walls straight away) */
 
     /* HACK: This needs changing if multiple improvements provide
      * this effect. */
-    wall_id = ai_find_source_building(pplayer, EFT_DEFEND_BONUS);
+    wall_id = ai_find_source_building(pcity, EFT_DEFEND_BONUS, NULL, 
LAND_MOVING);
     pimprove = improvement_by_number(wall_id);
 
     if (wall_id != B_LAST
diff -Nurd -X.diff_ignore freeciv/common/effects.c freeciv/common/effects.c
--- freeciv/common/effects.c    2008-01-15 04:54:52.000000000 +0200
+++ freeciv/common/effects.c    2008-07-21 23:52:58.000000000 +0300
@@ -504,24 +504,52 @@
   Note: this function is an inefficient hack to be used by the old AI.  It
   will never find wonders, since that's not what the AI wants.
 **************************************************************************/
-Impr_type_id ai_find_source_building(struct player *pplayer,
-                                    enum effect_type effect_type)
+Impr_type_id ai_find_source_building(struct city *pcity,
+                                    enum effect_type effect_type,
+                                     struct unit_class *uclass,
+                                     enum unit_move_type move)
 {
-  /* FIXME: this just returns the first building. it should return the best
-   * building instead. */
+  int greatest_value = 0;
+  struct impr_type *best_building = NULL;
+
+  /* There's no point in defining both of these as uclass is more restrictive
+   * than move_type */
+  assert(uclass == NULL || move == MOVETYPE_LAST);
+
   effect_list_iterate(get_effects(effect_type), peffect) {
-    requirement_list_iterate(peffect->reqs, preq) {
-      if (VUT_IMPROVEMENT == preq->source.kind) {
-       struct impr_type *building = preq->source.value.building;
+    if (peffect->value > greatest_value) {
+      struct impr_type *building = NULL;
+      bool wrong_unit = FALSE;
 
-       if (can_player_build_improvement_now(pplayer, building)
-           && !improvement_obsolete(pplayer, building)
-           && is_improvement(building)) {
-         return improvement_number(building);
-       }
+      requirement_list_iterate(peffect->reqs, preq) {
+        if (VUT_IMPROVEMENT == preq->source.kind) {
+          building = preq->source.value.building;
+
+          if (!can_city_build_improvement_now(pcity, building)
+              || !is_improvement(building)) {          
+            building = NULL;
+            break;
+          }
+        }
+        if (VUT_UCLASS == preq->source.kind) {
+          if ((uclass != NULL && preq->source.value.uclass != uclass)
+              || (move != MOVETYPE_LAST
+                  && uclass_move_type(preq->source.value.uclass) != move)) {
+            /* Effect requires other kind of unit than what we are interested 
about */
+            wrong_unit = TRUE;
+            break;
+          }
+        }
+      } requirement_list_iterate_end;
+      if (!wrong_unit && building != NULL) {
+        best_building = building;
       }
-    } requirement_list_iterate_end;
+    }
   } effect_list_iterate_end;
+
+  if (best_building) {
+    return improvement_number(best_building);
+  }
   return B_LAST;
 }
 
diff -Nurd -X.diff_ignore freeciv/common/effects.h freeciv/common/effects.h
--- freeciv/common/effects.h    2007-09-14 20:06:51.000000000 +0300
+++ freeciv/common/effects.h    2008-07-21 23:53:25.000000000 +0300
@@ -223,8 +223,10 @@
                                   enum effect_type effect_type,
                                    const enum req_problem_type prob_type);
 
-Impr_type_id ai_find_source_building(struct player *pplayer,
-                                    enum effect_type effect_type);
+Impr_type_id ai_find_source_building(struct city *pcity,
+                                    enum effect_type effect_type,
+                                     struct unit_class *uclass,
+                                     enum unit_move_type move);
 
 typedef bool (*iec_cb)(const struct effect*);
 bool iterate_effect_cache(iec_cb cb);
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to