So, for my first logic project, I decided to build a programmable factory that would maintain stock levels for multiple items. The factory is controlled by a single constant combinator that contains the minimum stock levels for the items; as soon as more items are needed, they (and their subcomponents) are automatically constructed and placed in chests. If a red signal is present, the factory pauses.
The end result looks like this:
The inner loop contains all the feedSTOCK; these are items produced outside the factory -- things like plates, and also items that require liquids to manufacture.
The outer loop moves all the assembled components and subcomponents around.
The core computational logic figures out what needs to be done:
In the hazard concrete is the ORDER chest, which contains the stock levels you want to maintain.
Coming up from the south is the INVENTORY, the sum of the contents of all holding chests.
A number of additional intermediate signals are computed; all of them are in the form MIN(A-B), so negative values don't propagate. EXTRA is the number of extra items in the boxes above our stocking levels. BUILD is how many items we need to build in order to meet our stocking requirements. NEED (coming up from the south) is what items we need in order to BUILD the items; it is computed by a recipe lattice (see below). Some of the NEEDed items may be in EXTRA inventory, so we may need to MAKE less than we NEED. If so, then we compute what items to EMIT from the boxes. Finally, we keep track of what items are on the outer "manufactured items" belt (more below) and use it to adjust our MAKE downwards and figure out how many items we need to ASSEMble; otherwise we would overproduce a bit because we wouldn't get updated on newly made items until they went around the loop and ended up back in the boxes.
ASSEM is sent off to control the inserters feeding the assemblers; EMIT controls inserters removing items from the chests.
The recipe lattice:
Note: this and some of the other images are from a prior version that didn't track the contents of the belt.
The lattice is pretty simple; for every item it has one or more combinators that compute the materials needed. In the case of items like copper wire where a single bit of raw material generates multiple items, 1 is added to the quantity needed before dividing, so it rounds up. The lattice loops back on itself, so that requirements from higher-level recipes propagate downwards until everything settles on a build order.
The belt counter:
Every inserter that places items on the belt is connected to a latch that maintains a running count of every placement. Similarly, every inserter that removes items is connected to a latch that keeps track of them. They report pulses. The removal circuit has the extra complexity that it also has to hold the commands to the inserters, and these need to be removed before going into the latch. There is an extra null comparator on the ASSEM input in order to balance the gate delays on the two legs of the circuit that end in the latch. The two latches are subtracted to result in a final BELT inventory.
The latches end up counting all the operations, so they could eventually overflow. It's my Factorio Y2K bug.
The inventory chests have filter inserters that grab everything they can. If a chest is commanded by EMIT to dump items back onto the belt, it puts them on a sub-belt and then another inserter moves them to the main belt; it is this inserter that does the counting. This is needed to keep the circuits separated.
The STOCK market:
This area maintains the supply of STOCK materials in the inner loop. The two rail wagons are used as sorters, each for 4 STOCK materials; they are dumped into it by multiple inserters, but extracted by a filter inserter associated with each stock chest. If the quantity in a chest goes below 200, the inserters at the far south dump the appropriate materials into the serpentine belt that puts them into the appropriate wagon.
All unused materials coming around the inner loop are put back into the wagons for restocking.
At the top of the STOCK market is the order computation logic. It gets the MAKE signals, and filters out just the STOCK items. If it turns out the resulting signal is empty, it replaces it with an "All items" signal.
This is then sent to the rate-limiter, which dumps out the required items, but waits after each cycle for the deposit area to clear; this prevents things from clogging up.
The end result is that if nothing is being built, the inner belt contains an even mix of all the STOCK items, but as soon as the factory starts building, the mix will change to just the items needed at any point in the build; this means that the assemblers on average will spend less time waiting for their inputs.
I look forward to your feedback; I am sure there are many simpler ways to implement these functions!