The Battle for Wesnoth  1.15.12+dev
translation.hpp
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 #pragma once
16 
17 #include <vector>
18 #include <map>
19 #include <cstdint>
20 #include <boost/bimap.hpp>
21 #include <boost/bimap/set_of.hpp>
22 #include <boost/bimap/multiset_of.hpp>
23 #include <boost/multi_array.hpp>
24 
25 #include "exceptions.hpp"
26 #include "map/location.hpp"
27 
28 #include <string_view>
29 
30 namespace t_translation {
31 
32  /**
33  * Return the maximum allowed map size (in either dimension),
34  * the maximum map area is, therefore, this value squared.
35  */
36  int max_map_size();
37 
38  typedef uint32_t ter_layer;
39  const ter_layer WILDCARD = 0x2A000000;
40  const ter_layer NO_LAYER = 0xFFFFFFFF;
41 
42  // The definitions for a terrain
43  /**
44  * A terrain string which is converted to a terrain is a string with 1 or 2 layers
45  * the layers are separated by a caret and each group consists of 2 to 4 characters
46  * if no second layer is defined it is stored as 0xFFFFFFFF, if the second layer
47  * is empty (needed for matching) the layer has the value 0.
48  */
49  struct terrain_code {
50  terrain_code(const std::string& b, const std::string& o);
51  explicit terrain_code(const std::string& b, ter_layer o = NO_LAYER);
52  terrain_code(ter_layer b, ter_layer o) : base(b), overlay(o) {}
53  terrain_code() : base(0), overlay(NO_LAYER) {}
54 
55  ter_layer base;
56  ter_layer overlay;
57  };
59 
60  inline bool operator<(const terrain_code& a, const terrain_code& b)
61  { return std::tie(a.base, a.overlay) < std::tie(b.base, b.overlay); };
62 
63  inline bool operator==(const terrain_code& a, const terrain_code& b)
64  { return a.base == b.base && a.overlay == b.overlay; }
65 
66  inline bool operator!=(const terrain_code& a, const terrain_code& b)
67  { return a.base != b.base || a.overlay != b.overlay; }
68 
70  { return terrain_code(a.base & b.base, a.overlay & b.overlay); }
71 
73  { return terrain_code(a.base | b.base, a.overlay | b.overlay); }
74 
75  // operator<< is defined later
76 
77  typedef std::vector<terrain_code> ter_list;
78  struct ter_map {
79 
80  ter_map() = default;
81  ter_map(const ter_map&) = default;
82  ter_map(ter_map&&) = default;
83 
84  ter_map(int w, int h, terrain_code fill = terrain_code()) : data(w * h, fill), w(w), h(h) {}
85 
86  ter_map & operator= (const ter_map &) = default;
87  ter_map & operator= (ter_map &&) = default;
88 
89  terrain_code& get(int x, int y) { std::size_t index = x * h + y; return data.at(index); }
90  const terrain_code& get(int x, int y) const { std::size_t index = x * h + y; return data.at(index); }
91 
92  std::vector<terrain_code> data;
93  int w;
94  int h;
95  std::vector<terrain_code>::iterator operator[](int x) { return data.begin() + h * x; }
96  std::vector<terrain_code>::const_iterator operator[](int x) const { return data.begin() + h * x; }
97  };
98 
99  /**
100  * This structure can be used for matching terrain strings.
101  * It optimized for strings that need to be matched often,
102  * and caches the wildcard info required for matching.
103  */
104  struct ter_match{
105  ter_match();
106  ter_match(std::string_view str, const ter_layer filler = NO_LAYER);
107  ter_match(const terrain_code& tcode);
108 
109  ter_list terrain;
110  ter_list mask;
111  ter_list masked_terrain;
113  bool is_empty;
114  };
115 
116  /** Contains an x and y coordinate used for starting positions in maps. */
118 
119  // Exception thrown if there's an error with the terrain.
120  // Note: atm most thrown result in a crash, but I like
121  // an uncatched exception better than an assert.
122  struct error : public game::error {
123  error(const std::string& message) : game::error(message) {}
124  };
125 
126  // Some types of terrain which must be known, and can't just
127  // be loaded in dynamically because they're special.
128  // It's asserted that there will be corresponding entries for
129  // these types of terrain in the terrain configuration file.
130  extern const terrain_code VOID_TERRAIN;
131  extern const terrain_code FOGGED;
132 
133  // On the map the user can use this type to make odd shaped maps look good.
134  extern const terrain_code OFF_MAP_USER;
135 
136  extern const terrain_code HUMAN_CASTLE;
137  extern const terrain_code HUMAN_KEEP;
138  extern const terrain_code SHALLOW_WATER;
139  extern const terrain_code DEEP_WATER;
140  extern const terrain_code GRASS_LAND;
141  extern const terrain_code FOREST;
142  extern const terrain_code MOUNTAIN;
143  extern const terrain_code HILL;
144 
145  extern const terrain_code CAVE_WALL;
146  extern const terrain_code CAVE;
147  extern const terrain_code UNDERGROUND_VILLAGE;
148  extern const terrain_code DWARVEN_CASTLE;
149  extern const terrain_code DWARVEN_KEEP;
150 
151  extern const terrain_code PLUS; // +
152  extern const terrain_code MINUS; // -
153  extern const terrain_code NOT; // !
154  extern const terrain_code STAR; // *
155  extern const terrain_code BASE; // references the base terrain in movement/defense aliases
156 
157  extern const ter_match ALL_OFF_MAP;
158  extern const ter_match ALL_FORESTS;
159  extern const ter_match ALL_HILLS;
160  extern const ter_match ALL_MOUNTAINS; //excluding impassable mountains
161  extern const ter_match ALL_SWAMPS;
162 
163  /**
164  * Reads a single terrain from a string.
165  *
166  * @param str The string which should contain 1 terrain code;
167  the new format of a terrain code
168  * is 2 to 4 characters in the set
169  *@verbatim
170  * [a-Z][A-Z]/|\_
171  *@endverbatim
172  * The underscore is intended for internal use.
173  * Other letters and characters are not validated but
174  * users of these letters can get nasty surprises.
175  * The * is used as wildcard in some cases.
176  * The terrain code can be two groups separated by a caret,
177  * the first group is the base terrain,
178  * the second the overlay terrain.
179  *
180  * @param filler if there's no layer this value will be used as the second layer
181  *
182  * @return A single terrain code
183  */
184  terrain_code read_terrain_code(std::string_view str, const ter_layer filler = NO_LAYER);
185 
186  /**
187  * Writes a single terrain code to a string.
188  * The writers only support the new format.
189  *
190  * @param tcode The terrain code to convert to a string
191  *
192  * @return A string containing the terrain code
193  */
194  std::string write_terrain_code(const terrain_code& tcode);
195  inline std::ostream &operator<<(std::ostream &s, const terrain_code &a)
196  { s << write_terrain_code(a); return s; }
197 
198  /**
199  * Reads a list of terrains from a string, when reading the
200  *
201  * @param str A string with one or more terrain codes (see read_terrain_code)
202  * @param filler If there's no layer, this value will be used as the second layer
203  *
204  * @returns A vector which contains the terrain codes found in the string
205  */
206  ter_list read_list(std::string_view str, const ter_layer filler = NO_LAYER);
207 
208  /**
209  * Writes a list of terrains to a string, only writes the new format.
210  *
211  * @param list A vector with one or more terrain codes
212  *
213  * @returns A string with the terrain codes, comma separated
214  * and a space behind the commas. Not padded.
215  */
216  std::string write_list(const ter_list& list);
217 
218  using starting_positions = boost::bimaps::bimap<boost::bimaps::set_of<std::string>, boost::bimaps::multiset_of<coordinate>>;
219  /**
220  * Reads a gamemap string into a 2D vector
221  *
222  * @param str A string containing the gamemap, the following rules
223  * are stated for a gamemap:
224  * * The map is square
225  * * The map can be prefixed with one or more empty lines,
226  * these lines are ignored
227  * * The map can be postfixed with one or more empty lines,
228  * these lines are ignored
229  * * Every end of line can be followed by one or more empty
230  * lines, these lines are ignored.
231  * @deprecated NOTE it's deprecated to use this feature.
232  * * Terrain strings are separated by comma's or an end of line
233  * symbol, for the last terrain string in the row. For
234  * readability it's allowed to pad strings with either spaces
235  * or tab, however the tab is deprecated.
236  * * A terrain string contains either a terrain or a terrain and
237  * starting location. The following format is used
238  * [S ]T
239  * S = starting location a positive non-zero number
240  * T = terrain code (see read_terrain_code)
241  * @param positions This parameter will be filled with the starting
242  * locations found. Starting locations can only occur once
243  * if multiple definitions occur of the same position only
244  * the last is stored. The returned value is a map:
245  * * first the starting locations
246  * * second a coordinate structure where the location was found
247  * @param border_offset
248  *
249  * @returns A 2D vector with the terrains found the vector data is stored
250  * like result[x][y] where x the column number is and y the row number.
251  */
252  ter_map read_game_map(std::string_view str, starting_positions& positions, coordinate border_offset = coordinate{ 0, 0 });
253 
254  /**
255  * Write a gamemap in to a vector string.
256  *
257  * @param map A terrain vector, as returned from read_game_map
258  * @param positions A starting positions map, as returned from read_game_map
259  * @param border_offset
260  *
261  * @returns A terrain string which can be read with read_game_map.
262  * For readability the map is padded to groups of 12 chars,
263  * followed by a comma and space.
264  */
265  std::string write_game_map(const ter_map& map, const starting_positions& positions = starting_positions(), coordinate border_offset = coordinate{ 0, 0 });
266 
267  /**
268  * Tests whether a specific terrain matches a list of expressions.
269  * The list can use wildcard matching with *.
270  * It also has an inversion function.
271  * When a ! is found the result of the match is inverted.
272  * The matching stops at the first match (regardless of the ! found)
273  * the data is match from start to end.
274  *
275  * Example:
276  * Ww, W* does match and returns true
277  * Ww, {!, W*} does match and returns false (due to the !)
278  * WW, Ww doesn't match and return false
279  *
280  * Multilayer rules:
281  * If a terrain has multiple layers, each layer will be matched separately,
282  * returning true only if both layers match.
283  *
284  * Example:
285  * A*^* matches Abcd but also Abcd^Abcd
286  * A*^ matches Abcd but *not* Abcd^Abcd
287  * A*^Abcd does not match Abcd but matches Abcd^Abcd
288  *
289  * Note: If an expression doesn't specify a second layer (i.e. it contains
290  * no caret) the second layer will be filled in with a default value
291  * (See read_terrain_code and read_list).
292  *
293  * In the terrain building code, the second layer will default to the wildcard,
294  * so both A* and A*^* will match Abcd^Abcd
295  *
296  * @param src the value to match (may not contain wildcards)
297  * @param dest the list of expressions to match against
298  *
299  * @returns the result of the match (depending on the !'s)
300  */
301  bool terrain_matches(const terrain_code& src, const ter_list& dest);
302 
303  /**
304  * Tests whether a specific terrain matches an expression,
305  * for matching rules see above.
306  *
307  * @param src the value to match (may not contain wildcards)
308  * @param dest the expression to match against
309  *
310  * @returns the result of the match (depending on the !'s)
311  */
312  bool terrain_matches(const terrain_code& src, const terrain_code& dest);
313 
314  /**
315  * Tests whether a certain terrain matches a list of expressions, for matching
316  * rules see above. The matching requires some bit mask which impose a
317  * certain overhead. This version uses a cache to cache the masks so if
318  * a list needs to be matched often this version is preferred.
319  *
320  * @param src the value to match (may not contain wildcards)
321  * @param dest the cached list of expressions to match against
322  *
323  * @returns the result of the match (depending on the !'s)
324  */
325  bool terrain_matches(const terrain_code& src, const ter_match& dest);
326 
327  /**
328  * Tests whether a terrain code contains a wildcard
329  *
330  * @param tcode the terrain code to test for a wildcard
331  *
332  * @returns true if wildcard found, else false
333  */
334  bool has_wildcard(const terrain_code& tcode);
335 
336  /**
337  * Tests whether a terrain-code list contains at least
338  * one item with a wildcard
339  *
340  * @param list the list to test for a wildcard
341  *
342  * @returns true if a wildcard found, else false
343  */
344  bool has_wildcard(const ter_list& list);
345 
346  // These terrain letters are in the builder format,
347  // and not usable in other parts of the engine
348  const ter_layer TB_STAR = '*' << 24; // It can be assumed this is the equivalent of STAR
349  const ter_layer TB_DOT = '.' << 24;
350 
351  /**
352  * Reads a builder map.
353  * A builder map differs a great deal from a normal map,
354  * hence the different functions.
355  *
356  * @param str The map data, a terrain letter is either a * or a . or a number as
357  * anchor. The star or dot are stored in the base part of the terrain
358  * and the anchor in the overlay part. If more letters are allowed as
359  * special case they will be stored in the base part.
360  * Anchor 0 is no anchor.
361  *
362  * @returns A 2D vector with the data found the vector data is stored
363  * like result[y][x] where x the column number is and y the row number.
364  */
365  ter_map read_builder_map(const std::string& str);
366 
367 } // end namespace t_translation
const terrain_code CAVE
ter_map(int w, int h, terrain_code fill=terrain_code())
Definition: translation.hpp:84
const terrain_code NONE_TERRAIN
Definition: translation.hpp:58
const terrain_code FOREST
boost::bimaps::bimap< boost::bimaps::set_of< std::string >, boost::bimaps::multiset_of< coordinate > > starting_positions
const terrain_code DWARVEN_KEEP
error(const std::string &message)
bool terrain_matches(const terrain_code &src, const terrain_code &dest)
Tests whether a specific terrain matches an expression, for matching rules see above.
#define a
uint32_t ter_layer
Definition: translation.hpp:38
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:49
std::vector< terrain_code > data
Definition: translation.hpp:92
const ter_layer NO_LAYER
Definition: translation.hpp:40
#define h
ter_map read_game_map(std::string_view str, starting_positions &starting_positions, coordinate border_offset)
Reads a gamemap string into a 2D vector.
const terrain_code HUMAN_KEEP
const terrain_code HILL
const ter_match ALL_MOUNTAINS("!,*^V*,!,M*")
terrain_code read_terrain_code(std::string_view str, const ter_layer filler)
Reads a single terrain from a string.
terrain_code(ter_layer b, ter_layer o)
Definition: translation.hpp:52
const terrain_code VOID_TERRAIN
VOID_TERRAIN is used for shrouded hexes.
#define b
std::vector< terrain_code >::const_iterator operator[](int x) const
Definition: translation.hpp:96
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
std::ostream & operator<<(std::ostream &s, const terrain_code &a)
bool operator<(const terrain_code &a, const terrain_code &b)
Definition: translation.hpp:60
const terrain_code FOGGED
const terrain_code STAR
const terrain_code DWARVEN_CASTLE
const terrain_code MINUS
const ter_layer TB_STAR
const terrain_code PLUS
const terrain_code NOT
const ter_layer TB_DOT
const ter_match ALL_HILLS("!,*^V*,!,H*")
const terrain_code OFF_MAP_USER
std::string write_terrain_code(const terrain_code &tcode)
Writes a single terrain code to a string.
const terrain_code HUMAN_CASTLE
terrain_code operator &(const terrain_code &a, const terrain_code &b)
Definition: translation.hpp:69
Encapsulates the map of the game.
Definition: location.hpp:37
std::vector< terrain_code >::iterator operator[](int x)
Definition: translation.hpp:95
const terrain_code BASE
const ter_match ALL_SWAMPS("!,*^V*,*^B*,!,S*")
bool operator==(const terrain_code &a, const terrain_code &b)
Definition: translation.hpp:63
terrain_code operator|(const terrain_code &a, const terrain_code &b)
Definition: translation.hpp:72
static map_location::DIRECTION s
ter_map read_builder_map(const std::string &str)
Reads a builder map.
bool operator!=(const terrain_code &a, const terrain_code &b)
Definition: translation.hpp:66
std::string write_list(const ter_list &list)
Writes a list of terrains to a string, only writes the new format.
int w
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
const terrain_code CAVE_WALL
bool has_wildcard(const terrain_code &tcode)
Tests whether a terrain code contains a wildcard.
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
Base class for all the errors encountered by the engine.
Definition: exceptions.hpp:27
const terrain_code UNDERGROUND_VILLAGE
std::vector< terrain_code > ter_list
Definition: translation.hpp:77
const ter_layer WILDCARD
Definition: translation.hpp:39
const terrain_code SHALLOW_WATER
This structure can be used for matching terrain strings.
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
const terrain_code GRASS_LAND
ter_list read_list(std::string_view str, const ter_layer filler)
Reads a list of terrains from a string, when reading the.
const ter_match ALL_FORESTS