1 /*
2  * Copyright (C) 2004-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 #include "ai/defaultai.h"
21 
22 #include <algorithm>
23 #include <memory>
24 
25 #include "ai/ai_hints.h"
26 #include "base/macros.h"
27 #include "base/time_string.h"
28 #include "base/wexception.h"
29 #include "economy/flag.h"
30 #include "economy/portdock.h"
31 #include "economy/road.h"
32 #include "economy/wares_queue.h"
33 #include "logic/map.h"
34 #include "logic/map_objects/findbob.h"
35 #include "logic/map_objects/findimmovable.h"
36 #include "logic/map_objects/findnode.h"
37 #include "logic/map_objects/tribes/constructionsite.h"
38 #include "logic/map_objects/tribes/militarysite.h"
39 #include "logic/map_objects/tribes/productionsite.h"
40 #include "logic/map_objects/tribes/ship.h"
41 #include "logic/map_objects/tribes/soldier.h"
42 #include "logic/map_objects/tribes/trainingsite.h"
43 #include "logic/map_objects/tribes/tribe_descr.h"
44 #include "logic/map_objects/tribes/tribes.h"
45 #include "logic/map_objects/tribes/warehouse.h"
46 #include "logic/map_objects/world/world.h"
47 #include "logic/player.h"
48 #include "logic/playercommand.h"
49 
50 // following is in milliseconds (widelands counts time in ms)
51 constexpr int kFieldInfoExpiration = 12 * 1000;
52 constexpr int kMineFieldInfoExpiration = 20 * 1000;
53 constexpr int kNewMineConstInterval = 19000;
54 constexpr int kBusyMineUpdateInterval = 2000;
55 // building of the same building can be started after 25s at earliest
56 constexpr int kBuildingMinInterval = 25 * 1000;
57 constexpr int kMinBFCheckInterval = 5 * 1000;
58 constexpr int kMinMFCheckInterval = 19 * 1000;
59 constexpr int kMarineDecisionInterval = 20 * 1000;
60 constexpr int kRemainingBasicBuildingsResetTime = 1 * 60 * 1000;
61 
62 // following two are used for roads management, for creating shortcuts and dismantling dispensable
63 // roads
64 constexpr int32_t kSpotsEnough = 25;
65 
66 constexpr uint16_t kTargetQuantCap = 30;
67 
68 // this is intended for map developers & testers, should be off by default
69 constexpr bool kPrintStats = false;
70 
71 // for scheduler
72 constexpr int kMaxJobs = 4;
73 
74 // Count of mine types / ground resources
75 constexpr int kMineTypes = 4;
76 
77 using namespace Widelands;
78 
79 DefaultAI::NormalImpl DefaultAI::normal_impl;
80 DefaultAI::WeakImpl DefaultAI::weak_impl;
81 DefaultAI::VeryWeakImpl DefaultAI::very_weak_impl;
82 
83 uint32_t DefaultAI::last_seafaring_check_ = 0;
84 bool DefaultAI::map_allows_seafaring_ = false;
85 
86 /// Constructor of DefaultAI
DefaultAI(Game & ggame,PlayerNumber const pid,Widelands::AiType const t)87 DefaultAI::DefaultAI(Game& ggame, PlayerNumber const pid, Widelands::AiType const t)
88    : ComputerPlayer(ggame, pid),
89      type_(t),
90      player_(nullptr),
91      tribe_(nullptr),
92      attackers_count_(0),
93      next_ai_think_(0),
94      scheduler_delay_counter_(0),
95      wood_policy_(WoodPolicy::kAllowRangers),
96      numof_psites_in_constr(0),
97      num_ports(0),
98      numof_warehouses_(0),
99      numof_warehouses_in_const_(0),
100      military_last_dismantle_(0),
101      military_last_build_(0),
102      time_of_last_construction_(0),
103      next_mine_construction_due_(0),
104      fishers_count_(0),
105      bakeries_count_(),
106      first_iron_mine_built(50 * 60 * 60 * 1000),
107      ts_finished_count_(0),
108      ts_in_const_count_(0),
109      ts_without_trainers_(0),
110      enemysites_check_delay_(30),
111      spots_(0),
112      resource_necessity_water_needed_(false),
113      highest_nonmil_prio_(0),
114      expedition_ship_(kNoShip) {
115 
116 	// Subscribe to NoteFieldPossession.
117 	field_possession_subscriber_ =
118 	   Notifications::subscribe<NoteFieldPossession>([this](const NoteFieldPossession& note) {
119 		   if (note.player != player_) {
120 			   return;
121 		   }
122 		   if (note.ownership == NoteFieldPossession::Ownership::GAINED) {
123 			   unusable_fields.push_back(note.fc);
124 		   }
125 		});
126 
127 	// Subscribe to NoteImmovables.
128 	immovable_subscriber_ =
129 	   Notifications::subscribe<NoteImmovable>([this](const NoteImmovable& note) {
130 		   if (player_ == nullptr) {
131 			   return;
132 		   }
133 		   if (note.pi->owner().player_number() != player_->player_number()) {
134 			   return;
135 		   }
136 		   if (note.ownership == NoteImmovable::Ownership::GAINED) {
137 			   gain_immovable(*note.pi);
138 		   } else {
139 			   lose_immovable(*note.pi);
140 		   }
141 		});
142 
143 	// Subscribe to ProductionSiteOutOfResources.
144 	outofresource_subscriber_ = Notifications::subscribe<NoteProductionSiteOutOfResources>(
145 	   [this](const NoteProductionSiteOutOfResources& note) {
146 		   if (note.ps->owner().player_number() != player_->player_number()) {
147 			   return;
148 		   }
149 
150 		   out_of_resources_site(*note.ps);
151 		});
152 
153 	// Subscribe to TrainingSiteSoldierTrained.
154 	soldiertrained_subscriber_ = Notifications::subscribe<NoteTrainingSiteSoldierTrained>(
155 	   [this](const NoteTrainingSiteSoldierTrained& note) {
156 		   if (note.ts->owner().player_number() != player_->player_number()) {
157 			   return;
158 		   }
159 
160 		   soldier_trained(*note.ts);
161 		});
162 
163 	// Subscribe to ShipNotes.
164 	shipnotes_subscriber_ = Notifications::subscribe<NoteShip>([this](const NoteShip& note) {
165 		// in a short time between start and late_initialization the player
166 		// can get notes that can not be processed.
167 		// It seems that this causes no problem, at least no substantial
168 		if (player_ == nullptr) {
169 			return;
170 		}
171 		if (note.ship->get_owner()->player_number() != player_->player_number()) {
172 			return;
173 		}
174 
175 		switch (note.action) {
176 
177 		case NoteShip::Action::kGained:
178 			gain_ship(*note.ship, NewShip::kBuilt);
179 			break;
180 
181 		case NoteShip::Action::kLost:
182 			for (std::deque<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i) {
183 				if (i->ship == note.ship) {
184 					allships.erase(i);
185 					break;
186 				}
187 			}
188 			break;
189 
190 		case NoteShip::Action::kWaitingForCommand:
191 			for (std::deque<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i) {
192 				if (i->ship == note.ship) {
193 					i->waiting_for_command_ = true;
194 					break;
195 				}
196 			}
197 			break;
198 		default:
199 			// Do nothing
200 			break;
201 		}
202 	});
203 }
204 
~DefaultAI()205 DefaultAI::~DefaultAI() {
206 	while (!buildable_fields.empty()) {
207 		delete buildable_fields.back();
208 		buildable_fields.pop_back();
209 	}
210 
211 	while (!mineable_fields.empty()) {
212 		delete mineable_fields.back();
213 		mineable_fields.pop_back();
214 	}
215 
216 	while (!economies.empty()) {
217 		delete economies.back();
218 		economies.pop_back();
219 	}
220 }
221 
222 /**
223  * Main loop of computer player_ "defaultAI"
224  *
225  * General behaviour is defined here.
226  */
think()227 void DefaultAI::think() {
228 
229 	if (tribe_ == nullptr) {
230 		late_initialization();
231 	}
232 
233 	const uint32_t gametime = static_cast<uint32_t>(game().get_gametime());
234 
235 	if (next_ai_think_ > gametime) {
236 		return;
237 	}
238 
239 	// AI now thinks twice in a seccond, if the game engine allows this
240 	// if too busy, the period can be many seconds.
241 	next_ai_think_ = gametime + 500;
242 	SchedulerTaskId due_task = SchedulerTaskId::kUnset;
243 
244 	sort_task_pool();
245 
246 	const int32_t delay_time = gametime - taskPool.front().due_time;
247 
248 	// Here we decide how many jobs will be run now (none - 5)
249 	// in case no job is due now, it can be zero
250 	uint32_t jobs_to_run_count = (delay_time < 0) ? 0 : 1;
251 
252 	// Here we collect data for "too late ..." message
253 	if (delay_time > 5000) {
254 		++scheduler_delay_counter_;
255 	} else {
256 		scheduler_delay_counter_ = 0;
257 	}
258 
259 	if (jobs_to_run_count == 0) {
260 		// well we have nothing to do now
261 		return;
262 	}
263 
264 	// And printing it now and resetting counter
265 	if (scheduler_delay_counter_ > 10) {
266 		log(" %d: AI: game speed too high, jobs are too late (now %2d seconds)\n", player_number(),
267 		    static_cast<int32_t>(delay_time / 1000));
268 		scheduler_delay_counter_ = 0;
269 	}
270 
271 	// 400 provides that second job is run if delay time is longer then 1.6 sec
272 	if (delay_time / 400 > 1) {
273 		jobs_to_run_count = sqrt(static_cast<uint32_t>(delay_time / 500));
274 	}
275 
276 	jobs_to_run_count = (jobs_to_run_count > kMaxJobs) ? kMaxJobs : jobs_to_run_count;
277 	assert(jobs_to_run_count > 0 && jobs_to_run_count <= kMaxJobs);
278 	assert(jobs_to_run_count < taskPool.size());
279 
280 	// Pool of tasks to be executed this run. In ideal situation it will consist of one task only.
281 	std::vector<SchedulerTask> current_task_queue;
282 	assert(current_task_queue.empty());
283 	// Here we push SchedulerTask members into the temporary queue, providing that a task is due now
284 	// and
285 	// the limit (jobs_to_run_count) is not exceeded
286 	for (uint8_t i = 0; i < jobs_to_run_count; ++i) {
287 		if (taskPool[i].due_time <= gametime) {
288 			current_task_queue.push_back(taskPool[i]);
289 			sort_task_pool();
290 		} else {
291 			break;
292 		}
293 	}
294 
295 	assert(!current_task_queue.empty() && current_task_queue.size() <= jobs_to_run_count);
296 
297 	// Ordering temporary queue so that higher priority (lower number) is on the beginning
298 	std::sort(current_task_queue.begin(), current_task_queue.end());
299 
300 	// Performing tasks from temporary queue one by one
301 	for (uint8_t i = 0; i < current_task_queue.size(); ++i) {
302 
303 		due_task = current_task_queue[i].id;
304 
305 		++sched_stat_[static_cast<uint32_t>(due_task)];
306 
307 		// Now AI runs a job selected above to be performed in this turn
308 		// (only one but some of them needs to run check_economies() to
309 		// guarantee consistency)
310 		// job names are selfexplanatory
311 		switch (due_task) {
312 		case SchedulerTaskId::kBbuildableFieldsCheck:
313 			update_all_buildable_fields(gametime);
314 			set_taskpool_task_time(
315 			   gametime + kMinBFCheckInterval, SchedulerTaskId::kBbuildableFieldsCheck);
316 			break;
317 		case SchedulerTaskId::kMineableFieldsCheck:
318 			update_all_mineable_fields(gametime);
319 			set_taskpool_task_time(
320 			   gametime + kMinMFCheckInterval, SchedulerTaskId::kMineableFieldsCheck);
321 			break;
322 		case SchedulerTaskId::kRoadCheck:
323 			if (check_economies()) {  // is a must
324 				return;
325 			}
326 			set_taskpool_task_time(gametime + 1000, SchedulerTaskId::kRoadCheck);
327 			// testing 5 roads
328 			{
329 				const int32_t roads_to_check = roads.size() / 30 + 1;
330 				for (int j = 0; j < roads_to_check; ++j) {
331 					// improve_roads function will test one road and rotate roads vector
332 					if (improve_roads(gametime)) {
333 						// if significant change takes place do not go on
334 						break;
335 					}
336 				}
337 			}
338 			break;
339 		case SchedulerTaskId::kUnbuildableFCheck:
340 			set_taskpool_task_time(gametime + 4000, SchedulerTaskId::kUnbuildableFCheck);
341 			update_all_not_buildable_fields();
342 			break;
343 		case SchedulerTaskId::kCheckEconomies:
344 			check_economies();
345 			set_taskpool_task_time(gametime + 8000, SchedulerTaskId::kCheckEconomies);
346 			break;
347 		case SchedulerTaskId::kProductionsitesStats:
348 			update_productionsite_stats();
349 			// Updating the stats every 10 seconds should be enough
350 			set_taskpool_task_time(gametime + 10000, SchedulerTaskId::kProductionsitesStats);
351 			break;
352 		case SchedulerTaskId::kConstructBuilding:
353 			if (check_economies()) {  // economies must be consistent
354 				return;
355 			}
356 			if (gametime < 15000) {  // More frequent at the beginning of game
357 				set_taskpool_task_time(gametime + 2000, SchedulerTaskId::kConstructBuilding);
358 			} else {
359 				set_taskpool_task_time(gametime + 6000, SchedulerTaskId::kConstructBuilding);
360 			}
361 			if (construct_building(gametime)) {
362 				time_of_last_construction_ = gametime;
363 			}
364 			break;
365 		case SchedulerTaskId::kCheckProductionsites:
366 			if (check_economies()) {  // economies must be consistent
367 				return;
368 			}
369 			{
370 				set_taskpool_task_time(gametime + 15000, SchedulerTaskId::kCheckProductionsites);
371 				// testing 5 productionsites (if there are 5 of them)
372 				int32_t ps_to_check = (productionsites.size() < 5) ? productionsites.size() : 5;
373 				for (int j = 0; j < ps_to_check; ++j) {
374 					// one productionsite per one check_productionsites() call
375 					if (check_productionsites(gametime)) {
376 						// if significant change takes place do not go on
377 						break;
378 					}
379 				}
380 			}
381 			break;
382 		case SchedulerTaskId::kCheckShips:
383 			// if function returns false, we can postpone next call
384 			{
385 				const uint8_t wait_multiplier = (check_ships(gametime)) ? 1 : 5;
386 				set_taskpool_task_time(
387 				   gametime + wait_multiplier * kShipCheckInterval, SchedulerTaskId::kCheckShips);
388 			}
389 			break;
390 		case SchedulerTaskId::KMarineDecisions:
391 			// if function returns false, we can postpone for next call
392 			{
393 				const uint8_t wait_multiplier = (marine_main_decisions(gametime)) ? 1 : 5;
394 				set_taskpool_task_time(gametime + wait_multiplier * kMarineDecisionInterval,
395 				                       SchedulerTaskId::KMarineDecisions);
396 			}
397 			break;
398 		case SchedulerTaskId::kCheckMines:
399 			if (check_economies()) {  // economies must be consistent
400 				return;
401 			}
402 			set_taskpool_task_time(gametime + 15000, SchedulerTaskId::kCheckMines);
403 			// checking 3 mines if possible
404 			{
405 				int32_t mines_to_check = (mines_.size() < 5) ? mines_.size() : 5;
406 				for (int j = 0; j < mines_to_check; ++j) {
407 					// every run of check_mines_() checks one mine
408 					if (check_mines_(gametime)) {
409 						// if significant change takes place do not go on
410 						break;
411 					}
412 				}
413 			}
414 			break;
415 		case SchedulerTaskId::kCheckMilitarysites:
416 			// just to be sure the value is reset
417 			if (check_militarysites(gametime)) {
418 				set_taskpool_task_time(gametime + 15 * 1000, SchedulerTaskId::kCheckMilitarysites);
419 			} else {
420 				set_taskpool_task_time(gametime + 4 * 1000, SchedulerTaskId::kCheckMilitarysites);
421 			}
422 			break;
423 		case SchedulerTaskId::kCheckTrainingsites:
424 			set_taskpool_task_time(
425 			   gametime + kTrainingSitesCheckInterval, SchedulerTaskId::kCheckTrainingsites);
426 			check_trainingsites(gametime);
427 			break;
428 		case SchedulerTaskId::kCountMilitaryVacant:
429 			count_military_vacant_positions();
430 			set_taskpool_task_time(gametime + 25 * 1000, SchedulerTaskId::kCountMilitaryVacant);
431 			break;
432 		case SchedulerTaskId::kWareReview:
433 			if (check_economies()) {  // economies must be consistent
434 				return;
435 			}
436 			set_taskpool_task_time(gametime + 15 * 60 * 1000, SchedulerTaskId::kWareReview);
437 			review_wares_targets(gametime);
438 			break;
439 		case SchedulerTaskId::kPrintStats:
440 			if (check_economies()) {  // economies must be consistent
441 				return;
442 			}
443 			set_taskpool_task_time(gametime + 10 * 60 * 1000, SchedulerTaskId::kPrintStats);
444 			print_stats(gametime);
445 			break;
446 		case SchedulerTaskId::kCheckEnemySites:
447 			check_enemy_sites(gametime);
448 			set_taskpool_task_time(gametime + 19 * 1000, SchedulerTaskId::kCheckEnemySites);
449 			break;
450 		case SchedulerTaskId::kManagementUpdate:
451 			// This task is used for training the AI, so it should be usually disabled
452 			{  // statistics for spotted warehouses
453 				uint16_t conquered_wh = 0;
454 				for (auto coords : enemy_warehouses) {
455 					if (get_land_owner(game().map(), coords) == player_number()) {
456 						++conquered_wh;
457 					}
458 				}
459 				if (!basic_economy_established) {
460 					assert(!persistent_data->remaining_basic_buildings.empty());
461 					log("%2d: Basic economy not achieved, %" PRIuS " building(s) missing, f.e.: %s\n",
462 					    player_number(), persistent_data->remaining_basic_buildings.size(),
463 					    get_building_observer(persistent_data->remaining_basic_buildings.begin()->first)
464 					       .name);
465 				}
466 				if (!enemy_warehouses.empty()) {
467 					log(
468 					   "Conquered warehouses: %d / %" PRIuS "\n", conquered_wh, enemy_warehouses.size());
469 				}
470 				management_data.review(
471 				   gametime, player_number(), player_statistics.get_player_land(player_number()),
472 				   player_statistics.get_enemies_max_land(),
473 				   player_statistics.get_old60_player_land(player_number()), attackers_count_,
474 				   soldier_trained_log.count(gametime),
475 				   player_statistics.get_player_power(player_number()),
476 				   count_productionsites_without_buildings(), first_iron_mine_built);
477 				set_taskpool_task_time(
478 				   gametime + kManagementUpdateInterval, SchedulerTaskId::kManagementUpdate);
479 			}
480 			break;
481 		case SchedulerTaskId::kUpdateStats:
482 			update_player_stat(gametime);
483 			set_taskpool_task_time(gametime + kStatUpdateInterval, SchedulerTaskId::kUpdateStats);
484 			break;
485 		case SchedulerTaskId::kWarehouseFlagDist:
486 			check_flag_distances(gametime);
487 			set_taskpool_task_time(
488 			   gametime + kFlagWarehouseUpdInterval, SchedulerTaskId::kWarehouseFlagDist);
489 			break;
490 		case SchedulerTaskId::kUnset:
491 			NEVER_HERE();
492 		}
493 	}
494 }
495 
496 /**
497  * Cares for all variables not initialised during construction
498  *
499  * When DefaultAI is constructed, some information is not yet available (e.g.
500  * world), so this is done after complete loading of the map.
501  */
late_initialization()502 void DefaultAI::late_initialization() {
503 	player_ = game().get_player(player_number());
504 	tribe_ = &player_->tribe();
505 	if (game().is_ai_training_mode()) {
506 		ai_training_mode_ = true;
507 		management_data.set_ai_training_mode();
508 	}
509 	const uint32_t gametime = game().get_gametime();
510 
511 	log("ComputerPlayer(%d): initializing as type %u%s\n", player_number(),
512 	    static_cast<unsigned int>(type_), (ai_training_mode_) ? ", in ai training mode" : "");
513 	if (player_->team_number() > 0) {
514 		log("    ... member of team %d\n", player_->team_number());
515 	}
516 
517 	wares.resize(game().tribes().nrwares());
518 	for (DescriptionIndex i = 0; i < static_cast<DescriptionIndex>(game().tribes().nrwares()); ++i) {
519 		wares.at(i).preciousness =
520 		   game().tribes().get_ware_descr(i)->ai_hints().preciousness(tribe_->name());
521 	}
522 
523 	const DescriptionIndex& nr_buildings = game().tribes().nrbuildings();
524 
525 	// The data struct below is owned by Player object, the purpose is to have them saved therein
526 	persistent_data = player_->get_mutable_ai_persistent_state();
527 	management_data.persistent_data = player_->get_mutable_ai_persistent_state();
528 	const bool create_basic_buildings_list =
529 	   !persistent_data->initialized || (gametime < kRemainingBasicBuildingsResetTime);
530 
531 	if (!persistent_data->initialized) {
532 		// As all data are initialized without given values, they must be populated with reasonable
533 		// values first
534 		persistent_data->initialize();
535 
536 		// AI's DNA population
537 		management_data.new_dna_for_persistent(player_number(), type_);
538 		management_data.copy_persistent_to_local();
539 		management_data.mutate(player_number());
540 		if (ai_training_mode_) {
541 			management_data.dump_data(player_number());
542 		}
543 
544 		management_data.test_consistency(true);
545 		assert(management_data.get_military_number_at(42) ==
546 		       management_data.get_military_number_at(kMutationRatePosition));
547 
548 	} else {
549 		// Doing some consistency checks
550 		check_range<uint32_t>(
551 		   persistent_data->expedition_start_time, gametime, "expedition_start_time");
552 		check_range<uint16_t>(persistent_data->ships_utilization, 0, 10000, "ships_utilization_");
553 
554 		// for backward consistency
555 		if (persistent_data->ai_personality_mil_upper_limit <
556 		    persistent_data->target_military_score) {
557 			persistent_data->ai_personality_mil_upper_limit = persistent_data->target_military_score;
558 		}
559 		if (persistent_data->least_military_score > persistent_data->target_military_score) {
560 			persistent_data->least_military_score = persistent_data->target_military_score;
561 		}
562 
563 		if (ai_training_mode_) {
564 			log("%2d: reinitializing dna (kAITrainingMode set true)", player_number());
565 			management_data.new_dna_for_persistent(player_number(), type_);
566 			management_data.copy_persistent_to_local();
567 			management_data.mutate(player_number());
568 			management_data.dump_data(player_number());
569 
570 		} else {
571 			management_data.copy_persistent_to_local();
572 		}
573 
574 		management_data.test_consistency(true);
575 
576 		log(" %2d: %" PRIuS " basic buildings in savegame file. %s\n", player_number(),
577 		    persistent_data->remaining_basic_buildings.size(),
578 		    (create_basic_buildings_list) ?
579 		       "New list will be recreated though (kAITrainingMode is true)" :
580 		       "");
581 	}
582 
583 	// Even if we have basic buildings from savefile, we ignore them and recreate them based
584 	// on lua conf files
585 	if (create_basic_buildings_list) {
586 		persistent_data->remaining_basic_buildings.clear();
587 	}
588 
589 	for (DescriptionIndex building_index = 0; building_index < nr_buildings; ++building_index) {
590 		const BuildingDescr& bld = *tribe_->get_building_descr(building_index);
591 		if (!tribe_->has_building(building_index) && bld.type() != MapObjectType::MILITARYSITE) {
592 			continue;
593 		}
594 
595 		const std::string& building_name = bld.name();
596 		const BuildingHints& bh = bld.hints();
597 		buildings_.resize(buildings_.size() + 1);
598 		BuildingObserver& bo = buildings_.back();
599 		bo.name = building_name.c_str();
600 		bo.id = building_index;
601 		bo.desc = &bld;
602 		bo.type = BuildingObserver::Type::kBoring;
603 		bo.cnt_built = 0;
604 		bo.cnt_under_construction = 0;
605 		bo.cnt_target = 1;  // default for everything
606 		bo.cnt_limit_by_aimode = std::numeric_limits<int32_t>::max();
607 		bo.cnt_upgrade_pending = 0;
608 		bo.stocklevel_count = 0;
609 		bo.stocklevel_time = 0;
610 		bo.last_dismantle_time = 0;
611 		// this is set to negative number, otherwise the AI would wait 25 sec
612 		// after game start not building anything
613 		bo.construction_decision_time = -60 * 60 * 1000;
614 		bo.last_building_built = kNever;
615 		bo.build_material_shortage = false;
616 		bo.current_stats = 0;
617 		bo.unoccupied_count = 0;
618 		bo.unconnected_count = 0;
619 		bo.new_building_overdue = 0;
620 		bo.primary_priority = 0;
621 		if (bld.is_buildable()) {
622 			bo.set_is(BuildingAttribute::kBuildable);
623 		}
624 		if (bld.needs_seafaring()) {
625 			bo.set_is(BuildingAttribute::kNeedsSeafaring);
626 		}
627 		if (create_basic_buildings_list &&
628 		    bh.basic_amount() > 0) {  // This is the very begining of the game
629 			assert(persistent_data->remaining_basic_buildings.count(bo.id) == 0);
630 			persistent_data->remaining_basic_buildings.emplace(
631 			   std::make_pair(bo.id, bh.basic_amount()));
632 		}
633 		bo.basic_amount = bh.basic_amount();
634 		if (bh.get_needs_water()) {
635 			bo.set_is(BuildingAttribute::kNeedsCoast);
636 		}
637 		if (bh.is_space_consumer()) {
638 			bo.set_is(BuildingAttribute::kSpaceConsumer);
639 		}
640 		bo.expansion_type = bh.is_expansion_type();
641 		bo.fighting_type = bh.is_fighting_type();
642 		bo.mountain_conqueror = bh.is_mountain_conqueror();
643 		bo.requires_supporters = bh.requires_supporters();
644 		bo.set_collected_map_resource(*tribe_, bh.collects_ware_from_map());
645 		if (bo.requires_supporters) {
646 			log(" %d: %s strictly requires supporters\n", player_number(), bo.name);
647 		}
648 		bo.prohibited_till = bh.get_prohibited_till() * 1000;  // value in conf is in seconds
649 		bo.forced_after = bh.get_forced_after() * 1000;        // value in conf is in seconds
650 		if (bld.get_isport()) {
651 			bo.set_is(BuildingAttribute::kPort);
652 		}
653 		bo.max_trainingsites_proportion = 100;
654 		bo.initial_preciousness = 0;
655 		bo.max_preciousness = 0;
656 		bo.max_needed_preciousness = 0;
657 
658 		for (auto ph : bh.supported_production()) {
659 			bo.production_hints.insert(tribe_->safe_ware_index(ph));
660 		}
661 		// I just presume cut wood is named "log" in the game
662 		if (bo.production_hints.count(tribe_->safe_ware_index("log"))) {
663 			bo.set_is(BuildingAttribute::kRanger);
664 		}
665 		// Is total count of this building limited by AI mode?
666 		if (bh.get_ai_limit(type_) >= 0) {
667 			bo.cnt_limit_by_aimode = bh.get_ai_limit(type_);
668 		}
669 
670 		// Read all interesting data from ware producing buildings
671 		if (bld.type() == MapObjectType::PRODUCTIONSITE) {
672 			const ProductionSiteDescr& prod = dynamic_cast<const ProductionSiteDescr&>(bld);
673 			bo.type = bld.get_ismine() ? BuildingObserver::Type::kMine :
674 			                             BuildingObserver::Type::kProductionsite;
675 			for (const auto& temp_input : prod.input_wares()) {
676 				bo.inputs.push_back(temp_input.first);
677 			}
678 			for (const DescriptionIndex& temp_output : prod.output_ware_types()) {
679 				bo.ware_outputs.push_back(temp_output);
680 				if (tribe_->is_construction_material(temp_output) && !bo.inputs.empty()) {
681 					wares.at(temp_output).refined_build_material = true;
682 				}
683 			}
684 
685 			// Read information about worker outputs
686 			if (prod.output_worker_types().size() > 0) {
687 				for (const DescriptionIndex& temp_output : prod.output_worker_types()) {
688 					if (temp_output == tribe_->soldier()) {
689 						bo.set_is(BuildingAttribute::kBarracks);
690 					}
691 					const WorkerHints* worker_hints = tribe_->get_worker_descr(temp_output)->ai_hints();
692 					if (worker_hints != nullptr) {
693 						const int worker_preciousness = worker_hints->preciousness(tribe_->name());
694 						if (worker_preciousness != Widelands::kInvalidWare) {
695 							bo.initial_preciousness += worker_preciousness;
696 						}
697 					}
698 				}
699 				if (!bo.is(BuildingAttribute::kBarracks) && bo.ware_outputs.empty()) {
700 					bo.set_is(BuildingAttribute::kRecruitment);
701 				}
702 			}
703 
704 			for (const auto& temp_position : prod.working_positions()) {
705 				for (uint8_t i = 0; i < temp_position.second; i++) {
706 					bo.positions.push_back(temp_position.first);
707 				}
708 			}
709 
710 			// If this is a producer, does it act also as supporter?
711 			if (!bo.ware_outputs.empty() && !bo.production_hints.empty()) {
712 				bo.set_is(BuildingAttribute::kSupportingProducer);
713 			}
714 
715 			iron_resource_id = game().world().resource_index("iron");
716 			if (iron_resource_id == INVALID_INDEX) {
717 				throw wexception("The AI needs the world to define the resource 'iron'");
718 			}
719 
720 			if (bo.type == BuildingObserver::Type::kMine) {
721 				// get the resource needed by the mine
722 				if (bh.get_mines()) {
723 					bo.mines = game().world().resource_index(bh.get_mines());
724 				}
725 
726 				bo.mines_percent = bh.get_mines_percent();
727 
728 				// populating mines_per_type map
729 				if (mines_per_type.count(bo.mines) == 0) {
730 					mines_per_type[bo.mines] = MineTypesObserver();
731 				}
732 				// Identify iron mines based on mines value
733 				if (bo.mines == iron_resource_id) {
734 					mines_per_type[bo.mines].is_critical = true;
735 					mine_fields_stat.add_critical_ore(bo.mines);
736 				}
737 			}
738 
739 			if (bh.is_shipyard()) {
740 				bo.set_is(BuildingAttribute::kShipyard);
741 			}
742 			if (bh.supports_seafaring()) {
743 				bo.set_is(BuildingAttribute::kSupportsSeafaring);
744 			}
745 
746 			// now we find out if the upgrade of the building is a full substitution
747 			// (produces all wares as current one)
748 			const DescriptionIndex enhancement = bld.enhancement();
749 			if (enhancement != INVALID_INDEX && bo.type == BuildingObserver::Type::kProductionsite) {
750 				std::unordered_set<DescriptionIndex> enh_outputs;
751 				const ProductionSiteDescr& enh_prod =
752 				   dynamic_cast<const ProductionSiteDescr&>(*tribe_->get_building_descr(enhancement));
753 
754 				// collecting wares that are produced in enhanced building
755 				for (const DescriptionIndex& ware : enh_prod.output_ware_types()) {
756 					enh_outputs.insert(ware);
757 				}
758 				// now testing outputs of current building
759 				// and comparing
760 				bo.set_is(BuildingAttribute::kUpgradeSubstitutes);
761 				for (DescriptionIndex ware : bo.ware_outputs) {
762 					if (enh_outputs.count(ware) == 0) {
763 						bo.unset_is(BuildingAttribute::kUpgradeSubstitutes);
764 						break;
765 					}
766 				}
767 
768 				std::unordered_set<DescriptionIndex> cur_outputs;
769 				// collecting wares that are produced in enhanced building
770 				for (const DescriptionIndex& ware : bo.ware_outputs) {
771 					cur_outputs.insert(ware);
772 				}
773 				// Does upgraded building produce any different outputs?
774 				for (DescriptionIndex ware : enh_outputs) {
775 					if (cur_outputs.count(ware) == 0) {
776 						bo.set_is(BuildingAttribute::kUpgradeExtends);
777 						break;
778 					}
779 				}
780 			}
781 
782 			// now we identify producers of critical build materials
783 			for (DescriptionIndex ware : bo.ware_outputs) {
784 				// building material except for trivial material
785 				if (wares.at(ware).refined_build_material) {
786 					bo.set_is(BuildingAttribute::kBuildingMatProducer);
787 					if (bo.type == BuildingObserver::Type::kMine) {
788 						mines_per_type[bo.mines].is_critical = true;
789 						mine_fields_stat.add_critical_ore(bo.mines);
790 					}
791 				}
792 			}
793 
794 			for (const auto& temp_buildcosts : prod.buildcost()) {
795 				// building material except for trivial material
796 				if (wares.at(temp_buildcosts.first).refined_build_material) {
797 					bo.critical_building_material.push_back(temp_buildcosts.first);
798 				}
799 			}
800 
801 			// some important buildings are identified first the woodcutter/lumberjack
802 			if (bh.collects_ware_from_map() == "log") {
803 				bo.set_is(BuildingAttribute::kLumberjack);
804 			}
805 			// quarries
806 			if (bh.collects_ware_from_map() == "granite") {
807 				bo.set_is(BuildingAttribute::kNeedsRocks);
808 			}
809 			// wells
810 			if (bh.collects_ware_from_map() == "water") {
811 				bo.set_is(BuildingAttribute::kWell);
812 			}
813 			// here we identify hunters
814 			if (bh.collects_ware_from_map() == "meat") {
815 				bo.set_is(BuildingAttribute::kHunter);
816 			}
817 			// and fishers
818 			if (bh.collects_ware_from_map() == "fish" && bo.inputs.empty()) {
819 				bo.set_is(BuildingAttribute::kFisher);
820 			}
821 			// and collectors
822 			if (bh.collects_ware_from_map() == "fruit") {
823 				bo.set_is(BuildingAttribute::kNeedsBerry);
824 			}
825 
826 			continue;
827 		}
828 
829 		// now for every military building, we fill critical_building_material vector
830 		// with critical construction wares
831 		if (bld.type() == MapObjectType::MILITARYSITE) {
832 			bo.type = BuildingObserver::Type::kMilitarysite;
833 			const MilitarySiteDescr& milit = dynamic_cast<const MilitarySiteDescr&>(bld);
834 			for (const auto& temp_buildcosts : milit.buildcost()) {
835 				// Below are non-critical wares (wares produced without inputs)
836 				if (wares.at(temp_buildcosts.first).refined_build_material) {
837 					bo.critical_building_material.push_back(temp_buildcosts.first);
838 				}
839 			}
840 			continue;
841 		}
842 
843 		if (bld.type() == MapObjectType::WAREHOUSE) {
844 			bo.type = BuildingObserver::Type::kWarehouse;
845 			continue;
846 		}
847 
848 		if (bld.type() == MapObjectType::TRAININGSITE) {
849 			bo.type = BuildingObserver::Type::kTrainingsite;
850 			bo.max_trainingsites_proportion = bh.trainingsites_max_percent();
851 			assert(bo.max_trainingsites_proportion <= 100);
852 			const TrainingSiteDescr& train = dynamic_cast<const TrainingSiteDescr&>(bld);
853 			for (const auto& temp_input : train.input_wares()) {
854 				bo.inputs.push_back(temp_input.first);
855 
856 				// collecting subsitutes
857 				if (tribe_->ware_index("meat") == temp_input.first ||
858 				    tribe_->ware_index("fish") == temp_input.first ||
859 				    tribe_->ware_index("smoked_meat") == temp_input.first ||
860 				    tribe_->ware_index("smoked_fish") == temp_input.first) {
861 					bo.substitute_inputs.insert(temp_input.first);
862 				}
863 			}
864 			// Creating vector with critical material, to be used to discourage
865 			// building of new sites if ware is lacking
866 			for (const auto& temp_buildcosts : train.buildcost()) {
867 				// building material except for trivial material
868 				if (wares.at(temp_buildcosts.first).refined_build_material) {
869 					bo.critical_building_material.push_back(temp_buildcosts.first);
870 				}
871 			}
872 			continue;
873 		}
874 
875 		if (bld.type() == MapObjectType::CONSTRUCTIONSITE) {
876 			bo.type = BuildingObserver::Type::kConstructionsite;
877 			continue;
878 		}
879 	}
880 
881 	// We must verify that some buildings has been identified
882 	// Also note that the AI assumes that some buildings are unique, if you want to
883 	// create e.g. two barracks or bakeries, the impact on the AI must be considered
884 	if (count_buildings_with_attribute(BuildingAttribute::kBarracks) != 1) {
885 		throw wexception("The AI needs the tribe '%s' to define 1 type of barracks building. "
886 		                 "This is the building that produces the tribe's 'soldier' worker.",
887 		                 tribe_->name().c_str());
888 	}
889 	if (count_buildings_with_attribute(BuildingAttribute::kRanger) != 1) {
890 		throw wexception(
891 		   "The AI needs the tribe '%s' to define 1 type of ranger's building. "
892 		   "This is the building that has 'supports_production_of = { \"log\" }' in its AI hints.",
893 		   tribe_->name().c_str());
894 	}
895 	if (count_buildings_with_attribute(BuildingAttribute::kWell) != 1) {
896 		throw wexception(
897 		   "The AI needs the tribe '%s' to define 1 type of well. "
898 		   "This is the building that has 'collects_ware_from_map = \"water\"' in its AI hints.",
899 		   tribe_->name().c_str());
900 	}
901 	if (count_buildings_with_attribute(BuildingAttribute::kLumberjack) != 1) {
902 		throw wexception(
903 		   "The AI needs the tribe '%s' to define 1 type of lumberjack's building. "
904 		   "This is the building that has 'collects_ware_from_map = \"log\"' in its AI hints.",
905 		   tribe_->name().c_str());
906 	}
907 
908 	if (count_buildings_with_attribute(BuildingAttribute::kHunter) != 0 &&
909 	    count_buildings_with_attribute(BuildingAttribute::kHunter) != 1) {
910 		throw wexception(
911 		   "The AI needs the tribe '%s' to define 1 type of hunter's building at the most. "
912 		   "Hunters are buildings that have 'collects_ware_from_map = \"meat\"' in their AI hints.",
913 		   tribe_->name().c_str());
914 	}
915 
916 	if (count_buildings_with_attribute(BuildingAttribute::kFisher) != 1) {
917 		throw wexception(
918 		   "The AI needs the tribe '%s' to define 1 type of fisher's building. "
919 		   "This is the building that has 'collects_ware_from_map = \"fish\"' in its AI hints "
920 		   "and doesn't have any ware inputs.",
921 		   tribe_->name().c_str());
922 	}
923 
924 	// atlanteans they consider water as a resource
925 	// (together with mines, rocks and wood)
926 	if (tribe_->name() == "atlanteans") {
927 		resource_necessity_water_needed_ = true;
928 	}
929 
930 	// Populating taskPool with all AI jobs and their starting times
931 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 0),
932 	                                 SchedulerTaskId::kConstructBuilding, 6,
933 	                                 "construct a building"));
934 	taskPool.push_back(SchedulerTask(
935 	   std::max<uint32_t>(gametime, 1 * 1000), SchedulerTaskId::kRoadCheck, 2, "roads check"));
936 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 15 * 1000),
937 	                                 SchedulerTaskId::kCheckProductionsites, 5,
938 	                                 "productionsites check"));
939 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 30 * 1000),
940 	                                 SchedulerTaskId::kProductionsitesStats, 1,
941 	                                 "productionsites statistics"));
942 	taskPool.push_back(SchedulerTask(
943 	   std::max<uint32_t>(gametime, 30 * 1000), SchedulerTaskId::kCheckMines, 5, "check mines"));
944 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 0 * 1000),
945 	                                 SchedulerTaskId::kCheckMilitarysites, 5,
946 	                                 "check militarysites"));
947 	taskPool.push_back(SchedulerTask(
948 	   std::max<uint32_t>(gametime, 30 * 1000), SchedulerTaskId::kCheckShips, 5, "check ships"));
949 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 1 * 1000),
950 	                                 SchedulerTaskId::kCheckEconomies, 1, "check economies"));
951 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 30 * 1000),
952 	                                 SchedulerTaskId::KMarineDecisions, 5, "marine decisions"));
953 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 2 * 60 * 1000),
954 	                                 SchedulerTaskId::kCheckTrainingsites, 5,
955 	                                 "check training sites"));
956 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 1 * 1000),
957 	                                 SchedulerTaskId::kBbuildableFieldsCheck, 2,
958 	                                 "check buildable fields"));
959 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 1 * 1000),
960 	                                 SchedulerTaskId::kMineableFieldsCheck, 2,
961 	                                 "check mineable fields"));
962 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 1 * 1000),
963 	                                 SchedulerTaskId::kUnbuildableFCheck, 1,
964 	                                 "check unbuildable fields"));
965 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 15 * 60 * 1000),
966 	                                 SchedulerTaskId::kWareReview, 9, "wares review"));
967 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 10 * 60 * 1000),
968 	                                 SchedulerTaskId::kPrintStats, 9, "print statistics"));
969 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 1 * 60 * 1000),
970 	                                 SchedulerTaskId::kCountMilitaryVacant, 2,
971 	                                 "count military vacant"));
972 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 10 * 60 * 1000),
973 	                                 SchedulerTaskId::kCheckEnemySites, 6, "check enemy sites"));
974 	if (ai_training_mode_) {
975 		taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 10 * 1000),
976 		                                 SchedulerTaskId::kManagementUpdate, 8, "reviewing"));
977 	}
978 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 9 * 1000),
979 	                                 SchedulerTaskId::kUpdateStats, 6, "update player stats"));
980 	taskPool.push_back(SchedulerTask(
981 	   std::max<uint32_t>(gametime, 10 * 1000), SchedulerTaskId::kUpdateStats, 15, "review"));
982 
983 	taskPool.push_back(SchedulerTask(std::max<uint32_t>(gametime, 10 * 1000),
984 	                                 SchedulerTaskId::kWarehouseFlagDist, 5,
985 	                                 "Flag-Warehouse Update"));
986 
987 	const Map& map = game().map();
988 
989 	// here we scan entire map for own ships
990 	std::set<OPtr<Ship>> found_ships;
991 	for (int16_t y = 0; y < map.get_height(); ++y) {
992 		for (int16_t x = 0; x < map.get_width(); ++x) {
993 			FCoords f = map.get_fcoords(Coords(x, y));
994 			// there are too many bobs on the map so we investigate
995 			// only bobs on water
996 			if (f.field->nodecaps() & MOVECAPS_SWIM) {
997 				for (Bob* bob = f.field->get_first_bob(); bob; bob = bob->get_next_on_field()) {
998 					if (upcast(Ship, ship, bob)) {
999 						if (ship->get_owner() == player_ && !found_ships.count(ship)) {
1000 							found_ships.insert(ship);
1001 							gain_ship(*ship, NewShip::kFoundOnLoad);
1002 						}
1003 					}
1004 				}
1005 			}
1006 		}
1007 	}
1008 
1009 	// here we scan entire map for owned unused fields and own buildings
1010 	std::set<OPtr<PlayerImmovable>> found_immovables;
1011 	for (int16_t y = 0; y < map.get_height(); ++y) {
1012 		for (int16_t x = 0; x < map.get_width(); ++x) {
1013 			FCoords f = map.get_fcoords(Coords(x, y));
1014 
1015 			if (f.field->get_owned_by() != player_number()) {
1016 				continue;
1017 			}
1018 
1019 			unusable_fields.push_back(f);
1020 
1021 			if (upcast(PlayerImmovable, imm, f.field->get_immovable())) {
1022 				//  Guard by a set - immovables might be on several nodes at once.
1023 				if (&imm->owner() == player_ && !found_immovables.count(imm)) {
1024 					found_immovables.insert(imm);
1025 					gain_immovable(*imm, true);
1026 				}
1027 			}
1028 		}
1029 	}
1030 
1031 	// blocking space consumers vicinity (when reloading a game)
1032 	for (const ProductionSiteObserver& ps_obs : productionsites) {
1033 		if (ps_obs.bo->is(BuildingAttribute::kSpaceConsumer) &&
1034 		    !ps_obs.bo->is(BuildingAttribute::kRanger)) {
1035 			MapRegion<Area<FCoords>> mr(
1036 			   map, Area<FCoords>(map.get_fcoords(ps_obs.site->get_position()), 4));
1037 			do {
1038 				blocked_fields.add(mr.location(), game().get_gametime() + 20 * 60 * 1000);
1039 			} while (mr.advance(map));
1040 		}
1041 	}
1042 
1043 	// getting list of all fields nearby port space
1044 	// TODO(tiborb): it seems port spaces can change over time so ports_vicinity needs to be
1045 	// refreshed from
1046 	// time to time
1047 	for (const Coords& c : map.get_port_spaces()) {
1048 		MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(c), 3));
1049 		do {
1050 			const uint32_t hash = mr.location().hash();
1051 			if (!ports_vicinity.count(hash)) {
1052 				ports_vicinity.insert(hash);
1053 			}
1054 		} while (mr.advance(map));
1055 	}
1056 
1057 	// printing identified basic buildings if we are in the basic economy mode
1058 	basic_economy_established = persistent_data->remaining_basic_buildings.empty();
1059 	if (!basic_economy_established) {
1060 		log("%2d: Initializing in the basic economy mode, required buildings:\n", player_number());
1061 		for (auto bb : persistent_data->remaining_basic_buildings) {
1062 			log("   %3d / %-28s- target %d\n", bb.first, get_building_observer(bb.first).name,
1063 			    bb.second);
1064 		}
1065 	}
1066 
1067 	update_player_stat(gametime);
1068 
1069 	// Initialise the max duration of a single ship's expedition
1070 	const uint32_t map_area = uint32_t(map.get_height()) * map.get_width();
1071 	const uint32_t map_area_root = round(sqrt(map_area));
1072 	int scope = 320 - 64;
1073 	int off = map_area_root - 64;
1074 	if (off < 0) {
1075 		off = 0;
1076 	}
1077 	if (off > scope) {
1078 		off = scope;
1079 	}
1080 	expedition_max_duration =
1081 	   kExpeditionMinDuration +
1082 	   static_cast<double>(off) * (kExpeditionMaxDuration - kExpeditionMinDuration) / scope;
1083 	log(" %d: expedition max duration = %u (%u minutes), map area root: %u\n", player_number(),
1084 	    expedition_max_duration / 1000, expedition_max_duration / kOneMinute, map_area_root);
1085 	assert(expedition_max_duration >= kExpeditionMinDuration);
1086 	assert(expedition_max_duration <= kExpeditionMaxDuration);
1087 
1088 	// Sometimes there can be a ship in expedition, but expedition start time is not given
1089 	// e.g. human player played this player before
1090 	if (expedition_ship_ != kNoShip &&
1091 	    persistent_data->expedition_start_time == Player::AiPersistentState::kNoExpedition) {
1092 		// Current gametime is better then 'Player::AiPersistentState::kNoExpedition'
1093 		persistent_data->expedition_start_time = gametime;
1094 	}
1095 
1096 	productionsites_ratio_ = management_data.get_military_number_at(86) / 10 + 12;
1097 
1098 	// Just to be initialized
1099 	soldier_status_ = SoldiersStatus::kEnough;
1100 	vacant_mil_positions_average_ = 0;
1101 	spots_avail.resize(4);
1102 	trees_nearby_treshold_ = 3 + std::abs(management_data.get_military_number_at(121)) / 2;
1103 	last_road_dismantled_ = 0;
1104 	dead_ends_check_ = true;
1105 }
1106 
1107 /**
1108  * Checks PART of available buildable fields.
1109  *
1110  * this checks about 40-50 buildable fields. In big games, the player can have thousands
1111  * of them, so we rotate the buildable_fields container and check 35 fields, and in addition
1112  * we look for medium & big fields and near border fields if needed.
1113  */
update_all_buildable_fields(const uint32_t gametime)1114 void DefaultAI::update_all_buildable_fields(const uint32_t gametime) {
1115 
1116 	// Every call we try to check first 35 buildable fields
1117 	constexpr uint16_t kMinimalFieldsCheck = 35;
1118 
1119 	uint16_t i = 0;
1120 
1121 	// To be sure we have some info about enemies we might see
1122 	update_player_stat(gametime);
1123 
1124 	// Generally we check fields as they are in the container, but we need also given
1125 	// number of "special" fields. So if given number of fields are not found within
1126 	// "regular" check, we must go on and look also on other fields...
1127 	uint8_t non_small_needed = 4;
1128 	uint8_t near_border_needed = 10;
1129 
1130 	// we test 35 fields that were update more than 1 seconds ago
1131 	while (!buildable_fields.empty() &&
1132 	       i < std::min<uint16_t>(kMinimalFieldsCheck, buildable_fields.size())) {
1133 		BuildableField& bf = *buildable_fields.front();
1134 
1135 		if ((buildable_fields.front()->field_info_expiration - kFieldInfoExpiration + 1000) <=
1136 		    gametime) {
1137 
1138 			//  check whether we lost ownership of the node
1139 			if (bf.coords.field->get_owned_by() != player_number()) {
1140 				delete &bf;
1141 				buildable_fields.pop_front();
1142 				continue;
1143 			}
1144 
1145 			//  check whether we can still construct regular buildings on the node
1146 			if ((player_->get_buildcaps(bf.coords) & BUILDCAPS_SIZEMASK) == 0) {
1147 				unusable_fields.push_back(bf.coords);
1148 				delete &bf;
1149 				buildable_fields.pop_front();
1150 				continue;
1151 			}
1152 
1153 			update_buildable_field(bf);
1154 			if (non_small_needed > 0) {
1155 				int32_t const maxsize = player_->get_buildcaps(bf.coords) & BUILDCAPS_SIZEMASK;
1156 				if (maxsize > 1) {
1157 					--non_small_needed;
1158 				}
1159 			}
1160 			if (near_border_needed > 0) {
1161 				if (bf.near_border) {
1162 					--near_border_needed;
1163 				}
1164 			}
1165 		}
1166 		bf.field_info_expiration = gametime + kFieldInfoExpiration;
1167 		buildable_fields.push_back(&bf);
1168 		buildable_fields.pop_front();
1169 
1170 		++i;
1171 	}
1172 
1173 	// If needed we iterate once more and look for 'special' fields
1174 	// starting in the middle of buildable_fields to skip fields tested lately
1175 	// But not doing this if the count of buildable fields is too low
1176 	// (no need to bother)
1177 	if (buildable_fields.size() < kMinimalFieldsCheck * 3) {
1178 		return;
1179 	}
1180 
1181 	for (uint32_t j = buildable_fields.size() / 2; j < buildable_fields.size(); j++) {
1182 		// If we dont need to iterate (anymore) ...
1183 		if (non_small_needed + near_border_needed == 0) {
1184 			break;
1185 		}
1186 
1187 		// Skip if the field is not ours or was updated lately
1188 		if (buildable_fields[j]->coords.field->get_owned_by() != player_number()) {
1189 			continue;
1190 		}
1191 		// We are not interested in fields where info has expired less than 20s ago
1192 		if (buildable_fields[j]->field_info_expiration + 20000 > gametime) {
1193 			continue;
1194 		}
1195 
1196 		// Continue if field is blocked at the moment
1197 		if (blocked_fields.is_blocked(buildable_fields[j]->coords)) {
1198 			continue;
1199 		}
1200 
1201 		// Few constants to keep the code cleaner
1202 		const int32_t field_maxsize =
1203 		   player_->get_buildcaps(buildable_fields[j]->coords) & BUILDCAPS_SIZEMASK;
1204 		const bool field_near_border = buildable_fields[j]->near_border;
1205 
1206 		// Let decide if we need to update and for what reason
1207 		const bool update_due_size = non_small_needed && field_maxsize > 1;
1208 		const bool update_due_border = near_border_needed && field_near_border;
1209 
1210 		if (!(update_due_size || update_due_border)) {
1211 			continue;
1212 		}
1213 
1214 		// decreasing the counters
1215 		if (update_due_size) {
1216 			assert(non_small_needed > 0);
1217 			--non_small_needed;
1218 		}
1219 		if (update_due_border) {
1220 			assert(near_border_needed > 0);
1221 			--near_border_needed;
1222 		}
1223 
1224 		// and finnaly update the buildable field
1225 		update_buildable_field(*buildable_fields[j]);
1226 		buildable_fields[j]->field_info_expiration = gametime + kFieldInfoExpiration;
1227 	}
1228 }
1229 
1230 /**
1231  * Checks ALL available mineable fields.
1232  *
1233  * this shouldn't be used often, as it might hang the game for some 100
1234  * milliseconds if the area the computer owns is big.
1235  */
update_all_mineable_fields(const uint32_t gametime)1236 void DefaultAI::update_all_mineable_fields(const uint32_t gametime) {
1237 
1238 	uint16_t i = 0;  // counter, used to track # of checked fields
1239 
1240 	// we test 30 fields that were updated more than 1 seconds ago
1241 	// to avoid re-test of the same field twice
1242 	while (!mineable_fields.empty() &&
1243 	       (mineable_fields.front()->field_info_expiration - kMineFieldInfoExpiration + 1000) <=
1244 	          gametime &&
1245 	       i < 30) {
1246 		MineableField* mf = mineable_fields.front();
1247 
1248 		//  check whether we lost ownership of the node
1249 		if (mf->coords.field->get_owned_by() != player_number()) {
1250 			delete mf;
1251 			mineable_fields.pop_front();
1252 			continue;
1253 		}
1254 
1255 		//  check whether we can still construct regular buildings on the node
1256 		if ((player_->get_buildcaps(mf->coords) & BUILDCAPS_MINE) == 0) {
1257 			unusable_fields.push_back(mf->coords);
1258 			delete mf;
1259 			mineable_fields.pop_front();
1260 			continue;
1261 		}
1262 
1263 		update_mineable_field(*mf);
1264 		mf->field_info_expiration = gametime + kMineFieldInfoExpiration;
1265 		mineable_fields.push_back(mf);
1266 		mineable_fields.pop_front();
1267 
1268 		++i;
1269 	}
1270 	// Updating overall statistics, first we flush the data and then iterate over all mine fields
1271 	// ignoring fields that are blocked usually because they are not accessible
1272 	mine_fields_stat.zero();
1273 	for (const auto& mineable_field : mineable_fields) {
1274 		if (mineable_field->coords.field->get_resources_amount() > 0 &&
1275 		    !blocked_fields.is_blocked(mineable_field->coords)) {
1276 			mine_fields_stat.add(mineable_field->coords.field->get_resources());
1277 		}
1278 	}
1279 
1280 	// Following asserts presume that there are 1-3 critical mines
1281 	if (mine_fields_stat.count_types() == kMineTypes) {
1282 		assert(mine_fields_stat.has_critical_ore_fields());
1283 	}
1284 	if (mine_fields_stat.count_types() == 0) {
1285 		assert(!mine_fields_stat.has_critical_ore_fields());
1286 	}
1287 }
1288 
1289 /**
1290  * Checks up to 50 fields that weren't buildable the last time.
1291  *
1292  * milliseconds if the area the computer owns is big.
1293  */
update_all_not_buildable_fields()1294 void DefaultAI::update_all_not_buildable_fields() {
1295 	int32_t const pn = player_number();
1296 
1297 	// We are checking at least 5 unusable fields (or less if there are not 5 of them)
1298 	// at once, but not more then 200...
1299 	// The idea is to check each field at least once a minute, of course with big maps
1300 	// it will take longer
1301 	uint32_t maxchecks = unusable_fields.size();
1302 	if (maxchecks > 5) {
1303 		maxchecks = std::min<uint32_t>(5 + (unusable_fields.size() - 5) / 15, 200);
1304 	}
1305 
1306 	for (uint32_t i = 0; i < maxchecks; ++i) {
1307 		//  check whether we lost ownership of the node
1308 		if (unusable_fields.front().field->get_owned_by() != pn) {
1309 			unusable_fields.pop_front();
1310 			continue;
1311 		}
1312 
1313 		// check whether building capabilities have improved
1314 		if (player_->get_buildcaps(unusable_fields.front()) & BUILDCAPS_SIZEMASK) {
1315 			buildable_fields.push_back(new BuildableField(unusable_fields.front()));
1316 			unusable_fields.pop_front();
1317 			update_buildable_field(*buildable_fields.back());
1318 			continue;
1319 		}
1320 
1321 		if (player_->get_buildcaps(unusable_fields.front()) & BUILDCAPS_MINE) {
1322 			mineable_fields.push_back(new MineableField(unusable_fields.front()));
1323 			unusable_fields.pop_front();
1324 			update_mineable_field(*mineable_fields.back());
1325 			continue;
1326 		}
1327 
1328 		unusable_fields.push_back(unusable_fields.front());
1329 		unusable_fields.pop_front();
1330 	}
1331 }
1332 
1333 /// Updates one buildable field
update_buildable_field(BuildableField & field)1334 void DefaultAI::update_buildable_field(BuildableField& field) {
1335 	// look if there is any unowned land nearby
1336 	const Map& map = game().map();
1337 	const uint32_t gametime = game().get_gametime();
1338 	FindNodeUnownedWalkable find_unowned_walkable(player_, game());
1339 	FindEnemyNodeWalkable find_enemy_owned_walkable(player_, game());
1340 	FindNodeUnownedBuildable find_unowned_buildable(player_, game());
1341 	FindNodeUnownedMineable find_unowned_mines_pots(player_, game());
1342 	FindNodeUnownedMineable find_unowned_iron_mines(player_, game(), iron_resource_id);
1343 	FindNodeAllyOwned find_ally(player_, game(), player_number());
1344 	PlayerNumber const pn = player_->player_number();
1345 	const World& world = game().world();
1346 
1347 	constexpr uint16_t kProductionArea = 6;
1348 	constexpr uint16_t kBuildableSpotsCheckArea = 10;
1349 	constexpr uint16_t kEnemyCheckArea = 16;
1350 	const uint16_t ms_enemy_check_area =
1351 	   kEnemyCheckArea + std::abs(management_data.get_military_number_at(75)) / 10;
1352 	constexpr uint16_t kDistantResourcesArea = 20;
1353 
1354 	uint16_t actual_enemy_check_area = kEnemyCheckArea;
1355 	field.is_militarysite = false;
1356 	if (field.coords.field->get_immovable()) {
1357 		if (field.coords.field->get_immovable()->descr().type() ==
1358 		    Widelands::MapObjectType::MILITARYSITE) {
1359 			field.is_militarysite = true;
1360 			actual_enemy_check_area = ms_enemy_check_area;
1361 		}
1362 	}
1363 
1364 	field.unowned_land_nearby = map.find_fields(
1365 	   game(), Area<FCoords>(field.coords, actual_enemy_check_area), nullptr, find_unowned_walkable);
1366 
1367 	field.enemy_owned_land_nearby =
1368 	   map.find_fields(game(), Area<FCoords>(field.coords, actual_enemy_check_area), nullptr,
1369 	                   find_enemy_owned_walkable);
1370 
1371 	field.nearest_buildable_spot_nearby = std::numeric_limits<uint16_t>::max();
1372 	field.unowned_buildable_spots_nearby = 0;
1373 	field.unowned_portspace_vicinity_nearby = 0;
1374 	if (field.unowned_land_nearby > 0 ||
1375 	    (field.enemy_owned_land_nearby > 0 &&
1376 	     field.enemy_military_presence <
1377 	        std::abs(management_data.get_military_number_at(174)) / 10)) {
1378 		std::vector<Coords> found_buildable_fields;
1379 
1380 		// first looking for unowned buildable spots
1381 		field.unowned_buildable_spots_nearby =
1382 		   map.find_fields(game(), Area<FCoords>(field.coords, kBuildableSpotsCheckArea),
1383 		                   &found_buildable_fields, find_unowned_buildable);
1384 		field.unowned_buildable_spots_nearby +=
1385 		   map.find_fields(game(), Area<FCoords>(field.coords, kBuildableSpotsCheckArea),
1386 		                   &found_buildable_fields, find_enemy_owned_walkable);
1387 		// Now iterate over fields to collect statistics
1388 		for (auto& coords : found_buildable_fields) {
1389 			// We are not interested in blocked fields
1390 			if (blocked_fields.is_blocked(coords)) {
1391 				continue;
1392 			}
1393 			// And now looking for nearest field
1394 			const uint32_t cur_distance = map.calc_distance(coords, field.coords);
1395 			if (cur_distance < field.nearest_buildable_spot_nearby) {
1396 				field.nearest_buildable_spot_nearby = cur_distance;
1397 			}
1398 		}
1399 
1400 		// now looking for unowned_portspace_vicinity_nearby
1401 		MapRegion<Area<FCoords>> mr(map, Area<FCoords>(field.coords, kBuildableSpotsCheckArea));
1402 		do {
1403 
1404 			if (mr.location().field->get_owned_by() == 0 &&
1405 			    ports_vicinity.count(mr.location().hash()) > 0) {
1406 				++field.unowned_portspace_vicinity_nearby;
1407 			}
1408 		} while (mr.advance(map));
1409 	}
1410 
1411 	// Is this near the border? Get rid of fields owned by ally
1412 	if (map.find_fields(game(), Area<FCoords>(field.coords, 3), nullptr, find_ally) ||
1413 	    map.find_fields(game(), Area<FCoords>(field.coords, 3), nullptr, find_unowned_walkable)) {
1414 		field.near_border = true;
1415 	} else {
1416 		field.near_border = false;
1417 	}
1418 
1419 	// are we going to count resources now?
1420 	static bool resource_count_now = false;
1421 	resource_count_now = false;
1422 	// Testing in first 10 seconds or if last testing was more then 60 sec ago
1423 	if (field.last_resources_check_time < 10000 ||
1424 	    field.last_resources_check_time - gametime > 60 * 1000) {
1425 		resource_count_now = true;
1426 		field.last_resources_check_time = gametime;
1427 	}
1428 
1429 	// testing mines
1430 	if (resource_count_now) {
1431 		uint32_t close_mines = map.find_fields(
1432 		   game(), Area<FCoords>(field.coords, kProductionArea), nullptr, find_unowned_mines_pots);
1433 		uint32_t distant_mines =
1434 		   map.find_fields(game(), Area<FCoords>(field.coords, kDistantResourcesArea), nullptr,
1435 
1436 		                   find_unowned_mines_pots);
1437 		distant_mines = distant_mines - close_mines;
1438 		field.unowned_mines_spots_nearby = 4 * close_mines + distant_mines / 2;
1439 		if (distant_mines > 0) {
1440 			field.unowned_mines_spots_nearby += 15;
1441 		}
1442 		if (field.unowned_mines_spots_nearby > 0 &&
1443 		    // for performance considerations we count iron nodes only if we have less than 2 iron
1444 		    // mines now...
1445 		    mines_per_type[iron_resource_id].total_count() <= 1) {
1446 			// counting iron mines, if we have less than two iron mines
1447 			field.unowned_iron_mines_nearby =
1448 			   map.find_fields(game(), Area<FCoords>(field.coords, kDistantResourcesArea), nullptr,
1449 			                   find_unowned_iron_mines);
1450 		} else {
1451 			field.unowned_iron_mines_nearby = 0;
1452 		}
1453 	}
1454 
1455 	// identifying portspace fields
1456 	if (player_->get_buildcaps(field.coords) & BUILDCAPS_PORT) {
1457 		field.is_portspace = ExtendedBool::kTrue;
1458 	} else {
1459 		field.is_portspace = ExtendedBool::kFalse;
1460 	}
1461 
1462 	// testing for near portspaces
1463 	if (ports_vicinity.count(field.coords.hash()) > 0) {
1464 		field.portspace_nearby = ExtendedBool::kTrue;
1465 	} else {
1466 		field.portspace_nearby = ExtendedBool::kFalse;
1467 	}
1468 
1469 	// testing if a port is nearby, such field will get a priority boost
1470 	if (resource_count_now) {  // misusing a bit
1471 		uint16_t nearest_distance = std::numeric_limits<uint16_t>::max();
1472 		for (const WarehouseSiteObserver& wh_obs : warehousesites) {
1473 			if (wh_obs.bo->is(BuildingAttribute::kPort)) {
1474 				const uint16_t actual_distance =
1475 				   map.calc_distance(field.coords, wh_obs.site->get_position());
1476 				nearest_distance = std::min(nearest_distance, actual_distance);
1477 			}
1478 		}
1479 		if (nearest_distance < 15) {
1480 			field.port_nearby = true;
1481 		} else {
1482 			field.port_nearby = false;
1483 		}
1484 	}
1485 
1486 	// testing fields in radius 1 to find biggest buildcaps.
1487 	// This is to calculate capacity that will be lost if something is
1488 	// built here
1489 	field.max_buildcap_nearby = 0;
1490 	MapRegion<Area<FCoords>> mr(map, Area<FCoords>(field.coords, 1));
1491 	do {
1492 		if ((player_->get_buildcaps(mr.location()) & BUILDCAPS_SIZEMASK) >
1493 		    field.max_buildcap_nearby) {
1494 			field.max_buildcap_nearby = player_->get_buildcaps(mr.location()) & BUILDCAPS_SIZEMASK;
1495 		}
1496 	} while (mr.advance(map));
1497 
1498 	assert((player_->get_buildcaps(field.coords) & BUILDCAPS_SIZEMASK) <= field.max_buildcap_nearby);
1499 
1500 	// Testing surface water (once only)
1501 	// TODO(GunChleoc): We can change the terrain by scripting, so we should work with notifications
1502 	// here.
1503 	// Let's leave this as it is for now for performance reasons - terrain change of water is
1504 	// currently only
1505 	// used in the Atlantean scenario.
1506 	if (field.water_nearby == kUncalculated) {
1507 		assert(field.open_water_nearby == kUncalculated);
1508 
1509 		FindNodeWater find_water(game().world());
1510 		field.water_nearby =
1511 		   map.find_fields(game(), Area<FCoords>(field.coords, kProductionArea), nullptr, find_water);
1512 
1513 		if (field.water_nearby > 0) {
1514 			FindNodeOpenWater find_open_water(game().world());
1515 			field.open_water_nearby = map.find_fields(
1516 			   game(), Area<FCoords>(field.coords, kProductionArea), nullptr, find_open_water);
1517 		}
1518 
1519 		if (resource_necessity_water_needed_) {  // for atlanteans
1520 			field.distant_water =
1521 			   map.find_fields(
1522 			      game(), Area<FCoords>(field.coords, kDistantResourcesArea), nullptr, find_water) -
1523 			   field.water_nearby;
1524 			assert(field.open_water_nearby <= field.water_nearby);
1525 		}
1526 	}
1527 
1528 	FCoords fse;
1529 	map.get_neighbour(field.coords, WALK_SE, &fse);
1530 	field.preferred = false;
1531 	if (BaseImmovable const* const imm = fse.field->get_immovable()) {
1532 		if (dynamic_cast<Flag const*>(imm) ||
1533 		    (dynamic_cast<Road const*>(imm) && (fse.field->nodecaps() & BUILDCAPS_FLAG))) {
1534 			field.preferred = true;
1535 		}
1536 	}
1537 
1538 	// counting fields with fish, doing it roughly every 10-th minute is enough
1539 	if (field.water_nearby > 0 &&
1540 	    (field.fish_nearby == kUncalculated || (resource_count_now && gametime % 10 == 0))) {
1541 		CheckStepWalkOn fisher_cstep(MOVECAPS_WALK, true);
1542 		static std::vector<Coords> fish_fields_list;  // pity this contains duplicates
1543 		fish_fields_list.clear();
1544 		map.find_reachable_fields(game(), Area<FCoords>(field.coords, kProductionArea),
1545 		                          &fish_fields_list, fisher_cstep,
1546 		                          FindNodeResource(world.resource_index("fish")));
1547 
1548 		// This is "list" of unique fields in fish_fields_list we got above
1549 		static std::set<Coords> counted_fields;
1550 		counted_fields.clear();
1551 		field.fish_nearby = 0;
1552 		for (auto fish_coords : fish_fields_list) {
1553 			if (counted_fields.insert(fish_coords).second) {
1554 				field.fish_nearby += map.get_fcoords(fish_coords).field->get_resources_amount();
1555 			}
1556 		}
1557 	}
1558 
1559 	// Counting resources that do not change fast
1560 	if (resource_count_now) {
1561 		// Counting fields with critters (game)
1562 		field.critters_nearby = map.find_bobs(
1563 		   game(), Area<FCoords>(field.coords, kProductionArea), nullptr, FindBobCritter());
1564 
1565 		// Rocks are not renewable, we will count them only if previous state is nonzero
1566 		if (field.rocks_nearby > 0) {
1567 			field.rocks_nearby = map.find_immovables(
1568 			   game(), Area<FCoords>(map.get_fcoords(field.coords), kProductionArea), nullptr,
1569 			   FindImmovableAttribute(MapObjectDescr::get_attribute_id("rocks")));
1570 
1571 			// adding 5 if rocks found
1572 			field.rocks_nearby = (field.rocks_nearby > 0) ? field.rocks_nearby + 2 : 0;
1573 		}
1574 
1575 		// ground water is not renewable and its amount can only fall, we will count them only if
1576 		// previous state is nonzero
1577 		if (field.ground_water > 0) {
1578 			field.ground_water = field.coords.field->get_resources_amount();
1579 		}
1580 
1581 		// Counting trees nearby
1582 		int32_t const tree_attr = MapObjectDescr::get_attribute_id("tree");
1583 		field.trees_nearby =
1584 		   map.find_immovables(game(), Area<FCoords>(map.get_fcoords(field.coords), kProductionArea),
1585 		                       nullptr, FindImmovableAttribute(tree_attr));
1586 
1587 		// Counting bushes nearby
1588 		int32_t const bush_attr = MapObjectDescr::get_attribute_id("ripe_bush");
1589 		field.bushes_nearby =
1590 		   map.find_immovables(game(), Area<FCoords>(map.get_fcoords(field.coords), kProductionArea),
1591 		                       nullptr, FindImmovableAttribute(bush_attr));
1592 	}
1593 
1594 	// resetting some values
1595 	field.enemy_nearby =
1596 	   (field.enemy_owned_land_nearby > std::abs(management_data.get_military_number_at(41) / 4)) ?
1597 	      true :
1598 	      false;
1599 	if (field.enemy_owned_land_nearby == 0) {
1600 		assert(!field.enemy_nearby);
1601 	}
1602 
1603 	// resetting a bunch of values for the field
1604 	field.ally_military_presence = 0;
1605 	field.area_military_capacity = 0;
1606 	field.consumers_nearby.clear();
1607 	field.consumers_nearby.resize(wares.size());
1608 	field.enemy_military_presence = 0;
1609 	field.enemy_military_sites = 0;
1610 	field.enemy_wh_nearby = false;
1611 	field.military_in_constr_nearby = 0;
1612 	field.military_loneliness = 1000;
1613 	field.military_stationed = 0;
1614 	field.military_unstationed = 0;
1615 	field.own_military_presence = 0;
1616 	field.own_non_military_nearby = 0;
1617 	field.producers_nearby.clear();
1618 	field.collecting_producers_nearby.clear();
1619 	field.producers_nearby.resize(wares.size());
1620 	field.collecting_producers_nearby.resize(wares.size());
1621 	field.rangers_nearby = 0;
1622 	field.space_consumers_nearby = 0;
1623 	field.supporters_nearby.clear();
1624 	field.supporters_nearby.resize(wares.size());
1625 	field.unconnected_nearby = false;
1626 
1627 	// collect information about productionsites nearby
1628 	static std::vector<ImmovableFound> immovables;
1629 	immovables.reserve(50);
1630 	immovables.clear();
1631 	// Search in a radius of range
1632 	map.find_immovables(game(), Area<FCoords>(field.coords, kProductionArea + 2), &immovables);
1633 
1634 	// function seems to return duplicates, so we will use serial numbers to filter them out
1635 	static std::set<uint32_t> unique_serials;
1636 	unique_serials.clear();
1637 
1638 	for (uint32_t i = 0; i < immovables.size(); ++i) {
1639 		const BaseImmovable& base_immovable = *immovables.at(i).object;
1640 		if (!unique_serials.insert(base_immovable.serial()).second) {
1641 			continue;  // serial was not inserted in the set, so this is a duplicate
1642 		}
1643 
1644 		if (upcast(PlayerImmovable const, player_immovable, &base_immovable)) {
1645 
1646 			// TODO(unknown): Only continue if this is an opposing site
1647 			// allied sites should be counted for military influence
1648 			if (player_immovable->owner().player_number() != pn) {
1649 				continue;
1650 			}
1651 			// here we identify the buiding (including expected building if constructionsite)
1652 			// and calculate some statistics about nearby buildings
1653 			if (player_immovable->descr().type() == MapObjectType::PRODUCTIONSITE) {
1654 				BuildingObserver& bo = get_building_observer(player_immovable->descr().name().c_str());
1655 				consider_productionsite_influence(field, immovables.at(i).coords, bo);
1656 			} else if (upcast(ConstructionSite const, constructionsite, player_immovable)) {
1657 				const BuildingDescr& target_descr = constructionsite->building();
1658 				BuildingObserver& bo = get_building_observer(target_descr.name().c_str());
1659 				consider_productionsite_influence(field, immovables.at(i).coords, bo);
1660 			}
1661 		}
1662 	}
1663 
1664 	// Now testing military aspects
1665 	immovables.clear();
1666 	map.find_immovables(game(), Area<FCoords>(field.coords, actual_enemy_check_area), &immovables);
1667 
1668 	// We are interested in unconnected immovables, but we must be also close to connected ones
1669 	static bool any_connected_imm = false;
1670 	any_connected_imm = false;
1671 	static bool any_unconnected_imm = false;
1672 	any_unconnected_imm = false;
1673 	unique_serials.clear();
1674 
1675 	for (uint32_t i = 0; i < immovables.size(); ++i) {
1676 		const BaseImmovable& base_immovable = *immovables.at(i).object;
1677 
1678 		if (!unique_serials.insert(base_immovable.serial()).second) {
1679 			continue;  // serial was not inserted in the set, so this is duplicate
1680 		}
1681 
1682 		// testing if immovable is owned by someone else and collecting some statistics
1683 		if (upcast(Building const, building, &base_immovable)) {
1684 
1685 			const PlayerNumber bpn = building->owner().player_number();
1686 			if (player_statistics.get_is_enemy(bpn)) {  // owned by enemy
1687 				assert(!player_statistics.players_in_same_team(bpn, pn));
1688 				field.enemy_nearby = true;
1689 				if (upcast(MilitarySite const, militarysite, building)) {
1690 					field.enemy_military_presence +=
1691 					   militarysite->soldier_control()->stationed_soldiers().size();
1692 					++field.enemy_military_sites;
1693 				}
1694 				if (upcast(ConstructionSite const, constructionsite, building)) {
1695 					const BuildingDescr& target_descr = constructionsite->building();
1696 					if (target_descr.type() == MapObjectType::MILITARYSITE) {
1697 						++field.enemy_military_sites;
1698 					}
1699 				}
1700 
1701 				// Warehouses are counted here too as they can host soldiers as well
1702 				if (upcast(Warehouse const, warehouse, building)) {
1703 					field.enemy_military_presence +=
1704 					   warehouse->soldier_control()->stationed_soldiers().size();
1705 					++field.enemy_military_sites;
1706 					field.enemy_wh_nearby = true;
1707 					enemy_warehouses.insert(building->get_position().hash());
1708 				}
1709 				continue;
1710 			} else if (bpn != pn) {  // it is an ally
1711 				assert(!player_statistics.get_is_enemy(bpn));
1712 				if (upcast(MilitarySite const, militarysite, building)) {
1713 					field.ally_military_presence +=
1714 					   militarysite->soldier_control()->stationed_soldiers().size();
1715 				}
1716 				continue;
1717 			}
1718 
1719 			// if we are here, the immovable is ours
1720 			assert(building->owner().player_number() == pn);
1721 
1722 			// connected to a warehouse
1723 			// TODO(Nordfriese): Someone should update the code since the big economy splitting for the
1724 			// ferries
1725 			bool connected = !building->get_economy(wwWORKER)->warehouses().empty();
1726 			if (connected) {
1727 				any_connected_imm = true;
1728 			}
1729 
1730 			if (upcast(ConstructionSite const, constructionsite, building)) {
1731 				const BuildingDescr& target_descr = constructionsite->building();
1732 
1733 				if (upcast(MilitarySiteDescr const, target_ms_d, &target_descr)) {
1734 					const int32_t dist = map.calc_distance(field.coords, immovables.at(i).coords);
1735 					const int32_t radius = target_ms_d->get_conquers() + 4;
1736 
1737 					if (radius > dist) {
1738 						field.area_military_capacity += target_ms_d->get_max_number_of_soldiers() / 2 + 1;
1739 						if (field.coords != immovables.at(i).coords) {
1740 							field.military_loneliness *= static_cast<double_t>(dist) / radius;
1741 						}
1742 						++field.military_in_constr_nearby;
1743 					}
1744 				}
1745 			} else if (!connected) {
1746 				// we don't care about unconnected constructionsites
1747 				any_unconnected_imm = true;
1748 			}
1749 
1750 			if (upcast(MilitarySite const, militarysite, building)) {
1751 				const int32_t dist = map.calc_distance(field.coords, immovables.at(i).coords);
1752 				const int32_t radius = militarysite->descr().get_conquers() + 4;
1753 
1754 				if (radius > dist) {
1755 					field.area_military_capacity +=
1756 					   militarysite->soldier_control()->max_soldier_capacity();
1757 					field.own_military_presence +=
1758 					   militarysite->soldier_control()->stationed_soldiers().size();
1759 
1760 					if (militarysite->soldier_control()->stationed_soldiers().empty()) {
1761 						++field.military_unstationed;
1762 					} else {
1763 						++field.military_stationed;
1764 					}
1765 
1766 					if (field.coords != immovables.at(i).coords) {
1767 						field.military_loneliness *= static_cast<double_t>(dist) / radius;
1768 					}
1769 				}
1770 			} else {
1771 				++field.own_non_military_nearby;
1772 			}
1773 		}
1774 	}
1775 
1776 	assert(field.military_loneliness <= 1000);
1777 
1778 	if (any_unconnected_imm && any_connected_imm && field.military_in_constr_nearby == 0) {
1779 		field.unconnected_nearby = true;
1780 	}
1781 
1782 	// if there is a militarysite on the field, we try to walk to enemy
1783 	field.enemy_accessible_ = false;
1784 	field.local_soldier_capacity = 0;
1785 	if (field.is_militarysite) {
1786 		if (upcast(MilitarySite, ms, field.coords.field->get_immovable())) {
1787 			if (field.enemy_nearby) {
1788 				uint32_t unused1 = 0;
1789 				uint16_t unused2 = 0;
1790 				field.enemy_accessible_ = other_player_accessible(
1791 				   actual_enemy_check_area + 3, &unused1, &unused2, field.coords, WalkSearch::kEnemy);
1792 			}
1793 			field.local_soldier_capacity = ms->soldier_control()->max_soldier_capacity();
1794 			field.is_militarysite = true;
1795 		} else {
1796 			NEVER_HERE();
1797 		}
1798 	}
1799 
1800 	// Calculating field score
1801 	field.military_score_ = 0;
1802 	field.inland = false;
1803 
1804 	if (!(field.enemy_nearby || field.near_border)) {
1805 		field.inland = true;
1806 	}
1807 
1808 	const uint8_t score_parts_size = 69;
1809 	int32_t score_parts[score_parts_size] = {0};
1810 	if (field.enemy_owned_land_nearby) {
1811 		score_parts[0] = 3 *
1812 		                 management_data.neuron_pool[73].get_result_safe(
1813 		                    field.enemy_owned_land_nearby / 5, kAbsValue);
1814 		score_parts[1] =
1815 		   3 *
1816 		   management_data.neuron_pool[76].get_result_safe(field.enemy_owned_land_nearby, kAbsValue);
1817 		score_parts[2] = 3 *
1818 		                 management_data.neuron_pool[54].get_result_safe(
1819 		                    field.enemy_military_presence * 2, kAbsValue);
1820 		score_parts[3] = 3 *
1821 		                 management_data.neuron_pool[61].get_result_safe(
1822 		                    field.enemy_military_presence / 3, kAbsValue);
1823 		score_parts[4] =
1824 		   (!field.enemy_accessible_) ? (-100 + management_data.get_military_number_at(55)) : 0;
1825 		score_parts[5] =
1826 		   2 *
1827 		   management_data.neuron_pool[50].get_result_safe(field.enemy_owned_land_nearby, kAbsValue);
1828 
1829 		score_parts[6] =
1830 		   field.enemy_military_sites * std::abs(management_data.get_military_number_at(67) / 2);
1831 		score_parts[7] =
1832 		   2 *
1833 		   management_data.neuron_pool[34].get_result_safe(field.enemy_military_sites * 2, kAbsValue);
1834 		score_parts[8] = management_data.neuron_pool[56].get_result_safe(
1835 		   field.enemy_military_presence * 2, kAbsValue);
1836 
1837 		score_parts[9] = management_data.neuron_pool[65].get_result_safe(
1838 		   (field.unowned_land_nearby + field.enemy_owned_land_nearby) / 2, kAbsValue);
1839 		score_parts[10] = (field.enemy_accessible_) ? management_data.get_military_number_at(80) : 0;
1840 
1841 		score_parts[11] =
1842 		   -3 *
1843 		   management_data.neuron_pool[8].get_result_safe(
1844 		      (field.military_in_constr_nearby + field.military_unstationed) * 3, kAbsValue);
1845 		score_parts[12] =
1846 		   -3 *
1847 		   management_data.neuron_pool[74].get_result_safe(
1848 		      (field.military_in_constr_nearby + field.military_unstationed) * 5, kAbsValue);
1849 		score_parts[13] = ((field.military_in_constr_nearby + field.military_unstationed) > 0) ?
1850 		                     -std::abs(management_data.get_military_number_at(32)) :
1851 		                     0;
1852 		score_parts[14] = -1 * (field.military_in_constr_nearby + field.military_unstationed) *
1853 		                  std::abs(management_data.get_military_number_at(12));
1854 
1855 		score_parts[15] =
1856 		   -2 * management_data.neuron_pool[75].get_result_safe(field.own_military_presence);
1857 		score_parts[16] = -5 * std::min<int16_t>(field.area_military_capacity, 20);
1858 		score_parts[17] = 3 * management_data.get_military_number_at(28);
1859 		score_parts[18] =
1860 		   (field.enemy_nearby) ? 3 * std::abs(management_data.get_military_number_at(68)) : 0;
1861 		score_parts[19] =
1862 		   (field.enemy_wh_nearby) ? 3 * std::abs(management_data.get_military_number_at(132)) : 0;
1863 		score_parts[64] = (field.enemy_wh_nearby) ?
1864 		                     std::abs(management_data.get_military_number_at(135)) :
1865 		                     -std::abs(management_data.get_military_number_at(135));
1866 
1867 	} else {  // for expansion or inner land
1868 
1869 		score_parts[20] = management_data.neuron_pool[22].get_result_safe(
1870 		   (field.unowned_mines_spots_nearby + 2) / 3, kAbsValue);
1871 		score_parts[21] = (field.unowned_mines_spots_nearby > 0) ?
1872 		                     std::abs(management_data.get_military_number_at(58)) :
1873 		                     0;
1874 		if (expansion_type.get_expansion_type() == ExpansionMode::kResources) {
1875 			score_parts[23] = 2 *
1876 			                  management_data.neuron_pool[78].get_result_safe(
1877 			                     (field.unowned_mines_spots_nearby + 2) / 3, kAbsValue);
1878 		}
1879 
1880 		score_parts[24] =
1881 		   (field.unowned_land_nearby) ?
1882 		      management_data.neuron_pool[25].get_result_safe(field.water_nearby / 2, kAbsValue) :
1883 		      0;
1884 		score_parts[25] =
1885 		   (field.unowned_land_nearby) ?
1886 		      management_data.neuron_pool[27].get_result_safe(field.trees_nearby / 2, kAbsValue) :
1887 		      0;
1888 
1889 		if (resource_necessity_water_needed_) {
1890 			score_parts[26] =
1891 			   (field.unowned_land_nearby) ?
1892 			      management_data.neuron_pool[15].get_result_safe(field.water_nearby, kAbsValue) :
1893 			      0;
1894 			score_parts[27] =
1895 			   resource_necessity_water_needed_ *
1896 			   management_data.neuron_pool[17].get_result_safe(field.distant_water, kAbsValue) / 100;
1897 		}
1898 		score_parts[28] =
1899 		   (field.unowned_land_nearby) ?
1900 		      management_data.neuron_pool[33].get_result_safe(field.water_nearby, kAbsValue) :
1901 		      0;
1902 		score_parts[29] =
1903 		   management_data.neuron_pool[10].get_result_safe(field.military_loneliness / 50, kAbsValue);
1904 
1905 		score_parts[30] =
1906 		   -10 *
1907 		   management_data.neuron_pool[8].get_result_safe(
1908 		      3 * (field.military_in_constr_nearby + field.military_unstationed), kAbsValue);
1909 		score_parts[31] =
1910 		   -10 *
1911 		   management_data.neuron_pool[31].get_result_safe(
1912 		      3 * (field.military_in_constr_nearby + field.military_unstationed), kAbsValue);
1913 		score_parts[32] = -4 * field.military_in_constr_nearby *
1914 		                  std::abs(management_data.get_military_number_at(82));
1915 		score_parts[33] = (field.military_in_constr_nearby > 0) ?
1916 		                     -5 * management_data.get_military_number_at(85) :
1917 		                     0;
1918 
1919 		score_parts[34] = -1 *
1920 		                  management_data.neuron_pool[4].get_result_safe(
1921 		                     (field.area_military_capacity + 4) / 5, kAbsValue);
1922 		score_parts[35] = 3 * management_data.get_military_number_at(133);
1923 
1924 		if (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) {
1925 			score_parts[36] = -100 - 4 * std::abs(management_data.get_military_number_at(139));
1926 		} else if (expansion_type.get_expansion_type() == ExpansionMode::kResources ||
1927 		           expansion_type.get_expansion_type() == ExpansionMode::kSpace) {
1928 			score_parts[37] =
1929 			   +100 + 4 * std::abs(management_data.get_military_number_at(139));  // The same as above
1930 		}
1931 		if (msites_in_constr() > 0 && field.max_buildcap_nearby == BUILDCAPS_BIG &&
1932 		    spots_avail.at(BUILDCAPS_BIG) <= 2) {
1933 			score_parts[65] = -10 * std::abs(management_data.get_military_number_at(54));
1934 		}
1935 	}
1936 
1937 	// common inputs
1938 	if (field.unowned_iron_mines_nearby > 0 && mines_per_type[iron_resource_id].total_count() == 0) {
1939 		score_parts[40] = field.unowned_iron_mines_nearby *
1940 		                  std::abs(management_data.get_military_number_at(92)) / 50;
1941 	}
1942 	if (field.unowned_iron_mines_nearby && mines_per_type[iron_resource_id].total_count() <= 1) {
1943 		score_parts[41] = 3 * std::abs(management_data.get_military_number_at(93));
1944 	}
1945 
1946 	score_parts[42] =
1947 	   (field.unowned_land_nearby) ?
1948 	      management_data.neuron_pool[18].get_result_safe(field.own_non_military_nearby, kAbsValue) :
1949 	      0;
1950 
1951 	score_parts[43] = 2 *
1952 	                  management_data.neuron_pool[11].get_result_safe(
1953 	                     field.unowned_buildable_spots_nearby, kAbsValue);
1954 	score_parts[44] =
1955 	   management_data.neuron_pool[12].get_result_safe(field.unowned_mines_spots_nearby, kAbsValue);
1956 	score_parts[45] =
1957 	   (field.unowned_land_nearby) ?
1958 	      field.military_loneliness * std::abs(management_data.get_military_number_at(53)) / 800 :
1959 	      0;
1960 
1961 	score_parts[46] =
1962 	   -1 * management_data.neuron_pool[55].get_result_safe(field.ally_military_presence, kAbsValue);
1963 	score_parts[47] =
1964 	   -1 *
1965 	   management_data.neuron_pool[53].get_result_safe(2 * field.ally_military_presence, kAbsValue);
1966 	score_parts[48] = -2 *
1967 	                  management_data.neuron_pool[4].get_result_safe(
1968 	                     (field.area_military_capacity + 4) / 5, kAbsValue);
1969 	score_parts[49] = ((field.military_in_constr_nearby + field.military_unstationed) > 0) ?
1970 	                     -std::abs(management_data.get_military_number_at(81)) :
1971 	                     0;
1972 	score_parts[55] = (field.military_loneliness < 10) ?
1973 	                     2 * std::abs(management_data.get_military_number_at(141)) :
1974 	                     0;
1975 	score_parts[56] =
1976 	   (any_unconnected_imm) ? 2 * std::abs(management_data.get_military_number_at(23)) : 0;
1977 	score_parts[57] = 1 *
1978 	                  management_data.neuron_pool[18].get_result_safe(
1979 	                     2 * field.unowned_portspace_vicinity_nearby, kAbsValue);
1980 	score_parts[58] = 3 *
1981 	                  management_data.neuron_pool[19].get_result_safe(
1982 	                     5 * field.unowned_portspace_vicinity_nearby, kAbsValue);
1983 	score_parts[59] = (field.unowned_portspace_vicinity_nearby) ?
1984 	                     10 * std::abs(management_data.get_military_number_at(31)) :
1985 	                     0;
1986 	score_parts[60] = 3 *
1987 	                  management_data.neuron_pool[21].get_result_safe(
1988 	                     20 - field.nearest_buildable_spot_nearby, kAbsValue);
1989 	score_parts[61] = (field.nearest_buildable_spot_nearby < 8) ?
1990 	                     std::abs(management_data.get_military_number_at(153) * 2) :
1991 	                     0;
1992 	score_parts[62] = (field.nearest_buildable_spot_nearby > 20) ?
1993 	                     -std::abs(management_data.get_military_number_at(154) * 2) :
1994 	                     0;
1995 	score_parts[63] = (field.nearest_buildable_spot_nearby < 4) ?
1996 	                     std::abs(management_data.get_military_number_at(155) * 2) :
1997 	                     0;
1998 	// 64 and 65 are used above
1999 	score_parts[66] =
2000 	   (field.unowned_mines_spots_nearby > 0 && !mine_fields_stat.has_critical_ore_fields()) ?
2001 	      std::abs(management_data.get_military_number_at(157)) :
2002 	      0;
2003 	score_parts[67] = (field.unowned_mines_spots_nearby > 0 && mine_fields_stat.count_types() <= 4) ?
2004 	                     std::abs(management_data.get_military_number_at(158)) :
2005 	                     0;
2006 	score_parts[68] =
2007 	   (field.unowned_mines_spots_nearby == 0 && mine_fields_stat.count_types() <= 4) ?
2008 	      -std::abs(management_data.get_military_number_at(159)) :
2009 	      0;
2010 
2011 	for (uint16_t i = 0; i < score_parts_size; i++) {
2012 		field.military_score_ += score_parts[i];
2013 	}
2014 
2015 	if (ai_training_mode_) {
2016 		if (field.military_score_ < -5000 || field.military_score_ > 2000) {
2017 			log("Warning field.military_score_ %5d, compounds: ", field.military_score_);
2018 			for (uint16_t i = 0; i < score_parts_size; i++) {
2019 				log("%d, ", score_parts[i]);
2020 			}
2021 			log("\n");
2022 		}
2023 	}
2024 
2025 	// is new site allowed at all here?
2026 	field.defense_msite_allowed = false;
2027 	static int16_t multiplicator = 10;
2028 	multiplicator = 10;
2029 	if (soldier_status_ == SoldiersStatus::kBadShortage) {
2030 		multiplicator = 4;
2031 	} else if (soldier_status_ == SoldiersStatus::kShortage) {
2032 		multiplicator = 7;
2033 	}
2034 	if (field.area_military_capacity < field.enemy_military_presence * multiplicator / 10) {
2035 		field.defense_msite_allowed = true;
2036 	}
2037 }
2038 
2039 /// Updates one mineable field
update_mineable_field(MineableField & field)2040 void DefaultAI::update_mineable_field(MineableField& field) {
2041 	// collect information about resources in the area
2042 	std::vector<ImmovableFound> immovables;
2043 	const Map& map = game().map();
2044 	map.find_immovables(game(), Area<FCoords>(field.coords, 5), &immovables);
2045 	field.preferred = false;
2046 	field.mines_nearby = 0;
2047 	FCoords fse;
2048 	map.get_brn(field.coords, &fse);
2049 
2050 	if (BaseImmovable const* const imm = fse.field->get_immovable()) {
2051 		if (dynamic_cast<Flag const*>(imm) ||
2052 		    (dynamic_cast<Road const*>(imm) && (fse.field->nodecaps() & BUILDCAPS_FLAG))) {
2053 			field.preferred = true;
2054 		}
2055 	}
2056 
2057 	for (const ImmovableFound& temp_immovable : immovables) {
2058 		if (upcast(Building const, bld, temp_immovable.object)) {
2059 			if (player_number() != bld->owner().player_number()) {
2060 				continue;
2061 			}
2062 			if (bld->descr().get_ismine()) {
2063 				if (get_building_observer(bld->descr().name().c_str()).mines ==
2064 				    field.coords.field->get_resources()) {
2065 					++field.mines_nearby;
2066 				}
2067 			} else if (upcast(ConstructionSite const, cs, bld)) {
2068 				if (cs->building().get_ismine()) {
2069 					if (get_building_observer(cs->building().name().c_str()).mines ==
2070 					    field.coords.field->get_resources()) {
2071 						++field.mines_nearby;
2072 					}
2073 				}
2074 			}
2075 		}
2076 	}
2077 
2078 	// 0 is default, and thus indicates that counting must be done
2079 	if (field.same_mine_fields_nearby == 0) {
2080 		FindNodeMineable find_mines_spots_nearby(game(), field.coords.field->get_resources());
2081 		field.same_mine_fields_nearby =
2082 		   map.find_fields(game(), Area<FCoords>(field.coords, 4), nullptr, find_mines_spots_nearby);
2083 	}
2084 }
2085 
2086 /// Updates the production and MINE sites statistics needed for construction decision.
update_productionsite_stats()2087 void DefaultAI::update_productionsite_stats() {
2088 
2089 	// Reset statistics for all buildings
2090 	for (uint32_t i = 0; i < buildings_.size(); ++i) {
2091 		buildings_.at(i).current_stats = 0;
2092 		buildings_.at(i).unoccupied_count = 0;
2093 		buildings_.at(i).unconnected_count = 0;
2094 	}
2095 
2096 	// Check all available productionsites
2097 	for (uint32_t i = 0; i < productionsites.size(); ++i) {
2098 		assert(productionsites.front().bo->cnt_built > 0);
2099 		// is connected
2100 		// TODO(Nordfriese): Someone should update the code since the big economy splitting for the
2101 		// ferries
2102 		const bool connected_to_wh =
2103 		   !productionsites.front().site->get_economy(wwWORKER)->warehouses().empty();
2104 
2105 		// unconnected buildings are excluded from statistics review
2106 		if (connected_to_wh) {
2107 			// Add statistics value
2108 			productionsites.front().bo->current_stats +=
2109 			   productionsites.front().site->get_statistics_percent();
2110 
2111 			// Check whether this building is completely occupied
2112 			if (!productionsites.front().site->can_start_working()) {
2113 				++productionsites.front().bo->unoccupied_count;
2114 			}
2115 		} else {
2116 			++productionsites.front().bo->unconnected_count;
2117 		}
2118 
2119 		// Now reorder the buildings
2120 		productionsites.push_back(productionsites.front());
2121 		productionsites.pop_front();
2122 	}
2123 
2124 	// for mines_ also
2125 	// Check all available mines
2126 	for (uint32_t i = 0; i < mines_.size(); ++i) {
2127 		assert(mines_.front().bo->cnt_built > 0);
2128 
2129 		const bool connected_to_wh =
2130 		   !mines_.front().site->get_economy(wwWORKER)->warehouses().empty();
2131 
2132 		// unconnected mines are excluded from statistics review
2133 		if (connected_to_wh) {
2134 			// Add statistics value
2135 			mines_.front().bo->current_stats += mines_.front().site->get_statistics_percent();
2136 			// Check whether this building is completely occupied
2137 			if (!mines_.front().site->can_start_working()) {
2138 				++mines_.front().bo->unoccupied_count;
2139 			}
2140 		} else {
2141 			++mines_.front().bo->unconnected_count;
2142 		}
2143 
2144 		// Now reorder the buildings
2145 		mines_.push_back(mines_.front());
2146 		mines_.pop_front();
2147 	}
2148 
2149 	// Scale statistics down
2150 	for (uint32_t i = 0; i < buildings_.size(); ++i) {
2151 		if ((buildings_.at(i).cnt_built - buildings_.at(i).unconnected_count) > 0) {
2152 			buildings_.at(i).current_stats /=
2153 			   (buildings_.at(i).cnt_built - buildings_.at(i).unconnected_count);
2154 		}
2155 	}
2156 }
2157 
2158 // * Constructs the most needed building
2159 //   algorithm goes over all available spots and all allowed buildings,
2160 //   scores every combination and one with highest and positive score
2161 //   is built.
2162 // * Buildings are split into categories
2163 // * The logic is complex but approximately:
2164 // - some buildings belong to "basic economy" - these are preferred
2165 // - some small huts are exempt from basic economy logic
2166 // - first bulding of a type is preferred
2167 // - algorithm is trying to take into account actual utlization of buildings
2168 //   (the one shown in GUI/game is not reliable, it calculates own statistics)
2169 // * military buildings use genetic algorithm logic to score fields
2170 //   Currently more military buildings are built than needed
2171 //   so there are always some vacant positions
construct_building(uint32_t gametime)2172 bool DefaultAI::construct_building(uint32_t gametime) {
2173 	if (buildable_fields.empty()) {
2174 		return false;
2175 	}
2176 
2177 	// Just used for easy checking whether a mine or something else was built.
2178 	static bool mine = false;
2179 	mine = false;
2180 	static uint32_t consumers_nearby_count = 0;
2181 	consumers_nearby_count = 0;
2182 
2183 	const Map& map = game().map();
2184 
2185 	if (gametime > last_seafaring_check_ + 20000U) {
2186 		map_allows_seafaring_ = map.allows_seafaring();
2187 		last_seafaring_check_ = gametime;
2188 	}
2189 
2190 	for (int32_t i = 0; i < 4; ++i) {
2191 		spots_avail.at(i) = 0;
2192 	}
2193 
2194 	// We calculate owned buildable spots, of course ignoring ones that are blocked
2195 	// for now
2196 	for (std::deque<BuildableField*>::iterator i = buildable_fields.begin();
2197 	     i != buildable_fields.end(); ++i) {
2198 		if (blocked_fields.is_blocked((*i)->coords)) {
2199 			continue;
2200 		}
2201 		++spots_avail.at((*i)->coords.field->nodecaps() & BUILDCAPS_SIZEMASK);
2202 	}
2203 
2204 	spots_ = spots_avail.at(BUILDCAPS_SMALL);
2205 	spots_ += spots_avail.at(BUILDCAPS_MEDIUM);
2206 	spots_ += spots_avail.at(BUILDCAPS_BIG);
2207 
2208 	// helper variable - we need some proportion of free spots vs productionsites
2209 	// the proportion depends on size of economy
2210 	// this proportion defines how dense the buildings will be
2211 	// it is degressive (allows high density on the beginning)
2212 	static int32_t needed_spots = 0;
2213 	if (productionsites.size() < 50) {
2214 		needed_spots = productionsites.size();
2215 	} else if (productionsites.size() < 100) {
2216 		needed_spots = 50 + (productionsites.size() - 50) * 5;
2217 	} else if (productionsites.size() < 200) {
2218 		needed_spots = 300 + (productionsites.size() - 100) * 10;
2219 	} else {
2220 		needed_spots = 1300 + (productionsites.size() - 200) * 20;
2221 	}
2222 	const bool has_enough_space = (spots_ > needed_spots);
2223 
2224 	// Do we have basic economy established? Informing that we just left the basic economy mode.
2225 	if (!basic_economy_established && persistent_data->remaining_basic_buildings.empty()) {
2226 		log("%2d: Player has achieved the basic economy at %s\n", player_number(),
2227 		    gamestring_with_leading_zeros(gametime));
2228 		basic_economy_established = true;
2229 		assert(persistent_data->remaining_basic_buildings.empty());
2230 	}
2231 
2232 	if (!basic_economy_established && player_statistics.any_enemy_seen_lately(gametime) &&
2233 	    management_data.f_neuron_pool[17].get_position(0)) {
2234 		log("%2d: Player has not all buildings for basic economy yet (%" PRIuS
2235 		    " missing), but enemy is "
2236 		    "nearby, so quitting the mode at %s\n",
2237 		    player_number(), persistent_data->remaining_basic_buildings.size(),
2238 		    gamestring_with_leading_zeros(gametime));
2239 		basic_economy_established = true;
2240 		// Zeroing following to preserve consistency
2241 		persistent_data->remaining_basic_buildings.clear();
2242 	}
2243 
2244 	// *_military_scores are used as minimal score for a new military building
2245 	// to be built. As AI does not traverse all building fields at once, these thresholds
2246 	// are gradually going down until it finds a field&building that are above threshold
2247 	// and this combination is used...
2248 	// least_military_score is hardlimit, floating very slowly
2249 	// target_military_score is always set according to latest best building (using the same
2250 	// score) and quickly falling down until it reaches the least_military_score
2251 	// this one (=target_military_score) is actually used to decide if building&field is allowed
2252 	// candidate
2253 
2254 	const PlayerNumber pn = player_number();
2255 
2256 	// Genetic algorithm is used here
2257 	static bool inputs[2 * kFNeuronBitSize] = {0};
2258 	for (int i = 0; i < 2 * kFNeuronBitSize; i++) {
2259 		inputs[i] = 0;
2260 	}
2261 	inputs[0] = (pow(msites_in_constr(), 2) > militarysites.size() + 2);
2262 	inputs[1] = !(pow(msites_in_constr(), 2) > militarysites.size() + 2);
2263 	inputs[2] =
2264 	   (highest_nonmil_prio_ > 18 + std::abs(management_data.get_military_number_at(29) / 10));
2265 	inputs[3] =
2266 	   !(highest_nonmil_prio_ > 18 + std::abs(management_data.get_military_number_at(29) / 10));
2267 	inputs[4] = (highest_nonmil_prio_ > 18 + std::abs(management_data.get_military_number_at(48)));
2268 	inputs[5] = !(highest_nonmil_prio_ > 18 + std::abs(management_data.get_military_number_at(49)));
2269 	inputs[6] = ((numof_psites_in_constr + mines_in_constr()) >
2270 	             (productionsites.size() + mines_built()) / productionsites_ratio_);
2271 	inputs[7] = !((numof_psites_in_constr + mines_in_constr()) >
2272 	              (productionsites.size() + mines_built()) / productionsites_ratio_);
2273 
2274 	inputs[8] = (has_enough_space);
2275 	inputs[9] = !(has_enough_space);
2276 	inputs[10] = (has_enough_space);
2277 	inputs[11] = !(has_enough_space);
2278 
2279 	inputs[12] = (gametime > 45 * 60 * 1000);
2280 	inputs[13] = !(gametime > 45 * 60 * 1000);
2281 
2282 	inputs[14] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy);
2283 	inputs[15] = !(expansion_type.get_expansion_type() == ExpansionMode::kEconomy);
2284 	inputs[16] = (expansion_type.get_expansion_type() == ExpansionMode::kSpace);
2285 	inputs[17] = !(expansion_type.get_expansion_type() == ExpansionMode::kSpace);
2286 
2287 	inputs[18] = (player_statistics.any_enemy_seen_lately(gametime));
2288 	inputs[19] = !(player_statistics.any_enemy_seen_lately(gametime));
2289 	inputs[20] = (player_statistics.get_player_power(pn) >
2290 	              player_statistics.get_old60_player_power(pn) +
2291 	                 std::abs(management_data.get_military_number_at(130)) / 10);
2292 	inputs[21] = !(player_statistics.get_player_power(pn) >
2293 	               player_statistics.get_old60_player_power(pn) +
2294 	                  std::abs(management_data.get_military_number_at(131)) / 10);
2295 	inputs[22] =
2296 	   (player_statistics.get_player_power(pn) > player_statistics.get_old_player_power(pn));
2297 	inputs[23] =
2298 	   !(player_statistics.get_player_power(pn) > player_statistics.get_old_player_power(pn));
2299 	inputs[24] = (highest_nonmil_prio_ > 18 + management_data.get_military_number_at(65) / 10);
2300 	inputs[25] = !(highest_nonmil_prio_ > 18 + management_data.get_military_number_at(65) / 10);
2301 	inputs[26] = (player_statistics.get_modified_player_power(pn) >
2302 	              player_statistics.get_visible_enemies_power(pn));
2303 	inputs[27] = (player_statistics.get_modified_player_power(pn) <=
2304 	              player_statistics.get_visible_enemies_power(pn));
2305 	inputs[28] =
2306 	   (player_statistics.get_player_power(pn) > player_statistics.get_enemies_average_power());
2307 	inputs[29] =
2308 	   !(player_statistics.get_player_power(pn) > player_statistics.get_enemies_average_power());
2309 	inputs[30] =
2310 	   (player_statistics.get_player_power(pn) > player_statistics.get_enemies_max_power());
2311 	inputs[31] =
2312 	   !(player_statistics.get_player_power(pn) > player_statistics.get_enemies_max_power());
2313 
2314 	inputs[32] = (persistent_data->least_military_score <
2315 	              persistent_data->ai_personality_mil_upper_limit *
2316 	                 std::abs(management_data.get_military_number_at(69)) / 100);
2317 	inputs[33] = !(persistent_data->least_military_score <
2318 	               persistent_data->ai_personality_mil_upper_limit *
2319 	                  std::abs(management_data.get_military_number_at(69)) / 100);
2320 	inputs[34] = player_statistics.strong_enough(pn);
2321 	inputs[35] = !player_statistics.strong_enough(pn);
2322 
2323 	inputs[36] = (player_statistics.get_player_land(pn) < 500);
2324 	inputs[37] = (player_statistics.get_player_land(pn) < 700);
2325 	inputs[38] = (player_statistics.get_player_land(pn) < 900);
2326 	inputs[39] = (player_statistics.get_player_land(pn) < 1100);
2327 	inputs[40] = (player_statistics.get_player_land(pn) > 500);
2328 	inputs[41] = (player_statistics.get_player_land(pn) > 700);
2329 	inputs[42] = (player_statistics.get_player_land(pn) > 900);
2330 	inputs[43] = (player_statistics.get_player_land(pn) > 1100);
2331 	inputs[44] = (player_statistics.get_player_power(pn) >
2332 	              player_statistics.get_old60_player_power(pn) +
2333 	                 std::abs(management_data.get_military_number_at(130)) / 10);
2334 	inputs[45] = !(player_statistics.get_player_power(pn) >
2335 	               player_statistics.get_old60_player_power(pn) +
2336 	                  std::abs(management_data.get_military_number_at(131)) / 10);
2337 	inputs[46] =
2338 	   (player_statistics.get_player_power(pn) > player_statistics.get_old_player_power(pn));
2339 	inputs[47] =
2340 	   !(player_statistics.get_player_power(pn) > player_statistics.get_old_player_power(pn));
2341 	inputs[48] = (bakeries_count_ == 0);
2342 	inputs[49] = (bakeries_count_ <= 1);
2343 	inputs[50] = (bakeries_count_ <= 1);
2344 	inputs[51] = (numof_psites_in_constr > 8);
2345 	inputs[52] = (numof_psites_in_constr < 8);
2346 	inputs[53] = (mine_fields_stat.has_critical_ore_fields());
2347 	inputs[54] = (!mine_fields_stat.has_critical_ore_fields());
2348 	inputs[55] = (mine_fields_stat.count_types() == kMineTypes);
2349 	inputs[56] = (mine_fields_stat.count_types() != kMineTypes);
2350 	inputs[57] = (mine_fields_stat.has_critical_ore_fields());
2351 	inputs[58] = (!mine_fields_stat.has_critical_ore_fields());
2352 
2353 	static int16_t needs_boost_economy_score = management_data.get_military_number_at(61) / 5;
2354 	needs_boost_economy_score = management_data.get_military_number_at(61) / 5;
2355 	static int16_t increase_score_limit_score = 0;
2356 	increase_score_limit_score = 0;
2357 
2358 	for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {
2359 		if (management_data.f_neuron_pool[51].get_position(i)) {
2360 			needs_boost_economy_score += (inputs[i]) ? 1 : -1;
2361 		}
2362 		if (management_data.f_neuron_pool[52].get_position(i)) {
2363 			increase_score_limit_score += (inputs[i]) ? 1 : -1;
2364 		}
2365 		if (management_data.f_neuron_pool[21].get_position(i)) {
2366 			needs_boost_economy_score += (inputs[kFNeuronBitSize + i]) ? 1 : -1;
2367 		}
2368 		if (management_data.f_neuron_pool[22].get_position(i)) {
2369 			increase_score_limit_score += (inputs[kFNeuronBitSize + i]) ? 1 : -1;
2370 		}
2371 	}
2372 
2373 	// Finding expansion policy
2374 	// Do we need basic resources? Do we have basic mines?
2375 	const bool needs_fishers = resource_necessity_water_needed_ && fishers_count_ < 1;
2376 
2377 	if (!mine_fields_stat.has_critical_ore_fields() ||
2378 	    mines_per_type[iron_resource_id].total_count() < 1 || needs_fishers) {
2379 		expansion_type.set_expantion_type(ExpansionMode::kResources);
2380 	} else {
2381 		// now we must decide if we go after spots or economy boost
2382 		if (needs_boost_economy_score >= 3) {
2383 			expansion_type.set_expantion_type(ExpansionMode::kEconomy);
2384 		} else if (needs_boost_economy_score >= -2) {
2385 			expansion_type.set_expantion_type(ExpansionMode::kBoth);
2386 		} else {
2387 			expansion_type.set_expantion_type(ExpansionMode::kSpace);
2388 		}
2389 	}
2390 
2391 	const bool increase_least_score_limit =
2392 	   (increase_score_limit_score > management_data.get_military_number_at(45) / 5);
2393 
2394 	static uint16_t concurent_ms_in_constr_no_enemy = 1;
2395 	concurent_ms_in_constr_no_enemy = 1;
2396 	static uint16_t concurent_ms_in_constr_enemy_nearby = 2;
2397 	concurent_ms_in_constr_enemy_nearby = 2;
2398 
2399 	// resetting highest_nonmil_prio_ so it can be recalculated anew
2400 	highest_nonmil_prio_ = 0;
2401 
2402 	if (increase_least_score_limit) {
2403 		if (persistent_data->least_military_score <
2404 		    persistent_data
2405 		       ->ai_personality_mil_upper_limit) {  // No sense in letting it grow too high
2406 			persistent_data->least_military_score += 20;
2407 			if (persistent_data->least_military_score > persistent_data->target_military_score) {
2408 				persistent_data->target_military_score = persistent_data->least_military_score;
2409 			}
2410 			if (persistent_data->target_military_score >
2411 			    persistent_data->ai_personality_mil_upper_limit) {
2412 				persistent_data->ai_personality_mil_upper_limit =
2413 				   persistent_data->target_military_score;
2414 			}
2415 		}
2416 	} else {
2417 
2418 		uint16_t divider = 1;  // this is to slow down decrementing the least military score
2419 		switch (expansion_type.get_expansion_type()) {
2420 		case ExpansionMode::kEconomy:
2421 			divider = 3;
2422 			break;
2423 		case ExpansionMode::kBoth:
2424 			divider = 2;
2425 			break;
2426 		default:
2427 			divider = 1;
2428 		}
2429 
2430 		// least_military_score is decreased, but depending on the size of territory
2431 		switch (static_cast<uint32_t>(log10(buildable_fields.size()))) {
2432 		case 0:
2433 			persistent_data->least_military_score -= 10 / divider;
2434 			break;
2435 		case 1:
2436 			persistent_data->least_military_score -= 8 / divider;
2437 			break;
2438 		case 2:
2439 			persistent_data->least_military_score -= 5 / divider;
2440 			break;
2441 		case 3:
2442 			persistent_data->least_military_score -= 3 / divider;
2443 			break;
2444 		default:
2445 			persistent_data->least_military_score -= 2 / divider;
2446 		}
2447 		if (persistent_data->least_military_score < 0) {
2448 			persistent_data->least_military_score = 0;
2449 		}
2450 	}
2451 
2452 	assert(persistent_data->least_military_score <= persistent_data->target_military_score);
2453 	assert(persistent_data->target_military_score <=
2454 	       persistent_data->ai_personality_mil_upper_limit);
2455 	persistent_data->target_military_score = 9 * persistent_data->target_military_score / 10;
2456 	if (persistent_data->target_military_score < persistent_data->least_military_score) {
2457 		persistent_data->target_military_score = persistent_data->least_military_score;
2458 	}
2459 	assert(persistent_data->target_military_score >= persistent_data->least_military_score);
2460 
2461 	// we must calculate wood policy
2462 	const DescriptionIndex wood_index = tribe_->safe_ware_index("log");
2463 	// stocked wood is to be in some propotion to productionsites and
2464 	// constructionsites (this proportion is bit artifical, or we can say
2465 	// it is proportion to the size of economy). Plus some positive 'margin'
2466 	const int32_t stocked_wood_margin = calculate_stocklevel(wood_index) -
2467 	                                    productionsites.size() * 2 - numof_psites_in_constr +
2468 	                                    management_data.get_military_number_at(87) / 5;
2469 	if (gametime < 15 * 60 * 1000) {
2470 		wood_policy_ = WoodPolicy::kAllowRangers;
2471 	} else if (stocked_wood_margin > 80) {
2472 		wood_policy_ = WoodPolicy::kDismantleRangers;
2473 	} else if (stocked_wood_margin > 25) {
2474 		wood_policy_ = WoodPolicy::kStopRangers;
2475 	} else {
2476 		wood_policy_ = WoodPolicy::kAllowRangers;
2477 	}
2478 
2479 	BuildingObserver* best_building = nullptr;
2480 	int32_t proposed_priority = 0;
2481 	Coords proposed_coords;
2482 
2483 	// Remove outdated fields from blocker list
2484 	blocked_fields.remove_expired(gametime);
2485 
2486 	// testing big military buildings, whether critical construction
2487 	// material is available (at least in amount of
2488 	// 2/3 of default target amount)
2489 	for (BuildingObserver& bo : buildings_) {
2490 		if (!bo.buildable(*player_)) {
2491 			continue;
2492 		}
2493 
2494 		// not doing this for non-military buildins
2495 		if (!(bo.type == BuildingObserver::Type::kMilitarysite ||
2496 		      bo.type == BuildingObserver::Type::kTrainingsite ||
2497 		      bo.type == BuildingObserver::Type::kProductionsite)) {
2498 			continue;
2499 		}
2500 
2501 		// and neither for small military buildings
2502 		if (bo.type == BuildingObserver::Type::kMilitarysite &&
2503 		    bo.desc->get_size() == BaseImmovable::SMALL) {
2504 			continue;
2505 		}
2506 
2507 		bo.build_material_shortage = false;
2508 
2509 		// checking we have enough critical material on stock
2510 		for (uint32_t m = 0; m < bo.critical_building_material.size(); ++m) {
2511 			DescriptionIndex wt(static_cast<size_t>(bo.critical_building_material.at(m)));
2512 			uint32_t treshold = 7;
2513 			// generally trainingsites are more important
2514 			if (bo.type == BuildingObserver::Type::kTrainingsite) {
2515 				treshold = 4;
2516 			}
2517 
2518 			if (bo.type == BuildingObserver::Type::kProductionsite) {
2519 				treshold = 2;
2520 			}
2521 
2522 			if (calculate_stocklevel(wt) <= treshold) {
2523 				bo.build_material_shortage = true;
2524 				break;
2525 			}
2526 		}
2527 	}
2528 
2529 	// Calculating actual needness
2530 	for (uint32_t j = 0; j < buildings_.size(); ++j) {
2531 		BuildingObserver& bo = buildings_.at(j);
2532 
2533 		// we check if a previously not buildable Building of the basic economy is buildable again
2534 		// If so and we don't have basic economy achieved we add readd it to basic buildings list
2535 		// This should only happen in scenarios via scripting
2536 		if (!basic_economy_established && bo.basic_amount > static_cast<uint32_t>(bo.total_count()) &&
2537 		    bo.buildable(*player_)) {
2538 			persistent_data->remaining_basic_buildings.emplace(std::make_pair(bo.id, bo.basic_amount));
2539 		}
2540 		if (!bo.buildable(*player_)) {
2541 			bo.new_building = BuildingNecessity::kNotNeeded;
2542 			// This line removes buildings from basic economy if they are not allowed for the player
2543 			// this should only happen by scripting.
2544 			if (bo.basic_amount) {
2545 				persistent_data->remaining_basic_buildings.erase(bo.id);
2546 			}
2547 		} else if (bo.type == BuildingObserver::Type::kProductionsite ||
2548 		           bo.type == BuildingObserver::Type::kMine) {
2549 
2550 			bo.new_building = check_building_necessity(bo, PerfEvaluation::kForConstruction, gametime);
2551 
2552 			if (bo.is(BuildingAttribute::kShipyard)) {
2553 				assert(bo.new_building == BuildingNecessity::kAllowed ||
2554 				       bo.new_building == BuildingNecessity::kNeeded ||
2555 				       bo.new_building == BuildingNecessity::kForbidden);
2556 			}
2557 
2558 			if (bo.new_building == BuildingNecessity::kAllowed) {
2559 				bo.new_building_overdue = 0;
2560 			}
2561 
2562 			// Now verifying that all 'buildable' buildings has positive max_needed_preciousness
2563 			// if they have outputs, all other must have zero max_needed_preciousness
2564 
2565 			if (bo.new_building == BuildingNecessity::kForbidden) {
2566 				bo.max_needed_preciousness = 0;
2567 			} else if ((bo.new_building == BuildingNecessity::kNeeded ||
2568 			            bo.new_building == BuildingNecessity::kForced ||
2569 			            bo.new_building == BuildingNecessity::kAllowed ||
2570 			            bo.new_building == BuildingNecessity::kNeededPending) &&
2571 			           (!bo.ware_outputs.empty() ||
2572 			            bo.initial_preciousness >
2573 			               0)) {  // bo.initial_preciousness signals that we have a worker output
2574 				bo.max_needed_preciousness =
2575 				   std::max(bo.max_needed_preciousness, bo.initial_preciousness);
2576 				bo.max_preciousness = std::max(bo.max_preciousness, bo.initial_preciousness);
2577 
2578 				if (bo.max_needed_preciousness <= 0) {
2579 					throw wexception("AI: Max preciousness must not be <= 0 for building: %s",
2580 					                 bo.desc->name().c_str());
2581 				}
2582 			} else {
2583 				// For other situations we make sure max_needed_preciousness is zero
2584 				assert(bo.max_needed_preciousness == 0);
2585 			}
2586 
2587 			// Positive max_needed_preciousness says a building type is needed
2588 			// here we increase or reset the counter
2589 			// The counter is added to score when considering new building
2590 			if (bo.max_needed_preciousness > 0) {
2591 				++bo.new_building_overdue;
2592 			} else {
2593 				bo.new_building_overdue = 0;
2594 			}
2595 
2596 			// Here we consider a time how long a building needed
2597 			// We calculate primary_priority used later in construct_building(),
2598 			// it is basically max_needed_preciousness_ plus some 'bonus' for due time
2599 			// Following scenarios are possible:
2600 			// a) building is needed or forced: primary_priority grows with time
2601 			// b) building is allowed: primary_priority = max_needed_preciousness (no time
2602 			// consideration)
2603 			// c) all other cases: primary_priority = 0;
2604 			if (bo.max_needed_preciousness > 0) {
2605 				if (bo.new_building == BuildingNecessity::kAllowed) {
2606 					bo.primary_priority += bo.max_needed_preciousness;
2607 				} else {
2608 					bo.primary_priority += bo.primary_priority * bo.new_building_overdue *
2609 					                       std::abs(management_data.get_military_number_at(120)) / 25;
2610 					bo.primary_priority += bo.max_needed_preciousness +
2611 					                       bo.max_needed_preciousness * bo.new_building_overdue *
2612 					                          std::abs(management_data.get_military_number_at(70)) /
2613 					                          100 +
2614 					                       bo.new_building_overdue *
2615 					                          std::abs(management_data.get_military_number_at(71)) / 10;
2616 					if (bo.new_building == BuildingNecessity::kForced) {
2617 						bo.primary_priority += bo.new_building_overdue *
2618 						                       std::abs(management_data.get_military_number_at(119)) / 25;
2619 					}
2620 				}
2621 			} else {
2622 				bo.primary_priority = 0;
2623 			}
2624 
2625 		} else if (bo.type == BuildingObserver::Type::kMilitarysite) {
2626 			bo.new_building = check_building_necessity(bo, gametime);
2627 		} else if (bo.type == BuildingObserver::Type::kTrainingsite) {
2628 			bo.new_building = check_building_necessity(bo, PerfEvaluation::kForConstruction, gametime);
2629 		} else if (bo.type == BuildingObserver::Type::kWarehouse) {
2630 			bo.new_building = check_warehouse_necessity(bo, gametime);
2631 		} else if (bo.aimode_limit_status() != AiModeBuildings::kAnotherAllowed) {
2632 			bo.new_building = BuildingNecessity::kNotNeeded;
2633 		} else {
2634 			bo.new_building = BuildingNecessity::kAllowed;
2635 			bo.primary_priority = 0;
2636 		}
2637 
2638 		const bool log_needed = (bo.new_building == BuildingNecessity::kAllowed ||
2639 		                         bo.new_building == BuildingNecessity::kForced ||
2640 		                         bo.new_building == BuildingNecessity::kNeeded);
2641 		if (ai_training_mode_ && bo.type == BuildingObserver::Type::kProductionsite &&
2642 		    (gametime % 20 == 0 || log_needed)) {
2643 			log("%2d: %-35s(%2d now) %-11s: max prec: %2d/%2d, primary priority: %4d, overdue: %3d\n",
2644 			    player_number(), bo.name, bo.total_count(), (log_needed) ? "needed" : "not needed",
2645 			    bo.max_needed_preciousness, bo.max_preciousness, bo.primary_priority,
2646 			    bo.new_building_overdue);
2647 		}
2648 	}
2649 
2650 	// first scan all buildable fields for regular buildings
2651 	for (std::deque<BuildableField*>::iterator i = buildable_fields.begin();
2652 	     i != buildable_fields.end(); ++i) {
2653 		BuildableField* const bf = *i;
2654 
2655 		if (bf->field_info_expiration < gametime) {
2656 			continue;
2657 		}
2658 
2659 		// Continue if field is blocked at the moment
2660 		if (blocked_fields.is_blocked(bf->coords)) {
2661 			continue;
2662 		}
2663 
2664 		assert(player_);
2665 		int32_t const maxsize = player_->get_buildcaps(bf->coords) & BUILDCAPS_SIZEMASK;
2666 
2667 		// For every field test all buildings
2668 		for (BuildingObserver& bo : buildings_) {
2669 			if (!bo.buildable(*player_)) {
2670 				continue;
2671 			}
2672 
2673 			if (bo.new_building == BuildingNecessity::kNotNeeded ||
2674 			    bo.new_building == BuildingNecessity::kNeededPending ||
2675 			    bo.new_building == BuildingNecessity::kForbidden) {
2676 				continue;
2677 			}
2678 
2679 			assert(bo.new_building == BuildingNecessity::kForced ||
2680 			       bo.new_building == BuildingNecessity::kNeeded ||
2681 			       bo.new_building == BuildingNecessity::kAllowed);
2682 
2683 			assert(bo.aimode_limit_status() == AiModeBuildings::kAnotherAllowed);
2684 
2685 			// if current field is not big enough
2686 			if (bo.desc->get_size() > maxsize) {
2687 				continue;
2688 			}
2689 
2690 			if (std::rand() % 3 == 0 && bo.total_count() > 0) {
2691 				continue;
2692 			}  // add randomnes and ease AI
2693 
2694 			if (bo.type == BuildingObserver::Type::kMine) {
2695 				continue;
2696 			}
2697 
2698 			// here we do an exemption for lumberjacks, mainly in early stages of game
2699 			// sometimes the first one is not built and AI waits too long for second attempt
2700 			if (gametime - bo.construction_decision_time < kBuildingMinInterval &&
2701 			    !bo.is(BuildingAttribute::kLumberjack)) {
2702 				continue;
2703 			}
2704 
2705 			if (!(bo.type == BuildingObserver::Type::kMilitarysite) &&
2706 			    bo.cnt_under_construction >= 2) {
2707 				continue;
2708 			}
2709 
2710 			int32_t prio = 0;  // score of a bulding on a field
2711 
2712 			// testing for reserved ports
2713 			if (!bo.is(BuildingAttribute::kPort)) {
2714 				if (bf->portspace_nearby == ExtendedBool::kTrue) {
2715 					if (num_ports == 0) {
2716 						continue;
2717 					}
2718 					// If we have at least on port, we can perhaps build here something
2719 					// but decreasing the score to discourage it
2720 					prio -= 5 * std::abs(management_data.get_military_number_at(52));
2721 				}
2722 			}
2723 
2724 			if (bo.type == BuildingObserver::Type::kProductionsite) {
2725 
2726 				prio += management_data.neuron_pool[44].get_result_safe(bf->military_score_ / 20) / 5;
2727 
2728 				// Some productionsites strictly require supporting sites nearby
2729 				if (bo.requires_supporters) {
2730 					uint16_t supporters_nearby = 0;
2731 					for (auto output : bo.ware_outputs) {
2732 						supporters_nearby += bf->supporters_nearby.at(output);
2733 					}
2734 					if (supporters_nearby == 0) {
2735 						continue;
2736 					}
2737 				}
2738 
2739 				// this can be only a well (as by now)
2740 				if (bo.is(BuildingAttribute::kWell)) {
2741 
2742 					if (bo.new_building == BuildingNecessity::kForced) {
2743 						assert(bo.total_count() - bo.unconnected_count == 0);
2744 					}
2745 
2746 					if (bf->ground_water < 2) {
2747 						continue;
2748 					}
2749 
2750 					prio += bo.primary_priority;
2751 
2752 					// keep wells more distant
2753 					if (bf->collecting_producers_nearby.at(bo.get_collected_map_resource()) > 2) {
2754 						continue;
2755 					}
2756 
2757 					// one well is forced
2758 					if (bo.new_building == BuildingNecessity::kForced) {
2759 						prio += 200;
2760 					}
2761 
2762 					prio += -10 +
2763 					        std::abs(management_data.get_military_number_at(59) / 50) * bf->ground_water;
2764 
2765 				} else if (bo.is(BuildingAttribute::kLumberjack)) {
2766 
2767 					prio += bo.primary_priority;
2768 
2769 					if (bo.new_building == BuildingNecessity::kForced) {
2770 						prio += 5 * std::abs(management_data.get_military_number_at(17));
2771 					}
2772 
2773 					if (bf->trees_nearby < trees_nearby_treshold_ &&
2774 					    bo.new_building == BuildingNecessity::kAllowed) {
2775 						continue;
2776 					}
2777 
2778 					prio += std::abs(management_data.get_military_number_at(26)) *
2779 					        (bf->trees_nearby - trees_nearby_treshold_) / 10;
2780 
2781 					// consider cutters and rangers nearby
2782 					prio += 2 * bf->supporters_nearby.at(bo.get_collected_map_resource()) *
2783 					        std::abs(management_data.get_military_number_at(25));
2784 					prio -= bf->collecting_producers_nearby.at(bo.get_collected_map_resource()) *
2785 					        std::abs(management_data.get_military_number_at(36)) * 3;
2786 
2787 				} else if (bo.is(BuildingAttribute::kNeedsRocks)) {
2788 
2789 					// Quarries are generally to be built everywhere where rocks are
2790 					// no matter the need for granite, as rocks are considered an obstacle
2791 					// to expansion
2792 					if (bf->rocks_nearby < 1) {
2793 						continue;
2794 					}
2795 					prio += 2 * bf->rocks_nearby;
2796 
2797 					if (bf->rocks_nearby > 0 && bf->near_border) {
2798 						prio += management_data.get_military_number_at(27) / 2;
2799 					}
2800 
2801 					// value is initialized with 1 but minimal value that can be
2802 					// calculated is 11
2803 					if (prio <= 1) {
2804 						continue;
2805 					}
2806 
2807 					if (bo.total_count() - bo.unconnected_count == 0) {
2808 						prio += 150;
2809 					}
2810 
2811 					if (get_stocklevel(bo, gametime) == 0) {
2812 						prio *= 2;
2813 					}
2814 
2815 					// to prevent to many quaries on one spot
2816 					prio =
2817 					   prio - 50 * bf->collecting_producers_nearby.at(bo.get_collected_map_resource());
2818 
2819 				} else if (bo.is(BuildingAttribute::kHunter)) {
2820 
2821 					if (bf->critters_nearby < 5) {
2822 						continue;
2823 					}
2824 
2825 					if (bo.new_building == BuildingNecessity::kForced) {
2826 						prio += 20;
2827 					}
2828 
2829 					// Overdue priority here
2830 					prio += bo.primary_priority;
2831 
2832 					prio += bf->supporters_nearby.at(bo.get_collected_map_resource()) * 5;
2833 
2834 					prio += (bf->critters_nearby * 3) - 8 -
2835 					        5 * bf->collecting_producers_nearby.at(bo.get_collected_map_resource());
2836 
2837 				} else if (bo.is(BuildingAttribute::kFisher)) {  // fisher
2838 
2839 					if (bf->fish_nearby <= 15) {
2840 						continue;
2841 					}
2842 
2843 					if (bo.new_building == BuildingNecessity::kForced) {
2844 						prio += 200;
2845 					}
2846 
2847 					// Overdue priority here
2848 					prio += bo.primary_priority;
2849 
2850 					prio -= bf->collecting_producers_nearby.at(bo.get_collected_map_resource()) * 20;
2851 					prio += bf->supporters_nearby.at(bo.get_collected_map_resource()) * 20;
2852 
2853 					prio +=
2854 					   -5 +
2855 					   bf->fish_nearby * (1 + std::abs(management_data.get_military_number_at(63) / 15));
2856 					if (resource_necessity_water_needed_) {
2857 						prio *= 3;
2858 					}
2859 
2860 				} else if (!bo.production_hints.empty()) {
2861 					if (bo.is(BuildingAttribute::kRanger)) {
2862 						assert(bo.cnt_target > 0);
2863 					}
2864 
2865 					prio += bo.primary_priority;
2866 
2867 					if (bo.is(BuildingAttribute::kRanger)) {
2868 
2869 						assert(bo.new_building == BuildingNecessity::kNeeded);
2870 
2871 						if (bo.total_count() == 0) {
2872 							prio += 200;
2873 						} else {
2874 							prio += std::abs(management_data.get_military_number_at(66)) *
2875 							        (bo.cnt_target - bo.total_count());
2876 						}
2877 
2878 						prio -= bf->water_nearby / 5;
2879 
2880 						for (auto ph : bo.production_hints) {
2881 							assert(ph != INVALID_INDEX);
2882 							prio += management_data.neuron_pool[67].get_result_safe(
2883 							           bf->collecting_producers_nearby.at(ph) * 5, kAbsValue) /
2884 							        2;
2885 						}
2886 
2887 						prio +=
2888 						   management_data.neuron_pool[49].get_result_safe(bf->trees_nearby, kAbsValue) /
2889 						   5;
2890 
2891 						for (auto ph : bo.production_hints) {
2892 							assert(ph != INVALID_INDEX);
2893 							prio += bf->collecting_producers_nearby.at(ph) * 5 -
2894 							        (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) * 15 -
2895 							        bf->space_consumers_nearby *
2896 							           std::abs(management_data.get_military_number_at(102)) / 5 -
2897 							        bf->rocks_nearby / 3 + bf->supporters_nearby.at(ph) * 3;
2898 						}
2899 						// don't block port building spots with trees
2900 						if (bf->unowned_portspace_vicinity_nearby > 0) {
2901 							prio -= 500;
2902 						}
2903 						// frisian claypit and frisian farm
2904 					} else if (bo.is(BuildingAttribute::kSupportingProducer)) {
2905 						// we dont like trees nearby
2906 						prio += 1 - bf->trees_nearby / 3;
2907 						// and be far from rangers
2908 						prio +=
2909 						   1 -
2910 						   bf->rangers_nearby * std::abs(management_data.get_military_number_at(102)) / 5;
2911 
2912 						// This is for a special case this is also supporter, it considers
2913 						// producers nearby
2914 						for (auto ph : bo.production_hints) {
2915 							assert(ph != INVALID_INDEX);
2916 							prio += management_data.neuron_pool[51].get_result_safe(
2917 							           bf->collecting_producers_nearby.at(ph) * 5, kAbsValue) /
2918 							        2;
2919 						}
2920 						// now we find out if the supporter is needed depending on output stocklevel
2921 						// and supported stocklevel
2922 						const uint32_t combined_stocklevel = (get_stocklevel(bo, gametime));
2923 
2924 						if (combined_stocklevel > 50 &&
2925 						    persistent_data->remaining_basic_buildings.count(bo.id) == 0) {
2926 							continue;
2927 						}
2928 
2929 						if (combined_stocklevel < 40) {
2930 							prio += 5 *
2931 							        management_data.neuron_pool[23].get_result_safe(
2932 							           (40 - combined_stocklevel) / 2, kAbsValue);
2933 						}
2934 
2935 						// taking into account the vicinity
2936 						for (auto ph : bo.production_hints) {
2937 							assert(ph != INVALID_INDEX);
2938 							prio += bf->collecting_producers_nearby.at(ph) * 10;
2939 							prio -= bf->supporters_nearby.at(ph) * 15;
2940 						}
2941 
2942 						if (bf->enemy_nearby) {  // not close to the enemy
2943 							prio -= 20;
2944 						}
2945 
2946 						// don't block port building spots with immovables
2947 						if (bo.is(BuildingAttribute::kSpaceConsumer) &&
2948 						    bf->unowned_portspace_vicinity_nearby > 0) {
2949 							prio -= 500;
2950 						}
2951 
2952 						if (bo.is(BuildingAttribute::kSpaceConsumer) &&
2953 						    bf->water_nearby) {  // not close to water
2954 							prio -= std::abs(management_data.get_military_number_at(103)) / 5;
2955 						}
2956 
2957 						if (bo.is(BuildingAttribute::kSpaceConsumer) &&
2958 						    bf->unowned_mines_spots_nearby) {  // not close to mountains
2959 							prio -= std::abs(management_data.get_military_number_at(104)) / 5;
2960 						}
2961 						// frisian berry farm
2962 					} else if (bo.is(BuildingAttribute::kSpaceConsumer)) {
2963 						// we dont like trees nearby
2964 						prio += 1 - bf->trees_nearby / 4;
2965 						// and be far from rangers
2966 						prio +=
2967 						   1 -
2968 						   bf->rangers_nearby * std::abs(management_data.get_military_number_at(102)) / 5;
2969 
2970 						// now we find out if the supporter is needed depending on stocklevel
2971 						const uint32_t current_stocklevel = (get_stocklevel(bo, gametime));
2972 
2973 						if (current_stocklevel > 50 &&
2974 						    persistent_data->remaining_basic_buildings.count(bo.id) == 0) {
2975 							continue;
2976 						}
2977 
2978 						if (current_stocklevel < 40) {
2979 							prio += 5 *
2980 							        management_data.neuron_pool[23].get_result_safe(
2981 							           (40 - current_stocklevel) / 2, kAbsValue);
2982 						}
2983 						// taking into account the vicinity
2984 						for (auto ph : bo.production_hints) {
2985 							assert(ph != INVALID_INDEX);
2986 							prio += bf->collecting_producers_nearby.at(ph) * 10;
2987 							prio -= bf->supporters_nearby.at(ph) * 8;
2988 						}
2989 
2990 						if (bf->enemy_nearby) {  // not close to the enemy
2991 							prio -= 20;
2992 						}
2993 
2994 						// don't block port building spots with immovables
2995 						if (bf->unowned_portspace_vicinity_nearby > 0) {
2996 							prio -= 500;
2997 						}
2998 
2999 						if (bf->water_nearby) {  // not close to water
3000 							prio -= std::abs(management_data.get_military_number_at(103)) / 5;
3001 						}
3002 
3003 						if (bf->unowned_mines_spots_nearby) {  // not close to mountains
3004 							prio -= std::abs(management_data.get_military_number_at(104)) / 5;
3005 						}
3006 
3007 					} else {  // FISH BREEDERS and GAME KEEPERS
3008 
3009 						// especially for fish breeders
3010 						if (bo.is(BuildingAttribute::kNeedsCoast) &&
3011 						    (bf->water_nearby < 6 || bf->fish_nearby < 6)) {
3012 							continue;
3013 						}
3014 						if (bo.is(BuildingAttribute::kNeedsCoast)) {
3015 							prio += (-6 + bf->water_nearby) / 3;
3016 							prio += (-6 + bf->fish_nearby) / 3;
3017 						}
3018 
3019 						const uint32_t current_stocklevel = (get_stocklevel(bo, gametime));
3020 
3021 						if (current_stocklevel > 50 &&
3022 						    persistent_data->remaining_basic_buildings.count(bo.id) == 0) {
3023 							continue;
3024 						}
3025 
3026 						if (current_stocklevel < 40) {
3027 							prio += 5 *
3028 							        management_data.neuron_pool[23].get_result_safe(
3029 							           (40 - current_stocklevel) / 2, kAbsValue);
3030 						}
3031 
3032 						for (auto ph : bo.production_hints) {
3033 							assert(ph != INVALID_INDEX);
3034 							prio += bf->collecting_producers_nearby.at(ph) * 10;
3035 							prio -= bf->supporters_nearby.at(ph) * 20;
3036 						}
3037 
3038 						if (bf->enemy_nearby) {
3039 							prio -= 20;
3040 						}
3041 
3042 						if (bf->unowned_portspace_vicinity_nearby > 0) {
3043 							prio -= 500;
3044 						}
3045 					}
3046 
3047 				} else if (bo.is(BuildingAttribute::kRecruitment)) {
3048 					prio += bo.primary_priority;
3049 					prio -= bf->unowned_land_nearby * 2;
3050 					prio -= (bf->enemy_nearby) * 100;
3051 					prio -= (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) * 100;
3052 				} else {  // finally normal productionsites
3053 					assert(bo.production_hints.empty());
3054 
3055 					if (bo.new_building == BuildingNecessity::kForced) {
3056 						prio += 150;
3057 						assert(!bo.is(BuildingAttribute::kShipyard));
3058 					} else if (bo.is(BuildingAttribute::kShipyard)) {
3059 						if (!map_allows_seafaring_) {
3060 							continue;
3061 						}
3062 					} else {
3063 						assert(bo.new_building == BuildingNecessity::kNeeded);
3064 					}
3065 
3066 					// Overdue priority here
3067 					prio += bo.primary_priority;
3068 
3069 					// we check separatelly buildings with no inputs and some inputs
3070 					if (bo.inputs.empty()) {
3071 
3072 						assert(!bo.is(BuildingAttribute::kShipyard));
3073 
3074 						if (bo.is(BuildingAttribute::kSpaceConsumer)) {  // e.g. farms
3075 							// we dont like trees nearby
3076 							prio += 1 - bf->trees_nearby / 4;
3077 							// we attempt to cluster space consumers together
3078 							prio += bf->space_consumers_nearby * 2;
3079 							// and be far from rangers
3080 							prio += 1 -
3081 							        bf->rangers_nearby *
3082 							           std::abs(management_data.get_military_number_at(102)) / 5;
3083 						} else {
3084 							// leave some free space between them
3085 							prio -= bf->collecting_producers_nearby.at(bo.get_collected_map_resource()) *
3086 							        std::abs(management_data.get_military_number_at(108)) / 5;
3087 						}
3088 
3089 						if (bo.is(BuildingAttribute::kSpaceConsumer) &&
3090 						    bf->water_nearby) {  // not close to water
3091 							prio -= std::abs(management_data.get_military_number_at(103)) / 5;
3092 						}
3093 
3094 						if (bo.is(BuildingAttribute::kSpaceConsumer) &&
3095 						    bf->unowned_mines_spots_nearby) {  // not close to mountains
3096 							prio -= std::abs(management_data.get_military_number_at(104)) / 5;
3097 						}
3098 						if (bo.is(BuildingAttribute::kSpaceConsumer) &&
3099 						    bf->unowned_portspace_vicinity_nearby > 0) {  // do not block Ports
3100 							prio -= 500;
3101 						}
3102 						if (bo.is(BuildingAttribute::kNeedsBerry)) {
3103 							prio += std::abs(management_data.get_military_number_at(13)) *
3104 							        bf->bushes_nearby / 12;
3105 						}
3106 					} else if (bo.is(BuildingAttribute::kShipyard)) {
3107 						// for now AI builds only one shipyard
3108 						assert(bo.total_count() == 0);
3109 						if (bf->open_water_nearby > 3 && map_allows_seafaring_) {
3110 							prio += productionsites.size() * 5 +
3111 							        bf->open_water_nearby *
3112 							           std::abs(management_data.get_military_number_at(109)) / 10;
3113 						} else {
3114 							continue;
3115 						}
3116 					}
3117 
3118 					// considering neededness depending on stocklevel
3119 					const uint32_t current_stocklevel = (get_stocklevel(bo, gametime));
3120 					if (current_stocklevel > 50 &&
3121 					    persistent_data->remaining_basic_buildings.count(bo.id) == 0) {
3122 						continue;
3123 					}
3124 					if (current_stocklevel < 40) {
3125 						prio += 5 *
3126 						        management_data.neuron_pool[23].get_result_safe(
3127 						           (40 - current_stocklevel) / 2, kAbsValue);
3128 					}
3129 					// This considers supporters nearby
3130 					for (auto ph : bo.ware_outputs) {
3131 						prio += management_data.neuron_pool[52].get_result_safe(
3132 						           bf->supporters_nearby.at(ph) * 5, kAbsValue) /
3133 						        2;
3134 					}
3135 
3136 					if (prio <= 0) {
3137 						continue;
3138 					}
3139 
3140 					// bonus for big buildings if shortage of big fields
3141 					if (spots_avail.at(BUILDCAPS_BIG) <= 5 && bo.desc->get_size() == 3) {
3142 						prio += std::abs(management_data.get_military_number_at(105)) / 5;
3143 					}
3144 
3145 					if (spots_avail.at(BUILDCAPS_MEDIUM) <= 5 && bo.desc->get_size() == 2) {
3146 						prio += std::abs(management_data.get_military_number_at(106)) / 5;
3147 					}
3148 
3149 					// +1 if any consumers_ are nearby
3150 					consumers_nearby_count = 0;
3151 
3152 					for (size_t k = 0; k < bo.ware_outputs.size(); ++k) {
3153 						consumers_nearby_count += bf->consumers_nearby.at(bo.ware_outputs.at(k));
3154 					}
3155 
3156 					if (consumers_nearby_count > 0) {
3157 						prio += std::abs(management_data.get_military_number_at(107)) / 3;
3158 					}
3159 				}
3160 
3161 				// Consider border with exemption of some huts
3162 				if (!(bo.is(BuildingAttribute::kLumberjack) || bo.is(BuildingAttribute::kNeedsCoast) ||
3163 				      bo.is(BuildingAttribute::kFisher))) {
3164 					prio += recalc_with_border_range(*bf, prio);
3165 				} else if (bf->near_border && (bo.is(BuildingAttribute::kLumberjack) ||
3166 				                               bo.is(BuildingAttribute::kNeedsCoast))) {
3167 					prio /= 2;
3168 				}
3169 
3170 			}  // production sites done
3171 			else if (bo.type == BuildingObserver::Type::kMilitarysite) {
3172 
3173 				prio += bo.primary_priority;
3174 
3175 				// Two possibilities why to construct militarysite here
3176 				if (!bf->defense_msite_allowed &&
3177 				    (bf->nearest_buildable_spot_nearby < bo.desc->get_conquers() ||
3178 				     bf->unowned_portspace_vicinity_nearby > 0) &&
3179 				    (bf->military_in_constr_nearby + bf->military_unstationed) <
3180 				       concurent_ms_in_constr_no_enemy) {
3181 					// it will conquer new buildable spots for buildings or mines
3182 				} else if (bf->defense_msite_allowed &&
3183 				           (bf->military_in_constr_nearby + bf->military_unstationed) <
3184 				              concurent_ms_in_constr_enemy_nearby) {
3185 					// we need it to increase capacity on the field
3186 					if (bo.fighting_type) {
3187 						prio += 5;
3188 					}
3189 				} else {
3190 					continue;
3191 				}
3192 				if (bf->unowned_mines_spots_nearby > 2 && bo.mountain_conqueror) {
3193 					prio += 5;
3194 				}
3195 				prio += std::abs(management_data.get_military_number_at(35)) / 5 *
3196 				        (static_cast<int16_t>(bo.desc->get_conquers()) -
3197 				         static_cast<int16_t>(bf->nearest_buildable_spot_nearby));
3198 
3199 				prio += bf->military_score_;
3200 
3201 				// if place+building is not good enough
3202 				if (prio <= persistent_data->target_military_score) {
3203 					continue;
3204 				}
3205 				if (prio > persistent_data->ai_personality_mil_upper_limit) {
3206 					persistent_data->ai_personality_mil_upper_limit = prio;
3207 				}
3208 			} else if (bo.type == BuildingObserver::Type::kWarehouse) {
3209 
3210 				// exclude spots on border
3211 				if (bf->near_border && !bo.is(BuildingAttribute::kPort)) {
3212 					continue;
3213 				}
3214 				assert(bf->is_portspace != ExtendedBool::kUnset);
3215 				if (bf->is_portspace != ExtendedBool::kTrue && bo.is(BuildingAttribute::kPort)) {
3216 					continue;
3217 				}
3218 				prio += bo.primary_priority;
3219 
3220 				// iterating over current warehouses and testing a distance
3221 				// getting distance to nearest warehouse and adding it to a score
3222 				uint16_t nearest_distance = std::numeric_limits<uint16_t>::max();
3223 				for (const WarehouseSiteObserver& wh_obs : warehousesites) {
3224 					const uint16_t actual_distance =
3225 					   map.calc_distance(bf->coords, wh_obs.site->get_position());
3226 					nearest_distance = std::min(nearest_distance, actual_distance);
3227 				}
3228 				// but limit to 30
3229 				const uint16_t max_distance_considered = 30;
3230 				nearest_distance = std::min(nearest_distance, max_distance_considered);
3231 				if (nearest_distance < 13) {
3232 					continue;
3233 				}
3234 				prio +=
3235 				   management_data.neuron_pool[47].get_result_safe(nearest_distance / 2, kAbsValue) / 2;
3236 
3237 				prio += bf->own_non_military_nearby * 3;
3238 
3239 				// dont be close to enemies
3240 				if (bf->enemy_nearby) {
3241 					prio -= 40;
3242 				}
3243 
3244 				// being too close to a border is not good either
3245 				if ((bf->unowned_land_nearby || bf->enemy_owned_land_nearby > 10) &&
3246 				    !bo.is(BuildingAttribute::kPort) && prio > 0) {
3247 					prio /= 2;
3248 					prio -= 10;
3249 				}
3250 
3251 			} else if (bo.type == BuildingObserver::Type::kTrainingsite) {
3252 
3253 				// Even if a site is forced it has kNeeded necessity now
3254 				assert(bo.primary_priority > 0 && bo.new_building == BuildingNecessity::kNeeded);
3255 
3256 				prio += bo.primary_priority;
3257 
3258 				// for spots close to a border
3259 				if (bf->near_border) {
3260 					prio -= 5;
3261 				}
3262 
3263 				// take care about borders and enemies
3264 				if (bf->enemy_nearby) {
3265 					prio -= 20;
3266 				}
3267 
3268 				if (bf->unowned_land_nearby || bf->enemy_owned_land_nearby) {
3269 					prio -= 15;
3270 				}
3271 			}
3272 
3273 			// think of space consuming buildings nearby like farms or vineyards
3274 			if (bo.type != BuildingObserver::Type::kMilitarysite) {
3275 				prio -= bf->space_consumers_nearby * 10;
3276 			}
3277 
3278 			// Stop here, if priority is 0 or less.
3279 			if (prio <= 0) {
3280 				continue;
3281 			}
3282 
3283 			// Prefer road side fields
3284 			prio += bf->preferred ? 5 : 0;
3285 
3286 			// don't waste good land for small huts
3287 			const bool space_stress =
3288 			   (spots_avail.at(BUILDCAPS_MEDIUM) < 5 || spots_avail.at(BUILDCAPS_BIG) < 5);
3289 
3290 			if (space_stress && bo.type == BuildingObserver::Type::kMilitarysite) {
3291 				prio -= (bf->max_buildcap_nearby - bo.desc->get_size()) * 10;
3292 			} else if (space_stress) {
3293 				prio -= (bf->max_buildcap_nearby - bo.desc->get_size()) * 30;
3294 			} else {
3295 				prio -= (bf->max_buildcap_nearby - bo.desc->get_size()) * 5;
3296 			}
3297 
3298 			// prefer vicinity of ports (with exemption of warehouses)
3299 			if (bf->port_nearby && bo.type == BuildingObserver::Type::kMilitarysite) {
3300 				prio *= 2;
3301 			}
3302 
3303 			if (bo.type != BuildingObserver::Type::kMilitarysite && highest_nonmil_prio_ < prio) {
3304 				highest_nonmil_prio_ = prio;
3305 			}
3306 
3307 			if (bo.type == BuildingObserver::Type::kMilitarysite) {
3308 				if (prio <= persistent_data->target_military_score) {
3309 					continue;
3310 				}
3311 			}
3312 
3313 			if (prio > proposed_priority) {
3314 				best_building = &bo;
3315 				proposed_priority = prio;
3316 				proposed_coords = bf->coords;
3317 			}
3318 		}  // ending loop over buildings
3319 	}     // ending loop over fields
3320 
3321 	// then try all mines_ - as soon as basic economy is build up.
3322 	if (gametime > next_mine_construction_due_) {
3323 
3324 		// not done here
3325 		// update_all_mineable_fields(gametime);
3326 		next_mine_construction_due_ = gametime + kNewMineConstInterval;
3327 
3328 		if (!mineable_fields.empty()) {
3329 
3330 			for (BuildingObserver& bo : buildings_) {
3331 				if (productionsites.size() <= 8) {
3332 					break;
3333 				}
3334 
3335 				if (bo.type != BuildingObserver::Type::kMine) {
3336 					continue;
3337 				}
3338 
3339 				assert(bo.new_building != BuildingNecessity::kAllowed);
3340 
3341 				// skip if a mine is not required
3342 				if (!(bo.new_building == BuildingNecessity::kNeeded ||
3343 				      bo.new_building == BuildingNecessity::kForced)) {
3344 					continue;
3345 				}
3346 
3347 				// iterating over fields
3348 				for (std::deque<MineableField*>::iterator j = mineable_fields.begin();
3349 				     j != mineable_fields.end(); ++j) {
3350 
3351 					MineableField* const mf = *j;
3352 
3353 					if (mf->field_info_expiration <= gametime) {
3354 						continue;
3355 					}
3356 
3357 					if (mf->coords.field->get_resources() != bo.mines) {
3358 						continue;
3359 					}
3360 
3361 					// Continue if field is blocked at the moment
3362 					if (blocked_fields.is_blocked(mf->coords)) {
3363 						continue;
3364 					}
3365 
3366 					int32_t prio = 0;
3367 					MapRegion<Area<FCoords>> mr(map, Area<FCoords>(mf->coords, 2));
3368 					do {
3369 						if (bo.mines == mr.location().field->get_resources()) {
3370 							prio += mr.location().field->get_resources_amount();
3371 						}
3372 					} while (mr.advance(map));
3373 
3374 					prio /= 10;
3375 
3376 					// Only build mines_ on locations where some material can be mined
3377 					if (prio < 1) {
3378 						continue;
3379 					}
3380 
3381 					// applying nearnest penalty
3382 					prio -= mf->mines_nearby * std::abs(management_data.get_military_number_at(126));
3383 
3384 					// applying max needed
3385 					prio += bo.primary_priority;
3386 
3387 					// prefer mines in the middle of mine fields of the
3388 					// same type, so we add a small bonus here
3389 					// depending on count of same mines nearby,
3390 					// though this does not reflects how many resources
3391 					// are (left) in nearby mines
3392 					prio += mf->same_mine_fields_nearby;
3393 
3394 					// Continue if field is blocked at the moment
3395 					if (blocked_fields.is_blocked(mf->coords)) {
3396 						continue;
3397 					}
3398 
3399 					// Prefer road side fields
3400 					prio += mf->preferred ? 1 : 0;
3401 
3402 					prio += bo.primary_priority;
3403 
3404 					if (prio > proposed_priority) {
3405 						best_building = &bo;
3406 						proposed_priority = prio;
3407 						proposed_coords = mf->coords;
3408 						mine = true;
3409 					}
3410 
3411 					if (prio > highest_nonmil_prio_) {
3412 						highest_nonmil_prio_ = prio;
3413 					}
3414 				}  // end of evaluation of field
3415 			}
3416 
3417 		}  // section if mine size >0
3418 	}     // end of mines_ section
3419 
3420 	// if there is no winner:
3421 	if (best_building == nullptr) {
3422 		return false;
3423 	}
3424 
3425 	if (best_building->type == BuildingObserver::Type::kMilitarysite) {
3426 		assert(proposed_priority >= persistent_data->least_military_score);
3427 		persistent_data->target_military_score = proposed_priority;
3428 		if (persistent_data->target_military_score >
3429 		    persistent_data->ai_personality_mil_upper_limit) {
3430 			persistent_data->ai_personality_mil_upper_limit = persistent_data->target_military_score;
3431 		}
3432 		assert(proposed_priority >= persistent_data->least_military_score);
3433 	}
3434 
3435 	// send the command to construct a new building
3436 	game().send_player_build(player_number(), proposed_coords, best_building->id);
3437 	blocked_fields.add(proposed_coords, game().get_gametime() + 2 * 60 * 1000);
3438 
3439 	// resetting new_building_overdue
3440 	best_building->new_building_overdue = 0;
3441 
3442 	// we block also nearby fields
3443 	// if farms and so on, for quite a long time
3444 	// if military sites only for short time for AI can update information on near buildable fields
3445 	if ((best_building->is(BuildingAttribute::kSpaceConsumer) &&
3446 	     !best_building->is(BuildingAttribute::kRanger)) ||
3447 	    best_building->type == BuildingObserver::Type::kMilitarysite) {
3448 		uint32_t block_time = 0;
3449 		uint32_t block_area = 0;
3450 		if (best_building->is(BuildingAttribute::kSpaceConsumer)) {
3451 			if (spots_ > kSpotsEnough) {
3452 				block_time = 45 * 60 * 1000;
3453 			} else {
3454 				block_time = 15 * 60 * 1000;
3455 			}
3456 			block_area = 5;
3457 		} else {  // militray buildings for a very short time
3458 			block_time = 25 * 1000;
3459 			block_area = 6;
3460 		}
3461 
3462 		MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(proposed_coords), block_area));
3463 		do {
3464 			blocked_fields.add(mr.location(), game().get_gametime() + block_time);
3465 		} while (mr.advance(map));
3466 	}
3467 
3468 	if (best_building->is(BuildingAttribute::kRecruitment)) {
3469 		log("%2d: Building a recruitment site: %s\n", player_number(), best_building->name);
3470 	}
3471 
3472 	if (!(best_building->type == BuildingObserver::Type::kMilitarysite)) {
3473 		best_building->construction_decision_time = gametime;
3474 	} else {
3475 		military_last_build_ = gametime;
3476 		best_building->construction_decision_time = gametime - kBuildingMinInterval / 2;
3477 	}
3478 
3479 	// set the type of update that is needed
3480 	if (mine) {
3481 		next_mine_construction_due_ = gametime + kBusyMineUpdateInterval;
3482 	}
3483 
3484 	return true;
3485 }
3486 
3487 // Re-calculating warehouse to flag distances
check_flag_distances(const uint32_t gametime)3488 void DefaultAI::check_flag_distances(const uint32_t gametime) {
3489 	for (WarehouseSiteObserver& wh_obs : warehousesites) {
3490 		uint16_t checked_flags = 0;
3491 		const uint32_t this_wh_hash = wh_obs.site->get_position().hash();
3492 		uint32_t highest_distance_set = 0;
3493 
3494 		std::queue<Widelands::Flag*>
3495 		   remaining_flags;  // only used to collect flags reachable walk over roads
3496 		remaining_flags.push(&wh_obs.site->base_flag());
3497 		flag_warehouse_distance.set_distance(
3498 		   wh_obs.site->base_flag().get_position().hash(), 0, gametime, this_wh_hash);
3499 		uint32_t tmp_wh;
3500 		assert(flag_warehouse_distance.get_distance(
3501 		          wh_obs.site->base_flag().get_position().hash(), gametime, &tmp_wh) == 0);
3502 
3503 		// Algorithm to walk on roads
3504 		// All nodes are marked as to_be_checked == true first and once the node is checked it is
3505 		// changed to false. Under some conditions, the same node can be checked twice, the
3506 		// to_be_checked can be set back to true. Because less hoops (fewer flag-to-flag roads) does
3507 		// not always mean shortest road.
3508 		while (!remaining_flags.empty()) {
3509 			++checked_flags;
3510 			// looking for a node with shortest existing road distance from starting flag and one that
3511 			// has to be checked Now going over roads leading from this flag
3512 			const uint16_t current_flag_distance = flag_warehouse_distance.get_distance(
3513 			   remaining_flags.front()->get_position().hash(), gametime, &tmp_wh);
3514 			for (uint8_t i = WalkingDir::FIRST_DIRECTION; i <= WalkingDir::LAST_DIRECTION; ++i) {
3515 				Road* const road = remaining_flags.front()->get_road(i);
3516 
3517 				if (!road) {
3518 					continue;
3519 				}
3520 
3521 				Flag* endflag = &road->get_flag(Road::FlagStart);
3522 
3523 				if (endflag == remaining_flags.front()) {
3524 					endflag = &road->get_flag(Road::FlagEnd);
3525 				}
3526 				const uint16_t steps_count = road->get_path().get_nsteps();
3527 
3528 				// Calculated distance can be used or ignored if f.e. longer than via other route
3529 				bool const updated = flag_warehouse_distance.set_distance(
3530 				   endflag->get_position().hash(), current_flag_distance + steps_count, gametime,
3531 				   this_wh_hash);
3532 
3533 				if (highest_distance_set < current_flag_distance + steps_count) {
3534 					highest_distance_set = current_flag_distance + steps_count;
3535 				}
3536 
3537 				if (updated) {
3538 					remaining_flags.push(endflag);
3539 				}
3540 			}
3541 			remaining_flags.pop();
3542 		}
3543 	}
3544 
3545 	// Now let do some lazy pruning - remove the flags that were not updated for long
3546 	flag_warehouse_distance.remove_old_flag(gametime);
3547 }
3548 
3549 // Here we pick about 25 roads and investigate them. If it is a dead end we dismantle it
dismantle_dead_ends()3550 bool DefaultAI::dismantle_dead_ends() {
3551 	bool road_dismantled = false;
3552 	const uint16_t stepping = roads.size() / 25 + 1;
3553 
3554 	for (uint16_t i = 0; i < roads.size(); i += stepping) {
3555 		const Flag& roadstartflag = roads[i]->get_flag(RoadBase::FlagStart);
3556 		const Flag& roadendflag = roads[i]->get_flag(RoadBase::FlagEnd);
3557 
3558 		if (!roadstartflag.get_building() && roadstartflag.is_dead_end()) {
3559 			game().send_player_bulldoze(*const_cast<Flag*>(&roadstartflag));
3560 			road_dismantled = true;
3561 		}
3562 
3563 		if (!roadendflag.get_building() && roadendflag.is_dead_end()) {
3564 			game().send_player_bulldoze(*const_cast<Flag*>(&roadendflag));
3565 			road_dismantled = true;
3566 		}
3567 	}
3568 	return road_dismantled;
3569 }
3570 
3571 // improves current road system
improve_roads(uint32_t gametime)3572 bool DefaultAI::improve_roads(uint32_t gametime) {
3573 
3574 	// First try to dismantle some dead ends on road
3575 	if (dead_ends_check_ || gametime % 50 == 0) {
3576 		if (dismantle_dead_ends()) {
3577 			return true;
3578 		}
3579 		dead_ends_check_ = false;
3580 		return false;
3581 	}
3582 
3583 	if (!roads.empty()) {
3584 		const Path& path = roads.front()->get_path();
3585 
3586 		// first force a split on roads that are longer than 3 parts
3587 		if (path.get_nsteps() > 3 && spots_ > kSpotsEnough) {
3588 			const Map& map = game().map();
3589 			CoordPath cp(map, path);
3590 			// try to split after two steps
3591 			CoordPath::StepVector::size_type i = cp.get_nsteps() - 1, j = 1;
3592 
3593 			for (; i >= j; --i, ++j) {
3594 				{
3595 					const Coords c = cp.get_coords().at(i);
3596 
3597 					if (map[c].nodecaps() & BUILDCAPS_FLAG) {
3598 						game().send_player_build_flag(player_number(), c);
3599 						return true;
3600 					}
3601 				}
3602 				{
3603 					const Coords c = cp.get_coords().at(j);
3604 
3605 					if (map[c].nodecaps() & BUILDCAPS_FLAG) {
3606 						game().send_player_build_flag(player_number(), c);
3607 						return true;
3608 					}
3609 				}
3610 			}
3611 
3612 			// Unable to set a flag - perhaps the road was build stupid
3613 			game().send_player_bulldoze(*const_cast<Road*>(roads.front()));
3614 			dead_ends_check_ = true;
3615 			return true;
3616 		}
3617 
3618 		roads.push_back(roads.front());
3619 		roads.pop_front();
3620 
3621 		// Occasionaly (not more then once in 15 seconds) we test if the road can be dismantled
3622 		// if there is shortage of spots we do it always
3623 		if (last_road_dismantled_ + 15 * 1000 < gametime &&
3624 		    (gametime % 40 == 0 || spots_ <= kSpotsEnough)) {
3625 			const Road& road = *roads.front();
3626 			if (dispensable_road_test(*const_cast<Road*>(&road))) {
3627 				game().send_player_bulldoze(*const_cast<Road*>(&road));
3628 				last_road_dismantled_ = gametime;
3629 				dead_ends_check_ = true;
3630 				return true;
3631 			}
3632 		}
3633 	}
3634 	// now we rotate economies and flags to get one flag to go on with
3635 	if (economies.empty()) {
3636 		check_economies();
3637 		return false;
3638 	}
3639 
3640 	if (economies.size() >= 2) {  // rotating economies
3641 		economies.push_back(economies.front());
3642 		economies.pop_front();
3643 	}
3644 
3645 	EconomyObserver* eco = economies.front();
3646 	if (eco->flags.empty()) {
3647 		check_economies();
3648 		return false;
3649 	}
3650 	if (eco->flags.size() > 1) {
3651 		eco->flags.push_back(eco->flags.front());
3652 		eco->flags.pop_front();
3653 	}
3654 
3655 	const Flag& flag = *eco->flags.front();
3656 
3657 	// now we test if it is dead end flag, if yes, destroying it
3658 	if (flag.is_dead_end() && flag.current_wares() == 0) {
3659 		game().send_player_bulldoze(*const_cast<Flag*>(&flag));
3660 		eco->flags.pop_front();
3661 		return true;
3662 	}
3663 
3664 	bool is_warehouse = false;
3665 	if (Building* b = flag.get_building()) {
3666 		BuildingObserver& bo = get_building_observer(b->descr().name().c_str());
3667 		if (bo.type == BuildingObserver::Type::kWarehouse) {
3668 			is_warehouse = true;
3669 		}
3670 	}
3671 	const uint32_t flag_coords_hash = flag.get_position().hash();
3672 
3673 	if (flag_warehouse_distance.is_road_prohibited(flag_coords_hash, gametime)) {
3674 		return false;
3675 	}
3676 	// TODO(Nordfriese): Someone should update the code since the big economy splitting for the
3677 	// ferries
3678 	const bool needs_warehouse = flag.get_economy(wwWORKER)->warehouses().empty();
3679 
3680 	uint32_t tmp_wh;
3681 
3682 	// when deciding if we attempt to build a road from here we use probability
3683 	uint16_t probability_score = 0;
3684 	if (flag.nr_of_roads() == 1) {
3685 		probability_score += 20;
3686 	}
3687 	if (is_warehouse && flag.nr_of_roads() <= 3) {
3688 		probability_score += 20;
3689 	}
3690 	probability_score += flag.current_wares() * 5;
3691 	if (needs_warehouse) {
3692 		probability_score += 500;
3693 	}
3694 	if (std::rand() % 10 == 0) {
3695 		probability_score +=
3696 		   flag_warehouse_distance.get_distance(flag_coords_hash, gametime, &tmp_wh);
3697 	}
3698 
3699 	if (std::rand() % 200 < probability_score) {
3700 		create_shortcut_road(flag, 14, gametime);
3701 		return true;
3702 	}
3703 
3704 	return false;
3705 }
3706 
3707 // This function takes a road (road is smallest section of roads with two flags on the ends)
3708 // look for longer section of road that starts and ends with building/road crossing
3709 // and tries to find alternative route from one end flag to another.
3710 // If route exists, it is not too long, and current road is not intensively used
3711 // the road can be dismantled
dispensable_road_test(const Widelands::Road & road)3712 bool DefaultAI::dispensable_road_test(const Widelands::Road& road) {
3713 
3714 	Flag& roadstartflag = road.get_flag(RoadBase::FlagStart);
3715 	Flag& roadendflag = road.get_flag(RoadBase::FlagEnd);
3716 
3717 	// Calculating full road (from crossing/building to another crossing/building),
3718 	// this means we calculate vector of all flags of the "full road"
3719 	std::vector<Widelands::Flag*> full_road;
3720 	full_road.push_back(&roadstartflag);
3721 	full_road.push_back(&roadendflag);
3722 
3723 	uint16_t road_length = road.get_path().get_nsteps();
3724 
3725 	for (int j = 0; j < 2; ++j) {
3726 		bool new_road_found = true;
3727 		while (new_road_found && full_road.back()->nr_of_roads() <= 2 &&
3728 		       full_road.back()->get_building() == nullptr) {
3729 			new_road_found = false;
3730 			for (uint8_t i = WalkingDir::FIRST_DIRECTION; i <= WalkingDir::LAST_DIRECTION; ++i) {
3731 				Road* const near_road = full_road.back()->get_road(i);
3732 
3733 				if (!near_road) {
3734 					continue;
3735 				}
3736 
3737 				Flag* other_end;
3738 				if (near_road->get_flag(RoadBase::FlagStart).get_position().hash() ==
3739 				    full_road.back()->get_position().hash()) {
3740 					other_end = &near_road->get_flag(RoadBase::FlagEnd);
3741 				} else {
3742 					other_end = &near_road->get_flag(RoadBase::FlagStart);
3743 				}
3744 
3745 				// Have we already the end of road in our full_road?
3746 				if (std::find(full_road.begin(), full_road.end(), other_end) == full_road.end()) {
3747 					full_road.push_back(other_end);
3748 					road_length += near_road->get_path().get_nsteps();
3749 					new_road_found = true;
3750 					break;
3751 				}
3752 			}
3753 		}
3754 		// we walked to one end, now let revert the content of full_road and repeat in opposite
3755 		// direction
3756 		std::reverse(full_road.begin(), full_road.end());
3757 	}
3758 
3759 	// To make decision how intensively the road is used, we count wares on it, but we distinguish
3760 	// situation when entire road has only 2 flags or is longer
3761 	uint16_t wares_on_road = 0;
3762 	assert(full_road.size() > 1);
3763 	if (full_road.size() == 2) {
3764 		wares_on_road = roadstartflag.current_wares() + roadendflag.current_wares();
3765 	} else {
3766 		// We count wares only on inner flags
3767 		for (uint16_t k = 1; k < full_road.size() - 1; ++k) {
3768 			wares_on_road += full_road[k]->current_wares();
3769 		}
3770 	}
3771 
3772 	// If it by chance starts or ends next to a warehouse...
3773 	if (Building* b = full_road.front()->get_building()) {
3774 		BuildingObserver& bo = get_building_observer(b->descr().name().c_str());
3775 		if (bo.type == BuildingObserver::Type::kWarehouse) {
3776 			return false;
3777 		}
3778 	}
3779 	if (Building* b = full_road.back()->get_building()) {
3780 		BuildingObserver& bo = get_building_observer(b->descr().name().c_str());
3781 		if (bo.type == BuildingObserver::Type::kWarehouse) {
3782 			return false;
3783 		}
3784 	}
3785 
3786 	if (spots_ > kSpotsEnough && wares_on_road > 5) {
3787 		return false;
3788 	} else if (wares_on_road > 8) {
3789 		return false;
3790 	}
3791 
3792 	std::priority_queue<NearFlag> queue;
3793 	// only used to collect flags reachable walking over roads
3794 	std::vector<NearFlag> reachableflags;
3795 
3796 	queue.push(NearFlag(full_road.front(), 0));
3797 	uint16_t alternative_path = std::numeric_limits<uint16_t>::max();
3798 	const uint8_t checkradius = 3 *
3799 	                            game().map().calc_distance(full_road.front()->get_position(),
3800 	                                                       full_road.back()->get_position());
3801 
3802 	// algorithm to walk on roads
3803 	while (!queue.empty()) {
3804 
3805 		// Testing if we stand on the roadendflag... if yes, the alternative path is found, no reason
3806 		// to go on
3807 		if (full_road.back()->get_position().x == queue.top().flag->get_position().x &&
3808 		    full_road.back()->get_position().y == queue.top().flag->get_position().y) {
3809 			alternative_path = queue.top().current_road_distance;
3810 			break;
3811 		}
3812 
3813 		// If we were here, do not evaluate the flag again
3814 		std::vector<NearFlag>::iterator f =
3815 		   find(reachableflags.begin(), reachableflags.end(), queue.top().flag);
3816 		if (f != reachableflags.end()) {
3817 			queue.pop();
3818 			continue;
3819 		}
3820 
3821 		reachableflags.push_back(queue.top());
3822 		queue.pop();
3823 		NearFlag& nf = reachableflags.back();
3824 
3825 		// Now go over roads going from this flag
3826 		for (uint8_t i = WalkingDir::FIRST_DIRECTION; i <= WalkingDir::LAST_DIRECTION; ++i) {
3827 			Road* const near_road = nf.flag->get_road(i);
3828 
3829 			if (!near_road) {
3830 				continue;
3831 			}
3832 
3833 			// alternate road cannot lead via road to be dismantled
3834 			if (near_road->serial() == road.serial()) {
3835 				continue;
3836 			}
3837 
3838 			Flag* endflag = &near_road->get_flag(RoadBase::FlagStart);
3839 
3840 			if (endflag == nf.flag) {
3841 				endflag = &near_road->get_flag(RoadBase::FlagEnd);
3842 			}
3843 
3844 			// When walking on nearby roads, we do not go too far from start and end of road
3845 			const int32_t dist1 =
3846 			   game().map().calc_distance(full_road.front()->get_position(), endflag->get_position());
3847 			const int32_t dist2 =
3848 			   game().map().calc_distance(full_road.back()->get_position(), endflag->get_position());
3849 			if ((dist1 + dist2) > checkradius) {
3850 				continue;
3851 			}
3852 
3853 			const uint32_t new_length = nf.current_road_distance + near_road->get_path().get_nsteps();
3854 			queue.push(NearFlag(endflag, new_length));
3855 		}
3856 	}
3857 
3858 	if (alternative_path + wares_on_road <= road_length + 12) {
3859 		return true;
3860 	}
3861 
3862 	return false;
3863 }
3864 
3865 // Trying to connect the flag to another one, be it from own economy
3866 // or other economy
3867 // The procedure is:
3868 // - Collect all flags within checkradius into RoadCandidates, but first we dont even know if a road
3869 // can be built to them
3870 // - Walking over road network to collect info on flags that are accessible over road network
3871 // - Then merge info from NearFlags to RoadCandidates and consider roads to few best candidates from
3872 // RoadCandidates. We use score named "reduction" that is basically diff between connection over
3873 // existing roads minus possible road from starting flag to candidate flag. Of course there are two
3874 // special cases:
3875 // - the candidate flag does not belong to the same economy, so no road connection exists
3876 // - they are from same economy, but are connected beyond range of checkradius, so actual length of
3877 // connection is not known
create_shortcut_road(const Flag & flag,uint16_t checkradius,uint32_t gametime)3878 bool DefaultAI::create_shortcut_road(const Flag& flag, uint16_t checkradius, uint32_t gametime) {
3879 
3880 	// Increasing the failed_connection_tries counter
3881 	// At the same time it indicates a time an economy is without a warehouse
3882 	// TODO(Nordfriese): Someone should update the code since the big economy splitting for the
3883 	// ferries
3884 	EconomyObserver* eco = get_economy_observer(flag.economy(wwWORKER));
3885 	// if we passed grace time this will be last attempt and if it fails
3886 	// building is destroyed
3887 	bool last_attempt_ = false;
3888 
3889 	// this should not happen, but if the economy has a warehouse and a dismantle
3890 	// grace time set, we must 'zero' the dismantle grace time
3891 	if (!flag.get_economy(wwWORKER)->warehouses().empty() && eco->dismantle_grace_time != kNever) {
3892 		eco->dismantle_grace_time = kNever;
3893 	}
3894 
3895 	// first we deal with situations when this is economy with no warehouses
3896 	// and this is a flag belonging to a building/constructionsite
3897 	// such economy must get dismantle grace time (if not set yet)
3898 	// end sometimes extended checkradius
3899 	if (flag.get_economy(wwWORKER)->warehouses().empty() && flag.get_building()) {
3900 
3901 		// occupied military buildings get special treatment
3902 		// (extended grace time + longer radius)
3903 		bool occupied_military_ = false;
3904 		Building* b = flag.get_building();
3905 		if (upcast(MilitarySite, militb, b)) {
3906 			if (militb->soldier_control()->stationed_soldiers().size() > 0) {
3907 				occupied_military_ = true;
3908 			}
3909 		}
3910 
3911 		// check if we are within grace time, if not or gracetime unset we need to do something
3912 		// if we are within gracetime we do nothing (this loop is skipped)
3913 
3914 		// if grace time is not set, this is probably first time without a warehouse and we must set
3915 		// it
3916 		if (eco->dismantle_grace_time == kNever) {
3917 
3918 			// constructionsites
3919 			if (upcast(ConstructionSite const, constructionsite, flag.get_building())) {
3920 				BuildingObserver& bo =
3921 				   get_building_observer(constructionsite->building().name().c_str());
3922 				// first very special case - a port (in the phase of constructionsite)
3923 				// this might be a new colonization port
3924 				if (bo.is(BuildingAttribute::kPort)) {
3925 					eco->dismantle_grace_time = gametime + 60 * 60 * 1000;  // one hour should be enough
3926 				} else {  // other constructionsites, usually new (standalone) constructionsites
3927 					eco->dismantle_grace_time =
3928 					   gametime + 30 * 1000 +            // very shot time is enough
3929 					   (eco->flags.size() * 30 * 1000);  // + 30 seconds for every flag in economy
3930 				}
3931 
3932 				// buildings
3933 			} else {
3934 
3935 				if (occupied_military_) {
3936 					eco->dismantle_grace_time =
3937 					   (gametime + 90 * 60 * 1000) + (eco->flags.size() * 20 * 1000);
3938 
3939 				} else {  // for other normal buildings
3940 					eco->dismantle_grace_time =
3941 					   gametime + (45 * 60 * 1000) + (eco->flags.size() * 20 * 1000);
3942 				}
3943 			}
3944 
3945 			// we have passed grace_time - it is time to dismantle
3946 		} else if (eco->dismantle_grace_time <= gametime) {
3947 			last_attempt_ = true;
3948 			// we increase a check radius in last attempt
3949 			checkradius += 2;
3950 		}
3951 
3952 		// and bonus for occupied military buildings:
3953 		if (occupied_military_) {
3954 			checkradius += 4;
3955 		}
3956 
3957 		// and generally increase radius for unconnected buildings
3958 		checkradius += 2;
3959 	}
3960 
3961 	// Now own roadfinding stuff
3962 	const Map& map = game().map();
3963 
3964 	// Initializing new object of FlagsForRoads, we will push there all candidate flags
3965 	// First we dont even know if a road can be built there (from current flag)
3966 	// Adding also distance of this flag to nearest wh
3967 	uint32_t tmp_wh;  // This information is not used, but we need it
3968 	const uint32_t current_flag_dist_to_wh =
3969 	   flag_warehouse_distance.get_distance(flag.get_position().hash(), gametime, &tmp_wh);
3970 
3971 	FlagCandidates flag_candidates(current_flag_dist_to_wh);
3972 
3973 	FindNodeWithFlagOrRoad functor;
3974 	CheckStepRoadAI check(player_, MOVECAPS_WALK, true);
3975 
3976 	// get all flags within radius
3977 	std::vector<Coords> reachable;
3978 	map.find_reachable_fields(game(),
3979 	                          Area<FCoords>(map.get_fcoords(flag.get_position()), checkradius),
3980 	                          &reachable, check, functor);
3981 
3982 	for (const Coords& reachable_coords : reachable) {
3983 
3984 		// ignore starting flag, of course
3985 		if (reachable_coords == flag.get_position()) {
3986 			continue;
3987 		}
3988 
3989 		const uint32_t reachable_coords_hash = reachable_coords.hash();
3990 
3991 		// first make sure there is an immovable (should be, but still)
3992 		Widelands::BaseImmovable* this_immovable = map[reachable_coords].get_immovable();
3993 		if (upcast(PlayerImmovable const, player_immovable, this_immovable)) {
3994 
3995 			// if it is the road, make a flag there
3996 			if (this_immovable->descr().type() == MapObjectType::ROAD) {
3997 				game().send_player_build_flag(player_number(), reachable_coords);
3998 			}
3999 
4000 			// do not go on if it is not a flag
4001 			if (this_immovable->descr().type() != MapObjectType::FLAG) {
4002 				continue;
4003 			}
4004 
4005 			// testing if a flag/road's economy has a warehouse, if not we are not
4006 			// interested to connect to it
4007 			// TODO(Nordfriese): Someone should update the code since the big economy splitting for the
4008 			// ferries
4009 			if (player_immovable->economy(wwWORKER).warehouses().size() == 0) {
4010 				continue;
4011 			}
4012 
4013 			// This is a candidate, sending all necessary info to RoadCandidates
4014 			const bool is_different_economy =
4015 			   (player_immovable->get_economy(wwWORKER) != flag.get_economy(wwWORKER));
4016 			const uint16_t air_distance = map.calc_distance(flag.get_position(), reachable_coords);
4017 
4018 			if (!flag_candidates.has_candidate(reachable_coords_hash) &&
4019 			    !flag_warehouse_distance.is_road_prohibited(reachable_coords_hash, gametime)) {
4020 				flag_candidates.add_flag(
4021 				   reachable_coords_hash, is_different_economy,
4022 				   flag_warehouse_distance.get_distance(reachable_coords_hash, gametime, &tmp_wh),
4023 				   air_distance);
4024 			}
4025 		}
4026 	}
4027 
4028 	// now we walk over roads and if field is reachable by roads, we change the distance assigned
4029 	// above
4030 	std::map<uint32_t, NearFlag> nearflags;  // only used to collect flags reachable walk over roads
4031 	nearflags[flag.get_position().hash()] = NearFlag(&flag, 0);
4032 
4033 	collect_nearflags(nearflags, flag, checkradius);
4034 
4035 	// Sending calculated walking costs from nearflags to RoadCandidates to update info on
4036 	// Candidate flags/roads
4037 	for (auto& nf_walk : nearflags) {
4038 		const uint32_t nf_hash = nf_walk.second.flag->get_position().hash();
4039 		// NearFlag contains also flags beyond check radius, these are not relevant for us
4040 		if (flag_candidates.has_candidate(nf_hash)) {
4041 			flag_candidates.set_cur_road_distance(nf_hash, nf_walk.second.current_road_distance);
4042 		}
4043 	}
4044 
4045 	// Here we must consider how much are buildable fields lacking
4046 	// the number will be transformed to a weight passed to findpath function
4047 	int32_t fields_necessity = 0;
4048 	if (spots_ < kSpotsTooLittle) {
4049 		fields_necessity += 10;
4050 	}
4051 	if (map_allows_seafaring_ && num_ports == 0) {
4052 		fields_necessity += 10;
4053 	}
4054 	if (num_ports < 4) {
4055 		fields_necessity += 5;
4056 	}
4057 	if (spots_ < kSpotsEnough) {
4058 		fields_necessity += 5;
4059 	}
4060 
4061 	fields_necessity *= std::abs(management_data.get_military_number_at(64)) * 5;
4062 
4063 	// Now we calculate roads from here to few best looking RoadCandidates....
4064 	flag_candidates.sort_by_air_distance();
4065 	uint32_t possible_roads_count = 0;
4066 	for (const auto& flag_candidate : flag_candidates.flags()) {
4067 		if (possible_roads_count > 10) {
4068 			break;
4069 		}
4070 		const Widelands::Coords coords = Coords::unhash(flag_candidate.coords_hash);
4071 		Path path;
4072 
4073 		// value of pathcost is not important, it just indicates, that the path can be built
4074 		// We send this information to RoadCandidates, with length of possible road if applicable
4075 		const int32_t pathcost =
4076 		   map.findpath(flag.get_position(), coords, 0, path, check, 0, fields_necessity);
4077 		if (pathcost >= 0) {
4078 			flag_candidates.set_road_possible(flag_candidate.coords_hash, path.get_nsteps());
4079 			++possible_roads_count;
4080 		}
4081 	}
4082 
4083 	// re-sorting again now by default by a score
4084 	flag_candidates.sort();
4085 
4086 	// Well and finally building the winning road (if any)
4087 	const int32_t winner_min_score = (spots_ < kSpotsTooLittle) ? 50 : 25;
4088 
4089 	FlagCandidates::Candidate* winner = flag_candidates.get_winner(winner_min_score);
4090 	if (winner) {
4091 		const Widelands::Coords target_coords = Coords::unhash(winner->coords_hash);
4092 
4093 		// This is to prohibit the flag for some time but with exemption of warehouse
4094 		if (flag_warehouse_distance.get_distance(winner->coords_hash, gametime, &tmp_wh) > 0) {
4095 			flag_warehouse_distance.set_road_built(winner->coords_hash, gametime);
4096 		}
4097 		// and we straight away set distance of future flag
4098 		flag_warehouse_distance.set_distance(
4099 		   flag.get_position().hash(), winner->start_flag_dist_to_wh + winner->possible_road_distance,
4100 		   gametime, 0);  // faking the warehouse
4101 
4102 		Path& path = *new Path();
4103 #ifndef NDEBUG
4104 		const int32_t pathcost =
4105 		   map.findpath(flag.get_position(), target_coords, 0, path, check, 0, fields_necessity);
4106 		assert(pathcost >= 0);
4107 #else
4108 		map.findpath(flag.get_position(), target_coords, 0, path, check, 0, fields_necessity);
4109 #endif
4110 		game().send_player_build_road(player_number(), path);
4111 		return true;
4112 	}
4113 	// We can't build a road so let's block the vicinity as an indication this area is not
4114 	// connectible
4115 	// Usually we block for 2 minutes, but if it is a last attempt we block for 10 minutes
4116 	// Note: we block the vicinity only if this economy (usually a sole flag with a building) is not
4117 	// connected to a warehouse
4118 	// TODO(Nordfriese): Someone should update the code since the big economy splitting for the
4119 	// ferries
4120 	if (flag.get_economy(wwWORKER)->warehouses().empty()) {
4121 
4122 		// blocking only if latest block was less then 60 seconds ago or it is last attempt
4123 		if (eco->fields_block_last_time + kOneMinute < gametime || last_attempt_) {
4124 			eco->fields_block_last_time = gametime;
4125 
4126 			const uint32_t block_time = last_attempt_ ? 10 * kOneMinute : 2 * kOneMinute;
4127 
4128 			FindNodeAcceptAll buildable_functor;
4129 			CheckStepOwnTerritory check_own(player_, MOVECAPS_WALK, true);
4130 
4131 			// get all flags within radius
4132 			std::vector<Coords> reachable_to_block;
4133 			map.find_reachable_fields(game(),
4134 			                          Area<FCoords>(map.get_fcoords(flag.get_position()), checkradius),
4135 			                          &reachable_to_block, check_own, buildable_functor);
4136 
4137 			for (auto coords : reachable_to_block) {
4138 				blocked_fields.add(coords, game().get_gametime() + block_time);
4139 			}
4140 		}
4141 
4142 		// If it last attempt we also destroy the flag (with a building if any attached)
4143 		if (last_attempt_) {
4144 			remove_from_dqueue<Widelands::Flag>(eco->flags, &flag);
4145 			game().send_player_bulldoze(*const_cast<Flag*>(&flag));
4146 			dead_ends_check_ = true;
4147 			return true;
4148 		}
4149 	}
4150 	return false;
4151 }
4152 
collect_nearflags(std::map<uint32_t,NearFlag> & nearflags,const Flag & flag,const uint16_t checkradius)4153 void DefaultAI::collect_nearflags(std::map<uint32_t, NearFlag>& nearflags,
4154                                   const Flag& flag,
4155                                   const uint16_t checkradius) {
4156 	// Algorithm to walk on roads
4157 	// All nodes are marked as to_be_checked == true first and once the node is checked it is changed
4158 	// to false. Under some conditions, the same node can be checked twice, the to_be_checked can
4159 	// be set back to true. Because less hoops (fewer flag-to-flag roads) does not always mean
4160 	// shortest road.
4161 
4162 	const Map& map = game().map();
4163 
4164 	for (;;) {
4165 		// looking for a node with shortest existing road distance from starting flag and one that has
4166 		// to be checked
4167 		uint32_t start_field = kNoField;
4168 		uint32_t nearest_distance = 10000;
4169 		for (auto item : nearflags) {
4170 			if (item.second.current_road_distance < nearest_distance && item.second.to_be_checked) {
4171 				nearest_distance = item.second.current_road_distance;
4172 				start_field = item.first;
4173 			}
4174 		}
4175 		// OK, we failed to find a NearFlag where to_be_checked == true, so quitting the loop now
4176 		if (start_field == kNoField) {
4177 			break;
4178 		}
4179 
4180 		nearflags[start_field].to_be_checked = false;
4181 
4182 		// Now going over roads leading from this flag
4183 		for (uint8_t i = WalkingDir::FIRST_DIRECTION; i <= WalkingDir::LAST_DIRECTION; ++i) {
4184 			Road* const road = nearflags[start_field].flag->get_road(i);
4185 
4186 			if (!road) {
4187 				continue;
4188 			}
4189 
4190 			Flag* endflag = &road->get_flag(Road::FlagStart);
4191 
4192 			if (endflag == nearflags[start_field].flag) {
4193 				endflag = &road->get_flag(Road::FlagEnd);
4194 			}
4195 
4196 			const uint32_t endflag_hash = endflag->get_position().hash();
4197 
4198 			const int32_t dist = map.calc_distance(flag.get_position(), endflag->get_position());
4199 
4200 			if (dist > checkradius + 2) {  //  Testing bigger vicinity then checkradius....
4201 				continue;
4202 			}
4203 
4204 			// There is few scenarios for this neighbour flag
4205 			if (nearflags.count(endflag_hash) == 0) {
4206 				// This is brand new flag
4207 				// calculating diff how much closer we will get to the flag
4208 				nearflags[endflag_hash] =
4209 				   NearFlag(endflag, nearflags[start_field].current_road_distance +
4210 				                        road->get_path().get_nsteps());
4211 			} else {
4212 				// We know about this flag already
4213 				if (nearflags[endflag_hash].current_road_distance >
4214 				    nearflags[start_field].current_road_distance + road->get_path().get_nsteps()) {
4215 					// ..but this current connection is shorter than one found before
4216 					nearflags[endflag_hash].current_road_distance =
4217 					   nearflags[start_field].current_road_distance + road->get_path().get_nsteps();
4218 					// So let re-check neighbours once more
4219 					nearflags[endflag_hash].to_be_checked = true;
4220 				}
4221 			}
4222 		}
4223 	}
4224 }
4225 
4226 /**
4227  * Checks if anything in one of the economies changed and takes care for these
4228  * changes.
4229  *
4230  * \returns true, if something was changed.
4231  */
check_economies()4232 bool DefaultAI::check_economies() {
4233 	while (!new_flags.empty()) {
4234 		const Flag& flag = *new_flags.front();
4235 		new_flags.pop_front();
4236 		// TODO(Nordfriese): Someone must urgently update the code since the big economy splitting for
4237 		// the ferries
4238 		get_economy_observer(flag.economy(wwWORKER))->flags.push_back(&flag);
4239 	}
4240 
4241 	for (std::deque<EconomyObserver*>::iterator obs_iter = economies.begin();
4242 	     obs_iter != economies.end(); ++obs_iter) {
4243 		// check if any flag has changed its economy
4244 		std::deque<Flag const*>& fl = (*obs_iter)->flags;
4245 
4246 		for (std::deque<Flag const*>::iterator j = fl.begin(); j != fl.end();) {
4247 			if (&(*obs_iter)->economy != &(*j)->economy(wwWORKER)) {
4248 				// the flag belongs to other economy so we must assign it there
4249 				get_economy_observer((*j)->economy(wwWORKER))->flags.push_back(*j);
4250 				// and erase from this economy's observer
4251 				j = fl.erase(j);
4252 			} else {
4253 				++j;
4254 			}
4255 		}
4256 
4257 		// if there are no more flags in this economy,
4258 		// we no longer need it's observer
4259 		if ((*obs_iter)->flags.empty()) {
4260 			delete *obs_iter;
4261 			economies.erase(obs_iter);
4262 			return true;
4263 		}
4264 	}
4265 	return false;
4266 }
4267 
4268 /**
4269  * checks the first productionsite in list, takes care if it runs out of
4270  * resources and finally reenqueues it at the end of the list.
4271  *
4272  * \returns true, if something was changed.
4273  */
check_productionsites(uint32_t gametime)4274 bool DefaultAI::check_productionsites(uint32_t gametime) {
4275 	if (productionsites.empty()) {
4276 		return false;
4277 	}
4278 
4279 	// Reorder and set new values; - better now because there are multiple returns in the function
4280 	productionsites.push_back(productionsites.front());
4281 	productionsites.pop_front();
4282 
4283 	// Get link to productionsite that should be checked
4284 	ProductionSiteObserver& site = productionsites.front();
4285 
4286 	// Inform if we are above ai type limit.
4287 	if (site.bo->total_count() > site.bo->cnt_limit_by_aimode) {
4288 		log("AI check_productionsites: Too many %s: %d, ai limit: %d\n", site.bo->name,
4289 		    site.bo->total_count(), site.bo->cnt_limit_by_aimode);
4290 	}
4291 
4292 	// first we werify if site is working yet (can be unoccupied since the start)
4293 	if (!site.site->can_start_working()) {
4294 		site.unoccupied_till = game().get_gametime();
4295 	}
4296 
4297 	// is it connected to wh at all?
4298 	// TODO(Nordfriese): Someone should update the code since the big economy splitting for the
4299 	// ferries
4300 	const bool connected_to_wh = !site.site->get_economy(wwWORKER)->warehouses().empty();
4301 
4302 	// do not dismantle or upgrade the same type of building too soon - to give some time to update
4303 	// statistics
4304 	if (site.bo->last_dismantle_time >
4305 	    game().get_gametime() -
4306 	       (std::abs(management_data.get_military_number_at(164)) / 25 + 1) * 60 * 1000) {
4307 		return false;
4308 	}
4309 
4310 	// Get max radius of recursive workarea
4311 	WorkareaInfo::size_type radius = 0;
4312 	const WorkareaInfo& workarea_info = site.bo->desc->workarea_info_;
4313 	for (const auto& temp_info : workarea_info) {
4314 		if (radius < temp_info.first) {
4315 			radius = temp_info.first;
4316 		}
4317 	}
4318 
4319 	const Map& map = game().map();
4320 
4321 	// First we check if we must release an experienced worker
4322 	// iterate over all working positions of the actual productionsite
4323 	for (uint8_t i = 0; i < site.site->descr().nr_working_positions(); i++) {
4324 		// get the pointer to the worker assigned to the actual position
4325 		const Worker* cw = site.site->working_positions()[i].worker;
4326 		if (cw) {  // a worker is assigned to the position
4327 			// get the descritpion index of the worker assigned on this position
4328 			DescriptionIndex current_worker = cw->descr().worker_index();
4329 			// if description indexes of assigned worker and normal worker differ
4330 			// (this means an experienced worker is assigned to the position)
4331 			// and we have none of the experienced workers on stock
4332 			if (current_worker != site.bo->positions.at(i) &&
4333 			    calculate_stocklevel(current_worker, WareWorker::kWorker) < 1) {
4334 				// kick out the worker
4335 				game().send_player_evict_worker(*site.site->working_positions()[i].worker);
4336 				return true;
4337 			}
4338 		}
4339 	}
4340 
4341 	// The code here is bit complicated
4342 	// a) Either this site is pending for upgrade, if ready, order the upgrade
4343 	// b) other site of type is pending for upgrade
4344 	// c) if none of above, we can consider upgrade of this one
4345 
4346 	const DescriptionIndex enhancement = site.site->descr().enhancement();
4347 
4348 	bool considering_upgrade = enhancement != INVALID_INDEX;
4349 
4350 	if (!basic_economy_established && management_data.f_neuron_pool[17].get_position(2)) {
4351 		considering_upgrade = false;
4352 	}
4353 
4354 	// First we check for rare case when input wares are set to 0 but AI is not aware that
4355 	// the site is pending for upgrade - one possible cause is this is a freshly loaded game
4356 	if (!site.upgrade_pending) {
4357 		bool resetting_wares = false;
4358 		for (auto& queue : site.site->inputqueues()) {
4359 			if (queue->get_max_fill() == 0) {
4360 				resetting_wares = true;
4361 				game().send_player_set_input_max_fill(
4362 				   *site.site, queue->get_index(), queue->get_type(), queue->get_max_size());
4363 			}
4364 		}
4365 		if (resetting_wares) {
4366 			log(" %d: AI: input queues were reset to max for %s (game just loaded?)\n",
4367 			    player_number(), site.bo->name);
4368 			return true;
4369 		}
4370 	}
4371 
4372 	if (site.upgrade_pending) {
4373 		// The site is in process of emptying its input queues
4374 		// Do nothing when some wares are left, but do not wait more then 4 minutes
4375 		if (site.bo->construction_decision_time + 4 * 60 * 1000 > gametime &&
4376 		    !set_inputs_to_zero(site)) {
4377 			return false;
4378 		}
4379 		assert(site.bo->cnt_upgrade_pending == 1);
4380 		assert(enhancement != INVALID_INDEX);
4381 		game().send_player_enhance_building(*site.site, enhancement, true);
4382 		return true;
4383 	} else if (site.bo->cnt_upgrade_pending > 0) {
4384 		// some other site of this type is in pending for upgrade
4385 		assert(site.bo->cnt_upgrade_pending == 1);
4386 		return false;
4387 	}
4388 	assert(site.bo->cnt_upgrade_pending == 0);
4389 
4390 	// Of course type of productionsite must be allowed
4391 	if (considering_upgrade && !player_->is_building_type_allowed(enhancement)) {
4392 		considering_upgrade = false;
4393 	}
4394 
4395 	// Site must be connected to warehouse
4396 	if (considering_upgrade && !connected_to_wh) {
4397 		considering_upgrade = false;
4398 	}
4399 
4400 	// If upgrade produces new outputs, we upgrade unless the site is younger
4401 	// then 10 minutes. Otherwise the site must be older then 20 minutes and
4402 	// gametime > 45 minutes.
4403 	if (considering_upgrade) {
4404 		if (site.bo->is(BuildingAttribute::kUpgradeExtends)) {
4405 			if (gametime < site.built_time + 10 * 60 * 1000) {
4406 				considering_upgrade = false;
4407 			}
4408 		} else {
4409 			if (gametime < 45 * 60 * 1000 || gametime < site.built_time + 20 * 60 * 1000) {
4410 				considering_upgrade = false;
4411 			}
4412 		}
4413 	}
4414 
4415 	// No upgrade without proper workers
4416 	if (considering_upgrade && !site.site->has_workers(enhancement, game())) {
4417 		const BuildingDescr& bld = *tribe_->get_building_descr(enhancement);
4418 		BuildingObserver& en_bo = get_building_observer(bld.name().c_str());
4419 		if (get_stocklevel(en_bo, gametime, WareWorker::kWorker) < 1) {
4420 			considering_upgrade = false;
4421 		}
4422 	}
4423 
4424 	if (considering_upgrade) {
4425 
4426 		const BuildingDescr& bld = *tribe_->get_building_descr(enhancement);
4427 		BuildingObserver& en_bo = get_building_observer(bld.name().c_str());
4428 		bool doing_upgrade = false;
4429 
4430 		// 10 minutes is a time to productions statics to settle
4431 		if ((en_bo.last_building_built == kNever ||
4432 		     gametime - en_bo.last_building_built >= 10 * 60 * 1000) &&
4433 		    (en_bo.cnt_under_construction + en_bo.unoccupied_count) == 0) {
4434 
4435 			// forcing first upgrade
4436 			if (en_bo.total_count() == 0 &&
4437 			    (site.bo->cnt_built > 1 || site.bo->is(BuildingAttribute::kUpgradeSubstitutes))) {
4438 				doing_upgrade = true;
4439 			}
4440 
4441 			if (en_bo.total_count() == 1 &&
4442 			    (site.bo->cnt_built > 1 || site.bo->is(BuildingAttribute::kUpgradeSubstitutes))) {
4443 				if (en_bo.current_stats > 55) {
4444 					doing_upgrade = true;
4445 				}
4446 			}
4447 
4448 			if (en_bo.total_count() > 1 &&
4449 			    (site.bo->cnt_built > 2 || site.bo->is(BuildingAttribute::kUpgradeSubstitutes))) {
4450 				if (en_bo.current_stats > 75) {
4451 					doing_upgrade = true;
4452 				}
4453 			}
4454 
4455 			// Don't forget about limitation of number of buildings
4456 			if (en_bo.aimode_limit_status() != AiModeBuildings::kAnotherAllowed) {
4457 				doing_upgrade = false;
4458 			}
4459 		}
4460 
4461 		// Here we just restrict input wares to 0 and set flag 'upgrade_pending' to true
4462 		if (doing_upgrade) {
4463 			set_inputs_to_zero(site);
4464 			site.bo->construction_decision_time = gametime;
4465 			en_bo.construction_decision_time = gametime;
4466 			site.upgrade_pending = true;
4467 			++site.bo->cnt_upgrade_pending;
4468 			return true;
4469 		}
4470 	}
4471 
4472 	// Barracks
4473 	if (site.bo->is(BuildingAttribute::kBarracks)) {
4474 		// If we somehow have more than one barracks we will dismantle current one
4475 		if (site.bo->total_count() > 1) {
4476 			log("%2d: We have %d barracks, that is not supported by AI and if caused by AI it is an "
4477 			    "error; dismantling the barracks at %3dx%3d\n",
4478 			    player_number(), site.bo->total_count(), site.site->get_position().x,
4479 			    site.site->get_position().y);
4480 			if (connected_to_wh) {
4481 				game().send_player_dismantle(*site.site, true);
4482 			} else {
4483 				game().send_player_bulldoze(*site.site);
4484 			}
4485 			return true;
4486 		}
4487 
4488 		assert(site.bo->total_count() == 1);
4489 		for (auto& queue : site.site->inputqueues()) {
4490 			if (queue->get_max_fill() > 4) {
4491 				game().send_player_set_input_max_fill(
4492 				   *site.site, queue->get_index(), queue->get_type(), 4);
4493 			}
4494 		}
4495 
4496 		// AI takes multiple inputs into account and makes decision if barracks to be stopped/started
4497 		int16_t tmp_score = 0;
4498 		int16_t inputs[kFNeuronBitSize] = {0};
4499 		const PlayerNumber pn = player_number();
4500 		tmp_score += (soldier_status_ == SoldiersStatus::kBadShortage) * 8;
4501 		tmp_score += (soldier_status_ == SoldiersStatus::kShortage) * 4;
4502 		tmp_score += (soldier_status_ == SoldiersStatus::kEnough) * 2;
4503 		tmp_score += (soldier_status_ == SoldiersStatus::kFull) * 1;
4504 		inputs[2] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) * -1;
4505 		inputs[3] = (expansion_type.get_expansion_type() == ExpansionMode::kSpace) * 1;
4506 		inputs[4] = -1;
4507 		inputs[5] = -2;
4508 		inputs[6] = -3;
4509 		inputs[14] =
4510 		   (player_statistics.get_player_power(pn) < player_statistics.get_old_player_power(pn)) * 1;
4511 		inputs[15] =
4512 		   (player_statistics.get_player_power(pn) < player_statistics.get_old60_player_power(pn)) *
4513 		   1;
4514 		inputs[16] =
4515 		   (player_statistics.get_player_power(pn) > player_statistics.get_old_player_power(pn)) * 1;
4516 		inputs[17] =
4517 		   (player_statistics.get_player_power(pn) > player_statistics.get_old60_player_power(pn)) *
4518 		   1;
4519 		inputs[18] = (expansion_type.get_expansion_type() == ExpansionMode::kSpace) * -1;
4520 		inputs[19] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) * 1;
4521 		inputs[20] = 1;
4522 		inputs[21] = 2;
4523 		inputs[22] = 3;
4524 		inputs[23] = (ts_without_trainers_ > 0) ? -1 : 0;
4525 		inputs[24] = (ts_without_trainers_ > 0) ? -2 : 0;
4526 		inputs[25] = (ts_without_trainers_ > 0) ? -3 : 0;
4527 		for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {
4528 			if (management_data.f_neuron_pool[24].get_position(i)) {
4529 				tmp_score += inputs[i];
4530 			}
4531 		}
4532 
4533 		// starting the site
4534 		if (site.site->is_stopped() && tmp_score >= 0) {
4535 			game().send_player_start_stop_building(*site.site);
4536 			for (auto& queue : site.site->inputqueues()) {
4537 				game().send_player_set_input_max_fill(
4538 				   *site.site, queue->get_index(), queue->get_type(), 4);
4539 			}
4540 		}
4541 		// stopping the site
4542 		if (!site.site->is_stopped() && tmp_score < 0) {
4543 			game().send_player_start_stop_building(*site.site);
4544 			for (auto& queue : site.site->inputqueues()) {
4545 				game().send_player_set_input_max_fill(
4546 				   *site.site, queue->get_index(), queue->get_type(), 2);
4547 			}
4548 		}
4549 	}
4550 
4551 	// Lumberjack / Woodcutter handling
4552 	if (site.bo->is(BuildingAttribute::kLumberjack)) {
4553 
4554 		// do not dismantle immediatelly
4555 		if ((game().get_gametime() - site.built_time) < 6 * 60 * 1000) {
4556 			return false;
4557 		}
4558 
4559 		// Do not destruct the last few lumberjacks
4560 		if (site.bo->cnt_built <= site.bo->cnt_target) {
4561 			return false;
4562 		}
4563 
4564 		const uint32_t remaining_trees = map.find_immovables(
4565 		   game(), Area<FCoords>(map.get_fcoords(site.site->get_position()), radius), nullptr,
4566 		   FindImmovableAttribute(MapObjectDescr::get_attribute_id("tree")));
4567 
4568 		if (site.site->get_statistics_percent() >
4569 		    std::abs(management_data.get_military_number_at(117)) / 2) {
4570 			return false;
4571 		}
4572 
4573 		if (remaining_trees > trees_nearby_treshold_ / 3) {
4574 			return false;
4575 		}
4576 
4577 		// so finally we dismantle the lumberjac
4578 		site.bo->last_dismantle_time = game().get_gametime();
4579 		if (connected_to_wh) {
4580 			game().send_player_dismantle(*site.site, true);
4581 		} else {
4582 			game().send_player_bulldoze(*site.site);
4583 		}
4584 
4585 		return true;
4586 	}
4587 
4588 	// Wells handling
4589 	if (site.bo->is(BuildingAttribute::kWell)) {
4590 		// Never get below target count of wells
4591 		if (site.bo->total_count() <= site.bo->cnt_target) {
4592 			return false;
4593 		}
4594 
4595 		if (site.unoccupied_till + 6 * 60 * 1000 < gametime &&
4596 		    site.site->get_statistics_percent() == 0) {
4597 			site.bo->last_dismantle_time = gametime;
4598 			if (connected_to_wh) {
4599 				game().send_player_dismantle(*site.site, true);
4600 			} else {
4601 				game().send_player_bulldoze(*site.site);
4602 			}
4603 
4604 			return true;
4605 		}
4606 
4607 		// do not consider dismantling if we are under target
4608 		if (site.bo->last_dismantle_time + 90 * 1000 > game().get_gametime()) {
4609 			return false;
4610 		}
4611 
4612 		// now we test the stocklevel and dismantle the well if we have enough water
4613 		// but first we make sure we do not dismantle a well too soon
4614 		// after dismantling previous one
4615 		if (get_stocklevel(*site.bo, gametime) > 250 + productionsites.size() * 5) {  // dismantle
4616 			site.bo->last_dismantle_time = game().get_gametime();
4617 			if (connected_to_wh) {
4618 				game().send_player_dismantle(*site.site, true);
4619 			} else {
4620 				game().send_player_bulldoze(*site.site);
4621 			}
4622 			return true;
4623 		}
4624 
4625 		return false;
4626 	}
4627 
4628 	// Quarry handling
4629 	if (site.bo->is(BuildingAttribute::kNeedsRocks)) {
4630 
4631 		if (map.find_immovables(
4632 		       game(), Area<FCoords>(map.get_fcoords(site.site->get_position()), 6), nullptr,
4633 
4634 		       FindImmovableAttribute(MapObjectDescr::get_attribute_id("rocks"))) == 0) {
4635 			// destruct the building and it's flag (via flag destruction)
4636 			// the destruction of the flag avoids that defaultAI will have too many
4637 			// unused roads - if needed the road will be rebuild directly.
4638 			if (connected_to_wh) {
4639 				game().send_player_dismantle(*site.site, true);
4640 			} else {
4641 				game().send_player_bulldoze(*site.site);
4642 			}
4643 			return true;
4644 		}
4645 
4646 		if (site.unoccupied_till + 6 * 60 * 1000 < gametime &&
4647 		    site.site->get_statistics_percent() == 0) {
4648 			// it is possible that there are rocks but quarry is not able to mine them
4649 			site.bo->last_dismantle_time = game().get_gametime();
4650 			if (connected_to_wh) {
4651 				game().send_player_dismantle(*site.site, true);
4652 			} else {
4653 				game().send_player_bulldoze(*site.site);
4654 			}
4655 
4656 			return true;
4657 		}
4658 
4659 		return false;
4660 	}
4661 
4662 	// All other SPACE_CONSUMERS without input and above target_count
4663 	if (site.bo->inputs.empty()               // does not consume anything
4664 	    && site.bo->production_hints.empty()  // not a renewing building (forester...)
4665 	    && site.bo->is(BuildingAttribute::kSpaceConsumer) &&
4666 	    !site.bo->is(BuildingAttribute::kRanger)) {
4667 
4668 		// if we have more buildings then target
4669 		if ((site.bo->cnt_built - site.bo->unconnected_count) > site.bo->cnt_target &&
4670 		    site.unoccupied_till +
4671 		          (std::abs(management_data.get_military_number_at(166)) / 5 + 1) * 60 * 1000 <
4672 		       gametime &&
4673 		    site.site->can_start_working()) {
4674 
4675 			if (site.site->get_statistics_percent() < 30 && get_stocklevel(*site.bo, gametime) > 100) {
4676 				site.bo->last_dismantle_time = game().get_gametime();
4677 				if (connected_to_wh) {
4678 					game().send_player_dismantle(*site.site, true);
4679 				} else {
4680 					game().send_player_bulldoze(*site.site);
4681 				}
4682 				return true;
4683 			}
4684 		}
4685 
4686 		// a building can be dismanteld if it performs too bad, if it is not the last one
4687 		if (site.site->get_statistics_percent() <= 10 && site.bo->cnt_built > 1 &&
4688 		    site.unoccupied_till +
4689 		          (std::abs(management_data.get_military_number_at(167)) / 5 + 1) * 60 * 1000 <
4690 		       gametime &&
4691 		    site.site->can_start_working() &&
4692 		    get_stocklevel(*site.bo, gametime) >
4693 		       static_cast<unsigned int>(
4694 		          (std::abs(management_data.get_military_number_at(168)) / 5))) {
4695 
4696 			if (connected_to_wh) {
4697 				game().send_player_dismantle(*site.site, true);
4698 			} else {
4699 				game().send_player_bulldoze(*site.site);
4700 			}
4701 			return true;
4702 		}
4703 
4704 		// Blocking the vicinity if too low performance and ware is still needed
4705 		if (site.site->get_statistics_percent() <= 50 || get_stocklevel(*site.bo, gametime) < 5) {
4706 			MapRegion<Area<FCoords>> mr(
4707 			   map, Area<FCoords>(map.get_fcoords(site.site->base_flag().get_position()), 5));
4708 			do {
4709 				blocked_fields.add(mr.location(), gametime + 5 * 60 * 100);
4710 			} while (mr.advance(map));
4711 		}
4712 
4713 		return false;
4714 	}
4715 
4716 	// buildings with inputs, checking if we can a dismantle some due to low performance
4717 	if (!site.bo->inputs.empty() && (site.bo->cnt_built - site.bo->unoccupied_count) >= 3 &&
4718 	    site.site->can_start_working() &&
4719 	    check_building_necessity(*site.bo, PerfEvaluation::kForDismantle, gametime) ==
4720 	       BuildingNecessity::kNotNeeded &&
4721 	    gametime - site.bo->last_dismantle_time >
4722 	       static_cast<uint32_t>((std::abs(management_data.get_military_number_at(169)) / 5 + 1) *
4723 	                             60 * 1000) &&
4724 
4725 	    site.bo->current_stats > site.site->get_statistics_percent() &&  // underperformer
4726 	    (game().get_gametime() - site.unoccupied_till) > 10 * 60 * 1000) {
4727 
4728 		site.bo->last_dismantle_time = game().get_gametime();
4729 
4730 		if (connected_to_wh) {
4731 			game().send_player_dismantle(*site.site, true);
4732 		} else {
4733 			game().send_player_bulldoze(*site.site);
4734 		}
4735 		return true;
4736 	}
4737 
4738 	// remaining buildings without inputs and not supporting ones (fishers only left probably and
4739 	// hunters)
4740 	if (site.bo->inputs.empty() && site.bo->production_hints.empty() &&
4741 	    site.site->can_start_working() && !site.bo->is(BuildingAttribute::kSpaceConsumer) &&
4742 	    site.site->get_statistics_percent() < 5 &&
4743 	    ((game().get_gametime() - site.built_time) > 10 * 60 * 1000)) {
4744 
4745 		site.bo->last_dismantle_time = game().get_gametime();
4746 		if (connected_to_wh) {
4747 			game().send_player_dismantle(*site.site, true);
4748 		} else {
4749 			game().send_player_bulldoze(*site.site);
4750 		}
4751 		return true;
4752 	}
4753 
4754 	// supporting productionsites (rangers)
4755 	// stop/start them based on stock avaiable
4756 	if (!site.bo->production_hints.empty()) {
4757 
4758 		if (!site.bo->is(BuildingAttribute::kRanger)) {
4759 			// other supporting sites, like fish breeders, gamekeepers are not dismantled at all
4760 			return false;
4761 		}
4762 
4763 		// dismantling the rangers hut, but only if we have them above a target
4764 		if (wood_policy_ == WoodPolicy::kDismantleRangers &&
4765 		    site.bo->cnt_built > site.bo->cnt_target) {
4766 
4767 			site.bo->last_dismantle_time = game().get_gametime();
4768 			if (connected_to_wh) {
4769 				game().send_player_dismantle(*site.site, true);
4770 			} else {
4771 				game().send_player_bulldoze(*site.site);
4772 			}
4773 			return true;
4774 		}
4775 
4776 		// stopping a ranger (sometimes the policy can be kDismantleRangers,
4777 		// but we still preserve some rangers for sure)
4778 		if ((wood_policy_ == WoodPolicy::kStopRangers ||
4779 		     wood_policy_ == WoodPolicy::kDismantleRangers) &&
4780 		    !site.site->is_stopped()) {
4781 
4782 			game().send_player_start_stop_building(*site.site);
4783 			return false;
4784 		}
4785 
4786 		const uint32_t trees_in_vicinity = map.find_immovables(
4787 		   game(), Area<FCoords>(map.get_fcoords(site.site->get_position()), 5), nullptr,
4788 		   FindImmovableAttribute(MapObjectDescr::get_attribute_id("tree")));
4789 
4790 		// stop ranger if enough trees around regardless of policy
4791 		if (trees_in_vicinity > 25) {
4792 			if (!site.site->is_stopped()) {
4793 				game().send_player_start_stop_building(*site.site);
4794 			}
4795 			// if not enough trees nearby, we can start them if required
4796 		} else if ((wood_policy_ == WoodPolicy::kAllowRangers) && site.site->is_stopped()) {
4797 			game().send_player_start_stop_building(*site.site);
4798 		}
4799 	}
4800 
4801 	return false;
4802 }
4803 
4804 /**
4805  * checks the first mine in list, takes care if it runs out of
4806  * resources and finally reenqueues it at the end of the list.
4807  *
4808  * \returns true, if something was changed.
4809  */
check_mines_(uint32_t const gametime)4810 bool DefaultAI::check_mines_(uint32_t const gametime) {
4811 	if (mines_.empty()) {
4812 		return false;
4813 	}
4814 
4815 	// Reorder and set new values; - due to returns within the function
4816 	mines_.push_back(mines_.front());
4817 	mines_.pop_front();
4818 
4819 	// Get link to productionsite that should be checked
4820 	ProductionSiteObserver& site = mines_.front();
4821 
4822 	// TODO(Nordfriese): Someone should update the code since the big economy splitting for the
4823 	// ferries
4824 	const bool connected_to_wh = !site.site->get_economy(wwWORKER)->warehouses().empty();
4825 
4826 	// First we dismantle mines that are marked as such, generally we wait till all wares all gone
4827 	if (site.dismantle_pending_since != kNever) {
4828 		assert(site.dismantle_pending_since <= gametime);
4829 		if (set_inputs_to_zero(site) || site.dismantle_pending_since + 5 * 60 * 1000 < gametime) {
4830 			if (connected_to_wh) {
4831 				game().send_player_dismantle(*site.site, true);
4832 			} else {
4833 				game().send_player_bulldoze(*site.site);
4834 			}
4835 
4836 			return true;
4837 		} else if (site.dismantle_pending_since + 3 * 60 * 1000 < gametime) {
4838 			stop_site(site);
4839 			return false;
4840 		} else {
4841 			return false;
4842 		}
4843 	} else if (site.site->can_start_working()) {
4844 		set_inputs_to_max(site);
4845 	} else {
4846 		set_inputs_to_zero(site);
4847 	}
4848 
4849 	// First we check if we must release an experienced worker
4850 	for (uint8_t i = 0; i < site.site->descr().nr_working_positions(); i++) {
4851 		const Worker* cw = site.site->working_positions()[i].worker;
4852 		if (cw) {
4853 			DescriptionIndex current_worker = cw->descr().worker_index();
4854 			if (current_worker != site.bo->positions.at(i) &&
4855 			    calculate_stocklevel(current_worker, WareWorker::kWorker) < 1) {
4856 				game().send_player_evict_worker(*site.site->working_positions()[i].worker);
4857 				return true;
4858 			}
4859 		}
4860 	}
4861 
4862 	// Single _critical is a critical mine if it is the only one of its type, so it needs special
4863 	// treatment
4864 	bool single_critical = false;
4865 	if ((site.bo->is(BuildingAttribute::kBuildingMatProducer) ||
4866 	     site.bo->mines == iron_resource_id) &&
4867 	    mines_per_type[site.bo->mines].finished == 1) {
4868 		single_critical = true;
4869 	}
4870 
4871 	// first get rid of mines that have been  missing workers for some time (10 minutes),
4872 	// released worker (if any) can be useful elsewhere !
4873 	if (!single_critical && site.built_time + 10 * 60 * 1000 < gametime &&
4874 	    !site.site->can_start_working() && mines_per_type[site.bo->mines].total_count() > 2) {
4875 		initiate_dismantling(site, gametime);
4876 		return false;
4877 	}
4878 
4879 	// to avoid problems with uint underflow, we discourage considerations below
4880 	if (gametime < 10 * 60 * 1000) {
4881 		return false;
4882 	}
4883 
4884 	// After 15 minutes in existence we check whether a miner is needed for a critical unoccupied
4885 	// mine elsewhere
4886 	if (site.built_time + 15 * 60 * 1000 < gametime) {
4887 		if (!mines_per_type[site.bo->mines].is_critical && critical_mine_unoccupied(gametime)) {
4888 			for (uint8_t i = 0; i < site.site->descr().nr_working_positions(); i++) {
4889 				const Worker* cw = site.site->working_positions()[i].worker;
4890 				if (cw) {
4891 					game().send_player_evict_worker(*site.site->working_positions()[i].worker);
4892 				}
4893 			}
4894 			return true;
4895 		}
4896 	}
4897 
4898 	// if mine is working, doing nothing
4899 	if (site.no_resources_since > gametime - 5 * 60 * 1000) {
4900 		return false;
4901 	}
4902 
4903 	// Out of resources, first check whether a mine is not needed for critical mine
4904 	if (!mines_per_type[site.bo->mines].is_critical && critical_mine_unoccupied(gametime)) {
4905 		initiate_dismantling(site, gametime);
4906 		return true;
4907 	}
4908 
4909 	// Check whether building is enhanceable. If yes consider an upgrade.
4910 	const DescriptionIndex enhancement = site.site->descr().enhancement();
4911 	bool has_upgrade = false;
4912 	if (enhancement != INVALID_INDEX) {
4913 		if (player_->is_building_type_allowed(enhancement)) {
4914 			has_upgrade = true;
4915 		}
4916 	}
4917 
4918 	// every type of mine has minimal number of mines that are to be preserved
4919 	// (we will not dismantle even if there are no mineable resources left for this level of mine
4920 	// and output is not needed)
4921 	bool forcing_upgrade = false;
4922 	const uint16_t minimal_mines_count =
4923 	   (site.bo->is(BuildingAttribute::kBuildingMatProducer)) ? 2 : 1;
4924 	if (has_upgrade && mines_per_type[site.bo->mines].total_count() <= minimal_mines_count) {
4925 		forcing_upgrade = true;
4926 	}
4927 
4928 	// dismantling a mine
4929 	if (!has_upgrade) {  // if no upgrade, now
4930 		initiate_dismantling(site, gametime);
4931 		return true;
4932 		// if having an upgrade, after half hour
4933 	} else if (site.no_resources_since < gametime - 30 * 60 * 1000 && !forcing_upgrade) {
4934 		initiate_dismantling(site, gametime);
4935 		return true;
4936 	}
4937 
4938 	// if we are here, a mine is upgradeable
4939 
4940 	// if we don't need the output, and we have other buildings of the same type, the function
4941 	// returns
4942 	// and building will be dismantled later.
4943 	check_building_necessity(*site.bo, PerfEvaluation::kForDismantle, gametime);
4944 	if (site.bo->max_needed_preciousness == 0 && !forcing_upgrade) {
4945 		return false;
4946 	}
4947 
4948 	// again similarly, no upgrading if not connected, other parts of AI will dismantle it,
4949 	// or connect to a warehouse
4950 	if (!connected_to_wh) {
4951 		return false;
4952 	}
4953 
4954 	// don't upgrade now if other mines of the same type are right now in construction
4955 	if (mines_per_type[site.bo->mines].in_construction > 0) {
4956 		return false;
4957 	}
4958 
4959 	bool changed = false;
4960 
4961 	// first exclude possibility there are enhancements in construction or unoccupied_count
4962 	const BuildingDescr& bld = *tribe_->get_building_descr(enhancement);
4963 	BuildingObserver& en_bo = get_building_observer(bld.name().c_str());
4964 
4965 	// Make sure we do not exceed limit given by AI mode
4966 	if (en_bo.aimode_limit_status() == AiModeBuildings::kAnotherAllowed) {
4967 
4968 		// if it is too soon for enhancement
4969 		if (gametime - en_bo.construction_decision_time >= kBuildingMinInterval) {
4970 			// now verify that there are enough workers
4971 			if (site.site->has_workers(enhancement, game())) {  // enhancing
4972 				game().send_player_enhance_building(*site.site, enhancement, true);
4973 				if (site.bo->max_needed_preciousness == 0) {
4974 					assert(mines_per_type[site.bo->mines].total_count() <= minimal_mines_count);
4975 				}
4976 				if (mines_per_type[site.bo->mines].total_count() > minimal_mines_count) {
4977 					assert(site.bo->max_needed_preciousness > 0);
4978 				}
4979 				en_bo.construction_decision_time = gametime;
4980 				changed = true;
4981 			}
4982 		}
4983 	}
4984 
4985 	return changed;
4986 }
4987 
check_warehouse_necessity(BuildingObserver & bo,const uint32_t gametime)4988 BuildingNecessity DefaultAI::check_warehouse_necessity(BuildingObserver& bo,
4989                                                        const uint32_t gametime) {
4990 	bo.primary_priority = 0;
4991 
4992 	// First there are situation when we cannot built the warehouse/port
4993 	// a) This is port and map is not seafaring one
4994 	if (bo.is(BuildingAttribute::kPort) && !map_allows_seafaring_) {
4995 		bo.new_building_overdue = 0;
4996 		return BuildingNecessity::kForbidden;
4997 	}
4998 
4999 	// b) the site is prohibited
5000 	if (bo.prohibited_till > gametime) {
5001 		bo.new_building_overdue = 0;
5002 		return BuildingNecessity::kForbidden;
5003 	}
5004 
5005 	// If this is a port and is the first bo be built
5006 	const bool first_port_allowed = (bo.is(BuildingAttribute::kPort) && bo.total_count() == 0);
5007 
5008 	// c) there are warehouses in construction (first port is exemption)
5009 	if (numof_warehouses_in_const_ > 0 && !first_port_allowed) {
5010 		bo.new_building_overdue = 0;
5011 		return BuildingNecessity::kForbidden;
5012 	}
5013 
5014 	// d) there is ai limit for this bulding
5015 	if (bo.aimode_limit_status() != AiModeBuildings::kAnotherAllowed) {
5016 		bo.new_building_overdue = 0;
5017 		return BuildingNecessity::kForbidden;
5018 	}
5019 
5020 	// e) basic economy not established, but first port is an exemption
5021 	if (!basic_economy_established && !first_port_allowed) {
5022 		bo.new_building_overdue = 0;
5023 		return BuildingNecessity::kForbidden;
5024 	}
5025 
5026 	// Number of needed warehouses decides if new one is needed and also
5027 	// converts to the score
5028 	int32_t needed_count = 0;
5029 	if (first_port_allowed) {
5030 		needed_count += numof_warehouses_ + numof_warehouses_in_const_ + 1;
5031 	} else {
5032 		needed_count += static_cast<int32_t>(productionsites.size() + mines_.size()) /
5033 		                   (40 + management_data.get_military_number_at(21) / 10) +
5034 		                1;
5035 	}
5036 
5037 	assert(needed_count >= 0 &&
5038 	       needed_count <= (static_cast<uint16_t>(productionsites.size() + mines_.size()) / 10) + 2);
5039 
5040 	if (player_statistics.any_enemy_seen_lately(gametime) +
5041 	       (productionsites.size() + mines_.size()) >
5042 	    10) {
5043 		++needed_count;
5044 	}
5045 
5046 	// Port should always have higher score than a warehouse
5047 	if (bo.is(BuildingAttribute::kPort)) {
5048 		++needed_count;
5049 	}
5050 
5051 	// suppres a warehouse if not enough spots
5052 	if (spots_ < kSpotsEnough && !bo.is(BuildingAttribute::kPort)) {
5053 		--needed_count;
5054 	}
5055 
5056 	if (needed_count <= numof_warehouses_in_const_ + numof_warehouses_) {
5057 		bo.new_building_overdue = 0;
5058 		return BuildingNecessity::kForbidden;
5059 	}
5060 
5061 	// So now we know the warehouse here is needed.
5062 	bo.primary_priority = 1 +
5063 	                      (needed_count - numof_warehouses_) *
5064 	                         std::abs(management_data.get_military_number_at(22) * 20);
5065 	++bo.new_building_overdue;
5066 	bo.primary_priority +=
5067 	   bo.new_building_overdue * std::abs(management_data.get_military_number_at(16));
5068 	if (bo.is(BuildingAttribute::kPort) && spots_ < kSpotsTooLittle) {
5069 		bo.primary_priority += std::abs(management_data.get_military_number_at(152)) * 10;
5070 	}
5071 	return BuildingNecessity::kAllowed;
5072 }
5073 
5074 // this receives an building observer and have to decide if new/one of
5075 // current buildings of this type is needed
5076 // This is core of construct_building() function
5077 // This is run once when construct_building() is run, or when considering
5078 // dismantle
check_building_necessity(BuildingObserver & bo,const PerfEvaluation purpose,const uint32_t gametime)5079 BuildingNecessity DefaultAI::check_building_necessity(BuildingObserver& bo,
5080                                                       const PerfEvaluation purpose,
5081                                                       const uint32_t gametime) {
5082 	bo.primary_priority = 0;
5083 
5084 	static BasicEconomyBuildingStatus site_needed_for_economy = BasicEconomyBuildingStatus::kNone;
5085 	site_needed_for_economy = BasicEconomyBuildingStatus::kNone;
5086 	if (gametime > 2 * 60 * 1000 && gametime < 120 * 60 * 1000 && !basic_economy_established) {
5087 		if (persistent_data->remaining_basic_buildings.count(bo.id) &&
5088 		    bo.cnt_under_construction == 0) {
5089 			assert(persistent_data->remaining_basic_buildings.count(bo.id) > 0);
5090 			if (spots_ < kSpotsTooLittle && bo.type != BuildingObserver::Type::kMine) {
5091 				site_needed_for_economy = BasicEconomyBuildingStatus::kNeutral;
5092 			} else {
5093 				site_needed_for_economy = BasicEconomyBuildingStatus::kEncouraged;
5094 			}
5095 
5096 		} else {
5097 			site_needed_for_economy = BasicEconomyBuildingStatus::kDiscouraged;
5098 		}
5099 	}
5100 
5101 	// Very first we finds if AI is allowed to build such building due to its mode
5102 	if (purpose == PerfEvaluation::kForConstruction &&
5103 	    bo.aimode_limit_status() != AiModeBuildings::kAnotherAllowed) {
5104 		return BuildingNecessity::kForbidden;
5105 	}
5106 
5107 	// Perhaps buildings are not allowed because the map is no seafaring
5108 	if (purpose == PerfEvaluation::kForConstruction && !map_allows_seafaring_ &&
5109 	    bo.is(BuildingAttribute::kNeedsSeafaring)) {
5110 		return BuildingNecessity::kForbidden;
5111 	}
5112 
5113 	// First we deal with training sites, they are separate category
5114 	if (bo.type == BuildingObserver::Type::kTrainingsite) {
5115 
5116 		if (!basic_economy_established && management_data.f_neuron_pool[17].get_position(1)) {
5117 			return BuildingNecessity::kNotNeeded;
5118 		} else if (bo.aimode_limit_status() != AiModeBuildings::kAnotherAllowed) {
5119 			return BuildingNecessity::kNotNeeded;
5120 		} else if (ts_without_trainers_ > 0 || bo.cnt_under_construction > 0 ||
5121 		           ts_in_const_count_ > 1) {
5122 			return BuildingNecessity::kNotNeeded;
5123 		} else if (bo.prohibited_till > gametime) {
5124 			return BuildingNecessity::kNotNeeded;
5125 		} else if (ts_without_trainers_ > 1) {
5126 			return BuildingNecessity::kNotNeeded;
5127 		} else if (bo.total_count() > 0) {
5128 			if (soldier_trained_log.count(gametime, bo.id) / bo.total_count() < 5) {
5129 				return BuildingNecessity::kNotNeeded;
5130 			}
5131 		}
5132 
5133 		// It seems we might need it after all
5134 		bo.primary_priority = -30;
5135 		if (bo.build_material_shortage) {
5136 			bo.primary_priority -= std::abs(management_data.get_military_number_at(72));
5137 		}
5138 
5139 		if (bo.forced_after > gametime && bo.total_count() == 0) {
5140 			bo.primary_priority += 50 + std::abs(management_data.get_military_number_at(112) / 5);
5141 		}
5142 
5143 		// If we are close to enemy (was seen in last 15 minutes)
5144 		if (player_statistics.any_enemy_seen_lately(gametime)) {
5145 			bo.primary_priority += std::abs(management_data.get_military_number_at(57) / 2);
5146 		}
5147 
5148 		// Do we own some minefields for each critical mine
5149 		if (!mine_fields_stat.has_critical_ore_fields()) {
5150 			bo.primary_priority -= std::abs(management_data.get_military_number_at(156));
5151 		}
5152 
5153 		// We build one trainig site per X military sites
5154 		// with some variations, of course
5155 		int32_t target = 1 +
5156 		                 static_cast<int32_t>(militarysites.size() + productionsites.size()) /
5157 		                    (std::abs(management_data.get_military_number_at(113) / 2) + 1);
5158 		assert(target > 0 && target < 500);
5159 
5160 		uint16_t current_proportion = 0;
5161 		if (ts_finished_count_ + ts_in_const_count_ > 0) {
5162 			current_proportion = bo.total_count() * 100 / (ts_finished_count_ + ts_in_const_count_);
5163 		}
5164 
5165 		bo.primary_priority += (target - ts_finished_count_ - ts_in_const_count_) *
5166 		                       std::abs(management_data.get_military_number_at(114) * 2);
5167 		bo.primary_priority += (static_cast<int32_t>(militarysites.size() + productionsites.size()) -
5168 		                        target * std::abs(management_data.get_military_number_at(78) / 4)) *
5169 		                       3;
5170 
5171 		// Special bonus for very first site of type
5172 		if (bo.total_count() == 0) {
5173 			bo.primary_priority += std::abs(management_data.get_military_number_at(56)) +
5174 			                       bo.max_trainingsites_proportion - current_proportion;
5175 		} else if (bo.max_trainingsites_proportion < current_proportion) {
5176 			bo.primary_priority -= std::abs(management_data.get_military_number_at(128) * 3);
5177 		}
5178 
5179 		if (bo.primary_priority > 0) {
5180 			return BuildingNecessity::kNeeded;
5181 		} else {
5182 			return BuildingNecessity::kNotNeeded;
5183 		}
5184 	}
5185 
5186 	if (bo.is(BuildingAttribute::kRecruitment)) {
5187 		if (bo.total_count() > 1) {
5188 			return BuildingNecessity::kForbidden;
5189 		}
5190 		if (critical_mine_unoccupied(gametime)) {
5191 			return BuildingNecessity::kForbidden;
5192 		}
5193 		if (!basic_economy_established) {
5194 			return BuildingNecessity::kForbidden;
5195 		}
5196 		const uint16_t min_roads_count =
5197 		   40 + std::abs(management_data.get_military_number_at(33)) / 2;
5198 		if (roads.size() < static_cast<size_t>(min_roads_count * (1 + bo.total_count()))) {
5199 			return BuildingNecessity::kForbidden;
5200 		}
5201 		bo.primary_priority += (roads.size() - min_roads_count * (1 + bo.total_count())) *
5202 		                       (2 + std::abs(management_data.get_military_number_at(143)) / 5);
5203 		return BuildingNecessity::kNeeded;
5204 	}
5205 
5206 	// Let deal with productionsites now
5207 	// First we iterate over outputs of building, count warehoused stock
5208 	// and deciding if we have enough on stock (in warehouses)
5209 
5210 	// Calulate preciousness
5211 	bo.max_preciousness = bo.initial_preciousness;
5212 	bo.max_needed_preciousness = bo.initial_preciousness;
5213 	for (uint32_t m = 0; m < bo.ware_outputs.size(); ++m) {
5214 		DescriptionIndex wt(static_cast<size_t>(bo.ware_outputs.at(m)));
5215 
5216 		uint16_t target = tribe_->get_ware_descr(wt)->default_target_quantity(tribe_->name());
5217 		if (target == Widelands::kInvalidWare) {
5218 			target = kTargetQuantCap;
5219 		}
5220 		target /= 3;
5221 
5222 		// at least  1
5223 		target = std::max<uint16_t>(target, 1);
5224 
5225 		// it seems there are wares with 0 preciousness (no entry in init files?), but we need
5226 		// positive value here.
5227 		// TODO(GunChleoc): Since we require in Tribes::postload() that this is set for all wares used
5228 		// by a tribe, something seems to be wrong here. It should always be > 0.
5229 		const uint16_t preciousness =
5230 		   std::max<uint16_t>(wares.at(bo.ware_outputs.at(m)).preciousness, 1);
5231 
5232 		if (calculate_stocklevel(wt) < target ||
5233 		    site_needed_for_economy == BasicEconomyBuildingStatus::kEncouraged) {
5234 			if (bo.max_needed_preciousness < preciousness) {
5235 				bo.max_needed_preciousness = preciousness;
5236 			}
5237 			if (site_needed_for_economy == BasicEconomyBuildingStatus::kEncouraged) {
5238 				bo.max_needed_preciousness +=
5239 				   std::abs(management_data.get_military_number_at(144)) / 10;
5240 			}
5241 		}
5242 
5243 		if (bo.max_preciousness < preciousness) {
5244 			bo.max_preciousness = preciousness;
5245 		}
5246 	}
5247 
5248 	// Do we have enough input materials on stock?
5249 	bool inputs_on_stock = true;
5250 	if (bo.type == BuildingObserver::Type::kProductionsite ||
5251 	    bo.type == BuildingObserver::Type::kMine) {
5252 		for (auto input : bo.inputs) {
5253 			if (calculate_stocklevel(input) < 2) {
5254 				inputs_on_stock = false;
5255 				break;
5256 			}
5257 		}
5258 	}
5259 
5260 	// Do we have enough workers available in warehouses?
5261 	bool workers_on_stock = true;
5262 	if (bo.type == BuildingObserver::Type::kProductionsite ||
5263 	    bo.type == BuildingObserver::Type::kMine) {
5264 		for (auto worker : bo.positions) {
5265 			if (calculate_stocklevel(worker, WareWorker::kWorker) < 1) {
5266 				workers_on_stock = false;
5267 				break;
5268 			}
5269 		}
5270 	}
5271 
5272 	// Do we have suppliers productionsites?
5273 	const bool suppliers_exist = check_supply(bo);
5274 
5275 	if (!bo.ware_outputs.empty()) {
5276 		assert(bo.max_preciousness > 0);
5277 	}
5278 
5279 	if (bo.is(BuildingAttribute::kShipyard)) {
5280 		assert(bo.max_preciousness == 0);
5281 	}
5282 
5283 	// This flag is to be used when buildig is forced. AI will not build another building when
5284 	// a substitution exists. F.e. mines or pairs like tavern-inn
5285 	// To skip unnecessary calculation, we calculate this only if we have 0 count of the buildings
5286 	bool has_substitution_building = false;
5287 	if (bo.total_count() == 0 && bo.is(BuildingAttribute::kUpgradeSubstitutes) &&
5288 	    bo.type == BuildingObserver::Type::kProductionsite) {
5289 		const DescriptionIndex enhancement = bo.desc->enhancement();
5290 		BuildingObserver& en_bo =
5291 		   get_building_observer(tribe_->get_building_descr(enhancement)->name().c_str());
5292 		if (en_bo.total_count() > 0) {
5293 			has_substitution_building = true;
5294 		}
5295 	}
5296 	if (bo.total_count() == 0 && bo.type == BuildingObserver::Type::kMine) {
5297 		if (mines_per_type[bo.mines].total_count() > 0) {
5298 			has_substitution_building = true;
5299 		}
5300 	}
5301 
5302 	// Some buildings are upgraded to ones that does not produce current output, so we need to have
5303 	// two of current buildings to have at least one left after one of them is upgraded
5304 	// Logic is: after 30th minute we need second building if there is no enhanced building yet,
5305 	// and after 90th minute we want second building unconditionally
5306 	bool needs_second_for_upgrade = false;
5307 	if (gametime > 30 * 60 * 1000 && bo.cnt_built == 1 && bo.cnt_under_construction == 0 &&
5308 	    bo.is(BuildingAttribute::kUpgradeExtends) &&
5309 	    !bo.is(BuildingAttribute::kUpgradeSubstitutes) &&
5310 	    bo.type == BuildingObserver::Type::kProductionsite) {
5311 		const DescriptionIndex enhancement = bo.desc->enhancement();
5312 		BuildingObserver& en_bo =
5313 		   get_building_observer(tribe_->get_building_descr(enhancement)->name().c_str());
5314 		if ((gametime > 30 * 60 * 1000 && en_bo.total_count() == 0) || gametime > 90 * 60 * 1000) {
5315 			// We fake this
5316 			bo.max_needed_preciousness = bo.max_preciousness * 2;
5317 			needs_second_for_upgrade = true;
5318 		}
5319 	}
5320 
5321 	// And finally the 'core' of this function
5322 	// First deal with construction of new sites
5323 	if (purpose == PerfEvaluation::kForConstruction) {
5324 		// Inform if we are above ai type limit.
5325 		if (bo.total_count() > bo.cnt_limit_by_aimode) {
5326 			log("AI check_building_necessity: Too many %s: %d, ai limit: %d\n", bo.name,
5327 			    bo.total_count(), bo.cnt_limit_by_aimode);
5328 		}
5329 
5330 		if (bo.forced_after < gametime && bo.total_count() == 0 && !has_substitution_building) {
5331 			bo.max_needed_preciousness = bo.max_preciousness;
5332 			return BuildingNecessity::kForced;
5333 		} else if (bo.prohibited_till > gametime) {
5334 			return BuildingNecessity::kForbidden;
5335 		} else if (bo.is(BuildingAttribute::kHunter) || bo.is(BuildingAttribute::kFisher) ||
5336 		           bo.is(BuildingAttribute::kWell)) {
5337 
5338 			bo.cnt_target = 1 + static_cast<int32_t>(mines_.size() + productionsites.size()) / 25;
5339 
5340 			if (bo.cnt_under_construction + bo.unoccupied_count > 0) {
5341 				return BuildingNecessity::kForbidden;
5342 			}
5343 
5344 			static int16_t inputs[kFNeuronBitSize] = {0};
5345 			// Reseting values as the variable is static
5346 			for (int i = 0; i < kFNeuronBitSize; i++) {
5347 				inputs[i] = 0;
5348 			}
5349 			inputs[0] = (bo.max_needed_preciousness == 0) ? -1 : 0;
5350 			inputs[1] = (bo.max_needed_preciousness > 0) ? 2 : 0;
5351 			inputs[2] = (bo.max_needed_preciousness == 0) ? -3 : 0;
5352 			inputs[3] = (bo.total_count() > 0) ? -1 : 0;
5353 			inputs[4] = (bo.total_count() > 1) ? -1 : 0;
5354 			inputs[5] = (bo.total_count() > 0) ? -1 : 0;
5355 			inputs[6] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? +1 : 0;
5356 			inputs[7] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? +2 : 0;
5357 			inputs[8] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? +3 : 0;
5358 			inputs[9] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0;
5359 			inputs[10] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0;
5360 			inputs[11] = (bo.last_building_built + 5 * 60 * 100 < gametime) ? +1 : 0;
5361 			inputs[12] = (bo.last_building_built + 10 * 60 * 100 < gametime) ? +1 : 0;
5362 			inputs[13] = (bo.last_building_built + 20 * 60 * 100 < gametime) ? +1 : 0;
5363 			inputs[14] = (bo.total_count() >= bo.cnt_target) ? -1 : 0;
5364 			inputs[15] = (bo.total_count() >= bo.cnt_target) ? -2 : 0;
5365 			inputs[16] = (bo.total_count() < bo.cnt_target) ? -1 : 0;
5366 			inputs[17] = (bo.total_count() < bo.cnt_target) ? -2 : 0;
5367 			inputs[18] = +1;
5368 			inputs[19] = +2;
5369 			inputs[20] = -1;
5370 			inputs[21] = -2;
5371 			inputs[22] = -3;
5372 			inputs[23] = -4;
5373 			inputs[24] = -5;
5374 			inputs[25] = (basic_economy_established) ? 1 : -1;
5375 			inputs[26] = (basic_economy_established) ? 1 : -1;
5376 			inputs[27] = (bo.total_count() > 0 && spots_ < kSpotsEnough) ? -2 : 0;
5377 			inputs[28] = (bo.total_count() > 0 && spots_ < kSpotsTooLittle) ? -2 : 0;
5378 			inputs[29] = (spots_ < kSpotsEnough) ? -1 : 0;
5379 			inputs[30] = (spots_ < kSpotsTooLittle) ? -1 : 0;
5380 			int16_t tmp_score = 0;
5381 			for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {
5382 				if (management_data.f_neuron_pool[53].get_position(i)) {
5383 					tmp_score += inputs[i];
5384 				}
5385 			}
5386 			if (site_needed_for_economy == BasicEconomyBuildingStatus::kEncouraged) {
5387 				tmp_score += 4;
5388 			}
5389 			if (site_needed_for_economy == BasicEconomyBuildingStatus::kDiscouraged) {
5390 				tmp_score -= 2;
5391 			}
5392 
5393 			if (tmp_score < 0) {
5394 				return BuildingNecessity::kForbidden;
5395 			} else {
5396 				if (bo.max_needed_preciousness <= 0) {
5397 					bo.max_needed_preciousness = 1;
5398 				}
5399 				bo.primary_priority =
5400 				   1 + tmp_score * std::abs(management_data.get_military_number_at(137) / 2);
5401 				return BuildingNecessity::kNeeded;
5402 			}
5403 		} else if (bo.is(BuildingAttribute::kLumberjack)) {
5404 			if (bo.total_count() > 1 && (bo.cnt_under_construction + bo.unoccupied_count > 0)) {
5405 				return BuildingNecessity::kForbidden;
5406 			}
5407 			bo.cnt_target = 2;
5408 			// adjusting/decreasing based on cnt_limit_by_aimode
5409 			bo.cnt_target = std::min(bo.cnt_target, bo.cnt_limit_by_aimode);
5410 
5411 			// for case the wood is not needed yet, to avoid inconsistency later on
5412 			bo.max_needed_preciousness = bo.max_preciousness;
5413 
5414 			bo.primary_priority = 0;
5415 
5416 			if (bo.total_count() < bo.cnt_target) {
5417 				bo.primary_priority += 10 * std::abs(management_data.get_military_number_at(34));
5418 			}
5419 			if (get_stocklevel(bo, gametime) < 10) {
5420 				bo.primary_priority += std::abs(management_data.get_military_number_at(118));
5421 			}
5422 			if (bo.total_count() < bo.cnt_target) {
5423 				return BuildingNecessity::kNeeded;
5424 			} else {
5425 				return BuildingNecessity::kAllowed;
5426 			}
5427 		} else if (bo.is(BuildingAttribute::kRanger)) {
5428 
5429 			// making sure we have one completed lumberjack
5430 			if (get_building_observer(BuildingAttribute::kLumberjack).cnt_built < 1) {
5431 				return BuildingNecessity::kForbidden;
5432 			}
5433 
5434 			// genetic algorithm to decide whether new rangers are needed
5435 			static int16_t tmp_target = 2;
5436 			tmp_target = 2;
5437 			static int16_t inputs[2 * kFNeuronBitSize] = {0};
5438 			// Reseting values as the variable is static
5439 			for (int i = 0; i < 2 * kFNeuronBitSize; i++) {
5440 				inputs[i] = 0;
5441 			}
5442 
5443 			inputs[0] = (persistent_data->trees_around_cutters < 10) * 2;
5444 			inputs[1] = (persistent_data->trees_around_cutters < 20) * 2;
5445 			inputs[2] = (persistent_data->trees_around_cutters < 30) * 2;
5446 			inputs[3] = (persistent_data->trees_around_cutters < 40) * 2;
5447 			inputs[4] = (persistent_data->trees_around_cutters < 50) * 1;
5448 			inputs[5] = (persistent_data->trees_around_cutters < 60) * 1;
5449 			inputs[6] = (persistent_data->trees_around_cutters < 10) * 1;
5450 			inputs[7] = (persistent_data->trees_around_cutters < 20) * 1;
5451 			inputs[8] = (persistent_data->trees_around_cutters < 100) * 1;
5452 			inputs[9] = (persistent_data->trees_around_cutters < 200) * 1;
5453 			inputs[10] = (persistent_data->trees_around_cutters < 300) * 1;
5454 			inputs[11] = (persistent_data->trees_around_cutters < 400) * 1;
5455 			inputs[12] = (wood_policy_ != WoodPolicy::kAllowRangers) * 1;
5456 			inputs[13] = (wood_policy_ != WoodPolicy::kAllowRangers) * 1;
5457 			inputs[14] = (get_stocklevel(bo, gametime) < 10) * 1;
5458 			inputs[15] = (get_stocklevel(bo, gametime) < 10) * 1;
5459 			inputs[16] = (get_stocklevel(bo, gametime) < 2) * 1;
5460 			if (gametime > 15 * 60) {
5461 				inputs[17] = (get_stocklevel(bo, gametime) > 30) * -1;
5462 				inputs[18] = (get_stocklevel(bo, gametime) > 20) * -1;
5463 				inputs[19] = (get_stocklevel(bo, gametime) > 10) * -1;
5464 			} else {
5465 				inputs[20] = 1;
5466 				inputs[21] = 1;
5467 			}
5468 			inputs[22] = (basic_economy_established) ? -1 : 1;
5469 			inputs[23] = (msites_in_constr() > 0) ? 1 : -2;
5470 			inputs[24] = (msites_in_constr() > 1) ? 1 : -2;
5471 			inputs[25] = (wood_policy_ != WoodPolicy::kAllowRangers) * 1;
5472 			if (gametime > 90 * 60) {
5473 				inputs[26] = (wood_policy_ != WoodPolicy::kAllowRangers) * 1;
5474 				inputs[27] = (persistent_data->trees_around_cutters < 20) * 1;
5475 			}
5476 			if (gametime > 45 * 60) {
5477 				inputs[28] = (wood_policy_ != WoodPolicy::kAllowRangers) * 1;
5478 				inputs[29] = (persistent_data->trees_around_cutters < 20) * 1;
5479 				inputs[30] = (get_stocklevel(bo, gametime) > 30) * -1;
5480 			}
5481 			inputs[31] = (persistent_data->trees_around_cutters < 100) * 2;
5482 			inputs[32] = (persistent_data->trees_around_cutters < 200) * 2;
5483 			inputs[33] = (mines_per_type[iron_resource_id].total_count() <= 1) * -1;
5484 			inputs[34] = (mines_per_type[iron_resource_id].total_count() <= 1) * -1;
5485 			inputs[35] = (mines_per_type[iron_resource_id].total_count() == 0) * -1;
5486 			inputs[36] = (mines_per_type[iron_resource_id].total_count() == 0) * -1;
5487 			inputs[37] = -1;
5488 			inputs[38] = -1;
5489 			inputs[39] = -1;
5490 			if (productionsites.size() / 3 > static_cast<uint32_t>(bo.total_count()) &&
5491 			    get_stocklevel(bo, gametime) < 20) {
5492 				inputs[40] = (persistent_data->trees_around_cutters < 40) * 1;
5493 				inputs[41] = (persistent_data->trees_around_cutters < 60) * 1;
5494 				inputs[42] = (persistent_data->trees_around_cutters < 80) * 1;
5495 			}
5496 			if (productionsites.size() / 4 > static_cast<uint32_t>(bo.total_count()) &&
5497 			    get_stocklevel(bo, gametime) < 20) {
5498 				inputs[43] = (persistent_data->trees_around_cutters < 40) * 2;
5499 				inputs[44] = (persistent_data->trees_around_cutters < 60) * 2;
5500 				inputs[45] = (persistent_data->trees_around_cutters < 80) * 2;
5501 			}
5502 
5503 			if (productionsites.size() / 2 > static_cast<uint32_t>(bo.total_count()) &&
5504 			    get_stocklevel(bo, gametime) < 10) {
5505 				inputs[46] = (persistent_data->trees_around_cutters < 20) * 1;
5506 				inputs[47] = (persistent_data->trees_around_cutters < 40) * 1;
5507 				inputs[48] = (persistent_data->trees_around_cutters < 60) * 1;
5508 				inputs[49] = (persistent_data->trees_around_cutters < 80) * 1;
5509 			}
5510 			inputs[50] = (bo.last_building_built + 1 * 60 * 100 > gametime) * -2;
5511 			inputs[51] = (bo.last_building_built + 2 * 60 * 100 > gametime) * -2;
5512 			inputs[52] = (bo.last_building_built + 4 * 60 * 100 > gametime) * -2;
5513 			inputs[53] = (bo.last_building_built + 6 * 60 * 100 > gametime) * -2;
5514 			inputs[54] = (5 * 60 * 100 > gametime) * -2;
5515 			inputs[55] = (6 * 60 * 100 > gametime) * -2;
5516 			inputs[56] = (8 * 60 * 100 > gametime) * -2;
5517 			inputs[57] = (10 * 60 * 100 > gametime) * -2;
5518 			inputs[58] = (spots_ < kSpotsEnough) ? -2 : 0;
5519 			inputs[59] = (spots_ < kSpotsTooLittle) ? -2 : 0;
5520 			inputs[60] = (spots_ < kSpotsTooLittle) ? -2 : 0;
5521 			inputs[61] = (spots_ < kSpotsTooLittle) ? -2 : 0;
5522 			inputs[62] = (basic_economy_established) ? 0 : -2;
5523 			inputs[63] = (spots_ < kSpotsTooLittle) ? 0 : -2;
5524 
5525 			for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {
5526 				if (management_data.f_neuron_pool[14].get_position(i)) {
5527 					assert(inputs[i] >= -2 && inputs[i] <= 2);
5528 					tmp_target += inputs[i];
5529 				}
5530 				if (management_data.f_neuron_pool[15].get_position(i)) {
5531 					tmp_target += inputs[kFNeuronBitSize + i];
5532 					assert(inputs[kFNeuronBitSize + i] >= -2 && inputs[kFNeuronBitSize + i] <= 2);
5533 				}
5534 			}
5535 
5536 			if (site_needed_for_economy == BasicEconomyBuildingStatus::kDiscouraged) {
5537 				tmp_target -= std::abs(management_data.get_military_number_at(145) / 10);
5538 			}
5539 
5540 			tmp_target = std::max<int16_t>(tmp_target, 2);
5541 
5542 			bo.cnt_target = tmp_target;
5543 
5544 			// adjusting/decreasing based on cnt_limit_by_aimode
5545 			bo.cnt_target = std::min(bo.cnt_target, bo.cnt_limit_by_aimode);
5546 
5547 			assert(bo.cnt_target > 1 && bo.cnt_target < 1000);
5548 
5549 			if (wood_policy_ != WoodPolicy::kAllowRangers) {
5550 				return BuildingNecessity::kForbidden;
5551 			}
5552 
5553 			if (bo.total_count() > bo.cnt_target) {
5554 				return BuildingNecessity::kForbidden;
5555 			}
5556 
5557 			const bool parallel_construction = (bo.total_count() + 2 < bo.cnt_target);
5558 			if (parallel_construction && (bo.cnt_under_construction + bo.unoccupied_count <= 1)) {
5559 				return BuildingNecessity::kNeeded;
5560 			} else if (bo.cnt_under_construction + bo.unoccupied_count == 0) {
5561 				return BuildingNecessity::kNeeded;
5562 			}
5563 			return BuildingNecessity::kForbidden;
5564 		} else if (bo.is(BuildingAttribute::kNeedsRocks) &&
5565 		           bo.cnt_under_construction + bo.unoccupied_count == 0) {
5566 			bo.max_needed_preciousness = bo.max_preciousness;  // even when rocks are not needed
5567 			return BuildingNecessity::kAllowed;
5568 		} else if (!bo.production_hints.empty() && !bo.is(BuildingAttribute::kSupportingProducer)) {
5569 			// Pure supporting sites only
5570 
5571 			if (bo.cnt_under_construction + bo.unoccupied_count - bo.unconnected_count > 0) {
5572 				return BuildingNecessity::kForbidden;
5573 			}
5574 
5575 			// Rangers have been processed above
5576 			assert(!bo.is(BuildingAttribute::kRanger));
5577 
5578 			bo.primary_priority = 0;
5579 
5580 			if (!basic_economy_established) {
5581 				bo.cnt_target = bo.basic_amount;
5582 			} else {
5583 				bo.cnt_target = 1 + static_cast<int32_t>(mines_.size() + productionsites.size()) / 30;
5584 			}
5585 
5586 			if (bo.total_count() > bo.cnt_target + 1) {
5587 				return BuildingNecessity::kForbidden;
5588 			}
5589 
5590 			// We allow another helper site if:
5591 			// a) we are under target
5592 			// b) if there is shortage of supported ware
5593 			if (bo.total_count() < bo.cnt_target ||
5594 			    (get_stocklevel(bo, gametime) == 0 &&
5595 			     bo.last_building_built + 10 * 60 * 100 < gametime)) {
5596 
5597 				if (persistent_data->remaining_basic_buildings.count(bo.id)) {
5598 					bo.primary_priority += std::abs(management_data.get_military_number_at(60) * 10);
5599 				}
5600 
5601 				if (bo.total_count() < bo.cnt_target) {
5602 					if (basic_economy_established) {
5603 						bo.primary_priority += std::abs(management_data.get_military_number_at(51) * 6);
5604 					} else if (persistent_data->remaining_basic_buildings.count(bo.id)) {
5605 						bo.primary_priority += std::abs(management_data.get_military_number_at(146) * 6);
5606 					} else {
5607 						bo.primary_priority +=
5608 						   -200 + std::abs(management_data.get_military_number_at(147) * 8);
5609 					}
5610 				}
5611 
5612 				return BuildingNecessity::kAllowed;
5613 			}
5614 			return BuildingNecessity::kForbidden;
5615 
5616 		} else if (bo.is(BuildingAttribute::kBarracks)) {
5617 			if (site_needed_for_economy == BasicEconomyBuildingStatus::kDiscouraged) {
5618 				return BuildingNecessity::kForbidden;
5619 			}
5620 			if (gametime > 30 * 60 * 1000 && bo.total_count() == 0) {
5621 
5622 				int16_t tmp_score = 1;
5623 				tmp_score += mines_per_type[iron_resource_id].total_count();
5624 				tmp_score += (soldier_status_ == SoldiersStatus::kBadShortage) * 2;
5625 				tmp_score += (soldier_status_ == SoldiersStatus::kShortage) * 2;
5626 				tmp_score += (gametime / 60 / 1000 - 20) / 4;
5627 				bo.max_needed_preciousness =
5628 				   1 + tmp_score * std::abs(management_data.get_military_number_at(134)) / 15;
5629 				bo.max_preciousness = bo.max_needed_preciousness;
5630 				return BuildingNecessity::kNeeded;
5631 			} else {
5632 				bo.max_needed_preciousness = 0;
5633 				bo.max_preciousness = 0;
5634 				return BuildingNecessity::kForbidden;
5635 			}
5636 		} else if (bo.type == BuildingObserver::Type::kMine) {
5637 			bo.primary_priority = bo.max_needed_preciousness;
5638 			if (mines_per_type[bo.mines].total_count() == 0 &&
5639 			    site_needed_for_economy != BasicEconomyBuildingStatus::kDiscouraged) {
5640 				// unless a mine is prohibited, we want to have at least one of the kind
5641 				bo.max_needed_preciousness = bo.max_preciousness;
5642 				return BuildingNecessity::kNeeded;
5643 			} else if (mines_per_type[bo.mines].finished == mines_per_type[bo.mines].total_count() &&
5644 			           bo.current_stats >
5645 			              static_cast<uint32_t>(
5646 			                 85 + std::abs(management_data.get_military_number_at(129)) / 10) &&
5647 			           site_needed_for_economy != BasicEconomyBuildingStatus::kDiscouraged) {
5648 				bo.max_needed_preciousness = bo.max_preciousness;
5649 				return BuildingNecessity::kNeeded;
5650 			}
5651 			if (bo.max_needed_preciousness == 0) {
5652 				return BuildingNecessity::kNotNeeded;
5653 			}
5654 			if (gametime - bo.construction_decision_time < kBuildingMinInterval) {
5655 				return BuildingNecessity::kForbidden;
5656 			}
5657 			if (mines_per_type[bo.mines].in_construction > 0) {
5658 				return BuildingNecessity::kForbidden;
5659 			}
5660 			if (mines_per_type[bo.mines].finished >= 1 && bo.current_stats < 50) {
5661 				return BuildingNecessity::kForbidden;
5662 			}
5663 
5664 			if (gametime < bo.last_building_built + 3 * 60 * 1000) {
5665 				return BuildingNecessity::kForbidden;
5666 			}
5667 
5668 			static int16_t inputs[kFNeuronBitSize] = {0};
5669 			// Reseting values as the variable is static
5670 			for (int i = 0; i < kFNeuronBitSize; i++) {
5671 				inputs[i] = 0;
5672 			}
5673 			inputs[0] = (gametime < 15 * 60 * 1000) ? -2 : 0;
5674 			inputs[1] = (gametime < 30 * 60 * 1000) ? -2 : 0;
5675 			inputs[2] = (gametime < 45 * 60 * 1000) ? -2 : 0;
5676 			inputs[3] = (mines_per_type[bo.mines].total_count() == 1) ? 3 : 0;
5677 			inputs[4] = (mines_per_type[bo.mines].total_count() == 1) ? 2 : 0;
5678 			inputs[5] = (bo.mines == iron_resource_id) ? 2 : 1;
5679 			inputs[6] = (bo.current_stats - 50) / 10;
5680 			inputs[7] = (gametime < 15 * 60 * 1000) ? -1 : 0;
5681 			inputs[8] = (gametime < 30 * 60 * 1000) ? -1 : 0;
5682 			inputs[9] = (gametime < 45 * 60 * 1000) ? -1 : 0;
5683 			inputs[10] = (mines_per_type[bo.mines].total_count() == 1) ? 2 : 0;
5684 			inputs[11] = (mines_per_type[bo.mines].total_count() == 1) ? 1 : 0;
5685 			inputs[12] = (bo.mines == iron_resource_id) ? 2 : 0;
5686 			inputs[13] = (bo.current_stats - 50) / 10;
5687 			inputs[14] = (bo.current_stats - 50) / 10;
5688 			inputs[15] = management_data.get_military_number_at(123) / 10;
5689 			inputs[16] = 0;
5690 			inputs[17] = (inputs_on_stock) ? 0 : -2;
5691 			inputs[18] = (suppliers_exist) ? 0 : -3;
5692 			inputs[19] = (inputs_on_stock) ? 0 : -4;
5693 			inputs[20] = (mines_per_type[bo.mines].total_count() == 1) ? 3 : 0;
5694 			inputs[21] = (mines_per_type[bo.mines].total_count() == 1) ? 2 : 0;
5695 			inputs[22] = (bo.current_stats - 50) / 10;
5696 			inputs[23] = (bo.current_stats - 50) / 20;
5697 			inputs[24] = (suppliers_exist) ? 0 : -5;
5698 			inputs[25] = (suppliers_exist) ? 0 : -2;
5699 			inputs[26] = (workers_on_stock) ? 0 : -5;
5700 			inputs[27] = (workers_on_stock) ? 0 : -2;
5701 			inputs[28] = (bo.is(BuildingAttribute::kBuildingMatProducer)) ? 1 : 0;
5702 			inputs[29] = (bo.is(BuildingAttribute::kBuildingMatProducer)) ? 3 : 0;
5703 			inputs[30] = (mines_per_type[bo.mines].is_critical) ? 1 : -1;
5704 
5705 			int16_t tmp_score = management_data.get_military_number_at(83) / 5;
5706 
5707 			// Building productionsites above limit in Basic economy mode is strongly discouraged, but
5708 			// still possible
5709 			const int16_t basic_economy_score =
5710 			   25 + std::abs(management_data.get_military_number_at(122) * 2);
5711 
5712 			if (site_needed_for_economy == BasicEconomyBuildingStatus::kEncouraged) {
5713 				tmp_score += basic_economy_score;
5714 			}
5715 
5716 			if (site_needed_for_economy == BasicEconomyBuildingStatus::kDiscouraged) {
5717 				tmp_score -= basic_economy_score;
5718 			}
5719 
5720 			for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {
5721 				if (management_data.f_neuron_pool[36].get_position(i)) {
5722 					tmp_score += inputs[i];
5723 				}
5724 			}
5725 			if (tmp_score < 0) {
5726 				return BuildingNecessity::kNeededPending;
5727 			} else {
5728 				bo.primary_priority +=
5729 				   tmp_score * std::abs(management_data.get_military_number_at(127) / 5);
5730 				return BuildingNecessity::kNeeded;
5731 			}
5732 
5733 		} else if (bo.max_needed_preciousness > 0) {
5734 
5735 			static int16_t inputs[4 * kFNeuronBitSize] = {0};
5736 			// Reseting values as the variable is static
5737 			for (int i = 0; i < 4 * kFNeuronBitSize; i++) {
5738 				inputs[i] = 0;
5739 			}
5740 			inputs[0] = (bo.total_count() <= 1) ?
5741 			               std::abs(management_data.get_military_number_at(110)) / 10 :
5742 			               0;
5743 			inputs[1] = bo.total_count() * -3 / 2;
5744 			inputs[2] =
5745 			   (bo.total_count() == 0) ? std::abs(management_data.get_military_number_at(0)) / 10 : 0;
5746 			inputs[3] = (gametime >= 25 * 60 * 1000 && bo.inputs.empty()) ?
5747 			               management_data.get_military_number_at(1) / 10 :
5748 			               0;
5749 			inputs[4] = (bo.max_needed_preciousness >= 10) ?
5750 			               std::abs(management_data.get_military_number_at(2)) / 10 :
5751 			               0;
5752 			inputs[5] =
5753 			   (!bo.ware_outputs.empty() && bo.current_stats > 10 + 70 / bo.ware_outputs.size()) ?
5754 			      management_data.get_military_number_at(3) / 10 :
5755 			      0;
5756 			inputs[6] = (needs_second_for_upgrade) ?
5757 			               std::abs(management_data.get_military_number_at(4)) / 5 :
5758 			               0;
5759 			inputs[7] = (bo.cnt_under_construction + bo.unoccupied_count) * -1 *
5760 			            std::abs(management_data.get_military_number_at(9)) / 5;
5761 			inputs[8] =
5762 			   (!bo.ware_outputs.empty() && bo.current_stats > 25 + 70 / bo.ware_outputs.size()) ?
5763 			      management_data.get_military_number_at(7) / 8 :
5764 			      0;
5765 			inputs[9] = (bo.is(BuildingAttribute::kBuildingMatProducer)) ?
5766 			               std::abs(management_data.get_military_number_at(10)) / 10 :
5767 			               0;
5768 			inputs[10] =
5769 			   (bo.build_material_shortage) ? -management_data.get_military_number_at(39) / 10 : 0;
5770 			inputs[11] = (wood_policy_ == WoodPolicy::kDismantleRangers ||
5771 			              wood_policy_ == WoodPolicy::kStopRangers) ?
5772 			                std::abs(management_data.get_military_number_at(15)) / 10 :
5773 			                0;
5774 			inputs[12] = (gametime >= 15 * 60 * 1000) ?
5775 			                std::abs(management_data.get_military_number_at(94)) / 10 :
5776 			                0;
5777 			inputs[13] = management_data.get_military_number_at(8) / 10;
5778 			inputs[14] = (persistent_data->trees_around_cutters < 20) ?
5779 			                -1 * std::abs(management_data.get_military_number_at(95)) / 10 :
5780 			                0;
5781 			inputs[15] = (persistent_data->trees_around_cutters > 100) ?
5782 			                std::abs(management_data.get_military_number_at(96)) / 10 :
5783 			                0;
5784 			inputs[16] = (player_statistics.any_enemy_seen_lately(gametime)) ?
5785 			                management_data.get_military_number_at(97) / 10 :
5786 			                0;
5787 			inputs[17] =
5788 			   (spots_ > kSpotsEnough) ? std::abs(management_data.get_military_number_at(74)) / 8 : 0;
5789 			inputs[18] = management_data.get_military_number_at(98) / 10;
5790 			inputs[19] = (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) ?
5791 			                -1 * std::abs(management_data.get_military_number_at(40)) / 10 :
5792 			                0;
5793 			inputs[20] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ?
5794 			                std::abs(management_data.get_military_number_at(50)) / 10 :
5795 			                0;
5796 			inputs[21] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy ||
5797 			              expansion_type.get_expansion_type() == ExpansionMode::kBoth) ?
5798 			                3 :
5799 			                0;
5800 			inputs[22] =
5801 			   (bo.total_count() == 0 && bo.is(BuildingAttribute::kBuildingMatProducer)) ? 3 : 0;
5802 			if (bo.cnt_built > 0 && !bo.ware_outputs.empty()) {
5803 				inputs[22] += bo.current_stats / 10;
5804 			}
5805 			inputs[23] = (!player_statistics.strong_enough(player_number())) ? 5 : 0;
5806 			inputs[24] = (bo.inputs.empty()) ? 6 : 0;
5807 			inputs[25] =
5808 			   (bo.total_count() == 0 && bo.is(BuildingAttribute::kBuildingMatProducer)) ? 4 : 0;
5809 			inputs[26] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? 2 : 0;
5810 			inputs[27] = (wood_policy_ == WoodPolicy::kDismantleRangers ||
5811 			              wood_policy_ == WoodPolicy::kStopRangers) ?
5812 			                4 :
5813 			                0;
5814 			inputs[28] = (bo.max_needed_preciousness >= 10) ? 4 : 0;
5815 			inputs[29] = (bo.inputs.empty() && bo.max_needed_preciousness >= 10) ? 3 : 0;
5816 			inputs[30] = bo.max_needed_preciousness / 2;
5817 			inputs[31] = ((bo.cnt_under_construction + bo.unoccupied_count) > 0) ? -5 : 0;
5818 			inputs[32] = bo.max_needed_preciousness / 2;
5819 			inputs[33] = -(bo.cnt_under_construction + bo.unoccupied_count) * 4;
5820 			if (bo.cnt_built > 0 && !bo.ware_outputs.empty() && !bo.inputs.empty()) {
5821 				inputs[34] +=
5822 				   bo.current_stats / (std::abs(management_data.get_military_number_at(192)) + 1) * 10;
5823 			}
5824 			inputs[35] = (!bo.ware_outputs.empty() && !bo.inputs.empty() &&
5825 			              bo.current_stats > 10 + 70 / bo.ware_outputs.size()) ?
5826 			                2 :
5827 			                0;
5828 			inputs[36] = (!bo.ware_outputs.empty() && !bo.inputs.empty() &&
5829 			              bo.cnt_under_construction + bo.unoccupied_count == 0) ?
5830 			                bo.current_stats / 12 :
5831 			                0;
5832 			if (bo.cnt_built > 0 && !bo.inputs.empty() && !bo.ware_outputs.empty() &&
5833 			    bo.current_stats < 20) {
5834 				inputs[37] = -5;
5835 			}
5836 			inputs[38] = (bo.cnt_under_construction + bo.unoccupied_count > 0) ? -10 : 0;
5837 			if (bo.cnt_built > 0 && !bo.ware_outputs.empty() && bo.current_stats < 15) {
5838 				inputs[39] = -10;
5839 			}
5840 			inputs[40] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? 3 : 0;
5841 			inputs[41] = (bo.build_material_shortage) ? -3 : 0;
5842 			inputs[42] = (!player_statistics.strong_enough(player_number())) ? 2 : 0;
5843 			inputs[43] = (bo.inputs.empty()) ? 3 : 0;
5844 			inputs[44] = (bo.inputs.empty() && bo.max_needed_preciousness >= 10) ? 3 : 0;
5845 			inputs[45] = bo.max_needed_preciousness / 2;
5846 			inputs[46] =
5847 			   (!bo.ware_outputs.empty() && bo.current_stats > 10 + 70 / bo.ware_outputs.size()) ? 4 :
5848 			                                                                                       0;
5849 			inputs[47] = (!bo.ware_outputs.empty() && bo.current_stats > 85) ? 4 : 0;
5850 			inputs[48] = (bo.max_needed_preciousness >= 10 &&
5851 			              (bo.cnt_under_construction + bo.unoccupied_count) == 1) ?
5852 			                5 :
5853 			                0;
5854 			inputs[49] = (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) ? -4 : 1;
5855 			inputs[50] = (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) ? -1 : 1;
5856 			inputs[51] = (gametime < 20 * 60 * 1000) ? -4 : 0;
5857 			inputs[52] = (bo.total_count() == 0) ? 4 : 0;
5858 			inputs[53] = (bo.total_count() == 0) ? 2 : 0;
5859 			inputs[54] = (spots_ < kSpotsEnough) ? -5 : 0;
5860 			inputs[55] = (bo.max_needed_preciousness >= 10 &&
5861 			              (bo.cnt_under_construction + bo.unoccupied_count) == 1) ?
5862 			                3 :
5863 			                0;
5864 			inputs[56] = (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) ? -8 : 1;
5865 			inputs[57] = (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) ? -6 : 1;
5866 			inputs[58] = (bo.total_count() == 0 && inputs_on_stock) ? 4 : 0;
5867 			inputs[59] = (bo.inputs.empty()) ? 5 : bo.current_stats / 10 - 5;
5868 			inputs[60] = (spots_ < kSpotsTooLittle) ? -10 : 0;
5869 			inputs[61] = (player_statistics.any_enemy_seen_lately(gametime)) ? 2 : 0;
5870 			inputs[62] = (player_statistics.any_enemy_seen_lately(gametime) &&
5871 			              bo.cnt_under_construction + bo.unoccupied_count == 0) ?
5872 			                6 :
5873 			                0;
5874 			inputs[63] = (!bo.ware_outputs.empty() && !bo.inputs.empty()) ? bo.current_stats / 10 : 0;
5875 			inputs[64] = (gametime > 20 * 60 * 1000 && bo.total_count() == 0) ? 3 : 0;
5876 			inputs[65] = (gametime > 45 * 60 * 1000 && bo.total_count() == 0) ? 3 : 0;
5877 			inputs[66] = (gametime > 60 * 60 * 1000 && bo.total_count() <= 1) ? 3 : 0;
5878 			inputs[67] = (gametime > 50 * 60 * 1000 && bo.total_count() <= 1) ? 2 : 0;
5879 			inputs[68] =
5880 			   (bo.inputs.empty() && gametime > 50 * 60 * 1000 && bo.total_count() <= 1) ? 2 : 0;
5881 			inputs[69] =
5882 			   (!bo.inputs.empty() && gametime > 50 * 60 * 1000 && bo.total_count() <= 1) ? 2 : 0;
5883 			inputs[70] =
5884 			   (bo.inputs.empty() && gametime > 25 * 60 * 1000 && bo.total_count() <= 1) ? 2 : 0;
5885 			inputs[71] =
5886 			   (!bo.inputs.empty() && gametime > 25 * 60 * 1000 && bo.total_count() <= 1) ? 2 : 0;
5887 			if (bo.last_building_built != kNever) {
5888 				inputs[72] = (gametime < bo.last_building_built + 3 * 60 * 1000) ? -4 : 0;
5889 				inputs[73] = (gametime < bo.last_building_built + 5 * 60 * 1000) ? -2 : 0;
5890 				inputs[74] = (gametime < bo.last_building_built + 2 * 60 * 1000) ? -5 : 0;
5891 				inputs[75] = (gametime < bo.last_building_built + 10 * 60 * 1000) ? -2 : 0;
5892 				inputs[76] = (gametime < bo.last_building_built + 20 * 60 * 1000) ? -2 : 0;
5893 			}
5894 			inputs[77] = (gametime > 35 * 60 * 1000 && bo.total_count() == 0) ? 3 : 0;
5895 			inputs[78] = (gametime > 60 * 60 * 1000 && bo.total_count() == 0) ? 3 : 0;
5896 			inputs[79] = (expansion_type.get_expansion_type() == ExpansionMode::kResources ||
5897 			              expansion_type.get_expansion_type() == ExpansionMode::kSpace) *
5898 			             management_data.get_military_number_at(37) / 10;
5899 			inputs[80] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) *
5900 			             management_data.get_military_number_at(38) / 10;
5901 			inputs[81] = (expansion_type.get_expansion_type() == ExpansionMode::kSpace) *
5902 			             management_data.get_military_number_at(46) / 10;
5903 			inputs[82] = (inputs_on_stock) ? 0 : -2;
5904 			inputs[83] = (suppliers_exist) ? 0 : -2;
5905 			inputs[84] = (inputs_on_stock) ? 0 : -4;
5906 			inputs[85] = (suppliers_exist) ? 0 : -4;
5907 			inputs[86] = (inputs_on_stock) ? 0 : -8;
5908 			inputs[87] = (suppliers_exist) ? 0 : -8;
5909 			inputs[88] = (workers_on_stock) ? 0 : -2;
5910 			inputs[89] = (workers_on_stock) ? 0 : -6;
5911 			inputs[90] = (bo.is(BuildingAttribute::kBuildingMatProducer)) ?
5912 			                std::abs(management_data.get_military_number_at(10)) / 10 :
5913 			                0;
5914 			inputs[91] = (bo.build_material_shortage) ? -2 : 0;
5915 			inputs[92] = (numof_psites_in_constr < 4) ? 3 : 0;
5916 			inputs[93] = (numof_psites_in_constr < 8) ? 3 : 0;
5917 			inputs[94] = (bo.inputs.empty()) ? 5 : 0;
5918 			inputs[95] = (bo.inputs.empty()) ? 3 : 0;
5919 			inputs[96] = (wood_policy_ == WoodPolicy::kAllowRangers) ? -2 : 0;
5920 			inputs[97] = (wood_policy_ == WoodPolicy::kAllowRangers) ? -8 : 0;
5921 			inputs[98] = (wood_policy_ == WoodPolicy::kAllowRangers) ? -4 : 0;
5922 			inputs[99] = (wood_policy_ == WoodPolicy::kAllowRangers) ? -1 : 0;
5923 			inputs[100] = (bo.total_count() == 0) ? 3 : 0;
5924 			inputs[101] = (bo.total_count() == 0) ? 6 : 0;
5925 			if (bo.is(BuildingAttribute::kSupportingProducer)) {
5926 				if (bo.total_count() == 0) {
5927 					inputs[102] = 1;
5928 					inputs[103] = 2;
5929 					inputs[104] = -2;
5930 				}
5931 				inputs[105] = -3;
5932 				inputs[106] = -2;
5933 			}
5934 			inputs[107] =
5935 			   std::abs(management_data.get_military_number_at(194)) - get_stocklevel(bo, gametime);
5936 			inputs[108] =
5937 			   std::abs(management_data.get_military_number_at(191)) - get_stocklevel(bo, gametime);
5938 			inputs[109] = (!bo.inputs.empty() && gametime > 50 * 60 * 1000 && bo.total_count() <= 1) ?
5939 			                 std::abs(management_data.get_military_number_at(163)) / 10 :
5940 			                 0;
5941 			inputs[110] = (bo.ware_outputs.size() == 1) ?
5942 			                 (tribe_->get_ware_descr(bo.ware_outputs.at(0))
5943 			                     ->default_target_quantity(tribe_->name()) -
5944 			                  get_stocklevel(bo, gametime)) *
5945 			                    std::abs(management_data.get_military_number_at(165)) / 20 :
5946 			                 0;
5947 			inputs[111] = bo.current_stats / (bo.ware_outputs.size() + 1);
5948 			// boost for buildings supporting seafaring
5949 			if (bo.is(BuildingAttribute::kSupportsSeafaring) && map_allows_seafaring_) {
5950 				inputs[112] = std::abs(management_data.get_military_number_at(170)) / 10;
5951 				inputs[113] = 4;
5952 				if (bo.total_count() == 0) {
5953 					inputs[114] = std::abs(management_data.get_military_number_at(172)) / 10;
5954 					inputs[115] = 4;
5955 				}
5956 			}
5957 			inputs[116] = -(bo.unoccupied_count * bo.unoccupied_count);
5958 			inputs[117] = -(2 * bo.unoccupied_count);
5959 
5960 			int16_t tmp_score = 0;
5961 			for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {
5962 				if (management_data.f_neuron_pool[8].get_position(i)) {
5963 					const int16_t partial_input = inputs[i];
5964 					tmp_score += partial_input;
5965 				}
5966 				if (management_data.f_neuron_pool[11].get_position(i)) {
5967 					const int16_t partial_input = inputs[i + kFNeuronBitSize];
5968 					tmp_score += partial_input;
5969 				}
5970 				if (management_data.f_neuron_pool[59].get_position(i)) {
5971 					const int16_t partial_input = inputs[i + 2 * kFNeuronBitSize];
5972 					tmp_score += partial_input;
5973 				}
5974 				if (management_data.f_neuron_pool[12].get_position(i)) {
5975 					const int16_t partial_input = inputs[i + 3 * kFNeuronBitSize];
5976 					tmp_score += partial_input;
5977 				}
5978 			}
5979 
5980 			const int32_t base_economy_bonus =
5981 			   30 + std::abs(management_data.get_military_number_at(142));
5982 			if (site_needed_for_economy == BasicEconomyBuildingStatus::kDiscouraged) {
5983 				tmp_score -= base_economy_bonus;
5984 			} else if (site_needed_for_economy == BasicEconomyBuildingStatus::kEncouraged) {
5985 				tmp_score += base_economy_bonus;
5986 			}
5987 
5988 			const int16_t bottom_limit = management_data.get_military_number_at(73) / 2 +
5989 			                             management_data.get_military_number_at(47) / 10;
5990 			const int16_t upper_limit =
5991 			   bottom_limit + std::abs(management_data.get_military_number_at(44) / 3);
5992 
5993 			if (tmp_score > upper_limit) {
5994 				// Productionsite is needed
5995 				bo.primary_priority += (tmp_score - bottom_limit) / 2;
5996 				return BuildingNecessity::kNeeded;
5997 			} else if (tmp_score > bottom_limit) {
5998 				// Site is needed, but not right now
5999 				return BuildingNecessity::kNeededPending;
6000 			} else {
6001 				// Not allowed
6002 				return BuildingNecessity::kForbidden;
6003 			}
6004 
6005 		} else if (bo.is(BuildingAttribute::kShipyard)) {
6006 			if (bo.total_count() > 0 ||
6007 			    (!basic_economy_established &&
6008 			     site_needed_for_economy == BasicEconomyBuildingStatus::kDiscouraged) ||
6009 			    !map_allows_seafaring_) {
6010 				return BuildingNecessity::kForbidden;
6011 			}
6012 			bo.primary_priority = 0;
6013 			if (num_ports > 0) {
6014 				bo.primary_priority += std::abs(management_data.get_military_number_at(150) * 3);
6015 			}
6016 			if (spots_ < kSpotsTooLittle) {
6017 				bo.primary_priority += std::abs(management_data.get_military_number_at(151) * 3);
6018 			}
6019 			if (bo.primary_priority > 0) {
6020 				return BuildingNecessity::kNeeded;
6021 			}
6022 			return BuildingNecessity::kAllowed;
6023 		} else if (bo.max_needed_preciousness == 0) {
6024 			return BuildingNecessity::kNotNeeded;
6025 		} else {
6026 			return BuildingNecessity::kForbidden;
6027 		}
6028 	} else if (purpose == PerfEvaluation::kForDismantle) {  // now for dismantling
6029 		// never dismantle last building (a care should be taken elsewhere)
6030 		assert(bo.total_count() > 0);
6031 		if (bo.total_count() == 1) {
6032 			return BuildingNecessity::kNeeded;
6033 		} else if (bo.max_preciousness >= 10 && bo.total_count() == 2) {
6034 			return BuildingNecessity::kNeeded;
6035 		} else if (!bo.ware_outputs.empty() &&
6036 		           bo.current_stats > (10 + 60 / bo.ware_outputs.size()) / 2) {
6037 			return BuildingNecessity::kNeeded;
6038 		} else if (bo.inputs.size() == 1 &&
6039 		           calculate_stocklevel(static_cast<size_t>(bo.inputs.at(0))) >
6040 		              static_cast<unsigned int>(
6041 		                 std::abs(management_data.get_military_number_at(171)))) {
6042 			return BuildingNecessity::kNeeded;
6043 		} else {
6044 			return BuildingNecessity::kNotNeeded;
6045 		}
6046 	}
6047 	NEVER_HERE();
6048 }
6049 
6050 // counts produced output on stock
calculate_stocklevel(Widelands::DescriptionIndex wt,const WareWorker what) const6051 uint32_t DefaultAI::calculate_stocklevel(Widelands::DescriptionIndex wt,
6052                                          const WareWorker what) const {
6053 	uint32_t count = 0;
6054 
6055 	for (const Widelands::WarehouseSiteObserver& obs : warehousesites) {
6056 		if (what == WareWorker::kWare) {
6057 			count += obs.site->get_wares().stock(wt);
6058 		} else {
6059 			count += obs.site->get_workers().stock(wt);
6060 		}
6061 	}
6062 	return count;
6063 }
6064 
6065 // This is a wrapper function to prevent too frequent recalculation of stocklevel
6066 // and distinguish if we count stocks for production hint, for outputs or for workers of a
6067 // productionsite
6068 // if multiple outputs, it returns lowest value
get_stocklevel(BuildingObserver & bo,const uint32_t gametime,const WareWorker what) const6069 uint32_t DefaultAI::get_stocklevel(BuildingObserver& bo,
6070                                    const uint32_t gametime,
6071                                    const WareWorker what) const {
6072 	if (bo.stocklevel_time < gametime - 5 * 1000) {
6073 		if (what == WareWorker::kWare && (!bo.production_hints.empty() || !bo.ware_outputs.empty())) {
6074 			// looking for smallest value
6075 			bo.stocklevel_count = std::numeric_limits<uint32_t>::max();
6076 			for (auto ph : bo.production_hints) {
6077 				const uint32_t res = calculate_stocklevel(static_cast<size_t>(ph), what);
6078 				if (res < bo.stocklevel_count) {
6079 					bo.stocklevel_count = res;
6080 				}
6081 			}
6082 			for (auto ph : bo.ware_outputs) {
6083 				const uint32_t res = calculate_stocklevel(static_cast<size_t>(ph), what);
6084 				if (res < bo.stocklevel_count) {
6085 					bo.stocklevel_count = res;
6086 				}
6087 			}
6088 		} else if (what == WareWorker::kWorker) {
6089 			bo.stocklevel_count = std::numeric_limits<uint32_t>::max();
6090 			for (auto ph : bo.positions) {
6091 				const uint32_t res = calculate_stocklevel(static_cast<size_t>(ph), what);
6092 				if (res < bo.stocklevel_count) {
6093 					bo.stocklevel_count = res;
6094 				}
6095 			}
6096 		} else {
6097 			bo.stocklevel_count = 0;
6098 		}
6099 		assert(bo.stocklevel_count < std::numeric_limits<uint32_t>::max());
6100 		bo.stocklevel_time = gametime;
6101 	}
6102 	return bo.stocklevel_count;
6103 }
6104 
6105 /**
6106  * This function takes care about the unowned and opposing territory and
6107  * recalculates the priority for non-military buildings
6108  * The goal is to minimize losses when territory is lost
6109  *
6110  * \arg bf   = BuildableField to be checked
6111  * \arg prio = priority until now.
6112  *
6113  * \returns the recalculated priority
6114  */
recalc_with_border_range(const BuildableField & bf,int32_t prio)6115 int32_t DefaultAI::recalc_with_border_range(const BuildableField& bf, int32_t prio) {
6116 
6117 	// no change when priority is not positive number
6118 	if (prio <= 0) {
6119 		return prio;
6120 	}
6121 
6122 	if (bf.enemy_nearby || bf.near_border) {
6123 		prio /= 2;
6124 	}
6125 
6126 	// if unowned territory nearby
6127 	prio -= bf.unowned_land_nearby / 4;
6128 	prio -= bf.enemy_owned_land_nearby / 3;
6129 
6130 	// further decrease the score if enemy nearby
6131 	if (bf.enemy_nearby) {
6132 		prio -= 10;
6133 	}
6134 
6135 	// and if close (up to 2 fields away) from border
6136 	if (bf.near_border) {
6137 		prio -= 10;
6138 		if (spots_ > 0 && spots_ < kSpotsEnough) {
6139 			prio -= std::abs(management_data.neuron_pool[60].get_result_safe(
6140 			           kSpotsEnough / spots_, kAbsValue)) /
6141 			        4;
6142 		}
6143 	}
6144 
6145 	return prio;
6146 }
6147 // for buildable field, it considers effect of building of type bo on position coords
consider_productionsite_influence(BuildableField & field,Coords coords,const BuildingObserver & bo)6148 void DefaultAI::consider_productionsite_influence(BuildableField& field,
6149                                                   Coords coords,
6150                                                   const BuildingObserver& bo) {
6151 	if (bo.is(BuildingAttribute::kSpaceConsumer) && !bo.is(BuildingAttribute::kRanger) &&
6152 	    game().map().calc_distance(coords, field.coords) < 8) {
6153 		++field.space_consumers_nearby;
6154 	}
6155 
6156 	for (size_t i = 0; i < bo.inputs.size(); ++i) {
6157 		++field.consumers_nearby.at(bo.inputs.at(i));
6158 	}
6159 
6160 	for (size_t i = 0; i < bo.ware_outputs.size(); ++i) {
6161 		++field.producers_nearby.at(bo.ware_outputs.at(i));
6162 	}
6163 	if (bo.has_collected_map_resource()) {
6164 		++field.collecting_producers_nearby.at(bo.get_collected_map_resource());
6165 	}
6166 
6167 	if (!bo.production_hints.empty()) {
6168 		for (auto ph : bo.production_hints) {
6169 			++field.supporters_nearby.at(ph);
6170 		}
6171 	}
6172 
6173 	if (bo.is(BuildingAttribute::kRanger)) {
6174 		++field.rangers_nearby;
6175 	}
6176 }
6177 
6178 /// \returns the economy observer containing \arg economy
get_economy_observer(Economy & economy)6179 EconomyObserver* DefaultAI::get_economy_observer(Economy& economy) {
6180 	for (std::deque<EconomyObserver*>::iterator i = economies.begin(); i != economies.end(); ++i) {
6181 		if (&(*i)->economy == &economy) {
6182 			return *i;
6183 		}
6184 	}
6185 
6186 	economies.push_front(new EconomyObserver(economy));
6187 	return economies.front();
6188 }
6189 
6190 // counts buildings with the BuildingAttribute
6191 // Type of buildings, not individual buildings are meant
count_buildings_with_attribute(BuildingAttribute attribute)6192 uint8_t DefaultAI::count_buildings_with_attribute(BuildingAttribute attribute) {
6193 	uint8_t count = 0;
6194 	if (tribe_ == nullptr) {
6195 		late_initialization();
6196 	}
6197 
6198 	for (BuildingObserver& bo : buildings_) {
6199 		if (bo.is(attribute)) {
6200 			++count;
6201 		}
6202 	}
6203 
6204 	return count;
6205 }
6206 
6207 // Calculates ratio of the buildings that the player has in comparison to all buildings that
6208 // are buildable by the player
6209 // In range 0 - 1000, to avoid floats
count_productionsites_without_buildings()6210 uint32_t DefaultAI::count_productionsites_without_buildings() {
6211 	uint32_t total = 0;
6212 	uint32_t existing = 0;
6213 	if (tribe_ == nullptr) {
6214 		late_initialization();
6215 	}
6216 
6217 	for (BuildingObserver& bo : buildings_) {
6218 		if (bo.type == BuildingObserver::Type::kProductionsite &&
6219 		    bo.is(BuildingAttribute::kBuildable)) {
6220 			++total;
6221 			if (bo.cnt_built > 0) {
6222 				existing += 1000;
6223 			} else if (bo.cnt_under_construction > 0) {
6224 				existing += 500;
6225 			}
6226 		}
6227 	}
6228 
6229 	return (total > 0) ? (existing / total) : 0;
6230 }
6231 
6232 // \returns the building observer
get_building_observer(char const * const name)6233 BuildingObserver& DefaultAI::get_building_observer(char const* const name) {
6234 	if (tribe_ == nullptr) {
6235 		late_initialization();
6236 	}
6237 
6238 	for (BuildingObserver& bo : buildings_) {
6239 		if (!strcmp(bo.name, name)) {
6240 			return bo;
6241 		}
6242 	}
6243 
6244 	throw wexception("Help: I (player %d / tribe %s) do not know what to do with a %s",
6245 	                 player_number(), tribe_->name().c_str(), name);
6246 }
6247 
6248 // checks if the building has a building observer (for debug purposes)
has_building_observer(char const * const name)6249 bool DefaultAI::has_building_observer(char const* const name) {
6250 	if (tribe_ == nullptr) {
6251 		late_initialization();
6252 	}
6253 
6254 	for (BuildingObserver& bo : buildings_) {
6255 		if (!strcmp(bo.name, name)) {
6256 			return true;
6257 		}
6258 	}
6259 
6260 	return false;
6261 }
6262 
6263 // return observer for a first (only) building that has required attribute
get_building_observer(BuildingAttribute attribute)6264 Widelands::BuildingObserver& DefaultAI::get_building_observer(BuildingAttribute attribute) {
6265 	if (tribe_ == nullptr) {
6266 		late_initialization();
6267 	}
6268 
6269 	for (BuildingObserver& bo : buildings_) {
6270 		if (bo.is(attribute)) {
6271 			return bo;
6272 		}
6273 	}
6274 
6275 	throw wexception(
6276 	   "Sorry, cannot find building with attribute %d", static_cast<int32_t>(attribute));
6277 }
6278 
6279 // return observer for a building with the id
get_building_observer(const DescriptionIndex di)6280 Widelands::BuildingObserver& DefaultAI::get_building_observer(const DescriptionIndex di) {
6281 	if (tribe_ == nullptr) {
6282 		late_initialization();
6283 	}
6284 
6285 	for (BuildingObserver& bo : buildings_) {
6286 		if (bo.id == di) {
6287 			return bo;
6288 		}
6289 	}
6290 
6291 	log("Sorry, cannot find building with id %d", static_cast<int32_t>(di));
6292 	// I noticed that exception test is being lost so will will print it into log as well
6293 	throw wexception("Sorry, cannot find building with id %d", static_cast<int32_t>(di));
6294 }
6295 
6296 // this is called whenever we gain ownership of a PlayerImmovable
gain_immovable(PlayerImmovable & pi,const bool found_on_load)6297 void DefaultAI::gain_immovable(PlayerImmovable& pi, const bool found_on_load) {
6298 	if (upcast(Building, building, &pi)) {
6299 		gain_building(*building, found_on_load);
6300 	} else if (upcast(Flag const, flag, &pi)) {
6301 		new_flags.push_back(flag);
6302 	} else if (upcast(Road const, road, &pi)) {
6303 		roads.push_front(road);
6304 	}
6305 }
6306 
6307 // this is called whenever we lose ownership of a PlayerImmovable
lose_immovable(const PlayerImmovable & pi)6308 void DefaultAI::lose_immovable(const PlayerImmovable& pi) {
6309 	if (upcast(Building const, building, &pi)) {
6310 		lose_building(*building);
6311 	} else if (upcast(Flag const, flag, &pi)) {
6312 		// Flag to be removed can be:
6313 		// 1. In one of our economies
6314 		for (EconomyObserver* eco_obs : economies) {
6315 			if (remove_from_dqueue<Widelands::Flag>(eco_obs->flags, flag)) {
6316 				return;
6317 			}
6318 		}
6319 
6320 		// 2. in new flags to be processed yet
6321 		if (remove_from_dqueue<Widelands::Flag>(new_flags, flag)) {
6322 			return;
6323 		}
6324 
6325 		// 3. Or in neither of them
6326 	} else if (upcast(Road const, road, &pi)) {
6327 		remove_from_dqueue<Widelands::Road>(roads, road);
6328 	}
6329 }
6330 
6331 // this is called when a mine reports "out of resources"
out_of_resources_site(const ProductionSite & site)6332 void DefaultAI::out_of_resources_site(const ProductionSite& site) {
6333 
6334 	const uint32_t gametime = game().get_gametime();
6335 
6336 	// we must identify which mine matches the productionsite a note reffers to
6337 	for (std::deque<ProductionSiteObserver>::iterator i = mines_.begin(); i != mines_.end(); ++i) {
6338 		if (i->site == &site) {
6339 			if (i->no_resources_since > gametime) {
6340 				i->no_resources_since = gametime;
6341 			}
6342 			break;
6343 		}
6344 	}
6345 }
6346 
6347 // walk and search for territory controlled by some player type
6348 // usually scanning radius is enough but sometimes we must walk to
6349 // verify that an enemy territory is really accessible by land
other_player_accessible(const uint32_t max_distance,uint32_t * tested_fields,uint16_t * mineable_fields_count,const Coords & starting_spot,const WalkSearch & type)6350 bool DefaultAI::other_player_accessible(const uint32_t max_distance,
6351                                         uint32_t* tested_fields,
6352                                         uint16_t* mineable_fields_count,
6353                                         const Coords& starting_spot,
6354                                         const WalkSearch& type) {
6355 	const Map& map = game().map();
6356 	std::list<uint32_t> queue;
6357 	std::unordered_set<uint32_t> done;
6358 	queue.push_front(starting_spot.hash());
6359 	PlayerNumber const pn = player_->player_number();
6360 
6361 	while (!queue.empty()) {
6362 		// if already processed
6363 		if (done.count(queue.front()) > 0) {
6364 			queue.pop_front();
6365 			continue;
6366 		}
6367 
6368 		done.insert(queue.front());
6369 
6370 		Coords tmp_coords = Coords::unhash(queue.front());
6371 
6372 		// if beyond range
6373 		if (map.calc_distance(starting_spot, tmp_coords) > max_distance) {
6374 			continue;
6375 		}
6376 
6377 		Field* f = map.get_fcoords(tmp_coords).field;
6378 
6379 		// not interested if not walkable (starting spot is an exemption.
6380 		if (tmp_coords != starting_spot && !(f->nodecaps() & MOVECAPS_WALK)) {
6381 			continue;
6382 		}
6383 
6384 		// sometimes we search for any owned territory (f.e. when considering
6385 		// a port location), but when testing (starting from) own military building
6386 		// we must ignore own territory, of course
6387 		const PlayerNumber field_owner = f->get_owned_by();
6388 		if (field_owner > 0) {
6389 
6390 			// if field is owned by anybody
6391 			if (type == WalkSearch::kAnyPlayer) {
6392 				*tested_fields = done.size();
6393 				return true;
6394 			}
6395 
6396 			// if somebody but not me
6397 			if (type == WalkSearch::kOtherPlayers && field_owner != pn) {
6398 				*tested_fields = done.size();
6399 				return true;
6400 			}
6401 
6402 			// if owned by enemy
6403 			if (type == WalkSearch::kEnemy && field_owner != pn) {
6404 				// if not in the same team => it is an enemy
6405 				if (!player_statistics.players_in_same_team(pn, field_owner)) {
6406 					*tested_fields = done.size();
6407 					return true;
6408 				}
6409 			}
6410 		}
6411 
6412 		// increase mines counter
6413 		// (used when testing possible port location)
6414 		if (f->nodecaps() & BUILDCAPS_MINE) {
6415 			++mineable_fields_count;
6416 		}
6417 
6418 		// add neighbours to a queue (duplicates are no problem)
6419 		// to relieve AI/CPU we skip every second field in each direction
6420 		// obstacles are usually wider then one field
6421 		for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
6422 			Coords neigh_coords1;
6423 			map.get_neighbour(tmp_coords, dir, &neigh_coords1);
6424 			Coords neigh_coords2;
6425 			map.get_neighbour(neigh_coords1, dir, &neigh_coords2);
6426 			queue.push_front(neigh_coords2.hash());
6427 		}
6428 	}
6429 	*tested_fields = done.size();
6430 	return false;  // no players found
6431 }
6432 
6433 // this is called whenever we gain a new building
gain_building(Building & b,const bool found_on_load)6434 void DefaultAI::gain_building(Building& b, const bool found_on_load) {
6435 
6436 	BuildingObserver& bo = get_building_observer(b.descr().name().c_str());
6437 
6438 	if (bo.type == BuildingObserver::Type::kConstructionsite) {
6439 		BuildingObserver& target_bo =
6440 		   get_building_observer(dynamic_cast<const ConstructionSite&>(b).building().name().c_str());
6441 		++target_bo.cnt_under_construction;
6442 		if (target_bo.type == BuildingObserver::Type::kProductionsite) {
6443 			++numof_psites_in_constr;
6444 		}
6445 		if (target_bo.type == BuildingObserver::Type::kMilitarysite) {
6446 			++msites_per_size[target_bo.desc->get_size()].in_construction;
6447 		}
6448 		if (target_bo.type == BuildingObserver::Type::kMine) {
6449 			++mines_per_type[target_bo.mines].in_construction;
6450 		}
6451 		if (target_bo.type == BuildingObserver::Type::kWarehouse) {
6452 			++numof_warehouses_in_const_;
6453 		}
6454 		if (target_bo.type == BuildingObserver::Type::kTrainingsite) {
6455 			++ts_in_const_count_;
6456 		}
6457 
6458 		set_taskpool_task_time(game().get_gametime(), SchedulerTaskId::kRoadCheck);
6459 
6460 	} else {
6461 		++bo.cnt_built;
6462 		const uint32_t gametime = game().get_gametime();
6463 		bo.last_building_built = gametime;
6464 		// erase building from remaining_basic_buildings, unless we are loading a saved game
6465 		if (!found_on_load && persistent_data->remaining_basic_buildings.count(bo.id) > 0) {
6466 			if (persistent_data->remaining_basic_buildings[bo.id] > 1) {
6467 				--persistent_data->remaining_basic_buildings[bo.id];
6468 			} else {
6469 				persistent_data->remaining_basic_buildings.erase(bo.id);
6470 			}
6471 		}
6472 		// Remaining basic buildings map contain either no entry for the building, or the number is
6473 		// nonzero
6474 		assert(persistent_data->remaining_basic_buildings.count(bo.id) == 0 ||
6475 		       persistent_data->remaining_basic_buildings[bo.id] > 0);
6476 
6477 		if (bo.type == BuildingObserver::Type::kProductionsite) {
6478 			productionsites.push_back(ProductionSiteObserver());
6479 			productionsites.back().site = &dynamic_cast<ProductionSite&>(b);
6480 			productionsites.back().bo = &bo;
6481 			productionsites.back().bo->new_building_overdue = 0;
6482 			if (found_on_load && gametime > 5 * 60 * 1000) {
6483 				productionsites.back().built_time = gametime - 5 * 60 * 1000;
6484 			} else {
6485 				productionsites.back().built_time = gametime;
6486 			}
6487 			productionsites.back().unoccupied_till = gametime;
6488 			++productionsites.back().bo->unoccupied_count;
6489 			if (bo.is(BuildingAttribute::kShipyard)) {
6490 				marine_task_queue.push_back(kStopShipyard);
6491 				marine_task_queue.push_back(kReprioritize);
6492 			}
6493 			if (bo.is(BuildingAttribute::kFisher)) {
6494 				++fishers_count_;
6495 			}
6496 
6497 		} else if (bo.type == BuildingObserver::Type::kMine) {
6498 			mines_.push_back(ProductionSiteObserver());
6499 			mines_.back().site = &dynamic_cast<ProductionSite&>(b);
6500 			mines_.back().bo = &bo;
6501 			mines_.back().built_time = gametime;
6502 			assert(mines_.back().no_resources_since == kNever);
6503 			assert(!mines_.back().upgrade_pending);
6504 			assert(mines_.back().dismantle_pending_since == kNever);
6505 			++mines_.back().bo->unoccupied_count;
6506 
6507 			++mines_per_type[bo.mines].finished;
6508 
6509 			if (bo.is(BuildingAttribute::kBuildingMatProducer)) {
6510 				++buil_material_mines_count;
6511 			}
6512 
6513 			set_inputs_to_zero(mines_.back());
6514 
6515 			// Is this first mine?
6516 			if (bo.mines == iron_resource_id && gametime < first_iron_mine_built) {
6517 				first_iron_mine_built = gametime;
6518 			}
6519 
6520 		} else if (bo.type == BuildingObserver::Type::kMilitarysite) {
6521 			militarysites.push_back(MilitarySiteObserver());
6522 			militarysites.back().site = &dynamic_cast<MilitarySite&>(b);
6523 			militarysites.back().bo = &bo;
6524 			militarysites.back().understaffed = 0;
6525 			if (found_on_load && gametime > 5 * 60 * 1000) {
6526 				militarysites.back().built_time = gametime - 5 * 60 * 1000;
6527 			} else {
6528 				militarysites.back().built_time = gametime;
6529 			}
6530 			militarysites.back().last_change = 0;
6531 			++msites_per_size[bo.desc->get_size()].finished;
6532 
6533 		} else if (bo.type == BuildingObserver::Type::kTrainingsite) {
6534 			++ts_without_trainers_;
6535 			++ts_finished_count_;
6536 			trainingsites.push_back(TrainingSiteObserver());
6537 			trainingsites.back().site = &dynamic_cast<TrainingSite&>(b);
6538 			trainingsites.back().bo = &bo;
6539 
6540 		} else if (bo.type == BuildingObserver::Type::kWarehouse) {
6541 			++numof_warehouses_;
6542 			warehousesites.push_back(WarehouseSiteObserver());
6543 			warehousesites.back().site = &dynamic_cast<Warehouse&>(b);
6544 			warehousesites.back().bo = &bo;
6545 			if (bo.is(BuildingAttribute::kPort)) {
6546 				++num_ports;
6547 			}
6548 		}
6549 	}
6550 }
6551 
6552 // this is called whenever we lose a building
lose_building(const Building & b)6553 void DefaultAI::lose_building(const Building& b) {
6554 
6555 	BuildingObserver& bo = get_building_observer(b.descr().name().c_str());
6556 
6557 	if (bo.type == BuildingObserver::Type::kConstructionsite) {
6558 		BuildingObserver& target_bo =
6559 		   get_building_observer(dynamic_cast<const ConstructionSite&>(b).building().name().c_str());
6560 		--target_bo.cnt_under_construction;
6561 		if (target_bo.type == BuildingObserver::Type::kProductionsite) {
6562 			--numof_psites_in_constr;
6563 		}
6564 		if (target_bo.type == BuildingObserver::Type::kMilitarysite) {
6565 			--msites_per_size[target_bo.desc->get_size()].in_construction;
6566 		}
6567 		if (target_bo.type == BuildingObserver::Type::kMine) {
6568 			--mines_per_type[target_bo.mines].in_construction;
6569 		}
6570 		if (target_bo.type == BuildingObserver::Type::kWarehouse) {
6571 			--numof_warehouses_in_const_;
6572 		}
6573 		if (target_bo.type == BuildingObserver::Type::kTrainingsite) {
6574 			assert(ts_in_const_count_ > 0);
6575 			--ts_in_const_count_;
6576 		}
6577 
6578 	} else {
6579 		--bo.cnt_built;
6580 
6581 		// we are not able to reliably identify if lost building is counted in
6582 		// unconnected or unoccupied count, but we must adjust the value to
6583 		// avoid inconsistency
6584 		const uint32_t cnt_built = bo.cnt_built;
6585 		if (bo.unconnected_count > cnt_built) {
6586 			bo.unconnected_count = cnt_built;
6587 		}
6588 		if (bo.unoccupied_count > cnt_built) {
6589 			bo.unoccupied_count = cnt_built;
6590 		}
6591 
6592 		if (bo.type == BuildingObserver::Type::kProductionsite) {
6593 			for (std::deque<ProductionSiteObserver>::iterator i = productionsites.begin();
6594 			     i != productionsites.end(); ++i) {
6595 				if (i->site == &b) {
6596 					if (i->upgrade_pending) {
6597 						--bo.cnt_upgrade_pending;
6598 					}
6599 					assert(bo.cnt_upgrade_pending == 0 || bo.cnt_upgrade_pending == 1);
6600 					productionsites.erase(i);
6601 					break;
6602 				}
6603 			}
6604 
6605 			if (bo.is(BuildingAttribute::kFisher)) {
6606 				assert(fishers_count_ > 0);
6607 				--fishers_count_;
6608 			}
6609 
6610 		} else if (bo.type == BuildingObserver::Type::kMine) {
6611 			for (std::deque<ProductionSiteObserver>::iterator i = mines_.begin(); i != mines_.end();
6612 			     ++i) {
6613 				if (i->site == &b) {
6614 					mines_.erase(i);
6615 					break;
6616 				}
6617 			}
6618 
6619 			--mines_per_type[bo.mines].finished;
6620 
6621 			if (bo.is(BuildingAttribute::kBuildingMatProducer)) {
6622 				assert(buil_material_mines_count > 0);
6623 				++buil_material_mines_count;
6624 			}
6625 
6626 		} else if (bo.type == BuildingObserver::Type::kMilitarysite) {
6627 			--msites_per_size[bo.desc->get_size()].finished;
6628 
6629 			for (std::deque<MilitarySiteObserver>::iterator i = militarysites.begin();
6630 			     i != militarysites.end(); ++i) {
6631 				if (i->site == &b) {
6632 					militarysites.erase(i);
6633 					break;
6634 				}
6635 			}
6636 		} else if (bo.type == BuildingObserver::Type::kTrainingsite) {
6637 			assert(ts_finished_count_ >= 1);
6638 			--ts_finished_count_;
6639 
6640 			for (std::deque<TrainingSiteObserver>::iterator i = trainingsites.begin();
6641 			     i != trainingsites.end(); ++i) {
6642 				if (i->site == &b) {
6643 					trainingsites.erase(i);
6644 					break;
6645 				}
6646 			}
6647 		} else if (bo.type == BuildingObserver::Type::kWarehouse) {
6648 			assert(numof_warehouses_ > 0);
6649 			--numof_warehouses_;
6650 			if (bo.is(BuildingAttribute::kPort)) {
6651 				--num_ports;
6652 			}
6653 
6654 			for (std::deque<WarehouseSiteObserver>::iterator i = warehousesites.begin();
6655 			     i != warehousesites.end(); ++i) {
6656 				if (i->site == &b) {
6657 					warehousesites.erase(i);
6658 					break;
6659 				}
6660 			}
6661 		}
6662 	}
6663 }
6664 
6665 // Checks that supply line exists for given building.
6666 // Recursively verify that all inputs have a producer.
6667 // TODO(unknown): this function leads to periodic freezes of ~1 second on big games on my system.
6668 // TODO(unknown): It needs profiling and optimization.
check_supply(const BuildingObserver & bo)6669 bool DefaultAI::check_supply(const BuildingObserver& bo) {
6670 	size_t supplied = 0;
6671 	for (const Widelands::DescriptionIndex& temp_inputs : bo.inputs) {
6672 		for (const BuildingObserver& temp_building : buildings_) {
6673 			if (temp_building.cnt_built &&
6674 			    std::find(temp_building.ware_outputs.begin(), temp_building.ware_outputs.end(),
6675 			              temp_inputs) != temp_building.ware_outputs.end() &&
6676 			    check_supply(temp_building)) {
6677 				++supplied;
6678 				break;
6679 			}
6680 		}
6681 	}
6682 
6683 	return supplied == bo.inputs.size();
6684 }
6685 
6686 // TODO(tiborb): - should be called from scheduler, once in 60s is enough
update_player_stat(const uint32_t gametime)6687 void DefaultAI::update_player_stat(const uint32_t gametime) {
6688 	if (player_statistics.get_update_time() > 0 &&
6689 	    player_statistics.get_update_time() + 15 * 1000 > gametime) {
6690 		return;
6691 	}
6692 	player_statistics.set_update_time(gametime);
6693 	Widelands::PlayerNumber const pn = player_number();
6694 	PlayerNumber const nr_players = game().map().get_nrplayers();
6695 
6696 	// receiving games statistics and parsing it (reading latest entry)
6697 	const Game::GeneralStatsVector& genstats = game().get_general_statistics();
6698 
6699 	// Collecting statistics and saving them in player_statistics object
6700 	const Player* me = game().get_player(pn);
6701 	for (Widelands::PlayerNumber j = 1; j <= nr_players; ++j) {
6702 		const Player* this_player = game().get_player(j);
6703 		if (this_player) {
6704 			try {
6705 				const uint32_t vsize = genstats.at(j - 1).miltary_strength.size();
6706 
6707 				uint32_t cur_strength = 0;
6708 				uint32_t cur_land = 0;
6709 				uint32_t old_strength = 0;
6710 				uint32_t old60_strength = 0;
6711 				uint32_t old_land = 0;
6712 				uint32_t old60_land = 0;
6713 				uint32_t cass = 0;
6714 				if (vsize > 0) {
6715 					cur_strength = genstats.at(j - 1).miltary_strength.back();
6716 					cur_land = genstats.at(j - 1).land_size.back();
6717 					cass = genstats.at(j - 1).nr_casualties.back();
6718 
6719 					if (vsize > 21) {
6720 						old_strength = genstats.at(j - 1).miltary_strength[vsize - 20];
6721 						old_land = genstats.at(j - 1).land_size[vsize - 20];
6722 					} else {
6723 						old_strength = genstats.at(j - 1).miltary_strength[0];
6724 						old_land = genstats.at(j - 1).land_size[0];
6725 					}
6726 					if (vsize > 91) {
6727 						old60_strength = genstats.at(j - 1).miltary_strength[vsize - 90];
6728 						old60_land = genstats.at(j - 1).land_size[vsize - 90];
6729 					} else {
6730 						old60_strength = genstats.at(j - 1).miltary_strength[0];
6731 						old60_land = genstats.at(j - 1).land_size[0];
6732 					}
6733 				}
6734 
6735 				player_statistics.add(pn, j, me->team_number(), this_player->team_number(),
6736 				                      cur_strength, old_strength, old60_strength, cass, cur_land,
6737 				                      old_land, old60_land);
6738 			} catch (const std::out_of_range&) {
6739 				log("ComputerPlayer(%d): genstats entry missing - size :%d\n",
6740 				    static_cast<unsigned int>(player_number()),
6741 				    static_cast<unsigned int>(genstats.size()));
6742 			}
6743 		} else {
6744 			// Well, under some circumstances it is possible we have stat for this player and he does
6745 			// not exist anymore
6746 			player_statistics.remove_stat(j);
6747 		}
6748 	}
6749 
6750 	player_statistics.recalculate_team_power();
6751 }
6752 
6753 // This runs once in 15 minutes, and adjust wares targets based on number of
6754 // productionsites and ports
review_wares_targets(uint32_t const gametime)6755 void DefaultAI::review_wares_targets(uint32_t const gametime) {
6756 
6757 	player_ = game().get_player(player_number());
6758 	tribe_ = &player_->tribe();
6759 
6760 	// to avoid floats real multiplier is multiplier/10
6761 	const uint16_t multiplier = std::max<uint16_t>((productionsites.size() + num_ports * 5) / 5, 10);
6762 
6763 	for (EconomyObserver* observer : economies) {
6764 		DescriptionIndex nritems = player_->egbase().tribes().nrwares();
6765 		for (Widelands::DescriptionIndex id = 0; id < nritems; ++id) {
6766 
6767 			// Just skip wares that are not used by a tribe
6768 			if (!tribe_->has_ware(id)) {
6769 				continue;
6770 			}
6771 
6772 			uint16_t default_target =
6773 			   tribe_->get_ware_descr(id)->default_target_quantity(tribe_->name());
6774 
6775 			// It seems that when default target for ware is not set, it returns
6776 			// kInvalidWare (=254), this is confusing for AI so we change it to 10
6777 			if (default_target == Widelands::kInvalidWare) {
6778 				default_target = kTargetQuantCap;
6779 			}
6780 
6781 			const uint16_t new_target = std::max<uint16_t>(default_target * multiplier / 10, 3);
6782 			assert(new_target > 1);
6783 
6784 			game().send_player_command(new Widelands::CmdSetWareTargetQuantity(
6785 			   gametime, player_number(), observer->economy.serial(), id, new_target));
6786 		}
6787 	}
6788 }
6789 
6790 // Sets due_time based on job ID
set_taskpool_task_time(const uint32_t gametime,const Widelands::SchedulerTaskId task)6791 void DefaultAI::set_taskpool_task_time(const uint32_t gametime,
6792                                        const Widelands::SchedulerTaskId task) {
6793 
6794 	for (auto& item : taskPool) {
6795 		if (item.id == task) {
6796 			item.due_time = gametime;
6797 			return;
6798 		}
6799 	}
6800 	NEVER_HERE();
6801 }
6802 
6803 // Retrieves due time of the task based on its ID
get_taskpool_task_time(const Widelands::SchedulerTaskId task)6804 uint32_t DefaultAI::get_taskpool_task_time(const Widelands::SchedulerTaskId task) {
6805 	for (const auto& item : taskPool) {
6806 		if (item.id == task) {
6807 			return item.due_time;
6808 		}
6809 	}
6810 
6811 	throw wexception("AI internal error: nonexistent task.");
6812 }
6813 
6814 // This performs one "iteration" of sorting based on due_time
6815 // We by design do not need full sorting...
sort_task_pool()6816 void DefaultAI::sort_task_pool() {
6817 	assert(!taskPool.empty());
6818 	for (int8_t i = taskPool.size() - 1; i > 0; --i) {
6819 		if (taskPool[i - 1].due_time > taskPool[i].due_time) {
6820 			std::iter_swap(taskPool.begin() + i - 1, taskPool.begin() + i);
6821 		}
6822 	}
6823 }
6824 
6825 // following two functions count mines of the same type (same output,
6826 // all levels)
mines_in_constr() const6827 uint32_t DefaultAI::mines_in_constr() const {
6828 	uint32_t count = 0;
6829 	for (const auto& m : mines_per_type) {
6830 		count += m.second.in_construction;
6831 	}
6832 	return count;
6833 }
6834 
mines_built() const6835 uint32_t DefaultAI::mines_built() const {
6836 	uint32_t count = 0;
6837 	for (const auto& m : mines_per_type) {
6838 		count += m.second.finished;
6839 	}
6840 	return count;
6841 }
6842 
6843 // following two functions count militarysites of the same size
msites_in_constr() const6844 uint32_t DefaultAI::msites_in_constr() const {
6845 	uint32_t count = 0;
6846 	for (const auto& m : msites_per_size) {
6847 		count += m.second.in_construction;
6848 	}
6849 	return count;
6850 }
msites_built() const6851 uint32_t DefaultAI::msites_built() const {
6852 	uint32_t count = 0;
6853 	for (const auto& m : msites_per_size) {
6854 		count += m.second.finished;
6855 	}
6856 	return count;
6857 }
6858 
6859 // This prints some basic statistics during a game to the command line -
6860 // missing materials and counts of different types of buildings.
6861 // The main purpose of this is when a game creator needs to finetune a map
6862 // and needs to know what resourcess are missing for which player and so on.
6863 // By default it is off (see kPrintStats)
6864 // TODO(tiborb): - it would be nice to have this activated by a command line switch
print_stats(uint32_t const gametime)6865 void DefaultAI::print_stats(uint32_t const gametime) {
6866 
6867 	if (!kPrintStats) {
6868 		set_taskpool_task_time(std::numeric_limits<int32_t>::max(), SchedulerTaskId::kPrintStats);
6869 		return;
6870 	}
6871 
6872 	PlayerNumber const pn = player_number();
6873 
6874 	const DescriptionIndex& nr_buildings = game().tribes().nrbuildings();
6875 	std::set<DescriptionIndex> materials;
6876 
6877 	// Collect information about the different buildings that our tribe can have
6878 	for (DescriptionIndex building_index = 0; building_index < nr_buildings; ++building_index) {
6879 		const BuildingDescr& bld = *tribe_->get_building_descr(building_index);
6880 		if (!tribe_->has_building(building_index)) {
6881 			continue;
6882 		}
6883 		if (bld.type() == MapObjectType::PRODUCTIONSITE) {
6884 			const ProductionSiteDescr& prod = dynamic_cast<const ProductionSiteDescr&>(bld);
6885 			for (const auto& temp_input : prod.input_wares()) {
6886 				if (materials.count(temp_input.first) == 0) {
6887 					materials.insert(temp_input.first);
6888 				}
6889 			}
6890 			for (const auto& temp_cost : prod.buildcost()) {
6891 				if (materials.count(temp_cost.first) == 0) {
6892 					materials.insert(temp_cost.first);
6893 				}
6894 			}
6895 		}
6896 
6897 		if (bld.type() == MapObjectType::TRAININGSITE) {
6898 			const ProductionSiteDescr& train = dynamic_cast<const TrainingSiteDescr&>(bld);
6899 			for (const auto& temp_cost : train.buildcost()) {
6900 				if (materials.count(temp_cost.first) == 0) {
6901 					materials.insert(temp_cost.first);
6902 				}
6903 			}
6904 		}
6905 	}
6906 
6907 	if (false) {
6908 		log(" %1d: %s Buildings count: Pr:%3u, Ml:%3u, Mi:%2u, Wh:%2u, Po:%u.\n", pn,
6909 		    gamestring_with_leading_zeros(gametime), static_cast<uint32_t>(productionsites.size()),
6910 		    static_cast<uint32_t>(militarysites.size()), static_cast<uint32_t>(mines_.size()),
6911 		    static_cast<uint32_t>(warehousesites.size() - num_ports), num_ports);
6912 	}
6913 	if (false) {
6914 		log(" %1s %-30s   %5s(perf)  %6s %6s %6s %8s %5s %5s %5s %5s\n", "T", "Buildings", "work.",
6915 		    "const.", "unocc.", "uncon.", "needed", "prec.", "pprio", "stock", "targ.");
6916 	}
6917 	for (uint32_t j = 0; j < buildings_.size(); ++j) {
6918 		BuildingObserver& bo = buildings_.at(j);
6919 		if ((bo.total_count() > 0 || bo.new_building == BuildingNecessity::kNeeded ||
6920 		     bo.new_building == BuildingNecessity::kForced ||
6921 		     bo.new_building == BuildingNecessity::kNeededPending ||
6922 		     bo.new_building == BuildingNecessity::kAllowed) &&
6923 		    bo.type != BuildingObserver::Type::kMilitarysite) {
6924 			std::string needeness;
6925 			if (bo.new_building == BuildingNecessity::kNeededPending) {
6926 				needeness = "pend";
6927 			} else if (bo.new_building == BuildingNecessity::kForced) {
6928 				needeness = "forc";
6929 			} else if (bo.new_building == BuildingNecessity::kAllowed) {
6930 				needeness = "allw";
6931 			} else if (bo.new_building == BuildingNecessity::kNotNeeded ||
6932 			           bo.new_building == BuildingNecessity::kForbidden) {
6933 				needeness = "no";
6934 			} else {
6935 				needeness = "yes";
6936 			}
6937 			std::string btype;
6938 			switch (bo.type) {
6939 			case BuildingObserver::Type::kWarehouse:
6940 				btype = "W";
6941 				break;
6942 			case BuildingObserver::Type::kMine:
6943 				btype = "M";
6944 				break;
6945 			case BuildingObserver::Type::kTrainingsite:
6946 				btype = "T";
6947 				break;
6948 			case BuildingObserver::Type::kProductionsite:
6949 				btype = "P";
6950 				break;
6951 			default:
6952 				btype = "?";
6953 			}
6954 
6955 			if (true) {
6956 				log(" %1s %-30s %5d(%3d%%)  %6d %6d %6d %8s %5d %5d %5d %5d\n", btype.c_str(), bo.name,
6957 				    bo.total_count() - bo.cnt_under_construction - bo.unoccupied_count -
6958 				       bo.unconnected_count,
6959 				    bo.current_stats, bo.cnt_under_construction, bo.unoccupied_count,
6960 				    bo.unconnected_count, needeness.c_str(), bo.max_needed_preciousness,
6961 				    bo.primary_priority, get_stocklevel(bo, gametime), bo.cnt_target);
6962 			}
6963 		}
6964 	}
6965 
6966 	std::string why = "; Why: ";
6967 
6968 	if ((numof_psites_in_constr + mines_in_constr()) >
6969 	    (productionsites.size() + mines_built()) / persistent_data->ai_productionsites_ratio + 2) {
6970 		why += " too many constr.";
6971 	}
6972 	// 3. too keep some proportions production sites vs military sites
6973 	if ((numof_psites_in_constr + productionsites.size()) >
6974 	    (msites_in_constr() + militarysites.size()) * 5) {
6975 		why += ", too many productionsites";
6976 	}
6977 	// 4. if we do not have 2 mines at least
6978 	if (mines_.size() < 2) {
6979 		why += ", less then 2 mines";
6980 	}
6981 
6982 	if (false) {
6983 		log("Prodsites in constr: %2d, mines in constr: %2d %s %s\n", numof_psites_in_constr,
6984 		    mines_in_constr(),
6985 		    (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) ? "NEW BUILDING STOP" :
6986 		                                                                       "",
6987 		    why.c_str());
6988 	}
6989 
6990 	if (false) {
6991 		log("Least military score: %5d/%3d, msites in constr: %3d,"
6992 		    "soldier st: %2d, strength: %3d\n",
6993 		    persistent_data->least_military_score, persistent_data->ai_personality_mil_upper_limit,
6994 		    msites_in_constr(), static_cast<int8_t>(soldier_status_),
6995 		    player_statistics.get_modified_player_power(player_number()));
6996 	}
6997 }
6998 
6999 template <typename T>
check_range(T value,T bottom_range,T upper_range,const char * value_name)7000 void DefaultAI::check_range(T value, T bottom_range, T upper_range, const char* value_name) {
7001 	if (value < bottom_range || value > upper_range) {
7002 		log(" %d: unexpected value for %s: %d\n", player_number(), value_name, value);
7003 	}
7004 }
7005 
check_range(T value,T upper_range,const char * value_name)7006 template <typename T> void DefaultAI::check_range(T value, T upper_range, const char* value_name) {
7007 	if (value > upper_range) {
7008 		log(" %d: unexpected value for %s: %d\n", player_number(), value_name, value);
7009 	}
7010 }
7011 
7012 template <typename T>
remove_from_dqueue(std::deque<T const * > & dq,T const * member)7013 bool DefaultAI::remove_from_dqueue(std::deque<T const*>& dq, T const* member) {
7014 	for (auto it = dq.begin(); it != dq.end(); ++it) {
7015 		if (*it == member) {
7016 			it = dq.erase(it);
7017 			return true;
7018 		}
7019 	}
7020 	return false;
7021 }
7022 
7023 // Looking for situation where for a critical mine (iron, or marble) there is just one mine and it
7024 // is
7025 // unoccupied, probably we need to dismantle another one to release a miner
critical_mine_unoccupied(uint32_t gametime)7026 bool DefaultAI::critical_mine_unoccupied(uint32_t gametime) {
7027 	// resetting unoccupied
7028 	for (auto& mine : mines_per_type) {
7029 		mine.second.unoccupied = 0;
7030 	}
7031 	for (auto& mine : mines_) {
7032 		if (!mines_per_type[mine.bo->mines].is_critical) {
7033 			continue;
7034 		}
7035 		if (mine.built_time + 3 * 60 * 1000 < gametime && !mine.site->can_start_working()) {
7036 			++mines_per_type[mine.bo->mines].unoccupied;
7037 		}
7038 	}
7039 
7040 	// Now check that that there is no working mine of the critical type
7041 	for (auto& mine : mines_per_type) {
7042 		if (mine.second.is_critical && mine.second.finished > 0 &&
7043 		    mine.second.unoccupied == mine.second.finished) {
7044 			return true;
7045 		}
7046 		assert(mine.second.unoccupied <= mines_.size());
7047 		assert(mine.second.unoccupied <= mine.second.total_count());
7048 	}
7049 	return false;
7050 }
7051 
7052 // Sets all inputs to zero and return true if inputs are already empty
set_inputs_to_zero(const Widelands::ProductionSiteObserver & site)7053 bool DefaultAI::set_inputs_to_zero(const Widelands::ProductionSiteObserver& site) {
7054 	uint16_t remaining_wares = 0;
7055 
7056 	for (auto& queue : site.site->inputqueues()) {
7057 		remaining_wares += queue->get_filled();
7058 		if (queue->get_max_fill() > 0) {
7059 			game().send_player_set_input_max_fill(
7060 			   *site.site, queue->get_index(), queue->get_type(), 0);
7061 		}
7062 	}
7063 	return remaining_wares == 0;
7064 }
7065 
set_inputs_to_max(const Widelands::ProductionSiteObserver & site)7066 void DefaultAI::set_inputs_to_max(const Widelands::ProductionSiteObserver& site) {
7067 	for (auto& queue : site.site->inputqueues()) {
7068 		if (queue->get_max_fill() < queue->get_max_size()) {
7069 			game().send_player_set_input_max_fill(
7070 			   *site.site, queue->get_index(), queue->get_type(), queue->get_max_size());
7071 		}
7072 	}
7073 }
stop_site(const Widelands::ProductionSiteObserver & site)7074 void DefaultAI::stop_site(const Widelands::ProductionSiteObserver& site) {
7075 	if (!site.site->is_stopped()) {
7076 		game().send_player_start_stop_building(*site.site);
7077 	}
7078 }
7079 
initiate_dismantling(Widelands::ProductionSiteObserver & site,uint32_t gametime)7080 void DefaultAI::initiate_dismantling(Widelands::ProductionSiteObserver& site, uint32_t gametime) {
7081 	site.dismantle_pending_since = gametime;
7082 	set_inputs_to_zero(site);
7083 	site.bo->construction_decision_time = gametime;
7084 }
7085 
get_land_owner(const Widelands::Map & map,const uint32_t coords) const7086 Widelands::PlayerNumber DefaultAI::get_land_owner(const Widelands::Map& map,
7087                                                   const uint32_t coords) const {
7088 	FCoords f = map.get_fcoords(Widelands::Coords::unhash(coords));
7089 	return f.field->get_owned_by();
7090 }
7091