Factorio’s Belt Malicious program

Factorio is a manufacturing facility-building game keen plenty (and I indicate, LOTS) of conveyor belts. The code that implements these belts is marvel of optimization, but unfortunately they can no longer address every accomplish.

The Problematic Sushi Belt

The concern occurs when belts are organized in a loop. Within the origin, items positioned on the belt appear to work in general, circulating spherical like the bags return at an airport. But as quickly because the belt reaches stout ability, it stops.

So what’s occurring on?

I accomplish no longer have access to Factorio’s offer code, but I reckon I will be able to give a truthful explanation of why this happens. Imagine a simplified version of Factorio through which belts are single-lane and can take care of most productive one merchandise per tile:

To update, we’ll usually iterate over every merchandise on the belt, attempting to search out items that have an empty tile in entrance of them. As we obtain such items, we’ll circulate them forwards on the belt and proceed our iteration.

Sooner than:    
After:

If the tile in entrance of an merchandise is not any longer empty, we can no longer circulate the merchandise there but nonetheless it’ll furthermore very well be likely to circulate the merchandise at a special iteration. As an illustration, merchandise “A” under can no longer circulate till merchandise “B” has moved, and this could well furthermore grasp several iterations.

There are diversified orders one can iterate – some extra efficient than others – but for the sake of correctness, all that issues is sooner or later reaching a mounted point. The algorithm stops when no items could well furthermore very well be moved anymore.

Lastly, or no longer it is a ways a need to have that when an merchandise moves, it’ll furthermore no longer circulate but again till the algorithm completes. Otherwise, items will teleport in each set at inconsistent speeds. We will desire to ticket every merchandise that moves and exclude it from future iterations.

Sooner than:    
After:

Here is the pseudocode:

perform
    state MADE_PROGRESS to deceptive
    for every merchandise, I
        if I has no longer already moved
            let B be the belt under I
            let B' be the belt B outputs to
            if B' has no merchandise
                circulate I from B to B'
                model I as moved
                state MADE_PROGRESS to correct
whereas MADE_PROGRESS is correct
            

And here’s the algorithm running to completion, visualized:

The Factorio corner case

For an merchandise to circulate under this algorithm, it need to have a free set to circulate onto. But when the items are packed tightly into a circle, there could be no such thing as a free set and so the total belt jams up.

Yikes!

Fixing things with optimism

The algorithm above tries to set which items can circulate, pessimistically assuming that any merchandise it must no longer set, could well furthermore no longer circulate.
But what if we offer out the different? Take into fable an algorithm that with any luck assumes all items circulate, then proves which items can no longer.

So how will we offer out this? Successfully, if an merchandise is at the reside of a belt, or no longer it is safe to affirm that merchandise can no longer circulate. Under, we’ll model such items with a crimson “X” to set they can no longer circulate.

Sooner than:    
After:

Likewise, if an merchandise is blocked by one other motionless merchandise, it must no longer circulate either. As soon as we model a crimson “X”, the merchandise old to it’ll furthermore very well be marked to boot.

Sooner than:    
After:

This contemporary algorithm also runs till it reaches a mounted point. Then, all items with out a crimson “X” could well furthermore very well be moved forwards.

Whenever you happen to determine that algorithm out on a spherical belt, which that that you simply must model it completes without marking a single “X”! But here is true: all items in the belt will circulate spherical it, as none had been proven to be motionless.

Merges

Sooner than giving the pseudocode, there could be one thing that wants to be addressed. What happens when two or three belt merge together, as in the case under?

As outlined, the 2d algorithm will circulate both items onto the merged belt true now since it must no longer set either to be motionless. A malicious program! The staunch behavior, as handled by the first algorithm, is to most productive circulate one or the other; no longer both.

We can fix the 2d algorithm by defining a precedence for every merging belt. A decrease precedence belt tile shall be deemed motionless if an even bigger precedence belt has an merchandise on it. Under, belt “A” is the larger precedence one, and belt “B” is the decrease precedence one. “A” is occupied, so “B” desire to be motionless.

Sooner than:    
After:

For a game like Factorio, these priorities could well furthermore very well be switched every frame to evenly zipper the contents of both belts into one.

The closing pseudocode

The code under follows three steps.

  1. Address merges
  2. Charge motionless belts (the crimson “X”)
  3. Switch all items on belts no longer marked motionless

for every belt intersection, S
    state BLOCKED to deceptive
    for every enter belt to S, B
        if BLOCKED is correct
            model B as motionless
        if B has an merchandise
            state BLOCKED to correct

perform
    state MADE_PROGRESS to deceptive
    for every merchandise, I
        let B be the belt under I
        let B' be the belt B outputs to
        if B' doesn't exist or if B' is motionless
            model B as motionless
            state MADE_PROGRESS to correct
whereas MADE_PROGRESS is correct

for every merchandise, I
    let B be the belt under I
    let B' be the belt B outputs to
    if B is not any longer motionless
        circulate I from B to B'
            

Consultants and Cons

From a correctness standpoint, the 2d algorithm is superior, but one need to admit that it takes extra code and is much less evident than the first accomplish. It also complicates the implementation of different parts like inserters, factories, and chests, though this could well furthermore very well be a non-worry for greenfield initiatives. I suspect Factorio is scheme too developed to ever alternate their belt algorithm, but I’m hopeful more moderen video games will grasp the 2d scheme at my collect advice.

Or no longer it is a ways a need to desire to watch that the 2d algorithm most productive produces a usable consequence when the algorithm finishes. Nonetheless, the first algorithm could well furthermore very well be mosey incrementally. Every iteration moves the sport state from one right state to the following, which could well furthermore very well be actually helpful at events.

An spirited connection to compiler research

I wrote this article about Factorio, however the strategy is extra general than that. Flipping in each place in the concern and reversing what which that that you simply must furthermore be proving is a terribly actually helpful skill!

Within the origin, I realized of this scheme from a paper on compiler research: “Combining Analyses, Combining Optimizations,” by Cliff Click on. Ammusingly, the paper used to be also utilizing the strategy to manage with loops, albeit of the programming kind. For certain, Cliff Click on is not any longer the first particular person to take care of out this ranking of thing. Mathematicians have been having fun with it from moderately a ways encourage.

[Back to my homepage]

Read More

Share your love