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")
global.version = constants.VERSION_77
end
if (global.version < constants.VERSION_79) then
if (global.version < constants.VERSION_85) then
--REMOVE ME
natives.expansion = true
natives.building = {}
natives.pendingAttack = {}
natives.cleanBuildingIndex = 1
game.surfaces[natives.activeSurface].print("Rampant - Version 0.17.4")
global.version = constants.VERSION_79
global.version = constants.VERSION_85
end
return starting ~= global.version, natives

View File

@@ -9,9 +9,12 @@ Date: 3. 5. 2019
- Removed old map path finder settings
- Added new find position centered flag to positions searches
- Adjusted new enemy worm ranges to vanilla levels
Optimizations:
- Improved squad processing and squad cleanup
Bugfixes:
- 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 retreat command not disengaging biters
---------------------------------------------------------------------------------------------------
Version: 0.17.3

View File

@@ -93,7 +93,7 @@ local recycleBases = baseUtils.recycleBases
local deathScent = pheromoneUtils.deathScent
local victoryScent = pheromoneUtils.victoryScent
local cleanSquads = unitGroupUtils.cleanSquads
local cleanBuilders = unitGroupUtils.cleanBuilders
local regroupSquads = unitGroupUtils.regroupSquads
local convertUnitGroupToSquad = unitGroupUtils.convertUnitGroupToSquad
@@ -269,16 +269,12 @@ local function rebuildMap()
ignore_planner = true
}
map.retreatCommand = { type = DEFINES_COMMAND_GROUP,
map.retreatCommand = {
type = DEFINES_COMMAND_GROUP,
group = nil,
distraction = DEFINES_DISTRACTION_NONE }
-- switched over to tick event
-- 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)
distraction = DEFINES_DISTRACTION_NONE,
use_group_distraction = false
}
end
@@ -441,9 +437,11 @@ script.on_nth_tick(INTERVAL_SQUAD,
function (event)
local gameRef = game
cleanSquads(natives, map)
-- cleanSquads(natives, map)
regroupSquads(natives, map)
cleanBuilders(natives)
squadsBeginAttack(natives, gameRef.players)
squadsDispatch(map, gameRef.surfaces[natives.activeSurface], natives)
end)

View File

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

View File

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

View File

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

View File

@@ -28,6 +28,9 @@ local SQUAD_BUILDING = constants.SQUAD_BUILDING
local SQUAD_RAIDING = constants.SQUAD_RAIDING
local SQUAD_SETTLING = constants.SQUAD_SETTLING
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
@@ -47,11 +50,14 @@ local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
-- imported functions
local mRandom = math.random
local tRemove = table.remove
local euclideanDistancePoints = mathUtils.euclideanDistancePoints
local findMovementPosition = movementUtils.findMovementPosition
local removeSquadFromChunk = chunkPropertyUtils.removeSquadFromChunk
local getNestCount = chunkPropertyUtils.getNestCount
local getNeighborChunks = mapUtils.getNeighborChunks
@@ -105,7 +111,7 @@ end
local function settleMove(map, attackPosition, attackCmd, settleCmd, squad, group, natives, surface)
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 x, y = positionToChunkXY(groupPosition)
local chunk = getChunkByXY(map, x, y)
@@ -176,7 +182,7 @@ end
local function attackMove(map, attackPosition, attackCmd, squad, group, natives, surface)
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 x, y = positionToChunkXY(groupPosition)
local chunk = getChunkByXY(map, x, y)
@@ -199,8 +205,11 @@ local function attackMove(map, attackPosition, attackCmd, squad, group, natives,
end
if group.valid and (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
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
local moreFrenzy = not squad.rabid and squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100)
@@ -239,37 +248,66 @@ function squadAttack.squadsDispatch(map, surface, natives)
local attackCmd = map.attackAreaCommand
local settleCmd = map.settleCommand
for i=1,#squads do
for i=#squads,1,-1 do
local squad = squads[i]
local group = squad.group
if group and group.valid then
if (squad.status == SQUAD_RAIDING) 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 (status == SQUAD_RAIDING) then
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)
elseif (status == SQUAD_RETREATING) and (cycles == 0) then
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
function squadAttack.squadsBeginAttack(natives, players)
local squads = natives.squads
local squads = natives.pendingAttack
for i=1,#squads do
local squad = squads[i]
local group = squad.group
if group and group.valid then
local kamikazeThreshold = calculateKamikazeThreshold(#squad.group.members, natives)
if not squad.kamikaze then
squad.kamikaze = (mRandom() < kamikazeThreshold)
end
if squad.settlers then
if (squad.status == SQUAD_GUARDING) and group and group.valid then
-- local kamikazeThreshold = calculateKamikazeThreshold(#squad.group.members, natives)
-- squad.kamikaze = mRandom() < kamikazeThreshold
-- if (squad.status == SQUAD_GUARDING) then
squad.status = SQUAD_SETTLING
end
natives.squads[#natives.squads+1] = squad
else
if (squad.status == SQUAD_GUARDING) and group and group.valid then
-- if (squad.status == SQUAD_GUARDING) then
local groupPosition = group.position
if playersWithinProximityToPosition(players, groupPosition, 100, natives) then
squad.frenzy = true
@@ -277,18 +315,16 @@ function squadAttack.squadsBeginAttack(natives, players)
squad.frenzyPosition.y = groupPosition.y
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
squad.attackScoreFunction = ATTACK_SCORE_KAMIKAZE
end
squad.status = SQUAD_RAIDING
natives.squads[#natives.squads+1] = squad
end
-- end
end
end
end
natives.pendingAttack = {}
end
squadAttackG = squadAttack

View File

@@ -91,12 +91,19 @@ function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, t
local newSquad = findNearbySquadFiltered(map, exitPath, retreatPosition)
if not newSquad then
newSquad = createSquad(retreatPosition, surface, natives)
newSquad.status = SQUAD_RETREATING
newSquad.cycles = 4
newSquad = createSquad(retreatPosition, surface)
natives.squads[#natives.squads+1] = newSquad
end
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
cmd.group = newSquad.group
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 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_DISTRACTION = defines.group_state.attacking_distraction
local SQUAD_RETREATING = constants.SQUAD_RETREATING
local SQUAD_GUARDING = constants.SQUAD_GUARDING
local SQUAD_SETTLING = constants.SQUAD_SETTLING
local SQUAD_BUILDING = constants.SQUAD_BUILDING
local GROUP_MERGE_DISTANCE = constants.GROUP_MERGE_DISTANCE
-- local SQUAD_SETTLING = constants.SQUAD_SETTLING
-- local SQUAD_BUILDING = constants.SQUAD_BUILDING
-- 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
@@ -37,14 +37,18 @@ local AI_SQUAD_MERGE_THRESHOLD = constants.AI_SQUAD_MERGE_THRESHOLD
-- imported functions
local tRemove = table.remove
local mRandom = math.random
local mLog = math.log10
local removeSquadFromChunk = chunkPropertyUtils.removeSquadFromChunk
local mMin = math.min
local getSquadsOnChunk = chunkPropertyUtils.getSquadsOnChunk
local removeSquadFromChunk = chunkPropertyUtils.removeSquadFromChunk
-- local removeSquadFromChunk = chunkPropertyUtils.removeSquadFromChunk
local getNeighborChunks = mapUtils.getNeighborChunks
@@ -104,7 +108,7 @@ function unitGroupUtils.findNearbySquad(map, chunk, position)
return nil
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 squad = {
@@ -124,7 +128,7 @@ function unitGroupUtils.createSquad(position, surface, natives, group, settlers)
y = 0},
chunk = nil
}
natives.squads[#natives.squads+1] = squad
return squad
end
@@ -150,7 +154,7 @@ function unitGroupUtils.convertUnitGroupToSquad(natives, unitGroup)
return squad
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)
return squad
end
@@ -165,49 +169,6 @@ local function isAttacking(group)
return (state == DEFINES_GROUP_STATE_ATTACKING_TARGET) or (state == DEFINES_GROUP_STATE_ATTACKING_DISTRACTION)
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)
local unitCount = #biters
for i=1,unitCount do
@@ -220,7 +181,7 @@ function unitGroupUtils.recycleBiters(natives, biters)
end
end
local function mergeGroups(squads, squad, group, status, position, memberCount)
local function mergeGroups(squads, squad, group, status, memberCount, map)
local merge = false
local maxed = false
for _,mergeSquad in pairs(squads) do
@@ -228,10 +189,9 @@ local function mergeGroups(squads, squad, group, status, position, memberCount)
local mergeGroup = mergeSquad.group
if mergeGroup and
mergeGroup.valid and
(squad.status ~= SQUAD_BUILDING) and
(mergeSquad.status == status) and
not isAttacking(mergeGroup) and
(euclideanDistanceNamed(position, mergeGroup.position) < GROUP_MERGE_DISTANCE)
not isAttacking(mergeGroup) -- and
-- (euclideanDistanceNamed(position, mergeGroup.position) < GROUP_MERGE_DISTANCE)
then
local mergeMembers = mergeGroup.members
local mergeCount = #mergeMembers
@@ -240,6 +200,7 @@ local function mergeGroups(squads, squad, group, status, position, memberCount)
group.add_member(mergeMembers[memberIndex])
end
merge = true
removeSquadFromChunk(map, mergeSquad)
mergeGroup.destroy()
end
memberCount = memberCount + mergeCount
@@ -253,6 +214,29 @@ local function mergeGroups(squads, squad, group, status, position, memberCount)
return merge, memberCount, maxed
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)
local squads = natives.squads
local squadCount = #squads
@@ -263,46 +247,20 @@ function unitGroupUtils.regroupSquads(natives, map)
for i=startIndex,maxSquadIndex do
local squad = squads[i]
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
if (memberCount < AI_SQUAD_MERGE_THRESHOLD) then
local status = squad.status
local squadPosition = group.position
local mergedSquads = false
local maxed
local chunk = squad.chunk
if chunk then
mergedSquads, memberCount, maxed = mergeGroups(getSquadsOnChunk(map, chunk),
mergeGroups(getSquadsOnChunk(map, chunk),
squad,
group,
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