Note: These are all designed with/for classic (original) map topology (not iso, hex, etc) and classic (original) square tiles. (And default Freeciv ruleset too, v2.6.4.)
AddMoat: This adds a moat (lake tiles) around each city when the city is built -- as though moats are included in the city specifications. Compatible with Freeciv 3+ only. There are a few options mentioned within the script itself (text after "--" are comments, not code.) This will radically change the gameplay experience of any scenario/map as far as early attacks on cities are concerned. Some moat designs will prevent city capture by any land unit at least until Marines or Paratroopers. A land-bridge tile is optional with any moat (a single land tile connecting city to land across the moat.) Without a land bridge, Map Making technology becomes a necessity for land units to cross to or from the city (or Radio for Airports later in the game.)
Code: Select all
--##############################################################################
function Lua_AddMoat(city)
if ( AddMoat == nil ) then AddMoat=true end
-- If this routine is disabled, just return without doing anything else
if not ( AddMoat ) then return end
if not ( ( string.sub(fc_version(),17,19) ) >= "2.6" ) then return end -- the commands used require at least Fc 2.6
if ( debugLuaScripts ) then log.error("%s","AddMoat BEGIN") end
-- Add moat to all cities
-- Consider increasing foodbox cost to slow city growth given that towns are less vulnerable to attack
-- Declare local variables
local owner, moatTerrain, moatStyle, i, x, y, landBridge, topology, count, field, topoFields, h, v
-- If needed global vars aren't set, set them
if ( topology == nil ) or ( _G.wrapX == nil ) or ( _G.wrapY == nil )
or ( _G.xSize == nil ) or ( _G.ySize == nil ) or ( _G.topo == nil )
or ( _G.citymindist == nil ) then
topology=(server.setting.get("topology"))
_G.xSize=tonumber(server.setting.get("xsize"))
_G.ySize=tonumber(server.setting.get("ysize"))
_G.dispersion=(server.setting.get("dispersion"))
_G.citymindist=(server.setting.get("citymindist"))
_G.topo="classic"
_G.wrapX=false
_G.wrapY=false
topoFields={}
-- Split topology field (from scenario settings) to a table
count=1
for field in string.gmatch(topology, "[^|]+") do
topoFields[count]=field
count=(count+1)
end
-- Evaluate topology settings
if ( #topoFields > 0 ) then
for i=1,#topoFields,1 do
if ( topoFields[i] == "WRAPX" ) then _G.wrapX=true
elseif ( topoFields[i] == "WRAPY" ) then _G.wrapY=true
elseif ( topoFields[i] == "ISO" ) then _G.topo="ISO"
elseif ( topoFields[i] == "HEX" ) then _G.topo="HEX" end
end
end
end
if not ( _G.topo == "classic" ) then return end -- AddMoat currently only supports classic topology
-- Declare global function
function _G.is_XY_map_location_valid(x,y)
if ( _G.wrapX and _G.wrapY )
or ( _G.wrapX and ( y >= 0 ) and ( y < _G.ySize ) )
or ( _G.wrapY and ( x >= 0 ) and ( x < _G.xSize ) )
or ( y >= 0 and y < _G.ySize and x >= 0 and x < _G.xSize ) then
return true
else
return false
end
end
x=((city).tile).x y=((city).tile).y
owner=tostring((city).owner)
moatTerrain=find.terrain("Lake")
-- Moat Styles:
-- 1 is next to city, 2 at city radius, 3 is outside city radius,
-- 4 is 5x5 with corners outside city radius
-- 5 is 5x3 horizontal
-- 6 is 3x5 vertical
moatStyle=(random(1,6)) -- or specify # such as 1 for consistent moat style on every city
if moatStyle == 1 then
-- ======= (C is city, # is tile changed to moat, = is unchanged tile)
-- ==###==
-- ==#C#==
-- ==###==
-- =======
-- Next to city, 8 tiles, full moat (no land connection - boat, aircraft, or airport required to/from city)
-- landBridge specifies which tile to leave for land access, or none if greater than # in tile list
-- Note that on moatStyle=1, a diagonal tile for landBridge leaves open city blindspot attack by fast attack units
h={-1,-1,-1, 0, 0, 1, 1, 1}
v={-1, 0, 1,-1, 1,-1, 0, 1}
landBridge=(random(1,9)) -- for 8 possible positions and 9=none
elseif moatStyle == 2 then
-- ==###==
-- =##=##=
-- =#=C=#=
-- =##=##=
-- ==###==
-- inside edge of city radius, 16 tiles
-- ToDo: Don't plot moat across neightboring moat (only applies if citymindist is too low)
h={-1,-0, 1,-2,-1, 1, 2,-2, 2,-2,-1, 1, 2,-1,-0, 1}
v={-2,-2,-2,-1,-1,-1,-1, 0, 0, 1, 1, 1, 1, 2, 2, 2}
landBridge=(random(1,17))
elseif moatStyle == 3 then
-- =#####=
-- ##===##
-- #=====#
-- #==C==#
-- #=====#
-- ##===##
-- =#####=
-- Outside city radius, 24 tiles
-- ToDo: Don't plot moat across neightboring moat (only applies if citymindist is too low)
h={-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-3,-2, 2, 3,-3,-3,-3, 3, 3, 3,-3,-2, 2, 3}
v={-3,-3,-3,-3,-3, 3, 3, 3, 3, 3,-2,-2,-2,-2,-1, 0, 1,-1, 0, 1, 2, 2, 2, 2}
landBridge=(random(1,25))
elseif moatStyle == 4 then
-- =#####=
-- =#===#=
-- =#=C=#=
-- =#===#=
-- =#####=
-- Within city radius + 4 corner tiles, 16 tiles
h={-2,-2,-2,-2,-2, 2, 2, 2, 2, 2,-1, 0, 1,-1, 0, 1}
v={-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-2,-2, 2, 2, 2}
landBridge=(random(1,17))
elseif moatStyle == 5 then
-- =======
-- =#####=
-- =#=C=#=
-- =#####=
-- =======
-- Within city radius, 12 tiles
h={-2,-1, 0, 1, 2,-2, 2,-2,-1, 0, 1, 2}
v={-1,-1,-1,-1,-1, 0, 0, 1, 1, 1, 1, 1}
landBridge=(random(1,13))
elseif moatStyle == 6 then
-- ==###==
-- ==#=#==
-- ==#C#==
-- ==#=#==
-- ==###==
-- Within city radius, 12 tiles
h={-1,-1,-1,-1,-1, 1, 1, 1, 1, 1, 0, 0}
v={-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2, 2}
landBridge=(random(1,13))
end
-- ToDo: Check if parts of moat area are already water tiles, especially if landbridge tile is water, then pick another?
for i=1,#h,1 do
if not (i == landBridge) then
if _G.is_XY_map_location_valid( (h[i]+x),(v[i]+y) ) then
moatTile=find.tile((h[i]+x),(v[i]+y))
if not ( moatTile.terrain.id == find.terrain("Lake").id )
and not ( moatTile.terrain.id == find.terrain("Ocean").id )
and not ( moatTile.terrain.id == find.terrain("Deep Ocean").id )
and not ( moatTile.terrain.id == find.terrain("Inaccessible").id ) then
if ( ( string.sub(fc_version(),17,19) ) >= "2.6" )
and ( ( string.sub(fc_version(),17,19) ) < "3.0" ) then
edit.create_extra(moatTile,"River") -- for Freeciv v2 testing purpose only
elseif ( ( string.sub(fc_version(),17,19) ) >= "3.0" ) then
edit.change_terrain(moatTile, moatTerrain)
end
end
end
end
end
if ( debugLuaScripts ) then log.error("%s","AddMoat END") end
end
signal.connect("city_built", "Lua_AddMoat")
Attached file "RandoMap Lua AddMoat only" is a scenario file for Freeciv 2.6 and later with only the AddMoat Lua script included. If testing with Freeciv 2.6, river will be added to tiles where moat would be in Freeciv 3. The scenario file FairTest has all the Lua scripts included, and is attached to my latest post in this topic.
To add the script to a scenario or to an uncompressed saved game text file ( .sav ), copy and paste the script into the scenario file between the $$ (dollar signs) in the "[script] code=$$" section of the file.
[script]
code=$
-- paste script here
$
vars=$$