1. Factorio
  2. News

Factorio News

Version 0.17.72 released

Bugfixes


  • Fixed another biter-related crash. more

You can get experimental releases by selecting the '0.17.x' beta branch under Factorio's properties in Steam.

Friday Facts #317 - New pathfinding algorithm

Read this post on our website.

New pathfinding algorithm - Oxyd

Last week we mentioned the change to make biters not collide with each other, but that wasn’t the only biter-related update we released this past week. Somewhat coincidentally, this week’s updates have included something I’d been working on for a few weeks before – an upgrade to the enemy pathfinding system.

Pathfinding
When a unit wants to go somewhere, it first needs to figure out how to get there. That could be as simple as going straight to its goal, but there can be obstacles – such as cliffs, trees, spawners, player entities – in the way. To do that, it will tell the pathfinder its current position and the goal position, and the pathfinder will – possibly after many ticks – reply with a path, which is simply a series of waypoints for the unit to follow in order to get to its destination.

To do its job, the pathfinder uses an algorithm called A* (pronounced 'A star'). A simple example of A* pathfinding is shown in the video below: A biter wants to go around some cliffs. The pathfinder starts exploring the map around the biter (shown as white dots). First it tries to go straight toward the goal, but as soon as it reaches the cliffs, it 'spills' both ways, trying to find a position from which it can again go toward the goal.

https://cdn.factorio.com/assets/img/blog/fff-317-basic-pf.mp4
In this video, the algorithm is slowed down to better show how it works.

Each dot in the animation represents a node. Each node remembers its distance from the start of the search, and an estimate of the distance from that node toward the goal – this estimate is provided by what's called a heuristic function. Heuristic functions are what make A* work – it's what steers the algorithm in the correct direction.

A simple choice for this function is simply the straight-line distance from the node to the goal position – this is what we have been using in Factorio since forever, and it’s what makes the algorithm initially go straight. It’s not the only choice, however – if the heuristic function knew about some of the obstacles, it could steer the algorithm around them, which would result in a faster search, since it wouldn’t have to explore extra nodes. Obviously, the smarter the heuristic, the more difficult it is to implement.

The simple straight-line heuristic function is fine for pathfinding over relatively short distances. This was okay in past versions of Factorio – about the only long distance pathfinding was done by biters made angry by pollution, and that doesn’t happen very often, relatively speaking. These days, however, we have artillery. Artillery can easily shoot – and aggro – massive numbers of biters on the far end of a large lake, who will then all try to pathfind around the lake. The video below shows what it looks like when the simple A* algorithm we've been using until now tries to go around a lake.

https://cdn.factorio.com/assets/img/blog/fff-317-long-pf-before.mp4
This video shows how fast the algorithm works in reality; it hasn’t been slowed down.

Contracting Chunks
Pathfinding is an old problem, and so there are many techniques for improving pathfinding. Some of these techniques fall into the category of hierarchical pathfinding – where the map is first simplified, a path is found in the simplified map, and this is then used to help find the real path. Again, there are several techniques for how exactly to do this, but all of them require a simplification of the search space.

So how can we simplify a Factorio world? Our maps are randomly generated, and also constantly changing – placing and removing entities (such as assemblers, walls or turrets) is probably the most core mechanic of the entire game. We don’t want to recalculate the simplification each time an entity is added or removed. At the same time, resimplifying the map from scratch every time we want to find a path could quite easily negate any performance gains made.

It was one of our source access people, Allaizn, who came up with the idea that I ended up implementing. In retrospect, the idea is obvious.

The game is based around 32x32 chunks of tiles. The simplification process will replace each chunk with one or more abstract nodes. Since our goal is to improve pathfinding around lakes, we can ignore all entities and consider the tiles only – water is impassable, land is passable. We split each chunk into separate components – a component is an area of tiles where a unit can go from any tile within the component to any other within the same component. The image below shows a chunk split into two distinct components, red and green. Each of these components will become a single abstract node – basically, the entire chunk is reduced into two 'points'.



Allaizn’s key insight was that we don’t need to store the component for every tile on the map – it is enough to remember the components for the tiles on the perimeter of each chunk. This is because what we really care about is what other components (in neighbouring chunks) each component is connected to – that can only depend on the tiles that are on the very edge of the chunk.

Hierarchical Pathfinding
We have figured out how to simplify the map, so how do we use that for finding paths? As I said earlier, there are multiple techniques for hierarchical pathfinding. The most straightforward idea would be to simply find a path using abstract nodes from start to goal – that is, the path would be a list of chunk components that we have to visit – and then use a series plain old A* searches to figure out how exactly to go from one chunk's component to another.

The problem here is that we simplified the map a bit too much: What if it isn’t possible to go from one chunk to another because of some entities (such as cliffs) blocking the path? When contracting chunks we ignore all entities, so we merely know that the tiles between the chunks are somehow connected, but know nothing about whether it actually is possible to go from one to the other or not.

The solution is to use the simplification merely as a 'suggestion' for the real search. Specifically, we will use it to provide a smart version of the heuristic function for the search.

So what we end up with is this: We have two pathfinders, called the base pathfinder, which finds the actual path, and the abstract pathfinder, which provides the heuristic function for the base pathfinder. Whenever the base pathfinder creates a new base node, it calls the abstract pathfinder to get the estimate on the distance to the goal. The abstract pathfinder works backwards – it starts at the goal of the search, and works its way toward the start, jumping from one chunk’s component to another. Once the abstract search finds the chunk and the component in which the new base node is created, it uses the distance from the start of the abstract search (which, again, is the goal position of the overall search) to calculate the estimated distance from the new base node to the overall goal.

Running an entire pathfinder for every single base node would, however, be anything but fast, even if the abstract pathfinder leaps from one chunk to the next. Instead we use what’s called Reverse Resumable A*. Reverse means simply it goes from goal to start, as I already said. Resumable means that after it finds the chunk the base pathfinder is interested in, we keep all its nodes in memory. The next time the base pathfinder creates a new node and needs to know its distance estimate, we simply look at the abstract nodes we kept from the previous search, with a good chance the required abstract node will still be there (after all, one abstract node covers a large part of a chunk, often the entire chunk).

Even if the base pathfinder creates a node that is in a chunk not covered by any abstract node, we don’t need to do an entire abstract search all over again. A nice property of the A* algorithm is that even after it 'finishes' and finds a path, it can keep going, exploring nodes around the nodes it already explored. And that's exactly what we do if we need a distance estimate for a base node located in a chunk not yet covered by the abstract search: We resume the abstract search from the nodes we kept in memory, until it expands to the node that we need.

The video below shows the new pathfinding system in action. Blue circles are the abstract nodes; white dots are the base search. The pathfinder was slowed down significantly to make this video, to show how it works. At normal speed, the entire search takes only a few ticks. Notice how the base search, which is still using the same old algorithm we've always used, just 'knows' where to go around the lake, as if by magic.

https://cdn.factorio.com/assets/img/blog/fff-317-long-pf-after.mp4

Since the abstract pathfinder is only used to provide the heuristic distance estimates, the base search can quite easily digress from the path suggested by the abstract search. This means that even though our chunk contraction scheme ignores all entities, the base pathfinder can still go around them with little trouble. Ignoring entities in the map simplification process means we don't have to redo it every time an entity is placed or removed, and only need to cover tiles being changed (such as with landfill) – which happens way less often than entity placements.

It also means that we are still essentially using the same old pathfinder we've been using for years now, only with an upgraded heuristic function. That means this change shouldn’t affect too many things, other than the speed of the search.

Bye bye TOGoS - TOGoS

Hi everybody!
I'm going to be resigning from official Factorio staff after today to start a new job closer to home.

The main reason for this switch is that working entirely remotely turned out to be something that I wasn't able to handle all that well. But also, my primary contribution to the project, the programmable map generator, is complete, stable, and pretty well understood by at least one other person, so timing-wise this seemed a good point for me to move on. To working in a cube farm writing Android applications for treadmills, apparently.
We'll see how that goes!

It's been an honor to be part of this awesome project and to leave my imprint on it. And working on a large and pretty well-managed C++ codebase, full of things done just a bit different than I had ever thought to, has been mind-opening.

I also want to thank the community for your continual patience, honest feedback, and the occasional bit of pressure that you put on us to make the game as good as it can be.

I'll continue to read the Friday Facts every week, lurk on the forums, and probably update documentation here and there. Hopefully I'll find time to crank out some terrain-altering mods of my own. And I'm looking forward to seeing what else y'all do with it, too. (Which includes working through a backlog of mods -- I have yet to get to the space exploration part of Space Exploration!)

Peace out for now.

Community spotlight - 13x9 Micro Factory - Klonan

Over 100 Friday Facts ago we covered DaveMcW's 9x14 Micro Factory (FFF-197). While it may have taken over 2 years, he has improved his design even further, and the result is just as impressive as before.

https://youtu.be/9dzQge6pe2o

He offers some more explanation of his Micro Factory in this forum post.

As always, let us know what you think on our forum.

Version 0.17.71 released

Bugfixes


  • Fixed a crash that would happen on loading certain saves made in previous versions. more
  • Fixed entity selection could desync from mouse cursor when switching to cutscene controller in multiplayer. more

Version 0.17.70 released

Features


  • Added interface option to adjust the number of shortcut bar rows that are visible on the screen.
  • Added ability to shift click a research in the technology screen to start that research.
  • Allowed setting filters with the ghost cursor.

Changes


  • Biters and Spitters will no longer collide with other biters/spitters. more

Graphics


  • Added new remnants for several entities. They are still work-in-progress and subject to further change.
Bugfixes


  • Excluding runtime fluid mixing check from assembler migration that caused some crashes when loading a save with mixing in it.
  • Fixed landfill map color on old saves. more
  • Added migration to recalculate tile transitions when tile layer definition changes in tile prototype. more
  • Fixed that artillery remote failure sounds could be duplicated in some cases. more
  • Fixed that the game would still process mod dependencies for disabled mods. more
  • Fixed that underground pipes with different length could sometimes connect one tile further.
  • Fixed that the cursor would appear in the wrong position after textbox alignment was changed by scripting. more
  • Fixed placement of scrollbars around textboxes. more
  • Fixed a crash related to teleporting biters during the ai-completed events. more
  • Fixed that non-square crafting machines without fluid boxes didn't rotate correctly. more
  • Fixed that the game would freeze when trying to find automatic artillery targets with very high levels of artillery range. more
  • Fixed tile ghosts sometimes overlapped on edges which created visible lines. more
  • Fixed that the on_gui_switch_state_changed event would fire twice in some cases. more
  • Fixed wrong damage bonus values in tooltips of combat robots and units in a different force. more
  • Fixed that the research screen would show a technology as "available" when it was queued. more
  • Fixed that LuaEntity::last_user didn't support writing `nil`. more
  • Fixed that mod GUIs could show on top of the technology screen after loading a save. more
  • Fixed a crash when using the /screenshot command. more
  • Fixed that the --disable-migration-window command line option didn't always work. more
  • Fixed that pumps had a drain when using a non-electric energy source. more
  • Fixed a bug in fluid system splitting.
  • Changed order of pipe connections to avoid previous cases of fluid mixing. A.k.a Boskid's deferred pipes.
  • Offshore pumps now set fluid filter automatically based on produced fluid. more
  • Fixed crash when closing shortcut selection list while dragging. more
  • Fixed that biters could get overloaded by artillery and stop moving. more
  • Fixed that biters could get stuck during attacks. more
  • Fixed that biter pathfinding could cause unreasonably large save files. more
  • Fixed that biters would attack in a single file due to their colliding with each other. more
  • Fixed that personal roboports would function with literally no power.
  • Fixed migrating pre-0.17 maps with detached characters that had a grid armor in quick bar would corrupt game state. more
Modding


  • Added optional flying robot prototype property "max_speed".
  • Added light_renderer_search_distance_limit to utility constants.
Scripting


  • Changed LuaEntity::color to also work for cars.
  • Changed LuaStyle::padding, margin to also accept arrays of padding values.
  • Added optional "unit_number" to on_post_entity_died event.
  • Added support to teleport car entity types between surfaces.
  • Added LuaEntityPrototype::call_for_help_radius, max_count_of_owned_units, max_friends_around_to_spawn, spawning_radius and spawning_spacing read.
  • Added LuaForce::research_enabled read.

Friday Facts #316 - Map editor Lua snippets Non-colliding Biters

Read this post on our website.

Map editor Lua snippets


In the last few weeks, we've really accelerated our work on the campaign. We've been pushing ahead a lot with both the scripting and blocking out the physical level design.One of the problems we've come up against a lot, is that we often need to perform custom edits to the map, which are quite tedious, but not common enough to add a new tool to the map editor for them. For example, something like "disable all the spawners in this region".

This kind of problem is easily solved with a little bit of custom Lua code, but getting the specification of the area we want to edit into Lua is a painful process of noting down and typing out location coordinates. It is also easy to lose track of these Lua snippets, as there is no good place to save them.

To solve this problem, we decided to add a Lua snippet tool to the map editor. This tool will let you drag your cursor over an area, and it will then run your custom Lua code on that area. The snippets are named, and saved in your player-data.json, so you can keep them around for later.

https://cdn.factorio.com/assets/img/blog/fff-316-snippet.mp4
For example, this simple snippet replaces trees with biters.

Currently, there doesn't seem to be a very big scene for community made custom maps/scenarios with custom maps, and we're hoping that the example from the campaign once released, as well as the much improved editor we have in 0.17 will encourage more people to give this a go.

Apple signing woes

As some of you may have heard, Apple is introducing a new system called notarizing to their MacOS apps. This is a system where you sign you packages and upload them to apple so they can run something akin to a virus scan, and mark it as approved. As of the new MacOS Catalina version, this will be mandatory. Our friends at Valve were nice enough to send us a warning with some info about the process. Up until now, our MacOS binaries haven't even been signed at all, so this seemed like a good time to get on that. To be clear, you could, and can play unsigned factorio binaries on MacOS, but you need to change your security settings to do so (or so I thought).

To test, I grabbed the .app of 0.17.69, signed it, uploaded it to apples notarization server, and got the notarization process to succeed (eventually). I then copied it onto a completely fresh, default settings install of macOS Catalina, double clicked it, and it ran, with no security prompt. Problem solved, right? Well, after that I decided to do a sanity check, and copied over the completely unsigned binary of 0.17.68, and it ran just fine as well, also with no security prompt.

So, at this point, it seems like we don't really have a way to test this process, so all we can do is set things up correctly to the best of our abilities, and see if it works for people. The next Factorio release should include signed and notarised macOS binaries, so if anyone has problems with 0.17.70 security warning on macOS, please let us know.This whole process has been rather slow and painful (just getting the notarizing tool working was a bit of a saga in itself), and doesn't inspire much confidence in Apple's developer ecosystem, so if anyone at Apple is reading this, please, please, make this process better.

Also to make it known again, we are still looking for a macOS developer to join our team, so if you are interested or know someone who is, please checkout the job listing.

Non-colliding Biters

For a long time we have been improving the biter pathing, with many iterative changes and tweaks. However we have long had a problem in the moment where a group of biters encounters the players base. I am sure the scene below is familiar to all Factorio players:

https://cdn.factorio.com/assets/img/blog/fff-316-biters-collide.mp4

This mating dance or whatever it is, has long been a thorn in our side. The reason behind it is quite logical. When moving, the biters are in a group, and everything goes smoothly. However when they see an enemy, they are 'distracted' by it, and individually try to attack it. Since the biters are now moving and pathing as individuals, things start to get messy. The biters find a path, but then there is another biter in the way, so he tries to move and turn around, but there are biters in the way there too, and each of those biters are trying the same thing, so it all goes gets clogged up for a while.

The solution we have decided, which some might consider a 'hack' is that we simply don't make biters collide with other biters. In the engine this was a rather simple change, and was already possible just using normal mods. The result speaks for itself:

https://cdn.factorio.com/assets/img/blog/fff-316-biters-no-collide.mp4

There is already some 'separation' logic in the engine to keep biters from getting too close to each other, so in the end we get away with a lot of the benefit of no collisions, without the immediate/obvious problem of biters infinitely stacking. There might be some smaller issues to pop-up with this change, and maybe some balancing tweaks to be made, but we are happy with the outcome so far.

Twinsen is going to Poznan Game Arena, Poland

Next week I'll be in Poland for 3 events:

If you are in the area and see a guy with a Factorio hoodie, it will most probably be me. I am looking forward to meet any fellow developers or fans attending.

Ludum Dare entry

Over the weekend, two of us (wheybags + Abregado) entered the Ludum Dare game jam. A game jam is an event where people make a game as completely as can be in a fixed time-frame (in this case 48 hours). We ended up making a rather Factorio-appropriate gear puzzle game. Check it out if you're interested.



As always, let us know what you think on our forum.