1
0
mirror of https://github.com/veden/Rampant.git synced 2025-02-03 13:11:54 +02:00

need to move settlers to two step pathfinding

This commit is contained in:
Aaron Veden 2019-10-13 22:49:52 -07:00
parent 1536f7f70c
commit b032668f74
14 changed files with 721 additions and 515 deletions

View File

@ -31,204 +31,201 @@ function upgrade.attempt(natives)
global.version = constants.VERSION_5 global.version = constants.VERSION_5
end end
if (global.version < constants.VERSION_10) then if (global.version < constants.VERSION_10) then
for _,squad in pairs(natives.squads) do for _,squad in pairs(natives.squads) do
squad.frenzy = false squad.frenzy = false
squad.frenzyPosition = {x=0,y=0} squad.frenzyPosition = {x=0,y=0}
squad.rabid = false squad.rabid = false
end end
global.version = constants.VERSION_10 global.version = constants.VERSION_10
end end
if (global.version < constants.VERSION_11) then if (global.version < constants.VERSION_11) then
natives.state = constants.AI_STATE_AGGRESSIVE natives.state = constants.AI_STATE_AGGRESSIVE
natives.temperament = 0 natives.temperament = 0
global.version = constants.VERSION_11 global.version = constants.VERSION_11
end end
if (global.version < constants.VERSION_12) then if (global.version < constants.VERSION_12) then
for _,squad in pairs(natives.squads) do for _,squad in pairs(natives.squads) do
squad.status = constants.SQUAD_GUARDING squad.status = constants.SQUAD_GUARDING
squad.kamikaze = false squad.kamikaze = false
end end
-- reset ai build points due to error in earning points -- reset ai build points due to error in earning points
natives.points = 0 natives.points = 0
global.version = constants.VERSION_12 global.version = constants.VERSION_12
end end
if (global.version < constants.VERSION_16) then if (global.version < constants.VERSION_16) then
natives.lastShakeMessage = 0 natives.lastShakeMessage = 0
--remove version 14 retreat limit, it has been made redundant --remove version 14 retreat limit, it has been made redundant
natives.retreats = nil natives.retreats = nil
game.surfaces[natives.activeSurface].print("Rampant - Version 0.14.13") game.surfaces[natives.activeSurface].print("Rampant - Version 0.14.13")
global.version = constants.VERSION_16 global.version = constants.VERSION_16
end end
if (global.version < constants.VERSION_18) then if (global.version < constants.VERSION_18) then
natives.safeEntities = {} natives.safeEntities = {}
natives.safeEntityName = {} natives.safeEntityName = {}
game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.5") game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.5")
global.version = constants.VERSION_18 global.version = constants.VERSION_18
end end
if (global.version < constants.VERSION_20) then if (global.version < constants.VERSION_20) then
natives.aiPointsScaler = settings.global["rampant-aiPointsScaler"].value natives.aiPointsScaler = settings.global["rampant-aiPointsScaler"].value
natives.aiNocturnalMode = settings.global["rampant-permanentNocturnal"].value natives.aiNocturnalMode = settings.global["rampant-permanentNocturnal"].value
game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.8") game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.8")
global.version = constants.VERSION_20 global.version = constants.VERSION_20
end end
if (global.version < constants.VERSION_22) then if (global.version < constants.VERSION_22) then
-- been made redundant -- been made redundant
natives.rallyCries = nil natives.rallyCries = nil
-- needs to be on inner logic tick loop interval -- needs to be on inner logic tick loop interval
natives.stateTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC) natives.stateTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC)
natives.temperamentTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC) natives.temperamentTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC)
--[[ --[[
For making changes to maps that haven't had Rampant loaded and aren't starting from a brand new map For making changes to maps that haven't had Rampant loaded and aren't starting from a brand new map
Was causing desyncs when client connected before having the below settings saved into the map 0.15.15 factorio Was causing desyncs when client connected before having the below settings saved into the map 0.15.15 factorio
--]] --]]
-- game.map_settings.path_finder.short_request_ratio = constants.PATH_FINDER_SHORT_REQUEST_RATIO -- game.map_settings.path_finder.short_request_ratio = constants.PATH_FINDER_SHORT_REQUEST_RATIO
-- game.map_settings.path_finder.short_cache_size = constants.PATH_FINDER_SHORT_CACHE_SIZE -- game.map_settings.path_finder.short_cache_size = constants.PATH_FINDER_SHORT_CACHE_SIZE
-- game.map_settings.path_finder.long_cache_size = constants.PATH_FINDER_LONG_REQUEST_RATIO -- game.map_settings.path_finder.long_cache_size = constants.PATH_FINDER_LONG_REQUEST_RATIO
game.map_settings.unit_group.max_group_radius = constants.UNIT_GROUP_MAX_RADIUS -- game.map_settings.unit_group.max_group_radius = constants.UNIT_GROUP_MAX_RADIUS
game.map_settings.unit_group.max_member_speedup_when_behind = constants.UNIT_GROUP_MAX_SPEED_UP
game.map_settings.unit_group.max_member_slowdown_when_ahead = constants.UNIT_GROUP_MAX_SLOWDOWN
game.map_settings.unit_group.max_group_slowdown_factor = constants.UNIT_GROUP_SLOWDOWN_FACTOR
game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.10") game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.10")
global.version = constants.VERSION_22 global.version = constants.VERSION_22
end end
if (global.version < constants.VERSION_23) then if (global.version < constants.VERSION_23) then
-- used to precompute some values per logic cycle -- used to precompute some values per logic cycle
natives.retreatThreshold = 0 natives.retreatThreshold = 0
-- natives.maxSquads = 0 -- natives.maxSquads = 0
natives.rallyThreshold = 0 natives.rallyThreshold = 0
natives.formSquadThreshold = 0 natives.formSquadThreshold = 0
natives.attackWaveSize = 0 natives.attackWaveSize = 0
natives.attackWaveDeviation = 0 natives.attackWaveDeviation = 0
natives.attackWaveUpperBound = 0 natives.attackWaveUpperBound = 0
natives.unitRefundAmount = 0 natives.unitRefundAmount = 0
-- natives.attackWaveThreshold = 0 -- natives.attackWaveThreshold = 0
game.map_settings.unit_group.member_disown_distance = constants.UNIT_GROUP_DISOWN_DISTANCE -- game.map_settings.unit_group.member_disown_distance = constants.UNIT_GROUP_DISOWN_DISTANCE
game.map_settings.unit_group.tick_tolerance_when_member_arrives = constants.UNIT_GROUP_TICK_TOLERANCE -- game.map_settings.unit_group.tick_tolerance_when_member_arrives = constants.UNIT_GROUP_TICK_TOLERANCE
-- used for breaking up how many squads are processing per logic cycle -- used for breaking up how many squads are processing per logic cycle
natives.regroupIndex = 1 natives.regroupIndex = 1
natives.randomGenerator = game.create_random_generator(settings.startup["rampant-enemySeed"].value+1024) natives.randomGenerator = game.create_random_generator(settings.startup["rampant-enemySeed"].value+1024)
game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.11") game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.11")
global.version = constants.VERSION_23 global.version = constants.VERSION_23
end end
if (global.version < constants.VERSION_25) then if (global.version < constants.VERSION_25) then
game.map_settings.path_finder.min_steps_to_check_path_find_termination = constants.PATH_FINDER_MIN_STEPS_TO_CHECK_PATH game.map_settings.path_finder.min_steps_to_check_path_find_termination = constants.PATH_FINDER_MIN_STEPS_TO_CHECK_PATH
game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.15") game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.15")
global.version = constants.VERSION_25 global.version = constants.VERSION_25
end end
if (global.version < constants.VERSION_26) then if (global.version < constants.VERSION_26) then
game.map_settings.max_failed_behavior_count = constants.MAX_FAILED_BEHAVIORS game.map_settings.max_failed_behavior_count = constants.MAX_FAILED_BEHAVIORS
game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.16") game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.16")
global.version = constants.VERSION_26 global.version = constants.VERSION_26
end end
if (global.version < constants.VERSION_27) then if (global.version < constants.VERSION_27) then
game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.17") game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.17")
global.version = constants.VERSION_27 global.version = constants.VERSION_27
end end
if (global.version < constants.VERSION_33) then if (global.version < constants.VERSION_33) then
global.world = nil global.world = nil
game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.23") game.surfaces[natives.activeSurface].print("Rampant - Version 0.15.23")
global.version = constants.VERSION_33 global.version = constants.VERSION_33
end end
if (global.version < constants.VERSION_38) then if (global.version < constants.VERSION_38) then
for _,squad in pairs(natives.squads) do for _,squad in pairs(natives.squads) do
squad.chunk = nil squad.chunk = nil
end end
global.regionMap = nil global.regionMap = nil
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.3") game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.3")
global.version = constants.VERSION_38 global.version = constants.VERSION_38
end end
if (global.version < constants.VERSION_41) then if (global.version < constants.VERSION_41) then
natives.evolutionTableUnitSpawner = {} natives.evolutionTableUnitSpawner = {}
natives.evolutionTableWorm = {} natives.evolutionTableWorm = {}
natives.evolutionTableAlignment = {} natives.evolutionTableAlignment = {}
natives.bases = {} natives.bases = {}
natives.baseIndex = 1 natives.baseIndex = 1
natives.baseIncrement = 0 natives.baseIncrement = 0
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.6") game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.6")
global.version = constants.VERSION_41 global.version = constants.VERSION_41
end end
if (global.version < constants.VERSION_44) then if (global.version < constants.VERSION_44) then
natives.kamikazeThreshold = 0 natives.kamikazeThreshold = 0
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.9") game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.9")
global.version = constants.VERSION_44 global.version = constants.VERSION_44
end end
if (global.version < constants.VERSION_51) then if (global.version < constants.VERSION_51) then
natives.scouts = nil natives.scouts = nil
natives.tunnels = nil natives.tunnels = nil
natives.baseLookup = nil natives.baseLookup = nil
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.16") game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.16")
global.version = constants.VERSION_51 global.version = constants.VERSION_51
end end
if (global.version < constants.VERSION_57) then if (global.version < constants.VERSION_57) then
natives.attackWaveLowerBound = 1 natives.attackWaveLowerBound = 1
for _,squad in pairs(natives.squads) do for _,squad in pairs(natives.squads) do
squad.maxDistance = 0 squad.maxDistance = 0
squad.originPosition = { squad.originPosition = {
x = 0, x = 0,
y = 0 y = 0
} }
squad.settlers = false squad.settlers = false
end end
natives.expansion = game.map_settings.enemy_expansion.enabled natives.expansion = game.map_settings.enemy_expansion.enabled
natives.expansionMaxDistance = game.map_settings.enemy_expansion.max_expansion_distance * CHUNK_SIZE natives.expansionMaxDistance = game.map_settings.enemy_expansion.max_expansion_distance * CHUNK_SIZE
natives.expansionMaxDistanceDerivation = natives.expansionMaxDistance * 0.33 natives.expansionMaxDistanceDerivation = natives.expansionMaxDistance * 0.33
natives.expansionMinTime = game.map_settings.enemy_expansion.min_expansion_cooldown natives.expansionMinTime = game.map_settings.enemy_expansion.min_expansion_cooldown
natives.expansionMaxTime = game.map_settings.enemy_expansion.max_expansion_cooldown natives.expansionMaxTime = game.map_settings.enemy_expansion.max_expansion_cooldown
natives.expansionMinSize = game.map_settings.enemy_expansion.settler_group_min_size natives.expansionMinSize = game.map_settings.enemy_expansion.settler_group_min_size
natives.expansionMaxSize = game.map_settings.enemy_expansion.settler_group_max_size natives.expansionMaxSize = game.map_settings.enemy_expansion.settler_group_max_size
natives.settlerCooldown = 0 natives.settlerCooldown = 0
natives.settlerWaveDeviation = 0 natives.settlerWaveDeviation = 0
natives.settlerWaveSize = 0 natives.settlerWaveSize = 0
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.22") game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.22")
global.version = constants.VERSION_57 global.version = constants.VERSION_57
end end
if (global.version < constants.VERSION_72) then if (global.version < constants.VERSION_72) then
for _,squad in pairs(natives.squads) do for _,squad in pairs(natives.squads) do
squad.status = SQUAD_GUARDING squad.status = SQUAD_GUARDING
squad.cycles = 0 squad.cycles = 0
end end
for _,base in pairs(natives.bases) do for _,base in pairs(natives.bases) do
base.temperament = 0 base.temperament = 0
@ -242,23 +239,23 @@ function upgrade.attempt(natives)
natives.nextChunkSortTick = 0 natives.nextChunkSortTick = 0
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.37") game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.37")
global.version = constants.VERSION_72 global.version = constants.VERSION_72
end end
if (global.version < constants.VERSION_75) then if (global.version < constants.VERSION_75) then
for _,squad in pairs(natives.squads) do for _,squad in pairs(natives.squads) do
squad.attackScoreFunction = ATTACK_SCORE squad.attackScoreFunction = ATTACK_SCORE
end end
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.40") game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.40")
global.version = constants.VERSION_75 global.version = constants.VERSION_75
end end
if (global.version < constants.VERSION_76) then if (global.version < constants.VERSION_76) then
natives.drainPylons = {} natives.drainPylons = {}
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.41") game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.41")
global.version = constants.VERSION_76 global.version = constants.VERSION_76
end end
if (global.version < constants.VERSION_77) then if (global.version < constants.VERSION_77) then
@ -313,14 +310,28 @@ function upgrade.attempt(natives)
game.surfaces[natives.activeSurface].print("Rampant - Version 0.17.28") game.surfaces[natives.activeSurface].print("Rampant - Version 0.17.28")
global.version = 95 global.version = 95
end end
if (global.version < 96) then if (global.version < 99) then
game.map_settings.unit_group.min_group_radius = constants.UNIT_GROUP_MAX_RADIUS * 0.5
game.map_settings.unit_group.max_group_radius = constants.UNIT_GROUP_MAX_RADIUS
game.map_settings.unit_group.member_disown_distance = constants.UNIT_GROUP_DISOWN_DISTANCE
game.map_settings.unit_group.tick_tolerance_when_member_arrives = constants.UNIT_GROUP_TICK_TOLERANCE
game.map_settings.unit_group.max_member_speedup_when_behind = constants.UNIT_GROUP_MAX_SPEED_UP
game.map_settings.unit_group.max_member_slowdown_when_ahead = constants.UNIT_GROUP_MAX_SLOWDOWN
game.map_settings.unit_group.max_group_slowdown_factor = constants.UNIT_GROUP_SLOWDOWN_FACTOR
for i=#natives.squads,1,-1 do for i=#natives.squads,1,-1 do
natives.squads[i].penalties = {} natives.squads[i].penalties = {}
if not natives.squads[i].chunk then
natives.squads[i].chunk = SENTINEL_IMPASSABLE_CHUNK
end
end end
game.surfaces[natives.activeSurface].print("Rampant - Version 0.17.29") game.surfaces[natives.activeSurface].print("Rampant - Version 0.17.29")
global.version = 96 global.version = 99
end end
return starting ~= global.version, natives return starting ~= global.version, natives
@ -329,8 +340,8 @@ end
function upgrade.compareTable(entities, option, new) function upgrade.compareTable(entities, option, new)
local changed = false local changed = false
if (entities[option] ~= new) then if (entities[option] ~= new) then
entities[option] = new entities[option] = new
changed = true changed = true
end end
return changed, new return changed, new
end end

View File

@ -1,3 +1,12 @@
---------------------------------------------------------------------------------------------------
Version: 0.17.29
Date: 10. 13. 2019
Improvements:
- Pathfinding now looks two steps ahead and using the compound command
- Squad formation now has a gathering delay to allow all members to make the initial group
Bugfixes:
- Fixed old savegames penalties having nil chunk index
--------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------
Version: 0.17.28 Version: 0.17.28
Date: 8. 17. 2019 Date: 8. 17. 2019

View File

@ -56,6 +56,8 @@ local DEFINES_COMMAND_FLEE = defines.command.flee
local DEFINES_COMMAND_STOP = defines.command.stop local DEFINES_COMMAND_STOP = defines.command.stop
local DEFINES_COMPOUND_COMMAND_RETURN_LAST = defines.compound_command.return_last local DEFINES_COMPOUND_COMMAND_RETURN_LAST = defines.compound_command.return_last
local DEFINES_COMPOUND_COMMAND_AND = defines.compound_command.logical_and
local DEFINES_COMPOUND_COMMAND_OR = defines.compound_command.logical_or
local CHUNK_SIZE = constants.CHUNK_SIZE local CHUNK_SIZE = constants.CHUNK_SIZE
@ -240,6 +242,10 @@ local function rebuildMap()
x=0, x=0,
y=0 y=0
} }
map.position2 = {
x=0,
y=0
}
map.scentStaging = {} map.scentStaging = {}
@ -307,15 +313,30 @@ local function rebuildMap()
map.attackCommand = { map.attackCommand = {
type = DEFINES_COMMAND_ATTACK_AREA, type = DEFINES_COMMAND_ATTACK_AREA,
destination = map.position, destination = map.position,
radius = CHUNK_SIZE, radius = CHUNK_SIZE * 1.5,
distraction = DEFINES_DISTRACTION_BY_ANYTHING
}
map.attack2Command = {
type = DEFINES_COMMAND_ATTACK_AREA,
destination = map.position2,
radius = CHUNK_SIZE * 1.5,
distraction = DEFINES_DISTRACTION_BY_ANYTHING distraction = DEFINES_DISTRACTION_BY_ANYTHING
} }
map.moveCommand = { map.moveCommand = {
type = DEFINES_COMMAND_GO_TO_LOCATION, type = DEFINES_COMMAND_GO_TO_LOCATION,
destination = map.position, destination = map.position,
radius = 6, radius = 1,
pathfind_flags = { prefer_straight_paths = true }, pathfind_flags = { prefer_straight_paths = true, cache = true },
distraction = DEFINES_DISTRACTION_BY_ENEMY
}
map.move2Command = {
type = DEFINES_COMMAND_GO_TO_LOCATION,
destination = map.position2,
radius = 1,
pathfind_flags = { prefer_straight_paths = true, cache = true },
distraction = DEFINES_DISTRACTION_BY_ENEMY distraction = DEFINES_DISTRACTION_BY_ENEMY
} }
@ -346,6 +367,33 @@ local function rebuildMap()
} }
} }
map.compoundMoveMoveCommand = {
type = DEFINES_COMMMAD_COMPOUND,
structure_type = DEFINES_COMPOUND_COMMAND_RETURN_LAST,
commands = {
map.moveCommand,
map.move2Command
}
}
map.compoundMoveAttackCommand = {
type = DEFINES_COMMMAD_COMPOUND,
structure_type = DEFINES_COMPOUND_COMMAND_RETURN_LAST,
commands = {
map.moveCommand,
map.attack2Command
}
}
map.compoundAttackAttackCommand = {
type = DEFINES_COMMMAD_COMPOUND,
structure_type = DEFINES_COMPOUND_COMMAND_RETURN_LAST,
commands = {
map.attackCommand,
map.attack2Command
}
}
map.retreatCommand = { map.retreatCommand = {
type = DEFINES_COMMAND_GROUP, type = DEFINES_COMMAND_GROUP,
group = nil, group = nil,
@ -856,6 +904,25 @@ local function onInit()
hookEvents() hookEvents()
end end
local function onCommandDebugger(event)
for i=1,#natives.squads do
if (natives.squads[i].group.valid) and (natives.squads[i].group.group_number == event.unit_number) then
local msg
if (event.result == defines.behavior_result.in_progress) then
msg = "progress"
elseif (event.result == defines.behavior_result.fail) then
msg = "fail"
elseif (event.result == defines.behavior_result.success) then
msg = "success"
elseif (event.result == defines.behavior_result.deleted) then
msg = "deleted"
end
print(msg, event.unit_number)
return
end
end
end
local function onForceCreated(event) local function onForceCreated(event)
map.activePlayerForces[#map.activePlayerForces+1] = event.force.name map.activePlayerForces[#map.activePlayerForces+1] = event.force.name
end end
@ -894,6 +961,8 @@ script.on_event({defines.events.on_built_entity,
defines.events.on_robot_built_entity, defines.events.on_robot_built_entity,
defines.events.script_raised_built}, onBuild) defines.events.script_raised_built}, onBuild)
-- script.on_event(defines.events.on_ai_command_completed, onCommandDebugger)
script.on_event(defines.events.on_rocket_launched, onRocketLaunch) script.on_event(defines.events.on_rocket_launched, onRocketLaunch)
script.on_event(defines.events.on_entity_died, onDeath) script.on_event(defines.events.on_entity_died, onDeath)
script.on_event(defines.events.on_chunk_generated, onChunkGenerated) script.on_event(defines.events.on_chunk_generated, onChunkGenerated)

View File

@ -79,40 +79,40 @@ end
if settings.startup["rampant-enableSwarm"].value then if settings.startup["rampant-enableSwarm"].value then
for k, unit in pairs(data.raw["unit"]) do for k, unit in pairs(data.raw["unit"]) do
if (string.find(k, "biter") or string.find(k, "spitter")) and unit.collision_box then if (string.find(k, "biter") or string.find(k, "spitter")) and unit.collision_box then
unit.collision_box = { unit.collision_box = {
{unit.collision_box[1][1] * 0.20, unit.collision_box[1][2] * 0.20}, {unit.collision_box[1][1] * 0.20, unit.collision_box[1][2] * 0.20},
{unit.collision_box[2][1] * 0.20, unit.collision_box[2][2] * 0.20} {unit.collision_box[2][1] * 0.20, unit.collision_box[2][2] * 0.20}
} }
-- if unit.collision_mask == nil then if unit.collision_mask == nil then
-- unit.collision_mask = {"player-layer", "train-layer", "not-colliding-with-itself"} unit.collision_mask = {"player-layer", "train-layer", "not-colliding-with-itself"}
-- else else
-- unit.collision_mask[#unit.collision_mask+1] = "not-colliding-with-itself" unit.collision_mask[#unit.collision_mask+1] = "not-colliding-with-itself"
-- end end
unit.ai_settings = { destroy_when_commands_fail = false, allow_try_return_to_spawner = false, path_resolution_modifier = -8, do_seperation = false } unit.ai_settings = { destroy_when_commands_fail = false, allow_try_return_to_spawner = false, path_resolution_modifier = -8, do_seperation = false }
end end
end end
end end
if settings.startup["rampant-enableShrinkNestsAndWorms"].value then if settings.startup["rampant-enableShrinkNestsAndWorms"].value then
for k, unit in pairs(data.raw["unit-spawner"]) do for k, unit in pairs(data.raw["unit-spawner"]) do
if (string.find(k, "biter") or string.find(k, "spitter")) and unit.collision_box then if (string.find(k, "biter") or string.find(k, "spitter")) and unit.collision_box then
unit.collision_mask = {"player-layer", "train-layer", "not-colliding-with-itself"} -- unit.collision_mask = {"player-layer", "train-layer"}
unit.collision_box = { unit.collision_box = {
{unit.collision_box[1][1] * 0.50, unit.collision_box[1][2] * 0.50}, {unit.collision_box[1][1] * 0.50, unit.collision_box[1][2] * 0.50},
{unit.collision_box[2][1] * 0.50, unit.collision_box[2][2] * 0.50} {unit.collision_box[2][1] * 0.50, unit.collision_box[2][2] * 0.50}
} }
end end
end end
for k, unit in pairs(data.raw["turret"]) do for k, unit in pairs(data.raw["turret"]) do
if string.find(k, "worm") and unit.collision_box then if string.find(k, "worm") and unit.collision_box then
unit.collision_box = { unit.collision_box = {
{unit.collision_box[1][1] * 0.50, unit.collision_box[1][2] * 0.50}, {unit.collision_box[1][1] * 0.50, unit.collision_box[1][2] * 0.50},
{unit.collision_box[2][1] * 0.50, unit.collision_box[2][2] * 0.50} {unit.collision_box[2][1] * 0.50, unit.collision_box[2][2] * 0.50}
} }
end end
end end
end end

View File

@ -122,21 +122,21 @@ end
function aiAttackWave.rallyUnits(chunk, map, surface, natives, tick) function aiAttackWave.rallyUnits(chunk, map, surface, natives, tick)
if ((tick - getRallyTick(map, chunk) > INTERVAL_RALLY) and (natives.points >= AI_VENGENCE_SQUAD_COST)) then if ((tick - getRallyTick(map, chunk) > INTERVAL_RALLY) and (natives.points >= AI_VENGENCE_SQUAD_COST)) then
setRallyTick(map, chunk, tick) setRallyTick(map, chunk, tick)
local cX = chunk.x local cX = chunk.x
local cY = chunk.y local cY = chunk.y
for x=cX - RALLY_CRY_DISTANCE, cX + RALLY_CRY_DISTANCE, 32 do for x=cX - RALLY_CRY_DISTANCE, cX + RALLY_CRY_DISTANCE, 32 do
for y=cY - RALLY_CRY_DISTANCE, cY + RALLY_CRY_DISTANCE, 32 do for y=cY - RALLY_CRY_DISTANCE, cY + RALLY_CRY_DISTANCE, 32 do
if (x ~= cX) and (y ~= cY) then if (x ~= cX) and (y ~= cY) then
local rallyChunk = getChunkByXY(map, x, y) local rallyChunk = getChunkByXY(map, x, y)
if (rallyChunk ~= SENTINEL_IMPASSABLE_CHUNK) and (getNestCount(map, rallyChunk) > 0) then if (rallyChunk ~= SENTINEL_IMPASSABLE_CHUNK) and (getNestCount(map, rallyChunk) > 0) then
if not aiAttackWave.formVengenceSquad(map, surface, natives, rallyChunk) then if not aiAttackWave.formVengenceSquad(map, surface, natives, rallyChunk) then
return return
end end
end end
end end
end end
end end
end end
end end
@ -144,14 +144,14 @@ local function noNearbySettlers(map, chunk, tick)
local cX = chunk.x local cX = chunk.x
local cY = chunk.y local cY = chunk.y
for x=cX - SETTLER_DISTANCE, cX + SETTLER_DISTANCE, 32 do for x=cX - SETTLER_DISTANCE, cX + SETTLER_DISTANCE, 32 do
for y=cY - SETTLER_DISTANCE, cY + SETTLER_DISTANCE, 32 do for y=cY - SETTLER_DISTANCE, cY + SETTLER_DISTANCE, 32 do
if (x ~= cX) and (y ~= cY) then if (x ~= cX) and (y ~= cY) then
local c = getChunkByXY(map, x, y) local c = getChunkByXY(map, x, y)
if (c ~= SENTINEL_IMPASSABLE_CHUNK) and ((tick - getChunkSettlerTick(map, c)) < 0) then if (c ~= SENTINEL_IMPASSABLE_CHUNK) and ((tick - getChunkSettlerTick(map, c)) < 0) then
return false return false
end end
end end
end end
end end
return true return true
end end
@ -173,31 +173,31 @@ function aiAttackWave.formSettlers(map, surface, natives, chunk, tick)
map) map)
end end
if (squadPath ~= SENTINEL_IMPASSABLE_CHUNK) and noNearbySettlers(map, chunk, tick) then if (squadPath ~= SENTINEL_IMPASSABLE_CHUNK) and noNearbySettlers(map, chunk, tick) then
local squadPosition = surface.find_non_colliding_position("chunk-scanner-squad-rampant", local squadPosition = surface.find_non_colliding_position("chunk-scanner-squad-rampant",
positionFromDirectionAndChunk(squadDirection, positionFromDirectionAndChunk(squadDirection,
chunk, chunk,
map.position, map.position,
0.98), 0.98),
CHUNK_SIZE, CHUNK_SIZE,
4, 4,
true) true)
if squadPosition then if squadPosition then
local squad = createSquad(squadPosition, surface, nil, true) local squad = createSquad(squadPosition, surface, nil, true)
squad.maxDistance = gaussianRandomRange(natives.expansionMaxDistance * 0.5, squad.maxDistance = gaussianRandomRange(natives.expansionMaxDistance * 0.5,
natives.expansionMaxDistanceDerivation, natives.expansionMaxDistanceDerivation,
10, 10,
natives.expansionMaxDistance) natives.expansionMaxDistance)
local scaledWaveSize = settlerWaveScaling(natives) local scaledWaveSize = settlerWaveScaling(natives)
map.formGroupCommand.group = squad.group map.formGroupCommand.group = squad.group
map.formCommand.unit_count = scaledWaveSize map.formCommand.unit_count = scaledWaveSize
local foundUnits = surface.set_multi_command(map.formCommand) local foundUnits = surface.set_multi_command(map.formCommand)
if (foundUnits > 0) then if (foundUnits > 0) then
setChunkSettlerTick(map, squadPath, tick + natives.settlerCooldown) setChunkSettlerTick(map, squadPath, tick + natives.settlerCooldown)
natives.pendingAttack[#natives.pendingAttack+1] = squad natives.pendingAttack[#natives.pendingAttack+1] = squad
natives.points = natives.points - AI_SETTLER_COST natives.points = natives.points - AI_SETTLER_COST
else else
if (squad.group.valid) then if (squad.group.valid) then
squad.group.destroy() squad.group.destroy()
@ -214,38 +214,38 @@ function aiAttackWave.formVengenceSquad(map, surface, natives, chunk)
if (mRandom() < natives.formSquadThreshold) and (#natives.squads < AI_MAX_SQUAD_COUNT) if (mRandom() < natives.formSquadThreshold) and (#natives.squads < AI_MAX_SQUAD_COUNT)
then then
local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y),
validUnitGroupLocation, validUnitGroupLocation,
scoreUnitGroupLocation, scoreUnitGroupLocation,
map) map)
if (squadPath ~= SENTINEL_IMPASSABLE_CHUNK) then if (squadPath ~= SENTINEL_IMPASSABLE_CHUNK) then
local squadPosition = surface.find_non_colliding_position("chunk-scanner-squad-rampant", local squadPosition = surface.find_non_colliding_position("chunk-scanner-squad-rampant",
positionFromDirectionAndChunk(squadDirection, positionFromDirectionAndChunk(squadDirection,
chunk, chunk,
map.position, map.position,
0.98), 0.98),
CHUNK_SIZE, CHUNK_SIZE,
4, 4,
true) true)
if squadPosition then if squadPosition then
local squad = createSquad(squadPosition, surface) local squad = createSquad(squadPosition, surface)
squad.rabid = mRandom() < 0.03 squad.rabid = mRandom() < 0.03
local scaledWaveSize = attackWaveScaling(natives) local scaledWaveSize = attackWaveScaling(natives)
map.formGroupCommand.group = squad.group map.formGroupCommand.group = squad.group
map.formCommand.unit_count = scaledWaveSize map.formCommand.unit_count = scaledWaveSize
local foundUnits = surface.set_multi_command(map.formCommand) local foundUnits = surface.set_multi_command(map.formCommand)
if (foundUnits > 0) then if (foundUnits > 0) then
natives.pendingAttack[#natives.pendingAttack+1] = squad natives.pendingAttack[#natives.pendingAttack+1] = squad
natives.points = natives.points - AI_VENGENCE_SQUAD_COST natives.points = natives.points - AI_VENGENCE_SQUAD_COST
else else
if (squad.group.valid) then if (squad.group.valid) then
squad.group.destroy() squad.group.destroy()
end end
end end
end end
end end
end end
return (natives.points - AI_VENGENCE_SQUAD_COST) > 0 return (natives.points - AI_VENGENCE_SQUAD_COST) > 0
@ -256,31 +256,31 @@ function aiAttackWave.formSquads(map, surface, natives, chunk, tick)
(mRandom() < natives.formSquadThreshold) and (mRandom() < natives.formSquadThreshold) and
(#natives.squads < AI_MAX_SQUAD_COUNT) (#natives.squads < AI_MAX_SQUAD_COUNT)
then then
local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y),
validUnitGroupLocation, validUnitGroupLocation,
scoreUnitGroupLocation, scoreUnitGroupLocation,
map) map)
if (squadPath ~= SENTINEL_IMPASSABLE_CHUNK) then if (squadPath ~= SENTINEL_IMPASSABLE_CHUNK) then
local squadPosition = surface.find_non_colliding_position("chunk-scanner-squad-rampant", local squadPosition = surface.find_non_colliding_position("chunk-scanner-squad-rampant",
positionFromDirectionAndChunk(squadDirection, positionFromDirectionAndChunk(squadDirection,
chunk, chunk,
map.position, map.position,
0.98), 0.98),
CHUNK_SIZE, CHUNK_SIZE,
4, 4,
true) true)
if squadPosition then if squadPosition then
local squad = createSquad(squadPosition, surface) local squad = createSquad(squadPosition, surface)
squad.rabid = mRandom() < 0.03 squad.rabid = mRandom() < 0.03
local scaledWaveSize = attackWaveScaling(natives) local scaledWaveSize = attackWaveScaling(natives)
map.formGroupCommand.group = squad.group map.formGroupCommand.group = squad.group
map.formCommand.unit_count = scaledWaveSize map.formCommand.unit_count = scaledWaveSize
local foundUnits = surface.set_multi_command(map.formCommand) local foundUnits = surface.set_multi_command(map.formCommand)
if (foundUnits > 0) then if (foundUnits > 0) then
natives.pendingAttack[#natives.pendingAttack+1] = squad natives.pendingAttack[#natives.pendingAttack+1] = squad
natives.points = natives.points - AI_SQUAD_COST natives.points = natives.points - AI_SQUAD_COST
if tick and (natives.state == AI_STATE_AGGRESSIVE) then if tick and (natives.state == AI_STATE_AGGRESSIVE) then
natives.canAttackTick = randomTickEvent(tick, natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
@ -291,7 +291,7 @@ function aiAttackWave.formSquads(map, surface, natives, chunk, tick)
if (squad.group.valid) then if (squad.group.valid) then
squad.group.destroy() squad.group.destroy()
end end
end end
end end
end end
end end

View File

@ -24,17 +24,17 @@ end
function chunkPropertyUtils.setWormCount(map, chunk, count) function chunkPropertyUtils.setWormCount(map, chunk, count)
if (count <= 0) then if (count <= 0) then
map.chunkToWorms[chunk] = nil map.chunkToWorms[chunk] = nil
else else
map.chunkToWorms[chunk] = count map.chunkToWorms[chunk] = count
end end
end end
function chunkPropertyUtils.setNestCount(map, chunk, count) function chunkPropertyUtils.setNestCount(map, chunk, count)
if (count <= 0) then if (count <= 0) then
map.chunkToNests[chunk] = nil map.chunkToNests[chunk] = nil
else else
map.chunkToNests[chunk] = count map.chunkToNests[chunk] = count
end end
end end
@ -44,9 +44,9 @@ end
function chunkPropertyUtils.setChunkSettlerTick(map, chunk, tick) function chunkPropertyUtils.setChunkSettlerTick(map, chunk, tick)
if (tick <= 0) then if (tick <= 0) then
map.chunkToSettler[chunk] = nil map.chunkToSettler[chunk] = nil
else else
map.chunkToSettler[chunk] = tick map.chunkToSettler[chunk] = tick
end end
end end
@ -88,9 +88,9 @@ end
function chunkPropertyUtils.setResourceGenerator(map, chunk, resourceGenerator) function chunkPropertyUtils.setResourceGenerator(map, chunk, resourceGenerator)
if (resourceGenerator <= 0) then if (resourceGenerator <= 0) then
map.chunkToResource[chunk] = nil map.chunkToResource[chunk] = nil
else else
map.chunkToResource[chunk] = resourceGenerator map.chunkToResource[chunk] = resourceGenerator
end end
end end
@ -137,9 +137,9 @@ end
function chunkPropertyUtils.setPassable(map, chunk, value) function chunkPropertyUtils.setPassable(map, chunk, value)
if (value == CHUNK_ALL_DIRECTIONS) then if (value == CHUNK_ALL_DIRECTIONS) then
map.chunkToPassable[chunk] = nil map.chunkToPassable[chunk] = nil
else else
map.chunkToPassable[chunk] = value map.chunkToPassable[chunk] = value
end end
end end
@ -149,9 +149,9 @@ end
function chunkPropertyUtils.setPathRating(map, chunk, value) function chunkPropertyUtils.setPathRating(map, chunk, value)
if (value == 1) then if (value == 1) then
map.chunkToPathRating[chunk] = nil map.chunkToPathRating[chunk] = nil
else else
map.chunkToPathRating[chunk] = value map.chunkToPathRating[chunk] = value
end end
end end
@ -162,13 +162,13 @@ end
function chunkPropertyUtils.decayDeathGenerator(map, chunk) function chunkPropertyUtils.decayDeathGenerator(map, chunk)
local gen = map.chunkToDeathGenerator[chunk] local gen = map.chunkToDeathGenerator[chunk]
if gen and (gen > 0) then if gen and (gen > 0) then
gen = gen * MOVEMENT_GENERATOR_PERSISTANCE gen = gen * MOVEMENT_GENERATOR_PERSISTANCE
if (gen >= -2) and (gen <= 2) then if (gen >= -2) and (gen <= 2) then
map.chunkToDeathGenerator[chunk] = nil map.chunkToDeathGenerator[chunk] = nil
else else
map.chunkToDeathGenerator[chunk] = gen map.chunkToDeathGenerator[chunk] = gen
end end
end end
end end
@ -180,7 +180,7 @@ function chunkPropertyUtils.addSquadToChunk(map, chunk, squad)
local chunkToSquad = map.chunkToSquad local chunkToSquad = map.chunkToSquad
if squad.chunk ~= chunk then if squad.chunk ~= chunk then
chunkPropertyUtils.removeSquadFromChunk(map, squad) chunkPropertyUtils.removeSquadFromChunk(map, squad)
local squads = chunkToSquad[chunk] local squads = chunkToSquad[chunk]
if not squads then if not squads then
squads = {} squads = {}
@ -196,17 +196,17 @@ function chunkPropertyUtils.removeSquadFromChunk(map, squad)
local chunkToSquad = map.chunkToSquad local chunkToSquad = map.chunkToSquad
local chunk = squad.chunk local chunk = squad.chunk
if chunk then if chunk then
local squads = chunkToSquad[chunk] local squads = chunkToSquad[chunk]
if squads then if squads then
for i=#squads,1,-1 do for i=#squads,1,-1 do
if (squads[i] == squad) then if (squads[i] == squad) then
tRemove(squads, i) tRemove(squads, i)
end end
end end
if (#squads == 0) then if (#squads == 0) then
chunkToSquad[chunk] = nil chunkToSquad[chunk] = nil
end end
end end
end end
end end
@ -216,9 +216,9 @@ end
function chunkPropertyUtils.setPlayerBaseGenerator(map, chunk, playerGenerator) function chunkPropertyUtils.setPlayerBaseGenerator(map, chunk, playerGenerator)
if (playerGenerator <= 0) then if (playerGenerator <= 0) then
map.chunkToPlayerBase[chunk] = nil map.chunkToPlayerBase[chunk] = nil
else else
map.chunkToPlayerBase[chunk] = playerGenerator map.chunkToPlayerBase[chunk] = playerGenerator
end end
end end

View File

@ -13,6 +13,7 @@ local chunkPropertyUtils = require("ChunkPropertyUtils")
-- constants -- constants
local CHUNK_SIZE_DIVIDER = constants.CHUNK_SIZE_DIVIDER
local DEFINES_WIRE_TYPE_RED = defines.wire_type.red local DEFINES_WIRE_TYPE_RED = defines.wire_type.red
local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green
@ -134,36 +135,36 @@ local function scanPaths(chunk, surface, map)
bottomPosition[2] = y + 32 bottomPosition[2] = y + 32
for xi=x, x + 32 do for xi=x, x + 32 do
topPosition[1] = xi topPosition[1] = xi
bottomPosition[1] = xi + 1 bottomPosition[1] = xi + 1
if (count_entities_filtered(filteredEntitiesCliffQuery) == 0) and if (count_entities_filtered(filteredEntitiesCliffQuery) == 0) and
(count_tiles_filtered(filteredTilesPathQuery) == 0) (count_tiles_filtered(filteredTilesPathQuery) == 0)
then then
passableNorthSouth = true passableNorthSouth = true
break break
end end
end end
topPosition[1] = x topPosition[1] = x
bottomPosition[1] = x + 32 bottomPosition[1] = x + 32
for yi=y, y + 32 do for yi=y, y + 32 do
topPosition[2] = yi topPosition[2] = yi
bottomPosition[2] = yi + 1 bottomPosition[2] = yi + 1
if (count_entities_filtered(filteredEntitiesCliffQuery) == 0) and if (count_entities_filtered(filteredEntitiesCliffQuery) == 0) and
(count_tiles_filtered(filteredTilesPathQuery) == 0) (count_tiles_filtered(filteredTilesPathQuery) == 0)
then then
passableEastWest = true passableEastWest = true
break break
end end
end end
if passableEastWest and passableNorthSouth then if passableEastWest and passableNorthSouth then
pass = CHUNK_ALL_DIRECTIONS pass = CHUNK_ALL_DIRECTIONS
elseif passableEastWest then elseif passableEastWest then
pass = CHUNK_EAST_WEST pass = CHUNK_EAST_WEST
elseif passableNorthSouth then elseif passableNorthSouth then
pass = CHUNK_NORTH_SOUTH pass = CHUNK_NORTH_SOUTH
end end
return pass return pass
end end
@ -181,15 +182,15 @@ function chunkUtils.initialScan(chunk, natives, surface, map, tick, evolutionFac
local passScore = 1 - (surface.count_tiles_filtered(map.filteredTilesQuery) * 0.0009765625) local passScore = 1 - (surface.count_tiles_filtered(map.filteredTilesQuery) * 0.0009765625)
if (passScore >= CHUNK_PASS_THRESHOLD) then if (passScore >= CHUNK_PASS_THRESHOLD) then
local pass = scanPaths(chunk, surface, map) local pass = scanPaths(chunk, surface, map)
local playerObjects = scorePlayerBuildings(surface, map) local playerObjects = scorePlayerBuildings(surface, map)
local nests = surface.find_entities_filtered(map.filteredEntitiesUnitSpawnereQuery) local nests = surface.find_entities_filtered(map.filteredEntitiesUnitSpawnereQuery)
if ((playerObjects > 0) or (#nests > 0)) and (pass == CHUNK_IMPASSABLE) then if ((playerObjects > 0) or (#nests > 0)) and (pass == CHUNK_IMPASSABLE) then
pass = CHUNK_ALL_DIRECTIONS pass = CHUNK_ALL_DIRECTIONS
end end
if (pass ~= CHUNK_IMPASSABLE) then if (pass ~= CHUNK_IMPASSABLE) then
local worms = surface.find_entities_filtered(map.filteredEntitiesWormQuery) local worms = surface.find_entities_filtered(map.filteredEntitiesWormQuery)
@ -270,20 +271,20 @@ function chunkUtils.chunkPassScan(chunk, surface, map)
local passScore = 1 - (surface.count_tiles_filtered(map.filteredTilesQuery) * 0.0009765625) local passScore = 1 - (surface.count_tiles_filtered(map.filteredTilesQuery) * 0.0009765625)
if (passScore >= CHUNK_PASS_THRESHOLD) then if (passScore >= CHUNK_PASS_THRESHOLD) then
local pass = scanPaths(chunk, surface, map) local pass = scanPaths(chunk, surface, map)
local playerObjects = getPlayerBaseGenerator(map, chunk) local playerObjects = getPlayerBaseGenerator(map, chunk)
local nests = getNestCount(map, chunk) local nests = getNestCount(map, chunk)
if ((playerObjects > 0) or (nests > 0)) and (pass == CHUNK_IMPASSABLE) then if ((playerObjects > 0) or (nests > 0)) and (pass == CHUNK_IMPASSABLE) then
pass = CHUNK_ALL_DIRECTIONS pass = CHUNK_ALL_DIRECTIONS
end end
setPassable(map, chunk, pass) setPassable(map, chunk, pass)
setPathRating(map, chunk, passScore) setPathRating(map, chunk, passScore)
return chunk return chunk
end end
return SENTINEL_IMPASSABLE_CHUNK return SENTINEL_IMPASSABLE_CHUNK
@ -313,8 +314,8 @@ end
function chunkUtils.createChunk(topX, topY) function chunkUtils.createChunk(topX, topY)
local chunk = { local chunk = {
x = topX, x = topX,
y = topY y = topY
} }
chunk[MOVEMENT_PHEROMONE] = 0 chunk[MOVEMENT_PHEROMONE] = 0
chunk[BASE_PHEROMONE] = 0 chunk[BASE_PHEROMONE] = 0
@ -327,10 +328,12 @@ end
function chunkUtils.colorChunk(x, y, tileType, surface) function chunkUtils.colorChunk(x, y, tileType, surface)
local tiles = {} local tiles = {}
for xi=x+5, x + 27 do local lx = math.floor(x * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
for yi=y+5, y + 27 do local ly = math.floor(y * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
tiles[#tiles+1] = {name=tileType, position={xi, yi}} for xi=lx+5, lx + 27 do
end for yi=ly+5, ly + 27 do
tiles[#tiles+1] = {name=tileType, position={xi, yi}}
end
end end
surface.set_tiles(tiles, false) surface.set_tiles(tiles, false)
end end
@ -338,7 +341,7 @@ end
function chunkUtils.registerEnemyBaseStructure(map, entity, base) function chunkUtils.registerEnemyBaseStructure(map, entity, base)
local entityType = entity.type local entityType = entity.type
if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then
local overlapArray = getEntityOverlapChunks(map, entity) local overlapArray = getEntityOverlapChunks(map, entity)
local lookup local lookup
if (entityType == "unit-spawner") then if (entityType == "unit-spawner") then
@ -362,7 +365,7 @@ end
function chunkUtils.unregisterEnemyBaseStructure(map, entity) function chunkUtils.unregisterEnemyBaseStructure(map, entity)
local entityType = entity.type local entityType = entity.type
if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then
local overlapArray = getEntityOverlapChunks(map, entity) local overlapArray = getEntityOverlapChunks(map, entity)
local mainLookup local mainLookup
local secondaryLookup local secondaryLookup

View File

@ -475,15 +475,15 @@ constants.PATH_FINDER_SHORT_CACHE_SIZE = 25
constants.PATH_FINDER_LONG_REQUEST_RATIO = 5 constants.PATH_FINDER_LONG_REQUEST_RATIO = 5
constants.PATH_FINDER_MIN_STEPS_TO_CHECK_PATH = 1000 constants.PATH_FINDER_MIN_STEPS_TO_CHECK_PATH = 1000
constants.MAX_FAILED_BEHAVIORS = 10 constants.MAX_FAILED_BEHAVIORS = 100
constants.UNIT_GROUP_DISOWN_DISTANCE = 10 constants.UNIT_GROUP_DISOWN_DISTANCE = 100
constants.UNIT_GROUP_TICK_TOLERANCE = 360 constants.UNIT_GROUP_TICK_TOLERANCE = 3600000
constants.UNIT_GROUP_MAX_RADIUS = 20 constants.UNIT_GROUP_MAX_RADIUS = 25
constants.UNIT_GROUP_MAX_SPEED_UP = 1.1 constants.UNIT_GROUP_MAX_SPEED_UP = 2
constants.UNIT_GROUP_MAX_SLOWDOWN = 1.0 constants.UNIT_GROUP_MAX_SLOWDOWN = 1.0
constants.UNIT_GROUP_SLOWDOWN_FACTOR = 0.9 constants.UNIT_GROUP_SLOWDOWN_FACTOR = 1.0
-- sentinels -- sentinels

View File

@ -41,7 +41,7 @@ end
function mapUtils.getChunkByPosition(map, position) function mapUtils.getChunkByPosition(map, position)
local chunkX = map[mFloor(position.x * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE] local chunkX = map[mFloor(position.x * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE]
if chunkX then if chunkX then
local chunkY = mFloor(position.y * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE local chunkY = mFloor(position.y * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
return chunkX[chunkY] or SENTINEL_IMPASSABLE_CHUNK return chunkX[chunkY] or SENTINEL_IMPASSABLE_CHUNK
end end
return SENTINEL_IMPASSABLE_CHUNK return SENTINEL_IMPASSABLE_CHUNK
@ -50,7 +50,7 @@ end
function mapUtils.getChunkByUnalignedXY(map, x, y) function mapUtils.getChunkByUnalignedXY(map, x, y)
local chunkX = map[mFloor(x * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE] local chunkX = map[mFloor(x * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE]
if chunkX then if chunkX then
local chunkY = mFloor(y * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE local chunkY = mFloor(y * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
return chunkX[chunkY] or SENTINEL_IMPASSABLE_CHUNK return chunkX[chunkY] or SENTINEL_IMPASSABLE_CHUNK
end end
return SENTINEL_IMPASSABLE_CHUNK return SENTINEL_IMPASSABLE_CHUNK
@ -79,9 +79,9 @@ function mapUtils.getNeighborChunks(map, x, y)
neighbors[4] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK neighbors[4] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK
neighbors[6] = xChunks[chunkYRow3] or SENTINEL_IMPASSABLE_CHUNK neighbors[6] = xChunks[chunkYRow3] or SENTINEL_IMPASSABLE_CHUNK
else else
neighbors[1] = SENTINEL_IMPASSABLE_CHUNK neighbors[1] = SENTINEL_IMPASSABLE_CHUNK
neighbors[4] = SENTINEL_IMPASSABLE_CHUNK neighbors[4] = SENTINEL_IMPASSABLE_CHUNK
neighbors[6] = SENTINEL_IMPASSABLE_CHUNK neighbors[6] = SENTINEL_IMPASSABLE_CHUNK
end end
xChunks = map[x+CHUNK_SIZE] xChunks = map[x+CHUNK_SIZE]
@ -90,9 +90,9 @@ function mapUtils.getNeighborChunks(map, x, y)
neighbors[5] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK neighbors[5] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK
neighbors[8] = xChunks[chunkYRow3] or SENTINEL_IMPASSABLE_CHUNK neighbors[8] = xChunks[chunkYRow3] or SENTINEL_IMPASSABLE_CHUNK
else else
neighbors[3] = SENTINEL_IMPASSABLE_CHUNK neighbors[3] = SENTINEL_IMPASSABLE_CHUNK
neighbors[5] = SENTINEL_IMPASSABLE_CHUNK neighbors[5] = SENTINEL_IMPASSABLE_CHUNK
neighbors[8] = SENTINEL_IMPASSABLE_CHUNK neighbors[8] = SENTINEL_IMPASSABLE_CHUNK
end end
xChunks = map[x] xChunks = map[x]
@ -100,8 +100,8 @@ function mapUtils.getNeighborChunks(map, x, y)
neighbors[2] = xChunks[chunkYRow1] or SENTINEL_IMPASSABLE_CHUNK neighbors[2] = xChunks[chunkYRow1] or SENTINEL_IMPASSABLE_CHUNK
neighbors[7] = xChunks[chunkYRow3] or SENTINEL_IMPASSABLE_CHUNK neighbors[7] = xChunks[chunkYRow3] or SENTINEL_IMPASSABLE_CHUNK
else else
neighbors[2] = SENTINEL_IMPASSABLE_CHUNK neighbors[2] = SENTINEL_IMPASSABLE_CHUNK
neighbors[7] = SENTINEL_IMPASSABLE_CHUNK neighbors[7] = SENTINEL_IMPASSABLE_CHUNK
end end
return neighbors return neighbors
end end
@ -120,27 +120,27 @@ function mapUtils.canMoveChunkDirection(map, direction, startChunk, endChunk)
local endPassable = getPassable(map, endChunk) local endPassable = getPassable(map, endChunk)
-- print(direction, startPassable, endPassable) -- print(direction, startPassable, endPassable)
if (startPassable == CHUNK_ALL_DIRECTIONS) then if (startPassable == CHUNK_ALL_DIRECTIONS) then
if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then
canMove = (endPassable == CHUNK_ALL_DIRECTIONS) canMove = (endPassable == CHUNK_ALL_DIRECTIONS)
elseif (direction == 2) or (direction == 7) then elseif (direction == 2) or (direction == 7) then
canMove = ((endPassable == CHUNK_NORTH_SOUTH) or (endPassable == CHUNK_ALL_DIRECTIONS)) canMove = ((endPassable == CHUNK_NORTH_SOUTH) or (endPassable == CHUNK_ALL_DIRECTIONS))
elseif (direction == 4) or (direction == 5) then elseif (direction == 4) or (direction == 5) then
canMove = ((endPassable == CHUNK_EAST_WEST) or (endPassable == CHUNK_ALL_DIRECTIONS)) canMove = ((endPassable == CHUNK_EAST_WEST) or (endPassable == CHUNK_ALL_DIRECTIONS))
end end
elseif (startPassable == CHUNK_NORTH_SOUTH) then elseif (startPassable == CHUNK_NORTH_SOUTH) then
if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then
canMove = (endPassable == CHUNK_ALL_DIRECTIONS) canMove = (endPassable == CHUNK_ALL_DIRECTIONS)
elseif (direction == 2) or (direction == 7) then elseif (direction == 2) or (direction == 7) then
canMove = ((endPassable == CHUNK_NORTH_SOUTH) or (endPassable == CHUNK_ALL_DIRECTIONS)) canMove = ((endPassable == CHUNK_NORTH_SOUTH) or (endPassable == CHUNK_ALL_DIRECTIONS))
end end
elseif (startPassable == CHUNK_EAST_WEST) then elseif (startPassable == CHUNK_EAST_WEST) then
if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then
canMove = (endPassable == CHUNK_ALL_DIRECTIONS) canMove = (endPassable == CHUNK_ALL_DIRECTIONS)
elseif (direction == 4) or (direction == 5) then elseif (direction == 4) or (direction == 5) then
canMove = ((endPassable == CHUNK_EAST_WEST) or (endPassable == CHUNK_ALL_DIRECTIONS)) canMove = ((endPassable == CHUNK_EAST_WEST) or (endPassable == CHUNK_ALL_DIRECTIONS))
end end
else else
canMove = (endPassable ~= CHUNK_IMPASSABLE) canMove = (endPassable ~= CHUNK_IMPASSABLE)
end end
return canMove return canMove
end end
@ -149,57 +149,87 @@ function mapUtils.getCardinalChunks(map, x, y)
local neighbors = map.cardinalNeighbors local neighbors = map.cardinalNeighbors
local xChunks = map[x] local xChunks = map[x]
if xChunks then if xChunks then
neighbors[1] = xChunks[y-CHUNK_SIZE] or SENTINEL_IMPASSABLE_CHUNK neighbors[1] = xChunks[y-CHUNK_SIZE] or SENTINEL_IMPASSABLE_CHUNK
neighbors[4] = xChunks[y+CHUNK_SIZE] or SENTINEL_IMPASSABLE_CHUNK neighbors[4] = xChunks[y+CHUNK_SIZE] or SENTINEL_IMPASSABLE_CHUNK
else else
neighbors[1] = SENTINEL_IMPASSABLE_CHUNK neighbors[1] = SENTINEL_IMPASSABLE_CHUNK
neighbors[4] = SENTINEL_IMPASSABLE_CHUNK neighbors[4] = SENTINEL_IMPASSABLE_CHUNK
end end
xChunks = map[x-CHUNK_SIZE] xChunks = map[x-CHUNK_SIZE]
if xChunks then if xChunks then
neighbors[2] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK neighbors[2] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK
else else
neighbors[2] = SENTINEL_IMPASSABLE_CHUNK neighbors[2] = SENTINEL_IMPASSABLE_CHUNK
end end
xChunks = map[x+CHUNK_SIZE] xChunks = map[x+CHUNK_SIZE]
if xChunks then if xChunks then
neighbors[3] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK neighbors[3] = xChunks[y] or SENTINEL_IMPASSABLE_CHUNK
else else
neighbors[3] = SENTINEL_IMPASSABLE_CHUNK neighbors[3] = SENTINEL_IMPASSABLE_CHUNK
end end
return neighbors return neighbors
end end
function mapUtils.positionFromDirectionAndChunk(direction, startPosition, endPosition, scaling) function mapUtils.positionFromDirectionAndChunk(direction, startPosition, endPosition, scaling)
if (direction == 1) then if (direction == 1) then
endPosition.x = startPosition.x - CHUNK_SIZE * (scaling - 0.1) endPosition.x = startPosition.x - CHUNK_SIZE * (scaling - 0.1)
endPosition.y = startPosition.y - CHUNK_SIZE * (scaling - 0.1) endPosition.y = startPosition.y - CHUNK_SIZE * (scaling - 0.1)
elseif (direction == 2) then elseif (direction == 2) then
endPosition.x = startPosition.x endPosition.x = startPosition.x
endPosition.y = startPosition.y - CHUNK_SIZE * (scaling + 0.25) endPosition.y = startPosition.y - CHUNK_SIZE * (scaling + 0.25)
elseif (direction == 3) then elseif (direction == 3) then
endPosition.x = startPosition.x + CHUNK_SIZE * (scaling - 0.1) endPosition.x = startPosition.x + CHUNK_SIZE * (scaling - 0.1)
endPosition.y = startPosition.y - CHUNK_SIZE * (scaling - 0.1) endPosition.y = startPosition.y - CHUNK_SIZE * (scaling - 0.1)
elseif (direction == 4) then elseif (direction == 4) then
endPosition.x = startPosition.x - CHUNK_SIZE * (scaling + 0.25) endPosition.x = startPosition.x - CHUNK_SIZE * (scaling + 0.25)
endPosition.y = startPosition.y endPosition.y = startPosition.y
elseif (direction == 5) then elseif (direction == 5) then
endPosition.x = startPosition.x + CHUNK_SIZE * (scaling + 0.25) endPosition.x = startPosition.x + CHUNK_SIZE * (scaling + 0.25)
endPosition.y = startPosition.y endPosition.y = startPosition.y
elseif (direction == 6) then elseif (direction == 6) then
endPosition.x = startPosition.x - CHUNK_SIZE * (scaling - 0.1) endPosition.x = startPosition.x - CHUNK_SIZE * (scaling - 0.1)
endPosition.y = startPosition.y + CHUNK_SIZE * (scaling - 0.1) endPosition.y = startPosition.y + CHUNK_SIZE * (scaling - 0.1)
elseif (direction == 7) then elseif (direction == 7) then
endPosition.x = startPosition.x endPosition.x = startPosition.x
endPosition.y = startPosition.y + CHUNK_SIZE * (scaling + 0.25) endPosition.y = startPosition.y + CHUNK_SIZE * (scaling + 0.25)
elseif (direction == 8) then elseif (direction == 8) then
endPosition.x = startPosition.x + CHUNK_SIZE * (scaling - 0.1) endPosition.x = startPosition.x + CHUNK_SIZE * (scaling - 0.1)
endPosition.y = startPosition.y + CHUNK_SIZE * (scaling - 0.1) endPosition.y = startPosition.y + CHUNK_SIZE * (scaling - 0.1)
end end
return endPosition return endPosition
end end
function mapUtils.positionFromDirectionAndFlat(direction, startPosition, endPosition)
local lx = startPosition.x
local ly = startPosition.y
if (direction == 1) then
lx = lx - CHUNK_SIZE
ly = ly - CHUNK_SIZE
elseif (direction == 2) then
ly = ly - CHUNK_SIZE
elseif (direction == 3) then
lx = lx + CHUNK_SIZE
ly = ly - CHUNK_SIZE
elseif (direction == 4) then
lx = lx - CHUNK_SIZE
elseif (direction == 5) then
lx = lx + CHUNK_SIZE
elseif (direction == 6) then
lx = lx - CHUNK_SIZE
ly = ly + CHUNK_SIZE
elseif (direction == 7) then
ly = ly + CHUNK_SIZE
elseif (direction == 8) then
lx = lx + CHUNK_SIZE
ly = ly + CHUNK_SIZE
end
endPosition.x = lx
endPosition.y = ly
-- return lx, ly
end
mapUtilsG = mapUtils mapUtilsG = mapUtils
return mapUtils return mapUtils

View File

@ -20,6 +20,7 @@ local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
-- imported functions -- imported functions
local canMoveChunkDirection = mapUtils.canMoveChunkDirection local canMoveChunkDirection = mapUtils.canMoveChunkDirection
local getNeighborChunks = mapUtils.getNeighborChunks
-- local recycleBiters = unitGroupUtils.recycleBiters -- local recycleBiters = unitGroupUtils.recycleBiters
@ -33,11 +34,19 @@ local distortPosition = mathUtils.distortPosition
function movementUtils.findMovementPosition(surface, position, distort) function movementUtils.findMovementPosition(surface, position, distort)
local pos = position local pos = position
if not surface.can_place_entity({name="chunk-scanner-squad-movement-rampant", position=position}) then if not surface.can_place_entity({name="chunk-scanner-squad-movement-rampant", position=position}) then
pos = surface.find_non_colliding_position("chunk-scanner-squad-movement-rampant", position, 15, 2, true) pos = surface.find_non_colliding_position("chunk-scanner-squad-movement-rampant", position, 4, 2, true)
end end
return (distort and distortPosition(pos)) or pos return (distort and distortPosition(pos)) or pos
end end
function movementUtils.findMovementXY(surface, x, y)
local pos = position
if not surface.can_place_entity({name="chunk-scanner-squad-movement-rampant", position={}}) then
pos = surface.find_non_colliding_position("chunk-scanner-squad-movement-rampant", position, 4, 2, true)
end
return pos
end
function movementUtils.addMovementPenalty(units, chunk) function movementUtils.addMovementPenalty(units, chunk)
local penalties = units.penalties local penalties = units.penalties
for i=1,#penalties do for i=1,#penalties do
@ -51,9 +60,9 @@ function movementUtils.addMovementPenalty(units, chunk)
tableRemove(penalties, 7) tableRemove(penalties, 7)
end end
tableInsert(penalties, tableInsert(penalties,
1, 1,
{ v = MOVEMENT_PENALTY_AMOUNT, { v = MOVEMENT_PENALTY_AMOUNT,
c = chunk }) c = chunk })
end end
function movementUtils.lookupMovementPenalty(squad, chunk) function movementUtils.lookupMovementPenalty(squad, chunk)
@ -76,6 +85,10 @@ function movementUtils.scoreNeighborsForAttack(map, natives, chunk, neighborDire
local highestScore = -MAGIC_MAXIMUM_NUMBER local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection local highestDirection
local nextHighestChunk = SENTINEL_IMPASSABLE_CHUNK
local nextHighestScore = -MAGIC_MAXIMUM_NUMBER
local nextHighestDirection
for x=1,8 do for x=1,8 do
local neighborChunk = neighborDirectionChunks[x] local neighborChunk = neighborDirectionChunks[x]
@ -89,7 +102,23 @@ function movementUtils.scoreNeighborsForAttack(map, natives, chunk, neighborDire
end end
end end
return highestChunk, highestDirection if (highestChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
neighborDirectionChunks = getNeighborChunks(map, highestChunk.x, highestChunk.y)
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(map, x, highestChunk, neighborChunk) then
local score = scoreFunction(natives, squad, neighborChunk)
if (score > nextHighestScore) then
nextHighestScore = score
nextHighestChunk = neighborChunk
nextHighestDirection = x
end
end
end
end
return highestChunk, highestDirection, nextHighestChunk, nextHighestDirection
end end
@ -113,7 +142,7 @@ function movementUtils.scoreNeighborsForSettling(map, chunk, neighborDirectionCh
end end
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (scoreFunction(squad, chunk) > highestScore) then if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (scoreFunction(squad, chunk) > highestScore) then
return chunk, -1 return chunk, -1
end end
return highestChunk, highestDirection return highestChunk, highestDirection
@ -139,7 +168,7 @@ function movementUtils.scoreNeighborsForResource(chunk, neighborDirectionChunks,
end end
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (scoreFunction(chunk) > highestScore) then if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (scoreFunction(chunk) > highestScore) then
return SENTINEL_IMPASSABLE_CHUNK, -1 return SENTINEL_IMPASSABLE_CHUNK, -1
end end
return highestChunk, highestDirection return highestChunk, highestDirection
@ -182,7 +211,7 @@ function movementUtils.scoreNeighborsForFormation(neighborChunks, validFunction,
if (score > highestScore) then if (score > highestScore) then
highestScore = score highestScore = score
highestChunk = neighborChunk highestChunk = neighborChunk
highestDirection = x highestDirection = x
end end
end end
end end

View File

@ -71,6 +71,7 @@ local addMovementPenalty = movementUtils.addMovementPenalty
local lookupMovementPenalty = movementUtils.lookupMovementPenalty local lookupMovementPenalty = movementUtils.lookupMovementPenalty
local calculateKamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold local calculateKamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
local positionFromDirectionAndFlat = mapUtils.positionFromDirectionAndFlat
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
@ -94,11 +95,12 @@ end
local function scoreAttackLocation(natives, squad, neighborChunk) local function scoreAttackLocation(natives, squad, neighborChunk)
local damage local damage
local movementPheromone = neighborChunk[MOVEMENT_PHEROMONE]
if (neighborChunk[MOVEMENT_PHEROMONE] >= 0) then if (movementPheromone >= 0) then
damage = neighborChunk[MOVEMENT_PHEROMONE] + (neighborChunk[BASE_PHEROMONE] ) + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER) damage = movementPheromone + (neighborChunk[BASE_PHEROMONE] ) + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
else else
damage = (neighborChunk[BASE_PHEROMONE] * (1 - (neighborChunk[MOVEMENT_PHEROMONE] / -natives.retreatThreshold))) + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER) damage = (neighborChunk[BASE_PHEROMONE] * (1 - (movementPheromone / -natives.retreatThreshold))) + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
end end
return damage - lookupMovementPenalty(squad, neighborChunk) return damage - lookupMovementPenalty(squad, neighborChunk)
@ -111,7 +113,7 @@ end
local function settleMove(map, squad, natives, surface) local function settleMove(map, squad, natives, surface)
local attackPosition = map.position local targetPosition = map.position
local group = squad.group local group = squad.group
local groupPosition = group.position local groupPosition = group.position
@ -202,62 +204,107 @@ local function settleMove(map, squad, natives, surface)
position = findMovementPosition(surface, position = findMovementPosition(surface,
positionFromDirectionAndChunk(attackDirection, positionFromDirectionAndChunk(attackDirection,
groupPosition, groupPosition,
attackPosition, targetPosition,
(largeGroup and 1.1) or 0.9)) (largeGroup and 1.1) or 0.9))
end end
if position then if position then
squad.cycles = (largeGroup and 6) or 4 squad.cycles = (largeGroup and 6) or 4
attackPosition.x = position.x targetPosition.x = position.x
attackPosition.y = position.y targetPosition.y = position.y
group.set_command(cmd) group.set_command(cmd)
group.start_moving() group.start_moving()
end end
end end
local function attackMove(map, squad, natives, surface) local function attackMove(map, squad, natives, surface)
local attackPosition = map.position local targetPosition = map.position
local targetPosition2 = map.position2
local group = squad.group local group = squad.group
local groupPosition = group.position local groupPosition = group.position
local x, y = positionToChunkXY(groupPosition) local x, y = positionToChunkXY(groupPosition)
local chunk = getChunkByXY(map, x, y) local chunk = getChunkByXY(map, x, y)
local attackScorer = scoreAttackLocation local attackScorer = scoreAttackLocation
local squadChunk = squad.chunk
if (squad.attackScoreFunction == ATTACK_SCORE_KAMIKAZE) then if (squad.attackScoreFunction == ATTACK_SCORE_KAMIKAZE) then
attackScorer = scoreAttackKamikazeLocation attackScorer = scoreAttackKamikazeLocation
end end
if squad.chunk and (squad.chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (squad.chunk ~= chunk) then if (squadChunk ~= SENTINEL_IMPASSABLE_CHUNK) and (squadChunk ~= chunk) then
addMovementPenalty(squad, squad.chunk) addMovementPenalty(squad, squadChunk)
end end
local attackChunk, attackDirection = scoreNeighborsForAttack(map,
natives,
chunk,
getNeighborChunks(map, x, y),
attackScorer,
squad)
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK)then if (chunk ~= SENTINEL_IMPASSABLE_CHUNK)then
addSquadToChunk(map, chunk, squad) addSquadToChunk(map, chunk, squad)
end end
squad.frenzy = (squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100))
local attackChunk, attackDirection, nextAttackChunk, nextAttackDirection = scoreNeighborsForAttack(map,
natives,
chunk,
getNeighborChunks(map, x, y),
attackScorer,
squad)
if (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then if (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
local playerBaseGenerator = getPlayerBaseGenerator(map, attackChunk)
local playerPheromone = attackChunk[PLAYER_PHEROMONE]
local cmd
local position
local largeGroup = (#squad.group.members > 80)
if (playerBaseGenerator == 0) and (playerPheromone < natives.attackPlayerThreshold) then positionFromDirectionAndFlat(attackDirection, groupPosition, targetPosition)
squad.frenzy = (squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100))
cmd = map.moveCommand local position = findMovementPosition(surface, targetPosition)
if squad.rabid or squad.frenzy then
cmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING if not position then
cmd = map.wonderCommand
group.set_command(cmd)
return
end
if ((getPlayerBaseGenerator(map, attackChunk) == 0) and
(attackChunk[PLAYER_PHEROMONE] < natives.attackPlayerThreshold)) then
if (nextAttackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
positionFromDirectionAndFlat(nextAttackDirection, targetPosition, targetPosition2)
local position2 = findMovementPosition(surface, targetPosition2)
if position2 then
if ((getPlayerBaseGenerator(map, nextAttackChunk) == 0) and
(nextAttackChunk[PLAYER_PHEROMONE] < natives.attackPlayerThreshold)) then
cmd = map.compoundMoveMoveCommand
if squad.rabid or squad.frenzy then
cmd.commands[1].distraction = DEFINES_DISTRACTION_BY_ANYTHING
cmd.commands[2].distraction = DEFINES_DISTRACTION_BY_ANYTHING
else
cmd.commands[1].distraction = DEFINES_DISTRACTION_BY_ENEMY
cmd.commands[2].distraction = DEFINES_DISTRACTION_BY_ENEMY
end
else
cmd = map.compoundMoveAttackCommand
cmd.commands[1].distraction = DEFINES_DISTRACTION_BY_ANYTHING
end
else
cmd = map.moveCommand
if squad.rabid or squad.frenzy then
cmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING
else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
end
end
else else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY cmd = map.attackCommand
end end
else else
cmd = map.attackCommand if (nextAttackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
positionFromDirectionAndFlat(nextAttackDirection, targetPosition, targetPosition2)
local position2 = findMovementPosition(surface, targetPosition2)
if position2 then
cmd = map.compoundAttackAttackCommand
else
cmd = map.attackCommand
end
else
cmd = map.attackCommand
end
if not squad.rabid then if not squad.rabid then
squad.frenzy = true squad.frenzy = true
@ -266,26 +313,16 @@ local function attackMove(map, squad, natives, surface)
end end
end end
position = findMovementPosition(surface, group.set_command(cmd)
positionFromDirectionAndChunk(attackDirection, else
groupPosition, cmd = map.wonderCommand
attackPosition, group.set_command(cmd)
(largeGroup and 1.1) or 0.9))
if position then
squad.cycles = (largeGroup and 6) or 4
attackPosition.x = position.x
attackPosition.y = position.y
group.set_command(cmd)
group.start_moving()
end
end end
end end
function squadAttack.squadsDispatch(map, surface, natives) function squadAttack.squadsDispatch(map, surface, natives)
local squads = natives.squads local squads = natives.squads
-- local attackPosition = map.position -- local targetPosition = map.position
-- local attackCmd = map.attackAreaCommand -- local attackCmd = map.attackAreaCommand
-- local settleCmd = map.settleCommand -- local settleCmd = map.settleCommand
@ -324,15 +361,16 @@ function squadAttack.squadsDispatch(map, surface, natives)
if (status == SQUAD_RAIDING) then if (status == SQUAD_RAIDING) then
if (groupState == DEFINES_GROUP_FINISHED) or if (groupState == DEFINES_GROUP_FINISHED) or
(groupState == DEFINES_GROUP_GATHERING) or (groupState == DEFINES_GROUP_GATHERING) -- or
((groupState == DEFINES_GROUP_MOVING) and (cycles <= 0)) -- ((groupState == DEFINES_GROUP_MOVING) and (cycles <= 0))
then then
-- print(group.group_number, groupState)
attackMove(map, squad, natives, surface) attackMove(map, squad, natives, surface)
end end
elseif (status == SQUAD_SETTLING) then elseif (status == SQUAD_SETTLING) then
if (groupState == DEFINES_GROUP_FINISHED) or if (groupState == DEFINES_GROUP_FINISHED) or
(groupState == DEFINES_GROUP_GATHERING) or (groupState == DEFINES_GROUP_GATHERING) -- or
((groupState == DEFINES_GROUP_MOVING) and (cycles <= 0)) -- ((groupState == DEFINES_GROUP_MOVING) and (cycles <= 0))
then then
settleMove(map, squad, natives, surface) settleMove(map, squad, natives, surface)
end end
@ -368,28 +406,34 @@ function squadAttack.squadsDispatch(map, surface, natives)
end end
function squadAttack.squadsBeginAttack(natives) function squadAttack.squadsBeginAttack(natives)
local squads = natives.pendingAttack local pending = natives.pendingAttack
for i=1,#squads do local squads = natives.squads
local squad = squads[i] for i=#pending,1,-1 do
local squad = pending[i]
local group = squad.group local group = squad.group
if group and group.valid then if group and group.valid then
local kamikazeThreshold = calculateKamikazeThreshold(#squad.group.members, natives) if (squad.cycles ~= 0) then
if not squad.kamikaze then squad.cycles = squad.cycles - 1
squad.kamikaze = (mRandom() < kamikazeThreshold)
end
if squad.settlers then
squad.status = SQUAD_SETTLING
natives.squads[#natives.squads+1] = squad
else else
if squad.kamikaze and (mRandom() < (kamikazeThreshold * 0.75)) then local kamikazeThreshold = calculateKamikazeThreshold(#squad.group.members, natives)
squad.attackScoreFunction = ATTACK_SCORE_KAMIKAZE if not squad.kamikaze then
squad.kamikaze = (mRandom() < kamikazeThreshold)
end end
squad.status = SQUAD_RAIDING if squad.settlers then
natives.squads[#natives.squads+1] = squad squad.status = SQUAD_SETTLING
squads[#squads+1] = squad
else
if squad.kamikaze and (mRandom() < (kamikazeThreshold * 0.75)) then
squad.attackScoreFunction = ATTACK_SCORE_KAMIKAZE
end
squad.status = SQUAD_RAIDING
squads[#squads+1] = squad
end
tRemove(pending, i)
end end
end end
end end
natives.pendingAttack = {} -- natives.pendingAttack = {}
end end
squadAttackG = squadAttack squadAttackG = squadAttack

View File

@ -60,61 +60,61 @@ function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, t
if (tick - getRetreatTick(map, chunk) > INTERVAL_RETREAT) and if (tick - getRetreatTick(map, chunk) > INTERVAL_RETREAT) and
((getEnemyStructureCount(map, chunk) == 0) or artilleryBlast) ((getEnemyStructureCount(map, chunk) == 0) or artilleryBlast)
then then
local performRetreat = false local performRetreat = false
local enemiesToSquad = nil local enemiesToSquad = nil
if not squad then if not squad then
enemiesToSquad = surface.find_enemy_units(position, radius) enemiesToSquad = surface.find_enemy_units(position, radius)
performRetreat = #enemiesToSquad > 0 performRetreat = #enemiesToSquad > 0
if (mRandom() < calculateKamikazeThreshold(#enemiesToSquad, natives)) then if (mRandom() < calculateKamikazeThreshold(#enemiesToSquad, natives)) then
setRetreatTick(map, chunk, tick) setRetreatTick(map, chunk, tick)
return return
end end
elseif squad.group and squad.group.valid and (squad.status ~= SQUAD_RETREATING) and not squad.kamikaze then elseif squad.group and squad.group.valid and (squad.status ~= SQUAD_RETREATING) and not squad.kamikaze then
performRetreat = #squad.group.members > 3 performRetreat = #squad.group.members > 3
end end
if performRetreat then if performRetreat then
setRetreatTick(map, chunk, tick) setRetreatTick(map, chunk, tick)
local exitPath,exitDirection = scoreNeighborsForRetreat(chunk, local exitPath,exitDirection = scoreNeighborsForRetreat(chunk,
getNeighborChunks(map, chunk.x, chunk.y), getNeighborChunks(map, chunk.x, chunk.y),
scoreRetreatLocation, scoreRetreatLocation,
map) map)
if (exitPath ~= SENTINEL_IMPASSABLE_CHUNK) then if (exitPath ~= SENTINEL_IMPASSABLE_CHUNK) then
local retreatPosition = findMovementPosition(surface, local retreatPosition = findMovementPosition(surface,
positionFromDirectionAndChunk(exitDirection, positionFromDirectionAndChunk(exitDirection,
position, position,
map.position, map.position,
0.98)) 0.98))
if not retreatPosition then if not retreatPosition then
return return
end end
-- in order for units in a group attacking to retreat, we have to create a new group and give the command to join -- in order for units in a group attacking to retreat, we have to create a new group and give the command to join
-- to each unit, this is the only way I have found to have snappy mid battle retreats even after 0.14.4 -- to each unit, this is the only way I have found to have snappy mid battle retreats even after 0.14.4
local newSquad = findNearbyRetreatingSquad(map, exitPath) local newSquad = findNearbyRetreatingSquad(map, exitPath)
if not newSquad then if not newSquad then
newSquad = createSquad(retreatPosition, surface) newSquad = createSquad(retreatPosition, surface)
natives.squads[#natives.squads+1] = newSquad natives.squads[#natives.squads+1] = newSquad
end end
if newSquad then if newSquad then
newSquad.status = SQUAD_RETREATING newSquad.status = SQUAD_RETREATING
newSquad.cycles = 4 newSquad.cycles = 4
local cmd = map.retreatCommand local cmd = map.retreatCommand
cmd.group = newSquad.group cmd.group = newSquad.group
if enemiesToSquad then if enemiesToSquad then
membersToSquad(cmd, enemiesToSquad, artilleryBlast) membersToSquad(cmd, enemiesToSquad, artilleryBlast)
else else
membersToSquad(cmd, squad.group.members, true) membersToSquad(cmd, squad.group.members, true)
if squad.rabid then if squad.rabid then
newSquad.rabid = true newSquad.rabid = true
end end
end end
if not newSquad.rapid then if not newSquad.rapid then
newSquad.frenzy = true newSquad.frenzy = true
@ -122,11 +122,11 @@ function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, t
newSquad.frenzyPosition.x = squadPosition.x newSquad.frenzyPosition.x = squadPosition.x
newSquad.frenzyPosition.y = squadPosition.y newSquad.frenzyPosition.y = squadPosition.y
end end
addSquadToChunk(map, chunk, newSquad) addSquadToChunk(map, chunk, newSquad)
addMovementPenalty(newSquad, chunk) addMovementPenalty(newSquad, chunk)
end end
end end
end end
end end
end end

View File

@ -54,8 +54,8 @@ function unitGroupUtils.findNearbyRetreatingSquad(map, chunk)
local squads = getSquadsOnChunk(map, chunk) local squads = getSquadsOnChunk(map, chunk)
for i=1,#squads do for i=1,#squads do
local squad = squads[i] local squad = squads[i]
local unitGroup = squad.group local unitGroup = squad.group
if unitGroup and unitGroup.valid and (squad.status == SQUAD_RETREATING) then if unitGroup and unitGroup.valid and (squad.status == SQUAD_RETREATING) then
return squad return squad
end end
end end
@ -121,12 +121,12 @@ function unitGroupUtils.createSquad(position, surface, group, settlers)
kamikaze = false, kamikaze = false,
frenzyPosition = {x = 0, frenzyPosition = {x = 0,
y = 0}, y = 0},
cycles = 60, cycles = 10,
maxDistance = 0, maxDistance = 0,
attackScoreFunction = 1, attackScoreFunction = 1,
originPosition = {x = 0, originPosition = {x = 0,
y = 0}, y = 0},
chunk = nil chunk = SENTINEL_IMPASSABLE_CHUNK
} }
if position then if position then

View File

@ -84,11 +84,22 @@
(copyDirectory "prototypes" modFolder))) (copyDirectory "prototypes" modFolder)))
(define (copy) (define (copy)
(set! packageName (string-append (string-replace (hash-ref configuration 'name) " " "_")
"_"
(hash-ref configuration 'version)))
(print 'copying)
(copyFiles modFolder)) (copyFiles modFolder))
(define (zipIt) (define (zipIt)
(set! packageName (string-append (string-replace (hash-ref configuration 'name) " " "_")
"_"
(hash-ref configuration 'version)))
(print 'zipping)
(makeZip modFolder)) (makeZip modFolder))
(define (runStart) (define (runStart)
(set! packageName (string-append (string-replace (hash-ref configuration 'name) " " "_")
"_"
(hash-ref configuration 'version)))
(copyFiles modFolder) (copyFiles modFolder)
(system*/exit-code "factorio"))) (system*/exit-code "factorio")))