Page 1 of 1

ChunkIterator with next

Posted: Sat Apr 15, 2017 2:46 pm
by sikian
Hi guys,

I've been trying to use the ChunkGenerator as an iterator and have finally managed to do so in a somewhat elegant way. However, I'm still not sure about some things. Maybe someone can help me out with this!
As for why I'm using it as an iterator is due to the fact that I want to get some info from all the chunks, but I think limiting the chunks checked by tick is probably a good way to go.

Let's start:
From http://lua-api.factorio.com/latest/LuaC ... rator.html, we can see that some_surface.get_chunks() provides a ChunkIterator.

From various documentations I've seen, getting the next element of an iterator can be reached either calling the iterator function or next (I might be waaaay off here, but that was my conclusion of what I read).
So I set off trying both things:

Code: Select all

local chunk_iter = surface.get_chunks()
local chunk = next(chunk_iter)
print(chunk, chunk.x, chunk.y)
This yields:
__self nil nil
So, wrong step.

Let's try with calling the iterator:

Code: Select all

local chunk_iter = surface.get_chunks()
local chunk = chunk_iter(1,1)
print(chunk, chunk.x, chunk.y)
The two arguments was what I found worked (as the function arity was complaining).
This seems to work, but now comes the question: what do those arguments mean?

Thanks in advance and sorry if this might seem a stupid question!

Re: ChunkIterator with next

Posted: Sat Apr 15, 2017 8:47 pm
by darkfrei

Code: Select all

/c local surface = game.player.surface
for c in surface.get_chunks() do
	local position = surface.find_non_colliding_position("biter-spawner", {x=c.x*32+16, y=c.y*32+16}, 10, 3)
	if position and surface.is_chunk_generated(c) then
		surface.create_entity{name="biter-spawner", position=position}
	end
end

Chunk is a table, chunk.x and chunk.y are coordinates of this chunk. In this example c is a chunk in all chunks.

Re: ChunkIterator with next

Posted: Sat Apr 15, 2017 10:25 pm
by DaveMcW
The arguments do not seem to do anything, you just need to have 2 of them.

Code: Select all

local chunk = chunk_iter(nil,nil)

Re: ChunkIterator with next

Posted: Sun Apr 16, 2017 10:15 am
by Rseding91
DaveMcW wrote:The arguments do not seem to do anything, you just need to have 2 of them.

Code: Select all

local chunk = chunk_iter(nil,nil)
In standard Lua "next" the call operator takes the last index retrieved and the thing to get the "next of last index" from. The LuaChunkIterator uses neither of those and each call simply gives the next chunk position while storing the state internally.

When you do this:

Code: Select all

for k,v in pairs(game.players) do ... end
That's actually doing something like this:

Code: Select all

local players = game.players
local k, v = next(nil, players)

while (k ~= nil) do
  ...
  k, v = next(k, players)
end

Re: ChunkIterator with next

Posted: Sun Apr 16, 2017 5:01 pm
by DaveMcW
Rseding91 wrote:The LuaChunkIterator uses neither of those
Any chance of fixing the error when you don't provide 2 arguments then?

Re: ChunkIterator with next

Posted: Mon Apr 17, 2017 12:39 am
by BenSeidel
DaveMcW wrote:
Rseding91 wrote:The LuaChunkIterator uses neither of those
Any chance of fixing the error when you don't provide 2 arguments then?
The LuaChunkIterator is not an Iterator, but an Iterable, hence the issues when using it. It's not about the arguments supplied.

Re: ChunkIterator with next

Posted: Sun Apr 23, 2017 7:22 pm
by sikian
Hey guys, thanks for your answers, but I yet don't understand how to use LuaChunkIterator to iterate through the chunks without a loop, but using something similar to next().

Thanks

Re: ChunkIterator with next

Posted: Sun Apr 23, 2017 9:16 pm
by prg
If you use next() on the return value of get_chunks(), you really only get the __self = "userdata: ..." thing out of it. The interesting behavior is implemented using metamethods so it can be used in a generic for. You can turn that into a while loop as mentioned in the manual like

Code: Select all

f, _, var = game.player.surface.get_chunks()
while true do
    var = f(nil, var)
    if var == nil then break end
    print(serpent.block(var))
end
if you like that better, but not much else you can do with it that I can see.