← Back to team overview

widelands-dev team mailing list archive

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

 

I added a comment to one of your comments :)

Diff comments:

> === 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-12-03 11:32:28 +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,9 @@
>  	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 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 +262,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 +313,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 +332,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 +376,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-30 18:53:22 +0000
> +++ src/ai/defaultai.cc	2014-12-03 11:32:28 +0000
> @@ -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;
>  		   }
> @@ -143,6 +159,39 @@
>  		   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()) {
> +			   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() {
> @@ -238,6 +287,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 +306,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 +318,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 +384,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 +430,13 @@
>  			} else {
>  				bo.is_fisher_ = false;
>  			}
> +
> +			if (building_name == "shipyard") {
> +				bo.is_shipyard_ = true;
> +			} else {
> +				bo.is_shipyard_ = false;
> +			}
> +
>  			continue;
>  		}
>  
> @@ -394,6 +469,11 @@
>  
>  		if (bld.type() == MapObjectType::TRAININGSITE) {
>  			bo.type = BuildingObserver::TRAININGSITE;
> +			const TrainingSiteDescr& train =
> +			   dynamic_cast<const TrainingSiteDescr&>(bld);
> +			for (const WareAmount& temp_input : train.inputs()) {
> +				bo.inputs_.push_back(temp_input.first);
> +			}
>  			continue;
>  		}
>  
> @@ -593,6 +673,37 @@
>  		}
>  	}
>  
> +	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 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 (const WarehouseSiteObserver& wh_obs : warehousesites) {
> +		const uint16_t actual_distance =
> +		   map.calc_distance(field.coords, wh_obs.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
> @@ -704,7 +815,6 @@
>  			field.stones_nearby_ = 0;
>  
>  			for (uint32_t j = 0; j < immovables.size(); ++j) {
> -				// const BaseImmovable & base_immovable = *immovables.at(i).object;
>  				if (immovables.at(j).object->has_attribute(stone_attr)) {
>  					++field.stones_nearby_;
>  				}
> @@ -906,14 +1016,14 @@
>  // - there is an enemy
>  //   Currently more military buildings are built then needed
>  //   and "optimalization" (dismantling not needed buildings) is done afterwards
> -bool DefaultAI::construct_building(int32_t gametime) {  // (int32_t gametime)
> +bool DefaultAI::construct_building(int32_t gametime) {
>  	//  Just used for easy checking whether a mine or something else was built.
>  	bool mine = false;
>  	bool field_blocked = false;
>  	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 +1129,8 @@
>  		}
>  
>  	// testing big military buildings, whether critical construction
> -	// material is (not) needed
> +	// material is available (at least 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 +1148,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 +1170,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 +1209,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 +1513,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 +1556,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 +1678,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 +1700,51 @@
>  				       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 (const WarehouseSiteObserver& wh_obs : warehousesites) {
> +					const uint16_t actual_distance =
> +					   map.calc_distance(bf->coords, wh_obs.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 +1755,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 +1778,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 +1932,6 @@
>  			block_time = 25 * 1000;
>  			block_area = 6;
>  		}
> -		Map& map = game().map();
>  
>  		MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(proposed_coords), block_area));
>  		do {
> @@ -1968,7 +2137,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());
> +			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 building
> +		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 +2215,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
> @@ -2119,7 +2320,7 @@
>  		int32_t const hash_walk =
>  		   nf_walk_it->flag->get_position().x << 16 | nf_walk_it->flag->get_position().y;
>  		if (lookuptable.count(hash_walk) > 0) {
> -			// iterting over nearflags
> +			// iterating over nearflags
>  			for (std::vector<NearFlag>::iterator nf_it = nearflags.begin(); nf_it != nearflags.end();
>  			     ++nf_it) {
>  				int32_t const hash =
> @@ -2488,7 +2689,7 @@
>  	}
>  
>  	// remaining buildings without inputs and not supporting ones (fishers only left probably and
> -	// huters)
> +	// hunters)
>  
>  	if (site.bo->inputs_.empty() && site.bo->production_hint_ < 0 &&
>  	    site.site->can_start_working() && !site.bo->space_consumer_ &&
> @@ -2536,6 +2737,222 @@
>  	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(uint32_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 territories_count = 1;
> +	bool idle_shipyard_stocked = false;
> +
> +	// goes over all warehouses (these includes ports)
> +	for (const WarehouseSiteObserver& wh_obs : warehousesites) {
> +		if (wh_obs.bo->is_port_) {
> +			ports_count += 1;
> +			if (Widelands::PortDock* pd = wh_obs.site->get_portdock()) {
> +				if (pd->expedition_started()) {
> +					expeditions_in_prep += 1;
> +				}
> +			} else {
> +				log("  there is a port without portdock at %3dx%3d?\n",
> +				    wh_obs.site->get_position().x,
> +				    wh_obs.site->get_position().y);
> +			}
> +		}
> +	}
> +
> +	// goes over productionsites and gets status of shipyards
> +	for (const ProductionSiteObserver& ps_obs : productionsites) {
> +		if (ps_obs.bo->is_shipyard_) {
> +			shipyards_count += 1;
> +			if (!ps_obs.site->is_stopped()) {
> +				working_shipyards_count += 1;
> +			}
> +			// counting stocks
> +			uint8_t stocked_wares = 0;
> +			std::vector<WaresQueue*> const warequeues = ps_obs.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_obs.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;
> +		}
> +	}
> +	territories_count += remote_ports_coords.size();
> +
> +	enum {NEEDSHIP = 0, ENOUGHSHIPS = 1, DONOTHING = 2 };

It will work without class, but if you use a class, there is less danger of naming conflicts with other enums that might have the same elements. We are planning to move to enum classes in general.

> +
> +	// 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>((territories_count - 1) * 0.6 + ports_count * 0.75)) {
> +		enough_ships = ENOUGHSHIPS;
> +	} else if (static_cast<float>(allships.size()) <
> +	           static_cast<float>((territories_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 (const ProductionSiteObserver& ps_obs : productionsites) {
> +			if (ps_obs.bo->is_shipyard_ && ps_obs.site->can_start_working() &&
> +			    ps_obs.site->is_stopped()) {
> +				// make sure it is fully stocked
> +				// counting stocks
> +				uint8_t stocked_wares = 0;
> +				std::vector<WaresQueue*> const warequeues = ps_obs.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_obs.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 (const WarehouseSiteObserver& wh_obs : warehousesites) {
> +
> +			if (wh_obs.bo->is_port_) {
> +				game().send_player_start_or_cancel_expedition(*wh_obs.site);
> +				return true;
> +			}
> +		}
> +	}
> +	return true;
> +}
> +
> +// This identifies ships that are waiting for command
> +bool DefaultAI::check_ships(uint32_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.
> @@ -2640,7 +3057,7 @@
>                                       int16_t* max_preciousness,
>                                       int16_t* max_needed_preciousness) {
>  
> -	// reseting values
> +	// resetting values
>  	*output_is_needed = false;
>  	*max_preciousness = 0;
>  	*max_needed_preciousness = 0;
> @@ -2709,6 +3126,50 @@
>  	return count;
>  }
>  
> +// counts produced output in warehouses (only)
> +// perhaps it will be able to replace get_stocklevel
> +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,13 +3463,210 @@
>  		}
>  }
>  
> +// 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(TiborB): 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.empty()) {
> +			// 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());
>  
>  	if (bo.type == BuildingObserver::CONSTRUCTIONSITE) {
>  		BuildingObserver& target_bo =
> -		   get_building_observer(dynamic_cast<ConstructionSite&>(b).building().name().c_str());
> +		   get_building_observer(dynamic_cast<const ConstructionSite&>(b).building().name().c_str());
>  		++target_bo.cnt_under_construction_;
>  		++num_constructionsites_;
>  		if (target_bo.type == BuildingObserver::PRODUCTIONSITE) {
> @@ -3031,6 +3689,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 +3717,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 = &dynamic_cast<TrainingSite&>(b);
> +			trainingsites.back().bo = &bo;
> +
>  		} else if (bo.type == BuildingObserver::WAREHOUSE) {
>  			++numof_warehouses_;
> +			warehousesites.push_back(WarehouseSiteObserver());
> +			warehousesites.back().site = &dynamic_cast<Warehouse&>(b);
> +			warehousesites.back().bo = &bo;
> +			if (bo.is_port_) {
> +				++num_ports;
> +			}
>  		}
>  	}
>  }
> @@ -3123,9 +3796,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;
> +				}
> +			}
>  		}
>  	}
>  
> @@ -3134,7 +3829,7 @@
>  }
>  
>  // Checks that supply line exists for given building.
> -// Recurcsively verify that all inputs_ have a producer.
> +// Recursively verify that all inputs_ have a producer.
>  // TODO(unknown): this function leads to periodic freezes of ~1 second on big games on my system.
>  // TODO(unknown): It needs profiling and optimization.
>  // NOTE: This is not needed anymore and it seems it is not missed neither
> @@ -3165,7 +3860,7 @@
>  
>  bool DefaultAI::consider_attack(int32_t const gametime) {
>  
> -	// we presume that we are not attacking so we extend waitperiod
> +	// we assume that we are not attacking so we extend waitperiod
>  	// in case of attack the variable will be decreased below
>  	// this is intended to save some CPU and add randomness in attacking
>  	// and also differentiate according to type
> @@ -3288,7 +3983,7 @@
>  
>  	for (uint32_t position = gametime % test_every; position < militarysites.size();
>  	     position += test_every) {
> -		// checked_own_ms_tmp += 1;
> +
>  		std::list<MilitarySiteObserver>::iterator mso = militarysites.begin();
>  		std::advance(mso, position);
>  
> @@ -3334,7 +4029,6 @@
>  						continue;
>  					}
>  
> -					// target_buildings.push_back(immovables.at(j));
>  					const int32_t soldiers_difference =
>  					   player_->find_attack_soldiers(bld->base_flag()) - bld->present_soldiers().size();
>  
> @@ -3379,7 +4073,7 @@
>  		}
>  	}
>  
> -	// we allways try to attack warehouse first
> +	// we always try to attack warehouse first
>  	if (best_wh_target != nullptr && gametime % 2 == 0) {
>  		// attacking with all attack-ready soldiers
>  		int32_t attackers = player_->find_attack_soldiers(best_wh_target->base_flag());
> @@ -3413,6 +4107,34 @@
>  	}
>  }
>  
> +// 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 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-12-03 11:32:28 +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(uint32_t);
> +	bool check_ships(uint32_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,7 @@
>  	void lose_immovable(const Widelands::PlayerImmovable&);
>  	void gain_building(Widelands::Building&);
>  	void lose_building(const Widelands::Building&);
> +	void expedition_management(ShipObserver&);
>  	void out_of_resources_site(const Widelands::ProductionSite&);
>  
>  	bool check_supply(const BuildingObserver&);
> @@ -181,10 +203,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 +219,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 +232,12 @@
>  	int32_t next_productionsite_check_due_;
>  	int32_t next_mine_check_due_;
>  	int32_t next_militarysite_check_due_;
> +	uint32_t next_ship_check_due;
> +	uint32_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 +264,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-11-28 16:40:55 +0000
> +++ src/economy/portdock.cc	2014-12-03 11:32:28 +0000
> @@ -21,6 +21,8 @@
>  
>  #include <memory>
>  
> +#include <boost/format.hpp>
> +
>  #include "base/log.h"
>  #include "base/macros.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-11-30 18:49:38 +0000
> +++ src/logic/ship.cc	2014-12-03 11:32:28 +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(dynamic_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-12-03 11:32:28 +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-11-30 18:49:38 +0000
> +++ src/logic/warehouse.cc	2014-12-03 11:32:28 +0000
> @@ -50,7 +50,7 @@
>  
>  namespace Widelands {
>  
> -namespace  {
> +namespace {
>  
>  static const uint32_t WORKER_WITHOUT_COST_SPAWN_INTERVAL = 2500;
>  
> @@ -68,19 +68,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();
>  }
>  
> @@ -96,10 +94,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;
>  
> @@ -126,87 +122,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.
> @@ -216,18 +199,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()))
> @@ -237,29 +218,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");
> @@ -271,25 +249,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;
>  }
> @@ -298,22 +272,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);
> @@ -325,13 +296,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;
> @@ -344,19 +312,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();
>  	}
> @@ -364,31 +329,32 @@
>  	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()))
>  		{
> -			upcast(Game, game, &egbase);
>  			if (next_spawn == static_cast<uint32_t>(never())) {
>  				next_spawn = schedule_act(dynamic_cast<Game&>(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);
>  		}
>  	}
>  
> @@ -406,13 +372,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);
> @@ -421,17 +386,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))) {
> @@ -457,11 +420,9 @@
>  		}
>  
>  	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);
> @@ -471,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;
>  	}
>  
> @@ -496,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;
>  	}
>  
> @@ -530,21 +506,34 @@
>  
>  	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()));
> +
> +	if (upcast(Game, game, &egbase)) {
> +		log("Message: removing %s (player %i)\n",
> +		    to_string(descr().type()).c_str(),
> +		    player.player_number());
> +		send_message(*game,
> +		             "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
> @@ -552,12 +541,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);
> @@ -575,8 +563,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();
>  			}
> @@ -587,19 +574,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) {
> @@ -612,7 +595,6 @@
>  					soldier->heal(total_heal);
>  					continue;
>  				}
> -
>  			}
>  		}
>  		m_next_military_act = schedule_act(game, 1000);
> @@ -633,11 +615,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;
> @@ -651,7 +631,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);
>  		}
>  	}
> @@ -663,82 +643,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 {
> @@ -746,7 +706,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
> @@ -763,9 +723,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);
> @@ -778,15 +736,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);
> @@ -801,7 +759,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);
>  			}
>  		}
> @@ -814,13 +772,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());
>  
> @@ -846,10 +801,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.
> @@ -860,9 +815,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);
>  
> @@ -871,15 +826,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))
> @@ -889,14 +842,11 @@
>  	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,
> @@ -922,38 +872,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)
> @@ -962,27 +909,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);
> @@ -1004,8 +950,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;
> @@ -1019,23 +964,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) {
> @@ -1051,14 +994,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) {
> @@ -1076,22 +1017,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());
>  		}
>  	}
>  
> @@ -1103,10 +1039,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);
> @@ -1115,7 +1049,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);
> @@ -1124,14 +1058,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;
>  	}
>  
> @@ -1147,8 +1079,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]);
> @@ -1162,33 +1093,23 @@
>  	}
>  }
>  
> -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;
>  
> @@ -1202,11 +1123,9 @@
>  		 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");
> @@ -1237,45 +1156,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;
>  }
> @@ -1284,8 +1194,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))
> @@ -1300,7 +1209,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;
>  	}
> @@ -1316,36 +1225,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);
> @@ -1358,13 +1265,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-12-03 11:32:28 +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/notifications/note_ids.h'
> --- src/notifications/note_ids.h	2014-11-23 14:34:38 +0000
> +++ src/notifications/note_ids.h	2014-12-03 11:32:28 +0000
> @@ -32,8 +32,9 @@
>  	FieldPossession,
>  	FieldTransformed,
>  	ProductionSiteOutOfResources,
> -
> +	ShipMessage,
>  	GraphicResolutionChanged,
> +
>  };
>  
>  #endif  // end of include guard: WL_NOTIFICATIONS_NOTE_IDS_H
> 


-- 
https://code.launchpad.net/~widelands-dev/widelands/seafaring-ai/+merge/242271
Your team Widelands Developers is subscribed to branch lp:~widelands-dev/widelands/seafaring-ai.


References