The International Simutrans Forum

Development => Extension Requests => Topic started by: diesseits on May 28, 2010, 11:04:44 PM

Title: Late starting games with historical buildings
Post by: diesseits on May 28, 2010, 11:04:44 PM
Is there any way to get new cities generated 'late' (for a map starting say 1950) to use a mixture of current and historical buildings? I'm not so interested in playing steam-era games, but I don't like the look of cities that appear to have just sprung up with only a handful of building types, especially in pak128.britain where the older buildings are important for the overall look and feel of the game.

Alternately, is there a way to use the timeline for vehicles but nothing else?
Title: Re: Late starting games with historical buildings
Post by: mobo on May 29, 2010, 12:15:13 PM
Well, if those old buildings are still being built in 1950, You could delete the more modern buildings from the pak folder before map creation. When you got xour map you can save it and add the files again. Not a very elegant way, but should work. If you want to do this more often you can have some prepared pakbritain folder for map creation in a different folder, then you only have to exchange the folders.

Title: Re: Late starting games with historical buildings
Post by: wlindley on June 04, 2010, 02:36:45 PM
Perhaps the city generation could be modified to include old buildings along with current ones; there would be some modification required to the chance calculation.
Title: Re: Late starting games with historical buildings
Post by: diesseits on June 05, 2010, 05:20:18 AM
@wlindley I think that would be good. I don't see any rationale for cities to be built with only current buildings in any pak. At the moment the only maps that look good are those created in the 18th century and those created without the 'use timeline' checkbox on, but I want to use the timeline for vehicles and infrastructure. City creation should obey the introduction date but not the retirement date of buildings to get a good mix.

I could probably fix it myself, except that the code seems to be in German so I'm a bit lost.
Title: Re: Late starting games with historical buildings
Post by: sdog on June 05, 2010, 05:34:36 AM
Quote
Well, if those old buildings are still being built in 1950, You could delete the more modern buildings from the pak folder before map creation.
this doesn't work for pak128.britain, since all buildings are in one pak. He'd need to generate that pak from the source.

Quote
City creation should obey the introduction date but not the retirement date of buildings to get a good mix.
that would be quite worth a try.


you could start looking for it in  simcity.cc  comments are mostly translated to english already in this file.

this routine replaces buildings with higher level buildings:
Code: [Select]
void stadt_t::renoviere_gebaeude(gebaeude_t* gb)
{
        const gebaeude_t::typ alt_typ = gb->get_haustyp();
        if (alt_typ == gebaeude_t::unbekannt) {
                return; // only renovate res, com, ind
        }

        if (gb->get_tile()->get_besch()->get_b()*gb->get_tile()->get_besch()->get_h()!=1) {
                return; // too big ...
        }

        // hier sind wir sicher dass es ein Gebaeude ist
        const int level = gb->get_tile()->get_besch()->get_level();

        // bisher gibt es 2 Sorten Haeuser
        // arbeit-spendende und wohnung-spendende
        const int will_arbeit  = (bev - arb) / 4;  // Nur ein viertel arbeitet
        const int will_wohnung = (bev - won);

        // does the timeline allow this buildings?
        const uint16 current_month = welt->get_timeline_year_month();
        const climate cl = welt->get_climate(gb->get_pos().z);
[\code]
[code]
// check for residence
        // (sum_wohnung>sum_industrie  &&  sum_wohnung>sum_gewerbe
        if (will_haben == gebaeude_t::unbekannt) {
                // we must check, if we can really update to higher level ...
                const int try_level = (alt_typ == gebaeude_t::wohnung ? level + 1 : level);
                h = hausbauer_t::get_wohnhaus(try_level, current_month, cl);
                if (h != NULL && h->get_level() >= try_level) {
                        will_haben = gebaeude_t::wohnung;
                        sum = sum_wohnung;
                } else {
                        h = NULL;
                }
        }
btw (my graps of the code is rather lacklustre, so pls don't get offended if i'm totally wrong):
hausbauer_t::get_wohnhaus(try_level, current_month, cl); gets a random house from a list, i think?
here it is checked if it is suitable. is it getting less effective if the timeline is very long and only a few houses are available at any given point in time? for a list with many suitable entries it should be much better than first selecting the list, then randomizing.[/code]
Title: Re: Late starting games with historical buildings
Post by: diesseits on June 05, 2010, 06:38:29 AM
sdog: thanks.

With the aid of google translate, I think I've tracked it down to this code.

In experimental:

L:3593

                if (h == NULL  &&  sum_wohnung > sum_industrie  &&  sum_wohnung > sum_gewerbe) {                                                                                                          
                        h = hausbauer_t::get_wohnhaus(0, current_month, cl, new_town);                                                                                                                    
                        if (h != NULL) {                                                                                                                                                                  
                                // will be aligned next to a street                                                                                                                                        
                                won += h->get_level() * 10;                                                                                                                                                
                        }                                                                                                                                                                                  
                }                                                                                                                                                                                          


... which appears to call " 'housebuilder_t': get a family house, passing (0, the current month, the climate, and whether it's a new town) as arguments]. All of which is great but I can't see where the hausbauer_t comes from, grepping though the files doesn't turn anything up, it's called a lot but where does it come from?

EDIT: oh, it was in a subdirectory.
Title: Re: Late starting games with historical buildings
Post by: sdog on June 05, 2010, 06:56:42 AM
it's in bauer/hausbauer.cc

it just calls  get_aus_liste  (trans: get_from_list), which does the actual work (line 696 in std)*
i think it randomly selects a house fitting to the conditions.

*if i knew you're looking to experimental too, i wouldn't have needed to look into standard, i know even less.

ps.: just post any comments you don't understand, i (or others) will try  to translate them for you.
Title: Re: Late starting games with historical buildings
Post by: diesseits on June 05, 2010, 07:17:33 AM
Yes, I'm looking at that now, but I'm confused because it already seems to be written as if it should behave as I've described, with the "allow_earlier" being set, in this instance, from "new_town" being passed to it. Then it appears to give a 35% chance of an old building being allowed to be selected from the list. So maybe it's a bug that prevents old buildings being used?

Code: [Select]

static const haus_besch_t* get_aus_liste(const vector_tpl<const haus_besch_t*>& liste, int level, uint16 time, climate cl, bool allow_earlier)                                                             
{                                                                                                                                                                                                         
        weighted_vector_tpl<const haus_besch_t *> auswahl(16);                                                                                                                                             
                                                                                                                                                                                                           
//      DBG_MESSAGE("hausbauer_t::get_aus_liste()","target level %i", level );                                                                                                                             
        const haus_besch_t *besch_at_least=NULL;                                                                                                                                                           
        for (vector_tpl<const haus_besch_t*>::const_iterator i = liste.begin(), end = liste.end(); i != end; ++i) {                                                                                       
                const haus_besch_t* besch = *i;                                                                                                                                                           
                const uint16 random = simrand(100);                                                                                                                                                       
                if(     besch->is_allowed_climate(cl)  &&                                                                                                                                                 
                        besch->get_chance()>0  &&                                                                                                                                                         
                        (time==0  ||  (besch->get_intro_year_month()<=time  &&  ((allow_earlier && random > 65) || besch->get_retire_year_month()>time)))) {                                               
                        besch_at_least = besch;                                                                                                                                                           
                }                                                                                                                                                                                         
                                                                                                                                                                                                           
                const int thislevel = besch->get_level();                                                                                                                                                 
                if(thislevel>level) {n                                                                                                                                                                     
                        if (auswahl.empty()) {                                                                                                                                                             
                                // continue with search ...                                                                                                                                               
                                level = thislevel;                                                                                                                                                         
                        }                                                                                                                                                                                 
                        else {                                                                                                                                                                             
                                // ok, we found something                                                                                                                                                 
                                break;                                                                                                                                                                     
                        }                                                     
                }

                if(thislevel==level  &&  besch->get_chance()>0) {
                        if(cl==MAX_CLIMATES  ||  besch->is_allowed_climate(cl)) {
                                if(time==0  ||  (besch->get_intro_year_month()<=time  &&  ((allow_earlier && random > 65) || besch->get_retire_year_month()>time))) {
//                              DBG_MESSAGE("hausbauer_t::get_aus_liste()","appended %s at %i", besch->get_name(), thislevel );                                                                           
                                        auswahl.append(besch,besch->get_chance(),4);
                                }
                        }
                }
        }

        if(auswahl.get_sum_weight()==0) {
                // this is some level below, but at least it is something                                                                                                                                 
                return besch_at_least;
        }
        if(auswahl.get_count()==1) {
                return auswahl.front();
        }
        // now there is something to choose                                                                                                                                                               
        return auswahl.at_weight( simrand(auswahl.get_sum_weight()) );
}

Title: Re: Late starting games with historical buildings
Post by: sdog on June 05, 2010, 07:25:25 AM
Code: [Select]
  if(     besch->is_allowed_climate(cl)  &&
                        besch->get_chance()>0  &&
                        (time==0  ||  (besch->get_intro_year_month()<=time  &&  besch->get_retire_year_month()>time))) {
                        besch_at_least = besch;
                }
it's different in standard, so james should likely know more about it.
Title: Re: Late starting games with historical buildings
Post by: diesseits on June 05, 2010, 07:47:24 AM
Well removing "&&  ((allow_earlier && random > 65) || besch->get_retire_year_month()>time)" gets the behaviour I want, which is fine, but I don't think that would do for a patch to simutrans. For one thing, that would mean new cities founded during the game would get all types of building, which is not necessarily what you want. An extra argument ... 'map_creation' is probably needed to go through to the building selection algorithm. Secondly, I'm nonplussed as to why the current code isn't allowing at least some old buildings through.

For really good looking maps, 'regions' of (large) towns built largely in one period's style (and small towns being built to a particular style) or another would be great, but that's a whole other level of complexity.
Title: Re: Late starting games with historical buildings
Post by: sdog on June 05, 2010, 07:54:03 AM
you could read the probability (now 1-65) from citirules.tab

i expect allow_earlier should be set to 1 only when welt is created. perhaps it is set already, or not. Have  you tried what happes if you get rid of  "&& random > 65" ?
Title: Re: Late starting games with historical buildings
Post by: jamespetts on June 05, 2010, 01:10:12 PM
The code in Experimental that you've found is code that was intended to acheive this result, but, for reasons that I have not been able to ascertain so far, oddly, it does not have that effect.