wesnoth/src/builder.hpp
2009-04-26 16:15:13 +00:00

749 lines
24 KiB
C++

/* $Id$ */
/*
Copyright (C) 2004 - 2009 by Philippe Plantier <ayin@anathas.org>
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 <map>
#include <set>
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<animated<image::locator> > 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
* <timing_string> ::= <timed_image> ( "," <timed_image> ) +
*
* <timed_image> ::= <image_name> [ ":" <timing> ]
*
* Where <image_name> represents the actual filename of an image,
* and <timing> 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::locator> 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<std::string, rule_image_variant> 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_image> 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<std::string> set_flag;
std::vector<std::string> no_flag;
std::vector<std::string> 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<int, const rule_image*> 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<std::string> 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<map_location, terrain_constraint> 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<tile> 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<int, building_rule> 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
* <code>@Rn</code>,
*@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
* <code>@Rn</code>, 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
* <strong>r1, r2, r3, r4, r5, r0</strong> (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<std::string>& 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<int, map_location> 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<t_translation::t_terrain, std::vector<map_location> > 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