void move::apply_temp_modifier(unit_map& unit_map) { if (get_source_hex() == get_dest_hex()) return; //zero-hex move, used by attack subclass // Safety: Make sure the old temporary_unit_mover (if any) is destroyed // before creating a new one. mover_.reset(); //@todo: deal with multi-turn moves, which may for instance end their first turn // by capturing a village //@todo: we may need to change unit status here and change it back in remove_temp_modifier unit* unit; { unit_map::iterator unit_it = unit_map.find(get_source_hex()); assert(unit_it != unit_map.end()); unit = &*unit_it; } //Modify movement points DBG_WB <<"Move: Changing movement points for unit " << unit->name() << " [" << unit->id() << "] from " << unit->movement_left() << " to " << unit->movement_left() - movement_cost_ << ".\n"; // Move the unit DBG_WB << "Move: Temporarily moving unit " << unit->name() << " [" << unit->id() << "] from (" << get_source_hex() << ") to (" << get_dest_hex() <<")\n"; mover_.reset(new temporary_unit_mover(unit_map, get_source_hex(), get_dest_hex(), unit->movement_left() - movement_cost_)); //Update status of fake unit (not undone by remove_temp_modifiers) //@todo this contradicts the name "temp_modifiers" fake_unit_->set_movement(unit->movement_left(), true); }
uint32_t install_(const std::string& fpath) { unit_map_cit cit = unit_map_.find(fpath); if(cit != unit_map_.end()) { // find it !, To be not install. return 0; } auto tpath = strip_last_of_delimita_path(fpath); auto bpath = get_file_path(tpath); bpath += '/'; unit_map_it it = unit_map_.find(bpath); if(it != unit_map_.end()) { unit_t& t = it->second; std::string name = get_file_name(tpath); if(fpath.back() == '/') name += '/'; t.install_child(name); } uint32_t hnd = handle_set_.create(); unit_t u; u.set_id(hnd); unit_map_.emplace(fpath, u); return hnd; }
static void verify(const unit_map& units, const config& cfg) { std::stringstream errbuf; LOG_REPLAY << "verifying unit structure...\n"; const size_t nunits = cfg["num_units"].to_size_t(); if(nunits != units.size()) { errbuf << "SYNC VERIFICATION FAILED: number of units from data source differ: " << nunits << " according to data source. " << units.size() << " locally\n"; std::set<map_location> locs; BOOST_FOREACH(const config &u, cfg.child_range("unit")) { const map_location loc(u); locs.insert(loc); if(units.count(loc) == 0) { errbuf << "data source says there is a unit at " << loc << " but none found locally\n"; } } for(unit_map::const_iterator j = units.begin(); j != units.end(); ++j) { if (locs.count(j->get_location()) == 0) { errbuf << "local unit at " << j->get_location() << " but none in data source\n"; } } replay::process_error(errbuf.str()); errbuf.clear(); }
time_of_day tod_manager::time_of_day_at(const unit_map& units,const map_location& loc, const gamemap& map) const { int lighten = std::max<int>(map.get_terrain_info(map.get_terrain(loc)).light_modification() , 0); int darken = std::min<int>(map.get_terrain_info(map.get_terrain(loc)).light_modification() , 0); time_of_day tod = get_time_of_day(lighten + darken,loc); if(loc.valid()) { map_location locs[7]; locs[0] = loc; get_adjacent_tiles(loc,locs+1); for(int i = 0; i != 7; ++i) { const unit_map::const_iterator itor = units.find(locs[i]); if(itor != units.end() && itor->second.get_ability_bool("illuminates") && !itor->second.incapacitated()) { unit_ability_list illum = itor->second.get_abilities("illuminates"); unit_abilities::effect illum_effect(illum,lighten,false); int mod = illum_effect.get_composite_value(); if(mod + tod.lawful_bonus > illum.highest("max_value").first) { mod = illum.highest("max_value").first - tod.lawful_bonus; } lighten = std::max<int>(mod, lighten); darken = std::min<int>(mod, darken); } } } tod = get_time_of_day(lighten + darken,loc); return tod; }
bool install_(const std::string& key, const T& value) { std::string fpath; if(!create_full_path(key, fpath)) { return false; } bool f = false; utils::strings ss = split_text(fpath, "/"); std::string p; for(uint32_t i = 0; i < ss.size(); ++i) { p += '/'; p += ss[i]; unit_t u; u.value = value; u.set_id(serial_id_); std::pair<unit_map_it, bool> ret = unit_map_.insert(unit_pair(p, u)); if(ret.second) { ++serial_id_; auto prev = utils::get_file_path(p); if(p != prev) { unit_map_it it = unit_map_.find(prev); if(it != unit_map_.end()) { unit_t& t = it->second; t.install_child(utils::get_file_name(p)); } } f = true; } else { f = false; } } return f; }
//-----------------------------------------------------------------// utils::strings get_sub_directory(const std::string& root, bool full) { utils::strings list; auto fpath = create_full_path(root); if(fpath.empty()) { return list; } if(fpath.back() != '/') fpath += '/'; unit_map_it it = unit_map_.find(fpath); if(it != unit_map_.end()) { const typename unit_t::childs& chs = it->second.get_childs(); list.resize(chs.size()); list.clear(); for(const auto& s : chs) { if(full) { list.push_back(fpath + strip_last_of_delimita_path(s)); } else { list.push_back(s); } } } return list; }
bool backstab_check(const map_location& attacker_loc, const map_location& defender_loc, const unit_map& units, const std::vector<team>& teams) { const unit_map::const_iterator defender = units.find(defender_loc); if(defender == units.end()) return false; // No defender map_location adj[6]; get_adjacent_tiles(defender_loc, adj); int i; for(i = 0; i != 6; ++i) { if(adj[i] == attacker_loc) break; } if(i >= 6) return false; // Attack not from adjacent location const unit_map::const_iterator opp = units.find(adj[(i+3)%6]); if(opp == units.end()) return false; // No opposite unit if (opp->incapacitated()) return false; if (size_t(defender->side() - 1) >= teams.size() || size_t(opp->side() - 1) >= teams.size()) return true; // If sides aren't valid teams, then they are enemies if (teams[defender->side() - 1].is_enemy(opp->side())) return true; // Defender and opposite are enemies return false; // Defender and opposite are friends }
void move_unit_spectator::reset(const unit_map &units) { ambusher_ = units.end(); failed_teleport_ = units.end(); seen_enemies_.clear(); seen_friends_.clear(); unit_ = units.end(); }
unit_map::unit_map(const unit_map& that) : umap_() , lmap_() { for (const_unit_iterator i = that.begin(); i != that.end(); ++i) { add(i->get_location(), *i); } }
std::pair<int, map_location> under_leadership(const unit_map& units, const map_location& loc) { const unit_map::const_iterator un = units.find(loc); if(un == units.end()) { return {0, map_location::null_location()}; } unit_ability_list abil = un->get_abilities("leadership"); return abil.highest("value"); }
unit_map::unit_map(const unit_map& that) : /* Initialize to silence compiler warnings. */ map_(), lmap_(), num_iters_(0), num_invalid_(0) { for (const_unit_iterator i = that.begin(); i != that.end(); i++) { add(i->first, i->second); } }
map_location under_leadership(const unit_map& units, const map_location& loc, int* bonus) { const unit_map::const_iterator un = units.find(loc); if(un == units.end()) { return map_location::null_location; } unit_ability_list abil = un->get_abilities("leadership"); if(bonus) { *bonus = abil.highest("value").first; } return abil.highest("value").second; }
//-----------------------------------------------------------------// uint32_t find(const std::string& path) const { auto fpath = create_full_path(path); if(fpath.empty()) { return 0; } unit_map_cit cit = unit_map_.find(fpath); if(cit != unit_map_.end()) { return cit->second.get_id(); } else { return 0; } }
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(); }
bool can_up_treasure(unit_map& units, const hero& h) { if (tent::tower_mode()) { return true; } unit* u = units.find_unit(h); if (u->is_city()) { return true; } artifical* city = units.city_from_loc(u->get_location()); if (city) { return true; } return false; }
battle_context::battle_context(const unit_map& units, const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon, int defender_weapon, double aggression, const combatant *prev_def, const unit* attacker_ptr) : attacker_stats_(nullptr), defender_stats_(nullptr), attacker_combatant_(nullptr), defender_combatant_(nullptr) { const unit &attacker = attacker_ptr ? *attacker_ptr : *units.find(attacker_loc); const unit &defender = *units.find(defender_loc); const double harm_weight = 1.0 - aggression; if (attacker_weapon == -1 && attacker.attacks().size() == 1 && attacker.attacks()[0].attack_weight() > 0 ) attacker_weapon = 0; if (attacker_weapon == -1) { attacker_weapon = choose_attacker_weapon(attacker, defender, units, attacker_loc, defender_loc, harm_weight, &defender_weapon, prev_def); } else if (defender_weapon == -1) { defender_weapon = choose_defender_weapon(attacker, defender, attacker_weapon, units, attacker_loc, defender_loc, prev_def); } // If those didn't have to generate statistics, do so now. if (!attacker_stats_) { const attack_type *adef = nullptr; const attack_type *ddef = nullptr; if (attacker_weapon >= 0) { VALIDATE(attacker_weapon < static_cast<int>(attacker.attacks().size()), _("An invalid attacker weapon got selected.")); adef = &attacker.attacks()[attacker_weapon]; } if (defender_weapon >= 0) { VALIDATE(defender_weapon < static_cast<int>(defender.attacks().size()), _("An invalid defender weapon got selected.")); ddef = &defender.attacks()[defender_weapon]; } assert(!defender_stats_ && !attacker_combatant_ && !defender_combatant_); attacker_stats_ = new battle_context_unit_stats(attacker, attacker_loc, attacker_weapon, true, defender, defender_loc, ddef, units); defender_stats_ = new battle_context_unit_stats(defender, defender_loc, defender_weapon, false, attacker, attacker_loc, adef, units); } // There have been various bugs where only one of these was set assert(attacker_stats_); assert(defender_stats_); }
void recall::apply_temp_modifier(unit_map& unit_map) { assert(valid_); temp_unit_->set_location(recall_hex_); DBG_WB << "Inserting future recall " << temp_unit_->name() << " [" << temp_unit_->id() << "] at position " << temp_unit_->get_location() << ".\n"; //temporarily remove unit from recall list std::vector<unit>& recalls = resources::teams->at(team_index()).recall_list(); std::vector<unit>::iterator it = std::find_if(recalls.begin(), recalls.end(), unit_comparator_predicate(*temp_unit_)); assert(it != recalls.end()); recalls.erase(it); // Temporarily insert unit into unit_map unit_map.insert(temp_unit_); //unit map takes ownership of temp_unit temp_unit_ = NULL; //Add cost to money spent on recruits. temp_cost_ = resources::teams->at(team_index()).recall_cost(); resources::teams->at(team_index()).get_side_actions()->change_gold_spent_by(temp_cost_); // Update gold in top bar resources::screen->invalidate_game_status(); }
bool can_generate(const gamemap& map, const std::vector<team>& teams, const unit_map& units, const unit& u, const map_location& loc) { if (!map.on_board(loc)) { return false; } if (u.movement_cost(map[loc]) == unit_movement_type::UNREACHABLE) { return false; } unit_map::const_iterator it = units.find(loc, false); if (it.valid() && !it->can_stand(u)) { return false; } map_location locs[6]; get_adjacent_tiles(loc, locs); for (int i = 0; i != 6; ++i) { if (!map.on_board(locs[i])) { continue; } if (u.movement_cost(map[locs[i]]) != unit_movement_type::UNREACHABLE) { return true; } } return false; }
void unit_map::swap(unit_map& o) { assert(num_iters() == 0 && o.num_iters() == 0); std::swap(umap_, o.umap_); std::swap(lmap_, o.lmap_); }
void recall::apply_temp_modifier(unit_map& unit_map) { assert(valid()); temp_unit_->set_location(recall_hex_); DBG_WB << "Inserting future recall " << temp_unit_->name() << " [" << temp_unit_->id() << "] at position " << temp_unit_->get_location() << ".\n"; //temporarily remove unit from recall list UnitPtr it = resources::teams->at(team_index()).recall_list().extract_if_matches_id(temp_unit_->id()); assert(it); //Add cost to money spent on recruits. int cost = resources::teams->at(team_index()).recall_cost(); if (it->recall_cost() > -1) { cost = it->recall_cost(); } // Temporarily insert unit into unit_map //unit map takes ownership of temp_unit unit_map.insert(temp_unit_); resources::teams->at(team_index()).get_side_actions()->change_gold_spent_by(cost); // Update gold in top bar resources::screen->invalidate_game_status(); }
void unit_map::swap(unit_map &o) { assert(num_iters()==0 && o.num_iters() == 0); std::swap(umap_, o.umap_); std::swap(lmap_, o.lmap_); std::swap(ilist_, o.ilist_); std::swap(the_end_, o.the_end_); }
//-----------------------------------------------------------------// bool is_directory(unit_map_cit cit) const { if(cit != unit_map_.end()) { return cit->first.back() == '/'; } else { return false; } }
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(); }
void recall::remove_temp_modifier(unit_map& unit_map) { temp_unit_ = unit_map.extract(recall_hex_); assert(temp_unit_.get()); //Put unit back into recall list resources::teams->at(team_index()).recall_list().add(temp_unit_); }
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 clear() { unit_map_.clear(); handle_set_.clear(); current_path_ = "/"; string_stack a; a.swap(stack_path_); make_directory(""); }
void tmkwin_theme::fill_object_list(const unit_map& units) { tlistbox* list = dynamic_cast<tlistbox*>(get_object("object-list")); list->clear(); const map_location& selected_hex = controller_.selected_hex(); std::stringstream ss; int index = 0; int cursel = 0; for (unit_map::const_iterator it = units.begin(); it != units.end(); ++ it) { unit& u = *dynamic_cast<unit*>(&*it); if (u.type() != unit::WIDGET) { continue; } if (u.get_location() == selected_hex) { cursel = index; } string_map list_item; std::map<std::string, string_map> list_item_item; list_item["label"] = str_cast(index ++); list_item_item.insert(std::make_pair("number", list_item)); list_item["label"] = u.cell().id; list_item_item.insert(std::make_pair("id", list_item)); ss.str(""); const SDL_Rect& rect = u.get_rect(); // ss << rect.x << "," << rect.y << "," << rect.w << "," << rect.h; ss << rect.x << "," << rect.y; list_item["label"] = ss.str(); list_item_item.insert(std::make_pair("rect", list_item)); list->add_row(list_item_item); tgrid* grid = list->get_row_grid(list->get_item_count() - 1); grid->set_cookie(reinterpret_cast<void*>(&u)); } if (list->get_item_count()) { list->select_row(cursel); } list->invalidate_layout(true); // window.invalidate_layout(); }
void move_candidate_action::evaluate(ai::formula_ai* ai, unit_map& units) { score_ = 0; candidate_action_filters::const_iterator me_filter = filter_map_.find("me"); std::vector<variant> unit_vector; for(unit_map::unit_iterator i = units.begin() ; i != units.end() ; ++i) { if (i->side() == ai->get_side() && i->movement_left() > 0) { unit_vector.push_back(variant(new unit_callable(*i))); } } variant my_units(&unit_vector); variant filtered_units; try { if(me_filter != filter_map_.end() ) filtered_units = do_filtering(ai, my_units, me_filter->second); else filtered_units=my_units; } catch(formula_error& e) { ai->handle_exception(e, "Error while executing filter formula for '" + get_name() + "' Candidate Action"); return; } for(variant_iterator i = filtered_units.begin() ; i != filtered_units.end() ; ++i) { game_logic::map_formula_callable callable(static_cast<const formula_callable*>(ai)); callable.add("me", *i); int res = execute_formula(eval_, callable, ai); if(res > score_) { score_ = res; my_unit_ = *i; } } }
//-----------------------------------------------------------------// bool is_directory(const std::string& path) const { auto fpath = create_full_path(path); if(fpath.empty()) { return false; } if(fpath.back() != '/') fpath += '/'; return is_directory(unit_map_.find(fpath)); }
paths::paths(gamemap const &map, unit_map const &units, map_location const &loc, std::vector<team> const &teams, bool force_ignore_zoc, bool allow_teleport, const team &viewing_team, int additional_turns, bool see_all, bool ignore_units) : destinations() { const unit_map::const_iterator i = units.find(loc); if(i == units.end()) { ERR_PF << "paths::paths() -- unit not found\n"; return; } if(i->second.side() < 1 || i->second.side() > int(teams.size())) { return; } find_routes(map,units,i->second,loc, i->second.movement_left(), destinations, teams, force_ignore_zoc, allow_teleport,additional_turns,viewing_team, see_all, ignore_units); }