-- Copyright (C) 2022 veden -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . if movementUtilsG then return movementUtilsG end local movementUtils = {} -- imports local constants = require("Constants") local mapUtils = require("MapUtils") local mathUtils = require("MathUtils") local unitGroupUtils = require("UnitGroupUtils") -- constants local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER local SQUAD_SETTLING = constants.SQUAD_SETTLING -- imported functions local calculateSettlerMaxDistance = unitGroupUtils.calculateSettlerMaxDistance local canMoveChunkDirection = mapUtils.canMoveChunkDirection local getNeighborChunks = mapUtils.getNeighborChunks local tableRemove = table.remove local tableInsert = table.insert local distortPosition = mathUtils.distortPosition -- module code function movementUtils.findMovementPosition(surface, position) local pos = position pos = surface.find_non_colliding_position("chunk-scanner-squad-movement-rampant", pos, 10, 2, false) return pos end function movementUtils.findMovementPositionEntity(entityName, surface, position) local pos = position pos = surface.find_non_colliding_position(entityName, pos, 5, 4, true) return pos end function movementUtils.findMovementPositionDistort(surface, position) local pos = position pos = surface.find_non_colliding_position("chunk-scanner-squad-movement-rampant", pos, 10, 2, false) return distortPosition(pos, 8) end function movementUtils.addMovementPenalty(squad, chunk) if (chunk == -1) then return end local penalties = squad.penalties local penaltyCount = #penalties for i=1,penaltyCount do local penalty = penalties[i] if (penalty.c.id == chunk.id) then penalty.v = penalty.v + 1 if (penalty.v > 2) and (penalty.v < 15) then squad.kamikaze = true elseif penalty.v >= 15 then local universe = squad.map.universe if universe.enabledMigration and (universe.builderCount < universe.AI_MAX_BUILDER_COUNT) then squad.settler = true squad.originPosition.x = squad.group.position.x squad.originPosition.y = squad.group.position.y squad.maxDistance = calculateSettlerMaxDistance(universe) squad.status = SQUAD_SETTLING else squad.group.destroy() end end return end end if (penaltyCount == 10) then tableRemove(penalties, 10) end tableInsert(penalties, 1, { v = 1, c = chunk }) end --[[ Expects all neighbors adjacent to a chunk --]] function movementUtils.scoreNeighborsForAttack(map, chunk, neighborDirectionChunks, scoreFunction) local highestChunk = -1 local highestScore = -MAGIC_MAXIMUM_NUMBER local highestDirection 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 (score > highestScore) then highestScore = score highestChunk = neighborChunk highestDirection = x end end end end local nextHighestChunk = -1 local nextHighestScore = highestScore local nextHighestDirection if (highestChunk ~= -1) then neighborDirectionChunks = getNeighborChunks(map, highestChunk.x, highestChunk.y) 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) if (score > nextHighestScore) then nextHighestScore = score nextHighestChunk = neighborChunk nextHighestDirection = x end end end end return highestChunk, highestDirection, nextHighestChunk, nextHighestDirection end --[[ Expects all neighbors adjacent to a chunk --]] function movementUtils.scoreNeighborsForSettling(map, chunk, neighborDirectionChunks, scoreFunction) local highestChunk = -1 local highestScore = -MAGIC_MAXIMUM_NUMBER local highestDirection = 0 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 (score > highestScore) then highestScore = score highestChunk = neighborChunk highestDirection = x end end end end if (chunk ~= -1) and (scoreFunction(map, chunk) > highestScore) then return chunk, 0, -1, 0 end local nextHighestChunk = -1 local nextHighestScore = highestScore local nextHighestDirection = 0 if (highestChunk ~= -1) then neighborDirectionChunks = getNeighborChunks(map, highestChunk.x, highestChunk.y) 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) if (score > nextHighestScore) then nextHighestScore = score nextHighestChunk = neighborChunk nextHighestDirection = x end end end end return highestChunk, highestDirection, nextHighestChunk, nextHighestDirection end --[[ Expects all neighbors adjacent to a chunk --]] function movementUtils.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 --]] function movementUtils.scoreNeighborsForRetreat(chunk, neighborDirectionChunks, scoreFunction, map) local highestChunk = -1 local highestScore = -MAGIC_MAXIMUM_NUMBER local highestDirection 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 (score > highestScore) then highestScore = score highestChunk = neighborChunk highestDirection = x end end end end local nextHighestChunk = -1 local nextHighestScore = highestScore local nextHighestDirection if (highestChunk ~= -1) then neighborDirectionChunks = getNeighborChunks(map, highestChunk.x, highestChunk.y) 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) if (score > nextHighestScore) then nextHighestScore = score nextHighestChunk = neighborChunk nextHighestDirection = x end end end end if (nextHighestChunk == nil) then nextHighestChunk = -1 end return highestChunk, highestDirection, nextHighestChunk, nextHighestDirection end --[[ Expects all neighbors adjacent to a chunk --]] function movementUtils.scoreNeighborsForFormation(neighborChunks, validFunction, scoreFunction, map) local highestChunk = -1 local highestScore = -MAGIC_MAXIMUM_NUMBER local highestDirection for x=1,8 do local neighborChunk = neighborChunks[x] if (neighborChunk ~= -1) and validFunction(map, neighborChunk) then local score = scoreFunction(map, neighborChunk) if (score > highestScore) then highestScore = score highestChunk = neighborChunk highestDirection = x end end end return highestChunk, highestDirection end movementUtilsG = movementUtils return movementUtils