← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1611323 into lp:widelands

 

TiborB has proposed merging lp:~widelands-dev/widelands/bug-1611323 into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1611323 in widelands: "ships can be built in non-floating spaces (shipyard)"
  https://bugs.launchpad.net/widelands/+bug/1611323

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1611323/+merge/315845

FindNodeShore now looks for more than one swimmable node reachable by sea from the current node (=shore). I used number 10 - but can be changed, but dont go too high - to make sure the sea is big enough.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1611323 into lp:widelands.
=== modified file 'src/logic/findnode.cc'
--- src/logic/findnode.cc	2017-01-25 18:55:59 +0000
+++ src/logic/findnode.cc	2017-01-28 20:00:13 +0000
@@ -129,14 +129,45 @@
 	return false;
 }
 
-bool FindNodeShore::accept(const Map& map, const FCoords& coord) const {
-	if (!(coord.field->nodecaps() & MOVECAPS_WALK))
+bool FindNodeShore::accept(const Map& map, const FCoords& coords) const {
+	if (!(coords.field->nodecaps() & MOVECAPS_WALK))
 		return false;
 
-	for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
-		FCoords neighb = map.get_neighbour(coord, dir);
-		if (neighb.field->nodecaps() & MOVECAPS_SWIM)
-			return true;
+	// Vector of fields whose neighbours are to be checked, starting with current one
+	std::vector<FCoords> nodes_to_process = {coords};
+	// Set of nodes that that are swimmable & and achievable by swimming
+	// We use hashes here
+	std::set<uint32_t> accepted_nodes = {};
+	// just not to check the same node twice
+	std::set<uint32_t> rejected_nodes = {};
+
+	// Continue untill all nodes to process are processed, or we found sufficient number of nodes
+	while (!nodes_to_process.empty() && accepted_nodes.size() < min_fields) {
+		FCoords cur = nodes_to_process.back();
+		nodes_to_process.pop_back();
+
+		// Now test all neighbours
+		for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
+			FCoords neighb = map.get_neighbour(cur, dir);
+			if (accepted_nodes.count(neighb.hash()) > 0 || rejected_nodes.count(neighb.hash()) > 0) {
+				// We already processed this node
+				continue;
+			}
+
+			if (neighb.field->nodecaps() & MOVECAPS_SWIM) {
+				// This is new node, that is swimmable
+				accepted_nodes.insert(neighb.hash());
+				// But also neighbours must be processed in next iterations
+				nodes_to_process.push_back(neighb);
+			} else {
+				rejected_nodes.insert(neighb.hash());
+			}
+		}
+	}
+
+	// We iterated over all reachanble fields or we found sufficient number of swimmable nodes
+	if (accepted_nodes.size() >= min_fields) {
+		return true;
 	}
 
 	return false;

=== modified file 'src/logic/findnode.h'
--- src/logic/findnode.h	2017-01-25 18:55:59 +0000
+++ src/logic/findnode.h	2017-01-28 20:00:13 +0000
@@ -186,13 +186,16 @@
 };
 
 /// Accepts a node if it is a shore node in the sense that it is walkable
-/// and has a neighbouring field that is swimmable
+/// and has at least one neighbouring field that is swimmable
 struct FindNodeShore {
-	FindNodeShore() {
+	FindNodeShore(uint16_t f = 1) : min_fields(f) {
 	}
 
 	bool accept(const Map&, const FCoords&) const;
+
+private:
+	// Minimal number of reachable swimmable fields. 1 is minimum for this to be considered "shore"
+	uint16_t min_fields;
 };
 }
-
 #endif  // end of include guard: WL_LOGIC_FINDNODE_H

=== modified file 'src/logic/map_objects/tribes/production_program.cc'
--- src/logic/map_objects/tribes/production_program.cc	2017-01-28 14:53:28 +0000
+++ src/logic/map_objects/tribes/production_program.cc	2017-01-28 20:00:13 +0000
@@ -1502,7 +1502,8 @@
 	std::vector<Coords> fields;
 	Map& map = game.map();
 	FindNodeAnd fna;
-	fna.add(FindNodeShore());
+	// 10 is custom value to make sure the "water" is at least 10 nodes big
+	fna.add(FindNodeShore(10));
 	fna.add(FindNodeImmovableSize(FindNodeImmovableSize::sizeNone));
 	if (map.find_reachable_fields(area, &fields, cstep, fna)) {
 		// Testing received fields to get one with less immovables nearby


Follow ups