1 /*
2  * Copyright (C) 2002-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_REQUEST_H
21 #define WL_ECONOMY_REQUEST_H
22 
23 #include "economy/trackptr.h"
24 #include "logic/map_objects/tribes/requirements.h"
25 #include "logic/map_objects/tribes/wareworker.h"
26 #include "logic/widelands.h"
27 #include "map_io/tribes_legacy_lookup_table.h"
28 
29 namespace Widelands {
30 
31 class Economy;
32 struct Flag;
33 class Game;
34 struct PlayerImmovable;
35 class RequestList;
36 struct Supply;
37 struct Transfer;
38 class Worker;
39 class Building;
40 class ProductionSite;
41 class Warehouse;
42 class ConstructionSite;
43 
44 /**
45  * A Request is issued whenever some object (road or building) needs a ware.
46  *
47  * Requests are always created and destroyed by their owner, i.e. the target
48  * player immovable. The owner is also responsible for calling set_economy()
49  * when its economy changes.
50  *
51  * Idle Requests need not be fulfilled; however, when there's a matching Supply
52  * left, a transfer may be initiated.
53  * The required time has no meaning for idle requests.
54  */
55 class Request : public Trackable {
56 public:
57 	friend class Economy;
58 	friend class RequestList;
59 
60 	using CallbackFn = void (*)(Game&, Request&, DescriptionIndex, Worker*, PlayerImmovable&);
61 
62 	Request(PlayerImmovable& target, DescriptionIndex, CallbackFn, WareWorker);
63 	~Request();
64 
target()65 	PlayerImmovable& target() const {
66 		return target_;
67 	}
get_index()68 	DescriptionIndex get_index() const {
69 		return index_;
70 	}
get_type()71 	WareWorker get_type() const {
72 		return type_;
73 	}
get_count()74 	Quantity get_count() const {
75 		return count_;
76 	}
get_open_count()77 	uint32_t get_open_count() const {
78 		return count_ - transfers_.size();
79 	}
get_exact_match()80 	bool get_exact_match() const {
81 		return exact_match_;
82 	}
is_open()83 	bool is_open() const {
84 		return transfers_.size() < count_;
85 	}
get_economy()86 	Economy* get_economy() const {
87 		return economy_;
88 	}
89 	int32_t get_required_time() const;
get_last_request_time()90 	int32_t get_last_request_time() const {
91 		return last_request_time_;
92 	}
93 	int32_t get_priority(int32_t cost) const;
94 	uint32_t get_transfer_priority() const;
get_num_transfers()95 	uint32_t get_num_transfers() const {
96 		return transfers_.size();
97 	}
98 
99 	Flag& target_flag() const;
100 
101 	void set_economy(Economy*);
102 	void set_count(Quantity);
103 	void set_exact_match(bool match);
104 	void set_required_time(int32_t time);
105 	void set_required_interval(int32_t interval);
106 
set_last_request_time(int32_t const time)107 	void set_last_request_time(int32_t const time) {
108 		last_request_time_ = time;
109 	}
110 
111 	void start_transfer(Game&, Supply&);
112 
113 	void
114 	read(FileRead&, Game&, MapObjectLoader&, const TribesLegacyLookupTable& tribes_lookup_table);
115 	void write(FileWrite&, Game&, MapObjectSaver&) const;
116 	Worker* get_transfer_worker();
117 
118 	//  callbacks for WareInstance/Worker code
119 	void transfer_finish(Game&, Transfer&);
120 	void transfer_fail(Game&, Transfer&);
121 	void cancel_transfer(uint32_t idx);
122 
set_requirements(const Requirements & r)123 	void set_requirements(const Requirements& r) {
124 		requirements_ = r;
125 	}
get_requirements()126 	const Requirements& get_requirements() const {
127 		return requirements_;
128 	}
129 
130 private:
131 	int32_t get_base_required_time(EditorGameBase&, uint32_t nr) const;
132 	void remove_transfer(uint32_t idx);
133 	uint32_t find_transfer(Transfer&);
134 
135 	using TransferList = std::vector<Transfer*>;
136 
137 	WareWorker type_;
138 
139 	PlayerImmovable& target_;  //  who requested it?
140 	//  Copies of target_ of various pointer types, to avoid expensive
141 	//  dynamic casting at runtime. Variables with an incompatible type
142 	//  are filled with nulls.
143 	Building* target_building_;
144 	ProductionSite* target_productionsite_;
145 	Warehouse* target_warehouse_;
146 	ConstructionSite* target_constructionsite_;
147 
148 	Economy* economy_;
149 	DescriptionIndex index_;  //  the index of the ware descr
150 	Quantity count_;          //  how many do we need in total
151 	bool exact_match_;        // Whether a worker supply has to match exactly
152 	                          // or if a can_act_as() comparison is good enough
153 
154 	CallbackFn callbackfn_;  //  called on request success
155 
156 	//  when do we need the first ware (can be in the past)
157 	int32_t required_time_;
158 	int32_t required_interval_;  //  time between wares
159 	int32_t last_request_time_;
160 
161 	TransferList transfers_;  //  maximum size is count_
162 
163 	Requirements requirements_;
164 };
165 }  // namespace Widelands
166 
167 #endif  // end of include guard: WL_ECONOMY_REQUEST_H
168