Complete.Org: Mailing Lists: Archives: freeciv-dev: July 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: Mon, 19 Jul 2004 10:26:07 -0700
Reply-to: rt@xxxxxxxxxxx

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

Jason Short wrote:
> <URL: http://rt.freeciv.org/Ticket/Display.html?id=7481 >
> 
> Here is a complete and updated patch for hex maps.
> 
> I plan to break this up into some smaller patches.  Including:
> 
> - Rewrite iterate_outward.
> - New iterator iterate_outward_dxy used by square_dxy_iterate.
> - Remove rectangle_iterate.
> - Fix circle_iterate.
> - ADD HEX STUFF

And here's the new patch.  Steps 1, 2, and 3 above are complete.  The 
patch is now just 10k in size.

jason

Index: client/connectdlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/connectdlg_common.c,v
retrieving revision 1.14
diff -u -r1.14 connectdlg_common.c
--- client/connectdlg_common.c  30 Jun 2004 14:34:30 -0000      1.14
+++ client/connectdlg_common.c  19 Jul 2004 17:21:43 -0000
@@ -243,12 +243,18 @@
    * 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)
+              | ((hex_width != 0 || hex_height != 0) ? TF_HEX : 0)));
   send_chat(buf);
 
   return TRUE;
Index: common/map.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.c,v
retrieving revision 1.180
diff -u -r1.180 map.c
--- common/map.c        18 Jul 2004 17:09:39 -0000      1.180
+++ common/map.c        19 Jul 2004 17:21:44 -0000
@@ -318,7 +318,7 @@
 
   /* In TF_ISO we need to double the map.ysize factor, since xsize is
    * in native coordinates which are compressed 2x in the X direction. */ 
-  const int iso = topo_has_flag(TF_ISO) ? 2 : 1;
+  const int iso = (topo_has_flag(TF_ISO) || topo_has_flag(TF_HEX)) ? 2 : 1;
 
   /* We have:
    *
@@ -537,7 +537,13 @@
 ****************************************************************************/
 static int map_vector_to_distance(int dx, int dy)
 {
-  return abs(dx) + abs(dy);
+  if (topo_has_flag(TF_HEX)) {
+    /* Hex: all directions are cardinal so the distance is equivalent to
+     * the real distance. */
+    return map_vector_to_real_distance(dx, dy);
+  } else {
+    return abs(dx) + abs(dy);
+  }
 }
 
 /****************************************************************************
@@ -545,7 +551,33 @@
 ****************************************************************************/
 int map_vector_to_real_distance(int dx, int dy)
 {
-  return MAX(abs(dx), abs(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 MAX(abs(dx), abs(dy));
+  }
 }
 
 /****************************************************************************
@@ -553,7 +585,15 @@
 ****************************************************************************/
 int map_vector_to_sq_distance(int dx, int dy)
 {
-  return dx * dx + dy * dy;
+  if (topo_has_flag(TF_HEX)) {
+    /* Hex: The square distance is just the square of the real distance; we
+     * don't worry about pythagorean calculations. */
+    int dist = map_vector_to_real_distance(dx, dy);
+
+    return dist * dist;
+  } else {
+    return dx * dx + dy * dy;
+  }
 }
 
 /***************************************************************
@@ -1722,14 +1762,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.197
diff -u -r1.197 map.h
--- common/map.h        19 Jul 2004 17:13:38 -0000      1.197
+++ common/map.h        19 Jul 2004 17:21:45 -0000
@@ -183,7 +183,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)
@@ -236,13 +237,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)))
@@ -329,9 +330,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);
@@ -487,7 +489,7 @@
   int _cr_radius = (int)sqrt((double)(sq_radius));                            \
   square_dxy_iterate(center_x, center_y, _cr_radius,                          \
                     x_itr, y_itr, _dx, _dy) {                                \
-    if (_dy * _dy + _dx * _dx <= (sq_radius)) {
+    if (map_vector_to_sq_distance(_dx, _dy) <= (sq_radius)) {
 
 #define circle_iterate_end                                                    \
     }                                                                         \
@@ -579,9 +581,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_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));
+  }
+  return FALSE;
+}
 
 enum direction8 dir_cw(enum direction8 dir);
 enum direction8 dir_ccw(enum direction8 dir);
@@ -614,7 +630,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
@@ -695,7 +711,9 @@
     /* 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
      * one tile away. */
-    int xdist = dist, ydist = topo_has_flag(TF_ISO) ? (2 * dist) : dist;
+    int xdist = dist;
+    int ydist = ((topo_has_flag(TF_ISO) || topo_has_flag(TF_HEX))
+                ? (2 * dist) : dist);
 
     return (nat_x < xdist 
            || nat_y < ydist
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.326
diff -u -r1.326 stdinhand.c
--- server/stdinhand.c  12 Jul 2004 15:51:11 -0000      1.326
+++ server/stdinhand.c  19 Jul 2004 17:21:47 -0000
@@ -274,7 +274,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 <=