Thank you all for your careful thoughts and consideration of this issue. I shall take the points out of order, as it will assist the clarity of the response. First of all, sixteen cities is a
very small number. Simutrans-Experimental combined with Pak128.Britain-Ex is intended to be able to simulate an area roughly the size of England to scale (at 250m/tile), with a realistic number of conurbations for an area of that size. Using a small map means that one only gets to use low-speed, local transport. Take the default size of 256x256 tiles (a default set, incidentally, back in the late 1990s, when computers were far less powerful than now). 256 x 250m = 64,000m or 64km. In other words, each side of the map is less than a third of the distance between London and Bristol. This is not far enough for express trains, let alone aircraft, to be worthwhile.
A good map size for a compelling game is something like 1280 x 512 or even 2048 x 768. To get a sensible density of towns and cities in a good variety of scale sizes in a map of that size, one needs about 100 - 250, with a median size of 2,500 - 6,000 each. A large size will be especially important when network multiplayer games become possible, as more players will need more space between them to build up a decent sized network each.
Sdog's saved game, which is
here is a modestly sized map, but considerably bigger than the default: something like 512 x 768, I think. It has something like (at a rough count) 64 cities. 64^2 = 4096.
However, given the way in which the current system works, it is not
quite an exponential growth. It might be sensible if I give an overview of how the system works, which, in its present state, is designed to maximise accuracy. Every time that the passenger generation routine is checking whether a private car trip is viable, it first checks to see whether the destination city is stored in the hashtable. If it is stored in the hashtable, it will retrieve the value, which is the average speed per straight line tile. This is then multiplied by the straight line distance between the actual origin and the actual destination of the packet of passengers to produce the travelling time. This travelling time is then compared with the travelling time for the players' transport, and the likelihood of passengers taking their own car as opposed to the players' transport is adjusted in proportion to the relative difference in travelling time between the two. Even when there is no such comparison, the journey time tolerance feature is used to check that the journey time is within the passengers' tolerances; if it is not, they will not travel. This is important, because passengers transported by car contribute to city growth just the same as passengers transported by any other means.
The travelling distance per straight line tile is calculated thus: a route is found between the road outside the townhall in the origin city and the road outside the townhall in the destination city. It is not enough just to measure from the boundary, since this ignores the part of the journey in the city itself, which is likely to be significant in the case of cities close together. The the minimum of the maximum speed of each road tile in the route and the average maximum private car speed (weighted by those cars' "chance" ratings) is summed then averaged for the
straight line distance between origin and destination, before being divided by a further factor to represent the fact that vehicles will inevitably travel at an average speed of somewhat less than the maximum speed. The average journey time per straight line tile is then calculated, which can then simply be multiplied by the straight line distance between origin and destination to get a realistic travelling time based on the directness of the route without having to measure the actual length of the route every time. If no route is found, 65535 (the highest number that can be stored in an unsigned 16-bit variable) is stored in the hashtable. If this value is detected, passengers will not register a private car trip at all.
Every time that a route is found between two cities (A and B, say), the journey time per straight line tile is added to
both cities' hashtables, so that the route does not need to be calculated backwards. Furthermore, it can be assumed that, if A is not connected to C, then, if B is connected to A, it, too, is not connected to B. So, whenever it is found that a city is
not connected to any city, it iterates through its list of cities that are connected to it in the hashtable, and puts the unconnected city as the key 65535 as the value in each of those hashtables. Further, industries already keep track of whether they are inside a city. When checking a route to an industry, the system first checks whether that industry is in a city. If so, the connexion data for that city is returned for the industry (treating the industry, in effect, as just another building in the city). These measures mean that the growth in the number of routes that it is necessary to calculate is less than exponential with the number of cities in the game.
If a private car trip is sought with an origin and destination in the same city, the trip is assumed to be possible: a route is not calculated, but the townhall road is used and assumed to have the same speed limit as the rest of the journey, which is then calculated in the normal way, save that an extra factor is added to approximate the difference between the straight line distance and the route distance.
I have thought at some length about using existing connexion data, as Dwachs suggests, but I can't see a way to make it work with the current system. Suppose we are at city A looking for a route to city C. We know that city A is connected to city B, and that the journey time per straight line tile is 5 tenths of a minute. How would that assist in knowing how many tenths of a minute per straight line tile it takes to get from city A to city C? For all the finding system knows, city B might be further away from city A than city C. We don't know the distance between cities A and B or B and C (or, before checking the route, avoiding which is the point of this exercise in the first place, A and C), and so cannot even calculate a proportion of the journey that should be assigned to the part between city B and city C at the known number of tenths of minute per straight line tile even if we do assume that the A is only connected to C via B, which may well not be the case: not only is it possible for there simply to be two roads (and not necessarily built on map generation: one of the roads may have been built by a player later, or the public service player), but the journey between B and C might well
pass through city A, and just happen to have been checked first. If there is a circuitous route between cities A and B, but a straight route between cities A and C, the B to C results will be positively misleading.
If the suggestion is to store something other than the journey time per straight line tile, then the problem with that is this: the method accessing the hashtable is called far more often than the route finding code, so speed there is even more important than in route finding. If the data are stored in as close as possible form to that in which it will need to be used, this will maximise the efficiency of the system at the point when it is used more heavily. There is no point in making it work better for the insertion end if that just makes the even more performance important extraction end worse.
I had also given some thought to the suggestions about making the feature a binary-only feature: in other words, not checking the journey time per tile at all, just checking whether a city is connected to another city, industry or attraction or not. However, this is of very limited use. By the time in the game when the proportion of people with access to a private car is high enough, most places should be connected to each other by road (or, at least, in real life would have been). The real issue in a great many cases will be whether the players' public transport connexions are better or worse than the road connexions, taking into account congestion. This is designed to give rise to particular gameplay considerations. For example, in a network game, suppose that the public service player is being directly played by a human: its goal is, unlike with other transport companies, whose goals are to maximise their profits, to maximise the economic growth of the region, measured by the population growth. The public service player will be faced with decisions such as: should a new, fast road be put in place to connect major towns together, which would allow a greater proportion of the people in those towns to travel than currently do, thus potentially leading to economic growth, or are the benefits of such a road outweighed by the increased congestion (which reduces population growth) or the fact that such a measure might undermine the viability of public transport connexions such that they would either have to be subsidised (meaning less public money available for other economy-boosting activities: installing more power lines, perhaps), or close down entirely (preventing those without access to a car from using them, or increasing congestion further)?
When the "assume_everywhere_connected_by_road" option is enabled, then city-to-city (and to industry and to attraction) time calculations are made in the same way as intra-city time calculations in the above method: it is assumed that every road tile will be of the current inter-city road type, and a factor added to approximate the fact that the road will likely not be straight.