News:

Simutrans.com Portal
Our Simutrans site. You can find everything about Simutrans from here.

Conceptual discussion: calibration of population/passenger generation/jobs

Started by jamespetts, September 12, 2013, 12:22:52 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

jamespetts

As I have intimated elsewhere, I am currently working on a particular issue on the passenger-generation branch of my Github repository which is causing no small difficulty with regard to how to calibrate it in principle.

As we know, the number of game hours in a game month (in other words, the relationship between the two distinct time scales used in the game) is determined by two variables: (1) the bits per month; and (2) the meters per tile. There are a number of parameters of various things that are based on the length of a month, such as passenger generation, factory production, electricity production/consumption and some maintenance costs. In the current version of Simutrans-Experimental, these are automatically scaled by bits per month, but not by meters per tile, which is wrong.

Given that I am working on re-calibrating passenger generation, I have corrected the anomaly in the passenger-generation branch. However, the question arises as to what the base level of calibration should be: in other words, for factory production, for example, if one puts "Productivity=14" in a .dat file for an industry, over what period should those 14 units be produced? What is the base-line month length at which the productivity in the game will be exactly 14, scaled neither up nor down?

My solution so far has been to start in principle with the original defaults from Standard: 18 bits per month and 1,000 meters per tile. That gives a month length of 3:12h as a base. That means that, if the combination of bits per month and meters per tile cause a month length to be, for example, 6:24h, a factory with "Productivity=14" in the .dat file will actually produce (taking out of account electricity, etc. for the time being) 28 units per game "month" (or 14 units for every 3:12 game hours).

What I have then done is allow the base meters per tile to be customisable in simuconf.tab (this part of the code is not yet complete: I am changing the hard-coded number for testing purposes). Using (nominal) a base of 7,500 meters per tile, the base game "month" becomes 24 hours or so: a day, in other words. This makes it much easier to calibrate for industry production, as real life production figures are usually given in weeks, months or years, which can easily be turned into days (indeed, the production figures are often given in days). So, for example, with "Productivity=14", that would give 14 units per 24 game hours, or 3.7 units per "month". This would require multiplying all existing factory production (base) figures by 3.75, but that should not inherently be too difficult.

This part is not the difficult part: the difficult part comes with jobs and population. One of the innovations on the passenger-generation branch is that passenger trips are split into commuting and non-commuting trips (in place of the old distance ranges): commuting trips require a destination that has jobs, and the number of jobs at each destination is restricted: once all the jobs are taken, no more passengers can travel to that building until jobs are available again. Job availability is time based: if, for example, a building has 100 jobs, once all the jobs are taken, it will slowly replenish the number of available jobs at the rate of 100 per game month (while all the while passengers travelling to that building deplete the number of jobs, which should result in an equilibrium).

This part of the code is already present and tested, and, subject to calibrating the number of jobs in factories and in other buildings according to the same scale, works well so far. The trouble is how to calibrate. There is no trouble in principle working out some sensible formula to convert the "level" values of buildings to a sensible numbers (nor with having separate values for jobs and population/visitor demand in the .dat files), save that the figures would not then produce sensible general figures for population or jobs unless the month length was in fact 24 hours.

Suppose that a bakery employs 6 people: those people go to work once a day, so the number of jobs equates to the number of daily passenger trips to that building that can be supported. If the game month length was 6:24h, the number of jobs per month would be 6 / 3.75 = 1.6 (which would be rounded down to 1 - rounding errors with low numbers is a separate issue here to which serious consideration needs to be given). However, in order for the figures for the total number of jobs in any given city/the game world to make any sense, they would have to correlate with the population figures (e.g., a town with 100 jobs and a population of 100 would have full employment with no labour shortage). The population level of a city would also have to correlate with the number of trips per game hour based on real world figures as to the number of trips that people actually make in any given period of time.

The trouble is, if the jobs that any given building is deemed to have is based on the number of jobs per game month, and the population that residential buildings accommodate calibrated accordingly, the population/job figures for any given town will be reduced proportionately to the number of "months" in 24 hours so that, for example, a town of 100,000 people in the game would have the passenger traffic of a town of 375,000 people.

One possible solution to all of this is to make some or all of these figures based, not on the length of a month at all, but the length of a notional day, although that would entail a fairly substantial departure from existing Simutrans ways of doing things. This would at least have the advantage that the rounding errors are abrogated, and a bakery would indeed have 6 not 1 (rounded down from 1.6) jobs.

Another way of doing things would simply be to adjust the reported population/job figures based on the ratio between the "month" length and the length of a day in the short-term time scale, but this would then entail a mismatch between the population/jobs numbers reported in individual buildings and the overall reported statistics, which would be confusing to players: this is not, after all, the latest version of SimCity.

I should be very interested in people's views on this somewhat vexed topic as to how to deal with these calibrational issues in a consistent way that does not involve more upheaval in the code and .dat files than is strictly necessary.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Philip

I'm afraid I don't wholly understand the issue, but one aspect of this is, or I think should be, that there is a distinction between the number of jobs at a factory—the maximum number of passengers that can be dropped off at once—and its labour consumption, which I would suggest is best expressed as a percentage of workdays per unit produced: a coal power plant producing 40 units per month might consume coal at 125% and labour at 10%, treating workdays of labour a little like other input resources. The 10% figure and the number of jobs (as the equivalent of the storage limit for input resources) wouldn't have to be scaled at all, and the number of jobs per game hour wouldn't even be displayed directly.

In other words, there is no reason a building with 100 jobs should replenish jobs at a rate of 100 jobs per game month, which I understood you to have said. 100 jobs should mean that a maximum of 100 passengers can be dropped off at once, just like a factory might have a storage limit of 200 crates but consume only 50 per game month.

I doubt it'll be possible to reuse much of the factory code, since labour should presumably be consumed even when no production happens and production shouldn't wait for labour to be delivered (at least for some factories), but I think the extra scale it gives us, units produced, is helpful, and the rounding problems have already been solved for input resources.

Of course it's true that there should be a fixed ratio between the number of jobs (the storage limit) and the consumption of labour (in workdays per game month, or work hours per game hour, or whatever), but there's no reason ever to display the latter, is there? After all, we don't make input resource consumption per game month or game hour visible for factories, either.

Or did I miss the issue entirely?

ӔO

I would like to just mention that, in real life, employment is never 100%, as there always needs to be some reserve work force for predictable loses, like retirees, vacations, sick, etc.
My Sketchup open project sources
various projects rolled up: http://dl.dropbox.com/u/17111233/Roll_up.rar

Colour safe chart:

Carl

I can't speak to the more general problem yet -- I'm not sure I understand the feature well enough. but I do have some questions and comments about the commuting/non-commuting distinction.

1. What kinds of buildings are going to be eligible to receive commuters? It won't, presumably, just be factories.

2. How will the commuter levels for non-factory buildings be set? Is this a .dat parameter, or just extrapolated from existing passenger_level?

3. What proportion of passengers will be commuters vs. non-commuters?

4. If building A has a maximum number of commuters of 300 per month, what happens when that limit is reached while some passengers heading to A are still en route? Will they be discarded, or will the building still be allowed to receive them?

5. Is there a danger that the "limit" behaviour will result in a flurry of passengers at the beginning of a month, followed by the flows gradually drying up as limits are met, until there are very few passengers at the end of a month?

6. What is the typical/maximum commute distance, and is the latter value configurable?

And a comment:

QuoteHowever, in order for the figures for the total number of jobs in any given city/the game world to make any sense, they would have to correlate with the population figures (e.g., a town with 100 jobs and a population of 100 would have full employment with no labour shortage).

This shouldn't be done on a per-town basis, I don't think, because of 'dormitory towns', where most of the population commutes to somewhere else for work. For example, I doubt there are anywhere near as many jobs as people in Burnley because most workers will commute to Leeds or Manchester (etc). Number of jobs should be related to population across the game world more broadly, of course.

But even then, the employed do not make up the whole population. The employment rate in the UK is 71% of those aged 16-64. When children and pensioners are taken into account, I would wager that this goes down towards 50%. So the number of jobs need not be even close to the total population.  More generally, if only (say) 60% of people are employed, then presumably a lower proportion of journeys than this will be for commuting. (Not all journeys made by employed people are commutes, but all journeys made by children, unemployed or pensioners are non-commutes, meaning that the percentage of commutes must be lower than the percentage of workers).

Sarlock

Lots to think about.  I've written four responses and deleted them each time as I started to lose my train of thought.  After spending over an hour doing that, I've decided to think about this for a few hours and get back to you - it's complex and has many permutations.

As I understand it, the core question you raise is how the interplay of bits per month and metres per tile impact the scale of population and passenger/mail/goods generation and what benchmark to use.

Productivity would ultimately need to be presented as: X goods produced over a Y day period at Z scale

[EDIT] This also is a good point to analyze what "bits per month" actually means.  Metres per tile is simple: it affects the scale of the world as a whole, though it has its own complex implications (should we have 64 factories instead of 1 if we move from 1km2 to 125m2?).  "bits per month" is meant to extend the length of a game.  With a +1 increment, this will double the time: should it double production of all passengers/mail/goods?  If it doesn't, this has the effect of slowing down the entire game as the player has twice the amount of game time to deal with the same monthly flow of goods.  If it does, this makes the notion of "scale" very difficult to define: a city of X people generates Y passengers but if you increase "bits" by 4, a city of x people generates 16Y passengers.  Or does this city now have 16X people generating 16Y passengers?  I'm still a bit new to the deeper meaning of these concepts in Sim-Ex so forgive me if I raise questions that are already well addressed.
Current projects: Pak128 Trees, blender graphics

jamespetts

Thank you all for your thoughtful replies - that is very helpful. I shall deal with the various issues raised in the sequence in which they have been raised, starting with the concept of labour consumption per hour. We need to be able to set the absolute number of jobs in the .dat files to make it reasonably easy to calibrate the game in the .dat files: if we used percentages, each factory for which this datum has to be calculated would involve manually converting an actual number of jobs from a research source into a percentage for that particular factory based on its production, which, given the number of factories for which calibration takes place, would not be feasible.

As to treating passengers in the same way as stored goods - that is more or less what the system that I have written does: in a factory with 100 jobs, if all jobs are available and 100 people are dropped off at once, the factory will initially have 0 jobs available, with that number increasing by 1 every 1/100th of a month (subject to any further inflow of passengers during that time). If more than 100 passengers are dropped off, the number will become negative, and still replenish at the same rate. No new passenger journeys to the factory can begin until the number is greater than zero. (This should answer Carl's question about what happens when passengers are already en route to a factory whose available jobs are used up). That is all very well, but we need to know, to make clear to the player, and properly to calibrate, the ratio between the number of jobs consumed in a game month and the actual number of jobs that the factory represents (which will be the same as the number of jobs consumed in 24 game hours, or possibly 16 game hours on the basis that we only simulate daytime traffic flows).

As to displaying what is described as the "consumption rate" for labour (which does make one think of statistics about the number of workers who contract tuberculosis, but that is another matter), this is already displayed in the current testing code: we show total/remaining jobs in the city building's information window. This is, in fact, done for factories, where the number of units currently in storage are shown with a large number of other statistics in the factory's information window.

Below is a work in progress example of how that appears in the game:



The success rates can be seen at the bottom, although these will need changing to reflect the abolition of distance ranges and replacement with trip types (in other words, commuter and visitor instead of local and non-local) and the fact that all non-residential buildings will need to measure the fulfilment of incoming visitor demand rather than the success at making outward trips.

As to the proportion of people who have a job (and the full employment example that I gave was just a simple example intended to illustrate the intended mathematical ratios between jobs and population rather than a statement of intention to simulate full employment), I see that as more a function of the city growth/building code in deciding where and how often to build/upgrade residential buildings, which is not being dealt with in the next major release, but should be dealt with in the major release after next (as that is a very large job all of its own). The system should be based on passenger success rates (in other words, a new house will only be built if greater than X% of all commuting journeys from residential buildings in surrounding tiles were successful within the last two months or thereabouts), which can then be calibrated to produce any given employment level (and, of course, depending on transport, there may well simultaneously people who cannot find jobs and jobs which cannot find people).

As to Carl's questions:

QuoteWhat kinds of buildings are going to be eligible to receive commuters? It won't, presumably, just be factories.

Indeed not - industrial and commercial city buildings will attract commuters, as will "tourist attractions" (I have renamed them "public amenities" in the latest English translation file, as they can be used to represent things that are not just for tourists, such as schools, hospitals, etc.), town halls, depots and, when I add the code for it, and if I can make it work properly, station extension buildings, as well, of course, as industries.

Quote2. How will the commuter levels for non-factory buildings be set? Is this a .dat parameter, or just extrapolated from existing passenger_level?

I have not finalised the detail for this yet, but I plan for there to be a separate .dat file parameter for the number of jobs in a building. If this is not specified, it will be based on the existing level.

Quote3. What proportion of passengers will be commuters vs. non-commuters?

This will be configurable in simuconf.tab

Quote4. If building A has a maximum number of commuters of 300 per month, what happens when that limit is reached while some passengers heading to A are still en route? Will they be discarded, or will the building still be allowed to receive them?

As explained above, the passengers will still go to the building, which will register negative jobs, with the result that it will take longer before any new passengers can begin a journey to it than if it were merely at zero jobs.

Quote5. Is there a danger that the "limit" behaviour will result in a flurry of passengers at the beginning of a month, followed by the flows gradually drying up as limits are met, until there are very few passengers at the end of a month?

There would be if the buildings replenished jobs all in one go at the beginning of each month, but, as explained above, they replenish gradually the whole time.

Quote6. What is the typical/maximum commute distance, and is the latter value configurable?

There is no restriction on distance: only time. The journey time tolerance range for commuting and visiting trips will be separately configurable from each other in simuconf.tab. For a realistic simulation, one should configure the commuting trips to have a much narrower tolerance range (something like 20 minutes to 1:30 hours) than visiting trips, which should have a very wide tolerance range (such as between 5 minutes and 24 hours). The selection of which journey time tolerance to use for any given passenger packet within the ranges will need to be biased (so that, for example, a far higher proportion of passengers have a journey time tolerance of less than rather than more than 6 hours), and the parameters for that bias should also be configurable in simuconf.tab, although I have not yet added the code for this.

As to dormatory towns, these should be possible: see above on town growth, the relevance of the full employment example and passenger success rates.

As to what "bits_per_month" means, this affects how many in-game hours pass before a new in-game month starts. Aside from causing any value that is calibrated by game month (such as the monthly maintenance of station buildings) to recalibrate itself accordingly, this setting has no other effect. For example, if a game lasts 3:12h at 18 bits per month and 1,000 meters per tile, increasing to 19 bits per month will increase the length of a month to 6:24h whilst keeping the ratio between an in-game hour and real time the same. The "monthly" cost of maintaining a station will double, but because the length of that month has also doubled, the cost per in-game hour remains fixed. The bits_per_month setting is intended to allow the pace of the game to be increased or decreased: the main purpose of this is to customise how fast that the era changes (and new vehicles, ways, etc. are introduced and retire) in comparison to the speed at which time passes in the game and in reality.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Carl

Thanks very much James for the comprehensive reply -- very useful. A few more questions and comments follow.

QuoteIndeed not - industrial and commercial city buildings will attract commuters, as will "tourist attractions" (I have renamed them "public amenities" in the latest English translation file, as they can be used to represent things that are not just for tourists, such as schools, hospitals, etc.), town halls, depots and, when I add the code for it, and if I can make it work properly, station extension buildings, as well, of course, as industries.

Excellent. One question about "public amenities". As I read the settings window now, these currently consume a configurable percentage of the total passenger flow. Is this behaviour to be abolished in favour of the jobs mechanic? I do wonder whether "tourist_percentage" causes as many problems as it solves. That said, many amenities generate traffic beyond merely their employees -- schools and hospitals are good examples -- so they will still require some source of passenger flow beyond their employees.

Similarly, will factory_worker_percentage be abolished? In contrast to amenities, I wouldn't expect factories to generate much passenger flow beyond their workers.

Quote
I plan for there to be a separate .dat file parameter for the number of jobs in a building. If this is not specified, it will be based on the existing level.

Two things:
1. I assume there will need to be a way to extrapolate a jobs figure from old pak files that don't have it specified.

2. If the .dat file specifies an absolute number of jobs for a building, this seems to make the passenger_factor setting somewhat obsolete (since commuter traffic will not scale with it). Or does passenger_factor only effect non-commuter traffic? If the latter, this might be in conflict with the idea that we can set commuter vs non-commuter ratios in simuconf.tab.

Quote
This will be configurable in simuconf.tab
Where there are new simuconf parameters, would it be possible to also add them to the in-game settings window too -- to allow for backwards compatibility with old savegames, as well as easier experimentation?


One more question. Given that short/mid/long range distances are being abolished, how will non-commuter traffic behave? Will it simply search for any random destination and have only one set of time tolerances?

Sarlock

Wonderful dialogue.  Not too much time this morning but I will address what I can and get back to it later in the day:

Quote"As to what "bits_per_month" means, this affects how many in-game hours pass before a new in-game month starts. Aside from causing any value that is calibrated by game month (such as the monthly maintenance of station buildings) to recalibrate itself accordingly, this setting has no other effect. For example, if a game lasts 3:12h at 18 bits per month and 1,000 meters per tile, increasing to 19 bits per month will increase the length of a month to 6:24h whilst keeping the ratio between an in-game hour and real time the same. The "monthly" cost of maintaining a station will double, but because the length of that month has also doubled, the cost per in-game hour remains fixed. The bits_per_month setting is intended to allow the pace of the game to be increased or decreased: the main purpose of this is to customise how fast that the era changes (and new vehicles, ways, etc. are introduced and retire) in comparison to the speed at which time passes in the game and in reality."

The core question is: an increase in "bits per month", all other things remaining equal, should this increase production rates of all goods/passengers as well?  If we are increasing the cost of maintaining the network then the answer would likely need to be "yes" as we would expect revenues to increase to offset the increased maintenance cost.  If this is the case, then we break the "realism" scale in the sense that suddenly our network becomes far more active over a period of game time (the Simutrans month is still a month long no matter what our bits setting is for translating it to our time scale).

We are applying two scales to our world to reduce it for use in the game: distance scale (metres per tile) and time scale (bits per month).  Distance scale would increase/decrease all items as the scale changes.  Time scale, in the purest mathematical basis, would not change anything.  A factory that produces 50 widgets at bits=19 would still produce 50 widgets at bits=20.  We just allow the player twice the time to transport those goods in the Simutrans month (need to come up with a good label to differentiate between a month as it exists to our Simutrans citizens and us as players).  The consequence is, of course, that at a high bits= figure, the game pace becomes very slow as monthly production is spread over such a long period of player time.

Off to work, more later.
Current projects: Pak128 Trees, blender graphics

jamespetts

QuoteOne question about "public amenities". As I read the settings window now, these currently consume a configurable percentage of the total passenger flow. Is this behaviour to be abolished in favour of the jobs mechanic? I do wonder whether "tourist_percentage" causes as many problems as it solves. That said, many amenities generate traffic beyond merely their employees -- schools and hospitals are good examples -- so they will still require some source of passenger flow beyond their employees.

Yes, indeed: the "tourist_percentage" and "factory_percentage" are to be abolished. Allocation of destinations will be based on weighting of the buildings by the number of jobs (for commuting trips) and by the visitor demand (for visting trips). You may well be correct about "tourist_percentage" causing as many problems as it solves - there is also the anomaly in the current system of commercial city buildings and industrial city buildings generating passengers, whereas tourist attractions and actual industries only consume passengers. In the new system, only residential buildings will generate passengers, and all other (relevant) buildings will consume passengers. As to passenger flows beyond employees - that is what visiting trips are for. The next stage in the coding of passenger generation after this conceptual issue is resolved is to separate jobs and visitor demand, and have allocation of commuting trips based on jobs and allocation of visiting trips based on visitor demand. Unlike with jobs, there will not be a limit on the number of visitors to any given building in any given period, but the extent to which demand is fulfilled will, when the city building/growth code is renewed, be used to inform which buildings are upgraded.

Quote1. I assume there will need to be a way to extrapolate a jobs figure from old pak files that don't have it specified.

Yes - the "level" will be used.

Quote2. If the .dat file specifies an absolute number of jobs for a building, this seems to make the passenger_factor setting somewhat obsolete (since commuter traffic will not scale with it). Or does passenger_factor only effect non-commuter traffic? If the latter, this might be in conflict with the idea that we can set commuter vs non-commuter ratios in simuconf.tab.

This is an interesting question, and I had not fully considered the implications of the issue that it raises. The passenger factor covers only the generation of passengers, rather than the demand for passengers. Further consideration will need to be given to whether any other adjustment is necessary. This calibration issue is actually very similar to the calibration issue that I raised in the original post, which is that, for the figures to make sense, 1 unit of population in the cities must (on average) make 1 round trip (one trip out, one trip back) to a commuting target once every 24 game hours (or, in fact, slightly less, to account for the fact that less than 100% of the population have jobs; but, in any event, the difference should be based on the percentage of those in jobs, rather than anything else). If this ratio is not maintained, the reported population levels relative to the number of passengers generated, the reported numbers of jobs relative to the number of passengers demanded, and the reported levels of jobs relative to the reported levels of population needed to sustain them will be miscalibrated and make no sense. Things such as the meters per tile and bits per month setting, and also the passenger factor are all capable in principle of skewing the relationship between these numbers. Any thoughts from anyone as to how the passenger factor can fit in with all of this would be appreciated (the leading option at present is just to leave it as it is, and make clear that all that is being altered is generation, not demand).

QuoteWhere there are new simuconf parameters, would it be possible to also add them to the in-game settings window too -- to allow for backwards compatibility with old savegames, as well as easier experimentation?

Yes, this should be done; remind me if I forget.

QuoteOne more question. Given that short/mid/long range distances are being abolished, how will non-commuter traffic behave? Will it simply search for any random destination and have only one set of time tolerances?

If I understand the question correctly, the answer is yes. Packets of passengers on visiting trips will search for a weighted random destination, the weighting being by the visitor demand of all buildings in the game world. After a destination is found, the game will work out what the fastest trip available to that packet of passengers is. If the total journey time (including walking to the initial transport stop, walking from the last transport stop to the destination, if applicable, and any waiting times) is within the passenger packet's tolerance, then the passenger makes the journey. If there is no route at all, or there is one outside the passenger packet's journey time tolerance, another destination is chosen at random, and the process continues until either the pre-set number of alternative destinations for that packet of passengers has expired (this is a random number selected from a range of numbers of alternative destinations, which range is specified in simuconf.tab) or the passengers find a viable route. The same process works for commuting journeys, except that the destination selection is weighted based on number of jobs rather than visitor demand, and there is an additional check as to whether there are any available jobs left before a route is calculated; if there are no available jobs left, the next destination (if the number of alternatives has not run out) is selected without checking for a route.

Quote from: Sarlock
The core question is: an increase in "bits per month", all other things remaining equal, should this increase production rates of all goods/passengers as well?  If we are increasing the cost of maintaining the network then the answer would likely need to be "yes" as we would expect revenues to increase to offset the increased maintenance cost.  If this is the case, then we break the "realism" scale in the sense that suddenly our network becomes far more active over a period of game time (the Simutrans month is still a month long no matter what our bits setting is for translating it to our time scale).

That depends on what you mean by "rate" here. Certainly, if you mean "per game month", then, yes, the amount of goods, passengers, etc. produced by game month is increased; but it is only increased by virtue of the fact that a game month comprises more game hours, combined with the fact that these rates are fixed against the number of game hours: if a factory produces 100 widgets an hour, if a "month" lasts six hours, it will produce twice as many widgets in a "month" than if a "month" lasts three hours, though its rate of widget production per hour remains constant.

All real simulation aspects of the game (production, cost, revenue, speed, journey time, etc.) of the game should be pegged to the distance scale (represented as to time in hours): all that is pegged to months and years, aside from statistics, is the progression of technology and the like.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Sarlock

Quote from: jamespetts on September 12, 2013, 09:19:43 PM
That depends on what you mean by "rate" here. Certainly, if you mean "per game month", then, yes, the amount of goods, passengers, etc. produced by game month is increased; but it is only increased by virtue of the fact that a game month comprises more game hours, combined with the fact that these rates are fixed against the number of game hours: if a factory produces 100 widgets an hour, if a "month" lasts six hours, it will produce twice as many widgets in a "month" than if a "month" lasts three hours, though its rate of widget production per hour remains constant.

All real simulation aspects of the game (production, cost, revenue, speed, journey time, etc.) of the game should be pegged to the distance scale (represented as to time in hours): all that is pegged to months and years, aside from statistics, is the progression of technology and the like.

Thank you for the clarification on how this should impact things.  The reason I focus on this is because if bits per month influences how many passengers, etc are created in a game month, then there is little connection to "real world" values unless the player is playing with the "bits per month" that we used to calibrate with.  Meaning: We design a dairy to have 100 employees and a production of 50 t/month as its base at a default bits per month (and distance scale).  Player increases bits per month to be a 4x multiplier (+2 bits) and thus the dairy will have 400 employees and produce 200 t/month.  From a scale perspective this dairy is overproducing what we would expect a "real world" dairy to produce, but has the same production rate in "real life" hours as it did as default.  This is primarily due to the fact that the speed of the vehicles does not change with time and distance scale changes.  It's an interesting reconciliation when you are dealing with fixed vehicle speeds, variable time and distance scales and attempting to base the numbers on some real world basis.  The real world comparative only works if the player is playing with the default bits and distance scale... which says to me that basing on real world numbers is probably only loosely applicable; what is most important is whether it "feels" right from a game flow perspective.
Current projects: Pak128 Trees, blender graphics

jamespetts

I am not sure that I fully understand the last point about calibration: the idea is that these figures are calibrated to be realistic based on the number of hours, not the number of months, and that, although the number of hours in a month may change, changing bits per month and meters per tile should not change the rate of production/consumption per hour for any given rate set in the .dat files.

The real difficulty is squaring these rates of production/consumption with absolute numbers of jobs and population, which would be the equivalent of the number of passengers per day (probably 16 rather than 24 hours on the basis that we only take into account daytime hours).

Edit: On further consideration, it is probably wise to remain with 24 hours rather than 16, or else we risk introducing anomalies with factories that really do produce all day, such as power stations and oil refineries.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

jamespetts

A further thought occurs to me about a possible means of solving this: if the idea is to use the base figures in the .dat files, based on 24 hours, then the statistics and displayed numbers for the total jobs/population could (perhaps optionally) be based on the numbers from the .dat files unadjusted for bits per month and meters per tile. (I suggest optionally, as this would not work well for paksets from Standard, for example, or that have been calibrated to use figures other than those based on 24 hours in the .dat files).

In that case, the displayed population and job figures and statistics would be automatically re-scaled to a nominal 24 hours/month which would provide a realistic ratio between the hourly passenger generation/demand rates and the absolute numbers of inhabitants/jobs.

I should be interested in any views on this approach.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Aquin

Part one: Calibration distance and time
I think the base parameters to think in are tiles and months (the time before next maintenance is due) and production. And the knobs to turn are meters per tile, months per year, and productivity per month and building.
So what will the knobs do to gameplay? Meters per tile will have a drastic effect on gameplay, Double meters per tile means the journey from a to b will take twice as long. Along with this maximum capacity of the route goes down.
Months per year will determine how fast you go through the timeline, should have only minor effects on balancing, but it will be easier for vehicles to earn their purchase prise before becoming obsolete.
Production, well more production is more stuff to move around, so its easier to fill the vehicles and easier to overcrowd the stations.
I would not try to couple any two of the three. Pak-designers should balance the pak for a given value of the three. The player should be allowed to fiddle around with those settings, but if he does he should not complain about broken balancing afterwards ;)

And then there is visual speed to make the game look nice to the player, this should be free to be anywhere between pause and fast forward to please the players convenience without impacting any blancing.

Part two: Passengers
There both three types of special buildings (attractions, industry and shops) and generic buildings (residential, industry and commercial). I would maintain these three categories when determining passenger destinations. Each building has a number of passangers it can consume per month, these would be jobs, clients or visitors. They are either level dependent or specified explicitly.
Each residential building has a number of passengers, these decide whether they need to go to work, go shopping or visit someone. Then they look at the list of available destinations of this type, decide for one, and check if there is a route. If there is a route the passenger starts his trip. The number of available passengers from this building is reduced accordingly.
Now tracing each individual passenger could be too bad for performance, so each building has a list of return-trips. Once a passenger starts his trip he adds his return-trip to the end of the list. When passengers arrive at a destination they wait for a given time before they start first return trip on the list. When they return to a residential building they increase the number of available passengers there again.



Carl

Quote from: jamespetts on September 14, 2013, 02:26:22 PM
A further thought occurs to me about a possible means of solving this: if the idea is to use the base figures in the .dat files, based on 24 hours, then the statistics and displayed numbers for the total jobs/population could (perhaps optionally) be based on the numbers from the .dat files unadjusted for bits per month and meters per tile. (I suggest optionally, as this would not work well for paksets from Standard, for example, or that have been calibrated to use figures other than those based on 24 hours in the .dat files).

In that case, the displayed population and job figures and statistics would be automatically re-scaled to a nominal 24 hours/month which would provide a realistic ratio between the hourly passenger generation/demand rates and the absolute numbers of inhabitants/jobs.

I should be interested in any views on this approach.
Insofar as I'm understanding this, it sounds like a good approach. (Thanks again for your comprehensive replies to my questions above).

Philip

I'm still confused about one thing: I think it's extremely confusing to say that the number of jobs or the population of a residential building depends on bits_per_month. The number of jobs per month or travellers per month varies, but that's a different concept! A building with 60 jobs and 60 jobs per month at bits_per_month 18 should have 240 jobs per month at bits_per_month 20, but not 240 jobs. Sorry for repeating myself on this point, but I think we're risking making the game unplayable at nonstandard bits_per_month values.

I'm finding it necessary to apply something like this patch to get things to compile, because the triply-overloaded function calc_adjusted_monthly_figure confuses gcc (also, the 64-bit version is using >> x where it should be using << -x); furthermore, jobs are never set for buildings that are constructed rather than loaded, so laden_abschliessen isn't called for them. This resulted in uninitialized jobs figures and much confusion.


diff --git a/dings/gebaeude.cc b/dings/gebaeude.cc
index 1ad1eba..2504645 100644
--- a/dings/gebaeude.cc
+++ b/dings/gebaeude.cc
@@ -142,6 +142,24 @@ gebaeude_t::gebaeude_t(karte_t *welt, koord3d pos, spieler_t *sp, const haus_til
spieler_t::add_maintenance(get_besitzer(), maint, tile->get_besch()->get_finance_waytype() );
}

+
+ if(tile->get_besch()->get_typ() == wohnung)
+ {
+ people.population = tile->get_besch()->get_population_and_visitor_demand_capacity() == 65535 ? tile->get_besch()->get_level() * welt->get_settings().get_population_per_level() : tile->get_besch()->get_population_and_visitor_demand_capacity();
+ adjusted_people.population = welt->calc_adjusted_monthly_figure(people.population);
+ }
+ else
+ {
+ people.visitor_demand = tile->get_besch()->get_population_and_visitor_demand_capacity() == 65535 ? tile->get_besch()->get_level() * welt->get_settings().get_visitor_demand_per_level() : tile->get_besch()->get_population_and_visitor_demand_capacity();
+ adjusted_people.visitor_demand = welt->calc_adjusted_monthly_figure(people.visitor_demand);
+ }
+
+ jobs = tile->get_besch()->get_employment_capacity() == 65535 ? (is_monument() || tile->get_besch()->get_typ() == wohnung) ? 0 : tile->get_besch()->get_level() * welt->get_settings().get_jobs_per_level() : tile->get_besch()->get_employment_capacity();
+ mail_demand = tile->get_besch()->get_mail_demand_and_production_capacity() == 65535 ? is_monument() ? 0 : tile->get_besch()->get_level() * welt->get_settings().get_mail_per_level() : tile->get_besch()->get_mail_demand_and_production_capacity();
+
+ adjusted_jobs = welt->calc_adjusted_monthly_figure(jobs);
+ adjusted_mail_demand = welt->calc_adjusted_monthly_figure(mail_demand);
+
grund_t *gr=welt->lookup(get_pos());
if(gr  &&  gr->get_weg_hang()!=gr->get_grund_hang()) {
set_yoff(-TILE_HEIGHT_STEP);
diff --git a/simworld.h b/simworld.h
index 5af7c19..f51042f 100644
--- a/simworld.h
+++ b/simworld.h
@@ -1337,7 +1337,7 @@ public:
// based on these real life values.
// Consider what to do about things already calibrated to a different level. (Answer: they could probably
// do with recalibration anyway).
-
+#if 0
sint32 calc_adjusted_monthly_figure(sint32 nominal_monthly_figure)
{
// Adjust for meters per tile
@@ -1359,7 +1359,7 @@ public:
return (sint32)(adjusted_monthly_figure >> (18l - ticks_per_world_month_shift));
}
}
-
+#endif
sint64 calc_adjusted_monthly_figure(sint64 nominal_monthly_figure)
{
// Adjust for meters per tile
@@ -1373,7 +1373,7 @@ public:
if (ticks_per_world_month_shift >= 18)
{
const sint64 adjusted_monthly_figure = nominal_monthly_figure / adjustment_factor;
- return (adjusted_monthly_figure >> (18ll - ticks_per_world_month_shift));
+ return (adjusted_monthly_figure << -(18ll - ticks_per_world_month_shift));
}
else
{
@@ -1382,6 +1382,7 @@ public:
}
}

+#if 0
uint32 calc_adjusted_monthly_figure(uint32 nominal_monthly_figure)
{
// Adjust for meters per tile
@@ -1403,6 +1404,7 @@ public:
return (uint32)(adjusted_monthly_figure >> (18u - ticks_per_world_month_shift));
}
}
+#endif

/**
* Standard timing conversion



EDIT: actually, calc_adjusted_monthly_figure should perform the left shift first, then the division, as the 32-bit version does. Sorry.

jamespetts

Thank you very much for the fixes - they are most helpful. I have applied all of the fixes bar the removal of the overloaded methods to my passenger-generation branch. As to the overloaded methods, may I ask what errors that you are getting in GCC? These triple overloaded methods are present on the 11.x branch and in the currently released versions, albeit with less code in them, so there should not be a problem with triple overloading here in principle. I did wonder at one point whether a template method might be better than overloading here, but concluded that it would be more cumbersome to call.

As to the more general point about population scaling, I think that I might have been unclear: what I am in the process of implementing is not the scaling of absolute population and jobs by the bits per month and meters per tile: quite the opposite in fact - the idea is to find a means of not scaling these things by meters per tile and bits per month whilst still scaling the hourly production/consumption rates. I have yet to write the code for calculating the population in any given city, but that will be based on the unadjusted figures, which is why I have retained them.

The one remaining anomaly which I have not worked out how to solve is that the graphs in the factory window (which represent factories' statistics, which are used in actual calculations, so cannot be changed easily merely for representational purposes) are based on the scaled numbers, whereas all other representations of jobs are based on the unscaled numbers. Any thoughts on how to deal with that would be much appreciated.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Philip

Thank you for your response, and as always for including the good parts of the patch; the #if 0 code wasn't meant for inclusion, just to demonstrate what I had to do. The problem is calling calc_adjusted_monthly_figure on the result of an atol() call in simwerkz.cc (this is on 32-bit linux, so longs are 32 bits but sint32 happens to be an int rather than a long). Here's a fix without explicit casting:


diff --git a/simwerkz.cc b/simwerkz.cc
index bfc7909..ce9d53e 100644
--- a/simwerkz.cc
+++ b/simwerkz.cc
@@ -5232,7 +5232,8 @@ const char *wkz_build_industries_land_t::work( karte_t *welt, spieler_t *sp, koo
// eventually adjust production
sint32 initial_prod = -1;
if (!strempty(default_param)) {
- initial_prod = welt->calc_adjusted_monthly_figure(atol(default_param + 2));
+ sint32 value = atol(default_param + 2);
+ initial_prod = welt->calc_adjusted_monthly_figure(value);
}

koord3d k = gr->get_pos();
@@ -5302,7 +5303,8 @@ const char *wkz_build_industries_city_t::work( karte_t *welt, spieler_t *sp, koo
// eventually adjust production
sint32 initial_prod = -1;
if (!strempty(default_param)) {
- initial_prod = welt->calc_adjusted_monthly_figure(atol(default_param + 2));
+ sint32 value = atol(default_param+2);
+ initial_prod = welt->calc_adjusted_monthly_figure(value);
}

k = gr->get_pos();
@@ -5406,7 +5408,8 @@ const char *wkz_build_factory_t::work( karte_t *welt, spieler_t *sp, koord3d k )
// eventually adjust production
sint32 initial_prod = -1;
if (!strempty(default_param)) {
- initial_prod = welt->calc_adjusted_monthly_figure(atol(default_param + 2));
+ sint32 value = atol(default_param+2);
+ initial_prod = welt->calc_adjusted_monthly_figure(value);
}

fabrik_t *f = fabrikbauer_t::baue_fabrik(welt, NULL, fab, initial_prod, rotation, gr->get_pos(), welt->get_spieler(1));



As for the calibration issue, I think I understand a little better now. Thank you for taking the time to explain! I'm experimenting with scaling things per "workday" rather than game month, to avoid rounding errors: jobs work properly, only being restored to the employment capacity even if there are two commutes per day (for testing purposes, though it's also true that returning home for lunch once was very common). I think renaming adjusted_population, in particular, would benefit code readability. Another place where workdays would make sense is for convoy spacing: with short months, 1 convoy/month can be too many, while one convoy per workday should work.

Would it make sense to limit the number of passengers en route to work, much like maximum_intransit_percentage does for goods? I don't think limiting the sum of employees already at the building and those on the way there to the employment capacity would cause a problem, and potentially avoid one.

Anyway, thank you again!
Philip

jamespetts

Thank you very much for that fix - that is most helpful. I have now incorporated that into the passenger-generation branch.

As to scaling by "workday", something similar is what is intended by the system of calibrating the .dat files to specify daily quantities, which are then scaled down into whatever proportion of a day that a "month" occupies. Is what you propose significantly different to this? If so, may I ask what the advantage would be?

As to renaming "adjusted_population", to what do you suggest that it be renamed?

Finally, on limiting the number of passengers en route to a particular workplace - it is hard to see what benefit that this will have. The current system allows the numbers to become negative, so that no new journeys are able to start until the number of jobs has once again replenished. Averaged out over only a handful of buildings, it is difficult to see that the far more complicated system of tracking individual packets of passengers would make a noticeable difference overall than this rather simpler system.

In any event, thank you again for your very helpful fixes, and do let me know if anything else needs clarifying, or if you have any further thoughts. Contributions always welcome!
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.