News:

Simutrans Wiki Manual
The official on-line manual for Simutrans. Read and contribute.

'Cities ignore height' option

Started by inkelyad, June 12, 2010, 07:41:07 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

inkelyad

How 'Cities ignore height' option works?
The only relevant place I can find is (simcity.cc)

const sint32 multiplied_number = umgebung_t::cities_ignore_height || welt == NULL ? anzahl : anzahl * 4;
<SKIP>
if(welt != NULL && !umgebung_t::cities_ignore_height)
    {
        pre_result = new weighted_vector_tpl<koord>(multiplied_number);
    }

and pre_result is not used anywhere..

jamespetts

Inkelyad,

thank you for spotting that. This was originally (and should still be) part of a system for distributing towns based on the height: the higher the tile, the less likely that it was that a town would be generated there. The "cities_ignore_height" option was a way of disabling that. It seems that, since then, the code in Standard has changed, and, when that change was merged, it obliterated the feature in Experimental. The original code looked like this:


vector_tpl<koord>* stadt_t::random_place(const karte_t* wl, const sint32 anzahl, sint16 old_x, sint16 old_y)
{
int cl = 0;
for (int i = 0; i < MAX_CLIMATES; i++)
{
if (hausbauer_t::get_special(0, haus_besch_t::rathaus, wl->get_timeline_year_month(), false, (climate)i))
{
cl |= (1 << i);
}
}

// For clustering cities by climate type, we need a list of at least 4x the number of sites actually needed
// for towns so that, from that expanded list, the final locations can be chosen.
const sint32 multiplied_number = umgebung_t::cities_ignore_height || welt == NULL ? anzahl : anzahl * 4;

DBG_DEBUG("karte_t::init()", "get random places in climates %x", cl);
slist_tpl<koord>* list = wl->finde_plaetze(2, 3, (climate_bits)cl, old_x, old_y);
DBG_DEBUG("karte_t::init()", "found %i places", list->get_count());
vector_tpl<koord>* result = new vector_tpl<koord>(anzahl);
weighted_vector_tpl<koord>* pre_result;
if(welt != NULL && !umgebung_t::cities_ignore_height)
{
pre_result = new weighted_vector_tpl<koord>(multiplied_number);
}

for (int i = 0; i < multiplied_number; i++)
{
int len = list->get_count();
// check distances of all cities to their respective neightbours
while (len > 0)
{
int minimum_dist = 0x7FFFFFFF;  // init with maximum
koord k;
const int index = simrand(len);
k = list->at(index);
list->remove(k);
len--;

// check minimum distance
for (int j = 0; (j < i) && minimum_dist > minimum_city_distance; j++)
{
int dist = koord_distance( k, (*pre_result)[j] );
if (minimum_dist > dist)
{
minimum_dist = dist;
}
}
if (minimum_dist > minimum_city_distance)
{
// all cities are far enough => ok, find next place

if(welt != NULL && !umgebung_t::cities_ignore_height)
{
const sint16 height_above_water = welt->lookup_hgt(k) - welt->get_grundwasser();
uint32 weight;
switch(height_above_water)
{
case 1:
weight = 24;
break;
case 2:
weight = 22;
break;
case 3:
weight = 16;
break;
case 4:
weight = 12;
break;
case 5:
weight = 10;
break;
case 6:
weight = 9;
break;
case 7:
weight = 8;
break;
case 8:
weight = 7;
break;
case 9:
weight = 6;
break;
case 10:
weight = 5;
break;
case 11:
weight = 4;
break;
case 12:
case 13:
weight = 3;
break;
case 14:
case 15:
weight = 2;
break;
default:
weight = 1;
};
pre_result->append(k, weight);
break;
}
else
{
result->append(k);
break;
}
}
// if we reached here, the city was not far enough => try again
}

if (len <= 0 && i < anzahl - 1)
{
dbg->warning("stadt_t::random_place()", "Not enough places found!");
break;
}
}
list->clear();
delete list;

if(welt != NULL && !umgebung_t::cities_ignore_height)
{
uint16 weight = 0;
const uint16 total_weight = pre_result->get_sum_weight();
for (int i = 0; i < anzahl; i++)
{
// Now produce the real results from the pre-list.
weight = simrand(total_weight);
if(!result->append_unique(pre_result->at_weight(weight)))
{
i--;
}
}

pre_result->clear();
delete pre_result;
}

return result;


When I get a chance, I shall have to look to see how I can acheive that result using the new code (which I understand is much faster than the old code). If you have any suggestions as to how to implement this with the new system, they'd be very gratefully received!
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.

inkelyad

Quote from: jamespetts on June 13, 2010, 11:02:30 PM
When I get a chance, I shall have to look to see how I can acheive that result using the new code (which I understand is much faster than the old code).
What reasoning was behind this option? Can I replace it? Right now I have planned somenting along 'rivers (even mountain ones)/sea attracts cities'

jamespetts

Quote from: inkelyad on June 14, 2010, 06:02:05 PM
What reasoning was behind this option? Can I replace it? Right now I have planned somenting along 'rivers (even mountain ones)/sea attracts cities'

I like your idea for water attracting cities - that would be a substantial enhancement to the game! The reason for my system was that towns are more often built on lowlands than highlands, although they are sometimes built on highlands: the idea was to weight the probability of building cities according to the height of the terrain. This would have the effect that there would be some areas with a large number of towns clustered together and some areas that are quite sparsely populated with towns. This is desirable in itself, not only because it is realistic, but because it provides interesting challenges of balancing, in the areas with many towns clustered together, a dense urban/suburban network, with the very different challenges of connecting remoter towns, or connecting distant pairs of large urban areas with little in between (and potentially over difficult terrain).
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 now put this feature back in a way that works with the new code in the 8.x branch. Inkelyad - I am still very interested in your ideas as to how to make cities more likely to be built near water - do let me know how you get on with that!
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.

inkelyad

I am a slow programmer. Furthermore  multiple weight maps interfere with each other. I still can't choose 'correct' formula.

jamespetts

Inkelyad,

the multiple weightings issue is actually the easiest to solve: the hard bit is actually working out which sites are near rivers and the sea, especially as, if I recall correctly, rivers are built after cities in map generation. The simple solution to weighting is to start with a neutral base weight of, say, 100, and to add and subtract (or multiply and divide) for each factor: near small river, add 20, near large river: add 50, on low ground, add 100, on top of mountain, subtract 90 - and so forth.
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.

inkelyad

Quote from: jamespetts on June 28, 2010, 07:58:55 PM
the hard bit is actually working out which sites are near rivers and the sea, especially as, if I recall correctly, rivers are built after cities in map generation.
No, rivers are built first.
Quote from: jamespetts on June 28, 2010, 07:58:55 PM
The simple solution to weighting is to start with a neutral base weight of, say, 100, and to add and subtract (or multiply and divide) for each factor: near small river, add 20, near large river: add 50, on low ground, add 100, on top of mountain, subtract 90 - and so forth.
Yes, it realy works almost like this. But it is hard to find coefficients. As it is river map and height map give me very similar effects.
Combine city distance/size + terrain height + water distance into something non-confusing is hard.

jamespetts

Well, I shall be interested in any progress!
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.

inkelyad

Teaser time. And I need english editor help. How should I actually name parameters in GUI? I beleve names of variables in code are confusing too.

patch against current 'devel' branch. No GUI yet. Just play with 'water_charge', 'one_population_charge', 'clustering' at the begining of  stadt_t::random_place_complex.

inkelyad

water atracts cities.

inkelyad

Cities avoid each other.

inkelyad

Clustering

jamespetts

I am very impressed! Is patched against Experimental or 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.

Isaac Eiland-Hall

That's freakin' sweet. Something I hope comes to Standard (as with many Experimental features, but this one stands out for me personally hehehe)

inkelyad

Quote from: jamespetts on June 30, 2010, 10:41:31 PM
Is patched against Experimental or Standard?
I use github Experimental 'devel' as a base. Don't know how it will work with Standard.