Complete.Org: Mailing Lists: Archives: freeciv-dev: November 2005:
[Freeciv-Dev] (PR#14664) rewrite client city drawing code
Home

[Freeciv-Dev] (PR#14664) rewrite client city drawing code

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#14664) rewrite client city drawing code
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 22 Nov 2005 00:47:39 -0800
Reply-to: bugs@xxxxxxxxxxx

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

This patch rewrites the client code to load and draw city sprites.  The 
new code is vastly simpler and more extensible.

Instead of storing "thresholds" and style information globally, a single 
opaque city_sprite struct exists.  This holds all possible sprites for 
drawing of a single element (city-tile, wall, or occupied-flag) based on 
city style and size.  As many or as few different sprites may be set for 
each as needed.

The structure is accessed via simple functions: load_city_sprite, 
get_city_sprite, free_city_sprite.  It's not 100% opaque though since 2 
small places outside of these functions do access the internals.

Overall code is reduced.  It's also more extensible because new elements 
can be drawn with the style-and-size options without added complexity. 
For instance to have the disorder sprite be based on city style and size 
would be quite trivial.

At the moment only the Amplio tileset is updated and tested.  I'll 
update the others before committing.

This cleanup is inspired by PR#14443.  One goal is to remove the use of 
city_got_citywalls from the tilespec code.  However this is not easy 
because in iso-view the city-walls sprite is not an overlay: it replaces 
the regular sprite.  So the tileset will have to be changed. 
Additionally a simple overlay is not enough: we have to have an underlay 
as well since the city wall appears both in front of and behind the core 
city graphic.  In general choosing the ordering of the city graphics if 
multiple buildings were involved would not be easy and would take more code.

-jason

Index: data/amplio/medievalcities.spec
===================================================================
--- data/amplio/medievalcities.spec     (revision 11263)
+++ data/amplio/medievalcities.spec     (working copy)
@@ -39,33 +39,33 @@
 
 ; used by all city styles
 
- 2,  11, "city.european_occupied"
- 2,  11, "city.industrial_occupied"
+ 2,  11, "city.european_occupied_0"
+ 2,  11, "city.industrial_occupied_0"
 
 ;
 ; city tiles
 ;
 
- 0,  0, "city.european_0"
- 0,  1, "city.european_4"
- 0,  2, "city.european_8"
- 0,  3, "city.european_12"
- 0,  4, "city.european_16" 
- 0,  5, "city.european_0_wall"
- 0,  6, "city.european_4_wall"
- 0,  7, "city.european_8_wall"
- 0,  8, "city.european_12_wall"
- 0,  9, "city.european_16_wall"
+ 0,  0, "city.european_city_0"
+ 0,  1, "city.european_city_4"
+ 0,  2, "city.european_city_8"
+ 0,  3, "city.european_city_12"
+ 0,  4, "city.european_city_16" 
+ 0,  5, "city.european_wall_0"
+ 0,  6, "city.european_wall_4"
+ 0,  7, "city.european_wall_8"
+ 0,  8, "city.european_wall_12"
+ 0,  9, "city.european_wall_16"
  
- 1,  0, "city.industrial_0"
- 1,  1, "city.industrial_4"
- 1,  2, "city.industrial_8"
- 1,  3, "city.industrial_12"
- 1,  4, "city.industrial_16" 
- 1,  5, "city.industrial_0_wall"
- 1,  6, "city.industrial_4_wall"
- 1,  7, "city.industrial_8_wall"
- 1,  8, "city.industrial_12_wall"
- 1,  9, "city.industrial_16_wall" 
+ 1,  0, "city.industrial_city_0"
+ 1,  1, "city.industrial_city_4"
+ 1,  2, "city.industrial_city_8"
+ 1,  3, "city.industrial_city_12"
+ 1,  4, "city.industrial_city_16" 
+ 1,  5, "city.industrial_wall_0"
+ 1,  6, "city.industrial_wall_4"
+ 1,  7, "city.industrial_wall_8"
+ 1,  8, "city.industrial_wall_12"
+ 1,  9, "city.industrial_wall_16"
 
 }
Index: data/amplio/ancientcities.spec
===================================================================
--- data/amplio/ancientcities.spec      (revision 11263)
+++ data/amplio/ancientcities.spec      (working copy)
@@ -41,73 +41,73 @@
 
 ; used by all city styles
 
- 2,  11, "city.asian_occupied"
- 2,  11, "city.tropical_occupied"
- 2,  11, "city.celtic_occupied"
- 2,  11, "city.classical_occupied"
- 2,  11, "city.babylonian_occupied"
+ 2,  11, "city.asian_occupied_0"
+ 2,  11, "city.tropical_occupied_0"
+ 2,  11, "city.celtic_occupied_0"
+ 2,  11, "city.classical_occupied_0"
+ 2,  11, "city.babylonian_occupied_0"
 
 
 ;
 ; city tiles
 ;
 
- 0,  0, "city.asian_0"
- 0,  1, "city.asian_4"
- 0,  2, "city.asian_8"
- 0,  3, "city.asian_12"
- 0,  4, "city.asian_16" 
- 0,  5, "city.asian_0_wall"
- 0,  6, "city.asian_4_wall"
- 0,  7, "city.asian_8_wall"
- 0,  8, "city.asian_12_wall"
- 0,  9, "city.asian_16_wall" 
+ 0,  0, "city.asian_city_0"
+ 0,  1, "city.asian_city_4"
+ 0,  2, "city.asian_city_8"
+ 0,  3, "city.asian_city_12"
+ 0,  4, "city.asian_city_16" 
+ 0,  5, "city.asian_wall_0"
+ 0,  6, "city.asian_wall_4"
+ 0,  7, "city.asian_wall_8"
+ 0,  8, "city.asian_wall_12"
+ 0,  9, "city.asian_wall_16" 
    
 
- 1,  0, "city.tropical_0"
- 1,  1, "city.tropical_4"
- 1,  2, "city.tropical_8"
- 1,  3, "city.tropical_12"
- 1,  4, "city.tropical_16" 
- 1,  5, "city.tropical_0_wall"
- 1,  6, "city.tropical_4_wall"
- 1,  7, "city.tropical_8_wall"
- 1,  8, "city.tropical_12_wall"
- 1,  9, "city.tropical_16_wall" 
+ 1,  0, "city.tropical_city_0"
+ 1,  1, "city.tropical_city_4"
+ 1,  2, "city.tropical_city_8"
+ 1,  3, "city.tropical_city_12"
+ 1,  4, "city.tropical_city_16" 
+ 1,  5, "city.tropical_wall_0"
+ 1,  6, "city.tropical_wall_4"
+ 1,  7, "city.tropical_wall_8"
+ 1,  8, "city.tropical_wall_12"
+ 1,  9, "city.tropical_wall_16" 
 
 
- 2,  0, "city.celtic_0"
- 2,  1, "city.celtic_4"
- 2,  2, "city.celtic_8"
- 2,  3, "city.celtic_12"
- 2,  4, "city.celtic_16" 
- 2,  5, "city.celtic_0_wall"
- 2,  6, "city.celtic_4_wall"
- 2,  7, "city.celtic_8_wall"
- 2,  8, "city.celtic_12_wall"
- 2,  9, "city.celtic_16_wall" 
+ 2,  0, "city.celtic_city_0"
+ 2,  1, "city.celtic_city_4"
+ 2,  2, "city.celtic_city_8"
+ 2,  3, "city.celtic_city_12"
+ 2,  4, "city.celtic_city_16" 
+ 2,  5, "city.celtic_wall_0"
+ 2,  6, "city.celtic_wall_4"
+ 2,  7, "city.celtic_wall_8"
+ 2,  8, "city.celtic_wall_12"
+ 2,  9, "city.celtic_wall_16" 
 
 
- 3,  0, "city.classical_0"
- 3,  1, "city.classical_4"
- 3,  2, "city.classical_8"
- 3,  3, "city.classical_12"
- 3,  4, "city.classical_16"
- 3,  5, "city.classical_0_wall"
- 3,  6, "city.classical_4_wall"
- 3,  7, "city.classical_8_wall"
- 3,  8, "city.classical_12_wall"
- 3,  9, "city.classical_16_wall"
+ 3,  0, "city.classical_city_0"
+ 3,  1, "city.classical_city_4"
+ 3,  2, "city.classical_city_8"
+ 3,  3, "city.classical_city_12"
+ 3,  4, "city.classical_city_16"
+ 3,  5, "city.classical_wall_0"
+ 3,  6, "city.classical_wall_4"
+ 3,  7, "city.classical_wall_8"
+ 3,  8, "city.classical_wall_12"
+ 3,  9, "city.classical_wall_16"
 
- 4,  0, "city.babylonian_0"
- 4,  1, "city.babylonian_4"
- 4,  2, "city.babylonian_8"
- 4,  3, "city.babylonian_12"
- 4,  4, "city.babylonian_16"
- 4,  5, "city.babylonian_0_wall"
- 4,  6, "city.babylonian_4_wall"
- 4,  7, "city.babylonian_8_wall"
- 4,  8, "city.babylonian_12_wall"
- 4,  9, "city.babylonian_16_wall"
+ 4,  0, "city.babylonian_city_0"
+ 4,  1, "city.babylonian_city_4"
+ 4,  2, "city.babylonian_city_8"
+ 4,  3, "city.babylonian_city_12"
+ 4,  4, "city.babylonian_city_16"
+ 4,  5, "city.babylonian_wall_0"
+ 4,  6, "city.babylonian_wall_4"
+ 4,  7, "city.babylonian_wall_8"
+ 4,  8, "city.babylonian_wall_12"
+ 4,  9, "city.babylonian_wall_16"
 
 }
Index: data/amplio/moderncities.spec
===================================================================
--- data/amplio/moderncities.spec       (revision 11263)
+++ data/amplio/moderncities.spec       (working copy)
@@ -50,47 +50,47 @@
  0,  2, "tx.airbase_full"
  0,  4, "tx.fortress"
  0,  5, "tx.fortress_back"
- 0,  6, "city.electricage_occupied"
- 0,  6, "city.modern_occupied"
- 0,  6, "city.postmodern_occupied"
+ 0,  6, "city.electricage_occupied_0"
+ 0,  6, "city.modern_occupied_0"
+ 0,  6, "city.postmodern_occupied_0"
 
 ;
 ; city tiles
 ;
 
- 2,  0, "city.electricage_0"
- 2,  1, "city.electricage_4"
- 2,  2, "city.electricage_8"
- 2,  3, "city.electricage_12"
- 2,  4, "city.electricage_16" 
- 2,  5, "city.electricage_0_wall"
- 2,  6, "city.electricage_4_wall"
- 2,  7, "city.electricage_8_wall"
- 2,  8, "city.electricage_12_wall"
- 2,  9, "city.electricage_16_wall" 
+ 2,  0, "city.electricage_city_0"
+ 2,  1, "city.electricage_city_4"
+ 2,  2, "city.electricage_city_8"
+ 2,  3, "city.electricage_city_12"
+ 2,  4, "city.electricage_city_16" 
+ 2,  5, "city.electricage_wall_0"
+ 2,  6, "city.electricage_wall_4"
+ 2,  7, "city.electricage_wall_8"
+ 2,  8, "city.electricage_wall_12"
+ 2,  9, "city.electricage_wall_16" 
 
 
- 3,  0, "city.modern_0"
- 3,  1, "city.modern_4"
- 3,  2, "city.modern_8"
- 3,  3, "city.modern_12"
- 3,  4, "city.modern_16"
- 3,  5, "city.modern_0_wall"
- 3,  6, "city.modern_4_wall"
- 3,  7, "city.modern_8_wall"
- 3,  8, "city.modern_12_wall"
- 3,  9, "city.modern_16_wall"
+ 3,  0, "city.modern_city_0"
+ 3,  1, "city.modern_city_4"
+ 3,  2, "city.modern_city_8"
+ 3,  3, "city.modern_city_12"
+ 3,  4, "city.modern_city_16"
+ 3,  5, "city.modern_wall_0"
+ 3,  6, "city.modern_wall_4"
+ 3,  7, "city.modern_wall_8"
+ 3,  8, "city.modern_wall_12"
+ 3,  9, "city.modern_wall_16"
 
 
- 4,  0, "city.postmodern_0"
- 4,  1, "city.postmodern_4"
- 4,  2, "city.postmodern_8"
- 4,  3, "city.postmodern_12"
- 4,  4, "city.postmodern_16" 
- 4,  5, "city.postmodern_0_wall"
- 4,  6, "city.postmodern_4_wall"
- 4,  7, "city.postmodern_8_wall"
- 4,  8, "city.postmodern_12_wall"
- 4,  9, "city.postmodern_16_wall" 
+ 4,  0, "city.postmodern_city_0"
+ 4,  1, "city.postmodern_city_4"
+ 4,  2, "city.postmodern_city_8"
+ 4,  3, "city.postmodern_city_12"
+ 4,  4, "city.postmodern_city_16" 
+ 4,  5, "city.postmodern_wall_0"
+ 4,  6, "city.postmodern_wall_4"
+ 4,  7, "city.postmodern_wall_8"
+ 4,  8, "city.postmodern_wall_12"
+ 4,  9, "city.postmodern_wall_16" 
 
 }
Index: data/amplio.tilespec
===================================================================
--- data/amplio.tilespec        (revision 11263)
+++ data/amplio.tilespec        (working copy)
@@ -2,7 +2,7 @@
 [tilespec]
 
 ; Format and options of this tilespec file:
-options = "+tilespec3 +Freeciv.Devel.2005.Oct.9"
+options = "+tilespec3 +Freeciv.Devel.2005.Nov.22"
 
 ; A simple name for the tileset specified by this file:
 name = "amplio"
Index: common/city.h
===================================================================
--- common/city.h       (revision 11263)
+++ common/city.h       (working copy)
@@ -307,10 +307,6 @@
   bool debug;
 };
 
-/* city drawing styles */
-
-#define MAX_CITY_TILES 8
-
 struct citystyle {
   const char *name; /* Translated string - doesn't need freeing. */
   char name_orig[MAX_LEN_NAME];              /* untranslated */
@@ -320,9 +316,6 @@
   char citizens_graphic_alt[MAX_LEN_NAME];
   struct requirement_vector reqs;
   int replaced_by;              /* index to replacing style          */
-                                /* client side-only:                 */
-  int tresh[MAX_CITY_TILES];    /* treshholds - what city size to use a tile */
-  int tiles_num;                /* number of "normal" city tiles,    */
 };                              /* not incl. wall and occupied tiles */
 
 extern struct citystyle *city_styles;
Index: client/packhand.c
===================================================================
--- client/packhand.c   (revision 11263)
+++ client/packhand.c   (working copy)
@@ -2056,7 +2056,6 @@
 **************************************************************************/
 void handle_ruleset_control(struct packet_ruleset_control *packet)
 {
-  tileset_free_city_tiles(tileset, game.control.styles_count);
   ruleset_data_free();
 
   ruleset_cache_init();
@@ -2065,7 +2064,6 @@
   governments_alloc(packet->government_count);
   nations_alloc(packet->nation_count);
   city_styles_alloc(packet->styles_count);
-  tileset_alloc_city_tiles(tileset, game.control.styles_count);
 }
 
 /**************************************************************************
Index: client/tilespec.c
===================================================================
--- client/tilespec.c   (revision 11263)
+++ client/tilespec.c   (working copy)
@@ -111,6 +111,16 @@
   struct sprite *mine;
 };
 
+struct city_sprite {
+  struct {
+    int num_thresholds;
+    struct {
+      int city_size;
+      struct sprite *sprite;
+    } *thresholds;
+  } *styles;
+};
+
 struct named_sprites {
   struct sprite
     *indicator[INDICATOR_COUNT][NUM_TILES_PROGRESS],
@@ -200,15 +210,16 @@
   } upkeep;
   struct {
     struct sprite
-      *occupied,
       *disorder,
       *size[NUM_TILES_DIGITS],
       *size_tens[NUM_TILES_DIGITS],            /* first unused */
       *tile_foodnum[NUM_TILES_DIGITS],
       *tile_shieldnum[NUM_TILES_DIGITS],
-      *tile_tradenum[NUM_TILES_DIGITS],
-      ***tile_wall,      /* only used for isometric view */
-      ***tile;
+      *tile_tradenum[NUM_TILES_DIGITS];
+    struct city_sprite
+      *tile,
+      *wall,
+      *occupied;
     struct sprite_vector worked_tile_overlay;
     struct sprite_vector unworked_tile_overlay;
   } city;
@@ -393,7 +404,7 @@
 
 struct tileset *tileset;
 
-#define TILESPEC_CAPSTR "+tilespec3 duplicates_ok +Freeciv.Devel.2005.Oct.9"
+#define TILESPEC_CAPSTR "+tilespec3 duplicates_ok +Freeciv.Devel.2005.Nov.22"
 /*
  * Tilespec capabilities acceptable to this program:
  *
@@ -888,7 +899,6 @@
    * We free all old data in preparation for re-reading it.
    */
   tileset_free_tiles(tileset);
-  tileset_free_city_tiles(tileset, game.control.styles_count);
   tileset_free_toplevel(tileset);
 
   /* Step 2:  Read.
@@ -947,9 +957,6 @@
     tileset_setup_specialist_type(tileset, sp);
   } specialist_type_iterate_end;
 
-  /* tilespec_load_tiles reverts the city tile pointers to 0.  This
-     is a workaround. */
-  tileset_alloc_city_tiles(tileset, game.control.styles_count);
   for (id = 0; id < game.control.styles_count; id++) {
     tileset_setup_city_tiles(tileset, id);
   }
@@ -1855,6 +1862,105 @@
   }
 }
 
+/****************************************************************************
+  Return the sprite in the city_sprite listing that corresponds to this
+  city - based on city style and size.
+
+  See also load_city_sprite, free_city_sprite.
+****************************************************************************/
+static struct sprite *get_city_sprite(const struct city_sprite *city_sprite,
+                                     const struct city *pcity)
+{
+  /* get style and match the best tile based on city size */
+  int style = get_city_style(pcity);
+  int num_thresholds = city_sprite->styles[style].num_thresholds;
+  int t;
+
+  if (num_thresholds == 0) {
+    return NULL;
+  }
+
+  for (t = 0; t < num_thresholds - 1; t++) {
+    if (pcity->size < city_sprite->styles[style].thresholds[t].city_size) {
+      break;
+    }
+  }
+
+  return city_sprite->styles[style].thresholds[t].sprite;
+}
+
+/****************************************************************************
+  Allocates and loads a new city sprite from the given sprite tags.
+
+  tag may be NULL.
+
+  See also get_city_sprite, free_city_sprite.
+****************************************************************************/
+static struct city_sprite *load_city_sprite(struct tileset *t,
+                                           const char *tag)
+{
+  struct city_sprite *city_sprite = fc_malloc(sizeof(*city_sprite));
+  int style, size;
+  char buffer[128];
+
+  city_sprite->styles = fc_malloc(game.control.styles_count
+                                 * sizeof(*city_sprite->styles));
+
+  for (style = 0; style < game.control.styles_count; style++) {
+    int thresholds = 0;
+    struct sprite *sprite;
+    char *graphic = city_styles[style].graphic;
+
+    city_sprite->styles[style].thresholds = NULL;
+    for (size = 0; size < MAX_CITY_SIZE; size++) {
+      my_snprintf(buffer, sizeof(buffer), "%s_%s_%d",
+                 city_styles[style].graphic, tag, size);
+      if ((sprite = load_sprite(t, buffer))) {
+       thresholds++;
+       city_sprite->styles[style].thresholds
+         = fc_realloc(city_sprite->styles[style].thresholds,
+                      thresholds
+                      * sizeof(*city_sprite->styles[style].thresholds));
+       city_sprite->styles[style].thresholds[thresholds - 1].city_size = size;
+       city_sprite->styles[style].thresholds[thresholds - 1].sprite = sprite;
+      } else if (size == 0) {
+       if (graphic == city_styles[style].graphic) {
+         /* Try again with graphic_alt. */
+         size--;
+         graphic = city_styles[style].graphic_alt;
+       } else {
+         /* Don't load any others if the 0 element isn't there. */
+         break;
+       }
+      }
+    }
+    city_sprite->styles[style].num_thresholds = thresholds;
+  }
+
+  return city_sprite;
+}
+
+/****************************************************************************
+  Frees a city sprite.
+
+  See also get_city_sprite, load_city_sprite.
+****************************************************************************/
+static void free_city_sprite(struct city_sprite *city_sprite)
+{
+  int style;
+
+  if (!city_sprite) {
+    return;
+  }
+  for (style = 0; style < game.control.styles_count; style++) {
+    if (city_sprite->styles[style].thresholds) {
+      free(city_sprite->styles[style].thresholds);
+    }
+  }
+  free(city_sprite->styles);
+  free(city_sprite);
+}
+
 /**********************************************************************
   Initialize 'sprites' structure based on hardwired tags which
   freeciv always requires. 
@@ -2322,8 +2428,6 @@
   }
 
   /* no other place to initialize these variables */
-  t->sprites.city.tile_wall = NULL;
-  t->sprites.city.tile = NULL;
   sprite_vector_init(&t->sprites.nation_flag);
   sprite_vector_init(&t->sprites.nation_shield);
 }
@@ -2728,54 +2832,6 @@
   }
 }
 
-/**************************************************************************
-Return the sprite needed to draw the city
-**************************************************************************/
-static struct sprite *get_city_sprite(const struct tileset *t,
-                                     const struct city *pcity)
-{
-  int size, style;
-
-  style = get_city_style(pcity);    /* get style and match the best tile */
-                                    /* based on city size                */
-  for( size=0; size < city_styles[style].tiles_num; size++)
-    if( pcity->size < city_styles[style].tresh[size]) 
-      break;
-
-  if (t->is_isometric) {
-    if (city_got_citywalls(pcity)) {
-      return t->sprites.city.tile_wall[style][size - 1];
-    } else {
-      return t->sprites.city.tile[style][size - 1];
-    }
-  } else {
-    return t->sprites.city.tile[style][size - 1];
-  }
-}
-
-/**************************************************************************
-Return the sprite needed to draw the city wall
-Not used for isometric view.
-**************************************************************************/
-static struct sprite *get_city_wall_sprite(const struct tileset *t,
-                                          const struct city *pcity)
-{
-  int style = get_city_style(pcity);
-
-  return t->sprites.city.tile[style][city_styles[style].tiles_num];
-}
-
-/**************************************************************************
-Return the sprite needed to draw the occupied tile
-**************************************************************************/
-static struct sprite *get_city_occupied_sprite(const struct tileset *t,
-                                              const struct city *pcity)
-{
-  int style = get_city_style(pcity);
-
-  return t->sprites.city.tile[style][city_styles[style].tiles_num + 1];
-}
-
 #define FULL_TILE_X_OFFSET ((t->normal_tile_width - t->full_tile_width) / 2)
 #define FULL_TILE_Y_OFFSET (t->normal_tile_height - t->full_tile_height)
 
@@ -3983,13 +4039,20 @@
                   FULL_TILE_X_OFFSET + t->city_flag_offset_x,
                   FULL_TILE_Y_OFFSET + t->city_flag_offset_y);
       }
-      ADD_SPRITE_FULL(get_city_sprite(t, pcity));
+      /* For iso-view the city.wall graphics include the full city, whereas
+       * for non-iso view they are an overlay on top of the base city
+       * graphic. */
+      if (!t->is_isometric || !city_got_citywalls(pcity)) {
+       ADD_SPRITE_FULL(get_city_sprite(t->sprites.city.tile, pcity));
+      }
+      if (t->is_isometric && city_got_citywalls(pcity)) {
+       ADD_SPRITE_FULL(get_city_sprite(t->sprites.city.wall, pcity));
+      }
       if (!draw_full_citybar && pcity->client.occupied) {
-       ADD_SPRITE_FULL(get_city_occupied_sprite(t, pcity));
+       ADD_SPRITE_FULL(get_city_sprite(t->sprites.city.occupied, pcity));
       }
       if (!t->is_isometric && city_got_citywalls(pcity)) {
-       /* In iso-view the city wall is a part of the city sprite. */
-       ADD_SPRITE_SIMPLE(get_city_wall_sprite(t, pcity));
+       ADD_SPRITE_FULL(get_city_sprite(t->sprites.city.wall, pcity));
       }
       if (pcity->client.unhappy) {
        ADD_SPRITE_FULL(t->sprites.city.disorder);
@@ -4091,142 +4154,33 @@
   Set city tiles sprite values; should only happen after
   tilespec_load_tiles().
 ***********************************************************************/
-static void tileset_setup_style_tile(struct tileset *t,
-                                    int style, char *graphics)
+void tileset_setup_city_tiles(struct tileset *t, int style)
 {
-  struct sprite *sp;
-  char buffer[128];
-  int j;
-  struct sprite *sp_wall = NULL;
-  char buffer_wall[128];
+  if (style == game.control.styles_count - 1) {
+    t->sprites.city.tile = load_city_sprite(t, "city");
+    t->sprites.city.wall = load_city_sprite(t, "wall");
+    t->sprites.city.occupied = load_city_sprite(t, "occupied");
 
-  city_styles[style].tiles_num = 0;
-
-  for(j=0; j<32 && city_styles[style].tiles_num < MAX_CITY_TILES; j++) {
-    my_snprintf(buffer, sizeof(buffer), "%s_%d", graphics, j);
-    sp = load_sprite(t, buffer);
-    if (t->is_isometric) {
-      my_snprintf(buffer, sizeof(buffer_wall), "%s_%d_wall", graphics, j);
-      sp_wall = load_sprite(t, buffer);
-    }
-    if (sp) {
-      t->sprites.city.tile[style][city_styles[style].tiles_num] = sp;
-      if (t->is_isometric) {
-       assert(sp_wall != NULL);
-       t->sprites.city.tile_wall[style][city_styles[style].tiles_num]
-         = sp_wall;
+    for (style = 0; style < game.control.styles_count; style++) {
+      if (t->sprites.city.tile->styles[style].num_thresholds == 0) {
+       freelog(LOG_ERROR, "No city graphics for %s style.",
+               city_styles[style].name);
+       exit(EXIT_FAILURE);
       }
-      city_styles[style].tresh[city_styles[style].tiles_num] = j;
-      city_styles[style].tiles_num++;
-      freelog(LOG_DEBUG, "Found tile %s_%d", graphics, j);
+      if (t->sprites.city.wall->styles[style].num_thresholds == 0) {
+       freelog(LOG_ERROR, "No wall graphics for %s style.",
+               city_styles[style].name);
+       exit(EXIT_FAILURE);
+      }
+      if (t->sprites.city.occupied->styles[style].num_thresholds == 0) {
+       freelog(LOG_ERROR, "No occupied graphics for %s style.",
+               city_styles[style].name);
+       exit(EXIT_FAILURE);
+      }
     }
   }
-
-  if(city_styles[style].tiles_num == 0)      /* don't waste more time */
-    return;
-
-  if (!t->is_isometric) {
-    /* the wall tile */
-    my_snprintf(buffer, sizeof(buffer), "%s_wall", graphics);
-    sp = load_sprite(t, buffer);
-    if (sp) {
-      t->sprites.city.tile[style][city_styles[style].tiles_num] = sp;
-    } else {
-      freelog(LOG_NORMAL, "Warning: no wall tile for graphic %s", graphics);
-    }
-  }
-
-  /* occupied tile */
-  my_snprintf(buffer, sizeof(buffer), "%s_occupied", graphics);
-  sp = load_sprite(t, buffer);
-  if (sp) {
-    t->sprites.city.tile[style][city_styles[style].tiles_num + 1] = sp;
-  } else {
-    freelog(LOG_NORMAL, "Warning: no occupied tile for graphic %s", graphics);
-  }
 }
 
-/**********************************************************************
-  Set city tiles sprite values; should only happen after
-  tilespec_load_tiles().
-***********************************************************************/
-void tileset_setup_city_tiles(struct tileset *t, int style)
-{
-  tileset_setup_style_tile(t, style, city_styles[style].graphic);
-
-  if (city_styles[style].tiles_num == 0) {
-    /* no tiles found, try alternate */
-    freelog(LOG_NORMAL, "No tiles for %s style, trying alternate %s style",
-            city_styles[style].graphic, city_styles[style].graphic_alt);
-
-    tileset_setup_style_tile(t, style, city_styles[style].graphic_alt);
-  }
-
-  if (city_styles[style].tiles_num == 0) {
-      /* no alternate, use default */
-
-    freelog(LOG_NORMAL,
-           "No tiles for alternate %s style, using default tiles",
-            city_styles[style].graphic_alt);
-
-    t->sprites.city.tile[style][0] = load_sprite(t, "cd.city");
-    t->sprites.city.tile[style][1] = load_sprite(t, "cd.city_wall");
-    t->sprites.city.tile[style][2] = load_sprite(t, "cd.occupied");
-    city_styles[style].tiles_num = 1;
-    city_styles[style].tresh[0] = 0;
-  }
-}
-
-/**********************************************************************
-  alloc memory for city tiles sprites
-***********************************************************************/
-void tileset_alloc_city_tiles(struct tileset *t, int count)
-{
-  int i;
-
-  if (t->is_isometric) {
-    t->sprites.city.tile_wall
-      = fc_calloc(count, sizeof(*t->sprites.city.tile_wall));
-  } else {
-    t->sprites.city.tile_wall = NULL;
-  }
-  t->sprites.city.tile = fc_calloc(count, sizeof(*t->sprites.city.tile));
-
-  for (i = 0; i < count; i++) {
-    if (t->is_isometric) {
-      t->sprites.city.tile_wall[i]
-       = fc_calloc(MAX_CITY_TILES + 2,
-                   sizeof(*t->sprites.city.tile_wall[0]));
-    }
-    t->sprites.city.tile[i]
-      = fc_calloc(MAX_CITY_TILES + 2, sizeof(*t->sprites.city.tile[0]));
-  }
-}
-
-/**********************************************************************
-  alloc memory for city tiles sprites
-***********************************************************************/
-void tileset_free_city_tiles(struct tileset *t, int count)
-{
-  int i;
-
-  for (i = 0; i < count; i++) {
-    if (t->is_isometric) {
-      free(t->sprites.city.tile_wall[i]);
-      t->sprites.city.tile_wall[i] = NULL;
-    }
-    free(t->sprites.city.tile[i]);
-    t->sprites.city.tile[i] = NULL;
-  }
-
-  if (t->is_isometric) {
-    free(t->sprites.city.tile_wall);
-    t->sprites.city.tile_wall = NULL;
-  }
-  free(t->sprites.city.tile);
-  t->sprites.city.tile = NULL;
-}
-
 /****************************************************************************
   Return the amount of time between calls to toggle_focus_unit_state.
   The main loop needs to call toggle_focus_unit_state about this often
@@ -4326,6 +4280,13 @@
 
   unload_all_sprites(t);
 
+  free_city_sprite(t->sprites.city.tile);
+  t->sprites.city.tile = NULL;
+  free_city_sprite(t->sprites.city.wall);
+  t->sprites.city.wall = NULL;
+  free_city_sprite(t->sprites.city.occupied);
+  t->sprites.city.occupied = NULL;
+
   if (t->sprite_hash) {
     const int entries = hash_num_entries(t->sprite_hash);
 
@@ -4489,9 +4450,14 @@
 struct sprite *get_sample_city_sprite(const struct tileset *t,
                                      int city_style)
 {
-  int index = city_styles[city_style].tiles_num - 1;
+  int num_thresholds = t->sprites.city.tile->styles[city_style].num_thresholds;
 
-  return t->sprites.city.tile[city_style][index];
+  if (num_thresholds == 0) {
+    return NULL;
+  } else {
+    return (t->sprites.city.tile->styles[city_style]
+           .thresholds[num_thresholds - 1].sprite);
+  }
 }
 
 /**************************************************************************
Index: client/tilespec.h
===================================================================
--- client/tilespec.h   (revision 11263)
+++ client/tilespec.h   (working copy)
@@ -123,8 +123,6 @@
 void tileset_setup_government(struct tileset *t, int id);
 void tileset_setup_nation_flag(struct tileset *t, int id);
 void tileset_setup_city_tiles(struct tileset *t, int style);
-void tileset_alloc_city_tiles(struct tileset *t, int count);
-void tileset_free_city_tiles(struct tileset *t, int count);
 
 /* Gfx support */
 

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