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