widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #01998
[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/219750
Significant rework of AI: scoring and algorithm of new buildings, stopping and resuming some types of buildings depending on stock level of produced goods, more agressive growth and with intend to keep an AI expanding.
Only defaultai.cc and defaultai.h were changed.
I dont consider it release-ready, but I need feedback and want to continue with changes.
--
https://code.launchpad.net/~tiborb95/widelands/tiborb-ai/+merge/219750
Your team Widelands Developers is requested to review the proposed merge of lp:~tiborb95/widelands/tiborb-ai into lp:widelands.
=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc 2014-04-29 18:39:52 +0000
+++ src/ai/defaultai.cc 2014-05-15 19:19:26 +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,16 @@
*/
void DefaultAI::think ()
{
+ if (ENABLE_CALLGRIND) {CALLGRIND_START_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);
@@ -117,7 +139,7 @@
// if there are more than one economy try to connect them with a road.
if (next_road_due <= gametime) {
- next_road_due = gametime + 1000;
+ next_road_due = gametime + 1000 ;
if (construct_roads (gametime)) {
m_buildable_changed = true;
m_mineable_changed = true;
@@ -175,6 +197,11 @@
if (check_militarysites(gametime))
return;
+ // going over helper buildings and start/stop them depending
+ // on stock level
+ //check_helpersites(gametime);
+
+
// Finally consider military actions if defaultAI type is Aggressive or
// Normal.
if (!(type == DEFENSIVE))
@@ -194,6 +221,7 @@
inhibit_road_building = gametime + 2500;
return;
}
+ if (ENABLE_CALLGRIND) {CALLGRIND_STOP_INSTRUMENTATION;}
}
/// called by Widelands game engine when an immovable changed
@@ -254,7 +282,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 +295,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)) {
@@ -381,7 +412,7 @@
}
update_buildable_field (bf);
- bf.next_update_due = gametime + FIELD_UPDATE_INTERVAL;
+ bf.next_update_due = gametime + FIELD_UPDATE_INTERVAL ;
buildable_fields.push_back (&bf);
buildable_fields.pop_front ();
@@ -673,7 +704,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 +715,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 +736,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 +766,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 +794,8 @@
++i)
++spots_avail.at((*i)->coords.field->nodecaps() & BUILDCAPS_SIZEMASK);
+
+ //calculating expand factor
int32_t expand_factor = 0;
if (type != DEFENSIVE) {
@@ -770,7 +812,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 +835,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 +894,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 +911,265 @@
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;
+ 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;
+ 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, enemy nearby:% 2d, cur stat: %2d/%2d/%2d, stops:%s %s\n"
+ ,bf->coords.x,bf->coords.y,bf->unowned_land_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() < 1800000) //do not built fortresses in first half of hour of game
+ //continue;
+
if (!bf->unowned_land_nearby)
- continue;
+ continue;
+
prio = bf->unowned_land_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 +1179,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;
-
+ 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,6 +1233,7 @@
if (!bo.buildable(*player) || bo.type != BuildingObserver::MINE)
continue;
+<<<<<<< TREE
// Don't build another building of this type, if there is already
// one that is unoccupied at the moment
@@ -1144,6 +1251,41 @@
continue;
+=======
+
+ //if (MINES_DEBUG ) printf(" TDEBUG: b\n");
+
+ 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");
+
+ // Only have 1 mine of a type under construction
+ if ((bo.cnt_under_construction + bo.unoccupied )> 0)
+ 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: stat: %3d(50), stocklevel: %2d(50), count %2d / %2d / %2d\n",bo.name,bo.current_stats,stocklevel,bo.total_count(),bo.unoccupied,bo.cnt_under_construction);
+ if (((bo.cnt_built-bo.unoccupied)>0 and bo.current_stats<50) or stocklevel>50)
+ continue;
+
+ //iterating over fields
+>>>>>>> MERGE-SOURCE
for
(std::list<MineableField *>::iterator j = mineable_fields.begin();
j != mineable_fields.end();
@@ -1154,7 +1296,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 +1314,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 +1356,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 +1707,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 +1724,8 @@
Map & map = game().map();
+
+
// Lumberjack / Woodcutter handling
if
(site.bo->need_trees
@@ -1604,19 +1734,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 +1773,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 +1811,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 +1869,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 +1926,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 +1949,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 +2001,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 +2021,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 +2075,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 +2106,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 +2189,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-15 19:19:26 +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
Follow ups