Skip to content
This repository has been archived by the owner on Nov 21, 2017. It is now read-only.

Commit

Permalink
Some data structure optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
Afforess committed Mar 28, 2016
1 parent a6f9342 commit 56d17f0
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 45 deletions.
23 changes: 0 additions & 23 deletions libs/ai/attack_plan.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,29 +60,6 @@ function attack_plan.tick(attack_data)
return
else
attack_plan.coordinate_biters(attack_data)
return
end

if not attack_data.pathfinder_data then
local surface = game.surfaces[attack_data.surface_name]

attack_data.pathfinder_data = pathfinder.partial_a_star(surface, attack_data.position, attack_data.target_position, 10)
elseif not attack_data.pathfinder_data.completed then
attack_data.pathfinder_data = pathfinder.resume_a_star(attack_data.pathfinder_data, 1)
if attack_data.pathfinder_data.iterations > 1000 then
Logger.log("Pathfinding between " .. serpent.line(attack_data.position) .. " and " .. serpent.line(attack_data.target_position) .. " took more than 1000 iterations")
attack_data.completed = true
return
end
else
local path = attack_data.pathfinder_data.path
if not path then
Logger.log("Failed to find a path between " .. serpent.line(attack_data.position) .. " and " .. serpent.line(attack_data.target_position))
attack_data.completed = true
else
attack_plan.attack_target(attack_data)
attack_data.completed = true
end
end
end

Expand Down
72 changes: 51 additions & 21 deletions libs/map.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,32 @@ function Map.new()
global.enemyRegionQueue = nil
global.foo = nil
global.bar = nil

if not global.migrated_keys then
global.migrated_keys = true

local region_queue = {}
for _, region_data in pairs(global.region_queue) do
table.insert(region_queue, region.region_key(region_data))
end
global.region_queue = region_queue

local visited_regions = {}
for _, region_data in pairs(global.visited_regions) do
visited_regions[region.region_key(region_data)] = true
end
global.visited_regions = visited_regions

local enemy_regions = {}
for _, region_data in pairs(global.enemy_regions) do
table.insert(enemy_regions, region.region_key(region_data))
end
global.enemy_regions = enemy_regions

Logger.log("Migrated reqion queue structures")
end


local Map = {}

function Map:tick()
Expand All @@ -46,6 +72,15 @@ function Map.new()
global.attack_plans[key] = nil
end
end

if not global.foo then
for _, region in pairs(global.regions) do
if region.danger_cache and not region.danger_cache.all_zeros then
danger_cache.calculate(region.danger_cache)
end
end
global.foo = true
end
end

function Map:update_region_ai(region_data)
Expand Down Expand Up @@ -79,13 +114,14 @@ function Map.new()
Logger.log("No enemy regions found.")
else
Logger.log("Current enemy regions: " .. #global.enemy_regions)
local enemy_region = table.remove(global.enemy_regions, 1)
local enemy_region_key = table.remove(global.enemy_regions, 1)
local enemy_region = global.regions[enemy_region_key]

Logger.log("")
Logger.log("Checking enemy region: " .. region.tostring(enemy_region))
if region.update_biter_base_locations(enemy_region) and region.any_potential_targets(enemy_region, 16) then
-- add back to the end of the list
table.insert(global.enemy_regions, enemy_region)
table.insert(global.enemy_regions, enemy_region_key)

if global.expansion_state == "Peaceful" then
return
Expand All @@ -110,7 +146,7 @@ function Map.new()
Logger.log("Iterating map, region: " .. region.tostring(region_data))
if not self:is_enemy_region(region_data) and (region.update_biter_base_locations(region_data) and region.any_potential_targets(region_data, 16)) then
Logger.log("Found enemy region: " .. region.tostring(region_data))
table.insert(global.enemy_regions, region_data)
table.insert(global.enemy_regions, region.region_key(region_data))
end
end
end
Expand All @@ -121,57 +157,51 @@ function Map.new()
-- reset lists
global.visited_regions = {}
global.region_queue = {}
global.enemy_regions = {}

for i = 1, #game.players do
if game.players[i].connected then
self:add_partially_charted(region.lookup_region_from_position(game.players[i].surface, game.players[i].position))
end
end
table.insert(global.region_queue, region.lookup_region(game.surfaces.nauvis.name, 0, 0))
table.insert(global.region_queue, region.lookup_region_key(game.surfaces.nauvis.name, 0, 0))
end

function Map:next_region()
if #global.region_queue == 0 then
self:seed_initial_values()
end
--Logger.log("Region queue: " .. serpent.line(global.region_queue))
--Logger.log("Visited Regions: " .. serpent.line(global.visited_regions))
--Logger.log("Enemy Regions: " .. serpent.line(global.enemy_regions))

local next_region = table.remove(global.region_queue, 1)
local next_region_key = table.remove(global.region_queue, 1)
local next_region = global.regions[next_region_key]

self:add_partially_charted(region.offset(next_region, 1, 0))
self:add_partially_charted(region.offset(next_region, -1, 0))
self:add_partially_charted(region.offset(next_region, 0, 1))
self:add_partially_charted(region.offset(next_region, 0, -1))

table.insert(global.visited_regions, next_region)
global.visited_regions[region.region_key(next_region)] = true

return next_region
end

function Map:is_already_iterated(region_data)
for i = 1, #global.visited_regions do
if (global.visited_regions[i].x == region_data.x and global.visited_regions[i].y == region_data.y) then
return true
end
end
return false
return global.visited_regions[region.region_key(region_data)]
end

function Map:is_pending_iteration(region_data)
local region_key = region.region_key(region_data)
for i = 1, #global.region_queue do
if (global.region_queue[i].x == region_data.x and global.region_queue[i].y == region_data.y) then
if (global.region_queue[i] == region_key) then
return true
end
end
return false
end

function Map:is_enemy_region(region_data)
for _, enemy_region in pairs(global.enemy_regions) do
if (enemy_region.x == region_data.x and enemy_region.y == region_data.y) then
local region_key = region.region_key(region_data)
for _, enemy_region_key in pairs(global.enemy_regions) do
if region_key == enemy_region_key then
return true
end
end
Expand All @@ -181,10 +211,10 @@ function Map.new()
function Map:add_partially_charted(region_data)
if not (self:is_already_iterated(region_data) or self:is_pending_iteration(region_data)) then
if region.is_partially_charted(region_data) then
table.insert(global.region_queue, region_data)
table.insert(global.region_queue, region.region_key(region_data))
else
-- don't recheck if partially charted over and over in the future, just add to 'visited list'
table.insert(global.visited_regions, region_data)
global.visited_regions[region.region_key(region_data)] = true
end
end
end
Expand Down
5 changes: 5 additions & 0 deletions libs/region.lua
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,11 @@ function region.region_key(region_data)
return string.format("%s@{%s,%s}", region_data.surface_name, region_data.x, region_data.y)
end

function region.lookup_region_key(surface_name, region_x, region_y)
region.lookup_region(surface_name, region_x, region_y)
return string.format("%s@{%s,%s}", surface_name, region_x, region_y)
end

function region.lookup_region_from_position(surface, pos)
local region_x = bit32.arshift(math.floor(pos.x), 7)
local region_y = bit32.arshift(math.floor(pos.y), 7)
Expand Down
20 changes: 19 additions & 1 deletion libs/region/danger_cache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@ function danger_cache.calculate(cache)
if not any_values then
cache.danger_cache = nil
cache.all_zeros = true
else
for x = 0, size - 1 do
local any_values_in_row = false
for y = 0, size - 1 do
cache.danger_cache[x][y] = 0
if cache.danger_cache[x][y] > 0 then
any_values_in_row = true
-- convert to integers and set the min value to 1
cache.danger_cache[x][y] = math.floor(math.max(1, cache.danger_cache[x][y]))
end
end
if not any_values_in_row then
cache.danger_cache[x] = nil
end
end
end
end

Expand All @@ -98,7 +113,10 @@ function danger_cache.get_danger(cache, position)
end
local x_idx = bit32.band(x, 0x7F)
local y_idx = bit32.band(y, 0x7F)
return cache.danger_cache[x_idx][y_idx]
if cache.danger_cache[x_idx] then
return cache.danger_cache[x_idx][y_idx]
end
return 0
end
return -1
end
Expand Down

0 comments on commit 56d17f0

Please sign in to comment.