Merge lp:~widelands-dev/widelands/request_supply_opt into lp:widelands

Proposed by TiborB
Status: Merged
Merged at revision: 7695
Proposed branch: lp:~widelands-dev/widelands/request_supply_opt
Merge into: lp:widelands
Diff against target: 314 lines (+123/-18)
8 files modified
src/economy/economy.cc (+76/-18)
src/economy/economy.h (+20/-0)
src/economy/idleworkersupply.cc (+5/-0)
src/economy/idleworkersupply.h (+1/-0)
src/economy/supply.h (+8/-0)
src/economy/ware_instance.cc (+11/-0)
src/economy/warehousesupply.h (+1/-0)
src/logic/warehouse.cc (+1/-0)
To merge this branch: bzr merge lp:~widelands-dev/widelands/request_supply_opt
Reviewer Review Type Date Requested Status
SirVer Approve
Tino Approve
Review via email: mp+280193@code.launchpad.net

Description of the change

This is small redesign of delivery of wares to requestors.
1. Engine now evenly distributes wares to all warehouses that are preferred for this type of ware (in other words, ware goes to a warehouse with lower stock of the material/worker)
2. Engine now test supplies in order starting from nearest one. This itself should lead to lesser computation. Additionaly I implemented a treshold (now 5) that test only 5 nearest supplies. The goal is to reduce CPU usage, especially on big maps. Routing is very expensive on long maps.

This was discussed on forum and must be yet considered.

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

Forum thread: https://wl.widelands.org/forum/topic/1856/

We still need to think about the threshold, but the rest of the code LGTM :)

This still needs testing, but I think we can wait with that until we have decided how to solve this.

Revision history for this message
TiborB (tiborb95) wrote :

Resubmit.

I removed controversial treshold, and added two features
a) if more wares (of the same type) on one flag, only one ware is considered
b) wares on ships are ignored. Routing is deceived because it considers port's flag as a actual location of ware/worker.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Hi, I am bunnybot (https://github.com/widelands/bunnybot).

I am keeping the source branch lp:~widelands-dev/widelands/request_supply_opt mirrored to
  https://github.com/widelands/widelands/tree/_widelands_dev_widelands_request_supply_opt

The latest continuous integration build can always be found here:
  https://travis-ci.org/widelands/widelands/branches
Please do not merge without making sure that it passes.

You can give me commands by starting a line with @bunnybot <command>. I understand:
 merge: Merges the source branch into the target branch, closing the pull request.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Travis build 119 has changed state to: failed. Details: https://travis-ci.org/widelands/widelands/builds/99743957.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Travis build 162 has changed state to: created. Details: https://travis-ci.org/widelands/widelands/builds/99874912.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Travis build 162 has changed state to: started. Details: https://travis-ci.org/widelands/widelands/builds/99874912.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Travis build 162 has changed state to: errored. Details: https://travis-ci.org/widelands/widelands/builds/99874912.

Revision history for this message
Tino (tino79) wrote :

LGTM.
I cannot really quantify the performance gain, but i did not find any regression.

review: Approve
Revision history for this message
bunnybot (widelandsofficial) wrote :

Travis build 162 has changed state to: errored. Details: https://travis-ci.org/widelands/widelands/builds/99874912.

Revision history for this message
SirVer (sirver) wrote :

I think this is broken in the current state. The problem is that logic depends on available_supply which is a multimap. The problem is that the map is sorted by distance, then by a pointer.

In a replay or in a multiplayer games, the order of elements in this map is different, yielding therefore different routing results. This will desync the game.

Change the ordering to use a tie-breaker, for example the game object id before the pointer.

review: Needs Fixing
Revision history for this message
bunnybot (widelandsofficial) wrote :

Travis build 162 has changed state to: passed. Details: https://travis-ci.org/widelands/widelands/builds/99874912.

Revision history for this message
TiborB (tiborb95) wrote :

@SirVer

What about:

std::multimap<<uint32_t,uint32_t>, Supply*> available_supplies;

Where <uint32_t,int32_t> is <distance, serial>, serial should be the same across the network clients, I presume...

Revision history for this message
SirVer (sirver) wrote :

That should work - but I would suggest to make a tiny private struct to improve readability.

struct SupplyQuality {
   uint32 distance;
   uint32 serial;

   bool operator<(const SupplyQuality& other) const {
       return std::forward_as_tuple(distance, serial) < std::forward_as_tuple(other.distance, other.serial);
   }
}

Revision history for this message
TiborB (tiborb95) wrote :

Well I am not that skillful in C++, I want(ed) to use trivial:

bool operator() (const uint32_t & p1, const uint32_t & p2) const {
 return p1.distance == p2.distance ? p1.serial < p2.serial : p1.distance < p2.distance;
}

(not tested of course)

Revision history for this message
TiborB (tiborb95) wrote :

Oh, I just read about comparison of tuples, so I understand your example now, thanks..

Revision history for this message
TiborB (tiborb95) wrote :

@SirVer

I reworked it and testing it. I am not satisfied with performance though. Perhaps you know that I proposed a treshold (f.e. 5) that would check only 5 nearest (as crow fly) wares and pick a one from them. This could improve performance, but was rejected and currently is not in the code.

However I have another suggestion - let revive the treshold and X nearest wares are checked all, and from other wares only the ones that are in the warehouses. It used to be this way before AFAIK. I mean only wares in warehouses were used for delivery.

I currently test 512x512 map and after 5 hours it can barely run at 2x speed. I dont say that the routing is culprit but I believe it has its share...

I have not pushed new code yet.

Revision history for this message
SirVer (sirver) wrote :

[threshold]
I did not follow the discussion about the threshold though, on a quick thought I can see downsides to this approach. I suggest doing more timing analysis (with AI disabled) to figure out what actually takes time here and if there are ways of improving the situation.

> I dont say that the routing is culprit but I believe it has its share...

you have to proof that to make me believe it :). In my benchmarks about timing with the drawing code, AI is always dwarfing everything else in profiles, especially in longer games - but I rarely look at very large maps, so I'd need to proof what actually takes the most time too.

If you feel this approach is an improvement, how about we merge it soonish and then go back and try timing a large map with AI disabled to see what actually eats cycles.

Revision history for this message
TiborB (tiborb95) wrote :

So I made a bit of profiling, first of all it seems the game (drawing itself) takes quite a lot of CPU time - perhaps problem on my side? Tests run for 3 minutes of gameplay, but loading took also quite a bit of time (not counted in 3 minutes)....

But results:
I compared
1. trunk + crater (small map after 45 min)
2. trunk + Cristobals sea (512x512 after 4 hours)
3. request_supply_opt + Cristobals sea (512x512 after 4 hours)

I used savegames...

I picked only 3 functions here, look at second column (cummulative %)

trunk+crater:
[79] 1.8 0.00 0.17 4530 DefaultAI::think() [79]
[90] 1.6 0.00 0.14 37761 Widelands::Economy::_find_best_supply()
[94] 1.6 0.00 0.14 5494 Widelands::Economy::find_route()

trunk + big map (Cristobals sea)
[16] 22.8 0.00 8.43 105284 Widelands::Economy::find_route()
[24] 17.5 0.26 6.20 1145776 Widelands::Economy::_find_best_supply() [24]
[65] 3.8 0.02 1.38 22120 DefaultAI::think()

this branch + big map (Cristobals sea)
[20] 15.7 0.00 5.76 112254 Widelands::Economy::find_route()
[24] 14.8 0.39 5.06 1302844 Widelands::Economy::_find_best_supply()
[61] 4.3 0.00 1.59 33740 DefaultAI::think() [61]

My conclusions:
On big maps, _find_best_supply takes significant portion of CPU time, many fold then AI.
My changes as they are now, brings reduction about 20% of _find_best_supply and about 35% of find_route() + on big maps.

I believe implementing a treshold would help to further reduction.....

Revision history for this message
SirVer (sirver) wrote :

> So I made a bit of profiling, first of all it seems the game (drawing itself) takes quite a lot of CPU time - perhaps problem on my side?

No, that is accurate. The render_queue branch makes this already better, but only a full texture_atlas will make this really fast. I picked up working on this today again.

The threshold will at most cut the time in half for find_best_supply if i understood correctly. How much will that actually buy us? I suggest getting the change in as is without the threshold - as it should be correct in all cases and then experiment on threshold or even completely different approaches. Let us know if you think it is ready for another look.

Revision history for this message
TiborB (tiborb95) wrote :

> The threshold will at most cut the time in half for find_best_supply if i understood correctly.

I dont think there is mathematical reason for 'half' but if it was half it would be great....

It depends on number of supplies - if supplies count<=treshold - no change at all. Or rather - savings depend on the size of player's teritorry/economy....

I did some changes today so you can look at the code again now

Revision history for this message
SirVer (sirver) wrote :

code lgtm now. A couple of minor nits, feel free to merge after addressing these.

review: Approve
Revision history for this message
TiborB (tiborb95) wrote :

Added a comment to your comment, see in diff

Revision history for this message
TiborB (tiborb95) wrote :

@SirVer

I incorporated your comments, with one exception, can I merge it?

Revision history for this message
SirVer (sirver) wrote :

Tibor, sure, go ahead and merge.

> I looked at other examples f.e. here: http://bazaar.launchpad.net/~widelands-dev/widelands/request_supply_opt/view/head:/src/economy/supply.h#L94 and everywhere it is done this way.

Ah, that is a philosophical question, really. Does local style trump global style? Should better paradigms be adapted peu-a-peu or in one big refactoring? There are many school of thoughts here. I think once you identified a better approach, you should start using it for new code and fix old code over time. Other people think that you should keep the old ways until you can change a full code base to new ways.

So there are really two questions for you here:

1) do you agree that passing mutable values by pointer is better than passing them by non-const reference? I find foo(&game) vs foo(game) a clear advantage for readability, so I'd say yes. This also follows the google style guide which I find a great reference of how and why to do things anyways. But you might disagree and I am in no position to enforce a 'true' widelands code style.

2) do you agree that new code should adopt new paradigms immediately at the cost of inconsistency in the code base or not?

As said, I answer yes to both questions, so I'd change the code to using a pointer. But it is entirely your call. I will not think any worse of you if you decide against changing the code :)

> Also note the 'const' at the end of line, does it not guarantee immutability of Game?

no, the const at the end of the line means that the object represented by 'this' cannot change, but does not say anything about the arguments of the method - they can change.

Revision history for this message
TiborB (tiborb95) wrote :

You are right, I will rework it, though I am not that good programmer so it is not as simple for me as for you. This is only reason why I opted to mimic the existing code.
But as there is no need to hurry with this branch so it can wait a bit again

Revision history for this message
GunChleoc (gunchleoc) wrote :

Changing a reference to a pointer can be a bit of a pain, but it isn't complex - the compiler will tell you if anything goes wrong, so you can't mess it up. What you need to do is change foo.bar to foo->bar within the function, and add & or * in front of foo when calling the function - I can never remember which symbol to use here, but the compiler will tell me :)

Revision history for this message
TiborB (tiborb95) wrote :

reworked, tested (not long time). Can you please look at it once more?

Revision history for this message
SirVer (sirver) wrote :

there are still NOCOM in the diff which need removing, otherwise lgtm.

review: Approve
Revision history for this message
TiborB (tiborb95) wrote :

Thanks!

@bunnybot merge

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/economy/economy.cc'
--- src/economy/economy.cc 2015-11-11 09:52:55 +0000
+++ src/economy/economy.cc 2016-01-07 18:40:19 +0000
@@ -20,6 +20,7 @@
20#include "economy/economy.h"20#include "economy/economy.h"
2121
22#include <memory>22#include <memory>
23#include <unordered_set>
2324
24#include <boost/bind.hpp>25#include <boost/bind.hpp>
2526
@@ -664,14 +665,40 @@
664 Route * best_route = nullptr;665 Route * best_route = nullptr;
665 int32_t best_cost = -1;666 int32_t best_cost = -1;
666 Flag & target_flag = req.target_flag();667 Flag & target_flag = req.target_flag();
668 Map & map = game.map();
669
670 available_supplies.clear();
667671
668 for (size_t i = 0; i < m_supplies.get_nrsupplies(); ++i) {672 for (size_t i = 0; i < m_supplies.get_nrsupplies(); ++i) {
669 Supply & supp = m_supplies[i];673 Supply & supp = m_supplies[i];
670674
671 // Check requirements675 // Just skip if supply does not provide required ware
672 if (!supp.nr_supplies(game, req))676 if (!supp.nr_supplies(game, req))
673 continue;677 continue;
674678
679 const SupplyProviders provider = supp.provider_type(&game);
680
681 // We generally ignore disponible wares on ship as it is not possible to reliably
682 // calculate route (transportation time)
683 if (provider == SupplyProviders::kShip) {
684 continue;
685 }
686
687 const Widelands::Coords provider_position = supp.get_position(game)->base_flag().get_position();
688
689 const uint32_t dist = map.calc_distance(target_flag.get_position(), provider_position);
690
691 UniqueDistance ud = {dist, supp.get_position(game)->serial(), provider};
692
693 // std::map quarantees uniqueness, practically it means that if more wares are on the same flag, only
694 // first one will be inserted into available_supplies
695 available_supplies.insert(std::make_pair(ud, &m_supplies[i]));
696 }
697
698 // Now available supplies have been sorted by distance to requestor
699 for (auto& supplypair : available_supplies) {
700 Supply & supp = *supplypair.second;
701
675 Route * const route =702 Route * const route =
676 best_route != &buf_route0 ? &buf_route0 : &buf_route1;703 best_route != &buf_route0 ? &buf_route0 : &buf_route1;
677 // will be cleared by find_route()704 // will be cleared by find_route()
@@ -685,11 +712,17 @@
685 req.get_type(),712 req.get_type(),
686 best_cost))713 best_cost))
687 {714 {
688 if (!best_route)715 if (!best_route) {
689 log ("Economy::find_best_supply: Error, COULD NOT FIND A ROUTE!");716 log ("Economy::find_best_supply: Error, COULD NOT FIND A ROUTE!");
717 // To help to debug this a bit:
718 log (" ... ware at: %3dx%3d, requestor at: %3dx%3d!",
719 supp.get_position(game)->base_flag().get_position().x,
720 supp.get_position(game)->base_flag().get_position().y,
721 target_flag.get_position().x,
722 target_flag.get_position().y);
723 }
690 continue;724 continue;
691 }725 }
692
693 best_supply = &supp;726 best_supply = &supp;
694 best_route = route;727 best_route = route;
695 best_cost = route->get_totalcost();728 best_cost = route->get_totalcost();
@@ -776,8 +809,9 @@
776 }809 }
777810
778 int32_t const priority = req.get_priority(cost);811 int32_t const priority = req.get_priority(cost);
779 if (priority < 0)812 if (priority < 0) {
780 continue;813 continue;
814 }
781815
782 // Otherwise, consider this request/supply pair for queueing816 // Otherwise, consider this request/supply pair for queueing
783 RequestSupplyPair rsp;817 RequestSupplyPair rsp;
@@ -825,8 +859,9 @@
825 rsps.nexttimer = 200;859 rsps.nexttimer = 200;
826 }860 }
827861
828 if (rsps.nexttimer > 0) // restart the timer, if necessary862 if (rsps.nexttimer > 0) { // restart the timer, if necessary
829 _start_request_timer(rsps.nexttimer);863 _start_request_timer(rsps.nexttimer);
864 }
830}865}
831866
832867
@@ -1037,12 +1072,30 @@
10371072
1038 bool haveprefer = false;1073 bool haveprefer = false;
1039 bool havenormal = false;1074 bool havenormal = false;
1075
1076 // One of preferred warehouses (if any) with lowest stock of ware/worker
1077 Warehouse * preferred_wh = nullptr;
1078 // Stock of particular ware in preferred warehouse
1079 uint32_t preferred_wh_stock = std::numeric_limits<uint32_t>::max();
1080
1040 for (uint32_t nwh = 0; nwh < m_warehouses.size(); ++nwh) {1081 for (uint32_t nwh = 0; nwh < m_warehouses.size(); ++nwh) {
1041 Warehouse * wh = m_warehouses[nwh];1082 Warehouse * wh = m_warehouses[nwh];
1042 Warehouse::StockPolicy policy = wh->get_stock_policy(type, ware);1083 Warehouse::StockPolicy policy = wh->get_stock_policy(type, ware);
1043 if (policy == Warehouse::SP_Prefer) {1084 if (policy == Warehouse::SP_Prefer) {
1044 haveprefer = true;1085 haveprefer = true;
1045 break;1086
1087 // Getting count of worker/ware
1088 uint32_t current_stock;
1089 if (type == WareWorker::wwWARE) {
1090 current_stock = wh->get_wares().stock(ware);
1091 } else {
1092 current_stock = wh->get_workers().stock(ware);
1093 }
1094 // Stocks lower then in previous one?
1095 if (current_stock < preferred_wh_stock) {
1096 preferred_wh = wh;
1097 preferred_wh_stock = current_stock;
1098 }
1046 }1099 }
1047 if (policy == Warehouse::SP_Normal)1100 if (policy == Warehouse::SP_Normal)
1048 havenormal = true;1101 havenormal = true;
@@ -1050,17 +1103,22 @@
1050 if (!havenormal && !haveprefer && type == wwWARE)1103 if (!havenormal && !haveprefer && type == wwWARE)
1051 continue;1104 continue;
10521105
1053 Warehouse * wh = find_closest_warehouse1106 // We either have one preferred warehouse picked up or walk on roads to find nearest one
1054 (supply.get_position(game)->base_flag(), type, nullptr, 0,1107 Warehouse * wh = nullptr;
1055 (!haveprefer && !havenormal)1108 if (preferred_wh) {
1056 ?1109 wh = preferred_wh;
1057 WarehouseAcceptFn()1110 } else {
1058 :1111 wh = find_closest_warehouse
1059 boost::bind1112 (supply.get_position(game)->base_flag(), type, nullptr, 0,
1060 (&accept_warehouse_if_policy,1113 (!havenormal)
1061 _1, type, ware,1114 ?
1062 haveprefer ? Warehouse::SP_Prefer : Warehouse::SP_Normal));1115 WarehouseAcceptFn()
10631116 :
1117 boost::bind
1118 (&accept_warehouse_if_policy,
1119 _1, type, ware,
1120 Warehouse::SP_Normal));
1121 }
1064 if (!wh) {1122 if (!wh) {
1065 log1123 log
1066 ("Warning: Economy::_handle_active_supplies "1124 ("Warning: Economy::_handle_active_supplies "
10671125
=== modified file 'src/economy/economy.h'
--- src/economy/economy.h 2015-11-11 09:52:55 +0000
+++ src/economy/economy.h 2016-01-07 18:40:19 +0000
@@ -31,6 +31,7 @@
31#include "logic/instances.h"31#include "logic/instances.h"
32#include "logic/warelist.h"32#include "logic/warelist.h"
33#include "logic/wareworker.h"33#include "logic/wareworker.h"
34#include "economy/supply.h"
34#include "economy/supply_list.h"35#include "economy/supply_list.h"
35#include "ui_basic/unique_window.h"36#include "ui_basic/unique_window.h"
3637
@@ -184,6 +185,22 @@
184 void rebalance_supply() {_start_request_timer();}185 void rebalance_supply() {_start_request_timer();}
185186
186private:187private:
188
189 // This structs is to store distance from supply to request(or), but to allow unambiguous
190 // sorting if distances are the same, we use also serial number of provider and type of provider (flag,
191 // warehouse)
192 struct UniqueDistance {
193 bool operator<(const UniqueDistance& other) const {
194 return std::forward_as_tuple(distance, serial, provider_type)
195 <
196 std::forward_as_tuple(other.distance, other.serial, other.provider_type);
197 }
198
199 uint32_t distance;
200 uint32_t serial;
201 SupplyProviders provider_type;
202 };
203
187/*************/204/*************/
188/* Functions */205/* Functions */
189/*************/206/*************/
@@ -237,6 +254,9 @@
237 static std::unique_ptr<Soldier> m_soldier_prototype;254 static std::unique_ptr<Soldier> m_soldier_prototype;
238 UI::UniqueWindow::Registry m_optionswindow_registry;255 UI::UniqueWindow::Registry m_optionswindow_registry;
239256
257 // 'list' of unique providers
258 std::map<UniqueDistance, Supply*> available_supplies;
259
240 DISALLOW_COPY_AND_ASSIGN(Economy);260 DISALLOW_COPY_AND_ASSIGN(Economy);
241};261};
242262
243263
=== modified file 'src/economy/idleworkersupply.cc'
--- src/economy/idleworkersupply.cc 2015-11-11 09:52:55 +0000
+++ src/economy/idleworkersupply.cc 2016-01-07 18:40:19 +0000
@@ -71,6 +71,11 @@
71 return true;71 return true;
72}72}
7373
74SupplyProviders IdleWorkerSupply::provider_type(Game *) const
75{
76 return SupplyProviders::kFlagOrRoad;
77}
78
74bool IdleWorkerSupply::has_storage() const79bool IdleWorkerSupply::has_storage() const
75{80{
76 return m_worker.get_transfer();81 return m_worker.get_transfer();
7782
=== modified file 'src/economy/idleworkersupply.h'
--- src/economy/idleworkersupply.h 2015-11-11 09:52:55 +0000
+++ src/economy/idleworkersupply.h 2016-01-07 18:40:19 +0000
@@ -34,6 +34,7 @@
34 PlayerImmovable * get_position(Game &) override;34 PlayerImmovable * get_position(Game &) override;
3535
36 bool is_active() const override;36 bool is_active() const override;
37 SupplyProviders provider_type(Game *) const override;
37 bool has_storage() const override;38 bool has_storage() const override;
38 void get_ware_type(WareWorker & type, DescriptionIndex & ware) const override;39 void get_ware_type(WareWorker & type, DescriptionIndex & ware) const override;
39 void send_to_storage(Game &, Warehouse * wh) override;40 void send_to_storage(Game &, Warehouse * wh) override;
4041
=== modified file 'src/economy/supply.h'
--- src/economy/supply.h 2015-11-11 09:52:55 +0000
+++ src/economy/supply.h 2016-01-07 18:40:19 +0000
@@ -33,6 +33,8 @@
33class WareInstance;33class WareInstance;
34class Worker;34class Worker;
3535
36enum class SupplyProviders {kWarehouse, kFlagOrRoad, kShip};
37
36/**38/**
37 * A Supply is a virtual base class representing something that can offer39 * A Supply is a virtual base class representing something that can offer
38 * wares of any type for any purpose.40 * wares of any type for any purpose.
@@ -57,6 +59,12 @@
57 virtual bool is_active() const = 0;59 virtual bool is_active() const = 0;
5860
59 /**61 /**
62 * Return the type of player im/movable where the ware is now (warehouse,
63 * flag or ship).
64 */
65 virtual SupplyProviders provider_type(Game *) const = 0;
66
67 /**
60 * Indicates whether this supply is in storage or on its way to68 * Indicates whether this supply is in storage or on its way to
61 * storage.69 * storage.
62 *70 *
6371
=== modified file 'src/economy/ware_instance.cc'
--- src/economy/ware_instance.cc 2015-12-28 10:08:39 +0000
+++ src/economy/ware_instance.cc 2016-01-07 18:40:19 +0000
@@ -55,6 +55,7 @@
55 // implementation of Supply55 // implementation of Supply
56 PlayerImmovable * get_position(Game &) override;56 PlayerImmovable * get_position(Game &) override;
57 bool is_active() const override;57 bool is_active() const override;
58 SupplyProviders provider_type(Game *) const override;
58 bool has_storage() const override;59 bool has_storage() const override;
59 void get_ware_type(WareWorker & type, DescriptionIndex & ware) const override;60 void get_ware_type(WareWorker & type, DescriptionIndex & ware) const override;
60 void send_to_storage(Game &, Warehouse * wh) override;61 void send_to_storage(Game &, Warehouse * wh) override;
@@ -126,6 +127,16 @@
126 return true;127 return true;
127}128}
128129
130SupplyProviders IdleWareSupply::provider_type(Game* game) const
131{
132 MapObject * const loc = m_ware.get_location(*game);
133 if (is_a(Ship, loc)) {
134 return SupplyProviders::kShip;
135 }
136
137 return SupplyProviders::kFlagOrRoad;
138}
139
129bool IdleWareSupply::has_storage() const140bool IdleWareSupply::has_storage() const
130{141{
131 return m_ware.is_moving();142 return m_ware.is_moving();
132143
=== modified file 'src/economy/warehousesupply.h'
--- src/economy/warehousesupply.h 2015-11-11 09:52:55 +0000
+++ src/economy/warehousesupply.h 2016-01-07 18:40:19 +0000
@@ -55,6 +55,7 @@
55 // Supply implementation55 // Supply implementation
56 PlayerImmovable * get_position(Game &) override;56 PlayerImmovable * get_position(Game &) override;
57 bool is_active() const override;57 bool is_active() const override;
58 SupplyProviders provider_type(Game *) const override;
58 bool has_storage() const override;59 bool has_storage() const override;
59 void get_ware_type(WareWorker & type, DescriptionIndex & ware) const override;60 void get_ware_type(WareWorker & type, DescriptionIndex & ware) const override;
6061
6162
=== modified file 'src/logic/warehouse.cc'
--- src/logic/warehouse.cc 2015-11-21 11:34:10 +0000
+++ src/logic/warehouse.cc 2016-01-07 18:40:19 +0000
@@ -183,6 +183,7 @@
183183
184/// Warehouse supplies are never active.184/// Warehouse supplies are never active.
185bool WarehouseSupply::is_active() const {return false;}185bool WarehouseSupply::is_active() const {return false;}
186SupplyProviders WarehouseSupply::provider_type(Game *) const {return SupplyProviders::kWarehouse;}
186187
187bool WarehouseSupply::has_storage() const188bool WarehouseSupply::has_storage() const
188{189{

Subscribers

People subscribed via source and target branches

to status/vote changes: