1 /* 2 * Copyright (C) 2004-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_ECONOMY_FLAG_H 21 #define WL_ECONOMY_FLAG_H 22 23 #include <algorithm> 24 #include <deque> 25 #include <iterator> 26 27 #include "base/macros.h" 28 #include "economy/routing_node.h" 29 #include "logic/map_objects/immovable.h" 30 #include "logic/map_objects/info_to_draw.h" 31 #include "logic/map_objects/walkingdir.h" 32 33 namespace Widelands { 34 class Request; 35 struct RoadBase; 36 struct Road; 37 struct Waterway; 38 class WareInstance; 39 40 class FlagDescr : public MapObjectDescr { 41 public: FlagDescr(char const * const init_name,char const * const init_descname)42 FlagDescr(char const* const init_name, char const* const init_descname) 43 : MapObjectDescr(MapObjectType::FLAG, init_name, init_descname, "") { 44 } ~FlagDescr()45 ~FlagDescr() override { 46 } 47 48 private: 49 DISALLOW_COPY_AND_ASSIGN(FlagDescr); 50 }; 51 52 /** 53 * Flag represents a flag as you see it on the map. 54 * 55 * A flag itself doesn't do much. However, it can have up to 6 roads/waterways 56 * attached to it. Instead of the WALK_NW road, it can also have a building 57 * attached to it. It cannot have more than one waterway. 58 * Flags also have a store of up to 8 wares. 59 * 60 * You can also assign an arbitrary number of "jobs" for a flag. 61 * A job consists of a request for a worker, and the name of a program that the 62 * worker is to execute. Once execution of the program has finished, the worker 63 * will return to a warehouse. 64 * 65 * Important: Do not access roads_ directly. get_road() and others use 66 * WALK_xx in all "direction" parameters. 67 */ 68 struct Flag : public PlayerImmovable, public RoutingNode { 69 using Wares = std::vector<const WareInstance*>; 70 71 friend class Economy; 72 friend class FlagQueue; 73 friend class MapFlagdataPacket; // has to read/write this to a file 74 friend struct MapWarePacket; // has to look at pending wares 75 friend struct MapWaredataPacket; // has to look at pending wares 76 friend struct Router; 77 78 const FlagDescr& descr() const; 79 80 /// Empty flag, for unit tests only. 81 Flag(); 82 83 /// Create a new flag. Only specify an economy during saveloading. 84 /// Otherwise, a new economy will be created automatically if needed. 85 Flag(EditorGameBase&, 86 Player* owner, 87 const Coords&, 88 Economy* ware_economy = nullptr, 89 Economy* worker_economy = nullptr); 90 ~Flag() override; 91 92 void load_finish(EditorGameBase&) override; 93 void destroy(EditorGameBase&) override; 94 95 int32_t get_size() const override; 96 bool get_passable() const override; 97 98 Flag& base_flag() override; 99 get_positionFlag100 const Coords& get_position() const override { 101 return position_; 102 } 103 PositionList get_positions(const EditorGameBase&) const override; 104 void get_neighbours(WareWorker type, RoutingNodeNeighbours&) override; get_waitcostFlag105 int32_t get_waitcost() const { 106 return ware_filled_; 107 } 108 109 void set_economy(Economy*, WareWorker) override; 110 get_buildingFlag111 Building* get_building() const { 112 return building_; 113 } 114 void attach_building(EditorGameBase&, Building&); 115 void detach_building(EditorGameBase&); 116 has_roadbaseFlag117 bool has_roadbase() const { 118 return std::any_of(std::begin(roads_), std::end(roads_), 119 [](const RoadBase* road) { return road != nullptr; }); 120 } has_waterwayFlag121 bool has_waterway() const { 122 return nr_of_waterways() > 0; 123 } has_roadFlag124 bool has_road() const { 125 return nr_of_roads() > 0; 126 } get_roadbaseFlag127 RoadBase* get_roadbase(uint8_t dir) const { 128 return roads_[dir - 1]; 129 } 130 Road* get_road(uint8_t dir) const; 131 Waterway* get_waterway(uint8_t dir) const; 132 uint8_t nr_of_roadbases() const; 133 uint8_t nr_of_roads() const; 134 uint8_t nr_of_waterways() const; 135 void attach_road(int32_t dir, RoadBase*); 136 void detach_road(int32_t dir); 137 138 RoadBase* get_roadbase(Flag&); 139 Road* get_road(Flag&); 140 141 bool is_dead_end() const; 142 143 bool has_capacity() const; total_capacityFlag144 uint32_t total_capacity() { 145 return ware_capacity_; 146 } current_waresFlag147 uint32_t current_wares() const { 148 return ware_filled_; 149 } 150 void wait_for_capacity(Game&, Worker&); 151 void skip_wait_for_capacity(Game&, Worker&); 152 void add_ware(EditorGameBase&, WareInstance&); 153 bool has_pending_ware(Game&, Flag& destflag); 154 bool ack_pickup(Game&, Flag& destflag); 155 bool cancel_pickup(Game&, Flag& destflag); 156 WareInstance* fetch_pending_ware(Game&, PlayerImmovable& dest); 157 void propagate_promoted_road(Road* promoted_road); 158 Wares get_wares(); 159 uint8_t count_wares_in_queue(PlayerImmovable& dest) const; 160 161 void call_carrier(Game&, WareInstance&, PlayerImmovable* nextstep); 162 void update_wares(Game&, Flag* other); 163 164 void remove_ware(EditorGameBase&, WareInstance* const); 165 166 void add_flag_job(Game&, DescriptionIndex workerware, const std::string& programname); 167 168 void log_general_info(const EditorGameBase&) const override; 169 170 protected: 171 bool init(EditorGameBase&) override; 172 void cleanup(EditorGameBase&) override; 173 174 void draw(uint32_t gametime, 175 InfoToDraw info_to_draw, 176 const Vector2f& point_on_dst, 177 const Coords& coords, 178 float scale, 179 RenderTarget* dst) override; 180 181 void wake_up_capacity_queue(Game&); 182 183 static void 184 flag_job_request_callback(Game&, Request&, DescriptionIndex, Worker*, PlayerImmovable&); 185 186 void set_flag_position(Coords coords); 187 188 private: 189 struct PendingWare { 190 WareInstance* ware; ///< the ware itself 191 bool pending; ///< if the ware is pending 192 int32_t priority; ///< carrier prefers the ware with highest priority 193 OPtr<PlayerImmovable> nextstep; ///< next step that this ware is sent to 194 }; 195 196 struct FlagJob { 197 Request* request; 198 std::string program; 199 }; 200 201 Coords position_; 202 int32_t animstart_; 203 204 Building* building_; ///< attached building (replaces road WALK_NW) 205 RoadBase* roads_[WalkingDir::LAST_DIRECTION]; 206 207 int32_t ware_capacity_; ///< size of wares_ array 208 int32_t ware_filled_; ///< number of wares currently on the flag 209 PendingWare* wares_; ///< wares currently on the flag 210 211 /// call_carrier() will always call a carrier when the destination is 212 /// the given flag 213 Flag* always_call_for_flag_; 214 215 using CapacityWaitQueue = std::deque<OPtr<Worker>>; 216 CapacityWaitQueue capacity_wait_; ///< workers waiting for capacity 217 218 using FlagJobs = std::list<FlagJob>; 219 FlagJobs flag_jobs_; 220 }; 221 222 extern FlagDescr g_flag_descr; 223 } // namespace Widelands 224 225 #endif // end of include guard: WL_ECONOMY_FLAG_H 226