The Battle for Wesnoth  1.15.11+dev
location.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 class config;
18 class variable_set;
19 
20 #include <array>
21 #include <set>
22 #include <string>
23 #include <tuple>
24 #include <vector>
25 #include <utility>
26 
27 struct wml_loc {};
28 
29 /**
30  * Encapsulates the map of the game.
31  *
32  * Although the game is hexagonal, the map is stored as a grid.
33  * Each type of terrain is represented by a multiletter terrain code.
34  * @todo Update for new map-format.
35  */
36 /** Represents a location on the map. */
37 struct map_location {
38  /** Valid directions which can be moved in our hexagonal world. */
39  enum DIRECTION { NORTH=0, NORTH_EAST=1, SOUTH_EAST=2, SOUTH=3,
40  SOUTH_WEST=4, NORTH_WEST=5, NDIRECTIONS=6 };
41 
42  static const std::vector<DIRECTION> & default_dirs();
43 
44  static DIRECTION rotate_right(DIRECTION d, unsigned int k = 1u)
45  {
46  return (d == map_location::NDIRECTIONS) ? map_location::NDIRECTIONS : static_cast<map_location::DIRECTION>((d + (k%6u)) % 6u);
47  }
48 
49  static DIRECTION rotate_right(DIRECTION d, signed int k)
50  {
51  return (k>=0) ? rotate_right(d, static_cast<unsigned int> (k)) : rotate_right(d, (static_cast<unsigned int>(-k) % 6u) * 5u);
52  }
53 
55  {
56  return rotate_right(d,3u);
57  }
58 
59  static DIRECTION parse_direction(const std::string& str);
60 
61  /**
62  * Parse_directions takes a comma-separated list, and filters out any
63  * invalid directions
64  */
65  static std::vector<DIRECTION> parse_directions(const std::string& str);
66  static std::string write_direction(DIRECTION dir);
67  static std::string write_translated_direction(DIRECTION dir);
68 
69  map_location() : x(-1000), y(-1000) {}
70  map_location(int x, int y) : x(x), y(y) {}
71  map_location(int x, int y, wml_loc) : x(x - 1), y(y - 1) {}
72  map_location(const config& cfg, const variable_set *variables = nullptr);
73 
74  static const map_location & ZERO()
75  {
76  static const map_location z(0,0);
77  return z;
78  }
79 
80  static const map_location & null_location()
81  {
82  static const map_location l;
83  return l;
84  }
85 
86  void write(config& cfg) const;
87 
88  bool valid() const { return x >= 0 && y >= 0; }
89 
90  bool valid(const int parWidth, const int parHeight) const
91  { return ((x >= 0) && (y >= 0) && (x < parWidth) && (y < parHeight)); }
92 
93  bool valid(const int parWidth, const int parHeight, const int border) const
94  { return ((x + border >= 0) && (y + border >= 0) && (x < parWidth + border) && (y < parHeight + border)); }
95 
96  bool matches_range(const std::string& xloc, const std::string& yloc) const;
97 
98  // Inlining those for performance reasons
99  bool operator<(const map_location& a) const { return std::tie(x, y) < std::tie(a.x, a.y); }
100  bool operator==(const map_location& a) const { return x == a.x && y == a.y; }
101  bool operator!=(const map_location& a) const { return !operator==(a); }
102 
103  /** three-way comparator */
104  int do_compare(const map_location& a) const {return x == a.x ? y - a.y : x - a.x; }
105 
106  // Location arithmetic operations treating the locations as vectors in
107  // a hex-based space. These operations form an abelian group, i.e.
108  // everything works as you would expect addition and subtraction to
109  // work, with associativity and commutativity.
111  {
112  return map_location(-x, -y - (x & 1)); //subtract one if we're on an odd x coordinate
113  }
114 
116  {
117  return map_location(*this).vector_sum_assign(a);
118  }
119 
121  {
122  y += ((x & 1) && (a.x & 1)); //add one if both x coords are odd
123  x += a.x;
124  y += a.y;
125  return *this;
126  }
127 
129  {
130  return vector_sum_assign(a.vector_negation());
131  }
132 
133  // Do n step in the direction d
134  map_location get_direction(DIRECTION dir, unsigned int n = 1u) const;
135  map_location get_direction(DIRECTION dir, signed int n) const
136  {
137  return (n >= 0) ? get_direction(dir, static_cast<unsigned int> (n)) : get_direction(get_opposite_dir(dir), static_cast<unsigned int> (-n));
138  }
139 
140  enum RELATIVE_DIR_MODE { DEFAULT , RADIAL_SYMMETRY };
141  DIRECTION get_relative_dir(const map_location & loc, map_location::RELATIVE_DIR_MODE mode /*= map_location::RADIAL_SYMMETRY*/ ) const;
142  DIRECTION get_relative_dir(const map_location & loc) const; //moved the default setting to .cpp file for ease of testing
143 
144  // Express as a vector in the basis N, NE. N, and NE may be obtained by zero.get_direction(NORTH), ...(NORTH_EAST), respectively.
145  std::pair<int,int> get_in_basis_N_NE() const;
146 
147  // Rotates the map_location clockwise in 60 degree increments around a center point. Negative numbers of steps are permitted.
148  map_location rotate_right_around_center(const map_location & center, int k) const;
149 
150  friend std::size_t hash_value(const map_location& a);
151 
152  int wml_x() const { return x + 1; }
153  int wml_y() const { return y + 1; }
154 
155  void set_wml_x(int v) { x = v - 1; }
156  void set_wml_y(int v) { y = v - 1; }
157  //on purpose these functions don't take map_location objects, if you use map_location objects to store 'differences' between 2 locations use vector_sum().
158  void add(int x_diff, int y_diff) { x += x_diff; y += y_diff; }
159  map_location plus(int x_diff, int y_diff) const { return map_location(x + x_diff, y + y_diff); }
160 
161 
162  int x, y;
163 };
164 
165 /** Function which tells if two locations are adjacent. */
166 bool tiles_adjacent(const map_location& a, const map_location& b);
167 
168 /**
169  * Function which, given a location, will place all adjacent locations in res.
170  * res must point to an array of 6 location objects.
171  */
172 void get_adjacent_tiles(const map_location& a, map_location* res);
173 
174 /** Returns an array of the six hexes adjacent to @p center. */
175 std::array<map_location, 6> get_adjacent_tiles(const map_location& center);
176 
177 /**
178  * Function which gives the number of hexes between two tiles
179  * (i.e. the minimum number of hexes that have to be traversed
180  * to get from one hex to the other).
181  */
182 std::size_t distance_between(const map_location& a, const map_location& b);
183 
184 /**
185  * Write a set of locations into a config using ranges,
186  * adding keys x=x1,..,xn and y=y1a-y1b,..,yna-ynb
187  */
188 void write_location_range(const std::set<map_location>& locs, config& cfg);
189 
190 /**
191  * Parse x,y keys of a config into a vector of locations
192  *
193  * Throws bad_lexical_cast if it fails to parse.
194  */
195 void read_locations(const config& cfg, std::vector<map_location>& locs);
196 
197 /** Write a vector of locations into a config
198  * adding keys x=x1,x2,..,xn and y=y1,y2,..,yn */
199 void write_locations(const std::vector<map_location>& locs, config& cfg);
200 
201 /** Dumps a position on a stream, for debug purposes. */
202 std::ostream &operator<<(std::ostream &s, const map_location& l);
203 /** Dumps a vector of positions on a stream, for debug purposes. */
204 std::ostream &operator<<(std::ostream &s, const std::vector<map_location>& v);
205 
206 namespace std {
207 template<>
208 struct hash<map_location> {
209  std::size_t operator()(const map_location& l) const noexcept {
210  // The 2000 bias supposedly ensures that the correct x is recovered for negative y
211  // This implementation copied from the Lua location_set
212  return (l.wml_x()) * 16384 + (l.wml_y()) + 2000;
213  }
214 };
215 }
void set_wml_y(int v)
Definition: location.hpp:156
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,..,yna-ynb.
Definition: location.cpp:398
map_location(int x, int y)
Definition: location.hpp:70
map_location & vector_sum_assign(const map_location &a)
Definition: location.hpp:120
std::ostream & operator<<(std::ostream &s, const map_location &l)
Dumps a position on a stream, for debug purposes.
Definition: location.cpp:36
map_location & vector_difference_assign(const map_location &a)
Definition: location.hpp:128
map_location(int x, int y, wml_loc)
Definition: location.hpp:71
static const map_location & ZERO()
Definition: location.hpp:74
#define a
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.cpp:474
int do_compare(const map_location &a) const
three-way comparator
Definition: location.hpp:104
int wml_x() const
Definition: location.hpp:152
void set_wml_x(int v)
Definition: location.hpp:155
STL namespace.
bool valid(const int parWidth, const int parHeight, const int border) const
Definition: location.hpp:93
map_location vector_negation() const
Definition: location.hpp:110
static DIRECTION rotate_right(DIRECTION d, unsigned int k=1u)
Definition: location.hpp:44
#define d
#define b
void write(std::ostream &out, const configr_of &cfg, unsigned int level)
Definition: parser.cpp:763
std::size_t operator()(const map_location &l) const noexcept
Definition: location.hpp:209
map_location plus(int x_diff, int y_diff) const
Definition: location.hpp:159
void add(int x_diff, int y_diff)
Definition: location.hpp:158
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Definition: location.cpp:502
bool operator!=(const map_location &a) const
Definition: location.hpp:101
int wml_y() const
Definition: location.hpp:153
bool valid() const
Definition: location.hpp:88
bool operator==(const map_location &a) const
Definition: location.hpp:100
static const std::string & get_direction(std::size_t n)
Definition: display.cpp:959
static DIRECTION rotate_right(DIRECTION d, signed int k)
Definition: location.hpp:49
Encapsulates the map of the game.
Definition: location.hpp:37
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.
Definition: location.cpp:545
bool operator<(const map_location &a) const
Definition: location.hpp:99
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,..,yn.
Definition: location.cpp:454
map_location vector_sum(const map_location &a) const
Definition: location.hpp:115
std::size_t hash_value(const map_location &a)
Definition: location.cpp:59
bool operator==(const config &a, const config &b)
Definition: config.cpp:1450
static map_location::DIRECTION s
DIRECTION
Valid directions which can be moved in our hexagonal world.
Definition: location.hpp:39
static DIRECTION get_opposite_dir(DIRECTION d)
Definition: location.hpp:54
static const map_location & null_location()
Definition: location.hpp:80
bool valid(const int parWidth, const int parHeight) const
Definition: location.hpp:90
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
map_location get_direction(DIRECTION dir, signed int n) const
Definition: location.hpp:135
static map_location::DIRECTION n
void read_locations(const config &cfg, std::vector< map_location > &locs)
Parse x,y keys of a config into a vector of locations.
Definition: location.cpp:442