Complete.Org: Mailing Lists: Archives: freeciv-dev: July 2005:
[Freeciv-Dev] (PR#13442) access terrains by pointer
Home

[Freeciv-Dev] (PR#13442) access terrains by pointer

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#13442) access terrains by pointer
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 9 Jul 2005 16:28:07 -0700
Reply-to: bugs@xxxxxxxxxxx

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

This is a preliminary patch that changes all access to terrains to be
done by pointer.  In fact Terrain_type_id is now used in so few places
that it could potentially be removed.

1.  Almost all Terrain_type_id are changed to struct terrain *.  I also
renamed lots of variables like "ttype" to "pterrain".

2.  T_UNKNOWN and T_NONE are changed to NULL.  This also fixes/exposes
several bugs where get_terrain(T_UNKNOWN) could be called resulting in a
buffer underrun (now it will result in a segfault unless properly
handled).  T_ANY seems to be unused (?) and is removed.

3.  The terrains[] struct is made static in terrain.c.  This is not
strictly necessary perhaps but there is the issue of namespace conflicts.

4.  Some more terrain_type_iterate callers are added.

5.  Fixed style, added comments throughout the modified code.

This is a serious patch.  It's 120k (700 lines changed) and none of it
is automated changes.

It's a preliminary patch because it gives a segfault in mapgen.  However
the backtrace for this segfault seems rather useless to me and I've
spent some time without any luck understanding it at all.  If anyone
wants to give it a run and look at it I'd be appreciative.

-jason

Index: ai/aisettler.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aisettler.c,v
retrieving revision 1.24
diff -p -u -r1.24 aisettler.c
--- ai/aisettler.c      9 Jul 2005 17:46:06 -0000       1.24
+++ ai/aisettler.c      9 Jul 2005 23:17:24 -0000
@@ -296,7 +296,7 @@ static int defense_bonus(struct cityresu
 {
   /* Defense modification (as tie breaker mostly) */
   int defense_bonus = 
-    10 + get_terrain(tile_get_terrain(result->tile))->defense_bonus / 10;
+    10 + tile_get_terrain(result->tile)->defense_bonus / 10;
   if (tile_has_special(result->tile, S_RIVER)) {
     defense_bonus +=
         (defense_bonus * terrain_control.river_defense_bonus) / 100;
Index: ai/aitools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitools.c,v
retrieving revision 1.153
diff -p -u -r1.153 aitools.c
--- ai/aitools.c        9 Jul 2005 17:46:06 -0000       1.153
+++ ai/aitools.c        9 Jul 2005 23:17:24 -0000
@@ -478,7 +478,7 @@ static double chance_killed_at(const str
   double p = is_ocean(ptile->terrain)? 0.05: 0.15;
 
   /* If we are on defensive terrain, we are more likely to survive */
-  db = 10 + get_terrain(ptile->terrain)->defense_bonus / 10;
+  db = 10 + ptile->terrain->defense_bonus / 10;
   if (tile_has_special(ptile, S_RIVER)) {
     db += (db * terrain_control.river_defense_bonus) / 100;
   }
Index: ai/aiunit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aiunit.c,v
retrieving revision 1.363
diff -p -u -r1.363 aiunit.c
--- ai/aiunit.c 9 Jul 2005 17:46:06 -0000       1.363
+++ ai/aiunit.c 9 Jul 2005 23:17:25 -0000
@@ -775,14 +775,14 @@ static bool find_beachhead(struct unit *
                           struct tile **beachhead_tile)
 {
   int ok, best = 0;
-  Terrain_type_id t;
 
   CHECK_UNIT(punit);
 
   adjc_iterate(dest_tile, tile1) {
+    struct terrain *pterrain = tile_get_terrain(tile1);
+
     ok = 0;
-    t = tile_get_terrain(tile1);
-    if (WARMAP_SEACOST(tile1) <= 6 * THRESHOLD && !is_ocean(t)) {
+    if (WARMAP_SEACOST(tile1) <= 6 * THRESHOLD && !is_ocean(pterrain)) {
       /* accessible beachhead */
       adjc_iterate(tile1, tile2) {
        if (is_ocean(tile_get_terrain(tile2))
@@ -799,10 +799,10 @@ static bool find_beachhead(struct unit *
 
       if (ok > 0) {
        /* accessible beachhead with zoc-ok water tile nearby */
-        ok = 10 + get_terrain(t)->defense_bonus / 10;
+        ok = 10 + pterrain->defense_bonus / 10;
        if (tile_has_special(tile1, S_RIVER))
          ok += (ok * terrain_control.river_defense_bonus) / 100;
-        if (get_terrain(t)->movement_cost * SINGLE_MOVE <
+        if (pterrain->movement_cost * SINGLE_MOVE <
             unit_move_rate(punit))
          ok *= 8;
         ok += (6 * THRESHOLD - WARMAP_SEACOST(tile1));
Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.181
diff -p -u -r1.181 control.c
--- client/control.c    9 Jul 2005 17:46:07 -0000       1.181
+++ client/control.c    9 Jul 2005 23:17:25 -0000
@@ -696,8 +696,7 @@ static bool is_activity_on_tile(struct t
 bool can_unit_do_connect(struct unit *punit, enum unit_activity activity) 
 {
   struct player *pplayer = unit_owner(punit);
-  Terrain_type_id terrain = tile_get_terrain(punit->tile);
-  struct terrain *ttype = get_terrain(terrain);
+  struct terrain *pterrain = tile_get_terrain(punit->tile);
 
   /* HACK: This code duplicates that in
    * can_unit_do_activity_targeted_at(). The general logic here is that
@@ -711,7 +710,7 @@ bool can_unit_do_connect(struct unit *pu
     return terrain_control.may_road
       && unit_flag(punit, F_SETTLERS)
       && (tile_has_special(punit->tile, S_ROAD)
-         || (ttype->road_time != 0
+         || (pterrain->road_time != 0
              && (!tile_has_special(punit->tile, S_RIVER)
                  || player_knows_techs_with_flag(pplayer, TF_BRIDGE))));
   case ACTIVITY_RAILROAD:
@@ -727,7 +726,7 @@ bool can_unit_do_connect(struct unit *pu
     return (terrain_control.may_irrigate
            && unit_flag(punit, F_SETTLERS)
            && (tile_has_special(punit->tile, S_IRRIGATION)
-               || (terrain == ttype->irrigation_result
+               || (pterrain == pterrain->irrigation_result
                    && is_water_adjacent_to_tile(punit->tile)
                    && !is_activity_on_tile(punit->tile, ACTIVITY_MINE))));
   default:
Index: client/goto.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/goto.c,v
retrieving revision 1.88
diff -p -u -r1.88 goto.c
--- client/goto.c       9 Jul 2005 17:46:07 -0000       1.88
+++ client/goto.c       9 Jul 2005 23:17:26 -0000
@@ -390,7 +390,7 @@ static enum tile_behavior get_TB_caravan
 static int get_activity_time(const struct tile *ptile,
                             struct player *pplayer)
 {
-  struct terrain *ttype = get_terrain(ptile->terrain);
+  struct terrain *pterrain = ptile->terrain;
   int activity_mc = 0;
 
   assert(hover_state == HOVER_CONNECT);
@@ -398,7 +398,7 @@ static int get_activity_time(const struc
  
   switch (connect_activity) {
   case ACTIVITY_IRRIGATE:
-    if (ttype->irrigation_time == 0) {
+    if (pterrain->irrigation_time == 0) {
       return -1;
     }
     if (tile_has_special(ptile, S_MINE)) {
@@ -410,24 +410,24 @@ static int get_activity_time(const struc
       break;
     }
 
-    activity_mc = ttype->irrigation_time;
+    activity_mc = pterrain->irrigation_time;
     break;
   case ACTIVITY_RAILROAD:
   case ACTIVITY_ROAD:
     if (!tile_has_special(ptile, S_ROAD)) {
-      if (ttype->road_time == 0
+      if (pterrain->road_time == 0
          || (tile_has_special(ptile, S_RIVER)
              && !player_knows_techs_with_flag(pplayer, TF_BRIDGE))) {
        /* 0 means road is impossible here (??) */
        return -1;
       }
-      activity_mc += ttype->road_time;
+      activity_mc += pterrain->road_time;
     }
     if (connect_activity == ACTIVITY_ROAD 
         || tile_has_special(ptile, S_RAILROAD)) {
       break;
     }
-    activity_mc += ttype->rail_time;
+    activity_mc += pterrain->rail_time;
     /* No break */
     break;
   default:
Index: client/helpdata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/helpdata.c,v
retrieving revision 1.118
diff -p -u -r1.118 helpdata.c
--- client/helpdata.c   9 Jul 2005 17:46:07 -0000       1.118
+++ client/helpdata.c   9 Jul 2005 23:17:26 -0000
@@ -115,33 +115,31 @@ void free_help_texts(void)
 static void insert_generated_table(const char* name, char* outbuf)
 {
   if (0 == strcmp (name, "TerrainAlterations")) {
-    int i;
-
     strcat(outbuf, _("Terrain     Road   Irrigation     Mining         "
                      "Transform\n"));
     strcat(outbuf, "---------------------------------------------------"
           "------------\n");
-    for (i = T_FIRST; i < T_COUNT; i++) {
-      if (*(terrains[i].terrain_name) != '\0') {
+    terrain_type_iterate(pterrain) {
+      if (*(pterrain->terrain_name) != '\0') {
        outbuf = strchr(outbuf, '\0');
        sprintf(outbuf,
                "%-10s %3d    %3d %-10s %3d %-10s %3d %-10s\n",
-               terrains[i].terrain_name,
-               terrains[i].road_time,
-               terrains[i].irrigation_time,
-               ((terrains[i].irrigation_result == i
-                 || terrains[i].irrigation_result == T_NONE) ? ""
-                : terrains[terrains[i].irrigation_result].terrain_name),
-               terrains[i].mining_time,
-               ((terrains[i].mining_result == i
-                 || terrains[i].mining_result == T_NONE) ? ""
-                : terrains[terrains[i].mining_result].terrain_name),
-               terrains[i].transform_time,
-               ((terrains[i].transform_result == i
-                || terrains[i].transform_result == T_NONE) ? ""
-                : terrains[terrains[i].transform_result].terrain_name));
+               pterrain->terrain_name,
+               pterrain->road_time,
+               pterrain->irrigation_time,
+               ((pterrain->irrigation_result == pterrain
+                 || pterrain->irrigation_result == T_NONE) ? ""
+                : pterrain->irrigation_result->terrain_name),
+               pterrain->mining_time,
+               ((pterrain->mining_result == pterrain
+                 || pterrain->mining_result == T_NONE) ? ""
+                : pterrain->mining_result->terrain_name),
+               pterrain->transform_time,
+               ((pterrain->transform_result == pterrain
+                || pterrain->transform_result == T_NONE) ? ""
+                : pterrain->transform_result->terrain_name));
       }
-    }
+    } terrain_type_iterate_end;
     strcat(outbuf, "\n");
     strcat(outbuf, _("(Railroads and fortresses require 3 turns, "
                     "regardless of terrain.)"));
@@ -387,16 +385,16 @@ void boot_help_texts(void)
            }
          } tech_type_iterate_end;
        } else if (current_type == HELP_TERRAIN) {
-         for (i = T_FIRST; i < T_COUNT; i++) {
-           if (*(terrains[i].terrain_name) != '\0') {
+         terrain_type_iterate(pterrain) {
+           if (*(pterrain->terrain_name) != '\0') {
              pitem = new_help_item(current_type);
              my_snprintf(name, sizeof(name), " %s",
-                         terrains[i].terrain_name);
+                         pterrain->terrain_name);
              pitem->topic = mystrdup(name);
              pitem->text = mystrdup("");
              help_list_append(category_nodes, pitem);
            }
-         }
+         } terrain_type_iterate_end;
          /* Add special Civ2-style river help text if it's supplied. */
          if (terrain_control.river_help_text) {
            pitem = new_help_item(HELP_TEXT);
@@ -1184,50 +1182,48 @@ void helptext_tech(char *buf, int i, con
 /****************************************************************
   Append text for terrain.
 *****************************************************************/
-void helptext_terrain(char *buf, int i, const char *user_text)
+void helptext_terrain(char *buf, const struct terrain *pterrain,
+                     const char *user_text)
 {
-  struct terrain *pt;
-  
   buf[0] = '\0';
   
-  if (i < 0 || i >= T_COUNT) {
-    freelog(LOG_ERROR, "Unknown terrain %d.", i);
+  if (!pterrain) {
+    freelog(LOG_ERROR, "Unknown terrain!");
     return;
   }
-  pt = &terrains[i];
 
-  if (terrain_has_flag(i, TER_NO_POLLUTION)) {
+  if (terrain_has_flag(pterrain, TER_NO_POLLUTION)) {
     sprintf(buf + strlen(buf),
            _("* Pollution cannot be generated on this terrain."));
     strcat(buf, "\n");
   }
-  if (terrain_has_flag(i, TER_NO_CITIES)) {
+  if (terrain_has_flag(pterrain, TER_NO_CITIES)) {
     sprintf(buf + strlen(buf),
            _("* You cannot build cities on this terrain."));
     strcat(buf, "\n");
   }
-  if (terrain_has_flag(i, TER_UNSAFE_COAST)
-      && !is_ocean(i)) {
+  if (terrain_has_flag(pterrain, TER_UNSAFE_COAST)
+      && !is_ocean(pterrain)) {
     sprintf(buf + strlen(buf),
            _("* The coastline of this terrain is unsafe."));
     strcat(buf, "\n");
   }
-  if (terrain_has_flag(i, TER_UNSAFE)) {
+  if (terrain_has_flag(pterrain, TER_UNSAFE)) {
     sprintf(buf + strlen(buf),
            _("* This terrain is unsafe for units to travel on."));
     strcat(buf, "\n");
   }
-  if (terrain_has_flag(i, TER_OCEANIC)) {
+  if (terrain_has_flag(pterrain, TER_OCEANIC)) {
     sprintf(buf + strlen(buf),
            _("* Land units cannot travel on oceanic terrains."));
     strcat(buf, "\n");
   }
 
-  if (pt->helptext[0] != '\0') {
+  if (pterrain->helptext[0] != '\0') {
     if (buf[0] != '\0') {
       strcat(buf, "\n");
     }
-    sprintf(buf + strlen(buf), "%s", _(pt->helptext));
+    sprintf(buf + strlen(buf), "%s", _(pterrain->helptext));
   }
   if (user_text && user_text[0] != '\0') {
     strcat(buf, "\n\n");
Index: client/helpdata.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/helpdata.h,v
retrieving revision 1.13
diff -p -u -r1.13 helpdata.h
--- client/helpdata.h   30 Apr 2005 17:09:25 -0000      1.13
+++ client/helpdata.h   9 Jul 2005 23:17:26 -0000
@@ -42,7 +42,8 @@ char *helptext_building(char *buf, size_
                        const char *user_text);
 void helptext_unit(char *buf, int i, const char *user_text);
 void helptext_tech(char *buf, int i, const char *user_text);
-void helptext_terrain(char *buf, int i, const char *user_text);
+void helptext_terrain(char *buf, const struct terrain *pterrain,
+                     const char *user_text);
 void helptext_government(char *buf, int i, const char *user_text);
 
 char *helptext_unit_upkeep_str(int i);
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.528
diff -p -u -r1.528 packhand.c
--- client/packhand.c   9 Jul 2005 17:46:07 -0000       1.528
+++ client/packhand.c   9 Jul 2005 23:17:26 -0000
@@ -1861,9 +1861,9 @@ void handle_tile_info(struct packet_tile
   bool known_changed = FALSE;
   enum tile_special_type spe;
 
-  if (ptile->terrain != packet->type) { /*terrain*/
+  if (!ptile->terrain || ptile->terrain->index != packet->type) {
     tile_changed = TRUE;
-    ptile->terrain = packet->type;
+    ptile->terrain = get_terrain(packet->type);
   }
   for (spe = 0; spe < S_LAST; spe++) {
     if (packet->special[spe]) {
@@ -2273,62 +2273,61 @@ void handle_ruleset_government_ruler_tit
 **************************************************************************/
 void handle_ruleset_terrain(struct packet_ruleset_terrain *p)
 {
-  struct terrain *t;
+  struct terrain *pterrain = get_terrain(p->id);
 
-  if (p->id < T_FIRST || p->id >= T_COUNT) {
+  if (!pterrain) {
     freelog(LOG_ERROR,
            "Received bad terrain id %d in handle_ruleset_terrain",
            p->id);
     return;
   }
-  t = &(terrains[p->id]);
 
-  sz_strlcpy(t->terrain_name_orig, p->terrain_name);
-  t->terrain_name = t->terrain_name_orig;
-  sz_strlcpy(t->graphic_str, p->graphic_str);
-  sz_strlcpy(t->graphic_alt, p->graphic_alt);
-  t->movement_cost = p->movement_cost;
-  t->defense_bonus = p->defense_bonus;
+  sz_strlcpy(pterrain->terrain_name_orig, p->terrain_name);
+  pterrain->terrain_name = pterrain->terrain_name_orig;
+  sz_strlcpy(pterrain->graphic_str, p->graphic_str);
+  sz_strlcpy(pterrain->graphic_alt, p->graphic_alt);
+  pterrain->movement_cost = p->movement_cost;
+  pterrain->defense_bonus = p->defense_bonus;
 
   output_type_iterate(o) {
-    t->output[o] = p->output[o];
-    t->special[0].output[o] = p->output_special_1[o];
-    t->special[1].output[o] = p->output_special_2[o];
+    pterrain->output[o] = p->output[o];
+    pterrain->special[0].output[o] = p->output_special_1[o];
+    pterrain->special[1].output[o] = p->output_special_2[o];
   } output_type_iterate_end;
 
-  sz_strlcpy(t->special[0].name_orig, p->special_1_name);
-  t->special[0].name = t->special[0].name_orig;
+  sz_strlcpy(pterrain->special[0].name_orig, p->special_1_name);
+  pterrain->special[0].name = pterrain->special[0].name_orig;
 
-  sz_strlcpy(t->special[1].name_orig, p->special_2_name);
-  t->special[1].name = t->special[1].name_orig;
+  sz_strlcpy(pterrain->special[1].name_orig, p->special_2_name);
+  pterrain->special[1].name = pterrain->special[1].name_orig;
 
-  sz_strlcpy(t->special[0].graphic_str, p->graphic_str_special_1);
-  sz_strlcpy(t->special[0].graphic_alt, p->graphic_alt_special_1);
+  sz_strlcpy(pterrain->special[0].graphic_str, p->graphic_str_special_1);
+  sz_strlcpy(pterrain->special[0].graphic_alt, p->graphic_alt_special_1);
 
-  sz_strlcpy(t->special[1].graphic_str, p->graphic_str_special_2);
-  sz_strlcpy(t->special[1].graphic_alt, p->graphic_alt_special_2);
-
-  t->road_time = p->road_time;
-  t->road_trade_incr = p->road_trade_incr;
-  t->irrigation_result = p->irrigation_result;
-  t->irrigation_food_incr = p->irrigation_food_incr;
-  t->irrigation_time = p->irrigation_time;
-  t->mining_result = p->mining_result;
-  t->mining_shield_incr = p->mining_shield_incr;
-  t->mining_time = p->mining_time;
-  t->transform_result = p->transform_result;
-  t->transform_time = p->transform_time;
-  t->rail_time = p->rail_time;
-  t->airbase_time = p->airbase_time;
-  t->fortress_time = p->fortress_time;
-  t->clean_pollution_time = p->clean_pollution_time;
-  t->clean_fallout_time = p->clean_fallout_time;
+  sz_strlcpy(pterrain->special[1].graphic_str, p->graphic_str_special_2);
+  sz_strlcpy(pterrain->special[1].graphic_alt, p->graphic_alt_special_2);
+
+  pterrain->road_time = p->road_time;
+  pterrain->road_trade_incr = p->road_trade_incr;
+  pterrain->irrigation_result = get_terrain(p->irrigation_result);
+  pterrain->irrigation_food_incr = p->irrigation_food_incr;
+  pterrain->irrigation_time = p->irrigation_time;
+  pterrain->mining_result = get_terrain(p->mining_result);
+  pterrain->mining_shield_incr = p->mining_shield_incr;
+  pterrain->mining_time = p->mining_time;
+  pterrain->transform_result = get_terrain(p->transform_result);
+  pterrain->transform_time = p->transform_time;
+  pterrain->rail_time = p->rail_time;
+  pterrain->airbase_time = p->airbase_time;
+  pterrain->fortress_time = p->fortress_time;
+  pterrain->clean_pollution_time = p->clean_pollution_time;
+  pterrain->clean_fallout_time = p->clean_fallout_time;
   
-  t->flags = p->flags;
+  pterrain->flags = p->flags;
 
-  t->helptext = mystrdup(p->helptext);
+  pterrain->helptext = mystrdup(p->helptext);
   
-  tileset_setup_tile_type(tileset, p->id);
+  tileset_setup_tile_type(tileset, pterrain);
 }
 
 /**************************************************************************
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.313
diff -p -u -r1.313 tilespec.c
--- client/tilespec.c   9 Jul 2005 17:46:07 -0000       1.313
+++ client/tilespec.c   9 Jul 2005 23:17:27 -0000
@@ -878,9 +878,9 @@ void tilespec_reread(const char *new_til
     /* The ruleset data is not sent until this point. */
     return;
   }
-  for (id = T_FIRST; id < T_COUNT; id++) {
-    tileset_setup_tile_type(tileset, id);
-  }
+  terrain_type_iterate(pterrain) {
+    tileset_setup_tile_type(tileset, pterrain);
+  } terrain_type_iterate_end;
   unit_type_iterate(id) {
     tileset_setup_unit_type(tileset, id);
   } unit_type_iterate_end;
@@ -2390,23 +2390,24 @@ void tileset_setup_tech_type(struct tile
   Set tile_type sprite values; should only happen after
   tilespec_load_tiles().
 ***********************************************************************/
-void tileset_setup_tile_type(struct tileset *t, Terrain_type_id terrain)
+void tileset_setup_tile_type(struct tileset *t,
+                            const struct terrain *pterrain)
 {
-  struct terrain *tt = get_terrain(terrain);
   struct terrain_drawing_data *draw;
   char buffer1[MAX_LEN_NAME + 20];
   int i, l;
   
-  if (tt->terrain_name[0] == '\0') {
+  if (pterrain->terrain_name[0] == '\0') {
     return;
   }
 
-  draw = hash_lookup_data(t->terrain_hash, tt->graphic_str);
+  draw = hash_lookup_data(t->terrain_hash, pterrain->graphic_str);
   if (!draw) {
-    draw = hash_lookup_data(t->terrain_hash, tt->graphic_alt);
+    draw = hash_lookup_data(t->terrain_hash, pterrain->graphic_alt);
     if (!draw) {
       freelog(LOG_FATAL, "No graphics %s or %s for %s terrain.",
-             tt->graphic_str, tt->graphic_alt, tt->terrain_name);
+             pterrain->graphic_str, pterrain->graphic_alt,
+             pterrain->terrain_name);
       exit(EXIT_FAILURE);
     }
   }
@@ -2443,7 +2444,7 @@ void tileset_setup_tile_type(struct tile
                      "t.%s_%s", draw->name, cardinal_index_str(t, i));
          draw->layer[l].match[i] = lookup_sprite_tag_alt(t, buffer1, "", TRUE,
                                                          "tile_type",
-                                                         tt->terrain_name);
+                                                         
pterrain->terrain_name);
        }
        draw->layer[l].base.p[0] = draw->layer[l].match[0];
        break;
@@ -2474,7 +2475,7 @@ void tileset_setup_tile_type(struct tile
                          (value >> 2) & 1);
              draw->layer[l].cells[i]
                = lookup_sprite_tag_alt(t, buffer1, "", TRUE, "tile_type",
-                                       tt->terrain_name);
+                                       pterrain->terrain_name);
              break;
            case MATCH_FULL:
              {
@@ -2550,7 +2551,7 @@ void tileset_setup_tile_type(struct tile
        my_snprintf(buffer1, sizeof(buffer1), "t.%s1", draw->name);
        draw->layer[l].base.p[0]
          = lookup_sprite_tag_alt(t, buffer1, "", FALSE, "tile_type",
-                                 tt->terrain_name);
+                                 pterrain->terrain_name);
        break;
       }
     }
@@ -2574,12 +2575,12 @@ void tileset_setup_tile_type(struct tile
   }
 
   for (i = 0; i < MAX_NUM_SPECIALS; i++) {
-    const char *name = tt->special[i].name;
+    const char *name = pterrain->special[i].name;
 
     if (name[0] != '\0') {
       draw->special[i]
-       = lookup_sprite_tag_alt(t, tt->special[i].graphic_str,
-                               tt->special[i].graphic_alt,
+       = lookup_sprite_tag_alt(t, pterrain->special[i].graphic_str,
+                               pterrain->special[i].graphic_alt,
                                TRUE, "tile_type special", name);
       assert(draw->special[i] != NULL);
     } else {
@@ -2594,7 +2595,7 @@ void tileset_setup_tile_type(struct tile
     draw->mine = NULL;
   }
 
-  t->sprites.terrain[terrain] = draw;
+  t->sprites.terrain[pterrain->index] = draw;
 }
 
 /**********************************************************************
@@ -2743,28 +2744,28 @@ static struct sprite *get_city_occupied_
     tspecial_near  : specials of all adjacent terrain
 **************************************************************************/
 static void build_tile_data(const struct tile *ptile,
-                           Terrain_type_id *ttype,
+                           struct terrain **tterrain,
                            bv_special *tspecial,
-                           Terrain_type_id *ttype_near,
+                           struct terrain **tterrain_near,
                            bv_special *tspecial_near)
 {
   enum direction8 dir;
 
   *tspecial = tile_get_special(ptile);
-  *ttype = tile_get_terrain(ptile);
+  *tterrain = tile_get_terrain(ptile);
 
   /* Loop over all adjacent tiles.  We should have an iterator for this. */
   for (dir = 0; dir < 8; dir++) {
     struct tile *tile1 = mapstep(ptile, dir);
 
     if (tile1 && client_tile_get_known(tile1) != TILE_UNKNOWN) {
+      tterrain_near[dir] = tile_get_terrain(tile1);
       tspecial_near[dir] = tile_get_special(tile1);
-      ttype_near[dir] = tile_get_terrain(tile1);
     } else {
       /* We draw the edges of the (known) map as if the same terrain just
        * continued off the edge of the map. */
+      tterrain_near[dir] = *tterrain;
       BV_CLR_ALL(tspecial_near[dir]);
-      ttype_near[dir] = *ttype;
     }
   }
 }
@@ -3298,12 +3299,12 @@ static int fill_city_overlays_sprite_arr
 static int fill_blending_sprite_array(const struct tileset *t,
                                      struct drawn_sprite *sprs,
                                      const struct tile *ptile,
-                                     Terrain_type_id *ttype_near)
+                                     struct terrain **tterrain_near)
 {
   struct drawn_sprite *saved_sprs = sprs;
-  Terrain_type_id ttype = tile_get_terrain(ptile);
+  struct terrain *pterrain = tile_get_terrain(ptile);
 
-  if (t->is_isometric && t->sprites.terrain[ttype]->is_blended) {
+  if (t->is_isometric && t->sprites.terrain[pterrain->index]->is_blended) {
     enum direction4 dir;
     const int W = t->normal_tile_width, H = t->normal_tile_height;
     const int offsets[4][2] = {
@@ -3317,16 +3318,16 @@ static int fill_blending_sprite_array(co
      */
     for (dir = 0; dir < 4; dir++) {
       struct tile *tile1 = mapstep(ptile, DIR4_TO_DIR8[dir]);
-      Terrain_type_id other = ttype_near[DIR4_TO_DIR8[dir]];
+      struct terrain *other = tterrain_near[DIR4_TO_DIR8[dir]];
 
       if (!tile1
          || client_tile_get_known(tile1) == TILE_UNKNOWN
-         || other == ttype
-         || !t->sprites.terrain[other]->is_blended) {
+         || other == pterrain
+         || !t->sprites.terrain[other->index]->is_blended) {
        continue;
       }
 
-      ADD_SPRITE(t->sprites.terrain[other]->blend[dir], TRUE,
+      ADD_SPRITE(t->sprites.terrain[other->index]->blend[dir], TRUE,
                 offsets[dir][0], offsets[dir][1]);
     }
   }
@@ -3394,12 +3395,12 @@ static int fill_terrain_sprite_array(str
                                     struct drawn_sprite *sprs,
                                     int layer,
                                     const struct tile *ptile,
-                                    Terrain_type_id *ttype_near)
+                                    struct terrain **tterrain_near)
 {
   struct drawn_sprite *saved_sprs = sprs;
   struct sprite *sprite;
-  Terrain_type_id ttype = ptile->terrain;
-  struct terrain_drawing_data *draw = t->sprites.terrain[ttype];
+  struct terrain *pterrain = ptile->terrain;
+  struct terrain_drawing_data *draw = t->sprites.terrain[pterrain->index];
   const int l = layer;
   int i, tileno;
   struct tile *adjc_tile;
@@ -3444,8 +3445,9 @@ static int fill_terrain_sprite_array(str
     int match_type = draw->layer[l].match_type;
 
 #define MATCH(dir)                                                         \
-    (t->sprites.terrain[ttype_near[(dir)]]->num_layers > l                 \
-     ? t->sprites.terrain[ttype_near[(dir)]]->layer[l].match_type : -1)
+    (t->sprites.terrain[tterrain_near[(dir)]->index]->num_layers > l       \
+     ? t->sprites.terrain[tterrain_near[(dir)]->index]->layer[l].match_type \
+     : -1)
 
     if (draw->layer[l].cell_type == CELL_SINGLE) {
       int ox = draw->layer[l].offset_x, oy = draw->layer[l].offset_y;
@@ -3525,7 +3527,7 @@ static int fill_terrain_sprite_array(str
 
   /* Add blending on top of the first layer. */
   if (l == 0 && draw->is_blended) {
-    sprs += fill_blending_sprite_array(t, sprs, ptile, ttype_near);
+    sprs += fill_blending_sprite_array(t, sprs, ptile, tterrain_near);
   }
 
   /* Add darkness on top of the first layer.  Note that darkness is always
@@ -3767,7 +3769,7 @@ int fill_sprite_array(struct tileset *t,
                      const struct unit *punit, const struct city *pcity,
                      const struct city *citymode)
 {
-  Terrain_type_id ttype = T_UNKNOWN, ttype_near[8];
+  struct terrain *pterrain = NULL, *tterrain_near[8];
   bv_special tspecial, tspecial_near[8];
   int tileno, dir;
   struct unit *pfocus = get_unit_in_focus();
@@ -3812,7 +3814,7 @@ int fill_sprite_array(struct tileset *t,
 
   if (ptile && client_tile_get_known(ptile) != TILE_UNKNOWN) {
     build_tile_data(ptile,
-                   &ttype, &tspecial, ttype_near, tspecial_near);
+                   &pterrain, &tspecial, tterrain_near, tspecial_near);
   }
 
   switch (layer) {
@@ -3840,13 +3842,13 @@ int fill_sprite_array(struct tileset *t,
       assert(MAX_NUM_LAYERS == 2);
       sprs += fill_terrain_sprite_array(t, sprs,
                                        (layer == LAYER_TERRAIN1) ? 0 : 1,
-                                       ptile, ttype_near);
+                                       ptile, tterrain_near);
     }
     break;
 
   case LAYER_WATER:
     if (ptile && client_tile_get_known(ptile) != TILE_UNKNOWN) {
-      if (is_ocean(ttype) && draw_terrain && !solid_bg) {
+      if (is_ocean(pterrain) && draw_terrain && !solid_bg) {
        for (dir = 0; dir < 4; dir++) {
          if (contains_special(tspecial_near[DIR4_TO_DIR8[dir]], S_RIVER)) {
            ADD_SPRITE_SIMPLE(t->sprites.tx.river_outlet[dir]);
@@ -3866,7 +3868,7 @@ int fill_sprite_array(struct tileset *t,
          enum direction8 dir = t->cardinal_tileset_dirs[i];
 
          if (contains_special(tspecial_near[dir], S_RIVER)
-             || is_ocean(ttype_near[dir])) {
+             || is_ocean(tterrain_near[dir])) {
            tileno |= 1 << i;
          }
        }
@@ -3886,9 +3888,9 @@ int fill_sprite_array(struct tileset *t,
     if (ptile && client_tile_get_known(ptile) != TILE_UNKNOWN) {
       if (draw_specials) {
        if (contains_special(tspecial, S_SPECIAL_1)) {
-         ADD_SPRITE_SIMPLE(t->sprites.terrain[ttype]->special[0]);
+         ADD_SPRITE_SIMPLE(t->sprites.terrain[pterrain->index]->special[0]);
        } else if (contains_special(tspecial, S_SPECIAL_2)) {
-         ADD_SPRITE_SIMPLE(t->sprites.terrain[ttype]->special[1]);
+         ADD_SPRITE_SIMPLE(t->sprites.terrain[pterrain->index]->special[1]);
        }
       }
 
@@ -3898,8 +3900,8 @@ int fill_sprite_array(struct tileset *t,
       }
 
       if (draw_mines && contains_special(tspecial, S_MINE)
-         && t->sprites.terrain[ttype]->mine) {
-       ADD_SPRITE_SIMPLE(t->sprites.terrain[ttype]->mine);
+         && t->sprites.terrain[pterrain->index]->mine) {
+       ADD_SPRITE_SIMPLE(t->sprites.terrain[pterrain->index]->mine);
       }
 
       if (draw_specials && contains_special(tspecial, S_HUT)) {
Index: client/tilespec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.h,v
retrieving revision 1.154
diff -p -u -r1.154 tilespec.h
--- client/tilespec.h   22 May 2005 18:12:52 -0000      1.154
+++ client/tilespec.h   9 Jul 2005 23:17:27 -0000
@@ -115,7 +115,8 @@ void tileset_setup_specialist_type(struc
 void tileset_setup_unit_type(struct tileset *t, int id);
 void tileset_setup_impr_type(struct tileset *t, int id);
 void tileset_setup_tech_type(struct tileset *t, int id);
-void tileset_setup_tile_type(struct tileset *t, Terrain_type_id terrain);
+void tileset_setup_tile_type(struct tileset *t,
+                            const struct terrain *pterrain);
 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);
Index: client/gui-gtk-2.0/helpdlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/helpdlg.c,v
retrieving revision 1.54
diff -p -u -r1.54 helpdlg.c
--- client/gui-gtk-2.0/helpdlg.c        9 Jul 2005 17:46:07 -0000       1.54
+++ client/gui-gtk-2.0/helpdlg.c        9 Jul 2005 23:17:27 -0000
@@ -1023,104 +1023,104 @@ static void help_update_tech(const struc
 ...
 **************************************************************************/
 static void help_update_terrain(const struct help_item *pitem,
-                               char *title, int i)
+                               char *title, struct terrain *pterrain)
 {
   char *buf = &long_buffer[0];
 
   create_help_page(HELP_TERRAIN);
 
-  if (i < T_COUNT) {
+  if (pterrain) {
     sprintf(buf, "%d/%d.%d",
-           terrains[i].movement_cost,
-           (int)((terrains[i].defense_bonus + 100) / 100),
-           (terrains[i].defense_bonus + 100) % 100 / 10);
+           pterrain->movement_cost,
+           (int)((pterrain->defense_bonus + 100) / 100),
+           (pterrain->defense_bonus + 100) % 100 / 10);
     gtk_label_set_text(GTK_LABEL(help_tlabel[0][1]), buf);
 
     sprintf(buf, "%d/%d/%d",
-           terrains[i].output[O_FOOD],
-           terrains[i].output[O_SHIELD],
-           terrains[i].output[O_TRADE]);
+           pterrain->output[O_FOOD],
+           pterrain->output[O_SHIELD],
+           pterrain->output[O_TRADE]);
     gtk_label_set_text(GTK_LABEL(help_tlabel[0][4]), buf);
 
-    if (*(terrains[i].special[0].name)) {
+    if (*(pterrain->special[0].name)) {
       sprintf(buf, _("%s F/R/T:"),
-              terrains[i].special[0].name);
+              pterrain->special[0].name);
       gtk_label_set_text(GTK_LABEL(help_tlabel[1][0]), buf);
       sprintf(buf, "%d/%d/%d",
-             terrains[i].special[0].output[O_FOOD],
-             terrains[i].special[0].output[O_SHIELD],
-             terrains[i].special[0].output[O_TRADE]);
+             pterrain->special[0].output[O_FOOD],
+             pterrain->special[0].output[O_SHIELD],
+             pterrain->special[0].output[O_TRADE]);
       gtk_label_set_text(GTK_LABEL(help_tlabel[1][1]), buf);
     } else {
       gtk_label_set_text(GTK_LABEL(help_tlabel[1][0]), "");
       gtk_label_set_text(GTK_LABEL(help_tlabel[1][1]), "");
     }
 
-    if (*(terrains[i].special[1].name)) {
+    if (*(pterrain->special[1].name)) {
       sprintf(buf, _("%s F/R/T:"),
-             terrains[i].special[1].name);
+             pterrain->special[1].name);
       gtk_label_set_text(GTK_LABEL(help_tlabel[1][3]), buf);
       sprintf(buf, "%d/%d/%d",
-             terrains[i].special[1].output[O_FOOD],
-             terrains[i].special[1].output[O_SHIELD],
-             terrains[i].special[1].output[O_TRADE]);
+             pterrain->special[1].output[O_FOOD],
+             pterrain->special[1].output[O_SHIELD],
+             pterrain->special[1].output[O_TRADE]);
       gtk_label_set_text(GTK_LABEL(help_tlabel[1][4]), buf);
     } else {
       gtk_label_set_text(GTK_LABEL(help_tlabel[1][3]), "");
       gtk_label_set_text(GTK_LABEL(help_tlabel[1][4]), "");
     }
 
-    if (terrains[i].road_trade_incr > 0) {
+    if (pterrain->road_trade_incr > 0) {
       sprintf(buf, _("+%d Trade / %d"),
-             terrains[i].road_trade_incr,
-             terrains[i].road_time);
-    } else if (terrains[i].road_time > 0) {
+             pterrain->road_trade_incr,
+             pterrain->road_time);
+    } else if (pterrain->road_time > 0) {
       sprintf(buf, _("no extra / %d"),
-             terrains[i].road_time);
+             pterrain->road_time);
     } else {
       strcpy(buf, _("n/a"));
     }
     gtk_label_set_text(GTK_LABEL(help_tlabel[2][1]), buf);
 
     strcpy(buf, _("n/a"));
-    if (terrains[i].irrigation_result == i) {
-      if (terrains[i].irrigation_food_incr > 0) {
+    if (pterrain->irrigation_result == pterrain) {
+      if (pterrain->irrigation_food_incr > 0) {
        sprintf(buf, _("+%d Food / %d"),
-               terrains[i].irrigation_food_incr,
-               terrains[i].irrigation_time);
+               pterrain->irrigation_food_incr,
+               pterrain->irrigation_time);
       }
-    } else if (terrains[i].irrigation_result != T_NONE) {
+    } else if (pterrain->irrigation_result != T_NONE) {
       sprintf(buf, "%s / %d",
-             terrains[terrains[i].irrigation_result].terrain_name,
-             terrains[i].irrigation_time);
+             pterrain->irrigation_result->terrain_name,
+             pterrain->irrigation_time);
     }
     gtk_label_set_text(GTK_LABEL(help_tlabel[2][4]), buf);
 
     strcpy(buf, _("n/a"));
-    if (terrains[i].mining_result == i) {
-      if (terrains[i].mining_shield_incr > 0) {
+    if (pterrain->mining_result == pterrain) {
+      if (pterrain->mining_shield_incr > 0) {
        sprintf(buf, _("+%d Res. / %d"),
-               terrains[i].mining_shield_incr,
-               terrains[i].mining_time);
+               pterrain->mining_shield_incr,
+               pterrain->mining_time);
       }
-    } else if (terrains[i].mining_result != T_NONE) {
+    } else if (pterrain->mining_result != T_NONE) {
       sprintf(buf, "%s / %d",
-             terrains[terrains[i].mining_result].terrain_name,
-             terrains[i].mining_time);
+             pterrain->mining_result->terrain_name,
+             pterrain->mining_time);
     }
     gtk_label_set_text(GTK_LABEL(help_tlabel[3][1]), buf);
 
-    if (terrains[i].transform_result != T_NONE) {
+    if (pterrain->transform_result != T_NONE) {
       sprintf(buf, "%s / %d",
-              terrains[terrains[i].transform_result].terrain_name,
-              terrains[i].transform_time);
+             pterrain->transform_result->terrain_name,
+             pterrain->transform_time);
     } else {
       strcpy(buf, "n/a");
     }
     gtk_label_set_text(GTK_LABEL(help_tlabel[3][4]), buf);
   }
 
-  helptext_terrain(buf, i, pitem->text);
+  helptext_terrain(buf, pterrain, pitem->text);
   
   gtk_text_buffer_set_text(help_text, buf, -1);
   gtk_widget_show(help_text_sw);
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.80
diff -p -u -r1.80 menu.c
--- client/gui-gtk-2.0/menu.c   9 Jul 2005 17:46:07 -0000       1.80
+++ client/gui-gtk-2.0/menu.c   9 Jul 2005 23:17:28 -0000
@@ -1292,8 +1292,7 @@ void update_menus(void)
       const char *transfmt = _("Transf_orm to %s");
       char irrtext[128], mintext[128], transtext[128];
       const char *roadtext;
-      Terrain_type_id  ttype;
-      struct terrain *      tinfo;
+      struct terrain *pterrain;
 
       sz_strlcpy(irrtext, _("Build _Irrigation"));
       sz_strlcpy(mintext, _("Build _Mine"));
@@ -1386,10 +1385,9 @@ void update_menus(void)
       else
        menus_rename("<main>/_Orders/Build _Road", _("Build _Road"));
 
-      ttype = punit->tile->terrain;
-      tinfo = get_terrain(ttype);
-      if (tinfo->irrigation_result != T_NONE
-         && tinfo->irrigation_result != ttype) {
+      pterrain = punit->tile->terrain;
+      if (pterrain->irrigation_result != T_NONE
+         && pterrain->irrigation_result != pterrain) {
        my_snprintf(irrtext, sizeof(irrtext), irrfmt,
                    get_tile_change_menu_text(punit->tile,
                                              ACTIVITY_IRRIGATE));
@@ -1398,13 +1396,13 @@ void update_menus(void)
                                                 TF_FARMLAND)) {
        sz_strlcpy(irrtext, _("Bu_ild Farmland"));
       }
-      if (tinfo->mining_result != T_NONE
-         && tinfo->mining_result != ttype) {
+      if (pterrain->mining_result != T_NONE
+         && pterrain->mining_result != pterrain) {
        my_snprintf(mintext, sizeof(mintext), minfmt,
                    get_tile_change_menu_text(punit->tile, ACTIVITY_MINE));
       }
-      if (tinfo->transform_result != T_NONE
-         && tinfo->transform_result != ttype) {
+      if (pterrain->transform_result != T_NONE
+         && pterrain->transform_result != pterrain) {
        my_snprintf(transtext, sizeof(transtext), transfmt,
                    get_tile_change_menu_text(punit->tile,
                                              ACTIVITY_TRANSFORM));
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.353
diff -p -u -r1.353 city.c
--- common/city.c       9 Jul 2005 17:46:08 -0000       1.353
+++ common/city.c       9 Jul 2005 23:17:28 -0000
@@ -573,22 +573,22 @@ static int base_get_output_tile(const st
                                int city_x, int city_y, bool is_celebrating,
                                Output_type_id otype)
 {
-  const struct terrain *ptype = get_terrain(ptile->terrain);
+  const struct terrain *pterrain = ptile->terrain;
   struct tile tile;
   int prod;
   const bool auto_water = (pcity && is_city_center(city_x, city_y)
-                          && ptile->terrain == ptype->irrigation_result
+                          && ptile->terrain == pterrain->irrigation_result
                           && terrain_control.may_irrigate);
   const struct output_type *output = &output_types[otype];
 
   assert(otype >= 0 && otype < O_LAST);
 
   if (tile_has_special(ptile, S_SPECIAL_1)) {
-    prod = terrains[ptile->terrain].special[0].output[otype];
+    prod = pterrain->special[0].output[otype];
   } else if (tile_has_special(ptile, S_SPECIAL_2)) {
-    prod = terrains[ptile->terrain].special[1].output[otype];
+    prod = pterrain->special[1].output[otype];
   } else {
-    prod = terrains[ptile->terrain].output[otype];
+    prod = pterrain->output[otype];
   }
 
   /* create dummy tile which has the city center bonuses. */
@@ -607,12 +607,12 @@ static int base_get_output_tile(const st
   switch (otype) {
   case O_SHIELD:
     if (contains_special(tile.special, S_MINE)) {
-      prod += ptype->mining_shield_incr;
+      prod += pterrain->mining_shield_incr;
     }
     break;
   case O_FOOD:
     if (contains_special(tile.special, S_IRRIGATION)) {
-      prod += ptype->irrigation_food_incr;
+      prod += pterrain->irrigation_food_incr;
     }
     break;
   case O_TRADE:
@@ -620,7 +620,7 @@ static int base_get_output_tile(const st
       prod += terrain_control.river_trade_incr;
     }
     if (contains_special(tile.special, S_ROAD)) {
-      prod += ptype->road_trade_incr;
+      prod += pterrain->road_trade_incr;
     }
     break;
   case O_GOLD:
Index: common/combat.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/combat.c,v
retrieving revision 1.58
diff -p -u -r1.58 combat.c
--- common/combat.c     9 Jul 2005 17:46:08 -0000       1.58
+++ common/combat.c     9 Jul 2005 23:17:28 -0000
@@ -81,8 +81,8 @@ bool can_unit_attack_unit_at_tile(const 
                                  const struct unit *pdefender,
                                   const struct tile *dest_tile)
 {
-  Terrain_type_id fromtile = punit->tile->terrain;
-  Terrain_type_id totile = dest_tile->terrain;
+  struct terrain *fromtile = punit->tile->terrain;
+  struct terrain *totile = dest_tile->terrain;
   struct city *pcity = dest_tile->city;
 
   /* 1. Can we attack _anything_ ? */
@@ -385,7 +385,7 @@ int get_defense_power(const struct unit 
 {
   int db, power = base_get_defense_power(punit);
 
-  db = 10 + get_terrain(punit->tile->terrain)->defense_bonus / 10;
+  db = 10 + punit->tile->terrain->defense_bonus / 10;
   if (tile_has_special(punit->tile, S_RIVER)) {
     db += (db * terrain_control.river_defense_bonus) / 100;
   }
@@ -485,15 +485,15 @@ int get_virtual_defense_power(Unit_type_
                              bool fortified, int veteran)
 {
   int defensepower = unit_types[def_type].defense_strength;
-  Terrain_type_id t = tile_get_terrain(ptile);
   int db;
 
-  if (unit_types[def_type].move_type == LAND_MOVING && is_ocean(t)) {
+  if (unit_types[def_type].move_type == LAND_MOVING
+      && is_ocean(ptile->terrain)) {
     /* Ground units on ship doesn't defend. */
     return 0;
   }
 
-  db = 10 + get_terrain(t)->defense_bonus / 10;
+  db = 10 + ptile->terrain->defense_bonus / 10;
   if (tile_has_special(ptile, S_RIVER)) {
     db += (db * terrain_control.river_defense_bonus) / 100;
   }
Index: common/game.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.c,v
retrieving revision 1.226
diff -p -u -r1.226 game.c
--- common/game.c       9 Jul 2005 17:46:08 -0000       1.226
+++ common/game.c       9 Jul 2005 23:17:29 -0000
@@ -572,9 +572,7 @@ void translate_data_names(void)
     tthis->name = Q_(tthis->name_orig);
   } impr_type_iterate_end;
 
-  terrain_type_iterate(i) {
-    struct terrain *tthis = &terrains[i];
-
+  terrain_type_iterate(tthis) {
     tthis->terrain_name = ((strcmp(tthis->terrain_name_orig, "") != 0)
                           ? Q_(tthis->terrain_name_orig) : "");
 
Index: common/map.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.c,v
retrieving revision 1.231
diff -p -u -r1.231 map.c
--- common/map.c        9 Jul 2005 17:46:08 -0000       1.231
+++ common/map.c        9 Jul 2005 23:17:29 -0000
@@ -555,8 +555,8 @@ bool is_cardinally_adj_to_ocean(const st
 bool is_safe_ocean(const struct tile *ptile)
 {
   adjc_iterate(ptile, tile1) {
-    Terrain_type_id ter = tile_get_terrain(tile1);
-    if (!terrain_has_flag(ter, TER_UNSAFE_COAST) && ter != T_UNKNOWN) {
+    if (tile1->terrain != T_UNKNOWN
+       && !terrain_has_flag(tile1->terrain, TER_UNSAFE_COAST)) {
       return TRUE;
     }
   } adjc_iterate_end;
@@ -682,7 +682,7 @@ static int tile_move_cost_ptrs(struct un
     }
   }
 
-  return(get_terrain(t2->terrain)->movement_cost*SINGLE_MOVE);
+  return t2->terrain->movement_cost * SINGLE_MOVE;
 }
 
 /****************************************************************************
Index: common/movement.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/movement.c,v
retrieving revision 1.12
diff -p -u -r1.12 movement.c
--- common/movement.c   30 Jun 2005 15:43:01 -0000      1.12
+++ common/movement.c   9 Jul 2005 23:17:29 -0000
@@ -183,13 +183,13 @@ bool can_unit_exist_at_tile(const struct
   even on native terrain. All terrains are native to air units.
 ****************************************************************************/
 bool is_native_terrain(const struct unit *punit,
-                       Terrain_type_id terrain)
+                       const struct terrain *pterrain)
 {
   switch (unit_types[punit->type].move_type) {
   case LAND_MOVING:
-    return !is_ocean(terrain);
+    return !is_ocean(pterrain);
   case SEA_MOVING:
-    return is_ocean(terrain);
+    return is_ocean(pterrain);
   default:
     return TRUE;
   }
Index: common/movement.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/movement.h,v
retrieving revision 1.6
diff -p -u -r1.6 movement.h
--- common/movement.h   28 Jun 2005 17:24:56 -0000      1.6
+++ common/movement.h   9 Jul 2005 23:17:29 -0000
@@ -31,7 +31,7 @@ bool is_heli_unittype(Unit_type_id id);
 bool is_ground_unittype(Unit_type_id id);
 
 bool is_native_terrain(const struct unit *punit,
-                       Terrain_type_id terrain);
+                       const struct terrain *pterrain);
 bool can_unit_exist_at_tile(const struct unit *punit, const struct tile 
*ptile);
 bool can_unit_survive_at_tile(const struct unit *punit,
                              const struct tile *ptile);
Index: common/requirements.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/requirements.c,v
retrieving revision 1.28
diff -p -u -r1.28 requirements.c
--- common/requirements.c       23 Jun 2005 08:01:09 -0000      1.28
+++ common/requirements.c       9 Jul 2005 23:17:29 -0000
@@ -204,7 +204,7 @@ struct req_source req_source_from_values
     source.value.special = value;
     return source;
   case REQ_TERRAIN:
-    source.value.terrain = value;
+    source.value.terrain = get_terrain(value);
     return source;
   case REQ_NATION:
     source.value.nation = value;
@@ -260,7 +260,7 @@ void req_source_get_values(const struct 
     *value = source->value.special;
     return;
   case REQ_TERRAIN:
-    *value = source->value.terrain;
+    *value = source->value.terrain->index;
     return;
   case REQ_NATION:
     *value = source->value.nation;
@@ -657,7 +657,7 @@ static bool is_special_in_range(const st
 ****************************************************************************/
 static bool is_terrain_in_range(const struct tile *target_tile,
                                enum req_range range, bool survives,
-                               Terrain_type_id terrain)
+                               const struct terrain *pterrain)
 {
   if (!target_tile) {
     return FALSE;
@@ -666,9 +666,9 @@ static bool is_terrain_in_range(const st
   switch (range) {
   case REQ_RANGE_LOCAL:
     /* The requirement is filled if the tile has the terrain. */
-    return target_tile->terrain == terrain;
+    return pterrain && target_tile->terrain == pterrain;
   case REQ_RANGE_ADJACENT:
-    return is_terrain_near_tile(target_tile, terrain);
+    return pterrain && is_terrain_near_tile(target_tile, pterrain);
   case REQ_RANGE_CITY:
   case REQ_RANGE_CONTINENT:
   case REQ_RANGE_PLAYER:
Index: common/requirements.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/requirements.h,v
retrieving revision 1.19
diff -p -u -r1.19 requirements.h
--- common/requirements.h       11 May 2005 14:11:21 -0000      1.19
+++ common/requirements.h       9 Jul 2005 23:17:29 -0000
@@ -57,7 +57,7 @@ struct req_source {
     int gov;                            /* source government */
     Impr_type_id building;              /* source building */
     enum tile_special_type special;     /* source special */
-    Terrain_type_id terrain;            /* source terrain type */
+    struct terrain *terrain;            /* source terrain type */
     Nation_type_id nation;              /* source nation type */
     Unit_type_id unittype;              /* source unittype */
     enum unit_flag_id unitflag;         /* source unit flag */
Index: common/terrain.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/terrain.c,v
retrieving revision 1.25
diff -p -u -r1.25 terrain.c
--- common/terrain.c    9 Jul 2005 17:46:08 -0000       1.25
+++ common/terrain.c    9 Jul 2005 23:17:32 -0000
@@ -27,7 +27,7 @@
 #include "support.h"
 #include "terrain.h"
 
-struct terrain terrains[MAX_NUM_TERRAINS];
+static struct terrain civ_terrains[MAX_NUM_TERRAINS];
 
 enum tile_special_type infrastructure_specials[] = {
   S_ROAD,
@@ -47,44 +47,44 @@ void terrains_init(void)
 {
   int i;
 
-  for (i = 0; i < ARRAY_SIZE(terrains); i++) {
-    struct terrain *t = get_terrain(i);
-
-    t->index = i;
+  for (i = 0; i < ARRAY_SIZE(civ_terrains); i++) {
+    /* Can't use get_terrain here because it does a bounds check. */
+    civ_terrains[i].index = i;
   }
 }
 
-/***************************************************************
-...
-***************************************************************/
+/****************************************************************************
+  Return the terrain for the given terrain index.
+****************************************************************************/
 struct terrain *get_terrain(Terrain_type_id type)
 {
-  return &terrains[type];
+  if (type < 0 || type >= game.control.terrain_count) {
+    /* This isn't an error; some T_UNKNOWN callers depend on it. */
+    return NULL;
+  }
+  return &civ_terrains[type];
 }
 
 /****************************************************************************
   Return the terrain type matching the name, or T_UNKNOWN if none matches.
 ****************************************************************************/
-Terrain_type_id get_terrain_by_name(const char *name)
+struct terrain *get_terrain_by_name(const char *name)
 {
-  Terrain_type_id tt;
-
-  for (tt = T_FIRST; tt < T_COUNT; tt++) {
-    if (0 == strcmp (terrains[tt].terrain_name, name)) {
-      return tt;
+  terrain_type_iterate(pterrain) {
+    if (0 == strcmp(pterrain->terrain_name, name)) {
+      return pterrain;
     }
-  }
+  } terrain_type_iterate_end;
 
   return T_UNKNOWN;
 }
 
-/***************************************************************
-...
-***************************************************************/
-const char *get_terrain_name(Terrain_type_id type)
+/****************************************************************************
+  Return the name of the terrain.
+****************************************************************************/
+const char *get_terrain_name(const struct terrain *pterrain)
 {
-  assert(type < T_COUNT);
-  return terrains[type].terrain_name;
+  return pterrain->terrain_name;
 }
 
 /****************************************************************************
@@ -118,31 +118,32 @@ enum terrain_flag_id terrain_flag_from_s
 }
 
 /****************************************************************************
-  Return a random terrain that has the specified flag.
+  Return a random terrain that has the specified flag.  Returns T_UNKNOWN if
+  there is no matching terrain.
 ****************************************************************************/
-Terrain_type_id get_flag_terrain(enum terrain_flag_id flag)
+struct terrain *get_flag_terrain(enum terrain_flag_id flag)
 {
   bool has_flag[T_COUNT];
   int count = 0;
 
-  terrain_type_iterate(t) {
-    if ((has_flag[t] = terrain_has_flag(t, flag))) {
+  terrain_type_iterate(pterrain) {
+    if ((has_flag[pterrain->index] = terrain_has_flag(pterrain, flag))) {
       count++;
     }
   } terrain_type_iterate_end;
 
   count = myrand(count);
-  terrain_type_iterate(t) {
-    if (has_flag[t]) {
+  terrain_type_iterate(pterrain) {
+    if (has_flag[pterrain->index]) {
       if (count == 0) {
-       return t;
+       return pterrain;
       }
       count--;
     }
   } terrain_type_iterate_end;
 
   die("Reached end of get_flag_terrain!");
-  return T_NONE;
+  return T_UNKNOWN;
 }
 
 /****************************************************************************
@@ -150,11 +151,9 @@ Terrain_type_id get_flag_terrain(enum te
 ****************************************************************************/
 void terrains_free(void)
 {
-  terrain_type_iterate(t) {
-    struct terrain *p = get_terrain(t);
-
-    free(p->helptext);
-    p->helptext = NULL;
+  terrain_type_iterate(pterrain) {
+    free(pterrain->helptext);
+    pterrain->helptext = NULL;
   } terrain_type_iterate_end;
 }
 
@@ -185,10 +184,11 @@ void terrains_free(void)
 /****************************************************************************
   Returns TRUE iff any adjacent tile contains the given terrain.
 ****************************************************************************/
-bool is_terrain_near_tile(const struct tile *ptile, Terrain_type_id t)
+bool is_terrain_near_tile(const struct tile *ptile,
+                         const struct terrain *pterrain)
 {
   adjc_iterate(ptile, adjc_tile) {
-    if (adjc_tile->terrain == t) {
+    if (pterrain && adjc_tile->terrain == pterrain) {
       return TRUE;
     }
   } adjc_iterate_end;
@@ -201,12 +201,12 @@ bool is_terrain_near_tile(const struct t
 ****************************************************************************/
 int count_terrain_near_tile(const struct tile *ptile,
                            bool cardinal_only, bool percentage,
-                           Terrain_type_id t)
+                           const struct terrain *pterrain)
 {
   int count = 0, total = 0;
 
   variable_adjc_iterate(ptile, adjc_tile, cardinal_only) {
-    if (tile_get_terrain(adjc_tile) == t) {
+    if (pterrain && tile_get_terrain(adjc_tile) == pterrain) {
       count++;
     }
     total++;
@@ -228,7 +228,7 @@ int count_terrain_property_near_tile(con
   int count = 0, total = 0;
 
   variable_adjc_iterate(ptile, adjc_tile, cardinal_only) {
-    if (get_terrain(adjc_tile->terrain)->property[prop] > 0) {
+    if (adjc_tile->terrain->property[prop] > 0) {
       count++;
     }
     total++;
@@ -386,7 +386,7 @@ int count_terrain_flag_near_tile(const s
   int count = 0, total = 0;
 
   variable_adjc_iterate(ptile, adjc_tile, cardinal_only) {
-    if (terrain_has_flag(tile_get_terrain(adjc_tile), flag)) {
+    if (terrain_has_flag(adjc_tile->terrain, flag)) {
       count++;
     }
     total++;
Index: common/terrain.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/terrain.h,v
retrieving revision 1.38
diff -p -u -r1.38 terrain.h
--- common/terrain.h    9 Jul 2005 17:46:08 -0000       1.38
+++ common/terrain.h    9 Jul 2005 23:17:32 -0000
@@ -43,9 +43,8 @@ extern enum tile_special_type infrastruc
 
 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. */
-#define T_UNKNOWN (-1) /* An unknown terrain. */
+#define T_NONE (NULL) /* A special flag meaning no terrain type. */
+#define T_UNKNOWN (NULL) /* An unknown terrain. */
 
 /* The first terrain value and number of base terrains.  This is used in
  * loops.  T_COUNT may eventually be turned into a variable. */
@@ -127,15 +126,15 @@ struct terrain {
   int road_trade_incr;
   int road_time;
 
-  Terrain_type_id irrigation_result;
+  struct terrain *irrigation_result;
   int irrigation_food_incr;
   int irrigation_time;
 
-  Terrain_type_id mining_result;
+  struct terrain *mining_result;
   int mining_shield_incr;
   int mining_time;
 
-  Terrain_type_id transform_result;
+  struct terrain *transform_result;
   int transform_time;
   int rail_time;
   int airbase_time;
@@ -143,8 +142,9 @@ struct terrain {
   int clean_pollution_time;
   int clean_fallout_time;
 
-  Terrain_type_id warmer_wetter_result, warmer_drier_result;
-  Terrain_type_id cooler_wetter_result, cooler_drier_result;
+  /* May be NULL if the transformation is impossible. */
+  struct terrain *warmer_wetter_result, *warmer_drier_result;
+  struct terrain *cooler_wetter_result, *cooler_drier_result;
 
   /* These are special properties of the terrain used by mapgen.  Generally
    * for each property, if a tile is deemed to have that property then
@@ -160,25 +160,24 @@ struct terrain {
   char *helptext;
 };
 
-extern struct terrain terrains[MAX_NUM_TERRAINS];
-
 /* Terrain allocation functions. */
 void terrains_init(void);
 
 /* General terrain accessor functions. */
 struct terrain *get_terrain(Terrain_type_id type);
-Terrain_type_id get_terrain_by_name(const char * name);
-const char *get_terrain_name(Terrain_type_id type);
+struct terrain *get_terrain_by_name(const char *name);
+const char *get_terrain_name(const struct terrain *pterrain);
 enum terrain_flag_id terrain_flag_from_str(const char *s);
-#define terrain_has_flag(terr, flag) BV_ISSET(terrains[(terr)].flags, flag)
-Terrain_type_id get_flag_terrain(enum terrain_flag_id flag);
+#define terrain_has_flag(terr, flag) BV_ISSET((terr)->flags, flag)
+struct terrain *get_flag_terrain(enum terrain_flag_id flag);
 void terrains_free(void);
 
 /* Functions to operate on a general terrain type. */
-bool is_terrain_near_tile(const struct tile *ptile, Terrain_type_id t);
+bool is_terrain_near_tile(const struct tile *ptile,
+                         const struct terrain *pterrain);
 int count_terrain_near_tile(const struct tile *ptile,
                            bool cardinal_only, bool percentage,
-                           Terrain_type_id t);
+                           const struct terrain *pterrain);
 int count_terrain_property_near_tile(const struct tile *ptile,
                                     bool cardinal_only, bool percentage,
                                     enum mapgen_terrain_property prop);
@@ -212,17 +211,20 @@ enum tile_special_type get_infrastructur
 enum tile_special_type get_preferred_pillage(bv_special pset);
 
 /* Terrain-specific functions. */
-#define is_ocean(x) (terrain_has_flag((x), TER_OCEANIC))
+#define is_ocean(pterrain) (terrain_has_flag((pterrain), TER_OCEANIC))
 #define is_ocean_near_tile(ptile) \
   is_terrain_flag_near_tile(ptile, TER_OCEANIC)
 #define count_ocean_near_tile(ptile, cardinal_only, percentage)                
\
   count_terrain_flag_near_tile(ptile, cardinal_only, percentage, TER_OCEANIC)
 
 /* This iterator iterates over all terrain types. */
-#define terrain_type_iterate(id)                                            \
+#define terrain_type_iterate(pterrain)                                     \
 {                                                                           \
-  Terrain_type_id id;                                                \
-  for (id = T_FIRST; id < T_COUNT; id++) {
+  Terrain_type_id _index;                                                  \
+                                                                           \
+  for (_index = T_FIRST; _index < T_COUNT; _index++) {                     \
+    struct terrain *pterrain = get_terrain(_index);
+    
 
 #define terrain_type_iterate_end                                            \
   }                                                                         \
Index: common/tile.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/tile.c,v
retrieving revision 1.8
diff -p -u -r1.8 tile.c
--- common/tile.c       9 Jul 2005 17:46:08 -0000       1.8
+++ common/tile.c       9 Jul 2005 23:17:32 -0000
@@ -57,7 +57,7 @@ void tile_set_city(struct tile *ptile, s
   Return the terrain ID of the tile.  Terrains are defined in the ruleset
   (see terrain.h).
 ****************************************************************************/
-Terrain_type_id tile_get_terrain(const struct tile *ptile)
+struct terrain *tile_get_terrain(const struct tile *ptile)
 {
   return ptile->terrain;
 }
@@ -65,9 +65,9 @@ Terrain_type_id tile_get_terrain(const s
 /****************************************************************************
   Set the terrain ID of the tile.  See tile_get_terrain.
 ****************************************************************************/
-void tile_set_terrain(struct tile *ptile, Terrain_type_id ter)
+void tile_set_terrain(struct tile *ptile, struct terrain *pterrain)
 {
-  ptile->terrain = ter;
+  ptile->terrain = pterrain;
 }
 
 /****************************************************************************
@@ -164,23 +164,23 @@ int tile_activity_time(enum unit_activit
 {
   switch (activity) {
   case ACTIVITY_POLLUTION:
-    return terrains[ptile->terrain].clean_pollution_time * ACTIVITY_FACTOR;
+    return ptile->terrain->clean_pollution_time * ACTIVITY_FACTOR;
   case ACTIVITY_ROAD:
-    return terrains[ptile->terrain].road_time * ACTIVITY_FACTOR;
+    return ptile->terrain->road_time * ACTIVITY_FACTOR;
   case ACTIVITY_MINE:
-    return terrains[ptile->terrain].mining_time * ACTIVITY_FACTOR;
+    return ptile->terrain->mining_time * ACTIVITY_FACTOR;
   case ACTIVITY_IRRIGATE:
-    return terrains[ptile->terrain].irrigation_time * ACTIVITY_FACTOR;
+    return ptile->terrain->irrigation_time * ACTIVITY_FACTOR;
   case ACTIVITY_FORTRESS:
-    return terrains[ptile->terrain].fortress_time * ACTIVITY_FACTOR;
+    return ptile->terrain->fortress_time * ACTIVITY_FACTOR;
   case ACTIVITY_RAILROAD:
-    return terrains[ptile->terrain].rail_time * ACTIVITY_FACTOR;
+    return ptile->terrain->rail_time * ACTIVITY_FACTOR;
   case ACTIVITY_TRANSFORM:
-    return terrains[ptile->terrain].transform_time * ACTIVITY_FACTOR;
+    return ptile->terrain->transform_time * ACTIVITY_FACTOR;
   case ACTIVITY_AIRBASE:
-    return terrains[ptile->terrain].airbase_time * ACTIVITY_FACTOR;
+    return ptile->terrain->airbase_time * ACTIVITY_FACTOR;
   case ACTIVITY_FALLOUT:
-    return terrains[ptile->terrain].clean_fallout_time * ACTIVITY_FACTOR;
+    return ptile->terrain->clean_fallout_time * ACTIVITY_FACTOR;
   default:
     return 0;
   }
@@ -212,10 +212,10 @@ static void tile_clear_dirtiness(struct 
   the tile (as will happen when mining/irrigation/transforming changes the
   tile's terrain).
 ****************************************************************************/
-void tile_change_terrain(struct tile *ptile, Terrain_type_id type)
+void tile_change_terrain(struct tile *ptile, struct terrain *pterrain)
 {
-  tile_set_terrain(ptile, type);
-  if (is_ocean(type)) {
+  tile_set_terrain(ptile, pterrain);
+  if (is_ocean(pterrain)) {
     tile_clear_infrastructure(ptile);
     tile_clear_dirtiness(ptile);
 
@@ -227,11 +227,11 @@ void tile_change_terrain(struct tile *pt
   /* Clear mining/irrigation if resulting terrain type cannot support
    * that feature. */
   
-  if (terrains[type].mining_result != type) {
+  if (pterrain->mining_result != pterrain) {
     tile_clear_special(ptile, S_MINE);
   }
 
-  if (terrains[type].irrigation_result != type) {
+  if (pterrain->irrigation_result != pterrain) {
     tile_clear_special(ptile, S_IRRIGATION);
     tile_clear_special(ptile, S_FARMLAND);
   }
@@ -243,10 +243,10 @@ void tile_change_terrain(struct tile *pt
 ****************************************************************************/
 static void tile_irrigate(struct tile *ptile)
 {
-  Terrain_type_id now, result;
+  struct terrain *now, *result;
   
   now = ptile->terrain;
-  result = terrains[now].irrigation_result;
+  result = now->irrigation_result;
 
   if (now == result) {
     if (tile_has_special(ptile, S_IRRIGATION)) {
@@ -266,10 +266,10 @@ static void tile_irrigate(struct tile *p
 ****************************************************************************/
 static void tile_mine(struct tile *ptile)
 {
-  Terrain_type_id now, result;
+  struct terrain *now, *result;
   
   now = ptile->terrain;
-  result = terrains[now].mining_result;
+  result = now->mining_result;
   
   if (now == result) {
     tile_set_special(ptile, S_MINE);
@@ -286,10 +286,10 @@ static void tile_mine(struct tile *ptile
 ****************************************************************************/
 static void tile_transform(struct tile *ptile)
 {
-  Terrain_type_id now, result;
+  struct terrain *now, *result;
   
   now = ptile->terrain;
-  result = terrains[now].transform_result;
+  result = now->transform_result;
   
   if (result != T_NONE) {
     tile_change_terrain(ptile, result);
@@ -378,7 +378,7 @@ const char *tile_get_info_text(const str
   static char s[256];
   bool first;
 
-  sz_strlcpy(s, terrains[ptile->terrain].terrain_name);
+  sz_strlcpy(s, ptile->terrain->terrain_name);
   if (tile_has_special(ptile, S_RIVER)) {
     sz_strlcat(s, "/");
     sz_strlcat(s, get_special_name(S_RIVER));
@@ -392,7 +392,7 @@ const char *tile_get_info_text(const str
     } else {
       sz_strlcat(s, "/");
     }
-    sz_strlcat(s, terrains[ptile->terrain].special[0].name);
+    sz_strlcat(s, ptile->terrain->special[0].name);
   }
   if (tile_has_special(ptile, S_SPECIAL_2)) {
     if (first) {
@@ -401,7 +401,7 @@ const char *tile_get_info_text(const str
     } else {
       sz_strlcat(s, "/");
     }
-    sz_strlcat(s, terrains[ptile->terrain].special[1].name);
+    sz_strlcat(s, ptile->terrain->special[1].name);
   }
   if (!first) {
     sz_strlcat(s, ")");
Index: common/tile.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/tile.h,v
retrieving revision 1.10
diff -p -u -r1.10 tile.h
--- common/tile.h       8 Jul 2005 03:31:18 -0000       1.10
+++ common/tile.h       9 Jul 2005 23:17:32 -0000
@@ -28,7 +28,7 @@ struct tile {
   int x, y; /* Cartesian (map) coordinates of the tile. */
   int nat_x, nat_y; /* Native coordinates of the tile. */
   int index; /* Index coordinate of the tile. */
-  Terrain_type_id terrain;
+  struct terrain *terrain; /* May be NULL for unknown tiles. */
   bv_special special;
   struct city *city;        /* city standing on the tile, NULL if none */
   struct unit_list *units;
@@ -53,8 +53,8 @@ struct player *tile_get_owner(const stru
 void tile_set_owner(struct tile *ptile, struct player *pplayer);
 struct city *tile_get_city(const struct tile *ptile);
 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);
+struct terrain *tile_get_terrain(const struct tile *ptile);
+void tile_set_terrain(struct tile *ptile, struct terrain *pterrain);
 bv_special tile_get_special(const struct tile *ptile);
 bool tile_has_special(const struct tile *ptile,
                      enum tile_special_type to_test_for);
@@ -73,7 +73,7 @@ enum known_type tile_get_known(const str
 int tile_activity_time(enum unit_activity activity,
                       const struct tile *ptile);
 
-void tile_change_terrain(struct tile *ptile, Terrain_type_id type);
+void tile_change_terrain(struct tile *ptile, struct terrain *pterrain);
 bool tile_apply_activity(struct tile *ptile, Activity_type_id act);
 
 const char *tile_get_info_text(const struct tile *ptile);
Index: common/unit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.c,v
retrieving revision 1.244
diff -p -u -r1.244 unit.c
--- common/unit.c       9 Jul 2005 17:46:08 -0000       1.244
+++ common/unit.c       9 Jul 2005 23:17:32 -0000
@@ -731,7 +731,7 @@ bool can_unit_do_activity_targeted_at(co
                                      const struct tile *ptile)
 {
   struct player *pplayer = unit_owner(punit);
-  struct terrain *type = get_terrain(ptile->terrain);
+  struct terrain *pterrain = ptile->terrain;
 
   switch(activity) {
   case ACTIVITY_IDLE:
@@ -750,7 +750,7 @@ bool can_unit_do_activity_targeted_at(co
     return (terrain_control.may_road
            && unit_flag(punit, F_SETTLERS)
            && !tile_has_special(ptile, S_ROAD)
-           && type->road_time != 0
+           && pterrain->road_time != 0
            && (!tile_has_special(ptile, S_RIVER)
                || player_knows_techs_with_flag(pplayer, TF_BRIDGE)));
 
@@ -759,17 +759,17 @@ bool can_unit_do_activity_targeted_at(co
      * *Do* allow it if they're transforming - the mine may survive */
     if (terrain_control.may_mine
        && unit_flag(punit, F_SETTLERS)
-       && ((ptile->terrain == type->mining_result
+       && ((ptile->terrain == pterrain->mining_result
             && !tile_has_special(ptile, S_MINE))
-           || (ptile->terrain != type->mining_result
-               && type->mining_result != T_NONE
+           || (ptile->terrain != pterrain->mining_result
+               && pterrain->mining_result != T_NONE
                && (!is_ocean(ptile->terrain)
-                   || is_ocean(type->mining_result)
+                   || is_ocean(pterrain->mining_result)
                    || can_reclaim_ocean(ptile))
                && (is_ocean(ptile->terrain)
-                   || !is_ocean(type->mining_result)
+                   || !is_ocean(pterrain->mining_result)
                    || can_channel_land(ptile))
-               && (!is_ocean(type->mining_result)
+               && (!is_ocean(pterrain->mining_result)
                    || !tile_get_city(ptile))))) {
       unit_list_iterate(ptile->units, tunit) {
        if (tunit->activity == ACTIVITY_IRRIGATE) {
@@ -789,17 +789,17 @@ bool can_unit_do_activity_targeted_at(co
        && (!tile_has_special(ptile, S_IRRIGATION)
            || (!tile_has_special(ptile, S_FARMLAND)
                && player_knows_techs_with_flag(pplayer, TF_FARMLAND)))
-       && ((ptile->terrain == type->irrigation_result
+       && ((ptile->terrain == pterrain->irrigation_result
             && is_water_adjacent_to_tile(ptile))
-           || (ptile->terrain != type->irrigation_result
-               && type->irrigation_result != T_NONE
+           || (ptile->terrain != pterrain->irrigation_result
+               && pterrain->irrigation_result != T_NONE
                && (!is_ocean(ptile->terrain)
-                   || is_ocean(type->irrigation_result)
+                   || is_ocean(pterrain->irrigation_result)
                    || can_reclaim_ocean(ptile))
                && (is_ocean(ptile->terrain)
-                   || !is_ocean(type->irrigation_result)
+                   || !is_ocean(pterrain->irrigation_result)
                    || can_channel_land(ptile))
-               && (!is_ocean(type->irrigation_result)
+               && (!is_ocean(pterrain->irrigation_result)
                    || !tile_get_city(ptile))))) {
       unit_list_iterate(ptile->units, tunit) {
        if (tunit->activity == ACTIVITY_MINE) {
@@ -891,15 +891,15 @@ bool can_unit_do_activity_targeted_at(co
 
   case ACTIVITY_TRANSFORM:
     return (terrain_control.may_transform
-           && type->transform_result != T_NONE
-           && ptile->terrain != type->transform_result
+           && pterrain->transform_result != T_NONE
+           && ptile->terrain != pterrain->transform_result
            && (!is_ocean(ptile->terrain)
-               || is_ocean(type->transform_result)
+               || is_ocean(pterrain->transform_result)
                || can_reclaim_ocean(ptile))
            && (is_ocean(ptile->terrain)
-               || !is_ocean(type->transform_result)
+               || !is_ocean(pterrain->transform_result)
                || can_channel_land(ptile))
-           && (!terrain_has_flag(type->transform_result, TER_NO_CITIES)
+           && (!terrain_has_flag(pterrain->transform_result, TER_NO_CITIES)
                || !(tile_get_city(ptile)))
            && unit_flag(punit, F_TRANSFORM));
 
Index: common/aicore/pf_tools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/pf_tools.c,v
retrieving revision 1.34
diff -p -u -r1.34 pf_tools.c
--- common/aicore/pf_tools.c    9 Jul 2005 17:46:09 -0000       1.34
+++ common/aicore/pf_tools.c    9 Jul 2005 23:17:32 -0000
@@ -122,7 +122,7 @@ static int normal_move_unit(const struct
                            const struct tile *ptile1,
                            struct pf_parameter *param)
 {
-  Terrain_type_id terrain1 = ptile1->terrain;
+  struct terrain *terrain1 = ptile1->terrain;
   int move_cost;
 
   if (is_ocean(terrain1)) {
@@ -137,7 +137,7 @@ static int normal_move_unit(const struct
             || is_non_allied_city_tile(ptile1, param->owner))) {
       move_cost = PF_IMPOSSIBLE_MC;
     } else {
-      move_cost = get_terrain(terrain1)->movement_cost * SINGLE_MOVE;
+      move_cost = terrain1->movement_cost * SINGLE_MOVE;
     }
   } else {
     move_cost = map_move_cost_ai(ptile, ptile1);
@@ -169,8 +169,7 @@ static int land_attack_move(const struct
     /* Sea-to-Land. */
     if (!is_non_allied_unit_tile(tgt_tile, param->owner)
         && !is_non_allied_city_tile(tgt_tile, param->owner)) {
-      move_cost 
-        = get_terrain(tgt_tile->terrain)->movement_cost * SINGLE_MOVE;
+      move_cost = tgt_tile->terrain->movement_cost * SINGLE_MOVE;
     } else if (BV_ISSET(param->unit_flags, F_MARINES)) {
       /* Can attack!! */
       move_cost = SINGLE_MOVE;
@@ -217,13 +216,13 @@ static int land_overlap_move(const struc
                             const struct tile *ptile1,
                             struct pf_parameter *param)
 {
-  Terrain_type_id terrain1 = ptile1->terrain;
+  struct terrain *terrain1 = ptile1->terrain;
   int move_cost;
 
   if (is_ocean(terrain1)) {
     move_cost = SINGLE_MOVE;
   } else if (is_ocean(ptile->terrain)) {
-    move_cost = get_terrain(terrain1)->movement_cost * SINGLE_MOVE;
+    move_cost = terrain1->movement_cost * SINGLE_MOVE;
   } else {
     move_cost = map_move_cost_ai(ptile, ptile1);
   }
@@ -240,14 +239,14 @@ static int reverse_move_unit(const struc
                             const struct tile *ptile,
                             struct pf_parameter *param)
 {
-  int terrain0 = tile_get_terrain(tile0);
-  int terrain1 = ptile->terrain;
+  struct terrain *terrain0 = tile0->terrain;
+  struct terrain *terrain1 = ptile->terrain;
   int move_cost = PF_IMPOSSIBLE_MC;
 
   if (is_ocean(terrain1)) {
     if (ground_unit_transporter_capacity(ptile, param->owner) > 0) {
       /* Landing */
-      move_cost = get_terrain(terrain0)->movement_cost * SINGLE_MOVE;
+      move_cost = terrain0->movement_cost * SINGLE_MOVE;
     } else {
       /* Nothing to land from */
       move_cost = PF_IMPOSSIBLE_MC;
@@ -305,14 +304,14 @@ static int reverse_igter_move_unit(const
 {
   int move_cost;
 
-  if (is_ocean(tile_get_terrain(ptile))) {
+  if (is_ocean(ptile->terrain)) {
     if (ground_unit_transporter_capacity(ptile, param->owner) > 0) {
       /* Landing */
       move_cost = MOVE_COST_ROAD;
     } else {
       move_cost = PF_IMPOSSIBLE_MC;
     }
-  } else if (is_ocean(tile_get_terrain(tile0))) {
+  } else if (is_ocean(tile0->terrain)) {
     /* Boarding */
     move_cost = MOVE_COST_ROAD;
   } else {
@@ -378,7 +377,7 @@ static int afraid_of_dark_forest(const s
                                 enum known_type known,
                                 struct pf_parameter *param)
 {
-  if (tile_get_terrain(ptile) == T_FOREST) {
+  if (ptile->terrain->index == T_FOREST) {
     /* Willing to spend extra 2 turns to go around a forest tile */
     return PF_TURN_FACTOR * 2;
   }
Index: manual/civmanual.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/manual/civmanual.c,v
retrieving revision 1.13
diff -p -u -r1.13 civmanual.c
--- manual/civmanual.c  9 Jul 2005 17:46:09 -0000       1.13
+++ manual/civmanual.c  9 Jul 2005 23:17:33 -0000
@@ -225,38 +225,37 @@ static bool manual_command(void)
       fprintf(doc, _("<th>Irrigation +food</th><th>Mining +shields</th>\n"));
       fprintf(doc, _("<th>Transform to</th>"));
       fprintf(doc, "</tr>\n");
-      terrain_type_iterate(id) {
-       struct terrain *ptype = get_terrain(id);
+      terrain_type_iterate(pterrain) {
        int s;
 
-       if (ptype->defense_bonus == 0) {
+       if (pterrain->defense_bonus == 0) {
          /* Must be a disabled piece of terrain */
          continue;
        }
 
        fprintf(doc, "<tr><td>%s%s%s %s</td>", IMAGE_BEGIN,
-               ptype->graphic_str,
-               IMAGE_END, get_terrain_name(id));
+               pterrain->graphic_str,
+               IMAGE_END, get_terrain_name(pterrain));
        fprintf(doc, "<td>%d / %d / %d</td>",
-               ptype->output[O_FOOD], ptype->output[O_SHIELD],
-               ptype->output[O_TRADE]);
+               pterrain->output[O_FOOD], pterrain->output[O_SHIELD],
+               pterrain->output[O_TRADE]);
 
        for (s = 0; s < MAX_NUM_SPECIALS; s++) {
          fprintf(doc, "<td>%s%s%s %s</td>", IMAGE_BEGIN,
-                 ptype->special[s].graphic_str, IMAGE_END,
-                 ptype->special[s].name);
+                 pterrain->special[s].graphic_str, IMAGE_END,
+                 pterrain->special[s].name);
          fprintf(doc, "<td>%d / %d / %d</td>",
-                 ptype->special[s].output[O_FOOD],
-                 ptype->special[s].output[O_SHIELD],
-                 ptype->special[s].output[O_TRADE]);
+                 pterrain->special[s].output[O_FOOD],
+                 pterrain->special[s].output[O_SHIELD],
+                 pterrain->special[s].output[O_TRADE]);
        }
 
-       fprintf(doc, "<td>%d</td>\n", ptype->movement_cost);
+       fprintf(doc, "<td>%d</td>\n", pterrain->movement_cost);
        fprintf(doc, "<td>%d0%%</td><td>%d</td><td>%d</td><td>%d</td>\n",
-               ptype->defense_bonus, ptype->road_trade_incr,
-               ptype->irrigation_food_incr, ptype->mining_shield_incr);
+               pterrain->defense_bonus, pterrain->road_trade_incr,
+               pterrain->irrigation_food_incr, pterrain->mining_shield_incr);
        fprintf(doc, "<td>%s</td></tr>\n\n",
-               get_terrain_name(ptype->transform_result));
+               get_terrain_name(pterrain->transform_result));
       } terrain_type_iterate_end;
       fprintf(doc, _("</table><br><br><br><table border=1>"));
       fprintf(doc, _("<caption>Time to perform action</caption>"));
@@ -266,24 +265,23 @@ static bool manual_command(void)
       fprintf(doc, _("<th>Airbase</th><th>Fortress</th>\n"));
       fprintf(doc, _("<th>Clean pollution</th><th>Clean fallout</th>\n"));
       fprintf(doc, _("<th>Transform</th></tr>\n"));
-      terrain_type_iterate(id) {
-       const char *name = get_terrain_name(id);
-       struct terrain *ptype = get_terrain(id);
+      terrain_type_iterate(pterrain) {
+       const char *name = get_terrain_name(pterrain);
 
-       if (ptype->terrain_name[0] == '\0') {
+       if (pterrain->terrain_name[0] == '\0') {
          /* Must be a disabled piece of terrain */
          continue;
        }
 
        fprintf(doc, "<tr><td>%s%s%s %s</td><td>%d</td>\n",
-               IMAGE_BEGIN, ptype->graphic_str, IMAGE_END, name,
-               ptype->road_time);
+               IMAGE_BEGIN, pterrain->graphic_str, IMAGE_END, name,
+               pterrain->road_time);
        fprintf(doc, "<td>%d</td><td>%d</td><td>%d</td><td>%d</td>\n",
-               ptype->irrigation_time, ptype->mining_time,
-               ptype->rail_time, ptype->airbase_time);
+               pterrain->irrigation_time, pterrain->mining_time,
+               pterrain->rail_time, pterrain->airbase_time);
        fprintf(doc, "<td>%d</td><td>%d</td><td>%d</td><td>%d</td>\n",
-               ptype->fortress_time, ptype->clean_pollution_time,
-               ptype->clean_fallout_time, ptype->transform_time);
+               pterrain->fortress_time, pterrain->clean_pollution_time,
+               pterrain->clean_fallout_time, pterrain->transform_time);
        fprintf(doc, "</tr>\n\n");
       } terrain_type_iterate_end;
 
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.332
diff -p -u -r1.332 citytools.c
--- server/citytools.c  4 Jul 2005 17:48:38 -0000       1.332
+++ server/citytools.c  9 Jul 2005 23:17:33 -0000
@@ -128,7 +128,6 @@ static int evaluate_city_name_priority(s
   /* Lower values mean higher priority. */
   float priority = (float)default_priority;
   int goodness;
-  Terrain_type_id type;
 
   /* Increasing this value will increase the difference caused by
      (non-)matching terrain.  A matching terrain is mult_factor
@@ -183,16 +182,18 @@ static int evaluate_city_name_priority(s
     priority *= mult_factor;
   }
 
-  for (type = T_FIRST; type < T_COUNT; type++) {
+  terrain_type_iterate(pterrain) {
     /* Now we do the same for every available terrain. */
-    goodness = is_terrain_near_tile(ptile, type) ?
-                city_name->terrain[type] : -city_name->terrain[type];
+    goodness
+      = is_terrain_near_tile(ptile, pterrain)
+      ? city_name->terrain[pterrain->index]
+      : -city_name->terrain[pterrain->index];
     if (goodness > 0) {
       priority /= mult_factor;
     } else if (goodness < 0) {
       priority *= mult_factor;
     }
-  }
+  } terrain_type_iterate_end;
 
   return (int)priority;        
 }
Index: server/gotohand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gotohand.c,v
retrieving revision 1.194
diff -p -u -r1.194 gotohand.c
--- server/gotohand.c   9 Jul 2005 17:46:09 -0000       1.194
+++ server/gotohand.c   9 Jul 2005 23:17:34 -0000
@@ -311,7 +311,9 @@ void really_generate_warmap(struct city 
           else
            continue;
        } else if (is_ocean(ptile->terrain)) {
-         int base_cost = get_terrain(tile_get_terrain(tile1))->movement_cost * 
SINGLE_MOVE;
+         int base_cost
+           = tile_get_terrain(tile1)->movement_cost * SINGLE_MOVE;
+
          move_cost = igter ? MOVE_COST_ROAD : MIN(base_cost, 
unit_move_rate(punit));
         } else if (igter)
          /* NOT c = 1 (Syela) [why not? - Thue] */
@@ -655,7 +657,8 @@ static bool find_the_shortest_path(struc
          else
            move_cost = 3;
        } else if (is_ocean(psrctile->terrain)) {
-         int base_cost = get_terrain(pdesttile->terrain)->movement_cost * 
SINGLE_MOVE;
+         int base_cost = pdesttile->terrain->movement_cost * SINGLE_MOVE;
+
          move_cost = igter ? 1 : MIN(base_cost, unit_move_rate(punit));
        } else if (igter)
          move_cost = (map_move_cost_ai(psrctile, pdesttile) != 0
Index: server/maphand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/maphand.c,v
retrieving revision 1.169
diff -p -u -r1.169 maphand.c
--- server/maphand.c    9 Jul 2005 17:46:09 -0000       1.169
+++ server/maphand.c    9 Jul 2005 23:17:34 -0000
@@ -150,15 +150,15 @@ void assign_continent_numbers(bool skip_
 
   /* Assign new numbers */
   whole_map_iterate(ptile) {
-    const Terrain_type_id ter = tile_get_terrain(ptile);
+    const struct terrain *pterrain = tile_get_terrain(ptile);
 
     if (tile_get_continent(ptile) != 0) {
       /* Already assigned. */
       continue;
     }
 
-    if (!skip_unsafe || !terrain_has_flag(ter, TER_UNSAFE)) {
-      if (!is_ocean(ter)) {
+    if (!skip_unsafe || !terrain_has_flag(pterrain, TER_UNSAFE)) {
+      if (!is_ocean(pterrain)) {
        map.num_continents++;
        assert(map.num_continents < MAP_NCONT);
        assign_continent_flood(ptile, TRUE, map.num_continents, skip_unsafe);
@@ -209,15 +209,15 @@ void global_warming(int effect)
 
   k = map_num_tiles();
   while(effect > 0 && (k--) > 0) {
-    Terrain_type_id old, new;
+    struct terrain *old, *new;
     struct tile *ptile;
 
     ptile = rand_map_pos();
     old = tile_get_terrain(ptile);
     if (is_terrain_ecologically_wet(ptile)) {
-      new = get_terrain(old)->warmer_wetter_result;
+      new = old->warmer_wetter_result;
     } else {
-      new = get_terrain(old)->warmer_drier_result;
+      new = old->warmer_drier_result;
     }
     if (new != T_NONE && old != new) {
       effect--;
@@ -251,15 +251,15 @@ void nuclear_winter(int effect)
 
   k = map_num_tiles();
   while(effect > 0 && (k--) > 0) {
-    Terrain_type_id old, new;
+    struct terrain *old, *new;
     struct tile *ptile;
 
     ptile = rand_map_pos();
     old = tile_get_terrain(ptile);
     if (is_terrain_ecologically_wet(ptile)) {
-      new = get_terrain(old)->cooler_wetter_result;
+      new = old->cooler_wetter_result;
     } else {
-      new = get_terrain(old)->cooler_drier_result;
+      new = old->cooler_drier_result;
     }
     if (new != T_NONE && old != new) {
       effect--;
@@ -471,7 +471,7 @@ void send_tile_info(struct conn_list *de
     }
     if (!pplayer || map_is_known_and_seen(ptile, pplayer)) {
       info.known = TILE_KNOWN;
-      info.type = ptile->terrain;
+      info.type = ptile->terrain->index;
       for (spe = 0; spe < S_LAST; spe++) {
        info.special[spe] = BV_ISSET(ptile->special, spe);
       }
@@ -481,8 +481,9 @@ void send_tile_info(struct conn_list *de
     } else if (pplayer && map_is_known(ptile, pplayer)
               && map_get_seen(ptile, pplayer) == 0) {
       struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
+
       info.known = TILE_KNOWN_FOGGED;
-      info.type = plrtile->terrain;
+      info.type = plrtile->terrain->index;
       info.owner = plrtile->owner >= 0 ? plrtile->owner : MAP_TILE_OWNER_NULL;
       for (spe = 0; spe < S_LAST; spe++) {
        info.special[spe] = BV_ISSET(plrtile->special, spe);
@@ -522,7 +523,7 @@ static void send_tile_info_always(struct
   if (!pplayer) {
     /* Observer sees all. */
     info.known=TILE_KNOWN;
-    info.type = ptile->terrain;
+    info.type = ptile->terrain->index;
     for (spe = 0; spe < S_LAST; spe++) {
       info.special[spe] = BV_ISSET(ptile->special, spe);
     }
@@ -536,7 +537,7 @@ static void send_tile_info_always(struct
       info.known = TILE_KNOWN_FOGGED;
     }
     plrtile = map_get_player_tile(ptile, pplayer);
-    info.type = plrtile->terrain;
+    info.type = plrtile->terrain->index;
     for (spe = 0; spe < S_LAST; spe++) {
       info.special[spe] = BV_ISSET(plrtile->special, spe);
     }
@@ -544,7 +545,7 @@ static void send_tile_info_always(struct
   } else {
     /* Unknown (the client needs these sometimes to draw correctly). */
     info.known = TILE_UNKNOWN;
-    info.type = ptile->terrain;
+    info.type = ptile->terrain->index;
     for (spe = 0; spe < S_LAST; spe++) {
       info.special[spe] = BV_ISSET(ptile->special, spe);
     }
@@ -1514,9 +1515,9 @@ static void ocean_to_land_fix_rivers(str
   continent numbers.
 **************************************************************************/
 enum ocean_land_change check_terrain_ocean_land_change(struct tile *ptile,
-                                                Terrain_type_id oldter)
+                                                struct terrain *oldter)
 {
-  Terrain_type_id newter = tile_get_terrain(ptile);
+  struct terrain *newter = tile_get_terrain(ptile);
   enum ocean_land_change change_type = OLC_NONE;
 
   if (is_ocean(oldter) && !is_ocean(newter)) {
Index: server/maphand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/maphand.h,v
retrieving revision 1.58
diff -p -u -r1.58 maphand.h
--- server/maphand.h    4 Jul 2005 17:48:38 -0000       1.58
+++ server/maphand.h    9 Jul 2005 23:17:34 -0000
@@ -39,7 +39,7 @@ struct dumb_city{
 };
 
 struct player_tile {
-  Terrain_type_id terrain;
+  struct terrain *terrain; /* May be NULL for unknown tiles. */
   bv_special special;
   signed char owner;
   unsigned short seen_count;
@@ -108,7 +108,7 @@ void map_update_borders_landmass_change(
 void map_calculate_borders(void);
 
 enum ocean_land_change check_terrain_ocean_land_change(struct tile *ptile,
-                                              Terrain_type_id oldter);
+                                              struct terrain *oldter);
 int get_continent_size(Continent_id id);
 int get_ocean_size(Continent_id id);
 
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.271
diff -p -u -r1.271 ruleset.c
--- server/ruleset.c    9 Jul 2005 17:46:09 -0000       1.271
+++ server/ruleset.c    9 Jul 2005 23:17:34 -0000
@@ -72,8 +72,7 @@ static int lookup_city_cost(struct secti
                            const char *entry, const char *filename);
 static char *lookup_helptext(struct section_file *file, char *prefix);
 
-static Terrain_type_id lookup_terrain(char *name, 
-                                             Terrain_type_id tthis);
+static struct terrain *lookup_terrain(char *name, struct terrain *tthis);
 
 static void load_tech_names(struct section_file *file);
 static void load_unit_names(struct section_file *file);
@@ -646,11 +645,8 @@ static char *lookup_helptext(struct sect
 /**************************************************************************
   Look up a terrain name in the tile_types array and return its index.
 **************************************************************************/
-static Terrain_type_id lookup_terrain(char *name, 
-                                             Terrain_type_id tthis)
+static struct terrain *lookup_terrain(char *name, struct terrain *tthis)
 {
-  Terrain_type_id i;
-
   if (*name == '\0' || (0 == strcmp(name, "none")) 
       || (0 == strcmp(name, "no"))) {
     return T_NONE;
@@ -658,15 +654,15 @@ static Terrain_type_id lookup_terrain(ch
     return (tthis);
   }
 
-  for (i = T_FIRST; i < T_COUNT; i++) {
-    if (0 == strcmp(name, terrains[i].terrain_name)) {
-      return i;
+  terrain_type_iterate(pterrain) {
+    if (0 == strcmp(name, pterrain->terrain_name)) {
+      return pterrain;
     }
-  }
+  } terrain_type_iterate_end;
 
   /* TRANS: message for an obscure ruleset error. */
   freelog(LOG_ERROR, _("Unknown terrain %s in entry %s."),
-         name, terrains[tthis].terrain_name);
+         name, tthis->terrain_name);
   return T_NONE;
 }
 
@@ -1402,14 +1398,15 @@ static void load_terrain_names(struct se
   }
   game.control.terrain_count = nval;
 
-  terrain_type_iterate(i) {
-    char *name = secfile_lookup_str(file, "%s.terrain_name", sec[i]);
-
-    name_strlcpy(terrains[i].terrain_name_orig, name);
-    if (0 == strcmp(terrains[i].terrain_name_orig, "unused")) {
-      terrains[i].terrain_name_orig[0] = '\0';
+  terrain_type_iterate(pterrain) {
+    char *name = secfile_lookup_str(file, "%s.terrain_name",
+                                   sec[pterrain->index]);
+
+    name_strlcpy(pterrain->terrain_name_orig, name);
+    if (0 == strcmp(pterrain->terrain_name_orig, "unused")) {
+      pterrain->terrain_name_orig[0] = '\0';
     }
-    terrains[i].terrain_name = terrains[i].terrain_name_orig;
+    pterrain->terrain_name = pterrain->terrain_name_orig;
   } terrain_type_iterate_end;
 
   free(sec);
@@ -1490,137 +1487,147 @@ static void load_ruleset_terrain(struct 
 
   /* terrain details */
 
-  terrain_type_iterate(i) {
-      struct terrain *t = &(terrains[i]);
-      char **slist;
-
-      sz_strlcpy(t->graphic_str,
-                secfile_lookup_str(file,"%s.graphic", sec[i]));
-      sz_strlcpy(t->graphic_alt,
-                secfile_lookup_str(file,"%s.graphic_alt", sec[i]));
-
-      t->identifier = secfile_lookup_str(file, "%s.identifier", sec[i])[0];
-      for (j = T_FIRST; j < i; j++) {
-       if (t->identifier == terrains[j].identifier) {
-         freelog(LOG_FATAL,
-                 /* TRANS: message for an obscure ruleset error. */
-                 _("Terrains %s and %s have the same identifier."),
-                 t->terrain_name, terrains[j].terrain_name);
-         exit(EXIT_FAILURE);
-       }
-      }
-      if (t->identifier == UNKNOWN_TERRAIN_IDENTIFIER) {
-       /* TRANS: message for an obscure ruleset error. */
-       freelog(LOG_FATAL, _("'%c' cannot be used as a terrain identifier; "
-                            "it is reserved."), UNKNOWN_TERRAIN_IDENTIFIER);
+  terrain_type_iterate(pterrain) {
+    char **slist;
+    const int i = pterrain->index;
+
+    sz_strlcpy(pterrain->graphic_str,
+              secfile_lookup_str(file,"%s.graphic", sec[i]));
+    sz_strlcpy(pterrain->graphic_alt,
+              secfile_lookup_str(file,"%s.graphic_alt", sec[i]));
+
+    pterrain->identifier
+      = secfile_lookup_str(file, "%s.identifier", sec[i])[0];
+    for (j = T_FIRST; j < i; j++) {
+      if (pterrain->identifier == get_terrain(j)->identifier) {
+       freelog(LOG_FATAL,
+               /* TRANS: message for an obscure ruleset error. */
+               _("Terrains %s and %s have the same identifier."),
+               pterrain->terrain_name, get_terrain(j)->terrain_name);
        exit(EXIT_FAILURE);
       }
+    }
+    if (pterrain->identifier == UNKNOWN_TERRAIN_IDENTIFIER) {
+      /* TRANS: message for an obscure ruleset error. */
+      freelog(LOG_FATAL, _("'%c' cannot be used as a terrain identifier; "
+                          "it is reserved."), UNKNOWN_TERRAIN_IDENTIFIER);
+      exit(EXIT_FAILURE);
+    }
+
+    pterrain->movement_cost
+      = secfile_lookup_int(file, "%s.movement_cost", sec[i]);
+    pterrain->defense_bonus
+      = secfile_lookup_int(file, "%s.defense_bonus", sec[i]);
 
-      t->movement_cost = secfile_lookup_int(file, "%s.movement_cost", sec[i]);
-      t->defense_bonus = secfile_lookup_int(file, "%s.defense_bonus", sec[i]);
+    output_type_iterate(o) {
+      pterrain->output[o]
+       = secfile_lookup_int_default(file, 0, "%s.%s", sec[i],
+                                    get_output_identifier(o));
+    } output_type_iterate_end;
 
+    for (j = 0; j < MAX_NUM_SPECIALS; j++) {
+      char *name = secfile_lookup_str(file, "%s.special_%d_name",
+                                     sec[i], j + 1);
+
+      name_strlcpy(pterrain->special[j].name_orig, name);
+      if (0 == strcmp(pterrain->special[j].name_orig, "none")) {
+       pterrain->special[j].name_orig[0] = '\0';
+      }
+      pterrain->special[j].name = pterrain->special[j].name_orig;
       output_type_iterate(o) {
-       t->output[o] = secfile_lookup_int_default(file, 0, "%s.%s", sec[i],
-                                                 get_output_identifier(o));
+       pterrain->special[j].output[o]
+         = secfile_lookup_int_default(file, 0, "%s.%s_special_%d", sec[i],
+                                      get_output_identifier(o), j + 1);
       } output_type_iterate_end;
 
-      for (j = 0; j < MAX_NUM_SPECIALS; j++) {
-       char *name = secfile_lookup_str(file, "%s.special_%d_name",
-                                       sec[i], j + 1);
-
-       name_strlcpy(t->special[j].name_orig, name);
-       if (0 == strcmp(t->special[j].name_orig, "none")) {
-         t->special[j].name_orig[0] = '\0';
-       }
-       t->special[j].name = t->special[j].name_orig;
-       output_type_iterate(o) {
-         t->special[j].output[o]
-           = secfile_lookup_int_default(file, 0, "%s.%s_special_%d", sec[i],
-                                        get_output_identifier(o), j + 1);
-       } output_type_iterate_end;
-
-       sz_strlcpy(t->special[j].graphic_str,
-                  secfile_lookup_str(file,"%s.graphic_special_%d",
-                                     sec[i], j+1));
-       sz_strlcpy(t->special[j].graphic_alt,
-                  secfile_lookup_str(file,"%s.graphic_special_%da",
-                                     sec[i], j+1));
-      }
-
-      t->road_trade_incr =
-       secfile_lookup_int(file, "%s.road_trade_incr", sec[i]);
-      t->road_time = secfile_lookup_int(file, "%s.road_time", sec[i]);
-
-      t->irrigation_result =
-       lookup_terrain(secfile_lookup_str(file, "%s.irrigation_result", 
sec[i]), i);
-      t->irrigation_food_incr =
-       secfile_lookup_int(file, "%s.irrigation_food_incr", sec[i]);
-      t->irrigation_time = secfile_lookup_int(file, "%s.irrigation_time", 
sec[i]);
-
-      t->mining_result =
-       lookup_terrain(secfile_lookup_str(file, "%s.mining_result", sec[i]), i);
-      t->mining_shield_incr =
-       secfile_lookup_int(file, "%s.mining_shield_incr", sec[i]);
-      t->mining_time = secfile_lookup_int(file, "%s.mining_time", sec[i]);
-
-      t->transform_result =
-       lookup_terrain(secfile_lookup_str(file, "%s.transform_result", sec[i]), 
i);
-      t->transform_time = secfile_lookup_int(file, "%s.transform_time", 
sec[i]);
-      t->rail_time = 
-          secfile_lookup_int_default(file, 3, "%s.rail_time", sec[i]);
-      t->airbase_time = 
-          secfile_lookup_int_default(file, 3, "%s.airbase_time", sec[i]);
-      t->fortress_time = 
-          secfile_lookup_int_default(file, 3, "%s.fortress_time", sec[i]);
-      t->clean_pollution_time = 
-         secfile_lookup_int_default(file, 3, "%s.clean_pollution_time", 
sec[i]);
-      t->clean_fallout_time = 
-          secfile_lookup_int_default(file, 3, "%s.clean_fallout_time", sec[i]);
-
-      t->warmer_wetter_result
-       = lookup_terrain(secfile_lookup_str(file, "%s.warmer_wetter_result",
-                                           sec[i]), i);
-      t->warmer_drier_result
-       = lookup_terrain(secfile_lookup_str(file, "%s.warmer_drier_result",
-                                           sec[i]), i);
-      t->cooler_wetter_result
-       = lookup_terrain(secfile_lookup_str(file, "%s.cooler_wetter_result",
-                                           sec[i]), i);
-      t->cooler_drier_result
-       = lookup_terrain(secfile_lookup_str(file, "%s.cooler_drier_result",
-                                           sec[i]), i);
-
-      slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec[i]);
-      BV_CLR_ALL(t->flags);
-      for (j = 0; j < nval; j++) {
-       const char *sval = slist[j];
-       enum terrain_flag_id flag = terrain_flag_from_str(sval);
-
-       if (flag == TER_LAST) {
-         /* TRANS: message for an obscure ruleset error. */
-         freelog(LOG_FATAL, _("Terrain %s has unknown flag %s"),
-                 t->terrain_name, sval);
-         exit(EXIT_FAILURE);
-       } else {
-         BV_SET(t->flags, flag);
-       }
-      }
-      free(slist);
+      sz_strlcpy(pterrain->special[j].graphic_str,
+                secfile_lookup_str(file,"%s.graphic_special_%d",
+                                   sec[i], j+1));
+      sz_strlcpy(pterrain->special[j].graphic_alt,
+                secfile_lookup_str(file,"%s.graphic_special_%da",
+                                   sec[i], j+1));
+    }
+
+    pterrain->road_trade_incr
+      = secfile_lookup_int(file, "%s.road_trade_incr", sec[i]);
+    pterrain->road_time = secfile_lookup_int(file, "%s.road_time", sec[i]);
+
+    pterrain->irrigation_result
+      = lookup_terrain(secfile_lookup_str(file, "%s.irrigation_result",
+                                         sec[i]), pterrain);
+    pterrain->irrigation_food_incr
+      = secfile_lookup_int(file, "%s.irrigation_food_incr", sec[i]);
+    pterrain->irrigation_time
+      = secfile_lookup_int(file, "%s.irrigation_time", sec[i]);
+
+    pterrain->mining_result
+      = lookup_terrain(secfile_lookup_str(file, "%s.mining_result",
+                                         sec[i]), pterrain);
+    pterrain->mining_shield_incr
+      = secfile_lookup_int(file, "%s.mining_shield_incr", sec[i]);
+    pterrain->mining_time
+      = secfile_lookup_int(file, "%s.mining_time", sec[i]);
+
+    pterrain->transform_result
+      = lookup_terrain(secfile_lookup_str(file, "%s.transform_result",
+                                           sec[i]), pterrain);
+    pterrain->transform_time
+      = secfile_lookup_int(file, "%s.transform_time", sec[i]);
+    pterrain->rail_time
+      = secfile_lookup_int_default(file, 3, "%s.rail_time", sec[i]);
+    pterrain->airbase_time
+      = secfile_lookup_int_default(file, 3, "%s.airbase_time", sec[i]);
+    pterrain->fortress_time
+      = secfile_lookup_int_default(file, 3, "%s.fortress_time", sec[i]);
+    pterrain->clean_pollution_time
+      = secfile_lookup_int_default(file, 3, "%s.clean_pollution_time", sec[i]);
+    pterrain->clean_fallout_time
+      = secfile_lookup_int_default(file, 3, "%s.clean_fallout_time", sec[i]);
+
+    pterrain->warmer_wetter_result
+      = lookup_terrain(secfile_lookup_str(file, "%s.warmer_wetter_result",
+                                         sec[i]), pterrain);
+    pterrain->warmer_drier_result
+      = lookup_terrain(secfile_lookup_str(file, "%s.warmer_drier_result",
+                                         sec[i]), pterrain);
+    pterrain->cooler_wetter_result
+      = lookup_terrain(secfile_lookup_str(file, "%s.cooler_wetter_result",
+                                         sec[i]), pterrain);
+    pterrain->cooler_drier_result
+      = lookup_terrain(secfile_lookup_str(file, "%s.cooler_drier_result",
+                                         sec[i]), pterrain);
+
+    slist = secfile_lookup_str_vec(file, &nval, "%s.flags", sec[i]);
+    BV_CLR_ALL(pterrain->flags);
+    for (j = 0; j < nval; j++) {
+      const char *sval = slist[j];
+      enum terrain_flag_id flag = terrain_flag_from_str(sval);
 
-      for (j = 0; j < MG_LAST; j++) {
-       const char *mg_names[] = {
-         "mountainous", "green", "foliage",
-         "tropical", "temperate", "cold", "frozen",
-         "wet", "dry", "ocean_depth"
-       };
-       assert(ARRAY_SIZE(mg_names) == MG_LAST);
-
-       t->property[j] = secfile_lookup_int_default(file, 0,
-                                                   "%s.property_%s",
-                                                   sec[i], mg_names[j]);
+      if (flag == TER_LAST) {
+       /* TRANS: message for an obscure ruleset error. */
+       freelog(LOG_FATAL, _("Terrain %s has unknown flag %s"),
+               pterrain->terrain_name, sval);
+       exit(EXIT_FAILURE);
+      } else {
+       BV_SET(pterrain->flags, flag);
       }
-      
-      t->helptext = lookup_helptext(file, sec[i]);
+    }
+    free(slist);
+
+    for (j = 0; j < MG_LAST; j++) {
+      const char *mg_names[] = {
+       "mountainous", "green", "foliage",
+       "tropical", "temperate", "cold", "frozen",
+       "wet", "dry", "ocean_depth"
+      };
+      assert(ARRAY_SIZE(mg_names) == MG_LAST);
+
+      pterrain->property[j] = secfile_lookup_int_default(file, 0,
+                                                        "%s.property_%s",
+                                                        sec[i], mg_names[j]);
+    }
+
+    pterrain->helptext = lookup_helptext(file, sec[i]);
   } terrain_type_iterate_end;
 
   free(sec);
@@ -1979,9 +1986,8 @@ static struct city_name* load_city_name_
          } else {
            /* "handled" tracks whether we find a match (for error handling) */
            bool handled = FALSE;
-           Terrain_type_id type;
-       
-           for (type = T_FIRST; type < T_COUNT && !handled; type++) {
+
+           terrain_type_iterate(pterrain) {
               /*
                * Note that at this time (before a call to
                * translate_data_names) the terrain_name fields contains an
@@ -1989,11 +1995,12 @@ static struct city_name* load_city_name_
                * However this is not a problem because we take care of rivers
                * separately.
                */
-             if (mystrcasecmp(name, terrains[type].terrain_name) == 0) {
-               city_names[j].terrain[type] = setting;
+             if (mystrcasecmp(name, pterrain->terrain_name) == 0) {
+               city_names[j].terrain[pterrain->index] = setting;
                handled = TRUE;
+               break;
              }
-           }
+           } terrain_type_iterate_end;
            if (!handled) {
              freelog(LOG_ERROR, "Unreadable terrain description %s "
                      "in city name ruleset \"%s%s\" - skipping it.",
@@ -2772,61 +2779,68 @@ static void send_ruleset_terrain(struct 
 
   lsend_packet_ruleset_terrain_control(dest, &terrain_control);
 
-  terrain_type_iterate(i) {
-      struct terrain *t = &(terrains[i]);
+  terrain_type_iterate(pterrain) {
+    const int i = pterrain->index;
 
-      packet.id = i;
-
-      sz_strlcpy(packet.terrain_name, t->terrain_name_orig);
-      sz_strlcpy(packet.graphic_str, t->graphic_str);
-      sz_strlcpy(packet.graphic_alt, t->graphic_alt);
+    packet.id = i;
 
-      packet.movement_cost = t->movement_cost;
-      packet.defense_bonus = t->defense_bonus;
+    sz_strlcpy(packet.terrain_name, pterrain->terrain_name_orig);
+    sz_strlcpy(packet.graphic_str, pterrain->graphic_str);
+    sz_strlcpy(packet.graphic_alt, pterrain->graphic_alt);
 
-      output_type_iterate(o) {
-       packet.output[o] = t->output[o];
-       packet.output_special_1[o] = t->special[0].output[o];
-       packet.output_special_2[o] = t->special[1].output[o];
-      } output_type_iterate_end;
+    packet.movement_cost = pterrain->movement_cost;
+    packet.defense_bonus = pterrain->defense_bonus;
 
-      sz_strlcpy(packet.special_1_name, t->special[0].name_orig);
-      sz_strlcpy(packet.special_2_name, t->special[1].name_orig);
+    output_type_iterate(o) {
+      packet.output[o] = pterrain->output[o];
+      packet.output_special_1[o] = pterrain->special[0].output[o];
+      packet.output_special_2[o] = pterrain->special[1].output[o];
+    } output_type_iterate_end;
 
-      sz_strlcpy(packet.graphic_str_special_1, t->special[0].graphic_str);
-      sz_strlcpy(packet.graphic_alt_special_1, t->special[0].graphic_alt);
+    sz_strlcpy(packet.special_1_name, pterrain->special[0].name_orig);
+    sz_strlcpy(packet.special_2_name, pterrain->special[1].name_orig);
 
-      sz_strlcpy(packet.graphic_str_special_2, t->special[1].graphic_str);
-      sz_strlcpy(packet.graphic_alt_special_2, t->special[1].graphic_alt);
+    sz_strlcpy(packet.graphic_str_special_1,
+              pterrain->special[0].graphic_str);
+    sz_strlcpy(packet.graphic_alt_special_1,
+              pterrain->special[0].graphic_alt);
+
+    sz_strlcpy(packet.graphic_str_special_2,
+              pterrain->special[1].graphic_str);
+    sz_strlcpy(packet.graphic_alt_special_2,
+              pterrain->special[1].graphic_alt);
+
+    packet.road_trade_incr = pterrain->road_trade_incr;
+    packet.road_time = pterrain->road_time;
+
+    packet.irrigation_result = (pterrain->irrigation_result
+                               ? pterrain->irrigation_result->index : -1);
+    packet.irrigation_food_incr = pterrain->irrigation_food_incr;
+    packet.irrigation_time = pterrain->irrigation_time;
+
+    packet.mining_result = (pterrain->mining_result
+                           ? pterrain->mining_result->index : -1);
+    packet.mining_shield_incr = pterrain->mining_shield_incr;
+    packet.mining_time = pterrain->mining_time;
+
+    packet.transform_result = (pterrain->transform_result
+                              ? pterrain->transform_result->index : -1);
+    packet.transform_time = pterrain->transform_time;
+    packet.rail_time = pterrain->rail_time;
+    packet.airbase_time = pterrain->airbase_time;
+    packet.fortress_time = pterrain->fortress_time;
+    packet.clean_pollution_time = pterrain->clean_pollution_time;
+    packet.clean_fallout_time = pterrain->clean_fallout_time;
 
-      packet.road_trade_incr = t->road_trade_incr;
-      packet.road_time = t->road_time;
-
-      packet.irrigation_result = t->irrigation_result;
-      packet.irrigation_food_incr = t->irrigation_food_incr;
-      packet.irrigation_time = t->irrigation_time;
-
-      packet.mining_result = t->mining_result;
-      packet.mining_shield_incr = t->mining_shield_incr;
-      packet.mining_time = t->mining_time;
-
-      packet.transform_result = t->transform_result;
-      packet.transform_time = t->transform_time;
-      packet.rail_time = t->rail_time;
-      packet.airbase_time = t->airbase_time;
-      packet.fortress_time = t->fortress_time;
-      packet.clean_pollution_time = t->clean_pollution_time;
-      packet.clean_fallout_time = t->clean_fallout_time;
+    packet.flags = pterrain->flags;
 
-      packet.flags = t->flags;
+    if (pterrain->helptext) {
+      sz_strlcpy(packet.helptext, pterrain->helptext);
+    } else {
+      packet.helptext[0] = '\0';
+    }
 
-      if (t->helptext) {
-       sz_strlcpy(packet.helptext, t->helptext);
-      } else {
-       packet.helptext[0] = '\0';
-      }
-      
-      lsend_packet_ruleset_terrain(dest, &packet);
+    lsend_packet_ruleset_terrain(dest, &packet);
   } terrain_type_iterate_end;
 }
 
Index: server/sanitycheck.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/sanitycheck.c,v
retrieving revision 1.69
diff -p -u -r1.69 sanitycheck.c
--- server/sanitycheck.c        9 Jul 2005 17:46:09 -0000       1.69
+++ server/sanitycheck.c        9 Jul 2005 23:17:34 -0000
@@ -55,7 +55,7 @@
 static void check_specials(void)
 {
   whole_map_iterate(ptile) {
-    Terrain_type_id terrain = tile_get_terrain(ptile);
+    const struct terrain *pterrain = tile_get_terrain(ptile);
     bv_special special = tile_get_special(ptile);
 
     if (contains_special(special, S_RAILROAD))
@@ -65,12 +65,14 @@ static void check_specials(void)
     if (contains_special(special, S_SPECIAL_1))
       SANITY_CHECK(!contains_special(special,  S_SPECIAL_2));
 
-    if (contains_special(special, S_MINE))
-      SANITY_CHECK(get_terrain(terrain)->mining_result == terrain);
-    if (contains_special(special, S_IRRIGATION))
-      SANITY_CHECK(get_terrain(terrain)->irrigation_result == terrain);
+    if (contains_special(special, S_MINE)) {
+      SANITY_CHECK(pterrain->mining_result == pterrain);
+    }
+    if (contains_special(special, S_IRRIGATION)) {
+      SANITY_CHECK(pterrain->irrigation_result == pterrain);
+    }
 
-    SANITY_CHECK(terrain >= T_FIRST && terrain < T_COUNT);
+    SANITY_CHECK(pterrain->index >= T_FIRST && pterrain->index < T_COUNT);
   } whole_map_iterate_end;
 }
 
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.260
diff -p -u -r1.260 savegame.c
--- server/savegame.c   9 Jul 2005 17:46:09 -0000       1.260
+++ server/savegame.c   9 Jul 2005 23:17:35 -0000
@@ -229,14 +229,14 @@ static int ascii_hex2bin(char ch, int ha
   Dereferences the terrain character.  See terrains[].identifier
     example: char2terrain('a') => T_ARCTIC
 ****************************************************************************/
-static Terrain_type_id char2terrain(char ch)
+static struct terrain *char2terrain(char ch)
 {
   if (ch == UNKNOWN_TERRAIN_IDENTIFIER) {
     return T_UNKNOWN;
   }
-  terrain_type_iterate(id) {
-    if (terrains[id].identifier == ch) {
-      return id;
+  terrain_type_iterate(pterrain) {
+    if (pterrain->identifier == ch) {
+      return pterrain;
     }
   } terrain_type_iterate_end;
 
@@ -249,13 +249,12 @@ static Terrain_type_id char2terrain(char
   References the terrain character.  See terrains[].identifier
     example: terrain2char(T_ARCTIC) => 'a'
 ****************************************************************************/
-static char terrain2char(Terrain_type_id terr)
+static char terrain2char(const struct terrain *pterrain)
 {
-  if (terr == T_UNKNOWN) {
+  if (pterrain == T_UNKNOWN) {
     return UNKNOWN_TERRAIN_IDENTIFIER;
   } else {
-    assert(terr >= T_FIRST && terr < T_COUNT);
-    return terrains[terr].identifier;
+    return pterrain->identifier;
   }
 }
 
Index: server/settlers.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v
retrieving revision 1.243
diff -p -u -r1.243 settlers.c
--- server/settlers.c   9 Jul 2005 17:46:09 -0000       1.243
+++ server/settlers.c   9 Jul 2005 23:17:36 -0000
@@ -232,15 +232,12 @@ static int ai_calc_fallout(struct city *
 **************************************************************************/
 static bool is_wet(struct player *pplayer, struct tile *ptile)
 {
-  Terrain_type_id terrain;
-
   /* FIXME: this should check a handicap. */
   if (!pplayer->ai.control && !map_is_known(ptile, pplayer)) {
     return FALSE;
   }
 
-  terrain = tile_get_terrain(ptile);
-  if (is_ocean(terrain)) {
+  if (is_ocean(ptile->terrain)) {
     /* TODO: perhaps salt water should not be usable for irrigation? */
     return TRUE;
   }
@@ -293,10 +290,9 @@ static int ai_calc_irrigate(struct city 
                            int city_x, int city_y, struct tile *ptile)
 {
   int goodness;
-  Terrain_type_id old_terrain = ptile->terrain;
+  struct terrain *old_terrain = ptile->terrain;
   bv_special old_special = ptile->special;
-  struct terrain *type = get_terrain(old_terrain);
-  Terrain_type_id new_terrain = type->irrigation_result;
+  struct terrain *new_terrain = old_terrain->irrigation_result;
 
   if (old_terrain != new_terrain && new_terrain != T_NONE) {
     /* Irrigation would change the terrain type, clearing the mine
@@ -358,10 +354,9 @@ static int ai_calc_mine(struct city *pci
                        int city_x, int city_y, struct tile *ptile)
 {
   int goodness;
-  Terrain_type_id old_terrain = ptile->terrain;
+  struct terrain *old_terrain = ptile->terrain;
   bv_special old_special = ptile->special;
-  struct terrain *type = get_terrain(old_terrain);
-  Terrain_type_id new_terrain = type->mining_result;
+  struct terrain *new_terrain = old_terrain->mining_result;
 
   if (old_terrain != new_terrain && new_terrain != T_NONE) {
     /* Mining would change the terrain type, clearing the irrigation
@@ -410,10 +405,9 @@ static int ai_calc_transform(struct city
                             int city_x, int city_y, struct tile *ptile)
 {
   int goodness;
-  Terrain_type_id old_terrain = ptile->terrain;
+  struct terrain *old_terrain = ptile->terrain;
   bv_special old_special = ptile->special;
-  struct terrain *type = get_terrain(old_terrain);
-  Terrain_type_id new_terrain = type->transform_result;
+  struct terrain *new_terrain = old_terrain->transform_result;
 
   if (old_terrain == new_terrain || new_terrain == T_NONE) {
     return -1;
@@ -436,10 +430,10 @@ static int ai_calc_transform(struct city
 
   ptile->terrain = new_terrain;
 
-  if (get_terrain(new_terrain)->mining_result != new_terrain) {
+  if (new_terrain->mining_result != new_terrain) {
     tile_clear_special(ptile, S_MINE);
   }
-  if (get_terrain(new_terrain)->irrigation_result != new_terrain) {
+  if (new_terrain->irrigation_result != new_terrain) {
     tile_clear_special(ptile, S_FARMLAND);
     tile_clear_special(ptile, S_IRRIGATION);
   }
@@ -476,14 +470,14 @@ static int road_bonus(struct tile *ptile
       has_road[i] = FALSE;
       is_slow[i] = FALSE; /* FIXME: should be TRUE? */
     } else {
-      struct terrain *ptype = get_terrain(tile1->terrain);
+      struct terrain *pterrain = tile1->terrain;
 
       has_road[i] = tile_has_special(tile1, special);
 
       /* If TRUE, this value indicates that this tile does not need
        * a road connector.  This is set for terrains which cannot have
        * road or where road takes "too long" to build. */
-      is_slow[i] = (ptype->road_time == 0 || ptype->road_time > 5);
+      is_slow[i] = (pterrain->road_time == 0 || pterrain->road_time > 5);
 
       if (!has_road[i]) {
        unit_list_iterate(tile1->units, punit) {
@@ -1193,7 +1187,7 @@ void initialize_infrastructure_cache(str
     city_map_checked_iterate(pcity->tile,
                             city_x, city_y, ptile) {
 #ifndef NDEBUG
-      Terrain_type_id old_terrain = ptile->terrain;
+      struct terrain *old_terrain = ptile->terrain;
       bv_special old_special = ptile->special;
 #endif
 
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.369
diff -p -u -r1.369 unittools.c
--- server/unittools.c  9 Jul 2005 17:46:09 -0000       1.369
+++ server/unittools.c  9 Jul 2005 23:17:36 -0000
@@ -774,7 +774,8 @@ static void update_unit_activity(struct 
   if (activity == ACTIVITY_IRRIGATE) {
     if (total_activity (ptile, ACTIVITY_IRRIGATE)
         >= tile_activity_time(ACTIVITY_IRRIGATE, ptile)) {
-      Terrain_type_id old = tile_get_terrain(ptile);
+      struct terrain *old = tile_get_terrain(ptile);
+
       tile_apply_activity(ptile, ACTIVITY_IRRIGATE);
       solvency = check_terrain_ocean_land_change(ptile, old);
       unit_activity_done = TRUE;
@@ -801,7 +802,7 @@ static void update_unit_activity(struct 
   if (activity == ACTIVITY_MINE) {
     if (total_activity (ptile, ACTIVITY_MINE)
         >= tile_activity_time(ACTIVITY_MINE, ptile)) {
-      Terrain_type_id old = tile_get_terrain(ptile);
+      struct terrain *old = tile_get_terrain(ptile);
 
       tile_apply_activity(ptile, ACTIVITY_MINE);
       solvency = check_terrain_ocean_land_change(ptile, old);
@@ -813,7 +814,7 @@ static void update_unit_activity(struct 
   if (activity == ACTIVITY_TRANSFORM) {
     if (total_activity (ptile, ACTIVITY_TRANSFORM)
         >= tile_activity_time(ACTIVITY_TRANSFORM, ptile)) {
-      Terrain_type_id old = tile_get_terrain(ptile);
+      struct terrain *old = tile_get_terrain(ptile);
 
       tile_apply_activity(ptile, ACTIVITY_TRANSFORM);
       solvency = check_terrain_ocean_land_change(ptile, old);
@@ -1205,7 +1206,7 @@ bool enemies_at(struct unit *punit, stru
   }
 
   /* Calculate how well we can defend at (x,y) */
-  db = 10 + get_terrain(tile_get_terrain(ptile))->defense_bonus / 10;
+  db = 10 + tile_get_terrain(ptile)->defense_bonus / 10;
   if (tile_has_special(ptile, S_RIVER))
     db += (db * terrain_control.river_defense_bonus) / 100;
   d = unit_def_rating_basic_sq(punit) * db;
@@ -2611,7 +2612,7 @@ static void wakeup_neighbor_sentries(str
     unit_list_iterate(ptile->units, penemy) {
       int range;
       enum unit_move_type move_type = unit_type(penemy)->move_type;
-      Terrain_type_id terrain = tile_get_terrain(ptile);
+      struct terrain *pterrain = tile_get_terrain(ptile);
 
       if (tile_has_special(ptile, S_FORTRESS)
          && unit_profits_of_watchtower(penemy))
@@ -2624,7 +2625,7 @@ static void wakeup_neighbor_sentries(str
          && range >= real_map_distance(punit->tile, ptile)
          && can_player_see_unit(unit_owner(penemy), punit)
          /* on board transport; don't awaken */
-         && !(move_type == LAND_MOVING && is_ocean(terrain))) {
+         && !(move_type == LAND_MOVING && is_ocean(pterrain))) {
        set_unit_activity(penemy, ACTIVITY_IDLE);
        send_unit_info(NULL, penemy);
       }
Index: server/generator/mapgen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/generator/mapgen.c,v
retrieving revision 1.28
diff -p -u -r1.28 mapgen.c
--- server/generator/mapgen.c   9 Jul 2005 17:46:09 -0000       1.28
+++ server/generator/mapgen.c   9 Jul 2005 23:17:37 -0000
@@ -235,24 +235,26 @@ static bool terrain_is_too_high(struct t
 
   If the avoid property is given, then any terrain with (any of) that
   property will be avoided.
+
+  This function must always return a valid terrain.
 ****************************************************************************/
-static Terrain_type_id pick_terrain(enum mapgen_terrain_property target,
+static struct terrain *pick_terrain(enum mapgen_terrain_property target,
                                    enum mapgen_terrain_property prefer,
                                    enum mapgen_terrain_property avoid)
 {
   int sum = 0;
 
   /* Find the total weight. */
-  terrain_type_iterate(terrain) {
-    if (avoid != MG_LAST && get_terrain(terrain)->property[avoid] > 0) {
+  terrain_type_iterate(pterrain) {
+    if (avoid != MG_LAST && pterrain->property[avoid] > 0) {
       continue;
     }
-    if (prefer != MG_LAST && get_terrain(terrain)->property[prefer] == 0) {
+    if (prefer != MG_LAST && pterrain->property[prefer] == 0) {
       continue;
     }
 
     if (target != MG_LAST) {
-      sum += get_terrain(terrain)->property[target];
+      sum += pterrain->property[target];
     } else {
       sum++;
     }
@@ -262,23 +264,23 @@ static Terrain_type_id pick_terrain(enum
   sum = myrand(sum);
 
   /* Finally figure out which one we picked. */
-  terrain_type_iterate(terrain) {
+  terrain_type_iterate(pterrain) {
     int property;
 
-    if (avoid != MG_LAST && get_terrain(terrain)->property[avoid] > 0) {
+    if (avoid != MG_LAST && pterrain->property[avoid] > 0) {
       continue;
     }
-    if (prefer != MG_LAST && get_terrain(terrain)->property[prefer] == 0) {
+    if (prefer != MG_LAST && pterrain->property[prefer] == 0) {
       continue;
     }
 
     if (target != MG_LAST) {
-      property = get_terrain(terrain)->property[target];
+      property = pterrain->property[target];
     } else {
       property = 1;
     }
     if (sum < property) {
-      return terrain;
+      return pterrain;
     }
     sum -= property;
   } terrain_type_iterate_end;
@@ -296,20 +298,22 @@ static Terrain_type_id pick_terrain(enum
 
 /**************************************************************************
   Picks an ocean terrain to match the given depth (as a percentage).
+
+  FIXME: this should return NULL if there is no available ocean.
 **************************************************************************/
-static Terrain_type_id pick_ocean(int depth)
+static struct terrain *pick_ocean(int depth)
 {
-  Terrain_type_id best_terrain = get_flag_terrain(TER_OCEANIC);
-  int best_match
-    = abs(depth - get_terrain(best_terrain)->property[MG_OCEAN_DEPTH]);
-
-  terrain_type_iterate(t) {
-    if (terrain_has_flag(t, TER_OCEANIC)) {
-      int match = abs(depth - get_terrain(t)->property[MG_OCEAN_DEPTH]);
+  /* FIXME: get_flag_terrain may return NULL if there is no match. */
+  struct terrain *best_terrain = get_flag_terrain(TER_OCEANIC);
+  int best_match = abs(depth - best_terrain->property[MG_OCEAN_DEPTH]);
+
+  terrain_type_iterate(pterrain) {
+    if (terrain_has_flag(pterrain, TER_OCEANIC)) {
+      int match = abs(depth - pterrain->property[MG_OCEAN_DEPTH]);
 
       if (match < best_match) {
        best_match = match;
-       best_terrain = t;
+       best_terrain = pterrain;
       }
     }
   } terrain_type_iterate_end;
@@ -336,12 +340,11 @@ static void make_relief(void)
          (myrand(10) > 5 
           || !terrain_is_too_high(ptile, hmap_mountain_level, hmap(ptile))))
         || terrain_is_too_flat(ptile, hmap_mountain_level, hmap(ptile)))) {
-      Terrain_type_id terrain
-       = pick_terrain(MG_MOUNTAINOUS,
-                      MG_LAST,
+      struct terrain *pterrain
+       = pick_terrain(MG_MOUNTAINOUS, MG_LAST,
                       (tmap_is(ptile, TT_NHOT) ? MG_GREEN : MG_LAST));
 
-      tile_set_terrain(ptile, terrain);
+      tile_set_terrain(ptile, pterrain);
       map_set_placed(ptile);
     }
   } whole_map_iterate_end;
@@ -405,7 +408,7 @@ static void make_polar_land(void)
   Recursively generate terrains.
 **************************************************************************/
 static void place_terrain(struct tile *ptile, int diff, 
-                           Terrain_type_id ter, int *to_be_placed,
+                           struct terrain *pterrain, int *to_be_placed,
                           wetness_c        wc,
                           temperature_type tc,
                           miscellaneous_c  mc)
@@ -414,7 +417,7 @@ static void place_terrain(struct tile *p
     return;
   }
   assert(not_placed(ptile));
-  tile_set_terrain(ptile, ter);
+  tile_set_terrain(ptile, pterrain);
   map_set_placed(ptile);
   (*to_be_placed)--;
   
@@ -427,7 +430,8 @@ static void place_terrain(struct tile *p
        && test_miscellaneous(tile1, mc)
        && Delta < diff 
        && myrand(10) > 4) {
-       place_terrain(tile1, diff - 1 - Delta, ter, to_be_placed, wc, tc, mc);
+       place_terrain(tile1, diff - 1 - Delta, pterrain,
+                     to_be_placed, wc, tc, mc);
     }
   } cardinal_adjc_iterate_end;
 }
@@ -584,7 +588,7 @@ static int river_test_rivergrid(struct t
 *********************************************************************/
 static int river_test_highlands(struct tile *ptile)
 {
-  return get_terrain(ptile->terrain)->property[MG_MOUNTAINOUS];
+  return ptile->terrain->property[MG_MOUNTAINOUS];
 }
 
 /*********************************************************************
@@ -611,7 +615,7 @@ static int river_test_adjacent_highlands
   int sum = 0;
 
   adjc_iterate(ptile, ptile2) {
-    sum += get_terrain(ptile2->terrain)->property[MG_MOUNTAINOUS];
+    sum += ptile2->terrain->property[MG_MOUNTAINOUS];
   } adjc_iterate_end;
 
   return sum;
@@ -622,7 +626,7 @@ static int river_test_adjacent_highlands
 *********************************************************************/
 static int river_test_swamp(struct tile *ptile)
 {
-  return FC_INFINITY - get_terrain(ptile->terrain)->property[MG_WET];
+  return FC_INFINITY - ptile->terrain->property[MG_WET];
 }
 
 /*********************************************************************
@@ -633,7 +637,7 @@ static int river_test_adjacent_swamp(str
   int sum = 0;
 
   adjc_iterate(ptile, ptile2) {
-    sum += get_terrain(ptile2->terrain)->property[MG_WET];
+    sum += ptile2->terrain->property[MG_WET];
   } adjc_iterate_end;
 
   return FC_INFINITY - sum;
@@ -792,7 +796,7 @@ static bool make_river(struct tile *ptil
     /* We arbitrarily make rivers end at the poles. */
     if (count_special_near_tile(ptile, TRUE, TRUE, S_RIVER) > 0
        || count_ocean_near_tile(ptile, TRUE, TRUE) > 0
-        || (get_terrain(ptile->terrain)->property[MG_FROZEN] > 0
+        || (ptile->terrain->property[MG_FROZEN] > 0
            && map_colatitude(ptile) < 0.8 * COLD_LEVEL)) { 
 
       freelog(LOG_DEBUG,
@@ -946,17 +950,17 @@ static void make_rivers(void)
 
        /* Don't start a river on hills unless it is hard to find
           somewhere else to start it. */
-       && (get_terrain(ptile->terrain)->property[MG_MOUNTAINOUS] == 0
+       && (ptile->terrain->property[MG_MOUNTAINOUS] == 0
            || iteration_counter >= RIVERS_MAXTRIES / 10 * 6)
 
        /* Don't start a river on arctic unless it is hard to find
           somewhere else to start it. */
-       && (get_terrain(ptile->terrain)->property[MG_FROZEN] == 0
+       && (ptile->terrain->property[MG_FROZEN] == 0
            || iteration_counter >= RIVERS_MAXTRIES / 10 * 8)
 
        /* Don't start a river on desert unless it is hard to find
           somewhere else to start it. */
-       && (get_terrain(ptile->terrain)->property[MG_DRY] == 0
+       && (ptile->terrain->property[MG_DRY] == 0
            || iteration_counter >= RIVERS_MAXTRIES / 10 * 9)) {
 
       /* Reset river_map before making a new river. */
@@ -971,12 +975,14 @@ static void make_rivers(void)
       if (make_river(ptile)) {
        whole_map_iterate(tile1) {
          if (TEST_BIT(rmap(tile1), RS_RIVER)) {
-           Terrain_type_id t = tile_get_terrain(tile1);
+           struct terrain *pterrain = tile_get_terrain(tile1);
 
-           if (!terrain_has_flag(t, TER_CAN_HAVE_RIVER)) {
+           if (!terrain_has_flag(pterrain, TER_CAN_HAVE_RIVER)) {
              /* We have to change the terrain to put a river here. */
-             t = get_flag_terrain(TER_CAN_HAVE_RIVER);
-             tile_set_terrain(tile1, t);
+             /* FIXME: get_flag_terrain may return NULL
+              * if there is no match. */
+             pterrain = get_flag_terrain(TER_CAN_HAVE_RIVER);
+             tile_set_terrain(tile1, pterrain);
            }
            tile_set_special(tile1, S_RIVER);
            current_riverlength++;
@@ -1046,9 +1052,9 @@ static void make_land(void)
 **************************************************************************/
 static bool is_tiny_island(struct tile *ptile) 
 {
-  Terrain_type_id t = tile_get_terrain(ptile);
+  struct terrain *pterrain = tile_get_terrain(ptile);
 
-  if (is_ocean(t) || get_terrain(t)->property[MG_FROZEN] > 0) {
+  if (is_ocean(pterrain) || pterrain->property[MG_FROZEN] > 0) {
     /* The arctic check is needed for iso-maps: the poles may not have
      * any cardinally adjacent land tiles, but that's okay. */
     return FALSE;
@@ -1087,24 +1093,23 @@ static void print_mapgen_map(void)
   int terrain_count[T_COUNT];
   int total = 0;
 
-  terrain_type_iterate(t) {
-    terrain_count[t] = 0;
+  terrain_type_iterate(pterrain) {
+    terrain_count[pterrain->index] = 0;
   } terrain_type_iterate_end;
 
   whole_map_iterate(ptile) {
-    Terrain_type_id t = tile_get_terrain(ptile);
+    struct terrain *pterrain = tile_get_terrain(ptile);
 
-    assert(t >= 0 && t < T_COUNT);
-    terrain_count[t]++;
-    if (!is_ocean(t)) {
+    terrain_count[pterrain->index]++;
+    if (!is_ocean(pterrain)) {
       total++;
     }
   } whole_map_iterate_end;
 
-  terrain_type_iterate(t) {
+  terrain_type_iterate(pterrain) {
     freelog(loglevel, "%20s : %4d %d%%  ",
-           get_terrain_name(t), terrain_count[t],
-           (terrain_count[t] * 100 + 50) / total);
+           get_terrain_name(pterrain), terrain_count[pterrain->index],
+           (terrain_count[pterrain->index] * 100 + 50) / total);
   } terrain_type_iterate_end;
 }
 
@@ -1321,27 +1326,26 @@ static bool is_special_close(struct tile
 ****************************************************************************/
 static void add_specials(int prob)
 {
-  Terrain_type_id ttype;
-
   whole_map_iterate(ptile)  {
-    ttype = tile_get_terrain(ptile);
-    if (!is_ocean(ttype)
+    const struct terrain *pterrain = tile_get_terrain(ptile);
+
+    if (!is_ocean(pterrain)
        && !is_special_close(ptile) 
        && myrand(1000) < prob) {
-      if (terrains[ttype].special[0].name[0] != '\0'
-         && (terrains[ttype].special[1].name[0] == '\0'
+      if (pterrain->special[0].name[0] != '\0'
+         && (pterrain->special[1].name[0] == '\0'
              || (myrand(100) < 50))) {
        tile_set_special(ptile, S_SPECIAL_1);
-      } else if (terrains[ttype].special[1].name[0] != '\0') {
+      } else if (pterrain->special[1].name[0] != '\0') {
        tile_set_special(ptile, S_SPECIAL_2);
       }
-    } else if (is_ocean(ttype) && near_safe_tiles(ptile) 
+    } else if (is_ocean(pterrain) && near_safe_tiles(ptile) 
               && myrand(1000) < prob && !is_special_close(ptile)) {
-      if (terrains[ttype].special[0].name[0] != '\0'
-         && (terrains[ttype].special[1].name[0] == '\0'
+      if (pterrain->special[0].name[0] != '\0'
+         && (pterrain->special[1].name[0] == '\0'
              || (myrand(100) < 50))) {
         tile_set_special(ptile, S_SPECIAL_1);
-      } else if (terrains[ttype].special[1].name[0] != '\0') {
+      } else if (pterrain->special[1].name[0] != '\0') {
        tile_set_special(ptile, S_SPECIAL_2);
       }
     }
@@ -1384,10 +1388,10 @@ static struct tile *get_random_map_posit
 static void fill_island(int coast, long int *bucket,
                        int warm0_weight, int warm1_weight,
                        int cold0_weight, int cold1_weight,
-                       Terrain_type_id warm0,
-                       Terrain_type_id warm1,
-                       Terrain_type_id cold0,
-                       Terrain_type_id cold1,
+                       struct terrain *warm0,
+                       struct terrain *warm1,
+                       struct terrain *cold0,
+                       struct terrain *cold1,
                        const struct gen234_state *const pstate)
 {
   int i, k, capac;
Index: server/generator/startpos.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/generator/startpos.c,v
retrieving revision 1.14
diff -p -u -r1.14 startpos.c
--- server/generator/startpos.c 7 Jun 2005 06:17:15 -0000       1.14
+++ server/generator/startpos.c 9 Jul 2005 23:17:37 -0000
@@ -41,7 +41,7 @@ static int *islands_index;
 ****************************************************************************/
 static int get_tile_value(struct tile *ptile)
 {
-  Terrain_type_id old_terrain;
+  struct terrain *old_terrain;
   bv_special old_special;
   int value, irrig_bonus, mine_bonus;
 
Index: server/scripting/api.pkg
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/scripting/api.pkg,v
retrieving revision 1.10
diff -p -u -r1.10 api.pkg
--- server/scripting/api.pkg    4 Jul 2005 17:48:38 -0000       1.10
+++ server/scripting/api.pkg    9 Jul 2005 23:17:37 -0000
@@ -59,7 +59,7 @@ struct Tile {
   const int nat_x;
   const int nat_y;
 
-  int terrain @ terrain_id;
+  Terrain *terrain;
 
   const int index @ id;
 };
Index: server/scripting/api_find.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/scripting/api_find.c,v
retrieving revision 1.6
diff -p -u -r1.6 api_find.c
--- server/scripting/api_find.c 9 Jul 2005 17:46:09 -0000       1.6
+++ server/scripting/api_find.c 9 Jul 2005 23:17:37 -0000
@@ -157,7 +157,8 @@ Terrain *api_find_terrain(int terrain_id
 **************************************************************************/
 Terrain *api_find_terrain_by_name(const char *name_orig)
 {
-  Terrain_type_id id =  get_terrain_by_name(name_orig);
-  return api_find_terrain(id);
+  struct terrain *pterrain = get_terrain_by_name(name_orig);
+
+  return pterrain;
 }
 

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#13442) access terrains by pointer, Jason Short <=