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