1
0
mirror of https://github.com/veden/Rampant.git synced 2025-03-17 20:58:35 +02:00

shared tables performance check

This commit is contained in:
veden 2016-08-29 21:08:22 -07:00
parent a88f48bba0
commit 6c4c986df6
11 changed files with 121 additions and 59 deletions

View File

@ -1,5 +1,6 @@
-- imports
local setupUtils = require("setupUtils")
local entityUtils = require("libs/EntityUtils")
local unitGroupUtils = require("libs/UnitGroupUtils")
local chunkProcessor = require("libs/ChunkProcessor")
@ -41,6 +42,7 @@ local regionMap
local natives
local pheromoneTotals
local pendingChunks
local temps
-- hook functions
@ -50,11 +52,13 @@ function onInit()
global.pendingChunks = {}
global.natives = {}
global.pheromoneTotals = {}
global.temps = {}
regionMap = global.regionMap
natives = global.natives
pendingChunks = global.pendingChunks
pheromoneTotals = global.pheromoneTotals
temps = global.temps
onConfigChanged()
end
@ -65,6 +69,7 @@ function onLoad()
natives = global.natives
pendingChunks = global.pendingChunks
pheromoneTotals = global.pheromoneTotals
temps = global.temps
end
function onConfigChanged()
@ -97,6 +102,8 @@ function onConfigChanged()
regionMap.scanPointer = 1
regionMap.processRoll = -1
setupUtils.initTemps(temps)
pheromoneTotals[constants.DEATH_PHEROMONE] = 0
pheromoneTotals[constants.ENEMY_BASE_PHEROMONE] = 0
pheromoneTotals[constants.PLAYER_PHEROMONE] = 0
@ -132,21 +139,21 @@ function onTick(event)
accumulatePoints(natives)
-- put down player pheromone for player hunters
playerScent(regionMap, game.players, pheromoneTotals)
playerScent(regionMap, game.players)
regroupSquads(natives)
regroupSquads(natives, temps)
-- scouting(regionMap, natives)
squadBeginAttack(natives, game.players, game.evolution_factor)
squadAttack(regionMap, surface, natives)
squadAttack(regionMap, surface, natives, temps)
end
processPendingChunks(regionMap, surface, natives, pendingChunks)
scanMap(regionMap, surface)
processMap(regionMap, surface, natives, pheromoneTotals, game.evolution_factor)
processMap(regionMap, surface, natives, game.evolution_factor)
end
end
@ -175,7 +182,8 @@ function onDeath(event)
entity.unit_group),
regionMap,
surface,
natives)
natives,
temps)
end
removeScout(entity, global.natives)

View File

@ -66,8 +66,11 @@ local function scoreHuntPlayerLocation(position, squad, neighborChunk, surface)
return damageScore - avoidScore - squadMovementPenalty
end
function aiAttack.squadAttack(regionMap, surface, natives)
function aiAttack.squadAttack(regionMap, surface, natives, temps)
local squads = natives.squads
local attackPosition = temps[constants.ATTACK_POSITION]
local cmd = temps[constants.ATTACK_COMMAND]
local neighborsWithDirection = temps[constants.ATTACK_DIRECTION]
for i=1,#squads do
local squad = squads[i]
local group = squad.group
@ -86,22 +89,21 @@ function aiAttack.squadAttack(regionMap, surface, natives)
local chunk = getChunkByPosition(regionMap, group.position.x, group.position.y)
if (chunk ~= nil) then
addSquadMovementPenalty(squad, chunk.cX, chunk.cY)
getCardinalChunksWithDirection(regionMap, chunk.cX, chunk.cY, neighborsWithDirection)
local attackChunk, attackDirection = scoreNeighborsWithDirection(chunk,
getCardinalChunksWithDirection(regionMap, chunk.cX, chunk.cY),
neighborsWithDirection,
validLocation,
scoreLocation,
squad,
surface)
surface,
attackPosition)
if (attackChunk ~= nil) then
if ((attackChunk[PLAYER_BASE_GENERATOR] == 0) and (attackChunk[PLAYER_DEFENSE_GENERATOR] == 0)) or
((group.state == defines.group_state.finished) or (group.state == defines.group_state.gathering)) then
attackPosition = positionFromDirectionAndChunkCardinal(attackDirection, attackChunk)
positionFromDirectionAndChunkCardinal(attackDirection, attackChunk, attackPosition)
group.set_command({type=defines.command.attack_area,
destination=attackPosition,
radius=32,
distraction=defines.distraction.by_anything})
group.set_command(cmd)
group.start_moving()
end
end

View File

@ -114,14 +114,15 @@ function aiBuilding.formSquads(regionMap, surface, natives, chunk, evolution_fac
if (natives.points > AI_SQUAD_COST) then
local score = chunk[PLAYER_BASE_PHEROMONE] + chunk[PLAYER_PHEROMONE] + chunk[PLAYER_DEFENSE_PHEROMONE] + surface.get_pollution({chunk.pX, chunk.pY})
if (score > 20) and (chunk[ENEMY_BASE_GENERATOR] ~= 0) and (#natives.squads < (AI_MAX_SQUAD_COUNT * evolution_factor)) and (math.random() < 0.03) then
local squadPosition = {x=0, y=0}
local squadPath, squadScore = scoreNeighbors(chunk,
getNeighborChunks(regionMap, chunk.cX, chunk.cY),
validUnitGroupLocation,
scoreUnitGroupLocation,
nil,
surface)
surface,
squadPosition)
if (squadPath ~= nil) and (squadScore > 0) then
local squadPosition = {}
squadPosition.x = squadPath.pX + HALF_CHUNK_SIZE
squadPosition.y = squadPath.pY + HALF_CHUNK_SIZE

View File

@ -58,7 +58,7 @@ local function scoreRetreatLocation(position, squad, neighborChunk, surface)
return safeScore - dangerScore
end
function aiDefense.retreatUnits(position, squad, regionMap, surface, natives)
function aiDefense.retreatUnits(position, squad, regionMap, surface, natives, temps)
local chunk = getChunkByPosition(regionMap, position.x, position.y)
if (chunk ~= nil) and (chunk[DEATH_PHEROMONE] > (game.evolution_factor * RETREAT_DEATH_PHEROMONE_LEVEL)) then
local performRetreat = false
@ -76,15 +76,17 @@ function aiDefense.retreatUnits(position, squad, regionMap, surface, natives)
end
if performRetreat then
local retreatPosition = {x=0, y=0}
local exitPath, exitDirection = scoreNeighborsWithDirection(chunk,
getNeighborChunksWithDirection(regionMap, chunk.cX, chunk.cY),
validRetreatLocation,
scoreRetreatLocation,
nil,
surface)
surface,
retreatPosition)
if (exitPath ~= nil) then
-- retreatPosition = positionDirectionToChunkCorner(exitDirection, exitPath)
local retreatPosition = {}
retreatPosition.x = exitPath.pX + HALF_CHUNK_SIZE
retreatPosition.y = exitPath.pY + HALF_CHUNK_SIZE
@ -99,9 +101,9 @@ function aiDefense.retreatUnits(position, squad, regionMap, surface, natives)
newSquad.cycles = 4
end
if (enemiesToSquad ~= nil) then
membersToSquad(newSquad, enemiesToSquad, false, DISTRACTION_NONE)
membersToSquad(newSquad, enemiesToSquad, false, temps)
else
membersToSquad(newSquad, squad.group.members, true, DISTRACTION_NONE)
membersToSquad(newSquad, squad.group.members, true, temps)
end
end
end

View File

@ -13,6 +13,25 @@ constants.RETREAT_DEATH_PHEROMONE_LEVEL = 10000
constants.PROCESS_QUEUE_SIZE = 350
constants.SCAN_QUEUE_SIZE = 10
--[[
do local _={[1]=92760.165682081453,[2]=59023158.2706149,[3]=71158.702188598996,[4]=1370918.7093454537,[5]=124419.45677482936,[6]=0};return _;end
do local _={[1]=98158.616299591231,[2]=59038394.450318933,[3]=72057.135701418039,[4]=1370836.2445672308,[5]=124395.7734356139,[6]=0};return _;end
do local _={[1]=97736.590112861784,[2]=59041062.525305107,[3]=72057.168895194831,[4]=1370828.7351421521,[5]=124390.748724705,[6]=0};return _;end
do local _={[1]=98524.250226115269,[2]=59054883.613909028,[3]=71458.283358627028,[4]=1370869.1662952597,[5]=124392.5867513624,[6]=0};return _;end
do local _={[1]=98095.238244060965,[2]=59031100.050544381,[3]=71758.312283350504,[4]=1370861.5327379622,[5]=124387.79348559103,[6]=0};return _;end
do local _={[1]=102387.66713415453,[2]=59312468.932505473,[3]=71759.869348238717,[4]=1370608.8889602837,[5]=124218.76705564446,[6]=0};return _;end
do local _={[1]=104347.56572804038,[2]=59323517.951402277,[3]=70876.813399261708,[4]=1372125.2449267947,[5]=124425.11174299028,[6]=0};return _;end
do local _={[1]=60400.251770513649,[2]=59579686.835306533,[3]=72072.361934938977,[4]=1367118.9798292378,[5]=124228.81413756762,[6]=0};return _;end
--]]
-- temps
constants.ATTACK_POSITION = 1
constants.ATTACK_COMMAND = 2
constants.ATTACK_DIRECTION = 3
constants.GROUP_COMMAND = 4
-- ai
constants.AI_POINT_GENERATOR_AMOUNT = 5

View File

@ -25,7 +25,7 @@ local mMin = math.min
-- so 200 chunks is processed 3 times a second and 1200 chunks is processed once a second
-- In theory, this might be fine as smaller bases have less surface to attack and need to have
-- pheromone dissipate at a faster rate.
function mapProcessor.processMap(regionMap, surface, natives, pheromoneTotals, evolution_factor)
function mapProcessor.processMap(regionMap, surface, natives, evolution_factor)
local roll = regionMap.processRoll
local index = regionMap.processPointer
local scouts = false
@ -49,7 +49,7 @@ function mapProcessor.processMap(regionMap, surface, natives, pheromoneTotals, e
for x=index,endIndex do
local chunk = processQueue[x]
scents(chunk, pheromoneTotals)
scents(chunk)
if scouts then
makeScouts(surface, natives, chunk, evolution_factor)
@ -58,7 +58,7 @@ function mapProcessor.processMap(regionMap, surface, natives, pheromoneTotals, e
formSquads(regionMap, surface, natives, chunk, evolution_factor)
end
processPheromone(chunk, getCardinalChunks(regionMap, chunk.cX, chunk.cY), pheromoneTotals)
processPheromone(chunk, getCardinalChunks(regionMap, chunk.cX, chunk.cY))
end
if (endIndex == #processQueue) then

View File

@ -112,8 +112,8 @@ end
|
4
]]--
function mapUtils.getCardinalChunksWithDirection(regionMap, chunkX, chunkY)
local neighbors = {{d=1},{d=2},{d=3},{d=4}}
function mapUtils.getCardinalChunksWithDirection(regionMap, chunkX, chunkY, neighbors)
-- local neighbors = {{d=1},{d=2},{d=3},{d=4}}
local xChunks = regionMap[chunkX]
if (xChunks ~= nil) then
neighbors[1].c = xChunks[chunkY-1]
@ -129,7 +129,7 @@ function mapUtils.getCardinalChunksWithDirection(regionMap, chunkX, chunkY)
if (xChunks ~= nil) then
neighbors[3].c = xChunks[chunkY]
end
return neighbors
-- return neighbors
end
function mapUtils.getCardinalChunks(regionMap, chunkX, chunkY)
@ -188,8 +188,8 @@ function mapUtils.canMoveChunkDirectionCardinal(direction, startChunk, endChunk)
return canMove
end
function mapUtils.positionFromDirectionAndChunkCardinal(direction, chunk)
local position = {x=0,y=0}
function mapUtils.positionFromDirectionAndChunkCardinal(direction, chunk, position)
-- local position = {x=0,y=0}
if (direction == 1) then
position.x = chunk.pX + HALF_CHUNK_SIZE
position.y = chunk.pY
@ -203,7 +203,7 @@ function mapUtils.positionFromDirectionAndChunkCardinal(direction, chunk)
position.x = chunk.pX + HALF_CHUNK_SIZE
position.y = chunk.pY + CHUNK_SIZE
end
return position
-- return position
end
function mapUtils.positionFromDirectionAndChunk(direction, chunk)

View File

@ -10,11 +10,10 @@ local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
-- module code
function neighborUtils.scoreNeighborsWithDirection(chunk, neighborDirectionChunks, validFunction, scoreFunction, squad, surface)
function neighborUtils.scoreNeighborsWithDirection(chunk, neighborDirectionChunks, validFunction, scoreFunction, squad, surface, position)
local highestChunk
local highestScore = -MAGIC_MAXIMUM_NUMBER
local highestDirection
local position = {x=0, y=0}
for x=1,#neighborDirectionChunks do
local neighborDirectionChunk = neighborDirectionChunks[x]
local neighborChunk = neighborDirectionChunk.c
@ -33,10 +32,9 @@ function neighborUtils.scoreNeighborsWithDirection(chunk, neighborDirectionChunk
return highestChunk, highestDirection
end
function neighborUtils.scoreNeighbors(chunk, neighborChunks, validFunction, scoreFunction, squad, surface)
function neighborUtils.scoreNeighbors(chunk, neighborChunks, validFunction, scoreFunction, squad, surface, position)
local highestChunk
local highestScore = -MAGIC_MAXIMUM_NUMBER
local position = {x=0, y=0}
for x=1,#neighborChunks do
local neighborChunk = neighborChunks[x]
if (neighborChunk ~= nil) and validFunction(x, chunk, neighborChunk) then

View File

@ -32,23 +32,20 @@ local getChunkByPosition = mapUtils.getChunkByPosition
-- module code
function pheromoneUtils.scents(chunk, pheromoneTotals)
function pheromoneUtils.scents(chunk)
local amount = chunk[PLAYER_DEFENSE_GENERATOR]
if (amount > 0) then
chunk[PLAYER_DEFENSE_PHEROMONE] = chunk[PLAYER_DEFENSE_PHEROMONE] + amount
-- pheromoneTotals[PLAYER_DEFENSE_PHEROMONE] = pheromoneTotals[PLAYER_DEFENSE_PHEROMONE] + amount
end
amount = chunk[PLAYER_BASE_GENERATOR]
if (amount > 0) then
chunk[PLAYER_BASE_PHEROMONE] = chunk[PLAYER_BASE_PHEROMONE] + amount
-- pheromoneTotals[PLAYER_BASE_PHEROMONE] = pheromoneTotals[PLAYER_BASE_PHEROMONE] + amount
end
amount = chunk[ENEMY_BASE_GENERATOR]
if (amount > 0) then
chunk[ENEMY_BASE_PHEROMONE] = chunk[ENEMY_BASE_PHEROMONE] + amount
-- pheromoneTotals[ENEMY_BASE_PHEROMONE] = pheromoneTotals[ENEMY_BASE_PHEROMONE] + amount
end
end
@ -56,11 +53,11 @@ function pheromoneUtils.deathScent(regionMap, position, pheromoneTotals)
local chunk = getChunkByPosition(regionMap, position.x, position.y)
if (chunk ~= nil) then
chunk[DEATH_PHEROMONE] = chunk[DEATH_PHEROMONE] + DEATH_PHEROMONE_GENERATOR_AMOUNT
-- pheromoneTotals[DEATH_PHEROMONE] = pheromoneTotals[DEATH_PHEROMONE] + DEATH_PHEROMONE_GENERATOR_AMOUNT
pheromoneTotals[DEATH_PHEROMONE] = pheromoneTotals[DEATH_PHEROMONE] + DEATH_PHEROMONE_GENERATOR_AMOUNT
end
end
function pheromoneUtils.playerScent(regionMap, players, pheromoneTotals)
function pheromoneUtils.playerScent(regionMap, players)
for i=1,#players do
local player = players[i]
if (player ~= nil) and player.connected and (player.character ~= nil) and player.character.valid and (player.character.surface.index == 1) then
@ -68,34 +65,43 @@ function pheromoneUtils.playerScent(regionMap, players, pheromoneTotals)
local playerChunk = getChunkByPosition(regionMap, playerPosition.x, playerPosition.y)
if (playerChunk ~= nil) then
playerChunk[PLAYER_PHEROMONE] = playerChunk[PLAYER_PHEROMONE] + PLAYER_PHEROMONE_GENERATOR_AMOUNT
-- pheromoneTotals[PLAYER_PHEROMONE] = pheromoneTotals[PLAYER_PHEROMONE] + PLAYER_PHEROMONE_GENERATOR_AMOUNT
end
end
end
end
function pheromoneUtils.processPheromone(chunk, neighbors, pheromoneTotals)
local diffusionAmount
local persistence
for x=1,6 do -- pheromone level indexes on chunks are 1 - 6
if (x == DEATH_PHEROMONE) then
diffusionAmount = DEATH_PHEROMONE_DIFFUSION_AMOUNT
persistence = DEATH_PHEROMONE_PERSISTANCE
else
diffusionAmount = STANDARD_PHERONOME_DIFFUSION_AMOUNT
persistence = STANDARD_PHEROMONE_PERSISTANCE
function pheromoneUtils.processPheromone(chunk, neighbors)
-- pheromone level indexes on chunks are 1 - 6
-- unrolled loop one level
local diffusionAmount = DEATH_PHEROMONE_DIFFUSION_AMOUNT
local persistence = DEATH_PHEROMONE_PERSISTANCE
local totalDiffused = 0
local chunkValue = chunk[DEATH_PHEROMONE] * persistence
local diffusedAmount = chunkValue * diffusionAmount
for i=1,#neighbors do
local neighborChunk = neighbors[i]
if (neighborChunk ~= nil) then
totalDiffused = totalDiffused + diffusedAmount
neighborChunk[DEATH_PHEROMONE] = neighborChunk[DEATH_PHEROMONE] + diffusedAmount
end
end
chunk[DEATH_PHEROMONE] = (chunkValue - totalDiffused)
diffusionAmount = STANDARD_PHERONOME_DIFFUSION_AMOUNT
persistence = STANDARD_PHEROMONE_PERSISTANCE
for x=2,6 do
local totalDiffused = 0
local chunkValue = chunk[x] * persistence
local diffusedAmount = chunkValue * diffusionAmount
for i=1,#neighbors do
local neighborChunk = neighbors[i]
if (neighborChunk ~= nil) then
local diffusedAmount = chunkValue * diffusionAmount
totalDiffused = totalDiffused + diffusedAmount
neighborChunk[x] = neighborChunk[x] + diffusedAmount
end
end
-- pheromoneTotals[x] = pheromoneTotals[x] + (chunkValue - chunk[x])
chunk[x] = (chunkValue - totalDiffused)
end
end

View File

@ -46,15 +46,14 @@ function unitGroupUtils.createSquad(position, surface, natives)
return squad
end
function unitGroupUtils.membersToSquad(squad, members, overwriteGroup, distraction)
function unitGroupUtils.membersToSquad(squad, members, overwriteGroup, temps)
if (members ~= nil) then
local group = squad.group
local groupCmd = temps[constants.GROUP_COMMAND]
groupCmd.group = squad.group
for i=1,#members do
local member = members[i]
if member.valid and (overwriteGroup or (not overwriteGroup and (member.unit_group == nil))) then
member.set_command({ type = defines.command.group,
group = group,
distraction = distraction })
member.set_command(groupCmd)
end
end
end
@ -108,7 +107,7 @@ function unitGroupUtils.lookupSquadMovementPenalty(squad, chunkX, chunkY)
return 0
end
function unitGroupUtils.regroupSquads(natives)
function unitGroupUtils.regroupSquads(natives, temps)
local squads = natives.squads
for i=1,#squads do
local squad = squads[i]
@ -118,7 +117,7 @@ function unitGroupUtils.regroupSquads(natives)
local mergeSquad = squads[x]
local mergeGroup = mergeSquad.group
if mergeGroup.valid and (mergeSquad.status == squad.status) and (euclideanDistanceNamed(squadPosition, mergeGroup.position) < 16) then
unitGroupUtils.membersToSquad(squad, mergeGroup.members, true)
unitGroupUtils.membersToSquad(squad, mergeGroup.members, true, temps)
mergeGroup.destroy()
end
end

27
setupUtils.lua Executable file
View File

@ -0,0 +1,27 @@
local setupUtils = {}
-- imports
local constants = require("libs/Constants")
-- module code
function setupUtils.initTemps(temps)
-- minimize garbage by preallocating all tables needed for operation
if (temps[constants.ATTACK_COMMAND] == nil) then
local attackPosition = {x=0, y=0}
temps[constants.ATTACK_POSITION] = attackPosition
temps[constants.ATTACK_COMMAND] = { type = defines.command.attack_area,
destination = attackPosition,
radius = 32,
distraction = defines.distraction.by_anything }
temps[constants.ATTACK_DIRECTION] = {{d=1}, {d=2}, {d=3}, {d=4}}
temps[constants.GROUP_COMMAND] = { type = defines.command.group,
group = 1,
distraction = defines.distraction.none }
end
end
return setupUtils