The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
team.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2016 by David White <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Team-management, allies, setup at start of scenario.
18  */
19 
20 #include "team.hpp"
21 
22 #include "ai/manager.hpp"
23 #include "formula/string_utils.hpp"
24 #include "game_events/manager.hpp"
25 #include "game_events/pump.hpp"
26 #include "game_data.hpp"
27 #include "map/map.hpp"
28 #include "resources.hpp"
29 #include "play_controller.hpp"
30 #include "game_preferences.hpp"
31 #include "sdl/utils.hpp" // Only needed for int_to_color (!)
32 #include "units/types.hpp"
33 #include "synced_context.hpp"
35 #include "config_assign.hpp"
37 
38 static lg::log_domain log_engine("engine");
39 #define DBG_NG LOG_STREAM(debug, log_engine)
40 #define LOG_NG LOG_STREAM(info, log_engine)
41 #define WRN_NG LOG_STREAM(warn, log_engine)
42 #define ERR_NG LOG_STREAM(warn, log_engine)
43 
44 static lg::log_domain log_engine_enemies("engine/enemies");
45 #define DBG_NGE LOG_STREAM(debug, log_engine_enemies)
46 #define LOG_NGE LOG_STREAM(info, log_engine_enemies)
47 #define WRN_NGE LOG_STREAM(warn, log_engine_enemies)
48 
49 
50 static std::vector<team> *&teams = resources::teams;
51 
52 //static member initialization
53 const int team::default_team_gold_ = 100;
54 
55 // Update this list of attributes if you change what is used to define a side
56 // (excluding those attributes used to define the side's leader).
57 const boost::container::flat_set<std::string> team::attributes = boost::assign::list_of<std::string>("ai_config")
58  ("carryover_add")("carryover_percentage")("color")("controller")("current_player")("defeat_condition")("flag")
59  ("flag_icon")("fog")("fog_data")("gold")("hidden")("income")
60  ("no_leader")("objectives")("objectives_changed")("persistent")("lost")
61  ("recall_cost")("recruit")("save_id")("scroll_to_leader")
62  ("share_vision")("share_maps")("share_view")("shroud")("shroud_data")("start_gold")
63  ("suppress_end_turn_confirmation")
64  ("team_name")("user_team_name")("side_name")("village_gold")("village_support")("is_local")
65  // Multiplayer attributes.
66  ("player_id")("action_bonus_count")("allow_changes")("allow_player")("color_lock")
67  ("countdown_time")("disallow_observers")("faction")
68  ("faction_from_recruit")("faction_name")("gold_lock")("income_lock")
69  ("leader")("random_leader")("team_lock")("terrain_liked")
70  ("user_description")("controller_lock")("chose_random")
71  ("disallow_shuffle")("description").convert_to_container<boost::container::flat_set<std::string> >();
72 
74  gold(0),
75  start_gold(0),
76  income(0),
77  income_per_village(0),
78  support_per_village(1),
79  minimum_recruit_price(0),
80  recall_cost(0),
81  can_recruit(),
82  team_name(),
83  user_team_name(),
84  side_name(),
85  faction(),
86  faction_name(),
87  save_id(),
88  current_player(),
89  countdown_time(),
90  action_bonus_count(0),
91  flag(),
92  flag_icon(),
93  id(),
94  scroll_to_leader(true),
95  objectives(),
96  objectives_changed(false),
97  controller(),
98  is_local(true),
99  defeat_condition(team::DEFEAT_CONDITION::NO_LEADER),
100  proxy_controller(team::PROXY_CONTROLLER::PROXY_HUMAN),
101  share_vision(team::SHARE_VISION::ALL),
102  disallow_observers(false),
103  allow_player(false),
104  chose_random(false),
105  no_leader(true),
106  hidden(true),
107  no_turn_confirmation(false),
108  color(),
109  side(0),
110  persistent(false),
111  lost(false),
112  carryover_percentage(game_config::gold_carryover_percentage),
113  carryover_add(false),
114  carryover_bonus(0),
115  carryover_gold(0)
116 {
117 }
118 
120 {
121  gold = cfg["gold"];
122  income = cfg["income"];
123  team_name = cfg["team_name"].str();
124  user_team_name = cfg["user_team_name"];
125  side_name = cfg["side_name"];
126  faction = cfg["faction"].str();
127  faction_name = cfg["faction_name"];
128  save_id = cfg["save_id"].str();
129  current_player = cfg["current_player"].str();
130  countdown_time = cfg["countdown_time"].str();
131  action_bonus_count = cfg["action_bonus_count"];
132  flag = cfg["flag"].str();
133  flag_icon = cfg["flag_icon"].str();
134  id = cfg["id"].str();
135  scroll_to_leader = cfg["scroll_to_leader"].to_bool(true);
136  objectives = cfg["objectives"];
137  objectives_changed = cfg["objectives_changed"].to_bool();
138  disallow_observers = cfg["disallow_observers"].to_bool();
139  allow_player = cfg["allow_player"].to_bool(true);
140  chose_random = cfg["chose_random"].to_bool(false);
141  no_leader = cfg["no_leader"].to_bool();
142  defeat_condition = cfg["defeat_condition"].to_enum<team::DEFEAT_CONDITION>(team::DEFEAT_CONDITION::NO_LEADER);
143  lost = cfg["lost"].to_bool(false);
144  hidden = cfg["hidden"].to_bool();
145  no_turn_confirmation = cfg["suppress_end_turn_confirmation"].to_bool();
146  side = cfg["side"].to_int(1);
147  carryover_percentage = cfg["carryover_percentage"].to_int(game_config::gold_carryover_percentage);
148  carryover_add = cfg["carryover_add"].to_bool(false);
149  carryover_bonus = cfg["carryover_bonus"].to_double(1);
150  carryover_gold = cfg["carryover_gold"].to_int(0);
151  variables = cfg.child_or_empty("variables");
152  is_local = cfg["is_local"].to_bool(true);
153 
154  if(cfg.has_attribute("color")) {
155  color = cfg["color"].str();
156  } else {
157  color = cfg["side"].str();
158  }
159 
160  // If arel starting new scenario override settings from [ai] tags
163 
164  if(cfg.has_attribute("ai_config")) {
165  ai::manager::add_ai_for_side_from_file(side, cfg["ai_config"], true);
166  } else {
168  }
169 
170  std::vector<std::string> recruits = utils::split(cfg["recruit"]);
171  can_recruit.insert(recruits.begin(), recruits.end());
172 
173  // at the start of a scenario "start_gold" is not set, we need to take the
174  // value from the gold setting (or fall back to the gold default)
175  if (!cfg["start_gold"].empty())
176  start_gold = cfg["start_gold"];
177  else if (!cfg["gold"].empty())
178  start_gold = gold;
179  else
181 
182  if(team_name.empty()) {
183  team_name = cfg["side"].str();
184  }
185 
186  if(save_id.empty()) {
187  save_id = id;
188  }
189 
190  income_per_village = cfg["village_gold"].to_int(game_config::village_income);
191  recall_cost = cfg["recall_cost"].to_int(game_config::recall_cost);
192 
193  const std::string& village_support = cfg["village_support"];
194  if(village_support.empty())
195  support_per_village = game_config::village_support;
196  else
197  support_per_village = lexical_cast_default<int>(village_support, game_config::village_support);
198 
199  controller = team::CONTROLLER::AI;
200  controller.parse(cfg["controller"].str());
201 
202  //TODO: Why do we read disallow observers differently when controller is empty?
203  if (controller == CONTROLLER::EMPTY) {
204  disallow_observers = cfg["disallow_observers"].to_bool(true);
205  }
206  //override persistence flag if it is explicitly defined in the config
207  //by default, persistence of a team is set depending on the controller
208  persistent = cfg["persistent"].to_bool(this->controller == CONTROLLER::HUMAN);
209 
210  //========================================================
211  //END OF MESSY CODE
212 
213  // Share_view and share_maps can't both be enabled,
214  // so share_view overrides share_maps.
215  share_vision = cfg["share_vision"].to_enum<team::SHARE_VISION>(team::SHARE_VISION::ALL);
217  LOG_NG << "team_info::team_info(...): team_name: " << team_name
218  << ", share_vision: " << share_vision << ".\n";
219 }
220 
222 {
223  if(cfg.has_attribute("share_view") || cfg.has_attribute("share_maps"))
224  {
225  if(cfg["share_view"].to_bool()) {
226  share_vision = team::SHARE_VISION::ALL;
227  }
228  else if(cfg["share_maps"].to_bool(true)) {
229  share_vision = team::SHARE_VISION::SHROUD;
230  }
231  else {
233  }
234  }
235 }
236 
238 {
239  cfg["gold"] = gold;
240  cfg["start_gold"] = start_gold;
241  cfg["income"] = income;
242  cfg["team_name"] = team_name;
243  cfg["user_team_name"] = user_team_name;
244  cfg["side_name"] = side_name;
245  cfg["faction"] = faction;
246  cfg["faction_name"] = faction_name;
247  cfg["save_id"] = save_id;
248  cfg["current_player"] = current_player;
249  cfg["flag"] = flag;
250  cfg["flag_icon"] = flag_icon;
251  cfg["id"] = id;
252  cfg["objectives"] = objectives;
253  cfg["objectives_changed"] = objectives_changed;
254  cfg["countdown_time"]= countdown_time;
255  cfg["action_bonus_count"]= action_bonus_count;
256  cfg["village_gold"] = income_per_village;
257  cfg["village_support"] = support_per_village;
258  cfg["recall_cost"] = recall_cost;
259  cfg["disallow_observers"] = disallow_observers;
260  cfg["allow_player"] = allow_player;
261  cfg["chose_random"] = chose_random;
262  cfg["no_leader"] = no_leader;
263  cfg["defeat_condition"] = defeat_condition;
264  cfg["hidden"] = hidden;
265  cfg["suppress_end_turn_confirmation"] = no_turn_confirmation;
266  cfg["scroll_to_leader"] = scroll_to_leader;
267  cfg["controller"] = controller;
268  cfg["recruit"] = utils::join(can_recruit);
269  cfg["share_vision"] = share_vision;
270 
271  cfg["color"] = color;
272  cfg["persistent"] = persistent;
273  cfg["lost"] = lost;
274  cfg["carryover_percentage"] = carryover_percentage;
275  cfg["carryover_add"] = carryover_add;
276  cfg["carryover_bonus"] = carryover_bonus;
277  cfg["carryover_gold"] = carryover_gold;
278 
279  cfg.add_child("variables", variables);
281 }
282 
284  gold_(0),
285  villages_(),
286  shroud_(),
287  fog_(),
288  fog_clearer_(),
289  auto_shroud_updates_(true),
290  info_(),
291  countdown_time_(0),
293  recall_list_(),
294  last_recruit_(),
295  enemies_(),
296  ally_shroud_(),
297  ally_fog_(),
299 {
300 }
301 
303 {
304 }
305 
306 void team::build(const config &cfg, const gamemap& map, int gold)
307 {
308  gold_ = gold;
309  info_.read(cfg);
310 
311  fog_.set_enabled(cfg["fog"].to_bool());
312  fog_.read(cfg["fog_data"]);
313  shroud_.set_enabled(cfg["shroud"].to_bool());
314  shroud_.read(cfg["shroud_data"]);
315  auto_shroud_updates_ = cfg["auto_shroud"].to_bool(auto_shroud_updates_);
316 
317  LOG_NG << "team::team(...): team_name: " << info_.team_name
318  << ", shroud: " << uses_shroud() << ", fog: " << uses_fog() << ".\n";
319 
320  // Load the WML-cleared fog.
321  const config &fog_override = cfg.child("fog_override");
322  if ( fog_override ) {
323  const std::vector<map_location> fog_vector =
324  map.parse_location_range(fog_override["x"], fog_override["y"], true);
325  fog_clearer_.insert(fog_vector.begin(), fog_vector.end());
326  }
327 
328  // To ensure some minimum starting gold,
329  // gold is the maximum of 'gold' and what is given in the config file
330  gold_ = std::max(gold, info_.gold);
331  if (gold_ != info_.gold)
333  // Old code was doing:
334  // info_.start_gold = std::to_string(gold) + " (" + info_.start_gold + ")";
335  // Was it correct?
336 
337  // Load in the villages the side controls at the start
338  for (const config &v : cfg.child_range("village"))
339  {
340  map_location loc(v);
341  if (map.is_village(loc)) {
342  villages_.insert(loc);
343  } else {
344  WRN_NG << "[side] " << current_player() << " [village] points to a non-village location " << loc << std::endl;
345  }
346  }
347 
348  countdown_time_ = cfg["countdown_time"];
349  action_bonus_count_ = cfg["action_bonus_count"];
350 
351  planned_actions_.reset(new wb::side_actions());
352  planned_actions_->set_team_index(info_.side - 1);
353 }
354 
355 void team::write(config& cfg) const
356 {
357  info_.write(cfg);
358  cfg["auto_shroud"] = auto_shroud_updates_;
359  cfg["shroud"] = uses_shroud();
360  cfg["fog"] = uses_fog();
361  cfg["gold"] = gold_;
362 
363  // Write village locations
364  for(std::set<map_location>::const_iterator t = villages_.begin(); t != villages_.end(); ++t) {
365  t->write(cfg.add_child("village"));
366  }
367 
368  cfg["shroud_data"] = shroud_.write();
369  cfg["fog_data"] = fog_.write();
370  if ( !fog_clearer_.empty() )
371  write_location_range(fog_clearer_, cfg.add_child("fog_override"));
372 
373  cfg["countdown_time"] = countdown_time_;
374  cfg["action_bonus_count"] = action_bonus_count_;
375 }
376 
377 bool team::get_village(const map_location& loc, const int owner_side, game_data * gamedata)
378 {
379  villages_.insert(loc);
380  bool gamestate_changed = false;
381  if(gamedata) {
382  config::attribute_value& var = gamedata->get_variable("owner_side");
383  const config::attribute_value old_value = var;
384  var = owner_side;
385 
386  // During team building, game_events pump is not guaranteed to exist yet. (At current revision.) We skip capture events in this case.
388  gamestate_changed = resources::game_events->pump().fire("capture",loc);
389  }
390 
391  if(old_value.blank())
392  gamedata->clear_variable("owner_side");
393  else
394  var = old_value;
395  }
396  return gamestate_changed;
397 }
398 
400 {
401  const std::set<map_location>::const_iterator vil = villages_.find(loc);
402  assert(vil != villages_.end());
403  villages_.erase(vil);
404 }
405 
406 void team::set_recruits(const std::set<std::string>& recruits)
407 {
411 }
412 
413 void team::add_recruit(const std::string &recruit)
414 {
415  info_.can_recruit.insert(recruit);
418 }
419 
421 {
424  }else{
425  int min = 20;
426  for(std::string recruit : info_.can_recruit) {
427  const unit_type *ut = unit_types.find(recruit);
428  if(!ut)
429  continue;
430  else{
431  if(ut->cost() < min)
432  min = ut->cost();
433  }
434 
435  }
437  }
439 }
440 
441 bool team::calculate_enemies(size_t index) const
442 {
443  if(teams == nullptr || index >= teams->size()) {
444  return false;
445  }
446 
447  while(enemies_.size() <= index) {
448  enemies_.push_back(calculate_is_enemy(enemies_.size()));
449  }
450 
451  return enemies_.back();
452 }
453 
454 bool team::calculate_is_enemy(size_t index) const
455 {
456  // We're not enemies of ourselves
457  if(&(*teams)[index] == this) {
458  return false;
459  }
460 
461  // We are friends with anyone who we share a teamname with
462  std::vector<std::string> our_teams = utils::split(info_.team_name),
463  their_teams = utils::split((*teams)[index].info_.team_name);
464 
465  LOG_NGE << "team " << info_.side << " calculates if it has enemy in team "<<index+1 << "; our team_name ["<<info_.team_name<<"], their team_name is ["<<(*teams)[index].info_.team_name<<"]"<< std::endl;
466  for(std::vector<std::string>::const_iterator t = our_teams.begin(); t != our_teams.end(); ++t) {
467  if(std::find(their_teams.begin(), their_teams.end(), *t) != their_teams.end())
468  {
469  LOG_NGE << "team " << info_.side << " found same team name [" << *t << "] in team "<< index+1 << std::endl;
470  return false;
471  } else {
472  LOG_NGE << "team " << info_.side << " not found same team name [" << *t << "] in team "<< index+1 << std::endl;
473  }
474  }
475  LOG_NGE << "team " << info_.side << " has enemy in team " << index+1 << std::endl;
476  return true;
477 }
478 
479 namespace
480 {
481  class controller_server_choice : public synced_context::server_choice
482  {
483  public:
484  controller_server_choice(team::CONTROLLER new_controller, const team& team)
485  : new_controller_(new_controller)
486  , team_(team)
487  {
488  }
489  /// We are in a game with no mp server and need to do this choice locally
490  virtual config local_choice() const
491  {
492  return config_of("controller", new_controller_)("is_local", true);
493  }
494  /// the request which is sended to the mp server.
495  virtual config request() const
496  {
497  return config_of
498  ("new_controller", new_controller_)
499  ("old_controller", team_.controller())
500  ("side", team_.side());
501  }
502  virtual const char* name() const
503  {
504  return "change_controller_wml";
505  }
506  private:
507  team::CONTROLLER new_controller_;
508  const team& team_;
509  };
510 }
511 
512 void team::change_controller_by_wml(const std::string& new_controller_string)
513 {
514  CONTROLLER new_controller;
515  if(!new_controller.parse(new_controller_string)) {
516  ERR_NG << "ignored attempt to change controller to " << new_controller_string << std::endl;
517  return;
518  }
519  if(new_controller == CONTROLLER::EMPTY && resources::controller->current_side() == this->side()) {
520  ERR_NG << "ignored attempt to change the currently playing side's controller to 'null'" << std::endl;
521  return;
522  }
523  config choice = synced_context::ask_server_choice(controller_server_choice(new_controller, *this));
524  if(!new_controller.parse(choice["controller"])) {
525  //TODO: this should be more than a ERR_NG message.
526  ERR_NG << "recieved an invalid controller string from the server" << choice["controller"] << std::endl;
527  }
528  if(!resources::controller->is_replay()) {
529  set_local(choice["is_local"].to_bool());
530  }
531  change_controller(new_controller);
532 }
533 
534 void team::change_team(const std::string &name, const t_string &user_name)
535 {
536  info_.team_name = name;
537  if (!user_name.empty())
538  {
539  info_.user_team_name = user_name;
540  }
541  else
542  {
544  }
545 
546  clear_caches();
547 }
548 
550  // Reset the cache of allies for all teams
551  if(teams != nullptr) {
552  for(std::vector<team>::const_iterator i = teams->begin(); i != teams->end(); ++i) {
553  i->enemies_.clear();
554  i->ally_shroud_.clear();
555  i->ally_fog_.clear();
556  }
557  }
558 }
559 
560 void team::set_objectives(const t_string& new_objectives, bool silently)
561 {
562  info_.objectives = new_objectives;
563  if(!silently)
564  info_.objectives_changed = true;
565 }
566 
567 bool team::shrouded(const map_location& loc) const
568 {
569  if(!teams)
570  return shroud_.value(loc.x+1,loc.y+1);
571 
572  return shroud_.shared_value(ally_shroud(*teams),loc.x+1,loc.y+1);
573 }
574 
575 bool team::fogged(const map_location& loc) const
576 {
577  if(shrouded(loc)) return true;
578 
579  // Check for an override of fog.
580  if ( fog_clearer_.count(loc) > 0 )
581  return false;
582 
583  if(!teams)
584  return fog_.value(loc.x+1,loc.y+1);
585 
586  return fog_.shared_value(ally_fog(*teams),loc.x+1,loc.y+1);
587 }
588 
589 const std::vector<const team::shroud_map*>& team::ally_shroud(const std::vector<team>& teams) const
590 {
591  if(ally_shroud_.empty()) {
592  for(size_t i = 0; i < teams.size(); ++i) {
593  if(!is_enemy(i + 1) && (&(teams[i]) == this || teams[i].share_view() || teams[i].share_maps())) {
594  ally_shroud_.push_back(&(teams[i].shroud_));
595  }
596  }
597  }
598 
599  return ally_shroud_;
600 }
601 
602 const std::vector<const team::shroud_map*>& team::ally_fog(const std::vector<team>& teams) const
603 {
604  if(ally_fog_.empty()) {
605  for(size_t i = 0; i < teams.size(); ++i) {
606  if(!is_enemy(i + 1) && (&(teams[i]) == this || teams[i].share_view())) {
607  ally_fog_.push_back(&(teams[i].fog_));
608  }
609  }
610  }
611 
612  return ally_fog_;
613 }
614 
615 bool team::knows_about_team(size_t index) const
616 {
617  const team& t = (*teams)[index];
618 
619  // We know about our own team
620  if(this == &t) return true;
621 
622  // If we aren't using shroud or fog, then we know about everyone
623  if(!uses_shroud() && !uses_fog()) return true;
624 
625  // We don't know about enemies
626  if(is_enemy(index+1)) return false;
627 
628  // We know our human allies.
629  if (t.is_human()) return true;
630 
631  // We know about allies we're sharing maps with
632  if(share_maps() && t.uses_shroud()) return true;
633 
634  // We know about allies we're sharing view with
635  if(share_view() && (t.uses_fog() || t.uses_shroud())) return true;
636 
637  return false;
638 }
639 
640 /**
641  * Removes the record of hexes that were cleared of fog via WML.
642  * @param[in] hexes The hexes to no longer keep clear.
643  */
644 void team::remove_fog_override(const std::set<map_location> &hexes)
645 {
646  // Take a set difference.
647  std::vector<map_location> result(fog_clearer_.size());
649  std::set_difference(fog_clearer_.begin(), fog_clearer_.end(),
650  hexes.begin(), hexes.end(), result.begin());
651 
652  // Put the result into fog_clearer_.
653  fog_clearer_.clear();
654  fog_clearer_.insert(result.begin(), result_end);
655 }
656 
657 void validate_side(int side)
658 {
659  if(teams == nullptr) {
660  return;
661  }
662 
663  if(side < 1 || side > int(teams->size())) {
664  throw game::game_error("invalid side(" + std::to_string(side) + ") found in unit definition");
665  }
666 }
667 
669 {
670  if(enabled_ == false || x < 0 || y < 0)
671  return false;
672 
673  if(x >= static_cast<int>(data_.size()))
674  data_.resize(x+1);
675 
676  if(y >= static_cast<int>(data_[x].size()))
677  data_[x].resize(y+1);
678 
679  if(data_[x][y] == false) {
680  data_[x][y] = true;
681  return true;
682  } else {
683  return false;
684  }
685 }
686 
688 {
689  if(enabled_ == false || x < 0 || y < 0)
690  return;
691 
692  if (x >= static_cast<int>(data_.size())) {
693  DBG_NG << "Couldn't place shroud on invalid x coordinate: ("
694  << x << ", " << y << ") - max x: " << data_.size() - 1 << "\n";
695  } else if (y >= static_cast<int>(data_[x].size())) {
696  DBG_NG << "Couldn't place shroud on invalid y coordinate: ("
697  << x << ", " << y << ") - max y: " << data_[x].size() - 1 << "\n";
698  } else {
699  data_[x][y] = false;
700  }
701 }
702 
704 {
705  if(enabled_ == false)
706  return;
707 
708  for(std::vector<std::vector<bool> >::iterator i = data_.begin(); i != data_.end(); ++i) {
709  std::fill(i->begin(),i->end(),false);
710  }
711 }
712 
713 bool team::shroud_map::value(int x, int y) const
714 {
715  if ( !enabled_ )
716  return false;
717 
718  // Locations for which we have no data are assumed to still be covered.
719  if ( x < 0 || x >= static_cast<int>(data_.size()) )
720  return true;
721  if ( y < 0 || y >= static_cast<int>(data_[x].size()) )
722  return true;
723 
724  // data_ stores whether or not a location has been cleared, while
725  // we want to return whether or not a location is covered.
726  return !data_[x][y];
727 }
728 
729 bool team::shroud_map::shared_value(const std::vector<const shroud_map*>& maps, int x, int y) const
730 {
731  if ( !enabled_ )
732  return false;
733 
734  // A quick abort:
735  if ( x < 0 || y < 0 )
736  return true;
737 
738  // A tile is uncovered if it is uncovered on any shared map.
739  for (const shroud_map * const shared_map : maps) {
740  if ( shared_map->enabled_ && !shared_map->value(x,y) )
741  return false;
742  }
743  return true;
744 }
745 
747 {
748  std::stringstream shroud_str;
749  for(std::vector<std::vector<bool> >::const_iterator sh = data_.begin(); sh != data_.end(); ++sh) {
750  shroud_str << '|';
751 
752  for(std::vector<bool>::const_iterator i = sh->begin(); i != sh->end(); ++i) {
753  shroud_str << (*i ? '1' : '0');
754  }
755 
756  shroud_str << '\n';
757  }
758 
759  return shroud_str.str();
760 }
761 
763 {
764  data_.clear();
765  for(std::string::const_iterator sh = str.begin(); sh != str.end(); ++sh) {
766  if(*sh == '|')
767  data_.resize(data_.size()+1);
768 
769  if(data_.empty() == false) {
770  if(*sh == '1')
771  data_.back().push_back(true);
772  else if(*sh == '0')
773  data_.back().push_back(false);
774  }
775  }
776 }
777 
779 {
780  int x=0, y=0;
781  for(std::string::const_iterator sh = str.begin(); sh != str.end(); ++sh) {
782  if(*sh == '|' && sh != str.begin()) {
783  y=0;
784  x++;
785  } else if(*sh == '1') {
786  clear(x,y);
787  y++;
788  } else if(*sh == '0') {
789  y++;
790  }
791  }
792 }
793 
794 bool team::shroud_map::copy_from(const std::vector<const shroud_map*>& maps)
795 {
796  if(enabled_ == false)
797  return false;
798 
799  bool cleared = false;
800  for(std::vector<const shroud_map*>::const_iterator i = maps.begin(); i != maps.end(); ++i) {
801  if((*i)->enabled_ == false)
802  continue;
803 
804  const std::vector<std::vector<bool> >& v = (*i)->data_;
805  for(size_t x = 0; x != v.size(); ++x) {
806  for(size_t y = 0; y != v[x].size(); ++y) {
807  if(v[x][y]) {
808  cleared |= clear(x,y);
809  }
810  }
811  }
812  }
813  return cleared;
814 }
815 
817 {
820 
821  if(gp != game_config::team_rgb_range.end()){
822  return(gp->second);
823  }
824 
825  return(color_range(0x00FF0000,0x00FFFFFF,0x00000000,0x00FF0000));
826 }
827 
829 {
830  return int_to_color(get_side_color_range(side).mid());
831 }
832 
834 {
835  // Note: use mid() instead of rep() unless
836  // high contrast is needed over a map or minimap!
837  return int_to_color(get_side_color_range(side).rep());
838 }
839 
841 {
842  size_t index = size_t(side-1);
843 
844  if(teams != nullptr && index < teams->size()) {
845  const std::string side_map = (*teams)[index].color();
846  if(!side_map.empty()) {
847  return side_map;
848  }
849  }
850  return std::to_string(side);
851 }
852 
854 {
855  return rgb2highlight(get_side_color_range(side+1).mid());
856 }
857 
859 {
860  return rgb2highlight_pango(get_side_color_range(side+1).mid());
861 }
862 
863 void team::log_recruitable() const {
864  LOG_NG << "Adding recruitable units: \n";
865  for (std::set<std::string>::const_iterator it = info_.can_recruit.begin();
866  it != info_.can_recruit.end(); ++it) {
867  LOG_NG << *it << std::endl;
868  }
869  LOG_NG << "Added all recruitable units\n";
870 }
871 
873 {
874  config cfg;
875  config& result = cfg.add_child("side");
876  write(result);
877  return result;
878 }
879 
881 {
882  std::vector<int> res;
883  for(const team& t : *teams)
884  {
885  if(!t.is_enemy(this->side()) && t.is_human()) {
886  res.push_back(t.side());
887  }
888  }
889  return utils::join(res);
890 }
const t_string & faction_name() const
Definition: team.hpp:309
play_controller * controller
Definition: resources.cpp:21
bool uses_shroud() const
Definition: team.hpp:315
child_itors child_range(const std::string &key)
Definition: config.cpp:613
bool is_local() const
Definition: team.hpp:261
static const int default_team_gold_
Definition: team.hpp:172
const std::string & flag() const
Definition: team.hpp:301
void place(int x, int y)
Definition: team.cpp:687
std::vector< bool > enemies_
Definition: team.hpp:426
bool translatable() const
Definition: tstring.hpp:172
std::string last_recruit_
Definition: team.hpp:422
const std::string & current_player() const
Definition: team.hpp:238
#define ERR_NG
Definition: team.cpp:42
void write(config &cfg) const
Definition: team.cpp:237
int start_gold() const
Definition: team.hpp:195
static std::string get_side_highlight(int side)
Definition: team.cpp:853
const std::string & color() const
Definition: team.hpp:257
std::map< std::string, color_range > team_rgb_range
int village_support
Definition: game_config.cpp:39
void handle_legacy_share_vision(const config &cfg)
Definition: team.cpp:221
void set_objectives(const t_string &new_objectives, bool silently=false)
Definition: team.cpp:560
bool shrouded(const map_location &loc) const
Definition: team.cpp:567
#define DBG_NG
Definition: team.cpp:39
bool persistent() const
Definition: team.hpp:346
const std::set< std::string > & recruits() const
Definition: team.hpp:228
SDL_Color int_to_color(const Uint32 rgb)
Definition: utils.cpp:63
bool hidden() const
Definition: team.hpp:344
void handle_legacy_share_vision(const config &cfg)
Definition: team.hpp:397
static const color_range get_side_color_range(int side)
Definition: team.cpp:816
bool is_village(const map_location &loc) const
Definition: map.cpp:68
t_string objectives
Definition: team.hpp:135
double carryover_bonus() const
Definition: team.hpp:356
bool is_enemy(int n) const
Definition: team.hpp:247
const t_string & objectives() const
Definition: team.hpp:244
void clear(const std::string &key)
virtual config local_choice() const =0
We are in a game with no mp server and need to do this choice locally.
#define WRN_NG
Definition: team.cpp:41
bool objectives_changed() const
Definition: team.hpp:245
unit_type_data unit_types
Definition: types.cpp:1314
void build(const config &cfg, const gamemap &map, int gold=default_team_gold_)
Definition: team.cpp:306
config to_config() const
Definition: team.cpp:872
bool fire(const std::string &event, const entity_location &loc1=entity_location::null_entity, const entity_location &loc2=entity_location::null_entity, const config &data=config())
Function to fire an event.
Definition: pump.cpp:471
int minimum_recruit_price
Definition: team.hpp:114
DEFEAT_CONDITION defeat_condition() const
Definition: team.hpp:339
boost::shared_ptr< wb::side_actions > planned_actions_
Whiteboard planned actions for this team.
Definition: team.hpp:433
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
team()
Definition: team.cpp:283
const config & child_or_empty(const std::string &key) const
Returns the first child with the given key, or an empty config if there is none.
Definition: config.cpp:722
bool objectives_changed
< Team's objectives for the current level.
Definition: team.hpp:140
void add_recruit(const std::string &)
Definition: team.cpp:413
-file sdl_utils.hpp
void change_controller(const std::string &new_controller)
Definition: team.hpp:275
GLdouble GLdouble t
Definition: glew.h:1366
int carryover_gold() const
Definition: team.hpp:358
Variant for storing WML attributes.
Definition: config.hpp:223
game_data * gamedata
Definition: resources.cpp:22
config::attribute_value & get_variable(const std::string &varname)
throws invalid_variablename_exception if varname is no valid variable name.
Definition: game_data.cpp:70
SHARE_VISION share_vision() const
Definition: team.hpp:388
static std::string get_side_highlight_pango(int side)
Definition: team.cpp:858
std::string flag_icon
Definition: game_config.cpp:84
bool blank() const
Tests for an attribute that was never set.
Definition: config.cpp:367
static const boost::container::flat_set< std::string > attributes
Stores the attributes recognized by [side].
Definition: team.hpp:180
shroud_map shroud_
Definition: team.hpp:410
static lg::log_domain log_engine_enemies("engine/enemies")
team_info info_
Definition: team.hpp:416
static bool add_ai_for_side_from_file(side_number side, const std::string &file, bool replace=true)
Adds active AI for specified side from file.
Definition: manager.cpp:640
static std::vector< team > *& teams
Definition: team.cpp:50
std::string team_name
Definition: team.hpp:117
static void raise_recruit_list_changed()
Notifies all observers of 'ai_recruit_list_changed' event.
Definition: manager.cpp:469
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:50
bool calculate_enemies(size_t index) const
Definition: team.cpp:441
bool is_human() const
Definition: team.hpp:264
int recall_cost() const
Definition: team.hpp:198
const std::string & flag_icon() const
Definition: team.hpp:302
GLuint GLuint end
Definition: glew.h:1221
GLuint64EXT * result
Definition: glew.h:10727
GLuint id
Definition: glew.h:1647
std::vector< team > * teams
Definition: resources.cpp:29
void read(const config &cfg)
Definition: team.cpp:119
virtual const char * name() const =0
int village_support() const
Definition: team.hpp:204
config & variables()
Definition: team.hpp:359
const t_string & user_team_name() const
Definition: team.hpp:298
int carryover_percentage() const
Definition: team.hpp:352
const int gold_carryover_percentage
Default percentage gold carried over to the next scenario.
Definition: game_config.cpp:47
const GLdouble * v
Definition: glew.h:1359
void set_local(bool local)
Definition: team.hpp:272
bool lost() const
Definition: team.hpp:349
static config to_config(side_number side)
Gets AI config for active AI of the given side.
Definition: manager.cpp:759
void write(config &cfg) const
Definition: team.cpp:355
Encapsulates the map of the game.
Definition: map.hpp:37
bool share_maps() const
Definition: team.hpp:386
config & add_child(const std::string &key)
Definition: config.cpp:743
const std::string & team_name() const
Definition: team.hpp:297
bool no_leader() const
Definition: team.hpp:338
void log_recruitable() const
Definition: team.cpp:863
Managing the AIs lifecycle - headers.
void merge(const std::string &shroud_data)
Definition: team.cpp:778
Error used for any general game error, e.g.
Definition: game_errors.hpp:46
bool auto_shroud_updates_
Definition: team.hpp:414
void remove_fog_override(const std::set< map_location > &hexes)
Removes the record of hexes that were cleared of fog via WML.
Definition: team.cpp:644
std::vector< const shroud_map * > ally_fog_
Definition: team.hpp:428
game_events::manager * game_events
Definition: resources.cpp:24
GLuint color
Definition: glew.h:5801
const std::string & save_id() const
Definition: team.hpp:236
std::string join(T const &v, const std::string &s=",")
Generates a new string joining container items in a list.
int cost() const
Definition: types.hpp:134
Encapsulates the map of the game.
Definition: location.hpp:38
bool calculate_is_enemy(size_t index) const
Definition: team.cpp:454
std::vector< map_location > parse_location_range(const std::string &xvals, const std::string &yvals, bool with_border=false) const
Parses ranges of locations into a vector of locations, using this map's dimensions as bounds...
Definition: map.cpp:537
GLuint res
Definition: glew.h:9258
static void clear_caches()
clear the shroud, fog, and enemies cache for all teams
Definition: team.cpp:549
int start_gold
Definition: team.hpp:110
const std::vector< const shroud_map * > & ally_shroud(const std::vector< team > &teams) const
Definition: team.cpp:589
virtual ~team()
Definition: team.cpp:302
bool share_view() const
Definition: team.hpp:387
void write_location_range(const std::set< map_location > &locs, config &cfg)
Write a set of locations into a config using ranges, adding keys x=x1,..,xn and y=y1a-y1b,..,yna-ynb.
Definition: location.cpp:371
bool value(int x, int y) const
Definition: team.cpp:713
const std::vector< const shroud_map * > & ally_fog(const std::vector< team > &teams) const
Definition: team.cpp:602
const std::string & faction() const
Definition: team.hpp:308
void read(const std::string &shroud_data)
Definition: team.cpp:762
int countdown_time_
Definition: team.hpp:418
void set_enabled(bool enabled)
Definition: team.hpp:98
Game configuration data as global variables.
Definition: build_info.cpp:38
std::set< map_location > villages_
Definition: team.hpp:408
int village_income
Definition: game_config.cpp:38
#define LOG_NGE
Definition: team.cpp:46
static SDL_Color get_minimap_color(int side)
Definition: team.cpp:833
GLuint index
Definition: glew.h:1782
Define the game's event mechanism.
A color range definition is made of four reference RGB colors, used for calculating conversions from ...
Definition: color_range.hpp:54
size_t i
Definition: function.cpp:1057
static SDL_Color get_side_color(int side)
Definition: team.cpp:828
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
bool fogged(const map_location &loc) const
Definition: team.cpp:575
static t_string from_serialized(const std::string &string)
Definition: tstring.hpp:135
void validate_side(int side)
Definition: team.cpp:657
int side() const
Definition: team.hpp:193
bool no_turn_confirmation() const
Definition: team.hpp:362
static bool add_ai_for_side_from_config(side_number side, const config &cfg, bool replace=true)
Adds active AI for specified side from cfg.
Definition: manager.cpp:651
std::vector< const shroud_map * > ally_shroud_
Definition: team.hpp:428
recall_list_manager recall_list_
Definition: team.hpp:421
void change_controller_by_wml(const std::string &new_controller)
Definition: team.cpp:512
bool clear(int x, int y)
Definition: team.cpp:668
static lg::log_domain log_engine("engine")
game_events::t_pump & pump()
Definition: manager.cpp:194
#define LOG_NG
Definition: team.cpp:40
GLuint const GLchar * name
Definition: glew.h:1782
CONTROLLER controller() const
Definition: team.hpp:256
bool knows_about_team(size_t index) const
Definition: team.cpp:615
GLsizeiptr size
Definition: glew.h:1649
int gold() const
Definition: team.hpp:194
void reset()
Definition: team.cpp:703
int countdown_time() const
Definition: team.hpp:215
bool has_attribute(const std::string &key) const
Definition: config.cpp:514
std::set< map_location > fog_clearer_
Stores hexes that have been cleared of fog via WML.
Definition: team.hpp:412
const std::string & side_name() const
Definition: team.hpp:307
bool find(E event, F functor)
Tests whether an event handler is available.
void lose_village(const map_location &)
Definition: team.cpp:399
shroud_map fog_
Definition: team.hpp:410
bool uses_fog() const
Definition: team.hpp:316
int gold_
Definition: team.hpp:407
t_string user_team_name
Definition: team.hpp:118
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:658
int action_bonus_count_
Definition: team.hpp:419
std::vector< std::vector< bool > > data_
Definition: team.hpp:101
static std::string get_side_color_index(int side)
Definition: team.cpp:840
void change_team(const std::string &name, const t_string &user_name)
Definition: team.cpp:534
std::string rgb2highlight(Uint32 rgb)
Converts a color value to WML text markup syntax for highlighting.
std::set< std::string > can_recruit
Definition: team.hpp:116
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:1155
bool carryover_add() const
Definition: team.hpp:354
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
std::string rgb2highlight_pango(Uint32 rgb)
Converts a color value to WML text markup syntax for highlighting.
void clear_variable(const std::string &varname)
Clears attributes config children does nothing if varname is no valid variable name.
Definition: game_data.cpp:122
void set_recruits(const std::set< std::string > &recruits)
Definition: team.cpp:406
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
std::string allied_human_teams() const
Definition: team.cpp:880
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
int action_bonus_count() const
Definition: team.hpp:218
bool copy_from(const std::vector< const shroud_map * > &maps)
Definition: team.cpp:794
virtual config request() const =0
the request which is sended to the mp server.
GLsizei const GLcharARB ** string
Definition: glew.h:4503
This internal whiteboard class holds the planned action queues for a team, and offers many utility me...
std::string write() const
Definition: team.cpp:746
bool empty() const
Definition: tstring.hpp:166
bool shared_value(const std::vector< const shroud_map * > &maps, int x, int y) const
Definition: team.cpp:729
bool get_village(const map_location &, const int owner_side, game_data *fire_event)
Acquires a village from owner_side. Pointer fire_event should be the game_data for the game if it is ...
Definition: team.cpp:377
static config ask_server_choice(const server_choice &)
int minimum_recruit_price() const
Definition: team.cpp:420