Index: simworld.cc =================================================================== --- simworld.cc (revision 9140) +++ simworld.cc (working copy) @@ -211,7 +211,7 @@ world_thread_param[t].welt = this; world_thread_param[t].thread_num = t; - world_thread_param[t].x_step = min( 64, max_x / env_t::num_threads ); + world_thread_param[t].x_step = sync_x_steps ? min( 64, max_x / env_t::num_threads ) : max_x; world_thread_param[t].x_world_max = max_x; world_thread_param[t].y_min = (t * max_y) / env_t::num_threads; world_thread_param[t].y_max = ((t + 1) * max_y) / env_t::num_threads; @@ -1353,6 +1358,81 @@ * To start with every tile in the map is checked - but when we fail for * a tile then it is excluded from subsequent checks */ +sint8 *stage; +sint8 *new_stage; +sint8 *local_stage; +sint8 *max_water_hgt; +bool need_to_flood; +sint8 h; + +#define LAKE_SUCCESS 1 +#define LAKE_FAIL 0 +#define LAKE_SEAM -1 + +void karte_t::create_lakes_loop( sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max ) +{ +// printf("flooding: %d,%d,%d,%d,%d\n", x_min, x_max, y_min, y_max, h); + const sint8 max_lake_height = groundwater + 8; + const uint16 size_x = get_size().x; + const uint16 size_y = get_size().y; + + if( x_min < 1 ) x_min = 1; + //if( y_min < 1 ) y_min = 1; + y_min++; // first row is barrier even if not at world edge + if( x_max > size_x-1 ) x_max = size_x-1; + if( y_max > size_y-1 ) y_max = size_y-1; + + for( uint16 y = y_min; y < y_max; y++ ) { + for( uint16 x = x_min; x < x_max; x++ ) { + uint32 offset = array_koord(x,y); + if( max_water_hgt[offset]==1 && stage[offset]==-1 ) { + + sint8 hgt = lookup_hgt_nocheck( x, y ); + const sint8 water_hgt = water_hgts[offset]; // optimised <- get_water_hgt_nocheck(x, y); + const sint8 new_water_hgt = max(hgt, water_hgt); + if( new_water_hgt>max_lake_height ) { + max_water_hgt[offset] = 0; + } + else if( h>new_water_hgt ) { + koord k(x,y); +//printf("flood to depth: init(%d-", dr_time()); + for( uint16 iy = y_min; iy -1 ) { + max_water_hgt[local_offset] = 0; + } + } + } + } +//printf("end: %d\n", dr_time()); + } + } + } + } +} + void karte_t::create_lakes( int xoff, int yoff ) { if( xoff > 0 || yoff > 0 ) { @@ -1364,54 +1444,45 @@ const uint16 size_x = get_size().x; const uint16 size_y = get_size().y; - sint8 *max_water_hgt = new sint8[size_x * size_y]; + max_water_hgt = new sint8[size_x * size_y]; memset( max_water_hgt, 1, sizeof(sint8) * size_x * size_y ); - sint8 *stage = new sint8[size_x * size_y]; - sint8 *new_stage = new sint8[size_x * size_y]; - sint8 *local_stage = new sint8[size_x * size_y]; + stage = new sint8[size_x * size_y]; + new_stage = new sint8[size_x * size_y]; + local_stage = new sint8[size_x * size_y]; - for( sint8 h = groundwater+1; hmax_lake_height ) { - max_water_hgt[offset] = 0; - } - else if( h>new_water_hgt ) { - koord k(x,y); - memcpy( new_stage, stage, sizeof(sint8) * size_x * size_y ); - if(can_flood_to_depth( k, h, new_stage, local_stage )) { - sint8 *tmp_stage = new_stage; - new_stage = stage; - stage = tmp_stage; - need_to_flood = true; - } - else { - for( uint16 iy = 1; iy -1 ) { - max_water_hgt[local_offset] = 0; - } - } - } - } - } - } - } +// set seams to invalid + for( int t = 1; t < env_t::num_threads; t++ ) { + sint16 y_min = (t * size_y) / env_t::num_threads; + create_lakes_loop( 0, size_x, y_min, y_min + 1 ); + memset( stage + sizeof(sint8) * array_koord(0,y_min), -2, sizeof(sint8) * (size_x) ); } + + world_xy_loop(&karte_t::create_lakes_loop, 0); + if(need_to_flood) { flood_to_depth( h, stage ); } - else { + + bool threaded_need_to_flood = need_to_flood; + need_to_flood = false; + memset( stage, -1, sizeof(sint8) * size_x * size_y ); + + for( int t = 1; t < env_t::num_threads - 1; t++ ) { + sint16 y_min = (t * size_y) / env_t::num_threads; + create_lakes_loop( 0, size_x, y_min, y_min + 1 ); + } + + if(need_to_flood) { + flood_to_depth( h, stage ); + } + else if(!threaded_need_to_flood) { break; } } @@ -1426,10 +1497,9 @@ } } - -bool karte_t::can_flood_to_depth( koord k, sint8 new_water_height, sint8 *stage, sint8 *our_stage ) const +uint8 karte_t::can_flood_to_depth( koord k, sint8 new_water_height, sint8 *stage, sint8 *our_stage, sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max ) const { - bool succeeded = true; + uint8 succeeded = LAKE_SUCCESS; if( k == koord::invalid ) { return false; } @@ -1448,8 +1518,14 @@ our_stage = new sint8[get_size().x * get_size().y]; } - memset( from_dir, -1, sizeof(sint8) * get_size().x * get_size().y ); - memset( our_stage, -1, sizeof(sint8) * get_size().x * get_size().y ); +// memset( from_dir, -1, sizeof(sint8) * get_size().x * get_size().y ); +// memset( our_stage, -1, sizeof(sint8) * get_size().x * get_size().y ); + + for( uint16 iy = y_min; iy= x_min && k_neighbour.x= y_min && k_neighbour.y -1) goto next_neighbour; + if(our_stage[neighbour_offset] == -2) { + succeeded = LAKE_SEAM; + goto next_neighbour; + } + // water height above if(water_hgts[neighbour_offset] >= new_water_height) goto next_neighbour; @@ -1484,7 +1565,7 @@ } else { // edge of map - we keep iterating so we can mark all connected tiles as failing - succeeded = false; + succeeded = LAKE_FAIL; } next_neighbour: //return back to previous tile @@ -1512,7 +1593,7 @@ uint32 offset_max = size_x*size_y; for( uint32 offset = 0; offset < offset_max; offset++ ) { - if( stage[offset] == -1 ) { + if( stage[offset] < 0 ) { continue; } water_hgts[offset] = new_water_height; Index: simworld.h =================================================================== --- simworld.h (revision 9140) +++ simworld.h (working copy) @@ -649,6 +649,11 @@ void create_rivers(sint16 number); /** + * Will create lakes (multithreaded). + */ + void create_lakes_loop(sint16, sint16, sint16, sint16); + + /** * Will create lakes. */ void create_lakes( int xoff, int yoff ); @@ -1117,7 +1122,7 @@ * lakes are left where there is no drainage */ void drain_tile(koord k, sint8 water_height); - bool can_flood_to_depth(koord k, sint8 new_water_height, sint8 *stage, sint8 *our_stage) const; + uint8 can_flood_to_depth(koord k, sint8 new_water_height, sint8 *stage, sint8 *our_stage, sint16, sint16, sint16, sint16) const; public: void flood_to_depth(sint8 new_water_height, sint8 *stage);