← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands

 

TiborB has proposed merging lp:~widelands-dev/widelands/seafaring-ai into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/seafaring-ai/+merge/242271

Hi, after some time this is ready for review, read the branch info for more info.

Tested a lot as AI-only games, I would welcome a human players tests and feedback.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/seafaring-ai into lp:widelands.
=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h	2014-10-30 20:24:57 +0000
+++ src/ai/ai_help_structs.h	2014-11-19 21:19:43 +0000
@@ -32,6 +32,8 @@
 #include "logic/player.h"
 #include "logic/world/terrain_description.h"
 #include "logic/world/world.h"
+#include "logic/ship.h"
+#include <unordered_set>
 
 namespace Widelands {
 
@@ -227,10 +229,10 @@
 	int16_t military_stationed_;
 	// stationed (manned) military buildings nearby
 	int16_t military_unstationed_;
-	// some buildings must be postponed bit
-	int32_t prohibited_till_;
-	// and then some must be forced
-	int32_t forced_after_;
+	bool is_portspace_;
+	// bool portspace_nearby_; // to prohibit buildings near a portspace Not needed?
+	bool port_nearby_;  // to increase priority if a port is nearby,
+	// especially for new colonies
 
 	std::vector<uint8_t> consumers_nearby_;
 	std::vector<uint8_t> producers_nearby_;
@@ -261,7 +263,9 @@
 	     military_loneliness_(1000),
 	     military_in_constr_nearby_(0),
 	     military_presence_(0),
-	     military_stationed_(0) {
+	     military_stationed_(0),
+	     is_portspace_(false),
+	     port_nearby_(false) {
 	}
 };
 
@@ -310,12 +314,14 @@
 	bool plants_trees_;
 	bool recruitment_;  // is "producing" workers?
 	bool is_buildable_;
-	bool need_trees_;          // lumberjack = true
-	bool need_stones_;         // quarry = true
-	bool mines_water_;         // wells
-	bool need_water_;          // fisher, fish_breeder = true
-	bool is_hunter_;           // need to identify hunters
-	bool is_fisher_;           // need to identify fishers
+	bool need_trees_;   // lumberjack = true
+	bool need_stones_;  // quarry = true
+	bool mines_water_;  // wells
+	bool need_water_;   // fisher, fish_breeder = true
+	bool is_hunter_;    // need to identify hunters
+	bool is_fisher_;    // need to identify fishers
+	bool is_port_;
+	bool is_shipyard_;
 	bool space_consumer_;      // farm, vineyard... = true
 	bool expansion_type_;      // military building used that can be used to control area
 	bool fighting_type_;       // military building built near enemies
@@ -327,7 +333,6 @@
 
 	int32_t mines_;           // type of resource it mines_
 	uint16_t mines_percent_;  // % of res it can mine
-
 	uint32_t current_stats_;
 
 	std::vector<int16_t> inputs_;
@@ -372,6 +377,25 @@
 	bool enemies_nearby_;
 };
 
+struct TrainingSiteObserver {
+	Widelands::TrainingSite* site;
+	BuildingObserver* bo;
+};
+
+struct WarehouseSiteObserver {
+	Widelands::Warehouse* site;
+	BuildingObserver* bo;
+};
+
+struct ShipObserver {
+	Widelands::Ship* ship;
+	Widelands::Coords expedition_start_point_;
+	std::unordered_set<uint32_t> visited_spots_;
+	bool island_circ_direction = true;  // a ship circumvents all island in the same direction
+	bool waiting_for_command_ = false;
+	int32_t last_command_time = 0;
+};
+
 struct WareObserver {
 	uint8_t producers_;
 	uint8_t consumers_;

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2014-11-03 06:45:32 +0000
+++ src/ai/defaultai.cc	2014-11-19 21:19:43 +0000
@@ -6,7 +6,7 @@
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful,
+ * This program is distributed in the hope that it will be useful,n
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -31,7 +31,9 @@
 #include "base/macros.h"
 #include "economy/economy.h"
 #include "economy/flag.h"
+#include "economy/portdock.h"
 #include "economy/road.h"
+#include "economy/wares_queue.h"
 #include "logic/constructionsite.h"
 #include "logic/findbob.h"
 #include "logic/findimmovable.h"
@@ -39,15 +41,19 @@
 #include "logic/map.h"
 #include "logic/militarysite.h"
 #include "logic/player.h"
+#include "logic/playercommand.h"
 #include "logic/productionsite.h"
+#include "logic/ship.h"
 #include "logic/trainingsite.h"
 #include "logic/tribe.h"
 #include "logic/warehouse.h"
 #include "logic/world/world.h"
 #include "profile/profile.h"
 
+
 // Building of new military buildings can be restricted
 constexpr int kPushExpansion = 1;
+
 constexpr int kResourcesOrDefense = 2;
 constexpr int kDefenseOnly = 3;
 constexpr int kNoNewMilitary = 4;
@@ -59,6 +65,10 @@
 // building of the same building can be started after 25s at earliest
 constexpr int kBuildingMinInterval = 25 * 1000;
 constexpr int kMinBFCheckInterval = 5 * 1000;
+constexpr int kShipCheckInterval = 5 * 1000;
+constexpr int kMarineDecisionInterval = 20 * 1000;
+constexpr int kTrainingSitesCheckInterval = 30 * 1000;
+
 // Some buildings have to be built close to borders and their
 // priority might be decreased below 0, so this is to
 // compensate
@@ -81,6 +91,7 @@
      num_constructionsites_(0),
      num_milit_constructionsites(0),
      num_prod_constructionsites(0),
+     num_ports(0),
      next_road_due_(2000),
      next_stats_update_due_(30000),
      next_construction_due_(1000),
@@ -88,9 +99,12 @@
      next_productionsite_check_due_(0),
      next_mine_check_due_(0),
      next_militarysite_check_due_(0),
+     next_ship_check_due(5 * 60 * 1000),
+     next_marine_decisions_due(5 * 60 * 1000),
      next_attack_consideration_due_(300000),
-     next_helpersites_check_due_(180000),
+     next_trainingsites_check_due_(15 * 60 * 1000),
      next_bf_check_due_(1000),
+     next_wares_review_due_(5 * 60 * 1000),  // review
      inhibit_road_building_(0),
      time_of_last_construction_(0),
      enemy_last_seen_(-2 * 60 * 1000),
@@ -103,15 +117,17 @@
      resource_necessity_water_needed_(false),
      unstationed_milit_buildings_(0),
      military_last_dismantle_(0),
-     military_last_build_(-60 * 1000),
-	last_attack_target_(
+	 military_last_build_(-60 * 1000),
+	 last_attack_target_(
         std::numeric_limits<uint16_t>::max(), std::numeric_limits<uint16_t>::max()),
      next_attack_waittime_(10),
+     seafaring_economy(false),
+     colony_scan_area_(35),
      spots_(0) {
 
 	// Subscribe to NoteFieldPossession.
 	field_possession_subscriber_ =
-	   Notifications::subscribe<NoteFieldPossession>([this](const NoteFieldPossession& note) {
+		Notifications::subscribe<NoteFieldPossession>([this](const NoteFieldPossession& note) {
 			if (note.player != player_) {
 			   return;
 		   }
@@ -137,12 +153,47 @@
 	outofresource_subscriber_ = Notifications::subscribe<NoteProductionSiteOutOfResources>(
 	   [this](const NoteProductionSiteOutOfResources& note) {
 			if (note.ps->owner().player_number() != player_->player_number()) {
+			   // if (note.ps->owner().player_number() != pid) {
 			   return;
 		   }
 
 		   out_of_resources_site(*note.ps);
 
 		});
+
+	// Subscribe to ShipNotes.
+	shipnotes_subscriber_ =
+	   Notifications::subscribe<NoteShipMessage>([this](const NoteShipMessage& note) {
+			if (note.ship->get_owner()->player_number() != player_->player_number()) {
+			   // if (note.ship->get_owner()->player_number() != pid) {
+			   return;
+		   }
+
+			if (note.message == NoteShipMessage::Message::GAINED) {
+			   marineTaskQueue_.push_back(STOPSHIPYARD);
+
+			   allships.push_back(ShipObserver());
+			   allships.back().ship = note.ship;
+				if (game().get_gametime() % 2 == 0) {
+				   allships.back().island_circ_direction = true;
+			   } else {
+				   allships.back().island_circ_direction = false;
+			   }
+
+		   } else if (note.message == NoteShipMessage::Message::LOST) {
+			   for (std::list<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i)
+					if (i->ship == note.ship) {
+					   allships.erase(i);
+					   break;
+				   }
+		   } else if (note.message == NoteShipMessage::Message::WAITINGFORCOMMAND) {
+			   for (std::list<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i)
+					if (i->ship == note.ship) {
+					   i->waiting_for_command_ = true;
+					   break;
+				   }
+		   }
+		});
 }
 
 DefaultAI::~DefaultAI() {
@@ -169,7 +220,7 @@
  */
 void DefaultAI::think() {
 
-	if (tribe_ == nullptr) {
+	if (tribe_ == nullptr || player_ == nullptr) {
 		late_initialization();
 	}
 
@@ -238,6 +289,14 @@
 		return;
 	}
 
+	if (check_ships(gametime)) {
+		return;
+	}
+
+	if (marine_main_decisions(gametime)) {
+		return;
+	}
+
 	// Check the mines and consider upgrading or destroying one
 	if (check_mines_(gametime)) {
 		return;
@@ -249,6 +308,10 @@
 		return;
 	}
 
+	if (check_trainingsites(gametime)) {
+		return;
+	}
+
 	// improve existing roads!
 	// main part of this improvment is creation 'shortcut roads'
 	// this includes also connection of new buildings
@@ -257,6 +320,12 @@
 		m_mineable_changed = true;
 		return;
 	}
+
+	// once in 15 minutes we increase(or decrease) targets for wares
+	if (next_wares_review_due_ <= gametime) {
+		next_wares_review_due_ = gametime + 15 * 60 * 1000;
+		review_wares_targets(gametime);
+	}
 }
 
 /**
@@ -317,6 +386,7 @@
 		bo.mountain_conqueror_ = bh.is_mountain_conqueror();
 		bo.prohibited_till_ = bh.get_prohibited_till() * 1000;  // value in conf is in seconds
 		bo.forced_after_ = bh.get_forced_after() * 1000;        // value in conf is in seconds
+		bo.is_port_ = bld.get_isport();
 		if (char const* const s = bh.get_renews_map_resource()) {
 			bo.production_hint_ = tribe_->safe_ware_index(s);
 		}
@@ -362,6 +432,13 @@
 			} else {
 				bo.is_fisher_ = false;
 			}
+
+			if (building_name == "shipyard") {
+				bo.is_shipyard_ = true;
+			} else {
+				bo.is_shipyard_ = false;
+			}
+
 			continue;
 		}
 
@@ -394,6 +471,11 @@
 
 		if (typeid(bld) == typeid(TrainingSiteDescr)) {
 			bo.type = BuildingObserver::TRAININGSITE;
+			const TrainingSiteDescr& train =
+			   ref_cast<TrainingSiteDescr const, BuildingDescr const>(bld);
+			for (const WareAmount& temp_input : train.inputs()) {
+				bo.inputs_.push_back(temp_input.first);
+			}
 			continue;
 		}
 
@@ -593,6 +675,40 @@
 		}
 	}
 
+	if (!field.is_portspace_) {  // if we know it no need to do it once more
+		if (player_->get_buildcaps(field.coords) & BUILDCAPS_PORT) {
+			field.is_portspace_ = true;
+			seafaring_economy = true;
+			// blocking fields in vicinity
+			MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(field.coords), 3));
+			do {
+				// const Coords coords = map.get_fcoords(*(mr.location().field));
+				const int32_t hash = coords_hash(map.get_fcoords(*(mr.location().field)));
+				if (port_reserved_coords.count(hash) == 0)
+					port_reserved_coords.insert(hash);
+			} while (mr.advance(map));
+		} else {
+			field.is_portspace_ = false;
+		}
+	}
+
+	// testing if a port is nearby, such field will get a priority boost
+	uint16_t nearest_distance = std::numeric_limits<uint16_t>::max();
+	for (std::list<WarehouseSiteObserver>::iterator wh_iter = warehousesites.begin();
+	     wh_iter != warehousesites.end();
+	     ++wh_iter) {
+		const uint16_t actual_distance =
+		   map.calc_distance(field.coords, wh_iter->site->get_position());
+		if (nearest_distance > actual_distance) {
+			nearest_distance = actual_distance;
+		}
+	}
+	if (nearest_distance < 15) {
+		field.port_nearby_ = true;
+	} else {
+		field.port_nearby_ = false;
+	}
+
 	// collect information about resources in the area
 	std::vector<ImmovableFound> immovables;
 	// Search in a radius of range
@@ -901,6 +1017,7 @@
 //   (there should be no upgrade when there are not two buildings of the same type)
 // - algorigthm is trying to take into account actual utlization of buildings
 //   (the one shown in GUI/game is not reliable, it calculates own statistics)
+// * military buildings have own strategy, split into two situations:spot
 // * military buildings have own strategy, split into two situations:
 // - there is no enemy
 // - there is an enemy
@@ -913,7 +1030,7 @@
 	uint32_t consumers_nearby_count = 0;
 	std::vector<int32_t> spots_avail;
 	spots_avail.resize(4);
-	// uint16_t const pn = player_number();
+	Map& map = game().map();
 
 	for (int32_t i = 0; i < 4; ++i)
 		spots_avail.at(i) = 0;
@@ -1019,7 +1136,8 @@
 		}
 
 	// testing big military buildings, whether critical construction
-	// material is (not) needed
+	// material is available (at lest in amount of
+	// 2/3 of default target amount)
 	for (uint32_t j = 0; j < buildings_.size(); ++j) {
 
 		BuildingObserver& bo = buildings_.at(j);
@@ -1037,19 +1155,13 @@
 
 		bo.build_material_shortage_ = false;
 
-		for (EconomyObserver* observer : economies) {
-			// Don't check if the economy has no warehouse.
-			if (observer->economy.warehouses().empty()) {
-				continue;
-			}
-
-			for (uint32_t m = 0; m < bo.critical_built_mat_.size(); ++m) {
-				WareIndex wt(static_cast<size_t>(bo.critical_built_mat_.at(m)));
-
-				if (observer->economy.needs_ware(wt)) {
-					bo.build_material_shortage_ = true;
-					continue;
-				}
+		// checking we have enough critical material on stock
+		for (uint32_t m = 0; m < bo.critical_built_mat_.size(); ++m) {
+			WareIndex wt(static_cast<size_t>(bo.critical_built_mat_.at(m)));
+			// using default ware quantity, not the best solution but will do
+			if (get_warehoused_stock(wt) <
+			    tribe_->get_ware_descr(wt)->default_target_quantity() * 2 / 3) {
+				bo.build_material_shortage_ = true;
 			}
 		}
 	}
@@ -1065,10 +1177,6 @@
 	     ++i) {
 		BuildableField* const bf = *i;
 
-		// if 'buildable field' update is overdue for more then 8 seconds
-		// (= bf has not been updated for about 15 seconds)
-		// skip the bf in evaluation, bacause information
-		// contained in bf are too old
 		if (bf->next_update_due_ < gametime - 8000) {
 			continue;
 		}
@@ -1108,6 +1216,13 @@
 				continue;
 			}
 
+			// testing for reserved ports
+			if (!bo.is_port_) {
+				if (port_reserved_coords.count(coords_hash(bf->coords)) > 0) {
+					continue;
+				}
+			}
+
 			if (time(nullptr) % 3 == 0 && bo.total_count() > 0) {
 				continue;
 			}  // add randomnes and ease AI
@@ -1405,6 +1520,10 @@
 					} else if (bo.cnt_built_ == 1 && game().get_gametime() > 40 * 60 * 1000 &&
 					           bo.desc->enhancement() != INVALID_INDEX && !mines_.empty()) {
 						prio += 10;
+					} else if (bo.is_shipyard_ && seafaring_economy) {
+						;
+					} else if (bo.is_shipyard_ && !seafaring_economy) {
+						continue;
 					} else if (!output_is_needed) {
 						continue;
 					} else if (bo.cnt_built_ == 0 && game().get_gametime() > 40 * 60 * 1000) {
@@ -1444,7 +1563,13 @@
 						prio -= bf->space_consumers_nearby_ * 3;
 					}
 
-					if (!bo.inputs_.empty()) {
+					else if (bo.is_shipyard_) {
+						// for now AI builds only one shipyard
+						if (bf->water_nearby_ > 3 && bo.total_count() == 0 && seafaring_economy) {
+							prio += kDefaultPrioBoost + productionsites.size() * 5 + bf->water_nearby_;
+						}
+
+					} else if (!bo.inputs_.empty()) {
 						if (bo.total_count() == 0) {
 							prio += max_needed_preciousness + kDefaultPrioBoost;
 						}
@@ -1560,9 +1685,19 @@
 			} else if (bo.type == BuildingObserver::WAREHOUSE) {
 
 				// exclude spots on border
-				if (bf->near_border_) {
-					continue;
-				}
+				if (bf->near_border_ && !bo.is_port_) {
+					continue;
+				}
+
+				if (!bf->is_portspace_ && bo.is_port_) {
+					continue;
+				}
+
+				if (bo.cnt_under_construction_ > 0) {
+					continue;
+				}
+
+				bool warehouse_needed = false;
 
 				//  Build one warehouse for ~every 35 productionsites and mines_.
 				//  Militarysites are slightly important as well, to have a bigger
@@ -1572,22 +1707,53 @@
 				       static_cast<int32_t>(numof_warehouses_) &&
 				    bo.cnt_under_construction_ == 0) {
 					prio = 20;
-				}
-
-				// take care about borders and enemies
+					warehouse_needed = true;
+				}
+
+				// but generally we prefer ports
+				if (bo.is_port_) {
+					prio += 10;
+				}
+
+				// special boost for first port
+				if (bo.is_port_ && bo.total_count() == 0 && productionsites.size() > 5 &&
+				    !bf->enemy_nearby_ && bf->is_portspace_ && seafaring_economy) {
+					prio += kDefaultPrioBoost + productionsites.size();
+					warehouse_needed = true;
+				}
+
+				if (!warehouse_needed) {
+					continue;
+				}
+
+				// iterating over current warehouses and testing a distance
+				// getting distance to nearest warehouse and adding it to a score
+				uint16_t nearest_distance = std::numeric_limits<uint16_t>::max();
+				for (std::list<WarehouseSiteObserver>::iterator wh_iter = warehousesites.begin();
+				     wh_iter != warehousesites.end();
+				     ++wh_iter) {
+					const uint16_t actual_distance =
+					   map.calc_distance(bf->coords, wh_iter->site->get_position());
+					if (nearest_distance > actual_distance) {
+						nearest_distance = actual_distance;
+					}
+				}
+
+				// take care about and enemies
 				if (bf->enemy_nearby_) {
 					prio /= 2;
 				}
 
-				if (bf->unowned_land_nearby_) {
+				if (bf->unowned_land_nearby_ && !bo.is_port_) {
 					prio /= 2;
 				}
 
-				// TODO(unknown): introduce check that there is no warehouse nearby
-				// to prevent too close placing
-
 			} else if (bo.type == BuildingObserver::TRAININGSITE) {
 
+				if (virtual_mines < 5) {
+					continue;
+				}
+
 				// exclude spots on border
 				if (bf->near_border_) {
 					continue;
@@ -1598,7 +1764,7 @@
 				}
 
 				// build after 20 production sites and then after each 50 production site
-				if (static_cast<int32_t>((productionsites.size() + 30) / 50) > bo.total_count() &&
+				if (static_cast<int32_t>((productionsites.size() + 40) / 60) > bo.total_count() &&
 				    bo.cnt_under_construction_ == 0) {
 					prio = 4 + kDefaultPrioBoost;
 				}
@@ -1621,11 +1787,24 @@
 				continue;
 			}
 
+			// testing also vicinity
+			if (!bo.is_port_) {
+				const int32_t hash = bf->coords.x << 16 | bf->coords.y;
+				if (port_reserved_coords.count(hash) > 0) {
+					continue;
+				}
+			}
+
 			// Prefer road side fields
 			prio += bf->preferred_ ? 1 : 0;
 			// don't waste good land for small huts
 			prio -= (maxsize - bo.desc->get_size()) * 5;
 
+			// prefer vicinity of ports (with exemption of warehouses)
+			if (bf->port_nearby_ && bo.type == BuildingObserver::MILITARYSITE) {
+				prio *= 2;
+			}
+
 			if (prio > proposed_priority) {
 				best_building = &bo;
 				proposed_priority = prio;
@@ -1762,7 +1941,7 @@
 			block_time = 25 * 1000;
 			block_area = 6;
 		}
-		Map& map = game().map();
+		// Map& map = game().map();
 
 		MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(proposed_coords), block_area));
 		do {
@@ -1968,7 +2147,39 @@
 	// Increasing the failed_connection_tries counter
 	// At the same time it indicates a time an economy is without a warehouse
 	EconomyObserver* eco = get_economy_observer(flag.economy());
+
+	// there are two special situations which have a bit different treatment
+	bool is_remote_port_csite = false;
+	bool stationed_military = false;
 	if (flag.get_economy()->warehouses().empty()) {
+		// first very special case - lonesome port (in the phase of constructionsite)
+		// obviously it has no warehouse/road network to connect to
+		if (upcast(ConstructionSite const, constructionsite, flag.get_building())) {
+			BuildingObserver& bo = get_building_observer(
+			   constructionsite->building().name().c_str());  // constructionsite->building();
+			if (bo.is_port_ &&
+			    remote_ports_coords.count(coords_hash(flag.get_building()->get_position())) > 0) {
+				is_remote_port_csite = true;
+			}
+		}
+
+		// second exemption is when a military buiding was conquered, it
+		// might be just too far from near connected builging
+		if (Building* b = flag.get_building()) {
+			if (upcast(MilitarySite, militb, b)) {
+				if (militb->present_soldiers().size() > 0) {
+					stationed_military = true;
+					// also increasing checkradius a bit
+					checkradius += 4;
+				}
+			}
+		}
+	}
+
+	if (is_remote_port_csite ||
+	    (stationed_military && game().get_gametime() % 10 > 0)) {  // counter disabled
+		;
+	} else if (flag.get_economy()->warehouses().empty()) {
 		eco->failed_connection_tries += 1;
 	} else {
 		eco->failed_connection_tries = 0;
@@ -2014,7 +2225,7 @@
 
 	for (const Coords& reachable_coords : reachable) {
 
-		// first make sure there is an immovable (shold be, but still)
+		// first make sure there is an immovable (should be, but still)
 		if (upcast(PlayerImmovable const, player_immovable, map[reachable_coords].get_immovable())) {
 
 			// if it is the road, make a flag there
@@ -2536,6 +2747,233 @@
 	return changed;
 }
 
+// This function scans current situation with shipyards, ports, ships, ongoing expeditions
+// and makes two decisions:
+// - build a ship
+// - start preparation for expedition
+bool DefaultAI::marine_main_decisions(int32_t const gametime) {
+	if (gametime < next_marine_decisions_due) {
+		return false;
+	}
+	next_marine_decisions_due += kMarineDecisionInterval;
+
+	if (!seafaring_economy) {
+		return false;
+	}
+
+	// getting some base statistics
+	player_ = game().get_player(player_number());
+	uint16_t ports_count = 0;
+	uint16_t shipyards_count = 0;
+	uint16_t working_shipyards_count = 0;
+	uint16_t expeditions_in_prep = 0;
+	uint16_t expeditions_in_progress = 0;
+	uint16_t terittories_count = 1;
+	bool idle_shipyard_stocked = false;
+
+	// goes over all wareouses (these includes ports)
+	for (std::list<WarehouseSiteObserver>::iterator wh_iter = warehousesites.begin();
+	     wh_iter != warehousesites.end();
+	     ++wh_iter) {
+
+		if (wh_iter->bo->is_port_) {
+			ports_count += 1;
+			if (Widelands::PortDock* pd = wh_iter->site->get_portdock()) {
+				if (pd->expedition_started()) {
+					expeditions_in_prep += 1;
+				}
+			} else {
+				log("  there is a port without portdock at %3dx%3d?\n",
+				    wh_iter->site->get_position().x,
+				    wh_iter->site->get_position().y);
+			}
+		}
+	}
+
+	// goes over productionsites and gets status of shipyards
+	for (std::list<ProductionSiteObserver>::iterator ps_iter = productionsites.begin();
+	     ps_iter != productionsites.end();
+	     ++ps_iter) {
+
+		if (ps_iter->bo->is_shipyard_) {
+			shipyards_count += 1;
+			if (!ps_iter->site->is_stopped()) {
+				working_shipyards_count += 1;
+			}
+			// counting stocks
+			uint8_t stocked_wares = 0;
+			std::vector<WaresQueue*> const warequeues = ps_iter->site->warequeues();
+			size_t const nr_warequeues = warequeues.size();
+			for (size_t i = 0; i < nr_warequeues; ++i) {
+				stocked_wares += warequeues[i]->get_filled();
+			}
+			if (stocked_wares == 16 && ps_iter->site->is_stopped()) {
+				idle_shipyard_stocked = true;
+			}
+		}
+	}
+
+	// and now over ships
+	for (std::list<ShipObserver>::iterator sp_iter = allships.begin(); sp_iter != allships.end();
+	     ++sp_iter) {
+		if (sp_iter->ship->state_is_expedition()) {
+			expeditions_in_progress += 1;
+		}
+	}
+
+	// we must verify that all remote ports are still ours (and exists at all)
+	bool still_ours;
+	for (std::unordered_set<uint32_t>::iterator ports_iter = remote_ports_coords.begin();
+	     ports_iter != remote_ports_coords.end();
+	     ++ports_iter) {
+		still_ours = false;
+		FCoords fcoords = game().map().get_fcoords(coords_unhash(*ports_iter));
+		if (fcoords.field->get_owned_by() == player_number()) {
+			if (upcast(PlayerImmovable, imm, fcoords.field->get_immovable())) {
+				still_ours = true;
+			}
+		}
+
+		if (!still_ours) {
+			remote_ports_coords.erase(*ports_iter);
+			break;
+		}
+	}
+	terittories_count += remote_ports_coords.size();
+
+	enum {NEEDSHIP = 0, ENOUGHSHIPS = 1, DONOTHING = 2 };
+
+	// now we must compare ports vs ships to decide if new ship is needed or new expedition can start
+	uint8_t enough_ships = DONOTHING;
+	if (static_cast<float>(allships.size()) >
+	    static_cast<float>((terittories_count - 1) * 0.6 + ports_count * 0.75)) {
+		enough_ships = ENOUGHSHIPS;
+	} else if (static_cast<float>(allships.size()) <
+	           static_cast<float>((terittories_count - 1) * 0.6 + ports_count * 0.75)) {
+		enough_ships = NEEDSHIP;
+	}
+
+	// building a ship? if yes, find a shipyard and order it to build a ship
+	if (shipyards_count > 0 && enough_ships == NEEDSHIP && idle_shipyard_stocked &&
+	    ports_count > 0) {
+
+		for (std::list<ProductionSiteObserver>::iterator ps_iter = productionsites.begin();
+		     ps_iter != productionsites.end();
+		     ++ps_iter) {
+
+			if (ps_iter->bo->is_shipyard_ && ps_iter->site->can_start_working() &&
+			    ps_iter->site->is_stopped()) {
+				// make sure it is fully stocked
+				// counting stocks
+				uint8_t stocked_wares = 0;
+				std::vector<WaresQueue*> const warequeues = ps_iter->site->warequeues();
+				size_t const nr_warequeues = warequeues.size();
+				for (size_t i = 0; i < nr_warequeues; ++i) {
+					stocked_wares += warequeues[i]->get_filled();
+				}
+				if (stocked_wares < 16) {
+					continue;
+				}
+
+				game().send_player_start_stop_building(*ps_iter->site);
+				return true;
+			}
+		}
+	}
+
+	// starting an expedition? if yes, find a port and order it to start an expedition
+	if (ports_count > 0 && enough_ships == ENOUGHSHIPS && expeditions_in_prep == 0 &&
+	    expeditions_in_progress == 0) {
+		// we need to find a port
+		for (std::list<WarehouseSiteObserver>::iterator wh_iter = warehousesites.begin();
+		     wh_iter != warehousesites.end();
+		     ++wh_iter) {
+
+			if (wh_iter->bo->is_port_) {
+				game().send_player_start_or_cancel_expedition(*wh_iter->site);
+				return true;
+			}
+		}
+	}
+	return true;
+}
+
+// This identifies ships that are waiting for command
+bool DefaultAI::check_ships(int32_t const gametime) {
+	if (gametime < next_ship_check_due) {
+		return false;
+	}
+
+	next_ship_check_due += kShipCheckInterval;
+
+	if (!seafaring_economy) {
+		return false;
+	}
+
+	if (!allships.empty()) {
+		// iterating over ships and executing what is needed
+		for (std::list<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i) {
+
+			// only two states need an attention
+			if ((i->ship->get_ship_state() == Widelands::Ship::EXP_WAITING ||
+			     i->ship->get_ship_state() == Widelands::Ship::EXP_FOUNDPORTSPACE) &&
+			    !i->waiting_for_command_) {
+				if (gametime - i->last_command_time > 180 * 1000) {
+					i->waiting_for_command_ = true;
+					log("  %1d: last command for ship at %3dx%3d was %3d seconds ago, something wrong "
+					    "here?...\n",
+					    player_number(),
+					    i->ship->get_position().x,
+					    i->ship->get_position().y,
+					    (gametime - i->last_command_time) / 1000);
+				}
+			}
+			// only two states need an attention
+			if (!(i->ship->get_ship_state() == Widelands::Ship::EXP_WAITING ||
+			      i->ship->get_ship_state() == Widelands::Ship::EXP_FOUNDPORTSPACE) &&
+			    i->waiting_for_command_) {
+			}
+			// if ships is waiting for command
+			if (i->waiting_for_command_) {
+				expedition_management(*i);
+			}
+		}
+	}
+
+	// processing marineTaskQueue_
+	while (!marineTaskQueue_.empty()) {
+		if (marineTaskQueue_.back() == STOPSHIPYARD) {
+			// iterate over all production sites searching for shipyard
+			for (std::list<ProductionSiteObserver>::iterator site = productionsites.begin();
+			     site != productionsites.end();
+			     ++site) {
+				if (site->bo->is_shipyard_) {
+					if (!site->site->is_stopped()) {
+						game().send_player_start_stop_building(*site->site);
+					}
+				}
+			}
+		}
+
+		if (marineTaskQueue_.back() == REPRIORITIZE) {
+			for (std::list<ProductionSiteObserver>::iterator site = productionsites.begin();
+			     site != productionsites.end();
+			     ++site) {
+				if (site->bo->is_shipyard_) {
+					for (uint32_t k = 0; k < site->bo->inputs_.size(); ++k) {
+						game().send_player_set_ware_priority(
+						   *site->site, wwWARE, site->bo->inputs_.at(k), HIGH_PRIORITY);
+					}
+				}
+			}
+		}
+
+		marineTaskQueue_.pop_back();
+	}
+
+	return true;
+}
+
 /**
  * checks the first mine in list, takes care if it runs out of
  * resources and finally reenqueues it at the end of the list.
@@ -2709,6 +3147,51 @@
 	return count;
 }
 
+// counts produced output in warehouses (only)
+// perhaps it wil might replace get_stocklevel
+// if multiple outputs, it returns lowest value
+uint32_t DefaultAI::get_warehoused_stock(WareIndex wt) {
+	uint32_t count = 0;
+
+	for (std::list<WarehouseSiteObserver>::iterator i = warehousesites.begin();
+	     i != warehousesites.end();
+	     ++i) {
+		count += i->site->get_wares().stock(wt);
+	}
+
+	return count;
+}
+
+// this function only manipulates with trainingsites' inputs priority
+// decreases it when too many unoccupied military buildings
+bool DefaultAI::check_trainingsites(int32_t gametime) {
+	if (next_trainingsites_check_due_ > gametime) {
+		return false;
+	}
+	if (!trainingsites.empty()) {
+		next_trainingsites_check_due_ = gametime + kTrainingSitesCheckInterval;
+	} else {
+		next_trainingsites_check_due_ = gametime + 3 * kTrainingSitesCheckInterval;
+	}
+
+	uint8_t new_priority = DEFAULT_PRIORITY;
+	if (unstationed_milit_buildings_ > 2) {
+		new_priority = LOW_PRIORITY;
+	} else {
+		new_priority = DEFAULT_PRIORITY;
+	}
+	for (std::list<TrainingSiteObserver>::iterator site = trainingsites.begin();
+	     site != trainingsites.end();
+	     ++site) {
+
+		for (uint32_t k = 0; k < site->bo->inputs_.size(); ++k) {
+			game().send_player_set_ware_priority(
+			   *site->site, wwWARE, site->bo->inputs_.at(k), new_priority);
+		}
+	}
+	return true;
+}
+
 /**
  * Updates the first military building in list and reenques it at the end of
  * the list afterwards. If a militarysite is in secure area but holds more than
@@ -3002,6 +3485,203 @@
 		}
 }
 
+// this scores spot for potential colony
+uint8_t DefaultAI::spot_scoring(Widelands::Coords candidate_spot) {
+
+	uint8_t score = 0;
+	uint16_t mineable_fields_count = 0;
+	Map& map = game().map();
+	// first making sure there are no other players nearby
+	std::list<uint32_t> queue;
+	std::unordered_set<uint32_t> done;
+	queue.push_front(coords_hash(candidate_spot));
+	while (!queue.empty()) {
+
+		// if already processed
+		if (done.count(queue.front()) > 0) {
+			queue.pop_front();
+			continue;
+		}
+
+		done.insert(queue.front());
+
+		Coords tmp_coords = coords_unhash(queue.front());
+
+		// if beyond range
+		if (map.calc_distance(candidate_spot, tmp_coords) > colony_scan_area_) {
+			continue;
+		}
+
+		Field* f = map.get_fcoords(tmp_coords).field;
+
+		// if owned by someone:
+		if (f->get_owned_by() > 0) {
+			// just return 0 as score
+			return 0;
+		}
+
+		// not interested if not walkable
+		if (!(f->nodecaps() & MOVECAPS_WALK)) {
+			continue;
+		}
+
+		// increase mines counter
+		if (f->nodecaps() & BUILDCAPS_MINE) {
+			mineable_fields_count += 1;
+		};
+
+		// add neighbours to a queue (duplicates are no problem)
+		// to relieve AI/CPU we skip every second field in each direction
+		// obstacles are usually wider then one field
+		for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
+			Coords neigh_coords1;
+			map.get_neighbour(tmp_coords, dir, &neigh_coords1);
+			Coords neigh_coords2;
+			map.get_neighbour(neigh_coords1, dir, &neigh_coords2);
+			queue.push_front(coords_hash(neigh_coords2));
+		}
+	}
+
+	// if the island is too small
+	if (done.size() < 50) {
+		return 0;
+	}
+
+	// if we are here we put score
+	score = 1;
+	if (mineable_fields_count > 0) {
+		score += 1;
+	}
+
+	// here we check for surface stones + trees
+	std::vector<ImmovableFound> immovables;
+	// Search in a radius of range
+	map.find_immovables(Area<FCoords>(map.get_fcoords(candidate_spot), 10), &immovables);
+
+	int32_t const stone_attr = MapObjectDescr::get_attribute_id("granite");
+	uint16_t stones = 0;
+	int32_t const tree_attr = MapObjectDescr::get_attribute_id("tree");
+	uint16_t trees = 0;
+
+	for (uint32_t j = 0; j < immovables.size(); ++j) {
+		if (immovables.at(j).object->has_attribute(stone_attr)) {
+			++stones;
+		}
+		if (immovables.at(j).object->has_attribute(tree_attr)) {
+			++trees;
+		}
+	}
+	if (stones > 1) {
+		score += 1;
+	}
+	if (trees > 1) {
+		score += 1;
+	}
+
+	return score;
+}
+
+// this is called whenever ship received a notification that requires
+// navigation decisions (these notifiation are processes not in 'real time')
+void DefaultAI::expedition_management(ShipObserver& so) {
+
+	Map& map = game().map();
+	const int32_t gametime = game().get_gametime();
+
+	// first we put current spot into visited_spots_
+	bool first_time_here = false;
+	if (so.visited_spots_.count(coords_hash(so.ship->get_position())) == 0) {
+		first_time_here = true;
+		so.visited_spots_.insert(coords_hash(so.ship->get_position()));
+	}
+
+	// If we have portspace following options are avaiable:
+	// 1. Build a port there
+	if (so.ship->exp_port_spaces()->size() > 0) {  // making sure we have possible portspaces
+
+		// we score the place
+		const uint8_t spot_score = spot_scoring(so.ship->exp_port_spaces()->front());
+
+		if ((gametime / 10) % 8 < spot_score) {  // we build a port here
+			const Coords last_portspace = so.ship->exp_port_spaces()->front();
+			remote_ports_coords.insert(coords_hash(last_portspace));
+			game().send_player_ship_construct_port(*so.ship, so.ship->exp_port_spaces()->front());
+			so.last_command_time = gametime;
+			so.waiting_for_command_ = false;
+			// blocking the area for some time to save AI from idle attempts to built there
+			// buildings
+			// TODO(anybody): how long it takes to build a port?
+			// I used 5 minutes
+			MapRegion<Area<FCoords>> mr(
+			   game().map(), Area<FCoords>(map.get_fcoords(so.ship->exp_port_spaces()->front()), 8));
+			do {
+				BlockedField blocked2(
+				   map.get_fcoords(*(mr.location().field)), gametime + 5 * 60 * 1000);
+				blocked_fields.push_back(blocked2);
+			} while (mr.advance(map));
+
+			return;
+		}
+
+		// decreasing colony_scan_area_
+		if (colony_scan_area_ > 15 && gametime % 10 == 0) {
+			colony_scan_area_ -= 1;
+		}
+	}
+
+	// if we are here, port was not ordered above
+	// 2. Go on with expedition
+
+	if (first_time_here) {
+		game().send_player_ship_explore_island(*so.ship, so.island_circ_direction);
+		so.last_command_time = gametime;
+		so.waiting_for_command_ = false;
+
+		// we was here but to add randomnes we might continue with expedition
+	} else if (gametime % 2 == 0) {
+		game().send_player_ship_explore_island(*so.ship, so.island_circ_direction);
+		so.last_command_time = gametime;
+		so.waiting_for_command_ = false;
+	} else {
+		// get swimable directions
+		std::vector<Direction> possible_directions;
+		for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
+
+			// testing distance of 8 fields
+			// this would say there is an 'open sea' there
+			Widelands::FCoords tmp_fcoords = map.get_fcoords(so.ship->get_position());
+			for (int8_t i = 0; i < 8; ++i) {
+				tmp_fcoords = map.get_neighbour(tmp_fcoords, dir);
+				if (tmp_fcoords.field->nodecaps() & MOVECAPS_SWIM) {
+					if (i == 7) {
+						possible_directions.push_back(dir);
+						break;  // not needed but.....
+					}
+				} else {
+					break;
+				}
+			}
+		}
+
+		// we test if there is open sea
+		if (possible_directions.size() == 0) {
+			// 2.A No there is no open sea
+			game().send_player_ship_explore_island(*so.ship, so.island_circ_direction);
+			so.last_command_time = gametime;
+			so.waiting_for_command_ = false;
+			;
+		} else {
+			// 2.B Yes, pick one of avaiable directions
+			const Direction final_direction =
+			   possible_directions.at(gametime % possible_directions.size());
+			game().send_player_ship_scout_direction(*so.ship, final_direction);
+			so.last_command_time = gametime;
+			so.waiting_for_command_ = false;
+		}
+	}
+	return;
+}
+
 // this is called whenever we gain a new building
 void DefaultAI::gain_building(Building& b) {
 	BuildingObserver& bo = get_building_observer(b.descr().name().c_str());
@@ -3031,6 +3711,10 @@
 			productionsites.back().unoccupied_till_ = game().get_gametime();
 			productionsites.back().stats_zero_ = 0;
 			productionsites.back().no_resources_count = 0;
+			if (bo.is_shipyard_) {
+				marineTaskQueue_.push_back(STOPSHIPYARD);
+				marineTaskQueue_.push_back(REPRIORITIZE);
+			}
 
 			for (uint32_t i = 0; i < bo.outputs_.size(); ++i)
 				++wares.at(bo.outputs_.at(i)).producers_;
@@ -3055,8 +3739,19 @@
 			militarysites.back().checks = bo.desc->get_size();
 			militarysites.back().enemies_nearby_ = true;
 
+		} else if (bo.type == BuildingObserver::TRAININGSITE) {
+			trainingsites.push_back(TrainingSiteObserver());
+			trainingsites.back().site = &ref_cast<TrainingSite, Building>(b);
+			trainingsites.back().bo = &bo;
+
 		} else if (bo.type == BuildingObserver::WAREHOUSE) {
 			++numof_warehouses_;
+			warehousesites.push_back(WarehouseSiteObserver());
+			warehousesites.back().site = &ref_cast<Warehouse, Building>(b);
+			warehousesites.back().bo = &bo;
+			if (bo.is_port_) {
+				++num_ports;
+			}
 		}
 	}
 }
@@ -3123,9 +3818,31 @@
 					break;
 				}
 			}
+		} else if (bo.type == BuildingObserver::TRAININGSITE) {
+
+			for (std::list<TrainingSiteObserver>::iterator i = trainingsites.begin();
+			     i != trainingsites.end();
+			     ++i) {
+				if (i->site == &b) {
+					trainingsites.erase(i);
+					break;
+				}
+			}
 		} else if (bo.type == BuildingObserver::WAREHOUSE) {
 			assert(numof_warehouses_ > 0);
 			--numof_warehouses_;
+			if (bo.is_port_) {
+				--num_ports;
+			}
+
+			for (std::list<WarehouseSiteObserver>::iterator i = warehousesites.begin();
+			     i != warehousesites.end();
+			     ++i) {
+				if (i->site == &b) {
+					warehousesites.erase(i);
+					break;
+				}
+			}
 		}
 	}
 
@@ -3411,6 +4128,35 @@
 	}
 }
 
+// This runs once in 15 minutes, and adjust wares targets based on number of
+// productionsites and ports
+void DefaultAI::review_wares_targets(int32_t const gametime) {
+
+	player_ = game().get_player(player_number());
+	tribe_ = &player_->tribe();
+
+	// to avoid floats real multiplicator is multiplicator/10
+	uint16_t multiplicator = 10;
+	if ((productionsites.size() + num_ports * 5) > 50) {
+		multiplicator = (productionsites.size() + num_ports * 5) / 5;
+	}
+
+	for (EconomyObserver* observer : economies) {
+		WareIndex nritems = observer->economy.owner().tribe().get_nrwares();
+		for (Widelands::WareIndex id = 0; id < nritems; ++id) {
+			// const Economy::TargetQuantity & tq = observer->economy.ware_target_quantity(id);
+			const uint16_t default_target = tribe_->get_ware_descr(id)->default_target_quantity();
+
+			game().send_player_command(*new Widelands::CmdSetWareTargetQuantity(
+			                              gametime,
+			                              player_number(),
+			                              player_->get_economy_number(&observer->economy),
+			                              id,
+			                              default_target * multiplicator / 10));
+		}
+	}
+}
+
 // This is used for profiling, so usually this is not used :)
 void DefaultAI::print_land_stats() {
 	// this will just print statistics of land size

=== modified file 'src/ai/defaultai.h'
--- src/ai/defaultai.h	2014-10-17 19:13:39 +0000
+++ src/ai/defaultai.h	2014-11-19 21:19:43 +0000
@@ -27,6 +27,8 @@
 #include "ai/computer_player.h"
 #include "base/i18n.h"
 #include "logic/immovable.h"
+#include "logic/ship.h"
+#include <unordered_set>
 
 namespace Widelands {
 struct Road;
@@ -130,6 +132,18 @@
 
 	bool construct_building(int32_t);
 
+	uint32_t coords_hash(Widelands::Coords coords) {
+		uint32_t hash = coords.x << 16 | coords.y;
+		return hash;
+	}
+
+	Widelands::Coords coords_unhash(uint32_t hash) {
+		Widelands::Coords coords;
+		coords.x = hash >> 16;  // is cast needed here???
+		coords.y = hash;
+		return coords;
+	}
+
 	// all road management is invoked by function improve_roads()
 	// if needed it calls create_shortcut_road() with a flag from which
 	// new road should be considered (or is needed)
@@ -139,18 +153,25 @@
 	bool dispensable_road_test(const Widelands::Road&);
 	bool check_economies();
 	bool check_productionsites(int32_t);
+	bool check_trainingsites(int32_t);
 	bool check_mines_(int32_t);
 	bool check_militarysites(int32_t);
+	bool marine_main_decisions(int32_t);
+	bool check_ships(int32_t);
 	uint32_t get_stocklevel_by_hint(size_t);
 	uint32_t get_stocklevel(BuildingObserver&);
+	uint32_t get_warehoused_stock(Widelands::WareIndex wt);
 	uint32_t get_stocklevel(Widelands::WareIndex);  // count all direct outputs_
 	void check_helpersites(int32_t);
+	void review_wares_targets(int32_t);
 
 	int32_t recalc_with_border_range(const BuildableField&, int32_t);
 	int32_t calculate_need_for_ps(BuildingObserver&, int32_t);
 
 	void
 	consider_productionsite_influence(BuildableField&, Widelands::Coords, const BuildingObserver&);
+	// considering wood, stones, mines, water, fishes for candidate for colonization (new port)
+	uint8_t spot_scoring(Widelands::Coords candidate_spot);
 
 	EconomyObserver* get_economy_observer(Widelands::Economy&);
 	BuildingObserver& get_building_observer(char const*);
@@ -159,6 +180,8 @@
 	void lose_immovable(const Widelands::PlayerImmovable&);
 	void gain_building(Widelands::Building&);
 	void lose_building(const Widelands::Building&);
+	void expedition_management(ShipObserver&);
+	// bool pick_farest_portspace(Widelands::Ship&);
 	void out_of_resources_site(const Widelands::ProductionSite&);
 
 	bool check_supply(const BuildingObserver&);
@@ -181,10 +204,14 @@
 	uint32_t num_constructionsites_;
 	uint32_t num_milit_constructionsites;
 	uint32_t num_prod_constructionsites;
+	uint32_t num_ports;
 
 	std::list<Widelands::FCoords> unusable_fields;
 	std::list<BuildableField*> buildable_fields;
 	std::list<BlockedField> blocked_fields;
+	std::unordered_set<uint32_t> port_reserved_coords;
+	// to distinquish which ports are on home teritory and which one are remote
+	std::unordered_set<uint32_t> remote_ports_coords;
 	std::list<MineableField*> mineable_fields;
 	std::list<Widelands::Flag const*> new_flags;
 	std::list<Widelands::Coords> flags_to_be_removed;
@@ -193,6 +220,9 @@
 	std::list<ProductionSiteObserver> productionsites;
 	std::list<ProductionSiteObserver> mines_;
 	std::list<MilitarySiteObserver> militarysites;
+	std::list<WarehouseSiteObserver> warehousesites;
+	std::list<TrainingSiteObserver> trainingsites;
+	std::list<ShipObserver> allships;
 
 	std::vector<WareObserver> wares;
 
@@ -203,9 +233,12 @@
 	int32_t next_productionsite_check_due_;
 	int32_t next_mine_check_due_;
 	int32_t next_militarysite_check_due_;
+	int32_t next_ship_check_due;
+	int32_t next_marine_decisions_due;
 	int32_t next_attack_consideration_due_;
-	int32_t next_helpersites_check_due_;
+	int32_t next_trainingsites_check_due_;
 	int32_t next_bf_check_due_;
+	int32_t next_wares_review_due_;
 	int32_t inhibit_road_building_;
 	int32_t time_of_last_construction_;
 	int32_t enemy_last_seen_;
@@ -232,13 +265,20 @@
 	Widelands::Coords
 	   last_attack_target_;         // flag to abuilding (position) that was attacked last time
 	int32_t next_attack_waittime_;  // second till the next attack consideration
-	int32_t spots_;                 // sum of buildable fields
+	bool seafaring_economy;  // false by default, until first port space is found
+	uint32_t colony_scan_area_;  // distance from a possible port that is scanned for owned territory
+	// it decreases with failed scans
+	int32_t spots_;  // sum of buildable fields
+
+	enum {REPRIORITIZE, STOPSHIPYARD, STARTSHIPYARD};
+	std::vector<int16_t> marineTaskQueue_;
 
 	std::unique_ptr<Notifications::Subscriber<Widelands::NoteFieldPossession>>
 	   field_possession_subscriber_;
 	std::unique_ptr<Notifications::Subscriber<Widelands::NoteImmovable>> immovable_subscriber_;
 	std::unique_ptr<Notifications::Subscriber<Widelands::NoteProductionSiteOutOfResources>>
 	   outofresource_subscriber_;
+	std::unique_ptr<Notifications::Subscriber<Widelands::NoteShipMessage>> shipnotes_subscriber_;
 };
 
 #endif  // end of include guard: WL_AI_DEFAULTAI_H

=== modified file 'src/economy/portdock.cc'
--- src/economy/portdock.cc	2014-09-20 09:37:47 +0000
+++ src/economy/portdock.cc	2014-11-19 21:19:43 +0000
@@ -21,6 +21,8 @@
 
 #include <memory>
 
+#include <boost/format.hpp>
+
 #include "base/deprecated.h"
 #include "base/log.h"
 #include "economy/fleet.h"
@@ -46,20 +48,16 @@
 	return g_portdock_descr;
 }
 
-
 PortdockDescr::PortdockDescr(char const* const _name, char const* const _descname)
-	:
-	MapObjectDescr(MapObjectType::PORTDOCK, _name, _descname)
-{
+   : MapObjectDescr(MapObjectType::PORTDOCK, _name, _descname) {
 }
 
-PortDock::PortDock(Warehouse* wh) :
-	PlayerImmovable(g_portdock_descr),
-	m_fleet(nullptr),
-	m_warehouse(wh),
-	m_need_ship(false),
-	m_expedition_ready(false)
-{
+PortDock::PortDock(Warehouse* wh)
+   : PlayerImmovable(g_portdock_descr),
+     m_fleet(nullptr),
+     m_warehouse(wh),
+     m_need_ship(false),
+     m_expedition_ready(false) {
 }
 
 PortDock::~PortDock() {
@@ -76,8 +74,7 @@
  *
  * @note This only works properly when called before @ref init
  */
-void PortDock::add_position(Coords where)
-{
+void PortDock::add_position(Coords where) {
 	m_dockpoints.push_back(where);
 }
 
@@ -90,29 +87,23 @@
  *
  * @warning This should only be called via @ref Fleet itself.
  */
-void PortDock::set_fleet(Fleet * fleet)
-{
+void PortDock::set_fleet(Fleet* fleet) {
 	m_fleet = fleet;
 }
 
-int32_t PortDock::get_size() const
-{
+int32_t PortDock::get_size() const {
 	return SMALL;
 }
 
-bool PortDock::get_passable() const
-{
+bool PortDock::get_passable() const {
 	return true;
 }
 
-PortDock::PositionList PortDock::get_positions
-	(const EditorGameBase &) const
-{
+PortDock::PositionList PortDock::get_positions(const EditorGameBase&) const {
 	return m_dockpoints;
 }
 
-Flag & PortDock::base_flag()
-{
+Flag& PortDock::base_flag() {
 	return m_warehouse->base_flag();
 }
 
@@ -120,8 +111,7 @@
  * Return the dock that has the given flag as its base, or 0 if no dock of our fleet
  * has the given flag.
  */
-PortDock * PortDock::get_dock(Flag & flag) const
-{
+PortDock* PortDock::get_dock(Flag& flag) const {
 	if (m_fleet)
 		return m_fleet->get_dock(flag);
 	return nullptr;
@@ -133,8 +123,7 @@
  * Called by @ref Warehouse::set_economy, and responsible for forwarding the
  * change to @ref Fleet.
  */
-void PortDock::set_economy(Economy * e)
-{
+void PortDock::set_economy(Economy* e) {
 	if (e == get_economy())
 		return;
 
@@ -152,18 +141,14 @@
 		m_expedition_bootstrap->set_economy(e);
 }
 
-
-void PortDock::draw
-		(const EditorGameBase &, RenderTarget &, const FCoords&, const Point&)
-{
+void PortDock::draw(const EditorGameBase&, RenderTarget&, const FCoords&, const Point&) {
 	// do nothing
 }
 
-void PortDock::init(EditorGameBase & egbase)
-{
+void PortDock::init(EditorGameBase& egbase) {
 	PlayerImmovable::init(egbase);
 
-	for (const Coords& coords: m_dockpoints) {
+	for (const Coords& coords : m_dockpoints) {
 		set_position(egbase, coords);
 	}
 
@@ -174,18 +159,21 @@
  * Create our initial singleton @ref Fleet. The fleet code ensures
  * that we merge with a larger fleet when possible.
  */
-void PortDock::init_fleet(EditorGameBase & egbase)
-{
-	Fleet * fleet = new Fleet(owner());
+void PortDock::init_fleet(EditorGameBase& egbase) {
+	Fleet* fleet = new Fleet(owner());
 	fleet->add_port(egbase, this);
 	fleet->init(egbase);
 	// Note: the Fleet calls our set_fleet automatically
 }
 
-void PortDock::cleanup(EditorGameBase & egbase)
-{
+void PortDock::cleanup(EditorGameBase& egbase) {
+
+	Warehouse* wh = nullptr;
+
 	if (egbase.objects().object_still_available(m_warehouse)) {
-		// Transfer all our wares into the warehouse.
+
+		wh = m_warehouse;
+
 		if (upcast(Game, game, &egbase)) {
 			for (ShippingItem& shipping_item : m_waiting) {
 				WareInstance* ware;
@@ -199,6 +187,7 @@
 				}
 			}
 		}
+
 		m_waiting.clear();
 		m_warehouse->m_portdock = nullptr;
 	}
@@ -212,7 +201,7 @@
 	if (m_fleet)
 		m_fleet->remove_port(egbase, this);
 
-	for (const Coords& coords: m_dockpoints) {
+	for (const Coords& coords : m_dockpoints) {
 		unset_position(egbase, coords);
 	}
 
@@ -222,13 +211,26 @@
 	}
 
 	PlayerImmovable::cleanup(egbase);
+
+	if (wh) {
+		if (upcast(Game, game, &egbase)) {
+			if (game->is_loaded()) {
+				Player& player = owner();
+				log("Message: Portdock lost, trying to restore it (player %d)\n",
+				    player.player_number());
+				wh->restore_portdock_or_destroy(egbase);
+				return;
+			}
+		}
+		// this is not a (running) game, destroying the port
+		wh->destroy(egbase);
+	}
 }
 
 /**
  * Add the flags of all ports that can be reached via this dock.
  */
-void PortDock::add_neighbours(std::vector<RoutingNodeNeighbour> & neighbours)
-{
+void PortDock::add_neighbours(std::vector<RoutingNodeNeighbour>& neighbours) {
 	if (m_fleet && m_fleet->active())
 		m_fleet->add_neighbours(*this, neighbours);
 }
@@ -236,8 +238,7 @@
 /**
  * The given @p ware enters the dock, waiting to be transported away.
  */
-void PortDock::add_shippingitem(Game & game, WareInstance & ware)
-{
+void PortDock::add_shippingitem(Game& game, WareInstance& ware) {
 	m_waiting.push_back(ShippingItem(ware));
 	ware.set_location(game, this);
 	ware.update(game);
@@ -247,15 +248,14 @@
  * The given @p ware, which is assumed to be inside the dock, has updated
  * its route.
  */
-void PortDock::update_shippingitem(Game & game, WareInstance & ware)
-{
+void PortDock::update_shippingitem(Game& game, WareInstance& ware) {
 	for (std::vector<ShippingItem>::iterator item_iter = m_waiting.begin();
-		  item_iter != m_waiting.end();
-		  ++item_iter) {
+	     item_iter != m_waiting.end();
+	     ++item_iter) {
 
 		if (item_iter->m_object.serial() == ware.serial()) {
 			_update_shippingitem(game, item_iter);
-				return;
+			return;
 		}
 	}
 }
@@ -263,8 +263,7 @@
 /**
  * The given @p worker enters the dock, waiting to be transported away.
  */
-void PortDock::add_shippingitem(Game & game, Worker & worker)
-{
+void PortDock::add_shippingitem(Game& game, Worker& worker) {
 	m_waiting.push_back(ShippingItem(worker));
 	worker.set_location(this);
 	update_shippingitem(game, worker);
@@ -274,24 +273,22 @@
  * The given @p worker, which is assumed to be inside the dock, has
  * updated its route.
  */
-void PortDock::update_shippingitem(Game & game, Worker & worker)
-{
+void PortDock::update_shippingitem(Game& game, Worker& worker) {
 	for (std::vector<ShippingItem>::iterator item_iter = m_waiting.begin();
-		  item_iter != m_waiting.end();
-		  ++item_iter) {
+	     item_iter != m_waiting.end();
+	     ++item_iter) {
 
 		if (item_iter->m_object.serial() == worker.serial()) {
 			_update_shippingitem(game, item_iter);
-				return;
+			return;
 		}
 	}
 }
 
-void PortDock::_update_shippingitem(Game & game, std::vector<ShippingItem>::iterator it)
-{
+void PortDock::_update_shippingitem(Game& game, std::vector<ShippingItem>::iterator it) {
 	it->update_destination(game, *this);
 
-	PortDock * dst = it->get_destination(game);
+	PortDock* dst = it->get_destination(game);
 	assert(dst != this);
 
 	// Destination might have vanished or be in another economy altogether.
@@ -312,8 +309,7 @@
  * A ship has arrived at the dock. Clear all items designated for this dock,
  * and load the ship.
  */
-void PortDock::ship_arrived(Game & game, Ship & ship)
-{
+void PortDock::ship_arrived(Game& game, Ship& ship) {
 	std::vector<ShippingItem> items_brought_by_ship;
 	ship.withdraw_items(game, *this, items_brought_by_ship);
 
@@ -330,7 +326,8 @@
 			// Load the ship
 			std::vector<Worker*> workers;
 			std::vector<WareInstance*> wares;
-			m_expedition_bootstrap->get_waiting_workers_and_wares(game, owner().tribe(), &workers, &wares);
+			m_expedition_bootstrap->get_waiting_workers_and_wares(
+			   game, owner().tribe(), &workers, &wares);
 
 			for (Worker* worker : workers) {
 				ship.add_item(game, ShippingItem(*worker));
@@ -375,8 +372,7 @@
 	m_fleet->update(game);
 }
 
-void PortDock::set_need_ship(Game & game, bool need)
-{
+void PortDock::set_need_ship(Game& game, bool need) {
 	molog("set_need_ship(%s)\n", need ? "true" : "false");
 
 	if (need == m_need_ship)
@@ -393,13 +389,12 @@
 /**
  * Return the number of wares or workers of the given type that are waiting at the dock.
  */
-uint32_t PortDock::count_waiting(WareWorker waretype, WareIndex wareindex)
-{
+uint32_t PortDock::count_waiting(WareWorker waretype, WareIndex wareindex) {
 	uint32_t count = 0;
 
 	for (ShippingItem& shipping_item : m_waiting) {
-		WareInstance * ware;
-		Worker * worker;
+		WareInstance* ware;
+		Worker* worker;
 		shipping_item.get(owner().egbase(), &ware, &worker);
 
 		if (waretype == wwWORKER) {
@@ -414,7 +409,6 @@
 	return count;
 }
 
-
 /// \returns whether an expedition was started or is even ready
 bool PortDock::expedition_started() {
 	return (m_expedition_bootstrap.get() != nullptr) || m_expedition_ready;
@@ -425,19 +419,18 @@
 	assert(!m_expedition_bootstrap);
 	m_expedition_bootstrap.reset(new ExpeditionBootstrap(this));
 	m_expedition_bootstrap->start();
-
 }
 
 ExpeditionBootstrap* PortDock::expedition_bootstrap() {
 	return m_expedition_bootstrap.get();
 }
 
-void PortDock::expedition_bootstrap_complete(Game & game) {
+void PortDock::expedition_bootstrap_complete(Game& game) {
 	m_expedition_ready = true;
 	get_fleet()->update(game);
 }
 
-void PortDock::cancel_expedition(Game & game) {
+void PortDock::cancel_expedition(Game& game) {
 	// Reset
 	m_expedition_ready = false;
 
@@ -445,38 +438,34 @@
 	m_expedition_bootstrap.reset(nullptr);
 }
 
-
-void PortDock::log_general_info(const EditorGameBase & egbase)
-{
+void PortDock::log_general_info(const EditorGameBase& egbase) {
 	PlayerImmovable::log_general_info(egbase);
 
 	Coords pos(m_warehouse->get_position());
-	molog
-		("PortDock for warehouse %u (at %i,%i) in fleet %u, need_ship: %s, waiting: %" PRIuS "\n",
-		 m_warehouse ? m_warehouse->serial() : 0, pos.x, pos.y,
-		 m_fleet ? m_fleet->serial() : 0,
-		 m_need_ship ? "true" : "false",
-		 m_waiting.size());
+	molog("PortDock for warehouse %u (at %i,%i) in fleet %u, need_ship: %s, waiting: %" PRIuS "\n",
+	      m_warehouse ? m_warehouse->serial() : 0,
+	      pos.x,
+	      pos.y,
+	      m_fleet ? m_fleet->serial() : 0,
+	      m_need_ship ? "true" : "false",
+	      m_waiting.size());
 
 	for (ShippingItem& shipping_item : m_waiting) {
-		molog
-			("  IT %u, destination %u\n",
-			 shipping_item.m_object.serial(),
-			 shipping_item.m_destination_dock.serial());
+		molog("  IT %u, destination %u\n",
+		      shipping_item.m_object.serial(),
+		      shipping_item.m_destination_dock.serial());
 	}
 }
 
 #define PORTDOCK_SAVEGAME_VERSION 3
 
-PortDock::Loader::Loader() : m_warehouse(0)
-{
+PortDock::Loader::Loader() : m_warehouse(0) {
 }
 
-void PortDock::Loader::load(FileRead & fr, uint8_t version)
-{
+void PortDock::Loader::load(FileRead& fr, uint8_t version) {
 	PlayerImmovable::Loader::load(fr);
 
-	PortDock & pd = get<PortDock>();
+	PortDock& pd = get<PortDock>();
 
 	m_warehouse = fr.unsigned_32();
 	uint16_t nrdockpoints = fr.unsigned_16();
@@ -507,11 +496,10 @@
 	}
 }
 
-void PortDock::Loader::load_pointers()
-{
+void PortDock::Loader::load_pointers() {
 	PlayerImmovable::Loader::load_pointers();
 
-	PortDock & pd = get<PortDock>();
+	PortDock& pd = get<PortDock>();
 	pd.m_warehouse = &mol().get<Warehouse>(m_warehouse);
 
 	pd.m_waiting.resize(m_waiting.size());
@@ -520,11 +508,10 @@
 	}
 }
 
-void PortDock::Loader::load_finish()
-{
+void PortDock::Loader::load_finish() {
 	PlayerImmovable::Loader::load_finish();
 
-	PortDock & pd = get<PortDock>();
+	PortDock& pd = get<PortDock>();
 
 	if (pd.m_warehouse->get_portdock() != &pd) {
 		log("Inconsistent PortDock <> Warehouse link\n");
@@ -537,9 +524,7 @@
 		pd.init_fleet(egbase());
 }
 
-MapObject::Loader * PortDock::load
-	(EditorGameBase & egbase, MapObjectLoader & mol, FileRead & fr)
-{
+MapObject::Loader* PortDock::load(EditorGameBase& egbase, MapObjectLoader& mol, FileRead& fr) {
 	std::unique_ptr<Loader> loader(new Loader);
 
 	try {
@@ -551,15 +536,14 @@
 			loader->load(fr, version);
 		} else
 			throw GameDataError("unknown/unhandled version %u", version);
-	} catch (const std::exception & e) {
+	} catch (const std::exception& e) {
 		throw wexception("loading portdock: %s", e.what());
 	}
 
 	return loader.release();
 }
 
-void PortDock::save(EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
-{
+void PortDock::save(EditorGameBase& egbase, MapObjectSaver& mos, FileWrite& fw) {
 	fw.unsigned_8(HeaderPortDock);
 	fw.unsigned_8(PORTDOCK_SAVEGAME_VERSION);
 
@@ -567,7 +551,7 @@
 
 	fw.unsigned_32(mos.get_object_file_index(*m_warehouse));
 	fw.unsigned_16(m_dockpoints.size());
-	for (const Coords& coords: m_dockpoints) {
+	for (const Coords& coords : m_dockpoints) {
 		write_coords_32(&fw, coords);
 	}
 
@@ -583,4 +567,4 @@
 	fw.unsigned_8(m_expedition_ready ? 1 : 0);
 }
 
-} // namespace Widelands
+}  // namespace Widelands

=== modified file 'src/logic/ship.cc'
--- src/logic/ship.cc	2014-09-20 09:37:47 +0000
+++ src/logic/ship.cc	2014-11-19 21:19:43 +0000
@@ -49,24 +49,24 @@
 
 namespace Widelands {
 
-ShipDescr::ShipDescr
-	(const char * given_name, const char * gdescname,
-	 const std::string & directory, Profile & prof, Section & global_s,
-	 const TribeDescr & gtribe)
-	:
-	BobDescr(MapObjectType::SHIP, given_name, gdescname, &gtribe)
-{
-	{ //  global options
-		Section & idle_s = prof.get_safe_section("idle");
+ShipDescr::ShipDescr(const char* given_name,
+                     const char* gdescname,
+                     const std::string& directory,
+                     Profile& prof,
+                     Section& global_s,
+                     const TribeDescr& gtribe)
+   : BobDescr(MapObjectType::SHIP, given_name, gdescname, &gtribe) {
+	{  //  global options
+		Section& idle_s = prof.get_safe_section("idle");
 		add_animation("idle", g_gr->animations().load(directory, idle_s));
 	}
 	m_sail_anims.parse(*this, directory, prof, "sail");
 
-	Section * sinking_s = prof.get_section("sinking");
+	Section* sinking_s = prof.get_section("sinking");
 	if (sinking_s)
 		add_animation("sinking", g_gr->animations().load(directory, *sinking_s));
 
-	m_capacity     = global_s.get_natural("capacity", 20);
+	m_capacity = global_s.get_natural("capacity", 20);
 	m_vision_range = global_s.get_natural("vision_range", 7);
 }
 
@@ -74,18 +74,12 @@
 	return MOVECAPS_SWIM;
 }
 
-Bob & ShipDescr::create_object() const {
+Bob& ShipDescr::create_object() const {
 	return *new Ship(*this);
 }
 
-
-Ship::Ship(const ShipDescr & gdescr) :
-	Bob(gdescr),
-	m_window(nullptr),
-	m_fleet(nullptr),
-	m_economy(nullptr),
-	m_ship_state(TRANSPORT)
-{
+Ship::Ship(const ShipDescr& gdescr)
+   : Bob(gdescr), m_window(nullptr), m_fleet(nullptr), m_economy(nullptr), m_ship_state(TRANSPORT) {
 }
 
 Ship::~Ship() {
@@ -104,13 +98,14 @@
 	return m_fleet;
 }
 
-void Ship::init_auto_task(Game & game) {
+void Ship::init_auto_task(Game& game) {
 	start_task_ship(game);
 }
 
-void Ship::init(EditorGameBase & egbase) {
+void Ship::init(EditorGameBase& egbase) {
 	Bob::init(egbase);
 	init_fleet(egbase);
+	Notifications::publish(NoteShipMessage(this, NoteShipMessage::Message::GAINED));
 }
 
 /**
@@ -118,15 +113,15 @@
  * The fleet code will automatically merge us into a larger
  * fleet, if one is reachable.
  */
-void Ship::init_fleet(EditorGameBase & egbase) {
+void Ship::init_fleet(EditorGameBase& egbase) {
 	assert(get_owner() != nullptr);
-	Fleet * fleet = new Fleet(*get_owner());
+	Fleet* fleet = new Fleet(*get_owner());
 	fleet->add_ship(this);
 	fleet->init(egbase);
 	// fleet calls the set_fleet function appropriately
 }
 
-void Ship::cleanup(EditorGameBase & egbase) {
+void Ship::cleanup(EditorGameBase& egbase) {
 	if (m_fleet) {
 		m_fleet->remove_ship(egbase, this);
 	}
@@ -136,34 +131,32 @@
 		m_items.pop_back();
 	}
 
+	Notifications::publish(NoteShipMessage(this, NoteShipMessage::Message::LOST));
+
 	Bob::cleanup(egbase);
 }
 
 /**
  * This function is to be called only by @ref Fleet.
  */
-void Ship::set_fleet(Fleet * fleet) {
+void Ship::set_fleet(Fleet* fleet) {
 	m_fleet = fleet;
 }
 
-void Ship::wakeup_neighbours(Game & game) {
+void Ship::wakeup_neighbours(Game& game) {
 	FCoords position = get_position();
 	Area<FCoords> area(position, 1);
-	std::vector<Bob *> ships;
+	std::vector<Bob*> ships;
 	game.map().find_bobs(area, &ships, FindBobShip());
 
-	for
-		(std::vector<Bob *>::const_iterator it = ships.begin();
-		 it != ships.end(); ++it)
-	{
+	for (std::vector<Bob*>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
 		if (*it == this)
 			continue;
 
-		static_cast<Ship *>(*it)->ship_wakeup(game);
+		static_cast<Ship*>(*it)->ship_wakeup(game);
 	}
 }
 
-
 /**
  * Standard behaviour of ships.
  *
@@ -174,20 +167,20 @@
 	static_cast<Bob::Ptr>(&Ship::ship_update),
 	nullptr,
 	nullptr,
-	true // unique task
+	true  // unique task
 };
 
-void Ship::start_task_ship(Game & game) {
+void Ship::start_task_ship(Game& game) {
 	push_task(game, taskShip);
 	top_state().ivar1 = 0;
 }
 
-void Ship::ship_wakeup(Game & game) {
+void Ship::ship_wakeup(Game& game) {
 	if (get_state(taskShip))
 		send_signal(game, "wakeup");
 }
 
-void Ship::ship_update(Game & game, Bob::State & state) {
+void Ship::ship_update(Game& game, Bob::State& state) {
 	// Handle signals
 	std::string signal = get_signal();
 	if (!signal.empty()) {
@@ -211,44 +204,43 @@
 	}
 
 	switch (m_ship_state) {
-		case TRANSPORT:
-			if (ship_update_transport(game, state))
-				return;
-			break;
-		case EXP_FOUNDPORTSPACE:
-		case EXP_SCOUTING:
-		case EXP_WAITING:
-			ship_update_expedition(game, state);
-			break;
-		case EXP_COLONIZING:
-			break;
-		case SINK_REQUEST:
-			if (descr().is_animation_known("sinking")) {
-				m_ship_state = SINK_ANIMATION;
-				start_task_idle(game, descr().get_animation("sinking"), 3000);
-				return;
-			}
-			log("Oh no... this ship has no sinking animation :(!\n");
-			// fall trough
-		case SINK_ANIMATION:
-			// The sink animation has been played, so finally remove the ship from the map
-			pop_task(game);
-			remove(game);
-			return;
-		default:
-			assert(false); // never here
+	case TRANSPORT:
+		if (ship_update_transport(game, state))
+			return;
+		break;
+	case EXP_FOUNDPORTSPACE:
+	case EXP_SCOUTING:
+	case EXP_WAITING:
+		ship_update_expedition(game, state);
+		break;
+	case EXP_COLONIZING:
+		break;
+	case SINK_REQUEST:
+		if (descr().is_animation_known("sinking")) {
+			m_ship_state = SINK_ANIMATION;
+			start_task_idle(game, descr().get_animation("sinking"), 3000);
+			return;
+		}
+		log("Oh no... this ship has no sinking animation :(!\n");
+	// fall trough
+	case SINK_ANIMATION:
+		// The sink animation has been played, so finally remove the ship from the map
+		pop_task(game);
+		remove(game);
+		return;
+	default:
+		assert(false);  // never here
 	}
 
 	// if the real update function failed (e.g. nothing to transport), the ship goes idle
 	ship_update_idle(game, state);
 }
 
-
 /// updates a ships tasks in transport mode \returns false if failed to update tasks
-bool Ship::ship_update_transport(Game & game, Bob::State &) {
-	Map & map = game.map();
+bool Ship::ship_update_transport(Game& game, Bob::State&) {
+	Map& map = game.map();
 
-	PortDock * dst = get_destination(game);
+	PortDock* dst = get_destination(game);
 	if (!dst) {
 		molog("ship_update: No destination anymore.\n");
 		if (m_items.empty())
@@ -277,7 +269,7 @@
 
 	molog("ship_update: Go to dock %u\n", dst->serial());
 
-	PortDock * lastdock = m_lastdock.get(game);
+	PortDock* lastdock = m_lastdock.get(game);
 	if (lastdock && lastdock != dst) {
 		molog("ship_update: Have lastdock %u\n", lastdock->serial());
 
@@ -332,10 +324,9 @@
 	return true;
 }
 
-
 /// updates a ships tasks in expedition mode
-void Ship::ship_update_expedition(Game & game, Bob::State &) {
-	Map & map = game.map();
+void Ship::ship_update_expedition(Game& game, Bob::State&) {
+	Map& map = game.map();
 
 	assert(m_expedition);
 
@@ -343,30 +334,30 @@
 	FCoords position = get_position();
 	for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
 		m_expedition->swimable[dir - 1] =
-			map.get_neighbour(position, dir).field->nodecaps() & MOVECAPS_SWIM;
+		   map.get_neighbour(position, dir).field->nodecaps() & MOVECAPS_SWIM;
 	}
 
 	if (m_ship_state == EXP_SCOUTING) {
 		// Check surrounding fields for port buildspaces
-		std::unique_ptr<std::list<Coords> > temp_port_buildspaces(new std::list<Coords>());
-		MapRegion<Area<Coords> > mr(map, Area<Coords>(position, descr().vision_range()));
+		std::unique_ptr<std::list<Coords>> temp_port_buildspaces(new std::list<Coords>());
+		MapRegion<Area<Coords>> mr(map, Area<Coords>(position, descr().vision_range()));
 		bool new_port_space = false;
 		do {
 			if (map.is_port_space(mr.location())) {
 				FCoords fc = map.get_fcoords(mr.location());
 
-				// Check whether the maximum theoretical possible NodeCap of the field is of the size big
+				// Check whether the maximum theoretical possible NodeCap of the field is of the size
+				// big
 				// and whether it can theoretically be a port space
-				if
-					((map.get_max_nodecaps(game.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG
-					 ||
-					 map.find_portdock(fc).empty())
-				{
+				if ((map.get_max_nodecaps(game.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG ||
+				    map.find_portdock(fc).empty()) {
 					continue;
 				}
 
-				// NOTE This is the place to handle enemy territory and "clearing a port space from the enemy".
-				// NOTE There is a simple check for the current land owner to avoid placement of ports into enemy
+				// NOTE This is the place to handle enemy territory and "clearing a port space from the
+				// enemy".
+				// NOTE There is a simple check for the current land owner to avoid placement of ports
+				// into enemy
 				// NOTE territory, as "clearing" is not yet implemented.
 				// NOTE further it checks, whether there is a Player_immovable on one of the fields.
 				// TODO(unknown): handle this more gracefully concering opposing players
@@ -378,7 +369,7 @@
 						invalid = true;
 						continue;
 					}
-					BaseImmovable * baim = coord.field->get_immovable();
+					BaseImmovable* baim = coord.field->get_immovable();
 					if (baim)
 						if (is_a(PlayerImmovable, baim)) {
 							invalid = true;
@@ -387,60 +378,60 @@
 
 					// Check all neighboured fields that will be used by the port
 					switch (step) {
-						case 0:
-							map.get_ln(fc, &coord);
-							break;
-						case 1:
-							map.get_tln(fc, &coord);
-							break;
-						case 2:
-							map.get_trn(fc, &coord);
-							break;
-						case 3:
-							// Flag coordinate
-							map.get_brn(fc, &coord);
-							break;
-						default:
-							break;
+					case 0:
+						map.get_ln(fc, &coord);
+						break;
+					case 1:
+						map.get_tln(fc, &coord);
+						break;
+					case 2:
+						map.get_trn(fc, &coord);
+						break;
+					case 3:
+						// Flag coordinate
+						map.get_brn(fc, &coord);
+						break;
+					default:
+						break;
 					}
 				}
 				// Now check whether there is a flag in the surroundings of the flag position
 				FCoords neighb;
 				map.get_ln(coord, &neighb);
 				for (uint8_t step = 0; !invalid && step < 5; ++step) {
-					BaseImmovable * baim = neighb.field->get_immovable();
+					BaseImmovable* baim = neighb.field->get_immovable();
 					if (baim)
 						if (is_a(Flag, baim)) {
 							invalid = true;
 							continue;
 						}
-					// Check all neighboured fields but not the one already checked for a PlayerImmovable.
+					// Check all neighboured fields but not the one already checked for a
+					// PlayerImmovable.
 					switch (step) {
-						case 0:
-							map.get_bln(coord, &neighb);
-							break;
-						case 1:
-							map.get_brn(coord, &neighb);
-							break;
-						case 2:
-							map.get_rn(coord, &neighb);
-							break;
-						case 3:
-							map.get_trn(coord, &neighb);
-							break;
-						default:
-							break;
+					case 0:
+						map.get_bln(coord, &neighb);
+						break;
+					case 1:
+						map.get_brn(coord, &neighb);
+						break;
+					case 2:
+						map.get_rn(coord, &neighb);
+						break;
+					case 3:
+						map.get_trn(coord, &neighb);
+						break;
+					default:
+						break;
 					}
 				}
 				if (invalid)
 					continue;
 
 				bool pbs_saved = false;
-				for
-					(std::list<Coords>::const_iterator it = m_expedition->seen_port_buildspaces->begin();
-					 it != m_expedition->seen_port_buildspaces->end() && !pbs_saved;
-					 ++it)
-				{
+				for (std::list<Coords>::const_iterator it =
+				        m_expedition->seen_port_buildspaces->begin();
+				     it != m_expedition->seen_port_buildspaces->end() && !pbs_saved;
+				     ++it) {
 					// Check if the ship knows this port space already from its last check
 					if (*it == mr.location()) {
 						temp_port_buildspaces->push_back(mr.location());
@@ -462,10 +453,13 @@
 			send_message(game, "exp_port_space", msg_head, msg_body, "port.png");
 		}
 		m_expedition->seen_port_buildspaces.swap(temp_port_buildspaces);
+		if (new_port_space) {
+			Notifications::publish(NoteShipMessage(this, NoteShipMessage::Message::WAITINGFORCOMMAND));
+		}
 	}
 }
 
-void Ship::ship_update_idle(Game & game, Bob::State & state) {
+void Ship::ship_update_idle(Game& game, Bob::State& state) {
 	if (state.ivar1) {
 		// We've just completed one step, so give neighbours
 		// a chance to move away first
@@ -475,172 +469,182 @@
 		return;
 	}
 
-	// If we are waiting for the next transport job, check if we should move away from ships and shores
+	// If we are waiting for the next transport job, check if we should move away from ships and
+	// shores
 	switch (m_ship_state) {
-		case TRANSPORT: {
-			FCoords position = get_position();
-			Map & map = game.map();
-			unsigned int dirs[LAST_DIRECTION + 1];
-			unsigned int dirmax = 0;
-
+	case TRANSPORT: {
+		FCoords position = get_position();
+		Map& map = game.map();
+		unsigned int dirs[LAST_DIRECTION + 1];
+		unsigned int dirmax = 0;
+
+		for (Direction dir = 0; dir <= LAST_DIRECTION; ++dir) {
+			FCoords node = dir ? map.get_neighbour(position, dir) : position;
+			dirs[dir] = node.field->nodecaps() & MOVECAPS_WALK ? 10 : 0;
+
+			Area<FCoords> area(node, 0);
+			std::vector<Bob*> ships;
+			map.find_bobs(area, &ships, FindBobShip());
+
+			for (std::vector<Bob*>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
+				if (*it == this)
+					continue;
+
+				dirs[dir] += 3;
+			}
+
+			dirmax = std::max(dirmax, dirs[dir]);
+		}
+
+		if (dirmax) {
+			unsigned int prob[LAST_DIRECTION + 1];
+			unsigned int totalprob = 0;
+
+			// The probability for moving into a given direction is also
+			// affected by the "close" directions.
 			for (Direction dir = 0; dir <= LAST_DIRECTION; ++dir) {
-				FCoords node = dir ? map.get_neighbour(position, dir) : position;
-				dirs[dir] = node.field->nodecaps() & MOVECAPS_WALK ? 10 : 0;
-
-				Area<FCoords> area(node, 0);
-				std::vector<Bob *> ships;
-				map.find_bobs(area, &ships, FindBobShip());
-
-				for (std::vector<Bob *>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
-					if (*it == this)
-						continue;
-
-					dirs[dir] += 3;
-				}
-
-				dirmax = std::max(dirmax, dirs[dir]);
-			}
-
-			if (dirmax) {
-				unsigned int prob[LAST_DIRECTION + 1];
-				unsigned int totalprob = 0;
-
-				// The probability for moving into a given direction is also
-				// affected by the "close" directions.
-				for (Direction dir = 0; dir <= LAST_DIRECTION; ++dir) {
-					prob[dir] = 10 * dirmax - 10 * dirs[dir];
-
-					if (dir > 0) {
-						unsigned int delta = std::min(prob[dir], dirs[(dir % 6) + 1] + dirs[1 + ((dir - 1) % 6)]);
-						prob[dir] -= delta;
-					}
-
-					totalprob += prob[dir];
-				}
-
-				if (totalprob == 0) {
-					start_task_idle(game, descr().main_animation(), 1500);
-					return;
-				}
-
-				unsigned int rnd = game.logic_rand() % totalprob;
-				Direction dir = 0;
-				while (rnd >= prob[dir]) {
-					rnd -= prob[dir];
-					++dir;
-				}
-
-				if (dir == 0 || dir > LAST_DIRECTION) {
-					start_task_idle(game, descr().main_animation(), 1500);
-					return;
-				}
-
-				FCoords neighbour = map.get_neighbour(position, dir);
-				if (!(neighbour.field->nodecaps() & MOVECAPS_SWIM)) {
-					start_task_idle(game, descr().main_animation(), 1500);
-					return;
-				}
-
-				state.ivar1 = 1;
-				start_task_move(game, dir, descr().get_sail_anims(), false);
-				return;
-			}
-			// No desire to move around, so sleep
-			start_task_idle(game, descr().main_animation(), -1);
+				prob[dir] = 10 * dirmax - 10 * dirs[dir];
+
+				if (dir > 0) {
+					unsigned int delta =
+					   std::min(prob[dir], dirs[(dir % 6) + 1] + dirs[1 + ((dir - 1) % 6)]);
+					prob[dir] -= delta;
+				}
+
+				totalprob += prob[dir];
+			}
+
+			if (totalprob == 0) {
+				start_task_idle(game, descr().main_animation(), 1500);
+				return;
+			}
+
+			unsigned int rnd = game.logic_rand() % totalprob;
+			Direction dir = 0;
+			while (rnd >= prob[dir]) {
+				rnd -= prob[dir];
+				++dir;
+			}
+
+			if (dir == 0 || dir > LAST_DIRECTION) {
+				start_task_idle(game, descr().main_animation(), 1500);
+				return;
+			}
+
+			FCoords neighbour = map.get_neighbour(position, dir);
+			if (!(neighbour.field->nodecaps() & MOVECAPS_SWIM)) {
+				start_task_idle(game, descr().main_animation(), 1500);
+				return;
+			}
+
+			state.ivar1 = 1;
+			start_task_move(game, dir, descr().get_sail_anims(), false);
 			return;
 		}
-		case EXP_SCOUTING: {
-			if (m_expedition->island_exploration) { // Exploration of the island
-				if (exp_close_to_coast()) {
-					if (m_expedition->direction == 0) {
-						// Make sure we know the location of the coast and use it as initial direction we come from
-						m_expedition->direction = WALK_SE;
-						for (uint8_t secure = 0; exp_dir_swimable(m_expedition->direction); ++secure) {
-							assert(secure < 6);
-							m_expedition->direction = get_cw_neighbour(m_expedition->direction);
-						}
-						m_expedition->direction = get_backward_dir(m_expedition->direction);
-						// Save the position - this is where we start
-						m_expedition->exploration_start = get_position();
-					} else {
-						// Check whether the island was completely surrounded
-						if (get_position() == m_expedition->exploration_start) {
-							std::string msg_head = _("Island Circumnavigated");
-							std::string msg_body = _("An expedition ship sailed around its"
-										 " island without any events.");
-							send_message(game, "exp_island", msg_head, msg_body,
-								"ship_explore_island_cw.png");
-							m_ship_state = EXP_WAITING;
-							return start_task_idle(game, descr().main_animation(), 1500);
-						}
+		// No desire to move around, so sleep
+		start_task_idle(game, descr().main_animation(), -1);
+		return;
+	}
+	case EXP_SCOUTING: {
+		if (m_expedition->island_exploration) {  // Exploration of the island
+			if (exp_close_to_coast()) {
+				if (m_expedition->direction == 0) {
+					// Make sure we know the location of the coast and use it as initial direction we
+					// come from
+					m_expedition->direction = WALK_SE;
+					for (uint8_t secure = 0; exp_dir_swimable(m_expedition->direction); ++secure) {
+						assert(secure < 6);
+						m_expedition->direction = get_cw_neighbour(m_expedition->direction);
 					}
-					// The ship is supposed to follow the coast as close as possible, therefore the check for
-					// a swimable field begins at the neighbour field of the direction we came from.
 					m_expedition->direction = get_backward_dir(m_expedition->direction);
-					if (m_expedition->clockwise) {
-						do {
-							m_expedition->direction = get_ccw_neighbour(m_expedition->direction);
-						} while (!exp_dir_swimable(m_expedition->direction));
-					} else {
-						do {
-							m_expedition->direction = get_cw_neighbour(m_expedition->direction);
-						} while (!exp_dir_swimable(m_expedition->direction));
-					}
-					state.ivar1 = 1;
-					return start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
-				} else {
-					// The ship got the command to scout around an island, but is not close to any island
-					// Most likely the command was send as the ship was on an exploration and just leaving
-					// the island - therefore we try to find the island again.
-					FCoords position = get_position();
-					Map & map = game.map();
-					for (uint8_t dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
-						FCoords neighbour = map.get_neighbour(position, dir);
-						for (uint8_t sur = FIRST_DIRECTION; sur <= LAST_DIRECTION; ++sur)
-							if (!(map.get_neighbour(neighbour, sur).field->nodecaps() & MOVECAPS_SWIM)) {
-								// Okay we found the next coast, so now the ship should go there.
-								// However, we do neither save the position as starting position, nor do we save
-								// the direction we currently go. So the ship can start exploring normally
-								state.ivar1 = 1;
-								return start_task_move(game, dir, descr().get_sail_anims(), false);
-							}
-					}
-					// if we are here, it seems something really strange happend.
-					log("WARNING: ship was not able to start exploration. Entering WAIT mode.");
-					m_ship_state = EXP_WAITING;
-					return start_task_idle(game, descr().main_animation(), 1500);
-				}
-			} else { // scouting towards a specific direction
-				if (exp_dir_swimable(m_expedition->direction)) {
-					// the scouting direction is still free to move
-					state.ivar1 = 1;
-					start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
-					return;
-				}
-				// coast reached
+					// Save the position - this is where we start
+					m_expedition->exploration_start = get_position();
+				} else {
+					// Check whether the island was completely surrounded
+					if (get_position() == m_expedition->exploration_start) {
+						std::string msg_head = _("Island Circumnavigated");
+						std::string msg_body = _("An expedition ship sailed around its"
+						                         " island without any events.");
+						send_message(
+						   game, "exp_island", msg_head, msg_body, "ship_explore_island_cw.png");
+						m_ship_state = EXP_WAITING;
+						Notifications::publish(
+						   NoteShipMessage(this, NoteShipMessage::Message::WAITINGFORCOMMAND));
+						return start_task_idle(game, descr().main_animation(), 1500);
+					}
+				}
+				// The ship is supposed to follow the coast as close as possible, therefore the check
+				// for
+				// a swimable field begins at the neighbour field of the direction we came from.
+				m_expedition->direction = get_backward_dir(m_expedition->direction);
+				if (m_expedition->clockwise) {
+					do {
+						m_expedition->direction = get_ccw_neighbour(m_expedition->direction);
+					} while (!exp_dir_swimable(m_expedition->direction));
+				} else {
+					do {
+						m_expedition->direction = get_cw_neighbour(m_expedition->direction);
+					} while (!exp_dir_swimable(m_expedition->direction));
+				}
+				state.ivar1 = 1;
+				return start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
+			} else {
+				// The ship got the command to scout around an island, but is not close to any island
+				// Most likely the command was send as the ship was on an exploration and just leaving
+				// the island - therefore we try to find the island again.
+				FCoords position = get_position();
+				Map& map = game.map();
+				for (uint8_t dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
+					FCoords neighbour = map.get_neighbour(position, dir);
+					for (uint8_t sur = FIRST_DIRECTION; sur <= LAST_DIRECTION; ++sur)
+						if (!(map.get_neighbour(neighbour, sur).field->nodecaps() & MOVECAPS_SWIM)) {
+							// Okay we found the next coast, so now the ship should go there.
+							// However, we do neither save the position as starting position, nor do we
+							// save
+							// the direction we currently go. So the ship can start exploring normally
+							state.ivar1 = 1;
+							return start_task_move(game, dir, descr().get_sail_anims(), false);
+						}
+				}
+				// if we are here, it seems something really strange happend.
+				log("WARNING: ship was not able to start exploration. Entering WAIT mode.");
 				m_ship_state = EXP_WAITING;
-				start_task_idle(game, descr().main_animation(), 1500);
-				// Send a message to the player, that a new coast was reached
-				std::string msg_head = _("Coast Reached");
-				std::string msg_body =
-					_("An expedition ship reached a coast and is waiting for further commands.");
-				send_message(game, "exp_coast", msg_head, msg_body, "ship_explore_island_cw.png");
+				return start_task_idle(game, descr().main_animation(), 1500);
+			}
+		} else {  // scouting towards a specific direction
+			if (exp_dir_swimable(m_expedition->direction)) {
+				// the scouting direction is still free to move
+				state.ivar1 = 1;
+				start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
 				return;
 			}
+			// coast reached
+			m_ship_state = EXP_WAITING;
+			start_task_idle(game, descr().main_animation(), 1500);
+			// Send a message to the player, that a new coast was reached
+			std::string msg_head = _("Coast Reached");
+			std::string msg_body =
+			   _("An expedition ship reached a coast and is waiting for further commands.");
+			send_message(game, "exp_coast", msg_head, msg_body, "ship_explore_island_cw.png");
+			Notifications::publish(NoteShipMessage(this, NoteShipMessage::Message::WAITINGFORCOMMAND));
+			return;
 		}
-		case EXP_COLONIZING: {
-			assert(m_expedition->seen_port_buildspaces && !m_expedition->seen_port_buildspaces->empty());
-			BaseImmovable * baim = game.map()[m_expedition->seen_port_buildspaces->front()].get_immovable();
-			assert(baim);
+	}
+	case EXP_COLONIZING: {
+		assert(m_expedition->seen_port_buildspaces && !m_expedition->seen_port_buildspaces->empty());
+		BaseImmovable* baim =
+		   game.map()[m_expedition->seen_port_buildspaces->front()].get_immovable();
+		if (baim) {
 			upcast(ConstructionSite, cs, baim);
 
 			for (int i = m_items.size() - 1; i >= 0; --i) {
-				WareInstance * ware;
-				Worker * worker;
+				WareInstance* ware;
+				Worker* worker;
 				m_items.at(i).get(game, &ware, &worker);
 				if (ware) {
-					// no, we don't transfer the wares, we create new ones out of air and remove the old ones ;)
-					WaresQueue & wq = cs->waresqueue(ware->descr_index());
+					// no, we don't transfer the wares, we create new ones out of air and remove the old
+					// ones ;)
+					WaresQueue& wq = cs->waresqueue(ware->descr_index());
 					const uint32_t max = wq.get_max_fill();
 					const uint32_t cur = wq.get_filled();
 					assert(max > cur);
@@ -654,35 +658,56 @@
 					worker->set_location(cs);
 					worker->set_position(game, cs->get_position());
 					worker->reset_tasks(game);
-					PartiallyFinishedBuilding::request_builder_callback
-						(game, *cs->get_builder_request(), worker->descr().worker_index(), worker, *cs);
+					PartiallyFinishedBuilding::request_builder_callback(
+					   game, *cs->get_builder_request(), worker->descr().worker_index(), worker, *cs);
 					m_items.resize(i);
 				}
 			}
-			if (m_items.empty()) {
-				m_ship_state = TRANSPORT; // That's it, expedition finished
-
-				init_fleet(game);
-				m_expedition.reset(nullptr);
-
-				if (upcast(InteractiveGameBase, igb, game.get_ibase()))
-					refresh_window(*igb);
+		} else {  // it seems that port constructionsite has dissapeared
+			// Send a message to the player, that a port constructionsite is gone
+			std::string msg_head = _("New port constructionsite is gone");
+			std::string msg_body = _("Unloading of wares failed, expedition is cancelled now.");
+			send_message(game, "exp_port_space", msg_head, msg_body, "port.png");
+			send_signal(game, "cancel_expedition");
+		}
+
+		if (m_items.empty() || !baim) {  // we are done, either way
+			m_ship_state = TRANSPORT;  // That's it, expedition finished
+
+			// Bring us back into a fleet and a economy.
+			init_fleet(game);
+
+			// for case that there are any workers left on board
+			// (applicable when port construction space is lost)
+			Worker* worker;
+			for (ShippingItem& item : m_items) {
+				item.get(game, nullptr, &worker);
+				if (worker) {
+					worker->reset_tasks(game);
+					worker->start_task_shipping(game, nullptr);
+				}
 			}
-			return start_task_idle(game, descr().main_animation(), 1500); // unload the next item
-		}
-
-		default: {
-			// wait for input
-			start_task_idle(game, descr().main_animation(), 1500);
-			return;
-		}
+
+			m_expedition.reset(nullptr);
+
+			if (upcast(InteractiveGameBase, igb, game.get_ibase()))
+				refresh_window(*igb);
+			return start_task_idle(game, descr().main_animation(), 1500);
+		}
+	}
+
+	default: {
+		// wait for input
+		start_task_idle(game, descr().main_animation(), 1500);
+		return;
+	}
 	}
 
 	// never here
-	assert (false);
+	assert(false);
 }
 
-void Ship::set_economy(Game & game, Economy * e) {
+void Ship::set_economy(Game& game, Economy* e) {
 	// Do not check here that the economy actually changed, because on loading
 	// we rely that wares really get reassigned our economy.
 
@@ -697,23 +722,23 @@
  *
  * @note This is supposed to be called only from the scheduling code of @ref Fleet.
  */
-void Ship::set_destination(Game & game, PortDock & pd) {
+void Ship::set_destination(Game& game, PortDock& pd) {
 	molog("set_destination to %u (currently %" PRIuS " items)\n", pd.serial(), m_items.size());
 	m_destination = &pd;
 	send_signal(game, "wakeup");
 }
 
-void Ship::add_item(Game & game, const ShippingItem & item) {
+void Ship::add_item(Game& game, const ShippingItem& item) {
 	assert(m_items.size() < descr().get_capacity());
 
 	m_items.push_back(item);
 	m_items.back().set_location(game, this);
 }
 
-void Ship::withdraw_items(Game & game, PortDock & pd, std::vector<ShippingItem> & items) {
+void Ship::withdraw_items(Game& game, PortDock& pd, std::vector<ShippingItem>& items) {
 	uint32_t dst = 0;
 	for (uint32_t src = 0; src < m_items.size(); ++src) {
-		PortDock * destination = m_items[src].get_destination(game);
+		PortDock* destination = m_items[src].get_destination(game);
 		if (!destination || destination == &pd) {
 			items.push_back(m_items[src]);
 		} else {
@@ -726,8 +751,8 @@
 /**
  * Find a path to the dock @p pd and follow it without using precomputed paths.
  */
-void Ship::start_task_movetodock(Game & game, PortDock & pd) {
-	Map & map = game.map();
+void Ship::start_task_movetodock(Game& game, PortDock& pd) {
+	Map& map = game.map();
 	StepEvalAStar se(pd.get_warehouse()->get_position());
 	se.m_swim = true;
 	se.m_conservative = false;
@@ -753,7 +778,7 @@
 }
 
 /// Prepare everything for the coming exploration
-void Ship::start_task_expedition(Game & game) {
+void Ship::start_task_expedition(Game& game) {
 	// Now we are waiting
 	m_ship_state = EXP_WAITING;
 	// Initialize a new, yet empty expedition
@@ -773,8 +798,8 @@
 	set_economy(game, m_expedition->economy.get());
 
 	for (int i = m_items.size() - 1; i >= 0; --i) {
-		WareInstance * ware;
-		Worker * worker;
+		WareInstance* ware;
+		Worker* worker;
 		m_items.at(i).get(game, &ware, &worker);
 		if (worker) {
 			worker->reset_tasks(game);
@@ -788,11 +813,12 @@
 	const std::string msg_head = _("Expedition Ready");
 	const std::string msg_body = _("An expedition ship is waiting for your commands.");
 	send_message(game, "exp_ready", msg_head, msg_body, "start_expedition.png");
+	Notifications::publish(NoteShipMessage(this, NoteShipMessage::Message::WAITINGFORCOMMAND));
 }
 
 /// Initializes / changes the direction of scouting to @arg direction
 /// @note only called via player command
-void Ship::exp_scout_direction(Game &, uint8_t direction) {
+void Ship::exp_scout_direction(Game&, uint8_t direction) {
 	assert(m_expedition);
 	m_ship_state = EXP_SCOUTING;
 	m_expedition->direction = direction;
@@ -801,7 +827,7 @@
 
 /// Initializes the construction of a port at @arg c
 /// @note only called via player command
-void Ship::exp_construct_port (Game &, const Coords& c) {
+void Ship::exp_construct_port(Game&, const Coords& c) {
 	assert(m_expedition);
 	BuildingIndex port_idx = get_owner()->tribe().safe_building_index("port");
 	get_owner()->force_csite(c, port_idx);
@@ -810,7 +836,7 @@
 
 /// Initializes / changes the direction the island exploration in @arg clockwise direction
 /// @note only called via player command
-void Ship::exp_explore_island (Game &, bool clockwise) {
+void Ship::exp_explore_island(Game&, bool clockwise) {
 	assert(m_expedition);
 	m_ship_state = EXP_SCOUTING;
 	m_expedition->clockwise = clockwise;
@@ -820,9 +846,10 @@
 
 /// Cancels a currently running expedition
 /// @note only called via player command
-void Ship::exp_cancel (Game & game) {
+void Ship::exp_cancel(Game& game) {
 	// Running colonization has the highest priority before cancelation
 	// + cancelation only works if an expedition is actually running
+
 	if ((m_ship_state == EXP_COLONIZING) || !state_is_expedition())
 		return;
 	send_signal(game, "cancel_expedition");
@@ -834,7 +861,7 @@
 	// Theres nothing to be done for wares - they already changed
 	// economy with us and the warehouse will make sure that they are
 	// getting used.
-	Worker * worker;
+	Worker* worker;
 	for (ShippingItem& item : m_items) {
 		item.get(game, nullptr, &worker);
 		if (worker) {
@@ -859,7 +886,7 @@
 
 /// Sinks the ship
 /// @note only called via player command
-void Ship::sink_ship (Game & game) {
+void Ship::sink_ship(Game& game) {
 	// Running colonization has the highest priority + a sink request is only valid once
 	if (!state_is_sinkable())
 		return;
@@ -869,25 +896,22 @@
 	close_window();
 }
 
-void Ship::log_general_info(const EditorGameBase & egbase)
-{
+void Ship::log_general_info(const EditorGameBase& egbase) {
 	Bob::log_general_info(egbase);
 
-	molog
-		("Fleet: %u, destination: %u, lastdock: %u, carrying: %" PRIuS "\n",
-		 m_fleet? m_fleet->serial() : 0,
-		 m_destination.serial(), m_lastdock.serial(),
-		 m_items.size());
+	molog("Fleet: %u, destination: %u, lastdock: %u, carrying: %" PRIuS "\n",
+	      m_fleet ? m_fleet->serial() : 0,
+	      m_destination.serial(),
+	      m_lastdock.serial(),
+	      m_items.size());
 
 	for (const ShippingItem& shipping_item : m_items) {
-		molog
-			("  IT %u, destination %u\n",
-			 shipping_item.m_object.serial(),
-			 shipping_item.m_destination_dock.serial());
+		molog("  IT %u, destination %u\n",
+		      shipping_item.m_object.serial(),
+		      shipping_item.m_destination_dock.serial());
 	}
 }
 
-
 /**
  * Send a message to the owning player.
  *
@@ -895,31 +919,31 @@
  *
  * \param msgsender a computer-readable description of why the message was sent
  * \param title user-visible title of the message
- * \param description user-visible message body, will be placed in an appropriate rich-text paragraph
+ * \param description user-visible message body, will be placed in an appropriate rich-text
+ *paragraph
  * \param picture picture name relative to the pics directory
  */
-void Ship::send_message
-	(Game & game, const std::string & msgsender,
-	 const std::string & title, const std::string & description,
-	 const std::string & picture)
-{
+void Ship::send_message(Game& game,
+                        const std::string& msgsender,
+                        const std::string& title,
+                        const std::string& description,
+                        const std::string& picture) {
 	std::string rt_description;
 	if (picture.size() > 3) {
-		rt_description  = "<rt image=pics/";
+		rt_description = "<rt image=pics/";
 		rt_description += picture;
 		rt_description += "><p font-size=14 font-face=DejaVuSerif>";
 	} else
-		rt_description  = "<rt><p font-size=14 font-face=DejaVuSerif>";
+		rt_description = "<rt><p font-size=14 font-face=DejaVuSerif>";
 	rt_description += description;
 	rt_description += "</p></rt>";
 
-	Message * msg = new Message
-		(msgsender, game.get_gametime(), title, rt_description, get_position(), m_serial);
+	Message* msg =
+	   new Message(msgsender, game.get_gametime(), title, rt_description, get_position(), m_serial);
 
 	get_owner()->add_message(game, *msg);
 }
 
-
 /*
 ==============================
 
@@ -930,20 +954,16 @@
 
 #define SHIP_SAVEGAME_VERSION 4
 
-Ship::Loader::Loader() :
-	m_lastdock(0),
-	m_destination(0)
-{
+Ship::Loader::Loader() : m_lastdock(0), m_destination(0) {
 }
 
-const Bob::Task * Ship::Loader::get_task(const std::string & name)
-{
-	if (name == "shipidle" || name == "ship") return &taskShip;
+const Bob::Task* Ship::Loader::get_task(const std::string& name) {
+	if (name == "shipidle" || name == "ship")
+		return &taskShip;
 	return Bob::Loader::get_task(name);
 }
 
-void Ship::Loader::load(FileRead & fr, uint8_t version)
-{
+void Ship::Loader::load(FileRead& fr, uint8_t version) {
 	Bob::Loader::load(fr);
 
 	if (version >= 2) {
@@ -952,15 +972,8 @@
 			m_ship_state = fr.unsigned_8();
 
 			// Expedition specific data
-			if
-				(m_ship_state == EXP_SCOUTING
-				 ||
-				 m_ship_state == EXP_WAITING
-				 ||
-				 m_ship_state == EXP_FOUNDPORTSPACE
-				 ||
-				 m_ship_state == EXP_COLONIZING)
-			{
+			if (m_ship_state == EXP_SCOUTING || m_ship_state == EXP_WAITING ||
+			    m_ship_state == EXP_FOUNDPORTSPACE || m_ship_state == EXP_COLONIZING) {
 				m_expedition.reset(new Expedition());
 				// Currently seen port build spaces
 				m_expedition->seen_port_buildspaces.reset(new std::list<Coords>());
@@ -992,11 +1005,10 @@
 	}
 }
 
-void Ship::Loader::load_pointers()
-{
+void Ship::Loader::load_pointers() {
 	Bob::Loader::load_pointers();
 
-	Ship & ship = get<Ship>();
+	Ship& ship = get<Ship>();
 
 	if (m_lastdock)
 		ship.m_lastdock = &mol().get<PortDock>(m_lastdock);
@@ -1009,11 +1021,10 @@
 	}
 }
 
-void Ship::Loader::load_finish()
-{
+void Ship::Loader::load_finish() {
 	Bob::Loader::load_finish();
 
-	Ship & ship = get<Ship>();
+	Ship& ship = get<Ship>();
 
 	// restore the state the ship is in
 	ship.m_ship_state = m_ship_state;
@@ -1023,7 +1034,8 @@
 		ship.m_expedition.swap(m_expedition);
 		ship.m_expedition->economy.reset(new Economy(*ship.get_owner()));
 		ship.m_economy = ship.m_expedition->economy.get();
-	} else assert(m_ship_state == TRANSPORT);
+	} else
+		assert(m_ship_state == TRANSPORT);
 
 	// Workers load code set their economy to the economy of their location
 	// (which is a PlayerImmovable), that means that workers on ships do not get
@@ -1034,10 +1046,7 @@
 	ship.set_economy(ref_cast<Game>(egbase()), ship.m_economy);
 }
 
-
-MapObject::Loader * Ship::load
-	(EditorGameBase & egbase, MapObjectLoader & mol, FileRead & fr)
-{
+MapObject::Loader* Ship::load(EditorGameBase& egbase, MapObjectLoader& mol, FileRead& fr) {
 	std::unique_ptr<Loader> loader(new Loader);
 
 	try {
@@ -1047,32 +1056,28 @@
 		if (1 <= version && version <= SHIP_SAVEGAME_VERSION) {
 			std::string owner = fr.c_string();
 			std::string name = fr.c_string();
-			const ShipDescr * descr = nullptr;
+			const ShipDescr* descr = nullptr;
 
 			egbase.manually_load_tribe(owner);
 
-			if (const TribeDescr * tribe = egbase.get_tribe(owner))
-				descr = dynamic_cast<const ShipDescr *>
-					(tribe->get_bob_descr(name));
+			if (const TribeDescr* tribe = egbase.get_tribe(owner))
+				descr = dynamic_cast<const ShipDescr*>(tribe->get_bob_descr(name));
 
 			if (!descr)
-				throw GameDataError
-					("undefined ship %s/%s", owner.c_str(), name.c_str());
+				throw GameDataError("undefined ship %s/%s", owner.c_str(), name.c_str());
 
 			loader->init(egbase, mol, descr->create_object());
 			loader->load(fr, version);
 		} else
 			throw GameDataError("unknown/unhandled version %u", version);
-	} catch (const std::exception & e) {
+	} catch (const std::exception& e) {
 		throw wexception("loading ship: %s", e.what());
 	}
 
 	return loader.release();
 }
 
-void Ship::save
-	(EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
-{
+void Ship::save(EditorGameBase& egbase, MapObjectSaver& mos, FileWrite& fw) {
 	fw.unsigned_8(HeaderShip);
 	fw.unsigned_8(SHIP_SAVEGAME_VERSION);
 
@@ -1089,11 +1094,9 @@
 		// currently seen port buildspaces
 		assert(m_expedition->seen_port_buildspaces);
 		fw.unsigned_8(m_expedition->seen_port_buildspaces->size());
-		for
-			(std::list<Coords>::const_iterator it = m_expedition->seen_port_buildspaces->begin();
-			 it != m_expedition->seen_port_buildspaces->end();
-			 ++it)
-		{
+		for (std::list<Coords>::const_iterator it = m_expedition->seen_port_buildspaces->begin();
+		     it != m_expedition->seen_port_buildspaces->end();
+		     ++it) {
 			write_coords_32(&fw, *it);
 		}
 		// swimability of the directions
@@ -1118,4 +1121,4 @@
 	}
 }
 
-} // namespace Widelands
+}  // namespace Widelands

=== modified file 'src/logic/ship.h'
--- src/logic/ship.h	2014-09-10 08:55:04 +0000
+++ src/logic/ship.h	2014-11-19 21:19:43 +0000
@@ -37,6 +37,19 @@
 struct Fleet;
 class PortDock;
 
+struct NoteShipMessage {
+	CAN_BE_SEND_AS_NOTE(NoteId::ShipMessage)
+
+	Ship* ship;
+
+	enum class Message {LOST, GAINED, WAITINGFORCOMMAND};
+	Message message;
+
+	NoteShipMessage(Ship* const init_ship, Message const init_message)
+	   : ship(init_ship), message(init_message) {
+	}
+};
+
 struct ShipDescr : BobDescr {
 	ShipDescr
 		(char const * name, char const * descname,

=== modified file 'src/logic/warehouse.cc'
--- src/logic/warehouse.cc	2014-09-30 05:41:55 +0000
+++ src/logic/warehouse.cc	2014-11-19 21:19:43 +0000
@@ -51,7 +51,7 @@
 
 namespace Widelands {
 
-namespace  {
+namespace {
 
 static const uint32_t WORKER_WITHOUT_COST_SPAWN_INTERVAL = 2500;
 
@@ -69,19 +69,17 @@
 
 }  // namespace
 
-WarehouseSupply::~WarehouseSupply()
-{
+WarehouseSupply::~WarehouseSupply() {
 	if (m_economy) {
-		log
-			("WarehouseSupply::~WarehouseSupply: Warehouse %u still belongs to "
-			 "an economy",
-			 m_warehouse->serial());
+		log("WarehouseSupply::~WarehouseSupply: Warehouse %u still belongs to "
+		    "an economy",
+		    m_warehouse->serial());
 		set_economy(nullptr);
 	}
 
 	// We're removed from the Economy. Therefore, the wares can simply
 	// be cleared out. The global inventory will be okay.
-	m_wares  .clear();
+	m_wares.clear();
 	m_workers.clear();
 }
 
@@ -97,10 +95,8 @@
 	m_workers.set_nrwares(i);
 }
 
-
 /// Add and remove our wares and the Supply to the economies as necessary.
-void WarehouseSupply::set_economy(Economy * const e)
-{
+void WarehouseSupply::set_economy(Economy* const e) {
 	if (e == m_economy)
 		return;
 
@@ -127,87 +123,74 @@
 	}
 }
 
-
 /// Add wares and update the economy.
-void WarehouseSupply::add_wares(WareIndex const id, uint32_t const count)
-{
+void WarehouseSupply::add_wares(WareIndex const id, uint32_t const count) {
 	if (!count)
 		return;
 
-	if (m_economy) // No economies in the editor
+	if (m_economy)  // No economies in the editor
 		m_economy->add_wares(id, count);
 	m_wares.add(id, count);
 }
 
-
 /// Remove wares and update the economy.
-void WarehouseSupply::remove_wares(WareIndex const id, uint32_t const count)
-{
+void WarehouseSupply::remove_wares(WareIndex const id, uint32_t const count) {
 	if (!count)
 		return;
 
 	m_wares.remove(id, count);
-	if (m_economy) // No economies in the editor
+	if (m_economy)  // No economies in the editor
 		m_economy->remove_wares(id, count);
 }
 
-
 /// Add workers and update the economy.
-void WarehouseSupply::add_workers(WareIndex const id, uint32_t const count)
-{
+void WarehouseSupply::add_workers(WareIndex const id, uint32_t const count) {
 	if (!count)
 		return;
 
-	if (m_economy) // No economies in the editor
+	if (m_economy)  // No economies in the editor
 		m_economy->add_workers(id, count);
 	m_workers.add(id, count);
 }
 
-
 /**
  * Remove workers and update the economy.
  * Comments see add_workers
  */
-void WarehouseSupply::remove_workers(WareIndex const id, uint32_t const count)
-{
+void WarehouseSupply::remove_workers(WareIndex const id, uint32_t const count) {
 	if (!count)
 		return;
 
 	m_workers.remove(id, count);
-	if (m_economy) // No economies in the editor
+	if (m_economy)  // No economies in the editor
 		m_economy->remove_workers(id, count);
 }
 
 /// Return the position of the Supply, i.e. the owning Warehouse.
-PlayerImmovable * WarehouseSupply::get_position(Game &) {return m_warehouse;}
-
+PlayerImmovable* WarehouseSupply::get_position(Game&) {
+	return m_warehouse;
+}
 
 /// Warehouse supplies are never active.
-bool WarehouseSupply::is_active() const {return false;}
+bool WarehouseSupply::is_active() const {
+	return false;
+}
 
-bool WarehouseSupply::has_storage() const
-{
+bool WarehouseSupply::has_storage() const {
 	return true;
 }
 
-void WarehouseSupply::get_ware_type(WareWorker & /* type */, WareIndex & /* ware */) const
-{
-	throw wexception
-		("WarehouseSupply::get_ware_type: calling this is nonsensical");
+void WarehouseSupply::get_ware_type(WareWorker& /* type */, WareIndex& /* ware */) const {
+	throw wexception("WarehouseSupply::get_ware_type: calling this is nonsensical");
 }
 
-void WarehouseSupply::send_to_storage(Game &, Warehouse * /* wh */)
-{
+void WarehouseSupply::send_to_storage(Game&, Warehouse* /* wh */) {
 	throw wexception("WarehouseSupply::send_to_storage: should never be called");
 }
 
-uint32_t WarehouseSupply::nr_supplies
-	(const Game & game, const Request & req) const
-{
+uint32_t WarehouseSupply::nr_supplies(const Game& game, const Request& req) const {
 	if (req.get_type() == wwWORKER)
-		return
-			m_warehouse->count_workers
-				(game, req.get_index(), req.get_requirements());
+		return m_warehouse->count_workers(game, req.get_index(), req.get_requirements());
 
 	//  Calculate how many wares can be sent out - it might be that we need them
 	// ourselves. E.g. for hiring new soldiers.
@@ -217,18 +200,16 @@
 	// of *this* warehouse + 1 (+1 is important, as else the ware would directly
 	// be taken back to the warehouse as the request of the warehouse would be
 	// highered and would have the same value as the original request)
-	int32_t const y =
-		x + (req.get_priority(0) / 100)
-		- (m_warehouse->get_priority(wwWARE, req.get_index()) / 100) - 1;
+	int32_t const y = x + (req.get_priority(0) / 100) -
+	                  (m_warehouse->get_priority(wwWARE, req.get_index()) / 100) - 1;
 	// But the number should never be higher than the number of wares available
 	if (y > x)
 		return x;
 	return (x > 0) ? x : 0;
 }
 
-
 /// Launch a ware.
-WareInstance & WarehouseSupply::launch_ware(Game & game, const Request & req) {
+WareInstance& WarehouseSupply::launch_ware(Game& game, const Request& req) {
 	if (req.get_type() != wwWARE)
 		throw wexception("WarehouseSupply::launch_ware: called for non-ware request");
 	if (!m_wares.stock(req.get_index()))
@@ -238,29 +219,26 @@
 }
 
 /// Launch a ware as worker.
-Worker & WarehouseSupply::launch_worker(Game & game, const Request & req)
-{
-	return
-		m_warehouse->launch_worker
-			(game, req.get_index(), req.get_requirements());
+Worker& WarehouseSupply::launch_worker(Game& game, const Request& req) {
+	return m_warehouse->launch_worker(game, req.get_index(), req.get_requirements());
 }
 
-
 /*
 ==============================
 Warehouse Building
 ==============================
 */
 
-
 /// Warehouse Descr
-WarehouseDescr::WarehouseDescr
-	(char const* const _name, char const* const _descname,
-	 const std::string& directory, Profile& prof, Section& global_s, const TribeDescr& _tribe)
-	: BuildingDescr(MapObjectType::WAREHOUSE, _name, _descname, directory, prof, global_s, _tribe),
-	  m_conquers         (0),
-	  m_heal_per_second  (0)
-{
+WarehouseDescr::WarehouseDescr(char const* const _name,
+                               char const* const _descname,
+                               const std::string& directory,
+                               Profile& prof,
+                               Section& global_s,
+                               const TribeDescr& _tribe)
+   : BuildingDescr(MapObjectType::WAREHOUSE, _name, _descname, directory, prof, global_s, _tribe),
+     m_conquers(0),
+     m_heal_per_second(0) {
 	m_heal_per_second = global_s.get_safe_int("heal_per_second");
 	if ((m_conquers = prof.get_safe_section("global").get_positive("conquers", 0)))
 		m_workarea_info[m_conquers].insert(descname() + " conquer");
@@ -272,25 +250,21 @@
 ==============================
 */
 
-Warehouse::Warehouse(const WarehouseDescr & warehouse_descr) :
-	Building(warehouse_descr),
-	m_supply(new WarehouseSupply(this)),
-	m_next_military_act(0),
-	m_portdock(nullptr)
-{
+Warehouse::Warehouse(const WarehouseDescr& warehouse_descr)
+   : Building(warehouse_descr),
+     m_supply(new WarehouseSupply(this)),
+     m_next_military_act(0),
+     m_portdock(nullptr) {
 	uint8_t nr_worker_types_without_cost =
-		warehouse_descr.tribe().worker_types_without_cost().size();
-	m_next_worker_without_cost_spawn =
-		new uint32_t[nr_worker_types_without_cost];
+	   warehouse_descr.tribe().worker_types_without_cost().size();
+	m_next_worker_without_cost_spawn = new uint32_t[nr_worker_types_without_cost];
 	for (int i = 0; i < nr_worker_types_without_cost; ++i) {
 		m_next_worker_without_cost_spawn[i] = never();
 	}
 	m_next_stock_remove_act = 0;
 }
 
-
-Warehouse::~Warehouse()
-{
+Warehouse::~Warehouse() {
 	delete m_supply;
 	delete[] m_next_worker_without_cost_spawn;
 }
@@ -299,22 +273,19 @@
  * Try to bring the given \ref PlannedWorkers up to date with our game data.
  * Return \c false if \p pw cannot be salvaged.
  */
-bool Warehouse::_load_finish_planned_worker(PlannedWorkers & pw)
-{
+bool Warehouse::_load_finish_planned_worker(PlannedWorkers& pw) {
 	if (pw.index == INVALID_INDEX || !(pw.index < m_supply->get_workers().get_nrwareids()))
 		return false;
 
-	const WorkerDescr * w_desc = descr().tribe().get_worker_descr(pw.index);
+	const WorkerDescr* w_desc = descr().tribe().get_worker_descr(pw.index);
 	if (!w_desc || !w_desc->is_buildable())
 		return false;
 
-	const WorkerDescr::Buildcost & cost = w_desc->buildcost();
+	const WorkerDescr::Buildcost& cost = w_desc->buildcost();
 	uint32_t idx = 0;
 
-	for
-		(WorkerDescr::Buildcost::const_iterator cost_it = cost.begin();
-		 cost_it != cost.end(); ++cost_it, ++idx)
-	{
+	for (WorkerDescr::Buildcost::const_iterator cost_it = cost.begin(); cost_it != cost.end();
+	     ++cost_it, ++idx) {
 		WareWorker type;
 		WareIndex ware;
 		ware = descr().tribe().ware_index(cost_it->first);
@@ -326,13 +297,10 @@
 			return false;
 
 		if (idx < pw.requests.size()) {
-			if
-				(pw.requests[idx]->get_type() == type &&
-				 pw.requests[idx]->get_index() == ware)
+			if (pw.requests[idx]->get_type() == type && pw.requests[idx]->get_index() == ware)
 				continue;
 
-			std::vector<Request *>::iterator req_it =
-				pw.requests.begin() + idx + 1;
+			std::vector<Request*>::iterator req_it = pw.requests.begin() + idx + 1;
 			while (req_it != pw.requests.end()) {
 				if ((*req_it)->get_type() == type && (*req_it)->get_index() == ware)
 					break;
@@ -345,19 +313,16 @@
 			}
 		}
 
-		log
-			("_load_finish_planned_worker: old savegame: "
-			 "need to create new request for '%s'\n",
-			 cost_it->first.c_str());
-		pw.requests.insert
-			(pw.requests.begin() + idx,
-			 new Request(*this, ware, &Warehouse::request_cb, type));
+		log("_load_finish_planned_worker: old savegame: "
+		    "need to create new request for '%s'\n",
+		    cost_it->first.c_str());
+		pw.requests.insert(
+		   pw.requests.begin() + idx, new Request(*this, ware, &Warehouse::request_cb, type));
 	}
 
 	while (pw.requests.size() > idx) {
-		log
-			("_load_finish_planned_worker: old savegame: "
-			 "removing outdated request.\n");
+		log("_load_finish_planned_worker: old savegame: "
+		    "removing outdated request.\n");
 		delete pw.requests.back();
 		pw.requests.pop_back();
 	}
@@ -365,32 +330,30 @@
 	return true;
 }
 
-void Warehouse::load_finish(EditorGameBase & egbase) {
+void Warehouse::load_finish(EditorGameBase& egbase) {
 	Building::load_finish(egbase);
 
 	uint32_t next_spawn = never();
-	const std::vector<WareIndex> & worker_types_without_cost =
-		descr().tribe().worker_types_without_cost();
+	const std::vector<WareIndex>& worker_types_without_cost =
+	   descr().tribe().worker_types_without_cost();
 	for (uint8_t i = worker_types_without_cost.size(); i;) {
 		WareIndex const worker_index = worker_types_without_cost.at(--i);
-		if
-			(owner().is_worker_type_allowed(worker_index) &&
-			 m_next_worker_without_cost_spawn[i] == static_cast<uint32_t>(never()))
-		{
+		if (owner().is_worker_type_allowed(worker_index) &&
+		    m_next_worker_without_cost_spawn[i] == static_cast<uint32_t>(never())) {
 			if (next_spawn == static_cast<uint32_t>(never()))
-				next_spawn =
-					schedule_act
-						(ref_cast<Game, EditorGameBase>(egbase),
-						 WORKER_WITHOUT_COST_SPAWN_INTERVAL);
+				next_spawn = schedule_act(
+				   ref_cast<Game, EditorGameBase>(egbase), WORKER_WITHOUT_COST_SPAWN_INTERVAL);
 			m_next_worker_without_cost_spawn[i] = next_spawn;
-			log
-				("WARNING: player %u is allowed to create worker type %s but his "
-				 "%s %u at (%i, %i) does not have a next_spawn time set for that "
-				 "worker type; setting it to %u\n",
-				 owner().player_number(),
-				 descr().tribe().get_worker_descr(worker_index)->descname().c_str(),
-				 descr().descname().c_str(), serial(), get_position().x, get_position().y,
-				 next_spawn);
+			log("WARNING: player %u is allowed to create worker type %s but his "
+			    "%s %u at (%i, %i) does not have a next_spawn time set for that "
+			    "worker type; setting it to %u\n",
+			    owner().player_number(),
+			    descr().tribe().get_worker_descr(worker_index)->descname().c_str(),
+			    descr().descname().c_str(),
+			    serial(),
+			    get_position().x,
+			    get_position().y,
+			    next_spawn);
 		}
 	}
 
@@ -408,13 +371,12 @@
 	}
 }
 
-void Warehouse::init(EditorGameBase & egbase)
-{
+void Warehouse::init(EditorGameBase& egbase) {
 	Building::init(egbase);
 
-	WareIndex const nr_wares   = descr().tribe().get_nrwares  ();
+	WareIndex const nr_wares = descr().tribe().get_nrwares();
 	WareIndex const nr_workers = descr().tribe().get_nrworkers();
-	m_supply->set_nrwares  (nr_wares);
+	m_supply->set_nrwares(nr_wares);
 	m_supply->set_nrworkers(nr_workers);
 
 	m_ware_policy.resize(nr_wares, SP_Normal);
@@ -423,17 +385,15 @@
 	// Even though technically, a warehouse might be completely empty,
 	// we let warehouse see always for simplicity's sake (since there's
 	// almost always going to be a carrier inside, that shouldn't hurt).
-	Player & player = owner();
+	Player& player = owner();
 	if (upcast(Game, game, &egbase)) {
-		player.see_area
-			(Area<FCoords>
-			 (egbase.map().get_fcoords(get_position()), descr().vision_range()));
+		player.see_area(
+		   Area<FCoords>(egbase.map().get_fcoords(get_position()), descr().vision_range()));
 
 		{
-			uint32_t const act_time = schedule_act
-					(*game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
-			const std::vector<WareIndex> & worker_types_without_cost =
-				descr().tribe().worker_types_without_cost();
+			uint32_t const act_time = schedule_act(*game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
+			const std::vector<WareIndex>& worker_types_without_cost =
+			   descr().tribe().worker_types_without_cost();
 
 			for (size_t i = 0; i < worker_types_without_cost.size(); ++i) {
 				if (owner().is_worker_type_allowed(worker_types_without_cost.at(i))) {
@@ -444,30 +404,25 @@
 		// m_next_military_act is not touched in the loading code. Is only needed
 		// if there warehous is created in the game?  I assume it's for the
 		// conquer_radius thing
-		m_next_military_act =
-			schedule_act
-				(ref_cast<Game, EditorGameBase>(egbase), 1000);
-
-		m_next_stock_remove_act =
-			schedule_act
-				(ref_cast<Game, EditorGameBase>(egbase), 4000);
-
-		log("Message: adding (wh) (%s) %i \n", to_string(descr().type()).c_str(), player.player_number());
-		send_message
-			(ref_cast<Game, EditorGameBase>(egbase),
-			 "warehouse",
-			 descr().descname(),
-			 (boost::format(_("A new %s was added to your economy."))
-			  % descr().descname().c_str()).str(),
-			 true);
-		}
+		m_next_military_act = schedule_act(ref_cast<Game, EditorGameBase>(egbase), 1000);
+
+		m_next_stock_remove_act = schedule_act(ref_cast<Game, EditorGameBase>(egbase), 4000);
+
+		log("Message: adding (wh) (%s) %i \n",
+		    to_string(descr().type()).c_str(),
+		    player.player_number());
+		send_message(ref_cast<Game, EditorGameBase>(egbase),
+		             "warehouse",
+		             descr().descname(),
+		             (boost::format(_("A new %s was added to your economy.")) %
+		              descr().descname().c_str()).str(),
+		             true);
+	}
 
 	if (uint32_t const conquer_radius = descr().get_conquers())
-		egbase.conquer_area
-			(PlayerArea<Area<FCoords> >
-			 	(player.player_number(),
-			 	 Area<FCoords>
-			 	 	(egbase.map().get_fcoords(get_position()), conquer_radius)));
+		egbase.conquer_area(PlayerArea<Area<FCoords>>(
+		   player.player_number(),
+		   Area<FCoords>(egbase.map().get_fcoords(get_position()), conquer_radius)));
 
 	if (descr().get_isport())
 		init_portdock(egbase);
@@ -477,14 +432,15 @@
  * Find a contiguous set of water fields close to the port for docking
  * and initialize the @ref PortDock instance.
  */
-void Warehouse::init_portdock(EditorGameBase & egbase)
-{
+void Warehouse::init_portdock(EditorGameBase& egbase) {
 	molog("Setting up port dock fields\n");
 
-	Map & map = egbase.map();
+	Map& map = egbase.map();
 	std::vector<Coords> dock = map.find_portdock(get_position());
 	if (dock.empty()) {
-		log("Attempting to setup port without neighboring water.\n");
+		log("Attempting to setup port without neighboring water (coords: %3dx%3d).\n",
+		    get_position().x,
+		    get_position().y);
 		return;
 	}
 
@@ -502,16 +458,30 @@
 		m_portdock->set_economy(get_economy());
 }
 
-void Warehouse::destroy(EditorGameBase & egbase)
-{
+void Warehouse::destroy(EditorGameBase& egbase) {
 	Building::destroy(egbase);
 }
 
+// if the port still exists and we are in game we first try to restore the portdock
+void Warehouse::restore_portdock_or_destroy(EditorGameBase& egbase) {
+	// re-init the portdock
+	Warehouse::init_portdock(egbase);
+	if (!m_portdock) {
+		log(" Portdock lost, removing the port now (coords: %3dx%3d)\n",
+		    get_position().x,
+		    get_position().y);
+		Building::destroy(egbase);
+	}
+}
+
 /// Destroy the warehouse.
-void Warehouse::cleanup(EditorGameBase & egbase)
-{
+void Warehouse::cleanup(EditorGameBase& egbase) {
+
+	// storing object of the portdock if exists
+	PortDock* pd = nullptr;
+
 	if (egbase.objects().object_still_available(m_portdock)) {
-		m_portdock->remove(egbase);
+		pd = m_portdock;
 		m_portdock = nullptr;
 	}
 
@@ -536,21 +506,32 @@
 
 	Map& map = egbase.map();
 	if (const uint32_t conquer_radius = descr().get_conquers())
-		egbase.unconquer_area
-			(PlayerArea<Area<FCoords> >
-			 	(owner().player_number(),
-			 	 Area<FCoords>(map.get_fcoords(get_position()), conquer_radius)),
-			 m_defeating_player);
+		egbase.unconquer_area(
+		   PlayerArea<Area<FCoords>>(owner().player_number(),
+		                             Area<FCoords>(map.get_fcoords(get_position()), conquer_radius)),
+		   m_defeating_player);
 
 	// Unsee the area that we started seeing in init()
-	Player & player = owner();
-	player.unsee_area
-			(Area<FCoords>(map.get_fcoords(get_position()), descr().vision_range()));
+	Player& player = owner();
+	player.unsee_area(Area<FCoords>(map.get_fcoords(get_position()), descr().vision_range()));
+
+	log("Message: removing %s (player %i)\n",
+	    to_string(descr().type()).c_str(),
+	    player.player_number());
+	send_message(ref_cast<Game, EditorGameBase>(egbase),
+	             "warehouse",
+	             descr().descname(),
+	             (boost::format(_("A %s was destroyed.")) % descr().descname().c_str()).str(),
+	             true);
 
 	Building::cleanup(egbase);
+
+	// if there was a portdock, removing it now
+	if (pd) {
+		pd->remove(egbase);
+	}
 }
 
-
 /// Act regularly to create workers of buildable types without cost. According
 /// to intelligence, this is some highly advanced technology. Not only do the
 /// settlers have no problems with birth control, they do not even need anybody
@@ -558,12 +539,11 @@
 /// what the hell are they doing, killing useless tribesmen! The Borg? Or just
 /// like Soylent Green? Or maybe I should just stop writing comments that late
 /// at night ;-)
-void Warehouse::act(Game & game, uint32_t const data)
-{
+void Warehouse::act(Game& game, uint32_t const data) {
 	uint32_t const gametime = game.get_gametime();
 	{
-		const std::vector<WareIndex> & worker_types_without_cost =
-			owner().tribe().worker_types_without_cost();
+		const std::vector<WareIndex>& worker_types_without_cost =
+		   owner().tribe().worker_types_without_cost();
 		for (size_t i = worker_types_without_cost.size(); i;)
 			if (m_next_worker_without_cost_spawn[--i] <= gametime) {
 				WareIndex const id = worker_types_without_cost.at(i);
@@ -581,8 +561,7 @@
 						remove_workers(id, 1);
 					}
 
-					m_next_worker_without_cost_spawn[i] =
-						schedule_act(game, tdelta);
+					m_next_worker_without_cost_spawn[i] = schedule_act(game, tdelta);
 				} else
 					m_next_worker_without_cost_spawn[i] = never();
 			}
@@ -593,19 +572,15 @@
 		WareIndex const ware = descr().tribe().safe_worker_index("soldier");
 
 		if (m_incorporated_workers.count(ware)) {
-			WorkerList & soldiers = m_incorporated_workers[ware];
+			WorkerList& soldiers = m_incorporated_workers[ware];
 
 			uint32_t total_heal = descr().get_heal_per_second();
 			// Using an explicit iterator, as we plan to erase some
 			// of those guys
-			for
-				(WorkerList::iterator it = soldiers.begin();
-				 it != soldiers.end();
-				 ++it)
-			{
+			for (WorkerList::iterator it = soldiers.begin(); it != soldiers.end(); ++it) {
 				// This is a safe cast: we know only soldiers can land in this
 				// slot in the incorporated array
-				Soldier * soldier = static_cast<Soldier *>(*it);
+				Soldier* soldier = static_cast<Soldier*>(*it);
 
 				//  Soldier dead ...
 				if (!soldier || soldier->get_current_hitpoints() == 0) {
@@ -618,7 +593,6 @@
 					soldier->heal(total_heal);
 					continue;
 				}
-
 			}
 		}
 		m_next_military_act = schedule_act(game, 1000);
@@ -639,11 +613,9 @@
 	Building::act(game, data);
 }
 
-
 /// Transfer our registration to the new economy.
-void Warehouse::set_economy(Economy * const e)
-{
-	Economy * const old = get_economy();
+void Warehouse::set_economy(Economy* const e) {
+	Economy* const old = get_economy();
 
 	if (old == e)
 		return;
@@ -657,7 +629,7 @@
 	Building::set_economy(e);
 
 	for (const PlannedWorkers& pw : m_planned_workers) {
-		for (Request * req : pw.requests) {
+		for (Request* req : pw.requests) {
 			req->set_economy(e);
 		}
 	}
@@ -669,82 +641,62 @@
 		e->add_warehouse(*this);
 }
 
-
-const WareList & Warehouse::get_wares() const
-{
+const WareList& Warehouse::get_wares() const {
 	return m_supply->get_wares();
 }
 
-
-const WareList & Warehouse::get_workers() const
-{
+const WareList& Warehouse::get_workers() const {
 	return m_supply->get_workers();
 }
 
-PlayerImmovable::Workers Warehouse::get_incorporated_workers()
-{
+PlayerImmovable::Workers Warehouse::get_incorporated_workers() {
 	PlayerImmovable::Workers all_workers;
 
 	for (const std::pair<WareIndex, WorkerList>& worker_pair : m_incorporated_workers) {
-		for (Worker * worker : worker_pair.second) {
+		for (Worker* worker : worker_pair.second) {
 			all_workers.push_back(worker);
 		}
 	}
 	return all_workers;
 }
 
-
 /// Magically create wares in this warehouse. Updates the economy accordingly.
-void Warehouse::insert_wares(WareIndex const id, uint32_t const count)
-{
+void Warehouse::insert_wares(WareIndex const id, uint32_t const count) {
 	m_supply->add_wares(id, count);
 }
 
-
 /// Magically destroy wares.
-void Warehouse::remove_wares(WareIndex const id, uint32_t const count)
-{
+void Warehouse::remove_wares(WareIndex const id, uint32_t const count) {
 	m_supply->remove_wares(id, count);
 }
 
-
 /// Magically create workers in this warehouse. Updates the economy accordingly.
-void Warehouse::insert_workers(WareIndex const id, uint32_t const count)
-{
+void Warehouse::insert_workers(WareIndex const id, uint32_t const count) {
 	m_supply->add_workers(id, count);
 }
 
-
 /// Magically destroy workers.
-void Warehouse::remove_workers(WareIndex const id, uint32_t const count)
-{
+void Warehouse::remove_workers(WareIndex const id, uint32_t const count) {
 	m_supply->remove_workers(id, count);
 }
 
-
-
 /// Launch a carrier to fetch an ware from our flag.
-bool Warehouse::fetch_from_flag(Game & game)
-{
+bool Warehouse::fetch_from_flag(Game& game) {
 	WareIndex const carrierid = descr().tribe().safe_worker_index("carrier");
 
-	if (!m_supply->stock_workers(carrierid)) // XXX yep, let's cheat
+	if (!m_supply->stock_workers(carrierid))  // XXX yep, let's cheat
 		insert_workers(carrierid, 1);
 
-	launch_worker(game, carrierid, Requirements()).start_task_fetchfromflag
-		(game);
+	launch_worker(game, carrierid, Requirements()).start_task_fetchfromflag(game);
 
 	return true;
 }
 
-
 /**
  * \return the number of workers that we can launch satisfying the given
  * requirements.
  */
-uint32_t Warehouse::count_workers
-	(const Game & /* game */, WareIndex ware, const Requirements & req)
-{
+uint32_t Warehouse::count_workers(const Game& /* game */, WareIndex ware, const Requirements& req) {
 	uint32_t sum = 0;
 
 	do {
@@ -752,7 +704,7 @@
 
 		// NOTE: This code lies about the TrainingAttributes of non-instantiated workers.
 		if (m_incorporated_workers.count(ware)) {
-			for (Worker * worker : m_incorporated_workers[ware]) {
+			for (Worker* worker : m_incorporated_workers[ware]) {
 				if (!req.check(*worker)) {
 					//  This is one of the workers in our sum.
 					//  But he is too stupid for this job
@@ -769,9 +721,7 @@
 
 /// Start a worker of a given type. The worker will
 /// be assigned a job by the caller.
-Worker & Warehouse::launch_worker
-	(Game & game, WareIndex ware, const Requirements & req)
-{
+Worker& Warehouse::launch_worker(Game& game, WareIndex ware, const Requirements& req) {
 	do {
 		if (m_supply->stock_workers(ware)) {
 			uint32_t unincorporated = m_supply->stock_workers(ware);
@@ -784,15 +734,15 @@
 				remove_no_longer_existing_workers(game, &m_incorporated_workers[ware]);
 				WorkerList& incorporated_workers = m_incorporated_workers[ware];
 
-				for (std::vector<Worker *>::iterator worker_iter = incorporated_workers.begin();
-					 worker_iter != incorporated_workers.end(); ++worker_iter)
-				{
+				for (std::vector<Worker*>::iterator worker_iter = incorporated_workers.begin();
+				     worker_iter != incorporated_workers.end();
+				     ++worker_iter) {
 					Worker* worker = *worker_iter;
 					--unincorporated;
 
 					if (req.check(*worker)) {
-						worker->reset_tasks(game);  //  forget everything you did
-						worker->set_location(this); //  back in a economy
+						worker->reset_tasks(game);   //  forget everything you did
+						worker->set_location(this);  //  back in a economy
 						incorporated_workers.erase(worker_iter);
 
 						m_supply->remove_workers(ware, 1);
@@ -807,7 +757,7 @@
 				// Create a new one
 				// NOTE: This code lies about the TrainingAttributes of the new worker
 				m_supply->remove_workers(ware, 1);
-				const WorkerDescr & workerdescr = *descr().tribe().get_worker_descr(ware);
+				const WorkerDescr& workerdescr = *descr().tribe().get_worker_descr(ware);
 				return workerdescr.create(game, owner(), this, m_position);
 			}
 		}
@@ -820,13 +770,10 @@
 		}
 	} while (ware != INVALID_INDEX);
 
-	throw wexception
-		("Warehouse::launch_worker: worker does not actually exist");
+	throw wexception("Warehouse::launch_worker: worker does not actually exist");
 }
 
-
-void Warehouse::incorporate_worker(EditorGameBase & egbase, Worker* w)
-{
+void Warehouse::incorporate_worker(EditorGameBase& egbase, Worker* w) {
 	assert(w != nullptr);
 	assert(w->get_owner() == &owner());
 
@@ -852,10 +799,10 @@
 
 	// Incorporate the worker
 	if (!m_incorporated_workers.count(worker_index))
-		m_incorporated_workers[worker_index] = std::vector<Worker *>();
+		m_incorporated_workers[worker_index] = std::vector<Worker*>();
 	m_incorporated_workers[worker_index].push_back(w);
 
-	w->set_location(nullptr); //  no longer in an economy
+	w->set_location(nullptr);  //  no longer in an economy
 
 	if (upcast(Game, game, &egbase)) {
 		//  Bind the worker into this house, hide him on the map.
@@ -866,9 +813,9 @@
 
 /// Create an instance of a ware and make sure it gets
 /// carried out of the warehouse.
-WareInstance & Warehouse::launch_ware(Game & game, WareIndex const ware_index) {
+WareInstance& Warehouse::launch_ware(Game& game, WareIndex const ware_index) {
 	// Create the ware
-	WareInstance & ware = *new WareInstance(ware_index, descr().tribe().get_ware_descr(ware_index));
+	WareInstance& ware = *new WareInstance(ware_index, descr().tribe().get_ware_descr(ware_index));
 	ware.init(game);
 	do_launch_ware(game, ware);
 
@@ -877,15 +824,13 @@
 	return ware;
 }
 
-
 /// Get a carrier to actually move this ware out of the warehouse.
-void Warehouse::do_launch_ware(Game & game, WareInstance & ware)
-{
+void Warehouse::do_launch_ware(Game& game, WareInstance& ware) {
 	// Create a carrier
 	WareIndex const carrierid = descr().tribe().worker_index("carrier");
-	const WorkerDescr & workerdescr = *descr().tribe().get_worker_descr(carrierid);
+	const WorkerDescr& workerdescr = *descr().tribe().get_worker_descr(carrierid);
 
-	Worker & worker = workerdescr.create(game, owner(), this, m_position);
+	Worker& worker = workerdescr.create(game, owner(), this, m_position);
 
 	// Yup, this is cheating.
 	if (m_supply->stock_workers(carrierid))
@@ -895,23 +840,15 @@
 	worker.start_task_dropoff(game, ware);
 }
 
-
-void Warehouse::incorporate_ware(EditorGameBase & egbase, WareInstance* ware)
-{
+void Warehouse::incorporate_ware(EditorGameBase& egbase, WareInstance* ware) {
 	m_supply->add_wares(ware->descr_index(), 1);
 	ware->destroy(egbase);
 }
 
-
 /// Called when a transfer for one of the idle Requests completes.
-void Warehouse::request_cb
-	(Game            &       game,
-	 Request         &,
-	 WareIndex        const ware,
-	 Worker          * const w,
-	 PlayerImmovable &       target)
-{
-	Warehouse & wh = ref_cast<Warehouse, PlayerImmovable>(target);
+void Warehouse::request_cb(
+   Game& game, Request&, WareIndex const ware, Worker* const w, PlayerImmovable& target) {
+	Warehouse& wh = ref_cast<Warehouse, PlayerImmovable>(target);
 
 	if (w) {
 		w->schedule_incorporate(game);
@@ -928,38 +865,35 @@
 /**
  * Receive a ware from a transfer that was not associated to a \ref Request.
  */
-void Warehouse::receive_ware(Game & /* game */, WareIndex ware)
-{
+void Warehouse::receive_ware(Game& /* game */, WareIndex ware) {
 	m_supply->add_wares(ware, 1);
 }
 
 /**
  * Receive a worker from a transfer that was not associated to a \ref Request.
  */
-void Warehouse::receive_worker(Game & game, Worker & worker)
-{
+void Warehouse::receive_worker(Game& game, Worker& worker) {
 	worker.schedule_incorporate(game);
 }
 
-Building & WarehouseDescr::create_object() const {
+Building& WarehouseDescr::create_object() const {
 	return *new Warehouse(*this);
 }
 
-
-bool Warehouse::can_create_worker(Game &, WareIndex const worker) const {
+bool Warehouse::can_create_worker(Game&, WareIndex const worker) const {
 	if (!(worker < m_supply->get_workers().get_nrwareids()))
-		throw wexception
-			("worker type %d does not exists (max is %d)",
-			 worker, m_supply->get_workers().get_nrwareids());
+		throw wexception("worker type %d does not exists (max is %d)",
+		                 worker,
+		                 m_supply->get_workers().get_nrwareids());
 
-	const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(worker);
+	const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(worker);
 	assert(&w_desc);
 	if (!w_desc.is_buildable())
 		return false;
 
 	//  see if we have the resources
 	for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
-		const std::string & input_name = buildcost.first;
+		const std::string& input_name = buildcost.first;
 		WareIndex id_w = descr().tribe().ware_index(input_name);
 		if (id_w != INVALID_INDEX) {
 			if (m_supply->stock_wares(id_w) < buildcost.second)
@@ -968,27 +902,26 @@
 			if (m_supply->stock_workers(id_w) < buildcost.second)
 				return false;
 		} else
-			throw wexception
-				("worker type %s needs \"%s\" to be built but that is neither "
-				 "a ware type nor a worker type defined in the tribe %s",
-				 w_desc.descname().c_str(), input_name.c_str(),
-				 descr().tribe().name().c_str());
+			throw wexception("worker type %s needs \"%s\" to be built but that is neither "
+			                 "a ware type nor a worker type defined in the tribe %s",
+			                 w_desc.descname().c_str(),
+			                 input_name.c_str(),
+			                 descr().tribe().name().c_str());
 	}
 	return true;
 }
 
-
-void Warehouse::create_worker(Game & game, WareIndex const worker) {
-	assert(can_create_worker (game, worker));
-
-	const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(worker);
+void Warehouse::create_worker(Game& game, WareIndex const worker) {
+	assert(can_create_worker(game, worker));
+
+	const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(worker);
 
 	for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
-		const std::string & input = buildcost.first;
+		const std::string& input = buildcost.first;
 		WareIndex const id_ware = descr().tribe().ware_index(input);
 		if (id_ware != INVALID_INDEX) {
-			remove_wares  (id_ware,                        buildcost.second);
-			//update statistic accordingly
+			remove_wares(id_ware, buildcost.second);
+			// update statistic accordingly
 			owner().ware_consumed(id_ware, buildcost.second);
 		} else
 			remove_workers(descr().tribe().safe_worker_index(input), buildcost.second);
@@ -1010,8 +943,7 @@
  * Return the number of workers of the given type that we plan to
  * create in this warehouse.
  */
-uint32_t Warehouse::get_planned_workers(Game & /* game */, WareIndex index) const
-{
+uint32_t Warehouse::get_planned_workers(Game& /* game */, WareIndex index) const {
 	for (const PlannedWorkers& pw : m_planned_workers) {
 		if (pw.index == index)
 			return pw.amount;
@@ -1025,23 +957,21 @@
  *
  * This is the current stock plus any incoming transfers.
  */
-std::vector<uint32_t> Warehouse::calc_available_for_worker
-	(Game & /* game */, WareIndex index) const
-{
-	const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(index);
+std::vector<uint32_t> Warehouse::calc_available_for_worker(Game& /* game */,
+                                                           WareIndex index) const {
+	const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(index);
 	std::vector<uint32_t> available;
 
 	for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
-		const std::string & input_name = buildcost.first;
+		const std::string& input_name = buildcost.first;
 		WareIndex id_w = descr().tribe().ware_index(input_name);
 		if (id_w != INVALID_INDEX) {
 			available.push_back(get_wares().stock(id_w));
 		} else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
 			available.push_back(get_workers().stock(id_w));
 		} else
-			throw wexception
-				("Economy::_create_requested_worker: buildcost inconsistency '%s'",
-				 input_name.c_str());
+			throw wexception(
+			   "Economy::_create_requested_worker: buildcost inconsistency '%s'", input_name.c_str());
 	}
 
 	for (const PlannedWorkers& pw : m_planned_workers) {
@@ -1057,14 +987,12 @@
 	return available;
 }
 
-
 /**
  * Set the amount of workers we plan to create
  * of the given \p index to \p amount.
  */
-void Warehouse::plan_workers(Game & game, WareIndex index, uint32_t amount)
-{
-	PlannedWorkers * pw = nullptr;
+void Warehouse::plan_workers(Game& game, WareIndex index, uint32_t amount) {
+	PlannedWorkers* pw = nullptr;
 
 	for (PlannedWorkers& planned_worker : m_planned_workers) {
 		if (planned_worker.index == index) {
@@ -1082,22 +1010,17 @@
 		pw->index = index;
 		pw->amount = 0;
 
-		const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(pw->index);
+		const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(pw->index);
 		for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
-			const std::string & input_name = buildcost.first;
+			const std::string& input_name = buildcost.first;
 
 			WareIndex id_w = descr().tribe().ware_index(input_name);
 			if (id_w != INVALID_INDEX) {
-				pw->requests.push_back
-					(new Request
-					 (*this, id_w, &Warehouse::request_cb, wwWARE));
+				pw->requests.push_back(new Request(*this, id_w, &Warehouse::request_cb, wwWARE));
 			} else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
-				pw->requests.push_back
-					(new Request
-					 (*this, id_w, &Warehouse::request_cb, wwWORKER));
+				pw->requests.push_back(new Request(*this, id_w, &Warehouse::request_cb, wwWORKER));
 			} else
-				throw wexception
-					("plan_workers: bad buildcost '%s'", input_name.c_str());
+				throw wexception("plan_workers: bad buildcost '%s'", input_name.c_str());
 		}
 	}
 
@@ -1109,10 +1032,8 @@
  * See if we can create the workers of the given plan,
  * and update requests accordingly.
  */
-void Warehouse::_update_planned_workers
-	(Game & game, Warehouse::PlannedWorkers & pw)
-{
-	const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(pw.index);
+void Warehouse::_update_planned_workers(Game& game, Warehouse::PlannedWorkers& pw) {
+	const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(pw.index);
 
 	while (pw.amount && can_create_worker(game, pw.index)) {
 		create_worker(game, pw.index);
@@ -1121,7 +1042,7 @@
 	uint32_t idx = 0;
 	for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
 
-		const std::string & input_name = buildcost.first;
+		const std::string& input_name = buildcost.first;
 		uint32_t supply;
 
 		WareIndex id_w = descr().tribe().ware_index(input_name);
@@ -1130,14 +1051,12 @@
 		} else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
 			supply = m_supply->stock_workers(id_w);
 		} else
-			throw wexception
-				("_update_planned_workers: bad buildcost '%s'", input_name.c_str());
+			throw wexception("_update_planned_workers: bad buildcost '%s'", input_name.c_str());
 
 		if (supply >= pw.amount * buildcost.second)
 			pw.requests[idx]->set_count(0);
 		else
-			pw.requests[idx]->set_count
-				(pw.amount * buildcost.second - supply);
+			pw.requests[idx]->set_count(pw.amount * buildcost.second - supply);
 		++idx;
 	}
 
@@ -1153,8 +1072,7 @@
  * Needs to be called periodically, because some necessary supplies might arrive
  * due to idle transfers instead of by explicit request.
  */
-void Warehouse::_update_all_planned_workers(Game & game)
-{
+void Warehouse::_update_all_planned_workers(Game& game) {
 	uint32_t idx = 0;
 	while (idx < m_planned_workers.size()) {
 		_update_planned_workers(game, m_planned_workers[idx]);
@@ -1168,51 +1086,35 @@
 	}
 }
 
-void Warehouse::enable_spawn
-	(Game & game, uint8_t const worker_types_without_cost_index)
-{
-	assert
-		(m_next_worker_without_cost_spawn[worker_types_without_cost_index]
-		 ==
-		 static_cast<uint32_t>(never()));
+void Warehouse::enable_spawn(Game& game, uint8_t const worker_types_without_cost_index) {
+	assert(m_next_worker_without_cost_spawn[worker_types_without_cost_index] ==
+	       static_cast<uint32_t>(never()));
 	m_next_worker_without_cost_spawn[worker_types_without_cost_index] =
-		schedule_act(game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
+	   schedule_act(game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
 }
-void Warehouse::disable_spawn(uint8_t const worker_types_without_cost_index)
-{
-	assert
-		(m_next_worker_without_cost_spawn[worker_types_without_cost_index]
-		 !=
-		 static_cast<uint32_t>(never()));
+void Warehouse::disable_spawn(uint8_t const worker_types_without_cost_index) {
+	assert(m_next_worker_without_cost_spawn[worker_types_without_cost_index] !=
+	       static_cast<uint32_t>(never()));
 	m_next_worker_without_cost_spawn[worker_types_without_cost_index] = never();
 }
 
-
-bool Warehouse::can_attack()
-{
+bool Warehouse::can_attack() {
 	return descr().get_conquers() > 0;
 }
 
-void Warehouse::aggressor(Soldier & enemy)
-{
+void Warehouse::aggressor(Soldier& enemy) {
 	if (!descr().get_conquers())
 		return;
 
-	Game & game = ref_cast<Game, EditorGameBase>(owner().egbase());
-	Map  & map  = game.map();
-	if
-		(enemy.get_owner() == &owner() ||
-		 enemy.get_battle() ||
-		 descr().get_conquers()
-		 <=
-		 map.calc_distance(enemy.get_position(), get_position()))
+	Game& game = ref_cast<Game, EditorGameBase>(owner().egbase());
+	Map& map = game.map();
+	if (enemy.get_owner() == &owner() || enemy.get_battle() ||
+	    descr().get_conquers() <= map.calc_distance(enemy.get_position(), get_position()))
 		return;
 
-	if
-		(game.map().find_bobs
-		 	(Area<FCoords>(map.get_fcoords(base_flag().get_position()), 2),
-		 	 nullptr,
-		 	 FindBobEnemySoldier(&owner())))
+	if (game.map().find_bobs(Area<FCoords>(map.get_fcoords(base_flag().get_position()), 2),
+	                         nullptr,
+	                         FindBobEnemySoldier(&owner())))
 		return;
 
 	WareIndex const soldier_index = descr().tribe().worker_index("soldier");
@@ -1221,20 +1123,17 @@
 	if (!count_workers(game, soldier_index, noreq))
 		return;
 
-	Soldier & defender =
-		ref_cast<Soldier, Worker>(launch_worker(game, soldier_index, noreq));
+	Soldier& defender = ref_cast<Soldier, Worker>(launch_worker(game, soldier_index, noreq));
 	defender.start_task_defense(game, false);
 }
 
-bool Warehouse::attack(Soldier & enemy)
-{
-	Game & game = ref_cast<Game, EditorGameBase>(owner().egbase());
+bool Warehouse::attack(Soldier& enemy) {
+	Game& game = ref_cast<Game, EditorGameBase>(owner().egbase());
 	WareIndex const soldier_index = descr().tribe().worker_index("soldier");
 	Requirements noreq;
 
 	if (count_workers(game, soldier_index, noreq)) {
-		Soldier & defender =
-			ref_cast<Soldier, Worker>(launch_worker(game, soldier_index, noreq));
+		Soldier& defender = ref_cast<Soldier, Worker>(launch_worker(game, soldier_index, noreq));
 		defender.start_task_defense(game, true);
 		enemy.send_signal(game, "sleep");
 		return true;
@@ -1245,45 +1144,36 @@
 	return false;
 }
 
-void Warehouse::PlannedWorkers::cleanup()
-{
+void Warehouse::PlannedWorkers::cleanup() {
 	while (!requests.empty()) {
 		delete requests.back();
 		requests.pop_back();
 	}
 }
 
-Warehouse::StockPolicy Warehouse::get_ware_policy(WareIndex ware) const
-{
+Warehouse::StockPolicy Warehouse::get_ware_policy(WareIndex ware) const {
 	assert(ware < m_ware_policy.size());
 	return m_ware_policy[ware];
 }
 
-Warehouse::StockPolicy Warehouse::get_worker_policy(WareIndex ware) const
-{
+Warehouse::StockPolicy Warehouse::get_worker_policy(WareIndex ware) const {
 	assert(ware < m_worker_policy.size());
 	return m_worker_policy[ware];
 }
 
-Warehouse::StockPolicy Warehouse::get_stock_policy
-	(WareWorker waretype, WareIndex wareindex) const
-{
+Warehouse::StockPolicy Warehouse::get_stock_policy(WareWorker waretype, WareIndex wareindex) const {
 	if (waretype == wwWORKER)
 		return get_worker_policy(wareindex);
 	else
 		return get_ware_policy(wareindex);
 }
 
-
-void Warehouse::set_ware_policy(WareIndex ware, Warehouse::StockPolicy policy)
-{
+void Warehouse::set_ware_policy(WareIndex ware, Warehouse::StockPolicy policy) {
 	assert(ware < m_ware_policy.size());
 	m_ware_policy[ware] = policy;
 }
 
-void Warehouse::set_worker_policy
-	(WareIndex ware, Warehouse::StockPolicy policy)
-{
+void Warehouse::set_worker_policy(WareIndex ware, Warehouse::StockPolicy policy) {
 	assert(ware < m_worker_policy.size());
 	m_worker_policy[ware] = policy;
 }
@@ -1292,8 +1182,7 @@
  * Check if there are remaining wares with stock policy \ref SP_Remove,
  * and remove one of them if appropriate.
  */
-void Warehouse::check_remove_stock(Game & game)
-{
+void Warehouse::check_remove_stock(Game& game) {
 	if (base_flag().current_wares() < base_flag().total_capacity() / 2) {
 		for (WareIndex ware = 0; ware < m_ware_policy.size(); ++ware) {
 			if (get_ware_policy(ware) != SP_Remove || !get_wares().stock(ware))
@@ -1308,7 +1197,7 @@
 		if (get_worker_policy(widx) != SP_Remove || !get_workers().stock(widx))
 			continue;
 
-		Worker & worker = launch_worker(game, widx, Requirements());
+		Worker& worker = launch_worker(game, widx, Requirements());
 		worker.start_task_leavebuilding(game, true);
 		break;
 	}
@@ -1324,36 +1213,34 @@
 /*
  * SoldierControl implementations
  */
-std::vector<Soldier *> Warehouse::present_soldiers() const
-{
-	std::vector<Soldier *> rv;
+std::vector<Soldier*> Warehouse::present_soldiers() const {
+	std::vector<Soldier*> rv;
 
 	WareIndex const ware = descr().tribe().safe_worker_index("soldier");
 	IncorporatedWorkers::const_iterator sidx = m_incorporated_workers.find(ware);
 
 	if (sidx != m_incorporated_workers.end()) {
-		const WorkerList & soldiers = sidx->second;
+		const WorkerList& soldiers = sidx->second;
 
-		for (Worker * temp_soldier: soldiers) {
-			rv.push_back(static_cast<Soldier *>(temp_soldier));
+		for (Worker* temp_soldier : soldiers) {
+			rv.push_back(static_cast<Soldier*>(temp_soldier));
 		}
 	}
 
 	return rv;
 }
-int Warehouse::incorporate_soldier(EditorGameBase & egbase, Soldier & soldier) {
+int Warehouse::incorporate_soldier(EditorGameBase& egbase, Soldier& soldier) {
 	incorporate_worker(egbase, &soldier);
 	return 0;
 }
 
-int Warehouse::outcorporate_soldier(EditorGameBase & /* egbase */, Soldier & soldier) {
+int Warehouse::outcorporate_soldier(EditorGameBase& /* egbase */, Soldier& soldier) {
 
 	WareIndex const ware = descr().tribe().safe_worker_index("soldier");
 	if (m_incorporated_workers.count(ware)) {
-		WorkerList & soldiers = m_incorporated_workers[ware];
+		WorkerList& soldiers = m_incorporated_workers[ware];
 
-		WorkerList::iterator i = std::find
-			(soldiers.begin(), soldiers.end(), &soldier);
+		WorkerList::iterator i = std::find(soldiers.begin(), soldiers.end(), &soldier);
 
 		soldiers.erase(i);
 		m_supply->remove_workers(ware, 1);
@@ -1366,13 +1253,10 @@
 	return 0;
 }
 
-void Warehouse::log_general_info(const EditorGameBase & egbase)
-{
+void Warehouse::log_general_info(const EditorGameBase& egbase) {
 	Building::log_general_info(egbase);
 
 	if (descr().get_isport())
 		molog("Port dock: %u\n", m_portdock ? m_portdock->serial() : 0);
 }
-
-
 }

=== modified file 'src/logic/warehouse.h'
--- src/logic/warehouse.h	2014-09-19 12:54:54 +0000
+++ src/logic/warehouse.h	2014-11-19 21:19:43 +0000
@@ -136,6 +136,8 @@
 
 	void destroy(EditorGameBase &) override;
 
+	void restore_portdock_or_destroy(EditorGameBase &);
+
 	void act(Game & game, uint32_t data) override;
 
 	void set_economy(Economy *) override;

=== modified file 'src/main.cc'
--- src/main.cc	2014-09-18 18:46:22 +0000
+++ src/main.cc	2014-11-19 21:19:43 +0000
@@ -1,3 +1,40 @@
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
 /*
  * Copyright (C) 2002-2004, 2008-2009 by the Widelands Development Team
  *

=== modified file 'src/notifications/note_ids.h'
--- src/notifications/note_ids.h	2014-09-10 19:54:01 +0000
+++ src/notifications/note_ids.h	2014-11-19 21:19:43 +0000
@@ -32,6 +32,7 @@
 	FieldPossession,
 	FieldTransformed,
 	ProductionSiteOutOfResources,
+	ShipMessage,
 };
 
 #endif  // end of include guard: WL_NOTIFICATIONS_NOTE_IDS_H


Follow ups