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

potential desync fix and warding pheromone on attack path

This commit is contained in:
Aaron Veden
2021-12-05 10:19:04 -08:00
parent c7850c3649
commit e814a9c648
15 changed files with 469 additions and 524 deletions

View File

@@ -3,11 +3,8 @@ local upgrade = {}
-- imports
local constants = require("libs/Constants")
local mathUtils = require("libs/MathUtils")
local chunkPropertyUtils = require("libs/ChunkPropertyUtils")
local mapUtils = require("libs/MapUtils")
local baseUtils = require("libs/BaseUtils")
local chunkProcessor = require("libs/ChunkProcessor")
local mapUtils = require("libs/MapUtils")
-- constants
@@ -31,37 +28,11 @@ local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE
-- imported functions
local queueGeneratedChunk = mapUtils.queueGeneratedChunk
local processPendingChunks = chunkProcessor.processPendingChunks
local queueGeneratedChunk = mapUtils.queueGeneratedChunk
local getEnemyStructureCount = chunkPropertyUtils.getEnemyStructureCount
local getChunkBase = chunkPropertyUtils.getChunkBase
local removeChunkBase = chunkPropertyUtils.removeChunkBase
local findNearbyBase = baseUtils.findNearbyBase
local createBase = baseUtils.createBase
local setChunkBase = chunkPropertyUtils.setChunkBase
local euclideanDistancePoints = mathUtils.euclideanDistancePoints
local mAbs = math.abs
local tSort = table.sort
-- module code
local function sorter(a, b)
if (a.dOrigin == b.dOrigin) then
if (a.x == b.x) then
return (mAbs(a.y) < mAbs(b.y))
else
return (mAbs(a.x) < mAbs(b.x))
end
end
return (a.dOrigin < b.dOrigin)
end
local function addCommandSet(queriesAndCommands)
-- preallocating memory to be used in code, making it fast by reducing garbage generated.
queriesAndCommands.neighbors = {
@@ -445,105 +416,165 @@ function upgrade.attempt(universe)
universe.maxPoints = 0
end
if global.version < 122 then
global.version = 122
if global.version < 200 then
global.version = 200
addCommandSet(universe)
universe.eventId = 0
universe.randomGenerator = nil
universe.random = game.create_random_generator(settings.startup["rampant--enemySeed"].value+game.map_gen_settings.seed)
if (universe.maps) then
local tick = game.tick
for _,map in pairs(universe.maps) do
map.random = universe.random
map.pendingUpgrades = {}
map.sentAggressiveGroups = 0
map.maxAggressiveGroups = 1
local basesToRemove = {}
for i=1,#map.processQueue do
local chunk = map.processQueue[i]
chunk.dOrigin = euclideanDistancePoints(chunk.x, chunk.y, 0, 0)
if universe.NEW_ENEMIES then
local base = getChunkBase(map, chunk)
if base then
if not map.bases[base.id] then
map.bases[base.id] = base
end
if not base.damagedBy then
base.damagedBy = {}
end
if not base.deathEvents then
base.deathEvents = 0
end
if not base.chunkCount then
base.chunkCount = 0
end
if not base.mutations then
base.mutations = 0
end
if not base.alignment[1] then
basesToRemove[base.id] = true
end
end
end
end
tSort(map.processQueue, sorter)
map.pendingChunks = {}
map.chunkToNests = {}
map.chunkToNestIds = {}
map.chunkToHives = {}
map.chunkToHiveIds = {}
map.chunkToTraps = {}
map.chunkToTrapIds = {}
map.chunkToTurrets = {}
map.chunkToTurretIds = {}
map.chunkToUtilities = {}
map.chunkToUtilityIds = {}
for chunkXY in map.surface.get_chunks() do
if map.surface.is_chunk_generated(chunkXY) then
local x = chunkXY.x * 32
local y = chunkXY.y * 32
queueGeneratedChunk(universe,
{
surface = map.surface,
area = {
left_top = {
x = x,
y = y
}
}
}
)
end
end
processPendingChunks(map, tick, true)
if universe.NEW_ENEMIES then
for baseId in pairs(basesToRemove) do
map.bases[baseId] = nil
end
map.chunkToBases = {}
for i=1,#map.processQueue do
local chunk = map.processQueue[i]
if (getEnemyStructureCount(map, chunk) > 0) then
local newBase = findNearbyBase(map, chunk)
if not newBase then
createBase(map, chunk, tick)
end
setChunkBase(map, chunk, newBase)
end
end
end
for _,squad in pairs(map.groupNumberToSquad) do
squad.commandTick = tick
end
end
universe.random = game.create_random_generator(settings.startup["rampant--enemySeed"].value+game.default_map_gen_settings.seed)
game.forces.enemy.kill_all_units()
universe.maps = {}
for _,surface in pairs(game.surfaces) do
upgrade.prepMap(universe, surface)
end
universe.activeMap = nil
universe.mapIterator = nil
game.print("Rampant - Version 1.2.0")
game.print("Rampant - Version 2.0.0")
end
return (starting ~= global.version) and global.version
end
function upgrade.prepMap(universe, surface)
game.print("Rampant - Indexing surface:" .. tostring(surface.index) .. ", please wait.")
local surfaceIndex = surface.index
if not universe.maps then
universe.maps = {}
end
local map = {}
universe.maps[surfaceIndex] = map
map.eventId = 1
map.chunkId = 1
map.maxAggressiveGroups = 1
map.sentAggressiveGroups = 0
map.processedChunks = 0
map.processQueue = {}
map.processIndex = 1
map.cleanupIndex = 1
map.scanPlayerIndex = 1
map.scanResourceIndex = 1
map.scanEnemyIndex = 1
map.processStaticIndex = 1
map.outgoingScanWave = true
map.outgoingStaticScanWave = true
map.pendingUpgrades = {}
map.pendingChunks = {}
map.chunkToBase = {}
map.chunkToNests = {}
map.chunkToTurrets = {}
map.chunkToTraps = {}
map.chunkToUtilities = {}
map.chunkToHives = {}
map.chunkToNestIds = {}
map.chunkToHiveIds = {}
map.chunkToTrapIds = {}
map.chunkToTurretIds = {}
map.chunkToUtilityIds = {}
map.chunkToPlayerBase = {}
map.chunkToResource = {}
map.chunkToPlayerCount = {}
map.playerToChunk = {}
map.pendingChunks = {}
map.chunkToPassScan = {}
map.chunkToSquad = {}
map.chunkToRetreats = {}
map.chunkToRallys = {}
map.chunkIdToChunk = {}
map.chunkToPassable = {}
map.chunkToPathRating = {}
map.chunkToDeathGenerator = {}
map.chunkToDrained = {}
map.chunkToVictory = {}
map.chunkToActiveNest = {}
map.chunkToActiveRaidNest = {}
map.chunkToPassScanIterator = nil
map.pendingUpgradeIterator = nil
map.squadIterator = nil
map.regroupIterator = nil
map.deployVengenceIterator = nil
map.recycleBaseIterator = nil
map.processActiveSpawnerIterator = nil
map.processActiveRaidSpawnerIterator = nil
map.processMigrationIterator = nil
map.processNestIterator = nil
map.victoryScentIterator = nil
map.chunkScanCounts = {}
map.chunkRemovals = {}
map.processActiveNest = {}
map.tickActiveNest = {}
map.emptySquadsOnChunk = {}
map.surface = surface
map.universe = universe
map.vengenceQueue = {}
map.bases = {}
map.baseIndex = 1
map.baseIncrement = 0
map.points = 0
map.state = constants.AI_STATE_AGGRESSIVE
map.baseId = 0
map.squads = nil
map.pendingAttack = nil
map.building = nil
map.evolutionLevel = game.forces.enemy.evolution_factor
map.canAttackTick = 0
map.drainPylons = {}
map.groupNumberToSquad = {}
map.activeRaidNests = 0
map.activeNests = 0
map.destroyPlayerBuildings = 0
map.lostEnemyUnits = 0
map.lostEnemyBuilding = 0
map.rocketLaunched = 0
map.builtEnemyBuilding = 0
map.ionCannonBlasts = 0
map.artilleryBlasts = 0
map.temperament = 0.5
map.temperamentScore = 0
map.stateTick = 0
map.random = universe.random
-- queue all current chunks that wont be generated during play
local tick = game.tick
for chunk in surface.get_chunks() do
if surface.is_chunk_generated(chunk) then
queueGeneratedChunk(universe,
{
surface = surface,
tick = tick,
area = {
left_top = {
x = chunk.x * 32,
y = chunk.y * 32
}
}
}
)
end
end
processPendingChunks(map, tick, true)
end
function upgrade.compareTable(entities, option, new)
local changed = false
if (entities[option] ~= new) then

View File

@@ -1,5 +1,5 @@
---------------------------------------------------------------------------------------------------
Version: 1.2.0
Version: 2.0.0
Date: 23. 11. 2021
Contributions:
- Astorin has provide an updated RU locale up through Rampant 1.1.1
@@ -42,6 +42,8 @@ Date: 23. 11. 2021
- Fixed regional bases would not be corrected distributed or cleaned up on spawners
- Fixed chunks that became impassable would not return an impassable chunk flag when pass scanned
- Fixed kastorio creep code be spawned when the building failed to upgrade
- Potential desync fix in relation to reference comparison and deserialization
- Fixed squad attack move would not properly place warding pheromone on taken path
Framework:
- Fixed Rampant in-memory map visualization tool for debugging
- Added debug mod settings for showing enemy structures being upgraded in place

View File

@@ -41,6 +41,8 @@ local ENERGY_THIEF_LOOKUP = constants.ENERGY_THIEF_LOOKUP
-- imported functions
local prepMap = upgrade.prepMap
local registerEnemyBaseStructure = chunkUtils.registerEnemyBaseStructure
local queueGeneratedChunk = mapUtils.queueGeneratedChunk
@@ -260,135 +262,6 @@ local function onModSettingsChange(event)
return true
end
local function prepMap(surface)
surface.print("Rampant - Indexing surface:" .. tostring(surface.index) .. ", please wait.")
local surfaceIndex = surface.index
if not universe.maps then
universe.maps = {}
end
local map = universe.maps[surfaceIndex]
if not map then
map = {}
universe.maps[surfaceIndex] = map
end
map.maxAggressiveGroups = 1
map.sentAggressiveGroups = 0
map.processedChunks = 0
map.processQueue = {}
map.processIndex = 1
map.cleanupIndex = 1
map.scanPlayerIndex = 1
map.scanResourceIndex = 1
map.scanEnemyIndex = 1
map.processStaticIndex = 1
map.outgoingScanWave = true
map.outgoingStaticScanWave = true
map.pendingUpgrades = {}
map.pendingChunks = {}
map.chunkToBase = {}
map.chunkToNests = {}
map.chunkToTurrets = {}
map.chunkToTraps = {}
map.chunkToUtilities = {}
map.chunkToHives = {}
map.chunkToNestIds = {}
map.chunkToHiveIds = {}
map.chunkToTrapIds = {}
map.chunkToTurretIds = {}
map.chunkToUtilityIds = {}
map.chunkToPlayerBase = {}
map.chunkToResource = {}
map.chunkToPlayerCount = {}
map.playerToChunk = {}
map.pendingChunks = {}
map.chunkToPassScan = {}
map.chunkToSquad = {}
map.chunkToRetreats = {}
map.chunkToRallys = {}
map.chunkToPassable = {}
map.chunkToPathRating = {}
map.chunkToDeathGenerator = {}
map.chunkToDrained = {}
map.chunkToVictory = {}
map.chunkToActiveNest = {}
map.chunkToActiveRaidNest = {}
map.pendingUpgradeIterator = nil
map.squadIterator = nil
map.regroupIterator = nil
map.deployVengenceIterator = nil
map.recycleBaseIterator = nil
map.processActiveSpawnerIterator = nil
map.processActiveRaidSpawnerIterator = nil
map.processMigrationIterator = nil
map.processNestIterator = nil
map.victoryScentIterator = nil
map.chunkScanCounts = {}
map.chunkRemovals = {}
map.processActiveNest = {}
map.tickActiveNest = {}
map.emptySquadsOnChunk = {}
map.surface = surface
map.universe = universe
map.vengenceQueue = {}
map.bases = {}
map.baseIndex = 1
map.baseIncrement = 0
map.points = 0
map.state = constants.AI_STATE_AGGRESSIVE
map.baseId = 0
map.squads = nil
map.pendingAttack = nil
map.building = nil
map.evolutionLevel = game.forces.enemy.evolution_factor
map.canAttackTick = 0
map.drainPylons = {}
map.groupNumberToSquad = {}
map.activeRaidNests = 0
map.activeNests = 0
map.destroyPlayerBuildings = 0
map.lostEnemyUnits = 0
map.lostEnemyBuilding = 0
map.rocketLaunched = 0
map.builtEnemyBuilding = 0
map.ionCannonBlasts = 0
map.artilleryBlasts = 0
map.temperament = 0.5
map.temperamentScore = 0
map.stateTick = 0
map.random = universe.random
-- queue all current chunks that wont be generated during play
local tick = game.tick
for chunk in surface.get_chunks() do
if surface.is_chunk_generated(chunk) then
onChunkGenerated({ surface = surface,
tick = tick,
area = { left_top = { x = chunk.x * 32,
y = chunk.y * 32}}})
end
end
processPendingChunks(map, tick, true)
end
local function onConfigChanged()
local version = upgrade.attempt(universe)
if version then
@@ -426,7 +299,7 @@ local function onConfigChanged()
universe.maps = {}
end
if not universe.maps[surface.index] then
prepMap(surface)
prepMap(universe, surface)
end
end
end
@@ -520,13 +393,13 @@ local function onDeath(event)
if pair then
local target = pair[1]
local pole = pair[2]
if target == entity then
if target.unit_number == entityUnitNumber then
map.drainPylons[entityUnitNumber] = nil
if pole.valid then
map.drainPylons[pole.unit_number] = nil
pole.die()
end
elseif (pole == entity) then
elseif (pole.unit_number == entityUnitNumber) then
map.drainPylons[entityUnitNumber] = nil
if target.valid then
map.drainPylons[target.unit_number] = nil
@@ -576,11 +449,12 @@ local function onDeath(event)
local creditNatives = false
if (event.force ~= nil) and (event.force.name == "enemy") then
creditNatives = true
local drained
if (chunk ~= -1) then
victoryScent(map, chunk, entityType)
drained = (entityType == "electric-turret") and map.chunkToDrained[chunk.id]
end
local drained = (entityType == "electric-turret") and map.chunkToDrained[chunk]
if cause or (drained and (drained - tick) > 0) then
if ((cause and ENERGY_THIEF_LOOKUP[cause.name]) or (not cause)) then
local conversion = ENERGY_THIEF_CONVERSION_TABLE[entityType]
@@ -698,7 +572,7 @@ local function onSurfaceTileChange(event)
local chunk = getChunkByPosition(map, position)
if (chunk ~= -1) then
map.chunkToPassScan[chunk] = true
map.chunkToPassScan[chunk.id] = true
else
local x,y = positionToChunkXY(position)
local addMe = true
@@ -727,7 +601,7 @@ local function onSurfaceTileChange(event)
local chunk = getChunkByPosition(map, position)
if (chunk ~= -1) then
map.chunkToPassScan[chunk] = true
map.chunkToPassScan[chunk.id] = true
else
local x,y = positionToChunkXY(position)
local addMe = true
@@ -804,7 +678,7 @@ local function onTriggerEntityCreated(event)
local map = universe.maps[event.surface_index]
local chunk = getChunkByPosition(map, entity.position)
if (chunk ~= -1) then
map.chunkToDrained[chunk] = event.tick + 60
map.chunkToDrained[chunk.id] = event.tick + 60
end
end
end
@@ -1003,7 +877,7 @@ local function onForceMerged(event)
end
local function onSurfaceCreated(event)
prepMap(game.surfaces[event.surface_index])
prepMap(universe, game.surfaces[event.surface_index])
end
local function onSurfaceDeleted(event)

View File

@@ -1,7 +1,7 @@
{
"name" : "Rampant",
"factorio_version" : "1.1",
"version" : "1.2.0",
"version" : "2.0.0",
"title" : "Rampant",
"author" : "Veden",
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",

View File

@@ -175,12 +175,12 @@ function aiAttackWave.rallyUnits(chunk, map, tick)
if (x ~= cX) and (y ~= cY) then
local rallyChunk = getChunkByXY(map, x, y)
if (rallyChunk ~= -1) and (getNestCount(map, rallyChunk) > 0) then
local count = vengenceQueue[rallyChunk]
local count = vengenceQueue[rallyChunk.id]
if not count then
count = 0
vengenceQueue[rallyChunk] = count
vengenceQueue[rallyChunk.id] = count
end
vengenceQueue[rallyChunk] = count + 1
vengenceQueue[rallyChunk.id] = count + 1
end
end
end

View File

@@ -407,7 +407,7 @@ function aiPlanning.temperamentPlanner(map)
map.temperament = ((map.temperamentScore + 10000) * 0.00005)
if universe.debugTemperament then
if game.tick % 240 == 0 then
if game.tick % 243 == 0 then
game.print("Rampant Stats:")
game.print("aN:" .. map.activeNests .. ", aRN:" .. map.activeRaidNests .. ", dPB:" .. map.destroyPlayerBuildings ..
", lEU:" .. map.lostEnemyUnits .. ", lEB:" .. map.lostEnemyBuilding .. ", rL:" .. map.rocketLaunched .. ", bEB:" .. map.builtEnemyBuilding ..

View File

@@ -284,9 +284,10 @@ function baseUtils.upgradeEntity(entity, base, map, disPos, evolve, register)
["name"] = spawnerName,
["position"] = disPos,
["register"] = register,
["base"] = base
["base"] = base,
["entity"] = entity
}
map.pendingUpgrades[entity] = entityData
map.pendingUpgrades[entity.unit_number] = entityData
return spawnerName
end
return nil
@@ -299,7 +300,7 @@ local function pickMutationFromDamageType(map, damageType, roll, base)
local mutation
if (damageFactions and (#damageFactions > 0)) then
mutation = damageFactions[math.random(#damageFactions)]
mutation = damageFactions[mRandom(#damageFactions)]
if baseAlignment[2] then
if (roll < 0.05) then
baseAlignment[2] = nil

View File

@@ -49,7 +49,7 @@ end
local function removeProcessQueueChunk(processQueue, chunk)
local insertionPoint = findInsertionPoint(processQueue, chunk)
for i=insertionPoint,1,-1 do
if (processQueue[i] == chunk) then
if (processQueue[i].id == chunk.id) then
tRemove(processQueue, i)
end
end
@@ -64,17 +64,20 @@ function chunkProcessor.processPendingChunks(map, tick, flush)
local topOffset = area[1]
local bottomOffset = area[2]
local event = map.chunkProcessorIterator
if not event then
event = next(pendingChunks, nil)
local eventId = map.chunkProcessorIterator
local event
if not eventId then
eventId, event = next(pendingChunks, nil)
else
event = pendingChunks[eventId]
end
local endCount = 1
if flush then
endCount = table_size(pendingChunks)
event = next(pendingChunks, nil)
eventId, event = next(pendingChunks, nil)
end
for _=1,endCount do
if not event then
if not eventId then
map.chunkProcessorIterator = nil
if (table_size(pendingChunks) == 0) then
-- this is needed as the next command remembers the max length a table has been
@@ -83,7 +86,7 @@ function chunkProcessor.processPendingChunks(map, tick, flush)
break
else
if not flush and (event.tick > tick) then
map.chunkProcessorIterator = event
map.chunkProcessorIterator = eventId
return
end
local topLeft = event.area.left_top
@@ -100,48 +103,52 @@ function chunkProcessor.processPendingChunks(map, tick, flush)
end
if map[x][y] then
local chunk = initialScan(map[x][y], map, tick)
local oldChunk = map[x][y]
local chunk = initialScan(oldChunk, map, tick)
if (chunk == -1) then
removeProcessQueueChunk(processQueue, map[x][y])
removeProcessQueueChunk(processQueue, oldChunk)
map.chunkIdToChunk[oldChunk.id] = nil
map[x][y] = nil
end
else
local chunk = createChunk(x, y)
map[x][y] = chunk
chunk = initialScan(chunk, map, tick)
local initialChunk = createChunk(map, x, y)
map[x][y] = initialChunk
map.chunkIdToChunk[initialChunk.id] = initialChunk
local chunk = initialScan(initialChunk, map, tick)
if (chunk ~= -1) then
map[x][y] = chunk
tInsert(
processQueue,
findInsertionPoint(processQueue, chunk),
chunk
)
else
map.chunkIdToChunk[initialChunk.id] = nil
map[x][y] = nil
end
end
local newEvent = next(pendingChunks, event)
pendingChunks[event] = nil
local newEventId, newEvent = next(pendingChunks, eventId)
pendingChunks[eventId] = nil
eventId = newEventId
event = newEvent
end
end
map.chunkProcessorIterator = event
map.chunkProcessorIterator = eventId
end
function chunkProcessor.processPendingUpgrades(map, tick)
local pendingUpgrades = map.pendingUpgrades
local entity = map.pendingUpgradeIterator
local entityId = map.pendingUpgradeIterator
local entityData
if not entity then
entity, entityData = next(pendingUpgrades, nil)
if not entityId then
entityId, entityData = next(map.pendingUpgrades, nil)
else
entityData = pendingUpgrades[entity]
entityData = map.pendingUpgrades[entityId]
end
if entity then
if entityId then
local entity = entityData.entity
if entity.valid then
map.pendingUpgradeIterator = next(pendingUpgrades, entity)
pendingUpgrades[entity] = nil
map.pendingUpgradeIterator = next(map.pendingUpgrades, entityId)
map.pendingUpgrades[entityId] = nil
local universe = map.universe
local query = universe.upgradeEntityQuery
query.position = entityData.position or entity.position
@@ -157,47 +164,46 @@ function chunkProcessor.processPendingUpgrades(map, tick)
end
end
else
map.pendingUpgradeIterator = next(pendingUpgrades, entity)
pendingUpgrades[entity] = nil
map.pendingUpgradeIterator = next(map.pendingUpgrades, entityId)
map.pendingUpgrades[entityId] = nil
end
end
end
function chunkProcessor.processScanChunks(map)
local area = map.universe.area
local topOffset = area[1]
local bottomOffset = area[2]
local removals = map.chunkRemovals
local chunkCount = 0
local chunkToPassScan = map.chunkToPassScan
for preScanChunk in pairs(chunkToPassScan) do
local x = preScanChunk.x
local y = preScanChunk.y
topOffset[1] = x
topOffset[2] = y
bottomOffset[1] = x + CHUNK_SIZE
bottomOffset[2] = y + CHUNK_SIZE
if (chunkPassScan(preScanChunk, map) == -1) then
map[x][y] = nil
chunkCount = chunkCount + 1
removals[chunkCount] = preScanChunk
end
chunkToPassScan[preScanChunk] = nil
local chunkId = map.chunkToPassScanIterator
local chunk
if not chunkId then
chunkId, chunk = next(map.chunkToPassScan, nil)
else
chunk = map.chunkToPassScan[chunkId]
end
if (chunkCount > 0) then
local processQueue = map.processQueue
for ri=chunkCount,1,-1 do
removeProcessQueueChunk(processQueue, removals[ri])
if not chunkId then
map.chunkToPassScanIterator = nil
if (table_size(map.chunkToPassScan) == 0) then
-- this is needed as the next command remembers the max length a table has been
map.chunkToPassScan = {}
end
else
map.chunkToPassScanIterator = next(map.chunkToPassScan, chunkId)
map.chunkToPassScan[chunkId] = nil
topOffset[1] = chunk.x
topOffset[2] = chunk.y
bottomOffset[1] = chunk.x + CHUNK_SIZE
bottomOffset[2] = chunk.y + CHUNK_SIZE
if (chunkPassScan(chunk, map) == -1) then
removeProcessQueueChunk(map.processQueue, chunk)
map[chunk.x][chunk.y] = nil
map.chunkIdToChunk[chunk.id] = nil
end
end
end

View File

@@ -22,130 +22,130 @@ local mMin = math.min
-- module code
function chunkPropertyUtils.getNestCount(map, chunk)
return map.chunkToNests[chunk] or 0
return map.chunkToNests[chunk.id] or 0
end
function chunkPropertyUtils.getTurretCount(map, chunk)
return map.chunkToTurrets[chunk] or 0
return map.chunkToTurrets[chunk.id] or 0
end
function chunkPropertyUtils.getTrapCount(map, chunk)
return map.chunkToTraps[chunk] or 0
return map.chunkToTraps[chunk.id] or 0
end
function chunkPropertyUtils.getUtilityCount(map, chunk)
return map.chunkToUtilities[chunk] or 0
return map.chunkToUtilities[chunk.id] or 0
end
function chunkPropertyUtils.getHiveCount(map, chunk)
return map.chunkToHives[chunk] or 0
return map.chunkToHives[chunk.id] or 0
end
function chunkPropertyUtils.addTurretCount(map, chunk, unitNumber)
if not map.chunkToTurretIds[chunk] then
map.chunkToTurretIds[chunk] = {}
if not map.chunkToTurretIds[chunk.id] then
map.chunkToTurretIds[chunk.id] = {}
end
if not map.chunkToTurretIds[chunk][unitNumber] then
map.chunkToTurretIds[chunk][unitNumber] = true
map.chunkToTurrets[chunk] = (map.chunkToTurrets[chunk] or 0) + 1
if not map.chunkToTurretIds[chunk.id][unitNumber] then
map.chunkToTurretIds[chunk.id][unitNumber] = true
map.chunkToTurrets[chunk.id] = (map.chunkToTurrets[chunk.id] or 0) + 1
end
end
function chunkPropertyUtils.removeTurretCount(map, chunk, unitNumber)
if map.chunkToTurretIds[chunk] and map.chunkToTurretIds[chunk][unitNumber] then
map.chunkToTurretIds[chunk][unitNumber] = nil
map.chunkToTurrets[chunk] = map.chunkToTurrets[chunk] - 1
if map.chunkToTurrets[chunk] == 0 then
map.chunkToTurretIds[chunk] = nil
map.chunkToTurrets[chunk] = nil
if map.chunkToTurretIds[chunk.id] and map.chunkToTurretIds[chunk.id][unitNumber] then
map.chunkToTurretIds[chunk.id][unitNumber] = nil
map.chunkToTurrets[chunk.id] = map.chunkToTurrets[chunk.id] - 1
if map.chunkToTurrets[chunk.id] == 0 then
map.chunkToTurretIds[chunk.id] = nil
map.chunkToTurrets[chunk.id] = nil
end
end
end
function chunkPropertyUtils.addTrapCount(map, chunk, unitNumber)
if not map.chunkToTrapIds[chunk] then
map.chunkToTrapIds[chunk] = {}
if not map.chunkToTrapIds[chunk.id] then
map.chunkToTrapIds[chunk.id] = {}
end
if not map.chunkToTrapIds[chunk][unitNumber] then
map.chunkToTrapIds[chunk][unitNumber] = true
map.chunkToTraps[chunk] = (map.chunkToTraps[chunk] or 0) + 1
if not map.chunkToTrapIds[chunk.id][unitNumber] then
map.chunkToTrapIds[chunk.id][unitNumber] = true
map.chunkToTraps[chunk.id] = (map.chunkToTraps[chunk.id] or 0) + 1
end
end
function chunkPropertyUtils.removeTrapCount(map, chunk, unitNumber)
if map.chunkToTrapIds[chunk] and map.chunkToTrapIds[chunk][unitNumber] then
map.chunkToTrapIds[chunk][unitNumber] = nil
map.chunkToTraps[chunk] = map.chunkToTraps[chunk] - 1
if map.chunkToTraps[chunk] == 0 then
map.chunkToTrapIds[chunk] = nil
map.chunkToTraps[chunk] = nil
if map.chunkToTrapIds[chunk.id] and map.chunkToTrapIds[chunk.id][unitNumber] then
map.chunkToTrapIds[chunk.id][unitNumber] = nil
map.chunkToTraps[chunk.id] = map.chunkToTraps[chunk.id] - 1
if map.chunkToTraps[chunk.id] == 0 then
map.chunkToTrapIds[chunk.id] = nil
map.chunkToTraps[chunk.id] = nil
end
end
end
function chunkPropertyUtils.addUtilitiesCount(map, chunk, unitNumber)
if not map.chunkToUtilityIds[chunk] then
map.chunkToUtilityIds[chunk] = {}
if not map.chunkToUtilityIds[chunk.id] then
map.chunkToUtilityIds[chunk.id] = {}
end
if not map.chunkToUtilityIds[chunk][unitNumber] then
map.chunkToUtilityIds[chunk][unitNumber] = true
map.chunkToUtilities[chunk] = (map.chunkToUtilities[chunk] or 0) + 1
if not map.chunkToUtilityIds[chunk.id][unitNumber] then
map.chunkToUtilityIds[chunk.id][unitNumber] = true
map.chunkToUtilities[chunk.id] = (map.chunkToUtilities[chunk.id] or 0) + 1
end
end
function chunkPropertyUtils.removeUtilitiesCount(map, chunk, unitNumber)
if map.chunkToUtilityIds[chunk] and map.chunkToUtilityIds[chunk][unitNumber] then
map.chunkToUtilityIds[chunk][unitNumber] = nil
map.chunkToUtilities[chunk] = map.chunkToUtilities[chunk] - 1
if map.chunkToUtilities[chunk] == 0 then
map.chunkToUtilityIds[chunk] = nil
map.chunkToUtilities[chunk] = nil
if map.chunkToUtilityIds[chunk.id] and map.chunkToUtilityIds[chunk.id][unitNumber] then
map.chunkToUtilityIds[chunk.id][unitNumber] = nil
map.chunkToUtilities[chunk.id] = map.chunkToUtilities[chunk.id] - 1
if map.chunkToUtilities[chunk.id] == 0 then
map.chunkToUtilityIds[chunk.id] = nil
map.chunkToUtilities[chunk.id] = nil
end
end
end
function chunkPropertyUtils.addHiveCount(map, chunk, unitNumber)
if not map.chunkToHiveIds[chunk] then
map.chunkToHiveIds[chunk] = {}
if not map.chunkToHiveIds[chunk.id] then
map.chunkToHiveIds[chunk.id] = {}
end
if not map.chunkToHiveIds[chunk][unitNumber] then
map.chunkToHiveIds[chunk][unitNumber] = true
map.chunkToHives[chunk] = (map.chunkToHives[chunk] or 0) + 1
if not map.chunkToHiveIds[chunk.id][unitNumber] then
map.chunkToHiveIds[chunk.id][unitNumber] = true
map.chunkToHives[chunk.id] = (map.chunkToHives[chunk.id] or 0) + 1
end
end
function chunkPropertyUtils.removeHiveCount(map, chunk, unitNumber)
if map.chunkToHiveIds[chunk] and map.chunkToHiveIds[chunk][unitNumber] then
map.chunkToHiveIds[chunk][unitNumber] = nil
map.chunkToHives[chunk] = map.chunkToHives[chunk] - 1
if map.chunkToHives[chunk] == 0 then
map.chunkToHiveIds[chunk] = nil
map.chunkToHives[chunk] = nil
if map.chunkToHiveIds[chunk.id] and map.chunkToHiveIds[chunk.id][unitNumber] then
map.chunkToHiveIds[chunk.id][unitNumber] = nil
map.chunkToHives[chunk.id] = map.chunkToHives[chunk.id] - 1
if map.chunkToHives[chunk.id] == 0 then
map.chunkToHiveIds[chunk.id] = nil
map.chunkToHives[chunk.id] = nil
end
end
end
function chunkPropertyUtils.addNestCount(map, chunk, unitNumber)
if not map.chunkToNestIds[chunk] then
map.chunkToNestIds[chunk] = {}
if not map.chunkToNestIds[chunk.id] then
map.chunkToNestIds[chunk.id] = {}
end
if not map.chunkToNestIds[chunk][unitNumber] then
map.chunkToNestIds[chunk][unitNumber] = true
map.chunkToNests[chunk] = (map.chunkToNests[chunk] or 0) + 1
if not map.chunkToNestIds[chunk.id][unitNumber] then
map.chunkToNestIds[chunk.id][unitNumber] = true
map.chunkToNests[chunk.id] = (map.chunkToNests[chunk.id] or 0) + 1
end
end
function chunkPropertyUtils.removeNestCount(map, chunk, unitNumber)
if map.chunkToNestIds[chunk] and map.chunkToNestIds[chunk][unitNumber] then
map.chunkToNestIds[chunk][unitNumber] = nil
map.chunkToNests[chunk] = map.chunkToNests[chunk] - 1
if map.chunkToNests[chunk] == 0 then
map.chunkToNestIds[chunk] = nil
map.chunkToNests[chunk] = nil
if (map.processMigrationIterator == chunk) then
if map.chunkToNestIds[chunk.id] and map.chunkToNestIds[chunk.id][unitNumber] then
map.chunkToNestIds[chunk.id][unitNumber] = nil
map.chunkToNests[chunk.id] = map.chunkToNests[chunk.id] - 1
if map.chunkToNests[chunk.id] == 0 then
map.chunkToNestIds[chunk.id] = nil
map.chunkToNests[chunk.id] = nil
if (map.processMigrationIterator == chunk.id) then
map.processMigrationIterator = nil
end
if (map.processNestIterator == chunk) then
if (map.processNestIterator == chunk.id) then
map.processNestIterator = nil
end
end
@@ -153,164 +153,164 @@ function chunkPropertyUtils.removeNestCount(map, chunk, unitNumber)
end
function chunkPropertyUtils.getNestCount(map, chunk)
return map.chunkToNests[chunk] or 0
return map.chunkToNests[chunk.id] or 0
end
function chunkPropertyUtils.getChunkBase(map, chunk)
return map.chunkToBase[chunk]
return map.chunkToBase[chunk.id]
end
function chunkPropertyUtils.removeChunkBase(map, chunk, base)
if map.chunkToBase[chunk] then
if map.chunkToBase[chunk.id] then
base.chunkCount = base.chunkCount - 1
map.chunkToBase[chunk] = nil
map.chunkToBase[chunk.id] = nil
end
end
function chunkPropertyUtils.setChunkBase(map, chunk, base)
if not map.chunkToBase[chunk] then
if not map.chunkToBase[chunk.id] then
base.chunkCount = base.chunkCount + 1
map.chunkToBase[chunk] = base
map.chunkToBase[chunk.id] = base
end
end
function chunkPropertyUtils.getEnemyStructureCount(map, chunk)
return (map.chunkToNests[chunk] or 0) + (map.chunkToTurrets[chunk] or 0) + (map.chunkToTraps[chunk] or 0) +
(map.chunkToUtilities[chunk] or 0) + (map.chunkToHives[chunk] or 0)
return (map.chunkToNests[chunk.id] or 0) + (map.chunkToTurrets[chunk.id] or 0) + (map.chunkToTraps[chunk.id] or 0) +
(map.chunkToUtilities[chunk.id] or 0) + (map.chunkToHives[chunk.id] or 0)
end
function chunkPropertyUtils.getRetreatTick(map, chunk)
return map.chunkToRetreats[chunk] or 0
return map.chunkToRetreats[chunk.id] or 0
end
function chunkPropertyUtils.getRallyTick(map, chunk)
return map.chunkToRallys[chunk] or 0
return map.chunkToRallys[chunk.id] or 0
end
function chunkPropertyUtils.setRallyTick(map, chunk, tick)
map.chunkToRallys[chunk] = tick
map.chunkToRallys[chunk.id] = tick
end
function chunkPropertyUtils.setRetreatTick(map, chunk, tick)
map.chunkToRetreats[chunk] = tick
map.chunkToRetreats[chunk.id] = tick
end
function chunkPropertyUtils.setResourceGenerator(map, chunk, resourceGenerator)
if (resourceGenerator <= 0) then
map.chunkToResource[chunk] = nil
map.chunkToResource[chunk.id] = nil
else
map.chunkToResource[chunk] = resourceGenerator
map.chunkToResource[chunk.id] = resourceGenerator
end
end
function chunkPropertyUtils.getResourceGenerator(map, chunk)
return map.chunkToResource[chunk] or 0
return map.chunkToResource[chunk.id] or 0
end
function chunkPropertyUtils.addResourceGenerator(map, chunk, delta)
map.chunkToResource[chunk] = (map.chunkToResource[chunk] or 0) + delta
map.chunkToResource[chunk.id] = (map.chunkToResource[chunk.id] or 0) + delta
end
function chunkPropertyUtils.getDeathGenerator(map, chunk)
return map.chunkToDeathGenerator[chunk] or 0
return map.chunkToDeathGenerator[chunk.id] or 0
end
function chunkPropertyUtils.getPassable(map, chunk)
return map.chunkToPassable[chunk] or CHUNK_ALL_DIRECTIONS
return map.chunkToPassable[chunk.id] or CHUNK_ALL_DIRECTIONS
end
function chunkPropertyUtils.getRaidNestActiveness(map, chunk)
return map.chunkToActiveRaidNest[chunk] or 0
return map.chunkToActiveRaidNest[chunk.id] or 0
end
function chunkPropertyUtils.setRaidNestActiveness(map, chunk, value)
if (value <= 0) then
if (map.chunkToActiveRaidNest[chunk] ~= nil) then
if map.chunkToActiveRaidNest[chunk.id] then
map.activeRaidNests = map.activeRaidNests - 1
end
if (map.processActiveRaidSpawnerIterator == chunk) then
if (map.processActiveRaidSpawnerIterator == chunk.id) then
map.processActiveRaidSpawnerIterator = nil
end
map.chunkToActiveRaidNest[chunk] = nil
map.chunkToActiveRaidNest[chunk.id] = nil
else
if (map.chunkToActiveRaidNest[chunk] == nil) then
if not map.chunkToActiveRaidNest[chunk.id] then
map.activeRaidNests = map.activeRaidNests + 1
end
map.chunkToActiveRaidNest[chunk] = value
map.chunkToActiveRaidNest[chunk.id] = value
end
end
function chunkPropertyUtils.getNestActiveTick(map, chunk)
return map.tickActiveNest[chunk] or 0
return map.tickActiveNest[chunk.id] or 0
end
function chunkPropertyUtils.setNestActiveTick(map, chunk, tick)
if (tick == 0) then
map.tickActiveNest[chunk] = nil
map.tickActiveNest[chunk.id] = nil
else
map.tickActiveNest[chunk] = tick
map.tickActiveNest[chunk.id] = tick
end
end
function chunkPropertyUtils.getNestActiveness(map, chunk)
return map.chunkToActiveNest[chunk] or 0
return map.chunkToActiveNest[chunk.id] or 0
end
function chunkPropertyUtils.setNestActiveness(map, chunk, value)
if (value <= 0) then
if (map.chunkToActiveNest[chunk] ~= nil) then
if map.chunkToActiveNest[chunk.id] then
map.activeNests = map.activeNests - 1
end
if (map.processActiveSpawnerIterator == chunk) then
if (map.processActiveSpawnerIterator == chunk.id) then
map.processActiveSpawnerIterator = nil
end
map.chunkToActiveNest[chunk] = nil
map.chunkToActiveNest[chunk.id] = nil
else
if (map.chunkToActiveNest[chunk] == nil) then
if not map.chunkToActiveNest[chunk.id] then
map.activeNests = map.activeNests + 1
end
map.chunkToActiveNest[chunk] = value
map.chunkToActiveNest[chunk.id] = value
end
end
function chunkPropertyUtils.setPassable(map, chunk, value)
if (value == CHUNK_ALL_DIRECTIONS) then
map.chunkToPassable[chunk] = nil
map.chunkToPassable[chunk.id] = nil
else
map.chunkToPassable[chunk] = value
map.chunkToPassable[chunk.id] = value
end
end
function chunkPropertyUtils.getPathRating(map, chunk)
return map.chunkToPathRating[chunk] or 1
return map.chunkToPathRating[chunk.id] or 1
end
function chunkPropertyUtils.setPathRating(map, chunk, value)
if (value == 1) then
map.chunkToPathRating[chunk] = nil
map.chunkToPathRating[chunk.id] = nil
else
map.chunkToPathRating[chunk] = value
map.chunkToPathRating[chunk.id] = value
end
end
function chunkPropertyUtils.addDeathGenerator(map, chunk, value)
map.chunkToDeathGenerator[chunk] = (map.chunkToDeathGenerator[chunk] or 0) + value
map.chunkToDeathGenerator[chunk.id] = (map.chunkToDeathGenerator[chunk.id] or 0) + value
end
function chunkPropertyUtils.addVictoryGenerator(map, chunk, value)
map.chunkToVictory[chunk] = (map.chunkToVictory[chunk] or 0) + value
map.chunkToVictory[chunk.id] = (map.chunkToVictory[chunk.id] or 0) + value
end
function chunkPropertyUtils.decayDeathGenerator(map, chunk)
local gen = map.chunkToDeathGenerator[chunk]
local gen = map.chunkToDeathGenerator[chunk.id]
if gen then
gen = gen * MOVEMENT_GENERATOR_PERSISTANCE
if (gen >= -2) and (gen <= 2) then
map.chunkToDeathGenerator[chunk] = nil
map.chunkToDeathGenerator[chunk.id] = nil
else
map.chunkToDeathGenerator[chunk] = gen
map.chunkToDeathGenerator[chunk.id] = gen
end
end
end
@@ -321,50 +321,50 @@ function chunkPropertyUtils.addPlayerToChunk(map, chunk, name)
local playerChunk = playerChunks[name]
if not playerChunk then
playerChunks[name] = chunk
local playerCount = playerCountChunks[chunk]
local playerCount = playerCountChunks[chunk.id]
if not playerCount then
playerCountChunks[chunk] = 1
playerCountChunks[chunk.id] = 1
else
playerCountChunks[chunk] = playerCount + 1
playerCountChunks[chunk.id] = playerCount + 1
end
elseif (playerChunk ~= chunk) then
elseif (playerChunk.id ~= chunk.id) then
playerChunks[name] = chunk
local playerCount = playerCountChunks[playerChunk]
local playerCount = playerCountChunks[playerChunk.id]
chunkPropertyUtils.setPlayersOnChunk(map, playerChunk, playerCount - 1)
playerCount = playerCountChunks[chunk]
playerCount = playerCountChunks[chunk.id]
if not playerCount then
playerCountChunks[chunk] = 1
playerCountChunks[chunk.id] = 1
else
playerCountChunks[chunk] = playerCount + 1
playerCountChunks[chunk.id] = playerCount + 1
end
end
end
function chunkPropertyUtils.setPlayersOnChunk(map, chunk, value)
if (value <= 0) then
map.chunkToPlayerCount[chunk] = nil
map.chunkToPlayerCount[chunk.id] = nil
else
map.chunkToPlayerCount[chunk] = value
map.chunkToPlayerCount[chunk.id] = value
end
end
function chunkPropertyUtils.getPlayersOnChunk(map, chunk)
return map.chunkToPlayerCount[chunk] or 0
return map.chunkToPlayerCount[chunk.id] or 0
end
function chunkPropertyUtils.getPlayerBaseGenerator(map, chunk)
return map.chunkToPlayerBase[chunk] or 0
return map.chunkToPlayerBase[chunk.id] or 0
end
function chunkPropertyUtils.addSquadToChunk(map, chunk, squad)
local chunkToSquad = map.chunkToSquad
if (chunk ~= -1) and (squad.chunk ~= chunk) then
if (chunk ~= -1) and ((squad.chunk == -1) or (squad.chunk.id ~= chunk.id)) then
chunkPropertyUtils.removeSquadFromChunk(map, squad)
local squads = chunkToSquad[chunk]
local squads = chunkToSquad[chunk.id]
if not squads then
squads = {}
chunkToSquad[chunk] = squads
chunkToSquad[chunk.id] = squads
end
squads[squad.groupNumber] = squad
squad.chunk = chunk
@@ -374,29 +374,31 @@ end
function chunkPropertyUtils.removeSquadFromChunk(map, squad)
local chunkToSquad = map.chunkToSquad
local chunk = squad.chunk
local squads = chunkToSquad[chunk]
if squads then
squads[squad.groupNumber] = nil
if (table_size(squads) == 0) then
chunkToSquad[chunk] = nil
if (chunk ~= -1) then
local squads = chunkToSquad[chunk.id]
if squads then
squads[squad.groupNumber] = nil
if (table_size(squads) == 0) then
chunkToSquad[chunk.id] = nil
end
end
end
end
function chunkPropertyUtils.getSquadsOnChunk(map, chunk)
return map.chunkToSquad[chunk] or map.emptySquadsOnChunk
return map.chunkToSquad[chunk.id] or map.emptySquadsOnChunk
end
function chunkPropertyUtils.setPlayerBaseGenerator(map, chunk, playerGenerator)
if (playerGenerator <= 0) then
map.chunkToPlayerBase[chunk] = nil
map.chunkToPlayerBase[chunk.id] = nil
else
map.chunkToPlayerBase[chunk] = playerGenerator
map.chunkToPlayerBase[chunk.id] = playerGenerator
end
end
function chunkPropertyUtils.addPlayerBaseGenerator(map, chunk, playerGenerator)
map.chunkToPlayerBase[chunk] = (map.chunkToPlayerBase[chunk] or 0) + playerGenerator
map.chunkToPlayerBase[chunk.id] = (map.chunkToPlayerBase[chunk.id] or 0) + playerGenerator
end
function chunkPropertyUtils.processNestActiveness(map, chunk)
@@ -409,12 +411,12 @@ function chunkPropertyUtils.processNestActiveness(map, chunk)
if universe.attackUsePlayer and (chunk[PLAYER_PHEROMONE] > universe.attackPlayerThreshold) then
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20))
elseif (chunk[BASE_PHEROMONE] > 0) then
local position = universe.position
if (surface.get_pollution(chunk) > 0) then
chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20))
else
local x = chunk.x
local y = chunk.y
local position = {x=0,y=0}
position.x = x + 32
position.y = y
if (surface.get_pollution(position) > 0) then

View File

@@ -351,16 +351,23 @@ function chunkUtils.entityForPassScan(map, entity)
for i=1,#overlapArray do
local chunk = overlapArray[i]
if (chunk ~= -1) then
map.chunkToPassScan[chunk] = true
map.chunkToPassScan[chunk.id] = chunk
end
end
end
function chunkUtils.createChunk(topX, topY)
function chunkUtils.newChunkId(map)
local id = map.chunkId
map.chunkId = map.chunkId + 1
return id
end
function chunkUtils.createChunk(map, topX, topY)
local chunk = {
x = topX,
y = topY,
dOrigin = euclideanDistancePoints(topX, topY, 0, 0)
dOrigin = euclideanDistancePoints(topX, topY, 0, 0),
id = chunkUtils.newChunkId(map)
}
chunk[BASE_PHEROMONE] = 0
chunk[PLAYER_PHEROMONE] = 0

View File

@@ -63,6 +63,7 @@ local formSettlers = aiAttackWave.formSettlers
local getChunkByPosition = mapUtils.getChunkByPosition
local getChunkByXY = mapUtils.getChunkByXY
local getChunkById = mapUtils.getChunkById
local validPlayer = playerUtils.validPlayer
@@ -253,7 +254,7 @@ function mapProcessor.processPlayers(players, map, tick)
queueNestSpawners(map, chunk, tick)
if vengence then
map.vengenceQueue[chunk] = (map.vengenceQueue[chunk] or 0) + 1
map.vengenceQueue[chunk.id] = (map.vengenceQueue[chunk.id] or 0) + 1
end
end
end
@@ -448,27 +449,28 @@ function mapProcessor.processActiveNests(map, tick)
end
function mapProcessor.processVengence(map)
local ss = map.vengenceQueue
local chunk = map.deployVengenceIterator
if not chunk then
chunk = next(ss, nil)
local vengence = map.vengenceQueue
local chunkId = map.deployVengenceIterator
if not chunkId then
chunkId = next(vengence, nil)
end
if not chunk then
if not chunkId then
map.deployVengenceIterator = nil
if (tableSize(ss) == 0) then
if (tableSize(vengence) == 0) then
map.vengenceQueue = {}
end
else
map.deployVengenceIterator = next(ss, chunk)
formVengenceSquad(map, chunk)
ss[chunk] = nil
map.deployVengenceIterator = next(vengence, chunkId)
formVengenceSquad(map, getChunkById(map, chunkId))
vengence[chunkId] = nil
end
end
function mapProcessor.processNests(map, tick)
local chunk = next(map.chunkToNests, map.processNestIterator)
map.processNestIterator = chunk
if chunk then
local chunkId = next(map.chunkToNests, map.processNestIterator)
map.processNestIterator = chunkId
if chunkId then
local chunk = getChunkById(map, chunkId)
processNestActiveness(map, chunk)
queueNestSpawners(map, chunk, tick)
@@ -481,10 +483,11 @@ function mapProcessor.processNests(map, tick)
end
end
local function processSpawners(map, iterator, chunks)
local chunk = next(chunks, map[iterator])
map[iterator] = chunk
if chunk then
local function processSpawnersBody(map, iterator, chunks)
local chunkId = next(chunks, map[iterator])
map[iterator] = chunkId
if chunkId then
local chunk = getChunkById(map, chunkId)
local migrate = canMigrate(map)
local attack = canAttack(map)
if migrate then
@@ -499,30 +502,30 @@ function mapProcessor.processSpawners(map)
if (map.state ~= AI_STATE_PEACEFUL) then
if (map.state == AI_STATE_MIGRATING) then
processSpawners(map,
"processMigrationIterator",
map.chunkToNests)
processSpawnersBody(map,
"processMigrationIterator",
map.chunkToNests)
elseif (map.state == AI_STATE_AGGRESSIVE) then
processSpawners(map,
"processActiveSpawnerIterator",
map.chunkToActiveNest)
processSpawnersBody(map,
"processActiveSpawnerIterator",
map.chunkToActiveNest)
elseif (map.state == AI_STATE_SIEGE) then
processSpawners(map,
"processActiveSpawnerIterator",
map.chunkToActiveNest)
processSpawners(map,
"processActiveRaidSpawnerIterator",
map.chunkToActiveRaidNest)
processSpawners(map,
"processMigrationIterator",
map.chunkToNests)
processSpawnersBody(map,
"processActiveSpawnerIterator",
map.chunkToActiveNest)
processSpawnersBody(map,
"processActiveRaidSpawnerIterator",
map.chunkToActiveRaidNest)
processSpawnersBody(map,
"processMigrationIterator",
map.chunkToNests)
else
processSpawners(map,
"processActiveSpawnerIterator",
map.chunkToActiveNest)
processSpawners(map,
"processActiveRaidSpawnerIterator",
map.chunkToActiveRaidNest)
processSpawnersBody(map,
"processActiveSpawnerIterator",
map.chunkToActiveNest)
processSpawnersBody(map,
"processActiveRaidSpawnerIterator",
map.chunkToActiveRaidNest)
end
end
end

View File

@@ -43,6 +43,10 @@ function mapUtils.getChunkByPosition(map, position)
return -1
end
function mapUtils.getChunkById(map, chunkId)
return map.chunkIdToChunk[chunkId] or -1
end
function mapUtils.positionToChunkXY(position)
local chunkX = mFloor(position.x * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
local chunkY = mFloor(position.y * CHUNK_SIZE_DIVIDER) * CHUNK_SIZE
@@ -51,7 +55,10 @@ end
function mapUtils.queueGeneratedChunk(universe, event)
event.tick = (event.tick or game.tick) + 20
universe.maps[event.surface.index].pendingChunks[event] = true
local map = universe.maps[event.surface.index]
event.id = map.eventId
map.pendingChunks[event.id] = event
map.eventId = map.eventId + 1
end
--[[
@@ -220,6 +227,5 @@ function mapUtils.positionFromDirectionAndFlat(direction, startPosition, endPosi
endPosition.y = ly
end
mapUtilsG = mapUtils
return mapUtils

View File

@@ -51,7 +51,7 @@ function movementUtils.addMovementPenalty(squad, chunk)
local penaltyCount = #penalties
for i=1,penaltyCount do
local penalty = penalties[i]
if (penalty.c == chunk) then
if (penalty.c.id == chunk.id) then
penalty.v = penalty.v + 1
if (penalty.v > 2) then
squad.kamikaze = true
@@ -79,7 +79,7 @@ function movementUtils.scoreNeighborsForAttack(map, chunk, neighborDirectionChun
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if (neighborChunk ~= -1) then
if canMoveChunkDirection(map, x, chunk, neighborChunk) or (chunk == -1) then
if (chunk == -1) or canMoveChunkDirection(map, x, chunk, neighborChunk) then
local score = scoreFunction(map, neighborChunk)
if (score > highestScore) then
highestScore = score
@@ -98,7 +98,7 @@ function movementUtils.scoreNeighborsForAttack(map, chunk, neighborDirectionChun
neighborDirectionChunks = getNeighborChunks(map, highestChunk.x, highestChunk.y)
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if ((neighborChunk ~= -1) and (neighborChunk ~= chunk) and
if ((neighborChunk ~= -1) and ((chunk == -1) or (neighborChunk.id ~= chunk.id)) and
canMoveChunkDirection(map, x, highestChunk, neighborChunk)) then
local score = scoreFunction(map, neighborChunk)
if (score > nextHighestScore) then
@@ -125,7 +125,7 @@ function movementUtils.scoreNeighborsForSettling(map, chunk, neighborDirectionCh
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if (neighborChunk ~= -1) then
if canMoveChunkDirection(map, x, chunk, neighborChunk) or (chunk == -1) then
if (chunk == -1) or canMoveChunkDirection(map, x, chunk, neighborChunk) then
local score = scoreFunction(map, neighborChunk)
if (score > highestScore) then
highestScore = score
@@ -148,7 +148,7 @@ function movementUtils.scoreNeighborsForSettling(map, chunk, neighborDirectionCh
neighborDirectionChunks = getNeighborChunks(map, highestChunk.x, highestChunk.y)
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if ((neighborChunk ~= -1) and (neighborChunk ~= chunk) and
if ((neighborChunk ~= -1) and ((chunk == -1) or (neighborChunk.id ~= chunk.id)) and
canMoveChunkDirection(map, x, highestChunk, neighborChunk)) then
local score = scoreFunction(map, neighborChunk)
if (score > nextHighestScore) then
@@ -203,7 +203,7 @@ function movementUtils.scoreNeighborsForRetreat(chunk, neighborDirectionChunks,
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if (neighborChunk ~= -1) then
if canMoveChunkDirection(map, x, chunk, neighborChunk) or (chunk == -1) then
if (chunk == -1) or canMoveChunkDirection(map, x, chunk, neighborChunk) then
local score = scoreFunction(map, neighborChunk)
if (score > highestScore) then
highestScore = score
@@ -223,7 +223,7 @@ function movementUtils.scoreNeighborsForRetreat(chunk, neighborDirectionChunks,
for x=1,8 do
local neighborChunk = neighborDirectionChunks[x]
if ((neighborChunk ~= -1) and (neighborChunk ~= chunk) and
if ((neighborChunk ~= -1) and ((chunk == -1) or (neighborChunk.id ~= chunk.id)) and
canMoveChunkDirection(map, x, highestChunk, neighborChunk)) then
local score = scoreFunction(map, neighborChunk)
if (score > nextHighestScore) then

View File

@@ -37,6 +37,7 @@ local addVictoryGenerator = chunkPropertyUtils.addVictoryGenerator
local getPlayersOnChunk = chunkPropertyUtils.getPlayersOnChunk
local getNeighborChunks = mapUtils.getNeighborChunks
local getChunkById = mapUtils.getChunkById
local getEnemyStructureCount = chunkPropertyUtils.getEnemyStructureCount
local getPathRating = chunkPropertyUtils.getPathRating
@@ -63,18 +64,20 @@ function pheromoneUtils.victoryScent(map, chunk, entityType)
end
function pheromoneUtils.disperseVictoryScent(map)
local chunk = map.victoryScentIterator
local chunkId = map.victoryScentIterator
local chunkToVictory = map.chunkToVictory
local pheromone
if not chunk then
chunk, pheromone = next(chunkToVictory, nil)
if not chunkId then
chunkId, pheromone = next(chunkToVictory, nil)
else
pheromone = chunkToVictory[chunk]
pheromone = chunkToVictory[chunkId]
end
if not chunk then
if not chunkId then
map.victoryScentIterator = nil
else
map.victoryScentIterator = next(chunkToVictory, chunk)
map.victoryScentIterator = next(chunkToVictory, chunkId)
chunkToVictory[chunkId] = nil
local chunk = getChunkById(map, chunkId)
local chunkX = chunk.x
local chunkY = chunk.y
local i = 1
@@ -87,8 +90,6 @@ function pheromoneUtils.disperseVictoryScent(map)
i = i + 1
end
end
chunkToVictory[chunk] = nil
end
end

View File

@@ -118,9 +118,14 @@ local function settleMove(map, squad)
elseif squad.kamikaze then
scoreFunction = scoreResourceLocationKamikaze
end
addDeathGenerator(map, chunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
addSquadToChunk(map, chunk, squad)
addMovementPenalty(squad, chunk)
local squadChunk = squad.chunk
if squadChunk ~= -1 then
addDeathGenerator(map, squadChunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
end
if chunk ~= -1 then
addSquadToChunk(map, chunk, squad)
addMovementPenalty(squad, chunk)
end
local distance = euclideanDistancePoints(groupPosition.x,
groupPosition.y,
squad.originPosition.x,
@@ -129,7 +134,8 @@ local function settleMove(map, squad)
local position
local surface = map.surface
if (distance >= squad.maxDistance) or ((getResourceGenerator(map, chunk) ~= 0) and (getNestCount(map, chunk) == 0))
if (chunk ~= -1) and
((distance >= squad.maxDistance) or ((getResourceGenerator(map, chunk) ~= 0) and (getNestCount(map, chunk) == 0)))
then
position = findMovementPosition(surface, groupPosition)
@@ -244,9 +250,13 @@ local function attackMove(map, squad)
attackScorer = scoreAttackKamikazeLocation
end
local squadChunk = squad.chunk
addDeathGenerator(map, squadChunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
addSquadToChunk(map, chunk, squad)
addMovementPenalty(squad, chunk)
if squadChunk ~= -1 then
addDeathGenerator(map, squadChunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
end
if chunk ~= -1 then
addSquadToChunk(map, chunk, squad)
addMovementPenalty(squad, chunk)
end
squad.frenzy = (squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100))
local attackChunk, attackDirection,
nextAttackChunk, nextAttackDirection = scoreNeighborsForAttack(map,
@@ -275,7 +285,7 @@ local function attackMove(map, squad)
else
targetPosition.x = position.x
targetPosition.y = position.y
if nextAttackChunk then
if (nextAttackChunk ~= -1) then
addDeathGenerator(map, nextAttackChunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
else
addDeathGenerator(map, attackChunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
@@ -322,26 +332,28 @@ end
function squadAttack.cleanSquads(map, tick)
local squads = map.groupNumberToSquad
local k = map.squadIterator
local groupId = map.squadIterator
local squad
if not k then
k, squad = next(squads, k)
if not groupId then
groupId, squad = next(squads, groupId)
else
squad = squads[k]
squad = squads[groupId]
end
if not k then
if not groupId then
map.squadIterator = nil
if (table_size(squads) == 0) then
-- this is needed as the next command remembers the max length a table has been
map.groupNumberToSquad = {}
end
else
map.squadIterator = next(squads, k)
map.squadIterator = next(squads, groupId)
local group = squad.group
if not group.valid then
addDeathGenerator(map, squad.chunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
if squad.chunk ~= -1 then
addDeathGenerator(map, squad.chunk, FIVE_DEATH_PHEROMONE_GENERATOR_AMOUNT)
end
removeSquadFromChunk(map, squad)
if (map.regroupIterator == k) then
if (map.regroupIterator == groupId) then
map.regroupIterator = nil
end
local universe = map.universe
@@ -350,7 +362,7 @@ function squadAttack.cleanSquads(map, tick)
else
universe.squadCount = universe.squadCount - 1
end
squads[k] = nil
squads[groupId] = nil
elseif (group.state == 4) then
squadAttack.squadDispatch(map, squad, tick)
elseif (squad.commandTick and (squad.commandTick < tick)) then