Merge lp:~widelands-dev/widelands/AI-fixes into lp:widelands
- AI-fixes
- Merge into trunk
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 | ||||||||||||||||
Related bugs: |
|
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
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.
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 :)
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.
GunChleoc (gunchleoc) wrote : | # |
I'll have a look.
Also, I got this:
../src/
../src/
1000 < gametime && site.site-
../src/
gametime - site.bo-
~
GunChleoc (gunchleoc) wrote : | # |
I think I found the problem:
(bo.outputs.size() == 1) means that there is 1 entry at index 0.
(tribe_
Unlike Lua, C++ starts counting from 0. Actually, Lua is quite exceptional here, since starting from 0 is the usual way of doing arrays.
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/
/home/benedikt/
[1007/1455] Building CXX object src/ai/
../src/
../src/
gametime - site.bo-
~
> 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
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4946. State: failed. Details: https:/
Appveyor build 4727. State: success. Details: https:/
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...
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..
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?
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.
hessenfarmer (stephan-lutz) wrote : | # |
@ Nordfriese:
If you want to test this further let us know, if you are finished we could merge this.
hessenfarmer (stephan-lutz) wrote : | # |
I still can't get the Ai to build a second carrier producer.
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...
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4962. State: errored. Details: https:/
Appveyor build 4743. State: success. Details: https:/
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.
hessenfarmer (stephan-lutz) wrote : | # |
oops I missed to fix the typo which GunChleoc found will be done in final polish
TiborB (tiborb95) wrote : | # |
I have one objection, see comment in code
Benedikt Straub (nordfriese) wrote : | # |
I´m through with the code review, a couple of nits. Will do more testing soon…
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.
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.
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.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4978. State: passed. Details: https:/
Appveyor build 4759. State: success. Details: https:/
Benedikt Straub (nordfriese) wrote : | # |
Tested, and it performs well. Code LGTM.
Good job :)
hessenfarmer (stephan-lutz) wrote : | # |
Ok I will remove the fri03 stuff and merge it then. will be tonight though
hessenfarmer (stephan-lutz) wrote : | # |
removed the lua stuff should be good to go now
hessenfarmer (stephan-lutz) wrote : | # |
@bunnybot merge
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?
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.
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.
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.
hessenfarmer (stephan-lutz) wrote : | # |
For my understanding it is not only that but we should discuss this in the bug report.
Preview Diff
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 | 166 | 161="79" | 166 | 161="79" |
6 | 167 | 162="-56" | 167 | 162="-56" |
7 | 168 | 163="-41" | 168 | 163="-41" |
9 | 169 | 164="0" | 169 | 164="55" |
10 | 170 | 165="-63" | 170 | 165="-63" |
11 | 171 | 166="8" | 171 | 166="8" |
12 | 172 | 167="-72" | 172 | 167="-72" |
13 | 173 | 173 | ||
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 | 166 | 161="79" | 166 | 161="79" |
19 | 167 | 162="-56" | 167 | 162="-56" |
20 | 168 | 163="-41" | 168 | 163="-41" |
22 | 169 | 164="0" | 169 | 164="55" |
23 | 170 | 165="-63" | 170 | 165="-63" |
24 | 171 | 166="8" | 171 | 166="8" |
25 | 172 | 167="-72" | 172 | 167="-72" |
26 | 173 | 173 | ||
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 | 166 | 161="79" | 166 | 161="79" |
32 | 167 | 162="-56" | 167 | 162="-56" |
33 | 168 | 163="-41" | 168 | 163="-41" |
35 | 169 | 164="0" | 169 | 164="55" |
36 | 170 | 165="-63" | 170 | 165="-63" |
37 | 171 | 166="8" | 171 | 166="8" |
38 | 172 | 167="-72" | 172 | 167="-72" |
39 | 173 | 173 | ||
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 | 166 | 161="79" | 166 | 161="79" |
45 | 167 | 162="-56" | 167 | 162="-56" |
46 | 168 | 163="-41" | 168 | 163="-41" |
48 | 169 | 164="0" | 169 | 164="55" |
49 | 170 | 165="-63" | 170 | 165="-63" |
50 | 171 | 166="8" | 171 | 166="8" |
51 | 172 | 167="-72" | 172 | 167="-72" |
52 | 173 | 173 | ||
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 | 32 | 32 | ||
58 | 33 | aihints = { | 33 | aihints = { |
59 | 34 | recruitment = true, | 34 | recruitment = true, |
61 | 35 | prohibited_till = 610 | 35 | prohibited_till = 610, |
62 | 36 | }, | 36 | }, |
63 | 37 | 37 | ||
64 | 38 | working_positions = { | 38 | working_positions = { |
65 | 39 | 39 | ||
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 | 37 | }, | 37 | }, |
71 | 38 | 38 | ||
72 | 39 | aihints = { | 39 | aihints = { |
73 | 40 | basic_amount = 1, | ||
74 | 41 | very_weak_ai_limit = 1, | 40 | very_weak_ai_limit = 1, |
75 | 42 | weak_ai_limit = 2, | 41 | weak_ai_limit = 2, |
76 | 43 | prohibited_till = 920 | 42 | prohibited_till = 920 |
77 | 44 | 43 | ||
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 | 32 | 32 | ||
83 | 33 | aihints = { | 33 | aihints = { |
84 | 34 | recruitment = true, | 34 | recruitment = true, |
86 | 35 | prohibited_till = 610 | 35 | prohibited_till = 610, |
87 | 36 | }, | 36 | }, |
88 | 37 | 37 | ||
89 | 38 | working_positions = { | 38 | working_positions = { |
90 | 39 | 39 | ||
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 | 32 | 32 | ||
96 | 33 | aihints = { | 33 | aihints = { |
97 | 34 | recruitment = true, | 34 | recruitment = true, |
99 | 35 | prohibited_till = 610 | 35 | prohibited_till = 610, |
100 | 36 | }, | 36 | }, |
101 | 37 | 37 | ||
102 | 38 | working_positions = { | 38 | working_positions = { |
103 | 39 | 39 | ||
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 | 14 | empire = 20 | 14 | empire = 20 |
109 | 15 | }, | 15 | }, |
110 | 16 | preciousness = { | 16 | preciousness = { |
115 | 17 | atlanteans = 1, | 17 | atlanteans = 10, |
116 | 18 | barbarians = 1, | 18 | barbarians = 20, |
117 | 19 | frisians = 6, | 19 | frisians = 40, |
118 | 20 | empire = 1 | 20 | empire = 10 |
119 | 21 | }, | 21 | }, |
120 | 22 | 22 | ||
121 | 23 | animations = { | 23 | animations = { |
122 | 24 | 24 | ||
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 | 1326 | field.nearest_buildable_spot_nearby = std::numeric_limits<uint16_t>::max(); | 1326 | field.nearest_buildable_spot_nearby = std::numeric_limits<uint16_t>::max(); |
128 | 1327 | field.unowned_buildable_spots_nearby = 0; | 1327 | field.unowned_buildable_spots_nearby = 0; |
129 | 1328 | field.unowned_portspace_vicinity_nearby = 0; | 1328 | field.unowned_portspace_vicinity_nearby = 0; |
131 | 1329 | if (field.unowned_land_nearby > 0) { | 1329 | if (field.unowned_land_nearby > 0 || (field.enemy_owned_land_nearby > 0 && |
132 | 1330 | field.enemy_military_presence < std::abs(management_data.get_military_number_at(174)) / 10)) { | ||
133 | 1330 | std::vector<Coords> found_buildable_fields; | 1331 | std::vector<Coords> found_buildable_fields; |
134 | 1331 | 1332 | ||
135 | 1332 | // first looking for unowned buildable spots | 1333 | // first looking for unowned buildable spots |
136 | 1333 | field.unowned_buildable_spots_nearby = | 1334 | field.unowned_buildable_spots_nearby = |
137 | 1334 | map.find_fields(Area<FCoords>(field.coords, kBuildableSpotsCheckArea), | 1335 | map.find_fields(Area<FCoords>(field.coords, kBuildableSpotsCheckArea), |
138 | 1335 | &found_buildable_fields, find_unowned_buildable); | 1336 | &found_buildable_fields, find_unowned_buildable); |
139 | 1337 | field.unowned_buildable_spots_nearby += | ||
140 | 1338 | map.find_fields(Area<FCoords>(field.coords, kBuildableSpotsCheckArea), | ||
141 | 1339 | &found_buildable_fields, find_enemy_owned_walkable); | ||
142 | 1336 | // Now iterate over fields to collect statistics | 1340 | // Now iterate over fields to collect statistics |
143 | 1337 | for (auto& coords : found_buildable_fields) { | 1341 | for (auto& coords : found_buildable_fields) { |
144 | 1338 | // We are not interested in blocked fields | 1342 | // We are not interested in blocked fields |
145 | @@ -2452,8 +2456,19 @@ | |||
146 | 2452 | for (uint32_t j = 0; j < buildings_.size(); ++j) { | 2456 | for (uint32_t j = 0; j < buildings_.size(); ++j) { |
147 | 2453 | BuildingObserver& bo = buildings_.at(j); | 2457 | BuildingObserver& bo = buildings_.at(j); |
148 | 2454 | 2458 | ||
149 | 2459 | // we check if a previously not buildable Building of the basic economy is buildable again | ||
150 | 2460 | // If so and we don't have basic economy achieved we add readd it to basic buildings list | ||
151 | 2461 | // This should only happen in scenarios via scripting | ||
152 | 2462 | if (!basic_economy_established && bo.basic_amount > static_cast<uint32_t>(bo.total_count()) && bo.buildable(*player_)) { | ||
153 | 2463 | persistent_data->remaining_basic_buildings.emplace(std::make_pair(bo.id, bo.basic_amount)); | ||
154 | 2464 | } | ||
155 | 2455 | if (!bo.buildable(*player_)) { | 2465 | if (!bo.buildable(*player_)) { |
156 | 2456 | bo.new_building = BuildingNecessity::kNotNeeded; | 2466 | bo.new_building = BuildingNecessity::kNotNeeded; |
157 | 2467 | // This line removes buildings from basic economy if they are not allowed for the player | ||
158 | 2468 | // this should only happen by scripting. | ||
159 | 2469 | if (bo.basic_amount) { | ||
160 | 2470 | persistent_data->remaining_basic_buildings.erase(bo.id); | ||
161 | 2471 | } | ||
162 | 2457 | } else if (bo.type == BuildingObserver::Type::kProductionsite || | 2472 | } else if (bo.type == BuildingObserver::Type::kProductionsite || |
163 | 2458 | bo.type == BuildingObserver::Type::kMine) { | 2473 | bo.type == BuildingObserver::Type::kMine) { |
164 | 2459 | 2474 | ||
165 | @@ -2947,6 +2962,7 @@ | |||
166 | 2947 | } | 2962 | } |
167 | 2948 | 2963 | ||
168 | 2949 | } else if (bo.is(BuildingAttribute::kRecruitment)) { | 2964 | } else if (bo.is(BuildingAttribute::kRecruitment)) { |
169 | 2965 | bo.max_needed_preciousness = 2; | ||
170 | 2950 | prio += bo.primary_priority; | 2966 | prio += bo.primary_priority; |
171 | 2951 | prio -= bf->unowned_land_nearby * 2; | 2967 | prio -= bf->unowned_land_nearby * 2; |
172 | 2952 | prio -= (bf->enemy_nearby) * 100; | 2968 | prio -= (bf->enemy_nearby) * 100; |
173 | @@ -3749,12 +3765,11 @@ | |||
174 | 3749 | } | 3765 | } |
175 | 3750 | } | 3766 | } |
176 | 3751 | 3767 | ||
183 | 3752 | // if we are within grace time, it is OK, just go on | 3768 | // check if we are within grace time, if not or gracetime unset we need to do something |
184 | 3753 | if (eco->dismantle_grace_time > gametime && | 3769 | // if we are within gracetime we do nothing (this loop is skipped) |
185 | 3754 | eco->dismantle_grace_time != std::numeric_limits<uint32_t>::max()) { | 3770 | |
186 | 3755 | // if grace time is not set, this is probably first time without a warehouse and we must | 3771 | // if grace time is not set, this is probably first time without a warehouse and we must set it |
187 | 3756 | // set it | 3772 | if (eco->dismantle_grace_time == std::numeric_limits<uint32_t>::max()) { |
182 | 3757 | } else if (eco->dismantle_grace_time == std::numeric_limits<uint32_t>::max()) { | ||
188 | 3758 | 3773 | ||
189 | 3759 | // constructionsites | 3774 | // constructionsites |
190 | 3760 | if (upcast(ConstructionSite const, constructionsite, flag.get_building())) { | 3775 | if (upcast(ConstructionSite const, constructionsite, flag.get_building())) { |
191 | @@ -3784,7 +3799,7 @@ | |||
192 | 3784 | } | 3799 | } |
193 | 3785 | 3800 | ||
194 | 3786 | // we have passed grace_time - it is time to dismantle | 3801 | // we have passed grace_time - it is time to dismantle |
196 | 3787 | } else { | 3802 | } else if (eco->dismantle_grace_time <= gametime) { |
197 | 3788 | last_attempt_ = true; | 3803 | last_attempt_ = true; |
198 | 3789 | // we increase a check radius in last attempt | 3804 | // we increase a check radius in last attempt |
199 | 3790 | checkradius += 2; | 3805 | checkradius += 2; |
200 | @@ -4104,7 +4119,8 @@ | |||
201 | 4104 | 4119 | ||
202 | 4105 | // do not dismantle or upgrade the same type of building too soon - to give some time to update | 4120 | // do not dismantle or upgrade the same type of building too soon - to give some time to update |
203 | 4106 | // statistics | 4121 | // statistics |
205 | 4107 | if (site.bo->last_dismantle_time > game().get_gametime() - 30 * 1000) { | 4122 | if (site.bo->last_dismantle_time > game().get_gametime() - |
206 | 4123 | (std::abs(management_data.get_military_number_at(164)) / 25 + 1) * 60 * 1000) { | ||
207 | 4108 | return false; | 4124 | return false; |
208 | 4109 | } | 4125 | } |
209 | 4110 | 4126 | ||
210 | @@ -4210,11 +4226,11 @@ | |||
211 | 4210 | (en_bo.cnt_under_construction + en_bo.unoccupied_count) == 0) { | 4226 | (en_bo.cnt_under_construction + en_bo.unoccupied_count) == 0) { |
212 | 4211 | 4227 | ||
213 | 4212 | // forcing first upgrade | 4228 | // forcing first upgrade |
215 | 4213 | if (en_bo.total_count() == 0) { | 4229 | if (en_bo.total_count() == 0 && (site.bo->cnt_built > 1 || site.bo->is(BuildingAttribute::kUpgradeSubstitutes))) { |
216 | 4214 | doing_upgrade = true; | 4230 | doing_upgrade = true; |
217 | 4215 | } | 4231 | } |
218 | 4216 | 4232 | ||
220 | 4217 | if (en_bo.total_count() == 1) { | 4233 | if (en_bo.total_count() == 1 && (site.bo->cnt_built > 1 || site.bo->is(BuildingAttribute::kUpgradeSubstitutes))) { |
221 | 4218 | if (en_bo.current_stats > 55) { | 4234 | if (en_bo.current_stats > 55) { |
222 | 4219 | doing_upgrade = true; | 4235 | doing_upgrade = true; |
223 | 4220 | } | 4236 | } |
224 | @@ -4441,7 +4457,8 @@ | |||
225 | 4441 | 4457 | ||
226 | 4442 | // if we have more buildings then target | 4458 | // if we have more buildings then target |
227 | 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 && |
229 | 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 * |
230 | 4461 | 1000 < gametime && site.site->can_start_working()) { | ||
231 | 4445 | 4462 | ||
232 | 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) { |
233 | 4447 | site.bo->last_dismantle_time = game().get_gametime(); | 4464 | site.bo->last_dismantle_time = game().get_gametime(); |
234 | @@ -4456,7 +4473,9 @@ | |||
235 | 4456 | 4473 | ||
236 | 4457 | // a building can be dismanteld if it performs too bad, if it is not the last one | 4474 | // a building can be dismanteld if it performs too bad, if it is not the last one |
237 | 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 && |
239 | 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 * |
240 | 4477 | 1000 < gametime && site.site->can_start_working() && get_stocklevel(*site.bo, gametime) > | ||
241 | 4478 | (std::abs(management_data.get_military_number_at(168)) / 5)) { | ||
242 | 4460 | 4479 | ||
243 | 4461 | if (connected_to_wh) { | 4480 | if (connected_to_wh) { |
244 | 4462 | game().send_player_dismantle(*site.site); | 4481 | game().send_player_dismantle(*site.site); |
245 | @@ -4483,7 +4502,8 @@ | |||
246 | 4483 | site.site->can_start_working() && | 4502 | site.site->can_start_working() && |
247 | 4484 | check_building_necessity(*site.bo, PerfEvaluation::kForDismantle, gametime) == | 4503 | check_building_necessity(*site.bo, PerfEvaluation::kForDismantle, gametime) == |
248 | 4485 | BuildingNecessity::kNotNeeded && | 4504 | BuildingNecessity::kNotNeeded && |
250 | 4486 | gametime - site.bo->last_dismantle_time > 5 * 60 * 1000 && | 4505 | gametime - site.bo->last_dismantle_time > |
251 | 4506 | static_cast<uint32_t>((std::abs(management_data.get_military_number_at(169)) / 5 + 1) * 60 * 1000) && | ||
252 | 4487 | 4507 | ||
253 | 4488 | site.bo->current_stats > site.site->get_statistics_percent() && // underperformer | 4508 | site.bo->current_stats > site.site->get_statistics_percent() && // underperformer |
254 | 4489 | (game().get_gametime() - site.unoccupied_till) > 10 * 60 * 1000) { | 4509 | (game().get_gametime() - site.unoccupied_till) > 10 * 60 * 1000) { |
255 | @@ -4821,7 +4841,6 @@ | |||
256 | 4821 | BuildingNecessity DefaultAI::check_building_necessity(BuildingObserver& bo, | 4841 | BuildingNecessity DefaultAI::check_building_necessity(BuildingObserver& bo, |
257 | 4822 | const PerfEvaluation purpose, | 4842 | const PerfEvaluation purpose, |
258 | 4823 | const uint32_t gametime) { | 4843 | const uint32_t gametime) { |
259 | 4824 | |||
260 | 4825 | bo.primary_priority = 0; | 4844 | bo.primary_priority = 0; |
261 | 4826 | 4845 | ||
262 | 4827 | static BasicEconomyBuildingStatus site_needed_for_economy = BasicEconomyBuildingStatus::kNone; | 4846 | static BasicEconomyBuildingStatus site_needed_for_economy = BasicEconomyBuildingStatus::kNone; |
263 | @@ -4935,11 +4954,11 @@ | |||
264 | 4935 | if (!basic_economy_established) { | 4954 | if (!basic_economy_established) { |
265 | 4936 | return BuildingNecessity::kForbidden; | 4955 | return BuildingNecessity::kForbidden; |
266 | 4937 | } | 4956 | } |
269 | 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; |
270 | 4939 | if (roads.size() < min_roads_count) { | 4958 | if (roads.size() < static_cast<size_t>(min_roads_count * (1 + bo.total_count()))) { |
271 | 4940 | return BuildingNecessity::kForbidden; | 4959 | return BuildingNecessity::kForbidden; |
272 | 4941 | } | 4960 | } |
274 | 4942 | bo.primary_priority = (roads.size() - min_roads_count) * | 4961 | bo.primary_priority += (roads.size() - min_roads_count * (1 + bo.total_count())) * |
275 | 4943 | (2 + std::abs(management_data.get_military_number_at(143)) / 5); | 4962 | (2 + std::abs(management_data.get_military_number_at(143)) / 5); |
276 | 4944 | return BuildingNecessity::kNeeded; | 4963 | return BuildingNecessity::kNeeded; |
277 | 4945 | } | 4964 | } |
278 | @@ -5054,7 +5073,7 @@ | |||
279 | 5054 | get_building_observer(tribe_->get_building_descr(enhancement)->name().c_str()); | 5073 | get_building_observer(tribe_->get_building_descr(enhancement)->name().c_str()); |
280 | 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) { |
281 | 5056 | // We fake this | 5075 | // We fake this |
283 | 5057 | bo.max_needed_preciousness = bo.max_preciousness; | 5076 | bo.max_needed_preciousness = bo.max_preciousness * 2; |
284 | 5058 | needs_second_for_upgrade = true; | 5077 | needs_second_for_upgrade = true; |
285 | 5059 | } | 5078 | } |
286 | 5060 | } | 5079 | } |
287 | @@ -5103,9 +5122,9 @@ | |||
288 | 5103 | inputs[8] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? +3 : 0; | 5122 | inputs[8] = (expansion_type.get_expansion_type() == ExpansionMode::kEconomy) ? +3 : 0; |
289 | 5104 | inputs[9] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0; | 5123 | inputs[9] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0; |
290 | 5105 | inputs[10] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0; | 5124 | inputs[10] = (expansion_type.get_expansion_type() == ExpansionMode::kBoth) ? +1 : 0; |
294 | 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; |
295 | 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; |
296 | 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; |
297 | 5109 | inputs[14] = (bo.total_count() >= bo.cnt_target) ? -1 : 0; | 5128 | inputs[14] = (bo.total_count() >= bo.cnt_target) ? -1 : 0; |
298 | 5110 | inputs[15] = (bo.total_count() >= bo.cnt_target) ? -2 : 0; | 5129 | inputs[15] = (bo.total_count() >= bo.cnt_target) ? -2 : 0; |
299 | 5111 | inputs[16] = (bo.total_count() < bo.cnt_target) ? -1 : 0; | 5130 | inputs[16] = (bo.total_count() < bo.cnt_target) ? -1 : 0; |
300 | @@ -5150,7 +5169,7 @@ | |||
301 | 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)) { |
302 | 5151 | return BuildingNecessity::kForbidden; | 5170 | return BuildingNecessity::kForbidden; |
303 | 5152 | } | 5171 | } |
305 | 5153 | bo.cnt_target = 3; | 5172 | bo.cnt_target = 2; |
306 | 5154 | // adjusting/decreasing based on cnt_limit_by_aimode | 5173 | // adjusting/decreasing based on cnt_limit_by_aimode |
307 | 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); |
308 | 5156 | 5175 | ||
309 | @@ -5173,8 +5192,7 @@ | |||
310 | 5173 | } else if (bo.is(BuildingAttribute::kRanger)) { | 5192 | } else if (bo.is(BuildingAttribute::kRanger)) { |
311 | 5174 | 5193 | ||
312 | 5175 | // making sure we have one completed lumberjack | 5194 | // making sure we have one completed lumberjack |
315 | 5176 | if (bo.total_count() > 0 && | 5195 | if (get_building_observer(BuildingAttribute::kLumberjack).cnt_built < 1) { |
314 | 5177 | get_building_observer(BuildingAttribute::kLumberjack).cnt_built < 1) { | ||
316 | 5178 | return BuildingNecessity::kForbidden; | 5196 | return BuildingNecessity::kForbidden; |
317 | 5179 | } | 5197 | } |
318 | 5180 | 5198 | ||
319 | @@ -5455,11 +5473,10 @@ | |||
320 | 5455 | inputs[14] = (bo.current_stats - 50) / 10; | 5473 | inputs[14] = (bo.current_stats - 50) / 10; |
321 | 5456 | inputs[15] = management_data.get_military_number_at(123) / 10; | 5474 | inputs[15] = management_data.get_military_number_at(123) / 10; |
322 | 5457 | inputs[16] = 0; | 5475 | inputs[16] = 0; |
325 | 5458 | // TODO(GunChleoc): This is overwritten below due to a typo | 5476 | inputs[17] = (inputs_on_stock) ? 0 : -2; |
324 | 5459 | // inputs[17] = (inputs_on_stock) ? 0 : -2; | ||
326 | 5460 | inputs[18] = (suppliers_exist) ? 0 : -3; | 5477 | inputs[18] = (suppliers_exist) ? 0 : -3; |
329 | 5461 | inputs[17] = (inputs_on_stock) ? 0 : -4; | 5478 | ; |
330 | 5462 | // Nothing on inputs[19] | 5479 | inputs[19] = (inputs_on_stock) ? 0 : -4; |
331 | 5463 | inputs[20] = | 5480 | inputs[20] = |
332 | 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) ? |
333 | 5465 | 3 : | 5482 | 3 : |
334 | @@ -5516,7 +5533,7 @@ | |||
335 | 5516 | inputs[0] = (bo.total_count() <= 1) ? | 5533 | inputs[0] = (bo.total_count() <= 1) ? |
336 | 5517 | std::abs(management_data.get_military_number_at(110)) / 10 : | 5534 | std::abs(management_data.get_military_number_at(110)) / 10 : |
337 | 5518 | 0; | 5535 | 0; |
339 | 5519 | inputs[1] = -2 * bo.total_count(); | 5536 | inputs[1] = bo.total_count() * -3 / 2; |
340 | 5520 | inputs[2] = | 5537 | inputs[2] = |
341 | 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; |
342 | 5522 | inputs[3] = (gametime >= 25 * 60 * 1000 && bo.inputs.empty()) ? | 5539 | inputs[3] = (gametime >= 25 * 60 * 1000 && bo.inputs.empty()) ? |
343 | @@ -5529,11 +5546,11 @@ | |||
344 | 5529 | management_data.get_military_number_at(3) / 10 : | 5546 | management_data.get_military_number_at(3) / 10 : |
345 | 5530 | 0; | 5547 | 0; |
346 | 5531 | inputs[6] = (needs_second_for_upgrade) ? | 5548 | inputs[6] = (needs_second_for_upgrade) ? |
348 | 5532 | std::abs(management_data.get_military_number_at(4)) / 10 : | 5549 | std::abs(management_data.get_military_number_at(4)) / 5 : |
349 | 5533 | 0; | 5550 | 0; |
350 | 5534 | inputs[7] = (bo.cnt_under_construction + bo.unoccupied_count) * -1 * | 5551 | inputs[7] = (bo.cnt_under_construction + bo.unoccupied_count) * -1 * |
351 | 5535 | std::abs(management_data.get_military_number_at(9)) / 5; | 5552 | std::abs(management_data.get_military_number_at(9)) / 5; |
353 | 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()) ? |
354 | 5537 | management_data.get_military_number_at(7) / 8 : | 5554 | management_data.get_military_number_at(7) / 8 : |
355 | 5538 | 0; | 5555 | 0; |
356 | 5539 | inputs[9] = (bo.is(BuildingAttribute::kBuildingMatProducer)) ? | 5556 | inputs[9] = (bo.is(BuildingAttribute::kBuildingMatProducer)) ? |
357 | @@ -5559,7 +5576,7 @@ | |||
358 | 5559 | management_data.get_military_number_at(97) / 10 : | 5576 | management_data.get_military_number_at(97) / 10 : |
359 | 5560 | 0; | 5577 | 0; |
360 | 5561 | inputs[17] = | 5578 | inputs[17] = |
362 | 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; |
363 | 5563 | inputs[18] = management_data.get_military_number_at(98) / 10; | 5580 | inputs[18] = management_data.get_military_number_at(98) / 10; |
364 | 5564 | inputs[19] = (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) ? | 5581 | inputs[19] = (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) ? |
365 | 5565 | -1 * std::abs(management_data.get_military_number_at(40)) / 10 : | 5582 | -1 * std::abs(management_data.get_military_number_at(40)) / 10 : |
366 | @@ -5592,7 +5609,7 @@ | |||
367 | 5592 | inputs[32] = bo.max_needed_preciousness / 2; | 5609 | inputs[32] = bo.max_needed_preciousness / 2; |
368 | 5593 | inputs[33] = -(bo.cnt_under_construction + bo.unoccupied_count) * 4; | 5610 | inputs[33] = -(bo.cnt_under_construction + bo.unoccupied_count) * 4; |
369 | 5594 | if (bo.cnt_built > 0 && !bo.outputs.empty() && !bo.inputs.empty()) { | 5611 | if (bo.cnt_built > 0 && !bo.outputs.empty() && !bo.inputs.empty()) { |
371 | 5595 | inputs[34] += bo.current_stats / 10; | 5612 | inputs[34] += bo.current_stats / std::abs(management_data.get_military_number_at(192)) * 10; |
372 | 5596 | } | 5613 | } |
373 | 5597 | inputs[35] = (!bo.outputs.empty() && !bo.inputs.empty() && | 5614 | inputs[35] = (!bo.outputs.empty() && !bo.inputs.empty() && |
374 | 5598 | bo.current_stats > 10 + 70 / bo.outputs.size()) ? | 5615 | bo.current_stats > 10 + 70 / bo.outputs.size()) ? |
375 | @@ -5703,6 +5720,14 @@ | |||
376 | 5703 | inputs[105] = -2; | 5720 | inputs[105] = -2; |
377 | 5704 | inputs[106] = -2; | 5721 | inputs[106] = -2; |
378 | 5705 | } | 5722 | } |
379 | 5723 | inputs[107] = std::abs(management_data.get_military_number_at(194)) - get_stocklevel(bo, gametime); | ||
380 | 5724 | inputs[108] = std::abs(management_data.get_military_number_at(191)) - get_stocklevel(bo, gametime); | ||
381 | 5725 | inputs[109] = (!bo.inputs.empty() && gametime > 50 * 60 * 1000 && bo.total_count() <= 1) ? | ||
382 | 5726 | std::abs(management_data.get_military_number_at(163)) / 10 : 0; | ||
383 | 5727 | inputs[110] = (bo.outputs.size() == 1) ? | ||
384 | 5728 | (tribe_->get_ware_descr(bo.outputs.at(0))->default_target_quantity(tribe_->name()) - | ||
385 | 5729 | get_stocklevel(bo, gametime)) * std::abs(management_data.get_military_number_at(165)) / 20 : 0; | ||
386 | 5730 | inputs[111] = bo.current_stats / (bo.outputs.size() + 1); | ||
387 | 5706 | 5731 | ||
388 | 5707 | int16_t tmp_score = 0; | 5732 | int16_t tmp_score = 0; |
389 | 5708 | for (uint8_t i = 0; i < kFNeuronBitSize; ++i) { | 5733 | for (uint8_t i = 0; i < kFNeuronBitSize; ++i) { |
390 | @@ -5779,7 +5804,9 @@ | |||
391 | 5779 | return BuildingNecessity::kNeeded; | 5804 | return BuildingNecessity::kNeeded; |
392 | 5780 | } else if (bo.max_preciousness >= 10 && bo.total_count() == 2) { | 5805 | } else if (bo.max_preciousness >= 10 && bo.total_count() == 2) { |
393 | 5781 | return BuildingNecessity::kNeeded; | 5806 | return BuildingNecessity::kNeeded; |
395 | 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) { |
396 | 5808 | return BuildingNecessity::kNeeded; | ||
397 | 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))) { | ||
398 | 5783 | return BuildingNecessity::kNeeded; | 5810 | return BuildingNecessity::kNeeded; |
399 | 5784 | } else { | 5811 | } else { |
400 | 5785 | return BuildingNecessity::kNotNeeded; | 5812 | return BuildingNecessity::kNotNeeded; |
401 | 5786 | 5813 | ||
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 | 212 | 212 | ||
407 | 213 | uint32_t get_stocklevel_by_hint(size_t); | 213 | uint32_t get_stocklevel_by_hint(size_t); |
408 | 214 | uint32_t get_stocklevel(Widelands::BuildingObserver&, uint32_t, WareWorker = WareWorker::kWare); | 214 | uint32_t get_stocklevel(Widelands::BuildingObserver&, uint32_t, WareWorker = WareWorker::kWare); |
409 | 215 | uint32_t calculate_stocklevel(Widelands::BuildingObserver&, WareWorker = WareWorker::kWare); | ||
410 | 216 | uint32_t calculate_stocklevel(Widelands::DescriptionIndex, | 215 | uint32_t calculate_stocklevel(Widelands::DescriptionIndex, |
411 | 217 | WareWorker = WareWorker::kWare); // count all direct outputs_ | 216 | WareWorker = WareWorker::kWare); // count all direct outputs_ |
412 | 218 | 217 |
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