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