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
1=== modified file 'data/ai/ai_input_1.wai'
2--- data/ai/ai_input_1.wai 2018-11-09 07:50:37 +0000
3+++ data/ai/ai_input_1.wai 2019-05-16 17:52:43 +0000
4@@ -166,7 +166,7 @@
5 161="79"
6 162="-56"
7 163="-41"
8-164="0"
9+164="55"
10 165="-63"
11 166="8"
12 167="-72"
13
14=== modified file 'data/ai/ai_input_2.wai'
15--- data/ai/ai_input_2.wai 2018-11-09 07:50:37 +0000
16+++ data/ai/ai_input_2.wai 2019-05-16 17:52:43 +0000
17@@ -166,7 +166,7 @@
18 161="79"
19 162="-56"
20 163="-41"
21-164="0"
22+164="55"
23 165="-63"
24 166="8"
25 167="-72"
26
27=== modified file 'data/ai/ai_input_3.wai'
28--- data/ai/ai_input_3.wai 2018-11-09 07:50:37 +0000
29+++ data/ai/ai_input_3.wai 2019-05-16 17:52:43 +0000
30@@ -166,7 +166,7 @@
31 161="79"
32 162="-56"
33 163="-41"
34-164="0"
35+164="55"
36 165="-63"
37 166="8"
38 167="-72"
39
40=== modified file 'data/ai/ai_input_4.wai'
41--- data/ai/ai_input_4.wai 2018-11-09 07:50:37 +0000
42+++ data/ai/ai_input_4.wai 2019-05-16 17:52:43 +0000
43@@ -166,7 +166,7 @@
44 161="79"
45 162="-56"
46 163="-41"
47-164="0"
48+164="55"
49 165="-63"
50 166="8"
51 167="-72"
52
53=== modified file 'data/tribes/buildings/productionsites/atlanteans/horsefarm/init.lua'
54--- data/tribes/buildings/productionsites/atlanteans/horsefarm/init.lua 2019-03-17 07:20:58 +0000
55+++ data/tribes/buildings/productionsites/atlanteans/horsefarm/init.lua 2019-05-16 17:52:43 +0000
56@@ -32,7 +32,7 @@
57
58 aihints = {
59 recruitment = true,
60- prohibited_till = 610
61+ prohibited_till = 610,
62 },
63
64 working_positions = {
65
66=== modified file 'data/tribes/buildings/productionsites/barbarians/barracks/init.lua'
67--- data/tribes/buildings/productionsites/barbarians/barracks/init.lua 2019-03-13 20:21:20 +0000
68+++ data/tribes/buildings/productionsites/barbarians/barracks/init.lua 2019-05-16 17:52:43 +0000
69@@ -37,7 +37,6 @@
70 },
71
72 aihints = {
73- basic_amount = 1,
74 very_weak_ai_limit = 1,
75 weak_ai_limit = 2,
76 prohibited_till = 920
77
78=== modified file 'data/tribes/buildings/productionsites/barbarians/cattlefarm/init.lua'
79--- data/tribes/buildings/productionsites/barbarians/cattlefarm/init.lua 2019-03-17 07:20:58 +0000
80+++ data/tribes/buildings/productionsites/barbarians/cattlefarm/init.lua 2019-05-16 17:52:43 +0000
81@@ -32,7 +32,7 @@
82
83 aihints = {
84 recruitment = true,
85- prohibited_till = 610
86+ prohibited_till = 610,
87 },
88
89 working_positions = {
90
91=== modified file 'data/tribes/buildings/productionsites/empire/donkeyfarm/init.lua'
92--- data/tribes/buildings/productionsites/empire/donkeyfarm/init.lua 2019-03-17 07:20:58 +0000
93+++ data/tribes/buildings/productionsites/empire/donkeyfarm/init.lua 2019-05-16 17:52:43 +0000
94@@ -32,7 +32,7 @@
95
96 aihints = {
97 recruitment = true,
98- prohibited_till = 610
99+ prohibited_till = 610,
100 },
101
102 working_positions = {
103
104=== modified file 'data/tribes/wares/coal/init.lua'
105--- data/tribes/wares/coal/init.lua 2017-06-30 15:31:17 +0000
106+++ data/tribes/wares/coal/init.lua 2019-05-16 17:52:43 +0000
107@@ -14,10 +14,10 @@
108 empire = 20
109 },
110 preciousness = {
111- atlanteans = 1,
112- barbarians = 1,
113- frisians = 6,
114- empire = 1
115+ atlanteans = 10,
116+ barbarians = 20,
117+ frisians = 40,
118+ empire = 10
119 },
120
121 animations = {
122
123=== modified file 'src/ai/defaultai.cc'
124--- src/ai/defaultai.cc 2019-04-20 05:44:37 +0000
125+++ src/ai/defaultai.cc 2019-05-16 17:52:43 +0000
126@@ -1326,13 +1326,17 @@
127 field.nearest_buildable_spot_nearby = std::numeric_limits<uint16_t>::max();
128 field.unowned_buildable_spots_nearby = 0;
129 field.unowned_portspace_vicinity_nearby = 0;
130- if (field.unowned_land_nearby > 0) {
131+ if (field.unowned_land_nearby > 0 || (field.enemy_owned_land_nearby > 0 &&
132+ field.enemy_military_presence < std::abs(management_data.get_military_number_at(174)) / 10)) {
133 std::vector<Coords> found_buildable_fields;
134
135 // first looking for unowned buildable spots
136 field.unowned_buildable_spots_nearby =
137 map.find_fields(Area<FCoords>(field.coords, kBuildableSpotsCheckArea),
138 &found_buildable_fields, find_unowned_buildable);
139+ field.unowned_buildable_spots_nearby +=
140+ map.find_fields(Area<FCoords>(field.coords, kBuildableSpotsCheckArea),
141+ &found_buildable_fields, find_enemy_owned_walkable);
142 // Now iterate over fields to collect statistics
143 for (auto& coords : found_buildable_fields) {
144 // We are not interested in blocked fields
145@@ -2452,8 +2456,19 @@
146 for (uint32_t j = 0; j < buildings_.size(); ++j) {
147 BuildingObserver& bo = buildings_.at(j);
148
149+ // we check if a previously not buildable Building of the basic economy is buildable again
150+ // If so and we don't have basic economy achieved we add readd it to basic buildings list
151+ // This should only happen in scenarios via scripting
152+ if (!basic_economy_established && bo.basic_amount > static_cast<uint32_t>(bo.total_count()) && bo.buildable(*player_)) {
153+ persistent_data->remaining_basic_buildings.emplace(std::make_pair(bo.id, bo.basic_amount));
154+ }
155 if (!bo.buildable(*player_)) {
156 bo.new_building = BuildingNecessity::kNotNeeded;
157+ // This line removes buildings from basic economy if they are not allowed for the player
158+ // this should only happen by scripting.
159+ if (bo.basic_amount) {
160+ persistent_data->remaining_basic_buildings.erase(bo.id);
161+ }
162 } else if (bo.type == BuildingObserver::Type::kProductionsite ||
163 bo.type == BuildingObserver::Type::kMine) {
164
165@@ -2947,6 +2962,7 @@
166 }
167
168 } else if (bo.is(BuildingAttribute::kRecruitment)) {
169+ bo.max_needed_preciousness = 2;
170 prio += bo.primary_priority;
171 prio -= bf->unowned_land_nearby * 2;
172 prio -= (bf->enemy_nearby) * 100;
173@@ -3749,12 +3765,11 @@
174 }
175 }
176
177- // if we are within grace time, it is OK, just go on
178- if (eco->dismantle_grace_time > gametime &&
179- eco->dismantle_grace_time != std::numeric_limits<uint32_t>::max()) {
180- // if grace time is not set, this is probably first time without a warehouse and we must
181- // set it
182- } else if (eco->dismantle_grace_time == std::numeric_limits<uint32_t>::max()) {
183+ // check if we are within grace time, if not or gracetime unset we need to do something
184+ // if we are within gracetime we do nothing (this loop is skipped)
185+
186+ // if grace time is not set, this is probably first time without a warehouse and we must set it
187+ if (eco->dismantle_grace_time == std::numeric_limits<uint32_t>::max()) {
188
189 // constructionsites
190 if (upcast(ConstructionSite const, constructionsite, flag.get_building())) {
191@@ -3784,7 +3799,7 @@
192 }
193
194 // we have passed grace_time - it is time to dismantle
195- } else {
196+ } else if (eco->dismantle_grace_time <= gametime) {
197 last_attempt_ = true;
198 // we increase a check radius in last attempt
199 checkradius += 2;
200@@ -4104,7 +4119,8 @@
201
202 // do not dismantle or upgrade the same type of building too soon - to give some time to update
203 // statistics
204- if (site.bo->last_dismantle_time > game().get_gametime() - 30 * 1000) {
205+ if (site.bo->last_dismantle_time > game().get_gametime() -
206+ (std::abs(management_data.get_military_number_at(164)) / 25 + 1) * 60 * 1000) {
207 return false;
208 }
209
210@@ -4210,11 +4226,11 @@
211 (en_bo.cnt_under_construction + en_bo.unoccupied_count) == 0) {
212
213 // forcing first upgrade
214- if (en_bo.total_count() == 0) {
215+ if (en_bo.total_count() == 0 && (site.bo->cnt_built > 1 || site.bo->is(BuildingAttribute::kUpgradeSubstitutes))) {
216 doing_upgrade = true;
217 }
218
219- if (en_bo.total_count() == 1) {
220+ if (en_bo.total_count() == 1 && (site.bo->cnt_built > 1 || site.bo->is(BuildingAttribute::kUpgradeSubstitutes))) {
221 if (en_bo.current_stats > 55) {
222 doing_upgrade = true;
223 }
224@@ -4441,7 +4457,8 @@
225
226 // if we have more buildings then target
227 if ((site.bo->cnt_built - site.bo->unconnected_count) > site.bo->cnt_target &&
228- site.unoccupied_till + 10 * 60 * 1000 < gametime && site.site->can_start_working()) {
229+ site.unoccupied_till + (std::abs(management_data.get_military_number_at(166)) / 5 + 1) * 60 *
230+ 1000 < gametime && site.site->can_start_working()) {
231
232 if (site.site->get_statistics_percent() < 30 && get_stocklevel(*site.bo, gametime) > 100) {
233 site.bo->last_dismantle_time = game().get_gametime();
234@@ -4456,7 +4473,9 @@
235
236 // a building can be dismanteld if it performs too bad, if it is not the last one
237 if (site.site->get_statistics_percent() <= 10 && site.bo->cnt_built > 1 &&
238- site.unoccupied_till + 10 * 60 * 1000 < gametime && site.site->can_start_working()) {
239+ site.unoccupied_till + (std::abs(management_data.get_military_number_at(167)) / 5 + 1) * 60 *
240+ 1000 < gametime && site.site->can_start_working() && get_stocklevel(*site.bo, gametime) >
241+ (std::abs(management_data.get_military_number_at(168)) / 5)) {
242
243 if (connected_to_wh) {
244 game().send_player_dismantle(*site.site);
245@@ -4483,7 +4502,8 @@
246 site.site->can_start_working() &&
247 check_building_necessity(*site.bo, PerfEvaluation::kForDismantle, gametime) ==
248 BuildingNecessity::kNotNeeded &&
249- gametime - site.bo->last_dismantle_time > 5 * 60 * 1000 &&
250+ gametime - site.bo->last_dismantle_time >
251+ static_cast<uint32_t>((std::abs(management_data.get_military_number_at(169)) / 5 + 1) * 60 * 1000) &&
252
253 site.bo->current_stats > site.site->get_statistics_percent() && // underperformer
254 (game().get_gametime() - site.unoccupied_till) > 10 * 60 * 1000) {
255@@ -4821,7 +4841,6 @@
256 BuildingNecessity DefaultAI::check_building_necessity(BuildingObserver& bo,
257 const PerfEvaluation purpose,
258 const uint32_t gametime) {
259-
260 bo.primary_priority = 0;
261
262 static BasicEconomyBuildingStatus site_needed_for_economy = BasicEconomyBuildingStatus::kNone;
263@@ -4935,11 +4954,11 @@
264 if (!basic_economy_established) {
265 return BuildingNecessity::kForbidden;
266 }
267- const uint16_t min_roads_count = 50 + std::abs(management_data.get_military_number_at(33));
268- if (roads.size() < min_roads_count) {
269+ const uint16_t min_roads_count = 40 + std::abs(management_data.get_military_number_at(33)) / 2;
270+ if (roads.size() < static_cast<size_t>(min_roads_count * (1 + bo.total_count()))) {
271 return BuildingNecessity::kForbidden;
272 }
273- bo.primary_priority = (roads.size() - min_roads_count) *
274+ bo.primary_priority += (roads.size() - min_roads_count * (1 + bo.total_count())) *
275 (2 + std::abs(management_data.get_military_number_at(143)) / 5);
276 return BuildingNecessity::kNeeded;
277 }
278@@ -5054,7 +5073,7 @@
279 get_building_observer(tribe_->get_building_descr(enhancement)->name().c_str());
280 if ((gametime > 30 * 60 * 1000 && en_bo.total_count() == 0) || gametime > 90 * 60 * 1000) {
281 // We fake this
282- bo.max_needed_preciousness = bo.max_preciousness;
283+ bo.max_needed_preciousness = bo.max_preciousness * 2;
284 needs_second_for_upgrade = true;
285 }
286 }
287@@ -5103,9 +5122,9 @@
288 inputs[8] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? +3 : 0;
289 inputs[9] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0;
290 inputs[10] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0;
291- inputs[11] = (bo.last_building_built + 5 * 60 * 100 > gametime) ? +1 : 0;
292- inputs[12] = (bo.last_building_built + 10 * 60 * 100 > gametime) ? +1 : 0;
293- inputs[13] = (bo.last_building_built + 20 * 60 * 100 > gametime) ? +1 : 0;
294+ inputs[11] = (bo.last_building_built + 5 * 60 * 100 < gametime) ? +1 : 0;
295+ inputs[12] = (bo.last_building_built + 10 * 60 * 100 < gametime) ? +1 : 0;
296+ inputs[13] = (bo.last_building_built + 20 * 60 * 100 < gametime) ? +1 : 0;
297 inputs[14] = (bo.total_count() >= bo.cnt_target) ? -1 : 0;
298 inputs[15] = (bo.total_count() >= bo.cnt_target) ? -2 : 0;
299 inputs[16] = (bo.total_count() < bo.cnt_target) ? -1 : 0;
300@@ -5150,7 +5169,7 @@
301 if (bo.total_count() > 1 && (bo.cnt_under_construction + bo.unoccupied_count > 0)) {
302 return BuildingNecessity::kForbidden;
303 }
304- bo.cnt_target = 3;
305+ bo.cnt_target = 2;
306 // adjusting/decreasing based on cnt_limit_by_aimode
307 bo.cnt_target = std::min(bo.cnt_target, bo.cnt_limit_by_aimode);
308
309@@ -5173,8 +5192,7 @@
310 } else if (bo.is(BuildingAttribute::kRanger)) {
311
312 // making sure we have one completed lumberjack
313- if (bo.total_count() > 0 &&
314- get_building_observer(BuildingAttribute::kLumberjack).cnt_built < 1) {
315+ if (get_building_observer(BuildingAttribute::kLumberjack).cnt_built < 1) {
316 return BuildingNecessity::kForbidden;
317 }
318
319@@ -5455,11 +5473,10 @@
320 inputs[14] = (bo.current_stats - 50) / 10;
321 inputs[15] = management_data.get_military_number_at(123) / 10;
322 inputs[16] = 0;
323- // TODO(GunChleoc): This is overwritten below due to a typo
324- // inputs[17] = (inputs_on_stock) ? 0 : -2;
325+ inputs[17] = (inputs_on_stock) ? 0 : -2;
326 inputs[18] = (suppliers_exist) ? 0 : -3;
327- inputs[17] = (inputs_on_stock) ? 0 : -4;
328- // Nothing on inputs[19]
329+ ;
330+ inputs[19] = (inputs_on_stock) ? 0 : -4;
331 inputs[20] =
332 (mines_per_type[bo.mines].in_construction + mines_per_type[bo.mines].finished == 1) ?
333 3 :
334@@ -5516,7 +5533,7 @@
335 inputs[0] = (bo.total_count() <= 1) ?
336 std::abs(management_data.get_military_number_at(110)) / 10 :
337 0;
338- inputs[1] = -2 * bo.total_count();
339+ inputs[1] = bo.total_count() * -3 / 2;
340 inputs[2] =
341 (bo.total_count() == 0) ? std::abs(management_data.get_military_number_at(0)) / 10 : 0;
342 inputs[3] = (gametime >= 25 * 60 * 1000 && bo.inputs.empty()) ?
343@@ -5529,11 +5546,11 @@
344 management_data.get_military_number_at(3) / 10 :
345 0;
346 inputs[6] = (needs_second_for_upgrade) ?
347- std::abs(management_data.get_military_number_at(4)) / 10 :
348+ std::abs(management_data.get_military_number_at(4)) / 5 :
349 0;
350 inputs[7] = (bo.cnt_under_construction + bo.unoccupied_count) * -1 *
351 std::abs(management_data.get_military_number_at(9)) / 5;
352- inputs[8] = (!bo.outputs.empty() && bo.current_stats > 30 + 70 / bo.outputs.size()) ?
353+ inputs[8] = (!bo.outputs.empty() && bo.current_stats > 25 + 70 / bo.outputs.size()) ?
354 management_data.get_military_number_at(7) / 8 :
355 0;
356 inputs[9] = (bo.is(BuildingAttribute::kBuildingMatProducer)) ?
357@@ -5559,7 +5576,7 @@
358 management_data.get_military_number_at(97) / 10 :
359 0;
360 inputs[17] =
361- (spots_ > kSpotsEnough) ? std::abs(management_data.get_military_number_at(74)) / 10 : 0;
362+ (spots_ > kSpotsEnough) ? std::abs(management_data.get_military_number_at(74)) / 8 : 0;
363 inputs[18] = management_data.get_military_number_at(98) / 10;
364 inputs[19] = (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) ?
365 -1 * std::abs(management_data.get_military_number_at(40)) / 10 :
366@@ -5592,7 +5609,7 @@
367 inputs[32] = bo.max_needed_preciousness / 2;
368 inputs[33] = -(bo.cnt_under_construction + bo.unoccupied_count) * 4;
369 if (bo.cnt_built > 0 && !bo.outputs.empty() && !bo.inputs.empty()) {
370- inputs[34] += bo.current_stats / 10;
371+ inputs[34] += bo.current_stats / std::abs(management_data.get_military_number_at(192)) * 10;
372 }
373 inputs[35] = (!bo.outputs.empty() && !bo.inputs.empty() &&
374 bo.current_stats > 10 + 70 / bo.outputs.size()) ?
375@@ -5703,6 +5720,14 @@
376 inputs[105] = -2;
377 inputs[106] = -2;
378 }
379+ inputs[107] = std::abs(management_data.get_military_number_at(194)) - get_stocklevel(bo, gametime);
380+ inputs[108] = std::abs(management_data.get_military_number_at(191)) - get_stocklevel(bo, gametime);
381+ inputs[109] = (!bo.inputs.empty() && gametime > 50 * 60 * 1000 && bo.total_count() <= 1) ?
382+ std::abs(management_data.get_military_number_at(163)) / 10 : 0;
383+ inputs[110] = (bo.outputs.size() == 1) ?
384+ (tribe_->get_ware_descr(bo.outputs.at(0))->default_target_quantity(tribe_->name()) -
385+ get_stocklevel(bo, gametime)) * std::abs(management_data.get_military_number_at(165)) / 20 : 0;
386+ inputs[111] = bo.current_stats / (bo.outputs.size() + 1);
387
388 int16_t tmp_score = 0;
389 for (uint8_t i = 0; i < kFNeuronBitSize; ++i) {
390@@ -5779,7 +5804,9 @@
391 return BuildingNecessity::kNeeded;
392 } else if (bo.max_preciousness >= 10 && bo.total_count() == 2) {
393 return BuildingNecessity::kNeeded;
394- } else if (!bo.outputs.empty() && bo.current_stats > (10 + 70 / bo.outputs.size()) / 2) {
395+ } else if (!bo.outputs.empty() && bo.current_stats > (10 + 60 / bo.outputs.size()) / 2) {
396+ return BuildingNecessity::kNeeded;
397+ } 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))) {
398 return BuildingNecessity::kNeeded;
399 } else {
400 return BuildingNecessity::kNotNeeded;
401
402=== modified file 'src/ai/defaultai.h'
403--- src/ai/defaultai.h 2019-02-23 11:00:49 +0000
404+++ src/ai/defaultai.h 2019-05-16 17:52:43 +0000
405@@ -212,7 +212,6 @@
406
407 uint32_t get_stocklevel_by_hint(size_t);
408 uint32_t get_stocklevel(Widelands::BuildingObserver&, uint32_t, WareWorker = WareWorker::kWare);
409- uint32_t calculate_stocklevel(Widelands::BuildingObserver&, WareWorker = WareWorker::kWare);
410 uint32_t calculate_stocklevel(Widelands::DescriptionIndex,
411 WareWorker = WareWorker::kWare); // count all direct outputs_
412

Subscribers

People subscribed via source and target branches

to status/vote changes: