Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2005:
[Freeciv-Dev] Re: (PR#12840) delay in pollution patrol (possible causes)
Home

[Freeciv-Dev] Re: (PR#12840) delay in pollution patrol (possible causes)

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#12840) delay in pollution patrol (possible causes)
From: "Brian Dunstan" <bdunstan149@xxxxxxxxx>
Date: Tue, 26 Apr 2005 16:23:10 -0700
Reply-to: bugs@xxxxxxxxxxx

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

Hm, revised version, the same except:

+ Unit_Type_id inbound;


instead of:

+ int inbound;


--- Brian Dunstan <bdunstan149@xxxxxxxxx> wrote:

> 
> <URL:
> http://bugs.freeciv.org/Ticket/Display.html?id=12840
> >
> 
> <URL:
>
http://bugs.freeciv.org/Ticket/Display.html?id=12840>
> 
> Here is a patch that fixes (to a large extent) the
> proplems of delay in autosettler pollution cleanup
> in
> the late game.
> 
> In the current algorithm, a worker that cannot begin
> cleanup in the present turn will reserve a polluted
> tile, preventing other, more ready, workers from
> responding.  
> 
> My patch records the worker moving to a given tile
> (if
> any) by its ID, along with its ETA.  Another worker
> may consider this tile, and displace the worker
> currently en route, if either:
> 
> 1) it can arrive at the tile sooner
> 2) it will arrive at the same time, but will have to
> traverse fewer squares to do so.
> 
> __________________________________________________
> Do You Yahoo!?
> Tired of spam?  Yahoo! Mail has the best spam
> protection around 
> http://mail.yahoo.com 
> > diff -Nur -Xfreeciv/diff_ignore
freeciv/common/map.c
> freeciv_nopollute/common/map.c
> --- freeciv/common/map.c      2005-04-26
> 11:12:32.000000000 -0400
> +++ freeciv_nopollute/common/map.c    2005-04-26
> 13:14:04.740438744 -0400
> @@ -344,6 +344,7 @@
>    ptile->assigned = 0; /* bitvector */
>    ptile->owner    = NULL; /* Tile not claimed by
> any nation. */
>    ptile->spec_sprite = NULL;
> +  ptile->inbound = -1;
>  }
>  
> 
>
/****************************************************************************
> diff -Nur -Xfreeciv/diff_ignore
> freeciv/common/tile.h
> freeciv_nopollute/common/tile.h
> --- freeciv/common/tile.h     2005-04-26
> 11:12:32.000000000 -0400
> +++ freeciv_nopollute/common/tile.h   2005-04-26
> 13:16:35.273554232 -0400
> @@ -38,6 +38,10 @@
>    Continent_id continent;
>    struct player *owner;     /* Player owning this
> tile, or NULL. */
>    char *spec_sprite;
> +
> +  int inbound;
> +  int inbound_eta;
> +
>  };
>  
>  /* get 'struct tile_list' and related functions: */
> diff -Nur -Xfreeciv/diff_ignore
> freeciv/server/settlers.c
> freeciv_nopollute/server/settlers.c
> --- freeciv/server/settlers.c 2005-04-26
> 11:12:40.000000000 -0400
> +++ freeciv_nopollute/server/settlers.c       2005-04-26
> 14:30:52.482955408 -0400
> @@ -16,6 +16,7 @@
>  #endif
>  
>  #include <assert.h>
> +#include <limits.h>
>  #include <math.h>
>  #include <stdio.h>
>  #include <string.h>
> @@ -835,10 +836,13 @@
>    this return value is >0, then (gx,gy) indicates
> the tile chosen and bestact
>    indicates the activity it wants to do.  If 0 is
> returned then there are no
>    worthwhile activities available.
> +
> +  travel_time is the time that would be taken by
> punit to reach best_tile
> 
>
****************************************************************************/
>  static int evaluate_improvements(struct unit
> *punit,
>                                enum unit_activity *best_act,
> -                              struct tile **best_tile)
> +                              struct tile **best_tile,
> +                              int *travel_time)
>  {
>    struct city *mycity = tile_get_city(punit->tile);
>    struct player *pplayer = unit_owner(punit);
> @@ -858,6 +862,9 @@
>    int best_newv = 0;
>    enemy_mask my_enemies =
> enemies[pplayer->player_no]; /* optimalization */
>  
> +  struct unit *inbound = NULL; /* closest worker,
> if any, headed towards 
> +                               target tile */
> +
>    generate_warmap(mycity, punit);
>  
>    city_list_iterate(pplayer->cities, pcity) {
> @@ -869,65 +876,83 @@
>       continue;
>        }
>        in_use = (get_worker_city(pcity, i, j) ==
> C_TILE_WORKER);
> +      inbound = unit_list_find(pplayer->units,
> ptile->inbound);
>        if (tile_get_continent(ptile) == ucont
>         && WARMAP_COST(ptile) <= THRESHOLD * mv_rate
>         && !BV_CHECK_MASK(TERRITORY(ptile), my_enemies)
> -       /* pretty good, hope it's enough! -- Syela */
> -       && !is_already_assigned(punit, pplayer, ptile))
> {
> -     /* calling is_already_assigned once instead of
> four times
> -        for obvious reasons;  structure is much the
> same as it once
> -        was but subroutines are not -- Syela */
> +       && (!(is_already_assigned(punit, pplayer,
> ptile)
> +             || (inbound 
> +                 && inbound->owner == pplayer->player_no)))) {
> +     
> +     int eta=INT_MAX, inbound_distance=INT_MAX;
>       int time;
> +     if(inbound) {
> +       eta = ptile->inbound_eta;
> +       inbound_distance = real_map_distance(ptile,
> inbound->tile);
> +     }
>       mv_turns = (WARMAP_COST(ptile)) / mv_rate;
>       oldv = city_tile_value(pcity, i, j, 0, 0);
>  
> -     /* now, consider various activities... */
> +     /* only consider this tile if we are closer in
> time and space to it than
> +        our other worker (if any) travelling to the
> site */
> +     if(mv_turns < eta ||
> +        (mv_turns == eta &&
> +         real_map_distance(ptile, punit->tile) <
> inbound_distance)) {
> +       
> +       /* now, consider various activities... */
> +       
> +       activity_type_iterate(act) {
> +         
> +         if(pcity->ai.act_value[act][i][j] >= 0 &&
> +            can_unit_do_activity_targeted_at(punit,
> act, 
> +                                             S_NO_SPECIAL, ptile)) {
> +           int extra = 0;
> +           int base_value =
> pcity->ai.act_value[act][i][j];
> +           int old_best_value = best_newv;
> +           time = mv_turns +
> get_turns_for_activity_at(punit, act, ptile);
> +           if(act == ACTIVITY_ROAD) {
> +             extra = road_bonus(ptile, S_ROAD) * 5;
> +             if (can_rr) {
> +               /* if we can make railroads eventually,
> consider making
> +                * road here, and set extras and time to to
> consider
> +                * railroads in main consider_settler_action
> call */
> +               consider_settler_action(pplayer, ACTIVITY_ROAD,
> +                                       extra,
> +                                       
> pcity->ai.act_value[ACTIVITY_ROAD][i][j], 
> +                                       oldv, in_use, time,
> +                                       &best_newv, &best_oldv, 
> +                                       best_act, best_tile,
> +                                       ptile);
> +               
> +               base_value =
> pcity->ai.act_value[ACTIVITY_RAILROAD][i][j];
> +               
> +               /* Count road time plus rail time. */
> +               time += get_turns_for_activity_at(punit,
> ACTIVITY_RAILROAD, 
> +                                                 ptile);
> +             }
> +           } else if (act == ACTIVITY_RAILROAD) {
> +             extra = road_bonus(ptile, S_RAILROAD) * 3;
> +           } else if (act == ACTIVITY_FALLOUT) {
> +             extra = pplayer->ai.frost;
> +           } else if (act == ACTIVITY_POLLUTION) {
> +             extra = pplayer->ai.warmth;
> +           }    
> +           
> +           consider_settler_action(pplayer, act,
> +                                   extra, 
> +                                   base_value, oldv, 
> +                                   in_use, time,
> +                                   &best_newv, &best_oldv,
> +                                   best_act, best_tile,
> +                                   ptile);
>  
> -     activity_type_iterate(act) {
> -
> -       if(pcity->ai.act_value[act][i][j] >= 0 &&
> -          can_unit_do_activity_targeted_at(punit, act, 
> -                                           S_NO_SPECIAL, ptile)) {
> -         int extra = 0;
> -         int base_value =
> pcity->ai.act_value[act][i][j];
> -         time = mv_turns +
> get_turns_for_activity_at(punit, act, ptile);
> -         if(act == ACTIVITY_ROAD) {
> -           extra = road_bonus(ptile, S_ROAD) * 5;
> -           if (can_rr) {
> -             /* if we can make railroads eventually, consider
> making
> -              * road here, and set extras and time to to
> consider
> -              * railroads in main consider_settler_action call
> */
> -             consider_settler_action(pplayer, ACTIVITY_ROAD,
> -                                     extra,
> 
=== message truncated ===

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
diff -Nur -Xfreeciv/diff_ignore freeciv/common/map.c 
freeciv_nopollute/common/map.c
--- freeciv/common/map.c        2005-04-26 11:12:32.000000000 -0400
+++ freeciv_nopollute/common/map.c      2005-04-26 13:14:04.000000000 -0400
@@ -344,6 +344,7 @@
   ptile->assigned = 0; /* bitvector */
   ptile->owner    = NULL; /* Tile not claimed by any nation. */
   ptile->spec_sprite = NULL;
+  ptile->inbound = -1;
 }
 
 /****************************************************************************
diff -Nur -Xfreeciv/diff_ignore freeciv/common/tile.h 
freeciv_nopollute/common/tile.h
--- freeciv/common/tile.h       2005-04-26 11:12:32.000000000 -0400
+++ freeciv_nopollute/common/tile.h     2005-04-26 16:24:40.695909256 -0400
@@ -38,6 +38,10 @@
   Continent_id continent;
   struct player *owner;     /* Player owning this tile, or NULL. */
   char *spec_sprite;
+
+  Unit_Type_id inbound;
+  int inbound_eta;
+
 };
 
 /* get 'struct tile_list' and related functions: */
diff -Nur -Xfreeciv/diff_ignore freeciv/server/settlers.c 
freeciv_nopollute/server/settlers.c
--- freeciv/server/settlers.c   2005-04-26 11:12:40.000000000 -0400
+++ freeciv_nopollute/server/settlers.c 2005-04-26 14:30:52.000000000 -0400
@@ -16,6 +16,7 @@
 #endif
 
 #include <assert.h>
+#include <limits.h>
 #include <math.h>
 #include <stdio.h>
 #include <string.h>
@@ -835,10 +836,13 @@
   this return value is >0, then (gx,gy) indicates the tile chosen and bestact
   indicates the activity it wants to do.  If 0 is returned then there are no
   worthwhile activities available.
+
+  travel_time is the time that would be taken by punit to reach best_tile
 ****************************************************************************/
 static int evaluate_improvements(struct unit *punit,
                                 enum unit_activity *best_act,
-                                struct tile **best_tile)
+                                struct tile **best_tile,
+                                int *travel_time)
 {
   struct city *mycity = tile_get_city(punit->tile);
   struct player *pplayer = unit_owner(punit);
@@ -858,6 +862,9 @@
   int best_newv = 0;
   enemy_mask my_enemies = enemies[pplayer->player_no]; /* optimalization */
 
+  struct unit *inbound = NULL; /* closest worker, if any, headed towards 
+                                 target tile */
+
   generate_warmap(mycity, punit);
 
   city_list_iterate(pplayer->cities, pcity) {
@@ -869,65 +876,83 @@
        continue;
       }
       in_use = (get_worker_city(pcity, i, j) == C_TILE_WORKER);
+      inbound = unit_list_find(pplayer->units, ptile->inbound);
       if (tile_get_continent(ptile) == ucont
          && WARMAP_COST(ptile) <= THRESHOLD * mv_rate
          && !BV_CHECK_MASK(TERRITORY(ptile), my_enemies)
-         /* pretty good, hope it's enough! -- Syela */
-         && !is_already_assigned(punit, pplayer, ptile)) {
-       /* calling is_already_assigned once instead of four times
-          for obvious reasons;  structure is much the same as it once
-          was but subroutines are not -- Syela */
+         && (!(is_already_assigned(punit, pplayer, ptile)
+               || (inbound 
+                   && inbound->owner == pplayer->player_no)))) {
+       
+       int eta=INT_MAX, inbound_distance=INT_MAX;
        int time;
+       if(inbound) {
+         eta = ptile->inbound_eta;
+         inbound_distance = real_map_distance(ptile, inbound->tile);
+       }
        mv_turns = (WARMAP_COST(ptile)) / mv_rate;
        oldv = city_tile_value(pcity, i, j, 0, 0);
 
-       /* now, consider various activities... */
+       /* only consider this tile if we are closer in time and space to it than
+          our other worker (if any) travelling to the site */
+       if(mv_turns < eta ||
+          (mv_turns == eta &&
+           real_map_distance(ptile, punit->tile) < inbound_distance)) {
+         
+         /* now, consider various activities... */
+         
+         activity_type_iterate(act) {
+           
+           if(pcity->ai.act_value[act][i][j] >= 0 &&
+              can_unit_do_activity_targeted_at(punit, act, 
+                                               S_NO_SPECIAL, ptile)) {
+             int extra = 0;
+             int base_value = pcity->ai.act_value[act][i][j];
+             int old_best_value = best_newv;
+             time = mv_turns + get_turns_for_activity_at(punit, act, ptile);
+             if(act == ACTIVITY_ROAD) {
+               extra = road_bonus(ptile, S_ROAD) * 5;
+               if (can_rr) {
+                 /* if we can make railroads eventually, consider making
+                  * road here, and set extras and time to to consider
+                  * railroads in main consider_settler_action call */
+                 consider_settler_action(pplayer, ACTIVITY_ROAD,
+                                         extra,
+                                         
pcity->ai.act_value[ACTIVITY_ROAD][i][j], 
+                                         oldv, in_use, time,
+                                         &best_newv, &best_oldv, 
+                                         best_act, best_tile,
+                                         ptile);
+                 
+                 base_value = pcity->ai.act_value[ACTIVITY_RAILROAD][i][j];
+                 
+                 /* Count road time plus rail time. */
+                 time += get_turns_for_activity_at(punit, ACTIVITY_RAILROAD, 
+                                                   ptile);
+               }
+             } else if (act == ACTIVITY_RAILROAD) {
+               extra = road_bonus(ptile, S_RAILROAD) * 3;
+             } else if (act == ACTIVITY_FALLOUT) {
+               extra = pplayer->ai.frost;
+             } else if (act == ACTIVITY_POLLUTION) {
+               extra = pplayer->ai.warmth;
+             }    
+             
+             consider_settler_action(pplayer, act,
+                                     extra, 
+                                     base_value, oldv, 
+                                     in_use, time,
+                                     &best_newv, &best_oldv,
+                                     best_act, best_tile,
+                                     ptile);
 
-       activity_type_iterate(act) {
-
-         if(pcity->ai.act_value[act][i][j] >= 0 &&
-            can_unit_do_activity_targeted_at(punit, act, 
-                                             S_NO_SPECIAL, ptile)) {
-           int extra = 0;
-           int base_value = pcity->ai.act_value[act][i][j];
-           time = mv_turns + get_turns_for_activity_at(punit, act, ptile);
-           if(act == ACTIVITY_ROAD) {
-             extra = road_bonus(ptile, S_ROAD) * 5;
-             if (can_rr) {
-               /* if we can make railroads eventually, consider making
-                * road here, and set extras and time to to consider
-                * railroads in main consider_settler_action call */
-               consider_settler_action(pplayer, ACTIVITY_ROAD,
-                                       extra,
-                                       
pcity->ai.act_value[ACTIVITY_ROAD][i][j], 
-                                       oldv, in_use, time,
-                                       &best_newv, &best_oldv, 
-                                       best_act, best_tile,
-                                       ptile);
-
-               base_value = pcity->ai.act_value[ACTIVITY_RAILROAD][i][j];
-
-               /* Count road time plus rail time. */
-               time += get_turns_for_activity_at(punit, ACTIVITY_RAILROAD, 
-                                                 ptile);
+             if(best_newv > old_best_value) {
+               *travel_time = mv_turns;
              }
-           } else if (act == ACTIVITY_RAILROAD) {
-             extra = road_bonus(ptile, S_RAILROAD) * 3;
-           } else if (act == ACTIVITY_FALLOUT) {
-             extra = pplayer->ai.frost;
-           } else if (act == ACTIVITY_POLLUTION) {
-             extra = pplayer->ai.warmth;
-           }    
-
-           consider_settler_action(pplayer, act,
-                                   extra, 
-                                   base_value, oldv, 
-                                   in_use, time,
-                                   &best_newv, &best_oldv,
-                                   best_act, best_tile,
-                                   ptile);
-         } /* endif: can the worker perform this action */
-       } activity_type_iterate_end;
+
+           } /* endif: can the worker perform this action */
+         } activity_type_iterate_end;
+       } /* endif: are we closer than the currenly assigned worker, if any? */
       } /* endif: are we travelling to a legal destination? */
     } city_map_checked_iterate_end;
   } city_list_iterate_end;
@@ -962,6 +987,8 @@
   enum unit_activity best_act;
   struct tile *best_tile = NULL;
   struct ai_data *ai = ai_data_get(pplayer);
+  int travel_time = 0; /* time it will take worker to reach 
+                         its destination tile */
 
   CHECK_UNIT(punit);
 
@@ -1014,7 +1041,7 @@
 
   if (unit_flag(punit, F_SETTLERS)) {
     TIMING_LOG(AIT_WORKERS, TIMER_START);
-    best_impr = evaluate_improvements(punit, &best_act, &best_tile);
+    best_impr = evaluate_improvements(punit, &best_act, &best_tile, 
&travel_time);
     TIMING_LOG(AIT_WORKERS, TIMER_STOP);
   }
 
@@ -1064,6 +1091,17 @@
   if (punit->ai.ai_role == AIUNIT_AUTO_SETTLER) {
     /* Mark the square as taken. */
     if (best_tile) {
+      struct unit *displaced = 
+       unit_list_find(pplayer->units, best_tile->inbound);
+      best_tile->inbound = punit->id;
+      best_tile->inbound_eta = travel_time;
+      
+      best_tile->assigned = best_tile->assigned | 1 << pplayer->player_no;
+
+      if(displaced) {
+       displaced->goto_tile = displaced->tile;
+       auto_settler_findwork(pplayer, displaced);
+      }
       best_tile->assigned = best_tile->assigned | 1 << pplayer->player_no;
     } else {
       UNIT_LOG(LOG_DEBUG, punit, "giving up trying to improve terrain");
@@ -1259,6 +1297,8 @@
 static void assign_settlers(void)
 {
   whole_map_iterate(ptile) {
+    ptile->inbound = -1;
+    ptile->inbound_eta = INT_MAX;
     ptile->assigned = 0;
   } whole_map_iterate_end;
 
@@ -1416,6 +1456,7 @@
   struct tile *ptile = pcity->tile;
   struct ai_data *ai = ai_data_get(pplayer);
   Unit_Type_id unit_type = best_role_unit(pcity, F_SETTLERS);
+  int travel_time;
 
   if (unit_type == U_LAST) {
     freelog(LOG_DEBUG, "No F_SETTLERS role unit available");
@@ -1425,7 +1466,8 @@
   /* Create a localized "virtual" unit to do operations with. */
   virtualunit = create_unit_virtual(pplayer, pcity, unit_type, 0);
   virtualunit->tile = pcity->tile;
-  want = evaluate_improvements(virtualunit, &best_act, &best_tile);
+  want = evaluate_improvements(virtualunit, &best_act,
+                              &best_tile, &travel_time);
   free(virtualunit);
 
   /* Massage our desire based on available statistics to prevent

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