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

Reply via email to