53 #define ERR_NG LOG_STREAM(err, log_engine)
54 #define DBG_NG LOG_STREAM(debug, log_engine)
103 : ambusher_(units.end())
104 , failed_teleport_(units.end())
109 , interrupted_(false)
120 , interrupted_(false)
182 take_village_step(
const config& cfg)
189 static const char* get_type_impl() {
return "take_village"; }
190 virtual const char* get_type()
const {
return get_type_impl(); }
192 virtual ~take_village_step() { }
204 virtual bool undo(
int)
218 static auto reg_undo_take_village_step = undo_action_container::subaction_factory<take_village_step>();
224 team *
t =
static_cast<unsigned>(side - 1) < teams.size() ? &teams[side - 1] :
nullptr;
225 if (
t &&
t->owns_village(
loc)) {
231 bool grants_timebonus =
false;
233 int old_owner_side = 0;
236 for(
team& tm : teams) {
237 int i_side = tm.side();
238 if (!
t || not_defeated ||
t->is_enemy(i_side)) {
239 if(tm.owns_village(
loc)) {
240 old_owner_side = i_side;
241 tm.lose_village(
loc);
243 if (side != i_side && action_timebonus) {
244 grants_timebonus =
true;
253 if(grants_timebonus) {
254 t->set_action_bonus_count(1 +
t->action_bonus_count());
255 *action_timebonus =
true;
274 typedef std::vector<map_location>::const_iterator route_iterator;
277 unit_mover(
const unit_mover&) =
delete;
278 unit_mover& operator=(
const unit_mover&) =
delete;
280 unit_mover(
const std::vector<map_location> & route,
281 move_unit_spectator *move_spectator,
282 bool skip_sightings,
bool skip_ally_sightings);
286 bool check_expected_movement();
288 void try_actual_movement(
bool show);
292 void feedback()
const;
294 void try_teleport(
bool show);
297 std::vector<map_location> expected_path()
const
303 std::size_t steps_travelled()
const
311 bool interrupted(
bool include_end_of_move_events=
true)
const
322 void cache_hidden_units(
const route_iterator &
start,
323 const route_iterator & stop);
325 void fire_hex_event(
const std::string & event_name,
326 const route_iterator & current,
327 const route_iterator & other);
329 bool is_ai_move()
const
334 route_iterator plot_turn(
const route_iterator &
start,
335 const route_iterator & stop);
340 void pump_sighted(
const route_iterator & from);
342 static std::string read_ambush_string(
const unit & ambusher);
344 void reveal_ambusher(
const map_location & hex,
bool update_alert=
true);
347 bool undo_blocked()
const
356 inline void check_for_ambushers(
const map_location & hex);
358 inline bool check_for_obstructing_unit(
const map_location & hex,
361 inline bool do_move(
const route_iterator & step_from,
362 const route_iterator & step_to,
369 inline void handle_fog(
const map_location & hex,
bool new_animation);
370 inline bool is_reasonable_stop(
const map_location & hex)
const;
372 inline void reveal_ambushers();
374 inline void validate_ambushers();
386 const std::vector<map_location> &
route_;
441 unit_mover::unit_mover(
const std::vector<map_location> & route,
442 move_unit_spectator *move_spectator,
443 bool skip_sightings,
bool skip_ally_sightings)
460 ,
goto_( is_ai_move() ?
move_it_->get_goto() : route.back() )
493 unit_mover::~unit_mover()
514 inline void unit_mover::check_for_ambushers(
const map_location & hex)
522 if ( neighbor_it != units.
end() &&
524 neighbor_it->invisible(
loc) )
541 inline bool unit_mover::check_for_obstructing_unit(
const map_location & hex,
564 const auto allowed_teleports = teleports.
get_adjacents(prev_hex);
566 if(allowed_teleports.count(hex) == 0) {
592 inline bool unit_mover::do_move(
const route_iterator & step_from,
593 const route_iterator & step_to,
606 move_it_->anim_comp().invalidate(disp);
617 move_it_->set_facing(step_from->get_relative_dir(*step_to));
621 move_it_->anim_comp().set_standing(
false);
628 move_it_->appearance_changed(),
false);
629 move_it_->set_appearance_changed(
false);
644 const route_iterator step_to =
begin_ + 1;
647 move_it_->anim_comp().invalidate(disp);
657 move_it_->anim_comp().set_standing(
false);
665 move_it_->set_appearance_changed(
false);
677 inline void unit_mover::handle_fog(
const map_location & hex,
705 inline bool unit_mover::is_reasonable_stop(
const map_location & hex)
const
726 inline void unit_mover::reveal_ambushers()
734 reveal_ambusher(reveal,
true);
747 inline void unit_mover::validate_ambushers()
778 void unit_mover::cache_hidden_units(
const route_iterator &
start,
779 const route_iterator & stop)
789 validate_ambushers();
802 if (
start == stop ) {
836 void unit_mover::fire_hex_event(
const std::string & event_name,
837 const route_iterator & current,
838 const route_iterator & other)
855 unit_mover::route_iterator unit_mover::plot_turn(
const route_iterator &
start,
856 const route_iterator & stop)
865 int remaining_moves =
move_it_->movement_left();
879 for ( ;
end != stop; ++
end )
885 remaining_moves -=
move_it_->movement_cost(map[*end]);
886 if ( remaining_moves < 0 ) {
894 if (!
move_it_->get_ability_bool(
"skirmisher", *end) &&
937 const route_iterator new_limit = plot_turn(step,
expected_end_);
938 cache_hidden_units(step, new_limit);
956 void unit_mover::pump_sighted(
const route_iterator & from)
959 post_wml(pump_res, from);
966 std::string unit_mover::read_ambush_string(
const unit & ambusher)
970 const std::string & ambush_string = (*hide.ability_cfg)[
"alert"].str();
971 if (!ambush_string.empty()) {
972 return ambush_string;
977 return std::string();
986 void unit_mover::reveal_ambusher(
const map_location & hex,
bool update_alert)
994 if ( ambusher != units.
end() ) {
1006 if ( update_alert ) {
1020 auto [wml_undo_blocked, wml_move_aborted] =
actor_sighted(*ambusher, &sight_cache);
1040 bool unit_mover::check_expected_movement()
1053 void unit_mover::try_actual_movement(
bool show)
1055 static const std::string enter_hex_str(
"enter hex");
1056 static const std::string exit_hex_str(
"exit hex");
1059 bool obstructed_stop =
false;
1077 const route_iterator step_from =
real_end_ - 1;
1084 if (
sighted_ && is_reasonable_stop(*step_from) ) {
1090 fire_hex_event(exit_hex_str, step_from,
real_end_);
1097 obstructed_stop =
true;
1102 bool new_animation = do_move(step_from,
real_end_, animator);
1112 fire_hex_event(enter_hex_str,
real_end_, step_from);
1135 if (!obstructed_stop) {
1149 void unit_mover::try_teleport(
bool show)
1151 const route_iterator step_from =
real_end_ - 1;
1158 fire_hex_event(
"exit hex", step_from,
begin_);
1160 bool new_animation = do_teleport(animator);
1163 handle_fog(*(
begin_ + 1), new_animation);
1167 fire_hex_event(
"enter hex",
begin_, step_from);
1169 if(is_reasonable_stop(*step_from)) {
1170 pump_sighted(step_from);
1173 pump_sighted(step_from);
1193 void unit_mover::post_move()
1197 int orig_village_owner = 0;
1198 bool action_time_bonus =
false;
1238 spectator_->set_tiles_entered(steps_travelled());
1244 if(!mover_valid || undo_blocked()) {
1261 void unit_mover::feedback()
const
1268 std::string message_prefix =
"";
1273 message_prefix +=
" \n";
1281 std::string teleport_string =
_(
"Failed teleport! Exit not empty");
1283 message_prefix +=
" \n";
1297 symbols[
"friendphrase"] =
VNGETTEXT(
"Part of 'Units sighted! (...)' sentence^1 friendly",
"$friends friendly",
friend_count_, symbols);
1299 symbols[
"enemyphrase"] =
VNGETTEXT(
"Part of 'Units sighted! (...)' sentence^1 enemy",
"$enemies enemy",
enemy_count_, symbols);
1302 message =
VGETTEXT(
"Units sighted! ($friendphrase, $enemyphrase)", symbols);
1316 disp.
announce(message_prefix + message, msg_color, announce_options);
1317 message_prefix +=
" \n";
1324 if ( !name.empty() ) {
1326 symbols[
"hotkey"] = name;
1327 std::string
message =
VGETTEXT(
"(press $hotkey to keep moving)", symbols);
1329 message_prefix +=
" \n";
1343 mover.try_actual_movement(show_move);
1347 "stopped_early", mover.stopped_early(),
1348 "final_hex_x", mover.final_hex().wml_x(),
1349 "final_hex_y", mover.final_hex().wml_y(),
1354 replay::process_error(
"calculated movement destination (x="+ cn[
"final_hex_x"].str() +
" y=" + cn[
"final_hex_y"].str() +
1355 ") didn't match the original destination(x="+ co[
"final_hex_x"].str() +
" y=" + co[
"final_hex_y"].str() +
")\n");
1385 bool continued_move,
1386 bool skip_ally_sighted,
1390 unit_mover mover(steps, move_spectator, continued_move, skip_ally_sighted);
1391 if(!mover.check_expected_movement()) {
1392 DBG_NG <<
"found expected empty move, aborting";
1404 config{
"teleport_from_x", teleport_from.
wml_x(),
"teleport_from_y", teleport_from.
wml_y(),
"teleport_to_x",
1405 teleport_to.
wml_x(),
"teleport_to_y", teleport_to.
wml_y()});
1409 bool continued_move,
bool skip_ally_sighted,
bool show_move)
1411 unit_mover mover(steps,
nullptr, continued_move, skip_ally_sighted);
1412 mover.try_teleport(show_move);
1432 const std::vector<map_location>& steps,
bool continued_move,
bool* interrupted)
1437 *interrupted = move_spectator.get_interrupted();
1439 return move_spectator.get_tiles_entered();
1456 const std::vector<map_location>& steps,
bool continued_move,
move_unit_spectator& move_spectator)
1460 if ( steps.size() < 2 || (steps.size() == 2 && steps.front() == steps.back()) ) {
1461 DBG_NG <<
"Ignoring a unit trying to jump on its hex at " <<
1472 const bool skip_ally_sighted = !
prefs::get().ally_sighted_interrupts();
std::string ambush_string_
bool event_mutated_mid_move_
std::vector< map_location > ambushers_
std::size_t friend_count_
unit_map::iterator move_it_
route_iterator expected_end_
map_location blocked_loc_
int original_village_owner
static lg::log_domain log_engine("engine")
const std::vector< map_location > & route_
map_location ambush_stop_
bool take_village_timebonus
const bool playing_team_is_viewing_
route_iterator obstructed_
const map_location::direction orig_dir_
std::deque< int > moves_left_
route_iterator ambush_limit_
move_unit_spectator *const spectator_
const route_iterator begin_
const bool skip_sighting_
const route_iterator full_end_
const bool skip_ally_sighting_
Various functions related to moving units.
void set_ambusher(const unit_map::const_iterator &u)
set the location of an ambusher
void add_seen_friend(const unit_map::const_iterator &u)
add a location of a seen friend
const std::vector< unit_map::const_iterator > & get_seen_enemies() const
get the locations of seen enemies
const unit_map::const_iterator & get_ambusher() const
get the location of an ambusher
void error(const std::string &message) override
ingerited from action_spectator
void add_seen_enemy(const unit_map::const_iterator &u)
add the location of new seen enemy
const unit_map::const_iterator & get_unit() const
get new location of moved unit
unit_map::const_iterator ambusher_
unit_map::const_iterator unit_
void reset(const unit_map &units)
reset all locations to empty values
void set_unit(const unit_map::const_iterator &u)
set the iterator to moved unit
std::vector< unit_map::const_iterator > seen_enemies_
void set_failed_teleport(const unit_map::const_iterator &u)
set the location of a failed teleport
std::vector< unit_map::const_iterator > seen_friends_
virtual ~move_unit_spectator()
destructor
const std::vector< unit_map::const_iterator > & get_seen_friends() const
get the locations of seen friends
std::size_t tiles_entered_
const unit_map::const_iterator & get_failed_teleport() const
get the location of a failed teleport
unit_map::const_iterator failed_teleport_
void add_custom(Args &&... args)
void add_move(const unit_const_ptr &u, const std::vector< map_location >::const_iterator &begin, const std::vector< map_location >::const_iterator &end, int start_moves, const map_location::direction dir=map_location::direction::indeterminate)
Adds a move to the undo stack.
virtual bool local_checkup(const config &expected_data, config &real_data)=0
Compares data to the results calculated during the original game.
A config object defines a single node in a WML file, with access to child nodes.
int village_owner(const map_location &loc) const
Given the location of a village, will return the 1-based number of the team that currently owns it,...
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
void redraw_minimap()
Schedule the minimap to be redrawn.
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
void announce(const std::string &msg, const color_t &color=font::GOOD_COLOR, const announce_options &options=announce_options())
Announce a message prominently.
bool fogged(const map_location &loc) const
Returns true if location (x,y) is covered in fog.
static display * get_singleton()
Returns the display object if a display object exists.
virtual const std::vector< team > & teams() const override
bool team_is_defeated(const team &t) const
Calculates whether a team is defeated.
virtual const unit_map & units() const override
virtual const gamemap & map() const override
void invalidate_unit_after_move(const map_location &src, const map_location &dst)
Same as invalidate_unit() if moving the displayed unit.
static game_display * get_singleton()
Encapsulates the map of the game.
bool is_village(const map_location &loc) const
const std::unordered_set< map_location > & get_adjacents(map_location loc) const
bool is_skipping_actions() const
bool is_skipping_replay() const
static config get_movement(const std::vector< map_location > &steps, bool skip_sighted, bool skip_ally_sighted)
Records a move that follows the provided steps.
static void process_error(const std::string &msg)
static void block_undo(bool do_block=true, bool clear_undo=true)
set this to false to prevent clearing the undo stack, this is important when we cannot change the gam...
static bool run_and_throw(const std::string &commandname, const config &data, action_spectator &spectator=get_default_spectator())
This class stores all the data for a single 'side' (in game nomenclature).
void set_action_bonus_count(const int count)
bool fog_or_shroud() const
bool auto_shroud_updates() const
bool is_enemy(int n) const
int action_bonus_count() const
bool owns_village(const map_location &loc) const
A class to encapsulate the steps of drawing a unit's move.
void finish(const unit_ptr &u, map_location::direction dir=map_location::direction::indeterminate)
Finishes the display of movement for the supplied unit.
void wait_for_anims()
Waits for the final animation of the most recent proceed_to() to finish.
void proceed_to(const unit_ptr &u, std::size_t path_index, bool update=false, bool wait=true)
Visually moves a unit from the last hex we drew to the one specified by path_index.
void start(const unit_ptr &u)
Initiates the display of movement for the supplied unit.
Container associating units to locations.
std::size_t count(const map_location &loc) const
unit_iterator find(std::size_t id)
umap_retval_pair_t move(const map_location &src, const map_location &dst)
Moves a unit from location src to location dst.
This class represents a single unit of a specific type.
static void clear_status_caches()
Clear this unit status cache for all units.
static std::string _(const char *str)
unit_ability_list get_abilities(const std::string &tag_name, const map_location &loc) const
Gets the unit's active abilities of a particular type if it were on a specified location.
@ STATE_UNCOVERED
The unit is petrified - it cannot move or be attacked.
T end(const std::pair< T, T > &p)
T begin(const std::pair< T, T > &p)
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Standard logging facilities (interface).
std::vector< int > get_sides_not_seeing(const unit &target)
Returns the sides that cannot currently see target.
void teleport_unit_from_replay(const std::vector< map_location > &steps, bool continued_move, bool skip_ally_sighted, bool show_move)
Teleports a unit across the board.
game_events::pump_result_t actor_sighted(const unit &target, const std::vector< int > *cache)
Fires sighted events for the sides that can see target.
void teleport_unit_and_record(const map_location &teleport_from, const map_location &teleport_to, move_unit_spectator *)
Teleports a unit across the board and enters the synced context.
void move_unit_and_record(const std::vector< map_location > &steps, bool continued_move, move_unit_spectator &move_spectator)
Moves a unit across the board.
game_events::pump_result_t get_village(const map_location &loc, int side, bool *action_timebonus, bool fire_event)
Makes it so the village at the given location is owned by the given side.
static void move_unit_internal(unit_mover &mover)
void execute_move_unit(const std::vector< map_location > &steps, bool continued_move, bool skip_ally_sighted, move_unit_spectator *move_spectator)
Moves a unit across the board.
EXIT_STATUS start(bool clear_id, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
void pump()
Process all events currently in the queue.
const color_t NORMAL_COLOR
std::tuple< bool, bool > pump_result_t
void show(const std::string &window_id, const t_string &message, const point &mouse, const SDL_Rect &source_rect)
Shows a tip.
bool fire_event(const ui_event event, const std::vector< std::pair< widget *, ui_event >> &event_chain, widget *dispatcher, widget *w, F &&... params)
Helper function for fire_event.
static bool is_active(const widget *wgt)
std::string get_names(const std::string &id)
Returns a comma-separated string of hotkey names.
bool enemy_zoc(const team ¤t_team, const map_location &loc, const team &viewing_team, bool see_all)
Determines if a given location is in an enemy zone of control.
const teleport_map get_teleport_locations(const unit &u, const team &viewing_team, bool see_all, bool ignore_units, bool check_vision)
game_events::manager * game_events
actions::undo_list * undo_stack
play_controller * controller
std::shared_ptr< wb::manager > whiteboard
std::map< std::string, t_string > string_map
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
This module contains various pathfinding functions and utilities.
Define the game's event mechanism.
void write(std::ostream &out, const configr_of &cfg, unsigned int level)
Records information to be able to undo an action.
virtual void write(config &cfg) const
Writes this into the provided config.
The basic class for representing 8-bit RGB or RGBA colour values.
Holds options for calls to function 'announce' (announce).
bool discard_previous
An announcement according these options should replace the previous announce (typical of fast announc...
static const hotkey_command & get_command_by_command(HOTKEY_COMMAND command)
the execute_command argument was changed from HOTKEY_COMMAND to hotkey_command, to be able to call it...
Encapsulates the map of the game.
direction
Valid directions which can be moved in our hexagonal world.
static const map_location & null_location()
void write(config &cfg) const
Data typedef for unit_ability_list.
pointer get_shared_ptr() const
This is exactly the same as operator-> but it's slightly more readable, and can replace &*iter syntax...
checkup * checkup_instance
Display units performing various actions: moving, attacking, and dying.
Various functions that implement the undoing (and redoing) of in-game commands.
Various functions implementing vision (through fog of war and shroud).