From: <geo...@us...> - 2009-04-12 06:03:55
|
Revision: 2974 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=2974&view=rev Author: geoffthemedio Date: 2009-04-12 06:03:54 +0000 (Sun, 12 Apr 2009) Log Message: ----------- -Fixed issue with supplied systems not being properly restored after loading a save by recalculating this when loading the universe from the save file. This was causing fleets passing through supplied systems on the first turn after loading a save to not get refuelled and to have to spend fuel when they shouldn't have needed to. -Also recalculated meter estimates in doing the previous, which might fix bug 2498657: Meter / Resource Estimates Wrong When Loading Save, but I can't tell due to a crash bug when saving the game in the current SVN version. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2009-04-12 05:29:26 UTC (rev 2973) +++ trunk/FreeOrion/server/ServerApp.cpp 2009-04-12 06:03:54 UTC (rev 2974) @@ -388,6 +388,21 @@ // the universe is loaded. That means we must do it here. m_universe.RebuildEmpireViewSystemGraphs(); + + // restore in-turn state data potentially lost during serialization.. + m_universe.ApplyMeterEffectsAndUpdateMeters(); + for (EmpireManager::iterator it = Empires().begin(); it != Empires().end(); ++it) { + Empire* empire = it->second; + + empire->UpdateSupplyUnobstructedSystems(); // determines which systems can propegate fleet and resource (same for both) + empire->UpdateSystemSupplyRanges(); // sets range systems can propegate fleet and resourse supply (separately) + empire->UpdateFleetSupply(); // determines which systems can access fleet supply, and starlane traversals used to do this + empire->UpdateResourceSupply(); // determines the separate groups of systems within which (but not between which) resources can be shared + empire->InitResourcePools(); // determines population centers and resource centers of empire, tells resource pools the centers and groups of systems that can share resources (note that being able to share resources doesn't mean a system produces resources) + empire->UpdateResourcePools(); // determines how much of each resources is available in each resource sharing group + } + + // compile map of PlayerInfo for each player, indexed by player ID std::map<int, PlayerInfo> players; for (ServerNetworking::const_established_iterator it = m_networking.established_begin(); it != m_networking.established_end(); ++it) { @@ -542,7 +557,7 @@ // 2.a - if only one empire which tries to colonize (empire who don't are ignored) is armed, this empire wins the race // 2.b - if more than one empire is armed or all forces are unarmed, no one can colonize the planet for (ColonizeOrderMap::iterator it = colonize_order_map.begin(); it != colonize_order_map.end(); ++it) { - Planet *planet = universe.Object<Planet>(it->first); + Planet *planet = m_universe.Object<Planet>(it->first); // only one empire? if (it->second.size()==1) { @@ -550,13 +565,13 @@ Empire* empire = empires.Lookup( it->second[0]->EmpireID() ); empire->AddSitRepEntry(CreatePlanetColonizedSitRep(planet->SystemID(), planet->ID())); } else { - const System *system = universe.Object<System>(planet->SystemID()); + const System *system = m_universe.Object<System>(planet->SystemID()); std::vector<const Fleet*> vec_fleet = system->FindObjects<Fleet>(); std::set<int> set_empire_with_military; for (unsigned int i=0;i<vec_fleet.size();i++) for (Fleet::const_iterator ship_it=vec_fleet[i]->begin();ship_it!=vec_fleet[i]->end();++ship_it) - if (universe.Object<Ship>(*ship_it)->IsArmed()) { + if (m_universe.Object<Ship>(*ship_it)->IsArmed()) { set_empire_with_military.insert(*vec_fleet[i]->Owners().begin()); break; } @@ -599,9 +614,9 @@ (*player_it)->SendMessage(TurnProgressMessage((*player_it)->ID(), Message::FLEET_MOVEMENT, -1)); } - for (Universe::const_iterator it = universe.begin(); it != universe.end(); ++it) { + for (Universe::const_iterator it = m_universe.begin(); it != m_universe.end(); ++it) { // save for possible SitRep generation after moving... - const Fleet* fleet = universe.Object<Fleet>(it->first); + const Fleet* fleet = m_universe.Object<Fleet>(it->first); int eta = -1; if (fleet) eta = fleet->ETA().first; @@ -633,7 +648,7 @@ (*player_it)->SendMessage(TurnProgressMessage((*player_it)->ID(), Message::COMBAT, -1)); } - std::vector<System*> sys_vec = universe.FindObjects<System>(); + std::vector<System*> sys_vec = m_universe.FindObjects<System>(); for (std::vector<System*>::iterator it = sys_vec.begin(); it != sys_vec.end(); ++it) { System* system = *it; if (TEST_3D_COMBAT) { @@ -739,7 +754,7 @@ // execute all effects and update meters prior to production, research, etc. - universe.ApplyAllEffectsAndUpdateMeters(); + m_universe.ApplyAllEffectsAndUpdateMeters(); @@ -769,14 +784,14 @@ // re-execute all meter-related effects after production, so that new UniverseObjects created during production // will have effects applied to them this turn, allowing (for example) ships to have max fuel meters greater than // 0 on the turn they are created. - universe.ApplyMeterEffectsAndUpdateMeters(); + m_universe.ApplyMeterEffectsAndUpdateMeters(); // regenerate empire system visibility, which is needed for some UniverseObject subclasses' PopGrowthProductionResearchPhase() - universe.RebuildEmpireViewSystemGraphs(); + m_universe.RebuildEmpireViewSystemGraphs(); // Population growth or loss, health meter growth, resource current meter growth - for (Universe::const_iterator it = universe.begin(); it != universe.end(); ++it) { + 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() } @@ -786,7 +801,7 @@ // copy latest updated current meter values to initial current values, and initial current values // to previous values, so that clients will have this information based on values after all changes // that occured this turn. - for (Universe::const_iterator it = universe.begin(); it != universe.end(); ++it) { + for (Universe::const_iterator it = m_universe.begin(); it != m_universe.end(); ++it) { for (MeterType i = MeterType(0); i != NUM_METER_TYPES; i = MeterType(i + 1)) if (Meter* meter = it->second->GetMeter(i)) meter->BackPropegate(); @@ -794,7 +809,7 @@ // create sitreps for starved planets - std::vector<Planet*> plt_vec = universe.FindObjects<Planet>(); + std::vector<Planet*> plt_vec = m_universe.FindObjects<Planet>(); for (std::vector<Planet*>::iterator it = plt_vec.begin(); it!=plt_vec.end(); ++it) { if ((*it)->Owners().size() > 0 && (*it)->GetMeter(METER_POPULATION)->Current() <= 0.0) { // add some information to sitrep @@ -828,8 +843,8 @@ // check for eliminated empires and players std::map<int, int> eliminations; // map from player id to empire id of eliminated players for (EmpireManager::const_iterator it = empires.begin(); it != empires.end(); ++it) { - empire = it->second; - if (!EmpireEliminated(empire, universe)) + Empire* empire = it->second; + if (!EmpireEliminated(empire, m_universe)) continue; int elim_empire_id = it->first; @@ -842,9 +857,9 @@ std::map<int, std::set<std::string> > new_victors; // map from player ID to set of victory reason strings // marked by Victory effect? - const std::multimap<int, std::string>& marked_for_victory = universe.GetMarkedForVictory(); + const std::multimap<int, std::string>& marked_for_victory = m_universe.GetMarkedForVictory(); for (std::multimap<int, std::string>::const_iterator it = marked_for_victory.begin(); it != marked_for_victory.end(); ++it) { - const UniverseObject* obj = universe.Object(it->first); + const UniverseObject* obj = m_universe.Object(it->first); if (!obj) continue; // perhaps it was destroyed? const std::set<int>& owners = obj->Owners(); if (owners.size() == 1) { @@ -893,7 +908,7 @@ // record victory m_victors[victor_player_id].insert(reason_string); - empire = GetPlayerEmpire(victor_player_id); + Empire* empire = GetPlayerEmpire(victor_player_id); if (!empire) { Logger().errorStream() << "Trying to grant victory to a missing empire!"; continue; @@ -923,7 +938,7 @@ for (std::map<int, int>::iterator it = eliminations.begin(); it != eliminations.end(); ++it) { int elim_player_id = it->first; int elim_empire_id = it->second; - empire = empires.Lookup(elim_empire_id); + Empire* empire = empires.Lookup(elim_empire_id); if (!empire) { Logger().errorStream() << "Trying to eliminate a missing empire!"; continue; |
From: <geo...@us...> - 2009-09-12 20:37:11
|
Revision: 3161 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3161&view=rev Author: geoffthemedio Date: 2009-09-12 20:36:50 +0000 (Sat, 12 Sep 2009) Log Message: ----------- Added empire fleet supply and resource pool updating after universe creation so that fleet supply is properly updated for the first turn. This fixes an issue where fleets departing the homeworld on the first turn consumed fuel to do so, while waiting 1 turn so that the fleet supply would be updated ruing turn processing and then departing wouldn't consume any fuel (as it should be). Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2009-09-12 18:23:19 UTC (rev 3160) +++ trunk/FreeOrion/server/ServerApp.cpp 2009-09-12 20:36:50 UTC (rev 3161) @@ -328,6 +328,20 @@ m_networking.NumPlayers() - m_ai_clients.size(), m_ai_clients.size(), player_setup_data); m_current_turn = 1; // after all game initialization stuff has been created, can set current turn to 1 for start of game + + // Determine initial supply distribution and exchanging and resource pools for empires + EmpireManager& empires = Empires(); + for (EmpireManager::iterator it = empires.begin(); it != empires.end(); ++it) { + Empire* empire = it->second; + + empire->UpdateSupplyUnobstructedSystems(); // determines which systems can propegate fleet and resource (same for both) + empire->UpdateSystemSupplyRanges(); // sets range systems can propegate fleet and resourse supply (separately) + empire->UpdateFleetSupply(); // determines which systems can access fleet supply, and starlane traversals used to do this + empire->UpdateResourceSupply(); // determines the separate groups of systems within which (but not between which) resources can be shared + empire->InitResourcePools(); // determines population centers and resource centers of empire, tells resource pools the centers and groups of systems that can share resources (note that being able to share resources doesn't mean a system produces resources) + empire->UpdateResourcePools(); // determines how much of each resources is available in each resource sharing group + } + Logger().debugStream() << "Universe Created. Adding empires to turn processing list"; std::vector<PlayerConnectionPtr> shuffled_players; @@ -516,7 +530,7 @@ void ServerApp::ProcessTurns() { - EmpireManager& empires = Empires(); + EmpireManager& empires = Empires(); // Now all orders, then process turns |
From: <geo...@us...> - 2009-10-10 04:07:41
|
Revision: 3200 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3200&view=rev Author: geoffthemedio Date: 2009-10-10 04:07:28 +0000 (Sat, 10 Oct 2009) Log Message: ----------- Added step to turn processing to remove empty fleets after destroying scrapped fleets. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2009-10-08 04:16:32 UTC (rev 3199) +++ trunk/FreeOrion/server/ServerApp.cpp 2009-10-10 04:07:28 UTC (rev 3200) @@ -650,6 +650,13 @@ } for (std::vector<int>::const_iterator it = objects_to_scrap.begin(); it != objects_to_scrap.end(); ++it) m_universe.Destroy(*it); + // check for empty fleets after scrapping + std::vector<Fleet*> fleets = m_universe.FindObjects<Fleet>(); + for (std::vector<Fleet*>::iterator it = fleets.begin(); it != fleets.end(); ++it) { + if (Fleet* fleet = *it) + if (fleet->Empty()) + m_universe.Destroy(fleet->ID()); + } // fleet movement |
From: <tz...@us...> - 2010-03-24 01:37:29
|
Revision: 3399 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3399&view=rev Author: tzlaine Date: 2010-03-24 01:37:22 +0000 (Wed, 24 Mar 2010) Log Message: ----------- Fixed typo. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2010-03-23 03:25:09 UTC (rev 3398) +++ trunk/FreeOrion/server/ServerApp.cpp 2010-03-24 01:37:22 UTC (rev 3399) @@ -817,7 +817,7 @@ } // re-execute all meter-related effects after orders, so that new - // UniverseObjects created during order executtion (eg. new fleets) will + // UniverseObjects created during order execution (eg. new fleets) will // have effects applied to them this turn, ensuring (eg.) new fleets will // have the appropriate stealth level on the turn they are created. m_universe.ApplyMeterEffectsAndUpdateMeters(); |
From: <tz...@us...> - 2010-04-15 16:21:11
|
Revision: 3503 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3503&view=rev Author: tzlaine Date: 2010-04-15 16:21:05 +0000 (Thu, 15 Apr 2010) Log Message: ----------- Fxied the problem of placement orders flipping ships aroung 180 degrees, by reinterpreting the placement direction vector at the server. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2010-04-15 15:59:33 UTC (rev 3502) +++ trunk/FreeOrion/server/ServerApp.cpp 2010-04-15 16:21:05 UTC (rev 3503) @@ -1432,7 +1432,7 @@ CombatShipPtr combat_ship = pathing_engine.FindShip(order.ID()); assert(combat_ship); combat_ship->setPosition(order.GetPositionAndDirection().first); - combat_ship->regenerateOrthonormalBasis(order.GetPositionAndDirection().first, + combat_ship->regenerateOrthonormalBasis(-order.GetPositionAndDirection().first, OpenSteer::Vec3(0.0, 0.0, 1.0)); break; } |
From: <tz...@us...> - 2010-04-22 03:45:31
|
Revision: 3520 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3520&view=rev Author: tzlaine Date: 2010-04-22 03:45:25 +0000 (Thu, 22 Apr 2010) Log Message: ----------- Changed the server-side constants used to simulate client-side update iterations to use the ones specified in PathingEngine. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2010-04-22 03:31:05 UTC (rev 3519) +++ trunk/FreeOrion/server/ServerApp.cpp 2010-04-22 03:45:25 UTC (rev 3520) @@ -1453,10 +1453,9 @@ if (m_current_combat->m_combat_turn_number) { // TODO: execute turn pathing_engine.TurnStarted(m_current_combat->m_combat_turn_number); - const unsigned int ITERATIONS_PER_SEC = 60; - const unsigned int TURN_LENGTH = 5; // seconds - const unsigned int ITERATIONS = TURN_LENGTH * ITERATIONS_PER_SEC; - const double ITERATION_DURATION = 1.0 / ITERATIONS_PER_SEC; + const std::size_t TURN_LENGTH = 5; // seconds + const unsigned int ITERATIONS = TURN_LENGTH * PathingEngine::TARGET_OBJECT_UPDATES_PER_SEC; + const double ITERATION_DURATION = 1.0 / PathingEngine::TARGET_OBJECT_UPDATES_PER_SEC; for (unsigned int i = 0; i < ITERATIONS; ++i) { pathing_engine.Update(0.0, ITERATION_DURATION); } |
From: <tz...@us...> - 2010-04-30 04:19:35
|
Revision: 3568 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3568&view=rev Author: tzlaine Date: 2010-04-30 04:19:26 +0000 (Fri, 30 Apr 2010) Log Message: ----------- Increased the minumum number of server-side PathingEngine update iterations, to increase agreement between the client and server object positions. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2010-04-30 04:03:04 UTC (rev 3567) +++ trunk/FreeOrion/server/ServerApp.cpp 2010-04-30 04:19:26 UTC (rev 3568) @@ -1452,9 +1452,11 @@ // process combat turn if (m_current_combat->m_combat_turn_number) { pathing_engine.TurnStarted(m_current_combat->m_combat_turn_number); + const unsigned int MIN_ITERATIONS = 30; const unsigned int ITERATIONS = - PathingEngine::SECONDS_PER_TURN * PathingEngine::TARGET_OBJECT_UPDATES_PER_SEC; - const double ITERATION_DURATION = 1.0 / PathingEngine::TARGET_OBJECT_UPDATES_PER_SEC; + std::max(MIN_ITERATIONS, + PathingEngine::SECONDS_PER_TURN * PathingEngine::TARGET_OBJECT_UPDATES_PER_SEC); + const double ITERATION_DURATION = 1.0 * PathingEngine::SECONDS_PER_TURN / ITERATIONS; for (unsigned int i = 0; i < ITERATIONS; ++i) { pathing_engine.Update(ITERATION_DURATION, true); } |
From: <geo...@us...> - 2010-08-31 08:25:25
|
Revision: 3785 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3785&view=rev Author: geoffthemedio Date: 2010-08-31 08:25:14 +0000 (Tue, 31 Aug 2010) Log Message: ----------- Tweaked ServerApp::PostCombatProcessTurns a bit more, to fix an issue (re)appearing with the previous patch's changes, where new effects acting on a meter wouldn't be properly calculated on the first turn they were active. Also removed some test debugging code and replaced with proper generic debugging code. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2010-08-31 07:47:55 UTC (rev 3784) +++ trunk/FreeOrion/server/ServerApp.cpp 2010-08-31 08:25:14 UTC (rev 3785) @@ -1596,12 +1596,11 @@ } Logger().debugStream() << "!!!!!!!!!!!!!!!!!!!!!!AFTER UPDATING RESOURCE POOLS AND SUPPLY STUFF"; - //Logger().debugStream() << objects.Dump(); - Logger().debugStream() << objects.Object(78)->Dump(); + Logger().debugStream() << objects.Dump(); + Logger().debugStream() << "ServerApp::ProcessTurns queue progress checking"; - // Consume distributed resources to planets and on queues, create new // objects for completed production and give techs to empires that have // researched them @@ -1616,6 +1615,10 @@ } + Logger().debugStream() << "!!!!!!!!!!!!!!!!!!!!!!AFTER CHECKING QUEUE AND RESOURCE PROGRESS"; + Logger().debugStream() << objects.Dump(); + + // determine the IDs of new objects created before or during queue processing std::vector<int> new_object_ids; int current_turn = CurrentTurn(); // skip objects created on invalid turns or before this turn @@ -1629,21 +1632,25 @@ // UniverseObjects will have effects applied to them this turn, allowing // (for example) ships to have max fuel meters greater than 0 on the turn // they are created. - m_universe.ApplyMeterEffectsAndUpdateMeters(new_object_ids); + m_universe.ApplyMeterEffectsAndUpdateMeters(); + Logger().debugStream() << "!!!!!!!!!!!!!!!!!!!!!!AFTER UPDATING METERS OF ALL OBJECTS"; + Logger().debugStream() << objects.Dump(); - // Population growth or loss, health meter growth, resource current meter - // growth + // growth, etc. for (ObjectMap::iterator it = objects.begin(); it != objects.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() } + Logger().debugStream() << "!!!!!!!!!!!!!!!!!!!!!!AFTER GROWTH AND CLAMPING"; + Logger().debugStream() << objects.Dump(); + // store initial values of meters for this turn. m_universe.BackPropegateObjectMeters(); |
From: <geo...@us...> - 2011-08-13 08:12:46
|
Revision: 4132 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4132&view=rev Author: geoffthemedio Date: 2011-08-13 08:12:40 +0000 (Sat, 13 Aug 2011) Log Message: ----------- Fixed a problem with code that determined whether combat conditions were present in a system, which was considering unpopulated planets as enemies of empire-controlled planets. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2011-08-13 07:17:55 UTC (rev 4131) +++ trunk/FreeOrion/server/ServerApp.cpp 2011-08-13 08:12:40 UTC (rev 4132) @@ -994,10 +994,7 @@ Logger().errorStream() << "GetEmpireIDsWithPlanetsAtSystem couldn't get Planet with id " << *planet_it; continue; } - - if (planet->Unowned() || planet->CurrentMeterValue(METER_POPULATION) == 0.0) - ids_of_empires_with_planets_here.insert(ALL_EMPIRES); - else + if (planet->CurrentMeterValue(METER_POPULATION) > 0.0) ids_of_empires_with_planets_here.insert(planet->Owner()); } } @@ -1213,12 +1210,14 @@ } } - /** Contains information about ground combats before and after they occur. */ - struct GroundCombatInfo { - }; + /** Clears and refills \a ground_combat_info with CombatInfo structs for + * every system where ground combat should occur this turn. */ + void AssembleSystemGroundCombatInfo(std::map<int, CombatInfo>& ground_combat_info) { + CleanupSystemCombatInfo(ground_combat_info); - /** Clears and refills */ + // for each system, find if + } } namespace { @@ -1595,24 +1594,21 @@ void ServerApp::ProcessCombats() { Logger().debugStream() << "ServerApp::ProcessCombats"; - // check for combats, and resolve them. for (ServerNetworking::const_established_iterator player_it = m_networking.established_begin(); player_it != m_networking.established_end(); ++player_it) { (*player_it)->SendMessage(TurnProgressMessage((*player_it)->PlayerID(), Message::COMBAT)); } - + std::set<int> human_controlled_empire_ids = HumanControlledEmpires(this, m_networking); std::map<int, CombatInfo> system_combat_info; // map from system ID to CombatInfo for that system - AssembleSystemCombatInfo(system_combat_info); - std::set<int> human_controlled_empire_ids = HumanControlledEmpires(this, m_networking); + // collect data about locations where combat is to occur + AssembleSystemCombatInfo(system_combat_info); - // TODO: inform players of locations of controllable combats, and get // players to specify which should be controlled and which should be // auto-resolved - // loop through assembled combat infos, handling each combat to update the // various systems' CombatInfo structs for (std::map<int, CombatInfo>::iterator it = system_combat_info.begin(); it != system_combat_info.end(); ++it) { @@ -1675,6 +1671,11 @@ CleanupSystemCombatInfo(system_combat_info); + // collect data bout locations where ground combat is to occur + AssembleSystemGroundCombatInfo(system_combat_info); + + // loop through assembled combat infos, handling each ground combat to + // update the various systems CombatInfo structs } void ServerApp::PostCombatProcessTurns() |
From: <geo...@us...> - 2011-08-17 04:50:43
|
Revision: 4155 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4155&view=rev Author: geoffthemedio Date: 2011-08-17 04:50:37 +0000 (Wed, 17 Aug 2011) Log Message: ----------- -Implemented invasion processing. Preliminary, but functional when ordered from the UI by players. -Removed code duplicating when determining colony capacity of ships that are colonizing. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2011-08-16 17:19:15 UTC (rev 4154) +++ trunk/FreeOrion/server/ServerApp.cpp 2011-08-17 04:50:37 UTC (rev 4155) @@ -1209,15 +1209,6 @@ } } } - - - /** Clears and refills \a ground_combat_info with CombatInfo structs for - * every system where ground combat should occur this turn. */ - void AssembleSystemGroundCombatInfo(std::map<int, CombatInfo>& ground_combat_info) { - CleanupSystemCombatInfo(ground_combat_info); - - // for each system, find if - } } namespace { @@ -1246,39 +1237,24 @@ return false; } - // get empire to give ownership of planet to - if (ship->Unowned()) { - Logger().errorStream() << "ColonizePlanet couldn't get an empire to colonize with"; - return false; - } - int empire_id = ship->Owner(); - - // get colonist capacity of ship: sum of capacities of parts - double colonist_capacity = 0.0; const ShipDesign* design = ship->Design(); if (!design) { Logger().errorStream() << "ColonizePlanet couldn't find ship's design!"; return false; } - const std::vector<std::string>& parts = design->Parts(); - for (std::vector<std::string>::const_iterator it = parts.begin(); it != parts.end(); ++it) { - const std::string& part_name = *it; - if (part_name.empty()) - continue; - const PartType* part_type = GetPartType(part_name); - if (!part_type) { - Logger().errorStream() << "ColonizePlanet couldn't find ship part type: " << part_name; - continue; - } - if (part_type->Class() == PC_COLONY) { - colonist_capacity += boost::get<double>(part_type->Stats()); - } - } + double colonist_capacity = design->ColonyCapacity(); + if (colonist_capacity <= 0.0) { Logger().debugStream() << "ColonizePlanet colonize order executed by ship with zero colonist capacity!"; return false; } + // get empire to give ownership of planet to + if (ship->Unowned()) { + Logger().errorStream() << "ColonizePlanet couldn't get an empire to colonize with"; + return false; + } + int empire_id = ship->Owner(); // all checks passed. proceed with colonization. @@ -1324,24 +1300,32 @@ // collect, for each planet, what ships have been ordered to colonize it std::map<int, std::map<int, std::set<int> > > planet_empire_colonization_ship_ids; // map from planet ID to map from empire ID to set of ship IDs std::vector<Ship*> ships = objects.FindObjects<Ship>(); + for (std::vector<Ship*>::iterator it = ships.begin(); it != ships.end(); ++it) { const Ship* ship = *it; if (!ship) { Logger().errorStream() << "HandleColonization couldn't get ship"; continue; } - int colonize_planet_id = ship->OrderedColonizePlanet(); - const Planet* planet = objects.Object<Planet>(colonize_planet_id); - if (!planet) - continue; if (ship->Unowned()) continue; int owner_empire_id = ship->Owner(); int ship_id = ship->ID(); if (ship_id == UniverseObject::INVALID_OBJECT_ID) continue; + + int colonize_planet_id = ship->OrderedColonizePlanet(); + if (colonize_planet_id == UniverseObject::INVALID_OBJECT_ID) + continue; + const Planet* planet = objects.Object<Planet>(colonize_planet_id); + if (!planet) + continue; + if (!planet->Unowned()) + continue; + if (ship->SystemID() != planet->SystemID() || ship->SystemID() == UniverseObject::INVALID_OBJECT_ID) continue; + planet_empire_colonization_ship_ids[colonize_planet_id][owner_empire_id].insert(ship_id); } @@ -1458,6 +1442,104 @@ // has been destroyed or become invisible, or if the ship leaves // the system? } + + /** Given initial set of ground forces on planet, determine ground forces on + * planet after a turn of ground combat. */ + void ResolveGroundCombat(std::map<int, double>& empires_troops) { + if (empires_troops.empty()) + return; + int victor_id = empires_troops.begin()->first; + double victor_troops = empires_troops.begin()->second; + for (std::map<int, double>::iterator it = empires_troops.begin(); it != empires_troops.end(); ++it) { + if (it->second > victor_troops) { + victor_troops = it->second; + victor_id = it->first; + } + } + empires_troops.clear(); + empires_troops[victor_id] = victor_troops; // wipe everyone else out, with no casualties! + } + + /** Determines which ships ordered to invade planets, does invasion and + * ground combat resolution */ + void HandleInvasion(ObjectMap& objects, EmpireManager& empires) { + // collect, for each planet, what ships have been ordered to invade it + std::map<int, std::map<int, double> > planet_empire_troops; // map from planet ID to map from empire ID to pair consisting of set of ship IDs and amount of troops empires have at planet + std::vector<Ship*> ships = objects.FindObjects<Ship>(); + + for (std::vector<Ship*>::iterator it = ships.begin(); it != ships.end(); ++it) { + const Ship* ship = *it; + if (!ship) { + Logger().errorStream() << "HandleInvasion couldn't get ship"; + continue; + } + if (!ship->HasTroops()) // can't invade without troops + continue; + if (ship->SystemID() == UniverseObject::INVALID_OBJECT_ID) + continue; + int ship_id = ship->ID(); + if (ship_id == UniverseObject::INVALID_OBJECT_ID) + continue; + const ShipDesign* design = ship->Design(); + if (!design) + continue; + + int invade_planet_id = ship->OrderedInvadePlanet(); + if (invade_planet_id == UniverseObject::INVALID_OBJECT_ID) + continue; + const Planet* planet = objects.Object<Planet>(invade_planet_id); + if (!planet) + continue; + if (planet->CurrentMeterValue(METER_SHIELD) > 0.0) + continue; // can't invade shielded planets + + if (ship->SystemID() != planet->SystemID()) + continue; + + // how many troops are invading? + planet_empire_troops[invade_planet_id][ship->Owner()] += design->TroopCapacity(); + // destroy invading ships + GetUniverse().Destroy(ship_id); + // current owner may also have troops from meter + planet_empire_troops[invade_planet_id][planet->Owner()] += planet->CurrentMeterValue(METER_TROOPS) + 0.0001; // small bonus to ensure ties are won by initial owner + } + + // process each planet's invasions + for (std::map<int, std::map<int, double> >::iterator planet_it = planet_empire_troops.begin(); + planet_it != planet_empire_troops.end(); ++planet_it) + { + int planet_id = planet_it->first; + Planet* planet = objects.Object<Planet>(planet_id); + // mark planet as no longer being invaded + planet->ResetIsAboutToBeInvaded(); + + std::map<int, double>& empires_troops = planet_it->second; + ResolveGroundCombat(empires_troops); + + // who won? + if (empires_troops.size() == 1) { + int victor_id = empires_troops.begin()->first; + // single empire was victorious. conquer planet if appropriate... + // if planet is unowned and victor is an empire, or if planet is + // owned by an empire that is not the victor, conquer it + if ((planet->Unowned() && victor_id != ALL_EMPIRES) || + (!planet->Unowned() && !planet->OwnedBy(victor_id))) + { + planet->Conquer(victor_id); + } + + // regardless of whether battle resulted in conquering, it did + // likely affect the troop numbers on the planet + if (Meter* meter = planet->GetMeter(METER_TROOPS)) + meter->SetCurrent(empires_troops.begin()->second); // new troops on planet is remainder after battle + + } else { + // no troops left? + if (Meter* meter = planet->GetMeter(METER_TROOPS)) + meter->SetCurrent(0.0); + } + } + } } void ServerApp::PreCombatProcessTurns() @@ -1500,6 +1582,7 @@ HandleColonization(objects, empires); + HandleInvasion(objects, empires); // scrap orders @@ -1669,13 +1752,6 @@ CreateCombatSitReps(system_combat_info); CleanupSystemCombatInfo(system_combat_info); - - - // collect data bout locations where ground combat is to occur - AssembleSystemGroundCombatInfo(system_combat_info); - - // loop through assembled combat infos, handling each ground combat to - // update the various systems CombatInfo structs } void ServerApp::PostCombatProcessTurns() |
From: <geo...@us...> - 2011-08-17 07:30:45
|
Revision: 4160 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4160&view=rev Author: geoffthemedio Date: 2011-08-17 07:30:36 +0000 (Wed, 17 Aug 2011) Log Message: ----------- Tweaked ground combat resolution so that invading with less than enough to conquer can reduce the troops present on the planet. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2011-08-17 07:12:55 UTC (rev 4159) +++ trunk/FreeOrion/server/ServerApp.cpp 2011-08-17 07:30:36 UTC (rev 4160) @@ -1446,18 +1446,23 @@ /** Given initial set of ground forces on planet, determine ground forces on * planet after a turn of ground combat. */ void ResolveGroundCombat(std::map<int, double>& empires_troops) { - if (empires_troops.empty()) + if (empires_troops.empty() || empires_troops.size() == 1) return; - int victor_id = empires_troops.begin()->first; - double victor_troops = empires_troops.begin()->second; - for (std::map<int, double>::iterator it = empires_troops.begin(); it != empires_troops.end(); ++it) { - if (it->second > victor_troops) { - victor_troops = it->second; - victor_id = it->first; - } - } + + std::multimap<double, int> inverted_empires_troops; + for (std::map<int, double>::const_iterator it = empires_troops.begin(); it != empires_troops.end(); ++it) + inverted_empires_troops.insert(std::make_pair(it->second, it->first)); + + // everyone but victor loses all troops. victor's troops remaining are + // what the victor started with minus what the second-largest troop + // amount was + std::multimap<double, int>::reverse_iterator victor_it = inverted_empires_troops.rbegin(); + std::multimap<double, int>::reverse_iterator next_it = victor_it; next_it++; + int victor_id = victor_it->second; + double victor_troops = victor_it->first - next_it->first; + empires_troops.clear(); - empires_troops[victor_id] = victor_troops; // wipe everyone else out, with no casualties! + empires_troops[victor_id] = victor_troops; } /** Determines which ships ordered to invade planets, does invasion and |
From: <geo...@us...> - 2011-08-24 22:31:03
|
Revision: 4185 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4185&view=rev Author: geoffthemedio Date: 2011-08-24 22:30:56 +0000 (Wed, 24 Aug 2011) Log Message: ----------- -Fixed bug where planet troop strength during combat was duplicated for each attacking ship in the battle. -Added SitReps for planets being captured to original and new owners. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2011-08-24 22:29:48 UTC (rev 4184) +++ trunk/FreeOrion/server/ServerApp.cpp 2011-08-24 22:30:56 UTC (rev 4185) @@ -1471,6 +1471,7 @@ // collect, for each planet, what ships have been ordered to invade it std::map<int, std::map<int, double> > planet_empire_troops; // map from planet ID to map from empire ID to pair consisting of set of ship IDs and amount of troops empires have at planet std::vector<Ship*> ships = objects.FindObjects<Ship>(); + std::set<Planet*> planets; for (std::vector<Ship*>::iterator it = ships.begin(); it != ships.end(); ++it) { const Ship* ship = *it; @@ -1495,21 +1496,27 @@ Planet* planet = objects.Object<Planet>(invade_planet_id); if (!planet) continue; - planet->ResetIsAboutToBeInvaded(); - if (planet->CurrentMeterValue(METER_SHIELD) > 0.0) - continue; // can't invade shielded planets - if (planet->CurrentMeterValue(METER_POPULATION) <= 0.0) - continue; // can't invade unpopulated planets if (ship->SystemID() != planet->SystemID()) continue; + planets.insert(planet); + // how many troops are invading? planet_empire_troops[invade_planet_id][ship->Owner()] += design->TroopCapacity(); // destroy invading ships GetUniverse().Destroy(ship_id); + } + + for (std::set<Planet*>::iterator planet_it = planets.begin(); planet_it != planets.end(); ++planet_it) { + Planet* planet = *planet_it; + planet->ResetIsAboutToBeInvaded(); + if (planet->CurrentMeterValue(METER_SHIELD) > 0.0) + continue; // can't invade shielded planets + if (planet->CurrentMeterValue(METER_POPULATION) <= 0.0) + continue; // can't invade unpopulated planets // current owner may also have troops from meter - planet_empire_troops[invade_planet_id][planet->Owner()] += planet->CurrentMeterValue(METER_TROOPS) + 0.0001; // small bonus to ensure ties are won by initial owner + planet_empire_troops[planet->ID()][planet->Owner()] += planet->CurrentMeterValue(METER_TROOPS) + 0.0001; // small bonus to ensure ties are won by initial owner } // process each planet's invasions @@ -1522,6 +1529,16 @@ planet->ResetIsAboutToBeInvaded(); std::map<int, double>& empires_troops = planet_it->second; + // create sitreps for all empires involved in battle + std::set<int> all_involved_empires; + for (std::map<int, double>::const_iterator empire_it = empires_troops.begin(); + empire_it != empires_troops.end(); ++empire_it) + { + all_involved_empires.insert(empire_it->first); + if (Empire* empire = empires.Lookup(empire_it->first)) + empire->AddSitRepEntry(CreateGroundCombatSitRep(planet_id)); + } + ResolveGroundCombat(empires_troops); // who won? @@ -1533,7 +1550,16 @@ if ((planet->Unowned() && victor_id != ALL_EMPIRES) || (!planet->Unowned() && !planet->OwnedBy(victor_id))) { + int original_owner_id = planet->Owner(); planet->Conquer(victor_id); + + // create planet conquered sitrep for all involved empires + for (std::set<int>::const_iterator empire_it = all_involved_empires.begin(); + empire_it != all_involved_empires.end(); ++empire_it) + { + if (Empire* empire = empires.Lookup(*empire_it)) + empire->AddSitRepEntry(CreatePlanetCapturedSitRep(planet_id, victor_id)); + } } // regardless of whether battle resulted in conquering, it did @@ -1621,7 +1647,9 @@ // process movement phase // player notifications - for (ServerNetworking::const_established_iterator player_it = m_networking.established_begin(); player_it != m_networking.established_end(); ++player_it) { + for (ServerNetworking::const_established_iterator player_it = m_networking.established_begin(); + player_it != m_networking.established_end(); ++player_it) + { (*player_it)->SendMessage(TurnProgressMessage((*player_it)->PlayerID(), Message::FLEET_MOVEMENT)); } |
From: <geo...@us...> - 2011-09-01 18:06:55
|
Revision: 4211 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4211&view=rev Author: geoffthemedio Date: 2011-09-01 18:06:49 +0000 (Thu, 01 Sep 2011) Log Message: ----------- Removed some unnecessary code from ServerApp.cpp that was finding new objects created during effects execution, the results of which were not used. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2011-09-01 18:04:11 UTC (rev 4210) +++ trunk/FreeOrion/server/ServerApp.cpp 2011-09-01 18:06:49 UTC (rev 4211) @@ -1829,7 +1829,6 @@ // execute all effects and update meters prior to production, research, etc. m_universe.ApplyAllEffectsAndUpdateMeters(); - Logger().debugStream() << "!!!!!!!!!!!!!!!!!!!!!!AFTER TURN PROCESSING EFFECTS APPLICATION"; Logger().debugStream() << objects.Dump(); @@ -1881,16 +1880,6 @@ Logger().debugStream() << "!!!!!!!!!!!!!!!!!!!!!!AFTER CHECKING QUEUE AND RESOURCE PROGRESS"; Logger().debugStream() << objects.Dump(); - - // determine the IDs of new objects created before or during queue processing - std::vector<int> new_object_ids; - int current_turn = CurrentTurn(); // skip objects created on invalid turns or before this turn - if (current_turn >= 0 && current_turn != IMPOSSIBLY_LARGE_TURN) { - for (ObjectMap::const_iterator it = objects.const_begin(); it != objects.const_end(); ++it) - if (it->second->CreationTurn() == current_turn) - new_object_ids.push_back(it->first); - } - // Execute meter-related effects on objects created this turn, so that new // UniverseObjects will have effects applied to them this turn, allowing // (for example) ships to have max fuel meters greater than 0 on the turn |
From: <geo...@us...> - 2011-10-21 08:17:46
|
Revision: 4425 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4425&view=rev Author: geoffthemedio Date: 2011-10-21 08:17:40 +0000 (Fri, 21 Oct 2011) Log Message: ----------- Gave newly colonized planets a default large food allocation, similar to previous commit. This isn't actually used as their food allocation, but is necessary so conditions function correction when testing if enough food is allocated for their need. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2011-10-21 05:52:17 UTC (rev 4424) +++ trunk/FreeOrion/server/ServerApp.cpp 2011-10-21 08:17:40 UTC (rev 4425) @@ -1300,6 +1300,8 @@ planet->GetMeter(METER_TARGET_HEALTH)->SetCurrent(20.0); planet->BackPropegateMeters(); + planet->SetAllocatedFood(Meter::LARGE_VALUE); + planet->SetOwner(empire_id); const std::set<int>& planet_buildings = planet->Buildings(); |
From: <geo...@us...> - 2011-12-20 00:02:26
|
Revision: 4525 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4525&view=rev Author: geoffthemedio Date: 2011-12-20 00:02:20 +0000 (Tue, 20 Dec 2011) Log Message: ----------- Patch by Vezzra to fix AI Python startup issues on OSX. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2011-12-19 20:30:02 UTC (rev 4524) +++ trunk/FreeOrion/server/ServerApp.cpp 2011-12-20 00:02:20 UTC (rev 4525) @@ -137,6 +137,10 @@ } } +#ifdef FREEORION_MACOSX +#include <stdlib.h> +#endif + void ServerApp::CreateAIClients(const std::vector<PlayerSetupData>& player_setup_data) { // check if AI clients are needed for given setup data @@ -158,6 +162,15 @@ if (!need_AIs) return; +#ifdef FREEORION_MACOSX + // On OSX set environment variable DYLD_LIBRARY_PATH to python framework folder + // bundled with app, so the dynamic linker uses the bundled python library. + // Otherwise the dynamic linker will look for a correct python lib in system + // paths, and if it can't find it, throw an error and terminate! + // Setting environment variable here, spawned child processes will inherit it. + setenv("DYLD_LIBRARY_PATH", GetPythonHome().string().c_str(), 1); +#endif + // binary / executable to run for AI clients const std::string AI_CLIENT_EXE = AIClientExe(); |
From: <geo...@us...> - 2012-01-25 10:48:13
|
Revision: 4615 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4615&view=rev Author: geoffthemedio Date: 2012-01-25 10:48:07 +0000 (Wed, 25 Jan 2012) Log Message: ----------- Grooming Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2012-01-25 00:44:09 UTC (rev 4614) +++ trunk/FreeOrion/server/ServerApp.cpp 2012-01-25 10:48:07 UTC (rev 4615) @@ -111,8 +111,7 @@ m_fsm->initiate(); } -ServerApp::~ServerApp() -{ +ServerApp::~ServerApp() { CleanupAIs(); delete m_fsm; } @@ -120,8 +119,7 @@ void ServerApp::operator()() { Run(); } -void ServerApp::Exit(int code) -{ +void ServerApp::Exit(int code) { Logger().fatalStream() << "Initiating Exit (code " << code << " - " << (code ? "error" : "normal") << " termination)"; exit(code); } @@ -141,8 +139,7 @@ #include <stdlib.h> #endif -void ServerApp::CreateAIClients(const std::vector<PlayerSetupData>& player_setup_data) -{ +void ServerApp::CreateAIClients(const std::vector<PlayerSetupData>& player_setup_data) { // check if AI clients are needed for given setup data bool need_AIs = false; for (int i = 0; i < static_cast<int>(player_setup_data.size()); ++i) { @@ -220,8 +217,7 @@ ServerNetworking& ServerApp::Networking() { return s_app->m_networking; } -void ServerApp::Run() -{ +void ServerApp::Run() { Logger().debugStream() << "FreeOrion server waiting for network events"; std::cout << "FreeOrion server waiting for network events" << std::endl; while (1) { @@ -232,16 +228,14 @@ } } -void ServerApp::CleanupAIs() -{ +void ServerApp::CleanupAIs() { Logger().debugStream() << "ServerApp::CleanupAIs() killing " << m_ai_client_processes.size() << " AI clients."; for (std::vector<Process>::iterator it = m_ai_client_processes.begin(); it != m_ai_client_processes.end(); ++it) it->Kill(); m_ai_client_processes.clear(); } -void ServerApp::HandleMessage(Message msg, PlayerConnectionPtr player_connection) -{ +void ServerApp::HandleMessage(Message msg, PlayerConnectionPtr player_connection) { if (msg.SendingPlayer() != player_connection->PlayerID()) { Logger().errorStream() << "ServerApp::HandleMessage : Received an message with a sender ID that differs from the sending player's ID. Terminating connection."; m_networking.Disconnect(player_connection); @@ -276,8 +270,7 @@ } } -void ServerApp::HandleNonPlayerMessage(Message msg, PlayerConnectionPtr player_connection) -{ +void ServerApp::HandleNonPlayerMessage(Message msg, PlayerConnectionPtr player_connection) { switch (msg.Type()) { case Message::HOST_SP_GAME: m_fsm->process_event(HostSPGame(msg, player_connection)); break; case Message::HOST_MP_GAME: m_fsm->process_event(HostMPGame(msg, player_connection)); break; @@ -296,8 +289,7 @@ void ServerApp::PlayerDisconnected(PlayerConnectionPtr player_connection) { m_fsm->process_event(Disconnection(player_connection)); } -void ServerApp::SelectNewHost() -{ +void ServerApp::SelectNewHost() { int new_host_id = Networking::INVALID_PLAYER_ID; int old_host_id = m_networking.HostPlayerID(); @@ -331,8 +323,7 @@ } } -void ServerApp::NewSPGameInit(const SinglePlayerSetupData& single_player_setup_data) -{ +void ServerApp::NewSPGameInit(const SinglePlayerSetupData& single_player_setup_data) { // associate player IDs with player setup data. the player connection with // id == m_networking.HostPlayerID() should be the human player in // PlayerSetupData. AI player connections are assigned one of the remaining @@ -382,8 +373,7 @@ NewGameInit(single_player_setup_data, player_id_setup_data); } -void ServerApp::NewMPGameInit(const MultiplayerLobbyData& multiplayer_lobby_data) -{ +void ServerApp::NewMPGameInit(const MultiplayerLobbyData& multiplayer_lobby_data) { // associate player IDs with player setup data by matching player IDs when // available (human) and names (for AI clients which didn't have an ID // before now because the lobby data was set up without connected/established @@ -454,8 +444,7 @@ NewGameInit(multiplayer_lobby_data, player_id_setup_data); } -void ServerApp::NewGameInit(const GalaxySetupData& galaxy_setup_data, const std::map<int, PlayerSetupData>& player_id_setup_data) -{ +void ServerApp::NewGameInit(const GalaxySetupData& galaxy_setup_data, const std::map<int, PlayerSetupData>& player_id_setup_data) { Logger().debugStream() << "ServerApp::NewGameInit"; // ensure some reasonable inputs @@ -894,12 +883,9 @@ } Empire* ServerApp::GetPlayerEmpire(int player_id) const -{ - return Empires().Lookup(PlayerEmpireID(player_id)); -} +{ return Empires().Lookup(PlayerEmpireID(player_id)); } -int ServerApp::PlayerEmpireID(int player_id) const -{ +int ServerApp::PlayerEmpireID(int player_id) const { std::map<int, int>::const_iterator it = m_player_empire_ids.find(player_id); if (it != m_player_empire_ids.end()) return it->second; @@ -907,8 +893,7 @@ return ALL_EMPIRES; } -int ServerApp::EmpirePlayerID(int empire_id) const -{ +int ServerApp::EmpirePlayerID(int empire_id) const { for (std::map<int, int>::const_iterator it = m_player_empire_ids.begin(); it != m_player_empire_ids.end(); ++it) if (it->second == empire_id) return it->first; @@ -916,22 +901,15 @@ } void ServerApp::AddEmpireTurn(int empire_id) -{ - m_turn_sequence[empire_id] = 0; // std::map<int, OrderSet*> -} +{ m_turn_sequence[empire_id] = 0; } // std::map<int, OrderSet*> void ServerApp::RemoveEmpireTurn(int empire_id) -{ - m_turn_sequence.erase(empire_id); -} +{ m_turn_sequence.erase(empire_id); } void ServerApp::SetEmpireTurnOrders(int empire_id, OrderSet* order_set) -{ - m_turn_sequence[empire_id] = order_set; -} +{ m_turn_sequence[empire_id] = order_set; } -void ServerApp::ClearEmpireTurnOrders() -{ +void ServerApp::ClearEmpireTurnOrders() { for (std::map<int, OrderSet*>::iterator it = m_turn_sequence.begin(); it != m_turn_sequence.end(); ++it) { if (it->second) { delete it->second; @@ -940,8 +918,7 @@ } } -bool ServerApp::AllOrdersReceived() -{ +bool ServerApp::AllOrdersReceived() { Logger().debugStream() << "ServerApp::AllOrdersReceived()"; // Loop through to find empire ID and check for valid orders pointer @@ -1037,7 +1014,6 @@ /** Returns true iff there is an appropriate combination of objects in the * system with id \a system_id for a combat to occur. */ bool CombatConditionsInSystem(int system_id) { - std::set<int> ids_of_empires_with_combat_fleets_here; std::set<int> ids_of_empires_with_fleets_here; GetEmpireIDsWithFleetsAndCombatFleetsAtSystem(ids_of_empires_with_fleets_here, ids_of_empires_with_combat_fleets_here, system_id); @@ -1610,8 +1586,7 @@ } } -void ServerApp::PreCombatProcessTurns() -{ +void ServerApp::PreCombatProcessTurns() { EmpireManager& empires = Empires(); ObjectMap& objects = m_universe.Objects(); @@ -1733,8 +1708,7 @@ } } -void ServerApp::ProcessCombats() -{ +void ServerApp::ProcessCombats() { Logger().debugStream() << "ServerApp::ProcessCombats"; m_networking.SendMessage(TurnProgressMessage(Message::COMBAT)); @@ -1816,8 +1790,7 @@ CleanupSystemCombatInfo(system_combat_info); } -void ServerApp::PostCombatProcessTurns() -{ +void ServerApp::PostCombatProcessTurns() { EmpireManager& empires = Empires(); ObjectMap& objects = m_universe.Objects(); @@ -2034,8 +2007,7 @@ } } -void ServerApp::CheckForEmpireEliminationOrVictory() -{ +void ServerApp::CheckForEmpireEliminationOrVictory() { //EmpireManager& empires = Empires(); //ObjectMap& objects = m_universe.Objects(); @@ -2185,8 +2157,7 @@ void ServerApp::AddEmpireCombatTurn(int empire_id) { m_combat_turn_sequence[empire_id] = 0; } -void ServerApp::ClearEmpireCombatTurns() -{ +void ServerApp::ClearEmpireCombatTurns() { ClearEmpireCombatTurnOrders(); m_combat_turn_sequence.clear(); } @@ -2194,8 +2165,7 @@ void ServerApp::SetEmpireCombatTurnOrders(int empire_id, CombatOrderSet* order_set) { m_combat_turn_sequence[empire_id] = order_set; } -void ServerApp::ClearEmpireCombatTurnOrders() -{ +void ServerApp::ClearEmpireCombatTurnOrders() { for (std::map<int, CombatOrderSet*>::iterator it = m_combat_turn_sequence.begin(); it != m_combat_turn_sequence.end(); ++it) { @@ -2204,8 +2174,7 @@ } } -bool ServerApp::AllCombatOrdersReceived() -{ +bool ServerApp::AllCombatOrdersReceived() { for (std::map<int, CombatOrderSet*>::iterator it = m_combat_turn_sequence.begin(); it != m_combat_turn_sequence.end(); ++it) { @@ -2215,8 +2184,7 @@ return true; } -void ServerApp::ProcessCombatTurn() -{ +void ServerApp::ProcessCombatTurn() { PathingEngine& pathing_engine = m_current_combat->m_pathing_engine; // apply combat orders @@ -2272,8 +2240,7 @@ ++m_current_combat->m_combat_turn_number; } -bool ServerApp::CombatTerminated() -{ +bool ServerApp::CombatTerminated() { // TODO return false; } |
From: <geo...@us...> - 2012-06-23 08:25:20
|
Revision: 4922 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4922&view=rev Author: geoffthemedio Date: 2012-06-23 08:25:14 +0000 (Sat, 23 Jun 2012) Log Message: ----------- Made non-aggressive fleets be treated as non-combat fleets when determining combat conditions. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2012-06-23 06:23:13 UTC (rev 4921) +++ trunk/FreeOrion/server/ServerApp.cpp 2012-06-23 08:25:14 UTC (rev 4922) @@ -972,7 +972,7 @@ ids_of_empires_with_fleets_here.insert(fleet->Owner()); // may be ALL_EMPIRES - if (fleet->HasArmedShips()) + if (fleet->HasArmedShips() && fleet->Aggressive()) ids_of_empires_with_combat_fleets_here.insert(fleet->Owner()); } } |
From: <geo...@us...> - 2012-07-01 22:51:23
|
Revision: 4955 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4955&view=rev Author: geoffthemedio Date: 2012-07-01 22:51:17 +0000 (Sun, 01 Jul 2012) Log Message: ----------- Reworked logic that determines when battles occur in systems to account for diplomatic status, visibility, and fleet aggression settings. Battle results don't necessarily all account for these yet, however. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2012-07-01 22:50:09 UTC (rev 4954) +++ trunk/FreeOrion/server/ServerApp.cpp 2012-07-01 22:51:17 UTC (rev 4955) @@ -979,92 +979,226 @@ return retval; } - void GetEmpireIDsWithFleetsAndCombatFleetsAtSystem(std::set<int>& ids_of_empires_with_fleets_here, - std::set<int>& ids_of_empires_with_combat_fleets_here, - int system_id) - { - ids_of_empires_with_fleets_here.clear(); - ids_of_empires_with_combat_fleets_here.clear(); + void GetEmpireFleetsAtSystem(std::map<int, std::set<int> >& empire_fleets, int system_id) { + empire_fleets.clear(); + const System* system = GetSystem(system_id); + if (!system) + return; + std::vector<int> system_fleets = system->FindObjectIDs<Fleet>(); + for (std::vector<int>::const_iterator it = system_fleets.begin(); it != system_fleets.end(); ++it) { + if (const Fleet* fleet = GetFleet(*it)) + empire_fleets[fleet->Owner()].insert(*it); + } + } + void GetEmpirePlanetsAtSystem(std::map<int, std::set<int> >& empire_planets, int system_id) { + empire_planets.clear(); const System* system = GetSystem(system_id); if (!system) return; - - std::vector<int> fleet_ids = system->FindObjectIDs<Fleet>(); - for (std::vector<int>::const_iterator fleet_it = fleet_ids.begin(); fleet_it != fleet_ids.end(); ++fleet_it) { - const Fleet* fleet = GetFleet(*fleet_it); - if (!fleet) { - Logger().errorStream() << "GetEmpireIDsWithFleetsAndCombatFleetsAtSystem couldn't get Fleet with id " << *fleet_it; - continue; + std::vector<int> system_planets = system->FindObjectIDs<Planet>(); + for (std::vector<int>::const_iterator it = system_planets.begin(); it != system_planets.end(); ++it) { + if (const Planet* planet = GetPlanet(*it)) { + if (!planet->Unowned()) + empire_planets[planet->Owner()].insert(*it); + else if (planet->CurrentMeterValue(METER_POPULATION) > 0.0) + empire_planets[ALL_EMPIRES].insert(*it); } - - ids_of_empires_with_fleets_here.insert(fleet->Owner()); // may be ALL_EMPIRES - - if (fleet->HasArmedShips() && fleet->Aggressive()) - ids_of_empires_with_combat_fleets_here.insert(fleet->Owner()); } } - void GetEmpireIDsWithPlanetsAtSystem(std::set<int>& ids_of_empires_with_planets_here, int system_id) { - ids_of_empires_with_planets_here.clear(); - + void GetFleetsVisibleToEmpireAtSystem(std::set<int>& visible_fleets, int empire_id, int system_id) { + visible_fleets.clear(); const System* system = GetSystem(system_id); if (!system) + return; // no such system + std::vector<int> fleet_ids = system->FindObjectIDs<Fleet>(); + if (fleet_ids.empty()) + return; // no fleets to be seen + if (empire_id != ALL_EMPIRES && !Empires().Lookup(empire_id)) + return; // no such empire + + // for visible fleets by an empire, check visibility of fleets by that empire + if (empire_id != ALL_EMPIRES) { + for (std::vector<int>::const_iterator fleet_it = fleet_ids.begin(); + fleet_it != fleet_ids.end(); ++fleet_it) + { + Visibility fleet_vis = GetUniverse().GetObjectVisibilityByEmpire(*fleet_it, empire_id); + if (fleet_vis >= VIS_PARTIAL_VISIBILITY) + visible_fleets.insert(*fleet_it); + } return; + } - std::vector<int> planet_ids = system->FindObjectIDs<Planet>(); - for (std::vector<int>::const_iterator planet_it = planet_ids.begin(); planet_it != planet_ids.end(); ++planet_it) { - const Planet* planet = GetPlanet(*planet_it); - if (!planet) { - Logger().errorStream() << "GetEmpireIDsWithPlanetsAtSystem couldn't get Planet with id " << *planet_it; + + // now considering only fleets visible to monsters + + + // get best monster detection strength here. Use monster detection meters for this... + double monster_detection_strength_here = 0.0; + std::vector<int> all_system_ship_ids = system->FindObjectIDs<Ship>(); + for (std::vector<int>::const_iterator ship_it = all_system_ship_ids.begin(); + ship_it != all_system_ship_ids.end(); ++ship_it) + { + const Ship* ship = GetShip(*ship_it); + if (!ship || !ship->Unowned()) // only want unowned / monster ships continue; + if (ship->CurrentMeterValue(METER_DETECTION) > monster_detection_strength_here) + monster_detection_strength_here = ship->CurrentMeterValue(METER_DETECTION); + } + + // test each ship in each fleet for visibility by best monster detection here + for (std::vector<int>::const_iterator fleet_it = fleet_ids.begin(); + fleet_it != fleet_ids.end(); ++fleet_it) + { + const Fleet* fleet = GetFleet(*fleet_it); + if (!fleet) + continue; + if (fleet->Unowned()) { + visible_fleets.insert(*fleet_it); // fleet is monster, so can be sen by monsters + continue; } - if (planet->CurrentMeterValue(METER_POPULATION) > 0.0) - ids_of_empires_with_planets_here.insert(planet->Owner()); + + const std::set<int>& fleet_ship_ids = fleet->ShipIDs(); + for (std::set<int>::const_iterator ship_it = fleet_ship_ids.begin(); + ship_it != fleet_ship_ids.end(); ++ship_it) + { + const Ship* ship = GetShip(*ship_it); + if (!ship) + continue; + // if a ship is low enough stealth, its fleet can be seen by monsters + if (monster_detection_strength_here >= ship->CurrentMeterValue(METER_STEALTH)) { + visible_fleets.insert(*fleet_it); + break; // fleet is seen, so don't need to check any more ships in it + } + } } } - /** Returns true iff there is an appropriate combination of objects in the * system with id \a system_id for a combat to occur. */ bool CombatConditionsInSystem(int system_id) { - std::set<int> ids_of_empires_with_combat_fleets_here; - std::set<int> ids_of_empires_with_fleets_here; - GetEmpireIDsWithFleetsAndCombatFleetsAtSystem(ids_of_empires_with_fleets_here, ids_of_empires_with_combat_fleets_here, system_id); + // combats occur if: + // 1) empires A and B are at war, and + // 2) a) empires A and B both have fleets in a system, or + // 2) b) empire A has a fleet and empire B has a planet in a system + // 3) empire A's can see the fleet or planet of empire B + // 4) empire A's fleet is set to aggressive + // 5) empire A's fleet has at least one armed ship + // + // note: monsters are treated as an empire always at war with all other empires - // combat can occur if more than one empire has a combat fleet in system - if (ids_of_empires_with_combat_fleets_here.size() > 1) - return true; + // what empires have fleets here? + std::map<int, std::set<int> > empire_fleets_here; + GetEmpireFleetsAtSystem(empire_fleets_here, system_id); + if (empire_fleets_here.empty()) + return false; - // combat can occur if one empire has a combat fleet and another empire - // has any fleet - if (!ids_of_empires_with_combat_fleets_here.empty() && ids_of_empires_with_fleets_here.size() > 1) - return true; + // which empires have aggressive ships here? + std::set<int> empires_with_aggressive_fleets_here; + for (std::map<int, std::set<int> >::const_iterator empire_it = empire_fleets_here.begin(); + empire_it != empire_fleets_here.end(); ++empire_it) + { + int empire_id = empire_it->first; + const std::set<int>& empire_fleets = empire_it->second; + for (std::set<int>::const_iterator fleet_it = empire_fleets.begin(); + fleet_it != empire_fleets.end(); ++fleet_it) + { + const Fleet* fleet = GetFleet(*fleet_it); + if (!fleet) + continue; + if (fleet->Aggressive()) { + empires_with_aggressive_fleets_here.insert(empire_id); + break; + } + } + } + if (empires_with_aggressive_fleets_here.empty()) + return false; + // what empires have planets here? + std::map<int, std::set<int> > empire_planets_here; + GetEmpirePlanetsAtSystem(empire_planets_here, system_id); + if (empire_planets_here.empty() && empire_fleets_here.size() <= 1) + return false; - std::set<int> ids_of_empires_with_planets_here; - GetEmpireIDsWithPlanetsAtSystem(ids_of_empires_with_planets_here, system_id); + // all empires with something here + std::set<int> empires_here; + for (std::map<int, std::set<int> >::const_iterator it = empire_fleets_here.begin(); + it != empire_fleets_here.end(); ++it) + { empires_here.insert(it->first); } + for (std::map<int, std::set<int> >::const_iterator it = empire_planets_here.begin(); + it != empire_planets_here.end(); ++it) + { empires_here.insert(it->first); } + // what combinations of present empires are at war? + std::map<int, std::set<int> > empires_here_at_war; // for each empire, what other empires here is it at war with? + for (std::set<int>::const_iterator emp1_it = empires_here.begin(); + emp1_it != empires_here.end(); ++emp1_it) + { + std::set<int>::const_iterator emp2_it = emp1_it; + ++emp2_it; + for (; emp2_it != empires_here.end(); ++emp2_it) { + if (*emp1_it == ALL_EMPIRES || *emp2_it == ALL_EMPIRES || + Empires().GetDiplomaticStatus(*emp1_it, *emp2_it) == DIPLO_WAR) + { + empires_here_at_war[*emp1_it].insert(*emp2_it); + empires_here_at_war[*emp2_it].insert(*emp1_it); + } + } + } + if (empires_here_at_war.empty()) + return false; - // combat can also occur if there is at least one fleet and one - // other empire's planetary defenses that can harm the fleets - if (!ids_of_empires_with_combat_fleets_here.empty() && !ids_of_empires_with_planets_here.empty()) { + // is an empire with an aggressive fleet here at war with an empire that + // has a planet here? + for (std::set<int>::const_iterator empire1_it = empires_with_aggressive_fleets_here.begin(); + empire1_it != empires_with_aggressive_fleets_here.end(); ++empire1_it) + { + int aggressive_empire_id = *empire1_it; - for (std::set<int>::const_iterator planet_owner_it = ids_of_empires_with_planets_here.begin(); - planet_owner_it != ids_of_empires_with_planets_here.end(); - ++planet_owner_it) + // what empires is the aggressive empire at war with? + const std::set<int>& at_war_with_empire_ids = empires_here_at_war[aggressive_empire_id]; + + // do any of the empires at war with the aggressive empire have a planet here? + for (std::set<int>::const_iterator at_war_empire_it = at_war_with_empire_ids.begin(); + at_war_empire_it != at_war_with_empire_ids.end(); ++at_war_empire_it) { - int planet_owner_id = *planet_owner_it; + int at_war_empire_id = *at_war_empire_it; + if (empire_planets_here.find(at_war_empire_id) != empire_planets_here.end()) + return true; + } + } - // find a combat fleet owned by a different empire - for (std::set<int>::const_iterator combat_fleet_owner_it = ids_of_empires_with_combat_fleets_here.begin(); - combat_fleet_owner_it != ids_of_empires_with_combat_fleets_here.end(); - ++combat_fleet_owner_it) - { - int combat_fleet_owner_id = *combat_fleet_owner_it; - if (combat_fleet_owner_id != planet_owner_id) - return true; - } + // is an empire with an aggressive fleet here able to see a fleet of an + // empire it is at war with here? + for (std::set<int>::const_iterator empire1_it = empires_with_aggressive_fleets_here.begin(); + empire1_it != empires_with_aggressive_fleets_here.end(); ++empire1_it) + { + int aggressive_empire_id = *empire1_it; + + // what empires is the aggressive empire at war with? + const std::set<int>& at_war_with_empire_ids = empires_here_at_war[aggressive_empire_id]; + if (at_war_with_empire_ids.empty()) + continue; + + // what fleets can the aggressive empire see? + std::set<int> aggressive_empire_visible_fleets; + GetFleetsVisibleToEmpireAtSystem(aggressive_empire_visible_fleets, aggressive_empire_id, system_id); + + // is any fleet owned by an empire at war with aggressive empire? + for (std::set<int>::const_iterator fleet_it = aggressive_empire_visible_fleets.begin(); + fleet_it != aggressive_empire_visible_fleets.end(); ++fleet_it) + { + int fleet_id = *fleet_it; + const Fleet* fleet = GetFleet(*fleet_it); + if (!fleet) + continue; + int visible_fleet_empire_id = fleet->Owner(); + + if (aggressive_empire_id != visible_fleet_empire_id && + at_war_with_empire_ids.find(visible_fleet_empire_id) != at_war_with_empire_ids.end()) + { return true; } // an aggressive empire can see a fleet onwned by an empire it is at war with } } @@ -1098,11 +1232,13 @@ * meter values from combat aren't lost when resetting meters during meter * updating after combat. */ void BackProjectSystemCombatInfoObjectMeters(std::map<int, CombatInfo>& system_combat_info) { - for (std::map<int, CombatInfo>::iterator it = system_combat_info.begin(); it != system_combat_info.end(); ++it) { + for (std::map<int, CombatInfo>::iterator it = system_combat_info.begin(); + it != system_combat_info.end(); ++it) + { ObjectMap& objects = it->second.objects; for (ObjectMap::iterator obj_it = objects.begin(); obj_it != objects.end(); ++obj_it) obj_it->second->BackPropegateMeters(); - } + } } /** Takes contents of CombatInfo struct and puts it into the universe. |
From: <geo...@us...> - 2012-07-02 21:09:08
|
Revision: 4962 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4962&view=rev Author: geoffthemedio Date: 2012-07-02 21:09:02 +0000 (Mon, 02 Jul 2012) Log Message: ----------- Made fleet arrival sitreps be generated for all visible arrived fleets, instead of just the player's own fleets. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2012-07-02 15:00:26 UTC (rev 4961) +++ trunk/FreeOrion/server/ServerApp.cpp 2012-07-02 21:09:02 UTC (rev 4962) @@ -1816,14 +1816,6 @@ // TODO: Do movement incrementally, and if the moving fleet encounters // stationary combat fleets or planetary defenses that can hurt it, it // must be resolved as a combat. - - // SitRep for fleets having arrived at destinations, to all owners of those fleets - if (fleet->ArrivedThisTurn() && !fleet->Unowned()) { - Empire* empire = empires.Lookup(fleet->Owner()); - if (!empire) - continue; - empire->AddSitRepEntry(CreateFleetArrivedAtDestinationSitRep(fleet->SystemID(), fleet->ID())); - } } @@ -1832,6 +1824,22 @@ m_universe.UpdateEmpireLatestKnownObjectsAndVisibilityTurns(); + // SitRep for fleets having arrived at destinations + for (std::vector<Fleet*>::iterator it = fleets.begin(); it != fleets.end(); ++it) { + // save for possible SitRep generation after moving... + const Fleet* fleet = *it; + if (!fleet || !fleet->ArrivedThisTurn()) + continue; + // sitreps for all empires that can see fleet at new location + for (EmpireManager::const_iterator empire_it = Empires().begin(); + empire_it != Empires().end(); ++empire_it) + { + if (fleet->GetVisibility(empire_it->first) >= VIS_BASIC_VISIBILITY) + empire_it->second->AddSitRepEntry(CreateFleetArrivedAtDestinationSitRep(fleet->SystemID(), fleet->ID())); + } + } + + // update fleet routes after movement for (std::vector<Fleet*>::iterator it = fleets.begin(); it != fleets.end(); ++it) { Fleet* fleet = *it; |
From: <geo...@us...> - 2012-07-07 18:19:50
|
Revision: 4992 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4992&view=rev Author: geoffthemedio Date: 2012-07-07 18:19:44 +0000 (Sat, 07 Jul 2012) Log Message: ----------- Made only aggressive armed fleets able to block other empires' colonization. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2012-07-07 06:54:41 UTC (rev 4991) +++ trunk/FreeOrion/server/ServerApp.cpp 2012-07-07 18:19:44 UTC (rev 4992) @@ -1525,8 +1525,7 @@ // 2) multiple empires try to colonize the same planet, but only one empire has armed ships in the system // otherwise, no colonization happens in the system for (std::map<int, std::map<int, std::set<int> > >::iterator planet_it = planet_empire_colonization_ship_ids.begin(); - planet_it != planet_empire_colonization_ship_ids.end(); - ++planet_it) + planet_it != planet_empire_colonization_ship_ids.end(); ++planet_it) { int planet_id = planet_it->first; Planet* planet = objects.Object<Planet>(planet_id); @@ -1547,7 +1546,7 @@ std::vector<int> system_fleet_ids = system->FindObjectIDs<Fleet>(); for (std::vector<int>::const_iterator fleet_it = system_fleet_ids.begin(); fleet_it != system_fleet_ids.end(); ++fleet_it) { const Fleet* fleet = objects.Object<Fleet>(*fleet_it); - if (fleet->HasArmedShips()) + if (fleet->Aggressive() && fleet->HasArmedShips()) empires_with_armed_ships_in_system.insert(fleet->Owner()); // may include ALL_EMPIRES, which is fine; this makes monsters prevent colonization } @@ -1560,8 +1559,7 @@ // check if any of the ships that want to colonize belong to the empire with armed ships std::map<int, std::set<int> >& empire_colonization_ship_map = planet_it->second; for (std::map<int, std::set<int> >::iterator empire_it = empire_colonization_ship_map.begin(); - empire_it != empire_colonization_ship_map.end(); - ++empire_it) + empire_it != empire_colonization_ship_map.end(); ++empire_it) { int empire_id = empire_it->first; if (!empires_with_armed_ships_in_system.empty() && @@ -1607,8 +1605,7 @@ // ships that wanted to colonize this planet if (planet_colonized) { for (std::map<int, std::set<int> >::iterator empire_it = empire_colonization_ship_map.begin(); - empire_it != empire_colonization_ship_map.end(); - ++empire_it) + empire_it != empire_colonization_ship_map.end(); ++empire_it) { std::set<int>& colonizing_ships = empire_it->second; for (std::set<int>::const_iterator ship_it = colonizing_ships.begin(); ship_it != colonizing_ships.end(); ++ship_it) @@ -1873,8 +1870,7 @@ // send partial turn updates to all players after orders and movement for (ServerNetworking::const_established_iterator player_it = m_networking.established_begin(); - player_it != m_networking.established_end(); - ++player_it) + player_it != m_networking.established_end(); ++player_it) { PlayerConnectionPtr player = *player_it; int player_id = player->PlayerID(); |
From: <geo...@us...> - 2012-07-08 00:41:51
|
Revision: 4997 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4997&view=rev Author: geoffthemedio Date: 2012-07-08 00:41:44 +0000 (Sun, 08 Jul 2012) Log Message: ----------- Reworked / tweaked some colonization logic for cases of multiple empires colonizing the same planet or enemy empires with agressive armed ships in the same system. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2012-07-07 23:40:49 UTC (rev 4996) +++ trunk/FreeOrion/server/ServerApp.cpp 2012-07-08 00:41:44 UTC (rev 4997) @@ -1403,13 +1403,13 @@ namespace { /** Does colonization, with safety checks */ - bool ColonizePlanet(ObjectMap& objects, int ship_id, int planet_id) { - Ship* ship = objects.Object<Ship>(ship_id); + bool ColonizePlanet(int ship_id, int planet_id) { + Ship* ship = GetShip(ship_id); if (!ship) { Logger().errorStream() << "ColonizePlanet couldn't get ship with id " << ship_id; return false; } - Planet* planet = objects.Object<Planet>(planet_id); + Planet* planet = GetPlanet(planet_id); if (!planet) { Logger().errorStream() << "ColonizePlanet couldn't get planet with id " << planet_id; return false; @@ -1471,7 +1471,7 @@ const std::set<int>& planet_buildings = planet->Buildings(); for (std::set<int>::const_iterator it = planet_buildings.begin(); it != planet_buildings.end(); ++it) { - if (Building* building = objects.Object<Building>(*it)) { + if (Building* building = GetBuilding(*it)) { building->SetOwner(empire_id); // TODO: only add owner if empire has visibility of building. Need to add a check for this every turn... maybe doesn't need to be done during colonization at all? } else { Logger().errorStream() << "ColonizePlanet couldn't find building with id: " << *it; @@ -1483,10 +1483,10 @@ /** Determines which ships ordered to colonize planet succeed, does * appropriate colonization, and cleans up after colonization orders */ - void HandleColonization(ObjectMap& objects, EmpireManager& empires) { + void HandleColonization() { // collect, for each planet, what ships have been ordered to colonize it std::map<int, std::map<int, std::set<int> > > planet_empire_colonization_ship_ids; // map from planet ID to map from empire ID to set of ship IDs - std::vector<Ship*> ships = objects.FindObjects<Ship>(); + std::vector<Ship*> ships = GetUniverse().Objects().FindObjects<Ship>(); for (std::vector<Ship*>::iterator it = ships.begin(); it != ships.end(); ++it) { const Ship* ship = *it; @@ -1504,7 +1504,7 @@ int colonize_planet_id = ship->OrderedColonizePlanet(); if (colonize_planet_id == INVALID_OBJECT_ID) continue; - Planet* planet = objects.Object<Planet>(colonize_planet_id); + Planet* planet = GetPlanet(colonize_planet_id); if (!planet) continue; @@ -1519,21 +1519,29 @@ std::vector<int> newly_colonize_planet_ids; - - // execute colonization when: - // 1) a single empire is colonizing a planet in a system that contains no enemy armed ships - // 2) multiple empires try to colonize the same planet, but only one empire has armed ships in the system - // otherwise, no colonization happens in the system + // execute colonization except when: + // 1) an enemy empire has armed aggressive ships in the system + // 2) multiple empires try to colonize a planet on the same turn for (std::map<int, std::map<int, std::set<int> > >::iterator planet_it = planet_empire_colonization_ship_ids.begin(); planet_it != planet_empire_colonization_ship_ids.end(); ++planet_it) { + // can't colonize if multiple empires attempting to do so on same turn + std::map<int, std::set<int> >& empires_ships_colonizing = planet_it->second; + if (empires_ships_colonizing.size() != 1) + continue; + int colonizing_empire_id = empires_ships_colonizing.begin()->first; + + const std::set<int>& empire_ships_colonizing = empires_ships_colonizing.begin()->second; + if (empire_ships_colonizing.empty()) + continue; + int colonizing_ship_id = *empire_ships_colonizing.begin(); + int planet_id = planet_it->first; - Planet* planet = objects.Object<Planet>(planet_id); + const Planet* planet = GetPlanet(planet_id); if (!planet) { Logger().errorStream() << "HandleColonization couldn't get planet with id " << planet_id; continue; } - int system_id = planet->SystemID(); const System* system = GetSystem(system_id); if (!system) { @@ -1541,82 +1549,49 @@ continue; } - // find which empires have armed ships in system + // find which empires have aggressive armed ships in system std::set<int> empires_with_armed_ships_in_system; std::vector<int> system_fleet_ids = system->FindObjectIDs<Fleet>(); for (std::vector<int>::const_iterator fleet_it = system_fleet_ids.begin(); fleet_it != system_fleet_ids.end(); ++fleet_it) { - const Fleet* fleet = objects.Object<Fleet>(*fleet_it); + const Fleet* fleet = GetFleet(*fleet_it); if (fleet->Aggressive() && fleet->HasArmedShips()) empires_with_armed_ships_in_system.insert(fleet->Owner()); // may include ALL_EMPIRES, which is fine; this makes monsters prevent colonization } - // no empires can colonize if there are more than one empire's armed fleets in system - if (empires_with_armed_ships_in_system.size() > 1) - continue; - - bool planet_colonized = false; - - // check if any of the ships that want to colonize belong to the empire with armed ships - std::map<int, std::set<int> >& empire_colonization_ship_map = planet_it->second; - for (std::map<int, std::set<int> >::iterator empire_it = empire_colonization_ship_map.begin(); - empire_it != empire_colonization_ship_map.end(); ++empire_it) + // are any of the empires with armed ships in the system enemies of the colonzing empire? + bool colonize_blocked = false; + for (std::set<int>::const_iterator empire_it = empires_with_armed_ships_in_system.begin(); + empire_it != empires_with_armed_ships_in_system.end(); ++empire_it) { - int empire_id = empire_it->first; - if (!empires_with_armed_ships_in_system.empty() && - empires_with_armed_ships_in_system.find(empire_id) == empires_with_armed_ships_in_system.end()) - { - // this empire can't colonize here this turn + int armed_ship_empire_id = *empire_it; + if (armed_ship_empire_id == colonizing_empire_id) continue; + if (armed_ship_empire_id == ALL_EMPIRES || + Empires().GetDiplomaticStatus(colonizing_empire_id, armed_ship_empire_id) == DIPLO_WAR) + { + colonize_blocked = true; + break; } + } - std::set<int>& colonizing_ships = empire_it->second; - if (colonizing_ships.empty()) { - Logger().errorStream() << "HandleColonization got empty set of ships attempting to colonize planet for an empire?!"; - continue; - } + if (colonize_blocked) + continue; - // pick the first ship this empire has that is trying to colonize this planet. - int ship_id = *colonizing_ships.begin(); + // do colonization + if (!ColonizePlanet(colonizing_ship_id, planet_id)) + continue; // skip sitrep if colonization failed + // record successful colonization + newly_colonize_planet_ids.push_back(planet_id); - // do colonization - if (!ColonizePlanet(objects, ship_id, planet_id)) - continue; // skip sitrep if colonization failed - - // record successful colonization - planet_colonized = true; - newly_colonize_planet_ids.push_back(planet_id); - - // remove ship from ships that wanted to colonize - colonizing_ships.erase(ship_id); - - // sitrep about colonization - Empire* empire = empires.Lookup(empire_id); - if (!empire) { - Logger().errorStream() << "HandleColonization couldn't get empire with id " << empire_id; - } else { - empire->AddSitRepEntry(CreatePlanetColonizedSitRep(planet_id)); - } - - break; // only one colonization per planet. + // sitrep about colonization + Empire* empire = Empires().Lookup(colonizing_empire_id); + if (!empire) { + Logger().errorStream() << "HandleColonization couldn't get empire with id " << colonizing_empire_id; + } else { + empire->AddSitRepEntry(CreatePlanetColonizedSitRep(planet_id)); } - - // if planet was colonized, remove colonize status from any other - // ships that wanted to colonize this planet - if (planet_colonized) { - for (std::map<int, std::set<int> >::iterator empire_it = empire_colonization_ship_map.begin(); - empire_it != empire_colonization_ship_map.end(); ++empire_it) - { - std::set<int>& colonizing_ships = empire_it->second; - for (std::set<int>::const_iterator ship_it = colonizing_ships.begin(); ship_it != colonizing_ships.end(); ++ship_it) - if (Ship* ship = objects.Object<Ship>(*ship_it)) - ship->ClearColonizePlanet(); - } - } } - // TODO elsewhere: clear colonization planet of ships when that planet - // has been destroyed or become invisible, or if the ship leaves - // the system? } /** Given initial set of ground forces on planet, determine ground forces on @@ -1643,10 +1618,10 @@ /** Determines which ships ordered to invade planets, does invasion and * ground combat resolution */ - void HandleInvasion(ObjectMap& objects, EmpireManager& empires) { + void HandleInvasion() { // collect, for each planet, what ships have been ordered to invade it std::map<int, std::map<int, double> > planet_empire_troops; // map from planet ID to map from empire ID to pair consisting of set of ship IDs and amount of troops empires have at planet - std::vector<Ship*> ships = objects.FindObjects<Ship>(); + std::vector<Ship*> ships = GetUniverse().Objects().FindObjects<Ship>(); std::set<Planet*> planets; for (std::vector<Ship*>::iterator it = ships.begin(); it != ships.end(); ++it) { @@ -1669,7 +1644,7 @@ int invade_planet_id = ship->OrderedInvadePlanet(); if (invade_planet_id == INVALID_OBJECT_ID) continue; - Planet* planet = objects.Object<Planet>(invade_planet_id); + Planet* planet = GetPlanet(invade_planet_id); if (!planet) continue; @@ -1700,7 +1675,7 @@ planet_it != planet_empire_troops.end(); ++planet_it) { int planet_id = planet_it->first; - Planet* planet = objects.Object<Planet>(planet_id); + Planet* planet = GetPlanet(planet_id); // mark planet as no longer being invaded planet->ResetIsAboutToBeInvaded(); @@ -1711,7 +1686,7 @@ empire_it != empires_troops.end(); ++empire_it) { all_involved_empires.insert(empire_it->first); - if (Empire* empire = empires.Lookup(empire_it->first)) + if (Empire* empire = Empires().Lookup(empire_it->first)) empire->AddSitRepEntry(CreateGroundCombatSitRep(planet_id)); } @@ -1732,7 +1707,7 @@ for (std::set<int>::const_iterator empire_it = all_involved_empires.begin(); empire_it != all_involved_empires.end(); ++empire_it) { - if (Empire* empire = empires.Lookup(*empire_it)) + if (Empire* empire = Empires().Lookup(*empire_it)) empire->AddSitRepEntry(CreatePlanetCapturedSitRep(planet_id, victor_id)); } } @@ -1786,8 +1761,8 @@ ClearEmpireTurnOrders(); - HandleColonization(objects, empires); - HandleInvasion(objects, empires); + HandleColonization(); + HandleInvasion(); // scrap orders |
From: <geo...@us...> - 2012-10-28 05:44:40
|
Revision: 5347 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=5347&view=rev Author: geoffthemedio Date: 2012-10-28 05:44:34 +0000 (Sun, 28 Oct 2012) Log Message: ----------- Fixed by Dilvish for unopposed invasions that were being skipped. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2012-10-27 23:49:29 UTC (rev 5346) +++ trunk/FreeOrion/server/ServerApp.cpp 2012-10-28 05:44:34 UTC (rev 5347) @@ -1653,6 +1653,7 @@ // how many troops are invading? planet_empire_troops[invade_planet_id][ship->Owner()] += design->TroopCapacity(); // destroy invading ships + Logger().debugStream() << "HandleInvasion has accounted for "<< design->TroopCapacity() << " troops to invade " << planet->Name() << " and is destroying ship " << ship_id << " named " << ship->Name(); GetUniverse().Destroy(ship_id); } @@ -1679,29 +1680,34 @@ { int planet_id = planet_it->first; Planet* planet = GetPlanet(planet_id); + std::set<int> all_involved_empires; std::map<int, double>& empires_troops = planet_it->second; - if (empires_troops.size() < 2) - continue; // no single participant battles... + if (empires_troops.size() < 2) { // no single participant battles + if ( planet->OwnedBy( empires_troops.begin()->first ) ) { + continue; // if troops all belong to planet owner, nothing to do... + } else { + Logger().debugStream() << "Ground combat on " << planet->Name() << " was unopposed"; + } + } else { - Logger().debugStream() << "Ground combat on" << planet->Name(); - for (std::map<int, double>::const_iterator empire_it = empires_troops.begin(); + Logger().debugStream() << "Ground combat on " << planet->Name(); + for (std::map<int, double>::const_iterator empire_it = empires_troops.begin(); + empire_it != empires_troops.end(); ++empire_it) + { Logger().debugStream() << " empire: " << empire_it->first << ": " << empire_it->second; } + + + // create sitreps for all empires involved in battle + for (std::map<int, double>::const_iterator empire_it = empires_troops.begin(); empire_it != empires_troops.end(); ++empire_it) - { Logger().debugStream() << " empire: " << empire_it->first << ": " << empire_it->second; } + { + all_involved_empires.insert(empire_it->first); + if (Empire* empire = Empires().Lookup(empire_it->first)) + empire->AddSitRepEntry(CreateGroundCombatSitRep(planet_id)); + } - - // create sitreps for all empires involved in battle - std::set<int> all_involved_empires; - for (std::map<int, double>::const_iterator empire_it = empires_troops.begin(); - empire_it != empires_troops.end(); ++empire_it) - { - all_involved_empires.insert(empire_it->first); - if (Empire* empire = Empires().Lookup(empire_it->first)) - empire->AddSitRepEntry(CreateGroundCombatSitRep(planet_id)); + ResolveGroundCombat(empires_troops); } - - ResolveGroundCombat(empires_troops); - // who won? if (empires_troops.size() == 1) { int victor_id = empires_troops.begin()->first; |
From: <geo...@us...> - 2013-01-10 10:23:42
|
Revision: 5626 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=5626&view=rev Author: geoffthemedio Date: 2013-01-10 10:23:35 +0000 (Thu, 10 Jan 2013) Log Message: ----------- Added extra step to invasion handing so the original owner gets an updated copy of the planet if its ownership changes. This should prevent cases of ownership changes not being shown in the UI. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2013-01-10 09:21:42 UTC (rev 5625) +++ trunk/FreeOrion/server/ServerApp.cpp 2013-01-10 10:23:35 UTC (rev 5626) @@ -201,14 +201,14 @@ args.push_back("\"" + GetOptionsDB().Get<std::string>("resource-dir") + "\""); args.push_back("--log-level"); args.push_back(GetOptionsDB().Get<std::string>("log-level")); - + Logger().debugStream() << "starting " << AI_CLIENT_EXE << " with GameSetup.ai-aggression set to " << maxAggr; m_ai_client_processes.push_back(Process(AI_CLIENT_EXE, args)); Logger().debugStream() << "done starting " << AI_CLIENT_EXE; } - + // set initial AI process priority to low SetAIsProcessPriorityToLow(true); } @@ -1800,6 +1800,9 @@ ResolveGroundCombat(empires_troops); } + + int planet_initial_owner_id = planet->Owner(); + // who won? if (empires_troops.size() == 1) { int victor_id = empires_troops.begin()->first; @@ -1846,7 +1849,6 @@ if (Meter* meter = planet->GetMeter(METER_TROOPS)) meter->SetCurrent(empires_troops.begin()->second); // new troops on planet is remainder after battle - } else { // no troops left? if (Meter* meter = planet->GetMeter(METER_TROOPS)) @@ -1856,6 +1858,13 @@ } planet->BackPropegateMeters(); + + // knowledge update to ensure previous owner of planet knows who owns it now? + if (planet_initial_owner_id != ALL_EMPIRES && planet_initial_owner_id != planet->Owner()) { + // get empire's knowledge of object + ObjectMap& empire_latest_known_objects = EmpireKnownObjects(planet_initial_owner_id); + empire_latest_known_objects.Copy(planet, planet_initial_owner_id); + } } } } |
From: <Bi...@us...> - 2013-01-28 02:52:39
|
Revision: 5688 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=5688&view=rev Author: Bigjoe5 Date: 2013-01-28 02:52:33 +0000 (Mon, 28 Jan 2013) Log Message: ----------- - Prevented ships from attacking planets of which they have only basic visibility. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2013-01-27 21:15:11 UTC (rev 5687) +++ trunk/FreeOrion/server/ServerApp.cpp 2013-01-28 02:52:33 UTC (rev 5688) @@ -1117,7 +1117,7 @@ { // include planets visible to empire Visibility planet_vis = GetUniverse().GetObjectVisibilityByEmpire(*planet_it, empire_id); - if (planet_vis < VIS_BASIC_VISIBILITY) + if (planet_vis <= VIS_BASIC_VISIBILITY) continue; // skip planets that have no owner and that are unpopulated; don't matter for combat conditions test const Planet* planet = GetPlanet(*planet_it); |
From: <geo...@us...> - 2013-02-24 10:02:30
|
Revision: 5797 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=5797&view=rev Author: geoffthemedio Date: 2013-02-24 10:02:23 +0000 (Sun, 24 Feb 2013) Log Message: ----------- Reworked how save game data is processed and sent to players when loading multiplayer games. Based initially on patch by Dilvish, but completely rewritten. Seems to work to let MP games with AIs load, although issues can still occur if loading with the wrong number of AI players added in the lobby. Modified Paths: -------------- trunk/FreeOrion/server/ServerApp.cpp Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2013-02-24 09:30:37 UTC (rev 5796) +++ trunk/FreeOrion/server/ServerApp.cpp 2013-02-24 10:02:23 UTC (rev 5797) @@ -563,7 +563,7 @@ // set server state info for new game - m_current_turn = BEFORE_FIRST_TURN; + m_current_turn = BEFORE_FIRST_TURN; m_victors.clear(); @@ -581,7 +581,10 @@ m_current_turn = 1; - // record empires for each active player: ID of empire and player should be the same when creating a new game. + // record empires for each active player: ID of empire and player should + // be the same when creating a new game. Note: active_players_id_setup_data + // contains only ids of players who control an empire; observers and + // moderators are not included. for (std::map<int, PlayerSetupData>::const_iterator player_setup_it = active_players_id_setup_data.begin(); player_setup_it != active_players_id_setup_data.end(); ++player_setup_it) { @@ -696,6 +699,133 @@ LoadGameInit(player_save_game_data, player_id_to_save_game_data_index, server_save_game_data); } +namespace { + /** Verifies that a human player is connected with the indicated \a id. */ + bool HumanPlayerWithIdConnected(const ServerNetworking& sn, int id) { + // make sure there is a human player connected with the player id + // matching what this PlayerSetupData say + ServerNetworking::const_established_iterator established_player_it = sn.GetPlayer(id); + if (established_player_it == sn.established_end()) { + Logger().errorStream() << "ServerApp::LoadMPGameInit couldn't find player connection for " + << "human player setup data with player id: " << id; + return false; + } + const PlayerConnectionPtr player_connection = *established_player_it; + if (player_connection->GetClientType() != Networking::CLIENT_TYPE_HUMAN_PLAYER) { + Logger().errorStream() << "ServerApp::LoadMPGameInit found player connection of wrong type " + << "for human player setup data with player id: " << id; + return false; + } + return true; + } + + /** Returns index into vector parameter that matches parameter empire id. */ + int VectorIndexForPlayerSaveGameDataForEmpireID(const std::vector<PlayerSaveGameData>& player_save_game_data, + int empire_id) + { + if (empire_id == ALL_EMPIRES) + return -1; + // find save game data vector index that has requested empire id + for (int i = 0; i < static_cast<int>(player_save_game_data.size()); ++i) { + const PlayerSaveGameData& psgd = player_save_game_data.at(i); + if (psgd.m_empire_id == empire_id) + return i; + } + return -1; + } + + /** Adds entry to \a player_id_to_save_game_data_index after validation. */ + void GetSaveGameDataIndexForHumanPlayer(std::vector<std::pair<int, int> >& player_id_to_save_game_data_index, + const PlayerSetupData& psd, int setup_data_player_id, + const std::vector<PlayerSaveGameData>& player_save_game_data, + const ServerNetworking& sn) + { + // safety check: setup data has valid empire assigned + if (psd.m_save_game_empire_id == ALL_EMPIRES) { + Logger().errorStream() << "ServerApp::LoadMPGameInit got player setup data for human player " + << "with no empire assigned..."; + return; + } + + // safety check: id-matched player is connected + bool consistent_human_player_connected = HumanPlayerWithIdConnected(sn, setup_data_player_id); + if (!consistent_human_player_connected) + return; // error message logged in HumanPlayerWithIdConnected + + // determine and store save game data index for this player + int index = VectorIndexForPlayerSaveGameDataForEmpireID(player_save_game_data, psd.m_save_game_empire_id); + if (index != -1) { + player_id_to_save_game_data_index.push_back(std::make_pair(setup_data_player_id, index)); + } else { + Logger().errorStream() << "ServerApp::LoadMPGameInit couldn't find save game data for " + << "human player with assigned empire id: " << psd.m_save_game_empire_id; + } + } + + /** Returns ID of AI player with the indicated \a player_name. */ + int AIPlayerIDWithName(const ServerNetworking& sn, const std::string& player_name) { + if (player_name.empty()) + return Networking::INVALID_PLAYER_ID; + + for (ServerNetworking::const_established_iterator established_player_it = sn.established_begin(); + established_player_it != sn.established_end(); ++established_player_it) + { + const PlayerConnectionPtr player_connection = *established_player_it; + if (player_connection->PlayerName() == player_name && + player_connection->GetClientType() == Networking::CLIENT_TYPE_AI_PLAYER) + { return player_connection->PlayerID(); } + } + return Networking::INVALID_PLAYER_ID; + } + + /** Adds entry to \a player_id_to_save_game_data_index after validation. */ + void GetSaveGameDataIndexForAIPlayer(std::vector<std::pair<int, int> >& player_id_to_save_game_data_index, + const PlayerSetupData& psd, + const std::vector<PlayerSaveGameData>& player_save_game_data, + const ServerNetworking& sn) + { + // For AI players, the multplayer setup data does not specify a + // player ID because the AI processes aren't run until after the + // game settings are confirmed and the game started in the UI, + // and thus the AI clients don't connect and get assigned player + // ids until after the lobby setup is done. + // + // In order to assign save game data to players (ie. determine + // the save game data vector index for each player id), need to + // match another property in the setup data: the AI player names. + // + // So: attempt to find player connections that have the same name + // as is listed in the player setup data for AI players. + + // safety check: setup data has valid empire assigned + if (psd.m_save_game_empire_id == ALL_EMPIRES) { + Logger().errorStream() << "ServerApp::LoadMPGameInit got player setup data for AI player " + << "with no empire assigned..."; + return; + } + + // get ID of name-matched AI player + int player_id = AIPlayerIDWithName(sn, psd.m_player_name); + if (player_id == Networking::INVALID_PLAYER_ID) { + Logger().errorStream() << "ServerApp::LoadMPGameInit couldn't find expected AI player with name " << psd.m_player_name; + return; + } + + Logger().debugStream() << "ServerApp::LoadMPGameInit matched player named " << psd.m_player_name + << " to setup data player id " << player_id + << " with setup data empire id " << psd.m_save_game_empire_id; + + // determine and store save game data index for this player + int index = VectorIndexForPlayerSaveGameDataForEmpireID(player_save_game_data, psd.m_save_game_empire_id); + if (index != -1) { + player_id_to_save_game_data_index.push_back(std::make_pair(player_id, index)); + } else { + Logger().errorStream() << "ServerApp::LoadMPGameInit couldn't find save game data for " + << "human player with assigned empire id: " << psd.m_save_game_empire_id; + } + } +} + void ServerApp::LoadMPGameInit(const MultiplayerLobbyData& lobby_data, const std::vector<PlayerSaveGameData>& player_save_game_data, boost::shared_ptr<ServerSaveGameData> server_save_game_data) @@ -703,8 +833,6 @@ // Need to determine which data in player_save_game_data should be assigned to which established player std::vector<std::pair<int, int> > player_id_to_save_game_data_index; - - //ServerNetworking::const_established_iterator established_player_it = m_networking.established_begin(); const std::list<std::pair<int, PlayerSetupData> >& player_setup_data = lobby_data.m_players; // * Multiplayer lobby data has a map from player ID to PlayerSetupData. @@ -715,23 +843,30 @@ // => Need to find which index into the PlayerSaveGameData vector has the right // empire id for each player id. - // assign all saved game data to a player ID + + // for every player setup data entry that represents an empire in the game, + // assign saved game data to the player ID of an established human or AI player for (std::list<std::pair<int, PlayerSetupData> >::const_iterator setup_data_it = player_setup_data.begin(); setup_data_it != player_setup_data.end(); ++setup_data_it) { - int player_id = setup_data_it->first; + const PlayerSetupData& psd = setup_data_it->second; - const PlayerSetupData& psd = setup_data_it->second; - int player_setup_empire_id = psd.m_save_game_empire_id; + if (psd.m_client_type == Networking::CLIENT_TYPE_HUMAN_PLAYER) { + int setup_data_player_id = setup_data_it->first; + GetSaveGameDataIndexForHumanPlayer(player_id_to_save_game_data_index, psd, + setup_data_player_id, player_save_game_data, + m_networking); - // find index in PlayerSaveGameData that has same empire ID as PlayerSetupData for this Player ID - for (int i = 0; i < static_cast<int>(player_save_game_data.size()); ++i) { - const PlayerSaveGameData& psgd = player_save_game_data.at(i); - if (psgd.m_empire_id == player_setup_empire_id) { - player_id_to_save_game_data_index.push_back(std::make_pair(player_id, i)); - break; - } + } else if (psd.m_client_type == Networking::CLIENT_TYPE_AI_PLAYER) { + // AI clients have no player id in setup data (even though humans do) + GetSaveGameDataIndexForAIPlayer(player_id_to_save_game_data_index, psd, + player_save_game_data, m_networking); + } + // do nothing for any other player type, until another player type + // is implemented. human observers and moderators don't need to be + // put into the map of id to player setup data, as they don't need + // empires to be created for them. } LoadGameInit(player_save_game_data, player_id_to_save_game_data_index, server_save_game_data); @@ -743,13 +878,13 @@ { Logger().debugStream() << "ServerApp::LoadGameInit"; - // ensure some reasonable inputs if (player_save_game_data.empty()) { Logger().errorStream() << "ServerApp::LoadGameInit passed empty player save game data. Aborting"; m_networking.SendMessage(ErrorMessage("SERVER_FOUND_NO_ACTIVE_PLAYERS", true)); return; } + // ensure number of players connected and for which data are provided are consistent if (player_id_to_save_game_data_index.size() != player_save_game_data.size()) { Logger().errorStream() << "ServerApp::LoadGameInit passed index mapping and player save game data are of different sizes..."; @@ -757,13 +892,16 @@ if (m_networking.NumEstablishedPlayers() != player_save_game_data.size()) { Logger().errorStream() << "ServerApp::LoadGameInit has " << m_networking.NumEstablishedPlayers() << " established players but " << player_save_game_data.size() << " entries in player save game data. Could be ok... so not aborting, but might crash"; } + // validate some connection info for (ServerNetworking::const_established_iterator player_connection_it = m_networking.established_begin(); player_connection_it != m_networking.established_end(); ++player_connection_it) { const PlayerConnectionPtr player_connection = *player_connection_it; Networking::ClientType client_type = player_connection->GetClientType(); - if (client_type != Networking::CLIENT_TYPE_AI_PLAYER && client_type != Networking::CLIENT_TYPE_HUMAN_PLAYER) { + if (client_type != Networking::CLIENT_TYPE_AI_PLAYER && + client_type != Networking::CLIENT_TYPE_HUMAN_PLAYER) + { Logger().errorStream() << "ServerApp::LoadGameInit found player connection with unsupported client type."; } if (player_connection->PlayerName().empty()) { @@ -779,8 +917,8 @@ // restore server state info from save - m_current_turn = server_save_game_data->m_current_turn; - m_victors = server_save_game_data->m_victors; + m_current_turn = server_save_game_data->m_current_turn; + m_victors = server_save_game_data->m_victors; // todo: save and restore m_eliminated_players ? std::map<int, PlayerSaveGameData> player_id_save_game_data; @@ -806,6 +944,7 @@ if (player_id != index_player_id) continue; player_save_game_data_index = index_it->second; + break; } if (player_save_game_data_index == -1) { Logger().debugStream() << "No save game data index for player with id " << player_id; @@ -893,38 +1032,43 @@ } - // send load game start messages + // assemble player state information, and send game start messages Logger().debugStream() << "ServerApp::CommonGameInit: Sending GameStartMessages to players"; + for (ServerNetworking::const_established_iterator player_connection_it = m_networking.established_begin(); player_connection_it != m_networking.established_end(); ++player_connection_it) { const PlayerConnectionPtr player_connection = *player_connection_it; int player_id = player_connection->PlayerID(); + Networking::ClientType client_type = player_connection->GetClientType(); + // attempt to find saved state data for this player. + PlayerSaveGameData psgd; std::map<int, PlayerSaveGameData>::const_iterator save_data_it = player_id_save_game_data.find(player_id); - if (save_data_it == player_id_save_game_data.end()) - continue; // no data for this player - const PlayerSaveGameData& psgd = save_data_it->second; + if (save_data_it != player_id_save_game_data.end()) { + psgd = save_data_it->second; + } else { + psgd.m_orders.reset(new OrderSet()); // need an empty order set pointed to for serialization in case no data is loaded but the game start message wants orders to send + } + // get empire ID for player. safety check on it. int empire_id = PlayerEmpireID(player_id); if (empire_id != psgd.m_empire_id) { Logger().errorStream() << "LoadGameInit got inconsistent empire ids between player save game data and result of PlayerEmpireID"; } + // restore saved orders. these will be re-executed on client and + // re-sent to the server (after possibly modification) by clients + // when they end their turn + boost::shared_ptr<OrderSet> orders = psgd.m_orders; - // get saved orders. these will be re-executed on client and re-sent - // to the server (after possibly modification) by clients when they - // end their turn - boost::shared_ptr<OrderSet> orders = psgd.m_orders; - - // send game start messages to players. AIs get a message with a save - // state string, and human clients get UI data that either has saved. - Networking::ClientType client_type = player_connection->GetClientType(); if (client_type == Networking::CLIENT_TYPE_AI_PLAYER) { + // get save state string const std::string* sss = 0; if (!psgd.m_save_state_string.empty()) sss = &psgd.m_save_state_string; + player_connection->SendMessage(GameStartMessage(player_id, m_single_player_game, empire_id, m_current_turn, m_empires, m_universe, GetSpeciesManager(), @@ -935,9 +1079,11 @@ m_current_turn, m_empires, m_universe, GetSpeciesManager(), player_info_map, *orders, psgd.m_ui_data.get())); + } else if (client_type == Networking::CLIENT_TYPE_HUMAN_OBSERVER || client_type == Networking::CLIENT_TYPE_HUMAN_MODERATOR) { + player_connection->SendMessage(GameStartMessage(player_id, m_single_player_game, ALL_EMPIRES, m_current_turn, m_empires, m_universe, GetSpeciesManager(), |