Hacker News new | ask | show | jobs
by bmgxyz 1950 days ago
I wonder how difficult it would be to implement a language for specifying Factorio factories without worrying about physical layouts. This post provides a lot of good insights into how that could be done. Once a factory is specified, a compiler could turn the high-level specification into a blueprint or a valid save file to be loaded up in the game.

Of course, the compiler would have no way to lay out the factory with respect to available resource deposits. Maybe that would have to be part of the specification as well? Or maybe the programmer (player?) could pass an empty map file as a compiler argument.

Also, this doesn't give any consideration to the tech tree or enemies within the game. I guess those could be compiler flags, as long as we're dreaming.

Look, all I'm saying is that it would be really cool to be able to check factories into version control.

15 comments

I actually made this, a factory "compiler" that takes in a target output (eg. 1000 science / minute), and lays out a blueprint working from raw inputs to the desired output. It's hacky and buggy (and by this point probably out of date) but you can see it here:

https://github.com/ekimekim/factoriocalc/tree/generator

The factory it generates is a main bus design, with discrete "steps" on the bus that take certain inputs, process them in a standardized area, then put the output onto the bus. It also stops every so often for "compaction" where it reduces several low-throughput belts into fewer high-throughput belts. The whole area is covered by roboports to enable automated construction (no logistic robots are used, production is entirely done by belt) along with power lines etc.

The full layout looks like this:

    ||bus||
    |||||||  ...beacons...
    vvvvvv\-> input to process
    ||||||
    ||||||/-- output from process
    |||||||  ...beacons...
in a repeating pattern, each process step sandwiched between two lines of beacons.

It is very much not optimised, the idea was to make something as simple as possible that would work.

There's also a blueprint-to-ascii-art renderer which I added to help debug layout issues.

I haven't played factorio in a while but I do plan to keep working on this. Due to some poor choices early on implementing the last few fiddly (and less interesting) bits ended up being the bottleneck. In its current state it can go from raw inputs to a full suite of science packs, though some of the recipes are probably out of date, and I think there's some bugs in a few of the layouts that manifest in the finished blueprint as belts the wrong way around, etc.

Oh it's a python app. I read `virtual factory constructor generator` and assumed it would be Java.
This sounds interesting! I would love to read a post about this. (I am currently working on automatically generating belt balancer layouts, but that is an entirely different beast.)
Yeah, I should write up how it works. There's a README but it was written as an initial plan of attack and the results didn't always reflect the original plan.
Just wanted to say that this is awesome.
Personally I think most of the game is actually about managing changing requirements and layouting, but there's certainly a subset of gamers that are after the perfect endgame base (the X science per second crowd). If that's the target group of the compiler then you can assume that enemies don't exist (they waste CPU power), resources are decoupled from the factory using trains (they run out too fast for tight integration) and that the entire tech tree is explored (everything before that is just a unimportant bootstrap base). Making those assumptions certainly makes the compiler more tractable, but it also gives you another interesting metric to optimize (CPU load of running the produced layout)
If you can make some assumptions like train length and loading/unloading station design, you can probably guess how many trains you need to supply a given design, which means you can probably automate the placement of resource collection outposts.

You'd need some empirical data on train acceleration and top speed, but once you have that plus some generous assumptions about latency tolerances, you can probably automatically lay out tracks and train routes and resource outposts.

Laying out the perfect Factorio game would be akin to laying out a high performance super scalar out of order cpu. CPUs are math factories.
There was a poster a while ago that designed a series of mods that would automate the sprawl of his base. It would detect ore patches and set up mining and train loading.

https://forums.factorio.com/viewtopic.php?t=41377

Did we just automate automation
Welcome to Factorio, the game where the goal is to automate your automation of automation.
I’m a beginning megabaser myself. For how engrossing Factorio is, the vanilla gameplay to the end of the tech tree is just not enough ;)

At some point, the inserter-to-belt interface becomes a serious bottleneck. CPU load does too. As for enemies, you can basically treat them as a solved or solvable problem after artillery even if you don’t turn them off.

Such a language could be an extension of VHDL or verilog (or more likely, just a library in such a language). The map could plausibly be the equivalent of an FPGA architecture, and build upon existing tooling. Caveat: I'm a bit of an FPGA noob and have zero clue how one specifies a detailed FPGA fabric to such tooling.
No, you are right. One would likely need to define more logic types to be fully accurate, but those could be abstracted away.

Just connect blocks A and B in some hardware description language. Further describe B as an assembly of blocks A and C.

Ask a compiler such as yosys to flatten your hierarchy down to a set of primitive blocks (say, A and C). Once you have the diagram, use a custom placer and router to position it.

There might be additional constraints while placing blocks. In silicon, this relates to impedance, design rules, and making sure the clocks are properly synchronized (adding buffers, etc). In factorio, this could be making sure conveyors are the same length, placing extractors on resources, etc. But the general topology doesn't change, since you are the one specifying it.

Note: I've done some, but very little logic synthesis, this is really a bird view.

I have a somewhat nooby question about Verilog:

Does Verilog allow the description of throughput or a capacity constraint? I'm imagining a situation where a specific component (or belt) can only allow so many messages per second or needs less than a specified amount of current. Or is this concept somehow handled in a different way when specifying circuits?

I am the latest in a chain of noobs in this thread, but I think what you're talking about is handled by clock cycles. Components use the clock to gate the flow of information down lanes.
Yeah, usually you want to sync everything with the same clock.

Verilog and VHDL allow specifying delays, which is basically troughoutput. Basically:

    when input changes:
        computed_output = f(input)
        after 10ps:
             actual_output = computed_output
That's not actual syntax, mind you, I am a bit rusty for this. But the idea is that you either make sure every delay fits in your clock period, you use different clocks, or wait a few clock cycles to sync everything (which is the same as having different clocks).

Of course, you can oversize a capacitor to drive a high-capacitance line faster, and that would require more current. I don't think logic synthesis tools can handle that sort of compromise yet.

This is also why non-sequential (no clock) logic is hard: you would likely need synchronization signals so that the rest of the circuit knows when it can change the inputs (maintaining those during setup and hold times is necessary to guarantee valid output... try changing the input numbers while you perform a multiplication by hand).

And that class of issues is likely not a problem at all in factorio: I have only played mindustry and infinifactory, but I guess that factories do not run until they have the right input materials? Control signals are already there, in the form of {material present, material absent} on the belt, and factories are already fully-fledged state machines.

The belts are horrible little buggers. They've got two sides, which get out of sync going around turns. But ultimately, factorio runs on a common clock, and the belts are state machines and should be modeled as such.
There was a game way back on the TRS-80(?) - I think it might have been called "robots" - and you had to program these robots to do things based on logic gates... (I can't recall the details, but surely some HNer will)

---

It would be cool to have a CPU/GPU/Circuit design game that literally made a game out of designing logic gates and instructions as a game - but based on real-world circuit design....

Do you mean Robot Odyssey: https://slate.com/technology/2014/01/robot-odyssey-the-harde... ?

As for your idea, Zachtronics had one for a while, but it was flash, so I don’t know if it still exists.

YUP!!!!

Thats the one

I thought you meant TIS-100 which is also a game by Zachatronics where you write a basic assembly to solve puzzles:

https://store.steampowered.com/app/370360/TIS100/

You absolutely can check factories into version control. They are exported as 'blueprints' and many blueprint management sites exist. One such example: https://factorioprints.com/
That's not quite as satisfying as text-based files managed via proper version control
"infrastructure" as code :)
"supply chain manufacturing as code"
Blueprints are text-based, though.
This is about as meaningful as saying base64 encoded pngs are text based.

Most tools operate on the compressed, binary header including, base64 encoded blueprint strings, not the raw blueprint JSON payload.

base64 is an encoding, and a base64-encoded PNG is still an image. Factorio blueprints are base64'd deflate'd JSON with a small single-byte header[0].

It would be comically trivial to setup a .gitattributes filter[1] to do the conversion for you on checkout (to the base64 form) and commit all JSON, allowing for beautiful diffs.

It's a bash one-liner[2] to turn JSON into their base-64 form and into your clipboard anyways.

[0] https://wiki.factorio.com/Blueprint_string_format [1] https://git-scm.com/docs/gitattributes#_filter [2] left as an exercise for the reader

Hardware description languages such as VHDL/Verilog feel very similar to Factorio in that "everything is happening at the same time in parallel". Definately takes a while to wrap your head around it coming from procedural languages.

The "compilers" for these languages have very sophisticated "routing" algorithms which synthesize efficient physical layouts of circuits.

Programs like Quartus even let you edit your description visually as an abstract block diagram by dragging around wires/placing blocks.

As an (technically) EE who studied mostly CS courses (and worked in software engineering since), that's something that's really (occasionally) bugged me with software, especially when deliberately choosing asynchronous (in the broadest concurrency-inclusive sense) patterns and syntax. It just seems so... much harder?

Electronics is just inherently 'parallelised', and software generally isn't, I get that. But some how we built up from parallel hardware to procedural synchronous (I know it isn't all but let's be honest it ~~all is) software, then built up further to sometimes wanting parallel again, and it's just sort of hard (er than it seems it should need to be) to use?

I challenge anyone who's used exclusively procedural languages to try an HDL (like Verilog or VHDL) or at least a high level declarative language (like Prolog or HCL/Terraform, as long as you view it as a language rather than config files) and not feel refreshed.

> Programs like Quartus

Egh, if I have nightmares tonight I'll know why!

Most folks will have used a least a little declarative programming if they're ever interacting with a DB - you can drop out into procedural land using cursors and functions but SQL really shines when you tell your DBMS what you want and let it figure out the details itself.

Building complex logic ins declarative languages is one of the most rewarding things I've ever done. I tend to prefer a strong focus on type transformation when approaching a problem in any paradigm (I'd tend to read "Get the user's name" as "Create a transformation from a User ID to the User's Name and then cast the value") but just putting all the blocks for declarative programming together and then saying "Now, go!" is quite satisfying.

If you use a language that lets you program in terms of data rather than operations this principle can be applied to programs - it's a hard problem, however.

Clock signals do seem like a very useful abstraction (when I have my software-hat on) - not sure how you'd do it for a general purpose CPU however.

I have been day dreaming about a program taking a factorio blueprint and running it through a genetic algorithm to produce a compressed but still functional version. I can imagine it could produce some interesting spaghetti layout! One way to ensure that the end result still works the same would be to only let the algorithm work with a selection of predefined refactoring steps that guarantee that the factory does not break. Another maybe more interesting approach would be to include some actual simulation that could test the factory. With the simulation the algorithm could work more freely with possibly destructive changes and apply them until the factory works as expected. This I figure would produce even more interesting spaghetti..
There's a haskell project called Clash[1] that produces VHDL/Verilog that gets pretty close to this for FPGA development. [1]https://clash-lang.org/
Bluespec is also based on Haskell and is now open source
This will take a specification: https://kirkmcdonald.github.io/calc.html#tab=graph&data=1-1-...

But 98% of the problem remains: generating a layout.

I don't think it's actually that hard, as long as you don't try too hard to optimize the layout itself. Write a few heuristics into the system and you can get really close to the thing you're describing. Most of the throughput modeling is pretty straightforward from an algorithmic perspective.

This probably gets the most interesting in the super-late game where players have unlocked all of the tech and are building megabases. Now that the making of everything has been automated, perhaps the building of everything should be automated as well.

I think optimizing layout or at least attempting to minimize the amount of crossed conveyors is most of the issue.

Comparing Factorio to Satifactory (basically a simpler Factorio but in 3d space) - component layout gets a lot easier to optimize since you can essentially float rando chunks of logic in random parts of the sky - Factorio does have an interesting mod[1] to allow what's essentially a black-box subroutine but the majority of the headache is trying to build a relatively compact (and thus defensible) layout while also allowing yourself the room to re-tool the setup as needs change.

Building absolutely can be automated - there are a lot of self-replicating structures out there, most of which automate the forward deployment of defenses since that's a real issue you're going to need to deal with.

1. https://mods.factorio.com/mod/Factorissimo2

I think optimizing layout or at least attempting to minimize the amount of crossed conveyors is most of the issue.

Yup that's exactly what I was thinking about. If you don't have to optimize, then you can mix and match heuristics to get the job done. If you have to optimize... now the search space gets real big real fast.

I work with a rather complex database in my day job and occasionally maintain a very human-oriented ERD for employee education - I've looked at various auto-ERDs in the past and failed to find one that can actually produce a decently pleasant visual diagram as output - most of them will just give up on the task and lay tables out in a roughly hierarchical display based on distance from a relatively core table and then let links between tables lie where they may.

Optimizing layout is a very interesting problem and one interest component in Factorio in particular is that you have some real values to measure as output like:

1. Total space used

2. Total energy required (more inserters means more power - more belts usually means more space)

3. Throughput

4. Pollution produced

5. Tile-ability of the design.

6. Proportion of unused space within a bounding box

Probably a few other fun ones - it actually sounds like a pretty approachable problem to get objectively good results out of.

It could take inspiration from some speedruns formats where the "seed" is pre-selected. That way you could have multiple people compete to write the most efficient factory in terms of resources and space to generate as many rockets as possible, and everyone with the same resource limitations and map layout!
I’ve been noodling away on this related question:

Given that sub factories in Factorio can be graded numerically on units/s output, and given that Factorio has a built in blueprint system, could one use ML to automatically create the most efficient blueprint possible for a given output?

Probably. The ratios are well known and easy to compute but it gets interesting with upgrade modules and effect transmitters. So you can for example trade power consumption for higher throughput. But belts only support so much throughput so you can only feed an area with so much resources, so you chain assemblers with direct insertion.

This would be a great application for ML or genetic programming.

I really want to see a factorio app with a pipeline that takes an HTTP request as input and eventually converts it into a useful JSON at the end.
Not too far off from circuit design languages (VHDL, Verilog) to me.
It sounds like it would be really easy to make a game like that, without the hassle of a 2D grid.
"Fractorio"