Optimizing ore searching

Place to get help with not working mods / modding interface.
User avatar
ThaPear
Fast Inserter
Fast Inserter
Posts: 226
Joined: Fri May 30, 2014 8:05 am
Contact:

Optimizing ore searching

Post by ThaPear »

I'm looking to find all ores within a certain radius, but I need to do it quickly, as it's done quite often.

The code I'm currently using to find ores in a specific radius around a specific position is this:

Code: Select all

local results = game.findentitiesfiltered{type = "resource", area = GetBoundingBox(position, radius)}
local ores = {}
for i = #results, 1, -1 do
	local ore = results[i]
	-- No fluids.
	if game.entityprototypes[ore.name].resourcecategory == "basic-fluid"
	-- No lava.
	or game.entityprototypes[ore.name].resourcecategory == "lava-magma"
	-- No depleted resources that aren't infinite.
	or (ore.amount <= 0 and not game.entityprototypes[ore.name].infiniteresource)
	-- No trees.
	or string.find(ore.name, "tree") then
		--table.remove(results, i)
	else
		table.insert(ores, results[i])
	end
end
--return results
return ores
This causes the script to take up about 15-25 ms, as opposed to just 1 ms when doing:

Code: Select all

local results = game.findentitiesfiltered{type = "resource", area = GetBoundingBox(self.vehicle.position, radius)}
return results
As you can see, I've tried removing them from the old results and I've tried creating a new list with only the filtered entities.
The new list was slightly faster, but only 2-4 ms (on the 15-25).

Situation: There are (currently 21) entities searching for ores in a certain radius, driving there, mining, searching anew, etc..

My question is: Does anyone have suggestions on optimizing this?
keyboardhack
Filter Inserter
Filter Inserter
Posts: 478
Joined: Sat Aug 23, 2014 11:43 pm
Contact:

Re: Optimizing ore searching

Post by keyboardhack »

You could split it up so it only does 1 tenth of the work every tick. something like this:

Code: Select all

local dY = yEnd - yStart
local results = game.findentitiesfiltered{type = "resource", area = {{xStart, yStart + ((dY / 10) * (cycleCounter - 1))}, {xEnd, ((dY / 10) * cycleCounter)}}}
if CycleCounter > 10 then
    cycleCounter = 1
end
cycleCounter = cycleCounter + 1

--filter results
Variables
cycleCounter is a variable controlling what tenth of the field the entity(i am guessing it's an entity) it's searching in.
xStart, yStart is the top left position of the search area
xEnd, yend is the bottom right position of the search area
(hopefully the code makes sense :))
Last edited by keyboardhack on Tue Jun 30, 2015 3:52 am, edited 1 time in total.
Waste of bytes : P
User avatar
DaveMcW
Smart Inserter
Smart Inserter
Posts: 3749
Joined: Tue May 13, 2014 11:06 am
Contact:

Re: Optimizing ore searching

Post by DaveMcW »

You can also divide it by the total number of entities. Each tick you pick the next entity in the list and process that one. This way performance is constant, there is only a bit of decision lag if you have a lot of them.

I believe Roboports do this already.
jorgenRe
Filter Inserter
Filter Inserter
Posts: 535
Joined: Wed Apr 09, 2014 3:32 pm
Contact:

Re: Optimizing ore searching

Post by jorgenRe »

Okay so what i would do is rather put each orefield in a table, so have that dropoff point search around it for resources ONLY when its built, and then put what it finds in a table. Then each miner looks through that table and takes the first position in it and mines it out. When its out it goes to the table again and takes the lowest from there too :)!
Summed up:
Make dropoff point 1 time search for resources, puts the results in a table -->(Point 2:) each miner within a radius of that dropoff point will take the first position and by using: "table.remove(glob.table[dropoffStationNr], 1)" it removes the first position in the table, and then moves everything over it down! It will now have a new resource entity to mine, then when it is mined out, it will ask for another resource^(back to point 2)
Logo
Noticed the told change in FFF #111 so il continue to use my signature ^_^
Thanks for listening to our suggestions, devs :D!
I would jump of joy if we could specify which tiles spawned in a surfaces
jorgenRe
Filter Inserter
Filter Inserter
Posts: 535
Joined: Wed Apr 09, 2014 3:32 pm
Contact:

Re: Optimizing ore searching

Post by jorgenRe »

keyboardhack wrote:You could split it up so it only does 1 tenth of the work every tick. something like this:

Code: Select all

local dY = yEnd - yStart
local results = game.findentitiesfiltered{type = "resource", area = {{xStart, yStart + ((dY / 10) * (cycleCounter - 1))}, {xEnd, ((dY / 10) * cycleCounter)}}}
if CycleCounter > 10 then
    cycleCounter = 1
end
cycleCounter = cycleCounter + 1

--filter results
Variables
cycleCounter is a variable controlling what tenth of the field the entity(i am guessing it's an entity) it's searching in.
xStart, yStart is the top left position of the search area
xEnd, yend is the bottom right position of the search area
(hopefully the code makes sense :))
Hmmmm If less than 10... Makes steps of 1.... resets to 1 does: 1+1...2+1... when 9 then goes back to 1 That is 8 steps and not 10! :ugeek:
Logo
Noticed the told change in FFF #111 so il continue to use my signature ^_^
Thanks for listening to our suggestions, devs :D!
I would jump of joy if we could specify which tiles spawned in a surfaces
keyboardhack
Filter Inserter
Filter Inserter
Posts: 478
Joined: Sat Aug 23, 2014 11:43 pm
Contact:

Re: Optimizing ore searching

Post by keyboardhack »

jorgenRe wrote:
keyboardhack wrote:You could split it up so it only does 1 tenth of the work every tick. something like this:

Code: Select all

local dY = yEnd - yStart
local results = game.findentitiesfiltered{type = "resource", area = {{xStart, yStart + ((dY / 10) * (cycleCounter - 1))}, {xEnd, ((dY / 10) * cycleCounter)}}}
if CycleCounter > 10 then
    cycleCounter = 1
end
cycleCounter = cycleCounter + 1

--filter results
Variables
cycleCounter is a variable controlling what tenth of the field the entity(i am guessing it's an entity) it's searching in.
xStart, yStart is the top left position of the search area
xEnd, yend is the bottom right position of the search area
(hopefully the code makes sense :))
Hmmmm If less than 10... Makes steps of 1.... resets to 1 does: 1+1...2+1... when 9 then goes back to 1 That is 8 steps and not 10! :ugeek:
There is an error in the code but that's not it.
It begins at 1 loops up to 9. 9 is not bigger than 10 so it continiues. 10 is not bigger than 10 so it continiues. It should actually stop at 10 so this line

Code: Select all

if CycleCounter > 10 then
Should be

Code: Select all

if CycleCounter == 10 then
Now it will loop from 1 to 10 which should be correct. Ofc i haven't tested it so there could be additional bugs : P
Waste of bytes : P
Post Reply

Return to “Modding help”