/* $Id$ */ /* Copyright (C) 2004 - 2009 by Philippe Plantier 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 version 2 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 builder.hpp * Definitions for the terrain builder. */ #ifndef BUILDER_H_INCLUDED #define BUILDER_H_INCLUDED #include "animated.hpp" #include "image.hpp" #include "map_location.hpp" #include #include class config; /** * The class terrain_builder is constructed from a config object, and a * gamemap object. On construction, it parses the configuration and extracts * the list of [terrain_graphics] rules. Each terrain_graphics rule attaches * one or more images to a specific terrain pattern. * It then applies the rules loaded from the configuration to the current map, * and calculates the list of images that must be associated to each hex of * the map. * * The get_terrain_at method can then be used to obtain the list of images * necessary to draw the terrain on a given tile. */ class terrain_builder { public: /** Used as a parameter for the get_terrain_at function. */ enum ADJACENT_TERRAIN_TYPE { ADJACENT_BACKGROUND, /**< * Represents terrains which are to be * drawn behind unit sprites */ ADJACENT_FOREGROUND /**< * Represents terrains which are to be * drawn in front of them. */ }; /** A shorthand typedef for a list of animated image locators, * the base data type returned by the get_terrain_at method. */ typedef std::vector > imagelist; /** Constructor for the terrain_builder class. * * @param cfg The main grame configuration object, where the * [terrain_graphics] rule reside. * @param level A level (scenario)-specific configuration file, * containing scenario-specific [terrain_graphics] rules. * @param map A properly-initialized gamemap object representing * the current terrain map. * @param offmap_image The filename of the image which will be used as * off map image (see add_off_map_rule()). * This image automatically gets the 'terrain/' prefix * and '.png' suffix */ terrain_builder(const config& cfg, const config &level, const gamemap* map, const std::string& offmap_image); const gamemap& map() const { return *map_; } /** * Updates internals that cache map size. This should be called when the map * size has changed. */ void reload_map(); void change_map(const gamemap* m); /** Returns a vector of strings representing the images to load & blit * together to get the built content for this tile. * * @param loc The location relative the the terrain map, * where we ask for the image list * @param tod The string representing the current time-of day. * Will be used if some images specify several * time-of-day- related variants. * @param terrain_type ADJACENT_BACKGROUND or ADJACENT_FOREGROUND, * depending on wheter we ask for the terrain which is * before, or after the unit sprite. * * @return Returns a pointer list of animated images corresponding * to the parameters, or NULL if there is none. */ const imagelist *get_terrain_at(const map_location &loc, const std::string &tod, ADJACENT_TERRAIN_TYPE const terrain_type); /** Updates the animation at a given tile. * Returns true if something has changed, and must be redrawn. * * @param loc the location to update * * @retval true: this tile must be redrawn. */ bool update_animation(const map_location &loc); /** Performs a "quick-rebuild" of the terrain in a given location. * The "quick-rebuild" is no proper rebuild: it only clears the * terrain cache for a given location, and replaces it with a single, * default image for this terrain. * * @param loc the location where to rebuild terrains */ void rebuild_terrain(const map_location &loc); /** Performs a complete rebuild of the list of terrain graphics * attached to a map. * Should be called when a terrain is changed in the map. */ void rebuild_all(); /** * An image variant. The in-memory representation of the [variant] * WML tag of the [image] WML tag. When an image only has one variant, * the [variant] tag may be omitted. */ struct rule_image_variant { /** Shorthand constructor for this structure */ rule_image_variant(const std::string &image_string, const std::string &tod) : image_string(image_string), image(), tod(tod) {}; /** A string representing either the filename for an image, or * a list of images, with an optional timing for each image. * Corresponds to the "name" parameter of the [variant] (or of * the [image]) WML tag. * * The timing string is in the following format (expressed in EBNF) * *@verbatim * ::= ( "," ) + * * ::= [ ":" ] * * Where represents the actual filename of an image, * and the number of milliseconds this image will last * in the animation. *@endverbatim */ std::string image_string; /** An animated image locator built according to the image string. * This will be the image locator which will actually * be returned to the user. */ animated image; /** * The time-of-day to which this variant applies. * Set to the empty string, this variant applies to all TODs. */ std::string tod; }; /** * A map associating a rule_image_variant to a string representing * the time of day. */ typedef std::map rule_image_variantlist; /** * Each terrain_graphics rule is associated a set of images, which are * applied on the terrain if the rule matches. An image is more than * graphics: it is graphics (with several possible tod-alternatives,) * and a position for these graphics. * The rule_image structure represents one such image. */ struct rule_image { rule_image(int layer, int x, int y, bool global_image=false, int center_x=-1, int center_y=-1); /** The layer of the image for horizontal layering */ int layer; /** The position of the image base (that is, the point where * the image reaches the floor) for vertical layering */ int basex, basey; /** A list of Time-Of-Day-related variants for this image */ rule_image_variantlist variants; /** Set to true if the image was defined as a child of the * [terrain_graphics] tag, set to false if it was defined as a * child of a [tile] tag */ bool global_image; /** The position where the center of the image base should be */ int center_x, center_y; }; /** * A shorthand notation for a vector of rule_images */ typedef std::vector rule_imagelist; /** * The in-memory representation of a [tile] WML rule * inside of a [terrain_graphics] WML rule. */ struct terrain_constraint { terrain_constraint() : loc(), terrain_types_match(), set_flag(), no_flag(), has_flag(), images() {}; terrain_constraint(map_location loc) : loc(loc), terrain_types_match(), set_flag(), no_flag(), has_flag(), images() {}; map_location loc; t_translation::t_match terrain_types_match; std::vector set_flag; std::vector no_flag; std::vector has_flag; rule_imagelist images; }; /** * Represents a tile of the game map, with all associated * builder-specific parameters: flags, images attached to this tile, * etc. An array of those tiles is built when terrains are built either * during construction, or upon calling the rebuild_all() method. */ struct tile { /** An ordered rule_image list */ typedef std::multimap ordered_ri_list; /** Contructor for the tile() structure */ tile(); /** Adds an image, extracted from an ordered rule_image list, * to the background or foreground image cache. * * @param tod The current time-of-day, to select between * images presenting several variants. * @param itor An iterator pointing to the rule_image where * to extract the image we wish to add to the * cache. */ void add_image_to_cache(const std::string &tod, ordered_ri_list::const_iterator itor); /** Rebuilds the whole image cache, for a given time-of-day. * Must be called when the time-of-day has changed, * to select the correct images. * * @param tod The current time-of-day */ void rebuild_cache(const std::string &tod); /** Clears all data in this tile, and resets the cache */ void clear(); /** The list of flags present in this tile */ std::set flags; /** The list of images associated to this tile, ordered by * their layer first and base-y position second. */ ordered_ri_list images; /** The list of images which are in front of the unit sprites, * attached to this tile. This member is considered a cache: * it is built once, and on-demand. */ imagelist images_foreground; /** The list of images which are behind the unit sprites, * attached to this tile. This member is considered a cache: * it is built once, and on-demand. */ imagelist images_background; /** * The time-of-day to which the image caches correspond. */ std::string last_tod; }; private: /** * The list of constraints attached to a terrain_graphics WML rule. */ typedef std::map constraint_set; /** * The in-memory representation of a [terrain_graphics] WML rule. */ struct building_rule { building_rule() : constraints(), location_constraints(), probability(0), precedence(0) {} /** * The set of [tile] constraints of this rule. */ constraint_set constraints; /** * The location on which this map may match. * Set to a valid map_location if the "x" and "y" parameters * of the [terrain_graphics] rule are set. */ map_location location_constraints; /** * The probability of this rule to match, when all conditions * are met. Defined if the "probability" parameter of the * [terrain_graphics] element is set. */ int probability; /** * The precedence of this rule. Used to order rules differently * that the order in which they appear. * Defined if the "precedence" parameter of the * [terrain_graphics] element is set. */ int precedence; }; /** * The map of "tile" structures corresponding to the level map. */ class tilemap { public: /** * Constructs a tilemap of dimensions x * y */ tilemap(int x, int y) : tiles_((x + 4) * (y + 4)), x_(x), y_(y) {} /** * Returns a reference to the tile which is at the position * pointed by loc. The location MUST be on the map! * * @param loc The location of the tile * * @return A reference to the tile at this location. * */ tile &operator[](const map_location &loc); /** * a const variant of operator[] */ const tile &operator[] (const map_location &loc) const; /** * Tests if a location is on the map. * * @param loc The location to test * * @return true if loc is on the map, false otherwise. */ bool on_map(const map_location &loc) const; /** * Resets the whole tile map */ void reset(); /** * Rebuilds the map to a new set of dimensions */ void reload(int x, int y); private: /** The map */ std::vector tiles_; /** The x dimension of the map */ int x_; /** The y dimension of the map */ int y_; }; /** * A set of building rules. In-memory representation * of the whole set of [terrain_graphics] rules. */ typedef std::multimap building_ruleset; /** * Tests for validity of a rule. A rule is considered valid if all its * images are present. This method is used, when building the ruleset, * to only add rules which are valid to the ruleset. * * @param rule The rule to test for validity * * @return true if the rule is valid, false if it is not. */ bool rule_valid(const building_rule &rule) const; /** * Starts the animation on a rule. * * @param rule The rule on which ot start animations * * @return true */ bool start_animation(building_rule &rule); /** * "Rotates" a constraint from a rule. * Takes a template constraint from a template rule, and creates * a constraint from this template, rotated to the given angle. * * On a constraint, the relative position of each rule, and the "base" * of each vertical images, are rotated according to the given angle. * * Template terrain constraints are defined like normal terrain * constraints, except that, flags, and image filenames, * may contain template strings of the form *@verbatim * @Rn, *@endverbatim * n being a number from 0 to 5. * See the rotate_rule method for more info. * * @param constraint A template constraint to rotate * @param angle An int, from 0 to 5, representing the rotation angle. */ terrain_constraint rotate(const terrain_constraint &constraint, int angle); /** * Replaces, in a given string, a token with its value. * * @param s The string in which to do the replacement * @param token The token to substitute * @param replacement The replacement string */ void replace_token(std::string &s, const std::string &token, const std::string& replacement); /** * Replaces, in a given rule_image, a token with its value. * The actual substitution is done in all variants of the given image. * * @param image The rule_image in which to do the replacement * @param token The token to substitute * @param replacement The replacement string */ void replace_token(rule_image &image, const std::string &token, const std::string& replacement); /** * Replaces, in a given rule_variant_image, a token with its value. * The actual substitution is done in the "image_string" parameter * of this rule_variant_image. * * @param variant The rule_variant_image in which to do the replacement * @param token The token to substitute * @param replacement The replacement string */ void replace_token(rule_image_variant &variant, const std::string &token, const std::string& replacement) { replace_token(variant.image_string, token, replacement); } /** * Replaces, in a given rule_imagelist, a token with its value. * The actual substitution is done in all rule_images contained * in the rule_imagelist. * * @param & The rule_imagelist in which to do the replacement * @param token The token to substitute * @param replacement The replacement string */ void replace_token(rule_imagelist &, const std::string &token, const std::string& replacement); /** * Replaces, in a given building_rule, a token with its value. * The actual substitution is done in the rule_imagelists contained * in all constraints of the building_rule, and in the flags * (has_flag, set_flag and no_flag) contained in all constraints * of the building_rule. * * @param rule The building_rule in which to do the replacement * @param token The token to substitute * @param replacement The replacement string */ void replace_token(building_rule &rule, const std::string &token, const std::string& replacement); /** * Rotates a template rule to a given angle, and returns the rotated rule. * * Template rules are defined like normal rules, except that: * * Flags and image filenames may contain template strings of the form *@verbatim * @Rn, n being a number from 0 to 5. *@endverbatim * * The rule contains the rotations=r0,r1,r2,r3,r4,r5, with r0 to r5 * being strings describing the 6 different positions, typically, * n, ne, se, s, sw, and nw (but maybe anything else.) * * A template rule will generate 6 rules, which are similar * to the template, except that: * * * The map of constraints ( [tile]s ) of this rule will be * rotated by an angle, of 0 to 5 pi / 6 * * * On the rule which is rotated to 0rad, the template strings *@verbatim * @R0, @R1, @R2, @R3, @R4, @R5, *@endverbatim * will be replaced by the corresponding r0, r1, r2, r3, r4, r5 * variables given in the rotations= element. * * * On the rule which is rotated to pi/3 rad, the template strings *@verbatim * @R0, @R1, @R2 etc. *@endverbatim * will be replaced by the corresponding * r1, r2, r3, r4, r5, r0 (note the shift in indices). * * * On the rule rotated 2pi/3, those will be replaced by * r2, r3, r4, r5, r0, r1 and so on. * */ building_rule rotate_rule(const building_rule &rule, int angle, const std::vector& angle_name); /** * Parses a "config" object, which should contains [image] children, * and adds the corresponding parsed rule_images to a rule_imagelist. * * @param images The rule_imagelist into which to add the parsed images. * @param cfg The WML configuration object to parse * @param global Whether those [image]s elements belong to a * [terrain_graphics] element, or to a [tile] child. * Set to true if those belong to a [terrain_graphics] * element. * @param dx The X coordinate of the constraint those images * apply to, relative to the start of the rule. Only * meaningful if global is set to false. * @param dy The Y coordinate of the constraint those images * apply to. */ void add_images_from_config(rule_imagelist &images, const config &cfg, bool global, int dx=0, int dy=0); /** * Creates a rule constraint object which matches a given list of * terrains, and adds it to the list of constraints of a rule. * * @param constraints The constraint set to which to add the constraint. * @param loc The location of the constraint * @param type The list of terrains this constraint will match * @param global_images A configuration object containing [image] tags * describing rule-global images. */ void add_constraints(constraint_set& constraints, const map_location &loc, const t_translation::t_match& type, const config& global_images); /** * Creates a rule constraint object from a config object and * adds it to the list of constraints of a rule. * * @param constraints The constraint set to which to add the constraint. * @param loc The location of the constraint * @param cfg The config object describing this constraint. * Usually, a [tile] child of a [terrain_graphics] rule. * @param global_images A configuration object containing [image] tags * describing rule-global images. */ void add_constraints(constraint_set& constraints, const map_location &loc, const config &cfg, const config& global_images); typedef std::multimap anchormap; /** * Parses a map string (the map= element of a [terrain_graphics] rule, * and adds constraints from this map to a building_rule. * * @param mapstring The map vector to parse * @param br The building rule into which to add the extracted * constraints * @param anchors A map where to put "anchors" extracted from the map. * @param global_images A config object representing the images defined * as direct children of the [terrain_graphics] rule. */ void parse_mapstring(const std::string &mapstring, struct building_rule &br, anchormap& anchors, const config& global_images); /** * Adds a rule to a ruleset. Checks for validity before adding the rule. * * @param rules The ruleset into which to add the rules. * @param rule The rule to add. */ void add_rule(building_ruleset& rules, building_rule &rule); /** * Adds a set of rules to a ruleset, from a template rule which spans * 6 rotations (or less if some of the rotated rules are invalid). * * @param rules The ruleset into which to add the rules. * @param tpl The template rule * @param rotations A comma-separated string containing the * 6 values for replacing rotation * template strings @verbatim (@Rn) @endverbatim */ void add_rotated_rules(building_ruleset& rules, building_rule& tpl, const std::string &rotations); /** * Parses a configuration object containing [terrain_graphics] rules, * and fills the building_rules_ member of the current class according * to those. * * @param cfg The configuration object to parse. */ void parse_config(const config &cfg); /** * Adds a builder rule for the _off^_usr tile, this tile only has 1 image. * * @param image The filename of the image */ void add_off_map_rule(const std::string& image); /** * Checks whether a terrain code matches a given list of terrain codes. * * @param tcode The terrain to check * @param terrains The terrain list agains which to check the terrain. * May contain the metacharacters * - '*' STAR, meaning "all terrains" * - '!' NOT, meaning "all terrains except those present in the list." * * @return returns true if "tcode" matches the list or the list is empty, * else false. */ bool terrain_matches(t_translation::t_terrain tcode, const t_translation::t_list& terrains) const { return terrains.empty()? true : t_translation::terrain_matches(tcode, terrains); } /** * Checks whether a terrain code matches a given list of terrain tcodes. * * @param tcode The terrain code to check * @param terrain The terrain match structure which to check the terrain. * See previous definition for more details. * * @return returns true if "tcode" matches the list or the list is empty, * else false. */ bool terrain_matches(t_translation::t_terrain tcode, const t_translation::t_match &terrain) const { return terrain.is_empty ? true : t_translation::terrain_matches(tcode, terrain); } /** * Checks whether a rule matches a given location in the map. * * @param rule The rule to check. * @param loc The location in the map where we want to check * whether the rule matches. * @param rule_index The index of the rule, relative to the start of * the rule list. Rule indices are used for seeding * the pseudo-random-number generator used for * probability calculations. * @param type_checked The constraint which we already know that its * terrain types matches. */ bool rule_matches(const building_rule &rule, const map_location &loc, const int rule_index, const constraint_set::const_iterator type_checked) const; /** * Applies a rule at a given location: applies the result of a * matching rule at a given location: attachs the images corresponding * to the rule, and sets the flags corresponding to the rule. * * @param rule The rule to apply * @param loc The location to which to apply the rule. */ void apply_rule(const building_rule &rule, const map_location &loc); /** * Calculates the list of terrains, and fills the tile_map_ member, * from the gamemap and the building_rules_. */ void build_terrains(); /** * A pointer to the gamemap class used in the current level. */ const gamemap* map_; /** * The tile_map_ for the current level, which is filled by the * build_terrains_ method to contain "tiles" representing images * attached to each tile. */ tilemap tile_map_; /** * Shorthand typedef for a map associating a list of locations to a terrain type. */ typedef std::map > terrain_by_type_map; /** * A map representing all locations whose terrain is of a given type. */ terrain_by_type_map terrain_by_type_; building_ruleset building_rules_; }; #endif