Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2003:
[Freeciv-Dev] Re: (PR#2650) Overflow in military_amortize
Home

[Freeciv-Dev] Re: (PR#2650) Overflow in military_amortize

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients:;
Subject: [Freeciv-Dev] Re: (PR#2650) Overflow in military_amortize
From: "Gregory Berkolaiko via RT" <rt@xxxxxxxxxxxxxx>
Date: Wed, 1 Jan 2003 04:39:29 -0800
Reply-to: rt@xxxxxxxxxxxxxx

Quoting "Per I. Mathisen via RT" <rt@xxxxxxxxxxxxxx>:

> 
> On Fri, 27 Dec 2002, Gregory Berkolaiko via RT wrote:
> > > I know that. Where is the error?
> ...
> > But the maths mistake is there, unless I am completely mad.
> >  time = cost / production
> 
> Ah, yes. You'll fix before committing, I suppose.

I have fixed it.  Also, I moved military_amortize to aitools (it doesn't have
any strong connections with units and aiunit is overinflated as it is) and
changed the  signature of create_unit_virtual (pass it a valid city always, it
is used to determine coordinates of the unit).

I run an autogame, it was ok, AI was using units as usual.

Unless there are objections, the patch will be committed soon.

G.



? saves
Index: ai/advmilitary.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/advmilitary.c,v
retrieving revision 1.127
diff -u -r1.127 advmilitary.c
--- ai/advmilitary.c    2002/12/31 18:15:49     1.127
+++ ai/advmilitary.c    2003/01/01 12:15:22
@@ -942,7 +942,7 @@
       desire -= move_time * (unhap ? SHIELD_WEIGHTING + 2 * TRADE_WEIGHTING
                              : SHIELD_WEIGHTING);
 
-      want = military_amortize(desire, MAX(1, move_time),
+      want = military_amortize(pplayer, pcity, desire, MAX(1, move_time),
                                bcost_balanced + needferry);
       
       if (want > 0) {
@@ -1188,7 +1188,8 @@
   }
   want -= move_time * (unhap ? SHIELD_WEIGHTING + 2 * TRADE_WEIGHTING 
                      : SHIELD_WEIGHTING);
-  want = military_amortize(want, MAX(1, move_time), bcost_bal + needferry);
+  want = military_amortize(pplayer, pcity, want, MAX(1, move_time), 
+                           bcost_bal + needferry);
   
   if (myunit->id != 0) {
     freelog(LOG_ERROR, "ERROR: Non-virtual unit in kill_something_with");
@@ -1234,7 +1235,7 @@
   struct unit *aunit = NULL;
   struct city *acity = NULL;
 
-  virtualunit = create_unit_virtual(pplayer, pcity->x, pcity->y, unit_type,
+  virtualunit = create_unit_virtual(pplayer, pcity, unit_type,
                                     do_make_unit_veteran(pcity, unit_type));
 
   if (choice->want < 100) {
@@ -1415,7 +1416,7 @@
      before we mung the seamap */
   unit_type = ai_choose_attacker(pcity, SEA_MOVING);
   if (unit_type >= 0) {
-    virtualunit = create_unit_virtual(pplayer, pcity->x, pcity->y, unit_type,
+    virtualunit = create_unit_virtual(pplayer, pcity, unit_type,
                               player_knows_improvement_tech(pplayer, B_PORT));
     kill_something_with(pplayer, pcity, virtualunit, choice);
     destroy_unit_virtual(virtualunit);
@@ -1424,8 +1425,7 @@
   /* Consider a land attacker */
   unit_type = ai_choose_attacker(pcity, LAND_MOVING);
   if (unit_type >= 0) {
-    virtualunit = create_unit_virtual(pplayer, pcity->x, pcity->y, unit_type,
-                                      TRUE); /* why assume veteran? -- Per */
+    virtualunit = create_unit_virtual(pplayer, pcity, unit_type, TRUE);
     kill_something_with(pplayer, pcity, virtualunit, choice);
     destroy_unit_virtual(virtualunit);
   }
Index: ai/aiair.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiair.c,v
retrieving revision 1.6
diff -u -r1.6 aiair.c
--- ai/aiair.c  2002/12/22 18:14:43     1.6
+++ ai/aiair.c  2003/01/01 12:15:22
@@ -144,7 +144,9 @@
   profit = kill_desire(victim_cost, unit_attack, unit_cost, victim_defence, 1) 
     - SHIELD_WEIGHTING + 2 * TRADE_WEIGHTING;
   if (profit > 0) {
-    profit = military_amortize(profit, sortie_time, balanced_cost);
+    profit = military_amortize(unit_owner(punit), 
+                               find_city_by_id(punit->homecity),
+                               profit, sortie_time, balanced_cost);
     freelog(LOG_DEBUG, 
            "%s at (%d, %d) is a worthy target with profit %d", 
            unit_type(pdefender)->name, dest_x, dest_y, profit);
@@ -409,7 +411,7 @@
     if (get_unit_type(u_type)->move_type != AIR_MOVING) continue;
     if (can_build_unit(pcity, u_type)) {
       struct unit *virtual_unit = 
-       create_unit_virtual(pplayer, pcity->x, pcity->y, u_type, TRUE);
+       create_unit_virtual(pplayer, pcity, u_type, TRUE);
       int profit = find_something_to_bomb(virtual_unit, pcity->x, pcity->y);
       if (profit > choice->want){
        /* Update choice */
Index: ai/aidata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.c,v
retrieving revision 1.6
diff -u -r1.6 aidata.c
--- ai/aidata.c 2002/12/28 20:36:18     1.6
+++ ai/aidata.c 2003/01/01 12:15:22
@@ -178,10 +178,13 @@
 
   ai->stats.workers = fc_calloc(map.num_continents + 1, sizeof(int));
   ai->stats.cities = fc_calloc(map.num_continents + 1, sizeof(int));
+  ai->stats.average_production = 0;
   city_list_iterate(pplayer->cities, pcity) {
     struct tile *ptile = map_get_tile(pcity->x, pcity->y);
     ai->stats.cities[ptile->continent]++;
+    ai->stats.average_production += pcity->shield_surplus;
   } city_list_iterate_end;
+  ai->stats.average_production /= MAX(1, city_list_size(&pplayer->cities));
   unit_list_iterate(pplayer->units, punit) {
     struct tile *ptile = map_get_tile(punit->x, punit->y);
     if (ptile->terrain != T_OCEAN && unit_flag(punit, F_SETTLERS)) {
Index: ai/aidata.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidata.h,v
retrieving revision 1.4
diff -u -r1.4 aidata.h
--- ai/aidata.h 2002/12/23 18:09:58     1.4
+++ ai/aidata.h 2003/01/01 12:15:22
@@ -47,6 +47,7 @@
   struct {
     int *workers; /* cities to workers on continent*/
     int *cities;  /* number of cities on continent */
+    int average_production;
   } stats;
 
   int num_continents; /* last time we updated our continent data */
Index: ai/aidiplomat.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aidiplomat.c,v
retrieving revision 1.4
diff -u -r1.4 aidiplomat.c
--- ai/aidiplomat.c     2002/12/29 18:39:09     1.4
+++ ai/aidiplomat.c     2003/01/01 12:15:22
@@ -202,7 +202,8 @@
       return;
     }
 
-    want = military_amortize(want, time_to_dest, ut->build_cost);
+    want = military_amortize(pplayer, pcity, want, time_to_dest, 
+                             ut->build_cost);
 
     if (!player_has_embassy(pplayer, city_owner(acity))) {
         freelog(LOG_DIPLOMAT, "A diplomat desired in %s to establish an "
Index: ai/aitools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitools.c,v
retrieving revision 1.69
diff -u -r1.69 aitools.c
--- ai/aitools.c        2002/12/24 18:08:36     1.69
+++ ai/aitools.c        2003/01/01 12:15:23
@@ -42,29 +42,55 @@
 #include "unittools.h"
 
 #include "aicity.h"
+#include "aidata.h"
 #include "ailog.h"
 #include "aiunit.h"
 
 #include "aitools.h"
 
 /**************************************************************************
-  Create a virtual unit to use in build want estimation
+  Amortize a want modified by the shields (build_cost) we risk losing.
+  We add the build time of the unit(s) we risk to amortize delay.  The
+  build time is claculated as the build cost divided by the production
+  output of the unit's homecity or the city where we want to produce
+  the unit. If the city has less than average shield output, we
+  instead use the average, to encourage long-term thinking.
 **************************************************************************/
-struct unit *create_unit_virtual(struct player *pplayer, int x, int y,
-                                Unit_Type_id type, bool make_veteran)
+int military_amortize(struct player *pplayer, struct city *pcity,
+                      int value, int delay, int build_cost)
 {
+  struct ai_data *ai = ai_data_get(pplayer);
+  int city_output = (pcity ? pcity->shield_surplus : 1);
+  int output = MAX(city_output, ai->stats.average_production);
+  int build_time = build_cost / output;
+
+  if (value <= 0) {
+    return 0;
+  }
+
+  return amortize(value, delay + build_time);
+}
+
+/**************************************************************************
+  Create a virtual unit to use in build want estimation. pcity can be 
+  NULL.
+**************************************************************************/
+struct unit *create_unit_virtual(struct player *pplayer, struct city *pcity,
+                                 Unit_Type_id type, bool make_veteran)
+{
   struct unit *punit;
   punit=fc_calloc(1, sizeof(struct unit));
 
+  assert(pcity);
   punit->type = type;
   punit->owner = pplayer->player_no;
-  CHECK_MAP_POS(x, y);
-  punit->x = x;
-  punit->y = y;
+  CHECK_MAP_POS(pcity->x, pcity->y);
+  punit->x = pcity->x;
+  punit->y = pcity->y;
   punit->goto_dest_x = 0;
   punit->goto_dest_y = 0;
   punit->veteran = make_veteran;
-  punit->homecity = 0;
+  punit->homecity = pcity->id;
   punit->upkeep = 0;
   punit->upkeep_food = 0;
   punit->upkeep_gold = 0;
Index: ai/aitools.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitools.h,v
retrieving revision 1.32
diff -u -r1.32 aitools.h
--- ai/aitools.h        2002/12/24 18:08:36     1.32
+++ ai/aitools.h        2003/01/01 12:15:23
@@ -27,8 +27,10 @@
   BODYGUARD_NONE
 };
 
-struct unit *create_unit_virtual(struct player *pplayer, int x, int y,
-                                Unit_Type_id type, bool make_veteran);
+int military_amortize(struct player *pplayer, struct city *pcity, 
+                      int value, int delay, int build_cost);
+struct unit *create_unit_virtual(struct player *pplayer, struct city *pcity,
+                                 Unit_Type_id type, bool make_veteran);
 void destroy_unit_virtual(struct unit *punit);
 bool is_stack_vulnerable(int x, int y);
 
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.247
diff -u -r1.247 aiunit.c
--- ai/aiunit.c 2002/12/31 18:15:49     1.247
+++ ai/aiunit.c 2003/01/01 12:15:24
@@ -775,26 +775,6 @@
 }
 
 /**************************************************************************
-Military "want" estimates are amortized in this complicated way.
-COMMENTME: Why not use simple amortize? -- GB
-**************************************************************************/
-int military_amortize(int value, int delay, int build_cost)
-{
-  int simply_amortized, fully_amortized;
-
-  if (value <= 0) {
-    return 0;
-  }
-
-  simply_amortized = amortize(value, delay);
-  fully_amortized = ((value * simply_amortized) * 100
-                     / (MAX(1, value - simply_amortized))
-                     / (build_cost * MORT));
-
-  return fully_amortized;
-}
-
-/**************************************************************************
   Calculates the value and cost of nearby allied units to see if we can
   expect any help in our attack. Base function.
 **************************************************************************/
@@ -1923,12 +1903,15 @@
       /* build_cost of ferry */
       needferry = (go_by_boat && !ferryboat ? unit_value(boattype) : 0);
       /* FIXME: add time to build the ferry? */
-      want = military_amortize(want, MAX(1, move_time), bcost_bal + needferry);
+      want = military_amortize(pplayer, find_city_by_id(punit->homecity),
+                               want, MAX(1, move_time), bcost_bal + needferry);
 
       /* BEGIN STEAM-ENGINES-ARE-OUR-FRIENDS KLUGE */
       if (want <= 0 && punit->id == 0 && best == 0) {
-        int bk_e = military_amortize(benefit * SHIELD_WEIGHTING, 
+        int bk_e = military_amortize(pplayer, find_city_by_id(punit->homecity),
+                                     benefit * SHIELD_WEIGHTING, 
                                      MAX(1, move_time), bcost_bal + needferry);
+
         if (bk_e > bk) {
           *x = acity->x;
           *y = acity->y;
@@ -2034,7 +2017,8 @@
          * (costs 2 luxuries to compensate) */
         want -= (unhap ? 2 * move_time * TRADE_WEIGHTING : 0);
       }
-      want = military_amortize(want, MAX(1, move_time), bcost_bal);
+      want = military_amortize(pplayer, find_city_by_id(punit->homecity),
+                               want, MAX(1, move_time), bcost_bal);
       if (want > best && ai_fuzzy(pplayer, TRUE)) {
         best = want;
         *x = aunit->x;
Index: ai/aiunit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.h,v
retrieving revision 1.39
diff -u -r1.39 aiunit.h
--- ai/aiunit.h 2002/12/31 18:15:49     1.39
+++ ai/aiunit.h 2003/01/01 12:15:25
@@ -69,7 +69,6 @@
                                int x, int y, bool fortified, bool veteran,
                                bool use_alternative_hp, int alternative_hp);
 int kill_desire(int benefit, int attack, int loss, int vuln, int attack_count);
-int military_amortize(int value, int delay, int build_cost);
 
 bool is_on_unit_upgrade_path(Unit_Type_id test, Unit_Type_id base);
 

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] Re: (PR#2650) Overflow in military_amortize, Gregory Berkolaiko via RT <=