Complete.Org: Mailing Lists: Archives: freeciv-dev: July 1999:
[Freeciv-Dev] PATCH: AI governments
Home

[Freeciv-Dev] PATCH: AI governments

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] PATCH: AI governments
From: rizos@xxxxxxxx
Date: Tue, 6 Jul 1999 15:49:45 -0500 (CDT)

Dear all,

Here goes the patch that allows the AI to switch between different
governments. 

As i wrote last month, the main criterion for a government change is 
the maximization of the quantity (3*trade_prod + 2*shield_surplus)/5. 
Apart from adding support for this, additional main changes were made to
the function evaluating the value of different buildings (advdomestic.c),
especially to distinguish between civic unhappiness and unhappiness
caused by military units (currently the AI doesn't know about this -
in fact it builds Colosseums even in cities of size 4 when there is
unhappiness due to aggressive units).

The patch has been heavily tested - the AI proved to adapt itself very
well to different forms of government - and is ready to be included to the 
distribution. At the moment though, for anyone who would like to compare, 
i left the code that allows comparison with the current AIs in place
(just create an AI with name old1, old2, old3, ... to old999 to get the 
current behaviour).

Experiences:
- I've played more than 30 games, mostly 4 new AIs against 4 old AIs.
  I have yet to see an old AI winning even though, in some cases, 
  winning AIs started from a handicapped position.
- The time needed for the patch is negligible: in games at an advanced
  stage, it was in the range of 0.1% of the total cost for a turn.
- It is quite educational to watch the AI winning while in democracy!
  However, not surprisingly, quite often winning AIs would go for
  Communism.

Enjoy,
--rizos

PS: diff against CVS of July 5th.
    Files changed:
        ai/aihand.c
        ai/advdomestic.c
        ai/aicity.c

=======================================================================

--- freeciv/ai/aihand.c Mon Jul  5 19:24:41 1999
+++ aihand.c    Tue Jul  6 02:49:26 1999
@@ -15,12 +15,12 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "player.h"
 #include "city.h"
 #include "game.h"
 #include "log.h"
 #include "map.h"
 #include "packets.h"
-#include "player.h"
 #include "shared.h"
 #include "unit.h"
 
@@ -36,6 +36,8 @@
 
 #include "aihand.h"
 
+#include "mem.h"
+
 /****************************************************************************
   A man builds a city
   With banks and cathedrals
@@ -98,6 +100,7 @@
 void ai_manage_government(struct player *pplayer);
 void ai_manage_diplomacy(struct player *pplayer);
 void ai_after_work(struct player *pplayer);
+int ai_evaluate_governments(struct player *pplayer);
 
 
 /**************************************************************************
@@ -444,35 +447,42 @@
 
 void ai_manage_government(struct player *pplayer)
 {
-  int government = get_race(pplayer)->goals.government;
-  government = G_REPUBLIC; /* need to be REPUBLIC+ to love */
-/* advantages of DEMOCRACY: partisans, no bribes, no corrup, +1 content if 
courthouse */
-/* disadvantages of DEMOCRACY: doubled unhappiness from attacking units, 
anarchy */
-/* realistically we should allow DEMOC in some circumstances but not yet -- 
Syela */
-  if (pplayer->government == government)
-    return;
-  if (can_change_to_government(pplayer, government)) {
-    ai_government_change(pplayer, government);
-    return;
-  }
-  switch (government) {
-  case G_COMMUNISM:
-    if (can_change_to_government(pplayer, G_MONARCHY)) 
-      ai_government_change(pplayer, G_MONARCHY);
-    break;
-  case G_DEMOCRACY:
-    if (can_change_to_government(pplayer, G_REPUBLIC)) 
-      ai_government_change(pplayer, G_REPUBLIC);
-    else if (can_change_to_government(pplayer, G_MONARCHY)) 
-      ai_government_change(pplayer, G_MONARCHY);
-    break;
-  case G_REPUBLIC:
-    if (can_change_to_government(pplayer, G_MONARCHY)) 
-      ai_government_change(pplayer, G_MONARCHY); /* better than despotism! -- 
Syela */
-    break;
+  int gov, govs_available=0;
+  int government = pplayer->government;
+  int new_gov = government;
+
+/* for debug purposes
+   char *government_names[G_LAST] = {"Anarchy", "Despotism", "Monarchy",
+        "Communism", "Republic", "Democracy"};  
+*/
+
+  if (strcmp(pplayer->name,"old000")>0 && strcmp(pplayer->name,"old999")<0)  {
+      if (can_change_to_government(pplayer, G_REPUBLIC))
+          ai_government_change(pplayer, G_REPUBLIC);
+      else
+         if (can_change_to_government(pplayer, G_MONARCHY))
+          ai_government_change(pplayer, G_MONARCHY);
+      return; /* remove to check anarchy and add else to the following */
   }
+  
+  for (gov=G_MONARCHY; gov<=G_DEMOCRACY; gov++)  
+      if (can_change_to_government(pplayer, gov)||(government==gov)) {
+          new_gov = gov;
+          govs_available++;
+      }
 
-  if( pplayer->government == G_ANARCHY ){
+  if (govs_available > 1) {
+     new_gov = ai_evaluate_governments(pplayer);
+     }
+
+  if (new_gov!=government && can_change_to_government(pplayer, new_gov)) {
+      /* printf("Changing %s from %s to %s \n", pplayer->name,
+              government_names[government], government_names[new_gov]); */
+      ai_government_change(pplayer, new_gov);
+      return;
+  }
+
+  if( government == G_ANARCHY ){
     /* if the ai ever intends to stay anarchy, */
     /* change condition to if( (pplayer->revolution==0) && */
     if( ((pplayer->revolution<=0) || (pplayer->revolution>5)) &&
@@ -480,5 +490,100 @@
        )
       { ai_government_change(pplayer, G_DESPOTISM); }
   }/* if ANARCHY */
+
+  /* if the ai prefers monarchy over republic there is good reason
+     to research communism... */
+  if(government==G_MONARCHY && get_invention(pplayer, A_REPUBLIC)==TECH_KNOWN)
+    if(get_invention(pplayer, A_COMMUNISM)!=TECH_KNOWN)
+      pplayer->ai.tech_want[A_COMMUNISM] += 
100*city_list_size(&pplayer->cities);
+     
+
+  return;
+}
+
+
+/* ********************************************************************** */
+/* The following evaluates the different forms of governement available   */
+/* to an AI player. The criterion for the best one is based on maximizing */
+/* (3*trade_prod + 2*shield_surplus)/5                                    */
+/* ********************************************************************** */
+int ai_evaluate_governments(struct player *pplayer)
+{
+  int i, x, y, gov;
+  int shield_surplus[4], trade_prod[4], unhappy_cities[4], score[4];
+  int democracy_disorder = 0;
+  struct city *tmp_city;
+
+  int current_gov = pplayer->government;
+
+  for (i=0; i<=3; i++) {
+      trade_prod[i] = 0;
+      shield_surplus[i] = 0;
+      unhappy_cities[i] = 0;
+  }
+
+  tmp_city = fc_malloc(sizeof(struct city));
+  city_list_iterate(pplayer->cities, pcity) 
+     *tmp_city = *pcity; 
+     for (gov = G_MONARCHY; gov <= G_DEMOCRACY; gov++)  {
+         if ((!can_change_to_government(pplayer, gov))&&(gov!=current_gov))
+            continue;
+         pplayer->government = gov;
+         city_refresh(tmp_city);
+         /* the 4 lines that follow are copied from ai_manage_city -
+            we don't need the sell_obsolete_buildings */
+         city_check_workers(pplayer, tmp_city);
+         auto_arrange_workers(tmp_city);
+         if (ai_fix_unhappy(tmp_city))
+            ai_scientists_taxmen(tmp_city);
+
+         trade_prod[gov - G_MONARCHY] += tmp_city->trade_prod;
+         shield_surplus[gov - G_MONARCHY] += tmp_city->shield_surplus;
+         if (city_unhappy(tmp_city)) {
+            unhappy_cities[gov - G_MONARCHY]++;
+            /* the following is essential to prevent falling into anarchy */
+            if (tmp_city->anarchy > 0 && gov == G_DEMOCRACY) 
+               democracy_disorder = 1;
+            /* if(current_gov == G_DEMOCRACY && gov==G_DEMOCRACY) 
+              printf("city anarchy in %s : %d \n",tmp_city->name, 
tmp_city->anarchy); */
+         }
+     }
+     /* the following is essential because the above may change the 
ptile->worked */
+     city_map_iterate(x, y) {
+        struct tile *ptile = map_get_tile(pcity->x+x-2, pcity->y+y-2);
+        if (ptile->worked == tmp_city)
+            ptile->worked = NULL;
+        set_worker_city(pcity, x, y, get_worker_city(pcity, x, y));
+     }
+  city_list_iterate_end;
+  pplayer->government = current_gov;
+  free(tmp_city);
+
+  freelog(LOG_DEBUG, "TOTAL-mon: %d %d - %d \n",trade_prod[0], 
shield_surplus[0], unhappy_cities[0]);
+  freelog(LOG_DEBUG, "TOTAL-com: %d %d - %d \n",trade_prod[1], 
shield_surplus[1], unhappy_cities[1]);
+  freelog(LOG_DEBUG, "TOTAL-rep: %d %d - %d \n",trade_prod[2], 
shield_surplus[2], unhappy_cities[2]);
+  freelog(LOG_DEBUG, "TOTAL-dem: %d %d - %d \n",trade_prod[3], 
shield_surplus[3], unhappy_cities[3]);
+
+  for (i=0; i<4; i++) {
+      score[i] = (3*trade_prod[i] + 2*shield_surplus[i])/5;
+  }
+
+  /* bonus for democracy - 1 for each city, up to 20 */
+  score[3] += min(20, city_list_size(&pplayer->cities)); 
+  /* bonus for current gov to avoid frequent flip-flop style changes */
+  if (current_gov >= G_MONARCHY && current_gov <= G_DEMOCRACY)
+     score[current_gov - G_MONARCHY] += city_list_size(&pplayer->cities) 
+                                     + 3*(current_gov - G_MONARCHY); 
+
+  if (score[3]>=score[2]&&score[3]>=score[1]&&score[3]>=score[0]&&
+      
((!unhappy_cities[3])||((current_gov==G_DEMOCRACY)&&(!democracy_disorder))))
+     return G_DEMOCRACY;  
+  if (score[2]>=score[1]&&score[2]>=score[0])
+     return G_REPUBLIC;
+  if (score[1]>=score[2]&&score[1]>=score[0])
+     return G_COMMUNISM;
+  if (score[0]>=score[2]&&score[0]>=score[1])
+     return G_MONARCHY;
+  return current_gov;
 }
 
--- freeciv/ai/advdomestic.c    Mon Jul  5 19:25:02 1999
+++ advdomestic.c       Mon Jul  5 23:44:07 1999
@@ -63,6 +63,107 @@
   return 0;
 }
 
+
+/* *************************************************************************
+The following evaluates the effectiveness of a building/wonder affecting
+city's unhappiness. The type_affected can be one of 0, 2, 1, meaning,
+respectively, whether the improvement/wonder affects civic unhappiness only,
+military unhappiness only (makes sense only in a republic or a democracy), 
+or both.
+************************************************************************* */
+int happy_building_value(int max, struct city *pcity, int val, int 
type_affected)
+{
+  int i, value = 0;
+  int military_unhappiness=0, civic_unhappiness;
+  int gov = get_government(city_owner(pcity)->player_no);
+  int elvis = pcity->ppl_elvis;
+  int sad = pcity->ppl_unhappy[0]; /* yes, I'm sure about that! */
+
+  /* no reason to buy anything in this case! */
+  if (city_affected_by_wonder(pcity, B_SHAKESPEARE))
+     return(0);
+
+  /* check if military units are causing unhappiness  */
+  if (gov >= G_REPUBLIC) {
+      unit_list_iterate(pcity->units_supported, punit)
+           military_unhappiness += punit->unhappiness;
+      unit_list_iterate_end;
+      if (city_got_effect(pcity, B_POLICE) && 
improvement_variant(B_WOMENS)==0) {
+          military_unhappiness--;
+          if (gov == G_DEMOCRACY) military_unhappiness--;
+          if (military_unhappiness < 0) military_unhappiness=0;
+      }
+      if (military_unhappiness>0 && type_affected >0)
+         value = military_unhappiness * pcity->ai.trade_want;
+  } 
+  /* printf("%d \n", military_unhappiness); */
+
+  /* find effect of civic unhappiness:
+     we should avoid building colosseums when the disorder is due to military 
units */
+  if (gov>=G_REPUBLIC)
+      civic_unhappiness = pcity->ppl_unhappy[2];
+  else
+      civic_unhappiness = pcity->ppl_unhappy[3];
+  /* the above means that we don't count unhappy citizens to whom martial law 
applies.
+     a peaceful AI shouldn't do this, but a peaceful AI should prefer Rep. or 
Democracy */
+
+  if (military_unhappiness==0 || pcity->ppl_unhappy[0] - pcity->ppl_unhappy[1] 
> 1)
+      civic_unhappiness += pcity->ppl_unhappy[0] - pcity->ppl_unhappy[1];
+
+  if (type_affected==0) sad += (military_unhappiness + 2)>>2;
+  if (type_affected==1) sad += military_unhappiness;
+  if (type_affected==2) sad = (sad>>1) + (military_unhappiness<<1);
+
+  freelog(LOG_DEBUG, "In %s, unh[0] = %d, unh[4] = %d, sad = %d",
+         pcity->name, pcity->ppl_unhappy[0], pcity->ppl_unhappy[4], sad);
+  /* printf("%s: %d %d %d   %d \n", pcity->name, sad, civic_unhappiness, 
military_unhappiness, val); */
+
+  i = max;
+  while (i && elvis) { 
+         i--; elvis--; 
+         if ((civic_unhappiness > 0)&&(type_affected < 2)) {
+             value += val; 
+         }
+         if ((military_unhappiness>0)&&(type_affected>0))  {
+             value += val;
+         }
+  }
+  while (i && sad) { 
+         i--; sad--; value += 5;
+         if ((civic_unhappiness > 0)&&(type_affected < 2))  {
+             value += 5 + 4 * civic_unhappiness;
+         }
+         if ((military_unhappiness>0)&&(type_affected>0))  {
+             value += 6 + 6 * military_unhappiness;
+         }
+  }
+
+  if (city_unhappy(pcity)) {  /* Desperately seeking something */
+      if (type_affected < 2)  
+          value += val * civic_unhappiness;
+      if (type_affected > 0) 
+          value += val * military_unhappiness;
+      value += 2 * val * pcity->anarchy;
+  }
+
+  while (i) { 
+      i--; 
+      value += 2 * (pcity->size + pcity->food_surplus);
+  }
+
+  freelog(LOG_DEBUG, "%s: %d elvis %d sad %d bored %d size %d max %d val",
+          pcity->name, pcity->ppl_elvis, pcity->ppl_unhappy[4],
+         pcity->ppl_content[4], pcity->size, max, value);
+
+  return(value);
+}
+
+
+/* *************************************************************************
+This is the original version of happy_building_value(). It was modified to
+distinguish unhappiness caused by military units as well as to treat 
+better different governments and different buildings...
+************************************************************************* */
 int building_value(int max, struct city *pcity, int val)
 {
   int i, j = 0;
@@ -75,8 +176,8 @@
 
   i = pcity->ppl_unhappy[3] - pcity->ppl_unhappy[2];
   sad += i; /* if units are making us unhappy, count that too. */
-  freelog(LOG_DEBUG, "In %s, unh[0] = %d, unh[4] = %d, sad = %d",
-         pcity->name, pcity->ppl_unhappy[0], pcity->ppl_unhappy[4], sad);
+  if(0) freelog(LOG_DEBUG, "In %s, unh[0] = %d, unh[4] = %d, sad = %d",
+               pcity->name, pcity->ppl_unhappy[0], pcity->ppl_unhappy[4], sad);
 
   i = max;
   while (i && elvis) { i--; elvis--; j += val; }
@@ -86,13 +187,15 @@
   while (i) { i--; j += 16; } /* 16 is debatable value */
   /* using (i && bored) led to a lack of foresight,
      especially re: Chapel -- Syela */
-  freelog(LOG_DEBUG, "%s: %d elvis %d sad %d bored %d size %d max %d val",
+  if(0) freelog(LOG_DEBUG, "%s: %d elvis %d sad %d bored %d size %d max %d 
val",
                pcity->name, pcity->ppl_elvis, pcity->ppl_unhappy[4],
                pcity->ppl_content[4], pcity->size, max, j);
 
   return(j);
 }
 
+
+
 int ocean_workers(struct city *pcity)
 {
   int x, y, i = 0;
@@ -111,7 +214,7 @@
   int x, y, i = 0; 
   city_map_iterate(x, y) {
     if (is_worker_here(pcity, x, y)) {
-      if (map_get_special(pcity->x+x-2, pcity->y+y-2) & S_RAILROAD) i++;
+      if (map_get_special(pcity->x+x-2, pcity->y+y-2) & S_ROAD) i++;
     }
   }  
   return(i); 
@@ -176,7 +279,7 @@
   } 
   return(c); /* benefit or cost of this building */
 }
- 
+
 void ai_eval_buildings(struct city *pcity)
 {
   int i, gov, val, a, t, food, j, k, hunger, bar, grana;
@@ -269,6 +372,324 @@
 TRADE_WEIGHTING * 100 / MORT.  This is comparable, thus the same weight -- 
Syela */
 
   if (could_build_improvement(pcity, B_CATHEDRAL) && !built_elsewhere(pcity, 
B_MICHELANGELO))
+    values[B_CATHEDRAL] = happy_building_value(get_cathedral_power(pcity), 
pcity, val, 0);
+  else if (tech_exists(game.rtech.cathedral_plus) &&
+          get_invention(pplayer, game.rtech.cathedral_plus) != TECH_KNOWN)
+    values[B_CATHEDRAL] = happy_building_value(4, pcity, val, 0);
+
+/* old wall code depended on danger, was a CPU hog and didn't really work 
anyway */
+/* it was so stupid, AI wouldn't start building walls until it was in danger */
+/* and it would have no chance to finish them before it was too late */
+
+  if (could_build_improvement(pcity, B_CITY))
+/* && !built_elsewhere(pcity, B_WALL))      was counterproductive -- Syela */
+    values[B_CITY] = 40; /* WAG */
+
+  if (could_build_improvement(pcity, B_COASTAL))
+    values[B_COASTAL] = 40; /* WAG */
+
+  if (could_build_improvement(pcity, B_SAM))
+    values[B_SAM] = 50; /* WAG */
+
+  if (could_build_improvement(pcity, B_COLOSSEUM))
+    values[B_COLOSSEUM] = happy_building_value(get_colosseum_power(pcity), 
pcity, val, 0);
+  else if (tech_exists(game.rtech.colosseum_plus) &&
+          get_invention(pplayer, game.rtech.colosseum_plus) != TECH_KNOWN)
+    values[B_COLOSSEUM] = happy_building_value(4, pcity, val, 0) - 
+                          happy_building_value(3, pcity, val, 0);
+  
+  if (could_build_improvement(pcity, B_COURTHOUSE)) {
+    if (gov < G_DEMOCRACY)
+       values[B_COURTHOUSE] = (pcity->corruption * t)>>1;
+    else
+       values[B_COURTHOUSE] = happy_building_value(1, pcity, val, 0);
+  }
+  
+  if (could_build_improvement(pcity, B_FACTORY))
+    values[B_FACTORY] = (prod>>1) + pollution_cost(pplayer, pcity, B_FACTORY);
+  
+  if (could_build_improvement(pcity, B_GRANARY) &&
+      !(improvement_variant(B_PYRAMIDS)==0 &&
+       built_elsewhere(pcity, B_PYRAMIDS)))
+    values[B_GRANARY] = grana * pcity->food_surplus;
+  
+  if (could_build_improvement(pcity, B_HARBOUR))
+    values[B_HARBOUR] = food * ocean_workers(pcity) * hunger;
+
+  if (could_build_improvement(pcity, B_HYDRO) && !built_elsewhere(pcity, 
B_HOOVER))
+    values[B_HYDRO] = ((needpower * prod)>>2) + pollution_cost(pplayer, pcity, 
B_HYDRO);
+
+  if (could_build_improvement(pcity, B_LIBRARY))
+    values[B_LIBRARY] = sci>>1;
+
+  if (could_build_improvement(pcity, B_MARKETPLACE))
+    values[B_MARKETPLACE] = (tax + 3*pcity->ppl_taxman +
+     pcity->ppl_elvis*wwtv)/2;
+
+  if (could_build_improvement(pcity, B_MFG))
+    values[B_MFG] = ((city_got_building(pcity, B_HYDRO) ||
+                     city_got_building(pcity, B_NUCLEAR) ||
+                     city_got_building(pcity, B_POWER) ||
+                     city_affected_by_wonder(pcity, B_HOOVER)) ?
+                     (prod * 3)>>2 : prod>>1) +
+                     pollution_cost(pplayer, pcity, B_MFG);
+
+  if (could_build_improvement(pcity, B_NUCLEAR))
+    values[B_NUCLEAR] = ((needpower * prod)>>2) + pollution_cost(pplayer, 
pcity, B_NUCLEAR);
+
+  if (could_build_improvement(pcity, B_OFFSHORE)) /* ignoring pollu.  FIX? */
+    values[B_OFFSHORE] = ocean_workers(pcity) * SHIELD_WEIGHTING;
+
+  if (could_build_improvement(pcity, B_POLICE) && !built_elsewhere(pcity, 
B_WOMENS)) {
+      if (gov >= G_REPUBLIC) {
+         if (improvement_variant(B_WOMENS)==0)
+             values[B_POLICE] += happy_building_value(gov-G_REPUBLIC+1, pcity, 
val, 2);
+         else
+             values[B_POLICE] += happy_building_value(pcity->shield_prod, 
pcity, val, 2);
+      }
+  }
+
+  if (could_build_improvement(pcity, B_POWER))
+    values[B_POWER] = ((needpower * prod)>>2) + pollution_cost(pplayer, pcity, 
B_POWER);
+
+  if (could_build_improvement(pcity, B_RESEARCH) && !built_elsewhere(pcity, 
B_SETI))
+    values[B_RESEARCH] = sci>>1;
+
+  if (could_build_improvement(pcity, B_SDI))
+    values[B_SDI] = 50; /* WAG */
+  
+  if (could_build_improvement(pcity, B_SEWER)) {
+    int ssz = game.sewer_size;
+    if (city_happy(pcity) && pcity->size > ssz-1 && est_food > 0)
+      values[B_SEWER] = ((((city_got_effect(pcity, B_GRANARY) ? 3 : 2) *
+         pcity->size * game.foodbox)>>1) - pcity->food_stock) * food;
+    else values[B_SEWER] = food * est_food * ssz * game.foodbox /
+          MAX(1, ((ssz+1 - MIN(ssz, pcity->size)) * MAX(ssz, pcity->size) *
+          game.foodbox - pcity->food_stock));
+  }
+
+  if (could_build_improvement(pcity, B_STOCK))
+    values[B_STOCK] = (tax + 3*pcity->ppl_taxman + pcity->ppl_elvis*wwtv)/2;
+
+  if (could_build_improvement(pcity, B_SUPERHIGHWAYS))
+    values[B_SUPERHIGHWAYS] = railroad_trade(pcity) * t;
+
+  if (could_build_improvement(pcity, B_SUPERMARKET))
+    values[B_SUPERMARKET] = farmland_food(pcity) * food * hunger;
+
+  if (could_build_improvement(pcity, B_TEMPLE))
+    values[B_TEMPLE] = happy_building_value(get_temple_power(pcity), pcity, 
val, 0);
+
+  if (could_build_improvement(pcity, B_UNIVERSITY))
+    values[B_UNIVERSITY] = sci>>1;
+
+  if (could_build_improvement(pcity, B_MASS))
+    values[B_MASS] = pollution_cost(pplayer, pcity, B_MASS);
+
+  if (could_build_improvement(pcity, B_RECYCLING))
+    values[B_RECYCLING] = pollution_cost(pplayer, pcity, B_RECYCLING);
+
+/* ignored: AIRPORT, PALACE. -- Syela*/
+/* military advisor will deal with CITY and PORT */
+
+  for (i = 0; i < B_LAST; i++) {
+    if (is_wonder(i) && could_build_improvement(pcity, i) && 
!wonder_obsolete(i)) {
+      if (i == B_ASMITHS)
+        for (j = 0; j < B_LAST; j++)
+          if (city_got_building(pcity, j) && improvement_upkeep(pcity, j) == 1)
+            values[i] += t;
+      if (i == B_COLLOSSUS)
+        values[i] = (pcity->size + 1) * t; /* probably underestimates the 
value */
+      if (i == B_COPERNICUS)
+        values[i] = sci>>1;
+      if (i == B_CURE)
+        values[i] = val + happy_building_value(1, pcity, val, 1);
+      if (i == B_DARWIN) /* this is a one-time boost, not constant */
+        values[i] = ((research_time(pplayer) * 2 + game.techlevel) * t -
+                    pplayer->research.researched * t) / MORT;
+      if (i == B_GREAT) /* basically (100 - freecost)% of a free tech per turn 
*/
+        values[i] = (research_time(pplayer) * (100 - game.freecost)) * t *
+                    (game.nplayers - 2) / (game.nplayers * 100); /* guessing */
+
+      if (i == B_WALL && !city_got_citywalls(pcity))
+/* allowing B_CITY when B_WALL exists, don't like B_WALL when B_CITY exists. */
+        values[B_WALL] = 1; /* WAG */
+ /* was 40, which led to the AI building WALL, not being able to build CITY,
+someone learning Metallurgy, and the AI collapsing.  I hate the WALL. -- Syela 
*/
+
+      if (i == B_HANGING) /* will add the global effect to this. */
+        values[i] = happy_building_value(3, pcity, val, 1) -
+                    happy_building_value(1, pcity, val, 1);
+      if (i == B_HOOVER && !city_got_building(pcity, B_HYDRO) &&
+                           !city_got_building(pcity, B_NUCLEAR))
+        values[i] = (city_got_building(pcity, B_POWER) ? 0 :
+               (needpower * prod)>>2) + pollution_cost(pplayer, pcity, 
B_HOOVER);
+      if (i == B_ISAAC)
+        values[i] = sci;
+      if (i == B_LEONARDO) {
+        unit_list_iterate(pcity->units_supported, punit)
+          j = can_upgrade_unittype(pplayer, punit->type);
+          if (j >= 0) values[i] = MAX(values[i], 8 * 
unit_upgrade_price(pplayer,
+               punit->type, j)); /* this is probably wrong -- Syela */
+        unit_list_iterate_end;
+      }
+      if (i == B_BACH)
+        values[i] = 2*val + happy_building_value(2, pcity, val, 1);
+      if (i == B_RICHARDS) /* ignoring pollu, I don't think it matters here -- 
Syela */
+        values[i] = (pcity->size + 1) * SHIELD_WEIGHTING;
+      if (i == B_MICHELANGELO && !city_got_building(pcity, B_CATHEDRAL))
+        values[i] = 3*val + happy_building_value(get_cathedral_power(pcity), 
pcity, val, 0);
+      if (i == B_ORACLE) {
+        if (city_got_building(pcity, B_TEMPLE) ||
+            get_invention(pplayer, A_MYSTICISM) != TECH_KNOWN)
+            values[i] = happy_building_value(2, pcity, val, 0);
+      /* The second || has nothing to do with oracle, just the tech_Want of 
mysticism! */
+      }
+          
+      if (i == B_PYRAMIDS && improvement_variant(B_PYRAMIDS)==0
+         && !city_got_building(pcity, B_GRANARY))
+        values[i] = food * pcity->food_surplus; /* different tech req's */
+      if (i == B_SETI && !city_got_building(pcity, B_RESEARCH))
+        values[i] = sci>>1;
+      if (i == B_SHAKESPEARE)
+        if (gov >= G_REPUBLIC)
+          values[i] = val + happy_building_value(pcity->shield_prod, pcity, 
val, 1);
+        else
+          values[i] = val + happy_building_value(pcity->size, pcity, val, 1);
+      if (i == B_SUNTZU)
+        values[i] = bar;
+      if (i == B_UNITED) {
+        unit_list_iterate(pcity->units_supported, punit)
+          if (is_military_unit(punit))
+              values[i]+=5;
+              if (punit->hp != get_unit_type(punit->type)->hp)
+                  values[i]+=2;
+        unit_list_iterate_end;
+      }        
+      if (i == B_WOMENS && !city_got_building(pcity, B_POLICE)) {
+        if (gov >= G_REPUBLIC) {
+          if (improvement_variant(B_WOMENS) == 0)
+             values[B_WOMENS] += val + happy_building_value(gov-G_REPUBLIC+1, 
pcity, val, 2);
+          else
+             values[B_WOMENS] += val + 
happy_building_value(pcity->shield_prod, pcity, val, 2);
+          }
+      }
+      /* ignoring APOLLO, LIGHTHOUSE, MAGELLAN, MANHATTEN, MARCO, STATUE */
+    }
+  }
+
+  for (i=0;i<B_LAST;i++) {
+    if (values[i]) {
+      freelog(LOG_DEBUG, "%s wants %s with desire %d.",
+             pcity->name, get_improvement_name(i), values[i]);
+    }
+    if (!is_wonder(i)) values[i] -= improvement_upkeep(pcity, i) * t;
+    values[i] *= 100;
+    if (!is_wonder(i)) { /* trying to buy fewer improvements */
+      values[i] *= SHIELD_WEIGHTING;
+      values[i] /= MORT;
+    }
+    j = improvement_value(i);
+/* handle H_PROD here? -- Syela */
+    pcity->ai.building_want[i] = values[i] / j;
+  }
+
+  return;
+}  
+
+
+void ai_eval_buildings_old(struct city *pcity)
+{
+  int i, gov, val, a, t, food, j, k, hunger, bar, grana;
+  int tax, prod, sci, values[B_LAST];
+  int est_food = pcity->food_surplus + 2 * pcity->ppl_scientist + 2 * 
pcity->ppl_taxman; 
+  struct player *pplayer = city_owner(pcity);
+  int needpower;
+  int wwtv = worst_worker_tile_value(pcity);
+  
+  a = get_race(city_owner(pcity))->attack;
+  t = pcity->ai.trade_want; /* trade_weighting */
+  sci = (pcity->trade_prod * pplayer->economic.science + 50) / 100;
+  tax = pcity->trade_prod - sci;
+#ifdef STUPID
+  sci *= t;
+  tax *= t;
+#else
+/* better might be a longterm weighted average, this is a quick-n-dirty fix -- 
Syela */
+  sci = ((sci + pcity->trade_prod) * t)>>1;
+  tax = ((tax + pcity->trade_prod) * t)>>1;
+#endif
+  if (pplayer->research.researching == A_NONE) sci = 0; /* don't need 
libraries!! */
+  prod = pcity->shield_prod * 100 / city_shield_bonus(pcity) * 
SHIELD_WEIGHTING;
+  needpower = (city_got_building(pcity, B_MFG) ? 2 :
+              (city_got_building(pcity, B_FACTORY) ? 1 : 0));
+  val = ai_best_tile_value(pcity);
+  food = food_weighting(MAX(2,pcity->size));
+  grana = food_weighting(MAX(3,pcity->size + 1));
+/* because the benefit doesn't come immediately, and to stop stupidity */
+/* the AI used to really love granaries for nascent cities, which is OK */
+/* as long as they aren't rated above Settlers and Laws is above Pottery -- 
Syela*/
+  i = (pcity->size * 2) + settler_eats(pcity);
+  i -= pcity->food_prod; /* amazingly left out for a week! -- Syela */
+  if (i > 0 && !pcity->ppl_scientist && !pcity->ppl_taxman) hunger = i + 1;
+  else hunger = 1;
+
+  gov = get_government(pcity->owner);
+
+  for (i=0;i<B_LAST;i++) {
+    values[i]=0;
+  } /* rewrite by Syela - old values seemed very random */
+
+  if (could_build_improvement(pcity, B_AQUEDUCT)) {
+    int asz = game.aqueduct_size;
+    if (city_happy(pcity) && pcity->size > asz-1 && est_food > 0)
+      values[B_AQUEDUCT] = ((((city_got_effect(pcity, B_GRANARY) ? 3 : 2) *
+         pcity->size * game.foodbox)>>1) - pcity->food_stock) * food;
+    else values[B_AQUEDUCT] = food * est_food * asz * game.foodbox /
+           MAX(1, ((asz+1 - MIN(asz, pcity->size)) * MAX(asz, pcity->size) *
+           game.foodbox - pcity->food_stock));
+  }
+
+
+  if (could_build_improvement(pcity, B_BANK))
+    values[B_BANK] = (tax + 3*pcity->ppl_taxman + pcity->ppl_elvis*wwtv)/2;
+  
+  j = 0; k = 0;
+  city_list_iterate(pplayer->cities, acity)
+    if (acity->is_building_unit) {
+      if (!unit_flag(acity->currently_building, F_NONMIL) &&
+          unit_types[acity->currently_building].move_type == LAND_MOVING)
+        j += prod;
+      else if (unit_flag(acity->currently_building, F_CARAVAN) &&
+        built_elsewhere(acity, B_SUNTZU)) j += prod; /* this also stops 
flip-flops */
+    } else if (acity->currently_building == B_BARRACKS || /* this stops 
flip-flops */
+             acity->currently_building == B_BARRACKS2 ||
+             acity->currently_building == B_BARRACKS3 ||
+             acity->currently_building == B_SUNTZU) j += prod;
+    k++;
+  city_list_iterate_end;
+  if (!k) freelog(LOG_FATAL,
+                 "Gonna crash, 0 k, looking at %s (ai_eval_buildings)",
+                 pcity->name);
+  /* rationale: barracks effectively double prod while building military units 
*/
+  /* if half our production is military, effective gain is 1/2 city prod */
+  bar = j / k;
+
+  if (!built_elsewhere(pcity, B_SUNTZU)) { /* yes, I want can, not could! */
+    if (can_build_improvement(pcity, B_BARRACKS3))
+      values[B_BARRACKS3] = bar;
+    else if (can_build_improvement(pcity, B_BARRACKS2))
+      values[B_BARRACKS2] = bar;
+    else if (can_build_improvement(pcity, B_BARRACKS))
+      values[B_BARRACKS] = bar;
+  }
+
+  if (could_build_improvement(pcity, B_CAPITAL))
+    values[B_CAPITAL] = TRADE_WEIGHTING * 999 / MORT; /* trust me */
+/* rationale: If cost is N and benefit is N gold per MORT turns, want is
+TRADE_WEIGHTING * 100 / MORT.  This is comparable, thus the same weight -- 
Syela */
+
+  if (could_build_improvement(pcity, B_CATHEDRAL) && !built_elsewhere(pcity, 
B_MICHELANGELO))
     values[B_CATHEDRAL] = building_value(get_cathedral_power(pcity), pcity, 
val);
   else if (tech_exists(game.rtech.cathedral_plus) &&
           get_invention(pplayer, game.rtech.cathedral_plus) != TECH_KNOWN)
@@ -477,6 +898,8 @@
 
   return;
 }  
+
+
 
 void domestic_advisor_choose_build(struct player *pplayer, struct city *pcity,
                                   struct ai_choice *choice)
--- freeciv/ai/aicity.c Tue Jul  6 01:28:12 1999
+++ aicity.c    Tue Jul  6 02:48:16 1999
@@ -104,7 +104,10 @@
 
   if (find_palace(pplayer) || pplayer->government == G_DEMOCRACY) palace = 1;
   city_list_iterate(pplayer->cities, pcity)
-    ai_eval_buildings(pcity);
+    if (strcmp(pplayer->name,"old000")>0 && strcmp(pplayer->name,"old999")<0)
+       ai_eval_buildings_old(pcity);
+    else
+       ai_eval_buildings(pcity);
     if (!palace) corr += pcity->corruption * 8;
     for (i = 0; i < B_LAST; i++) 
       if (pcity->ai.building_want[i] > 0) values[i] += 
pcity->ai.building_want[i];
@@ -149,6 +152,7 @@
     pcity->ai.building_want[B_PYRAMIDS] = values[B_PYRAMIDS];
     pcity->ai.building_want[B_SETI] = values[B_SETI];
     pcity->ai.building_want[B_SUNTZU] = values[B_SUNTZU];
+    pcity->ai.building_want[B_UNITED] = values[B_UNITED];
     pcity->ai.building_want[B_WOMENS] = values[B_WOMENS];
     pcity->ai.building_want[B_LEONARDO] = leon; /* hopefully will fix */
     pcity->ai.building_want[B_PALACE] = corr; /* urgent enough? */

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