Moon Logic deprecated

by mk-fg

Adds Lua-programmable circuit network combinator. Based on Sandboxed LuaCombinator and LuaCombinator2 mods. Probably won't work in multiplayer games.

Content
2 years ago
1.0 - 1.1
4.97K
Circuit network

g [lua-qiz] Delay Function

3 months ago
(updated 3 months ago)

I seem to be unable to grasp the nuances to the delay function.

For example using the syntax in the mod description:

delay, out['red/signal-X'] = 10, out['red/signal-X'] + 1

Works fine. On the red output wire the X signal is output and the value increments 6 times a second.

However if I try to do something like

local xValue = 0

while xValue < 512 do
   out['red/signal-X'] = xValue
   xValue = xValue + 1
   delay = 15
end

The final value is output without any delays in the iterations through the while loop. An X signal with only the final value of 511 is output on the red wire.

Thanks!

3 months ago

Code on a combinator runs as one uninterrupted function, i.e. if you put a loop like that there, it will run until completion (as it would if you'd call it in regular lua), without any game-time passing at all during that.
That function is supplied an environment from previous runs (those global variables), and after it finishes, some specific values are checked to do some special actions - outputs, delay, etc.

So to make signal loop through values in game-time, not immediately, you can't use lua loops, as they run immediately and return only one final value, but instead have to set multiple values over multiple function runs, setting delay= on each of those to schedule when to run the code next time.

Your first example indeed does that, except without stopping condition, which can be implemented like this:

if out['red/signal-X'] < 512 then
  delay, out['red/signal-X'] = 15, out['red/signal-X'] + 1
end
delay = 999999 -- no need to run this again
3 months ago
(updated 3 months ago)

Thanks that explanation clears a lot of stuff up about execution and delays and stuff.

I'm trying to get into recursive blueprints and self-replicating factories (or at least semi-autonomous) and so I ran into this issue with nested iterators.

This ended up working for my case which was setting down an AAI Industries zone. I have absolutely no idea what that does yet but it's a nice map symbol.

if out['red/signal-x-tile'] > 142 then
  out['red/signal-x-tile'] = 128
  out['red/signal-y-tile'] = out['red/signal-y-tile'] + 1
  if out['red/signal-y-tile'] > 64 then
    out['red/signal-y-tile'] = -56
  else
  end
end

delay, out['red/signal-x-tile'] = 2, out['red/signal-x-tile'] + 1

So what I gather from what you're saying is I should move the iteration logic out of the delay implementation and use a single delay = 20 or something like the below?

--increment the x-value
out['red/signal-x-tile'] = out['red/signal-x-tile'] + 1

--check if x-value overflowed the region and reset to region beginning
if out['red/signal-x-tile'] > 142 then
  out['red/signal-x-tile'] = 128
  --start a new row to scan or lay down tiles
  out['red/signal-y-tile'] = out['red/signal-y-tile'] + 1
  --check if y-value has overflowed and reset to beginning of grid/zone
  if out['red/signal-y-tile'] > 64 then
    out['red/signal-y-tile'] = -56
  else
  end
end

--maybe update slower than once a tick
delay = 5
3 months ago

Yeah, something like that.

Note that delay is in game engine ticks, which are 1/60th of a second (at 1x game speed), so delay=2 still means "run 30 times a second".
Simple counters can also be easy to implement with vanilla arithmetic and decider combinators, where output is wired back to input for "memory" on the counter + whatever checks/resets on connected deciders, but lua is probably still easier than that.

3 months ago
(updated 3 months ago)

That makes more sense now. I think what tripped me up was the delay call in both branches of the if/else tree.

I was thinking it was kind of a generic sleep or async/promise type thing. Which is another thing I don’t really understand lol.

And I’d always scrolled past this mod wondering what it was capable of and kind of struggling through factories that looked like I was hoarding combinators or a crazy combinator lady or something. Then I saw this self building factory thing and it started to make more sense.

https://youtu.be/PGiTkkMOfiw?si=enWB9gNn6F_B4n5w

3 months ago

I was thinking it was kind of a generic sleep or async/promise type thing. Which is another thing I don’t really understand lol.

Yeah, lua 5.2 (used in factorio) has coroutines in the reference implementation, which are for that async stuff, but they're disabled in factorio, and loaded lua code blobs can't be serialized in savegames (unless it changed in last couple years), so there's definitely no easy suspend/resume for code afaik.

Such explicit "let player take care of state between runs" is the easiest way to implement continued operation after delay too - just run lua code as-is, only handling inputs/outputs for it, instead of some complicated code-parsing and special rules around it.

factories that looked like I was hoarding combinators

They have their place too imo, for simple local stuff or something that has to run fast on every tick.

I think for me tipping point is usually when logic gets complex enough that it has to be written down in pseudocode first, instead of building combinators straight away, where you effectively "compile" it to combinators instead, and that last part doesn't seem really creative or fun, and this combinator kinda automates it away.

New response