1 /*
2 Copyright (C) 2010 - 2018 by Gabriel Morin <gabrielmorin (at) gmail (dot) com>
3 Part of the Battle for Wesnoth Project https://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 */
18
19 #include <algorithm>
20 #include <iterator>
21 #include <limits>
22
23 #include "whiteboard/utility.hpp"
24
25 #include "whiteboard/manager.hpp"
26 #include "whiteboard/side_actions.hpp"
27
28 #include "actions/create.hpp"
29 #include "display.hpp"
30 #include "map/map.hpp"
31 #include "play_controller.hpp"
32 #include "resources.hpp"
33 #include "team.hpp"
34 #include "units/unit.hpp"
35 #include "units/animation_component.hpp"
36 #include "utils/iterable_pair.hpp"
37
38 namespace wb {
39
viewer_team()40 size_t viewer_team()
41 {
42 return display::get_singleton()->viewing_team();
43 }
44
viewer_side()45 int viewer_side()
46 {
47 return display::get_singleton()->viewing_side();
48 }
49
viewer_actions()50 side_actions_ptr viewer_actions()
51 {
52 side_actions_ptr side_actions =
53 resources::gameboard->teams()[display::get_singleton()->viewing_team()].get_side_actions();
54 return side_actions;
55 }
56
current_side_actions()57 side_actions_ptr current_side_actions()
58 {
59 side_actions_ptr side_actions =
60 resources::gameboard->get_team(resources::controller->current_side()).get_side_actions();
61 return side_actions;
62 }
63
find_backup_leader(const unit & leader)64 unit_const_ptr find_backup_leader(const unit & leader)
65 {
66 assert(leader.can_recruit());
67 assert(resources::gameboard->map().is_keep(leader.get_location()));
68 for (unit_map::const_iterator unit = resources::gameboard->units().begin(); unit != resources::gameboard->units().end(); ++unit)
69 {
70 if (unit->can_recruit() && unit->id() != leader.id())
71 {
72 if (dynamic_cast<game_state&>(*resources::filter_con).can_recruit_on(*unit, leader.get_location()))
73 return unit.get_shared_ptr();
74 }
75 }
76 return unit_const_ptr();
77 }
78
find_recruiter(size_t team_index,const map_location & hex)79 unit* find_recruiter(size_t team_index, const map_location& hex)
80 {
81 if ( !resources::gameboard->map().is_castle(hex) )
82 return nullptr;
83
84 for(unit& u : resources::gameboard->units())
85 if(u.can_recruit()
86 && u.side() == static_cast<int>(team_index+1)
87 && dynamic_cast<game_state&>(*resources::filter_con).can_recruit_on(u, hex))
88 return &u;
89 return nullptr;
90 }
91
any_recruiter(int team_num,const map_location & loc,std::function<bool (unit &)> func)92 bool any_recruiter(int team_num, const map_location& loc, std::function<bool(unit&)> func)
93 {
94 if ( !resources::gameboard->map().is_castle(loc) ) {
95 return false;
96 }
97
98 for(unit& u : resources::gameboard->units()) {
99 if(u.can_recruit() && u.side() == team_num && dynamic_cast<game_state&>(*resources::filter_con).can_recruit_on(u, loc)) {
100 if(func(u)) {
101 return true;
102 }
103 }
104 }
105 return false;
106 }
107
future_visible_unit(map_location hex,int viewer_side)108 unit* future_visible_unit(map_location hex, int viewer_side)
109 {
110 future_map planned_unit_map;
111 if(!resources::whiteboard->has_planned_unit_map())
112 {
113 ERR_WB << "future_visible_unit cannot find unit, future unit map failed to build." << std::endl;
114 return nullptr;
115 }
116 //use global method get_visible_unit
117 return resources::gameboard->get_visible_unit(hex, resources::gameboard->get_team(viewer_side), false);
118 }
119
future_visible_unit(int on_side,map_location hex,int viewer_side)120 unit* future_visible_unit(int on_side, map_location hex, int viewer_side)
121 {
122 unit* unit = future_visible_unit(hex, viewer_side);
123 if (unit && unit->side() == on_side)
124 return unit;
125 else
126 return nullptr;
127 }
128
path_cost(const std::vector<map_location> & path,const unit & u)129 int path_cost(const std::vector<map_location>& path, const unit& u)
130 {
131 if(path.size() < 2)
132 return 0;
133
134 const team& u_team = resources::gameboard->get_team(u.side());
135 const map_location& dest = path.back();
136 if ( (resources::gameboard->map().is_village(dest) && !u_team.owns_village(dest))
137 || pathfind::enemy_zoc(u_team, dest, u_team) )
138 return u.total_movement();
139
140 int result = 0;
141 const gamemap& map = resources::gameboard->map();
142 for(const map_location& loc : std::make_pair(path.begin()+1,path.end())) {
143 result += u.movement_cost(map[loc]);
144 }
145 return result;
146 }
147
temporary_unit_hider(unit & u)148 temporary_unit_hider::temporary_unit_hider(unit& u)
149 : unit_(&u)
150 {unit_->set_hidden(true);}
~temporary_unit_hider()151 temporary_unit_hider::~temporary_unit_hider()
152 {
153 try {
154 unit_->set_hidden(false);
155 } catch (...) {}
156 }
157
ghost_owner_unit(unit * unit)158 void ghost_owner_unit(unit* unit)
159 {
160 unit->anim_comp().set_disabled_ghosted(false);
161 display::get_singleton()->invalidate(unit->get_location());
162 }
163
unghost_owner_unit(unit * unit)164 void unghost_owner_unit(unit* unit)
165 {
166 unit->anim_comp().set_standing(true);
167 display::get_singleton()->invalidate(unit->get_location());
168 }
169
has_actions()170 bool has_actions()
171 {
172 for (team& t : resources::gameboard->teams()) {
173 if (!t.get_side_actions()->empty())
174 return true;
175 }
176
177 return false;
178 }
179
team_has_visible_plan(team & t)180 bool team_has_visible_plan(team &t)
181 {
182 return !t.get_side_actions()->hidden();
183 }
184
for_each_action(std::function<void (action *)> function,team_filter team_filter)185 void for_each_action(std::function<void(action*)> function, team_filter team_filter)
186 {
187 bool end = false;
188 for(size_t turn=0; !end; ++turn) {
189 end = true;
190 for(team &side : resources::gameboard->teams()) {
191 side_actions &actions = *side.get_side_actions();
192 if(turn < actions.num_turns() && team_filter(side)) {
193 for(auto iter = actions.turn_begin(turn); iter != actions.turn_end(turn); ++iter) {
194 function(iter->get());
195 }
196 end = false;
197 }
198 }
199 }
200 }
201
find_action_at(map_location hex,team_filter team_filter)202 action_ptr find_action_at(map_location hex, team_filter team_filter)
203 {
204 action_ptr result;
205 size_t result_turn = std::numeric_limits<size_t>::max();
206
207 for(team &side : resources::gameboard->teams()) {
208 side_actions &actions = *side.get_side_actions();
209 if(team_filter(side)) {
210 side_actions::iterator chall = actions.find_first_action_at(hex);
211 if(chall == actions.end()) {
212 continue;
213 }
214
215 size_t chall_turn = actions.get_turn(chall);
216 if(chall_turn < result_turn) {
217 result = *chall;
218 result_turn = chall_turn;
219 }
220 }
221 }
222
223 return result;
224 }
225
find_actions_of(const unit & target)226 std::deque<action_ptr> find_actions_of(const unit& target)
227 {
228 return resources::gameboard->get_team(target.side()).get_side_actions()->actions_of(target);
229 }
230
231 } //end namespace wb
232