1 /*
2    Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
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  * Various functions implementing vision (through fog of war and shroud).
18  */
19 
20 #pragma once
21 
22 #include "movetype.hpp"
23 #include "game_events/fwd.hpp"
24 
25 struct map_location;
26 class  team;
27 class  unit;
28 
29 #include <cstring>
30 #include <map>
31 #include <set>
32 #include <vector>
33 
34 
35 namespace actions {
36 	class  move_unit_spectator;
37 
38 /// Class that stores the part of a unit's data that is needed for fog clearing.
39 /// (Used by the undo stack as that cannot rely on a unit sticking around, and
40 /// we do not really need to copy the entire unit.)
41 struct clearer_info {
42 	size_t underlying_id;
43 	int sight_range;
44 	bool slowed;
45 	/// costs is always non-null, all of the constructors initialize it
46 	std::unique_ptr<movetype::terrain_costs> costs;
47 
48 	clearer_info(const unit & viewer);
49 	clearer_info(const config & cfg);
50 
51 	void write(config & cfg) const;
52 };
53 
54 /// Class to encapsulate fog/shroud clearing and the resultant sighted events.
55 /// Note: This class uses teams as parameters (instead of sides) since a
56 /// function using this should first check to see if fog/shroud is in use (to
57 /// save processing when it is not), which implies the team is readily available.
58 class shroud_clearer {
59 public:
60 	shroud_clearer(const shroud_clearer&) = delete;
61 	shroud_clearer& operator=(const shroud_clearer&) = delete;
62 
63 	shroud_clearer();
64 	~shroud_clearer();
65 
66 	/// Function to be called if units have moved or otherwise changed.
67 	/// It can also be called if it is desirable to calculate the cache
68 	/// in advance of fog clearing.
69 	/// @param[in] new_team  The team whose vision will be used. If left as
70 	///                      nullptr, the cache will be just be cleared (to be
71 	///                      recalculated later as needed).
cache_units(const team * new_team=nullptr)72 	void cache_units(const team * new_team=nullptr) { calculate_jamming(new_team); }
73 	// cache_units() is currently a near-synonym for calculate_jamming(). The
74 	// reason for the two names is so the private function says what it does,
75 	// while the public one says why it might be invoked.
76 
77 	/// Clears shroud (and fog) around the provided location for @a view_team
78 	/// based on @a sight_range, @a costs, and @a slowed.
79 	bool clear_unit(const map_location &view_loc, team &view_team,
80 	                size_t viewer_id, int sight_range, bool slowed,
81 	                const movetype::terrain_costs & costs,
82 	                const map_location & real_loc,
83 					const std::set<map_location>* known_units = nullptr,
84 	                size_t * enemy_count = nullptr, size_t * friend_count = nullptr,
85 	                move_unit_spectator * spectator = nullptr, bool instant = true);
86 	/// Clears shroud (and fog) around the provided location for @a view_team
87 	/// as if @a viewer was standing there.
88 	bool clear_unit(const map_location &view_loc,
89 	                const unit &viewer, team &view_team,
90 	                const std::set<map_location>* known_units = nullptr,
91 	                size_t * enemy_count = nullptr, size_t * friend_count = nullptr,
92 	                move_unit_spectator * spectator = nullptr, bool instant = true);
93 	/// Clears shroud (and fog) around the provided location for @a view_team
94 	/// as if @a viewer was standing there. Setting @a instant to false
95 	/// allows some drawing delays that are used to make movement look better.
clear_unit(const map_location & view_loc,const unit & viewer,team & view_team,bool instant)96 	bool clear_unit(const map_location &view_loc, const unit &viewer,
97 	                team &view_team, bool instant)
98 	{ return clear_unit(view_loc, viewer, view_team, nullptr, nullptr, nullptr, nullptr, instant); }
99 	/// Clears shroud (and fog) around the provided location for @a view_team
100 	/// as if @a viewer was standing there.
101 	bool clear_unit(const map_location &view_loc, team &view_team,
102 	                const clearer_info &viewer, bool instant);
103 	/// Clears shroud (and fog) around the provided location as if @a viewer
104 	/// was standing there.
105 	bool clear_unit(const map_location &view_loc, const unit &viewer,
106 	                bool can_delay = false, bool invalidate = true,
107 	                bool instant = true);
108 
109 	/// Clears shroud (and fog) at the provided location and its immediate neighbors.
110 	bool clear_dest(const map_location &dest, const unit &viewer);
111 
112 	/// Erases the record of sighted events from earlier fog/shroud clearing.
113 	void drop_events();
114 
115 	/// Fires the sighted events that were earlier recorded by fog/shroud clearing.
116 	game_events::pump_result_t fire_events();
117 
118 	/// The invalidations that should occur after invoking clear_unit().
119 	void invalidate_after_clear();
120 
121 private:
122 	/// A record of a sighting event.
123 	struct sight_data;
124 
125 	/// Causes this object's "jamming" map to be recalculated.
126 	void calculate_jamming(const team * new_team);
127 
128 	/// Clears shroud from a single location.
129 	bool clear_loc(team &tm, const map_location &loc, const map_location &view_loc,
130 	               const map_location &event_non_loc, size_t viewer_id,
131 	               bool check_units, size_t &enemy_count, size_t &friend_count,
132 	               move_unit_spectator * spectator = nullptr);
133 
134 	/// Convenience wrapper for adding sighting data to the sightings_ vector.
135 	inline void record_sighting(const unit & seen, const map_location & seen_loc,
136 	                            size_t sighter_id, const map_location & sighter_loc);
137 
138 private: // data
139 	std::map<map_location, int> jamming_;
140 	std::vector<sight_data> sightings_;
141 	/// Keeps track of the team associated with jamming_.
142 	const team * view_team_;
143 };
144 
145 
146 /// Returns the sides that cannot currently see @a target.
147 std::vector<int> get_sides_not_seeing(const unit & target);
148 /// Fires sighted events for the sides that can see @a target.
149 game_events::pump_result_t actor_sighted(const unit & target, const std::vector<int> * cache =  nullptr);
150 
151 
152 /// Function that recalculates the fog of war.
153 void recalculate_fog(int side);
154 
155 /// Function that will clear shroud (and fog) based on current unit positions.
156 bool clear_shroud(int side, bool reset_fog = false, bool fire_events = true);
157 
158 
159 }//namespace actions
160