From 63eed3e08b6bbeb99a45b39e785cfcb7570a15d3 Mon Sep 17 00:00:00 2001 From: Aaron Veden Date: Tue, 4 Apr 2023 22:37:58 -0700 Subject: [PATCH] FACTO-287: Re-added kamikaze state and pheromone --- changelog.txt | 2 ++ libs/ChunkUtils.lua | 4 +++- libs/Constants.lua | 11 +++++---- libs/MapUtils.lua | 18 +++++++++++++-- libs/Squad.lua | 48 +++++++++++++++++++++++++++++++++++++++ libs/Upgrade.lua | 21 +++++++++++++++++ tests.lua | 3 ++- visualizer/parseState.rkt | 15 ++++++++---- visualizer/visual.rkt | 2 +- 9 files changed, 109 insertions(+), 15 deletions(-) diff --git a/changelog.txt b/changelog.txt index efadd58..2616dc8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,6 @@ Version: 3.2.3 + Improvements: + - Re-added kamikaze squad state to prevent unit group dancing and then disbanding Bugfixes: - Fixed occasionally compression number wouldn't appear on unit group - Fixed squad compression could take place when attacking diff --git a/libs/ChunkUtils.lua b/libs/ChunkUtils.lua index 6738050..b8e01c4 100644 --- a/libs/ChunkUtils.lua +++ b/libs/ChunkUtils.lua @@ -49,6 +49,7 @@ local BASE_PHEROMONE = Constants.BASE_PHEROMONE local PLAYER_PHEROMONE = Constants.PLAYER_PHEROMONE local RESOURCE_PHEROMONE = Constants.RESOURCE_PHEROMONE local ENEMY_PHEROMONE = Constants.ENEMY_PHEROMONE +local KAMIKAZE_PHEROMONE = Constants.KAMIKAZE_PHEROMONE local BUILDING_PHEROMONES = Constants.BUILDING_PHEROMONES local CHUNK_SIZE = Constants.CHUNK_SIZE @@ -396,11 +397,12 @@ function ChunkUtils.createChunk(map, topX, topY) id = newChunkId(), map = map } + chunk[CHUNK_TICK] = 0 chunk[BASE_PHEROMONE] = 0 chunk[PLAYER_PHEROMONE] = 0 chunk[RESOURCE_PHEROMONE] = 0 chunk[ENEMY_PHEROMONE] = 0 - chunk[CHUNK_TICK] = 0 + chunk[KAMIKAZE_PHEROMONE] = 0 return chunk end diff --git a/libs/Constants.lua b/libs/Constants.lua index dca1b26..5ff418f 100644 --- a/libs/Constants.lua +++ b/libs/Constants.lua @@ -189,11 +189,12 @@ constants.PLAYER_GENERATOR_PERSISTANCE = 0.92 -- chunk attributes -constants.BASE_PHEROMONE = 1 -constants.PLAYER_PHEROMONE = 2 -constants.RESOURCE_PHEROMONE = 3 -constants.ENEMY_PHEROMONE = 4 -constants.CHUNK_TICK = 5 +constants.CHUNK_TICK = 1 +constants.BASE_PHEROMONE = 2 +constants.PLAYER_PHEROMONE = 3 +constants.RESOURCE_PHEROMONE = 4 +constants.ENEMY_PHEROMONE = 5 +constants.KAMIKAZE_PHEROMONE = 6 -- constants.PATH_RATING = 7 diff --git a/libs/MapUtils.lua b/libs/MapUtils.lua index e814ce0..21a40ae 100644 --- a/libs/MapUtils.lua +++ b/libs/MapUtils.lua @@ -39,6 +39,7 @@ local BASE_PHEROMONE = Constants.BASE_PHEROMONE local PLAYER_PHEROMONE = Constants.PLAYER_PHEROMONE local RESOURCE_PHEROMONE = Constants.RESOURCE_PHEROMONE local ENEMY_PHEROMONE = Constants.ENEMY_PHEROMONE +local KAMIKAZE_PHEROMONE = Constants.KAMIKAZE_PHEROMONE local CHUNK_TICK = Constants.CHUNK_TICK @@ -575,6 +576,7 @@ function MapUtils.processPheromone(chunk, tick, player) local chunkDeath = getCombinedDeathGenerator(chunk) local chunkResource = -MAGIC_MAXIMUM_NUMBER local chunkEnemy = chunk[ENEMY_PHEROMONE] + local chunkKamikaze = chunk[KAMIKAZE_PHEROMONE] local chunkCount = 1 @@ -590,6 +592,10 @@ function MapUtils.processPheromone(chunk, tick, player) chunkPlayer = chunkPlayer + neighbor[PLAYER_PHEROMONE] chunkEnemy = chunkEnemy + neighbor[ENEMY_PHEROMONE] chunkDeath = chunkDeath + getCombinedDeathGenerator(neighbor) + tempPheromone = neighbor[KAMIKAZE_PHEROMONE] + if chunkKamikaze < tempPheromone then + chunkKamikaze = tempPheromone + end tempPheromone = neighbor[BASE_PHEROMONE] if chunkBase < tempPheromone then chunkBase = tempPheromone @@ -612,12 +618,12 @@ function MapUtils.processPheromone(chunk, tick, player) local chunkDeathRating = getCombinedDeathGeneratorRating(chunk) * getPathRating(chunk) - chunk[PLAYER_PHEROMONE] = chunkDeathRating * mMax( + chunk[PLAYER_PHEROMONE] = mMax( chunk.playerGenerator or 0, (chunkPlayer / chunkCount) * 0.98 ) - chunk[BASE_PHEROMONE] = chunkDeathRating * mMax( + chunk[BASE_PHEROMONE] = mMax( chunk.playerBaseGenerator or 0, chunkBase * 0.9 ) @@ -627,6 +633,14 @@ function MapUtils.processPheromone(chunk, tick, player) (chunkEnemy / chunkCount) * 0.9 ) + chunk[KAMIKAZE_PHEROMONE] = mMax( + chunkKamikaze, + chunk[PLAYER_PHEROMONE] + chunk[BASE_PHEROMONE] + ) * 0.95 + + chunk[PLAYER_PHEROMONE] = chunk[PLAYER_PHEROMONE] * chunkDeathRating + chunk[BASE_PHEROMONE] = chunk[BASE_PHEROMONE] * chunkDeathRating + local resourcePheromoneGenerator = chunk.resourceGenerator or 0 if (resourcePheromoneGenerator > 0) then chunkResource = linearInterpolation(resourcePheromoneGenerator, 15000, 20000) diff --git a/libs/Squad.lua b/libs/Squad.lua index 80a5758..c6c2ac1 100644 --- a/libs/Squad.lua +++ b/libs/Squad.lua @@ -45,6 +45,7 @@ local COMMAND_TIMEOUT = Constants.COMMAND_TIMEOUT local PLAYER_PHEROMONE = Constants.PLAYER_PHEROMONE local BASE_PHEROMONE = Constants.BASE_PHEROMONE local ENEMY_PHEROMONE = Constants.ENEMY_PHEROMONE +local KAMIKAZE_PHEROMONE = Constants.KAMIKAZE_PHEROMONE local RESOURCE_PHEROMONE = Constants.RESOURCE_PHEROMONE local HALF_CHUNK_SIZE = Constants.HALF_CHUNK_SIZE @@ -161,6 +162,23 @@ local function scoreSiegeLocation(neighborChunk) return score, preferred end +local function scoreSiegeKamikazeLocation(neighborChunk) + local preferred = false + if ( + not neighborChunk.playerBaseGenerator + and not neighborChunk.playerGenerator + ) + then + preferred = true + end + local settle = neighborChunk[KAMIKAZE_PHEROMONE] + + neighborChunk[RESOURCE_PHEROMONE] * 0.5 + + local score = settle - neighborChunk[ENEMY_PHEROMONE] + + return score, preferred +end + local function scoreAttackLocation(neighborChunk) local preferred = false if ( @@ -178,6 +196,22 @@ local function scoreAttackLocation(neighborChunk) return damage, preferred end +local function scoreAttackKamikazeLocation(neighborChunk) + local preferred = false + if ( + neighborChunk.playerBaseGenerator + or neighborChunk.playerGenerator + ) + then + preferred = true + end + local damage = neighborChunk[KAMIKAZE_PHEROMONE] + if preferred then + damage = damage * 2 + end + return damage, preferred +end + local function findMovementPosition(surface, position) return surface.find_non_colliding_position( "behemoth-biter", @@ -238,7 +272,15 @@ local function addMovementPenalty(squad, chunk) squad.maxDistance = calculateSettlerMaxDistance() squad.status = SQUAD_SETTLING + elseif not squad.kamikaze then + squad.kamikaze = true + squad.penalties = {} else + for entity in pairs(squad.group.members) do + if entity.valid then + entity.destroy() + end + end squad.group.destroy() end end @@ -405,6 +447,9 @@ local function settleMove(squad) local scoreFunction = scoreResourceLocation if (squad.type == BASE_AI_STATE_SIEGE) then scoreFunction = scoreSiegeLocation + if squad.kamikaze then + scoreFunction = scoreSiegeKamikazeLocation + end end local squadChunk = squad.chunk if squadChunk ~= -1 then @@ -549,6 +594,9 @@ local function attackMove(squad) end local attackScorer = scoreAttackLocation + if squad.kamikaze then + attackScorer = scoreAttackKamikazeLocation + end squad.frenzy = (squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100)) local searchPath = scoreNeighbors( diff --git a/libs/Upgrade.lua b/libs/Upgrade.lua index d1e911a..5b8f0bc 100644 --- a/libs/Upgrade.lua +++ b/libs/Upgrade.lua @@ -26,6 +26,13 @@ local Universe -- Constants +local BASE_PHEROMONE = Constants.BASE_PHEROMONE +local PLAYER_PHEROMONE = Constants.PLAYER_PHEROMONE +local RESOURCE_PHEROMONE = Constants.RESOURCE_PHEROMONE +local ENEMY_PHEROMONE = Constants.ENEMY_PHEROMONE +local KAMIKAZE_PHEROMONE = Constants.KAMIKAZE_PHEROMONE +local CHUNK_TICK = Constants.CHUNK_TICK + local MINIMUM_EXPANSION_DISTANCE = Constants.MINIMUM_EXPANSION_DISTANCE local DEFINES_COMMAND_GROUP = defines.command.group local DEFINES_COMMAND_WANDER = defines.command.wander @@ -552,6 +559,20 @@ function Upgrade.attempt() Universe.modAddedTick = game.tick end + if global.gameVersion < 2 then + global.gameVersion = 2 + + for _, map in pairs(Universe.maps) do + for _, chunk in pairs(map.processQueue) do + chunk[CHUNK_TICK] = 0 + chunk[BASE_PHEROMONE] = 0 + chunk[PLAYER_PHEROMONE] = 0 + chunk[RESOURCE_PHEROMONE] = 0 + chunk[ENEMY_PHEROMONE] = 0 + chunk[KAMIKAZE_PHEROMONE] = 0 + end + end + end end function Upgrade.init(universe) diff --git a/tests.lua b/tests.lua index cb4e56a..36079d0 100644 --- a/tests.lua +++ b/tests.lua @@ -215,7 +215,8 @@ function tests.exportAiState() chunk.hiveCount or 0, chunk.trapCount or 0, chunk.utilityCount or 0, - global.universe.chunkToVictory[chunk.id] or 0 + global.universe.chunkToVictory[chunk.id] or 0, + chunk[constants.KAMIKAZE_PHEROMONE] }, ",") .. "\n" end game.write_file("rampantState.txt", s, false) diff --git a/visualizer/parseState.rkt b/visualizer/parseState.rkt index 8b09d6b..50a2956 100644 --- a/visualizer/parseState.rkt +++ b/visualizer/parseState.rkt @@ -58,7 +58,8 @@ hives traps utility - vg) + vg + kamikaze) #:transparent) (struct Chunk (x @@ -92,7 +93,8 @@ hives traps utility - vg) + vg + kamikaze) #:transparent) (require threading) @@ -143,7 +145,8 @@ "H:" (~v (Chunk-hives chunk)) "\n" "T:" (~v (Chunk-traps chunk)) "\n" "U:" (~v (Chunk-utility chunk)) "\n" - "vg:" (~v (Chunk-vg chunk)) "\n")) + "vg:" (~v (Chunk-vg chunk)) "\n" + "kam:" (~v (Chunk-kamikaze chunk)) "\n"))) (define (normalizeRange xs) (let* ((sDev (stddev xs)) @@ -187,7 +190,8 @@ (H (map Chunk-hives chunks)) (T (map Chunk-traps chunks)) (U (map Chunk-utility chunks)) - (vg (map Chunk-vg chunks))) + (vg (map Chunk-vg chunks)) + (kamikaze (map Chunk-kamikaze chunks))) (ChunkRange (MinMax (apply min xs) (apply max xs)) (MinMax (apply min ys) (apply max ys)) @@ -220,7 +224,8 @@ (MinMax (apply min H) (apply max H)) (MinMax (apply min T) (apply max T)) (MinMax (apply min U) (apply max U)) - (MinMax (apply min vg) (apply max vg))) + (MinMax (apply min vg) (apply max vg)) + (normalizeRange kamikaze) )) (define (readState filePath) diff --git a/visualizer/visual.rkt b/visualizer/visual.rkt index 64f4deb..f55321b 100644 --- a/visualizer/visual.rkt +++ b/visualizer/visual.rkt @@ -279,7 +279,7 @@ (new radio-box% [label "Show Layer"] - [choices (list "movement" "base" "player" "resource" "enemy" "passable" "tick" "rating" "nests" "worms" "rally" "retreat" "resourceGen" "playerGen" "deathGen" "scoreResourceKamikaze" "scoreResource" "scoreSiegeKamikaze" "scoreSiege" "scoreAttackKamikaze" "scoreAttack" "pollution" "aNe" "aRNe" "squads" "baseAlign" "hives" "traps" "utility" "vg")] + [choices (list "movement" "base" "player" "resource" "enemy" "passable" "tick" "rating" "nests" "worms" "rally" "retreat" "resourceGen" "playerGen" "deathGen" "scoreResourceKamikaze" "scoreResource" "scoreSiegeKamikaze" "scoreSiege" "scoreAttackKamikaze" "scoreAttack" "pollution" "aNe" "aRNe" "squads" "baseAlign" "hives" "traps" "utility" "vg" "kamikaze")] [selection 0] [parent botPanel] (callback (lambda (radioButton event)