map.hpp

Go to the documentation of this file.
00001 /* $Id: map.hpp 26769 2008-05-22 13:21:04Z mog $ */
00002 /*
00003    Copyright (C) 2003 - 2008 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 //! @file map.hpp 
00016 //! 
00017 
00018 #ifndef MAP_H_INCLUDED
00019 #define MAP_H_INCLUDED
00020 
00021 class config;
00022 class gamestatus;
00023 class unit;
00024 class vconfig;
00025 class unit_map;
00026 
00027 #include "terrain.hpp"
00028 
00029 #include "serialization/string_utils.hpp"
00030 
00031 #include <iostream>
00032 #include <map>
00033 #include <string>
00034 #include <vector>
00035 #include <set>
00036 
00037 #define MAX_MAP_AREA    65536
00038 
00039 //! Encapsulates the map of the game. 
00040 //! Although the game is hexagonal, the map is stored as a grid. 
00041 //! Each type of terrain is represented by a multiletter terrain code.
00042 //! @todo Update for new map-format.
00043 class gamemap
00044 {
00045 public:
00046 
00047     // The name of the terrain is the terrain itself, 
00048     // The underlying terrain is the name of the terrain for game-logic purposes. 
00049     // I.e. if the terrain is simply an alias, the underlying terrain name 
00050     // is the name of the terrain that it's aliased to.
00051     const t_translation::t_list& underlying_mvt_terrain(t_translation::t_terrain terrain) const;
00052     const t_translation::t_list& underlying_def_terrain(t_translation::t_terrain terrain) const;
00053     const t_translation::t_list& underlying_union_terrain(t_translation::t_terrain terrain) const;
00054 
00055     //! Throws exception if the map file is not in the correct format.
00056     struct incorrect_format_exception {
00057         incorrect_format_exception(const char* msg) : msg_(msg) {}
00058         const char* const msg_;
00059     };
00060 
00061     //! Represents a location on the map.
00062     struct location {
00063         //! Valid directions which can be moved in our hexagonal world.
00064         enum DIRECTION { NORTH, NORTH_EAST, SOUTH_EAST, SOUTH,
00065                          SOUTH_WEST, NORTH_WEST, NDIRECTIONS };
00066 
00067         static DIRECTION parse_direction(const std::string& str);
00068         //! Parse_directions takes a comma-separated list,
00069         //! and filters out any invalid directions
00070         static std::vector<DIRECTION> parse_directions(const std::string& str);
00071         static std::string write_direction(DIRECTION dir);
00072 
00073         location() : x(-1000), y(-1000) {}
00074         location(int x, int y) : x(x), y(y) {}
00075         location(const config& cfg, const variable_set *variables);
00076 
00077         void write(config& cfg) const;
00078 
00079         inline bool valid() const { return x >= 0 && y >= 0; }
00080 
00081         inline bool valid(const int parWidth, const int parHeight) const
00082         {
00083             return ((x >= 0) && (y >= 0) && (x < parWidth) && (y < parHeight));
00084         }
00085 
00086         int x, y;
00087         bool matches_range(const std::string& xloc, const std::string& yloc) const;
00088 
00089         // Inlining those for performance reasons
00090         bool operator<(const location& a) const { return x < a.x || (x == a.x && y < a.y); }
00091         bool operator==(const location& a) const { return x == a.x && y == a.y; }
00092         bool operator!=(const location& a) const { return !operator==(a); }
00093 
00094         // Adds an absolute location to a "delta" location
00095         location operator-() const;
00096         location operator+(const location &a) const;
00097         location &operator+=(const location &a);
00098         location operator-(const location &a) const;
00099         location &operator-=(const location &a);
00100 
00101         // Do n step in the direction d 
00102         location get_direction(DIRECTION d, int n = 1) const;
00103         DIRECTION get_relative_dir(location loc) const;
00104         static DIRECTION get_opposite_dir(DIRECTION d);
00105 
00106         static const location null_location;
00107     };
00108 
00109     //! Drawing order, copied from ordered_draw in display.hpp.
00110     //!
00111     //! This returns the order in which the units should be drawn so they overlap 
00112     //! propererly.
00113     static int get_drawing_order (const gamemap::location& loc )
00114             { return (loc.y * 2 + loc.x % 2) * 1024+loc.x; }
00115        
00116     const t_translation::t_list& underlying_mvt_terrain(const location& loc) const
00117         { return underlying_mvt_terrain(get_terrain(loc)); }
00118     const t_translation::t_list& underlying_def_terrain(const location& loc) const
00119         { return underlying_def_terrain(get_terrain(loc)); }
00120     const t_translation::t_list& underlying_union_terrain(const location& loc) const
00121         { return underlying_union_terrain(get_terrain(loc)); }
00122 
00123     bool is_village(t_translation::t_terrain terrain) const
00124         { return get_terrain_info(terrain).is_village(); }
00125     int gives_healing(t_translation::t_terrain terrain) const
00126         { return get_terrain_info(terrain).gives_healing(); }
00127     bool is_castle(t_translation::t_terrain terrain) const
00128         { return get_terrain_info(terrain).is_castle(); }
00129     bool is_keep(t_translation::t_terrain terrain) const
00130         { return get_terrain_info(terrain).is_keep(); }
00131 
00132     bool is_village(const location& loc) const
00133         { return on_board(loc) && is_village(get_terrain(loc)); }
00134     int gives_healing(const location& loc) const
00135         { return on_board(loc) ?  gives_healing(get_terrain(loc)) : 0; }
00136     bool is_castle(const location& loc) const
00137         { return on_board(loc) && is_castle(get_terrain(loc)); }
00138     bool is_keep(const location& loc) const
00139         { return on_board(loc) && is_keep(get_terrain(loc)); }
00140 
00141     enum tborder {
00142         NO_BORDER = 0,
00143         SINGLE_TILE_BORDER
00144         };
00145     
00146     enum tusage {
00147         IS_MAP,
00148         IS_MASK
00149         };
00150 
00151     enum tmerge_mode {
00152         BASE,
00153         OVERLAY,    
00154         BOTH
00155         };
00156 
00157     //! Loads a map, with the given terrain configuration.
00158     //! Data should be a series of lines, with each character 
00159     //! representing one hex on the map. 
00160     //! Starting locations are represented by numbers, 
00161     //! and will be of type keep.
00162     gamemap(const config& terrain_cfg, const std::string& data); //throw(incorrect_format_exception)
00163     void read(const std::string& data);
00164 
00165     std::string write() const;
00166 
00167     //! Overlays another map onto this one at the given position.
00168     void overlay(const gamemap& m, const config& rules, const int x=0, const int y=0);
00169 
00170     //! Effective dimensions of the map.
00171     int w() const { return w_; }
00172     int h() const { return h_; }
00173 
00174     //! Real dimension of the map, including borders
00175     int total_width()  const { return total_width_; }
00176     int total_height() const { return total_height_; }
00177 
00178     const t_translation::t_terrain operator[](const gamemap::location& loc) const
00179         { return tiles_[loc.x + border_size_][loc.y + border_size_]; }
00180 
00181     //! Looks up terrain at a particular location. 
00182     //! Hexes off the map may be looked up, 
00183     //! and their 'emulated' terrain will also be returned.
00184     //! This allows proper drawing of the edges of the map.
00185     t_translation::t_terrain get_terrain(const location& loc) const;
00186 
00187     //! Writes the terrain at loc to cfg.
00188     void write_terrain(const gamemap::location &loc, config& cfg) const;
00189 
00190 
00191     //! Manipulate starting positions of the different sides.
00192     const location& starting_position(int side) const;
00193     int is_starting_position(const location& loc) const;
00194     int num_valid_starting_positions() const;
00195 
00196     void set_starting_position(int side, const location& loc);
00197 
00198     //! Tell if a location is on the map. 
00199     //! Should be called before indexing using [].
00200     bool on_board(const location& loc, const bool include_border = false) const;
00201 
00202     //! Tell if the map is of 0 size.
00203     bool empty() const
00204     {
00205         return w_ == 0 || h_ == 0;
00206     }
00207 
00208     //! Return a list of the locations of villages on the map
00209     const std::vector<location>& villages() const { return villages_; }
00210 
00211     //! Get the corresponding terrain_type information object
00212     //! for a given type of terrain.
00213     const terrain_type& get_terrain_info(const t_translation::t_terrain terrain) const;
00214 
00215     //! Shortcut to get_terrain_info(get_terrain(loc)).
00216     const terrain_type& get_terrain_info(const location &loc) const
00217         { return get_terrain_info(get_terrain(loc)); }
00218 
00219     //! Gets the list of terrains.
00220     const t_translation::t_list& get_terrain_list() const
00221         { return terrainList_; }
00222 
00223     //! Clobbers over the terrain at location 'loc', with the given terrain.
00224     //! Uses mode and replace_if_failed like merge_terrains().
00225     void set_terrain(const location& loc, const t_translation::t_terrain terrain, const tmerge_mode mode=BOTH, bool replace_if_failed = false);
00226 
00227     //! Returns a list of the frequencies of different terrain types on the map, 
00228     //! with terrain nearer the center getting weighted higher.
00229     const std::map<t_translation::t_terrain, size_t>& get_weighted_terrain_frequencies() const;
00230     //! Remove the cached border terrain at loc. 
00231     //! Needed by the editor to make tiles at the border update correctly 
00232     //! when drawing other tiles.
00233     void remove_from_border_cache(const location &loc)
00234         { borderCache_.erase(loc); }
00235 
00236     //! Maximum number of players supported. 
00237     //! Warning: when you increase this, you need to add 
00238     //! more definitions to the team_colors.cfg file.
00239     enum { MAX_PLAYERS = 9 };
00240 
00241     //! Returns the usage of the map.
00242     tusage get_usage() const { return usage_; }
00243 
00244     //! The default map header, needed for maps created with 
00245     //! terrain_translation::write_game_map().
00246     static const std::string default_map_header;
00247     //! The default border style for a map
00248     static const tborder default_border;
00249 
00250     //! Tries to merge old and new terrain using the merge_settings config
00251     //! Relevant parameters are "layer" and "replace_conflicting"
00252     //! "layer" specifies the layer that should be replaced (base or overlay, default is both). 
00253     //! If "replace_conflicting" is true the new terrain will replace the old one if merging failed
00254     //! (using the default base if new terrain is an overlay terrain)
00255     //! Will return the resulting terrain or NONE_TERRAIN if merging failed
00256     t_translation::t_terrain merge_terrains(const t_translation::t_terrain old_t, const t_translation::t_terrain new_t, const tmerge_mode mode, bool replace_if_failed = false);
00257 
00258 protected:
00259     t_translation::t_map tiles_;
00260     //! The size of the starting positions array is MAX_PLAYERS + 1, 
00261     //! because the positions themselves are numbered from 1.
00262     location startingPositions_[MAX_PLAYERS+1];
00263 
00264     /**
00265      * Clears the border cache, needed for the editor
00266      */
00267     void clear_border_cache() { borderCache_.clear(); }
00268 
00269 private:
00270     int num_starting_positions() const
00271         { return sizeof(startingPositions_)/sizeof(*startingPositions_); }
00272 
00273     //! Allows lookup of terrain at a particular location.
00274     const t_translation::t_list operator[](int index) const
00275         { return tiles_[index + border_size_]; }
00276 
00277     //! Tries to find out if "terrain" can be created by combining two existing terrains
00278     //! Will add the resulting terrain to the terrain list if successfull
00279     bool try_merge_terrains(const t_translation::t_terrain terrain);
00280 
00281     t_translation::t_list terrainList_;
00282     std::map<t_translation::t_terrain, terrain_type> tcodeToTerrain_;
00283     std::vector<location> villages_;
00284 
00285     mutable std::map<location, t_translation::t_terrain> borderCache_;
00286     mutable std::map<t_translation::t_terrain, size_t> terrainFrequencyCache_;
00287 
00288     //! Sizes of the map area.
00289     int w_;
00290     int h_;
00291 
00292     //! Sizes of the map including the borders.
00293     int total_width_;
00294     int total_height_;
00295 
00296     //! The size of the border around the map.
00297     int border_size_;
00298     //! The kind of map is being loaded.
00299     tusage usage_;
00300 };
00301 
00302 class viewpoint
00303 {
00304 public:
00305     virtual bool shrouded(const gamemap::location& loc) const = 0;
00306     virtual bool fogged(const gamemap::location& loc) const = 0;
00307     virtual ~viewpoint() {};
00308 };
00309 
00310 //! Parses ranges of locations into a vector of locations.
00311 std::vector<gamemap::location> parse_location_range(const std::string& xvals,
00312     const std::string& yvals, const gamemap *const map=NULL);
00313 
00314 //! Dumps a position on a stream, for debug purposes.
00315 std::ostream &operator<<(std::ostream &s, gamemap::location const &l);
00316 
00317 #endif

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs