diff --git a/Makefile b/Makefile index 2873594..d1699f9 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ PACKAGE_NAME := Misanthrope -VERSION_STRING := 0.4.0 +VERSION_STRING := 0.4.1 OUTPUT_NAME := $(PACKAGE_NAME)_$(VERSION_STRING) OUTPUT_DIR := build/$(OUTPUT_NAME) diff --git a/libs/biter/ai/attack_area.lua b/libs/biter/ai/attack_area.lua index e5b9633..59e2e41 100644 --- a/libs/biter/ai/attack_area.lua +++ b/libs/biter/ai/attack_area.lua @@ -30,7 +30,19 @@ AttackArea.stages.spawning = function(base, data) end AttackArea.stages.plan_attack = function(base, data) - local end_pos = Area.center(Chunk.to_area(base.target.chunk_pos)) + local candidates = base.targets.candidates + if #candidates == 0 then + base.targets = nil + return 'fail' + end + local idx = math.random(#candidates) + local candidate = table.remove(candidates, idx) + Log("Attack candidate: %s", base, serpent.line(candidate)) + if #candidates == 0 then + base.targets = nil + end + + local end_pos = Area.center(Chunk.to_area(candidate.chunk_pos)) local command = {type = defines.command.attack_area, destination = end_pos, radius = 16} local entities = table.filter(base.entities, Game.VALID_FILTER) @@ -62,6 +74,9 @@ function AttackArea.tick(base, data) end function AttackArea.is_expired(base, data) + if data.stage == 'fail' or data.stage == 'success' then + return true + end return data.attack_group and (not data.attack_group.valid or game.tick > data.attack_tick + Time.MINUTE * 6) end diff --git a/libs/biter/ai/identify_targets.lua b/libs/biter/ai/identify_targets.lua index b2ab8cf..df7828d 100644 --- a/libs/biter/ai/identify_targets.lua +++ b/libs/biter/ai/identify_targets.lua @@ -5,7 +5,7 @@ local Log = function(str, ...) BiterBase.LogAI("[IdentifyTargets] " .. str, ...) IdentifyTargets.stages.setup = function(base, data) local chunk_pos = Chunk.from_position(base.queen.position) - local search_area = Position.expand_to_area(chunk_pos, 15) + local search_area = Position.expand_to_area(chunk_pos, 20) data.start_chunk = chunk_pos data.search_queue = {} data.search_idx = 1 @@ -28,8 +28,8 @@ IdentifyTargets.stages.search = function(base, data) if chunk_data and chunk_data.player_value and chunk_data.player_value > 0 then local dist = Position.manhattan_distance(chunk_pos, data.start_chunk) - value = chunk_data.player_value / ((1 + dist) * (1 + dist)) - table.insert(data.candidates, { chunk_pos = chunk_pos, data = chunk_data, value = value}) + value = (chunk_data.player_value * chunk_data.player_value) / ((1 + dist) * (1 + dist)) + table.insert(data.candidates, { chunk_pos = chunk_pos, value = value}) end data.search_idx = data.search_idx + 1 @@ -46,15 +46,16 @@ IdentifyTargets.stages.sort = function(base, data) end) Log("All candidates: %s", base, serpent.block(data.candidates)) + data.candidates = table.filter(data.candidates, function(candidate) + return candidate.value > 100 + end) + if #data.candidates == 0 then + Log("No candidates, unable to identify any valuable targets.", base) + return 'fail' + end + Log("Filtered candidates: %s", base, serpent.block(data.candidates)) - return 'decide' -end - -IdentifyTargets.stages.decide = function(base, data) - local idx = math.random(#data.candidates) - local choosen_candidate = data.candidates[idx] - Log("Randomly chosen candidate was %s", base, serpent.line(choosen_candidate)) - base.target = { type = 'player_value', chunk_pos = choosen_candidate.chunk_pos, tick = game.tick} + base.targets = { candidates = data.candidates, tick = game.tick } return 'success' end diff --git a/libs/biter/base.lua b/libs/biter/base.lua index c6ab1de..3e69171 100644 --- a/libs/biter/base.lua +++ b/libs/biter/base.lua @@ -219,16 +219,13 @@ function BiterBase.create_plan(base) LogAI("Current Number of Worms in Base: %d", base, #base.worms) if base:can_afford('identify_targets') then - if not base.target then + if not base.targets then LogAI("No active targets, chooses AI plan to identify targets", base) BiterBase.set_active_plan(base, 'identify_targets') return true end - if not base.target.tick then - base.target.tick = game.tick - end - local age = game.tick - base.target.tick + local age = game.tick - base.targets.tick if math.random(200) < (age / Time.MINUTE) then LogAI("Recalculating targets, previous target is %s minutes old", base, serpent.line((age / Time.MINUTE))) BiterBase.set_active_plan(base, 'identify_targets') @@ -256,7 +253,7 @@ function BiterBase.create_plan(base) return true end - if base:can_afford('attack_area') and base.target and base.target.type == 'player_value' then + if base:can_afford('attack_area') and base.targets then local active_chunk = BiterBase.is_in_active_chunk(base) if active_chunk then LogAI("Is in an active chunk: true", base) else LogAI("Is in an active chunk: false", base) end diff --git a/libs/world.lua b/libs/world.lua index 23dec13..bdab122 100644 --- a/libs/world.lua +++ b/libs/world.lua @@ -5,24 +5,22 @@ require 'stdlib/surface' require 'libs/biter/base' World = {} -World.version = 40 +World.version = 41 World.Logger = Logger.new("Misanthrope", "world", DEBUG_MODE) local Log = function(str, ...) World.Logger.log(string.format(str, ...)) end function World.setup() - local mod_version = global.mod_version if not global.mod_version then -- goodbye fair world local old_global = global global = {} - global.mod_version = 40 - mod_version = 0 + global.mod_version = World.version Harpa.migrate(old_global) World.recalculate_chunk_values() end - if mod_version ~= global.mod_version then - World.migrate(mod_version, World.version) + if World.version ~= global.mod_version then + World.migrate(global.mod_version, World.version) global.mod_version = World.version end @@ -43,6 +41,14 @@ function World.migrate(old_version, new_version) end end end + elseif old_version < 41 then + for i = #global.bases, 1, -1 do + local base = global.bases[i] + base.target = nil + end + if global.overmind then + global.overmind.currency = 0 + end end end @@ -68,10 +74,11 @@ end Event.register(defines.events.on_player_created, World.resync_players) -Event.register(Event.core_events.configuration_changed, function(event) +Event.register({Event.core_events.init, Event.core_events.configuration_changed}, function(event) Log("Setting up world...") - Log("Mod data: %s" , serpent.line(event.data)) + if event.data then + Log("Mod data: %s", serpent.line(event.data)) + end World.setup() - Event.remove(defines.events.on_tick, event._handler) Log("World setup complete.") end)