From f12a7e74572bcc4158da36089a26edf2debecffa Mon Sep 17 00:00:00 2001 From: John Bytheway <52664+jbytheway@users.noreply.github.com> Date: Wed, 22 Sep 2021 13:00:08 -0400 Subject: [PATCH] Support more neighbours in jmapgen_nested Previously only the cardinal directions and above were supported; now all eight horizontal neighbours, above, and below are. --- src/game.cpp | 2 ++ src/line.cpp | 48 +++++++++++++++++++++++++++++++++++++++++ src/line.h | 8 +++++++ src/mapgen.cpp | 54 +++++++++++++++++----------------------------- src/mapgendata.cpp | 32 +++++++++++++++++++++++++++ src/mapgendata.h | 1 + 6 files changed, 111 insertions(+), 34 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 97cacc08a0c0c..29fbcf76b9349 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -3763,6 +3763,8 @@ void game::mon_info_update( ) case direction::BELOWSOUTHEAST: index = 3; break; + case direction::last: + cata_fatal( "invalid direction" ); } } diff --git a/src/line.cpp b/src/line.cpp index 10192bc934367..dc673a767e319 100644 --- a/src/line.cpp +++ b/src/line.cpp @@ -383,6 +383,52 @@ std::vector continue_line( const std::vector &line, const in return line_to( line.back(), move_along_line( line.back(), line, distance ) ); } +namespace io +{ + +template<> +std::string enum_to_string( direction data ) +{ + switch( data ) { + // *INDENT-OFF* + case direction::ABOVENORTHWEST: return "above_north_west"; + case direction::NORTHWEST: return "north_west"; + case direction::BELOWNORTHWEST: return "below_north_west"; + case direction::ABOVENORTH: return "above_north"; + case direction::NORTH: return "north"; + case direction::BELOWNORTH: return "below_north"; + case direction::ABOVENORTHEAST: return "above_north_east"; + case direction::NORTHEAST: return "north_east"; + case direction::BELOWNORTHEAST: return "below_north_east"; + + case direction::ABOVEWEST: return "above_west"; + case direction::WEST: return "west"; + case direction::BELOWWEST: return "below_west"; + case direction::ABOVECENTER: return "above"; + case direction::CENTER: return "center"; + case direction::BELOWCENTER: return "below"; + case direction::ABOVEEAST: return "above_east"; + case direction::EAST: return "east"; + case direction::BELOWEAST: return "below_east"; + + case direction::ABOVESOUTHWEST: return "above_south_west"; + case direction::SOUTHWEST: return "south_west"; + case direction::BELOWSOUTHWEST: return "below_south_west"; + case direction::ABOVESOUTH: return "above_south"; + case direction::SOUTH: return "south"; + case direction::BELOWSOUTH: return "below_south"; + case direction::ABOVESOUTHEAST: return "above_south_east"; + case direction::SOUTHEAST: return "south_east"; + case direction::BELOWSOUTHEAST: return "below_south_east"; + // *INDENT-ON* + case direction::last: + break; + } + cata_fatal( "Invalid direction" ); +} + +} // namespace io + direction direction_from( const point &p ) noexcept { return static_cast( make_xyz( tripoint( p, 0 ) ) ); @@ -442,6 +488,8 @@ point direction_XY( const direction dir ) case direction::ABOVESOUTHEAST: case direction::BELOWSOUTHEAST: return point_south_east; + case direction::last: + cata_fatal( "Invalid direction" ); } return point_zero; diff --git a/src/line.h b/src/line.h index 7414d482e39e7..46afadd0f290b 100644 --- a/src/line.h +++ b/src/line.h @@ -11,6 +11,7 @@ #include "point.h" #include "units_fwd.h" +template struct enum_traits; struct rl_vec2d; extern bool trigdist; @@ -68,6 +69,13 @@ enum class direction : unsigned { ABOVESOUTHEAST = make_xyz_unit( tripoint_above + tripoint_south_east ), SOUTHEAST = make_xyz_unit( tripoint_south_east ), BELOWSOUTHEAST = make_xyz_unit( tripoint_below + tripoint_south_east ), + + last = 27 +}; + +template<> +struct enum_traits { + static constexpr direction last = direction::last; }; template< class T > diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 4662c371fa239..61ebd15524046 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -15,6 +15,7 @@ #include #include +#include "all_enum_values.h" #include "calendar.h" #include "cata_assert.h" #include "catacharset.h" @@ -2690,53 +2691,38 @@ class jmapgen_nested : public jmapgen_piece class neighborhood_check { private: - // To speed up the most common case: no checks - bool has_any = false; - std::array, om_direction::size> neighbors; - std::set above; + std::unordered_map> neighbors; public: explicit neighborhood_check( const JsonObject &jsi ) { - for( om_direction::type dir : om_direction::all ) { - int index = static_cast( dir ); - neighbors[index] = jsi.get_tags( om_direction::id( dir ) ); - has_any |= !neighbors[index].empty(); - - above = jsi.get_tags( "above" ); - has_any |= !above.empty(); + for( direction dir : all_enum_values() ) { + cata::flat_set dir_neighbours = + jsi.get_tags>( + io::enum_to_string( dir ) ); + if( !dir_neighbours.empty() ) { + neighbors[dir] = std::move( dir_neighbours ); + } } } bool test( const mapgendata &dat ) const { - if( !has_any ) { - return true; - } + for( const std::pair> &p : + neighbors ) { + const direction dir = p.first; + const cata::flat_set &allowed_neighbors = p.second; - bool all_directions_match = true; - for( om_direction::type dir : om_direction::all ) { - int index = static_cast( dir ); - const std::set &allowed_neighbors = neighbors[index]; - - if( allowed_neighbors.empty() ) { - continue; // no constraints on this direction, skip. - } + cata_assert( !allowed_neighbors.empty() ); bool this_direction_matches = false; for( const oter_str_id &allowed_neighbor : allowed_neighbors ) { - this_direction_matches |= is_ot_match( allowed_neighbor.str(), dat.neighbor_at( dir ).id(), - ot_match_type::contains ); + this_direction_matches |= + is_ot_match( allowed_neighbor.str(), dat.neighbor_at( dir ).id(), + ot_match_type::contains ); } - all_directions_match &= this_direction_matches; - } - - if( !above.empty() ) { - bool above_matches = false; - for( const oter_str_id &allowed_neighbor : above ) { - above_matches |= is_ot_match( allowed_neighbor.str(), dat.above().id(), ot_match_type::contains ); + if( !this_direction_matches ) { + return false; } - all_directions_match &= above_matches; } - - return all_directions_match; + return true; } }; diff --git a/src/mapgendata.cpp b/src/mapgendata.cpp index c8a39ea3f47df..b8e0a20dd9f0b 100644 --- a/src/mapgendata.cpp +++ b/src/mapgendata.cpp @@ -207,3 +207,35 @@ const oter_id &mapgendata::neighbor_at( om_direction::type dir ) const debugmsg( "Tried to get neighbor from invalid direction %d", dir ); return north(); } + +const oter_id &mapgendata::neighbor_at( direction dir ) const +{ + // TODO: De-uglify, implement proper conversion somewhere + switch( dir ) { + case direction::NORTH: + return north(); + case direction::EAST: + return east(); + case direction::SOUTH: + return south(); + case direction::WEST: + return west(); + case direction::NORTHEAST: + return neast(); + case direction::SOUTHEAST: + return seast(); + case direction::SOUTHWEST: + return swest(); + case direction::NORTHWEST: + return nwest(); + case direction::ABOVECENTER: + return above(); + case direction::BELOWCENTER: + return below(); + default: + break; + } + + debugmsg( "Neighbor not supported for direction %d", io::enum_to_string( dir ) ); + return north(); +} diff --git a/src/mapgendata.h b/src/mapgendata.h index 20475afa23fc7..55df51f4716b2 100644 --- a/src/mapgendata.h +++ b/src/mapgendata.h @@ -169,6 +169,7 @@ class mapgendata return t_below; } const oter_id &neighbor_at( om_direction::type dir ) const; + const oter_id &neighbor_at( direction ) const; void fill_groundcover() const; void square_groundcover( const point &p1, const point &p2 ) const; ter_id groundcover() const;