Index: bauer/fabrikbauer.cc =================================================================== --- bauer/fabrikbauer.cc (revision 9169) +++ bauer/fabrikbauer.cc (working copy) @@ -154,7 +154,7 @@ return false; } // check for trees unless the map was generated without trees - if( site==factory_desc_t::forest && !welt->get_settings().get_no_trees() && condmet < mincond ) { + if( site==factory_desc_t::forest && welt->get_settings().get_tree()>0 && condmet < mincond ) { for(uint8 i=0; i< gr->get_top(); i++) { if (gr->obj_bei(i)->get_typ() == obj_t::baum) { condmet++; Index: dataobj/settings.cc =================================================================== --- dataobj/settings.cc (revision 9169) +++ dataobj/settings.cc (working copy) @@ -62,6 +62,7 @@ // default climate zones set_default_climates( ); + climate_generator = 0; // 0 = height based, 1 = temperature/rainfall groundwater = -2; winter_snowline = 7; // not mediterranean @@ -84,9 +85,9 @@ max_no_of_trees_on_square = 3; // Number of trees on square 2 - minimal usable, 3 good, 5 very nice looking tree_climates = 0; // bit set, if this climate is to be covered with trees entirely no_tree_climates = 0; // bit set, if this climate is to be void of random trees - no_trees = false; // if set, no trees at all, may be useful for low end engines + tree = 1; // 0=no trees may be useful for low end engines, 1=random, 2=rainfall - lake = true; // if set lakes will be added to map + lake = 8; // lakes will be generated below this height above groundwater // some settings more allow_player_change = true; @@ -744,7 +745,14 @@ file->rdwr_byte( max_no_of_trees_on_square ); file->rdwr_short( tree_climates ); file->rdwr_short( no_tree_climates ); - file->rdwr_bool( no_trees ); + /*if( file->is_version_atleast(INSERT LAKE_HEIGHT_VERSION) ) { + file->rdwr_byte(tree); + } + else */ { + bool no_trees = (tree==0); + file->rdwr_bool( no_trees ); + tree = no_trees ? 0 : 1; + } file->rdwr_long( minimum_city_distance ); file->rdwr_long( industry_increase ); } @@ -829,9 +837,18 @@ else if( file->is_loading() ) { default_ai_construction_speed = env_t::default_ai_construction_speed; } + /*if( file->is_version_atleast(INSERT LAKE_HEIGHT_VERSION) ) { + file->rdwr_byte(lake); + } + else */ if( file->is_version_atleast(120, 2) ) { + bool this_lake = lake > 0; + file->rdwr_bool(this_lake); + lake = this_lake ? 8 : 0; + bool no_trees = (tree==0); + file->rdwr_bool( no_trees ); + tree = no_trees ? 0 : 1; + } if( file->is_version_atleast(120, 2) ) { - file->rdwr_bool(lake); - file->rdwr_bool(no_trees); file->rdwr_long( max_choose_route_steps ); } if( file->is_version_atleast(120, 4) ) { @@ -1332,8 +1349,8 @@ max_no_of_trees_on_square = contents.get_int("max_no_of_trees_on_square", max_no_of_trees_on_square ); tree_climates = contents.get_int("tree_climates", tree_climates ); no_tree_climates = contents.get_int("no_tree_climates", no_tree_climates ); - no_trees = contents.get_int("no_trees", no_trees ); - lake = !contents.get_int("no_lakes", !lake ); + tree = contents.get_int("no_trees", (tree == 0) ) ? 0 : 1; + lake = (contents.get_int("no_lakes", (lake == 0) )) ? 0 : 8; // these are pak specific; the diagonal length affect travelling time (is game critical) pak_diagonal_multiplier = contents.get_int("diagonal_multiplier", pak_diagonal_multiplier ); Index: dataobj/settings.h =================================================================== --- dataobj/settings.h (revision 9169) +++ dataobj/settings.h (working copy) @@ -120,6 +120,7 @@ sint16 groundwater; sint16 winter_snowline; sint16 climate_borders[MAX_CLIMATES][2]; + uint16 climate_generator; double max_mountain_height; double map_roughness; @@ -137,9 +138,9 @@ uint8 max_no_of_trees_on_square; uint16 tree_climates; uint16 no_tree_climates; - bool no_trees; + uint16 tree; - bool lake; + sint8 lake; // game mechanics uint8 allow_player_change; @@ -429,6 +430,9 @@ void set_default_climates(); sint8 get_climate_borders( sint8 climate, sint8 start_end ) const { return climate_borders[climate][start_end]; } + uint16 get_climate_generator() const { return climate_generator; } + void set_climate_generator(uint16 generator) { climate_generator = generator; } + sint16 get_winter_snowline() const { return winter_snowline; } void rotate90() { @@ -555,11 +559,11 @@ uint8 get_max_no_of_trees_on_square() const { return max_no_of_trees_on_square; } uint16 get_tree_climates() const { return tree_climates; } uint16 get_no_tree_climates() const { return no_tree_climates; } - bool get_no_trees() const { return no_trees; } - void set_no_trees(bool b) { no_trees = b; } + uint16 get_tree() const { return tree; } + void set_tree(uint16 i) { tree = i; } - bool get_lake() const { return lake; } - void set_lake(bool b) { lake = b; } + sint8 get_lake() const { return lake; } + void set_lake(sint8 h) { lake = h; } uint32 get_industry_increase_every() const { return industry_increase; } void set_industry_increase_every( uint32 n ) { industry_increase = n; } Index: gui/climates.cc =================================================================== --- gui/climates.cc (revision 9169) +++ gui/climates.cc (working copy) @@ -63,6 +63,14 @@ snowline_winter.init( sets->get_winter_snowline(), sets->get_groundwater(), 127, gui_numberinput_t::AUTOLINEAR, false ); snowline_winter.add_listener( this ); add_component( &snowline_winter ); + + new_component("climate generator"); + climate_generator.set_focusable( false ); + climate_generator.new_component( translator::translate( "height" ), SYSCOL_TEXT ); + climate_generator.new_component( translator::translate( "temperature-rainfall" ), SYSCOL_TEXT ); + climate_generator.set_selection( sets->get_climate_generator() ); + add_component( &climate_generator ); + climate_generator.add_listener( this ); } end_table(); @@ -78,21 +86,35 @@ climate_borders_ui[i][1].add_listener( this ); add_component( &(climate_borders_ui[i][1]) ); } + + if( sets->get_climate_generator()==1 ) { + // disable climate height selection (except arctic which is used for snowline) + for( int i=desert_climate-1; iget_no_trees(); - no_tree.add_listener( this ); - add_component( &no_tree ); + add_table(2,0); + { + new_component("Trees"); + tree.set_focusable( false ); + tree.new_component( translator::translate( "none" ), SYSCOL_TEXT ); + tree.new_component( translator::translate( "random" ), SYSCOL_TEXT ); + if( sets->get_climate_generator()==1 ) { + tree.new_component( translator::translate( "rainfall" ), SYSCOL_TEXT ); + } + tree.set_selection( sets->get_tree() ); + add_component( &tree ); + tree.add_listener( this ); - lake.init( button_t::square_state, "lake" ); - lake.pressed = sets->get_lake(); - lake.add_listener( this ); - add_component( &lake ); + new_component("Lake height"); + lake.init( sets->lake, sets->get_groundwater(), 127, gui_numberinput_t::AUTOLINEAR, false ); + lake.add_listener( this ); + add_component( &lake ); - add_table(2,0); - { new_component("Number of rivers"); river_n.init( sets->get_river_number(), 0, 1024, gui_numberinput_t::POWER2, false ); river_n.add_listener(this); @@ -121,13 +143,11 @@ bool climate_gui_t::action_triggered( gui_action_creator_t *comp, value_t v) { welt_gui_t *welt_gui = dynamic_cast(win_get_magic( magic_welt_gui_t )); - if(comp==&no_tree) { - no_tree.pressed ^= 1; - sets->set_no_trees(no_tree.pressed); + if(comp==&tree) { + sets->set_tree((sint16)v.i); } else if(comp==&lake) { - lake.pressed ^= 1; - sets->set_lake(lake.pressed); + sets->lake = (sint16)v.i; } else if(comp==&water_level) { sets->groundwater = (sint16)v.i; @@ -150,6 +170,41 @@ welt_gui->update_preview(); } } + else if(comp==&climate_generator) { + sets->set_climate_generator( (uint16)v.i ); + if( sets->get_climate_generator()!=1 ) { + + // disable rainfall tree generation + if( sets->get_tree()==2 ) { + sets->set_tree(1); + } + tree.clear_elements(); + tree.new_component( translator::translate( "none" ), SYSCOL_TEXT ); + tree.new_component( translator::translate( "random" ), SYSCOL_TEXT ); + tree.set_selection( sets->get_tree() ); + + // enable climate height selection + for( int i=desert_climate-1; i( translator::translate( "none" ), SYSCOL_TEXT ); + tree.new_component( translator::translate( "random" ), SYSCOL_TEXT ); + tree.new_component( translator::translate( "rainfall" ), SYSCOL_TEXT ); + tree.set_selection( sets->get_tree() ); + + // disable climate height selection (except arctic which is used for snowline) + for( int i=desert_climate-1; iriver_number = (sint16)v.i; } Index: gui/climates.h =================================================================== --- gui/climates.h (revision 9169) +++ gui/climates.h (working copy) @@ -11,6 +11,7 @@ #include "components/gui_button.h" #include "components/gui_label.h" #include "components/gui_numberinput.h" +#include "components/gui_combobox.h" #include "components/action_listener.h" #include "components/gui_textinput.h" @@ -35,11 +36,12 @@ gui_label_buf_t summer_snowline; - button_t - no_tree; // without tree + gui_combobox_t + tree, + climate_generator; - button_t - lake; // lake + gui_numberinput_t + lake; // lake height gui_numberinput_t river_n, Index: gui/settings_stats.cc =================================================================== --- gui/settings_stats.cc (revision 9169) +++ gui/settings_stats.cc (working copy) @@ -513,7 +513,7 @@ end_table(); SEPERATOR - INIT_BOOL( "lake", sets->get_lake() ); + INIT_NUM_NEW( "lake", sets->get_lake(), 0, 127, gui_numberinput_t::AUTOLINEAR, false ); INIT_NUM_NEW( "Number of rivers", sets->get_river_number(), 0, 1024, gui_numberinput_t::AUTOLINEAR, false ); INIT_NUM_NEW( "minimum length of rivers", sets->get_min_river_length(), 0, max(16,sets->get_max_river_length())-16, gui_numberinput_t::AUTOLINEAR, false ); INIT_NUM_NEW( "maximum length of rivers", sets->get_max_river_length(), sets->get_min_river_length()+16, 8196, gui_numberinput_t::AUTOLINEAR, false ); @@ -523,7 +523,7 @@ } // the following are independent and thus need no listener SEPERATOR - INIT_BOOL( "no tree", sets->get_no_trees() ); + INIT_NUM_NEW( "tree", sets->get_tree() , 0, 2, gui_numberinput_t::AUTOLINEAR, false); INIT_NUM_NEW( "forest_base_size", sets->get_forest_base_size(), 10, 255, 1, false ); INIT_NUM_NEW( "forest_map_size_divisor", sets->get_forest_map_size_divisor(), 2, 255, 1, false ); INIT_NUM_NEW( "forest_count_divisor", sets->get_forest_count_divisor(), 2, 255, 1, false ); @@ -555,11 +555,11 @@ READ_NUM_VALUE( ch ); sets->climate_borders[i][1] = ch; } - READ_BOOL_VALUE( sets->lake ); + READ_NUM_VALUE_NEW( sets->lake ); READ_NUM_VALUE_NEW( sets->river_number ); READ_NUM_VALUE_NEW( sets->min_river_length ); READ_NUM_VALUE_NEW( sets->max_river_length ); - READ_BOOL_VALUE( sets->no_trees ); + READ_NUM_VALUE_NEW( sets->tree ); READ_NUM_VALUE_NEW( sets->forest_base_size ); READ_NUM_VALUE_NEW( sets->forest_map_size_divisor ); READ_NUM_VALUE_NEW( sets->forest_count_divisor ); Index: gui/welt.cc =================================================================== --- gui/welt.cc (revision 9169) +++ gui/welt.cc (working copy) @@ -338,7 +338,7 @@ ( sizeof(grund_t) + sizeof(planquadrat_t) + - sizeof(baum_t)*(1-sets->get_no_trees()) + /* only one since a lot will be water */ + sizeof(baum_t)*(sets->get_tree()>0) + /* only one since a lot will be water */ sizeof(void*)*2 ) * (uint64)sx * (uint64)sy ) / (1024ll * 1024ll); Index: obj/baum.h =================================================================== --- obj/baum.h (revision 9169) +++ obj/baum.h (working copy) @@ -50,8 +50,6 @@ static uint16 random_tree_for_climate_intern(climate cl); - static uint8 plant_tree_on_coordinate(koord pos, const uint8 maximum_count, const uint8 count); - public: /** * Only the load save constructor should be called outside @@ -119,6 +117,8 @@ static bool plant_tree_on_coordinate(koord pos, const tree_desc_t *desc, const bool check_climate, const bool random_age ); + static uint8 plant_tree_on_coordinate(koord pos, const uint8 maximum_count, const uint8 count); + static bool register_desc(tree_desc_t *desc); static bool successfully_loaded(); Index: simtool.cc =================================================================== --- simtool.cc (revision 9169) +++ simtool.cc (working copy) @@ -2129,7 +2129,7 @@ grund_t *gr = welt->lookup_kartenboden(k); if(gr) { // check if trees are allowed - if( welt->get_settings().get_no_trees() && !player->is_public_service() ) { + if( welt->get_settings().get_tree()==0 && !player->is_public_service() ) { return NOTICE_NO_TREES; } Index: simworld.cc =================================================================== --- simworld.cc (revision 9169) +++ simworld.cc (working copy) @@ -1187,8 +1187,12 @@ } +sint8 *humidity; + void karte_t::init(settings_t* const sets, sint8 const* const h_field) { + humidity = NULL; + clear_random_mode( 7 ); mute_sound(true); if (env_t::networkmode) { @@ -1272,10 +1276,44 @@ script_api::new_world(); DBG_DEBUG("karte_t::init()","distributing trees"); - if (!settings.get_no_trees()) { - baum_t::distribute_trees(3); + switch (settings.get_tree()) { + case 1: + baum_t::distribute_trees(3); + break; + case 2: + koord pos; + for( pos.y=0; pos.yget_top() == 0 && gr->get_typ() == grund_t::boden) { + if(humidity[pos.x+get_size().x*pos.y]>75) { + const uint32 tree_probability = (humidity[pos.x+get_size().x*pos.y] - 75)/5 + 38; + uint8 number_to_plant = 0; + uint8 const max_trees_here = min(get_settings().get_max_no_of_trees_on_square(), (tree_probability - 38 + 1) / 2); + for (uint8 c2 = 0 ; c230) { + // plant spare trees, (those with low preffered density) or in an entirely tree climate + uint16 cl = 1 << get_climate(pos); + settings_t const& s = get_settings(); + if ((cl & s.get_no_tree_climates()) == 0 && ((cl & s.get_tree_climates()) != 0 || simrand(s.get_forest_inverse_spare_tree_density() * (75-humidity[pos.x+get_size().x*pos.y])/5) < 100)) { + baum_t::plant_tree_on_coordinate(pos, 1, 1); + } + } + } + } + } + break; } + delete [] humidity; + DBG_DEBUG("karte_t::init()","built timeline"); private_car_t::build_timeline_list(this); pedestrian_t::build_timeline_list(this); @@ -1433,7 +1471,7 @@ } } -void karte_t::create_lakes( int xoff, int yoff ) +void karte_t::create_lakes( int xoff, int yoff, sint8 max_lake_height ) { if( xoff > 0 || yoff > 0 ) { // too complicated to add lakes to an already existing world... @@ -1440,7 +1478,6 @@ return; } - const sint8 max_lake_height = groundwater + 8; const uint16 size_x = get_size().x; const uint16 size_y = get_size().y; @@ -1896,8 +1933,8 @@ ls.set_progress(12); } - if( sets->get_lake() ) { - create_lakes( old_x, old_y ); + if( sets->get_lake()>0 ) { + create_lakes( old_x, old_y, sets->get_lake() ); } if ( old_x == 0 && old_y == 0 ) { @@ -5993,6 +6030,9 @@ sint16 groundwater = settings.get_groundwater(); + printf("%d\n",settings.get_climate_generator()); + switch(settings.get_climate_generator()) { + case 0: { // first remove water all clear single tiles from effort // for the first passes, we only work on the grid, which is much faster for( sint16 y = ytop; y < ybottom; y++ ) { @@ -6058,6 +6098,178 @@ } } } + } + break; + case 1: { + if(humidity == NULL) { + humidity = new sint8[get_size().x * get_size().y]; + } + + for( sint16 y = ytop; y < ybottom; y++ ) { + sint8 current_humidity = ( lookup_hgt_nocheck( 0, y ) < groundwater ) ? 50 : 50; + for( sint16 x = xtop; x < xbottom; x++ ) { + sint8 gradient = x>0 ? lookup_hgt_nocheck( x, y )-lookup_hgt_nocheck( x-1, y ) : 0; + + if( lookup_hgt_nocheck( x, y ) < groundwater ) { + current_humidity += 1; + } + else { + current_humidity += 1 + gradient * 10; + } + if( current_humidity > 100 ) current_humidity = 100; + if( current_humidity < 0 ) current_humidity = 0; + + humidity[x+y*get_size().x] = current_humidity; + + } + } + + for(int s=0; s<2; s++) { + for( sint16 y = ytop; y < ybottom; y++ ) { + for( sint16 x = xtop; x < xbottom; x++ ) { + sint8 our_humidity = humidity[x+y*(get_size().x)]; + for(int i=0; i<8; i++) { + sint8 their_humidity; + koord k_neighbour = koord(x,y) + koord::neighbours[i]; + if( is_within_limits(k_neighbour.x, k_neighbour.y) ) { + their_humidity = humidity[k_neighbour.x+k_neighbour.y*(get_size().x)]; + } + else { + their_humidity = humidity[x+y*(get_size().x)]; + } + if(their_humidity > our_humidity + ((i&1) ? 30:50)) our_humidity = humidity[x+y*(get_size().x)] + (i&1) ? 50 : 30; + } + humidity[x+y*(get_size().x)]=our_humidity; + } + } + } + + if( xtop == 0 && ytop == 0 ) { + climate_map.clear(); + } + climate_map.resize( xbottom, ybottom, 0x7F ); + + sint16 groundwater = settings.get_groundwater(); + const sint16 winterline = settings.get_winter_snowline(); + const sint16 summerline = max(settings.get_climate_borders(arctic_climate,1),settings.get_climate_borders(arctic_climate,0)); + + // annual mean temperature at summer snowline must be less than zero + // assume annual mean temperature at winter snowline is 14 celcius + + const sint8 snowline_diff = summerline-winterline; + + const sint8 groundwater_temperature = 14+((winterline-groundwater)*14)/(snowline_diff!=0?snowline_diff:1); + + // first remove water all clear single tiles from effort + // for the first passes, we only work on the grid, which is much faster + for( sint16 y = ytop; y < ybottom; y++ ) { + for( sint16 x = xtop; x < xbottom; x++ ) { + sint8 hgt = lookup_hgt_nocheck( x, y ); + if( hgt < groundwater ) { + climate_map.at( x, y ) = water_climate; + } + else { + climate this_climate; + + sint8 temperature = groundwater_temperature - (hgt-groundwater) - simrand(2); + sint8 this_humidity = humidity[x+y*get_size().x] + simrand(5); + + if( temperature >= 20 ) { + if( this_humidity > 75 ) { + this_climate = tropic_climate; + } + else if( this_humidity > 65 ) { + this_climate = mediterran_climate; + } + else { + this_climate = desert_climate; + } + } + else if( temperature >= 15 ) { + if( this_humidity > 65 ) { + this_climate = mediterran_climate; + } + else { + this_climate = desert_climate; + } + } + else if( temperature >= 8 ) { + if( this_humidity > 65 ) { + this_climate = temperate_climate; + } + else { + this_climate = mediterran_climate; + } + } + else if( temperature >= 0 ) { + if( this_humidity > 65 ) { + this_climate = tundra_climate; + } + else { + this_climate = temperate_climate; + } + } + else if( temperature >= -10 ) { + this_climate = rocky_climate; + } + else { + this_climate = arctic_climate; + } + + climate_map.at( x, y ) = this_climate; + } + } + } + + // smooth climates + const sint32 world_size = (get_size().x)*(sint32)(get_size().y); + climate *climate_smooth = new climate[world_size]; + climate *climate_smooth_cpy = new climate[world_size]; + + for(uint16 y=0; yget_map_roughness()*(simrand(8)); + climate_smooth[x+y*(get_size().x)]=(climate)((temp_climate)/16); + } + } + } + } + + for(uint16 y=0; y