Merge lp:~widelands-dev/widelands/AI-fixes into lp:widelands

Proposed by hessenfarmer
Status: Merged
Merged at revision: 9110
Proposed branch: lp:~widelands-dev/widelands/AI-fixes
Merge into: lp:widelands
Diff against target: 411 lines (+73/-48)
11 files modified
data/ai/ai_input_1.wai (+1/-1)
data/ai/ai_input_2.wai (+1/-1)
data/ai/ai_input_3.wai (+1/-1)
data/ai/ai_input_4.wai (+1/-1)
data/tribes/buildings/productionsites/atlanteans/horsefarm/init.lua (+1/-1)
data/tribes/buildings/productionsites/barbarians/barracks/init.lua (+0/-1)
data/tribes/buildings/productionsites/barbarians/cattlefarm/init.lua (+1/-1)
data/tribes/buildings/productionsites/empire/donkeyfarm/init.lua (+1/-1)
data/tribes/wares/coal/init.lua (+4/-4)
src/ai/defaultai.cc (+62/-35)
src/ai/defaultai.h (+0/-1)
To merge this branch: bzr merge lp:~widelands-dev/widelands/AI-fixes
Reviewer Review Type Date Requested Status
Benedikt Straub Approve
hessenfarmer Needs Resubmitting
TiborB Approve
Review via email: mp+367309@code.launchpad.net

Commit message

This fixes improves some behavior in AI performance
Ai is now able to adopt to scenarios to certain extend

Description of the change

Following things changed:
1. barbarian barracks no longer part of basic economy
2. AI expands towards low guarded enemy territory
3. AI builds more economy buildings based on neededness and preciousness od wares
4. AI is less agressive in dismantling. It does not dismantle if plenty of input is available for a building
5. added more decisions to genetics either in build and dismantle loops
6. AI now does properly upgrade barbarian smithies without running into a deadlock of having no smith for the tool smithy.
7. Fixed an issue which prevented AI from building second carrier recruiters

To post a comment you must log in.
Revision history for this message
TiborB (tiborb95) wrote :

From AI code point of view - The changes can be OK, it is hard to say just looking at the code. I presume that you made sure the magic numbers does not repeat - dont forget they are used also in other AI files...
I will do some training once it is approved and merged.
I did not review changes to LUA code..
So for my part it is OK

review: Approve
Revision history for this message
GunChleoc (gunchleoc) wrote :

Found a typo in a comment.

The Lua code does not need reviewing because it will be removed anyway, but we should do a bit of testing.

Revision history for this message
GunChleoc (gunchleoc) wrote :

I gave up on the scenario after connecting 20 farms or so. Multiplayer game ran fine for > 7 hours gametime.

So, this can go in once the branch has been cleaned up :)

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

@Tibor: of course I made sure the numbers are not used elsewhere. Shall I add more comments to explain my changes?

@GunChleoc: will fix the typo ofcourse. I never did any thing in the scenario but watching the AI's doing their job. If you do so you would see significant progress. And you can see that my changes work as desirred. But this was meant for Nordfriese in particular to see whether my changes would solve his issues in the scenario which led him to start working (and making good progress for his own scenario specific AI). However I already had the impression he might be a little bit sadistic with the player to connect all these farms. ;-)

@ both: there is still a line commented out (5710ff in defaultai.cc) I wanted to have a value here that depended on stocklevel vs economy target, but the Code didn't work. I got a crash. So I commented this out as my Skills are to bad for realizing the cause if you know why this would crash you could fix it or give me a hint.

Revision history for this message
GunChleoc (gunchleoc) wrote :

I'll have a look.

Also, I got this:

../src/ai/defaultai.cc: In member function ‘bool DefaultAI::check_productionsites(uint32_t)’:
../src/ai/defaultai.cc:4474:95: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
       1000 < gametime && site.site->can_start_working() && get_stocklevel(*site.bo, gametime) >
                                                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
       (std::abs(management_data.get_military_number_at(168)) / 5)) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/ai/defaultai.cc:4502:46: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
      gametime - site.bo->last_dismantle_time >
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
          (std::abs(management_data.get_military_number_at(169)) / 10 + 1) * 60 * 1000 &&
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Revision history for this message
GunChleoc (gunchleoc) wrote :

I think I found the problem:

(bo.outputs.size() == 1) means that there is 1 entry at index 0.

(tribe_->get_ware_descr(bo.outputs.at(1)) would only be available if bo.outputs.size() > 1

Unlike Lua, C++ starts counting from 0. Actually, Lua is quite exceptional here, since starting from 0 is the usual way of doing arrays.

Revision history for this message
Benedikt Straub (nordfriese) wrote :

Tested it now with the 3rd frisian scenario.

The AI behaved quite well, just some nits:
– It builds mainly blockhouses and small milsites. IMHO it should build preferably bigger milsites near the enemy´s border, even if it´s unguarded.
– It´s still quite confused by the inability to build woodcutters, quarries and mines. It builds useless buildings like taverns (that can be solved by just forbidding everything) and it neglects important buildings like warehouses (are very important there because that´s where the script creates wares you cannot produce yourself).
– There is much free space as a consequence of not having foresters, but space-consuming buildings (reedyard etc) are cramped closely together; but that´s a more general AI-problem.

– I get some compiler warnings:
/home/benedikt/wl/AI-fixes/src/ai/defaultai.cc:2461: Use "TODO(username): <msg>".
/home/benedikt/wl/AI-fixes/src/ai/defaultai.cc:2463: Trailing whitespace at end of line
[1007/1455] Building CXX object src/ai/CMakeFiles/ai.dir/defaultai.cc.o
../src/ai/defaultai.cc: In member function ‘bool DefaultAI::check_productionsites(uint32_t)’:
../src/ai/defaultai.cc:4502:46: warning: comparison of integer expressions of different signedness: ‘uint32_t’ {aka ‘unsigned int’} and ‘int’ [-Wsign-compare]
      gametime - site.bo->last_dismantle_time >
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
          (std::abs(management_data.get_military_number_at(169)) / 10 + 1) * 60 * 1000 &&
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

> But this was meant for Nordfriese in particular to see whether my changes would solve his issues in the scenario which led him to start working (and making good progress for his own scenario specific AI). However I already had the impression he might be a little bit sadistic with the player to connect all these farms. ;-)

Hey ;) The point of this objective is force the player to be almost idle until the enemy is standing right at his gates. And to force him to create a good road network under this pressure, which can be very important for the battles later.
Btw, my own AI is not scenario-specific – it´s a template for every(!) scenario that wants an AI specific to it

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4946. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/531247546.
Appveyor build 4727. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_AI_fixes-4727.

Revision history for this message
TiborB (tiborb95) wrote :

@nordfriese
about warehouses - they are in proportion to productionsites, I dont think AI can have any idea it needs more warehouses in this specific case...

Revision history for this message
TiborB (tiborb95) wrote :

@hessenfarmer

"@Tibor: of course I made sure the numbers are not used elsewhere. Shall I add more comments to explain my changes?"
No, I am fine, I also believe that AI training will settle down these changes. I intend to run 100 iterations as soon as the branch is in trunk..

Revision history for this message
GunChleoc (gunchleoc) wrote :

 > The point of this objective is force the player to be almost idle until the enemy is standing right at his gates. And to force him to create a good road network under this pressure, which can be very important for the battles later.

I get what you're trying to do, but hooking up all these farms is pretty repetitive. Maybe you can come up with some more varied stuff to do while still having some time pressure?

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

@ Nordfriese:
fixed the codecheck warnings.
We should try to forbid useless buildings like the tavern and see what's the effect.
Regarding warehouses the problem was not the number but the distribution. as the script delivers only to one warehouse a time, this is putting the road network under some pressure. therefore I forced at least one second carrrier.
As the gametime evolves I made the experience, that the AI starts to build bigger milsites, however they are normally based on enemy force which is neglectable in this scenario. so the closer you get to an enemy the bigger the chance of big military buildings.

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

@ Nordfriese:
If you want to test this further let us know, if you are finished we could merge this.

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

I still can't get the Ai to build a second carrier producer.

Revision history for this message
TiborB (tiborb95) wrote :

Generally AI can decide:
- it does not need second carrier producer
- it needs it but gives it too low priority

So for further debugging you should know which case it is...

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4962. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/531521221.
Appveyor build 4743. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_AI_fixes-4743.

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

Finally I got the AI to properly build second carrier recruiters depending on size of road network. The issue was that we need to fake a preciousness for this building (similar to barracks). Did some other changes as well to prevent the Ai from dismantling too many productionsites too often.

review: Needs Resubmitting
Revision history for this message
hessenfarmer (stephan-lutz) wrote :

oops I missed to fix the typo which GunChleoc found will be done in final polish

Revision history for this message
TiborB (tiborb95) wrote :

I have one objection, see comment in code

Revision history for this message
Benedikt Straub (nordfriese) wrote :

I´m through with the code review, a couple of nits. Will do more testing soon…

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

@ Tibor:
oops this was a left over of some trials. I don't think we need this anymore will fix this tonight when I am back at my dev machine.
@ Nordfriese
Thanks for the review. Will fix these issues as well. However I replied to some comments below them.

Revision history for this message
GunChleoc (gunchleoc) wrote :

How about we implement preciousness for workers, just like we do for wares? That way, we would not need an ugly hack and could play with how precious they are without having to recompile.

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

@GunChleoc:
I had the same thought but went the easy route for the moment being. Currently we only have 2 buildings recruiting "workers": the barracks and the second carrier recruiter. Both of them are limited for AI (barracks to 1, second carrier to 2 hardcoded) For these reasons I doubt if any effort in this way might be worth the pain.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4978. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/532671043.
Appveyor build 4759. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_AI_fixes-4759.

Revision history for this message
Benedikt Straub (nordfriese) wrote :

Tested, and it performs well. Code LGTM.
Good job :)

review: Approve
Revision history for this message
hessenfarmer (stephan-lutz) wrote :

Ok I will remove the fri03 stuff and merge it then. will be tonight though

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

removed the lua stuff should be good to go now

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

@bunnybot merge

Revision history for this message
GunChleoc (gunchleoc) wrote :

@hessenfarmer Hard-coding stuff in the AI has caused us problems before, e.g. when the Frisians were first introduced. I am fine with merging this now, but can you open a new bug, please?

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

@GunChleoc:
I will do so, however the 2 buildings (barracks, second carrier) are so special, we would need a lot of code to come to the same results (1 barracks, 2 carrier). We also have a lot of other hardcoded stuff regarding these two. But basically the AI just needs to ensure it builds a barracks but not to early to not run in a deadlock and not to late. more the less the same with second carrier. The problem with these buildings is that their demand is not steady, but has big spikes. By this we can't use the decision algorithms for normal buildings producing wares. And therefore just having a preciousness for the soldier and the second carrier would not do the trick. What I can think for is e.g. having them assigned a Normal Ai limit in lua instead of hardcoding the values as it is now.

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

@ GunChleoc:
I forgot to mention that I am pretty sure no matter what precautions we might take a new tribe would lead us to have some changes in Ai as well, as me and my crystal bowl can't foresee every issue that might arise. ;-)
In fact I was led to the current improvements only by the need of Nordfriese and his very special scenarios.

Revision history for this message
GunChleoc (gunchleoc) wrote :

Of course, there will always be things that we haven't thought of. And having too many hard-coded things already does not count as an argument in favor of adding even more of them.

The additional code needed wouldn't be that much, it's just a matter of adding 1 more property to the worker descr objects + AI hints, which I could do easily.

Revision history for this message
hessenfarmer (stephan-lutz) wrote :

For my understanding it is not only that but we should discuss this in the bug report.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'data/ai/ai_input_1.wai'
--- data/ai/ai_input_1.wai 2018-11-09 07:50:37 +0000
+++ data/ai/ai_input_1.wai 2019-05-16 17:52:43 +0000
@@ -166,7 +166,7 @@
166161="79"166161="79"
167162="-56"167162="-56"
168163="-41"168163="-41"
169164="0"169164="55"
170165="-63"170165="-63"
171166="8"171166="8"
172167="-72"172167="-72"
173173
=== modified file 'data/ai/ai_input_2.wai'
--- data/ai/ai_input_2.wai 2018-11-09 07:50:37 +0000
+++ data/ai/ai_input_2.wai 2019-05-16 17:52:43 +0000
@@ -166,7 +166,7 @@
166161="79"166161="79"
167162="-56"167162="-56"
168163="-41"168163="-41"
169164="0"169164="55"
170165="-63"170165="-63"
171166="8"171166="8"
172167="-72"172167="-72"
173173
=== modified file 'data/ai/ai_input_3.wai'
--- data/ai/ai_input_3.wai 2018-11-09 07:50:37 +0000
+++ data/ai/ai_input_3.wai 2019-05-16 17:52:43 +0000
@@ -166,7 +166,7 @@
166161="79"166161="79"
167162="-56"167162="-56"
168163="-41"168163="-41"
169164="0"169164="55"
170165="-63"170165="-63"
171166="8"171166="8"
172167="-72"172167="-72"
173173
=== modified file 'data/ai/ai_input_4.wai'
--- data/ai/ai_input_4.wai 2018-11-09 07:50:37 +0000
+++ data/ai/ai_input_4.wai 2019-05-16 17:52:43 +0000
@@ -166,7 +166,7 @@
166161="79"166161="79"
167162="-56"167162="-56"
168163="-41"168163="-41"
169164="0"169164="55"
170165="-63"170165="-63"
171166="8"171166="8"
172167="-72"172167="-72"
173173
=== modified file 'data/tribes/buildings/productionsites/atlanteans/horsefarm/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/horsefarm/init.lua 2019-03-17 07:20:58 +0000
+++ data/tribes/buildings/productionsites/atlanteans/horsefarm/init.lua 2019-05-16 17:52:43 +0000
@@ -32,7 +32,7 @@
3232
33 aihints = {33 aihints = {
34 recruitment = true,34 recruitment = true,
35 prohibited_till = 61035 prohibited_till = 610,
36 },36 },
3737
38 working_positions = {38 working_positions = {
3939
=== modified file 'data/tribes/buildings/productionsites/barbarians/barracks/init.lua'
--- data/tribes/buildings/productionsites/barbarians/barracks/init.lua 2019-03-13 20:21:20 +0000
+++ data/tribes/buildings/productionsites/barbarians/barracks/init.lua 2019-05-16 17:52:43 +0000
@@ -37,7 +37,6 @@
37 },37 },
3838
39 aihints = {39 aihints = {
40 basic_amount = 1,
41 very_weak_ai_limit = 1,40 very_weak_ai_limit = 1,
42 weak_ai_limit = 2,41 weak_ai_limit = 2,
43 prohibited_till = 92042 prohibited_till = 920
4443
=== modified file 'data/tribes/buildings/productionsites/barbarians/cattlefarm/init.lua'
--- data/tribes/buildings/productionsites/barbarians/cattlefarm/init.lua 2019-03-17 07:20:58 +0000
+++ data/tribes/buildings/productionsites/barbarians/cattlefarm/init.lua 2019-05-16 17:52:43 +0000
@@ -32,7 +32,7 @@
3232
33 aihints = {33 aihints = {
34 recruitment = true,34 recruitment = true,
35 prohibited_till = 61035 prohibited_till = 610,
36 },36 },
3737
38 working_positions = {38 working_positions = {
3939
=== modified file 'data/tribes/buildings/productionsites/empire/donkeyfarm/init.lua'
--- data/tribes/buildings/productionsites/empire/donkeyfarm/init.lua 2019-03-17 07:20:58 +0000
+++ data/tribes/buildings/productionsites/empire/donkeyfarm/init.lua 2019-05-16 17:52:43 +0000
@@ -32,7 +32,7 @@
3232
33 aihints = {33 aihints = {
34 recruitment = true,34 recruitment = true,
35 prohibited_till = 61035 prohibited_till = 610,
36 },36 },
3737
38 working_positions = {38 working_positions = {
3939
=== modified file 'data/tribes/wares/coal/init.lua'
--- data/tribes/wares/coal/init.lua 2017-06-30 15:31:17 +0000
+++ data/tribes/wares/coal/init.lua 2019-05-16 17:52:43 +0000
@@ -14,10 +14,10 @@
14 empire = 2014 empire = 20
15 },15 },
16 preciousness = {16 preciousness = {
17 atlanteans = 1,17 atlanteans = 10,
18 barbarians = 1,18 barbarians = 20,
19 frisians = 6,19 frisians = 40,
20 empire = 120 empire = 10
21 },21 },
2222
23 animations = {23 animations = {
2424
=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc 2019-04-20 05:44:37 +0000
+++ src/ai/defaultai.cc 2019-05-16 17:52:43 +0000
@@ -1326,13 +1326,17 @@
1326 field.nearest_buildable_spot_nearby = std::numeric_limits<uint16_t>::max();1326 field.nearest_buildable_spot_nearby = std::numeric_limits<uint16_t>::max();
1327 field.unowned_buildable_spots_nearby = 0;1327 field.unowned_buildable_spots_nearby = 0;
1328 field.unowned_portspace_vicinity_nearby = 0;1328 field.unowned_portspace_vicinity_nearby = 0;
1329 if (field.unowned_land_nearby > 0) {1329 if (field.unowned_land_nearby > 0 || (field.enemy_owned_land_nearby > 0 &&
1330 field.enemy_military_presence < std::abs(management_data.get_military_number_at(174)) / 10)) {
1330 std::vector<Coords> found_buildable_fields;1331 std::vector<Coords> found_buildable_fields;
13311332
1332 // first looking for unowned buildable spots1333 // first looking for unowned buildable spots
1333 field.unowned_buildable_spots_nearby =1334 field.unowned_buildable_spots_nearby =
1334 map.find_fields(Area<FCoords>(field.coords, kBuildableSpotsCheckArea),1335 map.find_fields(Area<FCoords>(field.coords, kBuildableSpotsCheckArea),
1335 &found_buildable_fields, find_unowned_buildable);1336 &found_buildable_fields, find_unowned_buildable);
1337 field.unowned_buildable_spots_nearby +=
1338 map.find_fields(Area<FCoords>(field.coords, kBuildableSpotsCheckArea),
1339 &found_buildable_fields, find_enemy_owned_walkable);
1336 // Now iterate over fields to collect statistics1340 // Now iterate over fields to collect statistics
1337 for (auto& coords : found_buildable_fields) {1341 for (auto& coords : found_buildable_fields) {
1338 // We are not interested in blocked fields1342 // We are not interested in blocked fields
@@ -2452,8 +2456,19 @@
2452 for (uint32_t j = 0; j < buildings_.size(); ++j) {2456 for (uint32_t j = 0; j < buildings_.size(); ++j) {
2453 BuildingObserver& bo = buildings_.at(j);2457 BuildingObserver& bo = buildings_.at(j);
24542458
2459 // we check if a previously not buildable Building of the basic economy is buildable again
2460 // If so and we don't have basic economy achieved we add readd it to basic buildings list
2461 // This should only happen in scenarios via scripting
2462 if (!basic_economy_established && bo.basic_amount > static_cast<uint32_t>(bo.total_count()) && bo.buildable(*player_)) {
2463 persistent_data->remaining_basic_buildings.emplace(std::make_pair(bo.id, bo.basic_amount));
2464 }
2455 if (!bo.buildable(*player_)) {2465 if (!bo.buildable(*player_)) {
2456 bo.new_building = BuildingNecessity::kNotNeeded;2466 bo.new_building = BuildingNecessity::kNotNeeded;
2467 // This line removes buildings from basic economy if they are not allowed for the player
2468 // this should only happen by scripting.
2469 if (bo.basic_amount) {
2470 persistent_data->remaining_basic_buildings.erase(bo.id);
2471 }
2457 } else if (bo.type == BuildingObserver::Type::kProductionsite ||2472 } else if (bo.type == BuildingObserver::Type::kProductionsite ||
2458 bo.type == BuildingObserver::Type::kMine) {2473 bo.type == BuildingObserver::Type::kMine) {
24592474
@@ -2947,6 +2962,7 @@
2947 }2962 }
29482963
2949 } else if (bo.is(BuildingAttribute::kRecruitment)) {2964 } else if (bo.is(BuildingAttribute::kRecruitment)) {
2965 bo.max_needed_preciousness = 2;
2950 prio += bo.primary_priority;2966 prio += bo.primary_priority;
2951 prio -= bf->unowned_land_nearby * 2;2967 prio -= bf->unowned_land_nearby * 2;
2952 prio -= (bf->enemy_nearby) * 100;2968 prio -= (bf->enemy_nearby) * 100;
@@ -3749,12 +3765,11 @@
3749 }3765 }
3750 }3766 }
37513767
3752 // if we are within grace time, it is OK, just go on3768 // check if we are within grace time, if not or gracetime unset we need to do something
3753 if (eco->dismantle_grace_time > gametime &&3769 // if we are within gracetime we do nothing (this loop is skipped)
3754 eco->dismantle_grace_time != std::numeric_limits<uint32_t>::max()) {3770
3755 // if grace time is not set, this is probably first time without a warehouse and we must3771 // if grace time is not set, this is probably first time without a warehouse and we must set it
3756 // set it3772 if (eco->dismantle_grace_time == std::numeric_limits<uint32_t>::max()) {
3757 } else if (eco->dismantle_grace_time == std::numeric_limits<uint32_t>::max()) {
37583773
3759 // constructionsites3774 // constructionsites
3760 if (upcast(ConstructionSite const, constructionsite, flag.get_building())) {3775 if (upcast(ConstructionSite const, constructionsite, flag.get_building())) {
@@ -3784,7 +3799,7 @@
3784 }3799 }
37853800
3786 // we have passed grace_time - it is time to dismantle3801 // we have passed grace_time - it is time to dismantle
3787 } else {3802 } else if (eco->dismantle_grace_time <= gametime) {
3788 last_attempt_ = true;3803 last_attempt_ = true;
3789 // we increase a check radius in last attempt3804 // we increase a check radius in last attempt
3790 checkradius += 2;3805 checkradius += 2;
@@ -4104,7 +4119,8 @@
41044119
4105 // do not dismantle or upgrade the same type of building too soon - to give some time to update4120 // do not dismantle or upgrade the same type of building too soon - to give some time to update
4106 // statistics4121 // statistics
4107 if (site.bo->last_dismantle_time > game().get_gametime() - 30 * 1000) {4122 if (site.bo->last_dismantle_time > game().get_gametime() -
4123 (std::abs(management_data.get_military_number_at(164)) / 25 + 1) * 60 * 1000) {
4108 return false;4124 return false;
4109 }4125 }
41104126
@@ -4210,11 +4226,11 @@
4210 (en_bo.cnt_under_construction + en_bo.unoccupied_count) == 0) {4226 (en_bo.cnt_under_construction + en_bo.unoccupied_count) == 0) {
42114227
4212 // forcing first upgrade4228 // forcing first upgrade
4213 if (en_bo.total_count() == 0) {4229 if (en_bo.total_count() == 0 && (site.bo->cnt_built > 1 || site.bo->is(BuildingAttribute::kUpgradeSubstitutes))) {
4214 doing_upgrade = true;4230 doing_upgrade = true;
4215 }4231 }
42164232
4217 if (en_bo.total_count() == 1) {4233 if (en_bo.total_count() == 1 && (site.bo->cnt_built > 1 || site.bo->is(BuildingAttribute::kUpgradeSubstitutes))) {
4218 if (en_bo.current_stats > 55) {4234 if (en_bo.current_stats > 55) {
4219 doing_upgrade = true;4235 doing_upgrade = true;
4220 }4236 }
@@ -4441,7 +4457,8 @@
44414457
4442 // if we have more buildings then target4458 // if we have more buildings then target
4443 if ((site.bo->cnt_built - site.bo->unconnected_count) > site.bo->cnt_target &&4459 if ((site.bo->cnt_built - site.bo->unconnected_count) > site.bo->cnt_target &&
4444 site.unoccupied_till + 10 * 60 * 1000 < gametime && site.site->can_start_working()) {4460 site.unoccupied_till + (std::abs(management_data.get_military_number_at(166)) / 5 + 1) * 60 *
4461 1000 < gametime && site.site->can_start_working()) {
44454462
4446 if (site.site->get_statistics_percent() < 30 && get_stocklevel(*site.bo, gametime) > 100) {4463 if (site.site->get_statistics_percent() < 30 && get_stocklevel(*site.bo, gametime) > 100) {
4447 site.bo->last_dismantle_time = game().get_gametime();4464 site.bo->last_dismantle_time = game().get_gametime();
@@ -4456,7 +4473,9 @@
44564473
4457 // a building can be dismanteld if it performs too bad, if it is not the last one4474 // a building can be dismanteld if it performs too bad, if it is not the last one
4458 if (site.site->get_statistics_percent() <= 10 && site.bo->cnt_built > 1 &&4475 if (site.site->get_statistics_percent() <= 10 && site.bo->cnt_built > 1 &&
4459 site.unoccupied_till + 10 * 60 * 1000 < gametime && site.site->can_start_working()) {4476 site.unoccupied_till + (std::abs(management_data.get_military_number_at(167)) / 5 + 1) * 60 *
4477 1000 < gametime && site.site->can_start_working() && get_stocklevel(*site.bo, gametime) >
4478 (std::abs(management_data.get_military_number_at(168)) / 5)) {
44604479
4461 if (connected_to_wh) {4480 if (connected_to_wh) {
4462 game().send_player_dismantle(*site.site);4481 game().send_player_dismantle(*site.site);
@@ -4483,7 +4502,8 @@
4483 site.site->can_start_working() &&4502 site.site->can_start_working() &&
4484 check_building_necessity(*site.bo, PerfEvaluation::kForDismantle, gametime) ==4503 check_building_necessity(*site.bo, PerfEvaluation::kForDismantle, gametime) ==
4485 BuildingNecessity::kNotNeeded &&4504 BuildingNecessity::kNotNeeded &&
4486 gametime - site.bo->last_dismantle_time > 5 * 60 * 1000 &&4505 gametime - site.bo->last_dismantle_time >
4506 static_cast<uint32_t>((std::abs(management_data.get_military_number_at(169)) / 5 + 1) * 60 * 1000) &&
44874507
4488 site.bo->current_stats > site.site->get_statistics_percent() && // underperformer4508 site.bo->current_stats > site.site->get_statistics_percent() && // underperformer
4489 (game().get_gametime() - site.unoccupied_till) > 10 * 60 * 1000) {4509 (game().get_gametime() - site.unoccupied_till) > 10 * 60 * 1000) {
@@ -4821,7 +4841,6 @@
4821BuildingNecessity DefaultAI::check_building_necessity(BuildingObserver& bo,4841BuildingNecessity DefaultAI::check_building_necessity(BuildingObserver& bo,
4822 const PerfEvaluation purpose,4842 const PerfEvaluation purpose,
4823 const uint32_t gametime) {4843 const uint32_t gametime) {
4824
4825 bo.primary_priority = 0;4844 bo.primary_priority = 0;
48264845
4827 static BasicEconomyBuildingStatus site_needed_for_economy = BasicEconomyBuildingStatus::kNone;4846 static BasicEconomyBuildingStatus site_needed_for_economy = BasicEconomyBuildingStatus::kNone;
@@ -4935,11 +4954,11 @@
4935 if (!basic_economy_established) {4954 if (!basic_economy_established) {
4936 return BuildingNecessity::kForbidden;4955 return BuildingNecessity::kForbidden;
4937 }4956 }
4938 const uint16_t min_roads_count = 50 + std::abs(management_data.get_military_number_at(33));4957 const uint16_t min_roads_count = 40 + std::abs(management_data.get_military_number_at(33)) / 2;
4939 if (roads.size() < min_roads_count) {4958 if (roads.size() < static_cast<size_t>(min_roads_count * (1 + bo.total_count()))) {
4940 return BuildingNecessity::kForbidden;4959 return BuildingNecessity::kForbidden;
4941 }4960 }
4942 bo.primary_priority = (roads.size() - min_roads_count) *4961 bo.primary_priority += (roads.size() - min_roads_count * (1 + bo.total_count())) *
4943 (2 + std::abs(management_data.get_military_number_at(143)) / 5);4962 (2 + std::abs(management_data.get_military_number_at(143)) / 5);
4944 return BuildingNecessity::kNeeded;4963 return BuildingNecessity::kNeeded;
4945 }4964 }
@@ -5054,7 +5073,7 @@
5054 get_building_observer(tribe_->get_building_descr(enhancement)->name().c_str());5073 get_building_observer(tribe_->get_building_descr(enhancement)->name().c_str());
5055 if ((gametime > 30 * 60 * 1000 && en_bo.total_count() == 0) || gametime > 90 * 60 * 1000) {5074 if ((gametime > 30 * 60 * 1000 && en_bo.total_count() == 0) || gametime > 90 * 60 * 1000) {
5056 // We fake this5075 // We fake this
5057 bo.max_needed_preciousness = bo.max_preciousness;5076 bo.max_needed_preciousness = bo.max_preciousness * 2;
5058 needs_second_for_upgrade = true;5077 needs_second_for_upgrade = true;
5059 }5078 }
5060 }5079 }
@@ -5103,9 +5122,9 @@
5103 inputs[8] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? +3 : 0;5122 inputs[8] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? +3 : 0;
5104 inputs[9] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0;5123 inputs[9] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0;
5105 inputs[10] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0;5124 inputs[10] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0;
5106 inputs[11] = (bo.last_building_built + 5 * 60 * 100 > gametime) ? +1 : 0;5125 inputs[11] = (bo.last_building_built + 5 * 60 * 100 < gametime) ? +1 : 0;
5107 inputs[12] = (bo.last_building_built + 10 * 60 * 100 > gametime) ? +1 : 0;5126 inputs[12] = (bo.last_building_built + 10 * 60 * 100 < gametime) ? +1 : 0;
5108 inputs[13] = (bo.last_building_built + 20 * 60 * 100 > gametime) ? +1 : 0;5127 inputs[13] = (bo.last_building_built + 20 * 60 * 100 < gametime) ? +1 : 0;
5109 inputs[14] = (bo.total_count() >= bo.cnt_target) ? -1 : 0;5128 inputs[14] = (bo.total_count() >= bo.cnt_target) ? -1 : 0;
5110 inputs[15] = (bo.total_count() >= bo.cnt_target) ? -2 : 0;5129 inputs[15] = (bo.total_count() >= bo.cnt_target) ? -2 : 0;
5111 inputs[16] = (bo.total_count() < bo.cnt_target) ? -1 : 0;5130 inputs[16] = (bo.total_count() < bo.cnt_target) ? -1 : 0;
@@ -5150,7 +5169,7 @@
5150 if (bo.total_count() > 1 && (bo.cnt_under_construction + bo.unoccupied_count > 0)) {5169 if (bo.total_count() > 1 && (bo.cnt_under_construction + bo.unoccupied_count > 0)) {
5151 return BuildingNecessity::kForbidden;5170 return BuildingNecessity::kForbidden;
5152 }5171 }
5153 bo.cnt_target = 3;5172 bo.cnt_target = 2;
5154 // adjusting/decreasing based on cnt_limit_by_aimode5173 // adjusting/decreasing based on cnt_limit_by_aimode
5155 bo.cnt_target = std::min(bo.cnt_target, bo.cnt_limit_by_aimode);5174 bo.cnt_target = std::min(bo.cnt_target, bo.cnt_limit_by_aimode);
51565175
@@ -5173,8 +5192,7 @@
5173 } else if (bo.is(BuildingAttribute::kRanger)) {5192 } else if (bo.is(BuildingAttribute::kRanger)) {
51745193
5175 // making sure we have one completed lumberjack5194 // making sure we have one completed lumberjack
5176 if (bo.total_count() > 0 &&5195 if (get_building_observer(BuildingAttribute::kLumberjack).cnt_built < 1) {
5177 get_building_observer(BuildingAttribute::kLumberjack).cnt_built < 1) {
5178 return BuildingNecessity::kForbidden;5196 return BuildingNecessity::kForbidden;
5179 }5197 }
51805198
@@ -5455,11 +5473,10 @@
5455 inputs[14] = (bo.current_stats - 50) / 10;5473 inputs[14] = (bo.current_stats - 50) / 10;
5456 inputs[15] = management_data.get_military_number_at(123) / 10;5474 inputs[15] = management_data.get_military_number_at(123) / 10;
5457 inputs[16] = 0;5475 inputs[16] = 0;
5458 // TODO(GunChleoc): This is overwritten below due to a typo5476 inputs[17] = (inputs_on_stock) ? 0 : -2;
5459 // inputs[17] = (inputs_on_stock) ? 0 : -2;
5460 inputs[18] = (suppliers_exist) ? 0 : -3;5477 inputs[18] = (suppliers_exist) ? 0 : -3;
5461 inputs[17] = (inputs_on_stock) ? 0 : -4;5478 ;
5462 // Nothing on inputs[19]5479 inputs[19] = (inputs_on_stock) ? 0 : -4;
5463 inputs[20] =5480 inputs[20] =
5464 (mines_per_type[bo.mines].in_construction + mines_per_type[bo.mines].finished == 1) ?5481 (mines_per_type[bo.mines].in_construction + mines_per_type[bo.mines].finished == 1) ?
5465 3 :5482 3 :
@@ -5516,7 +5533,7 @@
5516 inputs[0] = (bo.total_count() <= 1) ?5533 inputs[0] = (bo.total_count() <= 1) ?
5517 std::abs(management_data.get_military_number_at(110)) / 10 :5534 std::abs(management_data.get_military_number_at(110)) / 10 :
5518 0;5535 0;
5519 inputs[1] = -2 * bo.total_count();5536 inputs[1] = bo.total_count() * -3 / 2;
5520 inputs[2] =5537 inputs[2] =
5521 (bo.total_count() == 0) ? std::abs(management_data.get_military_number_at(0)) / 10 : 0;5538 (bo.total_count() == 0) ? std::abs(management_data.get_military_number_at(0)) / 10 : 0;
5522 inputs[3] = (gametime >= 25 * 60 * 1000 && bo.inputs.empty()) ?5539 inputs[3] = (gametime >= 25 * 60 * 1000 && bo.inputs.empty()) ?
@@ -5529,11 +5546,11 @@
5529 management_data.get_military_number_at(3) / 10 :5546 management_data.get_military_number_at(3) / 10 :
5530 0;5547 0;
5531 inputs[6] = (needs_second_for_upgrade) ?5548 inputs[6] = (needs_second_for_upgrade) ?
5532 std::abs(management_data.get_military_number_at(4)) / 10 :5549 std::abs(management_data.get_military_number_at(4)) / 5 :
5533 0;5550 0;
5534 inputs[7] = (bo.cnt_under_construction + bo.unoccupied_count) * -1 *5551 inputs[7] = (bo.cnt_under_construction + bo.unoccupied_count) * -1 *
5535 std::abs(management_data.get_military_number_at(9)) / 5;5552 std::abs(management_data.get_military_number_at(9)) / 5;
5536 inputs[8] = (!bo.outputs.empty() && bo.current_stats > 30 + 70 / bo.outputs.size()) ?5553 inputs[8] = (!bo.outputs.empty() && bo.current_stats > 25 + 70 / bo.outputs.size()) ?
5537 management_data.get_military_number_at(7) / 8 :5554 management_data.get_military_number_at(7) / 8 :
5538 0;5555 0;
5539 inputs[9] = (bo.is(BuildingAttribute::kBuildingMatProducer)) ?5556 inputs[9] = (bo.is(BuildingAttribute::kBuildingMatProducer)) ?
@@ -5559,7 +5576,7 @@
5559 management_data.get_military_number_at(97) / 10 :5576 management_data.get_military_number_at(97) / 10 :
5560 0;5577 0;
5561 inputs[17] =5578 inputs[17] =
5562 (spots_ > kSpotsEnough) ? std::abs(management_data.get_military_number_at(74)) / 10 : 0;5579 (spots_ > kSpotsEnough) ? std::abs(management_data.get_military_number_at(74)) / 8 : 0;
5563 inputs[18] = management_data.get_military_number_at(98) / 10;5580 inputs[18] = management_data.get_military_number_at(98) / 10;
5564 inputs[19] = (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) ?5581 inputs[19] = (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) ?
5565 -1 * std::abs(management_data.get_military_number_at(40)) / 10 :5582 -1 * std::abs(management_data.get_military_number_at(40)) / 10 :
@@ -5592,7 +5609,7 @@
5592 inputs[32] = bo.max_needed_preciousness / 2;5609 inputs[32] = bo.max_needed_preciousness / 2;
5593 inputs[33] = -(bo.cnt_under_construction + bo.unoccupied_count) * 4;5610 inputs[33] = -(bo.cnt_under_construction + bo.unoccupied_count) * 4;
5594 if (bo.cnt_built > 0 && !bo.outputs.empty() && !bo.inputs.empty()) {5611 if (bo.cnt_built > 0 && !bo.outputs.empty() && !bo.inputs.empty()) {
5595 inputs[34] += bo.current_stats / 10;5612 inputs[34] += bo.current_stats / std::abs(management_data.get_military_number_at(192)) * 10;
5596 }5613 }
5597 inputs[35] = (!bo.outputs.empty() && !bo.inputs.empty() &&5614 inputs[35] = (!bo.outputs.empty() && !bo.inputs.empty() &&
5598 bo.current_stats > 10 + 70 / bo.outputs.size()) ?5615 bo.current_stats > 10 + 70 / bo.outputs.size()) ?
@@ -5703,6 +5720,14 @@
5703 inputs[105] = -2;5720 inputs[105] = -2;
5704 inputs[106] = -2;5721 inputs[106] = -2;
5705 }5722 }
5723 inputs[107] = std::abs(management_data.get_military_number_at(194)) - get_stocklevel(bo, gametime);
5724 inputs[108] = std::abs(management_data.get_military_number_at(191)) - get_stocklevel(bo, gametime);
5725 inputs[109] = (!bo.inputs.empty() && gametime > 50 * 60 * 1000 && bo.total_count() <= 1) ?
5726 std::abs(management_data.get_military_number_at(163)) / 10 : 0;
5727 inputs[110] = (bo.outputs.size() == 1) ?
5728 (tribe_->get_ware_descr(bo.outputs.at(0))->default_target_quantity(tribe_->name()) -
5729 get_stocklevel(bo, gametime)) * std::abs(management_data.get_military_number_at(165)) / 20 : 0;
5730 inputs[111] = bo.current_stats / (bo.outputs.size() + 1);
57065731
5707 int16_t tmp_score = 0;5732 int16_t tmp_score = 0;
5708 for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {5733 for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {
@@ -5779,7 +5804,9 @@
5779 return BuildingNecessity::kNeeded;5804 return BuildingNecessity::kNeeded;
5780 } else if (bo.max_preciousness >= 10 && bo.total_count() == 2) {5805 } else if (bo.max_preciousness >= 10 && bo.total_count() == 2) {
5781 return BuildingNecessity::kNeeded;5806 return BuildingNecessity::kNeeded;
5782 } else if (!bo.outputs.empty() && bo.current_stats > (10 + 70 / bo.outputs.size()) / 2) {5807 } else if (!bo.outputs.empty() && bo.current_stats > (10 + 60 / bo.outputs.size()) / 2) {
5808 return BuildingNecessity::kNeeded;
5809 } else if (bo.inputs.size() == 1 && calculate_stocklevel(static_cast<size_t>(bo.inputs.at(0))) > std::abs(management_data.get_military_number_at(171))) {
5783 return BuildingNecessity::kNeeded;5810 return BuildingNecessity::kNeeded;
5784 } else {5811 } else {
5785 return BuildingNecessity::kNotNeeded;5812 return BuildingNecessity::kNotNeeded;
57865813
=== modified file 'src/ai/defaultai.h'
--- src/ai/defaultai.h 2019-02-23 11:00:49 +0000
+++ src/ai/defaultai.h 2019-05-16 17:52:43 +0000
@@ -212,7 +212,6 @@
212212
213 uint32_t get_stocklevel_by_hint(size_t);213 uint32_t get_stocklevel_by_hint(size_t);
214 uint32_t get_stocklevel(Widelands::BuildingObserver&, uint32_t, WareWorker = WareWorker::kWare);214 uint32_t get_stocklevel(Widelands::BuildingObserver&, uint32_t, WareWorker = WareWorker::kWare);
215 uint32_t calculate_stocklevel(Widelands::BuildingObserver&, WareWorker = WareWorker::kWare);
216 uint32_t calculate_stocklevel(Widelands::DescriptionIndex,215 uint32_t calculate_stocklevel(Widelands::DescriptionIndex,
217 WareWorker = WareWorker::kWare); // count all direct outputs_216 WareWorker = WareWorker::kWare); // count all direct outputs_
218217

Subscribers

People subscribed via source and target branches

to status/vote changes: