Page 1 of 1

efficiently cover all empty areas with ore

Posted: Wed Sep 21, 2022 10:06 pm
by adamwong246
The goal is to cover the whole map, except for other ore patches with a mine-able Earth. This code does work but makes my M1 Mac beachball-spin for about 5 seconds when starting a map. Can anything be done to make this more efficient?

Code: Select all

local earthResource = table.deepcopy(data.raw["resource"]["stone"]);
earthResource.name = "earth";
earthResource.minable.result = nil;
earthResource.infinite = true;
earthResource.minimum = 1;
earthResource.minable.results = {{
    name = "earth",
    probability = 0.9,
    amount = 1
}, {
    name = "stone",
    probability = 0.09,
    amount = 1
}, {
    name = "silver",
    probability = 0.009,
    amount = 1
}, {
    name = "gold",
    probability = 0.001,
    amount = 1
}};
earthResource.autoplace = nil;

Code: Select all

-- Iterate over every tile in the new chunk and spam with random resources, if empty and possible.
script.on_event(defines.events.on_chunk_generated, function(event)

    for x = event.area.left_top.x + 0, event.area.right_bottom.x - 1 do
        for y = event.area.left_top.y + 0, event.area.right_bottom.y - 1 do

            local resources = event.surface.count_entities_filtered({
                position = {x, y},
                radius = 1,
                type = "resource",
                limit = 1
            })

            log(serpent.block(resources))

            if resources == 0 then
                event.surface.create_entity({
                    name = "earth",
                    amount = 1,
                    position = {x, y}
                })

            end

        end
    end
end)

Re: efficiently cover all empty areas with ore

Posted: Thu Sep 22, 2022 5:20 am
by DaveMcW

Code: Select all

script.on_event(defines.events.on_chunk_generated, function(event)

    -- Only one API call
    local resources = event.surface.find_entities_filtered({
        area = event.area,
        type = "resource",
    })

    -- Find all tiles covered by resources
    local tiles = {}
    for _, resource in pairs(resources) do
        local pos = resource.position
        local box = resource.prototype.collision_box
        -- Big resources cover several tiles
        for x = math.floor(pos.x + box.left_top.x), math.floor(pos.x + box.right_bottom.x) do
            for y = math.floor(pos.y + box.left_top.y), math.floor(pos.y + box.right_bottom.y) do
                -- Store tile x,y as table key for fast lookup
                tiles[x..","..y] = true
            end     
        end
    end

    for x = event.area.left_top.x + 0, event.area.right_bottom.x - 1 do
        for y = event.area.left_top.y + 0, event.area.right_bottom.y - 1 do
        
            -- Check for colliding resource at this x,y
            if not tiles[x..","..y] then
                event.surface.create_entity({
                    name = "earth",
                    amount = 1,
                    position = {x, y}
                })
            end
            
        end
    end
    
end)