The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
mapbuilder.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2010 - 2025
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"
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
34namespace 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(display::get_singleton()->viewing_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
116void 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) {
154 std::set<class unit const*>::iterator invalid_it = has_invalid_actions_.find(unit.get());
155 if(invalid_it != has_invalid_actions_.end()) {
156 for(std::list<side_actions::iterator>::iterator it = invalid_actions_.begin(); it != 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
177void 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) {
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
const team & viewing_team() const
Definition display.cpp:337
static display * get_singleton()
Returns the display object if a display object exists.
Definition display.hpp:102
virtual const std::vector< team > & teams() const override
virtual const unit_map & units() const override
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:39
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_
mapbuilder(unit_map &unit_map)
std::set< unit const * > has_invalid_actions_
std::list< side_actions::iterator > invalid_actions_
Conserved invalid actions.
void build_map()
Builds every team's actions as far into the future as possible, in the correct order.
virtual ~mapbuilder()
std::vector< std::unique_ptr< temporary_unit_remover > > removers_
void restore_normal_map()
void process(side_actions &sa, side_actions::iterator action_it, bool is_local_side)
Function called on each action.
void post_visit_team(std::size_t turn)
Function called after visiting a team.
action_queue applied_actions_
void pre_build()
Does various preliminary actions on the unit map such as resetting moves for some units.
std::vector< std::unique_ptr< unit_movement_resetter > > resetters_
action_queue applied_actions_this_turn_
unit_map & unit_map_
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:289
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:1315
int total_movement() const
The maximum moves this unit has.
Definition unit.hpp:1236
game_board * gameboard
Definition resources.cpp:20
play_controller * controller
Definition resources.cpp:21
constexpr auto reverse
Definition ranges.hpp:44
Definition display.hpp:45
bool team_has_visible_plan(team &t)
Returns whether a given team's plan is visible.
Definition utility.cpp:171
std::shared_ptr< move > move_ptr
Definition typedefs.hpp:68
std::shared_ptr< action > action_ptr
Definition typedefs.hpp:62
bool has_actions()
Return whether the whiteboard has actions.
Definition utility.cpp:161
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.
Object which temporarily resets a unit's movement.
Definition unit.hpp:2017