Merge lp:~widelands-dev/widelands/remove-anti-congestion-algorithm into lp:widelands
- remove-anti-congestion-algorithm
- Merge into trunk
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 | ||||
Related bugs: |
|
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.
Description of the change
bunnybot (widelandsofficial) wrote : | # |
GunChleoc (gunchleoc) wrote : | # |
We can't start working on the desyncs without this branch, so I'm gonna merge.
@bunnybot merge
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4286. State: failed. Details: https:/
Appveyor build 4080. State: failed. Details: https:/
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:/
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4293. State: passed. Details: https:/
Appveyor build 4086. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
@bunnybot merge
Preview Diff
1 | === modified file 'src/economy/flag.cc' |
2 | --- src/economy/flag.cc 2018-09-04 15:48:47 +0000 |
3 | +++ src/economy/flag.cc 2018-11-26 06:43:43 +0000 |
4 | @@ -337,30 +337,7 @@ |
5 | } |
6 | |
7 | /** |
8 | - * Called by workers wanting to drop a ware to their building's flag. |
9 | - * \return true/allow on low congestion-risk. |
10 | - */ |
11 | -bool Flag::has_capacity_for_ware(WareInstance& ware) const { |
12 | - // avoid iteration for the easy cases |
13 | - if (ware_filled_ < ware_capacity_ - 2) { |
14 | - return true; // more than two free slots, allow |
15 | - } |
16 | - if (ware_filled_ >= ware_capacity_) { |
17 | - return false; // all slots filled, no room |
18 | - } |
19 | - |
20 | - DescriptionIndex const descr_index = ware.descr_index(); |
21 | - for (int i = 0; i < ware_filled_; ++i) { |
22 | - if (wares_[i].ware->descr_index() == descr_index) { |
23 | - return false; // ware of this type already present, leave room for other types |
24 | - } |
25 | - } |
26 | - return true; // ware of this type not present, allow |
27 | -} |
28 | - |
29 | -/** |
30 | - * \return true/allow if the flag can hold more wares of any type. |
31 | - * has_capacity_for_ware() also checks ware's type to prevent congestion. |
32 | + * Returns true if the flag can hold more wares. |
33 | */ |
34 | bool Flag::has_capacity() const { |
35 | return (ware_filled_ < ware_capacity_); |
36 | @@ -386,24 +363,13 @@ |
37 | capacity_wait_.erase(it); |
38 | } |
39 | |
40 | -/** |
41 | - * Adds given ware to this flag. |
42 | - * Please check has_capacity() or better has_capacity_for_ware() before. |
43 | - */ |
44 | void Flag::add_ware(EditorGameBase& egbase, WareInstance& ware) { |
45 | + |
46 | assert(ware_filled_ < ware_capacity_); |
47 | - init_ware(egbase, ware, wares_[ware_filled_++]); |
48 | - if (upcast(Game, game, &egbase)) { |
49 | - ware.update(*game); // will call call_carrier() if necessary |
50 | - } |
51 | -} |
52 | |
53 | -/** |
54 | - * Properly assigns given ware instance to given pending ware. |
55 | - */ |
56 | -void Flag::init_ware(EditorGameBase& egbase, WareInstance& ware, PendingWare& pi) { |
57 | + PendingWare& pi = wares_[ware_filled_++]; |
58 | pi.ware = &ware; |
59 | - pi.pending = true; |
60 | + pi.pending = false; |
61 | pi.nextstep = nullptr; |
62 | pi.priority = 0; |
63 | |
64 | @@ -423,24 +389,32 @@ |
65 | } |
66 | |
67 | ware.set_location(egbase, this); |
68 | + |
69 | + if (upcast(Game, game, &egbase)) { |
70 | + ware.update(*game); // will call call_carrier() if necessary |
71 | + } |
72 | } |
73 | |
74 | /** |
75 | - * \return a ware currently waiting for a carrier to the given destflag. |
76 | + * \return true if a ware is currently waiting for a carrier to the given Flag. |
77 | * |
78 | * \note Due to fetch_from_flag() semantics, this function makes no sense |
79 | * for a building destination. |
80 | */ |
81 | -Flag::PendingWare* Flag::get_ware_for_flag(Flag& destflag, bool const pending_only) { |
82 | +bool Flag::has_pending_ware(Game&, Flag& dest) { |
83 | for (int32_t i = 0; i < ware_filled_; ++i) { |
84 | - PendingWare* pw = &wares_[i]; |
85 | - if ((!pending_only || pw->pending) && pw->nextstep == &destflag && |
86 | - destflag.allow_ware_from_flag(*pw->ware, *this)) { |
87 | - return pw; |
88 | - } |
89 | + if (!wares_[i].pending) { |
90 | + continue; |
91 | + } |
92 | + |
93 | + if (wares_[i].nextstep != &dest) { |
94 | + continue; |
95 | + } |
96 | + |
97 | + return true; |
98 | } |
99 | |
100 | - return nullptr; |
101 | + return false; |
102 | } |
103 | |
104 | /** |
105 | @@ -450,124 +424,109 @@ |
106 | #define MAX_TRANSFER_PRIORITY 16 |
107 | |
108 | /** |
109 | - * Called by the carriercode when the carrier is called away from his job |
110 | - * but has acknowledged a ware before. This ware is then freed again |
111 | - * to be picked by another carrier. Returns true if a ware was indeed |
112 | - * made pending again. |
113 | + * Called by carrier code to indicate that the carrier is moving to pick up an |
114 | + * ware. Ware with highest transfer priority is chosen. |
115 | + * \return true if an ware is actually waiting for the carrier. |
116 | */ |
117 | -bool Flag::cancel_pickup(Game& game, Flag& destflag) { |
118 | +bool Flag::ack_pickup(Game&, Flag& destflag) { |
119 | + int32_t highest_pri = -1; |
120 | + int32_t i_pri = -1; |
121 | + |
122 | for (int32_t i = 0; i < ware_filled_; ++i) { |
123 | - PendingWare& pw = wares_[i]; |
124 | - if (!pw.pending && pw.nextstep == &destflag) { |
125 | - pw.pending = true; |
126 | - pw.ware->update(game); // will call call_carrier() if necessary |
127 | - return true; |
128 | - } |
129 | + if (!wares_[i].pending) { |
130 | + continue; |
131 | + } |
132 | + |
133 | + if (wares_[i].nextstep != &destflag) { |
134 | + continue; |
135 | + } |
136 | + |
137 | + if (wares_[i].priority > highest_pri) { |
138 | + highest_pri = wares_[i].priority; |
139 | + i_pri = i; |
140 | + |
141 | + // Increase ware priority, it matters only if the ware has to wait. |
142 | + if (wares_[i].priority < MAX_TRANSFER_PRIORITY) { |
143 | + wares_[i].priority++; |
144 | + } |
145 | + } |
146 | + } |
147 | + |
148 | + if (i_pri >= 0) { |
149 | + wares_[i_pri].pending = false; |
150 | + return true; |
151 | } |
152 | |
153 | return false; |
154 | } |
155 | - |
156 | /** |
157 | * Called by carrier code to find the best among the wares on this flag |
158 | * that are meant for the provided dest. |
159 | * \return index of found ware (carrier will take it) |
160 | * or kNotFoundAppropriate (carrier will leave empty-handed) |
161 | */ |
162 | -int32_t Flag::find_pending_ware(PlayerImmovable& dest) { |
163 | - int32_t highest_pri = -1; |
164 | - int32_t best_index = kNotFoundAppropriate; |
165 | - bool ware_pended = false; |
166 | - |
167 | - for (int32_t i = 0; i < ware_filled_; ++i) { |
168 | - PendingWare& pw = wares_[i]; |
169 | - if (pw.nextstep != &dest) { |
170 | - continue; |
171 | - } |
172 | - |
173 | - if (pw.priority < MAX_TRANSFER_PRIORITY) { |
174 | - pw.priority++; |
175 | - } |
176 | - // Release promised pickup, in case we find a preferable ware |
177 | - if (!ware_pended && !pw.pending) { |
178 | - ware_pended = pw.pending = true; |
179 | - } |
180 | - |
181 | - // If dest is flag, we exclude wares that can stress it |
182 | - if (&dest != building_ && !dynamic_cast<Flag&>(dest).allow_ware_from_flag(*pw.ware, *this)) { |
183 | - continue; |
184 | - } |
185 | - |
186 | - if (pw.priority > highest_pri) { |
187 | - highest_pri = pw.priority; |
188 | - best_index = i; |
189 | - } |
190 | - } |
191 | - |
192 | - return best_index; |
193 | -} |
194 | - |
195 | -/** |
196 | - * Like find_pending_ware() above, but for carriers who have a ware to drop on this flag. |
197 | - * \return same as find_pending_ware() above, plus kDenyDrop (carrier will wait) |
198 | - */ |
199 | -int32_t Flag::find_swappable_ware(WareInstance& ware, Flag& destflag) { |
200 | - DescriptionIndex const descr_index = ware.descr_index(); |
201 | - int32_t highest_pri = -1; |
202 | - int32_t best_index = kNotFoundAppropriate; |
203 | - bool has_same_ware = false; |
204 | - bool has_allowed = false; |
205 | - bool ware_pended = false; |
206 | - |
207 | - for (int32_t i = 0; i < ware_filled_; ++i) { |
208 | - PendingWare& pw = wares_[i]; |
209 | - if (pw.nextstep != &destflag) { |
210 | - if (pw.ware->descr_index() == descr_index) { |
211 | - has_same_ware = true; |
212 | - } |
213 | - continue; |
214 | - } |
215 | - |
216 | - if (pw.priority < MAX_TRANSFER_PRIORITY) { |
217 | - pw.priority++; |
218 | - } |
219 | - // Release promised pickup, in case we find a preferable ware |
220 | - if (!ware_pended && !pw.pending) { |
221 | - ware_pended = pw.pending = true; |
222 | - } |
223 | - |
224 | - // We prefer to retrieve wares that won't stress the destflag |
225 | - if (destflag.allow_ware_from_flag(*pw.ware, *this)) { |
226 | - if (!has_allowed) { |
227 | - has_allowed = true; |
228 | - highest_pri = -1; |
229 | - } |
230 | - } else { |
231 | - if (has_allowed) { |
232 | - continue; |
233 | - } |
234 | - } |
235 | - |
236 | - if (pw.priority > highest_pri) { |
237 | - highest_pri = pw.priority; |
238 | - best_index = i; |
239 | - } |
240 | - } |
241 | - |
242 | - if (best_index > kNotFoundAppropriate) { |
243 | - return (ware_filled_ > ware_capacity_ - 3 || has_allowed) ? best_index : kNotFoundAppropriate; |
244 | - } else { |
245 | - return (ware_filled_ < ware_capacity_ - 2 || |
246 | - (ware_filled_ < ware_capacity_ && !has_same_ware)) ? |
247 | - kNotFoundAppropriate : |
248 | - kDenyDrop; |
249 | - } |
250 | -} |
251 | - |
252 | -/** |
253 | - * Called by carrier code to retrieve a ware found by the previous methods. |
254 | - */ |
255 | -WareInstance* Flag::fetch_pending_ware(Game& game, int32_t best_index) { |
256 | +bool Flag::cancel_pickup(Game& game, Flag& destflag) { |
257 | + int32_t lowest_prio = MAX_TRANSFER_PRIORITY + 1; |
258 | + int32_t i_pri = -1; |
259 | + |
260 | + for (int32_t i = 0; i < ware_filled_; ++i) { |
261 | + if (wares_[i].pending) { |
262 | + continue; |
263 | + } |
264 | + |
265 | + if (wares_[i].nextstep != &destflag) { |
266 | + continue; |
267 | + } |
268 | + |
269 | + if (wares_[i].priority < lowest_prio) { |
270 | + lowest_prio = wares_[i].priority; |
271 | + i_pri = i; |
272 | + } |
273 | + } |
274 | + |
275 | + if (i_pri >= 0) { |
276 | + wares_[i_pri].pending = true; |
277 | + wares_[i_pri].ware->update(game); // will call call_carrier() if necessary |
278 | + return true; |
279 | + } |
280 | + |
281 | + return false; |
282 | +} |
283 | + |
284 | +/** |
285 | + * Wake one sleeper from the capacity queue. |
286 | +*/ |
287 | +void Flag::wake_up_capacity_queue(Game& game) { |
288 | + while (!capacity_wait_.empty()) { |
289 | + Worker* const w = capacity_wait_.front().get(game); |
290 | + capacity_wait_.pop_front(); |
291 | + if (w && w->wakeup_flag_capacity(game, *this)) { |
292 | + break; |
293 | + } |
294 | + } |
295 | +} |
296 | + |
297 | +/** |
298 | + * Called by carrier code to retrieve one of the wares on the flag that is meant |
299 | + * for that carrier. |
300 | + * |
301 | + * This function may return 0 even if \ref ack_pickup() has already been |
302 | + * called successfully. |
303 | +*/ |
304 | +WareInstance* Flag::fetch_pending_ware(Game& game, PlayerImmovable& dest) { |
305 | + int32_t best_index = -1; |
306 | + |
307 | + for (int32_t i = 0; i < ware_filled_; ++i) { |
308 | + if (wares_[i].nextstep != &dest) { |
309 | + continue; |
310 | + } |
311 | + |
312 | + // We prefer to retrieve wares that have already been acked |
313 | + if (best_index < 0 || !wares_[i].pending) { |
314 | + best_index = i; |
315 | + } |
316 | + } |
317 | + |
318 | if (best_index < 0) { |
319 | return nullptr; |
320 | } |
321 | @@ -579,43 +538,14 @@ |
322 | sizeof(wares_[0]) * (ware_filled_ - best_index)); |
323 | |
324 | ware->set_location(game, nullptr); |
325 | + |
326 | + // wake up capacity wait queue |
327 | + wake_up_capacity_queue(game); |
328 | + |
329 | return ware; |
330 | } |
331 | |
332 | /** |
333 | - * Called by carrier code to notify waiting carriers |
334 | - * which may be interested in the new state of this flag. |
335 | - */ |
336 | -void Flag::ware_departing(Game& game) { |
337 | - // Wake up one sleeper from the capacity queue. |
338 | - while (!capacity_wait_.empty()) { |
339 | - Worker* const w = capacity_wait_.front().get(game); |
340 | - capacity_wait_.erase(capacity_wait_.begin()); |
341 | - if (w && w->wakeup_flag_capacity(game, *this)) { |
342 | - return; |
343 | - } |
344 | - } |
345 | - |
346 | - // Consider pending wares of neighboring flags. |
347 | - for (int32_t dir = 1; dir <= WalkingDir::LAST_DIRECTION; ++dir) { |
348 | - Road* const road = get_road(dir); |
349 | - if (!road) { |
350 | - continue; |
351 | - } |
352 | - |
353 | - Flag* other = &road->get_flag(Road::FlagEnd); |
354 | - if (other == this) { |
355 | - other = &road->get_flag(Road::FlagStart); |
356 | - } |
357 | - |
358 | - PendingWare* pw = other->get_ware_for_flag(*this, kPendingOnly); |
359 | - if (pw && road->notify_ware(game, *other)) { |
360 | - pw->pending = false; |
361 | - } |
362 | - } |
363 | -} |
364 | - |
365 | -/** |
366 | * Accelerate potential promotion of roads adjacent to a newly promoted road. |
367 | */ |
368 | void Flag::propagate_promoted_road(Road* const promoted_road) { |
369 | @@ -684,7 +614,7 @@ |
370 | memmove(&wares_[i], &wares_[i + 1], sizeof(wares_[0]) * (ware_filled_ - i)); |
371 | |
372 | if (upcast(Game, game, &egbase)) { |
373 | - ware_departing(*game); |
374 | + wake_up_capacity_queue(*game); |
375 | } |
376 | |
377 | return; |
378 | @@ -755,20 +685,27 @@ |
379 | |
380 | for (int32_t dir = 1; dir <= 6; ++dir) { |
381 | Road* const road = get_road(dir); |
382 | + Flag* other; |
383 | + Road::FlagId flagid; |
384 | + |
385 | if (!road) { |
386 | continue; |
387 | } |
388 | |
389 | - Flag* other = &road->get_flag(Road::FlagEnd); |
390 | - if (other == this) { |
391 | + if (&road->get_flag(Road::FlagStart) == this) { |
392 | + flagid = Road::FlagStart; |
393 | + other = &road->get_flag(Road::FlagEnd); |
394 | + } else { |
395 | + flagid = Road::FlagEnd; |
396 | other = &road->get_flag(Road::FlagStart); |
397 | } |
398 | + |
399 | if (other != &nextflag) { |
400 | continue; |
401 | } |
402 | |
403 | // Yes, this is the road we want; inform it |
404 | - if (other->update_ware_from_flag(game, wares_[i], *road, *this)) { |
405 | + if (road->notify_ware(game, flagid)) { |
406 | return; |
407 | } |
408 | |
409 | @@ -782,72 +719,6 @@ |
410 | } |
411 | |
412 | /** |
413 | - * Called by neighboring flags, before agreeing for a carrier |
414 | - * to take one of their wares heading to this flag. |
415 | - * \return true/allow on low congestion-risk. |
416 | - */ |
417 | -bool Flag::allow_ware_from_flag(WareInstance& ware, Flag& flag) { |
418 | - // avoid iteration for the easy cases |
419 | - if (ware_filled_ < ware_capacity_ - 2) { |
420 | - return true; |
421 | - } |
422 | - |
423 | - DescriptionIndex const descr_index = ware.descr_index(); |
424 | - bool has_swappable = false; |
425 | - for (int i = 0; i < ware_filled_; ++i) { |
426 | - PendingWare& pw = wares_[i]; |
427 | - if (pw.pending && pw.nextstep == &flag) { |
428 | - has_swappable = true; |
429 | - } else if (pw.ware->descr_index() == descr_index) { |
430 | - return false; |
431 | - } |
432 | - } |
433 | - return ware_filled_ < ware_capacity_ || has_swappable; |
434 | -} |
435 | - |
436 | -/** |
437 | - * Called when a ware is trying to reach this flag through the provided road, |
438 | - * having just arrived to the provided flag. |
439 | - * Swaps pending wares if possible. Otherwise, |
440 | - * asks road for carrier on low congestion-risk. |
441 | - * \return false if the ware is not immediately served. |
442 | - */ |
443 | -bool Flag::update_ware_from_flag(Game& game, PendingWare& pw1, Road& road, Flag& flag) { |
444 | - WareInstance& w1 = *pw1.ware; |
445 | - DescriptionIndex const w1_descr_index = w1.descr_index(); |
446 | - bool has_same_ware = false; |
447 | - bool has_swappable = false; |
448 | - for (int i = 0; i < ware_filled_; ++i) { |
449 | - PendingWare& pw2 = wares_[i]; |
450 | - WareInstance& w2 = *pw2.ware; |
451 | - if (w2.descr_index() == w1_descr_index) { |
452 | - if (pw2.nextstep == &flag) { |
453 | - // swap pending wares remotely |
454 | - init_ware(game, w1, pw2); |
455 | - flag.init_ware(game, w2, pw1); |
456 | - w1.update(game); |
457 | - w2.update(game); |
458 | - return true; |
459 | - } |
460 | - |
461 | - has_same_ware = true; |
462 | - } else if (pw2.pending && pw2.nextstep == &flag) { |
463 | - has_swappable = true; |
464 | - } |
465 | - } |
466 | - |
467 | - // ask road for carrier on low congestion-risk |
468 | - if (ware_filled_ < ware_capacity_ - 2 || |
469 | - (!has_same_ware && (ware_filled_ < ware_capacity_ || has_swappable))) { |
470 | - if (road.notify_ware(game, flag)) { |
471 | - pw1.pending = false; |
472 | - return true; |
473 | - } |
474 | - } |
475 | - return false; |
476 | -} |
477 | - |
478 | -/** |
479 | * Called whenever a road gets broken or split. |
480 | * Make sure all wares on this flag are rerouted if necessary. |
481 | * |
482 | |
483 | === modified file 'src/economy/flag.h' |
484 | --- src/economy/flag.h 2018-09-25 06:32:35 +0000 |
485 | +++ src/economy/flag.h 2018-11-26 06:43:43 +0000 |
486 | @@ -47,10 +47,6 @@ |
487 | DISALLOW_COPY_AND_ASSIGN(FlagDescr); |
488 | }; |
489 | |
490 | -constexpr bool kPendingOnly = true; // ignore non-pending wares |
491 | -constexpr int32_t kNotFoundAppropriate = -1; // no ware appropiate for carrying |
492 | -constexpr int32_t kDenyDrop = -2; // flag is full and no ware appropiate for swapping |
493 | - |
494 | /** |
495 | * Flag represents a flag as you see it on the map. |
496 | * |
497 | @@ -125,15 +121,7 @@ |
498 | |
499 | bool is_dead_end() const; |
500 | |
501 | - struct PendingWare { |
502 | - WareInstance* ware; ///< the ware itself |
503 | - bool pending; ///< if the ware is pending |
504 | - int32_t priority; ///< carrier prefers the ware with highest priority |
505 | - OPtr<PlayerImmovable> nextstep; ///< next step that this ware is sent to |
506 | - }; |
507 | - |
508 | bool has_capacity() const; |
509 | - bool has_capacity_for_ware(WareInstance&) const; |
510 | uint32_t total_capacity() { |
511 | return ware_capacity_; |
512 | } |
513 | @@ -143,14 +131,10 @@ |
514 | void wait_for_capacity(Game&, Worker&); |
515 | void skip_wait_for_capacity(Game&, Worker&); |
516 | void add_ware(EditorGameBase&, WareInstance&); |
517 | - void init_ware(EditorGameBase&, WareInstance&, PendingWare&); |
518 | - PendingWare* get_ware_for_flag(Flag&, bool pending_only = false); |
519 | + bool has_pending_ware(Game&, Flag& destflag); |
520 | + bool ack_pickup(Game&, Flag& destflag); |
521 | bool cancel_pickup(Game&, Flag& destflag); |
522 | - void ware_departing(Game&); |
523 | - bool allow_ware_from_flag(WareInstance&, Flag&); |
524 | - int32_t find_swappable_ware(WareInstance&, Flag&); |
525 | - int32_t find_pending_ware(PlayerImmovable&); |
526 | - WareInstance* fetch_pending_ware(Game&, int32_t); |
527 | + WareInstance* fetch_pending_ware(Game&, PlayerImmovable& dest); |
528 | void propagate_promoted_road(Road* promoted_road); |
529 | Wares get_wares(); |
530 | uint8_t count_wares_in_queue(PlayerImmovable& dest) const; |
531 | @@ -171,13 +155,20 @@ |
532 | void |
533 | draw(uint32_t gametime, const Vector2f& point_on_dst, float scale, RenderTarget* dst) override; |
534 | |
535 | + void wake_up_capacity_queue(Game&); |
536 | + |
537 | static void |
538 | flag_job_request_callback(Game&, Request&, DescriptionIndex, Worker*, PlayerImmovable&); |
539 | |
540 | void set_flag_position(Coords coords); |
541 | |
542 | private: |
543 | - bool update_ware_from_flag(Game&, PendingWare&, Road&, Flag&); |
544 | + struct PendingWare { |
545 | + WareInstance* ware; ///< the ware itself |
546 | + bool pending; ///< if the ware is pending |
547 | + int32_t priority; ///< carrier prefers the ware with highest priority |
548 | + OPtr<PlayerImmovable> nextstep; ///< next step that this ware is sent to |
549 | + }; |
550 | |
551 | struct FlagJob { |
552 | Request* request; |
553 | |
554 | === modified file 'src/economy/road.cc' |
555 | --- src/economy/road.cc 2018-09-04 15:48:47 +0000 |
556 | +++ src/economy/road.cc 2018-11-26 06:43:43 +0000 |
557 | @@ -542,8 +542,7 @@ |
558 | * Try to pick up a ware from the given flag. |
559 | * \return true if a carrier has been sent on its way, false otherwise. |
560 | */ |
561 | -bool Road::notify_ware(Game& game, Flag& flag) { |
562 | - FlagId flagid = &flag == flags_[Road::FlagEnd] ? Road::FlagEnd : Road::FlagStart; |
563 | +bool Road::notify_ware(Game& game, FlagId const flagid) { |
564 | // Iterate over all carriers and try to find one which will take the ware |
565 | for (CarrierSlot& slot : carrier_slots_) { |
566 | if (Carrier* const carrier = slot.carrier.get(game)) { |
567 | |
568 | === modified file 'src/economy/road.h' |
569 | --- src/economy/road.h 2018-09-25 06:32:35 +0000 |
570 | +++ src/economy/road.h 2018-11-26 06:43:43 +0000 |
571 | @@ -113,7 +113,7 @@ |
572 | void presplit(Game&, Coords split); |
573 | void postsplit(Game&, Flag&); |
574 | |
575 | - bool notify_ware(Game& game, Flag& flag); |
576 | + bool notify_ware(Game& game, FlagId flagid); |
577 | void update_wallet_chargetime(Game& game); |
578 | void charge_wallet(Game& game); |
579 | int32_t wallet() const; |
580 | @@ -148,8 +148,8 @@ |
581 | uint8_t carriers_count() const; |
582 | |
583 | private: |
584 | - /// Counter that is incremented for every ware served by this road |
585 | - /// according to the delay of service and decremented over time. |
586 | + /// Counter that is incremented when a ware does not get a carrier for this |
587 | + /// road immediately and decremented over time. |
588 | int32_t wallet_; |
589 | |
590 | /// holds the gametime when wallet_ was last charged |
591 | |
592 | === modified file 'src/logic/map_objects/tribes/carrier.cc' |
593 | --- src/logic/map_objects/tribes/carrier.cc 2018-10-30 18:40:57 +0000 |
594 | +++ src/logic/map_objects/tribes/carrier.cc 2018-11-26 06:43:43 +0000 |
595 | @@ -51,7 +51,7 @@ |
596 | |
597 | top_state().ivar1 = 0; |
598 | |
599 | - operation_ = INIT; |
600 | + promised_pickup_to_ = NOONE; |
601 | } |
602 | |
603 | /** |
604 | @@ -78,14 +78,15 @@ |
605 | return pop_task(game); |
606 | } |
607 | |
608 | - if (operation_ == INIT) { |
609 | - operation_ = find_source_flag(game); |
610 | + // Check for pending wares |
611 | + if (promised_pickup_to_ == NOONE) { |
612 | + find_pending_ware(game); |
613 | } |
614 | |
615 | - if (operation_ > NO_OPERATION) { |
616 | + if (promised_pickup_to_ != NOONE) { |
617 | if (state.ivar1) { |
618 | state.ivar1 = 0; |
619 | - return start_task_transport(game, operation_); |
620 | + return start_task_transport(game, promised_pickup_to_); |
621 | } else { |
622 | // Short delay before we move to pick up |
623 | state.ivar1 = 1; |
624 | @@ -119,10 +120,10 @@ |
625 | * a ware there, we have to make sure that they do not count on us anymore. |
626 | */ |
627 | void Carrier::road_pop(Game& game, State& /* state */) { |
628 | - if (operation_ > NO_OPERATION && get_location(game)) { |
629 | + if (promised_pickup_to_ != NOONE && get_location(game)) { |
630 | Road& road = dynamic_cast<Road&>(*get_location(game)); |
631 | - Flag& flag = road.get_flag(static_cast<Road::FlagId>(operation_)); |
632 | - Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(operation_ ^ 1)); |
633 | + Flag& flag = road.get_flag(static_cast<Road::FlagId>(promised_pickup_to_)); |
634 | + Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(promised_pickup_to_ ^ 1)); |
635 | |
636 | flag.cancel_pickup(game, otherflag); |
637 | } |
638 | @@ -160,99 +161,35 @@ |
639 | return pop_task(game); |
640 | } |
641 | |
642 | - int32_t const ivar1 = state.ivar1; |
643 | - if (ivar1 == -1) { |
644 | + if (state.ivar1 == -1) { |
645 | // If we're "in" the target building, special code applies |
646 | - return deliver_to_building(game, state); |
647 | - } |
648 | - |
649 | - WareInstance* ware = get_carried_ware(game); |
650 | - if (ware) { |
651 | - assert(ware->get_location(game) == this); |
652 | - } |
653 | - |
654 | - Road& road = dynamic_cast<Road&>(*get_location(game)); |
655 | - int32_t const dest = ware ? ivar1 ^ 1 : ivar1; |
656 | - Flag& flag = road.get_flag(static_cast<Road::FlagId>(dest)); |
657 | - |
658 | - if (ware) { |
659 | - // If the ware should go to the building attached to our flag, |
660 | - // walk directly into said building |
661 | + deliver_to_building(game, state); |
662 | + } else if (!does_carry_ware()) { |
663 | + // If we don't carry something, walk to the flag |
664 | + pickup_from_flag(game, state); |
665 | + } else { |
666 | + Road& road = dynamic_cast<Road&>(*get_location(game)); |
667 | + // If the ware should go to the building attached to our flag, walk |
668 | + // directly into said building |
669 | + Flag& flag = road.get_flag(static_cast<Road::FlagId>(state.ivar1 ^ 1)); |
670 | + |
671 | + WareInstance& ware = *get_carried_ware(game); |
672 | + assert(ware.get_location(game) == this); |
673 | + |
674 | // A sanity check is necessary, in case the building has been destroyed |
675 | + PlayerImmovable* const next = ware.get_next_move_step(game); |
676 | |
677 | - PlayerImmovable* const next = ware->get_next_move_step(game); |
678 | if (next && next != &flag && &next->base_flag() == &flag) { |
679 | // pay some coins before entering the building, |
680 | // to compensate for the time to be spent in its street-segment |
681 | road.pay_for_building(); |
682 | - |
683 | - if (!start_task_walktoflag(game, dest)) { |
684 | - // Enter building |
685 | - state.ivar1 = -1; |
686 | - start_task_move(game, WALK_NW, descr().get_right_walk_anims(does_carry_ware()), true); |
687 | - } |
688 | - return; |
689 | - } |
690 | - } |
691 | - |
692 | - if (!start_task_walktoflag(game, dest, operation_ == WAIT)) { |
693 | - // If the flag is overloaded we are allowed to drop wares, |
694 | - // as long as we can pick another up. Otherwise we have to wait. |
695 | - |
696 | - Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(dest ^ 1)); |
697 | - int32_t otherware_idx = |
698 | - ware ? flag.find_swappable_ware(*ware, otherflag) : flag.find_pending_ware(otherflag); |
699 | - if (operation_ == WAIT) { |
700 | - if (otherware_idx < kNotFoundAppropriate) { |
701 | - return start_task_waitforcapacity(game, flag); // join flag's wait queue |
702 | - } else { |
703 | - operation_ = dest ^ 1; // resume transport without joining flag's wait queue |
704 | - set_animation(game, descr().get_animation("idle")); |
705 | - return schedule_act(game, 20); |
706 | - } |
707 | - } else if (otherware_idx < kNotFoundAppropriate) { |
708 | - operation_ = WAIT; // move one node away |
709 | - set_animation(game, descr().get_animation("idle")); |
710 | - return schedule_act(game, 20); |
711 | - } |
712 | - |
713 | - WareInstance* otherware = flag.fetch_pending_ware(game, otherware_idx); |
714 | - |
715 | - if (ware) { |
716 | - const bool ware_astray = (ware->get_next_move_step(game) == nullptr); |
717 | - // Drop our ware |
718 | - flag.add_ware(game, *fetch_carried_ware(game)); |
719 | - // If the destination of the dropped ware changed while carrying it and we don't have |
720 | - // anything else we should carry, we might pick it up again immediately, so check again |
721 | - if (ware_astray && otherware_idx == kNotFoundAppropriate) { |
722 | - otherware_idx = flag.find_pending_ware(otherflag); |
723 | - otherware = flag.fetch_pending_ware(game, otherware_idx); |
724 | - } |
725 | - } |
726 | - |
727 | - // Pick up new load, if any |
728 | - if (otherware) { |
729 | - // pay before getting the ware, while checking for road promotion |
730 | - road.pay_for_road(game, flag.count_wares_in_queue(otherflag)); |
731 | - |
732 | - set_carried_ware(game, otherware); |
733 | - flag.ware_departing(game); |
734 | - |
735 | - operation_ = state.ivar1 = dest; |
736 | - set_animation(game, descr().get_animation("idle")); |
737 | - schedule_act(game, 20); |
738 | - } else { |
739 | - Flag::PendingWare* pw = otherflag.get_ware_for_flag(flag, kPendingOnly); |
740 | - if (pw) { |
741 | - pw->pending = false; |
742 | - |
743 | - operation_ = state.ivar1 = dest ^ 1; |
744 | - set_animation(game, descr().get_animation("idle")); |
745 | - schedule_act(game, 20); |
746 | - } else { |
747 | - operation_ = NO_OPERATION; |
748 | - pop_task(game); |
749 | - } |
750 | + enter_building(game, state); |
751 | + } else if ((flag.has_capacity() || !swap_or_wait(game, state)) && |
752 | + !start_task_walktoflag(game, state.ivar1 ^ 1)) { |
753 | + // If the flag is overloaded we are allowed to drop wares as |
754 | + // long as we can pick another up. Otherwise we have to wait. |
755 | + // Drop the ware, possible exchanging it with another one |
756 | + drop_ware(game, state); |
757 | } |
758 | } |
759 | } |
760 | @@ -268,7 +205,6 @@ |
761 | BaseImmovable* const pos = game.map()[get_position()].get_immovable(); |
762 | |
763 | if (dynamic_cast<Flag const*>(pos)) { |
764 | - operation_ = INIT; |
765 | return pop_task(game); // we are done |
766 | } else if (upcast(Building, building, pos)) { |
767 | // Drop all wares addressed to this building |
768 | @@ -301,51 +237,212 @@ |
769 | } |
770 | |
771 | /** |
772 | - * Called by road code to indicate that the given flag |
773 | - * (0 = start, 1 = end) has a ware ready for transfer. |
774 | + * Walks to the queued flag and picks up one acked ware |
775 | + * |
776 | + * \param g Game the carrier lives on |
777 | + * \param s Flags sent to the task |
778 | + */ |
779 | +void Carrier::pickup_from_flag(Game& game, State& state) { |
780 | + int32_t const ivar1 = state.ivar1; |
781 | + if (!start_task_walktoflag(game, ivar1)) { |
782 | + |
783 | + promised_pickup_to_ = NOONE; |
784 | + |
785 | + Road& road = dynamic_cast<Road&>(*get_location(game)); |
786 | + Flag& flag = road.get_flag(static_cast<Road::FlagId>(ivar1)); |
787 | + Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(ivar1 ^ 1)); |
788 | + |
789 | + // Are there wares to move between our flags? |
790 | + if (WareInstance* const ware = flag.fetch_pending_ware(game, otherflag)) { |
791 | + // pay before getting the ware, while checking for road promotion |
792 | + road.pay_for_road(game, flag.count_wares_in_queue(otherflag)); |
793 | + set_carried_ware(game, ware); |
794 | + |
795 | + set_animation(game, descr().get_animation("idle")); |
796 | + return schedule_act(game, 20); |
797 | + } else { |
798 | + molog("[Carrier]: Nothing suitable on flag.\n"); |
799 | + return pop_task(game); |
800 | + } |
801 | + } |
802 | +} |
803 | + |
804 | +/** |
805 | + * Drop one ware in a flag, and pick up a new one if we acked it |
806 | + * |
807 | + * \param g Game the carrier lives on. |
808 | + * \param s Flags sent to the task |
809 | + */ |
810 | +void Carrier::drop_ware(Game& game, State& state) { |
811 | + WareInstance* other = nullptr; |
812 | + Road& road = dynamic_cast<Road&>(*get_location(game)); |
813 | + Flag& flag = road.get_flag(static_cast<Road::FlagId>(state.ivar1 ^ 1)); |
814 | + Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(state.ivar1)); |
815 | + |
816 | + if (promised_pickup_to_ == (state.ivar1 ^ 1)) { |
817 | + // If there's a ware we acked, we can drop ours even if the flag is |
818 | + // flooded |
819 | + other = flag.fetch_pending_ware(game, otherflag); |
820 | + |
821 | + if (!other && !flag.has_capacity()) { |
822 | + molog("[Carrier]: strange: acked ware from busy flag no longer " |
823 | + "present.\n"); |
824 | + |
825 | + promised_pickup_to_ = NOONE; |
826 | + set_animation(game, descr().get_animation("idle")); |
827 | + return schedule_act(game, 20); |
828 | + } |
829 | + |
830 | + state.ivar1 = promised_pickup_to_; |
831 | + promised_pickup_to_ = NOONE; |
832 | + } |
833 | + |
834 | + // Drop our ware |
835 | + flag.add_ware(game, *fetch_carried_ware(game)); |
836 | + |
837 | + // Pick up new load, if any |
838 | + if (other) { |
839 | + // pay before getting the ware, while checking for road promotion |
840 | + road.pay_for_road(game, flag.count_wares_in_queue(otherflag)); |
841 | + set_carried_ware(game, other); |
842 | + |
843 | + set_animation(game, descr().get_animation("idle")); |
844 | + return schedule_act(game, 20); |
845 | + } else { |
846 | + return pop_task(game); |
847 | + } |
848 | +} |
849 | + |
850 | +/** |
851 | + * When picking up wares, if some of them is targeted to the building attached |
852 | + * to target flag walk straight into it and deliver. |
853 | + * |
854 | + * \param g Game the carrier lives on. |
855 | + * \param s Flags sent to the task. |
856 | + */ |
857 | +void Carrier::enter_building(Game& game, State& state) { |
858 | + if (!start_task_walktoflag(game, state.ivar1 ^ 1)) { |
859 | + state.ivar1 = -1; |
860 | + return start_task_move(game, WALK_NW, descr().get_right_walk_anims(does_carry_ware()), true); |
861 | + } |
862 | +} |
863 | + |
864 | +/** |
865 | + * Swaps wares from an overloaded flag for as long as the carrier can pick |
866 | + * up new wares from it. Otherwise, changes the carrier state to wait. |
867 | + * |
868 | + * \param g Game the carrier lives on. |
869 | + * \param s Flags sent to the task. |
870 | + * |
871 | + * \return true if the carrier must wait before delivering his wares. |
872 | + */ |
873 | +bool Carrier::swap_or_wait(Game& game, State& state) { |
874 | + // Road that employs us |
875 | + Road& road = dynamic_cast<Road&>(*get_location(game)); |
876 | + // Flag we are delivering to |
877 | + Flag& flag = road.get_flag(static_cast<Road::FlagId>(state.ivar1 ^ 1)); |
878 | + // The other flag of our road |
879 | + Flag& otherflag = road.get_flag(static_cast<Road::FlagId>(state.ivar1)); |
880 | + |
881 | + if (promised_pickup_to_ == (state.ivar1 ^ 1)) { |
882 | + // All is well, we already acked a ware that we can pick up |
883 | + // from this flag |
884 | + return false; |
885 | + } else if (flag.has_pending_ware(game, otherflag)) { |
886 | + if (!flag.ack_pickup(game, otherflag)) { |
887 | + throw wexception( |
888 | + "MO(%u): transport: overload exchange: flag %u is fucked up", serial(), flag.serial()); |
889 | + } |
890 | + |
891 | + promised_pickup_to_ = state.ivar1 ^ 1; |
892 | + return false; |
893 | + } else if (!start_task_walktoflag(game, state.ivar1 ^ 1, true)) { |
894 | + start_task_waitforcapacity(game, flag); // wait one node away |
895 | + } |
896 | + |
897 | + return true; |
898 | +} |
899 | + |
900 | +/** |
901 | + * Called by Road code to indicate that a new ware has arrived on a flag |
902 | + * (0 = start, 1 = end). |
903 | * \return true if the carrier is going to fetch it. |
904 | */ |
905 | bool Carrier::notify_ware(Game& game, int32_t const flag) { |
906 | State& state = top_state(); |
907 | |
908 | - if (operation_ == WAIT) { |
909 | - if (state.objvar1.get(game) == |
910 | - &dynamic_cast<Road&>(*get_location(game)).get_flag(static_cast<Road::FlagId>(flag))) { |
911 | - operation_ = flag; |
912 | - send_signal(game, "wakeup"); |
913 | - return true; |
914 | - } |
915 | - } else if (operation_ == NO_OPERATION) { |
916 | - operation_ = flag; |
917 | + // Check if we've already acked something |
918 | + if (promised_pickup_to_ != NOONE) { |
919 | + return false; |
920 | + } |
921 | + |
922 | + // If we are currently in a transport. |
923 | + // Explanation: |
924 | + // a) a different carrier / road may be better suited for this ware |
925 | + // (the transport code does not have priorities for the actual |
926 | + // carrier that is notified) |
927 | + // b) the transport task has logic that allows it to |
928 | + // drop a ware on an overloaded flag iff it can pick up a ware |
929 | + // at the same time. |
930 | + // We should ack said ware to avoid more confusion before we move |
931 | + // onto the flag, but we can't do that if we have already acked |
932 | + // something. |
933 | + // c) we might ack for a flag that we are actually moving away from; |
934 | + // this will get us into trouble if wares have arrived on the other |
935 | + // flag while we couldn't ack them. |
936 | + // |
937 | + // (Maybe the need for this lengthy explanation is proof that the |
938 | + // ack system needs to be reworked.) |
939 | + if (State const* const transport = get_state(taskTransport)) |
940 | + if ((transport->ivar1 == -1 && find_closest_flag(game) != flag) || flag == transport->ivar1) |
941 | + return false; |
942 | + |
943 | + // Ack it if we haven't |
944 | + promised_pickup_to_ = flag; |
945 | + |
946 | + if (state.task == &taskRoad) { |
947 | send_signal(game, "ware"); |
948 | - return true; |
949 | + } else if (state.task == &taskWaitforcapacity) { |
950 | + send_signal(game, "wakeup"); |
951 | } |
952 | - |
953 | - return false; |
954 | + return true; |
955 | } |
956 | |
957 | /** |
958 | - * Find a pending ware meant for our road, |
959 | - * remove its pending status, and |
960 | - * \return the flag it is on. |
961 | + * Find a pending ware on one of the road's flags, ack it and set promised_pickup_to_ |
962 | + * accordingly. |
963 | */ |
964 | -int32_t Carrier::find_source_flag(Game& game) { |
965 | - assert(operation_ == INIT); |
966 | - |
967 | +void Carrier::find_pending_ware(Game& game) { |
968 | Road& road = dynamic_cast<Road&>(*get_location(game)); |
969 | - int32_t near = find_closest_flag(game); |
970 | - Flag& nearflag = road.get_flag(static_cast<Road::FlagId>(near)); |
971 | - Flag& farflag = road.get_flag(static_cast<Road::FlagId>(near ^ 1)); |
972 | - |
973 | - Flag::PendingWare* pw; |
974 | - if ((pw = nearflag.get_ware_for_flag(farflag))) { |
975 | - pw->pending = false; |
976 | - return near; |
977 | - } else if ((pw = farflag.get_ware_for_flag(nearflag, kPendingOnly))) { |
978 | - pw->pending = false; |
979 | - return near ^ 1; |
980 | - } else { |
981 | - return NO_OPERATION; |
982 | + uint32_t havewarebits = 0; |
983 | + |
984 | + assert(promised_pickup_to_ == NOONE); |
985 | + |
986 | + if (road.get_flag(Road::FlagStart).has_pending_ware(game, road.get_flag(Road::FlagEnd))) { |
987 | + havewarebits |= 1; |
988 | + } |
989 | + |
990 | + if (road.get_flag(Road::FlagEnd).has_pending_ware(game, road.get_flag(Road::FlagStart))) { |
991 | + havewarebits |= 2; |
992 | + } |
993 | + |
994 | + // If both flags have a ware, we pick the one closer to us. |
995 | + if (havewarebits == 3) { |
996 | + havewarebits = 1 << find_closest_flag(game); |
997 | + } |
998 | + |
999 | + // Ack our decision |
1000 | + if (havewarebits == 1) { |
1001 | + promised_pickup_to_ = START_FLAG; |
1002 | + if (!road.get_flag(Road::FlagStart).ack_pickup(game, road.get_flag(Road::FlagEnd))) { |
1003 | + throw wexception("Carrier::find_pending_ware: start flag is messed up"); |
1004 | + } |
1005 | + |
1006 | + } else if (havewarebits == 2) { |
1007 | + promised_pickup_to_ = END_FLAG; |
1008 | + if (!road.get_flag(Road::FlagEnd).ack_pickup(game, road.get_flag(Road::FlagStart))) { |
1009 | + throw wexception("Carrier::find_pending_ware: end flag is messed up"); |
1010 | + } |
1011 | } |
1012 | } |
1013 | |
1014 | @@ -418,7 +515,7 @@ |
1015 | |
1016 | Worker::log_general_info(egbase); |
1017 | |
1018 | - molog("operation = %i\n", operation_); |
1019 | + molog("promised_pickup_to = %i\n", promised_pickup_to_); |
1020 | } |
1021 | |
1022 | /* |
1023 | @@ -428,7 +525,7 @@ |
1024 | |
1025 | ============================== |
1026 | */ |
1027 | -constexpr uint8_t kCurrentPacketVersion = 2; |
1028 | +constexpr uint8_t kCurrentPacketVersion = 3; |
1029 | |
1030 | Carrier::Loader::Loader() { |
1031 | } |
1032 | @@ -437,10 +534,12 @@ |
1033 | Worker::Loader::load(fr); |
1034 | |
1035 | try { |
1036 | - uint8_t packet_version = fr.unsigned_8(); |
1037 | - if (packet_version == kCurrentPacketVersion) { |
1038 | + const uint8_t packet_version = fr.unsigned_8(); |
1039 | + // TODO(GunChleoc): Remove savegame compatibility after Build 21. |
1040 | + if (packet_version <= kCurrentPacketVersion && packet_version >= 1) { |
1041 | Carrier& carrier = get<Carrier>(); |
1042 | - carrier.operation_ = fr.signed_32(); |
1043 | + // TODO(GunChleoc): std::min is for savegame compatibility. Remove after Build 21. |
1044 | + carrier.promised_pickup_to_ = std::min(-1, fr.signed_32()); |
1045 | } else { |
1046 | throw UnhandledVersionError("Carrier", packet_version, kCurrentPacketVersion); |
1047 | } |
1048 | @@ -465,7 +564,7 @@ |
1049 | Worker::do_save(egbase, mos, fw); |
1050 | |
1051 | fw.unsigned_8(kCurrentPacketVersion); |
1052 | - fw.signed_32(operation_); |
1053 | + fw.signed_32(promised_pickup_to_); |
1054 | } |
1055 | |
1056 | CarrierDescr::CarrierDescr(const std::string& init_descname, |
1057 | |
1058 | === modified file 'src/logic/map_objects/tribes/carrier.h' |
1059 | --- src/logic/map_objects/tribes/carrier.h 2018-09-04 15:48:47 +0000 |
1060 | +++ src/logic/map_objects/tribes/carrier.h 2018-11-26 06:43:43 +0000 |
1061 | @@ -24,7 +24,6 @@ |
1062 | #include "logic/map_objects/tribes/worker.h" |
1063 | |
1064 | namespace Widelands { |
1065 | -class PendingWare; |
1066 | |
1067 | class CarrierDescr : public WorkerDescr { |
1068 | public: |
1069 | @@ -50,7 +49,7 @@ |
1070 | MO_DESCR(CarrierDescr) |
1071 | |
1072 | explicit Carrier(const CarrierDescr& carrier_descr) |
1073 | - : Worker(carrier_descr), operation_(NO_OPERATION) { |
1074 | + : Worker(carrier_descr), promised_pickup_to_(NOONE) { |
1075 | } |
1076 | ~Carrier() override { |
1077 | } |
1078 | @@ -67,7 +66,7 @@ |
1079 | static Task const taskRoad; |
1080 | |
1081 | private: |
1082 | - int32_t find_source_flag(Game&); |
1083 | + void find_pending_ware(Game&); |
1084 | int32_t find_closest_flag(Game&); |
1085 | |
1086 | // internal task stuff |
1087 | @@ -78,14 +77,17 @@ |
1088 | static Task const taskTransport; |
1089 | |
1090 | void deliver_to_building(Game&, State&); |
1091 | + void pickup_from_flag(Game&, State&); |
1092 | + void drop_ware(Game&, State&); |
1093 | + void enter_building(Game&, State&); |
1094 | + bool swap_or_wait(Game&, State&); |
1095 | |
1096 | + /// -1: no ware acked; 0/1: acked ware for start/end flag of road |
1097 | // This should be an enum, but this clutters the code with too many casts |
1098 | - static const int32_t INIT = -3; // ready to undertake or resume operations |
1099 | - static const int32_t WAIT = -2; // waiting for flag capacity |
1100 | - static const int32_t NO_OPERATION = -1; // idling |
1101 | - static const int32_t START_FLAG = 0; // serving start flag of road |
1102 | - static const int32_t END_FLAG = 1; // serving end flag of road |
1103 | - int32_t operation_; |
1104 | + static const int32_t NOONE = -1; |
1105 | + static const int32_t START_FLAG = 0; |
1106 | + static const int32_t END_FLAG = 1; |
1107 | + int32_t promised_pickup_to_; |
1108 | |
1109 | // saving and loading |
1110 | protected: |
1111 | |
1112 | === modified file 'src/logic/map_objects/tribes/worker.cc' |
1113 | --- src/logic/map_objects/tribes/worker.cc 2018-11-23 21:26:24 +0000 |
1114 | +++ src/logic/map_objects/tribes/worker.cc 2018-11-26 06:43:43 +0000 |
1115 | @@ -137,11 +137,10 @@ |
1116 | totalres += amount; |
1117 | totalchance += 8 * amount; |
1118 | |
1119 | - // Add penalty for fields that are running out |
1120 | - // Except for totally depleted fields or wrong ressource fields |
1121 | - // if we already know there is no ressource (left) we won't mine there |
1122 | + // Add penalty for fields that are running out |
1123 | if (amount == 0) |
1124 | - totalchance += 0; |
1125 | + // we already know it's completely empty, so punish is less |
1126 | + totalchance += 1; |
1127 | else if (amount <= 2) |
1128 | totalchance += 6; |
1129 | else if (amount <= 4) |
1130 | @@ -1820,11 +1819,12 @@ |
1131 | if (upcast(Flag, flag, pos)) { |
1132 | // Is this "our" flag? |
1133 | if (flag->get_building() == location) { |
1134 | - WareInstance* const ware = get_carried_ware(game); |
1135 | - if (state.ivar1 && ware && flag->has_capacity_for_ware(*ware)) { |
1136 | - flag->add_ware(game, *fetch_carried_ware(game)); |
1137 | - set_animation(game, descr().get_animation("idle")); |
1138 | - return schedule_act(game, 20); // rest a while |
1139 | + if (state.ivar1 && flag->has_capacity()) { |
1140 | + if (WareInstance* const ware = fetch_carried_ware(game)) { |
1141 | + flag->add_ware(game, *ware); |
1142 | + set_animation(game, descr().get_animation("idle")); |
1143 | + return schedule_act(game, 20); // rest a while |
1144 | + } |
1145 | } |
1146 | |
1147 | // Don't try to enter building if it is a dismantle site |
1148 | @@ -2057,18 +2057,16 @@ |
1149 | if (ware) { |
1150 | // We're in the building, walk onto the flag |
1151 | if (upcast(Building, building, location)) { |
1152 | - Flag& baseflag = building->base_flag(); |
1153 | - if (baseflag.has_capacity_for_ware(*ware)) { |
1154 | - start_task_leavebuilding(game, false); // exit throttle |
1155 | - } else { |
1156 | - start_task_waitforcapacity(game, baseflag); |
1157 | + if (start_task_waitforcapacity(game, building->base_flag())) { |
1158 | + return; |
1159 | } |
1160 | - return; |
1161 | + |
1162 | + return start_task_leavebuilding(game, false); // exit throttle |
1163 | } |
1164 | |
1165 | // We're on the flag, drop the ware and pause a little |
1166 | if (upcast(Flag, flag, location)) { |
1167 | - if (flag->has_capacity_for_ware(*ware)) { |
1168 | + if (flag->has_capacity()) { |
1169 | flag->add_ware(game, *fetch_carried_ware(game)); |
1170 | |
1171 | set_animation(game, descr().get_animation("idle")); |
1172 | @@ -2148,11 +2146,9 @@ |
1173 | |
1174 | // The ware has decided that it doesn't want to go to us after all |
1175 | // In order to return to the warehouse, we're switching to State_DropOff |
1176 | - Flag& flag = dynamic_cast<Flag&>(*location); |
1177 | if (WareInstance* const ware = |
1178 | - flag.fetch_pending_ware(game, flag.find_pending_ware(employer))) { |
1179 | + dynamic_cast<Flag&>(*location).fetch_pending_ware(game, employer)) { |
1180 | set_carried_ware(game, ware); |
1181 | - flag.ware_departing(game); |
1182 | } |
1183 | |
1184 | set_animation(game, descr().get_animation("idle")); |
1185 | @@ -2215,15 +2211,25 @@ |
1186 | static_cast<Bob::Ptr>(&Worker::waitforcapacity_pop), true}; |
1187 | |
1188 | /** |
1189 | - * Pushes a wait task and |
1190 | - * adds the worker to the flag's wait queue. |
1191 | + * Checks the capacity of the flag. |
1192 | + * |
1193 | + * If there is none, a wait task is pushed, and the worker is added to the |
1194 | + * flag's wait queue. The function returns true in this case. |
1195 | + * If the flag still has capacity, the function returns false and doesn't |
1196 | + * act at all. |
1197 | */ |
1198 | -void Worker::start_task_waitforcapacity(Game& game, Flag& flag) { |
1199 | +bool Worker::start_task_waitforcapacity(Game& game, Flag& flag) { |
1200 | + if (flag.has_capacity()) { |
1201 | + return false; |
1202 | + } |
1203 | + |
1204 | push_task(game, taskWaitforcapacity); |
1205 | |
1206 | top_state().objvar1 = &flag; |
1207 | |
1208 | flag.wait_for_capacity(game, *this); |
1209 | + |
1210 | + return true; |
1211 | } |
1212 | |
1213 | void Worker::waitforcapacity_update(Game& game, State&) { |
1214 | |
1215 | === modified file 'src/logic/map_objects/tribes/worker.h' |
1216 | --- src/logic/map_objects/tribes/worker.h 2018-09-14 08:46:36 +0000 |
1217 | +++ src/logic/map_objects/tribes/worker.h 2018-11-26 06:43:43 +0000 |
1218 | @@ -163,7 +163,7 @@ |
1219 | void start_task_releaserecruit(Game&, Worker&); |
1220 | void start_task_fetchfromflag(Game&); |
1221 | |
1222 | - void start_task_waitforcapacity(Game&, Flag&); |
1223 | + bool start_task_waitforcapacity(Game&, Flag&); |
1224 | void start_task_leavebuilding(Game&, bool changelocation); |
1225 | void start_task_fugitive(Game&); |
1226 |
Continuous integration builds have changed state:
Travis build 4272. State: errored. Details: https:/ /travis- ci.org/ widelands/ widelands/ builds/ 458903460. /ci.appveyor. com/project/ widelands- dev/widelands/ build/_ widelands_ dev_widelands_ remove_ anti_congestion _algorithm- 4066.
Appveyor build 4066. State: success. Details: https:/