From ac59b0d0e72c706a6e14fe59cb77ceaabcc7bce2 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Mon, 2 Jun 2014 01:04:40 -0400 Subject: [PATCH] resources::game_map is const *, move functionality to game_board This commit changes the resources::game_map pointer to a const *, so that changes to the game_map coming from lua or wml apis must go through the game_board. Three functions were moved into the game_board -- although substantively they did not change, there were minor changes, in terms of the kind of error reporting done, and also in how gui refresh orders are issued afterwards. In testing the differences due to this refactor don't seem to be noticeable. --- src/actions/vision.cpp | 2 +- src/ai/contexts.cpp | 6 +- src/ai/contexts.hpp | 4 +- src/ai/default/ai.cpp | 4 +- src/ai/default/contexts.cpp | 4 +- src/ai/testing/aspect_attacks.cpp | 4 +- src/ai/testing/ca.cpp | 10 +- src/ai/testing/ca_testing_move_to_targets.cpp | 8 +- src/game_board.cpp | 95 +++++++++++++++++++ src/game_board.hpp | 11 +++ src/game_events/action_wml.cpp | 92 ++---------------- src/map_location.cpp | 2 +- src/movetype.cpp | 2 +- src/resources.cpp | 2 +- src/resources.hpp | 2 +- src/scripting/lua.cpp | 9 +- 16 files changed, 148 insertions(+), 109 deletions(-) diff --git a/src/actions/vision.cpp b/src/actions/vision.cpp index 9fa1999a02df..d1bbe275271e 100644 --- a/src/actions/vision.cpp +++ b/src/actions/vision.cpp @@ -230,7 +230,7 @@ bool shroud_clearer::clear_loc(team &tm, const map_location &loc, size_t &enemy_count, size_t &friend_count, move_unit_spectator * spectator) { - gamemap &map = *resources::game_map; + const gamemap &map = resources::gameboard->map(); // This counts as clearing a tile for the return value if it is on the // board and currently fogged under shared vision. (No need to explicitly // check for shrouded since shrouded implies fogged.) diff --git a/src/ai/contexts.cpp b/src/ai/contexts.cpp index a50b039acc19..39ffae467139 100644 --- a/src/ai/contexts.cpp +++ b/src/ai/contexts.cpp @@ -242,7 +242,7 @@ readonly_context_impl::readonly_context_impl(side_context &context, const config add_known_aspect("support_villages",support_villages_); add_known_aspect("village_value",village_value_); add_known_aspect("villages_per_scout",villages_per_scout_); - keeps_.init(*resources::game_map); + keeps_.init(resources::gameboard->map()); } @@ -1002,7 +1002,7 @@ void keeps_cache::clear() } -void keeps_cache::init(gamemap &map) +void keeps_cache::init(const gamemap &map) { map_ = ↦ } @@ -1095,7 +1095,7 @@ double readonly_context_impl::power_projection(const map_location& loc, const mo map_location locs[6]; get_adjacent_tiles(loc,locs); - gamemap& map_ = *resources::game_map; + const gamemap& map_ = resources::gameboard->map(); unit_map& units_ = *resources::units; int res = 0; diff --git a/src/ai/contexts.hpp b/src/ai/contexts.hpp index 090836b86848..b51bbd35393c 100644 --- a/src/ai/contexts.hpp +++ b/src/ai/contexts.hpp @@ -115,9 +115,9 @@ class keeps_cache : public events::observer void handle_generic_event(const std::string& event_name); void clear(); const std::set& get(); - void init(gamemap &map); + void init(const gamemap &map); private: - gamemap *map_; + const gamemap *map_; std::set keeps_; }; diff --git a/src/ai/default/ai.cpp b/src/ai/default/ai.cpp index f7d1f46f7838..b14e036cbd3a 100644 --- a/src/ai/default/ai.cpp +++ b/src/ai/default/ai.cpp @@ -530,8 +530,8 @@ ai_default_recruitment_stage::~ai_default_recruitment_stage() void ai_default_recruitment_stage::analyze_potential_recruit_movements() { - unit_map &units_ = *resources::units; - gamemap &map_ = *resources::game_map; + const unit_map &units_ = *resources::units; + const gamemap &map_ = *resources::game_map; if(unit_movement_scores_.empty() == false || get_recruitment_ignore_bad_movement()) { diff --git a/src/ai/default/contexts.cpp b/src/ai/default/contexts.cpp index d228da7c2b3e..32dafe506409 100644 --- a/src/ai/default/contexts.cpp +++ b/src/ai/default/contexts.cpp @@ -97,7 +97,7 @@ default_ai_context& default_ai_context_impl::get_default_ai_context(){ int default_ai_context_impl::rate_terrain(const unit& u, const map_location& loc) const { - gamemap &map_ = *resources::game_map; + const gamemap &map_ = *resources::game_map; const t_translation::t_terrain terrain = map_.get_terrain(loc); const int defense = u.defense_modifier(terrain); int rating = 100 - defense; @@ -132,7 +132,7 @@ std::vector default_ai_context_impl::find_targets(const move_map& enemy_ log_scope2(log_ai, "finding targets..."); unit_map &units_ = *resources::units; unit_map::iterator leader = units_.find_leader(get_side()); - gamemap &map_ = *resources::game_map; + const gamemap &map_ = *resources::game_map; std::vector teams_ = *resources::teams; const bool has_leader = leader != units_.end(); diff --git a/src/ai/testing/aspect_attacks.cpp b/src/ai/testing/aspect_attacks.cpp index 6a9b48a09575..187434e82cb7 100644 --- a/src/ai/testing/aspect_attacks.cpp +++ b/src/ai/testing/aspect_attacks.cpp @@ -136,7 +136,7 @@ void aspect_attacks::do_attack_analysis( //std::cerr << "ANALYSIS " << cur_analysis.movements.size() << " >= " << get_attack_depth() << "\n"; return; } - gamemap &map_ = *resources::game_map; + const gamemap &map_ = *resources::game_map; unit_map &units_ = *resources::units; std::vector &teams_ = *resources::teams; @@ -359,7 +359,7 @@ void aspect_attacks::do_attack_analysis( int aspect_attacks::rate_terrain(const unit& u, const map_location& loc) { - gamemap &map_ = *resources::game_map; + const gamemap &map_ = *resources::game_map; const t_translation::t_terrain terrain = map_.get_terrain(loc); const int defense = u.defense_modifier(terrain); int rating = 100 - defense; diff --git a/src/ai/testing/ca.cpp b/src/ai/testing/ca.cpp index 038eaf2112ac..4460956da95c 100644 --- a/src/ai/testing/ca.cpp +++ b/src/ai/testing/ca.cpp @@ -64,7 +64,7 @@ double goto_phase::evaluate() // Execute goto-movements - first collect gotos in a list std::vector gotos; unit_map &units_ = *resources::units; - gamemap &map_ = *resources::game_map; + const gamemap &map_ = *resources::game_map; for(unit_map::iterator ui = units_.begin(); ui != units_.end(); ++ui) { if (ui->get_goto() == ui->get_location()) { @@ -222,9 +222,9 @@ void recruitment_phase::execute() unit_combat_scores_.clear(); unit_movement_scores_.clear(); - unit_map &units_ = *resources::units; - gamemap &map_ = *resources::game_map; - std::vector &teams_ = *resources::teams; + const unit_map &units_ = *resources::units; + const gamemap &map_ = *resources::game_map; + const std::vector &teams_ = *resources::teams; map_location start_pos = units_.find_leader(get_side())->get_location(); @@ -1046,7 +1046,7 @@ void get_villages_phase::find_villages( const bool passive_leader = get_passive_leader(); size_t min_distance = 100000; - gamemap &map_ = *resources::game_map; + const gamemap &map_ = *resources::game_map; std::vector &teams_ = *resources::teams; // When a unit is dispatched we need to make sure we don't diff --git a/src/ai/testing/ca_testing_move_to_targets.cpp b/src/ai/testing/ca_testing_move_to_targets.cpp index abb996a8016e..7306fb57e643 100644 --- a/src/ai/testing/ca_testing_move_to_targets.cpp +++ b/src/ai/testing/ca_testing_move_to_targets.cpp @@ -273,7 +273,7 @@ std::pair testing_move_to_targets_phase::choose_move( raise_user_interact(); unit_map &units_ = *resources::units; - gamemap &map_ = *resources::game_map; + const gamemap &map_ = *resources::game_map; unit_map::iterator u; @@ -620,7 +620,7 @@ std::pair testing_move_to_targets_phase::choose_move( void testing_move_to_targets_phase::access_points(const move_map& srcdst, const map_location& u, const map_location& dst, std::vector& out) { unit_map &units_ = *resources::units; - gamemap &map_ = *resources::game_map; + const gamemap &map_ = *resources::game_map; const unit_map::const_iterator u_it = units_.find(u); if(u_it == units_.end()) { return; @@ -711,7 +711,7 @@ map_location testing_move_to_targets_phase::form_group(const std::vector& route, const std::set& units) { unit_map &units_ = *resources::units; - gamemap &map_ = *resources::game_map; + const gamemap &map_ = *resources::game_map; const std::vector::const_iterator itor = std::find(route.begin(),route.end(),dst); if(itor == route.end()) { @@ -813,7 +813,7 @@ bool testing_move_to_targets_phase::move_group(const map_location& dst, const st double testing_move_to_targets_phase::rate_group(const std::set& group, const std::vector& battlefield) const { unit_map &units_ = *resources::units; - gamemap &map_ = *resources::game_map; + const gamemap &map_ = *resources::game_map; double strength = 0.0; for(std::set::const_iterator i = group.begin(); i != group.end(); ++i) { diff --git a/src/game_board.cpp b/src/game_board.cpp index 8b1ff2c8cd8f..16613fa2f202 100644 --- a/src/game_board.cpp +++ b/src/game_board.cpp @@ -14,10 +14,20 @@ #include "config.hpp" #include "game_board.hpp" +#include "game_preferences.hpp" +#include "log.hpp" #include "unit.hpp" +#include "utils/foreach.tpp" + #include +static lg::log_domain log_engine("enginerefac"); +#define DBG_RG LOG_STREAM(debug, log_engine) +#define LOG_RG LOG_STREAM(info, log_engine) +#define WRN_RG LOG_STREAM(warn, log_engine) +#define ERR_RG LOG_STREAM(err, log_engine) + void game_board::new_turn(int player_num) { BOOST_FOREACH (unit & i, units_) { @@ -87,6 +97,91 @@ void game_board::side_change_controller(int side_num, team::CONTROLLER ctrl, con } } +bool game_board::try_add_unit_to_recall_list(const map_location& loc, const unit& u) +{ + if(teams_[u.side()-1].persistent()) { + teams_[u.side()-1].recall_list().push_back(u); + return true; + } else { + ERR_RG << "unit with id " << u.id() << ": location (" << loc.x << "," << loc.y <<") is not on the map, and player " + << u.side() << " has no recall list.\n"; + return false; + } +} + + +boost::optional game_board::replace_map(const gamemap & newmap) { + boost::optional ret = boost::optional (); + + /* Remember the locations where a village is owned by a side. */ + std::map villages; + FOREACH(const AUTO& village, map_.villages()) { + const int owner = village_owner(village); + if(owner != -1) { + villages[village] = owner; + } + } + + for (unit_map::iterator itor = units_.begin(); itor != units_.end(); ) { + if (!newmap.on_board(itor->get_location())) { + if (!try_add_unit_to_recall_list(itor->get_location(), *itor)) { + *ret = std::string("replace_map: Cannot add a unit that would become off-map to the recall list\n"); + } + units_.erase(itor++); + } else { + ++itor; + } + } + + /* Disown villages that are no longer villages. */ + FOREACH(const AUTO& village, villages) { + if(!newmap.is_village(village.first)) { + teams_[village.second].lose_village(village.first); + } + } + + map_ = newmap; + return ret; +} + + + +void game_board::overlay_map(const gamemap & mask_map, const config & cfg, map_location loc, bool border) { + map_.overlay(mask_map, cfg, loc.x, loc.y, border); +} + +bool game_board::change_terrain(const map_location &loc, const t_translation::t_terrain &t, + gamemap::tmerge_mode mode, bool replace_if_failed) +{ + /* + * When a hex changes from a village terrain to a non-village terrain, and + * a team owned that village it loses that village. When a hex changes from + * a non-village terrain to a village terrain and there is a unit on that + * hex it does not automatically capture the village. The reason for not + * capturing villages it that there are too many choices to make; should a + * unit loose its movement points, should capture events be fired. It is + * easier to do this as wanted by the author in WML. + */ + + t_translation::t_terrain + old_t = map_.get_terrain(loc), + new_t = map_.merge_terrains(old_t, t, mode, replace_if_failed); + if (new_t == t_translation::NONE_TERRAIN) return false; + preferences::encountered_terrains().insert(new_t); + + if (map_.is_village(old_t) && !map_.is_village(new_t)) { + int owner = village_owner(loc); + if (owner != -1) + teams_[owner].lose_village(loc); + } + + map_.set_terrain(loc, new_t); + + BOOST_FOREACH(const t_translation::t_terrain &ut, map_.underlying_union_terrain(loc)) { + preferences::encountered_terrains().insert(ut); + } + return true; +} void game_board::write_config(config & cfg) const { for(std::vector::const_iterator t = teams_.begin(); t != teams_.end(); ++t) { diff --git a/src/game_board.hpp b/src/game_board.hpp index c8bc2b70ea5d..bff2305fefa0 100644 --- a/src/game_board.hpp +++ b/src/game_board.hpp @@ -21,6 +21,7 @@ #include "team.hpp" #include "unit_map.hpp" +#include #include class config; @@ -29,6 +30,7 @@ namespace events { class mouse_handler; } + class game_board { std::vector teams_; @@ -68,6 +70,15 @@ class game_board { void side_drop_to (int side_num, team::CONTROLLER ctrl); void side_change_controller (int side_num, team::CONTROLLER ctrl, const std::string pname = ""); + // Manipulator from actionwml + + bool try_add_unit_to_recall_list(const map_location& loc, const unit& u); + boost::optional replace_map (const gamemap & r); + void overlay_map (const gamemap & o, const config & cfg, map_location loc, bool border); + + bool change_terrain(const map_location &loc, const t_translation::t_terrain &t, + gamemap::tmerge_mode mode, bool replace_if_failed); //used only by lua + // Global accessor from unit.hpp unit_map::iterator find_visible_unit(const map_location &loc, const team& current_team, bool see_all = false); diff --git a/src/game_events/action_wml.cpp b/src/game_events/action_wml.cpp index 1bd1c3db1609..ab5c927c16a3 100644 --- a/src/game_events/action_wml.cpp +++ b/src/game_events/action_wml.cpp @@ -288,7 +288,7 @@ namespace { // Support functions std::vector fake_unit_path(const unit& fake_unit, const std::vector& xvals, const std::vector& yvals) { - gamemap *game_map = resources::game_map; + const gamemap *game_map = resources::game_map; std::vector path; map_location src; map_location dst; @@ -532,56 +532,8 @@ namespace { // Support functions resources::screen->invalidate_all(); } - bool try_add_unit_to_recall_list(const map_location& loc, const unit& u) - { - if((*resources::teams)[u.side()-1].persistent()) { - (*resources::teams)[u.side()-1].recall_list().push_back(u); - return true; - } else { - ERR_NG << "unit with id " << u.id() << ": location (" << loc.x << "," << loc.y <<") is not on the map, and player " - << u.side() << " has no recall list.\n"; - return false; - } - } - } // end anonymous namespace (support functions) - -void change_terrain(const map_location &loc, const t_translation::t_terrain &t, - gamemap::tmerge_mode mode, bool replace_if_failed) -{ - /* - * When a hex changes from a village terrain to a non-village terrain, and - * a team owned that village it loses that village. When a hex changes from - * a non-village terrain to a village terrain and there is a unit on that - * hex it does not automatically capture the village. The reason for not - * capturing villages it that there are too many choices to make; should a - * unit loose its movement points, should capture events be fired. It is - * easier to do this as wanted by the author in WML. - */ - - gamemap *game_map = resources::game_map; - - t_translation::t_terrain - old_t = game_map->get_terrain(loc), - new_t = game_map->merge_terrains(old_t, t, mode, replace_if_failed); - if (new_t == t_translation::NONE_TERRAIN) return; - preferences::encountered_terrains().insert(new_t); - - if (game_map->is_village(old_t) && !game_map->is_village(new_t)) { - int owner = village_owner(loc); - if (owner != -1) - (*resources::teams)[owner].lose_village(loc); - } - - game_map->set_terrain(loc, new_t); - context::screen_needs_rebuild(true); - - BOOST_FOREACH(const t_translation::t_terrain &ut, game_map->underlying_union_terrain(loc)) { - preferences::encountered_terrains().insert(ut); - } -} - void handle_deprecated_message(const config& cfg) { // Note: no need to translate the string, since only used for deprecated things. @@ -1728,19 +1680,9 @@ WML_HANDLER_FUNCTION(replace_map, /*event_info*/, cfg) * easier to do this as wanted by the author in WML. */ - gamemap *game_map = resources::game_map; - + const gamemap * game_map = resources::game_map; gamemap map(*game_map); - /* Remember the locations where a village is owned by a side. */ - std::map villages; - FOREACH(const AUTO& village, map.villages()) { - const int owner = village_owner(village); - if(owner != -1) { - villages[village] = owner; - } - } - try { if (cfg["map"].empty()) { const vconfig& map_cfg = cfg.child("map"); @@ -1748,7 +1690,7 @@ WML_HANDLER_FUNCTION(replace_map, /*event_info*/, cfg) } else map.read(cfg["map"], false); } catch(incorrect_map_format_error&) { - lg::wml_error << "replace_map: Unable to load map " << cfg["map"] << "\n"; + lg::wml_error << "replace_map: Unable to load map " << cfg["map"] << std::endl; return; } catch(twml_exception& e) { e.show(*resources::screen); @@ -1757,38 +1699,24 @@ WML_HANDLER_FUNCTION(replace_map, /*event_info*/, cfg) if (map.total_width() > game_map->total_width() || map.total_height() > game_map->total_height()) { if (!cfg["expand"].to_bool()) { - lg::wml_error << "replace_map: Map dimension(s) increase but expand is not set\n"; + lg::wml_error << "replace_map: Map dimension(s) increase but expand is not set" << std::endl; return; } } if (map.total_width() < game_map->total_width() || map.total_height() < game_map->total_height()) { if (!cfg["shrink"].to_bool()) { - lg::wml_error << "replace_map: Map dimension(s) decrease but shrink is not set\n"; + lg::wml_error << "replace_map: Map dimension(s) decrease but shrink is not set" << std::endl; return; } - unit_map *units = resources::units; - unit_map::iterator itor; - for (itor = units->begin(); itor != units->end(); ) { - if (!map.on_board(itor->get_location())) { - if (!try_add_unit_to_recall_list(itor->get_location(), *itor)) { - lg::wml_error << "replace_map: Cannot add a unit that would become off-map to the recall list\n"; - } - units->erase(itor++); - } else { - ++itor; - } - } } - /* Disown villages that are no longer villages. */ - FOREACH(const AUTO& village, villages) { - if(!map.is_village(village.first)) { - (*resources::teams)[village.second].lose_village(village.first); - } + boost::optional errmsg = resources::gameboard->replace_map(map); + + if (errmsg) { + lg::wml_error << *errmsg << std::endl; } - *game_map = map; resources::screen->reload_map(); context::screen_needs_rebuild(true); ai::manager::raise_map_changed(); @@ -2475,7 +2403,7 @@ WML_HANDLER_FUNCTION(terrain_mask, /*event_info*/, cfg) return; } bool border = cfg["border"].to_bool(); - resources::game_map->overlay(mask_map, cfg.get_parsed_config(), loc.x, loc.y, border); + resources::gameboard->overlay_map(mask_map, cfg.get_parsed_config(), loc, border); context::screen_needs_rebuild(true); } diff --git a/src/map_location.cpp b/src/map_location.cpp index 399449e12d19..ffb2c2c7e3c7 100644 --- a/src/map_location.cpp +++ b/src/map_location.cpp @@ -295,7 +295,7 @@ std::vector parse_location_range(const std::string &x, const std:: std::vector res; const std::vector xvals = utils::split(x); const std::vector yvals = utils::split(y); - gamemap *map = resources::game_map; + const gamemap *map = resources::game_map; assert(map); int xmin = 1, xmax = map->w(), ymin = 1, ymax = map->h(); if (with_border) { diff --git a/src/movetype.cpp b/src/movetype.cpp index 7aa776d2db83..ff838b0a7f45 100644 --- a/src/movetype.cpp +++ b/src/movetype.cpp @@ -281,7 +281,7 @@ int movetype::terrain_info::data::calc_value( return params_.default_value; } assert(resources::game_map); - gamemap & map = *resources::game_map; + const gamemap & map = *resources::game_map; // Get a list of underlying terrains. const t_translation::t_list & underlying = params_.use_move ? diff --git a/src/resources.cpp b/src/resources.cpp index da7357a1ec0e..5ddee1e5e1cb 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -21,7 +21,7 @@ namespace resources game_config_manager *config_manager = NULL; play_controller *controller = NULL; game_data *gamedata = NULL; - gamemap *game_map = NULL; + const gamemap *game_map = NULL; LuaKernel *lua_kernel = NULL; persist_manager *persist = NULL; game_display *screen = NULL; diff --git a/src/resources.hpp b/src/resources.hpp index f7230b623c1e..b8103093fd22 100644 --- a/src/resources.hpp +++ b/src/resources.hpp @@ -45,7 +45,7 @@ namespace resources extern play_controller *controller; extern game_board *gameboard; extern game_data *gamedata; - extern gamemap *game_map; + extern const gamemap *game_map; extern LuaKernel *lua_kernel; // Set by game_events::manager. extern persist_manager *persist; extern game_classification *classification; diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index a9c6891746f0..a88e66caf3f7 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -1288,7 +1288,12 @@ static int intf_set_terrain(lua_State *L) } } - game_events::change_terrain(map_location(x - 1, y - 1), terrain, mode, replace_if_failed); + bool result = resources::gameboard->change_terrain(map_location(x - 1, y - 1), terrain, mode, replace_if_failed); + if (result) { + resources::screen->recalculate_minimap(); + resources::screen->invalidate_all(); + resources::screen->rebuild_all(); + } return 0; } @@ -1776,7 +1781,7 @@ static int intf_find_path(lua_State *L) return luaL_argerror(L, arg - 2, "invalid location"); std::vector &teams = *resources::teams; - gamemap &map = *resources::game_map; + const gamemap &map = *resources::game_map; int viewing_side = 0; bool ignore_units = false, see_all = false, ignore_teleport = false; double stop_at = 10000;