The Battle for Wesnoth  1.19.13+dev
helper.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2025
3  by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * @file
18  * Support functions for dealing with units.
19  */
20 
21 #include "actions/create.hpp"
22 #include "formula/string_utils.hpp"
23 #include "resources.hpp"
24 #include "units/unit.hpp"
25 #include "units/helper.hpp"
26 #include "units/types.hpp"
27 #include "play_controller.hpp"
28 #include "serialization/markup.hpp"
29 #include "utils/general.hpp"
30 #include "whiteboard/manager.hpp"
31 
32 namespace unit_helper {
33 
35 {
36  return u.advances_to().size() + u.get_modification_advances().size();
37 }
38 
40 {
41  if(!u.valid()) {
42  return false;
43  }
44  return u->advances() && number_of_possible_advances(*u) > 0;
45 }
46 
47 /**
48  * Maps resistance <= -60 (resistance value <= -60%) to intense red.
49  * Maps resistance >= 60 (resistance value >= 60%) to intense green.
50  * Intermediate values are affinely mapped to the red-to-green scale,
51  * with 0 (0%) being mapped to yellow.
52  * Compare attack_info_percent_color() in reports.cpp.
53  */
54 std::string resistance_color(const int resistance)
55 {
56  // Passing false to select the more saturated red-to-green scale.
57  return game_config::red_to_green(50.0 + resistance * 5.0 / 6.0, false).to_hex_string();
58 }
59 
60 static std::string unit_level_tooltip(const int level, const std::vector<std::string> &adv_to_types, const std::vector<config> &adv_to_mods)
61 {
62  std::ostringstream tooltip;
63  tooltip << _("Level: ") << markup::bold(level) << "\n";
64  const bool has_advancements = !adv_to_types.empty() || !adv_to_mods.empty();
65  if(has_advancements) {
66  tooltip << _("Advancements:") << "\n\t";
67  if(!adv_to_types.empty())
68  tooltip << markup::bold(utils::join(adv_to_types, "\n\t"));
69  if(!adv_to_mods.empty()) {
70  if(!adv_to_types.empty())
71  tooltip << "\n\t";
72  std::vector<std::string> descriptions;
73  for(const config& adv : adv_to_mods)
74  descriptions.push_back(adv["description"].str());
75  tooltip << markup::bold(utils::join(descriptions, "\n\t"));
76  }
77  } else {
78  tooltip << _("No advancement");
79  }
80  return tooltip.str();
81 }
82 
83 std::string unit_level_tooltip(const unit &u)
84 {
86 }
87 
88 std::string unit_level_tooltip(const unit_type &type)
89 {
90  const auto mod_adv_iters = type.modification_advancements();
91  const std::vector<config> mod_advancements(mod_adv_iters.begin(), mod_adv_iters.end());
92 
93  return unit_level_tooltip(type.level(), type.advances_to(), mod_advancements);
94 }
95 
96 std::string maybe_inactive(const std::string& str, bool active)
97 {
98  return (active ? str : markup::span_color(font::INACTIVE_COLOR, str));
99 }
100 
101 std::string format_cost_string(int unit_recall_cost, bool active)
102 {
103  std::stringstream str;
104  if (active) {
105  str << markup::img("themes/gold.png") << ' ' << unit_recall_cost;
106  } else {
107  str << markup::img("themes/gold.png~GS()") << ' '
108  << maybe_inactive(std::to_string(unit_recall_cost), false);
109  }
110  return str.str();
111 }
112 
113 std::string format_cost_string(int unit_recall_cost, const int team_recall_cost)
114 {
115  if(unit_recall_cost < 0) {
116  unit_recall_cost = team_recall_cost;
117  }
118 
119  std::stringstream str;
120  str << markup::img("themes/gold.png") << ' ';
121 
122  if(unit_recall_cost > team_recall_cost) {
123  str << markup::span_color(font::BAD_COLOR, unit_recall_cost);
124  } else if(unit_recall_cost < team_recall_cost) {
125  str << markup::span_color(font::GOOD_COLOR, unit_recall_cost);
126  } else {
127  // Default: show cost in white font color.
128  // Should handle the unit cost = team cost case.
129  str << unit_recall_cost;
130  }
131 
132  return str.str();
133 }
134 
135 std::string format_level_string(const int level, bool recallable)
136 {
137  if(!recallable) {
138  // Same logic as when recallable, but always in inactive_color.
140  (level < 2 ? std::to_string(level) : markup::bold(level)));
141  } else if(level < 1) {
143  } else if(level == 1) {
144  return std::to_string(level);
145  } else if(level == 2) {
146  return markup::bold(level);
147  } else if(level == 3) {
148  return markup::span_color(color_t(0xe2, 0xb7, 0x76), markup::bold(level));
149  } else {
150  return markup::span_color(color_t(0xdd, 0x66, 0x00), markup::bold(level));
151  }
152 }
153 
154 std::string format_movement_string(const int moves_left, const int moves_max, bool active)
155 {
156  if (!active) {
157  return markup::span_color(font::GRAY_COLOR, moves_left, "/", moves_max);
158  } else if(moves_left == 0) {
159  return markup::span_color(font::BAD_COLOR, moves_left, "/", moves_max);
160  } else if(moves_left > moves_max) {
161  return markup::span_color(font::YELLOW_COLOR, moves_left, "/", moves_max);
162  } else {
163  return markup::span_color(font::GOOD_COLOR, moves_left, "/", moves_max);
164  }
165 }
166 
168 {
169  wb::future_map future; // FIXME: why not future_map_if_active?
171  return wb ? wb->get_spent_gold_for(side_number) : 0;
172 }
173 
174 std::string check_recruit_purse(int unit_cost, int current_purse, int investments)
175 {
176  if(unit_cost > (current_purse - investments)) {
177  return investments > 0
178  // TRANSLATORS: "plan" refers to Planning Mode
179  ? _("At this point in your plan, you will not have enough gold to recruit this unit.")
180  : _("You do not have enough gold to recruit this unit.");
181  }
182 
183  return "";
184 }
185 
186 std::string check_recruit_list(
187  const std::string& type, int side_number, const map_location& target_hex)
188 {
189  const unit_type* u_type = unit_types.find(type);
190  if(!u_type || utils::contains(actions::get_recruits(side_number, target_hex), type)) {
191  return "";
192  }
193 
194  utils::string_map symbols{{ "unit_type", u_type->type_name() }};
195  return VGETTEXT("The $unit_type is not available to recruit.", symbols);
196 }
197 
198 std::tuple<std::string, map_location, map_location> validate_recruit_target(
199  const std::string& type, int side_number, const map_location& target_hex)
200 {
201  // start planned unit map scope if in planning mode
203 
204  map_location recruit_to = target_hex;
205  map_location recruit_from; // Populated below
206 
207  std::string msg = actions::find_recruit_location(side_number, recruit_to, recruit_from, type);
208  return std::tuple(msg, recruit_to, recruit_from);
209 }
210 
211 } // unit_helper
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
std::shared_ptr< wb::manager > get_whiteboard() const
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
Definition: types.cpp:1224
A single unit type that the player may recruit.
Definition: types.hpp:43
const t_string & type_name() const
The name of the unit in the current language setting.
Definition: types.hpp:141
This class represents a single unit of a specific type.
Definition: unit.hpp:132
Various functions related to the creation of units (recruits, recalls, and placed units).
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
static std::string _(const char *str)
Definition: gettext.hpp:97
int level() const
The current level of this unit.
Definition: unit.hpp:574
std::vector< config > get_modification_advances() const
Gets any non-typed advanced options set by modifications.
Definition: unit.cpp:1887
const advances_to_t & advances_to() const
Gets the possible types this unit can advance to on level-up.
Definition: unit.hpp:243
const std::vector< std::string > advances_to_translated() const
Gets the names of the possible types this unit can advance to on level-up.
Definition: unit.cpp:1270
std::string tooltip
Shown when hovering over an entry in the filter's drop-down list.
Definition: manager.cpp:203
std::string find_recruit_location(const int side, map_location &recruit_location, map_location &recruited_from, const std::string &unit_type)
Finds a location on which to place a unit.
Definition: create.cpp:466
std::set< std::string > get_recruits(int side, const map_location &recruit_loc)
Gets the recruitable units from a side's leaders' personal recruit lists who can recruit on or from a...
Definition: create.cpp:60
int side_number
Definition: game_info.hpp:40
const color_t YELLOW_COLOR
const color_t GOOD_COLOR
const color_t BAD_COLOR
const color_t GRAY_COLOR
const color_t INACTIVE_COLOR
color_t red_to_green(double val, bool for_text)
Return a color corresponding to the value val red for val=0.0 to green for val=100....
std::string img(const std::string &src, const std::string &align, bool floating)
Generates a Help markup tag corresponding to an image.
Definition: markup.cpp:31
std::string bold(Args &&... data)
Applies bold Pango markup to the input.
Definition: markup.hpp:161
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
Definition: markup.hpp:110
play_controller * controller
Definition: resources.cpp:21
static std::string unit_level_tooltip(const int level, const std::vector< std::string > &adv_to_types, const std::vector< config > &adv_to_mods)
Definition: helper.cpp:60
bool will_certainly_advance(const unit_map::iterator &u)
Encapsulates the logic for deciding whether an iterator u points to a unit that can advance.
Definition: helper.cpp:39
std::string resistance_color(const int resistance)
Maps resistance <= -60 (resistance value <= -60%) to intense red.
Definition: helper.cpp:54
std::string format_level_string(const int level, bool recallable)
Definition: helper.cpp:135
std::string check_recruit_list(const std::string &type, int side_number, const map_location &target_hex)
Definition: helper.cpp:186
std::string format_movement_string(const int moves_left, const int moves_max, bool active)
Definition: helper.cpp:154
std::string check_recruit_purse(int unit_cost, int current_purse, int investments)
Definition: helper.cpp:174
int planned_gold_spent(int side_number)
Definition: helper.cpp:167
std::string maybe_inactive(const std::string &str, bool active)
Definition: helper.cpp:96
int number_of_possible_advances(const unit &u)
Determines the total number of available advancements (of any kind) for a given unit.
Definition: helper.cpp:34
std::string format_cost_string(int unit_recall_cost, bool active)
Definition: helper.cpp:101
std::tuple< std::string, map_location, map_location > validate_recruit_target(const std::string &type, int side_number, const map_location &target_hex)
Verifies that target_hex is a valid recruit location for the given side.
Definition: helper.cpp:198
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition: general.hpp:86
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
std::map< std::string, t_string > string_map
Definition: display.hpp:45
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
int moves_left
Definition: pathfind.cpp:156
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:61
std::string to_hex_string() const
Returns the stored color in rrggbb hex format.
Definition: color.cpp:88
Encapsulates the map of the game.
Definition: location.hpp:45
bool valid() const
Definition: map.hpp:273
ONLY IF whiteboard is currently active, applies the planned unit map for the duration of the struct's...
Definition: manager.hpp:274
Applies the planned unit map for the duration of the struct's life.
Definition: manager.hpp:253
unit_type_data unit_types
Definition: types.cpp:1463