Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2005:
[Freeciv-Dev] (PR#11777) Cleanup of AI tech code
Home

[Freeciv-Dev] (PR#11777) Cleanup of AI tech code

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#11777) Cleanup of AI tech code
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Mon, 3 Jan 2005 09:23:48 -0800
Reply-to: bugs@xxxxxxxxxxx

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

I was just looking to fix a bug, and got a bit carried away...

This patch:
 - Removes some essentially dead and useless, and probably buggy (with
team research) AI tech code.
 - Improves logging of AI tech want. Renamed PLAYER_LOG to DIPLO_LOG for
consistency. New /debug command "/debug tech". Renamed "/debug player" to
"/debug diplomacy".
 - Fixes diplomacy buglet that would use negative tech want to calculate
want for tech in exchanges (if present).
 - Fixes possible crash in aisettler.c if ruleset has no ferries and in
aidiplomat.c if ruleset has no diplomats.
 - Fixes increase of tech want when considering role units. Previously we
bumped tech want for every role unit in the unit list when we don't find
any to produce, now we just do it for cheapest to research of the next
ones up the list from the one we can (or cannot) produce. Halve the want
if we can produce any role unit of this kind. This helps reduce the
explosive want for Explosives, for default ruleset.
 - Fixes possible issue where tech want would be _reduced_ if there is a
govt that is second best but less good than the one we already have. (Yes,
this is bad, because the tech might be good for other reasons.)
 - Ensure that the minimum tech want bump is 100, so that early game tech
want (few cities) is forward-looking. Remove govt_hint system in favour of
a built-in bump that is more intelligent. This may be derailed by
excessive attack want in some cases, so definitely only cvs head material,
but is arguably more correct and more flexible.
 - Since tech want is never cleared (just keeps accumulating) we cannot
use this in diplomacy code as is, so I made it divide the tech want by the
number of game turns. This fix should be back-ported to 2.0. (The constant
accumulation means that rapid flip-flops do not occur, which is good, as
changing tech has a penalty. Perhaps we should do the same for buildings?)
 - AI is no longer used to suggest new tech goals for human players. I saw
no reason to keep this, and it was rather ugly and rather prone to failure
to find anything in any case.

Unsolved issues (not to be fixed in this patch):
 - The attack and defense code bump want for _every_ useful unit, even
units that are strictly inferior and are and will never actually be used.
 - Several parts of the code do not bump tech want (hunter, ferry, air,
explorer and diplomacy) and some do it without proper want (settler and
diplomats).
 - Govt hints and nation ruleset hints are no longer used, with this
patch, and should be removed.

Questions:
 - Why does Republic have Code of Laws as one prereq? It has Literacy as
its other prereq, and Literacy requires Code of Laws...
 - The algorithm for bumping defense units' tech want is really weird.
See comments in patch. Why is it written like this?

Finally: The temptation to rewrite process_defender_want() completely was
really big... what a mess :(

  - Per

Index: ai/advdiplomacy.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advdiplomacy.c,v
retrieving revision 1.53
diff -u -r1.53 advdiplomacy.c
--- ai/advdiplomacy.c   19 Dec 2004 19:44:39 -0000      1.53
+++ ai/advdiplomacy.c   3 Jan 2005 17:06:47 -0000
@@ -124,14 +124,14 @@
     return 0;
   }
   bulbs = total_bulbs_required_for_goal(pplayer, tech) * 3;
-  tech_want = pplayer->ai.tech_want[tech] / 3;
-  worth = bulbs + tech_want;
+  tech_want = pplayer->ai.tech_want[tech] / MAX(game.turn, 1);
+  worth = bulbs + MAX(tech_want, 0);
   if (get_invention(pplayer, tech) == TECH_REACHABLE) {
     worth /= 2;
   }
-  PLAYER_LOG(LOG_DEBUG, pplayer, ai, "eval tech %s to %d (bulbs=%d, "
-             "tech_want=%d)", get_tech_name(pplayer, tech), worth, bulbs, 
-             tech_want);
+  DIPLO_LOG(LOG_DEBUG, pplayer, ai, "eval tech %s to %d (bulbs=%d, "
+            "tech_want=%d)", get_tech_name(pplayer, tech), worth, bulbs, 
+            tech_want);
   return worth;
 }
 
@@ -431,7 +431,7 @@
     } else {
       worth = city_gold_worth(offer);
     }
-    PLAYER_LOG(LOG_DEBUG, pplayer, ai, "worth of %s is %d", offer->name, 
worth);
+    DIPLO_LOG(LOG_DEBUG, pplayer, ai, "worth of %s is %d", offer->name, worth);
     break;
   }
 
@@ -590,7 +590,7 @@
 
     i = MIN(i, ai->diplomacy.love_incr * 150) * 10;
     pplayer->ai.love[aplayer->player_no] += i;
-    PLAYER_LOG(LOG_DIPL2, pplayer, ai, "%s's gift to %s increased love by %d",
+    DIPLO_LOG(LOG_DIPL2, pplayer, ai, "%s's gift to %s increased love by %d",
             aplayer->name, pplayer->name, i);
   }
 }
@@ -742,8 +742,8 @@
         && !adip->at_war_with_ally
         && adip->ally_patience >= 0) {
       pplayer->ai.love[aplayer->player_no] += ai->diplomacy.love_incr;
-      PLAYER_LOG(LOG_DEBUG, pplayer, ai, "Increased love for %s (now %d)",
-                 aplayer->name, pplayer->ai.love[aplayer->player_no]);
+      DIPLO_LOG(LOG_DEBUG, pplayer, ai, "Increased love for %s (now %d)",
+                aplayer->name, pplayer->ai.love[aplayer->player_no]);
     } else if (pplayer->diplstates[aplayer->player_no].type == DS_WAR) {
       pplayer->ai.love[aplayer->player_no] -= ai->diplomacy.love_incr;
       if (ai->diplomacy.target != aplayer && 
@@ -751,14 +751,14 @@
         /* Give him a better chance for a cease fire */
         pplayer->ai.love[aplayer->player_no] += (MAX_AI_LOVE) * 3 / 100;
       }
-      PLAYER_LOG(LOG_DEBUG, pplayer, ai, "Reduced love for %s (now %d) ",
-                 aplayer->name, pplayer->ai.love[aplayer->player_no]);
+      DIPLO_LOG(LOG_DEBUG, pplayer, ai, "Reduced love for %s (now %d) ",
+                aplayer->name, pplayer->ai.love[aplayer->player_no]);
     } else if (pplayer->diplstates[a].has_reason_to_cancel != 0) {
       /* Provoked in time of peace */
       if (pplayer->ai.love[aplayer->player_no] > 0) {
-        PLAYER_LOG(LOG_DEBUG, pplayer, ai, "Provoked by %s! Love halved "
-                   "(was %d)", aplayer->name, 
-                   pplayer->ai.love[aplayer->player_no]);
+        DIPLO_LOG(LOG_DEBUG, pplayer, ai, "Provoked by %s! Love halved "
+                  "(was %d)", aplayer->name,
+                  pplayer->ai.love[aplayer->player_no]);
         pplayer->ai.love[aplayer->player_no] /= 2;
       }
       pplayer->ai.love[aplayer->player_no] -= ai->diplomacy.love_incr;
@@ -788,8 +788,8 @@
 
   /* Stop war against a dead player */
   if (ai->diplomacy.target && !ai->diplomacy.target->is_alive) {
-    PLAYER_LOG(LOG_DIPL2, pplayer, ai, "Target player %s is dead! Victory!",
-               ai->diplomacy.target->name);
+    DIPLO_LOG(LOG_DIPL2, pplayer, ai, "Target player %s is dead! Victory!",
+              ai->diplomacy.target->name);
     ai->diplomacy.timer = 0;
     ai->diplomacy.countdown = 0;
     ai->diplomacy.target = NULL;
@@ -855,8 +855,8 @@
       war_desire[aplayer->player_no] /= 2;
     }
     
-    PLAYER_LOG(LOG_DEBUG, pplayer, ai, "Against %s we have war desire "
-            "%d ", aplayer->name, war_desire[aplayer->player_no]);
+    DIPLO_LOG(LOG_DEBUG, pplayer, ai, "Against %s we have war desire "
+              "%d ", aplayer->name, war_desire[aplayer->player_no]);
 
     /* Find best target */
     if (war_desire[aplayer->player_no] > best_desire) {
@@ -866,14 +866,14 @@
   } players_iterate_end;
 
   if (!target) {
-    PLAYER_LOG(LOG_DEBUG, pplayer, ai, "Found no target.");
+    DIPLO_LOG(LOG_DEBUG, pplayer, ai, "Found no target.");
     ai->diplomacy.target = NULL;
     return;
   }
 
   /* Switch to target */
   if (target != ai->diplomacy.target) {
-    PLAYER_LOG(LOG_DIPL, pplayer, ai, "Setting target to %s", target->name);
+    DIPLO_LOG(LOG_DIPL, pplayer, ai, "Setting target to %s", target->name);
     ai->diplomacy.target = target;
     if (ai->diplomacy.strategy == WIN_CAPITAL) {
       ai->diplomacy.countdown = 1; /* Quickly!! */
@@ -977,7 +977,7 @@
     if (ai->diplomacy.acceptable_reputation > aplayer->reputation
         && pplayer->ai.love[aplayer->player_no] < 0
         && pplayer->diplstates[aplayer->player_no].has_reason_to_cancel >= 2) {
-      PLAYER_LOG(LOG_DIPL2, pplayer, ai, "Declaring war on %s in revenge",
+      DIPLO_LOG(LOG_DIPL2, pplayer, ai, "Declaring war on %s in revenge",
                  target->name);
       notify(target, _("*%s (AI)* I will NOT accept such behaviour! This "
              "means WAR!"), pplayer->name);
@@ -1036,7 +1036,7 @@
   if (target && !pplayers_at_war(pplayer, target)
       && ai->diplomacy.countdown <= 0) {
     if (pplayers_allied(pplayer, target)) {
-      PLAYER_LOG(LOG_DEBUG, pplayer, ai, "Went to war against %s, who is "
+      DIPLO_LOG(LOG_DEBUG, pplayer, ai, "Went to war against %s, who is "
                  "an ally!", target->name); /* Oh, my. */
     }
     if (pplayer->diplstates[target->player_no].has_reason_to_cancel > 0) {
@@ -1148,11 +1148,11 @@
         break;
       }
       if (target && pplayer->ai.control) {
-        PLAYER_LOG(LOG_DIPL2, pplayer, ai, "Ally %s not at war with enemy %s "
-                "(patience %d, %s %s)", aplayer->name, 
-                target->name, adip->ally_patience, adip->at_war_with_ally
-                ? "war_with_ally" : "", adip->is_allied_with_ally ? 
-                "allied_with_ally" : "");
+        DIPLO_LOG(LOG_DIPL2, pplayer, ai, "Ally %s not at war with enemy %s "
+                  "(patience %d, %s %s)", aplayer->name, 
+                  target->name, adip->ally_patience, adip->at_war_with_ally
+                  ? "war_with_ally" : "", adip->is_allied_with_ally ? 
+                  "allied_with_ally" : "");
 
       }
       switch (adip->ally_patience--) {
@@ -1171,8 +1171,8 @@
                  "alliance, and yet you remain at peace with our mortal "
                  "enemy, %s! This is unacceptable, our alliance is no "
                  "more!"), pplayer->name, target->name);
-          PLAYER_LOG(LOG_DIPL2, pplayer, ai, "breaking useless alliance with "
-                     "%s", aplayer->name);
+          DIPLO_LOG(LOG_DIPL2, pplayer, ai, "breaking useless alliance with "
+                    "%s", aplayer->name);
          /* to peace */
          handle_diplomacy_cancel_pact(pplayer, aplayer->player_no,
                                       CLAUSE_ALLIANCE);
Index: ai/advdomestic.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advdomestic.c,v
retrieving revision 1.124
diff -u -r1.124 advdomestic.c
--- ai/advdomestic.c    10 Dec 2004 21:19:20 -0000      1.124
+++ ai/advdomestic.c    3 Jan 2005 17:06:48 -0000
@@ -129,7 +129,12 @@
         int tech_req = get_unit_type(unit_type)->tech_requirement;
 
         /* XXX (FIXME): Had to add the scientist guess here too. -- Syela */
+        /* What Syela probably means is that this addition to tech want
+         * is in addition to the tech want implitictly added by 
+         * ai_choose_rule_unit() above. - Per */
         pplayer->ai.tech_want[tech_req] += want;
+        TECH_LOG(LOG_DEBUG, pplayer, tech_req, "+ %d for %s to build wonders",
+                 want, unit_name(unit_type));
       }
     }
   } city_list_iterate_end;
Index: ai/advmilitary.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advmilitary.c,v
retrieving revision 1.182
diff -u -r1.182 advmilitary.c
--- ai/advmilitary.c    19 Dec 2004 19:44:39 -0000      1.182
+++ ai/advmilitary.c    3 Jan 2005 17:06:49 -0000
@@ -663,7 +663,6 @@
                                   unsigned int danger, struct ai_choice 
*choice)
 {
   bool walls = city_got_citywalls(pcity);
-  bool shore = is_ocean_near_tile(pcity->tile);
   /* Technologies we would like to have. */
   int tech_desire[U_LAST];
   /* Our favourite unit. */
@@ -674,13 +673,16 @@
   
   simple_ai_unit_type_iterate (unit_type) {
       int move_type = unit_types[unit_type].move_type;
-    
-      /* How many technologies away it is? */
-      int tech_dist = num_unknown_techs_for_goal(pplayer,
-                        unit_types[unit_type].tech_requirement);
+      Tech_Type_id tech_req = unit_types[unit_type].tech_requirement;
+      int desire; /* How much we want the unit? */
+
+      /* Only consider proper defenders - otherwise waste CPU and
+       * bump tech want needlessly. */
+      if (!unit_has_role(unit_type, L_DEFEND_GOOD)) {
+        continue;
+      }
 
-      /* How much we want the unit? */
-      int desire = ai_unit_defence_desirability(unit_type);
+      desire = ai_unit_defence_desirability(unit_type);
 
       if (unit_type_flag(unit_type, F_FIELDUNIT)) {
         /* Causes unhappiness even when in defense, so not a good
@@ -707,9 +709,9 @@
           best = desire;
           best_unit_type = unit_type;
         }
-        
-      } else if (tech_dist > 0 && (shore || move_type == LAND_MOVING)
-                 && unit_types[unit_type].tech_requirement != A_LAST) {
+      } else if (tech_req != A_LAST
+                 && get_invention(pplayer, tech_req) == TECH_REACHABLE
+                 && can_eventually_build_unit(pcity, unit_type)) {
         /* We first need to develop the tech required by the unit... */
 
         /* Cost (shield equivalent) of gaining these techs. */
@@ -727,6 +729,7 @@
         }
 
         /* Yes, there's some similarity with kill_desire(). */
+        /* TODO: Explain what shield cost has to do with tech want. */
         tech_desire[unit_type] = (desire * danger /
                                  (unit_build_shield_cost(unit_type)
                                   + tech_cost));
@@ -744,14 +747,14 @@
   simple_ai_unit_type_iterate (unit_type) {
     if (tech_desire[unit_type] > 0) {
       Tech_Type_id tech_req = unit_types[unit_type].tech_requirement;
+      /* TODO: Document or fix the algorithm below. I have no idea why
+       * it is written this way, and the results seem strange to me. - Per */
       int desire = tech_desire[unit_type]
                    * unit_build_shield_cost(best_unit_type) / best;
       
       pplayer->ai.tech_want[tech_req] += desire;
-      
-      freelog(LOG_DEBUG, "%s wants %s for defense with desire %d <%d>",
-              pcity->name, get_tech_name(pplayer, tech_req), desire,
-              tech_desire[unit_type]);
+      TECH_LOG(LOG_DEBUG, pplayer, tech_req, "+ %d for %s to defend %s",
+               desire, unit_name(unit_type), pcity->name);
     }
   } simple_ai_unit_type_iterate_end;
   
@@ -921,12 +924,9 @@
         if (tech_dist > 0) {
           /* This is a future unit, tell the scientist how much we need it */
           pplayer->ai.tech_want[tech_req] += want;
-          
-          CITY_LOG(LOG_DEBUG, pcity, "wants %s to build %s to punish 
%s@(%d,%d)"
-                   " with desire %d", get_tech_name(pplayer, tech_req), 
-                   unit_name(unit_type), (acity ? acity->name : "enemy"),
-                   TILE_XY(ptile), want);
-
+          TECH_LOG(LOG_DEBUG, pplayer, tech_req, "+ %d for %s vs %s(%d,%d)",
+                   want, unit_name(unit_type), (acity ? acity->name : 
+                   unit_name(victim_unit_type)), TILE_XY(ptile));
         } else if (want > best_choice->want) {
           if (can_build_unit(pcity, unit_type)) {
             /* This is a real unit and we really want it */
Index: ai/aidiplomat.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidiplomat.c,v
retrieving revision 1.43
diff -u -r1.43 aidiplomat.c
--- ai/aidiplomat.c     19 Dec 2004 19:44:39 -0000      1.43
+++ ai/aidiplomat.c     3 Jan 2005 17:06:49 -0000
@@ -54,6 +54,10 @@
 #define LOG_DIPLOMAT LOG_DEBUG
 #define LOG_DIPLOMAT_BUILD LOG_DEBUG
 
+/* 3000 is a just a large number, but not hillariously large as the
+ * previously used one. This is important for diplomacy. - Per */
+#define DIPLO_DEFENSE_WANT 3000
+
 static void find_city_to_diplomat(struct player *pplayer, struct unit *punit,
                                   struct city **ctarget, int *move_dist,
                                   struct pf_map *map);
@@ -119,9 +123,13 @@
       freelog(LOG_DIPLOMAT_BUILD,
               "A defensive diplomat is wanted badly in city %s.", pcity->name);
       u = get_role_unit(F_DIPLOMAT, 0);
-      /* 3000 is a just a large number, but not hillariously large as the
-         previously used one. This is important for diplomacy later - Per */
-      pplayer->ai.tech_want[get_unit_type(u)->tech_requirement] += 3000;
+      if (u != U_LAST) {
+        Tech_Type_id tech_req = get_unit_type(u)->tech_requirement;
+
+        pplayer->ai.tech_want[tech_req] += DIPLO_DEFENSE_WANT;
+        TECH_LOG(LOG_DEBUG, pplayer, tech_req, "+ %d for %s in diplo defense",
+                 DIPLO_DEFENSE_WANT, unit_name(u));
+      }
     }
   }
 }
Index: ai/aihand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aihand.c,v
retrieving revision 1.97
diff -u -r1.97 aihand.c
--- ai/aihand.c 15 Dec 2004 00:15:12 -0000      1.97
+++ ai/aihand.c 3 Jan 2005 17:06:49 -0000
@@ -351,11 +351,19 @@
   /* Crank up tech want */
   if (get_invention(pplayer, ai->goal.govt.req) == TECH_KNOWN) {
     return; /* already got it! */
+  } else if (ai->goal.govt.val > 0) {
+    /* We have few cities in the beginning, compensate for this to ensure
+     * that we are sufficiently forward-looking. */
+    int want = MAX(ai->goal.govt.val, 100);
+
+    if (pplayer->government == game.default_government) {
+      want += 25 * game.turn;
+    }
+    pplayer->ai.tech_want[ai->goal.govt.req] += want;
+    TECH_LOG(LOG_DEBUG, pplayer, ai->goal.govt.req, "+ %d for %s in "
+             "ai_manage_government", want, 
+             get_government_name(ai->goal.govt.idx));
   }
-  pplayer->ai.tech_want[ai->goal.govt.req] += ai->goal.govt.val;
-  freelog(LOG_DEBUG, "%s wants %s with want %d", pplayer->name,
-          get_tech_name(pplayer, ai->goal.govt.req), 
-          pplayer->ai.tech_want[ai->goal.govt.req]);
 }
 
 /**************************************************************************
Index: ai/ailog.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/ailog.c,v
retrieving revision 1.17
diff -u -r1.17 ailog.c
--- ai/ailog.c  29 Sep 2004 02:24:18 -0000      1.17
+++ ai/ailog.c  3 Jan 2005 17:06:49 -0000
@@ -32,20 +32,57 @@
 /* General AI logging functions */
 
 /**************************************************************************
+  Log player tech messages.
+**************************************************************************/
+void TECH_LOG(int level, struct player *pplayer, Tech_Type_id id,
+              const char *msg, ...)
+{
+  char buffer[500];
+  char buffer2[500];
+  va_list ap;
+  int minlevel = MIN(LOGLEVEL_TECH, level);
+
+  if (!tech_exists(id) || id == A_NONE) {
+    return;
+  }
+
+  if (BV_ISSET(pplayer->debug, PLAYER_DEBUG_TECH)) {
+    minlevel = LOG_NORMAL;
+  } else if (minlevel > fc_log_level) {
+    return;
+  }
+
+  my_snprintf(buffer, sizeof(buffer), "%s::%s (want %d, dist %d) ", 
+              pplayer->name, get_tech_name(pplayer, id), 
+              pplayer->ai.tech_want[id], 
+              num_unknown_techs_for_goal(pplayer, id));
+
+  va_start(ap, msg);
+  my_vsnprintf(buffer2, sizeof(buffer2), msg, ap);
+  va_end(ap);
+
+  cat_snprintf(buffer, sizeof(buffer), buffer2);
+  if (BV_ISSET(pplayer->debug, PLAYER_DEBUG_TECH)) {
+    notify_conn(&game.est_connections, buffer);
+  }
+  freelog(minlevel, buffer);
+}
+
+/**************************************************************************
   Log player messages, they will appear like this
     2: perrin [ti12 co6 lo5 e]  Increased love for a (now 9)
   where ti is timer, co countdown and lo love for target, who is e.
 **************************************************************************/
-void PLAYER_LOG(int level, struct player *pplayer, struct ai_data *ai, 
-                const char *msg, ...)
+void DIPLO_LOG(int level, struct player *pplayer, struct ai_data *ai, 
+               const char *msg, ...)
 {
   char targetbuffer[250];
   char buffer[500];
   char buffer2[500];
   va_list ap;
-  int minlevel = MIN(LOGLEVEL_CITY, level);
+  int minlevel = MIN(LOGLEVEL_PLAYER, level);
 
-  if (pplayer->debug) {
+  if (BV_ISSET(pplayer->debug, PLAYER_DEBUG_DIPLOMACY)) {
     minlevel = LOG_NORMAL;
   } else if (minlevel > fc_log_level) {
     return;
@@ -70,7 +107,7 @@
   va_end(ap);
 
   cat_snprintf(buffer, sizeof(buffer), buffer2);
-  if (pplayer->debug) {
+  if (BV_ISSET(pplayer->debug, PLAYER_DEBUG_DIPLOMACY)) {
     notify_conn(&game.est_connections, buffer);
   }
   freelog(minlevel, buffer);
Index: ai/ailog.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/ailog.h,v
retrieving revision 1.9
diff -u -r1.9 ailog.h
--- ai/ailog.h  19 Dec 2004 19:45:56 -0000      1.9
+++ ai/ailog.h  3 Jan 2005 17:06:49 -0000
@@ -29,9 +29,14 @@
 #define LOGLEVEL_CITY LOG_DEBUG
 #define LOGLEVEL_BUILD LOG_DEBUG
 #define LOGLEVEL_HUNT LOG_DEBUG
+#define LOGLEVEL_PLAYER LOG_DEBUG
+#define LOGLEVEL_TECH LOG_DEBUG
 
-void PLAYER_LOG(int level, struct player *pplayer, struct ai_data *ai,
-                const char *msg, ...)
+void TECH_LOG(int level, struct player *pplayer, Tech_Type_id id,
+              const char *msg, ...)
+     fc__attribute((format (printf, 4, 5)));
+void DIPLO_LOG(int level, struct player *pplayer, struct ai_data *ai,
+               const char *msg, ...)
      fc__attribute((format (printf, 4, 5)));
 void CITY_LOG(int level, struct city *pcity, const char *msg, ...)
      fc__attribute((format (printf, 3, 4)));
Index: ai/aisettler.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aisettler.c,v
retrieving revision 1.15
diff -u -r1.15 aisettler.c
--- ai/aisettler.c      1 Jan 2005 22:47:13 -0000       1.15
+++ ai/aisettler.c      3 Jan 2005 17:06:50 -0000
@@ -590,9 +590,14 @@
       if (boattype == U_LAST) {
         /* Sea travel not possible yet. Bump tech want for ferries. */
         Unit_Type_id boattype = get_role_unit(L_FERRYBOAT, 0);
-        Tech_Type_id tech_req = unit_types[boattype].tech_requirement;
 
-        pplayer->ai.tech_want[tech_req] += FERRY_TECH_WANT;
+        if (boattype != U_LAST) {
+          Tech_Type_id tech_req = unit_types[boattype].tech_requirement;
+
+          pplayer->ai.tech_want[tech_req] += FERRY_TECH_WANT;
+          TECH_LOG(LOG_DEBUG, pplayer, tech_req, "+ %d for %s to ferry 
settler",
+                   FERRY_TECH_WANT, unit_name(boattype));
+        }
         return;
       }
       ferry = create_unit_virtual(pplayer, NULL, boattype, 0);
Index: ai/aitech.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitech.c,v
retrieving revision 1.48
diff -u -r1.48 aitech.c
--- ai/aitech.c 19 Dec 2004 16:47:08 -0000      1.48
+++ ai/aitech.c 3 Jan 2005 17:06:50 -0000
@@ -26,6 +26,7 @@
 #include "plrhand.h"
 
 #include "advmilitary.h"
+#include "ailog.h"
 #include "aitools.h"
 
 #include "aitech.h"
@@ -38,67 +39,6 @@
 };
 
 /**************************************************************************
-  Returns tech corresponding to players wonder goal from nations[],
-  if it makes sense, and wonder is not already built and not obsolete.
-  Otherwise returns A_UNSET.
-**************************************************************************/
-static Tech_Type_id get_wonder_tech(struct player *plr)
-{
-  Impr_Type_id building = get_nation_by_plr(plr)->goals.wonder;
-  
-  if (improvement_exists(building)
-      && is_great_wonder(building)
-      && !great_wonder_was_built(building)
-      && !improvement_obsolete(plr, building)) {
-    Tech_Type_id tech = improvement_types[building].tech_req;
-
-    if (tech_is_available(plr, tech) 
-        && get_invention(plr, tech) != TECH_KNOWN) {
-      return tech;
-    }
-  }
-  return A_UNSET;
-}
-
-/**************************************************************************
-  Puts into choice the closest (in terms of unknown techs needed) of
-    - national tech goals,
-    - requirements for the national wonder goal
-**************************************************************************/
-static Tech_Type_id ai_next_tech_goal_default(struct player *pplayer)
-{
-  struct nation_type *prace = get_nation_by_plr(pplayer);
-  int bestdist = A_LAST + 1;
-  int dist, i;
-  Tech_Type_id goal = A_UNSET;
-  Tech_Type_id tech;
-
-  /* Find the closest of the national tech goals */
-  for (i = 0 ; i < MAX_NUM_TECH_GOALS; i++) {
-    Tech_Type_id j = prace->goals.tech[i];
-    if (!tech_is_available(pplayer, j) 
-        || get_invention(pplayer, j) == TECH_KNOWN) {
-      continue;
-    }
-    dist = num_unknown_techs_for_goal(pplayer, j);
-    if (dist < bestdist) { 
-      bestdist = dist;
-      goal = j;
-      break; /* remove this to restore old functionality -- Syela */
-    }
-  } 
-
-  /* Find the requirement for the national wonder */
-  tech = get_wonder_tech(pplayer);
-  if (tech != A_UNSET 
-      && num_unknown_techs_for_goal(pplayer, tech) < bestdist) {
-    goal = tech;
-  }
-
-  return goal;
-}
-
-/**************************************************************************
   Massage the numbers provided to us by ai.tech_want into unrecognizable 
   pulp.
 
@@ -185,9 +125,13 @@
       }
     }
   } tech_type_iterate_end;
-  freelog(LOG_DEBUG, "%s wants %s with desire %d (%d).", 
-         pplayer->name, get_tech_name(pplayer, newtech), values[newtech], 
-         pplayer->ai.tech_want[newtech]);
+#ifdef REALLY_DEBUG_THIS
+  tech_type_iterate(id) {
+    if (values[id] > 0 && get_invention(pplayer, id) == TECH_REACHABLE) {
+      TECH_LOG(LOG_DEBUG, pplayer, id, "turn end want: %d", values[id]);
+    }
+  } tech_type_iterate_end;
+#endif
   if (choice) {
     choice->choice = newtech;
     choice->want = values[newtech] / num_cities_nonzero;
@@ -210,64 +154,6 @@
 }
 
 /**************************************************************************
-  Choose our next tech goal.  Called by the server when a new tech is 
-  discovered to determine new goal and, from it, the new tech to be 
-  researched, which is quite stupid since ai_manage_tech sets a goal in 
-  ai.tech_goal and we should either respect it or not bother doing it.
-
-  TODO: Kill this function.
-**************************************************************************/
-void ai_next_tech_goal(struct player *pplayer)
-{
-  struct ai_tech_choice goal_choice = {0, 0, 0};
-
-  ai_select_tech(pplayer, NULL, &goal_choice);
-
-  if (goal_choice.want == 0) {
-    goal_choice.choice = ai_next_tech_goal_default(pplayer);
-  }
-  if (goal_choice.choice != A_UNSET) {
-    pplayer->ai.tech_goal = goal_choice.choice;
-    freelog(LOG_DEBUG, "next_tech_goal for %s is set to %s",
-           pplayer->name, get_tech_name(pplayer, goal_choice.choice));
-  }
-}
-
-/**************************************************************************
-  Use AI tech hints provided in governments.ruleset to up corresponding 
-  tech wants.
-
-  TODO: The hints structure is too complicated, simplify.
-**************************************************************************/
-static void ai_use_gov_tech_hint(struct player *pplayer)
-{
-  int i;
-
-  for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
-    struct ai_gov_tech_hint *hint = &ai_gov_tech_hints[i];
-    
-    if (hint->tech == A_LAST) {
-      break;
-    }
-    
-    if (get_invention(pplayer, hint->tech) != TECH_KNOWN) {
-      int steps = num_unknown_techs_for_goal(pplayer, hint->tech);
-
-      pplayer->ai.tech_want[hint->tech] += 
-       city_list_size(&pplayer->cities)
-       * (hint->turns_factor * steps + hint->const_factor);
-      if (hint->get_first) {
-       break;
-      }
-    } else {
-      if (hint->done) {
-       break;
-      }
-    }
-  }
-}
-
-/**************************************************************************
   Key AI research function. Disable if we are in a team with human team
   mates in a research pool.
 **************************************************************************/
@@ -286,18 +172,16 @@
     }
   } players_iterate_end;
 
-  ai_use_gov_tech_hint(pplayer);
-
   ai_select_tech(pplayer, &choice, &goal);
   if (choice.choice != pplayer->research.researching) {
     /* changing */
     if ((choice.want - choice.current_want) > penalty &&
        penalty + pplayer->research.bulbs_researched <=
        total_bulbs_required(pplayer)) {
-      freelog(LOG_DEBUG, "%s switching from %s to %s with penalty of %d.",
-             pplayer->name,
-             get_tech_name(pplayer, pplayer->research.researching),
-             get_tech_name(pplayer, choice.choice), penalty);
+      TECH_LOG(LOG_DEBUG, pplayer, choice.choice, "new research, was %s, "
+               "penalty was %d", 
+               get_tech_name(pplayer, pplayer->research.researching),
+               penalty);
       choose_tech(pplayer, choice.choice);
     }
   }
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.342
diff -u -r1.342 aiunit.c
--- ai/aiunit.c 20 Dec 2004 23:50:58 -0000      1.342
+++ ai/aiunit.c 3 Jan 2005 17:06:51 -0000
@@ -2218,30 +2218,64 @@
 }
 
 /**************************************************************************
- Assign tech wants for techs to get better units with given role/flag.
- Returns the best we can build so far, or U_LAST if none.  (dwp)
+  Returns the best we can build so far, or U_LAST if none. "Best" here
+  means last in the unit list as defined in the ruleset.  Assign tech 
+  wants for techs to get better units with given role, but only for the
+  cheapest to research "next" unit up the "chain".
 **************************************************************************/
 Unit_Type_id ai_wants_role_unit(struct player *pplayer, struct city *pcity,
                                 int role, int want)
 {
-  Unit_Type_id iunit;
-  Tech_Type_id itech;
   int i, n;
+  Tech_Type_id best_tech = A_NONE;
+  int best_cost = FC_INFINITY;
+  Unit_Type_id best_unit = U_LAST;
+  Unit_Type_id build_unit = U_LAST;
 
   n = num_role_units(role);
-  for (i=n-1; i>=0; i--) {
-    iunit = get_role_unit(role, i);
+  for (i = n - 1; i >= 0; i--) {
+    Unit_Type_id iunit = get_role_unit(role, i);
+    Tech_Type_id itech = get_unit_type(iunit)->tech_requirement;
+    Impr_Type_id iimpr = get_unit_type(iunit)->impr_requirement;
+
     if (can_build_unit(pcity, iunit)) {
-      return iunit;
-    } else {
-      /* careful; might be unable to build for non-tech reason... */
-      itech = get_unit_type(iunit)->tech_requirement;
-      if (get_invention(pplayer, itech) != TECH_KNOWN) {
-       pplayer->ai.tech_want[itech] += want;
+      build_unit = iunit;
+      break;
+    } else if (get_invention(pplayer, itech) == TECH_REACHABLE) {
+      /* See if we want to invent this. */
+      int cost = total_bulbs_required_for_goal(pplayer, itech);
+
+      if (cost < best_cost) {
+        best_tech = itech;
+        best_cost = cost;
+        best_unit = iunit;
+      }
+    } else if (iimpr != B_LAST) {
+      itech = get_improvement_type(iimpr)->tech_req;
+
+      if (get_invention(pplayer, itech) == TECH_REACHABLE) {
+        /* See if we want to invent this. */
+        int cost = total_bulbs_required_for_goal(pplayer, itech);
+
+        if (cost < best_cost) {
+          best_tech = itech;
+          best_cost = cost;
+          best_unit = iunit;
+        }
       }
     }
   }
-  return U_LAST;
+  if (best_tech != A_NONE) {
+    /* Crank up chosen tech want */
+    if (build_unit != U_LAST) {
+      /* We already have a role unit of this kind */
+      want /= 2;
+    }
+    pplayer->ai.tech_want[best_tech] += want;
+    TECH_LOG(LOG_DEBUG, pplayer, best_tech, "+ %d for %s by role",
+             want, unit_name(best_unit));
+  }
+  return build_unit;
 }
 
 /**************************************************************************
Index: common/player.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.c,v
retrieving revision 1.165
diff -u -r1.165 player.c
--- common/player.c     19 Dec 2004 16:47:09 -0000      1.165
+++ common/player.c     3 Jan 2005 17:06:52 -0000
@@ -140,7 +140,7 @@
 
   plr->attribute_block.data = NULL;
   plr->attribute_block.length = 0;
-  plr->debug = FALSE;
+  BV_CLR_ALL(plr->debug);
 }
 
 /***************************************************************
Index: common/player.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.h,v
retrieving revision 1.136
diff -u -r1.136 player.h
--- common/player.h     1 Jan 2005 21:48:10 -0000       1.136
+++ common/player.h     3 Jan 2005 17:06:52 -0000
@@ -175,6 +175,11 @@
   see doc/HACKING
 ***************************************************************************/
 
+enum player_debug_types {
+  PLAYER_DEBUG_DIPLOMACY, PLAYER_DEBUG_TECH, PLAYER_DEBUG_LAST
+};
+
+BV_DEFINE(bv_debug, PLAYER_DEBUG_LAST);
 struct player {
   int player_no;
   char name[MAX_LEN_NAME];
@@ -222,7 +227,7 @@
     int length;
     void *data;
   } attribute_block;
-  bool debug;
+  bv_debug debug;
 };
 
 void player_init(struct player *plr);
Index: data/trident/units.png
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident/units.png,v
retrieving revision 1.3
diff -u -r1.3 units.png
Binary files /tmp/cvs2y9mwF and units.png differ
Index: server/plrhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.c,v
retrieving revision 1.349
diff -u -r1.349 plrhand.c
--- server/plrhand.c    1 Jan 2005 21:48:10 -0000       1.349
+++ server/plrhand.c    3 Jan 2005 17:06:56 -0000
@@ -550,20 +550,8 @@
 {
   int sub_goal;
 
-  if (plr->ai.control) {
-    ai_next_tech_goal(plr);    /* tech-AI has been changed */
-  }
   sub_goal = get_next_tech(plr, plr->ai.tech_goal);
 
-  if (sub_goal == A_UNSET) {
-    if (plr->ai.control || plr->research.techs_researched == 1) {
-      ai_next_tech_goal(plr);
-      sub_goal = get_next_tech(plr, plr->ai.tech_goal);
-    } else {
-      plr->ai.tech_goal = A_UNSET;     /* clear goal when it is achieved */
-    }
-  }
-
   if (sub_goal != A_UNSET) {
     plr->research.researching = sub_goal;
     return TRUE;
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.376
diff -u -r1.376 stdinhand.c
--- server/stdinhand.c  1 Jan 2005 23:58:24 -0000       1.376
+++ server/stdinhand.c  3 Jan 2005 17:06:59 -0000
@@ -2186,9 +2186,9 @@
   char buf[MAX_LEN_CONSOLE_LINE];
   char *arg[3];
   int ntokens = 0, i;
-  const char *usage = _("Undefined arguments. Usage: debug <player "
+  const char *usage = _("Undefined arguments. Usage: debug <diplomacy "
                        "<player> | city <x> <y> | units <x> <y> | "
-                       "unit <id>>.");
+                       "unit <id> | tech <player>>.");
 
   if (server_state != RUN_GAME_STATE) {
     cmd_reply(CMD_DEBUG, caller, C_SYNTAX,
@@ -2204,7 +2204,7 @@
     ntokens = get_tokens(buf, arg, 3, TOKEN_DELIMITERS);
   }
 
-  if (strcmp(arg[0], "player") == 0) {
+  if (strcmp(arg[0], "diplomacy") == 0) {
     struct player *pplayer;
     enum m_pre_result match_result;
 
@@ -2217,13 +2217,37 @@
       cmd_reply_no_such_player(CMD_DEBUG, caller, arg[1], match_result);
       goto cleanup;
     }
-    if (pplayer->debug) {
-      pplayer->debug = FALSE;
-      cmd_reply(CMD_DEBUG, caller, C_OK, _("%s no longer debugged"), 
+    if (BV_ISSET(pplayer->debug, PLAYER_DEBUG_DIPLOMACY)) {
+      BV_CLR(pplayer->debug, PLAYER_DEBUG_DIPLOMACY);
+      cmd_reply(CMD_DEBUG, caller, C_OK, _("%s diplomacy no longer debugged"), 
                 pplayer->name);
     } else {
-      pplayer->debug = TRUE;
-      cmd_reply(CMD_DEBUG, caller, C_OK, _("%s debugged"), pplayer->name);
+      BV_SET(pplayer->debug, PLAYER_DEBUG_DIPLOMACY);
+      cmd_reply(CMD_DEBUG, caller, C_OK, _("%s diplomacy debugged"), 
+                pplayer->name);
+      /* TODO: print some info about the player here */
+    } 
+  } else if (strcmp(arg[0], "tech") == 0) {
+    struct player *pplayer;
+    enum m_pre_result match_result;
+
+    if (ntokens != 2) {
+      cmd_reply(CMD_DEBUG, caller, C_SYNTAX, usage);
+      goto cleanup;
+    }
+    pplayer = find_player_by_name_prefix(arg[1], &match_result);
+    if (pplayer == NULL) {
+      cmd_reply_no_such_player(CMD_DEBUG, caller, arg[1], match_result);
+      goto cleanup;
+    }
+    if (BV_ISSET(pplayer->debug, PLAYER_DEBUG_TECH)) {
+      BV_CLR(pplayer->debug, PLAYER_DEBUG_TECH);
+      cmd_reply(CMD_DEBUG, caller, C_OK, _("%s tech no longer debugged"), 
+                pplayer->name);
+    } else {
+      BV_SET(pplayer->debug, PLAYER_DEBUG_TECH);
+      cmd_reply(CMD_DEBUG, caller, C_OK, _("%s tech debugged"), 
+                pplayer->name);
       /* TODO: print some info about the player here */
     }
   } else if (strcmp(arg[0], "city") == 0) {

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#11777) Cleanup of AI tech code, Per I. Mathisen <=