Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2005:
[Freeciv-Dev] (PR#13171) turn specials into an enum
Home

[Freeciv-Dev] (PR#13171) turn specials into an enum

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#13171) turn specials into an enum
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 24 May 2005 12:56:05 -0700
Reply-to: bugs@xxxxxxxxxxx

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

This patch turns the specials from a mask to a true enum.  A bitvector
is used for storing special "sets", as in ptile->special.  We've
discussed several times why this is better than using masked integer values.

This is a preliminary patch.  I believe it works but it needs more
testing and scrutiny.  This is a pretty major change.

-jason

Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.175
diff -u -r1.175 control.c
--- client/control.c    7 May 2005 05:48:53 -0000       1.175
+++ client/control.c    24 May 2005 19:53:04 -0000
@@ -914,7 +914,7 @@
   }
 
   dsend_packet_unit_change_activity(&aconnection, punit->id, act,
-                                   S_NO_SPECIAL);
+                                   S_LAST);
 }
 
 /**************************************************************************
@@ -990,7 +990,7 @@
     /* Sentry the unit.  Don't request_unit_sentry since this can give a
      * recursive loop. */
     dsend_packet_unit_change_activity(&aconnection, pcargo->id,
-                                     ACTIVITY_SENTRY, S_NO_SPECIAL);
+                                     ACTIVITY_SENTRY, S_LAST);
   }
 }
 
@@ -1010,7 +1010,7 @@
 
     /* Activate the unit. */
     dsend_packet_unit_change_activity(&aconnection, pcargo->id,
-                                     ACTIVITY_IDLE, S_NO_SPECIAL);
+                                     ACTIVITY_IDLE, S_LAST);
   }
 }
 
@@ -1113,18 +1113,25 @@
 void request_unit_pillage(struct unit *punit)
 {
   struct tile *ptile = punit->tile;
-  enum tile_special_type pspresent = get_tile_infrastructure_set(ptile);
-  enum tile_special_type psworking =
-      get_unit_tile_pillage_set(punit->tile);
-  enum tile_special_type what =
-      get_preferred_pillage(pspresent & (~psworking));
-  enum tile_special_type would =
-      what | get_infrastructure_prereq(what);
-
-  if ((game.info.pillage_select) &&
-      ((pspresent & (~(psworking | would))) != S_NO_SPECIAL)) {
-    popup_pillage_dialog(punit, (pspresent & (~psworking)));
+  bv_special pspresent = get_tile_infrastructure_set(ptile, NULL);
+  bv_special psworking = get_unit_tile_pillage_set(punit->tile);
+  bv_special pspossible;
+  int count = 0;
+  enum tile_special_type spe;
+
+  BV_CLR_ALL(pspossible);
+  for (spe = 0; spe < S_LAST; spe++) {
+    if (BV_ISSET(pspresent, spe) && !BV_ISSET(psworking, spe)) {
+      BV_SET(pspossible, spe);
+      count++;
+    }
+  }
+
+  if (count > 1) {
+    popup_pillage_dialog(punit, pspossible);
   } else {
+    enum tile_special_type what = get_preferred_pillage(pspossible);
+
     request_new_unit_activity_targeted(punit, ACTIVITY_PILLAGE, what);
   }
 }
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.518
diff -u -r1.518 packhand.c
--- client/packhand.c   22 May 2005 17:48:10 -0000      1.518
+++ client/packhand.c   24 May 2005 19:53:04 -0000
@@ -1856,14 +1856,24 @@
   enum known_type old_known = client_tile_get_known(ptile);
   bool tile_changed = FALSE;
   bool known_changed = FALSE;
+  enum tile_special_type spe;
 
   if (ptile->terrain != packet->type) { /*terrain*/
     tile_changed = TRUE;
     ptile->terrain = packet->type;
   }
-  if (ptile->special != packet->special) { /*add-on*/
-    tile_changed = TRUE;
-    ptile->special = packet->special;
+  for (spe = 0; spe < S_LAST; spe++) {
+    if (packet->special[spe]) {
+      if (!tile_has_special(ptile, spe)) {
+       tile_set_special(ptile, spe);
+       tile_changed = TRUE;
+      }
+    } else {
+      if (tile_has_special(ptile, spe)) {
+       tile_clear_special(ptile, spe);
+       tile_changed = TRUE;
+      }
+    }
   }
   if (packet->owner == MAP_TILE_OWNER_NULL) {
     if (ptile->owner) {
Index: client/text.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/text.c,v
retrieving revision 1.40
diff -u -r1.40 text.c
--- client/text.c       7 May 2005 18:58:02 -0000       1.40
+++ client/text.c       24 May 2005 19:53:04 -0000
@@ -158,6 +158,8 @@
      "" /*unused, DS_CEASEFIRE */,
      Q_("?city:Peaceful"), Q_("?city:Friendly"), Q_("?city:Mysterious"),
      Q_("?city:Friendly(team)")};
+  int infracount;
+  bv_special infra;
   INIT;
 
 #ifdef DEBUG
@@ -241,8 +243,9 @@
                 hcity->name, trade_between_cities(hcity, pcity));
       }
     } 
-  } 
-  if (get_tile_infrastructure_set(ptile)) {
+  }
+  infra = get_tile_infrastructure_set(ptile, &infracount);
+  if (infracount > 0) {
     add_line(_("Infrastructure: %s"),
             get_infrastructure_text(ptile->special));
   }
@@ -568,8 +571,9 @@
   if (punit) {
     struct city *pcity =
        player_find_city_by_id(game.player_ptr, punit->homecity);
-    int infrastructure =
-       get_tile_infrastructure_set(punit->tile);
+    int infracount;
+    bv_special infrastructure =
+      get_tile_infrastructure_set(punit->tile, &infracount);
 
     if (hover_unit == punit->id) {
       add_line(_("Turns to target: %d"), get_goto_turns());
@@ -578,7 +582,7 @@
     }
 
     add_line("%s", tile_get_info_text(punit->tile));
-    if (infrastructure) {
+    if (infracount > 0) {
       add_line("%s", get_infrastructure_text(infrastructure));
     } else {
       add_line(" ");
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.307
diff -u -r1.307 tilespec.c
--- client/tilespec.c   22 May 2005 18:12:52 -0000      1.307
+++ client/tilespec.c   24 May 2005 19:53:05 -0000
@@ -2733,9 +2733,9 @@
 **************************************************************************/
 static void build_tile_data(const struct tile *ptile,
                            Terrain_type_id *ttype,
-                           enum tile_special_type *tspecial,
+                           bv_special *tspecial,
                            Terrain_type_id *ttype_near,
-                           enum tile_special_type *tspecial_near)
+                           bv_special *tspecial_near)
 {
   enum direction8 dir;
 
@@ -2752,7 +2752,7 @@
     } else {
       /* We draw the edges of the (known) map as if the same terrain just
        * continued off the edge of the map. */
-      tspecial_near[dir] = S_NO_SPECIAL;
+      BV_CLR_ALL(tspecial_near[dir]);
       ttype_near[dir] = *ttype;
     }
   }
@@ -2976,8 +2976,8 @@
 **************************************************************************/
 static int fill_road_rail_sprite_array(const struct tileset *t,
                                       struct drawn_sprite *sprs,
-                                      enum tile_special_type tspecial,
-                                      enum tile_special_type *tspecial_near,
+                                      bv_special tspecial,
+                                      bv_special *tspecial_near,
                                       const struct city *pcity)
 {
   struct drawn_sprite *saved_sprs = sprs;
@@ -3163,7 +3163,7 @@
   this).
 **************************************************************************/
 static int get_irrigation_index(const struct tileset *t,
-                               enum tile_special_type *tspecial_near)
+                               bv_special *tspecial_near)
 {
   int tileno = 0, i;
 
@@ -3184,8 +3184,8 @@
 **************************************************************************/
 static int fill_irrigation_sprite_array(const struct tileset *t,
                                        struct drawn_sprite *sprs,
-                                       enum tile_special_type tspecial,
-                                       enum tile_special_type *tspecial_near,
+                                       bv_special tspecial,
+                                       bv_special *tspecial_near,
                                        const struct city *pcity)
 {
   struct drawn_sprite *saved_sprs = sprs;
@@ -3757,7 +3757,7 @@
                      const struct city *citymode)
 {
   Terrain_type_id ttype = T_UNKNOWN, ttype_near[8];
-  enum tile_special_type tspecial = S_NO_SPECIAL, tspecial_near[8];
+  bv_special tspecial, tspecial_near[8];
   int tileno, dir;
   struct unit *pfocus = get_unit_in_focus();
   struct drawn_sprite *save_sprs = sprs;
Index: client/gui-gtk-2.0/dialogs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/dialogs.c,v
retrieving revision 1.105
diff -u -r1.105 dialogs.c
--- client/gui-gtk-2.0/dialogs.c        22 May 2005 18:05:06 -0000      1.105
+++ client/gui-gtk-2.0/dialogs.c        24 May 2005 19:53:06 -0000
@@ -1090,9 +1090,10 @@
 ...
 *****************************************************************/
 void popup_pillage_dialog(struct unit *punit,
-                         enum tile_special_type may_pillage)
+                         bv_special may_pillage)
 {
   GtkWidget *shl;
+  enum tile_special_type what, prereq;
 
   if (!is_showing_pillage_dialog) {
     is_showing_pillage_dialog = TRUE;
@@ -1102,13 +1103,19 @@
                               _("What To Pillage"),
                               _("Select what to pillage:"));
 
-    while (may_pillage != S_NO_SPECIAL) {
-      enum tile_special_type what = get_preferred_pillage(may_pillage);
+    while ((what = get_preferred_pillage(may_pillage)) != S_LAST) {
+      bv_special what_bv;
 
-      message_dialog_add(shl, get_infrastructure_text(what),
+      BV_CLR_ALL(what_bv);
+      BV_SET(what_bv, what);
+      message_dialog_add(shl, get_infrastructure_text(what_bv),
                         G_CALLBACK(pillage_callback), GINT_TO_POINTER(what));
 
-      may_pillage &= (~(what | get_infrastructure_prereq(what)));
+      clear_special(&may_pillage, what);
+      prereq = get_infrastructure_prereq(what);
+      if (prereq != S_LAST) {
+       clear_special(&may_pillage, prereq);
+      }
     }
 
     message_dialog_add(shl, GTK_STOCK_CANCEL, 0, 0);
Index: client/gui-gtk-2.0/menu.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/menu.c,v
retrieving revision 1.77
diff -u -r1.77 menu.c
--- client/gui-gtk-2.0/menu.c   8 May 2005 06:37:50 -0000       1.77
+++ client/gui-gtk-2.0/menu.c   24 May 2005 19:53:06 -0000
@@ -1159,27 +1159,10 @@
 static const char *get_tile_change_menu_text(struct tile *ptile,
                                             enum unit_activity activity)
 {
-  Terrain_type_id old_terrain = ptile->terrain;
-  enum tile_special_type old_special = ptile->special;
-  const char *text;
-
-  if(!(activity == ACTIVITY_IRRIGATE
-       || activity == ACTIVITY_MINE
-       || activity == ACTIVITY_TRANSFORM)) {
-    assert(0);
-    return "-";
-  }
-  else {
-    tile_apply_activity(ptile, activity);
-  }
-
-  text = tile_get_info_text(ptile);
-
-  /* Restore the original state of the tile. */
-  ptile->terrain = old_terrain;
-  ptile->special = old_special;
+  struct tile newtile = *ptile;
 
-  return text;
+  tile_apply_activity(&newtile, activity);
+  return tile_get_info_text(ptile);
 }
 
 /****************************************************************
Index: client/include/dialogs_g.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/include/dialogs_g.h,v
retrieving revision 1.25
diff -u -r1.25 dialogs_g.h
--- client/include/dialogs_g.h  22 May 2005 18:05:06 -0000      1.25
+++ client/include/dialogs_g.h  24 May 2005 19:53:06 -0000
@@ -41,8 +41,7 @@
 void popup_incite_dialog(struct city *pcity);
 void popup_bribe_dialog(struct unit *punit);
 void popup_sabotage_dialog(struct city *pcity);
-void popup_pillage_dialog(struct unit *punit,
-                         enum tile_special_type may_pillage);
+void popup_pillage_dialog(struct unit *punit, bv_special may_pillage);
 
 void popdown_all_game_dialogs(void);
 
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.347
diff -u -r1.347 city.c
--- common/city.c       14 May 2005 14:45:23 -0000      1.347
+++ common/city.c       24 May 2005 19:53:06 -0000
@@ -597,10 +597,10 @@
 
   if (auto_water) {
     /* The center tile is auto-irrigated. */
-    tile.special |= S_IRRIGATION;
+    tile_set_special(&tile, S_IRRIGATION);
 
     if (player_knows_techs_with_flag(city_owner(pcity), TF_FARMLAND)) {
-      tile.special |= S_FARMLAND;
+      tile_set_special(&tile, S_FARMLAND);
     }
   }
 
Index: common/map.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.c,v
retrieving revision 1.227
diff -u -r1.227 map.c
--- common/map.c        5 May 2005 18:32:50 -0000       1.227
+++ common/map.c        24 May 2005 19:53:07 -0000
@@ -59,11 +59,23 @@
 /****************************************************************************
   Return a bitfield of the specials on the tile that are infrastructure.
 ****************************************************************************/
-enum tile_special_type get_tile_infrastructure_set(const struct tile *ptile)
+bv_special get_tile_infrastructure_set(const struct tile *ptile,
+                                         int *pcount)
 {
-  return (ptile->special
-         & (S_ROAD | S_RAILROAD | S_IRRIGATION | S_FARMLAND | S_MINE
-            | S_FORTRESS | S_AIRBASE));
+  bv_special pspresent;
+  int i, count = 0;
+
+  BV_CLR_ALL(pspresent);
+  for (i = 0; infrastructure_specials[i] != S_LAST; i++) {
+    if (tile_has_special(ptile, infrastructure_specials[i])) {
+      BV_SET(pspresent, infrastructure_specials[i]);
+      count++;
+    }
+  }
+  if (pcount) {
+    *pcount = count;
+  }
+  return pspresent;
 }
 
 /***************************************************************
@@ -256,7 +268,7 @@
 static void tile_init(struct tile *ptile)
 {
   ptile->terrain  = T_UNKNOWN;
-  ptile->special  = S_NO_SPECIAL;
+  BV_CLR_ALL(ptile->special);
   BV_CLR_ALL(ptile->tile_known);
   BV_CLR_ALL(ptile->tile_seen);
   ptile->continent = 0;
Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.249
diff -u -r1.249 map.h
--- common/map.h        5 May 2005 18:32:51 -0000       1.249
+++ common/map.h        24 May 2005 19:53:07 -0000
@@ -247,7 +247,8 @@
 int map_move_cost_ai(const struct tile *tile0, const struct tile *tile1);
 bool is_safe_ocean(const struct tile *ptile);
 bool is_cardinally_adj_to_ocean(const struct tile *ptile);
-enum tile_special_type get_tile_infrastructure_set(const struct tile *ptile);
+bv_special get_tile_infrastructure_set(const struct tile *ptile,
+                                         int *count);
 
 bool can_channel_land(const struct tile *ptile);
 bool can_reclaim_ocean(const struct tile *ptile);
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.128
diff -u -r1.128 packets.def
--- common/packets.def  22 May 2005 18:05:06 -0000      1.128
+++ common/packets.def  24 May 2005 19:53:07 -0000
@@ -324,7 +324,7 @@
 
   TERRAIN type;
   UINT8 known;
-  SPECIAL special;
+  BOOL special[S_LAST];
   PLAYER owner;
   CONTINENT continent;
   STRING spec_sprite[MAX_LEN_NAME];
Index: common/requirements.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/requirements.c,v
retrieving revision 1.26
diff -u -r1.26 requirements.c
--- common/requirements.c       14 May 2005 15:34:41 -0000      1.26
+++ common/requirements.c       24 May 2005 19:53:07 -0000
@@ -124,7 +124,7 @@
     break;
   case REQ_SPECIAL:
     source.value.special = get_special_by_name(value);
-    if (source.value.special != S_NO_SPECIAL) {
+    if (source.value.special != S_LAST) {
       return source;
     }
     break;
Index: common/terrain.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/terrain.c,v
retrieving revision 1.22
diff -u -r1.22 terrain.c
--- common/terrain.c    5 May 2005 18:32:52 -0000       1.22
+++ common/terrain.c    24 May 2005 19:53:07 -0000
@@ -29,6 +29,17 @@
 
 struct tile_type tile_types[MAX_NUM_TERRAINS];
 
+enum tile_special_type infrastructure_specials[] = {
+  S_ROAD,
+  S_RAILROAD,
+  S_IRRIGATION,
+  S_FARMLAND,
+  S_MINE,
+  S_FORTRESS,
+  S_AIRBASE,
+  S_LAST
+};
+
 /***************************************************************
 ...
 ***************************************************************/
@@ -235,8 +246,19 @@
   N_("Fallout")
 };
 
+enum tile_special_type test[] = {
+  S_ROAD,
+  S_RAILROAD,
+  S_IRRIGATION,
+  S_FARMLAND,
+  S_MINE,
+  S_FORTRESS,
+  S_AIRBASE,
+  S_LAST
+};
+
 /****************************************************************************
-  Return the special with the given name, or S_NO_SPECIAL.
+  Return the special with the given name, or S_LAST.
 
   FIXME: should be find_special_by_name().
 ****************************************************************************/
@@ -245,15 +267,14 @@
   int i;
   enum tile_special_type st = 1;
 
-  for (i = 0; i < ARRAY_SIZE(tile_special_type_names); i++) {
+  assert(ARRAY_SIZE(tile_special_type_names) == S_LAST);
+  for (i = 0; i < S_LAST; i++) {
     if (0 == strcmp(name, tile_special_type_names[i])) {
       return st;
     }
-      
-    st <<= 1;
   }
 
-  return S_NO_SPECIAL;
+  return S_LAST;
 }
 
 /****************************************************************************
@@ -274,22 +295,31 @@
 }
 
 /***************************************************************
- Returns TRUE iff the given special is found in the given set.
+  Returns TRUE iff the given special is found in the given set.
 ***************************************************************/
-bool contains_special(enum tile_special_type set,
-                     enum tile_special_type to_test_for)
+void set_special(bv_special *set, enum tile_special_type to_set)
 {
-  enum tile_special_type masked = set & to_test_for;
-
-  assert(0 == (int) S_NO_SPECIAL);
+  assert(to_set >= 0 && to_set < S_LAST);
+  BV_SET(*set, to_set);
+}
 
-  /*
-   * contains_special should only be called with one S_* in
-   * to_test_for.
-   */
-  assert(masked == S_NO_SPECIAL || masked == to_test_for);
+/***************************************************************
+  Returns TRUE iff the given special is found in the given set.
+***************************************************************/
+void clear_special(bv_special *set, enum tile_special_type to_clear)
+{
+  assert(to_clear >= 0 && to_clear < S_LAST);
+  BV_CLR(*set, to_clear);
+}
 
-  return masked == to_test_for;
+/***************************************************************
+ Returns TRUE iff the given special is found in the given set.
+***************************************************************/
+bool contains_special(bv_special set,
+                     enum tile_special_type to_test_for)
+{
+  assert(to_test_for >= 0 && to_test_for < S_LAST);
+  return BV_ISSET(set, to_test_for);
 }
 
 /****************************************************************************
@@ -371,7 +401,7 @@
     eg: "Road/Farmland"
   This only includes "infrastructure", i.e., man-made specials.
 ****************************************************************************/
-const char *get_infrastructure_text(enum tile_special_type spe)
+const char *get_infrastructure_text(bv_special spe)
 {
   static char s[256];
   char *p;
@@ -417,16 +447,13 @@
 ****************************************************************************/
 enum tile_special_type get_infrastructure_prereq(enum tile_special_type spe)
 {
-  enum tile_special_type prereq = S_NO_SPECIAL;
-
-  if (contains_special(spe, S_RAILROAD)) {
-    prereq |= S_ROAD;
-  }
-  if (contains_special(spe, S_FARMLAND)) {
-    prereq |= S_IRRIGATION;
+  if (spe == S_RAILROAD) {
+    return S_ROAD;
+  } else if (spe == S_FARMLAND) {
+    return S_IRRIGATION;
+  } else {
+    return S_LAST;
   }
-
-  return prereq;
 }
 
 /****************************************************************************
@@ -434,7 +461,7 @@
   be pillaged from the terrain set.  May return S_NO_SPECIAL if nothing
   better is available.
 ****************************************************************************/
-enum tile_special_type get_preferred_pillage(enum tile_special_type pset)
+enum tile_special_type get_preferred_pillage(bv_special pset)
 {
   if (contains_special(pset, S_FARMLAND)) {
     return S_FARMLAND;
@@ -457,5 +484,5 @@
   if (contains_special(pset, S_ROAD)) {
     return S_ROAD;
   }
-  return S_NO_SPECIAL;
+  return S_LAST;
 }
Index: common/terrain.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/terrain.h,v
retrieving revision 1.34
diff -u -r1.34 terrain.h
--- common/terrain.h    5 May 2005 18:32:52 -0000       1.34
+++ common/terrain.h    24 May 2005 19:53:07 -0000
@@ -22,22 +22,23 @@
 };
 
 enum tile_special_type {
-  S_NO_SPECIAL =    0,
-  S_SPECIAL_1  =    1,
-  S_ROAD       =    2,
-  S_IRRIGATION =    4,
-  S_RAILROAD   =    8,
-  S_MINE       =   16,
-  S_POLLUTION  =   32,
-  S_HUT        =   64,
-  S_FORTRESS   =  128,
-  S_SPECIAL_2  =  256,
-  S_RIVER      =  512,
-  S_FARMLAND   = 1024,
-  S_AIRBASE    = 2048,
-  S_FALLOUT    = 4096
+  S_SPECIAL_1,
+  S_ROAD,
+  S_IRRIGATION,
+  S_RAILROAD,
+  S_MINE,
+  S_POLLUTION,
+  S_HUT,
+  S_FORTRESS,
+  S_SPECIAL_2,
+  S_RIVER,
+  S_FARMLAND,
+  S_AIRBASE,
+  S_FALLOUT,
+  S_LAST
 };
 
+#if 0
 #define S_ALL    \
  (  S_SPECIAL_1  \
   | S_ROAD       \
@@ -52,15 +53,12 @@
   | S_FARMLAND   \
   | S_AIRBASE    \
   | S_FALLOUT)
+#endif
 
-#define S_INFRASTRUCTURE_MASK \
-  (S_ROAD                   \
-   | S_RAILROAD             \
-   | S_IRRIGATION           \
-   | S_FARMLAND             \
-   | S_MINE                 \
-   | S_FORTRESS             \
-   | S_AIRBASE)
+/* S_LAST-terminated */
+extern enum tile_special_type infrastructure_specials[];
+
+BV_DEFINE(bv_special, S_LAST);
 
 #define T_NONE (-3) /* A special flag meaning no terrain type. */
 #define T_ANY (-2) /* A special flag that matches "any" terrain type. */
@@ -201,7 +199,9 @@
 /* General special accessor functions. */
 enum tile_special_type get_special_by_name(const char * name);
 const char *get_special_name(enum tile_special_type type);
-bool contains_special(enum tile_special_type all,
+void set_special(bv_special *all, enum tile_special_type to_set);
+void clear_special(bv_special *all, enum tile_special_type to_clear);
+bool contains_special(bv_special all,
                      enum tile_special_type to_test_for);
 
 /* Functions to operate on a terrain special. */
@@ -219,9 +219,9 @@
                                 enum terrain_flag_id flag);
 
 /* Special helper functions */
-const char *get_infrastructure_text(enum tile_special_type spe);
+const char *get_infrastructure_text(bv_special pset);
 enum tile_special_type get_infrastructure_prereq(enum tile_special_type spe);
-enum tile_special_type get_preferred_pillage(enum tile_special_type pset);
+enum tile_special_type get_preferred_pillage(bv_special pset);
 
 /* Terrain-specific functions. */
 #define is_ocean(x) (terrain_has_flag((x), TER_OCEANIC))
Index: common/tile.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/tile.c,v
retrieving revision 1.6
diff -u -r1.6 tile.c
--- common/tile.c       8 May 2005 06:37:50 -0000       1.6
+++ common/tile.c       24 May 2005 19:53:07 -0000
@@ -76,7 +76,7 @@
   Note that this returns a mask of _all_ the specials on the tile.  To
   check a specific special use tile_has_special.
 ****************************************************************************/
-enum tile_special_type tile_get_special(const struct tile *ptile)
+bv_special tile_get_special(const struct tile *ptile)
 {
   return ptile->special;
 }
@@ -100,7 +100,7 @@
 ****************************************************************************/
 void tile_set_special(struct tile *ptile, enum tile_special_type spe)
 {
-  ptile->special |= spe;
+  set_special(&ptile->special, spe);
 }
 
 /****************************************************************************
@@ -111,7 +111,7 @@
 ****************************************************************************/
 void tile_clear_special(struct tile *ptile, enum tile_special_type spe)
 {
-  ptile->special &= ~spe;
+  clear_special(&ptile->special, spe);
 }
 
 /****************************************************************************
@@ -119,8 +119,7 @@
 ****************************************************************************/
 void tile_clear_all_specials(struct tile *ptile)
 {
-  assert((int)S_NO_SPECIAL == 0);
-  ptile->special = S_NO_SPECIAL;
+  BV_CLR_ALL(ptile->special);
 }
 
 /****************************************************************************
@@ -192,7 +191,11 @@
 ****************************************************************************/
 static void tile_clear_infrastructure(struct tile *ptile)
 {
-  tile_clear_special(ptile, S_INFRASTRUCTURE_MASK);
+  int i;
+
+  for (i = 0; infrastructure_specials[i] != S_LAST; i++) {
+    tile_clear_special(ptile, infrastructure_specials[i]);
+  }
 }
 
 /****************************************************************************
Index: common/tile.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/tile.h,v
retrieving revision 1.8
diff -u -r1.8 tile.h
--- common/tile.h       8 May 2005 06:37:50 -0000       1.8
+++ common/tile.h       24 May 2005 19:53:07 -0000
@@ -29,7 +29,7 @@
   const int nat_x, nat_y; /* Native coordinates of the tile. */
   const int index; /* Index coordinate of the tile. */
   Terrain_type_id terrain;
-  enum tile_special_type special;
+  bv_special special;
   struct city *city;        /* city standing on the tile, NULL if none */
   struct unit_list *units;
   bv_player tile_known, tile_seen;
@@ -55,7 +55,7 @@
 void tile_set_city(struct tile *ptile, struct city *pcity);
 Terrain_type_id tile_get_terrain(const struct tile *ptile);
 void tile_set_terrain(struct tile *ptile, Terrain_type_id ter);
-enum tile_special_type tile_get_special(const struct tile *ptile);
+bv_special tile_get_special(const struct tile *ptile);
 bool tile_has_special(const struct tile *ptile,
                      enum tile_special_type to_test_for);
 void tile_set_special(struct tile *ptile, enum tile_special_type spe);
Index: common/unit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.c,v
retrieving revision 1.240
diff -u -r1.240 unit.c
--- common/unit.c       6 May 2005 20:11:52 -0000       1.240
+++ common/unit.c       24 May 2005 19:53:08 -0000
@@ -682,7 +682,7 @@
   bool result;
 
   punit->activity = ACTIVITY_IDLE;
-  punit->activity_target = S_NO_SPECIAL;
+  punit->activity_target = S_LAST;
 
   result = can_unit_do_activity_targeted(punit, current2, target);
 
@@ -702,7 +702,7 @@
 bool can_unit_do_activity(const struct unit *punit,
                          enum unit_activity activity)
 {
-  return can_unit_do_activity_targeted(punit, activity, S_NO_SPECIAL);
+  return can_unit_do_activity_targeted(punit, activity, S_LAST);
 }
 
 /**************************************************************************
@@ -851,27 +851,35 @@
 
   case ACTIVITY_PILLAGE:
     {
-      enum tile_special_type pspresent = get_tile_infrastructure_set(ptile);
-      enum tile_special_type psworking;
+      int numpresent;
+      bv_special pspresent = get_tile_infrastructure_set(ptile, &numpresent);
 
-      if (pspresent != S_NO_SPECIAL && is_ground_unit(punit)) {
-       psworking = get_unit_tile_pillage_set(ptile);
-       if (ptile->city && (contains_special(target, S_ROAD)
-                           || contains_special(target, S_RAILROAD))) {
+      if (numpresent > 0 && is_ground_unit(punit)) {
+       bv_special psworking;
+       int i;
+
+       if (ptile->city && (target == S_ROAD || target == S_RAILROAD)) {
          return FALSE;
        }
-       if (target == S_NO_SPECIAL) {
-         if (ptile->city) {
-           return ((pspresent & (~(psworking | S_ROAD | S_RAILROAD)))
-                   != S_NO_SPECIAL);
-         } else {
-           return ((pspresent & (~psworking)) != S_NO_SPECIAL);
+       psworking = get_unit_tile_pillage_set(ptile);
+       if (target == S_LAST) {
+         for (i = 0; infrastructure_specials[i] != S_LAST; i++) {
+           enum tile_special_type spe = infrastructure_specials[i];
+
+           if (ptile->city && (spe == S_ROAD || spe == S_RAILROAD)) {
+             /* Can't pillage this. */
+             continue;
+           }
+           if (BV_ISSET(pspresent, spe) && !BV_ISSET(psworking, spe)) {
+             /* Can pillage this! */
+             return TRUE;
+           }
          }
        } else if (!game.info.pillage_select
                   && target != get_preferred_pillage(pspresent)) {
          return FALSE;
        } else {
-         return ((pspresent & (~psworking) & target) != S_NO_SPECIAL);
+         return BV_ISSET(pspresent, target) && !BV_ISSET(psworking, target);
        }
       } else {
        return FALSE;
@@ -913,7 +921,7 @@
 {
   punit->activity=new_activity;
   punit->activity_count=0;
-  punit->activity_target = S_NO_SPECIAL;
+  punit->activity_target = S_LAST;
   if (new_activity == ACTIVITY_IDLE && punit->moves_left > 0) {
     /* No longer done. */
     punit->done_moving = FALSE;
@@ -949,13 +957,15 @@
   Return a mask of the specials which may be pillaged at the given
   tile.
 **************************************************************************/
-enum tile_special_type get_unit_tile_pillage_set(const struct tile *ptile)
+bv_special get_unit_tile_pillage_set(const struct tile *ptile)
 {
-  enum tile_special_type tgt_ret = S_NO_SPECIAL;
+  bv_special tgt_ret;
 
+  BV_CLR_ALL(tgt_ret);
   unit_list_iterate(ptile->units, punit) {
     if (punit->activity == ACTIVITY_PILLAGE) {
-      tgt_ret |= punit->activity_target;
+      assert(punit->activity_target < S_LAST);
+      BV_SET(tgt_ret, punit->activity_target);
     }
   } unit_list_iterate_end;
   return tgt_ret;
@@ -1025,12 +1035,16 @@
    case ACTIVITY_EXPLORE:
      return get_activity_text (punit->activity);
    case ACTIVITY_PILLAGE:
-     if(punit->activity_target == S_NO_SPECIAL) {
+     if (punit->activity_target == S_LAST) {
        return get_activity_text (punit->activity);
      } else {
+       bv_special pset;
+
+       BV_CLR_ALL(pset);
+       BV_SET(pset, punit->activity_target);
        my_snprintf(text, sizeof(text), "%s: %s",
                   get_activity_text (punit->activity),
-                  get_infrastructure_text(punit->activity_target));
+                  get_infrastructure_text(pset));
        return (text);
      }
    default:
Index: common/unit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v
retrieving revision 1.143
diff -u -r1.143 unit.h
--- common/unit.h       30 Apr 2005 17:09:28 -0000      1.143
+++ common/unit.h       24 May 2005 19:53:08 -0000
@@ -269,7 +269,7 @@
 bool can_unit_do_auto(const struct unit *punit); 
 bool is_unit_activity_on_tile(enum unit_activity activity,
                              const struct tile *ptile);
-enum tile_special_type get_unit_tile_pillage_set(const struct tile *ptile);
+bv_special get_unit_tile_pillage_set(const struct tile *ptile);
 bool is_attack_unit(const struct unit *punit);
 bool is_military_unit(const struct unit *punit);           /* !set !dip !cara 
*/
 bool is_diplomat_unit(const struct unit *punit);
Index: server/maphand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/maphand.c,v
retrieving revision 1.164
diff -u -r1.164 maphand.c
--- server/maphand.c    5 May 2005 18:32:53 -0000       1.164
+++ server/maphand.c    24 May 2005 19:53:09 -0000
@@ -465,13 +465,17 @@
 
   conn_list_iterate(dest, pconn) {
     struct player *pplayer = pconn->player;
+    enum tile_special_type spe;
+
     if (!pplayer && !pconn->observer) {
       continue;
     }
     if (!pplayer || map_is_known_and_seen(ptile, pplayer)) {
       info.known = TILE_KNOWN;
       info.type = ptile->terrain;
-      info.special = ptile->special;
+      for (spe = 0; spe < S_LAST; spe++) {
+       info.special[spe] = BV_ISSET(ptile->special, spe);
+      }
       info.continent = ptile->continent;
       send_packet_tile_info(pconn, &info);
     } else if (pplayer && map_is_known(ptile, pplayer)
@@ -480,7 +484,9 @@
       struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
       info.known = TILE_KNOWN_FOGGED;
       info.type = plrtile->terrain;
-      info.special = plrtile->special;
+      for (spe = 0; spe < S_LAST; spe++) {
+       info.special[spe] = BV_ISSET(plrtile->special, spe);
+      }
       info.continent = ptile->continent;
       send_packet_tile_info(pconn, &info);
     }
@@ -502,6 +508,7 @@
 {
   struct packet_tile_info info;
   struct player_tile *plrtile;
+  enum tile_special_type spe;
 
   info.x = ptile->x;
   info.y = ptile->y;
@@ -516,7 +523,9 @@
     /* Observer sees all. */
     info.known=TILE_KNOWN;
     info.type = ptile->terrain;
-    info.special = ptile->special;
+    for (spe = 0; spe < S_LAST; spe++) {
+      info.special[spe] = BV_ISSET(ptile->special, spe);
+    }
     info.continent = ptile->continent;
   } else if (map_is_known(ptile, pplayer)) {
     if (map_get_seen(ptile, pplayer) != 0) {
@@ -528,13 +537,17 @@
     }
     plrtile = map_get_player_tile(ptile, pplayer);
     info.type = plrtile->terrain;
-    info.special = plrtile->special;
+    for (spe = 0; spe < S_LAST; spe++) {
+      info.special[spe] = BV_ISSET(plrtile->special, spe);
+    }
     info.continent = ptile->continent;
   } else {
     /* Unknown (the client needs these sometimes to draw correctly). */
     info.known = TILE_UNKNOWN;
     info.type = ptile->terrain;
-    info.special = ptile->special;
+    for (spe = 0; spe < S_LAST; spe++) {
+      info.special[spe] = BV_ISSET(ptile->special, spe);
+    }
     info.continent = ptile->continent;
   }
   lsend_packet_tile_info(dest, &info);
@@ -1101,7 +1114,7 @@
     map_get_player_tile(ptile, pplayer);
 
   plrtile->terrain = T_UNKNOWN;
-  plrtile->special = S_NO_SPECIAL;
+  BV_CLR_ALL(plrtile->special);
   plrtile->city = NULL;
 
   plrtile->seen_count = 0;
@@ -1144,7 +1157,8 @@
   struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
 
   if (plrtile->terrain != ptile->terrain
-      || plrtile->special != ptile->special) {
+      || memcmp(&plrtile->special, &ptile->special,
+               sizeof(plrtile->special)) != 0) {
     plrtile->terrain = ptile->terrain;
     plrtile->special = ptile->special;
     return TRUE;
Index: server/maphand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/maphand.h,v
retrieving revision 1.55
diff -u -r1.55 maphand.h
--- server/maphand.h    4 May 2005 20:55:58 -0000       1.55
+++ server/maphand.h    24 May 2005 19:53:09 -0000
@@ -40,7 +40,7 @@
 
 struct player_tile {
   Terrain_type_id terrain;
-  enum tile_special_type special;
+  bv_special special;
   unsigned short seen_count;
   unsigned short own_seen;
   /* If you build a city with an unknown square within city radius
Index: server/sanitycheck.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/sanitycheck.c,v
retrieving revision 1.66
diff -u -r1.66 sanitycheck.c
--- server/sanitycheck.c        21 May 2005 19:40:25 -0000      1.66
+++ server/sanitycheck.c        24 May 2005 19:53:09 -0000
@@ -56,7 +56,7 @@
 {
   whole_map_iterate(ptile) {
     Terrain_type_id terrain = tile_get_terrain(ptile);
-    enum tile_special_type special = tile_get_special(ptile);
+    bv_special special = tile_get_special(ptile);
 
     if (contains_special(special, S_RAILROAD))
       SANITY_CHECK(contains_special(special, S_ROAD));
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.252
diff -u -r1.252 savegame.c
--- server/savegame.c   24 May 2005 16:45:39 -0000      1.252
+++ server/savegame.c   24 May 2005 19:53:10 -0000
@@ -629,12 +629,70 @@
 {
   /* Get the bits of the special flags which contain the river special
      and extract the rivers overlay from them. */
+  assert(S_LAST <= 32);
   LOAD_MAP_DATA(ch, line, ptile,
                secfile_lookup_str_default(file, NULL, "map.n%03d", line),
-               ptile->special |= (ascii_hex2bin(ch, 2) & S_RIVER));
+               ((ascii_hex2bin(ch, 2) & (1 << S_RIVER))
+                ? tile_set_special(ptile, S_RIVER) : (void)0));
   map.have_rivers_overlay = TRUE;
 }
 
+/****************************************************************************
+  Complicated helper function for loading specials from a savegame.
+
+  'ch' gives the character loaded from the savegame.  Specials are packed
+  in four to a character in hex notation.  'which' specifies which set
+  of specials are included in this character.
+****************************************************************************/
+static void set_savegame_special(bv_special *specials,
+                                char ch, int which)
+{
+  int i, bin;
+  char *pch = strchr(hex_chars, ch);
+
+  if (!pch || ch == '\0') {
+    freelog(LOG_ERROR, "Unknown hex value: '%c' %d", ch, ch);
+    bin = 0;
+  } else {
+    bin = pch - hex_chars;
+  }
+
+  for (i = 0; i < 4; i++) {
+    enum tile_special_type sp = 4 * which + i;
+
+    if (sp >= S_LAST) {
+      break;
+    }
+    if (bin & (1 << i)) {
+      set_special(specials, sp);
+    }
+  }
+}
+
+/****************************************************************************
+  Complicated helper function for saving specials into a savegame.
+
+  Specials are packed in four to a character in hex notation.  'which'
+  specifies which set of specials are included in this character.
+****************************************************************************/
+static char get_savegame_special(bv_special specials, int which)
+{
+  int i, bin = 0;
+
+  for (i = 0; i < 4; i++) {
+    enum tile_special_type sp = i + 4 * which;
+
+    if (sp >= S_LAST) {
+      break;
+    }
+    if (contains_special(specials, sp)) {
+      bin |= (1 << i);
+    }
+  }
+
+  return hex_chars[bin];
+}
+
 /***************************************************************
 load a complete map from a savegame file
 ***************************************************************/
@@ -657,16 +715,16 @@
   /* get 4-bit segments of 16-bit "special" field. */
   LOAD_MAP_DATA(ch, nat_y, ptile,
                secfile_lookup_str(file, "map.l%03d", nat_y),
-               ptile->special = ascii_hex2bin(ch, 0));
+               set_savegame_special(&ptile->special, ch, 0));
   LOAD_MAP_DATA(ch, nat_y, ptile,
                secfile_lookup_str(file, "map.u%03d", nat_y),
-               ptile->special |= ascii_hex2bin(ch, 1));
+               set_savegame_special(&ptile->special, ch, 1));
   LOAD_MAP_DATA(ch, nat_y, ptile,
                secfile_lookup_str_default(file, NULL, "map.n%03d", nat_y),
-               ptile->special |= ascii_hex2bin(ch, 2));
+               set_savegame_special(&ptile->special, ch, 2));
   LOAD_MAP_DATA(ch, nat_y, ptile,
                secfile_lookup_str_default(file, NULL, "map.f%03d", nat_y),
-               ptile->special |= ascii_hex2bin(ch, 3));
+               set_savegame_special(&ptile->special, ch, 3));
 
   if (secfile_lookup_bool_default(file, TRUE, "game.save_known")) {
     int known[MAP_INDEX_SIZE];
@@ -768,18 +826,18 @@
 
       /* bits 8-11 of special flags field */
       SAVE_NORMAL_MAP_DATA(ptile, file, "map.n%03d",
-                          bin2ascii_hex(ptile->special, 2));
+                          get_savegame_special(ptile->special, 2));
     }
     return;
   }
 
   /* put 4-bit segments of 12-bit "special flags" field */
   SAVE_NORMAL_MAP_DATA(ptile, file, "map.l%03d",
-                      bin2ascii_hex(ptile->special, 0));
+                      get_savegame_special(ptile->special, 0));
   SAVE_NORMAL_MAP_DATA(ptile, file, "map.u%03d",
-                      bin2ascii_hex(ptile->special, 1));
+                      get_savegame_special(ptile->special, 1));
   SAVE_NORMAL_MAP_DATA(ptile, file, "map.n%03d",
-                      bin2ascii_hex(ptile->special, 2));
+                      get_savegame_special(ptile->special, 2));
 
   secfile_insert_bool(file, game.save_options.save_known, "game.save_known");
   if (game.save_options.save_known) {
@@ -787,7 +845,7 @@
 
     /* put the top 4 bits (bits 12-15) of special flags */
     SAVE_NORMAL_MAP_DATA(ptile, file, "map.f%03d",
-                        bin2ascii_hex(ptile->special, 3));
+                        get_savegame_special(ptile->special, 3));
 
     /* HACK: we convert the data into a 32-bit integer, and then save it as
      * hex. */
@@ -1520,7 +1578,7 @@
                                               "player%d.u%d.activity_count",
                                               plrno, i);
     punit->activity_target
-      = secfile_lookup_int_default(file, (int) S_NO_SPECIAL,
+      = secfile_lookup_int_default(file, S_LAST,
                                   "player%d.u%d.activity_target", plrno, i);
 
     punit->done_moving = secfile_lookup_bool_default(file,
@@ -2362,18 +2420,18 @@
     LOAD_MAP_DATA(ch, nat_y, ptile,
                  secfile_lookup_str(file, "player%d.map_l%03d",
                                     plrno, nat_y),
-                 map_get_player_tile(ptile, plr)->special =
-                 ascii_hex2bin(ch, 0));
+       set_savegame_special(&map_get_player_tile(ptile, plr)->special,
+                            ch, 0));
     LOAD_MAP_DATA(ch, nat_y, ptile,
                  secfile_lookup_str(file, "player%d.map_u%03d",
                                     plrno, nat_y),
-                 map_get_player_tile(ptile, plr)->special |=
-                 ascii_hex2bin(ch, 1));
+       set_savegame_special(&map_get_player_tile(ptile, plr)->special,
+                            ch, 1));
     LOAD_MAP_DATA(ch, nat_y, ptile,
                  secfile_lookup_str_default
                  (file, NULL, "player%d.map_n%03d", plrno, nat_y),
-                 map_get_player_tile(ptile, plr)->special |=
-                 ascii_hex2bin(ch, 2));
+       set_savegame_special(&map_get_player_tile(ptile, plr)->special,
+                            ch, 2));
 
     /* get 4-bit segments of 16-bit "updated" field */
     LOAD_MAP_DATA(ch, nat_y, ptile,
@@ -2994,14 +3052,11 @@
 
     /* put 4-bit segments of 12-bit "special flags" field */
     SAVE_PLAYER_MAP_DATA(ptile, file,"player%d.map_l%03d", plrno,
-                        bin2ascii_hex(map_get_player_tile(ptile, plr)->
-                                      special, 0));
+                        get_savegame_special(map_get_player_tile(ptile, 
plr)->special, 0));
     SAVE_PLAYER_MAP_DATA(ptile, file, "player%d.map_u%03d", plrno,
-                        bin2ascii_hex(map_get_player_tile(ptile, plr)->
-                                      special, 1));
+                        get_savegame_special(map_get_player_tile(ptile, 
plr)->special, 1));
     SAVE_PLAYER_MAP_DATA(ptile, file, "player%d.map_n%03d", plrno,
-                        bin2ascii_hex(map_get_player_tile(ptile, plr)->
-                                      special, 2));
+                        get_savegame_special(map_get_player_tile(ptile, 
plr)->special, 2));
 
     /* put 4-bit segments of 16-bit "updated" field */
     SAVE_PLAYER_MAP_DATA(ptile, file,"player%d.map_ua%03d", plrno,
Index: server/settlers.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v
retrieving revision 1.237
diff -u -r1.237 settlers.c
--- server/settlers.c   7 May 2005 03:43:21 -0000       1.237
+++ server/settlers.c   24 May 2005 19:53:10 -0000
@@ -233,7 +233,6 @@
 static bool is_wet(struct player *pplayer, struct tile *ptile)
 {
   Terrain_type_id terrain;
-  enum tile_special_type special;
 
   /* FIXME: this should check a handicap. */
   if (!pplayer->ai.control && !map_is_known(ptile, pplayer)) {
@@ -246,9 +245,8 @@
     return TRUE;
   }
 
-  special = tile_get_special(ptile);
-  if (contains_special(special, S_RIVER)
-      || contains_special(special, S_IRRIGATION)) {
+  if (tile_has_special(ptile, S_RIVER)
+      || tile_has_special(ptile, S_IRRIGATION)) {
     return TRUE;
   }
 
@@ -296,7 +294,7 @@
 {
   int goodness;
   Terrain_type_id old_terrain = ptile->terrain;
-  enum tile_special_type old_special = ptile->special;
+  bv_special old_special = ptile->special;
   struct tile_type *type = get_tile_type(old_terrain);
   Terrain_type_id new_terrain = type->irrigation_result;
 
@@ -335,7 +333,9 @@
     tile_set_special(ptile, S_FARMLAND);
     goodness = city_tile_value(pcity, city_x, city_y, 0, 0);
     tile_clear_special(ptile, S_FARMLAND);
-    assert(ptile->terrain == old_terrain && ptile->special == old_special);
+    assert(ptile->terrain == old_terrain
+          && memcmp(&ptile->special, &old_special,
+                    sizeof(old_special)) == 0);
     return goodness;
   } else {
     return -1;
@@ -359,7 +359,7 @@
 {
   int goodness;
   Terrain_type_id old_terrain = ptile->terrain;
-  enum tile_special_type old_special = ptile->special;
+  bv_special old_special = ptile->special;
   struct tile_type *type = get_tile_type(old_terrain);
   Terrain_type_id new_terrain = type->mining_result;
 
@@ -411,7 +411,7 @@
 {
   int goodness;
   Terrain_type_id old_terrain = ptile->terrain;
-  enum tile_special_type old_special = ptile->special;
+  bv_special old_special = ptile->special;
   struct tile_type *type = get_tile_type(old_terrain);
   Terrain_type_id new_terrain = type->transform_result;
 
@@ -602,12 +602,12 @@
 
     /* HACK: calling tile_set_special here will have side effects, so we
      * have to set it manually. */
-    assert((ptile->special & S_ROAD) == 0);
-    ptile->special |= S_ROAD;
+    assert(!tile_has_special(ptile, S_ROAD));
+    set_special(&ptile->special, S_ROAD);
 
     goodness = city_tile_value(pcity, city_x, city_y, 0, 0);
 
-    ptile->special &= ~S_ROAD;
+    clear_special(&ptile->special, S_ROAD);
 
     return goodness;
   } else {
@@ -635,7 +635,7 @@
                            int city_x, int city_y, struct tile *ptile)
 {
   int goodness;
-  enum tile_special_type old_special;
+  bv_special old_special;
 
   if (!is_ocean(ptile->terrain)
       && player_knows_techs_with_flag(pplayer, TF_RAILROAD)
@@ -644,7 +644,8 @@
 
     /* HACK: calling tile_set_special here will have side effects, so we
      * have to set it manually. */
-    ptile->special |= (S_ROAD | S_RAILROAD);
+    set_special(&ptile->special, S_ROAD);
+    set_special(&ptile->special, S_RAILROAD);
 
     goodness = city_tile_value(pcity, city_x, city_y, 0, 0);
 
@@ -893,7 +894,7 @@
          activity_type_iterate(act) {
            if (pcity->ai.act_value[act][cx][cy] >= 0
                && can_unit_do_activity_targeted_at(punit, act, 
-                                                   S_NO_SPECIAL, ptile)) {
+                                                   S_LAST, ptile)) {
              int extra = 0;
              int base_value = pcity->ai.act_value[act][cx][cy];
              int old_best_value = best_newv;
@@ -1167,7 +1168,7 @@
                             city_x, city_y, ptile) {
 #ifndef NDEBUG
       Terrain_type_id old_terrain = ptile->terrain;
-      enum tile_special_type old_special = ptile->special;
+      bv_special old_special = ptile->special;
 #endif
 
       pcity->ai.act_value[ACTIVITY_POLLUTION][city_x][city_y] 
@@ -1190,7 +1191,9 @@
        = ai_calc_railroad(pcity, pplayer, city_x, city_y, ptile);
 
       /* Make sure nothing was accidentally changed by these calculations. */
-      assert(old_terrain == ptile->terrain && old_special == ptile->special);
+      assert(old_terrain == ptile->terrain
+            && memcmp(&ptile->special, &old_special,
+                      sizeof(old_special)) == 0);
     } city_map_checked_iterate_end;
   } city_list_iterate_end;
 }
@@ -1352,4 +1355,5 @@
            ai->stats.cities[ptile->continent]);
   assert(want >= 0);
   pcity->ai.settler_want = want;
+  freelog(LOG_NORMAL, "Settler want set to %d.", want);
 }
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.337
diff -u -r1.337 unithand.c
--- server/unithand.c   7 May 2005 13:55:56 -0000       1.337
+++ server/unithand.c   24 May 2005 19:53:11 -0000
@@ -1474,7 +1474,7 @@
       {
         enum tile_special_type prereq =
          get_infrastructure_prereq(old_target);
-        if (prereq != S_NO_SPECIAL) {
+        if (prereq != S_LAST) {
           unit_list_iterate (punit->tile->units, punit2)
             if ((punit2->activity == ACTIVITY_PILLAGE) &&
                 (punit2->activity_target == prereq)) {
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.355
diff -u -r1.355 unittools.c
--- server/unittools.c  11 May 2005 14:57:10 -0000      1.355
+++ server/unittools.c  24 May 2005 19:53:11 -0000
@@ -662,13 +662,12 @@
   }
 
   if (activity==ACTIVITY_PILLAGE) {
-    if (punit->activity_target == S_NO_SPECIAL) { /* case for old save files */
+    if (punit->activity_target == S_LAST) { /* case for old save files */
       if (punit->activity_count >= 1) {
-       enum tile_special_type what =
-         get_preferred_pillage(
-              get_tile_infrastructure_set(ptile));
+       enum tile_special_type what
+         = get_preferred_pillage(get_tile_infrastructure_set(ptile, NULL));
 
-       if (what != S_NO_SPECIAL) {
+       if (what != S_LAST) {
          tile_clear_special(ptile, what);
          update_tile_knowledge(ptile);
          set_unit_activity(punit, ACTIVITY_IDLE);
Index: server/generator/startpos.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/generator/startpos.c,v
retrieving revision 1.13
diff -u -r1.13 startpos.c
--- server/generator/startpos.c 8 May 2005 06:37:50 -0000       1.13
+++ server/generator/startpos.c 24 May 2005 19:53:11 -0000
@@ -42,7 +42,7 @@
 static int get_tile_value(struct tile *ptile)
 {
   Terrain_type_id old_terrain;
-  enum tile_special_type old_special;
+  bv_special old_special;
   int value, irrig_bonus, mine_bonus;
 
   /* Give one point for each food / shield / trade produced. */

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