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

This patch implements configurable resource conversion modes
for S2_2 and trunk. Builds on the patch in #40365.

Since packet definitions were changed, I don't think this
is usable for S2_1. In any case, to implement it for that
branch without changing packets would probably involve a
number of ugly hacks or deeper redesigns. :(

A server setting 'convertspecials' is added and stored in
game.info.convertspecials (i.e. the game info packet) that
controls how resources change in tile_convert_resource.

Three basic setting values are supported:
0 - Resources disappear when terrain changes (default).
1 - Resources remain when terrain changes.
2 - Resources convert by tier (see #40365).

These can be extended to the proposed scheme discussed
in this forum thread:
http://forum.freeciv.org/viewtopic.php?t=4098

This patch also implements ruleset control over this
setting, adding two parameters to the terrain ruleset
file:
1. supported_resource_conversion_modes
2. resource_conversion_mode

The first parameter is a list of values of the convertspecials
setting that would make sense for this ruleset. This would
be used, for example, if a ruleset had varying numbers of
resources in the 'resources' fields of certain terrains, so
that conversion-by-tier should not be used.

The second parameter is the preferred value of convertspecials
that should be used for this ruleset. For example, the
civ1 and civ2 rulesets could set convert-by-tier to be the
default conversion mode ensuring proper emulation of their
game rules.

If either parameter is left undefined, then the min/max/default
values of the convertspecials setting are enforced.


---------------------------------------------------------------------
君の熱い涙を貪る。
 common/fc_types.h            |    1 +
 common/map.h                 |   10 ++++++++++
 common/packets.def           |    5 +++++
 common/tile.c                |   37 ++++++++++++++++++++++++++-----------
 data/civ1/terrain.ruleset    |   13 +++++++++++++
 data/civ2/terrain.ruleset    |   13 +++++++++++++
 data/default/terrain.ruleset |   13 +++++++++++++
 server/ruleset.c             |   41 +++++++++++++++++++++++++++++++++++++++++
 server/settings.c            |   34 ++++++++++++++++++++++++++++++++++
 version.in                   |    2 +-
 10 files changed, 157 insertions(+), 12 deletions(-)

diff --git a/common/fc_types.h b/common/fc_types.h
index 68807db..57c6933 100644
--- a/common/fc_types.h
+++ b/common/fc_types.h
@@ -39,6 +39,7 @@
 #define MAX_LEN_GAME_IDENTIFIER 33
 #define MAX_GRANARY_INIS 24
 #define MAX_LEN_STARTUNIT (20+1)
+#define MAX_RESCONV_MODES 16
 
 /* symbol to flag missing numbers for better debugging */
 #define IDENTITY_NUMBER_ZERO (0)
diff --git a/common/map.h b/common/map.h
index a8eadbd..e13f6fa 100644
--- a/common/map.h
+++ b/common/map.h
@@ -436,6 +436,11 @@ bool is_cardinal_dir(enum direction8 dir);
 extern const int DIR_DX[8];
 extern const int DIR_DY[8];
 
+/* We don't used MAP_MAX_CONVERTSPECIALS to avoid
+ * circular dependencies and to allow its value to
+ * change without breaking network compatibility. */
+BV_DEFINE(bv_resconv, MAX_RESCONV_MODES);
+
 /* Used for network transmission; do not change. */
 #define MAP_TILE_OWNER_NULL	 MAX_UINT8
 
@@ -473,6 +478,11 @@ extern const int DIR_DY[8];
 #define MAP_MIN_RICHES           0
 #define MAP_MAX_RICHES           1000
 
+/* Must not exceed the range 0 to MAX_RESCONV_MODES - 1. */
+#define MAP_DEFAULT_CONVERTSPECIALS 0
+#define MAP_MIN_CONVERTSPECIALS     0
+#define MAP_MAX_CONVERTSPECIALS     2
+
 #define MAP_DEFAULT_STEEPNESS    30
 #define MAP_MIN_STEEPNESS        0
 #define MAP_MAX_STEEPNESS        100
diff --git a/common/packets.def b/common/packets.def
index 04f1da7..816e8a9 100644
--- a/common/packets.def
+++ b/common/packets.def
@@ -207,6 +207,7 @@ type BV_PLAYER          = bitvector(bv_player)
 type BV_UNIT_CLASSES    = bitvector(bv_unit_classes)
 type DIPLSTATE		= diplstate(struct player_diplstate)
 type VISION		= uint32(unsigned int)
+type BV_RESCONV         = bitvector(bv_resconv)
 
 # typedefs for IDs
 type PLAYER 		= UINT8
@@ -384,6 +385,7 @@ PACKET_GAME_INFO=15; sc
 
   UINT32 globalwarming, heating, warminglevel;
   UINT32 nuclearwinter, cooling, coolinglevel;
+  UINT8 convertspecials;
 
   UINT8 diplcost, freecost, conquercost;
   UINT8 angrycitizen;
@@ -1190,6 +1192,9 @@ PACKET_RULESET_TERRAIN_CONTROL=101;sc,lsend
   UINT16 rail_tile_bonus[O_MAX];        /* % added to output if railroad */
   UINT8 pollution_tile_penalty[O_MAX]; /* % taken from output if polluted */
   UINT8 fallout_tile_penalty[O_MAX]; /* % taken from output if polluted */
+
+  BV_RESCONV resconv_modes; /* Allowed conversion modes. */
+  UINT8 resconv; /* Preferred mode for this ruleset. */
 end
 
 PACKET_RULESET_NATION_GROUPS=118;sc,lsend
diff --git a/common/tile.c b/common/tile.c
index a20db32..542ae0c 100644
--- a/common/tile.c
+++ b/common/tile.c
@@ -20,6 +20,7 @@
 #include "log.h"
 #include "support.h"
 
+#include "game.h"
 #include "tile.h"
 
 #ifndef tile_index
@@ -402,23 +403,37 @@ static void tile_clear_dirtiness(struct tile *ptile)
 ****************************************************************************/
 void tile_convert_resource(struct tile *ptile)
 {
-  const struct terrain *newter;
-  const struct resource *oldres;
-  struct resource *newres;
-
   if (!ptile) {
     return;
   }
 
-  oldres = tile_resource(ptile);
-  if (!oldres) {
-    return;
-  }
+  if (game.info.convertspecials == 0) {
+
+    /* Resource is always lost. */
+    tile_set_resource(ptile, NULL);
+
+  } else if (game.info.convertspecials == 1) {
+
+    /* Resource always remains. */
 
-  newter = tile_terrain(ptile);
-  newres = resource_convert_by_tier(oldres, newter);
+  } else if (game.info.convertspecials == 2) {
+    const struct terrain *newter;
+    const struct resource *oldres;
+    struct resource *newres;
 
-  tile_set_resource(ptile, newres);
+    /* Convert to the resource of the new terrain
+     * having the same tier. */
+
+    oldres = tile_resource(ptile);
+    if (!oldres) {
+      return;
+    }
+
+    newter = tile_terrain(ptile);
+    newres = resource_convert_by_tier(oldres, newter);
+
+    tile_set_resource(ptile, newres);
+  }
 }
 
 /****************************************************************************
diff --git a/data/civ1/terrain.ruleset b/data/civ1/terrain.ruleset
index 00f7bdc..e599ca8 100644
--- a/data/civ1/terrain.ruleset
+++ b/data/civ1/terrain.ruleset
@@ -86,6 +86,19 @@ fallout_shield_penalty=50
 ; percent subtracted from trade production if square has fallout
 fallout_trade_penalty=50
 
+; List of resource conversion modes that are supported by the
+; terrain and resource definitions in this ruleset. See /help
+; convertspecials for the meaning of individual values. Leaving
+; this parameter undefined means to allow all possibly conversion
+; modes.
+;supported_resource_conversion_modes=0, 1, 2
+
+; Default resource conversion mode. This must be one value in
+; the resource_conversion list above. Leaving this parameter
+; undefined means to use the default value of the convertspecials
+; setting.
+resource_conversion_mode=2
+
 ; The individual terrain types, one per section.
 ; Roughly sorted by identifier.
 ; The actual tag used (the * in [terrain_*]) must be unique for each terrain,
diff --git a/data/civ2/terrain.ruleset b/data/civ2/terrain.ruleset
index cc12611..da2ed57 100644
--- a/data/civ2/terrain.ruleset
+++ b/data/civ2/terrain.ruleset
@@ -94,6 +94,19 @@ fallout_shield_penalty=50
 ; percent subtracted from trade production if square has fallout
 fallout_trade_penalty=50
 
+; List of resource conversion modes that are supported by the
+; terrain and resource definitions in this ruleset. See /help
+; convertspecials for the meaning of individual values. Leaving
+; this parameter undefined means to allow all possibly conversion
+; modes.
+;supported_resource_conversion_modes=0, 1, 2
+
+; Default resource conversion mode. This must be one value in
+; the resource_conversion list above. Leaving this parameter
+; undefined means to use the default value of the convertspecials
+; setting.
+resource_conversion_mode=2
+
 ; The individual terrain types, one per section.
 ; Roughly sorted by identifier.
 ; The actual tag used (the * in [terrain_*]) must be unique for each terrain,
diff --git a/data/default/terrain.ruleset b/data/default/terrain.ruleset
index 2b2e39a..56eaefa 100644
--- a/data/default/terrain.ruleset
+++ b/data/default/terrain.ruleset
@@ -94,6 +94,19 @@ fallout_shield_penalty=50
 ; percent subtracted from trade production if square has fallout
 fallout_trade_penalty=50
 
+; List of resource conversion modes that are supported by the
+; terrain and resource definitions in this ruleset. See /help
+; convertspecials for the meaning of individual values. Leaving
+; this parameter undefined means to allow all possibly conversion
+; modes.
+;supported_resource_conversion_modes=0, 1, 2
+
+; Default resource conversion mode. This must be one value in
+; the resource_conversion list above. Leaving this parameter
+; undefined means to use the default value of the convertspecials
+; setting.
+resource_conversion_mode=2
+
 ; The individual terrain types, one per section.
 ; Roughly sorted by identifier.
 ; The actual tag used (the * in [terrain_*]) must be unique for each terrain,
diff --git a/server/ruleset.c b/server/ruleset.c
index 6ee4927..25e3a82 100644
--- a/server/ruleset.c
+++ b/server/ruleset.c
@@ -1659,6 +1659,7 @@ static void load_ruleset_terrain(struct section_file *file)
   int nval;
   int j;
   char **res;
+  int *int_array;
   const char *filename = secfile_filename(file);
   /* char *datafile_options = */ (void)
     check_ruleset_capabilities(file, TERRAIN_CAPABILITY, filename);
@@ -1714,6 +1715,46 @@ static void load_ruleset_terrain(struct section_file *file)
 				   get_output_identifier(o));
   } output_type_iterate_end;
 
+  int_array = secfile_lookup_int_vec(file, &nval,
+      "parameters.supported_resource_conversion_modes");
+  BV_CLR_ALL(terrain_control.resconv_modes);
+  if (int_array) {
+    if (nval > MAX_RESCONV_MODES) {
+      ruleset_error(LOG_FATAL,
+                    "Too many supported_resource_conversion_modes "
+                    "entries (%d, max %d)",
+                    nval, MAX_RESCONV_MODES);
+    }
+    for (j = 0; j < nval; j++) {
+      if (!(MAP_MIN_CONVERTSPECIALS <= int_array[j]
+            && int_array[j] <= MAP_MAX_CONVERTSPECIALS)) {
+        ruleset_error(LOG_FATAL,
+                      "Invalid supported_resource_conversion_modes "
+                      "entry #%d, value %d. See /help convertspecials "
+                      "for allowed values.",
+                      j, int_array[j]);
+      }
+      BV_SET(terrain_control.resconv_modes, int_array[j]);
+    }
+    free(int_array);
+  } else {
+    for (j = 0; j <= MAP_MAX_CONVERTSPECIALS; j++) {
+      BV_SET(terrain_control.resconv_modes, j);
+    }
+  }
+
+  terrain_control.resconv
+    = secfile_lookup_int_default(file, MAP_DEFAULT_CONVERTSPECIALS,
+      "parameters.resource_conversion_mode");
+  if (!BV_ISSET(terrain_control.resconv_modes,
+                terrain_control.resconv)) {
+    ruleset_error(LOG_FATAL,
+                  "Value for resource_conversion_mode (%d) is "
+                  "disallowed by supported_resource_conversion_modes.",
+                  terrain_control.resconv);
+  }
+  game.info.convertspecials = terrain_control.resconv;
+
   /* Reset resource tiers here, since they will be set
    * below when loading terrains' resource lists.
    * See resource_get_tier() for tier explanation. */
diff --git a/server/settings.c b/server/settings.c
index 7b65d4e..657cacf 100644
--- a/server/settings.c
+++ b/server/settings.c
@@ -197,6 +197,19 @@ static bool aifill_callback(int value, const char **error_string)
   return TRUE;
 }
 
+/*************************************************************************
+  Check that the new convertspecials value is allowed by the ruleset.
+*************************************************************************/
+static bool convertspecials_callback(int value, const char **error_string)
+{
+  if (!BV_ISSET(terrain_control.resconv_modes, value)) {
+    *error_string = _("The current ruleset does not allow that kind of "
+                      "special resource conversion.");
+    return FALSE;
+  }
+  *error_string = NULL;
+  return TRUE;
+}
 
 /************************************************************************/
 #if defined(HAVE_LIBBZ2)
@@ -421,6 +434,27 @@ struct settings_s settings[] = {
 	     "thousand."), NULL,
 	  MAP_MIN_RICHES, MAP_MAX_RICHES, MAP_DEFAULT_RICHES)
 
+  GEN_INT("convertspecials", game.info.convertspecials,
+	  SSET_MAP_ADD, SSET_GEOLOGY, SSET_VITAL, SSET_TO_CLIENT,
+	  N_("How \"special\" resources change"), 
+	  N_("This setting controls how special resources change "
+             "when the terrain they are on changes. Not all rulesets "
+             "support all conversion modes; which ones are allowed "
+             "for a given ruleset depend on that ruleset's "
+             "\"supported_resource_conversion_modes\" parameter.\n"
+             "\n"
+             "  0 - Specials are lost when terrain changes.\n"
+             "  1 - Specials remain over all terrain changes.\n"
+             "  2 - Specials remain but are changed to the\n"
+             "      corresponding special of the same \"tier\"\n"
+             "      for the new terrain.\n"
+             "\n"
+             "The \"tier\" of a special resource is the order "
+             "in which it occurs in the 'resources' list in a "
+             "terrain entry in the terrain ruleset."),
+          convertspecials_callback, MAP_MIN_CONVERTSPECIALS,
+          MAP_MAX_CONVERTSPECIALS, MAP_DEFAULT_CONVERTSPECIALS)
+
   GEN_INT("huts", map.huts,
 	  SSET_MAP_ADD, SSET_GEOLOGY, SSET_VITAL, SSET_TO_CLIENT,
 	  N_("Amount of huts (minor tribe villages)"),
diff --git a/version.in b/version.in
index b1b5245..0219680 100644
--- a/version.in
+++ b/version.in
@@ -23,5 +23,5 @@ RELEASE_MONTH=3
 #   - Avoid adding a new mandatory capability to the development branch for
 #     as long as possible.  We want to maintain network compatibility with
 #     the stable branch for as long as possible.
-NETWORK_CAPSTRING_MANDATORY="+Freeciv.Devel.2008.Jul.01"
+NETWORK_CAPSTRING_MANDATORY="+Freeciv.Devel.2008.Jul.08"
 NETWORK_CAPSTRING_OPTIONAL=""
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to