From: <geo...@us...> - 2009-11-12 05:26:54
|
Revision: 3263 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3263&view=rev Author: geoffthemedio Date: 2009-11-12 05:26:46 +0000 (Thu, 12 Nov 2009) Log Message: ----------- -Tweaked locations of some includes in Universe.h and UniverseObject.h to hopefully fix some gcc compile errors -Removed unused Default0Combiner code Modified Paths: -------------- trunk/FreeOrion/universe/Universe.h trunk/FreeOrion/universe/UniverseObject.h Modified: trunk/FreeOrion/universe/Universe.h =================================================================== --- trunk/FreeOrion/universe/Universe.h 2009-11-11 19:56:56 UTC (rev 3262) +++ trunk/FreeOrion/universe/Universe.h 2009-11-12 05:26:46 UTC (rev 3263) @@ -4,6 +4,7 @@ #include "Enums.h" #include "Predicates.h" +#include "../util/AppInterface.h" #include <boost/signal.hpp> #include <boost/iostreams/filtering_stream.hpp> Modified: trunk/FreeOrion/universe/UniverseObject.h =================================================================== --- trunk/FreeOrion/universe/UniverseObject.h 2009-11-11 19:56:56 UTC (rev 3262) +++ trunk/FreeOrion/universe/UniverseObject.h 2009-11-12 05:26:46 UTC (rev 3263) @@ -14,15 +14,6 @@ #include <string> #include <vector> -/** Signal return value combiner used by ResourceCenter, PopCenter, and any other UniverseObject decorator that needs - access to its UniverseObject subclass. */ -struct Default0Combiner -{ - typedef UniverseObject* result_type; - template <class Iter> - UniverseObject* operator()(Iter first, Iter last); -}; - class Meter; class System; class SitRepEntry; @@ -204,19 +195,6 @@ }; // template implementations -template <class Iter> -UniverseObject* Default0Combiner::operator()(Iter first, Iter last) -{ - UniverseObject* retval = 0; - while (first != last) { - assert(!retval); // ensure we retrieve at most one UniverseObject - retval = *first++; - } - return retval; -} - -#include "../util/AppInterface.h" - template <class Archive> void UniverseObject::serialize(Archive& ar, const unsigned int version) { |
From: <geo...@us...> - 2009-11-13 04:17:04
|
Revision: 3265 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3265&view=rev Author: geoffthemedio Date: 2009-11-13 04:16:55 +0000 (Fri, 13 Nov 2009) Log Message: ----------- -Modified System::Copy to properly retain previously known starlanes and update for newly observed ones -Modified System::VisibleStarlanesWormholes to show lanes connected with one or more systems with partial or better visibility, or on which an owned fleet is moving -Rewrote EdgeVisibilityFilter in an unsuccessful attempt to fix fleet move ordering, which is presently broken -Rewrote Universe::SystemHasVisibleStarlanes to call the system object's StarlanesWormholes function and return whether the returned map is empty -Renamed typedefs of SystemPointerPropertyMap to SystemIDPropertyMap (in some cases with a Const in the name as well) Modified Paths: -------------- trunk/FreeOrion/universe/System.cpp trunk/FreeOrion/universe/Universe.cpp Modified: trunk/FreeOrion/universe/System.cpp =================================================================== --- trunk/FreeOrion/universe/System.cpp 2009-11-12 05:42:09 UTC (rev 3264) +++ trunk/FreeOrion/universe/System.cpp 2009-11-13 04:16:55 UTC (rev 3265) @@ -88,12 +88,34 @@ if (vis >= VIS_BASIC_VISIBILITY) { this->m_objects = copied_system->VisibleContainedObjects(empire_id); - this->m_starlanes_wormholes = copied_system->VisibleStarlanesWormholes(empire_id); + // add any visible lanes, without removing existing entries + StarlaneMap visible_lanes_holes = copied_system->VisibleStarlanesWormholes(empire_id); + for (StarlaneMap::const_iterator it = visible_lanes_holes.begin(); it != visible_lanes_holes.end(); ++it) + this->m_starlanes_wormholes[it->first] = it->second; + this->m_star = copied_system->m_star; - if (vis >= VIS_FULL_VISIBILITY) { - this->m_orbits = copied_system->m_orbits; + if (vis >= VIS_PARTIAL_VISIBILITY) { + // remove any not-visible lanes that were previously known: with + // partial vis, they should be seen, but aren't, so are known not + // to exist any more + + // assemble all previously known lanes + std::vector<int> initial_known_lanes; + for (StarlaneMap::const_iterator it = this->m_starlanes_wormholes.begin(); it != this->m_starlanes_wormholes.end(); ++it) + initial_known_lanes.push_back(it->first); + + // remove previously known lanes that aren't currently visible + for (std::vector<int>::const_iterator it = initial_known_lanes.begin(); it != initial_known_lanes.end(); ++it) { + int lane_end_sys_id = *it; + if (visible_lanes_holes.find(lane_end_sys_id) == visible_lanes_holes.end()) + this->m_starlanes_wormholes.erase(lane_end_sys_id); + } + + if (vis >= VIS_FULL_VISIBILITY) { + this->m_orbits = copied_system->m_orbits; + } } } } @@ -556,18 +578,39 @@ const Universe& universe = GetUniverse(); const ObjectMap& objects = universe.Objects(); + + Visibility this_system_vis = universe.GetObjectVisibilityByEmpire(this->ID(), empire_id); + + //visible starlanes are: + // - those connected to systems with vis >= partial + // - those with visible ships travelling along them + + + // return all starlanes if partially visible or better + if (this_system_vis >= VIS_PARTIAL_VISIBILITY) + return m_starlanes_wormholes; + + + // compile visible lanes connected to this only basically-visible system StarlaneMap retval; - // starlanes are visible if both systems have basic visibility or greater, - // and one or both systems has partial visibility or greater + // check if any of the adjacent systems are partial or better visible + for (StarlaneMap::const_iterator it = m_starlanes_wormholes.begin(); it != m_starlanes_wormholes.end(); ++it) { + int lane_end_sys_id = it->first; + if (universe.GetObjectVisibilityByEmpire(lane_end_sys_id, empire_id) >= VIS_PARTIAL_VISIBILITY) + retval[lane_end_sys_id] = it->second; + } - // check that current system has at least basic visibility - Visibility vis2 = universe.GetObjectVisibilityByEmpire(this->ID(), empire_id); - if (vis2 < VIS_BASIC_VISIBILITY) + + // early exit check... can't see any more lanes than exist, so don't need to check for more if all lanes are already visible + if (retval == m_starlanes_wormholes) return retval; + // check if any fleets owned by empire are moving along a starlane connected to this system... + + // get moving fleets owned by empire std::vector<const Fleet*> moving_empire_fleets; std::vector<const UniverseObject*> moving_fleet_objects = objects.FindObjects(MovingFleetVisitor()); for (std::vector<const UniverseObject*>::const_iterator it = moving_fleet_objects.begin(); it != moving_fleet_objects.end(); ++it) @@ -575,36 +618,37 @@ if (fleet->OwnedBy(empire_id)) moving_empire_fleets.push_back(fleet); - - // check each connected system, paired with current system, to ensure at - // least one is partial, and both are at least basically visible, or that - // both are basically visible if there is a ship owned by the indicated - // empire travelling along a lane between them - for (StarlaneMap::const_iterator it = m_starlanes_wormholes.begin(); it != m_starlanes_wormholes.end(); ++it) { - Visibility vis1 = universe.GetObjectVisibilityByEmpire(it->first, empire_id); - if (vis1 < VIS_BASIC_VISIBILITY) + // add any lanes an owned fleet is moving along that connect to this system + for (std::vector<const Fleet*>::const_iterator it = moving_empire_fleets.begin(); it != moving_empire_fleets.end(); ++it) { + const Fleet* fleet = *it; + if (fleet->SystemID() != UniverseObject::INVALID_OBJECT_ID) { + Logger().errorStream() << "System::VisibleStarlanesWormholes somehow got a moving fleet that had a valid system id?"; continue; + } - if (vis1 >= VIS_PARTIAL_VISIBILITY || vis2 >= VIS_PARTIAL_VISIBILITY) { - // one or both systems are partially visible, so lane is visible - retval.insert(*it); - continue; + int prev_sys_id = fleet->PreviousSystemID(); + int next_sys_id = fleet->NextSystemID(); - } else if (vis1 >= VIS_BASIC_VISIBILITY) { - // check for fleets not in a system and with next and previous - // systems that are the current pair - for (std::vector<const Fleet*>::const_iterator moving_fleet_it = moving_empire_fleets.begin(); moving_fleet_it != moving_empire_fleets.end(); ++moving_fleet_it) { - const Fleet* fleet = *moving_fleet_it; - if (fleet->SystemID() == UniverseObject::INVALID_OBJECT_ID && - ((fleet->NextSystemID() == this->ID() && fleet->PreviousSystemID() == it->first) || - (fleet->NextSystemID() == it->first && fleet->PreviousSystemID() == this->ID()))) - { - retval.insert(*it); - break; - } + // see if previous or next system is this system, and if so, is other + // system on lane along which ship is moving one of this system's + // starlanes or wormholes? + int other_lane_end_sys_id = UniverseObject::INVALID_OBJECT_ID; + + if (prev_sys_id == this->ID()) + other_lane_end_sys_id = next_sys_id; + else if (next_sys_id == this->ID()) + other_lane_end_sys_id = prev_sys_id; + + if (other_lane_end_sys_id != UniverseObject::INVALID_OBJECT_ID) { + StarlaneMap::const_iterator lane_it = m_starlanes_wormholes.find(other_lane_end_sys_id); + if (lane_it == m_starlanes_wormholes.end()) { + Logger().errorStream() << "System::VisibleStarlanesWormholes found an owned fleet moving along a starlane connected to this system that isn't also connected to one of this system's starlane-connected systems...?"; + continue; } + retval[other_lane_end_sys_id] = lane_it->second; } } + return retval; } Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2009-11-12 05:42:09 UTC (rev 3264) +++ trunk/FreeOrion/universe/Universe.cpp 2009-11-13 04:16:55 UTC (rev 3265) @@ -102,10 +102,10 @@ int SystemGraphIndex(const Graph& graph, int system_id) { typedef typename boost::property_map<Graph, vertex_system_id_t>::const_type ConstSystemIDPropertyMap; - ConstSystemIDPropertyMap pointer_property_map = boost::get(vertex_system_id_t(), graph); + ConstSystemIDPropertyMap sys_id_property_map = boost::get(vertex_system_id_t(), graph); for (unsigned int i = 0; i < boost::num_vertices(graph); ++i) { - const int loop_sys_id = pointer_property_map[i]; // get system ID of this vertex + const int loop_sys_id = sys_id_property_map[i]; // get system ID of this vertex if (loop_sys_id == system_id) return i; } @@ -127,7 +127,7 @@ std::pair<std::list<int>, double> retval; - ConstSystemIDPropertyMap pointer_property_map = boost::get(vertex_system_id_t(), graph); + ConstSystemIDPropertyMap sys_id_property_map = boost::get(vertex_system_id_t(), graph); int system1_index = SystemGraphIndex(graph, system1_id); @@ -170,7 +170,7 @@ int current_system = system2_index; while (predecessors[current_system] != current_system) { - retval.first.push_front(pointer_property_map[current_system]); + retval.first.push_front(sys_id_property_map[current_system]); current_system = predecessors[current_system]; } retval.second = distances[system2_index]; @@ -181,7 +181,7 @@ return retval; } else { // add start system to path, as it wasn't added by traversing predecessors array - retval.first.push_front(pointer_property_map[system1_index]); + retval.first.push_front(sys_id_property_map[system1_index]); } return retval; @@ -196,7 +196,7 @@ { typedef typename boost::property_map<Graph, vertex_system_id_t>::const_type ConstSystemIDPropertyMap; - ConstSystemIDPropertyMap pointer_property_map = boost::get(vertex_system_id_t(), graph); + ConstSystemIDPropertyMap sys_id_property_map = boost::get(vertex_system_id_t(), graph); std::pair<std::list<int>, int> retval; int system1_index = SystemGraphIndex(graph, system1_id); @@ -235,7 +235,7 @@ int current_system = system2_index; while (predecessors[current_system] != current_system) { - retval.first.push_front(pointer_property_map[current_system]); + retval.first.push_front(sys_id_property_map[current_system]); current_system = predecessors[current_system]; } retval.second = retval.first.size() - 1; // number of jumps is number of systems in path minus one for the starting system @@ -245,7 +245,7 @@ retval.second = -1; } else { // add start system to path, as it wasn't added by traversing predecessors array - retval.first.push_front(pointer_property_map[system1_index]); + retval.first.push_front(sys_id_property_map[system1_index]); } return retval; @@ -266,10 +266,10 @@ std::map<double, int> retval; ConstEdgeWeightPropertyMap edge_weight_map = boost::get(boost::edge_weight, graph); - ConstSystemIDPropertyMap pointer_property_map = boost::get(vertex_system_id_t(), graph); + ConstSystemIDPropertyMap sys_id_property_map = boost::get(vertex_system_id_t(), graph); std::pair<OutEdgeIterator, OutEdgeIterator> edges = boost::out_edges(SystemGraphIndex(graph, system_id), graph); for (OutEdgeIterator it = edges.first; it != edges.second; ++it) { - retval[edge_weight_map[*it]] = pointer_property_map[boost::target(*it, graph)]; + retval[edge_weight_map[*it]] = sys_id_property_map[boost::target(*it, graph)]; } return retval; } @@ -497,7 +497,10 @@ EdgeVisibilityFilter(const SystemGraph* graph, int empire_id) : m_graph(graph), m_empire_id(empire_id) - {} + { + if (!graph) + Logger().errorStream() << "EdgeVisibilityFilter passed null graph pointer"; + } template <typename EdgeDescriptor> bool operator()(const EdgeDescriptor& edge) const @@ -505,58 +508,40 @@ if (!m_graph) return false; - // for reverse-lookup System universe ID from graph indices... - ConstSystemIDPropertyMap pointer_property_map = boost::get(vertex_system_id_t(), *m_graph); - - const Universe& universe = GetUniverse(); - const ObjectMap& objects = universe.EmpireKnownObjects(m_empire_id); - - // get system id from graph index + // get system ids from graph indices + ConstSystemIDPropertyMap sys_id_property_map = boost::get(vertex_system_id_t(), *m_graph); // for reverse-lookup System universe ID from graph index int sys_graph_index_1 = boost::source(edge, *m_graph); - int sys_id_1 = pointer_property_map[sys_graph_index_1]; - - Visibility vis1 = universe.GetObjectVisibilityByEmpire(sys_id_1, m_empire_id); - if (vis1 < VIS_BASIC_VISIBILITY) - return false; - - - // get system id from graph index + int sys_id_1 = sys_id_property_map[sys_graph_index_1]; int sys_graph_index_2 = boost::target(edge, *m_graph); - int sys_id_2 = pointer_property_map[sys_graph_index_2]; + int sys_id_2 = sys_id_property_map[sys_graph_index_2]; - Visibility vis2 = universe.GetObjectVisibilityByEmpire(sys_id_2, m_empire_id); - if (vis2 < VIS_BASIC_VISIBILITY) - return false; - - - const System* system1 = objects.Object<System>(sys_id_1); + // look up lane between systems + const System* system1 = GetEmpireKnownConstObject<System>(sys_id_1, m_empire_id); if (!system1) { Logger().errorStream() << "EdgeDescriptor::operator() couldn't find system with id " << sys_id_1; return false; } - - // check if starlane is listed in system's visible starlanes - System::StarlaneMap lanes = system1->StarlanesWormholes(); - if (lanes.find(sys_id_2) != lanes.end()) + if (system1->HasStarlaneTo(sys_id_2)) return true; + // lane not found return false; } private: - const SystemGraph* m_graph; - int m_empire_id; + const SystemGraph* m_graph; + int m_empire_id; }; typedef boost::filtered_graph<SystemGraph, EdgeVisibilityFilter> EmpireViewSystemGraph; typedef std::map<int, boost::shared_ptr<EmpireViewSystemGraph> > EmpireViewSystemGraphMap; // declare property map types for properties declared above - typedef boost::property_map<SystemGraph, vertex_system_id_t>::const_type ConstSystemIDPropertyMap; - typedef boost::property_map<SystemGraph, vertex_system_id_t>::type SystemPointerPropertyMap; - typedef boost::property_map<SystemGraph, boost::vertex_index_t>::const_type ConstIndexPropertyMap; - typedef boost::property_map<SystemGraph, boost::vertex_index_t>::type IndexPropertyMap; - typedef boost::property_map<SystemGraph, boost::edge_weight_t>::const_type ConstEdgeWeightPropertyMap; - typedef boost::property_map<SystemGraph, boost::edge_weight_t>::type EdgeWeightPropertyMap; + typedef boost::property_map<SystemGraph, vertex_system_id_t>::const_type ConstSystemIDPropertyMap; + typedef boost::property_map<SystemGraph, vertex_system_id_t>::type SystemIDPropertyMap; + typedef boost::property_map<SystemGraph, boost::vertex_index_t>::const_type ConstIndexPropertyMap; + typedef boost::property_map<SystemGraph, boost::vertex_index_t>::type IndexPropertyMap; + typedef boost::property_map<SystemGraph, boost::edge_weight_t>::const_type ConstEdgeWeightPropertyMap; + typedef boost::property_map<SystemGraph, boost::edge_weight_t>::type EdgeWeightPropertyMap; SystemGraph m_system_graph; ///< a graph in which the systems are vertices and the starlanes are edges EmpireViewSystemGraphMap m_empire_system_graph_views; ///< a map of empire IDs to the views of the system graph by those empires @@ -782,13 +767,9 @@ bool Universe::SystemHasVisibleStarlanes(int system_id, int empire_id) const { - if (empire_id == ALL_EMPIRES) { - return SystemReachableImpl(m_graph_impl->m_system_graph, system_id); - } else { - GraphImpl::EmpireViewSystemGraphMap::const_iterator graph_it = m_graph_impl->m_empire_system_graph_views.find(empire_id); - if (graph_it != m_graph_impl->m_empire_system_graph_views.end()) - return SystemReachableImpl(*graph_it->second, system_id); - } + if (const System* system = GetEmpireKnownConstObject<System>(system_id, empire_id)) + if (!system->StarlanesWormholes().empty()) + return true; return false; } @@ -1569,7 +1550,7 @@ // check whether having a contained object wouldn't change container's // visibility anyway... if (container_vis_it->second >= VIS_BASIC_VISIBILITY) - continue; // having visible contained object grants part vis only. if container already has this for current empire, don't need to propegate + continue; // having visible contained object grants basic vis only. if container already has this for current empire, don't need to propegate } @@ -1926,7 +1907,7 @@ std::vector<int> system_ids = m_objects.FindObjectIDs<System>(); m_system_distances.resize(system_ids.size()); - GraphImpl::SystemPointerPropertyMap pointer_property_map = boost::get(vertex_system_id_t(), m_graph_impl->m_system_graph); + GraphImpl::SystemIDPropertyMap sys_id_property_map = boost::get(vertex_system_id_t(), m_graph_impl->m_system_graph); GraphImpl::EdgeWeightPropertyMap edge_weight_map = boost::get(boost::edge_weight, m_graph_impl->m_system_graph); typedef boost::graph_traits<GraphImpl::SystemGraph>::edge_descriptor EdgeDescriptor; @@ -1934,10 +1915,10 @@ std::map<int, int> system_id_graph_index_reverse_lookup_map; // key is system ID, value is index in m_graph_impl->m_system_graph of system's vertex for (int i = 0; i < static_cast<int>(system_ids.size()); ++i) { - // add a vertex to the graph for this system, and assign it a pointer for its System object + // add a vertex to the graph for this system, and assign it the system's universe ID as a property boost::add_vertex(m_graph_impl->m_system_graph); int system_id = system_ids[i]; - pointer_property_map[i] = system_id; + sys_id_property_map[i] = system_id; // add record of index in m_graph_impl->m_system_graph of this system system_id_graph_index_reverse_lookup_map[system_id] = i; } @@ -1966,19 +1947,21 @@ double x_dist = system2->X() - system1->X(); double y_dist = system2->Y() - system1->Y(); edge_weight_map[add_edge_result.first] = std::sqrt(x_dist*x_dist + y_dist*y_dist); + std::cout << "edge_weight_map " << system1_id << " to " << lane_dest_id << ": " << edge_weight_map[add_edge_result.first] << std::endl; } } // define the straight-line system distances for this system m_system_distances[i].clear(); for (int j = 0; j < i; ++j) { - int system2_id = system_ids[i]; + int system2_id = system_ids[j]; const UniverseObject* system2 = m_objects.Object(system2_id); double x_dist = system2->X() - system1->X(); double y_dist = system2->Y() - system1->Y(); m_system_distances[i].push_back(std::sqrt(x_dist*x_dist + y_dist*y_dist)); + std::cout << "m_system_distances: " << system1_id << " to " << system2_id << ": " << m_system_distances[i].back() << std::endl; } - m_system_distances[i].push_back(0.0); + m_system_distances[i].push_back(0.0); // distance from system to itself } RebuildEmpireViewSystemGraphs(); |
From: <geo...@us...> - 2009-11-19 21:17:16
|
Revision: 3274 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3274&view=rev Author: geoffthemedio Date: 2009-11-19 21:17:09 +0000 (Thu, 19 Nov 2009) Log Message: ----------- -Added a special case for fleets to visibility calculations so that fleets with partially visible or better ships are guaranteed to be themselves partially visible. This ensures that the owners of the fleet will be sent to players who can see the ships. Previously, fleets were showing as having no known owners on the map, even when their contained ships were visible and the ships' owners known. -Modified UniverseObject::AddOwner and RemoveOwner to do nothing if the added owner is already an owner, or if the removed owner is already not an owner. Modified Paths: -------------- trunk/FreeOrion/universe/Fleet.cpp trunk/FreeOrion/universe/Universe.cpp trunk/FreeOrion/universe/UniverseObject.cpp Modified: trunk/FreeOrion/universe/Fleet.cpp =================================================================== --- trunk/FreeOrion/universe/Fleet.cpp 2009-11-18 09:08:08 UTC (rev 3273) +++ trunk/FreeOrion/universe/Fleet.cpp 2009-11-19 21:17:09 UTC (rev 3274) @@ -732,7 +732,6 @@ return retval; } - bool Fleet::RemoveShip(int ship) { //std::cout << "Fleet::RemoveShip" << std::endl; Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2009-11-18 09:08:08 UTC (rev 3273) +++ trunk/FreeOrion/universe/Universe.cpp 2009-11-19 21:17:09 UTC (rev 3274) @@ -1568,16 +1568,20 @@ for (ObjectMap::const_iterator container_object_it = m_objects.const_begin(); container_object_it != m_objects.const_end(); ++container_object_it) { int container_obj_id = container_object_it->first; - // get contained object + // get container object const UniverseObject* container_obj = container_object_it->second; if (!container_obj) continue; // shouldn't be necessary, but I like to be safe... + // does object actually contain any other objects? std::vector<int> contained_objects = container_obj->FindObjectIDs(); if (contained_objects.empty()) continue; // nothing to propegate if no objects contained + // check if container object is a fleet, for special case later... + const Fleet* container_fleet = universe_object_cast<const Fleet*>(container_obj); + // for each contained object within container for (std::vector<int>::iterator contained_obj_it = contained_objects.begin(); contained_obj_it != contained_objects.end(); ++contained_obj_it) { int contained_obj_id = *contained_obj_it; @@ -1595,10 +1599,20 @@ // get iterator pointing at newly-created entry container_vis_it = vis_map.find(container_obj_id); } else { - // check whether having a contained object wouldn't change container's - // visibility anyway... - if (container_vis_it->second >= VIS_BASIC_VISIBILITY) - continue; // having visible contained object grants basic vis only. if container already has this for current empire, don't need to propegate + // check whether having a contained object would change container's visibility + if (container_fleet) { + // special case for fleets: grant partial visibility if + // a contained ship is seen with partial visibility or + // higher visibilitly + if (container_vis_it->second >= VIS_PARTIAL_VISIBILITY) + continue; + } else if (container_vis_it->second >= VIS_BASIC_VISIBILITY) { + // general case: for non-fleets, having visible + // contained object grants basic vis only. if + // container already has this or better for the current + // empire, don't need to propegate anything + continue; + } } @@ -1618,6 +1632,11 @@ // higher than partially visible if (container_vis_it->second < VIS_BASIC_VISIBILITY) container_vis_it->second = VIS_BASIC_VISIBILITY; + + // special case for fleets: grant partial visibility if + // visible contained object is partially or better visible + if (container_fleet && contained_obj_vis >= VIS_PARTIAL_VISIBILITY && container_vis_it->second < VIS_PARTIAL_VISIBILITY) + container_vis_it->second = VIS_PARTIAL_VISIBILITY; } } // end for empire visibility entries } // end for contained objects @@ -1667,8 +1686,8 @@ // ensure systems on either side of a starlane along which a fleet is - // moving are at least basically visible, so that the starlane itself will - // be visible + // moving are at least basically visible, so that the starlane itself can / + // will be visible std::vector<const Fleet*> moving_fleets; std::vector<UniverseObject*> moving_fleet_objects = m_objects.FindObjects(MovingFleetVisitor()); for (std::vector<UniverseObject*>::iterator it = moving_fleet_objects.begin(); it != moving_fleet_objects.end(); ++it) { Modified: trunk/FreeOrion/universe/UniverseObject.cpp =================================================================== --- trunk/FreeOrion/universe/UniverseObject.cpp 2009-11-18 09:08:08 UTC (rev 3273) +++ trunk/FreeOrion/universe/UniverseObject.cpp 2009-11-19 21:17:09 UTC (rev 3274) @@ -304,20 +304,21 @@ void UniverseObject::AddOwner(int id) { - if (id != ALL_EMPIRES) { + if (id != ALL_EMPIRES && m_owners.find(id) == m_owners.end()) { m_owners.insert(id); StateChangedSignal(); } /* TODO: if adding an owner to an object gives an the added owner an * observer in, or ownership of a previoiusly unexplored system, then need * to call empire->AddExploredSystem(system_id); */ - } void UniverseObject::RemoveOwner(int id) { - m_owners.erase(id); - StateChangedSignal(); + if (m_owners.find(id) != m_owners.end()) { + m_owners.erase(id); + StateChangedSignal(); + } } void UniverseObject::ClearOwners() |
From: <geo...@us...> - 2009-11-22 05:34:04
|
Revision: 3278 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3278&view=rev Author: geoffthemedio Date: 2009-11-22 04:38:14 +0000 (Sun, 22 Nov 2009) Log Message: ----------- -Modified Universe::RebuildEmpireViewSystemGraphs to use a single shared view of the system graph if the rebuilding is being done for a single empire, since duplicating the views for all empires is unnecessary -Made Fleet::Copy copy the fleet's speed if it is partially or better visible -Modified Fleet::CalculateRoute by commenting out the early exit code of the other of a fleet doesn't have visibility of the destination system, since this was preventing the human client's attempts to find routes for enemy fleets, for which the player's client doesn't know which systems are visible, and since visibility of a system on the current turn isn't necessary to plot a route to it now that empire's can remember systems they've seen on previous turns. Modified Paths: -------------- trunk/FreeOrion/universe/Fleet.cpp trunk/FreeOrion/universe/Universe.cpp Modified: trunk/FreeOrion/universe/Fleet.cpp =================================================================== --- trunk/FreeOrion/universe/Fleet.cpp 2009-11-20 09:31:57 UTC (rev 3277) +++ trunk/FreeOrion/universe/Fleet.cpp 2009-11-22 04:38:14 UTC (rev 3278) @@ -98,11 +98,14 @@ this->m_next_system = copied_fleet->m_next_system; this->m_prev_system = copied_fleet->m_prev_system; + if (vis >= VIS_PARTIAL_VISIBILITY) { + this->m_speed = copied_fleet->m_speed; + } + if (vis == VIS_FULL_VISIBILITY) { this->m_moving_to = copied_fleet->m_moving_to; this->m_travel_route = copied_fleet->m_travel_route; this->m_travel_distance = copied_fleet->m_travel_distance; - this->m_speed = copied_fleet->m_speed; } else { int moving_to = copied_fleet->m_next_system; @@ -960,6 +963,7 @@ void Fleet::CalculateRoute() const { const Universe& universe = GetUniverse(); + const ObjectMap& objects = GetMainObjectMap(); int owner = ALL_EMPIRES; if (Owners().size() == 1) owner = *Owners().begin(); @@ -972,94 +976,96 @@ if (m_prev_system != UniverseObject::INVALID_OBJECT_ID && SystemID() == m_prev_system) { // if we haven't actually left yet, we have to move from whichever system we are at now - if (!GetObject<System>(m_moving_to)) + if (!objects.Object<System>(m_moving_to)) return; // destination system doesn't exist or doesn't exist in known universe, so can't move to it. leave route empty. std::pair<std::list<int>, double> path = universe.ShortestPath(m_prev_system, m_moving_to, owner); m_travel_route = path.first; m_travel_distance = path.second; - } else { - int dest_system_id = m_moving_to; + return; + } - if (universe.GetObjectVisibilityByEmpire(dest_system_id, owner) <= VIS_NO_VISIBILITY) { - // destination system isn't visible to this fleet's owner, so the fleet can't move to it - // check if system to which fleet is moving is visible to the fleet's owner. this should always be true, but just in case... - if (universe.GetObjectVisibilityByEmpire(m_next_system, owner) <= VIS_NO_VISIBILITY) - return; // next system also isn't visible; leave route empty. + int dest_system_id = m_moving_to; - // safety check: ensure supposedly visible object actually exists in known universe. - if (!GetObject<System>(m_next_system)) { - Logger().errorStream() << "Fleet::CalculateRoute found system with id " << m_next_system << " should be visible to this fleet's owner, but the system doesn't exist in the known universe!"; - return; // abort if object doesn't exist in known universe... can't path to it if it's not there, even if it's considered visible for some reason... - } + //if (universe.GetObjectVisibilityByEmpire(dest_system_id, owner) <= VIS_NO_VISIBILITY) { + // // destination system isn't visible to this fleet's owner, so the fleet can't move to it - // next system is visible, so move to that instead of ordered destination (m_moving_to) - dest_system_id = m_next_system; - } + // // check if system to which fleet is moving is visible to the fleet's owner. this should always be true, but just in case... + // if (universe.GetObjectVisibilityByEmpire(m_next_system, owner) <= VIS_NO_VISIBILITY) + // return; // next system also isn't visible; leave route empty. - // if we're between systems, the shortest route may be through either one - if (this->CanChangeDirectionEnRoute()) { + // // safety check: ensure supposedly visible object actually exists in known universe. + // if (!GetObject<System>(m_next_system)) { + // Logger().errorStream() << "Fleet::CalculateRoute found system with id " << m_next_system << " should be visible to this fleet's owner, but the system doesn't exist in the known universe!"; + // return; // abort if object doesn't exist in known universe... can't path to it if it's not there, even if it's considered visible for some reason... + // } - std::pair<std::list<int>, double> path1 = universe.ShortestPath(m_next_system, dest_system_id, owner); - const std::list<int>& sys_list1 = path1.first; - if (sys_list1.empty()) { - Logger().errorStream() << "Fleet::CalculateRoute got empty route from ShortestPath"; - return; - } - const UniverseObject* obj = GetObject(sys_list1.front()); - if (!obj) { - Logger().errorStream() << "Fleet::CalculateRoute couldn't get path start object with id " << path1.first.front(); - return; - } - double dist_x = obj->X() - this->X(); - double dist_y = obj->Y() - this->Y(); - double dist1 = std::sqrt(dist_x*dist_x + dist_y*dist_y); + // // next system is visible, so move to that instead of ordered destination (m_moving_to) + // dest_system_id = m_next_system; + //} - std::pair<std::list<int>, double> path2 = universe.ShortestPath(m_prev_system, dest_system_id, owner); - const std::list<int>& sys_list2 = path2.first; - if (sys_list2.empty()) { - Logger().errorStream() << "Fleet::CalculateRoute got empty route from ShortestPath"; - return; - } - obj = GetObject(sys_list2.front()); - if (!obj) { - Logger().errorStream() << "Fleet::CalculateRoute couldn't get path start object with id " << path2.first.front(); - return; - } - dist_x = obj->X() - this->X(); - dist_y = obj->Y() - this->Y(); - double dist2 = std::sqrt(dist_x*dist_x + dist_y*dist_y); + // if we're between systems, the shortest route may be through either one + if (this->CanChangeDirectionEnRoute()) { - // pick whichever path is quicker - if (dist1 + path1.second < dist2 + path2.second) { - m_travel_route = path1.first; - m_travel_distance = dist1 + path1.second; - } else { - m_travel_route = path2.first; - m_travel_distance = dist2 + path2.second; - } + std::pair<std::list<int>, double> path1 = universe.ShortestPath(m_next_system, dest_system_id, owner); + const std::list<int>& sys_list1 = path1.first; + if (sys_list1.empty()) { + Logger().errorStream() << "Fleet::CalculateRoute got empty route from ShortestPath"; + return; + } + const UniverseObject* obj = objects.Object(sys_list1.front()); + if (!obj) { + Logger().errorStream() << "Fleet::CalculateRoute couldn't get path start object with id " << path1.first.front(); + return; + } + double dist_x = obj->X() - this->X(); + double dist_y = obj->Y() - this->Y(); + double dist1 = std::sqrt(dist_x*dist_x + dist_y*dist_y); + std::pair<std::list<int>, double> path2 = universe.ShortestPath(m_prev_system, dest_system_id, owner); + const std::list<int>& sys_list2 = path2.first; + if (sys_list2.empty()) { + Logger().errorStream() << "Fleet::CalculateRoute got empty route from ShortestPath"; + return; + } + obj = objects.Object(sys_list2.front()); + if (!obj) { + Logger().errorStream() << "Fleet::CalculateRoute couldn't get path start object with id " << path2.first.front(); + return; + } + dist_x = obj->X() - this->X(); + dist_y = obj->Y() - this->Y(); + double dist2 = std::sqrt(dist_x*dist_x + dist_y*dist_y); + + // pick whichever path is quicker + if (dist1 + path1.second < dist2 + path2.second) { + m_travel_route = path1.first; + m_travel_distance = dist1 + path1.second; } else { + m_travel_route = path2.first; + m_travel_distance = dist2 + path2.second; + } - std::pair<std::list<int>, double> route = universe.ShortestPath(m_next_system, dest_system_id, owner); - const std::list<int>& sys_list = route.first; - if (sys_list.empty()) { - Logger().errorStream() << "Fleet::CalculateRoute got empty route from ShortestPath"; - return; - } - const UniverseObject* obj = GetObject(sys_list.front()); - if (!obj) { - Logger().errorStream() << "Fleet::CalculateRoute couldn't get path start object with id " << route.first.front(); - return; - } - double dist_x = obj->X() - this->X(); - double dist_y = obj->Y() - this->Y(); - double dist = std::sqrt(dist_x*dist_x + dist_y*dist_y); - m_travel_route = route.first; - m_travel_distance = dist + route.second; + } else { + + std::pair<std::list<int>, double> route = universe.ShortestPath(m_next_system, dest_system_id, owner); + const std::list<int>& sys_list = route.first; + if (sys_list.empty()) { + Logger().errorStream() << "Fleet::CalculateRoute got empty route from ShortestPath"; + return; } + const UniverseObject* obj = objects.Object(sys_list.front()); + if (!obj) { + Logger().errorStream() << "Fleet::CalculateRoute couldn't get path start object with id " << route.first.front(); + return; + } + double dist_x = obj->X() - this->X(); + double dist_y = obj->Y() - this->Y(); + double dist = std::sqrt(dist_x*dist_x + dist_y*dist_y); + m_travel_route = route.first; + m_travel_distance = dist + route.second; } } } Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2009-11-20 09:31:57 UTC (rev 3277) +++ trunk/FreeOrion/universe/Universe.cpp 2009-11-22 04:38:14 UTC (rev 3278) @@ -1955,22 +1955,38 @@ void Universe::RebuildEmpireViewSystemGraphs(int for_empire_id) { + if (!Empires().Lookup(for_empire_id)) + Logger().errorStream() << "Universe::RebuildEmpireViewSystemGraphs couldn't find empire with id " << for_empire_id; + + m_graph_impl->m_empire_system_graph_views.clear(); + + // if building system graph views for all empires, then each empire's graph + // should accurately filter for that empire's visibility. if building + // graphs for one empire, that empire won't know what systems other empires + // have visibility of, so instead, have all empires' filtered graphs be + // equal to the empire for which filtering is being done. this way, on the + // clients, enemy fleets can have move paths even though the client doesn't + // know what systems those empires know about (so can't make an accurate + // filtered graph for other empires) + if (for_empire_id == ALL_EMPIRES) { - m_graph_impl->m_empire_system_graph_views.clear(); + // all empires get their own, accurately filtered graph for (EmpireManager::const_iterator it = Empires().begin(); it != Empires().end(); ++it) { int empire_id = it->first; GraphImpl::EdgeVisibilityFilter filter(&m_graph_impl->m_system_graph, empire_id); boost::shared_ptr<GraphImpl::EmpireViewSystemGraph> filtered_graph_ptr(new GraphImpl::EmpireViewSystemGraph(m_graph_impl->m_system_graph, filter)); m_graph_impl->m_empire_system_graph_views[empire_id] = filtered_graph_ptr; } + } else { - if (!Empires().Lookup(for_empire_id)) { - Logger().errorStream() << "Universe::RebuildEmpireViewSystemGraphs couldn't find empire with id " << for_empire_id; - return; - } + // all empires share a single filtered graph, filtered by the for_empire_id GraphImpl::EdgeVisibilityFilter filter(&m_graph_impl->m_system_graph, for_empire_id); boost::shared_ptr<GraphImpl::EmpireViewSystemGraph> filtered_graph_ptr(new GraphImpl::EmpireViewSystemGraph(m_graph_impl->m_system_graph, filter)); - m_graph_impl->m_empire_system_graph_views[for_empire_id] = filtered_graph_ptr; + + for (EmpireManager::const_iterator it = Empires().begin(); it != Empires().end(); ++it) { + int empire_id = it->first; + m_graph_impl->m_empire_system_graph_views[empire_id] = filtered_graph_ptr; + } } } |
From: <tz...@us...> - 2010-03-24 01:39:38
|
Revision: 3400 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3400&view=rev Author: tzlaine Date: 2010-03-24 01:39:31 +0000 (Wed, 24 Mar 2010) Log Message: ----------- Const-corrected Universe::ExecuteEffects() and Universe::ExecuteMeterEffects(). Modified Paths: -------------- trunk/FreeOrion/universe/Universe.cpp trunk/FreeOrion/universe/Universe.h Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2010-03-24 01:37:22 UTC (rev 3399) +++ trunk/FreeOrion/universe/Universe.cpp 2010-03-24 01:39:31 UTC (rev 3400) @@ -1343,7 +1343,7 @@ } } -void Universe::ExecuteEffects(EffectsTargetsCausesMap& targets_causes_map) +void Universe::ExecuteEffects(const EffectsTargetsCausesMap& targets_causes_map) { m_marked_destroyed.clear(); m_marked_for_victory.clear(); @@ -1385,7 +1385,7 @@ } } -void Universe::ExecuteMeterEffects(EffectsTargetsCausesMap& targets_causes_map) +void Universe::ExecuteMeterEffects(const EffectsTargetsCausesMap& targets_causes_map) { //Logger().debugStream() << "Universe::ExecuteMeterEffects"; std::map<std::string, Condition::ObjectSet> executed_nonstacking_effects; Modified: trunk/FreeOrion/universe/Universe.h =================================================================== --- trunk/FreeOrion/universe/Universe.h 2010-03-24 01:37:22 UTC (rev 3399) +++ trunk/FreeOrion/universe/Universe.h 2010-03-24 01:39:31 UTC (rev 3400) @@ -551,13 +551,13 @@ /** Executes all effects. Does not store effect accounting information. * For use on server when processing turns. */ - void ExecuteEffects(EffectsTargetsCausesMap& targets_causes_map); + void ExecuteEffects(const EffectsTargetsCausesMap& targets_causes_map); /** Executes only meter-altering effects; ignores other effects.. Stores * effect accounting information in \a targets_causes_map. Can be used * on server or on clients to determine meter values after effects are * applied */ - void ExecuteMeterEffects(EffectsTargetsCausesMap& targets_causes_map); + void ExecuteMeterEffects(const EffectsTargetsCausesMap& targets_causes_map); /** Does actual updating of meter estimates after the public function have * processed objects_vec or whatever they were passed and cleared the |
From: <tz...@us...> - 2010-03-24 01:51:00
|
Revision: 3401 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3401&view=rev Author: tzlaine Date: 2010-03-24 01:50:52 +0000 (Wed, 24 Mar 2010) Log Message: ----------- This patch addresses the longstanding question of how to affect ship part stats via Effects. It does this via three changes: - Added new Ship-only Meters that cover the Meter types that are ship-part specific. - Added SetShipPartMeter Effect to affect the new Ship Meters. - Added code to autogenerate EffectsGroups that adjust Ship Meters, just like the other part types already work (e.g. PC_SHILED parts, which increase a Ship's METER_SHIELD). What has not been done, and which will come in future commits: * Add parser code to allow SetShipPartMeter Effects to be specified in data files. * Adjust combat code to use the meter values instead of the nominal values straight out of the ShipDesign stats. Modified Paths: -------------- trunk/FreeOrion/universe/Effect.cpp trunk/FreeOrion/universe/Effect.h trunk/FreeOrion/universe/Enums.h trunk/FreeOrion/universe/Ship.cpp trunk/FreeOrion/universe/Ship.h trunk/FreeOrion/universe/ShipDesign.cpp trunk/FreeOrion/universe/Universe.cpp trunk/FreeOrion/universe/UniverseObject.cpp trunk/FreeOrion/universe/UniverseObject.h Modified: trunk/FreeOrion/universe/Effect.cpp =================================================================== --- trunk/FreeOrion/universe/Effect.cpp 2010-03-24 01:39:31 UTC (rev 3400) +++ trunk/FreeOrion/universe/Effect.cpp 2010-03-24 01:50:52 UTC (rev 3401) @@ -58,9 +58,9 @@ } /** Creates a new fleet at \a system and inserts \a ship into it. Used - * when a ship has been moved by the MoveTo effect separately from the - * fleet that previously held it. Also used by CreateShip effect to give - * the new ship a fleet. All ships need to be within fleets. */ + * when a ship has been moved by the MoveTo effect separately from the + * fleet that previously held it. Also used by CreateShip effect to give + * the new ship a fleet. All ships need to be within fleets. */ Fleet* CreateNewFleet(System* system, Ship* ship) { Universe& universe = GetUniverse(); if (!system || !ship) @@ -89,9 +89,9 @@ } /** creates a new fleet at a specified \a x and \a y location within the - * Universe, and and inserts \a ship into it. Used when a ship has been - * moved by the MoveTo effect separately from the fleet that previously - * held it. All ships need to be within fleets. */ + * Universe, and and inserts \a ship into it. Used when a ship has been + * moved by the MoveTo effect separately from the fleet that previously + * held it. All ships need to be within fleets. */ Fleet* CreateNewFleet(double x, double y, Ship* ship) { Universe& universe = GetUniverse(); if (!ship) @@ -130,9 +130,9 @@ } /** Resets the previous and next systems of \a fleet and recalcultes / - * resets the fleet's move route. Used after a fleet has been moved with - * the MoveTo effect, as its previous route was assigned based on its - * previous location, and may not be valid for its new location. */ + * resets the fleet's move route. Used after a fleet has been moved with + * the MoveTo effect, as its previous route was assigned based on its + * previous location, and may not be valid for its new location. */ void UpdateFleetRoute(Fleet* fleet, int new_next_system, int new_previous_system) { if (!fleet) { Logger().errorStream() << "UpdateFleetRoute passed a null fleet pointer"; @@ -192,6 +192,32 @@ return owner1 == owner2; } + + bool PartMatchesEffect(const PartType& part, + ShipPartClass part_class, + CombatFighterType fighter_type, + const std::string& part_name, + ShipSlotType slot_type) + { + if (slot_type != INVALID_SHIP_SLOT_TYPE && !part.CanMountInSlotType(slot_type)) + return false; + + if (part_name != "") + return part_name == part.Name(); + + switch (part.Class()) { + case PC_SHORT_RANGE: + case PC_MISSILES: + case PC_POINT_DEFENSE: + return part.Class() == part_class; + case PC_FIGHTERS: + return boost::get<FighterStats>(part.Stats()).m_type == fighter_type; + default: + break; + } + + return false; + } } /////////////////////////////////////////////////////////// @@ -456,6 +482,78 @@ /////////////////////////////////////////////////////////// +// SetShipPartMeter // +/////////////////////////////////////////////////////////// +SetShipPartMeter::SetShipPartMeter(MeterType meter, + ShipPartClass part_class, + const ValueRef::ValueRefBase<double>* value, + ShipSlotType slot_type/* = INVALID_SHIP_SLOT_TYPE*/) : + m_part_class(part_class), + m_fighter_type(INVALID_COMBAT_FIGHTER_TYPE), + m_part_name(), + m_slot_type(slot_type), + m_meter(meter), + m_value(value) +{ assert(m_part_class != PC_FIGHTERS); } + +SetShipPartMeter::SetShipPartMeter(MeterType meter, + CombatFighterType fighter_type, + const ValueRef::ValueRefBase<double>* value, + ShipSlotType slot_type/* = INVALID_SHIP_SLOT_TYPE*/) : + m_part_class(INVALID_SHIP_PART_CLASS), + m_fighter_type(fighter_type), + m_part_name(), + m_slot_type(slot_type), + m_meter(meter), + m_value(value) +{} + +SetShipPartMeter::SetShipPartMeter(MeterType meter, + const std::string& part_name, + const ValueRef::ValueRefBase<double>* value, + ShipSlotType slot_type/* = INVALID_SHIP_SLOT_TYPE*/) : + m_part_class(INVALID_SHIP_PART_CLASS), + m_fighter_type(INVALID_COMBAT_FIGHTER_TYPE), + m_part_name(part_name), + m_slot_type(slot_type), + m_meter(meter), + m_value(value) +{} + +SetShipPartMeter::~SetShipPartMeter() +{ delete m_value; } + +void SetShipPartMeter::Execute(const UniverseObject* source, UniverseObject* target) const +{ + if (Ship* ship = universe_object_cast<Ship*>(target)) { + for (std::size_t i = 0; i < ship->Design()->Parts().size(); ++i) { + if (Meter* meter = ship->GetMeter(m_meter, m_part_name)) { + const PartType* part = GetPartType(ship->Design()->Parts()[i]); + if (PartMatchesEffect(*part, m_part_class, m_fighter_type, m_part_name, m_slot_type)) { + double val = m_value->Eval(source, target, meter->Max()); + meter->SetMax(val); + meter->SetCurrent(val); + } + } + } + } +} + +std::string SetShipPartMeter::Description() const +{ + // TODO + return ""; +} + +std::string SetShipPartMeter::Dump() const +{ + std::string retval = DumpIndent() + "SetShipPartMeter"; + // TODO + return retval; +} + + +/////////////////////////////////////////////////////////// // SetEmpireStockpile // /////////////////////////////////////////////////////////// SetEmpireStockpile::SetEmpireStockpile(ResourceType stockpile, const ValueRef::ValueRefBase<double>* value) : Modified: trunk/FreeOrion/universe/Effect.h =================================================================== --- trunk/FreeOrion/universe/Effect.h 2010-03-24 01:39:31 UTC (rev 3400) +++ trunk/FreeOrion/universe/Effect.h 2010-03-24 01:50:52 UTC (rev 3401) @@ -22,6 +22,7 @@ class EffectsGroup; class EffectBase; class SetMeter; + class SetShipPartMeter; class SetEmpireStockpile; class SetEmpireCapitol; class SetPlanetType; @@ -136,6 +137,53 @@ void serialize(Archive& ar, const unsigned int version); }; +/** Sets the indicated meter on all ship parts in the indicated subset. This + has no effect on non-Ship targets. If slot_type is specified, only the + indicated (internal or external) parts are affected. */ +class Effect::SetShipPartMeter : public Effect::EffectBase +{ +public: + /** Affects the \a meter_type meters that belong to all parts of class \a + part_class. \a part_class must specify a class of parts for which + there is a ship meter (i.e. specifying PC_FUEL would be illegal). */ + SetShipPartMeter(MeterType meter_type, + ShipPartClass part_class, + const ValueRef::ValueRefBase<double>* value, + ShipSlotType slot_type = INVALID_SHIP_SLOT_TYPE); + + /** Affects the \a meter_type meters that belong to all PC_FIGHTERS parts + of type \a fighter_type. */ + SetShipPartMeter(MeterType meter_type, + CombatFighterType fighter_type, + const ValueRef::ValueRefBase<double>* value, + ShipSlotType slot_type = INVALID_SHIP_SLOT_TYPE); + + /** Affects the \a meter_type meters that belong to all parts named \a + part_name. */ + SetShipPartMeter(MeterType meter_type, + const std::string& part_name, + const ValueRef::ValueRefBase<double>* value, + ShipSlotType slot_type = INVALID_SHIP_SLOT_TYPE); + + virtual ~SetShipPartMeter(); + + virtual void Execute(const UniverseObject* source, UniverseObject* target) const; + virtual std::string Description() const; + virtual std::string Dump() const; + +private: + ShipPartClass m_part_class; + CombatFighterType m_fighter_type; + std::string m_part_name; + ShipSlotType m_slot_type; + MeterType m_meter; + const ValueRef::ValueRefBase<double>* m_value; + + friend class boost::serialization::access; + template <class Archive> + void serialize(Archive& ar, const unsigned int version); +}; + /** Sets the empire stockpile of the target's owning empire to \a value. If the target does not have exactly one owner, nothing is done. */ class Effect::SetEmpireStockpile : public Effect::EffectBase @@ -465,6 +513,7 @@ void serialize(Archive& ar, const unsigned int version); }; + // template implementations template <class Archive> void Effect::EffectsGroup::serialize(Archive& ar, const unsigned int version) @@ -490,6 +539,18 @@ } template <class Archive> +void Effect::SetShipPartMeter::serialize(Archive& ar, const unsigned int version) +{ + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(EffectBase) + & BOOST_SERIALIZATION_NVP(m_part_class) + & BOOST_SERIALIZATION_NVP(m_fighter_type) + & BOOST_SERIALIZATION_NVP(m_part_name) + & BOOST_SERIALIZATION_NVP(m_slot_type) + & BOOST_SERIALIZATION_NVP(m_meter) + & BOOST_SERIALIZATION_NVP(m_value); +} + +template <class Archive> void Effect::SetEmpireStockpile::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(EffectBase) Modified: trunk/FreeOrion/universe/Enums.h =================================================================== --- trunk/FreeOrion/universe/Enums.h 2010-03-24 01:39:31 UTC (rev 3400) +++ trunk/FreeOrion/universe/Enums.h 2010-03-24 01:50:52 UTC (rev 3401) @@ -201,6 +201,21 @@ METER_DETECTION, METER_SHIELD, METER_DEFENSE, + METER_BATTLE_SPEED, + METER_STARLANE_SPEED, + + // These meter enumerators only apply to ship part meters. + + METER_DAMAGE, + METER_ROF, + METER_RANGE, + METER_SPEED, + METER_CAPACITY, + METER_ANTI_SHIP_DAMAGE, + METER_ANTI_FIGHTER_DAMAGE, + METER_LAUNCH_RATE, + METER_FIGHTER_WEAPON_RANGE, + NUM_METER_TYPES }; @@ -221,6 +236,15 @@ GG_ENUM_MAP_INSERT(METER_DETECTION) GG_ENUM_MAP_INSERT(METER_SHIELD) GG_ENUM_MAP_INSERT(METER_DEFENSE) + GG_ENUM_MAP_INSERT(METER_DAMAGE) + GG_ENUM_MAP_INSERT(METER_ROF) + GG_ENUM_MAP_INSERT(METER_RANGE) + GG_ENUM_MAP_INSERT(METER_SPEED) + GG_ENUM_MAP_INSERT(METER_CAPACITY) + GG_ENUM_MAP_INSERT(METER_ANTI_SHIP_DAMAGE) + GG_ENUM_MAP_INSERT(METER_ANTI_FIGHTER_DAMAGE) + GG_ENUM_MAP_INSERT(METER_LAUNCH_RATE) + GG_ENUM_MAP_INSERT(METER_FIGHTER_WEAPON_RANGE) GG_ENUM_MAP_END } GG_ENUM_STREAM_IN(MeterType) @@ -476,6 +500,8 @@ /** Types of fighters. */ enum CombatFighterType { + INVALID_COMBAT_FIGHTER_TYPE, + /** A fighter that is better at attacking other fighters than at attacking ships. */ INTERCEPTOR, @@ -487,6 +513,7 @@ namespace GG { GG_ENUM_MAP_BEGIN(CombatFighterType) + GG_ENUM_MAP_INSERT(INVALID_COMBAT_FIGHTER_TYPE) GG_ENUM_MAP_INSERT(INTERCEPTOR) GG_ENUM_MAP_INSERT(BOMBER) GG_ENUM_MAP_END Modified: trunk/FreeOrion/universe/Ship.cpp =================================================================== --- trunk/FreeOrion/universe/Ship.cpp 2010-03-24 01:39:31 UTC (rev 3400) +++ trunk/FreeOrion/universe/Ship.cpp 2010-03-24 01:50:52 UTC (rev 3401) @@ -46,10 +46,12 @@ UniverseObject::Init(); - InsertMeter(METER_FUEL, Meter()); - InsertMeter(METER_SHIELD, Meter()); - InsertMeter(METER_DETECTION, Meter()); - InsertMeter(METER_HEALTH, Meter()); + InsertMeter(METER_FUEL, Meter()); + InsertMeter(METER_SHIELD, Meter()); + InsertMeter(METER_DETECTION, Meter()); + InsertMeter(METER_HEALTH, Meter()); + InsertMeter(METER_BATTLE_SPEED, Meter()); + InsertMeter(METER_STARLANE_SPEED, Meter()); const std::vector<std::string>& part_names = Design()->Parts(); for (std::size_t i = 0; i < part_names.size(); ++i) { @@ -59,17 +61,48 @@ Logger().errorStream() << "Ship::Ship couldn't get part with name " << part_names[i]; continue; } - if (part->Class() == PC_FIGHTERS) { - std::pair<std::size_t, std::size_t>& part_fighters = - m_fighters[part_names[i]]; - ++part_fighters.first; - part_fighters.second += boost::get<FighterStats>(part->Stats()).m_capacity; - } else if (part->Class() == PC_MISSILES) { + + switch (part->Class()) { + case PC_SHORT_RANGE: + case PC_POINT_DEFENSE: { + m_part_meters[std::make_pair(METER_DAMAGE, part->Name())]; + m_part_meters[std::make_pair(METER_ROF, part->Name())]; + m_part_meters[std::make_pair(METER_RANGE, part->Name())]; + break; + } + case PC_MISSILES: { std::pair<std::size_t, std::size_t>& part_missiles = m_missiles[part_names[i]]; ++part_missiles.first; part_missiles.second += boost::get<LRStats>(part->Stats()).m_capacity; + m_part_meters[std::make_pair(METER_DAMAGE, part->Name())]; + m_part_meters[std::make_pair(METER_ROF, part->Name())]; + m_part_meters[std::make_pair(METER_RANGE, part->Name())]; + m_part_meters[std::make_pair(METER_SPEED, part->Name())]; + m_part_meters[std::make_pair(METER_STEALTH, part->Name())]; + m_part_meters[std::make_pair(METER_HEALTH, part->Name())]; + m_part_meters[std::make_pair(METER_CAPACITY, part->Name())]; + break; } + case PC_FIGHTERS: { + std::pair<std::size_t, std::size_t>& part_fighters = + m_fighters[part_names[i]]; + ++part_fighters.first; + part_fighters.second += boost::get<FighterStats>(part->Stats()).m_capacity; + m_part_meters[std::make_pair(METER_ANTI_SHIP_DAMAGE, part->Name())]; + m_part_meters[std::make_pair(METER_ANTI_FIGHTER_DAMAGE, part->Name())]; + m_part_meters[std::make_pair(METER_LAUNCH_RATE, part->Name())]; + m_part_meters[std::make_pair(METER_FIGHTER_WEAPON_RANGE, part->Name())]; + m_part_meters[std::make_pair(METER_SPEED, part->Name())]; + m_part_meters[std::make_pair(METER_STEALTH, part->Name())]; + m_part_meters[std::make_pair(METER_HEALTH, part->Name())]; + m_part_meters[std::make_pair(METER_DETECTION, part->Name())]; + m_part_meters[std::make_pair(METER_CAPACITY, part->Name())]; + break; + } + default: + break; + } } } } @@ -108,9 +141,15 @@ this->m_design_id = copied_ship->m_design_id; this->m_fighters = copied_ship->m_fighters; this->m_missiles = copied_ship->m_missiles; + for (PartMeters::const_iterator it = copied_ship->m_part_meters.begin(); + it != copied_ship->m_part_meters.end(); + ++it) { + this->m_part_meters[it->first]; + } if (vis >= VIS_FULL_VISIBILITY) { this->m_ordered_scrapped = copied_ship->m_ordered_scrapped; + this->m_part_meters = copied_ship->m_part_meters; } } } @@ -211,6 +250,12 @@ } } +bool Ship::OrderedScrapped() const +{ return m_ordered_scrapped; } + +const Meter* Ship::GetMeter(MeterType type, const std::string& part_name) const +{ return const_cast<const Ship*>(this)->GetMeter(type, part_name); } + void Ship::SetFleetID(int fleet_id) { m_fleet_id = fleet_id; @@ -277,4 +322,28 @@ if (b == initial_status) return; m_ordered_scrapped = b; StateChangedSignal(); -} \ No newline at end of file +} + +Meter* Ship::GetMeter(MeterType type, const std::string& part_name) +{ + Meter* retval = 0; + PartMeters::iterator it = m_part_meters.find(std::make_pair(type, part_name)); + if (it != m_part_meters.end()) + retval = &it->second; + return retval; +} + +void Ship::CustomResetMaxMeters(MeterType meter_type/* = INVALID_METER_TYPE*/) +{ + for (PartMeters::iterator it = m_part_meters.begin(); it != m_part_meters.end(); ++it) { + if (meter_type == INVALID_METER_TYPE || it->first.first == meter_type) + it->second.ResetMax(); + } +} + +void Ship::CustomClampMeters() +{ + for (PartMeters::iterator it = m_part_meters.begin(); it != m_part_meters.end(); ++it) { + it->second.Clamp(); + } +} Modified: trunk/FreeOrion/universe/Ship.h =================================================================== --- trunk/FreeOrion/universe/Ship.h 2010-03-24 01:39:31 UTC (rev 3400) +++ trunk/FreeOrion/universe/Ship.h 2010-03-24 01:50:52 UTC (rev 3401) @@ -44,7 +44,11 @@ virtual double ProjectedCurrentMeter(MeterType type) const; ///< returns expected value of specified meter current value on the next turn - bool OrderedScrapped() const {return m_ordered_scrapped;} + bool OrderedScrapped() const; + + const Meter* GetMeter(MeterType type, const std::string& part_name) const; ///< returns the requested Meter, or 0 if no such Meter of that type is found in this object + + using UniverseObject::GetMeter; //@} /** \name Mutators */ //@{ @@ -61,14 +65,22 @@ virtual void MoveTo(double x, double y); void SetOrderedScrapped(bool b = true); ///< flags ship for scrapping + + Meter* GetMeter(MeterType type, const std::string& part_name); ///< returns the requested Meter, or 0 if no such Meter of that type is found in this object //@} private: + typedef std::map<std::pair<MeterType, std::string>, Meter> PartMeters; + + virtual void CustomResetMaxMeters(MeterType meter_type = INVALID_METER_TYPE); + virtual void CustomClampMeters(); + int m_design_id; int m_fleet_id; bool m_ordered_scrapped; ConsumablesMap m_fighters; ConsumablesMap m_missiles; + PartMeters m_part_meters; friend class boost::serialization::access; template <class Archive> @@ -84,7 +96,8 @@ & BOOST_SERIALIZATION_NVP(m_fleet_id) & BOOST_SERIALIZATION_NVP(m_ordered_scrapped) & BOOST_SERIALIZATION_NVP(m_fighters) - & BOOST_SERIALIZATION_NVP(m_missiles); + & BOOST_SERIALIZATION_NVP(m_missiles) + & BOOST_SERIALIZATION_NVP(m_part_meters); } #endif // _Ship_h_ Modified: trunk/FreeOrion/universe/ShipDesign.cpp =================================================================== --- trunk/FreeOrion/universe/ShipDesign.cpp 2010-03-24 01:39:31 UTC (rev 3400) +++ trunk/FreeOrion/universe/ShipDesign.cpp 2010-03-24 01:50:52 UTC (rev 3401) @@ -91,7 +91,7 @@ } boost::shared_ptr<const Effect::EffectsGroup> - IncreaseMax(MeterType meter_type, const std::string& meter_name, double increase) + IncreaseMeterMax(MeterType meter_type, double increase) { typedef boost::shared_ptr<const Effect::EffectsGroup> EffectsGroupPtr; typedef std::vector<Effect::EffectBase*> Effects; @@ -100,7 +100,7 @@ ValueRef::ValueRefBase<double>* vr = new ValueRef::Operation<double>( ValueRef::PLUS, - new ValueRef::Variable<double>(false, meter_name), + new ValueRef::Variable<double>(false, "Value"), new ValueRef::Constant<double>(increase) ); return EffectsGroupPtr( @@ -108,6 +108,24 @@ scope, activation, Effects(1, new Effect::SetMeter(meter_type, vr, true)))); } + boost::shared_ptr<const Effect::EffectsGroup> + IncreaseCurrentAndMax(MeterType meter_type, const std::string& part_name, double increase) + { + typedef boost::shared_ptr<const Effect::EffectsGroup> EffectsGroupPtr; + typedef std::vector<Effect::EffectBase*> Effects; + Condition::Self* scope = new Condition::Self; + Condition::Self* activation = new Condition::Self; + ValueRef::ValueRefBase<double>* vr = + new ValueRef::Operation<double>( + ValueRef::PLUS, + new ValueRef::Variable<double>(false, "Value"), + new ValueRef::Constant<double>(increase) + ); + return EffectsGroupPtr( + new Effect::EffectsGroup( + scope, activation, Effects(1, new Effect::SetShipPartMeter(meter_type, part_name, vr)), part_name)); + } + struct DescriptionVisitor : public boost::static_visitor<> { DescriptionVisitor(ShipPartClass part_class, std::string& description) : @@ -428,16 +446,57 @@ break; } - if (m_class == PC_SHIELD) - m_effects.push_back(IncreaseMax(METER_SHIELD, "MaxShield", boost::get<double>(m_stats))); - else if (m_class == PC_DETECTION) - m_effects.push_back(IncreaseMax(METER_DETECTION, "MaxDetection", boost::get<double>(m_stats))); - else if (m_class == PC_STEALTH) - m_effects.push_back(IncreaseMax(METER_STEALTH, "MaxStealth", boost::get<double>(m_stats))); - else if (m_class == PC_FUEL) - m_effects.push_back(IncreaseMax(METER_FUEL, "MaxFuel", boost::get<double>(m_stats))); - else if (m_class == PC_ARMOUR) - m_effects.push_back(IncreaseMax(METER_HEALTH, "MaxHealth", boost::get<double>(m_stats))); + switch (m_class) { + case PC_SHORT_RANGE: + case PC_POINT_DEFENSE: { + const DirectFireStats& stats = boost::get<DirectFireStats>(m_stats); + m_effects.push_back(IncreaseCurrentAndMax(METER_DAMAGE, m_name, stats.m_damage)); + m_effects.push_back(IncreaseCurrentAndMax(METER_ROF, m_name, stats.m_ROF)); + m_effects.push_back(IncreaseCurrentAndMax(METER_RANGE, m_name, stats.m_range)); + break; + } + case PC_MISSILES: { + const LRStats& stats = boost::get<LRStats>(m_stats); + m_effects.push_back(IncreaseCurrentAndMax(METER_DAMAGE, m_name, stats.m_damage)); + m_effects.push_back(IncreaseCurrentAndMax(METER_ROF, m_name, stats.m_ROF)); + m_effects.push_back(IncreaseCurrentAndMax(METER_RANGE, m_name, stats.m_range)); + m_effects.push_back(IncreaseCurrentAndMax(METER_SPEED, m_name, stats.m_speed)); + m_effects.push_back(IncreaseCurrentAndMax(METER_STEALTH, m_name, stats.m_stealth)); + m_effects.push_back(IncreaseCurrentAndMax(METER_HEALTH, m_name, stats.m_health)); + m_effects.push_back(IncreaseCurrentAndMax(METER_CAPACITY, m_name, stats.m_capacity)); + break; + } + case PC_FIGHTERS: { + const FighterStats& stats = boost::get<FighterStats>(m_stats); + m_effects.push_back(IncreaseCurrentAndMax(METER_ANTI_SHIP_DAMAGE, m_name, stats.m_anti_ship_damage)); + m_effects.push_back(IncreaseCurrentAndMax(METER_ANTI_FIGHTER_DAMAGE, m_name, stats.m_anti_fighter_damage)); + m_effects.push_back(IncreaseCurrentAndMax(METER_LAUNCH_RATE, m_name, stats.m_launch_rate)); + m_effects.push_back(IncreaseCurrentAndMax(METER_FIGHTER_WEAPON_RANGE, m_name, stats.m_fighter_weapon_range)); + m_effects.push_back(IncreaseCurrentAndMax(METER_SPEED, m_name, stats.m_speed)); + m_effects.push_back(IncreaseCurrentAndMax(METER_STEALTH, m_name, stats.m_stealth)); + m_effects.push_back(IncreaseCurrentAndMax(METER_HEALTH, m_name, stats.m_health)); + m_effects.push_back(IncreaseCurrentAndMax(METER_DETECTION, m_name, stats.m_detection)); + m_effects.push_back(IncreaseCurrentAndMax(METER_CAPACITY, m_name, stats.m_capacity)); + break; + } + case PC_SHIELD: + m_effects.push_back(IncreaseMeterMax(METER_SHIELD, boost::get<double>(m_stats))); + break; + case PC_DETECTION: + m_effects.push_back(IncreaseMeterMax(METER_DETECTION, boost::get<double>(m_stats))); + break; + case PC_STEALTH: + m_effects.push_back(IncreaseMeterMax(METER_STEALTH, boost::get<double>(m_stats))); + break; + case PC_FUEL: + m_effects.push_back(IncreaseMeterMax(METER_FUEL, boost::get<double>(m_stats))); + break; + case PC_ARMOUR: + m_effects.push_back(IncreaseMeterMax(METER_HEALTH, boost::get<double>(m_stats))); + break; + default: + break; + } for (std::vector<boost::shared_ptr<const Effect::EffectsGroup> >::const_iterator it = effects.begin(); it != effects.end(); ++it) m_effects.push_back(*it); @@ -569,9 +628,11 @@ m_effects(), m_graphic(graphic) { - m_effects.push_back(IncreaseMax(METER_FUEL, "MaxFuel", m_fuel)); - m_effects.push_back(IncreaseMax(METER_STEALTH, "MaxStealth", m_stealth)); - m_effects.push_back(IncreaseMax(METER_HEALTH, "MaxHealth", m_health)); + m_effects.push_back(IncreaseMeterMax(METER_FUEL, m_fuel)); + m_effects.push_back(IncreaseMeterMax(METER_STEALTH, m_stealth)); + m_effects.push_back(IncreaseMeterMax(METER_HEALTH, m_health)); + m_effects.push_back(IncreaseMeterMax(METER_BATTLE_SPEED, m_battle_speed)); + m_effects.push_back(IncreaseMeterMax(METER_STARLANE_SPEED, m_starlane_speed)); for (std::vector<boost::shared_ptr<const Effect::EffectsGroup> >::const_iterator it = effects.begin(); it != effects.end(); ++it) m_effects.push_back(*it); } @@ -598,9 +659,11 @@ m_effects(), m_graphic(graphic) { - m_effects.push_back(IncreaseMax(METER_FUEL, "MaxFuel", m_fuel)); - m_effects.push_back(IncreaseMax(METER_STEALTH, "MaxStealth", m_stealth)); - m_effects.push_back(IncreaseMax(METER_HEALTH, "MaxHealth", m_health)); + m_effects.push_back(IncreaseMeterMax(METER_FUEL, m_fuel)); + m_effects.push_back(IncreaseMeterMax(METER_STEALTH, m_stealth)); + m_effects.push_back(IncreaseMeterMax(METER_HEALTH, m_health)); + m_effects.push_back(IncreaseMeterMax(METER_BATTLE_SPEED, m_battle_speed)); + m_effects.push_back(IncreaseMeterMax(METER_STARLANE_SPEED, m_starlane_speed)); for (std::vector<boost::shared_ptr<const Effect::EffectsGroup> >::const_iterator it = effects.begin(); it != effects.end(); ++it) m_effects.push_back(*it); } Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2010-03-24 01:39:31 UTC (rev 3400) +++ trunk/FreeOrion/universe/Universe.cpp 2010-03-24 01:50:52 UTC (rev 3401) @@ -1408,50 +1408,54 @@ } - // execute only the SetMeter effects in the EffectsGroup + // execute only the SetMeter and SetShipPartMeter effects in the EffectsGroup const std::vector<Effect::EffectBase*>& effects = effects_group->EffectsList(); for (unsigned int i = 0; i < effects.size(); ++i) { const Effect::SetMeter* meter_effect = dynamic_cast<Effect::SetMeter*>(effects[i]); - if (!meter_effect) continue; + if (!meter_effect && !dynamic_cast<Effect::SetShipPartMeter*>(effects[i])) + continue; // determine meter to be altered by this effect - MeterType meter_type = meter_effect->GetMeterType(); + MeterType meter_type = INVALID_METER_TYPE; + if (meter_effect) { + meter_type = meter_effect->GetMeterType(); - // record pre-effect meter values - for (Condition::ObjectSet::iterator target_it = targets.begin(); target_it != targets.end(); ++target_it) { - UniverseObject* target = *target_it; - const Meter* meter = target->GetMeter(meter_type); - if (!meter) continue; // some objects might match target conditions, but not actually have the relevant meter + // record pre-effect meter values + for (Condition::ObjectSet::iterator target_it = targets.begin(); target_it != targets.end(); ++target_it) { + UniverseObject* target = *target_it; + const Meter* meter = target->GetMeter(meter_type); + if (!meter) continue; // some objects might match target conditions, but not actually have the relevant meter - // accounting info for this effect on this meter - EffectAccountingInfo info; - info.cause_type = targets_and_cause.effect_cause.cause_type; - info.specific_cause = targets_and_cause.effect_cause.specific_cause; - info.source_id = sourced_effects_group.source_object_id; - info.running_meter_total = meter->Max(); + // accounting info for this effect on this meter + EffectAccountingInfo info; + info.cause_type = targets_and_cause.effect_cause.cause_type; + info.specific_cause = targets_and_cause.effect_cause.specific_cause; + info.source_id = sourced_effects_group.source_object_id; + info.running_meter_total = meter->Max(); - // add accounting for this effect to end of vector - m_effect_accounting_map[target->ID()][meter_type].push_back(info); + // add accounting for this effect to end of vector + m_effect_accounting_map[target->ID()][meter_type].push_back(info); + } } - // apply meter-altering effect to targets effects_group->Execute(sourced_effects_group.source_object_id, targets, i); + if (meter_effect) { + // find change in meter due to effect: equal to post-meter minus pre-meter value + for (Condition::ObjectSet::iterator target_it = targets.begin(); target_it != targets.end(); ++target_it) { + UniverseObject* target = *target_it; + const Meter* meter = target->GetMeter(meter_type); + if (!meter) continue; // some objects might match target conditions, but not actually have the relevant meter - // find change in meter due to effect: equal to post-meter minus pre-meter value - for (Condition::ObjectSet::iterator target_it = targets.begin(); target_it != targets.end(); ++target_it) { - UniverseObject* target = *target_it; - const Meter* meter = target->GetMeter(meter_type); - if (!meter) continue; // some objects might match target conditions, but not actually have the relevant meter + // retreive info for this effect + EffectAccountingInfo& info = m_effect_accounting_map[target->ID()][meter_type].back(); - // retreive info for this effect - EffectAccountingInfo& info = m_effect_accounting_map[target->ID()][meter_type].back(); - - // update accounting info with meter change and new total - info.meter_change = meter->Max() - info.running_meter_total; - info.running_meter_total = meter->Max(); + // update accounting info with meter change and new total + info.meter_change = meter->Max() - info.running_meter_total; + info.running_meter_total = meter->Max(); + } } } Modified: trunk/FreeOrion/universe/UniverseObject.cpp =================================================================== --- trunk/FreeOrion/universe/UniverseObject.cpp 2010-03-24 01:39:31 UTC (rev 3400) +++ trunk/FreeOrion/universe/UniverseObject.cpp 2010-03-24 01:50:52 UTC (rev 3401) @@ -363,6 +363,7 @@ else Logger().errorStream() << "UniverseObject::ResetMaxMeters called with MeterType this object does not have"; } + CustomResetMaxMeters(meter_type); } void UniverseObject::ApplyUniverseTableMaxMeterAdjustments(MeterType meter_type) @@ -372,6 +373,7 @@ { for (std::map<MeterType, Meter>::iterator it = m_meters.begin(); it != m_meters.end(); ++it) it->second.Clamp(); + CustomClampMeters(); } void UniverseObject::PopGrowthProductionResearchPhase() @@ -395,4 +397,3 @@ } return retval; } - Modified: trunk/FreeOrion/universe/UniverseObject.h =================================================================== --- trunk/FreeOrion/universe/UniverseObject.h 2010-03-24 01:39:31 UTC (rev 3400) +++ trunk/FreeOrion/universe/UniverseObject.h 2010-03-24 01:50:52 UTC (rev 3401) @@ -178,6 +178,12 @@ private: std::map<MeterType, Meter> CensoredMeters(Visibility vis) const; ///< returns set of meters of this object that are censored based on the specified Visibility \a vis + /** any actions that should be performed at the end of ResetMaxMeters() goes here */ + virtual void CustomResetMaxMeters(MeterType meter_type = INVALID_METER_TYPE) {} + + /** any actions that should be performed at the end of ClampMeters() goes here */ + virtual void CustomClampMeters() {} + int m_id; std::string m_name; double m_x; |
From: <tz...@us...> - 2010-04-01 15:56:24
|
Revision: 3411 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3411&view=rev Author: tzlaine Date: 2010-04-01 15:56:17 +0000 (Thu, 01 Apr 2010) Log Message: ----------- Added a new accessor to Fleet, ArrivalStarlane(), which indicates the starlane ID from which the fleet arrived, if it arrived this turn. Modified Paths: -------------- trunk/FreeOrion/universe/Fleet.cpp trunk/FreeOrion/universe/Fleet.h Modified: trunk/FreeOrion/universe/Fleet.cpp =================================================================== --- trunk/FreeOrion/universe/Fleet.cpp 2010-03-30 02:08:44 UTC (rev 3410) +++ trunk/FreeOrion/universe/Fleet.cpp 2010-04-01 15:56:17 UTC (rev 3411) @@ -52,7 +52,8 @@ m_prev_system(INVALID_OBJECT_ID), m_next_system(INVALID_OBJECT_ID), m_travel_distance(0.0), - m_arrived_this_turn(false) + m_arrived_this_turn(false), + m_arrival_starlane(INVALID_OBJECT_ID) {} Fleet::Fleet(const std::string& name, double x, double y, int owner) : @@ -62,7 +63,8 @@ m_prev_system(INVALID_OBJECT_ID), m_next_system(INVALID_OBJECT_ID), m_travel_distance(0.0), - m_arrived_this_turn(false) + m_arrived_this_turn(false), + m_arrival_starlane(INVALID_OBJECT_ID) { UniverseObject::Init(); AddOwner(owner); @@ -595,6 +597,9 @@ bool Fleet::ArrivedThisTurn() const { return m_arrived_this_turn; } +int Fleet::ArrivalStarlane() const +{ return m_arrival_starlane; } + UniverseObject* Fleet::Accept(const UniverseObjectVisitor& visitor) const { return visitor.Visit(const_cast<Fleet* const>(this)); @@ -804,7 +809,10 @@ //Logger().debugStream() << "Fleet::MovementPhase this: " << this->Name() << " id: " << this->ID(); m_arrived_this_turn = false; + m_arrival_starlane = UniverseObject::INVALID_OBJECT_ID; + int prev_prev_system = m_prev_system; + // find if any of owners of fleet can resupply ships at the location of this fleet if (FleetOrResourceSupplyableAtSystemByAnyOfEmpiresWithIDs(this->SystemID(), this->Owners())) { // resupply all ships @@ -881,10 +889,9 @@ if (Empire* empire = Empires().Lookup(*owners_it)) empire->AddExploredSystem(it->object_id); - + prev_prev_system = m_prev_system; m_prev_system = system->ID(); // passing a system, so update previous system of this fleet - bool resupply_here = FleetOrResourceSupplyableAtSystemByAnyOfEmpiresWithIDs(system->ID(), this->Owners()); // if this system can provide supplies, reset consumed fuel and refuel ships @@ -943,8 +950,9 @@ } else { // no more systems on path + m_arrived_this_turn = current_system != initial_system; + m_arrival_starlane = prev_prev_system; m_moving_to = m_next_system = m_prev_system = UniverseObject::INVALID_OBJECT_ID; - m_arrived_this_turn = current_system != initial_system; } Modified: trunk/FreeOrion/universe/Fleet.h =================================================================== --- trunk/FreeOrion/universe/Fleet.h 2010-03-30 02:08:44 UTC (rev 3410) +++ trunk/FreeOrion/universe/Fleet.h 2010-04-01 15:56:17 UTC (rev 3411) @@ -80,6 +80,10 @@ /** Returns true iff this fleet arrived at its current System this turn. */ bool ArrivedThisTurn() const; + /** Returns the ID of the starlane that this fleet arrived on. The value + returned is undefined if ArrivedThisTurn() does not return true. */ + int ArrivalStarlane() const; + virtual UniverseObject* Accept(const UniverseObjectVisitor& visitor) const; //@} @@ -138,6 +142,7 @@ mutable double m_travel_distance; bool m_arrived_this_turn; + int m_arrival_starlane; friend class boost::serialization::access; template <class Archive> @@ -159,7 +164,8 @@ & BOOST_SERIALIZATION_NVP(m_next_system) & BOOST_SERIALIZATION_NVP(m_travel_route) & BOOST_SERIALIZATION_NVP(m_travel_distance) - & BOOST_SERIALIZATION_NVP(m_arrived_this_turn); + & BOOST_SERIALIZATION_NVP(m_arrived_this_turn) + & BOOST_SERIALIZATION_NVP(m_arrival_starlane); } #endif // _Fleet_h_ |
From: <geo...@us...> - 2010-05-15 20:28:11
|
Revision: 3588 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3588&view=rev Author: geoffthemedio Date: 2010-05-15 20:28:05 +0000 (Sat, 15 May 2010) Log Message: ----------- -Fixed some crash issues where asking a ResourceCenter for a next turn estimate of a target meter type would throw an exception unnecessarily -Changed LARGE_VALUE and INVALID_VALUE in Meter to small values, rather than +/- std::numeric_limits::max so that any additions to those meters won't cause them to overflow Modified Paths: -------------- trunk/FreeOrion/universe/Meter.cpp trunk/FreeOrion/universe/PopCenter.cpp trunk/FreeOrion/universe/ResourceCenter.cpp Modified: trunk/FreeOrion/universe/Meter.cpp =================================================================== --- trunk/FreeOrion/universe/Meter.cpp 2010-05-11 06:40:05 UTC (rev 3587) +++ trunk/FreeOrion/universe/Meter.cpp 2010-05-15 20:28:05 UTC (rev 3588) @@ -4,8 +4,8 @@ #include <boost/lexical_cast.hpp> const double Meter::DEFAULT_VALUE = 0.0; -const double Meter::LARGE_VALUE = std::numeric_limits<double>::max(); -const double Meter::INVALID_VALUE = -std::numeric_limits<double>::max(); +const double Meter::LARGE_VALUE = static_cast<double>(2 << 15); +const double Meter::INVALID_VALUE = -LARGE_VALUE; Meter::Meter() : m_current_value(DEFAULT_VALUE), Modified: trunk/FreeOrion/universe/PopCenter.cpp =================================================================== --- trunk/FreeOrion/universe/PopCenter.cpp 2010-05-11 06:40:05 UTC (rev 3587) +++ trunk/FreeOrion/universe/PopCenter.cpp 2010-05-15 20:28:05 UTC (rev 3588) @@ -76,7 +76,7 @@ Logger().debugStream() << "PopCenter::PopCenterNextTurnMeterValue passed valid but unusual (TARGET) meter_type. Returning meter->Current()"; return meter->Current(); } else { - throw std::runtime_error("PopCenter::PopCenterNextTurnMeterValue dealing with invalid meter type"); + Logger().errorStream() << "PopCenter::PopCenterNextTurnMeterValue dealing with invalid meter type"; return 0.0; } } Modified: trunk/FreeOrion/universe/ResourceCenter.cpp =================================================================== --- trunk/FreeOrion/universe/ResourceCenter.cpp 2010-05-11 06:40:05 UTC (rev 3587) +++ trunk/FreeOrion/universe/ResourceCenter.cpp 2010-05-15 20:28:05 UTC (rev 3588) @@ -85,14 +85,23 @@ MeterType target_meter_type = INVALID_METER_TYPE; switch (type) { - case (METER_FARMING): target_meter_type = METER_TARGET_FARMING; break; - case (METER_MINING): target_meter_type = METER_TARGET_MINING; break; - case (METER_INDUSTRY): target_meter_type = METER_TARGET_INDUSTRY; break; - case (METER_RESEARCH): target_meter_type = METER_TARGET_RESEARCH; break; - case (METER_TRADE): target_meter_type = METER_TARGET_TRADE; break; - case (METER_CONSTRUCTION): target_meter_type = METER_TARGET_CONSTRUCTION; break; + case METER_TARGET_FARMING: + case METER_TARGET_MINING: + case METER_TARGET_INDUSTRY: + case METER_TARGET_RESEARCH: + case METER_TARGET_TRADE: + case METER_TARGET_CONSTRUCTION: + return current_meter_value; + break; + case METER_FARMING: target_meter_type = METER_TARGET_FARMING; break; + case METER_MINING: target_meter_type = METER_TARGET_MINING; break; + case METER_INDUSTRY: target_meter_type = METER_TARGET_INDUSTRY; break; + case METER_RESEARCH: target_meter_type = METER_TARGET_RESEARCH; break; + case METER_TRADE: target_meter_type = METER_TARGET_TRADE; break; + case METER_CONSTRUCTION:target_meter_type = METER_TARGET_CONSTRUCTION; break; default: - throw std::runtime_error("ResourceCenter::ResourceCenterNextTurnMeterValue dealing with invalid meter type"); + Logger().errorStream() << "ResourceCenter::ResourceCenterNextTurnMeterValue dealing with invalid meter type"; + return 0.0; } const Meter* target_meter = GetMeter(target_meter_type); |
From: <geo...@us...> - 2010-06-21 08:30:24
|
Revision: 3630 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3630&view=rev Author: geoffthemedio Date: 2010-06-21 08:30:18 +0000 (Mon, 21 Jun 2010) Log Message: ----------- Added empty() and NumSpecies() functions to SpeciesManager. Modified Paths: -------------- trunk/FreeOrion/universe/Species.cpp trunk/FreeOrion/universe/Species.h Modified: trunk/FreeOrion/universe/Species.cpp =================================================================== --- trunk/FreeOrion/universe/Species.cpp 2010-06-21 08:29:07 UTC (rev 3629) +++ trunk/FreeOrion/universe/Species.cpp 2010-06-21 08:30:18 UTC (rev 3630) @@ -211,7 +211,15 @@ return m_species.end(); } +bool SpeciesManager::empty() const { + return m_species.empty(); +} +int SpeciesManager::NumSpecies() const { + return m_species.size(); +} + + /////////////////////////////////////////////////////////// // Free Functions // /////////////////////////////////////////////////////////// Modified: trunk/FreeOrion/universe/Species.h =================================================================== --- trunk/FreeOrion/universe/Species.h 2010-06-21 08:29:07 UTC (rev 3629) +++ trunk/FreeOrion/universe/Species.h 2010-06-21 08:30:18 UTC (rev 3630) @@ -104,6 +104,12 @@ /** iterator to the last + 1th building type */ iterator end() const; + /** returns true iff this SpeciesManager is empty. */ + bool empty() const; + + /** returns the number of species stored in this manager. */ + int NumSpecies() const; + /** returns the instance of this singleton class; you should use the free * function GetSpeciesManager() instead */ static SpeciesManager& GetSpeciesManager(); |
From: <geo...@us...> - 2010-07-09 07:30:28
|
Revision: 3650 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3650&view=rev Author: geoffthemedio Date: 2010-07-09 07:30:22 +0000 (Fri, 09 Jul 2010) Log Message: ----------- -Added a set of IDs to species to store the species' homeworlds(s) in a particular game, and accessors and mutators for this set. The homeworlds(s) that a species ends up having will vary from game to game, unlike the rest of the information about a species, which is determined from the species definition in data files. -Added serialization code for SpeciesManager, which just serializes or restores the homeworld ids of species in the manager, since that's the only information that needs to be sent. This assumes that the manager has already loaded the base species definitions from the data files. Modified Paths: -------------- trunk/FreeOrion/universe/Species.cpp trunk/FreeOrion/universe/Species.h Modified: trunk/FreeOrion/universe/Species.cpp =================================================================== --- trunk/FreeOrion/universe/Species.cpp 2010-07-09 06:44:17 UTC (rev 3649) +++ trunk/FreeOrion/universe/Species.cpp 2010-07-09 07:30:22 UTC (rev 3650) @@ -102,6 +102,10 @@ return m_description; } +const std::set<int>& Species::Homeworlds() const { + return m_homeworlds; +} + std::string Species::Dump() const { std::string retval = DumpIndent() + "Species\n"; ++g_indent; @@ -151,7 +155,32 @@ return m_graphic; } +void Species::AddHomeworld(int homeworld_id) { + if (!GetMainObjectMap().Object(homeworld_id)) + Logger().debugStream() << "Species asked to add homeworld id " << homeworld_id << " but there is no such object in the Universe"; + if (m_homeworlds.find(homeworld_id) == m_homeworlds.end()) + return; + m_homeworlds.insert(homeworld_id); + // TODO if needed: StateChangedSignal(); +} +void Species::RemoveHomeworld(int homeworld_id) { + if (m_homeworlds.find(homeworld_id) == m_homeworlds.end()) { + Logger().debugStream() << "Species asked to remove homeworld id " << homeworld_id << " but doesn't have that id as a homeworld"; + return; + } + m_homeworlds.erase(homeworld_id); + // TODO if needed: StateChangedSignal(); +} + +void Species::SetHomeworlds(const std::set<int>& homeworld_ids) { + if (m_homeworlds == homeworld_ids) + return; + m_homeworlds = homeworld_ids; + // TODO if needed: StateChangedSignal(); +} + + ///////////////////////////////////////////////// // SpeciesManager // ///////////////////////////////////////////////// @@ -219,7 +248,41 @@ return m_species.size(); } +void SpeciesManager::SetSpeciesHomeworlds(const std::map<std::string, std::set<int> >& species_homeworld_ids) { + for (std::map<std::string, std::set<int> >::const_iterator it = species_homeworld_ids.begin(); it != species_homeworld_ids.end(); ++it) { + const std::string& species_name = it->first; + const std::set<int>& homeworlds = it->second; + Species* species = 0; + std::map<std::string, Species*>::iterator species_it = m_species.find(species_name); + if (species_it != m_species.end()) + species = species_it->second; + + if (species) { + species->SetHomeworlds(homeworlds); + } else { + Logger().errorStream() << "SpeciesManager::SetSpeciesHomeworlds couldn't find a species with name " << species_name << " to assign homeworlds to"; + } + } +} + +std::map<std::string, std::set<int> > SpeciesManager::GetSpeciesHomeworldsMap() const { + std::map<std::string, std::set<int> > retval; + for (iterator it = begin(); it != end(); ++it) { + const std::string species_name = it->first; + const Species* species = it->second; + if (!species) { + Logger().errorStream() << "SpeciesManager::GetSpeciesHomeworldsMap found a null species pointer in SpeciesManager?!"; + continue; + } + const std::set<int>& homeworld_ids = species->Homeworlds(); + for (std::set<int>::const_iterator homeworlds_it = homeworld_ids.begin(); homeworlds_it != homeworld_ids.end(); ++homeworlds_it) + retval[species_name].insert(*homeworlds_it); + } + return retval; +} + + /////////////////////////////////////////////////////////// // Free Functions // /////////////////////////////////////////////////////////// Modified: trunk/FreeOrion/universe/Species.h =================================================================== --- trunk/FreeOrion/universe/Species.h 2010-07-09 06:44:17 UTC (rev 3649) +++ trunk/FreeOrion/universe/Species.h 2010-07-09 07:30:22 UTC (rev 3650) @@ -8,6 +8,7 @@ #include <string> #include <vector> #include <map> +#include <set> namespace Condition { struct ConditionBase; @@ -66,6 +67,7 @@ /** \name Accessors */ //@{ const std::string& Name() const; ///< returns the unique name for this type of species const std::string& Description() const;///< returns a text description of this type of species + const std::set<int>& Homeworlds() const; ///< returns the ids of objects that are homeworlds for this species std::string Dump() const; ///< returns a data file format representation of this object const std::vector<FocusType>& Foci() const; ///< returns the focus types this species can use, indexed by name const std::vector<boost::shared_ptr<const Effect::EffectsGroup> >& @@ -73,17 +75,20 @@ const std::string& Graphic() const; ///< returns the name of the grapic file for this species //@} + /** \name Mutators */ //@{ + void AddHomeworld(int homeworld_id); + void RemoveHomeworld(int homeworld_id); + void SetHomeworlds(const std::set<int>& homeworld_ids); + //@} + private: std::string m_name; std::string m_description; + std::set<int> m_homeworlds; std::vector<FocusType> m_foci; std::vector<boost::shared_ptr<const Effect::EffectsGroup> > m_effects; std::string m_graphic; - - friend class boost::serialization::access; - template <class Archive> - void serialize(Archive& ar, const unsigned int version); }; @@ -119,9 +124,21 @@ SpeciesManager(); ~SpeciesManager(); + /** sets the homeworld ids of species in this SpeciesManager to those + * specified in \a species_homeworld_ids */ + void SetSpeciesHomeworlds(const std::map<std::string, std::set<int> >& species_homeworld_ids); + + /** returns a map from species name to a set of object IDs that are the + * homeworld(s) of that species in the current game. */ + std::map<std::string, std::set<int> > GetSpeciesHomeworldsMap() const; + std::map<std::string, Species*> m_species; static SpeciesManager* s_instance; + + friend class boost::serialization::access; + template <class Archive> + void serialize(Archive& ar, const unsigned int version); }; /** returns the singleton species manager */ @@ -133,12 +150,22 @@ // template implementations template <class Archive> -void Species::serialize(Archive& ar, const unsigned int version) +void SpeciesManager::serialize(Archive& ar, const unsigned int version) { - ar & BOOST_SERIALIZATION_NVP(m_name) - & BOOST_SERIALIZATION_NVP(m_description) - & BOOST_SERIALIZATION_NVP(m_effects) - & BOOST_SERIALIZATION_NVP(m_graphic); + // Don't need to send all the data about species, as this is derived from + // content data files in species.txt that should be available to any + // client or server. Instead, just need to send the gamestate portion of + // species: their homeworlds in the current game + if (Archive::is_saving::value) { + std::map<std::string, std::set<int> > species_homeworlds_map = GetSpeciesHomeworldsMap(); + ar & BOOST_SERIALIZATION_NVP(species_homeworlds_map); + } + + if (Archive::is_loading::value) { + std::map<std::string, std::set<int> > species_homeworlds_map; + ar & BOOST_SERIALIZATION_NVP(species_homeworlds_map); + SetSpeciesHomeworlds(species_homeworlds_map); + } } #endif // _Species_h_ |
From: <geo...@us...> - 2010-07-11 18:03:51
|
Revision: 3652 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3652&view=rev Author: geoffthemedio Date: 2010-07-11 18:03:45 +0000 (Sun, 11 Jul 2010) Log Message: ----------- -Added std::string ValueRef specialization, with template specialized ValueRef::Constant::Description, ValueRef::Constant::Dump and ValueRef::Operation::Eval. The latter was necessary because the various mathematical operators don't work with std::string. The string version of Operation::Eval just concatenates the strings of the operands with the text symbols for the operations between them, or prepends a "-" for negation. It could have just thrown an exception if any of these operands were used on strings, but I though it might as well support them should someone want to use them... (Note: it might be worth adding stringtable lookup and string parameter substitution operands for strings, which would allow arbitrary strings to be created in effects, and would be used with a SetName effect for interesting results.) -Added several ValueRef object string properties and parsing support: object name, object species (works for ships and planets), building type name (works for buildings), and focus (works for planets, though should really work for any ResourceCenter). There is currently now way to actually use these properties, however, as no effects or conditions take string parameters. I'll be adding one soon, hopefully. -Added several ValueRef object int properties and parsing: DesignID (works for ships), FleetID (works for ships), PlanetID (works for buildings), SystemID (works for any object), FinalDestinationID (works for fleets), NextSystemID (works for fleets), PreviousSystemID (works for fleets), NumShips (works for fleets). -Edited comments in various files. Modified Paths: -------------- trunk/FreeOrion/universe/ValueRef.cpp trunk/FreeOrion/universe/ValueRef.h trunk/FreeOrion/universe/ValueRefParser.cpp trunk/FreeOrion/universe/ValueRefParser.h Modified: trunk/FreeOrion/universe/ValueRef.cpp =================================================================== --- trunk/FreeOrion/universe/ValueRef.cpp 2010-07-11 05:40:25 UTC (rev 3651) +++ trunk/FreeOrion/universe/ValueRef.cpp 2010-07-11 18:03:45 UTC (rev 3652) @@ -78,6 +78,12 @@ } template <> + std::string Constant<std::string>::Description() const + { + return m_value; + } + + template <> std::string Constant<PlanetSize>::Dump() const { switch (m_value) { @@ -165,6 +171,12 @@ { return Description(); } + + template <> + std::string Constant<std::string>::Dump() const + { + return Description(); + } } @@ -411,15 +423,50 @@ if (object->Owners().size() == 1) retval = *object->Owners().begin(); else - retval = -1; + retval = ALL_EMPIRES; } else if (boost::iequals(property_name, "ID")) { retval = object->ID(); - } else if (boost::iequals(property_name, "CurrentTurn")) { - retval = CurrentTurn(); } else if (boost::iequals(property_name, "CreationTurn")) { retval = object->CreationTurn(); } else if (boost::iequals(property_name, "Age")) { retval = object->AgeInTurns(); + } else if (boost::iequals(property_name, "DesignID")) { + if (const Ship* ship = universe_object_cast<const Ship*>(object)) + retval = ship->DesignID(); + else + retval = ShipDesign::INVALID_DESIGN_ID; + } else if (boost::iequals(property_name, "FleetID")) { + if (const Ship* ship = universe_object_cast<const Ship*>(object)) + retval = ship->FleetID(); + else + retval = UniverseObject::INVALID_OBJECT_ID; + } else if (boost::iequals(property_name, "PlanetID")) { + if (const Building* building = universe_object_cast<const Building*>(object)) + retval = building->PlanetID(); + else + retval = UniverseObject::INVALID_OBJECT_ID; + } else if (boost::iequals(property_name, "SystemID")) { + retval = object->SystemID(); + } else if (boost::iequals(property_name, "FinalDestinationID")) { + if (const Fleet* fleet = universe_object_cast<const Fleet*>(object)) + retval = fleet->FinalDestinationID(); + else + retval = UniverseObject::INVALID_OBJECT_ID; + } else if (boost::iequals(property_name, "NextSystemID")) { + if (const Fleet* fleet = universe_object_cast<const Fleet*>(object)) + retval = fleet->NextSystemID(); + else + retval = UniverseObject::INVALID_OBJECT_ID; + } else if (boost::iequals(property_name, "PreviousSystemID")) { + if (const Fleet* fleet = universe_object_cast<const Fleet*>(object)) + retval = fleet->PreviousSystemID(); + else + retval = UniverseObject::INVALID_OBJECT_ID; + } else if (boost::iequals(property_name, "NumShips")) { + if (const Fleet* fleet = universe_object_cast<const Fleet*>(object)) + retval = fleet->NumShips(); + else + retval = 0; } else if (boost::iequals(property_name, "CurrentTurn")) { retval = CurrentTurn(); } else { @@ -429,9 +476,65 @@ return retval; } + template <> + std::string Variable<std::string>::Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const + { + std::string retval; + const UniverseObject* object = FollowReference(m_property_name.begin(), m_property_name.end(), m_source_ref ? source : target); + std::string property_name = m_property_name.back(); + IF_CURRENT_VALUE_ELSE(std::string) + if (boost::iequals(property_name, "Name")) { + retval = object->Name(); + } else if (boost::iequals(property_name, "Species")) { + if (const Planet* planet = universe_object_cast<const Planet*>(object)) + retval = planet->SpeciesName(); + else if (const Ship* ship = universe_object_cast<const Ship*>(object)) + retval = ship->SpeciesName(); + } else if (boost::iequals(property_name, "BuildingType")) { + if (const Building* building = universe_object_cast<const Building*>(object)) + retval = building->BuildingTypeName(); + } else if (boost::iequals(property_name, "Focus")) { + if (const Planet* planet = universe_object_cast<const Planet*>(object)) + retval = planet->Focus(); + } else { + throw std::runtime_error("Attempted to read a non-string value \"" + ReconstructName(m_property_name, m_source_ref) + "\" using a ValueRef of type std::string."); + } + + return retval; + } + #undef IF_CURRENT_VALUE_ELSE } +/////////////////////////////////////////////////////////// +// Operation // +/////////////////////////////////////////////////////////// +namespace ValueRef { + template <> + std::string Operation<std::string>::Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const + { + std::string op_link; + switch (m_op_type) { + case PLUS: op_link = " + "; break; + case MINUS: op_link = " - "; break; + case TIMES: op_link = " * "; break; + case DIVIDES: op_link = " / "; break; + case NEGATE: + return "-" + m_operand1->Eval(source, target, current_value); + break; + default: + throw std::runtime_error("std::string ValueRef evaluated with an unknown OpType."); + break; + } + return m_operand1->Eval(source, target, current_value) + + op_link + + m_operand2->Eval(source, target, current_value); + } +} + + std::string DumpIndent() { return std::string(g_indent * 4, ' '); Modified: trunk/FreeOrion/universe/ValueRef.h =================================================================== --- trunk/FreeOrion/universe/ValueRef.h 2010-07-11 05:40:25 UTC (rev 3651) +++ trunk/FreeOrion/universe/ValueRef.h 2010-07-11 18:03:45 UTC (rev 3652) @@ -20,8 +20,9 @@ std::vector<std::string> TokenizeDottedReference(const std::string& str); } -/** this namespace contains ValueRefBase and its subclasses. The ValueRefBase subclasses represent expression trees that may be - evaluated at various times, and which refer to both constant and variable values. */ +/** This namespace contains ValueRefBase and its subclasses. The ValueRefBase + * subclasses represent expression trees that may be evaluated at various + * times, and which refer to both constant and variable values. */ namespace ValueRef { template <class T> struct ValueRefBase; template <class T> struct Constant; @@ -38,7 +39,8 @@ template <class T> bool ConstantExpr(const ValueRefBase<T>* expr); } -/** the base class for all ValueRef classes. This class provides the public interface for a ValueRef expression tree. */ +/** The base class for all ValueRef classes. This class provides the public + * interface for a ValueRef expression tree. */ template <class T> struct ValueRef::ValueRefBase { @@ -80,12 +82,14 @@ void serialize(Archive& ar, const unsigned int version); }; -/** the variable value ValueRef class. The value returned by this node is taken from either the \a source or \a target parameters to Eval. */ +/** The variable value ValueRef class. The value returned by this node is + * taken from either the \a source or \a target parameters to Eval. */ template <class T> struct ValueRef::Variable : public ValueRef::ValueRefBase<T> { - /** basic ctor. If \a source_ref is true, the field corresponding to \a property_name is read from the - \a source parameter of Eval; otherwise, the same field is read from Eval's \a target parameter. */ + /** basic ctor. If \a source_ref is true, the field corresponding to + * \a property_name is read from the \a source parameter of Eval; + * otherwise, the same field is read from Eval's \a target parameter. */ Variable(bool source_ref, const std::string& property_name); bool SourceRef() const; @@ -108,8 +112,9 @@ void serialize(Archive& ar, const unsigned int version); }; -/** the variable static_cast class. The value returned by this node is taken from the ctor \a value_ref parameter's FromType value, - static_cast to ToType. */ +/** The variable static_cast class. The value returned by this node is taken + * from the ctor \a value_ref parameter's FromType value, static_cast to + * ToType. */ template <class FromType, class ToType> struct ValueRef::StaticCast : public ValueRef::Variable<ToType> { @@ -129,8 +134,9 @@ void serialize(Archive& ar, const unsigned int version); }; -/** an arithmetic operation node ValueRef class. One of addition, subtraction, mutiplication, division, or unary negation is - performed on the child(ren) of this node, and the result is returned. */ +/** An arithmetic operation node ValueRef class. One of addition, subtraction, + * mutiplication, division, or unary negation is performed on the child(ren) + * of this node, and the result is returned. */ template <class T> struct ValueRef::Operation : public ValueRef::ValueRefBase<T> { @@ -157,8 +163,9 @@ void serialize(Archive& ar, const unsigned int version); }; -/** A function that returns the correct amount of spacing for the current indentation level during a dump. Note that - this function is used by several units (Condition.cpp, Effect.cpp, etc.), not just this one. */ +/** A function that returns the correct amount of spacing for the current + * indentation level during a dump. Note that this function is used by + * several units (Condition.cpp, Effect.cpp, etc.), not just this one. */ std::string DumpIndent(); @@ -206,6 +213,9 @@ std::string Constant<double>::Description() const; template <> + std::string Constant<std::string>::Description() const; + + template <> std::string Constant<PlanetSize>::Dump() const; template <> @@ -225,6 +235,9 @@ template <> std::string Constant<int>::Dump() const; + + template <> + std::string Constant<std::string>::Dump() const; } template <class T> @@ -437,6 +450,12 @@ } } +namespace ValueRef { + template <> + std::string Operation<std::string>::Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const; +} + template <class T> std::string ValueRef::Operation<T>::Description() const { Modified: trunk/FreeOrion/universe/ValueRefParser.cpp =================================================================== --- trunk/FreeOrion/universe/ValueRefParser.cpp 2010-07-11 05:40:25 UTC (rev 3651) +++ trunk/FreeOrion/universe/ValueRefParser.cpp 2010-07-11 18:03:45 UTC (rev 3652) @@ -7,6 +7,7 @@ using namespace boost::spirit::classic; using namespace phoenix; +StringValueRefRule string_expr_p; IntValueRefRule int_expr_p; DoubleValueRefRule double_expr_p; PlanetSizeValueRefRule planetsize_expr_p; @@ -20,11 +21,11 @@ class ValueRefParserDefinition { public: - typedef ValueRef::ValueRefBase<T> RefBase; - typedef ValueRef::Constant<T> RefConst; - typedef ValueRef::Variable<T> RefVar; - typedef ValueRef::Variable<int> IntRefVar; - typedef ValueRef::Operation<T> RefOp; + typedef ValueRef::ValueRefBase<T> RefBase; + typedef ValueRef::Constant<T> RefConst; + typedef ValueRef::Variable<T> RefVar; + typedef ValueRef::Variable<int> IntRefVar; + typedef ValueRef::Operation<T> RefOp; typedef typename ValueRefRule<T>::type Rule; @@ -47,6 +48,7 @@ Rule minus_expr; }; + ValueRefParserDefinition<std::string> string_value_ref_def(string_expr_p); ValueRefParserDefinition<int> int_value_ref_def(int_expr_p); ValueRefParserDefinition<double> double_value_ref_def(double_expr_p); ValueRefParserDefinition<PlanetSize> planetsize_value_ref_def(planetsize_expr_p); @@ -62,7 +64,15 @@ str_p("owner") | "id" | "creationturn" - | "age"; + | "age" + | "designid" + | "fleetid" + | "planetid" + | "systemid" + | "finaldestinationid" + | "nextsystemid" + | "previoussystemid" + | "numships"; SpecializedInit(); @@ -102,6 +112,19 @@ } template <> + void ValueRefParserDefinition<std::string>::SpecializedInit() + { + constant = + name_p[constant.this_ = new_<RefConst>(arg1)]; + + variable_final = + str_p("name") + | "species" + | "buildingtype" + | "focus"; + } + + template <> void ValueRefParserDefinition<int>::SpecializedInit() { constant = Modified: trunk/FreeOrion/universe/ValueRefParser.h =================================================================== --- trunk/FreeOrion/universe/ValueRefParser.h 2010-07-11 05:40:25 UTC (rev 3651) +++ trunk/FreeOrion/universe/ValueRefParser.h 2010-07-11 18:03:45 UTC (rev 3652) @@ -21,6 +21,7 @@ typedef boost::spirit::classic::rule<Scanner, typename Closure::context_t> type; }; +typedef ValueRefRule<std::string>::type StringValueRefRule; typedef ValueRefRule<int>::type IntValueRefRule; typedef ValueRefRule<double>::type DoubleValueRefRule; typedef ValueRefRule<PlanetSize>::type PlanetSizeValueRefRule; @@ -29,6 +30,7 @@ typedef ValueRefRule<UniverseObjectType>::type UniverseObjectTypeValueRefRule; typedef ValueRefRule<StarType>::type StarTypeValueRefRule; +extern StringValueRefRule string_expr_p; extern IntValueRefRule int_expr_p; extern DoubleValueRefRule double_expr_p; extern PlanetSizeValueRefRule planetsize_expr_p; |
From: <geo...@us...> - 2010-07-13 04:51:45
|
Revision: 3657 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3657&view=rev Author: geoffthemedio Date: 2010-07-13 04:51:37 +0000 (Tue, 13 Jul 2010) Log Message: ----------- -Added a non-const Species* getter to SpeciesManager -Modified Universe::GenerateEmpires to add homeworlds of empires to species on those homeworlds, so players' starting planets will receive any homeworld-related bonuses while populated by the species that start on them. None of this actually does anything yet, though, as the SpeciesManager isn't yet serialized in turn updates or saved games. Modified Paths: -------------- trunk/FreeOrion/universe/Species.cpp trunk/FreeOrion/universe/Species.h trunk/FreeOrion/universe/Universe.cpp Modified: trunk/FreeOrion/universe/Species.cpp =================================================================== --- trunk/FreeOrion/universe/Species.cpp 2010-07-13 03:18:18 UTC (rev 3656) +++ trunk/FreeOrion/universe/Species.cpp 2010-07-13 04:51:37 UTC (rev 3657) @@ -288,6 +288,11 @@ return it != m_species.end() ? it->second : 0; } +Species* SpeciesManager::GetSpecies(const std::string& name) { + std::map<std::string, Species*>::iterator it = m_species.find(name); + return it != m_species.end() ? it->second : 0; +} + SpeciesManager& SpeciesManager::GetSpeciesManager() { static SpeciesManager manager; return manager; Modified: trunk/FreeOrion/universe/Species.h =================================================================== --- trunk/FreeOrion/universe/Species.h 2010-07-13 03:18:18 UTC (rev 3656) +++ trunk/FreeOrion/universe/Species.h 2010-07-13 04:51:37 UTC (rev 3657) @@ -109,6 +109,7 @@ /** returns the building type with the name \a name; you should use the * free function GetSpecies() instead, mainly to save some typing. */ const Species* GetSpecies(const std::string& name) const; + Species* GetSpecies(const std::string& name); /** iterator to the first building type */ iterator begin() const; @@ -133,7 +134,7 @@ /** sets the homeworld ids of species in this SpeciesManager to those * specified in \a species_homeworld_ids */ - void SetSpeciesHomeworlds(const std::map<std::string, std::set<int> >& species_homeworld_ids); + void SetSpeciesHomeworlds(const std::map<std::string, std::set<int> >& species_homeworld_ids); /** returns a map from species name to a set of object IDs that are the * homeworld(s) of that species in the current game. */ Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2010-07-13 03:18:18 UTC (rev 3656) +++ trunk/FreeOrion/universe/Universe.cpp 2010-07-13 04:51:37 UTC (rev 3657) @@ -4184,7 +4184,7 @@ std::vector<GG::Clr> colors = EmpireColors(); // copy, not reference, so that individual colours can be removed after they're used - const SpeciesManager& species_manager = GetSpeciesManager(); + SpeciesManager& species_manager = GetSpeciesManager(); const PredefinedShipDesignManager& predefined_ship_designs = GetPredefinedShipDesignManager(); const FleetPlanManager& starting_fleet_plans = GetFleetPlanManager(); @@ -4286,6 +4286,11 @@ //home_system->AddOwner(empire_id); // should be redundant home_planet->SetSpecies(empire_starting_species); + if (Species* species = species_manager.GetSpecies(empire_starting_species)) + species->AddHomeworld(homeworld_id); + else + Logger().errorStream() << "Universe::GenerateEmpires Couldn't get species \"" << empire_starting_species << "\" to set with homeworld id " << homeworld_id; + // find a focus to give planets by default. use first defined available focus. // the planet's AvailableFoci function should return a vector of all names of // available foci, although this might be buggy since the universe isn't fully |
From: <geo...@us...> - 2010-07-13 07:56:50
|
Revision: 3660 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3660&view=rev Author: geoffthemedio Date: 2010-07-13 07:56:44 +0000 (Tue, 13 Jul 2010) Log Message: ----------- -Switched a == to a != in code that adds planet ID to a Species' list of homeworlds. This fixes a bug where species couldn't be given homeworlds they didn't already have. -Added a (currently unused) s_encoding_empire parameter to SpeciesManager::GetSpeciesHomeworldsMap that is used during serialization to get information to send to players or save to disk. This may be used to censor the species data sent to players in future. -Rewrote SpeciesManager::serialize to remove code redundancy. Modified Paths: -------------- trunk/FreeOrion/universe/Species.cpp trunk/FreeOrion/universe/Species.h Modified: trunk/FreeOrion/universe/Species.cpp =================================================================== --- trunk/FreeOrion/universe/Species.cpp 2010-07-13 05:09:16 UTC (rev 3659) +++ trunk/FreeOrion/universe/Species.cpp 2010-07-13 07:56:44 UTC (rev 3660) @@ -219,7 +219,7 @@ void Species::AddHomeworld(int homeworld_id) { if (!GetMainObjectMap().Object(homeworld_id)) Logger().debugStream() << "Species asked to add homeworld id " << homeworld_id << " but there is no such object in the Universe"; - if (m_homeworlds.find(homeworld_id) == m_homeworlds.end()) + if (m_homeworlds.find(homeworld_id) != m_homeworlds.end()) return; m_homeworlds.insert(homeworld_id); // TODO if needed: StateChangedSignal(); @@ -332,7 +332,7 @@ } } -std::map<std::string, std::set<int> > SpeciesManager::GetSpeciesHomeworldsMap() const { +std::map<std::string, std::set<int> > SpeciesManager::GetSpeciesHomeworldsMap(int encoding_empire/* = ALL_EMPIRES*/) const { std::map<std::string, std::set<int> > retval; for (iterator it = begin(); it != end(); ++it) { const std::string species_name = it->first; Modified: trunk/FreeOrion/universe/Species.h =================================================================== --- trunk/FreeOrion/universe/Species.h 2010-07-13 05:09:16 UTC (rev 3659) +++ trunk/FreeOrion/universe/Species.h 2010-07-13 07:56:44 UTC (rev 3660) @@ -3,6 +3,7 @@ #define _Species_h_ #include "Enums.h" +#include "Universe.h" #include <boost/shared_ptr.hpp> #include <boost/serialization/nvp.hpp> @@ -138,7 +139,7 @@ /** returns a map from species name to a set of object IDs that are the * homeworld(s) of that species in the current game. */ - std::map<std::string, std::set<int> > GetSpeciesHomeworldsMap() const; + std::map<std::string, std::set<int> > GetSpeciesHomeworldsMap(int encoding_empire = ALL_EMPIRES) const; std::map<std::string, Species*> m_species; @@ -164,14 +165,16 @@ // content data files in species.txt that should be available to any // client or server. Instead, just need to send the gamestate portion of // species: their homeworlds in the current game + + std::map<std::string, std::set<int> > species_homeworlds_map; + if (Archive::is_saving::value) { - std::map<std::string, std::set<int> > species_homeworlds_map = GetSpeciesHomeworldsMap(); - ar & BOOST_SERIALIZATION_NVP(species_homeworlds_map); + species_homeworlds_map = GetSpeciesHomeworldsMap(Universe::s_encoding_empire); } + ar & BOOST_SERIALIZATION_NVP(species_homeworlds_map); + if (Archive::is_loading::value) { - std::map<std::string, std::set<int> > species_homeworlds_map; - ar & BOOST_SERIALIZATION_NVP(species_homeworlds_map); SetSpeciesHomeworlds(species_homeworlds_map); } } |
From: <geo...@us...> - 2010-07-14 18:43:22
|
Revision: 3663 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3663&view=rev Author: geoffthemedio Date: 2010-07-14 18:43:16 +0000 (Wed, 14 Jul 2010) Log Message: ----------- -Added clamping and resetting of food consumption meter to PopCenter meter clamping and resetting (of several meters) functions. -Skipped further processing and storing of empty EffectsGroup target sets in Universe::StoreTargetsAndCausesOfEffectsGroups. Modified Paths: -------------- trunk/FreeOrion/universe/PopCenter.cpp trunk/FreeOrion/universe/Universe.cpp Modified: trunk/FreeOrion/universe/PopCenter.cpp =================================================================== --- trunk/FreeOrion/universe/PopCenter.cpp 2010-07-14 15:15:20 UTC (rev 3662) +++ trunk/FreeOrion/universe/PopCenter.cpp 2010-07-14 18:43:16 UTC (rev 3663) @@ -224,6 +224,7 @@ GetMeter(METER_TARGET_POPULATION)->ClampCurrentToRange(); GetMeter(METER_HEALTH)->ClampCurrentToRange(); GetMeter(METER_TARGET_HEALTH)->ClampCurrentToRange(); + GetMeter(METER_FOOD_CONSUMPTION)->ClampCurrentToRange(); } void PopCenter::Reset() @@ -232,6 +233,7 @@ GetMeter(METER_TARGET_POPULATION)->Reset(); GetMeter(METER_HEALTH)->Reset(); GetMeter(METER_TARGET_HEALTH)->Reset(); + GetMeter(METER_FOOD_CONSUMPTION)->Reset(); m_species_name.clear(); m_allocated_food = 0.0; } Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2010-07-14 15:15:20 UTC (rev 3662) +++ trunk/FreeOrion/universe/Universe.cpp 2010-07-14 18:43:16 UTC (rev 3663) @@ -1358,15 +1358,19 @@ // get effects group to process for this iteration boost::shared_ptr<const Effect::EffectsGroup> effects_group = *effects_it; + // get set of target objects for this effects group from potential targets specified + effects_group->GetTargetSet(source_object_id, target_set, potential_target_set); // transfers objects from potential_target_set to target_set if they meet the condition + + // abort if no targets + if (target_set.empty()) + continue; + // combine effects group and source object id into a sourced effects group SourcedEffectsGroup sourced_effects_group(source_object_id, effects_group); // combine cause type and specific cause into effect cause EffectCause effect_cause(effect_cause_type, specific_cause_name); - // get set of target objects for this effects group from potential targets specified - effects_group->GetTargetSet(source_object_id, target_set, potential_target_set); // transfers objects from potential_target_set to target_set if they meet the condition - // combine target set and effect cause EffectTargetAndCause target_and_cause(target_set, effect_cause); |
From: <geo...@us...> - 2010-07-15 03:22:24
|
Revision: 3665 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3665&view=rev Author: geoffthemedio Date: 2010-07-15 03:22:18 +0000 (Thu, 15 Jul 2010) Log Message: ----------- Added SpeciesManager::ClearSpeciesHomeworlds to remove all homeworlds from species. This is useful when deserializing species from a save or turn update, or starting a new game, where any previous homeworlds of species should not be retained, as they could very likely be different from those in the new game. Modified Paths: -------------- trunk/FreeOrion/universe/Species.cpp trunk/FreeOrion/universe/Species.h trunk/FreeOrion/universe/Universe.cpp Modified: trunk/FreeOrion/universe/Species.cpp =================================================================== --- trunk/FreeOrion/universe/Species.cpp 2010-07-15 02:33:36 UTC (rev 3664) +++ trunk/FreeOrion/universe/Species.cpp 2010-07-15 03:22:18 UTC (rev 3665) @@ -314,7 +314,13 @@ return m_species.size(); } +void SpeciesManager::ClearSpeciesHomeworlds() { + for (std::map<std::string, Species*>::iterator it = m_species.begin(); it != m_species.end(); ++it) + it->second->SetHomeworlds(std::set<int>()); +} + void SpeciesManager::SetSpeciesHomeworlds(const std::map<std::string, std::set<int> >& species_homeworld_ids) { + ClearSpeciesHomeworlds(); for (std::map<std::string, std::set<int> >::const_iterator it = species_homeworld_ids.begin(); it != species_homeworld_ids.end(); ++it) { const std::string& species_name = it->first; const std::set<int>& homeworlds = it->second; Modified: trunk/FreeOrion/universe/Species.h =================================================================== --- trunk/FreeOrion/universe/Species.h 2010-07-15 02:33:36 UTC (rev 3664) +++ trunk/FreeOrion/universe/Species.h 2010-07-15 03:22:18 UTC (rev 3665) @@ -129,6 +129,13 @@ static SpeciesManager& GetSpeciesManager(); //@} + /** \name Mutators */ //@{ + /** sets all species to have no homeworlds. this is useful when generating + * a new game, when any homeworlds species had in the previous game should + * be removed before the new game's homeworlds are added. */ + void ClearSpeciesHomeworlds(); + //@} + private: SpeciesManager(); ~SpeciesManager(); Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2010-07-15 02:33:36 UTC (rev 3664) +++ trunk/FreeOrion/universe/Universe.cpp 2010-07-15 03:22:18 UTC (rev 3665) @@ -4186,6 +4186,7 @@ std::vector<GG::Clr> colors = EmpireColors(); // copy, not reference, so that individual colours can be removed after they're used SpeciesManager& species_manager = GetSpeciesManager(); + species_manager.ClearSpeciesHomeworlds(); const PredefinedShipDesignManager& predefined_ship_designs = GetPredefinedShipDesignManager(); const FleetPlanManager& starting_fleet_plans = GetFleetPlanManager(); |
From: <geo...@us...> - 2010-07-21 17:10:34
|
Revision: 3693 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3693&view=rev Author: geoffthemedio Date: 2010-07-21 17:10:25 +0000 (Wed, 21 Jul 2010) Log Message: ----------- -Made Condition::ConditionBase::Match and ::Match of derived classes private again. It doesn't actually work to evaluate a single condition on a single object using Match, as some conditions override Eval to not use Match, or to use Match in a different way such that it only works in general to add an object to an ObjectSet and evalulate the condition on that ObjectSet to check if the single UniverseObject matches the condition. -Modified Planet::AvailableFoci and BuildingType::ProductionLocation to match locations using an ObjectSet and Eval rather than Match on a single object. -Changed Condition::ObjectSet to be a std::set<const UniverseObject*>. This allows evaluation of conditions to be const-correct: evaluating a condition on objects never changes them. -The above also means that passing an ObjectSet to be acted on by an effect won't work, so moved EffectsGroup::TargetSet into the enclosing Effect namespace, and changed it to a directly defined std::set<UniverseObject*> instead of being defined as a typedef of ConditionObjectSet. This lets Effect::ObjectSet be forward declared in files that don't include Effect.h, and makes ObjectSet and TargetSet not automatically interconvertable. -Added explicit conversion functions in either direction between TargetSet and ObjectSet in Effect.cpp. -Used conversion functions to rewrite EffectsGroup::GetTargetSet: this takes TargetSet parameters, converts to ObjectSet, evaluates conditions on the set, converts back to TargetSet that can be later acted on by effects. -Accordingly changed various Condition::ObjectSet uses throughout Universe header and code to use appropriate TargetSet where previously the equivalence of TargetSet and ObjectSet was being assumed. Modified Paths: -------------- trunk/FreeOrion/universe/Building.cpp trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/Condition.h trunk/FreeOrion/universe/Effect.cpp trunk/FreeOrion/universe/Effect.h trunk/FreeOrion/universe/Planet.cpp trunk/FreeOrion/universe/Universe.cpp trunk/FreeOrion/universe/Universe.h Modified: trunk/FreeOrion/universe/Building.cpp =================================================================== --- trunk/FreeOrion/universe/Building.cpp 2010-07-21 08:51:05 UTC (rev 3692) +++ trunk/FreeOrion/universe/Building.cpp 2010-07-21 17:10:25 UTC (rev 3693) @@ -284,24 +284,25 @@ } bool BuildingType::ProductionLocation(int empire_id, int location_id) const { - Condition::ObjectSet locations; - Condition::ObjectSet non_locations; + const ObjectMap& objects = GetMainObjectMap(); - ObjectMap& objects = GetMainObjectMap(); - - UniverseObject* loc = objects.Object(location_id); + const UniverseObject* loc = objects.Object(location_id); if (!loc) return false; - Empire* empire = Empires().Lookup(empire_id); + const Empire* empire = Empires().Lookup(empire_id); if (!empire) { Logger().debugStream() << "BuildingType::ProductionLocation: Unable to get pointer to empire " << empire_id; return false; } - UniverseObject* source = objects.Object(empire->CapitolID()); + const UniverseObject* source = objects.Object(empire->CapitolID()); if (!source) return false; - return m_location->Match(source, source); + Condition::ObjectSet potential_targets; potential_targets.insert(source); + Condition::ObjectSet matched_targets; + m_location->Eval(source, matched_targets, potential_targets); + + return !matched_targets.empty(); } CaptureResult BuildingType::GetCaptureResult(const std::set<int>& from_empire_ids, int to_empire_id, Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2010-07-21 08:51:05 UTC (rev 3692) +++ trunk/FreeOrion/universe/Condition.cpp 2010-07-21 17:10:25 UTC (rev 3693) @@ -1640,7 +1640,7 @@ // get current object while incrementing main iterator ObjectSet::iterator current_non_target_it = non_targets_it++; - UniverseObject* non_target_obj = *current_non_target_it; + const UniverseObject* non_target_obj = *current_non_target_it; // see if current object is within required distance of any condition target for (ObjectSet::iterator condition_targets_it = condition_targets.begin(); condition_targets_it != condition_targets.end(); ++condition_targets_it) { @@ -1667,7 +1667,7 @@ // get current object while incrementing main iterator ObjectSet::iterator current_initial_target_it = initial_targets_it++; - UniverseObject* initial_target_obj = *current_initial_target_it; + const UniverseObject* initial_target_obj = *current_initial_target_it; // see if current object is within required distance of any condition target for (ObjectSet::iterator condition_targets_it = condition_targets.begin(); condition_targets_it != condition_targets.end(); ++condition_targets_it) { Modified: trunk/FreeOrion/universe/Condition.h =================================================================== --- trunk/FreeOrion/universe/Condition.h 2010-07-21 08:51:05 UTC (rev 3692) +++ trunk/FreeOrion/universe/Condition.h 2010-07-21 17:10:25 UTC (rev 3693) @@ -12,7 +12,7 @@ /** this namespace holds ConditionBase and its subclasses; these classes represent predicates about UniverseObjects used by, for instance, the Effect system. */ namespace Condition { - typedef std::set<UniverseObject*> ObjectSet; + typedef std::set<const UniverseObject*> ObjectSet; enum SearchDomain { NON_TARGETS, ///< The Condition will only examine items in the nontarget set; those that match the Condition will be inserted into the target set. @@ -63,9 +63,9 @@ virtual void Eval(const UniverseObject* source, Condition::ObjectSet& targets, Condition::ObjectSet& non_targets, SearchDomain search_domain = NON_TARGETS) const; virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; - virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; private: + virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; friend class boost::serialization::access; template <class Archive> @@ -100,9 +100,10 @@ virtual ~Turn(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: const ValueRef::ValueRefBase<int>* m_low; const ValueRef::ValueRefBase<int>* m_high; @@ -152,9 +153,10 @@ virtual ~EmpireAffiliation(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: const ValueRef::ValueRefBase<int>* m_empire_id; EmpireAffiliationType m_affiliation; bool m_exclusive; @@ -170,9 +172,10 @@ Self(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: friend class boost::serialization::access; template <class Archive> void serialize(Archive& ar, const unsigned int version); @@ -187,9 +190,10 @@ virtual ~Homeworld(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::vector<const ValueRef::ValueRefBase<std::string>*> m_names; friend class boost::serialization::access; @@ -203,9 +207,10 @@ Capitol(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: friend class boost::serialization::access; template <class Archive> void serialize(Archive& ar, const unsigned int version); @@ -217,9 +222,10 @@ Type(const ValueRef::ValueRefBase<UniverseObjectType>* type); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: const ValueRef::ValueRefBase<UniverseObjectType>* m_type; friend class boost::serialization::access; @@ -235,9 +241,10 @@ virtual ~Building(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::vector<const ValueRef::ValueRefBase<std::string>*> m_names; friend class boost::serialization::access; @@ -253,9 +260,10 @@ HasSpecial(const std::string& name); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::string m_name; friend class boost::serialization::access; @@ -308,9 +316,10 @@ virtual ~PlanetType(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::vector<const ValueRef::ValueRefBase< ::PlanetType>*> m_types; friend class boost::serialization::access; @@ -327,9 +336,10 @@ virtual ~PlanetSize(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::vector<const ValueRef::ValueRefBase< ::PlanetSize>*> m_sizes; friend class boost::serialization::access; @@ -345,9 +355,10 @@ virtual ~PlanetEnvironment(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::vector<const ValueRef::ValueRefBase< ::PlanetEnvironment>*> m_environments; friend class boost::serialization::access; @@ -364,9 +375,10 @@ virtual ~Species(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::vector<const ValueRef::ValueRefBase<std::string>*> m_names; friend class boost::serialization::access; @@ -381,9 +393,10 @@ virtual ~FocusType(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::vector<const ValueRef::ValueRefBase<std::string>*> m_names; friend class boost::serialization::access; @@ -399,9 +412,10 @@ virtual ~StarType(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::vector<const ValueRef::ValueRefBase< ::StarType>*> m_types; friend class boost::serialization::access; @@ -415,9 +429,10 @@ DesignHasHull(const std::string& name); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::string m_name; friend class boost::serialization::access; @@ -433,9 +448,10 @@ virtual ~DesignHasPart(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: const ValueRef::ValueRefBase<int>* m_low; const ValueRef::ValueRefBase<int>* m_high; std::string m_name; @@ -452,9 +468,10 @@ virtual ~Chance(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: const ValueRef::ValueRefBase<double>* m_chance; friend class boost::serialization::access; @@ -470,9 +487,10 @@ virtual ~MeterValue(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: MeterType m_meter; const ValueRef::ValueRefBase<double>* m_low; const ValueRef::ValueRefBase<double>* m_high; @@ -490,9 +508,10 @@ virtual ~EmpireStockpileValue(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: ResourceType m_stockpile; const ValueRef::ValueRefBase<double>* m_low; const ValueRef::ValueRefBase<double>* m_high; @@ -508,9 +527,10 @@ OwnerHasTech(const std::string& name); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::string m_name; friend class boost::serialization::access; @@ -525,9 +545,10 @@ virtual ~VisibleToEmpire(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::vector<const ValueRef::ValueRefBase<int>*> m_empire_ids; friend class boost::serialization::access; @@ -545,9 +566,10 @@ virtual void Eval(const UniverseObject* source, Condition::ObjectSet& targets, Condition::ObjectSet& non_targets, SearchDomain search_domain = NON_TARGETS) const; virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: const ValueRef::ValueRefBase<double>* m_distance; const ConditionBase* m_condition; @@ -566,9 +588,10 @@ virtual void Eval(const UniverseObject* source, Condition::ObjectSet& targets, Condition::ObjectSet& non_targets, SearchDomain search_domain = NON_TARGETS) const; virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: const ValueRef::ValueRefBase<int>* m_jumps; const ConditionBase* m_condition; @@ -584,9 +607,10 @@ virtual ~ExploredByEmpire(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; + +private: virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; -private: std::vector<const ValueRef::ValueRefBase<int>*> m_empire_ids; friend class boost::serialization::access; @@ -601,9 +625,9 @@ Stationary(); virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; - virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; private: + virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; friend class boost::serialization::access; template <class Archive> Modified: trunk/FreeOrion/universe/Effect.cpp =================================================================== --- trunk/FreeOrion/universe/Effect.cpp 2010-07-21 08:51:05 UTC (rev 3692) +++ trunk/FreeOrion/universe/Effect.cpp 2010-07-21 17:10:25 UTC (rev 3693) @@ -218,6 +218,19 @@ return false; } + + Condition::ObjectSet EffectTargetSetToConditionObjectSet(const TargetSet& target_set) { + Condition::ObjectSet retval; + std::copy(target_set.begin(), target_set.end(), std::inserter(retval, retval.begin())); + return retval; + } + + TargetSet ConditionObjectSetToEffectTargetSet(const Condition::ObjectSet& object_set) { + TargetSet retval; + for (Condition::ObjectSet::const_iterator it = object_set.begin(); it != object_set.end(); ++it) + retval.insert(const_cast<UniverseObject*>(*it)); + return retval; + } } /////////////////////////////////////////////////////////// @@ -254,24 +267,30 @@ // evaluate the activation condition only on the source object Condition::ObjectSet non_targets; non_targets.insert(source); - m_activation->Eval(source, targets, non_targets); + Condition::ObjectSet matched_targets; + m_activation->Eval(source, matched_targets, non_targets); // if the activation condition did not evaluate to true for the source object, do nothing - if (targets.empty()) + if (matched_targets.empty()) return; // remove source object from target set after activation condition check - targets.clear(); + matched_targets.clear(); + // convert potential targets TargetSet to a Condition::ObjectSet so that condition can be applied to it + non_targets = EffectTargetSetToConditionObjectSet(potential_targets); + // evaluate the scope condition - non_targets = potential_targets; - m_scope->Eval(source, targets, non_targets); + m_scope->Eval(source, matched_targets, non_targets); + + // convert result back to TargetSet + targets = ConditionObjectSetToEffectTargetSet(matched_targets); } void EffectsGroup::GetTargetSet(int source_id, TargetSet& targets) const { ObjectMap& objects = GetUniverse().Objects(); - Condition::ObjectSet potential_targets; + TargetSet potential_targets; for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) potential_targets.insert(it->second); GetTargetSet(source_id, targets, potential_targets); @@ -286,7 +305,7 @@ } // execute effects on targets - for (Condition::ObjectSet::const_iterator it = targets.begin(); it != targets.end(); ++it) { + for (TargetSet::const_iterator it = targets.begin(); it != targets.end(); ++it) { //Logger().debugStream() << "effectsgroup source: " << source->Name() << " target " << (*it)->Name(); for (unsigned int i = 0; i < m_effects.size(); ++i) m_effects[i]->Execute(source, *it); @@ -305,7 +324,7 @@ assert(0 <= effect_index && effect_index < static_cast<int>(m_effects.size())); // execute effect on targets - for (Condition::ObjectSet::const_iterator it = targets.begin(); it != targets.end(); ++it) + for (TargetSet::const_iterator it = targets.begin(); it != targets.end(); ++it) m_effects[effect_index]->Execute(source, *it); } @@ -1178,7 +1197,7 @@ return; // "randomly" pick a destination - UniverseObject* destination = *valid_locations.begin(); + UniverseObject* destination = const_cast<UniverseObject*>(*valid_locations.begin()); // do the moving... Modified: trunk/FreeOrion/universe/Effect.h =================================================================== --- trunk/FreeOrion/universe/Effect.h 2010-07-21 08:51:05 UTC (rev 3692) +++ trunk/FreeOrion/universe/Effect.h 2010-07-21 17:10:25 UTC (rev 3693) @@ -15,7 +15,7 @@ namespace Condition { struct ConditionBase; - typedef std::set<UniverseObject*> ObjectSet; + typedef std::set<const UniverseObject*> ObjectSet; } namespace Effect { @@ -41,6 +41,8 @@ class SetEffectTarget; class MoveTo; class Victory; + + typedef std::set<UniverseObject*> TargetSet; } namespace ValueRef { @@ -57,8 +59,6 @@ class Effect::EffectsGroup { public: - typedef Condition::ObjectSet TargetSet; - struct Description { std::string scope_description; Modified: trunk/FreeOrion/universe/Planet.cpp =================================================================== --- trunk/FreeOrion/universe/Planet.cpp 2010-07-21 08:51:05 UTC (rev 3692) +++ trunk/FreeOrion/universe/Planet.cpp 2010-07-21 17:10:25 UTC (rev 3693) @@ -291,9 +291,14 @@ const std::vector<FocusType>& foci = species->Foci(); for (std::vector<FocusType>::const_iterator it = foci.begin(); it != foci.end(); ++it) { const FocusType& focus_type = *it; - if (const Condition::ConditionBase* location = focus_type.Location()) - if (location->Match(this, this)) + if (const Condition::ConditionBase* location = focus_type.Location()) { + const UniverseObject* source = this; + Condition::ObjectSet potential_targets; potential_targets.insert(this); + Condition::ObjectSet matched_targets; + location->Eval(source, matched_targets, potential_targets); + if (!matched_targets.empty()) retval.push_back(focus_type.Name()); + } } } return retval; Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2010-07-21 08:51:05 UTC (rev 3692) +++ trunk/FreeOrion/universe/Universe.cpp 2010-07-21 17:10:25 UTC (rev 3693) @@ -628,7 +628,7 @@ effect_cause() {} -Universe::EffectTargetAndCause::EffectTargetAndCause(const Condition::ObjectSet& target_set_, const EffectCause& effect_cause_) : +Universe::EffectTargetAndCause::EffectTargetAndCause(const Effect::TargetSet& target_set_, const EffectCause& effect_cause_) : target_set(target_set_), effect_cause(effect_cause_) {} @@ -1341,7 +1341,7 @@ const std::vector<int>& target_objects, EffectsTargetsCausesMap& targets_causes_map) { // transfer target objects from input vector to a set - Condition::ObjectSet all_potential_targets; + Effect::TargetSet all_potential_targets; for (std::vector<int>::const_iterator it = target_objects.begin(); it != target_objects.end(); ++it) all_potential_targets.insert(m_objects.Object(*it)); @@ -1349,8 +1349,8 @@ std::vector<boost::shared_ptr<const Effect::EffectsGroup> >::const_iterator effects_it; for (effects_it = effects_groups.begin(); effects_it != effects_groups.end(); ++effects_it) { // create non_targets and targets sets for current effects group - Condition::ObjectSet target_set; // initially empty - Condition::ObjectSet potential_target_set = all_potential_targets; // copy again each iteration, so previous iterations don't affect starting potential targets of next iteration + Effect::TargetSet target_set; // initially empty + Effect::TargetSet potential_target_set = all_potential_targets; // copy again each iteration, so previous iterations don't affect starting potential targets of next iteration // get effects group to process for this iteration boost::shared_ptr<const Effect::EffectsGroup> effects_group = *effects_it; @@ -1380,7 +1380,7 @@ { m_marked_destroyed.clear(); m_marked_for_victory.clear(); - std::map<std::string, Condition::ObjectSet> executed_nonstacking_effects; + std::map<std::string, Effect::TargetSet> executed_nonstacking_effects; for (EffectsTargetsCausesMap::const_iterator targets_it = targets_causes_map.begin(); targets_it != targets_causes_map.end(); ++targets_it) { // if other EffectsGroups with the same stacking group have affected some of the targets in @@ -1390,11 +1390,11 @@ const boost::shared_ptr<const Effect::EffectsGroup> effects_group = sourced_effects_group.effects_group; const EffectTargetAndCause& targets_and_cause = targets_it->second; - Condition::ObjectSet targets = targets_and_cause.target_set; + Effect::TargetSet targets = targets_and_cause.target_set; std::map<std::string, std::set<UniverseObject*> >::iterator non_stacking_it = executed_nonstacking_effects.find(effects_group->StackingGroup()); if (non_stacking_it != executed_nonstacking_effects.end()) { - for (Condition::ObjectSet::const_iterator object_it = non_stacking_it->second.begin(); object_it != non_stacking_it->second.end(); ++object_it) { + for (Effect::TargetSet::const_iterator object_it = non_stacking_it->second.begin(); object_it != non_stacking_it->second.end(); ++object_it) { targets.erase(*object_it); } } @@ -1406,8 +1406,8 @@ // if this EffectsGroup belongs to a stacking group, add the objects just affected by it to executed_nonstacking_effects if (effects_group->StackingGroup() != "") { - Condition::ObjectSet& affected_targets = executed_nonstacking_effects[effects_group->StackingGroup()]; - for (Condition::ObjectSet::const_iterator object_it = targets.begin(); object_it != targets.end(); ++object_it) { + Effect::TargetSet& affected_targets = executed_nonstacking_effects[effects_group->StackingGroup()]; + for (Effect::TargetSet::const_iterator object_it = targets.begin(); object_it != targets.end(); ++object_it) { affected_targets.insert(*object_it); } } @@ -1421,7 +1421,7 @@ void Universe::ExecuteMeterEffects(const EffectsTargetsCausesMap& targets_causes_map) { //Logger().debugStream() << "Universe::ExecuteMeterEffects"; - std::map<std::string, Condition::ObjectSet> executed_nonstacking_effects; + std::map<std::string, Effect::TargetSet> executed_nonstacking_effects; for (EffectsTargetsCausesMap::const_iterator targets_it = targets_causes_map.begin(); targets_it != targets_causes_map.end(); ++targets_it) { // if other EffectsGroups with the same stacking group have affected some of the targets in @@ -1431,11 +1431,11 @@ const boost::shared_ptr<const Effect::EffectsGroup> effects_group = sourced_effects_group.effects_group; const EffectTargetAndCause& targets_and_cause = targets_it->second; - Condition::ObjectSet targets = targets_and_cause.target_set; + Effect::TargetSet targets = targets_and_cause.target_set; std::map<std::string, std::set<UniverseObject*> >::iterator non_stacking_it = executed_nonstacking_effects.find(effects_group->StackingGroup()); if (non_stacking_it != executed_nonstacking_effects.end()) { - for (Condition::ObjectSet::const_iterator object_it = non_stacking_it->second.begin(); object_it != non_stacking_it->second.end(); ++object_it) { + for (Effect::TargetSet::const_iterator object_it = non_stacking_it->second.begin(); object_it != non_stacking_it->second.end(); ++object_it) { targets.erase(*object_it); } } @@ -1455,7 +1455,7 @@ meter_type = meter_effect->GetMeterType(); // record pre-effect meter values - for (Condition::ObjectSet::iterator target_it = targets.begin(); target_it != targets.end(); ++target_it) { + for (Effect::TargetSet::iterator target_it = targets.begin(); target_it != targets.end(); ++target_it) { UniverseObject* target = *target_it; const Meter* meter = target->GetMeter(meter_type); if (!meter) continue; // some objects might match target conditions, but not actually have the relevant meter @@ -1477,7 +1477,7 @@ if (meter_effect) { // find change in meter due to effect: equal to post-meter minus pre-meter value - for (Condition::ObjectSet::iterator target_it = targets.begin(); target_it != targets.end(); ++target_it) { + for (Effect::TargetSet::iterator target_it = targets.begin(); target_it != targets.end(); ++target_it) { UniverseObject* target = *target_it; const Meter* meter = target->GetMeter(meter_type); if (!meter) continue; // some objects might match target conditions, but not actually have the relevant meter @@ -1494,8 +1494,8 @@ // if this EffectsGroup belongs to a stacking group, add the objects just affected by it to executed_nonstacking_effects if (effects_group->StackingGroup() != "") { - Condition::ObjectSet& affected_targets = executed_nonstacking_effects[effects_group->StackingGroup()]; - for (Condition::ObjectSet::const_iterator object_it = targets.begin(); object_it != targets.end(); ++object_it) + Effect::TargetSet& affected_targets = executed_nonstacking_effects[effects_group->StackingGroup()]; + for (Effect::TargetSet::const_iterator object_it = targets.begin(); object_it != targets.end(); ++object_it) affected_targets.insert(*object_it); } } Modified: trunk/FreeOrion/universe/Universe.h =================================================================== --- trunk/FreeOrion/universe/Universe.h 2010-07-21 08:51:05 UTC (rev 3692) +++ trunk/FreeOrion/universe/Universe.h 2010-07-21 17:10:25 UTC (rev 3693) @@ -33,10 +33,11 @@ class UniverseObject; class System; namespace Condition { - typedef std::set<UniverseObject*> ObjectSet; + typedef std::set<const UniverseObject*> ObjectSet; } namespace Effect { class EffectsGroup; + typedef std::set<UniverseObject*> TargetSet; } @@ -228,8 +229,8 @@ /** Combination of targets and cause for an effects group. */ struct EffectTargetAndCause { EffectTargetAndCause(); - EffectTargetAndCause(const Condition::ObjectSet& target_set_, const EffectCause& effect_cause_); - Condition::ObjectSet target_set; + EffectTargetAndCause(const Effect::TargetSet& target_set_, const EffectCause& effect_cause_); + Effect::TargetSet target_set; EffectCause effect_cause; }; /** Map from (effects group and source object) to target set of for |
From: <geo...@us...> - 2010-07-30 04:10:19
|
Revision: 3711 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3711&view=rev Author: geoffthemedio Date: 2010-07-30 04:10:13 +0000 (Fri, 30 Jul 2010) Log Message: ----------- -Reverted previous change, so that names list parameter is now not optional for building type condition, so that just "Building" isn't ambiguous between the building type condition with no types listed, and the ObjectType condition with building as a type, which is the other way the parser interprets that condition text. Modified Paths: -------------- trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/ConditionParser1.cpp Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2010-07-29 07:51:37 UTC (rev 3710) +++ trunk/FreeOrion/universe/Condition.cpp 2010-07-30 04:10:13 UTC (rev 3711) @@ -594,7 +594,7 @@ return universe_object_cast<const System*>(target); break; default: - break; + break; } return false; } Modified: trunk/FreeOrion/universe/ConditionParser1.cpp =================================================================== --- trunk/FreeOrion/universe/ConditionParser1.cpp 2010-07-29 07:51:37 UTC (rev 3710) +++ trunk/FreeOrion/universe/ConditionParser1.cpp 2010-07-30 04:10:13 UTC (rev 3711) @@ -170,7 +170,7 @@ building = str_p("building") - >> !(name_label >> string_ref_vector[building.names = arg1]) + >> (name_label >> string_ref_vector[building.names = arg1]) [building.this_ = new_<Condition::Building>(building.names)]; species = |
From: <geo...@us...> - 2010-08-21 19:20:04
|
Revision: 3747 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3747&view=rev Author: geoffthemedio Date: 2010-08-21 19:19:57 +0000 (Sat, 21 Aug 2010) Log Message: ----------- Added, untested, parsing for GenerateSitRepMessage effect, including a parser for a vector of string - valueref pairs, which will be used to specify the VarText parameters for the effect. Modified Paths: -------------- trunk/FreeOrion/universe/EffectParser.cpp trunk/FreeOrion/universe/TopLevelParsers.cpp Modified: trunk/FreeOrion/universe/EffectParser.cpp =================================================================== --- trunk/FreeOrion/universe/EffectParser.cpp 2010-08-21 08:12:21 UTC (rev 3746) +++ trunk/FreeOrion/universe/EffectParser.cpp 2010-08-21 19:19:57 UTC (rev 3747) @@ -144,54 +144,83 @@ member4 include_tech; }; - typedef rule<Scanner, SetMeterClosure::context_t> SetMeterRule; - typedef rule<Scanner, SetShipPartMeterClosure::context_t> SetShipPartMeterRule; - typedef rule<Scanner, SetOwnerStockpileClosure::context_t> SetOwnerStockpileRule; - typedef rule<Scanner, SetPlanetTypeClosure::context_t> SetPlanetTypeRule; - typedef rule<Scanner, SetPlanetSizeClosure::context_t> SetPlanetSizeRule; - typedef rule<Scanner, EmpireParamClosure::context_t> EmpireParamRule; - typedef rule<Scanner, NameParamClosure::context_t> NameParamRule; - typedef rule<Scanner, NameRefParamClosure::context_t> NameRefParamRule; - typedef rule<Scanner, ConditionParamClosure::context_t> ConditionParamRule; - typedef rule<Scanner, SetStarTypeClosure::context_t> SetStarTypeRule; - typedef rule<Scanner, CreatePlanetClosure::context_t> CreatePlanetRule; - typedef rule<Scanner, CreateBuildingClosure::context_t> CreateBuildingRule; - typedef rule<Scanner, CreateShipClosure::context_t> CreateShipRule; - typedef rule<Scanner, SetTechAvailabilityClosure::context_t> SetTechAvailabilityRule; + struct GenerateSitRepMessageClosure : boost::spirit::classic::closure<GenerateSitRepMessageClosure, Effect::EffectBase*, + std::string, + std::vector<std::pair<std::string, const ValueRef::ValueRefBase<std::string>*> >, + ValueRef::ValueRefBase<int>*> + { + member1 this_; + member2 template_string; + member3 parameters; + member4 recipient_empire; + }; - SetMeterRule set_meter; - SetShipPartMeterRule set_ship_part_meter; - SetOwnerStockpileRule set_owner_stockpile; - Rule set_owner_capitol; - SetPlanetTypeRule set_planet_type; - SetPlanetSizeRule set_planet_size; - NameRefParamRule set_species; - EmpireParamRule add_owner; - EmpireParamRule remove_owner; - CreatePlanetRule create_planet; - CreateBuildingRule create_building; - CreateShipRule create_ship; - ConditionParamRule move_to; - Rule destroy; - NameParamRule victory; - NameParamRule add_special; - NameParamRule remove_special; - SetStarTypeRule set_star_type; - SetTechAvailabilityRule set_tech_availability; + struct StringAndStringRefVectorClosure : boost::spirit::classic::closure<StringAndStringRefVectorClosure, + std::vector<std::pair<std::string, const ValueRef::ValueRefBase<std::string>*> >, + std::string, + const ValueRef::ValueRefBase<std::string>*> + { + member1 this_; + member2 tag; + member3 data; + }; - ParamLabel value_label; - ParamLabel type_label; - ParamLabel planetsize_label; - ParamLabel empire_label; - ParamLabel name_label; - ParamLabel species_label; - ParamLabel design_name_label; - ParamLabel part_name_label; - ParamLabel destination_label; - ParamLabel reason_label; - ParamLabel fighter_type_label; - ParamLabel slot_type_label; - ParamLabel part_class_label; + typedef rule<Scanner, SetMeterClosure::context_t> SetMeterRule; + typedef rule<Scanner, SetShipPartMeterClosure::context_t> SetShipPartMeterRule; + typedef rule<Scanner, SetOwnerStockpileClosure::context_t> SetOwnerStockpileRule; + typedef rule<Scanner, SetPlanetTypeClosure::context_t> SetPlanetTypeRule; + typedef rule<Scanner, SetPlanetSizeClosure::context_t> SetPlanetSizeRule; + typedef rule<Scanner, EmpireParamClosure::context_t> EmpireParamRule; + typedef rule<Scanner, NameParamClosure::context_t> NameParamRule; + typedef rule<Scanner, NameRefParamClosure::context_t> NameRefParamRule; + typedef rule<Scanner, ConditionParamClosure::context_t> ConditionParamRule; + typedef rule<Scanner, SetStarTypeClosure::context_t> SetStarTypeRule; + typedef rule<Scanner, CreatePlanetClosure::context_t> CreatePlanetRule; + typedef rule<Scanner, CreateBuildingClosure::context_t> CreateBuildingRule; + typedef rule<Scanner, CreateShipClosure::context_t> CreateShipRule; + typedef rule<Scanner, SetTechAvailabilityClosure::context_t> SetTechAvailabilityRule; + typedef rule<Scanner, GenerateSitRepMessageClosure::context_t> GenerateSitRepMessageRule; + typedef rule<Scanner, StringAndStringRefVectorClosure::context_t> StringAndStringRefVectorRule; + + SetMeterRule set_meter; + SetShipPartMeterRule set_ship_part_meter; + SetOwnerStockpileRule set_owner_stockpile; + Rule set_owner_capitol; + SetPlanetTypeRule set_planet_type; + SetPlanetSizeRule set_planet_size; + NameRefParamRule set_species; + EmpireParamRule add_owner; + EmpireParamRule remove_owner; + CreatePlanetRule create_planet; + CreateBuildingRule create_building; + CreateShipRule create_ship; + ConditionParamRule move_to; + Rule destroy; + NameParamRule victory; + NameParamRule add_special; + NameParamRule remove_special; + SetStarTypeRule set_star_type; + SetTechAvailabilityRule set_tech_availability; + GenerateSitRepMessageRule generate_sitrep_message; + StringAndStringRefVectorRule string_and_string_ref_vector; + + ParamLabel value_label; + ParamLabel type_label; + ParamLabel planetsize_label; + ParamLabel empire_label; + ParamLabel name_label; + ParamLabel species_label; + ParamLabel design_name_label; + ParamLabel part_name_label; + ParamLabel destination_label; + ParamLabel reason_label; + ParamLabel fighter_type_label; + ParamLabel slot_type_label; + ParamLabel part_class_label; + ParamLabel message_label; + ParamLabel parameters_label; + ParamLabel tag_label; + ParamLabel data_label; }; EffectParserDefinition::EffectParserDefinition() : @@ -207,7 +236,11 @@ reason_label("reason"), fighter_type_label("fightertype"), slot_type_label("slottype"), - part_class_label("partclass") + part_class_label("partclass"), + message_label("message"), + parameters_label("parameters"), + tag_label("tag"), + data_label("data") { set_meter = (str_p("set") @@ -340,12 +373,16 @@ >> design_name_label >> name_p[create_ship.predefined_design_name = arg1] >> empire_label >> int_expr_p[create_ship.empire = arg1] >> species_label >> string_expr_p[create_ship.species = arg1]) - [create_ship.this_ = new_<Effect::CreateShip>(create_ship.predefined_design_name, create_ship.empire, create_ship.species)]) + [create_ship.this_ = new_<Effect::CreateShip>(create_ship.predefined_design_name, + create_ship.empire, + create_ship.species)]) | ((str_p("createship") >> design_name_label >> int_expr_p[create_ship.design_id = arg1] >> empire_label >> int_expr_p[create_ship.empire = arg1] >> species_label >> string_expr_p[create_ship.species = arg1]) - [create_ship.this_ = new_<Effect::CreateShip>(create_ship.design_id, create_ship.empire, create_ship.species)]) + [create_ship.this_ = new_<Effect::CreateShip>(create_ship.design_id, + create_ship.empire, + create_ship.species)]) ); move_to = @@ -383,8 +420,38 @@ | str_p("unlocktechitemsforowner")[set_tech_availability.available = val(true), set_tech_availability.include_tech = val(false)] | str_p("locktechitemsforowner")[set_tech_availability.available = val(false), set_tech_availability.include_tech = val(false)]) >> name_label >> name_p[set_tech_availability.name = arg1]) - [set_tech_availability.this_ = new_<Effect::SetTechAvailability>(set_tech_availability.name, new_<ValueRef::Variable<int> >(false, "Owner"), set_tech_availability.available, set_tech_availability.include_tech)]; + [set_tech_availability.this_ = new_<Effect::SetTechAvailability>( + set_tech_availability.name, + new_<ValueRef::Variable<int> >(false, "Owner"), + set_tech_availability.available, + set_tech_availability.include_tech) + ]; + // not an effect parser, but a utility function for parsing a list of string-ValueRef<string> pairs + string_and_string_ref_vector = + (tag_label >> name_p[string_and_string_ref_vector.tag = arg1] + >> data_label >> string_expr_p[string_and_string_ref_vector.data = arg1]) + [push_back_(string_and_string_ref_vector.this_, + make_pair_(string_and_string_ref_vector.tag, + string_and_string_ref_vector.data))] + | ('[' >> +((tag_label >> name_p[string_and_string_ref_vector.tag = arg1] + >> data_label >> string_expr_p[string_and_string_ref_vector.data = arg1]) + [push_back_(string_and_string_ref_vector.this_, + make_pair_(string_and_string_ref_vector.tag, + string_and_string_ref_vector.data))]) + >> ']'); + + generate_sitrep_message = + (str_p("generatesitrepmessage") + >> message_label >> name_p[generate_sitrep_message.template_string = arg1] + >> parameters_label >> string_and_string_ref_vector[generate_sitrep_message.parameters = arg1] + >> empire_label >> int_expr_p[generate_sitrep_message.recipient_empire = arg1]) + [generate_sitrep_message.this_ = new_<Effect::GenerateSitRepMessage>( + generate_sitrep_message.template_string, + generate_sitrep_message.parameters, + generate_sitrep_message.recipient_empire) + ]; + effect_p = set_meter[effect_p.this_ = arg1] | set_ship_part_meter[effect_p.this_ = arg1] @@ -404,7 +471,8 @@ | add_special[effect_p.this_ = arg1] | remove_special[effect_p.this_ = arg1] | set_star_type[effect_p.this_ = arg1] - | set_tech_availability[effect_p.this_ = arg1]; + | set_tech_availability[effect_p.this_ = arg1] + | generate_sitrep_message[effect_p.this_ = arg1]; } EffectParserDefinition effect_parser_def; } Modified: trunk/FreeOrion/universe/TopLevelParsers.cpp =================================================================== --- trunk/FreeOrion/universe/TopLevelParsers.cpp 2010-08-21 08:12:21 UTC (rev 3746) +++ trunk/FreeOrion/universe/TopLevelParsers.cpp 2010-08-21 19:19:57 UTC (rev 3747) @@ -212,7 +212,7 @@ [insert_(planet_type_environment_map_p.this_, make_pair_(planet_type_environment_map_p.type, planet_type_environment_map_p.env))]) - >> ']'); + >> ']'); species_p = (str_p("species") |
From: <geo...@us...> - 2010-08-21 20:23:17
|
Revision: 3748 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3748&view=rev Author: geoffthemedio Date: 2010-08-21 20:23:10 +0000 (Sat, 21 Aug 2010) Log Message: ----------- Modified GenerateSitRepMessage effect parsing to allow specifying no parameters in a list. Previous version required one or more parameters to be specified to parse. Modified Paths: -------------- trunk/FreeOrion/universe/EffectParser.cpp trunk/FreeOrion/universe/ValueRef.cpp Modified: trunk/FreeOrion/universe/EffectParser.cpp =================================================================== --- trunk/FreeOrion/universe/EffectParser.cpp 2010-08-21 19:19:57 UTC (rev 3747) +++ trunk/FreeOrion/universe/EffectParser.cpp 2010-08-21 20:23:10 UTC (rev 3748) @@ -434,7 +434,7 @@ [push_back_(string_and_string_ref_vector.this_, make_pair_(string_and_string_ref_vector.tag, string_and_string_ref_vector.data))] - | ('[' >> +((tag_label >> name_p[string_and_string_ref_vector.tag = arg1] + | ('[' >> !((tag_label >> name_p[string_and_string_ref_vector.tag = arg1] >> data_label >> string_expr_p[string_and_string_ref_vector.data = arg1]) [push_back_(string_and_string_ref_vector.this_, make_pair_(string_and_string_ref_vector.tag, Modified: trunk/FreeOrion/universe/ValueRef.cpp =================================================================== --- trunk/FreeOrion/universe/ValueRef.cpp 2010-08-21 19:19:57 UTC (rev 3747) +++ trunk/FreeOrion/universe/ValueRef.cpp 2010-08-21 20:23:10 UTC (rev 3748) @@ -482,7 +482,7 @@ template <> std::string Variable<std::string>::Eval(const UniverseObject* source, const UniverseObject* target, - const boost::any& current_value) const + const boost::any& current_value) const { std::string retval; const UniverseObject* object = FollowReference(m_property_name.begin(), m_property_name.end(), m_source_ref ? source : target); |
From: <geo...@us...> - 2010-08-30 16:26:20
|
Revision: 3781 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3781&view=rev Author: geoffthemedio Date: 2010-08-30 16:26:14 +0000 (Mon, 30 Aug 2010) Log Message: ----------- Added Universe::GenericShipDesign function that searches the ship designs for a design created by no empire with the requested name, and removed PredefinedShipDesignManager::GenericUniverseDesignID. The reason for this change is that the designs / ids map in PredefinedShipDesignManager was being set during universe creation, but not saved or restored with saving or loading games, so looking up design names' generic IDs wouldn't work in loaded games. Now the Universe::GenericShipDesign function scans through the designs in the Universe and tries to find one with the requested name that wasn't created by any empire. This seems to be working, and seems to fix the CreateShip effect which previously wasn't working for me when loading games, due to not finding the requested generic ship design. Modified Paths: -------------- trunk/FreeOrion/universe/ShipDesign.cpp trunk/FreeOrion/universe/ShipDesign.h trunk/FreeOrion/universe/Universe.cpp trunk/FreeOrion/universe/Universe.h Modified: trunk/FreeOrion/universe/ShipDesign.cpp =================================================================== --- trunk/FreeOrion/universe/ShipDesign.cpp 2010-08-30 07:50:14 UTC (rev 3780) +++ trunk/FreeOrion/universe/ShipDesign.cpp 2010-08-30 16:26:14 UTC (rev 3781) @@ -1394,14 +1394,6 @@ delete it->second; } -int PredefinedShipDesignManager::GenericUniverseDesignID(const std::string& name) const { - std::map<std::string, int>::const_iterator it = m_design_generic_ids.find(name); - if (it == m_design_generic_ids.end()) - return ShipDesign::INVALID_DESIGN_ID; - else - return it->second; -} - std::map<std::string, int> PredefinedShipDesignManager::AddShipDesignsToEmpire(Empire* empire) const { std::map<std::string, int> retval; @@ -1531,6 +1523,5 @@ } const ShipDesign* GetPredefinedShipDesign(const std::string& name) { - int universe_generic_design_id = GetPredefinedShipDesignManager().GenericUniverseDesignID(name); // gets id under which the premade ship design of the indicated name was stored generically in the universe. that is, the id under which the design was stored with no empire creator - return GetUniverse().GetShipDesign(universe_generic_design_id); // may return 0 + return GetUniverse().GetGenericShipDesign(name); // may return 0 } Modified: trunk/FreeOrion/universe/ShipDesign.h =================================================================== --- trunk/FreeOrion/universe/ShipDesign.h 2010-08-30 07:50:14 UTC (rev 3780) +++ trunk/FreeOrion/universe/ShipDesign.h 2010-08-30 16:26:14 UTC (rev 3781) @@ -540,15 +540,6 @@ /** Returns iterator pointing one past last ship design. */ iterator end() const; - - /** Returns ship design id in the universe under which the premade ship - * design with the indicated name was stored without an empire creator. - * Most designs have an empire that created them, including designs added - * to empires with AddShipDesignsToEmpire(), but designs added to the - * universe with AddShipDesignsToUniverse() don't have an empire creator - * set, and aren't tracked in an Empire object, so to get those generic - * creatorless designs, this function can be used. */ - int GenericUniverseDesignID(const std::string& name) const; //@} /** Adds designs in this manager to the specified \a empire using that Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2010-08-30 07:50:14 UTC (rev 3780) +++ trunk/FreeOrion/universe/Universe.cpp 2010-08-30 16:26:14 UTC (rev 3781) @@ -785,6 +785,20 @@ return (it != m_ship_designs.end() ? it->second : 0); } +const ShipDesign* Universe::GetGenericShipDesign(const std::string& name) const +{ + if (name.empty()) + return 0; + for (ship_design_iterator it = m_ship_designs.begin(); it != m_ship_designs.end(); ++it) { + const ShipDesign* design = it->second; + const std::string& design_name = design->Name(false); + int designed_by_empire_id = design->DesignedByEmpire(); + if (name == design_name && designed_by_empire_id == ALL_EMPIRES) + return design; + } + return 0; +} + const std::set<int>& Universe::EmpireKnownShipDesignIDs(int empire_id) const { std::map<int, std::set<int> >::const_iterator it = m_empire_known_ship_design_ids.find(empire_id); Modified: trunk/FreeOrion/universe/Universe.h =================================================================== --- trunk/FreeOrion/universe/Universe.h 2010-08-30 07:50:14 UTC (rev 3780) +++ trunk/FreeOrion/universe/Universe.h 2010-08-30 16:26:14 UTC (rev 3781) @@ -298,6 +298,8 @@ ship_design_iterator beginShipDesigns() const {return m_ship_designs.begin();} ///< returns the begin iterator for ship designs ship_design_iterator endShipDesigns() const {return m_ship_designs.end();} ///< returns the end iterator for ship designs + const ShipDesign* GetGenericShipDesign(const std::string& name) const; + /** Returns IDs of ship designs that the Empire with id \a empire_id has * seen during the game. If \a empire_id = ALL_EMPIRES an empty set of * ids is returned */ |
From: <geo...@us...> - 2010-09-01 00:22:57
|
Revision: 3787 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3787&view=rev Author: geoffthemedio Date: 2010-09-01 00:22:50 +0000 (Wed, 01 Sep 2010) Log Message: ----------- Added skeleton, but not parsing or implementation for SupplyLineConnected condition. Modified Paths: -------------- trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/Condition.h Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2010-08-31 22:32:06 UTC (rev 3786) +++ trunk/FreeOrion/universe/Condition.cpp 2010-09-01 00:22:50 UTC (rev 3787) @@ -1949,6 +1949,47 @@ } /////////////////////////////////////////////////////////// +// SupplyLineConnected // +/////////////////////////////////////////////////////////// +Condition::SupplyLineConnected::SupplyLineConnected(const ValueRef::ValueRefBase<int>* lane_owner, + const ValueRef::ValueRefBase<int>* max_jumps, + const ConditionBase* from_object_condition, + bool use_fleet_supply_lines, + bool use_resource_supply_lines) : + m_lane_owner(lane_owner), + m_max_jumps(max_jumps), + m_from_object_condition(from_object_condition), + m_use_fleet_supply_lines(use_fleet_supply_lines), + m_use_resource_supply_lines(use_resource_supply_lines) +{} + +Condition::SupplyLineConnected::~SupplyLineConnected() +{ + delete m_lane_owner; + delete m_max_jumps; + delete m_from_object_condition; +} + +void Condition::SupplyLineConnected::Eval(const UniverseObject* source, Condition::ObjectSet& targets, Condition::ObjectSet& non_targets, SearchDomain search_domain/* = NON_TARGETS*/) const +{ +} + +std::string Condition::SupplyLineConnected::Description(bool negated/* = false*/) const +{ + return ""; +} + +std::string Condition::SupplyLineConnected::Dump() const +{ + return ""; +} + +bool Condition::SupplyLineConnected::Match(const UniverseObject* source, const UniverseObject* target) const +{ + return false; +} + +/////////////////////////////////////////////////////////// // And // /////////////////////////////////////////////////////////// Condition::And::And(const std::vector<const ConditionBase*>& operands) : Modified: trunk/FreeOrion/universe/Condition.h =================================================================== --- trunk/FreeOrion/universe/Condition.h 2010-08-31 22:32:06 UTC (rev 3786) +++ trunk/FreeOrion/universe/Condition.h 2010-09-01 00:22:50 UTC (rev 3787) @@ -46,6 +46,7 @@ struct WithinStarlaneJumps; struct ExploredByEmpire; struct Stationary; + struct SupplyLineConnected; struct And; struct Or; struct Not; @@ -556,9 +557,10 @@ void serialize(Archive& ar, const unsigned int version); }; -/** Matches all objects that are within \a distance units of at least one object that meets \a condition. - Warning: this Condition can slow things down considerably if overused. It is best to use Conditions - that yield relatively few matches. */ +/** Matches all objects that are within \a distance units of at least one + * object that meets \a condition. Warning: this Condition can slow things + * down considerably if overused. It is best to use Conditions that yield + * relatively few matches. */ struct Condition::WithinDistance : Condition::ConditionBase { WithinDistance(const ValueRef::ValueRefBase<double>* distance, const ConditionBase* condition); @@ -578,9 +580,10 @@ void serialize(Archive& ar, const unsigned int version); }; -/** Matches all objects that are within \a jumps starlane jumps of at least one object that meets \a condition. - Warning: this Condition can slow things down considerably if overused. It is best to use Conditions - that yield relatively few matches. */ +/** Matches all objects that are within \a jumps starlane jumps of at least one + * object that meets \a condition. Warning: this Condition can slow things + * down considerably if overused. It is best to use Conditions that yield + * relatively few matches. */ struct Condition::WithinStarlaneJumps : Condition::ConditionBase { WithinStarlaneJumps(const ValueRef::ValueRefBase<int>* jumps, const ConditionBase* condition); @@ -634,6 +637,35 @@ void serialize(Archive& ar, const unsigned int version); }; +/** Matches objects that are connected by starlanes up to \a max_jumps starlane + * traversals to any object that matches \a from_object_condition using only + * starlanes that are resource or ship supply passable for empire \a lane_owner */ +struct Condition::SupplyLineConnected : Condition::ConditionBase +{ + SupplyLineConnected(const ValueRef::ValueRefBase<int>* lane_owner, + const ValueRef::ValueRefBase<int>* max_jumps, + const ConditionBase* from_object_condition, + bool use_fleet_supply_lines, + bool use_resource_supply_lines); + virtual ~SupplyLineConnected(); + virtual void Eval(const UniverseObject* source, Condition::ObjectSet& targets, Condition::ObjectSet& non_targets, SearchDomain search_domain = NON_TARGETS) const; + virtual std::string Description(bool negated = false) const; + virtual std::string Dump() const; + +private: + virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; + + const ValueRef::ValueRefBase<int>* m_lane_owner; + const ValueRef::ValueRefBase<int>* m_max_jumps; + const ConditionBase* m_from_object_condition; + bool m_use_fleet_supply_lines; + bool m_use_resource_supply_lines; + + friend class boost::serialization::access; + template <class Archive> + void serialize(Archive& ar, const unsigned int version); +}; + /** Matches all objects that match every Condition in \a operands. */ struct Condition::And : Condition::ConditionBase { @@ -910,6 +942,17 @@ } template <class Archive> +void Condition::SupplyLineConnected::serialize(Archive& ar, const unsigned int version) +{ + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(ConditionBase) + & BOOST_SERIALIZATION_NVP(m_lane_owner) + & BOOST_SERIALIZATION_NVP(m_max_jumps) + & BOOST_SERIALIZATION_NVP(m_from_object_condition) + & BOOST_SERIALIZATION_NVP(m_use_fleet_supply_lines) + & BOOST_SERIALIZATION_NVP(m_use_resource_supply_lines); +} + +template <class Archive> void Condition::And::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(ConditionBase) |
From: <geo...@us...> - 2010-09-27 01:00:05
|
Revision: 3802 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3802&view=rev Author: geoffthemedio Date: 2010-09-27 00:59:59 +0000 (Mon, 27 Sep 2010) Log Message: ----------- Fixed (anticipated but not observed) issue with WithinDistance, WithinStarlaneJumps and ResourceSupplyConnectedByEmpire conditions, which were using the objects that matched their sub-conditions as the source object when evaluating parameter references for the distance, number of starlane jumps or empire ID. This could lead to conditions where Source.SomeMeterValue would be the meter value of the object that matched the sub-condition, rather than the actual source object. Fix ivolved added a new Match function overload that takes 3 parameters instead of reusing the 2-parameter override where the condition-matching object was passed as the "source" object. Modified Paths: -------------- trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/Condition.h Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2010-09-27 00:32:07 UTC (rev 3801) +++ trunk/FreeOrion/universe/Condition.cpp 2010-09-27 00:59:59 UTC (rev 3802) @@ -1654,7 +1654,7 @@ // see if current object is within required distance of any condition target for (ObjectSet::iterator condition_targets_it = condition_targets.begin(); condition_targets_it != condition_targets.end(); ++condition_targets_it) { - if (Match(non_target_obj, *condition_targets_it)) { + if (Match(source, non_target_obj, *condition_targets_it)) { // current object is within required distance of current condition target. // transfer current object to targets set targets.insert(non_target_obj); @@ -1681,7 +1681,7 @@ // see if current object is within required distance of any condition target for (ObjectSet::iterator condition_targets_it = condition_targets.begin(); condition_targets_it != condition_targets.end(); ++condition_targets_it) { - if (Match(initial_target_obj, *condition_targets_it)) { + if (Match(source, initial_target_obj, *condition_targets_it)) { // current object is within required distance of current condition target. // transfer current object to back to targets set targets.insert(initial_target_obj); @@ -1718,12 +1718,12 @@ return retval; } -bool Condition::WithinDistance::Match(const UniverseObject* source, const UniverseObject* target) const +bool Condition::WithinDistance::Match(const UniverseObject* source, const UniverseObject* condition_match, const UniverseObject* target) const { double dist = m_distance->Eval(source, target, boost::any()); double distance_squared = dist * dist; - double delta_x = source->X() - target->X(); - double delta_y = source->Y() - target->Y(); + double delta_x = condition_match->X() - target->X(); + double delta_y = condition_match->Y() - target->Y(); return (delta_x * delta_x + delta_y * delta_y) <= distance_squared; } @@ -1774,7 +1774,7 @@ ObjectSet::iterator end_it2 = from_set.end(); for ( ; it2 != end_it2; ) { ObjectSet::iterator temp = it2++; - if (search_domain == TARGETS ? !Match(*it, *temp) : Match(*it, *temp)) { + if (search_domain == TARGETS ? !Match(source, *it, *temp) : Match(source, *it, *temp)) { to_set.insert(*temp); from_set.erase(temp); } @@ -1802,64 +1802,64 @@ return retval; } -bool Condition::WithinStarlaneJumps::Match(const UniverseObject* source, const UniverseObject* target) const +bool Condition::WithinStarlaneJumps::Match(const UniverseObject* source, const UniverseObject* condition_match, const UniverseObject* target) const { const ObjectMap& objects = GetMainObjectMap(); int jump_limit = m_jumps->Eval(source, target, boost::any()); if (jump_limit == 0) { // special case, since LeastJumpsPath() doesn't expect the start point to be the end point - double delta_x = source->X() - target->X(); - double delta_y = source->Y() - target->Y(); + double delta_x = condition_match->X() - target->X(); + double delta_y = condition_match->Y() - target->Y(); return !(delta_x * delta_x + delta_y * delta_y); } else { - const System* source_system = objects.Object<System>(source->SystemID()); - if (!source_system) - source_system = universe_object_cast<const System*>(source); + const System* condition_match_system = objects.Object<System>(condition_match->SystemID()); + if (!condition_match_system) + condition_match_system = universe_object_cast<const System*>(condition_match); const System* target_system = objects.Object<System>(target->SystemID()); if (!target_system) target_system = universe_object_cast<const System*>(target); - // need various special cases for whether the source and or target - // objects are or are in systems. - if (source_system && target_system) { - // both source and target are / in systems. can just find the - // shortest path between the two systems - std::pair<std::list<int>, double> path = GetUniverse().LeastJumpsPath(source_system->ID(), target_system->ID()); + // need various special cases for whether the condition-matching object + // and target objects are or are in systems. + if (condition_match_system && target_system) { + // both condition-matching object and target are / in systems. + // can just find the shortest path between the two systems + std::pair<std::list<int>, double> path = GetUniverse().LeastJumpsPath(condition_match_system->ID(), target_system->ID()); if (!path.first.empty()) { // if path.first is empty, no path exists between the systems return (static_cast<int>(path.first.size()) - 1) <= jump_limit; } - } else if (source_system) { - // just source is / in a system. need to check shortest path from + } else if (condition_match_system) { + // just condition-matching object is / in a system. need to check shortest path from // systems on either side of starlane target is on if (const Fleet* target_fleet = FleetFromObject(target)) { - std::pair<std::list<int>, double> path1 = GetUniverse().LeastJumpsPath(source_system->ID(), target_fleet->PreviousSystemID()); - std::pair<std::list<int>, double> path2 = GetUniverse().LeastJumpsPath(source_system->ID(), target_fleet->NextSystemID()); + std::pair<std::list<int>, double> path1 = GetUniverse().LeastJumpsPath(condition_match_system->ID(), target_fleet->PreviousSystemID()); + std::pair<std::list<int>, double> path2 = GetUniverse().LeastJumpsPath(condition_match_system->ID(), target_fleet->NextSystemID()); if (int jumps = static_cast<int>(std::max(path1.first.size(), path2.first.size())) - 1) return jumps <= jump_limit; } } else if (target_system) { // just target is / in a system. need to check shortest path from - // systems on either side of starlane source is on - if (const Fleet* source_fleet = FleetFromObject(source)) { - std::pair<std::list<int>, double> path1 = GetUniverse().LeastJumpsPath(source_fleet->PreviousSystemID(), target_system->ID()); - std::pair<std::list<int>, double> path2 = GetUniverse().LeastJumpsPath(source_fleet->NextSystemID(), target_system->ID()); + // systems on either side of starlane the condition-matching object is on + if (const Fleet* condition_matching_fleet = FleetFromObject(condition_match)) { + std::pair<std::list<int>, double> path1 = GetUniverse().LeastJumpsPath(condition_matching_fleet->PreviousSystemID(), target_system->ID()); + std::pair<std::list<int>, double> path2 = GetUniverse().LeastJumpsPath(condition_matching_fleet->NextSystemID(), target_system->ID()); if (int jumps = static_cast<int>(std::max(path1.first.size(), path2.first.size()))) return jumps - 1 <= jump_limit; } } else { - // neither source nor target are / in systems. need to check all - // combinations of systems on either sides of starlanes source and - // target are on - const Fleet* source_fleet = FleetFromObject(source); + // neither condition-matching object nor target are / in systems. + // need to check all combinations of systems on either sides of + // starlanes condition-matching object and target are on + const Fleet* condition_matching_fleet = FleetFromObject(condition_match); const Fleet* target_fleet = FleetFromObject(target); - if (source_fleet && target_fleet) { - int source_fleet_prev_system_id = source_fleet->PreviousSystemID(); - int source_fleet_next_system_id = source_fleet->NextSystemID(); + if (condition_matching_fleet && target_fleet) { + int condition_matching_fleet_prev_system_id = condition_matching_fleet->PreviousSystemID(); + int condition_matching_fleet_next_system_id = condition_matching_fleet->NextSystemID(); int target_fleet_prev_system_id = target_fleet->PreviousSystemID(); int target_fleet_next_system_id = target_fleet->NextSystemID(); - std::pair<std::list<int>, int> path1 = GetUniverse().LeastJumpsPath(source_fleet_prev_system_id, target_fleet_prev_system_id); - std::pair<std::list<int>, int> path2 = GetUniverse().LeastJumpsPath(source_fleet_prev_system_id, target_fleet_next_system_id); - std::pair<std::list<int>, int> path3 = GetUniverse().LeastJumpsPath(source_fleet_next_system_id, target_fleet_prev_system_id); - std::pair<std::list<int>, int> path4 = GetUniverse().LeastJumpsPath(source_fleet_next_system_id, target_fleet_next_system_id); + std::pair<std::list<int>, int> path1 = GetUniverse().LeastJumpsPath(condition_matching_fleet_prev_system_id, target_fleet_prev_system_id); + std::pair<std::list<int>, int> path2 = GetUniverse().LeastJumpsPath(condition_matching_fleet_prev_system_id, target_fleet_next_system_id); + std::pair<std::list<int>, int> path3 = GetUniverse().LeastJumpsPath(condition_matching_fleet_next_system_id, target_fleet_prev_system_id); + std::pair<std::list<int>, int> path4 = GetUniverse().LeastJumpsPath(condition_matching_fleet_next_system_id, target_fleet_next_system_id); if (int jumps = static_cast<int>(std::max(std::max(path1.second, path2.second), std::max(path3.second, path4.second)))) return jumps - 1 <= jump_limit; @@ -2069,7 +2069,7 @@ ObjectSet::iterator end_it2 = from_set.end(); for ( ; it2 != end_it2; ) { ObjectSet::iterator temp = it2++; - if (search_domain == TARGETS ? !Match(*it, *temp) : Match(*it, *temp)) { + if (search_domain == TARGETS ? !Match(source, *it, *temp) : Match(source, *it, *temp)) { to_set.insert(*temp); from_set.erase(temp); } @@ -2100,11 +2100,9 @@ return retval; } -bool Condition::ResourceSupplyConnectedByEmpire::Match(const UniverseObject* source, const UniverseObject* target) const +bool Condition::ResourceSupplyConnectedByEmpire::Match(const UniverseObject* source, const UniverseObject* condition_match, const UniverseObject* target) const { - // parameter source is an object that matched m_condition - - if (!source || !target) + if (!source || !target || !condition_match) return false; const EmpireManager& empires = Empires(); @@ -2113,8 +2111,8 @@ const std::set<std::set<int> >& groups = empire->ResourceSupplyGroups(); for (std::set<std::set<int> >::const_iterator groups_it = groups.begin(); groups_it != groups.end(); ++groups_it) { const std::set<int>& group = *groups_it; - if (group.find(source->SystemID()) != group.end()) { - // found resource sharing group containing source. Does it also contain target? + if (group.find(condition_match->SystemID()) != group.end()) { + // found resource sharing group containing condition-matching object. Does it also contain target? if (group.find(target->SystemID()) != group.end()) return true; // object matching m_condition and target object are in same resourse sharing group else Modified: trunk/FreeOrion/universe/Condition.h =================================================================== --- trunk/FreeOrion/universe/Condition.h 2010-09-27 00:32:07 UTC (rev 3801) +++ trunk/FreeOrion/universe/Condition.h 2010-09-27 00:59:59 UTC (rev 3802) @@ -571,7 +571,7 @@ virtual std::string Dump() const; private: - virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; + bool Match(const UniverseObject* source, const UniverseObject* condition_match, const UniverseObject* target) const; const ValueRef::ValueRefBase<double>* m_distance; const ConditionBase* m_condition; @@ -594,7 +594,7 @@ virtual std::string Dump() const; private: - virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; + bool Match(const UniverseObject* source, const UniverseObject* condition_match, const UniverseObject* target) const; const ValueRef::ValueRefBase<int>* m_jumps; const ConditionBase* m_condition; @@ -670,7 +670,7 @@ virtual std::string Dump() const; private: - virtual bool Match(const UniverseObject* source, const UniverseObject* target) const; + bool Match(const UniverseObject* source, const UniverseObject* condition_match, const UniverseObject* target) const; const ValueRef::ValueRefBase<int>* m_empire_id; const ConditionBase* m_condition; |
From: <geo...@us...> - 2010-10-11 09:53:29
|
Revision: 3813 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3813&view=rev Author: geoffthemedio Date: 2010-10-11 09:53:23 +0000 (Mon, 11 Oct 2010) Log Message: ----------- Added parsing for DesignHasPartClass condition. Modified Paths: -------------- trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/ConditionParser1.cpp trunk/FreeOrion/universe/ConditionParser2.cpp Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2010-10-11 08:42:33 UTC (rev 3812) +++ trunk/FreeOrion/universe/Condition.cpp 2010-10-11 09:53:23 UTC (rev 3813) @@ -1349,7 +1349,7 @@ } std::string Condition::DesignHasPartClass::Dump() const{ - return DumpIndent() + "DesignHasPartClass low = " + m_low->Dump() + "Number high = " + m_high->Dump() + " part_class = " + UserString(boost::lexical_cast<std::string>(m_class)); + return DumpIndent() + "DesignHasPartClass low = " + m_low->Dump() + "Number high = " + m_high->Dump() + " class = " + UserString(boost::lexical_cast<std::string>(m_class)); } bool Condition::DesignHasPartClass::Match(const UniverseObject* source, const UniverseObject* target) const Modified: trunk/FreeOrion/universe/ConditionParser1.cpp =================================================================== --- trunk/FreeOrion/universe/ConditionParser1.cpp 2010-10-11 08:42:33 UTC (rev 3812) +++ trunk/FreeOrion/universe/ConditionParser1.cpp 2010-10-11 09:53:23 UTC (rev 3813) @@ -15,6 +15,7 @@ ParamLabel affiliation_label("affiliation"); ParamLabel name_label("name"); ParamLabel type_label("type"); +ParamLabel class_label("class"); ParamLabel planetsize_label("size"); ParamLabel environment_label("environment"); ParamLabel probability_label("probability"); Modified: trunk/FreeOrion/universe/ConditionParser2.cpp =================================================================== --- trunk/FreeOrion/universe/ConditionParser2.cpp 2010-10-11 08:42:33 UTC (rev 3812) +++ trunk/FreeOrion/universe/ConditionParser2.cpp 2010-10-11 09:53:23 UTC (rev 3813) @@ -15,6 +15,7 @@ extern ParamLabel affiliation_label; extern ParamLabel name_label; extern ParamLabel type_label; +extern ParamLabel class_label; extern ParamLabel planetsize_label; extern ParamLabel environment_label; extern ParamLabel probability_label; @@ -94,6 +95,14 @@ member4 name; }; + struct DesignHasPartClassClosure : boost::spirit::classic::closure<DesignHasPartClassClosure, Condition::ConditionBase*, ValueRef::ValueRefBase<int>*, ValueRef::ValueRefBase<int>*, ShipPartClass> + { + member1 this_; + member2 int_ref_1; + member3 int_ref_2; + member4 part_class; + }; + struct DoubleRefClosure : boost::spirit::classic::closure<DoubleRefClosure, Condition::ConditionBase*, ValueRef::ValueRefBase<double>*> { member1 this_; @@ -129,6 +138,7 @@ typedef rule<Scanner, ConditionParamClosure::context_t> ConditionParamRule; typedef rule<Scanner, StarTypeClosure::context_t> StarTypeRule; typedef rule<Scanner, DesignHasPartClosure::context_t> DesignHasPartRule; + typedef rule<Scanner, DesignHasPartClassClosure::context_t> DesignHasPartClassRule; typedef rule<Scanner, DoubleRefClosure::context_t> DoubleRefRule; typedef rule<Scanner, StockpileClosure::context_t> StockpileRule; typedef rule<Scanner, IntRefVecClosure::context_t> IntRefVecRule; @@ -146,6 +156,7 @@ StarTypeRule star_type; StringRule design_has_hull; DesignHasPartRule design_has_part; + DesignHasPartClassRule design_has_part_class; DoubleRefRule random; StockpileRule owner_stockpile; IntRefVecRule visible_to_empire; @@ -221,11 +232,22 @@ design_has_part = (str_p("designhaspart") - >> low_label >> int_expr_p[design_has_part.int_ref_2 = arg1] - >> high_label >> int_expr_p[design_has_part.int_ref_1 = arg1] - >> name_label >> name_p[design_has_part.name = arg1]) - [design_has_part.this_ = new_<Condition::DesignHasPart>(design_has_part.int_ref_2, design_has_part.int_ref_1, design_has_part.name)]; + >> low_label >> int_expr_p[ design_has_part.int_ref_2 = arg1] + >> high_label >> int_expr_p[ design_has_part.int_ref_1 = arg1] + >> name_label >> name_p[ design_has_part.name = arg1]) + [design_has_part.this_ = new_<Condition::DesignHasPart>(design_has_part.int_ref_2, + design_has_part.int_ref_1, + design_has_part.name)]; + design_has_part_class = + (str_p("designhaspartclass") + >> low_label >> int_expr_p[ design_has_part_class.int_ref_2 = arg1] + >> high_label >> int_expr_p[ design_has_part_class.int_ref_1 = arg1] + >> class_label >> part_class_p[ design_has_part_class.part_class = arg1]) + [design_has_part_class.this_ = new_<Condition::DesignHasPartClass>(design_has_part_class.int_ref_2, + design_has_part_class.int_ref_1, + design_has_part_class.part_class)]; + random = (str_p("random") >> probability_label @@ -276,6 +298,7 @@ | star_type[condition2_p.this_ = arg1] | design_has_hull[condition2_p.this_ = arg1] | design_has_part[condition2_p.this_ = arg1] + | design_has_part_class[condition2_p.this_ = arg1] | random[condition2_p.this_ = arg1] | owner_stockpile[condition2_p.this_ = arg1] | visible_to_empire[condition2_p.this_ = arg1] |
From: <geo...@us...> - 2010-10-12 10:21:27
|
Revision: 3817 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3817&view=rev Author: geoffthemedio Date: 2010-10-12 10:21:20 +0000 (Tue, 12 Oct 2010) Log Message: ----------- -Added (untested) parsing for (nonfunctional) SetEmpireMeter effect. -Tweaked Dump output of SetEmpireMeter. Modified Paths: -------------- trunk/FreeOrion/universe/Effect.cpp trunk/FreeOrion/universe/EffectParser.cpp Modified: trunk/FreeOrion/universe/Effect.cpp =================================================================== --- trunk/FreeOrion/universe/Effect.cpp 2010-10-12 09:25:55 UTC (rev 3816) +++ trunk/FreeOrion/universe/Effect.cpp 2010-10-12 10:21:20 UTC (rev 3817) @@ -728,7 +728,7 @@ std::string SetEmpireMeter::Dump() const { - return DumpIndent() + "SetEmpire" + UserString(m_meter) + " empire = " + m_empire_id->Dump() + " value = " + m_value->Dump(); + return DumpIndent() + "SetEmpireMeter meter = " + UserString(m_meter) + " empire = " + m_empire_id->Dump() + " value = " + m_value->Dump(); } Modified: trunk/FreeOrion/universe/EffectParser.cpp =================================================================== --- trunk/FreeOrion/universe/EffectParser.cpp 2010-10-12 09:25:55 UTC (rev 3816) +++ trunk/FreeOrion/universe/EffectParser.cpp 2010-10-12 10:21:20 UTC (rev 3817) @@ -46,6 +46,17 @@ member7 slot_type; }; + struct SetEmpireMeterClosure : boost::spirit::classic::closure<SetEmpireMeterClosure, Effect::EffectBase*, + ValueRef::ValueRefBase<int>*, + std::string, + ValueRef::ValueRefBase<double>*> + { + member1 this_; + member2 empire; + member3 meter; + member4 value; + }; + struct SetEmpireStockpileClosure : boost::spirit::classic::closure<SetEmpireStockpileClosure, Effect::EffectBase*, ResourceType, ValueRef::ValueRefBase<int>*, @@ -169,6 +180,7 @@ typedef rule<Scanner, SetMeterClosure::context_t> SetMeterRule; typedef rule<Scanner, SetShipPartMeterClosure::context_t> SetShipPartMeterRule; + typedef rule<Scanner, SetEmpireMeterClosure::context_t> SetEmpireMeterRule; typedef rule<Scanner, SetEmpireStockpileClosure::context_t> SetEmpireStockpileRule; typedef rule<Scanner, SetPlanetTypeClosure::context_t> SetPlanetTypeRule; typedef rule<Scanner, SetPlanetSizeClosure::context_t> SetPlanetSizeRule; @@ -186,6 +198,7 @@ SetMeterRule set_meter; SetShipPartMeterRule set_ship_part_meter; + SetEmpireMeterRule set_empire_meter; SetEmpireStockpileRule set_empire_stockpile; EmpireParamRule set_empire_capitol; SetPlanetTypeRule set_planet_type; @@ -223,6 +236,7 @@ ParamLabel parameters_label; ParamLabel tag_label; ParamLabel data_label; + ParamLabel meter_label; }; EffectParserDefinition::EffectParserDefinition() : @@ -242,7 +256,8 @@ message_label("message"), parameters_label("parameters"), tag_label("tag"), - data_label("data") + data_label("data"), + meter_label("meter") { set_meter = (str_p("set") @@ -323,6 +338,18 @@ set_ship_part_meter.value, set_ship_part_meter.slot_type)])); + set_empire_meter = + ( ((str_p("setempiremeter") + >> empire_label >> int_expr_p[ set_empire_meter.empire = arg1] + >> meter_label >> name_p[ set_empire_meter.meter = arg1] + >> value_label >> double_expr_p[ set_empire_meter.value = arg1]) + [set_empire_meter.this_ = new_<Effect::SetEmpireMeter>(set_empire_meter.empire, set_empire_meter.meter, set_empire_meter.value)]) + | ((str_p("setempiremeter") + >> meter_label >> name_p[ set_empire_meter.meter = arg1] + >> value_label >> double_expr_p[ set_empire_meter.value = arg1]) + [set_empire_meter.this_ = new_<Effect::SetEmpireMeter>(set_empire_meter.meter, set_empire_meter.value)]) + ); + set_empire_stockpile = ( ((str_p("setempirefoodstockpile")[set_empire_stockpile.stockpile_type = val(RE_FOOD)] | str_p("setempiremineralstockpile")[set_empire_stockpile.stockpile_type = val(RE_MINERALS)] @@ -468,6 +495,7 @@ effect_p = set_meter[effect_p.this_ = arg1] | set_ship_part_meter[effect_p.this_ = arg1] + | set_empire_meter[effect_p.this_ = arg1] | set_empire_stockpile[effect_p.this_ = arg1] | set_empire_capitol[effect_p.this_ = arg1] | set_planet_type[effect_p.this_ = arg1] |
From: <geo...@us...> - 2010-12-20 21:20:49
|
Revision: 3897 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3897&view=rev Author: geoffthemedio Date: 2010-12-20 21:20:42 +0000 (Mon, 20 Dec 2010) Log Message: ----------- -Added Statistic ValueRef, derived from Variable. This has a Condition that is used to select objects, and then the Variable PropertyName is found for each. One of several StatisticType (eg. sum, mean, product, number) is calculated on those property values, and the result is returned as the appropriate type. Untested and incomplete, but basically sketched out. -Modified various Variable<>::Eval functions to use a local const reference to the property name to calculate instead of a local copy of the string. Modified Paths: -------------- trunk/FreeOrion/universe/ValueRef.cpp trunk/FreeOrion/universe/ValueRef.h Modified: trunk/FreeOrion/universe/ValueRef.cpp =================================================================== --- trunk/FreeOrion/universe/ValueRef.cpp 2010-12-19 22:09:33 UTC (rev 3896) +++ trunk/FreeOrion/universe/ValueRef.cpp 2010-12-20 21:20:42 UTC (rev 3897) @@ -6,6 +6,7 @@ #include "Planet.h" #include "System.h" #include "UniverseObject.h" +#include "Condition.h" #include "../Empire/EmpireManager.h" #include "../Empire/Empire.h" #include "../util/MultiplayerCommon.h" @@ -33,7 +34,7 @@ { const ObjectMap& objects = GetMainObjectMap(); while (first != last) { - std::string property_name = *first; + const std::string& property_name = *first; if (boost::iequals(property_name, "Planet")) { if (const Building* b = universe_object_cast<const Building*>(obj)) obj = objects.Object<Planet>(b->PlanetID()); @@ -208,7 +209,7 @@ PlanetSize Variable<PlanetSize>::Eval(const UniverseObject* source, const UniverseObject* target, const boost::any& current_value) const { - std::string property_name = m_property_name.back(); + const std::string& property_name = m_property_name.back(); IF_CURRENT_VALUE_ELSE(PlanetSize) @@ -230,7 +231,7 @@ PlanetType Variable<PlanetType>::Eval(const UniverseObject* source, const UniverseObject* target, const boost::any& current_value) const { - std::string property_name = m_property_name.back(); + const std::string& property_name = m_property_name.back(); IF_CURRENT_VALUE_ELSE(PlanetType) @@ -252,7 +253,7 @@ PlanetEnvironment Variable<PlanetEnvironment>::Eval(const UniverseObject* source, const UniverseObject* target, const boost::any& current_value) const { - std::string property_name = m_property_name.back(); + const std::string& property_name = m_property_name.back(); IF_CURRENT_VALUE_ELSE(PlanetEnvironment) @@ -274,7 +275,7 @@ UniverseObjectType Variable<UniverseObjectType>::Eval(const UniverseObject* source, const UniverseObject* target, const boost::any& current_value) const { - std::string property_name = m_property_name.back(); + const std::string& property_name = m_property_name.back(); IF_CURRENT_VALUE_ELSE(UniverseObjectType) @@ -309,7 +310,7 @@ StarType Variable<StarType>::Eval(const UniverseObject* source, const UniverseObject* target, const boost::any& current_value) const { - std::string property_name = m_property_name.back(); + const std::string& property_name = m_property_name.back(); IF_CURRENT_VALUE_ELSE(StarType) @@ -336,7 +337,7 @@ Logger().errorStream() << "Variable<double>::Eval unable to follow reference: " << ReconstructName(m_property_name, m_source_ref); return 0.0; } - std::string property_name = m_property_name.back(); + const std::string& property_name = m_property_name.back(); IF_CURRENT_VALUE_ELSE(double) @@ -454,7 +455,7 @@ Logger().errorStream() << "Variable<int>::Eval unable to follow reference: " << ReconstructName(m_property_name, m_source_ref); return 0; } - std::string property_name = m_property_name.back(); + const std::string& property_name = m_property_name.back(); IF_CURRENT_VALUE_ELSE(int) @@ -524,7 +525,7 @@ Logger().errorStream() << "Variable<std::string>::Eval unable to follow reference: " << ReconstructName(m_property_name, m_source_ref); return ""; } - std::string property_name = m_property_name.back(); + const std::string& property_name = m_property_name.back(); IF_CURRENT_VALUE_ELSE(std::string) @@ -552,6 +553,85 @@ } /////////////////////////////////////////////////////////// +// Statistic // +/////////////////////////////////////////////////////////// +namespace ValueRef { + template <> + double Statistic<double>::Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const + { + Condition::ObjectSet condition_matches; + GetConditionMatches(source, condition_matches, m_sampling_condition); + + // evaluate property for each condition-matched object + std::map<const UniverseObject*, double> object_property_values; + GetObjectPropertyValues(source, condition_matches, object_property_values); + + return ReduceData(object_property_values); + } + + template <> + int Statistic<int>::Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const + { + Condition::ObjectSet condition_matches; + GetConditionMatches(source, condition_matches, m_sampling_condition); + + // evaluate property for each condition-matched object + std::map<const UniverseObject*, int> object_property_values; + GetObjectPropertyValues(source, condition_matches, object_property_values); + + return ReduceData(object_property_values); + } + + template <> + std::string Statistic<std::string>::Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const + { + // the only statistic that can be computed on non-number property types + // and that is itself of a non-number type is the most common value + if (m_stat_type != MODE) + throw std::runtime_error("ValueRef evaluated with an invalid STatisticType for the return type (string)."); + + Condition::ObjectSet condition_matches; + GetConditionMatches(source, condition_matches, m_sampling_condition); + + if (condition_matches.empty()) + return ""; + + // evaluate property for each condition-matched object + std::map<const UniverseObject*, std::string> object_property_values; + GetObjectPropertyValues(source, condition_matches, object_property_values); + + // count number of each result, tracking which has the most occurances + std::map<std::string, unsigned int> histogram; + std::map<std::string, unsigned int>::const_iterator most_common_property_value_it = histogram.begin(); + unsigned int max_seen(0); + + for (std::map<const UniverseObject*, std::string>::const_iterator it = object_property_values.begin(); + it != object_property_values.end(); ++it) + { + const std::string& property_value = it->second; + + std::map<std::string, unsigned int>::iterator hist_it = histogram.find(property_value); + if (hist_it == histogram.end()) + hist_it = histogram.insert(std::make_pair(property_value, 0)).first; + unsigned int& num_seen = hist_it->second; + + num_seen += 1; + + if (num_seen > max_seen) { + most_common_property_value_it = hist_it; + max_seen = num_seen; + } + } + + // return result (property value) that occured most frequently + return most_common_property_value_it->first; + } +} + +/////////////////////////////////////////////////////////// // Operation // /////////////////////////////////////////////////////////// namespace ValueRef { Modified: trunk/FreeOrion/universe/ValueRef.h =================================================================== --- trunk/FreeOrion/universe/ValueRef.h 2010-12-19 22:09:33 UTC (rev 3896) +++ trunk/FreeOrion/universe/ValueRef.h 2010-12-20 21:20:42 UTC (rev 3897) @@ -13,8 +13,12 @@ #include <string> #include <vector> +#include <map> class UniverseObject; +namespace Condition { + struct ConditionBase; +} namespace detail { std::vector<std::string> TokenizeDottedReference(const std::string& str); @@ -27,6 +31,19 @@ template <class T> struct ValueRefBase; template <class T> struct Constant; template <class T> struct Variable; + template <class T> struct Statistic; + enum StatisticType { + NUMBER, // returns the number of objects matching the condition + SUM, // returns the sum of the property values of all objects matching the condition + MEAN, // returns the mean of the property values of all objects matching the condition + RMS, // returns the sqrt root of the mean of the squares of the property value sof all objects matching the condition + MODE, // returns the most common property value of objects matching the condition + MAX, // returns the maximum value of the property amongst objects matching the condition + MIN, // returns the minimum value of the property amongst objects matching the condition + SPREAD, // returns the (positive) difference between the maximum and minimum values of the property amongst objects matching the condition + STDEV, // returns the standard deviation of the property values of all objects matching the condition + PRODUCT // returns the product of the property values of all objects matching the condition + }; template <class FromType, class ToType> struct StaticCast; template <class FromType> struct StringCast; template <class T> struct Operation; @@ -93,26 +110,75 @@ * otherwise, the same field is read from Eval's \a target parameter. */ Variable(bool source_ref, const std::string& property_name); - bool SourceRef() const; + bool SourceRef() const; const std::vector<std::string>& PropertyName() const; - virtual T Eval(const UniverseObject* source, const UniverseObject* target, - const boost::any& current_value) const; - virtual std::string Description() const; - virtual std::string Dump() const; + virtual T Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const; + virtual std::string Description() const; + virtual std::string Dump() const; protected: Variable(bool source_ref, const std::vector<std::string>& property_name); private: - bool m_source_ref; - std::vector<std::string> m_property_name; + bool m_source_ref; + std::vector<std::string> m_property_name; friend class boost::serialization::access; template <class Archive> void serialize(Archive& ar, const unsigned int version); }; +/** The variable statistic class. The value returned by this node is + * computed from the general gamestate; the value of the indicated + * \a property_name is computed for each object that matches + * \a sampling_condition and the statistic indicated by \a stat_type is + * calculated from them and returned. */ +template <class T> +struct ValueRef::Statistic : public ValueRef::Variable<T> +{ + Statistic(const std::string& property_name, + StatisticType stat_type, + const Condition::ConditionBase* sampling_condition); + + StatisticType GetStatisticType() const; + const Condition::ConditionBase* SamplingCondition() const; + + virtual T Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const; + + virtual std::string Description() const; + virtual std::string Dump() const; + +protected: + Statistic(const std::vector<std::string>& property_name, + StatisticType stat_type, + const Condition::ConditionBase* sampling_condition); + + /** Gets the set of objects in the Universe that match the sampling condition. */ + void GetConditionMatches(const UniverseObject* source, + Condition::ObjectSet& condition_targets, + const Condition::ConditionBase* condition) const; + + /** Evaluates the property for the specified objects. */ + void GetObjectPropertyValues(const UniverseObject* source, + const Condition::ObjectSet& objects, + std::map<const UniverseObject*, T>& object_property_values) const; + + /** Computes the statistic from the specified set of property values. */ + T ReduceData(const std::map<const UniverseObject*, T>& object_property_values) const; + +private: + std::vector<std::string> m_property_name; + StatisticType m_stat_type; + const Condition::ConditionBase* m_sampling_condition; + + friend class boost::serialization::access; + template <class Archive> + void serialize(Archive& ar, const unsigned int version); +}; + /** The variable static_cast class. The value returned by this node is taken * from the ctor \a value_ref parameter's FromType value, static_cast to * ToType. */ @@ -362,6 +428,207 @@ } /////////////////////////////////////////////////////////// +// Statistic // +/////////////////////////////////////////////////////////// +template <class T> +ValueRef::Statistic<T>::Statistic(const std::string& property_name, + StatisticType stat_type, + const Condition::ConditionBase* sampling_condition) : + Variable(false, property_name), + m_stat_type(stat_type), + m_sampling_condition(sampling_condition) +{} + +template <class T> +ValueRef::Statistic<T>::Statistic(const std::vector<std::string>& property_name, + StatisticType stat_type, + const Condition::ConditionBase* sampling_condition) : + Variable(false, property_name), + m_stat_type(stat_type), + m_sampling_condition(sampling_condition) +{} + +template <class T> +ValueRef::StatisticType ValueRef::Statistic<T>::GetStatisticType() const +{ + return m_stat_type; +} + +template <class T> +const Condition::ConditionBase* ValueRef::Statistic<T>::SamplingCondition() const +{ + return m_sampling_condition; +} + +template <class T> +void ValueRef::Statistic<T>::GetConditionMatches(const UniverseObject* source, + Condition::ObjectSet& condition_targets, + const Condition::ConditionBase* condition) const +{ + condition_targets.clear(); + + if (!condition) + return; + + const ObjectMap& objects = GetMainObjectMap(); + + // evaluate condition on all objects in Universe + Condition::ObjectSet condition_non_targets; + for (ObjectMap::const_iterator it = objects.const_begin(); it != objects.const_end(); ++it) { + condition_non_targets.insert(it->second); + } + condition->Eval(source, condition_targets, condition_non_targets); +} + +template <class T> +void ValueRef::Statistic<T>::GetObjectPropertyValues(const UniverseObject* source, + const Condition::ObjectSet& objects, + std::map<const UniverseObject*, T>& object_property_values) const +{ + object_property_values.clear(); + + for (Condition::ObjectSet::const_iterator it = objects.begin(); it != objects.end(); ++it) { + const UniverseObject* obj = *it; + T property_value = this->Variable<T>::Eval(source, obj, boost::any()); + object_property_values[obj] = property_value; + } +} + +template <class T> +std::string ValueRef::Statistic<T>::Description() const +{ + return "Statistic Desc"; +} + +template <class T> +std::string ValueRef::Statistic<T>::Dump() const +{ + return "Statistic Dump"; +} + +template <class T> +virtual T ValueRef::Statistic<T>::Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const +{ + // the only statistic that can be computed on non-number property types + // and that is itself of a non-number type is the most common value + if (m_stat_type != MODE) + throw std::runtime_error("ValueRef evaluated with an invalid STatisticType for the return type."); + + Condition::ObjectSet condition_matches; + GetConditionMatches(source, condition_matches, m_sampling_condition); + + if (condition_matches.empty()) + return T(-1); // should be INVALID_T of enum types + + // evaluate property for each condition-matched object + std::map<const UniverseObject*, T> object_property_values; + GetObjectPropertyValues(source, condition_matches, object_property_values); + + // count number of each result, tracking which has the most occurances + std::map<T, unsigned int> histogram; + std::map<T, unsigned int>::const_iterator most_common_property_value_it = histogram.begin(); + unsigned int max_seen(0); + + for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + it != object_property_values.end(); ++it) + { + const T& property_value = it->second; + + std::map<T, unsigned int>::iterator hist_it = histogram.find(property_value); + if (hist_it == histogram.end()) + hist_it = histogram.insert(std::make_pair(property_value, 0)).first; + unsigned int& num_seen = hist_it->second; + + num_seen += 1; + + if (num_seen > max_seen) { + most_common_property_value_it = hist_it; + max_seen = num_seen; + } + } + + // return result (property value) that occured most frequently + return most_common_property_value_it->first; +} + +namespace ValueRef { + template <> + double Statistic<double>::Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const; + + template <> + int Statistic<int>::Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const; + + template <> + std::string Statistic<std::string>::Eval(const UniverseObject* source, const UniverseObject* target, + const boost::any& current_value) const; +} + +template <class T> +T ValueRef::Statistic<T>::ReduceData(const std::map<const UniverseObject*, T>& object_property_values) const +{ + switch (m_stat_type) { + case NUMBER: { + return T(object_property_values.size()); + break; + } + case SUM: { + T accumulator(0); + for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + it != object_property_values.end(); ++it) + { + accumulator += it->second; + } + return accumulator; + break; + } + + case MEAN: { + if (object_property_values.empty()) + return T(0); + + T accumulator(0); + for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + it != object_property_values.end(); ++it) + { + accumulator += it->second; + } + return accumulator / static_cast<T>(object_property_values.size()); + break; + } + + case RMS: + + case MODE: + + case MAX: + + case MIN: + + case SPREAD: + + case STDEV: + + case PRODUCT: + + default: + throw std::runtime_error("ValueRef evaluated with an unknown or invalid StatisticType."); + break; + } +} + +template <class T> +template <class Archive> +void ValueRef::Statistic<T>::serialize(Archive& ar, const unsigned int version) +{ + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Variable) + & BOOST_SERIALIZATION_NVP(m_stat_type) + & BOOST_SERIALIZATION_NVP(m_sampling_condition); +} + +/////////////////////////////////////////////////////////// // StaticCast // /////////////////////////////////////////////////////////// template <class FromType, class ToType> |