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

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

Description of the change

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

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

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

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

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

Continuous integration builds have changed state:

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

Teppo Mäenpää (kxq) wrote :

I get a compiler error on 8780:

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

Benedikt Straub (nordfriese) wrote :

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

Teppo Mäenpää (kxq) wrote :

Now I got it, thanks.

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Fixed merge conflicts

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Fixed ferry cancelling to row to destination

8804. By Nordfriese on 2018-11-22

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Seperated WareEconomy and WorkerEconomy

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Fixed compiler errors

8807. By Nordfriese on 2018-11-23

It works./widelands !

8808. By Nordfriese on 2018-11-23

Nicer log output

8809. By Nordfriese on 2018-11-23

Removed a strange crash

8810. By Nordfriese on 2018-11-23

Finally fixed the economy bug

8811. By Nordfriese on 2018-11-23

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Various fixes

8813. By Nordfriese on 2018-11-24

Fixed wares/workers in warehouses being counted twice

8814. By Nordfriese on 2018-11-24

Fixed crash on waterway cleanup

8815. By Nordfriese on 2018-11-24

Fixed crash on request rerouting

Benedikt Straub (nordfriese) wrote :

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

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

Show ferry yards only on ferry maps

8817. By Nordfriese on 2018-11-24

Fixed codecheck warning

8818. By Nordfriese on 2018-11-24

Fixed compile error

TiborB (tiborb95) wrote :

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

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

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

Benedikt Straub (nordfriese) wrote :

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

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

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

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

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

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

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

Merged trunk

8820. By Nordfriese on 2018-11-25

Fixed a typo

Benedikt Straub (nordfriese) wrote :

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

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

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

GunChleoc (gunchleoc) wrote :

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

Benedikt Straub (nordfriese) wrote :

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

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

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

8823. By Nordfriese on 2018-11-26

More debug output

8824. By Nordfriese on 2018-11-26

Merged trunk

8825. By Nordfriese on 2018-11-28

Fixing a bug in the pathfinding

8826. By Nordfriese on 2018-11-28

Fixing the testsuite

8827. By Nordfriese on 2018-11-28

Fixed compile error

8828. By Nordfriese on 2018-11-29

Fixed segfault when loading waterway

Benedikt Straub (nordfriese) wrote :

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

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

Do not balance expedition economies

8830. By Nordfriese on 2018-11-29

Fixing the test suite…

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Silence gcc complaint

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Add map tag »ferries«

8833. By Nordfriese on 2018-12-02

Fixing a bug with roadbuilding overlays. Removed RoadInfo again.

8834. By Nordfriese on 2018-12-02

Compiler error

8835. By Nordfriese on 2018-12-02

Overlooked a corner case for roadbuilding

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

merged trunk

8838. By Nordfriese on 2019-03-08

Documentation fix

8839. By Nordfriese on 2019-03-08

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

GunChleoc (gunchleoc) wrote :

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

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

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

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

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

Removed ferry animations

8843. By Nordfriese on 2019-03-23

Merged trunk

8844. By Nordfriese on 2019-03-23

Adressed first code review

8845. By Nordfriese on 2019-03-23

Changed buildcost for barbarian ferry yard

8846. By Nordfriese on 2019-03-23

Deleted some more images

8847. By Nordfriese on 2019-03-23

Stronger waterway textures

Benedikt Straub (nordfriese) wrote :

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

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

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

Fixed codecheck

8849. By Nordfriese on 2019-03-23

Quickfix for startup error

8850. By Nordfriese on 2019-03-24

Merged trunk

8851. By GunChleoc on 2019-03-24

Code review.

GunChleoc (gunchleoc) wrote :

The overlays look fine now, thank you.

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

Some notes that are not in the review commit:

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

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

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

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

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

Started to adress code review

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Fixed request creation for simultanously created waterways

Benedikt Straub (nordfriese) wrote :

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

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

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

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

GunChleoc (gunchleoc) wrote :

I did not think of the several oceans problem.

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

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

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

Implemented remaining diff comments and fixed a crash

8855. By Nordfriese on 2019-03-25

Merged trunk

8856. By Nordfriese on 2019-03-26

Make travis happy

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Merged trunk

8858. By Nordfriese on 2019-04-04

Fixed loadgame bug

8859. By Nordfriese on 2019-04-07

Improved ferry movement rules and cleaned up economy code

8860. By Nordfriese on 2019-04-07

Fixed bug in ferry assignment on waterway split

8861. By Nordfriese on 2019-04-07

Trigger economy balance when corresponding economy receives wares/workers

Benedikt Straub (nordfriese) wrote :

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

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

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

Undid accidental change

8863. By Nordfriese on 2019-04-07

Renamed duplicate StepEvalFindFleet

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

Benedikt Straub (nordfriese) wrote :

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

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

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

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

Small cleanup and better debug info

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Fixing the test suite

8866. By Nordfriese on 2019-04-09

Fixed duplication of fleets during loading

8867. By Nordfriese on 2019-04-13

fixed bug 1824586

kaputtnik (franku) wrote :

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

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

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

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

merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

GunChleoc (gunchleoc) wrote :

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

Benedikt Straub (nordfriese) wrote :

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

GunChleoc (gunchleoc) wrote :

Sounds like a plan :)

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

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Fixing the testsuite

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Open fieldaction instead of starting roadbuilding if waterway can be built

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

Benedikt Straub (nordfriese) wrote :

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

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

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

Klaus Halfmann (klaus-halfmann) wrote :

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

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

Klaus Halfmann (klaus-halfmann) wrote :

CLang gives me some comppiler warnings:

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

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

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

You should see them in the automated builds, too

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

Removed some unused variables

Benedikt Straub (nordfriese) wrote :

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

Klaus Halfmann (klaus-halfmann) wrote :

Plaaying Calvission for a while now:

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

Klaus Halfmann (klaus-halfmann) wrote :

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

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

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

I got a saveagme and some movie showing the Problem.

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

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

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

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

Fixed workers walking on waterways

Benedikt Straub (nordfriese) wrote :

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

Klaus Halfmann (klaus-halfmann) wrote :

I now get a compile Error at:

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Compile error

8876. By Nordfriese on 2019-05-02

Compile error

Klaus Halfmann (klaus-halfmann) wrote :

Loading may savegame I now get:

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

Do I have to restart that Map now?

Benedikt Straub (nordfriese) wrote :

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

GunChleoc (gunchleoc) wrote :

Fieldaction code looks OK.

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

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

Errors in some cases

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

Klaus Halfmann (klaus-halfmann) wrote :

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

Got an assert aftree trying to build two woodcutters:

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

....

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

Do you need a savegame?

review: Needs Fixing
Benedikt Straub (nordfriese) wrote :

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

Klaus Halfmann (klaus-halfmann) wrote :

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

Ferries2.wgf (Multiplayer Game)

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

Some transfer confusion

Benedikt Straub (nordfriese) wrote :

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

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

Klaus Halfmann (klaus-halfmann) wrote :

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

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

Lets get this decided soon.

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

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

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

Will merge trunk soon to fix the diverging

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

Merged trunk

GunChleoc (gunchleoc) wrote :

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

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

Merged trunk

8881. By Nordfriese on 2019-05-28

Corrected thatch_reed → reed

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Codecheck complains

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

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

Merged trunk

bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

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

Klaus Halfmann (klaus-halfmann) wrote :

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

GunChleoc (gunchleoc) wrote :

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

TiborB (tiborb95) wrote :

I added some question in the diff

TiborB (tiborb95) wrote :

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

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

Benedikt Straub (nordfriese) wrote :

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

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

TiborB (tiborb95) wrote :

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

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

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

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

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

These are just few thougts for discussion...

TiborB (tiborb95) wrote :

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

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

Benedikt Straub (nordfriese) wrote :

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

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

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

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

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

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

TiborB (tiborb95) wrote :

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

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

TiborB (tiborb95) wrote :

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

Benedikt Straub (nordfriese) wrote :

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

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

Add some functions to query waterways and ferryfleets

TiborB (tiborb95) wrote :

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

Benedikt Straub (nordfriese) wrote :

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

TiborB (tiborb95) wrote :

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

TiborB (tiborb95) wrote :

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

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

TiborB (tiborb95) wrote :

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

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

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

Benedikt Straub (nordfriese) wrote :

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

> It would be nice if the ferries were per economy

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

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

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

TiborB (tiborb95) wrote :

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

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

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

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

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

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

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

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.

Unmerged revisions

8889. By Nordfriese on 2019-08-09

Merged trunk

8888. By Nordfriese on 2019-06-28

Merge conflicts

8887. By Nordfriese on 2019-06-28

Merge conflicts

8886. By Nordfriese on 2019-06-28

Merged trunk

8885. By Nordfriese on 2019-06-21

Merged trunk

8884. By Nordfriese on 2019-06-11

Add some functions to query waterways and ferryfleets

8883. By Nordfriese on 2019-05-31

Merged trunk

8882. By Nordfriese on 2019-05-28

Codecheck complains

8881. By Nordfriese on 2019-05-28

Corrected thatch_reed → reed

8880. By Nordfriese on 2019-05-26

Merged trunk

Preview Diff

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