about 1 year ago - kovarex, Oxyd, Klonan - Direct link

Hello,
today we are going to talk about some flying robot behavior improvements. Some of the problems we fixed were reported countless times, so I hope that some people will appreciate it :).


Quality of life versus flashy featureskovarex

I know that you are mainly looking forward to the new content, and that just quality of life improvements aren't the kind of things that make people buy the game and get excited for.

But I strongly believe, that if you want to add content, mechanics, and systems to a game, which already isn't simple, there is always a risk of just it being too much. By doing QOL improvements, we reduce the small hassles and annoyances, which effectively creates an extra mental space to enjoy more in the game. Its like cleaning your room before getting a new toy.

So to make things clear, the reason that we make and present these kind of changes is not because we don't want to make new flashy features, we just want the new stuff to be enjoyable without a burden of having too much to deal with.
But don't worry, we will show something new next week!


Smarter robot tasksOxyd

Logistic and construction robots have been in the game for a while, and at their core they are fairly simple entities. A logistic robot, for example, may be told to go pick up an item from a chest, and deliver it to another chest. So far so good, but in Factorio there usually is more than one item to be transferred — so what does the game do when tasked with transferring, say, 500 items from one box to another?

The Old Way

In Factorio 1.1, the game keeps a list of all idle robots, including those hiding away in roboports, and when a task needs to be taken care of, it selects the nearest idle robot from that list. So, to transfer 500 items from a provider chest to requester, the game would find the first idle robot closest to the provider chest and task it with the transfer. This robot now has a task, so it is removed from the list of idle robots.

But we still have 499 other items to transfer (ignoring robot capacity bonus for simplicity). The logistic network simply repeats the previous steps for all the other items — find the next closest idle robot, task it with transferring the next item and so on until there is a robot for each of the 500 items in the box.

The problem with this strategy is that while the first few robots may be located in roboports reasonably close to the provider chest, by the time we get to the last items the network may have to reach for robots at the other end of the factory because there is no closer idle robot for the task. The end result is that the first batch of robots will arrive at the chest, take the item and deliver it to the destination, and then recharge and go have a nap in a roboport — transferring a single item was all these robots were tasked with and the remaining items have already been assigned to other robots. After that, a slow trickle of robots from far away parts of the factory will come in and transfer the remaining items.

Mp4 playback not supported on your device.

The situation is similar for construction robots, and this can be especially apparent when using one's portable roboport. Say the player wants to remove a bunch of trees in their factory. A single personal roboport can have up to 25 construction robots, so that's up to 25 trees that will be deconstructed using the player's personal robots. All remaining trees will be assigned to robots from the main logistic network, and the player will have to wait for them to arrive for the trees to be gone — even though the player's personal robots are right there with nothing better to do!

Mp4 playback not supported on your device.

The New Way

Choosing a robot for a task only from the list of idle robots clearly isn't the best strategy. Assigning a task to a robot that is currently busy but nearby may be a better choice, even if the new task may have to wait until the robot finishes its other tasks. This required two main changes to the logistic network code.

The first change was to allow robots to have multiple tasks assigned to them. Much of the code has been written with the assumption that a robot has exactly one job, but after some code refactor, robots now have a queue of tasks.

Second, we need a way to select a robot for a task. Each task has a starting position, for example a deconstruction order starts at the entity to be deconstructed. Until now, the selection process was simple — just select the idle robot closest to that point.
But now, when we can also select a robot with one or more queued tasks, the process becomes a bit more complex.

The new metric for robot selection is the arrival time. For an idle robot, its arrival time is simply the distance to the starting position divided by its speed. For a busy robot, we can look through its queue of tasks, figure out where and when the robot is going to end up when its done, and then add the flight time from there to the starting position of the new job.
When selecting a robot for a task, we select the one that is going to arrive first, even if it has to take care of other things before that.

It is worth pointing out that the arrival time calculation is only an estimate. For example, we simplify the effects of the recharging times. A keen-eyed player will no doubt notice situations where choosing a different robot could have been a little bit more efficient. But in the big picture, it doesn't seem to be very noticeable.

Let's see how the new system handles our previous two examples. The initial batch of robots is tasked with transferring all the items which results in them shuffling back and forth between the requester and the provider.

Mp4 playback not supported on your device.

For deconstructing trees, each of the player's personal robots does more than just a single tree. Robots from the main network still come to help out, but this time it's because they can help get the whole job done faster.

Mp4 playback not supported on your device.

Performance

Having a simple list of all busy robots and going through it each time a new task comes in may work fine for small factories, but with several thousand robots flying everywhere it can quickly become a UPS drain. To alleviate that, we implemented a different representation.

Whenever a robot's queue of tasks is updated, it calculates its final position estimate — that is, its final position and the time at which it will finish. Each map chunk now stores a list of all busy robots that are estimated to finish on that chunk. So when a robot updates its final position estimate, it registers itself in that chunk's list of robots. When searching for a robot for a particular task, the game now starts its search at the chunk where the job's starting position is located, and continues its search in an outward spiral.

Storing busy robots on chunks and searching in a spiral improved the performance by a lot, and even factories with thousands of busy robots run well.


Smarter robot other thingsKlonan

While playing and developing the expansion for the last 2 years, we have also accumulated a few more features and changes to make the robots feel smarter and work better.

Roboport robot requests

There are some situations when you need to make sure some roboports always have robots to service tasks. For example if you have a little resupply point with buffer chests, you want logistic robots around to quickly empty your trash and refill your supplies. It is quite annoying when all the materials are right there, but you are stuck waiting around, because due to natural robot migratory patterns, the roboports in the area are quite empty.

Mp4 playback not supported on your device.

It could be solved with requester chests, inserters, circuit network, and such... but we decided a smoother approach. You can now set logistic requests for robots directly inside the roboport GUI. Robots will be dispatched from other roboports to fulfill the request (important to note, robots will not be taken from storage or provider chests).

With this new feature, we can set all the roboports near our resupply point to always have 100 logistic robots available. Once we arrive, our needs are serviced in record time, and afterwards you can see robots arriving to get the roboport back up to 100.

Mp4 playback not supported on your device.

Another nice use of this is that we can use the roboport requests to remove certain robots from the network. Perchance we had some mod with higher quality worker robots, we can request the low quality ones and remove them with a filter inserter, over time removing the worse robots from circulation.

Better robot charging heuristic

When a worker robots runs low on energy, they need to find a nearby roboport to charge at, but they need to be a little bit smart about it. For instance if they always chose the closest roboport, then you would get queues and traffic jams at some roboports while others are completely empty.

For these 'smarts' we use a quite simple heuristic, factoring in not just how close the roboport is, but also how many other robots are currently charging there. Typically this worked 'well enough' but every so often you could encounter a little inconvenient situation where they are still bunching up on some roboports while ignoring others that are just a little bit further.

Mp4 playback not supported on your device.

In some extreme cases this can actually be quite a problem, as the robots waiting to charge still use energy for hovering, so lose more energy, in a positive feedback loop where all robots who join the queue will fall to 0 energy while they are waiting their turn. Generally though the main problem here is that the player looks at the robots and thinks "These robots are so dumb...". Not the end of the world, but we can do better...

Surprisingly in this case the issue can be helped a lot by just a small improvement in the heuristic logic. When deciding which roboport to charge at, the robots crucially did not consider the current robots on the way to that roboport, only those already in the queue, and did not factor in how many free charging spots the roboport has open. By adding these two extra parameters into the equations, the distribution of the robots improves quite nicely.

Mp4 playback not supported on your device.

Mitigation for robot pathing over lakes

It has been a problem for a long time, the robots are pretty dumb when it comes to pathfinding, and try to fly over areas that have no logistic network coverage. This is because for performance reasons, we don't do any pathfinding at all. The robots just fly in a straight line to the job position.

One major problem of this is the possibility of the robots to get stuck in an infinite loop. This is because they fly out over uncovered territory, run out of battery, and return back to recharge and try again. Obviously they will never make it.

Mp4 playback not supported on your device.

This issue was notable enough and annoying enough for us that we really did want to come up with a fix. The solution we came to was a smart trick in the roboport selection when they run out of energy. Usually the robot just chooses one of the nearest roboports, which is fine for normal circumstances, but in this case leads to the robot turning completely around in failure.

So we changed the selection logic, so that the robot tries to always charge at a roboport that is closer to the destination than the robot is. This means that even if the robot will potentially fly with low energy for longer, it will always be able to make some progress towards the target, and eventually complete their mission.

Mp4 playback not supported on your device.

It is not a perfect solution, but should hopefully help prevent the most egregious issue of this technical constraint.


As always, let us know what you think at the usual places.

about 1 year ago - /u/kovarex - Direct link

Originally posted by Malfuncti0n

I never knew I needed these changes, amazing!

Hope it might come in 1.2 before the expansion, I don't see a reason why not?

The source code (branch) of the the expansion WIP diverged so crazily much from the 1.1, that backporting any non-trivial feature is a lot of work, sometimes almost the same as doing it from scratch.

about 1 year ago - /u/kovarex - Direct link

Originally posted by I_IblackI_I

Do the things like the robot improvements come as a free update or require the purchase of the expansion?

These changes come as free update.
It would actually be technically harder to make it only for an expansion, as it is change of how the thing is programmed in general.
Generally speaking, expansion stuff is new content (like the space platform, other planets, etc.). Sometimes, new engine capabilities might be expansion only, as there would be way too easy to make mod which just gives you the new expansion content, it will be all nicely explained in the next FFF which will be a good example of such a case.

about 1 year ago - /u/kovarex - Direct link

Originally posted by BraxbroWasTaken

Will those capabilities be available for modders when the expansion is installed, then? (though I’m not sure I like locking down the engine to prevent reimplementation of the expansion; that seems more like something that should be a ToS enforcement on the mod portal than something built into the game, in my opinion; is this the plan just because it’s easier on your limited personnel?)

There are (will be) bunch of switches in the mod json file, which specifies what kind of "special features" is the mod demanding.
If the mod demands the space-platforms feature for example, the related stuff will be usable by the mod, but the mod will require to have the expansion executable.

TL;DR; There can be both expansion/non expansion mods, based on what the mod wants to use.

about 1 year ago - /u/kovarex - Direct link

Originally posted by DrAndros

An other new feature I've noticed is that in the image with the roboport robot request feature in the inventory the red wire doesn't stack. I think the wires are now permanent, so hopefully there is no need to craft a bunch of them when designing circuits.

And the wires are in two places in the inventory. This can't be filtering, because there would be a blue background behind the slot, so maybe it's changed.

Or the inventory sorting could be turned off entirely, but that wouldn't be exciting.

It will be discussed in more detail in the future, but

  1. It is quite clear, that there were things in the inventory which Scott just didn't want to show yet, so he just pasted the icon over.
  2. One of the FFFs in the future will be about all the improvements of how you can build and configure things remotely. Almost everything is doable remotely already (with more or less hussle), but you can only build wires locally, or by a blueprint trick, which was quite annoying, so you can guess what we did :)
about 1 year ago - /u/kovarex - Direct link

Originally posted by alexbarrett

If I understood everything correctly, actives robots will have properties for estimated idle time & position. Does this mean that:

  1. When a personal robot is constructing an entity: the estimated final position will be at the constructed entity's position.
  2. When a personal robot is bringing an item to the player's inventory: the estimated final position will be the player's position.

I assume also that once a task is added to a robot's queue, it will remain there and not get dynamically reassigned.

Does this mean that if a player stands e.g. very close to a full chest and deconstructs it, the game will assign tasks to empty the chest to the personal robots, and if the player then walks far away from the chest the personal robots would then a very long task queue ahead of them? Would the estimated idle time be updated when the player moves?

I don't think that existing tasks get re-evaluated this way, this is why we stated it is only an estimate (heuristic). We tried to hit the sweet spot of being reasonably precise and useful while also simple enough to not hit the performance.

about 1 year ago - /u/kovarex - Direct link

Originally posted by Darkhogg

Most of these additions are stuff I have at some point thought about, both problems and possible solutions, so I'm really glad they were addressed!

It would be amazing if bots did do some amount of pathfinding, it would not be that hard or complex (computatially sdpeaking) to implement an algorithm that chooses where to go based on max possible distance before needed to charge to some extent.

But at the very least, the game should make sure bots don't start looking to recharge when the can complete their assignment before running out of battery!!!

It would be possible to make robots pathing, but I personally prefer 10 000 beautiful idiot robot children (Thanks for the phrase r/Nicksaurus) rather then 1 000 smart robots.

I find the design which leaves it to the player to make robots more efficient part of the challange. That is why the change doesn't completely solve the lake problem at the end, as the robots would still get a huge speed penalty when going above a big lake without supporting charging places. So making a "bridge" of roboports for them is still desirable, but at least, this won't completely halt your factory.

about 1 year ago - /u/kovarex - Direct link

Originally posted by Weppet

I love it, does this mean that we can do bot megabases with one big network instead of many smaller ones? It seems that the queue system could really get rid of the problems that big networks have.

Lot of the advantages of separating networks still hold.

about 1 year ago - /u/kovarex - Direct link

Originally posted by Weppet

The main problems with big networks right now are (for me): resources get pulled from all over the base and bots migrate, this results in massive travel time and recharge time. I imagined this would be solved by being able to allocate bots to roboports and with the scheduling change. Sure, some resources might still be exchanged between lines of production but only if it's faster to do so, from what I understand.

Or are you also talking about UPS advantages?

Generally speaking, smaller network is somewhat more ups friendly, because there are less robots and charging places to choose from when doing the logic.We can optimise all we want, but I don't think it is possible to get the complexity to O(1) when choosing a roboport for charging for example, so the bigger network will always have some small penalty.

On the other hand, finding where to pick some specific material from actually has O(1) complexity, as we have a special data structure for that since the beginning, which is very nice, but the limitation of the data structure is, that you find "some" place where to drop the item, not the closest one.

about 1 year ago - /u/kovarex - Direct link

Originally posted by mrbaggins

It is quite clear, that there were things in the inventory which Scott just didn't want to show yet, so he just pasted the icon over.

You fool! Their location still tells us where they go in the tabs! Assuming one of the ones between roboports and combinators is the "Real" redwire, there's something there (Another colour? Or maybe coloured lamps or a new combinator. Leaning toward coloured or other variant lamps honestly.)

The other 5 after nuclear fuel are a bit harder. From memory of the inventory/tabs, the only thing after intermediates would be more science packs, then you're into the combat tab, so I'd probably guess new weapons/armor/toys

Wow, I didn't expect this kind of deduction!
There is bunch of things between the science packs and the military stuff indeed, and it is the "Space" tab. I guess that the information that we moved space related stuff (including existing rocket silo and satellite) into its own tab for easier navigation isn't that surprising after all.

about 1 year ago - /u/kovarex - Direct link

Originally posted by BraxbroWasTaken

Will a mod be able to adapt to whether or not the expansion is installed w/o requiring it as a hard dependency?

I assume the dependency will be the same as adding the expansion to the mod’s dependency list, so it’ll support optional and hard dependencies? Kinda like how all of the base game’s content is in __base__?

Currently this is not possible.

about 1 year ago - /u/Klonan - Direct link

Originally posted by Deranged40

For these 'smarts' we use a quite simple heuristic, factoring in not just how close the roboport is, but also how many other robots are currently charging there.

/u/factorioteam can you confirm that this will take into consideration "free spots" and not just blindly "how many are charging?" They seem very similar at first, but with modded roboports, we can have way more than 4 robots charging at once. So I just wanted to make sure that calculation will still consider open spots

It is the number of charging slots without any robots, so should work fine for modded roboports with more charge slots

about 1 year ago - /u/Klonan - Direct link

Originally posted by EpicRaginAsian

Wait so is weekly FFF back?

Yes :)

about 1 year ago - /u/kovarex - Direct link

Originally posted by UnGauchoCualquiera

On the the last gif (the lake one)

> always charge at a roboport that is closer to the destination than the robot is

Wouldn't that actually make them perform much worse in the much more common scenario of a perfect grid?

The perception of bots flying over available roboports but continuing on low energy might actually be worse than simply looping back and forth.

Example:

Given a fully covered 5x5 grid and a bot that travels diagonally from 1,1 to 5,5.

If it turns out mid flight at say 3,3 that it doesn't have enough juice it will try to recharge at 5,5 instead of the closer roboport at 3,3 and continue.

The robots always keep some reserve (10% I think), before they try to go for charging, which should probably be enough to make it work in a grid.






Recent Factorio Posts