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