1 /*
2  * Copyright (C) 2008-2020 by the Widelands Development Team
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  *
19  */
20 
21 #ifndef WL_AI_DEFAULTAI_H
22 #define WL_AI_DEFAULTAI_H
23 
24 #include <memory>
25 
26 #include "ai/ai_help_structs.h"
27 #include "ai/computer_player.h"
28 #include "base/i18n.h"
29 #include "base/log.h"
30 #include "economy/economy.h"
31 #include "logic/map_objects/immovable.h"
32 #include "logic/map_objects/tribes/ship.h"
33 #include "logic/map_objects/tribes/soldier.h"
34 #include "logic/map_objects/tribes/trainingsite.h"
35 
36 namespace Widelands {
37 struct Road;
38 }  // namespace Widelands
39 
40 /**
41  * Default Widelands Computer Player (defaultAI)
42  *
43  * The behaviour of defaultAI is controlled via \ref DefaultAI::think() and all
44  * functions called by \ref DefaultAI::think().
45  * At the moment defaultAI should be able to build up a basic infrastructure
46  * including food, mining and smithing infrastructure and a basic street net.
47  * It should be able to expand it's territory and to recruit some soldiers from
48  * the weapons made out of it's mined resources.
49  * It does only construct buildable and allowed (scenario mode) buildings.
50  * It behaves after preciousness_ of a ware, which can be defined in wares conf
51  * file. The higher the preciousness_, the more will defaultAI care for that ware
52  * and will try to build up an infrastructure to create that ware.
53  *
54  * \note Network safeness:
55  * - The current implementation does not care about network safe randomness, as
56  *   only the host is running the computer player code and sends it's player
57  *   commands to all other players. If this network behaviour is changed,
58  *   remember to change some time() in network save random functions.
59  */
60 // TODO(unknown): Improvements:
61 // - Improve different initialization types (Strong, Normal, Weak)
62 // - Improve update code - currently the whole buildable area owned by defaultAI
63 //   is rechecked after construction of a building or a road. Instead it would
64 //   be better to write down the changed coordinates and only check those and
65 //   surrounding ones. Same applies for other parts of the code:
66 //   e.g. check_militarysite checks the whole visible area for enemy area, but
67 //   it would already be enough, if it checks the outer circle ring.
68 // - improvements and speedups in the whole defaultAI code.
69 // - handling of trainingsites (if supply line is broken - send some soldiers
70 //   out, to have some more forces. Reincrease the number of soldiers that
71 //   should be trained if inputs_ get filled again.).
72 struct DefaultAI : ComputerPlayer {
73 
74 	DefaultAI(Widelands::Game&, const Widelands::PlayerNumber, Widelands::AiType);
75 	~DefaultAI() override;
76 	void think() override;
77 
78 	enum class WalkSearch : uint8_t { kAnyPlayer, kOtherPlayers, kEnemy };
79 	enum class WoodPolicy : uint8_t { kDismantleRangers, kStopRangers, kAllowRangers };
80 	enum class NewShip : uint8_t { kBuilt, kFoundOnLoad };
81 	enum class PerfEvaluation : uint8_t { kForConstruction, kForDismantle };
82 	enum class BasicEconomyBuildingStatus : uint8_t { kEncouraged, kDiscouraged, kNeutral, kNone };
83 
84 	enum class SoldiersStatus : uint8_t { kFull = 0, kEnough = 1, kShortage = 3, kBadShortage = 6 };
85 
86 	enum class WareWorker : uint8_t { kWare, kWorker };
87 
88 	/// Implementation for Strong
89 	struct NormalImpl : public ComputerPlayer::Implementation {
NormalImplDefaultAI::NormalImpl90 		NormalImpl()
91 		   : Implementation(
92 		        "normal",
93 		        /** TRANSLATORS: This is the name of an AI used in the game setup screens */
94 		        _("Normal AI"),
95 		        "images/ai/ai_normal.png",
96 		        Implementation::Type::kDefault) {
97 		}
instantiateDefaultAI::NormalImpl98 		ComputerPlayer* instantiate(Widelands::Game& game,
99 		                            Widelands::PlayerNumber const p) const override {
100 			return new DefaultAI(game, p, Widelands::AiType::kNormal);
101 		}
102 	};
103 
104 	struct WeakImpl : public ComputerPlayer::Implementation {
WeakImplDefaultAI::WeakImpl105 		WeakImpl()
106 		   : Implementation(
107 		        "weak",
108 		        /** TRANSLATORS: This is the name of an AI used in the game setup screens */
109 		        _("Weak AI"),
110 		        "images/ai/ai_weak.png",
111 		        Implementation::Type::kDefault) {
112 		}
instantiateDefaultAI::WeakImpl113 		ComputerPlayer* instantiate(Widelands::Game& game,
114 		                            Widelands::PlayerNumber const p) const override {
115 			return new DefaultAI(game, p, Widelands::AiType::kWeak);
116 		}
117 	};
118 
119 	struct VeryWeakImpl : public ComputerPlayer::Implementation {
VeryWeakImplDefaultAI::VeryWeakImpl120 		VeryWeakImpl()
121 		   : Implementation(
122 		        "very_weak",
123 		        /** TRANSLATORS: This is the name of an AI used in the game setup screens */
124 		        _("Very Weak AI"),
125 		        "images/ai/ai_very_weak.png",
126 		        Implementation::Type::kDefault) {
127 		}
instantiateDefaultAI::VeryWeakImpl128 		ComputerPlayer* instantiate(Widelands::Game& game,
129 		                            Widelands::PlayerNumber const p) const override {
130 			return new DefaultAI(game, p, Widelands::AiType::kVeryWeak);
131 		}
132 	};
133 
134 	static NormalImpl normal_impl;
135 	static WeakImpl weak_impl;
136 	static VeryWeakImpl very_weak_impl;
137 
138 private:
139 	static constexpr int8_t kUncalculated = -1;
140 	static constexpr uint8_t kFalse = 0;
141 	static constexpr uint8_t kTrue = 1;
142 
143 	static constexpr bool kAbsValue = true;
144 	static constexpr int32_t kSpotsTooLittle = 15;
145 	static constexpr int kManagementUpdateInterval = 10 * 60 * 1000;
146 	static constexpr int kStatUpdateInterval = 60 * 1000;
147 	static constexpr int kFlagWarehouseUpdInterval = 15 * 1000;
148 
149 	// For vision and scheduling
150 	static constexpr uint32_t kNever = std::numeric_limits<uint32_t>::max();
151 
152 	// common for defaultai.cc and defaultai_seafaring.cc
153 	static constexpr uint32_t kExpeditionMinDuration = 60 * 60 * 1000;
154 	static constexpr uint32_t kExpeditionMaxDuration = 210 * 60 * 1000;
155 	static constexpr Widelands::Serial kNoShip = Widelands::kInvalidSerial;
156 	static constexpr int kShipCheckInterval = 5 * 1000;
157 
158 	// used by defaultai_warfare.cc
159 	// duration of military campaign
160 	static constexpr int kCampaignDuration = 15 * 60 * 1000;
161 	static constexpr int kTrainingSitesCheckInterval = 15 * 1000;
162 
163 	// Variables of default AI
164 	Widelands::AiType type_;
165 	Widelands::Player* player_;
166 	Widelands::TribeDescr const* tribe_;
167 
168 	// This points to persistent data stored in Player object
169 	Widelands::Player::AiPersistentState* persistent_data;
170 
171 	void late_initialization();
172 
173 	void update_all_buildable_fields(uint32_t);
174 	void update_all_mineable_fields(uint32_t);
175 	void update_all_not_buildable_fields();
176 	void update_buildable_field(Widelands::BuildableField&);
177 	void update_mineable_field(Widelands::MineableField&);
178 	void update_productionsite_stats();
179 
180 	// for production sites
181 	Widelands::BuildingNecessity
182 	check_building_necessity(Widelands::BuildingObserver& bo, PerfEvaluation purpose, uint32_t);
183 	Widelands::BuildingNecessity check_warehouse_necessity(Widelands::BuildingObserver&,
184 	                                                       uint32_t gametime);
185 	void sort_task_pool();
186 	void sort_by_priority();
187 	void set_taskpool_task_time(uint32_t, Widelands::SchedulerTaskId);
188 	uint32_t get_taskpool_task_time(Widelands::SchedulerTaskId);
189 
190 	bool construct_building(uint32_t);
191 
192 	// all road management is invoked by function improve_roads()
193 	// if needed it calls create_shortcut_road() with a flag from which
194 	// new road should be considered (or is needed)
195 	bool improve_roads(uint32_t);
196 	bool
197 	create_shortcut_road(const Widelands::Flag&, uint16_t maxcheckradius, const uint32_t gametime);
198 	// trying to identify roads that might be removed
199 	bool dispensable_road_test(const Widelands::Road&);
200 	bool dismantle_dead_ends();
201 	void collect_nearflags(std::map<uint32_t, Widelands::NearFlag>&,
202 	                       const Widelands::Flag&,
203 	                       const uint16_t);
204 	// calculating distances from local warehouse to flags
205 	void check_flag_distances(uint32_t);
206 	Widelands::FlagWarehouseDistances flag_warehouse_distance;
207 
208 	bool check_economies();
209 	bool check_productionsites(uint32_t);
210 	bool check_mines_(uint32_t);
211 
212 	void print_stats(uint32_t);
213 
214 	uint32_t
215 	get_stocklevel(Widelands::BuildingObserver&, uint32_t, WareWorker = WareWorker::kWare) const;
216 	uint32_t
217 	   calculate_stocklevel(Widelands::DescriptionIndex,
218 	                        WareWorker = WareWorker::kWare) const;  // count all direct outputs_
219 
220 	void review_wares_targets(uint32_t);
221 
222 	void update_player_stat(uint32_t);
223 
224 	// sometimes scanning an area in radius gives inappropriate results, so this is to verify that
225 	// other player is accessible
226 	// via walking
227 	bool other_player_accessible(uint32_t max_distance,
228 	                             uint32_t* tested_fields,
229 	                             uint16_t* mineable_fields_count,
230 	                             const Widelands::Coords& starting_spot,
231 	                             const WalkSearch& type);
232 
233 	int32_t recalc_with_border_range(const Widelands::BuildableField&, int32_t);
234 
235 	void consider_productionsite_influence(Widelands::BuildableField&,
236 	                                       Widelands::Coords,
237 	                                       const Widelands::BuildingObserver&);
238 
239 	Widelands::EconomyObserver* get_economy_observer(Widelands::Economy&);
240 	uint8_t count_buildings_with_attribute(Widelands::BuildingAttribute);
241 	uint32_t count_productionsites_without_buildings();
242 	Widelands::BuildingObserver& get_building_observer(char const*);
243 	bool has_building_observer(char const*);
244 	Widelands::BuildingObserver& get_building_observer(Widelands::BuildingAttribute);
245 	Widelands::BuildingObserver& get_building_observer(Widelands::DescriptionIndex);
246 
247 	void gain_immovable(Widelands::PlayerImmovable&, bool found_on_load = false);
248 	void lose_immovable(const Widelands::PlayerImmovable&);
249 	void gain_building(Widelands::Building&, bool found_on_load);
250 	void lose_building(const Widelands::Building&);
251 	void out_of_resources_site(const Widelands::ProductionSite&);
252 	bool check_supply(const Widelands::BuildingObserver&);
253 	bool set_inputs_to_zero(const Widelands::ProductionSiteObserver&);
254 	void set_inputs_to_max(const Widelands::ProductionSiteObserver&);
255 	void stop_site(const Widelands::ProductionSiteObserver&);
256 	void initiate_dismantling(Widelands::ProductionSiteObserver&, uint32_t);
257 
258 	// Checks whether first value is in range, or lesser then...
259 	template <typename T> void check_range(const T, const T, const T, const char*);
260 	template <typename T> void check_range(const T, const T, const char*);
261 
262 	// Remove a member from std::deque
263 	template <typename T> bool remove_from_dqueue(std::deque<T const*>&, T const*);
264 
265 	// Functions used for seafaring / defaultai_seafaring.cc
266 	Widelands::IslandExploreDirection randomExploreDirection();
267 	void gain_ship(Widelands::Ship&, NewShip);
268 	void check_ship_in_expedition(Widelands::ShipObserver&, uint32_t);
269 	void expedition_management(Widelands::ShipObserver&);
270 	// considering trees, rocks, mines, water, fish for candidate for colonization (new port)
271 	uint8_t spot_scoring(Widelands::Coords candidate_spot);
272 	bool marine_main_decisions(uint32_t);
273 	bool check_ships(uint32_t);
274 	bool attempt_escape(Widelands::ShipObserver& so);
275 
276 	// finding and owner
277 	Widelands::PlayerNumber get_land_owner(const Widelands::Map&, uint32_t) const;
278 
279 	// Functions used for war and training stuff / defaultai_warfare.cc
280 	bool check_militarysites(uint32_t);
281 	bool check_enemy_sites(uint32_t);
282 	void count_military_vacant_positions();
283 	bool check_trainingsites(uint32_t);
284 	// return single number of strength of vector of soldiers
285 	int32_t calculate_strength(const std::vector<Widelands::Soldier*>&);
286 	// for militarysites (overloading the function)
287 	Widelands::BuildingNecessity check_building_necessity(Widelands::BuildingObserver&, uint32_t);
288 	void soldier_trained(const Widelands::TrainingSite&);
289 	bool critical_mine_unoccupied(uint32_t);
290 
291 	SoldiersStatus soldier_status_;
292 	int32_t vacant_mil_positions_average_;
293 	uint16_t attackers_count_;
294 	Widelands::EventTimeQueue soldier_trained_log;
295 	Widelands::EventTimeQueue soldier_attacks_log;
296 
297 	// used by AI scheduler
298 	uint32_t sched_stat_[20] = {0};
299 	uint32_t next_ai_think_;
300 	// this is helping counter to track how many scheduler tasks are too delayed
301 	// the purpose is to print out a warning that the game is pacing too fast
302 	int32_t scheduler_delay_counter_;
303 
304 	WoodPolicy wood_policy_;
305 	uint16_t trees_nearby_treshold_;
306 
307 	std::vector<Widelands::BuildingObserver> buildings_;
308 	std::deque<Widelands::FCoords> unusable_fields;
309 	std::deque<Widelands::BuildableField*> buildable_fields;
310 	Widelands::BlockedFields blocked_fields;
311 	std::unordered_set<uint32_t> ports_vicinity;
312 	Widelands::PlayersStrengths player_statistics;
313 	Widelands::ManagementData management_data;
314 	Widelands::ExpansionType expansion_type;
315 	std::deque<Widelands::MineableField*> mineable_fields;
316 	std::deque<Widelands::Flag const*> new_flags;
317 	std::deque<Widelands::Road const*> roads;
318 	std::deque<Widelands::EconomyObserver*> economies;
319 	std::deque<Widelands::ProductionSiteObserver> productionsites;
320 	std::deque<Widelands::ProductionSiteObserver> mines_;
321 	std::deque<Widelands::MilitarySiteObserver> militarysites;
322 	std::deque<Widelands::WarehouseSiteObserver> warehousesites;
323 	std::deque<Widelands::TrainingSiteObserver> trainingsites;
324 	std::deque<Widelands::ShipObserver> allships;
325 	std::vector<Widelands::WareObserver> wares;
326 	// This is a vector that is filled up on initiatlization
327 	// and no items are added/removed afterwards
328 	std::vector<Widelands::SchedulerTask> taskPool;
329 	std::map<uint32_t, Widelands::EnemySiteObserver> enemy_sites;
330 	std::set<uint32_t> enemy_warehouses;
331 	// it will map mined material to observer
332 	std::map<int32_t, Widelands::MineTypesObserver> mines_per_type;
333 	std::vector<uint32_t> spots_avail;
334 	Widelands::MineFieldsObserver mine_fields_stat;
335 
336 	// used for statistics of buildings
337 	uint32_t numof_psites_in_constr;
338 	uint32_t num_ports;
339 	uint16_t numof_warehouses_;
340 	uint16_t numof_warehouses_in_const_;
341 	uint32_t mines_in_constr() const;
342 	uint32_t mines_built() const;
343 	std::map<int32_t, Widelands::MilitarySiteSizeObserver> msites_per_size;
344 	// for militarysites
345 	uint32_t msites_in_constr() const;
346 	uint32_t msites_built() const;
347 	uint32_t military_last_dismantle_;
348 	uint32_t military_last_build_;  // sometimes expansions just stops, this is time of last military
349 	                                // building built
350 	uint32_t time_of_last_construction_;
351 	uint32_t next_mine_construction_due_;
352 	uint16_t fishers_count_;
353 	uint16_t bakeries_count_;
354 
355 	uint32_t first_iron_mine_built;
356 
357 	// for training sites per type
358 	int16_t ts_finished_count_;
359 	int16_t ts_in_const_count_;
360 	int16_t ts_without_trainers_;
361 
362 	// for roads
363 	uint32_t last_road_dismantled_;  // uses to prevent too frequent road dismantling
364 	bool dead_ends_check_;           // Do we need to check and dismantle dead ends?
365 
366 	uint32_t enemy_last_seen_;
367 	uint32_t last_attack_time_;
368 	// check ms in this interval - will auto-adjust
369 	uint32_t enemysites_check_delay_;
370 
371 	int32_t spots_;  // sum of buildable fields
372 
373 	int16_t productionsites_ratio_;
374 
375 	bool resource_necessity_water_needed_;  // unless atlanteans
376 
377 	// This stores highest priority for new buildings except for militarysites
378 	int32_t highest_nonmil_prio_;
379 
380 	// if the basic economy is not established, there must be a non-empty list of remaining basic
381 	// buildings
382 	bool basic_economy_established;
383 
384 	// id of iron as resource to identify iron mines in mines_per_type map
385 	int32_t iron_resource_id = Widelands::INVALID_INDEX;
386 
387 	// this is a bunch of patterns that have to identify weapons and armors for input queues of
388 	// trainingsites
389 	std::vector<std::string> const armors_and_weapons = {
390 	   "ax", "armor", "helm", "lance", "trident", "tabard", "shield", "mask", "spear"};
391 
392 	// seafaring related
393 	enum { kReprioritize, kStopShipyard, kStapShipyard };
394 	static uint32_t last_seafaring_check_;
395 	// False by default, until Map::allows_seafaring() is true
396 	static bool map_allows_seafaring_;
397 	uint32_t expedition_ship_;
398 	uint32_t expedition_max_duration;
399 	std::vector<int16_t> marine_task_queue;
400 	std::unordered_set<uint32_t> expedition_visited_spots;
401 
402 	std::vector<std::vector<int16_t>> AI_military_matrix;
403 	std::vector<int16_t> AI_military_numbers;
404 
405 	uint16_t buil_material_mines_count = 0;
406 
407 	bool ai_training_mode_ = false;
408 
409 	// Notification subscribers
410 	std::unique_ptr<Notifications::Subscriber<Widelands::NoteFieldPossession>>
411 	   field_possession_subscriber_;
412 	std::unique_ptr<Notifications::Subscriber<Widelands::NoteImmovable>> immovable_subscriber_;
413 	std::unique_ptr<Notifications::Subscriber<Widelands::NoteProductionSiteOutOfResources>>
414 	   outofresource_subscriber_;
415 	std::unique_ptr<Notifications::Subscriber<Widelands::NoteTrainingSiteSoldierTrained>>
416 	   soldiertrained_subscriber_;
417 	std::unique_ptr<Notifications::Subscriber<Widelands::NoteShip>> shipnotes_subscriber_;
418 };
419 
420 #endif  // end of include guard: WL_AI_DEFAULTAI_H
421