Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

priority being ignored for multi item deliveries, and when using train limits #128

Open
jagoly opened this issue Oct 6, 2023 · 0 comments

Comments

@jagoly
Copy link
Contributor

jagoly commented Oct 6, 2023

Issue 1: Multi Item Deliveries

create_manifest is able to handle multi-item deliveries in cases where a train has spare capacity after the primary item has been assigned space. The issue with the current implementation is that these extra items do not respect priority at all.

For example:

  • provider A provides X and Y, with Y set to priority 0
  • provider B provides Y, with Y set to priority 10
  • requester C requests both X and Y

In this case, if tick_dispatch generates an order to deliver X from A to C, then that order can also include Y, even when B also has Y available with higher priority.

Note that this is dependent on tick_dispatch randomly choosing X rather than Y. If Y is chosen, then it will generate a delivery for Y from B, and then on the next tick will generate a delivery for X from A.

Multi item deliveries in general are only possible in cases where multi-requesters can drop below the threshold for multiple items in between requests being generated, which can happen in any of these cases:

  • the number of trains available is not enough to meet demand
  • the requester has a train limit set
  • rarely, if two items just happen to run low within a few ticks of each other

On its own, this issue isn't too hard to fix. Just have create_manifest re-do most of the search done in tick_dispatch for each extra item and remove them if either a higher priority provider or requester with enough supply or demand is found. This would be done only once we already know there is space in the train for each item.

This isn't a perfect solution, since for that I think we'd need to go through ALL providers and requesters and work out if there's enough demand/supply for other stations to balance things out, which is not at all feasible. Perfect or not, I think that making sure that priority is consistently respected is more important than avoiding a superfluous delivery in some very rare edge cases.

Issue 2: Train Limits

The other case where priority is ignored is when you have train limits set on your providers or requesters. When tick_dispatch goes through providers or requesters, a station at it's train limit is simply skipped over entirely. In those cases, other providers or requesters might be used even when they have lower priority. I can think of two possible solutions.

Solution 1

The first solution would be to just reserve trains beyond train limits, and just have them wait at the depot until the station is free. This is my preferred solution since it's very simple to do, requiring few code changes. If we remember that this should only happen when a station is higher priority than all others (equal priority stations that are below their limit still get serviced first), then it seems reasonable to me to have a train idle for a bit if it means that high priority stations will be properly respected.

Solution 2

The second solution I came up with and wrote down first, and now compared to just reserving trains I think it's absolutely not the way to go, but I've decided to include it here because why not.

In tick_dispatch, instead of skipping over stations at train limit, the manifest (along with the provider and requester ids) should instead be added to a list of manifests not assigned to any trains. We also need to update both stations deliveries information. These manifests are only generated if there are no providers/requesters with equal or higher priority.

At the start of tick_dispatch we'd then go through the list of manifests and if we find one with both it's provider and requester now below their limits, we search for an available train, if we find one we then we remove the manifest from the global list and pass it to create_delivery as usual.

The main issue I see with this solution is that creating the manifest without a train means we can't limit item counts to what the train can actually carry. In the case where the requester is the one at it's train limit, this means that the provider wouldn't be able to provide those extra items to some other requester.

Bonus Issue: Networks

Priority is completely ignored across networks. If for example a station provides items on two networks, for example because it provides a byproduct, and you have a low priority requester on the second network that voids items, whether items go to the void station or higher priority stations on the main network is completely random. If you are only using one network with masks then this isn't an issue, but many players do use separate networks like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant