Complete.Org: Mailing Lists: Archives: freeciv-ai: August 2004:
[freeciv-ai] (PR#8474) RFC: clean up road_bonus()
Home

[freeciv-ai] (PR#8474) RFC: clean up road_bonus()

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: use_less@xxxxxxxxxxx
Subject: [freeciv-ai] (PR#8474) RFC: clean up road_bonus()
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 5 Aug 2004 11:25:36 -0700
Reply-to: rt@xxxxxxxxxxx

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

Forgetting that this ticket existed, I tried to rewrite road_bonus to
work with the same algorithm under hex maps.  I completely failed.

So instead I wrote a new algorithm.  The patch includes it.  I'm not
sure it's better, but at least it should be comprehensible.

Note this patch doesn't apply anymore because road_bonus has had some
variable renames and added comments.

jason

Index: server/settlers.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v
retrieving revision 1.186
diff -u -r1.186 settlers.c
--- server/settlers.c   3 Aug 2004 03:08:54 -0000       1.186
+++ server/settlers.c   3 Aug 2004 19:39:21 -0000
@@ -699,57 +699,114 @@
 }
 
 /**************************************************************************
+  Determine if the given tile has a road, or if one is being built.
+**************************************************************************/
+static bool has_road(int map_x, int map_y, enum tile_special_type special)
+{
+  struct tile *ptile = map_get_tile(map_x, map_y);
+
+  if (tile_has_special(ptile, special)) {
+    /* There's already a road here. */
+    return TRUE;
+  }
+
+  unit_list_iterate(ptile->units, punit) {
+    if ((punit->activity == ACTIVITY_ROAD && special == S_ROAD)
+       || punit->activity == ACTIVITY_RAILROAD) {
+      /* Someone's building a road. */
+      return TRUE;
+    }
+  } unit_list_iterate_end;
+
+  /* No road. */
+  return FALSE;
+}
+
+/**************************************************************************
 Calculate the attractiveness
 "spc" will be S_ROAD or S_RAILROAD for sane calls.
 **************************************************************************/
-static int road_bonus(int x, int y, enum tile_special_type spc)
+static int road_bonus(int x, int y, enum tile_special_type special)
 {
-  int m = 0, k;
-  bool rd[12], te[12];
-  int ii[12] = { -1, 0, 1, -1, 1, -1, 0, 1, 0, -2, 2, 0 };
-  int jj[12] = { -1, -1, -1, 0, 0, 1, 1, 1, -2, 0, 0, 2 };
-  struct tile *ptile;
-  bool is_border = IS_BORDER_MAP_POS(x, y, 2);
+  int goodness = 0, dir_index;
+  struct tile *ptile = map_get_tile(x, y);
   
-  assert(spc == S_ROAD || spc == S_RAILROAD);
+  assert(special == S_ROAD || special == S_RAILROAD);
 
-  if (!normalize_map_pos(&x, &y))
-    return 0;
+  for (dir_index = 0; dir_index < map.num_valid_dirs / 2; dir_index++) {
+    enum direction8 dir1 = map.valid_dirs[dir_index];
+    enum direction8 dir2a = DIR_REVERSE(dir1);
+    enum direction8 dir2b = dir_cw(dir2a);
+    enum direction8 dir2c = dir_ccw(dir2a);
+    int x1, y1, x2, y2;
 
-  for (k = 0; k < 12; k++) {
-    int x1 = x + ii[k], y1 = y + jj[k];
-    if (is_border && !normalize_map_pos(&x1, &y1)) {
-      rd[k] = FALSE;
-      te[k] = FALSE;
-    } else {
-      ptile = map_get_tile(x1, y1);
-      rd[k] = tile_has_special(ptile, spc);
-      te[k] = (ptile->terrain == T_MOUNTAINS || is_ocean(ptile->terrain));
-      if (!rd[k]) {
-       unit_list_iterate(ptile->units, punit) {
-         if (punit->activity == ACTIVITY_ROAD 
-              || punit->activity == ACTIVITY_RAILROAD) {
-           rd[k] = TRUE;
-          }
-       } unit_list_iterate_end;
+    if (!MAPSTEP(x1, y1, x, y, dir1) || !has_road(x1, y1, special)) {
+      continue;
+    }
+
+    if (MAPSTEP(x2, y2, x, y, dir2a) && has_road(x2, y2, special)) {
+      /* If opposite sides have a road, we want one here to connect
+       * them. */
+      freelog(LOG_NORMAL, "%d,%d connects opposite %d,%d through %d,%d.",
+             x1, y1, x2, y2, x, y);
+      goodness = 5;
+    }
+
+    if (MAPSTEP(x2, y2, x, y, dir2b) && has_road(x2, y2, special)) {
+      /* If nearly-opposite sides have a road, we want one here to connect
+       * them _unless_ there's already one adjacent connecting them.
+       * Consider:
+       *
+       * 1 2 3
+       * 4 5 6
+       * 7 8 9
+       *
+       * if 1 and 6 have a road, we want one at 5 unless there's already one
+       * at 2.
+       */
+      enum direction8 dir3;
+      int x3, y3;
+
+      /* This code is crafted to work for both hex and rectangular maps. */
+      if (is_cardinal_dir(dir2b)) {
+       dir3 = dir_cw(dir2b);
+      } else {
+       dir3 = dir_ccw(dir1);
+      }
+      if (!MAPSTEP(x3, y3, x, y, dir3) || !has_road(x3, y3, special)) {
+      freelog(LOG_NORMAL, "%d,%d connects nearly opposite %d,%d "
+             "through %d,%d; %d,%d is empty.",
+             x1, y1, x2, y2, x, y, x3, y3);
+       goodness = 5;
+      }
+    }
+
+    if (MAPSTEP(x2, y2, x, y, dir2c) && has_road(x2, y2, special)) {
+      /* Same as the above code, but for the other direction. */
+      enum direction8 dir3;
+      int x3, y3;
+
+      if (is_cardinal_dir(dir2c)) {
+       dir3 = dir_ccw(dir2b);
+      } else {
+       dir3 = dir_cw(dir1);
+      }
+      if (!MAPSTEP(x3, y3, x, y, dir3) || !has_road(x3, y3, special)) {
+       freelog(LOG_NORMAL, "%d,%d connects nearly opposite %d,%d "
+               "through %d,%d; %d,%d is empty.",
+               x1, y1, x2, y2, x, y, x3, y3);
+       goodness = 5;
       }
     }
   }
 
-  if (rd[0] && !rd[1] && !rd[3] && (!rd[2] || !rd[8]) &&
-      (!te[2] || !te[4] || !te[7] || !te[6] || !te[5])) m++;
-  if (rd[2] && !rd[1] && !rd[4] && (!rd[7] || !rd[10]) &&
-      (!te[0] || !te[3] || !te[7] || !te[6] || !te[5])) m++;
-  if (rd[5] && !rd[6] && !rd[3] && (!rd[5] || !rd[11]) &&
-      (!te[2] || !te[4] || !te[7] || !te[1] || !te[0])) m++;
-  if (rd[7] && !rd[6] && !rd[4] && (!rd[0] || !rd[9]) &&
-      (!te[2] || !te[3] || !te[0] || !te[1] || !te[5])) m++;
-
-  if (rd[1] && !rd[4] && !rd[3] && (!te[5] || !te[6] || !te[7])) m++;
-  if (rd[3] && !rd[1] && !rd[6] && (!te[2] || !te[4] || !te[7])) m++;
-  if (rd[4] && !rd[1] && !rd[6] && (!te[0] || !te[3] || !te[5])) m++;
-  if (rd[6] && !rd[4] && !rd[3] && (!te[0] || !te[1] || !te[2])) m++;
-  return(m);
+  /* If there are units on the tile, they probably want a road to travel
+   * on. */
+  unit_list_iterate(ptile->units, punit) {
+    goodness++;
+  } unit_list_iterate_end;
+
+  return goodness;
 }
 
 /**************************************************************************

[Prev in Thread] Current Thread [Next in Thread]
  • [freeciv-ai] (PR#8474) RFC: clean up road_bonus(), Jason Short <=