editor_action* editor_action_starting_position::perform(map_context& mc) const { editor_action_ptr undo; const std::string* old_loc_id = mc.map().is_starting_position(loc_); map_location old_loc = mc.map().special_location(loc_id_); if(old_loc_id != nullptr) { // If another player was starting at the location, we actually perform two actions, so the undo is an // action_chain. editor_action_chain* undo_chain = new editor_action_chain(); undo_chain->append_action(new editor_action_starting_position(loc_, *old_loc_id)); undo_chain->append_action(new editor_action_starting_position(old_loc, loc_id_)); undo.reset(undo_chain); LOG_ED << "ssp actual: " << *old_loc_id << " to " << map_location() << "\n"; mc.map().set_special_location(*old_loc_id, map_location()); } else { undo.reset(new editor_action_starting_position(old_loc, loc_id_)); } LOG_ED << "ssp actual: " << loc_id_ << " to " << loc_ << "\n"; mc.map().set_special_location(loc_id_, loc_); mc.set_needs_labels_reset(); return undo.release(); }
bool animate_unit_advancement(const map_location &loc, size_t choice, const bool &fire_event, const bool animate) { const events::command_disabler cmd_disabler; unit_map::iterator u = resources::units->find(loc); if (u == resources::units->end()) { LOG_DP << "animate_unit_advancement suppressed: invalid unit\n"; return false; } else if (!u->advances()) { LOG_DP << "animate_unit_advancement suppressed: unit does not advance\n"; return false; } const std::vector<std::string>& options = u->advances_to(); std::vector<config> mod_options = u->get_modification_advances(); if(choice >= options.size() + mod_options.size()) { LOG_DP << "animate_unit_advancement suppressed: invalid option\n"; return false; } // When the unit advances, it fades to white, and then switches // to the new unit, then fades back to the normal color if (animate && !resources::screen->video().update_locked()) { unit_animator animator; bool with_bars = true; animator.add_animation(&*u,"levelout", u->get_location(), map_location(), 0, with_bars); animator.start_animations(); animator.wait_for_end(); } if(choice < options.size()) { // chosen_unit is not a reference, since the unit may disappear at any moment. std::string chosen_unit = options[choice]; ::advance_unit(loc, chosen_unit, fire_event); } else { const config &mod_option = mod_options[choice - options.size()]; ::advance_unit(loc, "", fire_event, &mod_option); } u = resources::units->find(loc); resources::screen->invalidate_unit(); if (animate && u != resources::units->end() && !resources::screen->video().update_locked()) { unit_animator animator; animator.add_animation(&*u, "levelin", u->get_location(), map_location(), 0, true); animator.start_animations(); animator.wait_for_end(); animator.set_all_standing(); resources::screen->invalidate(loc); resources::screen->draw(); events::pump(); } resources::screen->invalidate_all(); resources::screen->draw(); return true; }
MLFixture() { va = map_location(3,4); vb = map_location(10,8); vc = map_location(0,9); vz = map_location::ZERO(); vt1 = va.vector_negation(); vt2 = vb.vector_sum(vc); vt3 = va.vector_sum(vc.vector_negation()); vs1 = vz.get_direction(nw); vs2 = vz.get_direction(n).get_direction(ne); vs3 = vz.get_direction(s).get_direction(se); vs4 = vz.get_direction(sw).get_direction(se); preset_locs.push_back(va); preset_locs.push_back(vb); preset_locs.push_back(vc); preset_locs.push_back(vz); preset_locs.push_back(vt1); preset_locs.push_back(vt2); preset_locs.push_back(vt3); preset_locs.push_back(vs1); preset_locs.push_back(vs2); preset_locs.push_back(vs3); preset_locs.push_back(vs4); }
move::move(config const& cfg, bool hidden) : action(cfg,hidden) , unit_underlying_id_(0) , unit_id_() , route_(new pathfind::marked_route()) , movement_cost_(0) , turn_number_(0) , arrow_(new arrow(hidden)) , fake_unit_() , arrow_brightness_() , arrow_texture_() , mover_() , fake_unit_hidden_(false) { // Construct and validate unit_ unit_map::iterator unit_itor = resources::units->find(cfg["unit_"]); if(unit_itor == resources::units->end()) throw action::ctor_err("move: Invalid underlying_id"); unit_underlying_id_ = unit_itor->underlying_id(); // Construct and validate route_ config const& route_cfg = cfg.child("route_"); if(!route_cfg) throw action::ctor_err("move: Invalid route_"); route_->move_cost = route_cfg["move_cost"]; BOOST_FOREACH(config const& loc_cfg, route_cfg.child_range("step")) { route_->steps.push_back(map_location(loc_cfg["x"],loc_cfg["y"])); } BOOST_FOREACH(config const& mark_cfg, route_cfg.child_range("mark")) { route_->marks[map_location(mark_cfg["x"],mark_cfg["y"])] = pathfind::marked_route::mark(mark_cfg["turns"], mark_cfg["zoc"].to_bool(), mark_cfg["capture"].to_bool(), mark_cfg["invisible"].to_bool()); } // Validate route_ some more std::vector<map_location> const& steps = route_->steps; if(steps.empty()) throw action::ctor_err("move: Invalid route_"); // Construct arrow_ arrow_->set_color(team::get_side_color_index(side_number())); arrow_->set_style(arrow::STYLE_STANDARD); arrow_->set_path(route_->steps); // Construct fake_unit_ fake_unit_.reset(new game_display::fake_unit(*get_unit()) ); if(hidden) fake_unit_->set_hidden(true); fake_unit_->place_on_game_display(resources::screen); fake_unit_->set_ghosted(true); unit_display::move_unit(route_->steps, *fake_unit_, false); //get facing right fake_unit_->set_location(route_->steps.back()); this->init(); }
/** * Creates an undo_action based on a config. * @param tag is the tag of this config, which is used for error reporting. * It should be enclosed in square brackets. * @return a pointer that must be deleted, or NULL if the @a cfg could not be parsed. */ undo_list::undo_action * undo_list::undo_action::create(const config & cfg, const std::string & tag) { const std::string str = cfg["type"]; undo_list::undo_action * res = NULL; // The general division of labor in this function is that the various // constructors will parse the "unit" child config, while this function // parses everything else. if ( str == "move" ) { res = new move_action(cfg.child("unit", tag), cfg, cfg["starting_moves"], cfg["time_bonus"], cfg["village_owner"], map_location::parse_direction(cfg["starting_direction"])); } if ( str == "recruit" ) { // Validate the unit type. const config & child = cfg.child("unit", tag); const unit_type * u_type = unit_types.find(child["type"]); if ( !u_type ) { // Bad data. ERR_NG << "Invalid recruit found in " << tag << "; unit type '" << child["type"] << "' was not found.\n"; return NULL; } res = new recruit_action(child, *u_type, map_location(cfg, NULL), map_location(cfg.child_or_empty("leader"), NULL)); } else if ( str == "recall" ) res = new recall_action(cfg.child("unit", tag), map_location(cfg, NULL), map_location(cfg.child_or_empty("leader"), NULL)); else if ( str == "dismiss" ) res = new dismiss_action(cfg.child("unit", tag)); else if ( str == "auto_shroud" ) res = new auto_shroud_action(cfg["active"].to_bool()); else if ( str == "update_shroud" ) res = new update_shroud_action; else { // Unrecognized type. ERR_NG << "Unrecognized undo action type: " << str << "." << std::endl; return NULL; } res->replay_data = cfg.child_or_empty("replay_data"); return res; }
map_location gamemap::special_location(const std::string& id) const { auto it = starting_positions_.left.find(id); if (it != starting_positions_.left.end()) { auto& coordinate = it->second; return map_location(coordinate.x, coordinate.y); } else { return map_location(); } }
static map_location place_village(const t_translation::t_map& map, const size_t x, const size_t y, const size_t radius, const config& cfg, tcode_list_cache &adj_liked_cache) { const map_location loc(x,y); std::set<map_location> locs; get_tiles_radius(loc,radius,locs); map_location best_loc; int best_rating = 0; for(std::set<map_location>::const_iterator i = locs.begin(); i != locs.end(); ++i) { if(i->x < 0 || i->y < 0 || i->x >= static_cast<long>(map.size()) || i->y >= static_cast<long>(map[i->x].size())) { continue; } const t_translation::t_terrain t = map[i->x][i->y]; const std::string str = t_translation::write_terrain_code(t); if (const config &child = cfg.find_child("village", "terrain", str)) { tcode_list_cache::iterator l = adj_liked_cache.find(t); t_translation::t_list *adjacent_liked; if (l != adj_liked_cache.end()) { adjacent_liked = &(l->second); } else { adj_liked_cache[t] = t_translation::read_list(child["adjacent_liked"]); adjacent_liked = &(adj_liked_cache[t]); } int rating = child["rating"]; map_location adj[6]; get_adjacent_tiles(map_location(i->x,i->y),adj); for(size_t n = 0; n != 6; ++n) { if(adj[n].x < 0 || adj[n].y < 0 || adj[n].x >= static_cast<long>(map.size()) || adj[n].y >= static_cast<long>(map[adj[n].x].size())) { continue; } const t_translation::t_terrain t2 = map[adj[n].x][adj[n].y]; rating += std::count(adjacent_liked->begin(),adjacent_liked->end(),t2); } if(rating > best_rating) { best_loc = map_location(i->x,i->y); best_rating = rating; } } } return best_loc; }
/** * Helper function which gets a map location from the stack. Handles lua (1-based) to C++ (0-based) conversion. * Expected: stack has at least two elements, top is y, next is x. */ static map_location pop_map_location(lua_State* L) { if (lua_gettop(L) < 2) { luaL_error(L, "pop_map_location: expected to find a map location on the stack, but stack has less than two elements"); return map_location(); } int y = luaL_checkint(L, -1); int x = luaL_checkint(L, -2); lua_pop(L, 2); return map_location(x-1, y-1); }
void editor_map::invert_selection() { std::set<map_location> new_selection; for (int x = -1; x < w() + 1; ++x) { for (int y = -1; y < h() + 1; ++y) { if (selection_.find(map_location(x, y)) == selection_.end()) { new_selection.insert(map_location(x, y)); } } } selection_.swap(new_selection); }
/** * Returns a random tile at one of the borders of a map that is of the given * dimensions. */ map_location default_map_generator_job::random_point_at_side(size_t width, size_t height) { const int side = rng_()%4; if(side < 2) { const int x = rng_()%width; const int y = side == 0 ? 0 : height-1; return map_location(x,y); } else { const int y = rng_()%height; const int x = side == 2 ? 0 : width-1; return map_location(x,y); } }
map_location pathfind::find_vacant_tile(const gamemap& map, const unit_map& units, const map_location& loc, pathfind::VACANT_TILE_TYPE vacancy, const unit* pass_check) { if (!map.on_board(loc)) return map_location(); std::set<map_location> pending_tiles_to_check, tiles_checked; pending_tiles_to_check.insert(loc); // Iterate out 50 hexes from loc for (int distance = 0; distance < 50; ++distance) { if (pending_tiles_to_check.empty()) return map_location(); //Copy over the hexes to check and clear the old set std::set<map_location> tiles_checking; tiles_checking.swap(pending_tiles_to_check); //Iterate over all the hexes we need to check foreach (const map_location &loc, tiles_checking) { //If this area is not a castle but should, skip it. if (vacancy == pathfind::VACANT_CASTLE && !map.is_castle(loc)) continue; const bool pass_check_and_unreachable = pass_check && pass_check->movement_cost(map[loc]) == unit_movement_type::UNREACHABLE; //If the unit can't reach the tile and we have searched //an area of at least radius 10 (arbitrary), skip the tile. //Neccessary for cases such as an unreachable //starting hex surrounded by 6 other unreachable hexes, in which case //the algorithm would not even search distance==1 //even if there's a reachable hex for distance==2. if (pass_check_and_unreachable && distance > 10) continue; //If the hex is empty and we do either no pass check or the hex is reachable, return it. if (units.find(loc) == units.end() && !pass_check_and_unreachable) return loc; map_location adjs[6]; get_adjacent_tiles(loc,adjs); foreach (const map_location &loc, adjs) { if (!map.on_board(loc)) continue; // Add the tile to be checked if it hasn't already been and // isn't being checked. if (tiles_checked.find(loc) == tiles_checked.end() && tiles_checking.find(loc) == tiles_checking.end()) { pending_tiles_to_check.insert(loc); } } } tiles_checked.swap(tiles_checking); } return map_location(); }
editor_action* mouse_action_starting_position::up_left(editor_display& disp, int x, int y) { if (!click_) return nullptr; click_ = false; map_location hex = disp.hex_clicked_on(x, y); if (!disp.map().on_board(hex)) { return nullptr; } auto player_starting_at_hex = disp.map().is_starting_position(hex); if (has_ctrl_modifier()) { if (player_starting_at_hex) { location_palette_.add_item(*player_starting_at_hex); } return nullptr; } std::string new_player_at_hex = location_palette_.selected_item(); editor_action* a = nullptr; if(!player_starting_at_hex || new_player_at_hex != *player_starting_at_hex) { // Set a starting position a = new editor_action_starting_position(hex, new_player_at_hex); } else { // Erase current starting position a = new editor_action_starting_position(map_location(), *player_starting_at_hex); } update_brush_highlights(disp, hex); return a; }
unit_map::const_xy_accessor::const_xy_accessor(const unit_xy_iterator &i) : counter_(i.map_), i_(i.i_), map_(i.map_), loc_(i.valid() ? i->first : map_location()) { }
editor_action* mouse_action::key_event( editor_display& disp, const SDL_Event& event) { if (!has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9')) { int side = event.key.keysym.sym - '0'; if (side >= 1 && side <= gamemap::MAX_PLAYERS) { map_location pos = disp.get_map().starting_position(side); if (pos.valid()) { disp.scroll_to_tile(pos, display::WARP); } } return nullptr; } if (!disp.map().on_board(previous_move_hex_) || event.type != SDL_KEYUP) { return nullptr; } editor_action* a = nullptr; if ((has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9')) || event.key.keysym.sym == SDLK_DELETE) { int res = event.key.keysym.sym - '0'; if (res > gamemap::MAX_PLAYERS || event.key.keysym.sym == SDLK_DELETE) res = 0; const std::string* old_id = disp.map().is_starting_position(previous_move_hex_); if (res == 0 && old_id != nullptr) { a = new editor_action_starting_position(map_location(), *old_id); } else if (res > 0 && (old_id == nullptr || *old_id == std::to_string(res))) { a = new editor_action_starting_position(previous_move_hex_, std::to_string(res)); } } return a; }
/** * Generate a lake. * * It will create water at (x,y), and then have 'lake_fall_off' % chance to * make another water tile in each of the directions n,s,e,w. In each of the * directions it does make another water tile, it will have 'lake_fall_off'/2 % * chance to make another water tile in each of the directions. This will * continue recursively. */ bool default_map_generator_job::generate_lake(terrain_map& terrain, int x, int y, int lake_fall_off, std::set<map_location>& locs_touched) { if(x < 0 || y < 0 || x >= terrain.w || y >= terrain.h || lake_fall_off < 0) { return false; } //we checked for this eariler. unsigned int ulake_fall_off = lake_fall_off; terrain[x][y] = t_translation::SHALLOW_WATER; locs_touched.insert(map_location(x,y)); if((rng_()%100) < ulake_fall_off) { generate_lake(terrain,x+1,y,lake_fall_off/2,locs_touched); } if((rng_()%100) < ulake_fall_off) { generate_lake(terrain,x-1,y,lake_fall_off/2,locs_touched); } if((rng_()%100) < ulake_fall_off) { generate_lake(terrain,x,y+1,lake_fall_off/2,locs_touched); } if((rng_()%100) < ulake_fall_off) { generate_lake(terrain,x,y-1,lake_fall_off/2,locs_touched); } return true; }
void paths::dest_vect::insert(const map_location &loc) { iterator i = lower_bound(*this, loc), i_end = end(); if (i != i_end && i->curr == loc) return; paths::step s = { loc, map_location(), 0 }; std::vector<step>::insert(i, s); }
editor_action* mouse_action_starting_position::up_left(editor_display& disp, int x, int y) { if (!click_) return NULL; click_ = false; map_location hex = disp.hex_clicked_on(x, y); if (!disp.map().on_board(hex)) { return NULL; } int player_starting_at_hex = disp.map().is_starting_position(hex) + 1; std::vector<std::string> players; players.push_back(_("(Player)^None")); for (int i = 1; i <= gamemap::MAX_PLAYERS; i++) { std::stringstream str; str << _("Player") << " " << i; players.push_back(str.str()); } gui::dialog pmenu = gui::dialog(disp, _("Choose player"), _("Which player should start here? You can use alt and a number key to set the starting position for a player, and del to clear the starting position under the cursor. Pressing a number key by itself will scroll to that player's starting position."), gui::OK_CANCEL); pmenu.set_menu(players); int res = pmenu.show(); editor_action* a = NULL; if (res == 0 && player_starting_at_hex != -1) { a = new editor_action_starting_position(map_location(), player_starting_at_hex); } else if (res > 0 && res != player_starting_at_hex) { a = new editor_action_starting_position(hex, res); } update_brush_highlights(disp, hex); return a; }
editor_action* mouse_action::key_event( editor_display& disp, const SDL_Event& event) { if (!has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9')) { int side = event.key.keysym.sym - '0'; if (side >= 1 && side <= gamemap::MAX_PLAYERS) { map_location pos = disp.get_map().starting_position(side); if (pos.valid()) { disp.scroll_to_tile(pos, display::WARP); } } return NULL; } if (!disp.map().on_board(previous_move_hex_) || event.type != SDL_KEYUP) { return NULL; } editor_action* a = NULL; if ((has_alt_modifier() && (event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9')) || event.key.keysym.sym == SDLK_DELETE) { int res = event.key.keysym.sym - '0'; if (res > gamemap::MAX_PLAYERS || event.key.keysym.sym == SDLK_DELETE) res = 0; int player_starting_at_hex = disp.map().is_starting_position(previous_move_hex_) + 1; if (res == 0 && player_starting_at_hex != -1) { a = new editor_action_starting_position(map_location(), player_starting_at_hex); } else if (res > 0 && res != player_starting_at_hex) { a = new editor_action_starting_position(previous_move_hex_, res); } } return a; }
/** * Creates an undo_action based on a config. * @return a pointer that must be deleted, or nullptr if the @a cfg could not be parsed. */ undo_action_base * undo_list::create_action(const config & cfg) { const std::string str = cfg["type"]; undo_action_base * res = nullptr; // The general division of labor in this function is that the various // constructors will parse the "unit" child config, while this function // parses everything else. if ( str == "move" ) { res = new undo::move_action(cfg, cfg.child_or_empty("unit"), cfg["starting_moves"], map_location::parse_direction(cfg["starting_direction"])); } else if ( str == "recruit" ) { // Validate the unit type. const config & child = cfg.child("unit"); const unit_type * u_type = unit_types.find(child["type"]); if ( !u_type ) { // Bad data. ERR_NG << "Invalid recruit found in [undo] or [redo]; unit type '" << child["type"] << "' was not found.\n"; return nullptr; } res = new undo::recruit_action(cfg, *u_type, map_location(cfg.child_or_empty("leader"), nullptr)); } else if ( str == "recall" ) res = new undo::recall_action(cfg, map_location(cfg.child_or_empty("leader"), nullptr)); else if ( str == "dismiss" ) res = new undo::dismiss_action(cfg, cfg.child("unit")); else if ( str == "auto_shroud" ) res = new undo::auto_shroud_action(cfg["active"].to_bool()); else if ( str == "update_shroud" ) res = new undo::update_shroud_action(); else { // Unrecognized type. ERR_NG << "Unrecognized undo action type: " << str << "." << std::endl; return nullptr; } return res; }
map_location find_vacant_tile(const gamemap& map, const unit_map& units, const map_location& loc, VACANT_TILE_TYPE vacancy, const unit* pass_check) { std::set<map_location> pending_tiles_to_check; std::set<map_location> tiles_checked; pending_tiles_to_check.insert( loc ); // Iterate out 50 hexes from loc for (int distance = 0; distance < 50; ++distance) { if (pending_tiles_to_check.empty()) return map_location(); //Copy over the hexes to check and clear the old set std::set<map_location> tiles_checking = pending_tiles_to_check; std::set<map_location>::const_iterator tc_itor = tiles_checking.begin(); pending_tiles_to_check.clear(); //Iterate over all the hexes we need to check for ( ; tc_itor != tiles_checking.end(); ++tc_itor ) { //If the unit cannot reach this area or it's not a castle but should, skip it. if ((vacancy == VACANT_CASTLE && !map.is_castle(*tc_itor)) || (pass_check && pass_check->movement_cost(map[*tc_itor]) == unit_movement_type::UNREACHABLE)) continue; //If the hex is empty, return it. if (map.on_board(*tc_itor) && units.find(*tc_itor) == units.end()) return (*tc_itor); map_location adjs[6]; get_adjacent_tiles(*tc_itor,adjs); for (int i = 0; i != 6; ++i) { //Add the tile to be checked if it hasn't already been and isn't already //pending to be checked if (pending_tiles_to_check.find(adjs[i]) == pending_tiles_to_check.end() && tiles_checked.find(adjs[i]) == tiles_checked.end() && tiles_checking.find(adjs[i]) == tiles_checking.end()) { pending_tiles_to_check.insert(adjs[i]); } } } tiles_checked = tiles_checking; } return map_location(); }
int gamemap::num_valid_starting_positions() const { const int res = is_starting_position(map_location()); if(res == -1) return num_starting_positions()-1; else return res; }
void terrain_builder::parse_mapstring(const std::string &mapstring, struct building_rule &br, anchormap& anchors, const config& global_images) { const t_translation::t_map map = t_translation::read_builder_map(mapstring); // If there is an empty map leave directly. // Determine after conversion, since a // non-empty string can return an empty map. if(map.empty()) { return; } int lineno = (map[0][0] == t_translation::NONE_TERRAIN) ? 1 : 0; int x = lineno; int y = 0; for(size_t y_off = 0; y_off < map.size(); ++y_off) { for(size_t x_off = x; x_off < map[y_off].size(); ++x_off) { const t_translation::t_terrain terrain = map[y_off][x_off]; if(terrain.base == t_translation::TB_DOT) { // Dots are simple placeholders, // which do not represent actual terrains. } else if (terrain.overlay != 0 ) { anchors.insert(std::pair<int, map_location>(terrain.overlay, map_location(x, y))); } else if (terrain.base == t_translation::TB_STAR) { add_constraints(br.constraints, map_location(x, y), t_translation::STAR, global_images); } else { ERR_NG << "Invalid terrain (" << t_translation::write_terrain_code(terrain) << ") in builder map\n"; assert(false); return; } x += 2; } if(lineno % 2 == 1) { ++y; x = 0; } else { x = 1; } ++lineno; } }
map_location pathfind::find_vacant_tile(const gamemap& map, const unit_map& units, const map_location& loc, pathfind::VACANT_TILE_TYPE vacancy, const unit* pass_check) { if (!map.on_board(loc)) return map_location(); std::set<map_location> pending_tiles_to_check, tiles_checked; pending_tiles_to_check.insert(loc); // Iterate out 50 hexes from loc for (int distance = 0; distance < 50; ++distance) { if (pending_tiles_to_check.empty()) return map_location(); //Copy over the hexes to check and clear the old set std::set<map_location> tiles_checking; tiles_checking.swap(pending_tiles_to_check); //Iterate over all the hexes we need to check foreach (const map_location &loc, tiles_checking) { //If the unit cannot reach this area or it's not a castle but should, skip it. if ((vacancy == pathfind::VACANT_CASTLE && !map.is_castle(loc)) || (pass_check && pass_check->movement_cost(map[loc]) == unit_movement_type::UNREACHABLE)) continue; //If the hex is empty, return it. if (units.find(loc) == units.end()) return loc; map_location adjs[6]; get_adjacent_tiles(loc,adjs); foreach (const map_location &loc, adjs) { if (!map.on_board(loc)) continue; // Add the tile to be checked if it hasn't already been and // isn't being checked. if (tiles_checked.find(loc) == tiles_checked.end() && tiles_checking.find(loc) == tiles_checking.end()) { pending_tiles_to_check.insert(loc); } } } tiles_checked.swap(tiles_checking); } return map_location(); }
void editor_action_starting_position::perform_without_undo(map_context& mc) const { const std::string* old_id = mc.get_map().is_starting_position(loc_); if (old_id != nullptr) { mc.get_map().set_special_location(*old_id, map_location()); } mc.get_map().set_special_location(loc_id_, loc_); mc.set_needs_labels_reset(); }
bool terrain_filter::match_internal(const map_location& loc, const bool ignore_xy) const { //Filter Areas if (cfg_.has_attribute("area") && resources::tod_manager->get_area_by_id(cfg_["area"]).count(loc) == 0) return false; if(cfg_.has_attribute("terrain")) { if(cache_.parsed_terrain == NULL) { cache_.parsed_terrain = new t_translation::t_match(cfg_["terrain"]); } if(!cache_.parsed_terrain->is_empty) { const t_translation::t_terrain letter = resources::game_map->get_terrain_info(loc).number(); if(!t_translation::terrain_matches(letter, *cache_.parsed_terrain)) { return false; } } } //Allow filtering on location ranges if(!ignore_xy) { if(!loc.matches_range(cfg_["x"], cfg_["y"])) { return false; } //allow filtering by searching a stored variable of locations if(cfg_.has_attribute("find_in")) { variable_info vi(cfg_["find_in"], false, variable_info::TYPE_CONTAINER); if(!vi.is_valid) return false; if(vi.explicit_index) { if(map_location(vi.as_container(),NULL) != loc) { return false; } } else { bool found = false; BOOST_FOREACH(const config &cfg, vi.as_array()) { if (map_location(cfg, NULL) == loc) { found = true; break; } } if (!found) return false; } } }
void gamemap::read(const std::string& data, const bool allow_invalid) { tiles_ = t_translation::ter_map(); villages_.clear(); starting_positions_.clear(); if(data.empty()) { w_ = 0; h_ = 0; if(allow_invalid) return; } int offset = read_header(data); const std::string& data_only = std::string(data, offset); try { tiles_ = t_translation::read_game_map(data_only, starting_positions_, t_translation::coordinate{ border_size(), border_size() }); } catch(const t_translation::error& e) { // We re-throw the error but as map error. // Since all codepaths test for this, it's the least work. throw incorrect_map_format_error(e.message); } // Post processing on the map w_ = total_width() - 2 * border_size(); h_ = total_height() - 2 * border_size(); //Disabled since there are callcases which pass along a valid map header but empty //map data. Still, loading (and actually applying) an empty map causes problems later on. //Other callcases which need to load a dummy map use completely empty data :(. //VALIDATE((w_ >= 1 && h_ >= 1), "A map needs at least 1 tile, the map cannot be loaded."); for(int x = 0; x < total_width(); ++x) { for(int y = 0; y < total_height(); ++y) { // Is the terrain valid? t_translation::terrain_code t = tiles_.get(x, y); if(tdata_->map().count(t) == 0) { if(!tdata_->try_merge_terrains(t)) { std::stringstream ss; ss << "Unknown tile in map: (" << t_translation::write_terrain_code(t) << ") '" << t << "'"; throw incorrect_map_format_error(ss.str().c_str()); } } // Is it a village? if(x >= border_size() && y >= border_size() && x < total_width()- border_size() && y < total_height()- border_size() && tdata_->is_village(tiles_.get(x, y))) { villages_.push_back(map_location(x - border_size(), y - border_size())); } } } }
editor_action* mouse_action_starting_position::up_right(editor_display& disp, int x, int y) { map_location hex = disp.hex_clicked_on(x, y); int player_starting_at_hex = disp.map().is_starting_position(hex) + 1; if (player_starting_at_hex != -1) { return new editor_action_starting_position(map_location(), player_starting_at_hex); } else { return NULL; } }
editor_action* mouse_action_starting_position::up_right(editor_display& disp, int x, int y) { map_location hex = disp.hex_clicked_on(x, y); auto player_starting_at_hex = disp.map().is_starting_position(hex); if (player_starting_at_hex != nullptr) { return new editor_action_starting_position(map_location(), *player_starting_at_hex); } else { return nullptr; } }
void move_result::do_execute() { LOG_AI_ACTIONS << "start of execution of: "<< *this << std::endl; assert(is_success()); move_spectator_.set_unit(get_info().units.find(from_)); if (from_ != to_) { move_unit( /*move_unit_spectator* move_spectator*/ &move_spectator_, /*std::vector<map_location> route*/ route_.steps, /*replay* move_recorder*/ &recorder, /*undo_list* undo_stack*/ NULL, /*bool show_move*/ preferences::show_ai_moves(), /*map_location *next_unit*/ NULL, /*bool continue_move*/ true, //@todo: 1.9 set to false after implemeting interrupt awareness /*bool should_clear_shroud*/ true, /*bool is_replay*/ false); if ( move_spectator_.get_ambusher().valid() || !move_spectator_.get_seen_enemies().empty() || !move_spectator_.get_seen_friends().empty() ) { set_gamestate_changed(); } else if (move_spectator_.get_unit().valid()){ unit_location_ = move_spectator_.get_unit()->first; if (unit_location_ != from_) { set_gamestate_changed(); } } } else { assert(remove_movement_); } if (move_spectator_.get_unit().valid()){ unit_location_ = move_spectator_.get_unit()->first; if ( remove_movement_ && ( move_spectator_.get_unit()->second.movement_left() > 0 ) && (unit_location_==to_)) { stopunit_result_ptr stopunit_res = actions::execute_stopunit_action(get_side(),true,unit_location_,true,false); if (!stopunit_res->is_ok()) { set_error(stopunit_res->get_status()); } if (stopunit_res->is_gamestate_changed()) { set_gamestate_changed(); } } } else { unit_location_ = map_location(); } if (is_gamestate_changed()) { try { manager::raise_gamestate_changed(); } catch (...) { is_ok(); //Silences "unchecked result" warning throw; } } }
void read_locations(const config& cfg, std::vector<map_location>& locs) { const std::vector<std::string> xvals = utils::split(cfg["x"]); const std::vector<std::string> yvals = utils::split(cfg["y"]); for (unsigned i = 0; i < xvals.size() || i < yvals.size(); ++i) { int x = lexical_cast<int>(xvals[i])-1; int y = lexical_cast<int>(yvals[i])-1; locs.push_back(map_location(x,y)); } }