The Battle for Wesnoth  1.15.12+dev
mapbuilder.cpp
Go to the documentation of this file.
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 
20 
21 #include "whiteboard/action.hpp"
22 #include "whiteboard/move.hpp"
24 #include "whiteboard/utility.hpp"
25 
26 #include "game_board.hpp"
27 #include "play_controller.hpp"
28 #include "resources.hpp"
29 #include "units/unit.hpp"
30 #include "units/map.hpp"
31 #include "utils/ranges.hpp"
32 
33 namespace wb
34 {
35 
37  : unit_map_(unit_map)
38  , applied_actions_()
39  , applied_actions_this_turn_()
40  , resetters_()
41  , removers_()
42  , acted_this_turn_()
43  , has_invalid_actions_()
44  , invalid_actions_()
45 {
46 }
47 
49 {
50  try {
52  //Remember that the member variable resetters_ is destructed here
53  } catch (...) {}
54 }
55 
57 {
58  for (team& t : resources::gameboard->teams()) {
59  //Reset spent gold to zero, it'll be recalculated during the map building
60  t.get_side_actions()->reset_gold_spent();
61  }
62 
63  int current_side = resources::controller->current_side();
64  for (unit& u : resources::gameboard->units()) {
65  bool on_current_side = (u.side() == current_side);
66 
67  //Remove any unit the current side cannot see to avoid their detection by planning
68  //Units will be restored to the unit map by destruction of removers_
69 
70  if(!on_current_side && !u.is_visible_to_team(resources::gameboard->teams()[viewer_team()], false)) {
71  removers_.emplace_back(new temporary_unit_remover(resources::gameboard->units(), u.get_location()));
72 
73  //Don't do anything else to the removed unit!
74  continue;
75  }
76 
77  //Reset movement points, to be restored by destruction of resetters_
78 
79  //restore movement points only to units not on the current side
80  resetters_.emplace_back(new unit_movement_resetter(u,!on_current_side));
81  //make sure current side's units are not reset to full moves on first turn
82  if(on_current_side) {
83  acted_this_turn_.insert(&u);
84  }
85  }
86 }
87 
89 {
90  pre_build();
91  if(!wb::has_actions()) {
92  return;
93  }
94 
95  bool stop = false;
96  for(std::size_t turn=0; !stop; ++turn) {
97  stop = true;
98  for (team &side : resources::gameboard->teams()) {
99  side_actions &actions = *side.get_side_actions();
100  if(turn < actions.num_turns() && team_has_visible_plan(side)) {
101  stop = false;
102  side_actions::iterator it = actions.turn_begin(turn), next = it, end = actions.turn_end(turn);
103  while(it != end) {
104  std::advance(next, 1);
105  process(actions, it, side.is_local());
106  it = next;
107  }
108 
109  post_visit_team(turn);
110  }
111  }
112  }
113 }
114 
115 void mapbuilder::process(side_actions &sa, side_actions::iterator action_it, bool is_local_side)
116 {
117  action_ptr action = *action_it;
118  bool acted=false;
119  unit_ptr unit = action->get_unit();
120  if(!unit) {
121  return;
122  }
123 
124 
125  if(acted_this_turn_.find(unit.get()) == acted_this_turn_.end() && !action->places_new_unit()) {
126  //reset MP
127  unit->set_movement(unit->total_movement());
128  acted=true;
129  }
130 
131  // Validity check
132  action::error erval = action->check_validity();
133  action->redraw();
134 
135  if(erval != action::OK) {
136  // We do not delete obstructed moves, nor invalid actions caused by obstructed moves.
137  if(has_invalid_actions_.find(unit.get()) == has_invalid_actions_.end()) {
138  if(!is_local_side || erval == action::TOO_FAR || (erval == action::LOCATION_OCCUPIED && std::dynamic_pointer_cast<move>(action))) {
139  has_invalid_actions_.insert(unit.get());
140  invalid_actions_.push_back(action_it);
141  } else {
142  sa.remove_action(action_it, false);
143  return;
144  }
145  } else {
146  invalid_actions_.push_back(action_it);
147  }
148  return;
149  }
150 
151  // We do not keep invalid actions replaced by a valid one.
152  if(is_local_side) {
153  std::set<class unit const*>::iterator invalid_it = has_invalid_actions_.find(unit.get());
154  if(invalid_it != has_invalid_actions_.end()) {
156  if((**it)->get_unit().get() == unit.get()) {
157  sa.remove_action(*it, false);
158  it = invalid_actions_.erase(it);
159  } else {
160  ++it;
161  }
162  }
163  has_invalid_actions_.erase(invalid_it);
164  }
165  }
166 
167  if(acted || action->places_new_unit()) {
168  acted_this_turn_.insert(unit.get());
169  }
170 
171  action->apply_temp_modifier(unit_map_);
172  applied_actions_.push_back(action);
173  applied_actions_this_turn_.push_back(action);
174 }
175 
176 void mapbuilder::post_visit_team(std::size_t turn)
177 {
178  std::set<unit const*> seen;
179 
180  // Go backwards through the actions of this turn to identify
181  // which ones are moves that end a turn.
183  move_ptr move = std::dynamic_pointer_cast<class move>(action);
184  if(move) {
185  move->set_turn_number(0);
186  if(move->get_route().steps.size() > 1 && seen.count(move->get_unit().get()) == 0) {
187  seen.insert(move->get_unit().get());
188  move->set_turn_number(turn + 1);
189  }
190  }
191  }
192 
193  // Clear list of planned actions applied this turn
195  // Clear the list of units of this team that have acted this turn
196  acted_this_turn_.clear();
197 }
198 
200 {
201  //applied_actions_ contain only the actions that we applied to the unit map
203  act->remove_temp_modifier(unit_map_);
204  }
205 }
206 
207 } // end namespace wb
virtual void set_turn_number(int turn)
Assigns a turn number to display to this planned move.
Definition: move.hpp:89
container::iterator iterator
play_controller * controller
Definition: resources.cpp:21
bool team_has_visible_plan(team &t)
Returns whether a given team&#39;s plan is visible.
Definition: utility.cpp:180
void set_movement(int moves, bool unit_action=false)
Set this unit&#39;s remaining movement to moves.
Definition: unit.cpp:1139
virtual const std::vector< team > & teams() const override
Definition: game_board.hpp:84
This class represents a single unit of a specific type.
Definition: unit.hpp:120
auto reversed_view(T &container)
Definition: ranges.hpp:27
bool has_actions()
Return whether the whiteboard has actions.
Definition: utility.cpp:170
std::set< unit const * > acted_this_turn_
Definition: mapbuilder.hpp:72
std::set< unit const * > has_invalid_actions_
Definition: mapbuilder.hpp:73
std::vector< std::unique_ptr< unit_movement_resetter > > resetters_
Definition: mapbuilder.hpp:68
std::shared_ptr< unit > unit_ptr
Definition: ptr.hpp:25
void process(side_actions &sa, side_actions::iterator action_it, bool is_local_side)
Function called on each action.
Definition: mapbuilder.cpp:115
void restore_normal_map()
Definition: mapbuilder.cpp:199
iterator remove_action(iterator position, bool validate_after_delete=true)
Deletes the action at the specified position.
void pre_build()
Does various preliminary actions on the unit map such as resetting moves for some units...
Definition: mapbuilder.cpp:56
This class stores all the data for a single &#39;side&#39; (in game nomenclature).
Definition: team.hpp:44
error
Possible errors.
Definition: action.hpp:105
game_board * gameboard
Definition: resources.cpp:20
unit_map & unit_map_
Definition: mapbuilder.hpp:62
std::shared_ptr< action > action_ptr
Definition: typedefs.hpp:61
Object which temporarily resets a unit&#39;s movement.
Definition: unit.hpp:1994
mapbuilder(unit_map &unit_map)
Definition: mapbuilder.cpp:36
action_queue applied_actions_
Definition: mapbuilder.hpp:64
This object is used to temporary remove a unit from the unit map.
Definition: game_board.hpp:210
iterator turn_begin(std::size_t turn_num)
std::list< side_actions::iterator > invalid_actions_
Conserved invalid actions.
Definition: mapbuilder.hpp:75
void post_visit_team(std::size_t turn)
Function called after visiting a team.
Definition: mapbuilder.cpp:176
std::shared_ptr< move > move_ptr
Definition: typedefs.hpp:67
#define next(ls)
Definition: llex.cpp:32
virtual ~mapbuilder()
Definition: mapbuilder.cpp:48
double t
Definition: astarsearch.cpp:64
iterator turn_end(std::size_t turn_num)
action_queue applied_actions_this_turn_
Definition: mapbuilder.hpp:65
int current_side() const
Returns the number of the side whose turn it is.
Container associating units to locations.
Definition: map.hpp:97
void build_map()
Builds every team&#39;s actions as far into the future as possible, in the correct order.
Definition: mapbuilder.cpp:88
std::size_t num_turns() const
Returns the number of turns that have plans.
Abstract base class for all the whiteboard planned actions.
Definition: action.hpp:32
std::vector< std::unique_ptr< temporary_unit_remover > > removers_
Definition: mapbuilder.hpp:69
This internal whiteboard class holds the planned action queues for a team, and offers many utility me...
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
A planned move, represented on the map by an arrow and a ghosted unit in the destination hex...
Definition: move.hpp:34
Definition: display.hpp:48
std::size_t viewer_team()
Definition: utility.cpp:40