News:

The Forum Rules and Guidelines
Our forum has Rules and Guidelines. Please, be kind and read them ;).

Results of cleaning up the revenue code

Started by neroden, June 23, 2013, 03:28:54 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

neroden

(which isn't done yet, by the way).

One of my prime goals in cleaning up the revenue code was to remove duplicate code -- so that the displays shown in the goods window are actually *accurate*, rather than diverging for various reasons from the real code.

This is mostly working (with the exception of some passenger and mail code).

It has revealed some unfortunate things which were already present.

----
#1: The system for linearly fading the speedbonus in is elegant enough, and I have reimplemented it more elegantly.

However, the default settings in pak128.britain turn out to be very undesirable. 
- As currently implemented, nobody cares about speed for trips of less than 75 km.  (This was already going on.)  This is not an appropriate setting.  In reality, people care about speed for trips as short as 1 kilometers.
- The 'default' speedbonus is reached at 250 km. (155 miles). 

Now, the default speedbonuses are actually pretty small to start with.   I figured out what the speed bonuses actually mean; a speed bonus of "18" means that for every 1% increase in speed, the revenue will increase by... 1.8%.  So if you double speed, the revenue will multiply by 3.6.

With the current default meters_per_tile settings in experimental, 85 km is a huge, long trip across the map.  But it barely qualifies for a speed bonus, ending up with a bonus of 3.   However, the speed bonus goes up to huge numbers for trips of 123 kilometers, if you can manage it... which causes distortion by creating massive profit centers.  (A transoceanic flour route is raking in 40,000/month.)

So, the settings for "fading in" the speed bonus need to be changed.  It should probably start "fading in" at 1 km, and it should probably not increase nearly as much for large numbers.  Ideally, it would have a flat section of its range...

---
#2 It has also become clear that the base payment for fresh fish -- and also for fish -- is really a bit too high.  I wouldn't adjust this just yet, though.  I'm still trying to get rid of the "magic number 3"...

jamespetts

Thank you very much for working on this. I did try to eliminate this duplication a while back, but couldn't quite work out how to do it. This is much appreciated.

As to the speed bonus settings, this is interesting. This does explain why very long trips seem to be excessively profitable. We could do with a shallower fade angle. Do you have any particular settings in mind? Bear in mind that I am calibrating Pak128.Britain-Ex to be able to work with very, very large maps in multi-player (at least the actual scaled size of England, possibly larger again if there is a sizeable ocean in the middle, allowing long journeys whilst keeping computational cost and memory usage not much above the level for a much smaller map without an intervening ocean).

As to the fish revenues, might I ask why you think that they are too high? I have obtained my relative revenues from historical data on goods transport costs, which are recorded in the goods128.dat as follows:


# See W. M. Ackworth, "The Elements of Railway Economics" p. 107 for historical records
# of relative charges for passengers and different types of goods on the Liverpool &
# Manchester Railway and previous pages for similar rates for canals (freight only).
#
# Generally speaking, per ton per mile:
# Low value bulk: 1d
# Medium value bulk (incl. coal) 1 1/2d
# High value bulk (incl. clay) 2d
# Perishables and semi-manufactured (incl. flour, timber and finished metals) 2 1/2d
# Manufactured goods: 3d
# Passengers (per passenger): -
# 1.8d (first 10 miles)
# 1.5d (next 20 miles)
# 1.4d (thereafter)
#
# Cattle (per head)
# 2d (first 15 miles)
# 1.4d (thereafter)
# Note that the LMR was only 35 miles long.
#
# See ibid pp. 111 and onwards for the later RCH classification system, as follows:
# A: Coal, coke, iron ore, furnace slag
# B: Clay, sand, manure, limestone, chalk, salt, unfinished stone, zinc ore, copper ore, bricks, paving stones, pig iron
# C: Hay, straw, grain, flour, seeds, fertiliser, chemicals, lead ore, part-finished iron goods
# I: Iron/steel hoops, pipes, sheets, plates, common fruit and vegetables, paper, cotton, beer in casks, oil in caks, tin ore
# II: Beer in bottles, wine in casks, bacon, biscuits, brass, china in casks or crates, coconut matting, nickel ore
# III: Cotton and linen goods, cured bacon, blankets, books, boots in casks, cases or boxes, china in hampers, woollen cloth, tea, silver ore
# IV: Pineapples, fresh cured meats, china in boxes or cases, woollen cloth in boxes, cases parcels or hampers.
# V: Amber, dyes, peaches and apricots, bonnet boxes, basketwork, bismouth, clocks, hats, artificial flowers, silk
#
# 1844 Act - 1d/mile for "parliamentary" vehicles for passengers.
#
# Ackworth, p. 145 has a table of maximum charges for each class for the GER, which was similar to that for other railway companies.
# This dates from around the 1890s as far as can be ascertained. (See for example:
# http://digital.slv.vic.gov.au/view/action/nmets.do?DOCCHOICE=771636.xml&dvs=1327967822965~470&locale=en_GB&search_terms=&adjacency=&usePid1=true&usePid2=true )
#
# Figures are all per ton per mile
#
# Class First 20 miles Next 30 miles Next 50 miles Remainder
# A 1.15d 0.90d 0.45d 0.40d
# B 1.40d 1.05d 0.80d 0.55d
# C 1.80d 1.50d 1.20d 0.70d
# I 2.20d 1.85d 1.40d 1.00d
# II 2.65d 2.30d 1.80d 1.50d
# III 3.10d 2.65d 2.00d 1.80d
# IV 3.60d 3.15d 2.50d 2.20d
# V 4.30d 3.70d 3.25d 2.50d
#


The price for fish is not specifically given, but I have treated it as class II. Should it perhaps instead be treated as class I, having a similar revenue to common fruit and vegetables?

neroden

Quote from: jamespetts on June 23, 2013, 03:47:27 PM
The price for fish is not specifically given, but I have treated it as class II. Should it perhaps instead be treated as class I, having a similar revenue to common fruit and vegetables?

Yes.  I think that's right.

QuoteDo you have any particular settings in mind?
So here's where it gets tricky.  :-) 

* First of all, I'd actually like to have more points to tweak.  I've defined a generic piecewise linear implementation, and I think this case might be significantly better off with four points rather than three.

* Second, I'm not at all sure I like the way the speedbonus is currently implemented.  It's a bit weird.  I'd kind of like something more clearly proportional to travel time (rather than to speed).

* Third, if we don't make those major changes, I actually think speed sensitivity should *drop* after a certain distance.  So I'd suggest something like this:

- I'd set the actual minimum very low, at maybe 1 km.

- Right now, it's not really good to have maps larger than about 4096x4096.  And anything larger than 32768x32768 requires major changes to the internals of simutrans.  At 125 meters/tile, this means that 8000 km is as long a trip as you're going to manage for the largest possible map and 256 km is more typical for "halfway across the map".  (Anyway, the UK is less than 1500 km long.  If we were doing pak128.US, or god forbid, pak128.Russia, we'd have a lot longer distances to think about.)

- So I'd fade it up to "standard" speedbonus, whatever we decide that that is, at around 160 km.  (And we might want to increase the standard speedbonus.)  This has the advantage of being "commuter belt" range, a range which is highly speed-sensitive.

- Then I'd have a long, very slow, fade *downward* to 50% of the standard speedbonus at around 1000 km.

jamespetts

#3
This bell curve idea is interesting. May I ask: does it originate in real life data? What exactly is the basis for the idea of having it reduce at higher distances?

As to the basic implementation, this was adapted from Standard so that speed bonus data from Standard paksets make sense when read into Experimental. It is difficult to see how a fundamentally different system might manage this.

Edit: I notice that in your latest mail-revenue branch commits, you have done this in base-texts-experimental.dat:


obj=program_text
+name=gl_btn_sort_weight
+note=Sorting by weight in the goods list
+-
+obj=program_text
name=signale bauen
note=Text for the automatic signal builder


This is not correct: additional text definitions need to go into a new file, and new files uploaded as necessary. Old files are not routinely re-uploaded, so this text will be missed.

Edit: I notice that with your latest commit in this branch, you have removed this line from einstellungen.cc:


livery_t liv = {liv_name, intro};


This relates to the livery feature rather than revenue - was this on purpose? It does not appear to be related to the commit message.

neroden

Quote from: jamespetts on June 23, 2013, 04:51:31 PM
This bell curve idea is interesting. May I ask: does it originate in real life data? What exactly is the basis for the idea of having it reduce at higher distances?
Time-sensitivity of passengers does seem to drop off a lot for very long trip times, where you are probably making the trip quite rarely and will have to stay more than overnight at your destination.  People start being more price-conscious and taking the slower alternative.  Consider the commercial failure of the Concorde.  This doesn't happen in "commuter" distances.

Quote
As to the basic implementation, this was adapted from Standard so that speed bonus data from Standard paksets make sense when read into Experimental. It is difficult to see how a fundamentally different system might manage this.
Yeah.  :sigh:  It would be possible to have a switch, set by a pakset, to use an alternative system.  I'll think about that.  If I can think of an alternative system.  :-)

Quote
Edit: I notice that in your latest mail-revenue branch commits, you have done this in base-texts-experimental.dat:


obj=program_text
+name=gl_btn_sort_weight
+note=Sorting by weight in the goods list
+-
+obj=program_text
name=signale bauen
note=Text for the automatic signal builder


This is not correct: additional text definitions need to go into a new file, and new files uploaded as necessary. Old files are not routinely re-uploaded, so this text will be missed.
OK, feel free to implement it properly.  Do I need a base_texts_experimental_11.0.dat?  (There are probably several new base texts due to the revenue code rerwrite.)

I was getting annoyed at the inability to sort by weight.  Now I can.  At the moment I have not been concerning myself with translation issues.  Most texts will read OK in English without translation, with these button names being the exception.

The method of base text delivery is baroque, and if you could explain it that would be appreciated.  I'm pretty sure some of the base texts are obsolete and not present in current versions -- is there any way to get rid of them?

Quote
Edit: I notice that with your latest commit in this branch, you have removed this line from einstellungen.cc:


livery_t liv = {liv_name, intro};


This relates to the livery feature rather than revenue - was this on purpose? It does not appear to be related to the commit message.
GCC pointed out that it was dead code.  "Variable liv set but never used".  I was just fixing warnings so that I could find the warnings which related to what I was actually doing.

jamespetts

Thank you for your replies. Ahh, if it was dead code, then that seems sensible enough.

As to text, each new string written into the code has to be added to a base_texts_experimental_xx.dat file, and uploaded to Simutranslator. I usually write a base texts file for each release cycle, and upload the texts shortly before release to enable people to start translating.

As to removing base texts - a few of them are obsolete, I think. I am not quite sure how to remove them: I think that that would have to be done one by one in Simutranslator.

On the commercial failure of Concorde - that is interesting. Was that not caused in large part by its operating costs being so high that most people could plain not afford a sufficiently high fare to make it profitable enough, combined with the fact that, after it crashed, fewer people wanted to fly it than before, rather than any inherent lack of preference for faster long distance travel? Or is your point in any event that affordability in effect puts a constraint on the price sensitivity for speed in very long journeys? I should be interested in any research on this, since none of the transport economics texts that I have read refer to this.

(On a related point, the true position is that price is actually set by reference to speed relative to the competition - but I have not worked out a satisfactory way of doing this yet, as defining exactly what counts as "the competition" in Simutrans is a conceptually very difficult task).

neroden

Quote from: jamespetts on June 24, 2013, 09:41:56 AM
Or is your point in any event that affordability in effect puts a constraint on the price sensitivity for speed in very long journeys?

That's my point.

If we actually implemented a system where the player could set prices for trips, and where passengers had differing price-sensitivities (which is way more complicated), then we could implement that directly.

Since we are hand-waving and saying "Well, this is what the market will bear, you will make this much", then the fact is that affordability sets a limit on how much extra you can charge for long trips, much more severely than for short trips.  Perhaps this is due to the fact that the base price for a long trips is so much larger than for short trips, so an extra 10% causes a lot more sticker shock for a long trip than for a short trip.

jamespetts

Ahh, yes, I see the point, which seems reasonable. I haven't had time to check yet - have you implemented the downward phasing in your pakset tweaks (or does this require a code change)?