Complete.Org: Mailing Lists: Archives: freeciv-dev: June 2004:
[Freeciv-Dev] Re: (PR#7481) meta-ticket for hex maps
Home

[Freeciv-Dev] Re: (PR#7481) meta-ticket for hex maps

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] Re: (PR#7481) meta-ticket for hex maps
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 19 Jun 2004 21:56:12 -0700
Reply-to: rt@xxxxxxxxxxx

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

Here's a new update of the hex patch.

It should now work out of the box for everyone.  I also /set the 
topology properly when launching a single-player game.  So if you 
download the update isophex tileset (in the contrib directory) and run 
./civ -t isophex it should just work.

jason


? gmon.out
Index: client/connectdlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/connectdlg_common.c,v
retrieving revision 1.12
diff -u -r1.12 connectdlg_common.c
--- client/connectdlg_common.c  8 May 2004 19:21:01 -0000       1.12
+++ client/connectdlg_common.c  20 Jun 2004 04:49:51 -0000
@@ -243,12 +243,19 @@
    * get an iso-map and for a classic tileset you get a classic map.  In
    * both cases the map wraps in the X direction by default.
    *
+   * This works with hex maps too now.  A hex map always has is_isometric
+   * set.  An iso-hex map has hex_height != 0, while a non-iso hex map
+   * has hex_width != 0.
+   *
    * Setting the option here is a bit of a hack, but so long as the client
    * has sufficient permissions to do so (it doesn't have HACK access yet) it
    * is safe enough.  Note that if you load a savegame the topology will be
    * set but then overwritten during the load. */
   my_snprintf(buf, sizeof(buf), "/set topology %d",
-             TF_WRAPX | (is_isometric ? TF_ISO : 0));
+             (TF_WRAPX
+              | ((is_isometric && hex_height == 0) ? TF_ISO : 0)
+              | ((is_isometric && (hex_width != 0
+                                   || hex_height != 0)) ? TF_HEX : 0)));
   send_chat(buf);
 
   return TRUE;
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.220
diff -u -r1.220 city.c
--- common/city.c       16 Jun 2004 03:01:02 -0000      1.220
+++ common/city.c       20 Jun 2004 04:49:52 -0000
@@ -45,6 +45,8 @@
 **************************************************************************/
 bool is_valid_city_coords(const int city_x, const int city_y)
 {
+  int dist = map_vector_to_sq_distance(city_x - CITY_MAP_RADIUS,
+                                      city_y - CITY_MAP_RADIUS);
   /* The city's valid positions are in a circle of radius CITY_MAP_RADIUS
    * around the city center.  Depending on the value of CITY_MAP_RADIUS
    * this circle will be:
@@ -61,9 +63,7 @@
    *
    * FIXME: this won't work for hexagonal tiles.
    */
-  if (CITY_MAP_RADIUS * CITY_MAP_RADIUS + 1
-      >= ((city_x - CITY_MAP_RADIUS) * (city_x - CITY_MAP_RADIUS) +
-         (city_y - CITY_MAP_RADIUS) * (city_y - CITY_MAP_RADIUS))) {
+  if (CITY_MAP_RADIUS * CITY_MAP_RADIUS + 1 >= dist) {
     return TRUE;
   } else {
     return FALSE;
@@ -200,7 +200,7 @@
       if (is_valid_city_coords(dx + CITY_MAP_RADIUS, dy + CITY_MAP_RADIUS)) {
        array[i].dx = dx;
        array[i].dy = dy;
-       array[i].dist = dx * dx + dy * dy;
+       array[i].dist = map_vector_to_sq_distance(dx, dy);
        i++;
       }
     }
Index: common/map.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.c,v
retrieving revision 1.170
diff -u -r1.170 map.c
--- common/map.c        12 Jun 2004 17:42:27 -0000      1.170
+++ common/map.c        20 Jun 2004 04:49:52 -0000
@@ -42,10 +42,6 @@
 const int DIR_DX[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };
 const int DIR_DY[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
 
-/* like DIR_DX[] and DIR_DY[], only cartesian */
-const int CAR_DIR_DX[4] = {1, 0, -1, 0};
-const int CAR_DIR_DY[4] = {0, 1, 0, -1};
-
 /* Names of specials.
  * (These must correspond to enum tile_special_type in terrain.h.)
  */
@@ -437,6 +433,10 @@
 {
   int dx, dy;
 
+  if (topo_has_flag(TF_HEX)) {
+    return map_distance(x0, y0, x1, y1);
+  }
+
   map_distance_vector(&dx, &dy, x0, y0, x1, y1);
 
   return MAX(abs(dx), abs(dy));
@@ -452,8 +452,49 @@
   int dx, dy;
 
   map_distance_vector(&dx, &dy, x0, y0, x1, y1);
+  return map_vector_to_sq_distance(dx, dy);
+}
 
-  return (dx*dx + dy*dy);
+int map_vector_to_distance(int dx, int dy)
+{
+  if (topo_has_flag(TF_HEX)) {
+    if (topo_has_flag(TF_ISO)) {
+      /* Iso-hex: you can't move NE or SW. */
+      if ((dx < 0 && dy > 0)
+         || (dx > 0 && dy < 0)) {
+       /* Diagonal moves in this direction aren't allowed, so it will take
+        * the full number of moves. */
+       return abs(dx) + abs(dy);
+      } else {
+       /* Diagonal moves in this direction *are* allowed. */
+       return MAX(abs(dx), abs(dy));
+      }
+    } else {
+      /* Hex: you can't move SE or NW. */
+      if ((dx > 0 && dy > 0)
+         || (dx < 0 && dy < 0)) {
+       /* Diagonal moves in this direction aren't allowed, so it will take
+        * the full number of moves. */
+       return abs(dx) + abs(dy);
+      } else {
+       /* Diagonal moves in this direction *are* allowed. */
+       return MAX(abs(dx), abs(dy));
+      }
+    }
+  } else {
+    return abs(dx) + abs(dy);
+  }
+}
+
+int map_vector_to_sq_distance(int dx, int dy)
+{
+  if (topo_has_flag(TF_HEX)) {
+    int dist = map_vector_to_distance(dx, dy);
+
+    return dist * dist;
+  } else {
+    return dx * dx + dy * dy;
+  }
 }
 
 /***************************************************************
@@ -467,7 +508,7 @@
 
   map_distance_vector(&dx, &dy, x0, y0, x1, y1);
 
-  return abs(dx) + abs(dy);
+  return map_vector_to_distance(dx, dy);
 }
 
 /***************************************************************
@@ -1598,14 +1639,16 @@
 bool is_valid_dir(enum direction8 dir)
 {
   switch (dir) {
-  case DIR8_NORTH:
+  case DIR8_SOUTHEAST:
+  case DIR8_NORTHWEST:
+    return !(topo_has_flag(TF_HEX) && !topo_has_flag(TF_ISO));
   case DIR8_NORTHEAST:
+  case DIR8_SOUTHWEST:
+    return !(topo_has_flag(TF_HEX) && topo_has_flag(TF_ISO));
+  case DIR8_NORTH:
   case DIR8_EAST:
-  case DIR8_SOUTHEAST:
   case DIR8_SOUTH:
-  case DIR8_SOUTHWEST:
   case DIR8_WEST:
-  case DIR8_NORTHWEST:
     return TRUE;
   default:
     return FALSE;
Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.188
diff -u -r1.188 map.h
--- common/map.h        12 Jun 2004 17:42:27 -0000      1.188
+++ common/map.h        20 Jun 2004 04:49:52 -0000
@@ -152,7 +152,8 @@
   /* Changing these values will break map_init_topology. */
   TF_WRAPX = 1,
   TF_WRAPY = 2,
-  TF_ISO = 4
+  TF_ISO = 4,
+  TF_HEX = 8
 };
 
 #define CURRENT_TOPOLOGY (map.topology_id)
@@ -169,6 +170,8 @@
 const char *map_get_tile_fpt_text(int x, int y);
 struct tile *map_get_tile(int x, int y);
 
+int map_vector_to_distance(int dx, int dy);
+int map_vector_to_sq_distance(int dx, int dy);
 int map_distance(int x0, int y0, int x1, int y1);
 int real_map_distance(int x0, int y0, int x1, int y1);
 int sq_map_distance(int x0, int y0, int x1, int y1);
@@ -202,13 +205,13 @@
 
 /* Obscure math.  See explanation in doc/HACKING. */
 #define native_to_map_pos(pmap_x, pmap_y, nat_x, nat_y)                     \
-  (topo_has_flag(TF_ISO)                                                    \
+  ((topo_has_flag(TF_ISO) || topo_has_flag(TF_HEX))                         \
    ? (*(pmap_x) = ((nat_y) + ((nat_y) & 1)) / 2 + (nat_x),                  \
       *(pmap_y) = (nat_y) - *(pmap_x) + map.xsize)                          \
    : (*(pmap_x) = (nat_x), *(pmap_y) = (nat_y)))
 
 #define map_to_native_pos(pnat_x, pnat_y, map_x, map_y)                     \
-  (topo_has_flag(TF_ISO)                                                    \
+  ((topo_has_flag(TF_ISO) || topo_has_flag(TF_HEX))                        \
    ? (*(pnat_y) = (map_x) + (map_y) - map.xsize,                            \
       *(pnat_x) = (2 * (map_x) - *(pnat_y) - (*(pnat_y) & 1)) / 2)          \
    : (*(pnat_x) = (map_x), *(pnat_y) = (map_y)))
@@ -295,9 +298,10 @@
  * we bend this rule here.
  */
 #define MAPSTEP(dest_x, dest_y, src_x, src_y, dir)     \
-(    (dest_x) = (src_x) + DIR_DX[(dir)],               \
-     (dest_y) = (src_y) + DIR_DY[(dir)],               \
-     normalize_map_pos(&(dest_x), &(dest_y)))
+  (is_valid_dir(dir)                                    \
+   && ((dest_x) = (src_x) + DIR_DX[(dir)],             \
+       (dest_y) = (src_y) + DIR_DY[(dir)],             \
+       normalize_map_pos(&(dest_x), &(dest_y))))
 
 struct player *map_get_owner(int x, int y);
 void map_set_owner(int x, int y, struct player *pplayer);
@@ -324,7 +328,6 @@
 bool contains_special(enum tile_special_type all,
                      enum tile_special_type to_test_for);
 
-
 bool is_singular_map_pos(int map_x, int map_y, int dist);
 bool normalize_map_pos(int *x, int *y);
 void nearest_real_pos(int *x, int *y);
@@ -538,6 +541,9 @@
   int MACRO_center_y = (center_y);                                            \
   CHECK_MAP_POS(MACRO_center_x, MACRO_center_y);                              \
   for (dir_itr = 0; dir_itr < 8; dir_itr++) {                                 \
+    if (!is_valid_dir(dir_itr)) {                                            \
+      continue;                                                                
      \
+    }                                                                        \
     DIRSTEP(x_itr, y_itr, dir_itr);                                           \
     x_itr += MACRO_center_x;                                                  \
     y_itr += MACRO_center_y;                                                  \
@@ -609,9 +615,23 @@
 
 /* is the direction "cardinal"?  Cardinal directions
  * (also called cartesian) are the four main ones */
-#define DIR_IS_CARDINAL(dir)                           \
-  ((dir) == DIR8_NORTH || (dir) == DIR8_EAST ||        \
-   (dir) == DIR8_WEST || (dir) == DIR8_SOUTH)
+static inline bool DIR_IS_CARDINAL(enum direction8 dir)
+{
+  switch (dir) {
+  case DIR8_NORTH:
+  case DIR8_SOUTH:
+  case DIR8_EAST:
+  case DIR8_WEST:
+    return TRUE;
+  case DIR8_NORTHEAST:
+  case DIR8_NORTHWEST:
+  case DIR8_SOUTHEAST:
+  case DIR8_SOUTHWEST:
+    /* In hex all directions are "cardinal". */
+    return topo_has_flag(TF_HEX);
+  }
+  return FALSE;
+}
 
 enum direction8 dir_cw(enum direction8 dir);
 enum direction8 dir_ccw(enum direction8 dir);
@@ -621,26 +641,14 @@
 extern const int DIR_DX[8];
 extern const int DIR_DY[8];
 
-/* like DIR_DX[] and DIR_DY[], only cartesian */
-extern const int CAR_DIR_DX[4];
-extern const int CAR_DIR_DY[4];
-
 #define cartesian_adjacent_iterate(x, y, IAC_x, IAC_y)                        \
 {                                                                             \
-  int IAC_i;                                                                  \
-  int IAC_x, IAC_y;                                                           \
-  bool _is_border = IS_BORDER_MAP_POS(x, y, 1);                               \
-  CHECK_MAP_POS(x, y);                                                        \
-  for (IAC_i = 0; IAC_i < 4; IAC_i++) {                                       \
-    IAC_x = x + CAR_DIR_DX[IAC_i];                                            \
-    IAC_y = y + CAR_DIR_DY[IAC_i];                                            \
-                                                                              \
-    if (_is_border && !normalize_map_pos(&IAC_x, &IAC_y)) {                   \
-      continue;                                                               \
-    }
+  adjc_dir_iterate(x, y, IAC_x, IAC_y, _dir) {                               \
+    if (DIR_IS_CARDINAL(_dir)) {
 
 #define cartesian_adjacent_iterate_end                                        \
-  }                                                                           \
+    }                                                                         \
+  } adjc_dir_iterate_end;                                                    \
 }
 
 /* Used for network transmission; do not change. */
@@ -666,7 +674,7 @@
 #define MAP_ORIGINAL_TOPO        TF_WRAPX
 #define MAP_DEFAULT_TOPO         TF_WRAPX
 #define MAP_MIN_TOPO             0
-#define MAP_MAX_TOPO             7
+#define MAP_MAX_TOPO             15
 
 #define MAP_DEFAULT_SEED         0
 #define MAP_MIN_SEED             0
@@ -743,6 +751,11 @@
 ****************************************************************************/
 static inline bool IS_BORDER_MAP_POS(int map_x, int map_y, int dist)
 {
+  if (topo_has_flag(TF_HEX)) {
+    /* TODO */
+    return TRUE;
+  }
+
   do_in_native_pos(nat_x, nat_y, map_x, map_y) {
     /* HACK: An iso-map compresses the value in the X direction but not in
      * the Y direction.  Hence (x+1,y) is 1 tile away while (x,y+2) is also
Index: server/mapgen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/mapgen.c,v
retrieving revision 1.137
diff -u -r1.137 mapgen.c
--- server/mapgen.c     12 Jun 2004 17:42:28 -0000      1.137
+++ server/mapgen.c     20 Jun 2004 04:49:53 -0000
@@ -832,9 +832,10 @@
     for (func_num = 0; func_num < NUM_TEST_FUNCTIONS; func_num++) {
       int best_val = -1;
       /* first get the tile values for the function */
-      for (dir = 0; dir < 4; dir++) {
-       int x1 = x + CAR_DIR_DX[dir];
-       int y1 = y + CAR_DIR_DY[dir];
+      adjc_dir_iterate(x, y, x1, y1, dir) {
+       if (!DIR_IS_CARDINAL(dir)) {
+         continue;
+       }
        if (normalize_map_pos(&x1, &y1)
            && rd_direction_is_valid[dir]) {
          rd_comparison_val[dir] = (test_funcs[func_num].func) (x1, y1);
@@ -844,22 +845,23 @@
            best_val = MIN(rd_comparison_val[dir], best_val);
          }
        }
-      }
+      } adjc_dir_iterate_end;
       assert(best_val != -1);
 
       /* should we abort? */
       if (best_val > 0 && test_funcs[func_num].fatal) return FALSE;
 
       /* mark the less attractive directions as invalid */
-      for (dir = 0; dir < 4; dir++) {
-       int x1 = x + CAR_DIR_DX[dir];
-       int y1 = y + CAR_DIR_DY[dir];
+      adjc_dir_iterate(x, y, x1, y1, dir) {
+       if (!DIR_IS_CARDINAL(dir)) {
+         continue;
+       }
        if (normalize_map_pos(&x1, &y1)
            && rd_direction_is_valid[dir]) {
          if (rd_comparison_val[dir] != best_val)
            rd_direction_is_valid[dir] = FALSE;
        }
-      }
+      } adjc_dir_iterate_end;
     }
 
     /* Directions evaluated with all functions. Now choose the best
@@ -873,16 +875,17 @@
     case 0:
       return FALSE; /* river aborted */
     case 1:
-      for (dir = 0; dir < 4; dir++) {
-       int x1 = x + CAR_DIR_DX[dir];
-       int y1 = y + CAR_DIR_DY[dir];
+      adjc_dir_iterate(x, y, x1, y1, dir) {
+       if (!DIR_IS_CARDINAL(dir)) {
+         continue;
+       }
        if (normalize_map_pos(&x1, &y1)
            && rd_direction_is_valid[dir]) {
          river_blockmark(x, y);
          x = x1;
          y = y1;
        }
-      }
+      } adjc_dir_iterate_end;
       break;
     default:
       /* More than one possible direction; Let the random number
@@ -893,9 +896,10 @@
       freelog(LOG_DEBUG, "mapgen.c: direction: %d", direction);
 
       /* Find the direction that the random number generator selected. */
-      for (dir = 0; dir < 4; dir++) {
-       int x1 = x + CAR_DIR_DX[dir];
-       int y1 = y + CAR_DIR_DY[dir];
+      adjc_dir_iterate(x, y, x1, y1, dir) {
+       if (!DIR_IS_CARDINAL(dir)) {
+         continue;
+       }
        if (normalize_map_pos(&x1, &y1)
            && rd_direction_is_valid[dir]) {
          if (direction > 0) direction--;
@@ -906,7 +910,7 @@
            break;
          }
        }
-      }
+      } adjc_dir_iterate_end;
       break;
     } /* end switch (rd_number_of_directions()) */
 
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.170
diff -u -r1.170 srv_main.c
--- server/srv_main.c   17 Jun 2004 19:50:41 -0000      1.170
+++ server/srv_main.c   20 Jun 2004 04:49:53 -0000
@@ -1645,7 +1645,7 @@
   test_random1(200000);
 #endif
     
-  if (topo_has_flag(TF_ISO) && topo_has_flag(TF_WRAPY)
+  if ((topo_has_flag(TF_ISO) || topo_has_flag(TF_HEX)) && 
topo_has_flag(TF_WRAPY)
       && (map.ysize % 2 == 1)) {
     /* To wrap north-south an iso-map must have even Y dimension.  Since the
      * X dimension is compressed this isn't an issue for east-west
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.323
diff -u -r1.323 stdinhand.c
--- server/stdinhand.c  12 Jun 2004 17:42:28 -0000      1.323
+++ server/stdinhand.c  20 Jun 2004 04:49:54 -0000
@@ -273,7 +273,15 @@
             "  4 Flat Earth (isometric)\n"
             "  5 Earth (isometric)\n"
             "  6 Uranus (isometric)\n"
-            "  7 Donut World (isometric)"
+            "  7 Donut World (isometric)\n"
+            "  8 Flat Earth (hexagonal)\n"
+            "  9 Earth (hexagonal)\n"
+            " 10 Uranus (hexagonal)\n"
+            " 11 Donut World (hexagonal)\n"
+            " 12 Flat Earth (iso-hex)\n"
+            " 13 Earth (iso-hex)\n"
+            " 14 Uranus (iso-hex)\n"
+            " 15 Donut World (iso-hex)"
           ), NULL, 
          MAP_MIN_TOPO, MAP_MAX_TOPO, MAP_DEFAULT_TOPO)
 

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] Re: (PR#7481) meta-ticket for hex maps, Jason Short <=