Merge lp:~widelands-dev/widelands/bug-1675179-lua-economy into lp:widelands
- bug-1675179-lua-economy
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 8330 | ||||
Proposed branch: | lp:~widelands-dev/widelands/bug-1675179-lua-economy | ||||
Merge into: | lp:widelands | ||||
Diff against target: |
321 lines (+248/-1) 4 files modified
src/scripting/lua_map.cc (+145/-1) src/scripting/lua_map.h (+50/-0) test/maps/lua_testsuite.wmf/scripting/geconomy.lua (+52/-0) test/maps/lua_testsuite.wmf/scripting/init.lua (+1/-0) |
||||
To merge this branch: | bzr merge lp:~widelands-dev/widelands/bug-1675179-lua-economy | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Klaus Halfmann | compile, review, test | Approve | |
Review via email: mp+321008@code.launchpad.net |
Commit message
Added a new object LuaEconomy to LuaMap.
Description of the change
This is for the Empire scenario scripting. The new functions aren't used anywhere in the game yet, so the unit test will have to cover the testing for now.
Klaus Halfmann (klaus-halfmann) wrote : | # |
Klaus Halfmann (klaus-halfmann) wrote : | # |
Where does a lua programme "find" that flag to fetch the economy from?
would it not be easier to get some "default" economy for the headquarter
(like you do in that test :-). Or some warehouses?
Can we have a test for a bare flag? Is there an ecomony for every
disconnected flag?
For the tutotrial this may be enough, but is this stable enoough
for general usage. Can wee add some test where the economies change?
See my inline comments, too
will compile this and let the test run.
GunChleoc (gunchleoc) wrote : | # |
Regarding your comments: The economy number is the array index of the economies owned by a player. So, we need both the player number and he economy index to identify it.
When an economy is merged with another economy or its last flag deleted, the vector gets reshuffled. I don't expect it to be a problem with the persistence code though, because the game is paused while its being saved, so economies can't disappear on us then.
Outside of saveloading, we reference the Economy object itself and not the economy & player numbers, so the worst thing that it can do to us is to become nil. Becoming nil can happen to any map object though, so this is something that a scenario Lua script will need to test for when necessary.
> Where does a lua programme "find" that flag to fetch the economy from?
It doesn't. Whoever writes a scenario will need to tell it which flag to use.
> would it not be easier to get some "default" economy for the headquarter
(like you do in that test :-). Or some warehouses?
No, because a scenario author might need to be able to access all economies, not just the "default" one. Also, if the headquarters gets conquered and the player still has 2 other economies with warehouses in them, which one will become the "default" economy?
> Can we have a test for a bare flag? Is there an ecomony for every
disconnected flag?
A disconnected flag has an economy that consists of that flag only. Unless you connect it to a warehouse, it will be an economy without a warehouse, but it's still an economy.
Klaus Halfmann (klaus-halfmann) wrote : | # |
Mhh, ./regression_
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 2064. State: passed. Details: https:/
Appveyor build 1899. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
Why do you think that?
It is definitely executed when I run
./widelands --scenario=
because it blew up in my face quite a few times until I fixed everything up. And it's registered in the same init.lua that ./regression_
From Travis:
test/
Running Widelands ... done.
ok
If you want to make sure that it's run, add a nonsense assert to make it fail. I just did that and it definitely fails then, so it is run.
Klaus Halfmann (klaus-halfmann) wrote : | # |
OK, checke that testsuite and foud how it is used.
updated again and run the tests agin, all fine.
Sorry fo taking so long.
@bunnybot merge
GunChleoc (gunchleoc) wrote : | # |
Don't apologize and thanks for reviewing! :)
Preview Diff
1 | === modified file 'src/scripting/lua_map.cc' |
2 | --- src/scripting/lua_map.cc 2017-01-30 14:40:12 +0000 |
3 | +++ src/scripting/lua_map.cc 2017-03-29 16:02:45 +0000 |
4 | @@ -3342,6 +3342,134 @@ |
5 | */ |
6 | |
7 | /* RST |
8 | +Economy |
9 | +------- |
10 | +.. class:: LuaEconomy |
11 | + |
12 | + Provides access to an economy. A player can have multiple economies; |
13 | + you can get an economy from a :class:`Flag`. |
14 | +*/ |
15 | +const char LuaEconomy::className[] = "Economy"; |
16 | +const MethodType<LuaEconomy> LuaEconomy::Methods[] = { |
17 | + METHOD(LuaEconomy, ware_target_quantity), |
18 | + METHOD(LuaEconomy, worker_target_quantity), |
19 | + METHOD(LuaEconomy, set_ware_target_quantity), |
20 | + METHOD(LuaEconomy, set_worker_target_quantity), |
21 | + {nullptr, nullptr}, |
22 | +}; |
23 | +const PropertyType<LuaEconomy> LuaEconomy::Properties[] = { |
24 | + {nullptr, nullptr, nullptr}, |
25 | +}; |
26 | + |
27 | +void LuaEconomy::__persist(lua_State* L) { |
28 | + const Widelands::Economy* economy = get(); |
29 | + const Widelands::Player& player = economy->owner(); |
30 | + PERS_UINT32("player", player.player_number()); |
31 | + PERS_UINT32("economy", player.get_economy_number(economy)); |
32 | +} |
33 | + |
34 | +void LuaEconomy::__unpersist(lua_State* L) { |
35 | + Widelands::PlayerNumber player_number; |
36 | + size_t economy_number; |
37 | + UNPERS_UINT32("player", player_number); |
38 | + UNPERS_UINT32("economy", economy_number); |
39 | + const Widelands::Player& player = get_egbase(L).player(player_number); |
40 | + set_economy_pointer(player.get_economy_by_number(economy_number)); |
41 | +} |
42 | + |
43 | +/* RST |
44 | + .. method:: ware_target_quantity(warename) |
45 | + |
46 | + Returns the amount of the given ware that should be kept in stock for this economy. |
47 | + |
48 | + :arg warename: the name of the ware. |
49 | + :type warename: :class:`string` |
50 | +*/ |
51 | +int LuaEconomy::ware_target_quantity(lua_State* L) { |
52 | + const std::string warename = luaL_checkstring(L, 2); |
53 | + const Widelands::DescriptionIndex index = get_egbase(L).tribes().ware_index(warename); |
54 | + if (get_egbase(L).tribes().ware_exists(index)) { |
55 | + const Widelands::Economy::TargetQuantity& quantity = get()->ware_target_quantity(index); |
56 | + lua_pushinteger(L, quantity.permanent); |
57 | + } else { |
58 | + report_error(L, "There is no ware '%s'.", warename.c_str()); |
59 | + } |
60 | + return 1; |
61 | +} |
62 | + |
63 | +/* RST |
64 | + .. method:: worker_target_quantity(workername) |
65 | + |
66 | + Returns the amount of the given worker that should be kept in stock for this economy. |
67 | + |
68 | + :arg workername: the name of the worker. |
69 | + :type workername: :class:`string` |
70 | +*/ |
71 | +int LuaEconomy::worker_target_quantity(lua_State* L) { |
72 | + const std::string workername = luaL_checkstring(L, 2); |
73 | + const Widelands::DescriptionIndex index = get_egbase(L).tribes().worker_index(workername); |
74 | + if (get_egbase(L).tribes().worker_exists(index)) { |
75 | + const Widelands::Economy::TargetQuantity& quantity = get()->worker_target_quantity(index); |
76 | + lua_pushinteger(L, quantity.permanent); |
77 | + } else { |
78 | + report_error(L, "There is no worker '%s'.", workername.c_str()); |
79 | + } |
80 | + return 1; |
81 | +} |
82 | + |
83 | +/* RST |
84 | + .. method:: set_ware_target_quantity(warename) |
85 | + |
86 | + Sets the amount of the given ware type that should be kept in stock for this economy. |
87 | + |
88 | + :arg warename: the name of the ware type. |
89 | + :type warename: :class:`string` |
90 | + |
91 | + :arg amount: the new target amount for the ware. Needs to be >= 0. |
92 | + :type amount: :class:`integer` |
93 | +*/ |
94 | +int LuaEconomy::set_ware_target_quantity(lua_State* L) { |
95 | + const std::string warename = luaL_checkstring(L, 2); |
96 | + const Widelands::DescriptionIndex index = get_egbase(L).tribes().ware_index(warename); |
97 | + if (get_egbase(L).tribes().ware_exists(index)) { |
98 | + const int quantity = luaL_checkinteger(L, 3); |
99 | + if (quantity < 0) { |
100 | + report_error(L, "Target ware quantity needs to be >= 0 but was '%d'.", quantity); |
101 | + } |
102 | + get()->set_ware_target_quantity(index, quantity, get_egbase(L).get_gametime()); |
103 | + } else { |
104 | + report_error(L, "There is no ware '%s'.", warename.c_str()); |
105 | + } |
106 | + return 1; |
107 | +} |
108 | + |
109 | +/* RST |
110 | + .. method:: set_worker_target_quantity(workername) |
111 | + |
112 | + Sets the amount of the given worker type that should be kept in stock for this economy. |
113 | + |
114 | + :arg workername: the name of the worker type. |
115 | + :type workername: :class:`string` |
116 | + |
117 | + :arg amount: the new target amount for the worker. Needs to be >= 0. |
118 | + :type amount: :class:`integer` |
119 | +*/ |
120 | +int LuaEconomy::set_worker_target_quantity(lua_State* L) { |
121 | + const std::string workername = luaL_checkstring(L, 2); |
122 | + const Widelands::DescriptionIndex index = get_egbase(L).tribes().worker_index(workername); |
123 | + if (get_egbase(L).tribes().worker_exists(index)) { |
124 | + const int quantity = luaL_checkinteger(L, 3); |
125 | + if (quantity < 0) { |
126 | + report_error(L, "Target worker quantity needs to be >= 0 but was '%d'.", quantity); |
127 | + } |
128 | + get()->set_worker_target_quantity(index, quantity, get_egbase(L).get_gametime()); |
129 | + } else { |
130 | + report_error(L, "There is no worker '%s'.", workername.c_str()); |
131 | + } |
132 | + return 1; |
133 | +} |
134 | + |
135 | +/* RST |
136 | MapObject |
137 | --------- |
138 | |
139 | @@ -3682,7 +3810,10 @@ |
140 | METHOD(LuaFlag, set_wares), METHOD(LuaFlag, get_wares), {nullptr, nullptr}, |
141 | }; |
142 | const PropertyType<LuaFlag> LuaFlag::Properties[] = { |
143 | - PROP_RO(LuaFlag, roads), PROP_RO(LuaFlag, building), {nullptr, nullptr, nullptr}, |
144 | + PROP_RO(LuaFlag, economy), |
145 | + PROP_RO(LuaFlag, roads), |
146 | + PROP_RO(LuaFlag, building), |
147 | + {nullptr, nullptr, nullptr}, |
148 | }; |
149 | |
150 | /* |
151 | @@ -3691,6 +3822,18 @@ |
152 | ========================================================== |
153 | */ |
154 | /* RST |
155 | + .. attribute:: economy |
156 | + |
157 | + (RO) Returns the economy that this flag belongs to. |
158 | + |
159 | + :returns: The :class:`Economy` associated with the flag. |
160 | +*/ |
161 | +int LuaFlag::get_economy(lua_State* L) { |
162 | + const Flag* f = get(L, get_egbase(L)); |
163 | + return to_lua<LuaEconomy>(L, new LuaEconomy(f->get_economy())); |
164 | +} |
165 | + |
166 | +/* RST |
167 | .. attribute:: roads |
168 | |
169 | (RO) Array of roads leading to the flag. Directions |
170 | @@ -6075,6 +6218,7 @@ |
171 | |
172 | register_class<LuaField>(L, "map"); |
173 | register_class<LuaPlayerSlot>(L, "map"); |
174 | + register_class<LuaEconomy>(L, "map"); |
175 | register_class<LuaMapObject>(L, "map"); |
176 | |
177 | register_class<LuaBob>(L, "map", true); |
178 | |
179 | === modified file 'src/scripting/lua_map.h' |
180 | --- src/scripting/lua_map.h 2017-01-25 18:55:59 +0000 |
181 | +++ src/scripting/lua_map.h 2017-03-29 16:02:45 +0000 |
182 | @@ -22,6 +22,7 @@ |
183 | |
184 | #include <set> |
185 | |
186 | +#include "economy/economy.h" |
187 | #include "economy/flag.h" |
188 | #include "economy/portdock.h" |
189 | #include "economy/road.h" |
190 | @@ -728,6 +729,54 @@ |
191 | const Widelands::TerrainDescription* terraindescr_; |
192 | }; |
193 | |
194 | +class LuaEconomy : public LuaMapModuleClass { |
195 | +public: |
196 | + LUNA_CLASS_HEAD(LuaEconomy); |
197 | + |
198 | + virtual ~LuaEconomy() { |
199 | + } |
200 | + |
201 | + LuaEconomy() : economy_(nullptr) { |
202 | + } |
203 | + LuaEconomy(Widelands::Economy* economy) : economy_(economy) { |
204 | + } |
205 | + LuaEconomy(lua_State* L) : economy_(nullptr) { |
206 | + report_error(L, "Cannot instantiate a 'LuaEconomy' directly!"); |
207 | + } |
208 | + |
209 | + void __persist(lua_State* L) override; |
210 | + void __unpersist(lua_State* L) override; |
211 | + |
212 | + /* |
213 | + * Properties |
214 | + */ |
215 | + |
216 | + /* |
217 | + * Lua methods |
218 | + */ |
219 | + int ware_target_quantity(lua_State*); |
220 | + int worker_target_quantity(lua_State*); |
221 | + int set_ware_target_quantity(lua_State*); |
222 | + int set_worker_target_quantity(lua_State*); |
223 | + |
224 | + /* |
225 | + * C methods |
226 | + */ |
227 | + |
228 | +protected: |
229 | + Widelands::Economy* get() const { |
230 | + assert(economy_ != nullptr); |
231 | + return economy_; |
232 | + } |
233 | + // For persistence. |
234 | + void set_economy_pointer(Widelands::Economy* pointer) { |
235 | + economy_ = pointer; |
236 | + } |
237 | + |
238 | +private: |
239 | + Widelands::Economy* economy_; |
240 | +}; |
241 | + |
242 | #define CASTED_GET(klass) \ |
243 | Widelands::klass* get(lua_State* L, Widelands::EditorGameBase& egbase) { \ |
244 | return static_cast<Widelands::klass*>(LuaMapObject::get(L, egbase, #klass)); \ |
245 | @@ -904,6 +953,7 @@ |
246 | /* |
247 | * Properties |
248 | */ |
249 | + int get_economy(lua_State* L); |
250 | int get_roads(lua_State* L); |
251 | int get_building(lua_State* L); |
252 | /* |
253 | |
254 | === added file 'test/maps/lua_testsuite.wmf/scripting/geconomy.lua' |
255 | --- test/maps/lua_testsuite.wmf/scripting/geconomy.lua 1970-01-01 00:00:00 +0000 |
256 | +++ test/maps/lua_testsuite.wmf/scripting/geconomy.lua 2017-03-29 16:02:45 +0000 |
257 | @@ -0,0 +1,52 @@ |
258 | +-- ================================================== |
259 | +-- Tests for Economy that are only useful in the Game |
260 | +-- ================================================== |
261 | + |
262 | +economy_tests = lunit.TestCase("Economy test") |
263 | +function economy_tests:test_instantiation_forbidden() |
264 | + assert_error("Cannot instantiate", function() |
265 | + wl.map.Economy() |
266 | + end) |
267 | +end |
268 | + |
269 | +function economy_tests:test_ware_target_quantity() |
270 | + |
271 | + -- Get the economy off a flag |
272 | + local sf = map:get_field(10, 10) |
273 | + local hq = player1:place_building("barbarians_headquarters", sf, false, true) |
274 | + local hq_flag = hq.flag |
275 | + local eco = hq_flag.economy |
276 | + |
277 | + -- Test illegal parameters |
278 | + assert_error("Nonexisting ware",function() eco:ware_target_quantity("foobar") end) |
279 | + assert_error("Quantity for nonexisting ware",function() eco:worker_target_quantity("foobar", 1) end) |
280 | + assert_error("Negative ware quantity",function() eco:set_ware_target_quantity("log", -1) end) |
281 | + |
282 | + -- Now set and confirm ware quantity |
283 | + quantity = eco:ware_target_quantity("log") |
284 | + quantity = quantity + 1 |
285 | + eco:set_ware_target_quantity("log", quantity) |
286 | + assert_equal(quantity, eco:ware_target_quantity("log")) |
287 | + |
288 | + hq_flag:remove() |
289 | +end |
290 | + |
291 | +function economy_tests:test_worker_target_quantity() |
292 | + -- Get the economy off a flag |
293 | + local sf = map:get_field(10, 10) |
294 | + local hq = player1:place_building("barbarians_headquarters", sf, false, true) |
295 | + local hq_flag = hq.flag |
296 | + local eco = hq_flag.economy |
297 | + |
298 | + -- Test illegal parameters |
299 | + assert_error("Nonexisting worker",function() eco:worker_target_quantity("foobar") end) |
300 | + assert_error("Quantity for nonexisting worker",function() eco:worker_target_quantity("foobar", 1) end) |
301 | + assert_error("Negative worker quantity",function() eco:set_worker_target_quantity("barbarians_soldier", -1) end) |
302 | + |
303 | + -- Now set and confirm worker quantity |
304 | + quantity = eco:worker_target_quantity("barbarians_soldier") |
305 | + quantity = quantity + 1 |
306 | + eco:set_worker_target_quantity("barbarians_soldier", quantity) |
307 | + assert_equal(quantity, eco:worker_target_quantity("barbarians_soldier")) |
308 | + hq_flag:remove() |
309 | +end |
310 | |
311 | === modified file 'test/maps/lua_testsuite.wmf/scripting/init.lua' |
312 | --- test/maps/lua_testsuite.wmf/scripting/init.lua 2016-04-12 07:35:33 +0000 |
313 | +++ test/maps/lua_testsuite.wmf/scripting/init.lua 2017-03-29 16:02:45 +0000 |
314 | @@ -40,6 +40,7 @@ |
315 | if not wl.editor then |
316 | include "map:scripting/game.lua" |
317 | |
318 | + include "map:scripting/geconomy.lua" |
319 | include "map:scripting/gplayer.lua" |
320 | include "map:scripting/gfield.lua" |
321 | include "map:scripting/gplr_access.lua" |
Id like to put in some comments, so we can do the review along them.
Please be patient ...