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/flag.h"
21 
22 #include <algorithm>
23 #include <iterator>
24 
25 #include "base/macros.h"
26 #include "base/wexception.h"
27 #include "economy/economy.h"
28 #include "economy/portdock.h"
29 #include "economy/request.h"
30 #include "economy/road.h"
31 #include "economy/ware_instance.h"
32 #include "economy/waterway.h"
33 #include "graphic/rendertarget.h"
34 #include "logic/editor_game_base.h"
35 #include "logic/game.h"
36 #include "logic/map_objects/map_object.h"
37 #include "logic/map_objects/tribes/building.h"
38 #include "logic/map_objects/tribes/tribe_descr.h"
39 #include "logic/map_objects/tribes/warehouse.h"
40 #include "logic/map_objects/tribes/worker.h"
41 #include "logic/player.h"
42 
43 namespace Widelands {
44 
45 FlagDescr g_flag_descr("flag", "Flag");
46 
descr() const47 const FlagDescr& Flag::descr() const {
48 	return g_flag_descr;
49 }
50 
51 /**
52  * A bare flag, used for testing only.
53  */
Flag()54 Flag::Flag()
55    : PlayerImmovable(g_flag_descr),
56      animstart_(0),
57      building_(nullptr),
58      ware_capacity_(8),
59      ware_filled_(0),
60      wares_(new PendingWare[ware_capacity_]),
61      always_call_for_flag_(nullptr) {
62 	std::fill(std::begin(roads_), std::end(roads_), nullptr);
63 }
64 
65 /**
66  * Shouldn't be necessary to do anything,
67  * since die() always calls cleanup() first.
68  */
~Flag()69 Flag::~Flag() {
70 	if (ware_filled_) {
71 		log("Flag: ouch! wares left\n");
72 	}
73 	delete[] wares_;
74 
75 	if (building_) {
76 		log("Flag: ouch! building left\n");
77 	}
78 
79 	if (flag_jobs_.size()) {
80 		log("Flag: ouch! flagjobs left\n");
81 	}
82 
83 	for (const RoadBase* const road : roads_) {
84 		if (road) {
85 			log("Flag: ouch! road left\n");
86 		}
87 	}
88 }
89 
load_finish(EditorGameBase & egbase)90 void Flag::load_finish(EditorGameBase& egbase) {
91 	auto should_be_deleted = [&egbase, this](const OPtr<Worker>& r) {
92 		Worker& worker = *r.get(egbase);
93 		Bob::State const* const state = worker.get_state(Worker::taskWaitforcapacity);
94 		if (state == nullptr) {
95 			log("WARNING: worker %u is in the capacity wait queue of flag %u but "
96 			    "does not have a waitforcapacity task! Removing from queue.\n",
97 			    worker.serial(), serial());
98 			return true;
99 		}
100 		if (state->objvar1 != this) {
101 			log("WARNING: worker %u is in the capacity wait queue of flag %u but "
102 			    "its waitforcapacity task is for map object %u! Removing from "
103 			    "queue.\n",
104 			    worker.serial(), serial(), state->objvar1.serial());
105 			return true;
106 		}
107 		return false;
108 	};
109 
110 	capacity_wait_.erase(
111 	   std::remove_if(capacity_wait_.begin(), capacity_wait_.end(), should_be_deleted),
112 	   capacity_wait_.end());
113 }
114 
115 /**
116  * Creates a flag at the given location.
117  */
Flag(EditorGameBase & egbase,Player * owning_player,const Coords & coords,Economy * ware_eco,Economy * worker_eco)118 Flag::Flag(EditorGameBase& egbase,
119            Player* owning_player,
120            const Coords& coords,
121            Economy* ware_eco,
122            Economy* worker_eco)
123    : PlayerImmovable(g_flag_descr),
124      building_(nullptr),
125      ware_capacity_(8),
126      ware_filled_(0),
127      wares_(new PendingWare[ware_capacity_]),
128      always_call_for_flag_(nullptr) {
129 	std::fill(std::begin(roads_), std::end(roads_), nullptr);
130 
131 	set_owner(owning_player);
132 
133 	set_flag_position(coords);
134 
135 	upcast(RoadBase, road, egbase.map().get_immovable(coords));
136 	upcast(Game, game, &egbase);
137 
138 	if (game) {
139 		if (ware_eco) {
140 			// We're saveloading
141 			ware_eco->add_flag(*this);
142 		} else {
143 			//  we split a road, or a new, standalone flag is created
144 			(road ? road->get_economy(wwWARE) : owning_player->create_economy(wwWARE))
145 			   ->add_flag(*this);
146 		}
147 		if (worker_eco) {
148 			// We're saveloading
149 			worker_eco->add_flag(*this);
150 		} else {
151 			//  we split a road, or a new, standalone flag is created
152 			(road ? road->get_economy(wwWORKER) : owning_player->create_economy(wwWORKER))
153 			   ->add_flag(*this);
154 		}
155 		if (road && !ware_eco && !worker_eco) {
156 			road->presplit(*game, coords);
157 		}
158 	}
159 
160 	init(egbase);
161 
162 	if (!ware_eco && !worker_eco && road && game) {
163 		road->postsplit(*game, *this);
164 	}
165 }
166 
set_flag_position(Coords coords)167 void Flag::set_flag_position(Coords coords) {
168 	position_ = coords;
169 }
170 
get_size() const171 int32_t Flag::get_size() const {
172 	return SMALL;
173 }
174 
get_passable() const175 bool Flag::get_passable() const {
176 	return true;
177 }
178 
base_flag()179 Flag& Flag::base_flag() {
180 	return *this;
181 }
182 
183 /**
184  * Call this only from Economy code!
185  */
set_economy(Economy * const e,WareWorker type)186 void Flag::set_economy(Economy* const e, WareWorker type) {
187 	Economy* const old = get_economy(type);
188 
189 	if (old == e) {
190 		return;
191 	}
192 
193 	PlayerImmovable::set_economy(e, type);
194 
195 	if (type == wwWARE) {
196 		for (int32_t i = 0; i < ware_filled_; ++i) {
197 			wares_[i].ware->set_economy(e);
198 		}
199 	}
200 
201 	if (building_) {
202 		building_->set_economy(e, type);
203 	}
204 
205 	for (const FlagJob& temp_job : flag_jobs_) {
206 		if (temp_job.request->get_type() == type) {
207 			temp_job.request->set_economy(e);
208 		}
209 	}
210 
211 	for (RoadBase* const road : roads_) {
212 		if (road) {
213 			road->set_economy(e, type);
214 		}
215 	}
216 }
217 
218 /**
219  * Call this only from the Building init!
220  */
attach_building(EditorGameBase & egbase,Building & building)221 void Flag::attach_building(EditorGameBase& egbase, Building& building) {
222 	assert(!building_ || building_ == &building);
223 
224 	building_ = &building;
225 
226 	const Map& map = egbase.map();
227 	egbase.set_road(
228 	   map.get_fcoords(map.tl_n(position_)), WALK_SE,
229 	   building_->get_size() == BaseImmovable::SMALL ? RoadSegment::kNormal : RoadSegment::kBusy);
230 
231 	building.set_economy(get_economy(wwWARE), wwWARE);
232 	building.set_economy(get_economy(wwWORKER), wwWORKER);
233 }
234 
235 /**
236  * Call this only from the Building cleanup!
237  */
detach_building(EditorGameBase & egbase)238 void Flag::detach_building(EditorGameBase& egbase) {
239 	assert(building_);
240 
241 	building_->set_economy(nullptr, wwWARE);
242 	building_->set_economy(nullptr, wwWORKER);
243 
244 	const Map& map = egbase.map();
245 	egbase.set_road(map.get_fcoords(map.tl_n(position_)), WALK_SE, RoadSegment::kNone);
246 
247 	building_ = nullptr;
248 }
249 
250 /**
251  * Call this only from the RoadBase init!
252  */
attach_road(int32_t const dir,RoadBase * const road)253 void Flag::attach_road(int32_t const dir, RoadBase* const road) {
254 	assert(!roads_[dir - 1] || roads_[dir - 1] == road);
255 
256 	roads_[dir - 1] = road;
257 	roads_[dir - 1]->set_economy(get_economy(wwWARE), wwWARE);
258 	roads_[dir - 1]->set_economy(get_economy(wwWORKER), wwWORKER);
259 }
260 
261 /**
262  * Call this only from the RoadBase init!
263  */
detach_road(int32_t const dir)264 void Flag::detach_road(int32_t const dir) {
265 	assert(roads_[dir - 1]);
266 
267 	roads_[dir - 1]->set_economy(nullptr, wwWARE);
268 	roads_[dir - 1]->set_economy(nullptr, wwWORKER);
269 	roads_[dir - 1] = nullptr;
270 }
271 
272 /**
273  * \return all positions we occupy on the map. For a Flag, this is only one.
274  */
get_positions(const EditorGameBase &) const275 BaseImmovable::PositionList Flag::get_positions(const EditorGameBase&) const {
276 	PositionList rv;
277 	rv.push_back(position_);
278 	return rv;
279 }
280 
281 /**
282  * \return neighbouring flags.
283  */
get_neighbours(WareWorker type,RoutingNodeNeighbours & neighbours)284 void Flag::get_neighbours(WareWorker type, RoutingNodeNeighbours& neighbours) {
285 	for (RoadBase* const road : roads_) {
286 		if (!road) {
287 			continue;
288 		}
289 
290 		// Only wares, workers cannot use ferries
291 		if (Waterway::is_waterway_descr(&road->descr()) && type == wwWORKER) {
292 			continue;
293 		}
294 
295 		Flag* f = &road->get_flag(RoadBase::FlagEnd);
296 		int32_t nb_cost;
297 		if (f != this) {
298 			nb_cost = road->get_cost(RoadBase::FlagStart);
299 		} else {
300 			f = &road->get_flag(RoadBase::FlagStart);
301 			nb_cost = road->get_cost(RoadBase::FlagEnd);
302 		}
303 		if (type == wwWARE) {
304 			nb_cost += nb_cost * (get_waitcost() + f->get_waitcost()) / 2;
305 		}
306 		RoutingNodeNeighbour n(f, nb_cost);
307 
308 		assert(n.get_neighbour() != this);
309 		neighbours.push_back(n);
310 	}
311 
312 	if (building_ && building_->descr().get_isport()) {
313 		Warehouse* wh = static_cast<Warehouse*>(building_);
314 		if (PortDock* pd = wh->get_portdock()) {
315 			pd->add_neighbours(neighbours);
316 		}
317 	}
318 }
319 
320 /**
321  * \return the road that leads to the given flag.
322  */
get_roadbase(Flag & flag)323 RoadBase* Flag::get_roadbase(Flag& flag) {
324 	for (RoadBase* const road : roads_) {
325 		if (road) {
326 			if (&road->get_flag(RoadBase::FlagStart) == &flag ||
327 			    &road->get_flag(RoadBase::FlagEnd) == &flag) {
328 				return road;
329 			}
330 		}
331 	}
332 	return nullptr;
333 }
get_road(Flag & flag)334 Road* Flag::get_road(Flag& flag) {
335 	for (int8_t i = WalkingDir::FIRST_DIRECTION; i <= WalkingDir::LAST_DIRECTION; ++i) {
336 		if (Road* const road = get_road(i)) {
337 			if (&road->get_flag(RoadBase::FlagStart) == &flag ||
338 			    &road->get_flag(RoadBase::FlagEnd) == &flag) {
339 				return road;
340 			}
341 		}
342 	}
343 	return nullptr;
344 }
345 
get_road(uint8_t const dir) const346 Road* Flag::get_road(uint8_t const dir) const {
347 	if (roads_[dir - 1] && Road::is_road_descr(&roads_[dir - 1]->descr())) {
348 		return dynamic_cast<Road*>(roads_[dir - 1]);
349 	}
350 	return nullptr;
351 }
get_waterway(uint8_t const dir) const352 Waterway* Flag::get_waterway(uint8_t const dir) const {
353 	if (roads_[dir - 1] && Waterway::is_waterway_descr(&roads_[dir - 1]->descr())) {
354 		return dynamic_cast<Waterway*>(roads_[dir - 1]);
355 	}
356 	return nullptr;
357 }
358 
359 /// \return the number of RoadBases connected to the flag
nr_of_roadbases() const360 uint8_t Flag::nr_of_roadbases() const {
361 	uint8_t counter = 0;
362 	for (uint8_t road_id = WalkingDir::LAST_DIRECTION; road_id >= WalkingDir::FIRST_DIRECTION;
363 	     --road_id) {
364 		if (get_roadbase(road_id) != nullptr) {
365 			++counter;
366 		}
367 	}
368 	return counter;
369 }
370 
371 /// \return the number of roads connected to the flag.
nr_of_roads() const372 uint8_t Flag::nr_of_roads() const {
373 	uint8_t counter = 0;
374 	for (uint8_t road_id = WalkingDir::LAST_DIRECTION; road_id >= WalkingDir::FIRST_DIRECTION;
375 	     --road_id) {
376 		if (get_roadbase(road_id) != nullptr) {
377 			++counter;
378 		}
379 	}
380 	return counter;
381 }
382 
383 /// \return the number of waterways connected to the flag.
nr_of_waterways() const384 uint8_t Flag::nr_of_waterways() const {
385 	uint8_t counter = 0;
386 	for (uint8_t road_id = WalkingDir::LAST_DIRECTION; road_id >= WalkingDir::FIRST_DIRECTION;
387 	     --road_id) {
388 		if (get_waterway(road_id) != nullptr) {
389 			++counter;
390 		}
391 	}
392 	return counter;
393 }
394 
is_dead_end() const395 bool Flag::is_dead_end() const {
396 	if (get_building()) {
397 		return false;
398 	}
399 	Flag const* first_other_flag = nullptr;
400 	for (uint8_t road_id = WalkingDir::LAST_DIRECTION; road_id >= WalkingDir::FIRST_DIRECTION;
401 	     --road_id) {
402 		if (RoadBase* const road = get_roadbase(road_id)) {
403 			Flag& start = road->get_flag(RoadBase::FlagStart);
404 			Flag& other = this == &start ? road->get_flag(RoadBase::FlagEnd) : start;
405 			if (first_other_flag) {
406 				if (&other != first_other_flag)
407 					return false;
408 			} else {
409 				first_other_flag = &other;
410 			}
411 		}
412 	}
413 	return true;
414 }
415 
416 /**
417  * Returns true if the flag can hold more wares.
418  */
has_capacity() const419 bool Flag::has_capacity() const {
420 	return (ware_filled_ < ware_capacity_);
421 }
422 
423 /**
424  * Signal the given bob by interrupting its task as soon as capacity becomes
425  * free.
426  *
427  * The capacity queue is a simple FIFO queue.
428  */
wait_for_capacity(Game &,Worker & bob)429 void Flag::wait_for_capacity(Game&, Worker& bob) {
430 	capacity_wait_.push_back(&bob);
431 }
432 
433 /**
434  * Remove the worker from the list of workers waiting for free capacity.
435  */
skip_wait_for_capacity(Game &,Worker & w)436 void Flag::skip_wait_for_capacity(Game&, Worker& w) {
437 	CapacityWaitQueue::iterator const it =
438 	   std::find(capacity_wait_.begin(), capacity_wait_.end(), &w);
439 	if (it != capacity_wait_.end())
440 		capacity_wait_.erase(it);
441 }
442 
add_ware(EditorGameBase & egbase,WareInstance & ware)443 void Flag::add_ware(EditorGameBase& egbase, WareInstance& ware) {
444 
445 	assert(ware_filled_ < ware_capacity_);
446 
447 	PendingWare& pi = wares_[ware_filled_++];
448 	pi.ware = &ware;
449 	pi.pending = false;
450 	pi.nextstep = nullptr;
451 	pi.priority = 0;
452 
453 	Transfer* trans = ware.get_transfer();
454 	if (trans) {
455 		uint32_t trans_steps = trans->get_steps_left();
456 		if (trans_steps < 3) {
457 			pi.priority = 2;
458 		} else if (trans_steps == 3) {
459 			pi.priority = 1;
460 		}
461 
462 		Request* req = trans->get_request();
463 		if (req) {
464 			pi.priority = pi.priority + req->get_transfer_priority();
465 		}
466 	}
467 
468 	ware.set_location(egbase, this);
469 
470 	if (upcast(Game, game, &egbase)) {
471 		ware.update(*game);  //  will call call_carrier() if necessary
472 	}
473 }
474 
475 /**
476  * \return true if a ware is currently waiting for a carrier to the given Flag.
477  *
478  * \note Due to fetch_from_flag() semantics, this function makes no sense
479  * for a  building destination.
480  */
has_pending_ware(Game &,Flag & dest)481 bool Flag::has_pending_ware(Game&, Flag& dest) {
482 	for (int32_t i = 0; i < ware_filled_; ++i) {
483 		if (!wares_[i].pending) {
484 			continue;
485 		}
486 
487 		if (wares_[i].nextstep != &dest) {
488 			continue;
489 		}
490 
491 		return true;
492 	}
493 
494 	return false;
495 }
496 
497 /**
498  * Clamp the maximal value of \ref PendingWare::priority.
499  * After reaching this value, the pure FIFO approach is applied
500  */
501 #define MAX_TRANSFER_PRIORITY 16
502 
503 /**
504  * Called by carrier code to indicate that the carrier is moving to pick up an
505  * ware. Ware with highest transfer priority is chosen.
506  * \return true if an ware is actually waiting for the carrier.
507  */
ack_pickup(Game &,Flag & destflag)508 bool Flag::ack_pickup(Game&, Flag& destflag) {
509 	int32_t highest_pri = -1;
510 	int32_t i_pri = -1;
511 
512 	for (int32_t i = 0; i < ware_filled_; ++i) {
513 		if (!wares_[i].pending) {
514 			continue;
515 		}
516 
517 		if (wares_[i].nextstep != &destflag) {
518 			continue;
519 		}
520 
521 		if (wares_[i].priority > highest_pri) {
522 			highest_pri = wares_[i].priority;
523 			i_pri = i;
524 
525 			// Increase ware priority, it matters only if the ware has to wait.
526 			if (wares_[i].priority < MAX_TRANSFER_PRIORITY) {
527 				wares_[i].priority++;
528 			}
529 		}
530 	}
531 
532 	if (i_pri >= 0) {
533 		wares_[i_pri].pending = false;
534 		return true;
535 	}
536 
537 	return false;
538 }
539 /**
540  * Called by carrier code to find the best among the wares on this flag
541  * that are meant for the provided dest.
542  * \return index of found ware (carrier will take it)
543  * or kNotFoundAppropriate (carrier will leave empty-handed)
544  */
cancel_pickup(Game & game,Flag & destflag)545 bool Flag::cancel_pickup(Game& game, Flag& destflag) {
546 	int32_t lowest_prio = MAX_TRANSFER_PRIORITY + 1;
547 	int32_t i_pri = -1;
548 
549 	for (int32_t i = 0; i < ware_filled_; ++i) {
550 		if (wares_[i].pending) {
551 			continue;
552 		}
553 
554 		if (wares_[i].nextstep != &destflag) {
555 			continue;
556 		}
557 
558 		if (wares_[i].priority < lowest_prio) {
559 			lowest_prio = wares_[i].priority;
560 			i_pri = i;
561 		}
562 	}
563 
564 	if (i_pri >= 0) {
565 		wares_[i_pri].pending = true;
566 		wares_[i_pri].ware->update(game);  //  will call call_carrier() if necessary
567 		return true;
568 	}
569 
570 	return false;
571 }
572 
573 /**
574  * Wake one sleeper from the capacity queue.
575  */
wake_up_capacity_queue(Game & game)576 void Flag::wake_up_capacity_queue(Game& game) {
577 	while (!capacity_wait_.empty()) {
578 		Worker* const w = capacity_wait_.front().get(game);
579 		capacity_wait_.pop_front();
580 		if (w && w->wakeup_flag_capacity(game, *this)) {
581 			break;
582 		}
583 	}
584 }
585 
586 /**
587  * Called by carrier code to retrieve one of the wares on the flag that is meant
588  * for that carrier.
589  *
590  * This function may return 0 even if \ref ack_pickup() has already been
591  * called successfully.
592  */
fetch_pending_ware(Game & game,PlayerImmovable & dest)593 WareInstance* Flag::fetch_pending_ware(Game& game, PlayerImmovable& dest) {
594 	int32_t best_index = -1;
595 
596 	for (int32_t i = 0; i < ware_filled_; ++i) {
597 		if (wares_[i].nextstep != &dest) {
598 			continue;
599 		}
600 
601 		// We prefer to retrieve wares that have already been acked
602 		if (best_index < 0 || !wares_[i].pending) {
603 			best_index = i;
604 		}
605 	}
606 
607 	if (best_index < 0) {
608 		return nullptr;
609 	}
610 
611 	// move the other wares up the list and return this one
612 	WareInstance* const ware = wares_[best_index].ware;
613 	--ware_filled_;
614 	memmove(&wares_[best_index], &wares_[best_index + 1],
615 	        sizeof(wares_[0]) * (ware_filled_ - best_index));
616 
617 	ware->set_location(game, nullptr);
618 
619 	// wake up capacity wait queue
620 	wake_up_capacity_queue(game);
621 
622 	return ware;
623 }
624 
625 /**
626  * Accelerate potential promotion of roads adjacent to a newly promoted road.
627  */
propagate_promoted_road(Road * const promoted_road)628 void Flag::propagate_promoted_road(Road* const promoted_road) {
629 	// Abort if flag has a building attached to it
630 	if (building_) {
631 		return;
632 	}
633 
634 	// Calculate the sum of the involved wallets' adjusted value
635 	int32_t sum = 0;
636 	for (int8_t i = WalkingDir::FIRST_DIRECTION; i <= WalkingDir::LAST_DIRECTION; ++i) {
637 		Road* const road = get_road(i);
638 		if (road && road != promoted_road) {
639 			sum += kRoadMaxWallet + road->wallet() * road->wallet();
640 		}
641 	}
642 
643 	// Distribute propagation coins in a smart way
644 	for (int8_t i = WalkingDir::FIRST_DIRECTION; i <= WalkingDir::LAST_DIRECTION; ++i) {
645 		Road* const road = get_road(i);
646 		if (road && !road->is_busy()) {
647 			road->add_to_wallet(0.5 * (kRoadMaxWallet - road->wallet()) *
648 			                    (kRoadMaxWallet + road->wallet() * road->wallet()) / sum);
649 		}
650 	}
651 }
652 
653 /**
654  * Count only those wares which are awaiting to be carried along the same road.
655  */
count_wares_in_queue(PlayerImmovable & dest) const656 uint8_t Flag::count_wares_in_queue(PlayerImmovable& dest) const {
657 	uint8_t n = 0;
658 	for (int32_t i = 0; i < ware_filled_; ++i) {
659 		if (wares_[i].nextstep == &dest) {
660 			++n;
661 		}
662 	}
663 	return n;
664 }
665 
666 /**
667  * Return a List of all the wares currently on this Flag.
668  * Do not rely the result value to stay valid and do not change them.
669  */
get_wares()670 Flag::Wares Flag::get_wares() {
671 	Wares rv;
672 
673 	for (int32_t i = 0; i < ware_filled_; ++i) {
674 		rv.push_back(wares_[i].ware);
675 	}
676 
677 	return rv;
678 }
679 
680 /**
681  * Force a removal of the given ware from this flag.
682  * Called by \ref WareInstance::cleanup()
683  */
remove_ware(EditorGameBase & egbase,WareInstance * const ware)684 void Flag::remove_ware(EditorGameBase& egbase, WareInstance* const ware) {
685 	for (int32_t i = 0; i < ware_filled_; ++i) {
686 		if (wares_[i].ware != ware) {
687 			continue;
688 		}
689 
690 		--ware_filled_;
691 		memmove(&wares_[i], &wares_[i + 1], sizeof(wares_[0]) * (ware_filled_ - i));
692 
693 		if (upcast(Game, game, &egbase)) {
694 			wake_up_capacity_queue(*game);
695 		}
696 
697 		return;
698 	}
699 
700 	throw wexception("MO(%u): Flag::remove_ware: ware %u not on flag", serial(), ware->serial());
701 }
702 
703 /**
704  * If nextstep is not null, a carrier will be called to move this ware to
705  * the given flag or building.
706  *
707  * If nextstep is null, the internal data will be reset to indicate that the
708  * ware isn't going anywhere right now.
709  *
710  * nextstep is compared with the cached data, and a new carrier is only called
711  * if that data hasn't changed.
712  *
713  * This behaviour is overridden by always_call_for_step_, which is set by
714  * update_wares() to ensure that new carriers are called when roads are
715  * split, for example.
716  */
call_carrier(Game & game,WareInstance & ware,PlayerImmovable * const nextstep)717 void Flag::call_carrier(Game& game, WareInstance& ware, PlayerImmovable* const nextstep) {
718 	PendingWare* pi = nullptr;
719 	int32_t i = 0;
720 
721 	// Find the PendingWare entry
722 	for (; i < ware_filled_; ++i) {
723 		if (wares_[i].ware != &ware) {
724 			continue;
725 		}
726 
727 		pi = &wares_[i];
728 		break;
729 	}
730 
731 	assert(pi);
732 
733 	// Deal with the non-moving case quickly
734 	if (!nextstep) {
735 		pi->nextstep = nullptr;
736 		pi->pending = true;
737 		return;
738 	}
739 
740 	// Find out whether we need to do anything
741 	if (pi->nextstep == nextstep && pi->nextstep != always_call_for_flag_) {
742 		return;  // no update needed
743 	}
744 
745 	pi->nextstep = nextstep;
746 	pi->pending = false;
747 
748 	// Deal with the building case
749 	if (nextstep == get_building()) {
750 		molog("Flag::call_carrier(%u): Tell building to fetch this ware\n", ware.serial());
751 
752 		if (!get_building()->fetch_from_flag(game)) {
753 			pi->ware->cancel_moving();
754 			pi->ware->update(game);
755 		}
756 
757 		return;
758 	}
759 
760 	// Deal with the normal (flag) case
761 	const Flag& nextflag = dynamic_cast<const Flag&>(*nextstep);
762 
763 	for (int32_t dir = WalkingDir::FIRST_DIRECTION; dir <= WalkingDir::LAST_DIRECTION; ++dir) {
764 		RoadBase* const road = get_roadbase(dir);
765 		Flag* other;
766 		RoadBase::FlagId flagid;
767 
768 		if (!road) {
769 			continue;
770 		}
771 
772 		if (&road->get_flag(RoadBase::FlagStart) == this) {
773 			flagid = RoadBase::FlagStart;
774 			other = &road->get_flag(RoadBase::FlagEnd);
775 		} else {
776 			flagid = RoadBase::FlagEnd;
777 			other = &road->get_flag(RoadBase::FlagStart);
778 		}
779 
780 		if (other != &nextflag) {
781 			continue;
782 		}
783 
784 		// Yes, this is the road we want; inform it
785 		if (road->notify_ware(game, flagid)) {
786 			return;
787 		}
788 
789 		// If the road doesn't react to the ware immediately, we try other roads:
790 		// They might lead to the same flag!
791 	}
792 
793 	// Nothing found, just let it be picked up by somebody
794 	pi->pending = true;
795 	return;
796 }
797 
798 /**
799  * Called whenever a road gets broken or split.
800  * Make sure all wares on this flag are rerouted if necessary.
801  *
802  * \note When two roads connect the same two flags, and one of these roads
803  * is removed, this might cause the carrier(s) on the other road to
804  * move unnecessarily. Fixing this could potentially be very expensive and
805  * fragile.
806  * A similar thing can happen when a road is split.
807  */
update_wares(Game & game,Flag * const other)808 void Flag::update_wares(Game& game, Flag* const other) {
809 	always_call_for_flag_ = other;
810 
811 	for (int32_t i = 0; i < ware_filled_; ++i) {
812 		wares_[i].ware->update(game);
813 	}
814 
815 	always_call_for_flag_ = nullptr;
816 }
817 
init(EditorGameBase & egbase)818 bool Flag::init(EditorGameBase& egbase) {
819 	PlayerImmovable::init(egbase);
820 
821 	set_position(egbase, position_);
822 
823 	animstart_ = egbase.get_gametime();
824 	return true;
825 }
826 
827 /**
828  * Detach building and free roads.
829  */
cleanup(EditorGameBase & egbase)830 void Flag::cleanup(EditorGameBase& egbase) {
831 	while (!flag_jobs_.empty()) {
832 		delete flag_jobs_.begin()->request;
833 		flag_jobs_.erase(flag_jobs_.begin());
834 	}
835 
836 	while (ware_filled_) {
837 		WareInstance& ware = *wares_[--ware_filled_].ware;
838 
839 		ware.set_location(egbase, nullptr);
840 		ware.destroy(egbase);
841 	}
842 
843 	if (building_) {
844 		building_->remove(egbase);  //  immediate death
845 		assert(!building_);
846 	}
847 
848 	for (uint8_t i = 0; i < (sizeof(roads_) / sizeof(roads_[0])); ++i) {
849 		if (roads_[i]) {
850 			roads_[i]->remove(egbase);  //  immediate death
851 			assert(!roads_[i]);
852 		}
853 	}
854 
855 	if (Economy* e = get_economy(wwWARE)) {
856 		e->remove_flag(*this);
857 	}
858 	if (Economy* e = get_economy(wwWORKER)) {
859 		e->remove_flag(*this);
860 	}
861 
862 	unset_position(egbase, position_);
863 
864 	PlayerImmovable::cleanup(egbase);
865 }
866 
draw(uint32_t gametime,const InfoToDraw,const Vector2f & field_on_dst,const Coords & coords,float scale,RenderTarget * dst)867 void Flag::draw(uint32_t gametime,
868                 const InfoToDraw,
869                 const Vector2f& field_on_dst,
870                 const Coords& coords,
871                 float scale,
872                 RenderTarget* dst) {
873 	static struct {
874 		float x, y;
875 	} ware_offsets[8] = {{-5.f, 1.f},  {-1.f, 3.f},  {3.f, 3.f},  {7.f, 1.f},
876 	                     {-6.f, -3.f}, {-1.f, -2.f}, {3.f, -2.f}, {8.f, -3.f}};
877 
878 	const RGBColor& player_color = owner().get_playercolor();
879 	dst->blit_animation(field_on_dst, coords, scale, owner().tribe().flag_animation(),
880 	                    gametime - animstart_, &player_color);
881 
882 	for (int32_t i = 0; i < ware_filled_; ++i) {  //  draw wares
883 		Vector2f warepos = field_on_dst;
884 		if (i < 8) {
885 			warepos.x += ware_offsets[i].x * scale;
886 			warepos.y += ware_offsets[i].y * scale;
887 		} else {
888 			warepos.y -= (6.f + (i - 8.f) * 3.f) * scale;
889 		}
890 		dst->blit_animation(warepos, Widelands::Coords::null(), scale,
891 		                    wares_[i].ware->descr().get_animation("idle", wares_[i].ware), 0,
892 		                    &player_color);
893 	}
894 }
895 
896 /**
897  * Destroy the building as well.
898  *
899  * \note This is needed in addition to the call to building_->remove() in
900  * \ref Flag::cleanup(). This function is needed to ensure a fire is created
901  * when a player removes a flag.
902  */
destroy(EditorGameBase & egbase)903 void Flag::destroy(EditorGameBase& egbase) {
904 	if (building_) {
905 		building_->destroy(egbase);
906 		assert(!building_);
907 	}
908 
909 	PlayerImmovable::destroy(egbase);
910 }
911 
912 /**
913  * Add a new flag job to request the worker with the given ID,
914  * and to execute the given program once it's completed.
915  */
add_flag_job(Game &,DescriptionIndex const workerware,const std::string & programname)916 void Flag::add_flag_job(Game&, DescriptionIndex const workerware, const std::string& programname) {
917 	FlagJob j;
918 
919 	j.request = new Request(*this, workerware, Flag::flag_job_request_callback, wwWORKER);
920 	j.program = programname;
921 
922 	flag_jobs_.push_back(j);
923 }
924 
925 /**
926  * This function is called when one of the flag job workers arrives on
927  * the flag. Give him his job.
928  */
flag_job_request_callback(Game & game,Request & rq,DescriptionIndex,Worker * const w,PlayerImmovable & target)929 void Flag::flag_job_request_callback(
930    Game& game, Request& rq, DescriptionIndex, Worker* const w, PlayerImmovable& target) {
931 	Flag& flag = dynamic_cast<Flag&>(target);
932 
933 	assert(w);
934 
935 	for (FlagJobs::iterator flag_iter = flag.flag_jobs_.begin(); flag_iter != flag.flag_jobs_.end();
936 	     ++flag_iter) {
937 		if (flag_iter->request == &rq) {
938 			delete &rq;
939 
940 			w->start_task_program(game, flag_iter->program);
941 
942 			flag.flag_jobs_.erase(flag_iter);
943 			return;
944 		}
945 	}
946 
947 	flag.molog("BUG: flag_job_request_callback: worker not found in list\n");
948 }
949 
log_general_info(const Widelands::EditorGameBase & egbase) const950 void Flag::log_general_info(const Widelands::EditorGameBase& egbase) const {
951 	molog("Flag at %i,%i\n", position_.x, position_.y);
952 
953 	Widelands::PlayerImmovable::log_general_info(egbase);
954 
955 	if (ware_filled_) {
956 		molog("Wares at flag:\n");
957 		for (int i = 0; i < ware_filled_; ++i) {
958 			PendingWare& pi = wares_[i];
959 			molog(" %i/%i: %s(%i), nextstep %i, %s\n", i + 1, ware_capacity_,
960 			      pi.ware->descr().name().c_str(), pi.ware->serial(), pi.nextstep.serial(),
961 			      pi.pending ? "pending" : "acked by carrier");
962 		}
963 	} else {
964 		molog("No wares at flag.\n");
965 	}
966 }
967 }  // namespace Widelands
968