Merge lp:~widelands-dev/widelands/remove-anti-congestion-algorithm into lp:widelands

Proposed by GunChleoc
Status: Merged
Merged at revision: 8936
Proposed branch: lp:~widelands-dev/widelands/remove-anti-congestion-algorithm
Merge into: lp:widelands
Diff against target: 1225 lines (+414/-446)
8 files modified
src/economy/flag.cc (+126/-255)
src/economy/flag.h (+11/-20)
src/economy/road.cc (+1/-2)
src/economy/road.h (+3/-3)
src/logic/map_objects/tribes/carrier.cc (+233/-134)
src/logic/map_objects/tribes/carrier.h (+11/-9)
src/logic/map_objects/tribes/worker.cc (+28/-22)
src/logic/map_objects/tribes/worker.h (+1/-1)
To merge this branch: bzr merge lp:~widelands-dev/widelands/remove-anti-congestion-algorithm
Reviewer Review Type Date Requested Status
Widelands Developers Pending
Review via email: mp+359294@code.launchpad.net

Commit message

Remove the anti-congestion algorithm introduced in r8775 because it has too many bugs in it.

To post a comment you must log in.
Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4272. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/458903460.
Appveyor build 4066. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_remove_anti_congestion_algorithm-4066.

Revision history for this message
GunChleoc (gunchleoc) wrote :

We can't start working on the desyncs without this branch, so I'm gonna merge.

@bunnybot merge

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4286. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/459339126.
Appveyor build 4080. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_remove_anti_congestion_algorithm-4080.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Refusing to merge, since Travis is not green. Use @bunnybot merge force for merging anyways.

Travis build 4286. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/459339126.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4293. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/459617030.
Appveyor build 4086. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_remove_anti_congestion_algorithm-4086.

Revision history for this message
GunChleoc (gunchleoc) wrote :

@bunnybot merge

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/economy/flag.cc'
--- src/economy/flag.cc 2018-09-04 15:48:47 +0000
+++ src/economy/flag.cc 2018-11-26 06:43:43 +0000
@@ -337,30 +337,7 @@
337}337}
338338
339/**339/**
340 * Called by workers wanting to drop a ware to their building's flag.340 * Returns true if the flag can hold more wares.
341 * \return true/allow on low congestion-risk.
342 */
343bool Flag::has_capacity_for_ware(WareInstance& ware) const {
344 // avoid iteration for the easy cases
345 if (ware_filled_ < ware_capacity_ - 2) {
346 return true; // more than two free slots, allow
347 }
348 if (ware_filled_ >= ware_capacity_) {
349 return false; // all slots filled, no room
350 }
351
352 DescriptionIndex const descr_index = ware.descr_index();
353 for (int i = 0; i < ware_filled_; ++i) {
354 if (wares_[i].ware->descr_index() == descr_index) {
355 return false; // ware of this type already present, leave room for other types
356 }
357 }
358 return true; // ware of this type not present, allow
359}
360
361/**
362 * \return true/allow if the flag can hold more wares of any type.
363 * has_capacity_for_ware() also checks ware's type to prevent congestion.
364 */341 */
365bool Flag::has_capacity() const {342bool Flag::has_capacity() const {
366 return (ware_filled_ < ware_capacity_);343 return (ware_filled_ < ware_capacity_);
@@ -386,24 +363,13 @@
386 capacity_wait_.erase(it);363 capacity_wait_.erase(it);
387}364}
388365
389/**
390 * Adds given ware to this flag.
391 * Please check has_capacity() or better has_capacity_for_ware() before.
392 */
393void Flag::add_ware(EditorGameBase& egbase, WareInstance& ware) {366void Flag::add_ware(EditorGameBase& egbase, WareInstance& ware) {
367
394 assert(ware_filled_ < ware_capacity_);368 assert(ware_filled_ < ware_capacity_);
395 init_ware(egbase, ware, wares_[ware_filled_++]);
396 if (upcast(Game, game, &egbase)) {
397 ware.update(*game); // will call call_carrier() if necessary
398 }
399}
400369
401/**370 PendingWare& pi = wares_[ware_filled_++];
402 * Properly assigns given ware instance to given pending ware.
403 */
404void Flag::init_ware(EditorGameBase& egbase, WareInstance& ware, PendingWare& pi) {
405 pi.ware = &ware;371 pi.ware = &ware;
406 pi.pending = true;372 pi.pending = false;
407 pi.nextstep = nullptr;373 pi.nextstep = nullptr;
408 pi.priority = 0;374 pi.priority = 0;
409375
@@ -423,24 +389,32 @@
423 }389 }
424390
425 ware.set_location(egbase, this);391 ware.set_location(egbase, this);
392
393 if (upcast(Game, game, &egbase)) {
394 ware.update(*game); // will call call_carrier() if necessary
395 }
426}396}
427397
428/**398/**
429 * \return a ware currently waiting for a carrier to the given destflag.399 * \return true if a ware is currently waiting for a carrier to the given Flag.
430 *400 *
431 * \note Due to fetch_from_flag() semantics, this function makes no sense401 * \note Due to fetch_from_flag() semantics, this function makes no sense
432 * for a building destination.402 * for a building destination.
433*/403*/
434Flag::PendingWare* Flag::get_ware_for_flag(Flag& destflag, bool const pending_only) {404bool Flag::has_pending_ware(Game&, Flag& dest) {
435 for (int32_t i = 0; i < ware_filled_; ++i) {405 for (int32_t i = 0; i < ware_filled_; ++i) {
436 PendingWare* pw = &wares_[i];406 if (!wares_[i].pending) {
437 if ((!pending_only || pw->pending) && pw->nextstep == &destflag &&407 continue;
438 destflag.allow_ware_from_flag(*pw->ware, *this)) {408 }
439 return pw;409
440 }410 if (wares_[i].nextstep != &dest) {
411 continue;
412 }
413
414 return true;
441 }415 }
442416
443 return nullptr;417 return false;
444}418}
445419
446/**420/**
@@ -450,124 +424,109 @@
450#define MAX_TRANSFER_PRIORITY 16424#define MAX_TRANSFER_PRIORITY 16
451425
452/**426/**
453 * Called by the carriercode when the carrier is called away from his job427 * Called by carrier code to indicate that the carrier is moving to pick up an
454 * but has acknowledged a ware before. This ware is then freed again428 * ware. Ware with highest transfer priority is chosen.
455 * to be picked by another carrier. Returns true if a ware was indeed429 * \return true if an ware is actually waiting for the carrier.
456 * made pending again.
457 */430 */
458bool Flag::cancel_pickup(Game& game, Flag& destflag) {431bool Flag::ack_pickup(Game&, Flag& destflag) {
432 int32_t highest_pri = -1;
433 int32_t i_pri = -1;
434
459 for (int32_t i = 0; i < ware_filled_; ++i) {435 for (int32_t i = 0; i < ware_filled_; ++i) {
460 PendingWare& pw = wares_[i];436 if (!wares_[i].pending) {
461 if (!pw.pending && pw.nextstep == &destflag) {437 continue;
462 pw.pending = true;438 }
463 pw.ware->update(game); // will call call_carrier() if necessary439
464 return true;440 if (wares_[i].nextstep != &destflag) {
465 }441 continue;
442 }
443
444 if (wares_[i].priority > highest_pri) {
445 highest_pri = wares_[i].priority;
446 i_pri = i;
447
448 // Increase ware priority, it matters only if the ware has to wait.
449 if (wares_[i].priority < MAX_TRANSFER_PRIORITY) {
450 wares_[i].priority++;
451 }
452 }
453 }
454
455 if (i_pri >= 0) {
456 wares_[i_pri].pending = false;
457 return true;
466 }458 }
467459
468 return false;460 return false;
469}461}
470
471/**462/**
472 * Called by carrier code to find the best among the wares on this flag463 * Called by carrier code to find the best among the wares on this flag
473 * that are meant for the provided dest.464 * that are meant for the provided dest.
474 * \return index of found ware (carrier will take it)465 * \return index of found ware (carrier will take it)
475 * or kNotFoundAppropriate (carrier will leave empty-handed)466 * or kNotFoundAppropriate (carrier will leave empty-handed)
476 */467 */
477int32_t Flag::find_pending_ware(PlayerImmovable& dest) {468bool Flag::cancel_pickup(Game& game, Flag& destflag) {
478 int32_t highest_pri = -1;469 int32_t lowest_prio = MAX_TRANSFER_PRIORITY + 1;
479 int32_t best_index = kNotFoundAppropriate;470 int32_t i_pri = -1;
480 bool ware_pended = false;471
481472 for (int32_t i = 0; i < ware_filled_; ++i) {
482 for (int32_t i = 0; i < ware_filled_; ++i) {473 if (wares_[i].pending) {
483 PendingWare& pw = wares_[i];474 continue;
484 if (pw.nextstep != &dest) {475 }
485 continue;476
486 }477 if (wares_[i].nextstep != &destflag) {
487478 continue;
488 if (pw.priority < MAX_TRANSFER_PRIORITY) {479 }
489 pw.priority++;480
490 }481 if (wares_[i].priority < lowest_prio) {
491 // Release promised pickup, in case we find a preferable ware482 lowest_prio = wares_[i].priority;
492 if (!ware_pended && !pw.pending) {483 i_pri = i;
493 ware_pended = pw.pending = true;484 }
494 }485 }
495486
496 // If dest is flag, we exclude wares that can stress it487 if (i_pri >= 0) {
497 if (&dest != building_ && !dynamic_cast<Flag&>(dest).allow_ware_from_flag(*pw.ware, *this)) {488 wares_[i_pri].pending = true;
498 continue;489 wares_[i_pri].ware->update(game); // will call call_carrier() if necessary
499 }490 return true;
500491 }
501 if (pw.priority > highest_pri) {492
502 highest_pri = pw.priority;493 return false;
503 best_index = i;494}
504 }495
505 }496/**
506497 * Wake one sleeper from the capacity queue.
507 return best_index;498*/
508}499void Flag::wake_up_capacity_queue(Game& game) {
509500 while (!capacity_wait_.empty()) {
510/**501 Worker* const w = capacity_wait_.front().get(game);
511 * Like find_pending_ware() above, but for carriers who have a ware to drop on this flag.502 capacity_wait_.pop_front();
512 * \return same as find_pending_ware() above, plus kDenyDrop (carrier will wait)503 if (w && w->wakeup_flag_capacity(game, *this)) {
513 */504 break;
514int32_t Flag::find_swappable_ware(WareInstance& ware, Flag& destflag) {505 }
515 DescriptionIndex const descr_index = ware.descr_index();506 }
516 int32_t highest_pri = -1;507}
517 int32_t best_index = kNotFoundAppropriate;508
518 bool has_same_ware = false;509/**
519 bool has_allowed = false;510 * Called by carrier code to retrieve one of the wares on the flag that is meant
520 bool ware_pended = false;511 * for that carrier.
521512 *
522 for (int32_t i = 0; i < ware_filled_; ++i) {513 * This function may return 0 even if \ref ack_pickup() has already been
523 PendingWare& pw = wares_[i];514 * called successfully.
524 if (pw.nextstep != &destflag) {515*/
525 if (pw.ware->descr_index() == descr_index) {516WareInstance* Flag::fetch_pending_ware(Game& game, PlayerImmovable& dest) {
526 has_same_ware = true;517 int32_t best_index = -1;
527 }518
528 continue;519 for (int32_t i = 0; i < ware_filled_; ++i) {
529 }520 if (wares_[i].nextstep != &dest) {
530521 continue;
531 if (pw.priority < MAX_TRANSFER_PRIORITY) {522 }
532 pw.priority++;523
533 }524 // We prefer to retrieve wares that have already been acked
534 // Release promised pickup, in case we find a preferable ware525 if (best_index < 0 || !wares_[i].pending) {
535 if (!ware_pended && !pw.pending) {526 best_index = i;
536 ware_pended = pw.pending = true;527 }
537 }528 }
538529
539 // We prefer to retrieve wares that won't stress the destflag
540 if (destflag.allow_ware_from_flag(*pw.ware, *this)) {
541 if (!has_allowed) {
542 has_allowed = true;
543 highest_pri = -1;
544 }
545 } else {
546 if (has_allowed) {
547 continue;
548 }
549 }
550
551 if (pw.priority > highest_pri) {
552 highest_pri = pw.priority;
553 best_index = i;
554 }
555 }
556
557 if (best_index > kNotFoundAppropriate) {
558 return (ware_filled_ > ware_capacity_ - 3 || has_allowed) ? best_index : kNotFoundAppropriate;
559 } else {
560 return (ware_filled_ < ware_capacity_ - 2 ||
561 (ware_filled_ < ware_capacity_ && !has_same_ware)) ?
562 kNotFoundAppropriate :
563 kDenyDrop;
564 }
565}
566
567/**
568 * Called by carrier code to retrieve a ware found by the previous methods.
569 */
570WareInstance* Flag::fetch_pending_ware(Game& game, int32_t best_index) {
571 if (best_index < 0) {530 if (best_index < 0) {
572 return nullptr;531 return nullptr;
573 }532 }
@@ -579,43 +538,14 @@
579 sizeof(wares_[0]) * (ware_filled_ - best_index));538 sizeof(wares_[0]) * (ware_filled_ - best_index));
580539
581 ware->set_location(game, nullptr);540 ware->set_location(game, nullptr);
541
542 // wake up capacity wait queue
543 wake_up_capacity_queue(game);
544
582 return ware;545 return ware;
583}546}
584547
585/**548/**
586 * Called by carrier code to notify waiting carriers
587 * which may be interested in the new state of this flag.
588 */
589void Flag::ware_departing(Game& game) {
590 // Wake up one sleeper from the capacity queue.
591 while (!capacity_wait_.empty()) {
592 Worker* const w = capacity_wait_.front().get(game);
593 capacity_wait_.erase(capacity_wait_.begin());
594 if (w && w->wakeup_flag_capacity(game, *this)) {
595 return;
596 }
597 }
598
599 // Consider pending wares of neighboring flags.
600 for (int32_t dir = 1; dir <= WalkingDir::LAST_DIRECTION; ++dir) {
601 Road* const road = get_road(dir);
602 if (!road) {
603 continue;
604 }
605
606 Flag* other = &road->get_flag(Road::FlagEnd);
607 if (other == this) {
608 other = &road->get_flag(Road::FlagStart);
609 }
610
611 PendingWare* pw = other->get_ware_for_flag(*this, kPendingOnly);
612 if (pw && road->notify_ware(game, *other)) {
613 pw->pending = false;
614 }
615 }
616}
617
618/**
619 * Accelerate potential promotion of roads adjacent to a newly promoted road.549 * Accelerate potential promotion of roads adjacent to a newly promoted road.
620 */550 */
621void Flag::propagate_promoted_road(Road* const promoted_road) {551void Flag::propagate_promoted_road(Road* const promoted_road) {
@@ -684,7 +614,7 @@
684 memmove(&wares_[i], &wares_[i + 1], sizeof(wares_[0]) * (ware_filled_ - i));614 memmove(&wares_[i], &wares_[i + 1], sizeof(wares_[0]) * (ware_filled_ - i));
685615
686 if (upcast(Game, game, &egbase)) {616 if (upcast(Game, game, &egbase)) {
687 ware_departing(*game);617 wake_up_capacity_queue(*game);
688 }618 }
689619
690 return;620 return;
@@ -755,20 +685,27 @@
755685
756 for (int32_t dir = 1; dir <= 6; ++dir) {686 for (int32_t dir = 1; dir <= 6; ++dir) {
757 Road* const road = get_road(dir);687 Road* const road = get_road(dir);
688 Flag* other;
689 Road::FlagId flagid;
690
758 if (!road) {691 if (!road) {
759 continue;692 continue;
760 }693 }
761694
762 Flag* other = &road->get_flag(Road::FlagEnd);695 if (&road->get_flag(Road::FlagStart) == this) {
763 if (other == this) {696 flagid = Road::FlagStart;
697 other = &road->get_flag(Road::FlagEnd);
698 } else {
699 flagid = Road::FlagEnd;
764 other = &road->get_flag(Road::FlagStart);700 other = &road->get_flag(Road::FlagStart);
765 }701 }
702
766 if (other != &nextflag) {703 if (other != &nextflag) {
767 continue;704 continue;
768 }705 }
769706
770 // Yes, this is the road we want; inform it707 // Yes, this is the road we want; inform it
771 if (other->update_ware_from_flag(game, wares_[i], *road, *this)) {708 if (road->notify_ware(game, flagid)) {
772 return;709 return;
773 }710 }
774711
@@ -782,72 +719,6 @@
782}719}
783720
784/**721/**
785 * Called by neighboring flags, before agreeing for a carrier
786 * to take one of their wares heading to this flag.
787 * \return true/allow on low congestion-risk.
788 */
789bool Flag::allow_ware_from_flag(WareInstance& ware, Flag& flag) {
790 // avoid iteration for the easy cases
791 if (ware_filled_ < ware_capacity_ - 2) {
792 return true;
793 }
794
795 DescriptionIndex const descr_index = ware.descr_index();
796 bool has_swappable = false;
797 for (int i = 0; i < ware_filled_; ++i) {
798 PendingWare& pw = wares_[i];
799 if (pw.pending && pw.nextstep == &flag) {
800 has_swappable = true;
801 } else if (pw.ware->descr_index() == descr_index) {
802 return false;
803 }
804 }
805 return ware_filled_ < ware_capacity_ || has_swappable;
806}
807
808/**
809 * Called when a ware is trying to reach this flag through the provided road,
810 * having just arrived to the provided flag.
811 * Swaps pending wares if possible. Otherwise,
812 * asks road for carrier on low congestion-risk.
813 * \return false if the ware is not immediately served.
814 */
815bool Flag::update_ware_from_flag(Game& game, PendingWare& pw1, Road& road, Flag& flag) {
816 WareInstance& w1 = *pw1.ware;
817 DescriptionIndex const w1_descr_index = w1.descr_index();
818 bool has_same_ware = false;
819 bool has_swappable = false;
820 for (int i = 0; i < ware_filled_; ++i) {
821 PendingWare& pw2 = wares_[i];
822 WareInstance& w2 = *pw2.ware;
823 if (w2.descr_index() == w1_descr_index) {
824 if (pw2.nextstep == &flag) {
825 // swap pending wares remotely
826 init_ware(game, w1, pw2);
827 flag.init_ware(game, w2, pw1);
828 w1.update(game);
829 w2.update(game);
830 return true;
831 }
832
833 has_same_ware = true;
834 } else if (pw2.pending && pw2.nextstep == &flag) {
835 has_swappable = true;
836 }
837 }
838
839 // ask road for carrier on low congestion-risk
840 if (ware_filled_ < ware_capacity_ - 2 ||
841 (!has_same_ware && (ware_filled_ < ware_capacity_ || has_swappable))) {
842 if (road.notify_ware(game, flag)) {
843 pw1.pending = false;
844 return true;
845 }
846 }
847 return false;
848}
849
850/**
851 * Called whenever a road gets broken or split.722 * Called whenever a road gets broken or split.
852 * Make sure all wares on this flag are rerouted if necessary.723 * Make sure all wares on this flag are rerouted if necessary.
853 *724 *
854725
=== modified file 'src/economy/flag.h'
--- src/economy/flag.h 2018-09-25 06:32:35 +0000
+++ src/economy/flag.h 2018-11-26 06:43:43 +0000
@@ -47,10 +47,6 @@
47 DISALLOW_COPY_AND_ASSIGN(FlagDescr);47 DISALLOW_COPY_AND_ASSIGN(FlagDescr);
48};48};
4949
50constexpr bool kPendingOnly = true; // ignore non-pending wares
51constexpr int32_t kNotFoundAppropriate = -1; // no ware appropiate for carrying
52constexpr int32_t kDenyDrop = -2; // flag is full and no ware appropiate for swapping
53
54/**50/**
55 * Flag represents a flag as you see it on the map.51 * Flag represents a flag as you see it on the map.
56 *52 *
@@ -125,15 +121,7 @@
125121
126 bool is_dead_end() const;122 bool is_dead_end() const;
127123
128 struct PendingWare {
129 WareInstance* ware; ///< the ware itself
130 bool pending; ///< if the ware is pending
131 int32_t priority; ///< carrier prefers the ware with highest priority
132 OPtr<PlayerImmovable> nextstep; ///< next step that this ware is sent to
133 };
134
135 bool has_capacity() const;124 bool has_capacity() const;
136 bool has_capacity_for_ware(WareInstance&) const;
137 uint32_t total_capacity() {125 uint32_t total_capacity() {
138 return ware_capacity_;126 return ware_capacity_;
139 }127 }
@@ -143,14 +131,10 @@
143 void wait_for_capacity(Game&, Worker&);131 void wait_for_capacity(Game&, Worker&);
144 void skip_wait_for_capacity(Game&, Worker&);132 void skip_wait_for_capacity(Game&, Worker&);
145 void add_ware(EditorGameBase&, WareInstance&);133 void add_ware(EditorGameBase&, WareInstance&);
146 void init_ware(EditorGameBase&, WareInstance&, PendingWare&);134 bool has_pending_ware(Game&, Flag& destflag);
147 PendingWare* get_ware_for_flag(Flag&, bool pending_only = false);135 bool ack_pickup(Game&, Flag& destflag);
148 bool cancel_pickup(Game&, Flag& destflag);136 bool cancel_pickup(Game&, Flag& destflag);
149 void ware_departing(Game&);137 WareInstance* fetch_pending_ware(Game&, PlayerImmovable& dest);
150 bool allow_ware_from_flag(WareInstance&, Flag&);
151 int32_t find_swappable_ware(WareInstance&, Flag&);
152 int32_t find_pending_ware(PlayerImmovable&);
153 WareInstance* fetch_pending_ware(Game&, int32_t);
154 void propagate_promoted_road(Road* promoted_road);138 void propagate_promoted_road(Road* promoted_road);
155 Wares get_wares();139 Wares get_wares();
156 uint8_t count_wares_in_queue(PlayerImmovable& dest) const;140 uint8_t count_wares_in_queue(PlayerImmovable& dest) const;
@@ -171,13 +155,20 @@
171 void155 void
172 draw(uint32_t gametime, const Vector2f& point_on_dst, float scale, RenderTarget* dst) override;156 draw(uint32_t gametime, const Vector2f& point_on_dst, float scale, RenderTarget* dst) override;
173157
158 void wake_up_capacity_queue(Game&);
159
174 static void160 static void
175 flag_job_request_callback(Game&, Request&, DescriptionIndex, Worker*, PlayerImmovable&);161 flag_job_request_callback(Game&, Request&, DescriptionIndex, Worker*, PlayerImmovable&);
176162
177 void set_flag_position(Coords coords);163 void set_flag_position(Coords coords);
178164
179private:165private:
180 bool update_ware_from_flag(Game&, PendingWare&, Road&, Flag&);166 struct PendingWare {
167 WareInstance* ware; ///< the ware itself
168 bool pending; ///< if the ware is pending
169 int32_t priority; ///< carrier prefers the ware with highest priority
170 OPtr<PlayerImmovable> nextstep; ///< next step that this ware is sent to
171 };
181172
182 struct FlagJob {173 struct FlagJob {
183 Request* request;174 Request* request;
184175
=== modified file 'src/economy/road.cc'
--- src/economy/road.cc 2018-09-04 15:48:47 +0000
+++ src/economy/road.cc 2018-11-26 06:43:43 +0000
@@ -542,8 +542,7 @@
542 * Try to pick up a ware from the given flag.542 * Try to pick up a ware from the given flag.
543 * \return true if a carrier has been sent on its way, false otherwise.543 * \return true if a carrier has been sent on its way, false otherwise.
544 */544 */
545bool Road::notify_ware(Game& game, Flag& flag) {545bool Road::notify_ware(Game& game, FlagId const flagid) {
546 FlagId flagid = &flag == flags_[Road::FlagEnd] ? Road::FlagEnd : Road::FlagStart;
547 // Iterate over all carriers and try to find one which will take the ware546 // Iterate over all carriers and try to find one which will take the ware
548 for (CarrierSlot& slot : carrier_slots_) {547 for (CarrierSlot& slot : carrier_slots_) {
549 if (Carrier* const carrier = slot.carrier.get(game)) {548 if (Carrier* const carrier = slot.carrier.get(game)) {
550549
=== modified file 'src/economy/road.h'
--- src/economy/road.h 2018-09-25 06:32:35 +0000
+++ src/economy/road.h 2018-11-26 06:43:43 +0000
@@ -113,7 +113,7 @@
113 void presplit(Game&, Coords split);113 void presplit(Game&, Coords split);
114 void postsplit(Game&, Flag&);114 void postsplit(Game&, Flag&);
115115
116 bool notify_ware(Game& game, Flag& flag);116 bool notify_ware(Game& game, FlagId flagid);
117 void update_wallet_chargetime(Game& game);117 void update_wallet_chargetime(Game& game);
118 void charge_wallet(Game& game);118 void charge_wallet(Game& game);
119 int32_t wallet() const;119 int32_t wallet() const;
@@ -148,8 +148,8 @@
148 uint8_t carriers_count() const;148 uint8_t carriers_count() const;
149149
150private:150private:
151 /// Counter that is incremented for every ware served by this road151 /// Counter that is incremented when a ware does not get a carrier for this
152 /// according to the delay of service and decremented over time.152 /// road immediately and decremented over time.
153 int32_t wallet_;153 int32_t wallet_;
154154
155 /// holds the gametime when wallet_ was last charged155 /// holds the gametime when wallet_ was last charged
156156
=== modified file 'src/logic/map_objects/tribes/carrier.cc'
--- src/logic/map_objects/tribes/carrier.cc 2018-10-30 18:40:57 +0000
+++ src/logic/map_objects/tribes/carrier.cc 2018-11-26 06:43:43 +0000
@@ -51,7 +51,7 @@
5151
52 top_state().ivar1 = 0;52 top_state().ivar1 = 0;
5353
54 operation_ = INIT;54 promised_pickup_to_ = NOONE;
55}55}
5656
57/**57/**
@@ -78,14 +78,15 @@
78 return pop_task(game);78 return pop_task(game);
79 }79 }
8080
81 if (operation_ == INIT) {81 // Check for pending wares
82 operation_ = find_source_flag(game);82 if (promised_pickup_to_ == NOONE) {
83 find_pending_ware(game);
83 }84 }
8485
85 if (operation_ > NO_OPERATION) {86 if (promised_pickup_to_ != NOONE) {
86 if (state.ivar1) {87 if (state.ivar1) {
87 state.ivar1 = 0;88 state.ivar1 = 0;
88 return start_task_transport(game, operation_);89 return start_task_transport(game, promised_pickup_to_);
89 } else {90 } else {
90 // Short delay before we move to pick up91 // Short delay before we move to pick up
91 state.ivar1 = 1;92 state.ivar1 = 1;
@@ -119,10 +120,10 @@
119 * a ware there, we have to make sure that they do not count on us anymore.120 * a ware there, we have to make sure that they do not count on us anymore.
120 */121 */
121void Carrier::road_pop(Game& game, State& /* state */) {122void Carrier::road_pop(Game& game, State& /* state */) {
122 if (operation_ > NO_OPERATION && get_location(game)) {123 if (promised_pickup_to_ != NOONE && get_location(game)) {
123 Road& road = dynamic_cast<Road&>(*get_location(game));124 Road& road = dynamic_cast<Road&>(*get_location(game));
124 Flag& flag = road.get_flag(static_cast<Road::FlagId>(operation_));125 Flag& flag = road.get_flag(static_cast<Road::FlagId>(promised_pickup_to_));
125 Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(operation_ ^ 1));126 Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(promised_pickup_to_ ^ 1));
126127
127 flag.cancel_pickup(game, otherflag);128 flag.cancel_pickup(game, otherflag);
128 }129 }
@@ -160,99 +161,35 @@
160 return pop_task(game);161 return pop_task(game);
161 }162 }
162163
163 int32_t const ivar1 = state.ivar1;164 if (state.ivar1 == -1) {
164 if (ivar1 == -1) {
165 // If we're "in" the target building, special code applies165 // If we're "in" the target building, special code applies
166 return deliver_to_building(game, state);166 deliver_to_building(game, state);
167 }167 } else if (!does_carry_ware()) {
168168 // If we don't carry something, walk to the flag
169 WareInstance* ware = get_carried_ware(game);169 pickup_from_flag(game, state);
170 if (ware) {170 } else {
171 assert(ware->get_location(game) == this);171 Road& road = dynamic_cast<Road&>(*get_location(game));
172 }172 // If the ware should go to the building attached to our flag, walk
173173 // directly into said building
174 Road& road = dynamic_cast<Road&>(*get_location(game));174 Flag& flag = road.get_flag(static_cast<Road::FlagId>(state.ivar1 ^ 1));
175 int32_t const dest = ware ? ivar1 ^ 1 : ivar1;175
176 Flag& flag = road.get_flag(static_cast<Road::FlagId>(dest));176 WareInstance& ware = *get_carried_ware(game);
177177 assert(ware.get_location(game) == this);
178 if (ware) {178
179 // If the ware should go to the building attached to our flag,
180 // walk directly into said building
181 // A sanity check is necessary, in case the building has been destroyed179 // A sanity check is necessary, in case the building has been destroyed
180 PlayerImmovable* const next = ware.get_next_move_step(game);
182181
183 PlayerImmovable* const next = ware->get_next_move_step(game);
184 if (next && next != &flag && &next->base_flag() == &flag) {182 if (next && next != &flag && &next->base_flag() == &flag) {
185 // pay some coins before entering the building,183 // pay some coins before entering the building,
186 // to compensate for the time to be spent in its street-segment184 // to compensate for the time to be spent in its street-segment
187 road.pay_for_building();185 road.pay_for_building();
188186 enter_building(game, state);
189 if (!start_task_walktoflag(game, dest)) {187 } else if ((flag.has_capacity() || !swap_or_wait(game, state)) &&
190 // Enter building188 !start_task_walktoflag(game, state.ivar1 ^ 1)) {
191 state.ivar1 = -1;189 // If the flag is overloaded we are allowed to drop wares as
192 start_task_move(game, WALK_NW, descr().get_right_walk_anims(does_carry_ware()), true);190 // long as we can pick another up. Otherwise we have to wait.
193 }191 // Drop the ware, possible exchanging it with another one
194 return;192 drop_ware(game, state);
195 }
196 }
197
198 if (!start_task_walktoflag(game, dest, operation_ == WAIT)) {
199 // If the flag is overloaded we are allowed to drop wares,
200 // as long as we can pick another up. Otherwise we have to wait.
201
202 Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(dest ^ 1));
203 int32_t otherware_idx =
204 ware ? flag.find_swappable_ware(*ware, otherflag) : flag.find_pending_ware(otherflag);
205 if (operation_ == WAIT) {
206 if (otherware_idx < kNotFoundAppropriate) {
207 return start_task_waitforcapacity(game, flag); // join flag's wait queue
208 } else {
209 operation_ = dest ^ 1; // resume transport without joining flag's wait queue
210 set_animation(game, descr().get_animation("idle"));
211 return schedule_act(game, 20);
212 }
213 } else if (otherware_idx < kNotFoundAppropriate) {
214 operation_ = WAIT; // move one node away
215 set_animation(game, descr().get_animation("idle"));
216 return schedule_act(game, 20);
217 }
218
219 WareInstance* otherware = flag.fetch_pending_ware(game, otherware_idx);
220
221 if (ware) {
222 const bool ware_astray = (ware->get_next_move_step(game) == nullptr);
223 // Drop our ware
224 flag.add_ware(game, *fetch_carried_ware(game));
225 // If the destination of the dropped ware changed while carrying it and we don't have
226 // anything else we should carry, we might pick it up again immediately, so check again
227 if (ware_astray && otherware_idx == kNotFoundAppropriate) {
228 otherware_idx = flag.find_pending_ware(otherflag);
229 otherware = flag.fetch_pending_ware(game, otherware_idx);
230 }
231 }
232
233 // Pick up new load, if any
234 if (otherware) {
235 // pay before getting the ware, while checking for road promotion
236 road.pay_for_road(game, flag.count_wares_in_queue(otherflag));
237
238 set_carried_ware(game, otherware);
239 flag.ware_departing(game);
240
241 operation_ = state.ivar1 = dest;
242 set_animation(game, descr().get_animation("idle"));
243 schedule_act(game, 20);
244 } else {
245 Flag::PendingWare* pw = otherflag.get_ware_for_flag(flag, kPendingOnly);
246 if (pw) {
247 pw->pending = false;
248
249 operation_ = state.ivar1 = dest ^ 1;
250 set_animation(game, descr().get_animation("idle"));
251 schedule_act(game, 20);
252 } else {
253 operation_ = NO_OPERATION;
254 pop_task(game);
255 }
256 }193 }
257 }194 }
258}195}
@@ -268,7 +205,6 @@
268 BaseImmovable* const pos = game.map()[get_position()].get_immovable();205 BaseImmovable* const pos = game.map()[get_position()].get_immovable();
269206
270 if (dynamic_cast<Flag const*>(pos)) {207 if (dynamic_cast<Flag const*>(pos)) {
271 operation_ = INIT;
272 return pop_task(game); // we are done208 return pop_task(game); // we are done
273 } else if (upcast(Building, building, pos)) {209 } else if (upcast(Building, building, pos)) {
274 // Drop all wares addressed to this building210 // Drop all wares addressed to this building
@@ -301,51 +237,212 @@
301}237}
302238
303/**239/**
304 * Called by road code to indicate that the given flag240 * Walks to the queued flag and picks up one acked ware
305 * (0 = start, 1 = end) has a ware ready for transfer.241 *
242 * \param g Game the carrier lives on
243 * \param s Flags sent to the task
244 */
245void Carrier::pickup_from_flag(Game& game, State& state) {
246 int32_t const ivar1 = state.ivar1;
247 if (!start_task_walktoflag(game, ivar1)) {
248
249 promised_pickup_to_ = NOONE;
250
251 Road& road = dynamic_cast<Road&>(*get_location(game));
252 Flag& flag = road.get_flag(static_cast<Road::FlagId>(ivar1));
253 Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(ivar1 ^ 1));
254
255 // Are there wares to move between our flags?
256 if (WareInstance* const ware = flag.fetch_pending_ware(game, otherflag)) {
257 // pay before getting the ware, while checking for road promotion
258 road.pay_for_road(game, flag.count_wares_in_queue(otherflag));
259 set_carried_ware(game, ware);
260
261 set_animation(game, descr().get_animation("idle"));
262 return schedule_act(game, 20);
263 } else {
264 molog("[Carrier]: Nothing suitable on flag.\n");
265 return pop_task(game);
266 }
267 }
268}
269
270/**
271 * Drop one ware in a flag, and pick up a new one if we acked it
272 *
273 * \param g Game the carrier lives on.
274 * \param s Flags sent to the task
275 */
276void Carrier::drop_ware(Game& game, State& state) {
277 WareInstance* other = nullptr;
278 Road& road = dynamic_cast<Road&>(*get_location(game));
279 Flag& flag = road.get_flag(static_cast<Road::FlagId>(state.ivar1 ^ 1));
280 Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(state.ivar1));
281
282 if (promised_pickup_to_ == (state.ivar1 ^ 1)) {
283 // If there's a ware we acked, we can drop ours even if the flag is
284 // flooded
285 other = flag.fetch_pending_ware(game, otherflag);
286
287 if (!other && !flag.has_capacity()) {
288 molog("[Carrier]: strange: acked ware from busy flag no longer "
289 "present.\n");
290
291 promised_pickup_to_ = NOONE;
292 set_animation(game, descr().get_animation("idle"));
293 return schedule_act(game, 20);
294 }
295
296 state.ivar1 = promised_pickup_to_;
297 promised_pickup_to_ = NOONE;
298 }
299
300 // Drop our ware
301 flag.add_ware(game, *fetch_carried_ware(game));
302
303 // Pick up new load, if any
304 if (other) {
305 // pay before getting the ware, while checking for road promotion
306 road.pay_for_road(game, flag.count_wares_in_queue(otherflag));
307 set_carried_ware(game, other);
308
309 set_animation(game, descr().get_animation("idle"));
310 return schedule_act(game, 20);
311 } else {
312 return pop_task(game);
313 }
314}
315
316/**
317 * When picking up wares, if some of them is targeted to the building attached
318 * to target flag walk straight into it and deliver.
319 *
320 * \param g Game the carrier lives on.
321 * \param s Flags sent to the task.
322 */
323void Carrier::enter_building(Game& game, State& state) {
324 if (!start_task_walktoflag(game, state.ivar1 ^ 1)) {
325 state.ivar1 = -1;
326 return start_task_move(game, WALK_NW, descr().get_right_walk_anims(does_carry_ware()), true);
327 }
328}
329
330/**
331 * Swaps wares from an overloaded flag for as long as the carrier can pick
332 * up new wares from it. Otherwise, changes the carrier state to wait.
333 *
334 * \param g Game the carrier lives on.
335 * \param s Flags sent to the task.
336 *
337 * \return true if the carrier must wait before delivering his wares.
338 */
339bool Carrier::swap_or_wait(Game& game, State& state) {
340 // Road that employs us
341 Road& road = dynamic_cast<Road&>(*get_location(game));
342 // Flag we are delivering to
343 Flag& flag = road.get_flag(static_cast<Road::FlagId>(state.ivar1 ^ 1));
344 // The other flag of our road
345 Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(state.ivar1));
346
347 if (promised_pickup_to_ == (state.ivar1 ^ 1)) {
348 // All is well, we already acked a ware that we can pick up
349 // from this flag
350 return false;
351 } else if (flag.has_pending_ware(game, otherflag)) {
352 if (!flag.ack_pickup(game, otherflag)) {
353 throw wexception(
354 "MO(%u): transport: overload exchange: flag %u is fucked up", serial(), flag.serial());
355 }
356
357 promised_pickup_to_ = state.ivar1 ^ 1;
358 return false;
359 } else if (!start_task_walktoflag(game, state.ivar1 ^ 1, true)) {
360 start_task_waitforcapacity(game, flag); // wait one node away
361 }
362
363 return true;
364}
365
366/**
367 * Called by Road code to indicate that a new ware has arrived on a flag
368 * (0 = start, 1 = end).
306 * \return true if the carrier is going to fetch it.369 * \return true if the carrier is going to fetch it.
307 */370 */
308bool Carrier::notify_ware(Game& game, int32_t const flag) {371bool Carrier::notify_ware(Game& game, int32_t const flag) {
309 State& state = top_state();372 State& state = top_state();
310373
311 if (operation_ == WAIT) {374 // Check if we've already acked something
312 if (state.objvar1.get(game) ==375 if (promised_pickup_to_ != NOONE) {
313 &dynamic_cast<Road&>(*get_location(game)).get_flag(static_cast<Road::FlagId>(flag))) {376 return false;
314 operation_ = flag;377 }
315 send_signal(game, "wakeup");378
316 return true;379 // If we are currently in a transport.
317 }380 // Explanation:
318 } else if (operation_ == NO_OPERATION) {381 // a) a different carrier / road may be better suited for this ware
319 operation_ = flag;382 // (the transport code does not have priorities for the actual
383 // carrier that is notified)
384 // b) the transport task has logic that allows it to
385 // drop a ware on an overloaded flag iff it can pick up a ware
386 // at the same time.
387 // We should ack said ware to avoid more confusion before we move
388 // onto the flag, but we can't do that if we have already acked
389 // something.
390 // c) we might ack for a flag that we are actually moving away from;
391 // this will get us into trouble if wares have arrived on the other
392 // flag while we couldn't ack them.
393 //
394 // (Maybe the need for this lengthy explanation is proof that the
395 // ack system needs to be reworked.)
396 if (State const* const transport = get_state(taskTransport))
397 if ((transport->ivar1 == -1 && find_closest_flag(game) != flag) || flag == transport->ivar1)
398 return false;
399
400 // Ack it if we haven't
401 promised_pickup_to_ = flag;
402
403 if (state.task == &taskRoad) {
320 send_signal(game, "ware");404 send_signal(game, "ware");
321 return true;405 } else if (state.task == &taskWaitforcapacity) {
406 send_signal(game, "wakeup");
322 }407 }
323408 return true;
324 return false;
325}409}
326410
327/**411/**
328 * Find a pending ware meant for our road,412 * Find a pending ware on one of the road's flags, ack it and set promised_pickup_to_
329 * remove its pending status, and413 * accordingly.
330 * \return the flag it is on.
331 */414 */
332int32_t Carrier::find_source_flag(Game& game) {415void Carrier::find_pending_ware(Game& game) {
333 assert(operation_ == INIT);
334
335 Road& road = dynamic_cast<Road&>(*get_location(game));416 Road& road = dynamic_cast<Road&>(*get_location(game));
336 int32_t near = find_closest_flag(game);417 uint32_t havewarebits = 0;
337 Flag& nearflag = road.get_flag(static_cast<Road::FlagId>(near));418
338 Flag& farflag = road.get_flag(static_cast<Road::FlagId>(near ^ 1));419 assert(promised_pickup_to_ == NOONE);
339420
340 Flag::PendingWare* pw;421 if (road.get_flag(Road::FlagStart).has_pending_ware(game, road.get_flag(Road::FlagEnd))) {
341 if ((pw = nearflag.get_ware_for_flag(farflag))) {422 havewarebits |= 1;
342 pw->pending = false;423 }
343 return near;424
344 } else if ((pw = farflag.get_ware_for_flag(nearflag, kPendingOnly))) {425 if (road.get_flag(Road::FlagEnd).has_pending_ware(game, road.get_flag(Road::FlagStart))) {
345 pw->pending = false;426 havewarebits |= 2;
346 return near ^ 1;427 }
347 } else {428
348 return NO_OPERATION;429 // If both flags have a ware, we pick the one closer to us.
430 if (havewarebits == 3) {
431 havewarebits = 1 << find_closest_flag(game);
432 }
433
434 // Ack our decision
435 if (havewarebits == 1) {
436 promised_pickup_to_ = START_FLAG;
437 if (!road.get_flag(Road::FlagStart).ack_pickup(game, road.get_flag(Road::FlagEnd))) {
438 throw wexception("Carrier::find_pending_ware: start flag is messed up");
439 }
440
441 } else if (havewarebits == 2) {
442 promised_pickup_to_ = END_FLAG;
443 if (!road.get_flag(Road::FlagEnd).ack_pickup(game, road.get_flag(Road::FlagStart))) {
444 throw wexception("Carrier::find_pending_ware: end flag is messed up");
445 }
349 }446 }
350}447}
351448
@@ -418,7 +515,7 @@
418515
419 Worker::log_general_info(egbase);516 Worker::log_general_info(egbase);
420517
421 molog("operation = %i\n", operation_);518 molog("promised_pickup_to = %i\n", promised_pickup_to_);
422}519}
423520
424/*521/*
@@ -428,7 +525,7 @@
428525
429==============================526==============================
430*/527*/
431constexpr uint8_t kCurrentPacketVersion = 2;528constexpr uint8_t kCurrentPacketVersion = 3;
432529
433Carrier::Loader::Loader() {530Carrier::Loader::Loader() {
434}531}
@@ -437,10 +534,12 @@
437 Worker::Loader::load(fr);534 Worker::Loader::load(fr);
438535
439 try {536 try {
440 uint8_t packet_version = fr.unsigned_8();537 const uint8_t packet_version = fr.unsigned_8();
441 if (packet_version == kCurrentPacketVersion) {538 // TODO(GunChleoc): Remove savegame compatibility after Build 21.
539 if (packet_version <= kCurrentPacketVersion && packet_version >= 1) {
442 Carrier& carrier = get<Carrier>();540 Carrier& carrier = get<Carrier>();
443 carrier.operation_ = fr.signed_32();541 // TODO(GunChleoc): std::min is for savegame compatibility. Remove after Build 21.
542 carrier.promised_pickup_to_ = std::min(-1, fr.signed_32());
444 } else {543 } else {
445 throw UnhandledVersionError("Carrier", packet_version, kCurrentPacketVersion);544 throw UnhandledVersionError("Carrier", packet_version, kCurrentPacketVersion);
446 }545 }
@@ -465,7 +564,7 @@
465 Worker::do_save(egbase, mos, fw);564 Worker::do_save(egbase, mos, fw);
466565
467 fw.unsigned_8(kCurrentPacketVersion);566 fw.unsigned_8(kCurrentPacketVersion);
468 fw.signed_32(operation_);567 fw.signed_32(promised_pickup_to_);
469}568}
470569
471CarrierDescr::CarrierDescr(const std::string& init_descname,570CarrierDescr::CarrierDescr(const std::string& init_descname,
472571
=== modified file 'src/logic/map_objects/tribes/carrier.h'
--- src/logic/map_objects/tribes/carrier.h 2018-09-04 15:48:47 +0000
+++ src/logic/map_objects/tribes/carrier.h 2018-11-26 06:43:43 +0000
@@ -24,7 +24,6 @@
24#include "logic/map_objects/tribes/worker.h"24#include "logic/map_objects/tribes/worker.h"
2525
26namespace Widelands {26namespace Widelands {
27class PendingWare;
2827
29class CarrierDescr : public WorkerDescr {28class CarrierDescr : public WorkerDescr {
30public:29public:
@@ -50,7 +49,7 @@
50 MO_DESCR(CarrierDescr)49 MO_DESCR(CarrierDescr)
5150
52 explicit Carrier(const CarrierDescr& carrier_descr)51 explicit Carrier(const CarrierDescr& carrier_descr)
53 : Worker(carrier_descr), operation_(NO_OPERATION) {52 : Worker(carrier_descr), promised_pickup_to_(NOONE) {
54 }53 }
55 ~Carrier() override {54 ~Carrier() override {
56 }55 }
@@ -67,7 +66,7 @@
67 static Task const taskRoad;66 static Task const taskRoad;
6867
69private:68private:
70 int32_t find_source_flag(Game&);69 void find_pending_ware(Game&);
71 int32_t find_closest_flag(Game&);70 int32_t find_closest_flag(Game&);
7271
73 // internal task stuff72 // internal task stuff
@@ -78,14 +77,17 @@
78 static Task const taskTransport;77 static Task const taskTransport;
7978
80 void deliver_to_building(Game&, State&);79 void deliver_to_building(Game&, State&);
80 void pickup_from_flag(Game&, State&);
81 void drop_ware(Game&, State&);
82 void enter_building(Game&, State&);
83 bool swap_or_wait(Game&, State&);
8184
85 /// -1: no ware acked; 0/1: acked ware for start/end flag of road
82 // This should be an enum, but this clutters the code with too many casts86 // This should be an enum, but this clutters the code with too many casts
83 static const int32_t INIT = -3; // ready to undertake or resume operations87 static const int32_t NOONE = -1;
84 static const int32_t WAIT = -2; // waiting for flag capacity88 static const int32_t START_FLAG = 0;
85 static const int32_t NO_OPERATION = -1; // idling89 static const int32_t END_FLAG = 1;
86 static const int32_t START_FLAG = 0; // serving start flag of road90 int32_t promised_pickup_to_;
87 static const int32_t END_FLAG = 1; // serving end flag of road
88 int32_t operation_;
8991
90 // saving and loading92 // saving and loading
91protected:93protected:
9294
=== modified file 'src/logic/map_objects/tribes/worker.cc'
--- src/logic/map_objects/tribes/worker.cc 2018-11-23 21:26:24 +0000
+++ src/logic/map_objects/tribes/worker.cc 2018-11-26 06:43:43 +0000
@@ -137,11 +137,10 @@
137 totalres += amount;137 totalres += amount;
138 totalchance += 8 * amount;138 totalchance += 8 * amount;
139139
140 // Add penalty for fields that are running out140 // Add penalty for fields that are running out
141 // Except for totally depleted fields or wrong ressource fields
142 // if we already know there is no ressource (left) we won't mine there
143 if (amount == 0)141 if (amount == 0)
144 totalchance += 0;142 // we already know it's completely empty, so punish is less
143 totalchance += 1;
145 else if (amount <= 2)144 else if (amount <= 2)
146 totalchance += 6;145 totalchance += 6;
147 else if (amount <= 4)146 else if (amount <= 4)
@@ -1820,11 +1819,12 @@
1820 if (upcast(Flag, flag, pos)) {1819 if (upcast(Flag, flag, pos)) {
1821 // Is this "our" flag?1820 // Is this "our" flag?
1822 if (flag->get_building() == location) {1821 if (flag->get_building() == location) {
1823 WareInstance* const ware = get_carried_ware(game);1822 if (state.ivar1 && flag->has_capacity()) {
1824 if (state.ivar1 && ware && flag->has_capacity_for_ware(*ware)) {1823 if (WareInstance* const ware = fetch_carried_ware(game)) {
1825 flag->add_ware(game, *fetch_carried_ware(game));1824 flag->add_ware(game, *ware);
1826 set_animation(game, descr().get_animation("idle"));1825 set_animation(game, descr().get_animation("idle"));
1827 return schedule_act(game, 20); // rest a while1826 return schedule_act(game, 20); // rest a while
1827 }
1828 }1828 }
18291829
1830 // Don't try to enter building if it is a dismantle site1830 // Don't try to enter building if it is a dismantle site
@@ -2057,18 +2057,16 @@
2057 if (ware) {2057 if (ware) {
2058 // We're in the building, walk onto the flag2058 // We're in the building, walk onto the flag
2059 if (upcast(Building, building, location)) {2059 if (upcast(Building, building, location)) {
2060 Flag& baseflag = building->base_flag();2060 if (start_task_waitforcapacity(game, building->base_flag())) {
2061 if (baseflag.has_capacity_for_ware(*ware)) {2061 return;
2062 start_task_leavebuilding(game, false); // exit throttle
2063 } else {
2064 start_task_waitforcapacity(game, baseflag);
2065 }2062 }
2066 return;2063
2064 return start_task_leavebuilding(game, false); // exit throttle
2067 }2065 }
20682066
2069 // We're on the flag, drop the ware and pause a little2067 // We're on the flag, drop the ware and pause a little
2070 if (upcast(Flag, flag, location)) {2068 if (upcast(Flag, flag, location)) {
2071 if (flag->has_capacity_for_ware(*ware)) {2069 if (flag->has_capacity()) {
2072 flag->add_ware(game, *fetch_carried_ware(game));2070 flag->add_ware(game, *fetch_carried_ware(game));
20732071
2074 set_animation(game, descr().get_animation("idle"));2072 set_animation(game, descr().get_animation("idle"));
@@ -2148,11 +2146,9 @@
21482146
2149 // The ware has decided that it doesn't want to go to us after all2147 // The ware has decided that it doesn't want to go to us after all
2150 // In order to return to the warehouse, we're switching to State_DropOff2148 // In order to return to the warehouse, we're switching to State_DropOff
2151 Flag& flag = dynamic_cast<Flag&>(*location);
2152 if (WareInstance* const ware =2149 if (WareInstance* const ware =
2153 flag.fetch_pending_ware(game, flag.find_pending_ware(employer))) {2150 dynamic_cast<Flag&>(*location).fetch_pending_ware(game, employer)) {
2154 set_carried_ware(game, ware);2151 set_carried_ware(game, ware);
2155 flag.ware_departing(game);
2156 }2152 }
21572153
2158 set_animation(game, descr().get_animation("idle"));2154 set_animation(game, descr().get_animation("idle"));
@@ -2215,15 +2211,25 @@
2215 static_cast<Bob::Ptr>(&Worker::waitforcapacity_pop), true};2211 static_cast<Bob::Ptr>(&Worker::waitforcapacity_pop), true};
22162212
2217/**2213/**
2218 * Pushes a wait task and2214 * Checks the capacity of the flag.
2219 * adds the worker to the flag's wait queue.2215 *
2216 * If there is none, a wait task is pushed, and the worker is added to the
2217 * flag's wait queue. The function returns true in this case.
2218 * If the flag still has capacity, the function returns false and doesn't
2219 * act at all.
2220 */2220 */
2221void Worker::start_task_waitforcapacity(Game& game, Flag& flag) {2221bool Worker::start_task_waitforcapacity(Game& game, Flag& flag) {
2222 if (flag.has_capacity()) {
2223 return false;
2224 }
2225
2222 push_task(game, taskWaitforcapacity);2226 push_task(game, taskWaitforcapacity);
22232227
2224 top_state().objvar1 = &flag;2228 top_state().objvar1 = &flag;
22252229
2226 flag.wait_for_capacity(game, *this);2230 flag.wait_for_capacity(game, *this);
2231
2232 return true;
2227}2233}
22282234
2229void Worker::waitforcapacity_update(Game& game, State&) {2235void Worker::waitforcapacity_update(Game& game, State&) {
22302236
=== modified file 'src/logic/map_objects/tribes/worker.h'
--- src/logic/map_objects/tribes/worker.h 2018-09-14 08:46:36 +0000
+++ src/logic/map_objects/tribes/worker.h 2018-11-26 06:43:43 +0000
@@ -163,7 +163,7 @@
163 void start_task_releaserecruit(Game&, Worker&);163 void start_task_releaserecruit(Game&, Worker&);
164 void start_task_fetchfromflag(Game&);164 void start_task_fetchfromflag(Game&);
165165
166 void start_task_waitforcapacity(Game&, Flag&);166 bool start_task_waitforcapacity(Game&, Flag&);
167 void start_task_leavebuilding(Game&, bool changelocation);167 void start_task_leavebuilding(Game&, bool changelocation);
168 void start_task_fugitive(Game&);168 void start_task_fugitive(Game&);
169169

Subscribers

People subscribed via source and target branches

to status/vote changes: