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

Proposed by Benedikt Straub on 2018-07-31
Status: Needs review
Proposed branch: lp:~widelands-dev/widelands/ferry
Merge into: lp:widelands
Diff against target: 14264 lines (+5656/-1908)
231 files modified
data/campaigns/emp03.wmf/scripting/mission_thread.lua (+1/-1)
data/campaigns/emp04.wmf/scripting/starting_conditions.lua (+1/-1)
data/campaigns/tutorial01_basic_control.wmf/scripting/mission_thread.lua (+2/-2)
data/campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua (+1/-1)
data/maps/Archipelago_Sea.wmf/elemental (+1/-1)
data/maps/Archipelago_Sea.wmf/port_spaces (+1/-0)
data/maps/Calvisson.wmf/elemental (+1/-1)
data/maps/Calvisson.wmf/port_spaces (+1/-0)
data/maps/Fellowships_v2.wmf/elemental (+1/-1)
data/maps/Fellowships_v2.wmf/port_spaces (+1/-0)
data/maps/Finnish_Lakes.wmf/port_spaces (+1/-0)
data/maps/Four_Castles.wmf/elemental (+1/-1)
data/maps/Four_Castles.wmf/port_spaces (+1/-0)
data/maps/Golden_Peninsula.wmf/elemental (+1/-1)
data/maps/Golden_Peninsula.wmf/port_spaces (+1/-0)
data/maps/Ice_wars.wmf/elemental (+1/-1)
data/maps/Ice_wars.wmf/port_spaces (+1/-0)
data/maps/Impact.wmf/elemental (+1/-1)
data/maps/Impact.wmf/port_spaces (+1/-0)
data/maps/Islands_at_War.wmf/elemental (+1/-1)
data/maps/Islands_at_War.wmf/port_spaces (+1/-0)
data/maps/Kings_and_Queens_v2.wmf/elemental (+1/-1)
data/maps/Kings_and_Queens_v2.wmf/port_spaces (+1/-0)
data/maps/Lake_of_Tranquility.wmf/elemental (+1/-1)
data/maps/Lake_of_Tranquility.wmf/port_spaces (+1/-0)
data/maps/Last_Bastion_v2.wmf/elemental (+1/-1)
data/maps/Last_Bastion_v2.wmf/port_spaces (+1/-0)
data/maps/Rendez-Vous.wmf/elemental (+1/-1)
data/maps/Rendez-Vous.wmf/port_spaces (+1/-0)
data/maps/River_Explorers.wmf/elemental (+1/-1)
data/maps/River_Explorers.wmf/port_spaces (+1/-0)
data/maps/Riverlands.wmf/elemental (+1/-1)
data/maps/Riverlands.wmf/port_spaces (+1/-0)
data/maps/Sun_of_Fire.wmf/elemental (+1/-1)
data/maps/Sun_of_Fire.wmf/port_spaces (+1/-0)
data/maps/The_Far_North.wmf/elemental (+1/-1)
data/maps/The_Far_North.wmf/port_spaces (+1/-0)
data/maps/The_Long_Way.wmf/elemental (+1/-1)
data/maps/The_Long_Way.wmf/port_spaces (+1/-0)
data/maps/The_Nile_v2.wmf/elemental (+1/-1)
data/maps/The_Nile_v2.wmf/port_spaces (+1/-0)
data/maps/The_Pass_Through_the_Mountains.wmf/elemental (+1/-1)
data/maps/The_Pass_Through_the_Mountains.wmf/port_spaces (+1/-0)
data/maps/Twin_Lagoons_v2.wmf/elemental (+1/-1)
data/maps/Twin_Lagoons_v2.wmf/port_spaces (+1/-0)
data/maps/Twinkling_Waves.wmf/elemental (+1/-1)
data/maps/Twinkling_Waves.wmf/port_spaces (+1/-0)
data/maps/Volcanic_Winter.wmf/elemental (+1/-1)
data/maps/Volcanic_Winter.wmf/port_spaces (+1/-0)
data/tribes/atlanteans.lua (+10/-2)
data/tribes/barbarians.lua (+7/-1)
data/tribes/buildings/productionsites/atlanteans/ferry_yard/helptexts.lua (+27/-0)
data/tribes/buildings/productionsites/atlanteans/ferry_yard/init.lua (+55/-0)
data/tribes/buildings/productionsites/atlanteans/shipyard/init.lua (+1/-1)
data/tribes/buildings/productionsites/barbarians/ferry_yard/helptexts.lua (+27/-0)
data/tribes/buildings/productionsites/barbarians/ferry_yard/init.lua (+54/-0)
data/tribes/buildings/productionsites/barbarians/shipyard/init.lua (+1/-1)
data/tribes/buildings/productionsites/barbarians/weaving_mill/init.lua (+1/-1)
data/tribes/buildings/productionsites/empire/ferry_yard/helptexts.lua (+27/-0)
data/tribes/buildings/productionsites/empire/ferry_yard/init.lua (+54/-0)
data/tribes/buildings/productionsites/empire/shipyard/init.lua (+1/-1)
data/tribes/buildings/productionsites/frisians/ferry_yard/helptexts.lua (+27/-0)
data/tribes/buildings/productionsites/frisians/ferry_yard/init.lua (+59/-0)
data/tribes/buildings/productionsites/frisians/shipyard/init.lua (+1/-1)
data/tribes/buildings/productionsites/frisians/weaving_mill/init.lua (+1/-1)
data/tribes/buildings/warehouses/atlanteans/port/init.lua (+1/-1)
data/tribes/buildings/warehouses/barbarians/port/init.lua (+1/-1)
data/tribes/buildings/warehouses/empire/port/init.lua (+1/-1)
data/tribes/buildings/warehouses/frisians/port/init.lua (+1/-1)
data/tribes/empire.lua (+7/-1)
data/tribes/frisians.lua (+7/-1)
data/tribes/init.lua (+8/-0)
data/tribes/workers/atlanteans/ferry/helptexts.lua (+4/-0)
data/tribes/workers/atlanteans/ferry/init.lua (+34/-0)
data/tribes/workers/atlanteans/shipwright/init.lua (+7/-1)
data/tribes/workers/barbarians/ferry/helptexts.lua (+4/-0)
data/tribes/workers/barbarians/ferry/init.lua (+34/-0)
data/tribes/workers/barbarians/shipwright/init.lua (+7/-1)
data/tribes/workers/empire/ferry/helptexts.lua (+4/-0)
data/tribes/workers/empire/ferry/init.lua (+34/-0)
data/tribes/workers/empire/shipwright/init.lua (+7/-1)
data/tribes/workers/frisians/ferry/helptexts.lua (+4/-0)
data/tribes/workers/frisians/ferry/init.lua (+34/-0)
data/tribes/workers/frisians/shipwright/init.lua (+7/-1)
src/ai/ai_help_structs.h (+1/-0)
src/ai/defaultai.cc (+35/-26)
src/ai/defaultai_seafaring.cc (+1/-1)
src/economy/CMakeLists.txt (+8/-2)
src/economy/cmd_call_economy_balance.cc (+8/-3)
src/economy/cmd_call_economy_balance.h (+1/-0)
src/economy/economy.cc (+230/-251)
src/economy/economy.h (+35/-48)
src/economy/economy_data_packet.cc (+45/-46)
src/economy/expedition_bootstrap.cc (+38/-27)
src/economy/expedition_bootstrap.h (+3/-2)
src/economy/ferry_fleet.cc (+500/-0)
src/economy/ferry_fleet.h (+123/-0)
src/economy/flag.cc (+120/-51)
src/economy/flag.h (+24/-9)
src/economy/idleworkersupply.cc (+1/-1)
src/economy/input_queue.cc (+12/-8)
src/economy/portdock.cc (+28/-22)
src/economy/portdock.h (+7/-7)
src/economy/request.cc (+29/-21)
src/economy/road.cc (+39/-237)
src/economy/road.h (+28/-87)
src/economy/roadbase.cc (+227/-0)
src/economy/roadbase.h (+123/-0)
src/economy/routeastar.cc (+5/-5)
src/economy/routeastar.h (+32/-12)
src/economy/router.cc (+3/-1)
src/economy/routing_node.h (+25/-15)
src/economy/ship_fleet.cc (+150/-112)
src/economy/ship_fleet.h (+15/-13)
src/economy/shippingitem.cc (+6/-4)
src/economy/shippingitem.h (+1/-1)
src/economy/test/test_routing.cc (+13/-7)
src/economy/transfer.cc (+16/-16)
src/economy/ware_instance.cc (+8/-7)
src/economy/warehousesupply.h (+4/-3)
src/economy/wares_queue.cc (+8/-7)
src/economy/waterway.cc (+236/-0)
src/economy/waterway.h (+95/-0)
src/editor/ui_menus/main_menu_map_options.cc (+17/-0)
src/editor/ui_menus/main_menu_map_options.h (+2/-0)
src/editor/ui_menus/main_menu_save_map.cc (+5/-0)
src/game_io/game_player_economies_packet.cc (+11/-7)
src/graphic/CMakeLists.txt (+1/-0)
src/graphic/gl/fields_to_draw.cc (+4/-1)
src/graphic/gl/fields_to_draw.h (+3/-1)
src/graphic/gl/road_program.cc (+9/-11)
src/graphic/minimap_renderer.cc (+2/-2)
src/logic/CMakeLists.txt (+1/-0)
src/logic/cookie_priority_queue.h (+29/-22)
src/logic/editor_game_base.cc (+26/-16)
src/logic/editor_game_base.h (+3/-1)
src/logic/field.h (+33/-12)
src/logic/game.cc (+17/-8)
src/logic/game.h (+1/-0)
src/logic/map.cc (+24/-8)
src/logic/map.h (+7/-1)
src/logic/map_objects/CMakeLists.txt (+2/-0)
src/logic/map_objects/checkstep.cc (+55/-0)
src/logic/map_objects/checkstep.h (+18/-0)
src/logic/map_objects/findnode.cc (+3/-1)
src/logic/map_objects/findnode.h (+1/-0)
src/logic/map_objects/immovable.cc (+12/-9)
src/logic/map_objects/immovable.h (+7/-6)
src/logic/map_objects/map_object.cc (+10/-2)
src/logic/map_objects/map_object.h (+11/-5)
src/logic/map_objects/tribes/building.cc (+25/-1)
src/logic/map_objects/tribes/building.h (+6/-0)
src/logic/map_objects/tribes/carrier.cc (+50/-35)
src/logic/map_objects/tribes/carrier.h (+4/-1)
src/logic/map_objects/tribes/ferry.cc (+321/-0)
src/logic/map_objects/tribes/ferry.h (+109/-0)
src/logic/map_objects/tribes/militarysite.cc (+4/-4)
src/logic/map_objects/tribes/militarysite.h (+1/-1)
src/logic/map_objects/tribes/partially_finished_building.cc (+10/-7)
src/logic/map_objects/tribes/partially_finished_building.h (+1/-1)
src/logic/map_objects/tribes/production_program.cc (+8/-17)
src/logic/map_objects/tribes/productionsite.cc (+18/-9)
src/logic/map_objects/tribes/productionsite.h (+1/-1)
src/logic/map_objects/tribes/road_textures.cc (+8/-0)
src/logic/map_objects/tribes/road_textures.h (+3/-0)
src/logic/map_objects/tribes/ship.cc (+49/-29)
src/logic/map_objects/tribes/ship.h (+14/-11)
src/logic/map_objects/tribes/trainingsite.cc (+3/-3)
src/logic/map_objects/tribes/trainingsite.h (+1/-1)
src/logic/map_objects/tribes/tribe_descr.cc (+14/-0)
src/logic/map_objects/tribes/tribe_descr.h (+8/-3)
src/logic/map_objects/tribes/tribes.cc (+10/-0)
src/logic/map_objects/tribes/tribes.h (+4/-0)
src/logic/map_objects/tribes/warehouse.cc (+82/-47)
src/logic/map_objects/tribes/warehouse.h (+1/-1)
src/logic/map_objects/tribes/worker.cc (+87/-45)
src/logic/map_objects/tribes/worker.h (+10/-6)
src/logic/map_objects/tribes/worker_program.cc (+25/-1)
src/logic/map_objects/tribes/worker_program.h (+1/-0)
src/logic/mapastar.h (+5/-3)
src/logic/pathfield.h (+5/-4)
src/logic/player.cc (+91/-27)
src/logic/player.h (+23/-10)
src/logic/playercommand.cc (+101/-23)
src/logic/playercommand.h (+29/-4)
src/logic/queue_cmd_factory.cc (+2/-0)
src/logic/queue_cmd_ids.h (+2/-1)
src/logic/roadtype.h (+6/-15)
src/map_io/CMakeLists.txt (+4/-0)
src/map_io/map_buildingdata_packet.cc (+4/-2)
src/map_io/map_flag_packet.cc (+15/-8)
src/map_io/map_object_packet.cc (+8/-3)
src/map_io/map_object_saver.cc (+12/-4)
src/map_io/map_object_saver.h (+6/-1)
src/map_io/map_players_view_packet.cc (+14/-19)
src/map_io/map_port_spaces_packet.cc (+4/-1)
src/map_io/map_roaddata_packet.cc (+7/-10)
src/map_io/map_saver.cc (+18/-0)
src/map_io/map_waterway_packet.cc (+96/-0)
src/map_io/map_waterway_packet.h (+27/-0)
src/map_io/map_waterwaydata_packet.cc (+198/-0)
src/map_io/map_waterwaydata_packet.h (+31/-0)
src/map_io/widelands_map_loader.cc (+16/-0)
src/scripting/lua_bases.cc (+4/-2)
src/scripting/lua_map.cc (+174/-148)
src/scripting/lua_map.h (+13/-9)
src/scripting/lua_root.cc (+24/-0)
src/scripting/lua_root.h (+1/-0)
src/ui_basic/spinbox.cc (+3/-0)
src/ui_basic/spinbox.h (+1/-1)
src/ui_fsmenu/internet_lobby.cc (+6/-6)
src/ui_fsmenu/mapselect.cc (+2/-1)
src/wui/building_statistics_menu.cc (+8/-5)
src/wui/building_statistics_menu.h (+2/-1)
src/wui/economy_options_window.cc (+38/-30)
src/wui/economy_options_window.h (+9/-4)
src/wui/fieldaction.cc (+163/-50)
src/wui/interactive_base.cc (+260/-20)
src/wui/interactive_base.h (+31/-16)
src/wui/interactive_player.cc (+60/-10)
src/wui/interactive_spectator.cc (+2/-0)
src/wui/map_tags.cc (+2/-0)
src/wui/seafaring_statistics_menu.cc (+1/-1)
src/wui/stock_menu.cc (+8/-5)
src/wui/transport_draw.cc (+2/-2)
test/maps/lua_testsuite.wmf/scripting/flag.lua (+2/-1)
test/maps/lua_testsuite.wmf/scripting/geconomy.lua (+14/-14)
test/maps/lua_testsuite.wmf/scripting/tribes_descriptions.lua (+6/-6)
test/maps/ship_transportation.wmf/scripting/test_rip_portdock_with_worker_and_ware_in_transit.lua (+4/-2)
test/maps/ship_transportation.wmf/scripting/test_rip_ports_with_ware_in_transit.lua (+4/-2)
test/maps/ship_transportation.wmf/scripting/test_rip_ports_with_worker_in_transit.lua (+4/-2)
To merge this branch: bzr merge lp:~widelands-dev/widelands/ferry
Reviewer Review Type Date Requested Status
Klaus Halfmann testplay Needs Fixing on 2019-05-19
kaputtnik testing 2018-07-31 Approve on 2019-04-14
Review via email: mp+351880@code.launchpad.net

Description of the change

This is a feature for post-build20 of course, but it´s ready for (review and) testing now. It´ll need very extensive testing anyway due to the great economy engine changes.

Ferries are a special kind of carrier that works on waterways and can transport only a ware, no workers. Waterways are built like roads.
I pulled out common code for Roads and Waterways into a base class RoadBase.
Ferries are distributed to waterways by fleets. They are built in a ferry yard by a shipwright (build costs still need discussion).

I solved the big problem of having separate road networks connected only by ferries with an overhaul of the entire economy concept. Each PlayerImmovable, Worker etc now has one Economy for wares and one for workers. They are completely independent of each other. This change breaks saveloding compatibility.
The AI works fine (though it is completely unaware of the existence of ferries and waterways), but someone should check the changed code parts nonetheless. I added some TODOs in the places I touched.

Ferries are enabled only for maps in which the key waterway_max_length is set to >= 2 in the port_spaces packet. There´s no GUI yet; defaults to 0 (= disabled).

To post a comment you must log in.
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3740. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/410375646.
Appveyor build 3540. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3540.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3745. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/410977319.
Appveyor build 3545. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3545.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3747. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/411195871.
Appveyor build 3547. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3547.

Teppo Mäenpää (kxq) wrote :

I get a compiler error on 8780:

../src/logic/map_objects/tribes/ferry.cc: In member function ‘void Widelands::Ferry::start_task_row(Widelands::Game&, Widelands::Waterway*)’:
../src/logic/map_objects/tribes/ferry.cc:106:17: error: invalid conversion from ‘const value_type*’ {aka ‘const Widelands::Coords*’} to ‘Widelands::Coords*’ [-fpermissive]
  destination_ = &(CoordPath(game.map(), ww->get_path()).get_coords()[ww->get_idle_index()]);

Benedikt Straub (nordfriese) wrote :

Thanks for reporting, hopefully fixed now. I can´t compile at the moment, so I don´t notice such errors until someone complains ;)
I very much hope I didn´t break the successes from 8777 with this…

Teppo Mäenpää (kxq) wrote :

Now I got it, thanks.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3756. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/412147917.
Appveyor build 3556. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3556.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3759. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/412376982.
Appveyor build 3559. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3559.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3772. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/415039555.
Appveyor build 3571. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3571.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3790. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/415596858.
Appveyor build 3589. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3589.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3801. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/416088423.
Appveyor build 3600. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3600.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3862. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/422757043.
Appveyor build 3660. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3660.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3874. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/423456112.
Appveyor build 3672. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3672.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3922. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/426400155.
Appveyor build 3720. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3720.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3938. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/427174251.
Appveyor build 3736. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-3736.

lp:~widelands-dev/widelands/ferry updated on 2018-11-21
8802. By Nordfriese on 2018-11-21

Fixed merge conflicts

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4260. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/458082330.
Appveyor build 4054. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4054.

lp:~widelands-dev/widelands/ferry updated on 2018-11-22
8803. By Nordfriese on 2018-11-22

Fixed ferry cancelling to row to destination

8804. By Nordfriese on 2018-11-22

Two economies connected only for wares but not for workers _have_ to be considered separate for both types

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4263. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/458376614.
Appveyor build 4057. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4057.

lp:~widelands-dev/widelands/ferry updated on 2018-11-22
8805. By Nordfriese on 2018-11-22

Seperated WareEconomy and WorkerEconomy

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4264. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/458580181.
Appveyor build 4058. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4058.

lp:~widelands-dev/widelands/ferry updated on 2018-11-23
8806. By Nordfriese on 2018-11-23

Fixed compiler errors

8807. By Nordfriese on 2018-11-23

It works./widelands !

8808. By Nordfriese on 2018-11-23

Nicer log output

8809. By Nordfriese on 2018-11-23

Removed a strange crash

8810. By Nordfriese on 2018-11-23

Finally fixed the economy bug

8811. By Nordfriese on 2018-11-23

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4277. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/458960300.
Appveyor build 4071. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4071.

lp:~widelands-dev/widelands/ferry updated on 2018-11-24
8812. By Nordfriese on 2018-11-24

Various fixes

8813. By Nordfriese on 2018-11-24

Fixed wares/workers in warehouses being counted twice

8814. By Nordfriese on 2018-11-24

Fixed crash on waterway cleanup

8815. By Nordfriese on 2018-11-24

Fixed crash on request rerouting

Benedikt Straub (nordfriese) wrote :

Hm... I´m found one remaining crash in this branch during loading a saved game. Sometimes it works, rarely it crashes directly after loading, and most time it crashes with a segfault while loading the waterwaydata packet. The strange thing is that the segfault always occurs in a different function. I have no idea how to debug this, any help would be appreciated...

lp:~widelands-dev/widelands/ferry updated on 2018-11-24
8816. By Nordfriese on 2018-11-24

Show ferry yards only on ferry maps

8817. By Nordfriese on 2018-11-24

Fixed codecheck warning

8818. By Nordfriese on 2018-11-24

Fixed compile error

TiborB (tiborb95) wrote :

I did not read the diff, but I wonder how are the two economies implemented.

A building or flag is a member of one or two economies?

As for segfault - are you using gdb to get backtrace? If this does not give enough clue than it is a problem..

Benedikt Straub (nordfriese) wrote :

Every building/flag/… belongs to two independent economies now. A PlayerImmovable now has the properties
    Economy* ware_economy_;
    Economy* worker_economy_;
instead of Economy* economy_;

Each Economy knows whether it is supposed to handle workers or wares (this is set when the economy is created). Low-level stuff like Requests and Supplies (and also WareInstance) belong to only one economy that matches their WareWorker type.
Exception: Workers also have two economies, because they themselves are handled by a worker economy, but they can also create wares which have to be added to a ware economy of course.

When a ware/worker or Request/Supply is added/removed to/from an economy, it is ensured that it is registered only in the Economy of the appropriate WareWorker type. When flags get connected, only economies of the same type can merge.

Most of the time (and if you don´t build waterways, always), the Ware Economy and the Worker Economy of any PlayerImmovable or Worker will encompass exactly the same PlayerImmovables. Only when you connect two separate road networks with a waterway, there will be one Ware Economy (for the whole network) and two Worker Economies (one for each road system).

Waterways and employed ferries always belongs to a Ware Economy. Since workers cannot cross a waterway and ferries can´t walk over land, the Worker Economies of WWs and Ferries are not well-defined.
For unemployed ferries, both Economies are not well-defined, because their (pseudo-)"requests" are handled by Fleets, and a Fleet can serve completely unconnected waterways.

I used gdb to analyse the crashes. Eight crashes produced eight backtraces that point to eight different functions, usually in Waterway, Ferry or Fleet. They seem completely random, except that the crash always happens at some time while loading the waterwaydata_packet. I also added lots of log output after every step in the called functions, but it segfaulted at always different seemingly random points…

lp:~widelands-dev/widelands/ferry updated on 2018-11-25
8819. By Nordfriese on 2018-11-25

Merged trunk

8820. By Nordfriese on 2018-11-25

Fixed a typo

Benedikt Straub (nordfriese) wrote :

Just discovered a couple of failing asserts. Perhaps debugging these will give me a hint to the nature of the crash...

lp:~widelands-dev/widelands/ferry updated on 2018-11-25
8821. By Nordfriese on 2018-11-25

Fixed a failing assert and a segfault in end-of-game cleanup

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4291. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/459456832.
Appveyor build 4085. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4085.

GunChleoc (gunchleoc) wrote :

I can see the Ferry Yard in the encyclopedia but i'm not allowed to build one, so I have no idea how to help with debugging, because I can't test. Can you add instructions and/or a savegame to the bug?

Benedikt Straub (nordfriese) wrote :

You can only build ferry yards on maps with waterways enabled. You need to edit the map´s "port_spaces" packet and add the key "waterway_max_length" (with a value >= 2) to the global section.
(Saving a map in the editor from this branch adds the key, but it defaults to 0; there is no GUI to change it yet.)

lp:~widelands-dev/widelands/ferry updated on 2018-11-29
8822. By Nordfriese on 2018-11-26

One Economy doesn´t need two types of split checks...

8823. By Nordfriese on 2018-11-26

More debug output

8824. By Nordfriese on 2018-11-26

Merged trunk

8825. By Nordfriese on 2018-11-28

Fixing a bug in the pathfinding

8826. By Nordfriese on 2018-11-28

Fixing the testsuite

8827. By Nordfriese on 2018-11-28

Fixed compile error

8828. By Nordfriese on 2018-11-29

Fixed segfault when loading waterway

Benedikt Straub (nordfriese) wrote :

The crash is fixed now!
It took me several days to discover the reason. The change is one line...

lp:~widelands-dev/widelands/ferry updated on 2018-11-29
8829. By Nordfriese on 2018-11-29

Do not balance expedition economies

8830. By Nordfriese on 2018-11-29

Fixing the test suite…

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4309. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/461328014.
Appveyor build 4103. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4103.

lp:~widelands-dev/widelands/ferry updated on 2018-11-29
8831. By Nordfriese on 2018-11-29

Silence gcc complaint

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4311. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/461462714.
Appveyor build 4105. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4105.

lp:~widelands-dev/widelands/ferry updated on 2018-12-02
8832. By Nordfriese on 2018-11-30

Add map tag »ferries«

8833. By Nordfriese on 2018-12-02

Fixing a bug with roadbuilding overlays. Removed RoadInfo again.

8834. By Nordfriese on 2018-12-02

Compiler error

8835. By Nordfriese on 2018-12-02

Overlooked a corner case for roadbuilding

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4316. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/462452641.
Appveyor build 4111. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4111.

lp:~widelands-dev/widelands/ferry updated on 2018-12-02
8836. By Nordfriese on 2018-12-02

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4317. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/462525707.
Appveyor build 4112. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4112.

lp:~widelands-dev/widelands/ferry updated on 2019-03-08
8837. By Nordfriese on 2019-02-27

merged trunk

8838. By Nordfriese on 2019-03-08

Documentation fix

8839. By Nordfriese on 2019-03-08

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4569. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/503691873.
Appveyor build 4356. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4356.

lp:~widelands-dev/widelands/ferry updated on 2019-03-12
8840. By Nordfriese on 2019-03-12

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4592. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/505198456.
Appveyor build 4356. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4356.

lp:~widelands-dev/widelands/ferry updated on 2019-03-19
8841. By Nordfriese on 2019-03-19

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4616. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/508307520.
Appveyor build 4403. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4403.

GunChleoc (gunchleoc) wrote :

Barbarian Ferry Yard needs cloth to build, but there is no Weaving Mill, because that building needs seafaring.

It would be nice to have some indicators for the range when building a new waterway - I think we best wait with that until after we have the new work areas, because there could be some common code there. It would also be nice to have visual indicators for established waterways as an overlay.

Can you please remove the ferry animations except for the first frame each? They cause the diff to be truncated, because there are so many of them. Since they are just placeholders, 1 frame should be good enough for visual quality.

Code review of the bits that I can see is done.

lp:~widelands-dev/widelands/ferry updated on 2019-03-23
8842. By Nordfriese on 2019-03-23

Removed ferry animations

8843. By Nordfriese on 2019-03-23

Merged trunk

8844. By Nordfriese on 2019-03-23

Adressed first code review

8845. By Nordfriese on 2019-03-23

Changed buildcost for barbarian ferry yard

8846. By Nordfriese on 2019-03-23

Deleted some more images

8847. By Nordfriese on 2019-03-23

Stronger waterway textures

Benedikt Straub (nordfriese) wrote :

Removed the duplicate code and the superfluous animation frames, downscaled the remaining images.
The barbarian ferry yard now uses reed instead of cloth.
The textures for built waterways are now better visible.

I agree about the range indicators. That will be easy to implement, but I´ll wait with that until the workareas branch is merged.

lp:~widelands-dev/widelands/ferry updated on 2019-03-24
8848. By Nordfriese on 2019-03-23

Fixed codecheck

8849. By Nordfriese on 2019-03-23

Quickfix for startup error

8850. By Nordfriese on 2019-03-24

Merged trunk

8851. By GunChleoc on 2019-03-24

Code review.

GunChleoc (gunchleoc) wrote :

The overlays look fine now, thank you.

I have pushed a commit with a code review. Check the "NOCOM" comments.

Some notes that are not in the review commit:

- Ferry yard needs an economy check, just like the Ox Farm etc. Otherwise, it will just keep producing en masse.

- switch is faster than if/else, so use that for distinguishing ware/worker cases if it keeps the code still readable

- And ASan is not happy. I built a ferry yard, then a waterway. Connected a construction site with a separate flag to the other end of the waterway and waited a bit. Only then did I connect the worker economy -> boom

TI(2857): destination appears to have become split from current location -> fail
=================================================================
==32501==ERROR: AddressSanitizer: heap-use-after-free on address 0x61100075fb38 at pc 0x55b7a7a1a6e7 bp 0x7ffcd58678f0 sp 0x7ffcd58678e0
READ of size 8 at 0x61100075fb38 thread T0
    #0 0x55b7a7a1a6e6 in __gnu_cxx::__normal_iterator<Widelands::Ferry**, std::vector<Widelands::Ferry*, std::allocator<Widelands::Ferry*> > >::__normal_iterator(Widelands::Ferry** const&) /usr/include/c++/7/bits/stl_iterator.h:780
    #1 0x55b7a7a127c5 in std::vector<Widelands::Ferry*, std::allocator<Widelands::Ferry*> >::begin() /usr/include/c++/7/bits/stl_vector.h:564
    #2 0x55b7a7a079d2 in Widelands::Fleet::cancel_ferry_request(Widelands::Game&, Widelands::Waterway*) ../src/economy/fleet.cc:533
    #3 0x55b7a7a5b870 in Widelands::Waterway::cleanup(Widelands::EditorGameBase&) ../src/economy/waterway.cc:227
    #4 0x55b7a7084ea7 in Widelands::MapObject::remove(Widelands::EditorGameBase&) ../src/logic/map_objects/map_object.cc:434
    #5 0x55b7a7081626 in Widelands::ObjectManager::cleanup(Widelands::EditorGameBase&) ../src/logic/map_objects/map_object.cc:162
    #6 0x55b7a6ccb2d7 in Widelands::EditorGameBase::cleanup_objects() ../src/logic/editor_game_base.h:170
    #7 0x55b7a6f6dd40 in Widelands::Game::run(UI::ProgressWindow*, Widelands::Game::StartGameType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ../src/logic/game.cc:554
    #8 0x55b7a6c6cef0 in WLApplication::new_game() ../src/wlapplication.cc:1320
    #9 0x55b7a6c6b29c in WLApplication::mainmenu_singleplayer() ../src/wlapplication.cc:1177
    #10 0x55b7a6c6a3d3 in WLApplication::mainmenu() ../src/wlapplication.cc:1082
    #11 0x55b7a6c61699 in WLApplication::run() ../src/wlapplication.cc:454
    #12 0x55b7a6c5dbee in main ../src/main.cc:44
    #13 0x7f0401bfbb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #14 0x55b7a6c5da69 in _start (/media/cuideigin/Linux/sources/widelands/ferry/widelands+0xd94a69)

lp:~widelands-dev/widelands/ferry updated on 2019-03-24
8852. By Nordfriese on 2019-03-24

Started to adress code review

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4638. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/510643337.
Appveyor build 4425. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4425.

lp:~widelands-dev/widelands/ferry updated on 2019-03-25
8853. By Nordfriese on 2019-03-25

Fixed request creation for simultanously created waterways

Benedikt Straub (nordfriese) wrote :

Implemented or replied to your diff comments in revision 8852.
I can´t reproduce the ASan complaint you reported anymore, but I fixed several others that surfaced now, except for one on game-end that will follow soon.

Regarding the ferry target quantity: IMHO the ferry yards work like shipyards, which also produce until the player stops them manually. A target quantity would be especially difficult if the ferry yard is close two several oceans.

Some of the waterway code which you annotated is copied 1:1 from road code. Should I therefore leave it as it is, or change both the new waterway code and the original road code?

And saveloading – I don´t think it is really possible to preserve compatibility here, see my comment in MapFlagPacket…

GunChleoc (gunchleoc) wrote :

I did not think of the several oceans problem.

I think it would be good if you could fix both the new and the original road code. This branch is huge anyway, so I don't mind having more changes in it.

I can look into the saveloading if you want. Just leave the annotations in until everything else has been finalized and I'll have a look if I can make it work.

lp:~widelands-dev/widelands/ferry updated on 2019-03-26
8854. By Nordfriese on 2019-03-25

Implemented remaining diff comments and fixed a crash

8855. By Nordfriese on 2019-03-25

Merged trunk

8856. By Nordfriese on 2019-03-26

Make travis happy

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4653. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/511594641.
Appveyor build 4440. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4440.

lp:~widelands-dev/widelands/ferry updated on 2019-04-07
8857. By Nordfriese on 2019-04-04

Merged trunk

8858. By Nordfriese on 2019-04-04

Fixed loadgame bug

8859. By Nordfriese on 2019-04-07

Improved ferry movement rules and cleaned up economy code

8860. By Nordfriese on 2019-04-07

Fixed bug in ferry assignment on waterway split

8861. By Nordfriese on 2019-04-07

Trigger economy balance when corresponding economy receives wares/workers

Benedikt Straub (nordfriese) wrote :

Uploaded the changes discussed in the bug report.
Ferries can now travel along any edge where both adjacent triangles are navigable terrain.
I cleaned up the economy code, removed lots of duplicate functionality for wares and workers, and fixed a bug in worker creation.

If you have two road networks connected only by waterways, and economy A requests a fisherman but all fishing nets are in economy B, nothing will happen. This is intentional because it mirrors the behaviour when a needed worker requires two tools which are in different warehouses. Newly produced fishing nets will be distributed to warehouses independent of such requests. Micromanaging is needed to get a fishing net from B to A, then it´ll be used to create a fisher as soon as it arrives there.

lp:~widelands-dev/widelands/ferry updated on 2019-04-07
8862. By Nordfriese on 2019-04-07

Undid accidental change

8863. By Nordfriese on 2019-04-07

Renamed duplicate StepEvalFindFleet

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4682. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/516878831.
Appveyor build 4468. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4468.

Benedikt Straub (nordfriese) wrote :

Can´t reply this in the bug report for some reason…:

Let W and E be the end flags of the waterway that has a ferry.
– Destroy both waterways.
– Build a waterway from W to a new flag F on the tiny island south of the warehouse. It´ll get the ferry that used to service the waterway from W to E.
– Build a waterway from F to E. It´ll get a new ferry.
– Now rebuild the other waterway – and it´ll also get a new ferry.

I´m no closer to finding the source of the problem yet though. I suspect the underlying reason may be related to the pathfinder…

lp:~widelands-dev/widelands/ferry updated on 2019-04-08
8864. By Nordfriese on 2019-04-08

Small cleanup and better debug info

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4696. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/517213969.
Appveyor build 4482. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4482.

lp:~widelands-dev/widelands/ferry updated on 2019-04-13
8865. By Nordfriese on 2019-04-09

Fixing the test suite

8866. By Nordfriese on 2019-04-09

Fixed duplication of fleets during loading

8867. By Nordfriese on 2019-04-13

fixed bug 1824586

kaputtnik (franku) wrote :

This is really a nice feature. Played two games (Map Twinkling Waves and The Nile) a lot but found no strange issues anymore. There is one small thing:

If you have the option 'Start building road after placing a flag' turned on, and place a flag at a coast, roadbuilding mode is immediately enabled. So if you wanted to start building a waterway, you have to make few more clicks to get into 'build waterway' mode (cancel roadbuilding -> click on flag -> click on build waterway).

No idea how to solve this in an easy manner. Just show the flag action window is a flag is placed where also a waterway can be build, regardless of the option 'Start building road after placing a flag'?

review: Approve (testing)
lp:~widelands-dev/widelands/ferry updated on 2019-04-14
8868. By Nordfriese on 2019-04-14

merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4720. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/520014396.
Appveyor build 4506. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4506.

GunChleoc (gunchleoc) wrote :

Or maybe the 2 functions could be the same thing, with Widelands detecting automatically whether it will become a road or a waterway?

Benedikt Straub (nordfriese) wrote :

Autodetection is not possible because there are paths where you can build both.
Having one mode for both where you get to choose on finish whether you want a road or waterway is possible but difficult to implement because of different placement rules.
+1 for showing the flagaction window instead of entering roadbuilding mode after placing a flag where both can be built if the option is enabled. Will implement this next week.

GunChleoc (gunchleoc) wrote :

Sounds like a plan :)

lp:~widelands-dev/widelands/ferry updated on 2019-04-19
8869. By Nordfriese on 2019-04-19

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4742. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/522276339.
Appveyor build 4527. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4527.

lp:~widelands-dev/widelands/ferry updated on 2019-04-20
8870. By Nordfriese on 2019-04-20

Fixing the testsuite

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4752. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/522535128.
Appveyor build 4537. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4537.

lp:~widelands-dev/widelands/ferry updated on 2019-04-22
8871. By Nordfriese on 2019-04-22

Open fieldaction instead of starting roadbuilding if waterway can be built

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4759. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/523086402.
Appveyor build 4543. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4543.

Benedikt Straub (nordfriese) wrote :

New behaviour is implemented and tested.
@GunChleoc Could you please re-review the latest changes in economy.cc, especially create_requested_worker(), and CheckStepFerry?

lp:~widelands-dev/widelands/ferry updated on 2019-04-29
8872. By Nordfriese on 2019-04-29

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4836. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/526029169.
Appveyor build 4617. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4617.

Klaus Halfmann (klaus-halfmann) wrote :

OK this is a little Monster and in depends on some workarea change?
Please direkt me to that branch or was this mereged by now?

Im checking this out now. and (try to) do some code review.

Klaus Halfmann (klaus-halfmann) wrote :

CLang gives me some comppiler warnings:

src/economy/economy.cc:854:45: warning: loop variable 'r' has type
    'const std::pair<Request *, uint32_t> &'
    (aka 'const pair<Widelands::Request *, unsigned int> &')
but is initialized with type 'std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::__value_type<Widelands::Request *, unsigned int>, std::__1::__tree_node<std::__1::__value_type<Widelands::Request *, unsigned int>, void *> *, long> >::value_type'
(aka 'pair<Widelands::Request *const, unsigned int>')
resulting in a copy [-Wrange-loop-analysis]
          for (const std::pair<Request*, uint32_t>& r : open_requests) {
                                                          ^
../src/economy/economy.cc:854:8: note: use non-reference type 'std::pair<Request *, uint32_t>' (aka 'pair<Widelands::Request *, unsigned int>') to keep the copy or type 'const std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::__value_type<Widelands::Request *, unsigned int>, std::__1::__tree_node<std::__1::__value_type<Widelands::Request *, unsigned int>, void *> *, long> >::value_type &'
(aka 'const pair<Widelands::Request *const, unsigned int> &') to prevent copying
                for (const std::pair<Request*, uint32_t>& r : open_requests)

I think you need more const inside the declaration of r?

/src/wui/economy_options_window.cc:20:
../src/wui/economy_options_window.h:56:25: warning: private field 'type_' is not used
[-Wunused-private-field] Widelands::WareWorker type_;

You should see them in the automated builds, too

lp:~widelands-dev/widelands/ferry updated on 2019-05-01
8873. By Nordfriese on 2019-05-01

Removed some unused variables

Benedikt Straub (nordfriese) wrote :

The automated builds only warn about some unused variables which I now removed. I don´t see the warning in economy.cc either there or when compiling myself…

Klaus Halfmann (klaus-halfmann) wrote :

Plaaying Calvission for a while now:

In case a location is reachabel by road and by waterway, but there is no ferry,
wares may get stuck waiting at the flag for the waterway, mmh. But well, works as designed.

Klaus Halfmann (klaus-halfmann) wrote :

The ccode is basiccally OK, I did not read all of it, sorry.

I noticed some odd Behavior that carrriees tried to use a wterway to reach theire destination,
but got stuck on the waterway. This way neither wares no carriers where transported in the end.

I think we cann still merge this one (nice work Benedikt!) and create Bugtickets later.

I got a saveagme and some movie showing the Problem.

review: Approve (compile, review, testplay)
Benedikt Straub (nordfriese) wrote :

> I noticed some odd Behavior that carriers tried to use a waterway to reach their destination,
but got stuck on the waterway. This way neither wares no carriers where transported in the end.

That sounds like a fairly serious bug. Could you upload the savegame to the bugreport linked to this branch please?

lp:~widelands-dev/widelands/ferry updated on 2019-05-01
8874. By Nordfriese on 2019-05-01

Fixed workers walking on waterways

Benedikt Straub (nordfriese) wrote :

Thanks for the video, bug should be fixed. I had overlooked the possibility that two flags can be connected by a road and a waterway.

Klaus Halfmann (klaus-halfmann) wrote :

I now get a compile Error at:

../src/economy/transfer.cc:166:72: error: non-pointer operand type 'Widelands::MapObjectType' incompatible with nullptr
                if (!curflag.get_roadbase(nextflag, request_->get_type() == wwWORKER ? MapObjectType::ROAD : nullptr)) {
                                                                                     ^ ~~~~~~~~~~~~~~~~~~~
../src/economy/transfer.cc:184:78: error: non-pointer operand type 'Widelands::MapObjectType' incompatible with nullptr
                        if (!nextflag.get_roadbase(nextnextflag, request_->get_type() == wwWORKER ? MapObjectType::ROAD : nullptr)) {

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4849. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/526968452.
Appveyor build 4630. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4630.

lp:~widelands-dev/widelands/ferry updated on 2019-05-02
8875. By Nordfriese on 2019-05-02

Compile error

8876. By Nordfriese on 2019-05-02

Compile error

Klaus Halfmann (klaus-halfmann) wrote :

Loading may savegame I now get:

Assertion failed: (wh), function get_next_step, file ../src/economy/transfer.cc, line 188.

Do I have to restart that Map now?

Benedikt Straub (nordfriese) wrote :

The worker already is in an impossible situation, so you need to load an older savegame that doesn´t contain the bug yet.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4855. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/527387898.
Appveyor build 4636. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4636.

GunChleoc (gunchleoc) wrote :

Fieldaction code looks OK.

How about passing wwWORKER/wwWARE to get_roadbase and checking for that there? Then you could just call get_roadbase as in your original attempt in r8874.

lp:~widelands-dev/widelands/ferry updated on 2019-05-03
8877. By Nordfriese on 2019-05-03

Errors in some cases

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4865. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/527627946.
Appveyor build 4646. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4646.

Klaus Halfmann (klaus-halfmann) wrote :

Played Calvission a #1 with a Barbarian at #2 , Imperial at #3 and Frisisan at #4

Got an assert aftree trying to build two woodcutters:

Forcing flag at (70, 164)
Message: adding warehouse for player 1 at (69, 163)
Forcing flag at (73, 163)
Forcing flag at (66, 165)
Forcing flag at (65, 169)
Forcing flag at (157, 27)
Message: adding warehouse for player 2 at (157, 26)
Forcing flag at (168, 141)
Message: adding warehouse for player 3 at (168, 140)
Forcing flag at (56, 45)
Message: adding warehouse for player 4 at (56, 44)
InternetGaming: Received a client list update with 18 items.
InternetGaming: Received a game list update with 1 items.
Assertion failed: (wh), function get_next_step, file ../src/economy/transfer.cc, line 186.
Abort trap: 6

....

4 widelands 0x00000001049b4f48 Widelands::Transfer::get_next_step(Widelands::PlayerImmovable*, bool&) + 3320 (transfer.cc:186)
5 widelands 0x00000001049bc711 Widelands::WareInstance::update(Widelands::Game&) + 1841 (ware_instance.cc:330)
6 widelands 0x00000001048f73f4 Widelands::Flag::add_ware(Widelands::EditorGameBase&, Widelands::WareInstance&) + 1524 (flag.cc:462)
7 widelands 0x0000000102f0cbfd Widelands::Worker::dropoff_update(Widelands::Game&, Widelands::Bob::State&) + 2381 (worker.cc:2123)
8 widelands 0x0000000102abc710 Widelands::Bob::do_act(Widelands::Game&) + 704 (bob.cc:195)

Do you need a savegame?

review: Needs Fixing
Benedikt Straub (nordfriese) wrote :

This one function with this one assert yet again... yes, please provide a savegame

Klaus Halfmann (klaus-halfmann) wrote :

Here is the SaveGame: https://www.magentacloud.de/share/tu4ayusx.k

Ferries2.wgf (Multiplayer Game)

lp:~widelands-dev/widelands/ferry updated on 2019-05-16
8878. By Nordfriese on 2019-05-16

Some transfer confusion

Benedikt Straub (nordfriese) wrote :

Thanks for the savegame :)
There were three different bugs overlayed here. All of them are fixed now.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5000. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/533393374.
Appveyor build 4781. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4781.

Klaus Halfmann (klaus-halfmann) wrote :

I played Calvission again fo about 4 hours gametime.
This was fine for the most parts, I found some of
the expected Issued: e.g. Buildings not attachted to roads dont get workers.
I found one Issue where ferries are not built.
But now I hit an seertion that should be reproducible, please check:
   https://www.magentacloud.de/share/tu4ayusx.k
   Unferry.wgf

If we really want this feature, we should get it in _now_ and fix such bugs
with seperate bugs. Otherwsie this Brnach will diverge more and more.

Lets get this decided soon.

review: Needs Fixing (testplay)
Benedikt Straub (nordfriese) wrote :

That assert is in trunk – it´s our famous Fleet::is_path_favourable problem...

A reason this is not being merged yet is, GunChleoc wanted to check if we can merge this without breaking savegame compatibility (I think it´s not possible).
I agree that apart from that this branch should be merged soon, and any not-yet-found bugs reported then on trunk.

Will merge trunk soon to fix the diverging

lp:~widelands-dev/widelands/ferry updated on 2019-05-23
8879. By Nordfriese on 2019-05-23

Merged trunk

GunChleoc (gunchleoc) wrote :

We are merging a lot of branches today, so maybe do the merging tomorrow and ping me so I'll take over and have a look?

lp:~widelands-dev/widelands/ferry updated on 2019-05-28
8880. By Nordfriese on 2019-05-26

Merged trunk

8881. By Nordfriese on 2019-05-28

Corrected thatch_reed → reed

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5075. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/538201201.
Appveyor build 4855. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4855.

lp:~widelands-dev/widelands/ferry updated on 2019-05-28
8882. By Nordfriese on 2019-05-28

Codecheck complains

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5077. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/538358799.
Appveyor build 4857. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4857.

lp:~widelands-dev/widelands/ferry updated on 2019-05-31
8883. By Nordfriese on 2019-05-31

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5106. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/539673312.
Appveyor build 4887. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4887.

Klaus Halfmann (klaus-halfmann) wrote :

Now, how do we get progress here?
Will try to play this again on Cavisson

GunChleoc (gunchleoc) wrote :

I'll need to set aside a weekend for this, so it can take some time until I get around to it.

TiborB (tiborb95) wrote :

I added some question in the diff

TiborB (tiborb95) wrote :

AI uses send_player_build_road() to build roads, I tried to find something like send_player_build_waterway() but nothing like this exists, correct?

Also, does particular fields have some MOVECAPS, like for roads:
f->nodecaps() & MOVECAPS_WALK

Benedikt Straub (nordfriese) wrote :

There is a method Game::send_player_build_waterway(int32_t, Path&) that works just like for roads.

Waterways have a special placement rule: They can go along any edge which is located between two water triangles. They can therefore reach all fields with MOVECAPS_SWIM plus some other fields. Always use a CheckStepFerry when checking ferry or waterway paths.

TiborB (tiborb95) wrote :

I cannot see that method in the diff, so it is probably something older, but fine...

AI will need to use CheckStepFerry or whatever to get list of all fields from which regular road can lead, I will investigate it...

Please look at this code: https://bazaar.launchpad.net/~widelands-dev/widelands/trunk/view/head:/src/ai/defaultai.cc#L3849

It would be convenient if equivalent of this was possible for waterroads, what do you think?

I still would like to have MOVECAPS_FERRY capability, so that AI would take random flag, and if it has this capability it would run map.find_reachable_fields() from this point to collect possible destinations for waterroads...

These are just few thougts for discussion...

TiborB (tiborb95) wrote :

Can ferries be transferred by ships? If not in some maps more then 1 ferryyard can be needed.

I had an impression that waterroads will work the same as normal roads, but now I see that quite a lot of management is needed for them...

Benedikt Straub (nordfriese) wrote :

Launchpad limits the diff preview to the first 5000 lines. The other >9000 lines remain hidden…

A MOVECAPS_FERRY is not possible. For MOVECAPS_WALK and MOVECAPS_SWIM, you always know that if two adjacent nodes both have this movecap, a bob that also has that movecap can pass directly from one node to the other. For ferries, it is possible that a waterway may pass both of two adjacent nodes, but it might not be allowed to go directly from the one to the other. They might even be in different oceans. Imagine e.g. situation with two lakes separated by a 1-tile-wide strip of land. If you want to check whether a spot is suited for waterways at all, always use CheckStepFerry::reachable_dest.

The equivalent of the function you linked is easily possible. Instead of plain CheckStepRoad, use this:
Widelands::CheckStepAnd cstep;
cstep.add(Widelands::CheckStepFerry(egbase()));
cstep.add(Widelands::CheckStepRoad(player, Widelands::MOVECAPS_SWIM | Widelands::MOVECAPS_WALK));

Also note that in lines like
if (dynamic_cast<const Road*>(map[reachable_coords].get_immovable())) {
Road should be replaces by RoadBase (the superclass of Road and Waterway).
Also keep in mind that waterways can transport only wares, no workers. The AI should build one between two flags only if they belong to the same worker economy, or if their respective worker economies both are "functional" (i.e. have a warehouse). Just so it doesn´t build a constructionsite on an unreachable shore – a road is still needed so a builder can come.

You need to build one ferry yard per Ferry Ocean, just as you need one shipyard per Ship Ocean. Ferries can use every path that is also suited for ships plus narrow channels where ships can´t pass, so a ferry ocean tends to encompass more places than a ship ocean. Ferries are implemented similar to ships, they´ll swim around idly until assigned to a waterway, then they swim to it autonomously.

And it´s not that much additional management that´s needed (less than e.g. for ports and ships), it only seems so because the concept is so different ;)

TiborB (tiborb95) wrote :

For ships the single ship is enough to attend all ports, with ferries it is the opposite, you need the same number of ferries as waterroads.

It would be convenient if AI can built "virtual roads" - from flag to flag, but if crossing the water this virtual road would break down into 3 roads - 2x actual roads and one waterroad. But this is more coding and bigger complexity....

TiborB (tiborb95) wrote :

Is there any function that returns number of ferries for a player or Fleet? Also I presume there is a way how to query the waterroad if it has a ferry...

Benedikt Straub (nordfriese) wrote :

To get all ferries in a fleet:
Waterway::get_fleet() or Ferry::get_fleet()
FerryFleet::count_ferries()
Counting stuff per player should not be needed, count per FerryFleet instead.
I´ll add some functions to query a waterway whether it has a ferry, and to query the fleet how many waterways are unemployed.
Btw, the FerryFleet does not keep a list of all waterways that belong to it. They are remembered only while they need a ferry; when they get one, the ferryfleet forgets that waterway.

lp:~widelands-dev/widelands/ferry updated on 2019-06-11
8884. By Nordfriese on 2019-06-11

Add some functions to query waterways and ferryfleets

TiborB (tiborb95) wrote :

And is there any link between ferryyard and a fleet?
Can I query the waterroad if if has a ferryyard to provide it with ferry?

Benedikt Straub (nordfriese) wrote :

No, because it can be close to several unconnected oceans, just like a shipyard.
You could keep a list of all ferry-reachable fields within the workarea of a ferry yard (*), and then check for a given waterway whether a CheckStepFerry-approved path exists from any node on the waterway to any of these fields.
(* this is actually an incorrect approximation in some corner cases but that shouldn´t matter normally)

TiborB (tiborb95) wrote :

AI currently is not able to cope with multiple oceans in the case of ships, just to remind this fact...

TiborB (tiborb95) wrote :

Another question is how can AI know if ferries are necessary. In case of ships - it builds shipyard and ports always - if there are portspaces. With ferries it can check if map has a water - but this is not sufficient check. Most maps have water, but will not need ferries at all.

So I see a lot of issues with implementing it in AI.

TiborB (tiborb95) wrote :

Also - another idea: It would be nice if the ferries were per economy and AI would know in advance if the waterroad will be supplied by a ferry immediately = if there is an available ferry. Without painfully calculating whatever.

The logic would be - AI is considering connecting flags A and B - no matter where they are.
If ferries are available - it can use pathfinding including waterroads, otherwise it falls back to current one.

But even this logic is stupid, because there will be non-critical sections where waterroads will be luxury and waste of precious material - but AI will not be able to distinguish such spots...

Benedikt Straub (nordfriese) wrote :

Whether waterways/ferries are enabled can be checked as
  map.get_waterway_max_length() >= 2
Typically, they are enabled only on maps where they make sense. Waterways have a maximum length that is map-dependent.
If two flags can be connected both by a new road and by a new waterway, the AI should build a waterway only if a road connection is much much longer. Building waterways if a road is also possible nearby makes sense in a handful of corner cases but not in the majority of cases.
Also, if there are two flags with the same ware economy but different worker economies, the AI should try very hard to connect them with a normal road if somehow possible.

> It would be nice if the ferries were per economy

Completely impossible, sorry. A ferry can be sent to any waterway that is in the same FerryFleet as itself – and there can be multiple economies adjacent to the same ocean (not to mention that each economy can be adjacent to multiple oceans). Per-economy distribution (or bookkeeping) of ferries is just not possible.

> and AI would know in advance if the waterroad will be supplied by a ferry immediately

You could either
– Build the waterway; some 10 seconds later query its fleet whether a ferry is coming, and if not, destroy the new waterway and remember not to retry for some time.
– Or if you really want to check before you build a waterway: Check out FerryFleet::find_other_fleet, and copy the pathfinding code from there to obtain the ferryfleet that belongs to the ocean you are interested in; then you can query that fleet for unoccupied ferries.

TiborB (tiborb95) wrote :

I am thinking a lot about this feature, but for AI it is relay difficult.

On most maps it will not be applicable and AI should be very cautious to use it at all.
It has complex logic for implementation.

So the conclusion is that it is not worth the effort to implement in AI.

What could be considered to make it more AI-friendly:

- to allow transfer of workers on ferries
- not to produce more ferries than needed
- allow transport of ferries over roads, or at least extend work radius of ferryyard significantly
- introduce WATERROAD_CAPS, and allow a waterroad between two such fields, or WALK_MOVECAPS and WATERROAD_CAPS. These WATERROAD_CAPS can be calculated and/or set by map creator (to restrict fields where waterroad can be built)
- not to route the wares over unattended waterroads (to avoid transportation blockages)

But I know that all of that violates your intentions for this branch, but an improvement in one of few of them would make AI implementation easier.

I will still keep thinking about this, because idea is interesting...

Unmerged revisions

8884. By Nordfriese on 2019-06-11

Add some functions to query waterways and ferryfleets

8883. By Nordfriese on 2019-05-31

Merged trunk

8882. By Nordfriese on 2019-05-28

Codecheck complains

8881. By Nordfriese on 2019-05-28

Corrected thatch_reed → reed

8880. By Nordfriese on 2019-05-26

Merged trunk

8879. By Nordfriese on 2019-05-23

Merged trunk

8878. By Nordfriese on 2019-05-16

Some transfer confusion

8877. By Nordfriese on 2019-05-03

Errors in some cases

8876. By Nordfriese on 2019-05-02

Compile error

8875. By Nordfriese on 2019-05-02

Compile error

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/campaigns/emp03.wmf/scripting/mission_thread.lua'
2--- data/campaigns/emp03.wmf/scripting/mission_thread.lua 2018-09-29 13:37:59 +0000
3+++ data/campaigns/emp03.wmf/scripting/mission_thread.lua 2019-06-11 08:19:26 +0000
4@@ -99,7 +99,7 @@
5 local objective = add_campaign_objective(obj_lower_marble_column_demand)
6
7 --- Check the headquarters' flag's economy
8- while sf.brn.immovable.economy:ware_target_quantity("marble_column") ~= 4 do
9+ while sf.brn.immovable.ware_economy:target_quantity("marble_column") ~= 4 do
10 sleep(2434)
11 end
12 sleep(4000)
13
14=== modified file 'data/campaigns/emp04.wmf/scripting/starting_conditions.lua'
15--- data/campaigns/emp04.wmf/scripting/starting_conditions.lua 2019-05-19 11:25:28 +0000
16+++ data/campaigns/emp04.wmf/scripting/starting_conditions.lua 2019-06-11 08:19:26 +0000
17@@ -20,7 +20,7 @@
18 r4 = p3:place_road(field_mill.immovable.flag, "br", "r", true)
19
20 p3:forbid_buildings("all")
21-field_warehouse.brn.immovable.economy:set_ware_target_quantity("beer", 180)
22+field_warehouse.brn.immovable.ware_economy:set_target_quantity("beer", 180)
23
24 -- =======================================================================
25 -- Player 1
26
27=== modified file 'data/campaigns/tutorial01_basic_control.wmf/scripting/mission_thread.lua'
28--- data/campaigns/tutorial01_basic_control.wmf/scripting/mission_thread.lua 2017-06-25 12:53:48 +0000
29+++ data/campaigns/tutorial01_basic_control.wmf/scripting/mission_thread.lua 2019-06-11 08:19:26 +0000
30@@ -219,7 +219,7 @@
31
32 -- Wait till the construction site is connected to the headquarters
33 sleep(20*1000)
34- while first_quarry_field.brn.immovable.debug_economy ~= sf.brn.immovable.debug_economy do
35+ while first_quarry_field.brn.immovable.debug_worker_economy ~= sf.brn.immovable.debug_worker_economy do
36 message_box_objective(plr,quarry_not_connected)
37 sleep(60*1000)
38 if not first_quarry_field.immovable then message_box_objective(plr,quarry_illegally_destroyed) return end
39@@ -258,7 +258,7 @@
40 while not cs do sleep(200) end
41
42 sleep(60*1000)
43- while second_quarry_field.brn.immovable.debug_economy ~= sf.brn.immovable.debug_economy do
44+ while second_quarry_field.brn.immovable.debug_worker_economy ~= sf.brn.immovable.debug_worker_economy do
45 message_box_objective(plr,quarry_not_connected)
46 sleep(60*1000)
47 if not second_quarry_field.immovable then message_box_objective(plr,quarry_illegally_destroyed) return end
48
49=== modified file 'data/campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua'
50--- data/campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua 2018-07-07 10:53:30 +0000
51+++ data/campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua 2019-06-11 08:19:26 +0000
52@@ -152,7 +152,7 @@
53 message_box_objective(plr, economy_settings2)
54 o = message_box_objective(plr, economy_settings3)
55
56- while sf.brn.immovable.economy:ware_target_quantity("marble_column") ~= 20 do
57+ while sf.brn.immovable.ware_economy:target_quantity("marble_column") ~= 20 do
58 sleep(200)
59 end
60 -- wait that the player has really changed the target quantity
61
62=== added file 'data/images/ui_basic/fsel_waterwaybuilding.png'
63Binary files data/images/ui_basic/fsel_waterwaybuilding.png 1970-01-01 00:00:00 +0000 and data/images/ui_basic/fsel_waterwaybuilding.png 2019-06-11 08:19:26 +0000 differ
64=== added file 'data/images/wui/fieldaction/menu_build_water.png'
65Binary files data/images/wui/fieldaction/menu_build_water.png 1970-01-01 00:00:00 +0000 and data/images/wui/fieldaction/menu_build_water.png 2019-06-11 08:19:26 +0000 differ
66=== added file 'data/images/wui/fieldaction/menu_rem_water.png'
67Binary files data/images/wui/fieldaction/menu_rem_water.png 1970-01-01 00:00:00 +0000 and data/images/wui/fieldaction/menu_rem_water.png 2019-06-11 08:19:26 +0000 differ
68=== added file 'data/images/wui/fieldaction/menu_tab_buildwaterway.png'
69Binary files data/images/wui/fieldaction/menu_tab_buildwaterway.png 1970-01-01 00:00:00 +0000 and data/images/wui/fieldaction/menu_tab_buildwaterway.png 2019-06-11 08:19:26 +0000 differ
70=== renamed file 'data/images/wui/overlays/roadb_green.png' => 'data/images/wui/overlays/road_building_green.png'
71=== renamed file 'data/images/wui/overlays/roadb_red.png' => 'data/images/wui/overlays/road_building_red.png'
72=== renamed file 'data/images/wui/overlays/roadb_reddown.png' => 'data/images/wui/overlays/road_building_reddown.png'
73=== renamed file 'data/images/wui/overlays/roadb_yellow.png' => 'data/images/wui/overlays/road_building_yellow.png'
74=== renamed file 'data/images/wui/overlays/roadb_yellowdown.png' => 'data/images/wui/overlays/road_building_yellowdown.png'
75=== added file 'data/images/wui/overlays/waterway_building_down.png'
76Binary files data/images/wui/overlays/waterway_building_down.png 1970-01-01 00:00:00 +0000 and data/images/wui/overlays/waterway_building_down.png 2019-06-11 08:19:26 +0000 differ
77=== added file 'data/images/wui/overlays/waterway_building_even.png'
78Binary files data/images/wui/overlays/waterway_building_even.png 1970-01-01 00:00:00 +0000 and data/images/wui/overlays/waterway_building_even.png 2019-06-11 08:19:26 +0000 differ
79=== added file 'data/images/wui/overlays/waterway_building_steepdown.png'
80Binary files data/images/wui/overlays/waterway_building_steepdown.png 1970-01-01 00:00:00 +0000 and data/images/wui/overlays/waterway_building_steepdown.png 2019-06-11 08:19:26 +0000 differ
81=== added file 'data/images/wui/overlays/waterway_building_steepup.png'
82Binary files data/images/wui/overlays/waterway_building_steepup.png 1970-01-01 00:00:00 +0000 and data/images/wui/overlays/waterway_building_steepup.png 2019-06-11 08:19:26 +0000 differ
83=== added file 'data/images/wui/overlays/waterway_building_up.png'
84Binary files data/images/wui/overlays/waterway_building_up.png 1970-01-01 00:00:00 +0000 and data/images/wui/overlays/waterway_building_up.png 2019-06-11 08:19:26 +0000 differ
85=== modified file 'data/maps/Archipelago_Sea.wmf/elemental'
86--- data/maps/Archipelago_Sea.wmf/elemental 2016-04-01 09:21:48 +0000
87+++ data/maps/Archipelago_Sea.wmf/elemental 2019-06-11 08:19:26 +0000
88@@ -9,4 +9,4 @@
89 author="King of nowhere"
90 descr=_"Between Sweden and Finland lies the archipelago sea. This place of incredible beauty is not land, and it is not sea, but it is both. Within a few hundred kilometers, there are no less than 50,000 islands and islets, most no more than a few acres across. The climate is quite mild for its latitude; farming thrives, berries are abundant, and fish plentiful. The small human population of this place never knew famine. You warlording bastards just couldn’t leave this little paradise in peace, could you?"
91 hint=_"Large plots are rare on those small islands. Prioritize construction of large buildings on them. Sometimes you will need big military buildings to expand all the way to the next island. The AI will perform poorly."
92-tags="official"
93+tags="ferries,official"
94
95=== modified file 'data/maps/Archipelago_Sea.wmf/port_spaces'
96--- data/maps/Archipelago_Sea.wmf/port_spaces 2016-03-21 19:29:24 +0000
97+++ data/maps/Archipelago_Sea.wmf/port_spaces 2019-06-11 08:19:26 +0000
98@@ -3,5 +3,6 @@
99 [global]
100 packet_version="1"
101 number_of_port_spaces="0"
102+waterway_max_length="3"
103
104 [port_spaces]
105
106=== modified file 'data/maps/Calvisson.wmf/elemental'
107--- data/maps/Calvisson.wmf/elemental 2016-03-25 09:45:18 +0000
108+++ data/maps/Calvisson.wmf/elemental 2019-06-11 08:19:26 +0000
109@@ -9,7 +9,7 @@
110 author="Kristin"
111 descr=_"It’s a pleasure to settle in the beauty of this fissured countryside. But the ways to encompass these large territories are long and meandering, so it is easy to err into the land of the foreign clans."
112 hint=
113-tags="2teams,official,seafaring"
114+tags="2teams,ferries,official,seafaring"
115
116 [teams00]
117 team1="0"
118
119=== modified file 'data/maps/Calvisson.wmf/port_spaces'
120--- data/maps/Calvisson.wmf/port_spaces 2016-03-21 19:29:24 +0000
121+++ data/maps/Calvisson.wmf/port_spaces 2019-06-11 08:19:26 +0000
122@@ -2,6 +2,7 @@
123
124 [global]
125 packet_version="1"
126+waterway_max_length="5"
127 number_of_port_spaces="45"
128
129 [port_spaces]
130
131=== modified file 'data/maps/Fellowships_v2.wmf/elemental'
132--- data/maps/Fellowships_v2.wmf/elemental 2016-03-29 18:29:13 +0000
133+++ data/maps/Fellowships_v2.wmf/elemental 2019-06-11 08:19:26 +0000
134@@ -9,4 +9,4 @@
135 author="Teppo"
136 descr=_"Ships are your best fellows. Starting positions are similar, so the map should be fair."
137 hint=_"This is a somewhat technical map, and it is best suited for two or three human players. Coal is hard to find – consider making some. There is gold near the starting point – do you see it?"
138-tags="ffa,seafaring,official"
139+tags="ferries,ffa,seafaring,official"
140
141=== modified file 'data/maps/Fellowships_v2.wmf/port_spaces'
142--- data/maps/Fellowships_v2.wmf/port_spaces 2016-03-22 10:38:29 +0000
143+++ data/maps/Fellowships_v2.wmf/port_spaces 2019-06-11 08:19:26 +0000
144@@ -2,6 +2,7 @@
145
146 [global]
147 packet_version="1"
148+waterway_max_length="6"
149 number_of_port_spaces="9"
150
151 [port_spaces]
152
153=== modified file 'data/maps/Finnish_Lakes.wmf/port_spaces'
154--- data/maps/Finnish_Lakes.wmf/port_spaces 2016-03-21 19:29:24 +0000
155+++ data/maps/Finnish_Lakes.wmf/port_spaces 2019-06-11 08:19:26 +0000
156@@ -3,5 +3,6 @@
157 [global]
158 packet_version="1"
159 number_of_port_spaces="0"
160+waterway_max_length="8"
161
162 [port_spaces]
163
164=== modified file 'data/maps/Four_Castles.wmf/elemental'
165--- data/maps/Four_Castles.wmf/elemental 2016-03-25 09:45:18 +0000
166+++ data/maps/Four_Castles.wmf/elemental 2019-06-11 08:19:26 +0000
167@@ -9,7 +9,7 @@
168 author="Winterwind"
169 descr=_"Well protected in their mighty fortresses, four power-hungry warlords are completing their schemes to dominate these lands…"
170 hint=
171-tags="2teams,artifacts,ffa,official"
172+tags="2teams,artifacts,ferries,ffa,official"
173
174 [teams00]
175 team1="0,1"
176
177=== modified file 'data/maps/Four_Castles.wmf/port_spaces'
178--- data/maps/Four_Castles.wmf/port_spaces 2016-03-21 19:29:24 +0000
179+++ data/maps/Four_Castles.wmf/port_spaces 2019-06-11 08:19:26 +0000
180@@ -3,5 +3,6 @@
181 [global]
182 packet_version="1"
183 number_of_port_spaces="0"
184+waterway_max_length="8"
185
186 [port_spaces]
187
188=== modified file 'data/maps/Golden_Peninsula.wmf/elemental'
189--- data/maps/Golden_Peninsula.wmf/elemental 2016-03-25 09:45:18 +0000
190+++ data/maps/Golden_Peninsula.wmf/elemental 2019-06-11 08:19:26 +0000
191@@ -9,4 +9,4 @@
192 author="Winterwind"
193 descr=_"Two empires race for the treasures of a legendary peninsula…"
194 hint=
195-tags="1v1,artifacts,official"
196+tags="1v1,artifacts,ferries,official"
197
198=== modified file 'data/maps/Golden_Peninsula.wmf/port_spaces'
199--- data/maps/Golden_Peninsula.wmf/port_spaces 2016-03-21 19:29:24 +0000
200+++ data/maps/Golden_Peninsula.wmf/port_spaces 2019-06-11 08:19:26 +0000
201@@ -3,5 +3,6 @@
202 [global]
203 packet_version="1"
204 number_of_port_spaces="0"
205+waterway_max_length="4"
206
207 [port_spaces]
208
209=== modified file 'data/maps/Ice_wars.wmf/elemental'
210--- data/maps/Ice_wars.wmf/elemental 2016-03-25 09:45:18 +0000
211+++ data/maps/Ice_wars.wmf/elemental 2019-06-11 08:19:26 +0000
212@@ -9,4 +9,4 @@
213 author="Einstein13"
214 descr=_"Autumn became winter. Some things are frozen, but not the war."
215 hint=_"Start positions are clockwise"
216-tags="2teams,3teams,4teams,official,seafaring"
217+tags="2teams,3teams,4teams,ferries,official,seafaring"
218
219=== modified file 'data/maps/Ice_wars.wmf/port_spaces'
220--- data/maps/Ice_wars.wmf/port_spaces 2016-03-21 19:29:24 +0000
221+++ data/maps/Ice_wars.wmf/port_spaces 2019-06-11 08:19:26 +0000
222@@ -2,6 +2,7 @@
223
224 [global]
225 packet_version="1"
226+waterway_max_length="12"
227 number_of_port_spaces="56"
228
229 [port_spaces]
230
231=== modified file 'data/maps/Impact.wmf/elemental'
232--- data/maps/Impact.wmf/elemental 2016-03-25 09:45:18 +0000
233+++ data/maps/Impact.wmf/elemental 2019-06-11 08:19:26 +0000
234@@ -9,4 +9,4 @@
235 author="deviant"
236 descr=_"After an impact of an asteroid and the following harsh winter, three isles are connected by ice and stone, setting an end to the peaceful coexistence of three tribes."
237 hint=
238-tags="official,unbalanced"
239+tags="ferries,official,unbalanced"
240
241=== modified file 'data/maps/Impact.wmf/port_spaces'
242--- data/maps/Impact.wmf/port_spaces 2016-03-21 19:29:24 +0000
243+++ data/maps/Impact.wmf/port_spaces 2019-06-11 08:19:26 +0000
244@@ -3,5 +3,6 @@
245 [global]
246 packet_version="1"
247 number_of_port_spaces="0"
248+waterway_max_length="6"
249
250 [port_spaces]
251
252=== modified file 'data/maps/Islands_at_War.wmf/elemental'
253--- data/maps/Islands_at_War.wmf/elemental 2016-10-31 11:14:07 +0000
254+++ data/maps/Islands_at_War.wmf/elemental 2019-06-11 08:19:26 +0000
255@@ -9,4 +9,4 @@
256 author="Tuxlands"
257 descr=_"For centuries, you’ve lived peacefully side by side with the other tribe on the neighboring island. This peace seems to come to an end now – your neighbor has begun to expand."
258 hint=
259-tags="1v1,official,unbalanced"
260+tags="1v1,ferries,official,unbalanced"
261
262=== modified file 'data/maps/Islands_at_War.wmf/port_spaces'
263--- data/maps/Islands_at_War.wmf/port_spaces 2016-03-21 19:29:24 +0000
264+++ data/maps/Islands_at_War.wmf/port_spaces 2019-06-11 08:19:26 +0000
265@@ -3,5 +3,6 @@
266 [global]
267 packet_version="1"
268 number_of_port_spaces="0"
269+waterway_max_length="6"
270
271 [port_spaces]
272
273=== modified file 'data/maps/Kings_and_Queens_v2.wmf/elemental'
274--- data/maps/Kings_and_Queens_v2.wmf/elemental 2016-03-29 18:29:13 +0000
275+++ data/maps/Kings_and_Queens_v2.wmf/elemental 2019-06-11 08:19:26 +0000
276@@ -9,4 +9,4 @@
277 author="fk"
278 descr=_"An old legend tells that these seven kingdoms, that have flourished for ages in prosperity, will someday collapse into a devastating war. Has your latest betrayal been one too many and will the prophecy come true?"
279 hint=
280-tags="ffa,unbalanced,official"
281+tags="ferries,ffa,unbalanced,official"
282
283=== modified file 'data/maps/Kings_and_Queens_v2.wmf/port_spaces'
284--- data/maps/Kings_and_Queens_v2.wmf/port_spaces 2016-03-21 19:29:24 +0000
285+++ data/maps/Kings_and_Queens_v2.wmf/port_spaces 2019-06-11 08:19:26 +0000
286@@ -2,6 +2,7 @@
287
288 [global]
289 packet_version="1"
290+waterway_max_length="20"
291 number_of_port_spaces="0"
292
293 [port_spaces]
294
295=== modified file 'data/maps/Lake_of_Tranquility.wmf/elemental'
296--- data/maps/Lake_of_Tranquility.wmf/elemental 2016-03-25 09:45:18 +0000
297+++ data/maps/Lake_of_Tranquility.wmf/elemental 2019-06-11 08:19:26 +0000
298@@ -9,4 +9,4 @@
299 author="Winterwind"
300 descr=_"This lake, deep in the most ancient forests, has long been known for its beauty and idyllic peace. However, its sanctity has been disturbed now, as two hostile tribes have arrived at its shores…"
301 hint=
302-tags="1v1,artifacts,official"
303+tags="1v1,artifacts,ferries,official"
304
305=== modified file 'data/maps/Lake_of_Tranquility.wmf/port_spaces'
306--- data/maps/Lake_of_Tranquility.wmf/port_spaces 2016-03-21 19:29:24 +0000
307+++ data/maps/Lake_of_Tranquility.wmf/port_spaces 2019-06-11 08:19:26 +0000
308@@ -3,5 +3,6 @@
309 [global]
310 packet_version="1"
311 number_of_port_spaces="0"
312+waterway_max_length="13"
313
314 [port_spaces]
315
316=== modified file 'data/maps/Last_Bastion_v2.wmf/elemental'
317--- data/maps/Last_Bastion_v2.wmf/elemental 2018-02-14 18:29:07 +0000
318+++ data/maps/Last_Bastion_v2.wmf/elemental 2019-06-11 08:19:26 +0000
319@@ -9,4 +9,4 @@
320 author=_"Another Barbarian – edited by king_of_nowhere"
321 descr=_"The whimsical Gods didn’t answer our prayers. Instead, the increasing sunlight heated up the Earth a thousandfold and melted glaciers and people were plunged into the deep. But now – high in the majestic mountains, on the last scrap of land – two surviving tribes are sheltering. Even though the Gods showed mercy and the climate thus turned cooler again, the water is still rising and rising. Onto the last secure place – the highest mountain range where the amount of gold and the space to live merely suffice for one tribe – only two opposite paths lead. But remember, be careful… this last living space is also a hard and small place to live."
322 hint=_"Don’t forget to take care of your timber supplies, you’ll need them."
323-tags="1v1,artifacts,official"
324+tags="1v1,artifacts,ferries,official"
325
326=== modified file 'data/maps/Last_Bastion_v2.wmf/port_spaces'
327--- data/maps/Last_Bastion_v2.wmf/port_spaces 2018-02-02 16:03:06 +0000
328+++ data/maps/Last_Bastion_v2.wmf/port_spaces 2019-06-11 08:19:26 +0000
329@@ -3,5 +3,6 @@
330 [global]
331 packet_version="1"
332 number_of_port_spaces="0"
333+waterway_max_length="5"
334
335 [port_spaces]
336
337=== modified file 'data/maps/Rendez-Vous.wmf/elemental'
338--- data/maps/Rendez-Vous.wmf/elemental 2016-09-18 07:01:55 +0000
339+++ data/maps/Rendez-Vous.wmf/elemental 2019-06-11 08:19:26 +0000
340@@ -9,4 +9,4 @@
341 author="Quappo"
342 descr=_"Only a small hill in the centre of the map connects these four competing tribes. Lead your army to this hill right away and build a giant stronghold as a sign of your superiority!"
343 hint=_"There is space for only one stronghold in the centre. Water can be found everywhere, so there is no need to send out geologists."
344-tags="2teams,ffa,official"
345+tags="2teams,ferries,ffa,official"
346
347=== modified file 'data/maps/Rendez-Vous.wmf/port_spaces'
348--- data/maps/Rendez-Vous.wmf/port_spaces 2016-03-21 19:29:24 +0000
349+++ data/maps/Rendez-Vous.wmf/port_spaces 2019-06-11 08:19:26 +0000
350@@ -3,5 +3,6 @@
351 [global]
352 packet_version="1"
353 number_of_port_spaces="0"
354+waterway_max_length="20"
355
356 [port_spaces]
357
358=== modified file 'data/maps/River_Explorers.wmf/elemental'
359--- data/maps/River_Explorers.wmf/elemental 2016-09-27 18:40:12 +0000
360+++ data/maps/River_Explorers.wmf/elemental 2019-06-11 08:19:26 +0000
361@@ -9,4 +9,4 @@
362 author="Jenia"
363 descr=_"Each player has a different obstacle to expansion, and there’s always more than one way to overcome it. While the AI can be defeated here without building a single ship, players are advised to make ports and shipyards a priority – expeditions are universally useful and are often the fastest way to gold deposits."
364 hint=
365-tags="artifacts,official,seafaring,unbalanced"
366+tags="artifacts,ferries,official,seafaring,unbalanced"
367
368=== modified file 'data/maps/River_Explorers.wmf/port_spaces'
369--- data/maps/River_Explorers.wmf/port_spaces 2016-09-27 18:40:12 +0000
370+++ data/maps/River_Explorers.wmf/port_spaces 2019-06-11 08:19:26 +0000
371@@ -2,6 +2,7 @@
372
373 [global]
374 packet_version="1"
375+waterway_max_length="16"
376 number_of_port_spaces="19"
377
378 [port_spaces]
379
380=== modified file 'data/maps/Riverlands.wmf/elemental'
381--- data/maps/Riverlands.wmf/elemental 2016-03-25 09:45:18 +0000
382+++ data/maps/Riverlands.wmf/elemental 2019-06-11 08:19:26 +0000
383@@ -9,4 +9,4 @@
384 author="ISCH"
385 descr=_"A mystical land, full of different landscapes, which are all crossed by a handful of big rivers."
386 hint=
387-tags="artifacts,official,unbalanced"
388+tags="artifacts,ferries,official,unbalanced"
389
390=== modified file 'data/maps/Riverlands.wmf/port_spaces'
391--- data/maps/Riverlands.wmf/port_spaces 2016-03-21 19:29:24 +0000
392+++ data/maps/Riverlands.wmf/port_spaces 2019-06-11 08:19:26 +0000
393@@ -3,5 +3,6 @@
394 [global]
395 packet_version="1"
396 number_of_port_spaces="0"
397+waterway_max_length="4"
398
399 [port_spaces]
400
401=== modified file 'data/maps/Sun_of_Fire.wmf/elemental'
402--- data/maps/Sun_of_Fire.wmf/elemental 2016-03-25 09:45:18 +0000
403+++ data/maps/Sun_of_Fire.wmf/elemental 2019-06-11 08:19:26 +0000
404@@ -9,4 +9,4 @@
405 author="Nasenbaer"
406 descr=_"For hundreds of years, this island was kept as a sanctuary of the Gods. No human ever ventured to set a foot on it. But now that a tribe had finally been barefaced enough to settle on the coast of that island, a lot of others followed in its wake."
407 hint=_"Start positions are clockwise"
408-tags="2teams,3teams,4teams,ffa,official"
409+tags="2teams,3teams,4teams,ferries,ffa,official"
410
411=== modified file 'data/maps/Sun_of_Fire.wmf/port_spaces'
412--- data/maps/Sun_of_Fire.wmf/port_spaces 2016-03-21 19:29:24 +0000
413+++ data/maps/Sun_of_Fire.wmf/port_spaces 2019-06-11 08:19:26 +0000
414@@ -3,5 +3,6 @@
415 [global]
416 packet_version="1"
417 number_of_port_spaces="0"
418+waterway_max_length="14"
419
420 [port_spaces]
421
422=== modified file 'data/maps/The_Far_North.wmf/elemental'
423--- data/maps/The_Far_North.wmf/elemental 2016-03-25 09:45:18 +0000
424+++ data/maps/The_Far_North.wmf/elemental 2019-06-11 08:19:26 +0000
425@@ -9,4 +9,4 @@
426 author="Another Barbarian"
427 descr=_"Some say that impenetrable lands to the far north scared away even the most courageous settlers and the bravest of the brave warriors. Big and old forests, full of big and predatory game, cut across by wetlands and hills were shrouded in mystery. The ones who had managed to come back mentioned tremendous buildings, decorated with carvings and gold from majestic mountain ranges somewhere amongst the wilderness. Dozens of years after only some crumbly ruins remain of these good old times, covered with moss and trees. Their shapes give only an idea about the craftsmanship of ancient constructors. Nobody knows why they (have) disappeared. Nobody knows why. People say that now nothing is blocking the road to wealth. But many will die pulled apart by wolves, engulfed by swamp… encircled by hostile tribes."
428 hint=
429-tags="1v1,artifacts,official"
430+tags="1v1,artifacts,ferries,official"
431
432=== modified file 'data/maps/The_Far_North.wmf/port_spaces'
433--- data/maps/The_Far_North.wmf/port_spaces 2016-03-21 19:29:24 +0000
434+++ data/maps/The_Far_North.wmf/port_spaces 2019-06-11 08:19:26 +0000
435@@ -3,5 +3,6 @@
436 [global]
437 packet_version="1"
438 number_of_port_spaces="0"
439+waterway_max_length="7"
440
441 [port_spaces]
442
443=== modified file 'data/maps/The_Long_Way.wmf/elemental'
444--- data/maps/The_Long_Way.wmf/elemental 2016-03-25 09:45:18 +0000
445+++ data/maps/The_Long_Way.wmf/elemental 2019-06-11 08:19:26 +0000
446@@ -9,4 +9,4 @@
447 author="ISCH"
448 descr=_"Another strange test by the Gods. To reach the other side, there seems to be no other way but to occupy the land of your enemies."
449 hint=
450-tags="official,unbalanced"
451+tags="ferries,official,unbalanced"
452
453=== modified file 'data/maps/The_Long_Way.wmf/port_spaces'
454--- data/maps/The_Long_Way.wmf/port_spaces 2016-03-21 19:29:24 +0000
455+++ data/maps/The_Long_Way.wmf/port_spaces 2019-06-11 08:19:26 +0000
456@@ -3,5 +3,6 @@
457 [global]
458 packet_version="1"
459 number_of_port_spaces="0"
460+waterway_max_length="14"
461
462 [port_spaces]
463
464=== modified file 'data/maps/The_Nile_v2.wmf/elemental'
465--- data/maps/The_Nile_v2.wmf/elemental 2016-03-29 18:29:13 +0000
466+++ data/maps/The_Nile_v2.wmf/elemental 2019-06-11 08:19:26 +0000
467@@ -10,7 +10,7 @@
468 descr=_"The river has always provided food and communication. This time, eight empires will fight for control over this land."
469 hint=_"Use the river wisely. Your opponents will do the same. You will find the main ore resources deep in the desert."
470 hint=
471-tags="1v1,2teams,3teams,4teams,seafaring,official"
472+tags="1v1,2teams,3teams,4teams,ferries,seafaring,official"
473
474 [teams00]
475 team1="0"
476
477=== modified file 'data/maps/The_Nile_v2.wmf/port_spaces'
478--- data/maps/The_Nile_v2.wmf/port_spaces 2016-03-21 19:29:24 +0000
479+++ data/maps/The_Nile_v2.wmf/port_spaces 2019-06-11 08:19:26 +0000
480@@ -2,6 +2,7 @@
481
482 [global]
483 packet_version="1"
484+waterway_max_length="10"
485 number_of_port_spaces="137"
486
487 [port_spaces]
488
489=== modified file 'data/maps/The_Pass_Through_the_Mountains.wmf/elemental'
490--- data/maps/The_Pass_Through_the_Mountains.wmf/elemental 2016-10-31 09:34:27 +0000
491+++ data/maps/The_Pass_Through_the_Mountains.wmf/elemental 2019-06-11 08:19:26 +0000
492@@ -9,4 +9,4 @@
493 author="Quappo"
494 descr=_"In this mountainous area two princes have settled. Now they are expanding their territories, unaware of the fact that they are not alone!"
495 hint=
496-tags="1v1,artifacts,official"
497+tags="1v1,artifacts,ferries,official"
498
499=== modified file 'data/maps/The_Pass_Through_the_Mountains.wmf/port_spaces'
500--- data/maps/The_Pass_Through_the_Mountains.wmf/port_spaces 2016-03-21 19:29:24 +0000
501+++ data/maps/The_Pass_Through_the_Mountains.wmf/port_spaces 2019-06-11 08:19:26 +0000
502@@ -3,5 +3,6 @@
503 [global]
504 packet_version="1"
505 number_of_port_spaces="0"
506+waterway_max_length="10"
507
508 [port_spaces]
509
510=== modified file 'data/maps/Twin_Lagoons_v2.wmf/elemental'
511--- data/maps/Twin_Lagoons_v2.wmf/elemental 2016-03-29 18:29:13 +0000
512+++ data/maps/Twin_Lagoons_v2.wmf/elemental 2019-06-11 08:19:26 +0000
513@@ -9,4 +9,4 @@
514 author="fk"
515 descr=_"When the wind swelled up and the first dunes were formed on these abandoned twin lagoons, nobody could have expected that two tribes that are desperately searching for more resources to support their endlessly ongoing wars, would end up in this forgotten place at the same time and for the same well-known reason."
516 hint=_"Defend your transport lines, or use ships to bypass the opponent. Then remove all enemy activity."
517-tags="1v1,seafaring,official"
518+tags="1v1,ferries,seafaring,official"
519
520=== modified file 'data/maps/Twin_Lagoons_v2.wmf/port_spaces'
521--- data/maps/Twin_Lagoons_v2.wmf/port_spaces 2016-03-21 19:29:24 +0000
522+++ data/maps/Twin_Lagoons_v2.wmf/port_spaces 2019-06-11 08:19:26 +0000
523@@ -2,6 +2,7 @@
524
525 [global]
526 packet_version="1"
527+waterway_max_length="10"
528 number_of_port_spaces="38"
529
530 [port_spaces]
531
532=== modified file 'data/maps/Twinkling_Waves.wmf/elemental'
533--- data/maps/Twinkling_Waves.wmf/elemental 2016-03-25 09:45:18 +0000
534+++ data/maps/Twinkling_Waves.wmf/elemental 2019-06-11 08:19:26 +0000
535@@ -9,4 +9,4 @@
536 author="Nasenbaer"
537 descr=_"Many beautiful, green islands await the ones brave enough to pass the thousand waves, twinkling in the sun."
538 hint=
539-tags="artifacts,official,seafaring,unbalanced"
540+tags="artifacts,ferries,official,seafaring,unbalanced"
541
542=== modified file 'data/maps/Twinkling_Waves.wmf/port_spaces'
543--- data/maps/Twinkling_Waves.wmf/port_spaces 2016-03-21 19:29:24 +0000
544+++ data/maps/Twinkling_Waves.wmf/port_spaces 2019-06-11 08:19:26 +0000
545@@ -2,6 +2,7 @@
546
547 [global]
548 packet_version="1"
549+waterway_max_length="7"
550 number_of_port_spaces="13"
551
552 [port_spaces]
553
554=== modified file 'data/maps/Volcanic_Winter.wmf/elemental'
555--- data/maps/Volcanic_Winter.wmf/elemental 2016-03-25 09:45:18 +0000
556+++ data/maps/Volcanic_Winter.wmf/elemental 2019-06-11 08:19:26 +0000
557@@ -9,4 +9,4 @@
558 author="Nasenbaer"
559 descr=_"In the middle of summer, a series of volcanic eruptions drew the winter in. Suddenly, the sun seemed to be gone and the only light and heat sources left were those that enforced this dramatic change. Continents, oceans and seas are frozen now, only the volcanic islands seem to be left as habitable land."
560 hint=
561-tags="1v1,artifacts,official,seafaring"
562+tags="1v1,artifacts,ferries,official,seafaring"
563
564=== modified file 'data/maps/Volcanic_Winter.wmf/port_spaces'
565--- data/maps/Volcanic_Winter.wmf/port_spaces 2016-03-21 19:29:24 +0000
566+++ data/maps/Volcanic_Winter.wmf/port_spaces 2019-06-11 08:19:26 +0000
567@@ -2,6 +2,7 @@
568
569 [global]
570 packet_version="1"
571+waterway_max_length="4"
572 number_of_port_spaces="12"
573
574 [port_spaces]
575
576=== modified file 'data/tribes/atlanteans.lua'
577--- data/tribes/atlanteans.lua 2019-05-25 08:51:42 +0000
578+++ data/tribes/atlanteans.lua 2019-06-11 08:19:26 +0000
579@@ -17,7 +17,7 @@
580 --
581 -- **animations**: Global animations. Contains subtables for ``frontier`` and ``flag``. Each animation needs the parameters ``pictures`` (table of filenames) and ``hotspot`` (2 integer coordinates), and may also define ``fps`` (integer frames per second).
582 --
583--- **roads**: The file paths for the tribes' road textures in 2 subtables ``busy`` and ``normal``
584+-- **roads**: The file paths for the tribe's road textures in 3 subtables ``busy``, ``normal`` and ``waterway``.
585 --
586 -- **resource_indicators**: The names for the resource indicators. This table contains a subtable for each resource name plus a subtable named "" for no resources. Each subtable is an array, in which the index of each entry is the highest amount of resources the indicator may indicate.
587 --
588@@ -43,6 +43,8 @@
589 --
590 -- **ship**: The internal name of the tribe's ship.
591 --
592+-- **ferry**: The internal name of the tribe's ferry.
593+--
594 -- **port**: The internal name of the tribe's port building. This unit needs to be defined in the ``buildings`` table too.
595
596 image_dirname = path.dirname(__file__) .. "images/atlanteans/"
597@@ -55,7 +57,7 @@
598 name = "atlanteans",
599 animations = animations,
600
601- -- Image file paths for this tribe's road textures
602+ -- Image file paths for this tribe's road and waterway textures
603 roads = {
604 busy = {
605 image_dirname .. "roadt_busy.png",
606@@ -64,6 +66,9 @@
607 image_dirname .. "roadt_normal_00.png",
608 image_dirname .. "roadt_normal_01.png",
609 },
610+ waterway = {
611+ "tribes/images/atlanteans/waterway_0.png",
612+ },
613 },
614
615 resource_indicators = {
616@@ -163,6 +168,7 @@
617 {
618 -- Carriers
619 "atlanteans_carrier",
620+ "atlanteans_ferry",
621 "atlanteans_horse",
622 "atlanteans_horsebreeder"
623 },
624@@ -265,6 +271,7 @@
625 "atlanteans_weaponsmithy",
626 "atlanteans_armorsmithy",
627 "atlanteans_shipyard",
628+ "atlanteans_ferry_yard",
629 "atlanteans_barracks",
630
631 -- Big
632@@ -365,6 +372,7 @@
633 geologist = "atlanteans_geologist",
634 soldier = "atlanteans_soldier",
635 ship = "atlanteans_ship",
636+ ferry = "atlanteans_ferry",
637 port = "atlanteans_port",
638 ironore = "iron_ore",
639 rawlog = "log",
640
641=== modified file 'data/tribes/barbarians.lua'
642--- data/tribes/barbarians.lua 2019-05-26 01:46:18 +0000
643+++ data/tribes/barbarians.lua 2019-06-11 08:19:26 +0000
644@@ -8,7 +8,7 @@
645 name = "barbarians",
646 animations = animations,
647
648- -- Image file paths for this tribe's road textures
649+ -- Image file paths for this tribe's road and waterway textures
650 roads = {
651 busy = {
652 image_dirname .. "roadt_busy.png",
653@@ -17,6 +17,9 @@
654 image_dirname .. "roadt_normal_00.png",
655 image_dirname .. "roadt_normal_01.png",
656 },
657+ waterway = {
658+ "tribes/images/barbarians/waterway_0.png",
659+ },
660 },
661
662 resource_indicators = {
663@@ -112,6 +115,7 @@
664 {
665 -- Carriers
666 "barbarians_carrier",
667+ "barbarians_ferry",
668 "barbarians_ox",
669 "barbarians_cattlebreeder"
670 },
671@@ -220,6 +224,7 @@
672 "barbarians_warmill",
673 "barbarians_ax_workshop",
674 "barbarians_shipyard",
675+ "barbarians_ferry_yard",
676 "barbarians_barracks",
677
678 -- Big
679@@ -300,6 +305,7 @@
680 geologist = "barbarians_geologist",
681 soldier = "barbarians_soldier",
682 ship = "barbarians_ship",
683+ ferry = "barbarians_ferry",
684 port = "barbarians_port",
685 ironore = "iron_ore",
686 rawlog = "log",
687
688=== added directory 'data/tribes/buildings/productionsites/atlanteans/ferry_yard'
689=== added file 'data/tribes/buildings/productionsites/atlanteans/ferry_yard/helptexts.lua'
690--- data/tribes/buildings/productionsites/atlanteans/ferry_yard/helptexts.lua 1970-01-01 00:00:00 +0000
691+++ data/tribes/buildings/productionsites/atlanteans/ferry_yard/helptexts.lua 2019-06-11 08:19:26 +0000
692@@ -0,0 +1,27 @@
693+-- This include can be removed when all help texts have been defined.
694+include "tribes/scripting/help/global_helptexts.lua"
695+
696+function building_helptext_lore()
697+ -- TRANSLATORS#: Lore helptext for a building
698+ return no_lore_text_yet()
699+end
700+
701+function building_helptext_lore_author()
702+ -- TRANSLATORS#: Lore author helptext for a building
703+ return no_lore_author_text_yet()
704+end
705+
706+function building_helptext_purpose()
707+ -- TRANSLATORS: Purpose helptext for a building
708+ return pgettext("building", "Builds ferries.")
709+end
710+
711+function building_helptext_note()
712+ -- TRANSLATORS: Note helptext for a building
713+ return pgettext("building", "Needs water nearby.")
714+end
715+
716+function building_helptext_performance()
717+ -- TRANSLATORS#: Performance helptext for a building
718+ return no_performance_text_yet()
719+end
720
721=== added file 'data/tribes/buildings/productionsites/atlanteans/ferry_yard/idle_00.png'
722Binary files data/tribes/buildings/productionsites/atlanteans/ferry_yard/idle_00.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/atlanteans/ferry_yard/idle_00.png 2019-06-11 08:19:26 +0000 differ
723=== added file 'data/tribes/buildings/productionsites/atlanteans/ferry_yard/idle_00_pc.png'
724Binary files data/tribes/buildings/productionsites/atlanteans/ferry_yard/idle_00_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/atlanteans/ferry_yard/idle_00_pc.png 2019-06-11 08:19:26 +0000 differ
725=== added file 'data/tribes/buildings/productionsites/atlanteans/ferry_yard/init.lua'
726--- data/tribes/buildings/productionsites/atlanteans/ferry_yard/init.lua 1970-01-01 00:00:00 +0000
727+++ data/tribes/buildings/productionsites/atlanteans/ferry_yard/init.lua 2019-06-11 08:19:26 +0000
728@@ -0,0 +1,55 @@
729+dirname = path.dirname(__file__)
730+
731+tribes:new_productionsite_type {
732+ msgctxt = "atlanteans_building",
733+ name = "atlanteans_ferry_yard",
734+ -- TRANSLATORS: This is a building name used in lists of buildings
735+ descname = pgettext("atlanteans_building", "Ferry Yard"),
736+ helptext_script = dirname .. "helptexts.lua",
737+ icon = dirname .. "menu.png",
738+ size = "medium",
739+ map_check = {"waterways"},
740+
741+ buildcost = {
742+ log = 3,
743+ planks = 2,
744+ granite = 3,
745+ spidercloth = 2
746+ },
747+ return_on_dismantle = {
748+ log = 1,
749+ planks = 1,
750+ granite = 2,
751+ spidercloth = 1
752+ },
753+
754+ -- TODO(Nordfriese): Make animations
755+ animations = {
756+ idle = {
757+ pictures = path.list_files(dirname .. "idle_??.png"),
758+ hotspot = { 53, 66 },
759+ }
760+ },
761+
762+ aihints = {},
763+
764+ working_positions = {
765+ atlanteans_shipwright = 1
766+ },
767+
768+ inputs = {
769+ { name = "log", amount = 8 },
770+ },
771+
772+ programs = {
773+ work = {
774+ -- TRANSLATORS: Completed/Skipped/Did not start working because ...
775+ descname = _"working",
776+ actions = {
777+ "sleep=20000",
778+ "consume=log:3",
779+ "callworker=buildferry"
780+ }
781+ },
782+ },
783+}
784
785=== added file 'data/tribes/buildings/productionsites/atlanteans/ferry_yard/menu.png'
786Binary files data/tribes/buildings/productionsites/atlanteans/ferry_yard/menu.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/atlanteans/ferry_yard/menu.png 2019-06-11 08:19:26 +0000 differ
787=== modified file 'data/tribes/buildings/productionsites/atlanteans/shipyard/init.lua'
788--- data/tribes/buildings/productionsites/atlanteans/shipyard/init.lua 2019-05-29 18:29:28 +0000
789+++ data/tribes/buildings/productionsites/atlanteans/shipyard/init.lua 2019-06-11 08:19:26 +0000
790@@ -8,7 +8,7 @@
791 helptext_script = dirname .. "helptexts.lua",
792 icon = dirname .. "menu.png",
793 size = "medium",
794- needs_seafaring = true,
795+ map_check = {"seafaring"},
796
797 buildcost = {
798 log = 3,
799
800=== added directory 'data/tribes/buildings/productionsites/barbarians/ferry_yard'
801=== added file 'data/tribes/buildings/productionsites/barbarians/ferry_yard/helptexts.lua'
802--- data/tribes/buildings/productionsites/barbarians/ferry_yard/helptexts.lua 1970-01-01 00:00:00 +0000
803+++ data/tribes/buildings/productionsites/barbarians/ferry_yard/helptexts.lua 2019-06-11 08:19:26 +0000
804@@ -0,0 +1,27 @@
805+-- This include can be removed when all help texts have been defined.
806+include "tribes/scripting/help/global_helptexts.lua"
807+
808+function building_helptext_lore()
809+ -- TRANSLATORS#: Lore helptext for a building
810+ return no_lore_text_yet()
811+end
812+
813+function building_helptext_lore_author()
814+ -- TRANSLATORS#: Lore author helptext for a building
815+ return no_lore_author_text_yet()
816+end
817+
818+function building_helptext_purpose()
819+ -- TRANSLATORS: Purpose helptext for a building
820+ return pgettext("building", "Builds ferries.")
821+end
822+
823+function building_helptext_note()
824+ -- TRANSLATORS: Note helptext for a building
825+ return pgettext("building", "Needs water nearby.")
826+end
827+
828+function building_helptext_performance()
829+ -- TRANSLATORS#: Performance helptext for a building
830+ return no_performance_text_yet()
831+end
832
833=== added file 'data/tribes/buildings/productionsites/barbarians/ferry_yard/idle_00.png'
834Binary files data/tribes/buildings/productionsites/barbarians/ferry_yard/idle_00.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/barbarians/ferry_yard/idle_00.png 2019-06-11 08:19:26 +0000 differ
835=== added file 'data/tribes/buildings/productionsites/barbarians/ferry_yard/idle_00_pc.png'
836Binary files data/tribes/buildings/productionsites/barbarians/ferry_yard/idle_00_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/barbarians/ferry_yard/idle_00_pc.png 2019-06-11 08:19:26 +0000 differ
837=== added file 'data/tribes/buildings/productionsites/barbarians/ferry_yard/init.lua'
838--- data/tribes/buildings/productionsites/barbarians/ferry_yard/init.lua 1970-01-01 00:00:00 +0000
839+++ data/tribes/buildings/productionsites/barbarians/ferry_yard/init.lua 2019-06-11 08:19:26 +0000
840@@ -0,0 +1,54 @@
841+dirname = path.dirname(__file__)
842+
843+tribes:new_productionsite_type {
844+ msgctxt = "barbarians_building",
845+ name = "barbarians_ferry_yard",
846+ -- TRANSLATORS: This is a building name used in lists of buildings
847+ descname = pgettext("barbarians_building", "Ferry Yard"),
848+ helptext_script = dirname .. "helptexts.lua",
849+ icon = dirname .. "menu.png",
850+ size = "medium",
851+ map_check = {"waterways"},
852+
853+ buildcost = {
854+ log = 3,
855+ blackwood = 2,
856+ granite = 3,
857+ cloth = 2
858+ },
859+ return_on_dismantle = {
860+ log = 1,
861+ blackwood = 1,
862+ granite = 2
863+ },
864+
865+ -- TODO(Nordfriese): Make animations
866+ animations = {
867+ idle = {
868+ pictures = path.list_files(dirname .. "idle_??.png"),
869+ hotspot = { 62, 48 },
870+ }
871+ },
872+
873+ aihints = {},
874+
875+ working_positions = {
876+ barbarians_shipwright = 1
877+ },
878+
879+ inputs = {
880+ { name = "log", amount = 8 },
881+ },
882+
883+ programs = {
884+ work = {
885+ -- TRANSLATORS: Completed/Skipped/Did not start working because ...
886+ descname = _"working",
887+ actions = {
888+ "sleep=20000",
889+ "consume=log:3",
890+ "callworker=buildferry"
891+ }
892+ },
893+ },
894+}
895
896=== added file 'data/tribes/buildings/productionsites/barbarians/ferry_yard/menu.png'
897Binary files data/tribes/buildings/productionsites/barbarians/ferry_yard/menu.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/barbarians/ferry_yard/menu.png 2019-06-11 08:19:26 +0000 differ
898=== modified file 'data/tribes/buildings/productionsites/barbarians/shipyard/init.lua'
899--- data/tribes/buildings/productionsites/barbarians/shipyard/init.lua 2019-05-29 18:29:28 +0000
900+++ data/tribes/buildings/productionsites/barbarians/shipyard/init.lua 2019-06-11 08:19:26 +0000
901@@ -14,7 +14,7 @@
902 helptext_script = dirname .. "helptexts.lua",
903 icon = dirname .. "menu.png",
904 size = "medium",
905- needs_seafaring = true,
906+ map_check = {"seafaring"},
907
908 buildcost = {
909 log = 3,
910
911=== modified file 'data/tribes/buildings/productionsites/barbarians/weaving_mill/init.lua'
912--- data/tribes/buildings/productionsites/barbarians/weaving_mill/init.lua 2019-05-19 11:25:28 +0000
913+++ data/tribes/buildings/productionsites/barbarians/weaving_mill/init.lua 2019-06-11 08:19:26 +0000
914@@ -8,7 +8,7 @@
915 helptext_script = dirname .. "helptexts.lua",
916 icon = dirname .. "menu.png",
917 size = "big",
918- needs_seafaring = true,
919+ map_check = {"seafaring", "waterways"},
920
921 buildcost = {
922 log = 5,
923
924=== added directory 'data/tribes/buildings/productionsites/empire/ferry_yard'
925=== added file 'data/tribes/buildings/productionsites/empire/ferry_yard/helptexts.lua'
926--- data/tribes/buildings/productionsites/empire/ferry_yard/helptexts.lua 1970-01-01 00:00:00 +0000
927+++ data/tribes/buildings/productionsites/empire/ferry_yard/helptexts.lua 2019-06-11 08:19:26 +0000
928@@ -0,0 +1,27 @@
929+-- This include can be removed when all help texts have been defined.
930+include "tribes/scripting/help/global_helptexts.lua"
931+
932+function building_helptext_lore()
933+ -- TRANSLATORS#: Lore helptext for a building
934+ return no_lore_text_yet()
935+end
936+
937+function building_helptext_lore_author()
938+ -- TRANSLATORS#: Lore author helptext for a building
939+ return no_lore_author_text_yet()
940+end
941+
942+function building_helptext_purpose()
943+ -- TRANSLATORS: Purpose helptext for a building
944+ return pgettext("building", "Builds ferries.")
945+end
946+
947+function building_helptext_note()
948+ -- TRANSLATORS: Note helptext for a building
949+ return pgettext("building", "Needs water nearby.")
950+end
951+
952+function building_helptext_performance()
953+ -- TRANSLATORS#: Performance helptext for a building
954+ return no_performance_text_yet()
955+end
956
957=== added file 'data/tribes/buildings/productionsites/empire/ferry_yard/idle_00.png'
958Binary files data/tribes/buildings/productionsites/empire/ferry_yard/idle_00.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/empire/ferry_yard/idle_00.png 2019-06-11 08:19:26 +0000 differ
959=== added file 'data/tribes/buildings/productionsites/empire/ferry_yard/idle_00_pc.png'
960Binary files data/tribes/buildings/productionsites/empire/ferry_yard/idle_00_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/empire/ferry_yard/idle_00_pc.png 2019-06-11 08:19:26 +0000 differ
961=== added file 'data/tribes/buildings/productionsites/empire/ferry_yard/init.lua'
962--- data/tribes/buildings/productionsites/empire/ferry_yard/init.lua 1970-01-01 00:00:00 +0000
963+++ data/tribes/buildings/productionsites/empire/ferry_yard/init.lua 2019-06-11 08:19:26 +0000
964@@ -0,0 +1,54 @@
965+dirname = path.dirname(__file__)
966+
967+tribes:new_productionsite_type {
968+ msgctxt = "empire_building",
969+ name = "empire_ferry_yard",
970+ -- TRANSLATORS: This is a building name used in lists of buildings
971+ descname = pgettext("empire_building", "Ferry Yard"),
972+ helptext_script = dirname .. "helptexts.lua",
973+ icon = dirname .. "menu.png",
974+ size = "medium",
975+ map_check = {"waterways"},
976+
977+ buildcost = {
978+ log = 3,
979+ planks = 2,
980+ granite = 3,
981+ cloth = 2
982+ },
983+ return_on_dismantle = {
984+ log = 1,
985+ granite = 2,
986+ cloth = 1
987+ },
988+
989+ -- TODO(Nordfriese): Make animations
990+ animations = {
991+ idle = {
992+ pictures = path.list_files(dirname .. "idle_??.png"),
993+ hotspot = { 50, 63 },
994+ }
995+ },
996+
997+ aihints = {},
998+
999+ working_positions = {
1000+ empire_shipwright = 1
1001+ },
1002+
1003+ inputs = {
1004+ { name = "log", amount = 8 },
1005+ },
1006+
1007+ programs = {
1008+ work = {
1009+ -- TRANSLATORS: Completed/Skipped/Did not start working because ...
1010+ descname = _"working",
1011+ actions = {
1012+ "sleep=20000",
1013+ "consume=log:3",
1014+ "callworker=buildferry"
1015+ }
1016+ },
1017+ },
1018+}
1019
1020=== added file 'data/tribes/buildings/productionsites/empire/ferry_yard/menu.png'
1021Binary files data/tribes/buildings/productionsites/empire/ferry_yard/menu.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/empire/ferry_yard/menu.png 2019-06-11 08:19:26 +0000 differ
1022=== modified file 'data/tribes/buildings/productionsites/empire/shipyard/init.lua'
1023--- data/tribes/buildings/productionsites/empire/shipyard/init.lua 2019-05-29 18:29:28 +0000
1024+++ data/tribes/buildings/productionsites/empire/shipyard/init.lua 2019-06-11 08:19:26 +0000
1025@@ -8,7 +8,7 @@
1026 helptext_script = dirname .. "helptexts.lua",
1027 icon = dirname .. "menu.png",
1028 size = "medium",
1029- needs_seafaring = true,
1030+ map_check = {"seafaring"},
1031
1032 buildcost = {
1033 log = 3,
1034
1035=== added directory 'data/tribes/buildings/productionsites/frisians/ferry_yard'
1036=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/helptexts.lua'
1037--- data/tribes/buildings/productionsites/frisians/ferry_yard/helptexts.lua 1970-01-01 00:00:00 +0000
1038+++ data/tribes/buildings/productionsites/frisians/ferry_yard/helptexts.lua 2019-06-11 08:19:26 +0000
1039@@ -0,0 +1,27 @@
1040+-- This include can be removed when all help texts have been defined.
1041+include "tribes/scripting/help/global_helptexts.lua"
1042+
1043+function building_helptext_lore()
1044+ -- TRANSLATORS#: Lore helptext for a building
1045+ return no_lore_text_yet()
1046+end
1047+
1048+function building_helptext_lore_author()
1049+ -- TRANSLATORS#: Lore author helptext for a building
1050+ return no_lore_author_text_yet()
1051+end
1052+
1053+function building_helptext_purpose()
1054+ -- TRANSLATORS: Purpose helptext for a building
1055+ return pgettext("building", "Builds ferries.")
1056+end
1057+
1058+function building_helptext_note()
1059+ -- TRANSLATORS: Note helptext for a building
1060+ return pgettext("building", "Needs water nearby.")
1061+end
1062+
1063+function building_helptext_performance()
1064+ -- TRANSLATORS#: Performance helptext for a building
1065+ return no_performance_text_yet()
1066+end
1067
1068=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_00.png'
1069Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_00.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_00.png 2019-06-11 08:19:26 +0000 differ
1070=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_00_pc.png'
1071Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_00_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_00_pc.png 2019-06-11 08:19:26 +0000 differ
1072=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_01.png'
1073Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_01.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_01.png 2019-06-11 08:19:26 +0000 differ
1074=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_01_pc.png'
1075Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_01_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_01_pc.png 2019-06-11 08:19:26 +0000 differ
1076=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_02.png'
1077Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_02.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_02.png 2019-06-11 08:19:26 +0000 differ
1078=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_02_pc.png'
1079Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_02_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_02_pc.png 2019-06-11 08:19:26 +0000 differ
1080=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_03.png'
1081Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_03.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_03.png 2019-06-11 08:19:26 +0000 differ
1082=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_03_pc.png'
1083Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_03_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_03_pc.png 2019-06-11 08:19:26 +0000 differ
1084=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_04.png'
1085Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_04.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_04.png 2019-06-11 08:19:26 +0000 differ
1086=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_04_pc.png'
1087Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_04_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_04_pc.png 2019-06-11 08:19:26 +0000 differ
1088=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_05.png'
1089Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_05.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_05.png 2019-06-11 08:19:26 +0000 differ
1090=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_05_pc.png'
1091Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_05_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_05_pc.png 2019-06-11 08:19:26 +0000 differ
1092=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_06.png'
1093Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_06.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_06.png 2019-06-11 08:19:26 +0000 differ
1094=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_06_pc.png'
1095Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_06_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_06_pc.png 2019-06-11 08:19:26 +0000 differ
1096=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_07.png'
1097Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_07.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_07.png 2019-06-11 08:19:26 +0000 differ
1098=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_07_pc.png'
1099Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_07_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_07_pc.png 2019-06-11 08:19:26 +0000 differ
1100=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_08.png'
1101Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_08.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_08.png 2019-06-11 08:19:26 +0000 differ
1102=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_08_pc.png'
1103Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_08_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_08_pc.png 2019-06-11 08:19:26 +0000 differ
1104=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_09.png'
1105Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_09.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_09.png 2019-06-11 08:19:26 +0000 differ
1106=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/idle_09_pc.png'
1107Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/idle_09_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/idle_09_pc.png 2019-06-11 08:19:26 +0000 differ
1108=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/init.lua'
1109--- data/tribes/buildings/productionsites/frisians/ferry_yard/init.lua 1970-01-01 00:00:00 +0000
1110+++ data/tribes/buildings/productionsites/frisians/ferry_yard/init.lua 2019-06-11 08:19:26 +0000
1111@@ -0,0 +1,59 @@
1112+dirname = path.dirname(__file__)
1113+
1114+tribes:new_productionsite_type {
1115+ msgctxt = "frisians_building",
1116+ name = "frisians_ferry_yard",
1117+ -- TRANSLATORS: This is a building name used in lists of buildings
1118+ descname = pgettext("frisians_building", "Ferry Yard"),
1119+ helptext_script = dirname .. "helptexts.lua",
1120+ icon = dirname .. "menu.png",
1121+ size = "medium",
1122+ map_check = {"waterways"},
1123+
1124+ buildcost = {
1125+ brick = 3,
1126+ granite = 1,
1127+ log = 3,
1128+ reed = 2,
1129+ cloth = 1
1130+ },
1131+ return_on_dismantle = {
1132+ brick = 2,
1133+ log = 2,
1134+ reed = 1
1135+ },
1136+
1137+ animations = {
1138+ idle = {
1139+ pictures = path.list_files (dirname .. "idle_??.png"),
1140+ hotspot = {56, 87},
1141+ fps = 10,
1142+ },
1143+ unoccupied = {
1144+ pictures = path.list_files (dirname .. "unoccupied_?.png"),
1145+ hotspot = {56, 66},
1146+ },
1147+ },
1148+
1149+ aihints = {},
1150+
1151+ working_positions = {
1152+ frisians_shipwright = 1
1153+ },
1154+
1155+ inputs = {
1156+ { name = "log", amount = 8 },
1157+ },
1158+
1159+ programs = {
1160+ work = {
1161+ -- TRANSLATORS: Completed/Skipped/Did not start working because ...
1162+ descname = _"working",
1163+ actions = {
1164+ "sleep=20000",
1165+ "consume=log:3",
1166+ "callworker=buildferry"
1167+ }
1168+ },
1169+ },
1170+}
1171
1172=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/menu.png'
1173Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/menu.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/menu.png 2019-06-11 08:19:26 +0000 differ
1174=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/unoccupied_0.png'
1175Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/unoccupied_0.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/unoccupied_0.png 2019-06-11 08:19:26 +0000 differ
1176=== added file 'data/tribes/buildings/productionsites/frisians/ferry_yard/unoccupied_0_pc.png'
1177Binary files data/tribes/buildings/productionsites/frisians/ferry_yard/unoccupied_0_pc.png 1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/frisians/ferry_yard/unoccupied_0_pc.png 2019-06-11 08:19:26 +0000 differ
1178=== modified file 'data/tribes/buildings/productionsites/frisians/shipyard/init.lua'
1179--- data/tribes/buildings/productionsites/frisians/shipyard/init.lua 2019-05-29 18:29:28 +0000
1180+++ data/tribes/buildings/productionsites/frisians/shipyard/init.lua 2019-06-11 08:19:26 +0000
1181@@ -8,7 +8,7 @@
1182 helptext_script = dirname .. "helptexts.lua",
1183 icon = dirname .. "menu.png",
1184 size = "medium",
1185- needs_seafaring = true,
1186+ map_check = {"seafaring"},
1187
1188 buildcost = {
1189 brick = 3,
1190
1191=== modified file 'data/tribes/buildings/productionsites/frisians/weaving_mill/init.lua'
1192--- data/tribes/buildings/productionsites/frisians/weaving_mill/init.lua 2019-05-29 18:29:28 +0000
1193+++ data/tribes/buildings/productionsites/frisians/weaving_mill/init.lua 2019-06-11 08:19:26 +0000
1194@@ -8,7 +8,7 @@
1195 helptext_script = dirname .. "helptexts.lua",
1196 icon = dirname .. "menu.png",
1197 size = "medium",
1198- needs_seafaring = true,
1199+ map_check = {"seafaring", "waterways"},
1200
1201 buildcost = {
1202 brick = 4,
1203
1204=== modified file 'data/tribes/buildings/warehouses/atlanteans/port/init.lua'
1205--- data/tribes/buildings/warehouses/atlanteans/port/init.lua 2018-04-07 08:53:42 +0000
1206+++ data/tribes/buildings/warehouses/atlanteans/port/init.lua 2019-06-11 08:19:26 +0000
1207@@ -8,7 +8,7 @@
1208 helptext_script = dirname .. "helptexts.lua",
1209 icon = dirname .. "menu.png",
1210 size = "port",
1211- needs_seafaring = true,
1212+ map_check = {"seafaring"},
1213
1214 buildcost = {
1215 log = 3,
1216
1217=== modified file 'data/tribes/buildings/warehouses/barbarians/port/init.lua'
1218--- data/tribes/buildings/warehouses/barbarians/port/init.lua 2019-05-19 11:25:28 +0000
1219+++ data/tribes/buildings/warehouses/barbarians/port/init.lua 2019-06-11 08:19:26 +0000
1220@@ -8,7 +8,7 @@
1221 helptext_script = dirname .. "helptexts.lua",
1222 icon = dirname .. "menu.png",
1223 size = "port",
1224- needs_seafaring = true,
1225+ map_check = {"seafaring"},
1226
1227 buildcost = {
1228 log = 3,
1229
1230=== modified file 'data/tribes/buildings/warehouses/empire/port/init.lua'
1231--- data/tribes/buildings/warehouses/empire/port/init.lua 2018-04-07 08:53:42 +0000
1232+++ data/tribes/buildings/warehouses/empire/port/init.lua 2019-06-11 08:19:26 +0000
1233@@ -8,7 +8,7 @@
1234 helptext_script = dirname .. "helptexts.lua",
1235 icon = dirname .. "menu.png",
1236 size = "port",
1237- needs_seafaring = true,
1238+ map_check = {"seafaring"},
1239
1240 buildcost = {
1241 log = 3,
1242
1243=== modified file 'data/tribes/buildings/warehouses/frisians/port/init.lua'
1244--- data/tribes/buildings/warehouses/frisians/port/init.lua 2019-05-19 11:25:28 +0000
1245+++ data/tribes/buildings/warehouses/frisians/port/init.lua 2019-06-11 08:19:26 +0000
1246@@ -8,7 +8,7 @@
1247 helptext_script = dirname .. "helptexts.lua",
1248 icon = dirname .. "menu.png",
1249 size = "port",
1250- needs_seafaring = true,
1251+ map_check = {"seafaring"},
1252
1253 buildcost = {
1254 brick = 6,
1255
1256=== modified file 'data/tribes/empire.lua'
1257--- data/tribes/empire.lua 2019-05-26 01:46:18 +0000
1258+++ data/tribes/empire.lua 2019-06-11 08:19:26 +0000
1259@@ -8,7 +8,7 @@
1260 name = "empire",
1261 animations = animations,
1262
1263- -- Image file paths for this tribe's road textures
1264+ -- Image file paths for this tribe's road and waterway textures
1265 roads = {
1266 busy = {
1267 image_dirname .. "roadt_busy.png",
1268@@ -18,6 +18,9 @@
1269 image_dirname .. "roadt_normal_01.png",
1270 image_dirname .. "roadt_normal_02.png",
1271 },
1272+ waterway = {
1273+ "tribes/images/empire/waterway_0.png",
1274+ },
1275 },
1276
1277 resource_indicators = {
1278@@ -116,6 +119,7 @@
1279 {
1280 -- Carriers
1281 "empire_carrier",
1282+ "empire_ferry",
1283 "empire_donkey",
1284 "empire_donkeybreeder"
1285 },
1286@@ -224,6 +228,7 @@
1287 "empire_toolsmithy",
1288 "empire_armorsmithy",
1289 "empire_shipyard",
1290+ "empire_ferry_yard",
1291 "empire_barracks",
1292
1293 -- Big
1294@@ -340,6 +345,7 @@
1295 geologist = "empire_geologist",
1296 soldier = "empire_soldier",
1297 ship = "empire_ship",
1298+ ferry = "empire_ferry",
1299 port = "empire_port",
1300 ironore = "iron_ore",
1301 rawlog = "log",
1302
1303=== modified file 'data/tribes/frisians.lua'
1304--- data/tribes/frisians.lua 2019-05-26 01:46:18 +0000
1305+++ data/tribes/frisians.lua 2019-06-11 08:19:26 +0000
1306@@ -8,7 +8,7 @@
1307 name = "frisians",
1308 animations = animations,
1309
1310- -- Image file paths for this tribe's road textures
1311+ -- Image file paths for this tribe's road and waterway textures
1312 roads = {
1313 busy = {
1314 image_dirname .. "roadt_busy.png",
1315@@ -17,6 +17,9 @@
1316 image_dirname .. "roadt_normal_00.png",
1317 image_dirname .. "roadt_normal_01.png",
1318 },
1319+ waterway = {
1320+ "tribes/images/frisians/waterway_0.png",
1321+ },
1322 },
1323
1324 resource_indicators = {
1325@@ -122,6 +125,7 @@
1326 {
1327 -- Carriers
1328 "frisians_carrier",
1329+ "frisians_ferry",
1330 "frisians_reindeer",
1331 "frisians_reindeer_breeder"
1332 },
1333@@ -280,6 +284,7 @@
1334 "frisians_barracks",
1335 "frisians_weaving_mill",
1336 "frisians_shipyard",
1337+ "frisians_ferry_yard",
1338
1339 -- Big
1340 "frisians_reindeer_farm",
1341@@ -341,6 +346,7 @@
1342 geologist = "frisians_geologist",
1343 soldier = "frisians_soldier",
1344 ship = "frisians_ship",
1345+ ferry = "frisians_ferry",
1346 port = "frisians_port",
1347 ironore = "iron_ore",
1348 rawlog = "log",
1349
1350=== added file 'data/tribes/images/atlanteans/waterway_0.png'
1351Binary files data/tribes/images/atlanteans/waterway_0.png 1970-01-01 00:00:00 +0000 and data/tribes/images/atlanteans/waterway_0.png 2019-06-11 08:19:26 +0000 differ
1352=== added file 'data/tribes/images/barbarians/waterway_0.png'
1353Binary files data/tribes/images/barbarians/waterway_0.png 1970-01-01 00:00:00 +0000 and data/tribes/images/barbarians/waterway_0.png 2019-06-11 08:19:26 +0000 differ
1354=== added file 'data/tribes/images/empire/waterway_0.png'
1355Binary files data/tribes/images/empire/waterway_0.png 1970-01-01 00:00:00 +0000 and data/tribes/images/empire/waterway_0.png 2019-06-11 08:19:26 +0000 differ
1356=== added file 'data/tribes/images/frisians/waterway_0.png'
1357Binary files data/tribes/images/frisians/waterway_0.png 1970-01-01 00:00:00 +0000 and data/tribes/images/frisians/waterway_0.png 2019-06-11 08:19:26 +0000 differ
1358=== modified file 'data/tribes/init.lua'
1359--- data/tribes/init.lua 2019-05-19 11:25:28 +0000
1360+++ data/tribes/init.lua 2019-06-11 08:19:26 +0000
1361@@ -208,6 +208,7 @@
1362
1363 print_loading_message("┃ Workers", function()
1364 include "tribes/workers/atlanteans/carrier/init.lua"
1365+ include "tribes/workers/atlanteans/ferry/init.lua"
1366 include "tribes/workers/atlanteans/armorsmith/init.lua"
1367 include "tribes/workers/atlanteans/baker/init.lua"
1368 include "tribes/workers/atlanteans/blackroot_farmer/init.lua"
1369@@ -239,6 +240,7 @@
1370 include "tribes/workers/atlanteans/woodcutter/init.lua"
1371
1372 include "tribes/workers/barbarians/carrier/init.lua"
1373+ include "tribes/workers/barbarians/ferry/init.lua"
1374 include "tribes/workers/barbarians/baker/init.lua"
1375 include "tribes/workers/barbarians/blacksmith_master/init.lua"
1376 include "tribes/workers/barbarians/blacksmith/init.lua"
1377@@ -272,6 +274,7 @@
1378 include "tribes/workers/barbarians/weaver/init.lua"
1379
1380 include "tribes/workers/empire/carrier/init.lua"
1381+ include "tribes/workers/empire/ferry/init.lua"
1382 include "tribes/workers/empire/armorsmith/init.lua"
1383 include "tribes/workers/empire/baker/init.lua"
1384 include "tribes/workers/empire/brewer/init.lua"
1385@@ -306,6 +309,7 @@
1386 include "tribes/workers/empire/weaver/init.lua"
1387
1388 include "tribes/workers/frisians/carrier/init.lua"
1389+ include "tribes/workers/frisians/ferry/init.lua"
1390 include "tribes/workers/frisians/reindeer/init.lua"
1391 include "tribes/workers/frisians/builder/init.lua"
1392 include "tribes/workers/frisians/soldier/init.lua"
1393@@ -385,6 +389,7 @@
1394 include "tribes/buildings/productionsites/atlanteans/bakery/init.lua"
1395 include "tribes/buildings/productionsites/atlanteans/charcoal_kiln/init.lua"
1396 include "tribes/buildings/productionsites/atlanteans/smelting_works/init.lua"
1397+ include "tribes/buildings/productionsites/atlanteans/ferry_yard/init.lua"
1398 include "tribes/buildings/productionsites/atlanteans/shipyard/init.lua"
1399 include "tribes/buildings/productionsites/atlanteans/toolsmithy/init.lua"
1400 include "tribes/buildings/productionsites/atlanteans/weaponsmithy/init.lua"
1401@@ -424,6 +429,7 @@
1402 include "tribes/buildings/productionsites/barbarians/tavern/init.lua"
1403 include "tribes/buildings/productionsites/barbarians/charcoal_kiln/init.lua"
1404 include "tribes/buildings/productionsites/barbarians/smelting_works/init.lua"
1405+ include "tribes/buildings/productionsites/barbarians/ferry_yard/init.lua"
1406 include "tribes/buildings/productionsites/barbarians/shipyard/init.lua"
1407 include "tribes/buildings/productionsites/barbarians/warmill/init.lua"
1408 include "tribes/buildings/productionsites/barbarians/ax_workshop/init.lua"
1409@@ -466,6 +472,7 @@
1410 include "tribes/buildings/productionsites/empire/tavern/init.lua"
1411 include "tribes/buildings/productionsites/empire/charcoal_kiln/init.lua"
1412 include "tribes/buildings/productionsites/empire/smelting_works/init.lua"
1413+ include "tribes/buildings/productionsites/empire/ferry_yard/init.lua"
1414 include "tribes/buildings/productionsites/empire/shipyard/init.lua"
1415 include "tribes/buildings/productionsites/empire/toolsmithy/init.lua"
1416 include "tribes/buildings/productionsites/empire/armorsmithy/init.lua"
1417@@ -523,6 +530,7 @@
1418 include "tribes/buildings/productionsites/frisians/brewery/init.lua"
1419 include "tribes/buildings/productionsites/frisians/weaving_mill/init.lua"
1420 include "tribes/buildings/productionsites/frisians/smokery/init.lua"
1421+ include "tribes/buildings/productionsites/frisians/ferry_yard/init.lua"
1422 include "tribes/buildings/productionsites/frisians/shipyard/init.lua"
1423 include "tribes/buildings/productionsites/frisians/furnace/init.lua"
1424 include "tribes/buildings/productionsites/frisians/recycling_center/init.lua"
1425
1426=== added directory 'data/tribes/workers/atlanteans/ferry'
1427=== added file 'data/tribes/workers/atlanteans/ferry/helptexts.lua'
1428--- data/tribes/workers/atlanteans/ferry/helptexts.lua 1970-01-01 00:00:00 +0000
1429+++ data/tribes/workers/atlanteans/ferry/helptexts.lua 2019-06-11 08:19:26 +0000
1430@@ -0,0 +1,4 @@
1431+function worker_helptext()
1432+ -- TRANSLATORS: Helptext for a worker: Ferry
1433+ return pgettext("frisians_worker", "Ships wares across narrow rivers.")
1434+end
1435
1436=== added file 'data/tribes/workers/atlanteans/ferry/idle_00.png'
1437Binary files data/tribes/workers/atlanteans/ferry/idle_00.png 1970-01-01 00:00:00 +0000 and data/tribes/workers/atlanteans/ferry/idle_00.png 2019-06-11 08:19:26 +0000 differ
1438=== added file 'data/tribes/workers/atlanteans/ferry/init.lua'
1439--- data/tribes/workers/atlanteans/ferry/init.lua 1970-01-01 00:00:00 +0000
1440+++ data/tribes/workers/atlanteans/ferry/init.lua 2019-06-11 08:19:26 +0000
1441@@ -0,0 +1,34 @@
1442+dirname = path.dirname (__file__)
1443+
1444+-- TODO(Nordfriese): Make animations
1445+animations = {
1446+ pictures = path.list_files (dirname .. "idle_??.png"),
1447+ hotspot = {22, 21},
1448+}
1449+animations = {
1450+ idle = animations,
1451+ walk_se = animations,
1452+ walk_sw = animations,
1453+ walk_ne = animations,
1454+ walk_nw = animations,
1455+ walk_e = animations,
1456+ walk_w = animations,
1457+ walkload_se = animations,
1458+ walkload_sw = animations,
1459+ walkload_ne = animations,
1460+ walkload_nw = animations,
1461+ walkload_e = animations,
1462+ walkload_w = animations,
1463+}
1464+
1465+tribes:new_ferry_type {
1466+ msgctxt = "atlanteans_worker",
1467+ name = "atlanteans_ferry",
1468+ -- TRANSLATORS: This is a worker name used in lists of workers
1469+ descname = pgettext ("atlanteans_worker", "Ferry"),
1470+ helptext_script = dirname .. "helptexts.lua",
1471+ icon = dirname .. "menu.png",
1472+ vision_range = 2,
1473+
1474+ animations = animations,
1475+}
1476
1477=== added file 'data/tribes/workers/atlanteans/ferry/menu.png'
1478Binary files data/tribes/workers/atlanteans/ferry/menu.png 1970-01-01 00:00:00 +0000 and data/tribes/workers/atlanteans/ferry/menu.png 2019-06-11 08:19:26 +0000 differ
1479=== modified file 'data/tribes/workers/atlanteans/shipwright/init.lua'
1480--- data/tribes/workers/atlanteans/shipwright/init.lua 2019-04-21 14:57:55 +0000
1481+++ data/tribes/workers/atlanteans/shipwright/init.lua 2019-06-11 08:19:26 +0000
1482@@ -38,7 +38,13 @@
1483 "construct",
1484 "animate=idle 5000",
1485 "return"
1486- }
1487+ },
1488+ buildferry = {
1489+ "findspace=size:swim radius:4",
1490+ "walk=coords",
1491+ "buildferry",
1492+ "return"
1493+ },
1494 },
1495
1496 animations = animations,
1497
1498=== added directory 'data/tribes/workers/barbarians/ferry'
1499=== added file 'data/tribes/workers/barbarians/ferry/helptexts.lua'
1500--- data/tribes/workers/barbarians/ferry/helptexts.lua 1970-01-01 00:00:00 +0000
1501+++ data/tribes/workers/barbarians/ferry/helptexts.lua 2019-06-11 08:19:26 +0000
1502@@ -0,0 +1,4 @@
1503+function worker_helptext()
1504+ -- TRANSLATORS: Helptext for a worker: Ferry
1505+ return pgettext("frisians_worker", "Ships wares across narrow rivers.")
1506+end
1507
1508=== added file 'data/tribes/workers/barbarians/ferry/idle_00.png'
1509Binary files data/tribes/workers/barbarians/ferry/idle_00.png 1970-01-01 00:00:00 +0000 and data/tribes/workers/barbarians/ferry/idle_00.png 2019-06-11 08:19:26 +0000 differ
1510=== added file 'data/tribes/workers/barbarians/ferry/init.lua'
1511--- data/tribes/workers/barbarians/ferry/init.lua 1970-01-01 00:00:00 +0000
1512+++ data/tribes/workers/barbarians/ferry/init.lua 2019-06-11 08:19:26 +0000
1513@@ -0,0 +1,34 @@
1514+dirname = path.dirname (__file__)
1515+
1516+-- TODO(Nordfriese): Make animations
1517+animations = {
1518+ pictures = path.list_files (dirname .. "idle_??.png"),
1519+ hotspot = {29, 19},
1520+}
1521+animations = {
1522+ idle = animations,
1523+ walk_se = animations,
1524+ walk_sw = animations,
1525+ walk_ne = animations,
1526+ walk_nw = animations,
1527+ walk_e = animations,
1528+ walk_w = animations,
1529+ walkload_se = animations,
1530+ walkload_sw = animations,
1531+ walkload_ne = animations,
1532+ walkload_nw = animations,
1533+ walkload_e = animations,
1534+ walkload_w = animations,
1535+}
1536+
1537+tribes:new_ferry_type {
1538+ msgctxt = "barbarians_worker",
1539+ name = "barbarians_ferry",
1540+ -- TRANSLATORS: This is a worker name used in lists of workers
1541+ descname = pgettext ("barbarians_worker", "Ferry"),
1542+ helptext_script = dirname .. "helptexts.lua",
1543+ icon = dirname .. "menu.png",
1544+ vision_range = 2,
1545+
1546+ animations = animations,
1547+}
1548
1549=== added file 'data/tribes/workers/barbarians/ferry/menu.png'
1550Binary files data/tribes/workers/barbarians/ferry/menu.png 1970-01-01 00:00:00 +0000 and data/tribes/workers/barbarians/ferry/menu.png 2019-06-11 08:19:26 +0000 differ
1551=== modified file 'data/tribes/workers/barbarians/shipwright/init.lua'
1552--- data/tribes/workers/barbarians/shipwright/init.lua 2019-04-28 09:14:59 +0000
1553+++ data/tribes/workers/barbarians/shipwright/init.lua 2019-06-11 08:19:26 +0000
1554@@ -34,7 +34,13 @@
1555 "construct",
1556 "animate=work 5000",
1557 "return"
1558- }
1559+ },
1560+ buildferry = {
1561+ "findspace=size:swim radius:4",
1562+ "walk=coords",
1563+ "buildferry",
1564+ "return"
1565+ },
1566 },
1567
1568 animations = animations,
1569
1570=== added directory 'data/tribes/workers/empire/ferry'
1571=== added file 'data/tribes/workers/empire/ferry/helptexts.lua'
1572--- data/tribes/workers/empire/ferry/helptexts.lua 1970-01-01 00:00:00 +0000
1573+++ data/tribes/workers/empire/ferry/helptexts.lua 2019-06-11 08:19:26 +0000
1574@@ -0,0 +1,4 @@
1575+function worker_helptext()
1576+ -- TRANSLATORS: Helptext for a worker: Ferry
1577+ return pgettext("frisians_worker", "Ships wares across narrow rivers.")
1578+end
1579
1580=== added file 'data/tribes/workers/empire/ferry/idle_00.png'
1581Binary files data/tribes/workers/empire/ferry/idle_00.png 1970-01-01 00:00:00 +0000 and data/tribes/workers/empire/ferry/idle_00.png 2019-06-11 08:19:26 +0000 differ
1582=== added file 'data/tribes/workers/empire/ferry/init.lua'
1583--- data/tribes/workers/empire/ferry/init.lua 1970-01-01 00:00:00 +0000
1584+++ data/tribes/workers/empire/ferry/init.lua 2019-06-11 08:19:26 +0000
1585@@ -0,0 +1,34 @@
1586+dirname = path.dirname (__file__)
1587+
1588+-- TODO(Nordfriese): Make animations
1589+animations = {
1590+ pictures = path.list_files (dirname .. "idle_??.png"),
1591+ hotspot = {29, 25},
1592+}
1593+animations = {
1594+ idle = animations,
1595+ walk_se = animations,
1596+ walk_sw = animations,
1597+ walk_ne = animations,
1598+ walk_nw = animations,
1599+ walk_e = animations,
1600+ walk_w = animations,
1601+ walkload_se = animations,
1602+ walkload_sw = animations,
1603+ walkload_ne = animations,
1604+ walkload_nw = animations,
1605+ walkload_e = animations,
1606+ walkload_w = animations,
1607+}
1608+
1609+tribes:new_ferry_type {
1610+ msgctxt = "empire_worker",
1611+ name = "empire_ferry",
1612+ -- TRANSLATORS: This is a worker name used in lists of workers
1613+ descname = pgettext ("empire_worker", "Ferry"),
1614+ helptext_script = dirname .. "helptexts.lua",
1615+ icon = dirname .. "menu.png",
1616+ vision_range = 2,
1617+
1618+ animations = animations,
1619+}
1620
1621=== added file 'data/tribes/workers/empire/ferry/menu.png'
1622Binary files data/tribes/workers/empire/ferry/menu.png 1970-01-01 00:00:00 +0000 and data/tribes/workers/empire/ferry/menu.png 2019-06-11 08:19:26 +0000 differ
1623=== modified file 'data/tribes/workers/empire/shipwright/init.lua'
1624--- data/tribes/workers/empire/shipwright/init.lua 2019-04-21 14:57:55 +0000
1625+++ data/tribes/workers/empire/shipwright/init.lua 2019-06-11 08:19:26 +0000
1626@@ -42,7 +42,13 @@
1627 "construct",
1628 "animate=work 5000",
1629 "return"
1630- }
1631+ },
1632+ buildferry = {
1633+ "findspace=size:swim radius:4",
1634+ "walk=coords",
1635+ "buildferry",
1636+ "return"
1637+ },
1638 },
1639
1640 animations = animations,
1641
1642=== added directory 'data/tribes/workers/frisians/ferry'
1643=== added file 'data/tribes/workers/frisians/ferry/helptexts.lua'
1644--- data/tribes/workers/frisians/ferry/helptexts.lua 1970-01-01 00:00:00 +0000
1645+++ data/tribes/workers/frisians/ferry/helptexts.lua 2019-06-11 08:19:26 +0000
1646@@ -0,0 +1,4 @@
1647+function worker_helptext()
1648+ -- TRANSLATORS: Helptext for a worker: Ferry
1649+ return pgettext("frisians_worker", "Ships wares across narrow rivers.")
1650+end
1651
1652=== added file 'data/tribes/workers/frisians/ferry/idle_00.png'
1653Binary files data/tribes/workers/frisians/ferry/idle_00.png 1970-01-01 00:00:00 +0000 and data/tribes/workers/frisians/ferry/idle_00.png 2019-06-11 08:19:26 +0000 differ
1654=== added file 'data/tribes/workers/frisians/ferry/init.lua'
1655--- data/tribes/workers/frisians/ferry/init.lua 1970-01-01 00:00:00 +0000
1656+++ data/tribes/workers/frisians/ferry/init.lua 2019-06-11 08:19:26 +0000
1657@@ -0,0 +1,34 @@
1658+dirname = path.dirname (__file__)
1659+
1660+-- TODO(Nordfriese): Make animations
1661+animations = {
1662+ pictures = path.list_files (dirname .. "idle_??.png"),
1663+ hotspot = {20, 36},
1664+}
1665+animations = {
1666+ idle = animations,
1667+ walk_se = animations,
1668+ walk_sw = animations,
1669+ walk_ne = animations,
1670+ walk_nw = animations,
1671+ walk_e = animations,
1672+ walk_w = animations,
1673+ walkload_se = animations,
1674+ walkload_sw = animations,
1675+ walkload_ne = animations,
1676+ walkload_nw = animations,
1677+ walkload_e = animations,
1678+ walkload_w = animations,
1679+}
1680+
1681+tribes:new_ferry_type {
1682+ msgctxt = "frisians_worker",
1683+ name = "frisians_ferry",
1684+ -- TRANSLATORS: This is a worker name used in lists of workers
1685+ descname = pgettext ("frisians_worker", "Ferry"),
1686+ helptext_script = dirname .. "helptexts.lua",
1687+ icon = dirname .. "menu.png",
1688+ vision_range = 2,
1689+
1690+ animations = animations,
1691+}
1692
1693=== added file 'data/tribes/workers/frisians/ferry/menu.png'
1694Binary files data/tribes/workers/frisians/ferry/menu.png 1970-01-01 00:00:00 +0000 and data/tribes/workers/frisians/ferry/menu.png 2019-06-11 08:19:26 +0000 differ
1695=== modified file 'data/tribes/workers/frisians/shipwright/init.lua'
1696--- data/tribes/workers/frisians/shipwright/init.lua 2019-04-21 14:57:55 +0000
1697+++ data/tribes/workers/frisians/shipwright/init.lua 2019-06-11 08:19:26 +0000
1698@@ -40,7 +40,13 @@
1699 "construct",
1700 "animate=work 5000",
1701 "return"
1702- }
1703+ },
1704+ buildferry = {
1705+ "findspace=size:swim radius:4",
1706+ "walk=coords",
1707+ "buildferry",
1708+ "return"
1709+ },
1710 },
1711
1712 ware_hotspot = {0, 20},
1713
1714=== modified file 'src/ai/ai_help_structs.h'
1715--- src/ai/ai_help_structs.h 2019-05-25 08:20:22 +0000
1716+++ src/ai/ai_help_structs.h 2019-06-11 08:19:26 +0000
1717@@ -78,6 +78,7 @@
1718 kUpgradeExtends,
1719 kLogRefiner,
1720 kIronMine,
1721+ // TODO(Nordfriese): Someone should update the AI code to handle buildings that need waterways enabled
1722 kNeedsSeafaring,
1723 kSupportingProducer,
1724 kNeedsBerry,
1725
1726=== modified file 'src/ai/defaultai.cc'
1727--- src/ai/defaultai.cc 2019-05-26 11:39:41 +0000
1728+++ src/ai/defaultai.cc 2019-06-11 08:19:26 +0000
1729@@ -1689,7 +1689,8 @@
1730 assert(building->owner().player_number() == pn);
1731
1732 // connected to a warehouse
1733- bool connected = !building->get_economy()->warehouses().empty();
1734+ // TODO(Nordfriese): Someone should update the code since the big economy splitting for the ferries
1735+ bool connected = !building->get_economy(wwWORKER)->warehouses().empty();
1736 if (connected) {
1737 any_connected_imm = true;
1738 }
1739@@ -2047,8 +2048,9 @@
1740 for (uint32_t i = 0; i < productionsites.size(); ++i) {
1741 assert(productionsites.front().bo->cnt_built > 0);
1742 // is connected
1743+ // TODO(Nordfriese): Someone should update the code since the big economy splitting for the ferries
1744 const bool connected_to_wh =
1745- !productionsites.front().site->get_economy()->warehouses().empty();
1746+ !productionsites.front().site->get_economy(wwWORKER)->warehouses().empty();
1747
1748 // unconnected buildings are excluded from statistics review
1749 if (connected_to_wh) {
1750@@ -2074,7 +2076,7 @@
1751 for (uint32_t i = 0; i < mines_.size(); ++i) {
1752 assert(mines_.front().bo->cnt_built > 0);
1753
1754- const bool connected_to_wh = !mines_.front().site->get_economy()->warehouses().empty();
1755+ const bool connected_to_wh = !mines_.front().site->get_economy(wwWORKER)->warehouses().empty();
1756
1757 // unconnected mines are excluded from statistics review
1758 if (connected_to_wh) {
1759@@ -3428,8 +3430,8 @@
1760 const uint16_t stepping = roads.size() / 25 + 1;
1761
1762 for (uint16_t i = 0; i < roads.size(); i += stepping) {
1763- const Flag& roadstartflag = roads[i]->get_flag(Road::FlagStart);
1764- const Flag& roadendflag = roads[i]->get_flag(Road::FlagEnd);
1765+ const Flag& roadstartflag = roads[i]->get_flag(RoadBase::FlagStart);
1766+ const Flag& roadendflag = roads[i]->get_flag(RoadBase::FlagEnd);
1767
1768 if (!roadstartflag.get_building() && roadstartflag.is_dead_end()) {
1769 game().send_player_bulldoze(*const_cast<Flag*>(&roadstartflag));
1770@@ -3548,7 +3550,8 @@
1771 }
1772
1773 // is connected to a warehouse?
1774- const bool needs_warehouse = flag.get_economy()->warehouses().empty();
1775+ // TODO(Nordfriese): Someone should update the code since the big economy splitting for the ferries
1776+ const bool needs_warehouse = flag.get_economy(wwWORKER)->warehouses().empty();
1777
1778 if (!has_building && flag.nr_of_roads() == 1) {
1779 return false;
1780@@ -3591,8 +3594,8 @@
1781 // the road can be dismantled
1782 bool DefaultAI::dispensable_road_test(const Widelands::Road& road) {
1783
1784- Flag& roadstartflag = road.get_flag(Road::FlagStart);
1785- Flag& roadendflag = road.get_flag(Road::FlagEnd);
1786+ Flag& roadstartflag = road.get_flag(RoadBase::FlagStart);
1787+ Flag& roadendflag = road.get_flag(RoadBase::FlagEnd);
1788
1789 // Calculating full road (from crossing/building to another crossing/building),
1790 // this means we calculate vector of all flags of the "full road"
1791@@ -3615,11 +3618,11 @@
1792 }
1793
1794 Flag* other_end;
1795- if (near_road->get_flag(Road::FlagStart).get_position().hash() ==
1796+ if (near_road->get_flag(RoadBase::FlagStart).get_position().hash() ==
1797 full_road.back()->get_position().hash()) {
1798- other_end = &near_road->get_flag(Road::FlagEnd);
1799+ other_end = &near_road->get_flag(RoadBase::FlagEnd);
1800 } else {
1801- other_end = &near_road->get_flag(Road::FlagStart);
1802+ other_end = &near_road->get_flag(RoadBase::FlagStart);
1803 }
1804
1805 // Have we already the end of road in our full_road?
1806@@ -3714,10 +3717,10 @@
1807 continue;
1808 }
1809
1810- Flag* endflag = &near_road->get_flag(Road::FlagStart);
1811+ Flag* endflag = &near_road->get_flag(RoadBase::FlagStart);
1812
1813 if (endflag == nf.flag) {
1814- endflag = &near_road->get_flag(Road::FlagEnd);
1815+ endflag = &near_road->get_flag(RoadBase::FlagEnd);
1816 }
1817
1818 // When walking on nearby roads, we do not go too far from start and end of road
1819@@ -3761,14 +3764,15 @@
1820
1821 // Increasing the failed_connection_tries counter
1822 // At the same time it indicates a time an economy is without a warehouse
1823- EconomyObserver* eco = get_economy_observer(flag.economy());
1824+ // TODO(Nordfriese): Someone should update the code since the big economy splitting for the ferries
1825+ EconomyObserver* eco = get_economy_observer(flag.economy(wwWORKER));
1826 // if we passed grace time this will be last attempt and if it fails
1827 // building is destroyes
1828 bool last_attempt_ = false;
1829
1830 // this should not happen, but if the economy has a warehouse and a dismantle
1831 // grace time set, we must 'zero' the dismantle grace time
1832- if (!flag.get_economy()->warehouses().empty() &&
1833+ if (!flag.get_economy(wwWORKER)->warehouses().empty() &&
1834 eco->dismantle_grace_time != std::numeric_limits<uint32_t>::max()) {
1835 eco->dismantle_grace_time = std::numeric_limits<uint32_t>::max();
1836 }
1837@@ -3777,7 +3781,7 @@
1838 // and this is a flag belonging to a building/constructionsite
1839 // such economy must get dismantle grace time (if not set yet)
1840 // end sometimes extended checkradius
1841- if (flag.get_economy()->warehouses().empty() && flag.get_building()) {
1842+ if (flag.get_economy(wwWORKER)->warehouses().empty() && flag.get_building()) {
1843
1844 // occupied military buildings get special treatment
1845 // (extended grace time + longer radius)
1846@@ -3876,12 +3880,13 @@
1847
1848 // testing if a flag/road's economy has a warehouse, if not we are not
1849 // interested to connect to it
1850- if (player_immovable->economy().warehouses().size() == 0) {
1851+ // TODO(Nordfriese): Someone should update the code since the big economy splitting for the ferries
1852+ if (player_immovable->economy(wwWORKER).warehouses().size() == 0) {
1853 continue;
1854 }
1855
1856 // This is a candidate, sending all necessary info to RoadCandidates
1857- const bool different_economy = (player_immovable->get_economy() != flag.get_economy());
1858+ const bool different_economy = (player_immovable->get_economy(wwWORKER) != flag.get_economy(wwWORKER));
1859 const int32_t air_distance = map.calc_distance(flag.get_position(), reachable_coords);
1860 if (!RoadCandidates.has_candidate(reachable_coords.hash())) {
1861 RoadCandidates.add_flag(reachable_coords, air_distance, different_economy);
1862@@ -3926,10 +3931,10 @@
1863 continue;
1864 }
1865
1866- Flag* endflag = &road->get_flag(Road::FlagStart);
1867+ Flag* endflag = &road->get_flag(RoadBase::FlagStart);
1868
1869 if (endflag == nearflags[start_field].flag) {
1870- endflag = &road->get_flag(Road::FlagEnd);
1871+ endflag = &road->get_flag(RoadBase::FlagEnd);
1872 }
1873
1874 const uint32_t endflag_hash = endflag->get_position().hash();
1875@@ -4038,7 +4043,8 @@
1876 // Usually we block for 2 minutes, but if it is a last attempt we block for 10 minutes
1877 // Note: we block the vicinity only if this economy (usually a sole flag with a building) is not
1878 // connected to a warehouse
1879- if (flag.get_economy()->warehouses().empty()) {
1880+ // TODO(Nordfriese): Someone should update the code since the big economy splitting for the ferries
1881+ if (flag.get_economy(wwWORKER)->warehouses().empty()) {
1882
1883 // blocking only if latest block was less then 60 seconds ago or it is last attempt
1884 if (eco->fields_block_last_time + 60000 < gametime || last_attempt_) {
1885@@ -4080,7 +4086,8 @@
1886 while (!new_flags.empty()) {
1887 const Flag& flag = *new_flags.front();
1888 new_flags.pop_front();
1889- get_economy_observer(flag.economy())->flags.push_back(&flag);
1890+ // TODO(Nordfriese): Someone must urgently update the code since the big economy splitting for the ferries
1891+ get_economy_observer(flag.economy(wwWORKER))->flags.push_back(&flag);
1892 }
1893
1894 for (std::deque<EconomyObserver*>::iterator obs_iter = economies.begin();
1895@@ -4089,9 +4096,9 @@
1896 std::deque<Flag const*>& fl = (*obs_iter)->flags;
1897
1898 for (std::deque<Flag const*>::iterator j = fl.begin(); j != fl.end();) {
1899- if (&(*obs_iter)->economy != &(*j)->economy()) {
1900+ if (&(*obs_iter)->economy != &(*j)->economy(wwWORKER)) {
1901 // the flag belongs to other economy so we must assign it there
1902- get_economy_observer((*j)->economy())->flags.push_back(*j);
1903+ get_economy_observer((*j)->economy(wwWORKER))->flags.push_back(*j);
1904 // and erase from this economy's observer
1905 j = fl.erase(j);
1906 } else {
1907@@ -4140,7 +4147,8 @@
1908 }
1909
1910 // is it connected to wh at all?
1911- const bool connected_to_wh = !site.site->get_economy()->warehouses().empty();
1912+ // TODO(Nordfriese): Someone should update the code since the big economy splitting for the ferries
1913+ const bool connected_to_wh = !site.site->get_economy(wwWORKER)->warehouses().empty();
1914
1915 // do not dismantle or upgrade the same type of building too soon - to give some time to update
1916 // statistics
1917@@ -4637,7 +4645,8 @@
1918 // Get link to productionsite that should be checked
1919 ProductionSiteObserver& site = mines_.front();
1920
1921- const bool connected_to_wh = !site.site->get_economy()->warehouses().empty();
1922+ // TODO(Nordfriese): Someone should update the code since the big economy splitting for the ferries
1923+ const bool connected_to_wh = !site.site->get_economy(wwWORKER)->warehouses().empty();
1924
1925 // First we dismantle mines that are marked as such, generally we wait till all wares all gone
1926 if (site.dismantle_pending_since != kNever) {
1927
1928=== modified file 'src/ai/defaultai_seafaring.cc'
1929--- src/ai/defaultai_seafaring.cc 2019-02-23 11:00:49 +0000
1930+++ src/ai/defaultai_seafaring.cc 2019-06-11 08:19:26 +0000
1931@@ -19,7 +19,7 @@
1932
1933 #include "ai/defaultai.h"
1934
1935-#include "economy/fleet.h"
1936+#include "economy/ship_fleet.h"
1937
1938 using namespace Widelands;
1939
1940
1941=== modified file 'src/economy/CMakeLists.txt'
1942--- src/economy/CMakeLists.txt 2019-05-05 18:53:14 +0000
1943+++ src/economy/CMakeLists.txt 2019-06-11 08:19:26 +0000
1944@@ -8,10 +8,10 @@
1945 economy_data_packet.h
1946 expedition_bootstrap.cc
1947 expedition_bootstrap.h
1948+ ferry_fleet.cc
1949+ ferry_fleet.h
1950 flag.cc
1951 flag.h
1952- fleet.cc
1953- fleet.h
1954 idleworkersupply.cc
1955 idleworkersupply.h
1956 iroute.h
1957@@ -20,6 +20,8 @@
1958 portdock.h
1959 request.cc
1960 request.h
1961+ roadbase.cc
1962+ roadbase.h
1963 road.cc
1964 road.h
1965 route.cc
1966@@ -29,6 +31,8 @@
1967 router.cc
1968 router.h
1969 routing_node.h
1970+ ship_fleet.cc
1971+ ship_fleet.h
1972 shippingitem.cc
1973 shippingitem.h
1974 supply.h
1975@@ -44,6 +48,8 @@
1976 input_queue.h
1977 wares_queue.cc
1978 wares_queue.h
1979+ waterway.cc
1980+ waterway.h
1981 workers_queue.cc
1982 workers_queue.h
1983 DEPENDS
1984
1985=== modified file 'src/economy/cmd_call_economy_balance.cc'
1986--- src/economy/cmd_call_economy_balance.cc 2019-02-23 11:00:49 +0000
1987+++ src/economy/cmd_call_economy_balance.cc 2019-06-11 08:19:26 +0000
1988@@ -34,8 +34,11 @@
1989 Economy* const economy,
1990 uint32_t const timerid)
1991 : GameLogicCommand(starttime) {
1992- flag_ = economy->get_arbitrary_flag();
1993+ Flag* flag = economy->get_arbitrary_flag();
1994+ flag_ = flag;
1995 timerid_ = timerid;
1996+ type_ = economy->type();
1997+ assert(flag->get_economy(type_) == economy);
1998 }
1999
2000 /**
2001@@ -44,10 +47,10 @@
2002 */
2003 void CmdCallEconomyBalance::execute(Game& game) {
2004 if (Flag* const flag = flag_.get(game))
2005- flag->get_economy()->balance(timerid_);
2006+ flag->get_economy(type_)->balance(timerid_);
2007 }
2008
2009-constexpr uint16_t kCurrentPacketVersion = 3;
2010+constexpr uint16_t kCurrentPacketVersion = 4;
2011
2012 /**
2013 * Read and write
2014@@ -61,6 +64,7 @@
2015 if (serial)
2016 flag_ = &mol.get<Flag>(serial);
2017 timerid_ = fr.unsigned_32();
2018+ type_ = fr.unsigned_8() ? wwWORKER : wwWARE;
2019 } else {
2020 throw UnhandledVersionError(
2021 "CmdCallEconomyBalance", packet_version, kCurrentPacketVersion);
2022@@ -79,5 +83,6 @@
2023 else
2024 fw.unsigned_32(0);
2025 fw.unsigned_32(timerid_);
2026+ fw.unsigned_8(type_);
2027 }
2028 } // namespace Widelands
2029
2030=== modified file 'src/economy/cmd_call_economy_balance.h'
2031--- src/economy/cmd_call_economy_balance.h 2019-02-23 11:00:49 +0000
2032+++ src/economy/cmd_call_economy_balance.h 2019-06-11 08:19:26 +0000
2033@@ -46,6 +46,7 @@
2034
2035 private:
2036 OPtr<Flag> flag_;
2037+ WareWorker type_;
2038 uint32_t timerid_;
2039 };
2040 } // namespace Widelands
2041
2042=== modified file 'src/economy/economy.cc'
2043--- src/economy/economy.cc 2019-04-09 16:43:49 +0000
2044+++ src/economy/economy.cc 2019-06-11 08:19:26 +0000
2045@@ -48,35 +48,34 @@
2046 last_economy_serial_ = 0;
2047 }
2048
2049-Economy::Economy(Player& player) : Economy(player, last_economy_serial_++) {
2050+Economy::Economy(Player& player, WareWorker wwtype) : Economy(player, last_economy_serial_++, wwtype) {
2051 }
2052
2053-Economy::Economy(Player& player, Serial init_serial)
2054- : serial_(init_serial), owner_(player), request_timerid_(0), has_window_(false) {
2055+Economy::Economy(Player& player, Serial init_serial, WareWorker wwtype)
2056+ : serial_(init_serial), owner_(player), type_(wwtype), request_timerid_(0), has_window_(false) {
2057 last_economy_serial_ = std::max(last_economy_serial_, serial_ + 1);
2058 const TribeDescr& tribe = player.tribe();
2059- DescriptionIndex const nr_wares = player.egbase().tribes().nrwares();
2060- DescriptionIndex const nr_workers = player.egbase().tribes().nrworkers();
2061- wares_.set_nrwares(nr_wares);
2062- workers_.set_nrwares(nr_workers);
2063+ DescriptionIndex const nr_wares_or_workers = wwtype == wwWARE ?
2064+ player.egbase().tribes().nrwares() : player.egbase().tribes().nrworkers();
2065+ wares_or_workers_.set_nrwares(nr_wares_or_workers);
2066
2067- ware_target_quantities_ = new TargetQuantity[nr_wares];
2068- for (DescriptionIndex i = 0; i < nr_wares; ++i) {
2069+ target_quantities_ = new TargetQuantity[nr_wares_or_workers];
2070+ for (DescriptionIndex i = 0; i < nr_wares_or_workers; ++i) {
2071 TargetQuantity tq;
2072- if (tribe.has_ware(i)) {
2073- tq.permanent = tribe.get_ware_descr(i)->default_target_quantity(tribe.name());
2074- } else {
2075- tq.permanent = 0;
2076+ switch (type_) {
2077+ case wwWARE:
2078+ if (tribe.has_ware(i)) {
2079+ tq.permanent = tribe.get_ware_descr(i)->default_target_quantity(tribe.name());
2080+ } else {
2081+ tq.permanent = 0;
2082+ }
2083+ break;
2084+ case wwWORKER:
2085+ tq.permanent = tribe.get_worker_descr(i)->default_target_quantity();
2086+ break;
2087 }
2088 tq.last_modified = 0;
2089- ware_target_quantities_[i] = tq;
2090- }
2091- worker_target_quantities_ = new TargetQuantity[nr_workers];
2092- for (DescriptionIndex i = 0; i < nr_workers; ++i) {
2093- TargetQuantity tq;
2094- tq.permanent = tribe.get_worker_descr(i)->default_target_quantity();
2095- tq.last_modified = 0;
2096- worker_target_quantities_[i] = tq;
2097+ target_quantities_[i] = tq;
2098 }
2099
2100 router_.reset(new Router(boost::bind(&Economy::reset_all_pathfinding_cycles, this)));
2101@@ -92,8 +91,7 @@
2102 if (warehouses_.size())
2103 log("Warning: Economy still has warehouses left on destruction\n");
2104
2105- delete[] ware_target_quantities_;
2106- delete[] worker_target_quantities_;
2107+ delete[] target_quantities_;
2108 }
2109
2110 /**
2111@@ -112,9 +110,9 @@
2112 * Since we could merge into both directions, we preserve the economy that is
2113 * currently bigger (should be more efficient).
2114 */
2115-void Economy::check_merge(Flag& f1, Flag& f2) {
2116- Economy* e1 = f1.get_economy();
2117- Economy* e2 = f2.get_economy();
2118+void Economy::check_merge(Flag& f1, Flag& f2, WareWorker type) {
2119+ Economy* e1 = f1.get_economy(type);
2120+ Economy* e2 = f2.get_economy(type);
2121 if (e1 != e2) {
2122 if (e1->get_nrflags() < e2->get_nrflags())
2123 std::swap(e1, e2);
2124@@ -126,11 +124,11 @@
2125 * Notify the economy that there may no longer be a connection between
2126 * the given flags in the road and seafaring network.
2127 */
2128-void Economy::check_split(Flag& f1, Flag& f2) {
2129+void Economy::check_split(Flag& f1, Flag& f2, WareWorker type) {
2130 assert(&f1 != &f2);
2131- assert(f1.get_economy() == f2.get_economy());
2132+ assert(f1.get_economy(type) == f2.get_economy(type));
2133
2134- Economy* e = f1.get_economy();
2135+ Economy* e = f1.get_economy(type);
2136 // No economy in the editor.
2137 if (!e)
2138 return;
2139@@ -151,22 +149,24 @@
2140 continue;
2141 if (!f1)
2142 f1 = f2;
2143- if (f1->get_economy() != this)
2144+ if (f1->get_economy(type_) != this)
2145 continue;
2146
2147 // Handle the case when two or more roads are removed simultaneously
2148- RouteAStar<AStarZeroEstimator> astar(*router_, wwWORKER, AStarZeroEstimator());
2149+ RouteAStar<AStarZeroEstimator> astar(*router_, type_, AStarZeroEstimator());
2150 astar.push(*f1);
2151 std::set<OPtr<Flag>> reachable;
2152- while (RoutingNode* current = astar.step())
2153+ while (RoutingNode* current = astar.step()) {
2154 reachable.insert(&current->base_flag());
2155- if (reachable.size() != flags_.size())
2156+ }
2157+ if (reachable.size() != flags_.size()) {
2158 split(reachable);
2159+ }
2160 continue;
2161 }
2162
2163 // If one (or both) of the flags have already been split off, we do not need to re-check
2164- if (f1->get_economy() != this || f2->get_economy() != this)
2165+ if (f1->get_economy(type_) != this || f2->get_economy(type_) != this)
2166 continue;
2167
2168 // Start an A-star searches from f1 with a heuristic bias towards f2,
2169@@ -176,7 +176,7 @@
2170 // This means that the newly created economy, which contains all the
2171 // flags that have been split, is already connected.
2172 RouteAStar<AStarEstimator> astar(
2173- *router_, wwWORKER, AStarEstimator(*egbase.mutable_map(), *f2));
2174+ *router_, type_, AStarEstimator(*egbase.mutable_map(), *f2));
2175 astar.push(*f1);
2176 std::set<OPtr<Flag>> reachable;
2177
2178@@ -185,8 +185,9 @@
2179 if (!current) {
2180 split(reachable);
2181 break;
2182- } else if (current == f2)
2183+ } else if (current == f2) {
2184 break;
2185+ }
2186 reachable.insert(&current->base_flag());
2187 }
2188 }
2189@@ -199,11 +200,11 @@
2190 * merely a delegator.
2191 */
2192 bool Economy::find_route(
2193- Flag& start, Flag& end, Route* const route, WareWorker const type, int32_t const cost_cutoff) {
2194- assert(start.get_economy() == this);
2195- assert(end.get_economy() == this);
2196+ Flag& start, Flag& end, Route* const route, int32_t const cost_cutoff) {
2197+ assert(start.get_economy(type_) == this);
2198+ assert(end.get_economy(type_) == this);
2199 return router_->find_route(
2200- start, end, route, type, cost_cutoff, *owner().egbase().mutable_map());
2201+ start, end, route, type_, cost_cutoff, *owner().egbase().mutable_map());
2202 }
2203
2204 struct ZeroEstimator {
2205@@ -219,13 +220,11 @@
2206 * a route is also computed.
2207 *
2208 * \param start starting flag
2209- * \param type whether to path-find as if the path were for a ware
2210 * \param route if non-null, fill in a route to the warehouse
2211 * \param cost_cutoff if positive, find paths of at most
2212 * that length (in milliseconds)
2213 */
2214 Warehouse* Economy::find_closest_warehouse(Flag& start,
2215- WareWorker type,
2216 Route* route,
2217 uint32_t cost_cutoff,
2218 const Economy::WarehouseAcceptFn& acceptfn) {
2219@@ -233,11 +232,12 @@
2220 return nullptr;
2221
2222 // A-star with zero estimator = Dijkstra
2223- RouteAStar<ZeroEstimator> astar(*router_, type);
2224+ RouteAStar<ZeroEstimator> astar(*router_, type_);
2225 astar.push(start);
2226
2227 while (RoutingNode* current = astar.step()) {
2228- if (cost_cutoff && current->mpf_realcost > static_cast<int32_t>(cost_cutoff))
2229+ if (cost_cutoff && (type_ == wwWARE ?
2230+ current->mpf_realcost_ware : current->mpf_realcost_worker) > static_cast<int32_t>(cost_cutoff))
2231 return nullptr;
2232
2233 Flag& flag = current->base_flag();
2234@@ -258,12 +258,12 @@
2235 * Only call from Flag init and split/merger code!
2236 */
2237 void Economy::add_flag(Flag& flag) {
2238- assert(flag.get_economy() == nullptr);
2239+ assert(flag.get_economy(type_) == nullptr);
2240
2241 flags_.push_back(&flag);
2242- flag.set_economy(this);
2243+ flag.set_economy(this, type_);
2244
2245- flag.reset_path_finding_cycle();
2246+ flag.reset_path_finding_cycle(type_);
2247 }
2248
2249 /**
2250@@ -271,7 +271,7 @@
2251 * Only call from Flag cleanup and split/merger code!
2252 */
2253 void Economy::remove_flag(Flag& flag) {
2254- assert(flag.get_economy() == this);
2255+ assert(flag.get_economy(type_) == this);
2256
2257 do_remove_flag(flag);
2258
2259@@ -286,7 +286,7 @@
2260 * This is called from the merge code.
2261 */
2262 void Economy::do_remove_flag(Flag& flag) {
2263- flag.set_economy(nullptr);
2264+ flag.set_economy(nullptr, type_);
2265
2266 // fast remove
2267 for (Flags::iterator flag_iter = flags_.begin(); flag_iter != flags_.end(); ++flag_iter) {
2268@@ -304,7 +304,7 @@
2269 */
2270 void Economy::reset_all_pathfinding_cycles() {
2271 for (Flag* flag : flags_) {
2272- flag->reset_path_finding_cycle();
2273+ flag->reset_path_finding_cycle(type_);
2274 }
2275 }
2276
2277@@ -315,20 +315,16 @@
2278 *
2279 * This is called from Cmd_ResetTargetQuantity and Cmd_SetTargetQuantity
2280 */
2281-void Economy::set_ware_target_quantity(DescriptionIndex const ware_type,
2282+void Economy::set_target_quantity(DescriptionIndex const ware_or_worker_type,
2283 Quantity const permanent,
2284 Time const mod_time) {
2285- assert(owner().egbase().tribes().ware_exists(ware_type));
2286- TargetQuantity& tq = ware_target_quantities_[ware_type];
2287- tq.permanent = permanent;
2288- tq.last_modified = mod_time;
2289-}
2290-
2291-void Economy::set_worker_target_quantity(DescriptionIndex const ware_type,
2292- Quantity const permanent,
2293- Time const mod_time) {
2294- assert(owner().egbase().tribes().worker_exists(ware_type));
2295- TargetQuantity& tq = worker_target_quantities_[ware_type];
2296+#ifndef NDEBUG
2297+ if (type_ == wwWARE)
2298+ assert(owner().egbase().tribes().ware_exists(ware_or_worker_type));
2299+ else
2300+ assert(owner().egbase().tribes().worker_exists(ware_or_worker_type));
2301+#endif
2302+ TargetQuantity& tq = target_quantities_[ware_or_worker_type];
2303 tq.permanent = permanent;
2304 tq.last_modified = mod_time;
2305 }
2306@@ -338,16 +334,16 @@
2307 * has felled a tree.
2308 * This is also called when a ware is added to the economy through trade or
2309 * a merger.
2310+ * Also notifies the corresponding other-type economy, if desired,
2311+ * so it may check e.g. whether a worker for whom a tool was missing can now be created.
2312 */
2313-void Economy::add_wares(DescriptionIndex const id, Quantity const count) {
2314- wares_.add(id, count);
2315- start_request_timer();
2316-
2317- // TODO(unknown): add to global player inventory?
2318-}
2319-void Economy::add_workers(DescriptionIndex const id, Quantity const count) {
2320- workers_.add(id, count);
2321- start_request_timer();
2322+void Economy::add_wares_or_workers(DescriptionIndex const id, Quantity const count, Economy* other_economy) {
2323+ wares_or_workers_.add(id, count);
2324+ start_request_timer();
2325+ if (other_economy) {
2326+ assert(other_economy->type() != type_);
2327+ other_economy->start_request_timer();
2328+ }
2329
2330 // TODO(unknown): add to global player inventory?
2331 }
2332@@ -358,20 +354,14 @@
2333 * This is also called when a ware is removed from the economy through trade or
2334 * a split of the Economy.
2335 */
2336-void Economy::remove_wares(DescriptionIndex const id, Quantity const count) {
2337- assert(owner_.egbase().tribes().ware_exists(id));
2338- wares_.remove(id, count);
2339-
2340- // TODO(unknown): remove from global player inventory?
2341-}
2342-
2343-/**
2344- * Call this whenever a worker is destroyed.
2345- * This is also called when a worker is removed from the economy through
2346- * a split of the Economy.
2347- */
2348-void Economy::remove_workers(DescriptionIndex const id, Quantity const count) {
2349- workers_.remove(id, count);
2350+void Economy::remove_wares_or_workers(DescriptionIndex const id, Quantity const count) {
2351+#ifndef NDEBUG
2352+ if (type_ == wwWARE)
2353+ assert(owner().egbase().tribes().ware_exists(id));
2354+ else
2355+ assert(owner().egbase().tribes().worker_exists(id));
2356+#endif
2357+ wares_or_workers_.remove(id, count);
2358
2359 // TODO(unknown): remove from global player inventory?
2360 }
2361@@ -460,50 +450,26 @@
2362 supplies_.remove_supply(supply);
2363 }
2364
2365-bool Economy::needs_ware(DescriptionIndex const ware_type) const {
2366- Quantity const t = ware_target_quantity(ware_type).permanent;
2367-
2368- // we have a target quantity set
2369- if (t > 0) {
2370- Quantity quantity = 0;
2371- for (const Warehouse* wh : warehouses_) {
2372- quantity += wh->get_wares().stock(ware_type);
2373- if (t <= quantity)
2374- return false;
2375- }
2376- return true;
2377-
2378- // we have target quantity set to 0, we need to check if there is an open request
2379- } else {
2380- for (const Request* temp_req : requests_) {
2381- const Request& req = *temp_req;
2382-
2383- if (req.get_type() == wwWARE && req.get_index() == ware_type)
2384- return true;
2385- }
2386- return false;
2387- }
2388-}
2389-
2390-bool Economy::needs_worker(DescriptionIndex const worker_type) const {
2391- Quantity const t = worker_target_quantity(worker_type).permanent;
2392-
2393- // we have a target quantity set
2394- if (t > 0) {
2395- Quantity quantity = 0;
2396- for (const Warehouse* wh : warehouses_) {
2397- quantity += wh->get_workers().stock(worker_type);
2398- if (t <= quantity)
2399- return false;
2400- }
2401- return true;
2402-
2403- // we have target quantity set to 0, we need to check if there is an open request
2404- } else {
2405- for (const Request* temp_req : requests_) {
2406- const Request& req = *temp_req;
2407-
2408- if (req.get_type() == wwWORKER && req.get_index() == worker_type)
2409+bool Economy::needs_ware_or_worker(DescriptionIndex const ware_or_worker_type) const {
2410+ Quantity const t = target_quantity(ware_or_worker_type).permanent;
2411+
2412+ // we have a target quantity set
2413+ if (t > 0) {
2414+ Quantity quantity = 0;
2415+ for (const Warehouse* wh : warehouses_) {
2416+ quantity += type_ == wwWARE ?
2417+ wh->get_wares().stock(ware_or_worker_type) : wh->get_workers().stock(ware_or_worker_type);
2418+ if (t <= quantity)
2419+ return false;
2420+ }
2421+ return true;
2422+
2423+ // we have target quantity set to 0, we need to check if there is an open request
2424+ } else {
2425+ for (const Request* temp_req : requests_) {
2426+ const Request& req = *temp_req;
2427+
2428+ if (req.get_type() == type_ && req.get_index() == ware_or_worker_type)
2429 return true;
2430 }
2431 return false;
2432@@ -517,17 +483,10 @@
2433 * requests if possible.
2434 */
2435 void Economy::merge(Economy& e) {
2436- for (const DescriptionIndex& ware_index : owner_.tribe().wares()) {
2437- TargetQuantity other_tq = e.ware_target_quantities_[ware_index];
2438- TargetQuantity& this_tq = ware_target_quantities_[ware_index];
2439- if (this_tq.last_modified < other_tq.last_modified) {
2440- this_tq = other_tq;
2441- }
2442- }
2443-
2444- for (const DescriptionIndex& worker_index : owner_.tribe().workers()) {
2445- TargetQuantity other_tq = e.worker_target_quantities_[worker_index];
2446- TargetQuantity& this_tq = worker_target_quantities_[worker_index];
2447+ assert(e.type() == type_);
2448+ for (const DescriptionIndex& w_index : (type_ == wwWARE ? owner_.tribe().wares() : owner_.tribe().workers())) {
2449+ TargetQuantity other_tq = e.target_quantities_[w_index];
2450+ TargetQuantity& this_tq = target_quantities_[w_index];
2451 if (this_tq.last_modified < other_tq.last_modified) {
2452 this_tq = other_tq;
2453 }
2454@@ -559,14 +518,10 @@
2455 void Economy::split(const std::set<OPtr<Flag>>& flags) {
2456 assert(!flags.empty());
2457
2458- Economy* e = owner_.create_economy();
2459-
2460- for (const DescriptionIndex& ware_index : owner_.tribe().wares()) {
2461- e->ware_target_quantities_[ware_index] = ware_target_quantities_[ware_index];
2462- }
2463-
2464- for (const DescriptionIndex& worker_index : owner_.tribe().workers()) {
2465- e->worker_target_quantities_[worker_index] = worker_target_quantities_[worker_index];
2466+ Economy* e = owner_.create_economy(type_);
2467+
2468+ for (const DescriptionIndex& w_index : (type_ == wwWARE ? owner_.tribe().wares() : owner_.tribe().workers())) {
2469+ e->target_quantities_[w_index] = target_quantities_[w_index];
2470 }
2471
2472 for (const OPtr<Flag>& temp_flag : flags) {
2473@@ -584,11 +539,15 @@
2474
2475 /**
2476 * Make sure the request timer is running.
2477+ * We can skip this for flagless economies (expedition ships don't need economy balancing...).
2478 */
2479 void Economy::start_request_timer(int32_t const delta) {
2480- if (upcast(Game, game, &owner_.egbase()))
2481- game->cmdqueue().enqueue(
2482- new CmdCallEconomyBalance(game->get_gametime() + delta, this, request_timerid_));
2483+ if (!flags_.empty()) {
2484+ if (upcast(Game, game, &owner_.egbase())) {
2485+ game->cmdqueue().enqueue(
2486+ new CmdCallEconomyBalance(game->get_gametime() + delta, this, request_timerid_));
2487+ }
2488+ }
2489 }
2490
2491 /**
2492@@ -642,14 +601,17 @@
2493 // will be cleared by find_route()
2494
2495 if (!find_route(
2496- supp.get_position(game)->base_flag(), target_flag, route, req.get_type(), best_cost)) {
2497+ supp.get_position(game)->base_flag(), target_flag, route, best_cost)) {
2498 if (!best_route) {
2499- log("Economy::find_best_supply: Error, COULD NOT FIND A ROUTE!");
2500+ log("Economy::find_best_supply: %s-Economy %u of player %u: Error, COULD NOT FIND A ROUTE!",
2501+ type_ ? "WORKER" : "WARE", serial_, owner_.player_number());
2502 // To help to debug this a bit:
2503- log(" ... ware at: %3dx%3d, requestor at: %3dx%3d!",
2504+ log(" ... ware at: %3dx%3d, requestor at: %3dx%3d! Item: %s.\n",
2505 supp.get_position(game)->base_flag().get_position().x,
2506 supp.get_position(game)->base_flag().get_position().y, target_flag.get_position().x,
2507- target_flag.get_position().y);
2508+ target_flag.get_position().y, type_ == wwWARE ?
2509+ game.tribes().get_ware_descr(req.get_index())->name().c_str() :
2510+ game.tribes().get_worker_descr(req.get_index())->name().c_str());
2511 }
2512 continue;
2513 }
2514@@ -802,12 +764,13 @@
2515 * worker request without supply, attempt to create a new worker in a warehouse.
2516 */
2517 void Economy::create_requested_worker(Game& game, DescriptionIndex index) {
2518- uint32_t demand = 0;
2519+ assert(type_ == wwWORKER);
2520
2521 bool soldier_level_check;
2522 const TribeDescr& tribe = owner().tribe();
2523 const WorkerDescr& w_desc = *tribe.get_worker_descr(index);
2524- Request* open_request = nullptr;
2525+ // Request mapped to demand
2526+ std::map<Request*, uint32_t> open_requests;
2527
2528 // Make a dummy soldier, which should never be assigned to any economy
2529 // Minimal invasive fix of bug 1236538: never create a rookie for a request
2530@@ -840,24 +803,21 @@
2531 }
2532
2533 uint32_t current_demand = req.get_open_count();
2534- demand += current_demand;
2535 if (current_demand > 0) {
2536- open_request = temp_req;
2537+ open_requests.emplace(temp_req, current_demand);
2538 }
2539 }
2540
2541- if (!demand)
2542+ if (open_requests.empty())
2543 return;
2544
2545- // We have worker demand that is not fulfilled by supplies
2546+ // We have worker demands that are not fulfilled by supplies.
2547 // Find warehouses where we can create the required workers,
2548 // and collect stats about existing build prerequisites
2549 const WorkerDescr::Buildcost& cost = w_desc.buildcost();
2550- std::vector<Quantity> total_available;
2551+ std::map<Economy*, std::vector<Quantity>> total_available;
2552 Quantity total_planned = 0;
2553
2554- total_available.insert(total_available.begin(), cost.size(), 0);
2555-
2556 for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) {
2557 Warehouse* wh = warehouses_[n_wh];
2558
2559@@ -866,85 +826,107 @@
2560
2561 while (wh->can_create_worker(game, index)) {
2562 wh->create_worker(game, index);
2563- if (!--demand)
2564+ --open_requests.begin()->second;
2565+ if (!open_requests.begin()->second) {
2566+ open_requests.erase(open_requests.begin());
2567+ }
2568+ if (open_requests.empty()) {
2569 return;
2570+ }
2571 }
2572
2573+ Economy* eco = wh->get_economy(wwWARE);
2574 std::vector<Quantity> wh_available = wh->calc_available_for_worker(game, index);
2575- assert(wh_available.size() == total_available.size());
2576-
2577- for (Quantity idx = 0; idx < total_available.size(); ++idx)
2578- total_available[idx] += wh_available[idx];
2579- }
2580-
2581- // Couldn't create enough workers now.
2582- // Let's see how many we have resources for that may be scattered
2583- // throughout the economy.
2584- uint32_t can_create = std::numeric_limits<uint32_t>::max();
2585- uint32_t idx = 0;
2586- uint32_t scarcest_idx = 0;
2587- bool plan_at_least_one = false;
2588- for (const auto& bc : cost) {
2589- uint32_t cc = total_available[idx] / bc.second;
2590- if (cc <= can_create) {
2591- scarcest_idx = idx;
2592- can_create = cc;
2593- }
2594-
2595- // if the target quantity of a resource is set to 0
2596- // plan at least one worker, so a request for that resource is triggered
2597- DescriptionIndex id_w = tribe.ware_index(bc.first);
2598- if (id_w != INVALID_INDEX && 0 == ware_target_quantity(id_w).permanent) {
2599- plan_at_least_one = true;
2600- }
2601- idx++;
2602- }
2603-
2604- if (total_planned > can_create && (!plan_at_least_one || total_planned > 1)) {
2605- // Eliminate some excessive plans, to make sure we never request more than
2606- // there are supplies for (otherwise, cyclic transportation might happen)
2607- // except in case of planAtLeastOne we continue to plan at least one
2608- // Note that supplies might suddenly disappear outside our control because
2609- // of loss of land or silly player actions.
2610- Warehouse* wh_with_plan = nullptr;
2611- for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) {
2612- Warehouse* wh = warehouses_[n_wh];
2613-
2614- uint32_t planned = wh->get_planned_workers(game, index);
2615- uint32_t reduce = std::min(planned, total_planned - can_create);
2616-
2617- if (plan_at_least_one && planned > 0) {
2618- wh_with_plan = wh;
2619- }
2620- wh->plan_workers(game, index, planned - reduce);
2621- total_planned -= reduce;
2622- }
2623-
2624- // in case of planAtLeastOne undo a set to zero
2625- if (nullptr != wh_with_plan && 0 == total_planned)
2626- wh_with_plan->plan_workers(game, index, 1);
2627-
2628- } else if (total_planned < demand) {
2629- uint32_t plan_goal = std::min(can_create, demand);
2630-
2631- for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) {
2632- Warehouse* wh = warehouses_[n_wh];
2633- uint32_t supply = wh->calc_available_for_worker(game, index)[scarcest_idx];
2634-
2635- total_planned -= wh->get_planned_workers(game, index);
2636- uint32_t plan = std::min(supply, plan_goal - total_planned);
2637- wh->plan_workers(game, index, plan);
2638- total_planned += plan;
2639- }
2640-
2641- // plan at least one if required and if we haven't done already
2642- // we are going to ignore stock policies of all warehouses here completely
2643- // the worker we are making is not going to be stocked, there is a request for him
2644- if (plan_at_least_one && 0 == total_planned) {
2645- Warehouse* wh = find_closest_warehouse(open_request->target_flag());
2646- if (nullptr == wh)
2647- wh = warehouses_[0];
2648- wh->plan_workers(game, index, 1);
2649+
2650+ auto iterate = total_available.find(eco);
2651+ if (iterate == total_available.end()) {
2652+ total_available[eco] = wh_available;
2653+ }
2654+ else {
2655+ for (Quantity idx = 0; idx < wh_available.size(); ++idx)
2656+ total_available[eco][idx] += wh_available[idx];
2657+ }
2658+ }
2659+
2660+ for (const std::pair<Economy*, std::vector<Quantity>>& pair : total_available) {
2661+ Request* req = nullptr;
2662+ uint32_t demand = 0;
2663+ for (const std::pair<Request*, uint32_t>& r : open_requests) {
2664+ if (r.first->target().get_economy(wwWARE) == pair.first) {
2665+ assert (r.second > 0);
2666+ demand += r.second;
2667+ req = r.first;
2668+ }
2669+ }
2670+ assert(demand > 0);
2671+ assert(req);
2672+
2673+ uint32_t can_create = std::numeric_limits<uint32_t>::max();
2674+ uint32_t idx = 0;
2675+ uint32_t scarcest_idx = 0;
2676+ bool plan_at_least_one = false;
2677+ for (const auto& bc : cost) {
2678+ uint32_t cc = total_available[pair.first][idx] / bc.second;
2679+ if (cc <= can_create) {
2680+ scarcest_idx = idx;
2681+ can_create = cc;
2682+ }
2683+
2684+ // if the target quantity of a resource is set to 0
2685+ // plan at least one worker, so a request for that resource is triggered
2686+ DescriptionIndex id_w = tribe.ware_index(bc.first);
2687+ if (id_w != INVALID_INDEX && 0 == pair.first->target_quantity(id_w).permanent) {
2688+ plan_at_least_one = true;
2689+ }
2690+ idx++;
2691+ }
2692+
2693+ if (total_planned > can_create && (!plan_at_least_one || total_planned > 1)) {
2694+ // Eliminate some excessive plans, to make sure we never request more than
2695+ // there are supplies for (otherwise, cyclic transportation might happen)
2696+ // except in case of planAtLeastOne we continue to plan at least one
2697+ // Note that supplies might suddenly disappear outside our control because
2698+ // of loss of land or silly player actions.
2699+ Warehouse* wh_with_plan = nullptr;
2700+ for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) {
2701+ Warehouse* wh = warehouses_[n_wh];
2702+
2703+ uint32_t planned = wh->get_planned_workers(game, index);
2704+ uint32_t reduce = std::min(planned, total_planned - can_create);
2705+
2706+ if (plan_at_least_one && planned > 0) {
2707+ wh_with_plan = wh;
2708+ }
2709+ wh->plan_workers(game, index, planned - reduce);
2710+ total_planned -= reduce;
2711+ }
2712+
2713+ // in case of planAtLeastOne undo a set to zero
2714+ if (nullptr != wh_with_plan && 0 == total_planned)
2715+ wh_with_plan->plan_workers(game, index, 1);
2716+
2717+ } else if (total_planned < demand) {
2718+ uint32_t plan_goal = std::min(can_create, demand);
2719+
2720+ for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) {
2721+ Warehouse* wh = warehouses_[n_wh];
2722+ uint32_t supply = wh->calc_available_for_worker(game, index)[scarcest_idx];
2723+
2724+ total_planned -= wh->get_planned_workers(game, index);
2725+ uint32_t plan = std::min(supply, plan_goal - total_planned);
2726+ wh->plan_workers(game, index, plan);
2727+ total_planned += plan;
2728+ }
2729+
2730+ // plan at least one if required and if we haven't done already
2731+ // we are going to ignore stock policies of all warehouses here completely
2732+ // the worker we are making is not going to be stocked, there is a request for him
2733+ if (plan_at_least_one && 0 == total_planned) {
2734+ Warehouse* wh = find_closest_warehouse(req->target_flag());
2735+ if (nullptr == wh)
2736+ wh = warehouses_[0];
2737+ wh->plan_workers(game, index, 1);
2738+ }
2739 }
2740 }
2741 }
2742@@ -954,7 +936,7 @@
2743 * try to create the worker at warehouses.
2744 */
2745 void Economy::create_requested_workers(Game& game) {
2746- if (!warehouses().size())
2747+ if (type_ != wwWORKER || !warehouses().size())
2748 return;
2749
2750 for (const DescriptionIndex& worker_index : owner().tribe().workers()) {
2751@@ -991,9 +973,10 @@
2752 if (supply.has_storage())
2753 continue;
2754
2755- WareWorker type;
2756+ WareWorker wwtype;
2757 DescriptionIndex ware;
2758- supply.get_ware_type(type, ware);
2759+ supply.get_ware_type(wwtype, ware);
2760+ assert(wwtype == type_);
2761
2762 bool haveprefer = false;
2763 bool havenormal = false;
2764@@ -1005,17 +988,13 @@
2765
2766 for (uint32_t nwh = 0; nwh < warehouses_.size(); ++nwh) {
2767 Warehouse* wh = warehouses_[nwh];
2768- Warehouse::StockPolicy policy = wh->get_stock_policy(type, ware);
2769+ Warehouse::StockPolicy policy = wh->get_stock_policy(type_, ware);
2770 if (policy == Warehouse::StockPolicy::kPrefer) {
2771 haveprefer = true;
2772
2773 // Getting count of worker/ware
2774 uint32_t current_stock;
2775- if (type == WareWorker::wwWARE) {
2776- current_stock = wh->get_wares().stock(ware);
2777- } else {
2778- current_stock = wh->get_workers().stock(ware);
2779- }
2780+ current_stock = type_ == wwWARE ? wh->get_wares().stock(ware) : wh->get_workers().stock(ware);
2781 // Stocks lower then in previous one?
2782 if (current_stock < preferred_wh_stock) {
2783 preferred_wh = wh;
2784@@ -1025,7 +1004,7 @@
2785 if (policy == Warehouse::StockPolicy::kNormal)
2786 havenormal = true;
2787 }
2788- if (!havenormal && !haveprefer && type == wwWARE)
2789+ if (!havenormal && !haveprefer && type_ == wwWARE)
2790 continue;
2791
2792 // We either have one preferred warehouse picked up or walk on roads to find nearest one
2793@@ -1033,10 +1012,10 @@
2794 if (preferred_wh) {
2795 wh = preferred_wh;
2796 } else {
2797- wh = find_closest_warehouse(supply.get_position(game)->base_flag(), type, nullptr, 0,
2798+ wh = find_closest_warehouse(supply.get_position(game)->base_flag(), nullptr, 0,
2799 (!havenormal) ?
2800 WarehouseAcceptFn() :
2801- boost::bind(&accept_warehouse_if_policy, _1, type, ware,
2802+ boost::bind(&accept_warehouse_if_policy, _1, type_, ware,
2803 Warehouse::StockPolicy::kNormal));
2804 }
2805 if (!wh) {
2806
2807=== modified file 'src/economy/economy.h'
2808--- src/economy/economy.h 2019-02-23 11:00:49 +0000
2809+++ src/economy/economy.h 2019-06-11 08:19:26 +0000
2810@@ -86,6 +86,11 @@
2811 * are \b always in the same economy, but two flags in the same economy are not always
2812 * connected by roads or the seafaring network - though of course, most code operates
2813 * on the assumption that they are, with fallbacks for when they aren't.
2814+ *
2815+ * Everything that has economies now has one economy that handles only wares and one that handles
2816+ * only workers. The reason for this design is that two road networks connected only by ferries
2817+ * are the same economy from the ware point of view, but separate economies from a worker's point
2818+ * of view. This fix involves the least amount of code duplication.
2819 */
2820 class Economy {
2821 public:
2822@@ -110,8 +115,8 @@
2823 Time last_modified;
2824 };
2825
2826- explicit Economy(Player&);
2827- explicit Economy(Player&, Serial serial); // For saveloading
2828+ explicit Economy(Player&, WareWorker);
2829+ explicit Economy(Player&, Serial serial, WareWorker); // For saveloading
2830 ~Economy();
2831
2832 Serial serial() const {
2833@@ -122,14 +127,17 @@
2834 return owner_;
2835 }
2836
2837- static void check_merge(Flag&, Flag&);
2838- static void check_split(Flag&, Flag&);
2839-
2840- bool find_route(Flag& start, Flag& end, Route* route, WareWorker type, int32_t cost_cutoff = -1);
2841+ WareWorker type() const {
2842+ return type_;
2843+ }
2844+
2845+ static void check_merge(Flag&, Flag&, WareWorker);
2846+ static void check_split(Flag&, Flag&, WareWorker);
2847+
2848+ bool find_route(Flag& start, Flag& end, Route* route, int32_t cost_cutoff = -1);
2849
2850 using WarehouseAcceptFn = boost::function<bool(Warehouse&)>;
2851 Warehouse* find_closest_warehouse(Flag& start,
2852- WareWorker type = wwWORKER,
2853 Route* route = nullptr,
2854 uint32_t cost_cutoff = 0,
2855 const WarehouseAcceptFn& acceptfn = WarehouseAcceptFn());
2856@@ -144,14 +152,10 @@
2857 // (i.e. an Expedition ship).
2858 Flag* get_arbitrary_flag();
2859
2860- void set_ware_target_quantity(DescriptionIndex, Quantity, Time);
2861- void set_worker_target_quantity(DescriptionIndex, Quantity, Time);
2862-
2863- void add_wares(DescriptionIndex, Quantity count = 1);
2864- void remove_wares(DescriptionIndex, Quantity count = 1);
2865-
2866- void add_workers(DescriptionIndex, Quantity count = 1);
2867- void remove_workers(DescriptionIndex, Quantity count = 1);
2868+ void set_target_quantity(DescriptionIndex, Quantity, Time);
2869+
2870+ void add_wares_or_workers(DescriptionIndex, Quantity count = 1, Economy* other_economy = nullptr);
2871+ void remove_wares_or_workers(DescriptionIndex, Quantity count = 1);
2872
2873 void add_warehouse(Warehouse&);
2874 void remove_warehouse(Warehouse&);
2875@@ -166,34 +170,20 @@
2876 void remove_supply(Supply&);
2877
2878 /// information about this economy
2879- Quantity stock_ware(DescriptionIndex const i) {
2880- return wares_.stock(i);
2881- }
2882- Quantity stock_worker(DescriptionIndex const i) {
2883- return workers_.stock(i);
2884+ Quantity stock_ware_or_worker(DescriptionIndex const i) {
2885+ return wares_or_workers_.stock(i);
2886 }
2887
2888- /// Whether the economy needs more of this ware type.
2889+ /// Whether the economy needs more of this ware/worker type.
2890 /// Productionsites may ask this before they produce, to avoid depleting a
2891 /// ware type by overproducing another from it.
2892- bool needs_ware(DescriptionIndex) const;
2893-
2894- /// Whether the economy needs more of this worker type.
2895- /// Productionsites may ask this before they produce, to avoid depleting a
2896- /// ware type by overproducing a worker type from it.
2897- bool needs_worker(DescriptionIndex) const;
2898-
2899- const TargetQuantity& ware_target_quantity(DescriptionIndex const i) const {
2900- return ware_target_quantities_[i];
2901- }
2902- TargetQuantity& ware_target_quantity(DescriptionIndex const i) {
2903- return ware_target_quantities_[i];
2904- }
2905- const TargetQuantity& worker_target_quantity(DescriptionIndex const i) const {
2906- return worker_target_quantities_[i];
2907- }
2908- TargetQuantity& worker_target_quantity(DescriptionIndex const i) {
2909- return worker_target_quantities_[i];
2910+ bool needs_ware_or_worker(DescriptionIndex) const;
2911+
2912+ const TargetQuantity& target_quantity(DescriptionIndex const i) const {
2913+ return target_quantities_[i];
2914+ }
2915+ TargetQuantity& target_quantity(DescriptionIndex const i) {
2916+ return target_quantities_[i];
2917 }
2918
2919 bool has_window() const {
2920@@ -203,11 +193,8 @@
2921 has_window_ = yes;
2922 }
2923
2924- const WareList& get_wares() const {
2925- return wares_;
2926- }
2927- const WareList& get_workers() const {
2928- return workers_;
2929+ const WareList& get_wares_or_workers() const {
2930+ return wares_or_workers_;
2931 }
2932
2933 ///< called by \ref Cmd_Call_Economy_Balance
2934@@ -268,15 +255,15 @@
2935
2936 using Flags = std::vector<Flag*>;
2937 Flags flags_;
2938- WareList wares_; ///< virtual storage with all wares in this Economy
2939- WareList workers_; ///< virtual storage with all workers in this Economy
2940+ WareList wares_or_workers_; ///< virtual storage with all wares/workers in this Economy
2941 std::vector<Warehouse*> warehouses_;
2942
2943+ WareWorker type_; ///< whether we are a WareEconomy or a WorkerEconomy
2944+
2945 RequestList requests_; ///< requests
2946 SupplyList supplies_;
2947
2948- TargetQuantity* ware_target_quantities_;
2949- TargetQuantity* worker_target_quantities_;
2950+ TargetQuantity* target_quantities_;
2951 std::unique_ptr<Router> router_;
2952
2953 using SplitPair = std::pair<OPtr<Flag>, OPtr<Flag>>;
2954
2955=== modified file 'src/economy/economy_data_packet.cc'
2956--- src/economy/economy_data_packet.cc 2019-02-23 11:00:49 +0000
2957+++ src/economy/economy_data_packet.cc 2019-06-11 08:19:26 +0000
2958@@ -27,7 +27,7 @@
2959 #include "map_io/map_object_loader.h"
2960 #include "map_io/map_object_saver.h"
2961
2962-constexpr uint16_t kCurrentPacketVersion = 4;
2963+constexpr uint16_t kCurrentPacketVersion = 5;
2964
2965 namespace Widelands {
2966
2967@@ -47,44 +47,48 @@
2968 while (Time const last_modified = fr.unsigned_32()) {
2969 char const* const type_name = fr.c_string();
2970 uint32_t const permanent = fr.unsigned_32();
2971- DescriptionIndex i = tribe.ware_index(type_name);
2972- if (tribe.has_ware(i)) {
2973- if (tribe.get_ware_descr(i)->default_target_quantity(tribe.name()) ==
2974- kInvalidWare) {
2975- log("WARNING: target quantity configured for %s, "
2976- "which should not have target quantity, "
2977- "ignoring\n",
2978- type_name);
2979- } else {
2980- Economy::TargetQuantity& tq = eco_->ware_target_quantities_[i];
2981- if (tq.last_modified) {
2982- throw GameDataError("duplicated entry for %s", type_name);
2983- }
2984- tq.permanent = permanent;
2985- tq.last_modified = last_modified;
2986- }
2987- } else {
2988- i = tribe.worker_index(type_name);
2989- if (tribe.has_worker(i)) {
2990- if (tribe.get_worker_descr(i)->default_target_quantity() == kInvalidWare) {
2991- log("WARNING: target quantity configured for %s, "
2992- "which should not have target quantity, "
2993- "ignoring\n",
2994- type_name);
2995+ DescriptionIndex i;
2996+ switch (eco_->type()) {
2997+ case wwWARE:
2998+ i = tribe.ware_index(type_name);
2999+ if (tribe.get_ware_descr(i)->default_target_quantity(tribe.name()) ==
3000+ kInvalidWare) {
3001+ log("WARNING: target quantity configured for ware %s, "
3002+ "which should not have target quantity, "
3003+ "ignoring\n",
3004+ type_name);
3005 } else {
3006- Economy::TargetQuantity& tq = eco_->worker_target_quantities_[i];
3007+ Economy::TargetQuantity& tq = eco_->target_quantities_[i];
3008 if (tq.last_modified) {
3009- throw GameDataError("duplicated entry for %s", type_name);
3010+ throw GameDataError("duplicated entry for ware %s", type_name);
3011 }
3012 tq.permanent = permanent;
3013 tq.last_modified = last_modified;
3014 }
3015- } else {
3016- log("WARNING: target quantity configured for \"%s\", "
3017- "which is not a ware or worker type defined in tribe "
3018- "%s, ignoring\n",
3019- type_name, tribe.name().c_str());
3020- }
3021+ break;
3022+ case wwWORKER:
3023+ i = tribe.worker_index(type_name);
3024+ if (tribe.has_worker(i)) {
3025+ if (tribe.get_worker_descr(i)->default_target_quantity() == kInvalidWare) {
3026+ log("WARNING: target quantity configured for worker %s, "
3027+ "which should not have target quantity, "
3028+ "ignoring\n",
3029+ type_name);
3030+ } else {
3031+ Economy::TargetQuantity& tq = eco_->target_quantities_[i];
3032+ if (tq.last_modified) {
3033+ throw GameDataError("duplicated entry for worker %s", type_name);
3034+ }
3035+ tq.permanent = permanent;
3036+ tq.last_modified = last_modified;
3037+ }
3038+ } else {
3039+ log("WARNING: target quantity configured for \"%s\" in %s-economy, "
3040+ "which is not a ware or worker type defined in tribe "
3041+ "%s, ignoring\n",
3042+ type_name, eco_->type() == wwWARE ? "Ware" : "Worker", tribe.name().c_str());
3043+ }
3044+ break;
3045 }
3046 }
3047 } catch (const WException& e) {
3048@@ -107,19 +111,14 @@
3049
3050 // Requests etc.
3051 const TribeDescr& tribe = eco_->owner().tribe();
3052- for (const DescriptionIndex& ware_index : tribe.wares()) {
3053- const Economy::TargetQuantity& tq = eco_->ware_target_quantities_[ware_index];
3054- if (Time const last_modified = tq.last_modified) {
3055- fw.unsigned_32(last_modified);
3056- fw.c_string(tribe.get_ware_descr(ware_index)->name());
3057- fw.unsigned_32(tq.permanent);
3058- }
3059- }
3060- for (const DescriptionIndex& worker_index : tribe.workers()) {
3061- const Economy::TargetQuantity& tq = eco_->worker_target_quantities_[worker_index];
3062- if (Time const last_modified = tq.last_modified) {
3063- fw.unsigned_32(last_modified);
3064- fw.c_string(tribe.get_worker_descr(worker_index)->name());
3065+ for (const DescriptionIndex& w_index : (eco_->type() == wwWARE ? tribe.wares() : tribe.workers())) {
3066+ const Economy::TargetQuantity& tq = eco_->target_quantities_[w_index];
3067+ if (Time const last_modified = tq.last_modified) {
3068+ fw.unsigned_32(last_modified);
3069+ if (eco_->type() == wwWARE)
3070+ fw.c_string(tribe.get_ware_descr(w_index)->name());
3071+ else
3072+ fw.c_string(tribe.get_worker_descr(w_index)->name());
3073 fw.unsigned_32(tq.permanent);
3074 }
3075 }
3076
3077=== modified file 'src/economy/expedition_bootstrap.cc'
3078--- src/economy/expedition_bootstrap.cc 2019-02-23 11:00:49 +0000
3079+++ src/economy/expedition_bootstrap.cc 2019-06-11 08:19:26 +0000
3080@@ -36,7 +36,7 @@
3081 namespace Widelands {
3082
3083 ExpeditionBootstrap::ExpeditionBootstrap(PortDock* const portdock)
3084- : portdock_(portdock), economy_(portdock->get_economy()) {
3085+ : portdock_(portdock), ware_economy_(portdock->get_economy(wwWARE)), worker_economy_(portdock->get_economy(wwWORKER)) {
3086 }
3087
3088 ExpeditionBootstrap::~ExpeditionBootstrap() {
3089@@ -98,14 +98,16 @@
3090 // Put all wares from the WaresQueues back into the warehouse
3091 Warehouse* const warehouse = portdock_->get_warehouse();
3092 for (std::unique_ptr<InputQueue>& iq : queues_) {
3093- if (iq->get_type() == wwWARE) {
3094- warehouse->insert_wares(iq->get_index(), iq->get_filled());
3095- } else {
3096- assert(iq->get_type() == wwWORKER);
3097- WorkersQueue* wq = dynamic_cast<WorkersQueue*>(iq.get());
3098- while (iq->get_filled() > 0) {
3099- warehouse->incorporate_worker(game, wq->extract_worker());
3100- }
3101+ switch (iq->get_type()) {
3102+ case wwWARE:
3103+ warehouse->insert_wares(iq->get_index(), iq->get_filled());
3104+ break;
3105+ case wwWORKER:
3106+ WorkersQueue* wq = dynamic_cast<WorkersQueue*>(iq.get());
3107+ while (iq->get_filled() > 0) {
3108+ warehouse->incorporate_worker(game, wq->extract_worker());
3109+ }
3110+ break;
3111 }
3112 iq->cleanup();
3113 }
3114@@ -141,19 +143,24 @@
3115 return return_value;
3116 }
3117
3118-void ExpeditionBootstrap::set_economy(Economy* new_economy) {
3119- if (new_economy == economy_)
3120+void ExpeditionBootstrap::set_economy(Economy* new_economy, WareWorker type) {
3121+ if (new_economy == (type == wwWARE ? ware_economy_ : worker_economy_))
3122 return;
3123
3124 // Transfer the wares and workers.
3125 for (std::unique_ptr<InputQueue>& iq : queues_) {
3126- if (economy_)
3127- iq->remove_from_economy(*economy_);
3128- if (new_economy)
3129+ if (type != iq->get_type()) {
3130+ continue;
3131+ }
3132+ if (Economy* e = type == wwWARE ? ware_economy_ : worker_economy_) {
3133+ iq->remove_from_economy(*e);
3134+ }
3135+ if (new_economy) {
3136 iq->add_to_economy(*new_economy);
3137+ }
3138 }
3139
3140- economy_ = new_economy;
3141+ (type == wwWARE ? ware_economy_ : worker_economy_) = new_economy;
3142 }
3143
3144 void ExpeditionBootstrap::get_waiting_workers_and_wares(Game& game,
3145@@ -161,19 +168,23 @@
3146 std::vector<Worker*>* return_workers,
3147 std::vector<WareInstance*>* return_wares) {
3148 for (std::unique_ptr<InputQueue>& iq : queues_) {
3149- if (iq->get_type() == wwWARE) {
3150- const DescriptionIndex ware_index = iq->get_index();
3151- for (uint32_t j = 0; j < iq->get_filled(); ++j) {
3152- WareInstance* temp = new WareInstance(ware_index, tribe.get_ware_descr(ware_index));
3153- temp->init(game);
3154- temp->set_location(game, portdock_);
3155- return_wares->emplace_back(temp);
3156+ switch (iq->get_type()) {
3157+ case wwWARE: {
3158+ const DescriptionIndex ware_index = iq->get_index();
3159+ for (uint32_t j = 0; j < iq->get_filled(); ++j) {
3160+ WareInstance* temp = new WareInstance(ware_index, tribe.get_ware_descr(ware_index));
3161+ temp->init(game);
3162+ temp->set_location(game, portdock_);
3163+ return_wares->emplace_back(temp);
3164+ }
3165+ break;
3166 }
3167- } else {
3168- assert(iq->get_type() == wwWORKER);
3169- WorkersQueue* wq = dynamic_cast<WorkersQueue*>(iq.get());
3170- while (iq->get_filled() > 0) {
3171- return_workers->emplace_back(wq->extract_worker());
3172+ case wwWORKER: {
3173+ WorkersQueue* wq = dynamic_cast<WorkersQueue*>(iq.get());
3174+ while (iq->get_filled() > 0) {
3175+ return_workers->emplace_back(wq->extract_worker());
3176+ }
3177+ break;
3178 }
3179 }
3180 }
3181
3182=== modified file 'src/economy/expedition_bootstrap.h'
3183--- src/economy/expedition_bootstrap.h 2019-02-23 11:00:49 +0000
3184+++ src/economy/expedition_bootstrap.h 2019-06-11 08:19:26 +0000
3185@@ -71,7 +71,7 @@
3186 std::vector<WareInstance*>* return_wares);
3187
3188 // Changes the economy for the wares that are already in store.
3189- void set_economy(Economy* economy);
3190+ void set_economy(Economy* economy, WareWorker);
3191
3192 // Returns the wares and workers currently waiting for the expedition.
3193 std::vector<InputQueue*> queues() const;
3194@@ -106,7 +106,8 @@
3195
3196 /** The Expedition is bootstapped here. */
3197 PortDock* const portdock_; // not owned
3198- Economy* economy_;
3199+ Economy* ware_economy_;
3200+ Economy* worker_economy_;
3201
3202 std::vector<std::unique_ptr<InputQueue>> queues_;
3203
3204
3205=== added file 'src/economy/ferry_fleet.cc'
3206--- src/economy/ferry_fleet.cc 1970-01-01 00:00:00 +0000
3207+++ src/economy/ferry_fleet.cc 2019-06-11 08:19:26 +0000
3208@@ -0,0 +1,500 @@
3209+/*
3210+ * Copyright (C) 2011-2019 by the Widelands Development Team
3211+ *
3212+ * This program is free software; you can redistribute it and/or
3213+ * modify it under the terms of the GNU General Public License
3214+ * as published by the Free Software Foundation; either version 2
3215+ * of the License, or (at your option) any later version.
3216+ *
3217+ * This program is distributed in the hope that it will be useful,
3218+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3219+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3220+ * GNU General Public License for more details.
3221+ *
3222+ * You should have received a copy of the GNU General Public License
3223+ * along with this program; if not, write to the Free Software
3224+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
3225+ *
3226+ */
3227+
3228+#include "economy/ferry_fleet.h"
3229+
3230+#include <memory>
3231+
3232+#include "base/macros.h"
3233+#include "economy/economy.h"
3234+#include "economy/flag.h"
3235+#include "economy/waterway.h"
3236+#include "io/fileread.h"
3237+#include "io/filewrite.h"
3238+#include "logic/game.h"
3239+#include "logic/map_objects/checkstep.h"
3240+#include "logic/map_objects/tribes/ferry.h"
3241+#include "logic/mapastar.h"
3242+#include "logic/path.h"
3243+#include "logic/player.h"
3244+#include "map_io/map_object_loader.h"
3245+#include "map_io/map_object_saver.h"
3246+
3247+namespace Widelands {
3248+
3249+namespace {
3250+// Every MapObject() needs to have a description. So we make a dummy one for
3251+// Fleet.
3252+FerryFleetDescr g_ferry_fleet_descr("ferry_fleet", "Ferry Fleet");
3253+} // namespace
3254+
3255+const FerryFleetDescr& FerryFleet::descr() const {
3256+ return g_ferry_fleet_descr;
3257+}
3258+
3259+/**
3260+ * Fleets are initialized empty.
3261+ *
3262+ * Intended use: @ref Ferry and @ref Waterway, when created, create a new @ref FerryFleet
3263+ * instance, then add themselves \em before calling the \ref init function.
3264+ * The FerryFleet takes care of merging with existing fleets, if any.
3265+ */
3266+FerryFleet::FerryFleet(Player* player) : MapObject(&g_ferry_fleet_descr), act_pending_(false) {
3267+ owner_ = player;
3268+}
3269+
3270+/**
3271+ * Whether the fleet is in fact useful for transporting wares.
3272+ * This is the case if we have a ferry and a request for a ferry.
3273+ */
3274+bool FerryFleet::active() const {
3275+ return !ferries_.empty() && !pending_ferry_requests_.empty();
3276+}
3277+
3278+/**
3279+ * Initialize the fleet, including a search through the map
3280+ * to rejoin with the next other fleet we can find.
3281+ */
3282+bool FerryFleet::init(EditorGameBase& egbase) {
3283+ MapObject::init(egbase);
3284+
3285+ if (empty()) {
3286+ molog("Empty fleet initialized; disband immediately\n");
3287+ remove(egbase);
3288+ return false;
3289+ }
3290+
3291+ return find_other_fleet(egbase);
3292+}
3293+
3294+struct StepEvalFindFerryFleet {
3295+ StepEvalFindFerryFleet(const EditorGameBase& egbase)
3296+ : checkstep_(new CheckStepFerry(egbase)) {
3297+ }
3298+
3299+ int32_t estimate(Map& /* map */, FCoords /* pos */) const {
3300+ return 0;
3301+ }
3302+ int32_t stepcost(Map& map, FCoords from, int32_t /* fromcost */, WalkingDir dir, FCoords to) const {
3303+ return checkstep_->allowed(map, from, to, dir, CheckStep::StepId::stepNormal) ? 1 : -1;
3304+ }
3305+private:
3306+ std::unique_ptr<CheckStepFerry> checkstep_;
3307+};
3308+
3309+/**
3310+ * Search the map, starting at our ferries and waterways, for another fleet
3311+ * of the same player.
3312+ */
3313+bool FerryFleet::find_other_fleet(EditorGameBase& egbase) {
3314+ StepEvalFindFerryFleet stepeval(egbase);
3315+ MapAStar<StepEvalFindFerryFleet> astar(*egbase.mutable_map(), stepeval, wwWORKER);
3316+ for (const Ferry* temp_ferry : ferries_) {
3317+ astar.push(temp_ferry->get_position());
3318+ }
3319+ for (const auto& temp_ww : pending_ferry_requests_) {
3320+ for (Coords& c : temp_ww.second->get_positions(egbase)) {
3321+ astar.push(c);
3322+ }
3323+ }
3324+
3325+ int32_t cost;
3326+ FCoords cur;
3327+ while (astar.step(cur, cost)) {
3328+ if (BaseImmovable* imm = cur.field->get_immovable()) {
3329+ const MapObjectType type = imm->descr().type();
3330+ if (type == MapObjectType::WATERWAY) {
3331+ upcast(Waterway, ww, imm);
3332+ if (ww->get_fleet() != this && ww->get_owner() == get_owner()) {
3333+ return ww->get_fleet()->merge(egbase, this);
3334+ }
3335+ }
3336+ }
3337+
3338+ for (Bob* bob = cur.field->get_first_bob(); bob != nullptr; bob = bob->get_next_bob()) {
3339+ const MapObjectType type = bob->descr().type();
3340+ if (type == MapObjectType::FERRY) {
3341+ upcast(Ferry, ferry, bob);
3342+ if (ferry->get_fleet() != nullptr && ferry->get_fleet() != this &&
3343+ ferry->get_owner() == get_owner()) {
3344+ return ferry->get_fleet()->merge(egbase, this);
3345+ }
3346+ }
3347+ }
3348+ }
3349+
3350+ if (active()) {
3351+ update(egbase);
3352+ return true;
3353+ }
3354+ return false;
3355+}
3356+
3357+/**
3358+ * Merge the @p other fleet into this fleet, and remove the other fleet.
3359+ *
3360+ * Returns true if 'other' is the resulting fleet and "false" if 'this' is
3361+ * the resulting fleet. The values are reversed because we originally call this from
3362+ * another 'other' for efficiency reasons.
3363+ */
3364+bool FerryFleet::merge(EditorGameBase& egbase, FerryFleet* other) {
3365+ if (ferries_.empty() && !other->ferries_.empty()) {
3366+ other->merge(egbase, this);
3367+ return true;
3368+ }
3369+
3370+ while (!other->ferries_.empty()) {
3371+ Ferry* ferry = other->ferries_.back();
3372+ other->ferries_.pop_back();
3373+ add_ferry(egbase, ferry);
3374+ }
3375+
3376+ while (!other->pending_ferry_requests_.empty()) {
3377+ auto pair = other->pending_ferry_requests_.begin();
3378+ uint32_t time = pair->first;
3379+ Waterway* ww = pair->second;
3380+ // set_fleet() tells the associated waterway to remove this request from the other fleet
3381+ ww->set_fleet(this);
3382+ pending_ferry_requests_.emplace(time, ww);
3383+ }
3384+
3385+ other->remove(egbase);
3386+
3387+ update(egbase);
3388+ return false;
3389+}
3390+
3391+void FerryFleet::cleanup(EditorGameBase& egbase) {
3392+ while (!ferries_.empty()) {
3393+ Ferry* ferry = ferries_.back();
3394+ if (egbase.objects().object_still_available(ferry)) {
3395+ ferry->set_fleet(nullptr);
3396+ }
3397+ ferries_.pop_back();
3398+ }
3399+ while (!pending_ferry_requests_.empty()) {
3400+ auto pair = pending_ferry_requests_.begin();
3401+ if (egbase.objects().object_still_available(pair->second)) {
3402+ pair->second->set_fleet(nullptr);
3403+ }
3404+ pending_ferry_requests_.erase(pair);
3405+ }
3406+
3407+ MapObject::cleanup(egbase);
3408+}
3409+
3410+uint32_t FerryFleet::count_ferries() const {
3411+ return ferries_.size();
3412+}
3413+
3414+uint32_t FerryFleet::count_unattended_waterways() const {
3415+ return pending_ferry_requests_.size();
3416+}
3417+
3418+// Returns true of this waterway has a ferry or a ferry is on the way there
3419+bool FerryFleet::has_ferry(const Waterway& ww) const {
3420+ if (ww.get_ferry()) {
3421+ return true;
3422+ }
3423+ assert(ww.get_fleet() == this);
3424+ for (const auto& pair : pending_ferry_requests_) {
3425+ if (pair.second == &ww) {
3426+ return false;
3427+ }
3428+ }
3429+ return true;
3430+}
3431+
3432+void FerryFleet::add_ferry(EditorGameBase& /* egbase */, Ferry* ferry) {
3433+ ferries_.push_back(ferry);
3434+ ferry->set_fleet(this);
3435+}
3436+
3437+void FerryFleet::remove_ferry(EditorGameBase& egbase, Ferry* ferry) {
3438+ std::vector<Ferry*>::iterator it = std::find(ferries_.begin(), ferries_.end(), ferry);
3439+ if (it != ferries_.end()) {
3440+ *it = ferries_.back();
3441+ ferries_.pop_back();
3442+ }
3443+ ferry->set_fleet(nullptr);
3444+
3445+ if (ferry->get_location(egbase)) {
3446+ update(egbase);
3447+ }
3448+
3449+ if (empty()) {
3450+ remove(egbase);
3451+ }
3452+}
3453+
3454+/**
3455+ * Adds a request for a ferry. The request will be fulfilled as soon as possible
3456+ * in the next call to act(). When a ferry is found, its destination will be set to the waterway.
3457+ * Multiple requests will be treated first come first served.
3458+ */
3459+void FerryFleet::request_ferry(EditorGameBase& egbase, Waterway* waterway, int32_t gametime) {
3460+ for (const auto& pair : pending_ferry_requests_) {
3461+ if (pair.second == waterway) {
3462+ if (waterway->get_fleet() != this) {
3463+ waterway->set_fleet(this);
3464+ }
3465+ // One and the same request may be issued twice, e.g. when splitting a waterway – ignore
3466+ return;
3467+ }
3468+ }
3469+ pending_ferry_requests_.emplace(gametime < 0 ? egbase.get_gametime() : gametime, waterway);
3470+ waterway->set_fleet(this);
3471+}
3472+
3473+void FerryFleet::cancel_ferry_request(Game& game, Waterway* waterway) {
3474+ for (Ferry* ferry : ferries_) {
3475+ if (game.objects().object_still_available(ferry) && ferry->get_destination(game) == waterway) {
3476+ ferry->set_destination(game, nullptr);
3477+ return;
3478+ }
3479+ }
3480+ for (auto it = pending_ferry_requests_.begin(); it != pending_ferry_requests_.end(); ++it) {
3481+ if (it->second == waterway) {
3482+
3483+ pending_ferry_requests_.erase(it);
3484+ if (empty()) {
3485+ // We're no longer needed, act() will destroy us soon
3486+ update(game);
3487+ }
3488+ return;
3489+ }
3490+ }
3491+}
3492+
3493+void FerryFleet::reroute_ferry_request(Game& game, Waterway* oldww, Waterway* newww) {
3494+ for (Ferry* ferry : ferries_) {
3495+ if (ferry->get_destination(game) == oldww) {
3496+ ferry->set_destination(game, newww);
3497+ return;
3498+ }
3499+ }
3500+ for (auto it = pending_ferry_requests_.begin(); it != pending_ferry_requests_.end(); ++it) {
3501+ if (it->second == oldww) {
3502+ it->second = newww;
3503+ return;
3504+ }
3505+ }
3506+ log("FerryFleet::reroute_ferry_request: received order to reroute inexistent request\n");
3507+}
3508+
3509+bool FerryFleet::empty() const {
3510+ return ferries_.empty() && pending_ferry_requests_.empty();
3511+}
3512+
3513+/**
3514+ * Trigger an update of ship scheduling
3515+ */
3516+void FerryFleet::update(EditorGameBase& egbase, uint32_t tdelta) {
3517+ if (act_pending_) {
3518+ return;
3519+ }
3520+
3521+ if (upcast(Game, game, &egbase)) {
3522+ schedule_act(*game, tdelta);
3523+ act_pending_ = true;
3524+ }
3525+}
3526+
3527+/**
3528+ * Act callback updates ferry assigning. All decisions about which ferry to assign to which waterway
3529+ * are supposed to be made by this function.
3530+ *
3531+ * @note Do not call this directly; instead, trigger it via @ref update
3532+ */
3533+void FerryFleet::act(Game& game, uint32_t /* data */) {
3534+ assert(act_pending_);
3535+ act_pending_ = false;
3536+
3537+ if (empty()) {
3538+ molog("FerryFleet::act: remove empty fleet\n");
3539+ remove(game);
3540+ return;
3541+ }
3542+
3543+ if (!active()) {
3544+ // If we are here, most likely update() was called by a pending ferry request
3545+ // when there are no ferries yet or by a new ferry when we can't offer
3546+ // employment yet. We can't handle it now, so we reschedule the act()
3547+ molog("FerryFleet::act: inactive, retry later\n");
3548+ return update(game, 5000);
3549+ }
3550+
3551+ molog("FerryFleet::act\n");
3552+
3553+ std::vector<Ferry*> idle_ferries;
3554+ for (Ferry* f : ferries_) {
3555+ if (f->unemployed()) {
3556+ idle_ferries.push_back(f);
3557+ }
3558+ }
3559+ while (!pending_ferry_requests_.empty() && !idle_ferries.empty()) {
3560+ // The map is sorted by ascending gametime
3561+ Waterway* ww = pending_ferry_requests_.begin()->second;
3562+
3563+ Ferry* ferry = nullptr;
3564+ int32_t shortest_distance = 0;
3565+ for (Ferry* temp_ferry : idle_ferries) {
3566+ // Decide how far this ferry is from the waterway
3567+ int32_t f_distance = game.map().findpath(
3568+ temp_ferry->get_position(), ww->base_flag().get_position(),
3569+ 0, *new Path(), CheckStepFerry(game));
3570+ if (f_distance < 0) {
3571+ log("FerryFleet(%u)::act: We have a ferry (%u at %dx%d) "
3572+ "that can't reach one of our waterways (%u at %dx%d)!\n",
3573+ serial_, temp_ferry->serial(), temp_ferry->get_position().x, temp_ferry->get_position().y,
3574+ ww->serial(), ww->base_flag().get_position().x, ww->base_flag().get_position().y);
3575+ continue;
3576+ }
3577+
3578+ if (!ferry || f_distance < shortest_distance) {
3579+ ferry = temp_ferry;
3580+ shortest_distance = f_distance;
3581+ }
3582+ }
3583+ assert(ferry);
3584+
3585+ idle_ferries.erase(std::find(idle_ferries.begin(), idle_ferries.end(), ferry));
3586+ pending_ferry_requests_.erase(pending_ferry_requests_.begin());
3587+
3588+ ferry->start_task_row(game, ww);
3589+ }
3590+
3591+ if (!pending_ferry_requests_.empty()) {
3592+ molog("... there are %" PRIuS " waterways requesting a ferry we cannot satisfy yet\n",
3593+ pending_ferry_requests_.size());
3594+ // try again later
3595+ return update(game, 5000);
3596+ }
3597+}
3598+
3599+void FerryFleet::log_general_info(const EditorGameBase& egbase) const {
3600+ MapObject::log_general_info(egbase);
3601+
3602+ molog("%" PRIuS " ferries and %" PRIuS " waterways\n", ferries_.size(), pending_ferry_requests_.size());
3603+ for (const Ferry* f : ferries_) {
3604+ molog("* Ferry %u\n", f->serial());
3605+ }
3606+ for (const auto& pair : pending_ferry_requests_) {
3607+ molog("* Waterway %u (requested at %u)\n", pair.second->serial(), pair.first);
3608+ }
3609+}
3610+
3611+constexpr uint8_t kCurrentPacketVersion = 1;
3612+
3613+FerryFleet::Loader::Loader() {
3614+}
3615+
3616+void FerryFleet::Loader::load(FileRead& fr) {
3617+ MapObject::Loader::load(fr);
3618+
3619+ FerryFleet& fleet = get<FerryFleet>();
3620+
3621+ fleet.act_pending_ = fr.unsigned_8();
3622+
3623+ const uint32_t nrferries = fr.unsigned_32();
3624+ ferries_.resize(nrferries);
3625+ for (uint32_t i = 0; i < nrferries; ++i) {
3626+ ferries_[i] = fr.unsigned_32();
3627+ }
3628+
3629+ const uint32_t nrww = fr.unsigned_32();
3630+ for (uint32_t i = 0; i < nrww; ++i) {
3631+ const uint32_t gametime = fr.unsigned_32();
3632+ const uint32_t serial = fr.unsigned_32();
3633+ pending_ferry_requests_.emplace(gametime, serial);
3634+ }
3635+}
3636+
3637+void FerryFleet::Loader::load_pointers() {
3638+ MapObject::Loader::load_pointers();
3639+
3640+ FerryFleet& fleet = get<FerryFleet>();
3641+
3642+ // Act commands created during loading are not persistent, so we need to undo any
3643+ // changes to the pending state.
3644+ bool save_act_pending = fleet.act_pending_;
3645+
3646+ for (const uint32_t& temp_ferry : ferries_) {
3647+ fleet.ferries_.push_back(&mol().get<Ferry>(temp_ferry));
3648+ fleet.ferries_.back()->set_fleet(&fleet);
3649+ }
3650+ for (const auto& temp_ww : pending_ferry_requests_) {
3651+ Waterway& ww = mol().get<Waterway>(temp_ww.second);
3652+ fleet.pending_ferry_requests_.emplace(temp_ww.first, &ww);
3653+ ww.set_fleet(&fleet);
3654+ }
3655+
3656+ fleet.act_pending_ = save_act_pending;
3657+}
3658+
3659+MapObject::Loader* FerryFleet::load(EditorGameBase& egbase, MapObjectLoader& mol, FileRead& fr) {
3660+ std::unique_ptr<Loader> loader(new Loader);
3661+
3662+ try {
3663+ // The header has been peeled away by the caller
3664+ uint8_t const packet_version = fr.unsigned_8();
3665+ if (packet_version == kCurrentPacketVersion) {
3666+ PlayerNumber owner_number = fr.unsigned_8();
3667+ if (!owner_number || owner_number > egbase.map().get_nrplayers())
3668+ throw GameDataError("owner number is %u but there are only %u players", owner_number,
3669+ egbase.map().get_nrplayers());
3670+
3671+ Player* owner = egbase.get_player(owner_number);
3672+ if (!owner)
3673+ throw GameDataError("owning player %u does not exist", owner_number);
3674+
3675+ loader->init(egbase, mol, *(new FerryFleet(owner)));
3676+ loader->load(fr);
3677+ } else {
3678+ throw UnhandledVersionError("FerryFleet", packet_version, kCurrentPacketVersion);
3679+ }
3680+ } catch (const std::exception& e) {
3681+ throw wexception("loading ferry fleet: %s", e.what());
3682+ }
3683+
3684+ return loader.release();
3685+}
3686+
3687+void FerryFleet::save(EditorGameBase& egbase, MapObjectSaver& mos, FileWrite& fw) {
3688+ fw.unsigned_8(HeaderFerryFleet);
3689+ fw.unsigned_8(kCurrentPacketVersion);
3690+
3691+ fw.unsigned_8(owner_->player_number());
3692+
3693+ MapObject::save(egbase, mos, fw);
3694+
3695+ fw.unsigned_8(act_pending_ ? 1 : 0);
3696+
3697+ fw.unsigned_32(ferries_.size());
3698+ for (const Ferry* temp_ferry : ferries_) {
3699+ fw.unsigned_32(mos.get_object_file_index(*temp_ferry));
3700+ }
3701+ fw.unsigned_32(pending_ferry_requests_.size());
3702+ for (const auto& temp_ww : pending_ferry_requests_) {
3703+ fw.unsigned_32(temp_ww.first);
3704+ fw.unsigned_32(mos.get_object_file_index(*temp_ww.second));
3705+ }
3706+}
3707+
3708+} // namespace Widelands
3709
3710=== added file 'src/economy/ferry_fleet.h'
3711--- src/economy/ferry_fleet.h 1970-01-01 00:00:00 +0000
3712+++ src/economy/ferry_fleet.h 2019-06-11 08:19:26 +0000
3713@@ -0,0 +1,123 @@
3714+/*
3715+ * Copyright (C) 2011-2019 by the Widelands Development Team
3716+ *
3717+ * This program is free software; you can redistribute it and/or
3718+ * modify it under the terms of the GNU General Public License
3719+ * as published by the Free Software Foundation; either version 2
3720+ * of the License, or (at your option) any later version.
3721+ *
3722+ * This program is distributed in the hope that it will be useful,
3723+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3724+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3725+ * GNU General Public License for more details.
3726+ *
3727+ * You should have received a copy of the GNU General Public License
3728+ * along with this program; if not, write to the Free Software
3729+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
3730+ *
3731+ */
3732+
3733+#ifndef WL_ECONOMY_FERRY_FLEET_H
3734+#define WL_ECONOMY_FERRY_FLEET_H
3735+
3736+#include <boost/shared_ptr.hpp>
3737+
3738+#include "base/macros.h"
3739+#include "logic/map_objects/map_object.h"
3740+#include "logic/widelands_geometry.h"
3741+
3742+namespace Widelands {
3743+
3744+class Economy;
3745+struct Flag;
3746+struct RoutingNodeNeighbour;
3747+struct Ferry;
3748+struct Waterway;
3749+
3750+class FerryFleetDescr : public MapObjectDescr {
3751+public:
3752+ FerryFleetDescr(char const* const init_name, char const* const init_descname)
3753+ : MapObjectDescr(MapObjectType::FERRY_FLEET, init_name, init_descname, "") {
3754+ }
3755+ ~FerryFleetDescr() override {
3756+ }
3757+
3758+private:
3759+ DISALLOW_COPY_AND_ASSIGN(FerryFleetDescr);
3760+};
3761+
3762+/**
3763+ * Manage all ferries and waterways of a player that are connected by ocean.
3764+ *
3765+ * @paragraph Lifetime
3766+ *
3767+ * Fleet objects are created on-the-fly by @ref Ferry and @ref Waterway,
3768+ * and destroy themselves when they become empty.
3769+ *
3770+ * The intention is for fleet objects to merge automatically and separate
3771+ * again in reaction to changes in the map. However, this may not work
3772+ * properly at the moment.
3773+ */
3774+struct FerryFleet : MapObject {
3775+ const FerryFleetDescr& descr() const;
3776+
3777+ explicit FerryFleet(Player* player);
3778+
3779+ bool active() const;
3780+
3781+ bool init(EditorGameBase&) override;
3782+ void cleanup(EditorGameBase&) override;
3783+ void update(EditorGameBase&, uint32_t tdelta = 100);
3784+
3785+ void add_ferry(EditorGameBase& egbase, Ferry* ferry);
3786+ void remove_ferry(EditorGameBase& egbase, Ferry* ferry);
3787+
3788+ void log_general_info(const EditorGameBase&) const override;
3789+
3790+ uint32_t count_ferries() const;
3791+ uint32_t count_unattended_waterways() const;
3792+ bool has_ferry(const Waterway& ww) const;
3793+
3794+ void request_ferry(EditorGameBase& egbase, Waterway* waterway, int32_t gametime = -1);
3795+ void reroute_ferry_request(Game& game, Waterway* oldww, Waterway* newww);
3796+ void cancel_ferry_request(Game& game, Waterway* waterway);
3797+
3798+ bool empty() const;
3799+
3800+protected:
3801+ void act(Game&, uint32_t data) override;
3802+
3803+private:
3804+ bool find_other_fleet(EditorGameBase& egbase);
3805+ bool merge(EditorGameBase& egbase, FerryFleet* other);
3806+
3807+ std::vector<Ferry*> ferries_;
3808+ std::multimap<uint32_t, Waterway*> pending_ferry_requests_;
3809+
3810+ bool act_pending_;
3811+
3812+ // saving and loading
3813+protected:
3814+ struct Loader : MapObject::Loader {
3815+ Loader();
3816+
3817+ void load(FileRead&);
3818+ void load_pointers() override;
3819+
3820+ private:
3821+ std::vector<uint32_t> ferries_;
3822+ std::multimap<uint32_t, uint32_t> pending_ferry_requests_;
3823+ };
3824+
3825+public:
3826+ bool has_new_save_support() override {
3827+ return true;
3828+ }
3829+ void save(EditorGameBase&, MapObjectSaver&, FileWrite&) override;
3830+
3831+ static MapObject::Loader* load(EditorGameBase&, MapObjectLoader&, FileRead&);
3832+};
3833+
3834+} // namespace Widelands
3835+
3836+#endif // end of include guard: WL_ECONOMY_FERRY_FLEET_H
3837
3838=== modified file 'src/economy/flag.cc'
3839--- src/economy/flag.cc 2019-02-23 11:00:49 +0000
3840+++ src/economy/flag.cc 2019-06-11 08:19:26 +0000
3841@@ -26,6 +26,7 @@
3842 #include "economy/request.h"
3843 #include "economy/road.h"
3844 #include "economy/ware_instance.h"
3845+#include "economy/waterway.h"
3846 #include "logic/editor_game_base.h"
3847 #include "logic/game.h"
3848 #include "logic/map_objects/map_object.h"
3849@@ -112,7 +113,7 @@
3850 /**
3851 * Creates a flag at the given location.
3852 */
3853-Flag::Flag(EditorGameBase& egbase, Player* owning_player, const Coords& coords, Economy* eco)
3854+Flag::Flag(EditorGameBase& egbase, Player* owning_player, const Coords& coords, Economy* ware_eco, Economy* worker_eco)
3855 : PlayerImmovable(g_flag_descr),
3856 building_(nullptr),
3857 ware_capacity_(8),
3858@@ -127,25 +128,32 @@
3859
3860 set_flag_position(coords);
3861
3862- upcast(Road, road, egbase.map().get_immovable(coords));
3863+ upcast(RoadBase, road, egbase.map().get_immovable(coords));
3864 upcast(Game, game, &egbase);
3865
3866 if (game) {
3867- if (eco) {
3868- // We're saveloading
3869- eco->add_flag(*this);
3870- } else {
3871- // we split a road, or a new, standalone flag is created
3872- (road ? road->get_economy() : owning_player->create_economy())->add_flag(*this);
3873- if (road) {
3874- road->presplit(*game, coords);
3875- }
3876+ if (ware_eco) {
3877+ // We're saveloading
3878+ ware_eco->add_flag(*this);
3879+ } else {
3880+ // we split a road, or a new, standalone flag is created
3881+ (road ? road->get_economy(wwWARE) : owning_player->create_economy(wwWARE))->add_flag(*this);
3882+ }
3883+ if (worker_eco) {
3884+ // We're saveloading
3885+ worker_eco->add_flag(*this);
3886+ } else {
3887+ // we split a road, or a new, standalone flag is created
3888+ (road ? road->get_economy(wwWORKER) : owning_player->create_economy(wwWORKER))->add_flag(*this);
3889+ }
3890+ if (road && !ware_eco && !worker_eco) {
3891+ road->presplit(*game, coords);
3892 }
3893 }
3894
3895 init(egbase);
3896
3897- if (!eco && road && game) {
3898+ if (!ware_eco && !worker_eco && road && game) {
3899 road->postsplit(*game, *this);
3900 }
3901 }
3902@@ -169,30 +177,34 @@
3903 /**
3904 * Call this only from Economy code!
3905 */
3906-void Flag::set_economy(Economy* const e) {
3907- Economy* const old = get_economy();
3908+void Flag::set_economy(Economy* const e, WareWorker type) {
3909+ Economy* const old = get_economy(type);
3910
3911 if (old == e) {
3912 return;
3913 }
3914
3915- PlayerImmovable::set_economy(e);
3916+ PlayerImmovable::set_economy(e, type);
3917
3918- for (int32_t i = 0; i < ware_filled_; ++i) {
3919- wares_[i].ware->set_economy(e);
3920+ if (type == wwWARE) {
3921+ for (int32_t i = 0; i < ware_filled_; ++i) {
3922+ wares_[i].ware->set_economy(e);
3923+ }
3924 }
3925
3926 if (building_) {
3927- building_->set_economy(e);
3928+ building_->set_economy(e, type);
3929 }
3930
3931 for (const FlagJob& temp_job : flag_jobs_) {
3932- temp_job.request->set_economy(e);
3933+ if (temp_job.request->get_type() == type) {
3934+ temp_job.request->set_economy(e);
3935+ }
3936 }
3937
3938 for (int8_t i = 0; i < 6; ++i) {
3939 if (roads_[i]) {
3940- roads_[i]->set_economy(e);
3941+ roads_[i]->set_economy(e, type);
3942 }
3943 }
3944 }
3945@@ -207,10 +219,11 @@
3946
3947 const Map& map = egbase.map();
3948 egbase.set_road(
3949- map.get_fcoords(map.tl_n(position_)), RoadType::kSouthEast,
3950+ map.get_fcoords(map.tl_n(position_)), WALK_SE,
3951 building_->get_size() == BaseImmovable::SMALL ? RoadType::kNormal : RoadType::kBusy);
3952
3953- building.set_economy(get_economy());
3954+ building.set_economy(get_economy(wwWARE), wwWARE);
3955+ building.set_economy(get_economy(wwWORKER), wwWORKER);
3956 }
3957
3958 /**
3959@@ -219,31 +232,34 @@
3960 void Flag::detach_building(EditorGameBase& egbase) {
3961 assert(building_);
3962
3963- building_->set_economy(nullptr);
3964+ building_->set_economy(nullptr, wwWARE);
3965+ building_->set_economy(nullptr, wwWORKER);
3966
3967 const Map& map = egbase.map();
3968- egbase.set_road(map.get_fcoords(map.tl_n(position_)), RoadType::kSouthEast, RoadType::kNone);
3969+ egbase.set_road(map.get_fcoords(map.tl_n(position_)), WALK_SE, RoadType::kNone);
3970
3971 building_ = nullptr;
3972 }
3973
3974 /**
3975- * Call this only from the Road init!
3976+ * Call this only from the RoadBase init!
3977 */
3978-void Flag::attach_road(int32_t const dir, Road* const road) {
3979+void Flag::attach_road(int32_t const dir, RoadBase* const road) {
3980 assert(!roads_[dir - 1] || roads_[dir - 1] == road);
3981
3982 roads_[dir - 1] = road;
3983- roads_[dir - 1]->set_economy(get_economy());
3984+ roads_[dir - 1]->set_economy(get_economy(wwWARE), wwWARE);
3985+ roads_[dir - 1]->set_economy(get_economy(wwWORKER), wwWORKER);
3986 }
3987
3988 /**
3989- * Call this only from the Road init!
3990+ * Call this only from the RoadBase init!
3991 */
3992 void Flag::detach_road(int32_t const dir) {
3993 assert(roads_[dir - 1]);
3994
3995- roads_[dir - 1]->set_economy(nullptr);
3996+ roads_[dir - 1]->set_economy(nullptr, wwWARE);
3997+ roads_[dir - 1]->set_economy(nullptr, wwWORKER);
3998 roads_[dir - 1] = nullptr;
3999 }
4000
4001@@ -261,18 +277,23 @@
4002 */
4003 void Flag::get_neighbours(WareWorker type, RoutingNodeNeighbours& neighbours) {
4004 for (int8_t i = 0; i < 6; ++i) {
4005- Road* const road = roads_[i];
4006+ RoadBase* const road = roads_[i];
4007 if (!road) {
4008 continue;
4009 }
4010
4011- Flag* f = &road->get_flag(Road::FlagEnd);
4012+ // Only wares, workers cannot use ferries
4013+ if (Waterway::is_waterway_descr(&road->descr()) && type == wwWORKER) {
4014+ continue;
4015+ }
4016+
4017+ Flag* f = &road->get_flag(RoadBase::FlagEnd);
4018 int32_t nb_cost;
4019 if (f != this) {
4020- nb_cost = road->get_cost(Road::FlagStart);
4021+ nb_cost = road->get_cost(RoadBase::FlagStart);
4022 } else {
4023- f = &road->get_flag(Road::FlagStart);
4024- nb_cost = road->get_cost(Road::FlagEnd);
4025+ f = &road->get_flag(RoadBase::FlagStart);
4026+ nb_cost = road->get_cost(RoadBase::FlagEnd);
4027 }
4028 if (type == wwWARE) {
4029 nb_cost += nb_cost * (get_waitcost() + f->get_waitcost()) / 2;
4030@@ -294,10 +315,20 @@
4031 /**
4032 * \return the road that leads to the given flag.
4033 */
4034+RoadBase* Flag::get_roadbase(Flag& flag) {
4035+ for (int8_t i = 0; i < 6; ++i) {
4036+ if (RoadBase* const road = roads_[i]) {
4037+ if (&road->get_flag(RoadBase::FlagStart) == &flag || &road->get_flag(RoadBase::FlagEnd) == &flag) {
4038+ return road;
4039+ }
4040+ }
4041+ }
4042+ return nullptr;
4043+}
4044 Road* Flag::get_road(Flag& flag) {
4045- for (int8_t i = 0; i < 6; ++i) {
4046- if (Road* const road = roads_[i]) {
4047- if (&road->get_flag(Road::FlagStart) == &flag || &road->get_flag(Road::FlagEnd) == &flag) {
4048+ for (int8_t i = 1; i <= 6; ++i) {
4049+ if (Road* const road = get_road(i)) {
4050+ if (&road->get_flag(RoadBase::FlagStart) == &flag || &road->get_flag(RoadBase::FlagEnd) == &flag) {
4051 return road;
4052 }
4053 }
4054@@ -305,11 +336,46 @@
4055 return nullptr;
4056 }
4057
4058+Road* Flag::get_road(uint8_t const dir) const {
4059+ if (roads_[dir - 1] && Road::is_road_descr(&roads_[dir - 1]->descr())) {
4060+ return dynamic_cast<Road*>(roads_[dir - 1]);
4061+ }
4062+ return nullptr;
4063+}
4064+Waterway* Flag::get_waterway(uint8_t const dir) const {
4065+ if (roads_[dir - 1] && Waterway::is_waterway_descr(&roads_[dir - 1]->descr())) {
4066+ return dynamic_cast<Waterway*>(roads_[dir - 1]);
4067+ }
4068+ return nullptr;
4069+}
4070+
4071+/// \return the number of RoadBases connected to the flag
4072+uint8_t Flag::nr_of_roadbases() const {
4073+ uint8_t counter = 0;
4074+ for (uint8_t road_id = 6; road_id; --road_id) {
4075+ if (get_roadbase(road_id) != nullptr) {
4076+ ++counter;
4077+ }
4078+ }
4079+ return counter;
4080+}
4081+
4082 /// \return the number of roads connected to the flag.
4083 uint8_t Flag::nr_of_roads() const {
4084 uint8_t counter = 0;
4085 for (uint8_t road_id = 6; road_id; --road_id) {
4086- if (get_road(road_id) != nullptr) {
4087+ if (get_roadbase(road_id) != nullptr) {
4088+ ++counter;
4089+ }
4090+ }
4091+ return counter;
4092+}
4093+
4094+/// \return the number of waterways connected to the flag.
4095+uint8_t Flag::nr_of_waterways() const {
4096+ uint8_t counter = 0;
4097+ for (uint8_t road_id = 6; road_id; --road_id) {
4098+ if (get_waterway(road_id) != nullptr) {
4099 ++counter;
4100 }
4101 }
4102@@ -322,9 +388,9 @@
4103 }
4104 Flag const* first_other_flag = nullptr;
4105 for (uint8_t road_id = 6; road_id; --road_id) {
4106- if (Road* const road = get_road(road_id)) {
4107- Flag& start = road->get_flag(Road::FlagStart);
4108- Flag& other = this == &start ? road->get_flag(Road::FlagEnd) : start;
4109+ if (RoadBase* const road = get_roadbase(road_id)) {
4110+ Flag& start = road->get_flag(RoadBase::FlagStart);
4111+ Flag& other = this == &start ? road->get_flag(RoadBase::FlagEnd) : start;
4112 if (first_other_flag) {
4113 if (&other != first_other_flag)
4114 return false;
4115@@ -557,7 +623,7 @@
4116 // Calculate the sum of the involved wallets' adjusted value
4117 int32_t sum = 0;
4118 for (int8_t i = 0; i < WalkingDir::LAST_DIRECTION; ++i) {
4119- Road* const road = roads_[i];
4120+ Road* const road = get_road(i);
4121 if (road && road != promoted_road) {
4122 sum += kRoadMaxWallet + road->wallet() * road->wallet();
4123 }
4124@@ -565,7 +631,7 @@
4125
4126 // Distribute propagation coins in a smart way
4127 for (int8_t i = 0; i < WalkingDir::LAST_DIRECTION; ++i) {
4128- Road* const road = roads_[i];
4129+ Road* const road = get_road(i);
4130 if (road && road->get_roadtype() != RoadType::kBusy) {
4131 road->add_to_wallet(0.5 * (kRoadMaxWallet - road->wallet()) *
4132 (kRoadMaxWallet + road->wallet() * road->wallet()) / sum);
4133@@ -684,20 +750,20 @@
4134 const Flag& nextflag = dynamic_cast<const Flag&>(*nextstep);
4135
4136 for (int32_t dir = 1; dir <= 6; ++dir) {
4137- Road* const road = get_road(dir);
4138+ RoadBase* const road = get_roadbase(dir);
4139 Flag* other;
4140- Road::FlagId flagid;
4141+ RoadBase::FlagId flagid;
4142
4143 if (!road) {
4144 continue;
4145 }
4146
4147- if (&road->get_flag(Road::FlagStart) == this) {
4148- flagid = Road::FlagStart;
4149- other = &road->get_flag(Road::FlagEnd);
4150+ if (&road->get_flag(RoadBase::FlagStart) == this) {
4151+ flagid = RoadBase::FlagStart;
4152+ other = &road->get_flag(RoadBase::FlagEnd);
4153 } else {
4154- flagid = Road::FlagEnd;
4155- other = &road->get_flag(Road::FlagStart);
4156+ flagid = RoadBase::FlagEnd;
4157+ other = &road->get_flag(RoadBase::FlagStart);
4158 }
4159
4160 if (other != &nextflag) {
4161@@ -775,7 +841,10 @@
4162 }
4163 }
4164
4165- if (Economy* e = get_economy()) {
4166+ if (Economy* e = get_economy(wwWARE)) {
4167+ e->remove_flag(*this);
4168+ }
4169+ if (Economy* e = get_economy(wwWORKER)) {
4170 e->remove_flag(*this);
4171 }
4172
4173
4174=== modified file 'src/economy/flag.h'
4175--- src/economy/flag.h 2019-04-24 06:01:37 +0000
4176+++ src/economy/flag.h 2019-06-11 08:19:26 +0000
4177@@ -33,7 +33,9 @@
4178 namespace Widelands {
4179 class Building;
4180 class Request;
4181+struct RoadBase;
4182 struct Road;
4183+struct Waterway;
4184 class WareInstance;
4185
4186 class FlagDescr : public MapObjectDescr {
4187@@ -51,9 +53,10 @@
4188 /**
4189 * Flag represents a flag as you see it on the map.
4190 *
4191- * A flag itself doesn't do much. However, it can have up to 6 roads attached
4192- * to it. Instead of the WALK_NW road, it can also have a building attached to
4193- * it. Flags also have a store of up to 8 wares.
4194+ * A flag itself doesn't do much. However, it can have up to 6 roads/waterways
4195+ * attached to it. Instead of the WALK_NW road, it can also have a building
4196+ * attached to it. It cannot have more than one waterway.
4197+ * Flags also have a store of up to 8 wares.
4198 *
4199 * You can also assign an arbitrary number of "jobs" for a flag.
4200 * A job consists of a request for a worker, and the name of a program that the
4201@@ -80,7 +83,8 @@
4202
4203 /// Create a new flag. Only specify an economy during saveloading.
4204 /// Otherwise, a new economy will be created automatically if needed.
4205- Flag(EditorGameBase&, Player* owner, const Coords&, Economy* economy = nullptr);
4206+ Flag(EditorGameBase&, Player* owner, const Coords&,
4207+ Economy* ware_economy = nullptr, Economy* worker_economy = nullptr);
4208 ~Flag() override;
4209
4210 void load_finish(EditorGameBase&) override;
4211@@ -100,7 +104,7 @@
4212 return ware_filled_;
4213 }
4214
4215- void set_economy(Economy*) override;
4216+ void set_economy(Economy*, WareWorker) override;
4217
4218 Building* get_building() const {
4219 return building_;
4220@@ -108,16 +112,27 @@
4221 void attach_building(EditorGameBase&, Building&);
4222 void detach_building(EditorGameBase&);
4223
4224+ bool has_roadbase() const {
4225+ return roads_[0] || roads_[1] || roads_[2] || roads_[3] || roads_[4] || roads_[5];
4226+ }
4227+ bool has_waterway() const {
4228+ return nr_of_waterways() > 0;
4229+ }
4230 bool has_road() const {
4231- return roads_[0] || roads_[1] || roads_[2] || roads_[3] || roads_[4] || roads_[5];
4232+ return nr_of_roads() > 0;
4233 }
4234- Road* get_road(uint8_t const dir) const {
4235+ RoadBase* get_roadbase(uint8_t dir) const {
4236 return roads_[dir - 1];
4237 }
4238+ Road* get_road(uint8_t dir) const;
4239+ Waterway* get_waterway(uint8_t dir) const;
4240+ uint8_t nr_of_roadbases() const;
4241 uint8_t nr_of_roads() const;
4242- void attach_road(int32_t dir, Road*);
4243+ uint8_t nr_of_waterways() const;
4244+ void attach_road(int32_t dir, RoadBase*);
4245 void detach_road(int32_t dir);
4246
4247+ RoadBase* get_roadbase(Flag&);
4248 Road* get_road(Flag&);
4249
4250 bool is_dead_end() const;
4251@@ -184,7 +199,7 @@
4252 int32_t animstart_;
4253
4254 Building* building_; ///< attached building (replaces road WALK_NW)
4255- Road* roads_[WalkingDir::LAST_DIRECTION];
4256+ RoadBase* roads_[WalkingDir::LAST_DIRECTION];
4257
4258 int32_t ware_capacity_; ///< size of wares_ array
4259 int32_t ware_filled_; ///< number of wares currently on the flag
4260
4261=== modified file 'src/economy/idleworkersupply.cc'
4262--- src/economy/idleworkersupply.cc 2019-02-23 11:00:49 +0000
4263+++ src/economy/idleworkersupply.cc 2019-06-11 08:19:26 +0000
4264@@ -36,7 +36,7 @@
4265 * Automatically register with the worker's economy.
4266 */
4267 IdleWorkerSupply::IdleWorkerSupply(Worker& w) : worker_(w), economy_(nullptr) {
4268- set_economy(w.get_economy());
4269+ set_economy(w.get_economy(wwWORKER));
4270 }
4271
4272 /**
4273
4274=== modified file 'src/economy/input_queue.cc'
4275--- src/economy/input_queue.cc 2019-02-23 11:00:49 +0000
4276+++ src/economy/input_queue.cc 2019-06-11 08:19:26 +0000
4277@@ -175,8 +175,9 @@
4278 throw UnhandledVersionError("InputQueue", packet_version, kCurrentPacketVersion);
4279 }
4280 // Now Economy stuff. We have to add our filled items to the economy.
4281- if (owner_.get_economy())
4282- add_to_economy(*owner_.get_economy());
4283+ if (owner_.get_economy(type_)) {
4284+ add_to_economy(*owner_.get_economy(type_));
4285+ }
4286 } catch (const GameDataError& e) {
4287 throw GameDataError("inputqueue: %s", e.what());
4288 }
4289@@ -186,12 +187,15 @@
4290 fw.unsigned_16(kCurrentPacketVersion);
4291
4292 // Owner and callback is not saved, but this should be obvious on load.
4293- if (type_ == wwWARE) {
4294- fw.unsigned_8(0);
4295- fw.c_string(owner().tribe().get_ware_descr(index_)->name().c_str());
4296- } else {
4297- fw.unsigned_8(1);
4298- fw.c_string(owner().tribe().get_worker_descr(index_)->name().c_str());
4299+ switch (type_) {
4300+ case wwWARE:
4301+ fw.unsigned_8(0);
4302+ fw.c_string(owner().tribe().get_ware_descr(index_)->name().c_str());
4303+ break;
4304+ case wwWORKER:
4305+ fw.unsigned_8(1);
4306+ fw.c_string(owner().tribe().get_worker_descr(index_)->name().c_str());
4307+ break;
4308 }
4309 fw.signed_32(max_size_);
4310 fw.signed_32(max_fill_);
4311
4312=== modified file 'src/economy/portdock.cc'
4313--- src/economy/portdock.cc 2019-05-26 10:09:28 +0000
4314+++ src/economy/portdock.cc 2019-06-11 08:19:26 +0000
4315@@ -26,7 +26,7 @@
4316 #include "base/log.h"
4317 #include "base/macros.h"
4318 #include "economy/expedition_bootstrap.h"
4319-#include "economy/fleet.h"
4320+#include "economy/ship_fleet.h"
4321 #include "economy/ware_instance.h"
4322 #include "economy/wares_queue.h"
4323 #include "io/filewrite.h"
4324@@ -83,11 +83,11 @@
4325 }
4326
4327 /**
4328- * Update which @ref Fleet we belong to.
4329+ * Update which @ref ShipFleet we belong to.
4330 *
4331- * @warning This should only be called via @ref Fleet itself.
4332+ * @warning This should only be called via @ref ShipFleet itself.
4333 */
4334-void PortDock::set_fleet(Fleet* fleet) {
4335+void PortDock::set_fleet(ShipFleet* fleet) {
4336 fleet_ = fleet;
4337 }
4338
4339@@ -125,24 +125,27 @@
4340 * Signal to the dock that it now belongs to the given economy.
4341 *
4342 * Called by @ref Warehouse::set_economy, and responsible for forwarding the
4343- * change to @ref Fleet.
4344+ * change to @ref ShipFleet.
4345 */
4346-void PortDock::set_economy(Economy* e) {
4347- if (e == get_economy())
4348+void PortDock::set_economy(Economy* e, WareWorker type) {
4349+ if (e == get_economy(type)) {
4350 return;
4351+ }
4352
4353- PlayerImmovable::set_economy(e);
4354- if (fleet_)
4355- fleet_->set_economy(e);
4356+ PlayerImmovable::set_economy(e, type);
4357+ if (fleet_) {
4358+ fleet_->set_economy(e, type);
4359+ }
4360
4361 if (upcast(Game, game, &get_owner()->egbase())) {
4362 for (ShippingItem& shipping_item : waiting_) {
4363- shipping_item.set_economy(*game, e);
4364+ shipping_item.set_economy(*game, e, type);
4365 }
4366 }
4367
4368- if (expedition_bootstrap_)
4369- expedition_bootstrap_->set_economy(e);
4370+ if (expedition_bootstrap_) {
4371+ expedition_bootstrap_->set_economy(e, type);
4372+ }
4373 }
4374
4375 void PortDock::draw(
4376@@ -162,11 +165,11 @@
4377 }
4378
4379 /**
4380- * Create our initial singleton @ref Fleet. The fleet code ensures
4381+ * Create our initial singleton @ref ShipFleet. The fleet code ensures
4382 * that we merge with a larger fleet when possible.
4383 */
4384 void PortDock::init_fleet(EditorGameBase& egbase) {
4385- Fleet* fleet = new Fleet(get_owner());
4386+ ShipFleet* fleet = new ShipFleet(get_owner());
4387 fleet->add_port(egbase, this);
4388 fleet->init(egbase);
4389 // Note: the Fleet calls our set_fleet automatically
4390@@ -292,7 +295,7 @@
4391 assert(dst != this);
4392
4393 // Destination might have vanished or be in another economy altogether.
4394- if (dst && dst->get_economy() == get_economy()) {
4395+ if (dst && dst->get_economy(wwWARE) == get_economy(wwWARE) && dst->get_economy(wwWORKER) == get_economy(wwWORKER)) {
4396 if (ships_coming_ <= 0) {
4397 set_need_ship(game, true);
4398 }
4399@@ -440,12 +443,15 @@
4400 Worker* worker;
4401 shipping_item.get(owner().egbase(), &ware, &worker);
4402
4403- if (waretype == wwWORKER) {
4404- if (worker && worker->descr().worker_index() == wareindex)
4405- count++;
4406- } else {
4407- if (ware && ware->descr_index() == wareindex)
4408- count++;
4409+ switch (waretype) {
4410+ case wwWORKER:
4411+ if (worker && worker->descr().worker_index() == wareindex)
4412+ count++;
4413+ break;
4414+ case wwWARE:
4415+ if (ware && ware->descr_index() == wareindex)
4416+ count++;
4417+ break;
4418 }
4419 }
4420
4421
4422=== modified file 'src/economy/portdock.h'
4423--- src/economy/portdock.h 2019-04-24 06:51:31 +0000
4424+++ src/economy/portdock.h 2019-06-11 08:19:26 +0000
4425@@ -30,7 +30,7 @@
4426
4427 namespace Widelands {
4428
4429-struct Fleet;
4430+struct ShipFleet;
4431 struct RoutingNodeNeighbour;
4432 struct Ship;
4433 class Warehouse;
4434@@ -68,7 +68,7 @@
4435 * port that is on a land bridge and therefore close to two
4436 * disconnected bodies of water. Such a port would have to have
4437 * two PortDock that belong to the same @ref Warehouse, but have
4438- * separate @ref Fleet instances.
4439+ * separate @ref ShipFleet instances.
4440 * However, we expect this to be such a rare case that it is not
4441 * implemented at the moment.
4442 */
4443@@ -82,13 +82,13 @@
4444 void add_position(Widelands::Coords where);
4445 Warehouse* get_warehouse() const;
4446
4447- Fleet* get_fleet() const {
4448+ ShipFleet* get_fleet() const {
4449 return fleet_;
4450 }
4451 PortDock* get_dock(Flag& flag) const;
4452 uint32_t get_need_ship() const;
4453
4454- void set_economy(Economy*) override;
4455+ void set_economy(Economy*, WareWorker) override;
4456
4457 int32_t get_size() const override;
4458 bool get_passable() const override;
4459@@ -138,14 +138,14 @@
4460 void expedition_bootstrap_complete(Game& game);
4461
4462 private:
4463- friend struct Fleet;
4464+ friend struct ShipFleet;
4465
4466 void init_fleet(EditorGameBase& egbase);
4467- void set_fleet(Fleet* fleet);
4468+ void set_fleet(ShipFleet* fleet);
4469 void update_shippingitem(Game&, std::list<ShippingItem>::iterator);
4470 void set_need_ship(Game&, bool need);
4471
4472- Fleet* fleet_;
4473+ ShipFleet* fleet_;
4474 Warehouse* warehouse_;
4475 PositionList dockpoints_;
4476 std::list<ShippingItem> waiting_;
4477
4478=== modified file 'src/economy/request.cc'
4479--- src/economy/request.cc 2019-02-23 11:00:49 +0000
4480+++ src/economy/request.cc 2019-06-11 08:19:26 +0000
4481@@ -57,7 +57,7 @@
4482 target_productionsite_(dynamic_cast<ProductionSite*>(&init_target)),
4483 target_warehouse_(dynamic_cast<Warehouse*>(&init_target)),
4484 target_constructionsite_(dynamic_cast<ConstructionSite*>(&init_target)),
4485- economy_(init_target.get_economy()),
4486+ economy_(init_target.get_economy(w)),
4487 index_(index),
4488 count_(1),
4489 exact_match_(false),
4490@@ -175,12 +175,15 @@
4491 // Target and economy should be set. Same is true for callback stuff.
4492
4493 assert(type_ == wwWARE || type_ == wwWORKER);
4494- if (type_ == wwWARE) {
4495- assert(game.tribes().ware_exists(index_));
4496- fw.c_string(game.tribes().get_ware_descr(index_)->name());
4497- } else if (type_ == wwWORKER) {
4498- assert(game.tribes().worker_exists(index_));
4499- fw.c_string(game.tribes().get_worker_descr(index_)->name());
4500+ switch (type_) {
4501+ case wwWARE:
4502+ assert(game.tribes().ware_exists(index_));
4503+ fw.c_string(game.tribes().get_ware_descr(index_)->name());
4504+ break;
4505+ case wwWORKER:
4506+ assert(game.tribes().worker_exists(index_));
4507+ fw.c_string(game.tribes().get_worker_descr(index_)->name());
4508+ break;
4509 }
4510
4511 fw.unsigned_32(count_);
4512@@ -385,20 +388,25 @@
4513 ss.unsigned_32(supp.get_position(game)->serial());
4514
4515 Transfer* t;
4516- if (get_type() == wwWORKER) {
4517- // Begin the transfer of a soldier or worker.
4518- // launch_worker() creates or starts the worker
4519- Worker& s = supp.launch_worker(game, *this);
4520- ss.unsigned_32(s.serial());
4521- t = new Transfer(game, *this, s);
4522- } else {
4523- // Begin the transfer of an ware. The ware itself is passive.
4524- // launch_ware() ensures the WareInstance is transported out of the
4525- // warehouse. Once it's on the flag, the flag code will decide what to
4526- // do with it.
4527- WareInstance& ware = supp.launch_ware(game, *this);
4528- ss.unsigned_32(ware.serial());
4529- t = new Transfer(game, *this, ware);
4530+ switch (get_type()) {
4531+ case wwWORKER: {
4532+ // Begin the transfer of a soldier or worker.
4533+ // launch_worker() creates or starts the worker
4534+ Worker& s = supp.launch_worker(game, *this);
4535+ ss.unsigned_32(s.serial());
4536+ t = new Transfer(game, *this, s);
4537+ break;
4538+ }
4539+ case wwWARE: {
4540+ // Begin the transfer of an ware. The ware itself is passive.
4541+ // launch_ware() ensures the WareInstance is transported out of the
4542+ // warehouse. Once it's on the flag, the flag code will decide what to
4543+ // do with it.
4544+ WareInstance& ware = supp.launch_ware(game, *this);
4545+ ss.unsigned_32(ware.serial());
4546+ t = new Transfer(game, *this, ware);
4547+ break;
4548+ }
4549 }
4550
4551 transfers_.push_back(t);
4552
4553=== modified file 'src/economy/road.cc'
4554--- src/economy/road.cc 2019-02-23 11:00:49 +0000
4555+++ src/economy/road.cc 2019-06-11 08:19:26 +0000
4556@@ -37,32 +37,23 @@
4557 const RoadDescr g_road_descr("road", "Road");
4558 }
4559
4560-const RoadDescr& Road::descr() const {
4561- return g_road_descr;
4562-}
4563-
4564 bool Road::is_road_descr(MapObjectDescr const* const descr) {
4565 return descr == &g_road_descr;
4566 }
4567
4568+Road::CarrierSlot::CarrierSlot() : carrier(nullptr), carrier_request(nullptr), second_carrier(false) {
4569+}
4570+
4571 /**
4572 * Most of the actual work is done in init.
4573 */
4574 Road::Road()
4575- : PlayerImmovable(g_road_descr), wallet_(0), last_wallet_charge_(0), type_(0), idle_index_(0) {
4576- flags_[0] = flags_[1] = nullptr;
4577- flagidx_[0] = flagidx_[1] = -1;
4578-
4579- // Initialize the worker slots for the road
4580- // TODO(unknown): make this configurable
4581+ : RoadBase(g_road_descr, RoadType::kNone), wallet_(0), last_wallet_charge_(0) {
4582 CarrierSlot slot;
4583- carrier_slots_.push_back(slot);
4584- carrier_slots_.push_back(slot);
4585- carrier_slots_[0].carrier_type = 1;
4586- carrier_slots_[1].carrier_type = 2;
4587-}
4588-
4589-Road::CarrierSlot::CarrierSlot() : carrier(nullptr), carrier_request(nullptr), carrier_type(0) {
4590+ carrier_slots_.push_back(slot);
4591+ carrier_slots_.push_back(slot);
4592+ carrier_slots_[0].second_carrier = false;
4593+ carrier_slots_[1].second_carrier = true;
4594 }
4595
4596 /**
4597@@ -95,185 +86,9 @@
4598 return road;
4599 }
4600
4601-int32_t Road::get_size() const {
4602- return SMALL;
4603-}
4604-
4605-bool Road::get_passable() const {
4606- return true;
4607-}
4608-
4609-BaseImmovable::PositionList Road::get_positions(const EditorGameBase& egbase) const {
4610- const Map& map = egbase.map();
4611- Coords curf = map.get_fcoords(path_.get_start());
4612-
4613- PositionList rv;
4614- const Path::StepVector::size_type nr_steps = path_.get_nsteps();
4615- for (Path::StepVector::size_type steps = 0; steps < nr_steps + 1; ++steps) {
4616- if (steps > 0 && steps < path_.get_nsteps())
4617- rv.push_back(curf);
4618-
4619- if (steps < path_.get_nsteps())
4620- map.get_neighbour(curf, path_[steps], &curf);
4621- }
4622- return rv;
4623-}
4624-
4625-Flag& Road::base_flag() {
4626- return *flags_[FlagStart];
4627-}
4628-
4629-/**
4630- * Return the cost of getting from fromflag to the other flag.
4631- */
4632-int32_t Road::get_cost(FlagId fromflag) {
4633- return cost_[fromflag];
4634-}
4635-
4636-/**
4637- * Set the new path, calculate costs.
4638- * You have to set start and end flags before calling this function.
4639- */
4640-void Road::set_path(EditorGameBase& egbase, const Path& path) {
4641- assert(path.get_nsteps() >= 2);
4642- assert(path.get_start() == flags_[FlagStart]->get_position());
4643- assert(path.get_end() == flags_[FlagEnd]->get_position());
4644-
4645- path_ = path;
4646- egbase.map().calc_cost(path, &cost_[FlagStart], &cost_[FlagEnd]);
4647-
4648- // Figure out where carriers should idle
4649- idle_index_ = path.get_nsteps() / 2;
4650-}
4651-
4652-/**
4653- * Add road markings to the map
4654- */
4655-void Road::mark_map(EditorGameBase& egbase) {
4656- const Map& map = egbase.map();
4657- FCoords curf = map.get_fcoords(path_.get_start());
4658-
4659- const Path::StepVector::size_type nr_steps = path_.get_nsteps();
4660- for (Path::StepVector::size_type steps = 0; steps < nr_steps + 1; ++steps) {
4661- if (steps > 0 && steps < path_.get_nsteps())
4662- set_position(egbase, curf);
4663-
4664- // mark the road that leads up to this field
4665- if (steps > 0) {
4666- const Direction dir = get_reverse_dir(path_[steps - 1]);
4667- Direction const rdir = 2 * (dir - WALK_E);
4668-
4669- if (rdir <= 4)
4670- egbase.set_road(curf, rdir, type_);
4671- }
4672-
4673- // mark the road that leads away from this field
4674- if (steps < path_.get_nsteps()) {
4675- const Direction dir = path_[steps];
4676- Direction const rdir = 2 * (dir - WALK_E);
4677-
4678- if (rdir <= 4)
4679- egbase.set_road(curf, rdir, type_);
4680-
4681- map.get_neighbour(curf, dir, &curf);
4682- }
4683- }
4684-}
4685-
4686-/**
4687- * Remove road markings from the map
4688- */
4689-void Road::unmark_map(EditorGameBase& egbase) {
4690- const Map& map = egbase.map();
4691- FCoords curf(path_.get_start(), &map[path_.get_start()]);
4692-
4693- const Path::StepVector::size_type nr_steps = path_.get_nsteps();
4694- for (Path::StepVector::size_type steps = 0; steps < nr_steps + 1; ++steps) {
4695- if (steps > 0 && steps < path_.get_nsteps())
4696- unset_position(egbase, curf);
4697-
4698- // mark the road that leads up to this field
4699- if (steps > 0) {
4700- const Direction dir = get_reverse_dir(path_[steps - 1]);
4701- Direction const rdir = 2 * (dir - WALK_E);
4702-
4703- if (rdir <= 4)
4704- egbase.set_road(curf, rdir, RoadType::kNone);
4705- }
4706-
4707- // mark the road that leads away from this field
4708- if (steps < path_.get_nsteps()) {
4709- const Direction dir = path_[steps];
4710- Direction const rdir = 2 * (dir - WALK_E);
4711-
4712- if (rdir <= 4)
4713- egbase.set_road(curf, rdir, RoadType::kNone);
4714-
4715- map.get_neighbour(curf, dir, &curf);
4716- }
4717- }
4718-}
4719-
4720-/**
4721- * Initialize the road.
4722- */
4723-bool Road::init(EditorGameBase& egbase) {
4724- PlayerImmovable::init(egbase);
4725-
4726- if (2 <= path_.get_nsteps())
4727- link_into_flags(egbase);
4728- return true;
4729-}
4730-
4731-/**
4732- * This links into the flags, calls a carrier
4733- * and so on. This was formerly done in init (and
4734- * still is for normal games). But for save game loading
4735- * we needed to have this road already registered
4736- * as Map Object, thats why this is moved
4737- */
4738-void Road::link_into_flags(EditorGameBase& egbase) {
4739- assert(path_.get_nsteps() >= 2);
4740-
4741- // Link into the flags (this will also set our economy)
4742- {
4743- const Direction dir = path_[0];
4744- flags_[FlagStart]->attach_road(dir, this);
4745- flagidx_[FlagStart] = dir;
4746- }
4747-
4748- const Direction dir = get_reverse_dir(path_[path_.get_nsteps() - 1]);
4749- flags_[FlagEnd]->attach_road(dir, this);
4750- flagidx_[FlagEnd] = dir;
4751-
4752- Economy::check_merge(*flags_[FlagStart], *flags_[FlagEnd]);
4753-
4754- // Mark Fields
4755- mark_map(egbase);
4756-
4757- /*
4758- * Iterate over all Carrierslots
4759- * If a carrier is set assign it to this road, else
4760- * request a new carrier
4761- */
4762- if (upcast(Game, game, &egbase)) {
4763- for (CarrierSlot& slot : carrier_slots_) {
4764- if (Carrier* const carrier = slot.carrier.get(*game)) {
4765- // This happens after a road split. Tell the carrier what's going on.
4766- carrier->set_location(this);
4767- carrier->update_task_road(*game);
4768- } else if (!slot.carrier_request && (slot.carrier_type == 1 || type_ == RoadType::kBusy)) {
4769- request_carrier(slot);
4770- }
4771- }
4772- }
4773-}
4774-
4775-/**
4776- * Cleanup the road
4777- */
4778 void Road::cleanup(EditorGameBase& egbase) {
4779-
4780+ Economy::check_split(*flags_[FlagStart], *flags_[FlagEnd], wwWARE);
4781+ Economy::check_split(*flags_[FlagStart], *flags_[FlagEnd], wwWORKER);
4782 for (CarrierSlot& slot : carrier_slots_) {
4783 delete slot.carrier_request;
4784 slot.carrier_request = nullptr;
4785@@ -281,34 +96,34 @@
4786 // carrier will be released via PlayerImmovable::cleanup
4787 slot.carrier = nullptr;
4788 }
4789-
4790- // Unmark Fields
4791- unmark_map(egbase);
4792-
4793- // Unlink from flags (also clears the economy)
4794- flags_[FlagStart]->detach_road(flagidx_[FlagStart]);
4795- flags_[FlagEnd]->detach_road(flagidx_[FlagEnd]);
4796-
4797- Economy::check_split(*flags_[FlagStart], *flags_[FlagEnd]);
4798-
4799+ RoadBase::cleanup(egbase);
4800+}
4801+
4802+void Road::link_into_flags(EditorGameBase& egbase, bool) {
4803+ RoadBase::link_into_flags(egbase);
4804+ Economy::check_merge(*flags_[FlagStart], *flags_[FlagEnd], wwWARE);
4805+ Economy::check_merge(*flags_[FlagStart], *flags_[FlagEnd], wwWORKER);
4806 if (upcast(Game, game, &egbase)) {
4807- flags_[FlagStart]->update_wares(*game, flags_[FlagEnd]);
4808- flags_[FlagEnd]->update_wares(*game, flags_[FlagStart]);
4809+ for (CarrierSlot& slot : carrier_slots_) {
4810+ if (Carrier* const carrier = slot.carrier.get(*game)) {
4811+ // This happens after a road split. Tell the carrier what's going on.
4812+ carrier->set_location(this);
4813+ carrier->update_task_road(*game);
4814+ } else if (!slot.carrier_request && (!slot.second_carrier || get_roadtype() == RoadType::kBusy)) {
4815+ // Normal carriers are requested at once, second carriers only for busy roads
4816+ request_carrier(slot);
4817+ }
4818+ }
4819 }
4820-
4821- PlayerImmovable::cleanup(egbase);
4822 }
4823
4824-/**
4825- * Workers' economies are fixed by PlayerImmovable, but we need to handle
4826- * any requests ourselves.
4827- */
4828-void Road::set_economy(Economy* const e) {
4829- PlayerImmovable::set_economy(e);
4830-
4831- for (CarrierSlot& slot : carrier_slots_) {
4832- if (slot.carrier_request) {
4833- slot.carrier_request->set_economy(e);
4834+void Road::set_economy(Economy* const e, WareWorker type) {
4835+ RoadBase::set_economy(e, type);
4836+ if (type == wwWORKER) {
4837+ for (CarrierSlot& slot : carrier_slots_) {
4838+ if (slot.carrier_request) {
4839+ slot.carrier_request->set_economy(e);
4840+ }
4841 }
4842 }
4843 }
4844@@ -320,12 +135,8 @@
4845 * been issued.
4846 */
4847 void Road::request_carrier(CarrierSlot& slot) {
4848- if (slot.carrier_type == 1)
4849- slot.carrier_request =
4850- new Request(*this, owner().tribe().carrier(), Road::request_carrier_callback, wwWORKER);
4851- else
4852- slot.carrier_request =
4853- new Request(*this, owner().tribe().carrier2(), Road::request_carrier_callback, wwWORKER);
4854+ slot.carrier_request = new Request(*this, slot.second_carrier ? owner().tribe().carrier2() :
4855+ owner().tribe().carrier(), request_carrier_callback, wwWORKER);
4856 }
4857
4858 /**
4859@@ -400,15 +211,6 @@
4860 }
4861
4862 /**
4863- * A flag has been placed that splits this road. This function is called before
4864- * the new flag initializes. We remove markings to avoid interference with the
4865- * flag.
4866- */
4867-void Road::presplit(Game& game, Coords) {
4868- unmark_map(game);
4869-}
4870-
4871-/**
4872 * The flag that splits this road has been initialized. Perform the actual
4873 * splitting.
4874 *
4875@@ -499,7 +301,7 @@
4876 old_slot.carrier = nullptr;
4877 for (CarrierSlot& new_slot : newroad.carrier_slots_) {
4878 if (!new_slot.carrier.get(game) && !new_slot.carrier_request &&
4879- new_slot.carrier_type == old_slot.carrier_type) {
4880+ new_slot.second_carrier == old_slot.second_carrier) {
4881 upcast(Carrier, new_carrier, w);
4882 new_slot.carrier = new_carrier;
4883 break;
4884@@ -528,7 +330,7 @@
4885 // work correctly
4886 for (CarrierSlot& slot : carrier_slots_) {
4887 if (!slot.carrier.get(game) && !slot.carrier_request &&
4888- (slot.carrier_type == 1 || type_ == RoadType::kBusy)) {
4889+ (!slot.second_carrier || type_ == RoadType::kBusy)) {
4890 request_carrier(slot);
4891 }
4892 }
4893@@ -615,7 +417,7 @@
4894 flags_[1]->propagate_promoted_road(this);
4895 mark_map(game);
4896 for (CarrierSlot& slot : carrier_slots_) {
4897- if (!slot.carrier.get(game) && !slot.carrier_request && slot.carrier_type != 1) {
4898+ if (!slot.carrier.get(game) && !slot.carrier_request && slot.second_carrier) {
4899 request_carrier(slot);
4900 }
4901 }
4902
4903=== modified file 'src/economy/road.h'
4904--- src/economy/road.h 2019-04-24 06:01:37 +0000
4905+++ src/economy/road.h 2019-06-11 08:19:26 +0000
4906@@ -23,18 +23,17 @@
4907 #include <vector>
4908
4909 #include "base/macros.h"
4910-#include "logic/map_objects/immovable.h"
4911+#include "economy/roadbase.h"
4912 #include "logic/path.h"
4913 #include "logic/roadtype.h"
4914
4915 namespace Widelands {
4916-struct Carrier;
4917 class Request;
4918
4919-class RoadDescr : public MapObjectDescr {
4920+class RoadDescr : public RoadBaseDescr {
4921 public:
4922- RoadDescr(char const* const init_name, char const* const init_descname)
4923- : MapObjectDescr(MapObjectType::ROAD, init_name, init_descname, "") {
4924+ explicit RoadDescr(char const* const init_name, char const* const init_descname)
4925+ : RoadBaseDescr(init_name, init_descname, MapObjectType::ROAD) {
4926 }
4927 ~RoadDescr() override {
4928 }
4929@@ -48,72 +47,34 @@
4930 // https://stackoverflow.com/questions/40690260/undefined-reference-error-for-static-constexpr-member
4931 constexpr int32_t kRoadAnimalPrice = 600;
4932 constexpr int32_t kRoadMaxWallet = static_cast<int32_t>(2.5 * kRoadAnimalPrice);
4933-
4934 /**
4935- * Road is a special object which connects two flags.
4936- * The Road itself is never rendered; however, the appropriate Field::roads are
4937- * set to represent the road visually.
4938- * The actual steps involved in a road are stored as a Path from the starting
4939- * flag to the ending flag. Apart from that, however, the two flags are treated
4940- * exactly the same, as far as most transactions are concerned. There are minor
4941- * exceptions: placement of carriers if the path's length is odd, splitting
4942- * a road when a flag is inserted.
4943- *
4944- * Every road has one or more Carriers attached to it. Carriers are attached
4945+ * Every Road has one or more Carriers attached to it. Carriers are attached
4946 * when they arrive via the callback function passed to the request. The
4947 * callback then calls assign_carrier which incorporates this carrier on this
4948- * road.
4949+ * Road.
4950 */
4951-struct Road : public PlayerImmovable {
4952+struct Road : public RoadBase {
4953 friend class MapRoaddataPacket; // For saving
4954 friend class MapRoadPacket; // For init()
4955
4956- const RoadDescr& descr() const;
4957-
4958 static bool is_road_descr(MapObjectDescr const*);
4959
4960- enum FlagId { FlagStart = 0, FlagEnd = 1 };
4961-
4962+ explicit Road();
4963+ ~Road() override;
4964+
4965+ static Road& create(EditorGameBase&, Flag& start, Flag& end, const Path&);
4966+
4967+ // A CarrierSlot can store a carrier.
4968 struct CarrierSlot {
4969 CarrierSlot();
4970
4971 OPtr<Carrier> carrier;
4972 Request* carrier_request;
4973- uint8_t carrier_type;
4974+ bool second_carrier;
4975 };
4976
4977- Road();
4978- ~Road() override;
4979-
4980- static Road& create(EditorGameBase&, Flag& start, Flag& end, const Path&);
4981-
4982- Flag& get_flag(FlagId const flag) const {
4983- return *flags_[flag];
4984- }
4985-
4986- uint8_t get_roadtype() const {
4987- return type_;
4988- }
4989- int32_t get_size() const override;
4990- bool get_passable() const override;
4991- PositionList get_positions(const EditorGameBase&) const override;
4992-
4993- Flag& base_flag() override;
4994-
4995- void set_economy(Economy*) override;
4996-
4997- int32_t get_cost(FlagId fromflag);
4998- const Path& get_path() const {
4999- return path_;
5000- }
The diff has been truncated for viewing.