wesnoth/src/terrain_translation.hpp
Thonsew 3a41db7acd Updated unit_types to use t_token...
...in place of std::string and to replace std::map with
boost::unordered_map in the t_move_cost_cache, both to increase speed.
2011-09-08 19:17:31 +00:00

356 lines
12 KiB
C++

/* $Id$ */
/*
Copyright (C) 2006 - 2011 by Mark de Wever <koraq@xs4all.nl>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/** @file */
#ifndef TERRAIN_TRANSLATION_H_INCLUDED
#define TERRAIN_TRANSLATION_H_INCLUDED
#include <boost/functional/hash.hpp>
#include <SDL_types.h> //used for Uint32 definition
#include <vector>
#include <map>
#include "exceptions.hpp"
namespace t_translation {
/**
* Return the maximum allowed map size (in either dimension),
* the maximum map area is, therefore, this value squared.
*/
size_t max_map_size();
typedef Uint32 t_layer;
const t_layer WILDCARD = 0x2A000000;
const t_layer NO_LAYER = 0xFFFFFFFF;
// The definitions for a terrain
/**
* A terrain string which is converted to a terrain is a string with 1 or 2 layers
* the layers are separated by a caret and each group consists of 2 to 4 characters
* if no second layer is defined it is stored as 0xFFFFFFFF, if the second layer
* is empty (needed for matching) the layer has the value 0.
*/
struct t_terrain {
t_terrain(const std::string& b, const std::string& o);
t_terrain(const std::string& b, t_layer o = NO_LAYER);
t_terrain(t_layer b, t_layer o) : base(b), overlay(o) {};
t_terrain() : base(0), overlay(NO_LAYER) {}
t_layer base;
t_layer overlay;
};
const t_terrain NONE_TERRAIN = t_terrain();
inline bool operator<(const t_terrain& a, const t_terrain& b)
{ return a.base < b.base || (a.base == b.base && a.overlay < b.overlay); }
inline bool operator==(const t_terrain& a, const t_terrain& b)
{ return a.base == b.base && a.overlay == b.overlay; }
inline bool operator!=(const t_terrain& a, const t_terrain& b)
{ return a.base != b.base || a.overlay != b.overlay; }
inline t_terrain operator&(const t_terrain& a, const t_terrain& b)
{ return t_terrain(a.base & b.base, a.overlay & b.overlay); }
inline t_terrain operator|(const t_terrain& a, const t_terrain& b)
{ return t_terrain(a.base | b.base, a.overlay | b.overlay); }
inline std::size_t hash_value(t_terrain const& a) {
std::size_t seed = 0;
boost::hash_combine(seed, a.base);
boost::hash_combine(seed, a.overlay);
return seed; }
// operator<< is defined later
typedef std::vector<t_terrain> t_list;
typedef std::vector<std::vector<t_terrain> > t_map;
/**
* This structure can be used for matching terrain strings.
* It optimized for strings that need to be matched often,
* and caches the wildcard info required for matching.
*/
struct t_match{
t_match();
t_match(const std::string& str, const t_layer filler = NO_LAYER);
t_match(const t_terrain& tcode);
t_list terrain;
t_list mask;
t_list masked_terrain;
bool has_wildcard;
bool is_empty;
};
/** Contains an x and y coordinate used for starting positions in maps. */
struct coordinate {
size_t x;
size_t y;
};
// Exception thrown if there's an error with the terrain.
// Note: atm most thrown result in a crash, but I like
// an uncatched exception better than an assert.
struct error : public game::error {
error(const std::string& message) : game::error(message) {}
};
// Some types of terrain which must be known, and can't just
// be loaded in dynamically because they're special.
// It's asserted that there will be corresponding entries for
// these types of terrain in the terrain configuration file.
extern const t_terrain VOID_TERRAIN;
extern const t_terrain FOGGED;
// On the map the user can use this type to make odd shaped maps look good.
extern const t_terrain OFF_MAP_USER;
extern const t_terrain HUMAN_CASTLE;
extern const t_terrain HUMAN_KEEP;
extern const t_terrain SHALLOW_WATER;
extern const t_terrain DEEP_WATER;
extern const t_terrain GRASS_LAND;
extern const t_terrain FOREST;
extern const t_terrain MOUNTAIN;
extern const t_terrain HILL;
extern const t_terrain CAVE_WALL;
extern const t_terrain CAVE;
extern const t_terrain UNDERGROUND_VILLAGE;
extern const t_terrain DWARVEN_CASTLE;
extern const t_terrain DWARVEN_KEEP;
extern const t_terrain PLUS; // +
extern const t_terrain MINUS; // -
extern const t_terrain NOT; // !
extern const t_terrain STAR; // *
extern const t_terrain BASE; // references the base terrain in movement/defense aliases
extern const t_match ALL_FORESTS;
extern const t_match ALL_HILLS;
extern const t_match ALL_MOUNTAINS; //excluding impassable mountains
extern const t_match ALL_SWAMPS;
/**
* Reads a single terrain from a string.
*
* @param str The string which should contain 1 terrain code;
the new format of a terrain code
* is 2 to 4 characters in the set
*@verbatim
* [a-Z][A-Z]/|\_
*@endverbatim
* The underscore is intended for internal use.
* Other letters and characters are not validated but
* users of these letters can get nasty surprices.
* The * is used as wildcard in some cases.
* The terrain code can be two groups separated by a caret,
* the first group is the base terrain,
* the second the overlay terrain.
*
* @param filler if there's no layer this value will be used as the second layer
*
* @return A single terrain code
*/
t_terrain read_terrain_code(const std::string& str, const t_layer filler = NO_LAYER);
/**
* Writes a single terrain code to a string.
* The writers only support the new format.
*
* @param tcode The terrain code to convert to a string
*
* @return A string containing the terrain code
*/
std::string write_terrain_code(const t_terrain& tcode);
inline std::ostream &operator<<(std::ostream &s, const t_terrain &a)
{ s << write_terrain_code(a); return s; }
/**
* Reads a list of terrains from a string, when reading the
*
* @param str A string with one or more terrain codes (see read_terrain_code)
* @param filler If there's no layer, this value will be used as the second layer
*
* @returns A vector which contains the terrain codes found in the string
*/
t_list read_list(const std::string& str, const t_layer filler = NO_LAYER);
/**
* Writes a list of terrains to a string, only writes the new format.
*
* @param list A vector with one or more terrain codes
*
* @returns A string with the terrain codes, comma separated
* and a space behind the commas. Not padded.
*/
std::string write_list(const t_list& list);
/**
* Reads a gamemap string into a 2D vector
*
* @param str A string containing the gamemap, the following rules
* are stated for a gamemap:
* * The map is square
* * The map can be prefixed with one or more empty lines,
* these lines are ignored
* * The map can be postfixed with one or more empty lines,
* these lines are ignored
* * Every end of line can be followed by one or more empty
* lines, these lines are ignored.
* @deprecated NOTE it's deprecated to use this feature.
* * Terrain strings are separated by comma's or an end of line
* symbol, for the last terrain string in the row. For
* readability it's allowed to pad strings with either spaces
* or tab, however the tab is deprecated.
* * A terrain string contains either a terrain or a terrain and
* starting loction. The following format is used
* [S ]T
* S = starting location a positive non-zero number
* T = terrain code (see read_terrain_code)
* @param starting_positions This parameter will be filled with the starting
* locations found. Starting locations can only occur once
* if multiple definitions occur of the same position only
* the last is stored. The returned value is a map:
* * first the starting locations
* * second a coordinate structure where the location was found
*
* @returns A 2D vector with the terrains found the vector data is stored
* like result[x][y] where x the column number is and y the row number.
*/
t_map read_game_map(const std::string& str, std::map<int, coordinate>& starting_positions);
/**
* Write a gamemap in to a vector string.
*
* @param map A terrain vector, as returned from read_game_map
* @param starting_positions A starting positions map, as returned from read_game_map
*
* @returns A terrain string which can be read with read_game_map.
* For readability the map is padded to groups of 12 chars,
* followed by a comma and space.
*/
std::string write_game_map(const t_map& map, std::map<int, coordinate> starting_positions = std::map<int, coordinate>());
/**
* Tests whether a specific terrain matches a list of expressions.
* The list can use wildcard matching with *.
* It also has an inversion function.
* When a ! is found the result of the match is inverted.
* The matching stops at the first match (regardless of the ! found)
* the data is match from start to end.
*
* Example:
* Ww, W* does match and returns true
* Ww, {!, W*} does match and returns false (due to the !)
* WW, Ww doesn't match and return false
*
* Multilayer rules:
* If a terrain has multiple layers, each layer will be matched separately,
* returning true only if both layers match.
*
* Example:
* A*^* matches Abcd but also Abcd^Abcd
* A*^ matches Abcd but *not* Abcd^Abcd
* A*^Abcd does not match Abcd but matches Abcd^Abcd
*
* Note: If an expression doesn't specify a second layer (i.e. it contains
* no caret) the second layer will be filled in with a default value
* (See read_terrain_code and read_list).
*
* In the terrain building code, the second layer will default to the wildcard,
* so both A* and A*^* will match Abcd^Abcd
*
* @param src the value to match (may not contain wildcards)
* @param dest the list of expressions to match against
*
* @returns the result of the match (depending on the !'s)
*/
bool terrain_matches(const t_terrain& src, const t_list& dest);
/**
* Tests whether a specific terrain matches an expression,
* for matching rules see above.
*
* @param src the value to match (may not contain wildcards)
* @param dest the expression to match against
*
* @returns the result of the match (depending on the !'s)
*/
bool terrain_matches(const t_terrain& src, const t_terrain& dest);
/**
* Tests whether a certain terrain matches a list of expressions, for matching
* rules see above. The matching requires some bit mask which impose a
* certain overhead. This version uses a cache to cache the masks so if
* a list needs to be matched often this version is preferred.
*
* @param src the value to match (may not contain wildcards)
* @param dest the cached list of expressions to match against
*
* @returns the result of the match (depending on the !'s)
*/
bool terrain_matches(const t_terrain& src, const t_match& dest);
/**
* Tests whether a terrain code contains a wildcard
*
* @param tcode the terrain code to test for a wildcard
*
* @returns true if wildcard found, else false
*/
bool has_wildcard(const t_terrain& tcode);
/**
* Tests whether a terrain-code list contains at least
* one item with a wildcard
*
* @param list the list to test for a wildcard
*
* @returns true if a wildcard found, else false
*/
bool has_wildcard(const t_list& list);
// These terrain letters are in the builder format,
// and not usable in other parts of the engine
const t_layer TB_STAR = '*' << 24; // It can be assumed this is the equivalent of STAR
const t_layer TB_DOT = '.' << 24;
/**
* Reads a builder map.
* A builder map differs a great deal from a normal map,
* hence the different functions.
*
* @param str The map data, a terrain letter is either a * or a . or a number as
* anchor. The star or dot are stored in the base part of the terrain
* and the anchor in the overlay part. If more letters are allowed as
* special case they will be stored in the base part.
* Anchor 0 is no anchor.
*
* @returns A 2D vector with the data found the vector data is stored
* like result[y][x] where x the column number is and y the row number.
*/
t_map read_builder_map(const std::string& str);
} // end namespace t_translation
#endif