From b0883da090d67e0e054446907545c0f1f7972a27 Mon Sep 17 00:00:00 2001 From: Alina Lenk Date: Sat, 11 May 2024 13:37:49 +0200 Subject: [PATCH 3/3] Unhardcode terrain-class-specific border claiming rules See RM #588 Signed-off-by: Alina Lenk --- ai/default/daieffects.c | 2 + common/fc_types.h | 20 +++++ common/tech.h | 23 ++--- data/alien/effects.ruleset | 47 ++++++++++ data/alien/techs.ruleset | 6 +- data/civ1/effects.ruleset | 20 +++++ data/civ1/techs.ruleset | 4 - data/civ2/effects.ruleset | 20 +++++ data/civ2/techs.ruleset | 4 - data/civ2civ3/effects.ruleset | 20 +++++ data/civ2civ3/techs.ruleset | 4 - data/classic/effects.ruleset | 20 +++++ data/classic/techs.ruleset | 4 - data/goldkeep/effects.ruleset | 20 +++++ data/goldkeep/techs.ruleset | 4 - data/granularity/effects.ruleset | 27 ++++++ data/granularity/techs.ruleset | 4 - data/multiplayer/effects.ruleset | 20 +++++ data/multiplayer/techs.ruleset | 4 - data/ruledit/comments-3.3.txt | 4 - data/sandbox/effects.ruleset | 20 +++++ data/sandbox/techs.ruleset | 4 - data/stub/effects.ruleset | 27 ++++++ data/stub/techs.ruleset | 4 - data/webperimental/effects.ruleset | 20 +++++ data/webperimental/techs.ruleset | 4 - doc/README.effects | 19 ++++ gen_headers/enums/effects_enums.def | 2 + server/generator/mapgen_utils.c | 75 +++++++++++----- server/generator/mapgen_utils.h | 3 +- server/maphand.c | 118 +++++++++++++++--------- server/ruleset/rscompat.c | 133 ++++++++++++++++++++++++++++ 32 files changed, 581 insertions(+), 125 deletions(-) diff --git a/ai/default/daieffects.c b/ai/default/daieffects.c index a307ba9a8a..28b0ffe3eb 100644 --- a/ai/default/daieffects.c +++ b/ai/default/daieffects.c @@ -612,6 +612,8 @@ adv_want dai_effect_value(struct player *pplayer, case EFT_UNIT_SHIELD_VALUE_PCT: case EFT_NUKE_BLAST_RADIUS_1_SQ: case EFT_HEAL_UNIT_PCT: + case EFT_TILE_CLAIMABLE_FROM_SAME: + case EFT_TILE_CLAIMABLE_FROM_OTHER: break; /* This has no effect for AI */ case EFT_VISIBLE_WALLS: diff --git a/common/fc_types.h b/common/fc_types.h index 55ab057015..11ae0b3c52 100644 --- a/common/fc_types.h +++ b/common/fc_types.h @@ -487,6 +487,26 @@ typedef int Unit_Class_id; * compatibility code to server/rscompat.c. */ #define CASUS_BELLI_OUTRAGE 1000 +/* A border source can claim adjacent tiles if EFT_TILE_CLAIMABLE_* is + * equal to or above TILE_CLAIMABLE_ADJACENT. To change this value you must + * update the documentation of each Tile_Claimable_* effect in + * doc/README.effects, update existing rulesets and add ruleset + * compatibility code to server/rscompat.c. */ +#define TILE_CLAIMABLE_ADJACENT 1 +/* A border source can claim tiles on or surrounded by the same continent + * or body of water if EFT_TILE_CLAIMABLE_* is equal to or above + * TILE_CLAIMABLE_CONTINENT. To change this value you must update the + * documentation of each Tile_Claimable_* effect in + * doc/README.effects, update existing rulesets and add ruleset + * compatibility code to server/rscompat.c. */ +#define TILE_CLAIMABLE_CONTINENT 100 +/* A border source can claim any tiles if EFT_TILE_CLAIMABLE_* is equal to + * or above TILE_CLAIMABLE_ALWAYS. To change this value you must update the + * documentation of each Tile_Claimable_* effect in + * doc/README.effects, update existing rulesets and add ruleset + * compatibility code to server/rscompat.c. */ +#define TILE_CLAIMABLE_ALWAYS 10000 + /* Really in ai.c */ const char *ai_level_name_update_cb(const char *old); diff --git a/common/tech.h b/common/tech.h index ff4c70ec42..f5fbd5303b 100644 --- a/common/tech.h +++ b/common/tech.h @@ -84,20 +84,15 @@ typedef int Tech_type_id; /* Player can build air units */ #define SPECENUM_VALUE2 TF_BUILD_AIRBORNE #define SPECENUM_VALUE2NAME N_("Build_Airborne") -/* Player can claim ocean tiles non-adjacent to border source */ -#define SPECENUM_VALUE3 TF_CLAIM_OCEAN -#define SPECENUM_VALUE3NAME N_("Claim_Ocean") -/* Player can claim ocean tiles non-adjacent to border source as long - * as source is ocean tile */ -#define SPECENUM_VALUE4 TF_CLAIM_OCEAN_LIMITED -#define SPECENUM_VALUE4NAME N_("Claim_Ocean_Limited") -#define SPECENUM_VALUE5 TECH_USER_1 -#define SPECENUM_VALUE6 TECH_USER_2 -#define SPECENUM_VALUE7 TECH_USER_3 -#define SPECENUM_VALUE8 TECH_USER_4 -#define SPECENUM_VALUE9 TECH_USER_5 -#define SPECENUM_VALUE10 TECH_USER_6 -#define SPECENUM_VALUE11 TECH_USER_7 +#define SPECENUM_VALUE3 TECH_USER_1 +#define SPECENUM_VALUE4 TECH_USER_2 +#define SPECENUM_VALUE5 TECH_USER_3 +#define SPECENUM_VALUE6 TECH_USER_4 +#define SPECENUM_VALUE7 TECH_USER_5 +#define SPECENUM_VALUE8 TECH_USER_6 +#define SPECENUM_VALUE9 TECH_USER_7 +#define SPECENUM_VALUE10 TECH_USER_8 +#define SPECENUM_VALUE11 TECH_USER_9 #define SPECENUM_VALUE12 TECH_USER_LAST /* Keep this last. */ #define SPECENUM_COUNT TF_COUNT diff --git a/data/alien/effects.ruleset b/data/alien/effects.ruleset index 4fe6c48395..fb969a3f3b 100644 --- a/data/alien/effects.ruleset +++ b/data/alien/effects.ruleset @@ -1165,3 +1165,50 @@ reqs = { "type", "name", "range", "present" "Action", "Upgrade Unit", "Local", TRUE } + +; claim land from land on the same continent +[effect_claim_land] +type = "Tile_Claimable_From_Same" +value = 100 +reqs = + { "type", "name", "range" + "TerrainClass", "Land", "Tile" + } + +; claim ocean from adjacent ocean +[effect_claim_ocean_base_same] +type = "Tile_Claimable_From_Same" +value = 1 +reqs = + { "type", "name", "range" + "TerrainClass", "Oceanic", "Tile" + } + +; claim ocean from surrounding land +[effect_claim_ocean_base_other] +type = "Tile_Claimable_From_Other" +value = 100 +reqs = + { "type", "name", "range" + "TerrainClass", "Oceanic", "Tile" + } + +; claim ocean from any ocean with Ocean Cities +[effect_claim_ocean_full_same] +type = "Tile_Claimable_From_Same" +value = 10000 +reqs = + { "type", "name", "range" + "TerrainClass", "Oceanic", "Tile" + "Tech", "Ocean Cities", "Player" + } + +; claim ocean from any land with Ocean Cities +[effect_claim_ocean_full_other] +type = "Tile_Claimable_From_Other" +value = 10000 +reqs = + { "type", "name", "range" + "TerrainClass", "Oceanic", "Tile" + "Tech", "Ocean Cities", "Player" + } diff --git a/data/alien/techs.ruleset b/data/alien/techs.ruleset index 0acf003468..a9a694d415 100644 --- a/data/alien/techs.ruleset +++ b/data/alien/techs.ruleset @@ -111,10 +111,6 @@ format_version = 40 ; extra. See "bridged_over" extra property in ; terrain.ruleset. ; "Build_Airborne" = from now on can build air units (for use by AI) -; "Claim_Ocean" = Player claims ocean tiles even if they are not -; adjacent to border source -; "Claim_Ocean_Limited" = Oceanic border sources claim ocean tiles even if -; they are not adjacent to border source ; ; */ <-- avoid gettext warnings @@ -530,7 +526,7 @@ Increases max tax/science/lux rate by 10%.") name = _("Ocean Cities") req1 = "Deneb Radar" req2 = "Thermal Module" -flags = "Claim_Ocean" +flags = "" graphic = "a.ocean_cities" graphic_alt = "-" helptext = _("Cities on ocean. Why not?") diff --git a/data/civ1/effects.ruleset b/data/civ1/effects.ruleset index 96d7783f7b..40284b31e4 100644 --- a/data/civ1/effects.ruleset +++ b/data/civ1/effects.ruleset @@ -1595,3 +1595,23 @@ reqs = { "type", "name", "range", "present" "Action", "Disband Unit Recover", "Local", TRUE } + +; claim land from land on the same continent +[effect_claim_land] +type = "Tile_Claimable_From_Same" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Land", "Tile" +; } + +; claim ocean from surrounding land +[effect_claim_ocean] +type = "Tile_Claimable_From_Other" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Oceanic", "Tile" +; } diff --git a/data/civ1/techs.ruleset b/data/civ1/techs.ruleset index 1a60432b87..63fc9f03c2 100644 --- a/data/civ1/techs.ruleset +++ b/data/civ1/techs.ruleset @@ -107,10 +107,6 @@ format_version = 40 ; extra. See "bridged_over" extra property in ; terrain.ruleset. ; "Build_Airborne" = from now on can build air units (for use by AI) -; "Claim_Ocean" = Player claims ocean tiles even if they are not -; adjacent to border source -; "Claim_Ocean_Limited" = Oceanic border sources claim ocean tiles even if -; they are not adjacent to border source ; ; */ <-- avoid gettext warnings diff --git a/data/civ2/effects.ruleset b/data/civ2/effects.ruleset index b8e476ed4c..136bad6d54 100644 --- a/data/civ2/effects.ruleset +++ b/data/civ2/effects.ruleset @@ -2678,3 +2678,23 @@ reqs = { "type", "name", "range", "present" "Action", "Upgrade Unit", "Local", TRUE } + +; claim land from land on the same continent +[effect_claim_land] +type = "Tile_Claimable_From_Same" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Land", "Tile" +; } + +; claim ocean from surrounding land +[effect_claim_ocean] +type = "Tile_Claimable_From_Other" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Oceanic", "Tile" +; } diff --git a/data/civ2/techs.ruleset b/data/civ2/techs.ruleset index 0a107a40e8..7fe80de956 100644 --- a/data/civ2/techs.ruleset +++ b/data/civ2/techs.ruleset @@ -107,10 +107,6 @@ format_version = 40 ; extra. See "bridged_over" extra property in ; terrain.ruleset. ; "Build_Airborne" = from now on can build air units (for use by AI) -; "Claim_Ocean" = Player claims ocean tiles even if they are not -; adjacent to border source -; "Claim_Ocean_Limited" = Oceanic border sources claim ocean tiles even if -; they are not adjacent to border source ; ; */ <-- avoid gettext warnings diff --git a/data/civ2civ3/effects.ruleset b/data/civ2civ3/effects.ruleset index 784dd942b4..c6768b3e0b 100644 --- a/data/civ2civ3/effects.ruleset +++ b/data/civ2civ3/effects.ruleset @@ -4617,3 +4617,23 @@ reqs = { "type", "name", "range", "present" "Action", "Upgrade Unit", "Local", TRUE } + +; claim land from land on the same continent +[effect_claim_land] +type = "Tile_Claimable_From_Same" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Land", "Tile" +; } + +; claim ocean from surrounding land +[effect_claim_ocean] +type = "Tile_Claimable_From_Other" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Oceanic", "Tile" +; } diff --git a/data/civ2civ3/techs.ruleset b/data/civ2civ3/techs.ruleset index 935e5642a8..9ead2fc48e 100644 --- a/data/civ2civ3/techs.ruleset +++ b/data/civ2civ3/techs.ruleset @@ -107,10 +107,6 @@ format_version = 40 ; extra. See "bridged_over" extra property in ; terrain.ruleset. ; "Build_Airborne" = from now on can build air units (for use by AI) -; "Claim_Ocean" = Player claims ocean tiles even if they are not -; adjacent to border source -; "Claim_Ocean_Limited" = Oceanic border sources claim ocean tiles even if -; they are not adjacent to border source ; ; */ <-- avoid gettext warnings diff --git a/data/classic/effects.ruleset b/data/classic/effects.ruleset index cae07651a5..af7256f65b 100644 --- a/data/classic/effects.ruleset +++ b/data/classic/effects.ruleset @@ -2733,3 +2733,23 @@ reqs = { "type", "name", "range", "present" "Action", "Upgrade Unit", "Local", TRUE } + +; claim land from land on the same continent +[effect_claim_land] +type = "Tile_Claimable_From_Same" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Land", "Tile" +; } + +; claim ocean from surrounding land +[effect_claim_ocean] +type = "Tile_Claimable_From_Other" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Oceanic", "Tile" +; } diff --git a/data/classic/techs.ruleset b/data/classic/techs.ruleset index 130a58e55d..bee8fd31d5 100644 --- a/data/classic/techs.ruleset +++ b/data/classic/techs.ruleset @@ -107,10 +107,6 @@ format_version = 40 ; extra. See "bridged_over" extra property in ; terrain.ruleset. ; "Build_Airborne" = from now on can build air units (for use by AI) -; "Claim_Ocean" = Player claims ocean tiles even if they are not -; adjacent to border source -; "Claim_Ocean_Limited" = Oceanic border sources claim ocean tiles even if -; they are not adjacent to border source ; ; */ <-- avoid gettext warnings diff --git a/data/goldkeep/effects.ruleset b/data/goldkeep/effects.ruleset index 0fc2993f76..b08f0c7b7c 100644 --- a/data/goldkeep/effects.ruleset +++ b/data/goldkeep/effects.ruleset @@ -3074,3 +3074,23 @@ reqs = { "type", "name", "range", "present" "Action", "Upgrade Unit", "Local", TRUE } + +; claim land from land on the same continent +[effect_claim_land] +type = "Tile_Claimable_From_Same" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Land", "Tile" +; } + +; claim ocean from surrounding land +[effect_claim_ocean] +type = "Tile_Claimable_From_Other" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Oceanic", "Tile" +; } diff --git a/data/goldkeep/techs.ruleset b/data/goldkeep/techs.ruleset index 8b27939e54..e0a90e40ee 100644 --- a/data/goldkeep/techs.ruleset +++ b/data/goldkeep/techs.ruleset @@ -109,10 +109,6 @@ format_version = 40 ; extra. See "bridged_over" extra property in ; terrain.ruleset. ; "Build_Airborne" = from now on can build air units (for use by AI) -; "Claim_Ocean" = Player claims ocean tiles even if they are not -; adjacent to border source -; "Claim_Ocean_Limited" = Oceanic border sources claim ocean tiles even if -; they are not adjacent to border source ; ; */ <-- avoid gettext warnings diff --git a/data/granularity/effects.ruleset b/data/granularity/effects.ruleset index fcd4763cc9..57186ff48e 100644 --- a/data/granularity/effects.ruleset +++ b/data/granularity/effects.ruleset @@ -621,3 +621,30 @@ reqs = { "type", "name", "range" "Extra", "Mine", "Tile" } + +; claim land from land on the same continent +[effect_claim_land] +type = "Tile_Claimable_From_Same" +value = 100 +reqs = + { "type", "name", "range" + "TerrainClass", "Land", "Tile" + } + +; claim ocean from adjacent ocean +[effect_claim_ocean_base_same] +type = "Tile_Claimable_From_Same" +value = 1 +reqs = + { "type", "name", "range" + "TerrainClass", "Oceanic", "Tile" + } + +; claim ocean from surrounding land +[effect_claim_ocean_base_other] +type = "Tile_Claimable_From_Other" +value = 100 +reqs = + { "type", "name", "range" + "TerrainClass", "Oceanic", "Tile" + } diff --git a/data/granularity/techs.ruleset b/data/granularity/techs.ruleset index 6b3f1aa412..67b8a2f0fa 100644 --- a/data/granularity/techs.ruleset +++ b/data/granularity/techs.ruleset @@ -107,10 +107,6 @@ format_version = 40 ; extra. See "bridged_over" extra property in ; terrain.ruleset. ; "Build_Airborne" = from now on can build air units (for use by AI) -; "Claim_Ocean" = Player claims ocean tiles even if they are not -; adjacent to border source -; "Claim_Ocean_Limited" = Oceanic border sources claim ocean tiles even if -; they are not adjacent to border source ; ; */ <-- avoid gettext warnings diff --git a/data/multiplayer/effects.ruleset b/data/multiplayer/effects.ruleset index 90c958ec67..e65a9c8bc0 100644 --- a/data/multiplayer/effects.ruleset +++ b/data/multiplayer/effects.ruleset @@ -2772,3 +2772,23 @@ reqs = { "type", "name", "range", "present" "Action", "Upgrade Unit", "Local", TRUE } + +; claim land from land on the same continent +[effect_claim_land] +type = "Tile_Claimable_From_Same" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Land", "Tile" +; } + +; claim ocean from surrounding land +[effect_claim_ocean] +type = "Tile_Claimable_From_Other" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Oceanic", "Tile" +; } diff --git a/data/multiplayer/techs.ruleset b/data/multiplayer/techs.ruleset index 52061025ed..a8ce9e5f17 100644 --- a/data/multiplayer/techs.ruleset +++ b/data/multiplayer/techs.ruleset @@ -107,10 +107,6 @@ format_version = 40 ; extra. See "bridged_over" extra property in ; terrain.ruleset. ; "Build_Airborne" = from now on can build air units (for use by AI) -; "Claim_Ocean" = Player claims ocean tiles even if they are not -; adjacent to border source -; "Claim_Ocean_Limited" = Oceanic border sources claim ocean tiles even if -; they are not adjacent to border source ; ; */ <-- avoid gettext warnings diff --git a/data/ruledit/comments-3.3.txt b/data/ruledit/comments-3.3.txt index e09fe465d2..a00dddb9d1 100644 --- a/data/ruledit/comments-3.3.txt +++ b/data/ruledit/comments-3.3.txt @@ -160,10 +160,6 @@ techs = "\ ; extra. See \"bridged_over\" extra property in\n\ ; terrain.ruleset.\n\ ; \"Build_Airborne\" = from now on can build air units (for use by AI)\n\ -; \"Claim_Ocean\" = Player claims ocean tiles even if they are not\n\ -; adjacent to border source\n\ -; \"Claim_Ocean_Limited\" = Oceanic border sources claim ocean tiles even if\n\ -; they are not adjacent to border source\n\ ;\n\ ; */ <-- avoid gettext warnings\n\ " diff --git a/data/sandbox/effects.ruleset b/data/sandbox/effects.ruleset index 41d6dbb54e..cc5043db05 100644 --- a/data/sandbox/effects.ruleset +++ b/data/sandbox/effects.ruleset @@ -5422,3 +5422,23 @@ reqs = "Counter", "Turn_Owned2", "City", TRUE "Counter", "Turn_of_Celebration", "City", TRUE } + +; claim land from land on the same continent +[effect_claim_land] +type = "Tile_Claimable_From_Same" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Land", "Tile" +; } + +; claim ocean from surrounding land +[effect_claim_ocean] +type = "Tile_Claimable_From_Other" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Oceanic", "Tile" +; } diff --git a/data/sandbox/techs.ruleset b/data/sandbox/techs.ruleset index b8d60d927d..18da555f89 100644 --- a/data/sandbox/techs.ruleset +++ b/data/sandbox/techs.ruleset @@ -107,10 +107,6 @@ format_version = 40 ; extra. See "bridged_over" extra property in ; terrain.ruleset. ; "Build_Airborne" = from now on can build air units (for use by AI) -; "Claim_Ocean" = Player claims ocean tiles even if they are not -; adjacent to border source -; "Claim_Ocean_Limited" = Oceanic border sources claim ocean tiles even if -; they are not adjacent to border source ; ; */ <-- avoid gettext warnings diff --git a/data/stub/effects.ruleset b/data/stub/effects.ruleset index 9fe122258f..acd2f052a7 100644 --- a/data/stub/effects.ruleset +++ b/data/stub/effects.ruleset @@ -77,3 +77,30 @@ value = 1 [effect_city_build_slots_basic] type = "City_Build_Slots" value = 1 + +; claim land from land on the same continent +[effect_claim_land] +type = "Tile_Claimable_From_Same" +value = 100 +reqs = + { "type", "name", "range" + "TerrainClass", "Land", "Tile" + } + +; claim ocean from adjacent ocean +[effect_claim_ocean_base_same] +type = "Tile_Claimable_From_Same" +value = 1 +reqs = + { "type", "name", "range" + "TerrainClass", "Oceanic", "Tile" + } + +; claim ocean from surrounding land +[effect_claim_ocean_base_other] +type = "Tile_Claimable_From_Other" +value = 100 +reqs = + { "type", "name", "range" + "TerrainClass", "Oceanic", "Tile" + } diff --git a/data/stub/techs.ruleset b/data/stub/techs.ruleset index fa6c329311..2a7a08310e 100644 --- a/data/stub/techs.ruleset +++ b/data/stub/techs.ruleset @@ -101,10 +101,6 @@ format_version = 40 ; extra. See "bridged_over" extra property in ; terrain.ruleset. ; "Build_Airborne" = from now on can build air units (for use by AI) -; "Claim_Ocean" = Player claims ocean tiles even if they are not -; adjacent to border source -; "Claim_Ocean_Limited" = Oceanic border sources claim ocean tiles even if -; they are not adjacent to border source ; ; */ <-- avoid gettext warnings diff --git a/data/webperimental/effects.ruleset b/data/webperimental/effects.ruleset index 3b9a8e3db7..b217ddf1ae 100644 --- a/data/webperimental/effects.ruleset +++ b/data/webperimental/effects.ruleset @@ -3019,3 +3019,23 @@ reqs = { "type", "name", "range", "present" "Action", "Upgrade Unit", "Local", TRUE } + +; claim land from land on the same continent +[effect_claim_land] +type = "Tile_Claimable_From_Same" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Land", "Tile" +; } + +; claim ocean from surrounding land +[effect_claim_ocean] +type = "Tile_Claimable_From_Other" +value = 100 +; there are no oceanic border sources +;reqs = +; { "type", "name", "range" +; "TerrainClass", "Oceanic", "Tile" +; } diff --git a/data/webperimental/techs.ruleset b/data/webperimental/techs.ruleset index b4d1e4918d..2a1ec3807c 100644 --- a/data/webperimental/techs.ruleset +++ b/data/webperimental/techs.ruleset @@ -107,10 +107,6 @@ format_version = 40 ; extra. See "bridged_over" extra property in ; terrain.ruleset. ; "Build_Airborne" = from now on can build air units (for use by AI) -; "Claim_Ocean" = Player claims ocean tiles even if they are not -; adjacent to border source -; "Claim_Ocean_Limited" = Oceanic border sources claim ocean tiles even if -; they are not adjacent to border source ; ; */ <-- avoid gettext warnings diff --git a/doc/README.effects b/doc/README.effects index 8d3460df31..37880482d2 100644 --- a/doc/README.effects +++ b/doc/README.effects @@ -711,6 +711,25 @@ Thiefs_Share_Pm "Steal Gold Escape" actions that is lost before it reaches the player ordering it. Evaluated against the actor unit. +Tile_Claimable_From_Other + Controls whether national borders can expand to a tile from a border + source (city or base) on a tile of a different terrain class. + A positive value means the tile can be claimed if it is adjacent to the + border source. + A value of at least 100 means the tile can be claimed if it is + sufficiently surrounded by the continent (or body of water) the source + is part of (e.g. inland seas, bays, small islands). + A value of at least 10000 means the tile can always be claimed. + +Tile_Claimable_From_Same + Controls whether national borders can expand to a tile from a border + source (city or base) on a tile of the same terrain class. + A positive value means the tile can be claimed if it is adjacent to the + border source. + A value of at least 100 means the tile can be claimed if it is part of + the same continent (or same body of water) as the border source. + A value of at least 10000 means the tile can always be claimed. + Tile_Workable If value > 0, city can work target tile. diff --git a/gen_headers/enums/effects_enums.def b/gen_headers/enums/effects_enums.def index 73d08870de..da0d8a4591 100644 --- a/gen_headers/enums/effects_enums.def +++ b/gen_headers/enums/effects_enums.def @@ -163,6 +163,8 @@ values TECH_LEAKAGE "Tech_Leakage" IMPR_UPKEEP_REDUCTION "Impr_Upkeep_Reduction" CULTURE_PCT "Culture_Pct" + TILE_CLAIMABLE_FROM_SAME "Tile_Claimable_From_Same" + TILE_CLAIMABLE_FROM_OTHER "Tile_Claimable_From_Other" USER_EFFECT_1 "User_Effect_1" USER_EFFECT_2 "User_Effect_2" USER_EFFECT_3 "User_Effect_3" diff --git a/server/generator/mapgen_utils.c b/server/generator/mapgen_utils.c index 1c1dc3522b..9ec902f840 100644 --- a/server/generator/mapgen_utils.c +++ b/server/generator/mapgen_utils.c @@ -242,19 +242,25 @@ void smooth_int_map(int *int_map, bool zeroes_at_edges) * ocean. */ static Continent_id *lake_surrounders = NULL; +static Continent_id *island_surrounders = NULL; static int *continent_sizes = NULL; static int *ocean_sizes = NULL; /**********************************************************************//** - Calculate lake_surrounders[] array + Calculate lake_surrounders[] and island_surrounders[] arrays **************************************************************************/ -static void recalculate_lake_surrounders(void) +static void recalculate_surrounders(void) { - const size_t size = (wld.map.num_oceans + 1) * sizeof(*lake_surrounders); + size_t size; + size = (wld.map.num_oceans + 1) * sizeof(*lake_surrounders); lake_surrounders = fc_realloc(lake_surrounders, size); memset(lake_surrounders, 0, size); + size = (wld.map.num_continents + 1) * sizeof(*island_surrounders); + island_surrounders = fc_realloc(island_surrounders, size); + memset(island_surrounders, 0, size); + whole_map_iterate(&(wld.map), ptile) { const struct terrain *pterrain = tile_terrain(ptile); Continent_id cont = tile_continent(ptile); @@ -263,17 +269,33 @@ static void recalculate_lake_surrounders(void) continue; } - if (terrain_type_terrain_class(pterrain) != TC_OCEAN) { - adjc_iterate(&(wld.map), ptile, tile2) { - Continent_id cont2 = tile_continent(tile2); - - if (is_ocean_tile(tile2)) { - if (lake_surrounders[-cont2] == 0) { - lake_surrounders[-cont2] = cont; - } else if (lake_surrounders[-cont2] != cont) { - lake_surrounders[-cont2] = -1; - } - } + if (is_ocean(pterrain)) { + fc_assert_action(cont < 0, continue); + adjc_iterate(&(wld.map), ptile, adj_tile) { + Continent_id adj_cont = tile_continent(adj_tile); + + if (!is_ocean_tile(adj_tile)) { + fc_assert_action(adj_cont > 0, continue); + if (island_surrounders[adj_cont] == 0) { + island_surrounders[adj_cont] = -cont; + } else if (island_surrounders[adj_cont] != -cont) { + island_surrounders[adj_cont] = -1; + } + } + } adjc_iterate_end; + } else { + fc_assert_action(cont > 0, continue); + adjc_iterate(&(wld.map), ptile, adj_tile) { + Continent_id adj_cont = tile_continent(adj_tile); + + if (is_ocean_tile(adj_tile)) { + fc_assert_action(adj_cont < 0, continue); + if (lake_surrounders[-adj_cont] == 0) { + lake_surrounders[-adj_cont] = cont; + } else if (lake_surrounders[-adj_cont] != cont) { + lake_surrounders[-adj_cont] = -1; + } + } } adjc_iterate_end; } } whole_map_iterate_end; @@ -343,8 +365,7 @@ static void assign_continent_flood(struct tile *ptile, bool is_land, int nr) /**********************************************************************//** Regenerate all oceanic tiles for small water bodies as lakes. - Assumes assign_continent_numbers() and recalculate_lake_surrounders() - have already been done! + Assumes assign_continent_numbers() has already been called! FIXME: insufficiently generalized, use terrain property. **************************************************************************/ void regenerate_lakes(void) @@ -417,9 +438,19 @@ void regenerate_lakes(void) /**********************************************************************//** Get continent surrounding lake, or -1 if there is multiple continents. **************************************************************************/ -int get_lake_surrounders(Continent_id cont) +int get_lake_surrounders(Continent_id id) { - return lake_surrounders[-cont]; + fc_assert_ret_val(id < 0, -1); + return lake_surrounders[-id]; +} + +/**********************************************************************//** + Get ocean surrounding island, or +1 if there are multiple oceans. +**************************************************************************/ +int get_island_surrounders(Continent_id id) +{ + fc_assert_ret_val(id > 0, -1); + return -island_surrounders[id]; } /**********************************************************************//** @@ -444,7 +475,7 @@ int get_ocean_size(Continent_id id) /**********************************************************************//** Assigns continent and ocean numbers to all tiles, and set map.num_continents and map.num_oceans. Recalculates continent and - ocean sizes, and lake_surrounders[] arrays. + ocean sizes, and lake_surrounders[] and island_surrounders[] arrays. Continents have numbers 1 to map.num_continents _inclusive_. Oceans have (negative) numbers -1 to -map.num_oceans _inclusive_. @@ -487,7 +518,7 @@ void assign_continent_numbers(void) } } whole_map_iterate_end; - recalculate_lake_surrounders(); + recalculate_surrounders(); log_verbose("Map has %d continents and %d oceans", wld.map.num_continents, wld.map.num_oceans); @@ -665,6 +696,10 @@ void generator_free(void) free(lake_surrounders); lake_surrounders = NULL; } + if (island_surrounders != NULL) { + free(island_surrounders); + island_surrounders = NULL; + } if (continent_sizes != NULL) { free(continent_sizes); continent_sizes = NULL; diff --git a/server/generator/mapgen_utils.h b/server/generator/mapgen_utils.h index df2867fee4..d6a290ee7e 100644 --- a/server/generator/mapgen_utils.h +++ b/server/generator/mapgen_utils.h @@ -22,7 +22,8 @@ void generator_free(void); void regenerate_lakes(void); void smooth_water_depth(void); void assign_continent_numbers(void); -int get_lake_surrounders(Continent_id cont); +int get_lake_surrounders(Continent_id id); +int get_island_surrounders(Continent_id id); int get_continent_size(Continent_id id); int get_ocean_size(Continent_id id); diff --git a/server/maphand.c b/server/maphand.c index 0016651d3a..707e423c5c 100644 --- a/server/maphand.c +++ b/server/maphand.c @@ -59,7 +59,7 @@ #include "maphand.h" -#define MAXIMUM_CLAIMED_OCEAN_SIZE (20) +#define MAXIMUM_CLAIMED_LAKE_OR_ISLAND_SIZE (20) /* Suppress send_tile_info() during game_load() */ static bool send_tile_suppressed = FALSE; @@ -87,8 +87,8 @@ static inline bool map_is_also_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer); -static bool is_claimable_ocean(struct tile *ptile, struct tile *source, - struct player *pplayer); +static bool is_tile_claimable(struct tile *ptile, struct tile *source, + struct player *pplayer); /**********************************************************************//** Used only in global_warming() and nuclear_winter() below. @@ -2061,7 +2061,7 @@ void check_terrain_change(struct tile *ptile, struct terrain *oldter) claimer = tile_claimer(ptile); if (claimer != NULL && is_ocean_tile(ptile)) { - if (!is_claimable_ocean(ptile, claimer, tile_owner(ptile))) { + if (!is_tile_claimable(ptile, claimer, tile_owner(ptile))) { map_clear_border(ptile); } } @@ -2070,60 +2070,104 @@ void check_terrain_change(struct tile *ptile, struct terrain *oldter) } /**********************************************************************//** - Ocean tile can be claimed iff one of the following conditions stands: - a) it is an inland lake not larger than MAXIMUM_OCEAN_SIZE - b) it is adjacent to only one continent and not more than two ocean tiles - c) It is one tile away from a border source - d) Player knows tech with Claim_Ocean flag - e) Source itself is Oceanic tile and player knows tech with Claim_Ocean_Limited flag - The source which claims the ocean has to be placed on the correct continent. - in case a) The continent which surrounds the inland lake - in case b) The only continent which is adjacent to the tile + A tile can be claimed by a border source iff one of the following + conditions is fulfilled: + a) The tile is the border source + b) The relevant Tile_Claimable_* effect is TILE_CLAIMABLE_ADJACENT or + more, and the tile is next to the border source + c) The relevant Tile_Claimable_* effect is TILE_CLAIMABLE_CONTINENT or + more, and the tile is on the same continent as the border source + d) The relevant Tile_Claimable_* effect is TILE_CLAIMABLE_CONTINENT or + more, the tile is part of an inland lake or an island not larger than + MAXIMUM_CLAIMED_LAKE_OR_ISLAND_SIZE, and the border source is on the + continent or ocean surrounding that lake or island + e) The relevant Tile_Claimable_* effect is TILE_CLAIMABLE_CONTINENT or + more, the tile is adjacent to no more than two tiles of the same + terrain class and only one contiguous continent/ocean of the other, + and the border source is on that continent or ocean + f) The relevant Tile_Claimable_* effect is TILE_CLAIMABLE_ALWAYS or more **************************************************************************/ -static bool is_claimable_ocean(struct tile *ptile, struct tile *source, - struct player *pplayer) +static bool is_tile_claimable(struct tile *ptile, struct tile *source, + struct player *pplayer) { Continent_id cont = tile_continent(ptile); Continent_id source_cont = tile_continent(source); - int ocean_tiles; + int same_class_tiles, eft_value; + enum effect_type eft_type; bool other_continent; - if (get_ocean_size(-cont) <= MAXIMUM_CLAIMED_OCEAN_SIZE - && get_lake_surrounders(cont) == source_cont) { + if (ptile == source) { + /* Source itself is always claimable (a) */ return TRUE; } - if (ptile == source) { - /* Source itself is always claimable. */ - return TRUE; + if ((cont < 0 && source_cont < 0) || (cont > 0 && source_cont > 0)) { + /* Same terrain class */ + eft_type = EFT_TILE_CLAIMABLE_FROM_SAME; + } else { + /* Different terrain classes */ + eft_type = EFT_TILE_CLAIMABLE_FROM_OTHER; + } + eft_value = get_target_bonus_effects(nullptr, + &(const struct req_context) { + .tile = ptile, + .player = pplayer, + }, + nullptr, eft_type); + + if (eft_value < TILE_CLAIMABLE_ADJACENT) { + /* Not claimable (except a, checked above) */ + return FALSE; } - if (num_known_tech_with_flag(pplayer, TF_CLAIM_OCEAN) > 0 - || (source_cont < 0 && num_known_tech_with_flag(pplayer, TF_CLAIM_OCEAN_LIMITED) > 0)) { + if (eft_value >= TILE_CLAIMABLE_ALWAYS) { + /* Claimable no matter adjacency or continents (f) */ return TRUE; } - ocean_tiles = 0; + if (eft_value >= TILE_CLAIMABLE_CONTINENT) { + if (cont == source_cont) { + /* Same continent/ocean (c) */ + return TRUE; + } + if (cont < 0 && source_cont > 0 + && get_ocean_size(-cont) <= MAXIMUM_CLAIMED_LAKE_OR_ISLAND_SIZE + && get_lake_surrounders(cont) == source_cont) { + /* Lake is claimable from the surrounding continent (d) */ + return TRUE; + } + if (cont > 0 && source_cont < 0 + && get_continent_size(cont) <= MAXIMUM_CLAIMED_LAKE_OR_ISLAND_SIZE + && get_island_surrounders(cont) == source_cont) { + /* Island is claimable from the surrounding ocean (d) */ + return TRUE; + } + } + + same_class_tiles = 0; other_continent = FALSE; adjc_iterate(&(wld.map), ptile, adj_tile) { Continent_id adj_cont = tile_continent(adj_tile); if (adj_tile == source) { - /* Water next to border source is always claimable */ + /* Tile next to border source is claimable (b) */ return TRUE; } if (adj_cont == cont) { - ocean_tiles++; + same_class_tiles++; } else if (adj_cont != source_cont) { - /* This water is adjacent to a continent different from the one + /* This tile is adjacent to a continent/ocean different from the one * the border source is on */ other_continent = TRUE; } } adjc_iterate_end; - if (!other_continent && ocean_tiles <= 2) { + + if (eft_value >= TILE_CLAIMABLE_CONTINENT + && !other_continent && same_class_tiles <= 2) { + /* Bay/peninsula claimable from the surrounding continent/ocean (e) */ return TRUE; - } else { - return FALSE; } + + return FALSE; } /**********************************************************************//** @@ -2338,17 +2382,9 @@ void map_claim_border(struct tile *ptile, struct player *owner, } } - if (is_ocean_tile(dtile)) { - /* Only certain water tiles are claimable */ - if (is_claimable_ocean(dtile, ptile, owner)) { - map_claim_ownership(dtile, owner, ptile, dr == 0); - } - } else { - /* Only land tiles on the same island as the border source - * are claimable */ - if (tile_continent(dtile) == tile_continent(ptile)) { - map_claim_ownership(dtile, owner, ptile, dr == 0); - } + /* Only certain tiles are claimable */ + if (is_tile_claimable(dtile, ptile, owner)) { + map_claim_ownership(dtile, owner, ptile, dr == 0); } } circle_dxyr_iterate_end; } diff --git a/server/ruleset/rscompat.c b/server/ruleset/rscompat.c index 72fef173e4..10322d2104 100644 --- a/server/ruleset/rscompat.c +++ b/server/ruleset/rscompat.c @@ -48,8 +48,10 @@ FC_STATIC_ASSERT((ARRAY_SIZE(_new_flags_) \ not_enough_new_##_name_##_user_flags) #define UTYF_LAST_USER_FLAG_3_2 UTYF_USER_FLAG_50 +#define TECH_LAST_USER_FLAG_3_2 TECH_USER_7 static int first_free_unit_type_user_flag(void); +static int first_free_tech_user_flag(void); /**********************************************************************//** Initialize rscompat information structure @@ -386,6 +388,54 @@ bool rscompat_names(struct rscompat_info *info) } } + if (info->version < RSFORMAT_3_3) { + int first_free; + int i; + + /* Some tech flags moved to the ruleset between 3.2 and 3.3. + * Add them back as user flags. + * XXX: ruleset might not need all of these, and may have enough + * flags of its own that these additional ones prevent conversion. */ + const struct { + const char *name; + const char *helptxt; + } new_flags_33[] = { + { N_("Claim_Ocean"), + N_("National borders expand freely into the ocean.") }, + { N_("Claim_Ocean_Limited"), + N_("National borders from oceanic sources expand freely.") }, + }; + + enough_new_user_flags(new_flags_33, tech, + (TECH_USER_LAST - 1), TECH_LAST_USER_FLAG_3_2); + + /* Unit type flags. */ + first_free = first_free_tech_user_flag() + TECH_USER_1; + + for (i = 0; i < ARRAY_SIZE(new_flags_33); i++) { + if (TECH_USER_1 + MAX_NUM_USER_TECH_FLAGS <= first_free + i) { + /* Can't add the user unit type flags. */ + ruleset_error(NULL, LOG_ERROR, + "Can't upgrade the ruleset. Not enough free tech " + "user flags to add user flags for the tech flags " + "that used to be hardcoded."); + return FALSE; + } + /* Shouldn't be possible for valid old ruleset to have flag names that + * clash with these ones */ + if (tech_flag_id_by_name(new_flags_33[i].name, fc_strcasecmp) + != tech_flag_id_invalid()) { + ruleset_error(NULL, LOG_ERROR, + "Ruleset had illegal user tech flag '%s'", + new_flags_33[i].name); + return FALSE; + } + set_user_tech_flag_name(first_free + i, + new_flags_33[i].name, + new_flags_33[i].helptxt); + } + } + /* No errors encountered. */ return TRUE; } @@ -405,6 +455,7 @@ static bool effect_list_compat_cb(struct effect *peffect, void *data) void rscompat_postprocess(struct rscompat_info *info) { struct action_enabler *enabler; + struct effect *effect; struct requirement e_req; if (!info->compat_mode || info->version >= RSFORMAT_CURRENT) { @@ -441,6 +492,69 @@ void rscompat_postprocess(struct rscompat_info *info) * thought limited by game.info.tech_leakage setting. */ effect_new(EFT_TECH_LEAKAGE, 1, nullptr); + /* Old behavior: Land tiles can always be claimed by land border sources + * on the same continent. */ + effect = effect_new(EFT_TILE_CLAIMABLE_FROM_SAME, + TILE_CLAIMABLE_CONTINENT, + nullptr); + e_req = req_from_values(VUT_TERRAINCLASS, REQ_RANGE_TILE, + FALSE, TRUE, FALSE, TC_LAND); + effect_req_append(effect, e_req); + + /* Old behavior: Oceanic tiles can always be claimed by adjacent oceanic + * border sources. */ + effect = effect_new(EFT_TILE_CLAIMABLE_FROM_SAME, + TILE_CLAIMABLE_ADJACENT, + nullptr); + e_req = req_from_values(VUT_TERRAINCLASS, REQ_RANGE_TILE, + FALSE, TRUE, FALSE, TC_OCEAN); + effect_req_append(effect, e_req); + + /* Old behavior: Oceanic tiles can always be claimed by land border + * sources on a surrounding continent. */ + effect = effect_new(EFT_TILE_CLAIMABLE_FROM_OTHER, + TILE_CLAIMABLE_CONTINENT, + nullptr); + e_req = req_from_values(VUT_TERRAINCLASS, REQ_RANGE_TILE, + FALSE, TRUE, FALSE, TC_OCEAN); + effect_req_append(effect, e_req); + + /* Old behavior: Oceanic tiles can be claimed by any oceanic border + * sources with Claim_Ocean_Limited techflag. */ + effect = effect_new(EFT_TILE_CLAIMABLE_FROM_SAME, + TILE_CLAIMABLE_ALWAYS, + nullptr); + e_req = req_from_values(VUT_TERRAINCLASS, REQ_RANGE_TILE, + FALSE, TRUE, FALSE, TC_OCEAN); + effect_req_append(effect, e_req); + e_req = req_from_str("TechFlag", "Player", FALSE, TRUE, FALSE, + "Claim_Ocean_Limited"); + effect_req_append(effect, e_req); + + /* Old behavior: Oceanic tiles can be claimed by any oceanic border + * sources with Claim_Ocean techflag. */ + effect = effect_new(EFT_TILE_CLAIMABLE_FROM_SAME, + TILE_CLAIMABLE_ALWAYS, + nullptr); + e_req = req_from_values(VUT_TERRAINCLASS, REQ_RANGE_TILE, + FALSE, TRUE, FALSE, TC_OCEAN); + effect_req_append(effect, e_req); + e_req = req_from_str("TechFlag", "Player", FALSE, TRUE, FALSE, + "Claim_Ocean"); + effect_req_append(effect, e_req); + + /* Old behavior: Oceanic tiles can be claimed by any land border sources + * with Claim_Ocean techflag. */ + effect = effect_new(EFT_TILE_CLAIMABLE_FROM_OTHER, + TILE_CLAIMABLE_ALWAYS, + nullptr); + e_req = req_from_values(VUT_TERRAINCLASS, REQ_RANGE_TILE, + FALSE, TRUE, FALSE, TC_OCEAN); + effect_req_append(effect, e_req); + e_req = req_from_str("TechFlag", "Player", FALSE, TRUE, FALSE, + "Claim_Ocean"); + effect_req_append(effect, e_req); + /* Make sure that all action enablers added or modified by the * compatibility post processing fulfills all hard action requirements. */ rscompat_enablers_add_obligatory_hard_reqs(); @@ -473,6 +587,25 @@ static int first_free_unit_type_user_flag(void) return MAX_NUM_USER_UNIT_FLAGS; } +/**********************************************************************//** + Find and return the first unused tech user flag. If all tech + user flags are taken MAX_NUM_USER_TECH_FLAGS is returned. +**************************************************************************/ +static int first_free_tech_user_flag(void) +{ + int flag; + + /* Find the first unused user defined tech flag. */ + for (flag = 0; flag < MAX_NUM_USER_TECH_FLAGS; flag++) { + if (tech_flag_id_name_cb(flag + TECH_USER_1) == NULL) { + return flag; + } + } + + /* All tech user flags are taken. */ + return MAX_NUM_USER_TECH_FLAGS; +} + /**********************************************************************//** Convert 3.2 unit type flag name to 3.3 one. **************************************************************************/ -- 2.34.1