← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1718745-allows-seafaring into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/bug-1718745-allows-seafaring into lp:widelands.

Commit message:
Split new function cleanup_portspaces() from allows_seafaring(), and refactored port spaces checks. allows_seafaring() is now const and used more widely. Exposed 3 new functions to LuaMap:

    - get_allows_seafaring
    - get_number_of_port_spaces
    - set_port_space

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1718745 in widelands: "Please expose "allows_seafaring" in Lua interface"
  https://bugs.launchpad.net/widelands/+bug/1718745

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1718745-allows-seafaring/+merge/333233
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1718745-allows-seafaring into lp:widelands.
=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2017-11-04 23:59:03 +0000
+++ src/ai/defaultai.cc	2017-11-06 13:39:56 +0000
@@ -1974,11 +1974,9 @@
 
 	const Map& map = game().map();
 
-	if (gametime % 5 == 0) {
-		// TODO(unknown): Counting port spaces is very primitive way for this
-		// there should be better alternative f.e. like map::allows_seafaring()
-		// function but simplier
-		seafaring_economy = map.get_port_spaces().size() >= 2;
+	// Checking for seafaring is a bit expensive, so we only do it once per second
+	if (gametime % 1000 == 0) {
+		seafaring_economy = map.allows_seafaring();
 	}
 
 	for (int32_t i = 0; i < 4; ++i)

=== modified file 'src/editor/ui_menus/main_menu_save_map.cc'
--- src/editor/ui_menus/main_menu_save_map.cc	2017-08-20 17:45:42 +0000
+++ src/editor/ui_menus/main_menu_save_map.cc	2017-11-06 13:39:56 +0000
@@ -279,6 +279,7 @@
 		   g_fs->create_sub_file_system(tmp_name, binary ? FileSystem::ZIP : FileSystem::DIR));
 
 		// Recompute seafaring tag
+		map->cleanup_port_spaces();
 		if (map->allows_seafaring()) {
 			map->add_tag("seafaring");
 		} else {

=== modified file 'src/logic/map.cc'
--- src/logic/map.cc	2017-09-13 07:27:00 +0000
+++ src/logic/map.cc	2017-11-06 13:39:56 +0000
@@ -1303,18 +1303,28 @@
 	return portdock;
 }
 
+bool Map::is_port_space_allowed(const FCoords fc) const {
+	return (fc.field->get_caps() & BUILDCAPS_SIZEMASK) == BUILDCAPS_BIG && !find_portdock(fc).empty();
+}
+
 /// \returns true, if Coordinates are in port space list
 bool Map::is_port_space(const Coords& c) const {
 	return port_spaces_.count(c);
 }
 
-/// Set or unset a space as port space
-void Map::set_port_space(Coords c, bool allowed) {
+bool Map::set_port_space(Coords c, bool allowed, bool force) {
+	bool success = false;
 	if (allowed) {
 		port_spaces_.insert(c);
+		success = force || is_port_space_allowed(get_fcoords(c));
+		if (!success) {
+			port_spaces_.erase(c);
+		}
 	} else {
 		port_spaces_.erase(c);
+		success = true;
 	}
+	return success;
 }
 
 /**
@@ -1949,46 +1959,29 @@
 			check_neighbour_heights(n[i], area);
 }
 
-/*
-===========
-Map::allows_seafaring()
-
-This function checks if there are two ports that are reachable
-for each other - then the map is seafaring.
-=============
-*/
-bool Map::allows_seafaring() {
-	Map::PortSpacesSet port_spaces = get_port_spaces();
-	std::vector<Coords> portdocks;
+bool Map::allows_seafaring() const {
 	std::set<Coords> swim_coords;
 
-	for (const Coords& c : port_spaces) {
-		std::queue<Coords> q_positions;
+	for (const Coords& c : get_port_spaces()) {
+		std::queue<Coords> positions_to_check;
 		std::set<Coords> visited_positions;
 		FCoords fc = get_fcoords(c);
-		portdocks = find_portdock(fc);
-
-		/* remove the port space if it is not longer valid port space */
-		if ((fc.field->get_caps() & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG || portdocks.empty()) {
-			set_port_space(c, false);
-			continue;
-		}
-
-		for (const Coords& portdock : portdocks) {
+
+		for (const Coords& portdock : find_portdock(fc)) {
 			visited_positions.insert(portdock);
-			q_positions.push(portdock);
+			positions_to_check.push(portdock);
 		}
 
-		while (!q_positions.empty()) {
-			const Coords& swim_coord = q_positions.front();
-			q_positions.pop();
+		while (!positions_to_check.empty()) {
+			const Coords& swim_coord = positions_to_check.front();
+			positions_to_check.pop();
 			for (uint8_t i = 1; i <= 6; ++i) {
 				FCoords neighbour;
 				get_neighbour(get_fcoords(swim_coord), i, &neighbour);
 				if ((neighbour.field->get_caps() & (MOVECAPS_SWIM | MOVECAPS_WALK)) == MOVECAPS_SWIM) {
 					if (visited_positions.count(neighbour) == 0) {
 						visited_positions.insert(neighbour);
-						q_positions.push(neighbour);
+						positions_to_check.push(neighbour);
 					}
 				}
 			}
@@ -2003,6 +1996,18 @@
 	return false;
 }
 
+bool Map::cleanup_port_spaces() {
+	bool was_clean = true;
+	for (const Coords& c : get_port_spaces()) {
+		if (!is_port_space_allowed(get_fcoords(c))) {
+			set_port_space(c, false);
+			was_clean = false;
+			continue;
+		}
+	}
+	return was_clean;
+}
+
 bool Map::has_artifacts() {
 	for (MapIndex i = 0; i < max_index(); ++i) {
 		if (upcast(Immovable, immovable, fields_[i].get_immovable())) {

=== modified file 'src/logic/map.h'
--- src/logic/map.h	2017-09-01 15:45:59 +0000
+++ src/logic/map.h	2017-11-06 13:39:56 +0000
@@ -444,14 +444,29 @@
 	/// Translate the whole map so that the given point becomes the new origin.
 	void set_origin(const Coords&);
 
-	/// Port space specific functions
+	// Port space specific functions
+
+	/// Checks whether the port space at the given fccords has enough space and enough water nearby.
+	bool is_port_space_allowed(const FCoords fc) const;
 	bool is_port_space(const Coords& c) const;
-	void set_port_space(Coords c, bool allowed);
+
+	/**
+	  * Set or unset a space as port space.
+	  * 'force' sets the port space even if it isn't viable, and is to be used for map loading only,
+	  * or if you want to set a port space somewhere where immovables might already be present on the map.
+	  * Returns whether the port space was set/unset successfully.
+	  */
+	bool set_port_space(Coords c, bool allowed, bool force = false);
 	const PortSpacesSet& get_port_spaces() const {
 		return port_spaces_;
 	}
 	std::vector<Coords> find_portdock(const Widelands::Coords& c) const;
-	bool allows_seafaring();
+
+	/// Check whether there are at least 2 port spaces that can be reached from each other by water
+	bool allows_seafaring() const;
+	/// Remove all port spaces that are not valid (Buildcap < big or not enough space for a portdock).
+	/// Returns false if a port space got removed.
+	bool cleanup_port_spaces();
 
 	/// Checks whether there are any artifacts on the map
 	bool has_artifacts();

=== modified file 'src/logic/map_objects/tribes/production_program.cc'
--- src/logic/map_objects/tribes/production_program.cc	2017-08-20 17:45:42 +0000
+++ src/logic/map_objects/tribes/production_program.cc	2017-11-06 13:39:56 +0000
@@ -742,9 +742,9 @@
 void ProductionProgram::ActCheckMap::execute(Game& game, ProductionSite& ps) const {
 	switch (feature_) {
 	case SEAFARING: {
-		if (game.map().get_port_spaces().size() > 1)
+		if (game.map().allows_seafaring()) {
 			return ps.program_step(game, 0);
-		else {
+		} else {
 			ps.set_production_result(_("No use for ships on this map!"));
 			return ps.program_end(game, Failed);
 		}

=== modified file 'src/map_io/map_port_spaces_packet.cc'
--- src/map_io/map_port_spaces_packet.cc	2017-08-19 22:22:20 +0000
+++ src/map_io/map_port_spaces_packet.cc	2017-11-06 13:39:56 +0000
@@ -51,8 +51,7 @@
 
 			Section& s2 = prof.get_safe_section("port_spaces");
 			for (uint16_t i = 0; i < num; ++i) {
-				map->set_port_space(
-				   get_safe_coords(std::to_string(static_cast<unsigned int>(i)), ext, &s2), true);
+				map->set_port_space(get_safe_coords(std::to_string(static_cast<unsigned int>(i)), ext, &s2), true, true);
 			}
 		} else {
 			throw UnhandledVersionError("MapPortSpacesPacket", packet_version, kCurrentPacketVersion);
@@ -70,8 +69,7 @@
 	s1.set_int("packet_version", kCurrentPacketVersion);
 
 	const Map& map = egbase.map();
-	const uint16_t num = map.get_port_spaces().size();
-	s1.set_int("number_of_port_spaces", num);
+	s1.set_int("number_of_port_spaces", map.get_port_spaces().size());
 
 	Section& s2 = prof.create_section("port_spaces");
 	int i = 0;

=== modified file 'src/map_io/s2map.cc'
--- src/map_io/s2map.cc	2017-08-19 13:02:14 +0000
+++ src/map_io/s2map.cc	2017-11-06 13:39:56 +0000
@@ -392,7 +392,7 @@
 
 	map_.recalc_whole_map(egbase.world());
 
-	postload_fix_conversion(egbase);
+	postload_set_port_spaces();
 
 	set_state(STATE_LOADED);
 
@@ -473,8 +473,9 @@
 		for (int16_t x = 0; x < mapwidth; ++x, ++f, ++pc) {
 			uint8_t c = *pc;
 			// Harbour buildspace & textures - Information taken from:
-			if (c & 0x40)
-				map_.set_port_space(Widelands::Coords(x, y), true);
+			if (c & 0x40) {
+				port_spaces_to_set_.insert(Widelands::Coords(x, y));
+			}
 			f->set_terrain_d(terrain_converter.lookup(worldtype_, c & 0x1f));
 		}
 
@@ -490,8 +491,9 @@
 			uint8_t c = *pc;
 			// Harbour buildspace & textures - Information taken from:
 			// http://bazaar.launchpad.net/~xaser/s25rttr/s25edit/view/head:/WLD_reference.txt
-			if (c & 0x40)
-				map_.set_port_space(Widelands::Coords(x, y), true);
+			if (c & 0x40) {
+				port_spaces_to_set_.insert(Widelands::Coords(x, y));
+			}
 			f->set_terrain_r(terrain_converter.lookup(worldtype_, c & 0x1f));
 		}
 
@@ -1041,41 +1043,25 @@
 	}
 }
 
-/// Try to fix data, which is incompatible between S2 and Widelands
-void S2MapLoader::postload_fix_conversion(Widelands::EditorGameBase& egbase) {
-
-	/*
-	 * 1: Try to fix port spaces
-	 */
-	const Widelands::Map::PortSpacesSet ports(map_.get_port_spaces());
-	const Widelands::World& world = egbase.world();
-
-	// Check if port spaces are valid
-	for (const Widelands::Coords& c : ports) {
-		Widelands::FCoords fc = map_.get_fcoords(c);
-		Widelands::NodeCaps nc = map_.get_max_nodecaps(world, fc);
-		if ((nc & Widelands::BUILDCAPS_SIZEMASK) != Widelands::BUILDCAPS_BIG ||
-		    map_.find_portdock(fc).empty()) {
-			log("Invalid port build space: ");
-			map_.set_port_space(c, false);
-
-			bool fixed = false;
+/// Try to fix data which is incompatible between S2 and Widelands.
+/// This is only the port space locations.
+void S2MapLoader::postload_set_port_spaces() {
+	// Set port spaces near desired locations if possible
+	for (const Widelands::Coords& coords : port_spaces_to_set_) {
+		bool was_set = map_.set_port_space(coords, true);
+		const Widelands::FCoords fc = map_.get_fcoords(coords);
+		if (!was_set) {
+			// Try to set a port space at alternative location
 			Widelands::MapRegion<Widelands::Area<Widelands::FCoords>> mr(
-			   map_, Widelands::Area<Widelands::FCoords>(fc, 3));
+				map_, Widelands::Area<Widelands::FCoords>(fc, 3));
 			do {
-				// Check whether the maximum theoretical possible NodeCap of the field is big + port
-				Widelands::NodeCaps nc2 =
-				   map_.get_max_nodecaps(world, const_cast<Widelands::FCoords&>(mr.location()));
-				if ((nc2 & Widelands::BUILDCAPS_SIZEMASK) == Widelands::BUILDCAPS_BIG &&
-				    (!map_.find_portdock(mr.location()).empty())) {
-					map_.set_port_space(Widelands::Coords(mr.location().x, mr.location().y), true);
-					fixed = true;
-				}
-			} while (mr.advance(map_) && !fixed);
-			if (!fixed) {
-				log("FAILED! No alternative port buildspace for (%i, %i) found!\n", fc.x, fc.y);
-			} else
-				log("Fixed!\n");
+				was_set = map_.set_port_space(Widelands::Coords(mr.location().x, mr.location().y), true);
+			} while (!was_set && mr.advance(map_));
+		}
+		if (!was_set) {
+			log("FAILED! No port buildspace for (%i, %i) found!\n", fc.x, fc.y);
+		} else {
+			log("SUCCESS! Port buildspace set for (%i, %i) \n", fc.x, fc.y);
 		}
 	}
 }

=== modified file 'src/map_io/s2map.h'
--- src/map_io/s2map.h	2017-06-24 10:38:19 +0000
+++ src/map_io/s2map.h	2017-11-06 13:39:56 +0000
@@ -42,10 +42,11 @@
 private:
 	const std::string filename_;
 	WorldType worldtype_;
+	std::set<Widelands::Coords> port_spaces_to_set_;
 
 	void load_s2mf_header(FileRead&);
 	void load_s2mf(Widelands::EditorGameBase&);
-	void postload_fix_conversion(Widelands::EditorGameBase&);
+	void postload_set_port_spaces();
 };
 
 #endif  // end of include guard: WL_MAP_IO_S2MAP_H

=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc	2017-10-04 00:27:47 +0000
+++ src/scripting/lua_map.cc	2017-11-06 13:39:56 +0000
@@ -1138,7 +1138,7 @@
 
 .. class:: Map
 
-   Access to the map and it's objects. You cannot instantiate this directly,
+   Access to the map and its objects. You cannot instantiate this directly,
    instead access it via :attr:`wl.Game.map`.
 */
 const char LuaMap::className[] = "Map";
@@ -1146,9 +1146,12 @@
    METHOD(LuaMap, place_immovable),
    METHOD(LuaMap, get_field),
    METHOD(LuaMap, recalculate),
+   METHOD(LuaMap, set_port_space),
    {nullptr, nullptr},
 };
 const PropertyType<LuaMap> LuaMap::Properties[] = {
+   PROP_RO(LuaMap, allows_seafaring),
+   PROP_RO(LuaMap, number_of_port_spaces),
    PROP_RO(LuaMap, width),
    PROP_RO(LuaMap, height),
    PROP_RO(LuaMap, player_slots),
@@ -1167,6 +1170,31 @@
  ==========================================================
  */
 /* RST
+   .. attribute:: allows_seafaring
+
+      (RO) Whether the map currently allows seafaring. This will calculate a path between port spaces,
+		so it's more accurate but less efficient than :any:`number_of_port_spaces`.
+
+		:returns: True if there are at least two port spaces that can be reached from each other.
+*/
+int LuaMap::get_allows_seafaring(lua_State* L) {
+	lua_pushboolean(L, get_egbase(L).map().allows_seafaring());
+	return 1;
+}
+/* RST
+   .. attribute:: number_of_port_spaces
+
+      (RO) The amount of port spaces on the map. If this is >= 2, one can assume that the map
+      allows seafaring. This is checked very quickly and is more efficient than :any:`allows_seafaring`,
+      but it won't detect whether the port spaces can be reached from each other, so it's less accurate.
+
+      :returns: An integer with the number of port spaces.
+*/
+int LuaMap::get_number_of_port_spaces(lua_State* L) {
+	lua_pushuint32(L, get_egbase(L).map().get_port_spaces().size());
+	return 1;
+}
+/* RST
    .. attribute:: width
 
       (RO) The width of the map in fields.
@@ -1297,6 +1325,37 @@
 	return 0;
 }
 
+/* RST
+   .. method:: set_port_space(x, y, allowed)
+
+      Sets whether a port space is allowed at the coordinates (x, y).
+      Returns false if the port space couldn't be set.
+
+      :arg x: The x coordinate of the port space to set/unset.
+      :type x: :class:`int`
+      :arg y: The y coordinate of the port space to set/unset.
+      :type y: :class:`int`
+      :arg allowed: Whether building a port will be allowed here.
+      :type allowed: :class:`bool`
+      :arg force: Force a port space, even if it isn't viable in this position.
+      :type force: :class:`bool`
+
+      :returns: :const:`true` on success, or :const:`false` otherwise
+      :rtype: :class:`bool`
+*/
+int LuaMap::set_port_space(lua_State* L) {
+	const int x = luaL_checkint32(L, 2);
+	const int y = luaL_checkint32(L, 3);
+	const bool allowed = luaL_checkboolean(L, 4);
+	bool force = false;
+	if (lua_gettop(L) == 5) {
+		force = luaL_checkboolean(L, 5);
+	}
+	const bool success = get_egbase(L).mutable_map()->set_port_space(Widelands::Coords(x, y), allowed, force);
+	lua_pushboolean(L, success);
+	return 1;
+}
+
 /*
  ==========================================================
  C METHODS

=== modified file 'src/scripting/lua_map.h'
--- src/scripting/lua_map.h	2017-09-22 19:54:27 +0000
+++ src/scripting/lua_map.h	2017-11-06 13:39:56 +0000
@@ -86,6 +86,8 @@
 	/*
 	 * Properties
 	 */
+	int get_allows_seafaring(lua_State*);
+	int get_number_of_port_spaces(lua_State*);
 	int get_width(lua_State*);
 	int get_height(lua_State*);
 	int get_player_slots(lua_State*);
@@ -96,6 +98,7 @@
 	int place_immovable(lua_State*);
 	int get_field(lua_State*);
 	int recalculate(lua_State*);
+	int set_port_space(lua_State*);
 
 	/*
 	 * C methods

=== modified file 'src/wui/building_statistics_menu.cc'
--- src/wui/building_statistics_menu.cc	2017-08-20 08:34:02 +0000
+++ src/wui/building_statistics_menu.cc	2017-11-06 13:39:56 +0000
@@ -138,8 +138,8 @@
 	               g_gr->images().get("images/wui/fieldaction/menu_tab_buildmine.png"),
 	               tabs_[BuildingTab::Mines], _("Mines"));
 
-	// Hide the ports tab for non-seafaring maps
-	if (iplayer().game().map().get_port_spaces().size() > 1) {
+	// Only show the ports tab for seafaring maps
+	if (iplayer().game().map().allows_seafaring()) {
 		tab_panel_.add("building_stats_ports",
 		               g_gr->images().get("images/wui/fieldaction/menu_tab_buildport.png"),
 		               tabs_[BuildingTab::Ports], _("Ports"));

=== modified file 'src/wui/fieldaction.cc'
--- src/wui/fieldaction.cc	2017-09-13 07:27:00 +0000
+++ src/wui/fieldaction.cc	2017-11-06 13:39:56 +0000
@@ -416,11 +416,13 @@
 		//  Some building types cannot be built (i.e. construction site) and not
 		//  allowed buildings.
 		if (dynamic_cast<const Game*>(&ibase().egbase())) {
-			if (!building_descr->is_buildable() || !player_->is_building_type_allowed(building_index))
+			if (!building_descr->is_buildable() || !player_->is_building_type_allowed(building_index)) {
 				continue;
+			}
 			if (building_descr->needs_seafaring() &&
-			    ibase().egbase().map().get_port_spaces().size() < 2)
+				 !ibase().egbase().map().allows_seafaring()) {
 				continue;
+			}
 		} else if (!building_descr->is_buildable() && !building_descr->is_enhanced())
 			continue;
 

=== added directory 'test/maps/two_ponds.wmf'
=== added directory 'test/maps/two_ponds.wmf/binary'
=== added file 'test/maps/two_ponds.wmf/binary/heights'
Binary files test/maps/two_ponds.wmf/binary/heights	1970-01-01 00:00:00 +0000 and test/maps/two_ponds.wmf/binary/heights	2017-11-06 13:39:56 +0000 differ
=== added file 'test/maps/two_ponds.wmf/binary/mapobjects'
Binary files test/maps/two_ponds.wmf/binary/mapobjects	1970-01-01 00:00:00 +0000 and test/maps/two_ponds.wmf/binary/mapobjects	2017-11-06 13:39:56 +0000 differ
=== added file 'test/maps/two_ponds.wmf/binary/resource'
Binary files test/maps/two_ponds.wmf/binary/resource	1970-01-01 00:00:00 +0000 and test/maps/two_ponds.wmf/binary/resource	2017-11-06 13:39:56 +0000 differ
=== added file 'test/maps/two_ponds.wmf/binary/terrain'
Binary files test/maps/two_ponds.wmf/binary/terrain	1970-01-01 00:00:00 +0000 and test/maps/two_ponds.wmf/binary/terrain	2017-11-06 13:39:56 +0000 differ
=== added file 'test/maps/two_ponds.wmf/elemental'
--- test/maps/two_ponds.wmf/elemental	1970-01-01 00:00:00 +0000
+++ test/maps/two_ponds.wmf/elemental	2017-11-06 13:39:56 +0000
@@ -0,0 +1,12 @@
+# Automatically created by Widelands bzr8477[trunk] (Debug)
+
+[global]
+packet_version="1"
+map_w="64"
+map_h="64"
+nr_players="1"
+name="Two Ponds"
+author="Unknown"
+descr="Test map with 2 bodies of water, with 1 port space each."
+hint=
+tags=

=== added file 'test/maps/two_ponds.wmf/minimap.png'
Binary files test/maps/two_ponds.wmf/minimap.png	1970-01-01 00:00:00 +0000 and test/maps/two_ponds.wmf/minimap.png	2017-11-06 13:39:56 +0000 differ
=== added file 'test/maps/two_ponds.wmf/objective'
--- test/maps/two_ponds.wmf/objective	1970-01-01 00:00:00 +0000
+++ test/maps/two_ponds.wmf/objective	2017-11-06 13:39:56 +0000
@@ -0,0 +1,4 @@
+# Automatically created by Widelands bzr8477[trunk] (Debug)
+
+[global]
+packet_version="2"

=== added file 'test/maps/two_ponds.wmf/player_names'
--- test/maps/two_ponds.wmf/player_names	1970-01-01 00:00:00 +0000
+++ test/maps/two_ponds.wmf/player_names	2017-11-06 13:39:56 +0000
@@ -0,0 +1,10 @@
+# Automatically created by Widelands bzr8477[trunk] (Debug)
+
+[global]
+packet_version="2"
+
+[player_1]
+name="Cluicheadair 1"
+tribe="barbarians"
+ai=
+closeable="false"

=== added file 'test/maps/two_ponds.wmf/player_position'
--- test/maps/two_ponds.wmf/player_position	1970-01-01 00:00:00 +0000
+++ test/maps/two_ponds.wmf/player_position	2017-11-06 13:39:56 +0000
@@ -0,0 +1,5 @@
+# Automatically created by Widelands bzr8477[trunk] (Debug)
+
+[global]
+packet_version="2"
+player_1="63 59"

=== added file 'test/maps/two_ponds.wmf/port_spaces'
--- test/maps/two_ponds.wmf/port_spaces	1970-01-01 00:00:00 +0000
+++ test/maps/two_ponds.wmf/port_spaces	2017-11-06 13:39:56 +0000
@@ -0,0 +1,9 @@
+# Automatically created by Widelands bzr8477[trunk] (Debug)
+
+[global]
+packet_version="1"
+number_of_port_spaces="2"
+
+[port_spaces]
+0="5 2"
+1="12 24"

=== added directory 'test/maps/two_ponds.wmf/scripting'
=== added file 'test/maps/two_ponds.wmf/scripting/init.lua'
--- test/maps/two_ponds.wmf/scripting/init.lua	1970-01-01 00:00:00 +0000
+++ test/maps/two_ponds.wmf/scripting/init.lua	2017-11-06 13:39:56 +0000
@@ -0,0 +1,5 @@
+include "scripting/coroutine.lua"
+include "scripting/lunit.lua"
+
+game = wl.Game()
+map = game.map

=== added file 'test/maps/two_ponds.wmf/scripting/test_seafaring.lua'
--- test/maps/two_ponds.wmf/scripting/test_seafaring.lua	1970-01-01 00:00:00 +0000
+++ test/maps/two_ponds.wmf/scripting/test_seafaring.lua	2017-11-06 13:39:56 +0000
@@ -0,0 +1,34 @@
+run(function()
+   -- The map in its initial state has 2 unconnected port spaces, so it should not allow seafaring
+   assert_equal(2, map.number_of_port_spaces)
+   assert_equal(false, map.allows_seafaring)
+
+   -- Now try to add a port space on a medium buildcap, it should fail
+   assert_equal(false, map:set_port_space(11, 9, true))
+   assert_equal(2, map.number_of_port_spaces)
+   assert_equal(false, map.allows_seafaring)
+
+   -- Now try to add a port space away from water, it should fail
+   assert_equal(false, map:set_port_space(18, 9, true))
+   assert_equal(2, map.number_of_port_spaces)
+   assert_equal(false, map.allows_seafaring)
+
+   -- Now add a connecting port space - it should succeed and we should have seafaring then
+   assert_equal(true, map:set_port_space(0, 2, true))
+   assert_equal(3, map.number_of_port_spaces)
+   assert_equal(true, map.allows_seafaring)
+
+  -- Remove the port space again
+   assert_equal(true, map:set_port_space(0, 2, false))
+   assert_equal(2, map.number_of_port_spaces)
+   assert_equal(false, map.allows_seafaring)
+
+   -- Now try to force a port space away from water, it should succeed
+   assert_equal(true, map:set_port_space(18, 9, true, true))
+   assert_equal(3, map.number_of_port_spaces)
+   assert_equal(false, map.allows_seafaring)
+   map:set_port_space(18, 9, false)
+
+   print("# All Tests passed.")
+   wl.ui.MapView():close()
+end)

=== added file 'test/maps/two_ponds.wmf/version'
--- test/maps/two_ponds.wmf/version	1970-01-01 00:00:00 +0000
+++ test/maps/two_ponds.wmf/version	2017-11-06 13:39:56 +0000
@@ -0,0 +1,11 @@
+# Automatically created by Widelands bzr8477[trunk] (Debug)
+
+[global]
+map_source_url=
+map_release=
+map_creator_version="bzr8477[trunk]"
+map_version_major="0"
+map_version_minor="1"
+map_version_timestamp="1509900753"
+packet_version="1"
+packet_compatibility="1"


Follow ups