Re: Automatic Pumpjack Beacon Placement
Posted: Mon Jan 05, 2026 2:37 pm
I am personally the kind of player that would place 20 more beacons if it resulted in +1oil/second, even if i don't need it 
www.factorio.com
https://test.forums.factorio.com/
Yea, .. Aquilo with its litium and heatpipes .. pain in the a##Coppermine wrote: Mon Jan 05, 2026 2:33 pm On the other hand, it is not a great player experience to have to think of a good threshold for each different fluid. It would be nice if there were a simple metric we could use which was independent of the fluid being pumped.
And of course there's the extra complication of the pumpjacks on Aquilo which can fully exhaust their resource patches, rather than diminishing to some minimum flow rate. Should they be handled differently?
Thanks for clearing that up!Lindor wrote: Mon Jan 05, 2026 2:37 pm I am personally the kind of player that would place 20 more beacons if it resulted in +1oil/second, even if i don't need it![]()
I agree, but for different reasons than you might think.Xcone wrote: Mon Jan 05, 2026 1:47 pm If you want this for a mod (or added to an existing one); calculating all possible layouts, then comparing them, from within the game, .. that's just unacceptably slow. It'd freeze the game completely. Unless you separate all the math in batches and run it as some sort of spread out routine (for instance, calculate 1 or 2 possible layouts per in-game frame). But then the process would take unbearably long. That's not a good player experience.
Maybe when the amount of electricity it would consume to place another beacon outgrows the amount of electricity you would gain by burning all the additional oil/second?Coppermine wrote: Mon Jan 05, 2026 2:33 pm On the other hand, it is not a great player experience to have to think of a good threshold for each different fluid. It would be nice if there were a simple metric we could use which was independent of the fluid being pumped
Excellent QuestionXcone wrote: Mon Jan 05, 2026 2:58 pm Additional question; you as an oil-squeezer.. would you re-plan your oil field later on; or go straight for depletion rates as not to have to worry about it anymore?
Yes. If there is no minimum, we can only optimize for the maximum.Coppermine wrote: Mon Jan 05, 2026 2:33 pm And of course there's the extra complication of the pumpjacks on Aquilo which can fully exhaust their resource patches, rather than diminishing to some minimum flow rate. Should they be handled differently?
I am not sure what to make of that. I thought you were having problems with the speed of it?I think you're underestimating the calculation intensity of the greedy approach. The binary tree approach is both faster and more reliable since it has been proven that it always finds the best solution. And it's also better in memory complexity.
I haven't checked your code earlier. I don't do well with other people's code usually. But just had a peek, and I think the base premise between your code and mine isn't even that different. So it might just boil down to a difference in understanding the meaning of `greedy`. I too compute beacon coverage for each spot and put it in a lookup table. And then compare the positions which has the most affected pumps.
Code: Select all
local score = #(self.affectedPumpjacks)Code: Select all
score = score - beacon.score(seen)I do agree that audience probably exists within the Factorio community. But I can't be sure how sizable it is. Based on the kind of feedback I've received on my mod over the years, I don't think they're using my mod.However i still think that for the audience of Factorio it would make sense to at least give them the option to use the binary tree algorithm to calculate the optimal result.
Factorio's Lua is modified, and doesn't support lua-native coroutines. I've looked at that before.We could let it calculate in the background using coroutines. I can also provide some sort of progress bar data. We'd just need to make sure to be able to save the calculation state in-between game sessions.
That wouldn't work with sulfuric acid, lithium brine and fluoride. And the various other modded resources. I've done some reading about how the yield is calculated and what it means. And that percentage should be just fine to keep using, as it already represents the amount of oil (or other liquid). See: viewtopic.php?p=574243#p574243Maybe when the amount of electricity it would consume to place another beacon outgrows the amount of electricity you would gain by burning all the additional oil/second?
I mean the approach to check every possible layout.Xcone wrote: Mon Jan 05, 2026 8:00 pm I am also unsure what you are referring to with `binary tree approach`.
Well, there's the "correct" greedy approach, there's the "intermediate" and there's the "lazy" greedy approach.Xcone wrote: Mon Jan 05, 2026 8:00 pm I am not sure what to make of that. I thought you were having problems with the speed of it?
My routine currently takes milliseconds instead of seconds. So I am not entirely sure what I am underestimating?
That's awesome!Xcone wrote: Mon Jan 05, 2026 8:00 pm I haven't checked your code earlier. I don't do well with other people's code usually. But just had a peek
YepXcone wrote: Mon Jan 05, 2026 8:00 pm Where they differ is that that's good enough for me (being greedy), while you do 1 line of extra code (to keep away from being too greedy):However, that one line is a very expensive one, as it adds sooo many additional iterations. (as you already addressed in the post after you posted yourCode: Select all
score = score - beacon.score(seen)
Okay, i'm sorryXcone wrote: Mon Jan 05, 2026 8:00 pm So no, .. I believe I am not not underestimating the calculation intensity (or lack thereof) of taking the greedy approach.
I see two unrelated ideas here.Xcone wrote: Mon Jan 05, 2026 8:00 pm I am still figuring out the dynamics of `seen` and `ignore`; and wonder if they are essential to repeat every time (recursively), or can be computed once.
So if for each beacon position you could check which other positions are in range and sum the affected pumps of all of them and use that as some sort of penalty for that position. But I think you explained earlier that's not possible. So I need to read that bit again.
Maybe once you pick a beacon position, iterate all positions in range again, and reduce their penalty by the number of pumps the new beacon affects.
Clever thought, but it doesn't work. if A blocks B1 and B2, then seen is the same for B1 and B2. But if B2 blocks A and C1, while B2 blocks A and C2, then seen is not the same anymore for C1 and C2.Xcone wrote: Mon Jan 05, 2026 8:00 pm I am still figuring out the dynamics of `seen` and `ignore`; and wonder if they are essential to repeat every time (recursively), or can be computed once.
That is the thing, the penalty is not just the affected pumpjacks of the subbeacons, it's the value you use by not being able to place the subbeacons, and that value does not only depend on the affected subpumpjacks, but also on the subsubbeacons that the subbeacons would block. And so on and so forth.Xcone wrote: Mon Jan 05, 2026 8:00 pm So if for each beacon position you could check which other positions are in range and sum the affected pumps of all of them and use that as some sort of penalty for that position. But I think you explained earlier that's not possible. So I need to read that bit again.
Maybe once you pick a beacon position, iterate all positions in range again, and reduce their penalty by the number of pumps the new beacon affects.
No, you're correct. It's just a proof-of-concept-code where i only look at the number of affected pumpjacks. In an actual mod i'd calculate the oil per second gain.Xcone wrote: Mon Jan 05, 2026 8:00 pm Interestingly; I don't see any code that reflects the yield of the pumpjack is taking into account. Am I missing something?
That is a very good questionXcone wrote: Mon Jan 05, 2026 8:00 pm Additional question:
Have you considered the output pipes![]()
I notice your code doesn't do anything with pipes. So all the perfect layouts you're currently computing are not representative, since they have no means of carrying liquids outside of the field.
What's your expectation with those? Because I am very confident that where the pipes are, also affect where the beacons can be.
It seems a shame to figure out near-perfect beacon coverage, only to learn that had the pipes been put down differently you could put down even more beacons. But the pipe routine is a much bigger @#$%^ then the beacon routine, and I'm not really getting excited by the prospect of having to rework it for a few drops of oil.![]()
Ah right. Good clarification/distinction!Lindor wrote: Mon Jan 05, 2026 9:10 pm The "correct" greedy approach with an unlimited number of iterations is extremely slow.
The "intermediate" greedy approach with a limited number of iterations is a balance between speed and accuracy.
The "lazy" greedy approach where we ignore beacon blockage is extremely fast and inaccurate.
Yea, this bit is a real headscratcher.Lindor wrote: Mon Jan 05, 2026 9:10 pm That is the thing, the penalty is not just the affected pumpjacks of the subbeacons, it's the value you use by not being able to place the subbeacons, and that value does not only depend on the affected subpumpjacks, but also on the subsubbeacons that the subbeacons would block. And so on and so forth.
Your idea is basically limiting the number of iterations to 2. Which would still be a very inaccurate result. So far i found 5 to be the sweet spot.
Right, .. me neither.Lindor wrote: Mon Jan 05, 2026 9:10 pm It's not gonna be optimal, it's gonna loose us efficiency. But figuring out the optimum with both pipes, heat pipes and beacons? Yeh i wouldn't even know where to start.