← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~tiborb95/widelands/tiborb-ai into lp:widelands

 

Tibor Bamhor has proposed merging lp:~tiborb95/widelands/tiborb-ai into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~tiborb95/widelands/tiborb-ai/+merge/219947

conflicts should be resolved now
-- 
https://code.launchpad.net/~tiborb95/widelands/tiborb-ai/+merge/219947
Your team Widelands Developers is requested to review the proposed merge of lp:~tiborb95/widelands/tiborb-ai into lp:widelands.
=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h	2013-07-26 19:16:51 +0000
+++ src/ai/ai_help_structs.h	2014-05-17 19:43:16 +0000
@@ -77,6 +77,31 @@
 };
 
 
+struct FindNodeUnownedMineable {
+	bool accept (const Map &, const FCoords & fc) const {
+		// when looking for unowned terrain to acquire, we are actually
+		// only interested in fields where mines can be built.
+		// Fields should be completely unowned
+		//this is just modified copy of  FindNodeUnowned (:
+		return
+			(fc.field->nodecaps() & BUILDCAPS_MINE)
+			&&
+			(fc.field->get_owned_by() == 0);
+			 //|| player->is_hostile(*game.get_player(fc.field->get_owned_by())))
+			//&& (!onlyenemies || (fc.field->get_owned_by() != 0));
+	}
+
+	//int8_t playernum;
+	Player * player;
+	Game & game;
+	//bool onlyenemies;
+
+	FindNodeUnownedMineable(Player * p, Game & g)
+		: player(p), game(g)//, onlyenemies(oe)
+	{}
+};
+
+
 struct FindNodeWater {
 	bool accept(const Map & map, const FCoords & coord) const {
 		return
@@ -152,6 +177,7 @@
 	bool    enemy_nearby;
 
 	uint8_t unowned_land_nearby;
+	uint8_t unowned_minespots_nearby;
 
 	uint8_t trees_nearby;
 	uint8_t stones_nearby;

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2014-04-29 18:39:52 +0000
+++ src/ai/defaultai.cc	2014-05-17 19:43:16 +0000
@@ -46,7 +46,19 @@
 #include "profile/profile.h"
 #include "upcast.h"
 
+#include <valgrind/callgrind.h> //remove
+
 #define FIELD_UPDATE_INTERVAL 1000
+#define MILITARY_DEBUG 		false
+#define MIL_DISM_DEBUG 		false
+#define PRODUCTION_DEBUG 	false
+#define HINT_DEBUG 			false
+#define ENABLE_CALLGRIND 	false
+#define WINNER_DEBUG 		false
+#define NEW_BUILDING_DEBUG 	false
+#define STANDBY_DEBUG 		false
+#define MINES_DEBUG 		false
+#define UPGRADE_DEBUG 		false
 
 using namespace Widelands;
 
@@ -70,9 +82,14 @@
 	next_mine_check_due          (0),
 	next_militarysite_check_due  (0),
 	next_attack_consideration_due(300000),
+	next_helpersites_check_due   (180000),
 	inhibit_road_building        (0),
 	time_of_last_construction    (0),
-	numof_warehouses             (0)
+	numof_warehouses             (0),
+	new_buildings_stop	         (false),
+	unstationed_milit_buildings  (0),
+	military_under_constr        (0),
+	military_last_build          (0)
 {}
 
 DefaultAI::~DefaultAI()
@@ -99,11 +116,18 @@
  */
 void DefaultAI::think ()
 {
+	if (ENABLE_CALLGRIND and game().get_gametime()>20*60*1000) {CALLGRIND_START_INSTRUMENTATION;}
+	if (ENABLE_CALLGRIND and game().get_gametime()>22*60*1000) {CALLGRIND_STOP_INSTRUMENTATION;}
+
+	
 	if (tribe == nullptr)
 		late_initialization ();
 
 	const int32_t gametime = game().get_gametime();
 
+
+	//printf (" DefaultAI::think: %d\n",gametime);
+
 	if (m_buildable_changed) {
 		// update statistics about buildable fields
 		update_all_buildable_fields(gametime);
@@ -194,6 +218,7 @@
 		inhibit_road_building = gametime + 2500;
 		return;
 	}
+
 }
 
 /// called by Widelands game engine when an immovable changed
@@ -254,7 +279,7 @@
 		bo.cnt_built              = 0;
 		bo.cnt_under_construction = 0;
 		bo.production_hint        = -1;
-		bo.current_stats          = 100;
+		bo.current_stats          = 0;
 		bo.unoccupied             = false;
 
 		bo.is_basic               = false;
@@ -267,8 +292,11 @@
 		bo.recruitment            = bh.for_recruitment();
 		bo.space_consumer         = bh.is_space_consumer();
 
-		if (char const * const s = bh.get_renews_map_resource())
+		if (char const * const s = bh.get_renews_map_resource()) {
 			bo.production_hint = tribe->safe_ware_index(s);
+			if (HINT_DEBUG)
+				printf (" TDEBUG: %-20s get production hint: %d\n",bo.name,bo.production_hint);			
+			}
 
 		// Read all interesting data from ware producing buildings
 		if (typeid(bld) == typeid(ProductionSite_Descr)) {
@@ -481,11 +509,17 @@
 	// look if there is any unowned land nearby
 	Map & map = game().map();
 	FindNodeUnowned find_unowned(player, game());
+	FindNodeUnownedMineable find_unowned_minespots(player, game());
 	Player_Number const pn = player->player_number();
 
 	field.unowned_land_nearby =
 		map.find_fields(Area<FCoords>(field.coords, range), nullptr, find_unowned);
-
+	if (field.unowned_land_nearby>2) // 2 is 'reasonably low' number here
+		field.unowned_minespots_nearby =
+			map.find_fields(Area<FCoords>(field.coords, range+2), nullptr, find_unowned_minespots); //+2: a mine can mine raw materials from some range
+	else 
+		field.unowned_minespots_nearby = 0;
+		
 	// collect information about resources in the area
 	std::vector<ImmovableFound> immovables;
 
@@ -673,7 +707,7 @@
 }
 
 
-/// Updates the productionsites statistics needed for construction decision.
+/// Updates the production and MINE sites statistics needed for construction decision.
 void DefaultAI::update_productionsite_stats(int32_t const gametime) {
 	// Updating the stats every 20 seconds should be enough
 	next_stats_update_due = gametime + 20000;
@@ -684,7 +718,7 @@
 			buildings.at(i).current_stats = 0;
 		// If there are no buildings of that type set the current_stats to 100
 		else
-			buildings.at(i).current_stats = 100;
+			buildings.at(i).current_stats = 0;  //there was 100, this confuses algorithm
 		buildings.at(i).unoccupied = false;
 	}
 
@@ -705,6 +739,29 @@
 		productionsites.pop_front();
 	}
 
+	//for mines also
+	// Check all available productionsites
+	for (uint32_t i = 0; i < mines.size(); ++i) {
+		assert(mines.front().bo->cnt_built > 0);
+
+		// Add statistics value
+		mines.front().bo->current_stats +=
+			mines.front().site->get_statistics_percent();
+
+		// Check whether this building is completely occupied
+		mines.front().bo->unoccupied |=
+			!mines.front().site->can_start_working();
+
+		// Now reorder the buildings
+		mines.push_back(mines.front());
+		mines.pop_front();
+	}
+
+
+
+
+
+
 	// Scale statistics down
 	for (uint32_t i = 0; i < buildings.size(); ++i) {
 		if (buildings.at(i).cnt_built > 0)
@@ -712,35 +769,21 @@
 	}
 }
 
-
-/**
- * constructs the most needed building
- *
- * The need for a productionsite or a mine is calculated by the need for
- * their produced wares. The need for logproducers (like lumberjack's huts),
- * stoneproducers (like quarries) and resource refreshing buildings (like
- * forester's houses, gamekeeper's huts or fishbreeder houses) are calculated
- * separately as these buildings should have another priority (on one hand they
- * are important for the basic infrastructure, but there is no need for a lot
- * of these buildings.
- * Militarysites, warehouses and trainingsites have a different calculation,
- * that (should) depend on the initialisation type (Aggressive, Normal,
- * Defensive)
- */
+//constructs the most needed building
+//algorithm goes over all avaiable spots and all allowed buildings, 
+//scores every combination and one with highest and positive score
+//is built.
+//buildings are split into cathegories
 bool DefaultAI::construct_building (int32_t) // (int32_t gametime)
 {
-	// TODO make this smarter, easier and yet more effective
-
-	// TODO implement handling of seafaring
-
-	// Do not have too many constructionsites
-	uint32_t producers = mines.size() + productionsites.size();
-	bool onlymissing = false;
-	if (total_constructionsites >= (2 + (producers / 10)))
-		onlymissing = true;
-
+	
 	//  Just used for easy checking whether a mine or something else was built.
 	bool mine = false;
+	bool field_blocked=false;
+	int32_t spots=0;
+	uint32_t consumers_nearby_count=0;
+	int32_t bulgarian_constant=12;  //some building get preciousness as priority at that
+	// can be too low in many cases
 
 	std::vector<int32_t> spots_avail;
 	spots_avail.resize(4);
@@ -754,6 +797,8 @@
 		 ++i)
 		++spots_avail.at((*i)->coords.field->nodecaps() & BUILDCAPS_SIZEMASK);
 
+	
+	//calculating expand factor
 	int32_t expand_factor = 0;
 
 	if (type != DEFENSIVE) {
@@ -770,7 +815,7 @@
 			 static_cast<uint16_t>(4 + (productionsites.size() / 50)))
 			expand_factor += type;
 
-		uint32_t spots = spots_avail.at(BUILDCAPS_SMALL);
+		spots = spots_avail.at(BUILDCAPS_SMALL);
 		spots += spots_avail.at(BUILDCAPS_MEDIUM);
 		spots += spots_avail.at(BUILDCAPS_BIG);
 		if (type == AGGRESSIVE)
@@ -793,10 +838,46 @@
 			 16)
 			expand_factor *= 3;
 	}
-
-	// don't expand when we have unoccupied military buildings
-	//if (TODO) expand_factor = 0;
-
+	
+
+	//checking amount of free spots, if needed setting new building stop flag
+	new_buildings_stop=false;
+	if (militarysites.size()*2+20<	productionsites.size() or spots+mines.size()<8 or game().get_gametime()<900000){
+		new_buildings_stop=true;
+	}
+	if (NEW_BUILDING_DEBUG) printf (" TDEBUG new buildings stop: %s; milit: %3d vs prod: %3d buildings, spots: %4d\n",new_buildings_stop?"Y":"N",militarysites.size(),productionsites.size(),spots);	
+	
+	
+	bool new_military_buildings_stop;
+	bool near_enemy_b_buildings_stop;	
+	int32_t military_boost=1;
+	new_military_buildings_stop=false;
+	near_enemy_b_buildings_stop=false;
+	int32_t treshold=(militarysites.size()+productionsites.size())/100+1;
+	if (unstationed_milit_buildings + military_under_constr/3 > treshold ){
+		new_military_buildings_stop=true;
+		if (MILITARY_DEBUG) printf (" TDEBUG new military buildings stop ON, %d %d \n",unstationed_milit_buildings,military_under_constr);
+	} else
+		if (MILITARY_DEBUG) printf (" TDEBUG new military buildings stop OFF, %d %d\n",unstationed_milit_buildings,military_under_constr);
+	if (new_buildings_stop and new_military_buildings_stop and militarysites.size()*2 +30 >	productionsites.size()) {
+		if (MILITARY_DEBUG or NEW_BUILDING_DEBUG) printf (" TDEBUG Allowing production buildings because of lack of soldiers and military buildings stop\n");
+		new_buildings_stop=false;
+	}
+	if (unstationed_milit_buildings + military_under_constr/3 > 2*treshold ){
+		near_enemy_b_buildings_stop=true;
+		if (MILITARY_DEBUG) printf (" TDEBUG new military near-enemy buildings stop ON, %d %d \n",unstationed_milit_buildings,military_under_constr);
+	} 	
+	//here we deal with situation when for some time no new military building was built (and there are no unoccupied ones)
+	if ((unstationed_milit_buildings + military_under_constr)>0)
+		military_last_build=game().get_gametime();
+	if (military_last_build+180000<game().get_gametime()) {
+		if (MILITARY_DEBUG) printf (" TDEBUG: Boosting military building\n");
+		military_boost=100;
+	}
+		
+
+
+	
 	// Defensive AIs also attack sometimes (when they want to expand)
 	if (type == DEFENSIVE && expand_factor > 1)
 		if (next_attack_consideration_due <= game().get_gametime())
@@ -816,6 +897,12 @@
 		}
 		else ++i;
 
+	//these are 3 helping variables
+	bool output_is_needed=false;
+	int16_t max_preciousness=0; //preciousness of most precious output
+	int16_t max_needed_preciousness=0; //preciousness of most precious NEEDED output
+	int16_t stocklevel;
+	
 	// first scan all buildable fields for regular buildings
 	for
 		(std::list<BuildableField *>::iterator i = buildable_fields.begin();
@@ -827,218 +914,272 @@
 		if (!bf->reachable)
 			continue;
 
+		if (time(nullptr) % 5 ==0)
+				continue;   //add randomnes and ease AI
+
 		// Continue if field is blocked at the moment
+		field_blocked=false;
 		for
 			(std::list<BlockedField>::iterator j = blocked_fields.begin();
 			 j != blocked_fields.end();
 			 ++j)
 			if (j->coords == bf->coords)
-				continue;
+				field_blocked=true;
+				//continue;
+		if (field_blocked) continue;
 
 		assert(player);
 		int32_t const maxsize =
 			player->get_buildcaps(bf->coords) & BUILDCAPS_SIZEMASK;
 
-		// Check all buildable buildings
+		// For every field test all buildings
 		for (uint32_t j = 0; j < buildings.size(); ++j) {
 			BuildingObserver & bo = buildings.at(j);
 
 			if (!bo.buildable(*player))
 				continue;
 
+			if (time(nullptr) % 5 ==0)
+				continue;   //add randomnes and ease AI
+
 			if (bo.type == BuildingObserver::MINE)
 				continue;
+	
+			if (bo.unoccupied)
+				continue;
+			
+			if (not bo.type == BuildingObserver::MILITARYSITE and bo.cnt_under_construction >=2)
+				continue;
+	
+	
+			//so we are going to seriously evaluate this building on this field,
+			//first some base info
+			output_is_needed=false;
+			max_preciousness=0;
+			max_needed_preciousness=0;	
+			stocklevel=0; // amount of output wares stock
+			// Check if the produced wares are needed (if it is producing anything)
+			if (bo.outputs.size()>0) {
+				container_iterate(std::list<EconomyObserver *>, economies, l) {
+				// Don't check if the economy has no warehouse.
+				if ((*l.current)->economy.warehouses().empty())
+					continue;
+				for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
+					Ware_Index wt(static_cast<size_t>(bo.outputs.at(m)));
+					
+					//count stocklevel
+					if ((*l.current)->economy.stock_ware(wt)<static_cast<uint16_t>(stocklevel))
+						stocklevel+=(*l.current)->economy.stock_ware(wt);	
+					// verify whether the economy needs this ware
+					if ((*l.current)->economy.needs_ware(wt)) {
+						output_is_needed=true;
+						if (wares.at(bo.outputs.at(m)).preciousness>max_needed_preciousness)
+							max_needed_preciousness=wares.at(bo.outputs.at(m)).preciousness;
+							max_preciousness=wares.at(bo.outputs.at(m)).preciousness;
 
-			// If there are already a lot of constructionsites, only missing
-			// productionsites that produce build material are allowed
-			// (perhaps they are needed to finish the other constructionsites?)
-			if (onlymissing) {
-				if (!(bo.type == BuildingObserver::PRODUCTIONSITE))
-					continue;
-				if ((bo.total_count() > 0) || !bo.prod_build_material)
-					continue;
+						}
+					else {
+						if (wares.at(bo.outputs.at(m)).preciousness>max_preciousness)
+							max_preciousness=wares.at(bo.outputs.at(m)).preciousness;
+						}
+					}
+				}
 			}
-
+	
+			//if current field is not sufficient (by building size)
 			if (bo.desc->get_size() > maxsize)
 				continue;
 
-			int32_t prio = 0;
-
+			int32_t prio = 0; //score of a bulding on a field
+			
 			if (bo.type == BuildingObserver::PRODUCTIONSITE) {
-				// Don't build another building of this type, if there is already
-				// one that is unoccupied at the moment
-				if (bo.unoccupied)
-					continue;
-				if (bo.need_trees) {
-					// Priority of woodcutters depend on the number of near trees
-					prio += bf->trees_nearby * 3;
-					prio /= 3 * (1 + bf->producers_nearby.at(bo.outputs.at(0)));
-
-					// TODO improve this - it's still useless to place lumberjack huts randomly
-					/*if (prio <= 0) // no, sometimes we need wood without having a forest
-						continue;*/
-
-					// Check if the produced wares are needed
-					Ware_Index wt(static_cast<size_t>(bo.outputs.at(0)));
-					container_iterate(std::list<EconomyObserver *>, economies, l) {
-						// Don't check if the economy has no warehouse.
-						if ((*l.current)->economy.warehouses().empty())
-							continue;
-						if ((*l.current)->economy.needs_ware(wt))
-							prio += 1 + wares.at(bo.outputs.at(0)).preciousness;
-					}
-
-					if (bo.total_count() < 2) {
-						prio *= 6; // big bonus for the basics
-						if (bo.total_count() == 0)
-							prio *= 4; // even more for the absolute basics
-					}
-				} else if (bo.need_stones) {
-					// Priority of quarries depend on the number of near stones
-					prio += bf->stones_nearby * 3;
-					prio /= 3 * (1 + bf->producers_nearby.at(bo.outputs.at(0)));
-					if (bo.total_count() < 2) {
-						prio *= 6; // big bonus for the basics
-						if (bo.total_count() == 0)
-							prio *= 4; // even more for the absolute basics
-					}
-				} else if (bo.production_hint >= 0) {
+				if (bo.need_trees) { //LUMBERJACS
+					if (bo.total_count()+bo.cnt_under_construction+bo.unoccupied<=2)
+						prio=bulgarian_constant+200+bf->trees_nearby;
+					if (bo.cnt_under_construction<=2 and bf->trees_nearby > bf->producers_nearby.at(bo.outputs.at(0))*10)
+						prio=bf->trees_nearby/2;
+				}  else  if (bo.need_stones) {
+					if (bo.total_count()==0 and output_is_needed and bo.cnt_under_construction==0 and bf->stones_nearby>2)
+						prio=45+bf->stones_nearby;
+					else if (bf->producers_nearby.at(bo.outputs.at(0))<=1 and bf->stones_nearby >0 and bo.cnt_under_construction<1)
+						prio=bulgarian_constant+bf->stones_nearby/3;
+				} else if (bo.production_hint >= 0) {   //SUPPORTING PRODUCTIONS
+				
 					// production hint (f.e. associate forester with logs)
-
-					// Calculate the need for this building
-					int16_t inout = wares.at(bo.production_hint).consumers;
-					if
-						(tribe->safe_ware_index("log")
-						 ==
-						 bo.production_hint)
-						inout += total_constructionsites / 4;
-					inout -= wares.at(bo.production_hint).producers;
-					if (inout < 1)
-						inout = 1;
-					// the ware they're refreshing
-					Ware_Index wt(static_cast<size_t>(bo.production_hint));
-					container_iterate(std::list<EconomyObserver *>, economies, l) {
-						// Don't check if the economy has no warehouse.
-						if ((*l.current)->economy.warehouses().empty())
-							continue;
-						if ((*l.current)->economy.needs_ware(wt)) {
-							prio += wares.at(bo.production_hint).preciousness * inout * 2;
-							break;
-						}
-					}
-
-					// Do not build too many of these buildings, but still care
-					// to build at least two.
-					// And add bonus near buildings outputting production_hint ware.
-					prio += (5 * bf->producers_nearby.at(bo.production_hint)) / 2;
-					prio -= bo.total_count() * 2;
-					prio /= bo.total_count() + 1;
-					prio += (bf->producers_nearby.at(bo.production_hint) - 1) * 5;
-					if (bo.total_count() > 2)
-						prio -= bo.total_count();
-					else {
-						prio += wares.at(bo.production_hint).preciousness;
-						prio *= 3;
-					}
-					if (prio < 0)
-						continue;
-				} else if (bo.recruitment) {
-					// "recruitment centeres" like the donkey farm should be build up
-					// as soon as a basic infrastructure was completed.
-					// and of course the defaultAI should think of further
-					// constructions of that type later in game.
-					prio -= 12; // start calculation with an offset
-					prio += productionsites.size() + mines.size();
-					prio -= (bo.total_count()) * 40;
-					prio *= 2;
-
-					// take care about borders and enemies
-					prio = recalc_with_border_range(*bf, prio);
-				} else { // "normal" productionsites
-
-					// ToDo: prefer soldier producing things
-					// Ware_Index const soldier_index = tribe().worker_index("soldier");
-
-					if (bo.is_basic && (bo.total_count() == 0))
-						prio += 100; // for very important buildings
-
-					// Check if the produced wares are needed
-					container_iterate(std::list<EconomyObserver *>, economies, l) {
-						// Don't check if the economy has no warehouse.
-						if ((*l.current)->economy.warehouses().empty())
-							continue;
-						for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
-							Ware_Index wt(static_cast<size_t>(bo.outputs.at(m)));
-
-							// if we have too much of it (avoids mass storage)
-							if
-								((*l.current)->economy.stock_ware(wt) > 6 *
-								 (*l.current)->economy.ware_target_quantity(wt).permanent)
-								prio -= 20;
-
-							// if the economy needs this ware
-							if ((*l.current)->economy.needs_ware(wt)) {
-								prio += 1 + wares.at(bo.outputs.at(m)).preciousness;
-								if (bo.total_count() == 0)
-									// big bonus, this site might be elemental
-									prio += 3 * wares.at(bo.outputs.at(m)).preciousness;
-							}
-
-							// we can enhance this building. build more
-							// maybe the enhancement can produce needed ware
-							if (bo.desc->enhancements().size() > 0) {
-								// this code builds more metalworks
-								if (bo.total_count() == 0)
-									prio += 2;
-								if (bo.total_count() == 1)
-									prio += 8;
-							}
-						}
-						for (uint32_t m = 0; m < bo.inputs.size(); ++m) {
-							Ware_Index wt(static_cast<size_t>(bo.inputs.at(m)));
-
-							// if the economies don't need it: "waste" it
-							if (!(*l.current)->economy.needs_ware(wt)) {
-								if (bo.total_count() == 0 && bo.prod_build_material)
-									// big bonus, this site might be elemental
-									prio += 3 * wares.at(bo.inputs.at(m)).preciousness;
-							}
-						}
-					}
-
-					// If the produced wares are needed
-					if (prio > 0) {
-						int32_t inout_prio = 0;
-						for (size_t k = 0; k < bo.inputs.size(); ++k) {
-							inout_prio += bf->producers_nearby.at(bo.inputs.at(k));
-							inout_prio -= bf->consumers_nearby.at(bo.inputs.at(k)) / 2;
-						}
+					if (bo.need_water and  bf->water_nearby < 3) //probably some of them needs water
+							continue;
+					
+					//to eliminate to many fisher huts - this refers probably to underground water
+					//but this deserves better algorithm - to count fishes in water
+					//if (bo.need_water and  bf->producers_nearby.at(bo.outputs.at(0))>2)
+						//continue;
+												
+					if (bo.total_count() < 3){
+						prio=bulgarian_constant+2;
+						prio = recalc_with_border_range(*bf, prio);
+						}
+					else if (bo.cnt_under_construction==0 and bo.unoccupied==0 and
+						bo.total_count()*6< static_cast<int32_t>(productionsites.size() + militarysites.size())) {
+
+						//bool is_needed=false;
+						stocklevel=0;
+						Ware_Index wt(static_cast<size_t>(bo.production_hint));
+						container_iterate(std::list<EconomyObserver *>, economies, l) {
+							// Don't check if the economy has no warehouse.
+							if ((*l.current)->economy.warehouses().empty())
+								continue;
+							stocklevel+=(*l.current)->economy.stock_ware(wt);
+							}
+
+ 						if (HINT_DEBUG) printf (" TDEBUG: Considering new %-20s, prio: %2d, total so far: %2d, producers %2d., stocklevel: %2d\n"
+ 						,bo.name,prio,bo.total_count(),wares.at(bo.production_hint).producers,stocklevel);
+						
+						//we treat separately lumberjacts and other supporters
+						if (tribe->safe_ware_index("log") == bo.production_hint and stocklevel<50)
+							prio=bulgarian_constant+5+bf->producers_nearby.at(bo.production_hint)*3;
+						//number of supporting buldings should be less then producers of final material
+						else if (game().get_gametime()<1800000)
+							prio=-1;
+						else if (stocklevel<50 and (bo.cnt_under_construction +bo.unoccupied) ==0 and bo.total_count()<wares.at(bo.production_hint).producers)
+							prio=bulgarian_constant+5+bf->producers_nearby.at(bo.production_hint)*3;
+						else
+							prio=-1;
+
+
+ 
+ 						if (prio<=0)
+ 							continue;
+ 						
+ 						//then we consider borders and enemies nearby (if any)		
+						prio = recalc_with_border_range(*bf, prio);	
+ 					
+					}
+					
+				} else  if (bo.recruitment) {
+						//this will depend on number of mines and productionsites
+						if (static_cast<int32_t>((productionsites.size() + mines.size())/30)>bo.total_count() and bo.cnt_under_construction==0)
+							prio=4+bulgarian_constant;
+				} else { //finally normal productionsites
+
+						if (bo.production_hint>=0)
+							continue;
+							
+						if ((bo.cnt_under_construction + bo.unoccupied)>0)	
+							continue;
+												
+						//first eliminate buildings needing water if there is short supplies
+						if (bo.need_water and  bf->water_nearby < 3)
+							continue;
+						if (game().get_gametime() < 8*60*1000 ) {
+							if ((bo.is_basic or bo.prod_build_material) and bo.total_count()==0)
+								prio=150+max_preciousness;
+						} else if (game().get_gametime() < 15*60*1000) {
+							if ((bo.is_basic or bo.prod_build_material) and  bo.total_count()==0)
+								prio=max_preciousness+150+bulgarian_constant;
+							else if ((bo.is_basic or bo.prod_build_material) and  output_is_needed and bo.total_count()<=1)
+								prio=max_preciousness+80+bulgarian_constant;
+							//else if (bo.is_basic and  bo.total_count()<=0 and bo.cnt_under_construction==0 )
+								//prio=max_preciousness;
+							else if (! bo.is_basic and  bo.total_count()<=1 and  output_is_needed){
+								prio=max_preciousness+bulgarian_constant+50; //+50 to make sure at least one of such building is built
+								if (PRODUCTION_DEBUG) printf (" TDEBUG: %2d/%-15s in second period,  setting priority: %2d, on %3d %3d\n",bo.id,bo.name,prio,bf->coords.x,bf->coords.y);
+							}
+						} else if (new_buildings_stop and not ((bo.is_basic or bo.prod_build_material) and bo.cnt_built<2)){
+							continue; 
+						} else if (bo.inputs.size()==0){
+							if (output_is_needed and  stocklevel<50){
+								prio=max_preciousness+bulgarian_constant;
+								if (PRODUCTION_DEBUG) printf (" TDEBUG: %2d/%-15s without inputs: stats: %3d/%2d, setting priority: %2d, on %3d %3d\n",bo.id,bo.name,bo.current_stats,bo.total_count(),prio,bf->coords.x,bf->coords.y);
+							}
+						} else if (bo.inputs.size()>0) {
+							
+							//to have two buildings from everything (intended for upgradeable buildings)
+							// but I do not know how to identify such buildings
+							if ( bo.cnt_built==1 and game().get_gametime()>60*60*1000 and bo.desc->enhancements().size() > 0 and mines.size()>0){ 
+								prio=max_preciousness+bulgarian_constant;     
+								if (UPGRADE_DEBUG) printf (" TDEBUG: proposing %-16s at %3dx%3d as second building of a type, score: %2d\n",bo.name,bf->coords.x,bf->coords.y,prio);
+								}
+							
+							//if output is needed and there are no idle buildings
+							if (output_is_needed ){
+								//if (bo.cnt_built>0)
+								//printf (" TDEBUG: building: %d, built: %d, utilization: %d, in construction: %d\n",bo.id,bo.cnt_built,bo.current_stats,bo.cnt_under_construction);
+								if (bo.cnt_built>0 and bo.current_stats>90){
+									prio=max_preciousness+bulgarian_constant+30;
+									if (PRODUCTION_DEBUG) printf (" TDEBUG: %2d/%-15s with inputs: stats: %3d>90, setting priority: %2d, on %3d %3d\n",bo.id,bo.name,bo.current_stats,prio,bf->coords.x,bf->coords.y);
+								}
+								else if (bo.cnt_built>0 and bo.current_stats>60){
+									prio=max_preciousness+bulgarian_constant;
+									if (PRODUCTION_DEBUG) printf (" TDEBUG: %2d/%-15s with inputs: stats: %3d>60, setting priority: %2d, on %3d %3d\n",bo.id,bo.name,bo.current_stats,prio,bf->coords.x,bf->coords.y);
+								}
+								else if (bo.cnt_built==0){
+									prio=max_preciousness+80+bulgarian_constant;	
+									if (PRODUCTION_DEBUG) printf (" TDEBUG: %2d/%-15s as first building of the type, setting priority: %2d, on %3d %3d\n",bo.id,bo.name,prio,bf->coords.x,bf->coords.y);
+								} 
+							}
+						} 
+						
+						if (prio<=0 )
+							continue;
+						
+						//then we consider borders and enemies nearby (if any)	
+						//printf ("  TDEBUG: 	%s: prio before: %d, unowned nearby %d,coords: %3d x %3d,\n",
+						//bo.name,prio,bf->unowned_land_nearby,bf->coords.x,bf->coords.y);
+						prio = recalc_with_border_range(*bf, prio);	
+						//printf ("  TDEBUG: 	 prio after: %d\n",prio);
+						
+						
+						//+1 if any consumers are nearby
+						consumers_nearby_count=0;
 						for (size_t k = 0; k < bo.outputs.size(); ++k)
-							inout_prio += bf->consumers_nearby.at(bo.outputs.at(k));
-						prio += 2 * inout_prio;
-						prio = calculate_need_for_ps(bo, prio);
-					} else
-						continue;
-
-					// take care about borders and enemies
-					prio = recalc_with_border_range(*bf, prio);
-
-					// do not construct more than one building,
-					// if supply line is already broken.
-					if (!check_supply(bo) && bo.total_count() > 0)
-						prio -= 12;
-
-				}
-			} else if (bo.type == BuildingObserver::MILITARYSITE) {
+							consumers_nearby_count += bf->consumers_nearby.at(bo.outputs.at(k));
+						if (consumers_nearby_count>0)
+							prio += 1;
+							
+						// do not construct more than one building,
+						// if supply line is already broken.
+						// is this needed?
+						//if (!check_supply(bo) && bo.total_count() > 0)
+						//prio -= 12;
+					}
+				}  //production sites done
+				
+			else if (bo.type == BuildingObserver::MILITARYSITE) {
+				
+				if (MILITARY_DEBUG) printf (" Considering field %3dx%3d: unowned_land: %3d, near minespots: %3d, enemy nearby:% 2d, cur stat: %2d/%2d/%2d, stops:%s %s\n"
+				,bf->coords.x,bf->coords.y,bf->unowned_land_nearby,bf->unowned_minespots_nearby,bf->enemy_nearby,bo.cnt_built,unstationed_milit_buildings,bo.cnt_under_construction,
+				new_military_buildings_stop?"Y":"N",near_enemy_b_buildings_stop?"Y":"N");
+				
+				if (military_boost>1 and MILITARY_DEBUG)
+					printf (" TDEBUG: boosting: unowned land %d \n",bf->unowned_land_nearby);
+					
+				if (new_military_buildings_stop and not bf->enemy_nearby)
+					continue;
+
+				if (near_enemy_b_buildings_stop and bf->enemy_nearby) 
+					continue;
+				if (bo.desc->get_size()==3 and game().get_gametime() < 15*60*1000) //do not built fortresses in first half of hour of game
+					continue;
+				
 				if (!bf->unowned_land_nearby)
 					continue;
-				prio  = bf->unowned_land_nearby * (1 + type);
+				
+				//printf (" TDEBUG field: %3dx%3d: unowned land: %3d, mine spots: %3d\n",bf->coords.x,bf->coords.y,bf->unowned_land_nearby,bf->unowned_minespots_nearby);
+				prio  = (bf->unowned_land_nearby + 10 * bf->unowned_minespots_nearby) * (1 + type);
+				if (military_boost>1 and MILITARY_DEBUG)
+					printf (" TDEBUG: Original priority before boosting: %d \n",prio);
+				prio *= military_boost;
 				prio -= bf->military_influence * (5 - type);
 				// set to at least 1
 				prio  = prio > 0 ? prio : 1;
 				prio *= expand_factor;
 				prio /= 2;
 
+				//adding weight for stones, but only affecting small buildings (? good idea ?)
+				//printf (" TDEBUG stones nearby: %3d\n",bf->stones_nearby);
+				if (bo.desc->get_size()==1)
+					prio+=bf->stones_nearby/5;
+
 				if (bf->enemy_nearby)
 					prio *= 2;
 				else
@@ -1048,77 +1189,52 @@
 					prio /= 5;
 
 				prio -= militarysites.size() - productionsites.size() / (3 - type);
-
-			} else if (bo.type == BuildingObserver::WAREHOUSE) {
+				if (military_boost>1 and MILITARY_DEBUG)
+					printf (" TDEBUG: - Final priority: %d \n",prio);				
+
+
+									
+			}	else if (bo.type == BuildingObserver::WAREHOUSE) {
 				//  Build one warehouse for ~every 35 productionsites and mines.
 				//  Militarysites are slightly important as well, to have a bigger
 				//  chance for a warehouses (containing waiting soldiers or wares
 				//  needed for soldier training) near the frontier.
-				prio += productionsites.size() + mines.size();
-				prio += militarysites.size() / 3;
-				prio -= (bo.cnt_under_construction + numof_warehouses) * 35;
-				prio *= 2;
+				if ((static_cast<int32_t>(productionsites.size() + mines.size()))/35 > static_cast<int32_t>(numof_warehouses) and bo.cnt_under_construction==0)
+					prio = 13;
 
 				// take care about borders and enemies
 				prio = recalc_with_border_range(*bf, prio);
-
 			} else if (bo.type == BuildingObserver::TRAININGSITE) {
-				// Start building trainingsites when there are already more than 50
-				// other buildings. That should be enough for a working economy.
-				//  On the other hand only build more trainingsites of the same
-				//  type if the economy is really big.
-				prio += productionsites.size() + militarysites.size();
-				prio += mines.size();
-				prio += type * 10; // +0 / +10 / +20 for DEFF/NORM/AGGR
-				prio  = prio / (bo.total_count() + 1);
-				prio -= (bo.total_count() + 1) * 70;
-
+				// build after 20 production sites and then after each 50 production site
+				if (static_cast<int32_t>((productionsites.size()+30)/50)>bo.total_count() and bo.cnt_under_construction==0)
+					prio=4;
 				// take care about borders and enemies
-				prio = recalc_with_border_range(*bf, prio);
-			}
-
-			// avoid to have too many construction sites
-			// but still enable the player to build up basic productionsites
-			if
-				(bo.type != BuildingObserver::PRODUCTIONSITE ||
-				 !bo.is_basic || bo.total_count() > 0)
-				prio /=
-					1 + bo.cnt_under_construction * (bo.cnt_under_construction + 1);
-
-			// add big penalty if water is needed, but is not near
-			if (bo.need_water) {
-				if (bf->water_nearby < 3)
-					continue;
-				int effect = bf->water_nearby - 8;
-				prio +=
-					effect > 0 ?
-					static_cast<int>(sqrt(static_cast<double>(effect))) : effect;
-				// if same producers are nearby, then give some penalty
-				for (size_t k = 0; k < bo.outputs.size(); ++k)
-					if (bf->producers_nearby.at(bo.outputs.at(k)) > 0)
-						prio -= 3;
-			}
-
+				prio = recalc_with_border_range(*bf, prio);				
+			}	
+				
 			// think of space consuming buildings nearby like farms or vineyards
-			prio /= 1 + bf->space_consumers_nearby;
-
+			prio -=  bf->space_consumers_nearby*10;				
+				
 			// Stop here, if priority is 0 or less.
 			if (prio <= 0)
 				continue;
 
 			// Prefer road side fields
 			prio += bf->preferred ?  1 : 0;
-
+				
 			// don't waste good land for small huts
-			prio -= (maxsize - bo.desc->get_size()) * 3;
+			prio -= (maxsize - bo.desc->get_size()) * 5;
 			if (prio > proposed_priority) {
 				proposed_building = bo.id;
 				proposed_priority = prio;
 				proposed_coords   = bf->coords;
-			}
-		}
-	}
-
+			}				
+				
+		}	//ending loop over buildings
+	}  //ending loop over fields
+
+
+	//if (MINES_DEBUG ) printf(" TDEBUG: a\n");
 	// then try all mines - as soon as basic economy is build up.
 	for
 		(uint32_t i = 0; i < buildings.size() && productionsites.size() > 8; ++i)
@@ -1127,23 +1243,64 @@
 
 		if (!bo.buildable(*player) || bo.type != BuildingObserver::MINE)
 			continue;
+		
+		if (game().get_gametime() < 15*60*1000)
+			continue;
+			
+		if (game().get_gametime() < 30*60*1000 and (bo.total_count() + bo.unoccupied + bo.cnt_under_construction)>0)
+			continue;	
+		//if (MINES_DEBUG ) printf(" TDEBUG: c\n");
 
 		// Don't build another building of this type, if there is already
 		// one that is unoccupied at the moment
-		if (bo.unoccupied)
-			continue;
-
-
-		// Only have 2 mines of a type under construction
-		if (bo.cnt_under_construction > 2)
-			continue;
-
-		if (onlymissing)
-			// Do not build mines twice, as long as other buildings might be more needed
-			if (bo.total_count() > 0)
-				continue;
-
-
+		// or under construction
+		if ((bo.cnt_under_construction + bo.unoccupied )> 0)
+			continue;
+
+		/* - uninteresting if a mine ware is needed - we exploit the raw material
+		// Check if the produced wares are needed
+		bool needed = false;
+		container_iterate(std::list<EconomyObserver *>, economies, l) {
+			// Don't check if the economy has no warehouse.
+			if ((*l.current)->economy.warehouses().empty())
+				continue;
+			for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
+				Ware_Index wt(static_cast<size_t>(bo.outputs.at(m)));
+				if ((*l.current)->economy.needs_ware(wt)) {
+					needed = true;
+					break;
+				}
+			}
+			if (needed)
+				break;
+		}
+
+		// Only try to build mines that produce needed wares.
+		if (!needed)
+			continue;
+		*/
+	
+		//calculating actual amount of mined raw materials
+		stocklevel=0;
+		container_iterate(std::list<EconomyObserver *>, economies, l) {
+			// Don't check if the economy has no warehouse.
+			if ((*l.current)->economy.warehouses().empty())
+				continue;
+			for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
+				Ware_Index wt(static_cast<size_t>(bo.outputs.at(m)));
+				//count stocklevel
+				stocklevel+=(*l.current)->economy.stock_ware(wt);
+				}
+			}
+					
+			
+		if (MINES_DEBUG ) printf (" TDEBUG: considering %12s/%1d: stat: %3d(50), stocklevel: %2d(50), count %2d / %2d / %2d\n",bo.name,bo.mines,bo.current_stats,stocklevel,bo.total_count(),bo.unoccupied,bo.cnt_under_construction);
+
+		// Only try to build mines that produce needed wares.
+		if (((bo.cnt_built-bo.unoccupied)>0 and bo.current_stats<50) or stocklevel>50)
+			continue;
+			
+		//iterating over fields
 		for
 			(std::list<MineableField *>::iterator j = mineable_fields.begin();
 			 j != mineable_fields.end();
@@ -1154,7 +1311,7 @@
 			if ((*j)->coords.field->get_resources() != bo.mines)
 				continue;
 			else
-				prio += (*j)->coords.field->get_resources_amount() * 4 / 3;
+				prio += (*j)->coords.field->get_resources_amount() * 4 / 3;		
 
 			// Only build mines on locations where some material can be mined
 			if (prio < 2)
@@ -1172,59 +1329,38 @@
 				}
 			if (blocked) continue;
 
-			// Check if current economy can supply enough food for production.
-			for (uint32_t k = 0; k < bo.inputs.size(); ++k) {
-				prio += wares.at(bo.inputs.at(k)).producers;
-				prio -= wares.at(bo.inputs.at(k)).consumers / 2;
-			}
-
-			// our wares are needed? gimme more
-			uint32_t ioprio = 0;
-			for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
-				ioprio += 5 * wares.at(bo.outputs.at(m)).preciousness;
-			}
-
-			// tribes that have enhanceable mines should build more mines
-			prio *= 1 + 100 / bo.mines_percent;
-
-			// No plus for mines with multiple output
-			ioprio /= bo.outputs.size();
-			prio += ioprio;
-
-			prio -= 3 * (*j)->mines_nearby * (*j)->mines_nearby;
-			//prio /= 1 + bo.cnt_built * 2;
-
-			// multiply with current statistics of all other buildings of this
-			// type to avoid constructing buildings where already some are running
-			// on low resources.
-			prio *= 5 + bo.current_stats;
-			prio /= 100;
-
-			if (onlymissing) // mines aren't *that* important
-				prio /= 3;
+			if (MINES_DEBUG) printf ("  TDEBUG: priority before near mines consideration: %3d, at  %3d x %3d\n",prio,(*j)->coords.x,(*j)->coords.y);
+	
+			//if mines nearby - this check mines in too big radius - no sense to consider this
+			//prio -= 4 * (*j)->mines_nearby ;
+			//if (MINES_DEBUG) printf ("  TDEBUG: priority after near mines consideration: %3d; value: %2d\n",prio,(*j)->mines_nearby);		
 			if (prio > proposed_priority) {
 
 				proposed_building = bo.id;
 				proposed_priority = prio;
 				proposed_coords = (*j)->coords;
 				mine = true;
+				if (MINES_DEBUG) printf ("   TDEBUG: using %-12s as a candidate\n",bo.name);	
 			}
-		}
+		} //ending interation over fields
+	} //ending iteration over buildings
+
+	//if there is no winner:
+	if (proposed_building == INVALID_INDEX) {
+		if (WINNER_DEBUG) printf (" TDEBUG:  no building picked up, best priority: %3d, building: %2d\n",proposed_priority,proposed_building);
+		return false;
 	}
 
-	if (proposed_building == INVALID_INDEX)
-		return false;
-
-	// do not have too many construction sites
-	if
-		(proposed_priority < static_cast<int32_t>(total_constructionsites)
-		 and not
-		 onlymissing) // only return here, if we do NOT try to build a missing bld
-		return false;
-
 	// send the command to construct a new building
 	game().send_player_build
 		(player_number(), proposed_coords, proposed_building);
+	BlockedField blocked
+		(game().map().get_fcoords(proposed_coords), game().get_gametime() + 120000);  //two minutes
+		blocked_fields.push_back(blocked);
+
+	if (WINNER_DEBUG) printf (" TDEBUG:  winning priority %4d, building %2d, coords: %3d x %3d, M: %s\n",
+	proposed_priority,proposed_building,proposed_coords.x,proposed_coords.y,mine?"Y":"N");
+	
 
 	// set the type of update that is needed
 	if (mine)
@@ -1235,6 +1371,7 @@
 	return true;
 }
 
+
 /**
  * This function searches for places where a new road is needed to connect two
  * economies. It then sends the request to build the road.
@@ -1585,6 +1722,12 @@
 	// Get link to productionsite that should be checked
 	ProductionSiteObserver & site = productionsites.front();
 	bool changed = false;
+	int32_t stocklevel;
+	//bool ware_is_needed;
+
+	// Reorder and set new values; - better now because there are multiple returns in the function
+	productionsites.push_back(productionsites.front());
+	productionsites.pop_front();
 
 	// Get max radius of recursive workarea
 	Workarea_Info::size_type radius = 0;
@@ -1596,6 +1739,8 @@
 
 	Map & map = game().map();
 
+	
+
 	// Lumberjack / Woodcutter handling
 	if
 		(site.bo->need_trees
@@ -1604,19 +1749,20 @@
 		 	(Area<FCoords>(map.get_fcoords(site.site->get_position()), radius),
 		 	 nullptr,
 		 	 FindImmovableAttribute(Map_Object_Descr::get_attribute_id("tree")))
-		 ==
-		 0)
+		 < 3)
 	{
-		if (site.site->get_statistics_percent() == 0) {
-			// Do not destruct the last lumberjack - perhaps some small trees are
-			// near, a forester will plant some trees or some new trees will seed
-			// in reach. Computer players can easily run out of wood if this check
-			// is not done.
-			if (site.bo->cnt_built == 1)
-				return false;
+		
+		// Do not destruct the last lumberjack - perhaps some small trees are
+		// near, a forester will plant some trees or some new trees will seed
+		// in reach. Computer players can easily run out of wood if this check
+		// is not done.
+		if (site.bo->cnt_built <= 5)
+			return false;
+		if (site.site->get_statistics_percent() < 10 ) {
 			// destruct the building and it's flag (via flag destruction)
 			// the destruction of the flag avoids that defaultAI will have too many
 			// unused roads - if needed the road will be rebuild directly.
+			//printf (" TDEBUG: dismantling lumberjacks hut\n");
 			flags_to_be_removed.push_back(site.site->base_flag().get_position());
 			game().send_player_dismantle(*site.site);
 			return true;
@@ -1642,7 +1788,7 @@
 		return true;
 	}
 
-	// All other productionsites without input...
+	// All other productionsites without input and not supporting ones (rangers...)...
 	if
 		(site.bo->inputs.empty() // does not consume anything
 		 and
@@ -1680,6 +1826,39 @@
 			site.statszero = 0; // reset zero counter
 	}
 
+	//supporting productionsites (rangers)
+	//stop/start them based on stock avaiable
+	if (site.bo->production_hint >=0){
+		//if (STANDBY_DEBUG) printf ("  TDEBUG: check_productionsites(): testing building %s\n",site.bo->name);
+		stocklevel=0;
+		
+		container_iterate(std::list<EconomyObserver *>, economies, l) {
+			// Don't check if the economy has no warehouse.
+			if ((*l.current)->economy.warehouses().empty())
+				continue;
+			Ware_Index wt(static_cast<size_t>(site.bo->production_hint));
+			stocklevel+=(*l.current)->economy.stock_ware(wt);
+			//ware_is_needed =site.site->economy().needs_ware(wt);
+		}
+					
+		if (STANDBY_DEBUG) printf ("  TDEBUG: standby review: %-16s(%dx):stock level: %3d, status: %s\n",site.bo->name,site.bo->cnt_built,stocklevel,site.site->is_stopped()?"stopped":"running");
+		if (stocklevel>220 and site.bo->cnt_built>3){
+			if (STANDBY_DEBUG) printf ("   * dismantling the building\n");
+			flags_to_be_removed.push_back(site.site->base_flag().get_position());
+			game().send_player_dismantle(*site.site);
+			return true;}
+		if (stocklevel>190 and not site.site->is_stopped()){
+			if (STANDBY_DEBUG) printf ("   * stopping building\n");
+			game().send_player_start_stop_building (*site.site);}
+		if (stocklevel<150 and site.site->is_stopped()){
+			if (STANDBY_DEBUG) printf ("   * starting building\n");
+			game().send_player_start_stop_building (*site.site);}		
+					
+		
+	}
+	
+	
+
 	// Do not have too many constructionsites
 	uint32_t producers = mines.size() + productionsites.size();
 	if (total_constructionsites >= (5 + (producers / 10)))
@@ -1705,6 +1884,17 @@
 			if (!site.site->has_workers(*x.current, game()))
 				continue;
 
+			//forcing first upgrade 
+			if (en_bo.cnt_under_construction==0 and en_bo.cnt_built==0 and en_bo.unoccupied==0 and 
+			    (site.bo->cnt_built - site.bo->unoccupied)>1 and  (game().get_gametime()-site.builttime)>45*60*1000 and  mines.size()>0){
+			    if (UPGRADE_DEBUG) printf (" upgrading %12s at %3d x %3d: age %d min.\n",site.bo->name,site.site->get_position().x,site.site->get_position().y,(game().get_gametime()-site.builttime)/60000);
+			    game().send_player_enhance_building(*site.site, (*x.current));
+				return true;
+			}
+			    
+			
+			
+			
 			int32_t prio = 0; // priority for enhancement
 
 			// Find new outputs of enhanced building
@@ -1751,9 +1941,9 @@
 		changed = true;
 	}
 
-	// Reorder and set new values;
-	productionsites.push_back(productionsites.front());
-	productionsites.pop_front();
+	//// Reorder and set new values;
+	//productionsites.push_back(productionsites.front());
+	//productionsites.pop_front();
 	return changed;
 }
 
@@ -1774,6 +1964,10 @@
 	Map & map = game().map();
 	Field * field = map.get_fcoords(site.site->get_position()).field;
 
+	// Reorder and set new values; - due to returns within the function
+	mines.push_back(mines.front());
+	mines.pop_front();
+
 	// Don't try to enhance as long as stats are not down to 0% - it is possible,
 	// that some neighbour fields still have resources
 	if (site.site->get_statistics_percent() > 0)
@@ -1822,12 +2016,13 @@
 		changed = true;
 	}
 
-	// Reorder and set new values;
-	mines.push_back(mines.front());
-	mines.pop_front();
+	//// Reorder and set new values;
+	//mines.push_back(mines.front());
+	//mines.pop_front();
 	return changed;
 }
 
+	
 /**
  * Updates the first military building in list and reenques it at the end of
  * the list afterwards. If a militarysite is in secure area but holds more than
@@ -1841,20 +2036,38 @@
 	if (next_militarysite_check_due > gametime)
 		return false;
 
+	//even if there are no finished & attended military sites, probably there are ones just in construction
+	unstationed_milit_buildings=0;
+	for (std::list<MilitarySiteObserver >::iterator it = militarysites.begin(); it != militarysites.end(); ++it)
+		if (it->site->stationedSoldiers().size()==0)
+			unstationed_milit_buildings+=1;
+
+	//count militarysites in construction	
+	military_under_constr=0;
+	for (uint32_t j = 0; j < buildings.size(); ++j) {
+		BuildingObserver & bo = buildings.at(j);
+		if (bo.type == BuildingObserver::MILITARYSITE)
+			military_under_constr+=bo.cnt_under_construction;
+		}
+
 	// Only useable, if defaultAI owns at least one militarysite
 	if (militarysites.empty())
 		return false;
-
 	// Check next militarysite
 	bool changed = false;
 	Map & map = game().map();
+
 	MilitarySite * ms = militarysites.front().site;
 	uint32_t const vision = ms->vision_range();
 	FCoords f = map.get_fcoords(ms->get_position());
 
+	
+
 	// look if there is any enemy land nearby
 	FindNodeUnowned find_unowned(player, game(), true);
-
+	
+	//printf (" TDEBUG: check_militarysites()\n");
+	
 	if (map.find_fields(Area<FCoords>(f, vision), nullptr, find_unowned) == 0) {
 		// If no enemy in sight - decrease the number of stationed soldiers
 		// as long as it is > 1 - BUT take care that there is a warehouse in the
@@ -1877,11 +2090,30 @@
 				BuildableField bf(f);
 				update_buildable_field(bf, vision, true);
 
+				if (MIL_DISM_DEBUG) printf (" TDEBUG: considering milit. build. dismantle at %3dx%3d: Unowned land: %3d, enemy: %1d, mil. influence: %4d,  soldiers: %d,%d, ratio:%5d, unstationed: %d\n",
+				f.x,f.y,bf.unowned_land_nearby,bf.enemy_nearby,bf.military_influence,j,ms->maxSoldierCapacity(),bf.military_influence-ms->maxSoldierCapacity()*100,unstationed_milit_buildings);
+
+				//regardless of following check, if there is too big military influence
+				//and no enemy in sight, destroying the building
+				if ((unstationed_milit_buildings>5 and bf.military_influence-static_cast<int32_t>(ms->maxSoldierCapacity()*100)>700 and not bf.enemy_nearby) or
+				(bf.military_influence-static_cast<int32_t>(ms->maxSoldierCapacity()*100)>1500 and not bf.enemy_nearby)) {
+						if (MIL_DISM_DEBUG) printf ("  * dismantling the building\n");
+							if (ms->get_playercaps() & Widelands::Building::PCap_Dismantle) {
+								flags_to_be_removed.push_back(ms->base_flag().get_position());
+								game().send_player_dismantle(*ms);
+							} else {
+								game().send_player_bulldoze(*ms);
+							}
+							return true;	//do not go on with building, we need to refresh statistics
+						}
+
 				// watch out if there is any unowned land in vision range. If there
 				// is none, there must be another building nearer to the frontier.
-				if (bf.unowned_land_nearby == 0) {
+				else if (bf.unowned_land_nearby == 0) {
 					// bigger buildings are only checked after all smaller
 					// ones are at least one time checked.
+					
+					
 					if (militarysites.front().checks == 0) {
 						// If the military influence of other near buildings is higher
 						// than the own doubled max SoldierCapacity destruct the
@@ -1889,7 +2121,8 @@
 						// the destruction of the flag avoids that defaultAI will have
 						// too many unused roads - if needed the road will be rebuild
 						// directly.
-						if (static_cast<int32_t>(ms->maxSoldierCapacity() * 4) < bf.military_influence) {
+						if (static_cast<int32_t>(ms->maxSoldierCapacity() * 4) < bf.military_influence ) {
+						//if (bf.military_influence>1000) { // HERE CHANGED
 							if (ms->get_playercaps() & Widelands::Building::PCap_Dismantle) {
 								flags_to_be_removed.push_back(ms->base_flag().get_position());
 								game().send_player_dismantle(*ms);
@@ -1971,12 +2204,14 @@
 {
 	// Prefer building space in the inner land.
 	prio /= (1 + (bf.unowned_land_nearby / 4));
+	if (bf.unowned_land_nearby>15)
+		prio-=(bf.unowned_land_nearby-15);
 
 	// Especially places near the frontier to the enemies are unlikely
 	//  NOTE take care about the type of computer player. The more
 	//  NOTE aggressive a computer player is, the more important is
 	//  NOTE this check. So we add \var type as bonus.
-	if (bf.enemy_nearby)
+	if (bf.enemy_nearby and prio>0)
 		prio /= (3 + type);
 
 	return prio;

=== modified file 'src/ai/defaultai.h'
--- src/ai/defaultai.h	2014-02-22 18:04:02 +0000
+++ src/ai/defaultai.h	2014-05-17 19:43:16 +0000
@@ -134,6 +134,7 @@
 	bool check_productionsites (int32_t);
 	bool check_mines           (int32_t);
 	bool check_militarysites   (int32_t);
+	void check_helpersites	   (int32_t);
 
 	int32_t recalc_with_border_range(const BuildableField &, int32_t);
 	int32_t calculate_need_for_ps(BuildingObserver &, int32_t);
@@ -188,10 +189,17 @@
 	int32_t next_mine_check_due;
 	int32_t next_militarysite_check_due;
 	int32_t next_attack_consideration_due;
+	int32_t next_helpersites_check_due;
 	int32_t inhibit_road_building;
 	int32_t time_of_last_construction;
+	int32_t next_wood_cutting_check_due;	
 
 	uint16_t numof_warehouses;
+	
+	bool new_buildings_stop;
+	uint16_t unstationed_milit_buildings; //counts empty military buildings (ones where no soldier is belogning to)
+	uint16_t military_under_constr;
+	int32_t military_last_build;  //sometimes expansions just stops, this is time of last military building build
 };
 
 #endif