widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #02803
Re: [Merge] lp:~widelands-dev/widelands/tibor-ai5 into lp:widelands
I added a bunch of nitpicky code style comments. Can you please fix these? They will make the code a lot easier to read for others :)
Diff comments:
> === modified file 'src/ai/ai_help_structs.cc'
> --- src/ai/ai_help_structs.cc 2014-09-19 12:54:54 +0000
> +++ src/ai/ai_help_structs.cc 2014-10-03 21:34:06 +0000
> @@ -25,21 +25,24 @@
> namespace Widelands {
>
> // FindNodeWithFlagOrRoad
> -
> bool FindNodeWithFlagOrRoad::accept(const Map&, FCoords fc) const {
> if (upcast(PlayerImmovable const, pimm, fc.field->get_immovable()))
> - return pimm->get_economy() != economy && (dynamic_cast<Flag const*>(pimm)
> - || (dynamic_cast<Road const*>(pimm) &&
> - (fc.field->nodecaps() & BUILDCAPS_FLAG)));
> + return (dynamic_cast<Flag const*>(pimm) ||
> + (dynamic_cast<Road const*>(pimm) && (fc.field->nodecaps() & BUILDCAPS_FLAG)));
> return false;
> }
>
> // CheckStepRoadAI
>
> -bool CheckStepRoadAI::allowed(Map& map, FCoords, FCoords end, int32_t, CheckStep::StepId const id)
> - const {
> +bool CheckStepRoadAI::allowed(
> + Map& map, FCoords start, FCoords end, int32_t, CheckStep::StepId const id) const {
> uint8_t endcaps = player_->get_buildcaps(end);
>
> + // we should not cross fields with road or flags (or any other immovable)
> + if ((map.get_immovable(start)) && !(id == CheckStep::stepFirst)) {
> + return false;
> + }
> +
> // Calculate cost and passability
> if (!(endcaps & movecaps_))
> return false;
>
> === modified file 'src/ai/ai_help_structs.h'
> --- src/ai/ai_help_structs.h 2014-09-19 12:54:54 +0000
> +++ src/ai/ai_help_structs.h 2014-10-03 21:34:06 +0000
> @@ -137,9 +137,7 @@
> const World& world_;
> };
>
> -
> struct FindNodeWithFlagOrRoad {
> - Economy* economy;
> bool accept(const Map&, FCoords) const;
> };
>
> @@ -166,6 +164,13 @@
> }
> };
>
> +// ordering nearflags by biggest reduction
> +struct CompareShortening {
> + bool operator()(const NearFlag& a, const NearFlag& b) const {
> + return (a.cost_ - a.distance_) > (b.cost_ - b.distance_);
> + }
> +};
> +
> struct WalkableSpot {
> Coords coords;
> bool has_flag_;
> @@ -191,7 +196,6 @@
>
> int32_t next_update_due_;
>
> - bool reachable;
> bool preferred_;
> bool enemy_nearby_;
>
> @@ -220,6 +224,10 @@
> int16_t military_presence_;
> // stationed (manned) military buildings nearby
> int16_t military_stationed_;
> + // some buildings must be postponed bit
> + int32_t prohibited_till_;
> + // and then some must be forced
> + int32_t forced_after_;
>
> std::vector<uint8_t> consumers_nearby_;
> std::vector<uint8_t> producers_nearby_;
> @@ -227,7 +235,6 @@
> BuildableField(const Widelands::FCoords& fc)
> : coords(fc),
> next_update_due_(0),
> - reachable(false),
> preferred_(false),
> enemy_nearby_(0),
> unowned_land_nearby_(0),
> @@ -259,13 +266,12 @@
>
> int32_t next_update_due_;
>
> - bool reachable;
> bool preferred_;
>
> int32_t mines_nearby_;
>
> MineableField(const Widelands::FCoords& fc)
> - : coords(fc), next_update_due_(0), reachable(false), preferred_(false), mines_nearby_(0) {
> + : coords(fc), next_update_due_(0), preferred_(false), mines_nearby_(0) {
> }
> };
>
> @@ -296,22 +302,22 @@
> MINE
> } type;
>
> - bool is_basic_; // is a "must" to have for the ai
> - bool is_food_basic_; // few food producer to be built sooner
> bool prod_build_material_;
> bool plants_trees_;
> bool recruitment_; // is "producing" workers?
> bool is_buildable_;
> bool need_trees_; // lumberjack = true
> bool need_stones_; // quarry = true
> - bool mines_marble_; // need to distinquish mines_ that produce marbles
> bool mines_water_; // wells
> bool need_water_; // fisher, fish_breeder = true
> bool is_hunter_; // need to identify hunters
> + bool is_fisher_; // need to identify hunters
> bool space_consumer_; // farm, vineyard... = true
> bool expansion_type_; // military building used that can be used to control area
> bool fighting_type_; // military building built near enemies
> bool mountain_conqueror_; // military building built near mountains
> + int32_t prohibited_till_; // do not build before (ms)
> + int32_t forced_after_; // do not wait until ware is needed
>
> bool unoccupied_; //
>
> @@ -347,6 +353,7 @@
> int32_t built_time_;
> int32_t unoccupied_till_;
> uint8_t stats_zero_;
> + uint8_t no_resources_count;
> BuildingObserver* bo;
> };
>
>
> === modified file 'src/ai/ai_hints.cc'
> --- src/ai/ai_hints.cc 2014-07-14 10:45:44 +0000
> +++ src/ai/ai_hints.cc 2014-10-03 21:34:06 +0000
> @@ -32,12 +32,8 @@
> BuildingHints::BuildingHints(Section* const section)
> : renews_map_resource(nullptr),
> mines_(nullptr),
> - basic_(section ? section->get_bool("is_basic") : false),
> - food_basic_(section ? section->get_bool("is_food_basic") : false),
> - build_material_(section ? section->get_bool("build_material") : true),
> log_producer_(section ? section->get_bool("logproducer") : false),
> stone_producer_(section ? section->get_bool("stoneproducer") : false),
> - marble_producer_(section ? section->get_bool("marbleproducer") : false),
> needs_water_(section ? section->get_bool("needs_water") : false),
> mines_water_(section ? section->get_bool("mines_water") : false),
> recruitment_(section ? section->get_bool("recruitment") : false),
> @@ -45,6 +41,8 @@
> expansion_(section ? section->get_bool("expansion") : false),
> fighting_(section ? section->get_bool("fighting") : false),
> mountain_conqueror_(section ? section->get_bool("mountain_conqueror") : false),
> + prohibited_till_(section ? section->get_int("prohibited_till", 0) : 0),
> + forced_after_(section ? section->get_int("forced_after", 864000) : 0), // 10 days default
> mines_percent_(section ? section->get_int("mines_percent", 100) : 0) {
> if (section) {
> if (char const* const s = section->get_string("renews_map_resource"))
>
> === modified file 'src/ai/ai_hints.h'
> --- src/ai/ai_hints.h 2014-07-15 05:12:37 +0000
> +++ src/ai/ai_hints.h 2014-10-03 21:34:06 +0000
> @@ -41,18 +41,6 @@
> return mines_;
> }
>
> - bool is_basic() const {
> - return basic_;
> - }
> -
> - bool is_food_basic() const {
> - return food_basic_;
> - }
> -
> - bool prod_build_material() const {
> - return build_material_;
> - }
> -
> bool is_logproducer() const {
> return log_producer_;
> }
> @@ -61,10 +49,6 @@
> return stone_producer_;
> }
>
> - bool is_marbleproducer() const {
> - return marble_producer_;
> - }
> -
> bool mines_water() const {
> return mines_water_;
> }
> @@ -90,6 +74,14 @@
> return mountain_conqueror_;
> }
>
> + int32_t get_prohibited_till() const {
> + return prohibited_till_;
> + }
> +
> + int32_t get_forced_after() const {
> + return forced_after_;
> + }
> +
> uint8_t get_mines_percent() const {
> return mines_percent_;
> }
> @@ -97,12 +89,8 @@
> private:
> char* renews_map_resource;
> char* mines_;
> - bool basic_;
> - bool food_basic_;
> - bool build_material_; // whether the building produces build material
> bool log_producer_;
> bool stone_producer_;
> - bool marble_producer_;
> bool needs_water_;
> bool mines_water_;
> bool recruitment_; // whether building recruits special workers
> @@ -110,6 +98,8 @@
> bool expansion_;
> bool fighting_;
> bool mountain_conqueror_;
> + int32_t prohibited_till_;
> + int32_t forced_after_;
> uint8_t mines_percent_;
>
> DISALLOW_COPY_AND_ASSIGN(BuildingHints);
>
> === modified file 'src/ai/defaultai.cc'
> --- src/ai/defaultai.cc 2014-09-19 12:54:54 +0000
> +++ src/ai/defaultai.cc 2014-10-03 21:34:06 +0000
> @@ -23,6 +23,7 @@
> #include <ctime>
> #include <queue>
> #include <typeinfo>
> +#include <unordered_set>
>
> #include "ai/ai_hints.h"
> #include "base/log.h"
> @@ -44,16 +45,19 @@
> #include "logic/world/world.h"
> #include "profile/profile.h"
>
> +// Building of new military buildings can be restricted
> +constexpr int kFreeExpansion = 1;
> +constexpr int kResourcesOrDefense = 2;
> +constexpr int kDefenseOnly = 3;
> +constexpr int kNoNewMilitary = 4;
> +
> // following is in miliseconds (widelands counts time in ms)
> -constexpr int kFieldUpdateInterval = 1000;
> +constexpr int kFieldUpdateInterval = 2000;
> constexpr int kIdleMineUpdateInterval = 22000;
> constexpr int kBusyMineUpdateInterval = 2000;
> // building of the same building can be started after 25s at earliest
> constexpr int kBuildingMinInterval = 25 * 1000;
> -constexpr int kBaseInfrastructureTime = 20 * 60 * 1000;
> -// buildings marked as is_food_basic will be forced after 15 minutes, even though their outputs are
> -// not needed yet
> -constexpr int kPrimaryFoodStartTime = 15 * 60 * 1000;
> +constexpr int kMinBFCheckInterval = 6 * 1000;
What does the BF in "kMinBFCheckInterval" mean? Unless this makes lines too long, can you rename this variable? Otherwise, add a comment as to what it does?
I have now found this farther down in a comment, maybe "kBuildableFieldsCheckInterval" would be a good name
>
> using namespace Widelands;
>
> @@ -70,6 +74,8 @@
> player_(nullptr),
> tribe_(nullptr),
> num_constructionsites_(0),
> + num_milit_constructionsites(0),
> + num_prod_constructionsites(0),
> next_road_due_(2000),
> next_stats_update_due_(30000),
> next_construction_due_(1000),
> @@ -79,37 +85,53 @@
> next_militarysite_check_due_(0),
> next_attack_consideration_due_(300000),
> next_helpersites_check_due_(180000),
> + next_bf_check_due_(1000),
As above - what does "bf" mean?
> inhibit_road_building_(0),
> time_of_last_construction_(0),
> + enemy_last_seen_(-2 * 60 * 1000),
> numof_warehouses_(0),
> new_buildings_stop_(false),
> + water_is_important_(false),
> + mines_need_intensity_ (10),
> + water_need_intensity_ (4),
> unstationed_milit_buildings_(0),
> - military_under_constr_(0),
> military_last_dismantle_(0),
> - military_last_build_(0) {
> + military_last_build_(-60 * 1000),
> + spots_(0) {
>
> // Subscribe to NoteFieldPossession.
> field_possession_subscriber_ =
> - Notifications::subscribe<NoteFieldPossession>([this](const NoteFieldPossession& note) {
> - if (note.player != player_) {
> - return;
> - }
> - if (note.ownership == NoteFieldPossession::Ownership::GAINED) {
> - unusable_fields.push_back(note.fc);
> - }
> + Notifications::subscribe<NoteFieldPossession>([this](const NoteFieldPossession& note) {
> + if (note.player != player_) {
> + return;
> + }
> + if (note.ownership == NoteFieldPossession::Ownership::GAINED) {
> + unusable_fields.push_back(note.fc);
> + }
> });
>
> // Subscribe to NoteImmovables.
> immovable_subscriber_ =
> - Notifications::subscribe<NoteImmovable>([this](const NoteImmovable& note) {
> - if (note.pi->owner().player_number() != player_->player_number()) {
> - return;
> - }
> - if (note.ownership == NoteImmovable::Ownership::GAINED) {
> - gain_immovable(*note.pi);
> - } else {
> - lose_immovable(*note.pi);
> - }
> + Notifications::subscribe<NoteImmovable>([this](const NoteImmovable& note) {
> + if (note.pi->owner().player_number() != player_->player_number()) {
> + return;
> + }
> + if (note.ownership == NoteImmovable::Ownership::GAINED) {
> + gain_immovable(*note.pi);
> + } else {
> + lose_immovable(*note.pi);
> + }
> + });
> +
> + // Subscribe to ProductionSiteOutOfResources.
> + outofresource_subscriber_ = Notifications::subscribe<NoteProductionSiteOutOfResources>(
> + [this](const NoteProductionSiteOutOfResources& note) {
> + if (note.ps->owner().player_number() != player_->player_number()) {
> + return;
> + }
> +
> + out_of_resources_site(*note.ps);
> +
> });
> }
>
> @@ -142,23 +164,24 @@
>
> const int32_t gametime = game().get_gametime();
>
> - if (m_buildable_changed) {
> + if (m_buildable_changed || next_bf_check_due_ < gametime) {
> // update statistics about buildable fields
> update_all_buildable_fields(gametime);
> + next_bf_check_due_ = gametime + kMinBFCheckInterval;
> }
>
> m_buildable_changed = false;
>
> - // if there are more than one economy try to connect them with a road.
> + // perpetually tries to improve roads
> if (next_road_due_ <= gametime) {
> next_road_due_ = gametime + 1000;
>
> - if (construct_roads(gametime)) {
> + if (improve_roads(gametime)) {
> m_buildable_changed = true;
> return;
> }
> } else
> - // only go on, after defaultAI tried to connect all economies.
> + // only go on, after defaultAI tried to improve roads.
> return;
>
> // NOTE Because of the check above, the following parts of think() are used
> @@ -190,6 +213,7 @@
>
> if (construct_building(gametime)) {
> time_of_last_construction_ = gametime;
> + m_buildable_changed = true;
> return;
> }
> }
> @@ -208,16 +232,12 @@
> return;
>
> // improve existing roads!
> - // This sounds important, but actually is not as important as the other
> - // actions are. Reasons are the following:
> - // * The "donkey feature" made economies more stable, even with stupid
> - // roads.
> - // * If defaultAI builds too much roads, it will waste good building
> - // space.
> + // main part of this improvment is creation 'shortcut roads'
> + // this includes also connection of new buildings
> if (improve_roads(gametime)) {
> m_buildable_changed = true;
> m_mineable_changed = true;
> - inhibit_road_building_ = gametime + 2500;
> + // inhibit_road_building_ = gametime + 1000;
Do you still need this line? If so, please add a TODO comment. Otherwise, remove.
> return;
> }
> }
> @@ -257,7 +277,7 @@
> bo.type = BuildingObserver::BORING;
> bo.cnt_built_ = 0;
> bo.cnt_under_construction_ = 0;
> - bo.cnt_target_ = 0;
> + bo.cnt_target_ = 1; // default for everything
> bo.stocklevel_ = 0;
> bo.stocklevel_time = 0;
> bo.last_dismantle_time_ = 0;
> @@ -267,12 +287,9 @@
> bo.production_hint_ = -1;
> bo.current_stats_ = 0;
> bo.unoccupied_ = false;
> - bo.is_basic_ = false;
> - bo.is_food_basic_ = false;
> bo.is_buildable_ = bld.is_buildable();
> bo.need_trees_ = bh.is_logproducer();
> bo.need_stones_ = bh.is_stoneproducer();
> - bo.mines_marble_ = bh.is_marbleproducer();
> bo.need_water_ = bh.get_needs_water();
> bo.mines_water_ = bh.mines_water();
> bo.recruitment_ = bh.for_recruitment();
> @@ -280,9 +297,10 @@
> bo.expansion_type_ = bh.is_expansion_type();
> bo.fighting_type_ = bh.is_fighting_type();
> bo.mountain_conqueror_ = bh.is_mountain_conqueror();
> + bo.prohibited_till_ = bh.get_prohibited_till() * 1000; // value in conf is in seconds
> + bo.forced_after_ = bh.get_forced_after() * 1000; // value in conf is in seconds
> if (char const* const s = bh.get_renews_map_resource()) {
> bo.production_hint_ = tribe_->safe_ware_index(s);
> -
> }
>
> // I just presume cut wood is named "log" in the game
> @@ -294,7 +312,7 @@
> // Read all interesting data from ware producing buildings
> if (typeid(bld) == typeid(ProductionSiteDescr)) {
> const ProductionSiteDescr& prod =
> - ref_cast<ProductionSiteDescr const, BuildingDescr const>(bld);
> + ref_cast<ProductionSiteDescr const, BuildingDescr const>(bld);
> bo.type = bld.get_ismine() ? BuildingObserver::MINE : BuildingObserver::PRODUCTIONSITE;
> for (const WareAmount& temp_input : prod.inputs()) {
> bo.inputs_.push_back(temp_input.first);
> @@ -311,16 +329,17 @@
> bo.mines_percent_ = bh.get_mines_percent();
> }
>
> - bo.is_basic_ = bh.is_basic();
> - bo.is_food_basic_ = bh.is_food_basic();
> - bo.prod_build_material_ = bh.prod_build_material();
> -
> // here we identify hunters
> if (bo.outputs_.size() == 1 && tribe_->safe_ware_index("meat") == bo.outputs_.at(0)) {
> bo.is_hunter_ = true;
> } else
> bo.is_hunter_ = false;
>
> + // and fishers
> + if (bo.outputs_.size() == 1 && tribe_->safe_ware_index("fish") == bo.outputs_.at(0)) {
> + bo.is_fisher_ = true;
> + } else
> + bo.is_fisher_ = false;
> continue;
> }
>
> @@ -346,10 +365,16 @@
> }
>
> num_constructionsites_ = 0;
> + num_milit_constructionsites = 0;
> + num_prod_constructionsites = 0;
> next_construction_due_ = 0;
> next_road_due_ = 1000;
> next_productionsite_check_due_ = 0;
> inhibit_road_building_ = 0;
> + // if atlanteans they consider water as a resource
> + //(together with mines, stones and wood)
> + if (tribe_->name() == "atlanteans")
> + water_is_important_ = true;
> // Add all fields that we own
> Map& map = game().map();
> std::set<OPtr<PlayerImmovable>> found_immovables;
> @@ -381,7 +406,11 @@
> * milliseconds if the area the computer owns is big.
> */
> void DefaultAI::update_all_buildable_fields(const int32_t gametime) {
> - while (!buildable_fields.empty() && buildable_fields.front()->next_update_due_ <= gametime) {
> +
> + uint16_t i = 0;
> +
> + while (!buildable_fields.empty() && buildable_fields.front()->next_update_due_ <= gametime &&
> + i < 25) {
How about a "for" loop? This will make the code easier to read, and we save 2 lines.
for (uint16_t i = 0; !buildable_fields.empty() && buildable_fields.front()->next_update_due_ <= gametime &&
502 + i < 25; i++) {
> BuildableField& bf = *buildable_fields.front();
>
> // check whether we lost ownership of the node
> @@ -403,6 +432,8 @@
> bf.next_update_due_ = gametime + kFieldUpdateInterval;
> buildable_fields.push_back(&bf);
> buildable_fields.pop_front();
> +
> + i += 1;
> }
> }
>
> @@ -413,7 +444,11 @@
> * milliseconds if the area the computer owns is big.
> */
> void DefaultAI::update_all_mineable_fields(const int32_t gametime) {
> - while (!mineable_fields.empty() && mineable_fields.front()->next_update_due_ <= gametime) {
> +
> + uint16_t i = 0; // counter, used to track # of checked fields
> +
> + while (!mineable_fields.empty() && mineable_fields.front()->next_update_due_ <= gametime &&
> + i < 40) {
"for" loop?
> MineableField* mf = mineable_fields.front();
>
> // check whether we lost ownership of the node
> @@ -435,6 +470,8 @@
> mf->next_update_due_ = gametime + kFieldUpdateInterval; // in fact this has very small effect
> mineable_fields.push_back(mf);
> mineable_fields.pop_front();
> +
> + i += 1;
> }
> }
>
> @@ -495,13 +532,16 @@
> }
>
> // to save some CPU
> - if (mines_.size() > 8 && game().get_gametime() % 3 > 0)
> + if ((mines_.size() > 8 && game().get_gametime() % 3 > 0) || field.unowned_land_nearby_ == 0)
Since "else" now has {}, give "if" {} as well
>From http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Conditionals
"if one part of an if-else statement uses curly braces, the other part must too"
> field.unowned_mines_pots_nearby_ = 0;
> - else
> - field.unowned_mines_pots_nearby_ = map.find_fields(
> - Area<FCoords>(field.coords, range + 4),
> - nullptr,
> - find_unowned_mines_pots); //+2: a mine can mine raw materials from some range
> + else {
> + uint32_t close_mines =
> + map.find_fields(Area<FCoords>(field.coords, 4), nullptr, find_unowned_mines_pots);
> + uint32_t distant_mines =
> + map.find_fields(Area<FCoords>(field.coords, range + 6), nullptr, find_unowned_mines_pots);
> + distant_mines = distant_mines - close_mines;
> + field.unowned_mines_pots_nearby_ = 6 * close_mines + distant_mines;
> + }
>
> // collect information about resources in the area
> std::vector<ImmovableFound> immovables;
> @@ -512,7 +552,6 @@
> // (second is used in check_militarysites)
> if (!military) {
> int32_t const tree_attr = MapObjectDescr::get_attribute_id("tree");
> - field.reachable = false;
> field.preferred_ = false;
> field.enemy_nearby_ = false;
> field.military_capacity_ = 0;
> @@ -536,7 +575,7 @@
> }
>
> // counting fields with fish
> - if (field.water_nearby_ > 0 && game().get_gametime() % 10 == 0) {
> + if (field.water_nearby_ > 0 && (field.fish_nearby_ = -1 || game().get_gametime() % 10 == 0)) {
> map.find_fields(Area<FCoords>(field.coords, 6),
> &resource_list,
> FindNodeResource(world.get_resource("fish")));
> @@ -554,16 +593,13 @@
> map.get_neighbour(field.coords, WALK_SE, &fse);
>
> if (BaseImmovable const* const imm = fse.field->get_immovable())
> - if (dynamic_cast<Flag const*>(imm)
> - || (dynamic_cast<Road const*>(imm) && (fse.field->nodecaps() & BUILDCAPS_FLAG)))
> + if (dynamic_cast<Flag const*>(imm) ||
> + (dynamic_cast<Road const*>(imm) && (fse.field->nodecaps() & BUILDCAPS_FLAG)))
> field.preferred_ = true;
>
> for (uint32_t i = 0; i < immovables.size(); ++i) {
> const BaseImmovable& base_immovable = *immovables.at(i).object;
>
> - if (dynamic_cast<const Flag*>(&base_immovable))
> - field.reachable = true;
> -
> if (upcast(PlayerImmovable const, player_immovable, &base_immovable))
>
> // TODO(unknown): Only continue; if this is an opposing site
> @@ -571,6 +607,7 @@
> if (player_immovable->owner().player_number() != pn) {
> if (player_->is_hostile(player_immovable->owner()))
> field.enemy_nearby_ = true;
> + enemy_last_seen_ = game().get_gametime();
>
> continue;
> }
> @@ -588,7 +625,9 @@
>
> if (dynamic_cast<const ProductionSite*>(building))
> consider_productionsite_influence(
> - field, immovables.at(i).coords, get_building_observer(building->descr().name().c_str()));
> + field,
> + immovables.at(i).coords,
> + get_building_observer(building->descr().name().c_str()));
> }
>
> if (immovables.at(i).object->has_attribute(tree_attr))
> @@ -616,7 +655,15 @@
> }
>
> // folowing is done allways (regardless of military or not)
> +
> + // we get immovables with higher radius
> + immovables.clear();
> + map.find_immovables(Area<FCoords>(field.coords, (range < 10) ? 10 : range), &immovables);
> field.military_stationed_ = 0;
> + field.military_in_constr_nearby_ = 0;
> + field.military_capacity_ = 0;
> + field.military_loneliness_ = 1000;
> + field.military_presence_ = 0;
>
> for (uint32_t i = 0; i < immovables.size(); ++i) {
> const BaseImmovable& base_immovable = *immovables.at(i).object;
> @@ -644,7 +691,8 @@
> const int32_t v = radius - dist;
>
> if (v > 0) {
> - field.military_capacity_ += 2;
> + field.military_capacity_ += target_ms_d->get_max_number_of_soldiers() / 2 + 1;
> + // field.military_capacity_ += 2;
Can this line go? If not, please add a "TODO" comment.
When I comment something out to test if the code works/compiles first, I often add a quick "NOCOM", so I can grep for it and remove before a merge request.
> field.military_loneliness_ *= static_cast<double_t>(dist) / radius;
> field.military_in_constr_nearby_ += 1;
> }
> @@ -663,14 +711,15 @@
>
> if (!militarysite->stationed_soldiers().empty()) {
> field.military_stationed_ += 1;
> - }
> + } else
curly braces?
> + // the name does not match much
> + field.military_in_constr_nearby_ += 1;
>
> field.military_loneliness_ *= static_cast<double_t>(dist) / radius;
> }
> }
> }
> }
> -
> }
>
> /// Updates one mineable field
> @@ -679,21 +728,18 @@
> std::vector<ImmovableFound> immovables;
> Map& map = game().map();
> map.find_immovables(Area<FCoords>(field.coords, 5), &immovables);
> - field.reachable = false;
> field.preferred_ = false;
> field.mines_nearby_ = 1;
> FCoords fse;
> map.get_brn(field.coords, &fse);
>
> if (BaseImmovable const* const imm = fse.field->get_immovable())
> - if (dynamic_cast<Flag const*>(imm)
> - || (dynamic_cast<Road const*>(imm) && (fse.field->nodecaps() & BUILDCAPS_FLAG)))
> + if (dynamic_cast<Flag const*>(imm) ||
> + (dynamic_cast<Road const*>(imm) && (fse.field->nodecaps() & BUILDCAPS_FLAG)))
> field.preferred_ = true;
>
> for (const ImmovableFound& temp_immovable : immovables) {
> - if (dynamic_cast<Flag const*>(temp_immovable.object))
> - field.reachable = true;
> - else if (upcast(Building const, bld, temp_immovable.object)) {
> + if (upcast(Building const, bld, temp_immovable.object)) {
> if (bld->descr().get_ismine()) {
> ++field.mines_nearby_;
> } else if (upcast(ConstructionSite const, cs, bld)) {
> @@ -708,6 +754,7 @@
> void DefaultAI::update_productionsite_stats(int32_t const gametime) {
> // Updating the stats every 10 seconds should be enough
> next_stats_update_due_ = gametime + 10000;
> + uint16_t fishers_count=0; //used for atlanteans only
>
> // Reset statistics for all buildings
> for (uint32_t i = 0; i < buildings_.size(); ++i) {
> @@ -726,6 +773,10 @@
> // Add statistics value
> productionsites.front().bo->current_stats_ +=
> productionsites.front().site->get_crude_statistics();
> +
> + //counting fishers
> + if (productionsites.front().bo->is_fisher_)
> + fishers_count+=1;
>
> // Check whether this building is completely occupied
> productionsites.front().bo->unoccupied_ |= !productionsites.front().site->can_start_working();
> @@ -735,8 +786,14 @@
> productionsites.pop_front();
> }
>
> + if (fishers_count >4)
Space between > and 4. We have more of these, can you please run codecheck and fix?
cmake/codecheck/CodeCheck.py src/* | grep -v "src/third_party"
> + water_need_intensity_ = 0;
> + else
> + water_need_intensity_ = 4-fishers_count;
> + //printf (" %2d: water need intensity: %3d%%/ %2d fishers\n",player_number(),100*water_need_intensity_/4,fishers_count);
Can this go? Otherwise, TODO
> +
> // for mines_ also
> - // Check all available productionsites
> + // Check all available mines
> for (uint32_t i = 0; i < mines_.size(); ++i) {
> assert(mines_.front().bo->cnt_built_ > 0);
> // Add statistics value
> @@ -779,7 +836,6 @@
> // 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;
> // this is to increase score so also building near borders can be built
> int32_t bulgarian_constant = 12;
> @@ -795,53 +851,67 @@
> ++i)
> ++spots_avail.at((*i)->coords.field->nodecaps() & BUILDCAPS_SIZEMASK);
>
> - spots = spots_avail.at(BUILDCAPS_SMALL);
> - spots += spots_avail.at(BUILDCAPS_MEDIUM);
> - spots += spots_avail.at(BUILDCAPS_BIG);
> + spots_ = spots_avail.at(BUILDCAPS_SMALL);
> + spots_ += spots_avail.at(BUILDCAPS_MEDIUM);
> + spots_ += spots_avail.at(BUILDCAPS_BIG);
>
> - // checking amount of free spots, if needed setting new building stop flag
> + // here we possible stop building of new buildings
> new_buildings_stop_ = false;
> -
> - if ((militarysites.size() * 2 + 20) <
> - productionsites.size()
> - || spots<(3 + (static_cast<int32_t>(productionsites.size()) / 5)) || num_constructionsites_>(
> - (militarysites.size() + productionsites.size()) / 2)) {
> - new_buildings_stop_ = true;
> - }
> -
> - // sometimes there is to many military buildings in construction, so we must
> + uint8_t expansion_mode = kFreeExpansion;
> +
> + // there are couple of reasons why to stop building production buildings
> + //(note there are numberous exemptions to this stop)
> + // 1. to not have too many constructionsites
> + if (num_prod_constructionsites > productionsites.size() / 7 + 2) {
> + new_buildings_stop_ = true;
> + }
> + // 2. to not exhaust all free spots
> + if (spots_ * 3 / 2 + 5 < static_cast<int32_t>(productionsites.size())) {
> + new_buildings_stop_ = true;
> + }
> + // 3. too keep some proportions production sites vs military sites
> + if ((num_prod_constructionsites + productionsites.size()) >
> + (num_milit_constructionsites + militarysites.size()) * 3) {
> + new_buildings_stop_ = true;
> + }
> + // 4. if we do not have 3 mines at least
> + if (mines_.size() < 3)
> + new_buildings_stop_ = true;
> + // BUT if enemy is nearby, we cancel above stop
> + if (new_buildings_stop_ && enemy_last_seen_ + 2 * 60 * 1000 > gametime) {
> + new_buildings_stop_ = false;
> + }
> +
> + // sometimes there is too many military buildings in construction, so we must
> // prevent initialization of further buildings start
> - bool new_military_buildings_stop = false;
> - // in areas close to enemies, above limit is not effective, so we have second one
> - // more benevolent limit
> - bool near_enemy_b_buildings_stop = false;
> - // in some situation expansion just halts because there are not good spots to expand
> - // so this is a boost to increase a score and allow building a military building on a spot
> - // that is normally not suitable for building
> - int32_t military_boost = 1;
> -
> - int32_t treshold = (militarysites.size() + productionsites.size()) / 100 + 1;
> -
> - if (unstationed_milit_buildings_ + military_under_constr_ / 3 > treshold) {
> - new_military_buildings_stop = true;
> -
> - }
> -
> - if (unstationed_milit_buildings_ + military_under_constr_ / 3 > 2 * treshold) {
> - near_enemy_b_buildings_stop = true;
> -
> - }
> -
> - // here we deal with situation when for some time no new military building was built
> - // in fact this is a last time when there were any military buildings in construction
> - if ((unstationed_milit_buildings_ + military_under_constr_) > 0)
> - military_last_build_ = game().get_gametime();
> -
> - if (military_last_build_ + 1 * 60 * 1000 < game().get_gametime()) {
> - military_boost = 200;
> - }
> -
> - // BuildingIndex proposed_building = INVALID_INDEX; // I need BuildingObserver not index
> + const uint32_t treshold = militarysites.size() / 40 + 2;
> +
> + if (unstationed_milit_buildings_ + num_milit_constructionsites > 3 * treshold)
> + expansion_mode = kNoNewMilitary;
> + else if (unstationed_milit_buildings_ + num_milit_constructionsites > 2 * treshold)
> + expansion_mode = kDefenseOnly;
> + else if (unstationed_milit_buildings_ + num_milit_constructionsites > 1 * treshold)
> + expansion_mode = kResourcesOrDefense;
> + else
> + expansion_mode = kFreeExpansion;
> +
> + // slowing down the expansion also because of new_buildings_stop_
> + if (new_buildings_stop_ && unstationed_milit_buildings_ + num_milit_constructionsites > 0 &&
> + spots_avail.at(BUILDCAPS_BIG) > 3)
> + expansion_mode += 1;
> + if (expansion_mode > kNoNewMilitary)
> + expansion_mode = kNoNewMilitary;
> +
> + //we must consider need for mines
> + const int32_t virtual_mines = mines_.size()+ mineable_fields.size()/10;
> + if (virtual_mines<4)
> + mines_need_intensity_ = 10;
> + else if (virtual_mines>14)
> + mines_need_intensity_ = 0;
> + else
> + mines_need_intensity_ = 14-virtual_mines;
> + //printf (" %1d: mines need intensity: %3d%% / %2d mines\n",player_number(),100*mines_need_intensity_/10,mines_.size());
Delete? or TODO
> +
> BuildingObserver* best_building = nullptr;
> int32_t proposed_priority = 0;
> Coords proposed_coords;
> @@ -864,11 +934,10 @@
> ++i) {
> BuildableField* const bf = *i;
>
> - if (!bf->reachable)
> - continue;
> -
> - // add randomnes and ease AI
> - if (time(nullptr) % 5 == 0)
> + // if bf update is overdue for more then 8 seconds
> + // this will also speed up the game
> + // this way there should be allways more then 100 bf evaluated
> + if (bf->next_update_due_ < gametime - 8000)
> continue;
>
> // Continue if field is blocked at the moment
> @@ -893,13 +962,23 @@
> if (!bo.buildable(*player_))
> continue;
>
> - if (time(nullptr) % 3 == 0)
> + if (bo.prohibited_till_ > gametime) {
> + continue;
> + }
> +
> + // if current field is not big enough
> + if (bo.desc->get_size() > maxsize)
> + continue;
> +
> + if (time(nullptr) % 3 == 0 && bo.total_count() > 0)
> continue; // add randomnes and ease AI
>
> if (bo.type == BuildingObserver::MINE)
> continue;
>
> - if (gametime - bo.construction_decision_time_ < kBuildingMinInterval)
> + // here we do an exemption for lumberjacs, mainly in early stages of game
> + // sometimes the first one is not built and AI waits too long for second attempt
> + if (gametime - bo.construction_decision_time_ < kBuildingMinInterval && !bo.need_trees_)
> continue;
>
> if (bo.unoccupied_)
> @@ -909,49 +988,15 @@
> continue;
>
> // so we are going to seriously evaluate this building on this field,
> - // first some base info
> - // if at least on of outputs is needed
> - output_is_needed = false;
> - // max presiousness of outputs
> - max_preciousness = 0;
> - // max preciousness of most needed output
> - max_needed_preciousness = 0;
> -
> - // Check if the produced wares are needed (if it is producing anything)
> - if (!bo.outputs_.empty()) {
> - for (EconomyObserver* observer : economies) {
> - // Don't check if the economy has no warehouse.
> - if (observer->economy.warehouses().empty())
> - continue;
> -
> - for (uint32_t m = 0; m < bo.outputs_.size(); ++m) {
> - WareIndex wt(static_cast<size_t>(bo.outputs_.at(m)));
> -
> - if (observer->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_;
> - } else {
> - if (wares.at(bo.outputs_.at(m)).preciousness_ > max_preciousness)
> - max_preciousness = wares.at(bo.outputs_.at(m)).preciousness_;
> - }
> - }
> - }
> - }
> + // first some base info - is its output needed at all?
> + check_ware_needeness(bo, &output_is_needed, &max_preciousness, &max_needed_preciousness);
Rename to check_ware_necessity? Function name has a typo in any case.
>
> int32_t prio = 0; // score of a bulding on a field
>
> - // if current field is not big enough
> - if (bo.desc->get_size() > maxsize)
> - continue;
> -
> if (bo.type == BuildingObserver::PRODUCTIONSITE) {
>
> // exclude spots on border
> - if (bf->near_border_ && !bo.need_trees_ && !bo.need_stones_)
> + if (bf->near_border_ && !bo.need_trees_ && !bo.need_stones_ && !bo.is_fisher_)
> continue;
>
> // this can be only a well (as by now)
> @@ -961,32 +1006,52 @@
>
> if (bo.cnt_under_construction_ + bo.unoccupied_ > 0)
> continue;
> - if ((bo.cnt_built_ + bo.unoccupied_) > 0 && gametime < kBaseInfrastructureTime)
> - continue;
> - if (new_buildings_stop_)
> - continue;
> - bo.cnt_target_ =
> - 2 + static_cast<int32_t>(mines_.size() + productionsites.size()) / 20;
> - if ((bo.cnt_built_ + bo.cnt_under_construction_ + bo.unoccupied_) > bo.cnt_target_)
> - continue;
> +
> + prio = 0;
> + // one well is forced
> + if (bo.total_count() == 0)
> + prio = 200; // boost for first/only well
> + else if (new_buildings_stop_)
> + continue;
> +
> + bo.cnt_target_ = 1 + productionsites.size() / 50;
>
> if (bo.stocklevel_time < game().get_gametime() - 30 * 1000) {
> bo.stocklevel_ = get_stocklevel(bo);
> bo.stocklevel_time = game().get_gametime();
> }
> - if (bo.stocklevel_ > 50)
> + if (bo.stocklevel_ > 40)
> continue;
> - prio = bf->ground_water_ - 2;
> + prio += bf->ground_water_ - 2;
> prio = recalc_with_border_range(*bf, prio);
>
> } else if (bo.need_trees_) { // LUMBERJACS
>
> - if (bo.cnt_built_ + bo.cnt_under_construction_ + bo.unoccupied_ <= 2)
> - prio = bulgarian_constant + 200 + bf->trees_nearby_;
> - else if (bo.cnt_under_construction_ + bo.unoccupied_ <= 1) {
> - prio =
> - bf->trees_nearby_ - 5 - bf->producers_nearby_.at(bo.outputs_.at(0)) * 5 -
> - new_buildings_stop_ * 15; //+ bf->producers_nearby_.at(bo.outputs_.at(0))*5;
> + bo.cnt_target_ =
> + 3 + static_cast<int32_t>(mines_.size() + productionsites.size()) / 15;
> +
> + if (bo.total_count() == 0)
> + prio = 500 + bf->trees_nearby_;
> +
> + else if (bo.total_count() == 1)
> + prio = 400 + bf->trees_nearby_;
> +
> + else if (bf->trees_nearby_ < 2)
> + continue;
> +
> + else {
> +
> + if (bo.total_count() < bo.cnt_target_)
> + prio = 75;
> + else
> + prio = 0;
> +
> + prio += 2 * bf->trees_nearby_ - 10 -
> + bf->producers_nearby_.at(bo.outputs_.at(0)) * 5 -
> + new_buildings_stop_ * 15;
> +
> + if (bf->near_border_)
> + prio = prio / 2;
> }
>
> } else if (bo.need_stones_) {
> @@ -998,20 +1063,66 @@
> continue;
> prio = bf->stones_nearby_;
>
> + if (prio <= 0)
> + continue;
> +
> + if (bo.total_count() == 0)
> + prio += 150;
> +
> if (bo.stocklevel_time < game().get_gametime() - 5 * 1000) {
> bo.stocklevel_ = get_stocklevel_by_hint(static_cast<size_t>(bo.production_hint_));
> bo.stocklevel_time = game().get_gametime();
> }
>
> - if (bo.stocklevel_ < 20)
> - prio = prio * 2;
> -
> - if (bo.total_count() == 0)
> - prio = prio * 5;
> + if (bo.stocklevel_ == 0)
> + prio *= 2;
>
> // to prevent to many quaries on one spot
> prio = prio - 50 * bf->producers_nearby_.at(bo.outputs_.at(0));
>
> + if (bf->near_border_)
> + prio = prio / 2;
> +
> + } else if (bo.is_hunter_) {
> + if (bf->critters_nearby_ < 5)
> + continue;
> +
> + if (new_buildings_stop_)
> + continue;
> +
> + prio +=
> + (bf->critters_nearby_ * 2) - 8 - 5 * bf->producers_nearby_.at(bo.outputs_.at(0));
> +
> + } else if (bo.is_fisher_) { // fisher
> +
> + // ~are fishes needed?
> + if (max_needed_preciousness == 0)
> + continue;
> +
> + if (bo.cnt_under_construction_ + bo.unoccupied_ > 0)
> + continue;
> +
> + if (bf->water_nearby_ < 5)
> + continue;
> +
> + // we use preciousness to allow atlanteans to build the fishers huts
> + // atlanteans have preciousness 4, other tribes 3
> + if (max_needed_preciousness < 4 && new_buildings_stop_)
> + continue;
> +
> + if (bo.stocklevel_time < game().get_gametime() - 5 * 1000) {
> + bo.stocklevel_ = get_stocklevel_by_hint(static_cast<size_t>(bo.production_hint_));
> + bo.stocklevel_time = game().get_gametime();
> + }
> +
> + if (bo.stocklevel_ > 50)
> + continue;
> +
> + if (bf->producers_nearby_.at(bo.outputs_.at(0)) >= 1)
> + continue;
> +
> + prio = bf->fish_nearby_ - new_buildings_stop_ * 15 * bo.total_count();
> +
> } else if (bo.production_hint_ >= 0) {
> // first setting targets (needed also for dismantling)
> if (bo.plants_trees_)
> @@ -1024,77 +1135,75 @@
> if ((bo.cnt_under_construction_ + bo.unoccupied_) > 1)
> continue;
>
> - // production hint (f.e. associate forester with logs)
> -
> - if (bo.need_water_ && bf->water_nearby_ < 5) // probably some of them needs water
> - continue;
> -
> if (bo.plants_trees_) { // RANGERS
>
> // if there are too many trees nearby
> - if (bf->trees_nearby_ > 25 && bo.total_count() >= 2)
> + if (bf->trees_nearby_ > 25 && bo.total_count() >= 1)
> continue;
>
> // sometimes all area is blocked by trees so this is to prevent this
> if (buildable_fields.size() < 4)
> continue;
>
> - // prevent too many rangers
> - if (bo.total_count() * 3 > static_cast<int32_t>(productionsites.size()))
> - continue;
> -
> - if (bo.stocklevel_time < game().get_gametime() - 5 * 1000) {
> - bo.stocklevel_ =
> - get_stocklevel_by_hint(static_cast<size_t>(bo.production_hint_));
> - bo.stocklevel_time = game().get_gametime();
> - }
> - prio = 0;
> - // if we need wood
> - if (bo.stocklevel_ < 50)
> - prio =
> - (50 - bo.stocklevel_) + bf->producers_nearby_.at(bo.production_hint_) * 5;
> -
> - // if we just need some rangers to be on safe side
> - if (bo.total_count() < 2)
> - prio += (60 - bf->trees_nearby_) * 3 +
> - bf->producers_nearby_.at(bo.production_hint_) * 5;
> - else if (bo.total_count() < bo.cnt_target_)
> - prio += 30 + bf->producers_nearby_.at(bo.production_hint_) * 5;
> -
> - } else if (gametime > kBaseInfrastructureTime &&
> - !new_buildings_stop_) { // gamekeepers or so
> - if (bo.stocklevel_time < game().get_gametime() - 5 * 1000) {
> - bo.stocklevel_ =
> - get_stocklevel_by_hint(static_cast<size_t>(bo.production_hint_));
> - bo.stocklevel_time = game().get_gametime();
> - }
> + if (bo.stocklevel_time < game().get_gametime() - 5 * 1000) {
> + bo.stocklevel_ =
> + get_stocklevel_by_hint(static_cast<size_t>(bo.production_hint_));
> + bo.stocklevel_time = game().get_gametime();
> + }
> +
> + if (bo.total_count() == 0)
> + prio = 200;
> + if (bo.total_count() > 2 * bo.cnt_target_)
> + continue;
> + // we can go above target if there is shortage of logs on stock
> + else if (bo.total_count() >= bo.cnt_target_ && bo.stocklevel_ > 40)
> + continue;
> +
> + // considering near trees and producers
> + prio += (30 - bf->trees_nearby_) * 2 +
> + bf->producers_nearby_.at(bo.production_hint_) * 5 -
> + new_buildings_stop_ * 15;
> +
> + // considering space consumers nearby
> + prio -= bf->space_consumers_nearby_ * 5;
> +
> + } else { // FISH BREEDERS and GAME KEEPERS
> + if (new_buildings_stop_ && bo.total_count() > 0)
> + continue;
>
> // especially for fish breeders
> + if (bo.need_water_ && bf->water_nearby_ < 8)
> + continue;
> if (bo.need_water_)
> - prio = bf->water_nearby_;
> -
> - if (bo.total_count() == 0)
> - prio += 5;
> -
> - if (bo.total_count() < bo.cnt_target_) {
> + prio += bf->water_nearby_ / 5;
> +
> + if (bo.total_count() > bo.cnt_target_)
> + continue;
> +
> + if (bo.stocklevel_time < game().get_gametime() - 5 * 1000) {
> + bo.stocklevel_ =
> + get_stocklevel_by_hint(static_cast<size_t>(bo.production_hint_));
> + bo.stocklevel_time = game().get_gametime();
> + }
> + if (bo.stocklevel_ > 50)
> + continue;
> +
> + if (bo.total_count() == 0 && gametime > 45 * 1000)
> + prio += 100 + bf->producers_nearby_.at(bo.production_hint_) * 10;
> + else if (bf->producers_nearby_.at(bo.production_hint_) == 0)
> + continue;
> + else
> prio += bf->producers_nearby_.at(bo.production_hint_) * 10;
> - prio += recalc_with_border_range(*bf, prio);
>
> - } else if (bo.stocklevel_ < 50 && !new_buildings_stop_) {
> - prio += bf->producers_nearby_.at(bo.production_hint_) * 5;
> - prio += recalc_with_border_range(*bf, prio); // only for not wood producers_
> - } else
> - continue;
> + if (bf->enemy_nearby_)
> + prio -= 10;
> }
>
> - if (prio <= 0)
> - continue;
> - } else if (bo.recruitment_ && gametime >
> - kBaseInfrastructureTime && !new_buildings_stop_) {
> + } else if (bo.recruitment_ && !new_buildings_stop_) {
> // this will depend on number of mines_ and productionsites
> if (static_cast<int32_t>((productionsites.size() + mines_.size()) / 30) >
> - bo.total_count() && bo.cnt_under_construction_ ==
> - 0)
> + bo.total_count() &&
> + bo.cnt_under_construction_ == 0)
> prio = 4 + bulgarian_constant;
> } else { // finally normal productionsites
> if (bo.production_hint_ >= 0)
> @@ -1103,102 +1212,58 @@
> if ((bo.cnt_under_construction_ + bo.unoccupied_) > 0)
> continue;
>
> - // if hunter and too little critters nearby skipping
> - if (bo.is_hunter_ && bf->critters_nearby_ < 5)
> - continue;
> - // similarly for fishers
> - if (bo.need_water_ && bf->fish_nearby_ <= 1)
> - continue;
> -
> - // first eliminate buildings needing water if there is short supplies
> - if (bo.need_water_ && bf->water_nearby_ < 4)
> - continue;
> -
> - if (bo.is_basic_ && bo.total_count() == 0)
> - prio = 150 + max_preciousness;
> - else if (bo.is_food_basic_ && game().get_gametime() >
> - kPrimaryFoodStartTime && bo.total_count() ==
> - 0) {
> - prio = 40 + max_preciousness;
> - } else if (game().get_gametime() <
> - kBaseInfrastructureTime ||
> - new_buildings_stop_) // leave 15 minutes for basic infrastructure only
> - continue;
> - else if ((bo.is_basic_ && bo.total_count() <=
> - 1) || (output_is_needed && bo.total_count() == 0))
> - prio = 80 + max_preciousness;
> - else if (bo.inputs_.size() == 0) {
> - bo.cnt_target_ =
> - 1 + static_cast<int32_t>(mines_.size() + productionsites.size()) / 8;
> -
> - if (bo.cnt_built_ >
> - bo.cnt_target_ &&
> - !(bo.space_consumer_ || bo.is_food_basic_)) // spaceconsumers_ and basic_s
> - // can be built more then target
> - continue;
> -
> - if (bo.stocklevel_time < game().get_gametime() - 5 * 1000) {
> - bo.stocklevel_ = get_stocklevel(bo);
> - bo.stocklevel_time = game().get_gametime();
> - }
> -
> - if (bo.stocklevel_ < 50) {
> - prio = max_preciousness + bulgarian_constant;
> -
> - if (bo.space_consumer_) // need to consider trees nearby
> - prio += 20 - (bf->trees_nearby_ / 3);
> -
> - if (!bo.space_consumer_)
> - prio -= bf->producers_nearby_.at(bo.outputs_.at(0)) *
> - 20; // leave some free space between them
> -
> - if (bo.cnt_built_ < 2)
> - prio += 5;
> -
> - prio = recalc_with_border_range(*bf, prio);
> -
> - if (bo.stocklevel_ < 20)
> - prio += 20 - bo.stocklevel_;
> -
> - // fisher
> - if (bo.need_water_) {
> - prio += bf->fish_nearby_ - 4;
> - }
> -
> - // hunters
> - if (bo.is_hunter_) {
> - prio += (bf->critters_nearby_ * 2) - 8;
> - }
> -
> - }
> - } else if (!bo.inputs_.empty()) {
> - // 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
> - && game().get_gametime() > 60 * 60 * 1000
> - && bo.desc->enhancement() != INVALID_INDEX
> - && !mines_.empty())
> - {
> - prio = max_preciousness + bulgarian_constant;
> - }
> - // if output is needed and there are no idle buildings
> - else if (output_is_needed) {
> - if (bo.cnt_built_ > 0 && bo.current_stats_ > 80) {
> - prio = max_preciousness + bulgarian_constant + 30;
> -
> - } else if (bo.cnt_built_ > 0 && bo.current_stats_ > 55) {
> - prio = max_preciousness + bulgarian_constant;
> -
> - }
> + if (bo.forced_after_ < gametime && bo.total_count() == 0) {
> + prio += 150;
> + } else if (bo.cnt_built_ == 1 && game().get_gametime() > 40 * 60 * 1000 &&
> + bo.desc->enhancement() != INVALID_INDEX && !mines_.empty()) {
> + prio += 10;
> + } else if (!output_is_needed) {
> + continue;
> + } else if (bo.cnt_built_ == 0 && game().get_gametime() > 40 * 60 * 1000) {
> + prio += bulgarian_constant;
> + } else if (bo.cnt_built_ > 1 && bo.current_stats_ > 98) {
> + prio -= bulgarian_constant * (new_buildings_stop_);
> + } else if (new_buildings_stop_)
> + continue;
> +
> + // we check separatelly buildings with no inputs and some inputs
> + if (bo.inputs_.empty()) {
> +
> + prio += max_needed_preciousness + bulgarian_constant;
> +
> + if (bo.space_consumer_) // need to consider trees nearby
> + prio += 20 - (bf->trees_nearby_ / 3);
> +
> + // we attempt to cluster space consumers together
> + if (bo.space_consumer_) // need to consider trees nearby
> + prio += bf->space_consumers_nearby_ * 2;
> +
> + if (bo.space_consumer_ && !bf->water_nearby_) // not close to water
> + prio += 1;
> +
> + if (bo.space_consumer_ &&
> + !bf->unowned_mines_pots_nearby_) // not close to mountains
> + prio += 1;
> +
> + if (!bo.space_consumer_)
> + prio -= bf->producers_nearby_.at(bo.outputs_.at(0)) *
> + 20; // leave some free space between them
> +
> + prio -= bf->space_consumers_nearby_ * 3;
> + }
> +
> + if (!bo.inputs_.empty()) {
> + if (bo.total_count() == 0)
> + prio += max_needed_preciousness + bulgarian_constant;
> + if (bo.cnt_built_ > 0 && bo.current_stats_ > 70) {
> + prio += max_needed_preciousness + bulgarian_constant - 3 +
> + (bo.current_stats_ - 70) / 5;
> }
> }
>
> if (prio <= 0)
> continue;
>
> - // then we consider borders and enemies nearby (if any)
> - prio = recalc_with_border_range(*bf, prio);
> -
> //+1 if any consumers_ are nearby
> consumers_nearby_count = 0;
>
> @@ -1211,33 +1276,39 @@
> } // production sites done
> else if (bo.type == BuildingObserver::MILITARYSITE) {
>
> - if (new_military_buildings_stop && !bf->enemy_nearby_)
> - continue;
> -
> - if (near_enemy_b_buildings_stop && bf->enemy_nearby_)
> + if (military_last_build_ > gametime - 10 * 1000)
> + continue;
> +
> + if (expansion_mode == kNoNewMilitary)
> + continue;
> +
> + if (expansion_mode == kDefenseOnly && !bf->enemy_nearby_)
> + continue;
> +
> + if (expansion_mode == kResourcesOrDefense &&
> + !(bf->enemy_nearby_ || bf->unowned_mines_pots_nearby_ || bf->stones_nearby_ ||
> + (water_is_important_ && bf->water_nearby_)))
> continue;
>
> if (bf->enemy_nearby_ && bo.fighting_type_)
> ; // it is ok, go on
> - else if (bf->unowned_mines_pots_nearby_ >
> - 0 && (bo.mountain_conqueror_ || bo.expansion_type_))
> + else if (bf->unowned_mines_pots_nearby_ > 2 &&
> + (bo.mountain_conqueror_ || bo.expansion_type_))
> ; // it is ok, go on
> - else if (bf->unowned_land_nearby_ && bo.expansion_type_) {
> - // decreasing probability for big buidlings
> - if (bo.desc->get_size() == 2 && gametime % 5 >= 1)
> + else if (bf->unowned_land_nearby_ && bo.expansion_type_ &&
> + num_milit_constructionsites <= 1) {
> + ; // we allow big buildings now
> + } else if (bf->unowned_land_nearby_ &&
> + bo.expansion_type_) { // decreasing probability for big buidlings
> + if (bo.desc->get_size() == 2 && gametime % 15 >= 1)
> continue;
> - if (bo.desc->get_size() == 3 && gametime % 15 >= 1)
> + if (bo.desc->get_size() == 3 && gametime % 40 >= 1)
> continue;
> }
> // it is ok, go on
> else
> continue; // the building is not suitable for situation
>
> - if (bo.desc->get_size() ==
> - 3 && game().get_gametime() <
> - 15 * 60 * 1000) // do not built fortresses in first half of hour of game
> - continue;
> -
> if (!bf->unowned_land_nearby_)
> continue;
>
> @@ -1245,17 +1316,24 @@
> if (!bf->enemy_nearby_ && bf->military_in_constr_nearby_ > 0)
> continue;
>
> - // here is to consider unowned potential mines
> - int32_t mines_spots_score = 0;
> - mines_spots_score = bf->unowned_mines_pots_nearby_;
> -
> - if (mines_spots_score > 0) {
> - mines_spots_score *= 4;
> - mines_spots_score += 8;
> - }
> -
> - prio = (bf->unowned_land_nearby_ - 4 + mines_spots_score + bf->stones_nearby_ / 2 +
> - bf->military_loneliness_ / 5 - 100 + military_boost); // * (1 + type);
> + // a boost to prevent an expansion halt
> + int32_t local_boost = 0;
> + if (num_milit_constructionsites == 1)
> + local_boost = 50;
> + if (num_milit_constructionsites == 0)
> + local_boost = 200;
> +
> + // if going after resources we do not consider unowned land
> + if (expansion_mode == kResourcesOrDefense && !bf->enemy_nearby_)
> + prio = (bf->unowned_mines_pots_nearby_ * mines_need_intensity_ / 10
> + + bf->stones_nearby_ / 2 +
> + bf->military_loneliness_ / 5 - 100 + local_boost +
> + water_is_important_ * bf->water_nearby_ * water_need_intensity_ / 12);
> + else
> + prio = (bf->unowned_land_nearby_ - 4 +
> + bf->unowned_mines_pots_nearby_ * mines_need_intensity_ / 10 +
> + bf->stones_nearby_ / 2 + bf->military_loneliness_ / 5 - 100 + local_boost +
> + water_is_important_ * bf->water_nearby_ * water_need_intensity_ / 12);
>
> if (bo.desc->get_size() < maxsize)
> prio = prio - 5; // penalty
> @@ -1274,13 +1352,17 @@
> // 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.
> - if ((static_cast<int32_t>(productionsites.size() + mines_.size())) / 35 >
> - static_cast<int32_t>(numof_warehouses_) && bo.cnt_under_construction_ ==
> - 0)
> - prio = 13;
> + if ((static_cast<int32_t>(productionsites.size() + mines_.size()) + 20) / 35 >
> + static_cast<int32_t>(numof_warehouses_) &&
> + bo.cnt_under_construction_ == 0)
> + prio = 20;
>
> // take care about borders and enemies
> - prio = recalc_with_border_range(*bf, prio);
> + if (bf->enemy_nearby_)
> + prio /= 2;
> +
> + if (bf->unowned_land_nearby_)
> + prio /= 2;
>
> // TODO(unknown): introduce check that there is no warehouse nearby
> // to prevent too close placing
> @@ -1292,13 +1374,16 @@
> continue;
>
> // build after 20 production sites and then after each 50 production site
> - if (static_cast<int32_t>((productionsites.size() + 30) / 50) >
> - bo.total_count() && bo.cnt_under_construction_ ==
> - 0)
> - prio = 4;
> + if (static_cast<int32_t>((productionsites.size() + 30) / 50) > bo.total_count() &&
> + bo.cnt_under_construction_ == 0)
> + prio = 4 + bulgarian_constant;
>
> // take care about borders and enemies
> - prio = recalc_with_border_range(*bf, prio);
> + if (bf->enemy_nearby_)
> + prio /= 2;
> +
> + if (bf->unowned_land_nearby_)
> + prio /= 2;
> }
>
> // think of space consuming buildings nearby like farms or vineyards
> @@ -1332,13 +1417,13 @@
> for (uint32_t i = 0; i < buildings_.size() && productionsites.size() > 8; ++i) {
> BuildingObserver& bo = buildings_.at(i);
>
> - if (!bo.mines_marble_ && gametime <
> - kBaseInfrastructureTime) // allow only stone mines_ in early stages of game
> - continue;
> -
> if (!bo.buildable(*player_) || bo.type != BuildingObserver::MINE)
> continue;
>
> + if (bo.prohibited_till_ > gametime) {
> + continue;
> + }
> +
> if (gametime - bo.construction_decision_time_ < kBuildingMinInterval)
> continue;
>
> @@ -1348,26 +1433,22 @@
> if ((bo.cnt_under_construction_ + bo.unoccupied_) > 0)
> continue;
>
> - // calculating actual amount of mined raw materials
> - if (bo.stocklevel_time < game().get_gametime() - 5 * 1000) {
> - bo.stocklevel_ = get_stocklevel(bo);
> - bo.stocklevel_time = game().get_gametime();
> - }
> -
> - // Only try to build mines_ that produce needed wares.
> - if (((bo.cnt_built_ - bo.unoccupied_) > 0 && bo.current_stats_ < 20) || bo.stocklevel_ >
> - 40 + static_cast<uint32_t>(bo.mines_marble_) * 30) {
> -
> - continue;
> - }
> + // testing if building's output is needed
> + check_ware_needeness(
> + bo, &output_is_needed, &max_preciousness, &max_needed_preciousness);
> +
> + if (!output_is_needed && bo.total_count() > 0)
> + continue;
> +
> + // if current one(s) are performing badly
> + if (bo.total_count() >= 1 && bo.current_stats_ < 50)
> + continue;
>
> // this is penalty if there are existing mines too close
> // it is treated as multiplicator for count of near mines
> uint32_t nearness_penalty = 0;
> if ((bo.cnt_built_ + bo.cnt_under_construction_) == 0)
> nearness_penalty = 0;
> - else if (bo.mines_marble_)
> - nearness_penalty = 7;
> else
> nearness_penalty = 10;
>
> @@ -1404,13 +1485,15 @@
> continue;
> }
>
> + // Prefer road side fields
> + prio += (*j)->preferred_ ? 1 : 0;
> +
> if (prio > proposed_priority) {
> // proposed_building = bo.id;
> best_building = &bo;
> proposed_priority = prio;
> proposed_coords = (*j)->coords;
> mine = true;
> -
> }
> } // end of evaluation of field
> }
> @@ -1429,22 +1512,36 @@
> game().map().get_fcoords(proposed_coords), game().get_gametime() + 120000); // two minutes
> blocked_fields.push_back(blocked);
>
> - // if space consumer we block also nearby fields
> - if (best_building->space_consumer_ && !best_building->plants_trees_) {
> + // we block also nearby fields
> + // if farms and so on, for quite a long time
> + // if military sites only for short time for AI can update information on near buildable fields
> + if ((best_building->space_consumer_ && !best_building->plants_trees_) ||
> + best_building->type == BuildingObserver::MILITARYSITE) {
> + uint32_t block_time = 0;
> + uint32_t block_area = 0;
> + if (best_building->space_consumer_) {
> + block_time = 45 * 60 * 1000;
> + block_area = 3;
> + } else { // militray buildings for a very short time
> + block_time = 25 * 1000;
> + block_area = 6;
> + }
> Map& map = game().map();
>
> - MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(proposed_coords), 3));
> + MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(proposed_coords), block_area));
> do {
> BlockedField blocked2(
> - map.get_fcoords(*(mr.location().field)), game().get_gametime() + 45 * 60 * 1000);
> + map.get_fcoords(*(mr.location().field)), game().get_gametime() + block_time);
> blocked_fields.push_back(blocked2);
> } while (mr.advance(map));
> }
>
> if (!(best_building->type == BuildingObserver::MILITARYSITE))
> best_building->construction_decision_time_ = gametime;
> - else // very ugly hack here
> + else { // very ugly hack here
> + military_last_build_ = gametime;
> best_building->construction_decision_time_ = gametime - kBuildingMinInterval / 2;
> + }
>
> // set the type of update that is needed
> if (mine) {
> @@ -1456,101 +1553,12 @@
> 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.
> - */
> -bool DefaultAI::construct_roads(int32_t gametime) {
> - if (economies.size() < 2) {
> - // only one economy, no need for new roads
> - return false;
> - }
> -
> - uint32_t economies_to_connect = 0;
> - EconomyObserver* eo_to_connect = economies.front(); // dummy initialisation
> -
> - // fetch first two economies that might be connectable
> - for (std::list<EconomyObserver*>::iterator i = economies.begin();
> - economies_to_connect < 2 && i != economies.end();
> - ++i)
> -
> - // Do not try to connect economies that already failed in last time.
> - if ((*i)->next_connection_try <= gametime) {
> - if (economies_to_connect == 1)
> - eo_to_connect = *i;
> -
> - ++economies_to_connect;
> - }
> -
> - // No need to connect, if only one economy
> - if (economies_to_connect < 2)
> - return false;
> -
> - if (eo_to_connect->flags.empty())
> - return check_economies();
> -
> - // Check if the flag is still there and if not care about that situation
> - if (!eo_to_connect->flags.front()) {
> - eo_to_connect->flags.pop_front();
> - return check_economies();
> - }
> -
> - // Try to connect - this should work fine as in nearly all cases we simply
> - // connect a constructionsite
> - bool done = connect_flag_to_another_economy(*eo_to_connect->flags.front());
> - eo_to_connect->flags.push_back(eo_to_connect->flags.front());
> - eo_to_connect->flags.pop_front();
> -
> - if (done) {
> - eo_to_connect->failed_connection_tries = 0;
> - return true;
> - }
> -
> - // If the economy consists of just one constructionsite, and the defaultAI
> - // failed more than 4 times to connect, we remove the constructionsite
> - if (eo_to_connect->failed_connection_tries > 3 && eo_to_connect->flags.size() == 1) {
> - Building* bld = eo_to_connect->flags.front()->get_building();
> -
> - if (bld) {
> - BuildingObserver& bo = get_building_observer(bld->descr().name().c_str());
> -
> - if (bo.type == BuildingObserver::CONSTRUCTIONSITE) {
> - game().send_player_bulldoze(*const_cast<Flag*>(eo_to_connect->flags.front()));
> - eo_to_connect->flags.pop_front();
> - // Block the field at constructionsites coords for 5 minutes
> - // against new construction tries.
> - BlockedField blocked(
> - game().map().get_fcoords(bld->get_position()), game().get_gametime() + 300000);
> - blocked_fields.push_back(blocked);
> - }
> - }
> - }
> -
> - // Unable to connect, so we let this economy wait for 30 seconds.
> - eo_to_connect->next_connection_try = gametime + 30000;
> - ++eo_to_connect->failed_connection_tries;
> - return false;
> -}
> -
> // improves current road system
> bool DefaultAI::improve_roads(int32_t gametime) {
> - // Remove flags of dead end roads, as long as no more wares are stored on them
> - for (EconomyObserver* eco_obs : economies) {
> - for (std::list<Flag const*>::iterator flag_iter = eco_obs->flags.begin();
> - flag_iter != eco_obs->flags.end();
> - ++flag_iter) {
> - if ((*flag_iter)->is_dead_end() && (*flag_iter)->current_wares() == 0) {
> - game().send_player_bulldoze(*const_cast<Flag*>(*flag_iter));
> - flag_iter = eco_obs->flags.erase(flag_iter);
> - return true;
> - }
> - }
> - }
>
> - // force a split on roads that are longer than 3 parts
> - // actually we do not care for loss of building capabilities - normal maps
> - // should have enough space and the computer can expand it's territory.
> - if (!roads.empty()) {
> + // first force a split on roads that are longer than 3 parts
> + // with exemption when there is too few building spots
> + if (spots_ > 20 && !roads.empty()) {
> const Path& path = roads.front()->get_path();
>
> if (path.get_nsteps() > 3) {
> @@ -1584,128 +1592,253 @@
>
> roads.push_back(roads.front());
> roads.pop_front();
> - }
> -
> - if (!economies.empty() && inhibit_road_building_ <= gametime) {
> - EconomyObserver* eco = economies.front();
> -
> - if (!eco->flags.empty()) {
> - bool finish = false;
> - const Flag& flag = *eco->flags.front();
> -
> - // try to connect to another economy
> - if (economies.size() > 1)
> - finish = connect_flag_to_another_economy(flag);
> -
> - // try to improve the roads at this flag
> - // TODO(unknown): do this only on useful places - the attempt below
> - // unfortunatey did not work as it should...
> - // if the flag is full of wares or if it is not yet a fork.
> - if (!finish) //&& (!flag.has_capacity() || flag.nr_of_roads() < 3))
> - finish = improve_transportation_ways(flag);
> -
> - // cycle through flags one at a time
> - eco->flags.push_back(eco->flags.front());
> - eco->flags.pop_front();
> - // and cycle through economies
> - economies.push_back(eco);
> - economies.pop_front();
> - return finish;
> - } else
> - // If the economy has no flag, the observers need to be updated.
> - return check_economies();
> - }
> -
> - return false;
> -}
> -
> -// connects a specific flag to another economy
> -bool DefaultAI::connect_flag_to_another_economy(const Flag& flag) {
> +
> + // occasionaly we test if the road can be dismounted
> + if (gametime % 25 == 0) {
> + const Road& road = *roads.front();
> + if (abundant_road_test(*const_cast<Road*>(&road))) {
> + game().send_player_bulldoze(*const_cast<Road*>(&road));
> + return true;
> + }
> + }
> + }
> +
> + if (inhibit_road_building_ >= gametime)
> + return false;
> +
> + // now we rotate economies and flags to get one flag to go on with
> + if (economies.size() == 0)
> + return check_economies();
> +
> + if (economies.size() >= 2) { // rotating economies
> + economies.push_back(economies.front());
> + economies.pop_front();
> + }
> +
> + EconomyObserver* eco = economies.front();
> + if (eco->flags.empty())
> + return check_economies();
> + if (eco->flags.size() > 1) {
> + eco->flags.push_back(eco->flags.front());
> + eco->flags.pop_front();
> + }
> +
> + const Flag& flag = *eco->flags.front();
> +
> + // now we test if it is dead end flag, if yes, destroying it
> + if (flag.is_dead_end() && flag.current_wares() == 0) {
> + game().send_player_bulldoze(*const_cast<Flag*>(&flag));
> + eco->flags.pop_front();
> + return true;
> + }
> +
> + // if this is end flag (or sole building) or just randomly
> + if (flag.nr_of_roads() <= 1 || gametime % 200 == 0) {
> + create_shortcut_road(flag, 13, 20);
> + inhibit_road_building_ = gametime + 800;
> + }
> + // this is when a flag is full
> + else if (flag.current_wares() > 6 && gametime % 10 == 0) {
> + create_shortcut_road(flag, 9, 0);
> + inhibit_road_building_ = gametime + 400;
> + }
> +
> + return false;
> +}
> +
> +// identifying roads where wares are not intensively transported
> +// and that have bypasses not much longer
> +bool DefaultAI::abundant_road_test(const Road& road) {
> +
> + Flag& roadstartflag = road.get_flag(Road::FlagStart);
> + Flag& roadendflag = road.get_flag(Road::FlagEnd);
> +
> + if (roadstartflag.current_wares() > 0 || roadendflag.current_wares() > 0)
> + return false;
> +
> + std::priority_queue<NearFlag> queue;
> + // only used to collect flags reachable walking over roads
> + std::vector<NearFlag> reachableflags;
> + queue.push(NearFlag(roadstartflag, 0, 0));
> + uint8_t pathcounts = 0;
> + uint8_t checkradius = 8;
> + Map& map = game().map();
> +
> + // algorithm to walk on roads
> + while (!queue.empty()) {
> +
> + // testing if we stand on the roadendflag
> + // if is is for first time, just go on,
> + // if second time, the goal is met, function returns true
> + // NOCOM: what is the right way to compare the flags?
Is this still NOCOM?
> + if (roadendflag.get_position().x == queue.top().flag->get_position().x &&
> + roadendflag.get_position().y == queue.top().flag->get_position().y) {
> + pathcounts += 1;
> + if (pathcounts > 1) {
> + // OK, this is a second route how to get to roadendflag
> + return true;
> + }
> + queue.pop();
> + continue;
> + }
> +
> + std::vector<NearFlag>::iterator f =
> + find(reachableflags.begin(), reachableflags.end(), queue.top().flag);
> +
> + if (f != reachableflags.end()) {
> + queue.pop();
> + continue;
> + }
> +
> + reachableflags.push_back(queue.top());
> + queue.pop();
> + NearFlag& nf = reachableflags.back();
> +
> + for (uint8_t i = 1; i <= 6; ++i) {
> + Road* const near_road = nf.flag->get_road(i);
> +
> + if (!near_road)
> + continue;
> +
> + Flag* endflag = &near_road->get_flag(Road::FlagStart);
> +
> + if (endflag == nf.flag)
> + endflag = &near_road->get_flag(Road::FlagEnd);
> +
> + int32_t dist = map.calc_distance(roadstartflag.get_position(), endflag->get_position());
> +
> + if (dist > checkradius) // out of range of interest
> + continue;
> +
> + queue.push(NearFlag(*endflag, 0, dist));
> + }
> + }
> + return false;
> +}
> +
> +// trying to connect the flag to another one, be it from own economy
> +// or other economy
> +bool DefaultAI::create_shortcut_road(const Flag& flag, uint16_t checkradius, uint16_t minred) {
> +
> + // Increasing the failed_connection_tries counter
> + // At the same time it indicates a time an economy is without a warehouse
> + EconomyObserver* eco = get_economy_observer(flag.economy());
> + if (flag.get_economy()->warehouses().empty()) {
> + eco->failed_connection_tries += 1;
> + } else {
> + eco->failed_connection_tries = 0;
> + }
> +
> + // explanation for 'eco->flags.size() * eco->flags.size()'
> + // The AI is able to dismantle whole economy without warehouse as soon as single
> + // building not connected anywhere. But so fast dismantling is not deserved (probably)
> + // so the bigger economy the longer it takes to be dismantled
> + if (eco->failed_connection_tries > 3 + eco->flags.size() * eco->flags.size()) {
> +
> + Building* bld = flag.get_building();
> +
> + if (bld) {
> + // first we block the field for 15 minutes, probably it is not good place to build a
> + // building on
> + BlockedField blocked(
> + game().map().get_fcoords(bld->get_position()), game().get_gametime() + 15 * 60 * 1000);
> + blocked_fields.push_back(blocked);
> + eco->flags.remove(&flag);
> + game().send_player_bulldoze(*const_cast<Flag*>(&flag));
> + }
> + return true;
> + }
> +
> + Map& map = game().map();
> +
> + // 1. first we collect all reachange points
> + std::vector<NearFlag> nearflags;
> + std::unordered_set<int32_t> lookuptable;
> +
> FindNodeWithFlagOrRoad functor;
> CheckStepRoadAI check(player_, MOVECAPS_WALK, true);
> std::vector<Coords> reachable;
> - // first look for possible destinations
> - functor.economy = flag.get_economy();
> - Map& map = game().map();
> +
> + // vector reachable now contains all suitable fields
> map.find_reachable_fields(
> - Area<FCoords>(map.get_fcoords(flag.get_position()), 16), &reachable, check, functor);
> + Area<FCoords>(map.get_fcoords(flag.get_position()), checkradius), &reachable, check, functor);
>
> - if (reachable.empty())
> + // Does this make sense?
Turn this into a TODO comment?
> + if (reachable.empty()) {
> return false;
> + }
>
> - // then choose the one with the shortest path
> - Path* path = new Path();
> - bool found = false;
> - check.set_openend(false);
> - Coords closest;
> for (const Coords& reachable_coords : reachable) {
> - Path* path2 = new Path();
> -
> - if (map.findpath(flag.get_position(), reachable_coords, 0, *path2, check) >= 0) {
> - if (!found || path->get_nsteps() > path2->get_nsteps()) {
> - delete path;
> - path = path2;
> - path2 = nullptr;
> - closest = reachable_coords;
> - found = true;
> - }
> - }
> -
> - delete path2;
> - }
> -
> - if (found) {
> - // if we join a road and there is no flag yet, build one
> - if (dynamic_cast<const Road*>(map[closest].get_immovable()))
> - game().send_player_build_flag(player_number(), closest);
> -
> - // and finally build the road
> - game().send_player_build_road(player_number(), *path);
> - return true;
> - } else {
> - delete path;
> - return false;
> - }
> -}
> -
> -// adds alternative ways to already existing ones
> -bool DefaultAI::improve_transportation_ways(const Flag& flag) {
> - // First of all try to remove old building flags to clean up the road web if possible
> - for (std::list<Widelands::Coords>::iterator coords_iter = flags_to_be_removed.begin();
> - coords_iter != flags_to_be_removed.end();
> - ++coords_iter) {
> - // Maybe the flag was already removed?
> - FCoords f = game().map().get_fcoords(*(coords_iter));
> -
> - if (upcast(Flag, other_flag, f.field->get_immovable())) {
> - // Check if building is dismantled, but don't waste precious wares
> - if (!other_flag->get_building() && other_flag->current_wares() == 0) {
> - game().send_player_bulldoze(*other_flag);
> - flags_to_be_removed.erase(coords_iter);
> - break;
> - }
> - } else {
> - flags_to_be_removed.erase(coords_iter);
> - break;
> - }
> - }
> +
> + // first make sure there is an immovable (shold be, but still)
> + if (upcast(PlayerImmovable const, player_immovable, map[reachable_coords].get_immovable())) {
> +
> + // if it is the road, make a flag there
> + if (dynamic_cast<const Road*>(map[reachable_coords].get_immovable()))
> + game().send_player_build_flag(player_number(), reachable_coords);
> +
> + // do not go on if it is not a flag
> + if (!dynamic_cast<const Flag*>(map[reachable_coords].get_immovable()))
> + continue;
> +
> + // testing if a flag/road's economy has a warehouse, if not we are not
> + // interested to connect to it
> + if (player_immovable->economy().warehouses().size() == 0) {
> + continue;
> + }
> +
> + // now make sure that this field has not been processed yet
> + const int32_t hash = reachable_coords.x * 1234 + reachable_coords.y;
> + if (lookuptable.count(hash) == 0) {
> + lookuptable.insert(hash);
> +
> + // adding flag into NearFlags if road is possible
> + Path* path2 = new Path();
> +
> + if (map.findpath(flag.get_position(), reachable_coords, 0, *path2, check) >= 0) {
> +
> + // path is possible, but for now we presume connection
> + //'walking on existing roads' is not possible
> + // so we assign 'virtual distance'
> + int32_t virtual_distance = 0;
> + // the same economy, but connection not spotted above via "walking on roads"
> + // algorithm
> + if (player_immovable->get_economy() == flag.get_economy())
> + virtual_distance = 50;
> + else // and now different economies
> + virtual_distance = 100;
> +
> + // distance as the crow flies
> + const int32_t dist = map.calc_distance(flag.get_position(), reachable_coords);
> +
> + nearflags.push_back(
> + NearFlag(*dynamic_cast<const Flag*>(map[reachable_coords].get_immovable()),
> + virtual_distance,
> + dist));
> + }
> + delete path2;
> + }
> + }
> + }
> +
> + // now we walk over roads and if field is reachable by roads, we change distance asigned before
> std::priority_queue<NearFlag> queue;
> - std::vector<NearFlag> nearflags;
> + std::vector<NearFlag> nearflags_tmp; // only used to collect flags reachable walk over roads
> queue.push(NearFlag(flag, 0, 0));
> - Map& map = game().map();
>
> + // algorithm to walk on roads
> while (!queue.empty()) {
> std::vector<NearFlag>::iterator f =
> - find(nearflags.begin(), nearflags.end(), queue.top().flag);
> + find(nearflags_tmp.begin(), nearflags_tmp.end(), queue.top().flag);
>
> - if (f != nearflags.end()) {
> + if (f != nearflags_tmp.end()) {
> queue.pop();
> continue;
> }
>
> - nearflags.push_back(queue.top());
> + nearflags_tmp.push_back(queue.top());
> queue.pop();
> - NearFlag& nf = nearflags.back();
> + NearFlag& nf = nearflags_tmp.back();
>
> for (uint8_t i = 1; i <= 6; ++i) {
> Road* const road = nf.flag->get_road(i);
> @@ -1720,32 +1853,87 @@
>
> int32_t dist = map.calc_distance(flag.get_position(), endflag->get_position());
>
> - if (dist > 12) // out of range
> + if (dist > checkradius) // out of range of interest
> continue;
>
> queue.push(NearFlag(*endflag, nf.cost_ + road->get_path().get_nsteps(), dist));
> }
> }
>
> - std::sort(nearflags.begin(), nearflags.end(), CompareDistance());
> - CheckStepRoadAI check(player_, MOVECAPS_WALK, false);
> -
> - for (uint32_t i = 1; i < nearflags.size(); ++i) {
> + // iterating over nearflags_tmp, each item in nearflags_tmp should be contained also in nearflags
> + // so for each corresponding field in nearflags we update "cost" (distance on existing roads)
> + // to actual value
> + for (std::vector<NearFlag>::iterator nf_walk_it = nearflags_tmp.begin();
> + nf_walk_it != nearflags_tmp.end();
> + ++nf_walk_it) {
> + int32_t const hash_walk =
> + nf_walk_it->flag->get_position().x * 1234 + nf_walk_it->flag->get_position().y;
> + if (lookuptable.count(hash_walk) > 0) {
> + // iterting over nearflags
> + for (std::vector<NearFlag>::iterator nf_it = nearflags.begin(); nf_it != nearflags.end();
> + ++nf_it) {
> + int32_t const hash =
> + nf_it->flag->get_position().x * 1234 + nf_it->flag->get_position().y;
> + if (hash == hash_walk) {
> + // decreasing "cost" (of walking via roads)
> + if (nf_it->cost_ > nf_walk_it->cost_) {
> + nf_it->cost_ = nf_walk_it->cost_;
> + }
> + }
> + }
> + }
> + }
> +
> + // ordering nearflags
> + std::sort(nearflags.begin(), nearflags.end(), CompareShortening());
> +
> + // this is just a random number, will be used later
> + int32_t random_gametime = game().get_gametime();
> +
> + // the problem here is that send_player_build_road() does not return succes/failed
> + // if it did, we would just test the first nearflag, then go on with further flags until
> + // a road is built or nearflags are exhausted
> + // but now we must just randomly pick one of nearflags
> + // probabililty of picking decreases with position in nearflags
> + for (uint32_t i = 0; i < nearflags.size() && i < 10; ++i) {
> NearFlag& nf = nearflags.at(i);
>
> - if (2 * nf.distance_ + 2 < nf.cost_) {
> + // terminating looping if reduction is too low (nearflags are sorted by reduction)
> + if ((nf.cost_ - nf.distance_) < minred) {
> + return false;
> + }
> +
> + // testing the nearflag
> + // usually we allow connecting only if both flags are closer then 'checkradius-2'
> + // with exeption the flag belongs to a small economy (typically a new building not connected
> + // yet)
> + if ((nf.cost_ - nf.distance_) >= minred && nf.distance_ >= 2 &&
> + nf.distance_ < checkradius - 2) {
> +
> + // sometimes the shortest road is not the buildable, even if map.findpath claims so
> + // best so we add some randomness
> + random_gametime /= 3;
> + if (random_gametime % 3 > 1) {
> + continue;
> + }
> +
> Path& path = *new Path();
>
> - if (map.findpath(flag.get_position(), nf.flag->get_position(), 0, path, check) >=
> - 0 && static_cast<int32_t>(2 * path.get_nsteps() + 2) < nf.cost_) {
> - game().send_player_build_road(player_number(), path);
> - return true;
> + // value of pathcost is not important, it just indicates, that the path can be built
> + const int32_t pathcost =
> + map.findpath(flag.get_position(), nf.flag->get_position(), 0, path, check);
> +
> + if (pathcost >= 0) {
> + if (static_cast<int32_t>(nf.cost_ - path.get_nsteps()) > minred) {
> + game().send_player_build_road(player_number(), path);
> + return true;
> + }
> }
> -
> delete &path;
> }
> }
>
> + // if all possible roads skipped
> return false;
> }
>
> @@ -1763,8 +1951,8 @@
> }
>
> for (std::list<EconomyObserver*>::iterator obs_iter = economies.begin();
> - obs_iter != economies.end();
> - ++obs_iter) {
> + obs_iter != economies.end();
> + ++obs_iter) {
> // check if any flag has changed its economy
> std::list<Flag const*>& fl = (*obs_iter)->flags;
>
> @@ -1812,10 +2000,15 @@
> site.unoccupied_till_ = game().get_gametime();
> }
>
> + // do not dismantle or upgrade the same type of building too soon - to give some time to update
> + // statistics
> + if (site.bo->last_dismantle_time_ > game().get_gametime() - 30 * 1000)
> + return false;
> +
> // Get max radius of recursive workarea
> WorkareaInfo::size_type radius = 0;
> const WorkareaInfo& workarea_info = site.bo->desc->m_workarea_info;
> - for (const std::pair<uint32_t, std::set<std::string> > & temp_info : workarea_info) {
> + for (const std::pair<uint32_t, std::set<std::string>>& temp_info : workarea_info) {
> if (radius < temp_info.first) {
> radius = temp_info.first;
> }
> @@ -1823,54 +2016,128 @@
>
> Map& map = game().map();
>
> - // do not dismantle same type of building too soon - to give some time to update statistics
> - // yes it interferes with building updates, but not big problem here
> - if (site.bo->last_dismantle_time_ > game().get_gametime() - 30 * 1000)
> - return false;
> + // first we try to upgrade
> + // Upgrading policy
> + // a) if there are two buildings and none enhanced and there are workers
> + // available, one is to be enhanced
> + // b) if there are two buildings
> + // statistics percents are decisive
> + const BuildingIndex enhancement = site.site->descr().enhancement();
> + if (enhancement != INVALID_INDEX && (site.bo->cnt_built_ - site.bo->unoccupied_) > 1) {
> +
> + BuildingIndex enbld = INVALID_INDEX; // to get rid of this
> + BuildingObserver* bestbld = nullptr;
> +
> + // Only enhance buildings that are allowed (scenario mode)
> + // do not do decisions to fast
> + if (player_->is_building_type_allowed(enhancement)) {
> +
> + const BuildingDescr& bld = *tribe_->get_building_descr(enhancement);
> + BuildingObserver& en_bo = get_building_observer(bld.name().c_str());
> +
> + if (gametime - en_bo.construction_decision_time_ >= kBuildingMinInterval &&
> + (en_bo.cnt_under_construction_ + en_bo.unoccupied_) == 0) {
> +
> + // don't upgrade without workers
> + if (site.site->has_workers(enhancement, game())) {
> +
> + // forcing first upgrade
> + if (en_bo.cnt_built_ == 0 && !mines_.empty()) {
> + enbld = enhancement;
> + bestbld = &en_bo;
> + }
> +
> + // if the decision was not made yet, consider normal upgrade
> + if (enbld == INVALID_INDEX) {
> + // compare the performance %
> + if (static_cast<int32_t>(en_bo.current_stats_) -
> + static_cast<int32_t>(site.bo->current_stats_) >
> + 20) {
> +
> + enbld = enhancement;
> + bestbld = &en_bo;
> + }
> + }
> + }
> + }
> +
> + // Enhance if enhanced building is useful
> + // additional: we dont want to lose the old building
> + if (enbld != INVALID_INDEX) {
> + game().send_player_enhance_building(*site.site, enbld);
> + bestbld->construction_decision_time_ = gametime;
> +
> + return true;
> + }
> + }
> + }
>
> // Lumberjack / Woodcutter handling
> if (site.bo->need_trees_) {
> - if (map.find_immovables(Area<FCoords>(map.get_fcoords(site.site->get_position()), radius),
> - nullptr,
> - FindImmovableAttribute(MapObjectDescr::get_attribute_id("tree"))) <
> - 6) {
> - // 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 player_s can easily run out of wood if this check
> - // is not done.
> - if (site.bo->cnt_built_ <=
> - 3 + static_cast<int32_t>(mines_.size() + productionsites.size()) / 20) {
> -
> - return false;
> - }
> -
> - if (site.site->get_statistics_percent() <= 20) {
> - // 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.
> - // log (" TDEBUG: dismantling lumberjacks hut\n");
> - site.bo->last_dismantle_time_ = game().get_gametime();
> - flags_to_be_removed.push_back(site.site->base_flag().get_position());
> - game().send_player_dismantle(*site.site);
> -
> - return true;
> - }
> - return false;
> - }
> - return false;
> +
> + // Do not destruct the last few lumberjacks
> + if (site.bo->cnt_built_ <= site.bo->cnt_target_) {
> + return false;
> + }
> +
> + if (site.site->get_statistics_percent() > 20)
> + return false;
> +
> + const uint32_t remaining_trees =
> + map.find_immovables(Area<FCoords>(map.get_fcoords(site.site->get_position()), radius),
> + nullptr,
> + FindImmovableAttribute(MapObjectDescr::get_attribute_id("tree")));
> +
> + // do not dismantle if there are some trees remaining
> + if (remaining_trees > 5)
> + return false;
> +
> + if (site.bo->stocklevel_time < game().get_gametime() - 10 * 1000) {
> + site.bo->stocklevel_ = get_stocklevel(*site.bo);
> + site.bo->stocklevel_time = game().get_gametime();
> + }
> +
> + // if we need wood badly
> + if (remaining_trees > 0 && site.bo->stocklevel_ <= 50)
> + return false;
> +
> + // so finally we dismantle the lumberjac
lumberjack
> + site.bo->last_dismantle_time_ = game().get_gametime();
> + flags_to_be_removed.push_back(site.site->base_flag().get_position());
> + game().send_player_dismantle(*site.site);
> +
> + return true;
> }
>
> // Wells handling
> if (site.bo->mines_water_) {
> - if (site.unoccupied_till_ + 6 * 60 * 1000 < game().get_gametime()
> - && site.site->get_statistics_percent() ==
> - 0) {
> - site.bo->last_dismantle_time_ = game().get_gametime();
> - flags_to_be_removed.push_back(site.site->base_flag().get_position());
> - game().send_player_dismantle(*site.site);
> -
> - return true;
> - }
> + if (site.unoccupied_till_ + 6 * 60 * 1000 < game().get_gametime() &&
> + site.site->get_statistics_percent() == 0) {
> + site.bo->last_dismantle_time_ = game().get_gametime();
> + flags_to_be_removed.push_back(site.site->base_flag().get_position());
> + game().send_player_dismantle(*site.site);
> +
> + return true;
> + }
> +
> + // do not consider dismantling if we are under target
> + if (site.bo->last_dismantle_time_ + 90 * 1000 > game().get_gametime())
> + return false;
> +
> + // now we test the stocklevel and dismantle the well if we have enough water
> + // but first we make sure we do not dismantle a well too soon
> + // after dismantling previous one
> + if (site.bo->stocklevel_time < game().get_gametime() - 5 * 1000) {
> + site.bo->stocklevel_ = get_stocklevel(*site.bo);
> + site.bo->stocklevel_time = game().get_gametime();
> + }
> + if (site.bo->stocklevel_ > 250) { // dismantle
> + site.bo->last_dismantle_time_ = game().get_gametime();
> + flags_to_be_removed.push_back(site.site->base_flag().get_position());
> + game().send_player_dismantle(*site.site);
> + return true;
> + }
> +
> return false;
> }
>
> @@ -1880,7 +2147,8 @@
> if (map.find_immovables(
> Area<FCoords>(map.get_fcoords(site.site->get_position()), radius),
> nullptr,
> - FindImmovableAttribute(MapObjectDescr::get_attribute_id("granite"))) == 0) {
> +
> + FindImmovableAttribute(MapObjectDescr::get_attribute_id("granite"))) == 0) {
> // 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.
> @@ -1889,9 +2157,8 @@
> return true;
> }
>
> - if (site.unoccupied_till_ + 6 * 60 * 1000 < game().get_gametime()
> - && site.site->get_statistics_percent() ==
> - 0) {
> + if (site.unoccupied_till_ + 6 * 60 * 1000 < game().get_gametime() &&
> + site.site->get_statistics_percent() == 0) {
> // it is possible that there are stones but quary is not able to mine them
> site.bo->last_dismantle_time_ = game().get_gametime();
> flags_to_be_removed.push_back(site.site->base_flag().get_position());
> @@ -1905,13 +2172,14 @@
>
> // All other SPACE_CONSUMERS without input and above target_count
> if (site.bo->inputs_.empty() // does not consume anything
> - && site.bo->production_hint_ ==
> - -1 // not a renewing building (forester...)
> - && site.unoccupied_till_ +
> - 10 * 60 * 1000 <
> - game().get_gametime() // > 10 minutes old
> - && site.site->can_start_working() // building is occupied
> - && site.bo->space_consumer_ && !site.bo->plants_trees_) {
> + &&
> + site.bo->production_hint_ == -1 // not a renewing building (forester...)
> + &&
> + site.unoccupied_till_ + 10 * 60 * 1000 < game().get_gametime() // > 10 minutes old
> + &&
> + site.site->can_start_working() // building is occupied
> + &&
> + site.bo->space_consumer_ && !site.bo->plants_trees_) {
>
> // if we have more buildings then target
> if (site.bo->cnt_built_ > site.bo->cnt_target_) {
> @@ -1920,8 +2188,8 @@
> site.bo->stocklevel_time = game().get_gametime();
> }
>
> - if (site.site->get_statistics_percent()<
> - 30 && site.bo->stocklevel_> 100) { // production stats == 0%
> + if (site.site->get_statistics_percent() < 30 &&
> + site.bo->stocklevel_ > 100) { // production stats == 0%
> site.bo->last_dismantle_time_ = game().get_gametime();
> flags_to_be_removed.push_back(site.site->base_flag().get_position());
> game().send_player_dismantle(*site.site);
> @@ -1929,8 +2197,8 @@
> }
> }
>
> - // regardless of count of sites a building can be dismanteld if it performs too bad
> - if (site.site->get_statistics_percent() <= 10) {
> + // a building can be dismanteld if it performs too bad, if it is not the last one
dismantled
> + if (site.site->get_statistics_percent() <= 10 && site.bo->cnt_built_ > 1) {
>
> flags_to_be_removed.push_back(site.site->base_flag().get_position());
> game().send_player_dismantle(*site.site);
> @@ -1941,12 +2209,11 @@
> }
>
> // buildings with inputs_, checking if we can a dismantle some due to low performance
> - if (!site.bo->inputs_.empty() && (site.bo->cnt_built_ - site.bo->unoccupied_) >=
> - 3 && site.site->can_start_working() && site.site->get_statistics_percent() <
> - 20 && // statistics for the building
> - site.bo->current_stats_<30 && // overall statistics
> - (game().get_gametime() - site.unoccupied_till_)> 10 *
> - 60 * 1000) {
> + if (!site.bo->inputs_.empty() && (site.bo->cnt_built_ - site.bo->unoccupied_) >= 3 &&
> + site.site->can_start_working() &&
> + site.site->get_statistics_percent() < 20 && // statistics for the building
> + site.bo->current_stats_ < 30 && // overall statistics
> + (game().get_gametime() - site.unoccupied_till_) > 10 * 60 * 1000) {
>
> site.bo->last_dismantle_time_ = game().get_gametime();
> flags_to_be_removed.push_back(site.site->base_flag().get_position());
> @@ -1956,13 +2223,11 @@
>
> // remaining buildings without inputs and not supporting ones (fishers only left probably and
> // huters)
> - // first if is only for log, second one is "executive"
>
> - if (site.bo->inputs_.size() ==
> - 0 && site.bo->production_hint_ <
> - 0 && site.site->can_start_working()
> - && !site.bo->space_consumer_ && site.site->get_statistics_percent() <
> - 10 && ((game().get_gametime() - site.built_time_) > 10 * 60 * 1000)) {
> + if (site.bo->inputs_.size() == 0 && site.bo->production_hint_ < 0 &&
> + site.site->can_start_working() && !site.bo->space_consumer_ &&
> + site.site->get_statistics_percent() < 10 &&
> + ((game().get_gametime() - site.built_time_) > 10 * 60 * 1000)) {
>
> site.bo->last_dismantle_time_ = game().get_gametime();
> flags_to_be_removed.push_back(site.site->base_flag().get_position());
> @@ -1981,8 +2246,7 @@
>
> uint16_t score = site.bo->stocklevel_;
>
> -
> - if (score > 150 && site.bo->cnt_built_ > site.bo->cnt_target_) {
> + if (score > 200 && site.bo->cnt_built_ > site.bo->cnt_target_) {
>
> site.bo->last_dismantle_time_ = game().get_gametime();
> flags_to_be_removed.push_back(site.site->base_flag().get_position());
> @@ -1990,82 +2254,15 @@
> return true;
> }
>
> - if (score > 70 && !site.site->is_stopped()) {
> -
> - game().send_player_start_stop_building(*site.site);
> - }
> -
> - if (score < 50 && site.site->is_stopped()) {
> -
> - game().send_player_start_stop_building(*site.site);
> - }
> - }
> -
> - // Upgrading policy
> - // a) if there are two buildings and none enhanced, one is enhanced
> - // b) if there are two buildings and at least one functional
> - // statistics percents are decisive
> -
> - // do not upgrade if current building is only one in operation
> - if ((site.bo->cnt_built_ - site.bo->unoccupied_) <= 1)
> - return false;
> -
> - // Check whether building is enhanceable and if wares of the enhanced
> - // buildings are needed. If yes consider an upgrade.
> - const BuildingIndex enhancement = site.site->descr().enhancement();
> - BuildingIndex enbld = INVALID_INDEX; // to get rid of this
> - BuildingObserver* bestbld = nullptr;
> -
> - // Only enhance buildings that are allowed (scenario mode)
> - if (player_->is_building_type_allowed(enhancement)) {
> - const BuildingDescr& bld = *tribe_->get_building_descr(enhancement);
> - BuildingObserver& en_bo = get_building_observer(bld.name().c_str());
> -
> - // do not build the same building so soon (kind of duplicity check)
> - if (gametime - en_bo.construction_decision_time_ >= kBuildingMinInterval)
> - {
> - // Don't enhance this building, if there is already one of same type
> - // under construction or unoccupied_
> - if (en_bo.cnt_under_construction_ + en_bo.unoccupied_ <= 0)
> - {
> - // don't upgrade without workers
> - if (site.site->has_workers(enhancement, game()))
> - {
> - // forcing first upgrade
> - if ((en_bo.cnt_under_construction_ + en_bo.cnt_built_ + en_bo.unoccupied_) == 0
> - && (site.bo->cnt_built_ - site.bo->unoccupied_) >= 1
> - && (game().get_gametime() - site.unoccupied_till_) > 30 * 60 * 1000
> - && !mines_.empty())
> - {
> - game().send_player_enhance_building(*site.site, enhancement);
> - return true;
> - }
> - }
> - }
> - }
> -
> - // now, let consider normal upgrade
> - // do not upgrade if candidate production % is too low
> - if ((en_bo.cnt_built_ - en_bo.unoccupied_) != 0
> - || (en_bo.cnt_under_construction_ + en_bo.unoccupied_) <= 0
> - || en_bo.current_stats_ >= 50) {
> -
> - if (en_bo.current_stats_ > 65
> - && ((en_bo.current_stats_ - site.bo->current_stats_) + // priority for enhancement
> - (en_bo.current_stats_ - 65)) > 0)
> - {
> - enbld = enhancement;
> - bestbld = &en_bo;
> - }
> - }
> - }
> -
> - // Enhance if enhanced building is useful
> - // additional: we dont want to lose the old building
> - if (enbld != INVALID_INDEX) {
> - game().send_player_enhance_building(*site.site, enbld);
> - bestbld->construction_decision_time_ = gametime;
> - changed = true;
> + if (score > 120 && !site.site->is_stopped()) {
> +
> + game().send_player_start_stop_building(*site.site);
> + }
> +
> + if (score < 80 && site.site->is_stopped()) {
> +
> + game().send_player_start_stop_building(*site.site);
> + }
> }
>
> return changed;
> @@ -2081,82 +2278,72 @@
> if ((next_mine_check_due_ > gametime) || mines_.empty())
> return false;
>
> - next_mine_check_due_ = gametime + 10000; // 10 seconds is enough
> + next_mine_check_due_ = gametime + 7000; // 7 seconds is enough
> // Reorder and set new values; - due to returns within the function
> mines_.push_back(mines_.front());
> mines_.pop_front();
> - // also statistics must be recalculated
> +
> // Get link to productionsite that should be checked
> ProductionSiteObserver& site = mines_.front();
> - Map& map = game().map();
> - Field* field = map.get_fcoords(site.site->get_position()).field;
>
> - // first get rid of mines that are missing workers for some time (5 minutes)
> + // first get rid of mines that are missing workers for some time (6 minutes),
> // released worker (if any) can be usefull elsewhere !
> - if (site.built_time_ + 5 * 60 * 1000 < gametime && !site.site->can_start_working()) {
> - flags_to_be_removed.push_back(site.site->base_flag().get_position());
> - game().send_player_dismantle(*site.site);
> - return true;
> - }
> -
> - // It takes some time till performance gets to 0
> - // so I use 40% as a limit to check if there are some resources left
> - if (site.site->get_statistics_percent() > 40)
> - return false;
> -
> - // Check if mine ran out of resources
> - uint8_t current = field->get_resources_amount();
> -
> - if (current < 1) {
> - // 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.
> - flags_to_be_removed.push_back(site.site->base_flag().get_position());
> - game().send_player_dismantle(*site.site);
> -
> - return true;
> - }
> + if (site.built_time_ + 6 * 60 * 1000 < gametime && !site.site->can_start_working()) {
> + flags_to_be_removed.push_back(site.site->base_flag().get_position());
> + game().send_player_dismantle(*site.site);
> + return true;
> + }
> +
> + // doing nothing when failed count is too low
> + if (site.no_resources_count < 6)
> + return false;
> +
> + // dismantling when the failed count is too high
> + if (site.no_resources_count > 14) {
> + flags_to_be_removed.push_back(site.site->base_flag().get_position());
> + game().send_player_dismantle(*site.site);
> + site.bo->construction_decision_time_ = gametime;
> + return true;
> + }
> +
> + // updating statistics if needed
> + if (site.bo->stocklevel_time < game().get_gametime() - 5 * 1000) {
> + site.bo->stocklevel_ = get_stocklevel_by_hint(site.bo->production_hint_);
> + site.bo->stocklevel_time = game().get_gametime();
> + }
> +
> + // if we have enough of mined resources on stock - do not upgrade
> + if (site.bo->stocklevel_ > 150)
> + return false;
>
> // Check whether building is enhanceable. If yes consider an upgrade.
> const BuildingIndex enhancement = site.site->descr().enhancement();
> - BuildingIndex enbld = INVALID_INDEX;
> - BuildingObserver* bestbld = nullptr;
> +
> + // if no enhancement is possible
> + if (enhancement == INVALID_INDEX) {
> + // will be destroyed when no_resource_count will overflow
> + return false;
> + }
> +
> bool changed = false;
> - // Only enhance buildings that are allowed (scenario mode)
> if (player_->is_building_type_allowed(enhancement)) {
> // first exclude possibility there are enhancements in construction or unoccupied_
> const BuildingDescr& bld = *tribe_->get_building_descr(enhancement);
> BuildingObserver& en_bo = get_building_observer(bld.name().c_str());
>
> - if (en_bo.unoccupied_ + en_bo.cnt_under_construction_ <= 0)
> - {
> - // do not upgrade target building are not working properly (probably do not have food)
> - if (en_bo.cnt_built_ <= 0 && en_bo.current_stats_ >= 60)
> - {
> - // do not build the same building so soon (kind of duplicity check)
> - if (gametime - en_bo.construction_decision_time_ >= kBuildingMinInterval)
> - {
> - // Check if mine needs an enhancement to mine more resources
> - uint8_t const until =
> - field->get_starting_res_amount() * (100 - site.bo->mines_percent_) / 100;
> + // if it is too soon for enhancement and making sure there are no unoccupied mines
> + if (gametime - en_bo.construction_decision_time_ >= kBuildingMinInterval &&
> + en_bo.unoccupied_ + en_bo.cnt_under_construction_ == 0) {
>
> - if (until >= current) {
> - enbld = enhancement;
> - bestbld = &en_bo;
> - }
> - }
> + // now verify that there are enough workers
> + if (site.site->has_workers(enhancement, game())) { // enhancing
> + game().send_player_enhance_building(*site.site, enhancement);
> + en_bo.construction_decision_time_ = gametime;
> + changed = true;
> }
> }
> }
>
> - // Enhance if enhanced building is useful and possible
> - if (enbld != INVALID_INDEX) {
> - game().send_player_enhance_building(*site.site, enbld);
> - bestbld->construction_decision_time_ = gametime;
> - changed = true;
> -
> - }
> -
> return changed;
> }
>
> @@ -2175,9 +2362,43 @@
> return count;
> }
>
> -// this count all stock for all output
> +// calculating how much an output is needed
> +// 'max' is because the building can have more outputs
> +void DefaultAI::check_ware_needeness(BuildingObserver& bo,
> + bool* output_is_needed,
> + int16_t* max_preciousness,
> + int16_t* max_needed_preciousness) {
> +
> + // reseting values
resetting values
> + *output_is_needed = false;
> + *max_preciousness = 0;
> + *max_needed_preciousness = 0;
> +
> + for (EconomyObserver* observer : economies) {
> + // Don't check if the economy has no warehouse.
> + if (observer->economy.warehouses().empty())
> + continue;
> +
> + for (uint32_t m = 0; m < bo.outputs_.size(); ++m) {
> + WareIndex wt(static_cast<size_t>(bo.outputs_.at(m)));
> +
> + if (observer->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_;
> + }
> +
> + if (wares.at(bo.outputs_.at(m)).preciousness_ > *max_preciousness)
> + *max_preciousness = wares.at(bo.outputs_.at(m)).preciousness_;
> + }
> + }
> +}
> +
> +// counts produced output on stock
> +// if multiple outputs, it returns lowest value
> uint32_t DefaultAI::get_stocklevel(BuildingObserver& bo) {
> - uint32_t count = 0;
> + uint32_t count = 10000;
>
> if (!bo.outputs_.empty()) {
> for (EconomyObserver* observer : economies) {
> @@ -2187,7 +2408,8 @@
>
> for (uint32_t m = 0; m < bo.outputs_.size(); ++m) {
> WareIndex wt(static_cast<size_t>(bo.outputs_.at(m)));
> - count += observer->economy.stock_ware(wt);
> + if (count > observer->economy.stock_ware(wt))
> + count = observer->economy.stock_ware(wt);
> }
> }
> }
> @@ -2219,16 +2441,6 @@
> if (it->site->stationed_soldiers().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;
> @@ -2239,16 +2451,15 @@
> MilitarySite* ms = militarysites.front().site;
> uint32_t const vision = ms->descr().vision_range();
> FCoords f = map.get_fcoords(ms->get_position());
> - // look if there is any enemy land nearby
> - // FindNodeEnemy find_enemy(player, game());
> - // look if there is any enemies building
> + // look if there are any enemies building
> FindNodeEnemiesBuilding find_enemy(player_, game());
>
> // first if there are enemies nearby, check for buildings not land
> - if (map.find_fields(Area<FCoords>(f, vision + 2), nullptr, find_enemy) == 0) {
> + if (map.find_fields(Area<FCoords>(f, vision + 4), nullptr, find_enemy) == 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
> // same economy where the thrown out soldiers can go to.
> +
> if (ms->economy().warehouses().size()) {
> uint32_t const j = ms->soldier_capacity();
>
> @@ -2266,9 +2477,15 @@
> update_buildable_field(bf, vision, true);
> const int32_t size_penalty = ms->get_size() - 1;
>
> - if (bf.military_capacity_ > 9 && bf.military_presence_ >
> - 3 && bf.military_loneliness_<160 && bf.military_stationed_>(2 + size_penalty)) {
> + int16_t score = 0;
> + score += (bf.military_capacity_ > 5);
> + score += (bf.military_presence_ > 3);
> + score += (bf.military_loneliness_ < 180);
> + score += (bf.military_stationed_ > (2 + size_penalty));
> + score -= (ms->soldier_capacity() * 2 > static_cast<uint32_t>(bf.military_capacity_));
> + score += (bf.unowned_land_nearby_ < 10);
>
> + if (score >= 4) {
> if (ms->get_playercaps() & Widelands::Building::PCap_Dismantle) {
> flags_to_be_removed.push_back(ms->base_flag().get_position());
> game().send_player_dismantle(*ms);
> @@ -2281,19 +2498,22 @@
> }
> }
> } else {
> +
> // If an enemy is in sight and the number of stationed soldier is not
> // at maximum - set it to maximum.
> uint32_t const j = ms->max_soldier_capacity();
> uint32_t const k = ms->soldier_capacity();
>
> - if (j > k)
> - // game().send_player_change_soldier_capacity(*ms, j - k);
> -
> - if (MilitarySite::kPrefersHeroes != ms->get_soldier_preference())
> - game().send_player_militarysite_set_soldier_preference(
> - *ms, MilitarySite::kPrefersHeroes);
> -
> - changed = true;
> + if (j > k) {
> + game().send_player_change_soldier_capacity(*ms, j - k);
> + changed = true;
> + }
> +
> + // and also set preference to Heroes
> + if (MilitarySite::kPrefersHeroes != ms->get_soldier_preference()) {
> + game().send_player_militarysite_set_soldier_preference(*ms, MilitarySite::kPrefersHeroes);
> + changed = true;
> + }
> }
>
> // reorder:;
> @@ -2388,7 +2608,8 @@
> void DefaultAI::consider_productionsite_influence(BuildableField& field,
> Coords coords,
> const BuildingObserver& bo) {
> - if (bo.space_consumer_ && game().map().calc_distance(coords, field.coords) < 4)
> + if (bo.space_consumer_ && !bo.plants_trees_ &&
> + game().map().calc_distance(coords, field.coords) < 8)
> ++field.space_consumers_nearby_;
>
> for (size_t i = 0; i < bo.inputs_.size(); ++i)
> @@ -2437,8 +2658,8 @@
> else if (upcast(Flag const, flag, &pi)) {
> for (EconomyObserver* eco_obs : economies) {
> for (std::list<Flag const*>::iterator flag_iter = eco_obs->flags.begin();
> - flag_iter != eco_obs->flags.end();
> - ++flag_iter) {
> + flag_iter != eco_obs->flags.end();
> + ++flag_iter) {
> if (*flag_iter == flag) {
> eco_obs->flags.erase(flag_iter);
> return;
> @@ -2446,8 +2667,8 @@
> }
> }
> for (std::list<Flag const*>::iterator flag_iter = new_flags.begin();
> - flag_iter != new_flags.end();
> - ++flag_iter) {
> + flag_iter != new_flags.end();
> + ++flag_iter) {
> if (*flag_iter == flag) {
> new_flags.erase(flag_iter);
> return;
> @@ -2457,6 +2678,17 @@
> roads.remove(road);
> }
>
> +// this is called when a mine reports "out of resources"
> +void DefaultAI::out_of_resources_site(const ProductionSite& site) {
> +
> + // we must identify which mine matches the productionsite a note reffers to
> + for (std::list<ProductionSiteObserver>::iterator i = mines_.begin(); i != mines_.end(); ++i)
> + if (i->site == &site) {
> + i->no_resources_count += 1;
> + break;
> + }
> +}
> +
> // this is called whenever we gain a new building
> void DefaultAI::gain_building(Building& b) {
> BuildingObserver& bo = get_building_observer(b.descr().name().c_str());
> @@ -2466,6 +2698,11 @@
> get_building_observer(ref_cast<ConstructionSite, Building>(b).building().name().c_str());
> ++target_bo.cnt_under_construction_;
> ++num_constructionsites_;
> + if (target_bo.type == BuildingObserver::PRODUCTIONSITE)
> + ++num_prod_constructionsites;
> + if (target_bo.type == BuildingObserver::MILITARYSITE)
> + ++num_milit_constructionsites;
> +
> // Let defaultAI try to directly connect the constructionsite
> next_road_due_ = game().get_gametime();
> } else {
> @@ -2478,6 +2715,7 @@
> productionsites.back().built_time_ = game().get_gametime();
> productionsites.back().unoccupied_till_ = game().get_gametime();
> productionsites.back().stats_zero_ = 0;
> + productionsites.back().no_resources_count = 0;
>
> for (uint32_t i = 0; i < bo.outputs_.size(); ++i)
> ++wares.at(bo.outputs_.at(i)).producers_;
> @@ -2501,6 +2739,7 @@
> militarysites.back().bo = &bo;
> militarysites.back().checks = bo.desc->get_size();
> militarysites.back().enemies_nearby = true;
> +
> } else if (bo.type == BuildingObserver::WAREHOUSE)
> ++numof_warehouses_;
> }
> @@ -2515,6 +2754,11 @@
> ref_cast<ConstructionSite const, Building const>(b).building().name().c_str());
> --target_bo.cnt_under_construction_;
> --num_constructionsites_;
> + if (target_bo.type == BuildingObserver::PRODUCTIONSITE)
> + --num_prod_constructionsites;
> + if (target_bo.type == BuildingObserver::MILITARYSITE)
> + --num_milit_constructionsites;
> +
> } else {
> --bo.cnt_built_;
>
> @@ -2547,6 +2791,7 @@
> for (uint32_t i = 0; i < bo.inputs_.size(); ++i)
> --wares.at(bo.inputs_.at(i)).consumers_;
> } else if (bo.type == BuildingObserver::MILITARYSITE) {
> +
> for (std::list<MilitarySiteObserver>::iterator i = militarysites.begin();
> i != militarysites.end();
> ++i)
> @@ -2574,9 +2819,9 @@
> for (const int16_t& temp_inputs : bo.inputs_) {
> for (const BuildingObserver& temp_building : buildings_) {
> if (temp_building.cnt_built_ &&
> - std::find(temp_building.outputs_.begin(), temp_building.outputs_.end(), temp_inputs) !=
> - temp_building.outputs_.end() &&
> - check_supply(temp_building)) {
> + std::find(temp_building.outputs_.begin(), temp_building.outputs_.end(), temp_inputs) !=
> + temp_building.outputs_.end() &&
> + check_supply(temp_building)) {
> ++supplied;
> break;
> }
> @@ -2637,7 +2882,6 @@
> } else {
> player_attackable[j - 1] = false;
> }
> -
> }
>
> if (!any_attackable) {
> @@ -2650,8 +2894,9 @@
> const uint16_t attempts = militarysites.size() / 6 + 1;
> Map& map = game().map();
>
> + uint16_t position = 0;
> for (uint32_t i = 0; i < attempts && !any_attacked; ++i) {
> - const uint16_t position = (game().get_gametime() + (3 * i)) % militarysites.size();
> + position = (game().get_gametime() + (3 * i)) % militarysites.size();
>
> // picking random military sites
> // using gametime as a random value, but it is constant so each next is on position +3
> @@ -2670,7 +2915,6 @@
> uint32_t defenders = 0;
> uint32_t defend_ready_enemies = 0; // enemy soldiers that can come to defend the attacked
> // building (one soldier has to stay)
> - // uint8_t retreat = ms->owner().get_retreat_percentage();
>
> // skipping if based on "enemies nearby" there are probably no enemies nearby
> if (!mso->enemies_nearby && gametime % 8 > 0) {
> @@ -2777,3 +3021,31 @@
> return false;
> }
> }
> +
> +// This is used for profiling, so usually this is not used :)
> +void DefaultAI::print_land_stats() {
> + // this will just print statistics of land size
> + // intended for AI development only
> + uint32_t plr_in_game = 0;
> + uint32_t sum_l = 0;
> + uint32_t count_l = 0;
> + uint32_t sum_m = 0;
> + uint32_t count_m = 0;
> + PlayerNumber const nr_players = game().map().get_nrplayers();
> + iterate_players_existing_novar(p, nr_players, game())++ plr_in_game;
> + const Game::GeneralStatsVector& genstats = game().get_general_statistics();
> +
> + for (uint8_t j = 1; j <= plr_in_game; ++j) {
> + log(" player: %1d, landsize: %5d, military strength: %3d\n",
> + j,
> + genstats[j - 1].land_size.back(),
> + genstats[j - 1].miltary_strength.back());
> +
> + sum_l += genstats[j - 1].land_size.back();
> + count_l += 1;
> + sum_m += genstats[j - 1].miltary_strength.back();
> + count_m += 1;
> + }
> +
> + log(" Average: Landsize: %5d, military strenght: %3d\n", sum_l / count_l, sum_m / count_m);
> +}
>
> === modified file 'src/ai/defaultai.h'
> --- src/ai/defaultai.h 2014-09-10 13:03:40 +0000
> +++ src/ai/defaultai.h 2014-10-03 21:34:06 +0000
> @@ -123,13 +123,20 @@
>
> void update_productionsite_stats(int32_t);
>
> + void check_ware_needeness(BuildingObserver& bo,
> + bool* output_is_needed,
> + int16_t* max_preciousness,
> + int16_t* max_needed_preciousness);
> +
> bool construct_building(int32_t);
> - bool construct_roads(int32_t);
> +
> + // all road management is invoked by function improve_roads()
> + // if needed it calls create_shortcut_road() with a flag from which
> + // new road should be considered (or is needed)
> bool improve_roads(int32_t);
> -
> - bool improve_transportation_ways(const Widelands::Flag&);
> - bool connect_flag_to_another_economy(const Widelands::Flag&);
> -
> + bool create_shortcut_road(const Widelands::Flag&, uint16_t maxcheckradius, uint16_t minred);
> + // trying to identify roads that might be removed
> + bool abundant_road_test(const Widelands::Road&);
> bool check_economies();
> bool check_productionsites(int32_t);
> bool check_mines_(int32_t);
> @@ -152,11 +159,14 @@
> void lose_immovable(const Widelands::PlayerImmovable&);
> void gain_building(Widelands::Building&);
> void lose_building(const Widelands::Building&);
> + void out_of_resources_site(const Widelands::ProductionSite&);
>
> bool check_supply(const BuildingObserver&);
>
> bool consider_attack(int32_t);
>
> + void print_land_stats();
> +
> private:
> // Variables of default AI
> uint8_t type_;
> @@ -169,6 +179,8 @@
>
> std::vector<BuildingObserver> buildings_;
> uint32_t num_constructionsites_;
> + uint32_t num_milit_constructionsites;
> + uint32_t num_prod_constructionsites;
>
> std::list<Widelands::FCoords> unusable_fields;
> std::list<BuildableField*> buildable_fields;
> @@ -193,22 +205,32 @@
> int32_t next_militarysite_check_due_;
> int32_t next_attack_consideration_due_;
> int32_t next_helpersites_check_due_;
> + int32_t next_bf_check_due_;
> int32_t inhibit_road_building_;
> int32_t time_of_last_construction_;
> - int32_t next_wood_cutting_check_due_;
> + int32_t enemy_last_seen_;
>
> uint16_t numof_warehouses_;
>
> bool new_buildings_stop_;
> + bool water_is_important_; //for atlanteans, water is on pair with mines and so on
> + uint16_t mines_need_intensity_; // when we have enough mines weight of possible mines spots
> + // is decreased (range 0-10)
> + uint16_t water_need_intensity_; // when we have enough fishers weight of water nearby
> + // is decreased (range 0-5)
> uint16_t unstationed_milit_buildings_; // counts empty military buildings (ones where no soldier
> // is belogning to)
> uint16_t military_under_constr_;
> uint16_t military_last_dismantle_;
> int32_t military_last_build_; // sometimes expansions just stops, this is time of last military
> // building build
> + int32_t spots_; // sum of buildable fields
>
> - std::unique_ptr<Notifications::Subscriber<Widelands::NoteFieldPossession>> field_possession_subscriber_;
> + std::unique_ptr<Notifications::Subscriber<Widelands::NoteFieldPossession>>
> + field_possession_subscriber_;
> std::unique_ptr<Notifications::Subscriber<Widelands::NoteImmovable>> immovable_subscriber_;
> + std::unique_ptr<Notifications::Subscriber<Widelands::NoteProductionSiteOutOfResources>>
> + outofresource_subscriber_;
> };
>
> #endif // end of include guard: WL_AI_DEFAULTAI_H
>
> === modified file 'src/logic/productionsite.cc'
> --- src/logic/productionsite.cc 2014-09-10 18:56:42 +0000
> +++ src/logic/productionsite.cc 2014-10-03 21:34:06 +0000
> @@ -912,6 +912,7 @@
>
> void ProductionSite::notify_player(Game & game, uint8_t minutes)
> {
> +
> if (m_out_of_resource_delay_counter >=
> descr().out_of_resource_delay_attempts()) {
> if (descr().out_of_resource_title().empty())
> @@ -930,6 +931,10 @@
> true,
> minutes * 60000, 0);
> }
> + // following sends "out of resources" messages to be picked up by AI
> + // used as a information for dismantling and upgrading mines
> + if (descr().get_ismine())
> + Notifications::publish(NoteProductionSiteOutOfResources(this, get_owner()));
> }
> if (m_out_of_resource_delay_counter++ >=
> descr().out_of_resource_delay_attempts()) {
>
> === modified file 'src/logic/productionsite.h'
> --- src/logic/productionsite.h 2014-09-19 12:54:54 +0000
> +++ src/logic/productionsite.h 2014-10-03 21:34:06 +0000
> @@ -155,6 +155,7 @@
> uint8_t get_statistics_percent() {return m_last_stat_percent;}
> uint8_t get_crude_statistics() {return (m_crude_percent + 5000) / 10000;}
>
> +
> const std::string& production_result() const {return m_production_result;}
>
> // Production and worker programs set this to explain the current
> @@ -303,6 +304,24 @@
> uint8_t m_max;
> };
>
> +/**
> + * Note to be published when a production site is out of resources
> + */
> +// A note we're using to notify the AI
> +struct NoteProductionSiteOutOfResources {
> + CAN_BE_SEND_AS_NOTE(NoteId::ProductionSiteOutOfResources)
> +
> + // The production site that is out of resources.
> + ProductionSite* ps;
> +
> + // The player that owns the production site.
> + Player * player;
> +
> + NoteProductionSiteOutOfResources(ProductionSite* const init_ps, Player* init_player)
> + : ps(init_ps), player(init_player) {
> + }
> +};
> +
> }
>
> #endif // end of include guard: WL_LOGIC_PRODUCTIONSITE_H
>
> === modified file 'src/notifications/note_ids.h'
> --- src/notifications/note_ids.h 2014-07-16 07:44:33 +0000
> +++ src/notifications/note_ids.h 2014-10-03 21:34:06 +0000
> @@ -31,6 +31,7 @@
> Immovable,
> FieldPossession,
> FieldTransformed,
> + ProductionSiteOutOfResources,
> };
>
> #endif // end of include guard: WL_NOTIFICATIONS_NOTE_IDS_H
>
> === modified file 'tribes/atlanteans/armorsmithy/conf'
> --- tribes/atlanteans/armorsmithy/conf 2014-07-27 19:31:34 +0000
> +++ tribes/atlanteans/armorsmithy/conf 2014-10-03 21:34:06 +0000
> @@ -3,7 +3,7 @@
> output=steel_shield
>
> [aihints]
> -build_material=false
> +prohibited_till=900
>
> [buildcost]
> log=2
>
> === modified file 'tribes/atlanteans/bakery/conf'
> --- tribes/atlanteans/bakery/conf 2014-07-27 19:31:34 +0000
> +++ tribes/atlanteans/bakery/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=bread
>
> [aihints]
> -build_material=false
> -is_food_basic=true
> +forced_after=1200
> +prohibited_till=900
>
> [buildcost]
> log=2
>
> === modified file 'tribes/atlanteans/blackroot_farm/conf'
> --- tribes/atlanteans/blackroot_farm/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/blackroot_farm/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=blackroot
>
> [aihints]
> +prohibited_till=600
> space_consumer=true
> -build_material=false
>
> [buildcost]
> planks=3
>
> === modified file 'tribes/atlanteans/castle/conf'
> --- tribes/atlanteans/castle/conf 2014-07-28 12:48:04 +0000
> +++ tribes/atlanteans/castle/conf 2014-10-03 21:34:06 +0000
> @@ -13,6 +13,7 @@
> expansion=true
> fighting=true
> mountain_conqueror=true
> +prohibited_till=1800
>
> [buildcost]
> planks=4
>
> === modified file 'tribes/atlanteans/charcoal_kiln/conf'
> --- tribes/atlanteans/charcoal_kiln/conf 2014-08-26 17:25:00 +0000
> +++ tribes/atlanteans/charcoal_kiln/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=coal
>
> [aihints]
> -build_material=false
> +prohibited_till=1200
>
> [buildcost]
> log=2
>
> === modified file 'tribes/atlanteans/coalmine/conf'
> --- tribes/atlanteans/coalmine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/coalmine/conf 2014-10-03 21:34:06 +0000
> @@ -3,6 +3,7 @@
>
> [aihints]
> mines=coal
> +prohibited_till=1200
>
> [buildcost]
> log=7
>
> === modified file 'tribes/atlanteans/cornflour/conf'
> --- tribes/atlanteans/cornflour/conf 2014-07-28 14:04:36 +0000
> +++ tribes/atlanteans/cornflour/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,7 @@
> help=_Cornflour is produced in a mill out of corn and is one of three parts of the Atlantean bread produced in bakeries.
>
> default_target_quantity=15
> -preciousness=2
> +preciousness=7
>
> [idle]
> pics=idle.png
>
> === modified file 'tribes/atlanteans/crystalmine/conf'
> --- tribes/atlanteans/crystalmine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/crystalmine/conf 2014-10-03 21:34:06 +0000
> @@ -5,6 +5,7 @@
>
> [aihints]
> mines=granite
> +prohibited_till=600
>
> [buildcost]
> log=7
>
> === modified file 'tribes/atlanteans/farm/conf'
> --- tribes/atlanteans/farm/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/farm/conf 2014-10-03 21:34:06 +0000
> @@ -3,8 +3,9 @@
>
> [aihints]
> space_consumer=true
> -is_basic=true # farm needs spidercloth to be build and spidercloth needs
> +forced_after=180 # farm needs spidercloth to be build and spidercloth needs
> # corn for production -> farm should be build ASAP!
> +prohibited_till=120
>
> [buildcost]
> log=3
>
> === modified file 'tribes/atlanteans/fish_breeders_house/conf'
> --- tribes/atlanteans/fish_breeders_house/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/fish_breeders_house/conf 2014-10-03 21:34:06 +0000
> @@ -1,9 +1,9 @@
> size=small
>
> [aihints]
> -build_material=false
> needs_water=true
> renews_map_resource=fish
> +prohibited_till=900
>
> [buildcost]
> log=1
>
> === modified file 'tribes/atlanteans/fishers_house/conf'
> --- tribes/atlanteans/fishers_house/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/fishers_house/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=fish
>
> [aihints]
> -build_material=false
> needs_water=true
> +prohibited_till=600
>
> [buildcost]
> log=1
>
> === modified file 'tribes/atlanteans/foresters_house/conf'
> --- tribes/atlanteans/foresters_house/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/foresters_house/conf 2014-10-03 21:34:06 +0000
> @@ -3,6 +3,7 @@
> [aihints]
> space_consumer=true
> renews_map_resource=log
> +prohibited_till=50
>
> [buildcost]
> log=1
>
> === modified file 'tribes/atlanteans/gold-spinning-mill/conf'
> --- tribes/atlanteans/gold-spinning-mill/conf 2014-07-27 19:31:34 +0000
> +++ tribes/atlanteans/gold-spinning-mill/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=goldyarn
>
> [aihints]
> -build_material=false
> +prohibited_till=600
>
> [buildcost]
> log=2
>
> === modified file 'tribes/atlanteans/goldmine/conf'
> --- tribes/atlanteans/goldmine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/goldmine/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=goldore
>
> [aihints]
> -build_material=false
> mines=gold
> +prohibited_till=1200
>
> [buildcost]
> log=7
>
> === modified file 'tribes/atlanteans/horsefarm/conf'
> --- tribes/atlanteans/horsefarm/conf 2014-07-27 19:31:34 +0000
> +++ tribes/atlanteans/horsefarm/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,6 @@
> output=horse
>
> [aihints]
> -build_material=false
> recruitment=true
>
> [buildcost]
>
> === modified file 'tribes/atlanteans/hunters_house/conf'
> --- tribes/atlanteans/hunters_house/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/hunters_house/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=meat
>
> [aihints]
> -build_material=false
> +prohibited_till=60
>
> [buildcost]
> log=1
>
> === modified file 'tribes/atlanteans/ironmine/conf'
> --- tribes/atlanteans/ironmine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/ironmine/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=ironore
>
> [aihints]
> -build_material=false
> mines=iron
> +prohibited_till=1200
>
> [buildcost]
> log=7
>
> === modified file 'tribes/atlanteans/labyrinth/conf'
> --- tribes/atlanteans/labyrinth/conf 2014-09-30 08:05:35 +0000
> +++ tribes/atlanteans/labyrinth/conf 2014-10-03 21:34:06 +0000
> @@ -97,3 +97,6 @@
> [idle]
> pics=labyrinth_i_??.png # ???
> hotspot=80 88
> +
> +[aihints]
> +prohibited_till=2700
>
> === modified file 'tribes/atlanteans/mill/conf'
> --- tribes/atlanteans/mill/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/mill/conf 2014-10-03 21:34:06 +0000
> @@ -3,7 +3,7 @@
> output=blackrootflour
>
> [aihints]
> -build_material=false
> +prohibited_till=600
>
> [buildcost]
> log=3
>
> === modified file 'tribes/atlanteans/quarry/conf'
> --- tribes/atlanteans/quarry/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/quarry/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=stone
>
> [aihints]
> -is_basic=true
> +forced_after=60
> stoneproducer=true
>
> [buildcost]
>
> === modified file 'tribes/atlanteans/sawmill/conf'
> --- tribes/atlanteans/sawmill/conf 2014-07-27 19:31:34 +0000
> +++ tribes/atlanteans/sawmill/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,8 @@
> output=planks
>
> [aihints]
> -is_basic=true
> +forced_after=300
> +prohibited_till=60
>
> [buildcost]
> log=2
>
> === modified file 'tribes/atlanteans/scouts_house/conf'
> --- tribes/atlanteans/scouts_house/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/scouts_house/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,6 @@
> size=small
>
> [aihints]
> -build_material=false
>
> [buildcost]
> log=2
>
> === modified file 'tribes/atlanteans/shipyard/conf'
> --- tribes/atlanteans/shipyard/conf 2014-09-30 08:05:35 +0000
> +++ tribes/atlanteans/shipyard/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,6 @@
> size=medium
>
> [aihints]
> -build_material=false
> needs_water=true
>
> [buildcost]
>
> === modified file 'tribes/atlanteans/smelting_works/conf'
> --- tribes/atlanteans/smelting_works/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/smelting_works/conf 2014-10-03 21:34:06 +0000
> @@ -3,7 +3,7 @@
> output=gold
>
> [aihints]
> -build_material=false
> +prohibited_till=600
>
> [buildcost]
> log=1
>
> === modified file 'tribes/atlanteans/smokery/conf'
> --- tribes/atlanteans/smokery/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/smokery/conf 2014-10-03 21:34:06 +0000
> @@ -3,8 +3,8 @@
> output=smoked_fish
>
> [aihints]
> -build_material=false
> -is_food_basic=true
> +forced_after=900
> +prohibited_till=60
>
> [buildcost]
> log=1
>
> === modified file 'tribes/atlanteans/spidercloth/conf'
> --- tribes/atlanteans/spidercloth/conf 2014-07-28 14:04:36 +0000
> +++ tribes/atlanteans/spidercloth/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,7 @@
> help=_Spidercloth is made out of spideryarn in a weaving mill. It is used in the toolsmithy and the shipyard. Also some higher developed buildings need spidercloth for their construction.
>
> default_target_quantity=20
> -preciousness=1
> +preciousness=5
>
> [idle]
> pics=idle.png
>
> === modified file 'tribes/atlanteans/spiderfarm/conf'
> --- tribes/atlanteans/spiderfarm/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/spiderfarm/conf 2014-10-03 21:34:06 +0000
> @@ -35,3 +35,7 @@
> [working]
> pics=spiderfarm_i_??.png # ???
> hotspot=87 75
> +
> +[aihints]
> +forced_after=60
> +prohibited_till=60
>
> === modified file 'tribes/atlanteans/spideryarn/conf'
> --- tribes/atlanteans/spideryarn/conf 2014-04-08 06:28:45 +0000
> +++ tribes/atlanteans/spideryarn/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,7 @@
> help=_This yarn is produced by spiders, which are bred by spider farms. It is processed into spidercloth in a weaving mill.
>
> default_target_quantity=10
> -preciousness=2
> +preciousness=11
>
> [idle]
> pics=idle.png
>
> === modified file 'tribes/atlanteans/toolsmithy/conf'
> --- tribes/atlanteans/toolsmithy/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/toolsmithy/conf 2014-10-03 21:34:06 +0000
> @@ -13,8 +13,8 @@
> output=shovel
>
> [aihints]
> -build_material=false
> -is_basic=true
> +forced_after=900
> +prohibited_till=450
>
> [buildcost]
> log=1
>
> === modified file 'tribes/atlanteans/tower/conf'
> --- tribes/atlanteans/tower/conf 2014-07-28 12:48:04 +0000
> +++ tribes/atlanteans/tower/conf 2014-10-03 21:34:06 +0000
> @@ -14,6 +14,7 @@
> [aihints]
> expansion=true
> mountain_conqueror=true
> +prohibited_till=600
>
> [buildcost]
> log=2
>
> === modified file 'tribes/atlanteans/weaponsmithy/conf'
> --- tribes/atlanteans/weaponsmithy/conf 2014-07-27 19:31:34 +0000
> +++ tribes/atlanteans/weaponsmithy/conf 2014-10-03 21:34:06 +0000
> @@ -6,7 +6,7 @@
> output=heavy_double_trident
>
> [aihints]
> -build_material=false
> +prohibited_till=900
>
> [buildcost]
> log=2
>
> === modified file 'tribes/atlanteans/weaving-mill/conf'
> --- tribes/atlanteans/weaving-mill/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/weaving-mill/conf 2014-10-03 21:34:06 +0000
> @@ -4,7 +4,8 @@
> output=golden_tabard
>
> [aihints]
> -is_basic=true
> +forced_after=60
> +prohibited_till=60
>
> [buildcost]
> log=3
>
> === modified file 'tribes/atlanteans/well/conf'
> --- tribes/atlanteans/well/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/well/conf 2014-10-03 21:34:06 +0000
> @@ -3,6 +3,8 @@
>
> [aihints]
> mines_water=true
> +forced_after=600
> +prohibited_till=300
>
> [buildcost]
> log=2
>
> === modified file 'tribes/atlanteans/woodcutters_house/conf'
> --- tribes/atlanteans/woodcutters_house/conf 2014-07-29 09:27:08 +0000
> +++ tribes/atlanteans/woodcutters_house/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=log
>
> [aihints]
> -is_basic=true
> logproducer=true
> +forced_after=0
>
> [buildcost]
> log=2
>
> === modified file 'tribes/barbarians/axfactory/conf'
> --- tribes/barbarians/axfactory/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/axfactory/conf 2014-10-03 21:34:06 +0000
> @@ -7,7 +7,6 @@
> enhancement=warmill
>
> [aihints]
> -build_material=false
>
> [enhancement_cost]
> log=1
>
> === modified file 'tribes/barbarians/bakery/conf'
> --- tribes/barbarians/bakery/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/bakery/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=pittabread
>
> [aihints]
> -build_material=false
> +prohibited_till=600
>
> [buildcost]
> log=2
>
> === modified file 'tribes/barbarians/cattlefarm/conf'
> --- tribes/barbarians/cattlefarm/conf 2014-07-27 19:32:24 +0000
> +++ tribes/barbarians/cattlefarm/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,6 @@
> output=ox
>
> [aihints]
> -build_material=false
> recruitment=true
>
> [buildcost]
>
> === modified file 'tribes/barbarians/charcoal_kiln/conf'
> --- tribes/barbarians/charcoal_kiln/conf 2014-08-26 17:25:00 +0000
> +++ tribes/barbarians/charcoal_kiln/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=coal
>
> [aihints]
> -build_material=false
> +prohibited_till=900
>
> [buildcost]
> log=3
>
> === modified file 'tribes/barbarians/coalmine/conf'
> --- tribes/barbarians/coalmine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/coalmine/conf 2014-10-03 21:34:06 +0000
> @@ -5,6 +5,7 @@
> [aihints]
> mines=coal
> mines_percent=30
> +prohibited_till=1200
>
> [buildcost]
> log=4
>
> === modified file 'tribes/barbarians/donjon/conf'
> --- tribes/barbarians/donjon/conf 2014-07-28 12:48:04 +0000
> +++ tribes/barbarians/donjon/conf 2014-10-03 21:34:06 +0000
> @@ -14,6 +14,7 @@
> expansion=true
> fighting=true
> mountain_conqueror=true
> +prohibited_till=1500
>
> [buildcost]
> blackwood=7
>
> === modified file 'tribes/barbarians/fishers_hut/conf'
> --- tribes/barbarians/fishers_hut/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/fishers_hut/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=fish
>
> [aihints]
> -build_material=false
> needs_water=true
> +prohibited_till=900
>
> [buildcost]
> log=4
>
> === modified file 'tribes/barbarians/fortress/conf'
> --- tribes/barbarians/fortress/conf 2014-07-28 12:48:04 +0000
> +++ tribes/barbarians/fortress/conf 2014-10-03 21:34:06 +0000
> @@ -14,6 +14,7 @@
> expansion=true
> fighting=true
> mountain_conqueror=true
> +prohibited_till=1800
>
> [buildcost]
> blackwood=9
>
> === modified file 'tribes/barbarians/gamekeepers_hut/conf'
> --- tribes/barbarians/gamekeepers_hut/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/gamekeepers_hut/conf 2014-10-03 21:34:06 +0000
> @@ -1,8 +1,8 @@
> size=small
>
> [aihints]
> -build_material=false
> renews_map_resource=meat
> +prohibited_till=900
>
> [buildcost]
> log=4
>
> === modified file 'tribes/barbarians/goldmine/conf'
> --- tribes/barbarians/goldmine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/goldmine/conf 2014-10-03 21:34:06 +0000
> @@ -3,9 +3,9 @@
> enhancement=deep_goldmine
>
> [aihints]
> -build_material=false
> mines=gold
> mines_percent=30
> +prohibited_till=1200
>
> [buildcost]
> log=4
>
> === modified file 'tribes/barbarians/granitemine/conf'
> --- tribes/barbarians/granitemine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/granitemine/conf 2014-10-03 21:34:06 +0000
> @@ -3,6 +3,7 @@
>
> [aihints]
> mines=granite
> +prohibited_till=900
>
> [buildcost]
> log=4
>
> === modified file 'tribes/barbarians/hardener/conf'
> --- tribes/barbarians/hardener/conf 2014-07-27 19:32:24 +0000
> +++ tribes/barbarians/hardener/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=blackwood
>
> [aihints]
> -is_basic=true
> +forced_after=0
>
> [buildcost]
> log=3
>
> === modified file 'tribes/barbarians/helmsmithy/conf'
> --- tribes/barbarians/helmsmithy/conf 2014-07-27 19:32:24 +0000
> +++ tribes/barbarians/helmsmithy/conf 2014-10-03 21:34:06 +0000
> @@ -4,7 +4,7 @@
> output=warhelm
>
> [aihints]
> -build_material=false
> +prohibited_till=1200
>
> [buildcost]
> log=3
>
> === modified file 'tribes/barbarians/hunters_hut/conf'
> --- tribes/barbarians/hunters_hut/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/hunters_hut/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=meat
>
> [aihints]
> -build_material=false
> +prohibited_till=300
>
> [buildcost]
> log=4
>
> === modified file 'tribes/barbarians/lumberjacks_hut/conf'
> --- tribes/barbarians/lumberjacks_hut/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/lumberjacks_hut/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=log
>
> [aihints]
> -is_basic=true
> +forced_after=0
> logproducer=true
>
> [buildcost]
>
> === modified file 'tribes/barbarians/metalworks/conf'
> --- tribes/barbarians/metalworks/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/metalworks/conf 2014-10-03 21:34:06 +0000
> @@ -12,8 +12,8 @@
> enhancement=axfactory
>
> [aihints]
> -build_material=false
> -is_basic=true
> +forced_after=300
> +prohibited_till=120
>
> [buildcost]
> log=1
>
> === modified file 'tribes/barbarians/micro-brewery/conf'
> --- tribes/barbarians/micro-brewery/conf 2014-07-27 19:32:24 +0000
> +++ tribes/barbarians/micro-brewery/conf 2014-10-03 21:34:06 +0000
> @@ -3,7 +3,7 @@
> enhancement=brewery
>
> [aihints]
> -build_material=false
> +forced_after=500
>
> [buildcost]
> log=3
>
> === modified file 'tribes/barbarians/oremine/conf'
> --- tribes/barbarians/oremine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/oremine/conf 2014-10-03 21:34:06 +0000
> @@ -3,8 +3,8 @@
> enhancement=deep_oremine
>
> [aihints]
> -build_material=false
> mines=iron
> +prohibited_till=1200
> mines_percent=30
>
> [buildcost]
>
> === modified file 'tribes/barbarians/quarry/conf'
> --- tribes/barbarians/quarry/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/quarry/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=raw_stone
>
> [aihints]
> -is_basic=true
> +forced_after=0
> stoneproducer=true
>
> [buildcost]
>
> === modified file 'tribes/barbarians/reed_yard/conf'
> --- tribes/barbarians/reed_yard/conf 2014-07-27 19:32:24 +0000
> +++ tribes/barbarians/reed_yard/conf 2014-10-03 21:34:06 +0000
> @@ -3,6 +3,7 @@
>
> [aihints]
> space_consumer=true
> +forced_after=0
>
> [buildcost]
> log=5
>
> === modified file 'tribes/barbarians/scouts_hut/conf'
> --- tribes/barbarians/scouts_hut/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/scouts_hut/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,6 @@
> size=small
>
> [aihints]
> -build_material=false
>
> [buildcost]
> log=2
>
> === modified file 'tribes/barbarians/shipyard/conf'
> --- tribes/barbarians/shipyard/conf 2014-09-30 08:05:35 +0000
> +++ tribes/barbarians/shipyard/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,6 @@
> size=medium
>
> [aihints]
> -build_material=false
> needs_water=true
>
> [buildcost]
>
> === modified file 'tribes/barbarians/smelting_works/conf'
> --- tribes/barbarians/smelting_works/conf 2014-07-27 19:32:24 +0000
> +++ tribes/barbarians/smelting_works/conf 2014-10-03 21:34:06 +0000
> @@ -3,7 +3,7 @@
> output=gold
>
> [aihints]
> -build_material=false
> +prohibited_till=300
>
> [buildcost]
> log=3
>
> === modified file 'tribes/barbarians/tavern/conf'
> --- tribes/barbarians/tavern/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/tavern/conf 2014-10-03 21:34:06 +0000
> @@ -3,8 +3,7 @@
> enhancement=inn
>
> [aihints]
> -build_material=false
> -is_food_basic=true
> +forced_after=900
>
> [buildcost]
> log=3
>
> === modified file 'tribes/barbarians/trainingcamp/conf'
> --- tribes/barbarians/trainingcamp/conf 2014-08-26 17:25:00 +0000
> +++ tribes/barbarians/trainingcamp/conf 2014-10-03 21:34:06 +0000
> @@ -35,6 +35,9 @@
> min_level=0
> max_level=4
>
> +[aihints]
> +prohibited_till=2700
> +
> [soldier hp]
> min_level=0
> max_level=2
>
> === modified file 'tribes/barbarians/warmill/conf'
> --- tribes/barbarians/warmill/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/warmill/conf 2014-10-03 21:34:06 +0000
> @@ -9,7 +9,6 @@
> enhanced_building=yes
>
> [aihints]
> -build_material=false
>
> [enhancement_cost]
> log=1
>
> === modified file 'tribes/barbarians/weaving-mill/conf'
> --- tribes/barbarians/weaving-mill/conf 2014-07-27 19:32:24 +0000
> +++ tribes/barbarians/weaving-mill/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=cloth
>
> [aihints]
> -build_material=false
> +prohibited_till=1200
>
> [buildcost]
> log=5
>
> === modified file 'tribes/barbarians/well/conf'
> --- tribes/barbarians/well/conf 2014-07-29 09:27:08 +0000
> +++ tribes/barbarians/well/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=water
>
> [aihints]
> -build_material=false
> mines_water=true
> +prohibited_till=600
>
> [buildcost]
> log=4
>
> === modified file 'tribes/empire/armorsmithy/conf'
> --- tribes/empire/armorsmithy/conf 2014-07-27 19:32:24 +0000
> +++ tribes/empire/armorsmithy/conf 2014-10-03 21:34:06 +0000
> @@ -5,7 +5,7 @@
> output=plate_armor
>
> [aihints]
> -build_material=false
> +prohibited_till=900
>
> [buildcost]
> log=2
>
> === modified file 'tribes/empire/bakery/conf'
> --- tribes/empire/bakery/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/bakery/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=bread
>
> [aihints]
> -build_material=false
> +prohibited_till=600
>
> [buildcost]
> log=2
>
> === modified file 'tribes/empire/beer/conf'
> --- tribes/empire/beer/conf 2013-07-23 19:04:12 +0000
> +++ tribes/empire/beer/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,7 @@
> help=_This beer is produced in a brewery out of wheat and water. It is consumed by miners in coal and iron ore mines.
>
> default_target_quantity=15
> -preciousness=2
> +preciousness=5
>
> [idle]
> pics=idle.png
>
> === modified file 'tribes/empire/brewery/conf'
> --- tribes/empire/brewery/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/brewery/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=beer
>
> [aihints]
> -build_material=false
> -is_food_basic=true
> +forced_after=900
> +prohibited_till=600
>
> [buildcost]
> log=1
>
> === modified file 'tribes/empire/charcoal_kiln/conf'
> --- tribes/empire/charcoal_kiln/conf 2014-08-26 17:25:00 +0000
> +++ tribes/empire/charcoal_kiln/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=coal
>
> [aihints]
> -build_material=false
> +prohibited_till=600
>
> [buildcost]
> log=2
>
> === modified file 'tribes/empire/coalmine/conf'
> --- tribes/empire/coalmine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/coalmine/conf 2014-10-03 21:34:06 +0000
> @@ -5,6 +5,7 @@
> [aihints]
> mines=coal
> mines_percent=50
> +prohibited_till=1200
>
> [buildcost]
> log=4
>
> === modified file 'tribes/empire/donkeyfarm/conf'
> --- tribes/empire/donkeyfarm/conf 2014-07-27 19:32:24 +0000
> +++ tribes/empire/donkeyfarm/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,6 @@
> output=donkey
>
> [aihints]
> -build_material=false
> recruitment=true
>
> [buildcost]
>
> === modified file 'tribes/empire/farm/conf'
> --- tribes/empire/farm/conf 2014-07-27 19:32:24 +0000
> +++ tribes/empire/farm/conf 2014-10-03 21:34:06 +0000
> @@ -3,7 +3,7 @@
>
> [aihints]
> space_consumer=true
> -is_food_basic=true
> +forced_after=900
>
> [buildcost]
> wood=2
>
> === modified file 'tribes/empire/fishers_house/conf'
> --- tribes/empire/fishers_house/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/fishers_house/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=fish
>
> [aihints]
> -build_material=false
> needs_water=true
> +prohibited_till=600
>
> [buildcost]
> log=1
>
> === modified file 'tribes/empire/flour/conf'
> --- tribes/empire/flour/conf 2013-07-23 19:04:12 +0000
> +++ tribes/empire/flour/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,7 @@
> help=_Flour is produced by the mill out of wheat and is needed in the bakery to produce the tasty Empire bread.
>
> default_target_quantity=20
> -preciousness=3
> +preciousness=5
>
> [idle]
> pics=flour_idle.png
>
> === modified file 'tribes/empire/fortress/conf'
> --- tribes/empire/fortress/conf 2014-07-28 12:48:04 +0000
> +++ tribes/empire/fortress/conf 2014-10-03 21:34:06 +0000
> @@ -14,6 +14,7 @@
> expansion=true
> fighting=true
> mountain_conqueror=true
> +prohibited_till=1500
>
> [buildcost]
> wood=5
>
> === modified file 'tribes/empire/goldmine/conf'
> --- tribes/empire/goldmine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/goldmine/conf 2014-10-03 21:34:06 +0000
> @@ -3,9 +3,9 @@
> enhancement=deep_goldmine
>
> [aihints]
> -build_material=false
> mines=gold
> mines_percent=50
> +prohibited_till=1200
>
> [buildcost]
> log=4
>
> === modified file 'tribes/empire/grape/conf'
> --- tribes/empire/grape/conf 2014-07-28 14:04:36 +0000
> +++ tribes/empire/grape/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,7 @@
> help=_These grapes are the base for a tasty wine. They are harvested in a vineyard and processed in a winery.
>
> default_target_quantity=20 # currently not used
> -preciousness=2
> +preciousness=9
>
> [idle]
> pics=grape_idle.png
>
> === modified file 'tribes/empire/hunters_house/conf'
> --- tribes/empire/hunters_house/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/hunters_house/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,6 @@
> output=meat
>
> [aihints]
> -build_material=false
>
> [buildcost]
> log=1
>
> === modified file 'tribes/empire/lumberjacks_house/conf'
> --- tribes/empire/lumberjacks_house/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/lumberjacks_house/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=log
>
> [aihints]
> -is_basic=true
> +forced_after=0
> logproducer=true
>
> [buildcost]
>
> === modified file 'tribes/empire/marblemine/conf'
> --- tribes/empire/marblemine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/marblemine/conf 2014-10-03 21:34:06 +0000
> @@ -6,7 +6,7 @@
> [aihints]
> mines=granite
> mines_percent=50
> -marbleproducer=true
> +prohibited_till=450
>
> [buildcost]
> log=4
>
> === modified file 'tribes/empire/mill/conf'
> --- tribes/empire/mill/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/mill/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=flour
>
> [aihints]
> -build_material=false
> +prohibited_till=600
>
> [buildcost]
> log=3
>
> === modified file 'tribes/empire/oremine/conf'
> --- tribes/empire/oremine/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/oremine/conf 2014-10-03 21:34:06 +0000
> @@ -3,9 +3,9 @@
> enhancement=deep_oremine
>
> [aihints]
> -build_material=false
> mines=iron
> mines_percent=50
> +prohibited_till=1200
>
> [buildcost]
> log=4
>
> === modified file 'tribes/empire/outpost/conf'
> --- tribes/empire/outpost/conf 2014-07-28 12:48:04 +0000
> +++ tribes/empire/outpost/conf 2014-10-03 21:34:06 +0000
> @@ -12,6 +12,7 @@
>
> [aihints]
> expansion=true
> +prohibited_till=600
>
> [buildcost]
> log=1
>
> === modified file 'tribes/empire/piggery/conf'
> --- tribes/empire/piggery/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/piggery/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,6 @@
> output=meat
>
> [aihints]
> -build_material=false
>
> [buildcost]
> log=2
>
> === modified file 'tribes/empire/quarry/conf'
> --- tribes/empire/quarry/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/quarry/conf 2014-10-03 21:34:06 +0000
> @@ -3,7 +3,7 @@
> output=marble
>
> [aihints]
> -is_basic=true
> +forced_after=0
> stoneproducer=true
>
> [buildcost]
>
> === modified file 'tribes/empire/sawmill/conf'
> --- tribes/empire/sawmill/conf 2014-07-27 19:32:24 +0000
> +++ tribes/empire/sawmill/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,8 @@
> output=wood
>
> [aihints]
> -is_basic=true
> +forced_after=60
> +prohibited_till=60
>
> [buildcost]
> log=2
>
> === modified file 'tribes/empire/scouts_house/conf'
> --- tribes/empire/scouts_house/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/scouts_house/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,6 @@
> size=small
>
> [aihints]
> -build_material=false
>
> [buildcost]
> log=2
>
> === modified file 'tribes/empire/sheepfarm/conf'
> --- tribes/empire/sheepfarm/conf 2014-07-27 19:32:24 +0000
> +++ tribes/empire/sheepfarm/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,7 @@
> output=wool
>
> [aihints]
> -build_material=false
> +prohibited_till=600
>
> [buildcost]
> log=2
> @@ -39,3 +39,4 @@
> [working]
> pics=sheepfarm_i_??.png # ???
> hotspot=73 60
> +
>
> === modified file 'tribes/empire/shipyard/conf'
> --- tribes/empire/shipyard/conf 2014-09-30 08:05:35 +0000
> +++ tribes/empire/shipyard/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,6 @@
> size=medium
>
> [aihints]
> -build_material=false
> needs_water=true
>
> [buildcost]
>
> === modified file 'tribes/empire/smelting_works/conf'
> --- tribes/empire/smelting_works/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/smelting_works/conf 2014-10-03 21:34:06 +0000
> @@ -3,7 +3,7 @@
> output=gold
>
> [aihints]
> -build_material=false
> +prohibited_till=600
>
> [buildcost]
> log=1
>
> === modified file 'tribes/empire/stonemasons_house/conf'
> --- tribes/empire/stonemasons_house/conf 2014-07-27 19:32:24 +0000
> +++ tribes/empire/stonemasons_house/conf 2014-10-03 21:34:06 +0000
> @@ -2,7 +2,8 @@
> output=marblecolumn
>
> [aihints]
> -is_basic=true
> +forced_after=300
> +prohibited_till=120
>
> [buildcost]
> log=1
>
> === modified file 'tribes/empire/tavern/conf'
> --- tribes/empire/tavern/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/tavern/conf 2014-10-03 21:34:06 +0000
> @@ -3,8 +3,8 @@
> enhancement=inn
>
> [aihints]
> -build_material=false
> -is_food_basic=true
> +forced_after=900
> +prohibited_till=300
>
> [buildcost]
> wood=2
>
> === modified file 'tribes/empire/toolsmithy/conf'
> --- tribes/empire/toolsmithy/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/toolsmithy/conf 2014-10-03 21:34:06 +0000
> @@ -13,8 +13,8 @@
> output=saw
>
> [aihints]
> -build_material=false
> -is_basic=true
> +forced_after=1200
> +prohibited_till=120
>
> [buildcost]
> log=1
>
> === modified file 'tribes/empire/tower/conf'
> --- tribes/empire/tower/conf 2014-07-28 12:48:04 +0000
> +++ tribes/empire/tower/conf 2014-10-03 21:34:06 +0000
> @@ -12,6 +12,7 @@
>
> [aihints]
> mountain_conqueror=true
> +prohibited_till=300
>
> [buildcost]
> log=2
>
> === modified file 'tribes/empire/trainingcamp/conf'
> --- tribes/empire/trainingcamp/conf 2014-07-27 19:32:24 +0000
> +++ tribes/empire/trainingcamp/conf 2014-10-03 21:34:06 +0000
> @@ -125,3 +125,6 @@
> [idle]
> pics=trainingcamp_i_??.png # ???
> hotspot=82 105
> +
> +[aihints]
> +prohibited_till=2700
>
> === modified file 'tribes/empire/vineyard/conf'
> --- tribes/empire/vineyard/conf 2014-07-27 19:32:24 +0000
> +++ tribes/empire/vineyard/conf 2014-10-03 21:34:06 +0000
> @@ -3,9 +3,7 @@
>
> [aihints]
> space_consumer=true
> -is_basic=true
> -build_material=false
> -is_food_basic=true
> +forced_after=120
>
> [buildcost]
> wood=2
>
> === modified file 'tribes/empire/weaponsmithy/conf'
> --- tribes/empire/weaponsmithy/conf 2014-07-27 19:32:24 +0000
> +++ tribes/empire/weaponsmithy/conf 2014-10-03 21:34:06 +0000
> @@ -6,7 +6,7 @@
> output=war_lance
>
> [aihints]
> -build_material=false
> +prohibited_till=900
>
> [buildcost]
> log=2
>
> === modified file 'tribes/empire/weaving-mill/conf'
> --- tribes/empire/weaving-mill/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/weaving-mill/conf 2014-10-03 21:34:06 +0000
> @@ -43,3 +43,6 @@
> pics=weaving_mill_w_??.png # ???
> hotspot=65 62
> fps=5
> +
> +[aihints]
> +prohibited_till=120
>
> === modified file 'tribes/empire/well/conf'
> --- tribes/empire/well/conf 2014-07-29 09:27:08 +0000
> +++ tribes/empire/well/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=water
>
> [aihints]
> -build_material=false
> mines_water=true
> +prohibited_till=60
>
> [buildcost]
> log=2
>
> === modified file 'tribes/empire/wine/conf'
> --- tribes/empire/wine/conf 2014-07-28 14:04:36 +0000
> +++ tribes/empire/wine/conf 2014-10-03 21:34:06 +0000
> @@ -1,7 +1,7 @@
> help=_This tasty wine is drunk by the miners working the marble and gold mines. It is produced in a winery.
>
> default_target_quantity=20 # currently not used
> -preciousness=2
> +preciousness=8
>
> [idle]
> pics=idle.png
>
> === modified file 'tribes/empire/winery/conf'
> --- tribes/empire/winery/conf 2014-07-27 19:32:24 +0000
> +++ tribes/empire/winery/conf 2014-10-03 21:34:06 +0000
> @@ -2,8 +2,8 @@
> output=wine
>
> [aihints]
> -build_material=false
> -is_food_basic=true
> +forced_after=900
> +prohibited_till=60
>
> [buildcost]
> wood=1
>
--
https://code.launchpad.net/~widelands-dev/widelands/tibor-ai5/+merge/228762
Your team Widelands Developers is subscribed to branch lp:~widelands-dev/widelands/tibor-ai5.
References