twidget* tbuilder_panel::build() const { tpanel* panel = new tpanel(); init_control(panel); DBG_GUI << "Window builder: placed panel '" << id << "' with defintion '" << definition << "'.\n"; log_scope2(gui, "Window builder: building grid for panel."); const unsigned rows = grid->rows; const unsigned cols = grid->cols; panel->set_rows_cols(rows, cols); for(unsigned x = 0; x < rows; ++x) { panel->set_row_grow_factor(x, grid->row_grow_factor[x]); for(unsigned y = 0; y < cols; ++y) { if(x == 0) { panel->set_col_grow_factor(y, grid->col_grow_factor[y]); } twidget* widget = grid->widgets[x * cols + y]->build(); panel->set_child(widget, x, y, grid->flags[x * cols + y], grid->border_size[x * cols + y]); } } return panel; }
tpoint tscrollbar_container::calculate_best_size() const { log_scope2(log_gui_layout, LOG_SCOPE_HEADER); /***** get vertical scrollbar size *****/ const tpoint vertical_scrollbar = vertical_scrollbar_grid_->get_visible() == twidget::INVISIBLE ? tpoint(0, 0) : vertical_scrollbar_grid_->get_best_size(); /***** get horizontal scrollbar size *****/ const tpoint horizontal_scrollbar = horizontal_scrollbar_grid_->get_visible() == twidget::INVISIBLE ? tpoint(0, 0) : horizontal_scrollbar_grid_->get_best_size(); /***** get content size *****/ assert(content_grid_); const tpoint content = content_grid_->get_best_size(); const tpoint result( vertical_scrollbar.x + std::max(horizontal_scrollbar.x, content.x), horizontal_scrollbar.y + std::max(vertical_scrollbar.y, content.y)); DBG_GUI_L << LOG_HEADER << " vertical_scrollbar " << vertical_scrollbar << " horizontal_scrollbar " << horizontal_scrollbar << " content " << content << " result " << result << ".\n"; return result; }
void tgrid::reduce_height(const unsigned maximum_height) { /***** ***** ***** ***** INIT ***** ***** ***** *****/ log_scope2(log_gui_layout, LOG_SCOPE_HEADER); DBG_GUI_L << LOG_HEADER << " maximum height " << maximum_height << ".\n"; tpoint size = get_best_size(); if(size.y <= static_cast<int>(maximum_height)) { DBG_GUI_L << LOG_HEADER << " Already fits.\n"; return; } /***** ***** ***** ***** Request resize ***** ***** ***** *****/ request_reduce_height(maximum_height); size = get_best_size(); if(size.y <= static_cast<int>(maximum_height)) { DBG_GUI_L << LOG_HEADER << " Resize request honored.\n"; return; } /***** ***** ***** ***** Demand resize ***** ***** ***** *****/ /** @todo Implement. */ /***** ***** ***** ***** Acknowlegde failure ***** ***** ***** *****/ DBG_GUI_L << LOG_HEADER << " Resizing failed.\n"; throw tlayout_exception_height_resize_failed(); }
tpoint tcontainer_::calculate_best_size() const { log_scope2(log_gui_layout, LOG_SCOPE_HEADER); tpoint result(grid_.get_best_size()); const tpoint border_size = border_space(); const tpoint minimum_size = get_config_minimum_size(); // If the best size has a value of 0 it's means no limit so don't // add the border_size might set a very small best size. if(result.x) { result.x += border_size.x; } if(minimum_size.x != 0 && result.x < minimum_size.x) { result.x = minimum_size.x; } if(result.y) { result.y += border_size.y; } if(minimum_size.y != 0 && result.y < minimum_size.y) { result.y = minimum_size.y; } DBG_GUI_L << LOG_HEADER << " border size " << border_size << " returning " << result << ".\n"; return result; }
void tbuilder_grid::build(tgrid& grid, const treplacements& replacements) const { grid.set_id(id); grid.set_linked_group(linked_group); grid.set_rows_cols(rows, cols); log_scope2(log_gui_general, "Window builder: building grid"); DBG_GUI_G << "Window builder: grid '" << id << "' has " << rows << " rows and " << cols << " columns.\n"; for(unsigned x = 0; x < rows; ++x) { grid.set_row_grow_factor(x, row_grow_factor[x]); for(unsigned y = 0; y < cols; ++y) { if(x == 0) { grid.set_column_grow_factor(y, col_grow_factor[y]); } DBG_GUI_G << "Window builder: adding child at " << x << ',' << y << ".\n"; grid.set_child(widgets[x * cols + y]->build(replacements), x, y, flags[x * cols + y], border_size[x * cols + y]); } } }
tpoint tslider::calculate_best_size() const { log_scope2(log_gui_layout, LOG_SCOPE_HEADER); // Inherited. tpoint result = tcontrol::calculate_best_size(); if(best_slider_length_ != 0) { // Override length. boost::intrusive_ptr<const tslider_definition::tresolution> conf = boost::dynamic_pointer_cast<const tslider_definition::tresolution> (config()); assert(conf); result.x = conf->left_offset + best_slider_length_ + conf->right_offset; } DBG_GUI_L << LOG_HEADER << " best_slider_length " << best_slider_length_ << " result " << result << ".\n"; return result; }
void tcontainer_::init_grid( const boost::intrusive_ptr<tbuilder_grid>& grid_builder) { log_scope2(log_gui_general, LOG_SCOPE_HEADER); assert(initial_grid().get_rows() == 0 && initial_grid().get_cols() == 0); grid_builder->build(&initial_grid()); }
template<typename T> void dump(const T & units) { log_scope2(log_display, "dump()") LOG_DP << "size: " << units.size() << "\n"; size_t idx = 0; for (const unit_const_ptr & u_ptr : units) { LOG_DP << "unit[" << (idx++) << "]: " << u_ptr->id() << " name = '" << u_ptr->name() << "'\n"; } }
static void dump_recall_list_to_console(const T& units) { log_scope2(log_display, "dump_recall_list_to_console()") LOG_DP << "size: " << units.size() << "\n"; std::size_t idx = 0; for(const unit_const_ptr& u_ptr : units) { LOG_DP << "\tunit[" << (idx++) << "]: " << u_ptr->id() << " name = '" << u_ptr->name() << "'\n"; } }
void handle_event_command(const std::string &cmd, const queued_event &event_info, const vconfig &cfg) { log_scope2(log_engine, "handle_event_command"); LOG_NG << "handling command '" << cmd << "' from cfg 0x" << std::hex << std::setiosflags(std::ios::uppercase) << reinterpret_cast<uintptr_t>(&cfg.get_config()) << std::dec << "\n"; if (!resources::lua_kernel->run_wml_action(cmd, cfg, event_info)) { ERR_NG << "Couldn't find function for wml tag: "<< cmd <<"\n"; } DBG_NG << "done handling command...\n"; }
void tcontrol::layout_fit_width(const unsigned maximum_width, const tfit_flags flags) { assert(get_visible() != twidget::INVISIBLE); log_scope2(gui_layout, "tcontrol(" + get_control_type() + ") " + __func__); DBG_G_L << "maximum_width " << maximum_width << " flags " << flags << ".\n"; // Already fits. if(get_best_size().x <= static_cast<int>(maximum_width)) { DBG_G_L << "Already fits.\n"; return; } // Wrap. if((flags & twidget::WRAP) && can_wrap()) { layout_wrap(maximum_width); if(get_best_size().x <= static_cast<int>(maximum_width)) { DBG_G_L << "Success: Wrapped.\n"; return; } } // Horizontal scrollbar. if((flags & twidget::SCROLLBAR) && has_horizontal_scrollbar()) { layout_use_horizontal_scrollbar(maximum_width); if(get_best_size().x <= static_cast<int>(maximum_width)) { DBG_G_L << "Success: Horizontal scrollbar.\n"; return; } } // Shrink. if((flags & twidget::SHRINK) && can_shrink_width()) { layout_shrink_width(maximum_width); DBG_G_L << "Success: Shrunken.\n"; } DBG_G_L << "Failed.\n"; }
tpoint tscrollbar_container::calculate_best_size() const { log_scope2(log_gui_layout, LOG_SCOPE_HEADER); /***** get vertical scrollbar size *****/ const tpoint vertical_scrollbar = vertical_scrollbar_grid_->get_visible() == twidget::tvisible::invisible ? tpoint() : vertical_scrollbar_grid_->get_best_size(); /***** get horizontal scrollbar size *****/ const tpoint horizontal_scrollbar = horizontal_scrollbar_grid_->get_visible() == twidget::tvisible::invisible ? tpoint() : horizontal_scrollbar_grid_->get_best_size(); /***** get content size *****/ assert(content_grid_); const tpoint content = content_grid_->get_best_size(); tpoint result( vertical_scrollbar.x + std::max(horizontal_scrollbar.x, content.x), horizontal_scrollbar.y + std::max(vertical_scrollbar.y, content.y)); // // Workaround for bug #24780. This should probably be moved somewhere more specific to // the listbox, but for now it suffices. // if(const tgrid* header = find_widget<const tgrid>(&grid(), "_header_grid", false, false)) { result.y += header->get_best_size().y; } if(const tgrid* footer = find_widget<const tgrid>(&grid(), "_footer_grid", false, false)) { result.y += footer->get_best_size().y; } DBG_GUI_L << LOG_HEADER << " vertical_scrollbar " << vertical_scrollbar << " horizontal_scrollbar " << horizontal_scrollbar << " content " << content << " result " << result << ".\n"; return result; }
/*WIKI * @page = GUIToolkitWML * @order = 2_cell * @begin{parent}{name="gui/window/resolution/"} * = Cell = * @begin{tag}{name="grid"}{min="1"}{max="1"} * @begin{table}{config} * id & string & "" & A grid is a widget and can have an id. This isn't * used that often, but is allowed. $ * linked_group & string & 0 & $ * @end{table} * * Every grid cell has some cell configuration values and one widget in the grid * cell. Here we describe the what is available more information about the usage * can be found here [[GUILayout]]. * * == Row values == * @begin{tag}{name="row"}{min="0"}{max="-1"} * For every row the following variables are available: * * @begin{table}{config} * grow_factor & unsigned & 0 & The grow factor for a row. $ * @end{table} * * == Cell values == * @begin{tag}{name="column"}{min="0"}{max="-1"} * @allow{link}{name="gui/window/resolution/grid"} * For every column the following variables are available: * @begin{table}{config} * grow_factor & unsigned & 0 & The grow factor for a column, this * value is only read for the first row. $ * * border_size & unsigned & 0 & The border size for this grid cell. $ * border & border & "" & Where to place the border in this grid * cell. $ * * vertical_alignment & v_align & "" & * The vertical alignment of the widget in * the grid cell. (This value is ignored if * vertical_grow is true.) $ * horizontal_alignment & h_align & "" & * The horizontal alignment of the widget in * the grid cell.(This value is ignored if * horizontal_grow is true.) $ * * vertical_grow & bool & false & Does the widget grow in vertical * direction when the grid cell grows in the * vertical direction. This is used if the * grid cell is wider as the best width for * the widget. $ * horizontal_grow & bool & false & Does the widget grow in horizontal * direction when the grid cell grows in the * horizontal direction. This is used if the * grid cell is higher as the best width for * the widget. $ * @end{table} * @end{tag}{name="column"} * @end{tag}{name="row"} * @end{tag}{name="grid"} * @end{parent}{name="gui/window/resolution/"} * */ tbuilder_grid::tbuilder_grid(const config& cfg) : tbuilder_widget(cfg) , rows(0) , cols(0) , row_grow_factor() , col_grow_factor() , flags() , border_size() , widgets() { log_scope2(log_gui_parse, "Window builder: parsing a grid"); for(const auto & row : cfg.child_range("row")) { unsigned col = 0; row_grow_factor.push_back(row["grow_factor"]); for(const auto & c : row.child_range("column")) { flags.push_back(implementation::read_flags(c)); border_size.push_back(c["border_size"]); if(rows == 0) { col_grow_factor.push_back(c["grow_factor"]); } widgets.push_back(create_builder_widget(c)); ++col; } ++rows; if(rows == 1) { cols = col; } else { VALIDATE(col, _("A row must have a column.")); VALIDATE(col == cols, _("Number of columns differ.")); } } DBG_GUI_P << "Window builder: grid has " << rows << " rows and " << cols << " columns.\n"; }
tpoint tgrid::calculate_best_size() const { log_scope2(log_gui_layout, LOG_SCOPE_HEADER); // Reset the cached values. row_height_.clear(); row_height_.resize(rows_, 0); col_width_.clear(); col_width_.resize(cols_, 0); // First get the sizes for all items. for(unsigned row = 0; row < rows_; ++row) { for(unsigned col = 0; col < cols_; ++col) { const tpoint size = child(row, col).get_best_size(); if(size.x > static_cast<int>(col_width_[col])) { col_width_[col] = size.x; } if(size.y > static_cast<int>(row_height_[row])) { row_height_[row] = size.y; } } } for(unsigned row = 0; row < rows_; ++row) { DBG_GUI_L << LOG_HEADER << " the row_height_ for row " << row << " will be " << row_height_[row] << ".\n"; } for(unsigned col = 0; col < cols_; ++col) { DBG_GUI_L << LOG_HEADER << " the col_width_ for column " << col << " will be " << col_width_[col] << ".\n"; } const tpoint result( std::accumulate(col_width_.begin(), col_width_.end(), 0), std::accumulate(row_height_.begin(), row_height_.end(), 0)); DBG_GUI_L << LOG_HEADER << " returning " << result << ".\n"; return result; }
/*WIKI * @page = GUIWidgetInstanceWML * @order = 1 * * THIS PAGE IS AUTOMATICALLY GENERATED, DO NOT MODIFY DIRECTLY !!! * * = Widget instance = * * Inside a grid (which is inside all container widgets) a widget is * instantiated. With this instantiation some more variables of a widget can * be tuned. This page will describe what can be tuned. * */ twindow* build(CVideo& video, const std::string& type) { std::vector<twindow_builder::tresolution>::const_iterator definition = get_window_builder(type); // We set the values from the definition since we can only determine the // best size (if needed) after all widgets have been placed. twindow* window = new twindow(video, definition->x, definition->y, definition->width, definition->height, definition->automatic_placement, definition->horizontal_placement, definition->vertical_placement, definition->definition); assert(window); log_scope2(gui, "Window builder: building grid for window"); window->set_easy_close(definition->easy_close); const unsigned rows = definition->grid->rows; const unsigned cols = definition->grid->cols; window->set_rows_cols(rows, cols); for(unsigned x = 0; x < rows; ++x) { window->set_row_grow_factor(x, definition->grid->row_grow_factor[x]); for(unsigned y = 0; y < cols; ++y) { if(x == 0) { window->set_col_grow_factor(y, definition->grid->col_grow_factor[y]); } twidget* widget = definition->grid->widgets[x * cols + y]->build(); window->set_child(widget, x, y, definition->grid->flags[x * cols + y], definition->grid->border_size[x * cols + y]); } } window->add_to_keyboard_chain(window); return window; }
point slider::calculate_best_size() const { log_scope2(log_gui_layout, LOG_SCOPE_HEADER); // Inherited. point result = styled_widget::calculate_best_size(); if(best_slider_length_ != 0) { // Override length. std::shared_ptr<const slider_definition::resolution> conf = std::static_pointer_cast<const slider_definition:: resolution>(config()); assert(conf); result.x = conf->left_offset + best_slider_length_ + conf->right_offset; } DBG_GUI_L << LOG_HEADER << " best_slider_length " << best_slider_length_ << " result " << result << ".\n"; return result; }
bool ai_default_recruitment_stage::recruit_usage(const std::string& usage) { raise_user_interact(); analyze_all(); const int min_gold = 0; log_scope2(log_ai, "recruiting troops"); LOG_AI << "recruiting '" << usage << "'\n"; //make sure id, usage and cost are known for the coming evaluation of unit types unit_types.build_all(unit_type::HELP_INDEXED); std::vector<std::string> options; bool found = false; // Find an available unit that can be recruited, // matches the desired usage type, and comes in under budget. BOOST_FOREACH(const std::string &name, current_team().recruits()) { const unit_type *ut = unit_types.find(name); if (!ut) continue; // If usage is empty consider any unit. if (usage.empty() || ut->usage() == usage) { LOG_AI << name << " considered for " << usage << " recruitment\n"; found = true; if (current_team().gold() - ut->cost() < min_gold) { LOG_AI << name << " rejected, cost too high (cost: " << ut->cost() << ", current gold: " << current_team().gold() <<", min_gold: " << min_gold << ")\n"; continue; } if (not_recommended_units_.count(name)) { LOG_AI << name << " rejected, bad terrain or combat\n"; continue; } std::map<std::string,int>::iterator imc = maximum_counts_.find(name); if (imc != maximum_counts_.end()) { int count_active = 0; for (unit_map::const_iterator u = resources::units->begin(); u != resources::units->end(); ++u) { if (u->side() == get_side() && !u->incapacitated() && u->type().base_id() == name) { ++count_active; } } if (count_active >= imc->second) { LOG_AI << name << " rejected, too many in the field\n"; continue; } } LOG_AI << "recommending '" << name << "'\n"; options.push_back(name); } } // From the available options, choose one at random if(options.empty() == false) { const int option = rand()%options.size(); recruit_result_ptr recruit_res = check_recruit_action(options[option]); if (recruit_res->is_ok()) { recruit_res->execute(); if (!recruit_res->is_ok()) { ERR_AI << "recruitment failed "<< std::endl; } } return recruit_res->is_gamestate_changed(); } if (found) { LOG_AI << "No available units to recruit that come under the price.\n"; } else if (usage != "") { //FIXME: This message should be suppressed when WML author //chooses the default recruitment pattern. const std::string warning = "At difficulty level " + resources::classification->difficulty + ", trying to recruit a:" + usage + " but no unit of that type (usage=) is" " available. Check the recruit and [ai]" " recruitment_pattern keys for team '" + current_team().current_player() + "' (" + lexical_cast<std::string>(get_side()) + ")" " against the usage key of the" " units in question! Removing invalid" " recruitment_pattern entry and continuing...\n"; WRN_AI << warning; // Uncommented until the recruitment limiting macro can be fixed to not trigger this warning. //lg::wml_error << warning; //@fixme //return current_team_w().remove_recruitment_pattern_entry(usage); return false; } return false; }
point styled_widget::get_best_text_size(point minimum_size, point maximum_size) const { log_scope2(log_gui_layout, LOG_SCOPE_HEADER); assert(!label_.empty()); const point border(config_->text_extra_width, config_->text_extra_height); point size = minimum_size - border; renderer_.set_link_aware(get_link_aware()) .set_link_color(get_link_color()); renderer_.set_text(label_, use_markup_); renderer_.set_family_class(config_->text_font_family); renderer_.set_font_size(config_->text_font_size); renderer_.set_font_style(config_->text_font_style); renderer_.set_alignment(text_alignment_); // Try with the minimum wanted size. const int maximum_width = text_maximum_width_ != 0 ? text_maximum_width_ : maximum_size.x; renderer_.set_maximum_width(maximum_width); if(can_wrap()) { renderer_.set_ellipse_mode(PANGO_ELLIPSIZE_NONE); } renderer_.set_characters_per_line(get_characters_per_line()); if(get_characters_per_line() != 0 && !can_wrap()) { WRN_GUI_L << LOG_HEADER << " Limited the number of characters per line, " << "but wrapping is not set, output may not be as expected.\n"; } DBG_GUI_L << LOG_HEADER << " label '" << debug_truncate(label_) << "' status: " << " minimum_size " << minimum_size << " maximum_size " << maximum_size << " text_maximum_width_ " << text_maximum_width_ << " can_wrap " << can_wrap() << " characters_per_line " << get_characters_per_line() << " truncated " << renderer_.is_truncated() << " renderer size " << renderer_.get_size() << ".\n"; // If doesn't fit try the maximum. if(renderer_.is_truncated() && !can_wrap()) { // FIXME if maximum size is defined we should look at that // but also we don't adjust for the extra text space yet!!! maximum_size = point(config_->max_width, config_->max_height); renderer_.set_maximum_width(maximum_size.x ? maximum_size.x - border.x : -1); } size = renderer_.get_size() + border; if(size.x < minimum_size.x) { size.x = minimum_size.x; } if(size.y < minimum_size.y) { size.y = minimum_size.y; } DBG_GUI_L << LOG_HEADER << " label '" << debug_truncate(label_) << "' result " << size << ".\n"; return size; }
void tgrid::place(const tpoint& origin, const tpoint& size) { log_scope2(log_gui_layout, LOG_SCOPE_HEADER); /***** INIT *****/ twidget::place(origin, size); if(!rows_ || !cols_) { return; } // call the calculate so the size cache gets updated. const tpoint best_size = calculate_best_size(); assert(row_height_.size() == rows_); assert(col_width_.size() == cols_); assert(row_grow_factor_.size() == rows_); assert(col_grow_factor_.size() == cols_); DBG_GUI_L << LOG_HEADER << " best size " << best_size << " available size " << size << ".\n"; /***** BEST_SIZE *****/ if(best_size == size) { layout(origin); return; } if(best_size.x > size.x || best_size.y > size.y) { // The assertion below fails quite often so try to give as much information as possible. std::stringstream out; out << " Failed to place a grid, we have " << size << " space but we need " << best_size << " space."; out << " This happened at a grid with the id '" << id() << "'"; twidget* pw = parent(); while(pw != nullptr) { out << " in a '" << typeid(*pw).name() << "' with the id '" << pw->id() << "'"; pw = pw->parent(); } ERR_GUI_L << LOG_HEADER << out.str() << ".\n"; return; } /***** GROW *****/ // expand it. if(size.x > best_size.x) { const unsigned w = size.x - best_size.x; unsigned w_size = std::accumulate( col_grow_factor_.begin(), col_grow_factor_.end(), 0); DBG_GUI_L << LOG_HEADER << " extra width " << w << " will be divided amount " << w_size << " units in " << cols_ << " columns.\n"; if(w_size == 0) { // If all sizes are 0 reset them to 1 for(auto & val : col_grow_factor_) { val = 1; } w_size = cols_; } // We might have a bit 'extra' if the division doesn't fix exactly // but we ignore that part for now. const unsigned w_normal = w / w_size; for(unsigned i = 0; i < cols_; ++i) { col_width_[i] += w_normal * col_grow_factor_[i]; DBG_GUI_L << LOG_HEADER << " column " << i << " with grow factor " << col_grow_factor_[i] << " set width to " << col_width_[i] << ".\n"; } } if(size.y > best_size.y) { const unsigned h = size.y - best_size.y; unsigned h_size = std::accumulate( row_grow_factor_.begin(), row_grow_factor_.end(), 0); DBG_GUI_L << LOG_HEADER << " extra height " << h << " will be divided amount " << h_size << " units in " << rows_ << " rows.\n"; if(h_size == 0) { // If all sizes are 0 reset them to 1 for(auto & val : row_grow_factor_) { val = 1; } h_size = rows_; } // We might have a bit 'extra' if the division doesn't fix exactly // but we ignore that part for now. const unsigned h_normal = h / h_size; for(unsigned i = 0; i < rows_; ++i) { row_height_[i] += h_normal * row_grow_factor_[i]; DBG_GUI_L << LOG_HEADER << " row " << i << " with grow factor " << row_grow_factor_[i] << " set height to " << row_height_[i] << ".\n"; } } layout(origin); return; }
tbuilder_grid::tbuilder_grid(const config& cfg) : tbuilder_widget(cfg), id(cfg["id"]), rows(0), cols(0), row_grow_factor(), col_grow_factor(), flags(), border_size(), widgets() { /*WIKI * @page = GUIToolkitWML * @order = 2_cell * * = Cell = * * Every grid cell has some cell configuration values and one widget in the grid * cell. Here we describe the what is available more information about the usage * can be found here [[GUILayout]]. * * == Row values == * * For every row the following variables are available: * * @start_table = config * grow_factor (unsigned = 0) The grow factor for a row. * @end_table * * == Cell values == * * For every column the following variables are available: * @start_table = config * grow_factor (unsigned = 0) The grow factor for a column, this value * is only read for the first row. * * border_size (unsigned = 0) The border size for this grid cell. * border (border = "") Where to place the border in this grid * cell. * * vertical_alignment (v_align = "") * The vertical alignment of the widget in * the grid cell. (This value is ignored if * vertical_grow is true.) * horizontal_alignment (h_align = "") * The horizontal alignment of the widget in * the grid cell.(This value is ignored if * horizontal_grow is true.) * * vertical_grow (bool = false) Does the widget grow in vertical * direction when the grid cell grows in the * vertical directon. This is used if the * grid cell is wider as the best width for * the widget. * horizontal_grow (bool = false) Does the widget grow in horizontal * direction when the grid cell grows in the * horizontal directon. This is used if the * grid cell is higher as the best width for * the widget. * @end_table * */ log_scope2(gui_parse, "Window builder: parsing a grid"); const config::child_list& row_cfgs = cfg.get_children("row"); for(std::vector<config*>::const_iterator row_itor = row_cfgs.begin(); row_itor != row_cfgs.end(); ++row_itor) { unsigned col = 0; row_grow_factor.push_back(lexical_cast_default<unsigned>((**row_itor)["grow_factor"])); const config::child_list& col_cfgs = (**row_itor).get_children("column"); for(std::vector<config*>::const_iterator col_itor = col_cfgs.begin(); col_itor != col_cfgs.end(); ++col_itor) { flags.push_back(read_flags(**col_itor)); border_size.push_back(lexical_cast_default<unsigned>((**col_itor)["border_size"])); if(rows == 0) { col_grow_factor.push_back(lexical_cast_default<unsigned>((**col_itor)["grow_factor"])); } widgets.push_back(create_builder_widget(**col_itor)); ++col; } ++rows; if(row_itor == row_cfgs.begin()) { cols = col; } else { VALIDATE(col, _("A row must have a column.")); VALIDATE(col == cols, _("Number of columns differ.")); } } DBG_G_P << "Window builder: grid has " << rows << " rows and " << cols << " columns.\n"; }
std::vector<target> default_ai_context_impl::find_targets(const move_map& enemy_dstsrc) { log_scope2(log_ai, "finding targets..."); unit_map &units_ = resources::gameboard->units(); unit_map::iterator leader = units_.find_leader(get_side()); const gamemap &map_ = resources::gameboard->map(); std::vector<team> teams_ = resources::gameboard->teams(); const bool has_leader = leader != units_.end(); std::vector<target> targets; //=== start getting targets //if enemy units are in range of the leader, then we target the enemies who are in range. if(has_leader) { double threat = power_projection(leader->get_location(), enemy_dstsrc); if(threat > 0.0) { //find the location of enemy threats std::set<map_location> threats; map_location adj[6]; get_adjacent_tiles(leader->get_location(), adj); for(size_t n = 0; n != 6; ++n) { std::pair<move_map::const_iterator,move_map::const_iterator> itors = enemy_dstsrc.equal_range(adj[n]); while(itors.first != itors.second) { if(units_.count(itors.first->second)) { threats.insert(itors.first->second); } ++itors.first; } } assert(threats.empty() == false); const double value = threat/double(threats.size()); for(std::set<map_location>::const_iterator i = threats.begin(); i != threats.end(); ++i) { LOG_AI << "found threat target... " << *i << " with value: " << value << "\n"; targets.push_back(target(*i,value,target::TYPE::THREAT)); } } } double corner_distance = distance_between(map_location::ZERO(), map_location(map_.w(),map_.h())); double village_value = get_village_value(); if(has_leader && village_value > 0.0) { std::map<map_location,pathfind::paths> friends_possible_moves; move_map friends_srcdst, friends_dstsrc; calculate_possible_moves(friends_possible_moves, friends_srcdst, friends_dstsrc, false, true); const std::vector<map_location>& villages = map_.villages(); for(std::vector<map_location>::const_iterator t = villages.begin(); t != villages.end(); ++t) { assert(map_.on_board(*t)); bool ally_village = false; for (size_t i = 0; i != teams_.size(); ++i) { if (!current_team().is_enemy(i + 1) && teams_[i].owns_village(*t)) { ally_village = true; break; } } if (ally_village) { //Support seems to cause the AI to just 'sit around' a lot, so //only turn it on if it's explicitly enabled. if(get_support_villages()) { double enemy = power_projection(*t, enemy_dstsrc); if (enemy > 0) { enemy *= 1.7; double our = power_projection(*t, friends_dstsrc); double value = village_value * our / enemy; add_target(target(*t, value, target::TYPE::SUPPORT)); } } } else { double leader_distance = distance_between(*t, leader->get_location()); double value = village_value * (1.0 - leader_distance / corner_distance); LOG_AI << "found village target... " << *t << " with value: " << value << " distance: " << leader_distance << '\n'; targets.push_back(target(*t,value,target::TYPE::VILLAGE)); } } } std::vector<goal_ptr>& goals = get_goals(); //find the enemy leaders and explicit targets unit_map::const_iterator u; if (get_leader_value()>0.0) { for(u = units_.begin(); u != units_.end(); ++u) { //is a visible enemy leader if (u->can_recruit() && current_team().is_enemy(u->side()) && !u->invisible(u->get_location(), *resources::gameboard)) { assert(map_.on_board(u->get_location())); LOG_AI << "found enemy leader (side: " << u->side() << ") target... " << u->get_location() << " with value: " << get_leader_value() << "\n"; targets.push_back(target(u->get_location(), get_leader_value(), target::TYPE::LEADER)); } } } //explicit targets for this team for(std::vector<goal_ptr>::iterator j = goals.begin(); j != goals.end(); ++j) { if (!(*j)->active()) { continue; } (*j)->add_targets(std::back_inserter(targets)); } //=== end getting targets std::vector<double> new_values; for(std::vector<target>::iterator i = targets.begin(); i != targets.end(); ++i) { new_values.push_back(i->value); for(std::vector<target>::const_iterator j = targets.begin(); j != targets.end(); ++j) { if(i->loc == j->loc) { continue; } const double distance = std::abs(j->loc.x - i->loc.x) + std::abs(j->loc.y - i->loc.y); new_values.back() += j->value/(distance*distance); } } assert(new_values.size() == targets.size()); for(size_t n = 0; n != new_values.size(); ++n) { LOG_AI << "target value: " << targets[n].value << " -> " << new_values[n] << "\n"; targets[n].value = new_values[n]; } return targets; }