From 2d606ad534dfde58213bc78376a1ec202f479109 Mon Sep 17 00:00:00 2001 From: Kevin Granade Date: Wed, 15 May 2019 06:31:55 +0000 Subject: [PATCH] Extend shadowcasting test to 3D --- tests/shadowcasting_test.cpp | 298 +++++++++++++++++++++-------------- 1 file changed, 179 insertions(+), 119 deletions(-) diff --git a/tests/shadowcasting_test.cpp b/tests/shadowcasting_test.cpp index 50210a9d72cd3..3f2fac6f48d55 100644 --- a/tests/shadowcasting_test.cpp +++ b/tests/shadowcasting_test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -406,11 +407,11 @@ static void shadowcasting_3d_2d( const int iterations ) #define V LIGHT_TRANSPARENCY_CLEAR #define X LIGHT_TRANSPARENCY_SOLID -const point ORIGIN( 65, 65 ); +const tripoint ORIGIN( 65, 65, 11 ); struct grid_overlay { - std::vector> data; - point offset; + std::vector>> data; + tripoint offset; float default_value; // origin_offset is specified as the coordinates of the "camera" within the overlay. @@ -418,185 +419,244 @@ struct grid_overlay { this->offset = ORIGIN - origin_offset; this->default_value = default_value; } + grid_overlay( const tripoint origin_offset, const float default_value ) { + this->offset = ORIGIN - origin_offset; + this->default_value = default_value; + } - int height() const { + int depth() const { return data.size(); } - int width() const { + int height() const { if( data.empty() ) { return 0; } return data[0].size(); } + int width() const { + if( data.empty() || data[0].empty() ) { + return 0; + } + return data[0][0].size(); + } + tripoint get_max() const { + return offset + tripoint( width(), height(), depth() ); + } - float get_global( const int x, const int y ) const { + float get_global( const int x, const int y, const int z ) const { if( y >= offset.y && y < offset.y + height() && - x >= offset.x && x < offset.x + width() ) { - return data[ y - offset.y ][ x - offset.x ]; + x >= offset.x && x < offset.x + width() && + z >= offset.z && z < offset.z + depth() ) { + return data[ z - offset.z ][ y - offset.y ][ x - offset.x ]; } return default_value; } - - float get_local( const int x, const int y ) const { - return data[ y ][ x ]; - } }; -static void run_spot_check( const grid_overlay &test_case, const grid_overlay &expected_result ) +static void run_spot_check( const grid_overlay &test_case, const grid_overlay &expected, + bool fov_3d ) { - float seen_squares[ MAPSIZE * SEEY ][ MAPSIZE * SEEX ] = {{ 0 }}; - float transparency_cache[ MAPSIZE * SEEY ][ MAPSIZE * SEEX ] = {{ 0 }}; - - for( int y = 0; y < static_cast( sizeof( transparency_cache ) / - sizeof( transparency_cache[0] ) ); ++y ) { - for( int x = 0; x < static_cast( sizeof( transparency_cache[0] ) / - sizeof( transparency_cache[0][0] ) ); ++x ) { - transparency_cache[ y ][ x ] = test_case.get_global( x, y ); + // Reminder to not trigger 2D shadowcasting on 3D use cases. + if( !fov_3d ) { + REQUIRE( test_case.depth() == 1 ); + } + level_cache *caches[OVERMAP_LAYERS]; + std::array seen_squares; + std::array transparency_cache; + std::array floor_cache; + + int z = fov_3d ? 0 : 11; + const int upper_bound = fov_3d ? OVERMAP_LAYERS : 12; + for( ; z < upper_bound; ++z ) { + caches[z] = new level_cache(); + seen_squares[z] = &caches[z]->seen_cache; + transparency_cache[z] = &caches[z]->transparency_cache; + floor_cache[z] = &caches[z]->floor_cache; + for( int y = 0; y < MAPSIZE * SEEY; ++y ) { + for( int x = 0; x < MAPSIZE * SEEX; ++x ) { + caches[z]->transparency_cache[x][y] = test_case.get_global( x, y, z ); + } } } - castLightAll( - seen_squares, transparency_cache, ORIGIN.x, ORIGIN.y ); + if( fov_3d ) { + cast_zlight( seen_squares, + transparency_cache, floor_cache, { ORIGIN.x, ORIGIN.y, ORIGIN.z - OVERMAP_DEPTH }, 0, 1.0 ); + } else { + castLightAll( + *seen_squares[11], *transparency_cache[11], ORIGIN.x, ORIGIN.y ); - // Compares the whole grid, but out-of-bounds compares will de-facto pass. - for( int y = 0; y < expected_result.height(); ++y ) { - for( int x = 0; x < expected_result.width(); ++x ) { - INFO( "x:" << x << " y:" << y << " expected:" << expected_result.data[y][x] << " actual:" << - seen_squares[expected_result.offset.y + y][expected_result.offset.x + x] ); - if( V == expected_result.get_local( x, y ) ) { - CHECK( seen_squares[expected_result.offset.y + y][expected_result.offset.x + x] > 0 ); - } else { - CHECK( seen_squares[expected_result.offset.y + y][expected_result.offset.x + x] == 0 ); + } + bool passed = true; + std::ostringstream trans_grid; + std::ostringstream expected_grid; + std::ostringstream actual_grid; + for( int gz = expected.offset.z; gz < expected.get_max().z; ++gz ) { + for( int gy = expected.offset.y; gy < expected.get_max().y; ++gy ) { + for( int gx = expected.offset.x; gx < expected.get_max().x; ++gx ) { + trans_grid << caches[gz]->transparency_cache[gx][gy]; + expected_grid << ( expected.get_global( gx, gy, gz ) > 0 ? 'V' : 'O' ); + actual_grid << ( ( *seen_squares[gz] )[gx][gy] > 0 ? 'V' : 'O' ); + if( V == expected.get_global( gx, gy, gz ) && ( *seen_squares[gz] )[gx][gy] == 0 ) { + passed = false; + } else if( O == expected.get_global( gx, gy, gz ) && + ( *seen_squares[gz] )[gx][gy] > 0 ) { + passed = false; + } } + trans_grid << '\n'; + expected_grid << '\n'; + actual_grid << '\n'; } + trans_grid << '\n'; + expected_grid << '\n'; + actual_grid << '\n'; + delete caches[gz]; } + CAPTURE( fov_3d ); + INFO( "transparency:\n" << trans_grid.str() ); + INFO( "actual:\n" << actual_grid.str() ); + INFO( "expected:\n" << expected_grid.str() ); + CHECK( passed ); } TEST_CASE( "shadowcasting_slope_inversion_regression_test", "[shadowcasting]" ) { grid_overlay test_case( { 7, 8 }, LIGHT_TRANSPARENCY_CLEAR ); - test_case.data = { - {T, T, T, T, T, T, T, T, T, T}, - {T, O, T, T, T, T, T, T, T, T}, - {T, O, T, T, T, T, T, T, T, T}, - {T, O, O, T, O, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, O, T}, - {T, T, T, T, T, T, O, T, O, T}, - {T, T, T, T, T, T, O, O, O, T}, - {T, T, T, T, T, T, T, T, T, T} + test_case.data = { { + {T, T, T, T, T, T, T, T, T, T}, + {T, O, T, T, T, T, T, T, T, T}, + {T, O, T, T, T, T, T, T, T, T}, + {T, O, O, T, O, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, O, T}, + {T, T, T, T, T, T, O, T, O, T}, + {T, T, T, T, T, T, O, O, O, T}, + {T, T, T, T, T, T, T, T, T, T} + } }; grid_overlay expected_results( { 7, 8 }, LIGHT_TRANSPARENCY_CLEAR ); - expected_results.data = { - {O, O, O, V, V, V, V, V, V, V}, - {O, V, V, O, V, V, V, V, V, V}, - {O, O, V, V, V, V, V, V, V, V}, - {O, O, V, V, V, V, V, V, V, V}, - {O, O, V, V, V, V, V, V, V, V}, - {O, O, O, V, V, V, V, V, V, O}, - {O, O, O, O, V, V, V, V, V, O}, - {O, O, O, O, O, V, V, V, V, O}, - {O, O, O, O, O, O, V, X, V, O}, - {O, O, O, O, O, O, V, V, V, O}, - {O, O, O, O, O, O, O, O, O, O} + expected_results.data = { { + {O, O, O, V, V, V, V, V, V, V}, + {O, V, V, O, V, V, V, V, V, V}, + {O, O, V, V, V, V, V, V, V, V}, + {O, O, V, V, V, V, V, V, V, V}, + {O, O, V, V, V, V, V, V, V, V}, + {O, O, O, V, V, V, V, V, V, O}, + {O, O, O, O, V, V, V, V, V, O}, + {O, O, O, O, O, V, V, V, V, O}, + {O, O, O, O, O, O, V, X, V, O}, + {O, O, O, O, O, O, V, V, V, O}, + {O, O, O, O, O, O, O, O, O, O} + } }; - run_spot_check( test_case, expected_results ); + run_spot_check( test_case, expected_results, true ); + run_spot_check( test_case, expected_results, false ); } TEST_CASE( "shadowcasting_pillar_behavior_cardinally_adjacent", "[shadowcasting]" ) { grid_overlay test_case( { 1, 4 }, LIGHT_TRANSPARENCY_CLEAR ); - test_case.data = { - {T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T}, - {T, T, O, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T} + test_case.data = { { + {T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T}, + {T, T, O, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T} + } }; grid_overlay expected_results( { 1, 4 }, LIGHT_TRANSPARENCY_CLEAR ); - expected_results.data = { - {V, V, V, V, V, V, V, O, O}, - {V, V, V, V, V, V, O, O, O}, - {V, V, V, V, V, O, O, O, O}, - {V, V, V, V, O, O, O, O, O}, - {V, X, V, O, O, O, O, O, O}, - {V, V, V, V, O, O, O, O, O}, - {V, V, V, V, V, O, O, O, O}, - {V, V, V, V, V, V, O, O, O}, - {V, V, V, V, V, V, V, O, O} + expected_results.data = { { + {V, V, V, V, V, V, V, O, O}, + {V, V, V, V, V, V, O, O, O}, + {V, V, V, V, V, O, O, O, O}, + {V, V, V, V, O, O, O, O, O}, + {V, X, V, O, O, O, O, O, O}, + {V, V, V, V, O, O, O, O, O}, + {V, V, V, V, V, O, O, O, O}, + {V, V, V, V, V, V, O, O, O}, + {V, V, V, V, V, V, V, O, O} + } }; - run_spot_check( test_case, expected_results ); + run_spot_check( test_case, expected_results, true ); + run_spot_check( test_case, expected_results, false ); } TEST_CASE( "shadowcasting_pillar_behavior_2_1_diagonal_gap", "[shadowcasting]" ) { grid_overlay test_case( { 1, 1 }, LIGHT_TRANSPARENCY_CLEAR ); - test_case.data = { - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, O, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T} + test_case.data = { { + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, O, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T} + } }; grid_overlay expected_results( { 1, 1 }, LIGHT_TRANSPARENCY_CLEAR ); - expected_results.data = { - {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, - {V, X, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, - {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, - {V, V, V, V, V, O, O, O, V, V, V, V, V, V, V, V, V, V}, - {V, V, V, V, V, V, O, O, O, O, O, O, O, V, V, V, V, V}, - {V, V, V, V, V, V, V, O, O, O, O, O, O, O, O, O, O, O}, - {V, V, V, V, V, V, V, V, O, O, O, O, O, O, O, O, O, O}, - {V, V, V, V, V, V, V, V, V, O, O, O, O, O, O, O, O, O}, - {V, V, V, V, V, V, V, V, V, V, O, O, O, O, O, O, O, O}, + expected_results.data = { { + {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, + {V, X, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, + {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, + {V, V, V, V, V, O, O, O, V, V, V, V, V, V, V, V, V, V}, + {V, V, V, V, V, V, O, O, O, O, O, O, O, V, V, V, V, V}, + {V, V, V, V, V, V, V, O, O, O, O, O, O, O, O, O, O, O}, + {V, V, V, V, V, V, V, V, O, O, O, O, O, O, O, O, O, O}, + {V, V, V, V, V, V, V, V, V, O, O, O, O, O, O, O, O, O}, + {V, V, V, V, V, V, V, V, V, V, O, O, O, O, O, O, O, O}, + } }; - run_spot_check( test_case, expected_results ); + run_spot_check( test_case, expected_results, true ); + run_spot_check( test_case, expected_results, false ); } TEST_CASE( "shadowcasting_vision_along_a_wall", "[shadowcasting]" ) { grid_overlay test_case( { 8, 2 }, LIGHT_TRANSPARENCY_CLEAR ); - test_case.data = { - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, - {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T} + test_case.data = { { + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T}, + {T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T} + } }; grid_overlay expected_results( { 8, 2 }, LIGHT_TRANSPARENCY_CLEAR ); - expected_results.data = { - {O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O}, - {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, - {V, V, V, V, V, V, V, V, X, V, V, V, V, V, V, V, V, V}, - {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, - {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, - {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, - {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, - {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V} + expected_results.data = { { + {O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O}, + {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, + {V, V, V, V, V, V, V, V, X, V, V, V, V, V, V, V, V, V}, + {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, + {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, + {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, + {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}, + {V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V} + } }; - run_spot_check( test_case, expected_results ); + run_spot_check( test_case, expected_results, true ); + run_spot_check( test_case, expected_results, false ); } // Some random edge cases aren't matching.