widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #03085
[Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
TiborB has proposed merging lp:~widelands-dev/widelands/seafaring-ai into lp:widelands.
Requested reviews:
Widelands Developers (widelands-dev)
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/seafaring-ai/+merge/242271
Hi, after some time this is ready for review, read the branch info for more info.
Tested a lot as AI-only games, I would welcome a human players tests and feedback.
--
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/seafaring-ai into lp:widelands.
=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h 2014-10-30 20:24:57 +0000
+++ src/ai/ai_help_structs.h 2014-11-19 21:19:43 +0000
@@ -32,6 +32,8 @@
#include "logic/player.h"
#include "logic/world/terrain_description.h"
#include "logic/world/world.h"
+#include "logic/ship.h"
+#include <unordered_set>
namespace Widelands {
@@ -227,10 +229,10 @@
int16_t military_stationed_;
// stationed (manned) military buildings nearby
int16_t military_unstationed_;
- // some buildings must be postponed bit
- int32_t prohibited_till_;
- // and then some must be forced
- int32_t forced_after_;
+ bool is_portspace_;
+ // bool portspace_nearby_; // to prohibit buildings near a portspace Not needed?
+ bool port_nearby_; // to increase priority if a port is nearby,
+ // especially for new colonies
std::vector<uint8_t> consumers_nearby_;
std::vector<uint8_t> producers_nearby_;
@@ -261,7 +263,9 @@
military_loneliness_(1000),
military_in_constr_nearby_(0),
military_presence_(0),
- military_stationed_(0) {
+ military_stationed_(0),
+ is_portspace_(false),
+ port_nearby_(false) {
}
};
@@ -310,12 +314,14 @@
bool plants_trees_;
bool recruitment_; // is "producing" workers?
bool is_buildable_;
- bool need_trees_; // lumberjack = true
- bool need_stones_; // quarry = true
- bool mines_water_; // wells
- bool need_water_; // fisher, fish_breeder = true
- bool is_hunter_; // need to identify hunters
- bool is_fisher_; // need to identify fishers
+ bool need_trees_; // lumberjack = true
+ bool need_stones_; // quarry = true
+ bool mines_water_; // wells
+ bool need_water_; // fisher, fish_breeder = true
+ bool is_hunter_; // need to identify hunters
+ bool is_fisher_; // need to identify fishers
+ bool is_port_;
+ bool is_shipyard_;
bool space_consumer_; // farm, vineyard... = true
bool expansion_type_; // military building used that can be used to control area
bool fighting_type_; // military building built near enemies
@@ -327,7 +333,6 @@
int32_t mines_; // type of resource it mines_
uint16_t mines_percent_; // % of res it can mine
-
uint32_t current_stats_;
std::vector<int16_t> inputs_;
@@ -372,6 +377,25 @@
bool enemies_nearby_;
};
+struct TrainingSiteObserver {
+ Widelands::TrainingSite* site;
+ BuildingObserver* bo;
+};
+
+struct WarehouseSiteObserver {
+ Widelands::Warehouse* site;
+ BuildingObserver* bo;
+};
+
+struct ShipObserver {
+ Widelands::Ship* ship;
+ Widelands::Coords expedition_start_point_;
+ std::unordered_set<uint32_t> visited_spots_;
+ bool island_circ_direction = true; // a ship circumvents all island in the same direction
+ bool waiting_for_command_ = false;
+ int32_t last_command_time = 0;
+};
+
struct WareObserver {
uint8_t producers_;
uint8_t consumers_;
=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc 2014-11-03 06:45:32 +0000
+++ src/ai/defaultai.cc 2014-11-19 21:19:43 +0000
@@ -6,7 +6,7 @@
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
+ * This program is distributed in the hope that it will be useful,n
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
@@ -31,7 +31,9 @@
#include "base/macros.h"
#include "economy/economy.h"
#include "economy/flag.h"
+#include "economy/portdock.h"
#include "economy/road.h"
+#include "economy/wares_queue.h"
#include "logic/constructionsite.h"
#include "logic/findbob.h"
#include "logic/findimmovable.h"
@@ -39,15 +41,19 @@
#include "logic/map.h"
#include "logic/militarysite.h"
#include "logic/player.h"
+#include "logic/playercommand.h"
#include "logic/productionsite.h"
+#include "logic/ship.h"
#include "logic/trainingsite.h"
#include "logic/tribe.h"
#include "logic/warehouse.h"
#include "logic/world/world.h"
#include "profile/profile.h"
+
// Building of new military buildings can be restricted
constexpr int kPushExpansion = 1;
+
constexpr int kResourcesOrDefense = 2;
constexpr int kDefenseOnly = 3;
constexpr int kNoNewMilitary = 4;
@@ -59,6 +65,10 @@
// building of the same building can be started after 25s at earliest
constexpr int kBuildingMinInterval = 25 * 1000;
constexpr int kMinBFCheckInterval = 5 * 1000;
+constexpr int kShipCheckInterval = 5 * 1000;
+constexpr int kMarineDecisionInterval = 20 * 1000;
+constexpr int kTrainingSitesCheckInterval = 30 * 1000;
+
// Some buildings have to be built close to borders and their
// priority might be decreased below 0, so this is to
// compensate
@@ -81,6 +91,7 @@
num_constructionsites_(0),
num_milit_constructionsites(0),
num_prod_constructionsites(0),
+ num_ports(0),
next_road_due_(2000),
next_stats_update_due_(30000),
next_construction_due_(1000),
@@ -88,9 +99,12 @@
next_productionsite_check_due_(0),
next_mine_check_due_(0),
next_militarysite_check_due_(0),
+ next_ship_check_due(5 * 60 * 1000),
+ next_marine_decisions_due(5 * 60 * 1000),
next_attack_consideration_due_(300000),
- next_helpersites_check_due_(180000),
+ next_trainingsites_check_due_(15 * 60 * 1000),
next_bf_check_due_(1000),
+ next_wares_review_due_(5 * 60 * 1000), // review
inhibit_road_building_(0),
time_of_last_construction_(0),
enemy_last_seen_(-2 * 60 * 1000),
@@ -103,15 +117,17 @@
resource_necessity_water_needed_(false),
unstationed_milit_buildings_(0),
military_last_dismantle_(0),
- military_last_build_(-60 * 1000),
- last_attack_target_(
+ military_last_build_(-60 * 1000),
+ last_attack_target_(
std::numeric_limits<uint16_t>::max(), std::numeric_limits<uint16_t>::max()),
next_attack_waittime_(10),
+ seafaring_economy(false),
+ colony_scan_area_(35),
spots_(0) {
// Subscribe to NoteFieldPossession.
field_possession_subscriber_ =
- Notifications::subscribe<NoteFieldPossession>([this](const NoteFieldPossession& note) {
+ Notifications::subscribe<NoteFieldPossession>([this](const NoteFieldPossession& note) {
if (note.player != player_) {
return;
}
@@ -137,12 +153,47 @@
outofresource_subscriber_ = Notifications::subscribe<NoteProductionSiteOutOfResources>(
[this](const NoteProductionSiteOutOfResources& note) {
if (note.ps->owner().player_number() != player_->player_number()) {
+ // if (note.ps->owner().player_number() != pid) {
return;
}
out_of_resources_site(*note.ps);
});
+
+ // Subscribe to ShipNotes.
+ shipnotes_subscriber_ =
+ Notifications::subscribe<NoteShipMessage>([this](const NoteShipMessage& note) {
+ if (note.ship->get_owner()->player_number() != player_->player_number()) {
+ // if (note.ship->get_owner()->player_number() != pid) {
+ return;
+ }
+
+ if (note.message == NoteShipMessage::Message::GAINED) {
+ marineTaskQueue_.push_back(STOPSHIPYARD);
+
+ allships.push_back(ShipObserver());
+ allships.back().ship = note.ship;
+ if (game().get_gametime() % 2 == 0) {
+ allships.back().island_circ_direction = true;
+ } else {
+ allships.back().island_circ_direction = false;
+ }
+
+ } else if (note.message == NoteShipMessage::Message::LOST) {
+ for (std::list<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i)
+ if (i->ship == note.ship) {
+ allships.erase(i);
+ break;
+ }
+ } else if (note.message == NoteShipMessage::Message::WAITINGFORCOMMAND) {
+ for (std::list<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i)
+ if (i->ship == note.ship) {
+ i->waiting_for_command_ = true;
+ break;
+ }
+ }
+ });
}
DefaultAI::~DefaultAI() {
@@ -169,7 +220,7 @@
*/
void DefaultAI::think() {
- if (tribe_ == nullptr) {
+ if (tribe_ == nullptr || player_ == nullptr) {
late_initialization();
}
@@ -238,6 +289,14 @@
return;
}
+ if (check_ships(gametime)) {
+ return;
+ }
+
+ if (marine_main_decisions(gametime)) {
+ return;
+ }
+
// Check the mines and consider upgrading or destroying one
if (check_mines_(gametime)) {
return;
@@ -249,6 +308,10 @@
return;
}
+ if (check_trainingsites(gametime)) {
+ return;
+ }
+
// improve existing roads!
// main part of this improvment is creation 'shortcut roads'
// this includes also connection of new buildings
@@ -257,6 +320,12 @@
m_mineable_changed = true;
return;
}
+
+ // once in 15 minutes we increase(or decrease) targets for wares
+ if (next_wares_review_due_ <= gametime) {
+ next_wares_review_due_ = gametime + 15 * 60 * 1000;
+ review_wares_targets(gametime);
+ }
}
/**
@@ -317,6 +386,7 @@
bo.mountain_conqueror_ = bh.is_mountain_conqueror();
bo.prohibited_till_ = bh.get_prohibited_till() * 1000; // value in conf is in seconds
bo.forced_after_ = bh.get_forced_after() * 1000; // value in conf is in seconds
+ bo.is_port_ = bld.get_isport();
if (char const* const s = bh.get_renews_map_resource()) {
bo.production_hint_ = tribe_->safe_ware_index(s);
}
@@ -362,6 +432,13 @@
} else {
bo.is_fisher_ = false;
}
+
+ if (building_name == "shipyard") {
+ bo.is_shipyard_ = true;
+ } else {
+ bo.is_shipyard_ = false;
+ }
+
continue;
}
@@ -394,6 +471,11 @@
if (typeid(bld) == typeid(TrainingSiteDescr)) {
bo.type = BuildingObserver::TRAININGSITE;
+ const TrainingSiteDescr& train =
+ ref_cast<TrainingSiteDescr const, BuildingDescr const>(bld);
+ for (const WareAmount& temp_input : train.inputs()) {
+ bo.inputs_.push_back(temp_input.first);
+ }
continue;
}
@@ -593,6 +675,40 @@
}
}
+ if (!field.is_portspace_) { // if we know it no need to do it once more
+ if (player_->get_buildcaps(field.coords) & BUILDCAPS_PORT) {
+ field.is_portspace_ = true;
+ seafaring_economy = true;
+ // blocking fields in vicinity
+ MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(field.coords), 3));
+ do {
+ // const Coords coords = map.get_fcoords(*(mr.location().field));
+ const int32_t hash = coords_hash(map.get_fcoords(*(mr.location().field)));
+ if (port_reserved_coords.count(hash) == 0)
+ port_reserved_coords.insert(hash);
+ } while (mr.advance(map));
+ } else {
+ field.is_portspace_ = false;
+ }
+ }
+
+ // testing if a port is nearby, such field will get a priority boost
+ uint16_t nearest_distance = std::numeric_limits<uint16_t>::max();
+ for (std::list<WarehouseSiteObserver>::iterator wh_iter = warehousesites.begin();
+ wh_iter != warehousesites.end();
+ ++wh_iter) {
+ const uint16_t actual_distance =
+ map.calc_distance(field.coords, wh_iter->site->get_position());
+ if (nearest_distance > actual_distance) {
+ nearest_distance = actual_distance;
+ }
+ }
+ if (nearest_distance < 15) {
+ field.port_nearby_ = true;
+ } else {
+ field.port_nearby_ = false;
+ }
+
// collect information about resources in the area
std::vector<ImmovableFound> immovables;
// Search in a radius of range
@@ -901,6 +1017,7 @@
// (there should be no upgrade when there are not two buildings of the same type)
// - algorigthm is trying to take into account actual utlization of buildings
// (the one shown in GUI/game is not reliable, it calculates own statistics)
+// * military buildings have own strategy, split into two situations:spot
// * military buildings have own strategy, split into two situations:
// - there is no enemy
// - there is an enemy
@@ -913,7 +1030,7 @@
uint32_t consumers_nearby_count = 0;
std::vector<int32_t> spots_avail;
spots_avail.resize(4);
- // uint16_t const pn = player_number();
+ Map& map = game().map();
for (int32_t i = 0; i < 4; ++i)
spots_avail.at(i) = 0;
@@ -1019,7 +1136,8 @@
}
// testing big military buildings, whether critical construction
- // material is (not) needed
+ // material is available (at lest in amount of
+ // 2/3 of default target amount)
for (uint32_t j = 0; j < buildings_.size(); ++j) {
BuildingObserver& bo = buildings_.at(j);
@@ -1037,19 +1155,13 @@
bo.build_material_shortage_ = false;
- for (EconomyObserver* observer : economies) {
- // Don't check if the economy has no warehouse.
- if (observer->economy.warehouses().empty()) {
- continue;
- }
-
- for (uint32_t m = 0; m < bo.critical_built_mat_.size(); ++m) {
- WareIndex wt(static_cast<size_t>(bo.critical_built_mat_.at(m)));
-
- if (observer->economy.needs_ware(wt)) {
- bo.build_material_shortage_ = true;
- continue;
- }
+ // checking we have enough critical material on stock
+ for (uint32_t m = 0; m < bo.critical_built_mat_.size(); ++m) {
+ WareIndex wt(static_cast<size_t>(bo.critical_built_mat_.at(m)));
+ // using default ware quantity, not the best solution but will do
+ if (get_warehoused_stock(wt) <
+ tribe_->get_ware_descr(wt)->default_target_quantity() * 2 / 3) {
+ bo.build_material_shortage_ = true;
}
}
}
@@ -1065,10 +1177,6 @@
++i) {
BuildableField* const bf = *i;
- // if 'buildable field' update is overdue for more then 8 seconds
- // (= bf has not been updated for about 15 seconds)
- // skip the bf in evaluation, bacause information
- // contained in bf are too old
if (bf->next_update_due_ < gametime - 8000) {
continue;
}
@@ -1108,6 +1216,13 @@
continue;
}
+ // testing for reserved ports
+ if (!bo.is_port_) {
+ if (port_reserved_coords.count(coords_hash(bf->coords)) > 0) {
+ continue;
+ }
+ }
+
if (time(nullptr) % 3 == 0 && bo.total_count() > 0) {
continue;
} // add randomnes and ease AI
@@ -1405,6 +1520,10 @@
} else if (bo.cnt_built_ == 1 && game().get_gametime() > 40 * 60 * 1000 &&
bo.desc->enhancement() != INVALID_INDEX && !mines_.empty()) {
prio += 10;
+ } else if (bo.is_shipyard_ && seafaring_economy) {
+ ;
+ } else if (bo.is_shipyard_ && !seafaring_economy) {
+ continue;
} else if (!output_is_needed) {
continue;
} else if (bo.cnt_built_ == 0 && game().get_gametime() > 40 * 60 * 1000) {
@@ -1444,7 +1563,13 @@
prio -= bf->space_consumers_nearby_ * 3;
}
- if (!bo.inputs_.empty()) {
+ else if (bo.is_shipyard_) {
+ // for now AI builds only one shipyard
+ if (bf->water_nearby_ > 3 && bo.total_count() == 0 && seafaring_economy) {
+ prio += kDefaultPrioBoost + productionsites.size() * 5 + bf->water_nearby_;
+ }
+
+ } else if (!bo.inputs_.empty()) {
if (bo.total_count() == 0) {
prio += max_needed_preciousness + kDefaultPrioBoost;
}
@@ -1560,9 +1685,19 @@
} else if (bo.type == BuildingObserver::WAREHOUSE) {
// exclude spots on border
- if (bf->near_border_) {
- continue;
- }
+ if (bf->near_border_ && !bo.is_port_) {
+ continue;
+ }
+
+ if (!bf->is_portspace_ && bo.is_port_) {
+ continue;
+ }
+
+ if (bo.cnt_under_construction_ > 0) {
+ continue;
+ }
+
+ bool warehouse_needed = false;
// Build one warehouse for ~every 35 productionsites and mines_.
// Militarysites are slightly important as well, to have a bigger
@@ -1572,22 +1707,53 @@
static_cast<int32_t>(numof_warehouses_) &&
bo.cnt_under_construction_ == 0) {
prio = 20;
- }
-
- // take care about borders and enemies
+ warehouse_needed = true;
+ }
+
+ // but generally we prefer ports
+ if (bo.is_port_) {
+ prio += 10;
+ }
+
+ // special boost for first port
+ if (bo.is_port_ && bo.total_count() == 0 && productionsites.size() > 5 &&
+ !bf->enemy_nearby_ && bf->is_portspace_ && seafaring_economy) {
+ prio += kDefaultPrioBoost + productionsites.size();
+ warehouse_needed = true;
+ }
+
+ if (!warehouse_needed) {
+ continue;
+ }
+
+ // iterating over current warehouses and testing a distance
+ // getting distance to nearest warehouse and adding it to a score
+ uint16_t nearest_distance = std::numeric_limits<uint16_t>::max();
+ for (std::list<WarehouseSiteObserver>::iterator wh_iter = warehousesites.begin();
+ wh_iter != warehousesites.end();
+ ++wh_iter) {
+ const uint16_t actual_distance =
+ map.calc_distance(bf->coords, wh_iter->site->get_position());
+ if (nearest_distance > actual_distance) {
+ nearest_distance = actual_distance;
+ }
+ }
+
+ // take care about and enemies
if (bf->enemy_nearby_) {
prio /= 2;
}
- if (bf->unowned_land_nearby_) {
+ if (bf->unowned_land_nearby_ && !bo.is_port_) {
prio /= 2;
}
- // TODO(unknown): introduce check that there is no warehouse nearby
- // to prevent too close placing
-
} else if (bo.type == BuildingObserver::TRAININGSITE) {
+ if (virtual_mines < 5) {
+ continue;
+ }
+
// exclude spots on border
if (bf->near_border_) {
continue;
@@ -1598,7 +1764,7 @@
}
// build after 20 production sites and then after each 50 production site
- if (static_cast<int32_t>((productionsites.size() + 30) / 50) > bo.total_count() &&
+ if (static_cast<int32_t>((productionsites.size() + 40) / 60) > bo.total_count() &&
bo.cnt_under_construction_ == 0) {
prio = 4 + kDefaultPrioBoost;
}
@@ -1621,11 +1787,24 @@
continue;
}
+ // testing also vicinity
+ if (!bo.is_port_) {
+ const int32_t hash = bf->coords.x << 16 | bf->coords.y;
+ if (port_reserved_coords.count(hash) > 0) {
+ continue;
+ }
+ }
+
// Prefer road side fields
prio += bf->preferred_ ? 1 : 0;
// don't waste good land for small huts
prio -= (maxsize - bo.desc->get_size()) * 5;
+ // prefer vicinity of ports (with exemption of warehouses)
+ if (bf->port_nearby_ && bo.type == BuildingObserver::MILITARYSITE) {
+ prio *= 2;
+ }
+
if (prio > proposed_priority) {
best_building = &bo;
proposed_priority = prio;
@@ -1762,7 +1941,7 @@
block_time = 25 * 1000;
block_area = 6;
}
- Map& map = game().map();
+ // Map& map = game().map();
MapRegion<Area<FCoords>> mr(map, Area<FCoords>(map.get_fcoords(proposed_coords), block_area));
do {
@@ -1968,7 +2147,39 @@
// Increasing the failed_connection_tries counter
// At the same time it indicates a time an economy is without a warehouse
EconomyObserver* eco = get_economy_observer(flag.economy());
+
+ // there are two special situations which have a bit different treatment
+ bool is_remote_port_csite = false;
+ bool stationed_military = false;
if (flag.get_economy()->warehouses().empty()) {
+ // first very special case - lonesome port (in the phase of constructionsite)
+ // obviously it has no warehouse/road network to connect to
+ if (upcast(ConstructionSite const, constructionsite, flag.get_building())) {
+ BuildingObserver& bo = get_building_observer(
+ constructionsite->building().name().c_str()); // constructionsite->building();
+ if (bo.is_port_ &&
+ remote_ports_coords.count(coords_hash(flag.get_building()->get_position())) > 0) {
+ is_remote_port_csite = true;
+ }
+ }
+
+ // second exemption is when a military buiding was conquered, it
+ // might be just too far from near connected builging
+ if (Building* b = flag.get_building()) {
+ if (upcast(MilitarySite, militb, b)) {
+ if (militb->present_soldiers().size() > 0) {
+ stationed_military = true;
+ // also increasing checkradius a bit
+ checkradius += 4;
+ }
+ }
+ }
+ }
+
+ if (is_remote_port_csite ||
+ (stationed_military && game().get_gametime() % 10 > 0)) { // counter disabled
+ ;
+ } else if (flag.get_economy()->warehouses().empty()) {
eco->failed_connection_tries += 1;
} else {
eco->failed_connection_tries = 0;
@@ -2014,7 +2225,7 @@
for (const Coords& reachable_coords : reachable) {
- // first make sure there is an immovable (shold be, but still)
+ // first make sure there is an immovable (should be, but still)
if (upcast(PlayerImmovable const, player_immovable, map[reachable_coords].get_immovable())) {
// if it is the road, make a flag there
@@ -2536,6 +2747,233 @@
return changed;
}
+// This function scans current situation with shipyards, ports, ships, ongoing expeditions
+// and makes two decisions:
+// - build a ship
+// - start preparation for expedition
+bool DefaultAI::marine_main_decisions(int32_t const gametime) {
+ if (gametime < next_marine_decisions_due) {
+ return false;
+ }
+ next_marine_decisions_due += kMarineDecisionInterval;
+
+ if (!seafaring_economy) {
+ return false;
+ }
+
+ // getting some base statistics
+ player_ = game().get_player(player_number());
+ uint16_t ports_count = 0;
+ uint16_t shipyards_count = 0;
+ uint16_t working_shipyards_count = 0;
+ uint16_t expeditions_in_prep = 0;
+ uint16_t expeditions_in_progress = 0;
+ uint16_t terittories_count = 1;
+ bool idle_shipyard_stocked = false;
+
+ // goes over all wareouses (these includes ports)
+ for (std::list<WarehouseSiteObserver>::iterator wh_iter = warehousesites.begin();
+ wh_iter != warehousesites.end();
+ ++wh_iter) {
+
+ if (wh_iter->bo->is_port_) {
+ ports_count += 1;
+ if (Widelands::PortDock* pd = wh_iter->site->get_portdock()) {
+ if (pd->expedition_started()) {
+ expeditions_in_prep += 1;
+ }
+ } else {
+ log(" there is a port without portdock at %3dx%3d?\n",
+ wh_iter->site->get_position().x,
+ wh_iter->site->get_position().y);
+ }
+ }
+ }
+
+ // goes over productionsites and gets status of shipyards
+ for (std::list<ProductionSiteObserver>::iterator ps_iter = productionsites.begin();
+ ps_iter != productionsites.end();
+ ++ps_iter) {
+
+ if (ps_iter->bo->is_shipyard_) {
+ shipyards_count += 1;
+ if (!ps_iter->site->is_stopped()) {
+ working_shipyards_count += 1;
+ }
+ // counting stocks
+ uint8_t stocked_wares = 0;
+ std::vector<WaresQueue*> const warequeues = ps_iter->site->warequeues();
+ size_t const nr_warequeues = warequeues.size();
+ for (size_t i = 0; i < nr_warequeues; ++i) {
+ stocked_wares += warequeues[i]->get_filled();
+ }
+ if (stocked_wares == 16 && ps_iter->site->is_stopped()) {
+ idle_shipyard_stocked = true;
+ }
+ }
+ }
+
+ // and now over ships
+ for (std::list<ShipObserver>::iterator sp_iter = allships.begin(); sp_iter != allships.end();
+ ++sp_iter) {
+ if (sp_iter->ship->state_is_expedition()) {
+ expeditions_in_progress += 1;
+ }
+ }
+
+ // we must verify that all remote ports are still ours (and exists at all)
+ bool still_ours;
+ for (std::unordered_set<uint32_t>::iterator ports_iter = remote_ports_coords.begin();
+ ports_iter != remote_ports_coords.end();
+ ++ports_iter) {
+ still_ours = false;
+ FCoords fcoords = game().map().get_fcoords(coords_unhash(*ports_iter));
+ if (fcoords.field->get_owned_by() == player_number()) {
+ if (upcast(PlayerImmovable, imm, fcoords.field->get_immovable())) {
+ still_ours = true;
+ }
+ }
+
+ if (!still_ours) {
+ remote_ports_coords.erase(*ports_iter);
+ break;
+ }
+ }
+ terittories_count += remote_ports_coords.size();
+
+ enum {NEEDSHIP = 0, ENOUGHSHIPS = 1, DONOTHING = 2 };
+
+ // now we must compare ports vs ships to decide if new ship is needed or new expedition can start
+ uint8_t enough_ships = DONOTHING;
+ if (static_cast<float>(allships.size()) >
+ static_cast<float>((terittories_count - 1) * 0.6 + ports_count * 0.75)) {
+ enough_ships = ENOUGHSHIPS;
+ } else if (static_cast<float>(allships.size()) <
+ static_cast<float>((terittories_count - 1) * 0.6 + ports_count * 0.75)) {
+ enough_ships = NEEDSHIP;
+ }
+
+ // building a ship? if yes, find a shipyard and order it to build a ship
+ if (shipyards_count > 0 && enough_ships == NEEDSHIP && idle_shipyard_stocked &&
+ ports_count > 0) {
+
+ for (std::list<ProductionSiteObserver>::iterator ps_iter = productionsites.begin();
+ ps_iter != productionsites.end();
+ ++ps_iter) {
+
+ if (ps_iter->bo->is_shipyard_ && ps_iter->site->can_start_working() &&
+ ps_iter->site->is_stopped()) {
+ // make sure it is fully stocked
+ // counting stocks
+ uint8_t stocked_wares = 0;
+ std::vector<WaresQueue*> const warequeues = ps_iter->site->warequeues();
+ size_t const nr_warequeues = warequeues.size();
+ for (size_t i = 0; i < nr_warequeues; ++i) {
+ stocked_wares += warequeues[i]->get_filled();
+ }
+ if (stocked_wares < 16) {
+ continue;
+ }
+
+ game().send_player_start_stop_building(*ps_iter->site);
+ return true;
+ }
+ }
+ }
+
+ // starting an expedition? if yes, find a port and order it to start an expedition
+ if (ports_count > 0 && enough_ships == ENOUGHSHIPS && expeditions_in_prep == 0 &&
+ expeditions_in_progress == 0) {
+ // we need to find a port
+ for (std::list<WarehouseSiteObserver>::iterator wh_iter = warehousesites.begin();
+ wh_iter != warehousesites.end();
+ ++wh_iter) {
+
+ if (wh_iter->bo->is_port_) {
+ game().send_player_start_or_cancel_expedition(*wh_iter->site);
+ return true;
+ }
+ }
+ }
+ return true;
+}
+
+// This identifies ships that are waiting for command
+bool DefaultAI::check_ships(int32_t const gametime) {
+ if (gametime < next_ship_check_due) {
+ return false;
+ }
+
+ next_ship_check_due += kShipCheckInterval;
+
+ if (!seafaring_economy) {
+ return false;
+ }
+
+ if (!allships.empty()) {
+ // iterating over ships and executing what is needed
+ for (std::list<ShipObserver>::iterator i = allships.begin(); i != allships.end(); ++i) {
+
+ // only two states need an attention
+ if ((i->ship->get_ship_state() == Widelands::Ship::EXP_WAITING ||
+ i->ship->get_ship_state() == Widelands::Ship::EXP_FOUNDPORTSPACE) &&
+ !i->waiting_for_command_) {
+ if (gametime - i->last_command_time > 180 * 1000) {
+ i->waiting_for_command_ = true;
+ log(" %1d: last command for ship at %3dx%3d was %3d seconds ago, something wrong "
+ "here?...\n",
+ player_number(),
+ i->ship->get_position().x,
+ i->ship->get_position().y,
+ (gametime - i->last_command_time) / 1000);
+ }
+ }
+ // only two states need an attention
+ if (!(i->ship->get_ship_state() == Widelands::Ship::EXP_WAITING ||
+ i->ship->get_ship_state() == Widelands::Ship::EXP_FOUNDPORTSPACE) &&
+ i->waiting_for_command_) {
+ }
+ // if ships is waiting for command
+ if (i->waiting_for_command_) {
+ expedition_management(*i);
+ }
+ }
+ }
+
+ // processing marineTaskQueue_
+ while (!marineTaskQueue_.empty()) {
+ if (marineTaskQueue_.back() == STOPSHIPYARD) {
+ // iterate over all production sites searching for shipyard
+ for (std::list<ProductionSiteObserver>::iterator site = productionsites.begin();
+ site != productionsites.end();
+ ++site) {
+ if (site->bo->is_shipyard_) {
+ if (!site->site->is_stopped()) {
+ game().send_player_start_stop_building(*site->site);
+ }
+ }
+ }
+ }
+
+ if (marineTaskQueue_.back() == REPRIORITIZE) {
+ for (std::list<ProductionSiteObserver>::iterator site = productionsites.begin();
+ site != productionsites.end();
+ ++site) {
+ if (site->bo->is_shipyard_) {
+ for (uint32_t k = 0; k < site->bo->inputs_.size(); ++k) {
+ game().send_player_set_ware_priority(
+ *site->site, wwWARE, site->bo->inputs_.at(k), HIGH_PRIORITY);
+ }
+ }
+ }
+ }
+
+ marineTaskQueue_.pop_back();
+ }
+
+ return true;
+}
+
/**
* checks the first mine in list, takes care if it runs out of
* resources and finally reenqueues it at the end of the list.
@@ -2709,6 +3147,51 @@
return count;
}
+// counts produced output in warehouses (only)
+// perhaps it wil might replace get_stocklevel
+// if multiple outputs, it returns lowest value
+uint32_t DefaultAI::get_warehoused_stock(WareIndex wt) {
+ uint32_t count = 0;
+
+ for (std::list<WarehouseSiteObserver>::iterator i = warehousesites.begin();
+ i != warehousesites.end();
+ ++i) {
+ count += i->site->get_wares().stock(wt);
+ }
+
+ return count;
+}
+
+// this function only manipulates with trainingsites' inputs priority
+// decreases it when too many unoccupied military buildings
+bool DefaultAI::check_trainingsites(int32_t gametime) {
+ if (next_trainingsites_check_due_ > gametime) {
+ return false;
+ }
+ if (!trainingsites.empty()) {
+ next_trainingsites_check_due_ = gametime + kTrainingSitesCheckInterval;
+ } else {
+ next_trainingsites_check_due_ = gametime + 3 * kTrainingSitesCheckInterval;
+ }
+
+ uint8_t new_priority = DEFAULT_PRIORITY;
+ if (unstationed_milit_buildings_ > 2) {
+ new_priority = LOW_PRIORITY;
+ } else {
+ new_priority = DEFAULT_PRIORITY;
+ }
+ for (std::list<TrainingSiteObserver>::iterator site = trainingsites.begin();
+ site != trainingsites.end();
+ ++site) {
+
+ for (uint32_t k = 0; k < site->bo->inputs_.size(); ++k) {
+ game().send_player_set_ware_priority(
+ *site->site, wwWARE, site->bo->inputs_.at(k), new_priority);
+ }
+ }
+ return true;
+}
+
/**
* Updates the first military building in list and reenques it at the end of
* the list afterwards. If a militarysite is in secure area but holds more than
@@ -3002,6 +3485,203 @@
}
}
+// this scores spot for potential colony
+uint8_t DefaultAI::spot_scoring(Widelands::Coords candidate_spot) {
+
+ uint8_t score = 0;
+ uint16_t mineable_fields_count = 0;
+ Map& map = game().map();
+ // first making sure there are no other players nearby
+ std::list<uint32_t> queue;
+ std::unordered_set<uint32_t> done;
+ queue.push_front(coords_hash(candidate_spot));
+ while (!queue.empty()) {
+
+ // if already processed
+ if (done.count(queue.front()) > 0) {
+ queue.pop_front();
+ continue;
+ }
+
+ done.insert(queue.front());
+
+ Coords tmp_coords = coords_unhash(queue.front());
+
+ // if beyond range
+ if (map.calc_distance(candidate_spot, tmp_coords) > colony_scan_area_) {
+ continue;
+ }
+
+ Field* f = map.get_fcoords(tmp_coords).field;
+
+ // if owned by someone:
+ if (f->get_owned_by() > 0) {
+ // just return 0 as score
+ return 0;
+ }
+
+ // not interested if not walkable
+ if (!(f->nodecaps() & MOVECAPS_WALK)) {
+ continue;
+ }
+
+ // increase mines counter
+ if (f->nodecaps() & BUILDCAPS_MINE) {
+ mineable_fields_count += 1;
+ };
+
+ // add neighbours to a queue (duplicates are no problem)
+ // to relieve AI/CPU we skip every second field in each direction
+ // obstacles are usually wider then one field
+ for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
+ Coords neigh_coords1;
+ map.get_neighbour(tmp_coords, dir, &neigh_coords1);
+ Coords neigh_coords2;
+ map.get_neighbour(neigh_coords1, dir, &neigh_coords2);
+ queue.push_front(coords_hash(neigh_coords2));
+ }
+ }
+
+ // if the island is too small
+ if (done.size() < 50) {
+ return 0;
+ }
+
+ // if we are here we put score
+ score = 1;
+ if (mineable_fields_count > 0) {
+ score += 1;
+ }
+
+ // here we check for surface stones + trees
+ std::vector<ImmovableFound> immovables;
+ // Search in a radius of range
+ map.find_immovables(Area<FCoords>(map.get_fcoords(candidate_spot), 10), &immovables);
+
+ int32_t const stone_attr = MapObjectDescr::get_attribute_id("granite");
+ uint16_t stones = 0;
+ int32_t const tree_attr = MapObjectDescr::get_attribute_id("tree");
+ uint16_t trees = 0;
+
+ for (uint32_t j = 0; j < immovables.size(); ++j) {
+ if (immovables.at(j).object->has_attribute(stone_attr)) {
+ ++stones;
+ }
+ if (immovables.at(j).object->has_attribute(tree_attr)) {
+ ++trees;
+ }
+ }
+ if (stones > 1) {
+ score += 1;
+ }
+ if (trees > 1) {
+ score += 1;
+ }
+
+ return score;
+}
+
+// this is called whenever ship received a notification that requires
+// navigation decisions (these notifiation are processes not in 'real time')
+void DefaultAI::expedition_management(ShipObserver& so) {
+
+ Map& map = game().map();
+ const int32_t gametime = game().get_gametime();
+
+ // first we put current spot into visited_spots_
+ bool first_time_here = false;
+ if (so.visited_spots_.count(coords_hash(so.ship->get_position())) == 0) {
+ first_time_here = true;
+ so.visited_spots_.insert(coords_hash(so.ship->get_position()));
+ }
+
+ // If we have portspace following options are avaiable:
+ // 1. Build a port there
+ if (so.ship->exp_port_spaces()->size() > 0) { // making sure we have possible portspaces
+
+ // we score the place
+ const uint8_t spot_score = spot_scoring(so.ship->exp_port_spaces()->front());
+
+ if ((gametime / 10) % 8 < spot_score) { // we build a port here
+ const Coords last_portspace = so.ship->exp_port_spaces()->front();
+ remote_ports_coords.insert(coords_hash(last_portspace));
+ game().send_player_ship_construct_port(*so.ship, so.ship->exp_port_spaces()->front());
+ so.last_command_time = gametime;
+ so.waiting_for_command_ = false;
+ // blocking the area for some time to save AI from idle attempts to built there
+ // buildings
+ // TODO(anybody): how long it takes to build a port?
+ // I used 5 minutes
+ MapRegion<Area<FCoords>> mr(
+ game().map(), Area<FCoords>(map.get_fcoords(so.ship->exp_port_spaces()->front()), 8));
+ do {
+ BlockedField blocked2(
+ map.get_fcoords(*(mr.location().field)), gametime + 5 * 60 * 1000);
+ blocked_fields.push_back(blocked2);
+ } while (mr.advance(map));
+
+ return;
+ }
+
+ // decreasing colony_scan_area_
+ if (colony_scan_area_ > 15 && gametime % 10 == 0) {
+ colony_scan_area_ -= 1;
+ }
+ }
+
+ // if we are here, port was not ordered above
+ // 2. Go on with expedition
+
+ if (first_time_here) {
+ game().send_player_ship_explore_island(*so.ship, so.island_circ_direction);
+ so.last_command_time = gametime;
+ so.waiting_for_command_ = false;
+
+ // we was here but to add randomnes we might continue with expedition
+ } else if (gametime % 2 == 0) {
+ game().send_player_ship_explore_island(*so.ship, so.island_circ_direction);
+ so.last_command_time = gametime;
+ so.waiting_for_command_ = false;
+ } else {
+ // get swimable directions
+ std::vector<Direction> possible_directions;
+ for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
+
+ // testing distance of 8 fields
+ // this would say there is an 'open sea' there
+ Widelands::FCoords tmp_fcoords = map.get_fcoords(so.ship->get_position());
+ for (int8_t i = 0; i < 8; ++i) {
+ tmp_fcoords = map.get_neighbour(tmp_fcoords, dir);
+ if (tmp_fcoords.field->nodecaps() & MOVECAPS_SWIM) {
+ if (i == 7) {
+ possible_directions.push_back(dir);
+ break; // not needed but.....
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ // we test if there is open sea
+ if (possible_directions.size() == 0) {
+ // 2.A No there is no open sea
+ game().send_player_ship_explore_island(*so.ship, so.island_circ_direction);
+ so.last_command_time = gametime;
+ so.waiting_for_command_ = false;
+ ;
+ } else {
+ // 2.B Yes, pick one of avaiable directions
+ const Direction final_direction =
+ possible_directions.at(gametime % possible_directions.size());
+ game().send_player_ship_scout_direction(*so.ship, final_direction);
+ so.last_command_time = gametime;
+ so.waiting_for_command_ = false;
+ }
+ }
+ return;
+}
+
// this is called whenever we gain a new building
void DefaultAI::gain_building(Building& b) {
BuildingObserver& bo = get_building_observer(b.descr().name().c_str());
@@ -3031,6 +3711,10 @@
productionsites.back().unoccupied_till_ = game().get_gametime();
productionsites.back().stats_zero_ = 0;
productionsites.back().no_resources_count = 0;
+ if (bo.is_shipyard_) {
+ marineTaskQueue_.push_back(STOPSHIPYARD);
+ marineTaskQueue_.push_back(REPRIORITIZE);
+ }
for (uint32_t i = 0; i < bo.outputs_.size(); ++i)
++wares.at(bo.outputs_.at(i)).producers_;
@@ -3055,8 +3739,19 @@
militarysites.back().checks = bo.desc->get_size();
militarysites.back().enemies_nearby_ = true;
+ } else if (bo.type == BuildingObserver::TRAININGSITE) {
+ trainingsites.push_back(TrainingSiteObserver());
+ trainingsites.back().site = &ref_cast<TrainingSite, Building>(b);
+ trainingsites.back().bo = &bo;
+
} else if (bo.type == BuildingObserver::WAREHOUSE) {
++numof_warehouses_;
+ warehousesites.push_back(WarehouseSiteObserver());
+ warehousesites.back().site = &ref_cast<Warehouse, Building>(b);
+ warehousesites.back().bo = &bo;
+ if (bo.is_port_) {
+ ++num_ports;
+ }
}
}
}
@@ -3123,9 +3818,31 @@
break;
}
}
+ } else if (bo.type == BuildingObserver::TRAININGSITE) {
+
+ for (std::list<TrainingSiteObserver>::iterator i = trainingsites.begin();
+ i != trainingsites.end();
+ ++i) {
+ if (i->site == &b) {
+ trainingsites.erase(i);
+ break;
+ }
+ }
} else if (bo.type == BuildingObserver::WAREHOUSE) {
assert(numof_warehouses_ > 0);
--numof_warehouses_;
+ if (bo.is_port_) {
+ --num_ports;
+ }
+
+ for (std::list<WarehouseSiteObserver>::iterator i = warehousesites.begin();
+ i != warehousesites.end();
+ ++i) {
+ if (i->site == &b) {
+ warehousesites.erase(i);
+ break;
+ }
+ }
}
}
@@ -3411,6 +4128,35 @@
}
}
+// This runs once in 15 minutes, and adjust wares targets based on number of
+// productionsites and ports
+void DefaultAI::review_wares_targets(int32_t const gametime) {
+
+ player_ = game().get_player(player_number());
+ tribe_ = &player_->tribe();
+
+ // to avoid floats real multiplicator is multiplicator/10
+ uint16_t multiplicator = 10;
+ if ((productionsites.size() + num_ports * 5) > 50) {
+ multiplicator = (productionsites.size() + num_ports * 5) / 5;
+ }
+
+ for (EconomyObserver* observer : economies) {
+ WareIndex nritems = observer->economy.owner().tribe().get_nrwares();
+ for (Widelands::WareIndex id = 0; id < nritems; ++id) {
+ // const Economy::TargetQuantity & tq = observer->economy.ware_target_quantity(id);
+ const uint16_t default_target = tribe_->get_ware_descr(id)->default_target_quantity();
+
+ game().send_player_command(*new Widelands::CmdSetWareTargetQuantity(
+ gametime,
+ player_number(),
+ player_->get_economy_number(&observer->economy),
+ id,
+ default_target * multiplicator / 10));
+ }
+ }
+}
+
// This is used for profiling, so usually this is not used :)
void DefaultAI::print_land_stats() {
// this will just print statistics of land size
=== modified file 'src/ai/defaultai.h'
--- src/ai/defaultai.h 2014-10-17 19:13:39 +0000
+++ src/ai/defaultai.h 2014-11-19 21:19:43 +0000
@@ -27,6 +27,8 @@
#include "ai/computer_player.h"
#include "base/i18n.h"
#include "logic/immovable.h"
+#include "logic/ship.h"
+#include <unordered_set>
namespace Widelands {
struct Road;
@@ -130,6 +132,18 @@
bool construct_building(int32_t);
+ uint32_t coords_hash(Widelands::Coords coords) {
+ uint32_t hash = coords.x << 16 | coords.y;
+ return hash;
+ }
+
+ Widelands::Coords coords_unhash(uint32_t hash) {
+ Widelands::Coords coords;
+ coords.x = hash >> 16; // is cast needed here???
+ coords.y = hash;
+ return coords;
+ }
+
// all road management is invoked by function improve_roads()
// if needed it calls create_shortcut_road() with a flag from which
// new road should be considered (or is needed)
@@ -139,18 +153,25 @@
bool dispensable_road_test(const Widelands::Road&);
bool check_economies();
bool check_productionsites(int32_t);
+ bool check_trainingsites(int32_t);
bool check_mines_(int32_t);
bool check_militarysites(int32_t);
+ bool marine_main_decisions(int32_t);
+ bool check_ships(int32_t);
uint32_t get_stocklevel_by_hint(size_t);
uint32_t get_stocklevel(BuildingObserver&);
+ uint32_t get_warehoused_stock(Widelands::WareIndex wt);
uint32_t get_stocklevel(Widelands::WareIndex); // count all direct outputs_
void check_helpersites(int32_t);
+ void review_wares_targets(int32_t);
int32_t recalc_with_border_range(const BuildableField&, int32_t);
int32_t calculate_need_for_ps(BuildingObserver&, int32_t);
void
consider_productionsite_influence(BuildableField&, Widelands::Coords, const BuildingObserver&);
+ // considering wood, stones, mines, water, fishes for candidate for colonization (new port)
+ uint8_t spot_scoring(Widelands::Coords candidate_spot);
EconomyObserver* get_economy_observer(Widelands::Economy&);
BuildingObserver& get_building_observer(char const*);
@@ -159,6 +180,8 @@
void lose_immovable(const Widelands::PlayerImmovable&);
void gain_building(Widelands::Building&);
void lose_building(const Widelands::Building&);
+ void expedition_management(ShipObserver&);
+ // bool pick_farest_portspace(Widelands::Ship&);
void out_of_resources_site(const Widelands::ProductionSite&);
bool check_supply(const BuildingObserver&);
@@ -181,10 +204,14 @@
uint32_t num_constructionsites_;
uint32_t num_milit_constructionsites;
uint32_t num_prod_constructionsites;
+ uint32_t num_ports;
std::list<Widelands::FCoords> unusable_fields;
std::list<BuildableField*> buildable_fields;
std::list<BlockedField> blocked_fields;
+ std::unordered_set<uint32_t> port_reserved_coords;
+ // to distinquish which ports are on home teritory and which one are remote
+ std::unordered_set<uint32_t> remote_ports_coords;
std::list<MineableField*> mineable_fields;
std::list<Widelands::Flag const*> new_flags;
std::list<Widelands::Coords> flags_to_be_removed;
@@ -193,6 +220,9 @@
std::list<ProductionSiteObserver> productionsites;
std::list<ProductionSiteObserver> mines_;
std::list<MilitarySiteObserver> militarysites;
+ std::list<WarehouseSiteObserver> warehousesites;
+ std::list<TrainingSiteObserver> trainingsites;
+ std::list<ShipObserver> allships;
std::vector<WareObserver> wares;
@@ -203,9 +233,12 @@
int32_t next_productionsite_check_due_;
int32_t next_mine_check_due_;
int32_t next_militarysite_check_due_;
+ int32_t next_ship_check_due;
+ int32_t next_marine_decisions_due;
int32_t next_attack_consideration_due_;
- int32_t next_helpersites_check_due_;
+ int32_t next_trainingsites_check_due_;
int32_t next_bf_check_due_;
+ int32_t next_wares_review_due_;
int32_t inhibit_road_building_;
int32_t time_of_last_construction_;
int32_t enemy_last_seen_;
@@ -232,13 +265,20 @@
Widelands::Coords
last_attack_target_; // flag to abuilding (position) that was attacked last time
int32_t next_attack_waittime_; // second till the next attack consideration
- int32_t spots_; // sum of buildable fields
+ bool seafaring_economy; // false by default, until first port space is found
+ uint32_t colony_scan_area_; // distance from a possible port that is scanned for owned territory
+ // it decreases with failed scans
+ int32_t spots_; // sum of buildable fields
+
+ enum {REPRIORITIZE, STOPSHIPYARD, STARTSHIPYARD};
+ std::vector<int16_t> marineTaskQueue_;
std::unique_ptr<Notifications::Subscriber<Widelands::NoteFieldPossession>>
field_possession_subscriber_;
std::unique_ptr<Notifications::Subscriber<Widelands::NoteImmovable>> immovable_subscriber_;
std::unique_ptr<Notifications::Subscriber<Widelands::NoteProductionSiteOutOfResources>>
outofresource_subscriber_;
+ std::unique_ptr<Notifications::Subscriber<Widelands::NoteShipMessage>> shipnotes_subscriber_;
};
#endif // end of include guard: WL_AI_DEFAULTAI_H
=== modified file 'src/economy/portdock.cc'
--- src/economy/portdock.cc 2014-09-20 09:37:47 +0000
+++ src/economy/portdock.cc 2014-11-19 21:19:43 +0000
@@ -21,6 +21,8 @@
#include <memory>
+#include <boost/format.hpp>
+
#include "base/deprecated.h"
#include "base/log.h"
#include "economy/fleet.h"
@@ -46,20 +48,16 @@
return g_portdock_descr;
}
-
PortdockDescr::PortdockDescr(char const* const _name, char const* const _descname)
- :
- MapObjectDescr(MapObjectType::PORTDOCK, _name, _descname)
-{
+ : MapObjectDescr(MapObjectType::PORTDOCK, _name, _descname) {
}
-PortDock::PortDock(Warehouse* wh) :
- PlayerImmovable(g_portdock_descr),
- m_fleet(nullptr),
- m_warehouse(wh),
- m_need_ship(false),
- m_expedition_ready(false)
-{
+PortDock::PortDock(Warehouse* wh)
+ : PlayerImmovable(g_portdock_descr),
+ m_fleet(nullptr),
+ m_warehouse(wh),
+ m_need_ship(false),
+ m_expedition_ready(false) {
}
PortDock::~PortDock() {
@@ -76,8 +74,7 @@
*
* @note This only works properly when called before @ref init
*/
-void PortDock::add_position(Coords where)
-{
+void PortDock::add_position(Coords where) {
m_dockpoints.push_back(where);
}
@@ -90,29 +87,23 @@
*
* @warning This should only be called via @ref Fleet itself.
*/
-void PortDock::set_fleet(Fleet * fleet)
-{
+void PortDock::set_fleet(Fleet* fleet) {
m_fleet = fleet;
}
-int32_t PortDock::get_size() const
-{
+int32_t PortDock::get_size() const {
return SMALL;
}
-bool PortDock::get_passable() const
-{
+bool PortDock::get_passable() const {
return true;
}
-PortDock::PositionList PortDock::get_positions
- (const EditorGameBase &) const
-{
+PortDock::PositionList PortDock::get_positions(const EditorGameBase&) const {
return m_dockpoints;
}
-Flag & PortDock::base_flag()
-{
+Flag& PortDock::base_flag() {
return m_warehouse->base_flag();
}
@@ -120,8 +111,7 @@
* Return the dock that has the given flag as its base, or 0 if no dock of our fleet
* has the given flag.
*/
-PortDock * PortDock::get_dock(Flag & flag) const
-{
+PortDock* PortDock::get_dock(Flag& flag) const {
if (m_fleet)
return m_fleet->get_dock(flag);
return nullptr;
@@ -133,8 +123,7 @@
* Called by @ref Warehouse::set_economy, and responsible for forwarding the
* change to @ref Fleet.
*/
-void PortDock::set_economy(Economy * e)
-{
+void PortDock::set_economy(Economy* e) {
if (e == get_economy())
return;
@@ -152,18 +141,14 @@
m_expedition_bootstrap->set_economy(e);
}
-
-void PortDock::draw
- (const EditorGameBase &, RenderTarget &, const FCoords&, const Point&)
-{
+void PortDock::draw(const EditorGameBase&, RenderTarget&, const FCoords&, const Point&) {
// do nothing
}
-void PortDock::init(EditorGameBase & egbase)
-{
+void PortDock::init(EditorGameBase& egbase) {
PlayerImmovable::init(egbase);
- for (const Coords& coords: m_dockpoints) {
+ for (const Coords& coords : m_dockpoints) {
set_position(egbase, coords);
}
@@ -174,18 +159,21 @@
* Create our initial singleton @ref Fleet. The fleet code ensures
* that we merge with a larger fleet when possible.
*/
-void PortDock::init_fleet(EditorGameBase & egbase)
-{
- Fleet * fleet = new Fleet(owner());
+void PortDock::init_fleet(EditorGameBase& egbase) {
+ Fleet* fleet = new Fleet(owner());
fleet->add_port(egbase, this);
fleet->init(egbase);
// Note: the Fleet calls our set_fleet automatically
}
-void PortDock::cleanup(EditorGameBase & egbase)
-{
+void PortDock::cleanup(EditorGameBase& egbase) {
+
+ Warehouse* wh = nullptr;
+
if (egbase.objects().object_still_available(m_warehouse)) {
- // Transfer all our wares into the warehouse.
+
+ wh = m_warehouse;
+
if (upcast(Game, game, &egbase)) {
for (ShippingItem& shipping_item : m_waiting) {
WareInstance* ware;
@@ -199,6 +187,7 @@
}
}
}
+
m_waiting.clear();
m_warehouse->m_portdock = nullptr;
}
@@ -212,7 +201,7 @@
if (m_fleet)
m_fleet->remove_port(egbase, this);
- for (const Coords& coords: m_dockpoints) {
+ for (const Coords& coords : m_dockpoints) {
unset_position(egbase, coords);
}
@@ -222,13 +211,26 @@
}
PlayerImmovable::cleanup(egbase);
+
+ if (wh) {
+ if (upcast(Game, game, &egbase)) {
+ if (game->is_loaded()) {
+ Player& player = owner();
+ log("Message: Portdock lost, trying to restore it (player %d)\n",
+ player.player_number());
+ wh->restore_portdock_or_destroy(egbase);
+ return;
+ }
+ }
+ // this is not a (running) game, destroying the port
+ wh->destroy(egbase);
+ }
}
/**
* Add the flags of all ports that can be reached via this dock.
*/
-void PortDock::add_neighbours(std::vector<RoutingNodeNeighbour> & neighbours)
-{
+void PortDock::add_neighbours(std::vector<RoutingNodeNeighbour>& neighbours) {
if (m_fleet && m_fleet->active())
m_fleet->add_neighbours(*this, neighbours);
}
@@ -236,8 +238,7 @@
/**
* The given @p ware enters the dock, waiting to be transported away.
*/
-void PortDock::add_shippingitem(Game & game, WareInstance & ware)
-{
+void PortDock::add_shippingitem(Game& game, WareInstance& ware) {
m_waiting.push_back(ShippingItem(ware));
ware.set_location(game, this);
ware.update(game);
@@ -247,15 +248,14 @@
* The given @p ware, which is assumed to be inside the dock, has updated
* its route.
*/
-void PortDock::update_shippingitem(Game & game, WareInstance & ware)
-{
+void PortDock::update_shippingitem(Game& game, WareInstance& ware) {
for (std::vector<ShippingItem>::iterator item_iter = m_waiting.begin();
- item_iter != m_waiting.end();
- ++item_iter) {
+ item_iter != m_waiting.end();
+ ++item_iter) {
if (item_iter->m_object.serial() == ware.serial()) {
_update_shippingitem(game, item_iter);
- return;
+ return;
}
}
}
@@ -263,8 +263,7 @@
/**
* The given @p worker enters the dock, waiting to be transported away.
*/
-void PortDock::add_shippingitem(Game & game, Worker & worker)
-{
+void PortDock::add_shippingitem(Game& game, Worker& worker) {
m_waiting.push_back(ShippingItem(worker));
worker.set_location(this);
update_shippingitem(game, worker);
@@ -274,24 +273,22 @@
* The given @p worker, which is assumed to be inside the dock, has
* updated its route.
*/
-void PortDock::update_shippingitem(Game & game, Worker & worker)
-{
+void PortDock::update_shippingitem(Game& game, Worker& worker) {
for (std::vector<ShippingItem>::iterator item_iter = m_waiting.begin();
- item_iter != m_waiting.end();
- ++item_iter) {
+ item_iter != m_waiting.end();
+ ++item_iter) {
if (item_iter->m_object.serial() == worker.serial()) {
_update_shippingitem(game, item_iter);
- return;
+ return;
}
}
}
-void PortDock::_update_shippingitem(Game & game, std::vector<ShippingItem>::iterator it)
-{
+void PortDock::_update_shippingitem(Game& game, std::vector<ShippingItem>::iterator it) {
it->update_destination(game, *this);
- PortDock * dst = it->get_destination(game);
+ PortDock* dst = it->get_destination(game);
assert(dst != this);
// Destination might have vanished or be in another economy altogether.
@@ -312,8 +309,7 @@
* A ship has arrived at the dock. Clear all items designated for this dock,
* and load the ship.
*/
-void PortDock::ship_arrived(Game & game, Ship & ship)
-{
+void PortDock::ship_arrived(Game& game, Ship& ship) {
std::vector<ShippingItem> items_brought_by_ship;
ship.withdraw_items(game, *this, items_brought_by_ship);
@@ -330,7 +326,8 @@
// Load the ship
std::vector<Worker*> workers;
std::vector<WareInstance*> wares;
- m_expedition_bootstrap->get_waiting_workers_and_wares(game, owner().tribe(), &workers, &wares);
+ m_expedition_bootstrap->get_waiting_workers_and_wares(
+ game, owner().tribe(), &workers, &wares);
for (Worker* worker : workers) {
ship.add_item(game, ShippingItem(*worker));
@@ -375,8 +372,7 @@
m_fleet->update(game);
}
-void PortDock::set_need_ship(Game & game, bool need)
-{
+void PortDock::set_need_ship(Game& game, bool need) {
molog("set_need_ship(%s)\n", need ? "true" : "false");
if (need == m_need_ship)
@@ -393,13 +389,12 @@
/**
* Return the number of wares or workers of the given type that are waiting at the dock.
*/
-uint32_t PortDock::count_waiting(WareWorker waretype, WareIndex wareindex)
-{
+uint32_t PortDock::count_waiting(WareWorker waretype, WareIndex wareindex) {
uint32_t count = 0;
for (ShippingItem& shipping_item : m_waiting) {
- WareInstance * ware;
- Worker * worker;
+ WareInstance* ware;
+ Worker* worker;
shipping_item.get(owner().egbase(), &ware, &worker);
if (waretype == wwWORKER) {
@@ -414,7 +409,6 @@
return count;
}
-
/// \returns whether an expedition was started or is even ready
bool PortDock::expedition_started() {
return (m_expedition_bootstrap.get() != nullptr) || m_expedition_ready;
@@ -425,19 +419,18 @@
assert(!m_expedition_bootstrap);
m_expedition_bootstrap.reset(new ExpeditionBootstrap(this));
m_expedition_bootstrap->start();
-
}
ExpeditionBootstrap* PortDock::expedition_bootstrap() {
return m_expedition_bootstrap.get();
}
-void PortDock::expedition_bootstrap_complete(Game & game) {
+void PortDock::expedition_bootstrap_complete(Game& game) {
m_expedition_ready = true;
get_fleet()->update(game);
}
-void PortDock::cancel_expedition(Game & game) {
+void PortDock::cancel_expedition(Game& game) {
// Reset
m_expedition_ready = false;
@@ -445,38 +438,34 @@
m_expedition_bootstrap.reset(nullptr);
}
-
-void PortDock::log_general_info(const EditorGameBase & egbase)
-{
+void PortDock::log_general_info(const EditorGameBase& egbase) {
PlayerImmovable::log_general_info(egbase);
Coords pos(m_warehouse->get_position());
- molog
- ("PortDock for warehouse %u (at %i,%i) in fleet %u, need_ship: %s, waiting: %" PRIuS "\n",
- m_warehouse ? m_warehouse->serial() : 0, pos.x, pos.y,
- m_fleet ? m_fleet->serial() : 0,
- m_need_ship ? "true" : "false",
- m_waiting.size());
+ molog("PortDock for warehouse %u (at %i,%i) in fleet %u, need_ship: %s, waiting: %" PRIuS "\n",
+ m_warehouse ? m_warehouse->serial() : 0,
+ pos.x,
+ pos.y,
+ m_fleet ? m_fleet->serial() : 0,
+ m_need_ship ? "true" : "false",
+ m_waiting.size());
for (ShippingItem& shipping_item : m_waiting) {
- molog
- (" IT %u, destination %u\n",
- shipping_item.m_object.serial(),
- shipping_item.m_destination_dock.serial());
+ molog(" IT %u, destination %u\n",
+ shipping_item.m_object.serial(),
+ shipping_item.m_destination_dock.serial());
}
}
#define PORTDOCK_SAVEGAME_VERSION 3
-PortDock::Loader::Loader() : m_warehouse(0)
-{
+PortDock::Loader::Loader() : m_warehouse(0) {
}
-void PortDock::Loader::load(FileRead & fr, uint8_t version)
-{
+void PortDock::Loader::load(FileRead& fr, uint8_t version) {
PlayerImmovable::Loader::load(fr);
- PortDock & pd = get<PortDock>();
+ PortDock& pd = get<PortDock>();
m_warehouse = fr.unsigned_32();
uint16_t nrdockpoints = fr.unsigned_16();
@@ -507,11 +496,10 @@
}
}
-void PortDock::Loader::load_pointers()
-{
+void PortDock::Loader::load_pointers() {
PlayerImmovable::Loader::load_pointers();
- PortDock & pd = get<PortDock>();
+ PortDock& pd = get<PortDock>();
pd.m_warehouse = &mol().get<Warehouse>(m_warehouse);
pd.m_waiting.resize(m_waiting.size());
@@ -520,11 +508,10 @@
}
}
-void PortDock::Loader::load_finish()
-{
+void PortDock::Loader::load_finish() {
PlayerImmovable::Loader::load_finish();
- PortDock & pd = get<PortDock>();
+ PortDock& pd = get<PortDock>();
if (pd.m_warehouse->get_portdock() != &pd) {
log("Inconsistent PortDock <> Warehouse link\n");
@@ -537,9 +524,7 @@
pd.init_fleet(egbase());
}
-MapObject::Loader * PortDock::load
- (EditorGameBase & egbase, MapObjectLoader & mol, FileRead & fr)
-{
+MapObject::Loader* PortDock::load(EditorGameBase& egbase, MapObjectLoader& mol, FileRead& fr) {
std::unique_ptr<Loader> loader(new Loader);
try {
@@ -551,15 +536,14 @@
loader->load(fr, version);
} else
throw GameDataError("unknown/unhandled version %u", version);
- } catch (const std::exception & e) {
+ } catch (const std::exception& e) {
throw wexception("loading portdock: %s", e.what());
}
return loader.release();
}
-void PortDock::save(EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
-{
+void PortDock::save(EditorGameBase& egbase, MapObjectSaver& mos, FileWrite& fw) {
fw.unsigned_8(HeaderPortDock);
fw.unsigned_8(PORTDOCK_SAVEGAME_VERSION);
@@ -567,7 +551,7 @@
fw.unsigned_32(mos.get_object_file_index(*m_warehouse));
fw.unsigned_16(m_dockpoints.size());
- for (const Coords& coords: m_dockpoints) {
+ for (const Coords& coords : m_dockpoints) {
write_coords_32(&fw, coords);
}
@@ -583,4 +567,4 @@
fw.unsigned_8(m_expedition_ready ? 1 : 0);
}
-} // namespace Widelands
+} // namespace Widelands
=== modified file 'src/logic/ship.cc'
--- src/logic/ship.cc 2014-09-20 09:37:47 +0000
+++ src/logic/ship.cc 2014-11-19 21:19:43 +0000
@@ -49,24 +49,24 @@
namespace Widelands {
-ShipDescr::ShipDescr
- (const char * given_name, const char * gdescname,
- const std::string & directory, Profile & prof, Section & global_s,
- const TribeDescr & gtribe)
- :
- BobDescr(MapObjectType::SHIP, given_name, gdescname, >ribe)
-{
- { // 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, >ribe) {
+ { // global options
+ Section& idle_s = prof.get_safe_section("idle");
add_animation("idle", g_gr->animations().load(directory, idle_s));
}
m_sail_anims.parse(*this, directory, prof, "sail");
- Section * sinking_s = prof.get_section("sinking");
+ Section* sinking_s = prof.get_section("sinking");
if (sinking_s)
add_animation("sinking", g_gr->animations().load(directory, *sinking_s));
- m_capacity = global_s.get_natural("capacity", 20);
+ m_capacity = global_s.get_natural("capacity", 20);
m_vision_range = global_s.get_natural("vision_range", 7);
}
@@ -74,18 +74,12 @@
return MOVECAPS_SWIM;
}
-Bob & ShipDescr::create_object() const {
+Bob& ShipDescr::create_object() const {
return *new Ship(*this);
}
-
-Ship::Ship(const ShipDescr & gdescr) :
- Bob(gdescr),
- m_window(nullptr),
- m_fleet(nullptr),
- m_economy(nullptr),
- m_ship_state(TRANSPORT)
-{
+Ship::Ship(const ShipDescr& gdescr)
+ : Bob(gdescr), m_window(nullptr), m_fleet(nullptr), m_economy(nullptr), m_ship_state(TRANSPORT) {
}
Ship::~Ship() {
@@ -104,13 +98,14 @@
return m_fleet;
}
-void Ship::init_auto_task(Game & game) {
+void Ship::init_auto_task(Game& game) {
start_task_ship(game);
}
-void Ship::init(EditorGameBase & egbase) {
+void Ship::init(EditorGameBase& egbase) {
Bob::init(egbase);
init_fleet(egbase);
+ Notifications::publish(NoteShipMessage(this, NoteShipMessage::Message::GAINED));
}
/**
@@ -118,15 +113,15 @@
* The fleet code will automatically merge us into a larger
* fleet, if one is reachable.
*/
-void Ship::init_fleet(EditorGameBase & egbase) {
+void Ship::init_fleet(EditorGameBase& egbase) {
assert(get_owner() != nullptr);
- Fleet * fleet = new Fleet(*get_owner());
+ Fleet* fleet = new Fleet(*get_owner());
fleet->add_ship(this);
fleet->init(egbase);
// fleet calls the set_fleet function appropriately
}
-void Ship::cleanup(EditorGameBase & egbase) {
+void Ship::cleanup(EditorGameBase& egbase) {
if (m_fleet) {
m_fleet->remove_ship(egbase, this);
}
@@ -136,34 +131,32 @@
m_items.pop_back();
}
+ Notifications::publish(NoteShipMessage(this, NoteShipMessage::Message::LOST));
+
Bob::cleanup(egbase);
}
/**
* This function is to be called only by @ref Fleet.
*/
-void Ship::set_fleet(Fleet * fleet) {
+void Ship::set_fleet(Fleet* fleet) {
m_fleet = fleet;
}
-void Ship::wakeup_neighbours(Game & game) {
+void Ship::wakeup_neighbours(Game& game) {
FCoords position = get_position();
Area<FCoords> area(position, 1);
- std::vector<Bob *> ships;
+ std::vector<Bob*> ships;
game.map().find_bobs(area, &ships, FindBobShip());
- for
- (std::vector<Bob *>::const_iterator it = ships.begin();
- it != ships.end(); ++it)
- {
+ for (std::vector<Bob*>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
if (*it == this)
continue;
- static_cast<Ship *>(*it)->ship_wakeup(game);
+ static_cast<Ship*>(*it)->ship_wakeup(game);
}
}
-
/**
* Standard behaviour of ships.
*
@@ -174,20 +167,20 @@
static_cast<Bob::Ptr>(&Ship::ship_update),
nullptr,
nullptr,
- true // unique task
+ true // unique task
};
-void Ship::start_task_ship(Game & game) {
+void Ship::start_task_ship(Game& game) {
push_task(game, taskShip);
top_state().ivar1 = 0;
}
-void Ship::ship_wakeup(Game & game) {
+void Ship::ship_wakeup(Game& game) {
if (get_state(taskShip))
send_signal(game, "wakeup");
}
-void Ship::ship_update(Game & game, Bob::State & state) {
+void Ship::ship_update(Game& game, Bob::State& state) {
// Handle signals
std::string signal = get_signal();
if (!signal.empty()) {
@@ -211,44 +204,43 @@
}
switch (m_ship_state) {
- case TRANSPORT:
- if (ship_update_transport(game, state))
- return;
- break;
- case EXP_FOUNDPORTSPACE:
- case EXP_SCOUTING:
- case EXP_WAITING:
- ship_update_expedition(game, state);
- break;
- case EXP_COLONIZING:
- break;
- case SINK_REQUEST:
- if (descr().is_animation_known("sinking")) {
- m_ship_state = SINK_ANIMATION;
- start_task_idle(game, descr().get_animation("sinking"), 3000);
- return;
- }
- log("Oh no... this ship has no sinking animation :(!\n");
- // fall trough
- case SINK_ANIMATION:
- // The sink animation has been played, so finally remove the ship from the map
- pop_task(game);
- remove(game);
- return;
- default:
- assert(false); // never here
+ case TRANSPORT:
+ if (ship_update_transport(game, state))
+ return;
+ break;
+ case EXP_FOUNDPORTSPACE:
+ case EXP_SCOUTING:
+ case EXP_WAITING:
+ ship_update_expedition(game, state);
+ break;
+ case EXP_COLONIZING:
+ break;
+ case SINK_REQUEST:
+ if (descr().is_animation_known("sinking")) {
+ m_ship_state = SINK_ANIMATION;
+ start_task_idle(game, descr().get_animation("sinking"), 3000);
+ return;
+ }
+ log("Oh no... this ship has no sinking animation :(!\n");
+ // fall trough
+ case SINK_ANIMATION:
+ // The sink animation has been played, so finally remove the ship from the map
+ pop_task(game);
+ remove(game);
+ return;
+ default:
+ assert(false); // never here
}
// if the real update function failed (e.g. nothing to transport), the ship goes idle
ship_update_idle(game, state);
}
-
/// updates a ships tasks in transport mode \returns false if failed to update tasks
-bool Ship::ship_update_transport(Game & game, Bob::State &) {
- Map & map = game.map();
+bool Ship::ship_update_transport(Game& game, Bob::State&) {
+ Map& map = game.map();
- PortDock * dst = get_destination(game);
+ PortDock* dst = get_destination(game);
if (!dst) {
molog("ship_update: No destination anymore.\n");
if (m_items.empty())
@@ -277,7 +269,7 @@
molog("ship_update: Go to dock %u\n", dst->serial());
- PortDock * lastdock = m_lastdock.get(game);
+ PortDock* lastdock = m_lastdock.get(game);
if (lastdock && lastdock != dst) {
molog("ship_update: Have lastdock %u\n", lastdock->serial());
@@ -332,10 +324,9 @@
return true;
}
-
/// updates a ships tasks in expedition mode
-void Ship::ship_update_expedition(Game & game, Bob::State &) {
- Map & map = game.map();
+void Ship::ship_update_expedition(Game& game, Bob::State&) {
+ Map& map = game.map();
assert(m_expedition);
@@ -343,30 +334,30 @@
FCoords position = get_position();
for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
m_expedition->swimable[dir - 1] =
- map.get_neighbour(position, dir).field->nodecaps() & MOVECAPS_SWIM;
+ map.get_neighbour(position, dir).field->nodecaps() & MOVECAPS_SWIM;
}
if (m_ship_state == EXP_SCOUTING) {
// Check surrounding fields for port buildspaces
- std::unique_ptr<std::list<Coords> > temp_port_buildspaces(new std::list<Coords>());
- MapRegion<Area<Coords> > mr(map, Area<Coords>(position, descr().vision_range()));
+ std::unique_ptr<std::list<Coords>> temp_port_buildspaces(new std::list<Coords>());
+ MapRegion<Area<Coords>> mr(map, Area<Coords>(position, descr().vision_range()));
bool new_port_space = false;
do {
if (map.is_port_space(mr.location())) {
FCoords fc = map.get_fcoords(mr.location());
- // Check whether the maximum theoretical possible NodeCap of the field is of the size big
+ // Check whether the maximum theoretical possible NodeCap of the field is of the size
+ // big
// and whether it can theoretically be a port space
- if
- ((map.get_max_nodecaps(game.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG
- ||
- map.find_portdock(fc).empty())
- {
+ if ((map.get_max_nodecaps(game.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG ||
+ map.find_portdock(fc).empty()) {
continue;
}
- // NOTE This is the place to handle enemy territory and "clearing a port space from the enemy".
- // NOTE There is a simple check for the current land owner to avoid placement of ports into enemy
+ // NOTE This is the place to handle enemy territory and "clearing a port space from the
+ // enemy".
+ // NOTE There is a simple check for the current land owner to avoid placement of ports
+ // into enemy
// NOTE territory, as "clearing" is not yet implemented.
// NOTE further it checks, whether there is a Player_immovable on one of the fields.
// TODO(unknown): handle this more gracefully concering opposing players
@@ -378,7 +369,7 @@
invalid = true;
continue;
}
- BaseImmovable * baim = coord.field->get_immovable();
+ BaseImmovable* baim = coord.field->get_immovable();
if (baim)
if (is_a(PlayerImmovable, baim)) {
invalid = true;
@@ -387,60 +378,60 @@
// Check all neighboured fields that will be used by the port
switch (step) {
- case 0:
- map.get_ln(fc, &coord);
- break;
- case 1:
- map.get_tln(fc, &coord);
- break;
- case 2:
- map.get_trn(fc, &coord);
- break;
- case 3:
- // Flag coordinate
- map.get_brn(fc, &coord);
- break;
- default:
- break;
+ case 0:
+ map.get_ln(fc, &coord);
+ break;
+ case 1:
+ map.get_tln(fc, &coord);
+ break;
+ case 2:
+ map.get_trn(fc, &coord);
+ break;
+ case 3:
+ // Flag coordinate
+ map.get_brn(fc, &coord);
+ break;
+ default:
+ break;
}
}
// Now check whether there is a flag in the surroundings of the flag position
FCoords neighb;
map.get_ln(coord, &neighb);
for (uint8_t step = 0; !invalid && step < 5; ++step) {
- BaseImmovable * baim = neighb.field->get_immovable();
+ BaseImmovable* baim = neighb.field->get_immovable();
if (baim)
if (is_a(Flag, baim)) {
invalid = true;
continue;
}
- // Check all neighboured fields but not the one already checked for a PlayerImmovable.
+ // Check all neighboured fields but not the one already checked for a
+ // PlayerImmovable.
switch (step) {
- case 0:
- map.get_bln(coord, &neighb);
- break;
- case 1:
- map.get_brn(coord, &neighb);
- break;
- case 2:
- map.get_rn(coord, &neighb);
- break;
- case 3:
- map.get_trn(coord, &neighb);
- break;
- default:
- break;
+ case 0:
+ map.get_bln(coord, &neighb);
+ break;
+ case 1:
+ map.get_brn(coord, &neighb);
+ break;
+ case 2:
+ map.get_rn(coord, &neighb);
+ break;
+ case 3:
+ map.get_trn(coord, &neighb);
+ break;
+ default:
+ break;
}
}
if (invalid)
continue;
bool pbs_saved = false;
- for
- (std::list<Coords>::const_iterator it = m_expedition->seen_port_buildspaces->begin();
- it != m_expedition->seen_port_buildspaces->end() && !pbs_saved;
- ++it)
- {
+ for (std::list<Coords>::const_iterator it =
+ m_expedition->seen_port_buildspaces->begin();
+ it != m_expedition->seen_port_buildspaces->end() && !pbs_saved;
+ ++it) {
// Check if the ship knows this port space already from its last check
if (*it == mr.location()) {
temp_port_buildspaces->push_back(mr.location());
@@ -462,10 +453,13 @@
send_message(game, "exp_port_space", msg_head, msg_body, "port.png");
}
m_expedition->seen_port_buildspaces.swap(temp_port_buildspaces);
+ if (new_port_space) {
+ Notifications::publish(NoteShipMessage(this, NoteShipMessage::Message::WAITINGFORCOMMAND));
+ }
}
}
-void Ship::ship_update_idle(Game & game, Bob::State & state) {
+void Ship::ship_update_idle(Game& game, Bob::State& state) {
if (state.ivar1) {
// We've just completed one step, so give neighbours
// a chance to move away first
@@ -475,172 +469,182 @@
return;
}
- // If we are waiting for the next transport job, check if we should move away from ships and shores
+ // If we are waiting for the next transport job, check if we should move away from ships and
+ // shores
switch (m_ship_state) {
- case TRANSPORT: {
- FCoords position = get_position();
- Map & map = game.map();
- unsigned int dirs[LAST_DIRECTION + 1];
- unsigned int dirmax = 0;
-
+ case TRANSPORT: {
+ FCoords position = get_position();
+ Map& map = game.map();
+ unsigned int dirs[LAST_DIRECTION + 1];
+ unsigned int dirmax = 0;
+
+ for (Direction dir = 0; dir <= LAST_DIRECTION; ++dir) {
+ FCoords node = dir ? map.get_neighbour(position, dir) : position;
+ dirs[dir] = node.field->nodecaps() & MOVECAPS_WALK ? 10 : 0;
+
+ Area<FCoords> area(node, 0);
+ std::vector<Bob*> ships;
+ map.find_bobs(area, &ships, FindBobShip());
+
+ for (std::vector<Bob*>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
+ if (*it == this)
+ continue;
+
+ dirs[dir] += 3;
+ }
+
+ dirmax = std::max(dirmax, dirs[dir]);
+ }
+
+ if (dirmax) {
+ unsigned int prob[LAST_DIRECTION + 1];
+ unsigned int totalprob = 0;
+
+ // The probability for moving into a given direction is also
+ // affected by the "close" directions.
for (Direction dir = 0; dir <= LAST_DIRECTION; ++dir) {
- FCoords node = dir ? map.get_neighbour(position, dir) : position;
- dirs[dir] = node.field->nodecaps() & MOVECAPS_WALK ? 10 : 0;
-
- Area<FCoords> area(node, 0);
- std::vector<Bob *> ships;
- map.find_bobs(area, &ships, FindBobShip());
-
- for (std::vector<Bob *>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
- if (*it == this)
- continue;
-
- dirs[dir] += 3;
- }
-
- dirmax = std::max(dirmax, dirs[dir]);
- }
-
- if (dirmax) {
- unsigned int prob[LAST_DIRECTION + 1];
- unsigned int totalprob = 0;
-
- // The probability for moving into a given direction is also
- // affected by the "close" directions.
- for (Direction dir = 0; dir <= LAST_DIRECTION; ++dir) {
- prob[dir] = 10 * dirmax - 10 * dirs[dir];
-
- if (dir > 0) {
- unsigned int delta = std::min(prob[dir], dirs[(dir % 6) + 1] + dirs[1 + ((dir - 1) % 6)]);
- prob[dir] -= delta;
- }
-
- totalprob += prob[dir];
- }
-
- if (totalprob == 0) {
- start_task_idle(game, descr().main_animation(), 1500);
- return;
- }
-
- unsigned int rnd = game.logic_rand() % totalprob;
- Direction dir = 0;
- while (rnd >= prob[dir]) {
- rnd -= prob[dir];
- ++dir;
- }
-
- if (dir == 0 || dir > LAST_DIRECTION) {
- start_task_idle(game, descr().main_animation(), 1500);
- return;
- }
-
- FCoords neighbour = map.get_neighbour(position, dir);
- if (!(neighbour.field->nodecaps() & MOVECAPS_SWIM)) {
- start_task_idle(game, descr().main_animation(), 1500);
- return;
- }
-
- state.ivar1 = 1;
- start_task_move(game, dir, descr().get_sail_anims(), false);
- return;
- }
- // No desire to move around, so sleep
- start_task_idle(game, descr().main_animation(), -1);
+ prob[dir] = 10 * dirmax - 10 * dirs[dir];
+
+ if (dir > 0) {
+ unsigned int delta =
+ std::min(prob[dir], dirs[(dir % 6) + 1] + dirs[1 + ((dir - 1) % 6)]);
+ prob[dir] -= delta;
+ }
+
+ totalprob += prob[dir];
+ }
+
+ if (totalprob == 0) {
+ start_task_idle(game, descr().main_animation(), 1500);
+ return;
+ }
+
+ unsigned int rnd = game.logic_rand() % totalprob;
+ Direction dir = 0;
+ while (rnd >= prob[dir]) {
+ rnd -= prob[dir];
+ ++dir;
+ }
+
+ if (dir == 0 || dir > LAST_DIRECTION) {
+ start_task_idle(game, descr().main_animation(), 1500);
+ return;
+ }
+
+ FCoords neighbour = map.get_neighbour(position, dir);
+ if (!(neighbour.field->nodecaps() & MOVECAPS_SWIM)) {
+ start_task_idle(game, descr().main_animation(), 1500);
+ return;
+ }
+
+ state.ivar1 = 1;
+ start_task_move(game, dir, descr().get_sail_anims(), false);
return;
}
- case EXP_SCOUTING: {
- if (m_expedition->island_exploration) { // Exploration of the island
- if (exp_close_to_coast()) {
- if (m_expedition->direction == 0) {
- // Make sure we know the location of the coast and use it as initial direction we come from
- m_expedition->direction = WALK_SE;
- for (uint8_t secure = 0; exp_dir_swimable(m_expedition->direction); ++secure) {
- assert(secure < 6);
- m_expedition->direction = get_cw_neighbour(m_expedition->direction);
- }
- m_expedition->direction = get_backward_dir(m_expedition->direction);
- // Save the position - this is where we start
- m_expedition->exploration_start = get_position();
- } else {
- // Check whether the island was completely surrounded
- if (get_position() == m_expedition->exploration_start) {
- std::string msg_head = _("Island Circumnavigated");
- std::string msg_body = _("An expedition ship sailed around its"
- " island without any events.");
- send_message(game, "exp_island", msg_head, msg_body,
- "ship_explore_island_cw.png");
- m_ship_state = EXP_WAITING;
- return start_task_idle(game, descr().main_animation(), 1500);
- }
+ // No desire to move around, so sleep
+ start_task_idle(game, descr().main_animation(), -1);
+ return;
+ }
+ case EXP_SCOUTING: {
+ if (m_expedition->island_exploration) { // Exploration of the island
+ if (exp_close_to_coast()) {
+ if (m_expedition->direction == 0) {
+ // Make sure we know the location of the coast and use it as initial direction we
+ // come from
+ m_expedition->direction = WALK_SE;
+ for (uint8_t secure = 0; exp_dir_swimable(m_expedition->direction); ++secure) {
+ assert(secure < 6);
+ m_expedition->direction = get_cw_neighbour(m_expedition->direction);
}
- // The ship is supposed to follow the coast as close as possible, therefore the check for
- // a swimable field begins at the neighbour field of the direction we came from.
m_expedition->direction = get_backward_dir(m_expedition->direction);
- if (m_expedition->clockwise) {
- do {
- m_expedition->direction = get_ccw_neighbour(m_expedition->direction);
- } while (!exp_dir_swimable(m_expedition->direction));
- } else {
- do {
- m_expedition->direction = get_cw_neighbour(m_expedition->direction);
- } while (!exp_dir_swimable(m_expedition->direction));
- }
- state.ivar1 = 1;
- return start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
- } else {
- // The ship got the command to scout around an island, but is not close to any island
- // Most likely the command was send as the ship was on an exploration and just leaving
- // the island - therefore we try to find the island again.
- FCoords position = get_position();
- Map & map = game.map();
- for (uint8_t dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
- FCoords neighbour = map.get_neighbour(position, dir);
- for (uint8_t sur = FIRST_DIRECTION; sur <= LAST_DIRECTION; ++sur)
- if (!(map.get_neighbour(neighbour, sur).field->nodecaps() & MOVECAPS_SWIM)) {
- // Okay we found the next coast, so now the ship should go there.
- // However, we do neither save the position as starting position, nor do we save
- // the direction we currently go. So the ship can start exploring normally
- state.ivar1 = 1;
- return start_task_move(game, dir, descr().get_sail_anims(), false);
- }
- }
- // if we are here, it seems something really strange happend.
- log("WARNING: ship was not able to start exploration. Entering WAIT mode.");
- m_ship_state = EXP_WAITING;
- return start_task_idle(game, descr().main_animation(), 1500);
- }
- } else { // scouting towards a specific direction
- if (exp_dir_swimable(m_expedition->direction)) {
- // the scouting direction is still free to move
- state.ivar1 = 1;
- start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
- return;
- }
- // coast reached
+ // Save the position - this is where we start
+ m_expedition->exploration_start = get_position();
+ } else {
+ // Check whether the island was completely surrounded
+ if (get_position() == m_expedition->exploration_start) {
+ std::string msg_head = _("Island Circumnavigated");
+ std::string msg_body = _("An expedition ship sailed around its"
+ " island without any events.");
+ send_message(
+ game, "exp_island", msg_head, msg_body, "ship_explore_island_cw.png");
+ m_ship_state = EXP_WAITING;
+ Notifications::publish(
+ NoteShipMessage(this, NoteShipMessage::Message::WAITINGFORCOMMAND));
+ return start_task_idle(game, descr().main_animation(), 1500);
+ }
+ }
+ // The ship is supposed to follow the coast as close as possible, therefore the check
+ // for
+ // a swimable field begins at the neighbour field of the direction we came from.
+ m_expedition->direction = get_backward_dir(m_expedition->direction);
+ if (m_expedition->clockwise) {
+ do {
+ m_expedition->direction = get_ccw_neighbour(m_expedition->direction);
+ } while (!exp_dir_swimable(m_expedition->direction));
+ } else {
+ do {
+ m_expedition->direction = get_cw_neighbour(m_expedition->direction);
+ } while (!exp_dir_swimable(m_expedition->direction));
+ }
+ state.ivar1 = 1;
+ return start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
+ } else {
+ // The ship got the command to scout around an island, but is not close to any island
+ // Most likely the command was send as the ship was on an exploration and just leaving
+ // the island - therefore we try to find the island again.
+ FCoords position = get_position();
+ Map& map = game.map();
+ for (uint8_t dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
+ FCoords neighbour = map.get_neighbour(position, dir);
+ for (uint8_t sur = FIRST_DIRECTION; sur <= LAST_DIRECTION; ++sur)
+ if (!(map.get_neighbour(neighbour, sur).field->nodecaps() & MOVECAPS_SWIM)) {
+ // Okay we found the next coast, so now the ship should go there.
+ // However, we do neither save the position as starting position, nor do we
+ // save
+ // the direction we currently go. So the ship can start exploring normally
+ state.ivar1 = 1;
+ return start_task_move(game, dir, descr().get_sail_anims(), false);
+ }
+ }
+ // if we are here, it seems something really strange happend.
+ log("WARNING: ship was not able to start exploration. Entering WAIT mode.");
m_ship_state = EXP_WAITING;
- start_task_idle(game, descr().main_animation(), 1500);
- // Send a message to the player, that a new coast was reached
- std::string msg_head = _("Coast Reached");
- std::string msg_body =
- _("An expedition ship reached a coast and is waiting for further commands.");
- send_message(game, "exp_coast", msg_head, msg_body, "ship_explore_island_cw.png");
+ return start_task_idle(game, descr().main_animation(), 1500);
+ }
+ } else { // scouting towards a specific direction
+ if (exp_dir_swimable(m_expedition->direction)) {
+ // the scouting direction is still free to move
+ state.ivar1 = 1;
+ start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
return;
}
+ // coast reached
+ m_ship_state = EXP_WAITING;
+ start_task_idle(game, descr().main_animation(), 1500);
+ // Send a message to the player, that a new coast was reached
+ std::string msg_head = _("Coast Reached");
+ std::string msg_body =
+ _("An expedition ship reached a coast and is waiting for further commands.");
+ send_message(game, "exp_coast", msg_head, msg_body, "ship_explore_island_cw.png");
+ Notifications::publish(NoteShipMessage(this, NoteShipMessage::Message::WAITINGFORCOMMAND));
+ return;
}
- case EXP_COLONIZING: {
- assert(m_expedition->seen_port_buildspaces && !m_expedition->seen_port_buildspaces->empty());
- BaseImmovable * baim = game.map()[m_expedition->seen_port_buildspaces->front()].get_immovable();
- assert(baim);
+ }
+ case EXP_COLONIZING: {
+ assert(m_expedition->seen_port_buildspaces && !m_expedition->seen_port_buildspaces->empty());
+ BaseImmovable* baim =
+ game.map()[m_expedition->seen_port_buildspaces->front()].get_immovable();
+ if (baim) {
upcast(ConstructionSite, cs, baim);
for (int i = m_items.size() - 1; i >= 0; --i) {
- WareInstance * ware;
- Worker * worker;
+ WareInstance* ware;
+ Worker* worker;
m_items.at(i).get(game, &ware, &worker);
if (ware) {
- // no, we don't transfer the wares, we create new ones out of air and remove the old ones ;)
- WaresQueue & wq = cs->waresqueue(ware->descr_index());
+ // no, we don't transfer the wares, we create new ones out of air and remove the old
+ // ones ;)
+ WaresQueue& wq = cs->waresqueue(ware->descr_index());
const uint32_t max = wq.get_max_fill();
const uint32_t cur = wq.get_filled();
assert(max > cur);
@@ -654,35 +658,56 @@
worker->set_location(cs);
worker->set_position(game, cs->get_position());
worker->reset_tasks(game);
- PartiallyFinishedBuilding::request_builder_callback
- (game, *cs->get_builder_request(), worker->descr().worker_index(), worker, *cs);
+ PartiallyFinishedBuilding::request_builder_callback(
+ game, *cs->get_builder_request(), worker->descr().worker_index(), worker, *cs);
m_items.resize(i);
}
}
- if (m_items.empty()) {
- m_ship_state = TRANSPORT; // That's it, expedition finished
-
- init_fleet(game);
- m_expedition.reset(nullptr);
-
- if (upcast(InteractiveGameBase, igb, game.get_ibase()))
- refresh_window(*igb);
+ } else { // it seems that port constructionsite has dissapeared
+ // Send a message to the player, that a port constructionsite is gone
+ std::string msg_head = _("New port constructionsite is gone");
+ std::string msg_body = _("Unloading of wares failed, expedition is cancelled now.");
+ send_message(game, "exp_port_space", msg_head, msg_body, "port.png");
+ send_signal(game, "cancel_expedition");
+ }
+
+ if (m_items.empty() || !baim) { // we are done, either way
+ m_ship_state = TRANSPORT; // That's it, expedition finished
+
+ // Bring us back into a fleet and a economy.
+ init_fleet(game);
+
+ // for case that there are any workers left on board
+ // (applicable when port construction space is lost)
+ Worker* worker;
+ for (ShippingItem& item : m_items) {
+ item.get(game, nullptr, &worker);
+ if (worker) {
+ worker->reset_tasks(game);
+ worker->start_task_shipping(game, nullptr);
+ }
}
- return start_task_idle(game, descr().main_animation(), 1500); // unload the next item
- }
-
- default: {
- // wait for input
- start_task_idle(game, descr().main_animation(), 1500);
- return;
- }
+
+ m_expedition.reset(nullptr);
+
+ if (upcast(InteractiveGameBase, igb, game.get_ibase()))
+ refresh_window(*igb);
+ return start_task_idle(game, descr().main_animation(), 1500);
+ }
+ }
+
+ default: {
+ // wait for input
+ start_task_idle(game, descr().main_animation(), 1500);
+ return;
+ }
}
// never here
- assert (false);
+ assert(false);
}
-void Ship::set_economy(Game & game, Economy * e) {
+void Ship::set_economy(Game& game, Economy* e) {
// Do not check here that the economy actually changed, because on loading
// we rely that wares really get reassigned our economy.
@@ -697,23 +722,23 @@
*
* @note This is supposed to be called only from the scheduling code of @ref Fleet.
*/
-void Ship::set_destination(Game & game, PortDock & pd) {
+void Ship::set_destination(Game& game, PortDock& pd) {
molog("set_destination to %u (currently %" PRIuS " items)\n", pd.serial(), m_items.size());
m_destination = &pd;
send_signal(game, "wakeup");
}
-void Ship::add_item(Game & game, const ShippingItem & item) {
+void Ship::add_item(Game& game, const ShippingItem& item) {
assert(m_items.size() < descr().get_capacity());
m_items.push_back(item);
m_items.back().set_location(game, this);
}
-void Ship::withdraw_items(Game & game, PortDock & pd, std::vector<ShippingItem> & items) {
+void Ship::withdraw_items(Game& game, PortDock& pd, std::vector<ShippingItem>& items) {
uint32_t dst = 0;
for (uint32_t src = 0; src < m_items.size(); ++src) {
- PortDock * destination = m_items[src].get_destination(game);
+ PortDock* destination = m_items[src].get_destination(game);
if (!destination || destination == &pd) {
items.push_back(m_items[src]);
} else {
@@ -726,8 +751,8 @@
/**
* Find a path to the dock @p pd and follow it without using precomputed paths.
*/
-void Ship::start_task_movetodock(Game & game, PortDock & pd) {
- Map & map = game.map();
+void Ship::start_task_movetodock(Game& game, PortDock& pd) {
+ Map& map = game.map();
StepEvalAStar se(pd.get_warehouse()->get_position());
se.m_swim = true;
se.m_conservative = false;
@@ -753,7 +778,7 @@
}
/// Prepare everything for the coming exploration
-void Ship::start_task_expedition(Game & game) {
+void Ship::start_task_expedition(Game& game) {
// Now we are waiting
m_ship_state = EXP_WAITING;
// Initialize a new, yet empty expedition
@@ -773,8 +798,8 @@
set_economy(game, m_expedition->economy.get());
for (int i = m_items.size() - 1; i >= 0; --i) {
- WareInstance * ware;
- Worker * worker;
+ WareInstance* ware;
+ Worker* worker;
m_items.at(i).get(game, &ware, &worker);
if (worker) {
worker->reset_tasks(game);
@@ -788,11 +813,12 @@
const std::string msg_head = _("Expedition Ready");
const std::string msg_body = _("An expedition ship is waiting for your commands.");
send_message(game, "exp_ready", msg_head, msg_body, "start_expedition.png");
+ Notifications::publish(NoteShipMessage(this, NoteShipMessage::Message::WAITINGFORCOMMAND));
}
/// Initializes / changes the direction of scouting to @arg direction
/// @note only called via player command
-void Ship::exp_scout_direction(Game &, uint8_t direction) {
+void Ship::exp_scout_direction(Game&, uint8_t direction) {
assert(m_expedition);
m_ship_state = EXP_SCOUTING;
m_expedition->direction = direction;
@@ -801,7 +827,7 @@
/// Initializes the construction of a port at @arg c
/// @note only called via player command
-void Ship::exp_construct_port (Game &, const Coords& c) {
+void Ship::exp_construct_port(Game&, const Coords& c) {
assert(m_expedition);
BuildingIndex port_idx = get_owner()->tribe().safe_building_index("port");
get_owner()->force_csite(c, port_idx);
@@ -810,7 +836,7 @@
/// Initializes / changes the direction the island exploration in @arg clockwise direction
/// @note only called via player command
-void Ship::exp_explore_island (Game &, bool clockwise) {
+void Ship::exp_explore_island(Game&, bool clockwise) {
assert(m_expedition);
m_ship_state = EXP_SCOUTING;
m_expedition->clockwise = clockwise;
@@ -820,9 +846,10 @@
/// Cancels a currently running expedition
/// @note only called via player command
-void Ship::exp_cancel (Game & game) {
+void Ship::exp_cancel(Game& game) {
// Running colonization has the highest priority before cancelation
// + cancelation only works if an expedition is actually running
+
if ((m_ship_state == EXP_COLONIZING) || !state_is_expedition())
return;
send_signal(game, "cancel_expedition");
@@ -834,7 +861,7 @@
// Theres nothing to be done for wares - they already changed
// economy with us and the warehouse will make sure that they are
// getting used.
- Worker * worker;
+ Worker* worker;
for (ShippingItem& item : m_items) {
item.get(game, nullptr, &worker);
if (worker) {
@@ -859,7 +886,7 @@
/// Sinks the ship
/// @note only called via player command
-void Ship::sink_ship (Game & game) {
+void Ship::sink_ship(Game& game) {
// Running colonization has the highest priority + a sink request is only valid once
if (!state_is_sinkable())
return;
@@ -869,25 +896,22 @@
close_window();
}
-void Ship::log_general_info(const EditorGameBase & egbase)
-{
+void Ship::log_general_info(const EditorGameBase& egbase) {
Bob::log_general_info(egbase);
- molog
- ("Fleet: %u, destination: %u, lastdock: %u, carrying: %" PRIuS "\n",
- m_fleet? m_fleet->serial() : 0,
- m_destination.serial(), m_lastdock.serial(),
- m_items.size());
+ molog("Fleet: %u, destination: %u, lastdock: %u, carrying: %" PRIuS "\n",
+ m_fleet ? m_fleet->serial() : 0,
+ m_destination.serial(),
+ m_lastdock.serial(),
+ m_items.size());
for (const ShippingItem& shipping_item : m_items) {
- molog
- (" IT %u, destination %u\n",
- shipping_item.m_object.serial(),
- shipping_item.m_destination_dock.serial());
+ molog(" IT %u, destination %u\n",
+ shipping_item.m_object.serial(),
+ shipping_item.m_destination_dock.serial());
}
}
-
/**
* Send a message to the owning player.
*
@@ -895,31 +919,31 @@
*
* \param msgsender a computer-readable description of why the message was sent
* \param title user-visible title of the message
- * \param description user-visible message body, will be placed in an appropriate rich-text paragraph
+ * \param description user-visible message body, will be placed in an appropriate rich-text
+ *paragraph
* \param picture picture name relative to the pics directory
*/
-void Ship::send_message
- (Game & game, const std::string & msgsender,
- const std::string & title, const std::string & description,
- const std::string & picture)
-{
+void Ship::send_message(Game& game,
+ const std::string& msgsender,
+ const std::string& title,
+ const std::string& description,
+ const std::string& picture) {
std::string rt_description;
if (picture.size() > 3) {
- rt_description = "<rt image=pics/";
+ rt_description = "<rt image=pics/";
rt_description += picture;
rt_description += "><p font-size=14 font-face=DejaVuSerif>";
} else
- rt_description = "<rt><p font-size=14 font-face=DejaVuSerif>";
+ rt_description = "<rt><p font-size=14 font-face=DejaVuSerif>";
rt_description += description;
rt_description += "</p></rt>";
- Message * msg = new Message
- (msgsender, game.get_gametime(), title, rt_description, get_position(), m_serial);
+ Message* msg =
+ new Message(msgsender, game.get_gametime(), title, rt_description, get_position(), m_serial);
get_owner()->add_message(game, *msg);
}
-
/*
==============================
@@ -930,20 +954,16 @@
#define SHIP_SAVEGAME_VERSION 4
-Ship::Loader::Loader() :
- m_lastdock(0),
- m_destination(0)
-{
+Ship::Loader::Loader() : m_lastdock(0), m_destination(0) {
}
-const Bob::Task * Ship::Loader::get_task(const std::string & name)
-{
- if (name == "shipidle" || name == "ship") return &taskShip;
+const Bob::Task* Ship::Loader::get_task(const std::string& name) {
+ if (name == "shipidle" || name == "ship")
+ return &taskShip;
return Bob::Loader::get_task(name);
}
-void Ship::Loader::load(FileRead & fr, uint8_t version)
-{
+void Ship::Loader::load(FileRead& fr, uint8_t version) {
Bob::Loader::load(fr);
if (version >= 2) {
@@ -952,15 +972,8 @@
m_ship_state = fr.unsigned_8();
// Expedition specific data
- if
- (m_ship_state == EXP_SCOUTING
- ||
- m_ship_state == EXP_WAITING
- ||
- m_ship_state == EXP_FOUNDPORTSPACE
- ||
- m_ship_state == EXP_COLONIZING)
- {
+ if (m_ship_state == EXP_SCOUTING || m_ship_state == EXP_WAITING ||
+ m_ship_state == EXP_FOUNDPORTSPACE || m_ship_state == EXP_COLONIZING) {
m_expedition.reset(new Expedition());
// Currently seen port build spaces
m_expedition->seen_port_buildspaces.reset(new std::list<Coords>());
@@ -992,11 +1005,10 @@
}
}
-void Ship::Loader::load_pointers()
-{
+void Ship::Loader::load_pointers() {
Bob::Loader::load_pointers();
- Ship & ship = get<Ship>();
+ Ship& ship = get<Ship>();
if (m_lastdock)
ship.m_lastdock = &mol().get<PortDock>(m_lastdock);
@@ -1009,11 +1021,10 @@
}
}
-void Ship::Loader::load_finish()
-{
+void Ship::Loader::load_finish() {
Bob::Loader::load_finish();
- Ship & ship = get<Ship>();
+ Ship& ship = get<Ship>();
// restore the state the ship is in
ship.m_ship_state = m_ship_state;
@@ -1023,7 +1034,8 @@
ship.m_expedition.swap(m_expedition);
ship.m_expedition->economy.reset(new Economy(*ship.get_owner()));
ship.m_economy = ship.m_expedition->economy.get();
- } else assert(m_ship_state == TRANSPORT);
+ } else
+ assert(m_ship_state == TRANSPORT);
// Workers load code set their economy to the economy of their location
// (which is a PlayerImmovable), that means that workers on ships do not get
@@ -1034,10 +1046,7 @@
ship.set_economy(ref_cast<Game>(egbase()), ship.m_economy);
}
-
-MapObject::Loader * Ship::load
- (EditorGameBase & egbase, MapObjectLoader & mol, FileRead & fr)
-{
+MapObject::Loader* Ship::load(EditorGameBase& egbase, MapObjectLoader& mol, FileRead& fr) {
std::unique_ptr<Loader> loader(new Loader);
try {
@@ -1047,32 +1056,28 @@
if (1 <= version && version <= SHIP_SAVEGAME_VERSION) {
std::string owner = fr.c_string();
std::string name = fr.c_string();
- const ShipDescr * descr = nullptr;
+ const ShipDescr* descr = nullptr;
egbase.manually_load_tribe(owner);
- if (const TribeDescr * tribe = egbase.get_tribe(owner))
- descr = dynamic_cast<const ShipDescr *>
- (tribe->get_bob_descr(name));
+ if (const TribeDescr* tribe = egbase.get_tribe(owner))
+ descr = dynamic_cast<const ShipDescr*>(tribe->get_bob_descr(name));
if (!descr)
- throw GameDataError
- ("undefined ship %s/%s", owner.c_str(), name.c_str());
+ throw GameDataError("undefined ship %s/%s", owner.c_str(), name.c_str());
loader->init(egbase, mol, descr->create_object());
loader->load(fr, version);
} else
throw GameDataError("unknown/unhandled version %u", version);
- } catch (const std::exception & e) {
+ } catch (const std::exception& e) {
throw wexception("loading ship: %s", e.what());
}
return loader.release();
}
-void Ship::save
- (EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
-{
+void Ship::save(EditorGameBase& egbase, MapObjectSaver& mos, FileWrite& fw) {
fw.unsigned_8(HeaderShip);
fw.unsigned_8(SHIP_SAVEGAME_VERSION);
@@ -1089,11 +1094,9 @@
// currently seen port buildspaces
assert(m_expedition->seen_port_buildspaces);
fw.unsigned_8(m_expedition->seen_port_buildspaces->size());
- for
- (std::list<Coords>::const_iterator it = m_expedition->seen_port_buildspaces->begin();
- it != m_expedition->seen_port_buildspaces->end();
- ++it)
- {
+ for (std::list<Coords>::const_iterator it = m_expedition->seen_port_buildspaces->begin();
+ it != m_expedition->seen_port_buildspaces->end();
+ ++it) {
write_coords_32(&fw, *it);
}
// swimability of the directions
@@ -1118,4 +1121,4 @@
}
}
-} // namespace Widelands
+} // namespace Widelands
=== modified file 'src/logic/ship.h'
--- src/logic/ship.h 2014-09-10 08:55:04 +0000
+++ src/logic/ship.h 2014-11-19 21:19:43 +0000
@@ -37,6 +37,19 @@
struct Fleet;
class PortDock;
+struct NoteShipMessage {
+ CAN_BE_SEND_AS_NOTE(NoteId::ShipMessage)
+
+ Ship* ship;
+
+ enum class Message {LOST, GAINED, WAITINGFORCOMMAND};
+ Message message;
+
+ NoteShipMessage(Ship* const init_ship, Message const init_message)
+ : ship(init_ship), message(init_message) {
+ }
+};
+
struct ShipDescr : BobDescr {
ShipDescr
(char const * name, char const * descname,
=== modified file 'src/logic/warehouse.cc'
--- src/logic/warehouse.cc 2014-09-30 05:41:55 +0000
+++ src/logic/warehouse.cc 2014-11-19 21:19:43 +0000
@@ -51,7 +51,7 @@
namespace Widelands {
-namespace {
+namespace {
static const uint32_t WORKER_WITHOUT_COST_SPAWN_INTERVAL = 2500;
@@ -69,19 +69,17 @@
} // namespace
-WarehouseSupply::~WarehouseSupply()
-{
+WarehouseSupply::~WarehouseSupply() {
if (m_economy) {
- log
- ("WarehouseSupply::~WarehouseSupply: Warehouse %u still belongs to "
- "an economy",
- m_warehouse->serial());
+ log("WarehouseSupply::~WarehouseSupply: Warehouse %u still belongs to "
+ "an economy",
+ m_warehouse->serial());
set_economy(nullptr);
}
// We're removed from the Economy. Therefore, the wares can simply
// be cleared out. The global inventory will be okay.
- m_wares .clear();
+ m_wares.clear();
m_workers.clear();
}
@@ -97,10 +95,8 @@
m_workers.set_nrwares(i);
}
-
/// Add and remove our wares and the Supply to the economies as necessary.
-void WarehouseSupply::set_economy(Economy * const e)
-{
+void WarehouseSupply::set_economy(Economy* const e) {
if (e == m_economy)
return;
@@ -127,87 +123,74 @@
}
}
-
/// Add wares and update the economy.
-void WarehouseSupply::add_wares(WareIndex const id, uint32_t const count)
-{
+void WarehouseSupply::add_wares(WareIndex const id, uint32_t const count) {
if (!count)
return;
- if (m_economy) // No economies in the editor
+ if (m_economy) // No economies in the editor
m_economy->add_wares(id, count);
m_wares.add(id, count);
}
-
/// Remove wares and update the economy.
-void WarehouseSupply::remove_wares(WareIndex const id, uint32_t const count)
-{
+void WarehouseSupply::remove_wares(WareIndex const id, uint32_t const count) {
if (!count)
return;
m_wares.remove(id, count);
- if (m_economy) // No economies in the editor
+ if (m_economy) // No economies in the editor
m_economy->remove_wares(id, count);
}
-
/// Add workers and update the economy.
-void WarehouseSupply::add_workers(WareIndex const id, uint32_t const count)
-{
+void WarehouseSupply::add_workers(WareIndex const id, uint32_t const count) {
if (!count)
return;
- if (m_economy) // No economies in the editor
+ if (m_economy) // No economies in the editor
m_economy->add_workers(id, count);
m_workers.add(id, count);
}
-
/**
* Remove workers and update the economy.
* Comments see add_workers
*/
-void WarehouseSupply::remove_workers(WareIndex const id, uint32_t const count)
-{
+void WarehouseSupply::remove_workers(WareIndex const id, uint32_t const count) {
if (!count)
return;
m_workers.remove(id, count);
- if (m_economy) // No economies in the editor
+ if (m_economy) // No economies in the editor
m_economy->remove_workers(id, count);
}
/// Return the position of the Supply, i.e. the owning Warehouse.
-PlayerImmovable * WarehouseSupply::get_position(Game &) {return m_warehouse;}
-
+PlayerImmovable* WarehouseSupply::get_position(Game&) {
+ return m_warehouse;
+}
/// Warehouse supplies are never active.
-bool WarehouseSupply::is_active() const {return false;}
+bool WarehouseSupply::is_active() const {
+ return false;
+}
-bool WarehouseSupply::has_storage() const
-{
+bool WarehouseSupply::has_storage() const {
return true;
}
-void WarehouseSupply::get_ware_type(WareWorker & /* type */, WareIndex & /* ware */) const
-{
- throw wexception
- ("WarehouseSupply::get_ware_type: calling this is nonsensical");
+void WarehouseSupply::get_ware_type(WareWorker& /* type */, WareIndex& /* ware */) const {
+ throw wexception("WarehouseSupply::get_ware_type: calling this is nonsensical");
}
-void WarehouseSupply::send_to_storage(Game &, Warehouse * /* wh */)
-{
+void WarehouseSupply::send_to_storage(Game&, Warehouse* /* wh */) {
throw wexception("WarehouseSupply::send_to_storage: should never be called");
}
-uint32_t WarehouseSupply::nr_supplies
- (const Game & game, const Request & req) const
-{
+uint32_t WarehouseSupply::nr_supplies(const Game& game, const Request& req) const {
if (req.get_type() == wwWORKER)
- return
- m_warehouse->count_workers
- (game, req.get_index(), req.get_requirements());
+ return m_warehouse->count_workers(game, req.get_index(), req.get_requirements());
// Calculate how many wares can be sent out - it might be that we need them
// ourselves. E.g. for hiring new soldiers.
@@ -217,18 +200,16 @@
// of *this* warehouse + 1 (+1 is important, as else the ware would directly
// be taken back to the warehouse as the request of the warehouse would be
// highered and would have the same value as the original request)
- int32_t const y =
- x + (req.get_priority(0) / 100)
- - (m_warehouse->get_priority(wwWARE, req.get_index()) / 100) - 1;
+ int32_t const y = x + (req.get_priority(0) / 100) -
+ (m_warehouse->get_priority(wwWARE, req.get_index()) / 100) - 1;
// But the number should never be higher than the number of wares available
if (y > x)
return x;
return (x > 0) ? x : 0;
}
-
/// Launch a ware.
-WareInstance & WarehouseSupply::launch_ware(Game & game, const Request & req) {
+WareInstance& WarehouseSupply::launch_ware(Game& game, const Request& req) {
if (req.get_type() != wwWARE)
throw wexception("WarehouseSupply::launch_ware: called for non-ware request");
if (!m_wares.stock(req.get_index()))
@@ -238,29 +219,26 @@
}
/// Launch a ware as worker.
-Worker & WarehouseSupply::launch_worker(Game & game, const Request & req)
-{
- return
- m_warehouse->launch_worker
- (game, req.get_index(), req.get_requirements());
+Worker& WarehouseSupply::launch_worker(Game& game, const Request& req) {
+ return m_warehouse->launch_worker(game, req.get_index(), req.get_requirements());
}
-
/*
==============================
Warehouse Building
==============================
*/
-
/// Warehouse Descr
-WarehouseDescr::WarehouseDescr
- (char const* const _name, char const* const _descname,
- const std::string& directory, Profile& prof, Section& global_s, const TribeDescr& _tribe)
- : BuildingDescr(MapObjectType::WAREHOUSE, _name, _descname, directory, prof, global_s, _tribe),
- m_conquers (0),
- m_heal_per_second (0)
-{
+WarehouseDescr::WarehouseDescr(char const* const _name,
+ char const* const _descname,
+ const std::string& directory,
+ Profile& prof,
+ Section& global_s,
+ const TribeDescr& _tribe)
+ : BuildingDescr(MapObjectType::WAREHOUSE, _name, _descname, directory, prof, global_s, _tribe),
+ m_conquers(0),
+ m_heal_per_second(0) {
m_heal_per_second = global_s.get_safe_int("heal_per_second");
if ((m_conquers = prof.get_safe_section("global").get_positive("conquers", 0)))
m_workarea_info[m_conquers].insert(descname() + " conquer");
@@ -272,25 +250,21 @@
==============================
*/
-Warehouse::Warehouse(const WarehouseDescr & warehouse_descr) :
- Building(warehouse_descr),
- m_supply(new WarehouseSupply(this)),
- m_next_military_act(0),
- m_portdock(nullptr)
-{
+Warehouse::Warehouse(const WarehouseDescr& warehouse_descr)
+ : Building(warehouse_descr),
+ m_supply(new WarehouseSupply(this)),
+ m_next_military_act(0),
+ m_portdock(nullptr) {
uint8_t nr_worker_types_without_cost =
- warehouse_descr.tribe().worker_types_without_cost().size();
- m_next_worker_without_cost_spawn =
- new uint32_t[nr_worker_types_without_cost];
+ warehouse_descr.tribe().worker_types_without_cost().size();
+ m_next_worker_without_cost_spawn = new uint32_t[nr_worker_types_without_cost];
for (int i = 0; i < nr_worker_types_without_cost; ++i) {
m_next_worker_without_cost_spawn[i] = never();
}
m_next_stock_remove_act = 0;
}
-
-Warehouse::~Warehouse()
-{
+Warehouse::~Warehouse() {
delete m_supply;
delete[] m_next_worker_without_cost_spawn;
}
@@ -299,22 +273,19 @@
* Try to bring the given \ref PlannedWorkers up to date with our game data.
* Return \c false if \p pw cannot be salvaged.
*/
-bool Warehouse::_load_finish_planned_worker(PlannedWorkers & pw)
-{
+bool Warehouse::_load_finish_planned_worker(PlannedWorkers& pw) {
if (pw.index == INVALID_INDEX || !(pw.index < m_supply->get_workers().get_nrwareids()))
return false;
- const WorkerDescr * w_desc = descr().tribe().get_worker_descr(pw.index);
+ const WorkerDescr* w_desc = descr().tribe().get_worker_descr(pw.index);
if (!w_desc || !w_desc->is_buildable())
return false;
- const WorkerDescr::Buildcost & cost = w_desc->buildcost();
+ const WorkerDescr::Buildcost& cost = w_desc->buildcost();
uint32_t idx = 0;
- for
- (WorkerDescr::Buildcost::const_iterator cost_it = cost.begin();
- cost_it != cost.end(); ++cost_it, ++idx)
- {
+ for (WorkerDescr::Buildcost::const_iterator cost_it = cost.begin(); cost_it != cost.end();
+ ++cost_it, ++idx) {
WareWorker type;
WareIndex ware;
ware = descr().tribe().ware_index(cost_it->first);
@@ -326,13 +297,10 @@
return false;
if (idx < pw.requests.size()) {
- if
- (pw.requests[idx]->get_type() == type &&
- pw.requests[idx]->get_index() == ware)
+ if (pw.requests[idx]->get_type() == type && pw.requests[idx]->get_index() == ware)
continue;
- std::vector<Request *>::iterator req_it =
- pw.requests.begin() + idx + 1;
+ std::vector<Request*>::iterator req_it = pw.requests.begin() + idx + 1;
while (req_it != pw.requests.end()) {
if ((*req_it)->get_type() == type && (*req_it)->get_index() == ware)
break;
@@ -345,19 +313,16 @@
}
}
- log
- ("_load_finish_planned_worker: old savegame: "
- "need to create new request for '%s'\n",
- cost_it->first.c_str());
- pw.requests.insert
- (pw.requests.begin() + idx,
- new Request(*this, ware, &Warehouse::request_cb, type));
+ log("_load_finish_planned_worker: old savegame: "
+ "need to create new request for '%s'\n",
+ cost_it->first.c_str());
+ pw.requests.insert(
+ pw.requests.begin() + idx, new Request(*this, ware, &Warehouse::request_cb, type));
}
while (pw.requests.size() > idx) {
- log
- ("_load_finish_planned_worker: old savegame: "
- "removing outdated request.\n");
+ log("_load_finish_planned_worker: old savegame: "
+ "removing outdated request.\n");
delete pw.requests.back();
pw.requests.pop_back();
}
@@ -365,32 +330,30 @@
return true;
}
-void Warehouse::load_finish(EditorGameBase & egbase) {
+void Warehouse::load_finish(EditorGameBase& egbase) {
Building::load_finish(egbase);
uint32_t next_spawn = never();
- const std::vector<WareIndex> & worker_types_without_cost =
- descr().tribe().worker_types_without_cost();
+ const std::vector<WareIndex>& worker_types_without_cost =
+ descr().tribe().worker_types_without_cost();
for (uint8_t i = worker_types_without_cost.size(); i;) {
WareIndex const worker_index = worker_types_without_cost.at(--i);
- if
- (owner().is_worker_type_allowed(worker_index) &&
- m_next_worker_without_cost_spawn[i] == static_cast<uint32_t>(never()))
- {
+ if (owner().is_worker_type_allowed(worker_index) &&
+ m_next_worker_without_cost_spawn[i] == static_cast<uint32_t>(never())) {
if (next_spawn == static_cast<uint32_t>(never()))
- next_spawn =
- schedule_act
- (ref_cast<Game, EditorGameBase>(egbase),
- WORKER_WITHOUT_COST_SPAWN_INTERVAL);
+ next_spawn = schedule_act(
+ ref_cast<Game, EditorGameBase>(egbase), WORKER_WITHOUT_COST_SPAWN_INTERVAL);
m_next_worker_without_cost_spawn[i] = next_spawn;
- log
- ("WARNING: player %u is allowed to create worker type %s but his "
- "%s %u at (%i, %i) does not have a next_spawn time set for that "
- "worker type; setting it to %u\n",
- owner().player_number(),
- descr().tribe().get_worker_descr(worker_index)->descname().c_str(),
- descr().descname().c_str(), serial(), get_position().x, get_position().y,
- next_spawn);
+ log("WARNING: player %u is allowed to create worker type %s but his "
+ "%s %u at (%i, %i) does not have a next_spawn time set for that "
+ "worker type; setting it to %u\n",
+ owner().player_number(),
+ descr().tribe().get_worker_descr(worker_index)->descname().c_str(),
+ descr().descname().c_str(),
+ serial(),
+ get_position().x,
+ get_position().y,
+ next_spawn);
}
}
@@ -408,13 +371,12 @@
}
}
-void Warehouse::init(EditorGameBase & egbase)
-{
+void Warehouse::init(EditorGameBase& egbase) {
Building::init(egbase);
- WareIndex const nr_wares = descr().tribe().get_nrwares ();
+ WareIndex const nr_wares = descr().tribe().get_nrwares();
WareIndex const nr_workers = descr().tribe().get_nrworkers();
- m_supply->set_nrwares (nr_wares);
+ m_supply->set_nrwares(nr_wares);
m_supply->set_nrworkers(nr_workers);
m_ware_policy.resize(nr_wares, SP_Normal);
@@ -423,17 +385,15 @@
// Even though technically, a warehouse might be completely empty,
// we let warehouse see always for simplicity's sake (since there's
// almost always going to be a carrier inside, that shouldn't hurt).
- Player & player = owner();
+ Player& player = owner();
if (upcast(Game, game, &egbase)) {
- player.see_area
- (Area<FCoords>
- (egbase.map().get_fcoords(get_position()), descr().vision_range()));
+ player.see_area(
+ Area<FCoords>(egbase.map().get_fcoords(get_position()), descr().vision_range()));
{
- uint32_t const act_time = schedule_act
- (*game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
- const std::vector<WareIndex> & worker_types_without_cost =
- descr().tribe().worker_types_without_cost();
+ uint32_t const act_time = schedule_act(*game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
+ const std::vector<WareIndex>& worker_types_without_cost =
+ descr().tribe().worker_types_without_cost();
for (size_t i = 0; i < worker_types_without_cost.size(); ++i) {
if (owner().is_worker_type_allowed(worker_types_without_cost.at(i))) {
@@ -444,30 +404,25 @@
// m_next_military_act is not touched in the loading code. Is only needed
// if there warehous is created in the game? I assume it's for the
// conquer_radius thing
- m_next_military_act =
- schedule_act
- (ref_cast<Game, EditorGameBase>(egbase), 1000);
-
- m_next_stock_remove_act =
- schedule_act
- (ref_cast<Game, EditorGameBase>(egbase), 4000);
-
- log("Message: adding (wh) (%s) %i \n", to_string(descr().type()).c_str(), player.player_number());
- send_message
- (ref_cast<Game, EditorGameBase>(egbase),
- "warehouse",
- descr().descname(),
- (boost::format(_("A new %s was added to your economy."))
- % descr().descname().c_str()).str(),
- true);
- }
+ m_next_military_act = schedule_act(ref_cast<Game, EditorGameBase>(egbase), 1000);
+
+ m_next_stock_remove_act = schedule_act(ref_cast<Game, EditorGameBase>(egbase), 4000);
+
+ log("Message: adding (wh) (%s) %i \n",
+ to_string(descr().type()).c_str(),
+ player.player_number());
+ send_message(ref_cast<Game, EditorGameBase>(egbase),
+ "warehouse",
+ descr().descname(),
+ (boost::format(_("A new %s was added to your economy.")) %
+ descr().descname().c_str()).str(),
+ true);
+ }
if (uint32_t const conquer_radius = descr().get_conquers())
- egbase.conquer_area
- (PlayerArea<Area<FCoords> >
- (player.player_number(),
- Area<FCoords>
- (egbase.map().get_fcoords(get_position()), conquer_radius)));
+ egbase.conquer_area(PlayerArea<Area<FCoords>>(
+ player.player_number(),
+ Area<FCoords>(egbase.map().get_fcoords(get_position()), conquer_radius)));
if (descr().get_isport())
init_portdock(egbase);
@@ -477,14 +432,15 @@
* Find a contiguous set of water fields close to the port for docking
* and initialize the @ref PortDock instance.
*/
-void Warehouse::init_portdock(EditorGameBase & egbase)
-{
+void Warehouse::init_portdock(EditorGameBase& egbase) {
molog("Setting up port dock fields\n");
- Map & map = egbase.map();
+ Map& map = egbase.map();
std::vector<Coords> dock = map.find_portdock(get_position());
if (dock.empty()) {
- log("Attempting to setup port without neighboring water.\n");
+ log("Attempting to setup port without neighboring water (coords: %3dx%3d).\n",
+ get_position().x,
+ get_position().y);
return;
}
@@ -502,16 +458,30 @@
m_portdock->set_economy(get_economy());
}
-void Warehouse::destroy(EditorGameBase & egbase)
-{
+void Warehouse::destroy(EditorGameBase& egbase) {
Building::destroy(egbase);
}
+// if the port still exists and we are in game we first try to restore the portdock
+void Warehouse::restore_portdock_or_destroy(EditorGameBase& egbase) {
+ // re-init the portdock
+ Warehouse::init_portdock(egbase);
+ if (!m_portdock) {
+ log(" Portdock lost, removing the port now (coords: %3dx%3d)\n",
+ get_position().x,
+ get_position().y);
+ Building::destroy(egbase);
+ }
+}
+
/// Destroy the warehouse.
-void Warehouse::cleanup(EditorGameBase & egbase)
-{
+void Warehouse::cleanup(EditorGameBase& egbase) {
+
+ // storing object of the portdock if exists
+ PortDock* pd = nullptr;
+
if (egbase.objects().object_still_available(m_portdock)) {
- m_portdock->remove(egbase);
+ pd = m_portdock;
m_portdock = nullptr;
}
@@ -536,21 +506,32 @@
Map& map = egbase.map();
if (const uint32_t conquer_radius = descr().get_conquers())
- egbase.unconquer_area
- (PlayerArea<Area<FCoords> >
- (owner().player_number(),
- Area<FCoords>(map.get_fcoords(get_position()), conquer_radius)),
- m_defeating_player);
+ egbase.unconquer_area(
+ PlayerArea<Area<FCoords>>(owner().player_number(),
+ Area<FCoords>(map.get_fcoords(get_position()), conquer_radius)),
+ m_defeating_player);
// Unsee the area that we started seeing in init()
- Player & player = owner();
- player.unsee_area
- (Area<FCoords>(map.get_fcoords(get_position()), descr().vision_range()));
+ Player& player = owner();
+ player.unsee_area(Area<FCoords>(map.get_fcoords(get_position()), descr().vision_range()));
+
+ log("Message: removing %s (player %i)\n",
+ to_string(descr().type()).c_str(),
+ player.player_number());
+ send_message(ref_cast<Game, EditorGameBase>(egbase),
+ "warehouse",
+ descr().descname(),
+ (boost::format(_("A %s was destroyed.")) % descr().descname().c_str()).str(),
+ true);
Building::cleanup(egbase);
+
+ // if there was a portdock, removing it now
+ if (pd) {
+ pd->remove(egbase);
+ }
}
-
/// Act regularly to create workers of buildable types without cost. According
/// to intelligence, this is some highly advanced technology. Not only do the
/// settlers have no problems with birth control, they do not even need anybody
@@ -558,12 +539,11 @@
/// what the hell are they doing, killing useless tribesmen! The Borg? Or just
/// like Soylent Green? Or maybe I should just stop writing comments that late
/// at night ;-)
-void Warehouse::act(Game & game, uint32_t const data)
-{
+void Warehouse::act(Game& game, uint32_t const data) {
uint32_t const gametime = game.get_gametime();
{
- const std::vector<WareIndex> & worker_types_without_cost =
- owner().tribe().worker_types_without_cost();
+ const std::vector<WareIndex>& worker_types_without_cost =
+ owner().tribe().worker_types_without_cost();
for (size_t i = worker_types_without_cost.size(); i;)
if (m_next_worker_without_cost_spawn[--i] <= gametime) {
WareIndex const id = worker_types_without_cost.at(i);
@@ -581,8 +561,7 @@
remove_workers(id, 1);
}
- m_next_worker_without_cost_spawn[i] =
- schedule_act(game, tdelta);
+ m_next_worker_without_cost_spawn[i] = schedule_act(game, tdelta);
} else
m_next_worker_without_cost_spawn[i] = never();
}
@@ -593,19 +572,15 @@
WareIndex const ware = descr().tribe().safe_worker_index("soldier");
if (m_incorporated_workers.count(ware)) {
- WorkerList & soldiers = m_incorporated_workers[ware];
+ WorkerList& soldiers = m_incorporated_workers[ware];
uint32_t total_heal = descr().get_heal_per_second();
// Using an explicit iterator, as we plan to erase some
// of those guys
- for
- (WorkerList::iterator it = soldiers.begin();
- it != soldiers.end();
- ++it)
- {
+ for (WorkerList::iterator it = soldiers.begin(); it != soldiers.end(); ++it) {
// This is a safe cast: we know only soldiers can land in this
// slot in the incorporated array
- Soldier * soldier = static_cast<Soldier *>(*it);
+ Soldier* soldier = static_cast<Soldier*>(*it);
// Soldier dead ...
if (!soldier || soldier->get_current_hitpoints() == 0) {
@@ -618,7 +593,6 @@
soldier->heal(total_heal);
continue;
}
-
}
}
m_next_military_act = schedule_act(game, 1000);
@@ -639,11 +613,9 @@
Building::act(game, data);
}
-
/// Transfer our registration to the new economy.
-void Warehouse::set_economy(Economy * const e)
-{
- Economy * const old = get_economy();
+void Warehouse::set_economy(Economy* const e) {
+ Economy* const old = get_economy();
if (old == e)
return;
@@ -657,7 +629,7 @@
Building::set_economy(e);
for (const PlannedWorkers& pw : m_planned_workers) {
- for (Request * req : pw.requests) {
+ for (Request* req : pw.requests) {
req->set_economy(e);
}
}
@@ -669,82 +641,62 @@
e->add_warehouse(*this);
}
-
-const WareList & Warehouse::get_wares() const
-{
+const WareList& Warehouse::get_wares() const {
return m_supply->get_wares();
}
-
-const WareList & Warehouse::get_workers() const
-{
+const WareList& Warehouse::get_workers() const {
return m_supply->get_workers();
}
-PlayerImmovable::Workers Warehouse::get_incorporated_workers()
-{
+PlayerImmovable::Workers Warehouse::get_incorporated_workers() {
PlayerImmovable::Workers all_workers;
for (const std::pair<WareIndex, WorkerList>& worker_pair : m_incorporated_workers) {
- for (Worker * worker : worker_pair.second) {
+ for (Worker* worker : worker_pair.second) {
all_workers.push_back(worker);
}
}
return all_workers;
}
-
/// Magically create wares in this warehouse. Updates the economy accordingly.
-void Warehouse::insert_wares(WareIndex const id, uint32_t const count)
-{
+void Warehouse::insert_wares(WareIndex const id, uint32_t const count) {
m_supply->add_wares(id, count);
}
-
/// Magically destroy wares.
-void Warehouse::remove_wares(WareIndex const id, uint32_t const count)
-{
+void Warehouse::remove_wares(WareIndex const id, uint32_t const count) {
m_supply->remove_wares(id, count);
}
-
/// Magically create workers in this warehouse. Updates the economy accordingly.
-void Warehouse::insert_workers(WareIndex const id, uint32_t const count)
-{
+void Warehouse::insert_workers(WareIndex const id, uint32_t const count) {
m_supply->add_workers(id, count);
}
-
/// Magically destroy workers.
-void Warehouse::remove_workers(WareIndex const id, uint32_t const count)
-{
+void Warehouse::remove_workers(WareIndex const id, uint32_t const count) {
m_supply->remove_workers(id, count);
}
-
-
/// Launch a carrier to fetch an ware from our flag.
-bool Warehouse::fetch_from_flag(Game & game)
-{
+bool Warehouse::fetch_from_flag(Game& game) {
WareIndex const carrierid = descr().tribe().safe_worker_index("carrier");
- if (!m_supply->stock_workers(carrierid)) // XXX yep, let's cheat
+ if (!m_supply->stock_workers(carrierid)) // XXX yep, let's cheat
insert_workers(carrierid, 1);
- launch_worker(game, carrierid, Requirements()).start_task_fetchfromflag
- (game);
+ launch_worker(game, carrierid, Requirements()).start_task_fetchfromflag(game);
return true;
}
-
/**
* \return the number of workers that we can launch satisfying the given
* requirements.
*/
-uint32_t Warehouse::count_workers
- (const Game & /* game */, WareIndex ware, const Requirements & req)
-{
+uint32_t Warehouse::count_workers(const Game& /* game */, WareIndex ware, const Requirements& req) {
uint32_t sum = 0;
do {
@@ -752,7 +704,7 @@
// NOTE: This code lies about the TrainingAttributes of non-instantiated workers.
if (m_incorporated_workers.count(ware)) {
- for (Worker * worker : m_incorporated_workers[ware]) {
+ for (Worker* worker : m_incorporated_workers[ware]) {
if (!req.check(*worker)) {
// This is one of the workers in our sum.
// But he is too stupid for this job
@@ -769,9 +721,7 @@
/// Start a worker of a given type. The worker will
/// be assigned a job by the caller.
-Worker & Warehouse::launch_worker
- (Game & game, WareIndex ware, const Requirements & req)
-{
+Worker& Warehouse::launch_worker(Game& game, WareIndex ware, const Requirements& req) {
do {
if (m_supply->stock_workers(ware)) {
uint32_t unincorporated = m_supply->stock_workers(ware);
@@ -784,15 +734,15 @@
remove_no_longer_existing_workers(game, &m_incorporated_workers[ware]);
WorkerList& incorporated_workers = m_incorporated_workers[ware];
- for (std::vector<Worker *>::iterator worker_iter = incorporated_workers.begin();
- worker_iter != incorporated_workers.end(); ++worker_iter)
- {
+ for (std::vector<Worker*>::iterator worker_iter = incorporated_workers.begin();
+ worker_iter != incorporated_workers.end();
+ ++worker_iter) {
Worker* worker = *worker_iter;
--unincorporated;
if (req.check(*worker)) {
- worker->reset_tasks(game); // forget everything you did
- worker->set_location(this); // back in a economy
+ worker->reset_tasks(game); // forget everything you did
+ worker->set_location(this); // back in a economy
incorporated_workers.erase(worker_iter);
m_supply->remove_workers(ware, 1);
@@ -807,7 +757,7 @@
// Create a new one
// NOTE: This code lies about the TrainingAttributes of the new worker
m_supply->remove_workers(ware, 1);
- const WorkerDescr & workerdescr = *descr().tribe().get_worker_descr(ware);
+ const WorkerDescr& workerdescr = *descr().tribe().get_worker_descr(ware);
return workerdescr.create(game, owner(), this, m_position);
}
}
@@ -820,13 +770,10 @@
}
} while (ware != INVALID_INDEX);
- throw wexception
- ("Warehouse::launch_worker: worker does not actually exist");
+ throw wexception("Warehouse::launch_worker: worker does not actually exist");
}
-
-void Warehouse::incorporate_worker(EditorGameBase & egbase, Worker* w)
-{
+void Warehouse::incorporate_worker(EditorGameBase& egbase, Worker* w) {
assert(w != nullptr);
assert(w->get_owner() == &owner());
@@ -852,10 +799,10 @@
// Incorporate the worker
if (!m_incorporated_workers.count(worker_index))
- m_incorporated_workers[worker_index] = std::vector<Worker *>();
+ m_incorporated_workers[worker_index] = std::vector<Worker*>();
m_incorporated_workers[worker_index].push_back(w);
- w->set_location(nullptr); // no longer in an economy
+ w->set_location(nullptr); // no longer in an economy
if (upcast(Game, game, &egbase)) {
// Bind the worker into this house, hide him on the map.
@@ -866,9 +813,9 @@
/// Create an instance of a ware and make sure it gets
/// carried out of the warehouse.
-WareInstance & Warehouse::launch_ware(Game & game, WareIndex const ware_index) {
+WareInstance& Warehouse::launch_ware(Game& game, WareIndex const ware_index) {
// Create the ware
- WareInstance & ware = *new WareInstance(ware_index, descr().tribe().get_ware_descr(ware_index));
+ WareInstance& ware = *new WareInstance(ware_index, descr().tribe().get_ware_descr(ware_index));
ware.init(game);
do_launch_ware(game, ware);
@@ -877,15 +824,13 @@
return ware;
}
-
/// Get a carrier to actually move this ware out of the warehouse.
-void Warehouse::do_launch_ware(Game & game, WareInstance & ware)
-{
+void Warehouse::do_launch_ware(Game& game, WareInstance& ware) {
// Create a carrier
WareIndex const carrierid = descr().tribe().worker_index("carrier");
- const WorkerDescr & workerdescr = *descr().tribe().get_worker_descr(carrierid);
+ const WorkerDescr& workerdescr = *descr().tribe().get_worker_descr(carrierid);
- Worker & worker = workerdescr.create(game, owner(), this, m_position);
+ Worker& worker = workerdescr.create(game, owner(), this, m_position);
// Yup, this is cheating.
if (m_supply->stock_workers(carrierid))
@@ -895,23 +840,15 @@
worker.start_task_dropoff(game, ware);
}
-
-void Warehouse::incorporate_ware(EditorGameBase & egbase, WareInstance* ware)
-{
+void Warehouse::incorporate_ware(EditorGameBase& egbase, WareInstance* ware) {
m_supply->add_wares(ware->descr_index(), 1);
ware->destroy(egbase);
}
-
/// Called when a transfer for one of the idle Requests completes.
-void Warehouse::request_cb
- (Game & game,
- Request &,
- WareIndex const ware,
- Worker * const w,
- PlayerImmovable & target)
-{
- Warehouse & wh = ref_cast<Warehouse, PlayerImmovable>(target);
+void Warehouse::request_cb(
+ Game& game, Request&, WareIndex const ware, Worker* const w, PlayerImmovable& target) {
+ Warehouse& wh = ref_cast<Warehouse, PlayerImmovable>(target);
if (w) {
w->schedule_incorporate(game);
@@ -928,38 +865,35 @@
/**
* Receive a ware from a transfer that was not associated to a \ref Request.
*/
-void Warehouse::receive_ware(Game & /* game */, WareIndex ware)
-{
+void Warehouse::receive_ware(Game& /* game */, WareIndex ware) {
m_supply->add_wares(ware, 1);
}
/**
* Receive a worker from a transfer that was not associated to a \ref Request.
*/
-void Warehouse::receive_worker(Game & game, Worker & worker)
-{
+void Warehouse::receive_worker(Game& game, Worker& worker) {
worker.schedule_incorporate(game);
}
-Building & WarehouseDescr::create_object() const {
+Building& WarehouseDescr::create_object() const {
return *new Warehouse(*this);
}
-
-bool Warehouse::can_create_worker(Game &, WareIndex const worker) const {
+bool Warehouse::can_create_worker(Game&, WareIndex const worker) const {
if (!(worker < m_supply->get_workers().get_nrwareids()))
- throw wexception
- ("worker type %d does not exists (max is %d)",
- worker, m_supply->get_workers().get_nrwareids());
+ throw wexception("worker type %d does not exists (max is %d)",
+ worker,
+ m_supply->get_workers().get_nrwareids());
- const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(worker);
+ const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(worker);
assert(&w_desc);
if (!w_desc.is_buildable())
return false;
// see if we have the resources
for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
- const std::string & input_name = buildcost.first;
+ const std::string& input_name = buildcost.first;
WareIndex id_w = descr().tribe().ware_index(input_name);
if (id_w != INVALID_INDEX) {
if (m_supply->stock_wares(id_w) < buildcost.second)
@@ -968,27 +902,26 @@
if (m_supply->stock_workers(id_w) < buildcost.second)
return false;
} else
- throw wexception
- ("worker type %s needs \"%s\" to be built but that is neither "
- "a ware type nor a worker type defined in the tribe %s",
- w_desc.descname().c_str(), input_name.c_str(),
- descr().tribe().name().c_str());
+ throw wexception("worker type %s needs \"%s\" to be built but that is neither "
+ "a ware type nor a worker type defined in the tribe %s",
+ w_desc.descname().c_str(),
+ input_name.c_str(),
+ descr().tribe().name().c_str());
}
return true;
}
-
-void Warehouse::create_worker(Game & game, WareIndex const worker) {
- assert(can_create_worker (game, worker));
-
- const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(worker);
+void Warehouse::create_worker(Game& game, WareIndex const worker) {
+ assert(can_create_worker(game, worker));
+
+ const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(worker);
for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
- const std::string & input = buildcost.first;
+ const std::string& input = buildcost.first;
WareIndex const id_ware = descr().tribe().ware_index(input);
if (id_ware != INVALID_INDEX) {
- remove_wares (id_ware, buildcost.second);
- //update statistic accordingly
+ remove_wares(id_ware, buildcost.second);
+ // update statistic accordingly
owner().ware_consumed(id_ware, buildcost.second);
} else
remove_workers(descr().tribe().safe_worker_index(input), buildcost.second);
@@ -1010,8 +943,7 @@
* Return the number of workers of the given type that we plan to
* create in this warehouse.
*/
-uint32_t Warehouse::get_planned_workers(Game & /* game */, WareIndex index) const
-{
+uint32_t Warehouse::get_planned_workers(Game& /* game */, WareIndex index) const {
for (const PlannedWorkers& pw : m_planned_workers) {
if (pw.index == index)
return pw.amount;
@@ -1025,23 +957,21 @@
*
* This is the current stock plus any incoming transfers.
*/
-std::vector<uint32_t> Warehouse::calc_available_for_worker
- (Game & /* game */, WareIndex index) const
-{
- const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(index);
+std::vector<uint32_t> Warehouse::calc_available_for_worker(Game& /* game */,
+ WareIndex index) const {
+ const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(index);
std::vector<uint32_t> available;
for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
- const std::string & input_name = buildcost.first;
+ const std::string& input_name = buildcost.first;
WareIndex id_w = descr().tribe().ware_index(input_name);
if (id_w != INVALID_INDEX) {
available.push_back(get_wares().stock(id_w));
} else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
available.push_back(get_workers().stock(id_w));
} else
- throw wexception
- ("Economy::_create_requested_worker: buildcost inconsistency '%s'",
- input_name.c_str());
+ throw wexception(
+ "Economy::_create_requested_worker: buildcost inconsistency '%s'", input_name.c_str());
}
for (const PlannedWorkers& pw : m_planned_workers) {
@@ -1057,14 +987,12 @@
return available;
}
-
/**
* Set the amount of workers we plan to create
* of the given \p index to \p amount.
*/
-void Warehouse::plan_workers(Game & game, WareIndex index, uint32_t amount)
-{
- PlannedWorkers * pw = nullptr;
+void Warehouse::plan_workers(Game& game, WareIndex index, uint32_t amount) {
+ PlannedWorkers* pw = nullptr;
for (PlannedWorkers& planned_worker : m_planned_workers) {
if (planned_worker.index == index) {
@@ -1082,22 +1010,17 @@
pw->index = index;
pw->amount = 0;
- const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(pw->index);
+ const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(pw->index);
for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
- const std::string & input_name = buildcost.first;
+ const std::string& input_name = buildcost.first;
WareIndex id_w = descr().tribe().ware_index(input_name);
if (id_w != INVALID_INDEX) {
- pw->requests.push_back
- (new Request
- (*this, id_w, &Warehouse::request_cb, wwWARE));
+ pw->requests.push_back(new Request(*this, id_w, &Warehouse::request_cb, wwWARE));
} else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
- pw->requests.push_back
- (new Request
- (*this, id_w, &Warehouse::request_cb, wwWORKER));
+ pw->requests.push_back(new Request(*this, id_w, &Warehouse::request_cb, wwWORKER));
} else
- throw wexception
- ("plan_workers: bad buildcost '%s'", input_name.c_str());
+ throw wexception("plan_workers: bad buildcost '%s'", input_name.c_str());
}
}
@@ -1109,10 +1032,8 @@
* See if we can create the workers of the given plan,
* and update requests accordingly.
*/
-void Warehouse::_update_planned_workers
- (Game & game, Warehouse::PlannedWorkers & pw)
-{
- const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(pw.index);
+void Warehouse::_update_planned_workers(Game& game, Warehouse::PlannedWorkers& pw) {
+ const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(pw.index);
while (pw.amount && can_create_worker(game, pw.index)) {
create_worker(game, pw.index);
@@ -1121,7 +1042,7 @@
uint32_t idx = 0;
for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
- const std::string & input_name = buildcost.first;
+ const std::string& input_name = buildcost.first;
uint32_t supply;
WareIndex id_w = descr().tribe().ware_index(input_name);
@@ -1130,14 +1051,12 @@
} else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
supply = m_supply->stock_workers(id_w);
} else
- throw wexception
- ("_update_planned_workers: bad buildcost '%s'", input_name.c_str());
+ throw wexception("_update_planned_workers: bad buildcost '%s'", input_name.c_str());
if (supply >= pw.amount * buildcost.second)
pw.requests[idx]->set_count(0);
else
- pw.requests[idx]->set_count
- (pw.amount * buildcost.second - supply);
+ pw.requests[idx]->set_count(pw.amount * buildcost.second - supply);
++idx;
}
@@ -1153,8 +1072,7 @@
* Needs to be called periodically, because some necessary supplies might arrive
* due to idle transfers instead of by explicit request.
*/
-void Warehouse::_update_all_planned_workers(Game & game)
-{
+void Warehouse::_update_all_planned_workers(Game& game) {
uint32_t idx = 0;
while (idx < m_planned_workers.size()) {
_update_planned_workers(game, m_planned_workers[idx]);
@@ -1168,51 +1086,35 @@
}
}
-void Warehouse::enable_spawn
- (Game & game, uint8_t const worker_types_without_cost_index)
-{
- assert
- (m_next_worker_without_cost_spawn[worker_types_without_cost_index]
- ==
- static_cast<uint32_t>(never()));
+void Warehouse::enable_spawn(Game& game, uint8_t const worker_types_without_cost_index) {
+ assert(m_next_worker_without_cost_spawn[worker_types_without_cost_index] ==
+ static_cast<uint32_t>(never()));
m_next_worker_without_cost_spawn[worker_types_without_cost_index] =
- schedule_act(game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
+ schedule_act(game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
}
-void Warehouse::disable_spawn(uint8_t const worker_types_without_cost_index)
-{
- assert
- (m_next_worker_without_cost_spawn[worker_types_without_cost_index]
- !=
- static_cast<uint32_t>(never()));
+void Warehouse::disable_spawn(uint8_t const worker_types_without_cost_index) {
+ assert(m_next_worker_without_cost_spawn[worker_types_without_cost_index] !=
+ static_cast<uint32_t>(never()));
m_next_worker_without_cost_spawn[worker_types_without_cost_index] = never();
}
-
-bool Warehouse::can_attack()
-{
+bool Warehouse::can_attack() {
return descr().get_conquers() > 0;
}
-void Warehouse::aggressor(Soldier & enemy)
-{
+void Warehouse::aggressor(Soldier& enemy) {
if (!descr().get_conquers())
return;
- Game & game = ref_cast<Game, EditorGameBase>(owner().egbase());
- Map & map = game.map();
- if
- (enemy.get_owner() == &owner() ||
- enemy.get_battle() ||
- descr().get_conquers()
- <=
- map.calc_distance(enemy.get_position(), get_position()))
+ Game& game = ref_cast<Game, EditorGameBase>(owner().egbase());
+ Map& map = game.map();
+ if (enemy.get_owner() == &owner() || enemy.get_battle() ||
+ descr().get_conquers() <= map.calc_distance(enemy.get_position(), get_position()))
return;
- if
- (game.map().find_bobs
- (Area<FCoords>(map.get_fcoords(base_flag().get_position()), 2),
- nullptr,
- FindBobEnemySoldier(&owner())))
+ if (game.map().find_bobs(Area<FCoords>(map.get_fcoords(base_flag().get_position()), 2),
+ nullptr,
+ FindBobEnemySoldier(&owner())))
return;
WareIndex const soldier_index = descr().tribe().worker_index("soldier");
@@ -1221,20 +1123,17 @@
if (!count_workers(game, soldier_index, noreq))
return;
- Soldier & defender =
- ref_cast<Soldier, Worker>(launch_worker(game, soldier_index, noreq));
+ Soldier& defender = ref_cast<Soldier, Worker>(launch_worker(game, soldier_index, noreq));
defender.start_task_defense(game, false);
}
-bool Warehouse::attack(Soldier & enemy)
-{
- Game & game = ref_cast<Game, EditorGameBase>(owner().egbase());
+bool Warehouse::attack(Soldier& enemy) {
+ Game& game = ref_cast<Game, EditorGameBase>(owner().egbase());
WareIndex const soldier_index = descr().tribe().worker_index("soldier");
Requirements noreq;
if (count_workers(game, soldier_index, noreq)) {
- Soldier & defender =
- ref_cast<Soldier, Worker>(launch_worker(game, soldier_index, noreq));
+ Soldier& defender = ref_cast<Soldier, Worker>(launch_worker(game, soldier_index, noreq));
defender.start_task_defense(game, true);
enemy.send_signal(game, "sleep");
return true;
@@ -1245,45 +1144,36 @@
return false;
}
-void Warehouse::PlannedWorkers::cleanup()
-{
+void Warehouse::PlannedWorkers::cleanup() {
while (!requests.empty()) {
delete requests.back();
requests.pop_back();
}
}
-Warehouse::StockPolicy Warehouse::get_ware_policy(WareIndex ware) const
-{
+Warehouse::StockPolicy Warehouse::get_ware_policy(WareIndex ware) const {
assert(ware < m_ware_policy.size());
return m_ware_policy[ware];
}
-Warehouse::StockPolicy Warehouse::get_worker_policy(WareIndex ware) const
-{
+Warehouse::StockPolicy Warehouse::get_worker_policy(WareIndex ware) const {
assert(ware < m_worker_policy.size());
return m_worker_policy[ware];
}
-Warehouse::StockPolicy Warehouse::get_stock_policy
- (WareWorker waretype, WareIndex wareindex) const
-{
+Warehouse::StockPolicy Warehouse::get_stock_policy(WareWorker waretype, WareIndex wareindex) const {
if (waretype == wwWORKER)
return get_worker_policy(wareindex);
else
return get_ware_policy(wareindex);
}
-
-void Warehouse::set_ware_policy(WareIndex ware, Warehouse::StockPolicy policy)
-{
+void Warehouse::set_ware_policy(WareIndex ware, Warehouse::StockPolicy policy) {
assert(ware < m_ware_policy.size());
m_ware_policy[ware] = policy;
}
-void Warehouse::set_worker_policy
- (WareIndex ware, Warehouse::StockPolicy policy)
-{
+void Warehouse::set_worker_policy(WareIndex ware, Warehouse::StockPolicy policy) {
assert(ware < m_worker_policy.size());
m_worker_policy[ware] = policy;
}
@@ -1292,8 +1182,7 @@
* Check if there are remaining wares with stock policy \ref SP_Remove,
* and remove one of them if appropriate.
*/
-void Warehouse::check_remove_stock(Game & game)
-{
+void Warehouse::check_remove_stock(Game& game) {
if (base_flag().current_wares() < base_flag().total_capacity() / 2) {
for (WareIndex ware = 0; ware < m_ware_policy.size(); ++ware) {
if (get_ware_policy(ware) != SP_Remove || !get_wares().stock(ware))
@@ -1308,7 +1197,7 @@
if (get_worker_policy(widx) != SP_Remove || !get_workers().stock(widx))
continue;
- Worker & worker = launch_worker(game, widx, Requirements());
+ Worker& worker = launch_worker(game, widx, Requirements());
worker.start_task_leavebuilding(game, true);
break;
}
@@ -1324,36 +1213,34 @@
/*
* SoldierControl implementations
*/
-std::vector<Soldier *> Warehouse::present_soldiers() const
-{
- std::vector<Soldier *> rv;
+std::vector<Soldier*> Warehouse::present_soldiers() const {
+ std::vector<Soldier*> rv;
WareIndex const ware = descr().tribe().safe_worker_index("soldier");
IncorporatedWorkers::const_iterator sidx = m_incorporated_workers.find(ware);
if (sidx != m_incorporated_workers.end()) {
- const WorkerList & soldiers = sidx->second;
+ const WorkerList& soldiers = sidx->second;
- for (Worker * temp_soldier: soldiers) {
- rv.push_back(static_cast<Soldier *>(temp_soldier));
+ for (Worker* temp_soldier : soldiers) {
+ rv.push_back(static_cast<Soldier*>(temp_soldier));
}
}
return rv;
}
-int Warehouse::incorporate_soldier(EditorGameBase & egbase, Soldier & soldier) {
+int Warehouse::incorporate_soldier(EditorGameBase& egbase, Soldier& soldier) {
incorporate_worker(egbase, &soldier);
return 0;
}
-int Warehouse::outcorporate_soldier(EditorGameBase & /* egbase */, Soldier & soldier) {
+int Warehouse::outcorporate_soldier(EditorGameBase& /* egbase */, Soldier& soldier) {
WareIndex const ware = descr().tribe().safe_worker_index("soldier");
if (m_incorporated_workers.count(ware)) {
- WorkerList & soldiers = m_incorporated_workers[ware];
+ WorkerList& soldiers = m_incorporated_workers[ware];
- WorkerList::iterator i = std::find
- (soldiers.begin(), soldiers.end(), &soldier);
+ WorkerList::iterator i = std::find(soldiers.begin(), soldiers.end(), &soldier);
soldiers.erase(i);
m_supply->remove_workers(ware, 1);
@@ -1366,13 +1253,10 @@
return 0;
}
-void Warehouse::log_general_info(const EditorGameBase & egbase)
-{
+void Warehouse::log_general_info(const EditorGameBase& egbase) {
Building::log_general_info(egbase);
if (descr().get_isport())
molog("Port dock: %u\n", m_portdock ? m_portdock->serial() : 0);
}
-
-
}
=== modified file 'src/logic/warehouse.h'
--- src/logic/warehouse.h 2014-09-19 12:54:54 +0000
+++ src/logic/warehouse.h 2014-11-19 21:19:43 +0000
@@ -136,6 +136,8 @@
void destroy(EditorGameBase &) override;
+ void restore_portdock_or_destroy(EditorGameBase &);
+
void act(Game & game, uint32_t data) override;
void set_economy(Economy *) override;
=== modified file 'src/main.cc'
--- src/main.cc 2014-09-18 18:46:22 +0000
+++ src/main.cc 2014-11-19 21:19:43 +0000
@@ -1,3 +1,40 @@
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <unistd.h>
/*
* Copyright (C) 2002-2004, 2008-2009 by the Widelands Development Team
*
=== modified file 'src/notifications/note_ids.h'
--- src/notifications/note_ids.h 2014-09-10 19:54:01 +0000
+++ src/notifications/note_ids.h 2014-11-19 21:19:43 +0000
@@ -32,6 +32,7 @@
FieldPossession,
FieldTransformed,
ProductionSiteOutOfResources,
+ ShipMessage,
};
#endif // end of include guard: WL_NOTIFICATIONS_NOTE_IDS_H
Follow ups
-
[Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: noreply, 2015-02-12
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-02-12
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2015-02-12
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-02-12
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-12
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2015-02-12
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-11
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-02-11
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-10
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-10
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-09
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-09
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-02-09
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-08
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-08
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-02-08
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-02-08
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-07
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: Tino, 2015-02-07
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-07
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-07
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2015-02-07
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-02-07
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2015-02-07
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-06
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-06
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-02-05
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2015-02-05
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-05
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-05
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-05
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-02-05
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2015-02-05
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-02-05
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-04
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-04
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2015-02-04
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-03
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-03
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-02
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2015-02-02
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-02-02
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2015-01-31
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-01-30
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2015-01-30
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-01-30
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-01-30
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-01-29
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2015-01-29
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-01-23
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-01-21
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-01-17
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-01-08
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2015-01-08
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2015-01-07
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-12-16
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-15
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-12-15
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-15
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-12-13
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-12
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-12-12
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-12
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-12-12
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-12
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2014-12-06
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-12-06
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-12-05
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-05
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-12-05
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-04
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-12-04
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-03
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2014-12-03
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-03
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: SirVer, 2014-12-03
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-02
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-01
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-01
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-12-01
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-11-30
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-11-23
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-11-22
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-11-22
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-11-22
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: GunChleoc, 2014-11-22
-
Re: [Merge] lp:~widelands-dev/widelands/seafaring-ai into lp:widelands
From: TiborB, 2014-11-19