32 #include <boost/functional/hash_fwd.hpp>
35 #define ERR_CF LOG_STREAM(err, log_config)
41 std::ostream &
operator<<(std::ostream &
s,
const std::vector<map_location>& v) {
42 std::vector<map_location>::const_iterator
i = v.begin();
43 for(;
i!= v.end(); ++
i) {
44 s <<
"(" << *
i <<
") ";
61 std::hash<std::size_t>
h;
62 return h( (
static_cast<uint32_t
>(
a.x) << 16) ^
static_cast<uint32_t
>(
a.y) );
77 const std::size_t open = str.find_first_of(
'('), close = str.find_last_of(
')');
78 if (open != std::string::npos && close != std::string::npos) {
79 std::string sub = str.substr(open + 1, close - open - 1);
86 const std::size_t
start = str[0] ==
'-' ? 1 : 0;
87 const std::size_t end = str.find_first_of(
':');
88 const std::string& main_dir = str.substr(
start, end -
start);
91 if (main_dir ==
"n") {
93 }
else if (main_dir ==
"ne") {
95 }
else if (main_dir ==
"se") {
97 }
else if (main_dir ==
"s") {
99 }
else if (main_dir ==
"sw") {
101 }
else if (main_dir ==
"nw") {
111 if (end != std::string::npos) {
112 const std::string rel_dir = str.substr(end + 1);
113 if (rel_dir ==
"cw") {
115 }
else if (rel_dir ==
"ccw") {
128 std::vector<map_location::DIRECTION> to_return;
130 std::vector<std::string>::const_iterator
i, i_end=dir_strs.end();
131 for(
i = dir_strs.begin();
i != i_end; ++
i) {
135 to_return.push_back(temp);
145 return std::string(
"n");
147 return std::string(
"ne");
149 return std::string(
"nw");
151 return std::string(
"s");
153 return std::string(
"se");
155 return std::string(
"sw");
157 return std::string();
168 return _(
"North East");
170 return _(
"North West");
174 return _(
"South East");
176 return _(
"South West");
178 return std::string();
187 std::string xs = cfg[
"x"], ys = cfg[
"y"];
195 if(xs.empty() ==
false && xs !=
"recall") {
197 x = std::stoi(xs) - 1;
198 }
catch(
const std::invalid_argument&) {
199 ERR_CF <<
"Invalid map coordinate: " << xs;
203 if(ys.empty() ==
false && ys !=
"recall") {\
205 y = std::stoi(ys) - 1;
206 }
catch(
const std::invalid_argument&) {
207 ERR_CF <<
"Invalid map coordinate: " << ys;
234 if (loc.
x%2==0 &&
x%2==1) dy--;
238 int dist = std::abs(dx);
239 int dist_diag_SW_NE = std::abs(dy + (dx + (dy>0?0:1) )/2);
240 int dist_diag_SE_NW = std::abs(dy - (dx - (dy>0?0:1) )/2);
242 if (dy > 0) dir =
SOUTH;
245 if (dist_diag_SE_NW < dist) {
248 dist = dist_diag_SE_NW;
250 if (dist_diag_SW_NE < dist) {
278 }
else if (temp.
x >
x) {
280 }
else if (temp.
x <
x) {
290 std::pair<int, int> ret;
302 assert(temp == *
this);
323 if(xlocs.size() == 0 && ylocs.size() == 0) {
331 if(xlocs.size() != ylocs.size() && xlocs.size() && ylocs.size()) {
332 ERR_CF <<
"Different size lists when pairing coordinate ranges: " << xloc <<
" vs " << yloc;
336 for(;
i < xlocs.size() &&
i < ylocs.size(); ++
i) {
340 if(xr.first <=
x+1 &&
x+1 <= xr.second
341 && yr.first <=
y+1 &&
y+1 <= yr.second) {
345 for(;
i < xlocs.size(); ++
i) {
347 if(xr.first <=
x+1 &&
x+1 <= xr.second) {
351 for(;
i < ylocs.size(); ++
i) {
353 if(yr.first <=
y+1 &&
y+1 <= yr.second) {
374 int x_factor = (
static_cast<unsigned int> (dir) <= 2u) ? 1 : -1;
376 unsigned int tmp_y = dir - 2;
377 int y_factor = (tmp_y <= 2u) ? 1 : -1;
380 return map_location(
x + x_factor *
n,
y + y_factor * ((
n + ((
x & 1) == 1)) / 2));
382 return map_location(
x + x_factor *
n,
y + y_factor * ((
n + ((
x & 1) == 0)) / 2));
410 std::stringstream x, y;
411 std::set<map_location>::const_iterator
419 for(++
i;
i != locs.end(); ++
i) {
420 if(
i->wml_x() != first->wml_x() ||
i->wml_y() - 1 != last->wml_y()) {
421 if (last->wml_y() != first->wml_y()) {
422 y <<
"-" << (last->wml_y());
424 x <<
"," << (
i->wml_x());
425 y <<
"," << (
i->wml_y());
431 if(last->wml_y() != first->wml_y())
432 y <<
"-" << (last->wml_y());
445 const std::vector<std::string> xvals =
utils::split(cfg[
"x"]);
446 const std::vector<std::string> yvals =
utils::split(cfg[
"y"]);
448 if (xvals.size() != yvals.size()) {
449 throw std::invalid_argument(
"Number of x and y coordinates do not match.");
452 std::transform(xvals.begin(), xvals.end(), yvals.begin(), std::back_inserter(locs), &
read_locations_helper);
457 std::stringstream x, y;
459 std::vector<map_location>::const_iterator
i = locs.begin(),
462 for(;
i != end; ++
i) {
481 res->
y =
a.y - (((
a.x & 1) == 0) ? 1 : 0);
484 res->
y =
a.y + (((
a.x & 1) == 1) ? 1 : 0);
490 res->
y =
a.y + (((
a.x & 1) == 1) ? 1 : 0);
493 res->
y =
a.y - (((
a.x & 1) == 0) ? 1 : 0);
498 std::array<map_location, 6> res;
516 return (
a.x & 1) == 0;
526 return (
b.x & 1) == 0;
533 return ((
a.x -
b.x) == 1) || ((
a.x -
b.x) == - 1);
548 const std::size_t hdistance = std::abs(
a.x -
b.x);
550 const std::size_t vpenalty = ( (((
a.x & 1)==0) && ((
b.x & 1)==1) && (
a.y <
b.y))
551 || (((
b.x & 1)==0) && ((
a.x & 1)==1) && (
b.y <
a.y)) ) ? 1 : 0;
563 return std::max<int>(hdistance, std::abs(
a.y -
b.y) + vpenalty + hdistance/2);
A config object defines a single node in a WML file, with access to child nodes.
static std::string _(const char *str)
std::size_t hash_value(const map_location &a)
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
static bool is_vertically_higher_than(const map_location &m1, const map_location &m2)
static map_location read_locations_helper(const std::string &xi, const std::string &yi)
std::size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
void write_locations(const std::vector< map_location > &locs, config &cfg)
Write a vector of locations into a config adding keys x=x1,x2,..,xn and y=y1,y2,.....
std::ostream & operator<<(std::ostream &s, const map_location &l)
Dumps a position on a stream, for debug purposes.
void read_locations(const config &cfg, std::vector< map_location > &locs)
Parse x,y keys of a config into a vector of locations.
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
void write_location_range(const std::set< map_location > &locs, config &cfg)
Write a set of locations into a config using ranges, adding keys x=x1,..,xn and y=y1a-y1b,...
static lg::log_domain log_config("config")
Standard logging facilities (interface).
General math utility functions.
constexpr bool is_even(T num)
constexpr bool is_odd(T num)
EXIT_STATUS start(const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
Function which will interpolate variables, starting with '$' in the string 'str' with the equivalent ...
std::pair< int, int > parse_range(const std::string &str)
std::vector< std::string > split(const config_attribute_value &val)
Encapsulates the map of the game.
map_location & vector_difference_assign(const map_location &a)
static DIRECTION parse_direction(const std::string &str)
static const std::vector< DIRECTION > & default_dirs()
Default list of directions.
std::pair< int, int > get_in_basis_N_NE() const
DIRECTION
Valid directions which can be moved in our hexagonal world.
map_location get_direction(DIRECTION dir, unsigned int n=1u) const
static std::vector< DIRECTION > parse_directions(const std::string &str)
Parse_directions takes a comma-separated list, and filters out any invalid directions.
DIRECTION get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
map_location rotate_right_around_center(const map_location ¢er, int k) const
static DIRECTION rotate_right(DIRECTION d, unsigned int k=1u)
static const map_location & null_location()
static std::string write_translated_direction(DIRECTION dir)
void write(config &cfg) const
bool matches_range(const std::string &xloc, const std::string &yloc) const
static DIRECTION get_opposite_dir(DIRECTION d)
static std::string write_direction(DIRECTION dir)
static map_location::DIRECTION n
static map_location::DIRECTION s