← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/ai_variables_rework into lp:widelands

 

TiborB has proposed merging lp:~widelands-dev/widelands/ai_variables_rework into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/ai_variables_rework/+merge/333041

This change is only about memory allocation for AI functions. The goal is to reduce intensity how AI allocated and returns memory for its data. I dont have a proof but on PCs with low memory the game can have problems with allocation, resulting to crashes. After this changes I BELIEVE the number of crashes is reduced. Also I believe it has tiny, but measurable positive effect on game speed.
So what it contains:
1. changing std::lists to std::deque
2. making some vectors static + using reserve()
3. making some of integers static

I believe no harm should be done with this change
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/ai_variables_rework into lp:widelands.
=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h	2017-09-29 16:10:25 +0000
+++ src/ai/ai_help_structs.h	2017-10-31 17:41:52 +0000
@@ -388,7 +388,7 @@
 	explicit EconomyObserver(Widelands::Economy& e);
 
 	Widelands::Economy& economy;
-	std::list<Widelands::Flag const*> flags;
+	std::deque<Widelands::Flag const*> flags;
 	int32_t dismantle_grace_time;
 };
 

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2017-09-29 16:10:25 +0000
+++ src/ai/defaultai.cc	2017-10-31 17:41:52 +0000
@@ -162,43 +162,43 @@
 		});
 
 	// Subscribe to ShipNotes.
-	shipnotes_subscriber_ =
-	   Notifications::subscribe<NoteShipMessage>([this](const NoteShipMessage& note) {
-
-		   // in a short time between start and late_initialization the player
-		   // can get notes that can not be processed.
-		   // It seems that this causes no problem, at least no substantial
-		   if (player_ == nullptr) {
-			   return;
-		   }
-		   if (note.ship->get_owner()->player_number() != player_->player_number()) {
-			   return;
-		   }
-
-		   switch (note.message) {
-
-		   case NoteShipMessage::Message::kGained:
-			   gain_ship(*note.ship, NewShip::kBuilt);
-			   break;
-
-		   case NoteShipMessage::Message::kLost:
-			   for (std::list<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i) {
-				   if (i->ship == note.ship) {
-					   allships.erase(i);
-					   break;
-				   }
-			   }
-			   break;
-
-		   case NoteShipMessage::Message::kWaitingForCommand:
-			   for (std::list<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i) {
-				   if (i->ship == note.ship) {
-					   i->waiting_for_command_ = true;
-					   break;
-				   }
-			   }
-		   }
-		});
+	shipnotes_subscriber_ = Notifications::subscribe<NoteShipMessage>([this](
+	   const NoteShipMessage& note) {
+
+		// in a short time between start and late_initialization the player
+		// can get notes that can not be processed.
+		// It seems that this causes no problem, at least no substantial
+		if (player_ == nullptr) {
+			return;
+		}
+		if (note.ship->get_owner()->player_number() != player_->player_number()) {
+			return;
+		}
+
+		switch (note.message) {
+
+		case NoteShipMessage::Message::kGained:
+			gain_ship(*note.ship, NewShip::kBuilt);
+			break;
+
+		case NoteShipMessage::Message::kLost:
+			for (std::deque<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i) {
+				if (i->ship == note.ship) {
+					allships.erase(i);
+					break;
+				}
+			}
+			break;
+
+		case NoteShipMessage::Message::kWaitingForCommand:
+			for (std::deque<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i) {
+				if (i->ship == note.ship) {
+					i->waiting_for_command_ = true;
+					break;
+				}
+			}
+		}
+	});
 }
 
 DefaultAI::~DefaultAI() {
@@ -1254,7 +1254,8 @@
 	}
 
 	// are we going to count resources now?
-	bool resource_count_now = false;
+	static bool resource_count_now = false;
+	resource_count_now = false;
 	// Testing in first 10 seconds or if last testing was more then 60 sec ago
 	if (field.last_resources_check_time < 10000 ||
 	    field.last_resources_check_time - gametime > 60 * 1000) {
@@ -1445,12 +1446,15 @@
 	field.unconnected_nearby = false;
 
 	// collect information about productionsites nearby
-	std::vector<ImmovableFound> immovables;
+	static std::vector<ImmovableFound> immovables;
+	immovables.reserve(50);
+	immovables.clear();
 	// Search in a radius of range
 	map.find_immovables(Area<FCoords>(field.coords, kProductionArea + 2), &immovables);
 
 	// function seems to return duplicates, so we will use serial numbers to filter them out
-	std::set<uint32_t> unique_serials;
+	static std::set<uint32_t> unique_serials;
+	unique_serials.clear();
 
 	for (uint32_t i = 0; i < immovables.size(); ++i) {
 		const BaseImmovable& base_immovable = *immovables.at(i).object;
@@ -1483,8 +1487,10 @@
 	map.find_immovables(Area<FCoords>(field.coords, actual_enemy_check_area), &immovables);
 
 	// We are interested in unconnected immovables, but we must be also close to connected ones
-	bool any_connected_imm = false;
-	bool any_unconnected_imm = false;
+	static bool any_connected_imm = false;
+	any_connected_imm = false;
+	static bool any_unconnected_imm = false;
+	any_unconnected_imm = false;
 	unique_serials.clear();
 
 	for (uint32_t i = 0; i < immovables.size(); ++i) {
@@ -1806,7 +1812,8 @@
 
 	// is new site allowed at all here?
 	field.defense_msite_allowed = false;
-	int16_t multiplicator = 10;
+	static int16_t multiplicator = 10;
+	multiplicator = 10;
 	if (soldier_status_ == SoldiersStatus::kBadShortage) {
 		multiplicator = 4;
 	} else if (soldier_status_ == SoldiersStatus::kShortage) {
@@ -1953,15 +1960,17 @@
 	}
 
 	// Just used for easy checking whether a mine or something else was built.
-	bool mine = false;
-	uint32_t consumers_nearby_count = 0;
+	static bool mine = false;
+	mine = false;
+	static uint32_t consumers_nearby_count = 0;
+	consumers_nearby_count = 0;
 
 	const Map& map = game().map();
 
 	for (int32_t i = 0; i < 4; ++i)
 		spots_avail.at(i) = 0;
 
-	for (std::list<BuildableField*>::iterator i = buildable_fields.begin();
+	for (std::deque<BuildableField*>::iterator i = buildable_fields.begin();
 	     i != buildable_fields.end(); ++i)
 		++spots_avail.at((*i)->coords.field->nodecaps() & BUILDCAPS_SIZEMASK);
 
@@ -1973,7 +1982,7 @@
 	// the proportion depends on size of economy
 	// this proportion defines how dense the buildings will be
 	// it is degressive (allows high density on the beginning)
-	int32_t needed_spots = 0;
+	static int32_t needed_spots = 0;
 	if (productionsites.size() < 50) {
 		needed_spots = productionsites.size();
 	} else if (productionsites.size() < 100) {
@@ -2018,7 +2027,10 @@
 	const PlayerNumber pn = player_number();
 
 	// Genetic algorithm is used here
-	bool inputs[2 * kFNeuronBitSize] = {0};
+	static bool inputs[2 * kFNeuronBitSize] = {0};
+	for (int i = 0; i < 2 * kFNeuronBitSize; i++) {
+		inputs[i] = 0;
+	}
 	inputs[0] = (pow(msites_in_constr(), 2) > militarysites.size() + 2);
 	inputs[1] = !(pow(msites_in_constr(), 2) > militarysites.size() + 2);
 	inputs[2] =
@@ -2105,8 +2117,10 @@
 	inputs[51] = (numof_psites_in_constr > 8);
 	inputs[52] = (numof_psites_in_constr < 8);
 
-	int16_t needs_boost_economy_score = management_data.get_military_number_at(61) / 5;
-	int16_t increase_score_limit_score = 0;
+	static int16_t needs_boost_economy_score = management_data.get_military_number_at(61) / 5;
+	needs_boost_economy_score = management_data.get_military_number_at(61) / 5;
+	static int16_t increase_score_limit_score = 0;
+	increase_score_limit_score = 0;
 
 	for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {
 		if (management_data.f_neuron_pool[51].get_position(i)) {
@@ -2145,8 +2159,10 @@
 	const bool increase_least_score_limit =
 	   (increase_score_limit_score > management_data.get_military_number_at(45) / 5);
 
-	uint16_t concurent_ms_in_constr_no_enemy = 1;
-	uint16_t concurent_ms_in_constr_enemy_nearby = 2;
+	static uint16_t concurent_ms_in_constr_no_enemy = 1;
+	concurent_ms_in_constr_no_enemy = 1;
+	static uint16_t concurent_ms_in_constr_enemy_nearby = 2;
+	concurent_ms_in_constr_enemy_nearby = 2;
 
 	// resetting highest_nonmil_prio_ so it can be recalculated anew
 	highest_nonmil_prio_ = 0;
@@ -2379,7 +2395,7 @@
 	}
 
 	// first scan all buildable fields for regular buildings
-	for (std::list<BuildableField*>::iterator i = buildable_fields.begin();
+	for (std::deque<BuildableField*>::iterator i = buildable_fields.begin();
 	     i != buildable_fields.end(); ++i) {
 		BuildableField* const bf = *i;
 
@@ -2932,7 +2948,7 @@
 				}
 
 				// iterating over fields
-				for (std::list<MineableField*>::iterator j = mineable_fields.begin();
+				for (std::deque<MineableField*>::iterator j = mineable_fields.begin();
 				     j != mineable_fields.end(); ++j) {
 
 					MineableField* const mf = *j;
@@ -3529,7 +3545,7 @@
 		do {
 			blocked_fields.add(mr.location(), game().get_gametime() + 15 * 60 * 1000);
 		} while (mr.advance(map));
-		eco->flags.remove(&flag);
+		remove_from_dqueue<Widelands::Flag>(eco->flags, &flag);
 		game().send_player_bulldoze(*const_cast<Flag*>(&flag));
 		return true;
 	}
@@ -3550,12 +3566,12 @@
 		get_economy_observer(flag.economy())->flags.push_back(&flag);
 	}
 
-	for (std::list<EconomyObserver*>::iterator obs_iter = economies.begin();
+	for (std::deque<EconomyObserver*>::iterator obs_iter = economies.begin();
 	     obs_iter != economies.end(); ++obs_iter) {
 		// check if any flag has changed its economy
-		std::list<Flag const*>& fl = (*obs_iter)->flags;
+		std::deque<Flag const*>& fl = (*obs_iter)->flags;
 
-		for (std::list<Flag const*>::iterator j = fl.begin(); j != fl.end();) {
+		for (std::deque<Flag const*>::iterator j = fl.begin(); j != fl.end();) {
 			if (&(*obs_iter)->economy != &(*j)->economy()) {
 				get_economy_observer((*j)->economy())->flags.push_back(*j);
 				j = fl.erase(j);
@@ -4295,7 +4311,8 @@
 
 	bo.primary_priority = 0;
 
-	BasicEconomyBuildingStatus site_needed_for_economy = BasicEconomyBuildingStatus::kNone;
+	static BasicEconomyBuildingStatus site_needed_for_economy = BasicEconomyBuildingStatus::kNone;
+	site_needed_for_economy = BasicEconomyBuildingStatus::kNone;
 	if (gametime > 2 * 60 * 1000 && gametime < 120 * 60 * 1000 && !basic_economy_established) {
 		if (persistent_data->remaining_basic_buildings.count(bo.id) &&
 		    bo.cnt_under_construction == 0) {
@@ -4542,7 +4559,11 @@
 				return BuildingNecessity::kForbidden;
 			}
 
-			int16_t inputs[kFNeuronBitSize] = {0};
+			static int16_t inputs[kFNeuronBitSize] = {0};
+			// Reseting values as the variable is static
+			for (int i = 0; i < kFNeuronBitSize; i++) {
+				inputs[i] = 0;
+			}
 			inputs[0] = (bo.max_needed_preciousness == 0) ? -1 : 0;
 			inputs[1] = (bo.max_needed_preciousness > 0) ? 2 : 0;
 			inputs[2] = (bo.max_needed_preciousness == 0) ? -3 : 0;
@@ -4627,8 +4648,14 @@
 			}
 
 			// genetic algorithm to decide whether new rangers are needed
-			int16_t tmp_target = 2;
-			int16_t inputs[2 * kFNeuronBitSize] = {0};
+			static int16_t tmp_target = 2;
+			tmp_target = 2;
+			static int16_t inputs[2 * kFNeuronBitSize] = {0};
+			// Reseting values as the variable is static
+			for (int i = 0; i < 2 * kFNeuronBitSize; i++) {
+				inputs[i] = 0;
+			}
+
 			inputs[0] = (persistent_data->trees_around_cutters < 10) * 2;
 			inputs[1] = (persistent_data->trees_around_cutters < 20) * 2;
 			inputs[2] = (persistent_data->trees_around_cutters < 30) * 2;
@@ -4862,7 +4889,11 @@
 				return BuildingNecessity::kForbidden;
 			}
 
-			int16_t inputs[kFNeuronBitSize] = {0};
+			static int16_t inputs[kFNeuronBitSize] = {0};
+			// Reseting values as the variable is static
+			for (int i = 0; i < kFNeuronBitSize; i++) {
+				inputs[i] = 0;
+			}
 			inputs[0] = (gametime < 15 * 60 * 1000) ? -2 : 0;
 			inputs[1] = (gametime < 30 * 60 * 1000) ? -2 : 0;
 			inputs[2] = (gametime < 45 * 60 * 1000) ? -2 : 0;
@@ -4944,7 +4975,11 @@
 
 		} else if (bo.max_needed_preciousness > 0) {
 
-			int16_t inputs[4 * kFNeuronBitSize] = {0};
+			static int16_t inputs[4 * kFNeuronBitSize] = {0};
+			// Reseting values as the variable is static
+			for (int i = 0; i < 4 * kFNeuronBitSize; i++) {
+				inputs[i] = 0;
+			}
 			inputs[0] = (bo.total_count() <= 1) ?
 			               std::abs(management_data.get_military_number_at(110)) / 10 :
 			               0;
@@ -5222,7 +5257,7 @@
 uint32_t DefaultAI::calculate_stocklevel(Widelands::DescriptionIndex wt, const WareWorker what) {
 	uint32_t count = 0;
 
-	for (std::list<WarehouseSiteObserver>::iterator i = warehousesites.begin();
+	for (std::deque<WarehouseSiteObserver>::iterator i = warehousesites.begin();
 	     i != warehousesites.end(); ++i) {
 		if (what == WareWorker::kWare) {
 			count += i->site->get_wares().stock(wt);
@@ -5331,7 +5366,7 @@
 
 /// \returns the economy observer containing \arg economy
 EconomyObserver* DefaultAI::get_economy_observer(Economy& economy) {
-	for (std::list<EconomyObserver*>::iterator i = economies.begin(); i != economies.end(); ++i)
+	for (std::deque<EconomyObserver*>::iterator i = economies.begin(); i != economies.end(); ++i)
 		if (&(*i)->economy == &economy)
 			return *i;
 
@@ -5460,24 +5495,22 @@
 	if (upcast(Building const, building, &pi)) {
 		lose_building(*building);
 	} else if (upcast(Flag const, flag, &pi)) {
+		// Flag to be removed can be:
+		// 1. In one of our economies
 		for (EconomyObserver* eco_obs : economies) {
-			for (std::list<Flag const*>::iterator flag_iter = eco_obs->flags.begin();
-			     flag_iter != eco_obs->flags.end(); ++flag_iter) {
-				if (*flag_iter == flag) {
-					eco_obs->flags.erase(flag_iter);
-					return;
-				}
-			}
-		}
-		for (std::list<Flag const*>::iterator flag_iter = new_flags.begin();
-		     flag_iter != new_flags.end(); ++flag_iter) {
-			if (*flag_iter == flag) {
-				new_flags.erase(flag_iter);
+			if (remove_from_dqueue<Widelands::Flag>(eco_obs->flags, flag)) {
 				return;
 			}
 		}
+
+		// 2. in new flags to be processed yet
+		if (remove_from_dqueue<Widelands::Flag>(new_flags, flag)) {
+			return;
+		};
+
+		// 3. Or in neither of them
 	} else if (upcast(Road const, road, &pi)) {
-		roads.remove(road);
+		remove_from_dqueue<Widelands::Road>(roads, road);
 	}
 }
 
@@ -5487,7 +5520,7 @@
 	const uint32_t gametime = game().get_gametime();
 
 	// we must identify which mine matches the productionsite a note reffers to
-	for (std::list<ProductionSiteObserver>::iterator i = mines_.begin(); i != mines_.end(); ++i)
+	for (std::deque<ProductionSiteObserver>::iterator i = mines_.begin(); i != mines_.end(); ++i)
 		if (i->site == &site) {
 			if (i->no_resources_since > gametime) {
 				i->no_resources_since = gametime;
@@ -5762,7 +5795,7 @@
 
 		if (bo.type == BuildingObserver::Type::kProductionsite) {
 
-			for (std::list<ProductionSiteObserver>::iterator i = productionsites.begin();
+			for (std::deque<ProductionSiteObserver>::iterator i = productionsites.begin();
 			     i != productionsites.end(); ++i)
 				if (i->site == &b) {
 					if (i->upgrade_pending) {
@@ -5786,7 +5819,7 @@
 			}
 
 		} else if (bo.type == BuildingObserver::Type::kMine) {
-			for (std::list<ProductionSiteObserver>::iterator i = mines_.begin(); i != mines_.end();
+			for (std::deque<ProductionSiteObserver>::iterator i = mines_.begin(); i != mines_.end();
 			     ++i) {
 				if (i->site == &b) {
 					mines_.erase(i);
@@ -5812,7 +5845,7 @@
 		} else if (bo.type == BuildingObserver::Type::kMilitarysite) {
 			msites_per_size[bo.desc->get_size()].finished -= 1;
 
-			for (std::list<MilitarySiteObserver>::iterator i = militarysites.begin();
+			for (std::deque<MilitarySiteObserver>::iterator i = militarysites.begin();
 			     i != militarysites.end(); ++i) {
 				if (i->site == &b) {
 					militarysites.erase(i);
@@ -5823,7 +5856,7 @@
 			assert(ts_finished_count_ >= 1);
 			--ts_finished_count_;
 
-			for (std::list<TrainingSiteObserver>::iterator i = trainingsites.begin();
+			for (std::deque<TrainingSiteObserver>::iterator i = trainingsites.begin();
 			     i != trainingsites.end(); ++i) {
 				if (i->site == &b) {
 					trainingsites.erase(i);
@@ -5837,7 +5870,7 @@
 				--num_ports;
 			}
 
-			for (std::list<WarehouseSiteObserver>::iterator i = warehousesites.begin();
+			for (std::deque<WarehouseSiteObserver>::iterator i = warehousesites.begin();
 			     i != warehousesites.end(); ++i) {
 				if (i->site == &b) {
 					warehousesites.erase(i);
@@ -6192,6 +6225,17 @@
 	}
 }
 
+template <typename T>
+bool DefaultAI::remove_from_dqueue(std::deque<T const*>& dq, T const* member) {
+	for (auto it = dq.begin(); it != dq.end(); ++it) {
+		if (*it == member) {
+			it = dq.erase(it);
+			return true;
+		}
+	}
+	return false;
+}
+
 // Looking for situation where for a critical mine (iron, or marble) there is just one mine and it
 // is
 // unoccupied, probably we need to dismantle another one to release a miner

=== modified file 'src/ai/defaultai.h'
--- src/ai/defaultai.h	2017-09-29 16:10:25 +0000
+++ src/ai/defaultai.h	2017-10-31 17:41:52 +0000
@@ -244,6 +244,9 @@
 	template <typename T> void check_range(const T, const T, const T, const char*);
 	template <typename T> void check_range(const T, const T, const char*);
 
+	// Remove a member from std::deque
+	template <typename T> bool remove_from_dqueue(std::deque<T const*>&, T const*);
+
 	// Functions used for seafaring / defaultai_seafaring.cc
 	Widelands::IslandExploreDirection randomExploreDirection();
 	void gain_ship(Widelands::Ship&, NewShip);
@@ -285,24 +288,24 @@
 	uint16_t trees_nearby_treshold_;
 
 	std::vector<Widelands::BuildingObserver> buildings_;
-	std::list<Widelands::FCoords> unusable_fields;
-	std::list<Widelands::BuildableField*> buildable_fields;
+	std::deque<Widelands::FCoords> unusable_fields;
+	std::deque<Widelands::BuildableField*> buildable_fields;
 	Widelands::BlockedFields blocked_fields;
 	Widelands::PlayersStrengths player_statistics;
 	Widelands::ManagementData management_data;
 	Widelands::ExpansionType expansion_type;
 	std::unordered_set<uint32_t> port_reserved_coords;
-	std::list<Widelands::MineableField*> mineable_fields;
-	std::list<Widelands::Flag const*> new_flags;
-	std::list<Widelands::Coords> flags_to_be_removed;
-	std::list<Widelands::Road const*> roads;
-	std::list<Widelands::EconomyObserver*> economies;
-	std::list<Widelands::ProductionSiteObserver> productionsites;
-	std::list<Widelands::ProductionSiteObserver> mines_;
-	std::list<Widelands::MilitarySiteObserver> militarysites;
-	std::list<Widelands::WarehouseSiteObserver> warehousesites;
-	std::list<Widelands::TrainingSiteObserver> trainingsites;
-	std::list<Widelands::ShipObserver> allships;
+	std::deque<Widelands::MineableField*> mineable_fields;
+	std::deque<Widelands::Flag const*> new_flags;
+	std::deque<Widelands::Coords> flags_to_be_removed;
+	std::deque<Widelands::Road const*> roads;
+	std::deque<Widelands::EconomyObserver*> economies;
+	std::deque<Widelands::ProductionSiteObserver> productionsites;
+	std::deque<Widelands::ProductionSiteObserver> mines_;
+	std::deque<Widelands::MilitarySiteObserver> militarysites;
+	std::deque<Widelands::WarehouseSiteObserver> warehousesites;
+	std::deque<Widelands::TrainingSiteObserver> trainingsites;
+	std::deque<Widelands::ShipObserver> allships;
 	std::vector<Widelands::WareObserver> wares;
 	// This is a vector that is filled up on initiatlization
 	// and no items are added/removed afterwards

=== modified file 'src/ai/defaultai_seafaring.cc'
--- src/ai/defaultai_seafaring.cc	2017-08-20 08:34:02 +0000
+++ src/ai/defaultai_seafaring.cc	2017-10-31 17:41:52 +0000
@@ -70,7 +70,9 @@
 	}
 
 	// here we check for surface rocks + trees
-	std::vector<ImmovableFound> immovables;
+	static std::vector<ImmovableFound> immovables;
+	immovables.clear();
+	immovables.reserve(50);
 	// Search in a radius of range
 	map.find_immovables(Area<FCoords>(map.get_fcoords(candidate_spot), 10), &immovables);
 
@@ -148,7 +150,7 @@
 	}
 
 	// and now over ships
-	for (std::list<ShipObserver>::iterator sp_iter = allships.begin(); sp_iter != allships.end();
+	for (std::deque<ShipObserver>::iterator sp_iter = allships.begin(); sp_iter != allships.end();
 	     ++sp_iter) {
 		if (sp_iter->ship->state_is_expedition()) {
 			expeditions_in_progress += 1;
@@ -301,7 +303,7 @@
 	while (!marine_task_queue.empty()) {
 		if (marine_task_queue.back() == kStopShipyard) {
 			// iterate over all production sites searching for shipyard
-			for (std::list<ProductionSiteObserver>::iterator site = productionsites.begin();
+			for (std::deque<ProductionSiteObserver>::iterator site = productionsites.begin();
 			     site != productionsites.end(); ++site) {
 				if (site->bo->is(BuildingAttribute::kShipyard)) {
 					if (!site->site->is_stopped()) {
@@ -312,7 +314,7 @@
 		}
 
 		if (marine_task_queue.back() == kReprioritize) {
-			for (std::list<ProductionSiteObserver>::iterator site = productionsites.begin();
+			for (std::deque<ProductionSiteObserver>::iterator site = productionsites.begin();
 			     site != productionsites.end(); ++site) {
 				if (site->bo->is(BuildingAttribute::kShipyard)) {
 					for (uint32_t k = 0; k < site->bo->inputs.size(); ++k) {

=== modified file 'src/ai/defaultai_warfare.cc'
--- src/ai/defaultai_warfare.cc	2017-09-29 16:10:25 +0000
+++ src/ai/defaultai_warfare.cc	2017-10-31 17:41:52 +0000
@@ -50,7 +50,9 @@
 		FCoords f = map.get_fcoords(ms->get_position());
 
 		// get list of immovable around this our military site
-		std::vector<ImmovableFound> immovables;
+		static std::vector<ImmovableFound> immovables;
+		immovables.clear();
+		immovables.reserve(40);
 		map.find_immovables(Area<FCoords>(f, (vision + 3 < 13) ? 13 : vision + 3), &immovables,
 		                    FindImmovableAttackTarget());
 
@@ -87,7 +89,9 @@
 	uint8_t best_score = 0;
 	uint32_t count = 0;
 	// sites that were either conquered or destroyed
-	std::vector<uint32_t> disappeared_sites;
+	static std::vector<uint32_t> disappeared_sites;
+	disappeared_sites.clear();
+	disappeared_sites.reserve(6);
 
 	// Willingness to attack depend on how long ago the last soldier has been trained. This is used
 	// as indicator how busy our trainingsites are.
@@ -249,7 +253,11 @@
 					                      player_statistics.get_old60_player_land(pn);
 				}
 
-				int16_t inputs[3 * kFNeuronBitSize] = {0};
+				static int16_t inputs[3 * kFNeuronBitSize] = {0};
+				// Reseting values as the variable is static
+				for (int j = 0; j < 3 * kFNeuronBitSize; j++) {
+					inputs[j] = 0;
+				}
 				inputs[0] = (site->second.attack_soldiers_strength - site->second.defenders_strength) *
 				            std::abs(management_data.get_military_number_at(114)) / 30;
 				inputs[1] = (site->second.attack_soldiers_strength - site->second.defenders_strength) *
@@ -753,7 +761,7 @@
 	}
 
 	ts_without_trainers_ = 0;  // zeroing
-	for (std::list<TrainingSiteObserver>::iterator site = trainingsites.begin();
+	for (std::deque<TrainingSiteObserver>::iterator site = trainingsites.begin();
 	     site != trainingsites.end(); ++site) {
 
 		if (!site->site->can_start_working()) {
@@ -948,6 +956,10 @@
 	const uint16_t total_score = scores[0] + scores[1] + scores[2];
 
 	int32_t inputs[4 * kFNeuronBitSize] = {0};
+	// Reseting values as the variable is static
+	for (int i = 0; i < 4 * kFNeuronBitSize; i++) {
+		inputs[i] = 0;
+	}
 	inputs[0] = (msites_total < 1) ? 1 : 0;
 	inputs[1] = (msites_total < 2) ? 1 : 0;
 	inputs[2] = (msites_total < 3) ? 1 : 0;


Follow ups