widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #04711
[Merge] lp:~widelands-dev/widelands/ai_differentiation into lp:widelands
TiborB has proposed merging lp:~widelands-dev/widelands/ai_differentiation into lp:widelands.
Requested reviews:
Widelands Developers (widelands-dev)
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/ai_differentiation/+merge/278517
This is bunch of changes to allow limitting the number of buildings per difficulty level, it introduces two new flags for init.lua files weak_ai_limit and normal_ai_limit to limit number of buildings. And related changes to C++ code.
Also I fixed couple of small issues, related to upgrade of buildings and so on, the ones I run into during testing.
I populated init.lua files somehow but they would need more attention. Anyway, a rough testing shows promising results...
What is open is renaming of levels (we discussed about this on forum). So I have not renamed them yet.
--
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/ai_differentiation into lp:widelands.
=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h 2015-11-21 18:25:56 +0000
+++ src/ai/ai_help_structs.h 2015-11-24 21:27:31 +0000
@@ -43,7 +43,7 @@
enum class ExtendedBool : uint8_t {kUnset, kTrue, kFalse};
enum class BuildingNecessity : uint8_t
- {kForced, kNeeded, kNotNeeded, kUnset, kNotBuildable, kAllowed, kNeededPending};
+ {kForced, kNeeded, kNotNeeded, kUnset, kNotBuildable, kAllowed, kNeededPending, kForbidden};
enum class SchedulerTaskId : uint8_t {
kBbuildableFieldsCheck,
kMineableFieldsCheck,
@@ -443,12 +443,13 @@
int32_t cnt_built_;
int32_t cnt_under_construction_;
int32_t cnt_target_; // number of buildings as target
+ int32_t cnt_limit_by_aimode_; // limit imposed by weak or normal AI mode
// used to track amount of wares produced by building
uint32_t stocklevel_;
- int32_t stocklevel_time; // time when stocklevel_ was last time recalculated
- int32_t last_dismantle_time_;
- int32_t construction_decision_time_;
+ uint32_t stocklevel_time; // time when stocklevel_ was last time recalculated
+ uint32_t last_dismantle_time_;
+ uint32_t construction_decision_time_;
uint32_t unoccupied_count_;
=== modified file 'src/ai/ai_hints.cc'
--- src/ai/ai_hints.cc 2015-10-25 08:06:00 +0000
+++ src/ai/ai_hints.cc 2015-11-24 21:27:31 +0000
@@ -40,6 +40,8 @@
// 10 days default
forced_after_(table->has_key("forced_after") ? table->get_int("forced_after") : 864000),
mines_percent_(table->has_key("mines_percent") ? table->get_int("mines_percent") : 100),
+ weak_ai_limit_(table->has_key("weak_ai_limit") ? table->get_int("weak_ai_limit") : -1),
+ normal_ai_limit_(table->has_key("normal_ai_limit") ? table->get_int("normal_ai_limit") : -1),
trainingsite_type_(TrainingSiteType::kNoTS) {
if (table->has_key("trainingsite_type")) {
=== modified file 'src/ai/ai_hints.h'
--- src/ai/ai_hints.h 2015-11-02 08:01:37 +0000
+++ src/ai/ai_hints.h 2015-11-24 21:27:31 +0000
@@ -102,6 +102,14 @@
return mines_percent_;
}
+ int16_t get_weak_ai_limit() const {
+ return weak_ai_limit_;
+ }
+
+ int16_t get_normal_ai_limit() const {
+ return normal_ai_limit_;
+ }
+
TrainingSiteType get_trainingsite_type() const {
return trainingsite_type_;
}
@@ -121,7 +129,9 @@
bool shipyard_;
int32_t prohibited_till_;
int32_t forced_after_;
- uint8_t mines_percent_;
+ int8_t mines_percent_;
+ int16_t weak_ai_limit_;
+ int16_t normal_ai_limit_;
TrainingSiteType trainingsite_type_;
DISALLOW_COPY_AND_ASSIGN(BuildingHints);
=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc 2015-11-22 19:26:11 +0000
+++ src/ai/defaultai.cc 2015-11-24 21:27:31 +0000
@@ -512,6 +512,7 @@
bo.cnt_built_ = 0;
bo.cnt_under_construction_ = 0;
bo.cnt_target_ = 1; // default for everything
+ bo.cnt_limit_by_aimode_ = std::numeric_limits<int32_t>::max();
bo.stocklevel_ = 0;
bo.stocklevel_time = 0;
bo.last_dismantle_time_ = 0;
@@ -556,6 +557,22 @@
bo.plants_trees_ = false;
}
+ // Is total count of this building limited by AI mode?
+ if (type_ == DEFENSIVE && bh.get_weak_ai_limit() >= 0) {
+ bo.cnt_limit_by_aimode_ = bh.get_weak_ai_limit();
+ log (" %d: AI defensive mode: applying limit %d building(s) for %s\n",
+ player_number(),
+ bo.cnt_limit_by_aimode_,
+ bo.name);
+ }
+ if (type_ == NORMAL && bh.get_normal_ai_limit() >= 0) {
+ bo.cnt_limit_by_aimode_ = bh.get_normal_ai_limit();
+ log (" %d: AI normal mode: applying limit %d building(s) for %s\n",
+ player_number(),
+ bo.cnt_limit_by_aimode_,
+ bo.name);
+ }
+
// Read all interesting data from ware producing buildings
if (bld.type() == MapObjectType::PRODUCTIONSITE) {
const ProductionSiteDescr& prod = dynamic_cast<const ProductionSiteDescr&>(bld);
@@ -1686,11 +1703,21 @@
throw wexception("AI: Max presciousness must not be <= 0 for building: %s",
bo.desc->name().c_str());
}
- } else {
- // For other situations we set max_needed_preciousness_ to zero
+ } else if (bo.new_building_ == BuildingNecessity::kForbidden) {
bo.max_needed_preciousness_ = 0;
+ } else {
+ // For other situations we make sure max_needed_preciousness_ is zero
+ assert (bo.max_needed_preciousness_ == 0);
}
+ // Positive max_needed_preciousness_ says a building type is needed
+ // here we increase or reset the counter
+ // The counter is added to score when considering new building
+ if (bo.max_needed_preciousness_ > 0) {
+ bo.new_building_overdue_ += 1;
+ } else {
+ bo.new_building_overdue_ = 0;
+ }
// Here we consider a time how long a building needed
// We calculate primary_priority used later in construct_building(),
@@ -1734,7 +1761,13 @@
} else if (bo.type == BuildingObserver::MILITARYSITE) {
bo.new_building_ = check_building_necessity(bo.desc->get_size(), gametime);
- } else if (bo.type == BuildingObserver::TRAININGSITE && bo.build_material_shortage_) {
+ } else if (bo.type == BuildingObserver::TRAININGSITE
+ && // if we dont have enough build material or are above target of current ai mode
+ (bo.build_material_shortage_
+ ||
+ bo.total_count() - bo.unconnected_count_ >= bo.cnt_limit_by_aimode_)) {
+ bo.new_building_ = BuildingNecessity::kNotNeeded;
+ } else if (bo.total_count() - bo.unconnected_count_ >= bo.cnt_limit_by_aimode_) {
bo.new_building_ = BuildingNecessity::kNotNeeded;
} else {
bo.new_building_ = BuildingNecessity::kAllowed;
@@ -1778,7 +1811,8 @@
}
if (bo.new_building_ == BuildingNecessity::kNotNeeded ||
- bo.new_building_ == BuildingNecessity::kNeededPending) {
+ bo.new_building_ == BuildingNecessity::kNeededPending ||
+ bo.new_building_ == BuildingNecessity::kForbidden) {
continue;
}
@@ -3096,12 +3130,14 @@
const DescriptionIndex enhancement = site.site->descr().enhancement();
if (connected_to_wh && enhancement != INVALID_INDEX &&
- (site.bo->cnt_built_ - site.bo->unoccupied_count_ > 1 ||
- ((site.bo->upgrade_substitutes_ || site.bo->upgrade_extends_) &&
+ // if upgrade does not subsitute, we need to have two buildings at least
+ ((site.bo->cnt_built_ - site.bo->unoccupied_count_ > 1 && site.bo->upgrade_extends_)
+ ||
+ site.bo->upgrade_substitutes_) &&
gametime > 45 * 60 * 1000 &&
- gametime > site.built_time_ + 20 * 60 * 1000))) {
+ gametime > site.built_time_ + 20 * 60 * 1000) {
- DescriptionIndex enbld = INVALID_INDEX; // to get rid of this
+ //DescriptionIndex enbld = INVALID_INDEX; // to get rid of this
// Only enhance buildings that are allowed (scenario mode)
// do not do decisions too fast
@@ -3109,9 +3145,9 @@
const BuildingDescr& bld = *tribe_->get_building_descr(enhancement);
BuildingObserver& en_bo = get_building_observer(bld.name().c_str());
- BuildingObserver* bestbld = nullptr;
+ bool doing_upgrade = false;
- if (gametime - en_bo.construction_decision_time_ >= kBuildingMinInterval &&
+ if (gametime - en_bo.construction_decision_time_ >= 10 * 60 * 1000 &&
(en_bo.cnt_under_construction_ + en_bo.unoccupied_count_) == 0) {
// don't upgrade without workers
@@ -3119,19 +3155,15 @@
// forcing first upgrade
if (en_bo.total_count() == 0) {
- enbld = enhancement;
- bestbld = &en_bo;
+ doing_upgrade = true;
}
// if the decision was not made yet, consider normal upgrade
- if (enbld == INVALID_INDEX) {
+ if (!doing_upgrade) {
// 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;
+ static_cast<int32_t>(site.bo->current_stats_) > 20) {
+ doing_upgrade = true;
}
if ((static_cast<int32_t>(en_bo.current_stats_) > 85 &&
@@ -3139,8 +3171,12 @@
(static_cast<int32_t>(en_bo.current_stats_) > 50 &&
en_bo.total_count() * 4 < site.bo->total_count())) {
- enbld = enhancement;
- bestbld = &en_bo;
+ doing_upgrade = true;
+ }
+
+ // Dont forget about limitation of number of buildings
+ if (en_bo.cnt_limit_by_aimode_ <= en_bo.total_count() - en_bo.unconnected_count_) {
+ doing_upgrade = false;
}
}
}
@@ -3148,10 +3184,9 @@
// 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;
-
+ if (doing_upgrade) {
+ game().send_player_enhance_building(*site.site, enhancement);
+ en_bo.construction_decision_time_ = gametime;
return true;
}
}
@@ -3716,19 +3751,23 @@
const BuildingDescr& bld = *tribe_->get_building_descr(enhancement);
BuildingObserver& en_bo = get_building_observer(bld.name().c_str());
- // if it is too soon for enhancement
- if (gametime - en_bo.construction_decision_time_ >= kBuildingMinInterval) {
- // now verify that there are enough workers
- if (site.site->has_workers(enhancement, game())) { // enhancing
- game().send_player_enhance_building(*site.site, enhancement);
- if (site.bo->max_needed_preciousness_ == 0) {
- assert (mines_per_type[site.bo->mines_].total_count() <= minimal_mines_count);
- }
- if (mines_per_type[site.bo->mines_].total_count() > minimal_mines_count) {
- assert(site.bo->max_needed_preciousness_ > 0);
- }
- en_bo.construction_decision_time_ = gametime;
- changed = true;
+ // Make sure we do not exceed limit given by AI mode
+ if (en_bo.cnt_limit_by_aimode_ >= en_bo.total_count() - en_bo.unconnected_count_) {
+
+ // if it is too soon for enhancement
+ if (gametime - en_bo.construction_decision_time_ >= kBuildingMinInterval) {
+ // now verify that there are enough workers
+ if (site.site->has_workers(enhancement, game())) { // enhancing
+ game().send_player_enhance_building(*site.site, enhancement);
+ if (site.bo->max_needed_preciousness_ == 0) {
+ assert (mines_per_type[site.bo->mines_].total_count() <= minimal_mines_count);
+ }
+ if (mines_per_type[site.bo->mines_].total_count() > minimal_mines_count) {
+ assert(site.bo->max_needed_preciousness_ > 0);
+ }
+ en_bo.construction_decision_time_ = gametime;
+ changed = true;
+ }
}
}
@@ -3760,6 +3799,13 @@
const PerfEvaluation purpose,
const uint32_t gametime) {
+ // Very first we finds if AI is allowed to build such building due to its mode
+ if (purpose == PerfEvaluation::kForConstruction
+ &&
+ bo.total_count() - bo.unconnected_count_ >= bo.cnt_limit_by_aimode_) {
+ return BuildingNecessity::kForbidden;
+ }
+
// First we iterate over outputs of building, count warehoused stock
// and deciding if we have enough on stock (in warehouses)
bo.max_preciousness_ = 0;
@@ -3792,15 +3838,6 @@
assert (bo.max_preciousness_ > 0);
}
- // positive max_needed_preciousness_ says a building type is needed
- // here we increase of reset the counter
- // the counter is added to score when considering new building
- if (bo.max_needed_preciousness_ > 0) {
- bo.new_building_overdue_ += 1;
- } else {
- bo.new_building_overdue_ = 0;
- }
-
// This flag is to be used when buildig is forced. AI will not build another building when
// a substitution exists. F.e. mines or pairs like tavern-inn
// To skip unnecessary calculation, we calculate this only if we have 0 count of the buildings
@@ -3819,6 +3856,28 @@
}
}
+ // Some buildings are upgraded to ones that does not produce current output, so we need to have
+ // two of current buildings to have at least one left after one of them is upgraded
+ // Logic is: after 30th minute we need second building if there is no enhanced building yet,
+ // and after 90th minute we want second building unconditionally
+ bool needs_second_for_upgrade = false;
+ if (gametime > 30 * 60 * 1000 &&
+ bo.cnt_built_ == 1 &&
+ bo.cnt_under_construction_ == 0 &&
+ bo.upgrade_extends_ &&
+ !bo.upgrade_substitutes_ &&
+ bo.type == BuildingObserver::PRODUCTIONSITE) {
+ const DescriptionIndex enhancement = bo.desc->enhancement();
+ BuildingObserver& en_bo
+ = get_building_observer(tribe_->get_building_descr(enhancement)->name().c_str());
+ if ((gametime > 30 * 60 * 1000 && en_bo.total_count() == 0) ||
+ gametime > 90 * 60 * 1000) {
+ // We fake this
+ bo.max_needed_preciousness_ = bo.max_preciousness_;
+ needs_second_for_upgrade = true;
+ }
+ }
+
// This function is going to say if a building is needed. But there is a 'new_buildings_stop_'
// flag that should be obeyed, but sometimes can be ignored.
// So we can have two types of needed: kNeeded and KNeededPending
@@ -3865,25 +3924,28 @@
bo.max_needed_preciousness_ = bo.max_preciousness_;
return BuildingNecessity::kForced;
} else if (bo.prohibited_till_ > gametime) {
- return BuildingNecessity::kNotNeeded;
+ return BuildingNecessity::kForbidden;
} else if (bo.is_hunter_ || bo.is_fisher_) {
if (bo.max_needed_preciousness_ == 0) {
return BuildingNecessity::kNotNeeded;
} else if (bo.cnt_under_construction_ + bo.unoccupied_count_ > 0) {
- return BuildingNecessity::kNotNeeded;
+ return BuildingNecessity::kForbidden;
} else if (bo.total_count() > 0 && new_buildings_stop_) {
- return BuildingNecessity::kNotNeeded;
+ return BuildingNecessity::kForbidden;
} else {
return BuildingNecessity::kNeeded;
}
} else if (bo.need_trees_) {
if (bo.total_count() > 1 && (bo.cnt_under_construction_ + bo.unoccupied_count_ > 0)) {
- return BuildingNecessity::kNotNeeded;
+ return BuildingNecessity::kForbidden;
}
bo.cnt_target_ =
3 + static_cast<int32_t>(mines_.size() + productionsites.size()) / 20;
+ // adjusting/decreasing based on cnt_limit_by_aimode_
+ bo.cnt_target_ = limit_cnt_target(bo.cnt_target_, bo.cnt_limit_by_aimode_);
+
// for case the wood is not needed yet, to avoid inconsistency later on
bo.max_needed_preciousness_ = bo.max_preciousness_;
@@ -3897,17 +3959,21 @@
bo.cnt_target_ =
2 +
static_cast<int32_t>(mines_.size() + productionsites.size()) / 40;
+
+ // adjusting/decreasing based on cnt_limit_by_aimode_
+ bo.cnt_target_ = limit_cnt_target(bo.cnt_target_, bo.cnt_limit_by_aimode_);
+
if (wood_policy_ != WoodPolicy::kAllowRangers) {
- return BuildingNecessity::kNotNeeded;
+ return BuildingNecessity::kForbidden;
}
// 150 corresponds to 15 trees
if (trees_around_cutters_ < 150) {
bo.cnt_target_ *= 4;
}
if (bo.total_count() > 1 && (bo.cnt_under_construction_ + bo.unoccupied_count_ > 0)) {
- return BuildingNecessity::kNotNeeded;
+ return BuildingNecessity::kForbidden;
} else if (bo.total_count() > bo.cnt_target_) {
- return BuildingNecessity::kNotNeeded;
+ return BuildingNecessity::kForbidden;
}
return BuildingNecessity::kNeeded;
} else if (bo.need_rocks_ && bo.cnt_under_construction_ + bo.unoccupied_count_ == 0) {
@@ -3916,11 +3982,11 @@
} else if (bo.production_hint_ >= 0 && bo.cnt_under_construction_ + bo.unoccupied_count_ == 0) {
return BuildingNecessity::kAllowed;
} else if (bo.cnt_under_construction_ + bo.unoccupied_count_ > 0 && bo.max_needed_preciousness_ < 10) {
- return BuildingNecessity::kNotNeeded;
+ return BuildingNecessity::kForbidden;
} else if (bo.cnt_under_construction_ + bo.unoccupied_count_ > 0 && gametime < 30 * 60 * 1000) {
- return BuildingNecessity::kNotNeeded;
+ return BuildingNecessity::kForbidden;
} else if (bo.cnt_under_construction_ + bo.unoccupied_count_ > 1) {
- return BuildingNecessity::kNotNeeded; // for preciousness>=10 and after 30 min
+ return BuildingNecessity::kForbidden; // for preciousness>=10 and after 30 min
} else if (bo.type == BuildingObserver::MINE) {
if ((mines_per_type[bo.mines_].in_construction + mines_per_type[bo.mines_].finished) == 0) {
// unless a mine is prohibited, we want to have at least one of the kind
@@ -3935,8 +4001,8 @@
if (bo.max_needed_preciousness_ == 0) {
return BuildingNecessity::kNotNeeded;
}
- if (bo.total_count() - bo.unconnected_count_ >= 1 || bo.current_stats_ < 20) {
- return BuildingNecessity::kNotNeeded;
+ if (bo.current_stats_ < 40) {
+ return BuildingNecessity::kForbidden;
}
return needed_type;
} if (bo.max_needed_preciousness_ > 0) {
@@ -3955,15 +4021,17 @@
return needed_type;
} else if (bo.current_stats_ > 10 + 70 / bo.outputs_.size()) {
return needed_type;
+ } else if (needs_second_for_upgrade) {
+ return needed_type;
} else {
- return BuildingNecessity::kNotNeeded;
+ return BuildingNecessity::kForbidden;
}
} else if (bo.is_shipyard_) {
return BuildingNecessity::kAllowed;
} else if (bo.max_needed_preciousness_ == 0) {
return BuildingNecessity::kNotNeeded;
} else {
- return BuildingNecessity::kNotNeeded;
+ return BuildingNecessity::kForbidden;
}
} else if (purpose == PerfEvaluation::kForDismantle) { // now for dismantling
// never dismantle last building (a care should be taken elsewhere)
@@ -4115,6 +4183,8 @@
TrainingSite* ts = trainingsites.front().site;
TrainingSiteObserver& tso = trainingsites.front();
+ assert(tso.bo->total_count() <= tso.bo->cnt_limit_by_aimode_);
+
const DescriptionIndex enhancement = ts->descr().enhancement();
if (enhancement != INVALID_INDEX && ts_without_trainers_ == 0 && mines_.size() > 3 &&
@@ -5648,3 +5718,22 @@
value);
}
}
+
+int32_t DefaultAI::limit_cnt_target(const int32_t current_cnt_target, const int32_t ai_limit) {
+
+ if (ai_limit >= std::numeric_limits<int32_t>::max() - 1) {
+ // = ai limit is not set
+ return current_cnt_target;
+ }
+
+ int32_t new_target = current_cnt_target;
+
+ if (current_cnt_target > (ai_limit + 1) / 2) {
+ new_target = (ai_limit + 1) / 2;
+ }
+ assert (new_target * 2 >= ai_limit);
+ assert (new_target > 0);
+ assert (new_target <= ai_limit);
+
+ return new_target;
+}
=== modified file 'src/ai/defaultai.h'
--- src/ai/defaultai.h 2015-11-21 18:25:56 +0000
+++ src/ai/defaultai.h 2015-11-24 21:27:31 +0000
@@ -289,6 +289,8 @@
uint32_t msites_in_constr() const;
uint32_t msites_built() const;
+ int32_t limit_cnt_target(int32_t, int32_t);
+
std::vector<WareObserver> wares;
uint32_t next_ai_think_;
=== modified file 'tribes/buildings/productionsites/atlanteans/sawmill/init.lua'
--- tribes/buildings/productionsites/atlanteans/sawmill/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/atlanteans/sawmill/init.lua 2015-11-24 21:27:31 +0000
@@ -34,7 +34,9 @@
aihints = {
forced_after = 250,
- prohibited_till = 250
+ prohibited_till = 250,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/productionsites/atlanteans/smelting_works/init.lua'
--- tribes/buildings/productionsites/atlanteans/smelting_works/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/atlanteans/smelting_works/init.lua 2015-11-24 21:27:31 +0000
@@ -33,7 +33,9 @@
},
aihints = {
- prohibited_till = 600
+ prohibited_till = 600,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/productionsites/atlanteans/smokery/init.lua'
--- tribes/buildings/productionsites/atlanteans/smokery/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/atlanteans/smokery/init.lua 2015-11-24 21:27:31 +0000
@@ -35,7 +35,9 @@
aihints = {
forced_after = 800,
- prohibited_till = 180
+ prohibited_till = 180,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/productionsites/atlanteans/weaving_mill/init.lua'
--- tribes/buildings/productionsites/atlanteans/weaving_mill/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/atlanteans/weaving_mill/init.lua 2015-11-24 21:27:31 +0000
@@ -35,7 +35,9 @@
aihints = {
forced_after = 600,
- prohibited_till = 450
+ prohibited_till = 450,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/productionsites/barbarians/lime_kiln/init.lua'
--- tribes/buildings/productionsites/barbarians/lime_kiln/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/barbarians/lime_kiln/init.lua 2015-11-24 21:27:31 +0000
@@ -33,7 +33,9 @@
},
aihints = {
- forced_after = 600
+ forced_after = 600,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/productionsites/barbarians/smelting_works/init.lua'
--- tribes/buildings/productionsites/barbarians/smelting_works/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/barbarians/smelting_works/init.lua 2015-11-24 21:27:31 +0000
@@ -36,7 +36,9 @@
},
aihints = {
- prohibited_till = 400
+ prohibited_till = 400,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/productionsites/barbarians/wood_hardener/init.lua'
--- tribes/buildings/productionsites/barbarians/wood_hardener/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/barbarians/wood_hardener/init.lua 2015-11-24 21:27:31 +0000
@@ -43,7 +43,9 @@
aihints = {
forced_after = 250,
- prohibited_till = 250
+ prohibited_till = 250,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/productionsites/empire/brewery/init.lua'
--- tribes/buildings/productionsites/empire/brewery/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/empire/brewery/init.lua 2015-11-24 21:27:31 +0000
@@ -34,7 +34,9 @@
aihints = {
forced_after = 900,
- prohibited_till = 600
+ prohibited_till = 600,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/productionsites/empire/sawmill/init.lua'
--- tribes/buildings/productionsites/empire/sawmill/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/empire/sawmill/init.lua 2015-11-24 21:27:31 +0000
@@ -34,7 +34,9 @@
aihints = {
forced_after = 250,
- prohibited_till = 250
+ prohibited_till = 250,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/productionsites/empire/smelting_works/init.lua'
--- tribes/buildings/productionsites/empire/smelting_works/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/empire/smelting_works/init.lua 2015-11-24 21:27:31 +0000
@@ -39,7 +39,9 @@
},
aihints = {
- prohibited_till = 600
+ prohibited_till = 600,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/productionsites/empire/stonemasons_house/init.lua'
--- tribes/buildings/productionsites/empire/stonemasons_house/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/empire/stonemasons_house/init.lua 2015-11-24 21:27:31 +0000
@@ -35,7 +35,9 @@
aihints = {
forced_after = 400,
- prohibited_till = 400
+ prohibited_till = 400,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/productionsites/empire/winery/init.lua'
--- tribes/buildings/productionsites/empire/winery/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/productionsites/empire/winery/init.lua 2015-11-24 21:27:31 +0000
@@ -36,7 +36,9 @@
aihints = {
forced_after = 600,
- prohibited_till = 600
+ prohibited_till = 600,
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/trainingsites/atlanteans/dungeon/init.lua'
--- tribes/buildings/trainingsites/atlanteans/dungeon/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/trainingsites/atlanteans/dungeon/init.lua 2015-11-24 21:27:31 +0000
@@ -36,7 +36,9 @@
},
aihints = {
- trainingsite_type = "advanced"
+ trainingsite_type = "advanced",
+ weak_ai_limit = 0,
+ normal_ai_limit = 1
},
working_positions = {
=== modified file 'tribes/buildings/trainingsites/atlanteans/labyrinth/init.lua'
--- tribes/buildings/trainingsites/atlanteans/labyrinth/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/trainingsites/atlanteans/labyrinth/init.lua 2015-11-24 21:27:31 +0000
@@ -36,7 +36,9 @@
aihints = {
prohibited_till=900,
- trainingsite_type = "basic"
+ trainingsite_type = "basic",
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/trainingsites/barbarians/battlearena/init.lua'
--- tribes/buildings/trainingsites/barbarians/battlearena/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/trainingsites/barbarians/battlearena/init.lua 2015-11-24 21:27:31 +0000
@@ -52,7 +52,9 @@
aihints = {
prohibited_till = 2700,
- trainingsite_type = "basic"
+ trainingsite_type = "basic",
+ weak_ai_limit = 1,
+ normal_ai_limit = 3
},
working_positions = {
=== modified file 'tribes/buildings/trainingsites/barbarians/trainingcamp/init.lua'
--- tribes/buildings/trainingsites/barbarians/trainingcamp/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/trainingsites/barbarians/trainingcamp/init.lua 2015-11-24 21:27:31 +0000
@@ -45,7 +45,9 @@
aihints = {
prohibited_till = 500,
- trainingsite_type = "advanced"
+ trainingsite_type = "advanced",
+ weak_ai_limit = 0,
+ normal_ai_limit = 1
},
working_positions = {
=== modified file 'tribes/buildings/trainingsites/empire/arena/init.lua'
--- tribes/buildings/trainingsites/empire/arena/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/trainingsites/empire/arena/init.lua 2015-11-24 21:27:31 +0000
@@ -40,7 +40,9 @@
},
aihints = {
- trainingsite_type = "basic"
+ trainingsite_type = "basic",
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/trainingsites/empire/colosseum/init.lua'
--- tribes/buildings/trainingsites/empire/colosseum/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/trainingsites/empire/colosseum/init.lua 2015-11-24 21:27:31 +0000
@@ -34,7 +34,9 @@
},
aihints = {
- trainingsite_type = "basic"
+ trainingsite_type = "basic",
+ weak_ai_limit = 1,
+ normal_ai_limit = 2
},
working_positions = {
=== modified file 'tribes/buildings/trainingsites/empire/trainingcamp/init.lua'
--- tribes/buildings/trainingsites/empire/trainingcamp/init.lua 2015-10-31 12:11:44 +0000
+++ tribes/buildings/trainingsites/empire/trainingcamp/init.lua 2015-11-24 21:27:31 +0000
@@ -36,7 +36,9 @@
aihints = {
prohibited_till = 2700,
- trainingsite_type = "advanced"
+ trainingsite_type = "advanced",
+ weak_ai_limit = 0,
+ normal_ai_limit = 1
},
working_positions = {
Follow ups