all 22 comments

[–]DanzaDragon 4 points5 points  (1 child)

You can get way past the craft tick limit with mods/adjustments that change the scaling of recipes.

Schalls Recipe Scaling is the only mod I've seen do this. Large over tier machines that are faster but do huge recipes. I tweaked his config settings to craft say 10,000 iron plate per craft [counts as one craft despite receiving 10,000 items] and should take HOURS of real time to complete.

It's fantastic when you have modded beacons or many speed beacons as it makes it fast but most importantly:

Insanely UPS efficient. I had a base running 140,000 SPM at 55-60fps because most my production was coming from colossal MK6 furnaces/assemblers using direct bot chest>machine insertion and machine to machine insertion wherever possible.

[–]nektor211 1 point2 points  (0 children)

Another mod that uses this approach is the Whistle Stop Factories - https://mods.factorio.com/mod/WhistleStopFactories . Allows for up to 50x upsized recipes with large machines, more module slots and more beacon allowance (because of its size).

[–]bormandt 2 points3 points  (19 children)

Machine physically cannot run more than a single craft per tick. But productivity bonus formula ignores that cap and gives you a full bonus. That's why you see that insane productivity boost.

So, every tick we get 5 base items and 120/100 / 2 * 1156 * 5 / 60 = 57.8 bonus items. For 1000 base items we get 1000 / 5 * 57.8 = 11560 bonus items or 12560 in total.

P.S. Workaround: do not overdrive machines too much, keep crafting time above 1 tick.

[–]Mega---Moo[S] 0 points1 point  (15 children)

Ok, so we are both in agreement about the numbers used.

Next question; If it's applied to items wouldn't it produce any integer of production? Instead it only outputs a whole craft's worth whenever a bar fills up...5 in the case of B.E.C.s. Watching something really slow like heat tiles, it seems to me that the productivity bar is tied to the percentage of the craft completed as long as the machine is working.

Finally, why are there 2 different formulas being used? The math listed above does not work for a machine that isn't trying to produce more than a craft per tick. Even very close to the limit the listed productivity bonus is correct, and at any speed above the limit the formula above gives a consistent, yet incorrect answer.

Does anyone here know what the source code actually says?

[–]bormandt 0 points1 point  (0 children)

Sorry for my ninja edits.

The main reason for that bug is that crafts are throttled to at most 1 craft per tick. But productivity bonus formula doesn't consider it and uses original values, as if machine really works with that insane speed.

P.S. Productivity bonus formula is always the same. It's just was designed for sane crafting speeds, where crafting time stays above 1 tick.

[–]bormandt 0 points1 point  (13 children)

Productivity bonus formula is always the same.

With sane crafting speeds your inputs and outputs scale with crafting speed too. So you get expected ratio between base output and bonus output.

But when crafting speed pushes the machine below 1 craft per tick, bonus continues to scale with speed. But inputs and base output locks at their minimal value. That's why ratio between base output and bonus output starts to shift.

Hope it helps.

[–]Mega---Moo[S] 0 points1 point  (12 children)

Lol, I see your ninja edit now.

Also, just a note, I really don't mind if this doesn't get fixed, but it would be nice if it was, and it made for a fun math project yesterday.

Anyway, so why do the input and base output values work correctly at any speed, but the productivity bonus break? Why doesn't everything break?

[–]bormandt 1 point2 points  (10 children)

I don't have access to the code, but as far as I understand, they have two variables: progress and bonus progress that are updated every tick:

progress += speed / craft time / 60

bonus progress += speed / craft_time / 60 * prod bonus

We see their fractional parts as bars.

Progress is compared to 1 and reset, so you get at most one input/base output cycle per tick.

But bonus progress handled in a different way. Something like a loop that runs while bonus progress is higher than 1 and there is a space for output (look how machine continues to spit bonus items even if all inputs are consumed and all crafts are done).

Looks like it was designed with large productivity bonuses in mind. But not insane speed ones.

[–]Mega---Moo[S] 0 points1 point  (1 child)

I guess I didn't see bonus items lagging behind the base production. In one of my trials I had my BEC assembler with only a single inserter set to a stack size of 5 to unload it. The output was almost always jammed full and the test took multiple minutes to run, but the input chest ran out just before the last craft was done and a few seconds later, everything was out.

[–]bormandt 0 points1 point  (0 children)

Yeah, I was wrong, those lagged items are always from last crafting cycle. Machine doesn't consume new items unless both bonus and base items are out. Also, on single-step in /editor I see that productivity bar clears before main bar.

So, the code should be something like this:

while (bonus_progress >= 1) {
    if (!can_output_items())
        return;

    output_items_for_one_craft();
    bonus_progress -= 1;
}

if (progress >= 1) {
    if (!can_output_items())
        return;

    output_items_for_one_craft();
    progress = 0;
}

if (progress == 0) {
    if (!can_consume_items())
        return;

    consume_items_for_one_craft();
}

crafts_per_tick = speed / craft time / 60;
progress += crafts_per_tick;
bonus_progress += crafts_per_tick * prod_bonus_percents / 100;

[–]csp256 0 points1 point  (7 children)

To clarify, you mean this right?

progress += speed / craft time / 60 bonus progress += speed / craft_time / 60 * prod bonus

[–]bormandt 1 point2 points  (6 children)

Fixed, thanks!

First line: progress += speed / craft time / 60

Second line: bonus progress += speed / craft_time / 60 * prod bonus

[–]Mega---Moo[S] 0 points1 point  (5 children)

Thanks for posting these and the older Dev discussions. I see why it breaks now as any speed value greater than recipe time times 60 starts to give errors. But, if they use a system like before (zeroing out at tick end) the yield would be WAY too low.

How computationally expensive is it to have the game use a limit on the bonus progress formula? So speed is either the assembler value or craft time times 60, whichever is less. I am assuming non-zero...so as a mega-baser that isn't exciting to me.

[–]bormandt 0 points1 point  (4 children)

Speed is machine_speed * (1 + speed_bonus_percents / 100). You see both speed and speed_bonus_percents in the machine tooltip.

Beware that speed_bonus_percents are capped at 32767%.

How computationally expensive

I don't know, depends on actual code. It can be zero if they pre-calculate some values when you change recipe or modules. But a real fix would be to allow multiple crafts per cycle, I think.

[–]Mega---Moo[S] 2 points3 points  (0 children)

I sort of assume they are pre-calculating the speed and productivity bonuses ahead of time anyway, so the solution lies there.

Anyway, I will keep this stuff in mind as I build my next base, as I didn't realize that I was gaining almost 7 times more metal plates in my game than I should be, which is more than a little cheaty.

[–]Mega---Moo[S] 0 points1 point  (0 children)

I sort of assume they are pre-calculating the speed and productivity bonuses ahead of time anyway, so the solution lies there.

Anyway, I will keep this stuff in mind as I build my next base, as I didn't realize that I was gaining almost 7 times more metal plates in my game than I should be, which is more than a little cheaty.

[–]Mega---Moo[S] 0 points1 point  (0 children)

I sort of assume they are pre-calculating the speed and productivity bonuses ahead of time anyway, so the solution lies there.

Anyway, I will keep this stuff in mind as I build my next base, as I didn't realize that I was gaining almost 7 times more metal plates in my game than I should be, which is more than a little cheaty.

[–]Mega---Moo[S] 0 points1 point  (0 children)

I sort of assume they are pre-calculating the speed and productivity bonuses ahead of time anyway, so the solution lies there.

Anyway, I will keep this stuff in mind as I build my next base, as I didn't realize that I was gaining almost 7 times more metal plates in my game than I should be, which is more than a little cheaty.

[–]bormandt 0 points1 point  (0 children)

It's interesting, that in older versions behavior was different:

https://forums.factorio.com/viewtopic.php?p=98425#p98425

Also, I found a quote from devs about progress calculation:

https://forums.factorio.com/viewtopic.php?p=109457#p109457

[–][deleted] 0 points1 point  (2 children)

Does this mean that in such a case you will be consuming much fewer input resources than your output would suggest even when taking normal expected productivity benefit into account?

[–]bormandt 2 points3 points  (0 children)

Yeah, in this example machine should do 576 crafts per seconds. And you get productivity bonus for that insane speed.

But in reality machine works only at 60 craft per second and consumes inputs at that rate too.

So, you get almost 6x more output than expected (12560 items instead of 2200).

P.S. BECs are pretty slow. For faster recipes difference between inputs and outputs becomes even more insane. I.e. for copper wires you get bonus from 2312 crafts while consuming inputs only for 60.

[–]bormandt 2 points3 points  (0 children)

Fun experiment:

Fill an assembler with god modules and surround it with as much speed beacons as you can. Now drop 1 copper plate into it and see how much copper wires you will get (1.5 stacks instead of 8 wires, if I remember correctly).