← Back to team overview

widelands-dev team mailing list archive

[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