← Back to team overview

widelands-dev team mailing list archive

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

 

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

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1516785 in widelands: "Redefine difficulty levels"
  https://bugs.launchpad.net/widelands/+bug/1516785

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

- Redesigned limitation of buildings count for weaker player (It seems that it was broken)
- New set of WAI files
- Slight change in mutation logic
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/ai_differentiation into lp:widelands.
=== modified file 'data/ai/ai_input_1.wai'
--- data/ai/ai_input_1.wai	2017-09-08 04:37:41 +0000
+++ data/ai/ai_input_1.wai	2017-09-20 17:28:07 +0000
@@ -1,4 +1,4 @@
-# Automatically created by Widelands bzr8437[frisians] (Debug)
+# Automatically created by Widelands bzr8447[ai_adjust_hints] (Release)
 # See wiki for more info: https://wl.widelands.org/wiki/Ai%20Training/
 
 [magic_numbers]
@@ -25,7 +25,7 @@
 20="58"
 21="-28"
 22="13"
-23="39"
+23="59"
 24="0"
 25="0"
 26="45"
@@ -44,7 +44,7 @@
 39="-72"
 40="51"
 41="51"
-42="13"
+42="49"
 43="-49"
 44="73"
 45="-6"
@@ -54,7 +54,7 @@
 49="-41"
 50="-3"
 51="-55"
-52="62"
+52="58"
 53="0"
 54="57"
 55="-92"
@@ -142,7 +142,7 @@
 137="-100"
 138="36"
 139="-4"
-140="-28"
+140="-9"
 141="15"
 142="-57"
 143="-82"
@@ -321,7 +321,7 @@
 0="483200277"
 1="1310583807"
 2="1146587310"
-3="3992184279"
+3="3992167895"
 4="2392253055"
 5="72410151"
 6="3177317446"
@@ -334,7 +334,7 @@
 13="4031844007"
 14="466688301"
 15="1174624614"
-16="2326435667"
+16="2326697811"
 17="2785353768"
 18="2923165204"
 19="1657182988"
@@ -348,7 +348,7 @@
 27="3069847931"
 28="4080809651"
 29="119008422"
-30="2921738017"
+30="2921738081"
 31="3462444063"
 32="4152203232"
 33="2048168826"
@@ -366,7 +366,7 @@
 45="1543642853"
 46="1267826585"
 47="2484812109"
-48="2823884087"
+48="2832272695"
 49="3081242716"
 50="2293521686"
 51="727162548"

=== modified file 'data/ai/ai_input_2.wai'
--- data/ai/ai_input_2.wai	2017-09-08 04:37:41 +0000
+++ data/ai/ai_input_2.wai	2017-09-20 17:28:07 +0000
@@ -1,4 +1,4 @@
-# Automatically created by Widelands bzr8437[frisians] (Debug)
+# Automatically created by Widelands bzr8447[ai_adjust_hints] (Release)
 # See wiki for more info: https://wl.widelands.org/wiki/Ai%20Training/
 
 [magic_numbers]
@@ -39,12 +39,12 @@
 34="-72"
 35="52"
 36="-68"
-37="-31"
+37="-47"
 38="17"
 39="-72"
 40="51"
 41="51"
-42="0"
+42="-26"
 43="-49"
 44="47"
 45="0"
@@ -159,7 +159,7 @@
 2="0"
 3="47"
 4="-93"
-5="-88"
+5="63"
 6="-47"
 7="86"
 8="50"
@@ -182,7 +182,7 @@
 25="31"
 26="47"
 27="-49"
-28="79"
+28="68"
 29="0"
 30="0"
 31="25"
@@ -221,7 +221,7 @@
 64="-14"
 65="-36"
 66="0"
-67="63"
+67="51"
 68="0"
 69="-26"
 70="48"
@@ -324,7 +324,7 @@
 3="3989038583"
 4="2392240695"
 5="609313893"
-6="3177319494"
+6="3177319490"
 7="2470638061"
 8="1737719069"
 9="906272344"
@@ -358,8 +358,8 @@
 37="2245976000"
 38="1096631444"
 39="3885459710"
-40="3462144474"
-41="996514907"
+40="3457950168"
+41="996531291"
 42="2041263380"
 43="3998980624"
 44="3482467367"
@@ -371,10 +371,10 @@
 50="2293521678"
 51="727170724"
 52="2337924218"
-53="2822240129"
+53="2822240001"
 54="2099269402"
 55="3081820126"
 56="1364736179"
 57="3215255873"
-58="4220516419"
+58="3146774595"
 59="698271105"

=== modified file 'data/ai/ai_input_3.wai'
--- data/ai/ai_input_3.wai	2017-09-08 04:37:41 +0000
+++ data/ai/ai_input_3.wai	2017-09-20 17:28:07 +0000
@@ -1,4 +1,4 @@
-# Automatically created by Widelands bzr8437[frisians] (Debug)
+# Automatically created by Widelands bzr8447[ai_adjust_hints] (Release)
 # See wiki for more info: https://wl.widelands.org/wiki/Ai%20Training/
 
 [magic_numbers]
@@ -20,7 +20,7 @@
 15="-2"
 16="26"
 17="46"
-18="-77"
+18="-46"
 19="0"
 20="58"
 21="-28"
@@ -44,9 +44,9 @@
 39="-72"
 40="51"
 41="51"
-42="49"
+42="11"
 43="-49"
-44="47"
+44="73"
 45="-3"
 46="6"
 47="3"
@@ -106,7 +106,7 @@
 101="-42"
 102="31"
 103="-92"
-104="-62"
+104="-83"
 105="75"
 106="-35"
 107="-63"
@@ -326,8 +326,8 @@
 5="72410151"
 6="3178103874"
 7="2466439405"
-8="1670593821"
-9="906270296"
+8="1637039389"
+9="906272344"
 10="1266807704"
 11="2811238757"
 12="1160748840"
@@ -336,16 +336,16 @@
 15="1174624614"
 16="2326435667"
 17="2785353768"
-18="2923165204"
+18="2923034132"
 19="1657183084"
 20="127874232"
 21="2840446882"
 22="3269953620"
 23="2809068809"
-24="3213948893"
+24="3197171673"
 25="350248689"
 26="403599210"
-27="4143589755"
+27="4076480891"
 28="4078712499"
 29="119008422"
 30="2921738017"
@@ -364,12 +364,12 @@
 43="3998980624"
 44="3381672999"
 45="1560420069"
-46="1267826589"
-47="2484803917"
+46="1272020893"
+47="2493192525"
 48="2832796979"
 49="3081242716"
 50="2293521686"
-51="727162548"
+51="727162556"
 52="2405032058"
 53="2822242065"
 54="1025593118"
@@ -377,4 +377,4 @@
 56="1096297651"
 57="3215223873"
 58="3146774595"
-59="701417377"
+59="701482913"

=== modified file 'data/ai/ai_input_4.wai'
--- data/ai/ai_input_4.wai	2017-09-08 04:37:41 +0000
+++ data/ai/ai_input_4.wai	2017-09-20 17:28:07 +0000
@@ -1,4 +1,4 @@
-# Automatically created by Widelands bzr8437[frisians] (Debug)
+# Automatically created by Widelands bzr8447[ai_adjust_hints] (Release)
 # See wiki for more info: https://wl.widelands.org/wiki/Ai%20Training/
 
 [magic_numbers]
@@ -44,7 +44,7 @@
 39="-72"
 40="51"
 41="51"
-42="22"
+42="33"
 43="-49"
 44="47"
 45="-3"
@@ -193,7 +193,7 @@
 36="-60"
 37="-42"
 38="-55"
-39="-34"
+39="-71"
 40="-27"
 41="-73"
 42="-87"
@@ -324,21 +324,21 @@
 3="3990087127"
 4="2392236671"
 5="72410151"
-6="3178103874"
+6="3178102850"
 7="2466439405"
 8="1670593821"
-9="906272344"
+9="907318872"
 10="1266807704"
-11="2811238765"
+11="2811238757"
 12="1160748840"
 13="4031844007"
 14="1540430125"
-15="1174657382"
+15="1174624614"
 16="2326435667"
 17="2785353768"
 18="2923165204"
-19="1657182988"
-20="127743160"
+19="1657183076"
+20="127874232"
 21="2840446882"
 22="3269953620"
 23="2809068809"
@@ -364,7 +364,7 @@
 43="3998980624"
 44="3381672999"
 45="1560420069"
-46="1267826589"
+46="1269923741"
 47="2484803917"
 48="2832796979"
 49="3081242716"
@@ -372,9 +372,9 @@
 51="727162548"
 52="2405032058"
 53="2822242065"
-54="1026640670"
+54="1025593118"
 55="859101088"
 56="1096297651"
-57="3214961729"
+57="3215223873"
 58="3146774595"
 59="701417377"

=== modified file 'data/tribes/buildings/productionsites/atlanteans/blackroot_farm/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/blackroot_farm/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/atlanteans/blackroot_farm/init.lua	2017-09-20 17:28:07 +0000
@@ -29,7 +29,9 @@
 
    aihints = {
       prohibited_till = 550,
-      space_consumer = true
+      space_consumer = true,
+      very_weak_ai_limit = 1,
+      weak_ai_limit = 2
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/atlanteans/farm/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/farm/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/atlanteans/farm/init.lua	2017-09-20 17:28:07 +0000
@@ -33,7 +33,9 @@
       basic_amount = 1,
        -- Farm needs spidercloth to be built and spidercloth needs corn for production
        -- -> farm should be built ASAP!
-      prohibited_till = 250
+      prohibited_till = 250,
+      very_weak_ai_limit = 1,
+      weak_ai_limit = 3
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/atlanteans/fishers_house/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/fishers_house/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/atlanteans/fishers_house/init.lua	2017-09-20 17:28:07 +0000
@@ -27,7 +27,9 @@
    aihints = {
       needs_water = true,
       basic_amount = 1,
-      prohibited_till = 540
+      prohibited_till = 540,
+      very_weak_ai_limit = 2,
+      weak_ai_limit = 4
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/atlanteans/foresters_house/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/foresters_house/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/atlanteans/foresters_house/init.lua	2017-09-20 17:28:07 +0000
@@ -28,7 +28,9 @@
 
    aihints = {
       space_consumer = true,
-      supports_production_of = { "log" }
+      supports_production_of = { "log" },
+      very_weak_ai_limit = 2,
+      weak_ai_limit = 4
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/atlanteans/sawmill/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/sawmill/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/atlanteans/sawmill/init.lua	2017-09-20 17:28:07 +0000
@@ -32,7 +32,7 @@
 
    aihints = {
       basic_amount = 2,
-      very_weak_ai_limit = 1,
+      very_weak_ai_limit = 2,
       weak_ai_limit = 2
    },
 

=== modified file 'data/tribes/buildings/productionsites/barbarians/farm/init.lua'
--- data/tribes/buildings/productionsites/barbarians/farm/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/barbarians/farm/init.lua	2017-09-20 17:28:07 +0000
@@ -41,7 +41,9 @@
 
    aihints = {
       space_consumer = true,
-      prohibited_till = 400
+      prohibited_till = 400,
+      very_weak_ai_limit = 1,
+      weak_ai_limit = 3
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/barbarians/fishers_hut/init.lua'
--- data/tribes/buildings/productionsites/barbarians/fishers_hut/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/barbarians/fishers_hut/init.lua	2017-09-20 17:28:07 +0000
@@ -33,7 +33,9 @@
 
    aihints = {
       needs_water = true,
-      prohibited_till = 490
+      prohibited_till = 490,
+      very_weak_ai_limit = 1,
+      weak_ai_limit = 3
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/barbarians/hunters_hut/init.lua'
--- data/tribes/buildings/productionsites/barbarians/hunters_hut/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/barbarians/hunters_hut/init.lua	2017-09-20 17:28:07 +0000
@@ -35,7 +35,9 @@
 
    aihints = {
       prohibited_till = 480,
-      basic_amount = 1
+      basic_amount = 1,
+      very_weak_ai_limit = 1,
+      weak_ai_limit = 2
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/barbarians/rangers_hut/init.lua'
--- data/tribes/buildings/productionsites/barbarians/rangers_hut/init.lua	2017-08-25 19:17:15 +0000
+++ data/tribes/buildings/productionsites/barbarians/rangers_hut/init.lua	2017-09-20 17:28:07 +0000
@@ -34,7 +34,9 @@
    aihints = {
       supports_production_of = { "log" },
       space_consumer = true,
-      basic_amount = 1
+      basic_amount = 1,
+      very_weak_ai_limit = 3,
+      weak_ai_limit = 5
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/empire/bakery/init.lua'
--- data/tribes/buildings/productionsites/empire/bakery/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/empire/bakery/init.lua	2017-09-20 17:28:07 +0000
@@ -37,7 +37,9 @@
 
    aihints = {
       prohibited_till = 550,
-      basic_amount = 1
+      basic_amount = 1,
+      very_weak_ai_limit = 1,
+      weak_ai_limit = 2
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/empire/farm/init.lua'
--- data/tribes/buildings/productionsites/empire/farm/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/empire/farm/init.lua	2017-09-20 17:28:07 +0000
@@ -32,7 +32,9 @@
    aihints = {
       basic_amount = 1,
       space_consumer = true,
-      prohibited_till = 510
+      prohibited_till = 510,
+      very_weak_ai_limit = 1,
+      weak_ai_limit = 3
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/empire/foresters_house/init.lua'
--- data/tribes/buildings/productionsites/empire/foresters_house/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/empire/foresters_house/init.lua	2017-09-20 17:28:07 +0000
@@ -28,7 +28,9 @@
 
    aihints = {
       space_consumer = true,
-      supports_production_of = { "log" }
+      supports_production_of = { "log" },
+      very_weak_ai_limit = 2,
+      weak_ai_limit = 4
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/empire/sawmill/init.lua'
--- data/tribes/buildings/productionsites/empire/sawmill/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/empire/sawmill/init.lua	2017-09-20 17:28:07 +0000
@@ -32,7 +32,7 @@
 
    aihints = {
       basic_amount = 2,
-      very_weak_ai_limit = 1,
+      very_weak_ai_limit = 2,
       weak_ai_limit = 2
    },
 

=== modified file 'data/tribes/buildings/productionsites/empire/sheepfarm/init.lua'
--- data/tribes/buildings/productionsites/empire/sheepfarm/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/empire/sheepfarm/init.lua	2017-09-20 17:28:07 +0000
@@ -31,7 +31,9 @@
    },
 
    aihints = {
-      prohibited_till = 380
+      prohibited_till = 380,
+      very_weak_ai_limit = 1,
+      weak_ai_limit = 3
    },
 
    working_positions = {

=== modified file 'data/tribes/buildings/productionsites/empire/vineyard/init.lua'
--- data/tribes/buildings/productionsites/empire/vineyard/init.lua	2017-09-03 07:59:51 +0000
+++ data/tribes/buildings/productionsites/empire/vineyard/init.lua	2017-09-20 17:28:07 +0000
@@ -30,7 +30,10 @@
    aihints = {
       space_consumer = true,
       basic_amount = 1,
-      prohibited_till = 490
+      prohibited_till = 490,
+      very_weak_ai_limit = 1,
+      weak_ai_limit = 3
+
    },
 
    working_positions = {

=== modified file 'src/ai/ai_help_structs.cc'
--- src/ai/ai_help_structs.cc	2017-08-20 17:45:42 +0000
+++ src/ai/ai_help_structs.cc	2017-09-20 17:28:07 +0000
@@ -609,8 +609,16 @@
 // Mutating, but all done on persistent data
 void ManagementData::mutate(const uint8_t pn) {
 
+	// Below numbers are used to dictate intensity of mutation
+	// Probability that a value will be mutated = 1 / probability
+	// (lesser number means higher probability and higher mutation)
 	int16_t probability =
 	   shift_weight_value(get_military_number_at(kMutationRatePosition), false) + 101;
+	// Some of mutation will be agressive - over full range of values, the number below
+	// say how many (aproximately) they will be
+	uint16_t prefferred_numbers_count = 0;
+	// This is used to store status whether wild card was or was not used
+	bool wild_card = false;
 
 	// When doing training mutation probability is to be bigger than not in training mode
 	if (ai_training_mode_) {
@@ -620,29 +628,32 @@
 		if (probability < kLowerDefaultMutationLimit) {
 			probability = kLowerDefaultMutationLimit;
 		}
+		prefferred_numbers_count = 1;
 	} else {
 		probability = kNoAiTrainingMutation;
 	}
 
 	set_military_number_at(kMutationRatePosition, probability - 101);
-
 	// decreasing probability (or rather increasing probability of mutation) if weaker player
 	if (ai_type == Widelands::AiType::kWeak) {
-		probability /= 2;
-		log("%2d: Weak mode, increasing mutation probability to 1 / %d\n", pn, probability);
+		probability /= 15;
+		prefferred_numbers_count = 25;
 	} else if (ai_type == Widelands::AiType::kVeryWeak) {
-		probability /= 4;
-		log("%2d: Very weak mode, increasing mutation probability to 1 / %d\n", pn, probability);
+		probability /= 40;
+		prefferred_numbers_count = 50;
 	}
 
 	// Wildcard for ai trainingmode
-	if (ai_training_mode_ && std::rand() % 8 == 0) {
+	if (ai_training_mode_ && std::rand() % 8 == 0 && ai_type == Widelands::AiType::kNormal) {
 		probability /= 3;
+		prefferred_numbers_count = 5;
+		wild_card = true;
 	}
 
 	assert(probability > 0 && probability <= 201);
 
-	log("%2d: mutating DNA with probability 1 / %3d:\n", pn, probability);
+	log("%2d: mutating DNA with probability 1 / %3d, preffered numbers target %d%s:\n", pn,
+	    probability, prefferred_numbers_count, (wild_card) ? ", wild card" : "");
 
 	if (probability < 201) {
 
@@ -650,8 +661,10 @@
 		{
 			// Preferred numbers are ones that will be mutated agressively in full range
 			// [-kWeightRange, kWeightRange]
-			std::set<int32_t> preferred_numbers = {std::rand() % kMagicNumbersSize *
-			                                       pref_number_probability};
+			std::set<int32_t> preferred_numbers;
+			for (int i = 0; i < prefferred_numbers_count; i++) {
+				preferred_numbers.insert(std::rand() % pref_number_probability);
+			}
 
 			for (uint16_t i = 0; i < kMagicNumbersSize; i += 1) {
 				if (i == kMutationRatePosition) {  // mutated above
@@ -676,8 +689,10 @@
 		// Modifying pool of neurons
 		{
 			// Neurons to be mutated more agressively
-			std::set<int32_t> preferred_neurons = {std::rand() % kNeuronPoolSize *
-			                                       pref_number_probability};
+			std::set<int32_t> preferred_neurons;
+			for (int i = 0; i < prefferred_numbers_count; i++) {
+				preferred_neurons.insert(std::rand() % pref_number_probability);
+			}
 			for (auto& item : neuron_pool) {
 
 				const MutatingIntensity mutating_intensity =
@@ -707,8 +722,13 @@
 		// Modifying pool of f-neurons
 		{
 			// FNeurons to be mutated more agressively
-			std::set<int32_t> preferred_f_neurons = {std::rand() % kFNeuronPoolSize *
-			                                         pref_number_probability};
+			std::set<int32_t> preferred_f_neurons;
+			// prefferred_numbers_count is multiplied by 3 because FNeuron store more than
+			// one value
+			for (int i = 0; i < 3 * prefferred_numbers_count; i++) {
+				preferred_f_neurons.insert(std::rand() % pref_number_probability);
+			}
+
 			for (auto& item : f_neuron_pool) {
 				uint8_t changed_bits = 0;
 				// is this a preferred neuron

=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h	2017-08-25 19:17:15 +0000
+++ src/ai/ai_help_structs.h	2017-09-20 17:28:07 +0000
@@ -124,7 +124,6 @@
 constexpr int kFNeuronPoolSize = 60;
 constexpr int kFNeuronBitSize = 32;
 constexpr int kMutationRatePosition = 42;
-constexpr int16_t AiPrefNumberProbability = 5;
 
 constexpr uint32_t kNever = std::numeric_limits<uint32_t>::max();
 
@@ -664,7 +663,6 @@
 	}
 	void set_ai_training_mode() {
 		ai_training_mode_ = true;
-		pref_number_probability = AiPrefNumberProbability;
 	}
 
 	int16_t get_military_number_at(uint8_t);
@@ -687,7 +685,7 @@
 	uint16_t performance_change = 0U;
 	Widelands::AiType ai_type = Widelands::AiType::kNormal;
 	bool ai_training_mode_ = false;
-	uint16_t pref_number_probability = 100;
+	uint16_t pref_number_probability = 200;
 	AiDnaHandler ai_dna_handler;
 };
 

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2017-08-26 11:08:00 +0000
+++ src/ai/defaultai.cc	2017-09-20 17:28:07 +0000
@@ -448,6 +448,14 @@
 						++conquered_wh;
 					}
 				};
+				if (!basic_economy_established) {
+					assert(!persistent_data->remaining_basic_buildings.empty());
+					assert(persistent_data->remaining_buildings_size > 0);
+					log("%2d: Basic economy not achieved, %lu building(s) missing, f.e.: %s\n",
+					    player_number(), persistent_data->remaining_basic_buildings.size(),
+					    get_building_observer(persistent_data->remaining_basic_buildings.begin()->first)
+					       .name);
+				}
 				if (!enemy_warehouses.empty())
 					log("Conquered warehouses: %d / %lu\n", conquered_wh, enemy_warehouses.size());
 				management_data.review(
@@ -1007,7 +1015,7 @@
 	if (!basic_economy_established) {
 		log("%2d: Initializing in the basic economy mode, required buildings:\n", player_number());
 		for (auto bb : persistent_data->remaining_basic_buildings) {
-			log("   %3d / %-25s- target %d\n", bb.first, get_building_observer(bb.first).name,
+			log("   %3d / %-28s- target %d\n", bb.first, get_building_observer(bb.first).name,
 			    bb.second);
 		}
 	}
@@ -1045,6 +1053,9 @@
 
 	productionsites_ratio_ = management_data.get_military_number_at(86) / 10 + 12;
 
+	assert(persistent_data->remaining_basic_buildings.size() ==
+	       persistent_data->remaining_buildings_size);
+
 	// Just to be initialized
 	soldier_status_ = SoldiersStatus::kEnough;
 	vacant_mil_positions_average_ = 0;
@@ -1989,6 +2000,9 @@
 		    player_number(), persistent_data->remaining_basic_buildings.size(),
 		    gamestring_with_leading_zeros(gametime));
 		basic_economy_established = true;
+		// Zeroing following to preserve consistency
+		persistent_data->remaining_buildings_size = 0;
+		persistent_data->remaining_basic_buildings.clear();
 	}
 
 	// *_military_scores are used as minimal score for a new military building
@@ -2352,14 +2366,13 @@
 			bo.primary_priority = 0;
 		}
 
-		if (ai_training_mode_ && bo.type == BuildingObserver::Type::kProductionsite) {
+		const bool log_needed = (bo.new_building == BuildingNecessity::kAllowed ||
+		                         bo.new_building == BuildingNecessity::kForced ||
+		                         bo.new_building == BuildingNecessity::kNeeded);
+		if (ai_training_mode_ && bo.type == BuildingObserver::Type::kProductionsite &&
+		    (gametime % 20 == 0 || log_needed)) {
 			log("%2d: %-35s(%2d now) %-11s: max prec: %2d/%2d, primary priority: %4d, overdue: %3d\n",
-			    player_number(), bo.name, bo.total_count(),
-			    (bo.new_building == BuildingNecessity::kAllowed ||
-			     bo.new_building == BuildingNecessity::kForced ||
-			     bo.new_building == BuildingNecessity::kNeeded) ?
-			       "needed" :
-			       "not needed",
+			    player_number(), bo.name, bo.total_count(), (log_needed) ? "needed" : "not needed",
 			    bo.max_needed_preciousness, bo.max_preciousness, bo.primary_priority,
 			    bo.new_building_overdue);
 		}
@@ -3580,6 +3593,12 @@
 	// Get link to productionsite that should be checked
 	ProductionSiteObserver& site = productionsites.front();
 
+	// Make sure we are not above ai type limit
+	if (site.bo->total_count() > site.bo->cnt_limit_by_aimode) {
+		log("Too many %s: %d, ai limit: %d\n", site.bo->name, site.bo->total_count(), site.bo->cnt_limit_by_aimode);
+	}
+	assert(site.bo->total_count() <= site.bo->cnt_limit_by_aimode);
+
 	// first we werify if site is working yet (can be unoccupied since the start)
 	if (!site.site->can_start_working()) {
 		site.unoccupied_till = game().get_gametime();
@@ -4502,6 +4521,7 @@
 	// And finally the 'core' of this function
 	// First deal with construction of new sites
 	if (purpose == PerfEvaluation::kForConstruction) {
+		assert(bo.total_count() <= bo.cnt_limit_by_aimode);
 		if (bo.forced_after < gametime && bo.total_count() == 0 && !has_substitution_building) {
 			if (!bo.is(BuildingAttribute::kBarracks)) {
 				bo.max_needed_preciousness = bo.max_preciousness;
@@ -4579,7 +4599,7 @@
 			}
 			bo.cnt_target = 3;
 			// adjusting/decreasing based on cnt_limit_by_aimode
-			bo.cnt_target = limit_cnt_target(bo.cnt_target, bo.cnt_limit_by_aimode);
+			bo.cnt_target = std::min(bo.cnt_target, bo.cnt_limit_by_aimode);
 
 			// for case the wood is not needed yet, to avoid inconsistency later on
 			bo.max_needed_preciousness = bo.max_preciousness;
@@ -4718,7 +4738,7 @@
 			bo.cnt_target = tmp_target;
 
 			// adjusting/decreasing based on cnt_limit_by_aimode
-			bo.cnt_target = limit_cnt_target(bo.cnt_target, bo.cnt_limit_by_aimode);
+			bo.cnt_target = std::min(bo.cnt_target, bo.cnt_limit_by_aimode);
 
 			assert(bo.cnt_target > 1 && bo.cnt_target < 1000);
 
@@ -5418,6 +5438,8 @@
 		}
 	}
 
+	log("Sorry, cannot find building with id %d", static_cast<int32_t>(di));
+	// I noticed that exception test is being lost so will will print it into log as well
 	throw wexception("Sorry, cannot find building with id %d", static_cast<int32_t>(di));
 }
 
@@ -6189,25 +6211,6 @@
 	}
 }
 
-int32_t DefaultAI::limit_cnt_target(const int32_t current_cnt_target, const int32_t ai_limit) {
-
-	if (ai_limit >= std::numeric_limits<int32_t>::max() - 1) {
-		// = ai limit is not set
-		return current_cnt_target;
-	}
-
-	int32_t new_target = current_cnt_target;
-
-	if (current_cnt_target > (ai_limit + 1) / 2) {
-		new_target = (ai_limit + 1) / 2;
-	}
-	assert(new_target * 2 >= ai_limit);
-	assert(new_target > 0);
-	assert(new_target <= ai_limit);
-
-	return new_target;
-}
-
 // 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-08-18 10:23:45 +0000
+++ src/ai/defaultai.h	2017-09-20 17:28:07 +0000
@@ -328,7 +328,6 @@
 	uint32_t military_last_dismantle_;
 	uint32_t military_last_build_;  // sometimes expansions just stops, this is time of last military
 	                                // building built
-	int32_t limit_cnt_target(int32_t, int32_t);
 	uint32_t time_of_last_construction_;
 	uint32_t next_mine_construction_due_;
 	uint16_t fishers_count_;

=== modified file 'src/ai/defaultai_warfare.cc'
--- src/ai/defaultai_warfare.cc	2017-08-20 08:34:02 +0000
+++ src/ai/defaultai_warfare.cc	2017-09-20 17:28:07 +0000
@@ -567,6 +567,9 @@
 	TrainingSite* ts = trainingsites.front().site;
 	TrainingSiteObserver& tso = trainingsites.front();
 
+	// Make sure we are not above ai type limit
+	assert(tso.bo->total_count() <=  tso.bo->cnt_limit_by_aimode);
+
 	const DescriptionIndex enhancement = ts->descr().enhancement();
 
 	if (enhancement != INVALID_INDEX && ts_without_trainers_ == 0 && mines_.size() > 3 &&
@@ -778,6 +781,7 @@
 	// Check next militarysite
 	bool changed = false;
 	MilitarySite* ms = militarysites.front().site;
+	MilitarySiteObserver& mso = militarysites.front();
 
 	// Don't do anything if last change took place lately
 	if (militarysites.front().last_change + 2 * 60 * 1000 > gametime) {
@@ -786,6 +790,9 @@
 		return false;
 	}
 
+	// Make sure we are not above ai type limit
+	assert(mso.bo->total_count() <=  mso.bo->cnt_limit_by_aimode);
+
 	FCoords f = game().map().get_fcoords(ms->get_position());
 
 	BuildableField bf(f);


Follow ups