Skip to content

Commit

Permalink
Support more neighbours in jmapgen_nested
Browse files Browse the repository at this point in the history
Previously only the cardinal directions and above were supported; now
all eight horizontal neighbours, above, and below are.
  • Loading branch information
jbytheway committed Sep 22, 2021
1 parent 4f8529e commit f12a7e7
Showing 6 changed files with 111 additions and 34 deletions.
2 changes: 2 additions & 0 deletions src/game.cpp
Original file line number Diff line number Diff line change
@@ -3763,6 +3763,8 @@ void game::mon_info_update( )
case direction::BELOWSOUTHEAST:
index = 3;
break;
case direction::last:
cata_fatal( "invalid direction" );
}
}

48 changes: 48 additions & 0 deletions src/line.cpp
Original file line number Diff line number Diff line change
@@ -383,6 +383,52 @@ std::vector<tripoint> continue_line( const std::vector<tripoint> &line, const in
return line_to( line.back(), move_along_line( line.back(), line, distance ) );
}

namespace io
{

template<>
std::string enum_to_string<direction>( 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<direction>( 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;
8 changes: 8 additions & 0 deletions src/line.h
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
#include "point.h"
#include "units_fwd.h"

template <typename T> 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<direction> {
static constexpr direction last = direction::last;
};

template< class T >
54 changes: 20 additions & 34 deletions src/mapgen.cpp
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
#include <type_traits>
#include <unordered_map>

#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<std::set<oter_str_id>, om_direction::size> neighbors;
std::set<oter_str_id> above;
std::unordered_map<direction, cata::flat_set<oter_str_id>> neighbors;
public:
explicit neighborhood_check( const JsonObject &jsi ) {
for( om_direction::type dir : om_direction::all ) {
int index = static_cast<int>( dir );
neighbors[index] = jsi.get_tags<oter_str_id>( om_direction::id( dir ) );
has_any |= !neighbors[index].empty();

above = jsi.get_tags<oter_str_id>( "above" );
has_any |= !above.empty();
for( direction dir : all_enum_values<direction>() ) {
cata::flat_set<oter_str_id> dir_neighbours =
jsi.get_tags<oter_str_id, cata::flat_set<oter_str_id>>(
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<const direction, cata::flat_set<oter_str_id>> &p :
neighbors ) {
const direction dir = p.first;
const cata::flat_set<oter_str_id> &allowed_neighbors = p.second;

bool all_directions_match = true;
for( om_direction::type dir : om_direction::all ) {
int index = static_cast<int>( dir );
const std::set<oter_str_id> &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;
}
};

32 changes: 32 additions & 0 deletions src/mapgendata.cpp
Original file line number Diff line number Diff line change
@@ -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();
}
1 change: 1 addition & 0 deletions src/mapgendata.h
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit f12a7e7

Please sign in to comment.