1
0
mirror of https://github.com/veden/Rampant.git synced 2025-09-16 09:16:43 +02:00

Cleaned up settlers

This commit is contained in:
Aaron Veden
2019-03-06 22:12:39 -08:00
parent b1417cea3c
commit 2921d04e43
9 changed files with 187 additions and 166 deletions

View File

@@ -268,13 +268,17 @@ function upgrade.attempt(natives)
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.42") game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.42")
global.version = constants.VERSION_77 global.version = constants.VERSION_77
end end
if (global.version < constants.VERSION_79) then if (global.version < constants.VERSION_85) then
--REMOVE ME --REMOVE ME
natives.expansion = true natives.expansion = true
natives.building = {}
natives.pendingAttack = {}
natives.cleanBuildingIndex = 1
game.surfaces[natives.activeSurface].print("Rampant - Version 0.17.4") game.surfaces[natives.activeSurface].print("Rampant - Version 0.17.4")
global.version = constants.VERSION_79 global.version = constants.VERSION_85
end end
return starting ~= global.version, natives return starting ~= global.version, natives

View File

@@ -9,9 +9,12 @@ Date: 3. 5. 2019
- Removed old map path finder settings - Removed old map path finder settings
- Added new find position centered flag to positions searches - Added new find position centered flag to positions searches
- Adjusted new enemy worm ranges to vanilla levels - Adjusted new enemy worm ranges to vanilla levels
Optimizations:
- Improved squad processing and squad cleanup
Bugfixes: Bugfixes:
- Fixed player pheromone not having highest value on chunk player was on - Fixed player pheromone not having highest value on chunk player was on
- Fixed settlers not being able to see chunks with resources on them - Fixed settlers not being able to see chunks with resources on them
- Fixed retreat command not disengaging biters
--------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------
Version: 0.17.3 Version: 0.17.3

View File

@@ -93,7 +93,7 @@ local recycleBases = baseUtils.recycleBases
local deathScent = pheromoneUtils.deathScent local deathScent = pheromoneUtils.deathScent
local victoryScent = pheromoneUtils.victoryScent local victoryScent = pheromoneUtils.victoryScent
local cleanSquads = unitGroupUtils.cleanSquads local cleanBuilders = unitGroupUtils.cleanBuilders
local regroupSquads = unitGroupUtils.regroupSquads local regroupSquads = unitGroupUtils.regroupSquads
local convertUnitGroupToSquad = unitGroupUtils.convertUnitGroupToSquad local convertUnitGroupToSquad = unitGroupUtils.convertUnitGroupToSquad
@@ -269,16 +269,12 @@ local function rebuildMap()
ignore_planner = true ignore_planner = true
} }
map.retreatCommand = { type = DEFINES_COMMAND_GROUP, map.retreatCommand = {
group = nil, type = DEFINES_COMMAND_GROUP,
distraction = DEFINES_DISTRACTION_NONE } group = nil,
distraction = DEFINES_DISTRACTION_NONE,
-- switched over to tick event use_group_distraction = false
-- map.logicTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC) }
-- map.scanTick = roundToNearest(game.tick + INTERVAL_SCAN, INTERVAL_SCAN)
-- map.processTick = roundToNearest(game.tick + INTERVAL_PROCESS, INTERVAL_PROCESS)
-- map.chunkTick = roundToNearest(game.tick + INTERVAL_CHUNK, INTERVAL_CHUNK)
-- map.squadTick = roundToNearest(game.tick + INTERVAL_SQUAD, INTERVAL_SQUAD)
end end
@@ -441,9 +437,11 @@ script.on_nth_tick(INTERVAL_SQUAD,
function (event) function (event)
local gameRef = game local gameRef = game
cleanSquads(natives, map) -- cleanSquads(natives, map)
regroupSquads(natives, map) regroupSquads(natives, map)
cleanBuilders(natives)
squadsBeginAttack(natives, gameRef.players) squadsBeginAttack(natives, gameRef.players)
squadsDispatch(map, gameRef.surfaces[natives.activeSurface], natives) squadsDispatch(map, gameRef.surfaces[natives.activeSurface], natives)
end) end)

View File

@@ -146,7 +146,7 @@ local function noNearbySettlers(map, chunk, tick)
end end
function aiAttackWave.formSettlers(map, surface, natives, chunk, tick) function aiAttackWave.formSettlers(map, surface, natives, chunk, tick)
if (mRandom() < natives.formSquadThreshold) and (#natives.squads < AI_MAX_SQUAD_COUNT) then if (mRandom() < natives.formSquadThreshold) and ((#natives.squads + #natives.building) < AI_MAX_SQUAD_COUNT) then
local squadPath, squadDirection local squadPath, squadDirection
if (natives.state == AI_STATE_SIEGE) then if (natives.state == AI_STATE_SIEGE) then
@@ -172,7 +172,7 @@ function aiAttackWave.formSettlers(map, surface, natives, chunk, tick)
4, 4,
true) true)
if squadPosition then if squadPosition then
local squad = createSquad(squadPosition, surface, natives, nil, true) local squad = createSquad(squadPosition, surface, nil, true)
squad.maxDistance = gaussianRandomRange(natives.expansionMaxDistance, squad.maxDistance = gaussianRandomRange(natives.expansionMaxDistance,
natives.expansionMaxDistanceDerivation, natives.expansionMaxDistanceDerivation,
@@ -189,10 +189,15 @@ function aiAttackWave.formSettlers(map, surface, natives, chunk, tick)
unit_search_distance = TRIPLE_CHUNK_SIZE }) unit_search_distance = TRIPLE_CHUNK_SIZE })
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.points = natives.points - AI_SETTLER_COST natives.points = natives.points - AI_SETTLER_COST
end else
end if (squad.group.valid) then
end squad.group.destroy()
end
end
end
end
end end
return (natives.points - AI_SETTLER_COST) > 0 return (natives.points - AI_SETTLER_COST) > 0
@@ -216,7 +221,7 @@ function aiAttackWave.formVengenceSquad(map, surface, natives, chunk)
4, 4,
true) true)
if squadPosition then if squadPosition then
local squad = createSquad(squadPosition, surface, natives) local squad = createSquad(squadPosition, surface)
squad.rabid = mRandom() < 0.03 squad.rabid = mRandom() < 0.03
@@ -227,7 +232,12 @@ function aiAttackWave.formVengenceSquad(map, surface, natives, chunk)
unit_count = scaledWaveSize, unit_count = scaledWaveSize,
unit_search_distance = TRIPLE_CHUNK_SIZE }) unit_search_distance = TRIPLE_CHUNK_SIZE })
if (foundUnits > 0) then if (foundUnits > 0) then
natives.pendingAttack[#natives.pendingAttack+1] = squad
natives.points = natives.points - AI_VENGENCE_SQUAD_COST natives.points = natives.points - AI_VENGENCE_SQUAD_COST
else
if (squad.group.valid) then
squad.group.destroy()
end
end end
end end
end end
@@ -255,7 +265,7 @@ function aiAttackWave.formSquads(map, surface, natives, chunk)
4, 4,
true) true)
if squadPosition then if squadPosition then
local squad = createSquad(squadPosition, surface, natives) local squad = createSquad(squadPosition, surface)
squad.rabid = mRandom() < 0.03 squad.rabid = mRandom() < 0.03
@@ -266,10 +276,15 @@ function aiAttackWave.formSquads(map, surface, natives, chunk)
unit_count = scaledWaveSize, unit_count = scaledWaveSize,
unit_search_distance = TRIPLE_CHUNK_SIZE }) unit_search_distance = TRIPLE_CHUNK_SIZE })
if (foundUnits > 0) then if (foundUnits > 0) then
natives.pendingAttack[#natives.pendingAttack+1] = squad
natives.points = natives.points - AI_SQUAD_COST natives.points = natives.points - AI_SQUAD_COST
else
if (squad.group.valid) then
squad.group.destroy()
end
end end
end end
end end
end end
return (natives.points - AI_SQUAD_COST) > 0 return (natives.points - AI_SQUAD_COST) > 0

View File

@@ -29,7 +29,7 @@ constants.VERSION_73 = 73
constants.VERSION_75 = 75 constants.VERSION_75 = 75
constants.VERSION_76 = 76 constants.VERSION_76 = 76
constants.VERSION_77 = 77 constants.VERSION_77 = 77
constants.VERSION_79 = 79 constants.VERSION_85 = 85
-- misc -- misc

View File

@@ -84,7 +84,7 @@ function interop.getAttackUsePlayer()
end end
function interop.registerUnitGroup(unitGroup) function interop.registerUnitGroup(unitGroup)
unitGroupUtils.createSquad(unitGroup.position, unitGroup.surface, global.natives, unitGroup) unitGroupUtils.createSquad(unitGroup.position, unitGroup.surface, unitGroup)
end end
interopG = interop interopG = interop

View File

@@ -28,6 +28,9 @@ local SQUAD_BUILDING = constants.SQUAD_BUILDING
local SQUAD_RAIDING = constants.SQUAD_RAIDING local SQUAD_RAIDING = constants.SQUAD_RAIDING
local SQUAD_SETTLING = constants.SQUAD_SETTLING local SQUAD_SETTLING = constants.SQUAD_SETTLING
local SQUAD_GUARDING = constants.SQUAD_GUARDING local SQUAD_GUARDING = constants.SQUAD_GUARDING
local SQUAD_RETREATING = constants.SQUAD_RETREATING
local AI_MAX_BITER_GROUP_SIZE = constants.AI_MAX_BITER_GROUP_SIZE
local AI_STATE_SIEGE = constants.AI_STATE_SIEGE local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
@@ -47,11 +50,14 @@ local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
-- imported functions -- imported functions
local mRandom = math.random local mRandom = math.random
local tRemove = table.remove
local euclideanDistancePoints = mathUtils.euclideanDistancePoints local euclideanDistancePoints = mathUtils.euclideanDistancePoints
local findMovementPosition = movementUtils.findMovementPosition local findMovementPosition = movementUtils.findMovementPosition
local removeSquadFromChunk = chunkPropertyUtils.removeSquadFromChunk
local getNestCount = chunkPropertyUtils.getNestCount local getNestCount = chunkPropertyUtils.getNestCount
local getNeighborChunks = mapUtils.getNeighborChunks local getNeighborChunks = mapUtils.getNeighborChunks
@@ -105,7 +111,7 @@ end
local function settleMove(map, attackPosition, attackCmd, settleCmd, squad, group, natives, surface) local function settleMove(map, attackPosition, attackCmd, settleCmd, squad, group, natives, surface)
local groupState = group.state local groupState = group.state
if (groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING) or ((groupState == DEFINES_GROUP_MOVING) and (squad.cycles == 0)) then if (groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING) or ((groupState == DEFINES_GROUP_MOVING) and (squad.cycles <= 0)) then
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)
@@ -121,9 +127,9 @@ local function settleMove(map, attackPosition, attackCmd, settleCmd, squad, grou
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
addSquadToChunk(map, chunk, squad) addSquadToChunk(map, chunk, squad)
addMovementPenalty(natives, squad, chunk) addMovementPenalty(natives, squad, chunk)
-- elseif (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then -- elseif (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
-- addSquadToChunk(map, attackChunk, squad) -- addSquadToChunk(map, attackChunk, squad)
-- addMovementPenalty(natives, squad, attackChunk) -- addMovementPenalty(natives, squad, attackChunk)
end end
if group.valid and (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then if group.valid and (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
local resourceGenerator = getResourceGenerator(map, chunk) local resourceGenerator = getResourceGenerator(map, chunk)
@@ -176,7 +182,7 @@ end
local function attackMove(map, attackPosition, attackCmd, squad, group, natives, surface) local function attackMove(map, attackPosition, attackCmd, squad, group, natives, surface)
local groupState = group.state local groupState = group.state
if (groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING) or ((groupState == DEFINES_GROUP_MOVING) and (squad.cycles == 0)) then if (groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING) or ((groupState == DEFINES_GROUP_MOVING) and (squad.cycles <= 0)) then
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)
@@ -193,14 +199,17 @@ local function attackMove(map, attackPosition, attackCmd, squad, group, natives,
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
addSquadToChunk(map, chunk, squad) addSquadToChunk(map, chunk, squad)
addMovementPenalty(natives, squad, chunk) addMovementPenalty(natives, squad, chunk)
-- elseif (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then -- elseif (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
-- addSquadToChunk(map, attackChunk, squad) -- addSquadToChunk(map, attackChunk, squad)
-- addMovementPenalty(natives, squad, attackChunk) -- addMovementPenalty(natives, squad, attackChunk)
end end
if group.valid and (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then if group.valid and (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
local playerBaseGenerator = getPlayerBaseGenerator(map, attackChunk) local playerBaseGenerator = getPlayerBaseGenerator(map, attackChunk)
if (playerBaseGenerator == 0) or ((groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING)) then -- local playerPheromone = attackChunk[PLAYER_PHEROMONE]
if (playerBaseGenerator == 0) or
((groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING))-- or
-- (playerPheromone < natives.attackPlayerThreshold)
then
squad.cycles = ((#squad.group.members > 80) and 6) or 4 squad.cycles = ((#squad.group.members > 80) and 6) or 4
local moreFrenzy = not squad.rabid and squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100) local moreFrenzy = not squad.rabid and squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100)
@@ -239,56 +248,83 @@ function squadAttack.squadsDispatch(map, surface, natives)
local attackCmd = map.attackAreaCommand local attackCmd = map.attackAreaCommand
local settleCmd = map.settleCommand local settleCmd = map.settleCommand
for i=1,#squads do for i=#squads,1,-1 do
local squad = squads[i] local squad = squads[i]
local group = squad.group local group = squad.group
if group and group.valid then if group and group.valid then
local memberCount = #group.members
if (memberCount == 0) then
tRemove(squads, i)
removeSquadFromChunk(map, squad)
group.destroy()
elseif (memberCount > AI_MAX_BITER_GROUP_SIZE) then
local members = group.members
unitGroupUtils.recycleBiters(natives, members)
tRemove(squads, i)
removeSquadFromChunk(map, squad)
group.destroy()
else
local status = squad.status
local cycles = squad.cycles
if (squad.status == SQUAD_RAIDING) then if (status == SQUAD_RAIDING) then
attackMove(map, attackPosition, attackCmd, squad, group, natives, surface) attackMove(map, attackPosition, attackCmd, squad, group, natives, surface)
elseif (squad.status == SQUAD_SETTLING) then elseif (status == SQUAD_SETTLING) then
settleMove(map, attackPosition, attackCmd, settleCmd, squad, group, natives, surface) settleMove(map, attackPosition, attackCmd, settleCmd, squad, group, natives, surface)
end elseif (status == SQUAD_RETREATING) and (cycles == 0) then
end natives.pendingAttack[#natives.pendingAttack+1] = squad
squad.status = SQUAD_GUARDING
elseif (status == SQUAD_BUILDING) then
tRemove(squads, i)
removeSquadFromChunk(map, squad)
natives.building[#natives.building+1] = squad
end
if (cycles > 0) then
squad.cycles = cycles - 1
end
end
else
tRemove(squads, i)
removeSquadFromChunk(map, squad)
end
end end
end end
function squadAttack.squadsBeginAttack(natives, players) function squadAttack.squadsBeginAttack(natives, players)
local squads = natives.squads local squads = natives.pendingAttack
for i=1,#squads do for i=1,#squads do
local squad = squads[i] local squad = squads[i]
local group = squad.group local group = squad.group
local kamikazeThreshold = calculateKamikazeThreshold(#squad.group.members, natives) if group and group.valid then
if not squad.kamikaze then local kamikazeThreshold = calculateKamikazeThreshold(#squad.group.members, natives)
squad.kamikaze = (mRandom() < kamikazeThreshold) if not squad.kamikaze then
end squad.kamikaze = (mRandom() < kamikazeThreshold)
if squad.settlers then end
if (squad.status == SQUAD_GUARDING) and group and group.valid then if squad.settlers then
-- local kamikazeThreshold = calculateKamikazeThreshold(#squad.group.members, natives) -- if (squad.status == SQUAD_GUARDING) then
-- squad.kamikaze = mRandom() < kamikazeThreshold squad.status = SQUAD_SETTLING
squad.status = SQUAD_SETTLING natives.squads[#natives.squads+1] = squad
end else
else -- if (squad.status == SQUAD_GUARDING) then
if (squad.status == SQUAD_GUARDING) and group and group.valid then local groupPosition = group.position
local groupPosition = group.position if playersWithinProximityToPosition(players, groupPosition, 100, natives) then
if playersWithinProximityToPosition(players, groupPosition, 100, natives) then squad.frenzy = true
squad.frenzy = true squad.frenzyPosition.x = groupPosition.x
squad.frenzyPosition.x = groupPosition.x squad.frenzyPosition.y = groupPosition.y
squad.frenzyPosition.y = groupPosition.y end
end
-- local kamikazeThreshold = calculateKamikazeThreshold(#squad.group.members, natives)
-- if not squad.kamikaze then
-- squad.kamikaze = (mRandom() < kamikazeThreshold)
-- end
if squad.kamikaze and (mRandom() < (kamikazeThreshold * 0.75)) then if squad.kamikaze and (mRandom() < (kamikazeThreshold * 0.75)) then
squad.attackScoreFunction = ATTACK_SCORE_KAMIKAZE squad.attackScoreFunction = ATTACK_SCORE_KAMIKAZE
end end
squad.status = SQUAD_RAIDING squad.status = SQUAD_RAIDING
end natives.squads[#natives.squads+1] = squad
end end
-- end
end
end end
natives.pendingAttack = {}
end end
squadAttackG = squadAttack squadAttackG = squadAttack

View File

@@ -91,12 +91,19 @@ function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, t
local newSquad = findNearbySquadFiltered(map, exitPath, retreatPosition) local newSquad = findNearbySquadFiltered(map, exitPath, retreatPosition)
if not newSquad then if not newSquad then
newSquad = createSquad(retreatPosition, surface, natives) newSquad = createSquad(retreatPosition, surface)
newSquad.status = SQUAD_RETREATING natives.squads[#natives.squads+1] = newSquad
newSquad.cycles = 4
end end
if newSquad then if newSquad then
newSquad.status = SQUAD_RETREATING
newSquad.cycles = 4
squad.frenzy = true
local squadPosition = newSquad.group.position
squad.frenzyPosition.x = squadPosition.x
squad.frenzyPosition.y = squadPosition.y
local cmd = map.retreatCommand local cmd = map.retreatCommand
cmd.group = newSquad.group cmd.group = newSquad.group
if enemiesToSquad then if enemiesToSquad then

View File

@@ -16,17 +16,17 @@ local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE
local SQUAD_QUEUE_SIZE = constants.SQUAD_QUEUE_SIZE local SQUAD_QUEUE_SIZE = constants.SQUAD_QUEUE_SIZE
local DEFINES_GROUP_STATE_FINISHED = defines.group_state.finished -- local DEFINES_GROUP_STATE_FINISHED = defines.group_state.finished
local DEFINES_GROUP_STATE_ATTACKING_TARGET = defines.group_state.attacking_target local DEFINES_GROUP_STATE_ATTACKING_TARGET = defines.group_state.attacking_target
local DEFINES_GROUP_STATE_ATTACKING_DISTRACTION = defines.group_state.attacking_distraction local DEFINES_GROUP_STATE_ATTACKING_DISTRACTION = defines.group_state.attacking_distraction
local SQUAD_RETREATING = constants.SQUAD_RETREATING local SQUAD_RETREATING = constants.SQUAD_RETREATING
local SQUAD_GUARDING = constants.SQUAD_GUARDING local SQUAD_GUARDING = constants.SQUAD_GUARDING
local SQUAD_SETTLING = constants.SQUAD_SETTLING -- local SQUAD_SETTLING = constants.SQUAD_SETTLING
local SQUAD_BUILDING = constants.SQUAD_BUILDING -- local SQUAD_BUILDING = constants.SQUAD_BUILDING
local GROUP_MERGE_DISTANCE = constants.GROUP_MERGE_DISTANCE -- local GROUP_MERGE_DISTANCE = constants.GROUP_MERGE_DISTANCE
local RETREAT_FILTER = constants.RETREAT_FILTER -- local RETREAT_FILTER = constants.RETREAT_FILTER
local NO_RETREAT_SQUAD_SIZE_BONUS_MAX = constants.NO_RETREAT_SQUAD_SIZE_BONUS_MAX local NO_RETREAT_SQUAD_SIZE_BONUS_MAX = constants.NO_RETREAT_SQUAD_SIZE_BONUS_MAX
@@ -37,14 +37,18 @@ local AI_SQUAD_MERGE_THRESHOLD = constants.AI_SQUAD_MERGE_THRESHOLD
-- imported functions -- imported functions
local tRemove = table.remove
local mRandom = math.random local mRandom = math.random
local mLog = math.log10 local mLog = math.log10
local removeSquadFromChunk = chunkPropertyUtils.removeSquadFromChunk
local mMin = math.min local mMin = math.min
local getSquadsOnChunk = chunkPropertyUtils.getSquadsOnChunk local getSquadsOnChunk = chunkPropertyUtils.getSquadsOnChunk
local removeSquadFromChunk = chunkPropertyUtils.removeSquadFromChunk -- local removeSquadFromChunk = chunkPropertyUtils.removeSquadFromChunk
local getNeighborChunks = mapUtils.getNeighborChunks local getNeighborChunks = mapUtils.getNeighborChunks
@@ -104,7 +108,7 @@ function unitGroupUtils.findNearbySquad(map, chunk, position)
return nil return nil
end end
function unitGroupUtils.createSquad(position, surface, natives, group, settlers) function unitGroupUtils.createSquad(position, surface, group, settlers)
local unitGroup = group or surface.create_unit_group({position=position}) local unitGroup = group or surface.create_unit_group({position=position})
local squad = { local squad = {
@@ -124,7 +128,7 @@ function unitGroupUtils.createSquad(position, surface, natives, group, settlers)
y = 0}, y = 0},
chunk = nil chunk = nil
} }
natives.squads[#natives.squads+1] = squad
return squad return squad
end end
@@ -150,7 +154,7 @@ function unitGroupUtils.convertUnitGroupToSquad(natives, unitGroup)
return squad return squad
end end
end end
local squad = unitGroupUtils.createSquad(nil,nil,natives,unitGroup) local squad = unitGroupUtils.createSquad(nil,nil,unitGroup)
squad.kamikaze = mRandom() < unitGroupUtils.calculateKamikazeThreshold(#unitGroup.members, natives) squad.kamikaze = mRandom() < unitGroupUtils.calculateKamikazeThreshold(#unitGroup.members, natives)
return squad return squad
end end
@@ -165,49 +169,6 @@ local function isAttacking(group)
return (state == DEFINES_GROUP_STATE_ATTACKING_TARGET) or (state == DEFINES_GROUP_STATE_ATTACKING_DISTRACTION) return (state == DEFINES_GROUP_STATE_ATTACKING_TARGET) or (state == DEFINES_GROUP_STATE_ATTACKING_DISTRACTION)
end end
function unitGroupUtils.cleanSquads(natives, map)
local squads = natives.squads
local squadCount = #squads
local cleanSquads = {}
for i=1, squadCount do
local squad = squads[i]
local group = squad.group
if group and group.valid then
local memberCount = #group.members
if (memberCount == 0) then
removeSquadFromChunk(map, squad)
group.destroy()
elseif (memberCount > AI_MAX_BITER_GROUP_SIZE) then
local members = group.members
unitGroupUtils.recycleBiters(natives, members)
removeSquadFromChunk(map, squad)
group.destroy()
else
local status = squad.status
local cycles = squad.cycles
if (status == SQUAD_RETREATING) and (cycles == 0) then
squad.status = SQUAD_GUARDING
squad.frenzy = true
local squadPosition = group.position
squad.frenzyPosition.x = squadPosition.x
squad.frenzyPosition.y = squadPosition.y
elseif (group.state == DEFINES_GROUP_STATE_FINISHED) and not squad.settlers then
squad.status = SQUAD_GUARDING
elseif (cycles > 0) then
squad.cycles = cycles - 1
end
cleanSquads[#cleanSquads+1] = squad
end
else
removeSquadFromChunk(map, squad)
end
end
natives.squads = cleanSquads
end
function unitGroupUtils.recycleBiters(natives, biters) function unitGroupUtils.recycleBiters(natives, biters)
local unitCount = #biters local unitCount = #biters
for i=1,unitCount do for i=1,unitCount do
@@ -220,18 +181,17 @@ function unitGroupUtils.recycleBiters(natives, biters)
end end
end end
local function mergeGroups(squads, squad, group, status, position, memberCount) local function mergeGroups(squads, squad, group, status, memberCount, map)
local merge = false local merge = false
local maxed = false local maxed = false
for _,mergeSquad in pairs(squads) do for _,mergeSquad in pairs(squads) do
if (mergeSquad ~= squad) then if (mergeSquad ~= squad) then
local mergeGroup = mergeSquad.group local mergeGroup = mergeSquad.group
if mergeGroup and if mergeGroup and
mergeGroup.valid and mergeGroup.valid and
(squad.status ~= SQUAD_BUILDING) and
(mergeSquad.status == status) and (mergeSquad.status == status) and
not isAttacking(mergeGroup) and not isAttacking(mergeGroup) -- and
(euclideanDistanceNamed(position, mergeGroup.position) < GROUP_MERGE_DISTANCE) -- (euclideanDistanceNamed(position, mergeGroup.position) < GROUP_MERGE_DISTANCE)
then then
local mergeMembers = mergeGroup.members local mergeMembers = mergeGroup.members
local mergeCount = #mergeMembers local mergeCount = #mergeMembers
@@ -240,6 +200,7 @@ local function mergeGroups(squads, squad, group, status, position, memberCount)
group.add_member(mergeMembers[memberIndex]) group.add_member(mergeMembers[memberIndex])
end end
merge = true merge = true
removeSquadFromChunk(map, mergeSquad)
mergeGroup.destroy() mergeGroup.destroy()
end end
memberCount = memberCount + mergeCount memberCount = memberCount + mergeCount
@@ -253,6 +214,29 @@ local function mergeGroups(squads, squad, group, status, position, memberCount)
return merge, memberCount, maxed return merge, memberCount, maxed
end end
function unitGroupUtils.cleanBuilders(natives)
local squads = natives.building
local squadCount = #squads
local startIndex = natives.cleanBuildingIndex
local maxSquadIndex = mMin(startIndex + SQUAD_QUEUE_SIZE, squadCount)
for i=maxSquadIndex,startIndex,-1 do
local squad = squads[i]
local group = squad.group
if not (group and group.valid) then
tRemove(squads, i)
end
end
if (maxSquadIndex == squadCount) then
natives.cleanBuildingIndex = 1
else
natives.cleanBuildingIndex = maxSquadIndex + 1
end
end
function unitGroupUtils.regroupSquads(natives, map) function unitGroupUtils.regroupSquads(natives, map)
local squads = natives.squads local squads = natives.squads
local squadCount = #squads local squadCount = #squads
@@ -263,55 +247,29 @@ function unitGroupUtils.regroupSquads(natives, map)
for i=startIndex,maxSquadIndex do for i=startIndex,maxSquadIndex do
local squad = squads[i] local squad = squads[i]
local group = squad.group local group = squad.group
if group and group.valid and not isAttacking(group) and (squad.status ~= SQUAD_BUILDING) then if group and group.valid and not isAttacking(group) then
local memberCount = #group.members local memberCount = #group.members
if (memberCount < AI_SQUAD_MERGE_THRESHOLD) then if (memberCount < AI_SQUAD_MERGE_THRESHOLD) then
local status = squad.status local status = squad.status
local squadPosition = group.position
local mergedSquads = false
local maxed
local chunk = squad.chunk local chunk = squad.chunk
if chunk then if chunk then
mergedSquads, memberCount, maxed = mergeGroups(getSquadsOnChunk(map, chunk), mergeGroups(getSquadsOnChunk(map, chunk),
squad, squad,
group, group,
status, status,
squadPosition, memberCount,
memberCount) map)
if not maxed then
local neighbors = getNeighborChunks(map, chunk.x, chunk.y)
for x=1,#neighbors do
local maybeMerge
maybeMerge, memberCount, maxed = mergeGroups(getSquadsOnChunk(map, neighbors[x]),
squad,
group,
status,
squadPosition,
memberCount)
if maybeMerge then
mergedSquads = true
end
if maxed then
break
end
end
end
end
if mergedSquads then
squad.status = SQUAD_GUARDING
end end
end end
end end
end end
if (maxSquadIndex == squadCount) then if (maxSquadIndex == squadCount) then
natives.regroupIndex = 1 natives.regroupIndex = 1
else else
natives.regroupIndex = maxSquadIndex + 1 natives.regroupIndex = maxSquadIndex + 1
end end
end end