Factory Logistics Simulator
No scheduler. A machine runs whichever of its enabled recipes it has the inputs and output room
for, and belts, rails, pipes and bots carry components between machines. Nothing assigns work to a machine. These
are the rules to build in the game; floor.js is the same model and tick, with no page code in it.
The tick
- Docks: each raw kind arrives at its rate into the dock giving it with the most room; while every such dock is full, it stops arriving.
- Machines: a run that has finished puts its outputs in the machine's output buffer. Then the first enabled recipe, in the machine's order, whose share holds its inputs and has room for its outputs starts and takes its inputs. One run at a time.
- Direct connections, then pipes, then rails (move, then load), then belts (move, then load), then bots (move, then send idle ones).
That order is the priority between carriers: where more than one could take the same component, the machine next door gets it, then a pipe, a rail, a belt, and a bot gets only what nothing attached to the machine took. Between a rail and a bot, though, the machines' priority decides: a bot for a machine that comes before every machine the rail would take the component to is sent before the rail loads - only a bot actually sent: with none free, the rail loads as it would. Rails, bots and pipes each serve demand by priority: the highest-priority machine first, then the one that has waited longest since it was last served. A belt does not choose.
The floor
- A grid of 1×1 tiles on three levels: the ground, where machines stand and bots walk; the belt and pipe level, one belt or one pipe to a tile; and the rail level over it, so a rail crosses a belt or pipe freely.
- A belt or pipe built across a belt or pipe goes under it: straight, down on a tile of its own before, under, and up on a tile of its own after. It goes only under something running straight across it, under at most the underpass limit of tiles side by side, never under a splitter, and clear of any other underpass. The underpass and both its ramps connect to no port.
- Bots walk the ground eight ways, never cutting a machine's corner, under any belt, rail or pipe. Machines, splitters, and an underpass with the tiles either side of it, are all that close a tile to them.
- What is put down goes in piles: one kind to a tile, on the nearest tiles with no machine, belt, rail or pipe, starting where it was. A machine placed on a pile pushes it aside the same way. A fluid is never put down: it is spilt and lost.
Machines
- Recipes: a machine type carries processes; a machine's recipes are those of its processes the player enables, none at first. The player's order of them is their priority: the first that can start runs, and an arriving component goes to the first with room for it. What a machine makes can go back into it, by any carrier, when one of its recipes takes it.
- Buffers: room for headroom runs' inputs and outputs of every recipe the type can run, shared out among the enabled recipes as the same number of runs each, as near as whole components allow (what is left over goes to the largest fractions, the earlier recipe on a tie). So a buffer is the same size whichever recipes are enabled, and each recipe's share is its own, even of a kind another recipe takes.
- Demand: a machine wants a kind while its enabled recipes' shares have room for it, less what is on its way. Rails and bots reserve room when they set off; belts reserve nothing.
- Shape: a type the Dropforge Database draws a layout for covers the layout's tiles, stands on its origin tile, and turns about it. Without one it is 2 tiles deep and as wide as its busier face, 2 at least, inputs on the back face and outputs on the front.
- Ports are solid (a belt or rail) or fluid (a pipe). With a layout they are where it draws them, two on a tile if it says so; each recipe's component uses the port the layout chooses for it in that recipe, else the first free port of its form going its way, reading the layout top to bottom, left to right, then N, E, S, W - the database's rule. A port is for every component any recipe sends through it, and what a recipe makes leaves only by its own port. Without a layout, each side has as many solid ports as the most solid components any one recipe takes or makes, three at most, assigned widest recipe first with each component keeping its port, then one fluid port for each fluid any recipe takes or makes. Either way a port is for set components, whatever is enabled.
- Bot ports: the layout's, any number, or without a layout one on the side to the left of the way it faces, at the output end. Bots deliver and collect only there, standing on the tile in front, at any bot port they can reach. A machine with none gets nothing by bot. Its bot logistics switch, on unless the player switches it off, is whether bots deliver to it and collect from it: off, no bot comes to it, and what it holds leaves only by its built connections.
- Taken away, a machine puts down its buffers and the inputs of an unfinished run where it stood, and spills its fluids. A bot bringing it something puts it down where the bot is; a rail component bound for it goes to another machine, or is put down.
The machines that are not processes:
- Dock: gives the kinds ticked on it. Line: takes the ticked kinds and counts them - what the floor made. Their buffers are the factory's space, shared among the ticked kinds, in place of headroom.
- Airlock: destroys the ticked kinds, taking them as any machine takes inputs, but never straight from a dock: no bot, rail or direct connection brings it anything from one. With sweep all and bot logistics on, bots may also bring it anything on the ground that no machine wants by bot, after every machine that does, from the ground only.
- Storage: keeps the ticked kinds, up to the storage size across all of them, and gives from that stock. Storage trades only upward: one fills from another only if its priority is higher. It keeps no fluid. Where the database draws a storage or airlock layout it takes that shape, each port for anything of its form.
Carriers
| Belt | Rail | Pipe | Bot | |
|---|---|---|---|---|
| Carries | Solids | Solids | One fluid per network | Solids |
| Takes | From each output port it starts at or runs past: the oldest component that port gives, when its segment there is free and nothing straight behind has one ready | From each output port it starts at or runs past: only what a machine it reaches wants, reserving the room | From the machine on the network holding the most | From a pile or a machine's bot port, by the rules below |
| Gives | Into an input port it points into or runs past, if the port is for it and the machine has room | Into the port it was loaded for | As much as the machine has room for | Through a bot port |
| Splits | Only at a splitter | Anywhere | Anywhere: no direction | |
| Merges | Into a gap a spacing wide: the run's own flow first, then what joins it, first built first | By turns, skipping a way in with nothing to send: an output port sends only what a machine the rail reaches wants | ||
| Moves | Belt density components a tile, touching when full, at belt speed | One component a segment, at rail speed | An amount, at once, at most the pipe rate along each pipe run | The shortest way, at bot speed, plus the pickup time |
- Belt: keeps to its one way on, and what it carries is on its runs. A run goes from where the belt starts - an output port, a splitter, or a tile nothing feeds - along its way on, and on through a tile other belts join, as that tile's first way in (the one straight behind it, or else the first built); the others end there. It ends at an input port, a splitter, the side of another run, or nothing; or it is a loop. Its components keep one over the belt density of a tile apart, so on a full belt they touch, and each moves on at belt speed until the one ahead or the run's end stops it, the belt backing up behind. What joins a run - another run's end, an output port beside it, or the port or splitter it starts from - puts a component on only into a gap of that spacing either side, so a steady flow along a run is never broken into. A machine whose input port a run passes takes first what it wants and has room for. A belt carrying mixed kinds jams at the first machine without room for the one at its front.
- Splitter: a belt tile the same whichever way it faces. Its ways in are the belts ending in it and the output ports facing it; its ways out, the belts starting beside it that nothing else feeds, and the input ports facing it. A belt running past it is not joined to it. It takes its ways in by turns, and each way in deals to the ways out by turns of its own, skipping one that is backed up. A component on a tile with more than one way out picks one as it passes the middle: the first not backed up. It holds a tile's worth. Bots go round a splitter and nothing goes under it.
- Splitter priority: any side of a splitter can be marked priority, and the mark stays with the splitter whatever runs on that side. A priority way in goes before the others, which move only when none of the priority ones has something waiting. A priority way out is used whenever it is not backed up - one that is only busy, its belt still moving, is waited for - and the others only when every priority one is. Several priority sides take turns, so marking every way in, or every way out, is the same as marking none.
- Rail: a component goes the shortest way to the port it was loaded for, only ever one segment nearer, so it never crosses a segment twice. One whose machine is gone or out of reach goes to another machine the rail reaches that wants it, or is put down. A rail never jams. A belt and a rail may share a solid port; the rail loads first.
- Pipe: a fluid is an amount and a pipe holds none. Where pipes meet, end or touch a port is a node; the pipe between two nodes is a pipe run, carrying at most the pipe rate either way. A network carries the one fluid its output ports give that its input ports take, by the enabled recipes; one that would carry two is not built, and if enabling a recipe later makes it so, nothing flows until that is undone. Each tick the machines wanting the fluid are served in priority order, each getting as much as the pipe runs can still bring it.
- Direct connection: an output port facing an input port of the same form, machines side by side. Everything both ports are for passes straight across at once, as much as the second machine has room for, fluids included.
- A loop, belt or rail, that fills up moves round as one. A loop through a splitter does too. A belt run that ends by joining itself can fill up and stop, as a real belt would; a splitter where it meets itself keeps it turning.
Bots
- Bots never do a built connection's job. A connection brings a machine a component when a belt or rail on a port for it is fed by a machine giving it, or a machine giving it is connected directly. It takes a component from a machine when a belt or rail runs on from its port to a machine that takes it, or a machine taking it is connected directly.
- A machine with bot logistics on, and no connection bringing it a component it wants, gets it from the nearest pile; with none, the nearest machine with bot logistics on that no connection takes it from; and only with none, the nearest such machine a connection takes it from - what the connection leaves, since it takes first, unless the connection is rails alone and the machine comes before every machine they would take it to. A machine a connection brings it also takes it by bot, but only from a pile or such a machine no connection takes it from.
- The nearest idle bot goes, from no further than 10 tiles plus bot speed × the seconds the machine has waited, so the longer it waits the further a bot will come. At most 24 are sent a tick.
- Where a bot is wanted at a bot port it cannot reach, a warning names what is in the way: "A bot is trying to reach X to deliver (or take) Y but cannot due to obstruction by Z". A machine with no bot port says "X needs a bot to deliver Y, but has no bot port".
Building
- Belts and rails run one way, the way they were drawn; a pipe has no direction. Ports are sticky: a belt, rail or pipe on the tile in front of a port it fits connects to it, whichever way it runs. Nothing may point into an output port, which it could not connect to, and a machine may not be placed where something would.
- Ending a belt on a belt merges into it, but a belt branches only at a splitter: drawn off any other belt it starts beside it, not joined. A splitter is placed on a free tile or over a belt, keeping where that belt went. Starting a rail on a rail splits it, and ending on one merges. Starting or ending a pipe on a pipe joins it. Loops are allowed; a belt or rail cannot be drawn ending in one that points back into it.
- A belt's or rail's run is selected, removed and flipped whole, with the ports it runs past part of it: a belt's as above, carrying on through where others join it, and a rail's between nodes - a merge or a split. Flipping turns every tile round, and what is on it, each component staying where it is; what joined it still joins it, and nothing at either end changes, so an end that took from a port or node now points back into it, joined to nothing; one that pointed into a belt or node starts beside it, not joined; and one that pointed into a machine starts beside its port, which takes from it as from any belt running past. Flipping twice puts it back exactly: the first tile keeps which way its end pointed, where what is beside it would not say.
- Copying settings: a machine's settings - the recipes it has on and their order, or the kinds ticked on it, its priority, bot logistics and sweep - can be copied and pasted onto another machine, as far as it has them. A process machine takes the choices for the recipes its type shares, in the copied order, and keeps its others. A dock, line, airlock or storage takes the kinds ticked, or from a process machine the kinds its recipes take (onto a dock) or make (onto the others). Priority, bot logistics and sweep go where both have them. A machine picked up with its settings and built over one of the same type gives it all of them; it keeps where it stands and faces. A splitter's priority sides copy onto another splitter, side for side.
- Shown on the floor: a gap wherever a belt or rail is not joined to what it touches, and a scoop - a lip from the machine over the belt's edge - where a port takes from, or drops onto, a belt running past it. A belt tile turns as it needs to: where a belt starts at an output port, or ends at an input port, its tile is drawn joined to the port whichever side the port is on, and so is a rail.
From the Dropforge Database
- Components, each solid or fluid (what the data calls loose is solid); recipes, a process with inputs, outputs and a time; machine types, with their processes, a layout - tiles, typed ports and each recipe's choice of port - and a category; milestones, which give the tiers.
- The build bar groups by the database's machine categories, after Logistics (belts, rails, pipes, splitters, storage, airlocks) and Inputs & Outputs (docks, lines), in the order a player meets them: by the first tier any machine in one is had at. A machine with no category is Misc.
Factory settings
| Setting | Default | What it is |
|---|---|---|
| Headroom | 3 (1-10) | Runs of every recipe a machine's buffers hold |
| Space | 12 | A dock's, line's or airlock's buffer |
| Storage | 30 | A storage's stock, across its kinds |
| Underpass limit | 1 | Tiles a belt or pipe may go under side by side |
| Pipe rate | 6 a second | What a pipe run carries |
| Belt speed | 1 tile a second | |
| Belt density | 2 a tile (1-4) | Components a belt tile holds: a belt carries speed times density a second |
| Rail speed | 4 segments a second | |
| Bots | 6 | How many, starting from the factory's home tile |
| Bot speed | 4 tiles a second | |
| Pickup | 0.5 seconds | A bot's time to collect |
Not yet
- Rail carts: a rail moves components one a segment, as a belt does.
- Filters, on belts or splitters: a splitter sends any kind any way, and mixed kinds go by rail.
- Tanks: a fluid waits only in the machines at either end.
- Fuel: the database gives a machine's consumable a port; nothing uses it yet.
- Bots on big floors: finding their way is most of what a big floor costs a tick.