From: <geo...@us...> - 2010-12-20 22:36:34
|
Revision: 3898 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3898&view=rev Author: geoffthemedio Date: 2010-12-20 22:36:28 +0000 (Mon, 20 Dec 2010) Log Message: ----------- Implemented additional StatisticType operations in ValueRef::Statistic<T>::ReduceData. 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-20 21:20:42 UTC (rev 3897) +++ trunk/FreeOrion/universe/ValueRef.cpp 2010-12-20 22:36:28 UTC (rev 3898) @@ -184,7 +184,6 @@ } } - /////////////////////////////////////////////////////////// // Variable // /////////////////////////////////////////////////////////// @@ -618,7 +617,7 @@ hist_it = histogram.insert(std::make_pair(property_value, 0)).first; unsigned int& num_seen = hist_it->second; - num_seen += 1; + num_seen++; if (num_seen > max_seen) { most_common_property_value_it = hist_it; @@ -658,7 +657,6 @@ } } - std::string DumpIndent() { return std::string(g_indent * 4, ' '); Modified: trunk/FreeOrion/universe/ValueRef.h =================================================================== --- trunk/FreeOrion/universe/ValueRef.h 2010-12-20 21:20:42 UTC (rev 3897) +++ trunk/FreeOrion/universe/ValueRef.h 2010-12-20 22:36:28 UTC (rev 3898) @@ -540,7 +540,7 @@ hist_it = histogram.insert(std::make_pair(property_value, 0)).first; unsigned int& num_seen = hist_it->second; - num_seen += 1; + num_seen++; if (num_seen > max_seen) { most_common_property_value_it = hist_it; @@ -569,6 +569,9 @@ template <class T> T ValueRef::Statistic<T>::ReduceData(const std::map<const UniverseObject*, T>& object_property_values) const { + if (object_property_values.empty()) + return T(0); + switch (m_stat_type) { case NUMBER: { return T(object_property_values.size()); @@ -586,9 +589,6 @@ } 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) @@ -599,20 +599,137 @@ break; } - case RMS: + case RMS: { + 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 * it->second); + } + accumulator /= static_cast<T>(object_property_values.size()); - case MODE: + double retval = std::sqrt(static_cast<double>(accumulator)); + return static_cast<T>(retval); + break; + } - case MAX: + case MODE: { + // 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); - case MIN: + 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; - case SPREAD: + 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; - case STDEV: + num_seen++; - case PRODUCT: + 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; + break; + } + + case MAX: { + std::map<const UniverseObject*, T>::const_iterator max_it = object_property_values.begin(); + + 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; + if (property_value > max_it->second) + max_it = it; + } + + // return maximal observed propery value + return max_it->second; + break; + } + + case MIN: { + std::map<const UniverseObject*, T>::const_iterator min_it = object_property_values.begin(); + + 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; + if (property_value < min_it->second) + min_it = it; + } + + // return minimal observed propery value + return min_it->second; + break; + } + + case SPREAD: { + std::map<const UniverseObject*, T>::const_iterator max_it = object_property_values.begin(); + std::map<const UniverseObject*, T>::const_iterator min_it = object_property_values.begin(); + + 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; + if (property_value > max_it->second) + max_it = it; + if (property_value < min_it->second) + min_it = it; + } + + // return difference between maximal and minimal observed propery values + return max_it->second - min_it->second; + break; + } + + case STDEV: { + if (object_property_values.size() < 2) + return T(0); + + // find sample mean + 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; + } + const T MEAN(accumulator / static_cast<T>(object_property_values.size())); + + // find average of squared deviations from sample mean + accumulator = T(0); + for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + it != object_property_values.end(); ++it) + { + accumulator += (it->second - MEAN) * (it->second - MEAN); + } + const T MEAN_DEV2(accumulator / static_cast<T>(static_cast<int>(object_property_values.size()) - 1)); + double retval = std::sqrt(static_cast<double>(MEAN_DEV2)); + return static_cast<T>(retval); + break; + } + + case PRODUCT: { + T accumulator(1); + 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; + } + default: throw std::runtime_error("ValueRef evaluated with an unknown or invalid StatisticType."); break; |
From: <geo...@us...> - 2010-12-21 12:06:03
|
Revision: 3900 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3900&view=rev Author: geoffthemedio Date: 2010-12-21 12:05:56 +0000 (Tue, 21 Dec 2010) Log Message: ----------- -Made INVALID_UNIVERSE_OBJECT_TYPE enum have numerical value -1 like other INVALID enum values. -Layout in ValueRefParser.h Modified Paths: -------------- trunk/FreeOrion/universe/Enums.h trunk/FreeOrion/universe/ValueRefParser.h Modified: trunk/FreeOrion/universe/Enums.h =================================================================== --- trunk/FreeOrion/universe/Enums.h 2010-12-21 12:04:05 UTC (rev 3899) +++ trunk/FreeOrion/universe/Enums.h 2010-12-21 12:05:56 UTC (rev 3900) @@ -9,7 +9,7 @@ /* the various major subclasses of UniverseObject */ enum UniverseObjectType { - INVALID_UNIVERSE_OBJECT_TYPE, + INVALID_UNIVERSE_OBJECT_TYPE = -1, OBJ_BUILDING, OBJ_SHIP, OBJ_FLEET, Modified: trunk/FreeOrion/universe/ValueRefParser.h =================================================================== --- trunk/FreeOrion/universe/ValueRefParser.h 2010-12-21 12:04:05 UTC (rev 3899) +++ trunk/FreeOrion/universe/ValueRefParser.h 2010-12-21 12:05:56 UTC (rev 3900) @@ -30,13 +30,13 @@ 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; -extern PlanetTypeValueRefRule planettype_expr_p; -extern PlanetEnvironmentValueRefRule planetenvironment_expr_p; -extern UniverseObjectTypeValueRefRule universeobjecttype_expr_p; -extern StarTypeValueRefRule startype_expr_p; +extern StringValueRefRule string_expr_p; +extern IntValueRefRule int_expr_p; +extern DoubleValueRefRule double_expr_p; +extern PlanetSizeValueRefRule planetsize_expr_p; +extern PlanetTypeValueRefRule planettype_expr_p; +extern PlanetEnvironmentValueRefRule planetenvironment_expr_p; +extern UniverseObjectTypeValueRefRule universeobjecttype_expr_p; +extern StarTypeValueRefRule startype_expr_p; #endif // _ValueRefParser_h_ |
From: <tz...@us...> - 2010-12-22 18:15:19
|
Revision: 3905 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3905&view=rev Author: tzlaine Date: 2010-12-22 18:15:12 +0000 (Wed, 22 Dec 2010) Log Message: ----------- Fixed numerous gcc compilation failures due to a dependency cycle between ValueRef.h and Condition.h. Modified Paths: -------------- trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/Condition.h trunk/FreeOrion/universe/ConditionParser1.cpp trunk/FreeOrion/universe/ShipDesign.cpp trunk/FreeOrion/universe/ValueRef.h trunk/FreeOrion/universe/ValueRefParser.cpp Added Paths: ----------- trunk/FreeOrion/universe/ValueRefFwd.h Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2010-12-22 17:40:32 UTC (rev 3904) +++ trunk/FreeOrion/universe/Condition.cpp 2010-12-22 18:15:12 UTC (rev 3905) @@ -10,6 +10,7 @@ #include "System.h" #include "Species.h" #include "Meter.h" +#include "ValueRef.h" #include "../Empire/Empire.h" #include "../Empire/EmpireManager.h" Modified: trunk/FreeOrion/universe/Condition.h =================================================================== --- trunk/FreeOrion/universe/Condition.h 2010-12-22 17:40:32 UTC (rev 3904) +++ trunk/FreeOrion/universe/Condition.h 2010-12-22 18:15:12 UTC (rev 3905) @@ -2,10 +2,16 @@ #ifndef _Condition_h_ #define _Condition_h_ +#include "Enums.h" +#include "ValueRefFwd.h" + +#include <boost/serialization/access.hpp> +#include <boost/serialization/nvp.hpp> + #include <set> +#include <string> +#include <vector> -#include "ValueRef.h" - class UniverseObject; Modified: trunk/FreeOrion/universe/ConditionParser1.cpp =================================================================== --- trunk/FreeOrion/universe/ConditionParser1.cpp 2010-12-22 17:40:32 UTC (rev 3904) +++ trunk/FreeOrion/universe/ConditionParser1.cpp 2010-12-22 18:15:12 UTC (rev 3905) @@ -3,6 +3,7 @@ #include "ParserUtil.h" #include "ValueRefParser.h" #include "Condition.h" +#include "ValueRef.h" using namespace boost::spirit::classic; using namespace phoenix; Modified: trunk/FreeOrion/universe/ShipDesign.cpp =================================================================== --- trunk/FreeOrion/universe/ShipDesign.cpp 2010-12-22 17:40:32 UTC (rev 3904) +++ trunk/FreeOrion/universe/ShipDesign.cpp 2010-12-22 18:15:12 UTC (rev 3905) @@ -9,6 +9,7 @@ #include "ParserUtil.h" #include "Condition.h" #include "Effect.h" +#include "ValueRef.h" #include <boost/filesystem/fstream.hpp> Modified: trunk/FreeOrion/universe/ValueRef.h =================================================================== --- trunk/FreeOrion/universe/ValueRef.h 2010-12-22 17:40:32 UTC (rev 3904) +++ trunk/FreeOrion/universe/ValueRef.h 2010-12-22 18:15:12 UTC (rev 3905) @@ -3,6 +3,8 @@ #define _ValueRef_h_ #include "Enums.h" +#include "ValueRefFwd.h" +#include "Condition.h" #include "../util/MultiplayerCommon.h" #include <boost/algorithm/string/case_conv.hpp> @@ -16,47 +18,11 @@ #include <map> class UniverseObject; -namespace Condition { - struct ConditionBase; -} namespace detail { 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. */ -namespace ValueRef { - 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 of the mean of the squares of the property values of all objects matching the condition - MODE, // returns the most common property value of objects matching the condition. supported for non-numeric types such as enums. - 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; - enum OpType { - PLUS, - MINUS, - TIMES, - DIVIDES, - NEGATE - }; - 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. */ template <class T> @@ -434,7 +400,7 @@ ValueRef::Statistic<T>::Statistic(const std::string& property_name, StatisticType stat_type, const Condition::ConditionBase* sampling_condition) : - Variable(false, property_name), + Variable<T>(false, property_name), m_stat_type(stat_type), m_sampling_condition(sampling_condition) { @@ -445,7 +411,7 @@ ValueRef::Statistic<T>::Statistic(const std::vector<std::string>& property_name, StatisticType stat_type, const Condition::ConditionBase* sampling_condition) : - Variable(false, property_name), + Variable<T>(false, property_name), m_stat_type(stat_type), m_sampling_condition(sampling_condition) { @@ -494,7 +460,7 @@ Logger().debugStream() << "ValueRef::Statistic<T>::GetObjectPropertyValues source: " << source->Dump() << " sampling condition: " << m_sampling_condition->Dump() - << " property name final: " << PropertyName().back(); + << " property name final: " << this->PropertyName().back(); for (Condition::ObjectSet::const_iterator it = objects.begin(); it != objects.end(); ++it) { const UniverseObject* obj = *it; @@ -536,15 +502,15 @@ // 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(); + typename 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(); + for (typename 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); + typename 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; @@ -588,7 +554,7 @@ } case SUM: { T accumulator(0); - for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + for (typename std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); it != object_property_values.end(); ++it) { accumulator += it->second; @@ -599,7 +565,7 @@ case MEAN: { T accumulator(0); - for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + for (typename std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); it != object_property_values.end(); ++it) { accumulator += it->second; @@ -610,7 +576,7 @@ case RMS: { T accumulator(0); - for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + for (typename std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); it != object_property_values.end(); ++it) { accumulator += (it->second * it->second); @@ -625,15 +591,15 @@ case MODE: { // 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(); + typename 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(); + for (typename 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); + typename 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; @@ -652,9 +618,9 @@ } case MAX: { - std::map<const UniverseObject*, T>::const_iterator max_it = object_property_values.begin(); + typename std::map<const UniverseObject*, T>::const_iterator max_it = object_property_values.begin(); - for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + for (typename std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); it != object_property_values.end(); ++it) { const T& property_value = it->second; @@ -668,9 +634,9 @@ } case MIN: { - std::map<const UniverseObject*, T>::const_iterator min_it = object_property_values.begin(); + typename std::map<const UniverseObject*, T>::const_iterator min_it = object_property_values.begin(); - for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + for (typename std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); it != object_property_values.end(); ++it) { const T& property_value = it->second; @@ -684,10 +650,10 @@ } case SPREAD: { - std::map<const UniverseObject*, T>::const_iterator max_it = object_property_values.begin(); - std::map<const UniverseObject*, T>::const_iterator min_it = object_property_values.begin(); + typename std::map<const UniverseObject*, T>::const_iterator max_it = object_property_values.begin(); + typename std::map<const UniverseObject*, T>::const_iterator min_it = object_property_values.begin(); - for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + for (typename std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); it != object_property_values.end(); ++it) { const T& property_value = it->second; @@ -708,7 +674,7 @@ // find sample mean T accumulator(0); - for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + for (typename std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); it != object_property_values.end(); ++it) { accumulator += it->second; @@ -717,7 +683,7 @@ // find average of squared deviations from sample mean accumulator = T(0); - for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + for (typename std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); it != object_property_values.end(); ++it) { accumulator += (it->second - MEAN) * (it->second - MEAN); @@ -730,7 +696,7 @@ case PRODUCT: { T accumulator(1); - for (std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); + for (typename std::map<const UniverseObject*, T>::const_iterator it = object_property_values.begin(); it != object_property_values.end(); ++it) { accumulator *= it->second; Added: trunk/FreeOrion/universe/ValueRefFwd.h =================================================================== --- trunk/FreeOrion/universe/ValueRefFwd.h (rev 0) +++ trunk/FreeOrion/universe/ValueRefFwd.h 2010-12-22 18:15:12 UTC (rev 3905) @@ -0,0 +1,38 @@ +// -*- C++ -*- +#ifndef _ValueRefFwd_h_ +#define _ValueRefFwd_h_ + +/** 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; + 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 of the mean of the squares of the property values of all objects matching the condition + MODE, // returns the most common property value of objects matching the condition. supported for non-numeric types such as enums. + 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; + enum OpType { + PLUS, + MINUS, + TIMES, + DIVIDES, + NEGATE + }; + template <class T> bool ConstantExpr(const ValueRefBase<T>* expr); +} + +#endif // _ValueRefFwd_h_ Modified: trunk/FreeOrion/universe/ValueRefParser.cpp =================================================================== --- trunk/FreeOrion/universe/ValueRefParser.cpp 2010-12-22 17:40:32 UTC (rev 3904) +++ trunk/FreeOrion/universe/ValueRefParser.cpp 2010-12-22 18:15:12 UTC (rev 3905) @@ -27,10 +27,18 @@ ValueRef::StatisticType, std::string, const Condition::ConditionBase*> { - member1 this_; - member2 stat_type; - member3 property_name; - member4 sampling_condition; + typedef boost::spirit::classic::closure< + ValueRefStatisticClosure, + RefBase*, + ValueRef::StatisticType, + std::string, + const Condition::ConditionBase* + > BaseType; + + typename BaseType::member1 this_; + typename BaseType::member2 stat_type; + typename BaseType::member3 property_name; + typename BaseType::member4 sampling_condition; }; typedef boost::spirit::classic::rule<Scanner, typename ValueRefStatisticClosure::context_t> type; }; |
From: <geo...@us...> - 2010-12-23 21:20:52
|
Revision: 3912 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3912&view=rev Author: geoffthemedio Date: 2010-12-23 21:20:45 +0000 (Thu, 23 Dec 2010) Log Message: ----------- -Moved int_variable_final and double_variable_Final parsers, and variable_container parser out of ValueRefParserDefinition class into file scope, and declared them as a new SimpleRule with a default (empty) closure within ValueRefParser.h. Also added a new string_variable_final parser declared the same way. This makes those lists of properties for those types, and the container names, available in other source files. -Re-renamed SpecializedConstantDefinition to SpecializedConstantAndVariableFinalDefinition as it does do a bit more than just constant parser definition. Modified Paths: -------------- trunk/FreeOrion/universe/ValueRefParser.cpp trunk/FreeOrion/universe/ValueRefParser.h Modified: trunk/FreeOrion/universe/ValueRefParser.cpp =================================================================== --- trunk/FreeOrion/universe/ValueRefParser.cpp 2010-12-23 21:14:39 UTC (rev 3911) +++ trunk/FreeOrion/universe/ValueRefParser.cpp 2010-12-23 21:20:45 UTC (rev 3912) @@ -8,6 +8,31 @@ using namespace boost::spirit::classic; using namespace phoenix; +// final variable tokens: object property names that have the appropriate type +// for the ValueRef return type. +SimpleRule int_variable_final = + str_p("owner") | "id" | "creationturn" | "age" | "designid" + | "fleetid" | "planetid" | "systemid" | "finaldestinationid" + | "nextsystemid" | "previoussystemid" | "numships"; + +SimpleRule double_variable_final = + str_p("farming") | "targetfarming" | "industry" | "targetindustry" + | "research" | "targetresearch" | "trade" | "targettrade" + | "mining" | "targetmining" | "construction" | "targetconstruction" + | "population" | "targetpopulation" | "health" | "targethealth" + | "maxfuel" | "fuel" | "maxshield" | "shield" + | "maxdefense" | "defense" | "maxstructure" | "structure" + | "supply" | "stealth" | "detection" | "foodconsumption" + | "battlespeed" | "starlanespeed" + | "tradestockpile" | "mineralstockpile" | "foodstockpile"; + +SimpleRule string_variable_final = + str_p("name") | "species" | "buildingtype" | "focus"; + +SimpleRule variable_container = + str_p("planet") | "system" | "fleet"; + +// complete rule for all possible ValueRef return types StringValueRefRule string_expr_p; IntValueRefRule int_expr_p; DoubleValueRefRule double_expr_p; @@ -17,7 +42,6 @@ UniverseObjectTypeValueRefRule universeobjecttype_expr_p; StarTypeValueRefRule startype_expr_p; - // statistic parsers: require more complex parser than single-property valueref template <class T> struct ValueRefStatisticRule @@ -59,18 +83,15 @@ ValueRefParserDefinition(Rule& expr); private: - void SpecializedConstantDefinition(); + void SpecializedConstantAndVariableFinalDefinition(); void SpecializedVariableDefinition(); void SpecializedVariableStatisticDefinition(); typedef typename ValueRefStatisticRule<T>::type StatisticRule; StatisticRule statistic; + SimpleRule variable_final; Rule constant; - Rule variable_container; - Rule variable_final; - Rule int_variable_final; - Rule double_variable_final; Rule variable; Rule primary_expr; @@ -98,29 +119,8 @@ property_label("property"), condition_label("condition") { - int_variable_final = - str_p("owner") | "id" | "creationturn" | "age" | "designid" - | "fleetid" | "planetid" | "systemid" | "finaldestinationid" - | "nextsystemid" | "previoussystemid" | "numships"; - - double_variable_final = - str_p("farming") | "targetfarming" | "industry" | "targetindustry" - | "research" | "targetresearch" | "trade" | "targettrade" - | "mining" | "targetmining" | "construction" | "targetconstruction" - | "population" | "targetpopulation" | "health" | "targethealth" - | "maxfuel" | "fuel" | "maxshield" | "shield" - | "maxdefense" | "defense" | "maxstructure" | "structure" - | "supply" | "stealth" | "detection" | "foodconsumption" - | "battlespeed" | "starlanespeed" - | "tradestockpile" | "mineralstockpile" | "foodstockpile"; - - SpecializedConstantDefinition(); - - variable_container = - str_p("planet") | "system" | "fleet"; - + SpecializedConstantAndVariableFinalDefinition(); SpecializedVariableDefinition(); - SpecializedVariableStatisticDefinition(); // basic expression: constant, variable or statistical variable; input to further calculations @@ -156,7 +156,7 @@ } template <> - void ValueRefParserDefinition<std::string>::SpecializedConstantDefinition() + void ValueRefParserDefinition<std::string>::SpecializedConstantAndVariableFinalDefinition() { constant = // quote-enclosed string @@ -179,15 +179,11 @@ | (real_p >> eps_p) [constant.this_ = new_<RefConst>(construct_<std::string>(arg1, arg2))] | (int_p >> eps_p)[constant.this_ = new_<RefConst>(construct_<std::string>(arg1, arg2))]; - variable_final = - str_p("name") - | "species" - | "buildingtype" - | "focus"; + variable_final = string_variable_final; } template <> - void ValueRefParserDefinition<int>::SpecializedConstantDefinition() + void ValueRefParserDefinition<int>::SpecializedConstantAndVariableFinalDefinition() { constant = real_p[constant.this_ = new_<RefConst>(static_cast_<int>(arg1))] @@ -197,7 +193,7 @@ } template <> - void ValueRefParserDefinition<double>::SpecializedConstantDefinition() + void ValueRefParserDefinition<double>::SpecializedConstantAndVariableFinalDefinition() { constant = real_p[constant.this_ = new_<RefConst>(arg1)] @@ -207,7 +203,7 @@ } template <> - void ValueRefParserDefinition<PlanetSize>::SpecializedConstantDefinition() + void ValueRefParserDefinition<PlanetSize>::SpecializedConstantAndVariableFinalDefinition() { constant = planet_size_p[constant.this_ = new_<RefConst>(arg1)] @@ -217,7 +213,7 @@ } template <> - void ValueRefParserDefinition<PlanetType>::SpecializedConstantDefinition() + void ValueRefParserDefinition<PlanetType>::SpecializedConstantAndVariableFinalDefinition() { constant = planet_type_p[constant.this_ = new_<RefConst>(arg1)] @@ -227,7 +223,7 @@ } template <> - void ValueRefParserDefinition<PlanetEnvironment>::SpecializedConstantDefinition() + void ValueRefParserDefinition<PlanetEnvironment>::SpecializedConstantAndVariableFinalDefinition() { constant = planet_environment_type_p[constant.this_ = new_<RefConst>(arg1)] @@ -237,7 +233,7 @@ } template <> - void ValueRefParserDefinition<UniverseObjectType>::SpecializedConstantDefinition() + void ValueRefParserDefinition<UniverseObjectType>::SpecializedConstantAndVariableFinalDefinition() { constant = universe_object_type_p[constant.this_ = new_<RefConst>(arg1)] @@ -247,7 +243,7 @@ } template <> - void ValueRefParserDefinition<StarType>::SpecializedConstantDefinition() + void ValueRefParserDefinition<StarType>::SpecializedConstantAndVariableFinalDefinition() { constant = star_type_p[constant.this_ = new_<RefConst>(arg1)] @@ -337,7 +333,7 @@ statistic = (str_p("mode") >> property_label >> (!(variable_container >> ".") >> variable_final) - [statistic.property_name = construct_<std::string>(arg1, arg2)] + [statistic.property_name = construct_<std::string>(arg1, arg2)] >> condition_label >> condition_p[statistic.sampling_condition = arg1]) [statistic.this_ = new_<RefStat>(statistic.property_name, val(ValueRef::MODE), statistic.sampling_condition)]; } @@ -347,7 +343,7 @@ { statistic = ((str_p("number") >> condition_label >> condition_p[statistic.sampling_condition = arg1]) - [statistic.this_ = new_<RefStat>(val(""), val(ValueRef::NUMBER), statistic.sampling_condition)]) + [statistic.this_ = new_<RefStat>(val(""), val(ValueRef::NUMBER), statistic.sampling_condition)]) | (((str_p("sum")[statistic.stat_type = val(ValueRef::SUM)] | str_p("mean")[statistic.stat_type = val(ValueRef::MEAN)] | str_p("rms")[statistic.stat_type = val(ValueRef::RMS)] @@ -358,9 +354,9 @@ | str_p("stdev")[statistic.stat_type = val(ValueRef::STDEV)] | str_p("product")[statistic.stat_type = val(ValueRef::PRODUCT)]) >> property_label >> (!(variable_container >> ".") >> variable_final) - [statistic.property_name = construct_<std::string>(arg1, arg2)] + [statistic.property_name = construct_<std::string>(arg1, arg2)] >> condition_label >> condition_p[statistic.sampling_condition = arg1]) - [statistic.this_ = new_<RefStat>(statistic.property_name, statistic.stat_type, statistic.sampling_condition)]); + [statistic.this_ = new_<RefStat>(statistic.property_name, statistic.stat_type, statistic.sampling_condition)]); } template <> @@ -368,7 +364,7 @@ { statistic = ((str_p("number") >> condition_label >> condition_p[statistic.sampling_condition = arg1]) - [statistic.this_ = new_<RefStat>(val("dummy"), val(ValueRef::NUMBER), statistic.sampling_condition)]) + [statistic.this_ = new_<RefStat>(val("dummy"), val(ValueRef::NUMBER), statistic.sampling_condition)]) | (((str_p("sum")[statistic.stat_type = val(ValueRef::SUM)] | str_p("mean")[statistic.stat_type = val(ValueRef::MEAN)] | str_p("rms")[statistic.stat_type = val(ValueRef::RMS)] @@ -379,8 +375,8 @@ | str_p("stdev")[statistic.stat_type = val(ValueRef::STDEV)] | str_p("product")[statistic.stat_type = val(ValueRef::PRODUCT)]) >> property_label >> (!(variable_container >> ".") >> variable_final) - [statistic.property_name = construct_<std::string>(arg1, arg2)] + [statistic.property_name = construct_<std::string>(arg1, arg2)] >> condition_label >> condition_p[statistic.sampling_condition = arg1]) - [statistic.this_ = new_<RefStat>(statistic.property_name, statistic.stat_type, statistic.sampling_condition)]); + [statistic.this_ = new_<RefStat>(statistic.property_name, statistic.stat_type, statistic.sampling_condition)]); } } Modified: trunk/FreeOrion/universe/ValueRefParser.h =================================================================== --- trunk/FreeOrion/universe/ValueRefParser.h 2010-12-23 21:14:39 UTC (rev 3911) +++ trunk/FreeOrion/universe/ValueRefParser.h 2010-12-23 21:20:45 UTC (rev 3912) @@ -7,6 +7,12 @@ struct ValueRefBase; } +typedef boost::spirit::classic::rule<Scanner> SimpleRule; +extern SimpleRule int_variable_final; +extern SimpleRule double_variable_final; +extern SimpleRule string_variable_final; +extern SimpleRule variable_container; + template <class T> struct ValueRefRule { |
From: <geo...@us...> - 2010-12-23 21:25:28
|
Revision: 3913 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3913&view=rev Author: geoffthemedio Date: 2010-12-23 21:25:22 +0000 (Thu, 23 Dec 2010) Log Message: ----------- -Renamed NumberOf condition to SortedNumberOf, which has four options for how to pick which objects to match, one of which - random - duplicating the existing behaviour of NumberOf. Only the previously-existing behaviour has been implemented: random selection of a specified number of subcondition-matching objects. The other behaviours, max, min and mode sorting, will use a property name, like a ValueRef::Variable, to sort the objects that match the subcondition, and only those with the largest, smallest or most common values of the property, respectively, will be matched. -Added parsing for new variants of SortedNumberOf. The old parsing for random-selection NumberOf is retained, so existing content that uses NumberOf (of which there is one case, as far as I can tell) should be unaffected. Modified Paths: -------------- trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/Condition.h trunk/FreeOrion/universe/ConditionParser1.cpp trunk/FreeOrion/universe/ConditionParser2.cpp Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2010-12-23 21:20:45 UTC (rev 3912) +++ trunk/FreeOrion/universe/Condition.cpp 2010-12-23 21:25:22 UTC (rev 3913) @@ -180,7 +180,7 @@ } /////////////////////////////////////////////////////////// -// NumberOf // +// SortedNumberOf // /////////////////////////////////////////////////////////// namespace { /** Random number genrator function to use with random_shuffle */ @@ -189,9 +189,8 @@ } int (*CRI)(int) = CustomRandInt; - - /** Transfers the indicated \a number of objects from from_set to to_set */ - void TransferObjects(unsigned int number, Condition::ObjectSet& from_set, Condition::ObjectSet& to_set) { + /** Transfers the indicated \a number of objects, randomly selected from from_set to to_set */ + void TransferRandomObjects(unsigned int number, Condition::ObjectSet& from_set, Condition::ObjectSet& to_set) { // ensure number of objects to be moved is within reasonable range number = std::min<unsigned int>(number, from_set.size()); if (number == 0) @@ -219,41 +218,35 @@ } } -Condition::NumberOf::NumberOf(const ValueRef::ValueRefBase<int>* number, const ConditionBase* condition) : +Condition::SortedNumberOf::SortedNumberOf(const ValueRef::ValueRefBase<int>* number, + const ConditionBase* condition, + const std::string& property_name, + SortingMethod sorting_method) : m_number(number), - m_condition(condition) -{ -} + m_condition(condition), + m_property_name(::detail::TokenizeDottedReference(property_name)), + m_sorting_method(sorting_method) +{} -Condition::NumberOf::~NumberOf() +Condition::SortedNumberOf::SortedNumberOf(const ValueRef::ValueRefBase<int>* number, + const ConditionBase* condition, + const std::vector<std::string>& property_name, + SortingMethod sorting_method) : + m_number(number), + m_condition(condition), + m_property_name(), + m_sorting_method(sorting_method) +{} + +Condition::SortedNumberOf::~SortedNumberOf() { delete m_number; delete m_condition; } -std::string Condition::NumberOf::Description(bool negated/* = false*/) const +void Condition::SortedNumberOf::Eval(const UniverseObject* source, Condition::ObjectSet& targets, + Condition::ObjectSet& non_targets, SearchDomain search_domain/* = NON_TARGETS*/) const { - std::string value_str = ValueRef::ConstantExpr(m_number) ? lexical_cast<std::string>(m_number->Dump()) : m_number->Description(); - std::string description_str = "DESC_NUMBER_OF"; - if (negated) - description_str += "_NOT"; - return str(FlexibleFormat(UserString(description_str)) - % value_str - % m_condition->Description()); -} - -std::string Condition::NumberOf::Dump() const -{ - std::string retval = DumpIndent() + "NumberOf number = " + m_number->Dump() + " condition =\n"; - ++g_indent; - retval += m_condition->Dump(); - --g_indent; - return retval; -} - -void Condition::NumberOf::Eval(const UniverseObject* source, ObjectSet& targets, ObjectSet& non_targets, - SearchDomain search_domain/* = NON_TARGETS*/) const -{ int number = m_number->Eval(source, source, boost::any()); if (search_domain == NON_TARGETS) { @@ -261,8 +254,14 @@ ObjectSet matched_non_targets; m_condition->Eval(source, matched_non_targets, non_targets, NON_TARGETS); - // transfer the indicated number of matched_non_targets to targets - TransferObjects(number, matched_non_targets, targets); + switch (m_sorting_method) { + case SORT_RANDOM: + // transfer the indicated number of matched_non_targets to targets + TransferRandomObjects(number, matched_non_targets, targets); + break; + default: + break; + } // move remainder of matched_non_targets back to non_targets non_targets.insert(matched_non_targets.begin(), matched_non_targets.end()); @@ -277,8 +276,14 @@ ObjectSet matched_targets = targets; targets.clear(); - // transfer desired number of matched_targets back to targets set - TransferObjects(number, matched_targets, targets); + switch (m_sorting_method) { + case SORT_RANDOM: + // transfer desired number of matched_targets back to targets set + TransferRandomObjects(number, matched_targets, targets); + break; + default: + break; + } // move remainder to non_targets set non_targets.insert(matched_targets.begin(), matched_targets.end()); @@ -286,6 +291,52 @@ } } +std::string Condition::SortedNumberOf::Description(bool negated/* = false*/) const +{ + std::string value_str = ValueRef::ConstantExpr(m_number) ? lexical_cast<std::string>(m_number->Dump()) : m_number->Description(); + std::string description_str = "DESC_NUMBER_OF"; + if (negated) + description_str += "_NOT"; + return str(FlexibleFormat(UserString(description_str)) + % value_str + % m_condition->Description()); +} + +std::string Condition::SortedNumberOf::Dump() const +{ + std::string retval = DumpIndent(); + switch (m_sorting_method) { + case SORT_RANDOM: + retval += "NumberOf"; break; + case SORT_MAX: + retval += "MaximumNumberOf"; break; + case SORT_MIN: + retval += "MinimumNumberOf"; break; + case SORT_MODE: + retval += "ModeNumberOf"; break; + default: + retval += "?NumberOf"; break; + } + + retval += " number = " + m_number->Dump(); + + if (m_sorting_method != SORT_RANDOM) { + retval += " property = "; + for (std::vector<std::string>::const_iterator it = m_property_name.begin(); it != m_property_name.end(); ++it) { + if (it != m_property_name.begin()) + retval += "."; + retval += *it; + } + } + + retval += " condition =\n"; + ++g_indent; + retval += m_condition->Dump(); + --g_indent; + + return retval; +} + /////////////////////////////////////////////////////////// // All // /////////////////////////////////////////////////////////// @@ -786,7 +837,7 @@ { std::string retval = DumpIndent() + "ContainedBy condition =\n"; ++g_indent; - retval += m_condition->Dump(); + retval += m_condition->Dump(); --g_indent; return retval; } @@ -1300,7 +1351,7 @@ } std::string Condition::DesignHasPart::Dump() const{ - return DumpIndent() + "DesignHasPart low = " + m_low->Dump() + "Number high = " + m_high->Dump() + " name = " + m_name; + return DumpIndent() + "DesignHasPart low = " + m_low->Dump() + " high = " + m_high->Dump() + " name = " + m_name; } bool Condition::DesignHasPart::Match(const UniverseObject* source, const UniverseObject* target) const @@ -1349,7 +1400,7 @@ } std::string Condition::DesignHasPartClass::Dump() const{ - return DumpIndent() + "DesignHasPartClass low = " + m_low->Dump() + "Number high = " + m_high->Dump() + " class = " + UserString(boost::lexical_cast<std::string>(m_class)); + return DumpIndent() + "DesignHasPartClass low = " + m_low->Dump() + " high = " + m_high->Dump() + " class = " + UserString(boost::lexical_cast<std::string>(m_class)); } bool Condition::DesignHasPartClass::Match(const UniverseObject* source, const UniverseObject* target) const @@ -1441,7 +1492,7 @@ std::string Condition::MeterValue::Dump() const { - std::string retval = DumpIndent() + "Current"; + std::string retval = DumpIndent(); switch (m_meter) { case INVALID_METER_TYPE: retval += "INVALID_METER_TYPE"; break; case METER_TARGET_POPULATION: retval += "TargetPopulation"; break; @@ -1483,7 +1534,7 @@ case METER_ANTI_FIGHTER_DAMAGE: retval += "AntiFighterDamage"; break; case METER_LAUNCH_RATE: retval += "LaunchRate"; break; case METER_FIGHTER_WEAPON_RANGE:retval += "FighterWeaponRange"; break; - default: retval += "?"; break; + default: retval += "?Meter?"; break; } retval += " low = " + m_low->Dump() + " high = " + m_high->Dump() + "\n"; return retval; Modified: trunk/FreeOrion/universe/Condition.h =================================================================== --- trunk/FreeOrion/universe/Condition.h 2010-12-23 21:20:45 UTC (rev 3912) +++ trunk/FreeOrion/universe/Condition.h 2010-12-23 21:25:22 UTC (rev 3913) @@ -15,16 +15,24 @@ class UniverseObject; -/** this namespace holds ConditionBase and its subclasses; these classes represent predicates about UniverseObjects used - by, for instance, the Effect system. */ +/** 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<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. - TARGETS ///< The Condition will only examine items in the target set; those that do not match the Condition will be inserted into the nontarget set. + NON_TARGETS, ///< The Condition will only examine items in the nontarget set; those that match the Condition will be inserted into the target set. + TARGETS ///< The Condition will only examine items in the target set; those that do not match the Condition will be inserted into the nontarget set. }; + enum SortingMethod { + SORT_MAX, ///< Objects with the largest property value will be selected + SORT_MIN, ///< Objects with the smallest property value will be selected + SORT_MODE, ///< Objects with the most common property value will be selected + SORT_RANDOM ///< Objects will be selected randomly, without consideration of property values + }; + struct ConditionBase; struct All; struct EmpireAffiliation; @@ -59,9 +67,9 @@ struct Or; struct Not; struct Turn; - struct NumberOf; struct ContainedBy; struct Number; + struct SortedNumberOf; } /** The base class for all Conditions. */ @@ -121,19 +129,37 @@ void serialize(Archive& ar, const unsigned int version); }; -/** Matches a randomly selected \a number of objects that match Condition \a condition, or as many objects - as match the condition if the number of objects is less than the number requested. */ -struct Condition::NumberOf : Condition::ConditionBase +/** Matches a specified \a number of objects that match Condition \a condition + * or as many objects as match the condition if the number of objects is less + * than the number requested. If more objects match the condition than are + * requested, the objects are sorted according to the value of the specified + * \a property_name and objects are matched according to whether they have + * the specified \a sorting_type of those property values. For example, + * objects with the largest, smallest or most common property value may be + * selected preferentially. */ +struct Condition::SortedNumberOf : public Condition::ConditionBase { - NumberOf(const ValueRef::ValueRefBase<int>* number, const ConditionBase* condition); - virtual ~NumberOf(); + SortedNumberOf(const ValueRef::ValueRefBase<int>* number, + const ConditionBase* condition, + const std::string& property_name, + SortingMethod sorting_method); + + virtual ~SortedNumberOf(); 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; +protected: + SortedNumberOf(const ValueRef::ValueRefBase<int>* number, + const ConditionBase* condition, + const std::vector<std::string>& property_name, + SortingMethod sorting_method); + private: - const ValueRef::ValueRefBase<int>* m_number; - const ConditionBase* m_condition; + const ValueRef::ValueRefBase<int>* m_number; + const ConditionBase* m_condition; + std::vector<std::string> m_property_name; + SortingMethod m_sorting_method; friend class boost::serialization::access; template <class Archive> @@ -782,11 +808,13 @@ } template <class Archive> -void Condition::NumberOf::serialize(Archive& ar, const unsigned int version) +void Condition::SortedNumberOf::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(ConditionBase) & BOOST_SERIALIZATION_NVP(m_number) - & BOOST_SERIALIZATION_NVP(m_condition); + & BOOST_SERIALIZATION_NVP(m_condition) + & BOOST_SERIALIZATION_NVP(m_property_name) + & BOOST_SERIALIZATION_NVP(m_sorting_method); } template <class Archive> Modified: trunk/FreeOrion/universe/ConditionParser1.cpp =================================================================== --- trunk/FreeOrion/universe/ConditionParser1.cpp 2010-12-23 21:20:45 UTC (rev 3912) +++ trunk/FreeOrion/universe/ConditionParser1.cpp 2010-12-23 21:25:22 UTC (rev 3913) @@ -22,6 +22,7 @@ ParamLabel probability_label("probability"); ParamLabel distance_label("distance"); ParamLabel jumps_label("jumps"); +ParamLabel property_label("property"); rule<Scanner, ConditionClosure::context_t> condition1_p; Modified: trunk/FreeOrion/universe/ConditionParser2.cpp =================================================================== --- trunk/FreeOrion/universe/ConditionParser2.cpp 2010-12-23 21:20:45 UTC (rev 3912) +++ trunk/FreeOrion/universe/ConditionParser2.cpp 2010-12-23 21:25:22 UTC (rev 3913) @@ -21,6 +21,7 @@ extern ParamLabel probability_label; extern ParamLabel distance_label; extern ParamLabel jumps_label; +extern ParamLabel property_label; rule<Scanner, ConditionClosure::context_t> condition2_p; @@ -62,11 +63,15 @@ member3 int_ref_2; }; - struct NumberOfClosure : boost::spirit::classic::closure<NumberOfClosure, Condition::ConditionBase*, ValueRef::ValueRefBase<int>*, Condition::ConditionBase*> + struct SortedNumberOfClosure : boost::spirit::classic::closure<SortedNumberOfClosure, Condition::ConditionBase*, + ValueRef::ValueRefBase<int>*, Condition::ConditionBase*, + std::string, Condition::SortingMethod> { member1 this_; member2 number; member3 condition; + member4 property_name; + member5 sorting_method; }; struct StringClosure : boost::spirit::classic::closure<StringClosure, Condition::ConditionBase*, std::string> @@ -133,7 +138,7 @@ typedef rule<Scanner, IntRefConditionClosure::context_t> IntRefConditionRule; typedef rule<Scanner, IntRefIntRefConditionClosure::context_t> IntRefIntRefConditionRule; typedef rule<Scanner, IntRefIntRefClosure::context_t> IntRefIntRefRule; - typedef rule<Scanner, NumberOfClosure::context_t> NumberOfRule; + typedef rule<Scanner, SortedNumberOfClosure::context_t> SortedNumberOfRule; typedef rule<Scanner, StringClosure::context_t> StringRule; typedef rule<Scanner, ConditionParamClosure::context_t> ConditionParamRule; typedef rule<Scanner, StarTypeClosure::context_t> StarTypeRule; @@ -149,7 +154,7 @@ IntRefConditionRule within_starlane_jumps; IntRefIntRefConditionRule number; IntRefIntRefRule turn; - NumberOfRule number_of; + SortedNumberOfRule number_of; StringRule has_special; ConditionParamRule contains; ConditionParamRule contained_by; @@ -198,10 +203,20 @@ [turn.this_ = new_<Condition::Turn>(turn.int_ref_2, turn.int_ref_1)]; number_of = - (str_p("numberof") - >> number_label >> int_expr_p[number_of.number = arg1] - >> condition_label >> condition_p[number_of.condition = arg1]) - [number_of.this_ = new_<Condition::NumberOf>(number_of.number, number_of.condition)]; + ( ((str_p("numberof") + >> number_label >> int_expr_p[number_of.number = arg1] + >> condition_label >> condition_p[number_of.condition = arg1]) + [number_of.this_ = new_<Condition::SortedNumberOf>(number_of.number, number_of.condition, + val("dummy"), Condition::SORT_RANDOM)]) + | ((str_p("maximumnumberof")[number_of.sorting_method = val(Condition::SORT_MAX)] + | str_p("minimumnumberof")[number_of.sorting_method = val(Condition::SORT_MIN)] + | str_p("modenumberof")[number_of.sorting_method = val(Condition::SORT_MODE)]) + >> number_label >> int_expr_p[number_of.number = arg1] + >> property_label >> (!(variable_container >> ".") >> double_variable_final) + [number_of.property_name = construct_<std::string>(arg1, arg2)] + >> condition_label >> condition_p[number_of.condition = arg1])) + [number_of.this_ = new_<Condition::SortedNumberOf>(number_of.number, number_of.condition, + number_of.property_name, number_of.sorting_method)]; has_special = (str_p("hasspecial") |
From: <geo...@us...> - 2010-12-24 05:35:15
|
Revision: 3914 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3914&view=rev Author: geoffthemedio Date: 2010-12-24 05:35:09 +0000 (Fri, 24 Dec 2010) Log Message: ----------- Reworked SortedNumberOf to use a ValueRef as the sorting key rather than a property. This is more flexible and less work to implement (I don't need to reimplement the property-getting code that's already in ValueRef::Variable<T>). It's potentially confusing, though, as the meaning of "Target" can be a different object at different points of a nested ValueRef and Condition structure, as in each case "Target" will refer to the local condition match, and not the Target or potential target / match of an enclosing ValueRef or Condition. Modified Paths: -------------- trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/Condition.h trunk/FreeOrion/universe/ConditionParser1.cpp trunk/FreeOrion/universe/ConditionParser2.cpp Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2010-12-23 21:25:22 UTC (rev 3913) +++ trunk/FreeOrion/universe/Condition.cpp 2010-12-24 05:35:09 UTC (rev 3914) @@ -216,31 +216,54 @@ } } } + + /** */ + void TransferSortedObjects(unsigned int number, const ValueRef::ValueRefBase<double>* sort_key, + Condition::SortingMethod sorting_method, + Condition::ObjectSet& from_set, Condition::ObjectSet& to_set) + { + // handle random case, which doesn't need sorting key + if (sorting_method == Condition::SORT_RANDOM) { + TransferRandomObjects(number, from_set, to_set); + return; + } + + // get sort key values for all objects in from_set + + // sort them + + // pick max / min / most common values + + // pick objects in from set that match / don't match + } } Condition::SortedNumberOf::SortedNumberOf(const ValueRef::ValueRefBase<int>* number, - const ConditionBase* condition, - const std::string& property_name, - SortingMethod sorting_method) : + const ConditionBase* condition) : m_number(number), - m_condition(condition), - m_property_name(::detail::TokenizeDottedReference(property_name)), - m_sorting_method(sorting_method) -{} + m_sort_key(0), + m_sorting_method(Condition::SORT_RANDOM), + m_condition(condition) +{ + Logger().debugStream() << Dump(); +} Condition::SortedNumberOf::SortedNumberOf(const ValueRef::ValueRefBase<int>* number, - const ConditionBase* condition, - const std::vector<std::string>& property_name, - SortingMethod sorting_method) : + const ValueRef::ValueRefBase<double>* sort_key, + SortingMethod sorting_method, + const ConditionBase* condition) : m_number(number), - m_condition(condition), - m_property_name(), - m_sorting_method(sorting_method) -{} + m_sort_key(sort_key), + m_sorting_method(sorting_method), + m_condition(condition) +{ + Logger().debugStream() << Dump(); +} Condition::SortedNumberOf::~SortedNumberOf() { delete m_number; + delete m_sort_key; delete m_condition; } @@ -254,14 +277,8 @@ ObjectSet matched_non_targets; m_condition->Eval(source, matched_non_targets, non_targets, NON_TARGETS); - switch (m_sorting_method) { - case SORT_RANDOM: - // transfer the indicated number of matched_non_targets to targets - TransferRandomObjects(number, matched_non_targets, targets); - break; - default: - break; - } + // transfer the indicated number of matched_non_targets to targets + TransferSortedObjects(number, m_sort_key, m_sorting_method, matched_non_targets, targets); // move remainder of matched_non_targets back to non_targets non_targets.insert(matched_non_targets.begin(), matched_non_targets.end()); @@ -276,14 +293,7 @@ ObjectSet matched_targets = targets; targets.clear(); - switch (m_sorting_method) { - case SORT_RANDOM: - // transfer desired number of matched_targets back to targets set - TransferRandomObjects(number, matched_targets, targets); - break; - default: - break; - } + TransferSortedObjects(number, m_sort_key, m_sorting_method, matched_targets, targets); // move remainder to non_targets set non_targets.insert(matched_targets.begin(), matched_targets.end()); @@ -293,13 +303,49 @@ std::string Condition::SortedNumberOf::Description(bool negated/* = false*/) const { - std::string value_str = ValueRef::ConstantExpr(m_number) ? lexical_cast<std::string>(m_number->Dump()) : m_number->Description(); - std::string description_str = "DESC_NUMBER_OF"; - if (negated) - description_str += "_NOT"; - return str(FlexibleFormat(UserString(description_str)) - % value_str - % m_condition->Description()); + std::string number_str = ValueRef::ConstantExpr(m_number) ? lexical_cast<std::string>(m_number->Dump()) : m_number->Description(); + + if (m_sorting_method == SORT_RANDOM) { + std::string description_str = "DESC_NUMBER_OF"; + if (negated) + description_str += "_NOT"; + return str(FlexibleFormat(UserString(description_str)) + % number_str + % m_condition->Description()); + } else { + std::string sort_key_str = ValueRef::ConstantExpr(m_sort_key) ? lexical_cast<std::string>(m_sort_key->Dump()) : m_sort_key->Description(); + + std::string description_str, temp; + switch (m_sorting_method) { + case SORT_MAX: + temp = "DESC_MAX_NUMBER_OF"; + if (negated) + temp += "_NOT"; + description_str = UserString(temp); + break; + + case SORT_MIN: + temp = "DESC_MIN_NUMBER_OF"; + if (negated) + temp += "_NOT"; + description_str = UserString(temp); + break; + + case SORT_MODE: + temp = "DESC_MODE_NUMBER_OF"; + if (negated) + temp += "_NOT"; + description_str = UserString(temp); + break; + default: + break; + } + + return str(FlexibleFormat(UserString(description_str)) + % number_str + % sort_key_str + % m_condition->Description()); + } } std::string Condition::SortedNumberOf::Dump() const @@ -315,19 +361,13 @@ case SORT_MODE: retval += "ModeNumberOf"; break; default: - retval += "?NumberOf"; break; + retval += "??NumberOf??"; break; } retval += " number = " + m_number->Dump(); - if (m_sorting_method != SORT_RANDOM) { - retval += " property = "; - for (std::vector<std::string>::const_iterator it = m_property_name.begin(); it != m_property_name.end(); ++it) { - if (it != m_property_name.begin()) - retval += "."; - retval += *it; - } - } + if (m_sort_key) + retval += " sortby = " + m_sort_key->Dump(); retval += " condition =\n"; ++g_indent; Modified: trunk/FreeOrion/universe/Condition.h =================================================================== --- trunk/FreeOrion/universe/Condition.h 2010-12-23 21:25:22 UTC (rev 3913) +++ trunk/FreeOrion/universe/Condition.h 2010-12-24 05:35:09 UTC (rev 3914) @@ -27,9 +27,10 @@ }; enum SortingMethod { - SORT_MAX, ///< Objects with the largest property value will be selected - SORT_MIN, ///< Objects with the smallest property value will be selected - SORT_MODE, ///< Objects with the most common property value will be selected + SORT_MAX, ///< Objects with the largest sort key will be selected + SORT_MIN, ///< Objects with the smallest sort key will be selected + SORT_MODE, ///< Objects with the most common sort key will be selected + SORT_MODE_NOT, ///< Objects with the most common sort key will be excluded. Useful for implementing SORT_MODE SORT_RANDOM ///< Objects will be selected randomly, without consideration of property values }; @@ -139,27 +140,27 @@ * selected preferentially. */ struct Condition::SortedNumberOf : public Condition::ConditionBase { + /** Sorts randomly, without considering a sort key. */ SortedNumberOf(const ValueRef::ValueRefBase<int>* number, - const ConditionBase* condition, - const std::string& property_name, - SortingMethod sorting_method); + const ConditionBase* condition); + /** Sorts according to the specified method, based on the key values + * evaluated for each object. */ + SortedNumberOf(const ValueRef::ValueRefBase<int>* number, + const ValueRef::ValueRefBase<double>* sort_key_ref, + SortingMethod sorting_method, + const ConditionBase* condition); + virtual ~SortedNumberOf(); 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; -protected: - SortedNumberOf(const ValueRef::ValueRefBase<int>* number, - const ConditionBase* condition, - const std::vector<std::string>& property_name, - SortingMethod sorting_method); - private: - const ValueRef::ValueRefBase<int>* m_number; - const ConditionBase* m_condition; - std::vector<std::string> m_property_name; - SortingMethod m_sorting_method; + const ValueRef::ValueRefBase<int>* m_number; + const ValueRef::ValueRefBase<double>* m_sort_key; + SortingMethod m_sorting_method; + const ConditionBase* m_condition; friend class boost::serialization::access; template <class Archive> @@ -812,9 +813,9 @@ { ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(ConditionBase) & BOOST_SERIALIZATION_NVP(m_number) - & BOOST_SERIALIZATION_NVP(m_condition) - & BOOST_SERIALIZATION_NVP(m_property_name) - & BOOST_SERIALIZATION_NVP(m_sorting_method); + & BOOST_SERIALIZATION_NVP(m_sort_key) + & BOOST_SERIALIZATION_NVP(m_sorting_method) + & BOOST_SERIALIZATION_NVP(m_condition); } template <class Archive> Modified: trunk/FreeOrion/universe/ConditionParser1.cpp =================================================================== --- trunk/FreeOrion/universe/ConditionParser1.cpp 2010-12-23 21:25:22 UTC (rev 3913) +++ trunk/FreeOrion/universe/ConditionParser1.cpp 2010-12-24 05:35:09 UTC (rev 3914) @@ -22,7 +22,7 @@ ParamLabel probability_label("probability"); ParamLabel distance_label("distance"); ParamLabel jumps_label("jumps"); -ParamLabel property_label("property"); +ParamLabel sort_key_label("sortby"); rule<Scanner, ConditionClosure::context_t> condition1_p; Modified: trunk/FreeOrion/universe/ConditionParser2.cpp =================================================================== --- trunk/FreeOrion/universe/ConditionParser2.cpp 2010-12-23 21:25:22 UTC (rev 3913) +++ trunk/FreeOrion/universe/ConditionParser2.cpp 2010-12-24 05:35:09 UTC (rev 3914) @@ -21,7 +21,7 @@ extern ParamLabel probability_label; extern ParamLabel distance_label; extern ParamLabel jumps_label; -extern ParamLabel property_label; +extern ParamLabel sort_key_label; rule<Scanner, ConditionClosure::context_t> condition2_p; @@ -64,14 +64,14 @@ }; struct SortedNumberOfClosure : boost::spirit::classic::closure<SortedNumberOfClosure, Condition::ConditionBase*, - ValueRef::ValueRefBase<int>*, Condition::ConditionBase*, - std::string, Condition::SortingMethod> + ValueRef::ValueRefBase<int>*, ValueRef::ValueRefBase<double>*, + Condition::SortingMethod, Condition::ConditionBase*> { member1 this_; member2 number; - member3 condition; - member4 property_name; - member5 sorting_method; + member3 sort_key; + member4 sorting_method; + member5 condition; }; struct StringClosure : boost::spirit::classic::closure<StringClosure, Condition::ConditionBase*, std::string> @@ -203,20 +203,19 @@ [turn.this_ = new_<Condition::Turn>(turn.int_ref_2, turn.int_ref_1)]; number_of = - ( ((str_p("numberof") - >> number_label >> int_expr_p[number_of.number = arg1] - >> condition_label >> condition_p[number_of.condition = arg1]) - [number_of.this_ = new_<Condition::SortedNumberOf>(number_of.number, number_of.condition, - val("dummy"), Condition::SORT_RANDOM)]) - | ((str_p("maximumnumberof")[number_of.sorting_method = val(Condition::SORT_MAX)] + ((str_p("numberof") + >> number_label >> int_expr_p[number_of.number = arg1] + >> condition_label >> condition_p[number_of.condition = arg1]) + [number_of.this_ = new_<Condition::SortedNumberOf>(number_of.number, number_of.condition)]) + + | ( ((str_p("maximumnumberof")[number_of.sorting_method = val(Condition::SORT_MAX)] | str_p("minimumnumberof")[number_of.sorting_method = val(Condition::SORT_MIN)] | str_p("modenumberof")[number_of.sorting_method = val(Condition::SORT_MODE)]) - >> number_label >> int_expr_p[number_of.number = arg1] - >> property_label >> (!(variable_container >> ".") >> double_variable_final) - [number_of.property_name = construct_<std::string>(arg1, arg2)] - >> condition_label >> condition_p[number_of.condition = arg1])) - [number_of.this_ = new_<Condition::SortedNumberOf>(number_of.number, number_of.condition, - number_of.property_name, number_of.sorting_method)]; + >> number_label >> int_expr_p[number_of.number = arg1] + >> sort_key_label >> double_expr_p[number_of.sort_key = arg1] + >> condition_label >> condition_p[number_of.condition = arg1]) + [number_of.this_ = new_<Condition::SortedNumberOf>(number_of.number, number_of.sort_key, + number_of.sorting_method, number_of.condition)]); has_special = (str_p("hasspecial") |
From: <geo...@us...> - 2010-12-26 11:45:10
|
Revision: 3925 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3925&view=rev Author: geoffthemedio Date: 2010-12-26 11:45:04 +0000 (Sun, 26 Dec 2010) Log Message: ----------- Added (untested) DistanceToSource property to objects in content scripting. Modified Paths: -------------- trunk/FreeOrion/universe/ValueRef.cpp trunk/FreeOrion/universe/ValueRefParser.cpp Modified: trunk/FreeOrion/universe/ValueRef.cpp =================================================================== --- trunk/FreeOrion/universe/ValueRef.cpp 2010-12-26 08:29:02 UTC (rev 3924) +++ trunk/FreeOrion/universe/ValueRef.cpp 2010-12-26 11:45:04 UTC (rev 3925) @@ -438,6 +438,11 @@ Empire* empire = Empires().Lookup(*object->Owners().begin()); return empire->ResourceStockpile(RE_FOOD); } + } else if (boost::iequals(property_name, "DistanceToSource")) { + double delta_x = object->X() - source->X(); + double delta_y = object->Y() - source->Y(); + return std::sqrt(delta_x * delta_x + delta_y * delta_y); + } else { throw std::runtime_error("Attempted to read a non-double value \"" + ReconstructName(m_property_name, m_source_ref) + "\" using a ValueRef of type double."); } Modified: trunk/FreeOrion/universe/ValueRefParser.cpp =================================================================== --- trunk/FreeOrion/universe/ValueRefParser.cpp 2010-12-26 08:29:02 UTC (rev 3924) +++ trunk/FreeOrion/universe/ValueRefParser.cpp 2010-12-26 11:45:04 UTC (rev 3925) @@ -24,7 +24,8 @@ | "maxdefense" | "defense" | "maxstructure" | "structure" | "supply" | "stealth" | "detection" | "foodconsumption" | "battlespeed" | "starlanespeed" - | "tradestockpile" | "mineralstockpile" | "foodstockpile"; + | "tradestockpile" | "mineralstockpile" | "foodstockpile" + | "distancetosource"; SimpleRule string_variable_final = str_p("name") | "species" | "buildingtype" | "focus"; |
From: <geo...@us...> - 2010-12-27 20:39:59
|
Revision: 3933 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3933&view=rev Author: geoffthemedio Date: 2010-12-27 20:39:52 +0000 (Mon, 27 Dec 2010) Log Message: ----------- -Fixed a crash bug where a starlane added between a system and itself would mess up the graph used for pathfinding. -Commented out some debug output related to visibility turn history tracking. Modified Paths: -------------- trunk/FreeOrion/universe/System.cpp trunk/FreeOrion/universe/Universe.cpp Modified: trunk/FreeOrion/universe/System.cpp =================================================================== --- trunk/FreeOrion/universe/System.cpp 2010-12-27 03:44:27 UTC (rev 3932) +++ trunk/FreeOrion/universe/System.cpp 2010-12-27 20:39:52 UTC (rev 3933) @@ -465,15 +465,16 @@ void System::AddStarlane(int id) { - if (!HasStarlaneTo(id)) { + if (!HasStarlaneTo(id) && id != this->ID()) { m_starlanes_wormholes[id] = false; StateChangedSignal(); + Logger().debugStream() << "System " << this->Dump() << " added starlane to system " << id; } } void System::AddWormhole(int id) { - if (!HasWormholeTo(id)) { + if (!HasWormholeTo(id) && id != this->ID()) { m_starlanes_wormholes[id] = true; StateChangedSignal(); } Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2010-12-27 03:44:27 UTC (rev 3932) +++ trunk/FreeOrion/universe/Universe.cpp 2010-12-27 20:39:52 UTC (rev 3933) @@ -2001,7 +2001,7 @@ vis_turn_map[VIS_FULL_VISIBILITY] = current_turn; } } - Logger().debugStream() << " ... Setting empire " << empire_id << " object " << full_object->Name() << " (" << object_id << ") vis " << vis << " (and higher) turn to " << current_turn; + //Logger().debugStream() << " ... Setting empire " << empire_id << " object " << full_object->Name() << " (" << object_id << ") vis " << vis << " (and higher) turn to " << current_turn; } else { Logger().errorStream() << "Universe::UpdateEmpireLatestKnownObjectsAndVisibilityTurns() found invalid visibility for object with id " << object_id << " by empire with id " << empire_id; continue; @@ -2189,6 +2189,9 @@ for (System::const_lane_iterator it = system1->begin_lanes(); it != system1->end_lanes(); ++it) { // get id in universe of system at other end of lane int lane_dest_id = it->first; + // skip null lanes + if (lane_dest_id == system1_id) + continue; // get m_graph_impl->m_system_graph index for this system std::map<int, int>::iterator reverse_lookup_map_it = system_id_graph_index_reverse_lookup_map.find(lane_dest_id); |
From: <geo...@us...> - 2010-12-29 20:32:20
|
Revision: 3943 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3943&view=rev Author: geoffthemedio Date: 2010-12-29 20:32:14 +0000 (Wed, 29 Dec 2010) Log Message: ----------- Reimplemented Condition::And, Condition::Or and Condition::Not with Match instead of Eval, so that they can support a valid root candidate in their context to pass to subconditions. (It still remains to actually set the root candidate, though...) Modified Paths: -------------- trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/Condition.h Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2010-12-29 18:47:02 UTC (rev 3942) +++ trunk/FreeOrion/universe/Condition.cpp 2010-12-29 20:32:14 UTC (rev 3943) @@ -2618,66 +2618,17 @@ } } -void Condition::And::Eval(const ScriptingContext& parent_context, ObjectSet& matches, ObjectSet& non_matches, SearchDomain search_domain/* = NON_MATCHES*/) const +bool Condition::And::Match(const ScriptingContext& local_context) const { - //std::cout << "And::Eval: input matches:" << std::endl; - //for (ObjectSet::const_iterator it = matches.begin(); it != matches.end(); ++it) - // std::cout << "... " << (*it)->TypeName() << " " << (*it)->Name() << std::endl; - //std::cout << std::endl; - - //std::cout << "And::Eval: input non_matches:" << std::endl; - //for (ObjectSet::const_iterator it = non_matches.begin(); it != non_matches.end(); ++it) - // std::cout << "... " << (*it)->TypeName() << " " << (*it)->Name() << std::endl; - //std::cout << std::endl; - - // And does not have a valid local candidate to be matched - // before the subcondition is evaluated, so the local context that is - // passed to the subcondition needs to have a null local candidate. - const UniverseObject* no_object(0); - ScriptingContext local_context(parent_context, no_object); - - - if (search_domain == NON_MATCHES) { - ObjectSet partly_checked_non_matches; - - // move items in non_matches set that pass first operand condition into - // partly_checked_non_targets set - m_operands[0]->Eval(local_context, partly_checked_non_matches, non_matches, NON_MATCHES); - - //std::cout << "And::Eval: non_target input objects meeting first condition: " << m_operands[0]->Dump() << std::endl; - //for (ObjectSet::const_iterator it = partly_checked_non_targets.begin(); it != partly_checked_non_targets.end(); ++it) - // std::cout << "... " << (*it)->TypeName() << " " << (*it)->Name() << std::endl; - //std::cout << std::endl; - - // move items that don't pass one of the other conditions back to non_matches - for (unsigned int i = 1; i < m_operands.size(); ++i) { - if (partly_checked_non_matches.empty()) break; - m_operands[i]->Eval(local_context, partly_checked_non_matches, non_matches, MATCHES); - - //std::cout << "And::Eval: non_target input objects also meeting " << i + 1 <<"th condition: " << m_operands[i]->Dump() << std::endl; - //for (ObjectSet::const_iterator it = partly_checked_non_targets.begin(); it != partly_checked_non_targets.end(); ++it) - // std::cout << "... " << (*it)->TypeName() << " " << (*it)->Name() << std::endl; - //std::cout << std::endl; - } - - // merge items that passed all operand conditions into matches - matches.insert(partly_checked_non_matches.begin(), partly_checked_non_matches.end()); - - // items already in matches set are not checked, and remain in matches set even if - // they don't match one of the operand conditions - - } else /*(search_domain == MATCHES)*/ { - // check all operand conditions on all objects in the matches set, moving those - // that don't pass a condition to the non-matches set - - for (unsigned int i = 0; i < m_operands.size(); ++i) { - if (matches.empty()) break; - m_operands[i]->Eval(local_context, matches, non_matches, MATCHES); - } - - // items already in non_matches set are not checked, and remain in non_matches set - // even if they pass all operand conditions + ObjectSet non_match; + ObjectSet match; match.insert(local_context.condition_local_candidate); + // candidate must match all subconditions + for (std::vector<const ConditionBase*>::const_iterator it = m_operands.begin(); it != m_operands.end(); ++it) { + (*it)->Eval(local_context, match, non_match, MATCHES); + if (match.empty()) + return false; } + return true; } std::string Condition::And::Description(bool negated/* = false*/) const @@ -2725,48 +2676,17 @@ } } -void Condition::Or::Eval(const ScriptingContext& parent_context, ObjectSet& matches, ObjectSet& non_matches, SearchDomain search_domain/* = NON_MATCHES*/) const +bool Condition::Or::Match(const ScriptingContext& local_context) const { - // Or does not have a valid local candidate to be matched - // before the subcondition is evaluated, so the local context that is - // passed to the subcondition needs to have a null local candidate. - const UniverseObject* no_object(0); - ScriptingContext local_context(parent_context, no_object); - - - if (search_domain == NON_MATCHES) { - // check each item in the non-matches set against each of the operand conditions - // if a non-candidate item matches an operand condition, move the item to the - // matches set. - - for (unsigned int i = 0; i < m_operands.size(); ++i) { - if (non_matches.empty()) break; - m_operands[i]->Eval(local_context, matches, non_matches, NON_MATCHES); - } - - // items already in matches set are not checked and remain in the - // matches set even if they fail all the operand conditions - - } else { - ObjectSet partly_checked_matches; - - // move items in matches set the fail the first operand condition into - // partly_checked_targets set - m_operands[0]->Eval(local_context, matches, partly_checked_matches, MATCHES); - - // move items that pass any of the other conditions back into matches - for (unsigned int i = 1; i < m_operands.size(); ++i) { - if (partly_checked_matches.empty()) break; - m_operands[i]->Eval(local_context, matches, partly_checked_matches, NON_MATCHES); - } - - // merge items that failed all operand conditions into non_matches - non_matches.insert(partly_checked_matches.begin(), partly_checked_matches.end()); - - // items already in non_matches set are not checked and remain in - // non_matches set even if they pass one or more of the operand - // conditions + ObjectSet non_match; non_match.insert(local_context.condition_local_candidate); + ObjectSet match; + // candidate must match at least one subcondition + for (std::vector<const ConditionBase*>::const_iterator it = m_operands.begin(); it != m_operands.end(); ++it) { + (*it)->Eval(local_context, match, non_match); + if (non_match.empty()) + return true; } + return false; } std::string Condition::Or::Description(bool negated/* = false*/) const @@ -2812,23 +2732,12 @@ delete m_operand; } -void Condition::Not::Eval(const ScriptingContext& parent_context, ObjectSet& matches, ObjectSet& non_matches, SearchDomain search_domain/* = NON_MATCHES*/) const +bool Condition::Not::Match(const ScriptingContext& local_context) const { - // Not does not have a valid local candidate to be matched - // before the subcondition is evaluated, so the local context that is - // passed to the subcondition needs to have a null local candidate. - const UniverseObject* no_object(0); - ScriptingContext local_context(parent_context, no_object); - - if (search_domain == NON_MATCHES) { - // search non_matches set for items that don't meet the operand - // condition, and move those to the matches set - m_operand->Eval(local_context, non_matches, matches, MATCHES); // swapping order of matches and non_matches set parameters and MATCHES / NON_MATCHES search domain effects NOT on requested search domain - } else { - // search matches set for items that meet the operand condition - // condition, and move those to the non_matches set - m_operand->Eval(local_context, non_matches, matches, NON_MATCHES); - } + ObjectSet non_match; non_match.insert(local_context.condition_local_candidate); + ObjectSet match; + m_operand->Eval(local_context, match, non_match); + return match.empty(); } std::string Condition::Not::Description(bool negated/* = false*/) const Modified: trunk/FreeOrion/universe/Condition.h =================================================================== --- trunk/FreeOrion/universe/Condition.h 2010-12-29 18:47:02 UTC (rev 3942) +++ trunk/FreeOrion/universe/Condition.h 2010-12-29 20:32:14 UTC (rev 3943) @@ -774,11 +774,12 @@ { And(const std::vector<const ConditionBase*>& operands); virtual ~And(); - virtual void Eval(const ScriptingContext& parent_context, Condition::ObjectSet& matches, Condition::ObjectSet& non_matches, SearchDomain search_domain = NON_MATCHES) const; virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; private: + virtual bool Match(const ScriptingContext& local_context) const; + std::vector<const ConditionBase*> m_operands; friend class boost::serialization::access; @@ -791,11 +792,12 @@ { Or(const std::vector<const ConditionBase*>& operands); virtual ~Or(); - virtual void Eval(const ScriptingContext& parent_context, Condition::ObjectSet& matches, Condition::ObjectSet& non_matches, SearchDomain search_domain = NON_MATCHES) const; virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; private: + virtual bool Match(const ScriptingContext& local_context) const; + std::vector<const ConditionBase*> m_operands; friend class boost::serialization::access; @@ -808,14 +810,12 @@ { Not(const ConditionBase* operand); virtual ~Not(); - virtual void Eval(const ScriptingContext& parent_context, - Condition::ObjectSet& matches, - Condition::ObjectSet& non_matches, - SearchDomain search_domain = NON_MATCHES) const; virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; private: + virtual bool Match(const ScriptingContext& local_context) const; + const ConditionBase* m_operand; friend class boost::serialization::access; |
From: <geo...@us...> - 2011-02-12 08:58:40
|
Revision: 3970 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3970&view=rev Author: geoffthemedio Date: 2011-02-12 08:58:34 +0000 (Sat, 12 Feb 2011) Log Message: ----------- Added initial ScriptingContext when evaluating ShipDesign and BuildingType Location conditions, so that Source references (the empire's capitol) will function. Modified Paths: -------------- trunk/FreeOrion/universe/Building.cpp trunk/FreeOrion/universe/ShipDesign.cpp Modified: trunk/FreeOrion/universe/Building.cpp =================================================================== --- trunk/FreeOrion/universe/Building.cpp 2011-02-09 22:57:14 UTC (rev 3969) +++ trunk/FreeOrion/universe/Building.cpp 2011-02-12 08:58:34 UTC (rev 3970) @@ -8,6 +8,7 @@ #include "Enums.h" #include "Parser.h" #include "ParserUtil.h" +#include "ValueRef.h" #include "../Empire/Empire.h" #include "../Empire/EmpireManager.h" #include "../util/MultiplayerCommon.h" @@ -307,10 +308,12 @@ Logger().debugStream() << "BuildingType::ProductionLocation: Unable to get pointer to empire " << empire_id; return false; } + const UniverseObject* capitol = objects.Object(empire->CapitolID()); + ScriptingContext sc(capitol); Condition::ObjectSet potential_targets; potential_targets.insert(location); Condition::ObjectSet matched_targets; - m_location->Eval(matched_targets, potential_targets); + m_location->Eval(sc, matched_targets, potential_targets); return !matched_targets.empty(); } Modified: trunk/FreeOrion/universe/ShipDesign.cpp =================================================================== --- trunk/FreeOrion/universe/ShipDesign.cpp 2011-02-09 22:57:14 UTC (rev 3969) +++ trunk/FreeOrion/universe/ShipDesign.cpp 2011-02-12 08:58:34 UTC (rev 3970) @@ -1124,6 +1124,8 @@ Logger().debugStream() << "ShipDesign::ProductionLocation: Unable to get pointer to empire " << empire_id; return false; } + const UniverseObject* capitol = objects.Object(empire->CapitolID()); + ScriptingContext sc(capitol); locations.insert(loc); @@ -1133,7 +1135,7 @@ Logger().errorStream() << "ShipDesign::ProductionLocation ShipDesign couldn't get its own hull with name " << m_hull; return false; } - hull->Location()->Eval(locations, non_locations, Condition::MATCHES); + hull->Location()->Eval(sc, locations, non_locations, Condition::MATCHES); if (locations.empty()) return false; @@ -1148,7 +1150,7 @@ Logger().errorStream() << "ShipDesign::ProductionLocation ShipDesign couldn't get part with name " << part_name; return false; } - part->Location()->Eval(locations, non_locations, Condition::MATCHES); + part->Location()->Eval(sc, locations, non_locations, Condition::MATCHES); if (locations.empty()) return false; } |
From: <geo...@us...> - 2011-07-14 07:50:40
|
Revision: 4043 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4043&view=rev Author: geoffthemedio Date: 2011-07-14 07:50:33 +0000 (Thu, 14 Jul 2011) Log Message: ----------- Made location conditions more robust, to handle case where there is no useful capitol object for an empire, but attempting to use the potential build location or any other object owned by the empire as the condition source object, which is just used to give the condition script access to which empire that is. Modified Paths: -------------- trunk/FreeOrion/universe/Building.cpp trunk/FreeOrion/universe/ShipDesign.cpp Modified: trunk/FreeOrion/universe/Building.cpp =================================================================== --- trunk/FreeOrion/universe/Building.cpp 2011-07-14 04:39:35 UTC (rev 4042) +++ trunk/FreeOrion/universe/Building.cpp 2011-07-14 07:50:33 UTC (rev 4043) @@ -317,9 +317,29 @@ Logger().debugStream() << "BuildingType::ProductionLocation: Unable to get pointer to empire " << empire_id; return false; } - const UniverseObject* capitol = objects.Object(empire->CapitolID()); - ScriptingContext sc(capitol); + // get a source object, which is owned by the empire with the passed-in + // empire id. this is used in conditions to reference which empire is + // doing the building. Ideally this will be the capitol, but any object + // owned by the empire will work. + const UniverseObject* source = objects.Object(empire->CapitolID()); + if (!source && location->OwnedBy(empire_id)) + source = location; + // still no valid source?! scan through all objects to find one owned by this empire + if (!source) { + for (ObjectMap::const_iterator obj_it = objects.const_begin(); obj_it != objects.const_end(); ++obj_it) { + if (obj_it->second->OwnedBy(empire_id)) { + source = obj_it->second; + break; + } + } + } + // if this empire doesn't own ANYTHING, then how is it building anyway? + if (!source) + return false; + + ScriptingContext sc(source); + Condition::ObjectSet potential_targets; potential_targets.insert(location); Condition::ObjectSet matched_targets; m_location->Eval(sc, matched_targets, potential_targets); Modified: trunk/FreeOrion/universe/ShipDesign.cpp =================================================================== --- trunk/FreeOrion/universe/ShipDesign.cpp 2011-07-14 04:39:35 UTC (rev 4042) +++ trunk/FreeOrion/universe/ShipDesign.cpp 2011-07-14 07:50:33 UTC (rev 4043) @@ -1114,21 +1114,41 @@ Condition::ObjectSet locations; Condition::ObjectSet non_locations; - ObjectMap& objects = GetMainObjectMap(); + const ObjectMap& objects = GetMainObjectMap(); - UniverseObject* loc = objects.Object(location_id); - if (!loc) return false; + const UniverseObject* location = objects.Object(location_id); + if (!location) return false; Empire* empire = Empires().Lookup(empire_id); if (!empire) { Logger().debugStream() << "ShipDesign::ProductionLocation: Unable to get pointer to empire " << empire_id; return false; } - const UniverseObject* capitol = objects.Object(empire->CapitolID()); - ScriptingContext sc(capitol); - locations.insert(loc); + // get a source object, which is owned by the empire with the passed-in + // empire id. this is used in conditions to reference which empire is + // doing the producing. Ideally this will be the capitol, but any object + // owned by the empire will work. + const UniverseObject* source = objects.Object(empire->CapitolID()); + if (!source && location->OwnedBy(empire_id)) + source = location; + // still no valid source?! scan through all objects to find one owned by this empire + if (!source) { + for (ObjectMap::const_iterator obj_it = objects.const_begin(); obj_it != objects.const_end(); ++obj_it) { + if (obj_it->second->OwnedBy(empire_id)) { + source = obj_it->second; + break; + } + } + } + // if this empire doesn't own ANYTHING, then how is it producing anyway? + if (!source) + return false; + ScriptingContext sc(source); + + locations.insert(location); + // apply hull location conditions to potential location const HullType* hull = GetHull(); if (!hull) { |
From: <geo...@us...> - 2011-07-16 20:06:04
|
Revision: 4048 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4048&view=rev Author: geoffthemedio Date: 2011-07-16 20:05:58 +0000 (Sat, 16 Jul 2011) Log Message: ----------- -Fixed bug with JumpsBetweenObjects in Condition.cpp that was passed non-system object ids to Universe::LeastJumpsPath which could lead to crashes when finding the jumps between non-system objects. -Added a no-parameter constructor to the Homeworld condition. The condition already deals with the case where no species names are passed in, and this allows it to be used more easily. Modified Paths: -------------- trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/Condition.h Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2011-07-16 16:37:21 UTC (rev 4047) +++ trunk/FreeOrion/universe/Condition.cpp 2011-07-16 20:05:58 UTC (rev 4048) @@ -733,6 +733,10 @@ /////////////////////////////////////////////////////////// // Homeworld // /////////////////////////////////////////////////////////// +Condition::Homeworld::Homeworld() : + m_names() +{} + Condition::Homeworld::Homeworld(const std::vector<const ValueRef::ValueRefBase<std::string>*>& names) : m_names(names) {} @@ -2204,7 +2208,7 @@ if (system_one && system_two) { // both condition-matching object and candidate are / in systems. // can just find the shortest path between the two systems - std::pair<std::list<int>, double> path = GetUniverse().LeastJumpsPath(one->ID(), two->ID()); + std::pair<std::list<int>, double> path = GetUniverse().LeastJumpsPath(system_one->ID(), system_two->ID()); if (!path.first.empty()) // if path.first is empty, no path exists between the systems return static_cast<int>(path.first.size()); @@ -2213,8 +2217,8 @@ if (const Fleet* fleet = FleetFromObject(two)) { // other object is a fleet that is between systems // need to check shortest path from systems on either side of starlane fleet is on - std::pair<std::list<int>, double> path1 = GetUniverse().LeastJumpsPath(one->ID(), fleet->PreviousSystemID()); - std::pair<std::list<int>, double> path2 = GetUniverse().LeastJumpsPath(one->ID(), fleet->NextSystemID()); + std::pair<std::list<int>, double> path1 = GetUniverse().LeastJumpsPath(system_one->ID(), fleet->PreviousSystemID()); + std::pair<std::list<int>, double> path2 = GetUniverse().LeastJumpsPath(system_one->ID(), fleet->NextSystemID()); if (int jumps = static_cast<int>(std::max(path1.first.size(), path2.first.size()))) return jumps - 1; } @@ -2224,8 +2228,8 @@ if (const Fleet* fleet = FleetFromObject(two)) { // other object is a fleet that is between systems // need to check shortest path from systems on either side of starlane fleet is on - std::pair<std::list<int>, double> path1 = GetUniverse().LeastJumpsPath(two->ID(), fleet->PreviousSystemID()); - std::pair<std::list<int>, double> path2 = GetUniverse().LeastJumpsPath(two->ID(), fleet->NextSystemID()); + std::pair<std::list<int>, double> path1 = GetUniverse().LeastJumpsPath(system_two->ID(), fleet->PreviousSystemID()); + std::pair<std::list<int>, double> path2 = GetUniverse().LeastJumpsPath(system_two->ID(), fleet->NextSystemID()); if (int jumps = static_cast<int>(std::max(path1.first.size(), path2.first.size()))) return jumps - 1; } Modified: trunk/FreeOrion/universe/Condition.h =================================================================== --- trunk/FreeOrion/universe/Condition.h 2011-07-16 16:37:21 UTC (rev 4047) +++ trunk/FreeOrion/universe/Condition.h 2011-07-16 20:05:58 UTC (rev 4048) @@ -248,6 +248,7 @@ * any species in the current game Universe. */ struct Condition::Homeworld : Condition::ConditionBase { + Homeworld(); Homeworld(const std::vector<const ValueRef::ValueRefBase<std::string>*>& names); virtual ~Homeworld(); virtual std::string Description(bool negated = false) const; |
From: <geo...@us...> - 2011-07-20 15:03:00
|
Revision: 4065 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4065&view=rev Author: geoffthemedio Date: 2011-07-20 15:02:54 +0000 (Wed, 20 Jul 2011) Log Message: ----------- Semi-experimental reworking of a condition (EmpireAffiliation in this case) to optimize its evaluation in cases where a parameter's value (empire id in this case) doesn't depend on the object being matched. This is done by checking if the ValueRef is constant (hard-coded single value, not an object reference like Source.Owner or LocalCandidate.Owner), and if it is constant, only evaluating the ValueRef once and then matching all candidates against the single result. This is in contrast to standard condition evaluation, where the ValueRef could depend on the source or candidate objects, so is evaluated once per candidate object. There aren't currently any hard-coded (ie. not Source.Owner) uses of EmpireAffiliation, so this hasn't been thoroughly tested, but it seems to still work for Source.Owner references. In future, it would be better to also check for ValueRef and subconditions that don't depend on the local candidate object (but may still depend on the source, which doesn't change for each candidate being tested), and match those only once, even if they aren't actually constant in the ValueRef sense (no object reference at all). Modified Paths: -------------- trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/Condition.h Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2011-07-19 08:48:07 UTC (rev 4064) +++ trunk/FreeOrion/universe/Condition.cpp 2011-07-20 15:02:54 UTC (rev 4065) @@ -604,6 +604,69 @@ delete m_empire_id; } +namespace { + bool EmpireAffiliationSimpleMatch(const UniverseObject* candidate, int empire_id, + EmpireAffiliationType affiliation, bool exclusive) + { + if (!candidate) + return false; + + switch (affiliation) { + case AFFIL_SELF: + if (exclusive) { + // candidate object owned only by specified empire + return candidate->WhollyOwnedBy(empire_id); + } else { + // candidate object owned by specified empire, and possibly others + return candidate->OwnedBy(empire_id); + } + break; + case AFFIL_ENEMY: + if (exclusive) { + // candidate has an owner, but isn't owned by specified empire + return (!candidate->Owners().empty() && !candidate->OwnedBy(empire_id)); + } else { + // at least one of candidate's owners is not specified empire, but specified empire may also own candidate + return (candidate->Owners().size() > 1 || + (!candidate->Owners().empty() && !candidate->OwnedBy(empire_id)) + ); + } + break; + case AFFIL_ALLY: + // TODO + break; + default: + break; + } + return false; + } +} + +void Condition::EmpireAffiliation::Eval(const ScriptingContext& parent_context, ObjectSet& matches, ObjectSet& non_matches, SearchDomain search_domain/* = NON_MATCHES*/) const +{ + if (ValueRef::ConstantExpr(m_empire_id)) { + // evaluate empire id once, and use to check all candidate objects + int empire_id = m_empire_id->Eval(); + + ObjectSet& from_set = search_domain == MATCHES ? matches : non_matches; + ObjectSet& to_set = search_domain == MATCHES ? non_matches : matches; + ObjectSet::iterator it = from_set.begin(); + ObjectSet::iterator end_it = from_set.end(); + for ( ; it != end_it; ) { + ObjectSet::iterator temp = it++; + bool match = EmpireAffiliationSimpleMatch(*temp, empire_id, m_affiliation, m_exclusive); + if ((search_domain == MATCHES && !match) || (search_domain == NON_MATCHES && match)) { + to_set.insert(*temp); + from_set.erase(temp); + } + } + + } else { + // re-evaluate empire id for each candidate object + Condition::ConditionBase::Eval(parent_context, matches, non_matches, search_domain); + } +} + std::string Condition::EmpireAffiliation::Description(bool negated/* = false*/) const { std::string value_str = ValueRef::ConstantExpr(m_empire_id) ? @@ -648,34 +711,7 @@ int empire_id = m_empire_id->Eval(local_context); - switch (m_affiliation) { - case AFFIL_SELF: - if (m_exclusive) { - // candidate object owned only by specified empire - return candidate->WhollyOwnedBy(empire_id); - } else { - // candidate object owned by specified empire, and possibly others - return candidate->OwnedBy(empire_id); - } - break; - case AFFIL_ENEMY: - if (m_exclusive) { - // candidate has an owner, but isn't owned by specified empire - return (!candidate->Owners().empty() && !candidate->OwnedBy(empire_id)); - } else { - // at least one of candidate's owners is not specified empire, but specified empire may also own candidate - return (candidate->Owners().size() > 1 || - (!candidate->Owners().empty() && !candidate->OwnedBy(empire_id)) - ); - } - break; - case AFFIL_ALLY: - // TODO - break; - default: - break; - } - return false; + return EmpireAffiliationSimpleMatch(candidate, empire_id, m_affiliation, m_exclusive); } /////////////////////////////////////////////////////////// Modified: trunk/FreeOrion/universe/Condition.h =================================================================== --- trunk/FreeOrion/universe/Condition.h 2011-07-19 08:48:07 UTC (rev 4064) +++ trunk/FreeOrion/universe/Condition.h 2011-07-20 15:02:54 UTC (rev 4065) @@ -199,6 +199,7 @@ { EmpireAffiliation(const ValueRef::ValueRefBase<int>* empire_id, EmpireAffiliationType affiliation, bool exclusive); virtual ~EmpireAffiliation(); + virtual void Eval(const ScriptingContext& parent_context, Condition::ObjectSet& matches, Condition::ObjectSet& non_matches, SearchDomain search_domain = NON_MATCHES) const; virtual std::string Description(bool negated = false) const; virtual std::string Dump() const; |
From: <geo...@us...> - 2011-08-09 17:36:18
|
Revision: 4113 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4113&view=rev Author: geoffthemedio Date: 2011-08-09 17:36:12 +0000 (Tue, 09 Aug 2011) Log Message: ----------- -Added PC_TROOPS part type enum for troop carrying parts. -Added METER_TROOPS and METER_MAX_TROOPS enums for troops on ships / planets. Modified Paths: -------------- trunk/FreeOrion/universe/Enums.h trunk/FreeOrion/universe/ParserUtil.cpp trunk/FreeOrion/universe/ShipDesign.cpp trunk/FreeOrion/universe/ShipDesign.h Modified: trunk/FreeOrion/universe/Enums.h =================================================================== --- trunk/FreeOrion/universe/Enums.h 2011-08-07 22:45:37 UTC (rev 4112) +++ trunk/FreeOrion/universe/Enums.h 2011-08-09 17:36:12 UTC (rev 4113) @@ -172,6 +172,7 @@ METER_MAX_SHIELD, METER_MAX_STRUCTURE, METER_MAX_DEFENSE, + METER_MAX_TROOPS, METER_POPULATION, METER_HEALTH, @@ -186,6 +187,7 @@ METER_SHIELD, METER_STRUCTURE, METER_DEFENSE, + METER_TROOPS, METER_FOOD_CONSUMPTION, METER_SUPPLY, @@ -225,6 +227,7 @@ GG_ENUM_MAP_INSERT(METER_MAX_SHIELD) GG_ENUM_MAP_INSERT(METER_MAX_STRUCTURE) GG_ENUM_MAP_INSERT(METER_MAX_DEFENSE) + GG_ENUM_MAP_INSERT(METER_MAX_TROOPS) GG_ENUM_MAP_INSERT(METER_POPULATION) GG_ENUM_MAP_INSERT(METER_HEALTH) @@ -239,6 +242,7 @@ GG_ENUM_MAP_INSERT(METER_SHIELD) GG_ENUM_MAP_INSERT(METER_STRUCTURE) GG_ENUM_MAP_INSERT(METER_DEFENSE) + GG_ENUM_MAP_INSERT(METER_TROOPS) GG_ENUM_MAP_INSERT(METER_FOOD_CONSUMPTION) GG_ENUM_MAP_INSERT(METER_SUPPLY) @@ -472,6 +476,7 @@ PC_POINT_DEFENSE, ///< short range direct weapons, good against fighters or incoming missiles, bad against ships PC_SHIELD, ///< energy-based defense PC_ARMOUR, ///< defensive material on hull of ship + PC_TROOPS, ///< ground troops, used to conquer planets PC_DETECTION, ///< range of vision and seeing through stealth PC_STEALTH, ///< hiding from enemies PC_FUEL, ///< distance that can be traveled away from resupply @@ -490,6 +495,7 @@ GG_ENUM_MAP_INSERT(PC_POINT_DEFENSE) GG_ENUM_MAP_INSERT(PC_SHIELD) GG_ENUM_MAP_INSERT(PC_ARMOUR) + GG_ENUM_MAP_INSERT(PC_TROOPS) GG_ENUM_MAP_INSERT(PC_DETECTION) GG_ENUM_MAP_INSERT(PC_STEALTH) GG_ENUM_MAP_INSERT(PC_FUEL) Modified: trunk/FreeOrion/universe/ParserUtil.cpp =================================================================== --- trunk/FreeOrion/universe/ParserUtil.cpp 2011-08-07 22:45:37 UTC (rev 4112) +++ trunk/FreeOrion/universe/ParserUtil.cpp 2011-08-09 17:36:12 UTC (rev 4113) @@ -133,6 +133,7 @@ ("pointdefense", PC_POINT_DEFENSE) ("shield", PC_SHIELD) ("armour", PC_ARMOUR) + ("troops", PC_TROOPS) ("detection", PC_DETECTION) ("stealth", PC_STEALTH) ("fuel", PC_FUEL) Modified: trunk/FreeOrion/universe/ShipDesign.cpp =================================================================== --- trunk/FreeOrion/universe/ShipDesign.cpp 2011-08-07 22:45:37 UTC (rev 4112) +++ trunk/FreeOrion/universe/ShipDesign.cpp 2011-08-09 17:36:12 UTC (rev 4113) @@ -483,6 +483,9 @@ m_effects.push_back(IncreaseMeter(METER_CAPACITY, m_name, stats.m_capacity)); break; } + case PC_TROOPS: + m_effects.push_back(IncreaseMeter(METER_CAPACITY, m_name, boost::get<double>(m_stats))); + break; case PC_SHIELD: m_effects.push_back(IncreaseMeter(METER_MAX_SHIELD, boost::get<double>(m_stats))); break; Modified: trunk/FreeOrion/universe/ShipDesign.h =================================================================== --- trunk/FreeOrion/universe/ShipDesign.h 2011-08-07 22:45:37 UTC (rev 4112) +++ trunk/FreeOrion/universe/ShipDesign.h 2011-08-09 17:36:12 UTC (rev 4113) @@ -21,7 +21,7 @@ } class Empire; -/** Part stats for the PC_SHORT_RANGE and PC_POINT_DEFENSE part types. */ +/** Part stats for the PC_SHORT_RANGE and PC_POINT_DEFENSE part classes. */ struct DirectFireStats { DirectFireStats(); @@ -45,7 +45,7 @@ } }; -/** Part stats for the PC_MISSILES part type. */ +/** Part stats for the PC_MISSILES part class. */ struct LRStats { LRStats(); @@ -77,7 +77,7 @@ } }; -/** Part stats for the PC_FIGHTERS part type. */ +/** Part stats for the PC_FIGHTERS part class. */ struct FighterStats { FighterStats(); |
From: <geo...@us...> - 2011-08-10 03:36:25
|
Revision: 4118 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4118&view=rev Author: geoffthemedio Date: 2011-08-10 03:36:18 +0000 (Wed, 10 Aug 2011) Log Message: ----------- -Added TroopCapacity and HasTroops functions to ShipDesign, in the manner of ColonyCapacity and CanColonize. -Removed METER_TROOPS modifying of a part-specific meter from PartType handling of PC_TROOPS part class. Troop capacity instead treated as just a stat, not a meter, like colonization capacity. Modified Paths: -------------- trunk/FreeOrion/universe/ShipDesign.cpp trunk/FreeOrion/universe/ShipDesign.h Modified: trunk/FreeOrion/universe/ShipDesign.cpp =================================================================== --- trunk/FreeOrion/universe/ShipDesign.cpp 2011-08-10 03:33:56 UTC (rev 4117) +++ trunk/FreeOrion/universe/ShipDesign.cpp 2011-08-10 03:36:18 UTC (rev 4118) @@ -483,9 +483,6 @@ m_effects.push_back(IncreaseMeter(METER_CAPACITY, m_name, stats.m_capacity)); break; } - case PC_TROOPS: - m_effects.push_back(IncreaseMeter(METER_CAPACITY, m_name, boost::get<double>(m_stats))); - break; case PC_SHIELD: m_effects.push_back(IncreaseMeter(METER_MAX_SHIELD, boost::get<double>(m_stats))); break; @@ -733,6 +730,10 @@ return 0.0; // as of this writing, hulls don't have colonist capacity } +double HullType::TroopCapacity() const { + return 0.0; // as of this writing, hulls don't have troop capacity +} + double HullType::Detection() const { return 0.0; // as of this writing, hulls don't have detection ability } @@ -1009,6 +1010,9 @@ double ShipDesign::ColonyCapacity() const { return m_colony_capacity; } +double ShipDesign::TroopCapacity() const +{ return m_troop_capacity; } + double ShipDesign::Stealth() const { return m_stealth; } @@ -1093,6 +1097,10 @@ return (m_colony_capacity > 0.0); } +bool ShipDesign::HasTroops() const { + return (m_troop_capacity > 0.0); +} + bool ShipDesign::IsArmed() const { return m_is_armed; } @@ -1278,6 +1286,7 @@ m_producible = hull->Producible(); m_detection = hull->Detection(); m_colony_capacity = hull->ColonyCapacity(); + m_troop_capacity = hull->TroopCapacity(); m_stealth = hull->Stealth(); m_fuel = hull->Fuel(); m_shields = hull->Shields(); @@ -1342,6 +1351,9 @@ case PC_COLONY: m_colony_capacity += boost::get<double>(part->Stats()); break; + case PC_TROOPS: + m_troop_capacity += boost::get<double>(part->Stats()); + break; case PC_STEALTH: m_stealth += boost::get<double>(part->Stats()); break; Modified: trunk/FreeOrion/universe/ShipDesign.h =================================================================== --- trunk/FreeOrion/universe/ShipDesign.h 2011-08-10 03:33:56 UTC (rev 4117) +++ trunk/FreeOrion/universe/ShipDesign.h 2011-08-10 03:36:18 UTC (rev 4118) @@ -293,6 +293,7 @@ double Structure() const; ///< returns structure of hull double Shields() const; ///< returns shields of hull double ColonyCapacity() const; ///< returns colonist capacity of hull + double TroopCapacity() const; ///< returns the troop capacity of hull double Detection() const; ///< returns detection ability of hull double ProductionCost() const; ///< returns total cost of hull @@ -415,9 +416,11 @@ double Fuel() const; ///< returns the max fuel capacity of this design double Detection() const; ///< returns the detection ability of this design double ColonyCapacity() const; ///< returns the colonization capacity of this design + double TroopCapacity() const; ///< returns the troop capacity of this design double Stealth() const; ///< returns the stealth of this design bool CanColonize() const; + bool HasTroops() const; bool IsArmed() const; bool IsMonster() const; @@ -505,6 +508,7 @@ bool m_is_armed; double m_detection; double m_colony_capacity; + double m_troop_capacity; double m_stealth; double m_fuel; double m_shields; |
From: <geo...@us...> - 2011-08-10 05:52:02
|
Revision: 4121 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4121&view=rev Author: geoffthemedio Date: 2011-08-10 05:51:56 +0000 (Wed, 10 Aug 2011) Log Message: ----------- Parsing for troop meters Modified Paths: -------------- trunk/FreeOrion/universe/EffectParser.cpp trunk/FreeOrion/universe/ValueRef.cpp trunk/FreeOrion/universe/ValueRefParser.cpp Modified: trunk/FreeOrion/universe/EffectParser.cpp =================================================================== --- trunk/FreeOrion/universe/EffectParser.cpp 2011-08-10 05:32:40 UTC (rev 4120) +++ trunk/FreeOrion/universe/EffectParser.cpp 2011-08-10 05:51:56 UTC (rev 4121) @@ -279,6 +279,7 @@ | str_p("maxshield")[set_meter.meter = val(METER_MAX_SHIELD)] | str_p("maxstructure")[set_meter.meter = val(METER_MAX_STRUCTURE)] | str_p("maxdefense")[set_meter.meter = val(METER_MAX_DEFENSE)] + | str_p("maxtroops")[set_meter.meter = val(METER_MAX_TROOPS)] | str_p("population")[set_meter.meter = val(METER_POPULATION)] | str_p("health")[set_meter.meter = val(METER_HEALTH)] @@ -293,6 +294,7 @@ | str_p("shield")[set_meter.meter = val(METER_SHIELD)] | str_p("structure")[set_meter.meter = val(METER_STRUCTURE)] | str_p("defense")[set_meter.meter = val(METER_DEFENSE)] + | str_p("troops")[set_meter.meter = val(METER_TROOPS)] | str_p("foodconsumption")[set_meter.meter = val(METER_FOOD_CONSUMPTION)] | str_p("supply")[set_meter.meter = val(METER_SUPPLY)] Modified: trunk/FreeOrion/universe/ValueRef.cpp =================================================================== --- trunk/FreeOrion/universe/ValueRef.cpp 2011-08-10 05:32:40 UTC (rev 4120) +++ trunk/FreeOrion/universe/ValueRef.cpp 2011-08-10 05:51:56 UTC (rev 4121) @@ -488,6 +488,10 @@ return object->InitialMeterValue(METER_MAX_DEFENSE); } else if (boost::iequals(property_name, "Defense")) { return object->InitialMeterValue(METER_DEFENSE); + } else if (boost::iequals(property_name, "MaxTroops")) { + return object->InitialMeterValue(METER_MAX_TROOPS); + } else if (boost::iequals(property_name, "Troops")) { + return object->InitialMeterValue(METER_TROOPS); } else if (boost::iequals(property_name, "FoodConsumption")) { return object->InitialMeterValue(METER_FOOD_CONSUMPTION); Modified: trunk/FreeOrion/universe/ValueRefParser.cpp =================================================================== --- trunk/FreeOrion/universe/ValueRefParser.cpp 2011-08-10 05:32:40 UTC (rev 4120) +++ trunk/FreeOrion/universe/ValueRefParser.cpp 2011-08-10 05:51:56 UTC (rev 4121) @@ -21,7 +21,8 @@ | "mining" | "targetmining" | "construction" | "targetconstruction" | "population" | "targetpopulation" | "health" | "targethealth" | "maxfuel" | "fuel" | "maxshield" | "shield" - | "maxdefense" | "defense" | "maxstructure" | "structure" + | "maxdefense" | "defense" | "maxtroops" | "troops" + | "maxstructure" | "structure" | "supply" | "stealth" | "detection" | "foodconsumption" | "battlespeed" | "starlanespeed" | "tradestockpile" | "mineralstockpile" | "foodstockpile" |
From: <geo...@us...> - 2011-08-15 17:03:46
|
Revision: 4141 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4141&view=rev Author: geoffthemedio Date: 2011-08-15 17:03:40 +0000 (Mon, 15 Aug 2011) Log Message: ----------- -Added variant constructor for CreateShip effect that takes just a predefined ship design name, and doesn't need ValueRefs for empire id or specie sname. -Modified parsing to allow for the above variant to be used. -Modified CreateShip::Execute to handle cases where no valid empire or species name are specified (such when using the above changes). Modified Paths: -------------- trunk/FreeOrion/universe/Effect.cpp trunk/FreeOrion/universe/Effect.h trunk/FreeOrion/universe/EffectParser.cpp Modified: trunk/FreeOrion/universe/Effect.cpp =================================================================== --- trunk/FreeOrion/universe/Effect.cpp 2011-08-15 03:28:33 UTC (rev 4140) +++ trunk/FreeOrion/universe/Effect.cpp 2011-08-15 17:03:40 UTC (rev 4141) @@ -1147,7 +1147,7 @@ const ValueRef::ValueRefBase<int>* empire_id, const ValueRef::ValueRefBase<std::string>* species_name) : m_design_name(predefined_ship_design_name), - m_design_id(0), + m_design_id(0), // this specifies a null pointer to a ValueRef, not the constant 0 m_empire_id(empire_id), m_species_name(species_name) {} @@ -1161,6 +1161,13 @@ m_species_name(species_name) {} +CreateShip::CreateShip(const std::string& predefined_ship_design_name) : + m_design_name(predefined_ship_design_name), + m_design_id(0), // this specifies a null pointer to a ValueRef, not the constant 0 + m_empire_id(0), // ... + m_species_name(0) // ... +{} + CreateShip::~CreateShip() { delete m_design_id; @@ -1182,7 +1189,6 @@ } int design_id = ShipDesign::INVALID_DESIGN_ID; - if (m_design_id) { design_id = m_design_id->Eval(context); if (!GetShipDesign(design_id)) { @@ -1202,17 +1208,24 @@ return; } - int empire_id = m_empire_id->Eval(context); - Empire* empire = Empires().Lookup(empire_id); - if (!empire) { - Logger().errorStream() << "RemoveOwner::Execute couldn't get empire with id " << empire_id; - return; + int empire_id = ALL_EMPIRES; + Empire* empire(0); // not const Empire* so that empire::NewShipName can be called + if (m_empire_id) { + empire_id = m_empire_id->Eval(context); + empire = Empires().Lookup(empire_id); + if (!empire) { + Logger().errorStream() << "CreateShip::Execute couldn't get empire with id " << empire_id; + return; + } } - std::string species_name = m_species_name->Eval(context); - if (!GetSpecies(species_name)) { - Logger().errorStream() << "CreateShip::Execute couldn't get species with which to create a ship"; - return; + std::string species_name; + if (m_species_name) { + species_name = m_species_name->Eval(context); + if (!species_name.empty() && !GetSpecies(species_name)) { + Logger().errorStream() << "CreateShip::Execute couldn't get species with which to create a ship"; + return; + } } //// possible future modification: try to put new ship into existing fleet if @@ -1229,7 +1242,7 @@ Logger().errorStream() << "CreateShip::Execute couldn't create ship!"; return; } - ship->Rename(empire->NewShipName()); + ship->Rename(empire ? empire->NewShipName() : ship->Design()->Name()); ship->UniverseObject::GetMeter(METER_FUEL)->SetCurrent(Meter::LARGE_VALUE); ship->UniverseObject::GetMeter(METER_SHIELD)->SetCurrent(Meter::LARGE_VALUE); ship->UniverseObject::GetMeter(METER_STRUCTURE)->SetCurrent(Meter::LARGE_VALUE); @@ -1263,9 +1276,11 @@ design_str = UserString(m_design_name); } - std::string species_str = ValueRef::ConstantExpr(m_species_name) ? - UserString(m_species_name->Eval()) : - m_species_name->Description(); + std::string species_str = ""; + if (m_species_name) + species_str = ValueRef::ConstantExpr(m_species_name) ? + UserString(m_species_name->Eval()) : + m_species_name->Description(); return str(FlexibleFormat(UserString("DESC_CREATE_SHIP")) % design_str @@ -1275,14 +1290,17 @@ std::string CreateShip::Dump() const { + std::string retval; if (m_design_id) - return DumpIndent() + "CreateShip design_id = " + m_design_id->Dump() - + " empire = " + m_empire_id->Dump() - + " species_name = " + m_species_name->Dump() + "\n"; + retval = DumpIndent() + "CreateShip design_id = " + m_design_id->Dump(); else - return DumpIndent() + "CreateShip predefined_ship_design_name = \"" + m_design_name + "\"" - + " empire = " + m_empire_id->Dump() - + " species_name = " + m_species_name->Dump() + "\n"; + retval = DumpIndent() + "CreateShip predefined_ship_design_name = \"" + m_design_name + "\""; + if (m_empire_id) + retval += " empire = " + m_empire_id->Dump(); + if (m_species_name) + retval += " species_name = " + m_species_name->Dump(); + retval += "\n"; + return retval; } Modified: trunk/FreeOrion/universe/Effect.h =================================================================== --- trunk/FreeOrion/universe/Effect.h 2011-08-15 03:28:33 UTC (rev 4140) +++ trunk/FreeOrion/universe/Effect.h 2011-08-15 17:03:40 UTC (rev 4141) @@ -404,6 +404,7 @@ CreateShip(const ValueRef::ValueRefBase<int>* ship_design_id, const ValueRef::ValueRefBase<int>* empire_id, const ValueRef::ValueRefBase<std::string>* species_name); + CreateShip(const std::string& predefined_ship_design_name); virtual ~CreateShip(); virtual void Execute(const ScriptingContext& context) const; Modified: trunk/FreeOrion/universe/EffectParser.cpp =================================================================== --- trunk/FreeOrion/universe/EffectParser.cpp 2011-08-15 03:28:33 UTC (rev 4140) +++ trunk/FreeOrion/universe/EffectParser.cpp 2011-08-15 17:03:40 UTC (rev 4141) @@ -424,6 +424,9 @@ [create_ship.this_ = new_<Effect::CreateShip>(create_ship.design_id, create_ship.empire, create_ship.species)]) + | ((str_p("createship") + >> design_name_label >> name_p[create_ship.predefined_design_name = arg1]) + [create_ship.this_ = new_<Effect::CreateShip>(create_ship.predefined_design_name)]) ); move_to = |
From: <geo...@us...> - 2011-08-19 05:24:30
|
Revision: 4171 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4171&view=rev Author: geoffthemedio Date: 2011-08-19 03:49:31 +0000 (Fri, 19 Aug 2011) Log Message: ----------- Grooming Modified Paths: -------------- trunk/FreeOrion/universe/ResourceCenter.cpp trunk/FreeOrion/universe/Ship.cpp Modified: trunk/FreeOrion/universe/ResourceCenter.cpp =================================================================== --- trunk/FreeOrion/universe/ResourceCenter.cpp 2011-08-19 03:48:44 UTC (rev 4170) +++ trunk/FreeOrion/universe/ResourceCenter.cpp 2011-08-19 03:49:31 UTC (rev 4171) @@ -123,7 +123,7 @@ if (target_meter_value > current_meter_value) return std::min(current_meter_value + 1.0, target_meter_value); else if (target_meter_value < current_meter_value) - return std::max(target_meter_value, current_meter_value - 1.0); + return std::max(target_meter_value, current_meter_value - 1.0); else return current_meter_value; } Modified: trunk/FreeOrion/universe/Ship.cpp =================================================================== --- trunk/FreeOrion/universe/Ship.cpp 2011-08-19 03:48:44 UTC (rev 4170) +++ trunk/FreeOrion/universe/Ship.cpp 2011-08-19 03:49:31 UTC (rev 4171) @@ -315,9 +315,8 @@ } double Ship::NextTurnCurrentMeterValue(MeterType type) const { - if (type == INVALID_METER_TYPE || type == METER_FUEL) { - // todo: consider fleet movement or being stationary, which may parly replenish fuel + // todo: consider fleet movement or being stationary, which may parfly replenish fuel // todo: consider fleet passing through or being in a supplied system, which replenishes fuel } else if (type == INVALID_METER_TYPE || type == METER_SUPPLY) { // todo: consider fleet passing through or being in a supplied system, which replenishes supplies |
From: <geo...@us...> - 2011-09-01 18:08:18
|
Revision: 4212 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4212&view=rev Author: geoffthemedio Date: 2011-09-01 18:08:12 +0000 (Thu, 01 Sep 2011) Log Message: ----------- Commented out one debug line in PopCenter and added another in Universe. Modified Paths: -------------- trunk/FreeOrion/universe/PopCenter.cpp trunk/FreeOrion/universe/Universe.cpp Modified: trunk/FreeOrion/universe/PopCenter.cpp =================================================================== --- trunk/FreeOrion/universe/PopCenter.cpp 2011-09-01 18:06:49 UTC (rev 4211) +++ trunk/FreeOrion/universe/PopCenter.cpp 2011-09-01 18:08:12 UTC (rev 4212) @@ -251,7 +251,7 @@ double pop_growth = NextTurnPopGrowth(); // may be negative double new_pop = cur_pop + pop_growth; - Logger().debugStream() << "Planet Pop: " << cur_pop << " growth: " << pop_growth; + //Logger().debugStream() << "Planet Pop: " << cur_pop << " growth: " << pop_growth; GetMeter(METER_HEALTH)->AddToCurrent(NextTurnHealthGrowth()); // change may be negative Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2011-09-01 18:06:49 UTC (rev 4211) +++ trunk/FreeOrion/universe/Universe.cpp 2011-09-01 18:08:12 UTC (rev 4212) @@ -4158,6 +4158,8 @@ BackPropegateObjectMeters(); + Logger().debugStream() << "Re-applying first turn meter effects and updating meters"; + // Re-apply meter effects, so that results depending on meter values can be // re-checked after initial setting of those meter values ApplyMeterEffectsAndUpdateMeters(); |
From: <geo...@us...> - 2011-09-12 04:39:23
|
Revision: 4250 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4250&view=rev Author: geoffthemedio Date: 2011-09-12 04:39:17 +0000 (Mon, 12 Sep 2011) Log Message: ----------- Added variant of CreateShip, with parsing, that takes a predefined design name and empire ID but not species. The species is left empty when this variant is used, similar to specifying speces = "". Modified Paths: -------------- trunk/FreeOrion/universe/Effect.cpp trunk/FreeOrion/universe/Effect.h trunk/FreeOrion/universe/EffectParser.cpp Modified: trunk/FreeOrion/universe/Effect.cpp =================================================================== --- trunk/FreeOrion/universe/Effect.cpp 2011-09-12 04:04:58 UTC (rev 4249) +++ trunk/FreeOrion/universe/Effect.cpp 2011-09-12 04:39:17 UTC (rev 4250) @@ -1163,6 +1163,14 @@ m_species_name(species_name) {} +CreateShip::CreateShip(const std::string& predefined_ship_design_name, + const ValueRef::ValueRefBase<int>* empire_id) : + m_design_name(predefined_ship_design_name), + m_design_id(0), // this specifies a null pointer to a ValueRef, not the constant 0 + m_empire_id(empire_id), + m_species_name(0) // ... +{} + CreateShip::CreateShip(const std::string& predefined_ship_design_name) : m_design_name(predefined_ship_design_name), m_design_id(0), // this specifies a null pointer to a ValueRef, not the constant 0 Modified: trunk/FreeOrion/universe/Effect.h =================================================================== --- trunk/FreeOrion/universe/Effect.h 2011-09-12 04:04:58 UTC (rev 4249) +++ trunk/FreeOrion/universe/Effect.h 2011-09-12 04:39:17 UTC (rev 4250) @@ -404,6 +404,8 @@ CreateShip(const ValueRef::ValueRefBase<int>* ship_design_id, const ValueRef::ValueRefBase<int>* empire_id, const ValueRef::ValueRefBase<std::string>* species_name); + CreateShip(const std::string& predefined_ship_design_name, + const ValueRef::ValueRefBase<int>* empire_id); CreateShip(const std::string& predefined_ship_design_name); virtual ~CreateShip(); Modified: trunk/FreeOrion/universe/EffectParser.cpp =================================================================== --- trunk/FreeOrion/universe/EffectParser.cpp 2011-09-12 04:04:58 UTC (rev 4249) +++ trunk/FreeOrion/universe/EffectParser.cpp 2011-09-12 04:39:17 UTC (rev 4250) @@ -425,6 +425,11 @@ create_ship.empire, create_ship.species)]) | ((str_p("createship") + >> design_name_label >> name_p[create_ship.predefined_design_name = arg1] + >> empire_label >> int_expr_p[create_ship.empire = arg1]) + [create_ship.this_ = new_<Effect::CreateShip>(create_ship.predefined_design_name, + create_ship.empire)]) + | ((str_p("createship") >> design_name_label >> name_p[create_ship.predefined_design_name = arg1]) [create_ship.this_ = new_<Effect::CreateShip>(create_ship.predefined_design_name)]) ); |
From: <geo...@us...> - 2011-09-13 16:28:17
|
Revision: 4259 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4259&view=rev Author: geoffthemedio Date: 2011-09-13 16:28:10 +0000 (Tue, 13 Sep 2011) Log Message: ----------- Added, with parsing, a CreatedOnTurn condition that matches objects that were created on turns within the specified range. Untested. Modified Paths: -------------- trunk/FreeOrion/universe/Condition.cpp trunk/FreeOrion/universe/Condition.h trunk/FreeOrion/universe/ConditionParser3.cpp Modified: trunk/FreeOrion/universe/Condition.cpp =================================================================== --- trunk/FreeOrion/universe/Condition.cpp 2011-09-13 15:33:06 UTC (rev 4258) +++ trunk/FreeOrion/universe/Condition.cpp 2011-09-13 16:28:10 UTC (rev 4259) @@ -1574,6 +1574,100 @@ } /////////////////////////////////////////////////////////// +// CreatedOnTurn // +/////////////////////////////////////////////////////////// +Condition::CreatedOnTurn::CreatedOnTurn(const ValueRef::ValueRefBase<int>* low, + const ValueRef::ValueRefBase<int>* high) : + m_low(low), + m_high(high) +{} + +Condition::CreatedOnTurn::~CreatedOnTurn() +{ + delete m_low; + delete m_high; +} + +namespace { + bool CreatedOnTurnSimpleMatch(const UniverseObject* candidate, int low, int high) + { + return candidate && + low <= candidate->CreationTurn() && + candidate->CreationTurn() < high; + } +} + +void Condition::CreatedOnTurn::Eval(const ScriptingContext& parent_context, ObjectSet& matches, ObjectSet& non_matches, SearchDomain search_domain/* = NON_MATCHES*/) const +{ + bool simple_eval_safe = ((!m_low || m_low->LocalCandidateInvariant()) && + (!m_high || m_high->LocalCandidateInvariant()) && + (parent_context.condition_root_candidate || RootCandidateInvariant())); + if (simple_eval_safe) { + const UniverseObject* no_object(0); + ScriptingContext local_context(parent_context, no_object); + int low = (m_low ? m_low->Eval(local_context) : BEFORE_FIRST_TURN); + int high = (m_high ? m_high->Eval(local_context) : IMPOSSIBLY_LARGE_TURN); + + ObjectSet& from_set = search_domain == MATCHES ? matches : non_matches; + ObjectSet& to_set = search_domain == MATCHES ? non_matches : matches; + ObjectSet::iterator it = from_set.begin(); + ObjectSet::iterator end_it = from_set.end(); + for ( ; it != end_it; ) { + ObjectSet::iterator temp = it++; + bool match = CreatedOnTurnSimpleMatch(*temp, low, high); + if ((search_domain == MATCHES && !match) || (search_domain == NON_MATCHES && match)) { + to_set.insert(*temp); + from_set.erase(temp); + } + } + } else { + // re-evaluate allowed turn range for each candidate object + Condition::ConditionBase::Eval(parent_context, matches, non_matches, search_domain); + } +} + +bool Condition::CreatedOnTurn::RootCandidateInvariant() const +{ return (m_low->RootCandidateInvariant() && m_high->RootCandidateInvariant()); } + +bool Condition::CreatedOnTurn::TargetInvariant() const +{ return (m_low->TargetInvariant() && m_high->TargetInvariant()); } + +std::string Condition::CreatedOnTurn::Description(bool negated/* = false*/) const +{ + std::string low_str = ValueRef::ConstantExpr(m_low) ? + boost::lexical_cast<std::string>(m_low->Eval()) : + m_low->Description(); + std::string high_str = ValueRef::ConstantExpr(m_high) ? + boost::lexical_cast<std::string>(m_high->Eval()) : + m_high->Description(); + std::string description_str = "DESC_CREATED_ON_TURN"; + if (negated) + description_str += "_NOT"; + return str(FlexibleFormat(UserString(description_str)) + % low_str + % high_str); +} + +std::string Condition::CreatedOnTurn::Dump() const +{ + return DumpIndent() + "CreatedOnTurn low = " + m_low->Dump() + " high = " + m_high->Dump() + "\n"; +} + +bool Condition::CreatedOnTurn::Match(const ScriptingContext& local_context) const +{ + const UniverseObject* candidate = local_context.condition_local_candidate; + if (!candidate) { + Logger().errorStream() << "CreatedOnTurn::Match passed no candidate object"; + return false; + } + + double low = std::max(0, m_low->Eval(local_context)); + double high = std::min(m_high->Eval(local_context), IMPOSSIBLY_LARGE_TURN); + + return CreatedOnTurnSimpleMatch(candidate, low, high); +} + +/////////////////////////////////////////////////////////// // Contains // /////////////////////////////////////////////////////////// Condition::Contains::Contains(const ConditionBase* condition) : Modified: trunk/FreeOrion/universe/Condition.h =================================================================== --- trunk/FreeOrion/universe/Condition.h 2011-09-13 15:33:06 UTC (rev 4258) +++ trunk/FreeOrion/universe/Condition.h 2011-09-13 16:28:10 UTC (rev 4259) @@ -80,6 +80,7 @@ struct SortedNumberOf; struct InSystem; struct ObjectID; + struct CreatedOnTurn; } /** The base class for all Conditions. */ @@ -448,6 +449,32 @@ void serialize(Archive& ar, const unsigned int version); }; +/** Matches all objects that were created on turns within the specified range. */ +struct Condition::CreatedOnTurn : public Condition::ConditionBase +{ + CreatedOnTurn(const ValueRef::ValueRefBase<int>* low, const ValueRef::ValueRefBase<int>* high); + virtual ~CreatedOnTurn(); + virtual void Eval(const ScriptingContext& parent_context, Condition::ObjectSet& matches, + Condition::ObjectSet& non_matches, SearchDomain search_domain = NON_MATCHES) const; + void Eval(Condition::ObjectSet& matches, Condition::ObjectSet& non_matches, + SearchDomain search_domain = NON_MATCHES) const { ConditionBase::Eval(matches, non_matches, search_domain); } + virtual bool RootCandidateInvariant() const; + virtual bool TargetInvariant() const; + virtual std::string Description(bool negated = false) const; + virtual std::string Dump() const; + +private: + virtual bool Match(const ScriptingContext& local_context) const; + + const ValueRef::ValueRefBase<int>* m_low; + const ValueRef::ValueRefBase<int>* m_high; + + friend class boost::serialization::access; + template <class Archive> + void serialize(Archive& ar, const unsigned int version); +}; + + /** Matches all objects that contain an object that matches Condition * \a condition. Container objects are Systems, Planets (which contain * Buildings), and Fleets (which contain Ships). */ @@ -1341,6 +1368,14 @@ } template <class Archive> +void Condition::CreatedOnTurn::serialize(Archive& ar, const unsigned int version) +{ + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(ConditionBase) + & BOOST_SERIALIZATION_NVP(m_low) + & BOOST_SERIALIZATION_NVP(m_high); +} + +template <class Archive> void Condition::Contains::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(ConditionBase) Modified: trunk/FreeOrion/universe/ConditionParser3.cpp =================================================================== --- trunk/FreeOrion/universe/ConditionParser3.cpp 2011-09-13 15:33:06 UTC (rev 4258) +++ trunk/FreeOrion/universe/ConditionParser3.cpp 2011-09-13 16:28:10 UTC (rev 4259) @@ -109,6 +109,7 @@ IntRefConditionRule within_starlane_jumps; IntRefIntRefConditionRule number; IntRefIntRefRule turn; + IntRefIntRefRule created_on_turn; SortedNumberOfRule number_of; ConditionParamRule contains; ConditionParamRule contained_by; @@ -143,8 +144,14 @@ (str_p("turn") >> low_label >> int_expr_p[turn.int_ref_2 = arg1] >> high_label >> int_expr_p[turn.int_ref_1 = arg1]) - [turn.this_ = new_<Condition::Turn>(turn.int_ref_2, turn.int_ref_1)]; + [turn.this_ = new_<Condition::CreatedOnTurn>(turn.int_ref_2, turn.int_ref_1)]; + created_on_turn = + (str_p("createdonturn") + >> low_label >> int_expr_p[created_on_turn.int_ref_2 = arg1] + >> high_label >> int_expr_p[created_on_turn.int_ref_1 = arg1]) + [created_on_turn.this_ = new_<Condition::Turn>(created_on_turn.int_ref_2, created_on_turn.int_ref_1)]; + number_of = ((str_p("numberof") >> number_label >> int_expr_p[number_of.number = arg1] @@ -203,6 +210,7 @@ | within_starlane_jumps[condition3_p.this_ = arg1] | number[condition3_p.this_ = arg1] | turn[condition3_p.this_ = arg1] + | created_on_turn[condition3_p.this_ = arg1] | number_of[condition3_p.this_ = arg1] | contains[condition3_p.this_ = arg1] | contained_by[condition3_p.this_ = arg1] |
From: <geo...@us...> - 2011-09-15 06:51:48
|
Revision: 4266 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4266&view=rev Author: geoffthemedio Date: 2011-09-15 06:51:41 +0000 (Thu, 15 Sep 2011) Log Message: ----------- -Added a location condition, presently unused, to Special. -Grooming Modified Paths: -------------- trunk/FreeOrion/universe/Special.cpp trunk/FreeOrion/universe/Special.h trunk/FreeOrion/universe/TopLevelParsers.cpp trunk/FreeOrion/universe/Universe.cpp Modified: trunk/FreeOrion/universe/Special.cpp =================================================================== --- trunk/FreeOrion/universe/Special.cpp 2011-09-14 23:47:09 UTC (rev 4265) +++ trunk/FreeOrion/universe/Special.cpp 2011-09-15 06:51:41 UTC (rev 4266) @@ -115,22 +115,20 @@ ///////////////////////////////////////////////// Special::Special(const std::string& name, const std::string& description, const std::vector<boost::shared_ptr<const Effect::EffectsGroup> > effects, + const Condition::ConditionBase* location, const std::string& graphic) : m_name(name), m_description(description), m_effects(effects), + m_location(location), m_graphic(graphic) {} const std::string& Special::Name() const -{ - return m_name; -} +{ return m_name; } const std::string& Special::Description() const -{ - return m_description; -} +{ return m_description; } std::string Special::Dump() const { @@ -158,26 +156,19 @@ } const std::vector<boost::shared_ptr<const Effect::EffectsGroup> >& Special::Effects() const -{ - return m_effects; -} +{ return m_effects; } +const Condition::ConditionBase* Special::Location() const +{ return m_location; } + const std::string& Special::Graphic() const -{ - return m_graphic; -} +{ return m_graphic; } const Special* GetSpecial(const std::string& name) -{ - return GetSpecialManager().GetSpecial(name); -} +{ return GetSpecialManager().GetSpecial(name); } std::vector<std::string> SpecialNames() -{ - return SpecialManager().SpecialNames(); -} +{ return SpecialManager().SpecialNames(); } const std::set<std::string>& PlanetSpecialNames() -{ - return GetSpecialManager().PlanetSpecialNames(); -} +{ return GetSpecialManager().PlanetSpecialNames(); } Modified: trunk/FreeOrion/universe/Special.h =================================================================== --- trunk/FreeOrion/universe/Special.h 2011-09-14 23:47:09 UTC (rev 4265) +++ trunk/FreeOrion/universe/Special.h 2011-09-15 06:51:41 UTC (rev 4266) @@ -12,6 +12,9 @@ namespace Effect { class EffectsGroup; } +namespace Condition { + struct ConditionBase; +} /** A predefined set of EffectsGroups that can be attached to a UniverseObject * (often referred to as the "source" object). The effects of a Special are @@ -25,24 +28,27 @@ /** basic ctor */ Special(const std::string& name, const std::string& description, const std::vector<boost::shared_ptr<const Effect::EffectsGroup> > effects, + const Condition::ConditionBase* location, const std::string& graphic); //@} /** \name Accessors */ //@{ - const std::string& Name() const; ///< returns the unique name for this type of special - const std::string& Description() const; ///< returns a text description of this type of special - std::string Dump() const; ///< returns a data file format representation of this object + const std::string& Name() const; ///< returns the unique name for this type of special + const std::string& Description() const;///< returns a text description of this type of special + std::string Dump() const; ///< returns a data file format representation of this object const std::vector<boost::shared_ptr<const Effect::EffectsGroup> >& - Effects() const; ///< returns the EffectsGroups that encapsulate the effects that specials of this type have - const std::string& Graphic() const; ///< returns the name of the grapic file for this special + Effects() const; ///< returns the EffectsGroups that encapsulate the effects that specials of this type have + const Condition::ConditionBase* Location() const; ///< returns the condition that determines whether an UniverseObject can have this special applied during universe creation + const std::string& Graphic() const; ///< returns the name of the grapic file for this special //@} private: - std::string m_name; - std::string m_description; + std::string m_name; + std::string m_description; std::vector<boost::shared_ptr<const Effect::EffectsGroup> > - m_effects; - std::string m_graphic; + m_effects; + const Condition::ConditionBase* m_location; + std::string m_graphic; friend class boost::serialization::access; template <class Archive> @@ -58,9 +64,9 @@ /** Returns the names of all "planet specials"; though there are other specials * that may be applied to planets, these are ok to use when generating random - * specials during universe creation. Note that "planet specials" can be - * attached to non-planet UniverseObjects, just like all Specials, and are not - * restricted to use during universe creation. */ + * specials during universe creation. Note that "planet specials" can also be + * attached to non-planet UniverseObjects - like all Specials - and are not + * restricted to use only during universe creation. */ const std::set<std::string>& PlanetSpecialNames(); // template implementations @@ -70,6 +76,7 @@ ar & BOOST_SERIALIZATION_NVP(m_name) & BOOST_SERIALIZATION_NVP(m_description) & BOOST_SERIALIZATION_NVP(m_effects) + & BOOST_SERIALIZATION_NVP(m_location) & BOOST_SERIALIZATION_NVP(m_graphic); } Modified: trunk/FreeOrion/universe/TopLevelParsers.cpp =================================================================== --- trunk/FreeOrion/universe/TopLevelParsers.cpp 2011-09-14 23:47:09 UTC (rev 4265) +++ trunk/FreeOrion/universe/TopLevelParsers.cpp 2011-09-15 06:51:41 UTC (rev 4266) @@ -206,7 +206,7 @@ >> !(effectsgroups_label >> effects_group_vec_p[special_p.effects_groups = arg1]) >> graphic_label >> file_name_p[special_p.graphic = arg1]) [special_p.this_ = new_<Special>(special_p.name, special_p.description, special_p.effects_groups, - special_p.graphic)]; + val(NULL_COND), special_p.graphic)]; focus_type_p = (str_p("focus") Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2011-09-14 23:47:09 UTC (rev 4265) +++ trunk/FreeOrion/universe/Universe.cpp 2011-09-15 06:51:41 UTC (rev 4266) @@ -3164,9 +3164,8 @@ return m_name; } -const std::vector<std::string>& FleetPlan::ShipDesigns() const { - return m_ship_designs; -} +const std::vector<std::string>& FleetPlan::ShipDesigns() const +{ return m_ship_designs; } //////////////////////////////////////// @@ -3189,9 +3188,7 @@ {} MonsterFleetPlan::~MonsterFleetPlan() -{ - delete m_location; -} +{ delete m_location; } double MonsterFleetPlan::SpawnRate() const { return m_spawn_rate; } |
From: <geo...@us...> - 2011-09-16 01:01:21
|
Revision: 4269 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4269&view=rev Author: geoffthemedio Date: 2011-09-16 01:01:15 +0000 (Fri, 16 Sep 2011) Log Message: ----------- Added parsing of an optional location condition to specials. Still not actually used for anything. Modified Paths: -------------- trunk/FreeOrion/universe/Parser.h trunk/FreeOrion/universe/TopLevelParsers.cpp Modified: trunk/FreeOrion/universe/Parser.h =================================================================== --- trunk/FreeOrion/universe/Parser.h 2011-09-16 01:00:13 UTC (rev 4268) +++ trunk/FreeOrion/universe/Parser.h 2011-09-16 01:01:15 UTC (rev 4269) @@ -119,14 +119,16 @@ }; struct SpecialClosure : boost::spirit::classic::closure<SpecialClosure, Special*, std::string, std::string, + Condition::ConditionBase*, std::vector<boost::shared_ptr<const Effect::EffectsGroup> >, std::string> { member1 this_; member2 name; member3 description; - member4 effects_groups; - member5 graphic; + member4 location; + member5 effects_groups; + member6 graphic; }; struct SpeciesClosure : boost::spirit::classic::closure<SpeciesClosure, Species*, std::string, std::string, Modified: trunk/FreeOrion/universe/TopLevelParsers.cpp =================================================================== --- trunk/FreeOrion/universe/TopLevelParsers.cpp 2011-09-16 01:00:13 UTC (rev 4268) +++ trunk/FreeOrion/universe/TopLevelParsers.cpp 2011-09-16 01:01:15 UTC (rev 4269) @@ -191,7 +191,7 @@ eps_p[building_type_p.producible = val(true)]) >> location_label >> condition_p[building_type_p.location = arg1] >> (captureresult_label >> capture_result_p[building_type_p.capture_result = arg1] - | eps_p[building_type_p.capture_result = val(CR_CAPTURE)]) + | eps_p[building_type_p.capture_result = val(CR_CAPTURE)]) >> !(effectsgroups_label >> effects_group_vec_p[building_type_p.effects_groups = arg1]) >> graphic_label >> file_name_p[building_type_p.graphic = arg1]) [building_type_p.this_ = new_<BuildingType>(building_type_p.name, building_type_p.description, @@ -203,10 +203,12 @@ (str_p("special") >> name_label >> name_p[special_p.name = arg1] >> description_label >> name_p[special_p.description = arg1] + >> (location_label >> condition_p[special_p.location = arg1] + | eps_p[special_p.location = val(NULL_COND)]) >> !(effectsgroups_label >> effects_group_vec_p[special_p.effects_groups = arg1]) >> graphic_label >> file_name_p[special_p.graphic = arg1]) [special_p.this_ = new_<Special>(special_p.name, special_p.description, special_p.effects_groups, - val(NULL_COND), special_p.graphic)]; + special_p.location, special_p.graphic)]; focus_type_p = (str_p("focus") |
From: <geo...@us...> - 2011-09-16 01:52:50
|
Revision: 4270 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4270&view=rev Author: geoffthemedio Date: 2011-09-16 01:52:43 +0000 (Fri, 16 Sep 2011) Log Message: ----------- Fixed a probable memory leak by giving Special a destructor to delete its pointer to condition. Modified Paths: -------------- trunk/FreeOrion/universe/Special.cpp trunk/FreeOrion/universe/Special.h Modified: trunk/FreeOrion/universe/Special.cpp =================================================================== --- trunk/FreeOrion/universe/Special.cpp 2011-09-16 01:01:15 UTC (rev 4269) +++ trunk/FreeOrion/universe/Special.cpp 2011-09-16 01:52:43 UTC (rev 4270) @@ -2,6 +2,7 @@ #include "ParserUtil.h" #include "Effect.h" +#include "Condition.h" #include "../util/MultiplayerCommon.h" #include "../util/OptionsDB.h" #include "../util/Directories.h" @@ -124,6 +125,9 @@ m_graphic(graphic) {} +Special::~Special() +{ delete m_location; } + const std::string& Special::Name() const { return m_name; } Modified: trunk/FreeOrion/universe/Special.h =================================================================== --- trunk/FreeOrion/universe/Special.h 2011-09-16 01:01:15 UTC (rev 4269) +++ trunk/FreeOrion/universe/Special.h 2011-09-16 01:52:43 UTC (rev 4270) @@ -30,6 +30,8 @@ const std::vector<boost::shared_ptr<const Effect::EffectsGroup> > effects, const Condition::ConditionBase* location, const std::string& graphic); + + ~Special(); //@} /** \name Accessors */ //@{ |
From: <geo...@us...> - 2011-09-16 07:20:16
|
Revision: 4276 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=4276&view=rev Author: geoffthemedio Date: 2011-09-16 07:20:10 +0000 (Fri, 16 Sep 2011) Log Message: ----------- Added members, getters, and parsing for spawn rate and spawn limit for specials. These aren't yet used for anything. Modified Paths: -------------- trunk/FreeOrion/universe/Parser.h trunk/FreeOrion/universe/Special.cpp trunk/FreeOrion/universe/Special.h trunk/FreeOrion/universe/TopLevelParsers.cpp Modified: trunk/FreeOrion/universe/Parser.h =================================================================== --- trunk/FreeOrion/universe/Parser.h 2011-09-16 07:17:47 UTC (rev 4275) +++ trunk/FreeOrion/universe/Parser.h 2011-09-16 07:20:10 UTC (rev 4276) @@ -119,16 +119,18 @@ }; struct SpecialClosure : boost::spirit::classic::closure<SpecialClosure, Special*, std::string, std::string, - Condition::ConditionBase*, + double, int, Condition::ConditionBase*, std::vector<boost::shared_ptr<const Effect::EffectsGroup> >, std::string> { member1 this_; member2 name; member3 description; - member4 location; - member5 effects_groups; - member6 graphic; + member4 spawn_rate; + member5 spawn_limit; + member6 location; + member7 effects_groups; + member8 graphic; }; struct SpeciesClosure : boost::spirit::classic::closure<SpeciesClosure, Species*, std::string, std::string, Modified: trunk/FreeOrion/universe/Special.cpp =================================================================== --- trunk/FreeOrion/universe/Special.cpp 2011-09-16 07:17:47 UTC (rev 4275) +++ trunk/FreeOrion/universe/Special.cpp 2011-09-16 07:20:10 UTC (rev 4276) @@ -116,11 +116,14 @@ ///////////////////////////////////////////////// Special::Special(const std::string& name, const std::string& description, const std::vector<boost::shared_ptr<const Effect::EffectsGroup> > effects, + double spawn_rate, int spawn_limit, const Condition::ConditionBase* location, const std::string& graphic) : m_name(name), m_description(description), m_effects(effects), + m_spawn_rate(spawn_rate), + m_spawn_limit(spawn_limit), m_location(location), m_graphic(graphic) {} Modified: trunk/FreeOrion/universe/Special.h =================================================================== --- trunk/FreeOrion/universe/Special.h 2011-09-16 07:17:47 UTC (rev 4275) +++ trunk/FreeOrion/universe/Special.h 2011-09-16 07:20:10 UTC (rev 4276) @@ -28,8 +28,9 @@ /** basic ctor */ Special(const std::string& name, const std::string& description, const std::vector<boost::shared_ptr<const Effect::EffectsGroup> > effects, - const Condition::ConditionBase* location, - const std::string& graphic); + double spawn_rate = 1.0, int spawn_limit = 99999, + const Condition::ConditionBase* location = 0, + const std::string& graphic = ""); ~Special(); //@} @@ -40,6 +41,8 @@ std::string Dump() const; ///< returns a data file format representation of this object const std::vector<boost::shared_ptr<const Effect::EffectsGroup> >& Effects() const; ///< returns the EffectsGroups that encapsulate the effects that specials of this type have + double SpawnRate() const; + int SpawnLimit() const; const Condition::ConditionBase* Location() const; ///< returns the condition that determines whether an UniverseObject can have this special applied during universe creation const std::string& Graphic() const; ///< returns the name of the grapic file for this special //@} @@ -49,6 +52,8 @@ std::string m_description; std::vector<boost::shared_ptr<const Effect::EffectsGroup> > m_effects; + double m_spawn_rate; + int m_spawn_limit; const Condition::ConditionBase* m_location; std::string m_graphic; @@ -78,6 +83,8 @@ ar & BOOST_SERIALIZATION_NVP(m_name) & BOOST_SERIALIZATION_NVP(m_description) & BOOST_SERIALIZATION_NVP(m_effects) + & BOOST_SERIALIZATION_NVP(m_spawn_rate) + & BOOST_SERIALIZATION_NVP(m_spawn_limit) & BOOST_SERIALIZATION_NVP(m_location) & BOOST_SERIALIZATION_NVP(m_graphic); } Modified: trunk/FreeOrion/universe/TopLevelParsers.cpp =================================================================== --- trunk/FreeOrion/universe/TopLevelParsers.cpp 2011-09-16 07:17:47 UTC (rev 4275) +++ trunk/FreeOrion/universe/TopLevelParsers.cpp 2011-09-16 07:20:10 UTC (rev 4276) @@ -203,11 +203,16 @@ (str_p("special") >> name_label >> name_p[special_p.name = arg1] >> description_label >> name_p[special_p.description = arg1] + >> ((spawn_rate_label >> real_p[special_p.spawn_rate = arg1]) | + eps_p[special_p.spawn_rate = val(1.0)]) + >> ((spawn_limit_label >> int_p[special_p.spawn_limit = arg1]) | + eps_p[special_p.spawn_limit = val(9999)]) >> (location_label >> condition_p[special_p.location = arg1] | eps_p[special_p.location = val(NULL_COND)]) >> !(effectsgroups_label >> effects_group_vec_p[special_p.effects_groups = arg1]) >> graphic_label >> file_name_p[special_p.graphic = arg1]) [special_p.this_ = new_<Special>(special_p.name, special_p.description, special_p.effects_groups, + special_p.spawn_rate, special_p.spawn_limit, special_p.location, special_p.graphic)]; focus_type_p = |