This document describes how to convert freeciv 3.0 compatible ruleset to development version (one that will become freeciv 3.1) compatible ones. Currently this goes up to compatibility with freeciv master commit b8955f08ab, 16-May-20.

Capability[edit | edit source]

Capability string and format_version of each ruleset file must be updated. For 3.1 rulesets the format version is 20.

[datafile]
options="+Freeciv-ruleset-Devel-2017.Jan.02"
format_version=20

parser.lua[edit | edit source]

New parser.lua lua script is needed in the ruleset. Empty file by that name is enough when not wanting any new features from it but only to update ruleset with existing functionality.

Unit vision layer[edit | edit source]

Add vision_layer entry for unit types requiring it. You don't need to define it for units on default layer, but only for those units that have had Partial_Invis flag. Remove the flag and set vision_layer="Stealth" for them.

Bridge rules[edit | edit source]

Any extra can now require bridge building tech, not only roads. Each extra lists other extras that, if present, make it to require a bridge technology. Road flags RequiresBridge and PreventsOtherRoads are removed as obsolete. For each road that had RequiresBridge add bridged_over list of extras to equivalent extra section. That list should contain all the extras that formerly had PreventsOtherRoads in their road section. Once you've done that, remove the flags from all road sections.

[road_road]
extra = "Road"
...
flags = "RequiresBridge"

[road_rail]
extra = "Railroad"
...
flags = "RequiresBridge"

[road_river]
extra = "River"
...
flags = "PreventsOtherRoads"

[road_canal]
extra = "Canal"
...
flags = "PreventsOtherRoads"

->

[extra_road]
name = _("Road")
...
bridged_over = "River", "Canal"

[extra_rail]
name = _("Railroad")
...
bridged_over = "River", "Canal"

Convert effects to Action Enablers[edit | edit source]

Some boolean effects have been replaced by Action Enablers.

Transform_Possible effect to Transform_Terrain Enabler[edit | edit source]

Replace any Transform_Possible effect with equivalent Transform_Terrain Action Enabler.

[effect_transform]
type    = "Transform_Possible"
value   = 1
reqs    =
    { "type", "name", "range"
      "Tech", "Fusion Power", "Player"
      "UnitFlag", "Transform", "Local"
    }

->

[actionenabler_transform_terrain]
action        = "Transform Terrain"
actor_reqs    =
    { "type",          "name",         "range"
      "Tech",          "Fusion Power", "Player"
      "UnitFlag",      "Transform",    "Local"
      "UnitFlag",      "Settlers",     "Local"
    }

Irrig_Possible effect to Build Irrigation Enabler[edit | edit source]

Replace any Irrig_Possible effect with equivalent Build Irrigation Action Enabler. Add explicit requirement of Settlers unit to them.

[effect_irrigate_src_irrigation]
type    = "Irrig_Possible"
value   = 1
reqs    =
    { "type", "name", "range"
      "Extra", "Irrigation", "CAdjacent"
    }

->

[actionenabler_irrigate_src_irrigation]
action        = "Build Irrigation"
actor_reqs    =
    { "type",          "name",         "range"
      "UnitFlag",      "Settlers",     "Local"
    }
target_reqs    =
    { "type",    "name",       "range"
      "Extra",   "Irrigation", "CAdjacent"
    }

Mining_Possible effect to Build Mine Enabler[edit | edit source]

Replace any Mining_Possible effect with equivalent Build Mine Action Enabler. Add explicit requirement of Settlers unit to them.

[effect_mining]
type    = "Mining_Possible"
value   = 1
reqs    =
    { "type", "name", "range", "present"
      "TerrainFlag", "Oil", "Local", FALSE
    }

->

[actionenabler_mining]
action        = "Build Mine"
actor_reqs    =
    { "type",          "name",         "range"
      "UnitFlag",      "Settlers",     "Local"
    }
target_reqs    =
    { "type",        "name", "range", "present"
      "TerrainFlag", "Oil",  "Local", FALSE
    }

Irrig_TF_Possible effect to Cultivate Enabler[edit | edit source]

Replace any Irrig_TF_Possible effect with equivalent Cultivate Action Enabler. Add explicit requirement of Settlers unit to them.

[effect_irrig_tf]
type    = "Irrig_TF_Possible"
value   = 1

->

[actionenabler_cultivate]
action        = "Cultivate"
actor_reqs    =
    { "type",          "name",         "range", "present"
      "UnitFlag",      "Settlers",     "Local", TRUE
    }

Mining_TF_Possible effect to Plant Enabler[edit | edit source]

Replace any Mining_TF_Possible effect with equivalent Plant Action Enabler. Add explicit requirement of Settlers unit to them.

[effect_mining_tf]
type    = "Mining_TF_Possible"
value   = 1

->

[actionenabler_plant]
action        = "Plant"
actor_reqs    =
    { "type",          "name",         "range", "present"
      "UnitFlag",      "Settlers",     "Local", TRUE
    }

New action enablers[edit | edit source]

Suicide Attack action enabler[edit | edit source]

Missiles' attack of unit getting used in attack has been split to action enabler of its own. The Missile unit class flag is gone. For keeping missiles to work as they used to, add back Missile as a user unit class flag, exclude them from any existing attack related action enablers by present=FALSE requirements, and add a new Suicide Attack action enabler for them.

[actionenabler_explode_missile]
action = "Suicide Attack"
actor_reqs    =
    { "type",          "name",    "range", "present"
      "UnitFlag",      "NonMil",  "Local", FALSE
      "UnitClassFlag", "Missile", "Local", TRUE
      "MinMoveFrags",  "1",       "Local", TRUE
      "DiplRel",       "War",     "Local", TRUE
    }

Pillage action enabler[edit | edit source]

Add new action enabler for Pillaging and add back the CanPillage unit class flag as a user unit class flag to keep it functioning like it used to.

[actionenabler_pillage]
action        = "Pillage"
actor_reqs    =
    { "type",          "name",         "range"
      "UnitClassFlag", "CanPillage",   "Local"
    }

Fortify action enabler[edit | edit source]

Add new action enablers for Fortifying to keep it functioning like it used to.

[actionenabler_fortify_terrain]
action        = "Fortify"
actor_reqs    =
    { "type",          "name",         "range", "present"
      "UnitClassFlag", "CanFortify",   "Local", TRUE
      "UnitFlag",      "Cant_Fortify", "Local", FALSE
      "TerrainFlag",   "NoFortify",    "Local", FALSE
      "Activity",      "Fortified",    "Local", FALSE
    }

[actionenabler_fortify_city]
action        = "Fortify"
actor_reqs    =
    { "type",          "name",         "range", "present"
      "UnitClassFlag", "CanFortify",   "Local", TRUE
      "UnitFlag",      "Cant_Fortify", "Local", FALSE
      "CityTile",      "Center",       "Local", TRUE
      "Activity",      "Fortified",    "Local", FALSE
    }

Road building action enabler[edit | edit source]

Add new action enabler for Road building to keep it functioning like it used to.

[actionenabler_road]
action        = "Build Road"
actor_reqs    =
    { "type",          "name",         "range"
      "UnitFlag",      "Settlers",     "Local"
    }

Base building action enabler[edit | edit source]

Add new action enabler for Base building to keep it functioning like it used to.

[actionenabler_base]
action        = "Build Base"
actor_reqs    =
    { "type",          "name",         "range"
      "UnitFlag",      "Settlers",     "Local"
    }

Pollution and Fallout cleaning[edit | edit source]

Add action enablers for tile cleaning to keep it functioning like it used to.

[actionenabler_clean_pollution]
action        = "Clean Pollution"
actor_reqs    =
    { "type",          "name",         "range", "present"
      "UnitFlag",      "Settlers",     "Local", TRUE
    }

[actionenabler_clean_fallout]
action        = "Clean Fallout"
actor_reqs    =
    { "type",          "name",         "range", "present"
      "UnitFlag",      "Settlers",     "Local", TRUE
    }

Transport entry and exit action enablers[edit | edit source]

Entering to and exiting from a transport unit is now action enabler controlled. "Transport Board" covers cargo initiated entering of the actor unit to a transport on the same tile. "Transport Embark" covers cargo initiated entering of the actor unit to a transport on an adjacent tile. "Transport Alight" covers cargo initiated unloading of the actor from a transport to the current tile. "Transport Unload" covers transporter initiated unloading of a target unit to the current tile. "Transport Disembark" covers cargo initiated transport exit of the actor unit to an adjacent tile.

To keep the old rules add the following action enablers:

[actionenabler_alight]
action        = "Transport Alight"
actor_reqs    =
    { "type",      "name",          "range"
      "UnitState", "OnLivableTile", "Local"
      "UnitState", "Transported",   "Local"
    }
target_reqs    =
    { "type",      "name",         "range"
      "UnitState", "Transporting", "Local"
    }

[actionenabler_board]
action        = "Transport Board"
actor_reqs    =
    { "type",    "name",       "range", "present"
      "DiplRel", "Armistice",  "Local", FALSE
      "DiplRel", "War",        "Local", FALSE
      "DiplRel", "Cease-fire", "Local", FALSE
      "DiplRel", "Peace",      "Local", FALSE
      "DiplRel", "Never met",  "Local", FALSE
    }

[actionenabler_unload]
action        = "Transport Unload"
actor_reqs    =
    { "type",      "name",         "range"
      "UnitState", "Transporting", "Local"
    }
target_reqs    =
    { "type",      "name",          "range"
      "UnitState", "OnLivableTile", "Local"
      "UnitState", "Transported",   "Local"
    }

[actionenabler_disembark]
action        = "Transport Disembark"
actor_reqs    =
    { "type",         "name",        "range"
      "UnitState",    "Transported", "Local"
      "MinMoveFrags", "1",           "Local"
    }

[actionenabler_embark]
action        = "Transport Embark"
actor_reqs    =
    { "type",         "name",       "range", "present"
      "MinMoveFrags", "1",          "Local", TRUE
      "DiplRel",      "Armistice",  "Local", FALSE
      "DiplRel",      "War",        "Local", FALSE
      "DiplRel",      "Cease-fire", "Local", FALSE
      "DiplRel",      "Peace",      "Local", FALSE
      "DiplRel",      "Never met",  "Local", FALSE
    }

Explode Nuclear, Nuke City and Nuke Units[edit | edit source]

3.0's "Explode Nuclear" could only target the actor unit's current tile except when an adjacent tile could be targeted. An adjacent tile could be targeted if it contained an enemy city or an enemy unit stack. One move fragment was always required to target an adjacent tile.

The new actions "Nuke City" and "Nuke Units" has been split from the "Explode Nuclear" action so the above rules could move to the ruleset.

Go over your action requirements that requires "Explode Nuclear". Make them apply to "Nuke City" and "Nuke Units" too.

Create one "Nuke City" and one "Nuke Units" action enabler for each of your 3.0 "Explode Nuclear" enablers. Require that the actor unit has at least one move fragment and war with the target in both. Require that the target unit stack is outside a city in the "Nuke Units" enabler to avoid duplicate enabled nuke actions.

If your original "Explode Nuclear" enabler looks like

[actionenabler_nuke]
action = "Explode Nuclear"
actor_reqs    =
    { "type",   "name", "range", "present"
      "UnitFlag", "Nuclear", "Local", TRUE
    }

it should become the below enablers, including the original.

[actionenabler_nuke]
action = "Explode Nuclear"
actor_reqs    =
    { "type",   "name", "range", "present"
      "UnitFlag", "Nuclear", "Local", TRUE
    }

[actionenabler_nuke_city]
action="Nuke City"
actor_reqs=
    { "type",         "name",    "range"
      "UnitFlag",     "Nuclear", "Local"
      "MinMoveFrags", "1",       "Local"
      "DiplRel",      "War",     "Local"
    }

[actionenabler_nuke_units]
action="Nuke Units"
actor_reqs=
    { "type",         "name",    "range"
      "UnitFlag",     "Nuclear", "Local"
      "MinMoveFrags", "1",       "Local"
      "DiplRel",      "War",     "Local"
    }
target_reqs=
    { "type",     "name",   "range", "present"
      "CityTile", "Center", "Local", FALSE
    }

The max distance between actor and target for "Explode Nuclear", "Nuke City" and "Nuke Units" is set with the game.ruleset file's actions section's explode_nuclear_max_range, nuke_city_max_range and nuke_units_max_range. To match the old rules they should be set as like this:

explode_nuclear_max_range = 0
nuke_city_max_range = 1
nuke_units_max_range = 1

Sabotage City Production (Escape)[edit | edit source]

"Targeted Sabotage City" and "Targeted Sabotage City Escape" were able to target a player specified building or the target city's current production. They have been split in a city production target version and a building in city targeted version.

"Targeted Sabotage City" and "Targeted Sabotage City Escape" targets a player selected building in the target city. "Sabotage City Production" and "Sabotage City Production Escape" targets the city's current production.

To keep the old rules start by going over requirement vectors that requires actions. Make sure that they apply to both the building targeted and the production targeted version.

Then go over your action enablers. Copy each "Targeted Sabotage City" and make the copy about "Sabotage City Production". Copy each "Targeted Sabotage City Escape" and make the copy about "Sabotage City Production Escape".

So

[actionenabler_sabotage_city_target]
action = "Targeted Sabotage City Escape"
actor_reqs    =
    { "type",         "name",          "range"
      "DiplRel",      "War",           "Local"
      "UnitFlag",     "Spy",           "Local"
      "UnitState",    "OnLivableTile", "Local"
      "MinMoveFrags", "1",             "Local"
    }

should become

[actionenabler_sabotage_city_target]
action = "Targeted Sabotage City Escape"
actor_reqs    =
    { "type",         "name",          "range"
      "DiplRel",      "War",           "Local"
      "UnitFlag",     "Spy",           "Local"
      "UnitState",    "OnLivableTile", "Local"
      "MinMoveFrags", "1",             "Local"
    }

[actionenabler_sabotage_city_production]
action = "Sabotage City Production Escape"
actor_reqs    =
    { "type",         "name",          "range"
      "DiplRel",      "War",           "Local"
      "UnitFlag",     "Spy",           "Local"
      "UnitState",    "OnLivableTile", "Local"
      "MinMoveFrags", "1",             "Local"
    }

New in 3.1[edit | edit source]

Some brand new actions that didn't exist in 3.0 have been added. They are completely optional. To keep 3.0 behavior you shouldn't enable them at all.

  • "Surgical Strike Building" - destroy a player specified building.
  • "Surgical Strike Production" - destroy the target city's production.
  • "Spread Plague" - trigger illness in the target city.
  • "Spy Attack" - trigger a diplomatic battle to eliminate tile defenders.
  • "Bombard 2" and "Bombard 3" - perfect copies of "Bombard" for different ruleset defined rules.
  • "User Action 1", "User Action 2" and "User Action 3" - blank actions that should be defined in the ruleset.

Action move cost to the ruleset[edit | edit source]

The new effects Action_Success_Actor_Move_Cost and Action_Success_Target_Move_Cost have been added. Action_Success_Actor_Move_Cost subtracts move fragments from an actor unit after a successfully performed action. Action_Success_Target_Move_Cost does the same for a unit that is the target of an action.

Action_Success_Actor_Move_Cost[edit | edit source]

The actor move fragment price for successful "Establish Embassy", "Investigate City", "Capture Units", "Expel Unit", "Bombard" and "Heal Unit" has moved to the ruleset. The old hard coded move fragment cost was 1 for "Establish Embassy" and "Investigate City", a single move for "Capture Units" and "Expel Unit" and all remaining movement for "Bombard" and "Heal Unit". How many move fragments a single move is is defined in move_fragments in terrain.ruleset. 65535 is large enough to make Freeciv know that all remaining movement is gone when reasoning about an action's move cost. Assuming that move_fragments is 3 the below effects brings the old rules back:

[effect_action_success_move_cost_embassy]
type    = "Action_Success_Actor_Move_Cost"
value   = 1
reqs    =
    { "type", "name", "range", "present"
      "Action", "Establish Embassy", "Local", TRUE
    }

[effect_action_success_move_cost_investigate]
type    = "Action_Success_Actor_Move_Cost"
value   = 1
reqs    =
    { "type", "name", "range", "present"
      "Action", "Investigate City", "Local", TRUE
    }

[effect_action_success_move_cost_capture]
type    = "Action_Success_Actor_Move_Cost"
value   = 3
reqs    =
    { "type", "name", "range", "present"
      "Action", "Capture Units", "Local", TRUE
    }

[effect_action_success_move_cost_expel]
type    = "Action_Success_Actor_Move_Cost"
value   = 3
reqs    =
    { "type", "name", "range", "present"
      "Action", "Expel Unit", "Local", TRUE
    }

[effect_action_success_move_cost_bombard]
type    = "Action_Success_Actor_Move_Cost"
value   = 65535
reqs    =
    { "type", "name", "range", "present"
      "Action", "Bombard", "Local", TRUE
    }

[effect_action_success_move_cost_heal_unit]
type    = "Action_Success_Actor_Move_Cost"
value   = 65535
reqs    =
    { "type", "name", "range", "present"
      "Action", "Heal Unit", "Local", TRUE
    }

Action_Success_Target_Move_Cost[edit | edit source]

The actor move fragment price for successful "Expel Unit" has moved to the ruleset. It took all remaining move fragments. Assuming that move_fragments is 3 the below effects brings the old rules back:

[effect_action_success_move_cost_expelled]
type    = "Action_Success_Target_Move_Cost"
value   = 65535
reqs    =
    { "type", "name", "range", "present"
      "Action", "Expel Unit", "Local", TRUE
    }

Auto attack[edit | edit source]

The auto_attack section in game.ruleset has gained attack_actions, a list of actions that will be tried during an auto attack. It can remove or change the order of the old auto attack actions "Capture Units", "Bombard", "Attack" and "Suicide Attack". The old actions must be added in their old order to keep auto attack working as before.

The auto_attack section's will_never unit flag list has been replaced by the new requirement vector if_attacker. The if_attacker requirement vector must be true for a unit before it even considers to auto attack. This is the opposite of will_never, that contained unit type flags of units the never would consider to auto attack. So add each unit flag from your old will_never as not present UnitFlag requirements. The old hardcoded war requirement and the MinMoveFrags requirement has moved to if_attacker and therefore needs to be added too.

Assuming that your old auto_attack.will_never only contained the Nuclear unit type flag adding the following should keep your ruleset working as it used to:

[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.
;   attack_actions - the actions to try during an auto attack in the order
;                    they should be tried.
;   if_attacker    - this requirement vector must be true before a unit even
;                    considers to auto attack.

attack_actions= "Capture Units", "Bombard", "Attack", "Suicide Attack"

if_attacker =
    { "type",         "name",    "range", "present"
      "DiplRel",      "War",     "Local", TRUE
      "MinMoveFrags", "1",       "Local", TRUE
      ; Not a good idea to nuke our own area.
      "UnitFlag",     "Nuclear", "Local", FALSE
    }

Fortified effect to the ruleset[edit | edit source]

The defense bonus of the Fortified unit activity is now granted by the effect Fortify_Defense_Bonus. To keep the old rules - fortify bonus when fortified and fortify bonus when in a city for units that can fortify - add the following to effects.ruleset.

[effect_fortified]
type    = "Fortify_Defense_Bonus"
value   = 50
reqs    =
    { "type", "name", "range"
      "Activity", "Fortified", "Local"
    }

[effect_city_fortified]
type    = "Fortify_Defense_Bonus"
value   = 50
reqs    =
    { "type",          "name",         "range", "present"
      "CityTile",      "Center",       "Local", TRUE
      "Activity",      "Fortified",    "Local", FALSE
      "UnitClassFlag", "CanFortify",   "Local", TRUE
      "UnitFlag",      "Cant_Fortify", "Local", FALSE
    }

More configurable map theft[edit | edit source]

If you use one of the actions "Steal Maps" or "Steal Maps Escape" you will have to configure what it does. In the actions section of game.ruleset the new variable steal_maps_reveals_all_cities has shown up. It determines if all the victim's city tiles will be revealed to the thief when successfully performing the action. To get the Freeciv 3.0 behavior set it to TRUE.

steal_maps_reveals_all_cities = TRUE

The new effect type Maps_Stolen_Pct modifies the probability - originally 100% - that a tile is revealed on successful map theft. To get about half the map like you did in Freeciv 3.0 set it to -50 - subtracting 50% from 100% ending up with 50%.

[effect_steal_maps_pct]
type	= "Maps_Stolen_Pct"
value	= -50
reqs	=
    { "type", "name", "range", "present"
      "Action", "Steal Maps Escape", "Local", TRUE
    }

New settings in game.ruleset[edit | edit source]

Effects of happiness to Civil War chance[edit | edit source]

Add settings civil_war_bonus_celebrating and civil_war_bonus_unhappy to game.ruleset [civstyle] section. To keep old hardcoded behavior, use values -5 and 5, respectively, for them.

Output granularity[edit | edit source]

Add setting output_granularity to game.ruleset {civstyle] section. Use value 1 to keep old hardcoded behavior.

Nuke effects settings[edit | edit source]

Add settings nuke_pop_loss_pct and nuke_defender_survival_chance_pct to game.ruleset [combat_rules] section. To keep old hardcoded behavior, use values 50 and 0, respectively, for them.

History interest[edit | edit source]

Add setting history_interest_pml to game.ruleset [culture] section. Use value 0 to keep old behavior.

Configurable treaty clauses[edit | edit source]

Add sections for each enabled clause type to game.ruleset. To keep old behavior, enable them all

[clause_advance]
type = "Advance"

[clause_gold]
type = "Gold"

[clause_map]
type = "Map"

[clause_seamap]
type = "Seamap"

[clause_city]
type = "City"

[clause_ceasefire]
type = "Ceasefire"

[clause_peace]
type = "Peace"

[clause_alliance]
type = "Alliance"

[clause_vision]
type = "Vision"

[clause_embassy]
type = "Embassy"

Infrapoints[edit | edit source]

Extra infra cost[edit | edit source]

To completely disallow placing extras via infrapoints, like it used to be, set infracost of every extra type to 0.

Veterancy changes[edit | edit source]

Rename base chance settings[edit | edit source]

Some ruleset settings about veterancy gaining base chance have been renamed in units.ruleset. Replace veteran_raise_chance by veteran_base_raise_chance

Extra removal cause Enter[edit | edit source]

To keep old behavior of hut-type extras, add rmcause Enter for all of them.

AI trait builder has been added[edit | edit source]

The new AI trait "Builder" has been added. Add the following to nations.ruleset

; Value of trait "builder" defines how much AI wants to build buildings
builder_min = 30
builder_max = 90
builder_default = 50

See also[edit | edit source]

Editing Rulesets
Editing BuildingsEditing CitiesEditing EffectsEditing GameEditing Governments
Editing NationsEditing StylesEditing TechsEditing TerrainEditing Units
Update from 2.2 to 2.32.3 to 2.42.4 to 2.52.5 to 2.62.6 to 3.03.0 to 3.1
Community content is available under CC-BY-SA unless otherwise noted.