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 #include "economy/road.h"
21 
22 #include "base/macros.h"
23 #include "economy/economy.h"
24 #include "economy/flag.h"
25 #include "economy/request.h"
26 #include "logic/editor_game_base.h"
27 #include "logic/game.h"
28 #include "logic/map_objects/map_object.h"
29 #include "logic/map_objects/tribes/carrier.h"
30 #include "logic/map_objects/tribes/tribe_descr.h"
31 #include "logic/map_objects/world/terrain_description.h"
32 #include "logic/map_objects/world/world.h"
33 #include "logic/player.h"
34 
35 namespace Widelands {
36 
37 // dummy instance because MapObject needs a description
38 namespace {
39 const RoadDescr g_road_descr("road", "Road");
40 }
41 
is_road_descr(MapObjectDescr const * const descr)42 bool Road::is_road_descr(MapObjectDescr const* const descr) {
43 	return descr == &g_road_descr;
44 }
45 
CarrierSlot()46 Road::CarrierSlot::CarrierSlot()
47    : carrier(nullptr), carrier_request(nullptr), second_carrier(false) {
48 }
49 
50 /**
51  * Most of the actual work is done in init.
52  */
Road()53 Road::Road() : RoadBase(g_road_descr), busy_(false), wallet_(0), last_wallet_charge_(0) {
54 	CarrierSlot slot;
55 	carrier_slots_.push_back(slot);
56 	carrier_slots_.push_back(slot);
57 	carrier_slots_[0].second_carrier = false;
58 	carrier_slots_[1].second_carrier = true;
59 }
60 
61 /**
62  * Most of the actual work is done in cleanup.
63  */
~Road()64 Road::~Road() {
65 	for (CarrierSlot& slot : carrier_slots_) {
66 		delete slot.carrier_request;
67 	}
68 }
69 
70 /**
71  * Create a road between the given flags, using the given path.
72  */
create(EditorGameBase & egbase,Flag & start,Flag & end,const Path & path)73 Road& Road::create(EditorGameBase& egbase, Flag& start, Flag& end, const Path& path) {
74 	assert(start.get_position() == path.get_start());
75 	assert(end.get_position() == path.get_end());
76 	assert(start.get_owner() == end.get_owner());
77 
78 	Road& road = *new Road();
79 	road.set_owner(start.get_owner());
80 	road.busy_ = false;
81 	road.flags_[FlagStart] = &start;
82 	road.flags_[FlagEnd] = &end;
83 	// flagidx_ is set when attach_road() is called, i.e. in init()
84 	road.set_path(egbase, path);
85 
86 	road.init(egbase);
87 
88 	return road;
89 }
90 
road_type_for_drawing() const91 RoadSegment Road::road_type_for_drawing() const {
92 	return busy_ ? RoadSegment::kBusy : RoadSegment::kNormal;
93 }
94 
cleanup(EditorGameBase & egbase)95 void Road::cleanup(EditorGameBase& egbase) {
96 	Economy::check_split(*flags_[FlagStart], *flags_[FlagEnd], wwWARE);
97 	Economy::check_split(*flags_[FlagStart], *flags_[FlagEnd], wwWORKER);
98 	for (CarrierSlot& slot : carrier_slots_) {
99 		delete slot.carrier_request;
100 		slot.carrier_request = nullptr;
101 
102 		// carrier will be released via PlayerImmovable::cleanup
103 		slot.carrier = nullptr;
104 	}
105 	RoadBase::cleanup(egbase);
106 }
107 
link_into_flags(EditorGameBase & egbase,bool)108 void Road::link_into_flags(EditorGameBase& egbase, bool) {
109 	RoadBase::link_into_flags(egbase);
110 	Economy::check_merge(*flags_[FlagStart], *flags_[FlagEnd], wwWARE);
111 	Economy::check_merge(*flags_[FlagStart], *flags_[FlagEnd], wwWORKER);
112 	if (upcast(Game, game, &egbase)) {
113 		for (CarrierSlot& slot : carrier_slots_) {
114 			if (Carrier* const carrier = slot.carrier.get(*game)) {
115 				// This happens after a road split. Tell the carrier what's going on.
116 				carrier->set_location(this);
117 				carrier->update_task_road(*game);
118 			} else if (!slot.carrier_request && (!slot.second_carrier || busy_)) {
119 				// Normal carriers are requested at once, second carriers only for busy roads
120 				request_carrier(slot);
121 			}
122 		}
123 	}
124 }
125 
set_busy(EditorGameBase & e,bool b)126 void Road::set_busy(EditorGameBase& e, bool b) {
127 	unmark_map(e);
128 	wallet_ = b ? kRoadMaxWallet : 0;
129 	busy_ = b;
130 	mark_map(e);
131 }
132 
set_economy(Economy * const e,WareWorker type)133 void Road::set_economy(Economy* const e, WareWorker type) {
134 	RoadBase::set_economy(e, type);
135 	if (type == wwWORKER) {
136 		for (CarrierSlot& slot : carrier_slots_) {
137 			if (slot.carrier_request) {
138 				slot.carrier_request->set_economy(e);
139 			}
140 		}
141 	}
142 }
143 
144 /**
145  * Request a new carrier.
146  *
147  * Only call this if the road can handle a new carrier, and if no request has
148  * been issued.
149  */
request_carrier(CarrierSlot & slot)150 void Road::request_carrier(CarrierSlot& slot) {
151 	slot.carrier_request = new Request(
152 	   *this, slot.second_carrier ? owner().tribe().carrier2() : owner().tribe().carrier(),
153 	   request_carrier_callback, wwWORKER);
154 }
155 
156 /**
157  * The carrier has arrived successfully.
158  */
request_carrier_callback(Game & game,Request & rq,DescriptionIndex,Worker * const w,PlayerImmovable & target)159 void Road::request_carrier_callback(
160    Game& game, Request& rq, DescriptionIndex, Worker* const w, PlayerImmovable& target) {
161 	assert(w);
162 
163 	Road& road = dynamic_cast<Road&>(target);
164 
165 	for (CarrierSlot& slot : road.carrier_slots_) {
166 		if (slot.carrier_request == &rq) {
167 			Carrier& carrier = dynamic_cast<Carrier&>(*w);
168 			slot.carrier_request = nullptr;
169 			slot.carrier = &carrier;
170 
171 			carrier.start_task_road(game);
172 			delete &rq;
173 			return;
174 		}
175 	}
176 
177 	/*
178 	 * Oops! We got a request_callback but don't have the request.
179 	 * Try to send him home.
180 	 */
181 	log("Road(%u): got a request_callback but do not have the request\n", road.serial());
182 	delete &rq;
183 	w->start_task_gowarehouse(game);
184 }
carriers_count() const185 uint8_t Road::carriers_count() const {
186 	return (carrier_slots_[1].carrier == nullptr) ? 1 : 2;
187 }
188 
189 /**
190  * If we lost our carrier, re-request it.
191  */
remove_worker(Worker & w)192 void Road::remove_worker(Worker& w) {
193 	EditorGameBase& egbase = get_owner()->egbase();
194 
195 	for (CarrierSlot& slot : carrier_slots_) {
196 		Carrier const* carrier = slot.carrier.get(egbase);
197 
198 		if (carrier == &w) {
199 			slot.carrier = nullptr;
200 			carrier = nullptr;
201 			request_carrier(slot);
202 		}
203 	}
204 
205 	PlayerImmovable::remove_worker(w);
206 }
207 
208 /**
209  * A carrier was created by someone else (e.g. Scripting Engine)
210  * and should now be assigned to this road.
211  */
assign_carrier(Carrier & c,uint8_t slot)212 void Road::assign_carrier(Carrier& c, uint8_t slot) {
213 	assert(slot <= 1);
214 
215 	// Send the worker home if it occupies our slot
216 	CarrierSlot& s = carrier_slots_[slot];
217 
218 	delete s.carrier_request;
219 	s.carrier_request = nullptr;
220 	if (Carrier* const current_carrier = s.carrier.get(owner().egbase()))
221 		current_carrier->set_location(nullptr);
222 
223 	carrier_slots_[slot].carrier = &c;
224 	carrier_slots_[slot].carrier_request = nullptr;
225 }
226 
227 /**
228  * The flag that splits this road has been initialized. Perform the actual
229  * splitting.
230  *
231  * After the split, this road will span [start...new flag]. A new road will
232  * be created to span [new flag...end]
233  */
234 // TODO(SirVer): This needs to take an EditorGameBase as well.
postsplit(Game & game,Flag & flag)235 void Road::postsplit(Game& game, Flag& flag) {
236 	Flag& oldend = *flags_[FlagEnd];
237 
238 	// detach from end
239 	oldend.detach_road(flagidx_[FlagEnd]);
240 
241 	// build our new path and the new road's path
242 	const Map& map = game.map();
243 	CoordPath path(map, path_);
244 	CoordPath secondpath(path);
245 	int32_t const index = path.get_index(flag.get_position());
246 
247 	assert(index > 0);
248 	assert(static_cast<uint32_t>(index) < path.get_nsteps() - 1);
249 
250 	path.truncate(index);
251 	secondpath.trim_start(index);
252 
253 	molog("splitting road: first part:\n");
254 	for (const Coords& coords : path.get_coords()) {
255 		molog("* (%i, %i)\n", coords.x, coords.y);
256 	}
257 	molog("                second part:\n");
258 	for (const Coords& coords : secondpath.get_coords()) {
259 		molog("* (%i, %i)\n", coords.x, coords.y);
260 	}
261 
262 	// change road size and reattach
263 	flags_[FlagEnd] = &flag;
264 	set_path(game, path);
265 
266 	const Direction dir = get_reverse_dir(path_[path_.get_nsteps() - 1]);
267 	flags_[FlagEnd]->attach_road(dir, this);
268 	flagidx_[FlagEnd] = dir;
269 
270 	// recreate road markings
271 	mark_map(game);
272 
273 	// create the new road
274 	Road& newroad = *new Road();
275 	newroad.set_owner(get_owner());
276 	newroad.busy_ = busy_;
277 	newroad.flags_[FlagStart] = &flag;  //  flagidx will be set on init()
278 	newroad.flags_[FlagEnd] = &oldend;
279 	newroad.set_path(game, secondpath);
280 
281 	// Find workers on this road that need to be reassigned
282 	// The algorithm is pretty simplistic, and has a bias towards keeping
283 	// the worker around; there's obviously nothing wrong with that.
284 
285 	std::vector<Worker*> const workers = get_workers();
286 	std::vector<Worker*> reassigned_workers;
287 
288 	for (Worker* w : workers) {
289 		int32_t idx = path.get_index(w->get_position());
290 
291 		// Careful! If the worker is currently inside the building at our
292 		// starting flag, we *must not* reassign him.
293 		// If he is in the building at our end flag or at the other road's
294 		// end flag, he can be reassigned to the other road.
295 		if (idx < 0) {
296 			if (dynamic_cast<Building const*>(map.get_immovable(w->get_position()))) {
297 				Coords pos;
298 				map.get_brn(w->get_position(), &pos);
299 				if (pos == path.get_start())
300 					idx = 0;
301 			}
302 		}
303 
304 		if (idx < 0) {
305 			reassigned_workers.push_back(w);
306 
307 			/*
308 			 * The current worker is not on this road. Search him
309 			 * in this road and remove him. Than add him to the new road
310 			 */
311 			for (CarrierSlot& old_slot : carrier_slots_) {
312 				Carrier const* const carrier = old_slot.carrier.get(game);
313 
314 				if (carrier == w) {
315 					old_slot.carrier = nullptr;
316 					for (CarrierSlot& new_slot : newroad.carrier_slots_) {
317 						if (!new_slot.carrier.get(game) && !new_slot.carrier_request &&
318 						    new_slot.second_carrier == old_slot.second_carrier) {
319 							upcast(Carrier, new_carrier, w);
320 							new_slot.carrier = new_carrier;
321 							break;
322 						}
323 					}
324 				}
325 			}
326 		}
327 
328 		// Cause a worker update in any case
329 		w->send_signal(game, "road");
330 	}
331 
332 	// Initialize the new road
333 	newroad.init(game);
334 	newroad.wallet_ = wallet_;
335 
336 	// Actually reassign workers after the new road has initialized,
337 	// so that the reassignment is safe
338 	for (Worker*& w : reassigned_workers) {
339 		w->set_location(&newroad);
340 	}
341 
342 	//  Request a new carrier for this road if necessary. This must be done
343 	//  _after_ the new road initializes, otherwise request routing might not
344 	//  work correctly
345 	for (CarrierSlot& slot : carrier_slots_) {
346 		if (!slot.carrier.get(game) && !slot.carrier_request && (!slot.second_carrier || busy_)) {
347 			request_carrier(slot);
348 		}
349 	}
350 
351 	//  Make sure wares waiting on the original endpoint flags are dealt with.
352 	flags_[FlagStart]->update_wares(game, &oldend);
353 	oldend.update_wares(game, flags_[FlagStart]);
354 }
355 
356 /**
357  * Try to pick up a ware from the given flag.
358  * \return true if a carrier has been sent on its way, false otherwise.
359  */
notify_ware(Game & game,FlagId const flagid)360 bool Road::notify_ware(Game& game, FlagId const flagid) {
361 	// Iterate over all carriers and try to find one which will take the ware
362 	for (CarrierSlot& slot : carrier_slots_) {
363 		if (Carrier* const carrier = slot.carrier.get(game)) {
364 			if (carrier->notify_ware(game, flagid)) {
365 				// The carrier took the ware, so we're done
366 				return true;
367 			}
368 		}
369 	}
370 	// No carrier took the ware
371 	return false;
372 }
373 
374 // This returns true if and only if this is road covers the specified edge and
375 // both triangles adjacent to that edge are unwalkable
is_bridge(const EditorGameBase & egbase,const FCoords & field,uint8_t dir) const376 bool Road::is_bridge(const EditorGameBase& egbase, const FCoords& field, uint8_t dir) const {
377 	const Map& map = egbase.map();
378 
379 	FCoords iterate = map.get_fcoords(path_.get_start());
380 	const Path::StepVector::size_type nr_steps = path_.get_nsteps();
381 	bool found = false;
382 	for (Path::StepVector::size_type i = 0; i <= nr_steps; ++i) {
383 		if (iterate == field) {
384 			if ((i < nr_steps && path_[i] == dir) || (i > 0 && path_[i - 1] == get_reverse_dir(dir))) {
385 				found = true;
386 				break;
387 			}
388 			return false;
389 		}
390 		if (i < nr_steps) {
391 			map.get_neighbour(iterate, path_[i], &iterate);
392 		}
393 	}
394 	if (!found) {
395 		return false;
396 	}
397 
398 	FCoords fr, fd;
399 	switch (dir) {
400 	case WALK_SW:
401 		fd = field;
402 		map.get_ln(field, &fr);
403 		break;
404 	case WALK_SE:
405 		fd = field;
406 		fr = field;
407 		break;
408 	case WALK_NW:
409 		map.get_tln(field, &fd);
410 		fr = fd;
411 		break;
412 	case WALK_NE:
413 		map.get_trn(field, &fd);
414 		map.get_tln(field, &fr);
415 		break;
416 	case WALK_W:
417 		map.get_tln(field, &fd);
418 		map.get_ln(field, &fr);
419 		break;
420 	case WALK_E:
421 		map.get_trn(field, &fd);
422 		fr = field;
423 		break;
424 	default:
425 		NEVER_HERE();
426 	}
427 	return (egbase.world().terrain_descr(fd.field->terrain_d()).get_is() &
428 	        TerrainDescription::Is::kUnwalkable) &&
429 	       (egbase.world().terrain_descr(fr.field->terrain_r()).get_is() &
430 	        TerrainDescription::Is::kUnwalkable);
431 }
432 
433 /**
434  * Update last_wallet_charge_ with the current gametime.
435  */
update_wallet_chargetime(Game & game)436 void Road::update_wallet_chargetime(Game& game) {
437 	last_wallet_charge_ = game.get_gametime();
438 }
439 
440 /**
441  * Subtract maintenance cost, and check for demotion.
442  */
charge_wallet(Game & game)443 void Road::charge_wallet(Game& game) {
444 	const uint32_t current_gametime = game.get_gametime();
445 	assert(last_wallet_charge_ <= current_gametime);
446 
447 	wallet_ -= carriers_count() * (current_gametime - last_wallet_charge_) / 1000;
448 	last_wallet_charge_ = current_gametime;
449 
450 	if (wallet_ < 0) {
451 		wallet_ = 0;
452 		if (busy_) {
453 			// Demote the road
454 			Carrier* const second_carrier = carrier_slots_[1].carrier.get(game);
455 			if (second_carrier && second_carrier->top_state().task == &Carrier::taskRoad) {
456 				second_carrier->send_signal(game, "cancel");
457 				// This signal is not handled in any special way. It will simply pop the task off the
458 				// stack. The string "cancel" has been used to clarify the final goal we want to
459 				// achieve, ie: cancelling the current task.
460 				carrier_slots_[1].carrier = nullptr;
461 				carrier_slots_[1].carrier_request = nullptr;
462 				busy_ = false;
463 				mark_map(game);
464 			}
465 		}
466 	}
467 }
468 
wallet() const469 int32_t Road::wallet() const {
470 	return wallet_;
471 }
472 
add_to_wallet(int32_t sum)473 void Road::add_to_wallet(int32_t sum) {
474 	wallet_ += sum;
475 }
476 
477 /**
478  * Add carrying payment, and check for promotion.
479  */
pay_for_road(Game & game,uint8_t queue_length)480 void Road::pay_for_road(Game& game, uint8_t queue_length) {
481 	wallet_ += 2 * (carriers_count() + 1) * (4 * queue_length + path_.get_nsteps());
482 	charge_wallet(game);
483 
484 	if (!busy_ && wallet_ > 1.5 * kRoadAnimalPrice) {
485 		// Promote the road
486 		wallet_ -= kRoadAnimalPrice;
487 		busy_ = true;
488 		flags_[0]->propagate_promoted_road(this);
489 		flags_[1]->propagate_promoted_road(this);
490 		mark_map(game);
491 		for (CarrierSlot& slot : carrier_slots_) {
492 			if (!slot.carrier.get(game) && !slot.carrier_request && slot.second_carrier) {
493 				request_carrier(slot);
494 			}
495 		}
496 	}
497 	wallet_ = std::min(wallet_, kRoadMaxWallet);
498 }
499 
500 /**
501  * Add extra coins for street-segment at building.
502  */
pay_for_building()503 void Road::pay_for_building() {
504 	wallet_ += 2 * (carriers_count() + 1);
505 	// Don't bother with checks here, since the next ware will cause them anyway
506 }
507 
log_general_info(const EditorGameBase & egbase) const508 void Road::log_general_info(const EditorGameBase& egbase) const {
509 	PlayerImmovable::log_general_info(egbase);
510 	molog("wallet: %i\n", wallet_);
511 }
512 }  // namespace Widelands
513