← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1675179-lua-economy into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/bug-1675179-lua-economy into lp:widelands.

Commit message:
Added a new object LuaEconomy to LuaMap.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1675179 in widelands: "Implement lua functions needed for Empire scenario 3"
  https://bugs.launchpad.net/widelands/+bug/1675179

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1675179-lua-economy/+merge/321008

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.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1675179-lua-economy into lp:widelands.
=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc	2017-01-30 14:40:12 +0000
+++ src/scripting/lua_map.cc	2017-03-26 10:55:25 +0000
@@ -3342,6 +3342,128 @@
  */
 
 /* RST
+Economy
+-------
+.. class:: LuaEconomy
+
+   Provides access to an economy. A player can have multiple economies;
+   you can get an economy from a :class:`Flag`.
+*/
+const char LuaEconomy::className[] = "Economy";
+const MethodType<LuaEconomy> LuaEconomy::Methods[] = {
+   METHOD(LuaEconomy, ware_target_quantity),
+   METHOD(LuaEconomy, worker_target_quantity),
+   METHOD(LuaEconomy, set_ware_target_quantity),
+   METHOD(LuaEconomy, set_worker_target_quantity),
+   {nullptr, nullptr},
+};
+const PropertyType<LuaEconomy> LuaEconomy::Properties[] = {
+   {nullptr, nullptr, nullptr},
+};
+
+void LuaEconomy::__persist(lua_State* L) {
+	const Widelands::Economy* economy = get();
+	const Widelands::Player& player = economy->owner();
+	PERS_UINT32("player", player.player_number());
+	PERS_UINT32("economy", player.get_economy_number(economy));
+}
+
+void LuaEconomy::__unpersist(lua_State* L) {
+	Widelands::PlayerNumber player_number;
+	size_t economy_number;
+	UNPERS_UINT32("player", player_number);
+	UNPERS_UINT32("economy", economy_number);
+	const Widelands::Player& player = get_egbase(L).player(player_number);
+	set_economy_pointer(player.get_economy_by_number(economy_number));
+}
+
+/* RST
+   .. method:: ware_target_quantity(warename)
+
+      Returns the amount of the given ware that should be kept in stock for this economy.
+
+      :arg warename: the name of the ware.
+      :type warename: :class:`string`
+*/
+int LuaEconomy::ware_target_quantity(lua_State* L) {
+	const std::string warename = luaL_checkstring(L, 2);
+	const Widelands::DescriptionIndex index = get_egbase(L).tribes().ware_index(warename);
+	if (get_egbase(L).tribes().ware_exists(index)) {
+		const Widelands::Economy::TargetQuantity& quantity = get()->ware_target_quantity(index);
+		lua_pushinteger(L, quantity.permanent);
+	} else {
+		report_error(L, "There is no ware '%s'.", warename.c_str());
+	}
+	return 1;
+}
+
+/* RST
+   .. method:: worker_target_quantity(workername)
+
+      Returns the amount of the given worker that should be kept in stock for this economy.
+
+      :arg workername: the name of the worker.
+      :type workername: :class:`string`
+*/
+int LuaEconomy::worker_target_quantity(lua_State* L) {
+	const std::string workername = luaL_checkstring(L, 2);
+	const Widelands::DescriptionIndex index = get_egbase(L).tribes().worker_index(workername);
+	if (get_egbase(L).tribes().worker_exists(index)) {
+		const Widelands::Economy::TargetQuantity& quantity = get()->worker_target_quantity(index);
+		lua_pushinteger(L, quantity.permanent);
+	} else {
+		report_error(L, "There is no worker '%s'.", workername.c_str());
+	}
+	return 1;
+}
+
+/* RST
+   .. method:: set_ware_target_quantity(warename)
+
+      Sets the amount of the given ware type that should be kept in stock for this economy.
+
+      :arg warename: the name of the ware type.
+      :type warename: :class:`string`
+
+      :arg amount: the new target amount for the ware.
+      :type amount: :class:`integer`
+*/
+int LuaEconomy::set_ware_target_quantity(lua_State* L) {
+	const std::string warename = luaL_checkstring(L, 2);
+	const Widelands::DescriptionIndex index = get_egbase(L).tribes().ware_index(warename);
+	if (get_egbase(L).tribes().ware_exists(index)) {
+		const int quantity = luaL_checkinteger(L, 3);
+		get()->set_ware_target_quantity(index, quantity, get_egbase(L).get_gametime());
+	} else {
+		report_error(L, "There is no ware '%s'.", warename.c_str());
+	}
+	return 1;
+}
+
+/* RST
+   .. method:: set_worker_target_quantity(workername)
+
+      Sets the amount of the given worker type that should be kept in stock for this economy.
+
+      :arg workername: the name of the worker type.
+      :type workername: :class:`string`
+
+      :arg amount: the new target amount for the worker.
+      :type amount: :class:`integer`
+*/
+int LuaEconomy::set_worker_target_quantity(lua_State* L) {
+	const std::string workername = luaL_checkstring(L, 2);
+	const Widelands::DescriptionIndex index = get_egbase(L).tribes().worker_index(workername);
+	if (get_egbase(L).tribes().worker_exists(index)) {
+		const int quantity = luaL_checkinteger(L, 3);
+		get()->set_worker_target_quantity(index, quantity, get_egbase(L).get_gametime());
+	} else {
+		report_error(L, "There is no worker '%s'.", workername.c_str());
+	}
+	return 1;
+}
+
+/* RST
 MapObject
 ---------
 
@@ -3682,7 +3804,10 @@
    METHOD(LuaFlag, set_wares), METHOD(LuaFlag, get_wares), {nullptr, nullptr},
 };
 const PropertyType<LuaFlag> LuaFlag::Properties[] = {
-   PROP_RO(LuaFlag, roads), PROP_RO(LuaFlag, building), {nullptr, nullptr, nullptr},
+   PROP_RO(LuaFlag, economy),
+   PROP_RO(LuaFlag, roads),
+   PROP_RO(LuaFlag, building),
+   {nullptr, nullptr, nullptr},
 };
 
 /*
@@ -3691,6 +3816,18 @@
  ==========================================================
  */
 /* RST
+   .. attribute:: economy
+
+      (RO) Returns the economy that this flag belongs to.
+
+      :returns: The :class:`Economy` associated with the flag.
+*/
+int LuaFlag::get_economy(lua_State* L) {
+	const Flag* f = get(L, get_egbase(L));
+	return to_lua<LuaEconomy>(L, new LuaEconomy(f->get_economy()));
+}
+
+/* RST
    .. attribute:: roads
 
       (RO) Array of roads leading to the flag. Directions
@@ -6075,6 +6212,7 @@
 
 	register_class<LuaField>(L, "map");
 	register_class<LuaPlayerSlot>(L, "map");
+	register_class<LuaEconomy>(L, "map");
 	register_class<LuaMapObject>(L, "map");
 
 	register_class<LuaBob>(L, "map", true);

=== modified file 'src/scripting/lua_map.h'
--- src/scripting/lua_map.h	2017-01-25 18:55:59 +0000
+++ src/scripting/lua_map.h	2017-03-26 10:55:25 +0000
@@ -22,6 +22,7 @@
 
 #include <set>
 
+#include "economy/economy.h"
 #include "economy/flag.h"
 #include "economy/portdock.h"
 #include "economy/road.h"
@@ -728,6 +729,54 @@
 	const Widelands::TerrainDescription* terraindescr_;
 };
 
+class LuaEconomy : public LuaMapModuleClass {
+public:
+    LUNA_CLASS_HEAD(LuaEconomy);
+
+    virtual ~LuaEconomy() {
+    }
+
+    LuaEconomy() : economy_(nullptr) {
+    }
+	 LuaEconomy(Widelands::Economy* economy) : economy_(economy) {
+    }
+    LuaEconomy(lua_State* L) : economy_(nullptr) {
+        report_error(L, "Cannot instantiate a 'LuaEconomy' directly!");
+    }
+
+    void __persist(lua_State* L) override;
+    void __unpersist(lua_State* L) override;
+
+	 /*
+     * Properties
+     */
+
+	 /*
+	  * Lua methods
+	  */
+	 int ware_target_quantity(lua_State*);
+	 int worker_target_quantity(lua_State*);
+	 int set_ware_target_quantity(lua_State*);
+	 int set_worker_target_quantity(lua_State*);
+
+    /*
+     * C methods
+     */
+
+protected:
+	 Widelands::Economy* get() const {
+        assert(economy_ != nullptr);
+        return economy_;
+    }
+    // For persistence.
+	 void set_economy_pointer(Widelands::Economy* pointer) {
+        economy_ = pointer;
+    }
+
+private:
+	 Widelands::Economy* economy_;
+};
+
 #define CASTED_GET(klass)                                                                          \
 	Widelands::klass* get(lua_State* L, Widelands::EditorGameBase& egbase) {                        \
 		return static_cast<Widelands::klass*>(LuaMapObject::get(L, egbase, #klass));                 \
@@ -904,6 +953,7 @@
 	/*
 	 * Properties
 	 */
+	int get_economy(lua_State* L);
 	int get_roads(lua_State* L);
 	int get_building(lua_State* L);
 	/*

=== added file 'test/maps/lua_testsuite.wmf/scripting/geconomy.lua'
--- test/maps/lua_testsuite.wmf/scripting/geconomy.lua	1970-01-01 00:00:00 +0000
+++ test/maps/lua_testsuite.wmf/scripting/geconomy.lua	2017-03-26 10:55:25 +0000
@@ -0,0 +1,47 @@
+-- ==================================================
+-- Tests for Economy that are only useful in the Game
+-- ==================================================
+
+economy_tests = lunit.TestCase("Economy test")
+function test_descr:test_instantiation_forbidden()
+   assert_error("Cannot instantiate", function()
+      wl.map.Economy()
+   end)
+end
+
+function economy_tests:test_ware_target_quantity()
+
+   -- Get the economy off a flag
+   local sf = map:get_field(10, 10)
+   local hq = player1:place_building("barbarians_headquarters", sf, false, true)
+   local hq_flag = hq.flag
+   local eco = hq_flag.economy
+
+   -- Nonexisting ware should fail
+   assert_error("Nonexisting ware",function() eco:ware_target_quantity("foobar") end)
+
+   -- Now set and confirm ware quantity
+   quantity = eco:ware_target_quantity("log")
+   quantity = quantity + 1
+   eco:set_ware_target_quantity("log", quantity)
+   assert_equal(quantity, eco:ware_target_quantity("log"))
+   hq_flag:remove()
+end
+
+function economy_tests:test_worker_target_quantity()
+   -- Get the economy off a flag
+   local sf = map:get_field(10, 10)
+   local hq = player1:place_building("barbarians_headquarters", sf, false, true)
+   local hq_flag = hq.flag
+   local eco = hq_flag.economy
+
+   -- Nonexisting worker should fail
+   assert_error("Nonexisting worker",function() eco:worker_target_quantity("foobar") end)
+
+   -- Now set and confirm worker quantity
+   quantity = eco:worker_target_quantity("barbarians_soldier")
+   quantity = quantity + 1
+   eco:set_worker_target_quantity("barbarians_soldier", quantity)
+   assert_equal(quantity, eco:worker_target_quantity("barbarians_soldier"))
+   hq_flag:remove()
+end

=== modified file 'test/maps/lua_testsuite.wmf/scripting/init.lua'
--- test/maps/lua_testsuite.wmf/scripting/init.lua	2016-04-12 07:35:33 +0000
+++ test/maps/lua_testsuite.wmf/scripting/init.lua	2017-03-26 10:55:25 +0000
@@ -40,6 +40,7 @@
 if not wl.editor then
    include "map:scripting/game.lua"
 
+   include "map:scripting/geconomy.lua"
    include "map:scripting/gplayer.lua"
    include "map:scripting/gfield.lua"
    include "map:scripting/gplr_access.lua"


Follow ups