widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #09535
[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