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

Proposed by Benedikt Straub on 2018-07-31
Status: Work in progress
Proposed branch: lp:~widelands-dev/widelands/ferry
Merge into: lp:widelands
Diff against target: 14509 lines (+5809/-1922) (has conflicts)
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 (+1/-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 (+59/-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 (+58/-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 (+58/-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 (+63/-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 (+33/-24)
src/ai/defaultai_seafaring.cc (+1/-1)
src/economy/CMakeLists.txt (+8/-2)
src/economy/cmd_call_economy_balance.cc (+23/-5)
src/economy/cmd_call_economy_balance.h (+1/-0)
src/economy/economy.cc (+217/-260)
src/economy/economy.h (+39/-48)
src/economy/economy_data_packet.cc (+97/-54)
src/economy/economy_data_packet.h (+4/-1)
src/economy/expedition_bootstrap.cc (+38/-27)
src/economy/expedition_bootstrap.h (+3/-2)
src/economy/ferry_fleet.cc (+502/-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 (+30/-22)
src/economy/portdock.h (+7/-7)
src/economy/request.cc (+29/-21)
src/economy/road.cc (+39/-237)
src/economy/road.h (+28/-84)
src/economy/roadbase.cc (+228/-0)
src/economy/roadbase.h (+120/-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 (+15/-11)
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/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 (+322/-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 (+58/-32)
src/logic/map_objects/tribes/ship.h (+16/-12)
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/-0)
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 (+92/-27)
src/logic/player.h (+23/-10)
src/logic/playercommand.cc (+99/-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 (+31/-9)
src/map_io/map_object_loader.cc (+27/-0)
src/map_io/map_object_loader.h (+6/-0)
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 (+10/-12)
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 (+6/-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 (+48/-24)
src/wui/economy_options_window.h (+9/-4)
src/wui/fieldaction.cc (+166/-48)
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)
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)
Text conflict in src/economy/economy.cc
Text conflict in src/wui/economy_options_window.cc
Text conflict in src/wui/fieldaction.cc
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 (community) 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...

lp:~widelands-dev/widelands/ferry updated on 2019-06-21
8885. By Nordfriese on 2019-06-21

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5208. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/548539708.
Appveyor build 4987. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-4987.

lp:~widelands-dev/widelands/ferry updated on 2019-06-28
8886. By Nordfriese on 2019-06-28

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5251. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/551745114.
Appveyor build 5030. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-5030.

lp:~widelands-dev/widelands/ferry updated on 2019-06-28
8887. By Nordfriese on 2019-06-28

Merge conflicts

8888. By Nordfriese on 2019-06-28

Merge conflicts

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5254. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/551923331.
Appveyor build 5033. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-5033.

lp:~widelands-dev/widelands/ferry updated on 2019-08-09
8889. By Nordfriese on 2019-08-09

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5300. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/569856062.
Appveyor build 5073. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-5073.

Benedikt Straub (nordfriese) wrote :

What´s the status here?

Klaus Halfmann (klaus-halfmann) wrote :

Ohh, what a history, but I must confess , I lost track.

Can we merge this now (as only map with a falg are affcetd anyway?)

TiborB (tiborb95) wrote :

The status regarding AI is that it is not supported and probably not be anytime soon if ever.

kaputtnik (franku) wrote :

Will it be problem if the AI can't handle ferrys?

Need this branch more testing?

Benedikt Straub (nordfriese) wrote :

The AI will simply ignore the new feature, it will continue playing exactly as before. There are some AI code parts that should be looked into eventually (I added TODOs there), but they should most likely have no effect whatever as long as it doesn´t build a waterway.

This branch was tested quite extensively, IMHO it would be better to merge this now and report any bugs that might still be contained against trunk. (Only downside is that this branch breaks savegame compatibility.)

TiborB (tiborb95) wrote :

I am also for merging into trunk to get better testing.
Personally I dont like splitting the economy into two parallel economies, but if there is a consensus about this...

kaputtnik (franku) wrote :

I get some text conflicts when merging trunk. Benedikt, can look into this and make the call for merging?

Benedikt Straub (nordfriese) wrote :

I just had an idea how I might just perhaps be able to write savegame compatibility, give me a few days to try it out...

lp:~widelands-dev/widelands/ferry updated on 2019-08-29
8890. By GunChleoc on 2019-08-29

Code review.

GunChleoc (gunchleoc) wrote :

I have pushed a new commit with a code style review. I'll have to return later to go through the discussion.

lp:~widelands-dev/widelands/ferry updated on 2019-08-29
8891. By Nordfriese on 2019-08-29

Addressed code review

8892. By Nordfriese on 2019-08-29

Merged trunk

8893. By GunChleoc on 2019-08-29

More code review & code style fixes.

8894. By GunChleoc on 2019-08-29

Remove obsolete NOCOM comments.

GunChleoc (gunchleoc) wrote :

I have pushed another commit with code review. I'm done with this for now. I also did a grep on data and test for lua changes, and it looks like we didn't miss anything.

The following 2 bits in the code are a bit complicated and could do with testing:

* worker creation over multiple economies
* Barracks
* ferry paths, especially around coasts

For ferry oceans separated very narrowly, how about allowing portage there? This might simplify the CheckStepFerry.
https://en.wikipedia.org/wiki/Portage
Just an idea, don't feel obligagted to implement this.

The following new Lua functions don't have tests yet (we can implement those in a follow-up branch though):
* get_waterway_max_length
* set_waterway_max_length
* get_ferry

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5359. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/578495337.
Appveyor build 5129. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-5129.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5359. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/578495337.
Appveyor build 5129. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-5129.

lp:~widelands-dev/widelands/ferry updated on 2019-08-31
8895. By Nordfriese on 2019-08-31

Savegame compatibility

Benedikt Straub (nordfriese) wrote :

Savegame compatibility hack is up :)
Thanks for the review and codestyle.

lp:~widelands-dev/widelands/ferry updated on 2019-08-31
8896. By GunChleoc on 2019-08-31

Code review

GunChleoc (gunchleoc) wrote :

I have pushed a commit with a comment.

lp:~widelands-dev/widelands/ferry updated on 2019-09-02
8897. By Nordfriese on 2019-09-02

Addressed code review

Benedikt Straub (nordfriese) wrote :

Implemented your suggestion for Ferry and clarified the comment in EconomyDataPacket.
Economy::create_requested_workers is called directly from balance() for every economy, so we can just ignore it for ware ecos.

lp:~widelands-dev/widelands/ferry updated on 2019-09-03
8898. By GunChleoc on 2019-09-03

Fix clang compiler warnings.

GunChleoc (gunchleoc) wrote :

I have pushed a commit that shuts up clang compiler warnings, so you need to pull before continuing to work.

I think that Checkstep should ignore waterways that don't have ferries - I have attached a savegame to illustrate the issue.

https://bugs.launchpad.net/widelands/+bug/1584203/comments/47

GunChleoc (gunchleoc) wrote :

And another thing that can be improved in checkstep, but will probably be non-trivial:

https://bugs.launchpad.net/widelands/+bug/1584203/comments/48

I'd be OK with doing this in a follow-up branch.

GunChleoc (gunchleoc) wrote :

When I have 2 economies only liked by a waterway, the metal workshop won't produce the necessary wares - I expect the request is generated by the wrong warehouse.

Savegame: https://bugs.launchpad.net/widelands/+bug/1584203/comments/50

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5382. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/580127580.
Appveyor build 5152. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-5152.

kaputtnik (franku) wrote :

Looks like the metal workshop 'hangs', it always shows 'The Economy doesn't need the ware Bradpaddle', although the game run more than 5 Minutes.

Benedikt Straub (nordfriese) wrote :

No, the workshop just skips everything because no tools are needed. I´m trying to implement that the tools will be transported from one warehouse to another one so the missing workers can be created in the correct economy…

GunChleoc (gunchleoc) wrote :

Hm, at this point I'm wondering whether it might be easier to allow ferries to carry workers and have them waiting for it at the nearest flag. Then we would not need the separate economies.

lp:~widelands-dev/widelands/ferry updated on 2019-09-07
8899. By Nordfriese on 2019-09-07

Fix worker creation across economies

Benedikt Straub (nordfriese) wrote :

Pushed a fix for worker creation. As soon as you now trigger an economy update (e.g. by building a flag), the necessary tools are transported from the HQ to the warehouse and there turned into workers.

lp:~widelands-dev/widelands/ferry updated on 2019-09-07
8900. By Nordfriese on 2019-09-07

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5408. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/582051006.
Appveyor build 5178. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-5178.

lp:~widelands-dev/widelands/ferry updated on 2019-09-08
8901. By Nordfriese on 2019-09-08

Fixed merge conflicts

8902. By Nordfriese on 2019-09-08

Compile error

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 5418. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/582382256.
Appveyor build 5188. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_ferry-5188.

Unmerged revisions

8902. By Nordfriese on 2019-09-08

Compile error

8901. By Nordfriese on 2019-09-08

Fixed merge conflicts

8900. By Nordfriese on 2019-09-07

Merged trunk

8899. By Nordfriese on 2019-09-07

Fix worker creation across economies

8898. By GunChleoc on 2019-09-03

Fix clang compiler warnings.

8897. By Nordfriese on 2019-09-02

Addressed code review

8896. By GunChleoc on 2019-08-31

Code review

8895. By Nordfriese on 2019-08-31

Savegame compatibility

8894. By GunChleoc on 2019-08-29

Remove obsolete NOCOM comments.

8893. By GunChleoc on 2019-08-29

More code review & code style fixes.

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