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_CHECKSTEP_H 21 #define WL_LOGIC_MAP_OBJECTS_CHECKSTEP_H 22 23 #include <memory> 24 #include <set> 25 #include <vector> 26 27 #include "logic/widelands_geometry.h" 28 29 namespace Widelands { 30 31 class EditorGameBase; 32 class Map; 33 class Player; 34 35 struct CheckStep { 36 enum StepId { 37 stepNormal, // normal step treatment 38 stepFirst, // first step of a path 39 stepLast, // last step of a path 40 }; 41 42 private: 43 struct BaseCapsule { ~BaseCapsuleCheckStep::BaseCapsule44 virtual ~BaseCapsule() { 45 } 46 virtual bool allowed( 47 const Map&, const FCoords& start, const FCoords& end, int32_t dir, StepId id) const = 0; 48 virtual bool reachable_dest(const Map&, const FCoords& dest) const = 0; 49 }; 50 template <typename T> struct Capsule : public BaseCapsule { CapsuleCheckStep::Capsule51 Capsule(const T& init_op) : op(init_op) { 52 } 53 allowedCheckStep::Capsule54 bool allowed(const Map& map, 55 const FCoords& start, 56 const FCoords& end, 57 int32_t const dir, 58 StepId const id) const override { 59 return op.allowed(map, start, end, dir, id); 60 } reachable_destCheckStep::Capsule61 bool reachable_dest(const Map& map, const FCoords& dest) const override { 62 return op.reachable_dest(map, dest); 63 } 64 65 const T op; 66 }; 67 68 std::shared_ptr<BaseCapsule> capsule; 69 70 static const CheckStep& always_false(); 71 72 public: 73 CheckStep(); 74 CheckStepCheckStep75 template <typename T> CheckStep(const T& op) : capsule(new Capsule<T>(op)) { 76 } 77 78 /** 79 * \return \c true true if moving from start to end (single step in the given 80 * direction) is allowed. 81 */ allowedCheckStep82 bool allowed(const Map& map, 83 const FCoords& start, 84 const FCoords& end, 85 int32_t const dir, 86 StepId const id) const { 87 return capsule->allowed(map, start, end, dir, id); 88 } 89 90 /** 91 * \return \c true if the destination field can be reached at all 92 * (e.g. return false for land-based bobs when dest is in water). 93 */ reachable_destCheckStep94 bool reachable_dest(const Map& map, const FCoords& dest) const { 95 return capsule->reachable_dest(map, dest); 96 } 97 }; 98 99 /** 100 * CheckStep implementation that returns the logic and of all 101 * sub-implementations that have been added via \ref add(). 102 */ 103 struct CheckStepAnd { 104 void add(const CheckStep& sub); 105 106 bool allowed(const Map&, 107 const FCoords& start, 108 const FCoords& end, 109 int32_t dir, 110 CheckStep::StepId id) const; 111 bool reachable_dest(const Map&, const FCoords& dest) const; 112 113 private: 114 std::vector<CheckStep> subs; 115 }; 116 117 /** 118 * Implements the default step checking behaviours that should be used for all 119 * normal bobs. 120 * 121 * Simply check whether the movecaps are matching (basic exceptions for water 122 * bobs moving onto the shore). 123 */ 124 struct CheckStepDefault { CheckStepDefaultCheckStepDefault125 CheckStepDefault(uint8_t const movecaps) : movecaps_(movecaps) { 126 } 127 128 bool allowed( 129 const Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const; 130 bool reachable_dest(const Map&, const FCoords& dest) const; 131 132 private: 133 uint8_t movecaps_; 134 }; 135 136 /** 137 * Implements the step checking behaviour for ferries. 138 * 139 * A ferry can travel on an edge if and only if both adjacent triangles are water. 140 */ 141 struct CheckStepFerry { CheckStepFerryCheckStepFerry142 CheckStepFerry(const EditorGameBase& egbase) : egbase_(egbase) { 143 } 144 145 bool allowed( 146 const Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const; 147 bool reachable_dest(const Map&, const FCoords& dest) const; 148 149 private: 150 const EditorGameBase& egbase_; 151 }; 152 153 /** 154 * Implements the default step checking behaviours with one exception: we can 155 * move from a walkable field onto an unwalkable one. 156 * If onlyend is true, we can only do this on the final step. 157 */ 158 struct CheckStepWalkOn { CheckStepWalkOnCheckStepWalkOn159 CheckStepWalkOn(uint8_t const movecaps, bool const onlyend) 160 : movecaps_(movecaps), onlyend_(onlyend) { 161 } 162 163 bool allowed( 164 const Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const; 165 bool reachable_dest(const Map&, FCoords dest) const; 166 167 private: 168 uint8_t movecaps_; 169 bool onlyend_; 170 }; 171 172 /** 173 * Implements the step checking behaviour for road building. 174 * 175 * player is the player who is building the road. 176 * movecaps are the capabilities with which the road is to be built (swimming 177 * for boats, walking for normal roads). 178 */ 179 struct CheckStepRoad { CheckStepRoadCheckStepRoad180 CheckStepRoad(const Player& player, uint8_t const movecaps) 181 : player_(player), movecaps_(movecaps) { 182 } 183 184 bool allowed( 185 const Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const; 186 bool reachable_dest(const Map&, const FCoords& dest) const; 187 188 private: 189 const Player& player_; 190 uint8_t movecaps_; 191 }; 192 193 /** 194 * A version of CheckStep that is limited to a set of allowed locations. It 195 * only checks whether the target is an allowed location. 196 */ 197 struct CheckStepLimited { add_allowed_locationCheckStepLimited198 void add_allowed_location(const Coords& c) { 199 allowed_locations_.insert(c); 200 } 201 bool allowed( 202 const Map&, const FCoords& start, const FCoords& end, int32_t dir, CheckStep::StepId) const; 203 bool reachable_dest(const Map&, FCoords dest) const; 204 205 private: 206 // The ordering of the set does not matter, as long as it is system 207 // independent (for parallel simulation). 208 // The only thing that matters is whether a location is in the set. 209 std::set<Coords> allowed_locations_; 210 }; 211 } // namespace Widelands 212 213 #endif // end of include guard: WL_LOGIC_MAP_OBJECTS_CHECKSTEP_H 214