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 basic_unit_filter_impl::matches(const unit & u, const map_location& loc, const unit * u2) const { bool matches = true; if(loc.valid()) { scoped_xy_unit auto_store("this_unit", loc, fc_.get_disp_context().units()); if (u2) { const map_location& loc2 = u2->get_location(); scoped_xy_unit auto_store("other_unit", loc2, fc_.get_disp_context().units()); matches = internal_matches_filter(u, loc, u2); } else { matches = internal_matches_filter(u, loc, u2); } } else { // If loc is invalid, then this is a recall list unit (already been scoped) matches = internal_matches_filter(u, loc, nullptr); } // Handle [and], [or], and [not] with in-order precedence for (size_t i = 0; i < cond_children_.size(); i++) { switch (cond_child_types_[i].v) { case conditional::TYPE::AND: matches = matches && cond_children_[i].matches(u,loc); break; case conditional::TYPE::OR: matches = matches || cond_children_[i].matches(u,loc); break; case conditional::TYPE::NOT: matches = matches && !cond_children_[i].matches(u,loc); } } return matches; }
void game_display::select_hex(map_location hex) { if(hex.valid() && fogged(hex)) { return; } display::select_hex(hex); display_unit_hex(hex); }
// Notice: caller must make sure loc of parameter is centor location of desired erase unit! bool base_map::erase(const map_location& loc, bool overlay) { if (!loc.valid()) { return false; } base_unit* u = overlay? coor_map_[index(loc.x, loc.y)].overlay: coor_map_[index(loc.x, loc.y)].base; if (!u) { return false; } return erase2(u); }
void game_display::display_unit_hex(map_location hex) { if (!hex.valid()) return; wb::future_map future; /**< Lasts for whole method. */ const unit *u = resources::gameboard->get_visible_unit(hex, dc_->teams()[viewing_team()], !dont_show_all_); if (u) { displayedUnitHex_ = hex; invalidate_unit(); } }
void game_display::display_unit_hex(map_location hex) { if (!hex.valid()) return; wb::future_map future; //< Lasts for whole method. const unit *u = get_visible_unit(hex, (*teams_)[viewing_team()], !viewpoint_); if (u) { displayedUnitHex_ = hex; invalidate_unit(); } }
void highlighter::set_mouseover_hex(const map_location& hex) { clear(); if(!hex.valid()) { return; } real_map ensure_real_map; mouseover_hex_ = hex; //if we're right over a unit, just highlight all of this unit's actions unit_map::iterator it = get_unit_map().find(hex); if(it != get_unit_map().end()) { selection_candidate_ = it.get_shared_ptr(); if(resources::gameboard->teams().at(it->side()-1).get_side_actions()->unit_has_actions(*it)) { owner_unit_ = it.get_shared_ptr(); } //commented code below is to also select the first action of this unit as //the main highlight; it doesn't fit too well in the UI // side_actions::iterator action_it = side_actions_->find_first_action_of(*it); // if(action_it != side_actions_->end()) { // main_highlight_ = *action_it; // } } //Set the execution/deletion/bump targets. if(owner_unit_) { side_actions::iterator itor = side_actions_->find_first_action_of(*owner_unit_); if(itor != side_actions_->end()) { selected_action_ = *itor; } } //Overwrite the above selected_action_ if we find a better one if(side_actions_->empty()) { return; } for(action_ptr act : boost::adaptors::reverse(*side_actions_)) { /**@todo "is_numbering_hex" is not the "correct" criterion by which to * select the hightlighted/selected action. It's just convenient for me * to use at the moment since it happens to coincide with the "correct" * criterion, which is to use find_main_highlight.*/ if(act->is_numbering_hex(hex)) { selected_action_ = act; break; } } }
config replay_helper::get_event(const std::string& name, const map_location& loc, const map_location* last_select_loc) { config ev; ev["raise"] = name; if(loc.valid()) { config& source = ev.add_child("source"); loc.write(source); } if(last_select_loc != nullptr && last_select_loc->valid()) { config& source = ev.add_child("last_select"); last_select_loc->write(source); } return ev; }
void gamemap::set_special_location(const std::string& id, const map_location& loc) { bool valid = loc.valid(); auto it_left = starting_positions_.left.find(id); if (it_left != starting_positions_.left.end()) { if (valid) { starting_positions_.left.replace_data(it_left, loc); } else { starting_positions_.left.erase(it_left); } } else { starting_positions_.left.insert(it_left, std::make_pair(id, loc)); } }
const time_of_day tod_manager::get_illuminated_time_of_day(const map_location& loc, int for_turn) const { // get ToD ignoring illumination time_of_day tod = get_time_of_day(loc, for_turn); // now add illumination const gamemap& map = *resources::game_map; const unit_map& units = *resources::units; int light_modif = map.get_terrain_info(map.get_terrain(loc)).light_modification(); int light = tod.lawful_bonus + light_modif; int illum_light = light; 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->get_ability_bool("illuminates") && !itor->incapacitated()) { unit_ability_list illum = itor->get_abilities("illuminates"); unit_abilities::effect illum_effect(illum, light, false); illum_light = light + illum_effect.get_composite_value(); //max_value and min_value control the final result //unless ToD + terrain effect is stronger int max = std::max(light, illum.highest("max_value").first); int min = std::min(light, illum.lowest("min_value").first); if(illum_light > max) { illum_light = max; } else if (illum_light < min) { illum_light = min; } } } } tod.bonus_modified = illum_light - tod.lawful_bonus; tod.lawful_bonus = illum_light; return tod; }
void base_map::insert(const map_location loc, base_unit* u) { std::stringstream err; if (!loc.valid()) { err << "Trying to add " << u->name() << " at an invalid location; Discarding."; delete u; VALIDATE(false, err.str()); } bool base = u->base(); if ((base && coor_map_[index(loc.x, loc.y)].base) || (!base && coor_map_[index(loc.x, loc.y)].overlay)) { err << "trying to overwrite existing unit at (" << loc.x << ", " << loc.y << ")"; delete u; VALIDATE(false, err.str()); } // some application maybe require coor_map_ valid before set_location. // but touch_locs is got after set_location. only valid on center location. if (base) { coor_map_[index(loc.x, loc.y)].base = u; } else { coor_map_[index(loc.x, loc.y)].overlay = u; } u->set_location(loc); // it is called after set_location directly, use touch_locs safely. const std::set<map_location>& touch_locs = u->get_touch_locations(); if (touch_locs.size() != 1) { for (std::set<map_location>::const_iterator itor = touch_locs.begin(); itor != touch_locs.end(); ++ itor) { if (base) { coor_map_[index(itor->x, itor->y)].base = u; } else { coor_map_[index(itor->x, itor->y)].overlay = u; } } } // insert p into time-axis.* u->map_index_ = map_vsize_; map_[map_vsize_ ++] = u; if (u->require_sort()) { sort_map(*u); } }
time_of_day tod_manager::get_time_of_day(int illuminated, const map_location& loc, int n_turn) const { time_of_day res = get_time_of_day_turn(n_turn); if(loc.valid()) { for(std::vector<area_time_of_day>::const_iterator i = areas_.begin(); i != areas_.end(); ++i) { if(i->hexes.count(loc) == 1) { VALIDATE(i->times.size(), _("No time of day has been defined.")); res = i->times[(n_turn-1)%i->times.size()]; break; } } } if(illuminated) { res.bonus_modified=illuminated; res.lawful_bonus += illuminated; } return res; }
bool gamemap::on_board(const map_location& loc) const { return loc.valid() && loc.x < w_ && loc.y < h_; }
pathfind::plain_route pathfind::a_star_search(const map_location& src, const map_location& dst, double stop_at, const cost_calculator *calc, const size_t width, const size_t height, const teleport_map *teleports) { //----------------- PRE_CONDITIONS ------------------ assert(src.valid(width, height)); assert(dst.valid(width, height)); assert(calc != NULL); assert(stop_at <= calc->getNoPathValue()); //--------------------------------------------------- DBG_PF << "A* search: " << src << " -> " << dst << '\n'; if (calc->cost(dst, 0) >= stop_at) { LOG_PF << "aborted A* search because Start or Dest is invalid\n"; pathfind::plain_route locRoute; locRoute.move_cost = int(calc->getNoPathValue()); return locRoute; } // increment search_counter but skip the range equivalent to uninitialized search_counter += 2; if (search_counter - bad_search_counter <= 1u) search_counter += 2; static std::vector<node> nodes; nodes.resize(width * height); // this create uninitalized nodes indexer index(width, height); comp node_comp(nodes); nodes[index(dst)].g = stop_at + 1; nodes[index(src)] = node(0, src, map_location::null_location, dst, true, teleports); std::vector<int> pq; pq.push_back(index(src)); while (!pq.empty()) { node& n = nodes[pq.front()]; n.in = search_counter; std::pop_heap(pq.begin(), pq.end(), node_comp); pq.pop_back(); if (n.t >= nodes[index(dst)].g) break; std::vector<map_location> locs; int i; if (teleports && !teleports->empty()) { std::set<map_location> allowed_teleports; teleports->get_adjacents(allowed_teleports, n.curr); i = allowed_teleports.size() +6; locs = std::vector<map_location>(i); std::copy(allowed_teleports.begin(), allowed_teleports.end(), locs.begin() + 6); } else { locs = std::vector<map_location>(6); i = 6;} get_adjacent_tiles(n.curr, &locs[0]); for (; i-- > 0;) { if (!locs[i].valid(width, height)) continue; if (locs[i] == n.curr) continue; node& next = nodes[index(locs[i])]; double thresh = (next.in - search_counter <= 1u) ? next.g : stop_at + 1; // cost() is always >= 1 (assumed and needed by the heuristic) if (n.g + 1 >= thresh) continue; double cost = n.g + calc->cost(locs[i], n.g); if (cost >= thresh) continue; bool in_list = next.in == search_counter + 1; next = node(cost, locs[i], n.curr, dst, true, teleports); if (in_list) { std::push_heap(pq.begin(), std::find(pq.begin(), pq.end(), static_cast<int>(index(locs[i]))) + 1, node_comp); } else { pq.push_back(index(locs[i])); std::push_heap(pq.begin(), pq.end(), node_comp); } } } pathfind::plain_route route; if (nodes[index(dst)].g <= stop_at) { DBG_PF << "found solution; calculating it...\n"; route.move_cost = static_cast<int>(nodes[index(dst)].g); for (node curr = nodes[index(dst)]; curr.prev != map_location::null_location; curr = nodes[index(curr.prev)]) { route.steps.push_back(curr.curr); } route.steps.push_back(src); std::reverse(route.steps.begin(), route.steps.end()); } else { LOG_PF << "aborted a* search " << "\n"; route.move_cost = static_cast<int>(calc->getNoPathValue()); } return route; }