From ca88db640cf40c4144146ac9879c07b691953968 Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Sat, 2 Dec 2023 00:05:28 +0200
Subject: [PATCH 12/12] Add support for second alt terrain gfx tag

See RM #13

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 client/packhand.c                  |  1 +
 client/tilespec.c                  |  7 ++++---
 common/networking/packets.def      |  1 +
 common/terrain.h                   |  5 +++--
 data/alien/terrain.ruleset         | 10 ++++++++++
 data/civ1/terrain.ruleset          | 13 +++++++++++++
 data/civ2/terrain.ruleset          | 13 +++++++++++++
 data/civ2civ3/terrain.ruleset      | 16 ++++++++++++++++
 data/classic/terrain.ruleset       | 16 ++++++++++++++++
 data/goldkeep/terrain.ruleset      | 16 ++++++++++++++++
 data/granularity/terrain.ruleset   |  6 ++++++
 data/multiplayer/terrain.ruleset   | 16 ++++++++++++++++
 data/ruledit/comments-3.3.txt      |  2 ++
 data/sandbox/terrain.ruleset       | 16 ++++++++++++++++
 data/stub/terrain.ruleset          |  4 ++++
 data/webperimental/terrain.ruleset | 16 ++++++++++++++++
 server/ruleset.c                   |  5 ++++-
 tools/ruledit/edit_terrain.cpp     | 21 +++++++++++++++++++++
 tools/ruledit/edit_terrain.h       |  2 ++
 19 files changed, 180 insertions(+), 6 deletions(-)

diff --git a/client/packhand.c b/client/packhand.c
index 8b913bafe0..2f09e1104a 100644
--- a/client/packhand.c
+++ b/client/packhand.c
@@ -4044,6 +4044,7 @@ void handle_ruleset_terrain(const struct packet_ruleset_terrain *p)
   names_set(&pterrain->name, NULL, p->name, p->rule_name);
   sz_strlcpy(pterrain->graphic_str, p->graphic_str);
   sz_strlcpy(pterrain->graphic_alt, p->graphic_alt);
+  sz_strlcpy(pterrain->graphic_alt2, p->graphic_alt2);
   pterrain->movement_cost = p->movement_cost;
   pterrain->defense_bonus = p->defense_bonus;
 
diff --git a/client/tilespec.c b/client/tilespec.c
index c7401459f6..e3143aa0bb 100644
--- a/client/tilespec.c
+++ b/client/tilespec.c
@@ -4172,11 +4172,12 @@ void tileset_setup_tile_type(struct tileset *t,
   int i, l;
 
   if (!drawing_hash_lookup(t->tile_hash, pterrain->graphic_str, &draw)
-      && !drawing_hash_lookup(t->tile_hash, pterrain->graphic_alt, &draw)) {
+      && !drawing_hash_lookup(t->tile_hash, pterrain->graphic_alt, &draw)
+      && !drawing_hash_lookup(t->tile_hash, pterrain->graphic_alt2, &draw)) {
     tileset_error(LOG_FATAL, tileset_name_get(t),
-                  _("Terrain \"%s\": no graphic tile \"%s\" or \"%s\"."),
+                  _("Terrain \"%s\": no graphic tile \"%s\", \"%s\", or \"%s\"."),
                   terrain_rule_name(pterrain), pterrain->graphic_str,
-                  pterrain->graphic_alt);
+                  pterrain->graphic_alt, pterrain->graphic_alt2);
   }
 
   if (draw->init) {
diff --git a/common/networking/packets.def b/common/networking/packets.def
index 3584a5d9b0..542cc0603d 100644
--- a/common/networking/packets.def
+++ b/common/networking/packets.def
@@ -1695,6 +1695,7 @@ PACKET_RULESET_TERRAIN = 151; sc, lsend
   STRING rule_name[MAX_LEN_NAME];
   STRING graphic_str[MAX_LEN_NAME];
   STRING graphic_alt[MAX_LEN_NAME];
+  STRING graphic_alt2[MAX_LEN_NAME];
 
   UINT8 movement_cost; # Whole movement points (not multiplied by SINGLE_MOVE)
   SINT16 defense_bonus;
diff --git a/common/terrain.h b/common/terrain.h
index 978c055945..476a15535f 100644
--- a/common/terrain.h
+++ b/common/terrain.h
@@ -69,7 +69,7 @@ struct resource_type {
 #define MAX_NUM_TERRAINS (96)
 
 /*
- * This struct gives data about each terrain type.  There are many ways
+ * This struct gives data about each terrain type. There are many ways
  * it could be extended.
  */
 struct terrain {
@@ -77,8 +77,9 @@ struct terrain {
   struct name_translation name;
   bool ruledit_disabled; /* Does not really exist - hole in terrain array */
   void *ruledit_dlg;
-  char graphic_str[MAX_LEN_NAME];	/* add tile_ prefix */
+  char graphic_str[MAX_LEN_NAME];
   char graphic_alt[MAX_LEN_NAME];
+  char graphic_alt2[MAX_LEN_NAME];
 
   char identifier; /* Single-character identifier used in games saved. */
   char identifier_load; /* Single-character identifier that was used in the savegame
diff --git a/data/alien/terrain.ruleset b/data/alien/terrain.ruleset
index b84e1817ed..88a15ddbf7 100644
--- a/data/alien/terrain.ruleset
+++ b/data/alien/terrain.ruleset
@@ -100,6 +100,8 @@ ocean_resources = TRUE
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
 ;                        preferred graphic is not found, this will be used.
 ;                        Otherwise may be "-"
+; graphic_alt2         = second alternate graphic, to be used when neither
+;                        main tag nor first alternate tag is not found.
 ; identifier           = single-character identifier used in savegames. This
 ;                        must be unique for each terrain.
 ; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
@@ -218,6 +220,7 @@ ocean_resources = TRUE
 name                 = _("Inaccessible")
 graphic              = "inaccessible"
 graphic_alt          = "arctic"
+graphic_alt2         = "-"
 identifier           = "i"
 class                = "Land"
 movement_cost        = 0
@@ -259,6 +262,7 @@ No unit can enter this terrain, nor can city work the tile.\
 name                 = _("Savannah")
 graphic              = "savannah"
 graphic_alt	     = "grassland"
+graphic_alt2         = "-"
 identifier	     = "g" ; Since this used to be "Grassland"
 class                = "Land"
 movement_cost        = 1
@@ -307,6 +311,7 @@ For some reason, there is Earth like plants and animals around.\
 name                 = _("Alien Forest")
 graphic              = "alien_forest"
 graphic_alt	     = "forest"
+graphic_alt2         = "-"
 identifier	     = "f"
 class                = "Land"
 movement_cost        = 2
@@ -358,6 +363,7 @@ Inventing Alien Rights gives +1 production bonus to Alien Forest tiles.\
 name                 = _("Radiating Rocks")
 graphic              = "radiating_rocks"
 graphic_alt	     = "desert"
+graphic_alt2         = "-"
 identifier	     = "d"
 class                = "Land"
 movement_cost        = 2
@@ -408,6 +414,7 @@ Cities can work these tiles only when Organic Structures is known.\
 name                 = _("Hills")
 graphic              = "hills"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "h"
 class                = "Land"
 movement_cost        = 2
@@ -455,6 +462,7 @@ Hills just like on Earth.\
 name                 = _("Thick Mountains")
 graphic              = "mountains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "m"
 class                = "Land"
 movement_cost        = 3
@@ -503,6 +511,7 @@ but at least Burrowing technology makes mining them possible.\
 name                 = _("Ocean")
 graphic              = "ocean"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = " "
 class                = "Oceanic"
 movement_cost        = 1
@@ -550,6 +559,7 @@ This is normal oceanic terrain.\
 name                 = _("Boiling Ocean")
 graphic              = "boiling_ocean"
 graphic_alt          = "floor"
+graphic_alt2         = "-"
 identifier           = "b"
 class                = "Oceanic"
 movement_cost        = 1
diff --git a/data/civ1/terrain.ruleset b/data/civ1/terrain.ruleset
index 3feb297b83..3d556c6081 100644
--- a/data/civ1/terrain.ruleset
+++ b/data/civ1/terrain.ruleset
@@ -94,6 +94,8 @@ igter_cost = 1
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
 ;                        preferred graphic is not found, this will be used.
 ;                        Otherwise may be "-"
+; graphic_alt2         = second alternate graphic, to be used when neither
+;                        main tag nor first alternate tag is not found.
 ; identifier           = single-character identifier used in savegames. This
 ;                        must be unique for each terrain.
 ; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
@@ -212,6 +214,7 @@ igter_cost = 1
 name                 = _("Ocean")
 graphic              = "coast"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = " "
 class                = "Oceanic"
 movement_cost        = 1
@@ -262,6 +265,7 @@ In cities built on the coast, stored food and work towards the current\
 name                 = _("Arctic")
 graphic              = "arctic"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "a"
 class                = "Land"
 movement_cost        = 2
@@ -310,6 +314,7 @@ Arctic tiles are found only in the most northerly or southerly\
 name                 = _("Desert")
 graphic              = "desert"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "d"
 class                = "Land"
 movement_cost        = 1
@@ -358,6 +363,7 @@ Deserts are regions of extreme dryness, making agriculture and\
 name                 = _("Forest")
 graphic              = "forest"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "f"
 class                = "Land"
 movement_cost        = 2
@@ -408,6 +414,7 @@ Forests are densely wooded, making agriculture somewhat\
 name                 = _("Grassland")
 graphic              = "grassland"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "g"
 class                = "Land"
 movement_cost        = 1
@@ -455,6 +462,7 @@ Grasslands afford exceptional agricultural opportunities.\
 name                 = _("Hills")
 graphic              = "hills"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "h"
 class                = "Land"
 movement_cost        = 2
@@ -507,6 +515,7 @@ A city built in or next to hills is at risk of earthquakes, which can\
 name                 = _("Jungle")
 graphic              = "jungle"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "j"
 class                = "Land"
 movement_cost        = 2
@@ -554,6 +563,7 @@ Jungles are densely overgrown, making agriculture somewhat\
 name                 = _("Mountains")
 graphic              = "mountains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "m"
 class                = "Land"
 movement_cost        = 3
@@ -604,6 +614,7 @@ Cities built in or next to mountains are at risk from volcanic\
 name                 = _("Plains")
 graphic              = "plains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "p"
 class                = "Land"
 movement_cost        = 1
@@ -652,6 +663,7 @@ Plains are very broad, sparse regions, which makes trade slightly\
 name                 = _("Swamp")
 graphic              = "swamp"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "s"
 class                = "Land"
 movement_cost        = 2
@@ -701,6 +713,7 @@ Swamps suffer from an over-abundance of water, making agriculture\
 name                 = _("Tundra")
 graphic              = "tundra"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "t"
 class                = "Land"
 movement_cost        = 1
diff --git a/data/civ2/terrain.ruleset b/data/civ2/terrain.ruleset
index ee2260ed74..4750d743d6 100644
--- a/data/civ2/terrain.ruleset
+++ b/data/civ2/terrain.ruleset
@@ -94,6 +94,8 @@ pythagorean_diagonal = FALSE
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
 ;                        preferred graphic is not found, this will be used.
 ;                        Otherwise may be "-"
+; graphic_alt2         = second alternate graphic, to be used when neither
+;                        main tag nor first alternate tag is not found.
 ; identifier           = single-character identifier used in savegames. This
 ;                        must be unique for each terrain.
 ; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
@@ -212,6 +214,7 @@ pythagorean_diagonal = FALSE
 name                 = _("Ocean")
 graphic              = "coast"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = " "
 class                = "Oceanic"
 movement_cost        = 1
@@ -258,6 +261,7 @@ Oceans cover much of the world.\
 name                 = _("Glacier")
 graphic              = "arctic"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "a"
 class                = "Land"
 movement_cost        = 2
@@ -306,6 +310,7 @@ Glaciers are found only in the most northerly or southerly\
 name                 = _("Desert")
 graphic              = "desert"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "d"
 class                = "Land"
 movement_cost        = 1
@@ -355,6 +360,7 @@ Deserts are regions of extreme dryness, making agriculture and\
 name                 = _("Forest")
 graphic              = "forest"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "f"
 class                = "Land"
 movement_cost        = 2
@@ -405,6 +411,7 @@ Forests are densely wooded, making agriculture somewhat\
 name                 = _("Grassland")
 graphic              = "grassland"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "g"
 class                = "Land"
 movement_cost        = 1
@@ -452,6 +459,7 @@ Grasslands afford exceptional agricultural opportunities.\
 name                 = _("Hills")
 graphic              = "hills"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "h"
 class                = "Land"
 movement_cost        = 2
@@ -500,6 +508,7 @@ In addition to being amenable to agriculture, Hills are frequently\
 name                 = _("Jungle")
 graphic              = "jungle"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "j"
 class                = "Land"
 movement_cost        = 2
@@ -549,6 +558,7 @@ Jungles are densely overgrown, making agriculture somewhat\
 name                 = _("Mountains")
 graphic              = "mountains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "m"
 class                = "Land"
 movement_cost        = 3
@@ -596,6 +606,7 @@ Mountains are regions of extreme altitude, making agriculture and\
 name                 = _("Plains")
 graphic              = "plains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "p"
 class                = "Land"
 movement_cost        = 1
@@ -645,6 +656,7 @@ Plains are very broad, sparse regions, which makes trade slightly\
 name                 = _("Swamp")
 graphic              = "swamp"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "s"
 class                = "Land"
 movement_cost        = 2
@@ -695,6 +707,7 @@ Swamps suffer from an over-abundance of water, making agriculture\
 name                 = _("Tundra")
 graphic              = "tundra"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "t"
 class                = "Land"
 movement_cost        = 1
diff --git a/data/civ2civ3/terrain.ruleset b/data/civ2civ3/terrain.ruleset
index d7fce01ab5..246275617b 100644
--- a/data/civ2civ3/terrain.ruleset
+++ b/data/civ2civ3/terrain.ruleset
@@ -106,6 +106,8 @@ ocean_resources = FALSE
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
 ;                        preferred graphic is not found, this will be used.
 ;                        Otherwise may be "-"
+; graphic_alt2         = second alternate graphic, to be used when neither
+;                        main tag nor first alternate tag is not found.
 ; identifier           = single-character identifier used in savegames. This
 ;                        must be unique for each terrain.
 ; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
@@ -224,6 +226,7 @@ ocean_resources = FALSE
 name                 = _("Inaccessible")
 graphic              = "inaccessible"
 graphic_alt          = "arctic"
+graphic_alt2         = "-"
 identifier           = "i"
 class                = "Land"
 movement_cost        = 0
@@ -265,6 +268,7 @@ No unit can enter this terrain, nor can any city work its tiles.\
 name                 = _("Lake")
 graphic              = "lake"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = "+"
 class                = "Oceanic"
 movement_cost        = 1
@@ -314,6 +318,7 @@ Lakes are substantial bodies of fresh water.\
 name                 = _("Ocean")
 graphic              = "coast"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = " "
 class                = "Oceanic"
 movement_cost        = 1
@@ -364,6 +369,7 @@ Shallow oceans are mostly found near coastlines, and are often rich\
 name                 = _("Deep Ocean")
 graphic              = "floor"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = ":"
 class                = "Oceanic"
 movement_cost        = 1
@@ -414,6 +420,7 @@ Deep oceans cover much of the world away from coastlines, and only\
 name                 = _("Glacier")
 graphic              = "arctic"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "a"
 class                = "Land"
 movement_cost        = 2
@@ -465,6 +472,7 @@ Glaciers are found only in the most northerly or southerly\
 name                 = _("Desert")
 graphic              = "desert"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "d"
 class                = "Land"
 movement_cost        = 1
@@ -525,6 +533,7 @@ Rivers bring fertile soil to deserts; on a desert river not already\
 name                 = _("Forest")
 graphic              = "forest"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "f"
 class                = "Land"
 movement_cost        = 2
@@ -578,6 +587,7 @@ Forests are densely wooded, making agriculture somewhat\
 name                 = _("Grassland")
 graphic              = "grassland"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "g"
 class                = "Land"
 movement_cost        = 1
@@ -628,6 +638,7 @@ Grasslands afford exceptional agricultural opportunities.\
 name                 = _("Hills")
 graphic              = "hills"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "h"
 class                = "Land"
 movement_cost        = 2
@@ -682,6 +693,7 @@ Cities built in hills are at risk of earthquakes, which can interrupt\
 name                 = _("Jungle")
 graphic              = "jungle"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "j"
 class                = "Land"
 movement_cost        = 2
@@ -735,6 +747,7 @@ Jungles are densely overgrown, making agriculture somewhat\
 name                 = _("Mountains")
 graphic              = "mountains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "m"
 class                = "Land"
 movement_cost        = 3
@@ -790,6 +803,7 @@ Land units that move into mountains can see an extra space, but a\
 name                 = _("Plains")
 graphic              = "plains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "p"
 class                = "Land"
 movement_cost        = 1
@@ -841,6 +855,7 @@ Plains are very broad, sparse regions, which makes trade slightly\
 name                 = _("Swamp")
 graphic              = "swamp"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "s"
 class                = "Land"
 movement_cost        = 2
@@ -895,6 +910,7 @@ Swamps suffer from an over-abundance of water, making agriculture\
 name                 = _("Tundra")
 graphic              = "tundra"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "t"
 class                = "Land"
 movement_cost        = 1
diff --git a/data/classic/terrain.ruleset b/data/classic/terrain.ruleset
index 40f362913e..ca9188a5cf 100644
--- a/data/classic/terrain.ruleset
+++ b/data/classic/terrain.ruleset
@@ -99,6 +99,8 @@ ocean_resources = FALSE
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
 ;                        preferred graphic is not found, this will be used.
 ;                        Otherwise may be "-"
+; graphic_alt2         = second alternate graphic, to be used when neither
+;                        main tag nor first alternate tag is not found.
 ; identifier           = single-character identifier used in savegames. This
 ;                        must be unique for each terrain.
 ; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
@@ -217,6 +219,7 @@ ocean_resources = FALSE
 name                 = _("Inaccessible")
 graphic              = "inaccessible"
 graphic_alt          = "arctic"
+graphic_alt2         = "-"
 identifier           = "i"
 class                = "Land"
 movement_cost        = 0
@@ -258,6 +261,7 @@ No unit can enter this terrain, nor can any city work its tiles.\
 name                 = _("Lake")
 graphic              = "lake"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = "+"
 class                = "Oceanic"
 movement_cost        = 1
@@ -307,6 +311,7 @@ Lakes are substantial bodies of fresh water.\
 name                 = _("Ocean")
 graphic              = "coast"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = " "
 class                = "Oceanic"
 movement_cost        = 1
@@ -357,6 +362,7 @@ Shallow oceans are mostly found near coastlines, and are often rich\
 name                 = _("Deep Ocean")
 graphic              = "floor"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = ":"
 class                = "Oceanic"
 movement_cost        = 1
@@ -407,6 +413,7 @@ Deep oceans cover much of the world away from coastlines, and only\
 name                 = _("Glacier")
 graphic              = "arctic"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "a"
 class                = "Land"
 movement_cost        = 2
@@ -460,6 +467,7 @@ Oil wells can be built when Refining is known.\
 name                 = _("Desert")
 graphic              = "desert"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "d"
 class                = "Land"
 movement_cost        = 1
@@ -514,6 +522,7 @@ Oil wells can be built when Construction is known.\
 name                 = _("Forest")
 graphic              = "forest"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "f"
 class                = "Land"
 movement_cost        = 2
@@ -567,6 +576,7 @@ Forests are densely wooded, making agriculture somewhat\
 name                 = _("Grassland")
 graphic              = "grassland"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "g"
 class                = "Land"
 movement_cost        = 1
@@ -617,6 +627,7 @@ Grasslands afford exceptional agricultural opportunities.\
 name                 = _("Hills")
 graphic              = "hills"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "h"
 class                = "Land"
 movement_cost        = 2
@@ -668,6 +679,7 @@ In addition to being amenable to agriculture, Hills are frequently\
 name                 = _("Jungle")
 graphic              = "jungle"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "j"
 class                = "Land"
 movement_cost        = 2
@@ -720,6 +732,7 @@ Jungles are densely overgrown, making agriculture somewhat\
 name                 = _("Mountains")
 graphic              = "mountains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "m"
 class                = "Land"
 movement_cost        = 3
@@ -770,6 +783,7 @@ Mountains are regions of extreme altitude, making agriculture and\
 name                 = _("Plains")
 graphic              = "plains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "p"
 class                = "Land"
 movement_cost        = 1
@@ -821,6 +835,7 @@ Plains are very broad, sparse regions, which makes trade slightly\
 name                 = _("Swamp")
 graphic              = "swamp"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "s"
 class                = "Land"
 movement_cost        = 2
@@ -874,6 +889,7 @@ Swamps suffer from an over-abundance of water, making agriculture\
 name                 = _("Tundra")
 graphic              = "tundra"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "t"
 class                = "Land"
 movement_cost        = 1
diff --git a/data/goldkeep/terrain.ruleset b/data/goldkeep/terrain.ruleset
index 868a6ab0f4..7ddacdf5be 100644
--- a/data/goldkeep/terrain.ruleset
+++ b/data/goldkeep/terrain.ruleset
@@ -101,6 +101,8 @@ ocean_resources = FALSE
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
 ;                        preferred graphic is not found, this will be used.
 ;                        Otherwise may be "-"
+; graphic_alt2         = second alternate graphic, to be used when neither
+;                        main tag nor first alternate tag is not found.
 ; identifier           = single-character identifier used in savegames. This
 ;                        must be unique for each terrain.
 ; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
@@ -219,6 +221,7 @@ ocean_resources = FALSE
 name                 = _("Inaccessible")
 graphic              = "inaccessible"
 graphic_alt          = "arctic"
+graphic_alt2         = "-"
 identifier           = "i"
 class                = "Land"
 movement_cost        = 0
@@ -260,6 +263,7 @@ No unit can enter this terrain, nor can any city work its tiles.\
 name                 = _("Lake")
 graphic              = "lake"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = "+"
 class                = "Oceanic"
 movement_cost        = 1
@@ -307,6 +311,7 @@ Lakes are substantial bodies of fresh water.\
 name                 = _("Ocean")
 graphic              = "coast"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = " "
 class                = "Oceanic"
 movement_cost        = 1
@@ -355,6 +360,7 @@ Shallow oceans are mostly found near coastlines, and are often rich\
 name                 = _("Deep Ocean")
 graphic              = "floor"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = ":"
 class                = "Oceanic"
 movement_cost        = 1
@@ -403,6 +409,7 @@ Deep oceans cover much of the world away from coastlines, and only\
 name                 = _("Glacier")
 graphic              = "arctic"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "a"
 class                = "Land"
 movement_cost        = 2
@@ -454,6 +461,7 @@ Oil wells can be built when Refining is known.\
 name                 = _("Desert")
 graphic              = "desert"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "d"
 class                = "Land"
 movement_cost        = 1
@@ -506,6 +514,7 @@ Oil wells can be built when Construction is known.\
 name                 = _("Forest")
 graphic              = "forest"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "f"
 class                = "Land"
 movement_cost        = 2
@@ -557,6 +566,7 @@ Forests are densely wooded, making agriculture somewhat\
 name                 = _("Grassland")
 graphic              = "grassland"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "g"
 class                = "Land"
 movement_cost        = 1
@@ -605,6 +615,7 @@ Grasslands afford exceptional agricultural opportunities.\
 name                 = _("Hills")
 graphic              = "hills"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "h"
 class                = "Land"
 movement_cost        = 2
@@ -654,6 +665,7 @@ In addition to being amenable to agriculture, Hills are frequently\
 name                 = _("Jungle")
 graphic              = "jungle"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "j"
 class                = "Land"
 movement_cost        = 2
@@ -704,6 +716,7 @@ Jungles are densely overgrown, making agriculture somewhat\
 name                 = _("Mountains")
 graphic              = "mountains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "m"
 class                = "Land"
 movement_cost        = 3
@@ -752,6 +765,7 @@ Mountains are regions of extreme altitude, making agriculture and\
 name                 = _("Plains")
 graphic              = "plains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "p"
 class                = "Land"
 movement_cost        = 1
@@ -801,6 +815,7 @@ Plains are very broad, sparse regions, which makes trade slightly\
 name                 = _("Swamp")
 graphic              = "swamp"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "s"
 class                = "Land"
 movement_cost        = 2
@@ -852,6 +867,7 @@ Swamps suffer from an over-abundance of water, making agriculture\
 name                 = _("Tundra")
 graphic              = "tundra"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "t"
 class                = "Land"
 movement_cost        = 1
diff --git a/data/granularity/terrain.ruleset b/data/granularity/terrain.ruleset
index c270acfba0..7b2c19ef6e 100644
--- a/data/granularity/terrain.ruleset
+++ b/data/granularity/terrain.ruleset
@@ -96,6 +96,8 @@ ocean_resources = FALSE
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
 ;                        preferred graphic is not found, this will be used.
 ;                        Otherwise may be "-"
+; graphic_alt2         = second alternate graphic, to be used when neither
+;                        main tag nor first alternate tag is not found.
 ; identifier           = single-character identifier used in savegames. This
 ;                        must be unique for each terrain.
 ; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
@@ -212,6 +214,7 @@ ocean_resources = FALSE
 name                 = _("Grassland")
 graphic              = "grassland"
 graphic_alt	     = "-"
+graphic_alt2         = "-"
 identifier	     = "g"
 class                = "Land"
 movement_cost        = 5
@@ -260,6 +263,7 @@ Grasslands afford exceptional agricultural opportunities.\
 name                 = _("Forest")
 graphic              = "forest"
 graphic_alt	     = "-"
+graphic_alt2         = "-"
 identifier	     = "f"
 class                = "Land"
 movement_cost        = 15
@@ -309,6 +313,7 @@ Forest provides easily harvested resources.\
 name                 = _("Plains")
 graphic              = "plains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "p"
 class                = "Land"
 movement_cost        = 5
@@ -358,6 +363,7 @@ Plains are very broad, sparse regions, which makes trade slightly\
 name                 = _("Ocean")
 graphic              = "coast"
 graphic_alt	     = "-"
+graphic_alt2         = "-"
 identifier	     = " "
 class                = "Oceanic"
 movement_cost        = 5
diff --git a/data/multiplayer/terrain.ruleset b/data/multiplayer/terrain.ruleset
index 427eb92161..58bf9854cf 100644
--- a/data/multiplayer/terrain.ruleset
+++ b/data/multiplayer/terrain.ruleset
@@ -99,6 +99,8 @@ ocean_resources = FALSE
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
 ;                        preferred graphic is not found, this will be used.
 ;                        Otherwise may be "-"
+; graphic_alt2         = second alternate graphic, to be used when neither
+;                        main tag nor first alternate tag is not found.
 ; identifier           = single-character identifier used in savegames. This
 ;                        must be unique for each terrain.
 ; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
@@ -217,6 +219,7 @@ ocean_resources = FALSE
 name                 = _("Inaccessible")
 graphic              = "inaccessible"
 graphic_alt          = "arctic"
+graphic_alt2         = "-"
 identifier           = "i"
 class                = "Land"
 movement_cost        = 0
@@ -258,6 +261,7 @@ No unit can enter this terrain, nor can any city work its tiles.\
 name                 = _("Lake")
 graphic              = "lake"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = "+"
 class                = "Oceanic"
 movement_cost        = 1
@@ -305,6 +309,7 @@ Lakes are substantial bodies of fresh water.\
 name                 = _("Ocean")
 graphic              = "coast"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = " "
 class                = "Oceanic"
 movement_cost        = 1
@@ -353,6 +358,7 @@ Shallow oceans are mostly found near coastlines, and are often rich\
 name                 = _("Deep Ocean")
 graphic              = "floor"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = ":"
 class                = "Oceanic"
 movement_cost        = 1
@@ -401,6 +407,7 @@ Deep oceans cover much of the world away from coastlines, and only\
 name                 = _("Glacier")
 graphic              = "arctic"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "a"
 class                = "Land"
 movement_cost        = 2
@@ -452,6 +459,7 @@ Oil wells can be built when Refining is known.\
 name                 = _("Desert")
 graphic              = "desert"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "d"
 class                = "Land"
 movement_cost        = 1
@@ -504,6 +512,7 @@ Oil wells can be built when Construction is known.\
 name                 = _("Forest")
 graphic              = "forest"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "f"
 class                = "Land"
 movement_cost        = 2
@@ -555,6 +564,7 @@ Forests are densely wooded, making agriculture somewhat\
 name                 = _("Grassland")
 graphic              = "grassland"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "g"
 class                = "Land"
 movement_cost        = 1
@@ -603,6 +613,7 @@ Grasslands afford exceptional agricultural opportunities.\
 name                 = _("Hills")
 graphic              = "hills"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "h"
 class                = "Land"
 movement_cost        = 2
@@ -652,6 +663,7 @@ In addition to being amenable to agriculture, Hills are frequently\
 name                 = _("Jungle")
 graphic              = "jungle"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "j"
 class                = "Land"
 movement_cost        = 2
@@ -702,6 +714,7 @@ Jungles are densely overgrown, making agriculture somewhat\
 name                 = _("Mountains")
 graphic              = "mountains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "m"
 class                = "Land"
 movement_cost        = 3
@@ -750,6 +763,7 @@ Mountains are regions of extreme altitude, making agriculture and\
 name                 = _("Plains")
 graphic              = "plains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "p"
 class                = "Land"
 movement_cost        = 1
@@ -799,6 +813,7 @@ Plains are very broad, sparse regions, which makes trade slightly\
 name                 = _("Swamp")
 graphic              = "swamp"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "s"
 class                = "Land"
 movement_cost        = 2
@@ -850,6 +865,7 @@ Swamps suffer from an over-abundance of water, making agriculture\
 name                 = _("Tundra")
 graphic              = "tundra"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "t"
 class                = "Land"
 movement_cost        = 1
diff --git a/data/ruledit/comments-3.3.txt b/data/ruledit/comments-3.3.txt
index 07d5e542ac..5ce2a55bf5 100644
--- a/data/ruledit/comments-3.3.txt
+++ b/data/ruledit/comments-3.3.txt
@@ -589,6 +589,8 @@ terrains = "\
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching\n\
 ;                        preferred graphic is not found, this will be used.\n\
 ;                        Otherwise may be \"-\"\n\
+; graphic_alt2         = second alternate graphic, to be used when neither\n\
+;                        main tag nor first alternate tag is not found.\n\
 ; identifier           = single-character identifier used in savegames. This\n\
 ;                        must be unique for each terrain.\n\
 ; class                = Terrain class terrain belongs to: \"Land\" or \"Oceanic\"\n\
diff --git a/data/sandbox/terrain.ruleset b/data/sandbox/terrain.ruleset
index 765ab3e7e9..d826de087a 100644
--- a/data/sandbox/terrain.ruleset
+++ b/data/sandbox/terrain.ruleset
@@ -107,6 +107,8 @@ ocean_resources = FALSE
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
 ;                        preferred graphic is not found, this will be used.
 ;                        Otherwise may be "-"
+; graphic_alt2         = second alternate graphic, to be used when neither
+;                        main tag nor first alternate tag is not found.
 ; identifier           = single-character identifier used in savegames. This
 ;                        must be unique for each terrain.
 ; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
@@ -225,6 +227,7 @@ ocean_resources = FALSE
 name                 = _("Inaccessible")
 graphic              = "inaccessible"
 graphic_alt          = "arctic"
+graphic_alt2         = "-"
 identifier           = "i"
 class                = "Land"
 movement_cost        = 0
@@ -266,6 +269,7 @@ No unit can enter this terrain, nor can any city work its tiles.\
 name                 = _("Lake")
 graphic              = "lake"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = "+"
 class                = "Oceanic"
 movement_cost        = 1
@@ -315,6 +319,7 @@ Lakes are substantial bodies of fresh water.\
 name                 = _("Ocean")
 graphic              = "coast"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = " "
 class                = "Oceanic"
 movement_cost        = 1
@@ -365,6 +370,7 @@ Shallow oceans are mostly found near coastlines, and are often rich\
 name                 = _("Deep Ocean")
 graphic              = "floor"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = ":"
 class                = "Oceanic"
 movement_cost        = 1
@@ -415,6 +421,7 @@ Deep oceans cover much of the world away from coastlines, and only\
 name                 = _("Glacier")
 graphic              = "arctic"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "a"
 class                = "Land"
 movement_cost        = 2
@@ -466,6 +473,7 @@ Glaciers are found only in the most northerly or southerly\
 name                 = _("Desert")
 graphic              = "desert"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "d"
 class                = "Land"
 movement_cost        = 1
@@ -526,6 +534,7 @@ Rivers bring fertile soil to deserts; on a desert river not already\
 name                 = _("Forest")
 graphic              = "forest"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "f"
 class                = "Land"
 movement_cost        = 2
@@ -579,6 +588,7 @@ Forests are densely wooded, making agriculture somewhat\
 name                 = _("Grassland")
 graphic              = "grassland"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "g"
 class                = "Land"
 movement_cost        = 1
@@ -629,6 +639,7 @@ Grasslands afford exceptional agricultural opportunities.\
 name                 = _("Hills")
 graphic              = "hills"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "h"
 class                = "Land"
 movement_cost        = 2
@@ -683,6 +694,7 @@ Cities built in hills are at risk of earthquakes, which can interrupt\
 name                 = _("Jungle")
 graphic              = "jungle"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "j"
 class                = "Land"
 movement_cost        = 2
@@ -736,6 +748,7 @@ Jungles are densely overgrown, making agriculture somewhat\
 name                 = _("Mountains")
 graphic              = "mountains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "m"
 class                = "Land"
 movement_cost        = 3
@@ -791,6 +804,7 @@ Land units that move into mountains can see an extra space, but a\
 name                 = _("Plains")
 graphic              = "plains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "p"
 class                = "Land"
 movement_cost        = 1
@@ -842,6 +856,7 @@ Plains are very broad, sparse regions, which makes trade slightly\
 name                 = _("Swamp")
 graphic              = "swamp"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "s"
 class                = "Land"
 movement_cost        = 2
@@ -896,6 +911,7 @@ Swamps suffer from an over-abundance of water, making agriculture\
 name                 = _("Tundra")
 graphic              = "tundra"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "t"
 class                = "Land"
 movement_cost        = 1
diff --git a/data/stub/terrain.ruleset b/data/stub/terrain.ruleset
index edc54fe5c1..66be563456 100644
--- a/data/stub/terrain.ruleset
+++ b/data/stub/terrain.ruleset
@@ -87,6 +87,8 @@ ocean_resources = FALSE
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
 ;                        preferred graphic is not found, this will be used.
 ;                        Otherwise may be "-"
+; graphic_alt2         = second alternate graphic, to be used when neither
+;                        main tag nor first alternate tag is not found.
 ; identifier           = single-character identifier used in savegames. This
 ;                        must be unique for each terrain.
 ; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
@@ -203,6 +205,7 @@ ocean_resources = FALSE
 name                 = _("Generic")
 graphic              = "generic"
 graphic_alt	     = "grassland"
+graphic_alt2         = "-"
 identifier	     = "g"
 class                = "Land"
 movement_cost        = 1
@@ -251,6 +254,7 @@ This is only possible land terrain.\
 name                 = _("Ocean")
 graphic              = "coast"
 graphic_alt	     = "-"
+graphic_alt2         = "-"
 identifier	     = " "
 class                = "Oceanic"
 movement_cost        = 1
diff --git a/data/webperimental/terrain.ruleset b/data/webperimental/terrain.ruleset
index 79a0cf92e0..de9bf68899 100644
--- a/data/webperimental/terrain.ruleset
+++ b/data/webperimental/terrain.ruleset
@@ -99,6 +99,8 @@ ocean_resources = FALSE
 ; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
 ;                        preferred graphic is not found, this will be used.
 ;                        Otherwise may be "-"
+; graphic_alt2         = second alternate graphic, to be used when neither
+;                        main tag nor first alternate tag is not found.
 ; identifier           = single-character identifier used in savegames. This
 ;                        must be unique for each terrain.
 ; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
@@ -217,6 +219,7 @@ ocean_resources = FALSE
 name                 = _("Inaccessible")
 graphic              = "inaccessible"
 graphic_alt          = "arctic"
+graphic_alt2         = "-"
 identifier           = "i"
 class                = "Land"
 movement_cost        = 0
@@ -258,6 +261,7 @@ No unit can enter this terrain, nor can any city work its tiles.\
 name                 = _("Lake")
 graphic              = "lake"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = "+"
 class                = "Oceanic"
 movement_cost        = 1
@@ -307,6 +311,7 @@ Lakes are substantial bodies of fresh water.\
 name                 = _("Ocean")
 graphic              = "coast"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = " "
 class                = "Oceanic"
 movement_cost        = 1
@@ -357,6 +362,7 @@ Shallow oceans are mostly found near coastlines, and are often rich\
 name                 = _("Deep Ocean")
 graphic              = "floor"
 graphic_alt          = "coast"
+graphic_alt2         = "-"
 identifier           = ":"
 class                = "Oceanic"
 movement_cost        = 1
@@ -407,6 +413,7 @@ Deep oceans cover much of the world away from coastlines, and only\
 name                 = _("Glacier")
 graphic              = "arctic"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "a"
 class                = "Land"
 movement_cost        = 2
@@ -460,6 +467,7 @@ Oil wells can be built when Refining is known.\
 name                 = _("Desert")
 graphic              = "desert"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "d"
 class                = "Land"
 movement_cost        = 1
@@ -514,6 +522,7 @@ Oil wells can be built when Construction is known.\
 name                 = _("Forest")
 graphic              = "forest"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "f"
 class                = "Land"
 movement_cost        = 2
@@ -567,6 +576,7 @@ Forests are densely wooded, making agriculture somewhat\
 name                 = _("Grassland")
 graphic              = "grassland"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "g"
 class                = "Land"
 movement_cost        = 1
@@ -617,6 +627,7 @@ Grasslands afford exceptional agricultural opportunities.\
 name                 = _("Hills")
 graphic              = "hills"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "h"
 class                = "Land"
 movement_cost        = 2
@@ -668,6 +679,7 @@ In addition to being amenable to agriculture, Hills are frequently\
 name                 = _("Jungle")
 graphic              = "jungle"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "j"
 class                = "Land"
 movement_cost        = 2
@@ -720,6 +732,7 @@ Jungles are densely overgrown, making agriculture somewhat\
 name                 = _("Mountains")
 graphic              = "mountains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "m"
 class                = "Land"
 movement_cost        = 3
@@ -770,6 +783,7 @@ Mountains are regions of extreme altitude, making agriculture and\
 name                 = _("Plains")
 graphic              = "plains"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "p"
 class                = "Land"
 movement_cost        = 1
@@ -821,6 +835,7 @@ Plains are very broad, sparse regions, which makes trade slightly\
 name                 = _("Swamp")
 graphic              = "swamp"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "s"
 class                = "Land"
 movement_cost        = 2
@@ -874,6 +889,7 @@ Swamps suffer from an over-abundance of water, making agriculture\
 name                 = _("Tundra")
 graphic              = "tundra"
 graphic_alt          = "-"
+graphic_alt2         = "-"
 identifier           = "t"
 class                = "Land"
 movement_cost        = 1
diff --git a/server/ruleset.c b/server/ruleset.c
index 85e0f56819..317ebae44d 100644
--- a/server/ruleset.c
+++ b/server/ruleset.c
@@ -3161,7 +3161,7 @@ static bool load_ruleset_terrain(struct section_file *file,
   sz_strlcpy(terrain_control.gui_type_base1, text);
 
   if (ok) {
-    /* terrain details */
+    /* Terrain details */
 
     terrain_type_iterate(pterrain) {
       const char **slist;
@@ -3174,6 +3174,8 @@ static bool load_ruleset_terrain(struct section_file *file,
                  secfile_lookup_str(file, "%s.graphic", tsection));
       sz_strlcpy(pterrain->graphic_alt,
                  secfile_lookup_str(file, "%s.graphic_alt", tsection));
+      sz_strlcpy(pterrain->graphic_alt2,
+                 secfile_lookup_str(file, "%s.graphic_alt2", tsection));
 
       pterrain->identifier
         = secfile_lookup_str(file, "%s.identifier", tsection)[0];
@@ -8306,6 +8308,7 @@ static void send_ruleset_terrain(struct conn_list *dest)
     sz_strlcpy(packet.rule_name, rule_name_get(&pterrain->name));
     sz_strlcpy(packet.graphic_str, pterrain->graphic_str);
     sz_strlcpy(packet.graphic_alt, pterrain->graphic_alt);
+    sz_strlcpy(packet.graphic_alt2, pterrain->graphic_alt2);
 
     packet.movement_cost = pterrain->movement_cost;
     packet.defense_bonus = pterrain->defense_bonus;
diff --git a/tools/ruledit/edit_terrain.cpp b/tools/ruledit/edit_terrain.cpp
index 8a275e4bb0..67cc1abbdf 100644
--- a/tools/ruledit/edit_terrain.cpp
+++ b/tools/ruledit/edit_terrain.cpp
@@ -84,6 +84,15 @@ edit_terrain::edit_terrain(ruledit_gui *ui_in, struct terrain *ter_in) : QDialog
   ter_layout->addWidget(label, row, 0);
   ter_layout->addWidget(gfx_tag_alt, row++, 1);
 
+  label = new QLabel(QString::fromUtf8(R__("Second alt graphics tag")));
+  label->setParent(this);
+
+  gfx_tag_alt2 = new QLineEdit(this);
+  connect(gfx_tag_alt2, SIGNAL(returnPressed()), this, SLOT(gfx_tag_alt2_given()));
+
+  ter_layout->addWidget(label, row, 0);
+  ter_layout->addWidget(gfx_tag_alt2, row++, 1);
+
   refresh();
 
   main_layout->addLayout(ter_layout);
@@ -99,6 +108,7 @@ void edit_terrain::closeEvent(QCloseEvent *cevent)
   // Save values from text fields.
   gfx_tag_given();
   gfx_tag_alt_given();
+  gfx_tag_alt2_given();
 
   ter->ruledit_dlg = nullptr;
 }
@@ -112,6 +122,7 @@ void edit_terrain::refresh()
   defense->setValue(ter->defense_bonus);
   gfx_tag->setText(ter->graphic_str);
   gfx_tag_alt->setText(ter->graphic_alt);
+  gfx_tag_alt2->setText(ter->graphic_alt2);
 }
 
 /**********************************************************************//**
@@ -153,3 +164,13 @@ void edit_terrain::gfx_tag_alt_given()
 
   sz_strlcpy(ter->graphic_alt, tag_bytes);
 }
+
+/**********************************************************************//**
+  User entered new second alternative graphics tag.
+**************************************************************************/
+void edit_terrain::gfx_tag_alt2_given()
+{
+  QByteArray tag_bytes = gfx_tag_alt2->text().toUtf8();
+
+  sz_strlcpy(ter->graphic_alt2, tag_bytes);
+}
diff --git a/tools/ruledit/edit_terrain.h b/tools/ruledit/edit_terrain.h
index 0093da3169..5b79ddcd4b 100644
--- a/tools/ruledit/edit_terrain.h
+++ b/tools/ruledit/edit_terrain.h
@@ -41,6 +41,7 @@ class edit_terrain : public QDialog
     QSpinBox *defense;
     QLineEdit *gfx_tag;
     QLineEdit *gfx_tag_alt;
+    QLineEdit *gfx_tag_alt2;
 
   protected:
     void closeEvent(QCloseEvent *cevent);
@@ -50,6 +51,7 @@ class edit_terrain : public QDialog
     void set_defense_value(int value);
     void gfx_tag_given();
     void gfx_tag_alt_given();
+    void gfx_tag_alt2_given();
 };
 
 #endif // FC__EDIT_TERRAIN_H
-- 
2.42.0

