Aleksei-bird 7c9c708c92 Первый фикс
Пачки некоторых позиций увеличены
2024-03-01 20:54:33 +03:00

135 lines
4.8 KiB
Lua

local common = {}
local floor, ceil = math.floor, math.ceil
local min, max = math.min, math.max
---@param miner MinerStruct
function common.simple_miner_placement(miner)
local near, far, size, fullsize = miner.near, miner.far, miner.size, miner.full_size
local neighbor_cap = (near + 1) ^ 2
local leech = (far + 1) ^ 2
---@param center GridTile
return function(center)
return center.neighbor_count > neighbor_cap
-- return center.neighbor_count > neighbor_cap or center.far_neighbor_count > leech
end
end
---@param miner MinerStruct
function common.overfill_miner_placement(miner)
local near, far, size, fullsize = miner.near, miner.far, miner.size, miner.full_size
local neighbor_cap = (near + 1) ^ 2 - 1
local leech = far ^ 2 - 1
---@param center GridTile
return function(center)
return center.neighbor_count > 0 or center.far_neighbor_count > leech
end
end
---@param attempt PlacementAttempt
function common.simple_layout_heuristic(attempt)
--local lane_weigth = 0.05 * ((#attempt.lane_layout) ^ (1/3) - 1) + 1
return attempt.simple_density / attempt.miner_count + attempt.empty_space / attempt.miner_count
--return attempt.simple_density / attempt.miner_count * lane_weigth
--return (attempt.real_density - attempt.simple_density) -- * math.log(#attempt.lane_layout)
end
---@param attempt PlacementAttempt
function common.overfill_layout_heuristic(attempt)
--return (attempt.simple_density-attempt.real_density) / attempt.miner_count
--return attempt.simple_density - attempt.real_density -- * math.log(#attempt.lane_layout)
return -attempt.far_neighbor_sum
end
---Utility to fill in postponed miners on unconsumed resources
---@param state SimpleState
---@param heuristics PlacementAttempt
---@param miners MinerPlacement[]
---@param postponed MinerPlacement[]
function common.process_postponed(state, heuristics, miners, postponed)
local grid = state.grid
local size, near, far, fullsize = state.miner.size, state.miner.near, state.miner.far, state.miner.full_size
for _, miner in ipairs(miners) do
grid:consume(miner.center.x, miner.center.y)
end
for _, miner in ipairs(postponed) do
local center = miner.center
miner.unconsumed = grid:get_unconsumed(center.x, center.y)
end
table.sort(postponed, function(a, b)
if a.unconsumed == b.unconsumed then
local a_center, b_center = a.center, b.center
if a_center.neighbor_count == b_center.neighbor_count then
return a_center.far_neighbor_count > b_center.far_neighbor_count
end
return a_center.neighbor_count > b_center.neighbor_count
end
return a.unconsumed > b.unconsumed
end)
for _, miner in ipairs(postponed) do
local center = miner.center
local unconsumed_count = grid:get_unconsumed(center.x, center.y)
if unconsumed_count > 0 then
heuristics.neighbor_sum = heuristics.neighbor_sum + center.neighbor_count
heuristics.far_neighbor_sum = heuristics.far_neighbor_sum + center.far_neighbor_count
heuristics.empty_space = heuristics.empty_space + (size^2) - center.neighbor_count
heuristics.simple_density = heuristics.simple_density + center.neighbor_count / (size ^ 2)
heuristics.real_density = heuristics.real_density + center.far_neighbor_count / (fullsize ^ 2)
heuristics.leech_sum = heuristics.leech_sum + max(0, center.far_neighbor_count - center.neighbor_count)
heuristics.postponed_count = heuristics.postponed_count + 1
grid:consume(center.x, center.y)
miners[#miners+1] = miner
heuristics.miner_count = heuristics.miner_count + 1
miner.postponed = true
end
end
local unconsumed_sum = 0
for _, tile in ipairs(state.resource_tiles) do
if not tile.consumed then unconsumed_sum = unconsumed_sum + 1 end
end
heuristics.unconsumed_count = unconsumed_sum
grid:clear_consumed(state.resource_tiles)
end
local seed
local function get_map_seed()
if seed then return seed end
local game_exchange_string = game.get_map_exchange_string()
local map_data = game.parse_map_exchange_string(game_exchange_string)
local seed_number = map_data.map_gen_settings.seed
seed = string.format("%x", seed_number)
return seed
end
---Dump state to json for inspection
---@param state SimpleState
function common.save_state_to_file(state, type_)
local c = state.coords
local gx, gy = floor(c.gx), floor(c.gy)
local dir = state.direction_choice
local coverage = state.coverage_choice and "t" or "f"
local filename = string.format("layout_%s_%i;%i_%s_%i_%s_%s_%x.%s", get_map_seed(), gx, gy, state.miner_choice, #state.resources, dir, coverage, game.tick, type_)
if type_ == "json" then
game.print(string.format("Dumped data to %s ", filename))
game.write_file("mpp-inspect/"..filename, game.table_to_json(state), false, state.player.index)
elseif type_ == "lua" then
game.print(string.format("Dumped data to %s ", filename))
game.write_file("mpp-inspect/"..filename, serpent.dump(state, {}), false, state.player.index)
end
end
return common