← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~hono/widelands/carli2-ai-improvements into lp:widelands

 

Mark Scott has proposed merging lp:~hono/widelands/carli2-ai-improvements into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~hono/widelands/carli2-ai-improvements/+merge/142009

(Branch author is carli2: https://code.launchpad.net/~s3734770 - having bzr problems)

 - Add "demand" to wares
 - missing input wares count as demand
 - missing soldiers add demand to weapons
 - a depth pass filter is applied to demand in order to get stable values
 - enhancements are now priorized correctly

gains:
 - all three tribes manage to recruit soldiers
 - the AI is able to finish its enemy after 90 minutes
 - great improvement for AIs economy
-- 
https://code.launchpad.net/~hono/widelands/carli2-ai-improvements/+merge/142009
Your team Widelands Developers is requested to review the proposed merge of lp:~hono/widelands/carli2-ai-improvements into lp:widelands.
=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h	2012-09-21 21:36:07 +0000
+++ src/ai/ai_help_structs.h	2013-01-05 13:44:24 +0000
@@ -274,6 +274,7 @@
 	uint8_t producers;
 	uint8_t consumers;
 	uint8_t preciousness;
+	float demand;
 };
 
 #endif

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2012-09-21 21:36:07 +0000
+++ src/ai/defaultai.cc	2013-01-05 13:44:24 +0000
@@ -30,6 +30,7 @@
 #include "economy/economy.h"
 #include "economy/flag.h"
 #include "economy/road.h"
+#include "economy/wares_queue.h"
 #include "logic/findimmovable.h"
 #include "logic/findnode.h"
 #include "log.h"
@@ -75,7 +76,8 @@
 	next_attack_consideration_due(300000),
 	inhibit_road_building        (0),
 	time_of_last_construction    (0),
-	numof_warehouses             (0)
+	numof_warehouses             (0),
+	military_demand              (0.0)
 {}
 
 DefaultAI::~DefaultAI()
@@ -136,6 +138,9 @@
 	// handled by the AI itself.
 	update_all_not_buildable_fields();
 
+	// now update the statistics of what we need (wares and military power)
+	update_demand();
+
 	// IF defaultAI is AGGRESSIVE - we definitely should consider to attack as
 	// often as possible.
 	if (type == AGGRESSIVE)
@@ -234,6 +239,7 @@
 		wares.at(i).producers    = 0;
 		wares.at(i).consumers    = 0;
 		wares.at(i).preciousness = tribe->get_ware_descr(i)->preciousness();
+		wares.at(i).demand       = 0;
 	}
 
 	// collect information about the different buildings our tribe can construct
@@ -472,6 +478,85 @@
 	}
 }
 
+/***
+ * updates all needs of the economy
+ */
+void DefaultAI::update_demand()
+{
+   // military buildings need soldiers: count them!
+   for
+      (std::list<MilitarySiteObserver>::iterator i =
+      militarysites.begin();
+      i != militarysites.end();
+      ++i)
+      {
+         military_demand += i->site->missingSoldiers();
+      }
+   military_demand += 1; // some extra points such that we always get new soldiers
+   military_demand *= 0.99;
+   military_demand = std::max(military_demand, (type + 2) * (float) 2000.0); // then limit it to some degree.
+   // enable logging for debug purpose
+   //printf("mil = %f\n", military_demand);
+
+   // now we know how much military we need, so we
+   // need the wares to build the soldiers
+	Ware_Index const nr_workers = tribe->get_nrworkers();
+	for (Ware_Index i = Ware_Index::First(); i < nr_workers; ++i) {
+		// Find all build costs for soldiers
+		// is it a soldier?
+		if(tribe->get_worker_descr(i)->get_worker_type() == Worker_Descr::SOLDIER) {
+			Worker_Descr::Buildcost::const_iterator end = tribe->get_worker_descr(i)->buildcost().end();
+			for(Worker_Descr::Buildcost::const_iterator it = tribe->get_worker_descr(i)->buildcost().begin(); it != end; ++it) {
+				if(tribe->ware_index(it->first))
+					wares.at(tribe->ware_index(it->first)).demand += it->second * military_demand / 100.0; // Add soldier-need priority
+			}
+		}
+	}
+
+
+   // production buildings need inputs
+   std::list<ProductionSiteObserver>::const_iterator i =
+      productionsites.begin();
+   while(1)
+      {
+         // iterate through both: production buildings and mines
+         if(i == productionsites.end())
+            i = mines.begin();
+         if(i == mines.end())
+            break;
+         // count all empty slots
+         for
+            (ProductionSite::Input_Queues::const_iterator j =
+            i->site->warequeues().begin();
+            j != i->site->warequeues().end();
+            j++)
+            {
+               if((*j)->get_filled() == 0)
+                  // count queues that are empty
+                  wares.at((*j)->get_ware()).demand += 1;
+            }
+         i++;
+      }
+
+	/* TODO: Iterate over all construction sites and add material need
+	 // Remark: construction materials are also handled by other code, but this
+	 // code could do it more scalable for big empires
+
+	Buildcost::const_iterator end = bld.buildcost().end();
+	for(Buildcost::const_iterator it = bld.buildcost().begin(); it != end; ++it) {
+		wares.at(it->first).demand += it->second; // Add build-need priority
+	}*/
+
+	// now decrease the total ammount a bit
+	Ware_Index nr_wares = tribe->get_nrwares();
+	for (Ware_Index i = Ware_Index::First(); i < nr_wares; ++i)
+	   {
+	      wares.at(i).demand *= 0.99;
+	      // enable logging for debug purpose
+	      //printf("ware %s: %f\n", tribe->get_ware_descr(i)->name().c_str(), wares.at(i).demand);
+	   }
+}
+
 
 /// Updates one buildable field
 void DefaultAI::update_buildable_field
@@ -860,245 +945,7 @@
 			if (bo.desc->get_size() > maxsize)
 				continue;
 
-			int32_t prio = 0;
-
-			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) {
-					// production hint (f.e. associate forester with trunks)
-
-					// Calculate the need for this building
-					int16_t inout = wares.at(bo.production_hint).consumers;
-					if
-						(tribe->safe_ware_index("trunk").value()
-						 ==
-						 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;
-						}
-						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) {
-				if (!bf->unowned_land_nearby)
-					continue;
-				prio  = bf->unowned_land_nearby * (1 + type);
-				prio -= bf->military_influence * (5 - type);
-				// set to at least 1
-				prio  = prio > 0 ? prio : 1;
-				prio *= expand_factor;
-				prio /= 2;
-
-				if (bf->enemy_nearby)
-					prio *= 2;
-				else
-					prio -= bf->military_influence * 2;
-
-				if (bf->avoid_military)
-					prio /= 5;
-
-				prio -= militarysites.size() - productionsites.size() / (3 - type);
-
-			} 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;
-
-				// 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;
-
-				// 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;
-			}
-
-			// think of space consuming buildings nearby like farms or vineyards
-			prio /= 1 + bf->space_consumers_nearby;
+			int32_t prio = calculate_building_prio(bo, bf, expand_factor);
 
 			// Stop here, if priority is 0 or less.
 			if (prio <= 0)
@@ -1199,6 +1046,7 @@
 			uint32_t ioprio = 0;
 			for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
 				ioprio += 5 * wares.at(bo.outputs.at(m)).preciousness;
+				ioprio += round(wares.at(bo.outputs.at(m)).demand / 100.0);
 			}
 
 			// tribes that have enhanceable mines should build more mines
@@ -1214,7 +1062,7 @@
 			// 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 *= 45 + bo.current_stats;
 			prio /= 100;
 
 			if (onlymissing) // mines aren't *that* important
@@ -1252,6 +1100,262 @@
 	return true;
 }
 
+int32_t DefaultAI::calculate_building_prio(BuildingObserver & bo, BuildableField * const bf, uint32_t expand_factor)
+{
+	int32_t prio = 0;
+
+	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)
+			return -1;
+		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
+				return -1;*/
+
+			// 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) {
+			// production hint (f.e. associate forester with trunks)
+
+			// Calculate the need for this building
+			int16_t inout = wares.at(bo.production_hint).consumers;
+			if
+				(tribe->safe_ware_index("trunk").value()
+				 ==
+				 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)
+				return -1;
+		} 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
+
+			if (bo.is_basic && (bo.total_count() == 0))
+				prio += 100; // for very important buildings
+
+			// we can enhance this building. build more
+			// maybe the enhancement can produce needed ware
+			// TODO: rather plan an enhanced building from bottom up
+			for (std::set<Building_Index>::const_iterator enhancement =
+				bo.desc->enhancements().begin();
+				enhancement != bo.desc->enhancements().end();
+				enhancement++) {
+				// when we build a, we can build b, too...
+				BuildingObserver & bo2 = buildings[*enhancement];
+				// so simply add the score of the building behind it...
+				uint32_t prio2 = calculate_building_prio(bo2, bf, expand_factor);
+				if (prio2 * (1 + bo.total_count()) > prio * (1 + bo2.total_count()))
+					 prio = prio / 2 + prio2; // we want to build the enhanced building instead of this
+			}
+
+
+			// 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)));
+
+					// Our main instinct: what we actually need
+               // for military, production and construction
+					prio += round(wares.at(bo.outputs.at(m)).demand / 50.0);
+
+					// 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;
+					}
+				}
+				for (uint32_t m = 0; m < bo.inputs.size(); ++m) {
+					Ware_Index wt(static_cast<size_t>(bo.inputs.at(m)));
+
+					// Wares that are needed should not be consumed too much
+					prio -= round(wares.at(wt).demand / 100.0);
+
+					// if the economies don't need it: "waste" it
+					if (!(*l.current)->economy.needs_ware(wt)) {
+						prio++;
+						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;
+				}
+				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
+				return -1;
+
+			// 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) {
+		if (!bf->unowned_land_nearby)
+			return -1;
+		prio  = bf->unowned_land_nearby * (1 + type);
+		prio -= bf->military_influence * (5 - type);
+		// set to at least 1
+		prio  = prio > 0 ? prio : 1;
+		prio *= expand_factor;
+		prio /= 2;
+
+		if (bf->enemy_nearby)
+			prio *= 2;
+		else
+			prio -= bf->military_influence * 2;
+
+		if (bf->avoid_military)
+			prio /= 5;
+
+		prio -= militarysites.size() - productionsites.size() / (3 - type);
+
+	} 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;
+
+		// 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;
+
+		// 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)
+			return -1;
+		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;
+	}
+
+	// think of space consuming buildings nearby like farms or vineyards
+	prio /= 1 + bf->space_consumers_nearby;
+
+	return prio;
+}
+
 /**
  * This function searches for places where a new road is needed to connect two
  * economies. It then sends the request to build the road.
@@ -1722,7 +1826,9 @@
 			if (!site.site->has_workers(*x.current, game()))
 				continue;
 
-			int32_t prio = 0; // priority for enhancement
+			/*BuildableField bf(map.get_fcoords(site.site->get_position()));
+			int32_t prio = calculate_building_prio(en_bo, &bf, 0); // priority for enhancement*/
+			int32_t prio = 0;
 
 			// Find new outputs of enhanced building
 			std::vector<int16_t> & current_outputs = site.bo->outputs;
@@ -1742,6 +1848,7 @@
 			// Check if the new wares are needed in economy of the building
 			for (uint32_t i = 0; i < new_outputs.size(); ++i) {
 				Ware_Index wt(static_cast<size_t>(new_outputs.at(i)));
+				prio += round(wares.at(new_outputs.at(i)).demand / 50.0);
 				if (site.site->economy().needs_ware(wt))
 					prio += 2 + wares.at(new_outputs.at(i)).preciousness;
 			}
@@ -2012,6 +2119,7 @@
 	for (uint32_t k = 0; k < bo.inputs.size(); ++k) {
 		prio += 2 * wares.at(bo.inputs.at(k)).producers;
 		prio -= wares.at(bo.inputs.at(k)).consumers;
+		prio -= round(wares.at(bo.inputs.at(k)).demand / 100.0);
 	}
 	if (bo.inputs.empty())
 		prio += 4;
@@ -2021,6 +2129,7 @@
 		WareObserver & wo = wares.at(bo.outputs.at(k));
 		if (wo.consumers > 0) {
 			output_prio += wo.preciousness;
+			output_prio += round(wo.demand / 100.0);
 			output_prio += wo.consumers * 2;
 			output_prio -= wo.producers * 2;
 			if (bo.total_count() == 0)

=== modified file 'src/ai/defaultai.h'
--- src/ai/defaultai.h	2012-02-20 15:54:26 +0000
+++ src/ai/defaultai.h	2013-01-05 13:44:24 +0000
@@ -118,6 +118,7 @@
 	void update_all_buildable_fields     (int32_t);
 	void update_all_mineable_fields      (int32_t);
 	void update_all_not_buildable_fields ();
+	void update_demand();
 
 	void update_buildable_field(BuildableField &, uint16_t = 6, bool = false);
 	void update_mineable_field (MineableField &);
@@ -138,6 +139,7 @@
 
 	int32_t recalc_with_border_range(const BuildableField &, int32_t);
 	int32_t calculate_need_for_ps(BuildingObserver &, int32_t);
+	int32_t calculate_building_prio(BuildingObserver & bo, BuildableField * const bf, uint32_t expand_factor);
 
 	void consider_productionsite_influence
 		(BuildableField &, Widelands::Coords, BuildingObserver const &);
@@ -193,6 +195,8 @@
 	int32_t time_of_last_construction;
 
 	uint16_t numof_warehouses;
+
+	float military_demand;
 };
 
 #endif

=== modified file 'src/logic/militarysite.h'
--- src/logic/militarysite.h	2012-02-15 21:25:34 +0000
+++ src/logic/militarysite.h	2013-01-05 13:44:24 +0000
@@ -75,6 +75,7 @@
 	// Begin implementation of SoldierControl
 	virtual std::vector<Soldier *> presentSoldiers() const;
 	virtual std::vector<Soldier *> stationedSoldiers() const;
+	virtual uint32_t missingSoldiers() { return m_capacity - stationedSoldiers().size(); }
 	virtual uint32_t minSoldierCapacity() const throw ();
 	virtual uint32_t maxSoldierCapacity() const throw ();
 	virtual uint32_t soldierCapacity() const;

=== modified file 'tribes/barbarians/fernery/conf'
--- tribes/barbarians/fernery/conf	2011-09-12 17:29:32 +0000
+++ tribes/barbarians/fernery/conf	2013-01-05 13:44:24 +0000
@@ -3,6 +3,7 @@
 
 [aihints]
 space_consumer=true
+is_basic=true
 
 [buildcost]
 trunk=5