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