From c3d658b4a28a6332bff8674306929c782bcca9c5 Mon Sep 17 00:00:00 2001 From: veden Date: Thu, 18 Aug 2016 15:14:40 -0700 Subject: [PATCH] unit attack player and location, unit retreat work pretty well. Still needs balancing --- control.lua | 3 +- libs/AIAttack.lua | 74 ++++++++++++++++++++++++++++++----------- libs/AIDefense.lua | 9 ++++- libs/Constants.lua | 31 ++++++++--------- libs/PheromoneUtils.lua | 27 +++++++-------- libs/UnitGroupUtils.lua | 2 ++ libs/Utils.lua | 24 ++++++------- tests.lua | 13 ++++++++ 8 files changed, 120 insertions(+), 63 deletions(-) diff --git a/control.lua b/control.lua index 722a2b5..220cd5d 100755 --- a/control.lua +++ b/control.lua @@ -187,5 +187,6 @@ script.on_event(defines.events.on_chunk_generated, onChunkGenerated) remote.add_interface("rampant", { test1 = tests.test1, test2 = tests.test2, - test3 = tests.test3 + test3 = tests.test3, + test4 = tests.test4 }) diff --git a/libs/AIAttack.lua b/libs/AIAttack.lua index 30d2ede..828471f 100755 --- a/libs/AIAttack.lua +++ b/libs/AIAttack.lua @@ -13,11 +13,21 @@ local attackLocationNeighbors = {1,2,3,4,5,6,7,8} local attackLocationCommand = {type=defines.command.attack_area, destination=attackPosition, radius=constants.HALF_CHUNK_SIZE, - distraction=defines.distraction.by_damage} + distraction=defines.distraction.by_anything} + +local attackObjectCommand = {type=defines.command.attack, + target=1, + distraction=defines.distraction.by_anything} local attackPlayerCommand = {type=defines.command.attack, target=1} +local nearestAreaBox = {{1,2}, + {3,4}} +local nearestTable = {area=nearestAreaBox, + force="player", + limit=1} + local mRandom = math.random function aiAttack.squadAttackLocation(regionMap, surface, natives) @@ -35,6 +45,7 @@ function aiAttack.squadAttackLocation(regionMap, surface, natives) local group_states = factorio_defined.group_state local mathRandom = mRandom + -- local getNeighborChunks = mapUtils.getCardinalChunks local getNeighborChunks = mapUtils.getNeighborChunks local positionToChunk = mapUtils.positionToChunkOffset @@ -44,8 +55,14 @@ function aiAttack.squadAttackLocation(regionMap, surface, natives) local group = squad.group local squadStatus = squad.status if group.valid and ((squadStatus == SQUAD_RAIDING) or (squadStatus == SQUAD_SUICIDE_RAID)) then - if (group.state == group_states.finished) or (group.state == group_states.gathering) then - local cX, cY = positionToChunk(group.position) + if ((group.state == group_states.finished) or (group.state == group_states.gathering) or (group.state == group_states.moving)) and (squad.cycles == 0) then + local cX, cY + -- if (squad.cX == nil) then + cX, cY = positionToChunk(group.position) + -- else + -- cX = squad.cX + -- cY = squad.cY + -- end getNeighborChunks(regionMap, cX, cY, attackLocationNeighbors) local attackChunk local attackScore = -MAGIC_MAXIMUM_NUMBER @@ -56,8 +73,8 @@ function aiAttack.squadAttackLocation(regionMap, surface, natives) if (neighborChunk ~= nil) then attackPosition.x = neighborChunk.pX attackPosition.y = neighborChunk.pY - local damageScore = surface.get_pollution(attackPosition) + neighborChunk[PLAYER_BASE_PHEROMONE] + neighborChunk[PLAYER_PHEROMONE] --+ neighborChunk[PLAYER_DEFENSE_PHEROMONE] - local avoidScore = neighborChunk[DEATH_PHEROMONE] --+ neighborChunk[ENEMY_BASE_GENERATOR] + neighborChunk[ENEMY_BASE_PHEROMONE] + local damageScore = surface.get_pollution(attackPosition) + neighborChunk[PLAYER_BASE_PHEROMONE] + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[constants.PLAYER_DEFENSE_GENERATOR] + local avoidScore = neighborChunk[DEATH_PHEROMONE] + neighborChunk[ENEMY_BASE_GENERATOR] + neighborChunk[ENEMY_BASE_PHEROMONE] -- local score = damageScore - avoidScore if (score > attackScore) then attackScore = score @@ -70,21 +87,40 @@ function aiAttack.squadAttackLocation(regionMap, surface, natives) if (attackChunk ~= nil) then -- print("==") -- print (attackDirection, cX, cY) - -- utils.positionDirectionToChunkCorner(attackDirection, attackChunk, attackPosition) - attackPosition.x = attackChunk.pX + HALF_CHUNK_SIZE - attackPosition.y = attackChunk.pY + HALF_CHUNK_SIZE - - group.set_command(attackLocationCommand) - group.start_moving() - end - elseif (group.state == group_states.attacking_distraction) and (mathRandom() < 0.3) then - local playerTarget = surface.find_nearest_enemy({position=group.position, - max_distance=CHUNK_SIZE, - force="enemy"}) - if (playerTarget ~= nil) then - group.set_command({type=defines.command.attack, - target=playerTarget}) + -- local target + if (attackChunk[constants.PLAYER_BASE_GENERATOR] == 0) or (attackChunk[constants.PLAYER_DEFENSE_GENERATOR] == 0) then + -- nearestAreaBox[1][1] = group.position.x - CHUNK_SIZE + -- nearestAreaBox[1][2] = group.position.y - CHUNK_SIZE + -- nearestAreaBox[2][1] = group.position.x + CHUNK_SIZE + -- nearestAreaBox[2][2] = group.position.y + CHUNK_SIZE + -- target = surface.find_entities_filtered(nearestTable) + -- if (#target == 1) and (target[1].prototype.max_health ~= 0) then + -- print(target[1].name) + -- attackObjectCommand.target = target[1] + -- group.set_command(attackObjectCommand) + -- end + + -- if (target == nil) then + -- utils.positionDirectionToChunkCorner(attackDirection, attackChunk, attackPosition) + attackPosition.x = attackChunk.pX + HALF_CHUNK_SIZE + attackPosition.y = attackChunk.pY + HALF_CHUNK_SIZE + squad.cycles = 4 + squad.cX = attackChunk.cX + squad.cY = attackChunk.cY + + group.set_command(attackLocationCommand) + -- end + group.start_moving() + end end + -- elseif (group.state == group_states.attacking_distraction) and (mathRandom() < 0.3) then + -- local playerTarget = surface.find_nearest_enemy({position=group.position, + -- max_distance=CHUNK_SIZE, + -- force="enemy"}) + -- if (playerTarget ~= nil) then + -- group.set_command({type=defines.command.attack, + -- target=playerTarget}) + -- end end end end diff --git a/libs/AIDefense.lua b/libs/AIDefense.lua index e327da3..4478c0e 100755 --- a/libs/AIDefense.lua +++ b/libs/AIDefense.lua @@ -48,7 +48,7 @@ function aiDefense.retreatUnits(position, squad, regionMap, surface, natives) retreatPosition.x = neighborChunk.pX retreatPosition.y = neighborChunk.pY - local dangerScore = neighborChunk[DEATH_PHEROMONE] + surface.get_pollution(retreatPosition) + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[PLAYER_DEFENSE_PHEROMONE] - neighborChunk[ENEMY_BASE_PHEROMONE] + neighborChunk[ENEMY_BASE_GENERATOR] + local dangerScore = neighborChunk[DEATH_PHEROMONE] + surface.get_pollution(retreatPosition) + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[PLAYER_DEFENSE_PHEROMONE] - neighborChunk[ENEMY_BASE_PHEROMONE] + (neighborChunk[ENEMY_BASE_GENERATOR] * 5) if (dangerScore < exitScore) then exitScore = dangerScore exitPath = neighborChunk @@ -60,7 +60,14 @@ function aiDefense.retreatUnits(position, squad, regionMap, surface, natives) utils.positionDirectionToChunkCorner(exitDirection, exitPath, retreatPosition) -- in order for units in a group attacking to retreat, we have to create a new group and give the command to join -- to each unit + -- retreatPosition.x = exitPath.pX + constants.HALF_CHUNK_SIZE + -- retreatPosition.y = exitPath.pY + constants.HALF_CHUNK_SIZE + if (squad ~= nil) and (squad.cX ~= nil) then + local chunk = mapUtils.getChunkByIndex(regionMap, squad.cX, squad.cY) + chunk[constants.DEATH_PHEROMONE] = chunk[constants.DEATH_PHEROMONE] + constants.DEATH_PHEROMONE_GENERATOR_AMOUNT + end + local newSquad = unitGroupUtils.findNearBySquad(natives, retreatPosition, constants.HALF_CHUNK_SIZE, diff --git a/libs/Constants.lua b/libs/Constants.lua index ffe7229..0e7ff44 100755 --- a/libs/Constants.lua +++ b/libs/Constants.lua @@ -10,6 +10,7 @@ constants.RETREAT_LEVEL_DEATH_PHEROMONE = 15000 constants.CHUNK_SIZE = 32 constants.HALF_CHUNK_SIZE = constants.CHUNK_SIZE / 2 +constants.QUARTER_CHUNK_SIZE = constants.HALF_CHUNK_SIZE / 2 constants.NORTH_SOUTH = 1 constants.EAST_WEST = 2 @@ -17,13 +18,13 @@ constants.EAST_WEST = 2 constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = 150 constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = 35 -constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 400 +constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 25 constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT = 75 -- pheromone diffusion amounts constants.STANDARD_PHERONOME_DIFFUSION_AMOUNT = 0.03 -constants.DEATH_PHEROMONE_DIFFUSION_AMOUNT = 0.03 +constants.DEATH_PHEROMONE_DIFFUSION_AMOUNT = 0.00 -- chunk attributes @@ -59,30 +60,30 @@ constants.SQUAD_SUICIDE_RAID = 9 -- when player stuff is close with no retreat constants.buildingPheromones = {} -- constants.buildingPheromones["container"] = 1 -- constants.buildingPheromones["storage-tank"] = 1 --- constants.buildingPheromones["transport-belt"] = 1 -constants.buildingPheromones["generator"] = 35 --- constants.buildingPheromones["electric-pole"] = 1 -constants.buildingPheromones["pump"] = 10 -constants.buildingPheromones["offshore-pump"] = 10 +constants.buildingPheromones["generator"] = 30 +constants.buildingPheromones["pump"] = 4 +constants.buildingPheromones["offshore-pump"] = 4 -- constants.buildingPheromones["constant-combinator"] = 1 -- constants.buildingPheromones["train-stop"] = 2 -- constants.buildingPheromones["rail-signal"] = 1 +constants.buildingPheromones["electric-pole"] = 2 +constants.buildingPheromones["transport-belt"] = 2 constants.buildingPheromones["accumulator"] = 20 -constants.buildingPheromones["solar-panel"] = 10 +constants.buildingPheromones["solar-panel"] = 16 constants.buildingPheromones["boiler"] = 30 -constants.buildingPheromones["assembling-machine"] = 25 +constants.buildingPheromones["assembling-machine"] = 24 constants.buildingPheromones["roboport"] = 20 -constants.buildingPheromones["beacon"] = 15 -constants.buildingPheromones["furnace"] = 20 +constants.buildingPheromones["beacon"] = 20 +constants.buildingPheromones["furnace"] = 30 constants.buildingPheromones["mining-drill"] = 40 -- player defense pheromones constants.defensePheromones = {} -constants.defensePheromones["ammo-turret"] = 10 -constants.defensePheromones["electric-turret"] = 10 -constants.defensePheromones["fluid-turret"] = 15 -constants.defensePheromones["turret"] = 5 +constants.defensePheromones["ammo-turret"] = 5 +constants.defensePheromones["electric-turret"] = 7.5 +constants.defensePheromones["fluid-turret"] = 10 +constants.defensePheromones["turret"] = 3 -- enemy units diff --git a/libs/PheromoneUtils.lua b/libs/PheromoneUtils.lua index 8049695..429b15f 100755 --- a/libs/PheromoneUtils.lua +++ b/libs/PheromoneUtils.lua @@ -12,18 +12,15 @@ local nearestTable = {position=nearestEnemyPosition, function pheromoneUtils.deathScent(regionMap, surface, x, y, amount) - -- nearestEnemyPosition.x = x - -- nearestEnemyPosition.y = y - -- local playerKiller = surface.find_nearest_enemy(nearestTable) - -- if (playerKiller ~= nil) then - -- local chunk = regionMap[mathFloor(playerKiller.position.x * 0.03125)] - -- if (chunk ~= nil) then - -- chunk = chunk[mathFloor(playerKiller.position.y * 0.03125)] - -- if (chunk ~= nil) then - -- chunk[DEATH_PHEROMONE] = chunk[DEATH_PHEROMONE] + amount - -- end - -- end - -- end + nearestEnemyPosition.x = x + nearestEnemyPosition.y = y + local playerKiller = surface.find_nearest_enemy(nearestTable) + if (playerKiller ~= nil) then + local chunk = mapUtils.getChunkByPosition(regionMap, x, y) + if (chunk ~= nil) then + chunk[constants.DEATH_PHEROMONE] = chunk[constants.DEATH_PHEROMONE] + amount + end + end local chunk = mapUtils.getChunkByPosition(regionMap, x, y) if (chunk ~= nil) then @@ -41,7 +38,7 @@ end function pheromoneUtils.playerBaseScent(regionMap, surface, natives, chunk, neighbors) local baseScore = chunk[constants.PLAYER_BASE_GENERATOR] if (baseScore > 0) then - chunk[constants.PLAYER_BASE_PHEROMONE] = chunk[constants.PLAYER_BASE_PHEROMONE] + baseScore + chunk[constants.PLAYER_BASE_PHEROMONE] = chunk[constants.PLAYER_BASE_PHEROMONE] + (baseScore * 2) end end @@ -78,10 +75,10 @@ function pheromoneUtils.processPheromone(regionMap, surface, natives, chunk, nei local persistence if (x == DEATH_PHEROMONE) then diffusionAmount = DEATH_PHEROMONE_DIFFUSION_AMOUNT - persistence = 0.99 + persistence = 0.98 else diffusionAmount = STANDARD_PHERONOME_DIFFUSION_AMOUNT - persistence = 0.98 + persistence = 0.95 end local totalDiffused = 0 for i=1,4 do diff --git a/libs/UnitGroupUtils.lua b/libs/UnitGroupUtils.lua index fd69239..04eab24 100755 --- a/libs/UnitGroupUtils.lua +++ b/libs/UnitGroupUtils.lua @@ -116,6 +116,8 @@ function unitGroupUtils.regroupSquads(natives) table.remove(squads, i) else if (squad.status == SQUAD_RETREATING) and (squad.cycles == 0) then + squad.cX = nil + squad.cY = nil squad.status = SQUAD_GUARDING elseif (squad.cycles > 0) then squad.cycles = squad.cycles - 1 diff --git a/libs/Utils.lua b/libs/Utils.lua index 5eb1ae1..fa3ad21 100755 --- a/libs/Utils.lua +++ b/libs/Utils.lua @@ -17,29 +17,29 @@ end function utils.positionDirectionToChunkCorner(direction, chunk, position) -- local position = {} if (direction == 1) then - position.x = chunk.pX - position.y = chunk.pY + position.x = chunk.pX + constants.QUARTER_CHUNK_SIZE + position.y = chunk.pY + constants.QUARTER_CHUNK_SIZE elseif (direction == 2) then position.x = chunk.pX + constants.HALF_CHUNK_SIZE - position.y = chunk.pY + position.y = chunk.pY + constants.QUARTER_CHUNK_SIZE elseif (direction == 3) then - position.x = chunk.pX + constants.CHUNK_SIZE - position.y = chunk.pY + position.x = chunk.pX + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE + position.y = chunk.pY + constants.QUARTER_CHUNK_SIZE elseif (direction == 4) then - position.x = chunk.pX + position.x = chunk.pX + constants.QUARTER_CHUNK_SIZE position.y = chunk.pY + constants.HALF_CHUNK_SIZE elseif (direction == 5) then - position.x = chunk.pX + constants.CHUNK_SIZE + position.x = chunk.pX + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE position.y = chunk.pY + constants.HALF_CHUNK_SIZE elseif (direction == 6) then - position.x = chunk.pX - position.y = chunk.pY + constants.CHUNK_SIZE + position.x = chunk.pX + constants.QUARTER_CHUNK_SIZE + position.y = chunk.pY + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE elseif (direction == 7) then position.x = chunk.pX + constants.HALF_CHUNK_SIZE - position.y = chunk.pY + constants.CHUNK_SIZE + position.y = chunk.pY + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE elseif (direction == 8) then - position.x = chunk.pX + constants.CHUNK_SIZE - position.y = chunk.pY + constants.CHUNK_SIZE + position.x = chunk.pX + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE + position.y = chunk.pY + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE end return position end diff --git a/tests.lua b/tests.lua index 34633d2..9a74b76 100755 --- a/tests.lua +++ b/tests.lua @@ -51,4 +51,17 @@ function tests.test3() print("--") end +function tests.test4() + local playerPosition = game.players[1].position + local chunkX = math.floor(playerPosition.x * 0.03125) * 32 + local chunkY = math.floor(playerPosition.y * 0.03125) * 32 + local entity = game.surfaces[1].find_nearest_enemy({position={chunkX, chunkY}, + max_distance=constants.CHUNK_SIZE, + force = "enemy"}) + if (entity ~= nil) then + print(entity.name) + end + print("--") +end + return tests \ No newline at end of file