The Battle for Wesnoth  1.17.10+dev
test_map_location.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2022
3  by Chris Beck <render787@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-test"
17 
18 #include <functional>
19 #include <boost/test/unit_test.hpp>
20 
21 #include "map/location.hpp"
22 
23 static std::vector<map_location> preset_locs;
31 
32 
33 struct MLFixture
34 {
36  {
37  va = map_location(3,4);
38  vb = map_location(10,8);
39  vc = map_location(0,9);
40  vz = map_location::ZERO();
41  vt1 = va.vector_negation();
42  vt2 = vb.vector_sum(vc);
43  vt3 = va.vector_sum(vc.vector_negation());
44 
45  vs1 = vz.get_direction(nw);
46  vs2 = vz.get_direction(n).get_direction(ne);
47  vs3 = vz.get_direction(s).get_direction(se);
48  vs4 = vz.get_direction(sw).get_direction(se);
49 
50  preset_locs.push_back(va);
51  preset_locs.push_back(vb);
52  preset_locs.push_back(vc);
53  preset_locs.push_back(vz);
54  preset_locs.push_back(vt1);
55  preset_locs.push_back(vt2);
56  preset_locs.push_back(vt3);
57  preset_locs.push_back(vs1);
58  preset_locs.push_back(vs2);
59  preset_locs.push_back(vs3);
60  preset_locs.push_back(vs4);
61  }
62 
64 };
65 
66 BOOST_FIXTURE_TEST_SUITE ( test_map_location, MLFixture );
67 
68 //#define MAP_LOCATION_GET_OUTPUT
69 
70 #ifndef MAP_LOCATION_GET_OUTPUT
72 {
73  map_location ret(v1);
75  return ret;
76 }
77 #endif
78 
79 static void characterization_distance_direction (const std::vector<map_location> & locs, const std::vector<map_location::DIRECTION> & dir_answers, const std::vector<std::size_t> & int_answers, map_location::RELATIVE_DIR_MODE mode)
80 {
81  BOOST_CHECK_EQUAL(dir_answers.size(), int_answers.size());
82 
83  std::vector<map_location::DIRECTION>::const_iterator dir_it = dir_answers.begin();
84  std::vector<std::size_t>::const_iterator int_it = int_answers.begin();
85 
86  for (std::vector<map_location>::const_iterator it_a = locs.begin(); it_a != locs.end(); ++it_a) {
87  for (std::vector<map_location>::const_iterator it_b = it_a + 1; it_b != locs.end(); ++it_b) {
88  const map_location & a = *it_a;
89  const map_location & b = *it_b;
90 #ifdef MAP_LOCATION_GET_OUTPUT
91  std::cout << "(std::make_pair(" << distance_between(a,b) << ",\t\""
92  << map_location::write_direction( a.get_relative_dir(b,mode)) << "\"))" << std::endl;
93 #else
94  int expected_dist = *(int_it++);
95  map_location::DIRECTION expected_dir = *(dir_it++);
96  BOOST_CHECK_EQUAL( expected_dist, distance_between(a,b) );
97  BOOST_CHECK_EQUAL( expected_dist, distance_between(b,a) );
98  BOOST_CHECK_EQUAL( expected_dir, a.get_relative_dir(b, mode) );
99  //Note: This is not a valid assertion. get_relative_dir has much symmetry but not radial.
100  if (mode == map_location::RADIAL_SYMMETRY) {
101  BOOST_CHECK_EQUAL( map_location::get_opposite_dir(expected_dir), b.get_relative_dir(a,mode) );
102  }
103  BOOST_CHECK_EQUAL( a.vector_sum(b), b.vector_sum(a));
104  map_location temp1 = a;
105  temp1.vector_difference_assign(b);
106  map_location temp2 = b;
107  temp2.vector_difference_assign(a);
108  BOOST_CHECK_EQUAL( temp1, temp2.vector_negation());
109  BOOST_CHECK_EQUAL( a, a.vector_negation().vector_negation());
110 
111  for (std::vector<map_location>::const_iterator it_c = it_b + 1; it_c != locs.end(); ++it_c) {
112  const map_location & c = *it_c;
113  BOOST_CHECK_EQUAL(a.vector_sum(b.vector_sum(c)) , a.vector_sum(b).vector_sum(c));
114  BOOST_CHECK_EQUAL(a.vector_sum(vector_difference(b,c)) , vector_difference(a.vector_sum(b),c));
115  BOOST_CHECK_EQUAL(vector_difference(a,b.vector_sum(c)) , vector_difference(vector_difference(a,b),c));
116  //TODO: Investigate why this doesn't work
117  if (mode == map_location::RADIAL_SYMMETRY) {
118  BOOST_CHECK_EQUAL(expected_dir, (a.vector_sum(c)).get_relative_dir(b.vector_sum(c),mode));
119  }
120  }
121 #endif
122  }
123  }
124 
125  BOOST_CHECK_MESSAGE( dir_it == dir_answers.end(), "Did not exhaust answers list.");
126  BOOST_CHECK_MESSAGE( int_it == int_answers.end(), "Did not exhaust answers list.");
127 }
128 
129 static std::size_t get_first (std::pair<std::size_t, std::string> arg) {return arg.first; }
130 static map_location::DIRECTION get_second (std::pair<std::size_t, std::string> arg) {return map_location::parse_direction(arg.second); }
131 
132 /* This has to be recomputed, I'm commenting out the test so that it doesn't fail in the meantime. --iceiceice
133 
134 BOOST_AUTO_TEST_CASE ( map_location_characterization_test_default_mode )
135 {
136  std::vector<std::pair<std::size_t, std::string>> generated_answers = boost::assign::list_of(std::make_pair(7, "se"))
137 (std::make_pair(6, "s"))
138 (std::make_pair(6, "nw"))
139 (std::make_pair(12, "n"))
140 (std::make_pair(16, "s"))
141 (std::make_pair(9, "n"))
142 (std::make_pair(7, "nw"))
143 (std::make_pair(7, "n"))
144 (std::make_pair(4, "n"))
145 (std::make_pair(5, "nw"))
146 (std::make_pair(10, "sw"))
147 (std::make_pair(13, "nw"))
148 (std::make_pair(19, "nw"))
149 (std::make_pair(9, "s"))
150 (std::make_pair(16, "n"))
151 (std::make_pair(14, "nw"))
152 (std::make_pair(14, "nw"))
153 (std::make_pair(11, "nw"))
154 (std::make_pair(12, "nw"))
155 (std::make_pair(9, "n"))
156 (std::make_pair(15, "n"))
157 (std::make_pair(13, "se"))
158 (std::make_pair(15, "n"))
159 (std::make_pair(10, "n"))
160 (std::make_pair(11, "n"))
161 (std::make_pair(8, "n"))
162 (std::make_pair(8, "n"))
163 (std::make_pair(6, "n"))
164 (std::make_pair(22, "s"))
165 (std::make_pair(6, "n"))
166 (std::make_pair(1, "nw"))
167 (std::make_pair(2, "n"))
168 (std::make_pair(2, "se"))
169 (std::make_pair(1, "s"))
170 (std::make_pair(28, "s"))
171 (std::make_pair(6, "se"))
172 (std::make_pair(5, "s"))
173 (std::make_pair(5, "se"))
174 (std::make_pair(8, "s"))
175 (std::make_pair(7, "s"))
176 (std::make_pair(25, "n"))
177 (std::make_pair(23, "n"))
178 (std::make_pair(23, "n"))
179 (std::make_pair(20, "n"))
180 (std::make_pair(21, "n"))
181 (std::make_pair(6, "sw"))
182 (std::make_pair(4, "s"))
183 (std::make_pair(7, "s"))
184 (std::make_pair(7, "s"))
185 (std::make_pair(2, "ne"))
186 (std::make_pair(3, "se"))
187 (std::make_pair(2, "s"))
188 (std::make_pair(3, "s"))
189 (std::make_pair(3, "s"))
190 (std::make_pair(1, "sw")).to_container(generated_answers);
191 
192  std::vector<std::size_t> ans1;
193  std::vector<map_location::DIRECTION> ans2;
194  std::transform(generated_answers.begin(), generated_answers.end(), back_inserter(ans1), &get_first);
195  std::transform(generated_answers.begin(), generated_answers.end(), back_inserter(ans2), &get_second);
196 
197  characterization_distance_direction(preset_locs, ans2, ans1, map_location::DEFAULT);
198 }*/
199 
200 BOOST_AUTO_TEST_CASE ( map_location_characterization_test_radial_mode )
201 {
202  std::vector<std::pair<std::size_t, std::string>> generated_answers {
203 std::make_pair(7, "se"),
204 std::make_pair(6, "sw"),
205 std::make_pair(6, "n"),
206 std::make_pair(12, "n"),
207 std::make_pair(16, "s"),
208 std::make_pair(9, "n"),
209 std::make_pair(7, "nw"),
210 std::make_pair(7, "n"),
211 std::make_pair(4, "n"),
212 std::make_pair(5, "nw"),
213 std::make_pair(10, "sw"),
214 std::make_pair(13, "nw"),
215 std::make_pair(19, "nw"),
216 std::make_pair(9, "s"),
217 std::make_pair(16, "n"),
218 std::make_pair(14, "nw"),
219 std::make_pair(14, "nw"),
220 std::make_pair(11, "nw"),
221 std::make_pair(12, "nw"),
222 std::make_pair(9, "n"),
223 std::make_pair(15, "n"),
224 std::make_pair(13, "se"),
225 std::make_pair(15, "n"),
226 std::make_pair(10, "n"),
227 std::make_pair(11, "n"),
228 std::make_pair(8, "n"),
229 std::make_pair(8, "n"),
230 std::make_pair(6, "n"),
231 std::make_pair(22, "s"),
232 std::make_pair(6, "ne"),
233 std::make_pair(1, "nw"),
234 std::make_pair(2, "ne"),
235 std::make_pair(2, "s"),
236 std::make_pair(1, "s"),
237 std::make_pair(28, "s"),
238 std::make_pair(6, "se"),
239 std::make_pair(5, "s"),
240 std::make_pair(5, "se"),
241 std::make_pair(8, "s"),
242 std::make_pair(7, "s"),
243 std::make_pair(25, "n"),
244 std::make_pair(23, "n"),
245 std::make_pair(23, "n"),
246 std::make_pair(20, "n"),
247 std::make_pair(21, "n"),
248 std::make_pair(6, "sw"),
249 std::make_pair(4, "sw"),
250 std::make_pair(7, "s"),
251 std::make_pair(7, "s"),
252 std::make_pair(2, "ne"),
253 std::make_pair(3, "se"),
254 std::make_pair(2, "s"),
255 std::make_pair(3, "s"),
256 std::make_pair(3, "s"),
257 std::make_pair(1, "nw")};
258 
259  std::vector<std::size_t> ans1;
260  std::vector<map_location::DIRECTION> ans2;
261  std::transform(generated_answers.begin(), generated_answers.end(), back_inserter(ans1), &get_first);
262  std::transform(generated_answers.begin(), generated_answers.end(), back_inserter(ans2), &get_second);
263 
265 }
266 
267 static std::pair<map_location , map_location> mirror_walk( std::pair<map_location,map_location> p, map_location::DIRECTION d)
268 {
269  p.first = p.first.get_direction(d);
270  p.second = p.second.get_direction(map_location::get_opposite_dir(d));
271  BOOST_CHECK_EQUAL(p.first, p.second.vector_negation());
272  return p;
273 }
274 
275 BOOST_AUTO_TEST_CASE ( reality_check_vector_negation )
276 {
277  std::pair<map_location, map_location> p(vz,vz);
278 
279  p = mirror_walk(p, n);
280  p = mirror_walk(p, n);
281  p = mirror_walk(p, ne);
282  p = mirror_walk(p, nw);
283  p = mirror_walk(p, s);
284  p = mirror_walk(p, nw);
285  p = mirror_walk(p, se);
286  p = mirror_walk(p, sw);
287  p = mirror_walk(p, n);
288  p = mirror_walk(p, n);
289  p = mirror_walk(p, sw);
290  p = mirror_walk(p, sw);
291  p = mirror_walk(p, sw);
292 }
293 
295 {
296  map_location lz(vz.get_direction(d));
297 
298  map_location temp(loc.vector_sum(lz));
299  BOOST_CHECK_EQUAL(temp, loc.get_direction(d));
300  BOOST_CHECK(tiles_adjacent(loc,temp));
301  BOOST_CHECK(tiles_adjacent(temp,loc));
302  BOOST_CHECK_EQUAL(distance_between(loc,temp), 1);
303 }
304 
305 BOOST_AUTO_TEST_CASE ( reality_check_get_direction )
306 {
307  map_location a(3,4);
308  map_location b(6,5);
309 
316 
323 }
324 
326 {
327  switch (d) {
328  case map_location::NORTH:
329  return map_location::SOUTH;
334  case map_location::SOUTH:
335  return map_location::NORTH;
341  default:
343  }
344 }
345 
346 BOOST_AUTO_TEST_CASE ( check_get_opposite_dir_refactor )
347 {
348  for (unsigned int i = 0; i < 7; i++ ) {
350  BOOST_CHECK_EQUAL ( map_location::get_opposite_dir(d), legacy_get_opposite_dir(d) );
351  }
352 }
353 
354 BOOST_AUTO_TEST_CASE ( check_rotate )
355 {
358 
361 
364 
367 
370 
373 
374 
375  for (unsigned int i = 0; i < 7; i++ ) {
377  BOOST_CHECK_EQUAL ( map_location::get_opposite_dir(d), map_location::rotate_right(d,3) );
378  BOOST_CHECK_EQUAL ( map_location::rotate_right(d,-2), map_location::rotate_right(d,4) );
379  }
380 }
381 
382 static void rotate_around_centers ( const std::vector<map_location> & locs )
383 {
384  for (std::vector<map_location>::const_iterator it_a = locs.begin(); it_a != locs.end(); ++it_a) {
385  for (std::vector<map_location>::const_iterator it_b = it_a + 1; it_b != locs.end(); ++it_b) {
386  const map_location & a = *it_a;
387  const map_location & b = *it_b;
388 
395  }
396  }
397 }
398 
399 BOOST_AUTO_TEST_CASE ( check_rotate_around_center )
400 {
401  rotate_around_centers(preset_locs);
402 }
403 
404 /**
405  * This commented block was used to visualize the output of get_relative_dir
406  * and to help derive the implementation in commit
407  * 829b74c2beaa18eda42710c364b12c987f9caed5
408  */
409 
410 /*
411 static std::string dir_to_terrain (const map_location::DIRECTION dir)
412 {
413  switch(dir) {
414  case map_location::NORTH: return "Gg";
415  case map_location::SOUTH: return "Ai";
416  case map_location::SOUTH_EAST: return "Gs^Fp";
417  case map_location::SOUTH_WEST: return "Ss";
418  case map_location::NORTH_EAST: return "Hd";
419  case map_location::NORTH_WEST: return "Md";
420  default: return "Xv";
421  }
422 }
423 
424 static std::string visualize_helper ( int x , int y, const map_location & c )
425 {
426  map_location temp(x,y);
427  return dir_to_terrain(c.get_relative_dir(temp));
428 }
429 
430 BOOST_AUTO_TEST_CASE ( visualize_get_relative_dir )
431 {
432  map_location c7(7,8), c8(8,8);
433 
434  std::cout << "***" << std::endl;
435  int x;
436  int y;
437  for (y = 0; y < 16; y++) {
438  for (x = 0; x < 15; x++) {
439  std::cout << visualize_helper(x,y,c7) << ", ";
440  }
441  std::cout << visualize_helper(x,y,c7) << std::endl;
442  }
443 
444  std::cout << "***" << std::endl;
445  for (y = 0; y < 16; y++) {
446  for (x = 0; x < 15; x++) {
447  std::cout << visualize_helper(x,y,c8) << ", ";
448  }
449  std::cout << visualize_helper(x,y,c8) << std::endl;
450  }
451 
452  std::cout << "***" << std::endl;
453 }*/
454 
455 BOOST_AUTO_TEST_SUITE_END()
static DIRECTION parse_direction(const std::string &str)
Definition: location.cpp:66
map_location & vector_difference_assign(const map_location &a)
Definition: location.hpp:129
static map_location va
DIRECTION get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
Definition: location.cpp:227
static map_location vs1
static const map_location & ZERO()
Definition: location.hpp:75
#define a
static map_location vt2
static void rotate_around_centers(const std::vector< map_location > &locs)
static map_location::DIRECTION legacy_get_opposite_dir(map_location::DIRECTION d)
static std::vector< map_location > preset_locs
map_location vector_negation() const
Definition: location.hpp:111
static DIRECTION rotate_right(DIRECTION d, unsigned int k=1u)
Definition: location.hpp:45
#define d
BOOST_FIXTURE_TEST_SUITE(test_map_location, MLFixture)
static map_location vb
map_location get_direction(DIRECTION dir, unsigned int n=1u) const
Definition: location.cpp:360
static map_location vector_difference(const map_location &v1, const map_location &v2)
#define b
static map_location::DIRECTION get_second(std::pair< std::size_t, std::string > arg)
static void reality_check_get_direction_helper(const map_location &loc, const map_location::DIRECTION d)
static map_location vc
static map_location vt1
map_location rotate_right_around_center(const map_location &center, int k) const
Definition: location.cpp:307
static std::size_t get_first(std::pair< std::size_t, std::string > arg)
static void characterization_distance_direction(const std::vector< map_location > &locs, const std::vector< map_location::DIRECTION > &dir_answers, const std::vector< std::size_t > &int_answers, map_location::RELATIVE_DIR_MODE mode)
static map_location vs3
static map_location::DIRECTION se
Encapsulates the map of the game.
Definition: location.hpp:38
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Definition: location.cpp:503
std::size_t i
Definition: function.cpp:967
map_location vector_sum(const map_location &a) const
Definition: location.hpp:116
static map_location vs2
mock_party p
static map_location::DIRECTION s
DIRECTION
Valid directions which can be moved in our hexagonal world.
Definition: location.hpp:40
static map_location::DIRECTION sw
static map_location vs4
static DIRECTION get_opposite_dir(DIRECTION d)
Definition: location.hpp:55
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:546
static map_location::DIRECTION nw
static map_location::DIRECTION ne
static map_location vt3
static std::pair< map_location, map_location > mirror_walk(std::pair< map_location, map_location > p, map_location::DIRECTION d)
BOOST_AUTO_TEST_CASE(map_location_characterization_test_radial_mode)
mock_char c
static map_location::DIRECTION n
static std::string write_direction(DIRECTION dir)
Definition: location.cpp:141
static map_location vz