News:

SimuTranslator
Make Simutrans speak your language.

Factory upgrade

Started by Jim Knopf, January 06, 2011, 09:04:55 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Jim Knopf


The longer I play the experimental version the more pleasure affords it to me. Thanks for your great job James.   8)

Only one point frustrates me. It is the upgrading process of the factories. I quote your own words in the source code:
Quote// Check whether any upgrades are suitable.
// Currently, they must be of identical size and have
// identical outputs and inputs, as the upgrade mechanism
// is very simple. In future, it might be possible to write
// more sophisticated upgrading code to enable industries
// that are not identical in such a way to be upgraded.
// Thus, non-suitable upgrades are allowed to be specified
// in the .dat files for future compatibility.

The current implementation upgrades only the productivity of the factory. All other attributes (range, pax_level, ..) are ignored.
Is anything planned to improve the upgrading process?

Here is my proposal for a better upgrading process (in pseudo code):

for( i = 0,  upgrade_is_possible = 0;  i++;  i < cur_upgrades_count )
{
if not_exists_new_factory // the upgrade factory isn't defined
continue;
if new_intro_date > sysdate // the upgrade factory is too young
continue;
if new_retire_date < sysdate // the upgrade factory is too old
continue;
if new_location[i] != cur_location // the upgrade factory has wrong location
continue;
if new_climates[i] != cur_climates // the upgrade factory has wrong climates
continue;
if new_dims[i] != cur_dims // the upgrade factory picture has wrong dimensions
continue;
if new_mapcolor[i] != cur_mapcolor // the upgrade factory has wrong mapcolor (important?)
continue;

upgrade_is_possible = 1
break;
}



if upgrade_is_possible
{
cur_name = new_name // header parameters
cur_productivity = new_producivity
cur_range = new_range
cur_pax_level = new_pax_level
cur_electricity_proportion = new_electricity_proportion
(...)

if not exists new_smoke // smoke
delete_smoke
else
cur_smoke = new_smoke

cur_copyright = new_copyright // picture
cur_needs_ground = new_needs_ground
cur_backimage[...] = new_backimage[...]

cur_intro_date = new_intro_date // timeline
cur_retire_date = new_retire_date

if not exists new_fields // fields
delete fields
else
{ if cur_number_of_fields > new_max_fields
delete_the_surplus_fields
if cur_number_of_fields < new_min_fields
create_the_missing_fields
cur_fields = new_fields
cur_max_fields = new_max_fields
cur_min_fields = new_min_fields
(..)
}

if cur_lieferanten > new_lieferanten // suppliers
delete_the_surplus_lieferanten
if cur_lieferanten < new_lieferanten
create_the_missing_lieferanten
for( j = 0;  j++;  j < cur_lieferanten )
{
cur_inputgood = new_inputgood
cur_inputcapacity = new_inputcapacity
cur_inputsupplier = new_inputsupplier
cur_inputfactor = new_inputfactor
}

if cur_produkte > new_produkte // customers
delete_the_surplus_produkte
if cur_produkte < new_produkte
create_the_missing_produkte
for( j = 0;  j++;  j < cur_produkte )
{
cur_outputgood = new_outputgood
cur_outputcapacity = new_outputcapacity
cur_outputfactor = new_outputfactor
}

delete_surplus_contracts // delete contracts which doesn't fit anymore (invalid goods)

paint_picture // paint new picture

show_upgrade_message // show upgrade message
}



jamespetts

Jim,

welcome to the forum! I'm glad that you like Experimental. Passenger level and range are not ignored in factory upgrades (range in any event being relevant only to the range of different levels of productivity); they don't have to have the same number of fields, either. The difficult part is if the factories are of different sizes or have different input and output goods. If they were of a different size, they would not fit into the existing space (potentially) and would have to be relocated; but one can hardly call a factory upgrade an "upgrade" if the old one disappears and a new one appears on the other side of the map: the idea of upgrades is so that the factories can modernise without necessarily disrupting the player's transport.

As to connexions with other industries, there can potentially be quite a complicated web of connexions, and it would not be trivial matter to change the existing connexion patterning with the factory still in place; what if there aren't enough input suppliers for the new factory that aren't already committed to somewhere else such that if they were required for this factory, their production not being enough to serve all the factories to which they are now connected, and so on? In any event, if different inputs and outputs were needed, the player would have to change the transport routes to that factory in any event, which would be little better than the factory closing down and a new one opening somewhere else later (which is the alternative to upgrading).

One possibility is that the system could allow smaller factories to be built on the site of larger ones where the upgrades are smaller than their predecessors (as they would then fit in the land space), but I don't think that any pakset currently has any upgraded industries that are smaller than their predecessors.

Jim Knopf

In my opinion you think a bit too complicate (sorry)

it is logical for me that the building can not change his dimensions by upgrading. Otherwise, it will be far too complicated. The other point is the upgrade process, which is IMO much "easy" to implement.

We need the upgrading process to represent the technological progress. The population is growing. The Consumption is growing up in the same way. In addition, people require new products, old products are no longer required. Freight transportation was from the beginning in the 19th century the basis of all or the most transport companies. This currently is not represented at all in simutrans. Currently, only the passenger transportation is sufficient profitable and predictable


The worst possible solution for upgrading is to close a factory and open instead a new factory at another location. This is for me unacceptable. In this case it makes nearly no sense to connect a factory with his suppliers and customers. Very likely these connection are redundant in e.g. 20 years.


Subsequent I want to regard the upgrading process in more detail on the basis of three cases.

1 - A quarry can after the invention of dynamite deliver stones four times as much as before. This is in the language of simutrans possible with changing the productivity value.

2 - A pub sells more beer. Also this can be done by increasing the productivity value. But now the pub needs more suppliers (see below). Or in the meantime the current supplier provides also more (see first case).


3 - A Factory supplies other goods. A brewery produced 1850 beer in barrels. Therefor the brewery needs grain. From 1890 it is possible to fill beer in bottles. For that the brewery needs grain and glass (or bottles). Beer bottles are now produced additional to beer barrels. Currently this is not possible in Sumatrans. I see two different solutions for that:

Solution A (the better way): It is allowed that the upgraded factory has more/less supplied/sold goods than the old factory. The outcome of this is that these dat entries are working as intended:
name=brewery1850
retire_year=1890
inputgood[0]=grain
outputgood[0]=beer_barrels
upgrade[0]=brewery1890
---
name=brewery1890
intro_year=1890
inputgood[0]=grain
inputfactor[0]=100
inputgood[1]=glass
inputfactor[1]=10
outputgood[0]=beer_barrels
outputfactor[0]=20
outputgood[1]=beer_bottles
outputfactor[1]=80


Solution B (the simple way): all theoretically possible inputs and outputs must be equal for every upgrade step. Only the values for factor and capacity can vary:
name=brewery1850
retire_year=1890
inputgood[0]=grain
inputfactor[0]=100
inputgood[1]=glass
inputfactor[1]=0
outputgood[0]=beer_barrels
outputfactor[0]=100
outputgood[1]=beer_bottles
outputfactor[1]=0
upgrade[0]=brewery1890
---
name=brewery1890
intro_year=1890
inputgood[0]=grain
inputfactor[0]=100
inputgood[1]=glass
inputfactor[1]=10
outputgood[0]=beer_barrels
outputfactor[0]=20
outputgood[1]=beer_bottles
outputfactor[1]=80


In my opinion it is simple to realize the second solution. A is the better solution but it is of cause more complex.


Apart from the first example the program has periodically to check the connexions for all industries. Are there enough are they all right? This is not dependent of wether you improve the upgrading process or not. With the current implementation it is possible that an industry has invalid connections cause one supplier close down months ago. In my current game a steelworks had coal and iron mines as suppliers. After a few years the coal mine shut down. No new coal connection was build up since now although there exist more coal mines.


BTW: why did you removed all values for input[].supplier??


PS: puhh, it is very hard for me to discuss this stuff in English. I hope you understand right what I want to say :)

jamespetts

Jim,

apologies for having taken a long time to respond to this. Your suggestions are sensible ones: I am planning to address these issues in the next major release of Simutrans-Experimental by enhancing the way in which industry chains expand to check whether there are any unlinked industries and re-link them. This would then allow a relaxation of the upgrading rules such that industries with different inputs/outputs could be specified as upgrades (although the size and shape of the factory would have to remain constant).

Jim Knopf

Hi James, sorry for the long delay. In summer and spring I have no time to play simutrans. So I was absent for a long time.

On topic: did you made some changes to the upgrade process in the current version? In my first game with 10.1 I've got the effext that an out dated factory instead of upgrading. Is this intended? Next weekend I will start a new with 10.2.


jamespetts

Jim,

yes, indeed: the latest version of Simutrans-Experimental has the features that I described in my post above.

Jim Knopf

From my point of view the upgrading process of the factories doesn't work properly. In my current game (Exp 10.2 with pak-britain 0.8.2) four factories were closed instead of upgrading - see the attached screenie. Same happened in my last three games (10.2 and 10.1).

Attached is the dat file of factory "Steinbruch1700" (quarry). You see that there exist a better quarry to which the old one could be upgraded. But no upgrade happens, the factories were closed down.

Perhaps I doesn't understand right the mechanism as it is implemented. So I will describe how upgrades should imho work. When a factory has to close down then the program checks first(!) whether an upgrade is possible. If so then the old factory should be exchanged with the new one by retaining all the customer and supplier links which aren't obsolete now. Only if there is no possibility of upgrading then the factory has to close down.

Or did I made some errors in the dat?

PS: btw, many thanks to your good job here, James. I love the exp-version, mainly the monster trains with 50 wagons and more. :-)

jamespetts

Glad that you like Experimental! The way in which upgrading works is not quite as you suggest: instead, whether a factory upgrades or closes is based on a weighted random factor, which is weighted according to the ratio of the current actual industry density as against the target industry density. The code is as follows:


if(closedown)
{
grund_t *gr = 0;
gr = welt->lookup(pos);
gebaeude_t* gb = gr->find<gebaeude_t>();
char buf[192];

const int upgrades_count = besch->get_upgrades_count();
if(upgrades_count > 0)
{
// This factory has some upgrades: consider upgrading.
minivec_tpl<const fabrik_besch_t*> upgrade_list(upgrades_count);
const uint32 max_density = (welt->get_target_industry_density() * 150) / 100;
const uint32 adjusted_density = welt->get_actual_industry_density() - (100 / besch->get_gewichtung());
for(uint16 i = 0; i < upgrades_count; i ++)
{
// Check whether any upgrades are suitable.
// Currently, they must be of identical size, as the
// upgrade mechanism is quite simple. In future, it might
// be possible to write more sophisticated upgrading code
// to enable industries that are not identical in such a
// way to be upgraded. (Previously, the industry also
// had to have the same number of suppliers and consumers,
// but this is no longer necessary given the industry re-linker).

// Thus, non-suitable upgrades are allowed to be specified
// in the .dat files for future compatibility.

const fabrik_besch_t* fab = besch->get_upgrades(i);
if( fab != NULL && fab->is_electricity_producer() == besch->is_electricity_producer() &&
fab->get_haus()->get_b() == besch->get_haus()->get_b() &&
fab->get_haus()->get_h() == besch->get_haus()->get_h() &&
fab->get_haus()->get_groesse() == besch->get_haus()->get_groesse() &&
fab->get_haus()->get_intro_year_month() <= welt->get_timeline_year_month() &&
fab->get_haus()->get_retire_year_month() >= welt->get_timeline_year_month() &&
adjusted_density < (max_density + (100 / fab->get_gewichtung())))
{
upgrade_list.append_unique(fab);
}
}

const uint8 list_count = upgrade_list.get_count();
if(list_count > 0)
{
uint32 total_density = 0;
ITERATE(upgrade_list, j)
{
total_density += (100 / upgrade_list[j]->get_gewichtung());
}
const uint32 average_density = total_density / list_count;
const uint32 probability = 1 / ((100 - ((adjusted_density + average_density) / max_density)) * upgrade_list.get_count()) / 100;
const uint32 chance = simrand(probability, "void fabrik_t::neuer_monat()");
if(chance < list_count)
{
// All the conditions are met: upgrade.
const fabrik_besch_t* new_type = upgrade_list[chance];
uint32 percentage = new_type->get_field_group() ? (new_type->get_field_group()->get_max_fields() * 100) / besch->get_field_group()->get_max_fields() : 0;
const uint16 adjusted_number_of_fields = percentage ? (fields.get_count() * percentage) / 100 : 0;
delete_all_fields();
const char* old_name = get_name();
besch = new_type;
const char* new_name = get_name();
gb->calc_bild();
// Base production is randomised, so is an instance value. Must re-set from the type.
prodbase = besch->get_produktivitaet() + simrand(besch->get_bereich(), "void fabrik_t::neuer_monat()");
// Re-add the fields
for(uint16 i = 0; i < adjusted_number_of_fields; i ++)
{
add_random_field(0);
}
// Re-set the expansion counter: an upgraded factory may expand further.
times_expanded = 0;
// Re-calculate electricity conspumption, mail and passenger demand, etc.
recalc_storage_capacities();
update_scaled_electric_amount();
update_scaled_pax_demand();
update_scaled_mail_demand();
update_prodfactor_pax();
update_prodfactor_mail();
recalc_demands_at_target_cities();
sprintf(buf, translator::translate("Industry:\n%s\nhas been upgraded\nto industry:\n%s."), translator::translate(old_name), translator::translate(new_name));
welt->get_message()->add_message(buf, pos.get_2d(), message_t::industry, CITY_KI, skinverwaltung_t::neujahrsymbol->get_bild_nr(0));
return;
}
}
}

hausbauer_t::remove(welt, welt->get_spieler(1), gb);
}

Jim Knopf

Okay, but where can I define the target industry density? Is it in one of the tab files? In all my last games all factories were by and by closed down and no new factory was ever builded. Maybe that this parameter is set to a nonsense value in my configuration.

jamespetts

The target industry density is calculated when the game is first generated. It is calculated by adding 1 divided by the distributionweight of all the factories on the map when it is first generated, and then dividing that number by the population. So, as the population increases, the average distributionweight of factories on the map at any given time, or the number of factories decrease, the actual industry density decreases, and more factories need to be built to match the actual industry density to the target industry density.

Jim Knopf

This sounds convincing and logical. But in my last games it doesn't work. I will check my dat files and your code. Perhaps I see where the reason is for that.

greenling

Excuse Me!
Why make the Factory upgrade not so that in the game give a consumption of resource thats´s with the time Grow!

jamespetts

Jim - if you think that you've found a bug, I should be interested in your findings in this respect. So far, the information that you have given (that four factories have closed down when upgrades have been available) is not conclusive, since that is reasonably likely to happen in any event if the code is working correctly. However, if you find anything that points more strongly to there being a bug, please let me know.

Greenling - I don't understand, I'm afraid. What exactly do you mean?