Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2004:
[Freeciv-Dev] (PR#8817) generate city map indices
Home

[Freeciv-Dev] (PR#8817) generate city map indices

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#8817) generate city map indices
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 23 May 2004 00:44:53 -0700
Reply-to: rt@xxxxxxxxxxx

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

This patch is a rework of Remi's patch in PR#7350 to generate the city 
map indices.

I've changed it in several ways:

- Rathar than a linked-list solution with insertion sort I used a purely 
array solution with qsort.  This requires much less code (and is no 
doubt faster but who cares).

- The radius is _not_ passed to the generate function.  Rather the 
generate function should already know the radius.  If the radius is 
loaded from the ruleset, for instance, it will be stored in some global 
variable.

- Rather than calling the function when the ruleset is loaded I call it 
when the game starts.  This is a bit questionable but I'm not sure where 
else it should go.

- I use fc_realloc to avoid memory leaks when generate_indices is called 
multiple times (when the server plays multiple games, or the client 
reconnects).

My goal here is a little broader than Remi's.  His original patch only 
considered that the indices might be changed based on the ruleset. 
However I'm thinking about hex-tiled maps too, where the indices are 
changed based on the topology.

As a side note I would like to use a similar solution (reusing the 
iter_index struct) for iterate_outwards in map.h.  For iterate_outwards 
(and in Remi's city-radius patch) it is actually useful to have the 
distance stored in the array so that you can tell when it's time to stop 
the iteration.  However for the current code the "dist" element is 
unused except in the generation of the array.

As another side note it is easy to make city_map_iterate a wrapper for 
city_map_iterate_outwards.  I believe this is what Ross has suggested. 
In fact it might be simpler to remove city_map_iterate_outwards and just 
make all citymap iteration follow the outwards ordering.

jason

? convert.sh
? flags
? data/flags
Index: client/civclient.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.c,v
retrieving revision 1.187
diff -u -r1.187 civclient.c
--- client/civclient.c  21 Apr 2004 19:46:37 -0000      1.187
+++ client/civclient.c  23 May 2004 07:35:00 -0000
@@ -405,6 +405,7 @@
     client_state=newstate;
 
     if (client_state == CLIENT_GAME_RUNNING_STATE) {
+      generate_city_map_indices();
       load_ruleset_specific_options();
       create_event(-1, -1, E_GAME_START, _("Game started."));
       update_research(game.player_ptr);
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.211
diff -u -r1.211 city.c
--- common/city.c       21 May 2004 19:03:43 -0000      1.211
+++ common/city.c       23 May 2004 07:35:06 -0000
@@ -16,6 +16,7 @@
 #endif
 
 #include <assert.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "fcintl.h"
@@ -52,20 +53,7 @@
                                      bool asmiths);
 
 /* Iterate a city map, from the center (the city) outwards */
-
-int city_map_iterate_outwards_indices[CITY_TILES][2] =
-{
-  { 2, 2 },
-
-  { 1, 2 }, { 2, 1 }, { 3, 2 }, { 2, 3 },
-  { 1, 3 }, { 1, 1 }, { 3, 1 }, { 3, 3 },
-
-  { 0, 2 }, { 2, 0 }, { 4, 2 }, { 2, 4 },
-  { 0, 3 }, { 0, 1 },
-  { 1, 0 }, { 3, 0 },
-  { 4, 1 }, { 4, 3 },
-  { 3, 4 }, { 1, 4 }
-};
+struct iter_index *city_map_iterate_outwards_indices;
 
 struct citystyle *city_styles = NULL;
 
@@ -168,6 +156,62 @@
 }
 
 /**************************************************************************
+  Compare two iter_index values from the city_map_iterate_outward_indices.
+
+  This function will be passed to qsort().
+***************************************************************************/
+static int compare_index(const void *a, const void *b)
+{
+  const struct iter_index *index1 = a, *index2 = b;
+
+  if (index1->dist > index2->dist) {
+    return 1;
+  } else if (index1->dist < index2->dist) {
+    return -1;
+  } else {
+    return 0;
+  }
+}
+
+/**************************************************************************
+  Fill the iterate_outwards_indices array.  This may depend on topology and
+  ruleset settings.
+***************************************************************************/
+void generate_city_map_indices(void)
+{
+  int i = 0, x, y;
+  struct iter_index *array = city_map_iterate_outwards_indices;
+
+  /* Realloc is used because this function may be called multiple times. */
+  array = fc_realloc(array, CITY_TILES * sizeof(*array));
+
+  for (x = 0; x < CITY_MAP_SIZE; x++) {
+    for (y = 0; y < CITY_MAP_SIZE; y++) {
+      if (is_valid_city_coords(x, y)) {
+       int dx = x - CITY_MAP_RADIUS, dy = y - CITY_MAP_RADIUS;
+
+       array[i].x = x;
+       array[i].y = y;
+       array[i].dist = dx * dx + dy * dy;
+       i++;
+      }
+    }
+  }
+  assert(i == CITY_TILES);
+
+  qsort(array, CITY_TILES, sizeof(*array), compare_index);
+
+#ifdef DEBUG
+  for (i = 0; i < CITY_TILES; i++) {
+    freelog(LOG_NORMAL, "%2d : (%2d,%2d) : %d",
+           i, array[i].x, array[i].y, array[i].dist);
+  }
+#endif
+
+  city_map_iterate_outwards_indices = array;
+}
+
+/**************************************************************************
   Set the worker on the citymap.  Also sets the worked field in the map.
 **************************************************************************/
 void set_worker_city(struct city *pcity, int city_x, int city_y,
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.143
diff -u -r1.143 city.h
--- common/city.h       20 May 2004 21:38:53 -0000      1.143
+++ common/city.h       23 May 2004 07:35:06 -0000
@@ -102,26 +102,22 @@
 }
 
 /* Iterate a city map, from the center (the city) outwards */
+extern struct iter_index {
+  int x, y, dist;
+} *city_map_iterate_outwards_indices;
+
+/* Iterate a city map, from the center (the city) outwards.
+ * (city_x, city_y) will be the city coordinates. */
+#define city_map_iterate_outwards(city_x, city_y)                          \
+{                                                                          \
+  int city_x, city_y, _index;                                              \
+                                                                           \
+  for (_index = 0; _index < CITY_TILES; _index++) {                        \
+    city_x = city_map_iterate_outwards_indices[_index].x;                  \
+    city_y = city_map_iterate_outwards_indices[_index].y;
 
-extern int city_map_iterate_outwards_indices[CITY_TILES][2];
-
-/* Iterate a city map, from the center (the city) outwards. x and y
-   will be elements of [0, CITY_MAP_SIZE). */
-#define city_map_iterate_outwards(x, y) {                                      
\
-  int x, y;                                                                    
\
-  int city_map_iterate_outwards_index;                                         
\
-  for                                                                          
\
-  (                                                                            
\
-    city_map_iterate_outwards_index = 0;                                       
\
-    city_map_iterate_outwards_index < CITY_TILES;                              
\
-    city_map_iterate_outwards_index++                                          
\
-  )                                                                            
\
-  {                                                                            
\
-    x = city_map_iterate_outwards_indices[city_map_iterate_outwards_index][0]; 
\
-    y = city_map_iterate_outwards_indices[city_map_iterate_outwards_index][1];
-
-#define city_map_iterate_outwards_end                                          
\
-  }                                                                            
\
+#define city_map_iterate_outwards_end                                       \
+  }                                                                         \
 }
 
 /*
@@ -395,6 +391,7 @@
                         int city_map_y);
 bool city_map_to_map(int *map_x, int *map_y, const struct city *const pcity,
                    int city_map_x, int city_map_y);
+void generate_city_map_indices(void);
 
 /* shield on spot */
 int city_get_shields_tile(int city_x, int city_y, struct city *pcity);
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.160
diff -u -r1.160 srv_main.c
--- server/srv_main.c   2 May 2004 14:47:12 -0000       1.160
+++ server/srv_main.c   23 May 2004 07:35:06 -0000
@@ -1544,6 +1544,7 @@
     load_rulesets();
     /* otherwise rulesets were loaded when savegame was loaded */
   }
+  generate_city_map_indices();
 
   nations_avail = fc_calloc(game.playable_nation_count, sizeof(int));
   nations_used = fc_calloc(game.playable_nation_count, sizeof(int));

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#8817) generate city map indices, Jason Short <=