Complete.Org: Mailing Lists: Archives: freeciv-ai: July 2003:
[freeciv-ai] Re: New CM in server patch (PR#4335)
Home

[freeciv-ai] Re: New CM in server patch (PR#4335)

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [freeciv-ai] Re: New CM in server patch (PR#4335)
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Fri, 18 Jul 2003 11:08:51 -0700
Reply-to: rt@xxxxxxxxxxxxxx

On Fri, 18 Jul 2003, Per I. Mathisen wrote:
> New patch attached.

Newer patch attached. Now uses adjusted aidata priorities for weights, and
prefers to go into disorder rather than disbanding units.

  - Per

Index: ai/aicity.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.c,v
retrieving revision 1.142
diff -u -r1.142 aicity.c
--- ai/aicity.c 2003/07/14 22:40:05     1.142
+++ ai/aicity.c 2003/07/18 18:06:14
@@ -700,188 +700,11 @@
 static void ai_manage_city(struct player *pplayer, struct city *pcity)
 {
   auto_arrange_workers(pcity);
-  if (ai_fix_unhappy(pcity) && ai_fuzzy(pplayer, TRUE))
-    ai_scientists_taxmen(pcity);
   ai_sell_obsolete_buildings(pcity);
   sync_cities();
-/* ai_city_choose_build(pplayer, pcity); -- moved by Syela */
 }
 
 /**************************************************************************
-...
-**************************************************************************/
-static int ai_find_elvis_pos(struct city *pcity, int *xp, int *yp)
-{
-  struct government *g = get_gov_pcity(pcity);
-  int foodneed, prodneed, luxneed, pwr, e, worst_value = 0;
-
-  foodneed=(pcity->size *2) + settler_eats(pcity);
-  foodneed -= pcity->food_prod; /* much more robust now -- Syela */
-  prodneed = 0;
-  prodneed -= pcity->shield_prod;
-  luxneed = 2 * (2 * pcity->ppl_angry[4] + pcity->ppl_unhappy[4] -
-                pcity->ppl_happy[4]);
-  pwr = 2 * city_tax_bonus(pcity) / 100;
-  e = (luxneed + pwr - 1) / pwr;
-  if (e > 1) {
-    foodneed += (e - 1) * 2;
-    prodneed += (e - 1);
-  } /* not as good as elvising all at once, but should be adequate */
-
-  unit_list_iterate(pcity->units_supported, punit)
-    prodneed += utype_shield_cost(unit_type(punit), g);
-  unit_list_iterate_end;
-  
-  prodneed -= citygov_free_shield(pcity, g);
-
-  *xp = 0;
-  *yp = 0;
-  city_map_iterate(x, y) {
-    if (is_city_center(x, y))
-      continue; 
-    if (get_worker_city(pcity, x, y) == C_TILE_WORKER) {
-      int value = city_tile_value(pcity, x, y,
-                                 foodneed + city_get_food_tile(x, y, pcity),
-                                 prodneed + city_get_shields_tile(x, y,
-                                                                  pcity));
-
-      if ((*xp == 0 && *yp == 0) || value < worst_value) {
-       *xp = x;
-       *yp = y;
-       worst_value = value;
-      }
-    }
-  } city_map_iterate_end;
-  if (*xp == 0 && *yp == 0) return 0;
-  foodneed += city_get_food_tile(*xp, *yp, pcity);
-  prodneed += city_get_shields_tile(*xp, *yp, pcity);
-  if (e > 1) {
-    foodneed -= (e - 1) * 2; /* forgetting these two lines */
-    prodneed -= (e - 1); /* led to remarkable idiocy -- Syela */
-  }
-  if (foodneed > pcity->food_stock) {
-    freelog(LOG_DEBUG,
-           "No elvis_pos in %s - would create famine.", pcity->name);
-    return 0; /* Bad time to Elvis */
-  }
-  if (prodneed > 0) {
-    freelog(LOG_DEBUG,
-           "No elvis_pos in %s - would fail-to-upkeep.", pcity->name);
-    return 0; /* Bad time to Elvis */
-  }
-  return(city_tile_value(pcity, *xp, *yp, foodneed, prodneed));
-}
-
-/**************************************************************************
-...
-**************************************************************************/
-int ai_make_elvis(struct city *pcity)
-{
-  int xp, yp, val;
-  if ((val = ai_find_elvis_pos(pcity, &xp, &yp)) != 0) {
-    server_remove_worker_city(pcity, xp, yp);
-    pcity->ppl_elvis++;
-    city_refresh(pcity); /* this lets us call ai_make_elvis in luxury routine 
*/
-    return val; /* much more useful! */
-  } else
-    return 0;
-}
-
-/**************************************************************************
-...
-**************************************************************************/
-static void make_elvises(struct city *pcity)
-{
-  int xp, yp, elviscost;
-  pcity->ppl_elvis += (pcity->ppl_taxman + pcity->ppl_scientist);
-  pcity->ppl_taxman = 0;
-  pcity->ppl_scientist = 0;
-  city_refresh(pcity);
- 
-  while (TRUE) {
-    if ((elviscost = ai_find_elvis_pos(pcity, &xp, &yp)) != 0) {
-      int food = city_get_food_tile(xp, yp, pcity);
-
-      if (food > pcity->food_surplus)
-       break;
-      if (food == pcity->food_surplus && city_happy(pcity))
-       break; /* scientists don't party */
-      if (elviscost >= 24) /* doesn't matter if we wtbb or not! */
-        break; /* no benefit here! */
-      server_remove_worker_city(pcity, xp, yp);
-      pcity->ppl_elvis++;
-      city_refresh(pcity);
-    } else
-      break;
-  }
-    
-}
-
-/**************************************************************************
-...
-**************************************************************************/
-static void make_taxmen(struct city *pcity)
-{
-  while (!city_unhappy(pcity) && pcity->ppl_elvis > 0) {
-    pcity->ppl_taxman++;
-    pcity->ppl_elvis--;
-    city_refresh(pcity);
-  }
-  if (city_unhappy(pcity)) {
-    pcity->ppl_taxman--;
-    pcity->ppl_elvis++;
-    city_refresh(pcity);
-  }
-
-}
-
-/**************************************************************************
-...
-**************************************************************************/
-static void make_scientists(struct city *pcity)
-{
-  make_taxmen(pcity); /* reuse the code */
-  pcity->ppl_scientist = pcity->ppl_taxman;
-  pcity->ppl_taxman = 0;
-}
-
-/**************************************************************************
- we prefer science, but if both is 0 we prefer $ 
- (out of research goal situation)
-**************************************************************************/
-void ai_scientists_taxmen(struct city *pcity)
-{
-  int science_bonus, tax_bonus;
-  make_elvises(pcity);
-  if (pcity->ppl_elvis == 0 || city_unhappy(pcity)) 
-    return;
-  tax_bonus = city_tax_bonus(pcity);
-  science_bonus = city_science_bonus(pcity);
-  
-  if (tax_bonus > science_bonus || ai_wants_no_science(city_owner(pcity))) {
-    make_taxmen(pcity);
-  } else {
-    make_scientists(pcity);
-  }
-
-  sync_cities();
-}
-
-/**************************************************************************
-...
-**************************************************************************/
-bool ai_fix_unhappy(struct city *pcity)
-{
-  if (!city_unhappy(pcity))
-    return TRUE;
-  while (city_unhappy(pcity)) {
-    if(ai_make_elvis(pcity) == 0) break;
-/*     city_refresh(pcity);         moved into ai_make_elvis for utility -- 
Syela */
-  }
-  return (!city_unhappy(pcity));
-}
-
-/**************************************************************************
   This function tries desperately to save a city from going under by
   revolt or starvation of food or resources. We do this by taking
   over resources held by nearby cities and disbanding units.
@@ -919,8 +742,8 @@
 
     if (acity && acity != pcity && acity->owner == pcity->owner)  {
       if (same_pos(acity->x, acity->y, x, y)) {
-       /* can't stop working city center */
-       continue;
+        /* can't stop working city center */
+        continue;
       }
       freelog(LOG_DEBUG, "%s taking over %s's square in (%d, %d)",
               pcity->name, acity->name, x, y);
@@ -934,9 +757,6 @@
     }
   } map_city_radius_iterate_end;
   auto_arrange_workers(pcity);
-  if (ai_fix_unhappy(pcity) && ai_fuzzy(pplayer, TRUE)) {
-    ai_scientists_taxmen(pcity);
-  }
 
   if (!CITY_EMERGENCY(pcity)) {
     freelog(LOG_EMERGENCY, "Emergency in %s resolved", pcity->name);
@@ -954,7 +774,6 @@
       /* in rare cases the _safe might be needed? --dwp */
       handle_unit_disband_safe(pplayer, &pack, &myiter);
       city_refresh(pcity);
-      (void) ai_fix_unhappy(pcity);
     }
   } unit_list_iterate_end;
 
@@ -971,9 +790,6 @@
     /* otherwise food total and stuff was wrong. -- Syela */
     city_refresh(acity);
     auto_arrange_workers(pcity);
-    if (ai_fix_unhappy(acity) && ai_fuzzy(pplayer, TRUE)) {
-      ai_scientists_taxmen(acity);
-    }
   } city_list_iterate_end;
 
   sync_cities();
Index: ai/aicity.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aicity.h,v
retrieving revision 1.19
diff -u -r1.19 aicity.h
--- ai/aicity.h 2003/07/14 11:34:53     1.19
+++ ai/aicity.h 2003/07/18 18:06:14
@@ -28,9 +28,6 @@
 Unit_Type_id ai_choose_defender_by_type(struct city *pcity,
                                         enum unit_move_type which);
 Unit_Type_id ai_choose_defender(struct city *pcity);
-int ai_make_elvis(struct city *pcity);
-void ai_scientists_taxmen(struct city *pcity);
-bool ai_fix_unhappy(struct city *pcity);
 
 enum ai_city_task { AICITY_NONE, AICITY_TECH, AICITY_TAX, AICITY_PROD};
 /* These are not used (well, except AICITY_NONE)  --dwp */
Index: ai/aihand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aihand.c,v
retrieving revision 1.85
diff -u -r1.85 aihand.c
--- ai/aihand.c 2003/07/14 21:37:03     1.85
+++ ai/aihand.c 2003/07/18 18:06:14
@@ -200,9 +200,6 @@
       city_list_iterate(pplayer->cities, acity) {
         generic_city_refresh(acity, TRUE, NULL);
         auto_arrange_workers(acity);
-        if (ai_fix_unhappy(acity)) {
-          ai_scientists_taxmen(acity);
-        }
       } city_list_iterate_end;
       city_list_iterate(pplayer->cities, pcity) {
         val += ai_eval_calc_city(pcity, ai);
@@ -243,9 +240,6 @@
     city_list_iterate(pplayer->cities, acity) {
       generic_city_refresh(acity, FALSE, NULL);
       auto_arrange_workers(acity);
-      if (ai_fix_unhappy(acity)) {
-        ai_scientists_taxmen(acity);
-      }
     } city_list_iterate_end;
     ai->govt_reeval = CLIP(5, city_list_size(&pplayer->cities), 20);
   }
Index: server/cityhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/cityhand.c,v
retrieving revision 1.122
diff -u -r1.122 cityhand.c
--- server/cityhand.c   2003/05/05 12:11:13     1.122
+++ server/cityhand.c   2003/07/18 18:06:15
@@ -112,6 +112,7 @@
     break;
   }
 
+  sanity_check_city(pcity);
   city_refresh(pcity);
   send_city_info(pplayer, pcity);
 }
@@ -141,6 +142,7 @@
     notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,
                     _("Game: You don't have a worker here.")); 
   }
+  sanity_check_city(pcity);
 }
 
 /**************************************************************************
@@ -180,6 +182,7 @@
   else 
     pcity->ppl_taxman--;
 
+  sanity_check_city(pcity);
   city_refresh(pcity);
   sync_cities();
 }
@@ -374,6 +377,7 @@
   change_build_target(pplayer, pcity, preq->build_id,
                      preq->is_build_id_unit_id, E_NOEVENT);
 
+  sanity_check_city(pcity);
   city_refresh(pcity);
   send_city_info(pplayer, pcity);
 }
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.221
diff -u -r1.221 citytools.c
--- server/citytools.c  2003/07/17 16:42:59     1.221
+++ server/citytools.c  2003/07/18 18:06:15
@@ -954,6 +954,7 @@
     build_free_palace(pgiver, pcity->name);
   }
 
+  sanity_check_city(pcity);
   sync_cities();
 }
 
@@ -1046,6 +1047,8 @@
     if (!can_unit_continue_current_activity(punit))
       handle_unit_activity_request(punit, ACTIVITY_IDLE);
   } unit_list_iterate_end;
+
+  sanity_check_city(pcity);
 }
 
 /**************************************************************************
@@ -1997,7 +2000,8 @@
   case C_TILE_WORKER:
     if (!is_available) {
       server_set_tile_city(pcity, city_x, city_y, C_TILE_UNAVAILABLE);
-      add_adjust_workers(pcity); /* will place the displaced */
+      pcity->ppl_elvis++; /* keep city sanity */
+      auto_arrange_workers(pcity); /* will place the displaced */
       city_refresh(pcity);
       send_city_info(NULL, pcity);
     }
Index: server/cityturn.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/cityturn.c,v
retrieving revision 1.217
diff -u -r1.217 cityturn.c
--- server/cityturn.c   2003/07/18 15:51:01     1.217
+++ server/cityturn.c   2003/07/18 18:06:16
@@ -44,8 +44,12 @@
 #include "unittools.h"
 #include "unithand.h"
 
+#include "cm.h"
+
 #include "advdomestic.h"
 #include "aicity.h"
+#include "aidata.h"
+#include "ailog.h"
 #include "aitools.h"           /* for ai_advisor_choose_building/ai_choice */
 
 #include "cityturn.h"
@@ -68,17 +72,12 @@
 static void obsolete_building_test(struct city *pcity, int b1, int b2);
 static void pay_for_buildings(struct player *pplayer, struct city *pcity);
 
-static void sanity_check_city(struct city *pcity);
-
 static bool disband_city(struct city *pcity);
 
 static void define_orig_production_values(struct city *pcity);
 static void update_city_activity(struct player *pplayer, struct city *pcity);
 static void nullify_caravan_and_disband_plus(struct city *pcity);
 
-static void worker_loop(struct city *pcity, int *foodneed,
-                       int *prodneed, int *workers);
-
 static void advisor_choose_build(struct player *pplayer, struct city *pcity);
 
 /**************************************************************************
@@ -143,174 +142,119 @@
   } city_list_iterate_end;
 }
 
-/**************************************************************************
-You need to call sync_cities for the affected cities to be synced with the
-client.
-**************************************************************************/
-static void worker_loop(struct city *pcity, int *foodneed,
-                       int *prodneed, int *workers)
-{
-  int bx, by, best, cur;
-  int conflict[5][5];
-  int e, pwr, luxneed = 0; /* I should have thought of this earlier, it is so 
simple */
-
-  city_refresh(pcity);
-  luxneed = 2 * (2 * pcity->ppl_angry[4] + pcity->ppl_unhappy[4] -
-                pcity->ppl_happy[4]);
-  pwr = (2 * city_tax_bonus(pcity)) / 100;
-  luxneed += pwr * pcity->ppl_elvis;
-  if (luxneed < 0) luxneed = 0;
-
-  e = (luxneed + pwr - 1) / pwr;
-  if (e > (*workers - 1)) e = *workers - 1; /* stops the repeated emergencies. 
-- Syela */
-
-/* If I were real clever, I would optimize trade by luxneed and tax_bonus -- 
Syela */
-
-  *foodneed -= 2 * (*workers - 1 - e);
-  *prodneed -= (*workers - 1 - e);
-
-  freelog(LOG_DEBUG, "%s, %d workers, %d luxneed, %d e",
-         pcity->name, *workers, luxneed, e);
-  freelog(LOG_DEBUG, "%s, a4 %d u4 %d h4 %d pwr %d elv %d",
-         pcity->name, pcity->ppl_angry[4], pcity->ppl_unhappy[4],
-         pcity->ppl_happy[4], pwr, pcity->ppl_elvis);
-
-  if (city_happy(pcity) && wants_to_be_bigger(pcity) && pcity->size > 4)
-    *foodneed += 1;
-
-  freelog(LOG_DEBUG, "%s, foodneed %d prodneed %d",
-         pcity->name, *foodneed, *prodneed);
-
-  /* better than nothing, not as good as a global worker allocation -- Syela */
-  memset(conflict, 0, sizeof(conflict));
-  city_map_checked_iterate(pcity->x, pcity->y, cx, cy, mx, my) {
-      conflict[cx][cy] = -1 - minimap[mx][my];
-  } city_map_checked_iterate_end;
-
-  do {
-    /* try to work near the city */
-    bx = 0;
-    by = 0;
-    best = 0;
-
-    city_map_iterate_outwards(x, y) {
-      if (can_place_worker_here(pcity, x, y)
-         && city_can_work_tile(pcity, x, y)) {
-        cur = city_tile_value(pcity,x,y,*foodneed,*prodneed) - conflict[x][y];
-       if (cur > best) {
-         bx = x;
-         by = y;
-         best = cur;
-       }
-      }
-    } city_map_iterate_outwards_end;
-    if (bx != 0 || by != 0) {
-      server_set_worker_city(pcity, bx, by);
-      (*workers)--; /* amazing what this did with no parens! -- Syela */
-      *foodneed -= city_get_food_tile(bx,by,pcity) - 2;
-      *prodneed -= city_get_shields_tile(bx,by,pcity) - 1;
-    }
-  } while(*workers != 0 && (bx != 0 || by != 0));
-  *foodneed += 2 * (*workers - 1 - e);
-  *prodneed += (*workers - 1 - e);
-  if (*prodneed > 0) {
-    freelog(LOG_DEBUG, "Ignored prodneed? in %s (%d)",
-        pcity->name, *prodneed);
-  }
-}
-
 /**************************************************************************
-You need to call sync_cities for the affected cities to be synced with the
-client.
+  Hard check
 **************************************************************************/
-void add_adjust_workers(struct city *pcity)
+void sanity_check_city(struct city *pcity)
 {
-  int workers=pcity->size;
-  int iswork=0;
-  int toplace;
-  int foodneed;
-  int prodneed = 0;
+  int worker = 0;
 
   city_map_iterate(x, y) {
-    if (get_worker_city(pcity, x, y)==C_TILE_WORKER) 
-      iswork++;
+    if (get_worker_city(pcity, x, y) == C_TILE_WORKER) {
+      worker++;
+    }
   } city_map_iterate_end;
-  iswork--; /* City center */
-
-  if (iswork+city_specialists(pcity)>workers) {
-    freelog(LOG_ERROR, "Encountered an inconsistency in "
-           "add_adjust_workers() for city %s", pcity->name);
-    auto_arrange_workers(pcity);
-    sync_cities();
-    return;
+  if (worker + city_specialists(pcity) != pcity->size + 1) {
+    die("%s is illegal (size%d w%d e%d t%d s%d)",
+        pcity->name, pcity->size, worker, pcity->ppl_elvis,
+        pcity->ppl_taxman, pcity->ppl_scientist);
   }
-
-  if (iswork + city_specialists(pcity) == workers) {
-    return;
-  }
-
-  toplace = workers-(iswork+city_specialists(pcity));
-  foodneed = -pcity->food_surplus;
-  prodneed = -pcity->shield_surplus;
-
-  worker_loop(pcity, &foodneed, &prodneed, &toplace);
-
-  pcity->ppl_elvis+=toplace;
-  return;
 }
 
 /**************************************************************************
-You need to call sync_cities for the affected cities to be synced with the
-client.
+  You need to call sync_cities for the affected cities to be synced with 
+  the client.
 **************************************************************************/
 void auto_arrange_workers(struct city *pcity)
 {
-  struct government *g = get_gov_pcity(pcity);
-  int workers = pcity->size;
-  int taxwanted,sciwanted;
-  int foodneed, prodneed;
+  struct cm_parameter cmp;
+  struct cm_result cmr;
+  struct player *pplayer = city_owner(pcity);
+  struct ai_data *ai = ai_data_get(pplayer);
 
-  city_map_iterate(x, y) {
-    if (get_worker_city(pcity, x, y) == C_TILE_WORKER
-       && !is_city_center(x, y))
+  sanity_check_city(pcity);
+  cm_clear_cache(pcity);
+
+  cmp.require_happy = FALSE;
+  cmp.factor_target = FT_SURPLUS;
+
+  /* WAGs. FIXME: Adjust & remove kludges */
+  cmp.factor[FOOD] = ai->food_priority - 9;
+  cmp.factor[SHIELD] = ai->shield_priority - 7;
+  cmp.factor[TRADE] = 10;
+  cmp.factor[GOLD] = ai->gold_priority - 11;
+  cmp.factor[LUXURY] = ai->luxury_priority;
+  cmp.factor[SCIENCE] = ai->science_priority + 3;
+  cmp.happy_factor = ai->happy_priority - 1;
+
+  cmp.minimal_surplus[FOOD] = 1;
+  cmp.minimal_surplus[SHIELD] = 1;
+  cmp.minimal_surplus[TRADE] = 1;
+  cmp.minimal_surplus[GOLD] = 0;
+  cmp.minimal_surplus[LUXURY] = 0;
+  cmp.minimal_surplus[SCIENCE] = 0;
+
+  cm_query_result(pcity, &cmp, &cmr);
+
+  if (!cmr.found_a_valid) {
+    cmp.minimal_surplus[FOOD] = 0;
+    cmp.minimal_surplus[SHIELD] = 0;
+    cmp.minimal_surplus[TRADE] = 0;
+    cm_query_result(pcity, &cmp, &cmr);
+  }
+
+  if (!cmr.found_a_valid && !pplayer->ai.control) {
+    /* For human players: Try very hard to avoid negative
+     * production, even allow disorder. */
+    cmp.require_happy = FALSE;
+    cmp.minimal_surplus[FOOD] = -(pcity->food_stock);
+    cmp.minimal_surplus[TRADE] = -10;
+    cmp.minimal_surplus[GOLD] = -20;
+    cm_query_result(pcity, &cmp, &cmr);
+  }
+
+  if (!cmr.found_a_valid && pplayer->ai.control) {
+    /* AI: Try starvation and trade deficit but no loss of units. */
+    cmp.minimal_surplus[FOOD] = -(pcity->food_stock);
+    cmp.minimal_surplus[TRADE] = -1;
+    cmp.minimal_surplus[GOLD] = -10;
+    cm_query_result(pcity, &cmp, &cmr);
+  }
+
+  if (!cmr.found_a_valid) {
+    CITY_LOG(LOG_DEBUG, pcity, "emergency management");
+    cmp.minimal_surplus[FOOD] = -20;
+    cmp.minimal_surplus[SHIELD] = -20;
+    cmp.minimal_surplus[TRADE] = -20;
+    cmp.minimal_surplus[GOLD] = -20;
+    cmp.minimal_surplus[LUXURY] = -20;
+    cmp.minimal_surplus[SCIENCE] = -20;
+    cmp.require_happy = FALSE;
+
+    cm_query_result(pcity, &cmp, &cmr);
+
+    assert(cmr.found_a_valid);
+  }
+
+  /* Now apply results */
+  city_map_checked_iterate(pcity->x, pcity->y, x, y, mapx, mapy) {
+    if (pcity->city_map[x][y] == C_TILE_WORKER
+        && !cmr.worker_positions_used[x][y]
+        && !is_city_center(x, y)) {
       server_remove_worker_city(pcity, x, y);
-  } city_map_iterate_end;
-  
-  foodneed=(pcity->size *2 -city_get_food_tile(2,2, pcity)) + 
settler_eats(pcity);
-  prodneed = 0;
-  prodneed -= city_get_shields_tile(2,2,pcity);
-  prodneed -= citygov_free_shield(pcity, g);
-
-  unit_list_iterate(pcity->units_supported, this_unit) {
-    int shield_cost = utype_shield_cost(unit_type(this_unit), g);
-    if (shield_cost > 0) {
-      prodneed += shield_cost;
     }
-  }
-  unit_list_iterate_end;
-  
-  taxwanted=pcity->ppl_taxman;
-  sciwanted=pcity->ppl_scientist;
-  pcity->ppl_taxman=0;
-  pcity->ppl_scientist=0;
-  pcity->ppl_elvis=0;
-
-  worker_loop(pcity, &foodneed, &prodneed, &workers);
-
-  while (workers > 0 && (taxwanted > 0 || sciwanted > 0)) {
-    if (taxwanted > 0) {
-      workers--;
-      pcity->ppl_taxman++;
-      taxwanted--;
-    } 
-    if (sciwanted > 0 && workers > 0) {
-      workers--;
-      pcity->ppl_scientist++;
-      sciwanted--;
+    if (pcity->city_map[x][y] != C_TILE_WORKER
+        && cmr.worker_positions_used[x][y]
+        && !is_city_center(x, y)) {
+      server_set_worker_city(pcity, x, y);
     }
-  }
-  pcity->ppl_elvis=workers;
+  } city_map_checked_iterate_end;
+  pcity->ppl_elvis = cmr.entertainers;
+  pcity->ppl_scientist = cmr.scientists;
+  pcity->ppl_taxman = cmr.taxmen;
 
+  sanity_check_city(pcity);
+
   city_refresh(pcity);
 }
 
@@ -431,6 +375,10 @@
 **************************************************************************/
 void city_reduce_size(struct city *pcity, int pop_loss)
 {
+  if (pop_loss == 0) {
+    return;
+  }
+
   if (pcity->size <= pop_loss) {
     remove_city_from_minimap(pcity->x, pcity->y);
     remove_city(pcity);
@@ -446,9 +394,9 @@
   }
 
   while (pop_loss > 0 && city_specialists(pcity) > 0) {
-    if(pcity->ppl_taxman > 0) {
+    if (pcity->ppl_taxman > 0) {
       pcity->ppl_taxman--;
-    } else if(pcity->ppl_scientist > 0) {
+    } else if (pcity->ppl_scientist > 0) {
       pcity->ppl_scientist--;
     } else {
       assert(pcity->ppl_elvis > 0);
@@ -462,9 +410,20 @@
     city_refresh(pcity);
     send_city_info(city_owner(pcity), pcity);
   } else {
+    /* Take it out on workers */
+    city_map_iterate(x, y) {
+      if (get_worker_city(pcity, x, y) == C_TILE_WORKER
+          && !is_city_center(x, y) && pop_loss > 0) {
+        server_remove_worker_city(pcity, x, y);
+        pop_loss--;
+      }
+    } city_map_iterate_end;
+    /* Then rearrange workers */
+    assert(pop_loss == 0);
     auto_arrange_workers(pcity);
     sync_cities();
   }
+  sanity_check_city(pcity);
 }
 
 /**************************************************************************
@@ -548,18 +507,16 @@
     }
 
   } else {
-    add_adjust_workers(pcity);
+    pcity->ppl_taxman++; /* or else city is !sane */
+    auto_arrange_workers(pcity);
   }
 
   city_refresh(pcity);
 
-  if (powner->ai.control) /* don't know if we need this -- Syela */
-    if (ai_fix_unhappy(pcity))
-      ai_scientists_taxmen(pcity);
-
   notify_player_ex(powner, pcity->x, pcity->y, E_CITY_GROWTH,
                    _("Game: %s grows to size %d."), pcity->name, pcity->size);
 
+  sanity_check_city(pcity);
   sync_cities();
 }
 
@@ -1177,28 +1134,6 @@
 }
 
 /**************************************************************************
-...
-**************************************************************************/
-static void sanity_check_city(struct city *pcity)
-{
-  int size=pcity->size;
-  int iswork=0;
-  city_map_iterate(x, y) {
-    if (get_worker_city(pcity, x, y)==C_TILE_WORKER) 
-       iswork++;
-  } city_map_iterate_end;
-  iswork--;
-  if (iswork+city_specialists(pcity)!=size) {
-    freelog(LOG_ERROR,
-           "%s is bugged: size:%d workers:%d elvis: %d tax:%d sci:%d",
-           pcity->name, size, iswork, pcity->ppl_elvis,
-           pcity->ppl_taxman, pcity->ppl_scientist); 
-    auto_arrange_workers(pcity);
-    sync_cities();
-  }
-}
-
-/**************************************************************************
   Returns the cost to incite a city. This depends on the size of the city,
   the number of happy, unhappy and angry citizens, whether it is
   celebrating, how close it is to the capital, how many units it has and
@@ -1326,12 +1261,6 @@
   struct government *g = get_gov_pcity(pcity);
 
   city_refresh(pcity);
-
-  /* the AI often has widespread disorder when the Gardens or Oracle
-     become obsolete.  This is a quick hack to prevent this.  980805 -- Syela 
*/
-  while (pplayer->ai.control && city_unhappy(pcity)) {
-    if (ai_make_elvis(pcity) == 0) break;
-  } /* putting this lower in the routine would basically be cheating. -- Syela 
*/
 
   /* reporting of celebrations rewritten, copying the treatment of disorder 
below,
      with the added rapture rounds count.  991219 -- Jing */
Index: server/cityturn.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/cityturn.h,v
retrieving revision 1.28
diff -u -r1.28 cityturn.h
--- server/cityturn.h   2002/12/18 17:36:20     1.28
+++ server/cityturn.h   2003/07/18 18:06:16
@@ -21,11 +21,12 @@
 struct unit;
 struct conn_list;
 
+void sanity_check_city(struct city *pcity);
+
 void city_refresh(struct city *pcity);          /* call if city has changed */
 void global_city_refresh(struct player *pplayer); /* tax/govt changed */
 
 void auto_arrange_workers(struct city *pcity); /* will arrange the workers */
-void add_adjust_workers(struct city *pcity);   /* will add workers */
 
 void city_reduce_size(struct city *pcity, int pop_loss);
 void send_global_city_turn_notifications(struct conn_list *dest);
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.130
diff -u -r1.130 srv_main.c
--- server/srv_main.c   2003/07/13 01:51:11     1.130
+++ server/srv_main.c   2003/07/18 18:06:16
@@ -91,6 +91,8 @@
 #include "unithand.h"
 #include "unittools.h"
 
+#include "cm.h"
+
 #include "advmilitary.h"
 #include "aidata.h"
 #include "aihand.h"
@@ -1582,6 +1584,7 @@
 
   /* Run server loop */
   while (TRUE) {
+    cm_init(); /* initialize CM */
     srv_loop();
     if (game.timeout == -1) {
       server_quit();
@@ -1804,6 +1807,7 @@
 **************************************************************************/
 void server_game_free()
 {
+  cm_free();
   players_iterate(pplayer) {
     player_map_free(pplayer);
   } players_iterate_end;
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.264
diff -u -r1.264 unithand.c
--- server/unithand.c   2003/07/17 18:56:52     1.264
+++ server/unithand.c   2003/07/18 18:06:16
@@ -536,7 +536,7 @@
 
   assert(unit_pop_value(punit->type) > 0);
   pcity->size += unit_pop_value(punit->type);
-  add_adjust_workers(pcity);
+  auto_arrange_workers(pcity);
   wipe_unit(punit);
   send_city_info(NULL, pcity);
   notify_player_ex(pplayer, pcity->x, pcity->y, E_NOEVENT,

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