The Battle for Wesnoth  1.19.5+dev
carryover_show_gold.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2024
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 #include "carryover_show_gold.hpp"
17 
18 #include "log.hpp"
19 #include "team.hpp"
20 #include "game_state.hpp"
21 #include "gettext.hpp"
23 #include "formula/string_utils.hpp"
24 #include "map/map.hpp"
25 #include "serialization/markup.hpp"
26 #include <cassert>
27 
28 static lg::log_domain log_engine("engine");
29 #define LOG_NG LOG_STREAM(info, log_engine)
30 #define ERR_NG LOG_STREAM(err, log_engine)
31 
32 
33 void carryover_show_gold(game_state& state, bool hidden, bool is_observer, bool is_test)
34 {
35  assert(state.end_level_data_);
36  game_board& board = state.board_;
37  const end_level_data& end_level = *state.end_level_data_;
38  const bool is_victory = end_level.is_victory;
39  // We need to write the carryover amount to the team that's why we need non const
40  std::vector<team>& teams = board.teams();
41 
42  // maybe this can be the case for scenario that only contain a story and end during the prestart event ?
43  if(teams.size() < 1) {
44  return;
45  }
46 
47  std::ostringstream report;
48  std::string title;
49 
50 
51  if(is_observer) {
52  title = _("Scenario Report");
53  } else if(is_victory) {
54  title = _("Victory");
55  report << markup::bold(_("You have emerged victorious!"));
56  } else {
57  title = _("Defeat");
58  report << _("You have been defeated!");
59  }
60 
61  const std::string& next_scenario = state.get_game_data()->next_scenario();
62  const bool has_next_scenario = !next_scenario.empty() && next_scenario != "null";
63 
64  int persistent_teams = 0;
65  for(const team& t : teams) {
66  if(t.persistent()) {
67  ++persistent_teams;
68  }
69  }
70 
71  if(persistent_teams > 0 && ((has_next_scenario && end_level.proceed_to_next_level) || is_test)) {
72  const gamemap& map = board.map();
73  const tod_manager& tod = state.get_tod_man();
74 
75  const int turns_left = std::max<int>(0, tod.number_of_turns() - tod.turn());
76  for(team& t : teams) {
77  if(!t.persistent() || t.lost()) {
78  continue;
79  }
80 
81  const int finishing_bonus_per_turn = map.villages().size() * t.village_gold() + t.base_income();
82  const int finishing_bonus = t.carryover_bonus() * finishing_bonus_per_turn * turns_left;
83 
84  t.set_carryover_gold(div100rounded((t.gold() + finishing_bonus) * t.carryover_percentage()));
85 
86  if(!t.is_local_human()) {
87  continue;
88  }
89 
90  if(persistent_teams > 1) {
91  report << "\n\n" << markup::bold(t.side_name());
92  }
93 
94  report << "\n" << markup::tag("small", _("Remaining gold: "), utils::half_signed_value(t.gold()));
95 
96  if(t.carryover_bonus() != 0) {
97  if(turns_left > -1) {
98  report << "\n\n"
99  << markup::bold(_("Turns finished early: "), turns_left) << "\n"
100  << markup::tag("small",
101  _("Early finish bonus: "), finishing_bonus_per_turn, _(" per turn"), "\n",
102  _("Total bonus: "), finishing_bonus, "\n");
103  }
104 
105  report << markup::tag("small", _("Total gold: "), utils::half_signed_value(t.gold() + finishing_bonus));
106  }
107 
108  if(t.gold() > 0) {
109  report << "\n" << markup::tag("small", _("Carryover percentage: "), t.carryover_percentage());
110  }
111 
112  if(t.carryover_add()) {
113  report << "\n\n" << markup::tag("big", markup::bold(_("Bonus gold: "), utils::half_signed_value(t.carryover_gold())));
114  } else {
115  report << "\n\n" << markup::tag("big", markup::bold(_("Retained gold: "), utils::half_signed_value(t.carryover_gold())));
116  }
117 
118  std::string goldmsg;
119  utils::string_map symbols;
120 
121  symbols["gold"] = lexical_cast_default<std::string>(t.carryover_gold());
122 
123  // Note that both strings are the same in English, but some languages will
124  // want to translate them differently.
125  if(t.carryover_add()) {
126  if(t.carryover_gold() > 0) {
127  goldmsg = VNGETTEXT(
128  "You will start the next scenario with $gold on top of the defined minimum starting gold.",
129  "You will start the next scenario with $gold on top of the defined minimum starting gold.",
130  t.carryover_gold(), symbols
131  );
132 
133  } else {
134  goldmsg = VNGETTEXT(
135  "You will start the next scenario with the defined minimum starting gold.",
136  "You will start the next scenario with the defined minimum starting gold.",
137  t.carryover_gold(), symbols
138  );
139  }
140  } else {
141  goldmsg = VNGETTEXT(
142  "You will start the next scenario with $gold or its defined minimum starting gold, "
143  "whichever is higher.",
144  "You will start the next scenario with $gold or its defined minimum starting gold, "
145  "whichever is higher.",
146  t.carryover_gold(), symbols
147  );
148  }
149 
150  // xgettext:no-c-format
151  report << "\n" << goldmsg;
152  }
153  }
154 
155  if(end_level.transient.carryover_report && !hidden) {
156  gui2::show_transient_message(title, report.str(), "", true);
157  }
158 }
double t
Definition: astarsearch.cpp:63
static lg::log_domain log_engine("engine")
void carryover_show_gold(game_state &state, bool hidden, bool is_observer, bool is_test)
calculates the amount of gold carried over for each team, stores the data in the team object and show...
Game board class.
Definition: game_board.hpp:47
virtual const std::vector< team > & teams() const override
Definition: game_board.hpp:80
virtual const gamemap & map() const override
Definition: game_board.hpp:97
const std::string & next_scenario() const
Definition: game_data.hpp:130
utils::optional< end_level_data > end_level_data_
Definition: game_state.hpp:64
virtual const game_data * get_game_data() const override
Inherited from filter_context.
Definition: game_state.hpp:97
virtual const tod_manager & get_tod_man() const override
Inherited from filter_context.
Definition: game_state.hpp:91
game_board board_
Definition: game_state.hpp:44
Encapsulates the map of the game.
Definition: map.hpp:172
const std::vector< map_location > & villages() const
Return a list of the locations of villages on the map.
Definition: map.hpp:237
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:75
int number_of_turns() const
int turn() const
#define VNGETTEXT(msgid, msgid_plural, count,...)
static std::string _(const char *str)
Definition: gettext.hpp:93
Standard logging facilities (interface).
constexpr int div100rounded(int num)
Guarantees portable results for division by 100; round half up, to the nearest integer.
Definition: math.hpp:39
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup)
Shows a transient message to the user.
std::string tag(const std::string &tag_name, Args &&... contents)
Definition: markup.hpp:45
std::string bold(Args &&... data)
Definition: markup.hpp:128
std::string half_signed_value(int val)
Sign with Unicode "−" if negative.
std::map< std::string, t_string > string_map
int turns_left
Definition: pathfind.cpp:156
Additional information on the game outcome which can be provided by WML.
bool proceed_to_next_level
whether to proceed to the next scenario, equals is_victory in sp.
transient_end_level transient
bool carryover_report
Should a summary of the scenario outcome be displayed?