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