From: <geo...@us...> - 2009-09-09 06:33:37
|
Revision: 3152 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3152&view=rev Author: geoffthemedio Date: 2009-09-09 06:33:27 +0000 (Wed, 09 Sep 2009) Log Message: ----------- -Added a Reset function to Building that removes owners and can, in future, be modified to reset any other state information about a building to unowned / default, for use when a building's owner loses control of it, such as when their planet starves to 0 population -Made Planet::Reset reset planet specific meters and remove ownership of buildings on the planet, rather than removing the buildings from the list of buildings on the planet without actually changing those buildings' ownership, which was leading to bugs where players owned invisible buildings on planets they didn't own. -Added minimum population check to popcenter growth (or decay). Popcenters with less than the minimum population have their population set to 0. -Added a UniverseObject::ClearOwners function that calls this->RemoveOwner for all owners of the object. -Changed FleetColonizeOrder::ServerExecute to destroy rather than delete the colony ship, so that it can remain in destroyed objects. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp trunk/FreeOrion/universe/Building.cpp trunk/FreeOrion/universe/Building.h trunk/FreeOrion/universe/Planet.cpp trunk/FreeOrion/universe/PopCenter.cpp trunk/FreeOrion/universe/PopCenter.h trunk/FreeOrion/universe/ResourceCenter.cpp trunk/FreeOrion/universe/UniverseObject.cpp trunk/FreeOrion/universe/UniverseObject.h trunk/FreeOrion/util/Order.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2009-09-08 10:33:31 UTC (rev 3151) +++ trunk/FreeOrion/server/ServerApp.cpp 2009-09-09 06:33:27 UTC (rev 3152) @@ -797,7 +797,7 @@ // Population growth or loss, health meter growth, resource current meter growth for (Universe::const_iterator it = m_universe.begin(); it != m_universe.end(); ++it) { it->second->PopGrowthProductionResearchPhase(); - it->second->ClampMeters(); // ensures growth doesn't leave meters over MAX. should otherwise be redundant with ClampMeters() in Universe::ApplyMeterEffectsAndUpdateMeters() + it->second->ClampMeters(); // ensures growth doesn't leave meters over MAX. should otherwise be redundant with ClampMeters() in Universe::ApplyMeterEffectsAndUpdateMeters() } Modified: trunk/FreeOrion/universe/Building.cpp =================================================================== --- trunk/FreeOrion/universe/Building.cpp 2009-09-08 10:33:31 UTC (rev 3151) +++ trunk/FreeOrion/universe/Building.cpp 2009-09-09 06:33:27 UTC (rev 3152) @@ -121,6 +121,14 @@ void Building::PopGrowthProductionResearchPhase() {} +void Building::Reset() +{ + ClearOwners(); +} + +///////////////////////////////////////////////// +// BuildingType // +///////////////////////////////////////////////// BuildingType::BuildingType() : m_name(""), m_description(""), Modified: trunk/FreeOrion/universe/Building.h =================================================================== --- trunk/FreeOrion/universe/Building.h 2009-09-08 10:33:31 UTC (rev 3151) +++ trunk/FreeOrion/universe/Building.h 2009-09-09 06:33:27 UTC (rev 3152) @@ -44,6 +44,8 @@ virtual void MovementPhase(); virtual void PopGrowthProductionResearchPhase(); + + void Reset(); ///< resets any building state, and removes owners //@} private: @@ -74,22 +76,23 @@ //@} /** \name Accessors */ //@{ - const std::string& Name() const; ///< returns the unique name for this type of building - const std::string& Description() const; ///< returns a text description of this type of building - std::string Dump() const; ///< returns a data file format representation of this object - double BuildCost() const; ///< returns the number of production points required to build this building - int BuildTime() const; ///< returns the number of turns required to build this building - double MaintenanceCost() const; ///< returns the number of monetary points required per turn to operate this building - const Condition::ConditionBase* Location() const; ///< returns the condition that determines the locations where this building can be produced - const std::vector<boost::shared_ptr<const Effect::EffectsGroup> >& Effects() const; ///< returns the EffectsGroups that encapsulate the effects that buildings of this type have when operational - const std::string& Graphic() const; ///< returns the name of the grapic file for this building type + const std::string& Name() const; ///< returns the unique name for this type of building + const std::string& Description() const; ///< returns a text description of this type of building + std::string Dump() const; ///< returns a data file format representation of this object + double BuildCost() const; ///< returns the number of production points required to build this building + int BuildTime() const; ///< returns the number of turns required to build this building + double MaintenanceCost() const; ///< returns the number of monetary points required per turn to operate this building + const Condition::ConditionBase* Location() const; ///< returns the condition that determines the locations where this building can be produced + const std::vector<boost::shared_ptr<const Effect::EffectsGroup> >& + Effects() const; ///< returns the EffectsGroups that encapsulate the effects that buildings of this type have when operational + const std::string& Graphic() const; ///< returns the name of the grapic file for this building type bool ProductionLocation(int empire_id, int location_id) const; ///< returns true iff the empire with ID empire_id can produce this building at the location with location_id /** returns CaptureResult for empire with ID \a to_empire_id capturing from empire with ID \a from_empire_id the planet (or other UniverseObject) with id \a location_id on which this type of Building is located (if \a as_production_item is false) or which is the location of a Production Queue BuildItem for a building of this type (otherwise) */ - CaptureResult GetCaptureResult(int from_empire_id, int to_empire_id, int location_id, bool as_production_item) const; + CaptureResult GetCaptureResult(int from_empire_id, int to_empire_id, int location_id, bool as_production_item) const; //@} private: Modified: trunk/FreeOrion/universe/Planet.cpp =================================================================== --- trunk/FreeOrion/universe/Planet.cpp 2009-09-08 10:33:31 UTC (rev 3151) +++ trunk/FreeOrion/universe/Planet.cpp 2009-09-09 06:33:27 UTC (rev 3152) @@ -417,17 +417,19 @@ void Planet::RemoveOwner(int id) { - System *system = GetSystem(); + System* system = GetSystem(); + + // check if Empire(id) is owner of at least one other planet in same system std::vector<Planet*> planets = system->FindObjects<Planet>(); + int empire_owned_planets_in_this_planet_system = 0; + for (std::vector<Planet*>::const_iterator plt_it = planets.begin(); plt_it != planets.end(); ++plt_it) + if ((*plt_it)->OwnedBy(id)) + ++empire_owned_planets_in_this_planet_system; - // check if Empire(id) is owner of at least one other planet - std::vector<Planet*>::const_iterator plt_it; - int count_planets = 0; - for(plt_it = planets.begin(); plt_it != planets.end(); ++plt_it) - if((*plt_it)->Owners().find(id) != (*plt_it)->Owners().end()) - count_planets++; - - if(count_planets == 1) + // if this is the only planet owned by this planet's current owner, removing + // that owner means the empire owns no planets in this system, so loses + // any ownership of the system as well + if (empire_owned_planets_in_this_planet_system < 2) system->UniverseObject::RemoveOwner(id); UniverseObject::RemoveOwner(id); @@ -435,13 +437,28 @@ void Planet::Reset() { - std::set<int> owners = Owners(); - for (std::set<int>::iterator it = owners.begin(); it != owners.end(); ++it) { - RemoveOwner(*it); - } + // remove owners + ClearOwners(); + + // reset popcenter meters PopCenter::Reset(MaxPopMod(Size(), Environment(Type())), MaxHealthMod(Environment(Type()))); + + // reset resourcecenter meters ResourceCenter::Reset(); - m_buildings.clear(); + + // reset planet meters + GetMeter(METER_SUPPLY)->ResetMax(); + GetMeter(METER_SHIELD)->ResetMax(); + GetMeter(METER_DEFENSE)->ResetMax(); + GetMeter(METER_DETECTION)->ResetMax(); + GetMeter(METER_STEALTH)->ResetMax(); + + // reset buildings + for (std::set<int>::const_iterator it = m_buildings.begin(); it != m_buildings.end(); ++it) + if (Building* building = GetUniverse().Object<Building>(*it)) + building->Reset(); + + // reset other state m_available_trade = 0.0; m_just_conquered = false; m_is_about_to_be_colonized = false; @@ -556,12 +573,17 @@ PopCenter::PopGrowthProductionResearchPhase(); - double current_construction = GetMeter(METER_CONSTRUCTION)->Current(); // want current construction, that has been updated from initial current construction - GrowMeter(GetMeter(METER_SUPPLY), current_construction); - GrowMeter(GetMeter(METER_SHIELD), current_construction); - GrowMeter(GetMeter(METER_DEFENSE), current_construction); - GrowMeter(GetMeter(METER_DETECTION), current_construction); - GrowMeter(GetMeter(METER_STEALTH), current_construction); + // check for starvation + if (GetPopMeter()->Current() < PopCenter::MINIMUM_POP_CENTER_POPULATION) { + Reset(); + } else { + double current_construction = GetMeter(METER_CONSTRUCTION)->Current(); // want current construction, that has been updated from initial current construction + GrowMeter(GetMeter(METER_SUPPLY), current_construction); + GrowMeter(GetMeter(METER_SHIELD), current_construction); + GrowMeter(GetMeter(METER_DEFENSE), current_construction); + GrowMeter(GetMeter(METER_DETECTION), current_construction); + GrowMeter(GetMeter(METER_STEALTH), current_construction); + } StateChangedSignal(); } Modified: trunk/FreeOrion/universe/PopCenter.cpp =================================================================== --- trunk/FreeOrion/universe/PopCenter.cpp 2009-09-08 10:33:31 UTC (rev 3151) +++ trunk/FreeOrion/universe/PopCenter.cpp 2009-09-09 06:33:27 UTC (rev 3152) @@ -36,6 +36,8 @@ } } +const double PopCenter::MINIMUM_POP_CENTER_POPULATION = 0.051; // rounds up to 0.1 when showing only two digits + PopCenter::PopCenter(int race) : m_race(race), m_allocated_food(0.0) {} @@ -65,7 +67,20 @@ double cur = GetMeter(METER_POPULATION)->Current(); //Logger().debugStream() << "PopCenter::FuturePopGrowth growth max: " << FuturePopGrowthMax() << " allocated food: " << AllocatedFood(); - return std::max(-cur, std::min(FuturePopGrowthMax(), std::min(AllocatedFood(), max) - cur)); + // growth limited by max possible growth from health and current population + // based formula, by allocated food, and by max possible population for + // this PopCenter. + // population decline limited by current population: can't have negative + // population. + double raw_growth = std::max(-cur, std::min(FuturePopGrowthMax(), std::min(AllocatedFood(), max) - cur)); + + // if population will fall below minimum threshold, ensure this function + // returns actual decrease (although difference would be less than + // MINIMUM_POP_CENTER_POPULATION in any case + if (cur - raw_growth < MINIMUM_POP_CENTER_POPULATION) + return -cur; + + return raw_growth; } double PopCenter::FuturePopGrowthMax() const @@ -164,21 +179,22 @@ { UniverseObject* object = GetObjectSignal(); assert(object); + Meter* pop = GetMeter(METER_POPULATION); Meter* health = GetMeter(METER_HEALTH); - double pop_adjustment = FuturePopGrowth(); + double pop_growth = FuturePopGrowth(); + double cur = pop->Current(); + double new_pop = cur + pop_growth; + if (new_pop >= MINIMUM_POP_CENTER_POPULATION) { + pop->SetCurrent(new_pop); - pop->AdjustCurrent(pop_adjustment); - - double health_initial_current = health->InitialCurrent(); - double health_initial_max = health->InitialMax(); - - - if (health_initial_current < health_initial_max) { - double health_adjustment = (((health_initial_max + 1.0) - health_initial_current) / (health_initial_max + 1.0)); - health->AdjustCurrent(health_adjustment); - Logger().debugStream() << "PopCenter::PopGrowthProductionResearchPhase adjusted current health to: " << health->Current(); + double health_delta = 1.0; + health->AdjustCurrent(health_delta); + } else { + // if population falls below threshold, fall completely to zero. + pop->SetCurrent(0.0); + health->SetCurrent(0.0); } } Modified: trunk/FreeOrion/universe/PopCenter.h =================================================================== --- trunk/FreeOrion/universe/PopCenter.h 2009-09-08 10:33:31 UTC (rev 3151) +++ trunk/FreeOrion/universe/PopCenter.h 2009-09-09 06:33:27 UTC (rev 3152) @@ -49,6 +49,8 @@ void Reset(double max_pop_mod, double max_health_mod); ///< Resets the meters, etc. This should be called when a PopCenter is wiped out due to starvation, etc. //@} + static const double MINIMUM_POP_CENTER_POPULATION; ///< below this population, planet is considered unpopulated and reset to uncolonized state + protected: mutable GetObjectSignalType GetObjectSignal; ///< the UniverseObject-retreiving signal object for this PopCenter Modified: trunk/FreeOrion/universe/ResourceCenter.cpp =================================================================== --- trunk/FreeOrion/universe/ResourceCenter.cpp 2009-09-08 10:33:31 UTC (rev 3151) +++ trunk/FreeOrion/universe/ResourceCenter.cpp 2009-09-09 06:33:27 UTC (rev 3152) @@ -59,7 +59,6 @@ double initial_current = resource_meter->InitialCurrent(); double delta = 1.0; - resource_meter->AdjustCurrent(delta); } @@ -70,7 +69,6 @@ double initial_max = construction_meter->InitialMax(); double delta = 1.0; - construction_meter->AdjustCurrent(delta); } } Modified: trunk/FreeOrion/universe/UniverseObject.cpp =================================================================== --- trunk/FreeOrion/universe/UniverseObject.cpp 2009-09-08 10:33:31 UTC (rev 3151) +++ trunk/FreeOrion/universe/UniverseObject.cpp 2009-09-09 06:33:27 UTC (rev 3152) @@ -262,6 +262,12 @@ StateChangedSignal(); } +void UniverseObject::ClearOwners() +{ + for (std::set<int>::iterator it = m_owners.begin(); it != m_owners.end(); ++it) + RemoveOwner(*it); +} + void UniverseObject::SetSystem(int sys) { //Logger().debugStream() << "UniverseObject::SetSystem(int sys)"; Modified: trunk/FreeOrion/universe/UniverseObject.h =================================================================== --- trunk/FreeOrion/universe/UniverseObject.h 2009-09-08 10:33:31 UTC (rev 3151) +++ trunk/FreeOrion/universe/UniverseObject.h 2009-09-09 06:33:27 UTC (rev 3152) @@ -126,6 +126,7 @@ virtual void AddOwner(int id); ///< adds the Empire with ID \a id to the list of owners of this object virtual void RemoveOwner(int id); ///< removes the Empire with ID \a id to the list of owners of this object + virtual void ClearOwners(); ///< removes all empires from list of owners of this object virtual void SetSystem(int sys); ///< assigns this object to a System. does not actually move object in universe virtual void AddSpecial(const std::string& name); ///< adds the Special \a name to this object, if it is not already present virtual void RemoveSpecial(const std::string& name); ///< removes the Special \a name from this object, if it is already present Modified: trunk/FreeOrion/util/Order.cpp =================================================================== --- trunk/FreeOrion/util/Order.cpp 2009-09-08 10:33:31 UTC (rev 3151) +++ trunk/FreeOrion/util/Order.cpp 2009-09-09 06:33:27 UTC (rev 3152) @@ -294,44 +294,34 @@ // sanity check if (!source_fleet || !target_fleet) - { throw std::runtime_error("Illegal fleet id specified in fleet merge order."); - } // verify that empire is not trying to take ships from somebody else's fleet if ( !source_fleet->OwnedBy(EmpireID()) ) - { throw std::runtime_error("Empire attempted to merge ships from another's fleet."); - } // verify that empire cannot merge ships into somebody else's fleet. // this is just an additional security measure. IT could be removed to // allow 'donations' of ships to other players, provided the server // verifies IDs of the Empires issuing the orders. if ( !target_fleet->OwnedBy(EmpireID()) ) - { throw std::runtime_error("Empire attempted to merge ships into another's fleet."); - } + // iterate down the ship vector and add each one to the fleet // after first verifying that it is a valid ship id vector<int>::const_iterator itr = m_add_ships.begin(); - while (itr != m_add_ships.end()) - { + while (itr != m_add_ships.end()) { // find the ship, verify that ID is valid int curr = (*itr); Ship* a_ship = universe.Object<Ship>(curr); if (!a_ship) - { throw std::runtime_error("Illegal ship id specified in fleet merge order."); - } // figure out what fleet this ship is coming from -- verify its the one we // said it comes from - if (a_ship->FleetID() != SourceFleet() ) - { + if (a_ship->FleetID() != SourceFleet()) throw std::runtime_error("Ship in merge order is not in specified source fleet."); - } // send the ship to its new fleet //a_ship->SetFleetID(DestinationFleet()); // redundant: AddShip resets the Fleet ID of ships it adds @@ -387,7 +377,7 @@ } } - universe.Delete(m_ship); + universe.Destroy(m_ship); if (colonist_capacity <= 0.0) { Logger().debugStream() << "colonize order executed by ship with zero colonist capacity!"; @@ -403,15 +393,15 @@ planet->GetMeter(METER_POPULATION)->BackPropegate(); planet->GetMeter(METER_FARMING)->SetCurrent(10.0); planet->GetMeter(METER_FARMING)->BackPropegate(); - planet->GetMeter(METER_HEALTH)->SetCurrent(Meter::METER_MAX); + planet->GetMeter(METER_HEALTH)->SetCurrent(Meter::METER_MAX); // will later be clamped to max health planet->GetMeter(METER_HEALTH)->BackPropegate(); planet->AddOwner(EmpireID()); - Logger().debugStream() << "colonizing planet " << planet->Name() << " by empire " << EmpireID() << " meters:"; - for (MeterType meter_type = MeterType(0); meter_type != NUM_METER_TYPES; meter_type = MeterType(meter_type + 1)) - if (const Meter* meter = planet->GetMeter(meter_type)) - Logger().debugStream() << "type: " << boost::lexical_cast<std::string>(meter_type) << " val: " << meter->InitialCurrent() << "/" << meter->InitialMax(); + //Logger().debugStream() << "colonizing planet " << planet->Name() << " by empire " << EmpireID() << " meters:"; + //for (MeterType meter_type = MeterType(0); meter_type != NUM_METER_TYPES; meter_type = MeterType(meter_type + 1)) + // if (const Meter* meter = planet->GetMeter(meter_type)) + // Logger().debugStream() << "type: " << boost::lexical_cast<std::string>(meter_type) << " val: " << meter->InitialCurrent() << "/" << meter->InitialMax(); } void FleetColonizeOrder::ExecuteImpl() const |