The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
teambuilder.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2014 - 2025
3 by Chris Beck <render787@gmail.com>
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 "teambuilder.hpp"
17
18#include "actions/create.hpp"
19#include "game_board.hpp"
20#include "game_errors.hpp"
21#include "log.hpp"
22#include "map/map.hpp"
24#include "team.hpp"
25#include "units/type_error.hpp"
26#include "units/unit.hpp"
27
28#include <vector>
29
30static lg::log_domain log_engine_tc("engine/team_construction");
31#define ERR_NG_TC LOG_STREAM(err, log_engine_tc)
32#define WRN_NG_TC LOG_STREAM(warn, log_engine_tc)
33#define LOG_NG_TC LOG_STREAM(info, log_engine_tc)
34#define DBG_NG_TC LOG_STREAM(debug, log_engine_tc)
35
36team_builder::team_builder(const config& side_cfg, team& to_build, const config& level, game_board& board, int num)
37 : leader_configs_()
38 , level_(level)
39 , board_(board)
40 , seen_ids_()
41 , side_(num)
42 , side_cfg_(side_cfg)
43 , team_(to_build)
44 , unit_configs_()
45{
46}
47
49{
50 // initialize the context variables and flags, find relevant tags, set up everything
51 init();
52
53 // builds the team for the given side
54 new_team();
55
56 // set team objectives if necessary
57 objectives();
58
59 // If the game state specifies additional units that can be recruited by the player, add them.
61
62}
63
65{
66 // place leader
67 leader();
68
69 // prepare units, populate obvious recall lists elements
71}
72
74{
75 // place units
76 // this is separate stage because we need to place units only after every other team is constructed
78}
79
80void team_builder::log_step(const char* s) const
81{
82 LOG_NG_TC << "team " << side_ << " construction: " << s;
83}
84
86{
87 if(side_cfg_["side"].to_int(side_) != side_) {
88 ERR_NG_TC << "found invalid side=" << side_cfg_["side"].to_int(side_) << " in definition of side number " << side_;
89 throw game::load_game_failed("Invalid side definition");
90 }
91
92 log_step("init");
93
94 if(board_.map().empty()) {
95 throw game::load_game_failed("Map not found");
96 }
97
98 unit_configs_.clear();
99 seen_ids_.clear();
100}
101
102
104{
105 log_step("new team");
107}
108
110{
111 log_step("objectives");
112 // If this team has no objectives, set its objectives
113 // to the level-global "objectives"
114 // this is only used by the default mp 'Defeat enemy leader' objectives
115 if(team_.objectives().empty()) {
116 team_.set_objectives(level_["objectives"].t_str(), false);
117 }
118}
119
121{
122 log_step("previous recruits");
123
124 if(const config::attribute_value* v = side_cfg_.get("previous_recruits")) {
125 for(const std::string& rec : utils::split(*v)) {
126 DBG_NG_TC << "adding previous recruit: " << rec;
127 team_.add_recruit(rec);
128 }
129 }
130}
131
132void team_builder::handle_unit(const config& u, const char* origin)
133{
135 << "unit from " << origin << ": "
136 << "type=[" << u["type"] << "] "
137 << "id=[" << u["id"] << "] "
138 << "placement=[" << u["placement"] << "] "
139 << "x=[" << u["x"] << "] "
140 << "y=[" << u["y"] << "]";
141
142 if(u["type"].empty()) {
144 << "when building level, skipping a unit (id=[" << u["id"] << "]) from " << origin
145 << " with no type information,\n"
146 << "for side:\n"
147 << side_cfg_.debug();
148
149 return;
150 }
151
152 const std::string& id = u["id"];
153 if(!id.empty()) {
154 if(seen_ids_.find(id) != seen_ids_.end()) {
155 // seen before
156 config u_tmp = u;
157 u_tmp["side"] = std::to_string(side_);
158 team_.recall_list().add(unit::create(u_tmp, true));
159 } else {
160 // not seen before
161 unit_configs_.push_back(&u);
162 seen_ids_.insert(id);
163 }
164 } else {
165 unit_configs_.push_back(&u);
166 }
167}
168
170{
171 // Make a persistent copy of the config.
172 leader_configs_.push_back(leader);
173 config& stored = leader_configs_.back();
174
175 // Provide some default values, if not specified.
176 config::attribute_value& a1 = stored["canrecruit"];
177 if(a1.blank()) {
178 a1 = true;
179 }
180
181 config::attribute_value& a2 = stored["placement"];
182 if(a2.blank()) {
183 a2 = "map,leader";
184 }
185
186 // Add the leader to the list of units to create.
187 handle_unit(stored, "leader_cfg");
188}
189
191{
192 log_step("leader");
193 for(const config& l : side_cfg_.child_range("leader")) {
194 handle_leader(l);
195 }
196}
197
199{
200 // if this is a start-of-scenario save then playcampaign.cpp merged
201 // units in [replay_start][side] merged with [side] already
202 // units that are in '[scenario][side]' are 'first'
203
204 // for create-or-recall semantics to work: for each unit with non-empty
205 // id, unconditionally put OTHER, later, units with same id directly to
206 // recall list, not including them in unit_configs_
207 for(const config& su : side_cfg_.child_range("unit")) {
208 handle_unit(su, "side_cfg");
209 }
210}
211
213{
214 log_step("place units");
216 uc.allow_add_to_recall(true)
217 .allow_discover(true)
218 .allow_get_village(false)
219 .allow_invalidate(false)
220 .allow_rename_side(true)
221 .allow_show(false);
222
223 for(const config* u : unit_configs_) {
224 try {
225 uc.add_unit(*u);
226 } catch(const unit_type_error& e) {
227 ERR_NG_TC << e.what();
228 }
229 }
230}
Variant for storing WML attributes.
bool blank() const
Tests for an attribute that was never set.
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
child_itors child_range(std::string_view key)
Definition config.cpp:268
const attribute_value * get(std::string_view key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
Definition config.cpp:665
std::string debug() const
Definition config.cpp:1214
Game board class.
virtual const gamemap & map() const override
map_location starting_position(int side) const
Definition map.cpp:286
bool empty() const
Tell if the map is of 0 size.
Definition map.hpp:68
void add(const unit_ptr &ptr, int pos=-1)
Add a unit to the list.
bool empty() const
Definition tstring.hpp:200
std::deque< config > leader_configs_
team_builder(const config &side_cfg, team &to_build, const config &level, game_board &board, int num)
void build_team_stage_three()
Handles the third stage of team initialization (unit placement).
void handle_leader(const config &leader)
const config & side_cfg_
void build_team_stage_two()
Handles the second stage of team initialization ((some) unit construction).
void prepare_units()
std::set< std::string > seen_ids_
std::vector< const config * > unit_configs_
void previous_recruits()
void build_team_stage_one()
Handles the first stage of team initialization (everything except unit construction).
void handle_unit(const config &u, const char *origin)
const config & level_
void log_step(const char *s) const
game_board & board_
This class stores all the data for a single 'side' (in game nomenclature).
Definition team.hpp:74
void build(const config &cfg, const gamemap &map)
Definition team.cpp:344
const t_string & objectives() const
Definition team.hpp:267
void set_objectives(const t_string &new_objectives, bool silently=false)
Definition team.cpp:627
recall_list_manager & recall_list()
Definition team.hpp:242
void add_recruit(const std::string &)
Definition team.cpp:467
unit_creator & allow_invalidate(bool b)
unit_creator & allow_get_village(bool b)
void add_unit(const config &cfg, const vconfig *vcfg=nullptr)
adds a unit on map without firing any events (so, usable during team construction in gamestatus)
unit_creator & allow_discover(bool b)
unit_creator & allow_show(bool b)
unit_creator & allow_rename_side(bool b)
unit_creator & allow_add_to_recall(bool b)
static unit_ptr create(const config &cfg, bool use_traits=false, const vconfig *vcfg=nullptr)
Initializes a unit from a config.
Definition unit.hpp:107
Various functions related to the creation of units (recruits, recalls, and placed units).
Standard logging facilities (interface).
std::vector< std::string > split(const config_attribute_value &val)
Error used when game loading fails.
#define WRN_NG_TC
#define LOG_NG_TC
#define ERR_NG_TC
static lg::log_domain log_engine_tc("engine/team_construction")
#define DBG_NG_TC
static map_location::direction s
#define e