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_TRIBES_REQUIREMENTS_H 21 #define WL_LOGIC_MAP_OBJECTS_TRIBES_REQUIREMENTS_H 22 23 #include <climits> 24 #include <map> 25 #include <memory> 26 #include <vector> 27 28 #include "logic/map_objects/tribes/training_attribute.h" 29 30 class FileRead; 31 class FileWrite; 32 33 namespace Widelands { 34 35 class MapObject; 36 class EditorGameBase; 37 class MapObjectLoader; 38 struct MapObjectSaver; 39 40 struct RequirementsStorage; 41 42 /** 43 * Requirements can be attached to Requests. 44 * 45 * Requirements are matched to a \ref MapObject 's \ref TrainingAttribute as 46 * returned by \ref MapObject::get_training_attribute . 47 */ 48 struct Requirements { 49 private: 50 struct BaseCapsule { ~BaseCapsuleRequirements::BaseCapsule51 virtual ~BaseCapsule() { 52 } 53 54 virtual bool check(const MapObject&) const = 0; 55 virtual void write(FileWrite&, EditorGameBase&, MapObjectSaver&) const = 0; 56 virtual const RequirementsStorage& storage() const = 0; 57 }; 58 59 template <typename T> struct Capsule : public BaseCapsule { CapsuleRequirements::Capsule60 explicit Capsule(const T& init_m) : m(init_m) { 61 } 62 checkRequirements::Capsule63 bool check(const MapObject& obj) const override { 64 return m.check(obj); 65 } 66 writeRequirements::Capsule67 void write(FileWrite& fw, EditorGameBase& egbase, MapObjectSaver& mos) const override { 68 m.write(fw, egbase, mos); 69 } 70 storageRequirements::Capsule71 const RequirementsStorage& storage() const override { 72 return T::storage; 73 } 74 75 T m; 76 }; 77 78 public: RequirementsRequirements79 Requirements() { 80 } 81 RequirementsRequirements82 template <typename T> Requirements(const T& req) : m(new Capsule<T>(req)) { 83 } 84 85 /** 86 * \return \c true if the object satisfies the requirements. 87 */ 88 bool check(const MapObject&) const; 89 90 // For Save/Load Games 91 void read(FileRead&, EditorGameBase&, MapObjectLoader&); 92 void write(FileWrite&, EditorGameBase&, MapObjectSaver&) const; 93 94 private: 95 std::shared_ptr<BaseCapsule> m; 96 }; 97 98 /** 99 * On-disk IDs for certain requirements. 100 * 101 * Only add enums at the end, and make their value explicit. 102 */ 103 enum { 104 requirementIdOr = 1, 105 requirementIdAnd = 2, 106 requirementIdAttribute = 3, 107 }; 108 109 /** 110 * Factory-like system for requirement loading from files. 111 */ 112 struct RequirementsStorage { 113 using Reader = Requirements (*)(FileRead&, EditorGameBase&, MapObjectLoader&); 114 115 RequirementsStorage(uint32_t id, Reader reader); 116 uint32_t id() const; 117 118 static Requirements read(FileRead&, EditorGameBase&, MapObjectLoader&); 119 120 private: 121 using StorageMap = std::map<uint32_t, RequirementsStorage*>; 122 123 uint32_t id_; 124 Reader reader_; 125 126 static StorageMap& storageMap(); 127 }; 128 129 /** 130 * Require that at least one of the sub-requirements added with \ref add() 131 * is met. Defaults to \c false if no sub-requirement is added. 132 */ 133 struct RequireOr { 134 void add(const Requirements&); 135 136 bool check(const MapObject&) const; 137 void write(FileWrite&, EditorGameBase& egbase, MapObjectSaver&) const; 138 139 static const RequirementsStorage storage; 140 141 private: 142 std::vector<Requirements> m; 143 }; 144 145 /** 146 * Require that all sub-requirements added \ref add() are met. 147 * Defaults to \c true if no sub-requirement is added. 148 */ 149 struct RequireAnd { 150 void add(const Requirements&); 151 152 bool check(const MapObject&) const; 153 void write(FileWrite&, EditorGameBase& egbase, MapObjectSaver&) const; 154 155 static const RequirementsStorage storage; 156 157 private: 158 std::vector<Requirements> m; 159 }; 160 161 /** 162 * Require that a \ref TrainingAttribute lies in the given, inclusive, range. 163 */ 164 struct RequireAttribute { RequireAttributeRequireAttribute165 RequireAttribute(TrainingAttribute const init_at, int32_t const init_min, int32_t const init_max) 166 : at(init_at), min(init_min), max(init_max) { 167 } 168 RequireAttributeRequireAttribute169 RequireAttribute() : at(TrainingAttribute::kTotal), min(SHRT_MIN), max(SHRT_MAX) { 170 } 171 bool check(const MapObject&) const; 172 void write(FileWrite&, EditorGameBase& egbase, MapObjectSaver&) const; 173 174 static const RequirementsStorage storage; 175 get_minRequireAttribute176 int32_t get_min() const { 177 return min; 178 } get_maxRequireAttribute179 int32_t get_max() const { 180 return max; 181 } 182 183 private: 184 TrainingAttribute at; 185 int32_t min; 186 int32_t max; 187 }; 188 } // namespace Widelands 189 190 #endif // end of include guard: WL_LOGIC_MAP_OBJECTS_TRIBES_REQUIREMENTS_H 191