1 /*
2  * Copyright (C) 2008-2020 by the Widelands Development Team
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  *
18  */
19 
20 #ifndef WL_LOGIC_MAP_OBJECTS_FINDNODE_H
21 #define WL_LOGIC_MAP_OBJECTS_FINDNODE_H
22 
23 #include "logic/widelands.h"
24 
25 namespace Widelands {
26 
27 enum class AnimalBreedable { kDefault, kAnimalFull };
28 
29 class EditorGameBase;
30 struct FCoords;
31 
32 struct FindNode {
33 private:
34 	struct BaseCapsule {
BaseCapsuleFindNode::BaseCapsule35 		BaseCapsule() : refcount(1) {
36 		}
~BaseCapsuleFindNode::BaseCapsule37 		virtual ~BaseCapsule() {
38 		}
39 
addrefFindNode::BaseCapsule40 		void addref() {
41 			++refcount;
42 		}
derefFindNode::BaseCapsule43 		void deref() {
44 			if (--refcount == 0)
45 				delete this;
46 		}
47 		virtual bool accept(const EditorGameBase&, const FCoords& coord) const = 0;
48 
49 		int refcount;
50 	};
51 	template <typename T> struct Capsule : public BaseCapsule {
CapsuleFindNode::Capsule52 		explicit Capsule(const T& init_op) : op(init_op) {
53 		}
acceptFindNode::Capsule54 		bool accept(const EditorGameBase& map, const FCoords& coord) const override {
55 			return op.accept(map, coord);
56 		}
57 
58 		const T op;
59 	};
60 
61 	BaseCapsule* capsule;
62 
63 public:
FindNodeFindNode64 	explicit FindNode(const FindNode& o) {
65 		capsule = o.capsule;
66 		capsule->addref();
67 	}
~FindNodeFindNode68 	~FindNode() {
69 		capsule->deref();
70 		capsule = nullptr;
71 	}
72 	FindNode& operator=(const FindNode& o) {
73 		capsule->deref();
74 		capsule = o.capsule;
75 		capsule->addref();
76 		return *this;
77 	}
78 
FindNodeFindNode79 	template <typename T> FindNode(const T& op) {
80 		capsule = new Capsule<T>(op);
81 	}
82 
83 	// Return true if this node should be returned by find_fields()
acceptFindNode84 	bool accept(const EditorGameBase& map, const FCoords& coord) const {
85 		return capsule->accept(map, coord);
86 	}
87 };
88 
89 struct FindNodeCaps {
FindNodeCapsFindNodeCaps90 	explicit FindNodeCaps(uint8_t init_mincaps) : mincaps(init_mincaps) {
91 	}
92 
93 	bool accept(const EditorGameBase&, const FCoords&) const;
94 
95 private:
96 	uint8_t mincaps;
97 };
98 
99 /// Accepts a node if it is accepted by all subfunctors.
100 struct FindNodeAnd {
FindNodeAndFindNodeAnd101 	FindNodeAnd() {
102 	}
103 
104 	void add(const FindNode&, bool negate = false);
105 
106 	bool accept(const EditorGameBase&, const FCoords&) const;
107 
108 private:
109 	struct Subfunctor {
110 		bool negate;
111 		FindNode findfield;
112 
113 		Subfunctor(const FindNode&, bool init_negate);
114 	};
115 
116 	std::vector<Subfunctor> subfunctors;
117 };
118 
119 /// Accepts a node based on what can be built there.
120 struct FindNodeSize {
121 	enum Size {
122 		sizeAny = 0,  //  any field not occupied by a robust immovable
123 		sizeBuild,    //  any field we can build on (flag or building)
124 		sizeSmall,    //  at least small size
125 		sizeMedium,
126 		sizeBig,
127 		sizeMine,  //  can build a mine on this field
128 		sizePort,  //  can build a port on this field
129 		sizeSwim   // coast
130 	};
131 
FindNodeSizeFindNodeSize132 	explicit FindNodeSize(Size init_size) : size(init_size) {
133 	}
134 
135 	bool accept(const EditorGameBase&, const FCoords&) const;
136 
137 private:
138 	Size size;
139 };
140 
141 /// Accepts a node based on the size of the immovable there (if any).
142 struct FindNodeImmovableSize {
143 	enum { sizeNone = 1 << 0, sizeSmall = 1 << 1, sizeMedium = 1 << 2, sizeBig = 1 << 3 };
144 
FindNodeImmovableSizeFindNodeImmovableSize145 	explicit FindNodeImmovableSize(uint32_t init_sizes) : sizes(init_sizes) {
146 	}
147 
148 	bool accept(const EditorGameBase&, const FCoords&) const;
149 
150 private:
151 	uint32_t sizes;
152 };
153 
154 /// Accepts a node if it has an immovable with a given attribute.
155 struct FindNodeImmovableAttribute {
FindNodeImmovableAttributeFindNodeImmovableAttribute156 	explicit FindNodeImmovableAttribute(uint32_t attrib) : attribute(attrib) {
157 	}
158 
159 	bool accept(const EditorGameBase&, const FCoords&) const;
160 
161 private:
162 	uint32_t attribute;
163 };
164 
165 /// Accepts a node if it has at least one of the given resource.
166 struct FindNodeResource {
FindNodeResourceFindNodeResource167 	explicit FindNodeResource(DescriptionIndex res) : resource(res) {
168 	}
169 
170 	bool accept(const EditorGameBase&, const FCoords&) const;
171 
172 private:
173 	DescriptionIndex resource;
174 };
175 
176 /// Accepts a node if it has the given resource type and remaining capacity.
177 /// If 'br' == AnimalBreedable::kAnimalFull, only accepts the node if it is full
178 struct FindNodeResourceBreedable {
179 	explicit FindNodeResourceBreedable(DescriptionIndex res,
180 	                                   AnimalBreedable br = AnimalBreedable::kDefault)
resourceFindNodeResourceBreedable181 	   : resource(res), strictness(br) {
182 	}
183 
184 	bool accept(const EditorGameBase&, const FCoords&) const;
185 
186 private:
187 	DescriptionIndex resource;
188 	AnimalBreedable strictness;
189 };
190 
191 /// Accepts a node where at least 1 adjacent triangle has enhancable terrain
192 struct FindNodeTerraform {
193 	FindNodeTerraform() = default;
194 	bool accept(const EditorGameBase&, const FCoords&) const;
195 };
196 
197 /// Accepts a node if it is a shore node in the sense that it is walkable
198 /// and has at least one neighbouring field that is swimmable
199 struct FindNodeShore {
min_fieldsFindNodeShore200 	explicit FindNodeShore(uint16_t f = 1) : min_fields(f) {
201 	}
202 
203 	bool accept(const EditorGameBase&, const FCoords&) const;
204 
205 private:
206 	// Minimal number of reachable swimmable fields. 1 is minimum for this to be considered "shore"
207 	uint16_t min_fields;
208 };
209 }  // namespace Widelands
210 #endif  // end of include guard: WL_LOGIC_FINDNODE_H
211