News:

Simutrans Forum Archive
A complete record of the old Simutrans Forum.

[Patch] Competition with private cars and passenger generation (Revised 10 Jan.)

Started by jamespetts, January 09, 2009, 02:09:35 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

jamespetts

Attached is a patch to simulate the effect of competition from private cars on passenger traffic. It incorporates all of the features of my original passenger generation patch (discussed in this thread), and also includes Isidoro's overcrowding elimination patch, discussed here. Please refer to those threads for information on the effect of those features.

This patch adds the concept of car ownership, which is set in a privatecar.tab file (a sample copy, with information from UK government statistics between 1951 and 2006, and guessed figures for other years, is attached), the format of which is very similar to the speedbonus.tab file. At any given time, there is a percentage of people who own private cars (displayed in the city information window). For each passenger generated who has a private car, that passenger will (1) always go by car if there is no route to the destination by means of public (i.e., the player's) transport; or (2) sometimes go by car by preference in any case even if there is a route to the destination with public transport. Note that, even when passengers have alternative destinations (a feature of the original passenger generation patch, included here), if they own a private car, they will travel by car to their first preference destination in any event by car if they cannot go by public transport. Alternative destinations are therefore only effective for passengers who do not have private cars.

Each private car trip generated is logged statistically. The "City cars" graph now no longer keeps track of the number of graphical objects of city cars generated, but the number of passenger trips into, out of, and within that city made by private cars. Note that, because both incoming and outgoing trips are represented in each city, the number of car trips may well exceed the number of passengers generated in the city. The higher the number of private cars generated proportionate to the size of the city and the population density, the higher the congestion (the larger the size of the city, the lower the congestion; the higher the population density, the higher the congestion). There is a new graph in the city window representing congestion (I took the redundant electricity consumption graph and made it visible so as to avoid having to reversion the save game files). High congestion impacts on a city's growth. Congestion is measured in percentage terms, and, if congestion reaches 100% or more, a city will stop growing entirely, even if all the other conditions for growth are met.  However, balanced against that, trips by private car count towards growth in just the same way as passenger trips by public transport do (with the exception that incoming trips, but not outgoing trips, are measured for private cars), such that, when private car ownership is high, towns and cities will grow (as they would in real life) without any player intervention, albeit that growth will be slowed by congestion unless the player relieves it.

Whether passengers choose to use public transport or their own car when both are available is influenced by: (1) a base preference factor, settable in simuconf.tab (and high by default); (2) the average congestion of the origin and destination towns (or the congestion of the origin town if the trip is not to a different town); (3) the distance of the journey (passengers prefer public transport for very long distance journeys); (4) the number of hops required to reach the destination on public transport (the fewer, the better); and (5) the number of unhappy passengers at the origin station. This could in future be expanded to include: (1) the type of public transport (passengers preferring, in descending order, aircraft, maglev, monorail, train, boat, tram, narrowgauge and 'bus); (2) the quality of service metric for the line and/or vehicle in question (see discussion here for details of what is proposed in that regard); and (3) other factors yet to be considered (any thoughts would be welcome - especially if accompanied by an offer to code them!).

The generation of city car graphics is now handled a little differently. I have enabled the "city cars with destinations" code that was previously disabled. It does not, however, do exactly what it says, as there is no route finding mechanism built in. "City cars with origins" would be a more accurate description, since these city cars are generated near the place that the trips come from, but wander around aimlessly like all other city cars. I did try to build in a route finding mechanism for the city cars, but, unfortunately, was not able to succeed: the cars would become stuck after moving only a short distance, and would eternally try to find a route, eating up processor time, and making the game run very slowly. I have left in the code my attempts to make the cars find a route, but disabled it, so that anyone who wants to try to make it work can build on what I have done so far. I suspect, however, that having route finding for all cars generated might make the game much slower.

The number of city cars in circulation is now strictly monitored by means of a list of cars for each city, and, if the number exceeds the quota (now directly based on the number of recorded car trips in that city, to give an accurate graphical representation of car use), the cars that have been around for longest are removed. This prevents an endless build-up of cars clogging the roads and slowing the game whenever the rate of generation happens to exceed the rate of removal by the built-in timer.

This patch is intended to give a greater deal of challenge to players in the later part of the game, where revenues can be so high that money is not an issue. That, combined with the previous passenger generation patch that I have also incorporated, should enable there to be less of a challenge gap between the early game (which is made a little easier, if starting in an era with low private car ownership by alternative destinations and preference by passengers of local routes), and the late game (which is made harder with increasing use of private cars, Isidoro's crowding patch, and the lowering of the overall passenger level made possible without making the early game too hard by the alternative destinations and the increased preference for local transport). It also increases realism by simulating the reduction in passenger traffic coinciding with the steep increase of car ownership in the 1960s and 1970s - people might now have to close smaller passenger railway lines, as they become unprofitable with reducing passenger traffic, or at least, reduce the service (only to have to increase it later as growth gives rise to more congestion and greater demand for public transport...). An ideal accompaniment to this patch, which would enable there to be a similar effect for industry, would be the suggestion made in another thread somewhere by The Hood to have industries having retirement, as well as introduction dates, after which there would be an increasing chance that they would close. Industrial decline (or growth, or decline then renaissance) could thus be simulated by a combination of phased introduction and retirement dates.

As ever with these patches, there are a number of new options in simuconf.tab. In addition to the additional parts to simuconf.tab required for the passenger generation patch, the following settings are required for this patch (with documentation included):


# These ssettings relate to private car use. See /config/privatecar.tab for
# the configuration of private car ownership for different years.
#
# "Base car preference percent" is the chance, expressed in percentage, that, all
# other things being equal, a passenger with a private car will choose to use that
# car in preference to using public (i.e., the player's) transport. Higher values
# are more realistic; lower values make the game easier.
#
# "Always prefer car percent" is the percentage of drivers who prefer to use their
# car no matter how congested the roads. The remaining percentage of drivers are
# deterred from using their car to go to or from (or within) towns that have a
# high level of congestion. The default is 10.
#
# "Congestion density factor" is the factor by which the population density (in
# citizens per tile) is divided to get a factor multiplied by the number of cars
# per tile per month to get the congestion figure. In simple terms, the lower this
# number, the easier that it will be for cities to register as congested, and
# the more likely that it is that passengers will opt for public (i.e., the player's)
# transport instead.
#
# To revert to the original behaviour (with no competition from private cars at all),
# simply set "base_car_preference_percent" to 0. Passengers will then only choose
# private cars if no public transport is available.

base_car_preference_percent = 95
always_prefer_car_percent = 10
congestion_density_factor = 16


As this patch has the potential to make the game more difficult, the part that has the main effect on game play (passengers choosing to use private cars instead of the player's transport) can be turned off by setting "base_car_preference_percent" to 0. There will still be a "congestion" graph, the city car generation will still work as described above, and there will still be an indication of the percentage of car ownership in the city information box, but those are relatively cosmetic details that I do not imagine need to be turned off. Congestion will still affect city growth with "base_car_preference_percent" set to 0, but this can be eliminated by having a privatecar.tab file with "2050=0" in it, and nothing else.

I hope that people find this patch useful for stimulating more interest in the later part of the game. I should appreciate any feedback, either on the idea, or, better still, from having play-tested the game with the patch in place. I am particularly interested in opinions on where the congestion_density_factor should be set, as it was quite difficult getting the calibration of the congestion right: I suspect that it is presently calibrated a little too high (i.e., to record more congestion than it should). Any ideas of an alternative formula for calculating congestion would also be appreciated, since I suspect that mine might be a little too linear.

Edit: I found some bugs in the original version of the patch, which I have now withdrawn, and replaced with a revised version, now attached. The original version could have caused an access violation when deleting city cars with the remove tool, or in some other circumstances. That is now fixed. The revised version also contains a number of improvements. Firstly, the "traffic level" setting (which, incidentally, affects only the number of actual city car objects, not the number of private car trips logged in the city information window, nor the level of congestion) works better now (previously, the number of cars was too high even on low settings). Secondly, there is now a system for keeping track of the number of outstanding cars even when those cars cannot be assigned to a particular city, so that the total number of cars in circulation in the entire map is also carefully monitored and set not to exceed the number generated in the cities (as reduced in accordance with the traffic level setting: at no. 16, the actual number of cars will match the number of passenger trips generated, but it can get quite clogged up with cars with it set that high!). Again, this only affects the visual representation of the cars, not the simulation settings or graphs. Thirdly, I have tweaked the calibration of the congestion settings, which results in cities being less congested than they were before, to take account of the likely growth in cities over a long game. Finally, I have used the additional code that Prissi posted in relation to destination city cars in place of my original code in one place. Anyone who downloaded the original patch, I recommend downloading and applying the new patch. As ever, feedback is 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.

prissi

check out an older version. For instance revision 50 has working citycars with destinations.

YOu need to change to routines essentially:

void
stadtauto_t::betrete_feld()
{
#ifdef DESTINATION_CITYCARS
if(target!=koord::invalid  &&  abs_distance(pos_next.gib_2d(),target)<10) {
// delete it ...
time_to_life = 0;

fussgaenger_t *fg = new fussgaenger_t(welt, pos_next);
bool ok = welt->lookup(pos_next)->obj_add(fg) != 0;
for(int i=0; i<(fussgaenger_t::count & 3); i++) {
fg->sync_step(64*24);
}
welt->sync_add( fg );
}
#endif


and

bool
stadtauto_t::hop_check()
{
// V.Meyer: weg_position_t changed to grund_t::get_neighbour()
grund_t *from = welt->lookup(pos_next);
if(from==NULL) {
// nothing to go? => destroy ...
time_to_life = 0;
return false;
}

// find the allowed directions
const weg_t *weg = from->get_weg(road_wt);
if(weg==NULL) {
// nothing to go? => destroy ...
time_to_life = 0;
return false;
}

// traffic light phase check (since this is on next tile, it will always be neccessary!)
const ribi_t::ribi fahrtrichtung90 = ribi_typ(get_pos().get_2d(),pos_next.get_2d());

if(weg->has_sign()) {
const roadsign_t* rs = from->find<roadsign_t>();
const roadsign_besch_t* rs_besch = rs->get_besch();
if(rs_besch->is_traffic_light()  &&  (rs->get_dir()&fahrtrichtung90)==0) {
fahrtrichtung = fahrtrichtung90;
calc_bild();
// wait here
current_speed = 48;
weg_next = 0;
return false;
}
}

// next tile unknow => find next tile
if(pos_next_next==koord3d::invalid) {

// ok, nobody did delete the road in front of us
// so we can check for valid directions
ribi_t::ribi ribi = weg->get_ribi() & (~ribi_t::rueckwaerts(fahrtrichtung90));

// cul de sac: return
if(ribi==0) {
pos_next_next = get_pos();
return ist_weg_frei(from);
}

#ifdef DESTINATION_CITYCARS
static weighted_vector_tpl<grund_t *> liste(4);
liste.clear();
#endif
const uint8 offset = ribi_t::ist_einfach(ribi) ? 0 : simrand(4);
for(uint8 i = 0; i < 4; i++) {
const uint8 r = (i+offset)&3;
if(  (ribi&ribi_t::nsow[r])!=0  ) {
grund_t *to;
if(from->get_neighbour(to, road_wt, koord::nsow[r])) {
// check, if this is just a single tile deep after a crossing
weg_t *w=to->get_weg(road_wt);
if(ribi_t::ist_einfach(w->get_ribi())  &&  (w->get_ribi()&ribi_t::nsow[r])==0  &&  !ribi_t::ist_einfach(ribi)) {
ribi &= ~ribi_t::nsow[r];
continue;
}
// check, if roadsign forbid next step ...
if(w->has_sign()) {
const roadsign_besch_t* rs_besch = to->find<roadsign_t>()->get_besch();
if(rs_besch->get_min_speed()>besch->get_geschw()  ||  rs_besch->is_private_way()) {
// not allowed to go here
ribi &= ~ribi_t::nsow[r];
continue;
}
}
// ok, now check if we are allowed to go here (i.e. no cars blocking)
pos_next_next = to->get_pos();
if(ist_weg_frei(from)) {
// ok, this direction is fine!
ms_traffic_jam = 0;
if(current_speed<48) {
current_speed = 48;
}
#ifdef DESTINATION_CITYCARS
unsigned long dist=abs_distance( to->gib_pos().gib_2d(), target );
liste.push_back( to, dist*dist );
#else
return true;
#endif
}
else {
pos_next_next = koord3d::invalid;
}
}
else {
// not connected?!? => ribi likely wrong
ribi &= ~ribi_t::nsow[r];
}
}
}
#ifdef DESTINATION_CITYCARS
if(liste.get_count()>0) {
pos_next_next = pos_next = liste.at_weight(simrand(liste.get_sum_weight()))->gib_pos();
return true;
}
#endif


And citycar generate succeds only, if the road in question is empty.

jamespetts

Prissi,

thank you! I did not realise about the older versions. I shall have to look at that. Did that system work without consuming excessive CPU resources?

Edit: I have just looked at the code again. The first part seems only to destroy the cars if they get near their destinations (and generate some pedestrians nearby), and the second part is already in the code - there does not seem to be any code there for city cars actually attempting to go in the direction of their destinations, which is what I had originally attempted to do (using the same search route functions as for the player's road vehicles).
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

I have just posted a revised version of the patch, fixing a bug, and adding a few small new features. It is posted in the original post in place of the original version of the patch.
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.

prissi

In hop_check the citycars go onto the tile nearest to their destination with the highest probability.

jamespetts

Quote from: prissi on January 10, 2009, 09:07:53 PM
In hop_check the citycars go onto the tile nearest to their destination with the highest probability.

Interesting - but I am not sure where the code is to allow them to do that. Perhaps I missed it? Was it in the parts that you posted? If so, then that is very good, and a more CPU-friendly way than full routing in the same way as player vehicles...
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.

prissi

These wre the part I posted (albeit those are untested, just a quick adaption of the old code).

jamespetts

Prissi,

I have just realised that I have been rather silly - I did not notice that the hop check code box had a scroll bar! There was much more there than I realised. I thought that it was just the original code, but it is evidently much more. I will test it now. Thank you.

Edit: I have now tested it, but encountered a difficulty: the weighted vector class does not have a method called "push_back". It has an "append" method, but, when I used the code with that, the cars would not move, but freeze at a 45 degree angle.

Edit 2: The weighted vector's "append" method does indeed seem to be the equivalent of "push back", so I am afraid that the problem is not a simple naming error - the cars really do get stuck when they have to try to find their route. I am not immediately sure what the problem is, since I do not follow exactly how the code is supposed to work; but, in any event, it is non-functional, alas.
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.

VS

Quote from: jamespetts on January 10, 2009, 10:05:22 PM
the cars would not move, but freeze at a 45 degree angle.
For some reason, citycars can't drive through U - turns; is that it?

My projects... Tools for messing with Simutrans graphics. Graphic archive - templates and some other stuff for painters. Development logs for most recent information on what is going on. And of course pak128!

jamespetts

Quote from: VS on January 11, 2009, 11:30:00 AM
For some reason, citycars can't drive through U - turns; is that it?

No - all cars (or, after I made a small change to check for whether the target was valid before operating the routing code, all cars with destinations) would simply freeze after moving one or two tiles, and would often freeze at a 45 degree angle in the middle of a straight road, or in the middle of an intersection. No cars with destinations would move at all after a few tiles.
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

Aha - Prissi has fixed the city cars with destinations in the latest nightly! Thank you very much, Prissi. They do not get stuck any more, although it is a little hard to tell whether they really are heading for a destination. However, when I tried it, some towns certainly seemed a lot busier than others, so perhaps it does work. Very helpful - thank you.

Tell me - what was the reason that it was put behind conditional compilation again? Perhaps with this patch keeping track carefully of the total number of cars in the game, conditional compilation is no longer needed, and city cars with destinations can be kept as standard?
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.

prissi

You get flooded with citycars, no connection at all (bus stucked) even more city cars ... And it forces people to built roads, even though they want to connect by other means of transport. Not to mention that all city cars on a island are hopelessly stucked there.

jamespetts

Prissi,

ahh, very interesting - it's useful to know the history of these things! I am very much hoping that my new system for keeping track of the overall number of city cars generated (as well as the non-linear settings for the traffic level in the new map dialogue) should help to control the "flooded with cars" problem by making sure that there are no more cars with destination citycars enabled than without.

Cars getting stuck on islands is an interesting one - with the traffic level set high enough, I think, cars will get stuck in any isolated town without a road connexion in any event. But perhaps the original problem was the the city cars with destinations were not destroyed until they reached their destinations? This patch changes that, if that was ever so. I shall have to put up a new version with your amendments incorporated.

Incidentally, one thing that would be very good is a table somewhere of cities that have road connexions to other cities (i.e., each city having a table of the cities to which it has road connexions), which would help in citycar generation (no city cars with unreachable destinations), and would also make the competition with private cars part of things more interesting (and mean that players would still have to serve islands with a boat, for instance). How hard would it be to test a road connexion between city A and city B (perhaps checking whether A's town hall is connected to B's town hall by road), and where would be a good place in the code to start looking? If the check was made every month or so, and the table updated, the computational cost should be minimal.
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.

prissi

YOu can destroy them earlier, if you set their lifetime to one month or so. It was never released though.

Ah, and another point: I forces to transport passenger and mail, even though you may want to do a goods only game.

jamespetts

Quote from: prissi on January 12, 2009, 10:26:41 PM
YOu can destroy them earlier, if you set their lifetime to one month or so. It was never released though.

Ahh, that's interesting. In my patch, I use a system of keeping a check of the exact number of cars in the game world in addition to the existing timer system (which I have left untouched).

QuoteAh, and another point: I forces to transport passenger and mail, even though you may want to do a goods only game.

Hmm...  why would that be? Is that because the roads get clogged with cars unless one transports passengers, preventing one's trucks from reaching their destinations?
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.

Fabio


prissi

A car get generated each time a certain number of no route passengers are reached.

jamespetts

Quote from: prissi on January 13, 2009, 10:11:39 AM
A car get generated each time a certain number of no route passengers are reached.

Is that how it works by default? My patch makes it work differently, in that the city cars are generated when passengers actually take the car rather than use player transport, either because no player transport is available, or because they prefer to use their car in any event. Cars will only be generated in respect of passengers who have private cars (a weighted random chance for each set of passengers generated based on the current car ownership percentage), and the overall number of cars is precisely monitored to ensure that it does not exceed the total number of car journeys logged as being made in the current month, multiplied by the car generation factor (set by setting the "traffic level" - anything from 0.001 at level 1 to 1 at level 16). Any excess cars found at the beginning of each month are immediately removed from the game in order of the oldest (i.e., earliest generated) first.
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.