From 806366461620393f86d7045a986328d744317a8c Mon Sep 17 00:00:00 2001 From: Aaron Veden Date: Fri, 19 Feb 2021 21:41:30 -0800 Subject: [PATCH] working through runtime errors --- Upgrade.lua | 361 ++++++++-- control.lua | 1335 +++++++++++++---------------------- libs/AIAttackWave.lua | 86 +-- libs/AIPlanning.lua | 211 +++--- libs/AIPredicates.lua | 24 +- libs/BaseUtils.lua | 162 ++--- libs/ChunkProcessor.lua | 15 +- libs/ChunkPropertyUtils.lua | 14 +- libs/ChunkUtils.lua | 131 ++-- libs/Constants.lua | 20 +- libs/Interop.lua | 130 ++-- libs/MapProcessor.lua | 139 ++-- libs/SquadAttack.lua | 43 +- libs/SquadDefense.lua | 11 +- 14 files changed, 1312 insertions(+), 1370 deletions(-) diff --git a/Upgrade.lua b/Upgrade.lua index fb88601..1b5f0f1 100755 --- a/Upgrade.lua +++ b/Upgrade.lua @@ -3,20 +3,326 @@ local upgrade = {} -- imports local constants = require("libs/Constants") -local mathUtils = require("libs/MathUtils") -- constants -local INTERVAL_LOGIC = constants.INTERVAL_LOGIC +local DEFINES_COMMAND_GROUP = defines.command.group +local DEFINES_COMMAND_WANDER = defines.command.wander +local DEFINES_COMMAND_BUILD_BASE = defines.command.build_base +local DEFINES_COMMAND_ATTACK_AREA = defines.command.attack_area +local DEFINES_COMMAND_GO_TO_LOCATION = defines.command.go_to_location +local DEFINES_COMMMAD_COMPOUND = defines.command.compound +local DEFINES_COMMAND_FLEE = defines.command.flee +local DEFINES_COMMAND_STOP = defines.command.stop + +local DEFINES_COMPOUND_COMMAND_RETURN_LAST = defines.compound_command.return_last + +local DEFINES_DISTRACTION_NONE = defines.distraction.none +local DEFINES_DISTRACTION_BY_ENEMY = defines.distraction.by_enemy +local DEFINES_DISTRACTION_BY_ANYTHING = defines.distraction.by_anything + local CHUNK_SIZE = constants.CHUNK_SIZE +local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE -- imported functions -local roundToNearest = mathUtils.roundToNearest - -- module code -function upgrade.attempt(natives, setNewSurface, gameSurfaces) +local function addCommandSet(queriesAndCommands) + -- preallocating memory to be used in code, making it fast by reducing garbage generated. + queriesAndCommands.neighbors = { + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1 + } + queriesAndCommands.cardinalNeighbors = { + -1, + -1, + -1, + -1 + } + queriesAndCommands.position = { + x=0, + y=0 + } + queriesAndCommands.position2 = { + x=0, + y=0 + } + queriesAndCommands.position3 = { + x=0, + y=0 + } + + queriesAndCommands.chunkOverlapArray = { + -1, + -1, + -1, + -1 + } + + queriesAndCommands.position2Top = {0, 0} + queriesAndCommands.position2Bottom = {0, 0} + --this is shared between two different queries + queriesAndCommands.area = { + {0, 0}, + {0, 0} + } + queriesAndCommands.area2 = { + queriesAndCommands.position2Top, + queriesAndCommands.position2Bottom + } + queriesAndCommands.buildPositionTop = {0, 0} + queriesAndCommands.buildPositionBottom = {0, 0} + queriesAndCommands.buildArea = { + queriesAndCommands.buildPositionTop, + queriesAndCommands.buildPositionBottom + } + queriesAndCommands.countResourcesQuery = { + area=queriesAndCommands.area, + type="resource" + } + queriesAndCommands.filteredEntitiesUnitQuery = { + area=queriesAndCommands.area, + force="enemy", + type="unit" + } + queriesAndCommands.hasPlayerStructuresQuery = { + area=queriesAndCommands.area, + force={"enemy","neutral"}, + invert=true, + limit=1 + } + queriesAndCommands.filteredEntitiesEnemyStructureQuery = { + area=queriesAndCommands.area, + force="enemy", + type={ + "turret", + "unit-spawner" + } + } + queriesAndCommands.filteredEntitiesPointQueryLimited = { + position = queriesAndCommands.position, + radius = 10, + limit = 1, + force = "enemy", + type = { + "unit-spawner", + "turret" + } + } + queriesAndCommands.createBuildCloudQuery = { + name = "build-clear-cloud-rampant", + position = queriesAndCommands.position + } + + queriesAndCommands.activePlayerForces = {"player"} + + for _,force in pairs(game.forces) do + local add = true + + if (force.name ~= "neutral") and (force.name ~= "enemy") then + for i=1,#queriesAndCommands.activePlayerForces do + if (queriesAndCommands.activePlayerForces[i] == force.name) then + add = false + break + end + end + + if add then + queriesAndCommands.activePlayerForces[#queriesAndCommands.activePlayerForces+1] = force.name + end + end + end + + queriesAndCommands.filteredEntitiesPlayerQueryLowest = { + area=queriesAndCommands.area, + force=queriesAndCommands.activePlayerForces, + collision_mask = "player-layer", + type={ + "wall", + "transport-belt" + } + } + + queriesAndCommands.filteredEntitiesPlayerQueryLow = { + area=queriesAndCommands.area, + force=queriesAndCommands.activePlayerForces, + collision_mask = "player-layer", + type={ + "splitter", + "pump", + "offshore-pump", + "lamp", + "solar-panel", + "programmable-speaker", + "accumulator", + "assembling-machine", + "turret", + "ammo-turret" + } + } + + queriesAndCommands.filteredEntitiesPlayerQueryHigh = { + area=queriesAndCommands.area, + force=queriesAndCommands.activePlayerForces, + collision_mask = "player-layer", + type={ + "furnace", + "lab", + "roboport", + "beacon", + "radar", + "electric-turret", + "boiler", + "generator", + "fluid-turret", + "mining-drill" + } + } + + queriesAndCommands.filteredEntitiesPlayerQueryHighest = { + area=queriesAndCommands.area, + force=queriesAndCommands.activePlayerForces, + collision_mask = "player-layer", + type={ + "artillery-turret", + "reactor", + "rocket-silo" + } + } + + queriesAndCommands.filteredEntitiesChunkNeutral = { + area=queriesAndCommands.area, + collision_mask = "player-layer", + type={ + "tree", + "simple-entity" + } + } + + local sharedArea = { + {0,0}, + {0,0} + } + queriesAndCommands.filteredEntitiesCliffQuery = { + area=sharedArea, + type="cliff", + limit = 1 + } + queriesAndCommands.filteredTilesPathQuery = { + area=sharedArea, + collision_mask="water-tile", + limit = 1 + } + queriesAndCommands.cliffQuery = { + area=queriesAndCommands.area2, + type="cliff" + } + queriesAndCommands.canPlaceQuery = { + name="", + position={0,0} + } + queriesAndCommands.filteredTilesQuery = { + collision_mask="water-tile", + area=queriesAndCommands.area + } + + queriesAndCommands.upgradeEntityQuery = { + name = "", + position = nil + } + + queriesAndCommands.attackCommand = { + type = DEFINES_COMMAND_ATTACK_AREA, + destination = queriesAndCommands.position, + radius = CHUNK_SIZE * 1.5, + distraction = DEFINES_DISTRACTION_BY_ANYTHING + } + + queriesAndCommands.moveCommand = { + type = DEFINES_COMMAND_GO_TO_LOCATION, + destination = queriesAndCommands.position, + pathfind_flags = { cache = true }, + distraction = DEFINES_DISTRACTION_BY_ENEMY + } + + queriesAndCommands.settleCommand = { + type = DEFINES_COMMAND_BUILD_BASE, + destination = queriesAndCommands.position, + distraction = DEFINES_DISTRACTION_BY_ENEMY, + ignore_planner = true + } + + queriesAndCommands.wonderCommand = { + type = DEFINES_COMMAND_WANDER, + wander_in_group = false, + radius = TRIPLE_CHUNK_SIZE*2, + ticks_to_wait = 36000 + } + + queriesAndCommands.stopCommand = { + type = DEFINES_COMMAND_STOP + } + + queriesAndCommands.compoundSettleCommand = { + type = DEFINES_COMMMAD_COMPOUND, + structure_type = DEFINES_COMPOUND_COMMAND_RETURN_LAST, + commands = { + queriesAndCommands.wonder2Command, + queriesAndCommands.settleCommand + } + } + + queriesAndCommands.retreatCommand = { + type = DEFINES_COMMAND_GROUP, + group = nil, + distraction = DEFINES_DISTRACTION_BY_ANYTHING, + use_group_distraction = true + } + + queriesAndCommands.fleeCommand = { + type = DEFINES_COMMAND_FLEE, + from = nil, + distraction = DEFINES_DISTRACTION_NONE + } + + queriesAndCommands.compoundRetreatGroupCommand = { + type = DEFINES_COMMMAD_COMPOUND, + structure_type = DEFINES_COMPOUND_COMMAND_RETURN_LAST, + commands = { + queriesAndCommands.stopCommand, + queriesAndCommands.fleeCommand, + queriesAndCommands.retreatCommand + } + } + + queriesAndCommands.formGroupCommand = { + type = DEFINES_COMMAND_GROUP, + group = nil, + distraction = DEFINES_DISTRACTION_BY_ANYTHING, + use_group_distraction = false + } + + queriesAndCommands.formCommand = { + command = queriesAndCommands.formGroupCommand, + unit_count = 0, + unit_search_distance = TRIPLE_CHUNK_SIZE + } + + queriesAndCommands.formRetreatCommand = { + command = queriesAndCommands.compoundRetreatGroupCommand, + unit_count = 1, + unit_search_distance = CHUNK_SIZE + } +end + +function upgrade.attempt(natives, queriesAndCommands) local starting = global.version if not global.version or global.version < 106 then global.version = 106 @@ -31,8 +337,8 @@ function upgrade.attempt(natives, setNewSurface, gameSurfaces) natives.aiNocturnalMode = settings.global["rampant-permanentNocturnal"].value -- needs to be on inner logic tick loop interval - natives.stateTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC) - natives.temperamentTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC) + -- natives.stateTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC) + -- natives.temperamentTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC) -- used to precompute some values per logic cycle natives.retreatThreshold = 0 @@ -108,39 +414,6 @@ function upgrade.attempt(natives, setNewSurface, gameSurfaces) if (global.version < 111) then global.version = 111 - local gameSurfs - if not gameSurfaces then - gameSurfs = {} - global.gameSurfaces = gameSurfs - if natives.activeSurface == 1 then - natives.activeSurface = "nauvis" - end - else - gameSurfs = gameSurfaces - end - - for _,player in pairs(game.connected_players) do - if player and player.valid and - not settings.get_player_settings(player)["rampant-suppress-surface-change-warnings"].value - then - local surface = player.surface - if (natives.activeSurface ~= surface.name) then - local playerName = player.name - local surfaceName = surface.name - local playerSurfaces = gameSurfs[surfaceName] - if not playerSurfaces then - playerSurfaces = {} - gameSurfs[surfaceName] = playerSurfaces - player.print({"description.rampant-change-surface", surfaceName, natives.activeSurface}) - playerSurfaces[playerName] = true - elseif not playerSurfaces[playerName] then - player.print({"description.rampant-change-surface", surfaceName, natives.activeSurface}) - playerSurfaces[playerName] = true - end - end - end - end - natives.groupNumberToSquad = {} game.forces.enemy.kill_all_units() natives.squads = nil @@ -171,12 +444,12 @@ function upgrade.attempt(natives, setNewSurface, gameSurfaces) game.forces.enemy.ai_controllable = true - if not setNewSurface then - game.get_surface(natives.activeSurface).print("Rampant - Version 1.0.3") - end + addCommandSet(queriesAndCommands) + + game.print("Rampant - Version 1.0.3") end - return starting ~= global.version, natives + return starting ~= global.version end function upgrade.compareTable(entities, option, new) diff --git a/control.lua b/control.lua index 6f3569c..742b812 100755 --- a/control.lua +++ b/control.lua @@ -14,7 +14,7 @@ local squadDefense = require("libs/SquadDefense") local squadAttack = require("libs/SquadAttack") local aiAttackWave = require("libs/AIAttackWave") local aiPlanning = require("libs/AIPlanning") -local interop = require("libs/Interop") +-- local interop = require("libs/Interop") local tests = require("tests") local chunkUtils = require("libs/ChunkUtils") local upgrade = require("Upgrade") @@ -23,53 +23,22 @@ local aiPredicates = require("libs/AIPredicates") -- constants -local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE -local INTERVAL_LOGIC = constants.INTERVAL_LOGIC -local INTERVAL_SQUAD = constants.INTERVAL_SQUAD -local INTERVAL_TEMPERAMENT = constants.INTERVAL_TEMPERAMENT -local INTERVAL_SPAWNER = constants.INTERVAL_SPAWNER -local INTERVAL_PASS_SCAN = constants.INTERVAL_PASS_SCAN -local INTERVAL_NEST = constants.INTERVAL_NEST -local INTERVAL_CLEANUP = constants.INTERVAL_CLEANUP -local INTERVAL_VICTORY = constants.INTERVAL_VICTORY - local AI_SQUAD_COST = constants.AI_SQUAD_COST local AI_SETTLER_COST = constants.AI_SETTLER_COST local RECOVER_NEST_COST = constants.RECOVER_NEST_COST local RECOVER_WORM_COST = constants.RECOVER_WORM_COST -local PROCESS_QUEUE_SIZE = constants.PROCESS_QUEUE_SIZE - local RETREAT_GRAB_RADIUS = constants.RETREAT_GRAB_RADIUS local RETREAT_SPAWNER_GRAB_RADIUS = constants.RETREAT_SPAWNER_GRAB_RADIUS -local DEFINES_COMMAND_GROUP = defines.command.group -local DEFINES_COMMAND_WANDER = defines.command.wander -local DEFINES_COMMAND_BUILD_BASE = defines.command.build_base -local DEFINES_COMMAND_ATTACK_AREA = defines.command.attack_area -local DEFINES_COMMAND_GO_TO_LOCATION = defines.command.go_to_location -local DEFINES_COMMMAD_COMPOUND = defines.command.compound -local DEFINES_COMMAND_FLEE = defines.command.flee -local DEFINES_COMMAND_STOP = defines.command.stop - -local DEFINES_COMPOUND_COMMAND_RETURN_LAST = defines.compound_command.return_last - -local CHUNK_SIZE = constants.CHUNK_SIZE - -local DEFINES_DISTRACTION_NONE = defines.distraction.none -local DEFINES_DISTRACTION_BY_ENEMY = defines.distraction.by_enemy -local DEFINES_DISTRACTION_BY_ANYTHING = defines.distraction.by_anything - local DEFINES_WIRE_TYPE_RED = defines.wire_type.red local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green local ENERGY_THIEF_CONVERSION_TABLE = constants.ENERGY_THIEF_CONVERSION_TABLE local ENERGY_THIEF_LOOKUP = constants.ENERGY_THIEF_LOOKUP --- local POISON_LOOKUP = constants.POISON_LOOKUP - -- imported functions local canMigrate = aiPredicates.canMigrate @@ -147,8 +116,8 @@ local sFind = string.find -- local references to global -local gameSurfaces -- used for manage which surfaces have been visited -local map -- manages the chunks that make up the game world +local maps -- manages the chunks that make up the game world +local queriesAndCommands -- manages all the queries and commands that will be used local natives -- manages the enemy units, structures, and ai -- hook functions @@ -158,13 +127,15 @@ local function onIonCannonFired(event) event.force, event.surface, event.player_index, event.position, event.radius --]] local surface = event.surface - if (surface.name == natives.activeSurface) then - natives.ionCannonBlasts = natives.ionCannonBlasts + 1 - natives.points = natives.points + 4000 - local chunk = getChunkByPosition(map, event.position) - if (chunk ~= -1) then - rallyUnits(chunk, map, event.tick) - end + local surfaceIndex = surface.index + local map = maps.map[surfaceIndex] + local native = natives[surfaceIndex] + native.ionCannonBlasts = native.ionCannonBlasts + 1 + native.points = native.point + 4000 + + local chunk = getChunkByPosition(map, event.position) + if (chunk ~= -1) then + rallyUnits(chunk, map, event.tick) end end @@ -176,29 +147,138 @@ local function hookEvents() end local function onLoad() - map = global.map + maps = global.maps + queriesAndCommands = global.queriesAndCommands natives = global.natives - gameSurfaces = global.gameSurfaces hookEvents() end local function onChunkGenerated(event) - -- queue generated chunk for delayed processing, queuing is required because some mods (RSO) mess with chunk as they - -- are generated, which messes up the scoring. - if (event.surface.name == natives.activeSurface) then - map.pendingChunks[event] = true - end + -- queue generated chunk for delayed processing, queuing is required because + -- some mods (RSO) mess with chunk as they are generated, which messes up the + -- scoring. + maps.map[event.surface.index].pendingChunks[event] = true end -local function rebuildMap() - game.get_surface(natives.activeSurface).print("Rampant - Reindexing chunks, please wait.") - -- clear old map processing Queue - -- prevents queue adding duplicate chunks - -- chunks are by key, so should overwrite old +local function onModSettingsChange(event) - global.map = {} - map = global.map + if event and ((string.sub(event.setting, 1, 7) ~= "rampant") or + (string.sub(event.setting, 1, 15) == "rampant-arsenal") or + (string.sub(event.setting, 1, 17) == "rampant-resources") or + (string.sub(event.setting, 1, 17) == "rampant-evolution") or + (string.sub(event.setting, 1, 19) == "rampant-maintenance") or + (string.sub(event.setting, 1, 16) == "rampant-industry")) + then + return false + end + + upgrade.compareTable(natives, + "safeBuildings", + settings.global["rampant-safeBuildings"].value) + upgrade.compareTable(natives.safeEntities, + "curved-rail", + settings.global["rampant-safeBuildings-curvedRail"].value) + upgrade.compareTable(natives.safeEntities, + "straight-rail", + settings.global["rampant-safeBuildings-straightRail"].value) + upgrade.compareTable(natives.safeEntities, + "rail-signal", + settings.global["rampant-safeBuildings-railSignals"].value) + upgrade.compareTable(natives.safeEntities, + "rail-chain-signal", + settings.global["rampant-safeBuildings-railChainSignals"].value) + upgrade.compareTable(natives.safeEntities, + "train-stop", + settings.global["rampant-safeBuildings-trainStops"].value) + upgrade.compareTable(natives.safeEntities, + "lamp", + settings.global["rampant-safeBuildings-lamps"].value) + + local changed, newValue = upgrade.compareTable(natives.safeEntities, + "big-electric-pole", + settings.global["rampant-safeBuildings-bigElectricPole"].value) + if changed then + natives.safeEntities["big-electric-pole"] = newValue + natives.safeEntities["big-electric-pole-2"] = newValue + natives.safeEntities["big-electric-pole-3"] = newValue + natives.safeEntities["big-electric-pole-4"] = newValue + natives.safeEntities["lighted-big-electric-pole-4"] = newValue + natives.safeEntities["lighted-big-electric-pole-3"] = newValue + natives.safeEntities["lighted-big-electric-pole-2"] = newValue + natives.safeEntities["lighted-big-electric-pole"] = newValue + end + + upgrade.compareTable(natives, + "deadZoneFrequency", + settings.global["rampant-deadZoneFrequency"].value) + upgrade.compareTable(natives, + "raidAIToggle", + settings.global["rampant-raidAIToggle"].value) + upgrade.compareTable(natives, + "siegeAIToggle", + settings.global["rampant-siegeAIToggle"].value) + + upgrade.compareTable(natives, + "attackPlayerThreshold", + settings.global["rampant-attackPlayerThreshold"].value) + upgrade.compareTable(natives, + "attackUsePlayer", + settings.global["rampant-attackWaveGenerationUsePlayerProximity"].value) + + upgrade.compareTable(natives, + "attackWaveMaxSize", + settings.global["rampant-attackWaveMaxSize"].value) + upgrade.compareTable(natives, + "aiNocturnalMode", + settings.global["rampant-permanentNocturnal"].value) + upgrade.compareTable(natives, + "aiPointsScaler", + settings.global["rampant-aiPointsScaler"].value) + + natives.enabledMigration = natives.expansion and settings.global["rampant-enableMigration"].value + + upgrade.compareTable(natives, + "AI_MAX_SQUAD_COUNT", + settings.global["rampant-maxNumberOfSquads"].value) + upgrade.compareTable(natives, + "AI_MAX_BUILDER_COUNT", + settings.global["rampant-maxNumberOfBuilders"].value) + + return true +end + +local function prepWorld(surface) + surface.print("Rampant - Indexing chunks, please wait.") + + local surfaceIndex = surface.index + + if not maps.map then + maps.map = {} + end + + local map = maps.map[surfaceIndex] + if not map then + map = {} + maps.map[surfaceIndex] = map + if not maps.registeredMaps then + maps.registeredMaps = {} + end + local add = true + for _, v in pairs(maps.registeredMaps) do + if surfaceIndex == v then + add = false + break + end + end + if add then + maps.registeredMaps[#maps.registeredMaps+1] = surfaceIndex + end + end + + map.totalChunks = 0 + map.processedChunks = 0 + map.mapIterator = nil map.processQueue = {} map.processIndex = 1 map.cleanupIndex = 1 @@ -248,51 +328,8 @@ local function rebuildMap() map.processNestIterator = nil map.victoryScentIterator = nil - -- preallocating memory to be used in code, making it fast by reducing garbage generated. - map.neighbors = { - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1 - } - map.cardinalNeighbors = { - -1, - -1, - -1, - -1 - } - map.position = { - x=0, - y=0 - } - map.position2 = { - x=0, - y=0 - } - map.position3 = { - x=0, - y=0 - } - - map.scentStaging = {} - - for x=1,PROCESS_QUEUE_SIZE+1 do - map.scentStaging[x] = {0,0,0,0} - end - map.chunkScanCounts = {} - map.chunkOverlapArray = { - -1, - -1, - -1, - -1 - } - map.enemiesToSquad = {} map.enemiesToSquad.len = 0 map.chunkRemovals = {} @@ -300,311 +337,55 @@ local function rebuildMap() map.tickActiveNest = {} map.emptySquadsOnChunk = {} - map.position2Top = {0, 0} - map.position2Bottom = {0, 0} - --this is shared between two different queries - map.area = {{0, 0}, {0, 0}} - map.testArea = {{0, 0}, {0, 0}} - map.area2 = {map.position2Top, map.position2Bottom} - map.buildPositionTop = {0, 0} - map.buildPositionBottom = {0, 0} - map.buildArea = {map.buildPositionTop, map.buildPositionBottom} - map.countResourcesQuery = { area=map.area, type="resource" } - map.filteredEntitiesUnitQuery = { area=map.area, force="enemy",type="unit" } - map.filteredEntitiesClearBuildingQuery = { area=map.buildArea, force="neutral",collision_mask="player-layer" } - map.filteredEntitiesEnemyUnitQuery = { area=map.area, force="enemy", type="unit", limit=301 } - map.hasPlayerStructuresQuery = { area=map.area, force={"enemy","neutral"}, invert=true, limit=1 } - map.filteredEntitiesEnemyStructureQuery = { area=map.area, force="enemy", type={"turret","unit-spawner"} } - map.filteredEntitiesPointQueryLimited = { - position = map.position, - radius = 10, - limit = 1, - force = "enemy", - type = { - "unit-spawner", - "turret" - } - } - map.createBuildCloudQuery = { - name = "build-clear-cloud-rampant", - position = map.position - } - map.activePlayerForces = {"player"} + local native = natives[surface.index] + if not native then + native = {} + natives[surface.index] = native + end + map.native = native + native.map = map + map.surface = surface + native.surface = surface + map.queriesAndCommands = queriesAndCommands + native.queriesAndCommands = queriesAndCommands - for _,force in pairs(game.forces) do - local add = true - - if (force.name ~= "neutral") and (force.name ~= "enemy") then - for i=1,#map.activePlayerForces do - if (map.activePlayerForces[i] == force.name) then - add = false - break - end - end - - if add then - map.activePlayerForces[#map.activePlayerForces+1] = force.name - end + -- queue all current chunks that wont be generated during play + local tick = game.tick + local position = {0,0} + native.nextChunkSort = 0 + for chunk in surface.get_chunks() do + local x = chunk.x + local y = chunk.y + position[1] = x + position[2] = y + if surface.is_chunk_generated(position) then + onChunkGenerated({ surface = surface, + area = { left_top = { x = x * 32, + y = y * 32}}}) end end - map.filteredEntitiesPlayerQueryLowest = { area=map.area, - force=map.activePlayerForces, - collision_mask = "player-layer", - type={"wall", - "transport-belt"}} - - map.filteredEntitiesPlayerQueryLow = { area=map.area, - force=map.activePlayerForces, - collision_mask = "player-layer", - type={"splitter", - "pump", - "offshore-pump", - "lamp", - "solar-panel", - "programmable-speaker", - "accumulator", - "assembling-machine", - "turret", - "ammo-turret"}} - - map.filteredEntitiesPlayerQueryHigh = { area=map.area, - force=map.activePlayerForces, - collision_mask = "player-layer", - type={"furnace", - "lab", - "roboport", - "beacon", - "radar", - "electric-turret", - "boiler", - "generator", - "fluid-turret", - "mining-drill"}} - - map.filteredEntitiesPlayerQueryHighest = { area=map.area, - force=map.activePlayerForces, - collision_mask = "player-layer", - type={"artillery-turret", - "reactor", - "rocket-silo"}} - - map.filteredEntitiesChunkNeutral = { area=map.area, - collision_mask = "player-layer", - type={"tree", - "simple-entity"}} - - local sharedArea = {{0,0},{0,0}} - map.filteredEntitiesCliffQuery = { area=sharedArea, type="cliff", limit = 1 } - map.filteredTilesPathQuery = { area=sharedArea, collision_mask="water-tile", limit = 1 } - map.cliffQuery = { - area=map.area2, - type="cliff" - } - map.canPlaceQuery = { name="", position={0,0} } - map.filteredTilesQuery = { collision_mask="water-tile", area=map.area } - - map.upgradeEntityQuery = { - name = "", - position = nil - } - - map.attackCommand = { - type = DEFINES_COMMAND_ATTACK_AREA, - destination = map.position, - radius = CHUNK_SIZE * 1.5, - distraction = DEFINES_DISTRACTION_BY_ANYTHING - } - - map.moveCommand = { - type = DEFINES_COMMAND_GO_TO_LOCATION, - destination = map.position, - pathfind_flags = { cache = true }, - distraction = DEFINES_DISTRACTION_BY_ENEMY - } - - map.settleCommand = { - type = DEFINES_COMMAND_BUILD_BASE, - destination = map.position, - distraction = DEFINES_DISTRACTION_BY_ENEMY, - ignore_planner = true - } - - map.wonderCommand = { - type = DEFINES_COMMAND_WANDER, - wander_in_group = false, - radius = TRIPLE_CHUNK_SIZE*2, - ticks_to_wait = 36000 - } - - map.wonder2Command = { - type = DEFINES_COMMAND_WANDER, - wander_in_group = false, - radius = TRIPLE_CHUNK_SIZE, - ticks_to_wait = 36000 - } - - map.wonder3Command = { - type = DEFINES_COMMAND_WANDER, - wander_in_group = true, - radius = TRIPLE_CHUNK_SIZE, - distraction = DEFINES_DISTRACTION_BY_ANYTHING, - ticks_to_wait = 36000 - } - - map.stopCommand = { - type = DEFINES_COMMAND_STOP - } - - map.compoundSettleCommand = { - type = DEFINES_COMMMAD_COMPOUND, - structure_type = DEFINES_COMPOUND_COMMAND_RETURN_LAST, - commands = { - map.wonder2Command, - map.settleCommand - } - } - - map.retreatCommand = { - type = DEFINES_COMMAND_GROUP, - group = nil, - distraction = DEFINES_DISTRACTION_BY_ANYTHING, - use_group_distraction = true - } - - map.fleeCommand = { - type = DEFINES_COMMAND_FLEE, - from = nil, - distraction = DEFINES_DISTRACTION_NONE - } - - map.compoundRetreatGroupCommand = { - type = DEFINES_COMMMAD_COMPOUND, - structure_type = DEFINES_COMPOUND_COMMAND_RETURN_LAST, - commands = { - map.stopCommand, - map.fleeCommand, - map.retreatCommand - } - } - - map.compoundRetreatCommand = { - type = DEFINES_COMMMAD_COMPOUND, - structure_type = DEFINES_COMPOUND_COMMAND_RETURN_LAST, - commands = { - map.stopCommand, - map.fleeCommand, - map.moveCommand - } - } - - map.formGroupCommand = { type = DEFINES_COMMAND_GROUP, - group = nil, - distraction = DEFINES_DISTRACTION_BY_ANYTHING, - use_group_distraction = false - } - - map.formLocalGroupCommand = { type = DEFINES_COMMAND_GROUP, - group = nil, - distraction = DEFINES_DISTRACTION_BY_ANYTHING, - use_group_distraction = false - } - - map.formCommand = { command = map.formGroupCommand, - unit_count = 0, - unit_search_distance = TRIPLE_CHUNK_SIZE } - - map.formLocalCommand = { command = map.formLocalGroupCommand, - unit_count = natives.attackWaveMaxSize, - unit_search_distance = CHUNK_SIZE } - - map.formRetreatCommand = { command = map.compoundRetreatGroupCommand, - unit_count = natives.attackWaveMaxSize, - unit_search_distance = CHUNK_SIZE } + processPendingChunks(map, tick) end - -local function onModSettingsChange(event) - - if event and ((string.sub(event.setting, 1, 7) ~= "rampant") or - (string.sub(event.setting, 1, 15) == "rampant-arsenal") or - (string.sub(event.setting, 1, 17) == "rampant-resources") or - (string.sub(event.setting, 1, 17) == "rampant-evolution") or - (string.sub(event.setting, 1, 19) == "rampant-maintenance")) - then - return false +local function onConfigChanged() + if upgrade.attempt(natives, queriesAndCommands) then + onModSettingsChange(nil) end - upgrade.compareTable(natives, "safeBuildings", settings.global["rampant-safeBuildings"].value) - - upgrade.compareTable(natives.safeEntities, "curved-rail", settings.global["rampant-safeBuildings-curvedRail"].value) - upgrade.compareTable(natives.safeEntities, - "straight-rail", - settings.global["rampant-safeBuildings-straightRail"].value) - upgrade.compareTable(natives.safeEntities, - "rail-signal", - settings.global["rampant-safeBuildings-railSignals"].value) - upgrade.compareTable(natives.safeEntities, - "rail-chain-signal", - settings.global["rampant-safeBuildings-railChainSignals"].value) - upgrade.compareTable(natives.safeEntities, "train-stop", settings.global["rampant-safeBuildings-trainStops"].value) - upgrade.compareTable(natives.safeEntities, "lamp", settings.global["rampant-safeBuildings-lamps"].value) - - local changed, newValue = upgrade.compareTable(natives.safeEntities, - "big-electric-pole", - settings.global["rampant-safeBuildings-bigElectricPole"].value) - if changed then - natives.safeEntities["big-electric-pole"] = newValue - natives.safeEntities["big-electric-pole-2"] = newValue - natives.safeEntities["big-electric-pole-3"] = newValue - natives.safeEntities["big-electric-pole-4"] = newValue - natives.safeEntities["lighted-big-electric-pole-4"] = newValue - natives.safeEntities["lighted-big-electric-pole-3"] = newValue - natives.safeEntities["lighted-big-electric-pole-2"] = newValue - natives.safeEntities["lighted-big-electric-pole"] = newValue - end - - upgrade.compareTable(natives, "deadZoneFrequency", settings.global["rampant-deadZoneFrequency"].value) - upgrade.compareTable(natives, "raidAIToggle", settings.global["rampant-raidAIToggle"].value) - upgrade.compareTable(natives, "siegeAIToggle", settings.global["rampant-siegeAIToggle"].value) - - upgrade.compareTable(natives, "attackPlayerThreshold", settings.global["rampant-attackPlayerThreshold"].value) upgrade.compareTable(natives, - "attackUsePlayer", - settings.global["rampant-attackWaveGenerationUsePlayerProximity"].value) + "ENEMY_SEED", + settings.startup["rampant-enemySeed"].value) + upgrade.compareTable(natives, + "ENEMY_VARIATIONS", + settings.startup["rampant-newEnemyVariations"].value) + upgrade.compareTable(natives, + "NEW_ENEMIES", + settings.startup["rampant-newEnemies"].value) - upgrade.compareTable(natives, "attackWaveMaxSize", settings.global["rampant-attackWaveMaxSize"].value) - upgrade.compareTable(natives, "aiNocturnalMode", settings.global["rampant-permanentNocturnal"].value) - upgrade.compareTable(natives, "aiPointsScaler", settings.global["rampant-aiPointsScaler"].value) - - upgrade.compareTable(natives, "newEnemies", settings.startup["rampant-newEnemies"].value) - upgrade.compareTable(natives, "enemySeed", settings.startup["rampant-enemySeed"].value) - - natives.enabledMigration = natives.expansion and settings.global["rampant-enableMigration"].value - - upgrade.compareTable(natives, "ENEMY_VARIATIONS", settings.startup["rampant-newEnemyVariations"].value) - upgrade.compareTable(natives, "AI_MAX_SQUAD_COUNT", settings.global["rampant-maxNumberOfSquads"].value) - upgrade.compareTable(natives, "AI_MAX_BUILDER_COUNT", settings.global["rampant-maxNumberOfBuilders"].value) - - return true -end - -local function prepWorld(rebuild, surfaceName) - local upgraded - - if surfaceName then - natives.activeSurface = surfaceName - if rebuild then - global.version = nil - end - end - - upgraded, natives = upgrade.attempt(natives, surfaceName, gameSurfaces) - gameSurfaces = global.gameSurfaces - onModSettingsChange(nil) - if natives.newEnemies then - rebuildNativeTables(natives, game.create_random_generator(natives.enemySeed)) + if natives.NEW_ENEMIES then + rebuildNativeTables(natives, game.create_random_generator(natives.ENEMY_SEED)) else natives.buildingHiveTypeLookup = {} natives.buildingHiveTypeLookup["biter-spawner"] = "biter-spawner" @@ -614,44 +395,17 @@ local function prepWorld(rebuild, surfaceName) natives.buildingHiveTypeLookup["big-worm-turret"] = "turret" natives.buildingHiveTypeLookup["behemoth-worm-turret"] = "turret" end - if upgraded then - rebuildMap() - - map.natives = natives - natives.map = map - - -- queue all current chunks that wont be generated during play - local surface = game.get_surface(natives.activeSurface) - local tick = game.tick - local position = {0,0} - natives.nextChunkSort = 0 - for chunk in surface.get_chunks() do - local x = chunk.x - local y = chunk.y - position[1] = x - position[2] = y - if surface.is_chunk_generated(position) then - onChunkGenerated({ surface = surface, - area = { left_top = { x = x * 32, - y = y * 32}}}) - end - end - - processPendingChunks(map, surface, tick, rebuild, true) - end -end - -local function onConfigChanged() - prepWorld(true, natives.activeSurface) end local function onBuild(event) local entity = event.created_entity or event.entity - if (entity.surface.name == natives.activeSurface) then + if entity.valid then + local native = natives[entity.surface.index] + local map = native.map if (entity.type == "resource") and (entity.force.name == "neutral") then registerResource(entity, map) else - accountPlayerEntity(entity, natives, true, false) + accountPlayerEntity(entity, native, true, false) if natives.safeBuildings then if natives.safeEntities[entity.type] or natives.safeEntities[entity.name] then entity.destructible = false @@ -663,14 +417,15 @@ end local function onMine(event) local entity = event.entity - local surface = entity.surface - if (surface.name == natives.activeSurface) then + if entity.valid then + local native = natives[entity.surface.index] + local map = native.map if (entity.type == "resource") and (entity.force.name == "neutral") then if (entity.amount == 0) then unregisterResource(entity, map) end else - accountPlayerEntity(entity, natives, false, false) + accountPlayerEntity(entity, native, false, false) end end end @@ -679,152 +434,152 @@ local function onDeath(event) local entity = event.entity if entity.valid then local surface = entity.surface - if (surface.name == natives.activeSurface) then - local entityPosition = entity.position - local chunk = getChunkByPosition(map, entityPosition) - local cause = event.cause - local tick = event.tick - local entityType = entity.type - if (entity.force.name == "enemy") then + local native = natives[surface.index] + local map = native.map + local entityPosition = entity.position + local chunk = getChunkByPosition(map, entityPosition) + local cause = event.cause + local tick = event.tick + local entityType = entity.type + if (entity.force.name == "enemy") then - local artilleryBlast = (cause and - ((cause.type == "artillery-wagon") or (cause.type == "artillery-turret"))) + local artilleryBlast = (cause and + ((cause.type == "artillery-wagon") or (cause.type == "artillery-turret"))) - if artilleryBlast then - natives.artilleryBlasts = natives.artilleryBlasts + 1 - end + if artilleryBlast then + native.artilleryBlasts = native.artilleryBlasts + 1 + end - if (entityType == "unit") then - if (chunk ~= -1) and event.force and (event.force.name ~= "enemy") then - -- drop death pheromone where unit died - deathScent(map, chunk) + if (entityType == "unit") then + if (chunk ~= -1) and event.force and (event.force.name ~= "enemy") then + -- drop death pheromone where unit died + deathScent(map, chunk) - if (-getDeathGenerator(map, chunk) < -natives.retreatThreshold) and cause and cause.valid then - retreatUnits(chunk, - cause, - map, - surface, - tick, - (artilleryBlast and RETREAT_SPAWNER_GRAB_RADIUS) or RETREAT_GRAB_RADIUS) - end - - natives.lostEnemyUnits = natives.lostEnemyUnits + 1 - - if (mRandom() < natives.rallyThreshold) and not surface.peaceful_mode then - rallyUnits(chunk, map, tick) - end + if (-getDeathGenerator(map, chunk) < -native.retreatThreshold) and cause and cause.valid then + retreatUnits(chunk, + cause, + map, + tick, + (artilleryBlast and RETREAT_SPAWNER_GRAB_RADIUS) or RETREAT_GRAB_RADIUS) end - elseif event.force and (event.force.name ~= "enemy") and - ((entityType == "unit-spawner") or (entityType == "turret")) then - natives.points = natives.points + - (((entityType == "unit-spawner") and RECOVER_NEST_COST) or RECOVER_WORM_COST) + native.lostEnemyUnits = native.lostEnemyUnits + 1 - unregisterEnemyBaseStructure(map, entity) - - if (chunk ~= -1) then + if (mRandom() < native.rallyThreshold) and not surface.peaceful_mode then rallyUnits(chunk, map, tick) - - if cause and cause.valid then - retreatUnits(chunk, - cause, - map, - surface, - tick, - RETREAT_SPAWNER_GRAB_RADIUS) - end end - else - local entityUnitNumber = entity.unit_number - local pair = natives.drainPylons[entityUnitNumber] - if pair then - local target = pair[1] - local pole = pair[2] - if target == entity then - natives.drainPylons[entityUnitNumber] = nil - if pole.valid then - natives.drainPylons[pole.unit_number] = nil - pole.die() - end - elseif (pole == entity) then - natives.drainPylons[entityUnitNumber] = nil - if target.valid then - natives.drainPylons[target.unit_number] = nil - target.destroy() - end + end + elseif event.force and (event.force.name ~= "enemy") and + ((entityType == "unit-spawner") or (entityType == "turret")) + then + native.points = native.points + + (((entityType == "unit-spawner") and RECOVER_NEST_COST) or RECOVER_WORM_COST) + + unregisterEnemyBaseStructure(map, entity) + + if (chunk ~= -1) then + rallyUnits(chunk, map, tick) + + if cause and cause.valid then + retreatUnits(chunk, + cause, + map, + tick, + RETREAT_SPAWNER_GRAB_RADIUS) + end + end + else + local entityUnitNumber = entity.unit_number + local pair = native.drainPylons[entityUnitNumber] + if pair then + local target = pair[1] + local pole = pair[2] + if target == entity then + native.drainPylons[entityUnitNumber] = nil + if pole.valid then + native.drainPylons[pole.unit_number] = nil + pole.die() + end + elseif (pole == entity) then + native.drainPylons[entityUnitNumber] = nil + if target.valid then + native.drainPylons[target.unit_number] = nil + target.destroy() end end end + end - elseif (entity.force.name ~= "enemy") then - local creditNatives = false - if (event.force ~= nil) and (event.force.name == "enemy") then - creditNatives = true - if (chunk ~= -1) then - victoryScent(map, chunk, entityType) - end + elseif (entity.force.name ~= "enemy") then + local creditNatives = false + if (event.force ~= nil) and (event.force.name == "enemy") then + creditNatives = true + if (chunk ~= -1) then + victoryScent(map, chunk, entityType) + 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] - if conversion then - local newEntity = surface.create_entity({ + 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] + if conversion then + local newEntity = surface.create_entity({ + position=entity.position, + name=convertTypeToDrainCrystal(entity.force.evolution_factor, conversion), + direction=entity.direction + }) + if (conversion == "pole") then + local targetEntity = surface.create_entity({ position=entity.position, - name=convertTypeToDrainCrystal(entity.force.evolution_factor, conversion), + name="pylon-target-rampant", direction=entity.direction }) - if (conversion == "pole") then - local targetEntity = surface.create_entity({position=entity.position, - name="pylon-target-rampant", - direction=entity.direction}) - targetEntity.backer_name = "" - local pair = {targetEntity, newEntity} - natives.drainPylons[targetEntity.unit_number] = pair - natives.drainPylons[newEntity.unit_number] = pair - local wires = entity.neighbours - if wires then - for _,v in pairs(wires.copper) do - if (v.valid) then - newEntity.connect_neighbour(v); - end - end - for _,v in pairs(wires.red) do - if (v.valid) then - newEntity.connect_neighbour({ - wire = DEFINES_WIRE_TYPE_RED, - target_entity = v - }); - end - end - for _,v in pairs(wires.green) do - if (v.valid) then - newEntity.connect_neighbour({ - wire = DEFINES_WIRE_TYPE_GREEN, - target_entity = v - }); - end + targetEntity.backer_name = "" + local pair = {targetEntity, newEntity} + native.drainPylons[targetEntity.unit_number] = pair + native.drainPylons[newEntity.unit_number] = pair + local wires = entity.neighbours + if wires then + for _,v in pairs(wires.copper) do + if (v.valid) then + newEntity.connect_neighbour(v); + end + end + for _,v in pairs(wires.red) do + if (v.valid) then + newEntity.connect_neighbour({ + wire = DEFINES_WIRE_TYPE_RED, + target_entity = v + }); + end + end + for _,v in pairs(wires.green) do + if (v.valid) then + newEntity.connect_neighbour({ + wire = DEFINES_WIRE_TYPE_GREEN, + target_entity = v + }); end end - elseif newEntity.backer_name then - newEntity.backer_name = "" end + elseif newEntity.backer_name then + newEntity.backer_name = "" end end end - elseif (entity.type == "resource") and (entity.force.name == "neutral") then - if (entity.amount == 0) then - unregisterResource(entity, map) - end end - if creditNatives and natives.safeBuildings and - (natives.safeEntities[entityType] or natives.safeEntities[entity.name]) - then - makeImmortalEntity(surface, entity) - else - accountPlayerEntity(entity, natives, false, creditNatives) + elseif (entity.type == "resource") and (entity.force.name == "neutral") then + if (entity.amount == 0) then + unregisterResource(entity, map) end end + if creditNatives and natives.safeBuildings and + (natives.safeEntities[entityType] or natives.safeEntities[entity.name]) + then + makeImmortalEntity(surface, entity) + else + accountPlayerEntity(entity, native, false, creditNatives) + end end end end @@ -832,29 +587,26 @@ end local function onEnemyBaseBuild(event) local entity = event.entity if entity.valid then - local surface = entity.surface - - if (surface.name == natives.activeSurface) then - local chunk = getChunkByPosition(map, entity.position) - if (chunk ~= -1) then - local base - if natives.newEnemies then - base = findNearbyBase(map, chunk) - if not base then - base = createBase(natives, - chunk, - event.tick) - end - entity = upgradeEntity(entity, - surface, - base.alignment, - natives, - nil, - true) - end - if entity and entity.valid then - event.entity = registerEnemyBaseStructure(map, entity, base, surface) + local native = natives[entity.surface.index] + local map = native.map + local chunk = getChunkByPosition(map, entity.position) + if (chunk ~= -1) then + local base + if natives.NEW_ENEMIES then + base = findNearbyBase(map, chunk) + if not base then + base = createBase(native, + chunk, + event.tick) end + entity = upgradeEntity(entity, + base.alignment, + native, + nil, + true) + end + if entity and entity.valid then + event.entity = registerEnemyBaseStructure(map, entity, base) end end end @@ -862,63 +614,62 @@ end local function onSurfaceTileChange(event) local surfaceIndex = event.surface_index or (event.robot and event.robot.surface and event.robot.surface.index) - local surface = game.get_surface(natives.activeSurface) - if (surface.index == surfaceIndex) then - local chunks = {} - local tiles = event.tiles - if event.tile then - if ((event.tile.name == "landfill") or sFind(event.tile.name, "water")) then - for i=1,#tiles do - local position = tiles[i].position - local chunk = getChunkByPosition(map, position) + local map = maps.map[surfaceIndex] + local surface = map.surface + local chunks = {} + local tiles = event.tiles + if event.tile then + if ((event.tile.name == "landfill") or sFind(event.tile.name, "water")) then + for i=1,#tiles do + local position = tiles[i].position + local chunk = getChunkByPosition(map, position) - if (chunk ~= -1) then - map.chunkToPassScan[chunk] = true - else - local x,y = positionToChunkXY(position) - local addMe = true - for ci=1,#chunks do - local c = chunks[ci] - if (c.x == x) and (c.y == y) then - addMe = false - break - end - end - if addMe then - local chunkXY = {x=x,y=y} - chunks[#chunks+1] = chunkXY - onChunkGenerated({area = { left_top = chunkXY }, - surface = surface}) + if (chunk ~= -1) then + map.chunkToPassScan[chunk] = true + else + local x,y = positionToChunkXY(position) + local addMe = true + for ci=1,#chunks do + local c = chunks[ci] + if (c.x == x) and (c.y == y) then + addMe = false + break end end + if addMe then + local chunkXY = {x=x,y=y} + chunks[#chunks+1] = chunkXY + onChunkGenerated({area = { left_top = chunkXY }, + surface = surface}) + end end end - else - for i=1,#tiles do - local tile = tiles[i] - if (tile.name == "landfill") or sFind(tile.name, "water") then - local position = tile.position - local chunk = getChunkByPosition(map, position) + end + else + for i=1,#tiles do + local tile = tiles[i] + if (tile.name == "landfill") or sFind(tile.name, "water") then + local position = tile.position + local chunk = getChunkByPosition(map, position) - if (chunk ~= -1) then - map.chunkToPassScan[chunk] = true - else - local x,y = positionToChunkXY(position) - local addMe = true - for ci=1,#chunks do - local c = chunks[ci] - if (c.x == x) and (c.y == y) then - addMe = false - break - end - end - if addMe then - local chunkXY = {x=x,y=y} - chunks[#chunks+1] = chunkXY - onChunkGenerated({area = { left_top = chunkXY }, - surface = surface}) + if (chunk ~= -1) then + map.chunkToPassScan[chunk] = true + else + local x,y = positionToChunkXY(position) + local addMe = true + for ci=1,#chunks do + local c = chunks[ci] + if (c.x == x) and (c.y == y) then + addMe = false + break end end + if addMe then + local chunkXY = {x=x,y=y} + chunks[#chunks+1] = chunkXY + onChunkGenerated({area = { left_top = chunkXY }, + surface = surface}) + end end end end @@ -927,21 +678,26 @@ end local function onResourceDepleted(event) local entity = event.entity - if (entity.surface.name == natives.activeSurface) then + if entity.valid then + local map = maps.map[entity.surface.index] unregisterResource(entity, map) end end local function onRobotCliff(event) - local surface = event.robot.surface - if (surface.name == natives.activeSurface) and (event.item.name == "cliff-explosives") then - entityForPassScan(map, event.cliff) + local entity = event.robot + if entity.valid then + local map = maps.map[entity.surface.index] + if (event.item.name == "cliff-explosives") then + entityForPassScan(map, event.cliff) + end end end local function onUsedCapsule(event) local surface = game.players[event.player_index].surface - if (surface.name == natives.activeSurface) and (event.item.name == "cliff-explosives") then + local map = maps.map[surface.index] + if (event.item.name == "cliff-explosives") then map.position2Top.x = event.position.x-0.75 map.position2Top.y = event.position.y-0.75 map.position2Bottom.x = event.position.x+0.75 @@ -955,17 +711,17 @@ end local function onRocketLaunch(event) local entity = event.rocket_silo or event.rocket - if entity and entity.valid and (entity.surface.name == natives.activeSurface) then - natives.rocketLaunched = natives.rocketLaunched + 1 - natives.points = natives.points + 5000 + if entity.valid then + local native = natives[entity.surface.index] + native.rocketLaunched = native.rocketLaunched + 1 + native.points = native.points + 5000 end end local function onTriggerEntityCreated(event) local entity = event.entity - if entity.valid and (entity.surface.name == natives.activeSurface) and - (entity.name == "drain-trigger-rampant") - then + if entity.valid and (entity.name == "drain-trigger-rampant") then + local map = maps.map[entity.surface.index] local chunk = getChunkByPosition(map, entity.position) if (chunk ~= -1) then map.chunkToDrained[chunk] = event.tick + 60 @@ -975,42 +731,43 @@ local function onTriggerEntityCreated(event) end local function onInit() - global.map = {} + global.maps = {} global.natives = {} - global.gameSurfaces = {} + global.queriesAndCommands = {} - map = global.map + maps = global.maps + queriesAndCommands = global.queriesAndCommands natives = global.natives - gameSurfaces = global.gameSurfaces - prepWorld(false, "nauvis") hookEvents() + onConfigChanged() + prepWorld(game.surfaces["nauvis"]) end local function onEntitySpawned(event) local entity = event.mine - if natives.newEnemies and entity.valid then - local surface = entity.surface - if (surface.name == natives.activeSurface) and natives.buildingHiveTypeLookup[entity.name] then + if natives.NEW_ENEMIES and entity.valid then + local native = natives[entity.surface.index] + local map = native.map + if natives.buildingHiveTypeLookup[entity.name] then local disPos = mathUtils.distortPosition(entity.position, 8) local chunk = getChunkByPosition(map, disPos) if (chunk ~= -1) then local base = findNearbyBase(map, chunk) if not base then - base = createBase(natives, + base = createBase(native, chunk, event.tick) end entity = upgradeEntity(entity, - surface, base.alignment, - natives, + native, disPos) if entity and entity.valid then - event.entity = registerEnemyBaseStructure(map, entity, base, surface) + event.entity = registerEnemyBaseStructure(map, entity, base) end else entity.destroy() @@ -1021,23 +778,24 @@ end local function onUnitGroupCreated(event) local group = event.group - local surface = group.surface - local squad - if (surface.name == natives.activeSurface) and (group.force.name == "enemy") then + if (group.force.name == "enemy") then + local surface = group.surface + local squad if not group.is_script_driven then + local native = natives[surface.index] if not natives.aiNocturnalMode then local settler = mRandom() < 0.25 and - canMigrate(natives, group.surface) and + canMigrate(native) and (natives.builderCount < natives.AI_MAX_BUILDER_COUNT) if not settler and natives.squadCount > natives.AI_MAX_SQUAD_COUNT then group.destroy() - natives.points = natives.points + AI_SQUAD_COST + native.points = native.points + AI_SQUAD_COST return end squad = createSquad(nil, nil, group, settler) - natives.groupNumberToSquad[group.group_number] = squad + native.groupNumberToSquad[group.group_number] = squad if settler then natives.builderCount = natives.builderCount + 1 @@ -1046,18 +804,18 @@ local function onUnitGroupCreated(event) end else if not (surface.darkness > 0.65) then - natives.points = natives.points + AI_SQUAD_COST + native.points = native.points + AI_SQUAD_COST group.destroy() return end local settler = mRandom() < 0.25 and - canMigrate(natives, group.surface) and + canMigrate(native) and (natives.builderCount < natives.AI_MAX_BUILDER_COUNT) if not settler and natives.squadCount > natives.AI_MAX_SQUAD_COUNT then group.destroy() - natives.points = natives.points + AI_SQUAD_COST + native.points = native.points + AI_SQUAD_COST return end @@ -1077,112 +835,75 @@ local function onGroupFinishedGathering(event) local group = event.group if group.valid and (group.force.name == "enemy") then local unitNumber = group.group_number - if (group.surface.name == natives.activeSurface) then - local squad = natives.groupNumberToSquad[unitNumber] - if squad then - if squad.settler then - if (natives.builderCount < natives.AI_MAX_BUILDER_COUNT) then - squadDispatch(map, group.surface, squad, unitNumber) - else - group.destroy() - natives.points = natives.points + AI_SETTLER_COST - end + local native = natives[group.surface.index] + local map = native.map + local squad = native.groupNumberToSquad[unitNumber] + if squad then + if squad.settler then + if (natives.builderCount < natives.AI_MAX_BUILDER_COUNT) then + squadDispatch(map, squad, unitNumber) else - if (natives.squadCount < natives.AI_MAX_SQUAD_COUNT) then - squadDispatch(map, group.surface, squad, unitNumber) - else - group.destroy() - natives.points = natives.points + AI_SQUAD_COST - end + group.destroy() + native.points = native.points + AI_SETTLER_COST end else - local settler = mRandom() < 0.25 and - canMigrate(natives, group.surface) and - (natives.builderCount < natives.AI_MAX_BUILDER_COUNT) - - if not settler and natives.squadCount > natives.AI_MAX_SQUAD_COUNT then - group.destroy() - natives.points = natives.points + AI_SQUAD_COST - return - end - - squad = createSquad(nil, nil, group, settler) - natives.groupNumberToSquad[group.group_number] = squad - if settler then - natives.builderCount = natives.builderCount + 1 + if (natives.squadCount < natives.AI_MAX_SQUAD_COUNT) then + squadDispatch(map, squad, unitNumber) else - natives.squadCount = natives.squadCount + 1 + group.destroy() + native.points = native.points + AI_SQUAD_COST end - squadDispatch(map, group.surface, squad, unitNumber) end + else + local settler = mRandom() < 0.25 and + canMigrate(native) and + (natives.builderCount < natives.AI_MAX_BUILDER_COUNT) + + if not settler and natives.squadCount > natives.AI_MAX_SQUAD_COUNT then + group.destroy() + native.points = native.points + AI_SQUAD_COST + return + end + + squad = createSquad(nil, nil, group, settler) + native.groupNumberToSquad[group.group_number] = squad + if settler then + natives.builderCount = natives.builderCount + 1 + else + natives.squadCount = natives.squadCount + 1 + end + squadDispatch(map, squad, unitNumber) end end end local function onForceCreated(event) - map.activePlayerForces[#map.activePlayerForces+1] = event.force.name + queriesAndCommands.activePlayerForces[#queriesAndCommands.activePlayerForces+1] = event.force.name end local function onForceMerged(event) - for i=#map.activePlayerForces,1,-1 do - if (map.activePlayerForces[i] == event.source_name) then - tRemove(map.activePlayerForces, i) + for i=#queriesAndCommands.activePlayerForces,1,-1 do + if (queriesAndCommands.activePlayerForces[i] == event.source_name) then + tRemove(queriesAndCommands.activePlayerForces, i) break end end end -local function onSurfaceRenamed(event) - if event.old_name == natives.activeSurface then - natives.activeSurface = event.new_name - end - if (gameSurfaces[event.old_name]) then - gameSurfaces[event.new_name] = gameSurfaces[event.old_name] - gameSurfaces[event.old_name] = nil - end +local function onSurfaceCreated(event) + end local function onSurfaceCleared(event) - local surface = game.get_surface(event.surface_index) - if surface and surface.valid and (surface.name == natives.activeSurface) then - prepWorld(true, natives.activeSurface) - end -end - -local function onPlayerChangedSurface(event) - local player = game.players[event.player_index] - local surface - if player and player.valid and - not settings.get_player_settings(player)["rampant-suppress-surface-change-warnings"].value - then - surface = player.surface - if (natives.activeSurface ~= surface.name) then - local playerName = player.name - local surfaceName = surface.name - local playerSurfaces = gameSurfaces[surfaceName] - if not playerSurfaces then - playerSurfaces = {} - gameSurfaces[surfaceName] = playerSurfaces - player.print({"description.rampant-change-surface", surfaceName, natives.activeSurface}) - playerSurfaces[playerName] = true - elseif not playerSurfaces[playerName] then - player.print({"description.rampant-change-surface", surfaceName, natives.activeSurface}) - playerSurfaces[playerName] = true - end - end - end + local surfaceIndex = event.surface_index + -- maps.map[surfaceIndex] = nil + -- natives[surfaceIndex] = nil end local function onSurfaceDeleted(event) - local surface = game.get_surface(event.surface_index) - if surface and surface.valid then - if (surface.name == natives.activeSurface) then - prepWorld(true, "nauvis") - end - if (gameSurfaces[surface.name]) then - gameSurfaces[surface.name] = nil - end - end + local surfaceIndex = event.surface_index + maps.map[surfaceIndex] = nil + natives[surfaceIndex] = nil end local function onBuilderArrived(event) @@ -1195,106 +916,71 @@ local function onBuilderArrived(event) elseif (builder.force.name ~= "enemy") then return end - local targetPosition = map.position + local targetPosition = queriesAndCommands.position targetPosition.x = builder.position.x targetPosition.y = builder.position.y - builder.surface.create_entity(map.createBuildCloudQuery) + builder.surface.create_entity(queriesAndCommands.createBuildCloudQuery) end -- hooks -script.on_nth_tick(INTERVAL_PASS_SCAN, - function () - processScanChunks(map, - game.get_surface(natives.activeSurface)) -end) - -script.on_nth_tick(INTERVAL_LOGIC, - function (event) - local tick = event.tick - planning(natives, - game.forces.enemy.evolution_factor, - tick) - - if natives.newEnemies then - recycleBases(natives, tick) - end -end) - -script.on_nth_tick(INTERVAL_NEST, - function (event) - processNests(map, - game.get_surface(natives.activeSurface), - event.tick) -end) - - -script.on_nth_tick(INTERVAL_CLEANUP, - function (event) - cleanUpMapTables(map, - event.tick) -end) - -script.on_nth_tick(INTERVAL_SPAWNER, - function (event) - processSpawners(map, - game.get_surface(natives.activeSurface), - event.tick) -end) - -script.on_nth_tick(INTERVAL_VICTORY, - function () - disperseVictoryScent(map) -end) - -script.on_nth_tick(INTERVAL_SQUAD, - function () - processVengence(map, game.get_surface(natives.activeSurface)) -end) - -script.on_nth_tick(INTERVAL_TEMPERAMENT, - function () - temperamentPlanner(natives) -end) - script.on_event(defines.events.on_tick, - function (event) + function () local gameRef = game - local tick = event.tick + local tick = gameRef.tick local pick = tick % 7 - local surface = gameRef.get_surface(natives.activeSurface) -- local profiler = game.create_profiler() + local map = maps.activeMap + if (not map) or (map.processedChunks > map.totalChunks) then + maps.mapIterator, map = next(maps.map, maps.mapIterator) + maps.activeMap = map + print("initial", map, maps.mapIterator) + end + if not map then + print("after", map, maps.mapIterator) + maps.mapIterator, map = next(maps.map, maps.mapIterator) + if not map then + return + end + end + local native = map.native if (pick == 0) then - processPendingChunks(map, - surface, - event.tick) + processPendingChunks(map, tick) + processScanChunks(map) elseif (pick == 1) then - processPlayers(gameRef.connected_players, map, surface, tick) + processPlayers(gameRef.connected_players, map, tick) + cleanUpMapTables(map, tick) elseif (pick == 2) then processMap(map, tick) + planning(natives, native, gameRef.forces.enemy.evolution_factor, tick) + if natives.NEW_ENEMIES then + recycleBases(native, tick) + end elseif (pick == 3) then processStaticMap(map) + disperseVictoryScent(map) + cleanSquads(natives, native) elseif (pick == 4) then - scanResourceMap(map, surface, tick) + scanResourceMap(map, tick) + processVengence(map) elseif (pick == 5) then - scanEnemyMap(map, surface, tick) + scanEnemyMap(map, tick) + processSpawners(map, tick) + temperamentPlanner(native) elseif (pick == 6) then - scanPlayerMap(map, surface, tick) + scanPlayerMap(map, tick) + processNests(map, tick) end - cleanSquads(natives, map.squadIterator) - processActiveNests(map, surface, tick) - + processActiveNests(map, tick) -- game.print({"", "--dispatch4 ", profiler, ", ", game.tick, " ", mRandom()}) end) script.on_event(defines.events.on_surface_cleared, onSurfaceCleared) --- script.on_event(defines.events.on_surface_deleted, onSurfaceDeleted) -script.on_event(defines.events.on_surface_renamed, onSurfaceRenamed) -script.on_event(defines.events.on_player_changed_surface, onPlayerChangedSurface) +script.on_event(defines.events.on_surface_deleted, onSurfaceDeleted) script.on_init(onInit) script.on_load(onLoad) @@ -1321,7 +1007,6 @@ script.on_event({defines.events.on_built_entity, defines.events.script_raised_built, defines.events.script_raised_revive}, onBuild) --- script.on_event(defines.events.on_ai_command_completed, onCommandComplete) script.on_event(defines.events.on_land_mine_armed, onEntitySpawned) script.on_event(defines.events.on_rocket_launched, onRocketLaunch) @@ -1332,7 +1017,6 @@ script.on_event(defines.events.on_unit_group_created, onUnitGroupCreated) script.on_event(defines.events.on_force_created, onForceCreated) script.on_event(defines.events.on_forces_merged, onForceMerged) script.on_event(defines.events.on_unit_group_finished_gathering, onGroupFinishedGathering) --- script.on_event(defines.events.on_unit_removed_from_group, onUnitRemovedFromGroup) script.on_event(defines.events.on_build_base_arrived, onBuilderArrived) @@ -1371,45 +1055,4 @@ remote.add_interface("rampantTests", } ) -interop.setActiveSurface = function (surfaceName) - prepWorld(true, surfaceName) -end -commands.add_command("GetRampantAISurface", - {"description.rampant-get-surface"}, - function () - for _,player in pairs(game.connected_players) do - if (player.valid) then - player.print({"description.rampant-get-surface", - player.surface.name, - natives.activeSurface}) - end - end -end) -commands.add_command("SetRampantAISurface", - {"description.rampant-set-surface"}, - function (event) - local surfaceName = event.parameter - if surfaceName then - if (surfaceName ~= natives.activeSurface) then - if not game.get_surface(surfaceName) then - game.print({"description.rampant-invalid-set-surface", surfaceName}) - else - local surface = game.get_surface(natives.activeSurface) - if surface and surface.valid then - for _,entity in pairs(natives.drainPylons) do - if entity and entity.valid then - entity.destroy() - end - end - end - prepWorld(true, surfaceName) - game.print({"description.rampant-set-surface", surfaceName}) - end - else - game.print({"description.rampant-already-set-surface", surfaceName}) - end - else - game.print({"description.rampant-error-set-surface"}) - end -end) -remote.add_interface("rampant", interop) +-- remote.add_interface("rampant", interop) diff --git a/libs/AIAttackWave.lua b/libs/AIAttackWave.lua index fab6de7..ab7abf5 100755 --- a/libs/AIAttackWave.lua +++ b/libs/AIAttackWave.lua @@ -71,9 +71,9 @@ local getDeathGenerator = chunkPropertyUtils.getDeathGenerator -- module code -local function attackWaveValidCandidate(chunk, natives, map) +local function attackWaveValidCandidate(chunk, native, map) local isValid = getNestActiveness(map, chunk) - if natives.state == AI_STATE_RAIDING then + if native.state == AI_STATE_RAIDING then isValid = isValid + getRaidNestActiveness(map, chunk) end return (isValid > 0) @@ -155,12 +155,12 @@ local function visitPattern(o, cX, cY, distance) end function aiAttackWave.rallyUnits(chunk, map, tick) - if ((tick - getRallyTick(map, chunk) > COOLDOWN_RALLY) and (map.natives.points >= AI_VENGENCE_SQUAD_COST)) then + if ((tick - getRallyTick(map, chunk) > COOLDOWN_RALLY) and (map.native.points >= AI_VENGENCE_SQUAD_COST)) then setRallyTick(map, chunk, tick) local cX = chunk.x local cY = chunk.y local startX, endX, stepX, startY, endY, stepY = visitPattern(tick % 4, cX, cY, RALLY_CRY_DISTANCE) - local vengenceQueue = map.natives.vengenceQueue + local vengenceQueue = map.native.vengenceQueue for x=startX, endX, stepX do for y=startY, endY, stepY do if (x ~= cX) and (y ~= cY) then @@ -181,15 +181,15 @@ function aiAttackWave.rallyUnits(chunk, map, tick) end end -function aiAttackWave.formSettlers(map, surface, chunk) - - local natives = map.natives - if (natives.builderCount < natives.AI_MAX_BUILDER_COUNT) and - (mRandom() < natives.formSquadThreshold) and - ((natives.points - AI_SETTLER_COST) > 0) +function aiAttackWave.formSettlers(map, chunk) + local native = map.native + if (native.builderCount < native.AI_MAX_BUILDER_COUNT) and + (mRandom() < native.formSquadThreshold) and + ((native.points - AI_SETTLER_COST) > 0) then + local surface = map.surface local squadPath, squadDirection - if (natives.state == AI_STATE_SIEGE) then + if (native.state == AI_STATE_SIEGE) then squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), validSiegeSettlerLocation, scoreSiegeSettlerLocation, @@ -214,21 +214,21 @@ function aiAttackWave.formSettlers(map, surface, chunk) if squadPosition then local squad = createSquad(squadPosition, surface, nil, true) - squad.maxDistance = gaussianRandomRange(natives.expansionMaxDistance * 0.5, - natives.expansionMaxDistanceDerivation, + squad.maxDistance = gaussianRandomRange(native.expansionMaxDistance * 0.5, + native.expansionMaxDistanceDerivation, 10, - natives.expansionMaxDistance) + native.expansionMaxDistance) - local scaledWaveSize = settlerWaveScaling(natives) + local scaledWaveSize = settlerWaveScaling(native) map.formGroupCommand.group = squad.group map.formCommand.unit_count = scaledWaveSize local foundUnits = surface.set_multi_command(map.formCommand) if (foundUnits > 0) then - squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, natives) - natives.builderCount = natives.builderCount + 1 - natives.points = natives.points - AI_SETTLER_COST - natives.groupNumberToSquad[squad.groupNumber] = squad + squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, native) + native.builderCount = native.builderCount + 1 + native.points = native.points - AI_SETTLER_COST + native.groupNumberToSquad[squad.groupNumber] = squad else if (squad.group.valid) then squad.group.destroy() @@ -239,12 +239,13 @@ function aiAttackWave.formSettlers(map, surface, chunk) end end -function aiAttackWave.formVengenceSquad(map, surface, chunk) - local natives = map.natives - if (natives.squadCount < natives.AI_MAX_SQUAD_COUNT) and - (mRandom() < natives.formSquadThreshold) and - ((natives.points - AI_VENGENCE_SQUAD_COST) > 0) +function aiAttackWave.formVengenceSquad(map, chunk) + local native = map.native + if (native.squadCount < native.AI_MAX_SQUAD_COUNT) and + (mRandom() < native.formSquadThreshold) and + ((native.points - AI_VENGENCE_SQUAD_COST) > 0) then + local surface = map.surface local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), validUnitGroupLocation, scoreUnitGroupLocation, @@ -263,15 +264,15 @@ function aiAttackWave.formVengenceSquad(map, surface, chunk) squad.rabid = mRandom() < 0.03 - local scaledWaveSize = attackWaveScaling(natives) + local scaledWaveSize = attackWaveScaling(native) map.formGroupCommand.group = squad.group map.formCommand.unit_count = scaledWaveSize local foundUnits = surface.set_multi_command(map.formCommand) if (foundUnits > 0) then - squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, natives) - natives.groupNumberToSquad[squad.groupNumber] = squad - natives.squadCount = natives.squadCount + 1 - natives.points = natives.points - AI_VENGENCE_SQUAD_COST + squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, native) + native.groupNumberToSquad[squad.groupNumber] = squad + native.squadCount = native.squadCount + 1 + native.points = native.points - AI_VENGENCE_SQUAD_COST else if (squad.group.valid) then squad.group.destroy() @@ -282,13 +283,14 @@ function aiAttackWave.formVengenceSquad(map, surface, chunk) end end -function aiAttackWave.formSquads(map, surface, chunk, tick) - local natives = map.natives - if (natives.squadCount < natives.AI_MAX_SQUAD_COUNT) and - attackWaveValidCandidate(chunk, natives, map) and - (mRandom() < natives.formSquadThreshold) and - ((natives.points - AI_SQUAD_COST) > 0) +function aiAttackWave.formSquads(map, chunk, tick) + local native = map.native + if (native.squadCount < native.AI_MAX_SQUAD_COUNT) and + attackWaveValidCandidate(chunk, native, map) and + (mRandom() < native.formSquadThreshold) and + ((native.points - AI_SQUAD_COST) > 0) then + local surface = native.surface local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), validUnitGroupLocation, scoreUnitGroupLocation, @@ -307,17 +309,17 @@ function aiAttackWave.formSquads(map, surface, chunk, tick) squad.rabid = mRandom() < 0.03 - local scaledWaveSize = attackWaveScaling(natives) + local scaledWaveSize = attackWaveScaling(native) map.formGroupCommand.group = squad.group map.formCommand.unit_count = scaledWaveSize local foundUnits = surface.set_multi_command(map.formCommand) if (foundUnits > 0) then - squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, natives) - natives.points = natives.points - AI_SQUAD_COST - natives.squadCount = natives.squadCount + 1 - natives.groupNumberToSquad[squad.groupNumber] = squad - if tick and (natives.state == AI_STATE_AGGRESSIVE) then - natives.canAttackTick = randomTickEvent(tick, + squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, native) + native.points = native.points - AI_SQUAD_COST + native.squadCount = native.squadCount + 1 + native.groupNumberToSquad[squad.groupNumber] = squad + if tick and (native.state == AI_STATE_AGGRESSIVE) then + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) end diff --git a/libs/AIPlanning.lua b/libs/AIPlanning.lua index a3537fc..4dd6022 100755 --- a/libs/AIPlanning.lua +++ b/libs/AIPlanning.lua @@ -54,12 +54,13 @@ local mMin = math.min -- module code -function aiPlanning.planning(natives, evolution_factor, tick) +function aiPlanning.planning(natives, native, evolution_factor, tick) + native.evolutionLevel = evolution_factor natives.evolutionLevel = evolution_factor local maxPoints = mMax(AI_MAX_POINTS * evolution_factor, MINIMUM_AI_POINTS) - if not natives.ranIncompatibleMessage and natives.newEnemies and + if not native.ranIncompatibleMessage and native.newEnemies and (game.active_mods["bobenemies"] or game.active_mods["Natural_Evolution_Enemies"]) then natives.ranIncompatibleMessage = true game.print({"description.rampant-bobs-nee-newEnemies"}) @@ -75,8 +76,8 @@ function aiPlanning.planning(natives, evolution_factor, tick) natives.formSquadThreshold = mMax((0.20 * evolution_factor), 0.05) natives.attackWaveSize = attackWaveMaxSize * (evolution_factor ^ 1.4) - natives.attackWaveDeviation = (natives.attackWaveSize * 0.333) - natives.attackWaveUpperBound = natives.attackWaveSize + (natives.attackWaveSize * 0.35) + natives.attackWaveDeviation = (native.attackWaveSize * 0.333) + natives.attackWaveUpperBound = native.attackWaveSize + (native.attackWaveSize * 0.35) if (natives.attackWaveSize < 1) then natives.attackWaveSize = 2 @@ -85,202 +86,202 @@ function aiPlanning.planning(natives, evolution_factor, tick) end natives.settlerWaveSize = linearInterpolation(evolution_factor ^ 1.66667, - natives.expansionMinSize, - natives.expansionMaxSize) - natives.settlerWaveDeviation = (natives.settlerWaveSize * 0.33) + native.expansionMinSize, + native.expansionMaxSize) + natives.settlerWaveDeviation = (native.settlerWaveSize * 0.33) natives.settlerCooldown = mFloor(linearInterpolation(evolution_factor ^ 1.66667, - natives.expansionMaxTime, - natives.expansionMinTime)) + native.expansionMaxTime, + native.expansionMinTime)) natives.unitRefundAmount = AI_UNIT_REFUND * evolution_factor natives.kamikazeThreshold = NO_RETREAT_BASE_PERCENT + (evolution_factor * NO_RETREAT_EVOLUTION_BONUS_MAX) - local points = mFloor((AI_POINT_GENERATOR_AMOUNT * mRandom()) + (natives.activeNests * 0.25) + - (((AI_POINT_GENERATOR_AMOUNT * 0.7) * (evolution_factor ^ 2.5)) * natives.aiPointsScaler)) + local points = mFloor((AI_POINT_GENERATOR_AMOUNT * mRandom()) + (native.activeNests * 0.25) + + (((AI_POINT_GENERATOR_AMOUNT * 0.7) * (evolution_factor ^ 2.5)) * native.aiPointsScaler)) - if (natives.state == AI_STATE_ONSLAUGHT) then + if (native.state == AI_STATE_ONSLAUGHT) then points = points * 2 end - natives.baseIncrement = points + native.baseIncrement = points - local currentPoints = natives.points + local currentPoints = native.points if (currentPoints < maxPoints) then - natives.points = currentPoints + points + native.points = currentPoints + points end if (currentPoints > maxOverflowPoints) then - natives.points = maxOverflowPoints + native.points = maxOverflowPoints end - if (natives.stateTick <= tick) then - -- local roll = mRandom() * mMax(1 - evolution_factor, 0.15) * natives.aiAggressiveness + if (native.stateTick <= tick) then + -- local roll = mRandom() * mMax(1 - evolution_factor, 0.15) * native.aiAggressiveness local roll = mRandom() - if (natives.temperament < 0.05) then -- 0 - 0.05 + if (native.temperament < 0.05) then -- 0 - 0.05 if natives.enabledMigration then - natives.state = (natives.siegeAIToggle and AI_STATE_SIEGE) or AI_STATE_MIGRATING + native.state = (natives.siegeAIToggle and AI_STATE_SIEGE) or AI_STATE_MIGRATING else if natives.raidAIToggle then if (roll < 0.85) then - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) else - natives.state = AI_STATE_RAIDING + native.state = AI_STATE_RAIDING end else - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) end end - elseif (natives.temperament < 0.20) then -- 0.05 - 0.2 + elseif (native.temperament < 0.20) then -- 0.05 - 0.2 if (natives.enabledMigration) then if (roll < 0.4) then - natives.state = (natives.siegeAIToggle and AI_STATE_SIEGE) or AI_STATE_MIGRATING + native.state = (natives.siegeAIToggle and AI_STATE_SIEGE) or AI_STATE_MIGRATING else - natives.state = AI_STATE_MIGRATING + native.state = AI_STATE_MIGRATING end else if natives.raidAIToggle then if (roll < 0.95) then - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) else - natives.state = AI_STATE_RAIDING + native.state = AI_STATE_RAIDING end else - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) end end - elseif (natives.temperament < 0.4) then -- 0.2 - 0.4 + elseif (native.temperament < 0.4) then -- 0.2 - 0.4 if (natives.enabledMigration) then if (roll < 0.2) then - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) elseif (roll < 0.8) then - natives.state = AI_STATE_MIGRATING + native.state = AI_STATE_MIGRATING else - natives.state = AI_STATE_PEACEFUL + native.state = AI_STATE_PEACEFUL end else if (roll < 0.6) then - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) else - natives.state = AI_STATE_PEACEFUL + native.state = AI_STATE_PEACEFUL end end - elseif (natives.temperament < 0.6) then -- 0.4 - 0.6 + elseif (native.temperament < 0.6) then -- 0.4 - 0.6 if (roll < 0.5) then - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) else - natives.state = AI_STATE_PEACEFUL + native.state = AI_STATE_PEACEFUL end - elseif (natives.temperament < 0.8) then -- 0.6 - 0.8 + elseif (native.temperament < 0.8) then -- 0.6 - 0.8 if (roll < 0.6) then - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) elseif (roll < 0.8) then - natives.state = AI_STATE_ONSLAUGHT + native.state = AI_STATE_ONSLAUGHT else - natives.state = AI_STATE_PEACEFUL + native.state = AI_STATE_PEACEFUL end else -- 0.8 - 1 if (natives.enabledMigration and natives.raidAIToggle) then if (roll < 0.15) then - natives.state = (natives.siegeAIToggle and AI_STATE_SIEGE) or AI_STATE_ONSLAUGHT + native.state = (natives.siegeAIToggle and AI_STATE_SIEGE) or AI_STATE_ONSLAUGHT elseif (roll < 0.6) then - natives.state = AI_STATE_ONSLAUGHT + native.state = AI_STATE_ONSLAUGHT elseif (roll < 0.8) then - natives.state = AI_STATE_RAIDING + native.state = AI_STATE_RAIDING else - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) end elseif (natives.enabledMigration) then if (roll < 0.15) then - natives.state = (natives.siegeAIToggle and AI_STATE_SIEGE) or AI_STATE_ONSLAUGHT + native.state = (natives.siegeAIToggle and AI_STATE_SIEGE) or AI_STATE_ONSLAUGHT elseif (roll < 0.7) then - natives.state = AI_STATE_ONSLAUGHT + native.state = AI_STATE_ONSLAUGHT else - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) end elseif (natives.raidAIToggle) then if (roll < 0.4) then - natives.state = AI_STATE_ONSLAUGHT + native.state = AI_STATE_ONSLAUGHT elseif (roll < 0.7) then - natives.state = AI_STATE_RAIDING + native.state = AI_STATE_RAIDING else - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) end else if (roll < 0.6) then - natives.state = AI_STATE_ONSLAUGHT + native.state = AI_STATE_ONSLAUGHT else - natives.state = AI_STATE_AGGRESSIVE - natives.canAttackTick = randomTickEvent(tick, + native.state = AI_STATE_AGGRESSIVE + native.canAttackTick = randomTickEvent(tick, AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION, AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION) end end end - -- print("changing state", natives.state) + -- print("changing state", native.state) - natives.destroyPlayerBuildings = 0 - natives.lostEnemyUnits = 0 - natives.lostEnemyBuilding = 0 - natives.rocketLaunched = 0 - natives.builtEnemyBuilding = 0 - natives.ionCannonBlasts = 0 - natives.artilleryBlasts = 0 + native.destroyPlayerBuildings = 0 + native.lostEnemyUnits = 0 + native.lostEnemyBuilding = 0 + native.rocketLaunched = 0 + native.builtEnemyBuilding = 0 + native.ionCannonBlasts = 0 + native.artilleryBlasts = 0 - natives.stateTick = randomTickEvent(tick, AI_MIN_STATE_DURATION, AI_MAX_STATE_DURATION) + native.stateTick = randomTickEvent(tick, AI_MIN_STATE_DURATION, AI_MAX_STATE_DURATION) end end -function aiPlanning.temperamentPlanner(natives) - local destroyPlayerBuildings = natives.destroyPlayerBuildings - local lostEnemyUnits = natives.lostEnemyUnits - local lostEnemyBuilding = natives.lostEnemyBuilding - local rocketLaunched = natives.rocketLaunched - local builtEnemyBuilding = natives.builtEnemyBuilding - local ionCannonBlasts = natives.ionCannonBlasts - local artilleryBlasts = natives.artilleryBlasts - local activeNests = natives.activeNests - local activeRaidNests = natives.activeRaidNests +function aiPlanning.temperamentPlanner(native) + local destroyPlayerBuildings = native.destroyPlayerBuildings + local lostEnemyUnits = native.lostEnemyUnits + local lostEnemyBuilding = native.lostEnemyBuilding + local rocketLaunched = native.rocketLaunched + local builtEnemyBuilding = native.builtEnemyBuilding + local ionCannonBlasts = native.ionCannonBlasts + local artilleryBlasts = native.artilleryBlasts + local activeNests = native.activeNests + local activeRaidNests = native.activeRaidNests - local currentTemperament = natives.temperamentScore + local currentTemperament = native.temperamentScore local delta = 0 if activeNests > 0 then @@ -307,15 +308,15 @@ function aiPlanning.temperamentPlanner(natives) if lostEnemyUnits > 0 then local multipler - if natives.evolutionLevel < 0.3 then + if native.evolutionLevel < 0.3 then multipler = 0.0005 - elseif natives.evolutionLevel < 0.5 then + elseif native.evolutionLevel < 0.5 then multipler = 0.000385 - elseif natives.evolutionLevel < 0.7 then + elseif native.evolutionLevel < 0.7 then multipler = 0.00025 - elseif natives.evolutionLevel < 0.9 then + elseif native.evolutionLevel < 0.9 then multipler = 0.00012 - elseif natives.evolutionLevel < 0.9 then + elseif native.evolutionLevel < 0.9 then multipler = 0.00006 end local val = (multipler * lostEnemyUnits) @@ -361,23 +362,23 @@ function aiPlanning.temperamentPlanner(natives) delta = delta + val end - print("temperament", natives.activeNests, natives.activeRaidNests, natives.destroyPlayerBuildings, - natives.lostEnemyUnits, - natives.lostEnemyBuilding, natives.rocketLaunched, natives.builtEnemyBuilding, natives.ionCannonBlasts, - natives.artilleryBlasts) + print("temperament", native.activeNests, native.activeRaidNests, native.destroyPlayerBuildings, + native.lostEnemyUnits, + native.lostEnemyBuilding, native.rocketLaunched, native.builtEnemyBuilding, native.ionCannonBlasts, + native.artilleryBlasts) - -- natives.destroyPlayerBuildings = 0 - -- natives.lostEnemyUnits = 0 - -- natives.lostEnemyBuilding = 0 - -- natives.rocketLaunched = 0 - -- natives.builtEnemyBuilding = 0 - -- natives.ionCannonBlasts = 0 - -- natives.artilleryBlasts = 0 + -- native.destroyPlayerBuildings = 0 + -- native.lostEnemyUnits = 0 + -- native.lostEnemyBuilding = 0 + -- native.rocketLaunched = 0 + -- native.builtEnemyBuilding = 0 + -- native.ionCannonBlasts = 0 + -- native.artilleryBlasts = 0 - natives.temperamentScore = mMin(10000, mMax(-10000, currentTemperament + delta)) - natives.temperament = ((natives.temperamentScore + 10000) * 0.00005) + native.temperamentScore = mMin(10000, mMax(-10000, currentTemperament + delta)) + native.temperament = ((native.temperamentScore + 10000) * 0.00005) - print("tempResult", natives.temperament, natives.temperamentScore) + print("tempResult", native.temperament, native.temperamentScore) print("--") end diff --git a/libs/AIPredicates.lua b/libs/AIPredicates.lua index a24eb60..bea83b2 100755 --- a/libs/AIPredicates.lua +++ b/libs/AIPredicates.lua @@ -19,22 +19,24 @@ local AI_STATE_ONSLAUGHT = constants.AI_STATE_ONSLAUGHT -- module code -function aiPredicates.canAttack(natives, surface, tick) - local goodAI = (((natives.state == AI_STATE_AGGRESSIVE) and (natives.canAttackTick > tick)) or - (natives.state == AI_STATE_RAIDING) or - (natives.state == AI_STATE_ONSLAUGHT)) +function aiPredicates.canAttack(native, tick) + local surface = native.surface + local goodAI = (((native.state == AI_STATE_AGGRESSIVE) and (native.canAttackTick > tick)) or + (native.state == AI_STATE_RAIDING) or + (native.state == AI_STATE_ONSLAUGHT)) local notPeaceful = not surface.peaceful_mode - local noctural = (not natives.aiNocturnalMode) or (natives.aiNocturnalMode and surface.darkness > 0.65) + local noctural = (not native.aiNocturnalMode) or (native.aiNocturnalMode and surface.darkness > 0.65) return goodAI and notPeaceful and noctural end -function aiPredicates.canMigrate(natives, surface) - return ((natives.state == AI_STATE_MIGRATING) or - (natives.state == AI_STATE_SIEGE)) - and natives.expansion +function aiPredicates.canMigrate(native) + local surface = native.surface + return ((native.state == AI_STATE_MIGRATING) or + (native.state == AI_STATE_SIEGE)) + and native.expansion and not surface.peaceful_mode - and ((not natives.aiNocturnalMode) or - (natives.aiNocturnalMode and surface.darkness > 0.65)) + and ((not native.aiNocturnalMode) or + (native.aiNocturnalMode and surface.darkness > 0.65)) end aiPredicatesG = aiPredicates diff --git a/libs/BaseUtils.lua b/libs/BaseUtils.lua index 788b46d..c4fb19e 100755 --- a/libs/BaseUtils.lua +++ b/libs/BaseUtils.lua @@ -72,10 +72,10 @@ local mRandom = math.random -- module code -local function evoToTier(natives, evolutionFactor) +local function evoToTier(native, evolutionFactor) local v for i=10,1,-1 do - if natives.evoToTierMapping[i] <= evolutionFactor then + if native.evoToTierMapping[i] <= evolutionFactor then v = i if mRandom() <= 0.65 then break @@ -94,7 +94,7 @@ function baseUtils.findNearbyBase(map, chunk) return foundBase end - local bases = map.natives.bases + local bases = map.native.bases local closest = MAGIC_MAXIMUM_NUMBER for _, base in pairs(bases) do local distance = euclideanDistancePoints(base.x, base.y, x, y) @@ -107,9 +107,9 @@ function baseUtils.findNearbyBase(map, chunk) return foundBase end -local function findBaseMutation(natives, targetEvolution) - local tier = evoToTier(natives, targetEvolution or natives.evolutionLevel) - local alignments = natives.evolutionTableAlignment[tier] +local function findBaseMutation(native, targetEvolution) + local tier = evoToTier(native, targetEvolution or native.evolutionLevel) + local alignments = native.evolutionTableAlignment[tier] local roll = mRandom() for i=1,#alignments do @@ -124,8 +124,8 @@ local function findBaseMutation(natives, targetEvolution) return alignments[#alignments] end -local function initialEntityUpgrade(baseAlignment, tier, maxTier, natives, useHiveType) - local evolutionTable = natives.buildingEvolveLookup +local function initialEntityUpgrade(baseAlignment, tier, maxTier, native, useHiveType) + local evolutionTable = native.buildingEvolveLookup local entity local useTier @@ -172,9 +172,9 @@ local function initialEntityUpgrade(baseAlignment, tier, maxTier, natives, useHi return entity end -local function entityUpgrade(baseAlignment, tier, maxTier, originalEntity, natives) - local buildingHiveTypeLookup = natives.buildingHiveTypeLookup - local evolutionTable = natives.upgradeLookup +local function entityUpgrade(baseAlignment, tier, maxTier, originalEntity, native) + local buildingHiveTypeLookup = native.buildingHiveTypeLookup + local evolutionTable = native.upgradeLookup local entity local hiveType = buildingHiveTypeLookup[originalEntity.name] @@ -203,66 +203,67 @@ local function entityUpgrade(baseAlignment, tier, maxTier, originalEntity, nativ return entity end -local function findEntityUpgrade(baseAlignment, currentEvo, evoIndex, originalEntity, natives, evolve) +local function findEntityUpgrade(baseAlignment, currentEvo, evoIndex, originalEntity, native, evolve) local adjCurrentEvo = mMax( - ((baseAlignment ~= natives.enemyAlignmentLookup[originalEntity.name]) and 0) or currentEvo, + ((baseAlignment ~= native.enemyAlignmentLookup[originalEntity.name]) and 0) or currentEvo, 0 ) - local tier = evoToTier(natives, adjCurrentEvo) - local maxTier = evoToTier(natives, evoIndex) + local tier = evoToTier(native, adjCurrentEvo) + local maxTier = evoToTier(native, evoIndex) if (tier > maxTier) then return nil end if evolve then - local chunk = getChunkByPosition(natives.map, originalEntity.position) - local makeHive = (chunk ~= -1) and (getResourceGenerator(natives.map, chunk) > 0) and (mRandom() < 0.2) - return initialEntityUpgrade(baseAlignment, tier, maxTier, natives, (makeHive and "hive")) + local chunk = getChunkByPosition(native.map, originalEntity.position) + local makeHive = (chunk ~= -1) and (getResourceGenerator(native.map, chunk) > 0) and (mRandom() < 0.2) + return initialEntityUpgrade(baseAlignment, tier, maxTier, native, (makeHive and "hive")) else - return entityUpgrade(baseAlignment, tier, maxTier, originalEntity, natives) + return entityUpgrade(baseAlignment, tier, maxTier, originalEntity, native) end end -local function findBaseInitialAlignment(natives, evoIndex) +local function findBaseInitialAlignment(native, evoIndex) local dev = evoIndex * 0.3 local evoTop = gaussianRandomRange(evoIndex - dev, dev, 0, evoIndex) local result if mRandom() < 0.05 then - result = {findBaseMutation(natives, evoTop), findBaseMutation(natives, evoTop)} + result = {findBaseMutation(native, evoTop), findBaseMutation(native, evoTop)} else - result = {findBaseMutation(natives, evoTop)} + result = {findBaseMutation(native, evoTop)} end return result end -function baseUtils.recycleBases(natives, tick) - local bases = natives.bases - local id, base = next(bases, natives.map.recycleBaseIterator) - for _=1,2 do - if not id then - natives.map.recycleBaseIterator = nil - return +function baseUtils.recycleBases(native, tick) + local bases = native.bases + local id, base = next(bases, native.map.recycleBaseIterator) + -- for _=1,2 do + if not id then + native.map.recycleBaseIterator = nil + return + else + if ((tick - base.tick) > BASE_COLLECTION_THRESHOLD) then + local nextId + nextId = next(bases, id) + bases[id] = nil + id = nextId else - if ((tick - base.tick) > BASE_COLLECTION_THRESHOLD) then - local nextId - nextId, base = next(bases, id) - bases[id] = nil - id = nextId - else - id, base = next(bases, id) - end + id = next(bases, id) end end - natives.map.recycleBaseIterator = id + -- end + native.map.recycleBaseIterator = id end -function baseUtils.upgradeEntity(entity, surface, baseAlignment, natives, disPos, evolve) +function baseUtils.upgradeEntity(entity, baseAlignment, native, disPos, evolve) + local surface = native.surface local position = entity.position local currentEvo = entity.prototype.build_base_evolution_requirement or 0 @@ -272,19 +273,19 @@ function baseUtils.upgradeEntity(entity, surface, baseAlignment, natives, disPos end local distance = mMin(1, euclideanDistancePoints(position.x, position.y, 0, 0) * BASE_DISTANCE_TO_EVO_INDEX) - local evoIndex = mMax(distance, natives.evolutionLevel) + local evoIndex = mMax(distance, native.evolutionLevel) local spawnerName = findEntityUpgrade(baseAlignment[mRandom(#baseAlignment)], currentEvo, evoIndex, entity, - natives, + native, evolve) if spawnerName then entity.destroy() - local name = natives.buildingSpaceLookup[spawnerName] or spawnerName - local query = natives.map.upgradeEntityQuery + local name = native.buildingSpaceLookup[spawnerName] or spawnerName + local query = native.map.upgradeEntityQuery query.name = name query.position = disPos or position @@ -308,37 +309,38 @@ function baseUtils.upgradeEntity(entity, surface, baseAlignment, natives, disPos return entity end -local function upgradeBase(natives, base) +local function upgradeBase(native, base) local baseAlignment = base.alignment local roll = mRandom() if baseAlignment[2] then if (roll < 0.05) then baseAlignment[2] = nil - baseAlignment[1] = findBaseMutation(natives) + baseAlignment[1] = findBaseMutation(native) elseif (roll < 0.25) then - baseAlignment[1] = findBaseMutation(natives) + baseAlignment[1] = findBaseMutation(native) else - baseAlignment[2] = findBaseMutation(natives) + baseAlignment[2] = findBaseMutation(native) end return true else if (roll < 0.85) then - base.alignment[1] = findBaseMutation(natives) + base.alignment[1] = findBaseMutation(native) else - base.alignment[2] = findBaseMutation(natives) + base.alignment[2] = findBaseMutation(native) end return true end end -function baseUtils.processBase(chunk, surface, natives, tick, base) +function baseUtils.processBase(chunk, native, tick, base) if not base.alignment[1] then base.state = BASE_AI_STATE_DORMANT return end - local map = natives.map + local surface = native.surface + local map = native.map local point = map.position point.x = chunk.x + (CHUNK_SIZE * mRandom()) @@ -346,28 +348,28 @@ function baseUtils.processBase(chunk, surface, natives, tick, base) if (base.state == BASE_AI_STATE_ACTIVE) then local entity = surface.find_entities_filtered(map.filteredEntitiesPointQueryLimited) - local cost = (natives.costLookup[entity.name] or MAGIC_MAXIMUM_NUMBER) + local cost = (native.costLookup[entity.name] or MAGIC_MAXIMUM_NUMBER) if entity and (base.points >= cost) then local newEntity = baseUtils.upgradeEntity(entity, surface, base.alignment, - natives) + native) if newEntity then base.points = base.points - cost end end elseif (base.state == BASE_AI_STATE_MUTATE) then if (base.points >= BASE_UPGRADE) then - if upgradeBase(natives, base) then + if upgradeBase(native, base) then base.points = base.points - BASE_UPGRADE end end end if (base.state == BASE_AI_STATE_OVERDRIVE) then - base.points = base.points + (natives.baseIncrement * 5) + base.points = base.points + (native.baseIncrement * 5) elseif (base.state ~= BASE_AI_STATE_DORMANT) then - base.points = base.points + natives.baseIncrement + base.points = base.points + native.baseIncrement end if (base.temperamentTick <= tick) then @@ -378,8 +380,8 @@ function baseUtils.processBase(chunk, surface, natives, tick, base) end if (base.stateTick <= tick) then - local roll = mRandom() * mMax(1 - natives.evolutionLevel, 0.15) - if (roll > natives.temperament) then + local roll = mRandom() * mMax(1 - native.evolutionLevel, 0.15) + if (roll > native.temperament) then base.state = BASE_AI_STATE_DORMANT else roll = mRandom() @@ -403,7 +405,7 @@ function baseUtils.processBase(chunk, surface, natives, tick, base) base.tick = tick end -function baseUtils.createBase(natives, chunk, tick, rebuilding) +function baseUtils.createBase(native, chunk, tick, rebuilding) local x = chunk.x local y = chunk.y local distance = euclideanDistancePoints(x, y, 0, 0) @@ -411,16 +413,16 @@ function baseUtils.createBase(natives, chunk, tick, rebuilding) local meanLevel = mFloor(distance * 0.005) local distanceIndex = mMin(1, distance * BASE_DISTANCE_TO_EVO_INDEX) - local evoIndex = mMax(distanceIndex, natives.evolutionLevel) + local evoIndex = mMax(distanceIndex, native.evolutionLevel) local baseTick = tick local alignment - if (not rebuilding) and (mRandom() < natives.deadZoneFrequency) then + if (not rebuilding) and (mRandom() < native.deadZoneFrequency) then alignment = {} baseTick = BASE_DEADZONE_TTL else - alignment = findBaseInitialAlignment(natives, evoIndex) or {"neutral"} + alignment = findBaseInitialAlignment(native, evoIndex) or {"neutral"} end local baseLevel = gaussianRandomRange(meanLevel, meanLevel * 0.3, meanLevel * 0.50, meanLevel * 1.50) @@ -442,34 +444,34 @@ function baseUtils.createBase(natives, chunk, tick, rebuilding) createdTick = tick, temperament = 0, points = 0, - id = natives.baseId + id = native.baseId } - natives.baseId = natives.baseId + 1 + native.baseId = native.baseId + 1 - setChunkBase(natives.map, chunk, base) + setChunkBase(native.map, chunk, base) - natives.bases[base.id] = base + native.bases[base.id] = base return base end -function baseUtils.rebuildNativeTables(natives, rg) +function baseUtils.rebuildNativeTables(native, rg) local alignmentSet = {} - natives.evolutionTableAlignment = alignmentSet + native.evolutionTableAlignment = alignmentSet local buildingSpaceLookup = {} - natives.buildingSpaceLookup = buildingSpaceLookup + native.buildingSpaceLookup = buildingSpaceLookup local enemyAlignmentLookup = {} - natives.enemyAlignmentLookup = enemyAlignmentLookup + native.enemyAlignmentLookup = enemyAlignmentLookup local evoToTierMapping = {} - natives.evoToTierMapping = evoToTierMapping + native.evoToTierMapping = evoToTierMapping local upgradeLookup = {} - natives.upgradeLookup = upgradeLookup + native.upgradeLookup = upgradeLookup local buildingEvolveLookup = {} - natives.buildingEvolveLookup = buildingEvolveLookup + native.buildingEvolveLookup = buildingEvolveLookup local costLookup = {} - natives.costLookup = costLookup + native.costLookup = costLookup local buildingHiveTypeLookup = {} - natives.buildingHiveTypeLookup = buildingHiveTypeLookup + native.buildingHiveTypeLookup = buildingHiveTypeLookup for i=1,10 do evoToTierMapping[#evoToTierMapping+1] = (((i - 1) * 0.1) ^ 0.5) - 0.05 @@ -532,7 +534,7 @@ function baseUtils.rebuildNativeTables(natives, rg) end local variationSet = {} - for v=1,natives.ENEMY_VARIATIONS do + for v=1,native.ENEMY_VARIATIONS do local entry = faction.type .. "-" .. building.name .. "-v" .. v .. "-t" .. t .. "-rampant" enemyAlignmentLookup[entry] = faction.type local proxyEntity = "entity-proxy-" .. building.type .. "-t" .. t .. "-rampant" @@ -591,13 +593,13 @@ function baseUtils.rebuildNativeTables(natives, rg) end end - local evoIndex = evoToTier(natives, natives.evolutionLevel) + local evoIndex = evoToTier(native, native.evolutionLevel) - for _,base in pairs(natives.bases) do + for _,base in pairs(native.bases) do for x=1,#base.alignment do local alignment = base.alignment[x] - if not natives.buildingEvolveLookup[alignment] then - base.alignment = findBaseInitialAlignment(natives, evoIndex) + if not native.buildingEvolveLookup[alignment] then + base.alignment = findBaseInitialAlignment(native, evoIndex) break end end diff --git a/libs/ChunkProcessor.lua b/libs/ChunkProcessor.lua index 29920d8..7d612db 100755 --- a/libs/ChunkProcessor.lua +++ b/libs/ChunkProcessor.lua @@ -54,17 +54,18 @@ local function sorter(a, b) return (aDistance < bDistance) end -function chunkProcessor.processPendingChunks(map, surface, tick, rebuilding, flush) +function chunkProcessor.processPendingChunks(map, tick, flush) local processQueue = map.processQueue local pendingChunks = map.pendingChunks - local area = map.area + local surface = map.surface + local area = map.queriesAndCommands.area local topOffset = area[1] local bottomOffset = area[2] local event = next(pendingChunks, map.chunkProcessorIterator) - local endCount = 5 + local endCount = 2 if flush then endCount = table_size(pendingChunks) end @@ -98,7 +99,7 @@ function chunkProcessor.processPendingChunks(map, surface, tick, rebuilding, flu local chunk = createChunk(x, y) - chunk = initialScan(chunk, surface, map, tick, rebuilding) + chunk = initialScan(chunk, map, tick) if (chunk ~= -1) then map[x][y] = chunk @@ -123,8 +124,8 @@ function chunkProcessor.processPendingChunks(map, surface, tick, rebuilding, flu end end -function chunkProcessor.processScanChunks(map, surface) - local area = map.area +function chunkProcessor.processScanChunks(map) + local area = map.queriesAndCommands.area local topOffset = area[1] local bottomOffset = area[2] @@ -144,7 +145,7 @@ function chunkProcessor.processScanChunks(map, surface) bottomOffset[1] = x + CHUNK_SIZE bottomOffset[2] = y + CHUNK_SIZE - chunk = chunkPassScan(chunk, surface, map) + chunk = chunkPassScan(chunk, map) if (chunk == -1) then map[x][y] = nil diff --git a/libs/ChunkPropertyUtils.lua b/libs/ChunkPropertyUtils.lua index 4ccbfac..6d7c573 100755 --- a/libs/ChunkPropertyUtils.lua +++ b/libs/ChunkPropertyUtils.lua @@ -152,7 +152,7 @@ end function chunkPropertyUtils.setRaidNestActiveness(map, chunk, value) if (value <= 0) then if (map.chunkToActiveRaidNest[chunk] ~= nil) then - map.natives.activeRaidNests = map.natives.activeRaidNests - 1 + map.native.activeRaidNests = map.native.activeRaidNests - 1 end if (map.processActiveRaidSpawnerIterator == chunk) then map.processActiveRaidSpawnerIterator = nil @@ -160,7 +160,7 @@ function chunkPropertyUtils.setRaidNestActiveness(map, chunk, value) map.chunkToActiveRaidNest[chunk] = nil else if (map.chunkToActiveRaidNest[chunk] == nil) then - map.natives.activeRaidNests = map.natives.activeRaidNests + 1 + map.native.activeRaidNests = map.native.activeRaidNests + 1 end map.chunkToActiveRaidNest[chunk] = value end @@ -185,7 +185,7 @@ end function chunkPropertyUtils.setNestActiveness(map, chunk, value) if (value <= 0) then if (map.chunkToActiveNest[chunk] ~= nil) then - map.natives.activeNests = map.natives.activeNests - 1 + map.native.activeNests = map.native.activeNests - 1 end if (map.processActiveSpawnerIterator == chunk) then map.processActiveSpawnerIterator = nil @@ -193,7 +193,7 @@ function chunkPropertyUtils.setNestActiveness(map, chunk, value) map.chunkToActiveNest[chunk] = nil else if (map.chunkToActiveNest[chunk] == nil) then - map.natives.activeNests = map.natives.activeNests + 1 + map.native.activeNests = map.native.activeNests + 1 end map.chunkToActiveNest[chunk] = value end @@ -324,12 +324,14 @@ function chunkPropertyUtils.addPlayerBaseGenerator(map, chunk, playerGenerator) map.chunkToPlayerBase[chunk] = (map.chunkToPlayerBase[chunk] or 0) + playerGenerator end -function chunkPropertyUtils.processNestActiveness(map, chunk, natives, surface) +function chunkPropertyUtils.processNestActiveness(map, chunk) local nests = chunkPropertyUtils.getNestCount(map, chunk) if (nests > 0) then + local native = map.native + local surface = native.surface local activeness = chunkPropertyUtils.getNestActiveness(map, chunk) local raidActiveness = chunkPropertyUtils.getRaidNestActiveness(map, chunk) - if natives.attackUsePlayer and (chunk[PLAYER_PHEROMONE] > natives.attackPlayerThreshold) then + if native.attackUsePlayer and (chunk[PLAYER_PHEROMONE] > native.attackPlayerThreshold) then chunkPropertyUtils.setNestActiveness(map, chunk, mMin(activeness + 5, 20)) elseif (chunk[BASE_PHEROMONE] > 0) then local position = map.position diff --git a/libs/ChunkUtils.lua b/libs/ChunkUtils.lua index c54f17b..e57dd6e 100755 --- a/libs/ChunkUtils.lua +++ b/libs/ChunkUtils.lua @@ -89,7 +89,7 @@ local mFloor = math.floor local function getEntityOverlapChunks(map, entity) local boundingBox = entity.prototype.collision_box or entity.prototype.selection_box; - local overlapArray = map.chunkOverlapArray + local overlapArray = map.queriesAndCommands.chunkOverlapArray overlapArray[1] = -1 --LeftTop overlapArray[2] = -1 --RightTop @@ -129,14 +129,16 @@ local function getEntityOverlapChunks(map, entity) return overlapArray end -local function scanPaths(chunk, surface, map) +local function scanPaths(chunk, map) + local surface = map.surface local pass = CHUNK_IMPASSABLE local x = chunk.x local y = chunk.y - local filteredEntitiesCliffQuery = map.filteredEntitiesCliffQuery - local filteredTilesPathQuery = map.filteredTilesPathQuery + local queriesAndCommands = map.queriesAndCommands + local filteredEntitiesCliffQuery = queriesAndCommands.filteredEntitiesCliffQuery + local filteredTilesPathQuery = queriesAndCommands.filteredTilesPathQuery local count_entities_filtered = surface.count_entities_filtered local count_tiles_filtered = surface.count_tiles_filtered @@ -183,53 +185,57 @@ local function scanPaths(chunk, surface, map) return pass end -local function scorePlayerBuildings(surface, map) - if surface.count_entities_filtered(map.hasPlayerStructuresQuery) > 0 then - return (surface.count_entities_filtered(map.filteredEntitiesPlayerQueryLowest) * GENERATOR_PHEROMONE_LEVEL_1) + - (surface.count_entities_filtered(map.filteredEntitiesPlayerQueryLow) * GENERATOR_PHEROMONE_LEVEL_3) + - (surface.count_entities_filtered(map.filteredEntitiesPlayerQueryHigh) * GENERATOR_PHEROMONE_LEVEL_5) + - (surface.count_entities_filtered(map.filteredEntitiesPlayerQueryHighest) * GENERATOR_PHEROMONE_LEVEL_6) +local function scorePlayerBuildings(map) + local surface = map.surface + local queriesAndCommands = map.queriesAndCommands + if surface.count_entities_filtered(queriesAndCommands.hasPlayerStructuresQuery) > 0 then + return (surface.count_entities_filtered(queriesAndCommands.filteredEntitiesPlayerQueryLowest) * GENERATOR_PHEROMONE_LEVEL_1) + + (surface.count_entities_filtered(queriesAndCommands.filteredEntitiesPlayerQueryLow) * GENERATOR_PHEROMONE_LEVEL_3) + + (surface.count_entities_filtered(queriesAndCommands.filteredEntitiesPlayerQueryHigh) * GENERATOR_PHEROMONE_LEVEL_5) + + (surface.count_entities_filtered(queriesAndCommands.filteredEntitiesPlayerQueryHighest) * GENERATOR_PHEROMONE_LEVEL_6) end return 0 end -function chunkUtils.initialScan(chunk, surface, map, tick, rebuilding) - local waterTiles = (1 - (surface.count_tiles_filtered(map.filteredTilesQuery) * 0.0009765625)) * 0.80 - local natives = map.natives - local enemyBuildings = surface.find_entities_filtered(map.filteredEntitiesEnemyStructureQuery) +function chunkUtils.initialScan(chunk, map, tick) + local surface = map.surface + local queriesAndCommands = map.queriesAndCommands + local waterTiles = (1 - (surface.count_tiles_filtered(queriesAndCommands.filteredTilesQuery) * 0.0009765625)) * 0.80 + local native = map.native + local enemyBuildings = surface.find_entities_filtered(queriesAndCommands.filteredEntitiesEnemyStructureQuery) if (waterTiles >= CHUNK_PASS_THRESHOLD) or (#enemyBuildings > 0) then local neutralObjects = mMax(0, - mMin(1 - (surface.count_entities_filtered(map.filteredEntitiesChunkNeutral) * 0.005), + mMin(1 - (surface.count_entities_filtered(queriesAndCommands.filteredEntitiesChunkNeutral) * 0.005), 1) * 0.20) - local pass = scanPaths(chunk, surface, map) + local pass = scanPaths(chunk, map) - local playerObjects = scorePlayerBuildings(surface, map) + local playerObjects = scorePlayerBuildings(map) if ((playerObjects > 0) or (#enemyBuildings > 0)) and (pass == CHUNK_IMPASSABLE) then pass = CHUNK_ALL_DIRECTIONS end if (pass ~= CHUNK_IMPASSABLE) then - local resources = surface.count_entities_filtered(map.countResourcesQuery) * RESOURCE_NORMALIZER + local resources = surface.count_entities_filtered(queriesAndCommands.countResourcesQuery) * RESOURCE_NORMALIZER - local buildingHiveTypeLookup = natives.buildingHiveTypeLookup + local buildingHiveTypeLookup = native.buildingHiveTypeLookup local counts = map.chunkScanCounts for i=1,#HIVE_BUILDINGS_TYPES do counts[HIVE_BUILDINGS_TYPES[i]] = 0 end if (#enemyBuildings > 0) then - if natives.newEnemies then + if native.newEnemies then local base = findNearbyBase(map, chunk) if base then setChunkBase(map, chunk, base) else - base = createBase(natives, chunk, tick, rebuilding) + base = createBase(native, chunk, tick) end local alignment = base.alignment - local unitList = surface.find_entities_filtered(map.filteredEntitiesUnitQuery) + local unitList = surface.find_entities_filtered(queriesAndCommands.filteredEntitiesUnitQuery) for i=1,#unitList do local unit = unitList[i] if (unit.valid) then @@ -240,7 +246,7 @@ function chunkUtils.initialScan(chunk, surface, map, tick, rebuilding) for i = 1, #enemyBuildings do local enemyBuilding = enemyBuildings[i] if not isRampant(enemyBuilding.name) then - local newEntity = upgradeEntity(enemyBuilding, surface, alignment, natives, nil, true) + local newEntity = upgradeEntity(enemyBuilding, surface, alignment, native, nil, true) if newEntity then local hiveType = buildingHiveTypeLookup[newEntity.name] counts[hiveType] = counts[hiveType] + 1 @@ -286,14 +292,16 @@ function chunkUtils.initialScan(chunk, surface, map, tick, rebuilding) return -1 end -function chunkUtils.chunkPassScan(chunk, surface, map) - local waterTiles = (1 - (surface.count_tiles_filtered(map.filteredTilesQuery) * 0.0009765625)) * 0.80 +function chunkUtils.chunkPassScan(chunk, map) + local surface = map.surface + local queriesAndCommands = map.queriesAndCommands + local waterTiles = (1 - (surface.count_tiles_filtered(queriesAndCommands.filteredTilesQuery) * 0.0009765625)) * 0.80 if (waterTiles >= CHUNK_PASS_THRESHOLD) then local neutralObjects = mMax(0, - mMin(1 - (surface.count_entities_filtered(map.filteredEntitiesChunkNeutral) * 0.005), + mMin(1 - (surface.count_entities_filtered(queriesAndCommands.filteredEntitiesChunkNeutral) * 0.005), 1) * 0.20) - local pass = scanPaths(chunk, surface, map) + local pass = scanPaths(chunk, map) local playerObjects = getPlayerBaseGenerator(map, chunk) @@ -312,24 +320,27 @@ function chunkUtils.chunkPassScan(chunk, surface, map) return -1 end -function chunkUtils.mapScanPlayerChunk(chunk, surface, map) - local playerObjects = scorePlayerBuildings(surface, map) +function chunkUtils.mapScanPlayerChunk(chunk, map) + local playerObjects = scorePlayerBuildings(map) setPlayerBaseGenerator(map, chunk, playerObjects) end -function chunkUtils.mapScanResourceChunk(chunk, surface, map) - local resources = surface.count_entities_filtered(map.countResourcesQuery) * RESOURCE_NORMALIZER +function chunkUtils.mapScanResourceChunk(chunk, map) + local surface = map.surface + local queriesAndCommands = map.queriesAndCommands + local resources = surface.count_entities_filtered(queriesAndCommands.countResourcesQuery) * RESOURCE_NORMALIZER setResourceGenerator(map, chunk, resources) - local waterTiles = (1 - (surface.count_tiles_filtered(map.filteredTilesQuery) * 0.0009765625)) * 0.80 + local waterTiles = (1 - (surface.count_tiles_filtered(queriesAndCommands.filteredTilesQuery) * 0.0009765625)) * 0.80 local neutralObjects = mMax(0, - mMin(1 - (surface.count_entities_filtered(map.filteredEntitiesChunkNeutral) * 0.005), + mMin(1 - (surface.count_entities_filtered(queriesAndCommands.filteredEntitiesChunkNeutral) * 0.005), 1) * 0.20) setPathRating(map, chunk, waterTiles + neutralObjects) end -function chunkUtils.mapScanEnemyChunk(chunk, surface, map) - local buildingHiveTypeLookup = map.natives.buildingHiveTypeLookup - local buildings = surface.find_entities_filtered(map.filteredEntitiesEnemyStructureQuery) +function chunkUtils.mapScanEnemyChunk(chunk, map) + local buildingHiveTypeLookup = map.native.buildingHiveTypeLookup + local queriesAndCommands = map.queriesAndCommands + local buildings = map.surface.find_entities_filtered(queriesAndCommands.filteredEntitiesEnemyStructureQuery) local counts = map.chunkScanCounts for i=1,#HIVE_BUILDINGS_TYPES do counts[HIVE_BUILDINGS_TYPES[i]] = 0 @@ -407,42 +418,42 @@ function chunkUtils.colorXY(x, y, surface, color) end -function chunkUtils.registerEnemyBaseStructure(map, entity, base, surface) +function chunkUtils.registerEnemyBaseStructure(map, entity, base) local entityType = entity.type if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then local overlapArray = getEntityOverlapChunks(map, entity) - local natives = map.natives + local native = map.native local getFunc local setFunc - local hiveTypeLookup = natives.buildingHiveTypeLookup + local hiveTypeLookup = native.buildingHiveTypeLookup local hiveType = hiveTypeLookup[entity.name] if (hiveType == "spitter-spawner") or (hiveType == "biter-spawner") then - natives.builtEnemyBuilding = natives.builtEnemyBuilding + 1 + native.builtEnemyBuilding = native.builtEnemyBuilding + 1 getFunc = getNestCount setFunc = setNestCount elseif (hiveType == "turret") then - natives.builtEnemyBuilding = natives.builtEnemyBuilding + 1 + native.builtEnemyBuilding = native.builtEnemyBuilding + 1 getFunc = getTurretCount setFunc = setTurretCount elseif (hiveType == "trap") then getFunc = getTrapCount setFunc = setTrapCount elseif (hiveType == "utility") then - natives.builtEnemyBuilding = natives.builtEnemyBuilding + 1 + native.builtEnemyBuilding = native.builtEnemyBuilding + 1 getFunc = getUtilityCount setFunc = setUtilityCount elseif (hiveType == "hive") then - natives.builtEnemyBuilding = natives.builtEnemyBuilding + 1 + native.builtEnemyBuilding = native.builtEnemyBuilding + 1 getFunc = getHiveCount setFunc = setHiveCount else if (entityType == "turret") then - natives.builtEnemyBuilding = natives.builtEnemyBuilding + 1 + native.builtEnemyBuilding = native.builtEnemyBuilding + 1 getFunc = getTurretCount setFunc = setTurretCount elseif (entityType == "unit-spawner") then - natives.builtEnemyBuilding = natives.builtEnemyBuilding + 1 + native.builtEnemyBuilding = native.builtEnemyBuilding + 1 getFunc = getNestCount setFunc = setNestCount end @@ -453,7 +464,7 @@ function chunkUtils.registerEnemyBaseStructure(map, entity, base, surface) if (chunk ~= -1) then setFunc(map, chunk, getFunc(map, chunk) + 1) setChunkBase(map, chunk, base) - processNestActiveness(map, chunk, natives, surface) + processNestActiveness(map, chunk) end end end @@ -466,38 +477,38 @@ function chunkUtils.unregisterEnemyBaseStructure(map, entity) if ((entityType == "unit-spawner") or (entityType == "turret")) and (entity.force.name == "enemy") then local overlapArray = getEntityOverlapChunks(map, entity) - local natives = map.natives + local native = map.native local getFunc local setFunc - local hiveTypeLookup = map.natives.buildingHiveTypeLookup + local hiveTypeLookup = map.native.buildingHiveTypeLookup local hiveType = hiveTypeLookup[entity.name] if (hiveType == "spitter-spawner") or (hiveType == "biter-spawner") then - natives.lostEnemyBuilding = natives.lostEnemyBuilding + 1 + native.lostEnemyBuilding = native.lostEnemyBuilding + 1 getFunc = getNestCount setFunc = setNestCount elseif (hiveType == "turret") then - natives.lostEnemyBuilding = natives.lostEnemyBuilding + 1 + native.lostEnemyBuilding = native.lostEnemyBuilding + 1 getFunc = getTurretCount setFunc = setTurretCount elseif (hiveType == "trap") then getFunc = getTrapCount setFunc = setTrapCount elseif (hiveType == "utility") then - natives.lostEnemyBuilding = natives.lostEnemyBuilding + 1 + native.lostEnemyBuilding = native.lostEnemyBuilding + 1 getFunc = getUtilityCount setFunc = setUtilityCount elseif (hiveType == "hive") then - natives.lostEnemyBuilding = natives.lostEnemyBuilding + 1 + native.lostEnemyBuilding = native.lostEnemyBuilding + 1 getFunc = getHiveCount setFunc = setHiveCount else if (entityType == "turret") then - natives.lostEnemyBuilding = natives.lostEnemyBuilding + 1 + native.lostEnemyBuilding = native.lostEnemyBuilding + 1 getFunc = getTurretCount setFunc = setTurretCount elseif (entityType == "unit-spawner") then hiveType = "biter-spawner" - natives.lostEnemyBuilding = natives.lostEnemyBuilding + 1 + native.lostEnemyBuilding = native.lostEnemyBuilding + 1 getFunc = getNestCount setFunc = setNestCount end @@ -527,19 +538,19 @@ function chunkUtils.unregisterEnemyBaseStructure(map, entity) end end -function chunkUtils.accountPlayerEntity(entity, natives, addObject, creditNatives) +function chunkUtils.accountPlayerEntity(entity, native, addObject, creditNatives) if (BUILDING_PHEROMONES[entity.type] ~= nil) and (entity.force.name ~= "enemy") then - local map = natives.map + local map = native.map local entityValue = BUILDING_PHEROMONES[entity.type] local overlapArray = getEntityOverlapChunks(map, entity) if not addObject then if creditNatives then - natives.destroyPlayerBuildings = natives.destroyPlayerBuildings + 1 - if (natives.state == AI_STATE_ONSLAUGHT) then - natives.points = natives.points + entityValue + native.destroyPlayerBuildings = native.destroyPlayerBuildings + 1 + if (native.state == AI_STATE_ONSLAUGHT) then + native.points = native.points + entityValue else - natives.points = natives.points + (entityValue * 0.12) + native.points = native.points + (entityValue * 0.12) end end entityValue = -entityValue diff --git a/libs/Constants.lua b/libs/Constants.lua index 4964c7b..d0068f0 100755 --- a/libs/Constants.lua +++ b/libs/Constants.lua @@ -48,7 +48,7 @@ constants.SCAN_QUEUE_SIZE = 2 constants.RESOURCE_QUEUE_SIZE = 7 constants.ENEMY_QUEUE_SIZE = 7 constants.PLAYER_QUEUE_SIZE = 7 -constants.CLEANUP_QUEUE_SIZE = 15 +constants.CLEANUP_QUEUE_SIZE = 8 constants.ATTACK_QUEUE_SIZE = 18 constants.BASE_QUEUE_SIZE = 1 constants.PROCESS_STATIC_QUEUE_SIZE = 20 @@ -64,16 +64,16 @@ constants.CHUNK_PASS_THRESHOLD = 0.2 -- constants.INTERVAL_MAP_PROCESS = 5 -- constants.INTERVAL_MAP_STATIC_PROCESS = 11 -- constants.INTERVAL_SCAN = 19 -constants.INTERVAL_CHUNK_PROCESS = 23 -constants.INTERVAL_LOGIC = 59 -constants.INTERVAL_TEMPERAMENT = 121 -constants.INTERVAL_SQUAD = 14 -constants.INTERVAL_NEST = 16 -constants.INTERVAL_PASS_SCAN = 29 +-- constants.INTERVAL_CHUNK_PROCESS = 23 +-- constants.INTERVAL_LOGIC = 59 +-- constants.INTERVAL_TEMPERAMENT = 121 +-- constants.INTERVAL_SQUAD = 14 +-- constants.INTERVAL_NEST = 16 +-- constants.INTERVAL_PASS_SCAN = 29 -- constants.INTERVAL_RESQUAD = 101 -constants.INTERVAL_SPAWNER = 19 -constants.INTERVAL_VICTORY = 10 -constants.INTERVAL_CLEANUP = 34 +-- constants.INTERVAL_SPAWNER = 19 +-- constants.INTERVAL_VICTORY = 10 +-- constants.INTERVAL_CLEANUP = 34 constants.COOLDOWN_RALLY = constants.TICKS_A_SECOND * 10 constants.COOLDOWN_RETREAT = constants.TICKS_A_SECOND * 10 diff --git a/libs/Interop.lua b/libs/Interop.lua index 60b162e..9f44299 100755 --- a/libs/Interop.lua +++ b/libs/Interop.lua @@ -3,91 +3,91 @@ if interopG then end local interop = {} -function interop.addAIPoints(value) - global.natives.points = global.natives.points + value -end +-- function interop.addAIPoints(value) +-- global.natives.points = global.natives.points + value +-- end -function interop.getAIPoints() - return global.natives.points -end +-- function interop.getAIPoints() +-- return global.natives.points +-- end -function interop.setNocturnalMode(flag) - global.natives.aiNocturnalMode = flag -end +-- function interop.setNocturnalMode(flag) +-- global.natives.aiNocturnalMode = flag +-- end -function interop.getNocturnalMode() - return global.natives.aiNocturnalMode -end +-- function interop.getNocturnalMode() +-- return global.natives.aiNocturnalMode +-- end -function interop.setPointsPerCycleScaling(scale) - global.natives.aiPointsScaler = scale -end +-- function interop.setPointsPerCycleScaling(scale) +-- global.natives.aiPointsScaler = scale +-- end -function interop.getPointsPerCycleScaling() - return global.natives.aiPointsScaler -end +-- function interop.getPointsPerCycleScaling() +-- return global.natives.aiPointsScaler +-- end -function interop.changeState(aiState) - global.natives.state = aiState -end +-- function interop.changeState(aiState) +-- global.natives.state = aiState +-- end -function interop.getState() - return global.natives.state -end +-- function interop.getState() +-- return global.natives.state +-- end -function interop.getNextStateTick() - return global.natives.stateTick -end +-- function interop.getNextStateTick() +-- return global.natives.stateTick +-- end -function interop.getMaxWaveSize() - return global.natives.attackWaveMaxSize -end +-- function interop.getMaxWaveSize() +-- return global.natives.attackWaveMaxSize +-- end -function interop.getThresholds() - return global.natives.attackThresholdMin, global.natives.attackThresholdMax -end +-- function interop.getThresholds() +-- return global.natives.attackThresholdMin, global.natives.attackThresholdMax +-- end -function interop.changeMaxWaveSize(waveSize) - global.natives.attackWaveMaxSize = waveSize -end +-- function interop.changeMaxWaveSize(waveSize) +-- global.natives.attackWaveMaxSize = waveSize +-- end -function interop.getSettlerCooldown() - return global.natives.settlerCooldown -end +-- function interop.getSettlerCooldown() +-- return global.natives.settlerCooldown +-- end -function interop.getSettlerWaveSize() - return global.natives.settlerWaveSize -end +-- function interop.getSettlerWaveSize() +-- return global.natives.settlerWaveSize +-- end -function interop.changeThreshold(min, max) - global.natives.attackThresholdMin = min - global.natives.attackThresholdMax = max - global.natives.attackThresholdRange = max - min -end +-- function interop.changeThreshold(min, max) +-- global.natives.attackThresholdMin = min +-- global.natives.attackThresholdMax = max +-- global.natives.attackThresholdRange = max - min +-- end -function interop.changePlayerThreshold(value) - global.natives.attackPlayerThreshold = value -end +-- function interop.changePlayerThreshold(value) +-- global.natives.attackPlayerThreshold = value +-- end -function interop.getPlayerThreshold() - return global.natives.attackPlayerThreshold -end +-- function interop.getPlayerThreshold() +-- return global.natives.attackPlayerThreshold +-- end -function interop.changeAttackUsePollution(bool) - global.natives.attackUsePollution = bool -end +-- function interop.changeAttackUsePollution(bool) +-- global.natives.attackUsePollution = bool +-- end -function interop.changeAttackUsePlayer(bool) - global.natives.attackUsePlayer = bool -end +-- function interop.changeAttackUsePlayer(bool) +-- global.natives.attackUsePlayer = bool +-- end -function interop.getAttackUsePollution() - return global.natives.attackUsePollution -end +-- function interop.getAttackUsePollution() +-- return global.natives.attackUsePollution +-- end -function interop.getAttackUsePlayer() - return global.natives.attackUsePlayer -end +-- function interop.getAttackUsePlayer() +-- return global.natives.attackUsePlayer +-- end -- function interop.registerUnitGroup(unitGroup, isSettler) -- local squad = unitGroupUtils.createSquad(unitGroup.position, unitGroup.surface, unitGroup, isSettler) diff --git a/libs/MapProcessor.lua b/libs/MapProcessor.lua index b070bd2..f96b848 100755 --- a/libs/MapProcessor.lua +++ b/libs/MapProcessor.lua @@ -178,7 +178,7 @@ end local function queueNestSpawners(map, chunk, tick) local limitPerActiveChunkTick = - (map.natives.activeNests + map.natives.activeRaidNests) * DURATION_ACTIVE_NEST_DIVIDER + (map.native.activeNests + map.native.activeRaidNests) * DURATION_ACTIVE_NEST_DIVIDER local processActiveNest = map.processActiveNest @@ -220,24 +220,24 @@ end vs the slower passive version processing the entire map in multiple passes. --]] -function mapProcessor.processPlayers(players, map, surface, tick) +function mapProcessor.processPlayers(players, map, tick) -- put down player pheromone for player hunters -- randomize player order to ensure a single player isn't singled out - local natives = map.natives + local native = map.native - local allowingAttacks = canAttack(natives, surface, tick) + local allowingAttacks = canAttack(native, tick) -- not looping everyone because the cost is high enough already in multiplayer if (#players > 0) then local player = players[mRandom(#players)] - if validPlayer(player, natives) then + if validPlayer(player, native) then local playerChunk = getChunkByPosition(map, player.character.position) if (playerChunk ~= -1) then local vengence = allowingAttacks and - (natives.points >= AI_VENGENCE_SQUAD_COST) and + (native.points >= AI_VENGENCE_SQUAD_COST) and ((getEnemyStructureCount(map, playerChunk) > 0) or - (-getDeathGenerator(map, playerChunk) < -natives.retreatThreshold)) + (-getDeathGenerator(map, playerChunk) < -native.retreatThreshold)) for x=playerChunk.x - PROCESS_PLAYER_BOUND, playerChunk.x + PROCESS_PLAYER_BOUND, 32 do for y=playerChunk.y - PROCESS_PLAYER_BOUND, playerChunk.y + PROCESS_PLAYER_BOUND, 32 do @@ -248,16 +248,16 @@ function mapProcessor.processPlayers(players, map, surface, tick) processPheromone(map, chunk, true) if (getNestCount(map, chunk) > 0) then - processNestActiveness(map, chunk, natives, surface) + processNestActiveness(map, chunk) queueNestSpawners(map, chunk, tick) if vengence then - local count = natives.vengenceQueue[chunk] + local count = native.vengenceQueue[chunk] if not count then count = 0 - natives.vengenceQueue[chunk] = count + native.vengenceQueue[chunk] = count end - natives.vengenceQueue[chunk] = count + 1 + native.vengenceQueue[chunk] = count + 1 end end end @@ -269,7 +269,7 @@ function mapProcessor.processPlayers(players, map, surface, tick) for i=1,#players do local player = players[i] - if validPlayer(player, natives) then + if validPlayer(player, native) then local playerChunk = getChunkByPosition(map, player.character.position) if (playerChunk ~= -1) then @@ -323,7 +323,7 @@ end --[[ Passive scan to find entities that have been generated outside the factorio event system --]] -function mapProcessor.scanPlayerMap(map, surface, tick) +function mapProcessor.scanPlayerMap(map, tick) if (map.nextProcessMap == tick) or (map.nextPlayerScan == tick) or (map.nextEnemyScan == tick) or (map.nextChunkProcess == tick) then @@ -351,7 +351,7 @@ function mapProcessor.scanPlayerMap(map, surface, tick) offset[1] = chunk.x + CHUNK_SIZE offset[2] = chunk.y + CHUNK_SIZE - mapScanPlayerChunk(chunk, surface, map) + mapScanPlayerChunk(chunk, map) end if (endIndex == processQueueLength) then @@ -361,7 +361,7 @@ function mapProcessor.scanPlayerMap(map, surface, tick) end end -function mapProcessor.scanEnemyMap(map, surface, tick) +function mapProcessor.scanEnemyMap(map, tick) if (map.nextProcessMap == tick) or (map.nextPlayerScan == tick) or (map.nextChunkProcess == tick) then return end @@ -388,7 +388,7 @@ function mapProcessor.scanEnemyMap(map, surface, tick) offset[1] = chunk.x + CHUNK_SIZE offset[2] = chunk.y + CHUNK_SIZE - mapScanEnemyChunk(chunk, surface, map) + mapScanEnemyChunk(chunk, map) end if (endIndex == processQueueLength) then @@ -398,7 +398,7 @@ function mapProcessor.scanEnemyMap(map, surface, tick) end end -function mapProcessor.scanResourceMap(map, surface, tick) +function mapProcessor.scanResourceMap(map, tick) if (map.nextProcessMap == tick) or (map.nextPlayerScan == tick) or (map.nextEnemyScan == tick) or (map.nextChunkProcess == tick) then @@ -426,7 +426,7 @@ function mapProcessor.scanResourceMap(map, surface, tick) offset[1] = chunk.x + CHUNK_SIZE offset[2] = chunk.y + CHUNK_SIZE - mapScanResourceChunk(chunk, surface, map) + mapScanResourceChunk(chunk, map) end if (endIndex == processQueueLength) then @@ -436,15 +436,14 @@ function mapProcessor.scanResourceMap(map, surface, tick) end end -function mapProcessor.processActiveNests(map, surface, tick) +function mapProcessor.processActiveNests(map, tick) local processActiveNest = map.processActiveNest local slot = processActiveNest[tick] if slot then - local natives = map.natives for i=1,#slot do local chunk = slot[i] if (getNestActiveness(map, chunk) > 0) or (getRaidNestActiveness(map, chunk) > 0) then - processNestActiveness(map, chunk, natives, surface) + processNestActiveness(map, chunk) local nextTick = tick + DURATION_ACTIVE_NEST local nextSlot = processActiveNest[nextTick] if not nextSlot then @@ -460,17 +459,17 @@ function mapProcessor.processActiveNests(map, surface, tick) end end -function mapProcessor.processVengence(map, surface) - local natives = map.natives - local ss = natives.vengenceQueue +function mapProcessor.processVengence(map) + local native = map.native + local ss = native.vengenceQueue local chunk = next(ss, map.deployVengenceIterator) if not chunk then map.deployVengenceIterator = nil if (tableSize(ss) == 0) then - natives.vengenceQueue = {} + native.vengenceQueue = {} end else - formVengenceSquad(map, surface, chunk) + formVengenceSquad(map, chunk) local nextChunk nextChunk = next(ss, chunk) ss[chunk] = nil @@ -479,73 +478,75 @@ function mapProcessor.processVengence(map, surface) map.deployVengenceIterator = chunk end -function mapProcessor.processNests(map, surface, tick) - local natives = map.natives +function mapProcessor.processNests(map, tick) + local native = map.native local bases = map.chunkToBase local chunks = map.chunkToNests local chunk = next(chunks, map.processNestIterator) - for _=1,5 do - if not chunk then - map.processNestIterator = nil - return - else - processNestActiveness(map, chunk, natives, surface) - queueNestSpawners(map, chunk, tick) + if not chunk then + map.processNestIterator = nil + return + else + processNestActiveness(map, chunk) + queueNestSpawners(map, chunk, tick) - if natives.newEnemies then - local base = bases[chunk] - if base and ((tick - base.tick) > BASE_PROCESS_INTERVAL) then - processBase(chunk, surface, natives, tick, base) - end + if native.newEnemies then + local base = bases[chunk] + if base and ((tick - base.tick) > BASE_PROCESS_INTERVAL) then + processBase(chunk, native, tick, base) end - - chunk = next(chunks, chunk) end + + chunk = next(chunks, chunk) end map.processNestIterator = chunk end -local function processSpawners(map, surface, tick, natives, iteration, iterator, chunks) - +local function processSpawners(map, tick, iterator, chunks) + local native = map.native local chunk = next(chunks, map[iterator]) - local migrate = canMigrate(natives, surface) - local attack = canAttack(natives, surface, tick) - for _=1,iteration do - if not chunk then - map[iterator] = nil - return - else - if migrate then - formSettlers(map, surface, chunk) - elseif attack then - formSquads(map, surface, chunk, tick) - end - chunk = next(chunks, chunk) + local migrate = canMigrate(native) + local attack = canAttack(native, tick) + if not chunk then + map[iterator] = nil + return + else + if migrate then + formSettlers(map, chunk) + elseif attack then + formSquads(map, chunk, tick) end + chunk = next(chunks, chunk) end map[iterator] = chunk end -function mapProcessor.processSpawners(map, surface, tick) - local natives = map.natives +function mapProcessor.processSpawners(map, tick) + local native = map.native - if (natives.state ~= AI_STATE_PEACEFUL) then - if (natives.state == AI_STATE_MIGRATING) or - ((natives.state == AI_STATE_SIEGE) and natives.temperament <= 0.5) + if (native.state ~= AI_STATE_PEACEFUL) then + if (native.state == AI_STATE_MIGRATING) or + ((native.state == AI_STATE_SIEGE) and native.temperament <= 0.5) then - processSpawners(map, surface, tick, natives, 2, "processMigrationIterator", map.chunkToNests) + processSpawners(map, + tick, + "processMigrationIterator", + map.chunkToNests) else - if (natives.state ~= AI_STATE_AGGRESSIVE) then - processSpawners(map, surface, tick, natives, 1, "processActiveSpawnerIterator", map.chunkToActiveNest) + if (native.state ~= AI_STATE_AGGRESSIVE) then + processSpawners(map, + tick, + "processActiveSpawnerIterator", + map.chunkToActiveNest) processSpawners(map, - surface, tick, - natives, - 1, "processActiveRaidSpawnerIterator", map.chunkToActiveRaidNest) else - processSpawners(map, surface, tick, natives, 2, "processActiveSpawnerIterator", map.chunkToActiveNest) + processSpawners(map, + tick, + "processActiveSpawnerIterator", + map.chunkToActiveNest) end end end diff --git a/libs/SquadAttack.lua b/libs/SquadAttack.lua index 8d2a65f..1e82af5 100755 --- a/libs/SquadAttack.lua +++ b/libs/SquadAttack.lua @@ -98,7 +98,7 @@ local function scoreAttackKamikazeLocation(_, neighborChunk) return damage end -local function settleMove(map, squad, surface) +local function settleMove(map, squad) local targetPosition = map.position local targetPosition2 = map.position2 local group = squad.group @@ -107,8 +107,8 @@ local function settleMove(map, squad, surface) local x, y = positionToChunkXY(groupPosition) local chunk = getChunkByXY(map, x, y) local scoreFunction = scoreResourceLocation - local natives = map.natives - if (natives.state == AI_STATE_SIEGE) then + local native = map.native + if (native.state == AI_STATE_SIEGE) then if squad.kamikaze then scoreFunction = scoreSiegeLocationKamikaze else @@ -126,6 +126,7 @@ local function settleMove(map, squad, surface) squad.originPosition.y) local cmd local position + local surface = map.surface if (distance >= squad.maxDistance) or ((getResourceGenerator(map, chunk) ~= 0) and (getNestCount(map, chunk) == 0)) then @@ -162,7 +163,7 @@ local function settleMove(map, squad, surface) group.set_command(cmd) return elseif (attackDirection ~= 0) then - local attackPlayerThreshold = natives.attackPlayerThreshold + local attackPlayerThreshold = native.attackPlayerThreshold if (nextAttackChunk ~= -1) then attackChunk = nextAttackChunk @@ -224,13 +225,14 @@ local function settleMove(map, squad, surface) end end -local function attackMove(map, squad, surface) +local function attackMove(map, squad) local targetPosition = map.position local targetPosition2 = map.position2 local group = squad.group + local surface = map.surface local position local groupPosition = group.position local x, y = positionToChunkXY(groupPosition) @@ -279,7 +281,7 @@ local function attackMove(map, squad, surface) end if (getPlayerBaseGenerator(map, attackChunk) ~= 0) and - (attackChunk[PLAYER_PHEROMONE] >= map.natives.attackPlayerThreshold) + (attackChunk[PLAYER_PHEROMONE] >= map.native.attackPlayerThreshold) then cmd = map.attackCommand @@ -300,10 +302,10 @@ local function attackMove(map, squad, surface) group.set_command(cmd) end -local function buildMove(map, squad, surface) +local function buildMove(map, squad) local group = squad.group local position = map.position - local groupPosition = findMovementPosition(surface, group.position) + local groupPosition = findMovementPosition(map.surface, group.position) if not groupPosition then groupPosition = group.position @@ -315,15 +317,16 @@ local function buildMove(map, squad, surface) group.set_command(map.compoundSettleCommand) end -function squadAttack.cleanSquads(natives, iterator) - local squads = natives.groupNumberToSquad - local map = natives.map +function squadAttack.cleanSquads(natives, native) + local squads = native.groupNumberToSquad + local map = native.map + local iterator = map.squadIterator local k, squad = next(squads, iterator) if not k then if (table_size(squads) == 0) then -- this is needed as the next command remembers the max length a table has been - natives.groupNumberToSquad = {} + native.groupNumberToSquad = {} end else local group = squad.group @@ -349,32 +352,32 @@ function squadAttack.cleanSquads(natives, iterator) map.squadIterator = k end -function squadAttack.squadDispatch(map, surface, squad) +function squadAttack.squadDispatch(map, squad) local group = squad.group if group and group.valid then local status = squad.status if (status == SQUAD_RAIDING) then - attackMove(map, squad, surface) + attackMove(map, squad) elseif (status == SQUAD_SETTLING) then - settleMove(map, squad, surface) + settleMove(map, squad) elseif (status == SQUAD_RETREATING) then if squad.settlers then squad.status = SQUAD_SETTLING - settleMove(map, squad, surface) + settleMove(map, squad) else squad.status = SQUAD_RAIDING - attackMove(map, squad, surface) + attackMove(map, squad) end elseif (status == SQUAD_BUILDING) then removeSquadFromChunk(map, squad) - buildMove(map, squad, surface) + buildMove(map, squad) elseif (status == SQUAD_GUARDING) then if squad.settlers then squad.status = SQUAD_SETTLING - settleMove(map, squad, surface) + settleMove(map, squad) else squad.status = SQUAD_RAIDING - attackMove(map, squad, surface) + attackMove(map, squad) end end end diff --git a/libs/SquadDefense.lua b/libs/SquadDefense.lua index 0218928..9a88135 100755 --- a/libs/SquadDefense.lua +++ b/libs/SquadDefense.lua @@ -48,7 +48,7 @@ local function scoreRetreatLocation(map, neighborChunk) -(getPlayerBaseGenerator(map, neighborChunk) * 1000)) end -function aiDefense.retreatUnits(chunk, cause, map, surface, tick, radius) +function aiDefense.retreatUnits(chunk, cause, map, tick, radius) if (tick - getRetreatTick(map, chunk) > COOLDOWN_RETREAT) and (getEnemyStructureCount(map, chunk) == 0) then setRetreatTick(map, chunk, tick) @@ -64,6 +64,7 @@ function aiDefense.retreatUnits(chunk, cause, map, surface, tick, radius) local retreatPosition position.x = chunk.x + 16 position.y = chunk.y + 16 + local surface = map.surface if (exitPath == -1) then return elseif (nextExitPath ~= -1) then @@ -85,10 +86,10 @@ function aiDefense.retreatUnits(chunk, cause, map, surface, tick, radius) local newSquad = findNearbyRetreatingSquad(map, exitPath) local created = false - local natives = map.natives + local native = map.native if not newSquad then - if (natives.squadCount < natives.AI_MAX_SQUAD_COUNT) then + if (native.squadCount < native.AI_MAX_SQUAD_COUNT) then created = true newSquad = createSquad(position, surface) else @@ -111,8 +112,8 @@ function aiDefense.retreatUnits(chunk, cause, map, surface, tick, radius) end if created then - natives.groupNumberToSquad[newSquad.groupNumber] = newSquad - natives.squadCount = natives.squadCount + 1 + native.groupNumberToSquad[newSquad.groupNumber] = newSquad + native.squadCount = native.squadCount + 1 end newSquad.status = SQUAD_RETREATING