Merge lp:~widelands-dev/widelands/bug-1829471-worker-preciousness into lp:widelands
- bug-1829471-worker-preciousness
- Merge into trunk
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 9115 | ||||||||
Proposed branch: | lp:~widelands-dev/widelands/bug-1829471-worker-preciousness | ||||||||
Merge into: | lp:widelands | ||||||||
Diff against target: |
879 lines (+264/-158) 27 files modified
data/tribes/atlanteans.lua (+0/-1) data/tribes/barbarians.lua (+0/-1) data/tribes/buildings/productionsites/atlanteans/horsefarm/init.lua (+0/-1) data/tribes/buildings/productionsites/barbarians/cattlefarm/init.lua (+0/-1) data/tribes/buildings/productionsites/empire/donkeyfarm/init.lua (+0/-1) data/tribes/empire.lua (+0/-1) data/tribes/frisians.lua (+0/-1) data/tribes/workers/atlanteans/horse/init.lua (+6/-0) data/tribes/workers/atlanteans/soldier/init.lua (+6/-0) data/tribes/workers/barbarians/ox/init.lua (+6/-0) data/tribes/workers/barbarians/soldier/init.lua (+6/-0) data/tribes/workers/empire/donkey/init.lua (+6/-0) data/tribes/workers/empire/soldier/init.lua (+6/-0) data/tribes/workers/frisians/reindeer/init.lua (+6/-0) data/tribes/workers/frisians/soldier/init.lua (+6/-0) doc/sphinx/source/lua_tribes_workers.rst.org (+62/-54) src/ai/ai_help_structs.h (+1/-0) src/ai/ai_hints.cc (+25/-1) src/ai/ai_hints.h (+27/-5) src/ai/defaultai.cc (+76/-64) src/logic/map_objects/tribes/tribe_descr.cc (+0/-5) src/logic/map_objects/tribes/tribe_descr.h (+0/-2) src/logic/map_objects/tribes/tribes.cc (+1/-1) src/logic/map_objects/tribes/ware_descr.cc (+5/-14) src/logic/map_objects/tribes/ware_descr.h (+9/-5) src/logic/map_objects/tribes/worker_descr.cc (+1/-0) src/logic/map_objects/tribes/worker_descr.h (+9/-0) |
||||||||
To merge this branch: | bzr merge lp:~widelands-dev/widelands/bug-1829471-worker-preciousness | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
hessenfarmer | Approve | ||
TiborB | Approve | ||
Review via email: mp+367608@code.launchpad.net |
Commit message
Some AI code cleanups
- Implement AI hints for workers
- Deduce whether a building is a barracks or recruits other workers from building outputs
- Move ware preciousness into a new AI hint object
- Fixed warning about signed/unsigned comparisons.
Description of the change
There is an assert that is failing now. Since I am not very familiar with the AI code, I don't know why it is there. @Tibor: Do you remember why you put it there?
TiborB (tiborb95) wrote : | # |
TiborB (tiborb95) wrote : | # |
The logic is / was you cannot have max preciousness if you do not produce anything...
GunChleoc (gunchleoc) wrote : | # |
Thanks, that fixed it!
There should be no real impact on training from this branch. This is a pure refactoring without any intended semantic changes except that the reindeer farm now has a minimum preciousness of 2.
GunChleoc (gunchleoc) wrote : | # |
BTW that assert is already broken in trunk.
TiborB (tiborb95) wrote : | # |
I will investigate that assert....
TiborB (tiborb95) wrote : | # |
I am getting the failing assert for atlanteans horsefarm and barbarian cattlefarm - in trunk... They have max_needed_
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 5015. State: passed. Details: https:/
Appveyor build 4796. State: success. Details: https:/
TiborB (tiborb95) wrote : | # |
Was you considering making barracks a recruitment? Because preciousness of barracks (output) is now hardcoded to 5, if I am right.
GunChleoc (gunchleoc) wrote : | # |
I was only focusing on the code that hessenfarmer changed for the carrier2, but I think not having the barracks hard-coded would also be a good idea. I'll have a look.
GunChleoc (gunchleoc) wrote : | # |
Done. No need to investigate the assert failure in trunk further, because it is fixed in this branch. It slipped past us when we reviewed hessenfarmer's branch.
hessenfarmer (stephan-lutz) wrote : | # |
The failed assert came definitly from my changes. I did not compile and test them in debug, cause my machine is so slow. Sorry about that.
The problem is we were handling the recruitment as a producing building so it needed preciousness while in another part we handled it like a non producing building asserting that preciousness is 0.
The desired behaviour should be to handle the barracks and the recruiter like any other building with some output. This needs 2 things the definition of a preciousness for the soldier and the second carrier and some good decisiongates to be taken into account for determining neededness and priority for both of them.
TiborB (tiborb95) wrote : | # |
AI code is simply overcomplicated...
Animals are also workers?
Do we expect that same workers will have no preciousness set?
The overall change looks good to me
hessenfarmer (stephan-lutz) wrote : | # |
As soon as a worker is produced by a building he needs a preciousness (if we think of schools for example). If it is created in the warehouses he does not need a preciousness.
Maybe we have a problem now with the frisian reindeer farm, as it will now be identified as a recruitment site. this will limit the number of them to 2 which is far too less in terms of fur production. In my opinion we need to ensure, that the normal production part of a building takes precedence. But I need to make some tests to confirm this issue.
GunChleoc (gunchleoc) wrote : | # |
Confirmed by looking at the code and fixed. It's fine that you're on release builds, I used to do that too before I bought my new machine.
And yes, animals are carriers, so they are workers.
Unlike for wares, preciousness is not mandatory for workers, since most of them aren't recruited by buildings.
hessenfarmer (stephan-lutz) wrote : | # |
Hmm. I thought we are aiming at having more of the definition stuf in lua so we can change things without the need to recompile. I have the feeling that part of this branch is going in opposite direction. Fo the design of a new tribe I think I would like to have some flags in lua better than determine things from other values, cause this is giving us more flexibility.
hessenfarmer (stephan-lutz) wrote : | # |
One thing I would like to have is a definition of normal AI limit to be able to have the limit values currently hardcoded in lua.
GunChleoc (gunchleoc) wrote : | # |
There is a difference between hard-coding values like "preciousness = 5" and automatically deducing building types that get a completely different treatment and algorithm by the AI anyway.
GunChleoc (gunchleoc) wrote : | # |
P.S. What we probably really should do here is to treat output workers in the exact same way as output wares and get rid of the special treatment code for recruiting sites, but that is out of scope for this branch.
GunChleoc (gunchleoc) wrote : | # |
> One thing I would like to have is a definition of normal AI limit to be able to have the limit values currently hardcoded in lua.
Agreed, I have added it to the bug. I don't want to do it in this branch though, because then we will have to re-review the code in this branch for every new idea that we can come up. I prefer having separate branches for each issue.
hessenfarmer (stephan-lutz) wrote : | # |
> There is a difference between hard-coding values like "preciousness = 5" and
> automatically deducing building types that get a completely different
> treatment and algorithm by the AI anyway.
Agreed on the difference. But not deducing the types and having flags instead gives us more flexibility. However for the moment being we will try to get this in until we need it the other way round again.
hessenfarmer (stephan-lutz) wrote : | # |
I think the deduction of Recruitment of second carrier will not work this way as Outputs of recruitment sites contains the worker so it isn't empty. see inline comment as well
hessenfarmer (stephan-lutz) wrote : | # |
Forget my last comment. I had the wrong conception of bo.outputs
So for me Code looks good will test this tonight.
hessenfarmer (stephan-lutz) wrote : | # |
I have tested it now and found no anomalies (just tested with release build)
so from my side this could go in, although I would keep the first bug open.
hessenfarmer (stephan-lutz) wrote : | # |
@bunnybot merge
Preview Diff
1 | === modified file 'data/tribes/atlanteans.lua' | |||
2 | --- data/tribes/atlanteans.lua 2018-07-29 13:49:09 +0000 | |||
3 | +++ data/tribes/atlanteans.lua 2019-05-19 16:18:33 +0000 | |||
4 | @@ -375,7 +375,6 @@ | |||
5 | 375 | soldier = "atlanteans_soldier", | 375 | soldier = "atlanteans_soldier", |
6 | 376 | ship = "atlanteans_ship", | 376 | ship = "atlanteans_ship", |
7 | 377 | port = "atlanteans_port", | 377 | port = "atlanteans_port", |
8 | 378 | barracks = "atlanteans_barracks", | ||
9 | 379 | ironore = "iron_ore", | 378 | ironore = "iron_ore", |
10 | 380 | rawlog = "log", | 379 | rawlog = "log", |
11 | 381 | refinedlog = "planks", | 380 | refinedlog = "planks", |
12 | 382 | 381 | ||
13 | === modified file 'data/tribes/barbarians.lua' | |||
14 | --- data/tribes/barbarians.lua 2018-07-29 13:49:09 +0000 | |||
15 | +++ data/tribes/barbarians.lua 2019-05-19 16:18:33 +0000 | |||
16 | @@ -308,7 +308,6 @@ | |||
17 | 308 | soldier = "barbarians_soldier", | 308 | soldier = "barbarians_soldier", |
18 | 309 | ship = "barbarians_ship", | 309 | ship = "barbarians_ship", |
19 | 310 | port = "barbarians_port", | 310 | port = "barbarians_port", |
20 | 311 | barracks = "barbarians_barracks", | ||
21 | 312 | ironore = "iron_ore", | 311 | ironore = "iron_ore", |
22 | 313 | rawlog = "log", | 312 | rawlog = "log", |
23 | 314 | refinedlog = "blackwood", | 313 | refinedlog = "blackwood", |
24 | 315 | 314 | ||
25 | === modified file 'data/tribes/buildings/productionsites/atlanteans/horsefarm/init.lua' | |||
26 | --- data/tribes/buildings/productionsites/atlanteans/horsefarm/init.lua 2019-05-15 06:29:24 +0000 | |||
27 | +++ data/tribes/buildings/productionsites/atlanteans/horsefarm/init.lua 2019-05-19 16:18:33 +0000 | |||
28 | @@ -31,7 +31,6 @@ | |||
29 | 31 | }, | 31 | }, |
30 | 32 | 32 | ||
31 | 33 | aihints = { | 33 | aihints = { |
32 | 34 | recruitment = true, | ||
33 | 35 | prohibited_till = 610, | 34 | prohibited_till = 610, |
34 | 36 | }, | 35 | }, |
35 | 37 | 36 | ||
36 | 38 | 37 | ||
37 | === modified file 'data/tribes/buildings/productionsites/barbarians/cattlefarm/init.lua' | |||
38 | --- data/tribes/buildings/productionsites/barbarians/cattlefarm/init.lua 2019-05-15 06:29:24 +0000 | |||
39 | +++ data/tribes/buildings/productionsites/barbarians/cattlefarm/init.lua 2019-05-19 16:18:33 +0000 | |||
40 | @@ -31,7 +31,6 @@ | |||
41 | 31 | }, | 31 | }, |
42 | 32 | 32 | ||
43 | 33 | aihints = { | 33 | aihints = { |
44 | 34 | recruitment = true, | ||
45 | 35 | prohibited_till = 610, | 34 | prohibited_till = 610, |
46 | 36 | }, | 35 | }, |
47 | 37 | 36 | ||
48 | 38 | 37 | ||
49 | === modified file 'data/tribes/buildings/productionsites/empire/donkeyfarm/init.lua' | |||
50 | --- data/tribes/buildings/productionsites/empire/donkeyfarm/init.lua 2019-05-15 06:29:24 +0000 | |||
51 | +++ data/tribes/buildings/productionsites/empire/donkeyfarm/init.lua 2019-05-19 16:18:33 +0000 | |||
52 | @@ -31,7 +31,6 @@ | |||
53 | 31 | }, | 31 | }, |
54 | 32 | 32 | ||
55 | 33 | aihints = { | 33 | aihints = { |
56 | 34 | recruitment = true, | ||
57 | 35 | prohibited_till = 610, | 34 | prohibited_till = 610, |
58 | 36 | }, | 35 | }, |
59 | 37 | 36 | ||
60 | 38 | 37 | ||
61 | === modified file 'data/tribes/empire.lua' | |||
62 | --- data/tribes/empire.lua 2018-07-29 13:49:09 +0000 | |||
63 | +++ data/tribes/empire.lua 2019-05-19 16:18:33 +0000 | |||
64 | @@ -350,7 +350,6 @@ | |||
65 | 350 | soldier = "empire_soldier", | 350 | soldier = "empire_soldier", |
66 | 351 | ship = "empire_ship", | 351 | ship = "empire_ship", |
67 | 352 | port = "empire_port", | 352 | port = "empire_port", |
68 | 353 | barracks = "empire_barracks", | ||
69 | 354 | ironore = "iron_ore", | 353 | ironore = "iron_ore", |
70 | 355 | rawlog = "log", | 354 | rawlog = "log", |
71 | 356 | refinedlog = "planks", | 355 | refinedlog = "planks", |
72 | 357 | 356 | ||
73 | === modified file 'data/tribes/frisians.lua' | |||
74 | --- data/tribes/frisians.lua 2019-02-28 11:03:51 +0000 | |||
75 | +++ data/tribes/frisians.lua 2019-05-19 16:18:33 +0000 | |||
76 | @@ -349,7 +349,6 @@ | |||
77 | 349 | soldier = "frisians_soldier", | 349 | soldier = "frisians_soldier", |
78 | 350 | ship = "frisians_ship", | 350 | ship = "frisians_ship", |
79 | 351 | port = "frisians_port", | 351 | port = "frisians_port", |
80 | 352 | barracks = "frisians_barracks", | ||
81 | 353 | ironore = "iron_ore", | 352 | ironore = "iron_ore", |
82 | 354 | rawlog = "log", | 353 | rawlog = "log", |
83 | 355 | refinedlog = "brick", | 354 | refinedlog = "brick", |
84 | 356 | 355 | ||
85 | === modified file 'data/tribes/workers/atlanteans/horse/init.lua' | |||
86 | --- data/tribes/workers/atlanteans/horse/init.lua 2017-02-12 09:10:57 +0000 | |||
87 | +++ data/tribes/workers/atlanteans/horse/init.lua 2019-05-19 16:18:33 +0000 | |||
88 | @@ -24,4 +24,10 @@ | |||
89 | 24 | ware_hotspot = {-2, 12}, | 24 | ware_hotspot = {-2, 12}, |
90 | 25 | 25 | ||
91 | 26 | animations = animations, | 26 | animations = animations, |
92 | 27 | |||
93 | 28 | aihints = { | ||
94 | 29 | preciousness = { | ||
95 | 30 | atlanteans = 2 | ||
96 | 31 | }, | ||
97 | 32 | } | ||
98 | 27 | } | 33 | } |
99 | 28 | 34 | ||
100 | === modified file 'data/tribes/workers/atlanteans/soldier/init.lua' | |||
101 | --- data/tribes/workers/atlanteans/soldier/init.lua 2019-05-18 12:05:22 +0000 | |||
102 | +++ data/tribes/workers/atlanteans/soldier/init.lua 2019-05-19 16:18:33 +0000 | |||
103 | @@ -284,6 +284,12 @@ | |||
104 | 284 | pictures = path.list_files(dirname .. "evade_level?.png"), | 284 | pictures = path.list_files(dirname .. "evade_level?.png"), |
105 | 285 | }, | 285 | }, |
106 | 286 | 286 | ||
107 | 287 | aihints = { | ||
108 | 288 | preciousness = { | ||
109 | 289 | atlanteans = 5 | ||
110 | 290 | }, | ||
111 | 291 | }, | ||
112 | 292 | |||
113 | 287 | -- Random animations for battle | 293 | -- Random animations for battle |
114 | 288 | -- TODO(GunChleoc): Make more animations to use the random function | 294 | -- TODO(GunChleoc): Make more animations to use the random function |
115 | 289 | attack_success_w = { | 295 | attack_success_w = { |
116 | 290 | 296 | ||
117 | === modified file 'data/tribes/workers/barbarians/ox/init.lua' | |||
118 | --- data/tribes/workers/barbarians/ox/init.lua 2017-02-12 09:10:57 +0000 | |||
119 | +++ data/tribes/workers/barbarians/ox/init.lua 2019-05-19 16:18:33 +0000 | |||
120 | @@ -25,4 +25,10 @@ | |||
121 | 25 | ware_hotspot = { -2, 13 }, | 25 | ware_hotspot = { -2, 13 }, |
122 | 26 | 26 | ||
123 | 27 | animations = animations, | 27 | animations = animations, |
124 | 28 | |||
125 | 29 | aihints = { | ||
126 | 30 | preciousness = { | ||
127 | 31 | barbarians = 2 | ||
128 | 32 | }, | ||
129 | 33 | } | ||
130 | 28 | } | 34 | } |
131 | 29 | 35 | ||
132 | === modified file 'data/tribes/workers/barbarians/soldier/init.lua' | |||
133 | --- data/tribes/workers/barbarians/soldier/init.lua 2019-04-26 19:10:45 +0000 | |||
134 | +++ data/tribes/workers/barbarians/soldier/init.lua 2019-05-19 16:18:33 +0000 | |||
135 | @@ -110,6 +110,12 @@ | |||
136 | 110 | pictures = path.list_files(dirname .. "evade_level?.png"), | 110 | pictures = path.list_files(dirname .. "evade_level?.png"), |
137 | 111 | }, | 111 | }, |
138 | 112 | 112 | ||
139 | 113 | aihints = { | ||
140 | 114 | preciousness = { | ||
141 | 115 | barbarians = 5 | ||
142 | 116 | }, | ||
143 | 117 | }, | ||
144 | 118 | |||
145 | 113 | -- Random animations for battle | 119 | -- Random animations for battle |
146 | 114 | attack_success_w = { | 120 | attack_success_w = { |
147 | 115 | atk_ok_w = all_levels_bar, | 121 | atk_ok_w = all_levels_bar, |
148 | 116 | 122 | ||
149 | === modified file 'data/tribes/workers/empire/donkey/init.lua' | |||
150 | --- data/tribes/workers/empire/donkey/init.lua 2017-02-12 09:10:57 +0000 | |||
151 | +++ data/tribes/workers/empire/donkey/init.lua 2019-05-19 16:18:33 +0000 | |||
152 | @@ -24,4 +24,10 @@ | |||
153 | 24 | ware_hotspot = { -2, 8 }, | 24 | ware_hotspot = { -2, 8 }, |
154 | 25 | 25 | ||
155 | 26 | animations = animations, | 26 | animations = animations, |
156 | 27 | |||
157 | 28 | aihints = { | ||
158 | 29 | preciousness = { | ||
159 | 30 | empire = 2 | ||
160 | 31 | }, | ||
161 | 32 | } | ||
162 | 27 | } | 33 | } |
163 | 28 | 34 | ||
164 | === modified file 'data/tribes/workers/empire/soldier/init.lua' | |||
165 | --- data/tribes/workers/empire/soldier/init.lua 2019-04-26 19:10:45 +0000 | |||
166 | +++ data/tribes/workers/empire/soldier/init.lua 2019-05-19 16:18:33 +0000 | |||
167 | @@ -110,6 +110,12 @@ | |||
168 | 110 | pictures = path.list_files(dirname .. "evade_level?.png"), | 110 | pictures = path.list_files(dirname .. "evade_level?.png"), |
169 | 111 | }, | 111 | }, |
170 | 112 | 112 | ||
171 | 113 | aihints = { | ||
172 | 114 | preciousness = { | ||
173 | 115 | empire = 5 | ||
174 | 116 | }, | ||
175 | 117 | }, | ||
176 | 118 | |||
177 | 113 | -- Random animations for battle | 119 | -- Random animations for battle |
178 | 114 | attack_success_w = { | 120 | attack_success_w = { |
179 | 115 | atk_ok_w = all_levels_emp, | 121 | atk_ok_w = all_levels_emp, |
180 | 116 | 122 | ||
181 | === modified file 'data/tribes/workers/frisians/reindeer/init.lua' | |||
182 | --- data/tribes/workers/frisians/reindeer/init.lua 2018-02-06 11:17:48 +0000 | |||
183 | +++ data/tribes/workers/frisians/reindeer/init.lua 2019-05-19 16:18:33 +0000 | |||
184 | @@ -24,4 +24,10 @@ | |||
185 | 24 | ware_hotspot = { 0, 18 }, | 24 | ware_hotspot = { 0, 18 }, |
186 | 25 | 25 | ||
187 | 26 | animations = animations, | 26 | animations = animations, |
188 | 27 | |||
189 | 28 | aihints = { | ||
190 | 29 | preciousness = { | ||
191 | 30 | frisians = 2 | ||
192 | 31 | }, | ||
193 | 32 | } | ||
194 | 27 | } | 33 | } |
195 | 28 | 34 | ||
196 | === modified file 'data/tribes/workers/frisians/soldier/init.lua' | |||
197 | --- data/tribes/workers/frisians/soldier/init.lua 2019-05-18 20:43:25 +0000 | |||
198 | +++ data/tribes/workers/frisians/soldier/init.lua 2019-05-19 16:18:33 +0000 | |||
199 | @@ -434,6 +434,12 @@ | |||
200 | 434 | pictures = path.list_files (dirname .. "evade_level?.png"), | 434 | pictures = path.list_files (dirname .. "evade_level?.png"), |
201 | 435 | }, | 435 | }, |
202 | 436 | 436 | ||
203 | 437 | aihints = { | ||
204 | 438 | preciousness = { | ||
205 | 439 | frisians = 5 | ||
206 | 440 | }, | ||
207 | 441 | }, | ||
208 | 442 | |||
209 | 437 | -- Random animations for battle | 443 | -- Random animations for battle |
210 | 438 | attack_success_e = { | 444 | attack_success_e = { |
211 | 439 | atk_ok_1_w = fri_rookie, | 445 | atk_ok_1_w = fri_rookie, |
212 | 440 | 446 | ||
213 | === modified file 'doc/sphinx/source/lua_tribes_workers.rst.org' | |||
214 | --- doc/sphinx/source/lua_tribes_workers.rst.org 2018-11-30 10:36:42 +0000 | |||
215 | +++ doc/sphinx/source/lua_tribes_workers.rst.org 2019-05-19 16:18:33 +0000 | |||
216 | @@ -17,60 +17,68 @@ | |||
217 | 17 | 17 | ||
218 | 18 | Workers are defined with Lua functions called ``new_<worker_type>_type{table}``. The contents of ``table`` depend on the type of worker that you are defining. The common properties shared by all workers are: | 18 | Workers are defined with Lua functions called ``new_<worker_type>_type{table}``. The contents of ``table`` depend on the type of worker that you are defining. The common properties shared by all workers are: |
219 | 19 | 19 | ||
274 | 20 | **msgctxt**: The context that Gettext will use to disambiguate the | 20 | **msgctxt**: The context that Gettext will use to disambiguate the |
275 | 21 | translations for strings in this table. | 21 | translations for strings in this table. |
276 | 22 | 22 | ||
277 | 23 | **name**: A string containing the internal name of this worker. | 23 | **name**: A string containing the internal name of this worker. |
278 | 24 | 24 | ||
279 | 25 | **descname**: The translatable display name. Use ``pgettext`` with the | 25 | **descname**: The translatable display name. Use ``pgettext`` with the |
280 | 26 | ``msgctxt`` above to fetch the string. | 26 | ``msgctxt`` above to fetch the string. |
281 | 27 | 27 | ||
282 | 28 | **helptext_script**: The full path to the ``helptexts.lua`` script for this worker. | 28 | **helptext_script**: The full path to the ``helptexts.lua`` script for this worker. |
283 | 29 | 29 | ||
284 | 30 | **icon**: The full path to the menu icon for this worker. | 30 | **icon**: The full path to the menu icon for this worker. |
285 | 31 | 31 | ||
286 | 32 | **vision_range** | 32 | **vision_range** |
287 | 33 | The size of the radius that the worker sees. | 33 | The size of the radius that the worker sees. |
288 | 34 | 34 | ||
289 | 35 | **buildcost** | 35 | **buildcost** |
290 | 36 | *Optional*. A table with the wares and workers used by warehouses to | 36 | *Optional*. A table with the wares and workers used by warehouses to |
291 | 37 | create this worker, containing warename - amount pairs, e.g.:: | 37 | create this worker, containing warename - amount pairs, e.g.:: |
292 | 38 | 38 | ||
293 | 39 | buildcost = { atlanteans_carrier = 1, hammer = 1 } | 39 | buildcost = { atlanteans_carrier = 1, hammer = 1 } |
294 | 40 | 40 | ||
295 | 41 | **default_target_quantity**: | 41 | **default_target_quantity**: |
296 | 42 | *Optional*. An int defining the default target quantity for the worker's | 42 | *Optional*. An int defining the default target quantity for the worker's |
297 | 43 | tribe's economy. Use this if the worker is produced by a production site | 43 | tribe's economy. Use this if the worker is produced by a production site |
298 | 44 | rather than the warehouses. For example, ``default_target_quantity = 10`` | 44 | rather than the warehouses. For example, ``default_target_quantity = 10`` |
299 | 45 | 45 | ||
300 | 46 | **experience** | 46 | **experience** |
301 | 47 | *Optional*. The amount of experience that the worker needs to gather | 47 | *Optional*. The amount of experience that the worker needs to gather |
302 | 48 | in order to be transformend into a higher worker type. If `becomes` | 48 | in order to be transformend into a higher worker type. If `becomes` |
303 | 49 | is defined, this needs to be set as well. | 49 | is defined, this needs to be set as well. |
304 | 50 | 50 | ||
305 | 51 | **becomes** | 51 | **becomes** |
306 | 52 | *Optional*. The name of the higher worker type that this worker will | 52 | *Optional*. The name of the higher worker type that this worker will |
307 | 53 | transform to after gaining enough experience. If `experience` | 53 | transform to after gaining enough experience. If `experience` |
308 | 54 | is defined, this needs to be set as well. | 54 | is defined, this needs to be set as well. |
309 | 55 | 55 | ||
310 | 56 | **animations**: | 56 | **animations**: |
311 | 57 | A table containing all animations for this worker. | 57 | A table containing all animations for this worker. |
312 | 58 | Workers have an "idle" animation. They also have directional animations | 58 | Workers have an "idle" animation. They also have directional animations |
313 | 59 | called "walk" and "walkload" which are defined with the help of | 59 | called "walk" and "walkload" which are defined with the help of |
314 | 60 | :func:`add_walking_animations`, plus additional :ref:`animations` used in their | 60 | :func:`add_walking_animations`, plus additional :ref:`animations` used in their |
315 | 61 | worker programs. The "idle" and "walk" animations are mandatory. | 61 | worker programs. The "idle" and "walk" animations are mandatory. |
316 | 62 | 62 | ||
317 | 63 | **programs**: | 63 | **programs**: |
318 | 64 | *Optional*. If the worker leaves the building to do his work, the :ref:`tribes_worker_programs` that define which type of space or resource the worker has to find | 64 | *Optional*. If the worker leaves the building to do his work, the |
319 | 65 | on the map in order to do his work, and what that work is, including any | 65 | :ref:`tribes_worker_programs` that define which type of space or resource |
320 | 66 | animations and sounds played. | 66 | the worker has to find on the map in order to do his work, and what that |
321 | 67 | 67 | work is, including any animations and sounds played. | |
322 | 68 | **ware_hotspot** | 68 | |
323 | 69 | *Optional*. The x, y coordinates for adjusting the placement of the | 69 | **ware_hotspot** |
324 | 70 | ware being carried. The default value is ``{0, 15}``. Increase ``x`` | 70 | *Optional*. The x, y coordinates for adjusting the placement of the |
325 | 71 | to shift the ware to the left and ``y`` to shift it upwards. For example:: | 71 | ware being carried. The default value is ``{0, 15}``. Increase ``x`` |
326 | 72 | 72 | to shift the ware to the left and ``y`` to shift it upwards. For example:: | |
327 | 73 | ware_hotspot = { -2, 13 }, | 73 | |
328 | 74 | ware_hotspot = { -2, 13 }, | ||
329 | 75 | |||
330 | 76 | **aihints** | ||
331 | 77 | *Optional*. A list of hints for the AI. Can contain the following optional entries: | ||
332 | 78 | |||
333 | 79 | **preciousness**: How precious this worker is to each tribe. For example, | ||
334 | 80 | ``{ atlanteans = 0, empire = 1 }``. You can use this for workers that are recruited. | ||
335 | 81 | |||
336 | 74 | 82 | ||
337 | 75 | .. _lua_tribes_workers_helptexts: | 83 | .. _lua_tribes_workers_helptexts: |
338 | 76 | 84 | ||
339 | 77 | 85 | ||
340 | === modified file 'src/ai/ai_help_structs.h' | |||
341 | --- src/ai/ai_help_structs.h 2019-05-05 14:05:07 +0000 | |||
342 | +++ src/ai/ai_help_structs.h 2019-05-19 16:18:33 +0000 | |||
343 | @@ -477,6 +477,7 @@ | |||
344 | 477 | bool requires_supporters; | 477 | bool requires_supporters; |
345 | 478 | 478 | ||
346 | 479 | // information needed for decision on new building construction | 479 | // information needed for decision on new building construction |
347 | 480 | int16_t initial_preciousness; | ||
348 | 480 | int16_t max_preciousness; | 481 | int16_t max_preciousness; |
349 | 481 | int16_t max_needed_preciousness; | 482 | int16_t max_needed_preciousness; |
350 | 482 | 483 | ||
351 | 483 | 484 | ||
352 | === modified file 'src/ai/ai_hints.cc' | |||
353 | --- src/ai/ai_hints.cc 2019-02-23 11:00:49 +0000 | |||
354 | +++ src/ai/ai_hints.cc 2019-05-19 16:18:33 +0000 | |||
355 | @@ -223,7 +223,6 @@ | |||
356 | 223 | BuildingHints::BuildingHints(std::unique_ptr<LuaTable> table) | 223 | BuildingHints::BuildingHints(std::unique_ptr<LuaTable> table) |
357 | 224 | : mines_(table->has_key("mines") ? table->get_string("mines") : ""), | 224 | : mines_(table->has_key("mines") ? table->get_string("mines") : ""), |
358 | 225 | needs_water_(table->has_key("needs_water") ? table->get_bool("needs_water") : false), | 225 | needs_water_(table->has_key("needs_water") ? table->get_bool("needs_water") : false), |
359 | 226 | recruitment_(table->has_key("recruitment") ? table->get_bool("recruitment") : false), | ||
360 | 227 | space_consumer_(table->has_key("space_consumer") ? table->get_bool("space_consumer") : false), | 226 | space_consumer_(table->has_key("space_consumer") ? table->get_bool("space_consumer") : false), |
361 | 228 | expansion_(table->has_key("expansion") ? table->get_bool("expansion") : false), | 227 | expansion_(table->has_key("expansion") ? table->get_bool("expansion") : false), |
362 | 229 | fighting_(table->has_key("fighting") ? table->get_bool("fighting") : false), | 228 | fighting_(table->has_key("fighting") ? table->get_bool("fighting") : false), |
363 | @@ -274,3 +273,28 @@ | |||
364 | 274 | } | 273 | } |
365 | 275 | NEVER_HERE(); | 274 | NEVER_HERE(); |
366 | 276 | } | 275 | } |
367 | 276 | |||
368 | 277 | |||
369 | 278 | // TODO(GunChleoc): WareDescr has a bare "preciousness" table that should be moved below a new "aihints" table. | ||
370 | 279 | void WareWorkerHints::read_preciousness(const LuaTable& table) { | ||
371 | 280 | for (const std::string& key : table.keys<std::string>()) { | ||
372 | 281 | preciousnesses_.insert(std::make_pair(key, table.get_int(key))); | ||
373 | 282 | } | ||
374 | 283 | } | ||
375 | 284 | |||
376 | 285 | /// Returns the preciousness of the ware, or kInvalidWare if the tribe doesn't use the ware. | ||
377 | 286 | int WareWorkerHints::preciousness(const std::string& tribename) const { | ||
378 | 287 | if (preciousnesses_.count(tribename) > 0) { | ||
379 | 288 | return preciousnesses_.at(tribename); | ||
380 | 289 | } | ||
381 | 290 | return Widelands::kInvalidWare; | ||
382 | 291 | } | ||
383 | 292 | |||
384 | 293 | WareHints::WareHints(const LuaTable& table) : WareWorkerHints() { | ||
385 | 294 | read_preciousness(table); | ||
386 | 295 | } | ||
387 | 296 | |||
388 | 297 | |||
389 | 298 | WorkerHints::WorkerHints(const LuaTable& table) : WareWorkerHints() { | ||
390 | 299 | read_preciousness(*table.get_table("preciousness")); | ||
391 | 300 | } | ||
392 | 277 | 301 | ||
393 | === modified file 'src/ai/ai_hints.h' | |||
394 | --- src/ai/ai_hints.h 2019-02-23 11:00:49 +0000 | |||
395 | +++ src/ai/ai_hints.h 2019-05-19 16:18:33 +0000 | |||
396 | @@ -23,9 +23,11 @@ | |||
397 | 23 | #include <memory> | 23 | #include <memory> |
398 | 24 | #include <stdint.h> | 24 | #include <stdint.h> |
399 | 25 | #include <string> | 25 | #include <string> |
400 | 26 | #include <unordered_map> | ||
401 | 26 | 27 | ||
402 | 27 | #include "base/log.h" | 28 | #include "base/log.h" |
403 | 28 | #include "base/macros.h" | 29 | #include "base/macros.h" |
404 | 30 | #include "logic/widelands.h" | ||
405 | 29 | #include "scripting/lua_table.h" | 31 | #include "scripting/lua_table.h" |
406 | 30 | 32 | ||
407 | 31 | namespace Widelands { | 33 | namespace Widelands { |
408 | @@ -56,10 +58,6 @@ | |||
409 | 56 | return needs_water_; | 58 | return needs_water_; |
410 | 57 | } | 59 | } |
411 | 58 | 60 | ||
412 | 59 | bool for_recruitment() const { | ||
413 | 60 | return recruitment_; | ||
414 | 61 | } | ||
415 | 62 | |||
416 | 63 | bool is_space_consumer() const { | 61 | bool is_space_consumer() const { |
417 | 64 | return space_consumer_; | 62 | return space_consumer_; |
418 | 65 | } | 63 | } |
419 | @@ -110,7 +108,6 @@ | |||
420 | 110 | private: | 108 | private: |
421 | 111 | const std::string mines_; | 109 | const std::string mines_; |
422 | 112 | const bool needs_water_; | 110 | const bool needs_water_; |
423 | 113 | const bool recruitment_; | ||
424 | 114 | const bool space_consumer_; | 111 | const bool space_consumer_; |
425 | 115 | const bool expansion_; | 112 | const bool expansion_; |
426 | 116 | const bool fighting_; | 113 | const bool fighting_; |
427 | @@ -131,4 +128,29 @@ | |||
428 | 131 | DISALLOW_COPY_AND_ASSIGN(BuildingHints); | 128 | DISALLOW_COPY_AND_ASSIGN(BuildingHints); |
429 | 132 | }; | 129 | }; |
430 | 133 | 130 | ||
431 | 131 | /// Hints common to wares and workers | ||
432 | 132 | struct WareWorkerHints { | ||
433 | 133 | WareWorkerHints() = default; | ||
434 | 134 | |||
435 | 135 | /// Returns the preciousness of the ware/worker, or kInvalidWare if the tribe doesn't use the ware/worker or the worker has no preciousness defined for the tribe. | ||
436 | 136 | int preciousness(const std::string& tribename) const; | ||
437 | 137 | |||
438 | 138 | protected: | ||
439 | 139 | void read_preciousness(const LuaTable& table); | ||
440 | 140 | |||
441 | 141 | private: | ||
442 | 142 | // tribename, preciousness. No default. | ||
443 | 143 | std::unordered_map<std::string, int> preciousnesses_; | ||
444 | 144 | }; | ||
445 | 145 | |||
446 | 146 | /// Hints for wares | ||
447 | 147 | struct WareHints : WareWorkerHints { | ||
448 | 148 | explicit WareHints(const LuaTable& table); | ||
449 | 149 | }; | ||
450 | 150 | |||
451 | 151 | /// Hints for workers | ||
452 | 152 | struct WorkerHints : WareWorkerHints { | ||
453 | 153 | explicit WorkerHints(const LuaTable& table); | ||
454 | 154 | }; | ||
455 | 155 | |||
456 | 134 | #endif // end of include guard: WL_AI_AI_HINTS_H | 156 | #endif // end of include guard: WL_AI_AI_HINTS_H |
457 | 135 | 157 | ||
458 | === modified file 'src/ai/defaultai.cc' | |||
459 | --- src/ai/defaultai.cc 2019-05-17 11:45:39 +0000 | |||
460 | +++ src/ai/defaultai.cc 2019-05-19 16:18:33 +0000 | |||
461 | @@ -52,7 +52,7 @@ | |||
462 | 52 | #include "logic/player.h" | 52 | #include "logic/player.h" |
463 | 53 | #include "logic/playercommand.h" | 53 | #include "logic/playercommand.h" |
464 | 54 | 54 | ||
466 | 55 | // following is in miliseconds (widelands counts time in ms) | 55 | // following is in milliseconds (widelands counts time in ms) |
467 | 56 | constexpr int kFieldInfoExpiration = 12 * 1000; | 56 | constexpr int kFieldInfoExpiration = 12 * 1000; |
468 | 57 | constexpr int kMineFieldInfoExpiration = 20 * 1000; | 57 | constexpr int kMineFieldInfoExpiration = 20 * 1000; |
469 | 58 | constexpr int kNewMineConstInterval = 19000; | 58 | constexpr int kNewMineConstInterval = 19000; |
470 | @@ -517,7 +517,7 @@ | |||
471 | 517 | for (DescriptionIndex i = 0; i < static_cast<DescriptionIndex>(game().tribes().nrwares()); ++i) { | 517 | for (DescriptionIndex i = 0; i < static_cast<DescriptionIndex>(game().tribes().nrwares()); ++i) { |
472 | 518 | wares.at(i).producers = 0; | 518 | wares.at(i).producers = 0; |
473 | 519 | wares.at(i).consumers = 0; | 519 | wares.at(i).consumers = 0; |
475 | 520 | wares.at(i).preciousness = game().tribes().get_ware_descr(i)->preciousness(tribe_->name()); | 520 | wares.at(i).preciousness = game().tribes().get_ware_descr(i)->ai_hints().preciousness(tribe_->name()); |
476 | 521 | } | 521 | } |
477 | 522 | 522 | ||
478 | 523 | const DescriptionIndex& nr_buildings = game().tribes().nrbuildings(); | 523 | const DescriptionIndex& nr_buildings = game().tribes().nrbuildings(); |
479 | @@ -637,9 +637,6 @@ | |||
480 | 637 | if (bh.is_space_consumer()) { | 637 | if (bh.is_space_consumer()) { |
481 | 638 | bo.set_is(BuildingAttribute::kSpaceConsumer); | 638 | bo.set_is(BuildingAttribute::kSpaceConsumer); |
482 | 639 | } | 639 | } |
483 | 640 | if (bh.for_recruitment()) { | ||
484 | 641 | bo.set_is(BuildingAttribute::kRecruitment); | ||
485 | 642 | } | ||
486 | 643 | bo.expansion_type = bh.is_expansion_type(); | 640 | bo.expansion_type = bh.is_expansion_type(); |
487 | 644 | bo.fighting_type = bh.is_fighting_type(); | 641 | bo.fighting_type = bh.is_fighting_type(); |
488 | 645 | bo.mountain_conqueror = bh.is_mountain_conqueror(); | 642 | bo.mountain_conqueror = bh.is_mountain_conqueror(); |
489 | @@ -658,6 +655,7 @@ | |||
490 | 658 | bo.set_is(BuildingAttribute::kPort); | 655 | bo.set_is(BuildingAttribute::kPort); |
491 | 659 | } | 656 | } |
492 | 660 | bo.max_trainingsites_proportion = 100; | 657 | bo.max_trainingsites_proportion = 100; |
493 | 658 | bo.initial_preciousness = 0; | ||
494 | 661 | bo.max_preciousness = 0; | 659 | bo.max_preciousness = 0; |
495 | 662 | bo.max_needed_preciousness = 0; | 660 | bo.max_needed_preciousness = 0; |
496 | 663 | 661 | ||
497 | @@ -684,6 +682,26 @@ | |||
498 | 684 | for (const DescriptionIndex& temp_output : prod.output_ware_types()) { | 682 | for (const DescriptionIndex& temp_output : prod.output_ware_types()) { |
499 | 685 | bo.outputs.push_back(temp_output); | 683 | bo.outputs.push_back(temp_output); |
500 | 686 | } | 684 | } |
501 | 685 | |||
502 | 686 | // Read information about worker outputs | ||
503 | 687 | if (prod.output_worker_types().size() > 0) { | ||
504 | 688 | for (const DescriptionIndex& temp_output : prod.output_worker_types()) { | ||
505 | 689 | if (temp_output == tribe_->soldier()) { | ||
506 | 690 | bo.set_is(BuildingAttribute::kBarracks); | ||
507 | 691 | } | ||
508 | 692 | const WorkerHints* worker_hints = tribe_->get_worker_descr(temp_output)->ai_hints(); | ||
509 | 693 | if (worker_hints != nullptr) { | ||
510 | 694 | const int worker_preciousness = worker_hints->preciousness(tribe_->name()); | ||
511 | 695 | if (worker_preciousness != Widelands::kInvalidWare) { | ||
512 | 696 | bo.initial_preciousness += worker_preciousness; | ||
513 | 697 | } | ||
514 | 698 | } | ||
515 | 699 | } | ||
516 | 700 | if (!bo.is(BuildingAttribute::kBarracks) && bo.outputs.empty()) { | ||
517 | 701 | bo.set_is(BuildingAttribute::kRecruitment); | ||
518 | 702 | } | ||
519 | 703 | } | ||
520 | 704 | |||
521 | 687 | for (const auto& temp_position : prod.working_positions()) { | 705 | for (const auto& temp_position : prod.working_positions()) { |
522 | 688 | bo.positions.push_back(temp_position.first); | 706 | bo.positions.push_back(temp_position.first); |
523 | 689 | } | 707 | } |
524 | @@ -719,9 +737,6 @@ | |||
525 | 719 | if (bh.is_shipyard()) { | 737 | if (bh.is_shipyard()) { |
526 | 720 | bo.set_is(BuildingAttribute::kShipyard); | 738 | bo.set_is(BuildingAttribute::kShipyard); |
527 | 721 | } | 739 | } |
528 | 722 | if (building_index == tribe_->barracks()) { | ||
529 | 723 | bo.set_is(BuildingAttribute::kBarracks); | ||
530 | 724 | } | ||
531 | 725 | // Identify refined log producer | 740 | // Identify refined log producer |
532 | 726 | if (bo.outputs.size() == 1 && bo.outputs[0] == tribe_->refinedlog()) { | 741 | if (bo.outputs.size() == 1 && bo.outputs[0] == tribe_->refinedlog()) { |
533 | 727 | bo.set_is(BuildingAttribute::kLogRefiner); | 742 | bo.set_is(BuildingAttribute::kLogRefiner); |
534 | @@ -2489,20 +2504,23 @@ | |||
535 | 2489 | 2504 | ||
536 | 2490 | // Now verifying that all 'buildable' buildings has positive max_needed_preciousness | 2505 | // Now verifying that all 'buildable' buildings has positive max_needed_preciousness |
537 | 2491 | // if they have outputs, all other must have zero max_needed_preciousness | 2506 | // if they have outputs, all other must have zero max_needed_preciousness |
543 | 2492 | if ((bo.new_building == BuildingNecessity::kNeeded || | 2507 | |
544 | 2493 | bo.new_building == BuildingNecessity::kForced || | 2508 | if (bo.new_building == BuildingNecessity::kForbidden) { |
545 | 2494 | bo.new_building == BuildingNecessity::kAllowed || | 2509 | bo.max_needed_preciousness = 0; |
546 | 2495 | bo.new_building == BuildingNecessity::kNeededPending) && | 2510 | } else if ((bo.new_building == BuildingNecessity::kNeeded || |
547 | 2496 | (!bo.outputs.empty() || bo.is(BuildingAttribute::kBarracks))) { | 2511 | bo.new_building == BuildingNecessity::kForced || |
548 | 2512 | bo.new_building == BuildingNecessity::kAllowed || | ||
549 | 2513 | bo.new_building == BuildingNecessity::kNeededPending) && | ||
550 | 2514 | (!bo.outputs.empty() || bo.initial_preciousness > 0)) { // bo.initial_preciousness signals that we have a worker output | ||
551 | 2515 | bo.max_needed_preciousness = std::max(bo.max_needed_preciousness, bo.initial_preciousness); | ||
552 | 2516 | bo.max_preciousness = std::max(bo.max_preciousness, bo.initial_preciousness); | ||
553 | 2517 | |||
554 | 2497 | if (bo.max_needed_preciousness <= 0) { | 2518 | if (bo.max_needed_preciousness <= 0) { |
557 | 2498 | throw wexception("AI: Max presciousness must not be <= 0 for building: %s", | 2519 | throw wexception("AI: Max preciousness must not be <= 0 for building: %s", |
558 | 2499 | bo.desc->name().c_str()); | 2520 | bo.desc->name().c_str()); |
559 | 2500 | } | 2521 | } |
560 | 2501 | } else if (bo.new_building == BuildingNecessity::kForbidden) { | ||
561 | 2502 | bo.max_needed_preciousness = 0; | ||
562 | 2503 | } else { | 2522 | } else { |
563 | 2504 | // For other situations we make sure max_needed_preciousness is zero | 2523 | // For other situations we make sure max_needed_preciousness is zero |
564 | 2505 | |||
565 | 2506 | assert(bo.max_needed_preciousness == 0); | 2524 | assert(bo.max_needed_preciousness == 0); |
566 | 2507 | } | 2525 | } |
567 | 2508 | 2526 | ||
568 | @@ -2965,7 +2983,6 @@ | |||
569 | 2965 | } | 2983 | } |
570 | 2966 | 2984 | ||
571 | 2967 | } else if (bo.is(BuildingAttribute::kRecruitment)) { | 2985 | } else if (bo.is(BuildingAttribute::kRecruitment)) { |
572 | 2968 | bo.max_needed_preciousness = 2; | ||
573 | 2969 | prio += bo.primary_priority; | 2986 | prio += bo.primary_priority; |
574 | 2970 | prio -= bf->unowned_land_nearby * 2; | 2987 | prio -= bf->unowned_land_nearby * 2; |
575 | 2971 | prio -= (bf->enemy_nearby) * 100; | 2988 | prio -= (bf->enemy_nearby) * 100; |
576 | @@ -4487,7 +4504,7 @@ | |||
577 | 4487 | gametime && | 4504 | gametime && |
578 | 4488 | site.site->can_start_working() && | 4505 | site.site->can_start_working() && |
579 | 4489 | get_stocklevel(*site.bo, gametime) > | 4506 | get_stocklevel(*site.bo, gametime) > |
581 | 4490 | (std::abs(management_data.get_military_number_at(168)) / 5)) { | 4507 | static_cast<unsigned int>((std::abs(management_data.get_military_number_at(168)) / 5))) { |
582 | 4491 | 4508 | ||
583 | 4492 | if (connected_to_wh) { | 4509 | if (connected_to_wh) { |
584 | 4493 | game().send_player_dismantle(*site.site); | 4510 | game().send_player_dismantle(*site.site); |
585 | @@ -4980,42 +4997,41 @@ | |||
586 | 4980 | // Let deal with productionsites now | 4997 | // Let deal with productionsites now |
587 | 4981 | // First we iterate over outputs of building, count warehoused stock | 4998 | // First we iterate over outputs of building, count warehoused stock |
588 | 4982 | // and deciding if we have enough on stock (in warehouses) | 4999 | // and deciding if we have enough on stock (in warehouses) |
625 | 4983 | bo.max_preciousness = 0; | 5000 | |
626 | 4984 | bo.max_needed_preciousness = 0; | 5001 | // Calulate preciousness |
627 | 4985 | 5002 | bo.max_preciousness = bo.initial_preciousness; | |
628 | 4986 | if (!bo.is(BuildingAttribute::kBarracks)) { // barracks are now excluded from calculation | 5003 | bo.max_needed_preciousness = bo.initial_preciousness; |
629 | 4987 | // preciousness is assigned below in this fuction | 5004 | for (uint32_t m = 0; m < bo.outputs.size(); ++m) { |
630 | 4988 | for (uint32_t m = 0; m < bo.outputs.size(); ++m) { | 5005 | DescriptionIndex wt(static_cast<size_t>(bo.outputs.at(m))); |
631 | 4989 | DescriptionIndex wt(static_cast<size_t>(bo.outputs.at(m))); | 5006 | |
632 | 4990 | 5007 | uint16_t target = tribe_->get_ware_descr(wt)->default_target_quantity(tribe_->name()); | |
633 | 4991 | uint16_t target = tribe_->get_ware_descr(wt)->default_target_quantity(tribe_->name()); | 5008 | if (target == Widelands::kInvalidWare) { |
634 | 4992 | if (target == Widelands::kInvalidWare) { | 5009 | target = kTargetQuantCap; |
635 | 4993 | target = kTargetQuantCap; | 5010 | } |
636 | 4994 | } | 5011 | target /= 3; |
637 | 4995 | target /= 3; | 5012 | |
638 | 4996 | 5013 | // at least 1 | |
639 | 4997 | // at least 1 | 5014 | target = std::max<uint16_t>(target, 1); |
640 | 4998 | target = std::max<uint16_t>(target, 1); | 5015 | |
641 | 4999 | 5016 | // it seems there are wares with 0 preciousness (no entry in init files?), but we need | |
642 | 5000 | // it seems there are wares with 0 preciousness (no entry in init files?), but we need | 5017 | // positive value here. |
643 | 5001 | // positive value here. | 5018 | // TODO(GunChleoc): Since we require in Tribes::postload() that this is set for all wares used by a tribe, something seems to be wrong here. It should always be > 0. |
644 | 5002 | const uint16_t preciousness = | 5019 | const uint16_t preciousness = |
645 | 5003 | std::max<uint16_t>(wares.at(bo.outputs.at(m)).preciousness, 1); | 5020 | std::max<uint16_t>(wares.at(bo.outputs.at(m)).preciousness, 1); |
646 | 5004 | 5021 | ||
647 | 5005 | if (calculate_stocklevel(wt) < target || | 5022 | if (calculate_stocklevel(wt) < target || |
648 | 5006 | site_needed_for_economy == BasicEconomyBuildingStatus::kEncouraged) { | 5023 | site_needed_for_economy == BasicEconomyBuildingStatus::kEncouraged) { |
649 | 5007 | if (bo.max_needed_preciousness < preciousness) { | 5024 | if (bo.max_needed_preciousness < preciousness) { |
650 | 5008 | bo.max_needed_preciousness = preciousness; | 5025 | bo.max_needed_preciousness = preciousness; |
651 | 5009 | } | 5026 | } |
652 | 5010 | if (site_needed_for_economy == BasicEconomyBuildingStatus::kEncouraged) { | 5027 | if (site_needed_for_economy == BasicEconomyBuildingStatus::kEncouraged) { |
653 | 5011 | bo.max_needed_preciousness += | 5028 | bo.max_needed_preciousness += |
654 | 5012 | std::abs(management_data.get_military_number_at(144)) / 10; | 5029 | std::abs(management_data.get_military_number_at(144)) / 10; |
655 | 5013 | } | 5030 | } |
656 | 5014 | } | 5031 | } |
657 | 5015 | 5032 | ||
658 | 5016 | if (bo.max_preciousness < preciousness) { | 5033 | if (bo.max_preciousness < preciousness) { |
659 | 5017 | bo.max_preciousness = preciousness; | 5034 | bo.max_preciousness = preciousness; |
624 | 5018 | } | ||
660 | 5019 | } | 5035 | } |
661 | 5020 | } | 5036 | } |
662 | 5021 | 5037 | ||
663 | @@ -5102,12 +5118,7 @@ | |||
664 | 5102 | } | 5118 | } |
665 | 5103 | 5119 | ||
666 | 5104 | if (bo.forced_after < gametime && bo.total_count() == 0 && !has_substitution_building) { | 5120 | if (bo.forced_after < gametime && bo.total_count() == 0 && !has_substitution_building) { |
673 | 5105 | if (!bo.is(BuildingAttribute::kBarracks)) { | 5121 | bo.max_needed_preciousness = bo.max_preciousness; |
668 | 5106 | bo.max_needed_preciousness = bo.max_preciousness; | ||
669 | 5107 | } else { | ||
670 | 5108 | // barracks has no genuine preciousness as of now | ||
671 | 5109 | bo.max_needed_preciousness = 5; | ||
672 | 5110 | } | ||
674 | 5111 | return BuildingNecessity::kForced; | 5122 | return BuildingNecessity::kForced; |
675 | 5112 | } else if (bo.prohibited_till > gametime) { | 5123 | } else if (bo.prohibited_till > gametime) { |
676 | 5113 | return BuildingNecessity::kForbidden; | 5124 | return BuildingNecessity::kForbidden; |
677 | @@ -5417,7 +5428,8 @@ | |||
678 | 5417 | bo.max_preciousness = bo.max_needed_preciousness; | 5428 | bo.max_preciousness = bo.max_needed_preciousness; |
679 | 5418 | return BuildingNecessity::kNeeded; | 5429 | return BuildingNecessity::kNeeded; |
680 | 5419 | } else { | 5430 | } else { |
682 | 5420 | assert(bo.max_needed_preciousness == 0); | 5431 | bo.max_needed_preciousness = 0; |
683 | 5432 | bo.max_preciousness = 0; | ||
684 | 5421 | return BuildingNecessity::kForbidden; | 5433 | return BuildingNecessity::kForbidden; |
685 | 5422 | } | 5434 | } |
686 | 5423 | } else if (bo.type == BuildingObserver::Type::kMine) { | 5435 | } else if (bo.type == BuildingObserver::Type::kMine) { |
687 | @@ -5829,7 +5841,7 @@ | |||
688 | 5829 | return BuildingNecessity::kNeeded; | 5841 | return BuildingNecessity::kNeeded; |
689 | 5830 | } else if (bo.inputs.size() == 1 && | 5842 | } else if (bo.inputs.size() == 1 && |
690 | 5831 | calculate_stocklevel(static_cast<size_t>(bo.inputs.at(0))) > | 5843 | calculate_stocklevel(static_cast<size_t>(bo.inputs.at(0))) > |
692 | 5832 | std::abs(management_data.get_military_number_at(171))) { | 5844 | static_cast<unsigned int>(std::abs(management_data.get_military_number_at(171)))) { |
693 | 5833 | return BuildingNecessity::kNeeded; | 5845 | return BuildingNecessity::kNeeded; |
694 | 5834 | } else { | 5846 | } else { |
695 | 5835 | return BuildingNecessity::kNotNeeded; | 5847 | return BuildingNecessity::kNotNeeded; |
696 | 5836 | 5848 | ||
697 | === modified file 'src/logic/map_objects/tribes/tribe_descr.cc' | |||
698 | --- src/logic/map_objects/tribes/tribe_descr.cc 2019-05-04 10:47:44 +0000 | |||
699 | +++ src/logic/map_objects/tribes/tribe_descr.cc 2019-05-19 16:18:33 +0000 | |||
700 | @@ -199,7 +199,6 @@ | |||
701 | 199 | } | 199 | } |
702 | 200 | 200 | ||
703 | 201 | port_ = add_special_building(table.get_string("port")); | 201 | port_ = add_special_building(table.get_string("port")); |
704 | 202 | barracks_ = add_special_building(table.get_string("barracks")); | ||
705 | 203 | 202 | ||
706 | 204 | ironore_ = add_special_ware(table.get_string("ironore")); | 203 | ironore_ = add_special_ware(table.get_string("ironore")); |
707 | 205 | rawlog_ = add_special_ware(table.get_string("rawlog")); | 204 | rawlog_ = add_special_ware(table.get_string("rawlog")); |
708 | @@ -328,10 +327,6 @@ | |||
709 | 328 | assert(tribes_.building_exists(port_)); | 327 | assert(tribes_.building_exists(port_)); |
710 | 329 | return port_; | 328 | return port_; |
711 | 330 | } | 329 | } |
712 | 331 | DescriptionIndex TribeDescr::barracks() const { | ||
713 | 332 | assert(tribes_.building_exists(barracks_)); | ||
714 | 333 | return barracks_; | ||
715 | 334 | } | ||
716 | 335 | DescriptionIndex TribeDescr::ironore() const { | 330 | DescriptionIndex TribeDescr::ironore() const { |
717 | 336 | assert(tribes_.ware_exists(ironore_)); | 331 | assert(tribes_.ware_exists(ironore_)); |
718 | 337 | return ironore_; | 332 | return ironore_; |
719 | 338 | 333 | ||
720 | === modified file 'src/logic/map_objects/tribes/tribe_descr.h' | |||
721 | --- src/logic/map_objects/tribes/tribe_descr.h 2019-03-01 04:19:53 +0000 | |||
722 | +++ src/logic/map_objects/tribes/tribe_descr.h 2019-05-19 16:18:33 +0000 | |||
723 | @@ -116,7 +116,6 @@ | |||
724 | 116 | DescriptionIndex soldier() const; | 116 | DescriptionIndex soldier() const; |
725 | 117 | DescriptionIndex ship() const; | 117 | DescriptionIndex ship() const; |
726 | 118 | DescriptionIndex port() const; | 118 | DescriptionIndex port() const; |
727 | 119 | DescriptionIndex barracks() const; | ||
728 | 120 | DescriptionIndex ironore() const; | 119 | DescriptionIndex ironore() const; |
729 | 121 | DescriptionIndex rawlog() const; | 120 | DescriptionIndex rawlog() const; |
730 | 122 | DescriptionIndex refinedlog() const; | 121 | DescriptionIndex refinedlog() const; |
731 | @@ -206,7 +205,6 @@ | |||
732 | 206 | DescriptionIndex soldier_; // The soldier that this tribe uses | 205 | DescriptionIndex soldier_; // The soldier that this tribe uses |
733 | 207 | DescriptionIndex ship_; // The ship that this tribe uses | 206 | DescriptionIndex ship_; // The ship that this tribe uses |
734 | 208 | DescriptionIndex port_; // The port that this tribe uses | 207 | DescriptionIndex port_; // The port that this tribe uses |
735 | 209 | DescriptionIndex barracks_; // The barracks to create soldiers | ||
736 | 210 | DescriptionIndex ironore_; // Iron ore | 208 | DescriptionIndex ironore_; // Iron ore |
737 | 211 | DescriptionIndex rawlog_; // Simple log | 209 | DescriptionIndex rawlog_; // Simple log |
738 | 212 | DescriptionIndex refinedlog_; // Refined log, e.g. wood or blackwood | 210 | DescriptionIndex refinedlog_; // Refined log, e.g. wood or blackwood |
739 | 213 | 211 | ||
740 | === modified file 'src/logic/map_objects/tribes/tribes.cc' | |||
741 | --- src/logic/map_objects/tribes/tribes.cc 2019-05-16 09:15:03 +0000 | |||
742 | +++ src/logic/map_objects/tribes/tribes.cc 2019-05-19 16:18:33 +0000 | |||
743 | @@ -357,7 +357,7 @@ | |||
744 | 357 | 357 | ||
745 | 358 | // Verify that the preciousness has been set for all of the tribe's wares | 358 | // Verify that the preciousness has been set for all of the tribe's wares |
746 | 359 | for (const DescriptionIndex wi : tribe_descr->wares()) { | 359 | for (const DescriptionIndex wi : tribe_descr->wares()) { |
748 | 360 | if (tribe_descr->get_ware_descr(wi)->preciousness(tribe_descr->name()) == kInvalidWare) { | 360 | if (tribe_descr->get_ware_descr(wi)->ai_hints().preciousness(tribe_descr->name()) == kInvalidWare) { |
749 | 361 | throw GameDataError("The ware '%s' needs to define a preciousness for tribe '%s'", | 361 | throw GameDataError("The ware '%s' needs to define a preciousness for tribe '%s'", |
750 | 362 | tribe_descr->get_ware_descr(wi)->name().c_str(), | 362 | tribe_descr->get_ware_descr(wi)->name().c_str(), |
751 | 363 | tribe_descr->name().c_str()); | 363 | tribe_descr->name().c_str()); |
752 | 364 | 364 | ||
753 | === modified file 'src/logic/map_objects/tribes/ware_descr.cc' | |||
754 | --- src/logic/map_objects/tribes/ware_descr.cc 2019-02-23 11:00:49 +0000 | |||
755 | +++ src/logic/map_objects/tribes/ware_descr.cc 2019-05-19 16:18:33 +0000 | |||
756 | @@ -35,7 +35,8 @@ | |||
757 | 35 | * /data/tribes/wares/armor/init.lua | 35 | * /data/tribes/wares/armor/init.lua |
758 | 36 | */ | 36 | */ |
759 | 37 | WareDescr::WareDescr(const std::string& init_descname, const LuaTable& table) | 37 | WareDescr::WareDescr(const std::string& init_descname, const LuaTable& table) |
761 | 38 | : MapObjectDescr(MapObjectType::WARE, table.get_string("name"), init_descname, table) { | 38 | : MapObjectDescr(MapObjectType::WARE, table.get_string("name"), init_descname, table), |
762 | 39 | ai_hints_(new WareHints(*table.get_table("preciousness"))) { | ||
763 | 39 | if (helptext_script().empty()) { | 40 | if (helptext_script().empty()) { |
764 | 40 | throw GameDataError("Ware %s has no helptext script", name().c_str()); | 41 | throw GameDataError("Ware %s has no helptext script", name().c_str()); |
765 | 41 | } | 42 | } |
766 | @@ -51,19 +52,9 @@ | |||
767 | 51 | for (const std::string& key : items_table->keys<std::string>()) { | 52 | for (const std::string& key : items_table->keys<std::string>()) { |
768 | 52 | default_target_quantities_.emplace(key, items_table->get_int(key)); | 53 | default_target_quantities_.emplace(key, items_table->get_int(key)); |
769 | 53 | } | 54 | } |
783 | 54 | 55 | } | |
784 | 55 | items_table = table.get_table("preciousness"); | 56 | |
785 | 56 | for (const std::string& key : items_table->keys<std::string>()) { | 57 | |
773 | 57 | preciousnesses_.emplace(key, items_table->get_int(key)); | ||
774 | 58 | } | ||
775 | 59 | } | ||
776 | 60 | |||
777 | 61 | int WareDescr::preciousness(const std::string& tribename) const { | ||
778 | 62 | if (preciousnesses_.count(tribename) > 0) { | ||
779 | 63 | return preciousnesses_.at(tribename); | ||
780 | 64 | } | ||
781 | 65 | return kInvalidWare; | ||
782 | 66 | } | ||
786 | 67 | 58 | ||
787 | 68 | DescriptionIndex WareDescr::default_target_quantity(const std::string& tribename) const { | 59 | DescriptionIndex WareDescr::default_target_quantity(const std::string& tribename) const { |
788 | 69 | if (default_target_quantities_.count(tribename) > 0) { | 60 | if (default_target_quantities_.count(tribename) > 0) { |
789 | 70 | 61 | ||
790 | === modified file 'src/logic/map_objects/tribes/ware_descr.h' | |||
791 | --- src/logic/map_objects/tribes/ware_descr.h 2019-02-27 19:00:36 +0000 | |||
792 | +++ src/logic/map_objects/tribes/ware_descr.h 2019-05-19 16:18:33 +0000 | |||
793 | @@ -21,12 +21,14 @@ | |||
794 | 21 | #define WL_LOGIC_MAP_OBJECTS_TRIBES_WARE_DESCR_H | 21 | #define WL_LOGIC_MAP_OBJECTS_TRIBES_WARE_DESCR_H |
795 | 22 | 22 | ||
796 | 23 | #include <cstring> | 23 | #include <cstring> |
797 | 24 | #include <memory> | ||
798 | 24 | #include <string> | 25 | #include <string> |
799 | 25 | #include <unordered_map> | 26 | #include <unordered_map> |
800 | 26 | 27 | ||
801 | 27 | #include <stdint.h> | 28 | #include <stdint.h> |
802 | 28 | 29 | ||
803 | 29 | #include "base/macros.h" | 30 | #include "base/macros.h" |
804 | 31 | #include "ai/ai_hints.h" | ||
805 | 30 | #include "logic/map_objects/map_object.h" | 32 | #include "logic/map_objects/map_object.h" |
806 | 31 | #include "scripting/lua_table.h" | 33 | #include "scripting/lua_table.h" |
807 | 32 | 34 | ||
808 | @@ -52,9 +54,10 @@ | |||
809 | 52 | ~WareDescr() override { | 54 | ~WareDescr() override { |
810 | 53 | } | 55 | } |
811 | 54 | 56 | ||
815 | 55 | /// Returns the preciousness of the ware, or kInvalidWare if the tribe doesn't use the ware. | 57 | /// AI hints for this ware type |
816 | 56 | /// It is used by the computer player. | 58 | const WareHints& ai_hints() const { |
817 | 57 | int preciousness(const std::string& tribename) const; | 59 | return *ai_hints_; |
818 | 60 | } | ||
819 | 58 | 61 | ||
820 | 59 | /// How much of the ware type an economy should store in warehouses. | 62 | /// How much of the ware type an economy should store in warehouses. |
821 | 60 | /// The special value kInvalidWare means that the target quantity of this ware type will never be | 63 | /// The special value kInvalidWare means that the target quantity of this ware type will never be |
822 | @@ -82,8 +85,9 @@ | |||
823 | 82 | private: | 85 | private: |
824 | 83 | // tribename, quantity. No default. | 86 | // tribename, quantity. No default. |
825 | 84 | std::unordered_map<std::string, int> default_target_quantities_; | 87 | std::unordered_map<std::string, int> default_target_quantities_; |
828 | 85 | // tribename, preciousness. No default. | 88 | |
829 | 86 | std::unordered_map<std::string, int> preciousnesses_; | 89 | // Hints for the AI |
830 | 90 | std::unique_ptr<WareHints> ai_hints_; | ||
831 | 87 | 91 | ||
832 | 88 | std::set<DescriptionIndex> consumers_; // Buildings that consume this ware | 92 | std::set<DescriptionIndex> consumers_; // Buildings that consume this ware |
833 | 89 | std::set<DescriptionIndex> producers_; // Buildings that produce this ware | 93 | std::set<DescriptionIndex> producers_; // Buildings that produce this ware |
834 | 90 | 94 | ||
835 | === modified file 'src/logic/map_objects/tribes/worker_descr.cc' | |||
836 | --- src/logic/map_objects/tribes/worker_descr.cc 2019-05-05 14:05:07 +0000 | |||
837 | +++ src/logic/map_objects/tribes/worker_descr.cc 2019-05-19 16:18:33 +0000 | |||
838 | @@ -52,6 +52,7 @@ | |||
839 | 52 | becomes_(table.has_key("experience") ? tribes.safe_worker_index(table.get_string("becomes")) : | 52 | becomes_(table.has_key("experience") ? tribes.safe_worker_index(table.get_string("becomes")) : |
840 | 53 | INVALID_INDEX), | 53 | INVALID_INDEX), |
841 | 54 | needed_experience_(table.has_key("becomes") ? table.get_int("experience") : INVALID_INDEX), | 54 | needed_experience_(table.has_key("becomes") ? table.get_int("experience") : INVALID_INDEX), |
842 | 55 | ai_hints_(table.has_key("aihints") ? new WorkerHints(*table.get_table("aihints")) : nullptr), | ||
843 | 55 | tribes_(tribes) { | 56 | tribes_(tribes) { |
844 | 56 | if (helptext_script().empty()) { | 57 | if (helptext_script().empty()) { |
845 | 57 | throw GameDataError("Worker %s has no helptext script", name().c_str()); | 58 | throw GameDataError("Worker %s has no helptext script", name().c_str()); |
846 | 58 | 59 | ||
847 | === modified file 'src/logic/map_objects/tribes/worker_descr.h' | |||
848 | --- src/logic/map_objects/tribes/worker_descr.h 2019-05-11 13:48:12 +0000 | |||
849 | +++ src/logic/map_objects/tribes/worker_descr.h 2019-05-19 16:18:33 +0000 | |||
850 | @@ -22,6 +22,7 @@ | |||
851 | 22 | 22 | ||
852 | 23 | #include <memory> | 23 | #include <memory> |
853 | 24 | 24 | ||
854 | 25 | #include "ai/ai_hints.h" | ||
855 | 25 | #include "base/macros.h" | 26 | #include "base/macros.h" |
856 | 26 | #include "graphic/diranimations.h" | 27 | #include "graphic/diranimations.h" |
857 | 27 | #include "logic/map_objects/bob.h" | 28 | #include "logic/map_objects/bob.h" |
858 | @@ -116,6 +117,11 @@ | |||
859 | 116 | return programs_; | 117 | return programs_; |
860 | 117 | } | 118 | } |
861 | 118 | 119 | ||
862 | 120 | /// AI hints for this worker type. Can be nullptr. | ||
863 | 121 | const WorkerHints* ai_hints() const { | ||
864 | 122 | return ai_hints_.get(); | ||
865 | 123 | } | ||
866 | 124 | |||
867 | 119 | protected: | 125 | protected: |
868 | 120 | Programs programs_; | 126 | Programs programs_; |
869 | 121 | 127 | ||
870 | @@ -145,6 +151,9 @@ | |||
871 | 145 | std::set<DescriptionIndex> employers_; | 151 | std::set<DescriptionIndex> employers_; |
872 | 146 | 152 | ||
873 | 147 | private: | 153 | private: |
874 | 154 | // Hints for the AI | ||
875 | 155 | std::unique_ptr<WorkerHints> ai_hints_; | ||
876 | 156 | |||
877 | 148 | const Tribes& tribes_; | 157 | const Tribes& tribes_; |
878 | 149 | DISALLOW_COPY_AND_ASSIGN(WorkerDescr); | 158 | DISALLOW_COPY_AND_ASSIGN(WorkerDescr); |
879 | 150 | }; | 159 | }; |
See my comments below
BTW I am doing some training, I hope this will not interfere. Once it is merged, I will re-train too..