34 #define ERR_CF LOG_STREAM(err, log_config)
40 std::ostream &
operator<<(std::ostream &
s,
const std::vector<map_location>& v) {
41 std::vector<map_location>::const_iterator
i = v.begin();
42 for(;
i!= v.end(); ++
i) {
43 s <<
"(" << *
i <<
") ";
60 std::hash<std::size_t>
h;
61 return h( (
static_cast<uint32_t
>(
a.x) << 16) ^
static_cast<uint32_t
>(
a.y) );
76 const std::size_t open = str.find_first_of(
'('), close = str.find_last_of(
')');
77 if (open != std::string::npos && close != std::string::npos) {
78 std::string sub = str.substr(open + 1, close - open - 1);
85 const std::size_t
start = str[0] ==
'-' ? 1 : 0;
86 const std::size_t end = str.find_first_of(
':');
87 const std::string& main_dir = str.substr(
start, end -
start);
90 if (main_dir ==
"n") {
92 }
else if (main_dir ==
"ne") {
94 }
else if (main_dir ==
"se") {
96 }
else if (main_dir ==
"s") {
98 }
else if (main_dir ==
"sw") {
100 }
else if (main_dir ==
"nw") {
110 if (end != std::string::npos) {
111 const std::string rel_dir = str.substr(end + 1);
112 if (rel_dir ==
"cw") {
114 }
else if (rel_dir ==
"ccw") {
127 std::vector<map_location::DIRECTION> to_return;
129 std::vector<std::string>::const_iterator
i, i_end=dir_strs.end();
130 for(
i = dir_strs.begin();
i != i_end; ++
i) {
134 to_return.push_back(temp);
144 return std::string(
"n");
146 return std::string(
"ne");
148 return std::string(
"nw");
150 return std::string(
"s");
152 return std::string(
"se");
154 return std::string(
"sw");
156 return std::string();
167 return _(
"North East");
169 return _(
"North West");
173 return _(
"South East");
175 return _(
"South West");
177 return std::string();
186 std::string xs = cfg[
"x"], ys = cfg[
"y"];
194 if(xs.empty() ==
false && xs !=
"recall") {
196 x = std::stoi(xs) - 1;
197 }
catch(
const std::invalid_argument&) {
198 ERR_CF <<
"Invalid map coordinate: " << xs;
202 if(ys.empty() ==
false && ys !=
"recall") {\
204 y = std::stoi(ys) - 1;
205 }
catch(
const std::invalid_argument&) {
206 ERR_CF <<
"Invalid map coordinate: " << ys;
233 if (loc.
x%2==0 &&
x%2==1) dy--;
237 int dist = std::abs(dx);
238 int dist_diag_SW_NE = std::abs(dy + (dx + (dy>0?0:1) )/2);
239 int dist_diag_SE_NW = std::abs(dy - (dx - (dy>0?0:1) )/2);
241 if (dy > 0) dir =
SOUTH;
244 if (dist_diag_SE_NW < dist) {
247 dist = dist_diag_SE_NW;
249 if (dist_diag_SW_NE < dist) {
277 }
else if (temp.
x >
x) {
279 }
else if (temp.
x <
x) {
289 std::pair<int, int> ret;
301 assert(temp == *
this);
322 if(xlocs.size() == 0 && ylocs.size() == 0) {
330 if(xlocs.size() != ylocs.size() && xlocs.size() && ylocs.size()) {
331 ERR_CF <<
"Different size lists when pairing coordinate ranges: " << xloc <<
" vs " << yloc;
335 for(;
i < xlocs.size() &&
i < ylocs.size(); ++
i) {
339 if(xr.first <=
x+1 &&
x+1 <= xr.second
340 && yr.first <=
y+1 &&
y+1 <= yr.second) {
344 for(;
i < xlocs.size(); ++
i) {
346 if(xr.first <=
x+1 &&
x+1 <= xr.second) {
350 for(;
i < ylocs.size(); ++
i) {
352 if(yr.first <=
y+1 &&
y+1 <= yr.second) {
373 int x_factor = (
static_cast<unsigned int> (dir) <= 2u) ? 1 : -1;
375 unsigned int tmp_y = dir - 2;
376 int y_factor = (tmp_y <= 2u) ? 1 : -1;
379 return map_location(
x + x_factor *
n,
y + y_factor * ((
n + ((
x & 1) == 1)) / 2));
381 return map_location(
x + x_factor *
n,
y + y_factor * ((
n + ((
x & 1) == 0)) / 2));
409 std::stringstream x, y;
410 std::set<map_location>::const_iterator
418 for(++
i;
i != locs.end(); ++
i) {
419 if(
i->wml_x() != first->wml_x() ||
i->wml_y() - 1 != last->wml_y()) {
420 if (last->wml_y() != first->wml_y()) {
421 y <<
"-" << (last->wml_y());
423 x <<
"," << (
i->wml_x());
424 y <<
"," << (
i->wml_y());
430 if(last->wml_y() != first->wml_y())
431 y <<
"-" << (last->wml_y());
444 const std::vector<std::string> xvals =
utils::split(cfg[
"x"]);
445 const std::vector<std::string> yvals =
utils::split(cfg[
"y"]);
447 if (xvals.size() != yvals.size()) {
448 throw std::invalid_argument(
"Number of x and y coordinates do not match.");
451 std::transform(xvals.begin(), xvals.end(), yvals.begin(), std::back_inserter(locs), &
read_locations_helper);
456 std::stringstream x, y;
458 std::vector<map_location>::const_iterator
i = locs.begin(),
461 for(;
i != end; ++
i) {
480 res->
y =
a.y - (((
a.x & 1) == 0) ? 1 : 0);
483 res->
y =
a.y + (((
a.x & 1) == 1) ? 1 : 0);
489 res->
y =
a.y + (((
a.x & 1) == 1) ? 1 : 0);
492 res->
y =
a.y - (((
a.x & 1) == 0) ? 1 : 0);
497 std::array<map_location, 6> res;
515 return (
a.x & 1) == 0;
525 return (
b.x & 1) == 0;
532 return ((
a.x -
b.x) == 1) || ((
a.x -
b.x) == - 1);
547 const std::size_t hdistance = std::abs(
a.x -
b.x);
549 const std::size_t vpenalty = ( (((
a.x & 1)==0) && ((
b.x & 1)==1) && (
a.y <
b.y))
550 || (((
b.x & 1)==0) && ((
a.x & 1)==1) && (
b.y <
a.y)) ) ? 1 : 0;
562 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(bool clear_id, 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)
Recognises the following patterns, and returns a {min, max} pair.
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