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: Wed, 27 Apr 2005 14:54:54 -0700
Reply-to: bugs@xxxxxxxxxxx

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

--- Jason Short <jdorje@xxxxxxxxxxxxxxxxxxxxx> wrote:
> 
> <URL:
> http://bugs.freeciv.org/Ticket/Display.html?id=12840
> >
> 
> I like the design.  A few things about the
> implementation need fixing:
> 
> - Unit_type_id is not what you think it is.  It
> gives the type of a
> unit, not its ID.  The ID is just an int (I think?).
> 
> - Don't add new fields to the tile struct.  Instead
> make a new array of
> tile data in settlers.c.  This array can be
> reinitialized when the map
> is resized or on every turn or whatever.  See the
> warmap struct in
> gotohand.c or the map_deco struct in
> mapview_common.c or the
> pf_map->lattice struct in path_finding.c for other
> examples.
> 
> - Use FC_INFINITY, not INT_MAX.

I'm sending a new patch that fixes this.

> - Instead of using the "travel time" shouldn't you
> use the
> turns-to-completion?  E.g., if we have a
> high-priority task it's better
> to assign an engineer to it.  (Not entirely sure
> about this.)

on balance I think you're right.  The only time this
will affect behavior is when a worker and an engineer
both want to work the same tile; the engineer should
be given priority then imo.  So this has been changed
in the new patch.

-Brian

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
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-27 14:55:21.596891816 -0400
@@ -55,6 +55,9 @@
 BV_DEFINE(enemy_mask, MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS);
 static enemy_mask enemies[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS];
 
+static int *tile_inbound;
+static int *tile_inbound_time;
+
 static bool is_already_assigned(struct unit *myunit, struct player *pplayer,
                                struct tile *ptile);
 
@@ -835,10 +838,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.
+
+  completion_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 *completion_time)
 {
   struct city *mycity = tile_get_city(punit->tile);
   struct player *pplayer = unit_owner(punit);
@@ -858,6 +864,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 +878,83 @@
        continue;
       }
       in_use = (get_worker_city(pcity, i, j) == C_TILE_WORKER);
+      inbound = unit_list_find(pplayer->units, tile_inbound[ptile->index]);
       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=FC_INFINITY, inbound_distance=FC_INFINITY;
        int time;
+       if(inbound) {
+         eta = tile_inbound_time[ptile->index];
+         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) {
+               *completion_time = time;
              }
-           } 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 +989,8 @@
   enum unit_activity best_act;
   struct tile *best_tile = NULL;
   struct ai_data *ai = ai_data_get(pplayer);
+  int completion_time = 0; /* time it will take worker to complete 
+                             its given task */
 
   CHECK_UNIT(punit);
 
@@ -1014,7 +1043,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, 
&completion_time);
     TIMING_LOG(AIT_WORKERS, TIMER_STOP);
   }
 
@@ -1064,6 +1093,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, tile_inbound[best_tile->index]);
+      tile_inbound[best_tile->index] = punit->id;
+      tile_inbound_time[best_tile->index] = completion_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");
@@ -1258,7 +1298,10 @@
 **************************************************************************/
 static void assign_settlers(void)
 {
+
   whole_map_iterate(ptile) {
+    tile_inbound[ptile->index] = -1;
+    tile_inbound_time[ptile->index] = FC_INFINITY;
     ptile->assigned = 0;
   } whole_map_iterate_end;
 
@@ -1354,6 +1397,9 @@
 **************************************************************************/
 void auto_settlers_init(void)
 {
+  tile_inbound = fc_realloc(tile_inbound, MAP_INDEX_SIZE*(sizeof(int)));
+  tile_inbound_time = fc_realloc(tile_inbound_time, 
MAP_INDEX_SIZE*(sizeof(int)));
+
   assign_settlers();
   assign_territory();
   recount_enemy_masks();
@@ -1416,6 +1462,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 completion_time;
 
   if (unit_type == U_LAST) {
     freelog(LOG_DEBUG, "No F_SETTLERS role unit available");
@@ -1425,7 +1472,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, &completion_time);
   free(virtualunit);
 
   /* Massage our desire based on available statistics to prevent

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