The Battle for Wesnoth  1.19.0-dev
mapbuilder.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 2024
3  by Gabriel Morin <gabrielmorin (at) gmail (dot) 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 /**
17  * @file
18  */
19 
21 
22 #include "whiteboard/action.hpp"
23 #include "whiteboard/move.hpp"
25 #include "whiteboard/utility.hpp"
26 
27 #include "game_board.hpp"
28 #include "play_controller.hpp"
29 #include "resources.hpp"
30 #include "units/unit.hpp"
31 #include "units/map.hpp"
32 #include "utils/ranges.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_.emplace_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_.emplace_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;
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
129  acted=true;
130  }
131 
132  // Validity check
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) {
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 
173  applied_actions_.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
double t
Definition: astarsearch.cpp:63
virtual const std::vector< team > & teams() const override
Definition: game_board.hpp:79
int current_side() const
Returns the number of the side whose turn it is.
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:74
Container associating units to locations.
Definition: map.hpp:98
This class represents a single unit of a specific type.
Definition: unit.hpp:133
Abstract base class for all the whiteboard planned actions.
Definition: action.hpp:34
virtual unit_ptr get_unit() const =0
Return the unit targeted by this action.
virtual void redraw()
Redrawing function, called each time the action situation might have changed.
Definition: action.hpp:59
virtual bool places_new_unit() const
Returns true for recall and recruit actions.
Definition: action.hpp:74
virtual void apply_temp_modifier(unit_map &unit_map)=0
Applies temporarily the result of this action to the specified unit map.
error
Possible errors.
Definition: action.hpp:107
@ LOCATION_OCCUPIED
Definition: action.hpp:112
virtual error check_validity() const =0
Check the validity of the action.
std::set< unit const * > acted_this_turn_
Definition: mapbuilder.hpp:72
mapbuilder(unit_map &unit_map)
Definition: mapbuilder.cpp:37
std::set< unit const * > has_invalid_actions_
Definition: mapbuilder.hpp:73
std::list< side_actions::iterator > invalid_actions_
Conserved invalid actions.
Definition: mapbuilder.hpp:75
void build_map()
Builds every team's actions as far into the future as possible, in the correct order.
Definition: mapbuilder.cpp:89
virtual ~mapbuilder()
Definition: mapbuilder.cpp:49
std::vector< std::unique_ptr< temporary_unit_remover > > removers_
Definition: mapbuilder.hpp:69
void restore_normal_map()
Definition: mapbuilder.cpp:200
void process(side_actions &sa, side_actions::iterator action_it, bool is_local_side)
Function called on each action.
Definition: mapbuilder.cpp:116
void post_visit_team(std::size_t turn)
Function called after visiting a team.
Definition: mapbuilder.cpp:177
action_queue applied_actions_
Definition: mapbuilder.hpp:64
void pre_build()
Does various preliminary actions on the unit map such as resetting moves for some units.
Definition: mapbuilder.cpp:57
std::vector< std::unique_ptr< unit_movement_resetter > > resetters_
Definition: mapbuilder.hpp:68
action_queue applied_actions_this_turn_
Definition: mapbuilder.hpp:65
unit_map & unit_map_
Definition: mapbuilder.hpp:62
A planned move, represented on the map by an arrow and a ghosted unit in the destination hex.
Definition: move.hpp:36
virtual void set_turn_number(int turn)
Assigns a turn number to display to this planned move.
Definition: move.hpp:90
virtual unit_ptr get_unit() const
Return the unit targeted by this action.
Definition: move.cpp:287
virtual const pathfind::marked_route & get_route() const
Definition: move.hpp:70
This internal whiteboard class holds the planned action queues for a team, and offers many utility me...
iterator remove_action(iterator position, bool validate_after_delete=true)
Deletes the action at the specified position.
container::iterator iterator
void set_movement(int moves, bool unit_action=false)
Set this unit's remaining movement to moves.
Definition: unit.cpp:1200
int total_movement() const
The maximum moves this unit has.
Definition: unit.hpp:1266
game_board * gameboard
Definition: resources.cpp:20
play_controller * controller
Definition: resources.cpp:21
auto reversed_view(T &container)
Definition: ranges.hpp:28
Definition: display.hpp:45
bool team_has_visible_plan(team &t)
Returns whether a given team's plan is visible.
Definition: utility.cpp:178
std::shared_ptr< move > move_ptr
Definition: typedefs.hpp:68
std::size_t viewer_team()
Definition: utility.cpp:38
std::shared_ptr< action > action_ptr
Definition: typedefs.hpp:62
bool has_actions()
Return whether the whiteboard has actions.
Definition: utility.cpp:168
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
std::shared_ptr< unit > unit_ptr
Definition: ptr.hpp:26
std::vector< map_location > & steps
Definition: pathfind.hpp:187
This object is used to temporary remove a unit from the unit map.
Definition: game_board.hpp:206
Object which temporarily resets a unit's movement.
Definition: unit.hpp:2028