From 3a9f5b05cdc3bbfdc0e7d280a886ca27767f40d0 Mon Sep 17 00:00:00 2001 From: Aaron Veden Date: Sun, 12 Mar 2023 16:13:32 -0700 Subject: [PATCH] FACTO-256: Additional code consolidation, vengence settlers now have a separate cost --- .dir-locals.el | 10 +- .luacheckrc | 29 +--- changelog.txt | 1 + control.lua | 4 +- libs/BaseUtils.lua | 8 +- libs/ChunkUtils.lua | 2 - libs/Constants.lua | 1 + libs/MapUtils.lua | 35 +--- libs/Processor.lua | 12 +- libs/Squad.lua | 404 ++++++++++++++++---------------------------- libs/Upgrade.lua | 4 - 11 files changed, 176 insertions(+), 334 deletions(-) diff --git a/.dir-locals.el b/.dir-locals.el index af2ceb2..9e1c6ba 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -19,8 +19,14 @@ ((nil . ((projectile-project-install-cmd . "./make.sh copy") (projectile-install-buffer-suffix . "install") + + (projectile-project-compile-cmd . "luacheck .") + (projectile-compile-buffer-suffix . "lint") + (projectile-project-package-cmd . "./make.sh zip") (projectile-package-buffer-suffix . "install") - (projectile-project-uninstall-cmd . "./make.sh clear") + + (projectile-project-uninstall-cmd . "./make.sh clear") (projectile-uninstall-buffer-suffix . "install") - (projectile-project-run-cmd . "factorio")))) + + (projectile-project-run-cmd . "factorio")))) diff --git a/.luacheckrc b/.luacheckrc index d080c7a..f492410 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -11,27 +11,16 @@ globals = { "table_size", "script", "defines", - "mapProcessorG", - "pheromoneUtilsG", - "aiAttackWaveG", - "aiPlanningG", - "aiPredicatesG", - "constantsG", - "chunkProcessorG", - "chunkPropertyUtilsG", - "chunkUtilsG", - "interopG", - "mapUtilsG", - "mathUtilsG", - "movementUtilsG", - "playerUtilsG", - "squadAttackG", - "aiDefenseG", - "stringUtilsG", - "unitGroupUtilsG", + "ProcessorG", + "ConstantsG", + "ChunkPropertyUtilsG", + "ChunkUtilsG", + "MapUtilsG", + "MathUtilsG", + "SquadG", "unitUtilsG", - "baseUtilsG", - "queryUtilsG" + "BaseUtilsG", + "UtilsG" } max_line_length = false \ No newline at end of file diff --git a/changelog.txt b/changelog.txt index bc7a5f5..9d63420 100644 --- a/changelog.txt +++ b/changelog.txt @@ -34,6 +34,7 @@ Version: 3.2.0 - Reduced the size of stickers applied by Rampant new enemies to player entities - Recording the resource chunks covered by a given base as a property of a base - Use the enemy seed value instead of the map seed for puesdo random generating used by AI + - Vengence settlers now cost ~3x of vengence squad Bugfixes: - Removed layer-13 from projectiles - script_raised_built now looks for enemy faction and registers as needed diff --git a/control.lua b/control.lua index 0b8f15c..b39a503 100644 --- a/control.lua +++ b/control.lua @@ -786,7 +786,7 @@ local function onUnitGroupCreated(event) return end if not Universe.aiNocturnalMode then - local settler = canMigrate(map, base) and + local settler = canMigrate(base) and (Universe.builderCount < Universe.AI_MAX_VANILLA_BUILDER_COUNT) and (Universe.random() < 0.25) @@ -887,7 +887,7 @@ local function onGroupFinishedGathering(event) group.destroy() return end - local settler = canMigrate(map, base) and + local settler = canMigrate(base) and (Universe.builderCount < Universe.AI_MAX_VANILLA_BUILDER_COUNT) and (Universe.random() < 0.25) diff --git a/libs/BaseUtils.lua b/libs/BaseUtils.lua index e87b3a7..29d136f 100644 --- a/libs/BaseUtils.lua +++ b/libs/BaseUtils.lua @@ -171,7 +171,7 @@ local function findBaseMutation(targetEvolution, excludeFactions) return availableAlignments[#availableAlignments] end -local function initialEntityUpgrade(baseAlignment, tier, maxTier, map, useHiveType, entityType) +local function initialEntityUpgrade(baseAlignment, tier, maxTier, useHiveType, entityType) local entity local useTier @@ -228,7 +228,7 @@ local function initialEntityUpgrade(baseAlignment, tier, maxTier, map, useHiveTy return entity end -local function entityUpgrade(baseAlignment, tier, maxTier, originalEntity, map) +local function entityUpgrade(baseAlignment, tier, maxTier, originalEntity) local entity local hiveType = BUILDING_HIVE_TYPE_LOOKUP[originalEntity.name] @@ -298,9 +298,9 @@ function BaseUtils.findEntityUpgrade(baseAlignment, currentEvo, evoIndex, origin chunk.resourceGenerator ) ) - return initialEntityUpgrade(baseAlignment, tier, maxTier, map, (makeHive and "hive"), entityType) + return initialEntityUpgrade(baseAlignment, tier, maxTier, (makeHive and "hive"), entityType) else - return entityUpgrade(baseAlignment, tier, maxTier, originalEntity, map) + return entityUpgrade(baseAlignment, tier, maxTier, originalEntity) end end diff --git a/libs/ChunkUtils.lua b/libs/ChunkUtils.lua index 7daa543..5e57165 100644 --- a/libs/ChunkUtils.lua +++ b/libs/ChunkUtils.lua @@ -85,8 +85,6 @@ local addNestCount = ChunkPropertyUtils.addNestCount local removeNestCount = ChunkPropertyUtils.removeNestCount local addHiveCount = ChunkPropertyUtils.addHiveCount local removeHiveCount = ChunkPropertyUtils.removeHiveCount -local addTrapCount = ChunkPropertyUtils.addTrapCount -local removeTrapCount = ChunkPropertyUtils.removeTrapCount local addTurretCount = ChunkPropertyUtils.addTurretCount local removeTurretCount = ChunkPropertyUtils.removeTurretCount local addUtilityCount = ChunkPropertyUtils.addUtilityCount diff --git a/libs/Constants.lua b/libs/Constants.lua index 81f2edf..d16fa9d 100644 --- a/libs/Constants.lua +++ b/libs/Constants.lua @@ -97,6 +97,7 @@ constants.AI_SQUAD_COST = 175 constants.RECOVER_NEST_COST = constants.AI_SQUAD_COST constants.RECOVER_WORM_COST = constants.AI_SQUAD_COST * 0.5 constants.AI_VENGENCE_SQUAD_COST = 45 +constants.AI_VENGENCE_SETTLER_COST = 120 constants.AI_SETTLER_COST = 300 constants.AI_BASE_BUILDING_COST = 500 constants.AI_TUNNEL_COST = 100 diff --git a/libs/MapUtils.lua b/libs/MapUtils.lua index a1061e4..f62c951 100644 --- a/libs/MapUtils.lua +++ b/libs/MapUtils.lua @@ -395,7 +395,7 @@ end /|\ 6 7 8 ]]-- -function MapUtils.canMoveChunkDirection(map, direction, startChunk, endChunk) +function MapUtils.canMoveChunkDirection(direction, startChunk, endChunk) local canMove = false local startPassable = getPassable(startChunk) local endPassable = getPassable(endChunk) @@ -425,33 +425,6 @@ function MapUtils.canMoveChunkDirection(map, direction, startChunk, endChunk) return canMove end -function MapUtils.getCardinalChunks(map, x, y) - local neighbors = Universe.cardinalNeighbors - local xChunks = map[x] - if xChunks then - neighbors[1] = xChunks[y-CHUNK_SIZE] or -1 - neighbors[4] = xChunks[y+CHUNK_SIZE] or -1 - else - neighbors[1] = -1 - neighbors[4] = -1 - end - - xChunks = map[x-CHUNK_SIZE] - if xChunks then - neighbors[2] = xChunks[y] or -1 - else - neighbors[2] = -1 - end - - xChunks = map[x+CHUNK_SIZE] - if xChunks then - neighbors[3] = xChunks[y] or -1 - else - neighbors[3] = -1 - end - return neighbors -end - function MapUtils.positionFromDirectionAndChunk(direction, startPosition, scaling) local endPosition = {} if (direction == 1) then @@ -560,7 +533,7 @@ function MapUtils.deathScent(chunk, structure) addPermanentDeathGenerator(chunk, amount) end -function MapUtils.processPheromone(map, chunk, tick, player) +function MapUtils.processPheromone(chunk, tick, player) if chunk[CHUNK_TICK] > tick then return end @@ -576,12 +549,12 @@ function MapUtils.processPheromone(map, chunk, tick, player) local enemyStructureCount = getEnemyStructureCount(chunk) - local tempNeighbors = MapUtils.getNeighborChunks(map, chunk.x, chunk.y) + local tempNeighbors = MapUtils.getNeighborChunks(chunk.map, chunk.x, chunk.y) for i=1,8 do local tempPheromone local neighbor = tempNeighbors[i] if (neighbor ~= -1) then - if MapUtils.canMoveChunkDirection(map, i, chunk, neighbor) then + if MapUtils.canMoveChunkDirection(i, chunk, neighbor) then chunkCount = chunkCount + 1 chunkPlayer = chunkPlayer + neighbor[PLAYER_PHEROMONE] chunkEnemy = chunkEnemy + neighbor[ENEMY_PHEROMONE] diff --git a/libs/Processor.lua b/libs/Processor.lua index 5a551f0..c968eda 100644 --- a/libs/Processor.lua +++ b/libs/Processor.lua @@ -154,7 +154,7 @@ function Processor.processMap(map, tick) Universe.processedChunks = Universe.processedChunks + ((startIndex - endIndex) * step) for x=startIndex,endIndex,step do - processPheromone(map, processQueue[x], tick) + processPheromone(processQueue[x], tick) end end @@ -209,7 +209,7 @@ function Processor.processPlayers(players, tick) local chunk = getChunkByXY(map, x, y) if (chunk ~= -1) then - processPheromone(map, chunk, tick, true) + processPheromone(chunk, tick, true) if chunk.nestCount then processNestActiveness(chunk, tick) @@ -254,7 +254,7 @@ end --[[ Passive scan to find entities that have been generated outside the factorio event system --]] -function Processor.scanPlayerMap(map, tick) +function Processor.scanPlayerMap(map) local index = map.scanPlayerIndex local processQueue = map.processQueue @@ -300,7 +300,7 @@ function Processor.scanEnemyMap(map, tick) end end -function Processor.scanResourceMap(map, tick) +function Processor.scanResourceMap(map) local index = map.scanResourceIndex local processQueue = map.processQueue @@ -340,9 +340,9 @@ function Processor.processVengence() end local base = chunk.base if canMigrate(base) and (Universe.random() < 0.075) then - formVengenceSettler(chunk, base) + formVengenceSettler(chunk) else - formVengenceSquad(chunk, base) + formVengenceSquad(chunk) end end diff --git a/libs/Squad.lua b/libs/Squad.lua index 9ae0392..177c384 100644 --- a/libs/Squad.lua +++ b/libs/Squad.lua @@ -71,6 +71,7 @@ local RALLY_CRY_DISTANCE = Constants.RALLY_CRY_DISTANCE local AI_SQUAD_COST = Constants.AI_SQUAD_COST local AI_SETTLER_COST = Constants.AI_SETTLER_COST local AI_VENGENCE_SQUAD_COST = Constants.AI_VENGENCE_SQUAD_COST +local AI_VENGENCE_SETTLER_COST = Constants.AI_VENGENCE_SETTLER_COST local CHUNK_ALL_DIRECTIONS = Constants.CHUNK_ALL_DIRECTIONS -- imported functions @@ -113,19 +114,19 @@ local positionFromDirectionAndFlat = MapUtils.positionFromDirectionAndFlat local euclideanDistanceNamed = MathUtils.euclideanDistanceNamed -- module code -local function scoreRetreatLocation(map, neighborChunk) +local function scoreRetreatLocation(neighborChunk) return (-neighborChunk[BASE_PHEROMONE] + -(neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER) + -((neighborChunk.playerBaseGenerator or 0) * 1000)) end -local function scoreResourceLocation(map, neighborChunk) +local function scoreResourceLocation(neighborChunk) return neighborChunk[RESOURCE_PHEROMONE] - (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER) - neighborChunk[ENEMY_PHEROMONE] end -local function scoreSiegeLocation(map, neighborChunk) +local function scoreSiegeLocation(neighborChunk) local settle = neighborChunk[BASE_PHEROMONE] + neighborChunk[RESOURCE_PHEROMONE] * 0.5 + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER) @@ -133,16 +134,30 @@ local function scoreSiegeLocation(map, neighborChunk) return settle - neighborChunk[ENEMY_PHEROMONE] end -local function scoreAttackLocation(map, neighborChunk) +local function scoreAttackLocation(neighborChunk) local damage = neighborChunk[BASE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER) return damage end local function findMovementPosition(surface, position) - local pos = position - pos = surface.find_non_colliding_position("behemoth-biter", pos, 10, 2, false) - return pos + return surface.find_non_colliding_position( + "behemoth-biter", + position, + 10, + 2, + false + ) +end + +local function findDeploymentPosition(surface, position) + return surface.find_non_colliding_position( + "biter-spawner", + position, + CHUNK_SIZE, + 4, + true + ) end local function calculateSettlerMaxDistance() @@ -204,7 +219,7 @@ end --[[ Expects all neighbors adjacent to a chunk --]] -function scoreNeighborsForSettling(map, chunk, neighborDirectionChunks, scoreFunction) +local function scoreNeighborsForSettling(map, chunk, neighborDirectionChunks, scoreFunction) local highestChunk = -1 local highestScore = -MAGIC_MAXIMUM_NUMBER local highestDirection = 0 @@ -212,8 +227,8 @@ function scoreNeighborsForSettling(map, chunk, neighborDirectionChunks, scoreFun for x=1,8 do local neighborChunk = neighborDirectionChunks[x] if (neighborChunk ~= -1) then - if (chunk == -1) or canMoveChunkDirection(map, x, chunk, neighborChunk) then - local score = scoreFunction(map, neighborChunk) + if (chunk == -1) or canMoveChunkDirection(x, chunk, neighborChunk) then + local score = scoreFunction(neighborChunk) if (score > highestScore) then highestScore = score highestChunk = neighborChunk @@ -223,7 +238,7 @@ function scoreNeighborsForSettling(map, chunk, neighborDirectionChunks, scoreFun end end - if (chunk ~= -1) and (scoreFunction(map, chunk) > highestScore) then + if (chunk ~= -1) and (scoreFunction(chunk) > highestScore) then return chunk, 0, -1, 0 end @@ -236,8 +251,8 @@ function scoreNeighborsForSettling(map, chunk, neighborDirectionChunks, scoreFun for x=1,8 do local neighborChunk = neighborDirectionChunks[x] if ((neighborChunk ~= -1) and ((chunk == -1) or (neighborChunk.id ~= chunk.id)) and - canMoveChunkDirection(map, x, highestChunk, neighborChunk)) then - local score = scoreFunction(map, neighborChunk) + canMoveChunkDirection(x, highestChunk, neighborChunk)) then + local score = scoreFunction(neighborChunk) if (score > nextHighestScore) then nextHighestScore = score nextHighestChunk = neighborChunk @@ -426,8 +441,8 @@ local function scoreNeighborsForAttack(map, chunk, neighborDirectionChunks, scor for x=1,8 do local neighborChunk = neighborDirectionChunks[x] if (neighborChunk ~= -1) then - if (chunk == -1) or canMoveChunkDirection(map, x, chunk, neighborChunk) then - local score = scoreFunction(map, neighborChunk) + if (chunk == -1) or canMoveChunkDirection(x, chunk, neighborChunk) then + local score = scoreFunction(neighborChunk) if (score > highestScore) then highestScore = score highestChunk = neighborChunk @@ -446,8 +461,8 @@ local function scoreNeighborsForAttack(map, chunk, neighborDirectionChunks, scor for x=1,8 do local neighborChunk = neighborDirectionChunks[x] if ((neighborChunk ~= -1) and ((chunk == -1) or (neighborChunk.id ~= chunk.id)) and - canMoveChunkDirection(map, x, highestChunk, neighborChunk)) then - local score = scoreFunction(map, neighborChunk) + canMoveChunkDirection(x, highestChunk, neighborChunk)) then + local score = scoreFunction(neighborChunk) if (score > nextHighestScore) then nextHighestScore = score nextHighestChunk = neighborChunk @@ -674,8 +689,8 @@ local function scoreNeighborsForRetreat(chunk, neighborDirectionChunks, scoreFun for x=1,8 do local neighborChunk = neighborDirectionChunks[x] if (neighborChunk ~= -1) then - if (chunk == -1) or canMoveChunkDirection(map, x, chunk, neighborChunk) then - local score = scoreFunction(map, neighborChunk) + if (chunk == -1) or canMoveChunkDirection(x, chunk, neighborChunk) then + local score = scoreFunction(neighborChunk) if (score > highestScore) then highestScore = score highestChunk = neighborChunk @@ -695,8 +710,8 @@ local function scoreNeighborsForRetreat(chunk, neighborDirectionChunks, scoreFun local neighborChunk = neighborDirectionChunks[x] if ((neighborChunk ~= -1) and ((chunk == -1) or (neighborChunk.id ~= chunk.id)) and - canMoveChunkDirection(map, x, highestChunk, neighborChunk)) then - local score = scoreFunction(map, neighborChunk) + canMoveChunkDirection(x, highestChunk, neighborChunk)) then + local score = scoreFunction(neighborChunk) if (score > nextHighestScore) then nextHighestScore = score nextHighestChunk = neighborChunk @@ -914,35 +929,23 @@ local function attackWaveValidCandidate(chunk) return false end -local function scoreSettlerLocation(map, neighborChunk) +local function scoreSettlerLocation(neighborChunk) return neighborChunk[RESOURCE_PHEROMONE] + -neighborChunk[PLAYER_PHEROMONE] end -local function scoreSiegeSettlerLocation(map, neighborChunk) +local function scoreSiegeSettlerLocation(neighborChunk) return (neighborChunk[RESOURCE_PHEROMONE] + neighborChunk[BASE_PHEROMONE]) + -neighborChunk[PLAYER_PHEROMONE] end -local function scoreUnitGroupLocation(map, neighborChunk) +local function scoreUnitGroupLocation(neighborChunk) return neighborChunk[PLAYER_PHEROMONE] + neighborChunk[BASE_PHEROMONE] end -local function validSiegeSettlerLocation(map, neighborChunk) +local function validUnitGroupLocation(neighborChunk) return (getPassable(neighborChunk) == CHUNK_ALL_DIRECTIONS) and (not neighborChunk.nestCount) end -local function validSettlerLocation(map, chunk, neighborChunk) - local chunkResource = chunk[RESOURCE_PHEROMONE] - return (getPassable(neighborChunk) == CHUNK_ALL_DIRECTIONS) and - (not neighborChunk.nestCount) and - (neighborChunk[RESOURCE_PHEROMONE] >= chunkResource) -end - -local function validUnitGroupLocation(map, neighborChunk) - return getPassable(neighborChunk) == CHUNK_ALL_DIRECTIONS and - (not neighborChunk.nestCount) -end - local function visitPattern(o, cX, cY, distance) local startX local endX @@ -985,43 +988,15 @@ end --[[ Expects all neighbors adjacent to a chunk --]] -local function scoreNeighborsForResource(chunk, neighborDirectionChunks, validFunction, scoreFunction, map) - local highestChunk = -1 - local highestScore = -MAGIC_MAXIMUM_NUMBER - local highestDirection - for x=1,8 do - local neighborChunk = neighborDirectionChunks[x] - if (neighborChunk ~= -1) and - canMoveChunkDirection(map, x, chunk, neighborChunk) and - validFunction(map, chunk, neighborChunk) - then - local score = scoreFunction(map, neighborChunk) - if (score > highestScore) then - highestScore = score - highestChunk = neighborChunk - highestDirection = x - end - end - end - - if (chunk ~= -1) and (scoreFunction(map, chunk) > highestScore) then - return -1, -1 - end - - return highestChunk, highestDirection -end - ---[[ - Expects all neighbors adjacent to a chunk ---]] -local function scoreNeighborsForFormation(neighborChunks, validFunction, scoreFunction, map) +local function scoreNeighborsForFormation(chunk, validFunction, scoreFunction) local highestChunk = -1 local highestScore = -MAGIC_MAXIMUM_NUMBER local highestDirection + local neighborChunks = getNeighborChunks(chunk.map, chunk.x, chunk.y) for x=1,8 do local neighborChunk = neighborChunks[x] - if (neighborChunk ~= -1) and validFunction(map, neighborChunk) then - local score = scoreFunction(map, neighborChunk) + if (neighborChunk ~= -1) and validFunction(neighborChunk) then + local score = scoreFunction(neighborChunk) if (score > highestScore) then highestScore = score highestChunk = neighborChunk @@ -1060,213 +1035,116 @@ function Squad.rallyUnits(chunk, tick) end end -function Squad.formSettlers(chunk) +local function deploySquad(name, chunk, cost, vengence, attacker) local base = chunk.base - if (Universe.builderCount < Universe.AI_MAX_BUILDER_COUNT) - and (base.sentExpansionGroups < base.maxExpansionGroups) - and ((base.unitPoints - AI_SETTLER_COST) > 0) - and (Universe.random() < Universe.formSquadThreshold) - then - local map = chunk.map - local surface = map.surface - local squadPath, squadDirection - if (base.stateAI == BASE_AI_STATE_SIEGE) then - squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), - validSiegeSettlerLocation, - scoreSiegeSettlerLocation, - map) - else - squadPath, squadDirection = scoreNeighborsForResource(chunk, - getNeighborChunks(map, chunk.x, chunk.y), - validSettlerLocation, - scoreSettlerLocation, - map) - end - if (squadPath ~= -1) then - local squadPosition = surface.find_non_colliding_position("biter-spawner", - positionFromDirectionAndChunk(squadDirection, - chunk, - 0.98), - CHUNK_SIZE, - 4, - true) - if squadPosition then - local squad = Squad.createSquad(squadPosition, map, nil, true, base) - - local scaledWaveSize = settlerWaveScaling() - Universe.formGroupCommand.group = squad.group - Universe.formCommand.unit_count = scaledWaveSize - local foundUnits = surface.set_multi_command(Universe.formCommand) - if (foundUnits > 0) then - base.sentExpansionGroups = base.sentExpansionGroups + 1 - - squad.base = base - local kamikazeThreshold = Squad.calculateKamikazeSettlerThreshold(foundUnits) - if base.stateAI == BASE_AI_STATE_SIEGE then - kamikazeThreshold = kamikazeThreshold * 2.5 - end - squad.kamikaze = Universe.random() < kamikazeThreshold - - Universe.builderCount = Universe.builderCount + 1 - modifyBaseUnitPoints(base, -AI_SETTLER_COST, "Settler", squadPosition.x, squadPosition.y) - Universe.groupNumberToSquad[squad.groupNumber] = squad - else - if (squad.group.valid) then - squad.group.destroy() - end - end - end - end - end -end - -function Squad.formVengenceSquad(chunk, base) - if (Universe.squadCount < Universe.AI_MAX_SQUAD_COUNT) - and ((base.unitPoints - AI_VENGENCE_SQUAD_COST) > 0) - and (Universe.random() < Universe.formSquadThreshold) - then - if (chunk[BASE_PHEROMONE] < 0.0001) or (chunk[PLAYER_PHEROMONE] < 0.0001) then + local lackingPoints = ((base.unitPoints - cost) < 0) + if attacker then + if lackingPoints + or ((chunk[BASE_PHEROMONE] < 0.0001) and (chunk[PLAYER_PHEROMONE] < 0.0001)) + or (Universe.squadCount > Universe.AI_MAX_SQUAD_COUNT) + or (not vengence and not attackWaveValidCandidate(chunk)) + or (Universe.random() > Universe.formSquadThreshold) + then return end - local map = chunk.map - - local surface = map.surface - local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), - validUnitGroupLocation, - scoreUnitGroupLocation, - map) - if (squadPath ~= -1) then - local squadPosition = surface.find_non_colliding_position("biter-spawner", - positionFromDirectionAndChunk(squadDirection, - chunk, - 0.98), - CHUNK_SIZE, - 4, - true) - if squadPosition then - local squad = Squad.createSquad(squadPosition, map, nil, false, base) - - squad.rabid = Universe.random() < 0.03 - - local scaledWaveSize = attackWaveScaling() - Universe.formGroupCommand.group = squad.group - Universe.formCommand.unit_count = scaledWaveSize - local foundUnits = surface.set_multi_command(Universe.formCommand) - if (foundUnits > 0) then - squad.base = base - squad.kamikaze = Universe.random() < Squad.calculateKamikazeSquadThreshold(foundUnits) - Universe.groupNumberToSquad[squad.groupNumber] = squad - Universe.squadCount = Universe.squadCount + 1 - modifyBaseUnitPoints(base, -AI_VENGENCE_SQUAD_COST, "Vengence", squadPosition.x, squadPosition.y) - else - if (squad.group.valid) then - squad.group.destroy() - end - end - end + else + if lackingPoints + or (Universe.builderCount > Universe.AI_MAX_BUILDER_COUNT) + or (not vengence and (base.sentExpansionGroups > base.maxExpansionGroups)) + or (Universe.random() > Universe.formSquadThreshold) + then + return end end + + local scoringFunction + if attacker then + scoringFunction = scoreUnitGroupLocation + else + scoringFunction = scoreSettlerLocation + if base.stateAI == BASE_AI_STATE_SIEGE then + scoringFunction = scoreSiegeSettlerLocation + end + end + + local squadPath, squadDirection = scoreNeighborsForFormation( + chunk, + validUnitGroupLocation, + scoringFunction + ) + if (squadPath == -1) then + return + end + + local map = chunk.map + local surface = map.surface + + local squadPosition = findDeploymentPosition( + surface, + positionFromDirectionAndChunk(squadDirection, + chunk, + 0.98) + ) + + if not squadPosition then + return + end + + local squad = Squad.createSquad(squadPosition, map, nil, not attacker, base) + + local scaledWaveSize + if attacker then + scaledWaveSize = attackWaveScaling() + else + scaledWaveSize = settlerWaveScaling() + end + Universe.formGroupCommand.group = squad.group + Universe.formCommand.unit_count = scaledWaveSize + local foundUnits = surface.set_multi_command(Universe.formCommand) + if (foundUnits == 0) then + if squad.group.valid then + squad.group.destroy() + end + return + end + + if attacker then + squad.kamikaze = Universe.random() < Squad.calculateKamikazeSquadThreshold(foundUnits) + Universe.squadCount = Universe.squadCount + 1 + if not vengence and (base.stateAI == BASE_AI_STATE_AGGRESSIVE) then + base.sentAggressiveGroups = base.sentAggressiveGroups + 1 + end + else + local kamikazeThreshold = Squad.calculateKamikazeSettlerThreshold(foundUnits) + if base.stateAI == BASE_AI_STATE_SIEGE then + kamikazeThreshold = kamikazeThreshold * 2.5 + end + squad.kamikaze = Universe.random() < kamikazeThreshold + base.sentExpansionGroups = base.sentExpansionGroups + 1 + Universe.builderCount = Universe.builderCount + 1 + end + + squad.rabid = Universe.random() < 0.03 + + Universe.groupNumberToSquad[squad.groupNumber] = squad + modifyBaseUnitPoints(base, -cost, name, squadPosition.x, squadPosition.y) end -function Squad.formVengenceSettler(chunk, base) - if (Universe.builderCount < Universe.AI_MAX_BUILDER_COUNT) - and (base.sentExpansionGroups < base.maxExpansionGroups) - and ((base.unitPoints - AI_VENGENCE_SQUAD_COST) > 0) - and (Universe.random() < Universe.formSquadThreshold) - then - local map = chunk.map - local surface = map.surface - local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), - validUnitGroupLocation, - scoreUnitGroupLocation, - map) - if (squadPath ~= -1) then - local squadPosition = surface.find_non_colliding_position("biter-spawner", - positionFromDirectionAndChunk(squadDirection, - chunk, - 0.98), - CHUNK_SIZE, - 4, - true) - if squadPosition then - local squad = Squad.createSquad(squadPosition, map, nil, true, base) +function Squad.formSettlers(chunk) + deploySquad("Settler", chunk, AI_SETTLER_COST, false, false) +end - squad.rabid = Universe.random() < 0.03 - - local scaledWaveSize = settlerWaveScaling() - Universe.formGroupCommand.group = squad.group - Universe.formCommand.unit_count = scaledWaveSize - local foundUnits = surface.set_multi_command(Universe.formCommand) - if (foundUnits > 0) then - base.sentExpansionGroups = base.sentExpansionGroups + 1 - - squad.base = base - squad.kamikaze = Universe.random() < Squad.calculateKamikazeSettlerThreshold(foundUnits) - Universe.groupNumberToSquad[squad.groupNumber] = squad - Universe.builderCount = Universe.builderCount + 1 - modifyBaseUnitPoints(base, -AI_VENGENCE_SQUAD_COST, "Vengence Settlers", squadPosition.x, squadPosition.y) - else - if (squad.group.valid) then - squad.group.destroy() - end - end - end - end - end +function Squad.formVengenceSettler(chunk) + deploySquad("Vengence Settler", chunk, AI_VENGENCE_SETTLER_COST, true, false) end function Squad.formSquads(chunk) - local base = chunk.base - if (Universe.squadCount < Universe.AI_MAX_SQUAD_COUNT) - and attackWaveValidCandidate(chunk) - and ((base.unitPoints - AI_SQUAD_COST) > 0) - and (Universe.random() < Universe.formSquadThreshold) - then - if (chunk[BASE_PHEROMONE] < 0.0001) or (chunk[PLAYER_PHEROMONE] < 0.0001) then - return - end + deploySquad("Squad", chunk, AI_SQUAD_COST, false, true) +end - local map = chunk.map - local surface = map.surface - local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y), - validUnitGroupLocation, - scoreUnitGroupLocation, - map) - if (squadPath ~= -1) then - local squadPosition = surface.find_non_colliding_position("biter-spawner", - positionFromDirectionAndChunk(squadDirection, - chunk, - 0.98), - CHUNK_SIZE, - 4, - true) - if squadPosition then - local squad = Squad.createSquad(squadPosition, map, nil, false, base) - - squad.rabid = Universe.random() < 0.03 - - local scaledWaveSize = attackWaveScaling() - Universe.formGroupCommand.group = squad.group - Universe.formCommand.unit_count = scaledWaveSize - local foundUnits = surface.set_multi_command(Universe.formCommand) - if (foundUnits > 0) then - squad.base = base - squad.kamikaze = Universe.random() < Squad.calculateKamikazeSquadThreshold(foundUnits) - Universe.squadCount = Universe.squadCount + 1 - Universe.groupNumberToSquad[squad.groupNumber] = squad - if (base.stateAI == BASE_AI_STATE_AGGRESSIVE) then - base.sentAggressiveGroups = base.sentAggressiveGroups + 1 - end - modifyBaseUnitPoints(base, -AI_SQUAD_COST, "Squad", squadPosition.x, squadPosition.y) - else - if (squad.group.valid) then - squad.group.destroy() - end - end - end - end - end +function Squad.formVengenceSquad(chunk) + deploySquad("Vengence Squad", chunk, AI_VENGENCE_SQUAD_COST, true, true) end function Squad.init(universe) diff --git a/libs/Upgrade.lua b/libs/Upgrade.lua index 4b9814a..1fd2199 100644 --- a/libs/Upgrade.lua +++ b/libs/Upgrade.lua @@ -19,8 +19,6 @@ local Upgrade = {} -- imports local Constants = require("libs/Constants") -local ChunkPropertyUtils = require("libs/ChunkPropertyUtils") -local MapUtils = require("libs/MapUtils") -- @@ -51,8 +49,6 @@ local TICKS_A_MINUTE = Constants.TICKS_A_MINUTE -- imported functions -local addBaseResourceChunk = ChunkPropertyUtils.addBaseResourceChunk - -- module code local function addCommandSet(queriesAndCommands)