mirror of
https://github.com/veden/Rampant.git
synced 2025-09-16 09:16:43 +02:00
finish QA
This commit is contained in:
@@ -217,10 +217,10 @@ function upgrade.attempt(natives)
|
||||
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.22")
|
||||
global.version = constants.VERSION_57
|
||||
end
|
||||
if (global.version < constants.VERSION_67) then
|
||||
if (global.version < constants.VERSION_68) then
|
||||
|
||||
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.32")
|
||||
global.version = constants.VERSION_67
|
||||
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.33")
|
||||
global.version = constants.VERSION_68
|
||||
end
|
||||
|
||||
return starting ~= global.version, natives
|
||||
|
15
control.lua
15
control.lua
@@ -169,6 +169,8 @@ local function rebuildMap()
|
||||
-- prevents queue adding duplicate chunks
|
||||
-- chunks are by key, so should overwrite old
|
||||
|
||||
-- game.forces.enemy.kill_all_units()
|
||||
|
||||
global.map = {}
|
||||
map = global.map
|
||||
map.processQueue = {}
|
||||
@@ -189,6 +191,10 @@ local function rebuildMap()
|
||||
map.chunkToSpawner = {}
|
||||
map.chunkToSettler = {}
|
||||
|
||||
map.chunkToPassable = {}
|
||||
map.chunkToPathRating = {}
|
||||
map.chunkToDeathGenerator = {}
|
||||
|
||||
map.queueSpawners = {}
|
||||
|
||||
-- preallocating memory to be used in code, making it fast by reducing garbage generated.
|
||||
@@ -433,9 +439,9 @@ local function onDeath(event)
|
||||
|
||||
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
-- drop death pheromone where unit died
|
||||
deathScent(chunk)
|
||||
deathScent(map, chunk)
|
||||
|
||||
if event.force and (event.force.name ~= "enemy") and (chunk[MOVEMENT_PHEROMONE] < natives.retreatThreshold) then
|
||||
if event.force and (event.force.name ~= "enemy") and (chunk[MOVEMENT_PHEROMONE] < -natives.retreatThreshold) then
|
||||
local tick = event.tick
|
||||
|
||||
local artilleryBlast = (cause and ((cause.type == "artillery-wagon") or (cause.type == "artillery-turret")))
|
||||
@@ -647,7 +653,7 @@ remote.add_interface("rampantTests",
|
||||
dumpEnvironment = tests.dumpEnvironment,
|
||||
fillableDirtTest = tests.fillableDirtTest,
|
||||
tunnelTest = tests.tunnelTest,
|
||||
dumpNatives = tests.dumpNatives,
|
||||
dumpNatives = tests.dumpatives,
|
||||
createEnemy = tests.createEnemy,
|
||||
attackOrigin = tests.attackOrigin,
|
||||
cheatMode = tests.cheatMode,
|
||||
@@ -665,7 +671,8 @@ remote.add_interface("rampantTests",
|
||||
stepAdvanceTendrils = tests.stepAdvanceTendrils,
|
||||
unitGroupBuild = tests.unitGroupBuild,
|
||||
exportAiState = tests.exportAiState(nil),
|
||||
createEnergyTest = tests.createEnergyTest
|
||||
createEnergyTest = tests.createEnergyTest,
|
||||
killActiveSquads = tests.killActiveSquads
|
||||
}
|
||||
)
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name" : "Rampant",
|
||||
"factorio_version" : "0.16",
|
||||
"version" : "0.16.32",
|
||||
"version" : "0.16.33",
|
||||
"title" : "Rampant",
|
||||
"author" : "Veden",
|
||||
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",
|
||||
|
@@ -4,7 +4,7 @@ local aiAttackWave = {}
|
||||
|
||||
local constants = require("Constants")
|
||||
local mapUtils = require("MapUtils")
|
||||
local chunkPropetyUtils = require("ChunkPropertyUtils")
|
||||
local chunkPropertyUtils = require("ChunkPropertyUtils")
|
||||
local unitGroupUtils = require("UnitGroupUtils")
|
||||
local movementUtils = require("MovementUtils")
|
||||
local mathUtils = require("MathUtils")
|
||||
@@ -19,6 +19,7 @@ local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
||||
local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
|
||||
|
||||
local AI_SQUAD_COST = constants.AI_SQUAD_COST
|
||||
local AI_MAX_SQUAD_COUNT = constants.AI_MAX_SQUAD_COUNT
|
||||
local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST
|
||||
|
||||
local INTERVAL_RALLY = constants.INTERVAL_RALLY
|
||||
@@ -42,7 +43,7 @@ local AI_STATE_RAIDING = constants.AI_STATE_RAIDING
|
||||
|
||||
local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
|
||||
|
||||
local PASSABLE = constants.PASSABLE
|
||||
-- local PASSABLE = constants.PASSABLE
|
||||
|
||||
-- imported functions
|
||||
|
||||
@@ -50,11 +51,12 @@ local mRandom = math.random
|
||||
|
||||
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
|
||||
|
||||
local getNestCount = chunkPropetyUtils.getNestCount
|
||||
local getChunkSettlerTick = chunkPropetyUtils.getChunkSettlerTick
|
||||
local setChunkSettlerTick = chunkPropetyUtils.setChunkSettlerTick
|
||||
local getRallyTick = chunkPropetyUtils.getRallyTick
|
||||
local setRallyTick = chunkPropetyUtils.setRallyTick
|
||||
local getPassable = chunkPropertyUtils.getPassable
|
||||
local getNestCount = chunkPropertyUtils.getNestCount
|
||||
local getChunkSettlerTick = chunkPropertyUtils.getChunkSettlerTick
|
||||
local setChunkSettlerTick = chunkPropertyUtils.setChunkSettlerTick
|
||||
local getRallyTick = chunkPropertyUtils.getRallyTick
|
||||
local setRallyTick = chunkPropertyUtils.setRallyTick
|
||||
|
||||
local gaussianRandomRange = mathUtils.gaussianRandomRange
|
||||
|
||||
@@ -104,7 +106,7 @@ end
|
||||
|
||||
local function validSettlerLocation(map, chunk, neighborChunk)
|
||||
local chunkResource = chunk[RESOURCE_PHEROMONE]
|
||||
return (neighborChunk[PASSABLE] == CHUNK_ALL_DIRECTIONS) and (getNestCount(map, neighborChunk) == 0) and (neighborChunk[RESOURCE_PHEROMONE] >= (chunkResource * RESOURCE_MINIMUM_FORMATION_DELTA))
|
||||
return (getPassable(map, neighborChunk) == CHUNK_ALL_DIRECTIONS) and (getNestCount(map, neighborChunk) == 0) and (neighborChunk[RESOURCE_PHEROMONE] >= (chunkResource * RESOURCE_MINIMUM_FORMATION_DELTA))
|
||||
end
|
||||
|
||||
local function scoreUnitGroupLocation(neighborChunk)
|
||||
@@ -112,7 +114,7 @@ local function scoreUnitGroupLocation(neighborChunk)
|
||||
end
|
||||
|
||||
local function validUnitGroupLocation(map, neighborChunk)
|
||||
return neighborChunk[PASSABLE] == CHUNK_ALL_DIRECTIONS and (getNestCount(map, neighborChunk) == 0)
|
||||
return getPassable(map, neighborChunk) == CHUNK_ALL_DIRECTIONS and (getNestCount(map, neighborChunk) == 0)
|
||||
end
|
||||
|
||||
function aiAttackWave.rallyUnits(chunk, map, surface, natives, tick)
|
||||
@@ -153,7 +155,7 @@ end
|
||||
|
||||
function aiAttackWave.formSettlers(map, surface, natives, chunk, cost, tick)
|
||||
|
||||
if (mRandom() < natives.formSquadThreshold) then
|
||||
if (mRandom() < natives.formSquadThreshold) and (#natives.squads < AI_MAX_SQUAD_COUNT) then
|
||||
|
||||
local squadPath, squadDirection = scoreNeighborsForResource(chunk,
|
||||
getNeighborChunks(map, chunk.x, chunk.y),
|
||||
@@ -201,7 +203,7 @@ end
|
||||
function aiAttackWave.formSquads(map, surface, natives, chunk, cost)
|
||||
local valid = (cost == AI_VENGENCE_SQUAD_COST) or ((cost == AI_SQUAD_COST) and attackWaveValidCandidate(chunk, natives, surface))
|
||||
|
||||
if valid and (mRandom() < natives.formSquadThreshold) then
|
||||
if valid and (mRandom() < natives.formSquadThreshold) and (#natives.squads < AI_MAX_SQUAD_COUNT) then
|
||||
|
||||
local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y),
|
||||
validUnitGroupLocation,
|
||||
|
@@ -1,8 +1,12 @@
|
||||
local chunkPropertyUtils = {}
|
||||
|
||||
local constants = require("Constants")
|
||||
|
||||
-- imported functions
|
||||
|
||||
local tRemove = table.remove
|
||||
local DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
local DEATH_PHEROMONE_DECAY_AMOUNT = constants.DEATH_PHEROMONE_DECAY_AMOUNT
|
||||
local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS
|
||||
|
||||
-- module code
|
||||
|
||||
@@ -102,6 +106,50 @@ function chunkPropertyUtils.addResourceGenerator(map, chunk, delta)
|
||||
map.chunkToResource[chunk] = (map.chunkToResource[chunk] or 0) + delta
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.getDeathGenerator(map, chunk)
|
||||
return map.chunkToDeathGenerator[chunk] or 0
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.getPassable(map, chunk)
|
||||
return map.chunkToPassable[chunk] or CHUNK_ALL_DIRECTIONS
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.setPassable(map, chunk, value)
|
||||
if (value == CHUNK_ALL_DIRECTIONS) then
|
||||
map.chunkToPassable[chunk] = nil
|
||||
else
|
||||
map.chunkToPassable[chunk] = value
|
||||
end
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.getPathRating(map, chunk)
|
||||
return map.chunkToPathRating[chunk] or 1
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.setPathRating(map, chunk, value)
|
||||
if (value == 1) then
|
||||
map.chunkToPathRating[chunk] = nil
|
||||
else
|
||||
map.chunkToPathRating[chunk] = value
|
||||
end
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.addDeathGenerator(map, chunk)
|
||||
map.chunkToDeathGenerator[chunk] = (map.chunkToDeathGenerator[chunk] or 0) + DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.decayDeathGenerator(map, chunk)
|
||||
local gen = map.chunkToDeathGenerator[chunk]
|
||||
if gen and (gen > 0) then
|
||||
gen = gen - DEATH_PHEROMONE_DECAY_AMOUNT
|
||||
end
|
||||
if (gen == 0) then
|
||||
map.chunkToDeathGenerator[chunk] = nil
|
||||
else
|
||||
map.chunkToDeathGenerator[chunk] = gen
|
||||
end
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.getPlayerBaseGenerator(map, chunk)
|
||||
return map.chunkToPlayerBase[chunk] or 0
|
||||
end
|
||||
|
@@ -37,9 +37,9 @@ local CHUNK_TICK = constants.CHUNK_TICK
|
||||
|
||||
local BASE_ALIGNMENT_DEADZONE = constants.BASE_ALIGNMENT_DEADZONE
|
||||
|
||||
local PATH_RATING = constants.PATH_RATING
|
||||
-- local PATH_RATING = constants.PATH_RATING
|
||||
|
||||
local PASSABLE = constants.PASSABLE
|
||||
-- local PASSABLE = constants.PASSABLE
|
||||
|
||||
-- imported functions
|
||||
|
||||
@@ -59,6 +59,8 @@ local createBase = baseUtils.createBase
|
||||
local upgradeEntity = baseUtils.upgradeEntity
|
||||
|
||||
local setChunkBase = chunkPropertyUtils.setChunkBase
|
||||
local setPassable = chunkPropertyUtils.setPassable
|
||||
local setPathRating = chunkPropertyUtils.setPathRating
|
||||
local getEnemyStructureCount = chunkPropertyUtils.getEnemyStructureCount
|
||||
|
||||
local getChunkByXY = mapUtils.getChunkByXY
|
||||
@@ -320,9 +322,8 @@ function chunkUtils.initialScan(chunk, natives, surface, map, tick, evolutionFac
|
||||
setPlayerBaseGenerator(map, chunk, playerObjects)
|
||||
setResourceGenerator(map, chunk, resources)
|
||||
|
||||
|
||||
chunk[PASSABLE] = pass
|
||||
chunk[PATH_RATING] = passScore
|
||||
setPassable(map, chunk, pass)
|
||||
setPathRating(map, chunk, passScore)
|
||||
|
||||
return chunk
|
||||
end
|
||||
@@ -344,8 +345,8 @@ function chunkUtils.chunkPassScan(chunk, surface, map)
|
||||
pass = CHUNK_ALL_DIRECTIONS
|
||||
end
|
||||
|
||||
chunk[PASSABLE] = pass
|
||||
chunk[PATH_RATING] = passScore
|
||||
setPassable(map, chunk, pass)
|
||||
setPathRating(map, chunk, passScore)
|
||||
|
||||
return chunk
|
||||
end
|
||||
@@ -358,6 +359,10 @@ function chunkUtils.analyzeChunk(chunk, natives, surface, map)
|
||||
setPlayerBaseGenerator(map, chunk, playerObjects)
|
||||
local resources = surface.count_entities_filtered(map.countResourcesQuery) * RESOURCE_NORMALIZER
|
||||
setResourceGenerator(map, chunk, resources)
|
||||
local nests = surface.count_entities_filtered(map.filteredEntitiesUnitSpawnereQuery)
|
||||
setNestCount(map, chunk, nests)
|
||||
local worms = surface.count_entities_filtered(map.filteredEntitiesWormQuery)
|
||||
setWormCount(map, chunk, worms)
|
||||
end
|
||||
|
||||
function chunkUtils.createChunk(topX, topY)
|
||||
@@ -369,9 +374,9 @@ function chunkUtils.createChunk(topX, topY)
|
||||
chunk[BASE_PHEROMONE] = 0
|
||||
chunk[PLAYER_PHEROMONE] = 0
|
||||
chunk[RESOURCE_PHEROMONE] = 0
|
||||
chunk[PASSABLE] = 0
|
||||
-- chunk[PASSABLE] = 0
|
||||
chunk[CHUNK_TICK] = 0
|
||||
chunk[PATH_RATING] = 0
|
||||
-- chunk[PATH_RATING] = 0
|
||||
|
||||
return chunk
|
||||
end
|
||||
|
@@ -21,7 +21,7 @@ constants.VERSION_41 = 41
|
||||
constants.VERSION_44 = 44
|
||||
constants.VERSION_51 = 51
|
||||
constants.VERSION_57 = 57
|
||||
constants.VERSION_67 = 67
|
||||
constants.VERSION_68 = 68
|
||||
|
||||
-- misc
|
||||
|
||||
@@ -29,8 +29,9 @@ constants.WATER_TILE_NAMES = { "water", "deepwater", "water-green", "deepwater-g
|
||||
|
||||
constants.MAGIC_MAXIMUM_NUMBER = 1e99 -- used in loops trying to find the lowest/highest score
|
||||
constants.MAGIC_MAXIMUM_BASE_NUMBER = 100000000
|
||||
constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL_MIN = 7500
|
||||
constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL_MAX = 1200000
|
||||
constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL_MIN = 12500
|
||||
constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL_MAX = 900000
|
||||
|
||||
|
||||
constants.PROCESS_QUEUE_SIZE = 400
|
||||
constants.SCAN_QUEUE_SIZE = 5
|
||||
@@ -93,7 +94,7 @@ constants.RAIDING_MINIMUM_BASE_THRESHOLD = 250
|
||||
|
||||
constants.AI_UNIT_REFUND = 3
|
||||
|
||||
-- constants.AI_MAX_SQUAD_COUNT = 30
|
||||
constants.AI_MAX_SQUAD_COUNT = 30
|
||||
constants.AI_MAX_BITER_GROUP_SIZE = 450
|
||||
|
||||
constants.AI_SQUAD_MERGE_THRESHOLD = constants.AI_MAX_BITER_GROUP_SIZE * 0.75
|
||||
@@ -244,14 +245,14 @@ constants.NO_RETREAT_SQUAD_SIZE_BONUS_MAX = 0.40
|
||||
-- pheromone amounts
|
||||
|
||||
constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = 500
|
||||
constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 3000
|
||||
constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 300
|
||||
constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT = 300
|
||||
|
||||
constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT = -0.1
|
||||
|
||||
-- pheromone diffusion amounts
|
||||
|
||||
constants.MOVEMENT_PHEROMONE_PERSISTANCE = 0.99
|
||||
constants.MOVEMENT_PHEROMONE_PERSISTANCE = 0.999
|
||||
constants.BASE_PHEROMONE_PERSISTANCE = 0.99
|
||||
constants.PLAYER_PHEROMONE_PERSISTANCE = 0.98
|
||||
constants.RESOURCE_PHEROMONE_PERSISTANCE = 0.99
|
||||
@@ -263,11 +264,11 @@ constants.BASE_PHEROMONE = 2
|
||||
constants.PLAYER_PHEROMONE = 3
|
||||
constants.RESOURCE_PHEROMONE = 4
|
||||
|
||||
constants.PASSABLE = 5
|
||||
-- constants.PASSABLE = 5
|
||||
|
||||
constants.CHUNK_TICK = 6
|
||||
constants.CHUNK_TICK = 5
|
||||
|
||||
constants.PATH_RATING = 7
|
||||
-- constants.PATH_RATING = 7
|
||||
|
||||
-- Squad status
|
||||
|
||||
@@ -354,9 +355,9 @@ constants.SENTINEL_IMPASSABLE_CHUNK[constants.MOVEMENT_PHEROMONE] = constants.IM
|
||||
constants.SENTINEL_IMPASSABLE_CHUNK[constants.BASE_PHEROMONE] = constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT
|
||||
constants.SENTINEL_IMPASSABLE_CHUNK[constants.PLAYER_PHEROMONE] = constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT
|
||||
constants.SENTINEL_IMPASSABLE_CHUNK[constants.RESOURCE_PHEROMONE] = constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT
|
||||
constants.SENTINEL_IMPASSABLE_CHUNK[constants.PASSABLE] = constants.CHUNK_IMPASSABLE
|
||||
-- constants.SENTINEL_IMPASSABLE_CHUNK[constants.PASSABLE] = constants.CHUNK_IMPASSABLE
|
||||
constants.SENTINEL_IMPASSABLE_CHUNK[constants.CHUNK_TICK] = 0
|
||||
constants.SENTINEL_IMPASSABLE_CHUNK[constants.PATH_RATING] = 0
|
||||
-- constants.SENTINEL_IMPASSABLE_CHUNK[constants.PATH_RATING] = 0
|
||||
constants.SENTINEL_IMPASSABLE_CHUNK.x = -1
|
||||
constants.SENTINEL_IMPASSABLE_CHUNK.y = -1
|
||||
|
||||
@@ -400,6 +401,8 @@ local unitTiers = settings.startup["rampant-newEnemyUnitTiers"].value
|
||||
|
||||
constants.SPAWNER_EGG_TIMEOUT = constants.TICKS_A_SECOND * 5
|
||||
|
||||
constants.DEATH_PHEROMONE_DECAY_AMOUNT = (constants.DEATH_PHEROMONE_GENERATOR_AMOUNT * (constants.INTERVAL_SCAN / constants.TICKS_A_SECOND)) / 15
|
||||
|
||||
constants.NEUTRAL_NEST_TIERS = nestTiers
|
||||
constants.NEUTRAL_NEST_VARIATIONS = nestVariations
|
||||
constants.NEUTRAL_WORM_TIERS = wormTiers
|
||||
@@ -442,7 +445,6 @@ constants.SPAWNER_WORM_VARIATIONS = wormVariations
|
||||
constants.SPAWNER_UNIT_TIERS = unitTiers
|
||||
constants.SPAWNER_UNIT_VARIATIONS = unitVariations
|
||||
|
||||
|
||||
constants.FAST_NEST_TIERS = nestTiers
|
||||
constants.FAST_NEST_VARIATIONS = nestVariations
|
||||
constants.FAST_WORM_TIERS = wormTiers
|
||||
|
@@ -3,6 +3,7 @@ local mapUtils = {}
|
||||
-- imports
|
||||
|
||||
local constants = require("Constants")
|
||||
local chunkPropertyUtils = require("ChunkPropertyUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
@@ -11,7 +12,7 @@ local CHUNK_EAST_WEST = constants.CHUNK_EAST_WEST
|
||||
|
||||
local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS
|
||||
|
||||
local PASSABLE = constants.PASSABLE
|
||||
-- local PASSABLE = constants.PASSABLE
|
||||
|
||||
local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||
|
||||
@@ -22,6 +23,7 @@ local CHUNK_SIZE_DIVIDER = constants.CHUNK_SIZE_DIVIDER
|
||||
-- imported functions
|
||||
|
||||
local mFloor = math.floor
|
||||
local getPassable = chunkPropertyUtils.getPassable
|
||||
|
||||
-- module code
|
||||
|
||||
@@ -101,18 +103,38 @@ function mapUtils.getNeighborChunks(map, x, y)
|
||||
return neighbors
|
||||
end
|
||||
|
||||
function mapUtils.canMoveChunkDirection(direction, startChunk, endChunk)
|
||||
|
||||
--[[
|
||||
1 2 3
|
||||
\|/
|
||||
4- -5
|
||||
/|\
|
||||
6 7 8
|
||||
]]--
|
||||
function mapUtils.canMoveChunkDirection(map, direction, startChunk, endChunk)
|
||||
local canMove = false
|
||||
local startPassable = startChunk[PASSABLE]
|
||||
local endPassable = endChunk[PASSABLE]
|
||||
if (startPassable == CHUNK_ALL_DIRECTIONS) and (endPassable == CHUNK_ALL_DIRECTIONS) then
|
||||
canMove = true
|
||||
elseif ((direction == 2) or (direction == 7)) and (startPassable == CHUNK_NORTH_SOUTH) and (endPassable == CHUNK_NORTH_SOUTH) then
|
||||
canMove = true
|
||||
elseif ((direction == 4) or (direction == 5)) and (startPassable == CHUNK_EAST_WEST) and (endPassable == CHUNK_EAST_WEST) then
|
||||
canMove = true
|
||||
elseif (startChunk == SENTINEL_IMPASSABLE_CHUNK) and (endPassable == CHUNK_ALL_DIRECTIONS) then
|
||||
canMove = true
|
||||
local startPassable = getPassable(map, startChunk)
|
||||
local endPassable = getPassable(map, endChunk)
|
||||
if (startPassable == CHUNK_ALL_DIRECTIONS) then
|
||||
if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then
|
||||
canMove = (endPassable == CHUNK_ALL_DIRECTIONS)
|
||||
elseif (direction == 2) or (direction == 7) then
|
||||
canMove = ((endPassable == CHUNK_NORTH_SOUTH) or (endPassable == CHUNK_ALL_DIRECTIONS))
|
||||
elseif (direction == 4) or (direction == 5) then
|
||||
canMove = ((endPassable == CHUNK_EAST_WEST) or (endPassable == CHUNK_ALL_DIRECTIONS))
|
||||
end
|
||||
elseif (startPassable == CHUNK_NORTH_SOUTH) then
|
||||
if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then
|
||||
canMove = (endPassable == CHUNK_ALL_DIRECTIONS)
|
||||
elseif (direction == 2) or (direction == 7) then
|
||||
canMove = ((endPassable == CHUNK_NORTH_SOUTH) or (endPassable == CHUNK_ALL_DIRECTIONS))
|
||||
end
|
||||
elseif (startPassable == CHUNK_EAST_WEST) then
|
||||
if ((direction == 1) or (direction == 3) or (direction == 6) or (direction == 8)) then
|
||||
canMove = (endPassable == CHUNK_ALL_DIRECTIONS)
|
||||
elseif (direction == 4) or (direction == 5) then
|
||||
canMove = ((endPassable == CHUNK_EAST_WEST) or (endPassable == CHUNK_ALL_DIRECTIONS))
|
||||
end
|
||||
end
|
||||
return canMove
|
||||
end
|
||||
|
@@ -75,13 +75,41 @@ end
|
||||
--[[
|
||||
Expects all neighbors adjacent to a chunk
|
||||
--]]
|
||||
function movementUtils.scoreNeighborsForAttack(chunk, neighborDirectionChunks, scoreFunction, squad)
|
||||
function movementUtils.scoreNeighborsForAttack(map, chunk, neighborDirectionChunks, scoreFunction, squad)
|
||||
local highestChunk = SENTINEL_IMPASSABLE_CHUNK
|
||||
local highestScore = -MAGIC_MAXIMUM_NUMBER
|
||||
local highestDirection
|
||||
for x=1,8 do
|
||||
local neighborChunk = neighborDirectionChunks[x]
|
||||
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(x, chunk, neighborChunk) then
|
||||
|
||||
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(map, x, chunk, neighborChunk) then
|
||||
local score = scoreFunction(squad, neighborChunk)
|
||||
if (score > highestScore) then
|
||||
highestScore = score
|
||||
highestChunk = neighborChunk
|
||||
highestDirection = x
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (scoreFunction(squad, chunk) > highestScore) then
|
||||
return SENTINEL_IMPASSABLE_CHUNK, -1
|
||||
end
|
||||
|
||||
return highestChunk, highestDirection
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
Expects all neighbors adjacent to a chunk
|
||||
--]]
|
||||
function movementUtils.scoreNeighborsForSettling(map, chunk, neighborDirectionChunks, scoreFunction, squad)
|
||||
local highestChunk = SENTINEL_IMPASSABLE_CHUNK
|
||||
local highestScore = -MAGIC_MAXIMUM_NUMBER
|
||||
local highestDirection
|
||||
for x=1,8 do
|
||||
local neighborChunk = neighborDirectionChunks[x]
|
||||
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(map, x, chunk, neighborChunk) then
|
||||
local score = scoreFunction(squad, neighborChunk)
|
||||
if (score > highestScore) then
|
||||
highestScore = score
|
||||
@@ -92,7 +120,7 @@ function movementUtils.scoreNeighborsForAttack(chunk, neighborDirectionChunks, s
|
||||
end
|
||||
|
||||
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (scoreFunction(squad, chunk) > highestScore) then
|
||||
return SENTINEL_IMPASSABLE_CHUNK, -1
|
||||
return chunk, -1
|
||||
end
|
||||
|
||||
return highestChunk, highestDirection
|
||||
@@ -107,7 +135,7 @@ function movementUtils.scoreNeighborsForResource(chunk, neighborDirectionChunks,
|
||||
local highestDirection
|
||||
for x=1,8 do
|
||||
local neighborChunk = neighborDirectionChunks[x]
|
||||
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(x, chunk, neighborChunk) and validFunction(map, chunk, neighborChunk) then
|
||||
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(map, x, chunk, neighborChunk) and validFunction(map, chunk, neighborChunk) then
|
||||
local score = scoreFunction(neighborChunk)
|
||||
if (score > highestScore) then
|
||||
highestScore = score
|
||||
@@ -117,7 +145,7 @@ function movementUtils.scoreNeighborsForResource(chunk, neighborDirectionChunks,
|
||||
end
|
||||
end
|
||||
|
||||
if scoreFunction(chunk) > highestScore then
|
||||
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (scoreFunction(chunk) > highestScore) then
|
||||
return SENTINEL_IMPASSABLE_CHUNK, -1
|
||||
end
|
||||
|
||||
@@ -133,7 +161,7 @@ function movementUtils.scoreNeighborsForRetreat(chunk, neighborDirectionChunks,
|
||||
local highestDirection
|
||||
for x=1,8 do
|
||||
local neighborChunk = neighborDirectionChunks[x]
|
||||
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(x, chunk, neighborChunk) then
|
||||
if (neighborChunk ~= SENTINEL_IMPASSABLE_CHUNK) and canMoveChunkDirection(map, x, chunk, neighborChunk) then
|
||||
local score = scoreFunction(map, neighborChunk)
|
||||
if (score > highestScore) then
|
||||
highestScore = score
|
||||
|
@@ -16,23 +16,24 @@ local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
|
||||
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
|
||||
|
||||
local PLAYER_PHEROMONE_GENERATOR_AMOUNT = constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT
|
||||
local DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
|
||||
local MOVEMENT_PHEROMONE_PERSISTANCE = constants.MOVEMENT_PHEROMONE_PERSISTANCE
|
||||
local BASE_PHEROMONE_PERSISTANCE = constants.BASE_PHEROMONE_PERSISTANCE
|
||||
local PLAYER_PHEROMONE_PERSISTANCE = constants.PLAYER_PHEROMONE_PERSISTANCE
|
||||
local RESOURCE_PHEROMONE_PERSISTANCE = constants.RESOURCE_PHEROMONE_PERSISTANCE
|
||||
|
||||
local PATH_RATING = constants.PATH_RATING
|
||||
|
||||
-- imported functions
|
||||
|
||||
local getCardinalChunks = mapUtils.getCardinalChunks
|
||||
|
||||
local mMax = math.max
|
||||
local getEnemyStructureCount = chunkPropertyUtils.getEnemyStructureCount
|
||||
local getPathRating = chunkPropertyUtils.getPathRating
|
||||
local getPlayerBaseGenerator = chunkPropertyUtils.getPlayerBaseGenerator
|
||||
local getResourceGenerator = chunkPropertyUtils.getResourceGenerator
|
||||
local getDeathGenerator = chunkPropertyUtils.getDeathGenerator
|
||||
local addDeathGenerator = chunkPropertyUtils.addDeathGenerator
|
||||
|
||||
local decayDeathGenerator = chunkPropertyUtils.decayDeathGenerator
|
||||
|
||||
local linearInterpolation = mathUtils.linearInterpolation
|
||||
|
||||
@@ -42,6 +43,8 @@ function pheromoneUtils.scents(map, chunk)
|
||||
chunk[BASE_PHEROMONE] = chunk[BASE_PHEROMONE] + getPlayerBaseGenerator(map, chunk)
|
||||
local resourceGenerator = getResourceGenerator(map, chunk)
|
||||
local enemyCount = getEnemyStructureCount(map, chunk)
|
||||
chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] - getDeathGenerator(map, chunk)
|
||||
decayDeathGenerator(map, chunk)
|
||||
if (resourceGenerator > 0) and (enemyCount == 0) then
|
||||
chunk[RESOURCE_PHEROMONE] = chunk[RESOURCE_PHEROMONE] + linearInterpolation(resourceGenerator, 9000, 10000)
|
||||
end
|
||||
@@ -50,12 +53,12 @@ end
|
||||
function pheromoneUtils.victoryScent(chunk, entityType)
|
||||
local value = BUILDING_PHEROMONES[entityType]
|
||||
if value then
|
||||
chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] + (value * 10000)
|
||||
chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] + (value * 1000)
|
||||
end
|
||||
end
|
||||
|
||||
function pheromoneUtils.deathScent(chunk)
|
||||
chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] - DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
function pheromoneUtils.deathScent(map, chunk)
|
||||
addDeathGenerator(map, chunk)
|
||||
end
|
||||
|
||||
function pheromoneUtils.playerScent(playerChunk)
|
||||
@@ -68,7 +71,7 @@ function pheromoneUtils.processPheromone(map, chunk)
|
||||
local chunkBase = chunk[BASE_PHEROMONE]
|
||||
local chunkPlayer = chunk[PLAYER_PHEROMONE]
|
||||
local chunkResource = chunk[RESOURCE_PHEROMONE]
|
||||
local chunkPathRating = chunk[PATH_RATING]
|
||||
local chunkPathRating = getPathRating(map, chunk)
|
||||
|
||||
local clear = (getEnemyStructureCount(map, chunk) == 0)
|
||||
|
||||
@@ -111,7 +114,7 @@ function pheromoneUtils.processPheromone(map, chunk)
|
||||
resourceTotal = resourceTotal + (neighbor[RESOURCE_PHEROMONE] - chunkResource)
|
||||
end
|
||||
|
||||
chunk[MOVEMENT_PHEROMONE] = (chunkMovement + (0.125 * movementTotal)) * MOVEMENT_PHEROMONE_PERSISTANCE * chunkPathRating
|
||||
chunk[MOVEMENT_PHEROMONE] = (chunkMovement + (0.35 * movementTotal)) * MOVEMENT_PHEROMONE_PERSISTANCE * chunkPathRating
|
||||
chunk[BASE_PHEROMONE] = (chunkBase + (0.35 * baseTotal)) * BASE_PHEROMONE_PERSISTANCE * chunkPathRating
|
||||
chunk[PLAYER_PHEROMONE] = (chunkPlayer + (0.25 * playerTotal)) * PLAYER_PHEROMONE_PERSISTANCE * chunkPathRating
|
||||
if clear then
|
||||
|
@@ -66,6 +66,7 @@ local getPlayerBaseGenerator = chunkPropertyUtils.getPlayerBaseGenerator
|
||||
local getResourceGenerator = chunkPropertyUtils.getResourceGenerator
|
||||
|
||||
local scoreNeighborsForAttack = movementUtils.scoreNeighborsForAttack
|
||||
local scoreNeighborsForSettling = movementUtils.scoreNeighborsForSettling
|
||||
|
||||
-- module code
|
||||
|
||||
@@ -91,11 +92,12 @@ local function settleMove(map, attackPosition, attackCmd, settleCmd, squad, grou
|
||||
local groupPosition = group.position
|
||||
local x, y = positionToChunkXY(groupPosition)
|
||||
local chunk = getChunkByXY(map, x, y)
|
||||
local attackChunk, attackDirection = scoreNeighborsForAttack(chunk,
|
||||
getNeighborChunks(map, x, y),
|
||||
((natives.state == AI_STATE_SIEGE) and scoreSiegeLocation) or
|
||||
scoreResourceLocation,
|
||||
squad)
|
||||
local attackChunk, attackDirection = scoreNeighborsForSettling(map,
|
||||
chunk,
|
||||
getNeighborChunks(map, x, y),
|
||||
((natives.state == AI_STATE_SIEGE) and scoreSiegeLocation) or
|
||||
scoreResourceLocation,
|
||||
squad)
|
||||
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
addSquadToChunk(map, chunk, squad)
|
||||
addMovementPenalty(natives, squad, chunk)
|
||||
@@ -148,7 +150,8 @@ local function attackMove(map, attackPosition, attackCmd, squad, group, natives,
|
||||
local groupPosition = group.position
|
||||
local x, y = positionToChunkXY(groupPosition)
|
||||
local chunk = getChunkByXY(map, x, y)
|
||||
local attackChunk, attackDirection = scoreNeighborsForAttack(chunk,
|
||||
local attackChunk, attackDirection = scoreNeighborsForAttack(map,
|
||||
chunk,
|
||||
getNeighborChunks(map, x, y),
|
||||
scoreAttackLocation,
|
||||
squad)
|
||||
|
4
make.rkt
4
make.rkt
@@ -80,7 +80,7 @@
|
||||
(copyDirectory "prototypes" modFolder)))
|
||||
|
||||
(define (run)
|
||||
;;(copyFiles modFolder)
|
||||
(copyFiles modFolder)
|
||||
;;(copyFiles zipModFolder)
|
||||
(makeZip modFolder)
|
||||
;; (makeZip modFolder)
|
||||
(system*/exit-code "/data/games/factorio/bin/x64/factorio")))
|
||||
|
42
tests.lua
42
tests.lua
@@ -47,6 +47,20 @@ function tests.pheromoneLevels(size)
|
||||
end
|
||||
end
|
||||
|
||||
function tests.killActiveSquads()
|
||||
print("--")
|
||||
for i=1, #global.natives.squads do
|
||||
local squad = global.natives.squads[i]
|
||||
if (squad.group.valid) then
|
||||
local members = squad.group.members
|
||||
for x=1, #members do
|
||||
local member = members[x]
|
||||
local val = member.valid and member.die()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tests.activeSquads()
|
||||
print("--")
|
||||
for i=1, #global.natives.squads do
|
||||
@@ -312,11 +326,11 @@ function tests.showMovementGrid()
|
||||
for i=1,#chunks do
|
||||
local chunk = chunks[i]
|
||||
local color = "concrete"
|
||||
if (chunk[constants.PASSABLE] == constants.CHUNK_ALL_DIRECTIONS) then
|
||||
if (chunkPropertyUtils.getPassable(global.map, chunk) == constants.CHUNK_ALL_DIRECTIONS) then
|
||||
color = "hazard-concrete-left"
|
||||
elseif (chunk[constants.PASSABLE] == constants.CHUNK_NORTH_SOUTH) then
|
||||
elseif (chunkPropertyUtils.getPassable(global.map, chunk) == constants.CHUNK_NORTH_SOUTH) then
|
||||
color = "deepwater"
|
||||
elseif (chunk[constants.PASSABLE] == constants.CHUNK_EAST_WEST) then
|
||||
elseif (chunkPropertyUtils.getPassable(global.map, chunk) == constants.CHUNK_EAST_WEST) then
|
||||
color = "water-green"
|
||||
end
|
||||
chunkUtils.colorChunk(chunk.x, chunk.y, color, game.surfaces[global.natives.activeSurface])
|
||||
@@ -363,9 +377,9 @@ function tests.exportAiState()
|
||||
chunk[constants.BASE_PHEROMONE],
|
||||
chunk[constants.PLAYER_PHEROMONE],
|
||||
chunk[constants.RESOURCE_PHEROMONE],
|
||||
chunk[constants.PASSABLE],
|
||||
-- chunk[constants.PASSABLE],
|
||||
chunk[constants.CHUNK_TICK],
|
||||
chunk[constants.PATH_RATING],
|
||||
-- chunk[constants.PATH_RATING],
|
||||
chunk.x,
|
||||
chunk.y,
|
||||
chunkPropertyUtils.getNestCount(global.map, chunk),
|
||||
@@ -412,15 +426,15 @@ function tests.createEnergyTest(x)
|
||||
entity.connect_neighbour(entities[1])
|
||||
end
|
||||
|
||||
-- if wires then
|
||||
-- for connectType,neighbourGroup in pairs(wires) do
|
||||
-- if connectType == "copper" then
|
||||
-- for _,v in pairs(neighbourGroup) do
|
||||
-- ;
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- if wires then
|
||||
-- for connectType,neighbourGroup in pairs(wires) do
|
||||
-- if connectType == "copper" then
|
||||
-- for _,v in pairs(neighbourGroup) do
|
||||
-- ;
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
end
|
||||
|
||||
function tests.unitGroupBuild()
|
||||
|
Reference in New Issue
Block a user