1 /* 2 * Copyright (C) 2009-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 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 * 18 */ 19 20 #ifndef WL_AI_AI_HELP_STRUCTS_H 21 #define WL_AI_AI_HELP_STRUCTS_H 22 23 #include <bitset> 24 25 #include "ai/ai_hints.h" 26 #include "economy/flag.h" 27 #include "economy/road.h" 28 #include "logic/ai_dna_handler.h" 29 #include "logic/game.h" 30 #include "logic/map.h" 31 #include "logic/map_objects/checkstep.h" 32 #include "logic/map_objects/findnode.h" 33 #include "logic/map_objects/map_object.h" 34 #include "logic/map_objects/tribes/ship.h" 35 #include "logic/map_objects/world/terrain_description.h" 36 #include "logic/map_objects/world/world.h" 37 #include "logic/player.h" 38 39 namespace Widelands { 40 41 class ProductionSite; 42 class MilitarySite; 43 44 enum class ExtendedBool : uint8_t { kUnset, kTrue, kFalse }; 45 46 enum class MutatingIntensity : uint8_t { kNo, kNormal, kAgressive }; 47 48 enum class BuildingNecessity : uint8_t { 49 kForced, 50 kNeeded, 51 kNotNeeded, 52 kUnset, 53 kNotBuildable, 54 kAllowed, 55 kNeededPending, 56 kForbidden 57 }; 58 59 // A building type can have no, one or multiple of these attributes 60 enum class BuildingAttribute : uint8_t { 61 kRanger, 62 kBuildable, 63 kLumberjack, 64 kPort, 65 kNeedsRocks, 66 kWell, 67 kNeedsCoast, 68 kHunter, 69 kFisher, 70 kShipyard, 71 kBarracks, 72 kSpaceConsumer, 73 kRecruitment, 74 kBuildingMatProducer, 75 kUpgradeSubstitutes, 76 kUpgradeExtends, 77 // TODO(Nordfriese): Someone should update the AI code to handle buildings that need waterways 78 // enabled 79 kNeedsSeafaring, 80 kSupportsSeafaring, 81 kSupportingProducer, 82 kNeedsBerry, 83 }; 84 85 enum class ExpansionMode : uint8_t { kResources = 0, kSpace = 1, kEconomy = 2, kBoth = 3 }; 86 87 enum class AiModeBuildings : uint8_t { kAnotherAllowed, kOnLimit, kLimitExceeded }; 88 89 enum class SchedulerTaskId : uint8_t { 90 kBbuildableFieldsCheck, 91 kMineableFieldsCheck, 92 kRoadCheck, 93 kUnbuildableFCheck, 94 kCheckEconomies, 95 kProductionsitesStats, 96 kConstructBuilding, 97 kCheckProductionsites, 98 kCheckShips, 99 KMarineDecisions, 100 kCheckMines, 101 kWareReview, 102 kPrintStats, 103 kCheckMilitarysites, 104 kCheckTrainingsites, 105 kCountMilitaryVacant, 106 kCheckEnemySites, 107 kManagementUpdate, 108 kUpdateStats, 109 kWarehouseFlagDist, 110 kUnset 111 }; 112 113 enum class DnaParent : uint8_t { kPrimary, kSecondary }; 114 115 // This is a simplification of a curve, to avoid repeated calculation 116 const std::vector<std::vector<int8_t>> neuron_curves = { 117 {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100}, 118 {0, 0, 1, 2, 4, 6, 9, 12, 16, 20, 25, 30, 36, 42, 49, 56, 64, 72, 81, 90, 100}, 119 {0, 17, 25, 32, 38, 44, 49, 53, 58, 62, 66, 70, 74, 78, 81, 84, 88, 91, 94, 97, 100}, 120 }; 121 122 // TODO(tiborb): this should be replaced by command line switch 123 constexpr int kFNeuronBitSize = 32; 124 constexpr int kMutationRatePosition = 42; 125 // This is expiration time for distance from a flag to nearest warehouse 126 constexpr int kFlagDistanceExpirationPeriod = 120 * 1000; 127 // If the distance of flag-warehouse was not updated for this time, we presume that the flag 128 // does not exist anymore and remove it 129 constexpr int kOldFlagRemoveTime = 5 * 60 * 1000; 130 131 constexpr uint32_t kNever = std::numeric_limits<uint32_t>::max(); 132 133 constexpr uint32_t kNoField = std::numeric_limits<uint32_t>::max(); 134 135 constexpr uint32_t kOneMinute = 60 * 1000; 136 137 constexpr uint16_t kFarButReachable = 1000; 138 139 struct CheckStepRoadAI { 140 CheckStepRoadAI(Player* const pl, uint8_t const mc, bool const oe); 141 142 bool allowed(const Map&, FCoords start, FCoords end, int32_t dir, CheckStep::StepId) const; 143 bool reachable_dest(const Map&, const FCoords& dest) const; 144 145 Player* player; 146 uint8_t movecaps; 147 bool open_end; 148 }; 149 150 // Used to walk ower own territory, on fields that are walkable (or as given by mc) 151 // plus one step more to a field with own immovable. So that also flags and buildings are 152 // included in resulting list 153 struct CheckStepOwnTerritory { 154 CheckStepOwnTerritory(Player* const pl, uint8_t const mc, bool const oe); 155 156 bool allowed(const Map&, FCoords start, FCoords end, int32_t dir, CheckStep::StepId) const; 157 bool reachable_dest(const Map&, const FCoords& dest) const; 158 159 Player* player; 160 uint8_t movecaps; 161 bool open_end; 162 }; 163 164 // We are looking for fields we can walk on 165 // and owned by hostile player. 166 struct FindNodeEnemy { 167 FindNodeEnemy(Player* p, Game& g); 168 169 bool accept(const EditorGameBase&, const FCoords& fc) const; 170 171 Player* player; 172 Game& game; 173 }; 174 175 // We are looking for buildings owned by hostile player 176 // (sometimes there is a enemy's teritorry without buildings, and 177 // this confuses the AI) 178 179 struct FindNodeEnemiesBuilding { 180 FindNodeEnemiesBuilding(Player* p, Game& g); 181 182 bool accept(const EditorGameBase&, const FCoords& fc) const; 183 184 Player* player; 185 Game& game; 186 }; 187 188 // We need to count walkable fields owned by enemy 189 struct FindEnemyNodeWalkable { 190 FindEnemyNodeWalkable(Player* p, Game& g); 191 192 bool accept(const EditorGameBase&, const FCoords& fc) const; 193 194 Player* player; 195 Game& game; 196 }; 197 198 // Sometimes we need to know how many nodes our allies owns 199 struct FindNodeAllyOwned { 200 FindNodeAllyOwned(Player* p, Game& g, PlayerNumber n); 201 202 bool accept(const EditorGameBase&, const FCoords& fc) const; 203 204 Player* player; 205 Game& game; 206 PlayerNumber player_number; 207 }; 208 209 // When looking for unowned terrain to acquire, we must 210 // pay speciall attention to fields where mines can be built. 211 // Fields should be completely unowned 212 struct FindNodeUnownedMineable { 213 FindNodeUnownedMineable(Player* p, Game& g, int32_t t = INVALID_INDEX); 214 215 bool accept(const EditorGameBase&, const FCoords& fc) const; 216 217 Player* player; 218 Game& game; 219 int32_t ore_type; 220 }; 221 222 // When looking for unowned terrain to acquire, we must 223 // consider if any buildings (incl. mines) can be built on unowned land. 224 struct FindNodeUnownedBuildable { 225 FindNodeUnownedBuildable(Player* p, Game& g); 226 227 bool accept(const EditorGameBase&, const FCoords& fc) const; 228 229 Player* player; 230 Game& game; 231 }; 232 233 // Unowned but walkable fields nearby 234 struct FindNodeUnownedWalkable { 235 FindNodeUnownedWalkable(Player* p, Game& g); 236 237 bool accept(const EditorGameBase&, const FCoords& fc) const; 238 239 Player* player; 240 Game& game; 241 }; 242 243 // Looking only for mines-capable fields nearby 244 // of specific type 245 struct FindNodeMineable { 246 FindNodeMineable(Game& g, DescriptionIndex r); 247 248 bool accept(const EditorGameBase&, const FCoords& fc) const; 249 250 Game& game; 251 int32_t res; 252 }; 253 254 // Fishers and fishbreeders must be built near water 255 struct FindNodeWater { 256 explicit FindNodeWater(const World& world); 257 258 bool accept(const EditorGameBase&, const FCoords& coord) const; 259 260 private: 261 const World& world_; 262 }; 263 264 // This is to be used for shipyards to make sure the water is wide enough 265 // Open water is a field where all 6 adjacent triangles are water 266 struct FindNodeOpenWater { 267 // 'world' is unused, but we need to fit the template. FindNodeOpenWaterFindNodeOpenWater268 explicit FindNodeOpenWater(const World& /* world */) { 269 } 270 271 bool accept(const EditorGameBase&, const FCoords& coord) const; 272 }; 273 274 struct FindNodeWithFlagOrRoad { 275 bool accept(const EditorGameBase&, FCoords) const; 276 }; 277 278 // Accepts any field 279 struct FindNodeAcceptAll { acceptFindNodeAcceptAll280 bool accept(const EditorGameBase&, FCoords) const { 281 return true; 282 } 283 }; 284 285 struct NearFlag { 286 // ordering nearflags by biggest reduction 287 struct CompareShortening { operatorNearFlag::CompareShortening288 bool operator()(const NearFlag& a, const NearFlag& b) const { 289 return a.current_road_distance > b.current_road_distance; 290 } 291 }; 292 NearFlag(); 293 NearFlag(const Flag* f, int32_t const c); 294 295 bool operator<(const NearFlag& f) const { 296 return current_road_distance > f.current_road_distance; 297 } 298 299 bool operator==(Flag const* const f) const { 300 return flag == f; 301 } 302 303 Flag const* flag; 304 bool to_be_checked; 305 uint32_t current_road_distance; 306 }; 307 308 // FIFO like structure for pairs <gametime,id>, where id is optional 309 // used to count events within a time frame - duration_ (older ones are 310 // stripped with strip_old function) 311 struct EventTimeQueue { 312 EventTimeQueue(); 313 314 void push(uint32_t, uint32_t = std::numeric_limits<uint32_t>::max()); 315 uint32_t count(uint32_t, uint32_t = std::numeric_limits<uint32_t>::max()); 316 void strip_old(uint32_t); 317 318 private: 319 const uint32_t duration_ = 20 * 60 * 1000; 320 // FIFO container where newest goes to the front 321 std::deque<std::pair<uint32_t, uint32_t>> queue; 322 }; 323 324 struct WalkableSpot { 325 Coords coords; 326 bool has_flag; 327 328 int32_t cost; 329 void* eco; 330 331 int16_t from; 332 int16_t neighbours[6]; 333 }; 334 335 struct BuildableField { 336 explicit BuildableField(const Widelands::FCoords& fc); 337 338 Widelands::FCoords coords; 339 340 uint32_t field_info_expiration; 341 342 bool preferred; 343 bool enemy_nearby; 344 bool enemy_accessible_; 345 346 bool enemy_wh_nearby; 347 uint16_t unowned_land_nearby; 348 uint16_t enemy_owned_land_nearby; 349 uint16_t unowned_buildable_spots_nearby; 350 uint16_t unowned_portspace_vicinity_nearby; 351 uint16_t nearest_buildable_spot_nearby; 352 // to identify that field is too close to border and no production building should be built there 353 bool near_border; 354 uint16_t unowned_mines_spots_nearby; 355 uint16_t unowned_iron_mines_nearby; 356 uint8_t trees_nearby; 357 uint8_t bushes_nearby; 358 uint8_t rocks_nearby; 359 int16_t water_nearby; 360 int16_t open_water_nearby; 361 int16_t distant_water; 362 int16_t fish_nearby; 363 int8_t critters_nearby; 364 ResourceAmount ground_water; // used by wells 365 uint8_t space_consumers_nearby; 366 uint8_t rangers_nearby; 367 // to manage the military better following variables exists: 368 // capacity of nearby buildings: 369 int16_t area_military_capacity; 370 // distance to near buldings: 371 int16_t military_loneliness; 372 // count of military buildings in construction 373 // when making decision on new mulitary buildings it considers also 374 // unowned fields and mines, but this information is not quite correct as there 375 // are construction sites that will change this once they are built 376 int16_t military_in_constr_nearby; 377 // actual count of soldiers in nearby buldings 378 int16_t own_military_presence; 379 int16_t enemy_military_presence; 380 int16_t enemy_military_sites; // Including unfinished 381 int16_t ally_military_presence; 382 // stationed (manned) military buildings nearby 383 int16_t military_stationed; 384 // unconnected buildings nearby 385 bool unconnected_nearby; 386 int16_t military_unstationed; 387 int16_t own_non_military_nearby; 388 bool defense_msite_allowed; 389 Widelands::ExtendedBool is_portspace; 390 bool port_nearby; // to increase priority if a port is nearby, 391 // especially for new colonies 392 Widelands::ExtendedBool portspace_nearby; // special fields intended for ports 393 int32_t max_buildcap_nearby; 394 // It is not necessary to check resources (stones, fish...) too frequently as they do not change 395 // fast. This stores the time of the last check. 396 uint32_t last_resources_check_time; 397 int32_t military_score_; 398 bool inland; 399 uint16_t local_soldier_capacity; 400 bool is_militarysite; 401 402 std::vector<uint8_t> consumers_nearby; 403 std::vector<uint8_t> producers_nearby; 404 std::vector<uint8_t> collecting_producers_nearby; 405 // and for rangers, fishbreeders: 406 std::vector<uint8_t> supporters_nearby; 407 }; 408 409 struct MineableField { 410 explicit MineableField(const Widelands::FCoords& fc); 411 412 Widelands::FCoords coords; 413 uint32_t field_info_expiration; 414 bool preferred; 415 int32_t mines_nearby; 416 // this is to provide that a mine is not built on the edge of mine area 417 int32_t same_mine_fields_nearby; 418 }; 419 420 struct EconomyObserver { 421 explicit EconomyObserver(Widelands::Economy& e); 422 423 Widelands::Economy& economy; 424 std::deque<Widelands::Flag const*> flags; 425 uint32_t dismantle_grace_time; 426 uint32_t fields_block_last_time; 427 }; 428 429 struct BuildingObserver { 430 431 enum class Type { 432 kBoring, 433 kConstructionsite, 434 kProductionsite, 435 kMilitarysite, 436 kWarehouse, 437 kTrainingsite, 438 kMine 439 }; 440 441 int32_t total_count() const; 442 Widelands::AiModeBuildings aimode_limit_status() const; 443 bool buildable(Widelands::Player& p); 444 445 // Convenience functions for is_what 446 bool is(BuildingAttribute) const; 447 void set_is(BuildingAttribute); 448 void unset_is(BuildingAttribute); 449 450 // Building collects a ware from the map 451 bool has_collected_map_resource() const; 452 void set_collected_map_resource(const TribeDescr& tribe, const std::string& ware_name); 453 DescriptionIndex get_collected_map_resource() const; 454 455 char const* name; 456 Widelands::DescriptionIndex id; 457 Widelands::BuildingDescr const* desc; 458 459 Type type; 460 461 Widelands::BuildingNecessity new_building; 462 uint32_t new_building_overdue; 463 int32_t primary_priority; 464 465 bool expansion_type; // military building used that can be used to control area 466 bool fighting_type; // military building built near enemies 467 bool mountain_conqueror; // military building built near mountains 468 uint32_t prohibited_till; // do not build before (ms) 469 uint32_t forced_after; // do not wait until ware is needed 470 uint8_t max_trainingsites_proportion; 471 472 uint16_t unconnected_count; // to any warehouse (count of such buildings) 473 474 DescriptionIndex mines; // type of resource it mines_ 475 uint16_t mines_percent; // % of res it can mine 476 uint32_t current_stats; 477 478 uint32_t basic_amount; // basic amount for basic economy as defined in init.lua 479 480 std::vector<Widelands::DescriptionIndex> inputs; 481 std::vector<Widelands::DescriptionIndex> ware_outputs; 482 std::vector<Widelands::DescriptionIndex> positions; 483 std::vector<Widelands::DescriptionIndex> critical_building_material; 484 485 // It seems that fish and meat are subsitutes (for trainingsites), so 486 // when testing if a trainingsite is supplied enough 487 // we count the wares together 488 std::unordered_set<Widelands::DescriptionIndex> substitute_inputs; 489 int32_t substitutes_count; 490 491 std::set<DescriptionIndex> production_hints; 492 493 bool requires_supporters; 494 495 // information needed for decision on new building construction 496 int16_t initial_preciousness; 497 int16_t max_preciousness; 498 int16_t max_needed_preciousness; 499 int32_t cnt_built; 500 int32_t cnt_under_construction; 501 int32_t cnt_target; // number of buildings as target 502 int32_t cnt_limit_by_aimode; // limit imposed by weak or normal AI mode 503 504 int32_t cnt_upgrade_pending; // number of buildings that are to be upgraded 505 506 // used to track amount of wares produced by building 507 uint32_t stocklevel_count; 508 uint32_t stocklevel_time; // time when stocklevel_ was last time recalculated 509 uint32_t last_dismantle_time; 510 uint32_t construction_decision_time; 511 uint32_t last_building_built; 512 513 uint32_t unoccupied_count; 514 515 bool build_material_shortage; 516 517 private: 518 DescriptionIndex collected_map_resource; 519 std::set<BuildingAttribute> is_what; 520 }; 521 522 struct ProductionSiteObserver { 523 Widelands::ProductionSite* site = nullptr; 524 uint32_t built_time = 0U; 525 uint32_t unoccupied_till = 0U; 526 uint32_t no_resources_since = kNever; 527 bool upgrade_pending = false; 528 uint32_t dismantle_pending_since = kNever; 529 BuildingObserver* bo = nullptr; 530 }; 531 532 struct MilitarySiteObserver { 533 Widelands::MilitarySite* site; 534 BuildingObserver* bo; 535 uint16_t understaffed; 536 uint32_t last_change; // to prevent switching the occupancy policy too fast 537 uint32_t built_time; 538 }; 539 540 struct TrainingSiteObserver { 541 Widelands::TrainingSite* site; 542 BuildingObserver* bo; 543 }; 544 545 struct WarehouseSiteObserver { 546 547 Widelands::Warehouse* site; 548 BuildingObserver* bo; 549 uint32_t flag_distances_last_update; 550 }; 551 552 struct ShipObserver { 553 Widelands::Ship* ship; 554 bool waiting_for_command_ = false; 555 uint32_t last_command_time = 0; 556 bool escape_mode = false; 557 558 // direction by which the ship circumvents an island 559 // this is the last circle-island command's direction 560 Widelands::IslandExploreDirection island_circ_direction = 561 Widelands::IslandExploreDirection::kClockwise; 562 }; 563 564 struct WareObserver { 565 bool refined_build_material = false; 566 uint8_t preciousness; 567 }; 568 569 // Computer player does not get notification messages about enemy militarysites 570 // and warehouses, so following is collected based on observation 571 // It is conventient to have some information preserved, like nearby minefields, 572 // when it was attacked, whether it is warehouse and so on 573 // Also AI test more such targets when considering attack and calculated score is 574 // is stored in the observer 575 struct EnemySiteObserver { 576 bool is_warehouse = false; 577 int32_t attack_soldiers_strength = 0; 578 int32_t attack_soldiers_competency = 0; 579 int32_t defenders_strength = 0; 580 uint8_t stationed_soldiers = 0U; 581 uint32_t last_time_seen = 0U; 582 uint32_t last_tested = 0U; 583 int16_t score = 0; 584 Widelands::ExtendedBool mines_nearby = Widelands::ExtendedBool::kUnset; 585 uint32_t last_time_attacked = 0U; 586 uint32_t attack_counter = 0U; 587 uint16_t enemy_military_presence_in_region = 0U; 588 uint16_t enemy_military_sites_in_region = 0U; 589 }; 590 591 // as all mines have 3 levels, AI does not know total count of mines per mined material 592 // so this observer will be used for this 593 struct MineTypesObserver { 594 MineTypesObserver(); 595 596 uint16_t total_count() const; 597 598 uint16_t in_construction; 599 uint16_t finished; 600 bool is_critical; 601 uint16_t unoccupied; 602 }; 603 604 // This struct contains count of mineable fields grouped by ore/resource type 605 struct MineFieldsObserver { 606 607 void zero(); 608 void add(Widelands::DescriptionIndex); 609 void add_critical_ore(Widelands::DescriptionIndex); 610 bool has_critical_ore_fields(); 611 uint16_t get(Widelands::DescriptionIndex); 612 uint8_t count_types(); 613 614 private: 615 // This is the central information of the struct: a pair of resource and count of fields 616 std::map<Widelands::DescriptionIndex, uint16_t> stat; 617 std::set<Widelands::DescriptionIndex> critical_ores; 618 }; 619 620 constexpr int kNeuronWeightLimit = 100; 621 constexpr size_t kNeuronMaxPosition = 20; 622 constexpr size_t kSecondParentProbability = 50; 623 624 // A bunch of parameters used for trainig AI (for calculation of fitness function result) 625 constexpr int16_t kCurrentLandDivider = 2; 626 constexpr int16_t kLandDeltaMultiplier = 1; 627 constexpr int16_t kBonus = 1000; 628 constexpr int16_t kAttackersMultiplier = 1; 629 constexpr int16_t kAttackBonus = 100; 630 constexpr int16_t kTrainedSoldiersScore = 250; 631 constexpr int16_t kConqueredWhBonus = 300; 632 constexpr int16_t kStrengthMultiplier = 30; 633 constexpr int16_t kPSitesRatioMultiplier = 1; 634 635 struct Neuron { clip_weight_to_rangeNeuron636 static int clip_weight_to_range(int w) { 637 assert(w < 125); 638 assert(w > -125); 639 return std::max(-kNeuronWeightLimit, std::min(kNeuronWeightLimit, w)); 640 } 641 642 Neuron(int8_t, uint8_t, uint16_t); 643 void recalculate(); 644 void set_weight(int8_t w); get_weightNeuron645 int8_t get_weight() { 646 return weight; 647 } 648 int8_t get_result(size_t); 649 int8_t get_result_safe(int32_t, bool = false); 650 void set_type(uint8_t); get_typeNeuron651 uint8_t get_type() { 652 return type; 653 } get_idNeuron654 uint16_t get_id() { 655 return id; 656 } 657 658 private: 659 int8_t results[21]; // kPositions + 1 660 int8_t weight; 661 uint8_t type; 662 uint16_t id; 663 }; 664 665 struct FNeuron { 666 FNeuron(uint32_t, uint16_t); 667 668 void flip_bit(uint8_t); 669 bool get_result(bool, bool, bool, bool bool4 = true, bool bool5 = true); 670 bool get_position(uint8_t); 671 uint32_t get_int(); get_idFNeuron672 uint16_t get_id() { 673 return id; 674 } 675 676 private: 677 std::bitset<kFNeuronBitSize> core; 678 uint16_t id; 679 }; 680 681 struct ExpansionType { 682 ExpansionType(); 683 684 void set_expantion_type(ExpansionMode); get_expansion_typeExpansionType685 ExpansionMode get_expansion_type() { 686 return type; 687 } 688 689 private: 690 ExpansionMode type; 691 }; 692 693 // This is to keep all data related to AI magic numbers 694 struct ManagementData { 695 void mutate(PlayerNumber = 0); 696 void new_dna_for_persistent(uint8_t, Widelands::AiType); 697 void copy_persistent_to_local(); 698 void review(uint32_t gametime, 699 PlayerNumber pn, 700 uint32_t land, 701 uint32_t max_e_land, 702 uint32_t old_land, 703 uint16_t attackers, 704 int16_t trained_soldiers, 705 uint16_t strength, 706 uint32_t existing_ps, 707 uint32_t first_iron_mine_time); 708 void dump_data(PlayerNumber); new_neuron_idManagementData709 uint16_t new_neuron_id() { 710 ++next_neuron_id; 711 return next_neuron_id - 1; 712 } reset_neuron_idManagementData713 void reset_neuron_id() { 714 next_neuron_id = 0; 715 } new_bi_neuron_idManagementData716 uint16_t new_bi_neuron_id() { 717 ++next_bi_neuron_id; 718 return next_bi_neuron_id - 1; 719 } reset_bi_neuron_idManagementData720 void reset_bi_neuron_id() { 721 next_bi_neuron_id = 0; 722 } set_ai_training_modeManagementData723 void set_ai_training_mode() { 724 ai_training_mode_ = true; 725 } 726 727 int16_t get_military_number_at(uint8_t); 728 void set_military_number_at(uint8_t, int16_t); 729 MutatingIntensity do_mutate(uint8_t, int16_t); 730 int8_t shift_weight_value(int8_t, bool = true); 731 void test_consistency(bool = false); 732 733 std::vector<Neuron> neuron_pool; 734 std::vector<FNeuron> f_neuron_pool; 735 Widelands::Player::AiPersistentState* persistent_data; 736 737 private: 738 void dump_output(Widelands::Player::AiPersistentState, PlayerNumber); 739 740 int32_t score = 1; 741 uint8_t primary_parent = 255; 742 uint16_t next_neuron_id = 0U; 743 uint16_t next_bi_neuron_id = 0U; 744 uint16_t performance_change = 0U; 745 Widelands::AiType ai_type = Widelands::AiType::kNormal; 746 bool ai_training_mode_ = false; 747 uint16_t pref_number_probability = 200; 748 AiDnaHandler ai_dna_handler; 749 }; 750 751 // this is used to count militarysites by their size 752 struct MilitarySiteSizeObserver { 753 MilitarySiteSizeObserver(); 754 755 uint16_t in_construction; 756 uint16_t finished; 757 }; 758 759 // this represents a scheduler task 760 struct SchedulerTask { 761 SchedulerTask(const uint32_t time, 762 const Widelands::SchedulerTaskId t, 763 const uint8_t p, 764 const char* d); 765 766 bool operator<(const SchedulerTask& other) const; 767 768 uint32_t due_time; 769 Widelands::SchedulerTaskId id; 770 // used to sort jobs when AI has to perform more jobs at once 771 uint8_t priority; 772 // used only for debug purposes 773 std::string descr; 774 }; 775 776 // List of blocked fields with block time, with some accompanying functions 777 struct BlockedFields { 778 void add(Coords coords, uint32_t till); 779 uint32_t count(); 780 void remove_expired(uint32_t gametime); 781 bool is_blocked(Coords coords); 782 783 private: 784 // <hash of field coordinates, time till blocked> 785 std::map<uint32_t, uint32_t> blocked_fields_; 786 }; 787 788 // This is a struct that stores strength of players, info on teams and provides some outputs from 789 // these data 790 struct PlayersStrengths { 791 private: 792 struct PlayerStat { 793 PlayerStat() = default; 794 PlayerStat(Widelands::TeamNumber tc, 795 uint32_t pp, 796 uint32_t op, 797 uint32_t o60p, 798 uint32_t cs, 799 uint32_t land, 800 uint32_t oland, 801 uint32_t o60l); 802 803 Widelands::TeamNumber team_number = 0U; 804 uint32_t players_power = 0U; 805 uint32_t old_players_power = 0U; 806 uint32_t old60_players_power = 0U; 807 uint32_t players_casualities = 0U; 808 uint32_t last_time_seen = 0U; 809 uint32_t players_land = 0U; 810 uint32_t old_players_land = 0U; 811 uint32_t old60_players_land = 0U; 812 }; 813 814 public: 815 PlayersStrengths(); 816 // Inserting/updating data 817 void add(Widelands::PlayerNumber pn, 818 Widelands::PlayerNumber opn, 819 Widelands::TeamNumber mytn, 820 Widelands::TeamNumber pltn, 821 uint32_t pp, 822 uint32_t op, 823 uint32_t o60p, 824 uint32_t cs, 825 uint32_t land, 826 uint32_t oland, 827 uint32_t o60l); 828 void remove_stat(Widelands::PlayerNumber pn); 829 void recalculate_team_power(); 830 831 // This is strength of player plus third of strength of other members of his team 832 uint32_t get_modified_player_power(Widelands::PlayerNumber pn); 833 uint32_t get_player_power(Widelands::PlayerNumber pn); 834 uint32_t get_old_player_power(Widelands::PlayerNumber pn); 835 uint32_t get_old60_player_power(Widelands::PlayerNumber pn); 836 uint32_t get_player_land(Widelands::PlayerNumber pn); 837 uint32_t get_old_player_land(Widelands::PlayerNumber pn); 838 uint32_t get_old60_player_land(Widelands::PlayerNumber pn); 839 uint32_t get_visible_enemies_power(uint32_t); 840 uint32_t get_enemies_average_power(); 841 uint32_t get_enemies_average_land(); 842 uint32_t get_enemies_max_power(); 843 uint32_t get_enemies_max_land(); 844 uint32_t get_old_visible_enemies_power(uint32_t); 845 bool players_in_same_team(Widelands::PlayerNumber pl1, Widelands::PlayerNumber pl2); 846 bool strong_enough(Widelands::PlayerNumber pl); 847 void set_last_time_seen(uint32_t, Widelands::PlayerNumber); 848 bool player_seen_lately(Widelands::PlayerNumber, uint32_t); 849 bool get_is_enemy(Widelands::PlayerNumber); 850 uint8_t enemies_seen_lately_count(uint32_t); 851 bool any_enemy_seen_lately(uint32_t); 852 void set_update_time(uint32_t); 853 uint32_t get_update_time(); 854 855 private: 856 // This is the core part of this struct 857 std::map<Widelands::PlayerNumber, PlayerStat> all_stats; 858 859 // Number of team, sum of players' strength 860 std::map<Widelands::TeamNumber, uint32_t> team_powers; 861 862 uint32_t update_time; 863 PlayerNumber this_player_number; 864 PlayerNumber this_player_team; 865 }; 866 867 // This is a wrapper around map of <Flag coords hash:distance from flag to nearest warehouse> 868 // Flags does not have observers so this stuct server like "lazy" substitution for this, where 869 // keys are hash of flags positions 870 // This "lives" during entire "session", and is not saved, but is easily recalulated 871 struct FlagWarehouseDistances { 872 private: 873 struct FlagInfo { 874 FlagInfo(); 875 FlagInfo(uint32_t, uint16_t, uint32_t); 876 // Distance to a nearest warehouse expires, but in two stages 877 // This is complete expiration and such flag is treated as without distance to WH 878 uint32_t expiry_time; 879 // When recalculating new distance, if the current information is younger than 880 // soft_expiry_time it is only decreased if new value is smaller After soft_expiry_time is 881 // updated in any case 882 uint32_t soft_expiry_time; 883 uint16_t distance; 884 // This is coords hash of nearest warehouse, not used by now 885 uint32_t nearest_warehouse; 886 // after building of new road, the distance information is updated not immediately so 887 // we prohibit current flag from another road building... 888 uint32_t new_road_prohibited_till; 889 890 bool update(uint32_t, uint16_t, uint32_t); 891 // Saying the road was built and when 892 void set_road_built(uint32_t); 893 // Asking if road can be built from this flag (providing current gametime) 894 bool is_road_prohibited(uint32_t) const; 895 // get current distance (providing current gametime) 896 uint16_t get(uint32_t, uint32_t*) const; 897 }; 898 std::map<uint32_t, FlagInfo> flags_map; 899 900 public: 901 // All these function uses lookup in flags_map so first argument is usually flag coords hash 902 bool set_distance(uint32_t flag_coords, 903 uint16_t distance, 904 uint32_t gametime, 905 uint32_t nearest_warehouse); 906 int16_t get_distance(uint32_t flag_coords, uint32_t gametime, uint32_t* nw); 907 void set_road_built(uint32_t coords_hash, uint32_t gametime); 908 bool is_road_prohibited(uint32_t coords_hash, uint32_t gametime); 909 uint16_t count() const; 910 bool remove_old_flag(uint32_t gametime); 911 }; 912 913 // This is one-time structure - initiated and filled up when investigating possible roads to be 914 // built to a flag. At the end the flags are scored based on gained info), ordered and if treshold 915 // is achieved the road is to be built 916 struct FlagCandidates { 917 FlagCandidatesFlagCandidates918 explicit FlagCandidates(uint16_t wd) : start_flag_dist_to_wh(wd) { 919 } 920 921 struct Candidate { 922 Candidate() = delete; 923 Candidate(uint32_t, bool, uint16_t, uint16_t, uint16_t); 924 uint16_t air_distance; 925 uint32_t coords_hash; 926 bool different_economy; 927 uint16_t start_flag_dist_to_wh; 928 uint16_t flag_to_flag_road_distance; 929 uint16_t possible_road_distance; 930 uint16_t cand_flag_distance_to_wh; 931 // Scoring is considering multiple things 932 int16_t score() const; is_buildableFlagCandidates::Candidate933 bool is_buildable() { 934 return possible_road_distance > 0; 935 } 936 bool operator<(const Candidate& other) const { 937 return score() > other.score(); 938 } 939 }; 940 941 private: 942 std::vector<Candidate> flags_; 943 uint16_t start_flag_dist_to_wh; 944 945 public: flagsFlagCandidates946 const std::vector<Candidate>& flags() const { 947 return flags_; 948 } 949 bool has_candidate(uint32_t) const; 950 void add_flag(uint32_t, bool, uint16_t, uint16_t); 951 bool set_cur_road_distance(uint32_t, uint16_t); 952 bool set_road_possible(uint32_t, uint16_t); 953 void sort(); 954 void sort_by_air_distance(); countFlagCandidates955 uint32_t count() { 956 return flags_.size(); 957 } 958 FlagCandidates::Candidate* get_winner(const int16_t = 0); 959 }; 960 } // namespace Widelands 961 962 #endif // end of include guard: WL_AI_AI_HELP_STRUCTS_H 963