← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/ship_and_portspaces into lp:widelands

 

SirVer has proposed merging lp:~widelands-dev/widelands/ship_and_portspaces into lp:widelands.

Commit message:
- Only allow building a port if all fields can be conquered. Fixes bug 1542703. Also added a test for this issue.
- Forcing a constructionsite properly conquers the area that the finished building will occupy.
- Code simplifications/refactorings around ships.
- Small const correctness in Map.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1542703 in widelands: "Crash during battle in editor_game_base.cc:677"
  https://bugs.launchpad.net/widelands/+bug/1542703

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/ship_and_portspaces/+merge/285409
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/ship_and_portspaces into lp:widelands.
=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2016-02-03 10:01:08 +0000
+++ src/ai/defaultai.cc	2016-02-08 21:01:32 +0000
@@ -4858,13 +4858,13 @@
 
 	// If we have portspace following options are avaiable:
 	// 1. Build a port there
-	if (so.ship->exp_port_spaces()->size() > 0) {  // making sure we have possible portspaces
+	if (!so.ship->exp_port_spaces().empty()) {  // making sure we have possible portspaces
 
 		// we score the place
-		const uint8_t spot_score = spot_scoring(so.ship->exp_port_spaces()->front());
+		const uint8_t spot_score = spot_scoring(so.ship->exp_port_spaces().front());
 
 		if ((gametime / 10) % 8 < spot_score) {  // we build a port here
-			game().send_player_ship_construct_port(*so.ship, so.ship->exp_port_spaces()->front());
+			game().send_player_ship_construct_port(*so.ship, so.ship->exp_port_spaces().front());
 			so.last_command_time = gametime;
 			so.waiting_for_command_ = false;
 			// blocking the area for some time to save AI from idle attempts to built there
@@ -4872,7 +4872,7 @@
 			// TODO(TiborB): how long it takes to build a port?
 			// I used 5 minutes
 			MapRegion<Area<FCoords>> mr(
-			   game().map(), Area<FCoords>(map.get_fcoords(so.ship->exp_port_spaces()->front()), 8));
+			   game().map(), Area<FCoords>(map.get_fcoords(so.ship->exp_port_spaces().front()), 8));
 			do {
 				BlockedField blocked2(
 				   map.get_fcoords(*(mr.location().field)), gametime + 5 * 60 * 1000);

=== modified file 'src/logic/map.cc'
--- src/logic/map.cc	2016-02-07 09:30:20 +0000
+++ src/logic/map.cc	2016-02-08 21:01:32 +0000
@@ -573,7 +573,7 @@
 	}
 }
 
-NodeCaps Map::get_max_nodecaps(const World& world, FCoords & fc) {
+NodeCaps Map::get_max_nodecaps(const World& world, const FCoords& fc) {
 	NodeCaps caps = _calc_nodecaps_pass1(world, fc, false);
 	caps = _calc_nodecaps_pass2(world, fc, false, caps);
 	return caps;

=== modified file 'src/logic/map.h'
--- src/logic/map.h	2016-02-05 20:07:10 +0000
+++ src/logic/map.h	2016-02-08 21:01:32 +0000
@@ -256,7 +256,7 @@
 	void set_scenario_player_closeable(PlayerNumber, bool);
 
 	/// \returns the maximum theoretical possible nodecaps (no blocking bobs, etc.)
-	NodeCaps get_max_nodecaps(const World& world, FCoords &);
+	NodeCaps get_max_nodecaps(const World& world, const FCoords &);
 
 	BaseImmovable * get_immovable(Coords) const;
 	uint32_t find_bobs

=== modified file 'src/logic/map_objects/tribes/ship.cc'
--- src/logic/map_objects/tribes/ship.cc	2016-02-08 08:01:21 +0000
+++ src/logic/map_objects/tribes/ship.cc	2016-02-08 21:01:32 +0000
@@ -49,6 +49,59 @@
 
 namespace Widelands {
 
+namespace  {
+
+/// Returns true if 'coord' is not occupied or onwned by 'player_number' and
+/// nothing stands there.
+bool can_support_port(const PlayerNumber player_number, const FCoords& coord) {
+	const PlayerNumber owner = coord.field->get_owned_by();
+	if (owner != neutral() && owner != player_number) {
+		return false;
+	}
+	BaseImmovable* baim = coord.field->get_immovable();
+	if (baim != nullptr && baim->descr().type() >= MapObjectType::FLAG) {
+		return false;
+	}
+	return true;
+}
+
+/// Returns true if a ship owned by 'player_number' can land and errect a port at 'coord'.
+bool can_build_port_here(const PlayerNumber player_number, const Map& map, const FCoords& coord) {
+	if (!can_support_port(player_number, coord)) {
+		return false;
+	}
+
+	// All fields of the port + their neighboring fields (for the border) must
+	// be conquerable without military influence.
+	Widelands::FCoords c[4];  //  Big buildings occupy 4 locations.
+	c[0] = coord;
+	map.get_ln(coord, &c[1]);
+	map.get_tln(coord, &c[2]);
+	map.get_trn(coord, &c[3]);
+	for (int i = 0; i < 4; ++i) {
+		MapRegion<Area<FCoords>> area(map, Area<FCoords>(c[i], 1));
+		do {
+			if (!can_support_port(player_number, area.location())) {
+				return false;
+			}
+		} while (area.advance(map));
+	}
+
+	// Also all areas around the flag must be conquerable and must not contain
+	// another flag already.
+	FCoords flag_position;
+	map.get_brn(coord, &flag_position);
+	MapRegion<Area<FCoords>> area(map, Area<FCoords>(flag_position, 1));
+	do {
+		if (!can_support_port(player_number, area.location())) {
+			return false;
+		}
+	} while (area.advance(map));
+	return true;
+}
+
+}  // namespace
+
 ShipDescr::ShipDescr(const std::string& init_descname, const LuaTable& table)
 	:
 	BobDescr(init_descname, MapObjectType::SHIP, MapObjectDescr::OwnerType::kTribe, table) {
@@ -323,115 +376,40 @@
 
 	if (m_ship_state == EXP_SCOUTING) {
 		// Check surrounding fields for port buildspaces
-		std::unique_ptr<std::list<Coords>> temp_port_buildspaces(new std::list<Coords>());
+		std::vector<Coords> temp_port_buildspaces;
 		MapRegion<Area<Coords>> mr(map, Area<Coords>(position, descr().vision_range()));
 		bool new_port_space = false;
 		do {
-			if (map.is_port_space(mr.location())) {
-				FCoords fc = map.get_fcoords(mr.location());
-
-				// Check whether the maximum theoretical possible NodeCap of the field is of the size
-				// big
-				// and whether it can theoretically be a port space
-				if ((map.get_max_nodecaps(game.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG ||
-				    map.find_portdock(fc).empty()) {
-					continue;
-				}
-
-				// NOTE This is the place to handle enemy territory and "clearing a port space from the
-				// enemy".
-				// NOTE There is a simple check for the current land owner to avoid placement of ports
-				// into enemy
-				// NOTE territory, as "clearing" is not yet implemented.
-				// NOTE further it checks, whether there is a Player_immovable on one of the fields.
-				// TODO(unknown): handle this more gracefully concering opposing players
-				PlayerNumber pn = get_owner()->player_number();
-				FCoords coord = fc;
-				bool invalid = false;
-				for (uint8_t step = 0; !invalid && step < 5; ++step) {
-					if (coord.field->get_owned_by() != neutral() && coord.field->get_owned_by() != pn) {
-						invalid = true;
-						continue;
-					}
-					BaseImmovable* baim = coord.field->get_immovable();
-					if (baim)
-						if (is_a(PlayerImmovable, baim)) {
-							invalid = true;
-							continue;
-						}
-
-					// Check all neighboured fields that will be used by the port
-					switch (step) {
-					case 0:
-						map.get_ln(fc, &coord);
-						break;
-					case 1:
-						map.get_tln(fc, &coord);
-						break;
-					case 2:
-						map.get_trn(fc, &coord);
-						break;
-					case 3:
-						// Flag coordinate
-						map.get_brn(fc, &coord);
-						break;
-					default:
-						break;
-					}
-				}
-				// Now check whether there is a flag in the surroundings of the flag position
-				FCoords neighb;
-				map.get_ln(coord, &neighb);
-				for (uint8_t step = 0; !invalid && step < 5; ++step) {
-					BaseImmovable* baim = neighb.field->get_immovable();
-					if (baim)
-						if (is_a(Flag, baim)) {
-							invalid = true;
-							continue;
-						}
-					// Check all neighboured fields but not the one already checked for a
-					// PlayerImmovable.
-					switch (step) {
-					case 0:
-						map.get_bln(coord, &neighb);
-						break;
-					case 1:
-						map.get_brn(coord, &neighb);
-						break;
-					case 2:
-						map.get_rn(coord, &neighb);
-						break;
-					case 3:
-						map.get_trn(coord, &neighb);
-						break;
-					default:
-						break;
-					}
-				}
-				if (invalid)
-					continue;
-
-				bool pbs_saved = false;
-				for (std::list<Coords>::const_iterator it =
-				        m_expedition->seen_port_buildspaces->begin();
-				     it != m_expedition->seen_port_buildspaces->end() && !pbs_saved;
-				     ++it) {
-					// Check if the ship knows this port space already from its last check
-					if (*it == mr.location()) {
-						temp_port_buildspaces->push_back(mr.location());
-						pbs_saved = true;
-					}
-				}
-				if (!pbs_saved) {
-					new_port_space = true;
-					temp_port_buildspaces->push_front(mr.location());
-				}
+			if (!map.is_port_space(mr.location())) {
+				continue;
+			}
+
+			const FCoords fc = map.get_fcoords(mr.location());
+
+			// Check whether the maximum theoretical possible NodeCap of the field
+			// is of the size big and whether it can theoretically be a port space
+			if ((map.get_max_nodecaps(game.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG ||
+			    map.find_portdock(fc).empty()) {
+				continue;
+			}
+
+			if (!can_build_port_here(get_owner()->player_number(), map, fc)) {
+				continue;
+			}
+
+			// Check if the ship knows this port space already from its last check
+			if (std::find(m_expedition->seen_port_buildspaces.begin(),
+			              m_expedition->seen_port_buildspaces.end(),
+			              mr.location()) != m_expedition->seen_port_buildspaces.end()) {
+					temp_port_buildspaces.push_back(mr.location());
+			} else {
+				new_port_space = true;
+				temp_port_buildspaces.insert(temp_port_buildspaces.begin(), mr.location());
 			}
 		} while (mr.advance(map));
 
 		if (new_port_space) {
 			m_ship_state = EXP_FOUNDPORTSPACE;
-			// Send a message to the player, that a new port space was found
 			send_message(
 						game,
 						_("Port Space"),
@@ -439,7 +417,7 @@
 						_("An expedition ship found a new port build space."),
 						"images/wui/editor/fsel_editor_set_port_space.png");
 		}
-		m_expedition->seen_port_buildspaces.swap(temp_port_buildspaces);
+		m_expedition->seen_port_buildspaces = temp_port_buildspaces;
 		if (new_port_space) {
 			Notifications::publish(
 			   NoteShipMessage(this, NoteShipMessage::Message::kWaitingForCommand));
@@ -631,9 +609,8 @@
 		}
 	}
 	case EXP_COLONIZING: {
-		assert(m_expedition->seen_port_buildspaces && !m_expedition->seen_port_buildspaces->empty());
-		BaseImmovable* baim =
-		   game.map()[m_expedition->seen_port_buildspaces->front()].get_immovable();
+		assert(!m_expedition->seen_port_buildspaces.empty());
+		BaseImmovable* baim = game.map()[m_expedition->seen_port_buildspaces.front()].get_immovable();
 		if (baim) {
 			upcast(ConstructionSite, cs, baim);
 
@@ -832,7 +809,7 @@
 	m_ship_state = EXP_WAITING;
 	// Initialize a new, yet empty expedition
 	m_expedition.reset(new Expedition());
-	m_expedition->seen_port_buildspaces.reset(new std::list<Coords>());
+	m_expedition->seen_port_buildspaces.clear();
 	m_expedition->island_exploration = false;
 	m_expedition->scouting_direction = WalkingDir::IDLE;
 	m_expedition->exploration_start = Coords(0, 0);
@@ -1049,10 +1026,10 @@
 		 m_ship_state == EXP_FOUNDPORTSPACE || m_ship_state == EXP_COLONIZING) {
 		m_expedition.reset(new Expedition());
 		// Currently seen port build spaces
-		m_expedition->seen_port_buildspaces.reset(new std::list<Coords>());
+		m_expedition->seen_port_buildspaces.clear();
 		uint8_t numofports = fr.unsigned_8();
 		for (uint8_t i = 0; i < numofports; ++i)
-			m_expedition->seen_port_buildspaces->push_back(read_coords_32(&fr));
+			m_expedition->seen_port_buildspaces.push_back(read_coords_32(&fr));
 		// Swimability of the directions
 		for (uint8_t i = 0; i < LAST_DIRECTION; ++i)
 			m_expedition->swimable[i] = (fr.unsigned_8() == 1);
@@ -1174,12 +1151,9 @@
 	// expedition specific data
 	if (state_is_expedition()) {
 		// currently seen port buildspaces
-		assert(m_expedition->seen_port_buildspaces);
-		fw.unsigned_8(m_expedition->seen_port_buildspaces->size());
-		for (std::list<Coords>::const_iterator it = m_expedition->seen_port_buildspaces->begin();
-		     it != m_expedition->seen_port_buildspaces->end();
-		     ++it) {
-			write_coords_32(&fw, *it);
+		fw.unsigned_8(m_expedition->seen_port_buildspaces.size());
+		for (const Coords& coords : m_expedition->seen_port_buildspaces) {
+			write_coords_32(&fw, coords);
 		}
 		// swimability of the directions
 		for (uint8_t i = 0; i < LAST_DIRECTION; ++i)

=== modified file 'src/logic/map_objects/tribes/ship.h'
--- src/logic/map_objects/tribes/ship.h	2016-02-07 06:10:47 +0000
+++ src/logic/map_objects/tribes/ship.h	2016-02-08 21:01:32 +0000
@@ -197,10 +197,8 @@
 	}
 
 	/// \returns (in expedition mode only!) the list of currently seen port build spaces
-	const std::list<Coords>* exp_port_spaces() {
-		if (!m_expedition)
-			return nullptr;
-		return m_expedition->seen_port_buildspaces.get();
+	const std::vector<Coords>& exp_port_spaces() {
+		return m_expedition->seen_port_buildspaces;
 	}
 
 	void exp_scouting_direction(Game &, WalkingDir);
@@ -254,7 +252,7 @@
 	std::string m_shipname;
 
 	struct Expedition {
-		std::unique_ptr<std::list<Coords> > seen_port_buildspaces;
+		std::vector<Coords> seen_port_buildspaces;
 		bool swimable[LAST_DIRECTION];
 		bool island_exploration;
 		WalkingDir scouting_direction;

=== modified file 'src/logic/map_objects/tribes/warehouse.cc'
--- src/logic/map_objects/tribes/warehouse.cc	2016-02-07 06:10:47 +0000
+++ src/logic/map_objects/tribes/warehouse.cc	2016-02-08 21:01:32 +0000
@@ -446,7 +446,8 @@
 
 		m_next_stock_remove_act = schedule_act(*game, 4000);
 
-		log("Message: adding (wh) (%s) %i \n", to_string(descr().type()).c_str(), player.player_number());
+		log("Message: adding %s for player %i at (%d, %d)\n", to_string(descr().type()).c_str(),
+		    player.player_number(), m_position.x, m_position.y);
 
 		if (descr().get_isport()) {
 			send_message
@@ -478,12 +479,11 @@
 		}
 	}
 
-	if (uint32_t const conquer_radius = descr().get_conquers())
-		egbase.conquer_area
-			(PlayerArea<Area<FCoords> >
-			 	(player.player_number(),
-			 	 Area<FCoords>
-			 	 	(egbase.map().get_fcoords(get_position()), conquer_radius)));
+	if (uint32_t const conquer_radius = descr().get_conquers()) {
+		egbase.conquer_area(PlayerArea<Area<FCoords>>(
+		   player.player_number(),
+		   Area<FCoords>(egbase.map().get_fcoords(get_position()), conquer_radius)));
+	}
 
 	if (descr().get_isport()) {
 		init_portdock(egbase);
@@ -495,10 +495,7 @@
 			get_position().y);
 		}
 	}
-
-	//this is default
 	cleanup_in_progress_ = false;
-
 }
 
 void Warehouse::init_containers(Player& player) {
@@ -580,7 +577,6 @@
 
 /// Destroy the warehouse.
 void Warehouse::cleanup(EditorGameBase& egbase) {
-
 	// if this is a port, it will remove also portdock.
 	// But portdock must know that it should not try to recreate itself
 	cleanup_in_progress_ = true;

=== modified file 'src/logic/player.cc'
--- src/logic/player.cc	2016-01-28 05:24:34 +0000
+++ src/logic/player.cc	2016-02-08 21:01:32 +0000
@@ -535,19 +535,25 @@
 	(Coords const location, DescriptionIndex b_idx,
 	 const BuildingDescr::FormerBuildings & former_buildings)
 {
-	Map & map = egbase().map();
+	EditorGameBase& eg = egbase();
+	Map & map = eg.map();
+	const Tribes& tribes = eg.tribes();
+	const PlayerNumber pn = player_number();
+
 	if (!former_buildings.empty()) {
 		DescriptionIndex idx = former_buildings.back();
-		const BuildingDescr * descr = egbase().tribes().get_building_descr(idx);
-		terraform_for_building(egbase(), player_number(), location, descr);
+		const BuildingDescr * descr = tribes.get_building_descr(idx);
+		terraform_for_building(eg, pn, location, descr);
 	}
 	FCoords flag_loc;
 	map.get_brn(map.get_fcoords(location), &flag_loc);
 	force_flag(flag_loc);
 
-	return
-		egbase().warp_constructionsite
-			(map.get_fcoords(location), m_plnum, b_idx, false, former_buildings);
+	terraform_for_building(
+	   eg, pn, location, tribes.get_building_descr(b_idx));
+
+	return eg.warp_constructionsite(
+	   map.get_fcoords(location), m_plnum, b_idx, false, former_buildings);
 }
 
 

=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc	2016-01-31 15:31:00 +0000
+++ src/scripting/lua_map.cc	2016-02-08 21:01:32 +0000
@@ -4113,7 +4113,7 @@
 	Ship* ship =  get(L, get_egbase(L));
 	if (ship->get_ship_state() == Widelands::Ship::EXP_FOUNDPORTSPACE) {
 		if (upcast(Game, game, &get_egbase(L))) {
-			game->send_player_ship_construct_port(*ship, ship->exp_port_spaces()->front());
+			game->send_player_ship_construct_port(*ship, ship->exp_port_spaces().front());
 			return 1;
 		}
 	}

=== modified file 'src/wui/shipwindow.cc'
--- src/wui/shipwindow.cc	2016-01-29 08:37:22 +0000
+++ src/wui/shipwindow.cc	2016-02-08 21:01:32 +0000
@@ -321,9 +321,9 @@
 
 /// Constructs a port at the port build space in vision range
 void ShipWindow::act_construct_port() {
-	if (!m_ship.exp_port_spaces() || m_ship.exp_port_spaces()->empty())
+	if (m_ship.exp_port_spaces().empty())
 		return;
-	m_igbase.game().send_player_ship_construct_port(m_ship, m_ship.exp_port_spaces()->front());
+	m_igbase.game().send_player_ship_construct_port(m_ship, m_ship.exp_port_spaces().front());
 }
 
 /// Explores the island cw or ccw

=== added directory 'test/maps/port_space.wmf'
=== added directory 'test/maps/port_space.wmf/binary'
=== added file 'test/maps/port_space.wmf/binary/heights'
Binary files test/maps/port_space.wmf/binary/heights	1970-01-01 00:00:00 +0000 and test/maps/port_space.wmf/binary/heights	2016-02-08 21:01:32 +0000 differ
=== added file 'test/maps/port_space.wmf/binary/mapobjects'
Binary files test/maps/port_space.wmf/binary/mapobjects	1970-01-01 00:00:00 +0000 and test/maps/port_space.wmf/binary/mapobjects	2016-02-08 21:01:32 +0000 differ
=== added file 'test/maps/port_space.wmf/binary/resource'
Binary files test/maps/port_space.wmf/binary/resource	1970-01-01 00:00:00 +0000 and test/maps/port_space.wmf/binary/resource	2016-02-08 21:01:32 +0000 differ
=== added file 'test/maps/port_space.wmf/binary/terrain'
Binary files test/maps/port_space.wmf/binary/terrain	1970-01-01 00:00:00 +0000 and test/maps/port_space.wmf/binary/terrain	2016-02-08 21:01:32 +0000 differ
=== added file 'test/maps/port_space.wmf/elemental'
--- test/maps/port_space.wmf/elemental	1970-01-01 00:00:00 +0000
+++ test/maps/port_space.wmf/elemental	2016-02-08 21:01:32 +0000
@@ -0,0 +1,12 @@
+# Automatically created by Widelands bzr7801[trunk] (Debug)
+
+[global]
+packet_version="1"
+map_w="64"
+map_h="64"
+nr_players="2"
+name="port_space"
+author="Unknown"
+descr="No description defined"
+hint=
+tags="artifacts,seafaring"

=== added file 'test/maps/port_space.wmf/extra_data'
--- test/maps/port_space.wmf/extra_data	1970-01-01 00:00:00 +0000
+++ test/maps/port_space.wmf/extra_data	2016-02-08 21:01:32 +0000
@@ -0,0 +1,4 @@
+# Automatically created by Widelands bzr7801[trunk] (Debug)
+
+[global]
+packet_version="1"

=== added file 'test/maps/port_space.wmf/minimap.png'
Binary files test/maps/port_space.wmf/minimap.png	1970-01-01 00:00:00 +0000 and test/maps/port_space.wmf/minimap.png	2016-02-08 21:01:32 +0000 differ
=== added file 'test/maps/port_space.wmf/objective'
--- test/maps/port_space.wmf/objective	1970-01-01 00:00:00 +0000
+++ test/maps/port_space.wmf/objective	2016-02-08 21:01:32 +0000
@@ -0,0 +1,4 @@
+# Automatically created by Widelands bzr7801[trunk] (Debug)
+
+[global]
+packet_version="2"

=== added file 'test/maps/port_space.wmf/player_names'
--- test/maps/port_space.wmf/player_names	1970-01-01 00:00:00 +0000
+++ test/maps/port_space.wmf/player_names	2016-02-08 21:01:32 +0000
@@ -0,0 +1,16 @@
+# Automatically created by Widelands bzr7801[trunk] (Debug)
+
+[global]
+packet_version="2"
+
+[player_1]
+name="Player 1"
+tribe="barbarians"
+ai="very_weak"
+closeable="false"
+
+[player_2]
+name="Player 2"
+tribe="barbarians"
+ai="very_weak"
+closeable="false"

=== added file 'test/maps/port_space.wmf/player_position'
--- test/maps/port_space.wmf/player_position	1970-01-01 00:00:00 +0000
+++ test/maps/port_space.wmf/player_position	2016-02-08 21:01:32 +0000
@@ -0,0 +1,6 @@
+# Automatically created by Widelands bzr7801[trunk] (Debug)
+
+[global]
+packet_version="2"
+player_1="58 13"
+player_2="21 8"

=== added file 'test/maps/port_space.wmf/port_spaces'
--- test/maps/port_space.wmf/port_spaces	1970-01-01 00:00:00 +0000
+++ test/maps/port_space.wmf/port_spaces	2016-02-08 21:01:32 +0000
@@ -0,0 +1,9 @@
+# Automatically created by Widelands bzr7801[trunk] (Debug)
+
+[global]
+packet_version="1"
+number_of_port_spaces="2"
+
+[port_spaces]
+0="7 10"
+1="13 14"

=== added directory 'test/maps/port_space.wmf/scripting'
=== added file 'test/maps/port_space.wmf/scripting/init.lua'
--- test/maps/port_space.wmf/scripting/init.lua	1970-01-01 00:00:00 +0000
+++ test/maps/port_space.wmf/scripting/init.lua	2016-02-08 21:01:32 +0000
@@ -0,0 +1,87 @@
+include "scripting/coroutine.lua"
+include "scripting/infrastructure.lua"
+include "scripting/lunit.lua"
+include "scripting/ui.lua"
+
+game = wl.Game()
+map = game.map
+p1 = game.players[1]
+p2 = game.players[2]
+
+function archive_messages()
+   for idx, m in ipairs(p1.inbox) do
+      m.status = "archived"
+   end
+end
+
+function wait_for_message(title)
+   archive_messages()
+   sleep(5000)
+   local old_speed = game.desired_speed
+   game.desired_speed = 100 * 1000
+   sleep(5000)
+   while true do
+      while #p1.inbox == 0 do
+         sleep(313)
+      end
+      local message_title = p1.inbox[1].title
+      archive_messages()
+      if title == message_title then
+         break
+      end
+   end
+   game.desired_speed = old_speed
+   sleep(5000)
+end
+
+function create_infrastructure(tower_x, tower_y)
+   p1:allow_workers("all")
+   p1.see_all = true
+
+   prefilled_buildings(p2,
+      { "barbarians_headquarters", 40, 13 },
+      { "barbarians_tower", tower_x, tower_y,
+        soldiers = { [{0,0,0,0}] = 1 },
+      }
+   )
+
+   prefilled_buildings(p1,
+      { "barbarians_headquarters", 21, 8,
+         wares = {
+            blackwood = 100,
+            grout = 100,
+            iron = 100,
+            granite = 100,
+            thatch_reed = 100,
+            log = 100,
+         },
+         workers = {
+            barbarians_builder = 1,
+         },
+      },
+      { "barbarians_port", 13, 14,
+         wares = {
+            blackwood = 100,
+            grout = 100,
+            iron = 100,
+            granite = 100,
+            thatch_reed = 100,
+            log = 100,
+            gold = 100,
+         },
+         workers = {
+            barbarians_builder = 1,
+         },
+      }
+   )
+   local ship = p1:place_ship(map:get_field(9, 13))
+
+   local port = map:get_field(13, 14).immovable
+
+   game.desired_speed = 100 * 1000
+   port:start_expedition()
+   wait_for_message("Expedition")
+   ship.scouting_direction = "nw"
+
+   return ship
+end

=== added file 'test/maps/port_space.wmf/scripting/test_portfield_barely_unowned.lua'
--- test/maps/port_space.wmf/scripting/test_portfield_barely_unowned.lua	1970-01-01 00:00:00 +0000
+++ test/maps/port_space.wmf/scripting/test_portfield_barely_unowned.lua	2016-02-08 21:01:32 +0000
@@ -0,0 +1,8 @@
+run(function()
+   --  This places to tower so that the port just fits the space.
+   local ship = create_infrastructure(60, 10)
+   game.desired_speed = 1000
+   wait_for_message("Port Space")
+   print("# All Tests passed.")
+   wl.ui.MapView():close()
+end)

=== added file 'test/maps/port_space.wmf/scripting/test_portfield_neighbour_owned_by_p2.lua'
--- test/maps/port_space.wmf/scripting/test_portfield_neighbour_owned_by_p2.lua	1970-01-01 00:00:00 +0000
+++ test/maps/port_space.wmf/scripting/test_portfield_neighbour_owned_by_p2.lua	2016-02-08 21:01:32 +0000
@@ -0,0 +1,8 @@
+run(function()
+   -- This places to tower so that bug 1542703 triggered. Now, we do not allow
+   -- a portspace.
+   local ship = create_infrastructure(61, 10)
+   wait_for_message("Land Ahoy!")
+   print("# All Tests passed.")
+   wl.ui.MapView():close()
+end)

=== added file 'test/maps/port_space.wmf/scripting/test_portfield_owned_by_p2.lua'
--- test/maps/port_space.wmf/scripting/test_portfield_owned_by_p2.lua	1970-01-01 00:00:00 +0000
+++ test/maps/port_space.wmf/scripting/test_portfield_owned_by_p2.lua	2016-02-08 21:01:32 +0000
@@ -0,0 +1,8 @@
+run(function()
+   -- This places to tower so that the full island including the port space is
+   -- clearly owned by player1, no chance to build a port for p2.
+   local ship = create_infrastructure(63, 10)
+   wait_for_message("Land Ahoy!")
+   print("# All Tests passed.")
+   wl.ui.MapView():close()
+end)

=== added file 'test/maps/port_space.wmf/version'
--- test/maps/port_space.wmf/version	1970-01-01 00:00:00 +0000
+++ test/maps/port_space.wmf/version	2016-02-08 21:01:32 +0000
@@ -0,0 +1,11 @@
+# Automatically created by Widelands bzr7801[trunk] (Debug)
+
+[global]
+map_source_url=
+map_release=
+map_creator_version="bzr7801[trunk]"
+map_version_major="0"
+map_version_minor="1"
+map_version_timestamp="1454877347"
+packet_version="1"
+packet_compatibility="1"


References