From: <geo...@us...> - 2008-05-27 10:39:44
|
Revision: 2572 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=2572&view=rev Author: geoffthemedio Date: 2008-05-27 03:39:16 -0700 (Tue, 27 May 2008) Log Message: ----------- -Initial buggy implementation of fuel consumption when fleets move and range limits due to fuel. --Need to fix fleet move lines, which currently go from the fleet to the current system instead of the fleet's position at the end of the next turn. --Need to fix fleet move lines, which currently go to the next system on the requested path, even if the fleet has no fuel, which is misleading because it suggests the fleet will move, when it actually won't. Should reject move orders that can't be implemented. --Another reason to reject unimplementable move orders is that move orders stay in effect indefinitely if they can't be implemented, and even if fuel supply later arrives at the system so that the fleet should be able to move, it still doesn't. --There may be a crash when combat occurs, particularly if a combat destroys a ship or fleet -Added kroddn to credits for translation Modified Paths: -------------- trunk/FreeOrion/UI/FleetWnd.cpp trunk/FreeOrion/UI/MapWnd.cpp trunk/FreeOrion/UI/TechTreeWnd.cpp trunk/FreeOrion/default/credits.xml trunk/FreeOrion/default/eng_stringtable.txt trunk/FreeOrion/server/ServerApp.cpp trunk/FreeOrion/universe/Effect.cpp trunk/FreeOrion/universe/Fleet.cpp trunk/FreeOrion/universe/Fleet.h trunk/FreeOrion/universe/Planet.cpp trunk/FreeOrion/universe/Planet.h trunk/FreeOrion/universe/PopCenter.cpp trunk/FreeOrion/universe/Ship.cpp trunk/FreeOrion/universe/System.cpp trunk/FreeOrion/universe/System.h trunk/FreeOrion/universe/Universe.cpp trunk/FreeOrion/universe/UniverseObject.cpp trunk/FreeOrion/universe/UniverseObject.h Modified: trunk/FreeOrion/UI/FleetWnd.cpp =================================================================== --- trunk/FreeOrion/UI/FleetWnd.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/UI/FleetWnd.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -376,14 +376,15 @@ } } - const Ship* const m_ship; - GG::StaticGraphic* m_ship_icon; - GG::TextControl* m_ship_name_text; - StatisticIcon* m_ship_strength_stat; - StatisticIcon* m_damage_stat; - GG::StaticGraphic* m_colonizer_icon; - bool m_selected; - boost::signals::connection m_ship_connection; + const Ship* const m_ship; + GG::StaticGraphic* m_ship_icon; + GG::TextControl* m_ship_name_text; + StatisticIcon* m_ship_strength_stat; + StatisticIcon* m_damage_stat; + StatisticIcon* m_fuel_stat; + GG::StaticGraphic* m_colonizer_icon; + bool m_selected; + boost::signals::connection m_ship_connection; }; /** A ListBox::Row subclass used to represent fleets in FleetsListBox's. */ @@ -1056,18 +1057,41 @@ System* dest = m_fleet->FinalDestination(); System* current = m_fleet->GetSystem(); if (dest && dest != current) { - std::pair<int, int> eta = m_fleet->ETA(); - if (eta.first > 0) { - retval = boost::io::str(boost::format(UserString("FW_FLEET_MOVING_TO")) % (dest->Name().empty() ? UserString("UNKNOWN_SYSTEM") : dest->Name()) % eta.first); - if (eta.first != eta.second) - retval += "(" + boost::lexical_cast<std::string>(eta.second) + ")"; - } else if (eta.first == Fleet::ETA_UNKNOWN) { - retval = boost::io::str(boost::format(UserString("FW_FLEET_MOVING_TO")) % - (dest->Name().empty() ? UserString("UNKNOWN_SYSTEM") : dest->Name()) % - UserString(eta.first == Fleet::ETA_UNKNOWN ? "FW_FLEET_ETA_UNKNOWN" : "FW_FLEET_ETA_NEVER")); - } + std::pair<int, int> eta = m_fleet->ETA(); // .first is turns to final destination. .second is turns to next system on route + + // name of final destination + std::string dest_name = dest->Name(); + if (dest_name.empty()) + dest_name = UserString("UNKNOWN_SYSTEM"); + + // next system on path + std::string next_eta_text; + if (eta.second == Fleet::ETA_UNKNOWN) + next_eta_text = UserString("FW_FLEET_ETA_UNKNOWN"); + else if (eta.second == Fleet::ETA_NEVER) + next_eta_text = UserString("FW_FLEET_ETA_NEVER"); + else if (eta.second == Fleet::ETA_OUT_OF_RANGE) + next_eta_text = UserString("FW_FLEET_ETA_OUT_OF_RANGE"); + else + next_eta_text = boost::lexical_cast<std::string>(eta.second); + + // final destination + std::string final_eta_text; + if (eta.first == Fleet::ETA_UNKNOWN) + final_eta_text = UserString("FW_FLEET_ETA_UNKNOWN"); + else if (eta.first == Fleet::ETA_NEVER) + final_eta_text = UserString("FW_FLEET_ETA_NEVER"); + else if (eta.first == Fleet::ETA_OUT_OF_RANGE) + final_eta_text = UserString("FW_FLEET_ETA_OUT_OF_RANGE"); + else + final_eta_text = boost::lexical_cast<std::string>(eta.first); + + + retval = boost::io::str(FlexibleFormat(UserString("FW_FLEET_MOVING_TO")) % + dest_name % final_eta_text % next_eta_text); + } else if (current) { - retval = boost::io::str(boost::format(UserString("FW_FLEET_AT")) % current->Name()); + retval = boost::io::str(FlexibleFormat(UserString("FW_FLEET_AT")) % current->Name()); } return retval; } Modified: trunk/FreeOrion/UI/MapWnd.cpp =================================================================== --- trunk/FreeOrion/UI/MapWnd.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/UI/MapWnd.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -1824,8 +1824,11 @@ // if not done, add starting vertex for next leg of path std::list<MovePathNode>::const_iterator temp_it = path_it; - if (++temp_it != move_line.Path().end()) + if (++temp_it != move_line.Path().end()) { + if (path_it->eta >= Fleet::ETA_NEVER) // includes ETA_NEVER, ETA_UNKNOWN and ETA_OUT_OF_RANGE + break; // don't render additional legs of path that aren't reachable glVertex2d(path_it->x, path_it->y); + } } glEnd(); } @@ -1846,8 +1849,11 @@ // if not done, add starting vertex for next leg of path std::list<MovePathNode>::const_iterator temp_it = path_it; - if (++temp_it != m_projected_fleet_line.Path().end()) + if (++temp_it != m_projected_fleet_line.Path().end()) { + if (path_it->eta >= Fleet::ETA_NEVER) + break; // don't render additional legs of path that aren't reachable glVertex2d(path_it->x, path_it->y); + } } glEnd(); } Modified: trunk/FreeOrion/UI/TechTreeWnd.cpp =================================================================== --- trunk/FreeOrion/UI/TechTreeWnd.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/UI/TechTreeWnd.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -2079,7 +2079,7 @@ return; std::vector<int> col_widths = ColWidths(w); - const int GRAPHIC_WIDTH = col_widths[0]; + const int GRAPHIC_WIDTH = col_widths[0]; const int NAME_WIDTH = col_widths[1]; const int COST_WIDTH = col_widths[2]; const int TIME_WIDTH = col_widths[3]; Modified: trunk/FreeOrion/default/credits.xml =================================================================== --- trunk/FreeOrion/default/credits.xml 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/default/credits.xml 2008-05-27 10:39:16 UTC (rev 2572) @@ -67,6 +67,7 @@ <PERSON name="Ivan Sanchez" nick="Ivan s c" task="Spanish Translation"/> <PERSON name="Myckel Habets" nick="Myckel" task="Dutch Translation"/> <PERSON name="Martin Roth" nick="Captain Rage" task="Swedish Translation"/> + <PERSON name="Markus Sinner" nick="kroddn" task="German Translation"/> </GROUP> </CREDITS> </XMLDoc> Modified: trunk/FreeOrion/default/eng_stringtable.txt =================================================================== --- trunk/FreeOrion/default/eng_stringtable.txt 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/default/eng_stringtable.txt 2008-05-27 10:39:16 UTC (rev 2572) @@ -1218,7 +1218,7 @@ At %1% System FW_FLEET_MOVING_TO -Moving to %1%, ETA %2% +Moving to %1%, ETA %2% (%3%) FW_FLEET_ETA_NEVER Never @@ -1226,6 +1226,9 @@ FW_FLEET_ETA_UNKNOWN Unknown +FW_FLEET_ETA_OUT_OF_RANGE +Out of Range + FW_SHIP_CLASS Ship Class Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/server/ServerApp.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -578,7 +578,7 @@ { std::vector<CombatAssets> empire_combat_forces; System* system = *it; - + std::vector<Fleet*> flt_vec = system->FindObjects<Fleet>(); if (flt_vec.empty()) continue; // skip systems with not fleets, as these can't have combat Modified: trunk/FreeOrion/universe/Effect.cpp =================================================================== --- trunk/FreeOrion/universe/Effect.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/universe/Effect.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -116,6 +116,7 @@ // execute effects on targets for (Condition::ObjectSet::const_iterator it = targets.begin(); it != targets.end(); ++it) { + Logger().debugStream() << "effectsgroup source: " << source->Name() << " target " << (*it)->Name(); for (unsigned int i = 0; i < m_effects.size(); ++i) { m_effects[i]->Execute(source, *it); } @@ -256,6 +257,8 @@ { if (Meter* m = target->GetMeter(m_meter)) { double val = m_value->Eval(source, target); + //Logger().debugStream() << "Setting " << (m_max ? "max " : "current ") << boost::lexical_cast<std::string>(m_meter) << " meter from " + // << (m_max ? m->Max() : m->Current()) << " to " << val; m_max ? m->SetMax(val) : m->SetCurrent(val); } } Modified: trunk/FreeOrion/universe/Fleet.cpp =================================================================== --- trunk/FreeOrion/universe/Fleet.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/universe/Fleet.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -14,7 +14,8 @@ #include <cmath> namespace { - const double MAX_SHIP_SPEED = 500.0; // max allowed speed of ship movement + const double MAX_SHIP_SPEED = 500.0; // max allowed speed of ship movement + const double FLEET_MOVEMENT_EPSILON = 1.0e-5; // how close a fleet needs to be to a system to have arrived in the system inline bool SystemNotReachable(System* system, int empire_id) { return !GetUniverse().SystemReachable(system->ID(), empire_id); @@ -22,8 +23,9 @@ } // static(s) -const int Fleet::ETA_NEVER = -1; -const int Fleet::ETA_UNKNOWN = -2; +const int Fleet::ETA_UNKNOWN = (1 << 30); +const int Fleet::ETA_OUT_OF_RANGE = (1 << 30) - 1; +const int Fleet::ETA_NEVER = (1 << 30) - 2; Fleet::Fleet() : UniverseObject(), @@ -103,135 +105,199 @@ if (route.empty()) return retval; // nowhere to go => empty path if (route.size() == 2 && route.front() == route.back()) return retval; // nowhere to go => empty path - if (this->Speed() < 1.0e-5) return retval; // unable to move (epsilon taken from Fleet::MovementPhase()) - MovePathNode cur_pos(this->X(), this->Y(), true, 0); // initialize to initial position of fleet. + if (this->Speed() < FLEET_MOVEMENT_EPSILON) { // can't move => ETA is never + retval.push_back(MovePathNode(this->X(), this->Y(), true, ETA_NEVER, this->SystemID())); + return retval; + } - int running_eta = 1; // turns to each node - double this_turn_travel_dist_left = this->Speed(); - - // simulate moving fleet to each stop along path in sequence, remembering nodes at each stop and - // each time a turn's travel distance runs out - for(std::list<System*>::const_iterator next_sys_it = route.begin(); next_sys_it != route.end(); ++next_sys_it) { - const System* next_sys = *next_sys_it; + // determine fuel available to fleet (fuel of the ship that has the least fuel in the fleet) + // and determine the maximum amount of fuel that can be stored by the ship in the fleet that + // can store the least amount of fuel + const Universe& universe = GetUniverse(); + double fuel = Meter::METER_MAX, max_fuel = Meter::METER_MAX; + for (const_iterator ship_it = begin(); ship_it != end(); ++ship_it) { + const Ship* ship = universe.Object<Ship>(*ship_it); + assert(ship); + const Meter* meter = ship->GetMeter(METER_FUEL); + assert(meter); + fuel = std::min(fuel, meter->Current()); + max_fuel = std::min(max_fuel, meter->Max()); + } - if (GetSystem() && GetSystem() == next_sys) continue; // don't add system fleet starts in to the path + // determine all systems where fleet(s) can be resupplied if fuel runs out + std::set<int> fleet_supplied_systems; + const std::set<int>& owners = this->Owners(); + for (std::set<int>::const_iterator it = owners.begin(); it != owners.end(); ++it) { + const Empire* empire = Empires().Lookup(*it); + std::set<int> empire_fleet_supplied_systems; + if (empire) + empire_fleet_supplied_systems = empire->FleetSupplyableSystemIDs(); + fleet_supplied_systems.insert(empire_fleet_supplied_systems.begin(), empire_fleet_supplied_systems.end()); + } - // get direction and distance to next system - double x_dist = next_sys->X() - cur_pos.x; - double y_dist = next_sys->Y() - cur_pos.y; - double next_sys_dist = std::sqrt(x_dist * x_dist + y_dist * y_dist); - double unit_vec_x = x_dist / next_sys_dist; - double unit_vec_y = y_dist / next_sys_dist; - - - // take turn-travel-distance steps until next system is reached - while (next_sys_dist > 1.0e-5) { // epsilon taken from Fleet::MovementPhase() - if (next_sys_dist > this_turn_travel_dist_left) { - // system is further away than the fleet can travel this turn -> take the rest of this turn's movement + // node for initial position of fleet + MovePathNode cur_pos(this->X(), this->Y(), true, 0, this->SystemID()); + retval.push_back(cur_pos); - // set current position to position after this turn's movement - double step_vec_x = unit_vec_x * this_turn_travel_dist_left; - double step_vec_y = unit_vec_y * this_turn_travel_dist_left; - cur_pos.x += step_vec_x; - cur_pos.y += step_vec_y; - cur_pos.turn_end = true; // new position is at the end of a turn's movement - cur_pos.eta = running_eta; - // add new node to list - retval.push_back(cur_pos); + // get current system of fleet, if it is in a system, and next system reached in path + const System* cur_system = 0; + std::list<System*>::const_iterator route_it = route.begin(); + if ((*route_it)->ID() == SystemID()) { + cur_system = *route_it; + ++route_it; + } + if (route_it == route.end()) + return retval; + const System* next_system = *route_it; - // update distance to next system to account for this turn's movement - next_sys_dist -= this_turn_travel_dist_left; + MovePathNode next_sys_pos(next_system->X(), next_system->Y(), false, -1, next_system->SystemID()); - // next turn, can move a full turn's movement - this_turn_travel_dist_left = this->Speed(); - ++running_eta; + double dist_to_next_system = std::sqrt((next_sys_pos.x - cur_pos.x)*(next_sys_pos.x - cur_pos.x) + (next_sys_pos.y - cur_pos.y)*(next_sys_pos.y - cur_pos.y)); + double turn_dist_remaining = m_speed; // additional distance that can be travelled in current turn of fleet movement being simulated + bool new_turn = true; // does / should the next update iteration be the start of a new turn? - } else { - // system can be reached this turn - // set current position to system's position - cur_pos.x = next_sys->X(); - cur_pos.y = next_sys->Y(); - cur_pos.turn_end = false; - cur_pos.eta = running_eta; + // count turns to get to destination by simulating movement steps, accounting for fuel needs and resupply - // add new node to list - retval.push_back(cur_pos); + const int TOO_LONG = 200; // limit on turns to simulate + int turns_taken = 0; - // update distance that can still be travelled this turn - this_turn_travel_dist_left -= next_sys_dist; + while (turns_taken <= TOO_LONG) { + // check for arrival at next system on path + if (dist_to_next_system < FLEET_MOVEMENT_EPSILON) { + // update current system and position, and next system and position + cur_system = next_system; - // have arrived at system ensure inner loop ends and next system is fetched - next_sys_dist = 0.0; + cur_pos.x = next_system->X(); + cur_pos.y = next_system->Y(); + cur_pos.eta = turns_taken; + cur_pos.turn_end = false; + cur_pos.object_id = next_system->ID(); - // TO DO: Account for fuel use. If fleet has insufficient fuel, it can't move towards the next system + retval.push_back(cur_pos); + + ++route_it; + if (route_it == route.end()) + break; + + next_system = *route_it; + next_sys_pos.x = next_system->X(); + next_sys_pos.y = next_system->Y(); + next_sys_pos.eta = ETA_UNKNOWN; + next_sys_pos.turn_end = false; + next_sys_pos.object_id = next_system->ID(); + + dist_to_next_system = std::sqrt((next_sys_pos.x - cur_pos.x)*(next_sys_pos.x - cur_pos.x) + (next_sys_pos.y - cur_pos.y)*(next_sys_pos.y - cur_pos.y)); + } + + + // if this iteration is the start of a new simulated turn, distance to be travelled this turn is reset and turns taken incremented + if (new_turn) { + ++turns_taken; + cur_pos.eta = turns_taken; + turn_dist_remaining = m_speed; + } + + + // if this iteration starts at a system, the fleet must have fuel to start the next starlane jump. if the fleet + // doesn't have enough fuel to jump, it may be able to be resupplied by spending a turn in this sytem + if (cur_system) { + if (fuel >= 1.0) { + fuel -= 1.0; // can start next jump this turn. turn_dist_remaining is unchanged + new_turn = false; + } else { + turn_dist_remaining = 0.0; // can't progress this turn due to lack of fuel + + // if a new turn started this update, the fleet has a chance to get fuel by waiting for a full turn in current system + if (new_turn) { + // determine if current system is one where fuel can be supplied + std::set<int>::const_iterator it = fleet_supplied_systems.find(cur_system->ID()); + if (it != fleet_supplied_systems.end()) { + // fleet supply is available, so give it + fuel = max_fuel; + // turn_dist_remaining is zero, so new_turn will remain true; must wait a full turn without moving to refuel + } else { + // started a new turn with insufficient fuel to move, and can't get any more fuel by waiting, so can never get to destination. + turns_taken = ETA_OUT_OF_RANGE; + break; + } + } } } - } - return retval; -} -std::pair<int, int> Fleet::ETA() const -{ - // if route is unknown, ETA is unknown - if (UnknownRoute()) - return std::make_pair(ETA_UNKNOWN, ETA_UNKNOWN); - // if next system is an invalid system id, the fleet isn't moving, so ETA is 0 - if (m_next_system == UniverseObject::INVALID_OBJECT_ID) - return std::make_pair(0, 0); + // move ship as far as it can go this turn, or to next system, whichever is closer, and deduct distance travelled from distance + // travellable this turn + if (turn_dist_remaining >= FLEET_MOVEMENT_EPSILON) { + double dist_travelled_this_step = std::min(turn_dist_remaining, dist_to_next_system); - // if fleet can't move, ETA is never - if (m_speed <= 0.0) - return std::make_pair(ETA_NEVER, ETA_NEVER); + double x_dist = next_sys_pos.x - cur_pos.x; + double y_dist = next_sys_pos.y - cur_pos.y; + // dist_to_next_system = std::sqrt(x_dist * x_dist + y_dist * y_dist); // should already equal this distance, so don't need to recalculate + double unit_vec_x = x_dist / dist_to_next_system; + double unit_vec_y = y_dist / dist_to_next_system; - // otherwise, need to do calcuations to determine ETA - std::pair<int, int> retval(ETA_NEVER, ETA_NEVER); + cur_pos.x += unit_vec_x*dist_travelled_this_step; + cur_pos.y += unit_vec_y*dist_travelled_this_step; - CalculateRoute(); + turn_dist_remaining -= dist_travelled_this_step; + dist_to_next_system -= dist_travelled_this_step; - // determine fuel available to fleet (fuel of the ship that has the least fuel in the fleet) - const Universe& universe = GetUniverse(); - double fuel = Meter::METER_MAX; - for (const_iterator ship_it = begin(); ship_it != end(); ++ship_it) { - const Ship* ship = universe.Object<Ship>(*ship_it); - assert(ship); - fuel = std::min(fuel, ship->MeterPoints(METER_FUEL)); - } + if (dist_travelled_this_step >= FLEET_MOVEMENT_EPSILON && dist_to_next_system >= FLEET_MOVEMENT_EPSILON) + cur_system = 0; + } - //// if fleet has no fuel, it can't move - //if (fuel < 1.0) - // return std::make_pair(ETA_NEVER, ETA_NEVER); - // if fuel doesn't limit speed, ETA is just distance / speed - retval.first = static_cast<int>(std::ceil(m_travel_distance / m_speed)); - if (retval.first > 500) - retval.first = ETA_NEVER; // avoid overly-large ETA numbers - - if (!m_travel_route.empty()) { - std::list<System*>::iterator next_system_it = m_travel_route.begin(); - if (SystemID() == m_travel_route.front()->ID()) - ++next_system_it; - assert(next_system_it != m_travel_route.end()); - System* next = *next_system_it; - if (next == m_travel_route.back()) { - retval.second = retval.first; + // if fleet can't move, must wait until next turn for another chance to move + if (turn_dist_remaining < FLEET_MOVEMENT_EPSILON) { + turn_dist_remaining = 0.0; // to prevent any possible precision-related errors + new_turn = true; } else { - double x = next->X() - X(); - double y = next->Y() - Y(); - retval.second = static_cast<int>(std::ceil(std::sqrt(x * x + y * y) / m_speed)); + new_turn = false; } } + if (turns_taken >= TOO_LONG) { + next_sys_pos.eta = turns_taken; + next_sys_pos.turn_end = true; + retval.push_back(next_sys_pos); + } + return retval; } + +std::pair<int, int> Fleet::ETA() const +{ + return ETA(MovePath()); +} + +std::pair<int, int> Fleet::ETA(const std::list<MovePathNode>& move_path) const +{ + // check that path exists. if empty, there was no valid route or some other problem prevented pathing + if (move_path.empty()) + return std::make_pair(ETA_UNKNOWN, ETA_UNKNOWN); + + // check for single node in path. return the single node's eta as both .first and .second (likely indicates that fleet couldn't move) + if (move_path.size() == 1) { + const MovePathNode& node = *move_path.begin(); + return std::make_pair(node.eta, node.eta); + } + + // general case: there is a multi-node path. return the second (first after initial position of fleet) and last nodes' ETAs + std::list<MovePathNode>::const_iterator it = move_path.begin(); + ++it; + const MovePathNode& first = *it; + const MovePathNode& last = *move_path.rbegin(); + return std::make_pair(last.eta, first.eta); +} + int Fleet::FinalDestinationID() const { return m_moving_to; } @@ -431,6 +497,7 @@ void Fleet::SetSystem(int sys) { + Logger().debugStream() << "Fleet::MoveTo(UniverseObject* object)"; UniverseObject::SetSystem(sys); for (iterator it = begin(); it != end(); ++it) { UniverseObject* obj = GetUniverse().Object(*it); @@ -439,80 +506,166 @@ } } +void Fleet::Move(double x, double y) +{ + // move fleet itself + UniverseObject::Move(x, y); + // move ships in fleet + for (iterator it = begin(); it != end(); ++it) { + UniverseObject* obj = GetUniverse().Object(*it); + assert(obj); + obj->Move(x, y); + } +} + +void Fleet::MoveTo(UniverseObject* object) +{ + Logger().debugStream() << "Fleet::MoveTo(const UniverseObject* object)"; + UniverseObject::MoveTo(object); + // move ships in fleet + for (iterator it = begin(); it != end(); ++it) { + UniverseObject* obj = GetUniverse().Object(*it); + assert(obj); + obj->MoveTo(object); + } +} + +void Fleet::MoveTo(double x, double y) +{ + Logger().debugStream() << "Fleet::MoveTo(double x, double y)"; + // move fleet itself + UniverseObject::MoveTo(x, y); + // move ships in fleet + for (iterator it = begin(); it != end(); ++it) { + UniverseObject* obj = GetUniverse().Object(*it); + assert(obj); + obj->MoveTo(x, y); + } +} + void Fleet::MovementPhase() { - if (m_moving_to != INVALID_OBJECT_ID) { - if (m_travel_route.empty()) - CalculateRoute(); + Logger().debugStream() << "Fleet::MovementPhase this: " << this; - if (System* current_system = GetSystem()) { - if (current_system == m_travel_route.front()) - m_travel_route.pop_front(); - current_system->Remove(ID()); - SetSystem(INVALID_OBJECT_ID); - for (ShipIDSet::iterator it = m_ships.begin(); it != m_ships.end(); ++it) { - current_system->Remove(*it); - Ship* ship = GetUniverse().Object<Ship>(*it); - if (ship) ship->SetSystem(INVALID_OBJECT_ID); + // determine fuel available to fleet (fuel of the ship that has the least fuel in the fleet) + // and determine the maximum amount of fuel that can be stored by the ship in the fleet that + // can store the least amount of fuel + Universe& universe = GetUniverse(); + double fuel = Meter::METER_MAX; + for (const_iterator ship_it = begin(); ship_it != end(); ++ship_it) { + const Ship* ship = universe.Object<Ship>(*ship_it); + assert(ship); + const Meter* meter = ship->GetMeter(METER_FUEL); + assert(meter); + fuel = std::min(fuel, meter->Current()); + } + + System* current_system = GetSystem(); + + // if currently in a system, and don't have enough fuel to jump to next system or aren't + // ordered to move, can be supplied fuel this turn + if (current_system && (fuel < 1.0 || m_moving_to == INVALID_OBJECT_ID)) { + // search for this system in systems where fleet(s) can be resupplied if fuel runs out + + // get all supplyable systems + std::set<int> fleet_supplied_systems; + const std::set<int>& owners = this->Owners(); + for (std::set<int>::const_iterator it = owners.begin(); it != owners.end(); ++it) { + const Empire* empire = Empires().Lookup(*it); + std::set<int> empire_fleet_supplied_systems; + if (empire) + empire_fleet_supplied_systems = empire->FleetSupplyableSystemIDs(); + fleet_supplied_systems.insert(empire_fleet_supplied_systems.begin(), empire_fleet_supplied_systems.end()); + } + + // give fuel to ships, if fleet is supplyable at this location + if (fleet_supplied_systems.find(current_system->ID()) != fleet_supplied_systems.end()) { + for (const_iterator ship_it = begin(); ship_it != end(); ++ship_it) { + Ship* ship = universe.Object<Ship>(*ship_it); + assert(ship); + Meter* meter = ship->GetMeter(METER_FUEL); + assert(meter); + meter->SetCurrent(meter->Max()); } } + return; // can't move fleet this turn + } - System* next_system = m_travel_route.front(); - double movement_left = m_speed; - while (movement_left) { - double direction_x = next_system->X() - X(); - double direction_y = next_system->Y() - Y(); - double distance = std::sqrt(direction_x * direction_x + direction_y * direction_y); - if (distance <= movement_left) { - m_travel_route.pop_front(); - if (m_travel_route.empty()) { - MoveTo(next_system->X(), next_system->Y()); - next_system->Insert(this); - for (ShipIDSet::iterator it = m_ships.begin(); it != m_ships.end(); ++it) { - UniverseObject* ship = GetUniverse().Object(*it); - ship->MoveTo(X(), Y()); - next_system->Insert(ship); - } - movement_left = 0.0; - m_moving_to = m_prev_system = m_next_system = INVALID_OBJECT_ID; - m_travel_route.clear(); - m_travel_distance = 0.0; - } else { - MoveTo(next_system->X(), next_system->Y()); - next_system = m_travel_route.front(); - movement_left -= distance; - m_prev_system = m_next_system; - m_next_system = m_travel_route.front()->ID(); - m_travel_distance -= distance; - // if we're "at" this system (within some epsilon), insert this fleet into the system - if (std::abs(movement_left) < 1.0e-5) { - next_system->Insert(this); - for (ShipIDSet::iterator it = m_ships.begin(); it != m_ships.end(); ++it) { - UniverseObject* ship = GetUniverse().Object(*it); - ship->MoveTo(X(), Y()); - next_system->Insert(ship); - } - movement_left = 0.0; - } else { - for (ShipIDSet::iterator it = m_ships.begin(); it != m_ships.end(); ++it) { - UniverseObject* ship = GetUniverse().Object(*it); - ship->MoveTo(X(), Y()); - } - } + if (m_moving_to == INVALID_OBJECT_ID) + return; + + if (m_travel_route.empty()) + CalculateRoute(); + + if (current_system && current_system == m_travel_route.front()) + m_travel_route.pop_front(); + + // Fleet has a destination to move to, and all ships in fleet can move at least to + // the next system or a full turn's movement along a starlane, whichever is less + + System* next_system = m_travel_route.front(); + double movement_left = m_speed; + while (movement_left > FLEET_MOVEMENT_EPSILON) { + double direction_x = next_system->X() - X(); + double direction_y = next_system->Y() - Y(); + double distance = std::sqrt(direction_x*direction_x + direction_y*direction_y); + + // if starting update in a system, need at least one unit of fuel to start a jump + if (current_system) { + if (fuel < 1.0) { + movement_left = 0; + break; // done movement this turn + } else { + fuel -= 1; // local tracking of total fleet fuel, so individual ships don't need to be re-checked each update + // deduct fuel from ships to make next leg of jump + for (const_iterator ship_it = begin(); ship_it != end(); ++ship_it) { + Ship* ship = universe.Object<Ship>(*ship_it); + assert(ship); + Meter* meter = ship->GetMeter(METER_FUEL); + assert(meter); + meter->AdjustCurrent(-1.0); } + } + } + + if (distance <= movement_left) { + // can jump all the way to the next system + + m_travel_route.pop_front(); + if (m_travel_route.empty()) { + // next system is final destination. insert self into it and explore. + + next_system->Insert(this); + + movement_left = 0.0; + m_moving_to = m_prev_system = m_next_system = INVALID_OBJECT_ID; + m_travel_route.clear(); + m_travel_distance = 0.0; + // explore new system Empire* empire = Empires().Lookup(*Owners().begin()); // assumes one owner empire per fleet - empire->AddExploredSystem(m_travel_route.empty() ? SystemID() : m_prev_system); + empire->AddExploredSystem(SystemID()); + + break; // done movement this turn + } else { - Move(direction_x / distance * movement_left, direction_y / distance * movement_left); - for (ShipIDSet::iterator it = m_ships.begin(); it != m_ships.end(); ++it) { - UniverseObject* ship = GetUniverse().Object(*it); - ship->MoveTo(X(), Y()); - } + // next system is not final destination, so can keep moving after, if there is enough fuel in fleet + + next_system = m_travel_route.front(); + movement_left -= distance; + m_prev_system = m_next_system; + m_next_system = m_travel_route.front()->ID(); m_travel_distance -= distance; - movement_left = 0.0; + MoveTo(next_system); + current_system = next_system; } + + } else { + // can't make it all the way to the next system. go as far towards it as possible + Move(direction_x / distance * movement_left, direction_y / distance * movement_left); + m_travel_distance -= distance; + movement_left = 0.0; } } } Modified: trunk/FreeOrion/universe/Fleet.h =================================================================== --- trunk/FreeOrion/universe/Fleet.h 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/universe/Fleet.h 2008-05-27 10:39:16 UTC (rev 2572) @@ -11,12 +11,13 @@ //////////////////////////////////////////////// /** Contains info about a single notable point on the move path of a fleet or other UniverseObject. */ struct MovePathNode { - MovePathNode(double x_, double y_, bool turn_end_, int eta_) : - x(x_), y(y_), turn_end(turn_end_), eta(eta_) + MovePathNode(double x_, double y_, bool turn_end_, int eta_, int id_) : + x(x_), y(y_), turn_end(turn_end_), eta(eta_), object_id(id_) {} double x, y; ///< location in Universe of node bool turn_end; ///< true if the fleet will end a turn at this point int eta; ///< estimated turns to reach this node + int object_id; ///< id of object (most likely a system) located at this node, or INVALID_OBJECT_ID if there is no object here }; /** encapsulates data for a FreeOrion fleet. Fleets are basically a group of ships that travel together. */ @@ -52,7 +53,8 @@ location, however the fleet's current location will not be on the list, even if it is currently in a system. */ std::list<MovePathNode> MovePath(const std::list<System*>& route) const; std::list<MovePathNode> MovePath() const; ///< Returns MovePath for fleet's current TravelRoute - std::pair<int, int> ETA() const; ///< Returns the number of turns which must elapse before the fleet arrives at its final destination and the turns to the next system, respectively. + std::pair<int, int> ETA() const; ///< Returns the number of turns which must elapse before the fleet arrives at its current final destination and the turns to the next system, respectively. + std::pair<int, int> ETA(const std::list<MovePathNode>& move_path) const; ///< Returns the number of turns which must elapse before the fleet arrives at the final destination and next system in the spepcified \a move_path int FinalDestinationID() const; ///< Returns ID of system that this fleet is moving to. System* FinalDestination() const; ///< Returns system that this fleet is moving to (may be null). int PreviousSystemID() const; ///< Returns ID of system that this fleet is moving away from as it moves to its destination. @@ -86,12 +88,17 @@ iterator end(); ///< returns the end iterator for the ships in the fleet virtual void SetSystem(int sys); + virtual void Move(double x, double y); + virtual void MoveTo(UniverseObject* object); + virtual void MoveTo(double x, double y); + virtual void MovementPhase(); virtual void PopGrowthProductionResearchPhase(); //@} - static const int ETA_NEVER; - static const int ETA_UNKNOWN; + static const int ETA_NEVER; ///< returned by ETA when fleet can't reach destination due to lack of route or inability to move + static const int ETA_UNKNOWN; ///< returned when ETA can't be determined + static const int ETA_OUT_OF_RANGE; ///< returned by ETA when fleet can't reach destination due to insufficient fuel capacity and lack of fleet resupply on route private: void CalculateRoute() const; ///< sets m_travel_route and m_travel_distance to their proper values based on the other member data @@ -107,7 +114,12 @@ int m_prev_system; ///< the next system in the route, if any int m_next_system; ///< the previous system in the route, if any - mutable std::list<System*> m_travel_route; ///< Note that this may contain a single null ptr, indicating that the route is unknown, but needs not be recomputed. + /** list of systems on travel route of fleet from current position to destination. If the fleet is + * currently in a system, that will be the first system on the list. Otherwise, the first system on + * the list will be the next system the fleet will reach along its path. The list may also contain a + * single null pointer, which indicates that the route is unknown. The list may also be empty, which + * indicates that it has not yet been caluclated, and CalculateRoute should be called. */ + mutable std::list<System*> m_travel_route; mutable double m_travel_distance; friend class boost::serialization::access; Modified: trunk/FreeOrion/universe/Planet.cpp =================================================================== --- trunk/FreeOrion/universe/Planet.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/universe/Planet.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -466,6 +466,55 @@ SetIsAboutToBeColonized(false); } +void Planet::SetSystem(int sys) +{ + Logger().debugStream() << "Planet::MoveTo(UniverseObject* object)"; + UniverseObject::SetSystem(sys); + // set system of buildings on this planet. TODO: THIS + //for (iterator it = begin(); it != end(); ++it) { + // UniverseObject* obj = GetUniverse().Object(*it); + // assert(obj); + // obj->SetSystem(sys); + //} +} + +void Planet::Move(double x, double y) +{ + // move planet itself + UniverseObject::Move(x, y); + // move buildings TODO: THIS + //for (iterator it = begin(); it != end(); ++it) { + // UniverseObject* obj = GetUniverse().Object(*it); + // assert(obj); + // obj->Move(x, y); + //} +} + +void Planet::MoveTo(UniverseObject* object) +{ + Logger().debugStream() << "Planet::MoveTo(const UniverseObject* object)"; + UniverseObject::MoveTo(object); + // move buildings TODO: THIS + //for (iterator it = begin(); it != end(); ++it) { + // UniverseObject* obj = GetUniverse().Object(*it); + // assert(obj); + // obj->MoveTo(object); + //} +} + +void Planet::MoveTo(double x, double y) +{ + Logger().debugStream() << "Planet::MoveTo(double x, double y)"; + // move planet itself + UniverseObject::MoveTo(x, y); + // move buildings TODO: THIS + //for (iterator it = begin(); it != end(); ++it) { + // UniverseObject* obj = GetUniverse().Object(*it); + // assert(obj); + // obj->MoveTo(x, y); + //} +} + void Planet::MovementPhase() { } Modified: trunk/FreeOrion/universe/Planet.h =================================================================== --- trunk/FreeOrion/universe/Planet.h 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/universe/Planet.h 2008-05-27 10:39:16 UTC (rev 2572) @@ -130,6 +130,11 @@ //@} /** \name Mutators */ //@{ + virtual void SetSystem(int sys); + virtual void Move(double x, double y); + virtual void MoveTo(UniverseObject* object); + virtual void MoveTo(double x, double y); + virtual void MovementPhase(); virtual void ApplyUniverseTableMaxMeterAdjustments(MeterType meter_type = INVALID_METER_TYPE); virtual void PopGrowthProductionResearchPhase(); @@ -158,7 +163,7 @@ void SetAvailableTrade(double trade); ///< sets the trade available at this planet for use in building maintenance - virtual void AddOwner (int id); ///< adds the Empire with ID \a id to the list of owners of this planet, update system owners and empire planets + virtual void AddOwner(int id); ///< adds the Empire with ID \a id to the list of owners of this planet, update system owners and empire planets virtual void RemoveOwner(int id); ///< removes the Empire with ID \a id to the list of owners of this planet, update system owners and empire planets void Reset(); ///< Resets the meters, specials, etc., of a planet to an unowned state. This should be called when a planet is wiped out due to starvation, etc. Modified: trunk/FreeOrion/universe/PopCenter.cpp =================================================================== --- trunk/FreeOrion/universe/PopCenter.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/universe/PopCenter.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -189,20 +189,7 @@ Meter* pop = GetMeter(METER_POPULATION); Meter* health = GetMeter(METER_HEALTH); - GetMeter(METER_POPULATION)->AdjustCurrent(FuturePopGrowth()); - if (AvailableFood() < pop->Current()) { // starvation - //object->AddSpecial("STARVATION_SPECIAL"); - //health->AdjustMax(PlanetDataTables()["NutrientHealthMod"][0][0]); - } else if (m_available_food < 2 * pop->Current()) { // "minimal" nutrient levels - //object->RemoveSpecial("STARVATION_SPECIAL"); - //health->AdjustMax(PlanetDataTables()["NutrientHealthMod"][0][1]); - } else if (m_available_food < 4 * pop->Current()) { // "normal" nutrient levels - //object->RemoveSpecial("STARVATION_SPECIAL"); - //health->AdjustMax(PlanetDataTables()["NutrientHealthMod"][0][2]); - } else { // food orgy! - //object->RemoveSpecial("STARVATION_SPECIAL"); - //health->AdjustMax(PlanetDataTables()["NutrientHealthMod"][0][3]); - } + pop->AdjustCurrent(FuturePopGrowth()); health->AdjustCurrent(health->InitialCurrent() * (((health->InitialMax() + 1.0) - health->InitialCurrent()) / (health->InitialMax() + 1.0))); } Modified: trunk/FreeOrion/universe/Ship.cpp =================================================================== --- trunk/FreeOrion/universe/Ship.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/universe/Ship.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -89,17 +89,10 @@ double Ship::ProjectedCurrentMeter(MeterType type) const { return UniverseObject::ProjectedCurrentMeter(type); - //switch (type) { - //case METER_FUEL: - // return GetMeter(METER_FUEL)->Current(); - // break; - //default: - // return UniverseObject::ProjectedCurrentMeter(type); - // break; - //} } void Ship::MovementPhase() { + // Fleet::MovementPhase moves ships within fleet around and deals with ship fuel consumption } void Ship::PopGrowthProductionResearchPhase() { Modified: trunk/FreeOrion/universe/System.cpp =================================================================== --- trunk/FreeOrion/universe/System.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/universe/System.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -231,67 +231,107 @@ int System::Insert(UniverseObject* obj, int orbit) { + Logger().debugStream() << "System::Insert(UniverseObject* obj, int orbit)"; + if (!obj) throw std::invalid_argument("System::Insert() : Attempted to place a null object in a System"); + int obj_id = obj->ID(); + if (orbit < -1) throw std::invalid_argument("System::Insert() : Attempted to place an object in an orbit less than -1"); - obj->SetSystem(ID()); - obj->MoveTo(X(), Y()); - return Insert(obj->ID(), orbit); + + obj->MoveTo(X(), Y()); // ensure object is physically at same location in universe as this system + obj->SetSystem(this->ID()); // should do nothing if object is already in this system, but just to ensure things are consistent... + + // ensure object isn't already in this system (as far as the system is concerned). If the system already + // thinks the object is here, just return its current orbit and don't change anything. + for (orbit_iterator it = m_objects.begin(); it != m_objects.end(); ++it) { + if (it->second == obj_id) { + return it->first; + } + } + + // ensure this system has enough orbits to contain object + if (m_orbits <= orbit) + m_orbits = orbit + 1; + + // record object in this system's record of objects in each orbit + std::pair<int, int> insertion(orbit, obj_id); + m_objects.insert(insertion); + + + // special cases for if object is a planet or fleet + if (Planet* planet = universe_object_cast<Planet*>(obj)) + UpdateOwnership(); + else if (Fleet* fleet = universe_object_cast<Fleet*>(obj)) + FleetAddedSignal(*fleet); + + StateChangedSignal(); + + return orbit; } int System::Insert(int obj_id, int orbit) { if (orbit < -1) throw std::invalid_argument("System::Insert() : Attempted to place an object in an orbit less than -1"); - if (!GetUniverse().Object(obj_id)) + UniverseObject* object = GetUniverse().Object(obj_id); + if (!object) throw std::invalid_argument("System::Insert() : Attempted to place an object in a System, when the object is not already in the Universe"); - if (m_orbits <= orbit) - m_orbits = orbit + 1; - std::pair<int, int> insertion(orbit, obj_id); - bool already_in_system = false; - for (orbit_iterator it = m_objects.begin(); it != m_objects.end(); ++it) { - if (it->second == obj_id) { - already_in_system = true; - break; - } - } - if (!already_in_system) { - m_objects.insert(insertion); - if (GetUniverse().Object<Planet>(obj_id)) - UpdateOwnership(); - if (Fleet *fleet = GetUniverse().Object<Fleet>(obj_id)) - FleetAddedSignal(*fleet); - StateChangedSignal(); - } - return orbit; + + return Insert(object, orbit); } -bool System::Remove(int id) +void System::Remove(UniverseObject* obj) { - bool retval = false; + Logger().debugStream() << "System::Remove( " << obj->Name() <<" )"; + + // ensure object and its contents are all removed from system + std::vector<UniverseObject*> contained_objects = obj->FindObjects(); + for (std::vector<UniverseObject*>::iterator it = contained_objects.begin(); it != contained_objects.end(); ++it) + this->Remove(*it); + + + if (obj->SystemID() != this->ID()) + Logger().debugStream() << "System::Remove tried to remove an object whose system id was not this system. Its current system id is: " << obj->SystemID(); + + + // locate object in this system's map of objects, and erase if present for (ObjectMultimap::iterator it = m_objects.begin(); it != m_objects.end(); ++it) { - if (it->second == id) { + Logger().debugStream() << "..system object id " << it->second; + if (it->second == obj->ID()) { m_objects.erase(it); - retval = true; - if (GetUniverse().Object<Planet>(id)) + + obj->SetSystem(INVALID_OBJECT_ID); + + Logger().debugStream() << "....erased from system"; + + // UI bookeeping + if (Planet* planet = universe_object_cast<Planet*>(obj)) UpdateOwnership(); - if (Fleet *fleet = GetUniverse().Object<Fleet>(id)) - FleetRemovedSignal(*fleet); + else if (Fleet* fleet = universe_object_cast<Fleet*>(obj)) + FleetAddedSignal(*fleet); StateChangedSignal(); - break; + + return; // assuming object isn't in system twice... } } - return retval; + + + // didn't find object + Logger().errorStream() << "System::Remove didn't find object in system"; } +void System::Remove(int id) +{ + Remove(GetUniverse().Object(id)); +} + void System::SetStarType(StarType type) { m_star = type; - if (m_star <= INVALID_STAR_TYPE) - m_star = STAR_BLUE; - if (NUM_STAR_TYPES <= m_star) - m_star = STAR_BLACK; + if (m_star <= INVALID_STAR_TYPE || NUM_STAR_TYPES <= m_star) + Logger().errorStream() << "System::SetStarType set star type to " << boost::lexical_cast<std::string>(type); StateChangedSignal(); } Modified: trunk/FreeOrion/universe/System.h =================================================================== --- trunk/FreeOrion/universe/System.h 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/universe/System.h 2008-05-27 10:39:16 UTC (rev 2572) @@ -116,21 +116,25 @@ /** \name Mutators */ //@{ /** inserts a UniversObject into the system, though not in any particular orbit. Only objects free of any - particular orbit, such as ships, should be inserted using this function. This function calls obj->SetSystem(this).*/ + particular orbit, such as ships, should be inserted using this function. This function calls obj->SetSystem(this), + and obj->MoveTo( this system's position )*/ int Insert(UniverseObject* obj); /** inserts an object into a specific orbit position. Only orbit-bound objects, such as Planets, and planet-bound - objects should be inserted with this function. This function calls obj->SetSystem(this). \throw - std::invalid_arugment May throw std::invalid_arugment if \a orbit is out of the range [0, Orbits()].*/ + objects should be inserted with this function. This function calls obj->SetSystem(this) and obj->MoveTo( here ) + \throw std::invalid_arugment May throw std::invalid_arugment if \a orbit is out of the range [0, Orbits()].*/ int Insert(UniverseObject* obj, int orbit); /** inserts an object into a specific orbit position. Only orbit-bound objects, such as Planets, and planet-bound objects should be inserted with this function. */ int Insert(int obj_id, int orbit); - /** removes the object with ID number \a id from the system, and returns it; returns 0 if there is no such object*/ - bool Remove(int id); + /** removes object \a obj from this system. */ + void Remove(UniverseObject* obj); + /** removes the object with ID number \a id from this system. */ + void Remove(int id); + void SetStarType(StarType type); ///< sets the type of the star in this Systems to \a StarType void AddStarlane(int id); ///< adds a starlane between this system and the system with ID number \a id. \note Adding a starlane to a system to which there is already a wormhole erases the wormhole; you may want to check for a wormhole before calling this function. void AddWormhole(int id); ///< adds a wormhole between this system and the system with ID number \a id \note Adding a wormhole to a system to which there is already a starlane erases the starlane; you may want to check for a starlane before calling this function. Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/universe/Universe.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -98,7 +98,7 @@ return i; } - throw std::out_of_range("SystemGraphIndex cannot be found due to invalid system ID"); + throw std::out_of_range("SystemGraphIndex cannot be found due to invalid system ID " + boost::lexical_cast<std::string>(system_id)); return -1; } @@ -585,7 +585,7 @@ m_effect_discrepancy_map.clear(); m_effect_accounting_map.clear(); - Logger().debugStream() << "Universe::InitMeterEstimatesAndDiscrepancies"; + //Logger().debugStream() << "Universe::InitMeterEstimatesAndDiscrepancies"; // generate new estimates (normally uses discrepancies, but in this case will find none) UpdateMeterEstimates(); @@ -635,8 +635,6 @@ void Universe::UpdateMeterEstimates(int object_id, MeterType meter_type, bool update_contained_objects) { - Logger().debugStream() << "Universe::UpdateMeterEstimates"; - if (object_id == UniverseObject::INVALID_OBJECT_ID) { // update meters for all objects. Value of updated_contained_objects is irrelivant and is ignored in this case. std::vector<int> object_ids; @@ -820,7 +818,7 @@ void Universe::GetEffectsAndTargets(EffectsTargetsCausesMap& targets_causes_map, const std::vector<int>& target_objects) { - Logger().debugStream() << "Universe::GetEffectsAndTargets"; + //Logger().debugStream() << "Universe::GetEffectsAndTargets"; // 1) EffectsGroups from Specials for (Universe::const_iterator it = begin(); it != end(); ++it) { int source_object_id = it->first; @@ -949,7 +947,7 @@ void Universe::ExecuteMeterEffects(EffectsTargetsCausesMap& targets_causes_map) { - Logger().debugStream() << "Universe::ExecuteMeterEffects"; + //Logger().debugStream() << "Universe::ExecuteMeterEffects"; std::map<std::string, Effect::EffectsGroup::TargetSet> executed_nonstacking_effects; for (EffectsTargetsCausesMap::const_iterator targets_it = targets_causes_map.begin(); targets_it != targets_causes_map.end(); ++targets_it) { @@ -1092,7 +1090,7 @@ m_objects.erase(id); m_destroyed_objects[id] = obj; } else { - Logger().debugStream() << "Universe::Destroy called for nonexistant object with id: " << id; + Logger().errorStream() << "Universe::Destroy called for nonexistant object with id: " << id; } s_inhibit_universe_object_signals = false; @@ -2858,6 +2856,11 @@ homeworlds.clear(); std::vector<System*> sys_vec = FindObjects<System>(); + Logger().debugStream() << "Universe::GenerateHomeworlds sys_vec:"; + for (std::vector<System*>::const_iterator it = sys_vec.begin(); it != sys_vec.end(); ++it) { + const System* sys = *it; + Logger().debugStream() << "... sys ptr: " << sys << " name: " << (sys ? sys->Name() : "no system!?") << " id: " << (sys ? boost::lexical_cast<std::string>(sys->ID()) : "none?!"); + } if (sys_vec.empty()) throw std::runtime_error("Attempted to generate homeworlds in an empty galaxy."); @@ -2872,9 +2875,20 @@ do { too_close = false; system_index = RandSmallInt(0, static_cast<int>(sys_vec.size()) - 1); + Logger().debugStream() << "Universe::GenerateHomeworlds trying to put homeworld on system with index: " << system_index; system = sys_vec[system_index]; + Logger().debugStream() << "... system ptr: " << system << " name: " << (system ? system->Name() : "no system!?") << " id: " << (system ? boost::lexical_cast<std::string>(system->ID()) : "none?!"); + for (unsigned int j = 0; j < homeworlds.size(); ++j) { + Logger().debugStream() << "Universe::GenerateHomeworlds checking previously-existing homeworld with id " << homeworlds[j]; System* existing_system = Object(homeworlds[j])->GetSystem(); + Logger().debugStream() << ".... existing system ptr: " << existing_system; + + if (!existing_system) { + Logger().errorStream() << "couldn't find existing system!"; + continue; + } + double x_dist = existing_system->X() - system->X(); double y_dist = existing_system->Y() - system->Y(); if (x_dist * x_dist + y_dist * y_dist < MIN_HOME_SYSTEM_SEPARATION * MIN_HOME_SYSTEM_SEPARATION) { Modified: trunk/FreeOrion/universe/UniverseObject.cpp =================================================================== --- trunk/FreeOrion/universe/UniverseObject.cpp 2008-05-23 12:30:01 UTC (rev 2571) +++ trunk/FreeOrion/universe/UniverseObject.cpp 2008-05-27 10:39:16 UTC (rev 2572) @@ -212,17 +212,32 @@ { if (m_x + x < 0.0 || Universe::UniverseWidth() < m_x + x || m_y + y < 0.0 || Universe::UniverseWidth() < m_y + y) throw std::runtime_error("UniverseObject::Move : Attempted to move object \"" + m_name + "\" off the map area."); - m_x += x; - m_y += y; - StateChangedSignal(); + UniverseObject::MoveTo(m_x + x, m_y + y); } +void UniverseObject::MoveTo(int object_id) +{ + UniverseObject::MoveTo(GetUniverse().Object(object_id)); +} + +void UniverseObject::MoveTo(UniverseOb... [truncated message content] |