commit map border change for mordante

now only wmllint --maplift has to be run on data/, could you do this esr?
This commit is contained in:
Nils Kneuper 2007-10-26 16:02:04 +00:00
parent 2425e17fde
commit c588445335
23 changed files with 263 additions and 110 deletions

View file

@ -35,6 +35,7 @@ Version 1.3.9+svn:
* WML engine:
* new key "contains=" in [variable] conditions to check the presence of a
substring in a variable value
* maps now have a user definable border
* miscellaneous and bug fixes:
Version 1.3.9:

View file

@ -1885,7 +1885,7 @@ size_t move_unit(game_display* disp, const game_data& gamedata,
std::vector<gamemap::location>::const_iterator step;
std::string ambushed_string;
for(step = route.begin()+1; step != route.end(); ++step) {
const t_translation::t_letter terrain = map[step->x][step->y];
const t_translation::t_letter terrain = map[*step];
const unit_map::const_iterator enemy_unit = units.find(*step);
const bool skirmisher = ui->second.get_ability_bool("skirmisher",*step);
@ -1974,7 +1974,7 @@ size_t move_unit(game_display* disp, const game_data& gamedata,
gamemap::location const &loc = steps.back();
if (units.count(loc) == 0)
break;
moves_left += ui->second.movement_cost(map[loc.x][loc.y]);
moves_left += ui->second.movement_cost(map[loc]);
steps.pop_back();
}
@ -2158,7 +2158,7 @@ bool unit_can_move(const gamemap::location& loc, const unit_map& units,
}
}
if(u.movement_cost(map[locs[n].x][locs[n].y]) <= u.movement_left()) {
if(u.movement_cost(map[locs[n]]) <= u.movement_left()) {
return true;
}
}

View file

@ -622,7 +622,7 @@ double ai::power_projection(const gamemap::location& loc, const move_map& dstsr
continue;
}
const t_translation::t_letter terrain = map_[locs[i].x][locs[i].y];
const t_translation::t_letter terrain = map_[locs[i]];
typedef move_map::const_iterator Itor;
typedef std::pair<Itor,Itor> Range;

View file

@ -59,7 +59,7 @@ struct move_cost_calculator : cost_calculator
*/
wassert(map_.on_board(loc));
const t_translation::t_letter terrain = map_[loc.x][loc.y];
const t_translation::t_letter terrain = map_[loc];
const double modifier = 1.0; //move_type_.defense_modifier(map_,terrain);
const double move_cost = unit_.movement_cost(terrain);//move_type_[terrain];

View file

@ -39,6 +39,9 @@ cave_map_generator::cave_map_generator(const config* cfg) : wall_(t_translation:
width_ = atoi((*cfg_)["map_width"].c_str());
height_ = atoi((*cfg_)["map_height"].c_str());
width_ += 2 * gamemap::default_border;
height_ += 2 * gamemap::default_border;
village_density_ = atoi((*cfg_)["village_density"].c_str());
const int r = rand()%100;
@ -103,7 +106,8 @@ config cave_map_generator::create_scenario(const std::vector<std::string>& /*arg
LOG_NG << "outputting map....\n";
res_["map_data"] = t_translation::write_game_map(map_, starting_positions_);
res_["map_data"] = gamemap::default_map_header +
t_translation::write_game_map(map_, starting_positions_);
LOG_NG << "returning result...\n";

View file

@ -422,7 +422,7 @@ void save_preview_pane::draw_contents()
#else
const int minimap_size = 100;
#endif
map_->read(map_data);
map_->read(map_data, gamemap::SINGLE_TILE_BORDER, gamemap::IS_MAP);
map_surf = image::getMinimap(minimap_size, minimap_size, *map_);
if(map_surf != NULL) {
@ -579,7 +579,7 @@ std::string load_game_dialog(display& disp, const config& game_config, const gam
gui::menu::basic_sorter sorter;
sorter.set_alpha_sort(0).set_id_sort(1);
gamemap map_obj(game_config, "");
gamemap map_obj(game_config, "", gamemap::SINGLE_TILE_BORDER, gamemap::IS_MAP);
save_preview_pane save_preview(disp.video(),game_config,&map_obj,data,games,summaries);

View file

@ -1179,6 +1179,9 @@ void display::draw_minimap()
const SDL_Rect& area = minimap_area();
if(minimap_ == NULL || minimap_->w > area.w || minimap_->h > area.h) {
minimap_ = image::getMinimap(area.w, area.h, map_, viewpoint_);
if(minimap_ == NULL) {
return;
}
}
const surface screen(screen_.getSurface());

View file

@ -339,13 +339,13 @@ void map_editor::handle_mouse_button_event(const SDL_MouseButtonEvent &event,
}
if (button == SDL_BUTTON_LEFT) {
gamemap::location hex_clicked = gui_.hex_clicked_on(mousex, mousey);
if (map_.on_board(hex_clicked)) {
if (map_.on_board(hex_clicked, true)) {
left_click(hex_clicked);
}
}
if (button == SDL_BUTTON_RIGHT) {
gamemap::location hex_clicked = gui_.hex_clicked_on(mousex, mousey);
if (map_.on_board(hex_clicked)) {
if (map_.on_board(hex_clicked, true)) {
right_click(hex_clicked);
}
}
@ -489,7 +489,7 @@ void map_editor::change_language() {
hotkey::load_descriptions();
// To reload the terrain names, we need to reload the configuration file
editormap new_map(game_config_, map_.write());
editormap new_map(game_config_, map_.write(), gamemap::SINGLE_TILE_BORDER, gamemap::IS_MAP);
map_ = new_map;
// Update the selected terrain strings
@ -813,7 +813,7 @@ void map_editor::paste_buffer(const map_buffer &buffer, const gamemap::location
//the addition of locations is not commutative !
gamemap::location target = it->offset + loc;
if (map_.on_board(target)) {
if (map_.on_board(target, true)) {
undo_action.add_terrain(map_.get_terrain(target), it->terrain, target);
map_.set_terrain(target, it->terrain);
const int start_side = it->starting_side;
@ -851,7 +851,7 @@ void map_editor::perform_fill_hexes(std::set<gamemap::location> &fill_hexes,
const t_translation::t_letter terrain, map_undo_action &undo_action) {
std::set<gamemap::location>::const_iterator it;
for (it = fill_hexes.begin(); it != fill_hexes.end(); it++) {
if (map_.on_board(*it)) {
if (map_.on_board(*it, true)) {
undo_action.add_terrain(map_.get_terrain(*it), terrain, *it);
map_.set_terrain(*it, terrain);
}
@ -1166,7 +1166,7 @@ void map_editor::left_button_down(const int mousex, const int mousey) {
std::set<gamemap::location>::const_iterator it;
for (it = selected_hexes_.begin(); it != selected_hexes_.end(); it++) {
const gamemap::location hl_loc = (*it-selection_move_start_) + hex;
if (map_.on_board(hl_loc)) {
if (map_.on_board(hl_loc, true)) {
gui_.add_highlighted_loc(hl_loc);
}
}
@ -1175,22 +1175,21 @@ void map_editor::left_button_down(const int mousex, const int mousey) {
void map_editor::draw_on_mouseover_hexes(const t_translation::t_letter terrain) {
const gamemap::location hex = selected_hex_;
if(map_.on_board(hex)) {
const t_translation::t_letter old_terrain = map_[hex.x][hex.y];
if(map_.on_board(hex, true)) {
const t_translation::t_letter old_terrain = map_[hex];
// Optimize for common case
if(brush_.selected_brush_size() == 1) {
if(terrain != old_terrain) {
draw_terrain(terrain, hex);
}
}
else {
} else {
std::vector<gamemap::location> locs =
get_tiles(map_, hex, brush_.selected_brush_size());
map_undo_action action;
std::vector<gamemap::location> to_invalidate;
for(std::vector<gamemap::location>::const_iterator it = locs.begin();
it != locs.end(); ++it) {
if(terrain != map_[it->x][it->y]) {
if(terrain != map_.get_terrain(*it)) {
to_invalidate.push_back(*it);
action.add_terrain(map_.get_terrain(*it), terrain, *it);
map_.set_terrain(*it, terrain);
@ -1264,7 +1263,7 @@ void map_editor::invalidate_all_and_adjacent(const std::vector<gamemap::location
}
std::set<gamemap::location>::const_iterator its;
for (its = to_invalidate.begin(); its != to_invalidate.end(); its++) {
if (!map_.on_board(*its)) {
if (!map_.on_board(*its, true)) {
t_translation::t_letter terrain_before = map_.get_terrain(*its);
map_.remove_from_border_cache(*its);
t_translation::t_letter terrain_after = map_.get_terrain(*its);

View file

@ -59,7 +59,7 @@ void editor_display::draw(bool update,bool force)
for(it = invalidated_.begin(); it != invalidated_.end(); ++it) {
image::TYPE image_type = image::SCALED_TO_HEX;
if(*it == mouseoverHex_ && map_.on_board(mouseoverHex_)) {
if(*it == mouseoverHex_ && map_.on_board(mouseoverHex_, true)) {
image_type = image::BRIGHTENED;
}
else if (highlighted_locations_.find(*it) != highlighted_locations_.end()) {
@ -90,9 +90,9 @@ void editor_display::draw(bool update,bool force)
}
// Paint selection and mouseover overlays
if(*it == selectedHex_ && map_.on_board(selectedHex_) && selected_hex_overlay_ != NULL)
if(*it == selectedHex_ && map_.on_board(selectedHex_, true) && selected_hex_overlay_ != NULL)
tile_stack_append(selected_hex_overlay_);
if(*it == mouseoverHex_ && map_.on_board(mouseoverHex_) && mouseover_hex_overlay_ != NULL)
if(*it == mouseoverHex_ && map_.on_board(mouseoverHex_, true) && mouseover_hex_overlay_ != NULL)
tile_stack_append(mouseover_hex_overlay_);
tile_stack_render(xpos, ypos);
@ -104,7 +104,7 @@ void editor_display::draw(bool update,bool force)
}
// Fill in the terrain report
if(map_.on_board(mouseoverHex_)) {
if(map_.on_board(mouseoverHex_, true)) {
const t_translation::t_letter terrain = map_.get_terrain(mouseoverHex_);
const t_translation::t_list& underlying = map_.underlying_union_terrain(terrain);

View file

@ -301,7 +301,7 @@ int main(int argc, char** argv)
::init_textdomains(cfg);
if(mapdata.empty()) {
mapdata = map_editor::new_map(20, 20, t_translation::GRASS_LAND);
mapdata = map_editor::new_map(22, 22, t_translation::GRASS_LAND);
}
srand(time(NULL));
@ -319,7 +319,8 @@ int main(int argc, char** argv)
while (!done) {
try {
std::cerr << "creating map...\n";
editormap map(cfg, mapdata);
//! @todo allow the editor to also create mask maps
editormap map(cfg, mapdata, gamemap::SINGLE_TILE_BORDER, gamemap::IS_MAP);
const config dummy_cfg;
editor_display gui(video, map, *theme_cfg, cfg, dummy_cfg);

View file

@ -155,15 +155,13 @@ void editormap::swap_starting_position(const size_t x1, const size_t y1,
void editormap::add_tiles_right(
const unsigned count, const t_translation::t_letter& filler)
{
// std::cerr << "add right " << count << '\n';
for(size_t x = 1; x <= count; ++x) {
t_translation::t_list one_row(h());
t_translation::t_list one_row(total_height_);
for(size_t y = 0; y < tiles_[1].size(); ++y) {
one_row[y] =
filler != t_translation::NONE_TERRAIN ?
filler :
get_terrain(gamemap::location(x - 1, y));
tiles_[x - 1][y];
wassert(one_row[y] != t_translation::NONE_TERRAIN);
}
@ -174,15 +172,13 @@ void editormap::add_tiles_right(
void editormap::add_tiles_left(
const unsigned count, const t_translation::t_letter& filler)
{
// std::cerr << "add left " << count << '\n';
for(size_t i = 1; i <= count; ++i) {
t_translation::t_list one_row(h());
t_translation::t_list one_row(total_height_);
for(size_t y = 0; y < tiles_[1].size(); ++y) {
one_row[y] =
filler != t_translation::NONE_TERRAIN ?
filler :
get_terrain(gamemap::location(-1, y));
tiles_[0][y];
wassert(one_row[y] != t_translation::NONE_TERRAIN);
}
@ -193,8 +189,6 @@ void editormap::add_tiles_left(
void editormap::remove_tiles_right(const unsigned count)
{
// std::cerr << "remove right " << count << '\n';
if(count > tiles_.size()) {
std::stringstream sstr;
sstr << _("Can't resize the map, the requested size is bigger "
@ -209,8 +203,6 @@ void editormap::remove_tiles_right(const unsigned count)
void editormap::remove_tiles_left(const unsigned count)
{
// std::cerr << "remove left " << count << '\n';
if(count > tiles_.size()) {
std::stringstream sstr;
sstr << _("Can't resize the map, the requested size is bigger "
@ -226,14 +218,12 @@ void editormap::remove_tiles_left(const unsigned count)
void editormap::add_tiles_top(
const unsigned count, const t_translation::t_letter& filler)
{
// std::cerr << "add top " << count << '\n';
for(size_t i = 1; i <= count; ++i) {
for(size_t y = 0; y < tiles_.size(); ++y) {
t_translation::t_letter terrain =
filler != t_translation::NONE_TERRAIN ?
filler :
get_terrain(gamemap::location(y, -1));
tiles_[y][0];
wassert(terrain != t_translation::NONE_TERRAIN);
tiles_[y].insert(tiles_[y].begin(), 1, terrain);
@ -245,14 +235,12 @@ void editormap::add_tiles_top(
void editormap::add_tiles_bottom(
const unsigned count, const t_translation::t_letter& filler)
{
// std::cerr << "add bottom " << count << '\n';
for(size_t i = 1; i <= count; ++i) {
for(size_t x = 0; x < tiles_.size(); ++x) {
t_translation::t_letter terrain =
filler != t_translation::NONE_TERRAIN ?
filler :
get_terrain(gamemap::location(x, i - 1));
tiles_[x][i - 1];
wassert(terrain != t_translation::NONE_TERRAIN);
tiles_[x].push_back(terrain);
@ -262,8 +250,6 @@ void editormap::add_tiles_bottom(
void editormap::remove_tiles_top(const unsigned count)
{
// std::cerr << "remove top " << count << '\n';
if(count > tiles_[0].size()) {
std::stringstream sstr;
sstr << _("Can't resize the map, the requested size is bigger "
@ -280,8 +266,6 @@ void editormap::remove_tiles_top(const unsigned count)
void editormap::remove_tiles_bottom(const unsigned count)
{
// std::cerr << "remove bottom " << count << '\n';
if(count > tiles_[0].size()) {
std::stringstream sstr;
sstr << _("Can't resize the map, the requested size is bigger "
@ -319,7 +303,7 @@ std::vector<gamemap::location> get_tiles(const gamemap &map,
for (i = 0; i < 6; i++) {
for (unsigned int j = 1; j <= d; j++) {
loc = loc.get_direction(direction[i], 1);
if (map.on_board(loc)) {
if (map.on_board(loc, true)) {
res.push_back(loc);
}
}
@ -368,7 +352,7 @@ std::set<gamemap::location> get_component(const gamemap &map,
std::vector<gamemap::location> adj = get_tiles(map, loc, 2);
for (std::vector<gamemap::location>::iterator it2 = adj.begin();
it2 != adj.end(); it2++) {
if (map.on_board(*it2) && map.get_terrain(*it2) == terrain_to_fill
if (map.on_board(*it2, true) && map.get_terrain(*it2) == terrain_to_fill
&& filled.find(*it2) == filled.end()) {
to_fill.insert(*it2);
}
@ -394,7 +378,7 @@ bool valid_mapdata(const std::string &data, const config &cfg) {
// Create a map and see if we get an exception. Not very efficient,
// but simple as things are implemented now.
try {
const gamemap m(cfg, data);
const gamemap m(cfg, data, gamemap::SINGLE_TILE_BORDER, gamemap::IS_MAP);
// Having a zero size map may cause floating point exceptions
// at some places later on.
res = m.w() != 0 && m.h() != 0;
@ -410,7 +394,10 @@ std::string new_map(const size_t width, const size_t height, const t_translation
const t_translation::t_list column(height, filler);
const t_translation::t_map map(width, column);
return t_translation::write_game_map(map);
// @todo these should be parameters
const std::string& header = "border_size = 1\nusage = map";
return header + "\n\n" + t_translation::write_game_map(map);
}

View file

@ -38,7 +38,9 @@ enum FLIP_AXIS {NO_FLIP, FLIP_X, FLIP_Y};
class editormap : public gamemap
{
public:
editormap(const config& terrain_cfg, const std::string& data):gamemap(terrain_cfg,data){};
editormap(const config& terrain_cfg, const std::string& data,
const tborder border_tiles, const tusage usage) :
gamemap(terrain_cfg, data, border_tiles, usage){};
~editormap(){};
/**

View file

@ -290,7 +290,7 @@ game_display& game_controller::disp()
static unit_map dummy_umap;
static config dummy_cfg;
static gamemap dummy_map(dummy_cfg, "");
static gamemap dummy_map(dummy_cfg, "", gamemap::SINGLE_TILE_BORDER, gamemap::IS_MAP);
static gamestatus dummy_status(dummy_cfg, 0);
static std::vector<team> dummy_teams;
disp_.assign(new game_display(dummy_umap, video_, dummy_map, dummy_status,

View file

@ -1350,7 +1350,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
gamemap mask(*game_map);
try {
mask.read(cfg["mask"]);
mask.read(cfg["mask"], gamemap::NO_BORDER, gamemap::IS_MASK);
} catch(gamemap::incorrect_format_exception&) {
ERR_NG << "terrain mask is in the incorrect format, and couldn't be applied\n";
return rval;

View file

@ -442,7 +442,7 @@ Units cannot be killed by poison alone. The poison will not reduce it below 1 HP
break;
}
const t_translation::t_letter terrain = map[mouseover.x][mouseover.y];
const t_translation::t_letter terrain = map[mouseover];
if (terrain == t_translation::OFF_MAP_USER)
break;

View file

@ -24,6 +24,7 @@
#include "util.hpp"
#include "wassert.hpp"
#include "serialization/string_utils.hpp"
#include "serialization/parser.hpp"
#include <algorithm>
#include <cctype>
@ -41,6 +42,8 @@ std::ostream &operator<<(std::ostream &s, gamemap::location const &l) {
gamemap::location gamemap::location::null_location;
const std::string gamemap::default_map_header = "usage = map\nborder_size=1\n\n";
const t_translation::t_list& gamemap::underlying_mvt_terrain(t_translation::t_letter terrain) const
{
const std::map<t_translation::t_letter,terrain_type>::const_iterator i =
@ -274,32 +277,131 @@ gamemap::location::DIRECTION gamemap::location::get_opposite_dir(gamemap::locati
}
}
gamemap::gamemap(const config& cfg, const std::string& data) :
//! gamemap constructor
//!
//! @param cfg the game config
//! @param data the mapdata to load
//! @param border_tiles the type of border the map has
//! @todo parameter will be removed in 1.3.14
//! @param usage the type of map it being read
//! @todo parameter will be removed in 1.3.14
gamemap::gamemap(const config& cfg, const std::string& data,
const tborder border_tiles, const tusage usage) :
tiles_(1),
total_width_(0),
total_height_(0),
terrainList_(),
letterToTerrain_(),
villages_(),
borderCache_(),
terrainFrequencyCache_(),
w_(-1),
h_(-1)
h_(-1),
border_size_(border_tiles),
usage_(usage)
{
LOG_G << "loading map: '" << data << "'\n";
const config::child_list& terrains = cfg.get_children("terrain");
create_terrain_maps(terrains,terrainList_,letterToTerrain_);
read(data);
read(data, border_tiles, usage);
}
void gamemap::read(const std::string& data)
//! Reads a map
//!
//! @param data the mapdata to load
//! @param border_tiles the type of border the map has
//! @todo parameter will be removed in 1.3.14
//! @param usage the type of map it being read
//! @todo parameter will be removed in 1.3.14
void gamemap::read(const std::string& data, const tborder border_tiles, const tusage usage)
{
// Initial stuff
tiles_.clear();
villages_.clear();
std::fill(startingPositions_,startingPositions_+sizeof(startingPositions_)/sizeof(*startingPositions_),location());
std::fill(startingPositions_, startingPositions_ +
sizeof(startingPositions_) / sizeof(*startingPositions_), location());
std::map<int, t_translation::coordinate> starting_positions;
if(data.empty()) {
return;
}
// Test whether there's a header section
const size_t header_offset = data.find("\n\n");
const size_t comma_offset = data.find(",");
bool add_tiles = false;
std::string map;
// the header shouldn't contain comma's so if the comma is found before the header
// we hit a \n\n inside or after a map. This is no header so don't parse it as it would be.
if(header_offset == std::string::npos || comma_offset < header_offset) {
// The cutoff for backwards compatibility is longer as normal,
// because after the compatibility is removed the minimum
// savegame version should be set to 1.3.10
lg::wml_error<<"A map without a header section is deprecated, support will be removed in 1.3.14\n";
border_size_ = border_tiles;
usage_ = usage;
add_tiles = (border_size_ != 0);
map = data;
} else {
std::string header_str(std::string(data, 0, header_offset + 1));
config header;
::read(header, header_str);
border_size_ = lexical_cast_default<int>(header["border_size"], 0);
const std::string usage = header["usage"];
if(usage == "map") {
usage_ = IS_MAP;
} else if(usage == "mask") {
usage_ = IS_MASK;
} else if(usage == "") {
throw incorrect_format_exception("Map has a header but no usage");
} else {
std::string msg = "Map has a header but an unknown usage:" + usage;
throw incorrect_format_exception(msg.c_str());
}
map = std::string(data, header_offset + 2);
}
try {
tiles_ = t_translation::read_game_map(data, starting_positions);
tiles_ = t_translation::read_game_map(map, starting_positions);
if(border_tiles && add_tiles) {
// deprecated code remove at 1.3.14, there already has been a warning.
// add the tiles at the top and bottom
for(std::vector<std::vector<t_translation::t_letter> >::iterator itor =
tiles_.begin(); itor != tiles_.end(); ++itor) {
itor->insert(itor->begin(), t_translation::OFF_MAP_USER);
itor->push_back(t_translation::OFF_MAP_USER);
}
// add the tiles at the left and right side
if(tiles_.size() != 0) {
std::vector<t_translation::t_letter>
column(tiles_[0].size(), t_translation::OFF_MAP_USER);
tiles_.insert(tiles_.begin(), column);
tiles_.push_back(column);
}
} else {
// Fix the starting positions, this code will still be needed after
// 1.3.14, but can be merged with the conversion of the starting
// positions array.
for(std::map<int, t_translation::coordinate>::iterator itor1 =
starting_positions.begin();
itor1 != starting_positions.end(); ++itor1) {
--(itor1->second.x);
--(itor1->second.y);
}
}
} catch(t_translation::error& e) {
// We re-throw the error but as map error.
// Since all codepaths test for this, it's the least work.
@ -317,7 +419,8 @@ void gamemap::read(const std::string& data)
// so the offset 0 in the array is never used.
if(itor->first < 1 || itor->first >= STARTING_POSITIONS) {
ERR_CF << "Starting position " << itor->first << " out of range\n";
throw incorrect_format_exception("Illegal starting position found in map. The scenario cannot be loaded.");
throw incorrect_format_exception("Illegal starting position found"
" in map. The scenario cannot be loaded.");
}
// Add to the starting position array
@ -325,12 +428,13 @@ void gamemap::read(const std::string& data)
}
// Post processing on the map
const int width = tiles_.size();
const int height = width > 0 ? tiles_[0].size() : 0;
w_ = width;
h_ = height;
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
total_width_ = tiles_.size();
total_height_ = total_width_ > 0 ? tiles_[0].size() : 0;
w_ = total_width_ - 2 * border_size_;
h_ = total_height_ - 2 * border_size_;
for(int x = 0; x < total_width_; ++x) {
for(int y = 0; y < total_height_; ++y) {
// Is the terrain valid?
if(letterToTerrain_.count(tiles_[x][y]) == 0) {
@ -340,7 +444,9 @@ void gamemap::read(const std::string& data)
}
// Is it a village?
if(is_village(tiles_[x][y])) {
if(x >= border_size_ && x < w_ && y >= border_size_ && y < h_ &&
is_village(tiles_[x][y])) {
villages_.push_back(location(x, y));
}
}
@ -362,7 +468,10 @@ std::string gamemap::write() const
}
// Let the low level convertor do the conversion
return t_translation::write_game_map(tiles_, starting_positions);
const std::string& data = t_translation::write_game_map(tiles_, starting_positions);
const std::string& header = "border_size = " + lexical_cast<std::string>(border_size_)
+ "\nusage = " + (usage_ == IS_MAP ? "map" : "mask");
return header + "\n\n" + data;
}
void gamemap::overlay(const gamemap& m, const config& rules_cfg, const int xpos, const int ypos)
@ -381,8 +490,8 @@ void gamemap::overlay(const gamemap& m, const config& rules_cfg, const int xpos,
if (y2 < 0 || y2 >= h()) {
continue;
}
const t_translation::t_letter t = m[x1][y1];
const t_translation::t_letter current = (*this)[x2][y2];
const t_translation::t_letter t = m[x1][y1 + m.border_size_];
const t_translation::t_letter current = (*this)[x2][y2 + border_size_];
if(t == t_translation::FOGGED || t == t_translation::VOID_TERRAIN) {
continue;
@ -450,8 +559,8 @@ void gamemap::overlay(const gamemap& m, const config& rules_cfg, const int xpos,
t_translation::t_letter gamemap::get_terrain(const gamemap::location& loc) const
{
if(on_board(loc)) {
return tiles_[loc.x][loc.y];
if(on_board(loc, true)) {
return tiles_[loc.x + border_size_][loc.y + border_size_];
}
const std::map<location, t_translation::t_letter>::const_iterator itor = borderCache_.find(loc);
@ -546,6 +655,18 @@ void gamemap::set_starting_position(int side, const gamemap::location& loc)
}
}
bool gamemap::on_board(const location& loc, const bool include_border) const
{
if(!include_border) {
return loc.valid() && loc.x < w_ && loc.y < h_;
} else if(tiles_.empty()) {
return false;
} else {
return loc.x >= (0 - border_size_) && loc.x < (w_ + border_size_) &&
loc.y >= (0 - border_size_) && loc.y < (h_ + border_size_);
}
}
const terrain_type& gamemap::get_terrain_info(const t_translation::t_letter terrain) const
{
static const terrain_type default_terrain;
@ -620,8 +741,10 @@ bool gamemap::location::matches_range(const std::string& xloc, const std::string
void gamemap::set_terrain(const gamemap::location& loc, const t_translation::t_letter terrain)
{
if(!on_board(loc))
if(!on_board(loc, true)) {
// off the map ignore request
return;
}
const bool old_village = is_village(loc);
const bool new_village = is_village(terrain);
@ -632,14 +755,9 @@ void gamemap::set_terrain(const gamemap::location& loc, const t_translation::t_l
villages_.push_back(loc);
}
tiles_[loc.x][loc.y] = terrain;
// Temp hack, since the border can have multiple tiles.
// Depending on each other, every change has to invalidate the cache.
// Once the border tiles are part of the map, this hack is no longer required.
borderCache_.clear();
return;
tiles_[loc.x + border_size_][loc.y + border_size_] = terrain;
// update the off map autogenerated tiles
location adj[6];
get_adjacent_tiles(loc,adj);

View file

@ -124,25 +124,39 @@ public:
bool is_keep(const location& loc) const
{ return on_board(loc) && is_keep(get_terrain(loc)); }
enum tborder {
NO_BORDER = 0,
SINGLE_TILE_BORDER
};
enum tusage {
IS_MAP,
IS_MASK
};
//loads a map, with the given terrain configuration.
//data should be a series of lines, with each character representing
//one hex on the map. Starting locations are represented by numbers,
//and will be of type keep.
gamemap(const config& terrain_cfg, const std::string& data); //throw(incorrect_format_exception)
void read(const std::string& data);
gamemap(const config& terrain_cfg, const std::string& data,
const tborder border_tiles, const tusage usage); //throw(incorrect_format_exception)
void read(const std::string& data, const tborder border_tiles, const tusage usage);
std::string write() const;
//overlays another map onto this one at the given position.
void overlay(const gamemap& m, const config& rules, int x=0, int y=0);
//dimensions of the map.
// effective dimensions of the map.
int w() const { return w_; }
int h() const { return h_; }
//allows lookup of terrain at a particular location.
const t_translation::t_list& operator[](int index) const
{ return tiles_[index]; }
// real dimension of the map, including borders
int total_width() const { return total_width_; }
int total_height() const { return total_height_; }
const t_translation::t_letter operator[](const gamemap::location& loc) const
{ return tiles_[loc.x + border_size_][loc.y + border_size_]; }
//looks up terrain at a particular location. Hexes off the map
//may be looked up, and their 'emulated' terrain will also be returned.
@ -162,10 +176,7 @@ public:
//function which, given a location, will tell if that location is
//on the map. Should be called before indexing using []
bool on_board(const location& loc) const
{
return loc.valid(w_, h_);
}
bool on_board(const location& loc, const bool include_border = false) const;
//function to tell if the map is of 0 size.
bool empty() const
@ -206,6 +217,15 @@ public:
//STARTING_POSITIONS - 1
enum { STARTING_POSITIONS = 10 };
//! Retuns the usage of the map.
tusage get_usage() const { return usage_; }
//! The default map header, needed for maps created with
//! terrain_translation::write_game_map().
static const std::string default_map_header;
//! The default border style for a map
static const tborder default_border = SINGLE_TILE_BORDER;
protected:
t_translation::t_map tiles_;
location startingPositions_[STARTING_POSITIONS];
@ -214,10 +234,19 @@ protected:
* Clears the border cache, needed for the editor
*/
void clear_border_cache() { borderCache_.clear(); }
//! Sizes of the map including the borders.
int total_width_;
int total_height_;
private:
int num_starting_positions() const
{ return sizeof(startingPositions_)/sizeof(*startingPositions_); }
//allows lookup of terrain at a particular location.
const t_translation::t_list operator[](int index) const
{ return tiles_[index + border_size_]; }
t_translation::t_list terrainList_;
std::map<t_translation::t_letter, terrain_type> letterToTerrain_;
std::vector<location> villages_;
@ -225,8 +254,14 @@ private:
mutable std::map<location, t_translation::t_letter> borderCache_;
mutable std::map<t_translation::t_letter, size_t> terrainFrequencyCache_;
//! Sizes of the map area.
int w_;
int h_;
//! The size of the border around the map.
int border_size_;
//! The kind of map is being loaded.
tusage usage_;
};
class viewpoint

View file

@ -323,10 +323,11 @@ static std::string output_map(const terrain_map& terrain,
// Remember that we only want the middle 1/9th of the map.
// All other segments of the map are there only to give
// the important middle part some context.
const size_t begin_x = terrain.size()/3;
const size_t end_x = begin_x*2;
const size_t begin_y = terrain.front().size()/3;
const size_t end_y = begin_y*2;
// We also have a border so also adjust for that.
const size_t begin_x = terrain.size() / 3 - gamemap::default_border ;
const size_t end_x = terrain.size() * 2 / 3 + gamemap::default_border;
const size_t begin_y = terrain.front().size() / 3 - gamemap::default_border;
const size_t end_y = terrain.front().size() * 2 / 3 + gamemap::default_border;
terrain_map map;
map.resize(end_x - begin_x);
@ -347,7 +348,7 @@ static std::string output_map(const terrain_map& terrain,
itor->second.y -= begin_y;
}
return t_translation::write_game_map(map, starting_positions);
return gamemap::default_map_header + t_translation::write_game_map(map, starting_positions);
}
namespace {

View file

@ -50,8 +50,8 @@ surface getMinimap(int w, int h, const gamemap& map, const viewpoint* vw)
cache_map& cache = mini_terrain_cache;
cache_map& fog_cache = mini_fogged_terrain_cache;
for(int y = 0; y != map.h(); ++y) {
for(int x = 0; x != map.w(); ++x) {
for(int y = 0; y != map.total_height(); ++y) {
for(int x = 0; x != map.total_width(); ++x) {
surface surf(NULL);
@ -59,7 +59,8 @@ surface getMinimap(int w, int h, const gamemap& map, const viewpoint* vw)
if(map.on_board(loc)) {
const bool shrouded = vw != NULL && vw->shrouded(x,y);
const bool fogged = vw != NULL && vw->fogged(x,y) && !shrouded;
const t_translation::t_letter terrain = shrouded ? t_translation::VOID_TERRAIN : map[x][y];
const t_translation::t_letter terrain = shrouded ?
t_translation::VOID_TERRAIN : map[loc];
cache_map::iterator i;
bool need_fogging = false;

View file

@ -463,7 +463,7 @@ void create::process_event()
std::auto_ptr<gamemap> map(NULL);
try {
map = std::auto_ptr<gamemap>(new gamemap(game_config(), map_data));
map = std::auto_ptr<gamemap>(new gamemap(game_config(), map_data, gamemap::SINGLE_TILE_BORDER, gamemap::IS_MAP));
} catch(gamemap::incorrect_format_exception& e) {
LOG_STREAM(err,general) << "map could not be loaded: " << e.msg_ << "\n";
@ -618,7 +618,7 @@ void create::hide_children(bool hide)
const std::string& map_data = parameters_.scenario_data["map_data"];
try {
gamemap map(game_config(), map_data);
gamemap map(game_config(), map_data, gamemap::SINGLE_TILE_BORDER, gamemap::IS_MAP);
#ifndef USE_TINY_GUI
const surface mini(image::getMinimap(minimap_rect_.w,minimap_rect_.h,map,0));

View file

@ -401,7 +401,8 @@ void gamebrowser::set_game_items(const config& cfg, const config& game_config)
}
if (!found) {
// Parsing the map and generating the minimap are both cpu expensive
gamemap map(game_config, games_.back().map_data);
gamemap map(game_config, games_.back().map_data,
gamemap::SINGLE_TILE_BORDER, gamemap::IS_MAP);
games_.back().mini_map = image::getMinimap(minimap_size_, minimap_size_, map, 0);
games_.back().map_info_size = lexical_cast_default<std::string, int>(map.w(), "??")
+ std::string("x") + lexical_cast_default<std::string, int>(map.h(), "??");

View file

@ -161,7 +161,7 @@ static void find_routes(const gamemap& map, const gamestatus& status,
continue;
// Find the terrain of the adjacent location
const t_translation::t_letter terrain = map[currentloc.x][currentloc.y];
const t_translation::t_letter terrain = map[currentloc];
// Find the movement cost of this type onto the terrain
const int move_cost = u.movement_cost(terrain);
@ -232,7 +232,7 @@ int route_turns_to_complete(const unit &u, const gamemap &map, paths::route &rt,
for(std::vector<gamemap::location>::const_iterator i = rt.steps.begin()+1;
i != rt.steps.end(); ++i) {
wassert(map.on_board(*i));
const int move_cost = u.movement_cost(map[i->x][i->y]);
const int move_cost = u.movement_cost(map[*i]);
movement -= move_cost;
if (movement < 0) {
@ -295,7 +295,7 @@ double shortest_path_calculator::cost(const gamemap::location& /*src*/,const gam
if (team_.shrouded(loc.x, loc.y))
return getNoPathValue();
int const base_cost = unit_.movement_cost(map_[loc.x][loc.y]);
int const base_cost = unit_.movement_cost(map_[loc]);
wassert(base_cost >= 1); // Pathfinding heuristic: the cost must be at least 1
if (total_movement_ < base_cost)
return getNoPathValue();
@ -346,5 +346,5 @@ double emergency_path_calculator::cost(const gamemap::location&,const gamemap::l
{
wassert(map_.on_board(loc));
return unit_.movement_cost(map_[loc.x][loc.y]);
return unit_.movement_cost(map_[loc]);
}

View file

@ -39,7 +39,7 @@ play_controller::play_controller(const config& level, const game_data& gameinfo,
menu_handler_(gui_, units_, teams_, level, gameinfo, map_, game_config, status_, state_of_game, undo_stack_, redo_stack_),
generator_setter(&recorder), statistics_context_(level["name"]), gameinfo_(gameinfo), level_(level), game_config_(game_config),
gamestate_(state_of_game), status_(level, num_turns, &state_of_game),
map_(game_config, level["map_data"]), ticks_(ticks),
map_(game_config, level["map_data"], gamemap::SINGLE_TILE_BORDER, gamemap::IS_MAP), ticks_(ticks),
xp_mod_(atoi(level["experience_modifier"].c_str()) > 0 ? atoi(level["experience_modifier"].c_str()) : 100),
loading_game_(level["playing_team"].empty() == false),
first_human_team_(-1), player_number_(1),
@ -144,7 +144,7 @@ static int placing_score(const config& side, const gamemap& map, const gamemap::
const gamemap::location pos(i,j);
if(map.on_board(pos)) {
++positions;
if(std::count(terrain.begin(),terrain.end(),map[i][j])) {
if(std::count(terrain.begin(),terrain.end(),map[pos])) {
++liked;
}
}