2016-08-18 07:55:08 +02:00
|
|
|
local aiDefense = {}
|
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
-- imports
|
|
|
|
|
2016-08-18 07:55:08 +02:00
|
|
|
local constants = require("Constants")
|
|
|
|
local mapUtils = require("MapUtils")
|
|
|
|
local unitGroupUtils = require("UnitGroupUtils")
|
2016-08-27 08:44:17 +02:00
|
|
|
local neighborUtils = require("NeighborUtils")
|
2016-08-18 07:55:08 +02:00
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
-- constants
|
|
|
|
|
2017-01-20 07:58:36 +02:00
|
|
|
local RETREAT_GRAB_RADIUS = constants.RETREAT_GRAB_RADIUS
|
|
|
|
|
2016-10-15 02:00:18 +02:00
|
|
|
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
2016-08-20 04:52:27 +02:00
|
|
|
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
2016-10-15 02:00:18 +02:00
|
|
|
local BASE_PHEROMONE = constants.BASE_PHEROMONE
|
2016-08-20 04:52:27 +02:00
|
|
|
|
|
|
|
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
|
|
|
|
|
|
|
local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE
|
|
|
|
|
|
|
|
local SQUAD_RETREATING = constants.SQUAD_RETREATING
|
|
|
|
|
2016-08-25 01:30:45 +02:00
|
|
|
local RETREAT_FILTER = constants.RETREAT_FILTER
|
|
|
|
|
2017-04-22 01:14:04 +02:00
|
|
|
local RETREAT_TRIGGERED = constants.RETREAT_TRIGGERED
|
|
|
|
|
|
|
|
local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
|
|
|
|
|
2016-08-20 04:52:27 +02:00
|
|
|
-- imported functions
|
|
|
|
|
2016-08-27 08:44:17 +02:00
|
|
|
local getNeighborChunksWithDirection = mapUtils.getNeighborChunksWithDirection
|
2016-08-20 04:52:27 +02:00
|
|
|
local findNearBySquad = unitGroupUtils.findNearBySquad
|
2016-09-14 19:53:49 +02:00
|
|
|
local addSquadMovementPenalty = unitGroupUtils.addSquadMovementPenalty
|
2016-08-20 04:52:27 +02:00
|
|
|
local createSquad = unitGroupUtils.createSquad
|
|
|
|
local membersToSquad = unitGroupUtils.membersToSquad
|
2016-08-27 08:44:17 +02:00
|
|
|
local scoreNeighborsWithDirection = neighborUtils.scoreNeighborsWithDirection
|
2016-10-31 05:24:14 +02:00
|
|
|
local canMoveChunkDirection = mapUtils.canMoveChunkDirection
|
2016-08-20 04:52:27 +02:00
|
|
|
|
|
|
|
-- module code
|
2016-08-18 07:55:08 +02:00
|
|
|
|
2016-08-27 08:44:17 +02:00
|
|
|
local function validRetreatLocation(x, chunk, neighborChunk)
|
2016-10-31 05:24:14 +02:00
|
|
|
return canMoveChunkDirection(x, chunk, neighborChunk)
|
2016-08-27 08:44:17 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function scoreRetreatLocation(position, squad, neighborChunk, surface)
|
2016-10-15 02:00:18 +02:00
|
|
|
local safeScore = -neighborChunk[BASE_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE]
|
2017-04-22 01:14:04 +02:00
|
|
|
local dangerScore = surface.get_pollution(position) + (neighborChunk[PLAYER_PHEROMONE] * 100) + (neighborChunk[ENEMY_BASE_GENERATOR] * 50)
|
2016-08-28 04:03:36 +02:00
|
|
|
return safeScore - dangerScore
|
2016-08-27 08:44:17 +02:00
|
|
|
end
|
|
|
|
|
2017-04-22 01:14:04 +02:00
|
|
|
function aiDefense.retreatUnits(chunk, squad, regionMap, surface, natives, tick)
|
|
|
|
if (tick - chunk[RETREAT_TRIGGERED] > INTERVAL_LOGIC) and (chunk[ENEMY_BASE_GENERATOR] == 0) then
|
2016-11-04 01:51:35 +02:00
|
|
|
local performRetreat = false
|
|
|
|
local enemiesToSquad
|
2016-08-18 07:55:08 +02:00
|
|
|
|
2016-11-04 01:51:35 +02:00
|
|
|
if (squad == nil) then
|
2017-01-20 07:58:36 +02:00
|
|
|
enemiesToSquad = surface.find_enemy_units({x=chunk.pX,
|
|
|
|
y=chunk.pY}, RETREAT_GRAB_RADIUS)
|
2016-11-04 01:51:35 +02:00
|
|
|
if (#enemiesToSquad > 0) then
|
|
|
|
performRetreat = true
|
|
|
|
end
|
|
|
|
elseif squad.group.valid and (squad.status ~= SQUAD_RETREATING) and not squad.kamikaze then
|
|
|
|
if (#squad.group.members > 1) then
|
|
|
|
performRetreat = true
|
|
|
|
end
|
|
|
|
end
|
2016-08-18 07:55:08 +02:00
|
|
|
|
2016-11-04 01:51:35 +02:00
|
|
|
if performRetreat then
|
2017-04-22 01:14:04 +02:00
|
|
|
chunk[RETREAT_TRIGGERED] = tick
|
2016-09-13 01:23:26 +02:00
|
|
|
local retreatPosition = {x=0, y=0}
|
2016-11-04 01:51:35 +02:00
|
|
|
local exitPath,_ = scoreNeighborsWithDirection(chunk,
|
2016-09-13 01:23:26 +02:00
|
|
|
getNeighborChunksWithDirection(regionMap, chunk.cX, chunk.cY),
|
2016-08-30 06:08:22 +02:00
|
|
|
validRetreatLocation,
|
|
|
|
scoreRetreatLocation,
|
|
|
|
nil,
|
|
|
|
surface,
|
2016-11-04 01:51:35 +02:00
|
|
|
retreatPosition,
|
|
|
|
false)
|
|
|
|
if (exitPath ~= nil) then
|
|
|
|
retreatPosition.x = exitPath.pX + HALF_CHUNK_SIZE
|
|
|
|
retreatPosition.y = exitPath.pY + HALF_CHUNK_SIZE
|
2016-08-30 06:08:22 +02:00
|
|
|
|
2016-11-04 01:51:35 +02:00
|
|
|
-- 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, this is the only way I have found to have snappy mid battle retreats even after 0.14.4
|
2016-08-27 08:44:17 +02:00
|
|
|
|
2016-11-04 01:51:35 +02:00
|
|
|
local newSquad = findNearBySquad(natives, retreatPosition, HALF_CHUNK_SIZE, RETREAT_FILTER)
|
2016-08-27 08:44:17 +02:00
|
|
|
|
2016-11-04 01:51:35 +02:00
|
|
|
if (newSquad == nil) then
|
|
|
|
newSquad = createSquad(retreatPosition, surface, natives)
|
|
|
|
newSquad.status = SQUAD_RETREATING
|
|
|
|
newSquad.cycles = 4
|
|
|
|
end
|
2016-08-30 06:08:22 +02:00
|
|
|
|
2016-11-04 01:51:35 +02:00
|
|
|
if (enemiesToSquad ~= nil) then
|
|
|
|
membersToSquad(newSquad, enemiesToSquad, false)
|
|
|
|
else
|
|
|
|
membersToSquad(newSquad, squad.group.members, true)
|
2016-09-14 19:53:49 +02:00
|
|
|
newSquad.penalties = squad.penalties
|
2016-09-14 19:12:29 +02:00
|
|
|
if squad.rabid then
|
|
|
|
newSquad.rabid = true
|
|
|
|
end
|
2016-11-04 01:51:35 +02:00
|
|
|
end
|
2016-09-14 19:53:49 +02:00
|
|
|
addSquadMovementPenalty(newSquad, chunk.cX, chunk.cY)
|
2016-11-04 01:51:35 +02:00
|
|
|
end
|
|
|
|
end
|
2016-08-18 07:55:08 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-08-30 06:08:22 +02:00
|
|
|
return aiDefense
|