widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #02005
[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