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

Add: Option for population-linear town cargo generation #6965

Merged
merged 1 commit into from Mar 4, 2019

Conversation

nielsmh
Copy link
Contributor

@nielsmh nielsmh commented Nov 8, 2018

Introduce a new default algorithm for town cargo generation (passengers and mail), and a game setting to choose between the new and original algorithm.

The original town cargo generation algorithm has the property of the generated amount relating to the square of each building's population, meaning large towns easily produce more cargo than can realistically be transported. The problem is excessive cargo is amplified if playing with cargodist.

The new algorithm introduced instead has a linear relation to the population. The result is that smaller towns will produce slightly more cargo, while the largest towns will produce about a fourth of what they would with the original algorithm.

Existing savegames will use the original algorithm, while new games will default to the new algorithm.

@nielsmh
Copy link
Contributor Author

nielsmh commented Nov 8, 2018

Some preliminary playtesting is positive, but lots of people probably need to play lots of games with these new algorithms to test their worth.

In the meantime, here's a simulation in Python that shows how the various algorithms perform.

@nielsmh
Copy link
Contributor Author

nielsmh commented Nov 25, 2018

Having played a bunch with it now, it feels like the smallest generation amount is too little. The medium amount (whether it's the flat or the binomial version) are a bit much. It might be necessary to have a bit of non-linearity by building size, just not as extreme as the original algorithm.

@TrueBrain
Copy link
Member

We recently switched from Jenkins as CI to Azure Pipelines as CI. This means you need to rebase before this Pull Request will pass its checks. Sorry for the troubles!

@PeterN
Copy link
Member

PeterN commented Jan 20, 2019

Massive population definitely struck me as broken. I think we should fix it rather than give players yet another choice.

@ldpl
Copy link
Contributor

ldpl commented Jan 20, 2019

@PeterN, sadly harm is already done. Changing it will break old network saves and goal servers/scores/gamescripts that rely on certain population output. So as much as I prefer doing things one right way here I'd really like to see an option to keep old behavior for compatibility. It's also not a bad idea to have some way of adjusting population output as it may have some interesting use cases. Though I'd probably prefer just a multiplier for that instead of algo switch.

@LordAro
Copy link
Member

LordAro commented Jan 20, 2019

Defaulting to the original for old saves and using a new method for new games should be doable

@ldpl
Copy link
Contributor

ldpl commented Jan 20, 2019

@LordAro sure, but that still requires an option. And it's probably not a good idea to make that option hidden (if that even possible) in case someone wants to update his save.

@ldpl
Copy link
Contributor

ldpl commented Jan 20, 2019

Btw, just though of an interesting application for adjustable pop output. Make it quite low to force players to build bus transfers to fill the trains. Some may even call that more realistic xD

@PeterN
Copy link
Member

PeterN commented Feb 3, 2019

I'm sure goal servers / gamescripts can also be changed. We shouldn't add options to replicate buggy behaviour.

@nielsmh
Copy link
Contributor Author

nielsmh commented Feb 3, 2019

I'm for having generation algorithm a game option (as already implemented in this PR), defaulting old savegames to the old algorithm, and making the default for new games a new algorithm.

@Eddi-z
Copy link
Contributor

Eddi-z commented Feb 3, 2019

I'm for having a low/medium/high setting, but i don't really see a reason to keep original. I mean, we sort of guarantee that you can load old savegames, but not that they behave the same way.

@nielsmh
Copy link
Contributor Author

nielsmh commented Feb 3, 2019

I would expect players who load their ten year old save, and find their network is suddenly completely misdimensioned for the passenger amount, will get very annoyed.

But I can confirm that the passenger generation currently does match TTD (DOS version) so this behaviour is not something "invented" by OTTD.

@James103
Copy link
Contributor

James103 commented Feb 3, 2019

How about a custom town generation algorithm defined by a few game settings?

  • The formula is A * x^B. (in words: some value A times the house size raised to some value B)
  • The "A" parameter by default matches the original town generation algorithm as closely as possible. The corresponding game setting allows for further tweaking of the 'A' parameter from 1/16x to 16x in 1/16 increments. Default setting: 1x (same as original town cargo generation method)
  • The "B" parameter allows you to specify whether the town cargo generation shall be linear (1.0), superlinear (1.5), or quadratic like the original (2.0) with respect to the house size. Default setting: 2.0 (quadratic) for old save games, 1.0 (linear) for new games.

If players wanted a more realistic simulation, then they could reduce the 'A' and/or 'B' parameters. if they wanted a bigger challenge (or just more people to transport), they could increase the 'A' and/or 'B' parameters. Currently, the only workarounds to modify town cargo generation would either be very impractical (mostly due to NewGRFs) or would break various AIs and Game Scripts that depend on specific town populations, station ratings, or vehicle capacities to work.

Those settings could be accessible to Game Scripts so a Game Script could simulate real-world changes in passenger demand, such as rush hour (double the passengers) or during the night (half the passengers).

@PikkaBird
Copy link

PikkaBird commented Feb 3, 2019

Can I throw a few spanners in the general direction?

Firstly, it's by no means unrealistic that denser housing / activity areas produce more transport activity per resident. So I don't think we should make this change on the grounds of "realism". Nor is it undesirable, from a gameplay point of view, to have passenger production increase at a higher rate than the physical/visual size of the town. So I don't think we should make this change on the grounds of "gameplay" - at least, not without a lot more testing and evidence.

Secondly, the population, distribution, and cargo production of houses is entirely controllable in NewGRF, including overriding the relationship between population and production. Don't we typically avoid hard-coding features which can be accomplished in GRF?

Thirdly, "overproduction of passengers" is something most complained about when players use cargodist. The best solution to that problem probably lies in altering cargo distribution, rather than cargo production.

Lastly, adding multiple models (or a variable algorithm) and expecting players to find their own preferred setting is a design cop-out. IMO, before any "new town production" feature is considered (much less made a default setting), proponents should pick ONE model, and justify it as being the best option.

@nielsmh
Copy link
Contributor Author

nielsmh commented Feb 3, 2019

@James103 While a non-square non-linear distribution would be nice, keep in mind that all game logic code must be integer math, meaning your suggestions would probably require including some quite large pre-calculated logarithm tables in the code.

And @PikkaBird may have a point.

@Eddi-z
Copy link
Contributor

Eddi-z commented Feb 3, 2019

Thirdly, "overproduction of passengers" is something most complained about when players use cargodist. The best solution to that problem probably lies in altering cargo distribution, rather than cargo production.

i don't think that is a feasible approach, on two grounds

  1. with cargodist, if passengers travel on average N stops, you need N times the capacity of vehicles
  2. without cargodist, you can just ignore all overproduction, whereas with cargodist, everything generally collapses if links are overloaded

both these things are in the very nature of cargodist, and not dependent on any particular implementation detail that you could reasonably alter without dismantling the whole concept.

@nielsmh
Copy link
Contributor Author

nielsmh commented Feb 3, 2019

In the test game I played, with cargodist and the Medium new method, I still ended up with oversaturated links that were difficult to serve well. The issue there seemed to be that passengers were pretty much equally likely to go to a tiny village in the middle of nowhere, as they were to go to the metropolis two stops away.

@nielsmh
Copy link
Contributor Author

nielsmh commented Feb 3, 2019

So far just fixed saveload-version, going to clean up a bit more after this.

@nielsmh nielsmh added needs triage This issue needs further investigation before it becomes actionable and removed waiting on author labels Feb 3, 2019
@nielsmh nielsmh changed the title Add: Four alternative town cargo generation methods Add: Option for population-linear town cargo generation Feb 3, 2019
@nielsmh
Copy link
Contributor Author

nielsmh commented Feb 7, 2019

Savegame version fixed (again), everything squashed, and I believe ready for review.

@nielsmh
Copy link
Contributor Author

nielsmh commented Feb 13, 2019

Thought about merging this: Wait until after 1.9.0, then let it get a long cycle of testing and feedback before (possibly) hitting a release.

@PeterN
Copy link
Member

PeterN commented Feb 13, 2019

As long as original is original, I don't see an issue merging in the beta window. New algorithm can be tweaked if necessary. EDIT: I had not read the comments above, though :p

@audaki
Copy link

audaki commented Feb 15, 2019

I can vouch for the game design aspect of the original patches I submitted, PAX was still a moneymaker for big networks but I no longer needed train stations as big as the city itself to transport everyone...

@audaki
Copy link

audaki commented Feb 15, 2019

@PikkaBird The problem was/is with the old algorithm that the expectations of the NewGRF editor did not match the output.

Houses actually have an exact amount of residents configurable in the .grf! But let's say you are a .grf editor. You make one house tile with 5 residents and one house tile with 250 residents. You'd expect that the second tile has 50 times the generated passenger count, right? Sadly wrong, the second house generates 2500 (!) times as many passengers as the first one! (quadratic growth: 50^2)

If the first house generated 10 passengers per year, the second one will generate 25,000 passengers per year.

Honestly, guys, noone should argue for keeping the old algorithm, especially not when looking at .grf editors/modders. This is very counter intuitive.

@PeterN
Copy link
Member

PeterN commented Feb 15, 2019

But what's the right algorithm?

@Eddi-z
Copy link
Contributor

Eddi-z commented Feb 15, 2019

I don't know if there is a "right algorithm", but i can honestly say that as soon as i read the original breakdown of how the existing algorithm really works, i immediately recognized it as "wrong algorithm". nothing has changed my opinion since then. (talking about this thread)

@nielsmh
Copy link
Contributor Author

nielsmh commented Feb 20, 2019

Explaining the new algorithm implemented here:

Every 1024 ticks (13.8 days) a house has a chance to produce passengers. On this tick, one in every 8 population in the house (rounded up) has a 50% chance of making a trip. So a small house with 14 population will produce in average 1 passenger every month, and a larger house with 140 population will produce in average 4.4 passengers twice a month.

Mail generation follows the same pattern, just using the separate mail_generation value for each house rather than its population value.

@James103
Copy link
Contributor

I think that the population-linear town cargo generation should be implemented in a general way where every 1024 ticks (13.8 days), everyone in a house has a X / 256 chance of making a trip, where X can range from 1 to 256. @nielsmh says on 2019-02-20 that "one in every 8 population in the house (rounded up) has a 50% chance of making a trip". 1/8 * 50% = 1/16 = 16/256. This value of X would be changeable in a game setting in case someone does not like the default value of 16, which corresponds to ~0.14 passengers per person per month. The minimum value of 1 would correspond to ~0.0086 passengers per person per month, while the maximum of 256 would correspond to ~2.2 passengers per person per month. Mail would follow the same logic, but with a different default value that's lower than the passenger default value.

@nielsmh
Copy link
Contributor Author

nielsmh commented Feb 21, 2019

The reason for every 1/8 of the population getting a chance to make a trip is because the max population in a house is 255, and the coin flips are produced via a 32 bit random number. The maximum population of the house is divided evenly across those 32 chances, giving 8 population required for each chance to be considered.

Also my above comment was wrong, a 14 pop house will produce in average 2 passengers a month: Two chances each month, each chance has two coin flips to produce a passenger, so in total 4 * ½ passengers generated.

The easiest way to adjust my new algorithm is to change how often the production chance is calculated. The 1024 ticks comes from every fourth visit to the house (each house is visited once every 256 ticks for the general tile loop), but can easily be reduced to every 512 or every 256 ticks, to double or quadruple the production rate. A quadrupling of the rate would be equivalent to every house producing at the same rate as the largest houses do in the original algorithm.

With the current new rate, you'll need a good feeder network in a city to make large airports and train stations worthwhile, and quadrupling it should make even small-medium size towns produce more passengers than a single train can handle.

@James103
Copy link
Contributor

I did not realize that the tileloop hits all tiles every 256 ticks and that the 32d2 rolls (32 coin flips) are produced by a single 32-bit random integer. Still, I would like if there was a game setting that controlled how frequent do the towns produce their cargo, basically acting like a divisor to town cargo generation rates. Every X ticks, 1/8 of a house's population has a 50% or 1/2 chance of making a trip. X can range from 256 to 4096 (or higher if necessary, up to a hard limit of 65536) in steps of 256. The default value is 1024 ticks, as per @nielsmh's comments.

@nielsmh
Copy link
Contributor Author

nielsmh commented Feb 23, 2019

I tried setting up a scenario with some large cities (30k+ pop), build an airport outside, and set up a bus route of about 10 stops circling the city, and dropping off at the airport. Did that for two cities. Enabled cargodist for passengers (asymmetric), and set up bus routes going both ways around the circle.

Result is that even with 20+20 Foster MkII Superbus on the routes, the bus stops get overloaded. Of course, switching back to the original algorithm makes the numbers explode further, but there's still challenge with the new, linear production scale, now it just feels more achievable.

image

@audaki
Copy link

audaki commented Feb 24, 2019

@nielsmh You know what you really should test with your current build? My main concern was never that the big cities have too much passengers (they do!!) my main concern was that small cities had too few. Try some small village bus lines, with the linear passenger generation they are finally somewhat profitable :)

PS: The quadratic passenger generation always meant that small cities had too few PAX, medium cities were fine and big cities had too much. Both ends of the curve should be fixed with linear and probably should be playtested

@nielsmh
Copy link
Contributor Author

nielsmh commented Feb 24, 2019

So something like this case you're thinking of?

image

@audaki
Copy link

audaki commented Feb 24, 2019

Yes exactly 👍 thank you

@TrueBrain TrueBrain added needs testing and removed needs triage This issue needs further investigation before it becomes actionable labels Mar 3, 2019
@TrueBrain TrueBrain added this to the 1.10.0 milestone Mar 3, 2019
Introduce a new default algorithm for town cargo generation (passengers and mail), and a game setting to choose between the new and original algorithm.

The original town cargo generation algorithm has the property of the generated amount relating to the square of each building's population, meaning large towns easily produce more cargo than can realistically be transported. The problem is excessive cargo is amplified if playing with cargodist.

The new algorithm introduced instead has a linear relation to the population. The result is that smaller towns will produce slightly more cargo, while the largest towns will produce about a fourth of what they would with the original algorithm.

Existing savegames will use the original algorithm, while new games will default to the new algorithm.
@nielsmh nielsmh merged commit 52572ca into OpenTTD:master Mar 4, 2019
@nielsmh nielsmh deleted the house-cargogen-counter branch March 4, 2019 21:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants