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:
parent
2425e17fde
commit
c588445335
23 changed files with 263 additions and 110 deletions
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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(){};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
172
src/map.cpp
172
src/map.cpp
|
@ -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);
|
||||
|
||||
|
|
55
src/map.hpp
55
src/map.hpp
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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(), "??");
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue