1 /*
2  * Copyright (C) 2011-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_SHIP_FLEET_H
21 #define WL_ECONOMY_SHIP_FLEET_H
22 
23 #include <memory>
24 
25 #include "base/macros.h"
26 #include "economy/shipping_schedule.h"
27 #include "logic/map_objects/map_object.h"
28 #include "logic/map_objects/tribes/wareworker.h"
29 #include "logic/path.h"
30 #include "logic/widelands_geometry.h"
31 
32 namespace Widelands {
33 
34 class Economy;
35 struct Flag;
36 struct RoutingNodeNeighbour;
37 
38 class ShipFleetDescr : public MapObjectDescr {
39 public:
ShipFleetDescr(char const * const init_name,char const * const init_descname)40 	ShipFleetDescr(char const* const init_name, char const* const init_descname)
41 	   : MapObjectDescr(MapObjectType::SHIP_FLEET, init_name, init_descname, "") {
42 	}
~ShipFleetDescr()43 	~ShipFleetDescr() override {
44 	}
45 
46 private:
47 	DISALLOW_COPY_AND_ASSIGN(ShipFleetDescr);
48 };
49 
50 constexpr int32_t kFleetInterval = 4000;
51 constexpr uint32_t kRouteNotCalculated = std::numeric_limits<uint32_t>::max();
52 
53 /**
54  * Manage all ships and ports of a player that are connected
55  * by ocean.
56  *
57  * That is, two ports belong to the same fleet if - and only if - ships can
58  * travel between them, and so on. Players may have several fleets, if they
59  * build ports that cannot communicate (e.g. one port on the ocean, and another
60  * in a lake).
61  *
62  * @paragraph Lifetime
63  *
64  * Fleet objects are created on-the-fly by @ref Ship and @ref PortDock,
65  * and destroy themselves when they become empty.
66  *
67  * The intention is for fleet objects to merge automatically and separate
68  * again in reaction to changes in the map. However, this may not work
69  * properly at the moment.
70  */
71 struct ShipFleet : MapObject {
72 	struct PortPath {
73 		int32_t cost;
74 		std::shared_ptr<Path> path;
75 
PortPathShipFleet::PortPath76 		PortPath() : cost(-1) {
77 		}
78 	};
79 
80 	const ShipFleetDescr& descr() const;
81 
82 	explicit ShipFleet(Player* player);
83 
84 	PortDock* get_dock(Flag& flag) const;
85 	PortDock* get_dock(EditorGameBase&, Coords) const;
86 	PortDock* get_arbitrary_dock() const;
87 	void set_economy(Economy* e, WareWorker);
88 
89 	bool active() const;
90 
91 	bool init(EditorGameBase&) override;
92 	void cleanup(EditorGameBase&) override;
93 	void update(EditorGameBase&);
94 
95 	void add_ship(EditorGameBase&, Ship* ship);
96 	void remove_ship(EditorGameBase& egbase, Ship* ship);
97 	void add_port(EditorGameBase& egbase, PortDock* port);
98 	void remove_port(EditorGameBase& egbase, PortDock* port);
99 	bool has_ports() const;
100 
101 	void log_general_info(const EditorGameBase&) const override;
102 
103 	bool get_path(const PortDock& start, const PortDock& end, Path& path);
104 	void add_neighbours(PortDock& pd, std::vector<RoutingNodeNeighbour>& neighbours);
105 
106 	uint32_t count_ships() const;
107 	uint32_t count_ports() const;
108 	bool get_act_pending() const;
109 
110 	bool empty() const;
111 
get_scheduleShipFleet112 	ShippingSchedule& get_schedule() {
113 		return schedule_;
114 	}
115 
get_shipsShipFleet116 	std::vector<Ship*>& get_ships() {
117 		return ships_;
118 	}
get_portsShipFleet119 	std::vector<PortDock*>& get_ports() {
120 		return ports_;
121 	}
122 
123 protected:
124 	void act(Game&, uint32_t data) override;
125 
126 private:
127 	bool find_other_fleet(EditorGameBase& egbase);
128 	bool merge(EditorGameBase& egbase, ShipFleet* other);
129 	void check_merge_economy();
130 	void connect_port(EditorGameBase& egbase, uint32_t idx);
131 
132 	PortPath& portpath(uint32_t i, uint32_t j);
133 	const PortPath& portpath(uint32_t i, uint32_t j) const;
134 	PortPath& portpath_bidir(uint32_t i, uint32_t j, bool& reverse);
135 	const PortPath& portpath_bidir(uint32_t i, uint32_t j, bool& reverse) const;
136 
137 	std::vector<Ship*> ships_;
138 	std::vector<PortDock*> ports_;
139 
140 	bool act_pending_;
141 
142 	/**
143 	 * Store all pairs shortest paths between port docks
144 	 *
145 	 * Let i < j, then the path from ports_[i] to ports_[j] is stored in
146 	 * portpaths_[binom(j,2) + i]
147 	 */
148 	std::vector<PortPath> portpaths_;
149 
150 	ShippingSchedule schedule_;
151 
152 	// saving and loading
153 protected:
154 	struct Loader : MapObject::Loader {
155 		Loader();
156 
157 		void load(FileRead&);
158 		void load_pointers() override;
159 		void load_finish() override;
160 
161 		uint8_t packet_version_;
162 
163 	private:
164 		std::vector<uint32_t> ships_;
165 		std::vector<uint32_t> ports_;
166 	};
167 
168 public:
has_new_save_supportShipFleet169 	bool has_new_save_support() override {
170 		return true;
171 	}
172 	void save(EditorGameBase&, MapObjectSaver&, FileWrite&) override;
173 
174 	static MapObject::Loader* load(EditorGameBase&, MapObjectLoader&, FileRead&);
175 };
176 
177 }  // namespace Widelands
178 
179 #endif  // end of include guard: WL_ECONOMY_SHIP_FLEET_H
180