Author: dragonking
Date: Sat Jun 28 10:47:15 2008
New Revision: 27547
URL: http://svn.gna.org/viewcvs/wesnoth?rev=27547&view=rev
Log:
* added variant_iterator to iterate over variant elements
* added key_value_pair class, used while iterating over variant_list and
variant_map type
* fixed bug in map, filter and find formula functions, which caused game to
crash when optional parameter was specified and self was used within a
function formula
* changed choose, filter, find and map funcions, to use new variant_iterator
so they work for both variant_lists and variant_maps now
* added tolist formula function
Modified:
trunk/changelog
trunk/src/formula.cpp
trunk/src/formula_function.cpp
trunk/src/formula_function.hpp
trunk/src/variant.cpp
trunk/src/variant.hpp
Modified: trunk/changelog
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/changelog?rev=27547&r1=27546&r2=27547&view=diff
==============================================================================
--- trunk/changelog (original)
+++ trunk/changelog Sat Jun 28 10:47:15 2008
@@ -1,5 +1,9 @@
Version 1.5.1+svn:
* campaigns:
+ * formula AI:
+ * Added variant_iterator to iterate over variant elements
+ * Modified choose, filter, find and map functions to use variant_iterator,
+ so they work correctly with a variant_map type
* language and i18n:
* updated translations: Finnish, German, Greek, Lithuanian, Serbian
* miscellaneous and bug fixes:
Modified: trunk/src/formula.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/formula.cpp?rev=27547&r1=27546&r2=27547&view=diff
==============================================================================
--- trunk/src/formula.cpp (original)
+++ trunk/src/formula.cpp Sat Jun 28 10:47:15 2008
@@ -34,7 +34,7 @@
}
map_formula_callable::map_formula_callable(
- const formula_callable* fallback) : fallback_(fallback)
+ const formula_callable* fallback) : formula_callable(false),
fallback_(fallback)
{}
map_formula_callable& map_formula_callable::add(const std::string& key,
Modified: trunk/src/formula_function.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/formula_function.cpp?rev=27547&r1=27546&r2=27547&view=diff
==============================================================================
--- trunk/src/formula_function.cpp (original)
+++ trunk/src/formula_function.cpp Sat Jun 28 10:47:15 2008
@@ -285,29 +285,68 @@
}
};
+class tolist_function : public function_expression {
+public:
+ explicit tolist_function(const args_list& args)
+ : function_expression("values", args, 1, 1)
+ {}
+
+private:
+ variant execute(const formula_callable& variables) const {
+ const variant var = args()[0]->evaluate(variables);
+
+ std::vector<variant> tmp;
+
+ variant_iterator it = var.get_iterator();
+ for(it = var.begin(); it != var.end(); ++it) {
+ tmp.push_back( *it );
+ }
+
+ return variant( &tmp );
+ }
+};
+
+
+
class choose_function : public function_expression {
public:
explicit choose_function(const args_list& args)
- : function_expression("choose", args, 2, 2)
+ : function_expression("choose", args, 2, 3)
{}
private:
variant execute(const formula_callable& variables) const {
const variant items = args()[0]->evaluate(variables);
- int max_index = -1;
variant max_value;
- for(size_t n = 0; n != items.num_elements(); ++n) {
- const variant val =
args()[1]->evaluate(formula_variant_callable_with_backup(items[n], variables));
- if(max_index == -1 || val > max_value) {
- max_index = n;
- max_value = val;
- }
- }
-
- if(max_index == -1) {
+ variant_iterator it = items.get_iterator();
+ variant_iterator max = variant_iterator();
+
+ if(args().size() == 2) {
+ for(it = items.begin(); it != items.end(); ++it) {
+ const variant val =
args().back()->evaluate(formula_variant_callable_with_backup(*it, variables));
+ if(max == variant_iterator() || val >
max_value) {
+ max = it;
+ max_value = val;
+ }
+ }
+ } else {
+ map_formula_callable self_callable;
+ self_callable.add_ref();
+ const std::string self =
args()[1]->evaluate(variables).as_string();
+ for(it = items.begin(); it != items.end(); ++it) {
+ self_callable.add(self, *it);
+ const variant val =
args().back()->evaluate(formula_callable_with_backup(self_callable,
formula_variant_callable_with_backup(*it, variables)));
+ if(max == variant_iterator() || val >
max_value) {
+ max = it;
+ max_value = val;
+ }
+ }
+ }
+
+ if(max == variant_iterator() ) {
return variant();
} else {
- return items[max_index];
+ return *max;
}
}
};
@@ -388,28 +427,41 @@
{}
private:
variant execute(const formula_callable& variables) const {
- std::vector<variant> vars;
+ std::vector<variant> list_vars;
+ std::map<variant,variant> map_vars;
+
const variant items = args()[0]->evaluate(variables);
+
+ variant_iterator it = items.get_iterator();
+
if(args().size() == 2) {
- for(size_t n = 0; n != items.num_elements(); ++n) {
- const variant val =
args()[1]->evaluate(formula_variant_callable_with_backup(items[n], variables));
+ for(it = items.begin(); it != items.end(); ++it) {
+ const variant val =
args()[1]->evaluate(formula_variant_callable_with_backup(*it, variables));
if(val.as_bool()) {
- vars.push_back(items[n]);
+ if (items.is_map() )
+ map_vars[
(*it).get_member("key") ] = (*it).get_member("value");
+ else
+ list_vars.push_back(*it);
}
}
} else {
map_formula_callable self_callable;
+ self_callable.add_ref();
const std::string self =
args()[1]->evaluate(variables).as_string();
- for(size_t n = 0; n != items.num_elements(); ++n) {
- self_callable.add(self, items[n]);
- const variant val =
args()[2]->evaluate(formula_callable_with_backup(self_callable,
formula_variant_callable_with_backup(items[n], variables)));
+ for(it = items.begin(); it != items.end(); ++it) {
+ self_callable.add(self, *it);
+ const variant val =
args()[2]->evaluate(formula_callable_with_backup(self_callable,
formula_variant_callable_with_backup(*it, variables)));
if(val.as_bool()) {
- vars.push_back(items[n]);
- }
- }
- }
-
- return variant(&vars);
+ if (items.is_map() )
+ map_vars[
(*it).get_member("key") ] = (*it).get_member("value");
+ else
+ list_vars.push_back(*it);
+ }
+ }
+ }
+ if (items.is_map() )
+ return variant(&map_vars);
+ return variant(&list_vars);
}
};
@@ -423,21 +475,23 @@
variant execute(const formula_callable& variables) const {
const variant items = args()[0]->evaluate(variables);
+ variant_iterator it = items.get_iterator();
if(args().size() == 2) {
- for(size_t n = 0; n != items.num_elements(); ++n) {
- const variant val =
args()[1]->evaluate(formula_variant_callable_with_backup(items[n], variables));
+ for(it = items.begin(); it != items.end(); ++it) {
+ const variant val =
args()[1]->evaluate(formula_variant_callable_with_backup(*it, variables));
if(val.as_bool()) {
- return items[n];
+ return *it;
}
}
} else {
map_formula_callable self_callable;
+ self_callable.add_ref();
const std::string self =
args()[1]->evaluate(variables).as_string();
- for(size_t n = 0; n != items.num_elements(); ++n) {
- self_callable.add(self, items[n]);
- const variant val =
args().back()->evaluate(formula_callable_with_backup(self_callable,
formula_variant_callable_with_backup(items[n], variables)));
+ for(it = items.begin(); it != items.end(); ++it){
+ self_callable.add(self, *it);
+ const variant val =
args().back()->evaluate(formula_callable_with_backup(self_callable,
formula_variant_callable_with_backup(*it, variables)));
if(val.as_bool()) {
- return items[n];
+ return *it;
}
}
}
@@ -453,25 +507,35 @@
{}
private:
variant execute(const formula_callable& variables) const {
- std::vector<variant> vars;
+ std::vector<variant> list_vars;
+ std::map<variant,variant> map_vars;
const variant items = args()[0]->evaluate(variables);
+ variant_iterator it = items.get_iterator();
if(args().size() == 2) {
- for(size_t n = 0; n != items.num_elements(); ++n) {
- const variant val =
args().back()->evaluate(formula_variant_callable_with_backup(items[n],
variables));
- vars.push_back(val);
+ for(it = items.begin(); it != items.end(); ++it) {
+ const variant val =
args().back()->evaluate(formula_variant_callable_with_backup(*it, variables));
+ if (items.is_map() )
+ map_vars[ (*it).get_member("key") ] =
val;
+ else
+ list_vars.push_back(val);
}
} else {
map_formula_callable self_callable;
+ self_callable.add_ref();
const std::string self =
args()[1]->evaluate(variables).as_string();
- for(size_t n = 0; n != items.num_elements(); ++n) {
- self_callable.add(self, items[n]);
- const variant val =
args().back()->evaluate(formula_callable_with_backup(self_callable,
formula_variant_callable_with_backup(items[n], variables)));
- vars.push_back(val);
- }
- }
-
- return variant(&vars);
+ for(it = items.begin(); it != items.end(); ++it) {
+ self_callable.add(self, *it);
+ const variant val =
args().back()->evaluate(formula_callable_with_backup(self_callable,
formula_variant_callable_with_backup(*it, variables)));
+ if (items.is_map() )
+ map_vars[ (*it).get_member("key") ] =
val;
+ else
+ list_vars.push_back(val);
+ }
+ }
+ if (items.is_map() )
+ return variant(&map_vars);
+ return variant(&list_vars);
}
};
@@ -503,7 +567,9 @@
private:
variant execute(const formula_callable& variables) const {
const variant items = args()[0]->evaluate(variables);
- return items[0];
+ variant_iterator it = items.get_iterator();
+ it = items.begin();
+ return *it;
}
};
@@ -552,6 +618,24 @@
}
};
+}
+
+variant key_value_pair::get_value(const std::string& key) const
+{
+ if(key == "key")
+ {
+ return key_;
+ } else
+ if(key == "value")
+ {
+ return value_;
+ } else
+ return variant();
+}
+
+void key_value_pair::get_inputs(std::vector<game_logic::formula_input>*
inputs) const {
+ inputs->push_back(game_logic::formula_input("key",
game_logic::FORMULA_READ_ONLY));
+ inputs->push_back(game_logic::formula_input("value",
game_logic::FORMULA_READ_ONLY));
}
formula_function_expression::formula_function_expression(const std::string&
name, const args_list& args, const_formula_ptr formula, const_formula_ptr
precondition, const std::vector<std::string>& arg_names)
@@ -676,6 +760,7 @@
FUNCTION(loc);
FUNCTION(keys);
FUNCTION(values);
+ FUNCTION(tolist);
#undef FUNCTION
}
Modified: trunk/src/formula_function.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/formula_function.hpp?rev=27547&r1=27546&r2=27547&view=diff
==============================================================================
--- trunk/src/formula_function.hpp (original)
+++ trunk/src/formula_function.hpp Sat Jun 28 10:47:15 2008
@@ -68,6 +68,17 @@
args_list args_;
};
+class key_value_pair : public formula_callable {
+ variant key_;
+ variant value_;
+
+ variant get_value(const std::string& key) const;
+
+ void get_inputs(std::vector<game_logic::formula_input>* inputs) const;
+public:
+ explicit key_value_pair(const variant& key, const variant& value) :
key_(key), value_(value) {}
+};
+
class formula_function_expression : public function_expression {
public:
explicit formula_function_expression(const std::string& name, const
args_list& args, const_formula_ptr formula, const_formula_ptr precondition,
const std::vector<std::string>& arg_names);
Modified: trunk/src/variant.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/variant.cpp?rev=27547&r1=27546&r2=27547&view=diff
==============================================================================
--- trunk/src/variant.cpp (original)
+++ trunk/src/variant.cpp Sat Jun 28 10:47:15 2008
@@ -11,6 +11,7 @@
#include "formatter.hpp"
#include "formula.hpp"
#include "formula_callable.hpp"
+#include "formula_function.hpp"
#include "variant.hpp"
namespace {
@@ -66,6 +67,105 @@
std::cerr << "ERROR: " << message << "\n" << get_call_stack();
}
+variant_iterator::variant_iterator() : type_(TYPE_NULL), list_iterator_(NULL),
map_iterator_(NULL)
+{}
+
+variant_iterator::variant_iterator(const variant_iterator& iter) :
type_(iter.type_), list_iterator_(iter.list_iterator_),
map_iterator_(iter.map_iterator_)
+{}
+
+variant_iterator::variant_iterator(const std::vector<variant>::iterator& iter)
: type_(TYPE_LIST), list_iterator_(iter), map_iterator_(NULL)
+{}
+
+variant_iterator::variant_iterator(const std::map<variant, variant>::iterator&
iter) : type_(TYPE_MAP), list_iterator_(NULL), map_iterator_(iter)
+{}
+
+variant variant_iterator::operator*() const
+{
+ if (type_ == TYPE_LIST)
+ {
+ return variant( *list_iterator_);
+ } else if (type_ == TYPE_MAP)
+ {
+ game_logic::key_value_pair* p = new game_logic::key_value_pair(
map_iterator_->first, map_iterator_->second );
+ variant res( p );
+ return res;
+ } else
+ return variant();
+}
+
+variant_iterator variant_iterator::operator++()
+{
+ if (type_ == TYPE_LIST)
+ {
+ ++list_iterator_;
+ } else if (type_ == TYPE_MAP)
+ {
+ ++map_iterator_;
+ }
+
+ return *this;
+}
+
+variant_iterator variant_iterator::operator++(int)
+{
+ variant_iterator iter(*this);
+ if (type_ == TYPE_LIST)
+ {
+ ++list_iterator_;
+ } else if (type_ == TYPE_MAP)
+ {
+ ++map_iterator_;
+ }
+
+ return iter;
+}
+
+variant_iterator& variant_iterator::operator=(const variant_iterator& that)
+{
+ if (this == &that)
+ return *this;
+ type_ = that.type_;
+ list_iterator_ = that.list_iterator_;
+ map_iterator_ = that.map_iterator_;
+ return *this;
+}
+
+bool variant_iterator::operator==(const variant_iterator& that) const
+{
+ if (type_ == TYPE_LIST)
+ {
+ if (that.type_ != TYPE_LIST)
+ return false;
+ return list_iterator_ == that.list_iterator_;
+ } else if (type_ == TYPE_MAP)
+ {
+ if (that.type_ != TYPE_MAP)
+ return false;
+ return map_iterator_ == that.map_iterator_;
+ } else if (type_ == TYPE_NULL && that.type_ == TYPE_NULL )
+ return true;
+ else
+ return false;
+}
+
+bool variant_iterator::operator!=(const variant_iterator& that) const
+{
+ if (type_ == TYPE_LIST)
+ {
+ if (that.type_ != TYPE_LIST)
+ return true;
+ return list_iterator_ != that.list_iterator_;
+ } else if (type_ == TYPE_MAP)
+ {
+ if (that.type_ != TYPE_MAP)
+ return true;
+ return map_iterator_ != that.map_iterator_;
+ } else if (type_ == TYPE_NULL && that.type_ == TYPE_NULL )
+ return false;
+ else
+ return true;
+}
+
struct variant_list {
variant_list() : refcount(0)
{}
@@ -241,12 +341,6 @@
}
}
-std::map<variant, variant> variant::get_map() const
-{
- must_be(TYPE_MAP);
- return map_->elements;
-}
-
variant variant::get_keys() const
{
must_be(TYPE_MAP);
@@ -267,6 +361,43 @@
tmp.push_back(i->second);
}
return variant(&tmp);
+}
+
+variant_iterator variant::get_iterator() const
+{
+ if(type_ == TYPE_LIST)
+ {
+ std::vector<variant>::iterator i;
+ return variant_iterator( i );
+ }
+ if(type_ == TYPE_MAP)
+ {
+ std::map<variant,variant>::iterator i;
+ return variant_iterator( i );
+ }
+
+ return variant_iterator();
+}
+
+variant_iterator variant::begin() const
+{
+ if(type_ == TYPE_LIST)
+ return variant_iterator( list_->elements.begin() );
+
+ if(type_ == TYPE_MAP)
+ return variant_iterator( map_->elements.begin() );
+
+ return variant_iterator();
+}
+variant_iterator variant::end() const
+{
+ if(type_ == TYPE_LIST)
+ return variant_iterator( list_->elements.end() );
+
+ if(type_ == TYPE_MAP)
+ return variant_iterator( map_->elements.end() );
+
+ return variant_iterator();
}
size_t variant::num_elements() const
Modified: trunk/src/variant.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/variant.hpp?rev=27547&r1=27546&r2=27547&view=diff
==============================================================================
--- trunk/src/variant.hpp (original)
+++ trunk/src/variant.hpp Sat Jun 28 10:47:15 2008
@@ -27,11 +27,13 @@
struct variant_list;
struct variant_string;
struct variant_map;
+class variant_iterator;
struct type_error {
explicit type_error(const std::string& str);
std::string message;
};
+
class variant {
public:
@@ -103,9 +105,12 @@
bool operator<=(const variant&) const;
bool operator>=(const variant&) const;
- std::map<variant, variant> get_map() const;
variant get_keys() const;
variant get_values() const;
+
+ variant_iterator get_iterator() const;
+ variant_iterator begin() const;
+ variant_iterator end() const;
void serialize_to_string(std::string& str) const;
void serialize_from_string(const std::string& str);
@@ -132,6 +137,27 @@
void release();
};
+class variant_iterator {
+public:
+ variant_iterator();
+ variant_iterator(const variant_iterator&);
+ variant_iterator(const std::vector<variant>::iterator& );
+ variant_iterator(const std::map<variant, variant>::iterator& );
+
+ variant operator*() const;
+ variant_iterator operator++();
+ variant_iterator operator++(int);
+ variant_iterator& operator=(const variant_iterator& that);
+ bool operator==(const variant_iterator& that) const;
+ bool operator!=(const variant_iterator& that) const;
+
+ enum TYPE { TYPE_NULL, TYPE_LIST, TYPE_MAP };
+private:
+ TYPE type_;
+ std::vector<variant>::iterator list_iterator_;
+ std::map<variant,variant>::iterator map_iterator_;
+};
+
template<typename T>
T* convert_variant(const variant& v) {
T* res = dynamic_cast<T*>(v.mutable_callable());
@@ -141,6 +167,7 @@
return res;
}
+
template<typename T>
T* try_convert_variant(const variant& v) {
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits