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

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

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#13442) access terrains by pointer
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 12 Jul 2005 08:47:01 -0700
Reply-to: bugs@xxxxxxxxxxx

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

Jason Short wrote:

> 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.

Well, as far as I can tell these crashes occur because the current CVS
and 2.0 code is very buggy.

In mapgen, all tiles are initialized to T_UNKNOWN.  Then we do all sorts
of iterations and comparisons of tiles in the placement of terrains and
specials.  At many points we look at T_UNKNOWN tiles.  In the old code
this would result in a buffer underflow and unpredictable behavior
because T_UNKNOWN is -1.  However in the new code it causes a crash
outright because T_UNKNOWN is NULL and this is dereferenced.

I'm going to have to look at this a bit closer to make sure I'm missing
something.  But for the moment I believe this patch corrects the errors
by checking for T_UNKNOWN before dereferencing.  If this is indeed the
problem then S2_0 may need fixing as well.

-jason

? vgcore.pid12865
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      12 Jul 2005 15:43:22 -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        12 Jul 2005 15:43:22 -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 12 Jul 2005 15:43:23 -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    12 Jul 2005 15:43:23 -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       12 Jul 2005 15:43:23 -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   12 Jul 2005 15:43:23 -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   12 Jul 2005 15:43:23 -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   12 Jul 2005 15:43:24 -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   12 Jul 2005 15:43:25 -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   12 Jul 2005 15:43:25 -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        12 Jul 2005 15:43:25 -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   12 Jul 2005 15:43:25 -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       12 Jul 2005 15:43:26 -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     12 Jul 2005 15:43:26 -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       12 Jul 2005 15:43:26 -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        12 Jul 2005 15:43:26 -0000
@@ -540,13 +540,7 @@ int map_distance(const struct tile *tile
 *************************************************************************/
 bool is_cardinally_adj_to_ocean(const struct tile *ptile)
 {
-  cardinal_adjc_iterate(ptile, tile1) {
-    if (is_ocean(tile_get_terrain(tile1))) {
-      return TRUE;
-    }
-  } cardinal_adjc_iterate_end;
-
-  return FALSE;
+  return count_terrain_flag_near_tile(ptile, TRUE, FALSE, TER_OCEANIC) > 0;
 }
 
 /****************************************************************************
@@ -554,14 +548,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) {
-      return TRUE;
-    }
-  } adjc_iterate_end;
-
-  return FALSE;
+  return count_terrain_flag_near_tile(ptile, FALSE, TRUE,
+                                     TER_UNSAFE_COAST) < 100;
 }
 
 /***************************************************************
@@ -569,16 +557,20 @@ bool is_safe_ocean(const struct tile *pt
 ***************************************************************/
 bool is_water_adjacent_to_tile(const struct tile *ptile)
 {
-  if (is_ocean(ptile->terrain)
-      || tile_has_special(ptile, S_RIVER)
-      || tile_has_special(ptile, S_IRRIGATION))
+  if (ptile->terrain != T_UNKNOWN
+      && (is_ocean(ptile->terrain)
+         || tile_has_special(ptile, S_RIVER)
+         || tile_has_special(ptile, S_IRRIGATION))) {
     return TRUE;
+  }
 
   cardinal_adjc_iterate(ptile, tile1) {
-    if (is_ocean(tile1->terrain)
-       || tile_has_special(tile1, S_RIVER)
-       || tile_has_special(tile1, S_IRRIGATION))
+    if (ptile->terrain != T_UNKNOWN
+       && (is_ocean(tile1->terrain)
+           || tile_has_special(tile1, S_RIVER)
+           || tile_has_special(tile1, S_IRRIGATION))) {
       return TRUE;
+    }
   } cardinal_adjc_iterate_end;
 
   return FALSE;
@@ -682,7 +674,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   12 Jul 2005 15:43:26 -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   12 Jul 2005 15:43:26 -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       12 Jul 2005 15:43:27 -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       12 Jul 2005 15:43:27 -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    12 Jul 2005 15:43:27 -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,8 @@ 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 (adjc_tile->terrain != T_UNKNOWN
+       && 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    12 Jul 2005 15:43:27 -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       12 Jul 2005 15:43:27 -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       12 Jul 2005 15:43:27 -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       12 Jul 2005 15:43:27 -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    12 Jul 2005 15:43:27 -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  12 Jul 2005 15:43:27 -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  12 Jul 2005 15:43:28 -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   12 Jul 2005 15:43:29 -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    12 Jul 2005 15:43:29 -0000
@@ -65,7 +65,11 @@ static void assign_continent_flood(struc
   if (tile_get_continent(ptile) != 0) {
     return;
   }
-  
+
+  if (ptile->terrain == T_UNKNOWN) {
+    return;
+  }
+
   if (skip_unsafe && terrain_has_flag(tile_get_terrain(ptile), TER_UNSAFE)) {
     /* FIXME: This should check a specialized flag, not the TER_UNSAFE
      * flag which may not even be present. */
@@ -103,7 +107,7 @@ static void recalculate_lake_surrounders
   
   whole_map_iterate(ptile) {
     Continent_id cont = tile_get_continent(ptile);
-    if (!is_ocean(tile_get_terrain(ptile))) {
+    if (ptile->terrain != T_UNKNOWN && !is_ocean(tile_get_terrain(ptile))) {
       adjc_iterate(ptile, tile2) {
         Continent_id cont2 = tile_get_continent(tile2);
        if (is_ocean(tile_get_terrain(tile2))) {
@@ -150,15 +154,19 @@ 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 (ptile->terrain == T_UNKNOWN) {
+      continue; /* Can't assign this. */
+    }
+
+    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 +217,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 +259,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 +479,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 +489,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 +531,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 +545,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 +553,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 +1523,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    12 Jul 2005 15:43:29 -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    12 Jul 2005 15:43:30 -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        12 Jul 2005 15:43:30 -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.261
diff -p -u -r1.261 savegame.c
--- server/savegame.c   10 Jul 2005 16:03:11 -0000      1.261
+++ server/savegame.c   12 Jul 2005 15:43:30 -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   12 Jul 2005 15:43:31 -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  12 Jul 2005 15:43:31 -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   12 Jul 2005 15:43:32 -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;
@@ -373,8 +376,9 @@ static bool ok_for_separate_poles(struct
     return TRUE;
   }
   adjc_iterate(ptile, tile1) {
-    if (!is_ocean(tile_get_terrain(tile1)) && 
-        tile_get_continent(tile1) != 0) {
+    if (tile1->terrain != T_UNKNOWN
+       && !is_ocean(tile_get_terrain(tile1))
+        && tile_get_continent(tile1) != 0) {
       return FALSE;
     }
   } adjc_iterate_end;
@@ -405,7 +409,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 +418,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 +431,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 +589,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 +616,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 +627,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 +638,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 +797,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 +951,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 +976,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 +1053,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 +1094,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 +1327,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 +1389,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;
@@ -1494,7 +1499,8 @@ static bool is_near_land(struct tile *pt
 {
   /* Note this function may sometimes be called on land tiles. */
   adjc_iterate(ptile, tile1) {
-    if (!is_ocean(tile_get_terrain(tile1))) {
+    if (tile1->terrain != T_UNKNOWN
+       && !is_ocean(tile_get_terrain(tile1))) {
       return TRUE;
     }
   } adjc_iterate_end;
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 12 Jul 2005 15:43:32 -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/generator/utilities.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/generator/utilities.c,v
retrieving revision 1.14
diff -p -u -r1.14 utilities.c
--- server/generator/utilities.c        23 Apr 2005 17:40:29 -0000      1.14
+++ server/generator/utilities.c        12 Jul 2005 15:43:32 -0000
@@ -79,7 +79,7 @@ void map_unset_placed(struct tile *ptile
 void set_all_ocean_tiles_placed(void) 
 {
   whole_map_iterate(ptile) {
-    if (is_ocean(tile_get_terrain(ptile))) {
+    if (ptile->terrain != T_UNKNOWN && is_ocean(tile_get_terrain(ptile))) {
       map_set_placed(ptile);
     }
   } whole_map_iterate_end;
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    12 Jul 2005 15:43:32 -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 12 Jul 2005 15:43:32 -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] Re: (PR#13442) access terrains by pointer, Jason Short <=