1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-24 03:47:58 +02:00

Improve main_attack performance by 15x

This commit is contained in:
Matthias Neumayer 2020-01-07 04:35:18 +01:00 committed by Aleksander Mistewicz
parent b0f8078661
commit fe898b9252
2 changed files with 133 additions and 34 deletions

View File

@ -34,6 +34,12 @@ local threat_values = {
["spitter-spawner"] = 16
}
-- these areas are for north
local left_spawner_area = {left_top = {-2000, -1200}, right_bottom = {-800, -700}}
local right_spawner_area = {left_top = {800, -1200}, right_bottom = {2000, -700}}
local middle_spawner_area = {left_top = {-600, -1000}, right_bottom = {600, -400}}
local whole_spawner_area = {left_top = {-2048, -1400}, right_bottom = {2048, -400}}
local function get_active_biter_count(biter_force_name)
local count = 0
for _, biter in pairs(global.active_biters[biter_force_name]) do
@ -51,11 +57,17 @@ local unit_evo_limits = {
["big-biter"] = 2,
}
function Public.set_biter_raffle_table()
local surface = game.surfaces["biter_battles"]
local biter_force_name = global.next_attack .. "_biters"
local biters = surface.find_entities_filtered({type = "unit", force = biter_force_name})
if not biters[5] then return end
local function set_biter_raffle_table(surface, biter_force_name)
-- It's fine to only sample the middle
local area = middle_spawner_area
-- If south_biters: Mirror area along x-axis
if biter_force_name == "south_biters" then
area = {left_top = {area.left_top[1], -1*area.right_bottom[2]}, right_bottom = {area.right_bottom[1], -1*area.left_top[2]}}
end
local biters = surface.find_entities_filtered({type = "unit", force = biter_force_name, area = area})
if not biters[1] then return end
global.biter_raffle[biter_force_name] = {}
local raffle = global.biter_raffle[biter_force_name]
local i = 1
@ -166,15 +178,66 @@ Public.send_near_biters_to_silo = function()
end
local function get_random_close_spawner(surface, biter_force_name)
local spawners = surface.find_entities_filtered({type = "unit-spawner", force = biter_force_name})
-- Here we have two options:
-- 1. Random the area (left, middle, right) => smaller area to search
-- 2. Search the whole area => larger area => if it's not cached we get a lag spike (~20ms)
--
-- Option 1
--
local rand_value = math_random(1, 10)
-- assume north_biters first
local area = nil
if rand_value == 1 then
area_name = "left"
area = left_spawner_area
elseif rand_value == 2 then
area_name = "right"
area = right_spawner_area
else
area_name = "middle"
area = middle_spawner_area
end
--
-- Option 2
--
-- area = whole_spawner_area
-- area_name = whole
-- After here it's the same
-- If south_biters: Mirror area along x-axis
if biter_force_name == "south_biters" then
area_name = area_name .. "_south"
area = {left_top = {area.left_top[1], -1*area.right_bottom[2]}, right_bottom = {area.right_bottom[1], -1*area.left_top[2]}}
end
-- If possible get the spawners from cache
-- TODO: If a spawner was destroyed, we still have it in cache, this is fine for now as we just use spawner.position
local spawners = nil
if not global.cached_spawners then global.cached_spawners = {} end
if global.cached_spawners[area_name] then
spawners = global.cached_spawners[area_name]
else
spawners = surface.find_entities_filtered({type = "unit-spawner", force = biter_force_name, area = area})
global.cached_spawners[area_name] = spawners
end
if not spawners[1] then return false end
local spawner = spawners[math_random(1,#spawners)]
-- game.forces["north"].add_chart_tag("biter_battles", {icon={type="virtual", name="signal-green"}, position=spawner.position})
for i = 1, 5, 1 do
local spawner_2 = spawners[math_random(1,#spawners)]
-- game.forces["north"].add_chart_tag("biter_battles", {icon={type="virtual", name="signal-green"}, position=spawner_2.position})
if spawner_2.position.x ^ 2 + spawner_2.position.y ^ 2 < spawner.position.x ^ 2 + spawner.position.y ^ 2 then spawner = spawner_2 end
end
-- rendering.draw_rectangle{color={g=1}, width=5, filled=false, left_top=area.left_top, right_bottom=area.right_bottom, surface="biter_battles"}
-- game.forces["north"].add_chart_tag("biter_battles", {icon={type="virtual", name="signal-blue"}, position=spawner.position})
return spawner
end
@ -330,7 +393,7 @@ local function create_attack_group(surface, force_name, biter_force_name)
if global.bb_debug then game.print("No spawner found for team " .. force_name) end
return false
end
local nearest_player_unit = surface.find_nearest_enemy({position = spawner.position, max_distance = 2048, force = biter_force_name})
if not nearest_player_unit then nearest_player_unit = global.rocket_silo[force_name] end
@ -345,20 +408,36 @@ local function create_attack_group(surface, force_name, biter_force_name)
global.unit_groups[unit_group.group_number] = unit_group
end
Public.main_attack = function()
Public.pre_main_attack = function()
local surface = game.surfaces["biter_battles"]
local force_name = global.next_attack
if not global.training_mode or (global.training_mode and #game.forces[force_name].connected_players > 0) then
local biter_force_name = force_name .. "_biters"
local wave_amount = math.ceil(get_threat_ratio(biter_force_name) * 7)
for c = 1, wave_amount, 1 do
create_attack_group(surface, force_name, biter_force_name)
end
if global.bb_debug then game.print(wave_amount .. " unit groups designated for " .. force_name .. " biters.") end
global.main_attack_wave_amount = math.ceil(get_threat_ratio(biter_force_name) * 7)
set_biter_raffle_table(surface, biter_force_name)
if global.bb_debug then game.print(global.main_attack_wave_amount .. " unit groups designated for " .. force_name .. " biters.") end
else
global.main_attack_wave_amount = 0
end
end
Public.perform_main_attack = function()
if global.main_attack_wave_amount > 0 then
local surface = game.surfaces["biter_battles"]
local force_name = global.next_attack
local biter_force_name = force_name .. "_biters"
create_attack_group(surface, force_name, biter_force_name)
global.main_attack_wave_amount = global.main_attack_wave_amount - 1
end
end
Public.post_main_attack = function()
global.main_attack_wave_amount = 0
if global.next_attack == "north" then
global.next_attack = "south"
else
@ -420,4 +499,12 @@ function Public.subtract_threat(entity)
return true
end
return Public
-- Invalidate the cache if a new chunk was generated
-- TODO: This can be more precise
Public.on_chunk_generated = function(event)
if event.area.right_bottom.x < -2048 then return end
if event.area.left_top.x > 2048 then return end
global.cached_spawners = {}
end
return Public

View File

@ -94,32 +94,43 @@ end
local tick_minute_functions = {
[300 * 1] = Ai.raise_evo,
[300 * 2] = Ai.destroy_inactive_biters,
[300 * 3] = Ai.set_biter_raffle_table,
[300 * 4] = Ai.main_attack,
[300 * 5] = Ai.send_near_biters_to_silo,
[300 * 6] = Ai.wake_up_sleepy_groups,
[300 * 3 + 30 * 0] = Ai.pre_main_attack, -- setup for main_attack
[300 * 3 + 30 * 1] = Ai.perform_main_attack, -- call perform_main_attack 7 times on different ticks
[300 * 3 + 30 * 2] = Ai.perform_main_attack, -- some of these might do nothing (if there are no wave left)
[300 * 3 + 30 * 3] = Ai.perform_main_attack,
[300 * 3 + 30 * 4] = Ai.perform_main_attack,
[300 * 3 + 30 * 5] = Ai.perform_main_attack,
[300 * 3 + 30 * 6] = Ai.perform_main_attack,
[300 * 3 + 30 * 7] = Ai.perform_main_attack,
[300 * 3 + 30 * 8] = Ai.post_main_attack,
[300 * 4] = Ai.send_near_biters_to_silo,
[300 * 5] = Ai.wake_up_sleepy_groups,
[300 * 7] = Game_over.restart_idle_map,
}
local function on_tick(event)
Mirror_terrain.ticking_work()
local tick = game.tick
local tick = game.tick
if tick % 60 ~= 0 then return end
global.bb_threat["north_biters"] = global.bb_threat["north_biters"] + global.bb_threat_income["north_biters"]
global.bb_threat["south_biters"] = global.bb_threat["south_biters"] + global.bb_threat_income["south_biters"]
if tick % 60 == 0 then
global.bb_threat["north_biters"] = global.bb_threat["north_biters"] + global.bb_threat_income["north_biters"]
global.bb_threat["south_biters"] = global.bb_threat["south_biters"] + global.bb_threat_income["south_biters"]
end
if tick % 180 == 0 then Gui.refresh() end
if tick % 300 ~= 0 then return end
Gui.spy_fish()
if global.bb_game_won_by_team then
Game_over.reveal_map()
Game_over.server_restart()
return
if tick % 300 == 0 then
Gui.spy_fish()
if global.bb_game_won_by_team then
Game_over.reveal_map()
Game_over.server_restart()
return
end
end
if tick % 30 ~= 0 then return end
local key = tick % 3600
if tick_minute_functions[key] then tick_minute_functions[key]() end
end
@ -169,9 +180,10 @@ Event.add(defines.events.on_research_finished, on_research_finished)
Event.add(defines.events.on_robot_built_entity, on_robot_built_entity)
Event.add(defines.events.on_robot_built_tile, on_robot_built_tile)
Event.add(defines.events.on_tick, on_tick)
Event.add(defines.events.on_chunk_generated, Ai.on_chunk_generated)
Event.on_init(on_init)
Event.add_event_filter(defines.events.on_entity_damaged, { filter = "name", name = "rocket-silo" })
require "maps.biter_battles_v2.spec_spy"
require "maps.biter_battles_v2.difficulty_vote"
require "maps.biter_battles_v2.difficulty_vote"