From 2e79bf86cd36a917b3f9d6efc85c0ec5264e9ead Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C5=82awomir=20Lach?= <slawek@lach.art.pl>
Date: Thu, 9 Mar 2023 18:23:11 +0100
Subject: [PATCH] =?UTF-8?q?!OSND:=20TICKET:=20#45889.=20S=C5=82awomir=20La?=
 =?UTF-8?q?ch=20<slawek@lach.art.pl>?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Ruleset to test modifications.

diff --git a/data/testy-slawomir/Makefile.am b/data/testy-slawomir/Makefile.am
new file mode 100644
index 0000000000..b9eabbc795
--- /dev/null
+++ b/data/testy-slawomir/Makefile.am
@@ -0,0 +1,23 @@
+## Process this file with automake to produce Makefile.in
+
+## Override automake so that "make install" puts these in proper place:
+pkgdatadir = $(datadir)/$(PACKAGE)/stub
+
+SUBDIRS = nations
+
+pkgdata_DATA =          	\
+	actions.ruleset		\
+	buildings.ruleset 	\
+	cities.ruleset		\
+	effects.ruleset		\
+	script.lua		\
+	parser.lua		\
+	styles.ruleset		\
+	game.ruleset		\
+	governments.ruleset	\
+	nations.ruleset		\
+	techs.ruleset		\
+	terrain.ruleset		\
+	units.ruleset
+
+EXTRA_DIST = $(pkgdata_DATA)
diff --git a/data/testy-slawomir/actions.ruleset b/data/testy-slawomir/actions.ruleset
new file mode 100644
index 0000000000..90291e9d12
--- /dev/null
+++ b/data/testy-slawomir/actions.ruleset
@@ -0,0 +1,210 @@
+
+; This is minimal actions ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> actions data for Freeciv"
+options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
+format_version = 40
+
+[auto_attack]
+; An auto attack may be triggered when another unit moves to an adjacent
+; tile and the autoattack server setting is enabled. The following details
+; are ruleset controlled.
+;   if_attacker    - this requirement vector must be true before a unit even
+;                    considers to auto attack.
+;   attack_actions - the actions to try during an auto attack in the order
+;                    they should be tried.
+
+;if_attacker =
+;    { "type",         "name",    "range", "present"
+;    }
+
+;attack_actions = "Capture Units", "Bombard", "Attack", "Suicide Attack"
+
+[actions]
+; Forbid regular unit move if one of the actions below is legal.
+;move_blocked_by = "Conquer Extras"
+
+; Actor units will - under certain circumstances - be forced to try
+; performing the following actions in the specified order after successfully
+; performing "Bribe Unit".
+;bribe_unit_post_success_forced_actions = "Transport Embark", "Unit Move"
+
+; Actor units will - under certain circumstances - be forced to try
+; performing the following actions in the specified order after successfully
+; performing "Attack".
+;attack_post_success_forced_actions = "Conquer City", "Conquer City 2",
+;                                     "Unit Move"
+
+; The city that made the unit`s current tile native is gone. This is a Hail
+; Mary attempt at survival by performing an action. Evaluated against an
+; adjacent tile. Currently only able to target native tiles.
+; escape_city = "Enter Hut", "Frighten Hut", "Unit Move"
+
+; The unit`s stack has been defeated and is scheduled for execution but the
+; unit has the CanEscape unit type flag. Evaluated against an adjacent tile.
+;unit_stack_death = "Transport Embark", "Unit Move"
+
+; If poison_empties_food_stock is set to TRUE a successful "Poison City"
+; or "Poison City Escape" will empty the food stock.
+;poison_empties_food_stock = FALSE
+
+; If steal_maps_reveals_all_cities is set to TRUE a successful "Steal Maps"
+; or "Steal Maps Escape" will transfer the map for all tiles containing a
+; city.
+;steal_maps_reveals_all_cities = TRUE
+
+; The maximum distance from the actor unit to the target of the "Bombard"
+; action. The value 1 means that the targets must be on a tile adjacent to
+; the actor unit. The special value "unlimited" lifts the maximum distance
+; restriction. The maximum distance can`t be smaller than the minimum
+; distance.
+bombard_max_range = 1
+
+; The maximum distance from the actor unit to the target of the "Bombard 2"
+; action. The value 1 means that the targets must be on a tile adjacent to
+; the actor unit. The special value "unlimited" lifts the maximum distance
+; restriction. The maximum distance can`t be smaller than the minimum
+; distance.
+bombard_2_max_range = 1
+
+; The maximum distance from the actor unit to the target of the "Bombard 3"
+; action. The value 1 means that the targets must be on a tile adjacent to
+; the actor unit. The special value "unlimited" lifts the maximum distance
+; restriction. The maximum distance can`t be smaller than the minimum
+; distance.
+bombard_3_max_range = 1
+
+; The maximum distance from the actor unit to the target of the
+; "Bombard Lethal" action. The value 1 means that the targets must be on a
+; tile adjacent to the actor unit. The special value "unlimited" lifts the
+; maximum distance restriction. The maximum distance can`t be smaller than
+; the minimum distance.
+bombard_lethal_max_range = 1
+
+; The minimal distance from the actor unit to the target. The value 0 means
+; that the target must be at the tile of the actor unit. The value 1 means
+; that the tile must be a tile adjacent to the actor unit.
+;explode_nuclear_min_range = 0
+
+; The maximum distance from the actor unit to the target of the
+; "Explode Nuclear" action. The value 0 means that the target tile must be
+; the tile of the actor unit. The value 1 means that the tile must be a tile
+; adjacent to the actor unit. The special value "unlimited" lifts the
+; maximum distance restriction. The maximum distance can`t be smaller than
+; the minimum distance.
+;explode_nuclear_max_range = 0
+
+; Will performing this action always consume the actor unit?
+explode_nuclear_consuming_always = TRUE
+
+; The minimal distance from the actor unit to the target. The value 0 means
+; that the target must be at the tile of the actor unit. The value 1 means
+; that the tile must be a tile adjacent to the actor unit.
+;nuke_city_min_range = 1
+
+; The maximum distance from the actor unit to the target of the
+; "Nuke City" action. The value 1 means that the tile must be a tile
+; adjacent to the actor unit. The special value "unlimited" lifts the
+; maximum distance restriction. The maximum distance can`t be smaller than
+; the minimum distance.
+;nuke_city_max_range = 1
+
+; Will performing this action always consume the actor unit?
+nuke_city_consuming_always = TRUE
+
+; The kind of target the "Nuke City" action has. The target requirements of
+; its enablers are evaluated against the target. The target owner is the one
+; that gets a Casus Belli if the ruleset has a Casus Belli for this action.
+; Supported values are "City" and "Tile".
+nuke_city_target_kind = "City"
+
+; The minimal distance from the actor unit to the target. The value 0 means
+; that the target must be at the tile of the actor unit. The value 1 means
+; that the tile must be a tile adjacent to the actor unit.
+;nuke_units_min_range = 1
+
+; The maximum distance from the actor unit to the target of the
+; "Nuke Units" action. The value 1 means that the tile must be a tile
+; adjacent to the actor unit. The special value "unlimited" lifts the
+; maximum distance restriction. The maximum distance can`t be smaller than
+; the minimum distance.
+;nuke_units_max_range = 1
+
+; Will performing this action always consume the actor unit?
+nuke_units_consuming_always = TRUE
+
+; Will performing this action always consume the actor unit?
+found_city_consuming_always = TRUE
+
+; What each action should be called when showing them to the player.
+; The first %s should be before the mnemonic of the action. A Freeciv client
+; that supports mnemonics will replace it with the in-band signal that marks
+; the following character as a mnemonic in its graphical toolkit.
+; The second %s marks where extra details should be inserted.
+
+; ui_name_xxx = _("%s%s")
+
+; /* <-- avoid gettext warnings
+;
+; Action enablers:
+;
+; action               = the action to enable.
+; actor_reqs           = requirements that apply to the actor.
+; target_reqs          = requirements that apply to the target.
+;
+; README.actions lists the possible actions and their hard coded
+; requirements.
+;
+; An action enabler is active when its actor_reqs AND its target_reqs are
+; satisfied.
+;
+; */ <-- avoid gettext warnings
+
+; No enabled actions
+; [actionenabler_embassy]
+; action = "Establish Embassy"
+
+[actionenabler_regular_move]
+action     = "Unit Move"
+actor_reqs =
+    { "type",         "name",        "range", "present"
+      "MinMoveFrags", "1",           "Local", TRUE
+      "UnitState",    "Transported", "Local", FALSE
+    }
+
+[actionenabler_conquer_city_native]
+action = "Conquer City"
+actor_reqs    =
+{ "type",           "name",          "range", "present"
+  "UnitClassFlag",  "CanOccupyCity", "Local", TRUE
+  "MinMoveFrags",   "1",             "Local", TRUE
+  "DiplRel",        "War",           "Local", TRUE
+}
+target_reqs    =
+{ "type",           "name",          "range", "present"
+  "MaxUnitsOnTile", "0",             "Tile",  TRUE
+}
+
+; Blank ruleset defined user actions.
+; See the section "Ruleset defined actions" in doc/README.actions
+; Example: set up "User Action 1"
+;ui_name_user_action_1                = _("%sDisrupt Supply Lines%s")
+;user_action_1_target_kind            = "Unit"
+;user_action_1_min_range              = 1
+;user_action_1_max_range              = 3
+;user_action_1_actor_consuming_always = FALSE
+
+; Some actions have a action dice roll before the action starts where it can
+; fail. The initial probability of success is 100% unless the action appears
+; in the following list. Then the initial probability comes from the setting
+; diplchance. The initial probability of success is modified by the
+; Action_Odds_Pct effect before the roll happens.
+;diplchance_initial_odds = "Sabotage City", "Sabotage City Escape"
+
+; Suppress automatic help text generation about what enables and/or
+; disables the following actions.
+;
+; Can make the help text less redundant when you document it your self.
+;quiet_actions = "Targeted Sabotage City", "Targeted Steal Tech", "Unit Move"
diff --git a/data/testy-slawomir/buildings.ruleset b/data/testy-slawomir/buildings.ruleset
new file mode 100644
index 0000000000..547a385db3
--- /dev/null
+++ b/data/testy-slawomir/buildings.ruleset
@@ -0,0 +1,87 @@
+; This is minimal buildings ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> buildings data for Freeciv"
+options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
+format_version = 40
+
+[control]
+
+; Names for custom building flags. There can be up to 8 of these.
+; name          = rule name; In some circumstances user may see this
+;                 as part of some sentences, so try to make it descriptive
+;                 and sensible.
+; helptxt       = displayed in the help for building types with this flag
+;                 (optional)
+;building_flags =
+;  { "name", "helptxt"
+;  }
+
+; /* <-- avoid gettext warnings
+;
+; Below: The individual buildings, one per section.
+; (Buildings = City Improvements and Wonders)
+;
+; The actual tag used (the * in [building_*]) does not matter, except
+; it must be unique within this file, and it may be used in debug
+; output when reading this file.
+;
+; Notes:
+;
+; name          = translatable name as seen by user
+; rule_name     = (optional) internal name for savegames, rulesets etc; if
+;                 not present, "name" is used for this purpose too. Since
+;                 the name used in savegames must not change, if you want
+;                 to rename an item after a ruleset has been released, you
+;                 should set "rule_name" to the original value of "name".
+; genus	        = genus; one of:
+;                 "GreatWonder", "SmallWonder", "Improvement", "Special",
+;                 or "Convert".
+; reqs		= requirements to build the building (see effects.ruleset
+;		  and README.effects for help on requirements)
+; graphic	= icon of improvement (used in city dialog)
+; graphic_alt	= alternate icon of improvement
+; obsolete_by	= requirements for the building to become obsolete
+; build_cost	= production shields required to build
+; upkeep	= monetary upkeep value
+; sabotage	= percent chance of diplomat sabotage being successful
+; flags         = special flag strings
+;
+; ** Building flags **
+; "VisibleByOthers"  = Anyone who can see your city knows whether it has
+;                      this improvement. (Great and small wonders are
+;                      always visible.)
+; "SaveSmallWonder"  = If you lose the city with this building in, and the
+;                      "savepalace" server setting is enabled, another will
+;                      be built for free in a random city.
+;                      Should only be used with genus "SmallWonder".
+; "Gold"             = Not a real building; production turned into gold
+;                      indefinitely (capitalization/coinage).
+;                      Genus should be "Convert".
+; "DisasterProof"    = Disasters never destroy this building. Is meaningful
+;                      only for genus "Improvement" buildings as others are
+;                      automatically disaster proof.
+;
+; */ <-- avoid gettext warnings
+
+[building_generic]
+name		= _("Generic")
+genus		= "Improvement"
+reqs	=
+    { "type", "name", "range"
+; No requirements
+    }
+graphic	= "b.barracks"
+graphic_alt	= "-"
+obsolete_by     =
+    { "type", "name", "range"
+    }
+build_cost	= 100
+upkeep		= 0
+sabotage	= 100
+sound		= "b_barracks"
+sound_alt	= "b_generic"
+helptext	= _("\
+This is the only building you can build.\
+")
diff --git a/data/testy-slawomir/cities.ruleset b/data/testy-slawomir/cities.ruleset
new file mode 100644
index 0000000000..6380f2ad1b
--- /dev/null
+++ b/data/testy-slawomir/cities.ruleset
@@ -0,0 +1,96 @@
+; This is minimal cities ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> cities data for Freeciv"
+options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
+format_version = 40
+
+; /* <-- avoid gettext warnings
+;
+; A specialist is a city citizen who is not a tile worker.  Usually the
+; player can control what specialist each citizen is, so long as the
+; requirements for that specialist are met.
+;
+; Below are the entries for the specialists, one per specialist type.
+; The tag name (in [specialist_*]) doesn't matter so long as it's unique.
+; For each specialist the following fields may be set:
+;
+;
+; name          = translatable (plural) name as seen by user
+; rule_name     = (optional) internal name for savegames, rulesets etc; if
+;                 not present, "name" is used for this purpose too. Since
+;                 the name used in savegames must not change, if you want
+;                 to rename an item after a ruleset has been released, you
+;                 should set "rule_name" to the original value of "name".
+; short_name    = one-character "short name" used (for instance) in cityrep;
+;                 should be first character/abbrevation of "name"
+; graphic       = tag specifying preferred graphic
+;                 Different images based on citizen number are supported.
+;                 If no such images indexed with citizen number are found,
+;                 plain tag is used instead.
+; graphic_alt   = fallback graphic tag in case the specialist graphic isn't
+;                 found.
+; reqs          = requirements to have the specialist pick (see
+;                 effects.ruleset and README.effects for help on requirements)
+; helptext      = optional help text string; should escape all raw newlines
+;                 so that xgettext parsing works
+;
+; */ <-- avoid gettext warnings
+
+[specialist_generic]
+name            = _("Generic")
+short_name      = _("?gspecialist:G")
+graphic         = "specialist.entertainer"
+reqs            =
+    { "type", "name", "range"
+; No requirements
+    }
+
+[parameters]
+add_to_size_limit  = 8		; cities >= this cannot be added to.
+angry_citizens = TRUE           ; set to FALSE to disable angry citizens
+celebrate_size_limit = 3        ; cities >= can celebrate
+
+changable_tax = TRUE            ; set to FALSE to disallow changing of tax rates
+
+;forced_science = 0		; set these fields when changeable_tax is turned off
+;forced_luxury = 100
+;forced_gold = 0
+
+vision_reveal_tiles  = TRUE     ; civ1 & 2 default FALSE
+
+pop_report_zeroes    = 1        ; Population in reports in tens
+
+[citizen]
+nationality          = FALSE    ; account for the nationality of the citizens
+ubuilder_nationality = FALSE    ; does pop_cost unit get builder`s nationality,
+                                ; or that of the majority of the citizens in the city
+convert_speed        = 50       ; base probability 50/1000 -> once every 20 turns
+partisans_pct        = 0        ; percentage of own nationality to inspire partisans
+                                ; if 0, original city owner information is used instead
+conquest_convert_pct = 0        ; percentage which converts to the new nation
+                                ; after a city was conquered. Applied separately for each
+                                ; nationality present in the city, and number of
+                                ; converted people rounded up
+
+[missing_unit_upkeep]
+; Get rid of a unit the city is unable to pay the X upkeep of.
+; X_protected  - never get rid of a unit with any of the listed unit type
+;                flags.
+; X_unit_act   - have the unit perform the listed actions until success,
+;                death or the list ends.
+; X_wipe       - wipe the unit if it survived performing the actions listed
+;                above.
+
+; food_protected  = "EvacuateFirst"
+; food_unit_act   =
+; food_wipe       = TRUE
+
+; gold_protected  =
+; gold_unit_act   =
+; gold_wipe       = TRUE
+
+; shield_protected  = "EvacuateFirst"
+; shield_unit_act   = "Help Wonder", "Disband Unit Recover", "Disband Unit"
+; shield_wipe       = FALSE
diff --git a/data/testy-slawomir/effects.ruleset b/data/testy-slawomir/effects.ruleset
new file mode 100644
index 0000000000..462aad7698
--- /dev/null
+++ b/data/testy-slawomir/effects.ruleset
@@ -0,0 +1,96 @@
+; This is minimal effects ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> effects data for Freeciv"
+options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
+format_version = 40
+
+; /* <-- avoid gettext warnings
+;
+; User effect types
+;
+; type                    = Effect type to define. Must be one of user effects.
+; ai_valued_as            = Hardcoded effect type that AI considers this to match
+;
+; */ <-- avoid gettext warnings
+
+;[ueff_1]
+;type         = "User_Effect_1"
+;ai_valued_as = ""
+
+; /* <-- avoid gettext warnings
+;
+; Effects
+;
+; type                    = What the effect does. Values of multiple active effects
+;                           of the same type get summed for the total.
+;                           See README.effects for list of possible types
+; value                   = Value added for the effect type when this effect is active,
+;                           i.e., all requirements are fulfilled
+; multiplier              = Name of the policy that gives a multiplier for effect's value
+; reqs                    = Requirements for the effect to be active.
+;                           See README.effects for help on requirements
+; comment                 = Comment for the benefit to someone examining the ruleset
+;                           Not used by freeciv any other way.
+;
+; */ <-- avoid gettext warnings
+
+; Cheating AI effects are in separate file
+;*include "default/ai_effects.ruleset"
+
+; Base vision range - radius of vision is sqrt(5) = 2.24
+[effect_city_vision]
+type    = "City_Vision_Radius_Sq"
+value   = 5
+
+[effect_base_unit_upkeep]
+type	= "Upkeep_Factor"
+value	= 1
+
+[effect_empire_size_base]
+type    = "Empire_Size_Base"
+value   = 99999
+
+[effect_empire_size_step_base]
+type    = "Empire_Size_Step"
+value   = 0
+
+[effect_max_rates_base]
+type    = "Max_Rates"
+value   = 40
+
+[effect_base_size]
+type    = "Size_Adj"
+value   = 30
+
+[effect_tech_cost_base]
+type    = "Tech_Cost_Factor"
+value   = 1
+
+; Cities can always work tiles
+[effect_tile_workable]
+type    = "Tile_Workable"
+value   = 1
+
+; each city has at least one slot to build units
+[effect_city_build_slots_basic]
+type    = "City_Build_Slots"
+value   = 1
+
+[effect_love_ruler]
+type = "Output_Add_Tile"
+value = 2
+reqs =
+{ "type", "name", "range", "present", "quiet"
+  "Counter", "Cel1", "City", TRUE, TRUE
+}
+
+
+[effect_for_tests1]
+type = "Force_Content"
+value = 99999
+
+[effect_for_tests2]
+type = "Make_Happy"
+value = 99999
diff --git a/data/testy-slawomir/game.ruleset b/data/testy-slawomir/game.ruleset
new file mode 100644
index 0000000000..6386a584b4
--- /dev/null
+++ b/data/testy-slawomir/game.ruleset
@@ -0,0 +1,606 @@
+; This is minimal game ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> game rules for Freeciv"
+options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
+format_version = 40
+
+; This section contains meta information for freeciv-ruledit to recreate the ruleset
+; file in a form wanted. These have no in-game effect whatsoever
+[ruledit]
+
+; Which file to read description in from.
+;description_file = ""
+
+[about]
+; Ruleset name
+name = _("Stub")
+
+; Versioning of the ruleset
+;version = ""
+
+; When about to migrate ruleset under a new name in the future version, set
+; alt_dir to the name of that future directory. Then savegames saved with this
+; version of freeciv can find the ruleset from the correct place when loading
+; the savegame to the future version.
+;alt_dir = ""
+
+; Summary of the ruleset
+summary = _("\
+This ruleset is meant to be used as starting point for \
+real rulesets, not playable ruleset in itself.\
+")
+
+; Detailed description
+; When updating this, update also description_file in [ruledit] section to match
+; description = ""
+
+; What capabilities ruleset provides for the scenarios.
+capabilities = ""
+
+[options]
+global_init_techs = ""
+global_init_buildings = ""
+
+[tileset]
+; If preferred tileset is set, clients that support the feature will suggest
+; using that tileset with the ruleset.
+; preferred = ""
+
+[soundset]
+; If preferred soundset is set, clients that support the feature will suggest
+; using that soundset with the ruleset.
+; preferred = ""
+
+[musicset]
+; If preferred musicset is set, clients that support the feature will suggest
+; using that musicset with the ruleset.
+; preferred = ""
+
+[civstyle]
+; Value added to city pollution
+base_pollution   = -20
+
+; Cost in luxuries of making one citizen happier
+happy_cost       = 2
+
+; Cost in food of upkeeping a single citizen
+food_cost        = 2
+
+; Parameters used to generalize the calculation of city granary size:
+;   if city_size <= num_inis:
+;     city_granary_size = (granary_food_ini[city_size] * foodbox / 100)
+;   if city_size > num_inis;
+;     city_granary_size = (granary_food_ini[num_inis] +
+;        granary_food_inc * (city_size - num_inis)) * foodbox / 100
+granary_food_ini	= 20
+granary_food_inc	= 10
+
+; City center minimum outputs
+min_city_center_food	= 1
+min_city_center_shield	= 1
+min_city_center_trade	= 0
+
+; Square of initial city radius
+init_city_radius_sq     = 5
+
+; Square of initially visible radius (true distance).
+init_vis_radius_sq	= 5
+
+; A base bribe cost, modified heavily by other factors
+base_bribe_cost  = 750
+
+; Barbarian leader ransom in gold. The ransom is taken from
+; the victim (typically a barbarian player), and it`s possible
+; they cannot pay this in full.
+ransom_gold      = 100
+
+; Number of veteran levels lost when upgrading a unit
+upgrade_veteran_loss     = 0
+
+; Number of veteran levels lost when auto-upgrading a unit
+autoupgrade_veteran_loss = 0
+
+; Whether player gets to select which terrain improvement to pillage.
+pillage_select           = TRUE
+
+; Whether one can steal a tech for which prereqs are not known
+tech_steal_allow_holes    = TRUE
+; Whether one can get a tech for which prereqs are not known via
+; diplomatic trading
+tech_trade_allow_holes    = TRUE
+; ...and whether one can lose a tech which is prereq for another known
+; tech via trade, if techlost_donor is nonzero
+tech_trade_loss_allow_holes = TRUE
+; Whether one can get a tech for which prereqs are not known via
+; parasite effect (Great Library)
+tech_parasite_allow_holes = TRUE
+; Whether one can lose a tech which is prereq for another known tech
+; due to negative bulbs, if techlossforgiveness allows loss
+tech_loss_allow_holes     = TRUE
+
+; Whether civil war is possible at all
+civil_war_enabled        = TRUE
+
+; How many percents each celebrating city affects chance of civil war
+civil_war_bonus_celebrating = 0
+
+; How many percents each unhappy city affects chance of civil war
+civil_war_bonus_unhappy     = 0
+
+; Comma separated list of things to happen, in addition to death
+; of owner, when gameloss unit dies
+; "CivilWar"   - Part of the empire remains, controlled by a new player
+; "Barbarians" - Depending on if there`s also "CivilWar", all or part
+;                or half of the dead players empire gets under barbarian
+;                control.
+; "Loot"       - Player who killed the gameloss unit gets loot:
+;                Partial map, gold, techs, cities
+gameloss_style           = ""
+
+; Whether units may safely paradrop to transport on non-native terrain
+paradrop_to_transport    = FALSE
+
+;Method of paying unit and improvement gold upkeep
+; "City" -   The player`s total gold must be non-negative after paying upkeep
+;            costs associated with each city. If for any city the player`s
+;            gold is negative, random buildings in the city are sold off. If
+;            the gold is still negative, then supported units with gold upkeep
+;            are disbanded.
+; "Mixed" -  In the first step, the player`s total gold must be non-negative
+;            after paying upkeep for all buildings within a city. If for any
+;            city the player`s gold is negative, random buildings in the city
+;            are sold off.
+;            In the second step, gold upkeep for all units is paid in a lump
+;            sum. If the player does not have enough gold, random units with
+;            gold upkeep are disbanded.
+; "Nation" - Gold upkeep for all buildings and units is paid in a lump sum
+;            after all cities have been processed. If the player does not
+;            have enough gold, random buildings from random cities are sold.
+;            If still more gold is needed, then random units with gold
+;            upkeep are disbanded.
+gold_upkeep_style = "City"
+
+; Whether also homeless units pay gold upkeep. Enabling requires that
+; gold_upkeep_style is not "City"
+homeless_gold_upkeep = FALSE
+
+; How many points of output one basic unit consists of. Typically you
+; want this to be some 10^n.
+output_granularity = 1
+
+; Is it possible to airlift even with zero airlift capacity when
+; airliftingstyle server setting has been set to unlimited airlifts?
+airlift_from_always_enabled = FALSE
+airlift_to_always_enabled = TRUE
+
+[wonder_visibility]
+; When do opponents know which city, if any, has built the Small Wonder
+; "Always"  - Information is always sent
+; "Never"   - Information is never sent
+; "Embassy" - Information is sent when team has an embassy with Wonder owner
+small_wonders = "Always"
+
+[illness]
+; Whether plagues (illness) are possible
+illness_on = FALSE
+
+; the base factor for illness (of percent)
+illness_base_factor = 25
+
+; minimum city size for illness
+illness_min_size = 3
+
+; factor for how much trading with a plagued city increases our city`s
+; chance for plague (in percent)
+illness_trade_infection = 50
+
+; factor for how much pollution within a city increases its chance for
+; plague (in percent)
+illness_pollution_factor = 50
+
+[incite_cost]
+; city_incite_cost =
+; total_factor * (city_size) *
+; (base_incite_cost + (units_cost) * unit_factor +
+;   (improvements_cost) * improvement_factor)
+;  / (distance * 100)
+; See city_incite_cost() for more details
+base_incite_cost = 1000
+improvement_factor = 1
+unit_factor = 2
+total_factor = 100
+
+[combat_rules]
+; If tired_attack is set to TRUE, units that attack with less than a single
+; move point (per move_fragments in terrain.ruleset) will have their attack
+; power reduced accordingly. For instance, if move_fragments = 3, a unit with
+; 2/3 move points will have attack power 2/3 of normal.
+; If this is set to FALSE units will attack with full strength even if they
+; have only fractional moves left.
+tired_attack = FALSE
+
+; With some rules it`s possible that neither side of a combat dies.
+; Set this to TRUE if unit should never gain veterancy from such a combat.
+only_killing_makes_veteran = FALSE
+
+; If either side of the fight is completely powerless, i.e., has
+; zero attack/defense power after modifiers, fight is not considered
+; a real fight. If this setting is enabled, nobody gets made veteran after
+; such a fight.
+only_real_fight_makes_veteran = FALSE
+
+; When this setting is enabled, chance of getting veterancy from a combat
+; gets modified by the strength of the opponent relative to the strength
+; of unit that might gain the veterancy.
+; When this setting is disabled, the modifier is always simply considered
+; to be 100%, i.e, the base veterancy chance from units.ruleset is used as is.
+; This affects both regular and diplomat combat.
+combat_odds_scaled_veterancy = FALSE
+
+; Does unit`s bombard rate get scaled down by how damaged it is.
+; Even after this unit gets at least one bombard round.
+damage_reduces_bombard_rate = TRUE
+
+; When the attacker has BadWallAttacker flag, and there`s
+; positive DefendBonus effect applied to the attack, attacker`s
+; firepower gets reduced to this value.
+; If firepower is already lower than this, it won`t be affected.
+low_firepower_badwallattacker = 1
+
+; When the defender has BadCityDefender flag, and it`s
+; defending on a city tile, attacker`s firepower is doubled
+; and defenders firepower is reduced to this value.
+; If firepower is already lower than this, it won`t be affected.
+low_firepower_pearl_harbour = 1
+
+; When the opponent has LowFirepower combat bonus against
+; a unit, it`s firepower is reduced to this value.
+; If firepower is already lower than this, it won`t be affected.
+low_firepower_combat_bonus = 1
+
+; When a unit capable of attacking NonNative tiles does such an
+; attack against NonNatBombardTgt unit, firepower of both sides
+; is reduced to this value.
+; If firepower is already lower than this, it won`t be affected.
+low_firepower_nonnat_bombard = 1
+
+; Percentage of population lost by a city after nuclear attak. If set to
+; 100 city is destroyed along with all the units. If set to 0 city does not
+; lose population. Any value below 50 means the city can never be
+; destroyed completely using nuclear.
+nuke_pop_loss_pct = 49
+
+; Percentage chance of a city defender surviving nuclear attack. When set
+; to 50 roughly half of defenders will survive nuclear attack. When set to
+; 0 no defenders will survive. When set to 100 all defenders will survive.
+nuke_defender_survival_chance_pct = 0
+
+[borders]
+; Base border radius from city.
+radius_sq_city = 0
+
+; Border radius square increased by this amount / point of city size
+size_effect    = 0
+
+; Difference between city workable area and area permanently claimed by
+; city (these tiles cannot be stolen by stronger border sources).
+; 0 means exactly city workable area is immune to border stealing.
+; Negative value means outer workable tiles can be stolen; highly negative
+; value (more than max city radius_sq) means any workable tile can be stolen.
+; If City_Radius_Sq is variable, so is the set of locked tiles; this is
+; a squared value, so the radius of the ring of tiles which are workable
+; but not locked (or vice versa) varies but the area is constant.
+radius_sq_city_permanent = 0
+
+[research]
+; Method of calculating technology costs
+;   "Civ I|II"      - Civ (I|II) style. Every new tech add base_tech_cost to
+;                     cost of next tech.
+;   "Classic"       - Cost of technology is:
+;                       base_tech_cost * (1 + reqs) * sqrt(1 + reqs) / 2
+;                     where reqs == number of requirement for tech, counted
+;                     recursively.
+;   "Classic+"      - Cost are read from tech.ruleset. Missing costs are
+;                     generated by style "Classic".
+;   "Experimental"  - Cost of technology is:
+;                       base_tech_cost * (reqs^2 / (1 + sqrt(sqrt(reqs + 1)))
+;                                         - 0.5)
+;                     where reqs == number of requirement for tech, counted
+;                     recursively. Initial techs` cost will be base_tech_cost.
+;   "Experimental+" - Cost are read from tech.ruleset. Missing costs are
+;                     generated by style "Experimental".
+;   "Linear"        - Cost of technology is:
+;                     base_tech_cost * reqs
+;                     where reqs == number of requirement for tech, counted
+;                     recursively.
+tech_cost_style = "Classic"
+
+; Base research cost. Used in tech cost styles where tech cost is generated.
+; In other words: used everywhere unless the cost of *all* techs are
+; specified and the tech cost style is "Experimental+" or "Classic+".
+base_tech_cost   = 20
+
+; Minimum research cost. This is applied for techs that have their cost
+; calculated by a formula. This is not applied for techs that have their
+; cost explicitly stated in the tech.ruleset.
+min_tech_cost    = 20
+
+; Technology leak from other civilizations
+; "None"           - No reduction of the technology cost.
+; "Embassies"      - Technology cost is reduced depending on the number of
+;                    players which already know the tech and you have an
+;                    embassy with.
+; "All Players"    - Technology cost is reduced depending on the number of
+;                    all players (human, AI and barbarians) which already
+;                    know the tech.
+; "Normal Players" - Technology cost is reduced depending on the number of
+;                    normal players (human and AI) which already know the
+;                    tech.
+tech_leakage = "None"
+
+; Method of paying tech upkeep
+; "None"   - no upkeep
+; "Basic"  - upkeep is calculated as:
+;     <Cost of technology> / tech_upkeep_divider - tech_upkeep_free
+; "Cities" - upkeep is calculated like "Basic", but multiplied by number of cities
+tech_upkeep_style = "None"
+
+; upkeep cost is divided by this value
+tech_upkeep_divider = 2000
+
+; Method of selecting techs given for free
+; "Goal"     - Towards player`s goal, random if no goal
+; "Random"   - Random researchable tech
+; "Cheapest" - Cheapest researchable tech, random among equal cost ones
+free_tech_method = "Goal"
+
+[culture]
+; Minimum culture points for cultural domination victory
+victory_min_points = 1000
+
+; How big lead relative to second best player is needed for victory
+victory_lead_pct   = 200
+
+; How much existing history grows each turn. This makes older history
+; of the same original value more valuable as newer history, as it has
+; gained more interest.
+history_interest_pml = 0
+
+; How much each culture point affects the migration
+; from/to the city. Each culture point count as this many permilles
+; of a migration point.
+migration_pml = 50
+
+[calendar]
+; Year in the beginning of the game
+start_year = 0
+
+; Year 1 instead of 0.
+skip_year_0 = FALSE
+
+; How many fragments each year has. In addition to this, "Turn_Fragments" effects are
+; needed to control fragment accumulation.
+; Value 0 here disables year advancement by fragment accumulation.
+fragments = 0
+
+; Calendar fragment names. If name is missing, only a fragment number +1 (so human readable
+; numbers begin from 1 and not 0) is shown.
+
+;fragment_name0 = _("Jan")
+;fragment_name1 = _("Feb")
+; ...
+
+; What labels are used for positive and negative years.
+; /* TRANS: year label (Common Era) */
+positive_label = _("CE")
+; /* TRANS: year label (Before Common Era) */
+negative_label = _("BCE")
+
+; /* <-- avoid gettext warnings
+;
+; Disaster types:
+;
+; name                    = translatable name as seen by user
+; reqs                    = requirements for disaster to happen (see effects.ruleset
+;                           and README.effects for help on requirements)
+; frequency               = how likely disaster is to occur
+; effects
+;   - "DestroyBuilding"   = Random building is destroyed
+;   - "ReducePopulation"  = Reduce city size by one unless it's already 1
+;   - "ReducePopDestroy"  = Reduce city size by one, possibly destroying the city
+;   - "EmptyFoodStock"    = Remove all food from food stock
+;   - "EmptyProdStock"    = Destroy current production
+;   - "Pollution"         = One tile surrounding city polluted
+;   - "Fallout"           = One tile surrounding city polluted with fallout
+;
+; */ <-- avoid gettext warnings
+
+; No disasters
+; [disaster_earthquake]
+; name = _("Earthquake")
+; frequency = 10
+; effects = "DestroyBuilding"
+
+
+; /* <-- avoid gettext warnings
+;
+; Achievement types:
+;
+; name                    = translatable name as seen by user
+; rule_name               = (optional) internal name for savegames, rulesets
+;                           etc; if not present, "name" is used for this
+;                           purpose too. Since the name used in savegames must
+;                           not change, if you want to rename an item after a
+;                           ruleset has been released, you should set
+;                           "rule_name" to the original value of "name".
+; type                    = What event grants the achievement to player.
+;                           See README.achievements for list of these types.
+; unique                  = If TRUE, only first one reaching the achievement will
+;                           get it. Defaults to TRUE.
+; value                   = Value to reach. Exact meaning of this depends on
+;                           achievement type.
+; culture                 = Amount of culture granted to player who gets achievement
+;                           granted.
+; first_msg               = Message shown to first player gaining the achievement
+; cons_msg                = Message shown to consecutive players gaining the achievement
+;
+; */ <-- avoid gettext warnings
+
+; No achievements
+; [achievement_entire_map]
+; name  = "Entire Map Known"
+; type  = "Map_Known"
+; value = 100
+
+;
+; Trade settings
+;
+; IN = international, IC = intercontinental.
+; For each of the trade route types:
+; "pct"        - Trade income %. If this is 0, trade route cannot be
+;                established at all
+; "cancelling" - What to do to previously established traderoutes when they
+;                turn illegal
+;                "Active"   - Keep them active (although they will only
+;                             provide nonzero income if illegal due to
+;                             trademindist rather than pct==0)
+;                "Inactive" - Keep them inactive
+;                "Cancel"   - Cancel them altogether
+; "bonus"      - One-time bonuses granted when traderoute established
+;                "None"     - No one-time bonus
+;                "Gold"     - Bonus to gold
+;                "Science"  - Bonus to research
+;                "Both"     - Bonus to gold and research
+;
+[trade]
+settings =
+  { "type", "pct", "cancelling", "bonus"
+    "National",   0, "Cancel", "None"
+    "NationalIC", 0, "Cancel", "None"
+    "IN",         0, "Cancel", "None"
+    "INIC",       0, "Cancel", "None"
+    "Ally",       0, "Cancel", "None"
+    "AllyIC",     0, "Cancel", "None"
+    "Enemy",      0, "Cancel", "None"
+    "EnemyIC",    0, "Cancel", "None"
+    "Team",       0, "Cancel", "None"
+    "TeamIC",     0, "Cancel", "None"
+  }
+
+; Minimum trade a trade route produces, as long as the good has nonzero income
+; for the relevant direction (from_pct / to_pct)
+min_trade_route_val = 0
+
+; Reveal the trade partner city on map.
+reveal_trade_partner = FALSE
+
+; When are goods for the trade route chosen.
+; "Leaving" - Goods to carry are assigned to unit when it`s built, or it changes homecity
+; "Arrival" - Goods are chosen when trade route is established, when unit arrives to destination
+goods_selection = "Leaving"
+
+; /* <-- avoid gettext warnings
+;
+; Goods types:
+;
+; name                    = translatable name as seen by user
+; rule_name               = (optional) internal name for savegames, rulesets
+;                           etc; if not present, "name" is used for this
+;                           purpose too. Since the name used in savegames must
+;                           not change, if you want to rename an item after a
+;                           ruleset has been released, you should set
+;                           "rule_name" to the original value of "name".
+; reqs                    = requirements for a city to provide goods (see effects.ruleset
+;                           and README.effects for help on requirements)
+; from_pct                = Income for the sending end of the trade route. Default is 100%
+;                           This value is applied to both ends of bidirectional routes.
+; to_pct                  = Income for the receiving end of the trade route. Default is 100%
+;                           This value is not used at all in case of bidirectional routes.
+; onetime_pct             = Onetime bonuses when traderoute is established. Default is 100%
+; flags
+;   - "Bidirectional"     = Trade route carrying the goods does not have "from" and "to"
+;                           ends, but both ends are considered the same.
+;   - "Depletes"          = Trade route gets cancelled when the source city cannot provide
+;                           goods any more. Bidirectional routes gets cancelled if either
+;                           one of the involved cities cannot provide goods.
+;   - "Self-Provided"     = Good requirement (in requirement lists of other rules)
+;                           is fullfilled also for the city exporting, or capable of exporting,
+;                           the good. Otherwise it would be true only for cities importing the
+;                           good from elsewhere.
+; helptext                = Optional help text string; should escape all raw
+;                           newlines so that xgettext parsing works
+;
+; */ <-- avoid gettext warnings
+
+[goods_good]
+name = _("Goods")
+
+
+; /* <-- avoid gettext warnings
+;
+; Clause types
+;
+; Clause types that are not listed here, are not enabled at all.
+;
+; type                   = Type of the clause, one of "Advance", "Gold", "Map", "Seamap",
+;                          "City", "Ceasefire", "Peace", "Alliance", "Vision", "Embassy",
+;                          "SharedTiles"
+; giver_reqs             = requirements that the giving side of the clause needs to fulfill
+;                          (see effects.ruleset and README.effects for help on requirements)
+; receiver_reqs          = requirements that the receiving side of the clause needs to fulfill
+;
+; */ <-- avoid gettext warnings
+
+; /* <-- avoid gettext warnings
+;Counter types
+;
+;name                    = translatable name as seen by user
+;rule_name               = (optional) internal name for savegames, rulesets
+;                          etc; if not present, "name" is used for this
+;                          purpose too. Since the name used in savegames must
+;                          not change, if you want to rename an item after a
+;                          ruleset has been released, you should set
+;                          "rule_name" to the original value of "name".
+;checkpoint              = Trigger value of the counter. When counter`s
+;                          value is at least this much, the "Counter" requirement
+;                          is fulfilled.
+;def                     = Initial value of the counter.
+;type                    = Behavior of the counter:
+;                          "Owned" - Increased each turn, zeroed when city changes owner
+; */ <-- avoid gettext warnings
+
+[counter_celebrating_1]
+name = "Cel1"
+def = 0
+checkpoint = 2
+type = "Celebration"
+range = "City"
+
+[playercolors]
+background.r = 86
+background.g = 86
+background.b = 86
+
+colorlist =
+    { "r", "g", "b"
+      255,   0,   0
+    }
+
+[teams]
+; freeciv optional team names definition.
+;
+; names =
+; _("Team 1"),
+; _("Team 2"),
+; _("Team 3"),
+; _("Team 4"),
+; etc...
+
+[settings]
+
+set =
+    { "name", "value", "lock"
+      "startunits", "c", TRUE
+    }
diff --git a/data/testy-slawomir/game.ruleset.new b/data/testy-slawomir/game.ruleset.new
new file mode 100644
index 0000000000..233e24c752
--- /dev/null
+++ b/data/testy-slawomir/game.ruleset.new
@@ -0,0 +1,603 @@
+; This is minimal game ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> game rules for Freeciv"
+options = "+Freeciv-ruleset-3.2-Devel-2022.Feb.02"
+format_version = 30
+
+; This section contains meta information for freeciv-ruledit to recreate the ruleset
+; file in a form wanted. These have no in-game effect whatsoever
+[ruledit]
+
+; Which file to read description in from.
+;description_file = ""
+
+[about]
+; Ruleset name
+name = _("Stub")
+
+; Versioning of the ruleset
+;version = ""
+
+; When about to migrate ruleset under a new name in the future version, set
+; alt_dir to the name of that future directory. Then savegames saved with this
+; version of freeciv can find the ruleset from the correct place when loading
+; the savegame to the future version.
+;alt_dir = ""
+
+; Summary of the ruleset
+summary = _("\
+This ruleset is meant to be used as starting point for \
+real rulesets, not playable ruleset in itself.\
+")
+
+; Detailed description
+; When updating this, update also description_file in [ruledit] section to match
+; description = ""
+
+; What capabilities ruleset provides for the scenarios.
+capabilities = ""
+
+[options]
+global_init_techs = ""
+global_init_buildings = ""
+
+[tileset]
+; If preferred tileset is set, clients that support the feature will suggest
+; using that tileset with the ruleset.
+; preferred = ""
+
+[soundset]
+; If preferred soundset is set, clients that support the feature will suggest
+; using that soundset with the ruleset.
+; preferred = ""
+
+[musicset]
+; If preferred musicset is set, clients that support the feature will suggest
+; using that musicset with the ruleset.
+; preferred = ""
+
+[civstyle]
+; Value added to city pollution
+base_pollution   = -20
+
+; Cost in luxuries of making one citizen happier
+happy_cost       = 2
+
+; Cost in food of upkeeping a single citizen
+food_cost        = 2
+
+; Parameters used to generalize the calculation of city granary size:
+;   if city_size <= num_inis:
+;     city_granary_size = (granary_food_ini[city_size] * foodbox / 100)
+;   if city_size > num_inis;
+;     city_granary_size = (granary_food_ini[num_inis] +
+;        granary_food_inc * (city_size - num_inis)) * foodbox / 100
+granary_food_ini	= 20
+granary_food_inc	= 10
+
+; City center minimum outputs
+min_city_center_food	= 1
+min_city_center_shield	= 1
+min_city_center_trade	= 0
+
+; Square of initial city radius
+init_city_radius_sq     = 5
+
+; Square of initially visible radius (true distance).
+init_vis_radius_sq	= 5
+
+; A base bribe cost, modified heavily by other factors
+base_bribe_cost  = 750
+
+; Barbarian leader ransom in gold. The ransom is taken from
+; the victim (typically a barbarian player), and it`s possible
+; they cannot pay this in full.
+ransom_gold      = 100
+
+; Number of veteran levels lost when upgrading a unit
+upgrade_veteran_loss     = 0
+
+; Number of veteran levels lost when auto-upgrading a unit
+autoupgrade_veteran_loss = 0
+
+; Whether player gets to select which terrain improvement to pillage.
+pillage_select           = TRUE
+
+; Whether one can steal a tech for which prereqs are not known
+tech_steal_allow_holes    = TRUE
+; Whether one can get a tech for which prereqs are not known via
+; diplomatic trading
+tech_trade_allow_holes    = TRUE
+; ...and whether one can lose a tech which is prereq for another known
+; tech via trade, if techlost_donor is nonzero
+tech_trade_loss_allow_holes = TRUE
+; Whether one can get a tech for which prereqs are not known via
+; parasite effect (Great Library)
+tech_parasite_allow_holes = TRUE
+; Whether one can lose a tech which is prereq for another known tech
+; due to negative bulbs, if techlossforgiveness allows loss
+tech_loss_allow_holes     = TRUE
+
+; Whether civil war is possible at all
+civil_war_enabled        = TRUE
+
+; How many percents each celebrating city affects chance of civil war
+civil_war_bonus_celebrating = 0
+
+; How many percents each unhappy city affects chance of civil war
+civil_war_bonus_unhappy     = 0
+
+; Comma separated list of things to happen, in addition to death
+; of owner, when gameloss unit dies
+; "CivilWar"   - Part of the empire remains, controlled by a new player
+; "Barbarians" - Depending on if there`s also "CivilWar", all or part
+;                or half of the dead players empire gets under barbarian
+;                control.
+; "Loot"       - Player who killed the gameloss unit gets loot:
+;                Partial map, gold, techs, cities
+gameloss_style           = ""
+
+; Whether units may safely paradrop to transport on non-native terrain
+paradrop_to_transport    = FALSE
+
+;Method of paying unit and improvement gold upkeep
+; "City" -   The player`s total gold must be non-negative after paying upkeep
+;            costs associated with each city. If for any city the player`s
+;            gold is negative, random buildings in the city are sold off. If
+;            the gold is still negative, then supported units with gold upkeep
+;            are disbanded.
+; "Mixed" -  In the first step, the player`s total gold must be non-negative
+;            after paying upkeep for all buildings within a city. If for any
+;            city the player`s gold is negative, random buildings in the city
+;            are sold off.
+;            In the second step, gold upkeep for all units is paid in a lump
+;            sum. If the player does not have enough gold, random units with
+;            gold upkeep are disbanded.
+; "Nation" - Gold upkeep for all buildings and units is paid in a lump sum
+;            after all cities have been processed. If the player does not
+;            have enough gold, random buildings from random cities are sold.
+;            If still more gold is needed, then random units with gold
+;            upkeep are disbanded.
+gold_upkeep_style = "City"
+
+; Whether also homeless units pay gold upkeep. Enabling requires that
+; gold_upkeep_style is not "City"
+homeless_gold_upkeep = FALSE
+
+; How many points of output one basic unit consists of. Typically you
+; want this to be some 10^n.
+output_granularity = 1
+
+; Is it possible to airlift even with zero airlift capacity when
+; airliftingstyle server setting has been set to unlimited airlifts?
+airlift_from_always_enabled = FALSE
+airlift_to_always_enabled = TRUE
+
+[wonder_visibility]
+; When do opponents know which city, if any, has built the Small Wonder
+; "Always"  - Information is always sent
+; "Never"   - Information is never sent
+; "Embassy" - Information is sent when team has an embassy with Wonder owner
+small_wonders = "Always"
+
+[illness]
+; Whether plagues (illness) are possible
+illness_on = FALSE
+
+; the base factor for illness (of percent)
+illness_base_factor = 25
+
+; minimum city size for illness
+illness_min_size = 3
+
+; factor for how much trading with a plagued city increases our city`s
+; chance for plague (in percent)
+illness_trade_infection = 50
+
+; factor for how much pollution within a city increases its chance for
+; plague (in percent)
+illness_pollution_factor = 50
+
+[incite_cost]
+; city_incite_cost =
+; total_factor * (city_size) *
+; (base_incite_cost + (units_cost) * unit_factor +
+;   (improvements_cost) * improvement_factor)
+;  / (distance * 100)
+; See city_incite_cost() for more details
+base_incite_cost = 1000
+improvement_factor = 1
+unit_factor = 2
+total_factor = 100
+
+[combat_rules]
+; If tired_attack is set to TRUE, units that attack with less than a single
+; move point (per move_fragments in terrain.ruleset) will have their attack
+; power reduced accordingly. For instance, if move_fragments = 3, a unit with
+; 2/3 move points will have attack power 2/3 of normal.
+; If this is set to FALSE units will attack with full strength even if they
+; have only fractional moves left.
+tired_attack = FALSE
+
+; With some rules it`s possible that neither side of a combat dies.
+; Set this to TRUE if unit should never gain veterancy from such a combat.
+only_killing_makes_veteran = FALSE
+
+; If either side of the fight is completely powerless, i.e., has
+; zero attack/defense power after modifiers, fight is not considered
+; a real fight. If this setting is enabled, nobody gets made veteran after
+; such a fight.
+only_real_fight_makes_veteran = FALSE
+
+; When this setting is enabled, chance of getting veterancy from a combat
+; gets modified by the strength of the opponent relative to the strength
+; of unit that might gain the veterancy.
+; When this setting is disabled, the modifier is always simply considered
+; to be 100%, i.e, the base veterancy chance from units.ruleset is used as is.
+; This affects both regular and diplomat combat.
+combat_odds_scaled_veterancy = FALSE
+
+; Does unit`s bombard rate get scaled down by how damaged it is.
+; Even after this unit gets at least one bombard round.
+damage_reduces_bombard_rate = TRUE
+
+; When the attacker has BadWallAttacker flag, and there`s
+; positive DefendBonus effect applied to the attack, attacker`s
+; firepower gets reduced to this value.
+; If firepower is already lower than this, it won`t be affected.
+low_firepower_badwallattacker = 1
+
+; When the defender has BadCityDefender flag, and it`s
+; defending on a city tile, attacker`s firepower is doubled
+; and defenders firepower is reduced to this value.
+; If firepower is already lower than this, it won`t be affected.
+low_firepower_pearl_harbour = 1
+
+; When the opponent has LowFirepower combat bonus against
+; a unit, it`s firepower is reduced to this value.
+; If firepower is already lower than this, it won`t be affected.
+low_firepower_combat_bonus = 1
+
+; When a unit capable of attacking NonNative tiles does such an
+; attack against NonNatBombardTgt unit, firepower of both sides
+; is reduced to this value.
+; If firepower is already lower than this, it won`t be affected.
+low_firepower_nonnat_bombard = 1
+
+; Percentage of population lost by a city after nuclear attak. If set to
+; 100 city is destroyed along with all the units. If set to 0 city does not
+; lose population. Any value below 50 means the city can never be
+; destroyed completely using nuclear.
+nuke_pop_loss_pct = 49
+
+; Percentage chance of a city defender surviving nuclear attack. When set
+; to 50 roughly half of defenders will survive nuclear attack. When set to
+; 0 no defenders will survive. When set to 100 all defenders will survive.
+nuke_defender_survival_chance_pct = 0
+
+[borders]
+; Base border radius from city.
+radius_sq_city = 0
+
+; Border radius square increased by this amount / point of city size
+size_effect    = 0
+
+; Difference between city workable area and area permanently claimed by
+; city (these tiles cannot be stolen by stronger border sources).
+; 0 means exactly city workable area is immune to border stealing.
+; Negative value means outer workable tiles can be stolen; highly negative
+; value (more than max city radius_sq) means any workable tile can be stolen.
+; If City_Radius_Sq is variable, so is the set of locked tiles; this is
+; a squared value, so the radius of the ring of tiles which are workable
+; but not locked (or vice versa) varies but the area is constant.
+radius_sq_city_permanent = 0
+
+[research]
+; Method of calculating technology costs
+;   "Civ I|II"      - Civ (I|II) style. Every new tech add base_tech_cost to
+;                     cost of next tech.
+;   "Classic"       - Cost of technology is:
+;                       base_tech_cost * (1 + reqs) * sqrt(1 + reqs) / 2
+;                     where reqs == number of requirement for tech, counted
+;                     recursively.
+;   "Classic+"      - Cost are read from tech.ruleset. Missing costs are
+;                     generated by style "Classic".
+;   "Experimental"  - Cost of technology is:
+;                       base_tech_cost * (reqs^2 / (1 + sqrt(sqrt(reqs + 1)))
+;                                         - 0.5)
+;                     where reqs == number of requirement for tech, counted
+;                     recursively. Initial techs` cost will be base_tech_cost.
+;   "Experimental+" - Cost are read from tech.ruleset. Missing costs are
+;                     generated by style "Experimental".
+;   "Linear"        - Cost of technology is:
+;                     base_tech_cost * reqs
+;                     where reqs == number of requirement for tech, counted
+;                     recursively.
+tech_cost_style = "Classic"
+
+; Base research cost. Used in tech cost styles where tech cost is generated.
+; In other words: used everywhere unless the cost of *all* techs are
+; specified and the tech cost style is "Experimental+" or "Classic+".
+base_tech_cost   = 20
+
+; Minimum research cost. This is applied for techs that have their cost
+; calculated by a formula. This is not applied for techs that have their
+; cost explicitly stated in the tech.ruleset.
+min_tech_cost    = 20
+
+; Technology leak from other civilizations
+; "None"           - No reduction of the technology cost.
+; "Embassies"      - Technology cost is reduced depending on the number of
+;                    players which already know the tech and you have an
+;                    embassy with.
+; "All Players"    - Technology cost is reduced depending on the number of
+;                    all players (human, AI and barbarians) which already
+;                    know the tech.
+; "Normal Players" - Technology cost is reduced depending on the number of
+;                    normal players (human and AI) which already know the
+;                    tech.
+tech_leakage = "None"
+
+; Method of paying tech upkeep
+; "None"   - no upkeep
+; "Basic"  - upkeep is calculated as:
+;     <Cost of technology> / tech_upkeep_divider - tech_upkeep_free
+; "Cities" - upkeep is calculated like "Basic", but multiplied by number of cities
+tech_upkeep_style = "None"
+
+; upkeep cost is divided by this value
+tech_upkeep_divider = 2000
+
+; Method of selecting techs given for free
+; "Goal"     - Towards player`s goal, random if no goal
+; "Random"   - Random researchable tech
+; "Cheapest" - Cheapest researchable tech, random among equal cost ones
+free_tech_method = "Goal"
+
+[culture]
+; Minimum culture points for cultural domination victory
+victory_min_points = 1000
+
+; How big lead relative to second best player is needed for victory
+victory_lead_pct   = 200
+
+; How much existing history grows each turn. This makes older history
+; of the same original value more valuable as newer history, as it has
+; gained more interest.
+history_interest_pml = 0
+
+; How much each culture point affects the migration
+; from/to the city. Each culture point count as this many permilles
+; of a migration point.
+migration_pml = 50
+
+[calendar]
+; Year in the beginning of the game
+start_year = 0
+
+; Year 1 instead of 0.
+skip_year_0 = FALSE
+
+; How many fragments each year has. In addition to this, "Turn_Fragments" effects are
+; needed to control fragment accumulation.
+; Value 0 here disables year advancement by fragment accumulation.
+fragments = 0
+
+; Calendar fragment names. If name is missing, only a fragment number +1 (so human readable
+; numbers begin from 1 and not 0) is shown.
+
+;fragment_name0 = _("Jan")
+;fragment_name1 = _("Feb")
+; ...
+
+; What labels are used for positive and negative years.
+; /* TRANS: year label (Common Era) */
+positive_label = _("CE")
+; /* TRANS: year label (Before Common Era) */
+negative_label = _("BCE")
+
+; /* <-- avoid gettext warnings
+;
+; Disaster types:
+;
+; name                    = translatable name as seen by user
+; reqs                    = requirements for disaster to happen (see effects.ruleset
+;                           and README.effects for help on requirements)
+; frequency               = how likely disaster is to occur
+; effects
+;   - "DestroyBuilding"   = Random building is destroyed
+;   - "ReducePopulation"  = Reduce city size by one unless it's already 1
+;   - "ReducePopDestroy"  = Reduce city size by one, possibly destroying the city
+;   - "EmptyFoodStock"    = Remove all food from food stock
+;   - "EmptyProdStock"    = Destroy current production
+;   - "Pollution"         = One tile surrounding city polluted
+;   - "Fallout"           = One tile surrounding city polluted with fallout
+;
+; */ <-- avoid gettext warnings
+
+; No disasters
+; [disaster_earthquake]
+; name = _("Earthquake")
+; frequency = 10
+; effects = "DestroyBuilding"
+
+
+; /* <-- avoid gettext warnings
+;
+; Achievement types:
+;
+; name                    = translatable name as seen by user
+; rule_name               = (optional) internal name for savegames, rulesets
+;                           etc; if not present, "name" is used for this
+;                           purpose too. Since the name used in savegames must
+;                           not change, if you want to rename an item after a
+;                           ruleset has been released, you should set
+;                           "rule_name" to the original value of "name".
+; type                    = What event grants the achievement to player.
+;                           See README.achievements for list of these types.
+; unique                  = If TRUE, only first one reaching the achievement will
+;                           get it. Defaults to TRUE.
+; value                   = Value to reach. Exact meaning of this depends on
+;                           achievement type.
+; culture                 = Amount of culture granted to player who gets achievement
+;                           granted.
+; first_msg               = Message shown to first player gaining the achievement
+; cons_msg                = Message shown to consecutive players gaining the achievement
+;
+; */ <-- avoid gettext warnings
+
+; No achievements
+; [achievement_entire_map]
+; name  = "Entire Map Known"
+; type  = "Map_Known"
+; value = 100
+
+;
+; Trade settings
+;
+; IN = international, IC = intercontinental.
+; For each of the trade route types:
+; "pct"        - Trade income %. If this is 0, trade route cannot be
+;                established at all
+; "cancelling" - What to do to previously established traderoutes when they
+;                turn illegal
+;                "Active"   - Keep them active (although they will only
+;                             provide nonzero income if illegal due to
+;                             trademindist rather than pct==0)
+;                "Inactive" - Keep them inactive
+;                "Cancel"   - Cancel them altogether
+; "bonus"      - One-time bonuses granted when traderoute established
+;                "None"     - No one-time bonus
+;                "Gold"     - Bonus to gold
+;                "Science"  - Bonus to research
+;                "Both"     - Bonus to gold and research
+;
+[trade]
+settings =
+  { "type", "pct", "cancelling", "bonus"
+    "National",   0, "Cancel", "None"
+    "NationalIC", 0, "Cancel", "None"
+    "IN",         0, "Cancel", "None"
+    "INIC",       0, "Cancel", "None"
+    "Ally",       0, "Cancel", "None"
+    "AllyIC",     0, "Cancel", "None"
+    "Enemy",      0, "Cancel", "None"
+    "EnemyIC",    0, "Cancel", "None"
+    "Team",       0, "Cancel", "None"
+    "TeamIC",     0, "Cancel", "None"
+  }
+
+; Minimum trade a trade route produces, as long as the good has nonzero income
+; for the relevant direction (from_pct / to_pct)
+min_trade_route_val = 0
+
+; Reveal the trade partner city on map.
+reveal_trade_partner = FALSE
+
+; When are goods for the trade route chosen.
+; "Leaving" - Goods to carry are assigned to unit when it`s built, or it changes homecity
+; "Arrival" - Goods are chosen when trade route is established, when unit arrives to destination
+goods_selection = "Leaving"
+
+; /* <-- avoid gettext warnings
+;
+; Goods types:
+;
+; name                    = translatable name as seen by user
+; rule_name               = (optional) internal name for savegames, rulesets
+;                           etc; if not present, "name" is used for this
+;                           purpose too. Since the name used in savegames must
+;                           not change, if you want to rename an item after a
+;                           ruleset has been released, you should set
+;                           "rule_name" to the original value of "name".
+; reqs                    = requirements for a city to provide goods (see effects.ruleset
+;                           and README.effects for help on requirements)
+; from_pct                = Income for the sending end of the trade route. Default is 100%
+;                           This value is applied to both ends of bidirectional routes.
+; to_pct                  = Income for the receiving end of the trade route. Default is 100%
+;                           This value is not used at all in case of bidirectional routes.
+; onetime_pct             = Onetime bonuses when traderoute is established. Default is 100%
+; flags
+;   - "Bidirectional"     = Trade route carrying the goods does not have "from" and "to"
+;                           ends, but both ends are considered the same.
+;   - "Depletes"          = Trade route gets cancelled when the source city cannot provide
+;                           goods any more. Bidirectional routes gets cancelled if either
+;                           one of the involved cities cannot provide goods.
+;   - "Self-Provided"     = Good requirement (in requirement lists of other rules)
+;                           is fullfilled also for the city exporting, or capable of exporting,
+;                           the good. Otherwise it would be true only for cities importing the
+;                           good from elsewhere.
+; helptext                = Optional help text string; should escape all raw
+;                           newlines so that xgettext parsing works
+;
+; */ <-- avoid gettext warnings
+
+[goods_good]
+name = _("Goods")
+
+
+; /* <-- avoid gettext warnings
+;
+; Clause types
+;
+; Clause types that are not listed here, are not enabled at all.
+;
+; type                   = Type of the clause, one of "Advance", "Gold", "Map", "Seamap",
+;                          "City", "Ceasefire", "Peace", "Alliance", "Vision", "Embassy",
+;                          "SharedTiles"
+; giver_reqs             = requirements that the giving side of the clause needs to fulfill
+;                          (see effects.ruleset and README.effects for help on requirements)
+; receiver_reqs          = requirements that the receiving side of the clause needs to fulfill
+;
+; */ <-- avoid gettext warnings
+
+; /* <-- avoid gettext warnings
+;Counter types
+;
+;name                    = translatable name as seen by user
+;rule_name               = (optional) internal name for savegames, rulesets
+;                          etc; if not present, "name" is used for this
+;                          purpose too. Since the name used in savegames must
+;                          not change, if you want to rename an item after a
+;                          ruleset has been released, you should set
+;                          "rule_name" to the original value of "name".
+;checkpoint              = Trigger value of the counter. When counter`s
+;                          value is at least this much, the "Counter" requirement
+;                          is fulfilled.
+;def                     = Initial value of the counter.
+;type                    = Behavior of the counter:
+;                          "Owned" - Increased each turn, zeroed when city changes owner
+;                          "Celebraring" - Increased each celebrates turn. In case city
+;                          do not celebrates, counter is zeroed
+;                          "Disorder" - Increased each turn city is in disorder state. In
+;                          case riots are eliminated, value is zeroed.
+; */ <-- avoid gettext warnings
+
+[playercolors]
+background.r = 86
+background.g = 86
+background.b = 86
+
+colorlist =
+    { "r", "g", "b"
+      255,   0,   0
+    }
+
+[teams]
+; freeciv optional team names definition.
+;
+; names =
+; _("Team 1"),
+; _("Team 2"),
+; _("Team 3"),
+; _("Team 4"),
+; etc...
+
+[settings]
+
+set =
+    { "name", "value", "lock"
+      "startunits", "c", TRUE
+    }
diff --git a/data/testy-slawomir/governments.ruleset b/data/testy-slawomir/governments.ruleset
new file mode 100644
index 0000000000..ea555ff283
--- /dev/null
+++ b/data/testy-slawomir/governments.ruleset
@@ -0,0 +1,111 @@
+; This is minimal governments ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> governments data for Freeciv"
+options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
+format_version = 40
+
+[governments]
+during_revolution = "Anarchy"
+
+; /* <-- avoid gettext warnings
+;
+; Below: The individual government types, one per section.
+;
+; The actual tag used (the * in [government_*]) does not matter, except
+; it must be unique within this file, and it may be used in debug
+; output when reading this file.
+;
+; For the "official" rulesets, the order of these sections should not
+; be changed because that would break backward compatibility with
+; savegames.  (In particular, if Fundamentalism is added to default
+; ruleset, should be added at end.)
+;
+; Notes on fields:
+;
+; name         = translatable name as seen by user
+; rule_name    = (optional) internal name for savegames, rulesets etc; if
+;                not present, "name" is used for this purpose too. Since
+;                the name used in savegames must not change, if you want
+;                to rename an item after a ruleset has been released, you
+;                should set "rule_name" to the original value of "name".
+; reqs         = requirements for this government (see README.effects)
+; graphic      = tag specifing preferred graphic
+; graphic_alt  = alternate graphics tag if preferred is not found;
+;                should be a standard tag if preferred is not;
+;                otherwise may be "-"
+; ai_better    = AI will not consider this government for use if the
+;                government listed here is available
+; ruler_male_title   = The default male ruler title for the government type.
+;                      It's a format string where name of the ruler is marked
+;                      by '%s'.
+;                      Individual nations may override this by their
+;                      own title.
+; ruler_female_title = The default female ruler title for the government type.
+;                      See above ruler_male_title.
+; helptext     = optional help text string; should escape all raw newlines
+;                so that xgettext parsing works
+;
+; */ <-- avoid gettext warnings
+
+;------------------------------------------------------------------------
+[government_anarchy]
+
+name        = _("Anarchy")
+; No reqs
+graphic     = "gov.anarchy"
+graphic_alt = "-"
+
+ruler_male_title = _("Usurper %s")
+ruler_female_title = _("?female:Usurper %s")
+
+helptext = _("\
+Anarchy happens between government changes.\
+")
+
+;------------------------------------------------------------------------
+[government_generic]
+
+name        = _("Generic")
+reqs =
+   { "type", "name", "range"
+; No requirements
+   }
+graphic     = "gov.despotism"
+graphic_alt = "-"
+
+ruler_male_title = _("Leader %s")
+ruler_female_title = _("Leader %s")
+
+helptext = _("\
+  This is the only available form of government.\
+")
+
+; /* <-- avoid gettext warnings
+;
+; Multipliers (aka policies)
+;
+; name                    = translatable name as seen by user
+; rule_name               = (optional) internal name for savegames, rulesets
+;                           etc; if not present, "name" is used for this
+;                           purpose too. Since the name used in savegames must
+;                           not change, if you want to rename an item after a
+;                           ruleset has been released, you should set
+;                           "rule_name" to the original value of "name".
+; default                 = default value (as presented in UI)
+; start                   = minimum value (as presented in UI)
+; stop                    = maximum value (as presented in UI)
+; step                    = minimum increase/decrease (as presented in UI)
+; offset                  = offset/factor control how UI values are turned
+; factor                  = into effect values for use in effects.ruleset.
+;                           effect_value = (ui_value + offset) * (factor/100)
+;                           Optional; by default offset=0, factor=100, so
+;                           that UI values are used as-is.
+; minimum_turns           = how often multiplier can be changed, or: how long one is stuck
+;                           with the given value after changing to it
+; reqs                    = requirements for adjusting this policy (see README.effects)
+; helptext                = optional help text string; should escape all raw
+;                           newlines so that xgettext parsing works
+;
+; */ <-- avoid gettext warnings
diff --git a/data/testy-slawomir/nations.ruleset b/data/testy-slawomir/nations.ruleset
new file mode 100644
index 0000000000..5457792c62
--- /dev/null
+++ b/data/testy-slawomir/nations.ruleset
@@ -0,0 +1,119 @@
+; This is minimal nations ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> nations data for Freeciv"
+options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
+format_version = 40
+
+; This section contains meta information for freeciv-ruledit and freeciv-ruleup
+; to recreate the ruleset file in a form wanted.
+; These have no in-game effect whatsoever.
+[ruledit]
+
+; Nationlist to add include statement for. If this entry is omitted, all the nations
+; will be saved to nations.ruleset itself.
+;nationlist = ""
+
+; List of nations to embed to main nations.ruleset despite separate nationlist
+; being used for other nations.
+;embedded_nations = ""
+
+[default_traits]
+; Default values for the AI traits. These are used if nation specific
+; value for some trait has not been used. If these default too are
+; not defined, the ultimate default is 50.
+; <trait>_min and <trait>_max give the range from which the trait value
+; is randomly chosen for a given AI player unless 'traitdistribution'
+; server setting is 'FIXED'
+; <trait>_default is the exaxt trait value used when 'traitdistribution'
+; is 'FIXED'. If <trait>_default has not been given, it's set to the
+; midpoint between <trait>_min and <trait>_max.
+
+; Value of trait "expansionist" defines how much AI wants to settle new territory.
+;expansionist_min = 50
+;expansionist_max = 50
+;expansionist_default = 50
+
+; Value of trait "trader" defines how much AI wants to establish trade routes.
+;trader_min       = 50
+;trader_max       = 50
+;trader_default   = 50
+
+; Value of trait "aggressive" defines how easily AI declares war.
+;aggressive_min   = 50
+;aggressive_max   = 50
+;aggressive_default = 50
+
+; Value of trait "builder" defines how much AI wants to build buildings
+;builder_min = 50
+;builder_max = 50
+;builder_default = 50
+
+; Descriptions of nation sets
+; These are self-contained subsets of the available nations; one of these
+; can be chosen in pregame with the "nationset" option. No nations
+; outside the selected subset will be used.
+; The first set defined is the one that is used by default. It is mandatory
+; to have at least one, but if there is only one, it will be kept out of
+; the user`s way.
+; name 		= Translatable name of the set presented in the UI.
+; rule_name     = Unique persistent name; this is also visible to users as
+;                 the value of the "nationset" server option, and presented
+;                 in "/list nationsets". It should thus be short, in lower
+;                 case, and not contain spaces or punctuation.
+;                 The same saved "nationset" setting may be used for multiple
+;                 rulesets, so if your custom ruleset has any set which
+;                 contains all of its nations, it is useful to give it a
+;                 rule_name of "all" so that users can specify that they
+;                 always want the choice of all available nations by
+;                 default.
+; description   = Optional short user description of this set.
+
+[nset_full]
+name = _("?nationset:Full")
+rule_name = "all"
+
+; Descriptions of nation groups
+; These are more cosmetic than sets; they affect the "pick nation" dialog,
+; random nation selection, and possibly ruleset behaviour.
+; It`s OK to not define any nation groups at all.
+; name 		= name of the group (used adjectivally)
+; hidden        = TRUE to not include this group in the "pick nation" dialog
+;                 (for instance if it's for use in a NationGroup requirement).
+;                 Default FALSE.
+; match		= How much the AI will try to select a nation in the same
+;                 group
+
+[ngroup_generic]
+name = _("?nationgroup:Generic")
+match = 2
+
+[compatibility]
+; Initial government for all the nations that do not
+; have it explicitly defined
+default_government = "Generic"
+
+; Declare which governments etc the nations may refer to.
+; If a referenced game identifier is not on these
+; lists, it will cause an error, to allow typos to be spotted.
+
+allowed_govs =
+  "Anarchy", "Generic"
+allowed_terrains =
+  "Ocean", "Generic"
+allowed_styles =
+  "Generic"
+
+; Below: nations data loaded from ruleset files for
+; all nations available. If you want to have more
+; nations, just add the path to your ruleset to this list.
+;
+; See doc/README.nations for information on how to
+; create nation rulesets, including style guidelines.
+
+*include "testy-slawomir/nations/generic.ruleset"
+*include "testy-slawomir/nations/generic2.ruleset"
+
+; Must have a barbarian nations
+*include "testy-slawomir/nations/barbarian.ruleset"
diff --git a/data/testy-slawomir/nations/Makefile.am b/data/testy-slawomir/nations/Makefile.am
new file mode 100644
index 0000000000..ab14ea96be
--- /dev/null
+++ b/data/testy-slawomir/nations/Makefile.am
@@ -0,0 +1,10 @@
+## Process this file with automake to produce Makefile.in
+
+## Override automake so that "make install" puts these in proper place:
+pkgdatadir = $(datadir)/$(PACKAGE)/stub/nations
+
+pkgdata_DATA =          	\
+	barbarian.ruleset	\
+	generic.ruleset
+
+EXTRA_DIST = $(pkgdata_DATA)
diff --git a/data/testy-slawomir/nations/barbarian.ruleset b/data/testy-slawomir/nations/barbarian.ruleset
new file mode 100644
index 0000000000..8c05f3c12b
--- /dev/null
+++ b/data/testy-slawomir/nations/barbarian.ruleset
@@ -0,0 +1,22 @@
+[nation_barbarian]
+
+name=_("Barbarian")
+plural=_("?plural:Barbarians")
+legend=_("Since the dawn of civilization, barbarians have been a threat to\
+ cultured peoples everywhere.")
+leaders = { "name", "sex"
+ "Barbarian", "male"
+}
+
+flag     = "barbarian"
+flag_alt = "-"
+style    = "Generic"
+
+init_techs=""
+init_buildings=""
+init_units=""
+
+cities = "Barbaricum"
+
+is_playable = FALSE
+barbarian_type = "LandAndSea"
diff --git a/data/testy-slawomir/nations/generic.ruleset b/data/testy-slawomir/nations/generic.ruleset
new file mode 100644
index 0000000000..9e9c48fd0e
--- /dev/null
+++ b/data/testy-slawomir/nations/generic.ruleset
@@ -0,0 +1,22 @@
+[nation_generic]
+
+name=_("People")
+plural=_("?plural:People")
+groups="Generic"
+legend=_("This is the only nation you can select.\
+")
+leaders = { "name", "sex"
+ "Generic", "male"
+}
+
+flag     = "aborigines"
+flag_alt = "-"
+style    = "Generic"
+
+init_techs=""
+init_buildings=""
+init_units=""
+; civilwar_nations = ""
+
+cities =
+ "Generic"
diff --git a/data/testy-slawomir/nations/generic2.ruleset b/data/testy-slawomir/nations/generic2.ruleset
new file mode 100644
index 0000000000..fd4ee78980
--- /dev/null
+++ b/data/testy-slawomir/nations/generic2.ruleset
@@ -0,0 +1,22 @@
+[nation_generic2]
+
+name=_("Monster")
+plural=_("?plural:Monsters")
+groups="Generic"
+legend=_("This is the only nation you can select.\
+")
+leaders = { "name", "sex"
+ "Generic", "male"
+}
+
+flag     = "poland"
+flag_alt = "-"
+style    = "Generic"
+
+init_techs=""
+init_buildings=""
+init_units=""
+; civilwar_nations = ""
+
+cities =
+ "Generic"
diff --git a/data/testy-slawomir/parser.lua b/data/testy-slawomir/parser.lua
new file mode 100644
index 0000000000..ea4bf8c532
--- /dev/null
+++ b/data/testy-slawomir/parser.lua
@@ -0,0 +1,13 @@
+-- Freeciv - Copyright (C) 2007 - The Freeciv Project
+--   This program is free software; you can redistribute it and/or modify
+--   it under the terms of the GNU General Public License as published by
+--   the Free Software Foundation; either version 2, or (at your option)
+--   any later version.
+--
+--   This program is distributed in the hope that it will be useful,
+--   but WITHOUT ANY WARRANTY; without even the implied warranty of
+--   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--   GNU General Public License for more details.
+
+-- This file is for lua-functionality for parsing luadata.txt
+-- of this ruleset.
diff --git a/data/testy-slawomir/script.lua b/data/testy-slawomir/script.lua
new file mode 100644
index 0000000000..f0bdf05caa
--- /dev/null
+++ b/data/testy-slawomir/script.lua
@@ -0,0 +1,15 @@
+-- Freeciv - Copyright (C) 2007 - The Freeciv Project
+--   This program is free software; you can redistribute it and/or modify
+--   it under the terms of the GNU General Public License as published by
+--   the Free Software Foundation; either version 2, or (at your option)
+--   any later version.
+--
+--   This program is distributed in the hope that it will be useful,
+--   but WITHOUT ANY WARRANTY; without even the implied warranty of
+--   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--   GNU General Public License for more details.
+
+-- This file is for lua-functionality that is specific to a given
+-- ruleset. When freeciv loads a ruleset, it also loads script
+-- file called 'default.lua'. The one loaded if your ruleset
+-- does not provide an override is default/default.lua.
diff --git a/data/testy-slawomir/styles.ruleset b/data/testy-slawomir/styles.ruleset
new file mode 100644
index 0000000000..9570ca6bb1
--- /dev/null
+++ b/data/testy-slawomir/styles.ruleset
@@ -0,0 +1,71 @@
+; This is minimal styles ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> nation theme data for Freeciv"
+options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
+format_version = 40
+
+; /* <-- avoid gettext warnings
+;
+; Nation styles
+;
+; name          = translatable name as seen by user
+; rule_name     = (optional) internal name for savegames, rulesets etc; if
+;                 not present, "name" is used for this purpose too. Since
+;                 the name used in savegames must not change, if you want
+;                 to rename an item after a ruleset has been released, you
+;                 should set "rule_name" to the original value of "name".
+;
+; */ <-- avoid gettext warnings
+
+[style_generic]
+name = _("?style:Generic")
+
+; /* <-- avoid gettext warnings
+;
+; City styles define the way cities are drawn
+;
+; name             = translatable name as seen by user
+; rule_name        = (optional) internal name for savegames, rulesets etc; if
+;                    not present, "name" is used for this purpose too. Since
+;                    the name used in savegames must not change, if you want
+;                    to rename an item after a ruleset has been released, you
+;                    should set "rule_name" to the original value of "name".
+; graphic          = group of tiles to use, see cities spec for
+;                    more info on city tiles
+; citizens_graphic = group of citizens tiles to use, see citizens/small
+;                    spec for more info on citizens tiles
+; reqs             = requirements for this city style (see README.effects)
+;
+; */ <-- avoid gettext warnings
+
+[citystyle_generic]
+name                 = _("?citystyle:Generic")
+graphic              = "city.classical"
+graphic_alt          = "-"
+citizens_graphic     = "ancient"
+reqs = { "type", "name", "range"
+         "Style", "Generic", "Player"
+       }
+
+; /* <-- avoid gettext warnings
+;
+; Music styles
+;
+; Order is important. The last one for which activation requirements
+; are fulfilled is the one that plays.
+;
+; music_peaceful = Music to play when nation in peaceful mood
+; music_combat   = Music to play when nation in combat mood
+; reqs		 = requirements to activate the style (see effects.ruleset
+;		   and README.effects for help on requirements)
+;
+; */ <-- avoid gettext warnings
+
+[musicstyle_generic]
+music_peaceful     = "music_generic"
+music_combat       = "music_generic"
+reqs	=
+    { "type", "name", "range"
+    }
diff --git a/data/testy-slawomir/techs.ruleset b/data/testy-slawomir/techs.ruleset
new file mode 100644
index 0000000000..ebce214395
--- /dev/null
+++ b/data/testy-slawomir/techs.ruleset
@@ -0,0 +1,118 @@
+; This is minimal techs ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> technology data for Freeciv"
+options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
+format_version = 40
+
+[control]
+; Names for custom tech flags. There can be up to 8 of these.
+; name          = rule name; In some circumstances user may see this
+;                 as part of some sentences, so try to make it descriptive
+;                 and sensible.
+; helptxt       = displayed in the help for advances with this flag (optional)
+;flags =
+;  { "name", "helptxt"
+;  }
+
+; /* <-- avoid gettext warnings
+;
+; Tech classes:
+;
+; First one is the default one.
+; If there is none, tech classes feature is disabled
+;
+; name                    = translatable name as seen by user
+; rule_name               = (optional) internal name for savegames, rulesets
+;                           etc; if not present, "name" is used for this
+;                           purpose too. Since the name used in savegames must
+;                           not change, if you want to rename an item after a
+;                           ruleset has been released, you should set
+;                           "rule_name" to the original value of "name".
+; cost_pct                = how much techs of the class cost compared
+;                           to normal. Default is 100%.
+;
+; */ <-- avoid gettext warnings
+
+;[techclass_default]
+;name =
+
+; /* <-- avoid gettext warnings
+;
+; Below: The individual advances, one per section.
+; The number can be variable, up to 250.
+;
+; The actual tag used (the * in [advance_*]) does not matter, except
+; it must be unique within this file, and it may be used in debug
+; output when reading this file.
+;
+; Notes:
+;
+; name          = translatable name as seen by user
+; rule_name     = (optional) internal name for savegames, rulesets etc; if
+;                 not present, "name" is used for this purpose too. Since
+;                 the name used in savegames must not change, if you want
+;                 to rename an item after a ruleset has been released, you
+;                 should set "rule_name" to the original value of "name".
+; class         = tech class this tech belongs to, if they have been defined.
+;                 Default is first one defined above.
+; req1, req2    = advances required before researching this one
+; root_req      = tech required before acquiring this tech, by any means.
+;                 All techs with any direct or indirect dependency on this
+;                 one will *also* have this root_req, as well as their own
+;                 and any others they inherit.
+;                 Giving "None" explicitly here prevents a tech from
+;                 inheriting root_reqs in this way, and stops root_req
+;                 inheritance through that tech.
+;                 Specifying a tech's root_req as itself means that the tech
+;                 can only be acquired by special means (nation's init_techs,
+;                 scripting, etc).
+; research_reqs = requirements before researching this one. Can have non
+;                 tech requirements because it is a requirement vector.
+;                 See doc/README.effects to learn more about requirement
+;                 vectors.
+;                 Requiring a tech here instead of in req1, req2 or
+;                 root_req is not supported yet.
+;                 Requirements that may become fulfilled during the game
+;                 when they weren't at the start of the game is not
+;                 supported yet.
+; flags         = special flag strings
+; graphic       = icon for technology
+; graphic_alt   = alternate icon
+; helptext      = optional help text string (set units ruleset for examples)
+; bonus_message = text seen when a player is the first to discover
+;                 an bonus tech. Must contain '%s' to mark place of the tech
+;                 gained.
+; cost          = if tech_cost_style is set to "Classic+" or "Experimental+",
+;                 this field is read for information on how much a tech
+;                 costs.
+;
+; Special values for req1 and req2 are "None" (first section below)
+; and "Never" (never available).  If only one tech is required,
+; it should be listed as req1.
+;
+; As well as custom flags defined above, the following flag strings are
+; possible:
+;
+; "Bonus_Tech"          = player gets extra tech if reached first
+; "Bridge"              = "Settler" unit types can build extras that
+;                         require bridge when occurring with some other
+;                         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
+
+[advance_generic]
+name        = _("Generic Tech")
+req1        = "None"
+req2        = "None"
+flags       = ""
+graphic     = "a.alphabet"
+graphic_alt = "-"
+helptext    = _("This is the only technology you can research.")
diff --git a/data/testy-slawomir/terrain.ruleset b/data/testy-slawomir/terrain.ruleset
new file mode 100644
index 0000000000..b1aa9c75c8
--- /dev/null
+++ b/data/testy-slawomir/terrain.ruleset
@@ -0,0 +1,631 @@
+; This is minimal terrain ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> tile_type data for Freeciv"
+options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
+format_version = 40
+
+[control]
+; Names for custom terrain flags. There can be up to 10 of these.
+; name          = rule name; In some circumstances user may see this
+;                 as part of some sentences, so try to make it descriptive
+;                 and sensible.
+; helptxt       = displayed in the help for terrains with this flag (optional)
+;flags =
+;  { "name", "helptxt"
+;  }
+
+; Names for custom extra flags. There can be up to 10 of these.
+; name          = rule name; In some circumstances user may see this
+;                 as part of some sentences, so try to make it descriptive
+;                 and sensible.
+; helptxt       = displayed in the help for extra types with this flag
+;                 (optional)
+;extra_flags =
+;  { "name", "helptxt"
+;  }
+
+[parameters]
+
+; Percentage of "land" tiles required to be adjacent to an ocean tile before
+; it may be "reclaimed" into a land tile (0-101; 0=anywhere, 101=nowhere)
+ocean_reclaim_requirement = 30
+
+; Percentage of "ocean" tiles required to be adjacent to a land tile before
+; it may be "channeled" into an ocean tile (0-101; 0=anywhere, 101=nowhere)
+land_channel_requirement = 10
+
+; Percentage of unfrozen tiles (no "Frozen" flag) required to be adjacent
+; to a frozen tile before it can thaw (0-101; 0=anywhere, default 101=nowhere)
+;thaw_requirement = 101
+
+; Percentage of frozen tiles ("Frozen" flag) required to be adjacent to an
+; unfrozen tile before it can freeze (0-101; 0=anywhere, default 101=nowhere)
+;freeze_requirement = 101
+
+; Bodies of water up to this size are considered freshwater lakes, if there is
+; also terrain type(s) with flag "FreshWater" in the ruleset.
+lake_max_size = 0
+
+; How many native tiles first startunit must be able to reach.
+; 0 to disable check.
+min_start_native_area = 0
+
+; How many fragments each movement point has.
+; For example road movement costs are relative to this.
+move_fragments = 1
+
+; How many move_fragments IgTer unit movement costs
+igter_cost = 1
+
+; Whether diagonal movement has increased cost (no effect with hex topology)
+; The cost increase is more accurate with larger values for move_fragments
+pythagorean_diagonal = FALSE
+
+; There is no resources in the middle of the oceans, only near coast
+ocean_resources = FALSE
+
+; /* <-- avoid gettext warnings
+;
+; The individual terrain types, one per section.
+; Roughly sorted by identifier.
+; The actual tag used (the * in [terrain_*]) must be unique for each terrain,
+; and may be used in debug output when reading this file.
+;
+; Notes:
+;
+; name                 = translatable name as seen by user
+; rule_name            = (optional) internal name for savegames, rulesets etc;
+;                        if not present, "name" is used for this purpose too.
+;                        Since the name used in savegames must not change, if
+;                        you want to rename an item after a ruleset has been
+;                        released, you should set "rule_name" to the original
+;                        value of "name".
+; graphic              = preferred graphic; Tilespec [tile_*] section
+;                        with 'tag' matching this will be used.
+; graphic_alt          = alternate graphic. When no tilespec 'tag' matching
+;                        preferred graphic is not found, this will be used.
+;                        Otherwise may be "-"
+; identifier           = single-character identifier used in savegames. This
+;                        must be unique for each terrain.
+; class                = Terrain class terrain belongs to: "Land" or "Oceanic"
+; movement_cost        = in whole movement points, not move_fragments;
+;                        typically 1 to 3
+; defense_bonus        = percent added to defense; typically 0% to 200%
+; food                 = normal food production
+; shield               = normal shield production
+; trade                = normal trade production
+; resources            = list of possible resources on this terrain
+; resource_freq        = (optional) list of relative frequencies for each
+;                        possible resource on this terrain. When specified,
+;                        must be the same length as resource list.
+;                        Otherwise, all resources occur with approximately
+;                        equal frequency.
+; road_food_incr_pct   = percent of road food_incr applied to this terrain
+; road_shield_incr_pct = percent of road shield_incr applied to this terrain
+; road_trade_incr_pct  = percent of road trade_incr applied to this terrain
+; base_time            = time to build bases; if 0, cannot build any bases.
+;                        Nonzero values only affect extras with build_time 0.
+; road_time            = time to build roads; if 0, cannot build any roads.
+;                        Nonzero values only affect extras with build_time 0.
+; cultivate_result     = cultivate activity changes to that terrain
+;                        'no' to disable cultivate
+; cultivate_time       = time to cultivate
+; plant_result         = plant activity changes to that terrain
+;                        'no' to disable planting
+; plant_time           = time to plant
+; irrigation_food_incr = increment to food if tile is 100% irrigated
+;                        (actual bonus controlled by Irrigation_Pct effect)
+; irrigation_time      = time for 'irrigate' activity; if 0, cannot irrigate
+;                        Nonzero values only affect extras with build_time 0.
+;                        Such extras can modify time with build_time_factor.
+; mining_shield_incr   = increment to shields if tile is 100% mined
+;                        (actual bonus controlled by Mining_Pct effect)
+; mining_time          = time for 'mine' activity; if 0, cannot mine
+;                        Nonzero values only affect extras with build_time 0.
+;                        Such extras can modify time with build_time_factor.
+; transform_result     = result of transformation; one of:
+;                        "no"  -- cannot transform
+;                        terrain rule_name -- transformation changes to that
+;                          terrain
+; transform_time       = time to transform
+; placing_time         = time for 'placing' an extra; if 0, cannot place
+;                        Nonzero values only affect extras with build_time 0.
+;                        Such extras can modify time with build_time_factor.
+;                        Default is 1.
+; pillage_time         = time to pillage extra from the tile (0 = impossible)
+;                        Nonzero values only affect extras with removal_time 0.
+; extra_settings       = table of extra specific settings
+;   - "extra"            - Name of the extra
+;   - "removal_time"     - Time for cleaning activities (0 = impossible)
+;                          Nonzero values only affect extras with removal_time 0.
+; animal               = unit type that can appear as animal on the terrain
+; warmer_wetter_result = result of global warming for wet terrains; one of:
+;                        "no"  -- no change; doesn''t count for warming
+;                        "yes" -- no change; counts for warming
+;                        terrain rule_name -- warming changes to that terrain
+; warmer_drier_result  = result of global warming for dry terrains;
+;                        see warmer_wetter_result
+; cooler_wetter_result = result of nuclear winter for wet terrains;
+;                        see warmer_wetter_result
+; cooler_drier_result  = result of nuclear winter for dry terrains;
+;                        see warmer_wetter_result
+; native_to            = List of unit classes that can move here
+; flags                = General flags for this terrain. List taken from the
+;                        following, and/or any user flags defined above:
+;   - NoBarbs          = Barbarians will not be spawned here.
+;   - NoCities         = Cities may not be built or found on this terrain.
+;   - Starter          = Players will only be started on "Starter" terrain.
+;                        (Currently this cannot be Oceanic terrain.)
+;   - CanHaveRiver     = Set to 1 if this terrain can have river on it (the
+;                        actual chance of river generation is controlled
+;                        separately).
+;   - UnsafeCoast      = This terrain does not provide a safe coast for
+;                        units with flag "CoastStrict"
+;   - FreshWater       = This terrain is used for small bodies of water.
+;                        If this becomes adjacent to non-FreshWater terrain,
+;                        the whole contiguous FreshWater area will be flooded
+;                        with the non-FreshWater terrain.
+;   - NotGenerated     = Map generator never places this terrain type. It can
+;                        be added from editor only, or by ingame events
+;                        (lua scripting)
+;   - NoZoc            = Units on this terrain are not generating or subject
+;                        to zoc
+;   - EnterBorders     = Borders on this terrain are not blocking peaceful
+;                        units from entering and moving.
+;   - Frozen           = Frozen/polar terrain. For water tiles, Frozen terrain
+;                        is generated near poles. Conversion between frozen
+;                        and unfrozen terrain can be controlled with
+;                        thaw_requirement/freeze_requirement, and Frozen
+;                        terrain is shown differently on the overview map.
+; property_*           = specific property % values used by mapgen. Most
+;                        terrains will have 0 for most values. Properties
+;                        other than ocean_depth are only used for land tiles.
+;  - mountainous       = degree to which this terrain is mountainous
+;  - green             = how much life this terrain has
+;  - foliage           = how much thick undergrowth the terrain has
+;  - tropical          = how "tropical" the terrain is (high temperature)
+;  - temperate         = how "temperate" the terrain is (med temperature)
+;  - cold              = how "cold" the terrain is (low temperature)
+;  - frozen            = how "frozen" the terrain is (very low temperature)
+;                        (does not necessarily have to have the "Frozen" flag)
+;  - wet               = how "wet" the terrain is (moisture)
+;  - dry               = how "dry" the terrain is (moisture)
+;  - ocean_depth       = the depth of an ocean, as a percentage
+; color.r              = color of the terrain (red value)
+; color.g              = color of the terrain (green value)
+; color.b              = color of the terrain (blue value)
+; helptext	       = optional help text string; should escape all raw
+;		         newlines so that xgettext parsing works
+
+[terrain_generic]
+name                 = _("Generic")
+graphic              = "generic"
+graphic_alt	     = "grassland"
+identifier	     = "g"
+class                = "Land"
+movement_cost        = 1
+defense_bonus        = 0
+food                 = 1
+shield               = 1
+trade                = 0
+resources            = "Generic Resource"
+road_food_incr_pct   = 0
+road_shield_incr_pct = 0
+road_trade_incr_pct  = 100
+base_time            = 1
+road_time            = 1
+cultivate_result     = "no"
+cultivate_time       = 0
+plant_result         = "no"
+plant_time           = 0
+irrigation_food_incr = 1
+irrigation_time      = 5
+mining_shield_incr   = 0
+mining_time          = 10
+transform_result     = "no"
+transform_time       = 0
+placing_time         = 1
+pillage_time         = 1
+extra_settings       =
+    { "extra", "removal_time"
+    }
+animal               = "None"
+warmer_wetter_result = "no"
+warmer_drier_result  = "no"
+cooler_wetter_result = "no"
+cooler_drier_result  = "no"
+native_to            = "Generic"
+flags                = "Starter", "CanHaveRiver"
+property_temperate   = 50
+property_green       = 50
+color.r              = 200
+color.g              = 200
+color.b              = 200
+helptext	     = _("\
+This is only possible land terrain.\
+")
+
+[terrain_ocean]
+name                 = _("Ocean")
+graphic              = "coast"
+graphic_alt	     = "-"
+identifier	     = " "
+class                = "Oceanic"
+movement_cost        = 1
+defense_bonus        = 0
+food                 = 1
+shield               = 1
+trade                = 0
+resources            = "Generic Resource"
+road_food_incr_pct   = 0
+road_shield_incr_pct = 0
+road_trade_incr_pct  = 100
+base_time            = 1
+road_time            = 1
+cultivate_result     = "no"
+cultivate_time       = 0
+plant_result         = "no"
+plant_time           = 0
+irrigation_food_incr = 0
+irrigation_time      = 0
+mining_shield_incr   = 0
+mining_time          = 0
+transform_result     = "no"
+transform_time       = 0
+placing_time         = 1
+pillage_time         = 1
+extra_settings       =
+    { "extra", "removal_time"
+    }
+animal               = "None"
+warmer_wetter_result = "no"
+warmer_drier_result  = "no"
+cooler_wetter_result = "no"
+cooler_drier_result  = "no"
+native_to            = "Generic Ship"
+;flags                =
+property_ocean_depth = 10
+color.r              = 50
+color.g              = 50
+color.b              = 230
+helptext	     = _("\
+This is only possible oceanic terrain.\
+")
+
+; /* <-- avoid gettext warnings
+;
+; Resource types:
+;
+; The actual tag used (the * in [resource_*]) must be unique for each resource,
+; and may be used in debug output when reading this file.
+;
+; Notes:
+;
+; extra                = name of the extra this resource section is part of
+;                        (must have "Resource" in its causes)
+; identifier           = single-character identifier used in old savegames. This
+;                        must be unique for each resource, and changing it will
+;                        break loading those old savegames.
+; food                 = increased food production
+; shield               = increased shield production
+; trade                = increased trade production
+;
+; */ <-- avoid gettext warnings
+
+[resource_generic]
+extra       = "Generic Resource"
+food        = 0
+shield      = 0
+trade       = 1
+identifier  = "g"
+
+
+[extraui]
+
+; Player visible names of the base gui types.
+
+; ui_name_base_fortress refers to all bases that have gui_type "Fortress"
+ui_name_base_fortress = _("?gui_type:Build Type A Base")
+
+; ui_name_base_airbase refers to all bases that have gui_type "Airbase"
+ui_name_base_airbase = _("?gui_type:Build Type B Base")
+
+; /* <-- avoid gettext warnings
+;
+; Each extra, including bases, roads, and resource, must have a section here.
+; Bases, roads, and resources have additional sections for their specific features.
+;
+;
+; Extra types:
+;
+; name                    = translatable name as seen by user
+; rule_name               = (optional) internal name for savegames, rulesets
+;                           etc; if not present, "name" is used for this
+;                           purpose too. Since the name used in savegames must
+;                           not change, if you want to rename an item after a
+;                           ruleset has been released, you should set
+;                           "rule_name" to the original value of "name".
+; category                = How UI should categorize this extra. One of
+;                           "Infra", "Natural", "Nuisance", "Resource",
+;                           or "Bonus"
+; causes                  = events that can create extra type.
+;                           "Irrigation", "Mine", "Hut", "Pollution", "Fallout",
+;                           "Appear", "Resource", "Base", or "Road"
+;                           (the last three require a corresponding
+;                           [resource_*] / [base_*] / [road_*] section)
+; rmcauses                = events that can remove extra type.
+;                           "CleanPollution", "CleanFallout", "Pillage",
+;                           "Disappear", or "Enter"
+; infracost               = Number of infrapoints it costs to place this
+;                           extra. 0, the default, means extra cannot be placed.
+; graphic                 = tag specifying preferred graphic
+; graphic_alt             = tag for alternate graphic if preferred graphic is
+;                           not present. Can use eg "-" for no alternate
+;                           graphic
+; activity_gfx            = tag specifying graphic for unit building extra
+;                           This can be "None" to indicate that graphic sprite
+;                           is not needed.
+; act_gfx_alt             = tag for alternative graphic for unit building extra
+; act_gfx_alt2            = tag for second alternative graphic for unit building extra
+; rmact_gfx               = tag specifying graphic for unit removing extra
+;                           This can be "None" to indicate that graphic sprite
+;                           is not needed.
+; rmact_gfx_alt           = tag for alternative graphic for unit removing extra
+; reqs                    = requirements to build the extra (see effects.ruleset
+;                           and README.effects for help on requirements)
+; rmreqs                  = requirements to remove the extra
+; appearance_reqs         = spontaneous appearance requirements
+; disappearance_reqs      = spontaneous disappearance requirements
+; visibility_req          = Tech a player needs to have to see the extra
+;                           This affects visibility only, for all the rules
+;                           extra is still there even if player can't see it.
+; buildable               = Can extra be built? Defaults to TRUE if extra has
+;                           any causes indicating it can result from worker
+;                           activity.
+;                           If extra is not buildable, it can appear in game
+;                           only if placed in the editor, it's placed by
+;                           map generator, or on city tile if the extra
+;                           also has "AlwaysOnCityCenter" flag set.
+; generated               = Can map generator place the extra? Applicable
+;                           for Hut, Resource, and River extras.
+; build_time              = how long it takes a unit to build this extra.
+;                           Value of 0 (default) means that terrain- and
+;                           build activity specific time is used instead.
+; build_time_factor       = This setting take effect only if build_time is 0.
+;                           Terrain and activity specific build time will be
+;                           multiplied by this value (default 1)
+; removal_time            = how long it takes a unit to remove this extra.
+;                           Value of 0 (default) means that terrain- and
+;                           removal activity specific time is used instead.
+; removal_time_factor     = This setting take effect only if removal_time is 0.
+;                           Terrain and activity specific removal time will be
+;                           multiplied by this value (default 1)
+; defense_bonus           = Percent added to defense when tile has the extra
+;                           (default none)
+; unit_seen               = How opponents see units inside this extra
+;                           "Normal" - Units are seen normally (default)
+;                           "Hidden" - Units are hidden from opponents
+; appearance_chance       = If extra has cause "Appear" and other requirements
+;                           for its appearance are fulfilled, this tells how big
+;                           chance it has to appear each turn. The chance is 1/10000
+;                           times this value.
+; disappearance_chance    = If extra has rmcause "Disappear" and other requirements
+;                           for its disappearance are fulfilled, this tells how big
+;                           chance it has to disappear each turn. The chance is 1/10000
+;                           times this value.
+; native_to               = List of unit classes that are considered to
+;                           be inside the extra when they are on same tile
+; conflicts               = List of extras that cannot be on the same tile.
+;                           Bases with non-zero border_sq automatically conflict
+;                           with each other.
+; hidden_by               = List of extra types that will make this extra
+;                           type not to show on UI if both present.
+; bridged_over            = List of extra types that, if present in tile, will prevent
+;                           building this extra if can't be bridged over
+; no_aggr_near_city       = When at least zero, units inside are not considered
+;                           aggressive when there`s a friendly city within this distance
+; flags
+;   - "NativeTile"        = Native units consider tile native regardless of
+;                           terrain
+;   - "Refuel"            = Native units can use tile as refuel point
+;   - "TerrChangeRemoves" = Extra gets removed when ever terrain changes even
+;                           if target terrain could support it
+;   - "AlwaysOnCityCenter" = City center tiles always have this extra type
+;                           regardless of its other requirements
+;   - "AutoOnCityCenter"  = City center tiles will automatically have this
+;                           extra type if the player can build it
+;   - "ConnectLand"       = Road style gfx on Oceanic tiles are drawn to
+;                           connect to adjacent Land tiles even if they have
+;                           no extra. This affects appearance only
+;   - "GlobalWarming"     = Instances of this extra on map count towards
+;                           Global Warming
+;   - "NuclearWinter"     = Instances of this extra on map count towards
+;                           Nuclear Winter
+;   - "ShowFlag"          = Draw owner's flag
+;   - "NaturalDefense"    = Extra's defense bonus will be counted to "Natural"
+;                           defense layer. The defense bonus of all the extras
+;                           located at the tile, native to defending unit,
+;                           is calculated as a 1 + sum of bonuses from the extras
+;                           on the default "Fortification" defense layer multiplied
+;                           by the 1 + sum of bonuses from the extras on the
+;                           "Natural" layer.
+;   - "NoStackDeath"      = Units inside do not die all at once when attacked
+; helptext                = optional help text string; should escape all raw
+;                           newlines so that xgettext parsing works
+;
+; */ <-- avoid gettext warnings
+
+;[extra_generic]
+;name           = _("Generic")
+;category       = "Infra"
+;causes         = ""
+;rmcauses       = ""
+;graphic        = "tx.generic"
+;graphic_alt    = "-"
+;activity_gfx   = "unit.generic"
+;act_gfx_alt    = "-"
+;act_gfx_alt2   = "-"
+;rmact_gfx      = "None"
+;rmact_gfx_alt  = "-"
+;build_time     = 0
+;removal_time   = 0
+;helptext       = _("")
+
+;[extra_gbase]
+;name           = _("Generic Base")
+;category       = "Infra"
+;causes         = "Base"
+;rmcauses       = ""
+;graphic        = "base.generic"
+;graphic_alt    = "-"
+;activity_gfx   = "unit.gbase"
+;act_gfx_alt    = "-"
+;act_gfx_alt2   = "-"
+;rmact_gfx      = "None"
+;rmact_gfx_alt  = "-"
+;buildable      = FALSE
+;reqs           =
+;    { "type", "name", "range"
+; No requirements
+;    }
+;build_time     = 0
+;removal_time   = 0
+;helptext       = _("")
+
+;[extra_groad]
+;name           = _("Generic Road")
+;category       = "Infra"
+;causes         = "Road"
+;rmcauses       = ""
+;graphic        = "road.generic"
+;graphic_alt    = "-"
+;activity_gfx   = "unit.groad"
+;act_gfx_alt    = "-"
+;act_gfx_alt2   = "-"
+;rmact_gfx      = "None"
+;rmact_gfx_alt  = "-"
+;buildable      = FALSE
+;reqs           =
+;    { "type", "name", "range"
+; No requirements
+;    }
+;build_time     = 0
+;removal_time   = 0
+;helptext       = _("")
+
+[extra_gresource]
+name           = _("Generic Resource")
+category       = "Resource"
+causes         = "Resource"
+;rmcauses       = ""
+graphic        = "ts.grassland_resources"
+graphic_alt    = "-"
+activity_gfx   = "None"
+act_gfx_alt    = "-"
+act_gfx_alt2   = "-"
+rmact_gfx      = "None"
+rmact_gfx_alt  = "-"
+
+; /* <-- avoid gettext warnings
+;
+; Base types:
+;
+; extra                   = name of the extra this base section is part of
+;                           (must have "Base" in its causes)
+; gui_type                = How gui should handle this base.
+;                           Value can be "Fortress", "Airbase", or "Other"
+;                           See also [extraui] section
+; border_sq               = Base will claim land ownership up to this radius,
+;                           -1 to disable. If enabled, base cannot exist in
+;                           city tile.
+;                           Base (and border) ownership will change hands if
+;                           an enemy unit does "Conquer Extras" to the tile.
+; vision_main_sq          = Base will have main layer vision to this radius.
+;                           Vision initially provided to owner of unit that
+;                           built base; base will not then change hands unless
+;                           it also claims territory, or tile has another such
+;                           base or city, or another base is built (tile only
+;                           tracks one owner for all bases).
+; vision_invis_sq         = Base will have invisible layer vision to this radius
+; vision_subs_sq          = Base will have subsurface layer vision to this radius
+;
+; */ <-- avoid gettext warnings
+
+; It's ok to have no base types at all. I have left one, commented out, here as an
+; example
+
+;[base_gbase]
+;extra        = "Generic Base"
+;gui_type     = "Fortress"
+
+; /* <-- avoid gettext warnings
+;
+; Road types:
+;
+; extra                   = name of the extra this road section is part of
+;                           (must have "Road" in its causes)
+; first_reqs              = additional requirements to build the first part of
+;                           the road, when none of the adjacent tiles have any
+;                           integrating roads (see effects.ruleset and
+;                           README.effects for help on requirements)
+; move_cost               = how much movement it takes to to travel
+;                           via this road (in fractional move points, as
+;                           defined by move_fragments)
+;                           -1 means that road provides no speed bonus.
+; move_mode               = how movement costs are applied
+;   - "Cardinal"   = Road cost applies only on cardinal moves
+;   - "Relaxed"    = Road cost is normal for cardinal, double for diagonal moves
+;   - "FastAlways" = Road cost applies always between two tiles with the roads
+;                    (default)
+; food_incr_const         = food production added to tile regardless of terrain
+; shield_incr_const       = shield production added to tile regardless of
+;                           terrain
+; trade_incr_const        = trade production added to tile regardless of
+;                           terrain
+; food_incr               = food production added to tile; multiplied by
+;                           terrain-specific road_food_incr_pct
+; shield_incr             = shield production added to tile; multiplied by
+;                           terrain-specific road_shield_incr_pct
+; trade_incr              = trade production added to tile; multiplied by
+;                           terrain-specific road_trade_incr_pct
+; food_bonus              = percent added to food production
+; shield_bonus            = percent added to shield production
+; trade_bonus             = percent added to trade production
+;   In summary, output bonuses from roads are given by the formula:
+;   (base_prod + roads.incr_const + roads.incr*terrain.incr_pct) * roads.bonus
+; compat_special          = what kind of pre-2.5 special this road corresponds
+;                           to, if any: "Road", "Railroad", "River", or "None".
+;                           Used for loading old savegames.
+; gui_type                = How gui should handle this base.
+;                           Value can be "Road", "Railroad", "Maglev", or "Other"
+; integrates              = list of road types that are suitable next steps
+;                           for travel from this road type; such steps are
+;                           possible for units native to both roads and don`t
+;                           get cost from underlying terrain; graphics are
+;                           drawn accordingly
+; flags
+;   - "River"             = Automatically generated by map generator, always
+;                           flowing from land tiles to ocean
+;   - "UnrestrictedInfra" = Use of the enemy owned road is not restricted
+;                           even if server setting 'restrictinfra' is set
+;   - "JumpFrom"          = Move to a tile nativity providing "JumpTo"
+;                           road is considered native
+;   - "JumpTo"            = Move from a tile nativity providing "JumpFrom"
+;                           road is considered native
+;
+; */ <-- avoid gettext warnings
+
+; [road_groad]
+; extra          = "Generic Road"
+; move_cost      = 1
+; food_incr      = 0
+; shield_incr    = 0
+; trade_incr     = 0
+; food_bonus     = 0
+; shield_bonus   = 0
+; trade_bonus    = 0
+; compat_special = "None"
+; gui_type       = "Other"
+; flags          = ""
diff --git a/data/testy-slawomir/units.ruleset b/data/testy-slawomir/units.ruleset
new file mode 100644
index 0000000000..aaef5c4540
--- /dev/null
+++ b/data/testy-slawomir/units.ruleset
@@ -0,0 +1,431 @@
+; This is minimal units ruleset. Replace <modpack> with your module name in
+; description.
+
+[datafile]
+description = "<modpack> unit_type data for Freeciv"
+options = "+Freeciv-ruleset-3.3-Devel-2023.Feb.24"
+format_version = 40
+
+[control]
+; Names for custom unit type flags. There can be up to 45 of these.
+; name          = rule name; In some circumstances user may see this
+;                 as part of some sentences, so try to make it descriptive
+;                 and sensible.
+; helptxt       = displayed in the help for unit types with this flag (optional)
+; flags =
+;   { "name", "helptxt"
+;   }
+
+; Names for custom unit class flags. There can be up to 15 of these.
+; name          = rule name; In some circumstances user may see this
+;                 as part of some sentences, so try to make it descriptive
+;                 and sensible.
+; helptxt       = displayed in the help for unit types belonging to a class
+;                 with this flag (optional)
+;class_flags =
+;  { "name", "helptxt"
+;  }
+
+[veteran_system]
+; What are the names of the levels?
+veteran_names = _("green")
+
+; The percentage chance of increasing level through combat
+veteran_base_raise_chance = 0
+
+; Power factors are as a percentage.
+; +50% is represented by 150
+veteran_power_fact = 100
+
+; The percentage chance of a settler/engineer increasing level through
+; performing useful work (per turn)
+veteran_work_raise_chance = 0
+
+; The additional number of movement points granted for different veteran
+; levels. These are fractional move points as defined by move_fragments in
+; terrain.ruleset.
+veteran_move_bonus = 0
+
+; /* <-- avoid gettext warnings
+;
+; Unit classes
+; The number can be variable, up to 32
+; When adding new classes, remember to check effects.ruleset also.
+; Eg. if you divide class 'Land' to two separate classes, you may
+; want add effect giving City Walls defense bonus against new class
+; too.
+;
+; The actual tag used (the * in [unitclass_*]) does not matter, except
+; it must be unique within this file, and it may be used in debug
+; output when reading this file.
+;
+; ** Fields **
+;
+; name                = translatable name as seen by user
+; rule_name           = (optional) internal name for savegames, rulesets etc;
+;                       if not present, "name" is used for this purpose too.
+;                       Since the name used in savegames must not change, if
+;                       you want to rename an item after a ruleset has been
+;                       released, you should set "rule_name" to the original
+;                       value of "name".
+; min_speed           = Minimum speed after damage and effects (whole movement points)
+; hp_loss_pct         = Hitpoints lost each turn if unit not in city or native base
+; non_native_def_pct  = Defense power percentage applying when defending on
+;                       non-native terrain (such as ship in harbour)
+; flags               = List of unit class flags (from the following list; you
+;                       cannot add custom unit class flags)
+; helptext            = optional help text string; should escape all raw newlines
+;                       so that xgettext parsing works
+;
+; ** Unit class Flags **
+;
+; "TerrainSpeed"      = Units use terrain specific speed
+; "TerrainDefense"    = Units gain defense bonus from terrain
+; "DamageSlows"       = Damaged units are slowed down
+; "CanOccupyCity"     = Military units of this class can occupy enemy cities
+; "BuildAnywhere"     = Unit can be built even in the middle of non-native terrain
+; "Unreachable"       = Unit can be attacked only by units explicitly listing this
+;                       class in its 'targets', unless on a city or native base.
+;                       For class members which are transports, cargo cannot load/
+;                       unload except in a city or native base, unless that unit
+;                       explicitly lists this class in its 'embarks'/'disembarks'.
+; "CollectRansom"     = Unit can collect ransom when killing lone barbarian leader
+; "ZOC"               = Unit is subject to ZOC rules. Unit type flag "IgZOC" can
+;                       override this
+; "DoesntOccupyTile"  = Even if this kind of enemy unit is on tile, cities can
+;                       still work that tile
+; "AttackNonNative"   = Unit can attack units on non-native tiles. Unit type flag
+;                       "Only_Native_Attack" can override this
+; "KillCitizen"       = Upon successful attack against a city unit kills one citizen.
+;                       There's server setting, as well as effects, to disable this.
+; "HutFrighten"       = Will frighten rather than enter huts.
+; "NonNatBombardTgt"  = Certain attacks against these units are considered
+;                       Nonnative Bombard Attack type
+;
+; */ <-- avoid gettext warnings
+
+[unitclass_generic]
+name          = _("Generic")
+min_speed     = 1
+hp_loss_pct   = 0
+flags         = "CanOccupyCity"
+
+[unitclass_ship]
+name          = _("Generic Ship")
+min_speed     = 1
+hp_loss_pct   = 0
+flags         = ""
+
+; /* <-- avoid gettext warnings
+;
+; Below: The individual unit types, one per section.
+;
+; The number can be variable, up to 200.
+; However for the "official" rulesets, units should not be removed
+; because that would break backward compatibility with savegames.
+;
+; The order here matters: later units are considered "better" for
+; a given flag or role.
+;
+; The actual tag used (the * in [unit_*]) does not matter, except
+; it must be unique within this file, and it may be used in debug
+; output when reading this file.
+;
+; ** Fields **
+;
+; name          = translatable name as seen by user
+; rule_name     = (optional) internal name for savegames, rulesets etc; if
+;                 not present, "name" is used for this purpose too. Since
+;                 the name used in savegames must not change, if you want
+;                 to rename an item after a ruleset has been released, you
+;                 should set "rule_name" to the original value of "name".
+; graphic       = tag specifying preferred graphic
+; graphic_alt   = tag for alternate graphic if preferred graphic is not
+;                 present; especially if preferred graphic is non-standard,
+;                 this should be a standard tag.  Otherwise can use eg "-"
+;                 for no alternate graphic.
+; reqs          = requirements to build the unit (see effects.ruleset
+;                 and README.effects for help on requirements)
+; obsolete_by   = can be upgraded to and made obsolete by another unit by name
+; build_cost    = production shields required to build
+; pop_cost      = population removed from city when built; for 'Join City'
+;                 units this is also the population added to the destination
+; attack        = base attack strength (0 = cannot attack)
+; defense       = base defense strength (0 = cannot defend)
+; hitpoints     = how much damage unit can withstand
+; firepower     = number of hitpoints removed per round of combat; at least 1
+; move_rate     = base move rate (whole movement points)
+; vision_radius_sq = base vision of unit: unit can see tile up to the square
+;                 root of this value away
+; convert_to    = can be converted to another type of unit by name
+; convert_time  = number of movement points it takes to convert to
+;                 another unit type
+; class         = One of the classes listed above
+; transport_cap = Number of units (ground, or air/missiles, depending on flags)
+; fuel          = Number of turns unit can spend outside refuel points.
+;                 If more time passes without unit refueling over turn change,
+;                 they are lost. If this is zero, unit has no need to refuel
+;                 Units with "Coast" flag set consider any tile next to coast
+;                 refuel point
+; uk_*          = upkeep costs, these are used as base values in the game
+; cargo         = Unit classes this unit can transport
+; city_slots    = How many of homecity's unit maintenance slots unit takes
+; city_size     = Initial size of the cities built by 'Found City' type units
+;                 (but 'Join City' uses pop_cost)
+; tp_defense    = Method to decide if unit can be selected as a defender when
+;                 transported.
+;                   "Blocked" - Can't defend when transported
+;                   "Alight"  - Can defend if can alight or unload (current default)
+; targets       = list of unit classes this unit can attack against even
+;                 if they have Unreachable unit class flag
+; embarks       = list of unit classes this unit may load into while not in
+;                 native base or city even if transporter has Unreachable unit
+;                 class flag
+; disembarks    = list of unit classes this unit may unload from while not in
+;                 native base or city even if transporter has Unreachable unit
+;                 class flag
+; vision_layer  = At which layer this unit is visible; "Main", "Stealth",
+;                 or "Subsurface"
+; bonuses       = definitions of combat bonuses against specific other units
+; bonuses.flag  = flag of the unit that bonus applies against
+; bonuses.type  = type of the bonus. See below
+; bonuses.value = value of the bonus. Sum of these is used if multiple apply.
+; bonuses.quiet = don't auto generate help text for this bonus. Use this if
+;                 the bonus is documented in the unit type's help text.
+;                 This is useful when the combination of a unit's bonuses
+;                 becomes complex enough to make the auto generated help
+;                 ugly or inaccurate.
+; flags           = special flag strings; list of built-in flags described below
+;                   and/or user flags defined above
+; roles           = special role strings
+; sound_move      = optional sound effect when the unit moves
+; sound_move_alt  = optional alternative sound effect if above not
+;                   supported in client
+; sound_fight     = optional sound effect when the unit fights
+; sound_fight_alt = optional alternative sound effect if above not
+;                   supported in client
+; helptext        = optional help text string; should escape all raw newlines
+;                   so that xgettext parsing works
+;
+;
+; ** Bonuses **
+;
+; "DefenseMultiplier"    = See "DefenseMultiplierPct" below. This is
+;                          equivalent to that multiplied by 100.
+;                          Bonus is defined in defenders entry.
+; "DefenseMultiplierPct" = Multiply defense by 1 + (value / 100).
+;                          Value of 100 means multiplication by 2,
+;                          value of 50 means multiplication by 1.5, etc.
+;                          Effectively increases defense by value percent.
+;                          Bonus is defined in defenders entry.
+; "DefenseDivider"       = See "DefenseDividerPct" below. This is equivalent
+;                          to that multiplied by 100.
+;                          Bonus is defined in attackers entry.
+; "DefenseDividerPct"    = Divide defense value by 1 + (value / 100).
+;                          Value of 100 means division by 2,
+;                          value of 50 means division by 1.5, i.e.
+;                          multiplication with 2/3, etc.
+;                          Effectively increases *attack* by value percent.
+;                          Bonus is defined in attackers entry.
+; "LowFirepower"         = Defender firepower is reduced to low firepower
+;                          value defined in game.ruleset when
+;                          ever this has non-zero value.
+;                          Bonus is defined in attackers entry.
+; "CityDefensePct"       = In a city, instead of "Defend_Bonus" effect
+;                          uses this bonus.
+;                          Bonus is defined in defenders entry.
+;
+;
+; ** Flags **
+;
+; "IgZOC"       = ignore Zones of Control (ZOC) even if unit class has
+;                 "ZOC" flag
+; "HasNoZOC"    = unit has no Zone of Control (ZOC), thus any unit can move
+;                 around it freely
+; "NonMil"      = a non-military unit: no attacks; no martial law; can enter
+;                 peaceful borders; DoesntOccupyTile
+; "IgTer"       = use constant move cost defined in igter_cost (terrain.ruleset)
+;                 rather than terrain/road etc cost, unless terrain cost is
+;                 less
+; "FieldUnit"	= cause unhappiness even when not being aggressive
+; "AttackAny"   = can attack unreachable units
+; "Settlers"	= can irrigate and build roads
+; "Diplomat"	= can do diplomat actions (see diplchance server option)
+; "Spy"         = strong in diplomatic battles. _Must_ be "Diplomat" also
+; "CoastStrict" = (sea only) cannot leave coast
+; "Coast"       = (sea only) can refuel on coast. Set fuel to force unit
+;                 to regularly end turn on coast
+; "Only_Native_Attack" = cannot attack targets on non-native tiles even if
+;                 unit class can
+; "Fanatic"	= can only be built by governments that allow them
+;		  (see civ2/governments.ruleset, Fundamentalism government)
+; "Unique"	= a player can only have one of these units in the game at
+;		  the same time; barbarians cannot use this at present
+; "GameLoss"	= losing one of these units means you lose the game, but it
+;		  is produced without homecity and upkeep
+; "EvacuateFirst" = the game will try to rescue units with this flag before
+;                 it tries to rescue units without it when their transport
+;                 is destroyed. Think of the Birkenhead drill ("women and
+;                 children first"). Replace "women and children" with
+;                 "units with the EvacuateFirst unit type flag".
+; "SuperSpy"	= this unit always wins diplomatic contests, that is, unless
+;		  it encounters another SuperSpy, in which case defender wins;
+;		  can also be used on non-diplomat units, in which case it can
+;		  protect cities from diplomats; also 100% spy survival chance
+; "NoHome"	= this unit is built with no homecity, free of all upkeep, and
+;		  therefore will not revolt along with its city of origin should
+;		  it be incited
+; "NoVeteran"   = this unit cannot gain veteran levels through experience
+;                 (as if both base_raise_chance and work_raise_chance were zero);
+;                 it can still gain veterancy through Veteran_Build, etc
+; "CityBuster"  = this unit has double firepower against cities
+; "NoBuild"     = this unit cannot be built
+; "BadWallAttacker" = the firepower of this unit is set to 1 if
+;                     attacking a city
+;                     defended by a city wall (or other city building defense)
+; "BadCityDefender" = if attacked while in a city, firepower is set to 1
+;		  and firepower of attacker is doubled (the Pearl Harbour
+;                 rule)
+; "BarbarianOnly" = only barbarians can build this unit
+; "Shield2Gold" = Switch from shield upkeep to gold upkeep possible
+; "NewCityGamesOnly" = unit can't be built on scenarios where founding new cities
+;                 is not allowed. Give this flag to units that would make no sense
+;                 to have in a game with such a scenario
+; "CanEscape"   = this unit has, given that certain conditions are
+;                 fulfilled, a 50% chance to escape rather than being
+;                 killed when killstack is enabled and the defender of its
+;                 tile is defeated. The conditions are that it has more move
+;                 points than required to move to an adjacent tile plus the
+;                 attackers move points and that the attacker doesn't have
+;                 the "CanKillEscaping" unit type flag.
+; "CanKillEscaping" = an attack from this unit ignores the "CanEscape" unit
+;                 type flag.
+; "Provoking" =   a unit considering to auto attack this unit will choose to
+;                 do so even if has better odds when defending against it
+;                 then when attacking it. Applies when the autoattack server
+;                 setting is enabled.
+; "NeverProtects" = doesn't protect reachable units on its tile from enemy
+;                 attackers, even if the unreachableprotects server setting
+;                 is enabled and the unit class is unreachable
+; "RandomMovement" = Unit makes random movements in the beginning of the turn,
+;                 player has no control over its movement
+;
+; Following actions require extra fields:
+;  "Attack" and "Suicide Attack"
+;   attack = base attack strength
+;  "Bombard"
+;   attack       = base attack strength
+;   bombard_rate = the number of shots fired at enemy units when attacking
+;  "Join City"
+;   pop_cost = the number of population added to the target city
+;  "Paradrop Unit"
+;   paratroopers_range  = the maximal range the unit can be paradropped to.
+;                         Max range is 65534.
+;  "Upgrade Unit"
+;   obsolete_by = the unit type upgraded to.
+;  "Convert Unit"
+;   convert_to = the unit type converted to.
+;
+; ** Roles **
+;
+; "FirstBuild"            = first to be built when city founded
+; "Explorer"              = unit to use for exploring
+; "Hut"                   = can be found in a hut
+; "HutTech"               = can be found in a hut, but its techs required
+; "Partisan"              = can be created as a partisan (only one unit can have this
+;                           flag), see end of this file for its tech requirements option
+; "DefendOk"              = AI hint: ok for defending with
+; "DefendGood"            = AI hint: good for defending with
+; "Ferryboat"             = AI hint: useful for ferrying
+; "Barbarian"             = can be created as land barbarian
+; "BarbarianTech"         = can be created as land barbarian, if someone has
+;		            researched its tech requirements
+; "BarbarianBoat"         = can be created as boat for sea barbarian
+; "BarbarianBoatTech"     = can be created as boat for sea barbarian, if someone has
+;                           researched its tech requirements
+; "BarbarianBuild"        = can be built by barbarians
+; "BarbarianBuildTech"    = can be built by barbarians if someone has
+;		            researched its tech requirements
+; "BarbarianLeader"       = this unit is the barbarian leader (only one)
+; "BarbarianSea"          = can be created as a barbarian that disembarks from a barbarian boat
+; "BarbarianSeaTech"      = can be created as a barbarian that disembarks from a barbarian boat
+;                           if someone has researched its tech requirements
+; "Settlers"              = can irrigate and build roads
+; "Hunter"                = AI hint: good for hunting other units
+; "CitiesStartUnit"       = Gets granted as 'c' startunit
+; "WorkerStartUnit"       = Gets granted as 'w' startunit
+; "ExplorerStartUnit"     = Gets granted as 'x' startunit
+; "KingStartUnit"         = Gets granted as 'k' startunit
+; "DiplomatStartUnit"     = Gets granted as 's' startunit
+; "FerryStartUnit"        = Gets granted as 'f' startunit
+; "DefendOkStartUnit"     = Gets granted as 'd' startunit
+; "DefendGoodStartUnit"   = Gets granted as 'D' startunit
+; "AttackFastStartUnit"   = Gets granted as 'a' startunit
+; "AttackStrongStartUnit" = Gets granted as 'A' startunit
+;
+; */ <-- avoid gettext warnings
+
+[unit_generic]
+name          = _("Generic")
+class         = "Generic"
+;reqs
+obsolete_by   = "None"
+graphic       = "u.warriors"
+graphic_alt   = "-"
+sound_move    = "m_warriors"
+sound_move_alt = "m_generic"
+sound_fight   = "f_warriors"
+sound_fight_alt = "f_generic"
+build_cost    = 10
+pop_cost      = 0
+attack        = 1
+defense       = 1
+hitpoints     = 10
+firepower     = 1
+move_rate     = 1
+vision_radius_sq = 2
+transport_cap = 0
+fuel          = 0
+uk_happy      = 0
+uk_shield     = 0
+uk_food       = 0
+uk_gold       = 0
+tp_defense    = "Alight"
+flags         = "Settlers"
+roles         = "ExplorerStartUnit", "Firstbuild", "CitiesStartUnit"
+helptext      = _("\
+  This is the only land unit type you can build.\
+")
+
+[unit_ship]
+name          = _("Generic Ship")
+class         = "Generic Ship"
+;reqs
+obsolete_by   = "None"
+graphic       = "u.warriors"
+graphic_alt   = "-"
+sound_move    = "m_warriors"
+sound_move_alt = "m_generic"
+sound_fight   = "f_warriors"
+sound_fight_alt = "f_generic"
+build_cost    = 10
+pop_cost      = 0
+attack        = 1
+defense       = 1
+hitpoints     = 10
+firepower     = 1
+move_rate     = 1
+vision_radius_sq = 2
+transport_cap = 2
+fuel          = 0
+uk_happy      = 0
+uk_shield     = 0
+uk_food       = 0
+uk_gold       = 0
+tp_defense    = "Alight"
+cargo         = "Generic"
+flags         = ""
+roles         = "Ferryboat", "BarbarianBoat"
+helptext      = _("\
+  This is the only ship type you can build.\
+")
-- 
2.39.2

