The Battle for Wesnoth  1.15.7+dev
translation.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 - 2018 by Mark de Wever <koraq@xs4all.nl>
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 /**
16  * @file
17  * Routines for terrain-conversion.
18  */
19 
20 #define GETTEXT_DOMAIN "wesnoth-lib"
21 
22 #include "gettext.hpp"
23 #include "lexical_cast.hpp"
24 #include "log.hpp"
25 #include "terrain/translation.hpp"
27 #include "utils/iterable_pair.hpp" //equal_range returns a std:pair instead of sometihng iterable for some reason.
28 #include "wml_exception.hpp"
29 
30 
31 #define ERR_G LOG_STREAM(err, lg::general())
32 #define WRN_G LOG_STREAM(warn, lg::general())
33 
34 namespace t_translation {
35 
36  int max_map_size() {
37  return 1000; //TODO make this overridable by the user without having to rebuild
38  }
39 
40 /***************************************************************************************/
41 // forward declaration of internal functions
42 
43  // The low level convertors,
44  // These function are the ones which know about the internal format.
45  // All other functions are unaware of the internal format.
46 
47  /**
48  * Get the mask for a single layer.
49  *
50  * @param terrain 1 layer of a terrain, might have a wildcard.
51  *
52  * @return Mask for that layer.
53  */
54  static ter_layer get_layer_mask_(ter_layer terrain); //inlined
55 
56  /**
57  * Gets a mask for a terrain, this mask is used for wildcard matching.
58  *
59  * @param terrain The terrain which might have a wildcard.
60  *
61  * @return The mask for this terrain.
62  */
63  static terrain_code get_mask_(const terrain_code& terrain);
64 
66 
67  /**
68  * Converts a string to a layer.
69  *
70  * @param str The terrain string to convert, but needs to be
71  * sanitized so no spaces and only the terrain to convert.
72  *
73  * @return The converted layer.
74  */
76  {
78  }
79 
80  /**
81  * Converts a terrain string to a number.
82  * @param str The terrain string with an optional number.
83  * @param start_position Returns the start_position, the caller should
84  * set it on -1 and it's only changed it there is
85  * a starting position found.
86  * @param filler If the terrain has only 1 layer then the filler
87  * will be used as the second layer.
88  *
89  * @return The terrain code found in the string if no
90  * valid terrain is found VOID will be returned.
91  */
92  static terrain_code string_to_number_(utils::string_view str, std::vector<std::string>& start_positions, const ter_layer filler);
94 
95  /**
96  * Converts a terrain number to a string
97  *
98  * @param terrain The terrain number to convert.
99  * @param start_position The starting position, if smaller than 0
100  * it's ignored else it's written.
101  *
102  * @return The converted string, if no starting
103  * position given it's padded to 4 chars else
104  * padded to 7 chars.
105  */
106  static std::string number_to_string_(terrain_code terrain, const std::vector<std::string>& start_position = std::vector<std::string>());
107 
108  /**
109  * Converts a terrain string to a number for the builder.
110  * The translation rules differ from the normal conversion rules
111  *
112  * @param str The terrain string.
113  *
114  * @return Number for the builder map.
115  */
117 
118 /***************************************************************************************/
119 
121 
122 /**
123  * VOID_TERRAIN is used for shrouded hexes. It's also used by terrain_type's
124  * default constructor, but that's only used as the sentinel value for when
125  * terrain_type_data::get_terrain_info() is asked for an unknown terrain code.
126  */
129 
138 
144 
150 
151 const ter_match ALL_OFF_MAP("_off^_usr,*^_fme");
152 const ter_match ALL_FORESTS("F*,*^F*");
153 const ter_match ALL_HILLS("!,*^V*,!,H*");
154 const ter_match ALL_MOUNTAINS("!,*^V*,!,M*"); //excluding impassable mountains
155 const ter_match ALL_SWAMPS("!,*^V*,*^B*,!,S*"); //excluding swamp villages and bridges
156 
157 /***************************************************************************************/
158 
160  base(string_to_layer_(b)), overlay(o)
161 {}
162 
164  base(string_to_layer_(b)), overlay(string_to_layer_(o))
165 {}
166 
168  terrain(),
169  mask(),
170  masked_terrain(),
171  has_wildcard(false),
172  is_empty(true)
173 {}
174 
176  terrain(t_translation::read_list(str, filler)),
177  mask(),
178  masked_terrain(),
180  is_empty(terrain.empty())
181 
182 {
183  mask.resize(terrain.size());
184  masked_terrain.resize(terrain.size());
185 
186  for(std::size_t i = 0; i < terrain.size(); i++) {
187  mask[i] = t_translation::get_mask_(terrain[i]);
188  masked_terrain[i] = mask[i] & terrain[i];
189  }
190 }
191 
193  terrain(ter_list(1, tcode)),
194  mask(),
195  masked_terrain(),
197  is_empty(terrain.empty())
198 {
199  mask.resize(terrain.size());
200  masked_terrain.resize(terrain.size());
201 
202  for(std::size_t i = 0; i < terrain.size(); i++) {
203  mask[i] = t_translation::get_mask_(terrain[i]);
204  masked_terrain[i] = mask[i] & terrain[i];
205  }
206 }
207 
209 {
210  return string_to_number_(str, filler);
211 }
212 
214 {
215  return number_to_string_(tcode);
216 }
217 
219 {
220  // Handle an empty string
221  ter_list result;
222 
223  if(str.empty()) {
224  return result;
225  }
226 
227  std::size_t offset = 0;
228  while(offset < str.length()) {
229 
230  // Get a terrain chunk
231  const std::string separators = ",";
232  const size_t pos_separator = str.find_first_of(separators, offset);
233  utils::string_view terrain = str.substr(offset, pos_separator - offset);
234 
235  // Process the chunk
236  const terrain_code tile = string_to_number_(terrain, filler);
237 
238  // Add the resulting terrain number
239  result.push_back(tile);
240 
241  // Evaluate the separator
242  if(pos_separator == utils::string_view::npos) {
243  offset = str.length();
244  } else {
245  offset = pos_separator + 1;
246  }
247  }
248 
249  return result;
250 }
251 
253 {
254  std::stringstream result;
255 
256  ter_list::const_iterator itor = list.begin();
257  for( ; itor != list.end(); ++itor) {
258  if(itor == list.begin()) {
259  result << number_to_string_(*itor);
260  } else {
261  result << ", " << number_to_string_(*itor);
262  }
263  }
264 
265  return result.str();
266 }
267 
268 static std::pair<int, int> get_map_size(const char* begin, const char* end)
269 {
270  int w = 1;
271  int h = 0;
272  for (const char* it = begin; it != end;) {
273  int cur_w = 1;
274  ++h;
275 
276 
277  for (;it != end && (*it != '\n' && *it != '\r'); ++it) {
278  if (*it == ',') {
279  ++cur_w;
280  }
281  }
282  w = std::max(w, cur_w);
283 
284  while (it != end && (*it == '\n' || *it == '\r')) {
285  ++it;
286  }
287 
288  }
289  return{ w, h };
290 }
291 
293 {
294  std::size_t offset = 0;
295  int x = 0, y = 0, width = 0;
296 
297  // Skip the leading newlines
298  while(!str.empty() && utils::isnewline(str.front())) {
299  str.remove_prefix(1);
300  }
301 
302  // Did we get an empty map?
303  if(str.length() <= 1) {
304  return ter_map();
305  }
306 
307  auto map_size = get_map_size(&str[0], &str[0] + str.size());
308  ter_map result(map_size.first, map_size.second);
309 
310  while(offset < str.length()) {
311 
312  // Get a terrain chunk
313  const std::string separators = ",\n\r";
314  const std::size_t pos_separator = str.find_first_of(separators, offset);
315  utils::string_view terrain = str.substr(offset, pos_separator - offset);
316 
317  // Process the chunk
318  std::vector<std::string> sp;
319  // The gamemap never has a wildcard
320  const terrain_code tile = string_to_number_(terrain, sp, NO_LAYER);
321 
322  // Add to the resulting starting position
323  for(const auto& starting_position : sp) {
324  if (starting_positions.left.find(starting_position) != starting_positions.left.end()) {
325  WRN_G << "Starting position " << starting_position << " is redefined." << std::endl;
326  }
327  starting_positions.insert(starting_positions::value_type(starting_position, coordinate(x - border_offset.x, y - border_offset.y)));
328  }
329 
330  if(result.w <= x || result.h <= y) {
331  throw error("Map not a rectangle.");
332  }
333 
334  // Add the resulting terrain number
335  result.get(x, y) = tile;
336 
337  // Evaluate the separator
338  if(pos_separator == std::string::npos || utils::isnewline(str[pos_separator])) {
339  // the first line we set the with the other lines we check the width
340  if(y == 0) {
341  // x contains the offset in the map
342  width = x + 1;
343  } else {
344  if((x + 1) != width ) {
345  ERR_G << "Map not a rectangle error occurred at line offset " << y << " position offset " << x << std::endl;
346  throw error("Map not a rectangle.");
347  }
348  if (y > max_map_size()) {
349  ERR_G << "Map size exceeds limit (y > " << max_map_size() << ")" << std::endl;
350  throw error("Map height limit exceeded.");
351  }
352  }
353 
354  // Prepare next iteration
355  ++y;
356  x = 0;
357 
358  // Avoid in infinite loop if the last line ends without an EOL
359  if(pos_separator == std::string::npos) {
360  offset = str.length();
361 
362  } else {
363 
364  offset = pos_separator + 1;
365  // Skip the following newlines
366  while(offset < str.length() && utils::isnewline(str[offset])) {
367  ++offset;
368  }
369  }
370 
371  } else {
372  ++x;
373  offset = pos_separator + 1;
374  if (x > max_map_size()) {
375  ERR_G << "Map size exceeds limit (x > " << max_map_size() << ")" << std::endl;
376  throw error("Map width limit exceeded.");
377  }
378  }
379 
380  }
381 
382  if(x != 0 && (x + 1) != width) {
383  ERR_G << "Map not a rectangle error occurred at the end" << std::endl;
384  throw error("Map not a rectangle.");
385  }
386 
387  return result;
388 }
389 
391 {
392  std::stringstream str;
393 
394  for(int y = 0; y < map.h; ++y) {
395  for(int x = 0; x < map.w; ++x) {
396 
397  // If the current location is a starting position,
398  // it needs to be added to the terrain.
399  // After it's found it can't be found again,
400  // so the location is removed from the map.
401  std::vector<std::string> sp;
402 
403  for(const auto& pair : starting_positions.right.equal_range(coordinate(x - border_offset.x, y - border_offset.y))) {
404  sp.push_back(pair.second);
405  }
406  // Add the separator
407  if(x != 0) {
408  str << ", ";
409  }
410  str << number_to_string_(map[x][y], sp);
411  }
412 
413  if (y < map.h -1)
414  str << "\n";
415  }
416 
417  return str.str();
418 }
419 
420 bool terrain_matches(const terrain_code& src, const terrain_code& dest)
421 {
422  return terrain_matches(src, ter_list(1, dest));
423 }
424 
425 bool terrain_matches(const terrain_code& src, const ter_list& dest)
426 {
427  // NOTE we impose some code duplication.
428  // It could have been rewritten to get a match structure
429  // and then call the version with the match structure.
430  // IMO that's some extra overhead to this function
431  // which is not required. Hence the two versions
432  if(dest.empty()) {
433  return false;
434  }
435 
436 #if 0
437  std::cerr << std::hex << "src = " << src.base << "^" << src.overlay << "\t"
438  << src_mask.base << "^" << src_mask.overlay << "\t"
439  << masked_src.base << "^" << masked_src.overlay << "\t"
440  << src_has_wildcard << "\n";
441 #endif
442 
443  bool result = true;
444  ter_list::const_iterator itor = dest.begin();
445 
446  // Try to match the terrains if matched jump out of the loop.
447  for(; itor != dest.end(); ++itor) {
448 
449  // Match wildcard
450  if(*itor == STAR) {
451  return result;
452  }
453 
454  // Match inverse symbol
455  if(*itor == NOT) {
456  result = !result;
457  continue;
458  }
459 
460  // Full match
461  if(src == *itor) {
462  return result;
463  }
464 
465  // Does the destination wildcard match
466  const terrain_code dest_mask = get_mask_(*itor);
467  const terrain_code masked_dest = (*itor & dest_mask);
468  const bool dest_has_wildcard = has_wildcard(*itor);
469 #if 0
470  std::cerr << std::hex << "dest= "
471  << itor->base << "^" << itor->overlay << "\t"
472  << dest_mask.base << "^" << dest_mask.overlay << "\t"
473  << masked_dest.base << "^" << masked_dest.overlay << "\t"
474  << dest_has_wildcard << "\n";
475 #endif
476  if(dest_has_wildcard &&
477  (src.base & dest_mask.base) == masked_dest.base &&
478  (src.overlay & dest_mask.overlay) == masked_dest.overlay) {
479  return result;
480  }
481 
482 /* Test code */ /*
483  if(src_has_wildcard && dest_has_wildcard && (
484  (
485  get_layer_mask_(itor->base) != NO_LAYER &&
486  get_layer_mask_(src.overlay) != NO_LAYER &&
487  (src.base & dest_mask.base) == masked_dest.base &&
488  (itor->overlay & src_mask.overlay) == masked_src.overlay
489  ) || (
490  get_layer_mask_(itor->overlay) != NO_LAYER &&
491  get_layer_mask_(src.base) != NO_LAYER &&
492  (src.overlay & dest_mask.overlay) == masked_dest.overlay &&
493  (itor->base & src_mask.base) == masked_src.base
494  ))) {
495 
496  return result;
497  }
498 */
499  }
500 
501  // No match, return the inverse of the result
502  return !result;
503 }
504 
505 // This routine is used for the terrain building,
506 // so it's one of the delays while loading a map.
507 // This routine is optimized a bit at the loss of readability.
508 bool terrain_matches(const terrain_code& src, const ter_match& dest)
509 {
510  if(dest.is_empty) {
511  return false;
512  }
513 
514  bool result = true;
515 
516  // Try to match the terrains if matched jump out of the loop.
517  // We loop on the dest.terrain since the iterator is faster than operator[].
518  // The i holds the value for operator[].
519  // Since dest.mask and dest.masked_terrain need to be in sync,
520  // they are less often looked up, so no iterator for them.
521  std::size_t i = 0;
522  ter_list::const_iterator end = dest.terrain.end();
523  for(ter_list::const_iterator terrain_itor = dest.terrain.begin();
524  terrain_itor != end;
525  ++i, ++terrain_itor) {
526 
527  // Match wildcard
528  if(*terrain_itor == STAR) {
529  return result;
530  }
531 
532  // Match inverse symbol
533  if(*terrain_itor == NOT) {
534  result = !result;
535  continue;
536  }
537 
538  // Full match
539  if(*terrain_itor == src) {
540  return result;
541  }
542 
543  // Does the destination wildcard match
544  if(dest.has_wildcard &&
545  (src.base & dest.mask[i].base) == dest.masked_terrain[i].base &&
546  (src.overlay & dest.mask[i].overlay) == dest.masked_terrain[i].overlay) {
547  return result;
548  }
549 
550 /* Test code */ /*
551  if(src_has_wildcard && has_wildcard(*terrain_itor) && (
552  (
553  get_layer_mask_(terrain_itor->base) != NO_LAYER &&
554  get_layer_mask_(src.overlay) != NO_LAYER &&
555  (src.base & dest.mask[i].base) == dest.masked_terrain[i].base &&
556  (terrain_itor->overlay & src_mask.overlay) == masked_src.overlay
557  ) || (
558  get_layer_mask_(terrain_itor->overlay) != NO_LAYER &&
559  get_layer_mask_(src.base) != NO_LAYER &&
560  (src.overlay & dest.mask[i].overlay) == dest.masked_terrain[i].overlay &&
561  (terrain_itor->base & src_mask.base) == masked_src.base
562  ))) {
563 
564  return result;
565  }
566 */
567  }
568 
569  // No match, return the inverse of the result
570  return !result;
571 }
572 
573 bool has_wildcard(const terrain_code& tcode)
574 {
575  if(tcode.overlay == NO_LAYER) {
576  return get_layer_mask_(tcode.base) != NO_LAYER;
577  } else {
578  return get_layer_mask_(tcode.base) != NO_LAYER || get_layer_mask_(tcode.overlay) != NO_LAYER;
579  }
580 }
581 
582 bool has_wildcard(const ter_list& list)
583 {
584  if(list.empty()) {
585  return false;
586  }
587 
588  // Test all items for a wildcard
589  ter_list::const_iterator itor = list.begin();
590  for(; itor != list.end(); ++itor) {
591  if(has_wildcard(*itor)) {
592  return true;
593  }
594  }
595 
596  // No wildcard found
597  return false;
598 }
599 
601 {
602  boost::multi_array<int, sizeof(ter_map)> a;
603 
604  std::size_t offset = 0;
605  // Skip the leading newlines
606  while(offset < str.length() && utils::isnewline(str[offset])) {
607  ++offset;
608  }
609  // Did we get an empty map?
610  if((offset + 1) >= str.length()) {
611  return ter_map();
612  }
613 
614  auto map_size = get_map_size(&str[offset], str.c_str() + str.size());
615  ter_map result(map_size.second, map_size.first, terrain_code(t_translation::TB_DOT, ter_layer()));
616 
617  int x = 0, y = 0;
618  while(offset < str.length()) {
619 
620  // Get a terrain chunk
621  const std::string separators = ",\n\r";
622  const std::size_t pos_separator = str.find_first_of(separators, offset);
623  std::string terrain = "";
624  // Make sure we didn't hit an empty chunk
625  // which is allowed
626  if(pos_separator != offset) {
627  terrain = str.substr(offset, pos_separator - offset);
628  }
629 
630  // Process the chunk
631  const terrain_code tile = string_to_builder_number_(terrain);
632 
633  // Make space for the new item
634  if (result.h <= x || result.w <= y) {
635  throw error("Map not a rectangle.");
636  }
637 
638  // Add the resulting terrain number,
639  result.get(y, x) = tile;
640 
641  // evaluate the separator
642  if(pos_separator == std::string::npos) {
643  // Probably not required to change the value,
644  // but be sure the case should be handled at least.
645  // I'm not sure how it is defined in the standard,
646  // but here it's defined at max u32 which with +1 gives 0
647  // and make a nice infinite loop.
648  offset = str.length();
649  } else if(utils::isnewline(str[pos_separator])) {
650  // Prepare next iteration
651  ++y;
652  x = 0;
653 
654  offset = pos_separator + 1;
655  // Skip the following newlines
656  while(offset < str.length() && utils::isnewline(str[offset])) {
657  ++offset;
658  }
659 
660  } else {
661  ++x;
662  offset = pos_separator + 1;
663  }
664 
665  }
666 
667  return result;
668 }
669 
670 /***************************************************************************************/
671 // Internal
672 
674 {
675  // Test for the star 0x2A in every position
676  // and return the appropriate mask
677 /*
678  * This is what the code intents to do, but in order to gain some more
679  * speed it's changed to the code below, which does the same but faster.
680  * This routine is used often in the builder and the speedup is noticeable. */
681  if((terrain & 0xFF000000) == 0x2A000000) return 0x00000000;
682  if((terrain & 0x00FF0000) == 0x002A0000) return 0xFF000000;
683  if((terrain & 0x0000FF00) == 0x00002A00) return 0xFFFF0000;
684  if((terrain & 0x000000FF) == 0x0000002A) return 0xFFFFFF00;
685 
686 /*
687  uint8_t *ptr = (uint8_t *) &terrain;
688 
689  if(ptr[3] == 0x2A) return 0x00000000;
690  if(ptr[2] == 0x2A) return 0xFF000000;
691  if(ptr[1] == 0x2A) return 0xFFFF0000;
692  if(ptr[0] == 0x2A) return 0xFFFFFF00;
693 */
694  // no star found return the default
695  return 0xFFFFFFFF;
696 }
697 
698 static terrain_code get_mask_(const terrain_code& terrain)
699 {
700  if(terrain.overlay == NO_LAYER) {
701  return terrain_code(get_layer_mask_(terrain.base), 0xFFFFFFFF);
702  } else {
703  return terrain_code(get_layer_mask_(terrain.base), get_layer_mask_(terrain.overlay));
704  }
705 }
706 
708 {
709  if(str.empty()) {
710  return NO_LAYER;
711  }
712 
713  // Validate the string
714  VALIDATE(str.size() <= 4, _("A terrain with a string with more "
715  "than 4 characters has been found, the affected terrain is:") + std::string(str));
716 
717  ter_layer result = 0;
718  // The conversion to int puts the first char
719  // in the highest part of the number.
720  // This will make the wildcard matching
721  // later on a bit easier.
722  for(std::size_t i = 0; i < 4; ++i) {
723  const unsigned char c = (i < str.size()) ? str[i] : 0;
724 
725  // Clearing the lower area is a nop on i == 0
726  // so no need for if statement
727  result <<= 8;
728 
729  // Add the result
730  result += c;
731  }
732 
733  return result;
734 }
735 
737  std::vector<std::string> dummy;
738  return string_to_number_(str, dummy, filler);
739 }
740 
741 static terrain_code string_to_number_(utils::string_view str, std::vector<std::string>& start_positions, const ter_layer filler)
742 {
743  terrain_code result;
744 
745  // Strip the spaces around us
746  // unlike the old implementation this also trims newlines.
747  utils::trim(str);
748  if(str.empty()) {
749  return result;
750  }
751 
752  // Split if we have spaces inside
753  std::size_t offset = str.find(' ', 0);
754  while(offset != std::string::npos) {
755  start_positions.push_back(std::string(str.substr(0, offset)));
756  str.remove_prefix(offset + 1);
757  offset = str.find(' ', 0);
758  }
759 
760  offset = str.find('^', 0);
761  if(offset != std::string::npos) {
762  result = terrain_code { string_to_layer_(str.substr(0, offset)), string_to_layer_(str.substr(offset + 1)) };
763  } else {
764  result = terrain_code { string_to_layer_(str), filler };
765 
766  // Ugly hack
767  if(filler == WILDCARD && (result.base == NOT.base ||
768  result.base == STAR.base)) {
769 
770  result.overlay = NO_LAYER;
771  }
772  }
773 
774  return result;
775 }
776 
777 static std::string number_to_string_(terrain_code terrain, const std::vector<std::string>& start_positions)
778 {
779  std::string result = "";
780 
781  // Insert the start position
782  for (const std::string& str : start_positions) {
783  result = str + " " + result;
784  }
785 
786  /*
787  * The initialization of tcode is done to make gcc-4.7 happy. Otherwise it
788  * some uninitialized fields might be used. Its analysis are wrong, but
789  * Initialize to keep it happy.
790  */
791  unsigned char tcode[9] {0};
792  // Insert the terrain tcode
793  tcode[0] = ((terrain.base & 0xFF000000) >> 24);
794  tcode[1] = ((terrain.base & 0x00FF0000) >> 16);
795  tcode[2] = ((terrain.base & 0x0000FF00) >> 8);
796  tcode[3] = (terrain.base & 0x000000FF);
797 
798  if(terrain.overlay != NO_LAYER) {
799  tcode[4] = '^'; //the layer separator
800  tcode[5] = ((terrain.overlay & 0xFF000000) >> 24);
801  tcode[6] = ((terrain.overlay & 0x00FF0000) >> 16);
802  tcode[7] = ((terrain.overlay & 0x0000FF00) >> 8);
803  tcode[8] = (terrain.overlay & 0x000000FF);
804  } else {
805  // If no second layer, the second layer won't be written,
806  // so no need to initialize that part of the array
807  tcode[4] = 0;
808  }
809 
810  for(int i = 0; i < 9; ++i) {
811  if(tcode[i] != 0 && tcode[i] != 0xFF) {
812  result += tcode[i];
813  }
814  if(i == 4 && tcode[i] == 0) {
815  // no layer, stop
816  break;
817  }
818  }
819 
820  return result;
821 }
822 
824 {
825  // Strip the spaces around us
826  const std::string& whitespace = " \t";
827  str.erase(0, str.find_first_not_of(whitespace));
828  if(! str.empty()) {
829  str.erase(str.find_last_not_of(whitespace) + 1);
830  }
831 
832  // Empty string is allowed here, so handle it
833  if(str.empty()) {
834  return terrain_code();
835  }
836 
837  const int number = lexical_cast_default(str, -1);
838  if(number == -1) {
839  // At this point we have a single char
840  // which should be interpreted by the
841  // map builder, so return this number
842  return terrain_code(str[0] << 24, 0);
843  } else {
844  return terrain_code(0, number);
845  }
846 }
847 
848 } // end namespace t_translation
849 
850 #if 0
851 // small helper rule to test the matching rules
852 // building rule
853 // make terrain_translation.o && g++ terrain_translation.o libwesnoth-core.a -lSDL -o terrain_translation
854 int main(int argc, char** argv)
855 {
856  if(argc > 1) {
857 
858  if(std::string(argv[1]) == "match" && argc == 4) {
860 
862 
863  if(t_translation::terrain_matches(src, dest)) {
864  std::cout << "Match\n" ;
865  } else {
866  std::cout << "No match\n";
867  }
868  }
869  }
870 }
871 
872 #endif
#define ERR_G
Definition: translation.cpp:31
const terrain_code CAVE
BOOST_CXX14_CONSTEXPR size_type find(basic_string_view s, size_type pos=0) const BOOST_NOEXCEPT
const terrain_code FOREST
int dummy
Definition: lstrlib.cpp:1125
boost::bimaps::bimap< boost::bimaps::set_of< std::string >, boost::bimaps::multiset_of< coordinate > > starting_positions
const terrain_code DWARVEN_KEEP
Add a special kind of assert to validate whether the input from WML doesn&#39;t contain any problems that...
bool terrain_matches(const terrain_code &src, const terrain_code &dest)
Tests whether a specific terrain matches an expression, for matching rules see above.
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:39
New lexcical_cast header.
#define a
static ter_layer string_to_layer_(utils::string_view str)
BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n)
To lexical_cast_default(From value, To fallback=To())
Lexical cast converts one type to another with a fallback.
uint32_t ter_layer
Definition: translation.hpp:39
BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos, size_type n=npos) const
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:50
const ter_layer NO_LAYER
Definition: translation.hpp:41
#define h
BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT
const terrain_code HUMAN_KEEP
std::string str
Definition: statement.cpp:110
const terrain_code HILL
const ter_match ALL_MOUNTAINS("!,*^V*,!,M*")
int main(int argc, char **argv)
Definition: SDLMain.mm:95
const terrain_code VOID_TERRAIN
VOID_TERRAIN is used for shrouded hexes.
#define b
static std::string number_to_string_(terrain_code terrain, const std::vector< std::string > &start_position=std::vector< std::string >())
Converts a terrain number to a string.
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:100
int max_map_size()
Return the maximum allowed map size (in either dimension), the maximum map area is, therefore, this value squared.
Definition: translation.cpp:36
const terrain_code MOUNTAIN
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
const terrain_code FOGGED
void trim(string_view &s)
static const ::game_config_view * terrain
The terrain used to create the cache.
Definition: minimap.cpp:130
const terrain_code STAR
ter_map read_game_map(utils::string_view str, starting_positions &starting_positions, coordinate border_offset)
Reads a gamemap string into a 2D vector.
const terrain_code DWARVEN_CASTLE
const terrain_code MINUS
const terrain_code PLUS
BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT
const terrain_code NOT
#define WRN_G
Definition: translation.cpp:32
const ter_layer TB_DOT
const ter_match ALL_HILLS("!,*^V*,!,H*")
const terrain_code OFF_MAP_USER
static terrain_code string_to_builder_number_(std::string str)
Converts a terrain string to a number for the builder.
std::string write_terrain_code(const terrain_code &tcode)
Writes a single terrain code to a string.
const terrain_code HUMAN_CASTLE
BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT
Encapsulates the map of the game.
Definition: location.hpp:42
static ter_layer get_layer_mask_(ter_layer terrain)
Get the mask for a single layer.
const terrain_code BASE
std::size_t i
Definition: function.cpp:933
const ter_match ALL_SWAMPS("!,*^V*,*^B*,!,S*")
ter_map read_builder_map(const std::string &str)
Reads a builder map.
terrain_code read_terrain_code(utils::string_view str, const ter_layer filler)
Reads a single terrain from a string.
std::string write_list(const ter_list &list)
Writes a list of terrains to a string, only writes the new format.
int w
static BOOST_CONSTEXPR_OR_CONST size_type npos
Definition: string_view.hpp:84
static std::pair< int, int > get_map_size(const char *begin, const char *end)
const terrain_code CAVE_WALL
bool has_wildcard(const terrain_code &tcode)
Tests whether a terrain code contains a wildcard.
bool isnewline(const char c)
std::string write_game_map(const ter_map &map, const starting_positions &starting_positions, coordinate border_offset)
Write a gamemap in to a vector string.
const terrain_code DEEP_WATER
const ter_match ALL_OFF_MAP
BOOST_CONSTEXPR const_reference front() const
const terrain_code UNDERGROUND_VILLAGE
ter_list read_list(utils::string_view str, const ter_layer filler)
Reads a list of terrains from a string, when reading the.
Standard logging facilities (interface).
std::vector< terrain_code > ter_list
Definition: translation.hpp:78
const ter_layer WILDCARD
Definition: translation.hpp:40
static terrain_code get_mask_(const terrain_code &terrain)
Gets a mask for a terrain, this mask is used for wildcard matching.
const terrain_code SHALLOW_WATER
BOOST_CXX14_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos=0) const BOOST_NOEXCEPT
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
static terrain_code string_to_number_(utils::string_view str, std::vector< std::string > &start_positions, const ter_layer filler)
Converts a terrain string to a number.
mock_char c
This structure can be used for matching terrain strings.
const terrain_code GRASS_LAND
const ter_match ALL_FORESTS