mirror of
https://github.com/veden/Rampant.git
synced 2025-09-16 09:16:43 +02:00
attempted to make everything MP compatible, not very successfully
This commit is contained in:
174
control.lua
174
control.lua
@@ -1,3 +1,5 @@
|
||||
-- imports
|
||||
|
||||
local chunkUtils = require("libs/ChunkUtils")
|
||||
local mapUtils = require("libs/MapUtils")
|
||||
local unitGroupUtils = require("libs/UnitGroupUtils")
|
||||
@@ -10,45 +12,88 @@ local aiAttack = require("libs/AIAttack")
|
||||
local aiBuilding = require("libs/AIBuilding")
|
||||
local tests = require("Tests")
|
||||
|
||||
local mapRoutine --coroutine holding state of in progress processing
|
||||
local chunkRoutine
|
||||
-- state
|
||||
|
||||
-- local players
|
||||
local regionMap -- chunk based map
|
||||
local pendingChunks -- pending chunks to be processed
|
||||
local natives -- units that are being commanded
|
||||
local surface -- main game surface
|
||||
|
||||
-- initialization
|
||||
|
||||
chunkProcessor.install(chunkUtils.checkChunkPassability)
|
||||
chunkProcessor.install(chunkUtils.scoreChunk)
|
||||
|
||||
mapProcessor.install(pheromoneUtils.enemyBaseScent, 0, 1)
|
||||
mapProcessor.install(pheromoneUtils.playerDefenseScent, 0, 1)
|
||||
mapProcessor.install(pheromoneUtils.playerBaseScent, 0, 1)
|
||||
mapProcessor.install(aiBuilding.sendScouts, 0.05, 0.10)
|
||||
mapProcessor.install(aiBuilding.formSquads, 0.11, 0.25)
|
||||
mapProcessor.install(pheromoneUtils.processPheromone, 0, 1)
|
||||
|
||||
-- constants
|
||||
|
||||
local DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
|
||||
-- imported functions
|
||||
|
||||
local processPendingChunks = chunkProcessor.processPendingChunks
|
||||
|
||||
local processMap = mapProcessor.processMap
|
||||
|
||||
local accumulatePoints = aiBuilding.accumulatePoints
|
||||
local removeScout = aiBuilding.removeScout
|
||||
local scouting = aiBuilding.scouting
|
||||
|
||||
local playerScent = pheromoneUtils.playerScent
|
||||
local deathScent = pheromoneUtils.deathScent
|
||||
|
||||
local regroupSquads = unitGroupUtils.regroupSquads
|
||||
local convertUnitGroupToSquad = unitGroupUtils.convertUnitGroupToSquad
|
||||
|
||||
local squadAttackPlayer = aiAttack.squadAttackPlayer
|
||||
local squadAttackLocation = aiAttack.squadAttackLocation
|
||||
local squadBeginAttack = aiAttack.squadBeginAttack
|
||||
|
||||
local retreatUnits = aiDefense.retreatUnits
|
||||
|
||||
local addRemoveObject = mapUtils.addRemoveObject
|
||||
|
||||
local mRandom = math.random
|
||||
|
||||
-- hook functions
|
||||
|
||||
function onInit()
|
||||
print("init")
|
||||
-- print("init")
|
||||
global.regionMap = {}
|
||||
global.pendingChunks = {}
|
||||
global.natives = {}
|
||||
|
||||
regionMap = global.regionMap
|
||||
pendingChunks = global.pendingChunks
|
||||
regionMap.pQ = {{}} -- processing queue
|
||||
regionMap.pI = 1 -- insertion location for chunk processing
|
||||
regionMap.pP = 1 -- index for the chunk set to process
|
||||
regionMap.pR = -1 -- current processing roll
|
||||
natives = global.natives
|
||||
natives.squads = {}
|
||||
natives.scouts = {}
|
||||
natives.points = 0
|
||||
|
||||
-- queue all current chunks that wont be generated during play
|
||||
surface = game.surfaces[1]
|
||||
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}}})
|
||||
onChunkGenerated({ surface = surface,
|
||||
area = {left_top = { x = chunk.x * 32,
|
||||
y = chunk.y * 32 }}})
|
||||
end
|
||||
end
|
||||
|
||||
function onLoad()
|
||||
print("load")
|
||||
-- print("load")
|
||||
regionMap = global.regionMap
|
||||
pendingChunks = global.pendingChunks
|
||||
natives = global.natives
|
||||
-- commands = global.commands
|
||||
end
|
||||
|
||||
function onChunkGenerated(event)
|
||||
@@ -61,50 +106,34 @@ end
|
||||
|
||||
function onTick(event)
|
||||
if (event.tick % 40 == 0) then
|
||||
-- using coroutines to keep the cpu load time managable will still being able to work large maps
|
||||
local working, errorMsg = true, nil
|
||||
if (chunkRoutine ~= nil) and (coroutine.status(chunkRoutine) ~= "dead") then
|
||||
working, errorMsg = coroutine.resume(chunkRoutine)
|
||||
elseif (#pendingChunks > 0) then
|
||||
-- coroutines start suspended, so you have to resume them after creation
|
||||
chunkRoutine = coroutine.create(chunkProcessor.processPendingChunks)
|
||||
working, errorMsg = coroutine.resume(chunkRoutine, regionMap, surface, natives, pendingChunks)
|
||||
end
|
||||
if not working then
|
||||
error(errorMsg)
|
||||
end
|
||||
local surface = game.surfaces[1]
|
||||
|
||||
aiBuilding.accumulatePoints(natives)
|
||||
processPendingChunks(regionMap, surface, natives, pendingChunks)
|
||||
|
||||
accumulatePoints(natives)
|
||||
|
||||
-- put down player pheromone for player hunters
|
||||
pheromoneUtils.playerScent(regionMap, game.players)
|
||||
playerScent(regionMap, game.players)
|
||||
|
||||
unitGroupUtils.regroupSquads(natives)
|
||||
regroupSquads(natives)
|
||||
|
||||
-- aiBuilding.scouting(regionMap, surface, natives)
|
||||
aiAttack.squadAttackPlayer(regionMap, surface, natives, game.players)
|
||||
scouting(regionMap, surface, natives)
|
||||
|
||||
aiAttack.squadBeginAttack(natives)
|
||||
aiAttack.squadAttackLocation(regionMap, surface, natives)
|
||||
processMap(regionMap, surface, natives, game.evolution_factor)
|
||||
|
||||
if (mapRoutine ~= nil) and (coroutine.status(mapRoutine) ~= "dead") then
|
||||
working, errorMsg = coroutine.resume(mapRoutine)
|
||||
elseif (mapRoutine == nil) or (coroutine.status(mapRoutine) == "dead") then
|
||||
mapRoutine = coroutine.create(mapProcessor.processMap)
|
||||
working, errorMsg = coroutine.resume(mapRoutine, regionMap, surface, natives)
|
||||
end
|
||||
if not working then
|
||||
error(errorMsg)
|
||||
end
|
||||
squadAttackPlayer(regionMap, surface, natives, game.players)
|
||||
|
||||
squadBeginAttack(natives)
|
||||
squadAttackLocation(regionMap, surface, natives)
|
||||
end
|
||||
end
|
||||
|
||||
function onBuild(event)
|
||||
mapUtils.addRemoveObject(regionMap, event.created_entity, natives, true)
|
||||
addRemoveObject(regionMap, event.created_entity, natives, true)
|
||||
end
|
||||
|
||||
function onPickUp(event)
|
||||
mapUtils.addRemoveObject(regionMap, event.entity, natives, false)
|
||||
addRemoveObject(regionMap, event.entity, natives, false)
|
||||
end
|
||||
|
||||
function onDeath(event)
|
||||
@@ -113,65 +142,30 @@ function onDeath(event)
|
||||
if (entity.type == "unit") then
|
||||
local entityPosition = entity.position
|
||||
-- drop death pheromone where unit died
|
||||
pheromoneUtils.deathScent(regionMap,
|
||||
surface,
|
||||
entityPosition.x,
|
||||
entityPosition.y,
|
||||
constants.DEATH_PHEROMONE_GENERATOR_AMOUNT)
|
||||
local squad = convertUnitGroupToSquad(natives, entity.unit_group)
|
||||
|
||||
local surface = game.surfaces[1]
|
||||
|
||||
deathScent(regionMap,
|
||||
surface,
|
||||
entityPosition.x,
|
||||
entityPosition.y,
|
||||
squad,
|
||||
DEATH_PHEROMONE_GENERATOR_AMOUNT)
|
||||
|
||||
if (event.force ~= nil) and (event.force.name == "player") then
|
||||
local squad = unitGroupUtils.convertUnitGroupToSquad(natives, entity.unit_group)
|
||||
aiDefense.retreatUnits(entityPosition, squad, regionMap, surface, natives)
|
||||
retreatUnits(entityPosition, squad, regionMap, surface, natives)
|
||||
end
|
||||
|
||||
aiBuilding.removeScout(entity, natives)
|
||||
removeScout(entity, natives)
|
||||
elseif (entity.type == "unit-spawner") then
|
||||
mapUtils.addRemoveObject(regionMap, entity, natives, false)
|
||||
addRemoveObject(regionMap, entity, natives, false)
|
||||
end
|
||||
elseif (entity.force.name == "player") then
|
||||
mapUtils.addRemoveObject(regionMap, entity, natives, false)
|
||||
addRemoveObject(regionMap, entity, natives, false)
|
||||
end
|
||||
end
|
||||
|
||||
-- setup variables in the various modules
|
||||
function onInitialTick(event)
|
||||
-- players = game.players
|
||||
if (surface == nil) then
|
||||
surface = game.surfaces[1]
|
||||
end
|
||||
|
||||
-- game.forces.player.research_all_technologies()
|
||||
-- game.players[1].cheat_mode = true
|
||||
|
||||
-- turn off enemy ai
|
||||
-- game.surfaces[1].peaceful_mode = true
|
||||
-- game.surfaces[1].peaceful_mode = false
|
||||
-- remove enemies that aren't off
|
||||
-- game.forces.enemy.kill_all_units()
|
||||
|
||||
-- turn off base expansion
|
||||
game.forces.enemy.ai_controllable = false
|
||||
-- game.map_settings.enemy_expansion.enabled = false
|
||||
|
||||
-- add processing handler into generated chunk event loop
|
||||
chunkProcessor.install(chunkUtils.checkChunkPassability)
|
||||
chunkProcessor.install(chunkUtils.scoreChunk)
|
||||
|
||||
-- add processing handler into chunk map processing
|
||||
mapProcessor.install(pheromoneUtils.enemyBaseScent, 0, 1)
|
||||
mapProcessor.install(pheromoneUtils.playerDefenseScent, 0, 1)
|
||||
mapProcessor.install(pheromoneUtils.playerBaseScent, 0, 1)
|
||||
mapProcessor.install(aiBuilding.sendScouts, 0.05, 0.10)
|
||||
mapProcessor.install(aiBuilding.formSquads, 0.11, 0.20)
|
||||
mapProcessor.install(pheromoneUtils.processPheromone, 0, 1)
|
||||
|
||||
-- used for debugging
|
||||
tests.initTester()
|
||||
|
||||
-- swap to real on tick function
|
||||
script.on_event(defines.events.on_tick, onTick)
|
||||
end
|
||||
|
||||
-- hooks
|
||||
|
||||
script.on_init(onInit)
|
||||
@@ -185,7 +179,7 @@ script.on_event({defines.events.on_built_entity,
|
||||
onBuild)
|
||||
|
||||
script.on_event(defines.events.on_entity_died, onDeath)
|
||||
script.on_event(defines.events.on_tick, onInitialTick)
|
||||
script.on_event(defines.events.on_tick, onTick)
|
||||
script.on_event(defines.events.on_chunk_generated, onChunkGenerated)
|
||||
|
||||
remote.add_interface("rampant", {
|
||||
|
@@ -1,81 +1,82 @@
|
||||
local aiAttack = {}
|
||||
|
||||
-- local attackLocationNeighbors = {1,2,3,4}
|
||||
-- imports
|
||||
|
||||
local factorio_defined = defines
|
||||
local constants = require("Constants")
|
||||
local mapUtils = require("MapUtils")
|
||||
local utils = require("Utils")
|
||||
local unitGroupUtils = require("UnitGroupUtils")
|
||||
|
||||
local attackPosition = {x=0, y=0} -- used to minimize garbage generation
|
||||
local attackLocationNeighbors = {1,2,3,4,5,6,7,8}
|
||||
local attackLocationCommand = {type=defines.command.attack_area,
|
||||
destination=attackPosition,
|
||||
radius=constants.HALF_CHUNK_SIZE,
|
||||
distraction=defines.distraction.by_anything}
|
||||
-- constants
|
||||
|
||||
local attackObjectCommand = {type=defines.command.attack,
|
||||
target=1,
|
||||
distraction=defines.distraction.by_anything}
|
||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
||||
local ENEMY_BASE_PHEROMONE = constants.ENEMY_BASE_PHEROMONE
|
||||
local PLAYER_BASE_PHEROMONE = constants.PLAYER_BASE_PHEROMONE
|
||||
local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE
|
||||
|
||||
local attackPlayerCommand = {type=defines.command.attack,
|
||||
target=1}
|
||||
local SQUAD_RAIDING = constants.SQUAD_RAIDING
|
||||
local SQUAD_SUICIDE_RAID = constants.SQUAD_SUICIDE_RAID
|
||||
local SQUAD_HUNTING = constants.SQUAD_HUNTING
|
||||
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
||||
local SQUAD_SUICIDE_HUNT = constants.SQUAD_SUICIDE_HUNT
|
||||
|
||||
local nearestAreaBox = {{1,2},
|
||||
{3,4}}
|
||||
local nearestTable = {area=nearestAreaBox,
|
||||
force="player",
|
||||
limit=1}
|
||||
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_DEFENSE_GENERATOR = constants.PLAYER_DEFENSE_GENERATOR
|
||||
|
||||
local GROUP_STATE_FINISHED = defines.group_state.finished
|
||||
local GROUP_STATE_GATHERING = defines.group_state.gathering
|
||||
local GROUP_STATE_MOVING = defines.group_state.moving
|
||||
|
||||
local COMMAND_ATTACK_AREA = defines.command.attack_area
|
||||
local COMMAND_ATTACK = defines.command.attack
|
||||
|
||||
local DISTRACTION_BY_ANYTHING = defines.distraction.by_anything
|
||||
|
||||
-- imported functions
|
||||
|
||||
local getCardinalChunks = mapUtils.getCardinalChunks
|
||||
local positionToChunk = mapUtils.getChunkByPosition
|
||||
local canMove = mapUtils.canMoveChunkDirectionCardinal
|
||||
local addSquadMovementPenalty = unitGroupUtils.addSquadMovementPenalty
|
||||
local lookupSquadMovementPenalty = unitGroupUtils.lookupSquadMovementPenalty
|
||||
local positionDirectionToChunkCornerCardinal = mapUtils.positionDirectionToChunkCornerCardinal
|
||||
local findDistance = mapUtils.euclideanDistanceNamed
|
||||
|
||||
local mRandom = math.random
|
||||
|
||||
-- module code
|
||||
|
||||
function aiAttack.squadAttackLocation(regionMap, surface, natives)
|
||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
||||
local SQUAD_RAIDING = constants.SQUAD_RAIDING
|
||||
local SQUAD_SUICIDE_RAID = constants.SQUAD_SUICIDE_RAID
|
||||
local ENEMY_BASE_PHEROMONE = constants.ENEMY_BASE_PHEROMONE
|
||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||
local PLAYER_BASE_PHEROMONE = constants.PLAYER_BASE_PHEROMONE
|
||||
local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE
|
||||
local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
|
||||
local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE
|
||||
local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||
local group_states = factorio_defined.group_state
|
||||
local mathRandom = mRandom
|
||||
|
||||
-- local getNeighborChunks = mapUtils.getCardinalChunks
|
||||
local getNeighborChunks = mapUtils.getNeighborChunks
|
||||
local positionToChunk = mapUtils.positionToChunkOffset
|
||||
|
||||
local squads = natives.squads
|
||||
for i=1, #squads do
|
||||
local squad = squads[i]
|
||||
local group = squad.group
|
||||
local squadStatus = squad.status
|
||||
if group.valid and ((squadStatus == SQUAD_RAIDING) or (squadStatus == SQUAD_SUICIDE_RAID)) then
|
||||
if ((group.state == group_states.finished) or (group.state == group_states.gathering) or (group.state == group_states.moving)) and (squad.cycles == 0) then
|
||||
local cX, cY
|
||||
if (squad.cX == nil) then
|
||||
cX, cY = positionToChunk(group.position)
|
||||
else
|
||||
cX = squad.cX
|
||||
cY = squad.cY
|
||||
end
|
||||
getNeighborChunks(regionMap, cX, cY, attackLocationNeighbors)
|
||||
if group.valid and ((squad.status == SQUAD_RAIDING) or (squad.status == SQUAD_SUICIDE_RAID)) then
|
||||
local groupState = group.state
|
||||
if (groupState == GROUP_STATE_FINISHED) or (groupState == GROUP_STATE_GATHERING) or (groupState == GROUP_STATE_MOVING) then
|
||||
local chunk = positionToChunk(regionMap, group.position.x, group.position.y)
|
||||
addSquadMovementPenalty(squad, chunk.cX, chunk.cY)
|
||||
local attackLocationNeighbors = getCardinalChunks(regionMap, chunk.cX, chunk.cY)
|
||||
local attackChunk
|
||||
local attackScore = -MAGIC_MAXIMUM_NUMBER
|
||||
local attackDirection
|
||||
local attackPosition = {x=0, y=0}
|
||||
-- print("------")
|
||||
for x=1, #attackLocationNeighbors do
|
||||
local neighborChunk = attackLocationNeighbors[x]
|
||||
if (neighborChunk ~= nil) then
|
||||
if (neighborChunk ~= nil) and canMove(x, chunk, neighborChunk) then
|
||||
attackPosition.x = neighborChunk.pX
|
||||
attackPosition.y = neighborChunk.pY
|
||||
local damageScore = surface.get_pollution(attackPosition) + neighborChunk[PLAYER_BASE_PHEROMONE] + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[constants.PLAYER_DEFENSE_GENERATOR]
|
||||
local avoidScore = neighborChunk[DEATH_PHEROMONE] + neighborChunk[ENEMY_BASE_GENERATOR] + neighborChunk[ENEMY_BASE_PHEROMONE] --
|
||||
local score = damageScore - avoidScore
|
||||
local squadMovementPenalty = lookupSquadMovementPenalty(squad, neighborChunk.cX, neighborChunk.cY)
|
||||
local damageScore = surface.get_pollution(attackPosition) + neighborChunk[PLAYER_BASE_PHEROMONE] + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[PLAYER_DEFENSE_GENERATOR]
|
||||
local avoidScore = neighborChunk[DEATH_PHEROMONE] --+ neighborChunk[ENEMY_BASE_GENERATOR] + neighborChunk[ENEMY_BASE_PHEROMONE]
|
||||
local score = damageScore - avoidScore - squadMovementPenalty
|
||||
if (score > attackScore) then
|
||||
attackScore = score
|
||||
attackChunk = neighborChunk
|
||||
@@ -86,41 +87,21 @@ function aiAttack.squadAttackLocation(regionMap, surface, natives)
|
||||
end
|
||||
if (attackChunk ~= nil) then
|
||||
-- print("==")
|
||||
-- print (attackDirection, cX, cY)
|
||||
-- local target
|
||||
if (attackChunk[constants.PLAYER_BASE_GENERATOR] == 0) or (attackChunk[constants.PLAYER_DEFENSE_GENERATOR] == 0) then
|
||||
-- nearestAreaBox[1][1] = group.position.x - CHUNK_SIZE
|
||||
-- nearestAreaBox[1][2] = group.position.y - CHUNK_SIZE
|
||||
-- nearestAreaBox[2][1] = group.position.x + CHUNK_SIZE
|
||||
-- nearestAreaBox[2][2] = group.position.y + CHUNK_SIZE
|
||||
-- target = surface.find_entities_filtered(nearestTable)
|
||||
-- if (#target == 1) and (target[1].prototype.max_health ~= 0) then
|
||||
-- print(target[1].name)
|
||||
-- attackObjectCommand.target = target[1]
|
||||
-- group.set_command(attackObjectCommand)
|
||||
-- end
|
||||
|
||||
-- if (target == nil) then
|
||||
-- utils.positionDirectionToChunkCorner(attackDirection, attackChunk, attackPosition)
|
||||
attackPosition.x = attackChunk.pX + HALF_CHUNK_SIZE
|
||||
attackPosition.y = attackChunk.pY + HALF_CHUNK_SIZE
|
||||
squad.cycles = 4
|
||||
-- print (attackDirection, chunk.cX, chunk.cY)
|
||||
if ((attackChunk[PLAYER_BASE_GENERATOR] == 0) or (attackChunk[PLAYER_DEFENSE_GENERATOR] == 0)) or
|
||||
((groupState == GROUP_STATE_FINISHED) or (groupState == GROUP_STATE_GATHERING)) then
|
||||
-- print("attacking")
|
||||
attackPosition = positionDirectionToChunkCornerCardinal(attackDirection, attackChunk)
|
||||
squad.cX = attackChunk.cX
|
||||
squad.cY = attackChunk.cY
|
||||
|
||||
group.set_command(attackLocationCommand)
|
||||
-- end
|
||||
group.set_command({type=COMMAND_ATTACK_AREA,
|
||||
destination=attackPosition,
|
||||
radius=HALF_CHUNK_SIZE,
|
||||
distraction=DISTRACTION_BY_ANYTHING})
|
||||
group.start_moving()
|
||||
end
|
||||
end
|
||||
-- elseif (group.state == group_states.attacking_distraction) and (mathRandom() < 0.3) then
|
||||
-- local playerTarget = surface.find_nearest_enemy({position=group.position,
|
||||
-- max_distance=CHUNK_SIZE,
|
||||
-- force="enemy"})
|
||||
-- if (playerTarget ~= nil) then
|
||||
-- group.set_command({type=defines.command.attack,
|
||||
-- target=playerTarget})
|
||||
-- end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -128,15 +109,6 @@ end
|
||||
|
||||
|
||||
function aiAttack.squadAttackPlayer(regionMap, surface, natives, players)
|
||||
local SQUAD_HUNTING = constants.SQUAD_HUNTING
|
||||
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
||||
local SQUAD_SUICIDE_HUNT = constants.SQUAD_SUICIDE_HUNT
|
||||
local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
|
||||
local findDistance = utils.euclideanDistanceNamed
|
||||
-- local commandAttack =
|
||||
|
||||
local mathRandom = mRandom
|
||||
|
||||
local squads = natives.squads
|
||||
|
||||
for si=1, #squads do
|
||||
@@ -146,36 +118,38 @@ function aiAttack.squadAttackPlayer(regionMap, surface, natives, players)
|
||||
local closestPlayer
|
||||
local closestDistance = MAGIC_MAXIMUM_NUMBER
|
||||
for pi=1, #players do
|
||||
local playerCharacer = players[pi].character
|
||||
local distance = findDistance(playerCharacer.position, group.position)
|
||||
if (distance < closestDistance) then
|
||||
closestPlayer = playerCharacer
|
||||
closestDistance = distance
|
||||
local player = players[pi]
|
||||
if (player.connected) then
|
||||
local playerCharacer = player.character
|
||||
if (playerCharacer ~= nil) then
|
||||
local distance = findDistance(playerCharacer.position, group.position)
|
||||
if (distance < closestDistance) then
|
||||
closestPlayer = playerCharacer
|
||||
closestDistance = distance
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if (closestDistance < 75) then
|
||||
local squadType = SQUAD_HUNTING
|
||||
if (mathRandom() < 0.10) then -- TODO add sliding scale based on number of members and evolution
|
||||
if (mRandom() < 0.10) then -- TODO add sliding scale based on number of members and evolution
|
||||
squadType = SQUAD_SUICIDE_HUNT
|
||||
end
|
||||
squad.status = squadType
|
||||
attackPlayerCommand.target = closestPlayer
|
||||
group.set_command(attackPlayerCommand)
|
||||
group.set_command({type=COMMAND_ATTACK,
|
||||
target=closestPlayer})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function aiAttack.squadBeginAttack(natives)
|
||||
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
||||
local SQUAD_SUICIDE_RAID = constants.SQUAD_SUICIDE_RAID
|
||||
local SQUAD_RAIDING = constants.SQUAD_RAIDING
|
||||
local mathRandom = mRandom
|
||||
local squads = natives.squads
|
||||
|
||||
for i=1,#natives.squads do
|
||||
local squad = natives.squads[i]
|
||||
if (squad.status == SQUAD_GUARDING) and (mathRandom() < 0.7) then
|
||||
if (mathRandom() < 0.05) then
|
||||
for i=1,#squads do
|
||||
local squad = squads[i]
|
||||
if (squad.status == SQUAD_GUARDING) and (mRandom() < 0.7) then
|
||||
if (mRandom() < 0.05) then
|
||||
squad.status = SQUAD_SUICIDE_RAID
|
||||
else
|
||||
squad.status = SQUAD_RAIDING
|
||||
|
@@ -1,42 +1,84 @@
|
||||
local aiBuilding = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local constants = require("Constants")
|
||||
local mapUtils = require("MapUtils")
|
||||
local unitGroupUtils = require("UnitGroupUtils")
|
||||
|
||||
local squadNeighbors = {1,2,3,4,5,6,7,8}
|
||||
local squadPosition = {1,2}
|
||||
-- constants
|
||||
|
||||
local PLAYER_BASE_PHEROMONE = constants.PLAYER_BASE_PHEROMONE
|
||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||
local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_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 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_MAX_SQUAD_COUNT = constants.AI_MAX_SQUAD_COUNT
|
||||
local AI_MAX_SQUAD_SIZE = constants.AI_MAX_SQUAD_SIZE
|
||||
|
||||
local HALF_CHUNK_SIZE = constants.HALF_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 EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE
|
||||
|
||||
local COMMAND_GROUP = defines.command.group
|
||||
local DISTRACTION_BY_DAMAGE = defines.distraction.by_damage
|
||||
|
||||
-- imported functions
|
||||
|
||||
local getNeighborChunks = mapUtils.getNeighborChunks
|
||||
local createSquad = unitGroupUtils.createSquad
|
||||
|
||||
local tableRemove = table.remove
|
||||
local mRandom = math.random
|
||||
|
||||
-- module code
|
||||
|
||||
function aiBuilding.accumulatePoints(natives)
|
||||
natives.points = natives.points + constants.AI_POINT_GENERATOR_AMOUNT
|
||||
natives.points = natives.points + AI_POINT_GENERATOR_AMOUNT
|
||||
end
|
||||
|
||||
function aiBuilding.removeScout(entity, natives)
|
||||
for i=1, #natives.scouts do
|
||||
local scout = natives.scouts[i]
|
||||
local scouts = natives.scouts
|
||||
for i=1, #scouts do
|
||||
local scout = scouts[i]
|
||||
if (scout == entity) then
|
||||
table.remove(natives.scouts, i)
|
||||
tableRemove(scouts, i)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function aiBuilding.sendScouts(regionMap, surface, natives, chunk, neighbors)
|
||||
if (#natives.scouts < 5) and (mRandom() < 0.05) and (natives.points > constants.AI_SCOUT_COST) then -- TODO scaled with evolution factor
|
||||
local enemy = surface.find_nearest_enemy({position={x = chunk.pX + constants.HALF_CHUNK_SIZE,
|
||||
y = chunk.pY + constants.HALF_CHUNK_SIZE},
|
||||
max_distance = constants.HALF_CHUNK_SIZE})
|
||||
if (enemy ~= nil) and (enemy.type == "unit") then
|
||||
print("making scouts", natives.points)
|
||||
natives.points = natives.points - constants.AI_SCOUT_COST
|
||||
natives.scouts[#natives.scouts+1] = enemy
|
||||
function aiBuilding.sendScouts(regionMap, surface, natives, chunk, neighbors, evolution_factor)
|
||||
if (natives.points > AI_SCOUT_COST) then
|
||||
local scouts = natives.scouts
|
||||
if (#scouts < 5) and (mRandom() < 0.05) then -- TODO scaled with evolution factor
|
||||
local enemy = surface.find_nearest_enemy({ position = {x = chunk.pX + HALF_CHUNK_SIZE,
|
||||
y = chunk.pY + HALF_CHUNK_SIZE },
|
||||
max_distance = HALF_CHUNK_SIZE})
|
||||
|
||||
if (enemy ~= nil) and (enemy.type == "unit") then
|
||||
-- print("making scouts", natives.points)
|
||||
natives.points = natives.points - AI_SCOUT_COST
|
||||
scouts[#scouts+1] = enemy
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function aiBuilding.scouting(regionMap, surface, natives)
|
||||
print("scouting")
|
||||
-- print("scouting")
|
||||
-- enemy.set_command({type=defines.command.attack,
|
||||
-- target=game.players[1].character})
|
||||
|
||||
@@ -44,45 +86,50 @@ function aiBuilding.scouting(regionMap, surface, natives)
|
||||
end
|
||||
|
||||
|
||||
function aiBuilding.formSquads(regionMap, surface, natives, chunk, neighbors)
|
||||
local score = chunk[constants.PLAYER_BASE_PHEROMONE] + chunk[constants.PLAYER_PHEROMONE] + chunk[constants.PLAYER_DEFENSE_PHEROMONE]
|
||||
if (#natives.squads < constants.AI_MAX_SQUAD_COUNT * game.evolution_factor) and (mRandom() < 0.03) and (chunk[constants.ENEMY_BASE_GENERATOR] ~= 0) and (score > 30) and (natives.points > constants.AI_SQUAD_COST) then
|
||||
mapUtils.getNeighborChunks(regionMap,
|
||||
chunk.cX,
|
||||
chunk.cY,
|
||||
squadNeighbors)
|
||||
local squadPath
|
||||
local squadScore = -constants.MAGIC_MAXIMUM_NUMBER
|
||||
local squadDirection
|
||||
for i=1, #squadNeighbors do
|
||||
local neighborChunk = squadNeighbors[i]
|
||||
if (neighborChunk ~= nil) then
|
||||
squadPosition.x = neighborChunk.pX
|
||||
squadPosition.y = neighborChunk.pY
|
||||
|
||||
local attackScore = surface.get_pollution(squadPosition) + neighborChunk[constants.PLAYER_PHEROMONE] + neighborChunk[constants.PLAYER_DEFENSE_PHEROMONE] + neighborChunk[constants.ENEMY_BASE_PHEROMONE] - (neighborChunk[constants.ENEMY_BASE_GENERATOR] * 5) - neighborChunk[constants.DEATH_PHEROMONE]
|
||||
if (squadScore < attackScore) then
|
||||
squadScore = attackScore
|
||||
squadPath = neighborChunk
|
||||
squadDirection = i
|
||||
function aiBuilding.formSquads(regionMap, surface, natives, chunk, neighbors, evolution_factor)
|
||||
if (natives.points > AI_SQUAD_COST) then
|
||||
local score = chunk[PLAYER_BASE_PHEROMONE] + chunk[PLAYER_PHEROMONE] + chunk[PLAYER_DEFENSE_PHEROMONE]
|
||||
if (score > 20) and (chunk[ENEMY_BASE_GENERATOR] ~= 0) and (#natives.squads < AI_MAX_SQUAD_COUNT * evolution_factor) and (mRandom() < 0.03) then
|
||||
local squadNeighbors = getNeighborChunks(regionMap,
|
||||
chunk.cX,
|
||||
chunk.cY)
|
||||
local squadPath
|
||||
local squadScore = -MAGIC_MAXIMUM_NUMBER
|
||||
local squadDirection
|
||||
local squadPosition = {x = 0, y = 0}
|
||||
for i=1, #squadNeighbors do
|
||||
local neighborChunk = squadNeighbors[i]
|
||||
if (neighborChunk ~= nil) then
|
||||
squadPosition.x = neighborChunk.pX
|
||||
squadPosition.y = neighborChunk.pY
|
||||
if (neighborChunk[NORTH_SOUTH_PASSABLE] and neighborChunk[EAST_WEST_PASSABLE]) then
|
||||
local attackScore = surface.get_pollution(squadPosition) + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[PLAYER_DEFENSE_PHEROMONE]
|
||||
local avoidScore = neighborChunk[ENEMY_BASE_PHEROMONE] - (neighborChunk[ENEMY_BASE_GENERATOR] * 5) - neighborChunk[DEATH_PHEROMONE]
|
||||
local score = attackScore - avoidScore
|
||||
if (squadScore < attackScore) then
|
||||
squadScore = attackScore
|
||||
squadPath = neighborChunk
|
||||
squadDirection = i
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (squadPath ~= nil) then
|
||||
squadPosition.x = squadPath.pX
|
||||
squadPosition.y = squadPath.pY
|
||||
if (squadPath ~= nil) then
|
||||
squadPosition.x = squadPath.pX + HALF_CHUNK_SIZE
|
||||
squadPosition.y = squadPath.pY + HALF_CHUNK_SIZE
|
||||
|
||||
local squad = unitGroupUtils.createSquad(squadPosition, surface, natives)
|
||||
local squad = createSquad(squadPosition, surface, natives)
|
||||
|
||||
local foundUnits = surface.set_multi_command({command={type=defines.command.group,
|
||||
group=squad.group,
|
||||
distraction=defines.distraction.by_damage},
|
||||
unit_count=constants.AI_MAX_SQUAD_SIZE * game.evolution_factor,
|
||||
unit_search_distance=(constants.CHUNK_SIZE*2)})
|
||||
if (foundUnits > 0) then
|
||||
print("making squad", natives.points, foundUnits, squadPath.cX, squadPath.cY)
|
||||
natives.points = natives.points - constants.AI_SQUAD_COST
|
||||
local foundUnits = surface.set_multi_command({command = { type = COMMAND_GROUP,
|
||||
group = squad.group,
|
||||
distraction = DISTRACTION_BY_DAMAGE },
|
||||
unit_count = AI_MAX_SQUAD_SIZE * evolution_factor,
|
||||
unit_search_distance = (CHUNK_SIZE*2) })
|
||||
if (foundUnits > 0) then
|
||||
-- print("making squad", natives.points, foundUnits, squadPath.cX, squadPath.cY)
|
||||
natives.points = natives.points - AI_SQUAD_COST
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@@ -1,25 +1,53 @@
|
||||
local aiDefense = {}
|
||||
|
||||
local factorio_defined = defines
|
||||
-- imports
|
||||
|
||||
local constants = require("Constants")
|
||||
local mapUtils = require("MapUtils")
|
||||
local utils = require("Utils")
|
||||
local unitGroupUtils = require("UnitGroupUtils")
|
||||
|
||||
local retreatFilter = {[constants.SQUAD_RETREATING] = true}
|
||||
local retreatNeighbors = {1,2,3,4,5,6,7,8} -- used to minimize garbage generation
|
||||
local retreatPosition = {x=0, y=0} -- used to minimize garbage generation
|
||||
-- constants
|
||||
|
||||
local DISTRACTION_NONE = defines.distraction.none
|
||||
|
||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||
local ENEMY_BASE_PHEROMONE = constants.ENEMY_BASE_PHEROMONE
|
||||
local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE
|
||||
|
||||
local DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
|
||||
local RETREAT_DEATH_PHEROMONE_LEVEL = constants.RETREAT_DEATH_PHEROMONE_LEVEL
|
||||
|
||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||
|
||||
local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE
|
||||
|
||||
local SQUAD_RETREATING = constants.SQUAD_RETREATING
|
||||
local SQUAD_SUICIDE_HUNT = constants.SQUAD_SUICIDE_HUNT
|
||||
local SQUAD_SUICIDE_RAID = constants.SQUAD_SUICIDE_RAID
|
||||
|
||||
local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
|
||||
|
||||
-- imported functions
|
||||
|
||||
local getChunkByPosition = mapUtils.getChunkByPosition
|
||||
local getCardinalChunks = mapUtils.getCardinalChunks
|
||||
local positionDirectionToChunkCornerCardinal = mapUtils.positionDirectionToChunkCornerCardinal
|
||||
local getChunkByIndex = mapUtils.getChunkByIndex
|
||||
local findNearBySquad = unitGroupUtils.findNearBySquad
|
||||
local createSquad = unitGroupUtils.createSquad
|
||||
local membersToSquad = unitGroupUtils.membersToSquad
|
||||
|
||||
-- premade tables
|
||||
|
||||
local retreatFilter = {[SQUAD_RETREATING] = true}
|
||||
|
||||
-- module code
|
||||
|
||||
function aiDefense.retreatUnits(position, squad, regionMap, surface, natives)
|
||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
||||
|
||||
local chunk = mapUtils.getChunkByPosition(regionMap, position.x, position.y)
|
||||
if (chunk ~= nil) and (chunk[DEATH_PHEROMONE] > (game.evolution_factor * constants.RETREAT_LEVEL_DEATH_PHEROMONE)) then -- TODO sliding scale of death based on evolution
|
||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||
local ENEMY_BASE_PHEROMONE = constants.ENEMY_BASE_PHEROMONE
|
||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||
local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE
|
||||
|
||||
local chunk = getChunkByPosition(regionMap, position.x, position.y)
|
||||
if (chunk ~= nil) and (chunk[DEATH_PHEROMONE] > (game.evolution_factor * RETREAT_DEATH_PHEROMONE_LEVEL)) then -- TODO sliding scale of death based on evolution
|
||||
local performRetreat = false
|
||||
local enemiesToSquad
|
||||
|
||||
@@ -28,60 +56,63 @@ function aiDefense.retreatUnits(position, squad, regionMap, surface, natives)
|
||||
if (#enemiesToSquad > 0) then
|
||||
performRetreat = true
|
||||
end
|
||||
elseif squad.group.valid and (squad.status ~= constants.SQUAD_RETREATING) and (squad.status ~= constants.SQUAD_SUICIDE_HUNT) and (squad.status ~= constants.SQUAD_SUICIDE_RAID) then
|
||||
elseif squad.group.valid and (squad.status ~= SQUAD_RETREATING) and (squad.status ~= SQUAD_SUICIDE_HUNT) and (squad.status ~= SQUAD_SUICIDE_RAID) then
|
||||
if (#squad.group.members ~= 0) then
|
||||
performRetreat = true
|
||||
end
|
||||
end
|
||||
|
||||
if performRetreat then
|
||||
mapUtils.getNeighborChunks(regionMap,
|
||||
chunk.cX,
|
||||
chunk.cY,
|
||||
retreatNeighbors)
|
||||
local retreatNeighbors = getCardinalChunks(regionMap,
|
||||
chunk.cX,
|
||||
chunk.cY)
|
||||
local exitPath
|
||||
local exitScore = constants.MAGIC_MAXIMUM_NUMBER
|
||||
local exitScore = -MAGIC_MAXIMUM_NUMBER
|
||||
local exitDirection
|
||||
local retreatPosition = {x=0, y=0}
|
||||
for i=1, #retreatNeighbors do
|
||||
local neighborChunk = retreatNeighbors[i]
|
||||
if (neighborChunk ~= nil) then
|
||||
retreatPosition.x = neighborChunk.pX
|
||||
retreatPosition.y = neighborChunk.pY
|
||||
|
||||
local dangerScore = neighborChunk[DEATH_PHEROMONE] + surface.get_pollution(retreatPosition) + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[PLAYER_DEFENSE_PHEROMONE] - neighborChunk[ENEMY_BASE_PHEROMONE] + (neighborChunk[ENEMY_BASE_GENERATOR] * 5)
|
||||
if (dangerScore < exitScore) then
|
||||
exitScore = dangerScore
|
||||
local dangerScore = neighborChunk[DEATH_PHEROMONE] + surface.get_pollution(retreatPosition) + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[PLAYER_DEFENSE_PHEROMONE] + (neighborChunk[ENEMY_BASE_GENERATOR] * 5)
|
||||
local avoidScore = neighborChunk[ENEMY_BASE_PHEROMONE]
|
||||
local score = avoidScore - dangerScore
|
||||
if (exitScore < score) then
|
||||
exitScore = score
|
||||
exitPath = neighborChunk
|
||||
exitDirection = i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
utils.positionDirectionToChunkCorner(exitDirection, exitPath, retreatPosition)
|
||||
retreatPosition = positionDirectionToChunkCornerCardinal(exitDirection, exitPath)
|
||||
-- in order for units in a group attacking to retreat, we have to create a new group and give the command to join
|
||||
-- to each unit
|
||||
-- retreatPosition.x = exitPath.pX + constants.HALF_CHUNK_SIZE
|
||||
-- retreatPosition.y = exitPath.pY + constants.HALF_CHUNK_SIZE
|
||||
|
||||
if (squad ~= nil) and (squad.cX ~= nil) then
|
||||
local chunk = mapUtils.getChunkByIndex(regionMap, squad.cX, squad.cY)
|
||||
chunk[constants.DEATH_PHEROMONE] = chunk[constants.DEATH_PHEROMONE] + constants.DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
local chunk = getChunkByIndex(regionMap, squad.cX, squad.cY)
|
||||
chunk[DEATH_PHEROMONE] = chunk[DEATH_PHEROMONE] + DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
end
|
||||
|
||||
local newSquad = unitGroupUtils.findNearBySquad(natives,
|
||||
retreatPosition,
|
||||
constants.HALF_CHUNK_SIZE,
|
||||
retreatFilter)
|
||||
local newSquad = findNearBySquad(natives,
|
||||
retreatPosition,
|
||||
HALF_CHUNK_SIZE,
|
||||
retreatFilter)
|
||||
|
||||
if (newSquad == nil) then
|
||||
newSquad = unitGroupUtils.createSquad(retreatPosition, surface, natives)
|
||||
newSquad.status = constants.SQUAD_RETREATING
|
||||
newSquad = createSquad(retreatPosition, surface, natives)
|
||||
newSquad.status = SQUAD_RETREATING
|
||||
newSquad.cycles = 4
|
||||
end
|
||||
if (enemiesToSquad ~= nil) then
|
||||
unitGroupUtils.membersToSquad(newSquad, enemiesToSquad, false, factorio_defined.distraction.none)
|
||||
membersToSquad(newSquad, enemiesToSquad, false, DISTRACTION_NONE)
|
||||
else
|
||||
unitGroupUtils.membersToSquad(newSquad, squad.group.members, true, factorio_defined.distraction.none)
|
||||
-- newSquad.penalties = squad.penalties
|
||||
membersToSquad(newSquad, squad.group.members, true, DISTRACTION_NONE)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@@ -1,14 +1,33 @@
|
||||
local chunkProcessor = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local chunkUtils = require("ChunkUtils")
|
||||
local constants = require("Constants")
|
||||
|
||||
-- constants
|
||||
|
||||
local CHUNK_MAX_QUEUE_SIZE = constants.CHUNK_MAX_QUEUE_SIZE
|
||||
|
||||
-- imported functions
|
||||
|
||||
local createChunk = chunkUtils.createChunk
|
||||
|
||||
-- premade tables
|
||||
|
||||
local processors = {}
|
||||
|
||||
-- module code
|
||||
|
||||
function chunkProcessor.processPendingChunks(regionMap, surface, natives, pendingStack)
|
||||
local createChunk = chunkUtils.createChunk
|
||||
local processAll = false
|
||||
|
||||
if (#pendingStack > 100) then
|
||||
processAll = true
|
||||
end
|
||||
|
||||
local count = 0
|
||||
while (#pendingStack > 0) do
|
||||
for i=#pendingStack, 1, -1 do
|
||||
local event = pendingStack[#pendingStack]
|
||||
pendingStack[#pendingStack] = nil
|
||||
|
||||
@@ -26,9 +45,18 @@ function chunkProcessor.processPendingChunks(regionMap, surface, natives, pendin
|
||||
processors[i](chunk, surface, natives)
|
||||
end
|
||||
|
||||
local processQueue = regionMap.pQ[regionMap.pI]
|
||||
if (#processQueue == CHUNK_MAX_QUEUE_SIZE) then
|
||||
regionMap.pI = regionMap.pI + 1
|
||||
regionMap.pQ[regionMap.pI] = {}
|
||||
processQueue = regionMap.pQ[regionMap.pI]
|
||||
end
|
||||
|
||||
processQueue[#processQueue+1] = chunk
|
||||
|
||||
count = count + 1
|
||||
if (count % 5 == 0) and (#pendingStack < 20) then
|
||||
coroutine.yield()
|
||||
if (count == 5) and not processAll then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@@ -4,7 +4,9 @@ local constants = {}
|
||||
|
||||
constants.MAGIC_MAXIMUM_NUMBER = 1e99 -- used in loops trying to find the lowest score
|
||||
-- constants.MAX_PHEROMONE = 20000
|
||||
constants.RETREAT_LEVEL_DEATH_PHEROMONE = 15000
|
||||
constants.RETREAT_DEATH_PHEROMONE_LEVEL = 12000
|
||||
|
||||
constants.CHUNK_MAX_QUEUE_SIZE = 1000
|
||||
|
||||
-- ai
|
||||
|
||||
@@ -14,7 +16,7 @@ constants.AI_SQUAD_COST = 150
|
||||
constants.AI_SETTLER_COST = 75
|
||||
constants.AI_BASE_BUILDING_COST = 500
|
||||
|
||||
constants.AI_MAX_SQUAD_SIZE = 150
|
||||
constants.AI_MAX_SQUAD_SIZE = 120
|
||||
constants.AI_MAX_SQUAD_COUNT = 30
|
||||
|
||||
-- chunk properties
|
||||
@@ -27,10 +29,11 @@ constants.EAST_WEST = 2
|
||||
|
||||
-- pheromone amounts
|
||||
|
||||
constants.MOVEMENT_PENALTY_PHEROMONE_GENERATOR_AMOUNT = 500
|
||||
constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = 500
|
||||
constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = 35
|
||||
constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 35
|
||||
constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT = 75
|
||||
constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT = 300
|
||||
|
||||
-- pheromone diffusion amounts
|
||||
|
||||
@@ -68,33 +71,33 @@ constants.SQUAD_SUICIDE_RAID = 9 -- when player stuff is close with no retreat
|
||||
|
||||
-- player building pheromones
|
||||
|
||||
constants.buildingPheromones = {}
|
||||
constants.BUILDING_PHEROMONES = {}
|
||||
-- constants.buildingPheromones["container"] = 1
|
||||
-- constants.buildingPheromones["storage-tank"] = 1
|
||||
constants.buildingPheromones["generator"] = 30
|
||||
constants.buildingPheromones["pump"] = 4
|
||||
constants.buildingPheromones["offshore-pump"] = 4
|
||||
constants.BUILDING_PHEROMONES["generator"] = 60
|
||||
constants.BUILDING_PHEROMONES["pump"] = 8
|
||||
constants.BUILDING_PHEROMONES["offshore-pump"] = 8
|
||||
-- constants.buildingPheromones["constant-combinator"] = 1
|
||||
-- constants.buildingPheromones["train-stop"] = 2
|
||||
-- constants.buildingPheromones["rail-signal"] = 1
|
||||
constants.buildingPheromones["electric-pole"] = 2
|
||||
constants.buildingPheromones["transport-belt"] = 2
|
||||
constants.buildingPheromones["accumulator"] = 20
|
||||
constants.buildingPheromones["solar-panel"] = 16
|
||||
constants.buildingPheromones["boiler"] = 30
|
||||
constants.buildingPheromones["assembling-machine"] = 24
|
||||
constants.buildingPheromones["roboport"] = 20
|
||||
constants.buildingPheromones["beacon"] = 20
|
||||
constants.buildingPheromones["furnace"] = 30
|
||||
constants.buildingPheromones["mining-drill"] = 40
|
||||
constants.BUILDING_PHEROMONES["electric-pole"] = 4
|
||||
constants.BUILDING_PHEROMONES["transport-belt"] = 4
|
||||
constants.BUILDING_PHEROMONES["accumulator"] = 40
|
||||
constants.BUILDING_PHEROMONES["solar-panel"] = 32
|
||||
constants.BUILDING_PHEROMONES["boiler"] = 60
|
||||
constants.BUILDING_PHEROMONES["assembling-machine"] = 48
|
||||
constants.BUILDING_PHEROMONES["roboport"] = 40
|
||||
constants.BUILDING_PHEROMONES["beacon"] = 40
|
||||
constants.BUILDING_PHEROMONES["furnace"] = 60
|
||||
constants.BUILDING_PHEROMONES["mining-drill"] = 80
|
||||
|
||||
-- player defense pheromones
|
||||
|
||||
constants.defensePheromones = {}
|
||||
constants.defensePheromones["ammo-turret"] = 5
|
||||
constants.defensePheromones["electric-turret"] = 7.5
|
||||
constants.defensePheromones["fluid-turret"] = 10
|
||||
constants.defensePheromones["turret"] = 3
|
||||
constants.DEFENSE_PHEROMONES = {}
|
||||
constants.DEFENSE_PHEROMONES["ammo-turret"] = 5
|
||||
constants.DEFENSE_PHEROMONES["electric-turret"] = 7.5
|
||||
constants.DEFENSE_PHEROMONES["fluid-turret"] = 10
|
||||
constants.DEFENSE_PHEROMONES["turret"] = 3
|
||||
|
||||
-- enemy units
|
||||
|
||||
|
@@ -1,42 +1,47 @@
|
||||
local mapProcessor = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local mapUtils = require("MapUtils")
|
||||
|
||||
-- imported functions
|
||||
|
||||
local getCardinalChunks = mapUtils.getCardinalChunks
|
||||
|
||||
local mRandom = math.random
|
||||
local neighborsArray = {1,2,3,4,5,6,7,8}
|
||||
local cardinalArray = {1,2,3,4}
|
||||
|
||||
-- premade tables
|
||||
|
||||
local processors = {}
|
||||
local processorsProbabilityLow = {}
|
||||
local processorsProbabilityHigh = {}
|
||||
|
||||
function mapProcessor.processMap(regionMap, surface, natives)
|
||||
local getNeighborChunks = mapUtils.getCardinalChunks
|
||||
local mathRandom = mRandom
|
||||
-- module code
|
||||
|
||||
local neighbors = cardinalArray
|
||||
function mapProcessor.processMap(regionMap, surface, natives, evolution_factor)
|
||||
local count = 0
|
||||
|
||||
local roll = mathRandom()
|
||||
print("--")
|
||||
print(roll)
|
||||
print("--")
|
||||
for _,ys in pairs(regionMap) do
|
||||
for _,chunk in pairs(ys) do
|
||||
if (regionMap.pP == 1) then
|
||||
regionMap.pR = mRandom()
|
||||
end
|
||||
|
||||
getNeighborChunks(regionMap, chunk.cX, chunk.cY, neighbors)
|
||||
-- validNeighbors flag if the processor retrieved the neighbors of the chunk then true
|
||||
for i=1, #processors do
|
||||
if (processorsProbabilityLow[i] <= roll) and (roll <= processorsProbabilityHigh[i]) then
|
||||
validNeighbors = processors[i](regionMap, surface, natives, chunk, neighbors)
|
||||
end
|
||||
end
|
||||
local roll = regionMap.pR
|
||||
|
||||
count = count + 1
|
||||
if (count % 1000 == 0) then
|
||||
coroutine.yield()
|
||||
local chunkQueue = regionMap.pQ[regionMap.pP]
|
||||
for x=1, #chunkQueue do
|
||||
local chunk = chunkQueue[x]
|
||||
local cardinalArray = getCardinalChunks(regionMap, chunk.cX, chunk.cY)
|
||||
for i=1, #processors do
|
||||
if (processorsProbabilityLow[i] <= roll) and (roll <= processorsProbabilityHigh[i]) then
|
||||
processors[i](regionMap, surface, natives, chunk, cardinalArray, evolution_factor)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
regionMap.pP = regionMap.pP + 1
|
||||
if (regionMap.pP > regionMap.pI) then
|
||||
regionMap.pP = 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@@ -1,9 +1,31 @@
|
||||
local mapUtils = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local constants = require("Constants")
|
||||
|
||||
-- constants
|
||||
|
||||
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
|
||||
local DEFENSE_PHEROMONES = constants.DEFENSE_PHEROMONES
|
||||
|
||||
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 ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
||||
|
||||
local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE
|
||||
local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE
|
||||
|
||||
local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE
|
||||
local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||
|
||||
-- imported functions
|
||||
|
||||
local mFloor = math.floor
|
||||
local mAbs = math.abs
|
||||
|
||||
-- module code
|
||||
|
||||
function mapUtils.getChunkByPosition(regionMap, x, y)
|
||||
local cX = mFloor(x * 0.03125)
|
||||
@@ -27,9 +49,6 @@ function mapUtils.positionToChunkOffset(position)
|
||||
end
|
||||
|
||||
function mapUtils.getEntityOverlapChunks(regionMap, entity)
|
||||
local mathFloor = mFloor
|
||||
local mathAbs = mAbs
|
||||
|
||||
local boundingBox = entity.prototype.selection_box;
|
||||
|
||||
local leftTopChunk
|
||||
@@ -57,16 +76,16 @@ function mapUtils.getEntityOverlapChunks(regionMap, entity)
|
||||
bottomYOffset = boundingBox.right_bottom.y
|
||||
end
|
||||
|
||||
local leftTopChunkX = mathFloor((center.x + topXOffset) * 0.03125)
|
||||
local leftTopChunkY = mathFloor((center.y + topYOffset) * 0.03125)
|
||||
local leftTopChunkX = mFloor((center.x + topXOffset) * 0.03125)
|
||||
local leftTopChunkY = mFloor((center.y + topYOffset) * 0.03125)
|
||||
|
||||
-- used to force things on chunk boundary to not spill over 0.0001
|
||||
local rightTopChunkX = mathFloor((center.x + bottomXOffset - 0.0001) * 0.03125)
|
||||
local rightTopChunkX = mFloor((center.x + bottomXOffset - 0.0001) * 0.03125)
|
||||
local rightTopChunkY = leftTopChunkY
|
||||
|
||||
-- used to force things on chunk boundary to not spill over 0.0001
|
||||
local leftBottomChunkX = leftTopChunkX
|
||||
local leftBottomChunkY = mathFloor((center.y + bottomYOffset - 0.0001) * 0.03125)
|
||||
local leftBottomChunkY = mFloor((center.y + bottomYOffset - 0.0001) * 0.03125)
|
||||
|
||||
local rightBottomChunkX = rightTopChunkX
|
||||
local rightBottomChunkY = leftBottomChunkY
|
||||
@@ -89,21 +108,21 @@ function mapUtils.addRemoveObject(regionMap, entity, natives, addObject)
|
||||
local leftTop, rightTop, leftBottom, rightBottom
|
||||
local entityValue
|
||||
local pheromoneType
|
||||
if (constants.buildingPheromones[entity.type] ~= nil) then
|
||||
entityValue = constants.buildingPheromones[entity.type]
|
||||
pheromoneType = constants.PLAYER_BASE_GENERATOR
|
||||
elseif (constants.defensePheromones[entity.type] ~= nil) then
|
||||
entityValue = constants.defensePheromones[entity.type]
|
||||
pheromoneType = constants.PLAYER_DEFENSE_GENERATOR
|
||||
if (BUILDING_PHEROMONES[entity.type] ~= nil) then
|
||||
entityValue = BUILDING_PHEROMONES[entity.type]
|
||||
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
|
||||
entityValue = constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
||||
pheromoneType = constants.ENEMY_BASE_GENERATOR
|
||||
entityValue = ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
||||
pheromoneType = ENEMY_BASE_GENERATOR
|
||||
end
|
||||
if (entityValue ~= nil) then
|
||||
leftTop, rightTop, leftBottom, rightBottom = mapUtils.getEntityOverlapChunks(regionMap, entity)
|
||||
if not addObject then
|
||||
entityValue = -entityValue
|
||||
elseif (pheromoneType ~= constants.ENEMY_BASE_GENERATOR) then
|
||||
elseif (pheromoneType ~= ENEMY_BASE_GENERATOR) then
|
||||
natives.points = natives.points + entityValue
|
||||
end
|
||||
if (leftTop ~= nil) then
|
||||
@@ -128,12 +147,17 @@ end
|
||||
/|\
|
||||
6 7 8
|
||||
]]--
|
||||
function mapUtils.getNeighborChunks(regionMap, chunkX, chunkY, neighbors)
|
||||
function mapUtils.getNeighborChunks(regionMap, chunkX, chunkY)
|
||||
local neighbors = {1,2,3,4,5,6,7,8}
|
||||
local xChunks = regionMap[chunkX-1]
|
||||
if (xChunks ~= nil) then
|
||||
neighbors[1] = xChunks[chunkY-1]
|
||||
neighbors[4] = xChunks[chunkY]
|
||||
neighbors[6] = xChunks[chunkY+1]
|
||||
else
|
||||
neighbors[1] = nil
|
||||
neighbors[4] = nil
|
||||
neighbors[6] = nil
|
||||
end
|
||||
|
||||
xChunks = regionMap[chunkX+1]
|
||||
@@ -141,13 +165,21 @@ function mapUtils.getNeighborChunks(regionMap, chunkX, chunkY, neighbors)
|
||||
neighbors[3] = xChunks[chunkY-1]
|
||||
neighbors[5] = xChunks[chunkY]
|
||||
neighbors[8] = xChunks[chunkY+1]
|
||||
else
|
||||
neighbors[3] = nil
|
||||
neighbors[5] = nil
|
||||
neighbors[8] = nil
|
||||
end
|
||||
|
||||
xChunks = regionMap[chunkX]
|
||||
if (xChunks ~= nil) then
|
||||
neighbors[2] = xChunks[chunkY-1]
|
||||
neighbors[7] = xChunks[chunkY+1]
|
||||
else
|
||||
neighbors[2] = nil
|
||||
neighbors[7] = nil
|
||||
end
|
||||
return neighbors
|
||||
end
|
||||
|
||||
--[[
|
||||
@@ -157,24 +189,109 @@ end
|
||||
|
|
||||
4
|
||||
]]--
|
||||
function mapUtils.getCardinalChunks(regionMap, chunkX, chunkY, neighbors)
|
||||
function mapUtils.getCardinalChunks(regionMap, chunkX, chunkY)
|
||||
local neighbors = {1,2,3,4}
|
||||
local xChunks = regionMap[chunkX]
|
||||
if (xChunks ~= nil) then
|
||||
neighbors[1] = xChunks[chunkY-1]
|
||||
neighbors[4] = xChunks[chunkY+1]
|
||||
else
|
||||
neighbors[1] = nil
|
||||
neighbors[4] = nil
|
||||
end
|
||||
|
||||
xChunks = regionMap[chunkX-1]
|
||||
if (xChunks ~= nil) then
|
||||
neighbors[2] = xChunks[chunkY]
|
||||
else
|
||||
neighbors[2] = nil
|
||||
end
|
||||
|
||||
xChunks = regionMap[chunkX+1]
|
||||
if (xChunks ~= nil) then
|
||||
neighbors[3] = xChunks[chunkY]
|
||||
else
|
||||
neighbors[3] = nil
|
||||
end
|
||||
|
||||
return neighbors
|
||||
end
|
||||
|
||||
function mapUtils.euclideanDistanceNamed(p1, p2)
|
||||
local xs = p1.x - p2.x
|
||||
local ys = p1.y - p2.y
|
||||
return ((xs * xs) + (ys * ys)) ^ 0.5
|
||||
end
|
||||
|
||||
function mapUtils.euclideanDistanceArray(p1, p2)
|
||||
local xs = p1[1] - p2[1]
|
||||
local ys = p1[2] - p2[2]
|
||||
return ((xs * xs) + (ys * ys)) ^ 0.5
|
||||
end
|
||||
|
||||
--[[
|
||||
1
|
||||
|
|
||||
2- -3
|
||||
|
|
||||
4
|
||||
]]--
|
||||
function mapUtils.canMoveChunkDirectionCardinal(direction, startChunk, endChunk)
|
||||
local canMove = false
|
||||
if ((direction == 1) or (direction == 4)) and startChunk[NORTH_SOUTH_PASSABLE] and endChunk[NORTH_SOUTH_PASSABLE] then
|
||||
canMove = true
|
||||
elseif ((direction == 2) or (direction == 3)) and startChunk[EAST_WEST_PASSABLE] and endChunk[EAST_WEST_PASSABLE] then
|
||||
canMove = true
|
||||
end
|
||||
return canMove
|
||||
end
|
||||
|
||||
function mapUtils.positionDirectionToChunkCornerCardinal(direction, chunk)
|
||||
local position = {x=0,y=0}
|
||||
if (direction == 1) then
|
||||
position.x = chunk.pX + HALF_CHUNK_SIZE
|
||||
position.y = chunk.pY
|
||||
elseif (direction == 2) then
|
||||
position.x = chunk.pX
|
||||
position.y = chunk.pY + HALF_CHUNK_SIZE
|
||||
elseif (direction == 3) then
|
||||
position.x = chunk.pX + CHUNK_SIZE
|
||||
position.y = chunk.pY + HALF_CHUNK_SIZE
|
||||
elseif (direction == 4) then
|
||||
position.x = chunk.pX + HALF_CHUNK_SIZE
|
||||
position.y = chunk.pY + CHUNK_SIZE
|
||||
end
|
||||
return position
|
||||
end
|
||||
|
||||
function mapUtils.positionDirectionToChunkCorner(direction, chunk)
|
||||
local position = {x=0, y=0}
|
||||
if (direction == 1) then
|
||||
position.x = chunk.pX
|
||||
position.y = chunk.pY
|
||||
elseif (direction == 2) then
|
||||
position.x = chunk.pX + HALF_CHUNK_SIZE
|
||||
position.y = chunk.pY
|
||||
elseif (direction == 3) then
|
||||
position.x = chunk.pX + CHUNK_SIZE
|
||||
position.y = chunk.pY
|
||||
elseif (direction == 4) then
|
||||
position.x = chunk.pX
|
||||
position.y = chunk.pY + HALF_CHUNK_SIZE
|
||||
elseif (direction == 5) then
|
||||
position.x = chunk.pX + CHUNK_SIZE
|
||||
position.y = chunk.pY + HALF_CHUNK_SIZE
|
||||
elseif (direction == 6) then
|
||||
position.x = chunk.pX
|
||||
position.y = chunk.pY + CHUNK_SIZE
|
||||
elseif (direction == 7) then
|
||||
position.x = chunk.pX + HALF_CHUNK_SIZE
|
||||
position.y = chunk.pY + CHUNK_SIZE
|
||||
elseif (direction == 8) then
|
||||
position.x = chunk.pX + CHUNK_SIZE
|
||||
position.y = chunk.pY + CHUNK_SIZE
|
||||
end
|
||||
return position
|
||||
end
|
||||
|
||||
return mapUtils
|
@@ -1,60 +1,74 @@
|
||||
local pheromoneUtils = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local mapUtils = require("MapUtils")
|
||||
local constants = require("Constants")
|
||||
local mMin = math.min
|
||||
|
||||
-- constants
|
||||
|
||||
local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||
|
||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
||||
local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_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_DEFENSE_GENERATOR = constants.PLAYER_DEFENSE_GENERATOR
|
||||
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||
|
||||
local PLAYER_PHEROMONE_GENERATOR_AMOUNT = constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT
|
||||
|
||||
local STANDARD_PHERONOME_DIFFUSION_AMOUNT = constants.STANDARD_PHERONOME_DIFFUSION_AMOUNT
|
||||
local DEATH_PHEROMONE_DIFFUSION_AMOUNT = constants.DEATH_PHEROMONE_DIFFUSION_AMOUNT
|
||||
|
||||
-- imported functions
|
||||
|
||||
local getChunkByPosition = mapUtils.getChunkByPosition
|
||||
|
||||
local mFloor = math.floor
|
||||
|
||||
local nearestEnemyPosition = {x=1,y=2}
|
||||
local nearestTable = {position=nearestEnemyPosition,
|
||||
max_distance=constants.CHUNK_SIZE,
|
||||
force="enemy"}
|
||||
-- module code
|
||||
|
||||
function pheromoneUtils.deathScent(regionMap, surface, x, y, amount)
|
||||
function pheromoneUtils.deathScent(regionMap, surface, x, y, squad, amount)
|
||||
|
||||
nearestEnemyPosition.x = x
|
||||
nearestEnemyPosition.y = y
|
||||
local playerKiller = surface.find_nearest_enemy(nearestTable)
|
||||
if (playerKiller ~= nil) then
|
||||
local chunk = mapUtils.getChunkByPosition(regionMap, x, y)
|
||||
if (squad ~= nil) and (squad.cX ~= nil) then
|
||||
local chunk = getChunkByPosition(regionMap, x, y)
|
||||
if (chunk ~= nil) then
|
||||
chunk[constants.DEATH_PHEROMONE] = chunk[constants.DEATH_PHEROMONE] + amount
|
||||
chunk[DEATH_PHEROMONE] = chunk[DEATH_PHEROMONE] + (amount * 5)
|
||||
end
|
||||
end
|
||||
|
||||
local chunk = mapUtils.getChunkByPosition(regionMap, x, y)
|
||||
local chunk = getChunkByPosition(regionMap, x, y)
|
||||
if (chunk ~= nil) then
|
||||
chunk[constants.DEATH_PHEROMONE] = chunk[constants.DEATH_PHEROMONE] + amount
|
||||
chunk[DEATH_PHEROMONE] = chunk[DEATH_PHEROMONE] + amount
|
||||
end
|
||||
end
|
||||
|
||||
function pheromoneUtils.playerDefenseScent(regionMap, surface, natives, chunk, neighbors)
|
||||
local baseScore = chunk[constants.PLAYER_DEFENSE_GENERATOR]
|
||||
function pheromoneUtils.playerDefenseScent(regionMap, surface, natives, chunk, neighbors, evolution_factor)
|
||||
local baseScore = chunk[PLAYER_DEFENSE_GENERATOR]
|
||||
if (baseScore > 0) then
|
||||
chunk[constants.PLAYER_DEFENSE_PHEROMONE] = chunk[constants.PLAYER_DEFENSE_PHEROMONE] + baseScore
|
||||
chunk[PLAYER_DEFENSE_PHEROMONE] = chunk[PLAYER_DEFENSE_PHEROMONE] + baseScore
|
||||
end
|
||||
end
|
||||
|
||||
function pheromoneUtils.playerBaseScent(regionMap, surface, natives, chunk, neighbors)
|
||||
local baseScore = chunk[constants.PLAYER_BASE_GENERATOR]
|
||||
function pheromoneUtils.playerBaseScent(regionMap, surface, natives, chunk, neighbors, evolution_factor)
|
||||
local baseScore = chunk[PLAYER_BASE_GENERATOR]
|
||||
if (baseScore > 0) then
|
||||
chunk[constants.PLAYER_BASE_PHEROMONE] = chunk[constants.PLAYER_BASE_PHEROMONE] + (baseScore * 2)
|
||||
chunk[PLAYER_BASE_PHEROMONE] = chunk[PLAYER_BASE_PHEROMONE] + baseScore
|
||||
end
|
||||
end
|
||||
|
||||
function pheromoneUtils.enemyBaseScent(regionMap, surface, natives, chunk, neighbors)
|
||||
local spawners = chunk[constants.ENEMY_BASE_GENERATOR]
|
||||
function pheromoneUtils.enemyBaseScent(regionMap, surface, natives, chunk, neighbors, evolution_factor)
|
||||
local spawners = chunk[ENEMY_BASE_GENERATOR]
|
||||
if (spawners > 0) then
|
||||
chunk[constants.ENEMY_BASE_PHEROMONE] = chunk[constants.ENEMY_BASE_PHEROMONE] + spawners
|
||||
chunk[ENEMY_BASE_PHEROMONE] = chunk[ENEMY_BASE_PHEROMONE] + spawners
|
||||
end
|
||||
end
|
||||
|
||||
function pheromoneUtils.playerScent(regionMap, players)
|
||||
local PLAYER_PHEROMONE_GENERATOR_AMOUNT = constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT
|
||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||
local getChunkByPosition = mapUtils.getChunkByPosition
|
||||
local mathFloor = mFloor
|
||||
|
||||
for i=1, #players do
|
||||
local playerPosition = players[i].position
|
||||
local playerChunk = getChunkByPosition(regionMap, playerPosition.x, playerPosition.y)
|
||||
@@ -64,13 +78,8 @@ function pheromoneUtils.playerScent(regionMap, players)
|
||||
end
|
||||
end
|
||||
|
||||
function pheromoneUtils.processPheromone(regionMap, surface, natives, chunk, neighbors)
|
||||
local STANDARD_PHERONOME_DIFFUSION_AMOUNT = constants.STANDARD_PHERONOME_DIFFUSION_AMOUNT
|
||||
local DEATH_PHEROMONE_DIFFUSION_AMOUNT = constants.DEATH_PHEROMONE_DIFFUSION_AMOUNT
|
||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
||||
-- local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
||||
|
||||
for x=1,5 do
|
||||
function pheromoneUtils.processPheromone(regionMap, surface, natives, chunk, neighbors, evolution_factor)
|
||||
for x=1,6 do
|
||||
local diffusionAmount
|
||||
local persistence
|
||||
if (x == DEATH_PHEROMONE) then
|
||||
|
@@ -1,21 +1,37 @@
|
||||
local unitGroupUtils = {}
|
||||
|
||||
local utils = require("Utils")
|
||||
-- imports
|
||||
|
||||
local mapUtils = require("MapUtils")
|
||||
local constants = require("Constants")
|
||||
|
||||
local groupingCommand = {type=defines.command.group,
|
||||
group=1,
|
||||
distraction=0}
|
||||
-- constants
|
||||
|
||||
local MOVEMENT_PENALTY_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PENALTY_PHEROMONE_GENERATOR_AMOUNT
|
||||
|
||||
local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE
|
||||
|
||||
local GROUP_STATE_FINISHED = defines.group_state.finished
|
||||
|
||||
local SQUAD_RETREATING = constants.SQUAD_RETREATING
|
||||
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
||||
|
||||
-- imported functions
|
||||
|
||||
local tableRemove = table.remove
|
||||
local tableInsert = table.insert
|
||||
local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed
|
||||
|
||||
-- module code
|
||||
|
||||
function unitGroupUtils.findNearBySquad(natives, position, distance, filter)
|
||||
local getDistance = utils.euclideanDistanceNamed
|
||||
local squads = natives.squads
|
||||
local i = 1
|
||||
while (i <= #squads) do
|
||||
local squad = squads[i]
|
||||
local unitGroup = squad.group
|
||||
if (unitGroup ~= nil) and unitGroup.valid and ((filter == nil) or (filter ~= nil and filter[squad.status])) then
|
||||
if (getDistance(unitGroup.position, position) <= distance) then
|
||||
if (euclideanDistanceNamed(unitGroup.position, position) <= distance) then
|
||||
return squad
|
||||
end
|
||||
end
|
||||
@@ -27,7 +43,8 @@ function unitGroupUtils.createSquad(position, surface, natives)
|
||||
local unitGroup = surface.create_unit_group({position=position})
|
||||
|
||||
local squad = { group = unitGroup,
|
||||
status = constants.SQUAD_GUARDING,
|
||||
status = SQUAD_GUARDING,
|
||||
penalties = {},
|
||||
cycles = 0 }
|
||||
natives.squads[#natives.squads+1] = squad
|
||||
return squad
|
||||
@@ -39,9 +56,9 @@ function unitGroupUtils.membersToSquad(squad, members, overwriteGroup, distracti
|
||||
for i=1,#members do
|
||||
local member = members[i]
|
||||
if (member ~= nil) and member.valid and (overwriteGroup or (not overwriteGroup and (member.unit_group == nil))) then
|
||||
groupingCommand.group = group
|
||||
groupingCommand.distraction = distraction
|
||||
member.set_command(groupingCommand)
|
||||
member.set_command({ type = defines.command.group,
|
||||
group = group,
|
||||
distraction = distraction })
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -63,7 +80,8 @@ function unitGroupUtils.convertUnitGroupToSquad(natives, unitGroup)
|
||||
end
|
||||
if addUnitGroup then
|
||||
returnSquad = { group = unitGroup,
|
||||
status = constants.SQUAD_GUARDING,
|
||||
status = SQUAD_GUARDING,
|
||||
penalties = {},
|
||||
cycles = 0 }
|
||||
squads[#squads+1] = returnSquad
|
||||
end
|
||||
@@ -72,21 +90,35 @@ function unitGroupUtils.convertUnitGroupToSquad(natives, unitGroup)
|
||||
return returnSquad
|
||||
end
|
||||
|
||||
-- function unitGroupUtils.setSquadCommand(squad, command, state, cycles)
|
||||
-- local group = squad.group
|
||||
-- if (group ~= nil) and group.valid then
|
||||
-- squad.status = state
|
||||
-- squad.cycles = cycles
|
||||
-- group.set_command(command)
|
||||
-- group.start_moving()
|
||||
-- end
|
||||
-- end
|
||||
function unitGroupUtils.addSquadMovementPenalty(squad, chunkX, chunkY)
|
||||
local penalties = squad.penalties
|
||||
for penaltyIndex=1, #penalties do
|
||||
local penalty = squad.penalties[penaltyIndex]
|
||||
if (penalty.x == chunkX) and (penalty.y == chunkY) then
|
||||
penalty.v = penalty.v + MOVEMENT_PENALTY_PHEROMONE_GENERATOR_AMOUNT
|
||||
return
|
||||
end
|
||||
end
|
||||
if (#penalties == 10) then
|
||||
tableRemove(penalties, 10)
|
||||
end
|
||||
tableInsert(penalties, 1, { v = MOVEMENT_PENALTY_PHEROMONE_GENERATOR_AMOUNT,
|
||||
x = chunkX,
|
||||
y = chunkY })
|
||||
end
|
||||
|
||||
function unitGroupUtils.lookupSquadMovementPenalty(squad, chunkX, chunkY)
|
||||
local penalties = squad.penalties
|
||||
for penaltyIndex=1, #penalties do
|
||||
local penalty = penalties[penaltyIndex]
|
||||
if (penalty.x == chunkX) and (penalty.y == chunkY) then
|
||||
return penalty.v
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function unitGroupUtils.regroupSquads(natives)
|
||||
local SQUAD_RETREATING = constants.SQUAD_RETREATING
|
||||
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
||||
local findDistance = utils.euclideanDistanceNamed
|
||||
local mergeSquadMembers = unitGroupUtils.membersToSquad
|
||||
|
||||
local squads = natives.squads
|
||||
for i=1,#squads do
|
||||
@@ -96,29 +128,27 @@ function unitGroupUtils.regroupSquads(natives)
|
||||
for x=i+1, #squads do
|
||||
local mergeSquad = squads[x]
|
||||
local mergeGroup = mergeSquad.group
|
||||
if mergeGroup.valid and (mergeSquad.status == squad.status) and (findDistance(squadPosition, mergeGroup.position) < constants.HALF_CHUNK_SIZE) then
|
||||
mergeSquadMembers(squad, mergeGroup.members, true)
|
||||
if mergeGroup.valid and (mergeSquad.status == squad.status) and (euclideanDistanceNamed(squadPosition, mergeGroup.position) < HALF_CHUNK_SIZE) then
|
||||
unitGroupUtils.membersToSquad(squad, mergeGroup.members, true)
|
||||
mergeGroup.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local squads = natives.squads
|
||||
for i=#squads,1,-1 do
|
||||
local squad = squads[i]
|
||||
if (squad.group == nil) then
|
||||
table.remove(squads, i)
|
||||
tableRemove(squads, i)
|
||||
elseif not squad.group.valid then
|
||||
table.remove(squads, i)
|
||||
tableRemove(squads, i)
|
||||
elseif (#squad.group.members == 0) then
|
||||
squad.group.destroy()
|
||||
table.remove(squads, i)
|
||||
tableRemove(squads, i)
|
||||
else
|
||||
if (squad.status == SQUAD_RETREATING) and (squad.cycles == 0) then
|
||||
squad.cX = nil
|
||||
squad.cY = nil
|
||||
if (squad.status == SQUAD_RETREATING) and ((squad.cycles == 0) or (squad.group.state == GROUP_STATE_FINISHED)) then
|
||||
squad.status = SQUAD_GUARDING
|
||||
squad.cycles = 0
|
||||
elseif (squad.cycles > 0) then
|
||||
squad.cycles = squad.cycles - 1
|
||||
end
|
||||
|
@@ -1,47 +0,0 @@
|
||||
local utils = {}
|
||||
|
||||
local constants = require("Constants")
|
||||
|
||||
function utils.euclideanDistanceNamed(p1, p2)
|
||||
local xs = p1.x - p2.x
|
||||
local ys = p1.y - p2.y
|
||||
return ((xs * xs) + (ys * ys)) ^ 0.5
|
||||
end
|
||||
|
||||
function utils.euclideanDistanceArray(p1, p2)
|
||||
local xs = p1[1] - p2[1]
|
||||
local ys = p1[2] - p2[2]
|
||||
return ((xs * xs) + (ys * ys)) ^ 0.5
|
||||
end
|
||||
|
||||
function utils.positionDirectionToChunkCorner(direction, chunk, position)
|
||||
-- local position = {}
|
||||
if (direction == 1) then
|
||||
position.x = chunk.pX + constants.QUARTER_CHUNK_SIZE
|
||||
position.y = chunk.pY + constants.QUARTER_CHUNK_SIZE
|
||||
elseif (direction == 2) then
|
||||
position.x = chunk.pX + constants.HALF_CHUNK_SIZE
|
||||
position.y = chunk.pY + constants.QUARTER_CHUNK_SIZE
|
||||
elseif (direction == 3) then
|
||||
position.x = chunk.pX + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE
|
||||
position.y = chunk.pY + constants.QUARTER_CHUNK_SIZE
|
||||
elseif (direction == 4) then
|
||||
position.x = chunk.pX + constants.QUARTER_CHUNK_SIZE
|
||||
position.y = chunk.pY + constants.HALF_CHUNK_SIZE
|
||||
elseif (direction == 5) then
|
||||
position.x = chunk.pX + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE
|
||||
position.y = chunk.pY + constants.HALF_CHUNK_SIZE
|
||||
elseif (direction == 6) then
|
||||
position.x = chunk.pX + constants.QUARTER_CHUNK_SIZE
|
||||
position.y = chunk.pY + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE
|
||||
elseif (direction == 7) then
|
||||
position.x = chunk.pX + constants.HALF_CHUNK_SIZE
|
||||
position.y = chunk.pY + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE
|
||||
elseif (direction == 8) then
|
||||
position.x = chunk.pX + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE
|
||||
position.y = chunk.pY + constants.HALF_CHUNK_SIZE + constants.QUARTER_CHUNK_SIZE
|
||||
end
|
||||
return position
|
||||
end
|
||||
|
||||
return utils
|
@@ -1,20 +1,39 @@
|
||||
local chunkUtils = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local mapUtils = require("MapUtils")
|
||||
local constants = require("Constants")
|
||||
|
||||
-- optimize table creation and referencing
|
||||
local areaBoundingBox = {{1,2},
|
||||
{3,4}}
|
||||
local enemyChunkQuery = {area=areaBoundingBox,
|
||||
type="unit-spawner",
|
||||
force="enemy"}
|
||||
local playerChunkQuery = {area=areaBoundingBox,
|
||||
force="player"}
|
||||
-- constants
|
||||
|
||||
local DEATH_PHEROMONE = constants.DEATH_PHEROMONE
|
||||
local ENEMY_BASE_PHEROMONE = constants.ENEMY_BASE_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 DEFENSE_PHEROMONES = constants.DEFENSE_PHEROMONES
|
||||
local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
|
||||
|
||||
local PLAYER_DEFENSE_GENERATOR = constants.PLAYER_DEFENSE_GENERATOR
|
||||
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||
|
||||
local NORTH_SOUTH = constants.NORTH_SOUTH
|
||||
local EAST_WEST = constants.EAST_WEST
|
||||
|
||||
local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE
|
||||
local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE
|
||||
|
||||
local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||
|
||||
local ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
||||
|
||||
-- module code
|
||||
|
||||
function chunkUtils.checkForDeadendTiles(constantCoordinate, iteratingCoordinate, direction, chunkSize, surface)
|
||||
local NORTH_SOUTH = constants.NORTH_SOUTH
|
||||
local get_tile = surface.get_tile
|
||||
|
||||
local deadEnd = false
|
||||
@@ -37,12 +56,6 @@ function chunkUtils.checkForDeadendTiles(constantCoordinate, iteratingCoordinate
|
||||
end
|
||||
|
||||
function chunkUtils.checkChunkPassability(chunk, surface, natives)
|
||||
local checkForDeadendTiles = chunkUtils.checkForDeadendTiles
|
||||
local MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
|
||||
local NORTH_SOUTH = constants.NORTH_SOUTH
|
||||
local EAST_WEST = constants.EAST_WEST
|
||||
local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||
|
||||
local x = chunk.pX
|
||||
local y = chunk.pY
|
||||
|
||||
@@ -50,14 +63,14 @@ function chunkUtils.checkChunkPassability(chunk, surface, natives)
|
||||
local passableEastWest = false
|
||||
local xi = x
|
||||
while not passableNorthSouth and (xi < x + CHUNK_SIZE) do
|
||||
if (not checkForDeadendTiles(xi, y, NORTH_SOUTH, CHUNK_SIZE, surface)) then
|
||||
if (not chunkUtils.checkForDeadendTiles(xi, y, NORTH_SOUTH, CHUNK_SIZE, surface)) then
|
||||
passableNorthSouth = true
|
||||
end
|
||||
xi = xi + 1
|
||||
end
|
||||
local yi = y
|
||||
while not passableEastWest and (yi < y + CHUNK_SIZE) do
|
||||
if (not checkForDeadendTiles(yi, x, EAST_WEST, CHUNK_SIZE, surface)) then
|
||||
if (not chunkUtils.checkForDeadendTiles(yi, x, EAST_WEST, CHUNK_SIZE, surface)) then
|
||||
passableEastWest = true
|
||||
end
|
||||
yi = yi + 1
|
||||
@@ -73,54 +86,54 @@ function chunkUtils.checkChunkPassability(chunk, surface, natives)
|
||||
-- end
|
||||
|
||||
if passableEastWest then
|
||||
chunk[constants.EAST_WEST_PASSABLE] = true
|
||||
chunk[EAST_WEST_PASSABLE] = true
|
||||
else
|
||||
chunk[constants.EAST_WEST_PASSABLE] = false
|
||||
chunk[EAST_WEST_PASSABLE] = false
|
||||
end
|
||||
if passableNorthSouth then
|
||||
chunk[constants.NORTH_SOUTH_PASSABLE] = true
|
||||
chunk[NORTH_SOUTH_PASSABLE] = true
|
||||
else
|
||||
chunk[constants.NORTH_SOUTH_PASSABLE] = false
|
||||
chunk[NORTH_SOUTH_PASSABLE] = false
|
||||
end
|
||||
end
|
||||
|
||||
function chunkUtils.scoreChunk(chunk, surface, natives)
|
||||
local PLAYER_DEFENSE_PHEROMONES = constants.defensePheromones
|
||||
local PLAYER_BASE_PHEROMONES = constants.buildingPheromones
|
||||
|
||||
local x = chunk.pX
|
||||
local y = chunk.pY
|
||||
|
||||
areaBoundingBox[1][1] = x
|
||||
areaBoundingBox[1][2] = y
|
||||
areaBoundingBox[2][1] = x+constants.CHUNK_SIZE
|
||||
areaBoundingBox[2][2] = y+constants.CHUNK_SIZE
|
||||
local areaBoundingBox = {{x, y},
|
||||
{x + CHUNK_SIZE, y + CHUNK_SIZE}}
|
||||
local enemyChunkQuery = {area=areaBoundingBox,
|
||||
type="unit-spawner",
|
||||
force="enemy"}
|
||||
local playerChunkQuery = {area=areaBoundingBox,
|
||||
force="player"}
|
||||
|
||||
local entities = surface.count_entities_filtered(enemyChunkQuery)
|
||||
local spawners = 0
|
||||
local playerObjects = 0
|
||||
local playerDefenses = 0
|
||||
|
||||
spawners = entities * constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
||||
spawners = entities * ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
|
||||
|
||||
entities = surface.find_entities_filtered(playerChunkQuery)
|
||||
|
||||
for i=1, #entities do
|
||||
local entityType = entities[i].type
|
||||
|
||||
local entityScore = PLAYER_DEFENSE_PHEROMONES[entityType]
|
||||
local entityScore = DEFENSE_PHEROMONES[entityType]
|
||||
if (entityScore ~= nil) then
|
||||
playerDefenses = playerDefenses + entityScore
|
||||
end
|
||||
entityScore = PLAYER_BASE_PHEROMONES[entityType]
|
||||
entityScore = BUILDING_PHEROMONES[entityType]
|
||||
if (entityScore ~= nil) then
|
||||
playerObjects = playerObjects + entityScore
|
||||
end
|
||||
end
|
||||
|
||||
chunk[constants.PLAYER_BASE_GENERATOR] = playerObjects
|
||||
chunk[constants.PLAYER_DEFENSE_GENERATOR] = playerDefenses
|
||||
chunk[constants.ENEMY_BASE_GENERATOR] = spawners
|
||||
chunk[PLAYER_BASE_GENERATOR] = playerObjects
|
||||
chunk[PLAYER_DEFENSE_GENERATOR] = playerDefenses
|
||||
chunk[ENEMY_BASE_GENERATOR] = spawners
|
||||
end
|
||||
|
||||
function chunkUtils.createChunk(topX, topY)
|
||||
@@ -130,17 +143,16 @@ function chunkUtils.createChunk(topX, topY)
|
||||
cX = topX * 0.03125,
|
||||
cY = topY * 0.03125
|
||||
}
|
||||
chunk[constants.DEATH_PHEROMONE] = 0
|
||||
chunk[constants.ENEMY_BASE_PHEROMONE] = 0
|
||||
chunk[constants.PLAYER_PHEROMONE] = 0
|
||||
chunk[constants.PLAYER_BASE_PHEROMONE] = 0
|
||||
chunk[constants.PLAYER_DEFENSE_PHEROMONE] = 0
|
||||
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
|
||||
return chunk
|
||||
end
|
||||
|
||||
function chunkUtils.colorChunk(x, y, tileType, surface)
|
||||
local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||
|
||||
local tiles = {}
|
||||
for xi=x+5, x + CHUNK_SIZE-5 do
|
||||
for yi=y+5, y + CHUNK_SIZE-5 do
|
||||
|
24
tests.lua
24
tests.lua
@@ -2,14 +2,6 @@ local tests = {}
|
||||
|
||||
local constants = require("libs/Constants")
|
||||
|
||||
local regionMap
|
||||
local natives
|
||||
|
||||
function tests.initTester()
|
||||
regionMap = global.regionMap
|
||||
natives = global.natives
|
||||
end
|
||||
|
||||
function tests.test1()
|
||||
local player = game.players[1]
|
||||
local playerChunkX = math.floor(player.position.x / 32)
|
||||
@@ -19,8 +11,8 @@ function tests.test1()
|
||||
print("--")
|
||||
for x=playerChunkX-3, playerChunkX+3 do
|
||||
for y=playerChunkY-3, playerChunkY+3 do
|
||||
if (regionMap[x] ~= nil) then
|
||||
local chunk = regionMap[x][y]
|
||||
if (global.regionMap[x] ~= nil) then
|
||||
local chunk = global.regionMap[x][y]
|
||||
if (chunk ~= nil) then
|
||||
print(serpent.dump(chunk))
|
||||
end
|
||||
@@ -30,10 +22,12 @@ function tests.test1()
|
||||
end
|
||||
|
||||
function tests.test2()
|
||||
for i=1, #natives.squads do
|
||||
local squad = natives.squads[i]
|
||||
print("--")
|
||||
for i=1, #global.natives.squads do
|
||||
local squad = global.natives.squads[i]
|
||||
if squad.group.valid then
|
||||
print(math.floor(squad.group.position.x * 0.03125), math.floor(squad.group.position.y * 0.03125), squad.status, squad.group.state)
|
||||
print(serpent.dump(squad))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -56,8 +50,8 @@ function tests.test4()
|
||||
local chunkX = math.floor(playerPosition.x * 0.03125) * 32
|
||||
local chunkY = math.floor(playerPosition.y * 0.03125) * 32
|
||||
local entity = game.surfaces[1].find_nearest_enemy({position={chunkX, chunkY},
|
||||
max_distance=constants.CHUNK_SIZE,
|
||||
force = "enemy"})
|
||||
max_distance=constants.CHUNK_SIZE,
|
||||
force = "enemy"})
|
||||
if (entity ~= nil) then
|
||||
print(entity.name)
|
||||
end
|
||||
@@ -65,7 +59,7 @@ function tests.test4()
|
||||
end
|
||||
|
||||
function tests.test5()
|
||||
print(natives.points)
|
||||
print(global.natives.points)
|
||||
end
|
||||
|
||||
return tests
|
Reference in New Issue
Block a user