Complete.Org: Mailing Lists: Archives: freeciv-dev: June 2004:
[Freeciv-Dev] (PR#9128) tax code changes
Home

[Freeciv-Dev] (PR#9128) tax code changes

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#9128) tax code changes
From: "Per Inge Mathisen" <per@xxxxxxxxxxx>
Date: Sun, 27 Jun 2004 06:28:08 -0700
Reply-to: rt@xxxxxxxxxxx

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

This patch depends on PR#9127.

CHANGES:
 - AI does rapture/celebration again.
 - AI will now prefer luxuries to tax when we have maxrate spillover from
science.
 - We no longer will crash if maxrate is less than 50% (I think).
 - The tax code should be significantly faster if we do not have republic
or democracy, and significantly slower if we do. Not that this code makes
much of a difference in the big picture anyway.

AI cities grow much faster now, and a general luxury code (see TODO in
code) is really missed, as the AI only has elvises at its disposal to deal
with the unhappiness that ensues from such growth.

  - Per

Index: ai/aidata.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.h,v
retrieving revision 1.13
diff -u -r1.13 aidata.h
--- ai/aidata.h 20 Jun 2004 07:41:14 -0000      1.13
+++ ai/aidata.h 27 Jun 2004 13:12:56 -0000
@@ -123,6 +123,7 @@
       int req;        /* The tech requirement for the ideal gov */
     } govt;
     int revolution;   /* The best gov of the now available */
+    bool celebration; /* Are we trying to celebrate? */
   } goal;
 };
 
Index: ai/aihand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aihand.c,v
retrieving revision 1.88
diff -u -r1.88 aihand.c
--- ai/aihand.c 25 Jun 2004 23:43:01 -0000      1.88
+++ ai/aihand.c 27 Jun 2004 13:12:56 -0000
@@ -76,86 +76,140 @@
 }
 
 /**************************************************************************
-  Refresh all cities of the given player.  This function is only used by 
-  AI so we keep it here. 
-
-  Do not send_unit_info because it causes client to blink.
-**************************************************************************/
-static void ai_player_cities_refresh(struct player *pplayer)
-{
-  city_list_iterate(pplayer->cities, pcity) {
-    generic_city_refresh(pcity, TRUE, NULL);
-  } city_list_iterate_end;
-}
-
-/**************************************************************************
   Set tax/science/luxury rates.
 
-  TODO: Add support for luxuries: select the luxury rate at which all 
-  cities are content and the trade output (minus what is consumed by 
-  luxuries) is maximal.
+  TODO: Add general support for luxuries: select the luxury rate at which 
+  all cities are content and the trade output (minus what is consumed by 
+  luxuries) is maximal.  For this we need some more information from the 
+  city management code.
 
   TODO: Audit the use of pplayer->ai.maxbuycost in the code elsewhere,
   then add support for it here.
-
-  TODO: Add support for rapture, needs to be coordinated for entire
-  empire.
 **************************************************************************/
 static void ai_manage_taxes(struct player *pplayer) 
 {
   int maxrate = (ai_handicap(pplayer, H_RATES) 
                  ? get_government_max_rate(pplayer->government) : 100);
+  bool celebrate = TRUE;
+  bool no_science = ai_wants_no_science(pplayer);
+  int can_celebrate = 0, total_cities = 0;
+  struct government *g = get_gov_pplayer(pplayer);
+  struct ai_data *ai = ai_data_get(pplayer);
 
-  /* Otherwise stupid problems arise */
-  assert(maxrate >= 50);
-
-  /* Add proper support for luxury here */
-  pplayer->economic.luxury = 0;
-  /* After this moment don't touch luxury, it's optimal! */
-
-  if (ai_wants_no_science(pplayer)) {
-    /* Maximum tax, leftovers into science */
-    pplayer->economic.tax = MIN(maxrate, 100 - pplayer->economic.luxury);
-    pplayer->economic.science = (100 - pplayer->economic.tax
-                                 - pplayer->economic.luxury);
-    ai_player_cities_refresh(pplayer);
-  } else {
-    /* Set tax to the bare minimum which allows positive balance */
-
-    /* First set tax to the minimal available number */
-    pplayer->economic.science = MIN(maxrate, 100 - pplayer->economic.luxury);
-    pplayer->economic.tax = (100 - pplayer->economic.science
-                             - pplayer->economic.luxury);
-    ai_player_cities_refresh(pplayer);
-
-    /* Now find the minimum tax with positive balance */
-    while(pplayer->economic.tax < maxrate 
-          && pplayer->economic.science > 10) {
-
-      if (player_get_expected_income(pplayer) < 0) {
-        pplayer->economic.tax += 10;
-        pplayer->economic.science -= 10;
-        ai_player_cities_refresh(pplayer);
+  /* Find minimum tax rate which gives us a positive balance. We assume
+   * that we want science most and luxuries least here, and reverse or 
+   * modify this assumption later. on */
+
+  /* First set tax to the minimal available number */
+  pplayer->economic.science = maxrate; /* Assume we want science here */
+  pplayer->economic.tax = MAX(0, 100 - maxrate * 2); /* If maxrate < 50% */
+  pplayer->economic.luxury = (100 - pplayer->economic.science
+                             - pplayer->economic.tax); /* Spillover */
+
+  /* Now find the minimum tax with positive balance */
+  while(pplayer->economic.tax < maxrate
+        && (pplayer->economic.science > 0
+            || pplayer->economic.luxury > 0)) {
+
+    if (player_get_expected_income(pplayer) < 0) {
+      pplayer->economic.tax += 10;
+      if (pplayer->economic.luxury > 0) {
+        pplayer->economic.luxury -= 10;
       } else {
-        /* Ok, got positive balance */
-        if (pplayer->economic.gold < ai_gold_reserve(pplayer)) {
-          /* Need to refill coffers, increase tax a bit */
-          pplayer->economic.tax += 10;
+        pplayer->economic.science -= 10;
+      }
+    } else {
+      /* Ok, got positive balance */
+      if (pplayer->economic.gold < ai_gold_reserve(pplayer)) {
+        /* Need to refill coffers, increase tax a bit */
+        pplayer->economic.tax += 10;
+        if (pplayer->economic.luxury > 0) {
+          pplayer->economic.luxury -= 10;
+        } else {
           pplayer->economic.science -= 10;
-          ai_player_cities_refresh(pplayer);
         }
-        /* Done! Break the while loop */
-        break;
       }
+      /* Done! Break the while loop */
+      break;
+    }
+  }
+
+  /* Should we celebrate? */
+  if (government_has_flag(g, G_RAPTURE_CITY_GROWTH)) {
+    int luxrate = pplayer->economic.luxury;
+    int scirate = pplayer->economic.science;
+
+    while (pplayer->economic.luxury < maxrate
+           && pplayer->economic.science > 0) {
+      pplayer->economic.luxury += 10;
+      pplayer->economic.science -= 10;
+    }
 
+    city_list_iterate(pplayer->cities, pcity) {
+      pcity->ai.celebrate = TRUE;
+      /* TODO: ideally the city management code should set a flag
+       * in each city telling us whether it is capable of making
+       * the city celebrate, then we do not need this CPU burn,
+       * and can use this function in best_government calculation
+       * directly. */
+      auto_arrange_workers(pcity); /* have to burn some CPU here */
+
+      total_cities++;
+
+      if (!city_happy(pcity)
+          || pcity->food_surplus <= 0
+          || pcity->size < g->rapture_size
+          || (pcity->size >= game.aqueduct_size
+              && !city_got_building(pcity, B_AQUEDUCT))
+          || (pcity->size >= game.sewer_size
+              && !city_got_building(pcity, B_SEWER))) {
+        pcity->ai.celebrate = FALSE;
+      } else {
+        can_celebrate++;
+      }
+    } city_list_iterate_end;
+    /* If more than half our cities can celebrate, go for it! */
+    celebrate = (can_celebrate * 2 > total_cities);
+    if (celebrate) {
+      freelog(LOG_DEBUG, "*** %s CELEBRATES! ***", pplayer->name);
+    } else {
+      pplayer->economic.luxury = luxrate;
+      pplayer->economic.science = scirate;
     }
+  }
+  if (!celebrate) {
+    city_list_iterate(pplayer->cities, pcity) {
+      if (pcity->ai.celebrate == TRUE) {
+        pcity->ai.celebrate = FALSE;
+        auto_arrange_workers(pcity);
+      }
+    } city_list_iterate_end;
+  }
+  ai->goal.celebration = celebrate;
 
+  if (!celebrate && pplayer->economic.luxury < maxrate) {
+    /* TODO: Add general luxury code here. City management code should
+     * report to us what the optimal luxury rates are for each city,
+     * that is, at which point we will produce more by spending some
+     * more on luxury, and we should adjust to the median. */
   }
 
-  freelog(LOG_DEBUG, "%s rates: Sci %d Lux%d Tax %d NetIncome %d",
-          pplayer->name, pplayer->economic.science,
+  /* Ok, we now have the desired tax and luxury rates. Do we really want
+   * science? If not, swap it with tax if it is bigger. */
+  if (no_science && pplayer->economic.science > pplayer->economic.tax) {
+    int science = pplayer->economic.science;
+    /* Swap science and tax */
+    pplayer->economic.science = pplayer->economic.tax;
+    pplayer->economic.tax = science;
+  }
+
+  assert(pplayer->economic.tax + pplayer->economic.luxury 
+         + pplayer->economic.science == 100);
+  freelog(LOG_NORMAL, "%s rates: Sci %d Lux%d Tax %d NetIncome %d "
+          "celeb=(%d/%d)", pplayer->name, pplayer->economic.science,
           pplayer->economic.luxury, pplayer->economic.tax,
-          player_get_expected_income(pplayer));
+          player_get_expected_income(pplayer), can_celebrate, total_cities);
+  send_player_info(pplayer, pplayer);
 }
 
 /**************************************************************************
@@ -167,6 +221,8 @@
   necessary tech more.  The best of the available governments is recorded 
   in goal.revolution.  We record the want of each government, and only
   recalculate this data every ai->govt_reeval_turns turns.
+
+  Note: Call this _before_ doing taxes!
 **************************************************************************/
 void ai_best_government(struct player *pplayer)
 {
@@ -197,6 +253,7 @@
        * this is a rather big CPU operation, we'd rather not. */
       check_player_government_rates(pplayer);
       city_list_iterate(pplayer->cities, acity) {
+        acity->ai.celebrate = FALSE;
         generic_city_refresh(acity, TRUE, NULL);
         auto_arrange_workers(acity);
       } city_list_iterate_end;
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.149
diff -u -r1.149 city.h
--- common/city.h       14 Jun 2004 23:43:08 -0000      1.149
+++ common/city.h       27 Jun 2004 13:12:58 -0000
@@ -190,6 +190,7 @@
                                    wonders wisely */
   int distance_to_wonder_city;  /* wondercity will set this for us, 
                                    avoiding paradox */
+  bool celebrate;               /* try to celebrate this city */
 
   /* Used for caching when settlers evalueate which tile to improve,
      and when we place workers. */
Index: common/player.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.c,v
retrieving revision 1.139
diff -u -r1.139 player.c
--- common/player.c     25 Jun 2004 23:43:01 -0000      1.139
+++ common/player.c     27 Jun 2004 13:12:58 -0000
@@ -402,7 +402,8 @@
 
 /**************************************************************************
   Return the expected net income of the player this turn.  This includes
-  tax revenue and upkeep, but not one-time purchases or found gold.
+  tax revenue and upkeep, but not one-time purchases or found gold.  Does
+  not depend on pcity->total_tax being set correctly.
 **************************************************************************/
 int player_get_expected_income(struct player *pplayer)
 {
@@ -410,8 +411,13 @@
 
   /* City income/expenses. */
   city_list_iterate(pplayer->cities, pcity) {
-    /* Tax income. */
-    income += pcity->tax_total;
+    int lux, tax, sci, trade = pcity->trade_prod;
+
+    get_tax_income(pplayer, trade, &sci, &lux, &tax);
+    income += tax;
+    income += pcity->specialists[SP_TAXMAN]
+            * game.rgame.specialists[SP_TAXMAN].bonus;
+    income += get_city_tithes_bonus(pcity);
 
     /* Improvement upkeep. */
     impr_type_iterate(impr_id) {
Index: server/cityturn.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/cityturn.c,v
retrieving revision 1.249
diff -u -r1.249 cityturn.c
--- server/cityturn.c   29 May 2004 20:34:31 -0000      1.249
+++ server/cityturn.c   27 Jun 2004 13:12:59 -0000
@@ -182,7 +182,11 @@
   cmp.factor[SHIELD] = 5;
   cmp.factor[TRADE] = 0; /* Trade only provides gold/science. */
   cmp.factor[GOLD] = 2;
-  cmp.factor[LUXURY] = 0; /* Luxury only influences happiness. */
+  if (pplayer->ai.control && pcity->ai.celebrate) {
+    cmp.factor[LUXURY] = 9; /* Just below food */
+  } else {
+    cmp.factor[LUXURY] = 0; /* Luxury only influences happiness. */
+  }
   cmp.factor[SCIENCE] = 2;
   cmp.happy_factor = 0;
 
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.221
diff -u -r1.221 city.c
--- common/city.c       25 Jun 2004 23:29:59 -0000      1.221
+++ common/city.c       27 Jun 2004 13:15:11 -0000
@@ -2719,6 +2766,7 @@
   pcity->ai.invasion = 0;
   pcity->ai.bcost = 0;
   pcity->ai.attack = 0;
+  pcity->ai.celebrate = FALSE;
 
   pcity->corruption = 0;
   pcity->shield_waste = 0;

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