Hacker News new | past | comments | ask | show | jobs | submit login
Functorio (bartoszmilewski.com)
697 points by ibobev on Feb 16, 2021 | hide | past | favorite | 193 comments



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.


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"


I can definitely see the point the author is trying to make, and I agree that it naturally lends itself to a functional model of how the game works.

On the other hand, and this is speaking as someone who has played the game for an embarrassing number of hours all the way into endgame "megabase" territory: my mental abstraction of the game isn't really functional. It's directed graphs. Sure, the two views can be equivalent representations, but I find thinking about the game as a directed graph (and reasoning about throughputs in a graph representing a network) to be the perspective that gives actionable insights most readily.


It also seems to me that the author is conveniently ignoring the mechanics that aren’t mapping well to FP. To me, belts and buffer chests are much easier to describe as a mutable data structure (FIFO queues). That’s also analogous to how real world applications typically look like: functional core / imperative shell (see also Gary Bernhard’s brilliant ’Boundaries’ talk). It’s a nice article to introduce FP but I get immediately suspicious about statements like ‘Engineering is FP’. FP is a tool, not a unified theory on how to model the world.


FP is a unified theory on how to model the world: as functions, where equivalent inputs will always produce equivalent outputs. If there's something that makes outputs inequivalent, you should (under this theory) represent that with a corresponding input.

It's not the only possible way to model the world, but it absolutely is a unified approach that you can apply to a whole system, and it tends to work better when you do - trying to apply "FP as a tool" within a fundamentally mutation-oriented system (for example) gets you a very limited subset of the benefits, IME.


Real world is dirty. It needs logging, I/O, etc. Yes you can model those with monads in Haskell, but what happens much more frequently is that you’re in a team of Java/Python/Js/C++ programmers and you want to profit from some of the benefits of FP at least (testability, composeability). And that is where the perfect becomes the enemy of the better if you then just give up because you can’t get your single paradigm FP language. As a modeling tool however it is still very powerful, as are some aspects of OOP.


What does a functional Python look like?

To me, a functional language without tail recursion seems pointless. Is it possible to abstract away whether you are recursive or iterative, like an iterative recursion scheme?

One thing that I think would be great is if there was a Python approach to effects systems like Polysemy (free monads); what might an in between be for this?


I don't think Python's type system is capable enough (yet) for something like this. However tail recursion optimization to me is a non issue - for something expensive and deeply nested I use an iterative approach, and for everything else python's recursion is good enough. There are not that many usecases like this per code base anyways, in my experience. In my current one there is one central facility to do object loading based on yaml definitions, that's the one place I need it there for example.


> To me, a functional language without tail recursion seems pointless.

Tail recursion is a low-level detail IMO. Scala does fine without it.



In my experience a codebase that crisscrosses back and forth between FP and mutation-based style ends up worse and buggier than one that commits fully to one or the other; it's not perfect being the enemy of better because it's not better.


Criscrossing backwards and forwards would be bad, but the 'functional core, imperative shell' does work well. It is an excellent fit for Erlang/Elixir - you write a lot of pure functional logic (with the equivalently easy tests), and then you 'glue' it to the outside world with as little process machinery and statefulness as possible.

We are in Erlang though, so I wouldn't call it 'mutation' necessarily. The stateful bits are individual actors, creating a new internal state in response to messages.


I think it needs to be thought of as part of an overarching design - again, see Gary Bernhardt. A pure functional core that can be unit tested against, where the tricky logic happens. And a shell where you deal with dirty but dumb things like thread pools, logging, error handling, non-pure libraries etc. And then just be very diligent to separate concerns, i.e. don't put too many smart things into the shell.


> I think it needs to be thought of as part of an overarching design

Right. Which is very much opposed to your initial "FP is a tool, not a unified theory on how to model the world".


I don’t think it is? I don’t see the contradiction. My point is FP, imperative and OOP can be combined effectively in one architecture.


They can be, but you need to adopt a particular global perspective/worldview to make it work. Treating FP as just a tool in the toolbox that you can use ad-hoc anywhere in the codebase is not effective.


"Functional core, imperative shell" is exactly what IO in the Haskell type system enforces.


I think the core of the issue is that, while you can take a FP based view on how Factorio works, typically the interesting problems to model in Factorio aren't really "FP" problems. They're not really "imperative" problems either. Really, I don't think they're programming problems, even if they kind of look like programming problems.


> speaking as someone who has played the game for an embarrassing number of hours

I enjoyed reading that line - made me chuckle :) Would you mind sharing what it is that keeps bringing you back to play?

I'm a grey beard programmer, husband, father, and vanilla Linux kinda guy - and I've seen Factorio being mentioned on this forum quite a bit over the years. The chatter here today has once again piqued my interest to say the least.

I was once an avid gamer in my youth, but these days I have little free time - so if I were to pick up a game, it would have to be the sort of experience that I can play for a few minutes here and there (and / or immerse myself in for several hours at a time when the opportunity arises). It would also need to run smoothly on Linux, and be relatively easy on computing resources.

I tried Minecraft for a bit - and it ticked most of the above boxes - but I didn't much enjoy the interface and lack of "systems" if that makes sense. I love building things, but I also just enjoy sitting back and watching systems work. I prefer top-down planning / building games like the Sim City of old but that got boring pretty quickly.

Anyhow I think I oughta just install Factorio and check it out - but I'm deeply curious what it is that keeps bringing you back for more.


> Anyhow I think I oughta just install Factorio and check it out - but I'm deeply curious what it is that keeps bringing you back for more.

There's a demo version which gives you a pretty good idea of how Factorio feels. I forget whether the demo runs on Linux, but the full game is straightforward to run on Linux, by which I mean I forget whether you need an emulation layer.

> Would you mind sharing what it is that keeps bringing you back to play?

To be fair, I did reach the "I'm done with Factorio" point. I have one last hurrah of getting one last accomplishment in progress, and then I'm realistically done with the game.

But to answer your question: it's because Factorio's systems are extremely deep, where the nature of the puzzles and the way you think about them keep evolving. And as you solve those problems you get the satisfaction of seeing those systems working. It's the same high I get from seeing my code work, but in video game form.

> it would have to be the sort of experience that I can play for a few minutes here and there (and / or immerse myself in for several hours at a time when the opportunity arises).

Factorio isn't the type of game you can play for a few minutes at a time. For me, Factorio relies on the same kind of flow state I use for other focused work. So I play it when I opportunistically have long blocks of time. Most of my hours put into Factorio were from earlier years of my life when I had fewer responsibilities and obligations.


> I love building things

> I tried Minecraft [...] but I didn't much enjoy the [...] lack of "systems"

> I also just enjoy sitting back and watching systems work

> I prefer top-down planning

Yeah, you should love Factorio!


Because factorio is much closer to a gui-based HDL layout tool than a programming language. It might be fun to program a simulated annealer to play factorio.


That sounds like an awesome project for a graduate EE design class!


One of the HDL-to-Minecraft(Redstone) projects was done by undergraduates - from scratch even!

These kinds of projects are one of the only things I get FOMO over studying physics - I really like the idea of getting a few months to (say) write a compiler as a group rather than piles of utterly inane lab work teaching me how to use equipment I already know how to use


I often think about functional programming as a directed graph consuming information.


i honestly don't know of another way to think about it.

it's literally arrows


it's essentially the same as Reactive Streams (http://reactivex.io/) - the best known instance being RxJS.


The author is one of the main sources of Category Theory for Programmers material. Take that as you will.


> The author is one of the main sources of Category Theory for Programmers material. Take that as you will.

I'm having some trouble coming up with plausible inferences from that fact. Do you mean to imply that "when you have a hammer everything looks like a nail"?


That, or this article is an attempt to explain the author's speciality using a concrete example.


Pretty much. Bartosz's posts are pretty much exclusively about the superiority of Haskell and functional programming, with occasional forays into C++ to explain a functional concept in a more familiar syntax.


Maybe more like: “the best hammers can treat anything as a nail”


Including thumbs.


The realization at the end of your post is what the author is trying to get people to reach about software.

The category theory for programmers crowd argue that categorical diagrams (annotated graphs) are the right way to reason about software to gain insights — and the rest is describing the equivalence between functions in a type theory and maps in a category.

Your mental model of directed graphs is a functional model.


Your mental model of directed graphs is a functional model.

In the more general sense that may be true, but I was talking about Factorio specifically, where I'm using the graph representation to do the analysis.

Or rather, just because a functional interpretation exists doesn't mean I actually reach for the toolkit filed in my memory in the box labeled "functional stuff". In practice I mostly reach for the boxes I've filed away under "linear algebra", "graph theory", and "circuit design", which aren't things I typically reach for when I'm actually doing functional programming.


Well, this article helped me understand monads better than any of the other articles (though they provide important pretext).


if you don't mind going impure, you could translate those functions into actors and (easily) test their resiliency against alien attack using a virtual machine like the BEAM.


Factorio is a genre-defining game, and I think the number of clones is a testament to that.

Factorio is often compared to programming, but it's closer to Excel where the logic and the output live in the same space. The game does a great job letting the user build with programming-like constructs without them ever having to understand any theory.


Excel has been dryly noted as the most popular functional programming language before: https://www.infoworld.com/article/3033912/functional-languag...

In Excel you can't modify existing state in a cell, but only transform and output the results in a new cell.


You can change the evaluation semantics to allow cyclical references and either a max number of cycles or a stability parameter. This allows you to solve differential equations in excel. While this isn’t quite what you described, it’s closer than the default behavior.


Excel might spur users more to not separate code from data, but you can do so. Nothing prevent users from having one sheet for raw data input, one for output layouts, and the businesses implemented in dedicated formula sheets or VBA modules.

On the other side, within any programming environment, you can entangle your data, output layout and businesses code and thus create an unmaintainable mess.


I tend to disagree, there are some obvious aspects of programming in the game: refactoring spaghetti, converting monolith into microservices, multiprocessing, etc.


Factorio killed just about all ability for me to actually do normal work for two weeks. It took over my brain: all thoughts were about logistics, supply chains, the structures that would deliver them...

It was highly addictive, and fun and fun at first, but then got stressful. I've never been so relieved to finish a game, or had such an anti-climax watching the simple rocket animation.

I can't say I hate I hate the game, but saying I like it doesn't quite feel right either.


I just recently finally learned to play the game (after 5 years of playing it), you need to chiiillll... Take it easy, one problem at a time, the rocket isn't important (especially if you play with some huge mods like space exploration). It's actually similar to how I approach my job so I won't burn out.


I have found that playing with friends helps me to alleviate this problem, as scheduling constraints put an upper bound on playing time.


> I can't say I hate I hate the game

Sure you can

and many times


Ah well, typos. Or a freudian slip maybe...


It doesn’t help though!


I had to delete after I completed the 5 tutorial missions. Or else I would have failed my midterms.


Did you launch it in less than 8 hours though?


I suppose if I really optimized, planned far in advance not just in general but with detailed blueprints for different stages of development... Oh god no, you're trying to pull me back in aren't you?


Evil comment


> Merging an empty belt with any other belt, makes no difference.

I know the intended meaning was that it makes no difference to the result belt's type, but in-game it does have the important difference of putting all material from the input belt onto just 1 side of the output belt, halving throughput.

If in this image https://bartoszmilewski.files.wordpress.com/2020/11/unit.png the incoming belt had both sides filled, both would go onto only one side of the outgoing belt, possibly causing some stalling.

Do type systems exist that include a notion of "throughput" or "capacity" like this?


The inserter type is wrong when considering fluids, maybe it should be `inserter: Item a => a -> a'? Oh well, leaky abstractions are endemic.


Dependent types could presumably capture this idea. They are very expressive – see [1] for a perfectly type-safe printf implementation in Idris.

[1]: https://gist.github.com/chrisdone/672efcd784528b7d0b7e17ad9c...


From a practical perspective, I think considering throughput is a task that should be done by something utilizing the typesystem rather than the typesystem itself - i.e. give all Operations a throughput but don't try and do the checks on every single application of said operation.


An interesting writeup, but <troll>like most oversimplified functional programming writeups</troll> they are ignoring a lot of external state around Factorio "functions" and "composed functions" - things that absolutely need to be considered when creating a factory.

For example: energy requirements, inserter speed (and the impact of that and inserter stack size on throughput), input/output bottlenecks, pollution, efficiency modules (which really mucks with the "an assembler is a function" analogy), beacons, and probably more.


None of those resemble imperative programming though.

Imperative programming would be like instead of having your factorio factory, having 1-32 employees running around at ludicrously fast speeds doing all the work trying not to crash into each other.


Which is, funnily enough, roughly how it's programmed.

Each entity has a state, time is advanced, and the threads run through their queue of entities and update their state, along with the state of connected entities. Since some entities interact directly with other entities (such as two fluid pipe segments), these queues are ordered (so the fluid movement and pressure calculations make sense).

For example, a belt would advance the items on it 1/60th of its speed. Inserters would look to see if there's room in the destination, if there are items within their reach on the belt, and start moving to pick them up. Assemblers would check to see if they're currently building something, if they're full (the quantity that determines "full" is based on whether there's an outgoing inserter attached), if they have the necessary ingredients in their incoming buffer, and start incrementing the creation timer. The outgoing inserter would check for items in the assembler's output, grab them, and so forth.


See, Factorio should be implemented by reflashing an FPGA every time one places a new structure :D


And microservices is more like normal Factorio, but spending a bunch of time designing all the building blocks a few redundant ways, and then getting really drunk and blindfolded before placing them on the map. And then having your equally drunk and blindfolded factory reliability engineers fight off the swarming bugs.


That's basically what you get in Factorio with logistics bots. They fly around grabbing things out of boxes and putting them in other boxes, according to what's being "requested" and "provided" on their logistics network. (They don't crash into each other. That would be an amusing mod.)


I do think that Amazon being more interested in delivery drones than society is interested in the revival of large scale pneumatic tube networks says something deep about us.


<troll>Yeah, but it's a really good analogy. Here is this "nice" system that makes you feel warm and fuzzy, and underneath is implemented using imperative programming, whose purpose is to waste a huge amount of your spare time, for fun. Sounds exactly like functional languages to me!</troll>


Yeah, that was the obvious missing piece when I took a look at the article, a lack of rate calculations.

Basically the whole game is driven on rate and ratios, not just ratios.


As a counter argument in my day-job I generally assume that the DB will have available disk space and I don't have to worry too much about memory usage unless it becomes an issue (I do avoid naively globbing as much memory as possible but I also avoid premature optimization).

Both of those constraints do exist on programming but they don't come up often enough that generally we'll discuss or review code entirely ignoring those effects and instead favoring correctness.

Most of the items you listed aren't really important when discussing the nature of a function in the same way the fact that I happened to write my 1+1=2 algorithm on a RISC architecture isn't fundamental for teaching - sure it will potentially behave differently on a different processor - sometimes an intel bug might even cause subtle float errors - but those are implementation details and this article is focused on theory.


It is in factorio though.

Factorio, as normally played, is much closer to analog electrical circuits than it is to digital computers. In flows of resources and outflows of products that change dynamically and in real time.


>In Factorio, the nesting of functors is drastically limited. It’s possible to produce belts, and you can put them on belts, so you can have a beltful of belts, Belt Belt. Similarly you can store chests inside chests. But you can’t have belts of loaded belts.

You can, however, have vehicles on belts, and they have storage: https://youtu.be/JgqT6DEnBGM?t=2082

AFAIK that's where the nesting ends though.


Until you get into mods. https://mods.factorio.com/mod/Factorissimo2 Allows unlimited nesting of factory objects.


I discovered that her channel had episodes for Dyson Sphere Program, too, which I :heart: bunches


To me, Factorio looks more like dataflow programming (https://en.wikipedia.org/wiki/Dataflow_programming) much more than functional programming, but I guess people see much more similitude with what they are used to.


Dataflow, Pipelines, Signal Processing block diagrams, Functional programming, Flow-Based programming, Blender/Unreal Shader Graphs, The Grid in Bitwig, PureData/Max, VHDL, MATLAB Simulink, Node Red, Microservices, Tensorflow/Pytorch compute graphs, Houdini, Animation/behaviour graphs Unreal Blueprints, ...

There are so many things that we describe as a graph of boxes with inputs & outputs that we can indeed draw many parallels see many similarities between them. I think it's quite interesting to think about this diversity of tools and try to analyse what's common and what isn't between them (some are stateless others aren't, some have the notion of "time" and some have not, some are closer to state machines while other closer to mathematical functions, etc.) and it gives a lot of inspiration about new/alternative programming models & architectures


This (boxes with inputs and outputs) is how I reason about almost everything in life as well. I have been told this is what is called "systems thinking". Your comment is spot on.


Programming paradigms are all very much different sides of the same n-sided coin. One thing that's quite interesting to me about Factorio is how intelligent components like inserters are - they refuse to accept materials that their destination won't accept so one parallel in Factorio that isn't going to be matched by most views of functional programming is that you have an input of {{Gear, Gear, Iron Plate, Wire, Wire, Turret, Assembler, CPU}, {Coal, Coal, Coal, Wooden Chest, Ammo, Wire}} and an Assembler with Inserter setup to build Inserters - given that belt state prior to execution then you will apply that function and end up with a belt state like: {{Gear, Wire, Wire, Turret, Assembler}, {Coal, Coal, Coal, Wooden Chest, Ammo, Wire}} and a produced Inserter.

Factorio is incredibly resilient to mistakes which is a bit odd in that style of game - normally bad input in an assembly line game like that will result in a system freeze but Factorio just shrugs and keeps on keeping on.


I love how quick haskell folks are to bring types and say "hey look, look how neatly we can express this". What is skipped is that assemblies take unordered input. Why this is important, because the neatness would start to collapse. You would have to type `(a, b, c) -> d`, `(a, c, b) -> d` or you would require monads (case item of a) or there is some other fancy type machinery in haskell for that(without checking I am sure there is).

And we should talk about this even before we start talking about linear types. Hidden bonus is: we get a huge benefit of haskell's autocurrying matching the way "production" works in factorio. However why I am writting this. I am very disillusioned in haskell - getting something that seems about right(few rough edges) without hardcore typing bonanza is order of magnitude easier than getting precise types that you can depend on (since types that depend on them will be even more complex).

Its funny to me that some of this "precision" is lost(unheard of in haskell community). Especially by someone like Bartosz, who I can only speculate did it on purpose to fit to his story and not show the Hommer Simpson's pulled back :).

ps: I returned from vacations during which I was reading haskell/on haskell, as I often do on vacation. I am not trying to bash, haskell is pretty amazing even without any utility.


I think this is a neat attempt to make functional programming more acceptable but I really dislike the first section on assembler production

> If Factorio were a strongly typed language all the way, there would be separate recipes for producing different assemblers (that is assemblers with different recipes). For instance, we could have:

Technically yes - in a strongly typed language assemblers would be specifically specialized at compile time. For the Haskell side of things they go on to specify a higher order function to produce an assembler that can then be given a purpose by a second call. However they dropped the ball a bit on the C++ side and, while generics cause grief, they are quite good to learn about and this is a perfect place to use a templated function that could infer the correct type at compile time.


In 1986 people wanted to make real programming more like a computer game:

https://www.youtube.com/watch?v=I9LZ6TnSP40

Today, when we have much more computational resources, I'm reading this article about representing Factorio as static text with compiler checks. Something somewhere is off.


Probably only off by one, though.


I wrote a similar article explaining Kafka with Factorio analogies a while back: https://medium.com/@ruurtjan/understanding-kafka-with-factor...

Visually explaining abstract concepts works a lot better in building an intuition than explaining them in abstract terms in my experience.


I saw that. Honestly I think it maps better.


I don't really know much about functional languages, but did the section on higher order functions throw any flags for those of you who know both functional programming and the game? The "assembler" components, when used as an ingredient in a recipe, aren't really acting as assemblers anymore, just as a component...


Yeah, that seemed a bit of a stretch. Maybe a stronger case could be made for blueprints as functions, and blueprints that execute other blueprints as higher-order functions.

(I've played a lot of Factorio, but haven't really delved very far into the more exotic things that can be done with blueprints and circuit networks.)


John Carmack spent some time in one of his famous keynotes talking about functional programming. On the one hand, obviously video games tend to be very stateful, and implementing them in imperative terms is natural. On the other hand, tons of specific things you do inside a game (or in any program) can be described as pure functions, and doing that is often a great idea. I think it was this part of this keynote: https://youtu.be/Uooh0Y9fC_M?t=4660


Your comment made me feel compelled to mention a Blizzard talk I came across recently on the ECS (Entity Component System) architecture they used for Overwatch. It looks suspiciously like a function first architecture in that they don't allow mixing of data and functions. I'm not sure how purely functional it is, but it certainly strikes me as the kind of architecture that Carmack would appreciate in dealing with complexities that lead him to a more functional programming style.

This talk is 3 years after release, and includes all the hindsight they gained from that. Also, the parts talking about the netcode are quite amazing, and the precision of their predictors that they attribute to using ECS.

https://www.youtube.com/watch?v=W3aieHjyNvw&feature=youtu.be


> I'm not sure how purely functional it is

ECS systems overlap functional programming (FP) only in that both are data first.

Purely functional would mean never mutating an existing value, functions only receiving one value and returning another, monadically binding side effects and so on.

To put it bluntly, a non-trivial computer game in pure FP would hog every resource in your system to barely hit single digit frame rates.

(Disclaimer: I love FP, and use it at my day job. It is not fit for games though)


I love the way the author explained it. And surely there are places where functional programming helps eg. linear processing of data, analysis, processing. However in my field, frontend, there is more focus on interactions between very short factory lines. So functional programming does not shine, and often just leads to increased complexity and risk of mistakes.


Writing in a purely functional style isn't suited for any real world problems, functional programming remains a tool to be used like any other. However functional style programming comes with some seriously valuable effects that make it quite strong in the right situations. Front-end code tends to do a whole lot of mapping and filtering and being able to define stateless functions to execute these jobs can seriously reduce the amount of bugs you're likely going to accumulate over time.

I love programming in a variety of paradigms and settings and I'd suggest you take a bit of a closer look at what you can get out of statelessness and higher order functions in particular. Assuming you're working in a pure JS variant and not a strongly typed FE language (like Elm or TypeScript) my absolute favorite quality (strict typing) isn't available, but there are a lot of tools that can be quite helpful.


Sure. FP is helpful a little bit with some atomic operations, and processing data from data sources. However applying it to the whole project as the primary paradigm causes a lot of trouble. Purity comes with some serious drawbacks like desynchronising state risk, additional performance cost, risk of adding unnecessary complexity, code duplication and wrong code organisation.

Especially if it is considered as a competitor to object oriented programming. Unfortunately it is considered that way, and it is really a serious problem today.

People try to do stuff with FP that should be done with OOP and run into serious problems. OOP and FP paradigms work good together, but FP is often overused.


Then you can try React Hook


Where does one begin playing Factorio? Is there a place which doesn't make it feel like work?


Factorio by its nature does tend to feel a bit like work, whether that's a good thing or not is going to depend on your personality.

Whether I enjoy it depends very much what I'm doing in my actual job, if I'm in a period where I'm hands on writing code every day then finishing work and playing a game which is about incrementally building a system that inevitably needs refactoring or completely rebuilding to meet new requirements isn't much fun. If I'm in a period where the day job is planning projects, or supervising things with a long term payoff, Factorio is great for the satisfaction of picking it up and being able to achieve something concrete in a few hours.

Just remember, on at least your first 10 or so runs, what you think is a massive base that just needs some incremental improvements really isn't. Its the base you build in order to build the components for your actual base.


You just start it. Beware - this game is notorious for showing you in your face that whatever doesn't work in your base is YOUR problem, you made a mistake, probably plural, probably too basic to fix. So prepare to start over multiple times. It's my at least tenth attempt in 5 years right now. And it's lots of fun!


That was fun, now how do I build a warehouse dispatch and accounting 3-tier with functorio?


This is a fun read. Learn Haskell, functional programming, and game design all in one.


Just on the topic of Haskell - if you ever do want to give it a go there is an infinitely entertaining book out there called Learn You a Haskell for Great Good![1] that I'd highly recommend.

1. http://learnyouahaskell.com/


Bartosz and Factorio? That was an unexpected, but welcome crossover!


> It’s a simulation game called Factorio, in which you are given resources that you have to explore, build factories that process them, create more and more complex systems, until you are finally able to launch a spaceship that may take you away from an inhospitable planet. If this is not engineering at its purest then I don’t know what is.

I think that good engineers should focus first on how to prosper on the current planet which was favorable enough to sustain their live until now, rather than carelessly exploit its resources with a delusive goal of finding a more hospitable place somewhere else.


I started to dream in assemblers. And belts. Endless belts.


Would sure love something browser or phone based that's quick and something I can hop in and out when not busy. I'm currently on a factorio binge...


This is kind of unrelated, but it would be so cool if assemblers like that existed in real life. It's a "hard problem" unfortunately.


yeah that would be very cool. Some of the sub-components essentially exist (3d printers and pick-and-place machines come to mind), but not in a single package that could print/assemble complex objects (AFAIK).


More evidence that, not only do we live in a simulation, but that our simulation is running in Factorio. Great writeup Bartosz.


The inserter function automagically picks a direction for the ingredient/product flow.


> The building blocks of every programming language are functions.

Hmmm, no.


You're right, not every single programming language on this planet does have functions.

But, nearly all of them have functions, at least as a concept. Then in some languages they are called methods, sub-routines, procedures and more, but the concept are mostly the same. A collection of lines of code that does something, probably with a name.


Historically, all theses had a specific meaning which got lost or turned irrelevant with time. Subroutine, for example, came from a computer that Alan Turing worked on, it had multiple slots for punched tapes; one for the main routine and the rest for subroutines. You could jump from one tape to another tape and then return.


Most programs are not factories. Programming is mostly about handling state.


> Programming is mostly about handling state.

Only if you write your code that way, and then it's a self-fulfilling prophecy.

There's a good amount of mutable state that's just incidental for particular algorithms, and not intrinsic to the problem you're solving.


Bartosz is the best


I look forward to the inevitable two camps of comments on anything related to Factorio: "This is just software engineering, why would I do that in my free time?" and "This is just software engineering, but without all the distractions, frustrations, meetings, and dependencies - how can I do this all the time?"

(FWIW, I'm in the latter camp)


>how can I do this all the time?

Make a factorio-themed reskin of labview.

If it took me 100 hours to complete a coding project of the magnitude of a factorio playthrough I would say I'm pretty bad at coding.

I'm of the former of your two listed camps, but I don't try to look at how the game is like coding and look at it how it is like modded minecraft. Learning rules and discovering tricks and being creative is a fun way to spend free time. Maybe coding can have a similar track, but it often feels heavy on the grind.


There's a third camp: "This is just software engineering, I might as well code something useful and equally fun".


The problem with doing something useful is that you might end up with users.


Good point, but you could make something that's useful for yourself, or to learn something new, or even something like an art piece. Recently when I had some time I implemented a Minesweeper solver. Not useful to anybody, except perhaps rural Cambodian farmers, but it was great fun, and probably more satisfying than playing a game.


^^^ That's my camp by and large unless I'm playing multiplayer with friends it just makes me feel like I should be working on my side project.


When SVG was young someone made a graph game where a bunch of points are placed on a field. Each point has two edges leading to other points. You 'win' the game when no edges cross.

It was pretty fun for the first half hour. Then for the next fifteen minutes something didn't feel right. To quote Robert Zemeckis, it felt like kissing your brother.

The other thing that was hot around that time was UML, and it feels like half of UML is just trying to get lines not to cross each other. Ding! I was doing some of my least favorite work 'for fun'. Closed that window, pushed away from my desk dramatically, and went for a cup of coffee and a bit of perspective.



Yes, a clone of that, but I suspect GP meant the implementation at http://planarity.net/


"This is just software engineering, why would I do that in my free time?"

I was of this opinion until I realized I was basically doing digital logic in minecraft. You're right in that engineering without crud is very fun.


"Just" software engineering is a rare thing.

If you want to make real software, you have to do your software engineering in the middle of a sandwich with tooling and dependencies on one side and your platform on the other.

Dealing with either of these can sometimes be satisfying, but they both tend to require a lot more effort than is desired.


Software engineering with angry aliens.


That would be me in approx 2006 in Second Life, in-game coding using the Linden Scripting Language [0]. I have vague recollections of trying to script some sort of scanner object and explaining what I was doing to a curious gothic vampire demon who was passing by. I think she lost interest (and flew away) when I got to quarternions [1]

[0] http://wiki.secondlife.com/wiki/LSL_Portal

[1] http://wiki.secondlife.com/wiki/Quaternion


Literal bugs!


Angry aliens, or angry end-users?


I call it circuit design. "How can I fit this efficiently into the space I have allotted and protect it from outside influences (biters)?"


I never felt space (with normal game settings) was an issue in the game. The infinite map even means it’s literally impossible to run out of space.


Space becomes an issue when trying to minimize your buffers. During a casual playthrough, it won't really matter, but if you're dealing with megabases, the distances and buffers can really impact how the smoothly a factory works, how quickly it can respond to changes. For example, not all of the "infinite research" technologies have the same science pack requirements, which changes what your base has to produce.


The biters of clan cholg-un tphol have requested a meeting about the planned nuclear plant expansion into their sacred ancestral territory.


I know this kind of misses the point, but Factorio is one of the most addictive and rewarding gaming experience I've had. Beware: within months it ate up collectively hundreds of hours from myself and members of my friend group.


Wait until you try Dyson Sphere Program.

It definitely scratches that Factorio itch but in a different way.


I haven't found dyson sphere as addictive, but it's definitely fun and has a similar feel, but dyson sphere seems more about building massive amounts of things rather than clever designs


Fair, but it's in early access and just released a few weeks ago.

Roadmap includes a ton of interesting things which should make it more challenging in the long run.


I just looked up Dyson Sphere Program. What have... you done. Haha looks awesome - thanks!


I would agree that Factorio is addictive, but "rewarding" is not a word I would use to describe it personally. I finished it but did not enjoy the process.


Makes sense, it's not for everyone.

I will note that someone who does enjoy the game would never describe themselves as having "finished" it, there is always more to expand, more to optimize, etc. Not to mention all the mods to explore!


Frankly that's probably one of the big reasons I didn't enjoy it, but did enjoy many Zachtronics games.


I see this kind of comment often and it confuses me. If you didn't enjoy the process, why did you even bother finishing it?

Further, how was launching your first rocket anything other than rewarding?


As someone who loves Factorio, there is a lot about the process of the game that I don't love. Especially after having 'completed' about 4-5 factories with a friend, you get to a point where you know how to accomplish a task, but there is a lot of drudgery to get there. Also the combat is the game is tedious. When playing with a friend, we literally do a coin flip for who has to clear hives that are inside our pollution area. I personally push to turn off aliens when we play, but he thinks its lame to take out a function of the game.

With all of that said though, getting to a result is always a great feeling and basically why I still play it after all of these years.


A guess, compulsive completionism based around the sunk cost fallacy. Pretty common with videogame completionists (including myself).


I am not a completionist. I can't really put my finger on why I kept playing, possibly it was because the end goal was inevitable and the only thing separating me from it was time and tedium as opposed to any real difficulty. Possibly I just had nothing better to do at the time.


See: Addicting.

Launching the rocket was inevitable after a certain point, it was just a matter of tuning everything well enough to get there as quickly as possible, which seemed always to be hampered by some tedious task or another. Having robotics much much earlier in the game might have helped a lot there.


> which seemed always to be hampered by some tedious task or another.

IIRC, Factorio does have a sandbox mode where you can just create arbitrary designs without having to gather/assemble the stuff first.


I watched part of the speed run on marathon + death world challenge and the guy got robotics under 2 hours. So it’s nit that late game. Giving it earlier would be confusing for beginners.


> I watched part of the speed run on marathon + death world challenge and the guy got robotics under 2 hours. So it’s nit that late game.

You were watching a speed runner who knew exactly what they were doing. I was a first time player who didn't. I spent north of 30 hours tediously laying out factory bits and wondering "why the hell can't I automate this?"

P.S.: and hey wait, whole speed runs of Factorio seem to be in the range of 2-3 hours, and you're suggesting under 2 hours isn't late game?


In a speed run, investing in robots is a waste of time and oil (oil being the most precious resource because you have so little of it in your starting area). However, robotics is necessary for yellow science, which is likely to be the last science pack (purple science unlocks automation techs, which might be useful for speed). So leaving robotics until one of the last techs to be researched wouldn't be unreasonable in a speed run.

But robotics itself only requires blue research. In my own speed run of ~6h40m (admittedly, on an older version of the game, but the game pre-blue science hasn't changed much), I got blue science in about 2h, and bee-lining for robotics after that would only take a couple of researches beyond that (advanced oil, electric engine, robotics, and then construction robotics to do anything useful IIRC).

I wouldn't call anything that takes only blue science to get to be late game; for me, that requires at least purple or yellow science. Robotics is on the other side of the oil barrier, which is definitely going to push it far later in the game for new people, but it's also accessible before you hit the point of needing to repetitively scale up your factory (which tends to come with purple/yellow science), so it is accessible before you really need it. However, the game doesn't particularly guide you towards knowing that it exists, so I can see how it might be frustrating for new players.


"marathon + death" is much harder than normal Factorio. I agree that it's a bit of a weird data point to bring up ("in a harder game mode it took a significant amount of time") without further reference (such as how long the full run took) though.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: