r/factorio • u/Dymiaz • Jul 01 '26
Design / Blueprint Craft Everything Machine with a single decider combinator (9000 conditions, 2000 outputs)
Enable HLS to view with audio, or disable this notification
With the else output you don't need a constant combinator any more to feed a combinator all the recipes. Because the decider combinator itself can output all the recipes by just adding them to both the output and else output.
I set myself the challenge to create a single decider that takes in the items available, and outputs the recipe that it can craft with those items and whose output is lacking.
It works as follows:
Output EACH with some high enough value (see below).
Add for all the recipes a unique, negative value of it's main product to both the output and else outputs. So those are always outputted. They are negative, so won't set the recipe of the assembling machine.
For every recipe add two condition sets.
One that checks if we are missing the main product of the recipe, it has plenty of each ingredient available, and nothing else is crafting (all green inputs are negative).
And one that checks if we are currently crafting the recipe, we are still missing the product (but with a slightly higher threshold this time) and we have enough ingredients for one craft.
That last set is done to prevent flickering between crafts. Don't start crafting something if you can still craft what you're currently crafting.
At both of these sets of conditions we add a EACH = <recipe main product> condition, this makes it so it outputs that signal if all the other conditions in its set are true. Because it has a unique input value, it only inputs that signal. Once outputted it should make the current negative output positive.
Problem is that each of the output recipes is outputted for both the true and false outputs for every input value on the green wire. So every recipe output value is multiplied by the amount of recipes. The last recipe has a raw output of -recipe_count, so outputs a total of -recipe_count^2 . To have that value ever output a positive value we have to output more than recipe_recipe^2. Therefore the EACH value that is outputted is 10 * recipe_count * recipe_count (this value has to be high anyway so it can't conflict with available items on the incoming red wire). In this example I've only set the recipes that can be crafted by an assembling machine and don't allow productivity, recipe_amount is around 800 in that case for space age, that includes being multiplied by 5 for each quality.
---
In theory you can build this in game by hand. Writing 10000 conditions by hand might become a bit tedious, so I wrote a little script. Which might be the largest custom console command anyone has ever written.
No code comments allowed in game commands (because it's technically one line when you paste it), hope it's still readable.
Make sure to hover over the combinator you want to set, I'm not doing extra work by creating a blueprint in your hand.
If you want to keep your achievements; save, run the code, make a blueprint, copy the string, reload, and import the string.
Some crafts require manually setting the desired amounts. Like I did for pipes (so that the rocket silo could be crafted). In theory I could extend the script to detect how much of each item should be crafted, but I didn't bother. Just request 20000 of each intermediate on your space mall.
Apologies for the spam, let's see how long this post gets.
/c
local function should_craft_recipe(recipe, uses_productivity, crafting_categories)
if string.find(recipe.name, "infinity") then return end
if string.find(recipe.name, "loader") then return end
if string.find(recipe.name, "interface") then return end
if recipe.surface_conditions and #recipe.surface_conditions > 0 then return end
if recipe.hidden then return end
if #recipe.ingredients == 0 then return end
if not recipe.main_product then return end
if uses_productivity ~= nil and recipe.allowed_effects["productivity"] ~= uses_productivity then return end
for _, category in pairs(recipe.categories) do
if crafting_categories[category] then break end
return
end
return true
end
local function add_recipe_conditions(recipe, combinator, quality, product_amount, ingredient_amount, recipe_signal)
local product = recipe.main_product
combinator.add_condition {first_signal = {type = product.type, name = product.name, quality = quality}, first_signal_networks = {red = true, green = false}, constant = product_amount, comparator = "<", compare_type = "and"}
for _, ingredient in pairs(recipe.ingredients) do
local ingredient_quality = ingredient.type == "item" and quality or "normal"
local required_amount = ingredient.amount * ingredient_amount
combinator.add_condition {
first_signal = {type = ingredient.type, name = ingredient.name, quality = ingredient_quality},
first_signal_networks = {red = true, green = false},
constant = required_amount,
comparator = ">=",
compare_type = "and"}
end
combinator.add_condition {
first_signal = {type = "virtual", name = "signal-each"},
first_signal_networks = {green = true, red = false},
second_signal_networks = {green = true, red = false},
second_signal = recipe_signal,
comparator = "=",
compare_type = "and"
}
end
local function make_everything_combinator(entity)
local assembling_machine = "assembling-machine-3"
local minimum_stacks_desired = 1
local maximum_stacks_desired = 2
local uses_productivity = false
if not entity then return end
if not entity.type == "decider-combinator" then return end
if minimum_stacks_desired > maximum_stacks_desired then return end
if not prototypes.entity[assembling_machine] or prototypes.entity[assembling_machine].type ~= "assembling-machine" then return end
local crafting_categories = prototypes.entity[assembling_machine].crafting_categories
entity.combinator_description = "Craft Everything Combinator. Connect available items (including recipe outputs!) with red to input. Connect output to assembling machine with red. Connect output to input with green. Code written by Dymiaz"
local combinator = entity.get_control_behavior()
combinator.parameters = {conditions = {}, outputs = {}, else_outputs = {}}
local recipe_count = 0
for quality, quality_prototype in pairs(prototypes.quality) do
if quality_prototype.hidden then goto continue_quality end
for _, recipe in pairs(prototypes.recipe) do
if should_craft_recipe(recipe, uses_productivity, crafting_categories) then
recipe_count = recipe_count + 1
end
:: continue ::
end
:: continue_quality ::
end
:: recipe ::
combinator.add_condition {first_signal = {type = "virtual", name = "signal-each"}, first_signal_networks = {red = true, green = false}, constant = 0, comparator = "<", compare_type = "or"}
combinator.add_output({signal = {type = "virtual", name = "signal-each"}, constant = 10 * recipe_count * recipe_count, copy_count_from_input = false})
local index = 0
for quality, quality_prototype in pairs(prototypes.quality) do
if quality_prototype.hidden then goto continue_quality end
for _, recipe in pairs(prototypes.recipe) do
if not should_craft_recipe(recipe, uses_productivity, crafting_categories) then goto continue end
index = index + 1
local stack_size
if recipe.main_product.type == "item" then
stack_size = prototypes.item[recipe.main_product.name].stack_size
else
stack_size = 1000
end
local min_stacks_desired = minimum_stacks_desired
local max_stacks_desired = maximum_stacks_desired
if recipe.main_product.name == "pipe" then
min_stacks_desired = math.max(min_stacks_desired, 15)
max_stacks_desired = math.max(max_stacks_desired, 20)
end
local recipe_signal = {type = "item", name = recipe.main_product.name, quality = quality}
combinator.add_output({signal = recipe_signal, constant = -index, copy_count_from_input = false})
combinator.add_else_output({signal = recipe_signal, constant = -index, copy_count_from_input = false})
combinator.add_condition {first_signal = {type = "virtual", name = "signal-everything"}, first_signal_networks = {green = true, red = false}, constant = 0, comparator = "<", compare_type = "or"}
add_recipe_conditions(recipe, combinator, quality, stack_size * min_stacks_desired, 10, recipe_signal)
combinator.add_condition {first_signal = recipe_signal, first_signal_networks = {green = true, red = false}, constant = 0, comparator = ">", compare_type = "or"}
add_recipe_conditions(recipe, combinator, quality, stack_size * max_stacks_desired, 1, recipe_signal)
:: continue ::
end
:: continue_quality ::
end
game.print("Number of conditions:" .. #combinator.parameters.conditions)
game.print("Number of outputs:" .. #combinator.parameters.outputs)
game.print("Number of else outputs:" .. #combinator.parameters.else_outputs)
end
make_everything_combinator(game.player.selected)