mirror of
https://github.com/veden/Rampant.git
synced 2025-01-14 02:23:01 +02:00
see changelog 0.14.4
This commit is contained in:
parent
04c184078d
commit
d989322407
1
.gitignore
vendored
1
.gitignore
vendored
@ -47,3 +47,4 @@ luac.out
|
|||||||
*.dumpjump
|
*.dumpjump
|
||||||
/.emacs.desktop
|
/.emacs.desktop
|
||||||
/.emacs.desktop.lock
|
/.emacs.desktop.lock
|
||||||
|
/README.html
|
||||||
|
63
README.md
63
README.md
@ -7,6 +7,7 @@ https://forums.factorio.com/viewtopic.php?f=94&t=31445
|
|||||||
|
|
||||||
# Notes
|
# Notes
|
||||||
|
|
||||||
|
0.14.14 factorio version fixed save corruption
|
||||||
0.14.10 factorio version fixed more pathing issues
|
0.14.10 factorio version fixed more pathing issues
|
||||||
0.14.4 factorio version fixed some issues with unit groups commands
|
0.14.4 factorio version fixed some issues with unit groups commands
|
||||||
|
|
||||||
@ -33,36 +34,56 @@ Base Expansion
|
|||||||
|
|
||||||
# Version History
|
# Version History
|
||||||
|
|
||||||
0.14.3 - slightly lowered Rampant attack wave frequency
|
0.14.4 -
|
||||||
Altered attack wave size to ramp up slower
|
- Fixed a bug in the processing queue when upgrading mod
|
||||||
Added configuration options for:
|
- Greatly decreased Player pheromone radius, now sits at roughly 4 chunks around the player
|
||||||
attack wave generation area
|
- Reworked pheromone pathfinding
|
||||||
attack wave threshold
|
- Removed base and defense attack wave trigger, in favor of using player pheromone and pollution
|
||||||
attack wave size
|
- Added periods of time where the enemy is not sending Rampant attack waves
|
||||||
turn off rampant attack waves
|
- Adjusted retreat percentage to suit the reduced attack wave size
|
||||||
|
- Improved responsiveness on larger maps
|
||||||
|
- Reduced AI max build points
|
||||||
|
- Fixed player iteration bug
|
||||||
|
|
||||||
0.14.2 - adjusted unit retreat group size threshold
|
0.14.3 -
|
||||||
adjusted squad attack pattern (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=20#p203861)
|
- Slightly lowered Rampant attack wave frequency
|
||||||
Fixed migration issue
|
- Altered attack wave size to ramp up slower
|
||||||
|
- Added configuration options for:
|
||||||
|
- - Attack wave generation area
|
||||||
|
- - Attack wave threshold
|
||||||
|
- - Attack wave size
|
||||||
|
- - Turn off rampant attack waves
|
||||||
|
|
||||||
0.14.1 - fixed ai created bases not being counted in logic
|
0.14.2 -
|
||||||
Optimization to offset ai created bases scanning
|
- Adjusted unit retreat group size threshold
|
||||||
|
- Adjusted squad attack pattern (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=20#p203861)
|
||||||
|
- Fixed migration issue
|
||||||
|
|
||||||
|
0.14.1 -
|
||||||
|
- Fixed ai created bases not being counted in logic
|
||||||
|
- Optimization to offset ai created bases scanning
|
||||||
|
|
||||||
|
0.13.4 = 0.14.4
|
||||||
|
|
||||||
0.13.3 = 0.14.3
|
0.13.3 = 0.14.3
|
||||||
|
|
||||||
0.13.2 = 0.14.2
|
0.13.2 = 0.14.2
|
||||||
|
|
||||||
0.13.1 - backported 0.14 factorio version to 0.13 factorio version
|
0.13.1 - Backported 0.14 factorio version to 0.13 factorio version
|
||||||
|
|
||||||
0.0.8 - fixed retreat oscillations (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=10#p198750)
|
0.0.8 -
|
||||||
added scaling for kamikaze attack (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=10#p199401)
|
- Fixed retreat oscillations (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=10#p198750)
|
||||||
increased squad size max from 125 to 150, (larger waves)
|
- Added scaling for kamikaze attack (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=10#p199401)
|
||||||
|
- Increased squad size max from 125 to 150, (larger waves)
|
||||||
|
|
||||||
0.0.6 - some speed improvements
|
0.0.6 -
|
||||||
MP is working (https://github.com/veden/Rampant/issues/1)
|
- Some speed improvements
|
||||||
|
- MP is working (https://github.com/veden/Rampant/issues/1)
|
||||||
|
|
||||||
0.0.5 - fix for nil chunk in ai attack (https://mods.factorio.com/mods/Veden/Rampant/discussion/2512)
|
0.0.5 -
|
||||||
checks for main surface (https://forums.factorio.com/viewtopic.php?f=94&t=31445&p=198228#p198563)
|
- Fix for nil chunk in ai attack (https://mods.factorio.com/mods/Veden/Rampant/discussion/2512)
|
||||||
updated info with forum homepage
|
- Xhecks for main surface (https://forums.factorio.com/viewtopic.php?f=94&t=31445&p=198228#p198563)
|
||||||
|
- Updated info with forum homepage
|
||||||
|
|
||||||
0.0.4 - initial release
|
0.0.4 - initial release
|
||||||
|
|
||||||
|
28
config.lua
28
config.lua
@ -4,29 +4,37 @@ local config = {}
|
|||||||
the attackWaveGenerationUse* options are used to score chunks with biter nests that will generate a Rampant attack wave.
|
the attackWaveGenerationUse* options are used to score chunks with biter nests that will generate a Rampant attack wave.
|
||||||
Pollution, the vanilla pollution mechanic (shown on the minimap).
|
Pollution, the vanilla pollution mechanic (shown on the minimap).
|
||||||
Player Proximity, if a player moves near a biter nest there is a chance for the nest to spawn attack waves (not shown on the minimap).
|
Player Proximity, if a player moves near a biter nest there is a chance for the nest to spawn attack waves (not shown on the minimap).
|
||||||
Player Base Proximity, if the player builds near biters nest there is a chance for the nest to spawn attack waves (not shown on the minimap).
|
switching all to false will turn off Rampant biter waves
|
||||||
Player Defense Proximity, if the player builds defense near biters nest there is a chance for the nest to spawn attack waves (not shown on the minimap).
|
DOES NOT affect vanilla biters waves
|
||||||
switching all to false will turn off Rampant biter waves, does not turn off vanilla biter waves.
|
|
||||||
--]]
|
--]]
|
||||||
config.attackWaveGenerationUsePollution = true
|
config.attackWaveGenerationUsePollution = true
|
||||||
config.attackWaveGenerationUsePlayerProximity = true
|
config.attackWaveGenerationUsePlayerProximity = true
|
||||||
config.attackWaveGenerationUsePlayerBaseProximity = true
|
|
||||||
config.attackWaveGenerationUsePlayerDefenseProximity = true
|
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
attackWaveGenerationThreshold is the score that the attackWaveGenerationUse* has to reach in order for an attack wave to spawn.
|
attackWaveGenerationThreshold is the score that the attackWaveGenerationUse* has to reach in order for an attack wave to spawn.
|
||||||
increasing this will reduce the radius of attack wave generation.
|
increasing this will reduce the radius of attack wave generation.
|
||||||
default number is 70
|
DOES NOT affect vanilla biters waves
|
||||||
|
scaling linearly with evolution factor
|
||||||
|
starts 20 @ 0.0 evolution
|
||||||
|
ends 0 @ 100.0 evolution
|
||||||
|
default max is 20
|
||||||
|
default min is 00
|
||||||
--]]
|
--]]
|
||||||
config.attackWaveGenerationThreshold = 70
|
config.attackWaveGenerationThresholdMax = 20
|
||||||
|
config.attackWaveGenerationThresholdMin = 0
|
||||||
|
|
||||||
|
--[[
|
||||||
|
attackWaveMaxSize is the largest size that can be initially spawned by Rampant
|
||||||
|
--]]
|
||||||
|
config.attackWaveMaxSize = 150
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
attackWaveScaling is used to calculate the attack wave size from the evolutionFactor
|
attackWaveScaling is used to calculate the attack wave size from the evolutionFactor
|
||||||
default is 150 * (evolutionFactor ^ 1.666667)
|
default is config.attackWaveMaxSize * (evolutionFactor ^ 1.666667)
|
||||||
150 is the max group size
|
DOES NOT affect vanilla biters waves
|
||||||
--]]
|
--]]
|
||||||
config.attackWaveScaling = function (evolutionFactor)
|
config.attackWaveScaling = function (evolutionFactor)
|
||||||
return math.ceil(150 * (evolutionFactor ^ 1.666667))
|
return math.ceil(config.attackWaveMaxSize * (evolutionFactor ^ 1.666667))
|
||||||
end
|
end
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
114
control.lua
114
control.lua
@ -9,20 +9,27 @@ local pheromoneUtils = require("libs/PheromoneUtils")
|
|||||||
local aiDefense = require("libs/AIDefense")
|
local aiDefense = require("libs/AIDefense")
|
||||||
local aiAttack = require("libs/AIAttack")
|
local aiAttack = require("libs/AIAttack")
|
||||||
local aiBuilding = require("libs/AIBuilding")
|
local aiBuilding = require("libs/AIBuilding")
|
||||||
|
local aiPlanning = require("libs/AIPlanning")
|
||||||
|
local mathUtils = require("libs/MathUtils")
|
||||||
local tests = require("tests")
|
local tests = require("tests")
|
||||||
|
|
||||||
|
-- constants
|
||||||
|
|
||||||
|
local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
|
||||||
|
local INTERVAL_PROCESS = constants.INTERVAL_PROCESS
|
||||||
|
|
||||||
-- imported functions
|
-- imported functions
|
||||||
|
|
||||||
local processPendingChunks = chunkProcessor.processPendingChunks
|
local processPendingChunks = chunkProcessor.processPendingChunks
|
||||||
|
|
||||||
local processMap = mapProcessor.processMap
|
local processMap = mapProcessor.processMap
|
||||||
|
local processPlayers = mapProcessor.processPlayers
|
||||||
local scanMap = mapProcessor.scanMap
|
local scanMap = mapProcessor.scanMap
|
||||||
|
|
||||||
local accumulatePoints = aiBuilding.accumulatePoints
|
local planning = aiPlanning.planning
|
||||||
local removeScout = aiBuilding.removeScout
|
local removeScout = aiBuilding.removeScout
|
||||||
-- local scouting = aiBuilding.scouting
|
-- local scouting = aiBuilding.scouting
|
||||||
|
|
||||||
local playerScent = pheromoneUtils.playerScent
|
|
||||||
local deathScent = pheromoneUtils.deathScent
|
local deathScent = pheromoneUtils.deathScent
|
||||||
|
|
||||||
local regroupSquads = unitGroupUtils.regroupSquads
|
local regroupSquads = unitGroupUtils.regroupSquads
|
||||||
@ -35,6 +42,8 @@ local retreatUnits = aiDefense.retreatUnits
|
|||||||
|
|
||||||
local addRemoveEntity = entityUtils.addRemoveEntity
|
local addRemoveEntity = entityUtils.addRemoveEntity
|
||||||
|
|
||||||
|
local roundToNearest = mathUtils.roundToNearest
|
||||||
|
|
||||||
-- local references to global
|
-- local references to global
|
||||||
|
|
||||||
local regionMap
|
local regionMap
|
||||||
@ -44,11 +53,9 @@ local pendingChunks
|
|||||||
-- hook functions
|
-- hook functions
|
||||||
|
|
||||||
local function onLoad()
|
local function onLoad()
|
||||||
-- print("load")
|
|
||||||
regionMap = global.regionMap
|
regionMap = global.regionMap
|
||||||
natives = global.natives
|
natives = global.natives
|
||||||
pendingChunks = global.pendingChunks
|
pendingChunks = global.pendingChunks
|
||||||
-- pheromoneTotals = global.pheromoneTotals
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function onChunkGenerated(event)
|
local function onChunkGenerated(event)
|
||||||
@ -60,7 +67,6 @@ local function onChunkGenerated(event)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function onConfigChanged()
|
local function onConfigChanged()
|
||||||
-- print("reprocess")
|
|
||||||
if (global.version == nil) then
|
if (global.version == nil) then
|
||||||
|
|
||||||
-- removed in version 9
|
-- removed in version 9
|
||||||
@ -84,11 +90,6 @@ local function onConfigChanged()
|
|||||||
regionMap.pP = nil
|
regionMap.pP = nil
|
||||||
regionMap.pR = nil
|
regionMap.pR = nil
|
||||||
|
|
||||||
regionMap.processQueue = {}
|
|
||||||
regionMap.processPointer = 1
|
|
||||||
regionMap.scanPointer = 1
|
|
||||||
regionMap.processRoll = -1
|
|
||||||
|
|
||||||
global.version = constants.VERSION_9
|
global.version = constants.VERSION_9
|
||||||
end
|
end
|
||||||
if (global.version < constants.VERSION_10) then
|
if (global.version < constants.VERSION_10) then
|
||||||
@ -98,40 +99,64 @@ local function onConfigChanged()
|
|||||||
squad.rabid = false
|
squad.rabid = false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- queue all current chunks that wont be generated during play
|
|
||||||
local surface = game.surfaces[1]
|
|
||||||
for chunk in surface.get_chunks() do
|
|
||||||
onChunkGenerated({ surface = surface,
|
|
||||||
area = { left_top = { x = chunk.x * 32,
|
|
||||||
y = chunk.y * 32 }}})
|
|
||||||
end
|
|
||||||
global.version = constants.VERSION_10
|
global.version = constants.VERSION_10
|
||||||
end
|
end
|
||||||
|
if (global.version < constants.VERSION_11) then
|
||||||
|
for _,squad in pairs(natives.squads) do
|
||||||
|
squad.status = constants.SQUAD_GUARDING
|
||||||
|
end
|
||||||
|
|
||||||
|
natives.state = constants.AI_STATE_AGGRESSIVE
|
||||||
|
natives.temperament = 0
|
||||||
|
-- needs to be on inner logic tick loop interval
|
||||||
|
natives.stateTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC)
|
||||||
|
natives.temperamentTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC)
|
||||||
|
|
||||||
|
-- clear old regionMap processing Queue
|
||||||
|
-- prevents queue adding duplicate chunks
|
||||||
|
-- chunks are by key, so should overwrite old
|
||||||
|
regionMap.processQueue = {}
|
||||||
|
regionMap.processPointer = 1
|
||||||
|
regionMap.scanPointer = 1
|
||||||
|
-- clear pending chunks, will be added when loop runs below
|
||||||
|
pendingChunks = {}
|
||||||
|
|
||||||
|
-- queue all current chunks that wont be generated during play
|
||||||
|
local surface = game.surfaces[1]
|
||||||
|
for chunk in surface.get_chunks() do
|
||||||
|
onChunkGenerated({ surface = surface,
|
||||||
|
area = { left_top = { x = chunk.x * 32,
|
||||||
|
y = chunk.y * 32 }}})
|
||||||
|
end
|
||||||
|
|
||||||
|
global.version = constants.VERSION_11
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function onTick(event)
|
local function onTick(event)
|
||||||
if (event.tick % 20 == 0) then
|
if (event.tick % INTERVAL_PROCESS == 0) then
|
||||||
local surface = game.surfaces[1]
|
local surface = game.surfaces[1]
|
||||||
|
local evolutionFactor = game.evolution_factor
|
||||||
|
local players = game.players
|
||||||
|
|
||||||
processPendingChunks(regionMap, surface, pendingChunks)
|
processPendingChunks(regionMap, surface, pendingChunks)
|
||||||
scanMap(regionMap, surface)
|
scanMap(regionMap, surface)
|
||||||
|
|
||||||
if (event.tick % 40 == 0) then
|
if (event.tick % INTERVAL_LOGIC == 0) then
|
||||||
|
local tick = game.tick
|
||||||
|
planning(natives, evolutionFactor, tick)
|
||||||
|
|
||||||
accumulatePoints(natives)
|
regroupSquads(natives)
|
||||||
|
|
||||||
-- put down player pheromone for player hunters
|
processPlayers(players, regionMap, surface, natives, evolutionFactor, tick)
|
||||||
playerScent(regionMap, game.players)
|
|
||||||
|
|
||||||
regroupSquads(natives)
|
-- scouting(regionMap, natives)
|
||||||
|
|
||||||
-- scouting(regionMap, natives)
|
squadBeginAttack(natives, players, evolutionFactor)
|
||||||
|
squadAttack(regionMap, surface, natives)
|
||||||
|
end
|
||||||
|
|
||||||
squadBeginAttack(natives, game.players, game.evolution_factor)
|
processMap(regionMap, surface, natives, evolutionFactor)
|
||||||
squadAttack(regionMap, surface, natives)
|
|
||||||
end
|
|
||||||
|
|
||||||
processMap(regionMap, surface, natives, game.evolution_factor)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -181,16 +206,13 @@ local function onSurfaceTileChange(event)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function onInit()
|
local function onInit()
|
||||||
-- print("init")
|
|
||||||
global.regionMap = {}
|
global.regionMap = {}
|
||||||
global.pendingChunks = {}
|
global.pendingChunks = {}
|
||||||
global.natives = {}
|
global.natives = {}
|
||||||
-- global.pheromoneTotals = {}
|
|
||||||
|
|
||||||
regionMap = global.regionMap
|
regionMap = global.regionMap
|
||||||
natives = global.natives
|
natives = global.natives
|
||||||
pendingChunks = global.pendingChunks
|
pendingChunks = global.pendingChunks
|
||||||
-- pheromoneTotals = global.pheromoneTotals
|
|
||||||
|
|
||||||
onConfigChanged()
|
onConfigChanged()
|
||||||
end
|
end
|
||||||
@ -216,15 +238,15 @@ script.on_event(defines.events.on_tick, onTick)
|
|||||||
script.on_event(defines.events.on_chunk_generated, onChunkGenerated)
|
script.on_event(defines.events.on_chunk_generated, onChunkGenerated)
|
||||||
|
|
||||||
remote.add_interface("rampant", {
|
remote.add_interface("rampant", {
|
||||||
test1 = tests.test1,
|
test1 = tests.test1,
|
||||||
test2 = tests.test2,
|
test2 = tests.test2,
|
||||||
test3 = tests.test3,
|
test3 = tests.test3,
|
||||||
test4 = tests.test4,
|
test4 = tests.test4,
|
||||||
test5 = tests.test5,
|
test5 = tests.test5,
|
||||||
test6 = tests.test6,
|
test6 = tests.test6,
|
||||||
test7 = tests.test7,
|
test7 = tests.test7,
|
||||||
test8 = tests.test8,
|
test8 = tests.test8,
|
||||||
test9 = tests.test9,
|
test9 = tests.test9,
|
||||||
test10 = tests.test10,
|
test10 = tests.test10,
|
||||||
test11 = tests.test11
|
test11 = tests.test11
|
||||||
})
|
})
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name" : "Rampant",
|
"name" : "Rampant",
|
||||||
"factorio_version" : "0.14",
|
"factorio_version" : "0.14",
|
||||||
"version" : "0.14.3",
|
"version" : "0.14.4",
|
||||||
"title" : "Rampant AI",
|
"title" : "Rampant AI",
|
||||||
"author" : "Veden",
|
"author" : "Veden",
|
||||||
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",
|
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",
|
||||||
|
@ -7,29 +7,26 @@ local mapUtils = require("MapUtils")
|
|||||||
local unitGroupUtils = require("UnitGroupUtils")
|
local unitGroupUtils = require("UnitGroupUtils")
|
||||||
local playerUtils = require("PlayerUtils")
|
local playerUtils = require("PlayerUtils")
|
||||||
local neighborUtils = require("NeighborUtils")
|
local neighborUtils = require("NeighborUtils")
|
||||||
|
package.path = "../?.lua;" .. package.path
|
||||||
|
local config = require("config")
|
||||||
|
|
||||||
-- constants
|
-- constants
|
||||||
|
|
||||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
||||||
local ENEMY_BASE_PHEROMONE = constants.ENEMY_BASE_PHEROMONE
|
local BASE_PHEROMONE = constants.BASE_PHEROMONE
|
||||||
local PLAYER_BASE_PHEROMONE = constants.PLAYER_BASE_PHEROMONE
|
|
||||||
--local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE
|
|
||||||
|
|
||||||
local SQUAD_RAIDING = constants.SQUAD_RAIDING
|
local SQUAD_RAIDING = constants.SQUAD_RAIDING
|
||||||
local SQUAD_SUICIDE_RAID = constants.SQUAD_SUICIDE_RAID
|
local SQUAD_SUICIDE_RAID = constants.SQUAD_SUICIDE_RAID
|
||||||
local SQUAD_HUNTING = constants.SQUAD_HUNTING
|
|
||||||
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
||||||
local SQUAD_SUICIDE_HUNT = constants.SQUAD_SUICIDE_HUNT
|
|
||||||
|
|
||||||
--local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
|
||||||
--local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
|
|
||||||
|
|
||||||
--local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE
|
|
||||||
--local CHUNK_SIZE = constants.CHUNK_SIZE
|
|
||||||
|
|
||||||
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
||||||
local PLAYER_DEFENSE_GENERATOR = constants.PLAYER_DEFENSE_GENERATOR
|
|
||||||
|
local NO_RETREAT_BASE_PERCENT = constants.NO_RETREAT_BASE_PERCENT
|
||||||
|
local NO_RETREAT_EVOLUTION_BONUS_MAX = constants.NO_RETREAT_EVOLUTION_BONUS_MAX
|
||||||
|
local NO_RETREAT_SQUAD_SIZE_BONUS_MAX = constants.NO_RETREAT_SQUAD_SIZE_BONUS_MAX
|
||||||
|
|
||||||
|
local CONFIG_ATTACK_WAVE_MAX_SIZE = config.attackWaveMaxSize
|
||||||
|
|
||||||
-- imported functions
|
-- imported functions
|
||||||
|
|
||||||
@ -46,7 +43,7 @@ local playersWithinProximityToPosition = playerUtils.playersWithinProximityToPos
|
|||||||
|
|
||||||
local scoreNeighborsWithDirection = neighborUtils.scoreNeighborsWithDirection
|
local scoreNeighborsWithDirection = neighborUtils.scoreNeighborsWithDirection
|
||||||
|
|
||||||
|
local mLog = math.log10
|
||||||
|
|
||||||
-- module code
|
-- module code
|
||||||
|
|
||||||
@ -56,16 +53,8 @@ end
|
|||||||
|
|
||||||
local function scoreAttackLocation(position, squad, neighborChunk, surface)
|
local function scoreAttackLocation(position, squad, neighborChunk, surface)
|
||||||
local squadMovementPenalty = lookupSquadMovementPenalty(squad, neighborChunk.cX, neighborChunk.cY)
|
local squadMovementPenalty = lookupSquadMovementPenalty(squad, neighborChunk.cX, neighborChunk.cY)
|
||||||
local damageScore = surface.get_pollution(position) + neighborChunk[PLAYER_BASE_PHEROMONE] + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[PLAYER_DEFENSE_GENERATOR]
|
local r = surface.get_pollution(position) + neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE] + neighborChunk[PLAYER_PHEROMONE]
|
||||||
local avoidScore = neighborChunk[DEATH_PHEROMONE] + neighborChunk[ENEMY_BASE_PHEROMONE]
|
return r - squadMovementPenalty
|
||||||
return damageScore - avoidScore - squadMovementPenalty
|
|
||||||
end
|
|
||||||
|
|
||||||
local function scoreHuntPlayerLocation(position, squad, neighborChunk, surface)
|
|
||||||
local squadMovementPenalty = lookupSquadMovementPenalty(squad, neighborChunk.cX, neighborChunk.cY)
|
|
||||||
local damageScore = neighborChunk[PLAYER_PHEROMONE]
|
|
||||||
local avoidScore = neighborChunk[DEATH_PHEROMONE] + neighborChunk[ENEMY_BASE_PHEROMONE] + neighborChunk[PLAYER_DEFENSE_GENERATOR]
|
|
||||||
return damageScore - avoidScore - squadMovementPenalty
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function aiAttack.squadAttack(regionMap, surface, natives)
|
function aiAttack.squadAttack(regionMap, surface, natives)
|
||||||
@ -82,17 +71,7 @@ function aiAttack.squadAttack(regionMap, surface, natives)
|
|||||||
for i=1,#squads do
|
for i=1,#squads do
|
||||||
local squad = squads[i]
|
local squad = squads[i]
|
||||||
local group = squad.group
|
local group = squad.group
|
||||||
local raiding = false
|
if group.valid and ((squad.status == SQUAD_RAIDING) or (squad.status == SQUAD_SUICIDE_RAID)) then
|
||||||
local hunting = false
|
|
||||||
local scoreLocation
|
|
||||||
if (squad.status == SQUAD_RAIDING) or (squad.status == SQUAD_SUICIDE_RAID) then
|
|
||||||
raiding = true
|
|
||||||
scoreLocation = scoreAttackLocation
|
|
||||||
elseif (squad.status == SQUAD_HUNTING) or (squad.status == SQUAD_SUICIDE_HUNT) then
|
|
||||||
hunting = true
|
|
||||||
scoreLocation = scoreHuntPlayerLocation
|
|
||||||
end
|
|
||||||
if group.valid and (raiding or hunting) then
|
|
||||||
if (group.state == defines.group_state.finished) or (group.state == defines.group_state.gathering) or ((group.state == defines.group_state.moving) and (squad.cycles == 0)) then
|
if (group.state == defines.group_state.finished) or (group.state == defines.group_state.gathering) or ((group.state == defines.group_state.moving) and (squad.cycles == 0)) then
|
||||||
local chunk = getChunkByPosition(regionMap, group.position.x, group.position.y)
|
local chunk = getChunkByPosition(regionMap, group.position.x, group.position.y)
|
||||||
if (chunk ~= nil) then
|
if (chunk ~= nil) then
|
||||||
@ -100,15 +79,15 @@ function aiAttack.squadAttack(regionMap, surface, natives)
|
|||||||
local attackChunk, attackDirection = scoreNeighborsWithDirection(chunk,
|
local attackChunk, attackDirection = scoreNeighborsWithDirection(chunk,
|
||||||
getCardinalChunksWithDirection(regionMap, chunk.cX, chunk.cY),
|
getCardinalChunksWithDirection(regionMap, chunk.cX, chunk.cY),
|
||||||
validLocation,
|
validLocation,
|
||||||
scoreLocation,
|
scoreAttackLocation,
|
||||||
squad,
|
squad,
|
||||||
surface,
|
surface,
|
||||||
attackPosition)
|
attackPosition)
|
||||||
if (attackChunk ~= nil) then
|
if (attackChunk ~= nil) then
|
||||||
if ((attackChunk[PLAYER_BASE_GENERATOR] == 0) and (attackChunk[PLAYER_DEFENSE_GENERATOR] == 0)) or
|
if (attackChunk[PLAYER_BASE_GENERATOR] == 0) or
|
||||||
((group.state == defines.group_state.finished) or (group.state == defines.group_state.gathering)) then
|
((group.state == defines.group_state.finished) or (group.state == defines.group_state.gathering)) then
|
||||||
|
|
||||||
positionFromDirectionAndChunkCardinal(attackDirection, squad.group.position, attackPosition)
|
positionFromDirectionAndChunkCardinal(attackDirection, squad.group.position, attackPosition)
|
||||||
|
|
||||||
squad.cycles = 3
|
squad.cycles = 3
|
||||||
|
|
||||||
@ -122,14 +101,14 @@ function aiAttack.squadAttack(regionMap, surface, natives)
|
|||||||
attackCmd.distraction = defines.distraction.by_enemy
|
attackCmd.distraction = defines.distraction.by_enemy
|
||||||
end
|
end
|
||||||
|
|
||||||
group.set_command(attackCmd)
|
group.set_command(attackCmd)
|
||||||
group.start_moving()
|
group.start_moving()
|
||||||
elseif not squad.frenzy and not squad.rabid and
|
elseif not squad.frenzy and not squad.rabid and
|
||||||
(((group.state == defines.group_state.attacking_distraction) or (group.state == defines.group_state.attacking_distraction)) or
|
((group.state == defines.group_state.attacking_distraction) or (group.state == defines.group_state.attacking_distraction) or
|
||||||
(attackChunk[PLAYER_BASE_GENERATOR] ~= 0) or (attackChunk[PLAYER_DEFENSE_GENERATOR] ~= 0)) then
|
(attackChunk[PLAYER_BASE_GENERATOR] ~= 0)) then
|
||||||
squad.frenzy = true
|
squad.frenzy = true
|
||||||
squad.frenzyPosition.x = squad.group.position.x
|
squad.frenzyPosition.x = squad.group.position.x
|
||||||
squad.frenzyPosition.y = squad.group.position.y
|
squad.frenzyPosition.y = squad.group.position.y
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -143,7 +122,10 @@ function aiAttack.squadBeginAttack(natives, players, evolution_factor)
|
|||||||
for i=1,#squads do
|
for i=1,#squads do
|
||||||
local squad = squads[i]
|
local squad = squads[i]
|
||||||
if (squad.status == SQUAD_GUARDING) and squad.group.valid then
|
if (squad.status == SQUAD_GUARDING) and squad.group.valid then
|
||||||
local threshold = 0.05 + (evolution_factor * 0.20) + (#squad.group.members * 0.0033)
|
local threshold = NO_RETREAT_BASE_PERCENT + (evolution_factor * NO_RETREAT_EVOLUTION_BONUS_MAX)
|
||||||
|
local a = (#squad.group.members / CONFIG_ATTACK_WAVE_MAX_SIZE) ^ 1.4
|
||||||
|
local squadSizeBonus = mLog(a + 0.1) + 1
|
||||||
|
threshold = threshold + (NO_RETREAT_SQUAD_SIZE_BONUS_MAX * squadSizeBonus)
|
||||||
|
|
||||||
local playerNearby = playersWithinProximityToPosition(players, squad.group.position, 100)
|
local playerNearby = playersWithinProximityToPosition(players, squad.group.position, 100)
|
||||||
if playerNearby then
|
if playerNearby then
|
||||||
@ -152,24 +134,15 @@ function aiAttack.squadBeginAttack(natives, players, evolution_factor)
|
|||||||
squad.frenzyPosition.y = squad.group.position.y
|
squad.frenzyPosition.y = squad.group.position.y
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check to hunt player
|
-- check to raid base
|
||||||
if (math.random() < 0.30) and playerNearby then
|
if (math.random() < 0.70) then
|
||||||
if (math.random() < threshold) then
|
|
||||||
squad.status = SQUAD_SUICIDE_HUNT
|
|
||||||
else
|
|
||||||
squad.status = SQUAD_HUNTING
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check to raid base
|
|
||||||
if (squad.status == SQUAD_GUARDING) and (math.random() < 0.70) then
|
|
||||||
if (math.random() < threshold) then
|
if (math.random() < threshold) then
|
||||||
squad.status = SQUAD_SUICIDE_RAID
|
squad.status = SQUAD_SUICIDE_RAID
|
||||||
else
|
else
|
||||||
squad.status = SQUAD_RAIDING
|
squad.status = SQUAD_RAIDING
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -11,42 +11,26 @@ local config = require("config")
|
|||||||
|
|
||||||
-- constants
|
-- constants
|
||||||
|
|
||||||
-- local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
local BASE_PHEROMONE = constants.BASE_PHEROMONE
|
||||||
-- local SQUAD_BURROWING = constants.SQUAD_BURROWING
|
|
||||||
|
|
||||||
local PLAYER_BASE_PHEROMONE = constants.PLAYER_BASE_PHEROMONE
|
|
||||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||||
local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE
|
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
||||||
-- local ENEMY_BASE_PHEROMONE = constants.ENEMY_BASE_PHEROMONE
|
|
||||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
|
||||||
|
|
||||||
local AI_POINT_GENERATOR_AMOUNT = constants.AI_POINT_GENERATOR_AMOUNT
|
|
||||||
local AI_MAX_POINTS = constants.AI_MAX_POINTS
|
|
||||||
|
|
||||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||||
|
|
||||||
-- local AI_SCOUT_COST = constants.AI_SCOUT_COST
|
|
||||||
local AI_SQUAD_COST = constants.AI_SQUAD_COST
|
|
||||||
-- local AI_TUNNEL_COST = constants.AI_TUNNEL_COST
|
|
||||||
|
|
||||||
local AI_MAX_SQUAD_COUNT = constants.AI_MAX_SQUAD_COUNT
|
local AI_MAX_SQUAD_COUNT = constants.AI_MAX_SQUAD_COUNT
|
||||||
|
|
||||||
|
local AI_SQUAD_COST = constants.AI_SQUAD_COST
|
||||||
|
|
||||||
local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE
|
local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE
|
||||||
local CHUNK_SIZE = constants.CHUNK_SIZE
|
local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||||
|
|
||||||
-- local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
|
|
||||||
|
|
||||||
local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE
|
local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE
|
||||||
local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE
|
local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE
|
||||||
|
|
||||||
-- local COMMAND_GROUP = defines.command.group
|
|
||||||
-- local DISTRACTION_BY_DAMAGE = defines.distraction.by_damage
|
|
||||||
|
|
||||||
local CONFIG_USE_PLAYER_PROXIMITY = config.attackWaveGenerationUsePlayerProximity
|
local CONFIG_USE_PLAYER_PROXIMITY = config.attackWaveGenerationUsePlayerProximity
|
||||||
local CONFIG_USE_PLAYER_BASE_PROXIMITY = config.attackWaveGenerationUsePlayerBaseProximity
|
|
||||||
local CONFIG_USE_PLAYER_DEFENSE_PROXIMITY = config.attackWaveGenerationUsePlayerDefenseProximity
|
|
||||||
local CONFIG_USE_POLLUTION_PROXIMITY = config.attackWaveGenerationUsePollution
|
local CONFIG_USE_POLLUTION_PROXIMITY = config.attackWaveGenerationUsePollution
|
||||||
local CONFIG_USE_THRESHOLD = config.attackWaveGenerationThreshold
|
local CONFIG_USE_THRESHOLD_MIN = config.attackWaveGenerationThresholdMin
|
||||||
|
local CONFIG_USE_THRESHOLD_MAX = config.attackWaveGenerationThresholdMax
|
||||||
|
local CONFIG_USE_THRESHOLD_RANGE = CONFIG_USE_THRESHOLD_MAX - CONFIG_USE_THRESHOLD_MIN
|
||||||
|
|
||||||
-- imported functions
|
-- imported functions
|
||||||
|
|
||||||
@ -55,25 +39,23 @@ local scoreNeighbors = neighborUtils.scoreNeighbors
|
|||||||
local createSquad = unitGroupUtils.createSquad
|
local createSquad = unitGroupUtils.createSquad
|
||||||
local attackWaveScaling = config.attackWaveScaling
|
local attackWaveScaling = config.attackWaveScaling
|
||||||
|
|
||||||
|
local mMax = math.max
|
||||||
|
|
||||||
-- module code
|
-- module code
|
||||||
|
|
||||||
local function attackWaveValidCandidate(chunk, surface)
|
local function attackWaveValidCandidate(chunk, surface, evolutionFactor)
|
||||||
local total = 0;
|
local total = 0;
|
||||||
|
|
||||||
if CONFIG_USE_PLAYER_PROXIMITY then
|
if CONFIG_USE_PLAYER_PROXIMITY then
|
||||||
total = total + chunk[PLAYER_PHEROMONE]
|
total = total + chunk[PLAYER_PHEROMONE]
|
||||||
end
|
end
|
||||||
if CONFIG_USE_PLAYER_BASE_PROXIMITY then
|
|
||||||
total = total + chunk[PLAYER_BASE_PHEROMONE]
|
|
||||||
end
|
|
||||||
if CONFIG_USE_PLAYER_DEFENSE_PROXIMITY then
|
|
||||||
total = total + chunk[PLAYER_DEFENSE_PHEROMONE]
|
|
||||||
end
|
|
||||||
if CONFIG_USE_POLLUTION_PROXIMITY then
|
if CONFIG_USE_POLLUTION_PROXIMITY then
|
||||||
total = total + surface.get_pollution({chunk.pX, chunk.pY})
|
total = total + surface.get_pollution({chunk.pX, chunk.pY})
|
||||||
end
|
end
|
||||||
|
|
||||||
if (total >= CONFIG_USE_THRESHOLD) then
|
local delta = CONFIG_USE_THRESHOLD_RANGE * evolutionFactor
|
||||||
|
|
||||||
|
if (total > (CONFIG_USE_THRESHOLD_MAX - delta)) then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
@ -81,21 +63,13 @@ local function attackWaveValidCandidate(chunk, surface)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function scoreUnitGroupLocation(position, squad, neighborChunk, surface)
|
local function scoreUnitGroupLocation(position, squad, neighborChunk, surface)
|
||||||
local attackScore = surface.get_pollution(position) + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[PLAYER_DEFENSE_PHEROMONE]
|
return surface.get_pollution(position) + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE]
|
||||||
local avoidScore = neighborChunk[DEATH_PHEROMONE]
|
|
||||||
return attackScore - avoidScore
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function validUnitGroupLocation(x, chunk, neighborChunk)
|
local function validUnitGroupLocation(x, chunk, neighborChunk)
|
||||||
return neighborChunk[NORTH_SOUTH_PASSABLE] and neighborChunk[EAST_WEST_PASSABLE]
|
return neighborChunk[NORTH_SOUTH_PASSABLE] and neighborChunk[EAST_WEST_PASSABLE]
|
||||||
end
|
end
|
||||||
|
|
||||||
function aiBuilding.accumulatePoints(natives)
|
|
||||||
if (natives.points < AI_MAX_POINTS) then
|
|
||||||
natives.points = natives.points + math.floor(AI_POINT_GENERATOR_AMOUNT * math.random())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function aiBuilding.removeScout(entity, natives)
|
function aiBuilding.removeScout(entity, natives)
|
||||||
--[[
|
--[[
|
||||||
local scouts = natives.scouts
|
local scouts = natives.scouts
|
||||||
@ -142,12 +116,10 @@ function aiBuilding.scouting(regionMap, natives)
|
|||||||
--]]
|
--]]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function aiBuilding.formSquads(regionMap, surface, natives, chunk, evolution_factor)
|
function aiBuilding.formSquads(regionMap, surface, natives, chunk, evolution_factor)
|
||||||
if (natives.points > AI_SQUAD_COST) and (chunk[ENEMY_BASE_GENERATOR] ~= 0) and (#natives.squads < (AI_MAX_SQUAD_COUNT * evolution_factor)) then
|
if (natives.points > AI_SQUAD_COST) and (chunk[ENEMY_BASE_GENERATOR] ~= 0) and (#natives.squads < (AI_MAX_SQUAD_COUNT * evolution_factor)) then
|
||||||
local valid = attackWaveValidCandidate(chunk, surface)
|
local valid = attackWaveValidCandidate(chunk, surface, evolution_factor)
|
||||||
if valid and (math.random() < 0.03) then
|
if valid and (math.random() < mMax((0.25 * evolution_factor), 0.10)) then
|
||||||
local squadPosition = {x=0, y=0}
|
local squadPosition = {x=0, y=0}
|
||||||
local squadPath, squadScore = scoreNeighbors(chunk,
|
local squadPath, squadScore = scoreNeighbors(chunk,
|
||||||
getNeighborChunks(regionMap, chunk.cX, chunk.cY),
|
getNeighborChunks(regionMap, chunk.cX, chunk.cY),
|
||||||
|
@ -9,12 +9,11 @@ local neighborUtils = require("NeighborUtils")
|
|||||||
|
|
||||||
-- constants
|
-- constants
|
||||||
|
|
||||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
||||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||||
local ENEMY_BASE_PHEROMONE = constants.ENEMY_BASE_PHEROMONE
|
local BASE_PHEROMONE = constants.BASE_PHEROMONE
|
||||||
local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE
|
|
||||||
|
|
||||||
local RETREAT_DEATH_PHEROMONE_LEVEL = constants.RETREAT_DEATH_PHEROMONE_LEVEL
|
local RETREAT_MOVEMENT_PHEROMONE_LEVEL = constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL
|
||||||
|
|
||||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||||
|
|
||||||
@ -46,14 +45,14 @@ local function validRetreatLocation(x, chunk, neighborChunk)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function scoreRetreatLocation(position, squad, neighborChunk, surface)
|
local function scoreRetreatLocation(position, squad, neighborChunk, surface)
|
||||||
local safeScore = neighborChunk[ENEMY_BASE_PHEROMONE]
|
local safeScore = -neighborChunk[BASE_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE]
|
||||||
local dangerScore = neighborChunk[DEATH_PHEROMONE] + surface.get_pollution(position) + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[PLAYER_DEFENSE_PHEROMONE] + (neighborChunk[ENEMY_BASE_GENERATOR] * 6)
|
local dangerScore = surface.get_pollution(position) + neighborChunk[PLAYER_PHEROMONE] + (neighborChunk[ENEMY_BASE_GENERATOR] * 6)
|
||||||
return safeScore - dangerScore
|
return safeScore - dangerScore
|
||||||
end
|
end
|
||||||
|
|
||||||
function aiDefense.retreatUnits(position, squad, regionMap, surface, natives)
|
function aiDefense.retreatUnits(position, squad, regionMap, surface, natives)
|
||||||
local chunk = getChunkByPosition(regionMap, position.x, position.y)
|
local chunk = getChunkByPosition(regionMap, position.x, position.y)
|
||||||
if (chunk ~= nil) and (chunk[DEATH_PHEROMONE] > (game.evolution_factor * RETREAT_DEATH_PHEROMONE_LEVEL)) then
|
if (chunk ~= nil) and (chunk[MOVEMENT_PHEROMONE] > -(game.evolution_factor * RETREAT_MOVEMENT_PHEROMONE_LEVEL)) then
|
||||||
local performRetreat = false
|
local performRetreat = false
|
||||||
local enemiesToSquad
|
local enemiesToSquad
|
||||||
|
|
||||||
|
51
libs/AIPlanning.lua
Normal file
51
libs/AIPlanning.lua
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
local aiPlanning = {}
|
||||||
|
|
||||||
|
-- imports
|
||||||
|
|
||||||
|
local constants = require("Constants")
|
||||||
|
local mathUtils = require("MathUtils")
|
||||||
|
|
||||||
|
-- constants
|
||||||
|
|
||||||
|
local AI_STATE_PEACEFUL = constants.AI_STATE_PEACEFUL
|
||||||
|
local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE
|
||||||
|
|
||||||
|
local AI_MAX_POINTS = constants.AI_MAX_POINTS
|
||||||
|
local AI_POINT_GENERATOR_AMOUNT = constants.AI_POINT_GENERATOR_AMOUNT
|
||||||
|
|
||||||
|
local AI_MIN_STATE_DURATION = constants.AI_MIN_STATE_DURATION
|
||||||
|
local AI_MIN_TEMPERAMENT_DURATION = constants.AI_MIN_TEMPERAMENT_DURATION
|
||||||
|
local AI_MAX_STATE_DURATION = constants.AI_MAX_STATE_DURATION
|
||||||
|
local AI_MAX_TEMPERAMENT_DURATION = constants.AI_MAX_TEMPERAMENT_DURATION
|
||||||
|
|
||||||
|
-- imported functions
|
||||||
|
|
||||||
|
local randomTickEvent = mathUtils.randomTickEvent
|
||||||
|
|
||||||
|
local mMax = math.max
|
||||||
|
|
||||||
|
-- module code
|
||||||
|
|
||||||
|
function aiPlanning.planning(natives, evolution_factor, tick)
|
||||||
|
local maxPoints = AI_MAX_POINTS * evolution_factor
|
||||||
|
if (natives.points < maxPoints) then
|
||||||
|
natives.points = natives.points + math.floor(AI_POINT_GENERATOR_AMOUNT * math.random())
|
||||||
|
end
|
||||||
|
|
||||||
|
if (natives.temperamentTick == tick) then
|
||||||
|
natives.temperament = math.random()
|
||||||
|
natives.temperamentTick = randomTickEvent(tick, AI_MIN_TEMPERAMENT_DURATION, AI_MAX_TEMPERAMENT_DURATION)
|
||||||
|
end
|
||||||
|
|
||||||
|
if (natives.stateTick == tick) then
|
||||||
|
local roll = math.random() * mMax(1 - evolution_factor, 0.15)
|
||||||
|
if (roll > natives.temperament) then
|
||||||
|
natives.state = AI_STATE_PEACEFUL
|
||||||
|
else
|
||||||
|
natives.state = AI_STATE_AGGRESSIVE
|
||||||
|
end
|
||||||
|
natives.stateTick = randomTickEvent(tick, AI_MIN_STATE_DURATION, AI_MAX_STATE_DURATION)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return aiPlanning
|
@ -13,6 +13,7 @@ local scoreChunk = chunkUtils.scoreChunk
|
|||||||
-- module code
|
-- module code
|
||||||
|
|
||||||
function chunkProcessor.processPendingChunks(regionMap, surface, pendingStack)
|
function chunkProcessor.processPendingChunks(regionMap, surface, pendingStack)
|
||||||
|
local processQueue = regionMap.processQueue
|
||||||
|
|
||||||
for _=#pendingStack, 1, -1 do
|
for _=#pendingStack, 1, -1 do
|
||||||
local event = pendingStack[#pendingStack]
|
local event = pendingStack[#pendingStack]
|
||||||
@ -29,8 +30,6 @@ function chunkProcessor.processPendingChunks(regionMap, surface, pendingStack)
|
|||||||
|
|
||||||
checkChunkPassability(chunk, surface)
|
checkChunkPassability(chunk, surface)
|
||||||
scoreChunk(chunk, surface)
|
scoreChunk(chunk, surface)
|
||||||
|
|
||||||
local processQueue = regionMap.processQueue
|
|
||||||
processQueue[#processQueue+1] = chunk
|
processQueue[#processQueue+1] = chunk
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -2,22 +2,15 @@ local chunkUtils = {}
|
|||||||
|
|
||||||
-- imports
|
-- imports
|
||||||
|
|
||||||
-- local mapUtils = require("MapUtils")
|
|
||||||
local constants = require("Constants")
|
local constants = require("Constants")
|
||||||
|
|
||||||
-- constants
|
-- constants
|
||||||
|
|
||||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
local BASE_PHEROMONE = constants.BASE_PHEROMONE
|
||||||
local ENEMY_BASE_PHEROMONE = constants.ENEMY_BASE_PHEROMONE
|
|
||||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||||
local PLAYER_BASE_PHEROMONE = constants.PLAYER_BASE_PHEROMONE
|
|
||||||
local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE
|
|
||||||
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
||||||
|
|
||||||
local DEFENSE_PHEROMONES = constants.DEFENSE_PHEROMONES
|
|
||||||
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
|
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
|
||||||
|
|
||||||
local PLAYER_DEFENSE_GENERATOR = constants.PLAYER_DEFENSE_GENERATOR
|
|
||||||
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
||||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||||
|
|
||||||
@ -29,6 +22,8 @@ local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE
|
|||||||
|
|
||||||
local ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
local ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
||||||
|
|
||||||
|
local CHUNK_TICK = constants.CHUNK_TICK
|
||||||
|
|
||||||
-- module code
|
-- module code
|
||||||
|
|
||||||
function chunkUtils.checkForDeadendTiles(constantCoordinate, iteratingCoordinate, direction, surface)
|
function chunkUtils.checkForDeadendTiles(constantCoordinate, iteratingCoordinate, direction, surface)
|
||||||
@ -85,7 +80,6 @@ function chunkUtils.scoreChunk(chunk, surface)
|
|||||||
|
|
||||||
local entities = surface.count_entities_filtered(enemyChunkQuery)
|
local entities = surface.count_entities_filtered(enemyChunkQuery)
|
||||||
local playerObjects = 0
|
local playerObjects = 0
|
||||||
local playerDefenses = 0
|
|
||||||
|
|
||||||
chunk[ENEMY_BASE_GENERATOR] = entities * ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
chunk[ENEMY_BASE_GENERATOR] = entities * ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
||||||
|
|
||||||
@ -94,44 +88,41 @@ function chunkUtils.scoreChunk(chunk, surface)
|
|||||||
for i=1, #entities do
|
for i=1, #entities do
|
||||||
local entityType = entities[i].type
|
local entityType = entities[i].type
|
||||||
|
|
||||||
local entityScore = DEFENSE_PHEROMONES[entityType]
|
local entityScore = BUILDING_PHEROMONES[entityType]
|
||||||
if (entityScore ~= nil) then
|
|
||||||
playerDefenses = playerDefenses + entityScore
|
|
||||||
end
|
|
||||||
entityScore = BUILDING_PHEROMONES[entityType]
|
|
||||||
if (entityScore ~= nil) then
|
if (entityScore ~= nil) then
|
||||||
playerObjects = playerObjects + entityScore
|
playerObjects = playerObjects + entityScore
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
chunk[PLAYER_BASE_GENERATOR] = playerObjects
|
chunk[PLAYER_BASE_GENERATOR] = playerObjects
|
||||||
chunk[PLAYER_DEFENSE_GENERATOR] = playerDefenses
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function chunkUtils.createChunk(topX, topY)
|
function chunkUtils.createChunk(topX, topY)
|
||||||
local chunk = {
|
local chunk = {
|
||||||
pX = topX,
|
pX = topX,
|
||||||
pY = topY,
|
pY = topY,
|
||||||
cX = topX * 0.03125,
|
cX = topX * 0.03125,
|
||||||
cY = topY * 0.03125
|
cY = topY * 0.03125
|
||||||
}
|
}
|
||||||
chunk[DEATH_PHEROMONE] = 0
|
|
||||||
chunk[ENEMY_BASE_PHEROMONE] = 0
|
|
||||||
chunk[PLAYER_PHEROMONE] = 0
|
|
||||||
chunk[PLAYER_BASE_PHEROMONE] = 0
|
|
||||||
chunk[PLAYER_DEFENSE_PHEROMONE] = 0
|
|
||||||
chunk[MOVEMENT_PHEROMONE] = 0
|
chunk[MOVEMENT_PHEROMONE] = 0
|
||||||
|
chunk[BASE_PHEROMONE] = 0
|
||||||
|
chunk[PLAYER_PHEROMONE] = 0
|
||||||
|
chunk[ENEMY_BASE_GENERATOR] = 0
|
||||||
|
chunk[PLAYER_BASE_GENERATOR] = 0
|
||||||
|
chunk[NORTH_SOUTH_PASSABLE] = false
|
||||||
|
chunk[EAST_WEST_PASSABLE] = false
|
||||||
|
chunk[CHUNK_TICK] = 0
|
||||||
return chunk
|
return chunk
|
||||||
end
|
end
|
||||||
|
|
||||||
-- function chunkUtils.colorChunk(x, y, tileType, surface)
|
-- function chunkUtils.colorChunk(x, y, tileType, surface)
|
||||||
-- local tiles = {}
|
-- local tiles = {}
|
||||||
-- for xi=x+5, x + 27 do
|
-- for xi=x+5, x + 27 do
|
||||||
-- for yi=y+5, y + 27 do
|
-- for yi=y+5, y + 27 do
|
||||||
-- tiles[#tiles+1] = {name=tileType, position={xi, yi}}
|
-- tiles[#tiles+1] = {name=tileType, position={xi, yi}}
|
||||||
-- end
|
-- end
|
||||||
-- end
|
-- end
|
||||||
-- surface.set_tiles(tiles, false)
|
-- surface.set_tiles(tiles, false)
|
||||||
-- end
|
-- end
|
||||||
|
|
||||||
return chunkUtils
|
return chunkUtils
|
||||||
|
@ -5,44 +5,49 @@ local constants = {}
|
|||||||
constants.VERSION_5 = 5
|
constants.VERSION_5 = 5
|
||||||
constants.VERSION_9 = 9
|
constants.VERSION_9 = 9
|
||||||
constants.VERSION_10 = 10
|
constants.VERSION_10 = 10
|
||||||
|
constants.VERSION_11 = 11
|
||||||
|
|
||||||
-- misc
|
-- misc
|
||||||
|
|
||||||
constants.MAGIC_MAXIMUM_NUMBER = 1e99 -- used in loops trying to find the lowest/highest score
|
constants.MAGIC_MAXIMUM_NUMBER = 1e99 -- used in loops trying to find the lowest/highest score
|
||||||
constants.RETREAT_DEATH_PHEROMONE_LEVEL = 10000
|
constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL = 10000
|
||||||
|
|
||||||
constants.PROCESS_QUEUE_SIZE = 350
|
constants.PROCESS_QUEUE_SIZE = 500
|
||||||
constants.SCAN_QUEUE_SIZE = 10
|
constants.SCAN_QUEUE_SIZE = 10
|
||||||
|
constants.PROCESS_PLAYER_BOUND = 3
|
||||||
|
|
||||||
-- temps
|
constants.TICKS_A_SECOND = 60
|
||||||
|
constants.TICKS_A_MINUTE = constants.TICKS_A_SECOND * 60
|
||||||
|
|
||||||
-- constants.ATTACK_POSITION = 1
|
constants.INTERVAL_PROCESS = 20
|
||||||
-- constants.ATTACK_COMMAND = 2
|
constants.INTERVAL_LOGIC = 40
|
||||||
-- constants.ATTACK_DIRECTION = 3
|
|
||||||
|
|
||||||
-- constants.GROUP_COMMAND = 4
|
|
||||||
|
|
||||||
-- constants.SQUAD_POSITION = 5
|
|
||||||
|
|
||||||
-- constants.RETREAT_POSITION = 6
|
|
||||||
-- constants.RETREAT_NEIGHBORS_WITH_DIRECTION = 7
|
|
||||||
-- -- constants.RETREAT_COMMAND = 8
|
|
||||||
|
|
||||||
-- constants.MULTI_GROUP_COMMAND = 8
|
|
||||||
|
|
||||||
-- ai
|
-- ai
|
||||||
|
|
||||||
constants.AI_POINT_GENERATOR_AMOUNT = 6
|
constants.AI_POINT_GENERATOR_AMOUNT = 6
|
||||||
constants.AI_SCOUT_COST = 45
|
constants.AI_SCOUT_COST = 45
|
||||||
constants.AI_SQUAD_COST = 150
|
constants.AI_SQUAD_COST = 175
|
||||||
constants.AI_SETTLER_COST = 75
|
constants.AI_SETTLER_COST = 75
|
||||||
constants.AI_BASE_BUILDING_COST = 500
|
constants.AI_BASE_BUILDING_COST = 500
|
||||||
constants.AI_TUNNEL_COST = 100
|
constants.AI_TUNNEL_COST = 100
|
||||||
constants.AI_MAX_POINTS = 30000
|
constants.AI_MAX_POINTS = 10000
|
||||||
|
|
||||||
--constants.AI_MAX_SQUAD_SIZE = 150
|
|
||||||
constants.AI_MAX_SQUAD_COUNT = 30
|
constants.AI_MAX_SQUAD_COUNT = 30
|
||||||
|
|
||||||
|
constants.AI_STATE_PEACEFUL = 1
|
||||||
|
constants.AI_STATE_AGGRESSIVE = 2
|
||||||
|
|
||||||
|
constants.AI_MIN_STATE_DURATION = 1
|
||||||
|
constants.AI_MAX_STATE_DURATION = 4
|
||||||
|
constants.AI_MIN_TEMPERAMENT_DURATION = 5
|
||||||
|
constants.AI_MAX_TEMPERAMENT_DURATION = 15
|
||||||
|
|
||||||
|
-- ai retreat
|
||||||
|
|
||||||
|
constants.NO_RETREAT_BASE_PERCENT = 0.10
|
||||||
|
constants.NO_RETREAT_EVOLUTION_BONUS_MAX = 0.25
|
||||||
|
constants.NO_RETREAT_SQUAD_SIZE_BONUS_MAX = 0.40
|
||||||
|
|
||||||
-- chunk properties
|
-- chunk properties
|
||||||
|
|
||||||
constants.CHUNK_SIZE = 32
|
constants.CHUNK_SIZE = 32
|
||||||
@ -53,46 +58,41 @@ constants.EAST_WEST = 2
|
|||||||
|
|
||||||
-- pheromone amounts
|
-- pheromone amounts
|
||||||
|
|
||||||
constants.MOVEMENT_PENALTY_PHEROMONE_GENERATOR_AMOUNT = 500
|
|
||||||
constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = 500
|
constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = 500
|
||||||
constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = 175
|
constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = 15
|
||||||
constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 100
|
constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 100
|
||||||
constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT = 300
|
constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT = 100
|
||||||
|
|
||||||
-- pheromone diffusion amounts
|
-- pheromone diffusion amounts
|
||||||
|
|
||||||
constants.STANDARD_PHERONOME_DIFFUSION_AMOUNT = 0.10
|
constants.STANDARD_PHERONOME_DIFFUSION_AMOUNT = 0.05
|
||||||
constants.DEATH_PHEROMONE_DIFFUSION_AMOUNT = 0.02
|
constants.MOVEMENT_PHEROMONE_DIFFUSION_AMOUNT = 0.02
|
||||||
|
|
||||||
constants.DEATH_PHEROMONE_PERSISTANCE = 0.99
|
constants.MOVEMENT_PHEROMONE_PERSISTANCE = 0.98
|
||||||
constants.STANDARD_PHEROMONE_PERSISTANCE = 0.98
|
constants.STANDARD_PHEROMONE_PERSISTANCE = 0.98
|
||||||
|
|
||||||
-- chunk attributes
|
-- chunk attributes
|
||||||
|
|
||||||
constants.DEATH_PHEROMONE = 1
|
constants.MOVEMENT_PHEROMONE = 1
|
||||||
constants.ENEMY_BASE_PHEROMONE = 2
|
constants.BASE_PHEROMONE = 2
|
||||||
constants.PLAYER_PHEROMONE = 3
|
constants.PLAYER_PHEROMONE = 3
|
||||||
constants.PLAYER_BASE_PHEROMONE = 4
|
|
||||||
constants.PLAYER_DEFENSE_PHEROMONE = 5
|
|
||||||
constants.MOVEMENT_PHEROMONE = 6
|
|
||||||
|
|
||||||
constants.ENEMY_BASE_GENERATOR = 7
|
constants.ENEMY_BASE_GENERATOR = 4
|
||||||
constants.PLAYER_BASE_GENERATOR = 8
|
constants.PLAYER_BASE_GENERATOR = 5
|
||||||
constants.PLAYER_DEFENSE_GENERATOR = 9
|
|
||||||
|
|
||||||
constants.NORTH_SOUTH_PASSABLE = 10
|
constants.NORTH_SOUTH_PASSABLE = 6
|
||||||
constants.EAST_WEST_PASSABLE = 11
|
constants.EAST_WEST_PASSABLE = 7
|
||||||
|
|
||||||
|
constants.CHUNK_TICK = 8
|
||||||
|
|
||||||
-- Squad status
|
-- Squad status
|
||||||
|
|
||||||
constants.SQUAD_RETREATING = 1 -- used during squad retreat
|
constants.SQUAD_RETREATING = 1 -- used during squad retreat
|
||||||
constants.SQUAD_GUARDING = 2 -- used when squad is idle
|
constants.SQUAD_GUARDING = 2 -- used when squad is idle
|
||||||
constants.SQUAD_ATTACKING = 3 -- used as an attack state to be transitioned into hunt, raid, siege, burrow
|
constants.SQUAD_ATTACKING = 3 -- used as an attack state to be transitioned into hunt, raid, siege, burrow
|
||||||
constants.SQUAD_HUNTING = 4 -- used when player is close to unit group
|
constants.SQUAD_BURROWING = 4
|
||||||
constants.SQUAD_SUICIDE_HUNT = 5 -- used when player is close with no retreat
|
constants.SQUAD_RAIDING = 5 -- used when player stuff is close
|
||||||
constants.SQUAD_BURROWING = 6
|
constants.SQUAD_SUICIDE_RAID = 6 -- when player stuff is close with no retreat
|
||||||
constants.SQUAD_RAIDING = 8 -- used when player stuff is close
|
|
||||||
constants.SQUAD_SUICIDE_RAID = 9 -- when player stuff is close with no retreat
|
|
||||||
-- constants.SQUAD_SCOUTING = 7
|
-- constants.SQUAD_SCOUTING = 7
|
||||||
-- constants.SQUAD_SIEGE = 3
|
-- constants.SQUAD_SIEGE = 3
|
||||||
|
|
||||||
@ -101,36 +101,30 @@ constants.SQUAD_SUICIDE_RAID = 9 -- when player stuff is close with no retreat
|
|||||||
constants.BUILDING_PHEROMONES = {}
|
constants.BUILDING_PHEROMONES = {}
|
||||||
-- constants.buildingPheromones["container"] = 1
|
-- constants.buildingPheromones["container"] = 1
|
||||||
-- constants.buildingPheromones["storage-tank"] = 1
|
-- constants.buildingPheromones["storage-tank"] = 1
|
||||||
constants.BUILDING_PHEROMONES["generator"] = 60
|
constants.BUILDING_PHEROMONES["generator"] = 8
|
||||||
constants.BUILDING_PHEROMONES["pump"] = 8
|
constants.BUILDING_PHEROMONES["pump"] = 2
|
||||||
constants.BUILDING_PHEROMONES["offshore-pump"] = 8
|
constants.BUILDING_PHEROMONES["offshore-pump"] = 2
|
||||||
-- constants.buildingPheromones["constant-combinator"] = 1
|
-- constants.buildingPheromones["constant-combinator"] = 1
|
||||||
-- constants.buildingPheromones["train-stop"] = 2
|
-- constants.buildingPheromones["train-stop"] = 2
|
||||||
-- constants.buildingPheromones["rail-signal"] = 1
|
-- constants.buildingPheromones["rail-signal"] = 1
|
||||||
-- constants.BUILDING_PHEROMONES["electric-pole"] = 4
|
-- constants.BUILDING_PHEROMONES["electric-pole"] = 4
|
||||||
constants.BUILDING_PHEROMONES["transport-belt"] = 4
|
constants.BUILDING_PHEROMONES["transport-belt"] = 1
|
||||||
constants.BUILDING_PHEROMONES["accumulator"] = 40
|
constants.BUILDING_PHEROMONES["accumulator"] = 10
|
||||||
constants.BUILDING_PHEROMONES["solar-panel"] = 32
|
constants.BUILDING_PHEROMONES["solar-panel"] = 8
|
||||||
constants.BUILDING_PHEROMONES["boiler"] = 60
|
constants.BUILDING_PHEROMONES["boiler"] = 12
|
||||||
constants.BUILDING_PHEROMONES["assembling-machine"] = 48
|
constants.BUILDING_PHEROMONES["assembling-machine"] = 12
|
||||||
constants.BUILDING_PHEROMONES["roboport"] = 40
|
constants.BUILDING_PHEROMONES["roboport"] = 10
|
||||||
constants.BUILDING_PHEROMONES["beacon"] = 40
|
constants.BUILDING_PHEROMONES["beacon"] = 10
|
||||||
constants.BUILDING_PHEROMONES["furnace"] = 60
|
constants.BUILDING_PHEROMONES["furnace"] = 12
|
||||||
constants.BUILDING_PHEROMONES["mining-drill"] = 80
|
constants.BUILDING_PHEROMONES["mining-drill"] = 15
|
||||||
|
|
||||||
-- player defense pheromones
|
-- player defense pheromones
|
||||||
|
|
||||||
constants.DEFENSE_PHEROMONES = {}
|
constants.BUILDING_PHEROMONES["ammo-turret"] = 2.5
|
||||||
constants.DEFENSE_PHEROMONES["ammo-turret"] = 5
|
constants.BUILDING_PHEROMONES["wall"] = 0.25
|
||||||
constants.DEFENSE_PHEROMONES["wall"] = 0.5
|
constants.BUILDING_PHEROMONES["electric-turret"] = 4.25
|
||||||
constants.DEFENSE_PHEROMONES["electric-turret"] = 7.5
|
constants.BUILDING_PHEROMONES["fluid-turret"] = 5
|
||||||
constants.DEFENSE_PHEROMONES["fluid-turret"] = 10
|
constants.BUILDING_PHEROMONES["turret"] = 3.5
|
||||||
constants.DEFENSE_PHEROMONES["turret"] = 3
|
|
||||||
|
|
||||||
-- enemy units
|
|
||||||
|
|
||||||
-- constants.deathPheromones = {}
|
|
||||||
-- constants.deathPheromones[""]
|
|
||||||
|
|
||||||
constants.retreatFilter = {}
|
constants.retreatFilter = {}
|
||||||
constants.retreatFilter[constants.SQUAD_RETREATING] = true
|
constants.retreatFilter[constants.SQUAD_RETREATING] = true
|
||||||
|
@ -8,10 +8,8 @@ local constants = require("Constants")
|
|||||||
-- constants
|
-- constants
|
||||||
|
|
||||||
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
|
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
|
||||||
local DEFENSE_PHEROMONES = constants.DEFENSE_PHEROMONES
|
|
||||||
|
|
||||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||||
local PLAYER_DEFENSE_GENERATOR = constants.PLAYER_DEFENSE_GENERATOR
|
|
||||||
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
||||||
|
|
||||||
local ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
local ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
||||||
@ -87,9 +85,6 @@ function entityUtils.addRemoveEntity(regionMap, entity, natives, addObject)
|
|||||||
if (BUILDING_PHEROMONES[entity.type] ~= nil) then
|
if (BUILDING_PHEROMONES[entity.type] ~= nil) then
|
||||||
entityValue = BUILDING_PHEROMONES[entity.type]
|
entityValue = BUILDING_PHEROMONES[entity.type]
|
||||||
pheromoneType = PLAYER_BASE_GENERATOR
|
pheromoneType = PLAYER_BASE_GENERATOR
|
||||||
elseif (DEFENSE_PHEROMONES[entity.type] ~= nil) then
|
|
||||||
entityValue = DEFENSE_PHEROMONES[entity.type]
|
|
||||||
pheromoneType = PLAYER_DEFENSE_GENERATOR
|
|
||||||
elseif (entity.type == "unit-spawner") and (entity.force.name == "enemy") then
|
elseif (entity.type == "unit-spawner") and (entity.force.name == "enemy") then
|
||||||
entityValue = ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
entityValue = ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
||||||
pheromoneType = ENEMY_BASE_GENERATOR
|
pheromoneType = ENEMY_BASE_GENERATOR
|
||||||
|
@ -2,10 +2,10 @@ local mapProcessor = {}
|
|||||||
|
|
||||||
-- imports
|
-- imports
|
||||||
|
|
||||||
local mapUtils = require("MapUtils")
|
|
||||||
local pheromoneUtils = require("PheromoneUtils")
|
local pheromoneUtils = require("PheromoneUtils")
|
||||||
local aiBuilding = require("AIBuilding")
|
local aiBuilding = require("AIBuilding")
|
||||||
local constants = require("Constants")
|
local constants = require("Constants")
|
||||||
|
local mapUtils = require("MapUtils")
|
||||||
|
|
||||||
-- constants
|
-- constants
|
||||||
|
|
||||||
@ -15,6 +15,11 @@ local SCAN_QUEUE_SIZE = constants.SCAN_QUEUE_SIZE
|
|||||||
|
|
||||||
local CHUNK_SIZE = constants.CHUNK_SIZE
|
local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||||
|
local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE
|
||||||
|
|
||||||
|
local PROCESS_PLAYER_BOUND = constants.PROCESS_PLAYER_BOUND
|
||||||
|
local CHUNK_TICK = constants.CHUNK_TICK
|
||||||
|
|
||||||
|
|
||||||
-- imported functions
|
-- imported functions
|
||||||
|
|
||||||
@ -24,17 +29,38 @@ local processPheromone = pheromoneUtils.processPheromone
|
|||||||
local makeScouts = aiBuilding.makeScouts
|
local makeScouts = aiBuilding.makeScouts
|
||||||
local formSquads = aiBuilding.formSquads
|
local formSquads = aiBuilding.formSquads
|
||||||
|
|
||||||
local getCardinalChunks = mapUtils.getCardinalChunks
|
local getChunkByIndex = mapUtils.getChunkByIndex
|
||||||
|
local getChunkByPosition = mapUtils.getChunkByPosition
|
||||||
|
|
||||||
|
local playerScent = pheromoneUtils.playerScent
|
||||||
|
|
||||||
local mMin = math.min
|
local mMin = math.min
|
||||||
|
|
||||||
-- module code
|
-- module code
|
||||||
|
|
||||||
-- processing is not consistant as it depends on the number of chunks that have been generated
|
|
||||||
-- so 200 chunks is processed 3 times a second and 1200 chunks is processed once a second
|
local function nonRepeatingRandom(players)
|
||||||
-- In theory, this might be fine as smaller bases have less surface to attack and need to have
|
local ordering = {}
|
||||||
-- pheromone dissipate at a faster rate.
|
for _,player in pairs(players) do
|
||||||
function mapProcessor.processMap(regionMap, surface, natives, evolution_factor, temps)
|
ordering[#ordering+1] = player.index
|
||||||
|
end
|
||||||
|
for i=#ordering,1,-1 do
|
||||||
|
local s = math.random(i)
|
||||||
|
local t = ordering[i]
|
||||||
|
ordering[i] = ordering[s]
|
||||||
|
ordering[s] = t
|
||||||
|
end
|
||||||
|
return ordering
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
processing is not consistant as it depends on the number of chunks that have been generated
|
||||||
|
so if we process 400 chunks an iteration and 200 chunks have been generated than these are
|
||||||
|
processed 3 times a second and 1200 generated chunks would be processed once a second
|
||||||
|
In theory, this might be fine as smaller bases have less surface to attack and need to have
|
||||||
|
pheromone dissipate at a faster rate.
|
||||||
|
--]]
|
||||||
|
function mapProcessor.processMap(regionMap, surface, natives, evolution_factor)
|
||||||
local roll = regionMap.processRoll
|
local roll = regionMap.processRoll
|
||||||
local index = regionMap.processPointer
|
local index = regionMap.processPointer
|
||||||
local scouts = false
|
local scouts = false
|
||||||
@ -49,8 +75,8 @@ function mapProcessor.processMap(regionMap, surface, natives, evolution_factor,
|
|||||||
scouts = true
|
scouts = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if (0.11 <= roll) and (roll <= 0.35) then
|
if (natives.state == AI_STATE_AGGRESSIVE) and (0.11 <= roll) and (roll <= 0.35) then
|
||||||
squads = true
|
squads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
local processQueue = regionMap.processQueue
|
local processQueue = regionMap.processQueue
|
||||||
@ -64,10 +90,10 @@ function mapProcessor.processMap(regionMap, surface, natives, evolution_factor,
|
|||||||
makeScouts(surface, natives, chunk, evolution_factor)
|
makeScouts(surface, natives, chunk, evolution_factor)
|
||||||
end
|
end
|
||||||
if squads then
|
if squads then
|
||||||
formSquads(regionMap, surface, natives, chunk, evolution_factor, temps)
|
formSquads(regionMap, surface, natives, chunk, evolution_factor)
|
||||||
end
|
end
|
||||||
|
|
||||||
processPheromone(chunk, getCardinalChunks(regionMap, chunk.cX, chunk.cY))
|
processPheromone(regionMap, chunk)
|
||||||
end
|
end
|
||||||
|
|
||||||
if (endIndex == #processQueue) then
|
if (endIndex == #processQueue) then
|
||||||
@ -77,25 +103,90 @@ function mapProcessor.processMap(regionMap, surface, natives, evolution_factor,
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Localized player radius were processing takes place in realtime, doesn't store state
|
||||||
|
between calls.
|
||||||
|
vs
|
||||||
|
the slower passive version processing the entire map in multiple passes.
|
||||||
|
--]]
|
||||||
|
function mapProcessor.processPlayers(players, regionMap, surface, natives, evolution_factor, tick)
|
||||||
|
-- put down player pheromone for player hunters
|
||||||
|
-- randomize player order to ensure a single player isn't singled out
|
||||||
|
local playerOrdering = nonRepeatingRandom(players)
|
||||||
|
|
||||||
|
local scouts = false
|
||||||
|
local squads = false
|
||||||
|
local roll = math.random()
|
||||||
|
|
||||||
|
if (0.05 <= roll) and (roll <= 0.7) then
|
||||||
|
scouts = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if (natives.state == AI_STATE_AGGRESSIVE) and (0.11 <= roll) and (roll <= 0.20) then
|
||||||
|
squads = true
|
||||||
|
end
|
||||||
|
|
||||||
|
for i=1,#playerOrdering do
|
||||||
|
local player = players[playerOrdering[i]]
|
||||||
|
if (player ~= nil) and player.connected and (player.character ~= nil) and player.character.valid and (player.character.surface.index == 1) then
|
||||||
|
local playerPosition = player.character.position
|
||||||
|
local playerChunk = getChunkByPosition(regionMap, playerPosition.x, playerPosition.y)
|
||||||
|
|
||||||
|
if (playerChunk ~= nil) then
|
||||||
|
playerScent(playerChunk)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i=1,#playerOrdering do
|
||||||
|
local player = players[playerOrdering[i]]
|
||||||
|
if (player ~= nil) and player.connected and (player.character ~= nil) and player.character.valid and (player.character.surface.index == 1) then
|
||||||
|
local playerPosition = player.character.position
|
||||||
|
local playerChunk = getChunkByPosition(regionMap, playerPosition.x, playerPosition.y)
|
||||||
|
|
||||||
|
if (playerChunk ~= nil) then
|
||||||
|
for x=playerChunk.cX - PROCESS_PLAYER_BOUND, playerChunk.cX + PROCESS_PLAYER_BOUND do
|
||||||
|
for y=playerChunk.cY - PROCESS_PLAYER_BOUND, playerChunk.cY + PROCESS_PLAYER_BOUND do
|
||||||
|
local chunk = getChunkByIndex(regionMap, x, y)
|
||||||
|
|
||||||
|
if (chunk ~= nil) and (chunk[CHUNK_TICK] ~= tick) then
|
||||||
|
chunk[CHUNK_TICK] = tick
|
||||||
|
scents(chunk)
|
||||||
|
|
||||||
|
if scouts then
|
||||||
|
makeScouts(surface, natives, chunk, evolution_factor)
|
||||||
|
end
|
||||||
|
if squads then
|
||||||
|
formSquads(regionMap, surface, natives, chunk, evolution_factor)
|
||||||
|
end
|
||||||
|
|
||||||
|
processPheromone(regionMap, chunk)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function mapProcessor.scanMap(regionMap, surface)
|
function mapProcessor.scanMap(regionMap, surface)
|
||||||
local index = regionMap.scanPointer
|
local index = regionMap.scanPointer
|
||||||
|
|
||||||
local processQueue = regionMap.processQueue
|
local processQueue = regionMap.processQueue
|
||||||
local endIndex = mMin(index + SCAN_QUEUE_SIZE, #processQueue)
|
local endIndex = mMin(index + SCAN_QUEUE_SIZE, #processQueue)
|
||||||
for x=index,endIndex do
|
for x=index,endIndex do
|
||||||
local chunk = processQueue[x]
|
local chunk = processQueue[x]
|
||||||
|
|
||||||
local spawners = surface.count_entities_filtered({area = {{chunk.pX, chunk.pY},
|
local spawners = surface.count_entities_filtered({area = {{chunk.pX, chunk.pY},
|
||||||
{chunk.pX + CHUNK_SIZE, chunk.pY + CHUNK_SIZE}},
|
{chunk.pX + CHUNK_SIZE, chunk.pY + CHUNK_SIZE}},
|
||||||
type = "unit-spawner",
|
type = "unit-spawner",
|
||||||
force = "enemy"})
|
force = "enemy"})
|
||||||
chunk[ENEMY_BASE_GENERATOR] = spawners * ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
chunk[ENEMY_BASE_GENERATOR] = spawners * ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
||||||
end
|
end
|
||||||
|
|
||||||
if (endIndex == #processQueue) then
|
if (endIndex == #processQueue) then
|
||||||
regionMap.scanPointer = 1
|
regionMap.scanPointer = 1
|
||||||
else
|
else
|
||||||
regionMap.scanPointer = endIndex + 1
|
regionMap.scanPointer = endIndex + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
28
libs/MathUtils.lua
Normal file
28
libs/MathUtils.lua
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
local mathUtils = {}
|
||||||
|
|
||||||
|
-- imports
|
||||||
|
|
||||||
|
local constants = require("Constants")
|
||||||
|
|
||||||
|
-- constants
|
||||||
|
|
||||||
|
local TICKS_A_MINUTE = constants.TICKS_A_MINUTE
|
||||||
|
|
||||||
|
local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
|
||||||
|
|
||||||
|
-- imported functions
|
||||||
|
|
||||||
|
local mMax = math.max
|
||||||
|
|
||||||
|
function mathUtils.roundToNearest(number, multiple)
|
||||||
|
local num = number + (multiple * 0.5)
|
||||||
|
return num - (num % multiple)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mathUtils.randomTickEvent(tick, low, high)
|
||||||
|
local minutesToTick = mMax(high * math.random(), low)
|
||||||
|
local nextTick = mathUtils.roundToNearest(TICKS_A_MINUTE * minutesToTick, INTERVAL_LOGIC)
|
||||||
|
return tick + nextTick
|
||||||
|
end
|
||||||
|
|
||||||
|
return mathUtils
|
@ -7,96 +7,76 @@ local constants = require("Constants")
|
|||||||
|
|
||||||
-- constants
|
-- constants
|
||||||
|
|
||||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
||||||
local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE
|
local BASE_PHEROMONE = constants.BASE_PHEROMONE
|
||||||
local PLAYER_BASE_PHEROMONE = constants.PLAYER_BASE_PHEROMONE
|
|
||||||
local ENEMY_BASE_PHEROMONE = constants.ENEMY_BASE_PHEROMONE
|
|
||||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||||
|
|
||||||
local PLAYER_DEFENSE_GENERATOR = constants.PLAYER_DEFENSE_GENERATOR
|
|
||||||
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
||||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||||
|
|
||||||
local PLAYER_PHEROMONE_GENERATOR_AMOUNT = constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT
|
local PLAYER_PHEROMONE_GENERATOR_AMOUNT = constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT
|
||||||
local DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.DEATH_PHEROMONE_GENERATOR_AMOUNT
|
local DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
|
||||||
|
|
||||||
local STANDARD_PHERONOME_DIFFUSION_AMOUNT = constants.STANDARD_PHERONOME_DIFFUSION_AMOUNT
|
local STANDARD_PHERONOME_DIFFUSION_AMOUNT = constants.STANDARD_PHERONOME_DIFFUSION_AMOUNT
|
||||||
local DEATH_PHEROMONE_DIFFUSION_AMOUNT = constants.DEATH_PHEROMONE_DIFFUSION_AMOUNT
|
local MOVEMENT_PHEROMONE_DIFFUSION_AMOUNT = constants.MOVEMENT_PHEROMONE_DIFFUSION_AMOUNT
|
||||||
|
|
||||||
local DEATH_PHEROMONE_PERSISTANCE = constants.DEATH_PHEROMONE_PERSISTANCE
|
local MOVEMENT_PHEROMONE_PERSISTANCE = constants.MOVEMENT_PHEROMONE_PERSISTANCE
|
||||||
local STANDARD_PHEROMONE_PERSISTANCE = constants.STANDARD_PHEROMONE_PERSISTANCE
|
local STANDARD_PHEROMONE_PERSISTANCE = constants.STANDARD_PHEROMONE_PERSISTANCE
|
||||||
|
|
||||||
-- imported functions
|
-- imported functions
|
||||||
|
|
||||||
local getChunkByPosition = mapUtils.getChunkByPosition
|
local getChunkByPosition = mapUtils.getChunkByPosition
|
||||||
|
local getCardinalChunks = mapUtils.getCardinalChunks
|
||||||
|
|
||||||
-- module code
|
-- module code
|
||||||
|
|
||||||
function pheromoneUtils.scents(chunk)
|
function pheromoneUtils.scents(chunk)
|
||||||
local amount = chunk[PLAYER_DEFENSE_GENERATOR]
|
chunk[BASE_PHEROMONE] = chunk[BASE_PHEROMONE] + chunk[PLAYER_BASE_GENERATOR] - chunk[ENEMY_BASE_GENERATOR]
|
||||||
if (amount > 0) then
|
|
||||||
chunk[PLAYER_DEFENSE_PHEROMONE] = chunk[PLAYER_DEFENSE_PHEROMONE] + amount
|
|
||||||
end
|
|
||||||
|
|
||||||
amount = chunk[PLAYER_BASE_GENERATOR]
|
|
||||||
if (amount > 0) then
|
|
||||||
chunk[PLAYER_BASE_PHEROMONE] = chunk[PLAYER_BASE_PHEROMONE] + amount
|
|
||||||
end
|
|
||||||
|
|
||||||
amount = chunk[ENEMY_BASE_GENERATOR]
|
|
||||||
if (amount > 0) then
|
|
||||||
chunk[ENEMY_BASE_PHEROMONE] = chunk[ENEMY_BASE_PHEROMONE] + amount
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function pheromoneUtils.deathScent(regionMap, position)
|
function pheromoneUtils.deathScent(regionMap, position)
|
||||||
local chunk = getChunkByPosition(regionMap, position.x, position.y)
|
local chunk = getChunkByPosition(regionMap, position.x, position.y)
|
||||||
if (chunk ~= nil) then
|
if (chunk ~= nil) then
|
||||||
chunk[DEATH_PHEROMONE] = chunk[DEATH_PHEROMONE] + DEATH_PHEROMONE_GENERATOR_AMOUNT
|
chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] - DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||||
-- pheromoneTotals[DEATH_PHEROMONE] = pheromoneTotals[DEATH_PHEROMONE] + DEATH_PHEROMONE_GENERATOR_AMOUNT
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function pheromoneUtils.playerScent(regionMap, players)
|
function pheromoneUtils.playerScent(playerChunk)
|
||||||
for i=1,#players do
|
playerChunk[PLAYER_PHEROMONE] = playerChunk[PLAYER_PHEROMONE] + PLAYER_PHEROMONE_GENERATOR_AMOUNT
|
||||||
local player = players[i]
|
|
||||||
if (player ~= nil) and player.connected and (player.character ~= nil) and player.character.valid and (player.character.surface.index == 1) then
|
|
||||||
local playerPosition = player.character.position
|
|
||||||
local playerChunk = getChunkByPosition(regionMap, playerPosition.x, playerPosition.y)
|
|
||||||
if (playerChunk ~= nil) then
|
|
||||||
playerChunk[PLAYER_PHEROMONE] = playerChunk[PLAYER_PHEROMONE] + PLAYER_PHEROMONE_GENERATOR_AMOUNT
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function pheromoneUtils.processPheromone(chunk, neighbors)
|
function pheromoneUtils.processPheromone(regionMap, chunk)
|
||||||
|
local neighbors
|
||||||
|
|
||||||
-- pheromone level indexes on chunks are 1 - 6
|
-- pheromone level indexes on chunks are 1 - 3
|
||||||
-- unrolled loop one level
|
-- unrolled loop one level
|
||||||
local diffusionAmount = DEATH_PHEROMONE_DIFFUSION_AMOUNT
|
local diffusionAmount = MOVEMENT_PHEROMONE_DIFFUSION_AMOUNT
|
||||||
local persistence = DEATH_PHEROMONE_PERSISTANCE
|
local persistence = MOVEMENT_PHEROMONE_PERSISTANCE
|
||||||
local totalDiffused = 0
|
local totalDiffused = 0
|
||||||
local chunkValue = chunk[DEATH_PHEROMONE] * persistence
|
local chunkValue = chunk[MOVEMENT_PHEROMONE] * persistence
|
||||||
local diffusedAmount = chunkValue * diffusionAmount
|
local diffusedAmount = chunkValue * diffusionAmount
|
||||||
if (chunkValue > 2) then
|
if (diffusedAmount > 1.5) or (diffusedAmount < -1.5) then
|
||||||
|
neighbors = getCardinalChunks(regionMap, chunk.cX, chunk.cY)
|
||||||
for i=1,#neighbors do
|
for i=1,#neighbors do
|
||||||
local neighborChunk = neighbors[i]
|
local neighborChunk = neighbors[i]
|
||||||
if (neighborChunk ~= nil) then
|
if (neighborChunk ~= nil) then
|
||||||
totalDiffused = totalDiffused + diffusedAmount
|
totalDiffused = totalDiffused + diffusedAmount
|
||||||
neighborChunk[DEATH_PHEROMONE] = neighborChunk[DEATH_PHEROMONE] + diffusedAmount
|
neighborChunk[MOVEMENT_PHEROMONE] = neighborChunk[MOVEMENT_PHEROMONE] + diffusedAmount
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
chunk[DEATH_PHEROMONE] = (chunkValue - totalDiffused)
|
chunk[MOVEMENT_PHEROMONE] = (chunkValue - totalDiffused)
|
||||||
|
|
||||||
diffusionAmount = STANDARD_PHERONOME_DIFFUSION_AMOUNT
|
diffusionAmount = STANDARD_PHERONOME_DIFFUSION_AMOUNT
|
||||||
persistence = STANDARD_PHEROMONE_PERSISTANCE
|
persistence = STANDARD_PHEROMONE_PERSISTANCE
|
||||||
for x=2,6 do
|
for x=2,3 do
|
||||||
totalDiffused = 0
|
totalDiffused = 0
|
||||||
chunkValue = chunk[x] * persistence
|
chunkValue = chunk[x] * persistence
|
||||||
diffusedAmount = chunkValue * diffusionAmount
|
diffusedAmount = chunkValue * diffusionAmount
|
||||||
if (chunkValue > 2) then
|
if (diffusedAmount > 1.5) then
|
||||||
|
if (neighbors == nil) then
|
||||||
|
neighbors = getCardinalChunks(regionMap, chunk.cX, chunk.cY)
|
||||||
|
end
|
||||||
for i=1,#neighbors do
|
for i=1,#neighbors do
|
||||||
local neighborChunk = neighbors[i]
|
local neighborChunk = neighbors[i]
|
||||||
if (neighborChunk ~= nil) then
|
if (neighborChunk ~= nil) then
|
||||||
@ -105,7 +85,7 @@ function pheromoneUtils.processPheromone(chunk, neighbors)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
chunk[x] = (chunkValue - totalDiffused)
|
chunk[x] = (chunkValue - totalDiffused)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -11,13 +11,12 @@ local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed
|
|||||||
-- module code
|
-- module code
|
||||||
|
|
||||||
function playerUtils.playersWithinProximityToPosition(players, position, distance)
|
function playerUtils.playersWithinProximityToPosition(players, position, distance)
|
||||||
for x=1,#players do
|
for _,player in pairs(players) do
|
||||||
local player = players[x]
|
if (player ~= nil) and player.connected and (player.character ~= nil) and player.character.valid and (player.character.surface.index == 1) then
|
||||||
if (player ~= nil) and player.connected and (player.character ~= nil) and player.character.valid and (player.character.surface.index == 1) then
|
if (euclideanDistanceNamed(player.character.position, position) < distance) then
|
||||||
if (euclideanDistanceNamed(player.character.position, position) < distance) then
|
return true
|
||||||
return true
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
@ -7,7 +7,7 @@ local constants = require("Constants")
|
|||||||
|
|
||||||
-- constants
|
-- constants
|
||||||
|
|
||||||
local MOVEMENT_PENALTY_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PENALTY_PHEROMONE_GENERATOR_AMOUNT
|
local MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
|
||||||
|
|
||||||
local GROUP_STATE_FINISHED = defines.group_state.finished
|
local GROUP_STATE_FINISHED = defines.group_state.finished
|
||||||
|
|
||||||
@ -93,14 +93,14 @@ function unitGroupUtils.addSquadMovementPenalty(squad, chunkX, chunkY)
|
|||||||
for i=1,#penalties do
|
for i=1,#penalties do
|
||||||
local penalty = penalties[i]
|
local penalty = penalties[i]
|
||||||
if (penalty.x == chunkX) and (penalty.y == chunkY) then
|
if (penalty.x == chunkX) and (penalty.y == chunkY) then
|
||||||
penalty.v = penalty.v + MOVEMENT_PENALTY_PHEROMONE_GENERATOR_AMOUNT
|
penalty.v = penalty.v + MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (#penalties == 10) then
|
if (#penalties == 10) then
|
||||||
tableRemove(penalties, 10)
|
tableRemove(penalties, 10)
|
||||||
end
|
end
|
||||||
tableInsert(penalties, 1, { v = MOVEMENT_PENALTY_PHEROMONE_GENERATOR_AMOUNT,
|
tableInsert(penalties, 1, { v = MOVEMENT_PHEROMONE_GENERATOR_AMOUNT,
|
||||||
x = chunkX,
|
x = chunkX,
|
||||||
y = chunkY })
|
y = chunkY })
|
||||||
end
|
end
|
||||||
|
113
make.rkt
113
make.rkt
@ -6,74 +6,75 @@
|
|||||||
;(define modFolder "C:/Users/veden/AppData/Roaming/Factorio/mods/")
|
;(define modFolder "C:/Users/veden/AppData/Roaming/Factorio/mods/")
|
||||||
;(define zipModFolder "C:/Program Files/Factorio_0.14.1/mods/")
|
;(define zipModFolder "C:/Program Files/Factorio_0.14.1/mods/")
|
||||||
(define modFolder "/home/veden/.factorio/mods/")
|
(define modFolder "/home/veden/.factorio/mods/")
|
||||||
(define zipModFolder "/data/games/factorio14.13/mods/")
|
(define zipModFolder "/data/games/factorio14.14/mods/")
|
||||||
(define configuration (call-with-input-file "info.json"
|
(define configuration (call-with-input-file "info.json"
|
||||||
(lambda (port)
|
(lambda (port)
|
||||||
(string->jsexpr (port->string port)))))
|
(string->jsexpr (port->string port)))))
|
||||||
(define packageName (string-append (string-replace (hash-ref configuration 'name) " " "_")
|
(define packageName (string-append (string-replace (hash-ref configuration 'name) " " "_")
|
||||||
"_"
|
"_"
|
||||||
(hash-ref configuration 'version)))
|
(hash-ref configuration 'version)))
|
||||||
|
|
||||||
(define (makeZip)
|
(define (makeZip folder)
|
||||||
(let ((packagePath (string->path (string-append modFolder
|
(let ((packagePath (string->path (string-append folder
|
||||||
packageName
|
packageName
|
||||||
".zip"))))
|
".zip"))))
|
||||||
(when (file-exists? packagePath)
|
(when (file-exists? packagePath)
|
||||||
(delete-file packagePath)))
|
(delete-file packagePath)))
|
||||||
(zip (string-append modFolder
|
(zip (string-append folder
|
||||||
packageName
|
packageName
|
||||||
".zip")
|
".zip")
|
||||||
#:path-prefix packageName
|
#:path-prefix packageName
|
||||||
(string->path "info.json")
|
(string->path "info.json")
|
||||||
(string->path "control.lua")
|
(string->path "control.lua")
|
||||||
(string->path "config.lua")
|
(string->path "config.lua")
|
||||||
(string->path "data.lua")
|
(string->path "data.lua")
|
||||||
(string->path "LICENSE.md")
|
(string->path "LICENSE.md")
|
||||||
(string->path "tests.lua")
|
(string->path "tests.lua")
|
||||||
; (string->path "setupUtils.lua")
|
; (string->path "setupUtils.lua")
|
||||||
(string->path "README.md")
|
(string->path "README.md")
|
||||||
; (string->path "setup.lua")
|
; (string->path "setup.lua")
|
||||||
(string->path "NOTICE")
|
(string->path "NOTICE")
|
||||||
(string->path "libs")
|
(string->path "libs")
|
||||||
(string->path "locale")
|
(string->path "locale")
|
||||||
(string->path "graphics")
|
(string->path "graphics")
|
||||||
(string->path "prototypes")))
|
(string->path "prototypes")))
|
||||||
|
|
||||||
|
|
||||||
;(current-directory "..")
|
;(current-directory "..")
|
||||||
(define (copyFile fileName modFolder)
|
(define (copyFile fileName modFolder)
|
||||||
(copy-file (string->path fileName)
|
(copy-file (string->path fileName)
|
||||||
(string->path (string-append modFolder
|
(string->path (string-append modFolder
|
||||||
packageName
|
packageName
|
||||||
"/"
|
"/"
|
||||||
fileName))))
|
fileName))))
|
||||||
|
|
||||||
(define (copyDirectory directoryName modFolder)
|
(define (copyDirectory directoryName modFolder)
|
||||||
(copy-directory/files (string->path directoryName)
|
(copy-directory/files (string->path directoryName)
|
||||||
(string->path (string-append modFolder
|
(string->path (string-append modFolder
|
||||||
packageName
|
packageName
|
||||||
"/"
|
"/"
|
||||||
directoryName))))
|
directoryName))))
|
||||||
|
|
||||||
(define (copyFiles modFolder)
|
(define (copyFiles modFolder)
|
||||||
(let ((packagePath (string->path (string-append modFolder
|
(let ((packagePath (string->path (string-append modFolder
|
||||||
packageName))))
|
packageName))))
|
||||||
(when (directory-exists? packagePath)
|
(when (directory-exists? packagePath)
|
||||||
(delete-directory/files packagePath))
|
(delete-directory/files packagePath))
|
||||||
(sleep 0.1)
|
(sleep 0.1)
|
||||||
(make-directory packagePath)
|
(make-directory packagePath)
|
||||||
(copyFile "control.lua" modFolder)
|
(copyFile "control.lua" modFolder)
|
||||||
(copyFile "config.lua" modFolder)
|
(copyFile "config.lua" modFolder)
|
||||||
(copyFile "info.json" modFolder)
|
(copyFile "info.json" modFolder)
|
||||||
; (copyFile "setupUtils.lua" modFolder)
|
; (copyFile "setupUtils.lua" modFolder)
|
||||||
(copyFile "data.lua" modFolder)
|
(copyFile "data.lua" modFolder)
|
||||||
(copyFile "tests.lua" modFolder)
|
(copyFile "tests.lua" modFolder)
|
||||||
(copyDirectory "libs" modFolder)
|
(copyDirectory "libs" modFolder)
|
||||||
(copyDirectory "locale" modFolder)
|
(copyDirectory "locale" modFolder)
|
||||||
(copyDirectory "graphics" modFolder)
|
(copyDirectory "graphics" modFolder)
|
||||||
(copyDirectory "prototypes" modFolder)))
|
(copyDirectory "prototypes" modFolder)))
|
||||||
|
|
||||||
;; (copyFiles modFolder)
|
;; (copyFiles modFolder)
|
||||||
;; (copyFiles zipModFolder)
|
;; (copyFiles zipModFolder)
|
||||||
(makeZip)
|
(makeZip modFolder)
|
||||||
|
(makeZip zipModFolder)
|
||||||
)
|
)
|
||||||
|
19
tests.lua
19
tests.lua
@ -10,8 +10,8 @@ function tests.test1()
|
|||||||
print(#global.regionMap.processQueue)
|
print(#global.regionMap.processQueue)
|
||||||
print(playerChunkX .. ", " .. playerChunkY)
|
print(playerChunkX .. ", " .. playerChunkY)
|
||||||
print("--")
|
print("--")
|
||||||
for x=playerChunkX-3, playerChunkX+3 do
|
for x=playerChunkX-9, playerChunkX+9 do
|
||||||
for y=playerChunkY-3, playerChunkY+3 do
|
for y=playerChunkY-9, playerChunkY+9 do
|
||||||
if (global.regionMap[x] ~= nil) then
|
if (global.regionMap[x] ~= nil) then
|
||||||
local chunk = global.regionMap[x][y]
|
local chunk = global.regionMap[x][y]
|
||||||
if (chunk ~= nil) then
|
if (chunk ~= nil) then
|
||||||
@ -19,13 +19,14 @@ function tests.test1()
|
|||||||
for i=1,#chunk do
|
for i=1,#chunk do
|
||||||
str = str .. " " .. tostring(i) .. "/" .. tostring(chunk[i])
|
str = str .. " " .. tostring(i) .. "/" .. tostring(chunk[i])
|
||||||
end
|
end
|
||||||
if (chunk.cX == playerChunkX) and (chunk.cY == playerChunkY) then
|
str = str .. " " .. "p/" .. game.surfaces[1].get_pollution({x=chunk.pX, y=chunk.pY})
|
||||||
print("*", chunk.cX, chunk.cY, str)
|
if (chunk.cX == playerChunkX) and (chunk.cY == playerChunkY) then
|
||||||
else
|
print("*", chunk.cX, chunk.cY, str)
|
||||||
print(chunk.cX, chunk.cY, str)
|
else
|
||||||
end
|
print(chunk.cX, chunk.cY, str)
|
||||||
-- print(str)
|
end
|
||||||
print("-")
|
-- print(str)
|
||||||
|
print("-")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user