widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #09420
[Merge] lp:~widelands-dev/widelands/bug-1658317 into lp:widelands
TiborB has proposed merging lp:~widelands-dev/widelands/bug-1658317 into lp:widelands.
Requested reviews:
Widelands Developers (widelands-dev)
Related bugs:
Bug #1658317 in widelands: "Regression test suite is broken in trunk"
https://bugs.launchpad.net/widelands/+bug/1658317
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1658317/+merge/315302
I apologize for messing up the code, I added missing parts. However I see one regression test still fails: test_casern.lua
[string "world/init.lua"]:79: attempt to call a nil value (method 'new_editor_critter_category')
???
--
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1658317 into lp:widelands.
=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc 2017-01-21 16:14:52 +0000
+++ src/scripting/lua_map.cc 2017-01-21 20:09:14 +0000
@@ -769,7 +769,7 @@
// Very similar to above function, but expects numbers for every received ware/worker
RequestedWareWorker parse_wares_workers_counted(lua_State* L,
const TribeDescr& tribe,
- InputMap* ware_workers_list,
+ InputMap* ware_workers_list,
bool is_ware) {
RequestedWareWorker result = RequestedWareWorker::kUndefined;
int32_t nargs = lua_gettop(L);
@@ -785,14 +785,17 @@
if (tribe.ware_index(luaL_checkstring(L, 2)) == INVALID_INDEX) {
report_error(L, "Illegal ware %s", luaL_checkstring(L, 2));
}
- ware_workers_list->insert(
- std::make_pair(std::make_pair(tribe.ware_index(luaL_checkstring(L, 2)), Widelands::WareWorker::wwWARE), luaL_checkuint32(L, 3)));
+ ware_workers_list->insert(std::make_pair(
+ std::make_pair(tribe.ware_index(luaL_checkstring(L, 2)), Widelands::WareWorker::wwWARE),
+ luaL_checkuint32(L, 3)));
} else {
if (tribe.worker_index(luaL_checkstring(L, 2)) == INVALID_INDEX) {
report_error(L, "Illegal worker %s", luaL_checkstring(L, 2));
}
ware_workers_list->insert(
- std::make_pair(std::make_pair(tribe.worker_index(luaL_checkstring(L, 2)), Widelands::WareWorker::wwWORKER), luaL_checkuint32(L, 3)));
+ std::make_pair(std::make_pair(tribe.worker_index(luaL_checkstring(L, 2)),
+ Widelands::WareWorker::wwWORKER),
+ luaL_checkuint32(L, 3)));
}
} else {
result = RequestedWareWorker::kList;
@@ -812,10 +815,14 @@
if (is_ware) {
ware_workers_list->insert(
- std::make_pair(std::make_pair(tribe.ware_index(luaL_checkstring(L, -2)), Widelands::WareWorker::wwWARE), luaL_checkuint32(L, -1)));
+ std::make_pair(std::make_pair(tribe.ware_index(luaL_checkstring(L, -2)),
+ Widelands::WareWorker::wwWARE),
+ luaL_checkuint32(L, -1)));
} else {
ware_workers_list->insert(
- std::make_pair(std::make_pair(tribe.worker_index(luaL_checkstring(L, -2)), Widelands::WareWorker::wwWORKER), luaL_checkuint32(L, -1)));
+ std::make_pair(std::make_pair(tribe.worker_index(luaL_checkstring(L, -2)),
+ Widelands::WareWorker::wwWORKER),
+ luaL_checkuint32(L, -1)));
}
lua_pop(L, 1);
}
@@ -2101,7 +2108,7 @@
*/
const char LuaProductionSiteDescription::className[] = "ProductionSiteDescription";
const MethodType<LuaProductionSiteDescription> LuaProductionSiteDescription::Methods[] = {
- METHOD(LuaProductionSiteDescription, consumed_wares_workers),
+ METHOD(LuaProductionSiteDescription, consumed_wares_workers),
METHOD(LuaProductionSiteDescription, produced_wares),
METHOD(LuaProductionSiteDescription, recruited_workers),
{nullptr, nullptr},
@@ -3749,7 +3756,8 @@
for (const auto& ware : c_wares) {
// all wares currently on the flag without a setpoint should be removed
if (!setpoints.count(std::make_pair(ware.first, Widelands::WareWorker::wwWARE)))
- setpoints.insert(std::make_pair(std::make_pair(ware.first, Widelands::WareWorker::wwWARE), 0));
+ setpoints.insert(
+ std::make_pair(std::make_pair(ware.first, Widelands::WareWorker::wwWARE), 0));
nwares += ware.second;
}
@@ -4127,6 +4135,8 @@
METHOD(LuaWarehouse, get_workers),
METHOD(LuaWarehouse, set_soldiers),
METHOD(LuaWarehouse, get_soldiers),
+ METHOD(LuaWarehouse, set_warehouse_policies),
+ METHOD(LuaWarehouse, get_warehouse_policies),
METHOD(LuaWarehouse, start_expedition),
METHOD(LuaWarehouse, cancel_expedition),
{nullptr, nullptr},
@@ -4268,6 +4278,231 @@
return 0;
}
+// Transforms the given warehouse policy to a string which is used by the lua code
+inline void wh_policy_to_string(lua_State* L, Warehouse::StockPolicy p) {
+ switch (p) {
+ case Warehouse::StockPolicy::kNormal:
+ lua_pushstring(L, "normal");
+ break;
+ case Warehouse::StockPolicy::kPrefer:
+ lua_pushstring(L, "prefer");
+ break;
+ case Warehouse::StockPolicy::kDontStock:
+ lua_pushstring(L, "dontstock");
+ break;
+ case Warehouse::StockPolicy::kRemove:
+ lua_pushstring(L, "remove");
+ break;
+ }
+}
+// Transforms the given string from the lua code to a warehouse policy
+inline Warehouse::StockPolicy string_to_wh_policy(lua_State* L, uint32_t index) {
+ std::string str = luaL_checkstring(L, index);
+ if (str == "normal")
+ return Warehouse::StockPolicy::kNormal;
+ else if (str == "prefer")
+ return Warehouse::StockPolicy::kPrefer;
+ else if (str == "dontstock")
+ return Warehouse::StockPolicy::kDontStock;
+ else if (str == "remove")
+ return Warehouse::StockPolicy::kRemove;
+ else
+ report_error(L, "<%s> is no valid warehouse policy!", str.c_str());
+}
+
+bool do_set_ware_policy(Warehouse* wh, const DescriptionIndex idx, const Warehouse::StockPolicy p) {
+ wh->set_ware_policy(idx, p);
+ return true;
+}
+
+/**
+ * Sets the given policy for the given ware in the given warehouse and return true.
+ * If the no ware with the given name exists for the tribe of the warehouse, return false.
+ */
+bool do_set_ware_policy(Warehouse* wh, const std::string& name, const Warehouse::StockPolicy p) {
+ const TribeDescr& tribe = wh->owner().tribe();
+ DescriptionIndex idx = tribe.ware_index(name);
+ if (!tribe.has_ware(idx)) {
+ return false;
+ }
+ return do_set_ware_policy(wh, idx, p);
+}
+
+bool do_set_worker_policy(Warehouse* wh,
+ const DescriptionIndex idx,
+ const Warehouse::StockPolicy p) {
+ const TribeDescr& tribe = wh->owner().tribe();
+ // If the worker does not cost anything, ignore it
+ // Otherwise, an unlimited stream of carriers might leave the warehouse
+ if (tribe.get_worker_descr(idx)->is_buildable() &&
+ tribe.get_worker_descr(idx)->buildcost().empty()) {
+ return true;
+ }
+ wh->set_worker_policy(idx, p);
+ return true;
+}
+
+/**
+ * Sets the given policy for the given worker in the given warehouse and returns true.
+ * Also returns true if the given worker does not cost anything but in this case does not set its
+ * policy.
+ * If no worker with the given name exists for the tribe of the warehouse, return false.
+ */
+bool do_set_worker_policy(Warehouse* wh, const std::string& name, const Warehouse::StockPolicy p) {
+ const TribeDescr& tribe = wh->owner().tribe();
+ DescriptionIndex idx = tribe.worker_index(name);
+ if (!tribe.has_worker(idx)) {
+ return false;
+ }
+ return do_set_worker_policy(wh, idx, p);
+}
+/* RST
+ .. method:: set_warehouse_policies(which, policy)
+
+ Sets the policies how the warehouse should handle the given wares and workers.
+
+ Usage example:
+ .. code-block:: lua
+
+ wh:set_warehouse_policies("coal", "prefer")
+
+ :arg which: behaves like for :meth:`HasWares.get_wares`.
+
+ :arg policy: the policy to apply for all the wares and workers given in `which`.
+ :type policy: a string out of "normal", "prefer", "dontstock", "remove".
+*/
+int LuaWarehouse::set_warehouse_policies(lua_State* L) {
+ int32_t nargs = lua_gettop(L);
+ if (nargs != 3)
+ report_error(L, "Wrong number of arguments to set_warehouse_policies!");
+
+ Warehouse* wh = get(L, get_egbase(L));
+ Warehouse::StockPolicy p = string_to_wh_policy(L, -1);
+ lua_pop(L, 1);
+ const TribeDescr& tribe = wh->owner().tribe();
+
+ // takes either "all", a name or an array of names
+ if (lua_isstring(L, 2)) {
+ const std::string& what = luaL_checkstring(L, -1);
+ if (what == "all") {
+ for (const DescriptionIndex& i : tribe.wares()) {
+ do_set_ware_policy(wh, i, p);
+ }
+ for (const DescriptionIndex& i : tribe.workers()) {
+ do_set_worker_policy(wh, i, p);
+ }
+ } else {
+ // Only one item requested
+ if (!do_set_ware_policy(wh, what, p) && !do_set_worker_policy(wh, what, p)) {
+ // Unknown whatever, abort
+ report_error(L, "Unknown name: <%s>", what.c_str());
+ }
+ }
+ } else {
+ // array of names
+ luaL_checktype(L, 2, LUA_TTABLE);
+ lua_pushnil(L);
+ while (lua_next(L, 2) != 0) {
+ const std::string& what = luaL_checkstring(L, -1);
+ if (!do_set_ware_policy(wh, what, p) && !do_set_worker_policy(wh, what, p)) {
+ // Note that this will change the policy for entries earlier in the list
+ // but when the user provides broken data its his own fault
+ report_error(L, "Unknown name: <%s>", what.c_str());
+ }
+ lua_pop(L, 1);
+ }
+ }
+
+ return 0;
+}
+
+// Gets the warehouse policy by ware/worker-name or id
+#define WH_GET_POLICY(type) \
+ void do_get_##type##_policy(lua_State* L, Warehouse* wh, const DescriptionIndex idx) { \
+ wh_policy_to_string(L, wh->get_##type##_policy(idx)); \
+ } \
+ \
+ bool do_get_##type##_policy(lua_State* L, Warehouse* wh, const std::string& name) { \
+ const TribeDescr& tribe = wh->owner().tribe(); \
+ DescriptionIndex idx = tribe.type##_index(name); \
+ if (!tribe.has_##type(idx)) { \
+ return false; \
+ } \
+ do_get_##type##_policy(L, wh, idx); \
+ return true; \
+ }
+
+WH_GET_POLICY(ware)
+WH_GET_POLICY(worker)
+#undef WH_GET_POLICY
+
+/* RST
+ .. method:: get_warehouse_policies(which)
+
+ Gets the policies how the warehouse should handle the given wares and workers.
+ The method to handle is one of the strings "normal", "prefer", "dontstock", "remove".
+
+ Usage example:
+ .. code-block:: lua
+
+ wh:get_warehouse_policies({"ax", "coal"})
+ -- Returns a table like {ax="normal", coal="prefer"}
+
+ :arg which: behaves like for :meth:`HasWares.get_wares`.
+
+ :returns: :class:`string` or :class:`table`
+*/
+int LuaWarehouse::get_warehouse_policies(lua_State* L) {
+ int32_t nargs = lua_gettop(L);
+ if (nargs != 2)
+ report_error(L, "Wrong number of arguments to get_warehouse_policies!");
+ Warehouse* wh = get(L, get_egbase(L));
+ const TribeDescr& tribe = wh->owner().tribe();
+ // takes either "all", a single name or an array of names
+ if (lua_isstring(L, 2)) {
+ std::string what = luaL_checkstring(L, -1);
+ if (what == "all") {
+ lua_newtable(L);
+ for (const DescriptionIndex& i : tribe.wares()) {
+ std::string name = tribe.get_ware_descr(i)->name();
+ lua_pushstring(L, name.c_str());
+ do_get_ware_policy(L, wh, i);
+ lua_rawset(L, -3);
+ }
+ for (const DescriptionIndex& i : tribe.workers()) {
+ std::string name = tribe.get_worker_descr(i)->name();
+ lua_pushstring(L, name.c_str());
+ do_get_worker_policy(L, wh, i);
+ lua_rawset(L, -3);
+ }
+ } else {
+ // Only one item requested
+ if (!do_get_ware_policy(L, wh, what) && !do_get_worker_policy(L, wh, what)) {
+ // Unknown whatever, abort
+ report_error(L, "Unknown name: <%s>", what.c_str());
+ }
+ }
+ } else {
+ // array of names
+ luaL_checktype(L, 2, LUA_TTABLE);
+ lua_newtable(L);
+ lua_pushnil(L);
+ while (lua_next(L, 2) != 0) {
+ // Stack is: ... input_table new_table nil input_key input_value
+ // input_value is the name of the ware or worker and will be added into the new table
+ // input_key is an index and is dropped by the next call of lua_next()
+ const std::string& what = luaL_checkstring(L, -1);
+ if (!do_get_ware_policy(L, wh, what) && !do_get_worker_policy(L, wh, what)) {
+ // Note that this will change the policy for entries earlier in the list
+ // but when the user provides broken data its his own fault
+ report_error(L, "Unknown name: <%s>", what.c_str());
+ }
+ lua_rawset(L, -4);
+ }
+ }
+ return 1;
+}
+
// documented in parent class
int LuaWarehouse::get_soldiers(lua_State* L) {
Warehouse* wh = get(L, get_egbase(L));
=== modified file 'src/scripting/lua_map.h'
--- src/scripting/lua_map.h 2017-01-21 14:36:22 +0000
+++ src/scripting/lua_map.h 2017-01-21 20:09:14 +0000
@@ -1011,6 +1011,8 @@
int set_workers(lua_State*);
int set_soldiers(lua_State*);
int get_soldiers(lua_State*);
+ int set_warehouse_policies(lua_State*);
+ int get_warehouse_policies(lua_State*);
int start_expedition(lua_State*);
int cancel_expedition(lua_State*);
Follow ups