1 #include <memory> 2 #include <vector> 3 4 #include "calendar.h" 5 #include "catch/catch.hpp" 6 #include "common_types.h" 7 #include "coordinates.h" 8 #include "enums.h" 9 #include "game_constants.h" 10 #include "omdata.h" 11 #include "overmap.h" 12 #include "overmap_types.h" 13 #include "overmapbuffer.h" 14 #include "type_id.h" 15 16 TEST_CASE( "set_and_get_overmap_scents" ) 17 { 18 std::unique_ptr<overmap> test_overmap = std::make_unique<overmap>( point_abs_om() ); 19 20 // By default there are no scents set. 21 for( int x = 0; x < 180; ++x ) { 22 for( int y = 0; y < 180; ++y ) { 23 for( int z = -10; z < 10; ++z ) { 24 REQUIRE( test_overmap->scent_at( { x, y, z } ).creation_time == 25 calendar::before_time_starts ); 26 } 27 } 28 } 29 30 time_point creation_time = calendar::turn_zero + 50_turns; 31 scent_trace test_scent( creation_time, 90 ); 32 test_overmap->set_scent( { 75, 85, 0 }, test_scent ); 33 REQUIRE( test_overmap->scent_at( { 75, 85, 0} ).creation_time == creation_time ); 34 REQUIRE( test_overmap->scent_at( { 75, 85, 0} ).initial_strength == 90 ); 35 } 36 37 TEST_CASE( "default_overmap_generation_always_succeeds", "[slow]" ) 38 { 39 int overmaps_to_construct = 10; 40 for( const point_abs_om &candidate_addr : closest_points_first( point_abs_om(), 10 ) ) { 41 // Skip populated overmaps. 42 if( overmap_buffer.has( candidate_addr ) ) { 43 continue; 44 } 45 overmap_special_batch test_specials = overmap_specials::get_default_batch( candidate_addr ); 46 overmap_buffer.create_custom_overmap( candidate_addr, test_specials ); 47 for( const auto &special_placement : test_specials ) { 48 const overmap_special *special = special_placement.special_details; 49 INFO( "In attempt #" << overmaps_to_construct 50 << " failed to place " << special->id.str() ); 51 CHECK( special->occurrences.min <= special_placement.instances_placed ); 52 } 53 if( --overmaps_to_construct <= 0 ) { 54 break; 55 } 56 } 57 } 58 59 TEST_CASE( "default_overmap_generation_has_non_mandatory_specials_at_origin", "[slow]" ) 60 { 61 const point_abs_om origin{}; 62 63 overmap_special mandatory; 64 overmap_special optional; 65 66 // Get some specific overmap specials so we can assert their presence later. 67 // This should probably be replaced with some custom specials created in 68 // memory rather than tying this test to these, but it works for now... 69 for( const auto &elem : overmap_specials::get_all() ) { 70 if( elem.id == overmap_special_id( "Cabin" ) ) { 71 optional = elem; 72 } else if( elem.id == overmap_special_id( "Lab" ) ) { 73 mandatory = elem; 74 } 75 } 76 77 // Make this mandatory special impossible to place. 78 mandatory.city_size.min = 999; 79 80 // Construct our own overmap_special_batch containing only our single mandatory 81 // and single optional special, so we can make some assertions. 82 std::vector<const overmap_special *> specials; 83 specials.push_back( &mandatory ); 84 specials.push_back( &optional ); 85 overmap_special_batch test_specials = overmap_special_batch( origin, specials ); 86 87 // Run the overmap creation, which will try to place our specials. 88 overmap_buffer.create_custom_overmap( origin, test_specials ); 89 90 // Get the origin overmap... 91 overmap *test_overmap = overmap_buffer.get_existing( origin ); 92 93 // ...and assert that the optional special exists on this map. 94 bool found_optional = false; 95 for( int x = 0; x < OMAPX; ++x ) { 96 for( int y = 0; y < OMAPY; ++y ) { 97 const oter_id t = test_overmap->ter( { x, y, 0 } ); 98 if( t->id == "cabin" || 99 t->id == "cabin_north" || t->id == "cabin_east" || 100 t->id == "cabin_south" || t->id == "cabin_west" ) { 101 found_optional = true; 102 } 103 } 104 } 105 106 INFO( "Failed to place optional special on origin " ); 107 CHECK( found_optional == true ); 108 } 109 110 TEST_CASE( "is_ot_match", "[overmap][terrain]" ) 111 { 112 SECTION( "exact match" ) { 113 // Matches the complete string 114 CHECK( is_ot_match( "forest", oter_id( "forest" ), ot_match_type::exact ) ); 115 CHECK( is_ot_match( "central_lab", oter_id( "central_lab" ), ot_match_type::exact ) ); 116 117 // Does not exactly match if rotation differs 118 CHECK_FALSE( is_ot_match( "sub_station", oter_id( "sub_station_north" ), ot_match_type::exact ) ); 119 CHECK_FALSE( is_ot_match( "sub_station", oter_id( "sub_station_south" ), ot_match_type::exact ) ); 120 } 121 122 SECTION( "type match" ) { 123 // Matches regardless of rotation 124 CHECK( is_ot_match( "sub_station", oter_id( "sub_station_north" ), ot_match_type::type ) ); 125 CHECK( is_ot_match( "sub_station", oter_id( "sub_station_south" ), ot_match_type::type ) ); 126 CHECK( is_ot_match( "sub_station", oter_id( "sub_station_east" ), ot_match_type::type ) ); 127 CHECK( is_ot_match( "sub_station", oter_id( "sub_station_west" ), ot_match_type::type ) ); 128 129 // Does not match if base type does not match 130 CHECK_FALSE( is_ot_match( "lab", oter_id( "central_lab" ), ot_match_type::type ) ); 131 CHECK_FALSE( is_ot_match( "sub_station", oter_id( "sewer_sub_station" ), ot_match_type::type ) ); 132 } 133 134 SECTION( "prefix match" ) { 135 // Matches the complete string 136 CHECK( is_ot_match( "forest", oter_id( "forest" ), ot_match_type::prefix ) ); 137 CHECK( is_ot_match( "central_lab", oter_id( "central_lab" ), ot_match_type::prefix ) ); 138 139 // Prefix matches when an underscore separator exists 140 CHECK( is_ot_match( "central", oter_id( "central_lab" ), ot_match_type::prefix ) ); 141 CHECK( is_ot_match( "central", oter_id( "central_lab_stairs" ), ot_match_type::prefix ) ); 142 143 // Prefix itself may contain underscores 144 CHECK( is_ot_match( "central_lab", oter_id( "central_lab_stairs" ), ot_match_type::prefix ) ); 145 CHECK( is_ot_match( "central_lab_train", oter_id( "central_lab_train_depot" ), 146 ot_match_type::prefix ) ); 147 148 // Prefix does not match without an underscore separator 149 CHECK_FALSE( is_ot_match( "fore", oter_id( "forest" ), ot_match_type::prefix ) ); 150 CHECK_FALSE( is_ot_match( "fore", oter_id( "forest_thick" ), ot_match_type::prefix ) ); 151 152 // Prefix does not match the middle or end 153 CHECK_FALSE( is_ot_match( "lab", oter_id( "central_lab" ), ot_match_type::prefix ) ); 154 CHECK_FALSE( is_ot_match( "lab", oter_id( "central_lab_stairs" ), ot_match_type::prefix ) ); 155 } 156 157 SECTION( "contains match" ) { 158 // Matches the complete string 159 CHECK( is_ot_match( "forest", oter_id( "forest" ), ot_match_type::contains ) ); 160 CHECK( is_ot_match( "central_lab", oter_id( "central_lab" ), ot_match_type::contains ) ); 161 162 // Matches the beginning/middle/end of an underscore-delimited id 163 CHECK( is_ot_match( "central", oter_id( "central_lab_stairs" ), ot_match_type::contains ) ); 164 CHECK( is_ot_match( "lab", oter_id( "central_lab_stairs" ), ot_match_type::contains ) ); 165 CHECK( is_ot_match( "stairs", oter_id( "central_lab_stairs" ), ot_match_type::contains ) ); 166 167 // Matches the beginning/middle/end without undercores as well 168 CHECK( is_ot_match( "cent", oter_id( "central_lab_stairs" ), ot_match_type::contains ) ); 169 CHECK( is_ot_match( "ral_lab", oter_id( "central_lab_stairs" ), ot_match_type::contains ) ); 170 CHECK( is_ot_match( "_lab_", oter_id( "central_lab_stairs" ), ot_match_type::contains ) ); 171 CHECK( is_ot_match( "airs", oter_id( "central_lab_stairs" ), ot_match_type::contains ) ); 172 173 // Does not match if substring is not contained 174 CHECK_FALSE( is_ot_match( "forest", oter_id( "central_lab" ), ot_match_type::contains ) ); 175 CHECK_FALSE( is_ot_match( "forestry", oter_id( "forest" ), ot_match_type::contains ) ); 176 } 177 } 178 179