The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
function.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2017 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "formula/callable_objects.hpp"
16 #include "formula/debugger.hpp"
17 #include "formula/function.hpp"
18 #include "game_display.hpp"
19 #include "game_config.hpp"
20 #include "log.hpp"
21 #include "color.hpp"
22 
23 #include <boost/math/constants/constants.hpp>
24 #include <cctype>
25 #include <deque>
26 
27 using namespace boost::math::constants;
28 
29 static lg::log_domain log_engine("engine");
30 #define DBG_NG LOG_STREAM(debug, log_engine)
31 static lg::log_domain log_scripting_formula("scripting/formula");
32 #define LOG_SF LOG_STREAM(info, log_scripting_formula)
33 #define WRN_SF LOG_STREAM(warn, log_scripting_formula)
34 #define ERR_SF LOG_STREAM(err, log_scripting_formula)
35 
36 namespace wfl {
37 
38 static std::deque<std::string> call_stack;
39 
40 call_stack_manager::call_stack_manager(const std::string& str) {
41  call_stack.push_back(str);
42 }
43 
44 call_stack_manager::~call_stack_manager() {
45  call_stack.pop_back();
46 }
47 
49  std::ostringstream res;
50  for(const auto& frame : call_stack) {
51  if(!frame.empty()) {
52  res << " " << frame << "\n";
53  }
54  }
55 
56  return res.str();
57 }
58 
59 std::string function_expression::str() const
60 {
61  std::stringstream s;
62  s << get_name();
63  s << '(';
64  bool first_arg = true;
65  for (expression_ptr a : args()) {
66  if (!first_arg) {
67  s << ',';
68  } else {
69  first_arg = false;
70  }
71  s << a->str();
72  }
73  s << ')';
74  return s.str();
75 }
76 
77 namespace builtins {
78 
80 public:
81  explicit debug_function(const args_list& args)
82  : function_expression("debug",args, 0, 1)
83  {}
84 private:
85  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
86  std::shared_ptr<formula_debugger> fdbp;
87  bool need_wrapper = false;
88  if (fdb==nullptr) {
89  fdbp.reset(new formula_debugger());
90  fdb = &*fdbp;
91  need_wrapper = true;
92 
93  }
94 
95  if (args().size()==1) {
96  if (!need_wrapper) {
97  return args()[0]->evaluate(variables,fdb);
98  } else {
99  return wrapper_formula(args()[0]).evaluate(variables,fdb);
100  }
101  } else {
102  return wrapper_formula().evaluate(variables,fdb);
103  }
104  }
105 };
106 
107 
109 public:
110  explicit dir_function(const args_list& args)
111  : function_expression("dir", args, 1, 1)
112  {}
113 
114 private:
115  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
116  variant var = args()[0]->evaluate(variables, fdb);
117  auto callable = var.as_callable();
118  formula_input_vector inputs = callable->inputs();
119  std::vector<variant> res;
120  for(size_t i=0; i<inputs.size(); ++i) {
121  const formula_input& input = inputs[i];
122  res.emplace_back(input.name);
123  }
124 
125  return variant(res);
126  }
127 };
128 
130 public:
131  explicit if_function(const args_list& args)
132  : function_expression("if", args, 2, -1)
133  {}
134 
135 private:
136  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
137  for(size_t n = 0; n < args().size()-1; n += 2) {
138  if( args()[n]->evaluate(variables,fdb).as_bool() ) {
139  return args()[n+1]->evaluate(variables,fdb);
140  }
141  }
142 
143  if((args().size()%2) != 0) {
144  return args().back()->evaluate(variables,fdb);
145  } else {
146  return variant();
147  }
148 
149  }
150 };
151 
153 public:
154  explicit switch_function(const args_list& args)
155  : function_expression("switch", args, 3, -1)
156  {}
157 
158 private:
159  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
160  variant var = args()[0]->evaluate(variables,fdb);
161  for(size_t n = 1; n < args().size()-1; n += 2) {
162  variant val = args()[n]->evaluate(variables,fdb);
163  if(val == var) {
164  return args()[n+1]->evaluate(variables,fdb);
165  }
166  }
167 
168  if((args().size()%2) == 0) {
169  return args().back()->evaluate(variables,fdb);
170  } else {
171  return variant();
172  }
173  }
174 };
175 
177 public:
178  explicit abs_function(const args_list& args)
179  : function_expression("abs", args, 1, 1)
180  {}
181 
182 private:
183  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
184  const variant input = args()[0]->evaluate(variables,fdb);
185  if(input.is_decimal()) {
186  const int n = input.as_decimal();
187  return variant(n >= 0 ? n : -n, variant::DECIMAL_VARIANT);
188  } else {
189  const int n = input.as_int();
190  return variant(n >= 0 ? n : -n);
191  }
192  }
193 };
194 
196 public:
197  explicit min_function(const args_list& args)
198  : function_expression("min", args, 1, -1)
199  {}
200 
201 private:
202  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
203  variant res = args()[0]->evaluate(variables, fdb);
204  if(res.is_list()) {
205  if(res.is_empty()) {
206  throw formula_error("min(list): list is empty", "", "", 0);
207  }
208  res = *std::min_element(res.begin(), res.end());
209  }
210  for(size_t n = 1; n < args().size(); ++n) {
211  variant v = args()[n]->evaluate(variables,fdb);
212  if(v.is_list()) {
213  if(v.is_empty()) {
214  continue;
215  }
216  v = *std::min_element(v.begin(), v.end());
217  }
218  if(res.is_null() || v < res) {
219  res = v;
220  }
221  }
222 
223  return res;
224  }
225 };
226 
228 public:
229  explicit max_function(const args_list& args)
230  : function_expression("max", args, 1, -1)
231  {}
232 
233 private:
234  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
235  variant res = args()[0]->evaluate(variables, fdb);
236  if(res.is_list()) {
237  if(res.is_empty()) {
238  throw formula_error("max(list): list is empty", "", "", 0);
239  }
240  res = *std::max_element(res.begin(), res.end());
241  }
242  for(size_t n = 1; n < args().size(); ++n) {
243  variant v = args()[n]->evaluate(variables, fdb);
244  if(v.is_list()) {
245  if(v.is_empty()) {
246  continue;
247  }
248  v = *std::max_element(v.begin(), v.end());
249  }
250  if(res.is_null() || v > res) {
251  res = v;
252  }
253  }
254 
255  return res;
256  }
257 };
258 
260 public:
261  explicit debug_float_function(const args_list& args)
262  : function_expression("debug_float", args, 2, 3)
263  {}
264 
265 private:
266  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
267  const args_list& arguments = args();
268  const variant var0 = arguments[0]->evaluate(variables,fdb);
269  const variant var1 = arguments[1]->evaluate(variables,fdb);
270 
271  const map_location location = var0.convert_to<location_callable>()->loc();
272  std::string text;
273 
274  if(arguments.size() == 2) {
275  text = var1.to_debug_string();
276  display_float(location,text);
277  return var1;
278  } else {
279  const variant var2 = arguments[2]->evaluate(variables,fdb);
280  text = var1.string_cast() + var2.to_debug_string();
281  display_float(location,text);
282  return var2;
283  }
284 
285  }
286 
287  void display_float(const map_location& location, const std::string& text) const{
288  game_display::get_singleton()->float_label(location, text, color_t(255,0,0));
289  }
290 };
291 
292 
294 public:
295  explicit debug_print_function(const args_list& args)
296  : function_expression("debug_print", args, 1, 2)
297  {}
298 
299 private:
300  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
301  const variant var1 = args()[0]->evaluate(variables,fdb);
302 
303  std::string str1,str2;
304 
305  if( args().size() == 1)
306  {
307  str1 = var1.to_debug_string(true);
308  LOG_SF << str1 << std::endl;
309  if(game_config::debug) {
311  }
312  return var1;
313  } else {
314  str1 = var1.string_cast();
315  const variant var2 = args()[1]->evaluate(variables,fdb);
316  str2 = var2.to_debug_string(true);
317  LOG_SF << str1 << ": " << str2 << std::endl;
320  }
321  return var2;
322  }
323  }
324 };
325 
327 public:
328  explicit debug_profile_function(const args_list& args)
329  : function_expression("debug_profile", args, 1, 2)
330  {}
331 
332 private:
333  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
334  std::string speaker = "WFL";
335  int i_value = 0;
336  if(args().size() == 2) {
337  speaker = args()[0]->evaluate(variables, fdb).string_cast();
338  i_value = 1;
339  }
340 
341  const variant value = args()[i_value]->evaluate(variables,fdb);
342  long run_time = 0;
343  for(int i = 1; i < 1000; i++) {
344  const long start = SDL_GetTicks();
345  args()[i_value]->evaluate(variables,fdb);
346  run_time += SDL_GetTicks() - start;
347  }
348 
349  std::ostringstream str;
350  str << "Evaluated in " << (run_time / 1000.0) << " ms on average";
351  LOG_SF << speaker << ": " << str.str() << std::endl;
354  }
355  return value;
356  }
357 };
358 
360 public:
361  explicit keys_function(const args_list& args)
362  : function_expression("keys", args, 1, 1)
363  {}
364 
365 private:
366  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
367  const variant map = args()[0]->evaluate(variables,fdb);
368  return map.get_keys();
369  }
370 };
371 
373 public:
374  explicit values_function(const args_list& args)
375  : function_expression("values", args, 1, 1)
376  {}
377 
378 private:
379  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
380  const variant map = args()[0]->evaluate(variables,fdb);
381  return map.get_values();
382  }
383 };
384 
386 public:
387  explicit tolist_function(const args_list& args)
388  : function_expression("tolist", args, 1, 1)
389  {}
390 
391 private:
392  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
393  const variant var = args()[0]->evaluate(variables,fdb);
394 
395  std::vector<variant> tmp;
396 
397  for(variant_iterator it = var.begin(); it != var.end(); ++it) {
398  tmp.push_back( *it );
399  }
400 
401  return variant(tmp);
402  }
403 };
404 
406 public:
407  explicit tomap_function(const args_list& args)
408  : function_expression("tomap", args, 1, 2)
409  {}
410 
411 private:
412  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
413  const variant var_1 = args()[0]->evaluate(variables,fdb);
414 
415  std::map<variant, variant> tmp;
416 
417  if (args().size() == 2)
418  {
419  const variant var_2 = args()[1]->evaluate(variables,fdb);
420  if ( var_1.num_elements() != var_2.num_elements() )
421  return variant();
422  for(size_t i = 0; i < var_1.num_elements(); ++i )
423  tmp[ var_1[i] ] = var_2[i];
424  } else
425  {
426  for(variant_iterator it = var_1.begin(); it != var_1.end(); ++it) {
427  if(auto kv = (*it).try_convert<key_value_pair>())
428  tmp[kv->query_value("key")] = kv->query_value("value");
429  else {
430  std::map<variant, variant>::iterator map_it = tmp.find( *it );
431  if (map_it == tmp.end()) {
432  tmp[*it] = variant(1);
433  } else {
434  map_it->second = variant(map_it->second.as_int() + 1);
435  }
436  }
437  }
438  }
439 
440  return variant(tmp);
441  }
442 };
443 
445 public:
446  explicit substring_function(const args_list& args)
447  : function_expression("substring", args, 2, 3)
448  {}
449 private:
450  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
451 
452  std::string result = args()[0]->evaluate(variables, fdb).as_string();
453 
454  int offset = args()[1]->evaluate(variables, fdb).as_int();
455  if(offset < 0) {
456  offset += result.size();
457  if(offset < 0) {
458  offset = 0;
459  }
460  } else {
461  if(static_cast<size_t>(offset) >= result.size()) {
462  return variant(std::string());
463  }
464  }
465 
466  if(args().size() > 2) {
467  int size = args()[2]->evaluate(variables, fdb).as_int();
468  if(size < 0) {
469  size = -size;
470  offset = std::max(0, offset - size + 1);
471  }
472  return variant(result.substr(offset, size));
473  } else {
474  return variant(result.substr(offset));
475  }
476  }
477 };
478 
480 public:
481  explicit replace_function(const args_list& args)
482  : function_expression("replace", args, 3, 4)
483  {}
484 private:
485  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
486 
487  std::string result = args()[0]->evaluate(variables, fdb).as_string();
488  std::string replacement = args().back()->evaluate(variables, fdb).as_string();
489 
490  int offset = args()[1]->evaluate(variables, fdb).as_int();
491  if(offset < 0) {
492  offset += result.size();
493  if(offset < 0) {
494  offset = 0;
495  }
496  } else {
497  if(static_cast<size_t>(offset) >= result.size()) {
498  return variant(result);
499  }
500  }
501 
502  if(args().size() > 3) {
503  int size = args()[2]->evaluate(variables, fdb).as_int();
504  if(size < 0) {
505  size = -size;
506  offset = std::max(0, offset - size + 1);
507  }
508  return variant(result.replace(offset, size, replacement));
509  } else {
510  return variant(result.replace(offset, std::string::npos, replacement));
511  }
512  }
513 };
514 
516 public:
517  explicit length_function(const args_list& args)
518  : function_expression("length", args, 1, 1)
519  {}
520 private:
521  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
522  return variant(args()[0]->evaluate(variables, fdb).as_string().length());
523  }
524 };
525 
527 public:
528  explicit concatenate_function(const args_list& args)
529  : function_expression("concatenate", args, 1, -1)
530  {}
531 private:
532  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
533  std::string result;
534 
535  for(expression_ptr arg : args()) {
536  result += arg->evaluate(variables, fdb).string_cast();
537  }
538 
539  return variant(result);
540  }
541 };
542 
544 public:
545  explicit str_upper_function(const args_list& args)
546  : function_expression("str_upper", args, 1, 1)
547  {}
548 private:
549  variant execute(const formula_callable& variables, formula_debugger* fdb) const {
550  std::string str = args()[0]->evaluate(variables, fdb).as_string();
551  std::transform(str.begin(), str.end(), str.begin(), static_cast<int(*)(int)>(std::toupper));
552  return variant(str);
553  }
554 };
555 
557 public:
558  explicit str_lower_function(const args_list& args)
559  : function_expression("str_lower", args, 1, 1)
560  {}
561 private:
562  variant execute(const formula_callable& variables, formula_debugger* fdb) const {
563  std::string str = args()[0]->evaluate(variables, fdb).as_string();
564  std::transform(str.begin(), str.end(), str.begin(), static_cast<int(*)(int)>(std::tolower));
565  return variant(str);
566  }
567 };
568 
570 public:
571  explicit sin_function(const args_list& args)
572  : function_expression("sin", args, 1, 1)
573  {}
574 private:
575  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
576  const double angle = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
577  const double result = sin(angle * pi<double>() / 180.0);
578  return variant(result, variant::DECIMAL_VARIANT);
579  }
580 };
581 
583 public:
584  explicit cos_function(const args_list& args)
585  : function_expression("cos", args, 1, 1)
586  {}
587 private:
588  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
589  const double angle = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
590  const double result = cos(angle * pi<double>() / 180.0);
591  return variant(result, variant::DECIMAL_VARIANT);
592  }
593 };
594 
596 public:
597  explicit tan_function(const args_list& args)
598  : function_expression("tan", args, 1, 1)
599  {}
600 private:
601  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
602  const double angle = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
603  const double result = tan(angle * pi<double>() / 180.0);
604  if(std::isnan(result) || result <= INT_MIN || result >= INT_MAX) {
605  return variant();
606  }
607  return variant(result, variant::DECIMAL_VARIANT);
608  }
609 };
610 
612 public:
613  explicit asin_function(const args_list& args)
614  : function_expression("asin", args, 1, 1)
615  {}
616 
617 private:
618  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
619  const double num = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
620  const double result = asin(num) * 180.0 / pi<double>();
621  if(std::isnan(result)) {
622  return variant();
623  }
624  return variant(result, variant::DECIMAL_VARIANT);
625  }
626 };
627 
629 public:
630  explicit acos_function(const args_list& args)
631  : function_expression("acos", args, 1, 1)
632  {}
633 private:
634  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
635  const double num = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
636  const double result = acos(num) * 180.0 / pi<double>();
637  if(std::isnan(result)) {
638  return variant();
639  }
640  return variant(result, variant::DECIMAL_VARIANT);
641  }
642 };
643 
645 public:
646  explicit atan_function(const args_list& args)
647  : function_expression("acos", args, 1, 1)
648  {}
649 private:
650  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
651  const double num = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
652  const double result = atan(num) * 180.0 / pi<double>();
653  return variant(result, variant::DECIMAL_VARIANT);
654  }
655 };
656 
658 public:
659  explicit sqrt_function(const args_list& args)
660  : function_expression("sqrt", args, 1, 1)
661  {}
662 private:
663  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
664  const double num = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
665  const double result = sqrt(num);
666  if(std::isnan(result)) {
667  return variant();
668  }
669  return variant(result, variant::DECIMAL_VARIANT);
670  }
671 };
672 
674 public:
675  explicit cbrt_function(const args_list& args)
676  : function_expression("cbrt", args, 1, 1)
677  {}
678 private:
679  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
680  const double num = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
681  const double result = num < 0 ? -pow(-num, 1.0 / 3.0) : pow(num, 1.0 / 3.0);
682  return variant(result, variant::DECIMAL_VARIANT);
683  }
684 };
685 
687 public:
688  explicit root_function(const args_list& args)
689  : function_expression("root", args, 2, 2)
690  {}
691 private:
692  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
693  const double base = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
694  const double root = args()[1]->evaluate(variables,fdb).as_decimal() / 1000.0;
695  const double result = base < 0 && fmod(root,2) == 1 ? -pow(-base, 1.0 / root) : pow(base, 1.0 / root);
696  if(std::isnan(result)) {
697  return variant();
698  }
699  return variant(result, variant::DECIMAL_VARIANT);
700  }
701 };
702 
704 public:
705  explicit log_function(const args_list& args)
706  : function_expression("log", args, 1, 2)
707  {}
708 private:
709  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
710  const double num = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
711  if(args().size() == 1) {
712  const double result = log(num);
713  if(std::isnan(result)) {
714  return variant();
715  }
716  return variant(result, variant::DECIMAL_VARIANT);
717  } else {
718  const double base = args()[1]->evaluate(variables,fdb).as_decimal() / 1000.0;
719  const double result = log(num) / log(base);
720  if(std::isnan(result)) {
721  return variant();
722  }
723  return variant(result, variant::DECIMAL_VARIANT);
724  }
725  }
726 };
727 
729 public:
730  explicit exp_function(const args_list& args)
731  : function_expression("exp", args, 1, 1)
732  {}
733 private:
734  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
735  const double num = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
736  const double result = exp(num);
737  if(result == 0 || result >= INT_MAX) {
738  // These are range errors rather than NaNs,
739  // but I figure it's better than returning INT_MIN.
740  return variant();
741  }
742  return variant(result, variant::DECIMAL_VARIANT);
743  }
744 };
745 
747 public:
748  explicit pi_function(const args_list& args)
749  : function_expression("pi", args, 0, 0)
750  {}
751 private:
753  return variant(pi<double>(), variant::DECIMAL_VARIANT);
754  }
755 };
756 
758 public:
759  explicit hypot_function(const args_list& args)
760  : function_expression("hypot", args, 2, 2)
761  {}
762 private:
763  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
764  const double x = args()[0]->evaluate(variables,fdb).as_decimal() / 1000.0;
765  const double y = args()[1]->evaluate(variables,fdb).as_decimal() / 1000.0;
766  return variant(hypot(x,y), variant::DECIMAL_VARIANT);
767  }
768 };
769 
771 public:
772  explicit index_of_function(const args_list& args)
773  : function_expression("index_of", args, 2, 2)
774  {}
775 
776 private:
777  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
778  const variant value = args()[0]->evaluate(variables,fdb);
779  const variant list = args()[1]->evaluate(variables,fdb);
780 
781  for(size_t i = 0; i < list.num_elements(); ++i ) {
782  if( list[i] == value) {
783  return variant(i);
784  }
785  }
786 
787  return variant( -1 );
788  }
789 };
790 
791 
793 public:
794  explicit choose_function(const args_list& args)
795  : function_expression("choose", args, 2, 3)
796  {}
797 
798 private:
799  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
800  const variant items = args()[0]->evaluate(variables,fdb);
801  variant max_value;
802  variant_iterator max;
803 
804  if(args().size() == 2) {
805  for(variant_iterator it = items.begin(); it != items.end(); ++it) {
806  const variant val = args().back()->evaluate(formula_variant_callable_with_backup(*it, variables),fdb);
807  if(max == variant_iterator() || val > max_value) {
808  max = it;
809  max_value = val;
810  }
811  }
812  } else {
813  map_formula_callable self_callable;
814  const std::string self = args()[1]->evaluate(variables,fdb).as_string();
815  for(variant_iterator it = items.begin(); it != items.end(); ++it) {
816  self_callable.add(self, *it);
817  const variant val = args().back()->evaluate(formula_callable_with_backup(self_callable, formula_variant_callable_with_backup(*it, variables)),fdb);
818  if(max == variant_iterator() || val > max_value) {
819  max = it;
820  max_value = val;
821  }
822  }
823  }
824 
825  if(max == variant_iterator() ) {
826  return variant();
827  } else {
828  return *max;
829  }
830  }
831 };
832 
834 public:
835  explicit wave_function(const args_list& args)
836  : function_expression("wave", args, 1, 1)
837  {}
838 
839 private:
840  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
841  const int value = args()[0]->evaluate(variables,fdb).as_int()%1000;
842  const double angle = 2.0 * pi<double>() * (static_cast<double>(value) / 1000.0);
843  return variant(static_cast<int>(sin(angle)*1000.0));
844  }
845 };
846 
847 namespace {
848 class variant_comparator : public formula_callable {
850  const formula_callable* fallback_;
851  mutable variant a_, b_;
852  variant get_value(const std::string& key) const {
853  if(key == "a") {
854  return a_;
855  } else if(key == "b") {
856  return b_;
857  } else {
858  return fallback_->query_value(key);
859  }
860  }
861 
862  void get_inputs(formula_input_vector& inputs) const {
863  fallback_->get_inputs(inputs);
864  }
865 public:
866  variant_comparator(const expression_ptr& expr, const formula_callable& fallback) :
867  expr_(expr),
868  fallback_(&fallback),
869  a_(),
870  b_()
871  {}
872 
873  bool operator()(const variant& a, const variant& b) const {
874  a_ = a;
875  b_ = b;
876  return expr_->evaluate(*this).as_bool();
877  }
878 };
879 }
880 
882 public:
883  explicit sort_function(const args_list& args)
884  : function_expression("sort", args, 1, 2)
885  {}
886 
887 private:
888  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
889  variant list = args()[0]->evaluate(variables,fdb);
890  std::vector<variant> vars;
891  vars.reserve(list.num_elements());
892  for(size_t n = 0; n != list.num_elements(); ++n) {
893  vars.push_back(list[n]);
894  }
895 
896  if(args().size() == 1) {
897  std::sort(vars.begin(), vars.end());
898  } else {
899  std::sort(vars.begin(), vars.end(), variant_comparator(args()[1], variables));
900  }
901 
902  return variant(vars);
903  }
904 };
905 
907 public:
908  explicit reverse_function(const args_list& args)
909  : function_expression("reverse", args, 1, 1)
910  {}
911 
912 private:
913  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
914  const variant& arg = args()[0]->evaluate(variables,fdb);
915  if(arg.is_string()) {
916  std::string str = args()[0]->evaluate(variables,fdb).as_string();
917  std::reverse(str.begin(), str.end());
918  return variant(str);
919  } else if(arg.is_list()) {
920  std::vector<variant> list = args()[0]->evaluate(variables,fdb).as_list();
921  std::reverse(list.begin(), list.end());
922  return variant(list);
923  }
924  return variant();
925  }
926 };
927 
929 public:
930  explicit contains_string_function(const args_list& args)
931  : function_expression("contains_string", args, 2, 2)
932  {}
933 
934 private:
935  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
936  std::string str = args()[0]->evaluate(variables,fdb).as_string();
937  std::string key = args()[1]->evaluate(variables,fdb).as_string();
938 
939  return variant(str.find(key) != std::string::npos);
940  }
941 };
942 
944 public:
945  explicit find_string_function(const args_list& args)
946  : function_expression("find_string", args, 2, 2)
947  {}
948 
949 private:
950  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
951  const std::string str = args()[0]->evaluate(variables,fdb).as_string();
952  const std::string key = args()[1]->evaluate(variables,fdb).as_string();
953 
954  size_t pos = str.find(key);
955  return variant(static_cast<int>(pos));
956  }
957 };
958 
960 public:
961  explicit filter_function(const args_list& args)
962  : function_expression("filter", args, 2, 3)
963  {}
964 private:
965  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
966  std::vector<variant> list_vars;
967  std::map<variant,variant> map_vars;
968 
969  const variant items = args()[0]->evaluate(variables,fdb);
970 
971  if(args().size() == 2) {
972  for(variant_iterator it = items.begin(); it != items.end(); ++it) {
973  const variant val = args()[1]->evaluate(formula_variant_callable_with_backup(*it, variables),fdb);
974  if(val.as_bool()) {
975  if (items.is_map() )
976  map_vars[ (*it).get_member("key") ] = (*it).get_member("value");
977  else
978  list_vars.push_back(*it);
979  }
980  }
981  } else {
982  map_formula_callable self_callable;
983  const std::string self = args()[1]->evaluate(variables,fdb).as_string();
984  for(variant_iterator it = items.begin(); it != items.end(); ++it) {
985  self_callable.add(self, *it);
986  const variant val = args()[2]->evaluate(formula_callable_with_backup(self_callable, formula_variant_callable_with_backup(*it, variables)),fdb);
987  if(val.as_bool()) {
988  if (items.is_map() )
989  map_vars[ (*it).get_member("key") ] = (*it).get_member("value");
990  else
991  list_vars.push_back(*it);
992  }
993  }
994  }
995  if (items.is_map() )
996  return variant(map_vars);
997  return variant(list_vars);
998  }
999 };
1000 
1002 public:
1003  explicit find_function(const args_list& args)
1004  : function_expression("find", args, 2, 3)
1005  {}
1006 
1007 private:
1008  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1009  const variant items = args()[0]->evaluate(variables,fdb);
1010 
1011  if(args().size() == 2) {
1012  for(variant_iterator it = items.begin(); it != items.end(); ++it) {
1013  const variant val = args()[1]->evaluate(formula_variant_callable_with_backup(*it, variables),fdb);
1014  if(val.as_bool()) {
1015  return *it;
1016  }
1017  }
1018  } else {
1019  map_formula_callable self_callable;
1020  const std::string self = args()[1]->evaluate(variables,fdb).as_string();
1021  for(variant_iterator it = items.begin(); it != items.end(); ++it){
1022  self_callable.add(self, *it);
1023  const variant val = args().back()->evaluate(formula_callable_with_backup(self_callable, formula_variant_callable_with_backup(*it, variables)),fdb);
1024  if(val.as_bool()) {
1025  return *it;
1026  }
1027  }
1028  }
1029 
1030  return variant();
1031  }
1032 };
1033 
1035 public:
1036  explicit map_function(const args_list& args)
1037  : function_expression("map", args, 2, 3)
1038  {}
1039 private:
1040  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1041  std::vector<variant> list_vars;
1042  std::map<variant,variant> map_vars;
1043  const variant items = args()[0]->evaluate(variables,fdb);
1044 
1045  if(args().size() == 2) {
1046  for(variant_iterator it = items.begin(); it != items.end(); ++it) {
1047  const variant val = args().back()->evaluate(formula_variant_callable_with_backup(*it, variables),fdb);
1048  if (items.is_map() )
1049  map_vars[ (*it).get_member("key") ] = val;
1050  else
1051  list_vars.push_back(val);
1052  }
1053  } else {
1054  map_formula_callable self_callable;
1055  const std::string self = args()[1]->evaluate(variables,fdb).as_string();
1056  for(variant_iterator it = items.begin(); it != items.end(); ++it) {
1057  self_callable.add(self, *it);
1058  const variant val = args().back()->evaluate(formula_callable_with_backup(self_callable, formula_variant_callable_with_backup(*it, variables)),fdb);
1059  if (items.is_map() )
1060  map_vars[ (*it).get_member("key") ] = val;
1061  else
1062  list_vars.push_back(val);
1063  }
1064  }
1065  if (items.is_map() )
1066  return variant(map_vars);
1067  return variant(list_vars);
1068  }
1069 };
1070 
1072 public:
1073  explicit take_while_function(const args_list& args)
1074  : function_expression("take_while", args, 2, 2)
1075  {}
1076 private:
1077  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1078  const variant& items = args()[0]->evaluate(variables, fdb);
1079  variant_iterator it = items.begin();
1080  for(; it != items.end(); ++it) {
1081  const variant matches = args().back()->evaluate(formula_variant_callable_with_backup(*it, variables),fdb);
1082  if (!matches.as_bool())
1083  break;
1084  }
1085  std::vector<variant> result(items.begin(), it);
1086  return variant(result);
1087  }
1088 };
1089 
1091 public:
1092  explicit zip_function(const args_list& args)
1093  : function_expression("zip", args, 1, -1)
1094  {}
1095 private:
1096  struct indexer {
1097  size_t i;
1098  explicit indexer(size_t i) : i(i) {}
1099  variant operator()(const variant& v) const {
1100  if(i >= v.num_elements()) {
1101  return variant();
1102  } else {
1103  return v[i];
1104  }
1105  }
1106  };
1107  struct comparator {
1108  bool operator()(const variant& a, const variant& b) const {
1109  return a.num_elements() < b.num_elements();
1110  }
1111  };
1112  std::vector<variant> get_input(const formula_callable& variables, formula_debugger* fdb) const {
1113  if(args().size() == 1) {
1114  const variant list = args()[0]->evaluate(variables, fdb);
1115  return std::vector<variant>(list.begin(), list.end());
1116  } else {
1117  std::vector<variant> input;
1118  input.reserve(args().size());
1119  for(expression_ptr expr : args()) {
1120  input.push_back(expr->evaluate(variables, fdb));
1121  }
1122  return input;
1123  }
1124  }
1125  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1126  const std::vector<variant> input = get_input(variables, fdb);
1127  std::vector<variant> output;
1128  // So basically this does [[a,b,c],[d,e,f],[x,y,z]] -> [[a,d,x],[b,e,y],[c,f,z]]
1129  // Or [[a,b,c,d],[x,y,z]] -> [[a,x],[b,y],[c,z],[d,null()]]
1130  size_t max_i = std::max_element(input.begin(), input.end(), comparator())->num_elements();
1131  output.reserve(max_i);
1132  for(size_t i = 0; i < max_i; i++) {
1133  std::vector<variant> elem(input.size());
1134  std::transform(input.begin(), input.end(), elem.begin(), indexer(i));
1135  output.emplace_back(elem);
1136  }
1137  return variant(output);
1138  }
1139 };
1140 
1142 public:
1143  explicit reduce_function(const args_list& args)
1144  : function_expression("reduce", args, 2, 3)
1145  {}
1146 private:
1147  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1148  const variant items = args()[0]->evaluate(variables,fdb);
1149  const variant initial = args().size() == 2 ? variant() : args()[1]->evaluate(variables,fdb);
1150 
1151  if(items.num_elements() == 0)
1152  return initial;
1153 
1154  variant_iterator it = items.begin();
1155  variant res(initial.is_null() ? *it : initial);
1156  if(res != initial) {
1157  ++it;
1158  }
1159  map_formula_callable self_callable;
1160  for(; it != items.end(); ++it) {
1161  self_callable.add("a", res);
1162  self_callable.add("b", *it);
1163  res = args().back()->evaluate(formula_callable_with_backup(self_callable, formula_variant_callable_with_backup(*it, variables)),fdb);
1164  }
1165  return res;
1166  }
1167 };
1168 
1170 public:
1171  explicit sum_function(const args_list& args)
1172  : function_expression("sum", args, 1, 2)
1173  {}
1174 private:
1175  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1176  variant res(0);
1177  const variant items = args()[0]->evaluate(variables,fdb);
1178  if (items.num_elements() > 0)
1179  {
1180  if (items[0].is_list() )
1181  {
1182  std::vector<variant> tmp;
1183  res = variant(tmp);
1184  if(args().size() >= 2) {
1185  res = args()[1]->evaluate(variables,fdb);
1186  if(!res.is_list())
1187  return variant();
1188  }
1189  } else if( items[0].is_map() )
1190  {
1191  std::map<variant,variant> tmp;
1192  res = variant(tmp);
1193  if(args().size() >= 2) {
1194  res = args()[1]->evaluate(variables,fdb);
1195  if(!res.is_map())
1196  return variant();
1197  }
1198  } else
1199  {
1200  if(args().size() >= 2) {
1201  res = args()[1]->evaluate(variables,fdb);
1202  }
1203  }
1204  }
1205 
1206  for(size_t n = 0; n != items.num_elements(); ++n) {
1207  res = res + items[n];
1208  }
1209 
1210  return res;
1211  }
1212 };
1213 
1215 public:
1216  explicit head_function(const args_list& args)
1217  : function_expression("head", args, 1, 2)
1218  {}
1219 private:
1220  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1221  const variant items = args()[0]->evaluate(variables,fdb);
1222  variant_iterator it = items.begin();
1223  if(it == items.end()) {
1224  return variant();
1225  }
1226  if(args().size() == 1) {
1227  return *it;
1228  }
1229  const int n = items.num_elements(), req = args()[1]->evaluate(variables,fdb).as_int();
1230  const int count = req < 0 ? n - std::min(-req, n) : std::min(req, n);
1231  variant_iterator end = it;
1232  std::advance(end, count);
1233  std::vector<variant> res;
1234  std::copy(it, end, std::back_inserter(res));
1235  return variant(res);
1236  }
1237 };
1238 
1240 public:
1241  explicit tail_function(const args_list& args)
1242  : function_expression("tail", args, 1, 2)
1243  {}
1244 private:
1245  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1246  const variant items = args()[0]->evaluate(variables,fdb);
1247  variant_iterator it = items.end();
1248  if(it == items.begin()) {
1249  return variant();
1250  }
1251  if(args().size() == 1) {
1252  return *--it;
1253  }
1254  const int n = items.num_elements(), req = args()[1]->evaluate(variables,fdb).as_int();
1255  const int count = req < 0 ? n - std::min(-req, n) : std::min(req, n);
1256  std::advance(it, -count);
1257  std::vector<variant> res;
1258  std::copy(it, items.end(), std::back_inserter(res));
1259  return variant(res);
1260  }
1261 };
1262 
1264 public:
1265  explicit size_function(const args_list& args)
1266  : function_expression("size", args, 1, 1)
1267  {}
1268 private:
1269  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1270  const variant items = args()[0]->evaluate(variables,fdb);
1271  return variant(static_cast<int>(items.num_elements()));
1272  }
1273 };
1274 
1276 public:
1277  explicit null_function(const args_list& args)
1278  : function_expression("null", args, 0, -1)
1279  {}
1280 private:
1281  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1282  if(!args().empty()) {
1283  for( size_t i = 0; i < args().size() ; ++i)
1284  args()[i]->evaluate(variables,fdb);
1285  }
1286 
1287  return variant();
1288  }
1289 };
1290 
1291 
1293 public:
1294  explicit ceil_function(const args_list& args)
1295  : function_expression("ceil", args, 1, 1)
1296  {}
1297 private:
1298  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1299  variant decimal = args()[0]->evaluate(variables,fdb);
1300 
1301  int d = decimal.as_decimal();
1302 
1303  if( (d>=0) && (d%1000 != 0) ) {
1304  d/=1000;
1305  return variant( ++d );
1306  } else {
1307  d/=1000;
1308  return variant( d );
1309  }
1310  }
1311 };
1312 
1314 public:
1315  explicit round_function(const args_list& args)
1316  : function_expression("round", args, 1, 1)
1317  {}
1318 private:
1319  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1320  variant decimal = args()[0]->evaluate(variables,fdb);
1321 
1322  int d = decimal.as_decimal();
1323 
1324  int f = d%1000;
1325 
1326  if( f >= 500 ) {
1327  d/=1000;
1328  return variant( ++d );
1329  } else if( f <= -500 ) {
1330  d/=1000;
1331  return variant( --d );
1332  } else {
1333  d/=1000;
1334  return variant( d );
1335  }
1336  }
1337 };
1338 
1340 public:
1341  explicit floor_function(const args_list& args)
1342  : function_expression("floor", args, 1, 1)
1343  {}
1344 private:
1345  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1346  variant decimal = args()[0]->evaluate(variables,fdb);
1347 
1348  int d = decimal.as_decimal();
1349 
1350  if( (d<0) && (d%1000 != 0) ) {
1351  d/=1000;
1352  return variant( --d );
1353  } else {
1354  d/=1000;
1355  return variant( d );
1356  }
1357  }
1358 };
1359 
1361 public:
1362  explicit trunc_function(const args_list& args)
1363  : function_expression("trunc", args, 1, 1)
1364  {}
1365 private:
1366  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1367  variant decimal = args()[0]->evaluate(variables,fdb);
1368 
1369  int d = decimal.as_int();
1370 
1371  return variant( d );
1372  }
1373 };
1374 
1376 public:
1377  explicit frac_function(const args_list& args)
1378  : function_expression("frac", args, 1, 1)
1379  {}
1380 private:
1381  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1382  variant decimal = args()[0]->evaluate(variables,fdb);
1383 
1384  int d = decimal.as_decimal();
1385 
1386  d%=1000;
1387  return variant( d, variant::DECIMAL_VARIANT );
1388  }
1389 };
1390 
1392 public:
1393  explicit sgn_function(const args_list& args)
1394  : function_expression("sgn", args, 1, 1)
1395  {}
1396 private:
1397  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1398  variant decimal = args()[0]->evaluate(variables,fdb);
1399 
1400  int d = decimal.as_decimal();
1401 
1402  if( d != 0 ) {
1403  d = d>0 ? 1 : -1;
1404  }
1405 
1406  return variant( d );
1407  }
1408 };
1409 
1411 public:
1412  explicit as_decimal_function(const args_list& args)
1413  : function_expression("as_decimal", args, 1, 1)
1414  {}
1415 private:
1416  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1417  variant decimal = args()[0]->evaluate(variables,fdb);
1418 
1419  int d = decimal.as_decimal();
1420 
1421  return variant( d , variant::DECIMAL_VARIANT );
1422  }
1423 };
1424 
1426 public:
1427  explicit loc_function(const args_list& args)
1428  : function_expression("loc", args, 2, 2)
1429  {}
1430 private:
1431  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1432  return variant(std::make_shared<location_callable>(map_location(
1433  args()[0]->evaluate(variables,add_debug_info(fdb,0,"loc:x")).as_int(),
1434  args()[1]->evaluate(variables,add_debug_info(fdb,1,"loc:y")).as_int(), wml_loc())));
1435  }
1436 };
1437 
1439 public:
1440  explicit pair_function(const args_list& args)
1441  : function_expression("pair", args, 2, 2)
1442  {}
1443 private:
1444  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1445  return variant(std::make_shared<key_value_pair>(
1446  args()[0]->evaluate(variables,add_debug_info(fdb,0,"pair:key")),
1447  args()[1]->evaluate(variables,add_debug_info(fdb,1,"pair_value"))
1448  ));
1449  }
1450 };
1451 
1453 public:
1454  explicit distance_between_function(const args_list& args)
1455  : function_expression("distance_between", args, 2, 2)
1456  {}
1457 
1458 private:
1459  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1460  const map_location loc1 = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "distance_between:location_A")).convert_to<location_callable>()->loc();
1461  const map_location loc2 = args()[1]->evaluate(variables, add_debug_info(fdb, 1, "distance_between:location_B")).convert_to<location_callable>()->loc();
1462  return variant(distance_between(loc1, loc2));
1463  }
1464 };
1465 
1467 public:
1469  : function_expression("adjacent_locs", args, 1, 1) {}
1470 
1471 private:
1472  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1473  const map_location loc = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "adjacent_locs:location")).convert_to<location_callable>()->loc();
1474  map_location adj[6];
1475  get_adjacent_tiles(loc, adj);
1476 
1477  std::vector<variant> v;
1478  for(int n = 0; n != 6; ++n) {
1479  v.emplace_back(std::make_shared<location_callable>(adj[n]));
1480  }
1481 
1482  return variant(v);
1483  }
1484 };
1485 
1487 public:
1489  : function_expression("are_adjacent", args, 2, 2) {}
1490 
1491 private:
1492  variant execute(const formula_callable& variables, formula_debugger* fdb) const {
1493  const map_location loc1 = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "are_adjacent:location_A")).convert_to<location_callable>()->loc();
1494  const map_location loc2 = args()[1]->evaluate(variables, add_debug_info(fdb, 1, "are_adjacent:location_B")).convert_to<location_callable>()->loc();
1495  return variant(tiles_adjacent(loc1, loc2) ? 1 : 0);
1496  }
1497 };
1498 
1500 public:
1502  : function_expression("relative_dir", args, 2, 2) {}
1503 
1504 private:
1505  variant execute(const formula_callable& variables, formula_debugger* fdb) const {
1506  const map_location loc1 = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "relative_dir:location_A")).convert_to<location_callable>()->loc();
1507  const map_location loc2 = args()[1]->evaluate(variables, add_debug_info(fdb, 1, "relative_dir:location_B")).convert_to<location_callable>()->loc();
1509  }
1510 };
1511 
1513 public:
1515  : function_expression("direction_from", args, 2, 3) {}
1516 
1517 private:
1518  variant execute(const formula_callable& variables, formula_debugger* fdb) const {
1519  const map_location loc = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "direction_from:location")).convert_to<location_callable>()->loc();
1520  const std::string dir_str = args()[1]->evaluate(variables, add_debug_info(fdb, 1, "direction_from:dir")).as_string();
1521  int n = args().size() == 3 ? args()[2]->evaluate(variables, add_debug_info(fdb, 2, "direction_from:count")).as_int() : 1;
1522  return variant(std::make_shared<location_callable>(loc.get_direction(map_location::parse_direction(dir_str), n)));
1523  }
1524 };
1525 
1527 public:
1529  : function_expression("rotate_loc_around", args, 2, 3) {}
1530 
1531 private:
1532  variant execute(const formula_callable& variables, formula_debugger* fdb) const {
1533  const map_location center = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "direction_from:center")).convert_to<location_callable>()->loc();
1534  const map_location loc = args()[0]->evaluate(variables, add_debug_info(fdb, 1, "direction_from:location")).convert_to<location_callable>()->loc();
1535  int n = args().size() == 3 ? args()[2]->evaluate(variables, add_debug_info(fdb, 2, "direction_from:count")).as_int() : 1;
1536  return variant(std::make_shared<location_callable>(loc.rotate_right_around_center(center, n)));
1537  }
1538 };
1539 
1540 
1542 public:
1543  explicit type_function(const args_list& args)
1544  : function_expression("type", args, 1, 1)
1545  {}
1546 private:
1547  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1548  const variant& v = args()[0]->evaluate(variables, fdb);
1549  return variant(v.type_string());
1550  }
1551 };
1552 
1553 } // namespace builtins
1554 
1555 namespace actions {
1556 
1558 public:
1559  explicit safe_call_function(const args_list& args)
1560  : function_expression("safe_call", args, 2, 2) {}
1561 private:
1562  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1563  const variant main = args()[0]->evaluate(variables, fdb);
1564  const expression_ptr backup_formula = args()[1];
1565 
1566  return variant(std::make_shared<safe_call_callable>(main, backup_formula));
1567  }
1568 };
1569 
1571 public:
1572  explicit set_var_function(const args_list& args)
1573  : function_expression("set_var", args, 2, 2) {}
1574 private:
1575  variant execute(const formula_callable& variables, formula_debugger *fdb) const {
1576  return variant(std::make_shared<set_var_callable>(args()[0]->evaluate(variables, add_debug_info(fdb, 0, "set_var:key")).as_string(), args()[1]->evaluate(variables, add_debug_info(fdb, 1, "set_var:value"))));
1577  }
1578 };
1579 
1580 } // namespace actions
1581 
1582 variant key_value_pair::get_value(const std::string& key) const
1583 {
1584  if(key == "key")
1585  {
1586  return key_;
1587  } else
1588  if(key == "value")
1589  {
1590  return value_;
1591  } else
1592  return variant();
1593 }
1594 
1595 void key_value_pair::get_inputs(formula_input_vector& inputs) const {
1596  add_input(inputs, "key");
1597  add_input(inputs, "value");
1598 }
1599 
1600 
1601 void key_value_pair::serialize_to_string(std::string& str) const {
1602  str += "pair(";
1603  str += key_.serialize_to_string();
1604  str += ",";
1605  str += value_.serialize_to_string();
1606  str += ")";
1607 }
1608 
1609 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)
1610  : function_expression(name, args, arg_names.size(), arg_names.size()),
1611  formula_(formula), precondition_(precondition), arg_names_(arg_names), star_arg_(-1)
1612 {
1613  for(size_t n = 0; n != arg_names_.size(); ++n) {
1614  if(arg_names_.empty() == false && arg_names_[n][arg_names_[n].size()-1] == '*') {
1615  arg_names_[n].resize(arg_names_[n].size()-1);
1616  star_arg_ = n;
1617  break;
1618  }
1619  }
1620 }
1621 
1623 {
1624  static std::string indent;
1625  indent += " ";
1626  DBG_NG << indent << "executing '" << formula_->str() << "'\n";
1627  const int begin_time = SDL_GetTicks();
1628  map_formula_callable callable;
1629  for(size_t n = 0; n != arg_names_.size(); ++n) {
1630  variant var = args()[n]->evaluate(variables,fdb);
1631  callable.add(arg_names_[n], var);
1632  if(static_cast<int>(n) == star_arg_) {
1633  callable.set_fallback(var.as_callable());
1634  }
1635  }
1636 
1637  if(precondition_) {
1638  if(!precondition_->evaluate(callable,fdb).as_bool()) {
1639  DBG_NG << "FAILED function precondition for function '" << formula_->str() << "' with arguments: ";
1640  for(size_t n = 0; n != arg_names_.size(); ++n) {
1641  DBG_NG << " arg " << (n+1) << ": " << args()[n]->evaluate(variables,fdb).to_debug_string() << "\n";
1642  }
1643  }
1644  }
1645 
1646  variant res = formula_->evaluate(callable,fdb);
1647  const int taken = SDL_GetTicks() - begin_time;
1648  DBG_NG << indent << "returning: " << taken << "\n";
1649  indent.resize(indent.size() - 2);
1650 
1651  return res;
1652 }
1653 
1655 {
1657 }
1658 
1659 function_symbol_table::function_symbol_table(std::shared_ptr<function_symbol_table> parent) : parent(parent ? parent : get_builtins()) {}
1660 
1662 {
1663  custom_formulas_[name] = fcn;
1664 }
1665 
1666 expression_ptr function_symbol_table::create_function(const std::string& fn, const std::vector<expression_ptr>& args) const
1667 {
1668  const functions_map::const_iterator i = custom_formulas_.find(fn);
1669  if(i != custom_formulas_.end()) {
1670  return i->second->generate_function_expression(args);
1671  }
1672 
1673  if(parent) {
1674  expression_ptr res(parent->create_function(fn, args));
1675  if(res) {
1676  return res;
1677  }
1678  }
1679 
1680  throw formula_error("Unknown function: " + fn, "", "", 0);
1681 }
1682 
1683 std::set<std::string> function_symbol_table::get_function_names() const
1684 {
1685  std::set<std::string> res;
1686  if(parent) {
1687  res = parent->get_function_names();
1688  }
1689  for(functions_map::const_iterator iter = custom_formulas_.begin(); iter != custom_formulas_.end(); ++iter ) {
1690  res.insert((*iter).first);
1691  }
1692  return res;
1693 }
1694 
1695 std::shared_ptr<function_symbol_table> function_symbol_table::get_builtins() {
1696  static function_symbol_table functions_table(builtins_tag);
1697 
1698  if(functions_table.empty()) {
1699  functions_table.parent = nullptr;
1700  using namespace builtins;
1702  DECLARE_WFL_FUNCTION(dir);
1704  DECLARE_WFL_FUNCTION(switch);
1705  DECLARE_WFL_FUNCTION(abs);
1706  DECLARE_WFL_FUNCTION(min);
1707  DECLARE_WFL_FUNCTION(max);
1708  DECLARE_WFL_FUNCTION(choose);
1709  DECLARE_WFL_FUNCTION(debug_float);
1710  DECLARE_WFL_FUNCTION(debug_print);
1711  DECLARE_WFL_FUNCTION(debug_profile);
1712  DECLARE_WFL_FUNCTION(wave);
1714  DECLARE_WFL_FUNCTION(contains_string);
1715  DECLARE_WFL_FUNCTION(find_string);
1717  DECLARE_WFL_FUNCTION(filter);
1719  DECLARE_WFL_FUNCTION(map);
1720  DECLARE_WFL_FUNCTION(zip);
1721  DECLARE_WFL_FUNCTION(take_while);
1722  DECLARE_WFL_FUNCTION(reduce);
1723  DECLARE_WFL_FUNCTION(sum);
1724  DECLARE_WFL_FUNCTION(head);
1725  DECLARE_WFL_FUNCTION(tail);
1727  DECLARE_WFL_FUNCTION(null);
1728  DECLARE_WFL_FUNCTION(ceil);
1729  DECLARE_WFL_FUNCTION(floor);
1730  DECLARE_WFL_FUNCTION(trunc);
1731  DECLARE_WFL_FUNCTION(frac);
1732  DECLARE_WFL_FUNCTION(sgn);
1733  DECLARE_WFL_FUNCTION(round);
1734  DECLARE_WFL_FUNCTION(as_decimal);
1735  DECLARE_WFL_FUNCTION(pair);
1736  DECLARE_WFL_FUNCTION(loc);
1738  DECLARE_WFL_FUNCTION(adjacent_locs);
1739  DECLARE_WFL_FUNCTION(are_adjacent);
1740  DECLARE_WFL_FUNCTION(relative_dir);
1741  DECLARE_WFL_FUNCTION(direction_from);
1742  DECLARE_WFL_FUNCTION(rotate_loc_around);
1743  DECLARE_WFL_FUNCTION(index_of);
1744  DECLARE_WFL_FUNCTION(keys);
1745  DECLARE_WFL_FUNCTION(values);
1746  DECLARE_WFL_FUNCTION(tolist);
1747  DECLARE_WFL_FUNCTION(tomap);
1748  DECLARE_WFL_FUNCTION(substring);
1749  DECLARE_WFL_FUNCTION(replace);
1750  DECLARE_WFL_FUNCTION(length);
1751  DECLARE_WFL_FUNCTION(concatenate);
1752  DECLARE_WFL_FUNCTION(sin);
1753  DECLARE_WFL_FUNCTION(cos);
1754  DECLARE_WFL_FUNCTION(tan);
1755  DECLARE_WFL_FUNCTION(asin);
1756  DECLARE_WFL_FUNCTION(acos);
1757  DECLARE_WFL_FUNCTION(atan);
1758  DECLARE_WFL_FUNCTION(sqrt);
1759  DECLARE_WFL_FUNCTION(cbrt);
1760  DECLARE_WFL_FUNCTION(root);
1761  DECLARE_WFL_FUNCTION(log);
1762  DECLARE_WFL_FUNCTION(exp);
1764  DECLARE_WFL_FUNCTION(hypot);
1766  }
1767 
1768  return std::shared_ptr<function_symbol_table>(&functions_table, [](function_symbol_table*){});
1769 }
1770 
1772  using namespace actions;
1773  function_symbol_table& functions_table = *this;
1774  DECLARE_WFL_FUNCTION(safe_call);
1775  DECLARE_WFL_FUNCTION(set_var);
1776 }
1777 
1778 }
loc_function(const args_list &args)
Definition: function.cpp:1427
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:115
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:183
const_formula_ptr formula_
Definition: function.hpp:115
const_formula_callable_ptr as_callable() const
Definition: variant.hpp:79
static DIRECTION parse_direction(const std::string &str)
Definition: location.cpp:64
str_upper_function(const args_list &args)
Definition: function.cpp:545
static lg::log_domain log_engine("engine")
direction_from_function(const args_list &args)
Definition: function.cpp:1514
void display_float(const map_location &location, const std::string &text) const
Definition: function.cpp:287
map_function(const args_list &args)
Definition: function.cpp:1036
pair_function(const args_list &args)
Definition: function.cpp:1440
debug_print_function(const args_list &args)
Definition: function.cpp:295
std::vector< char_t > string
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:663
pi_function(const args_list &args)
Definition: function.cpp:748
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:935
values_function(const args_list &args)
Definition: function.cpp:374
tomap_function(const args_list &args)
Definition: function.cpp:407
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:85
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:412
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1245
std::vector< expression_ptr > args_list
Definition: function.hpp:57
void add_function(const std::string &name, formula_function_ptr fcn)
Definition: function.cpp:1661
variant b_
Definition: function.cpp:851
std::set< std::string > get_function_names() const
Definition: function.cpp:1683
#define DBG_NG
Definition: function.cpp:30
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:965
void set_fallback(const_formula_callable_ptr fallback)
Definition: callable.hpp:258
map_location rotate_right_around_center(const map_location &center, int k) const
Definition: location.cpp:305
dir_function(const args_list &args)
Definition: function.cpp:110
Formula AI debugger.
#define a
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.hpp:299
sort_function(const args_list &args)
Definition: function.cpp:883
int as_int() const
Definition: variant.cpp:298
formula_debugger * add_debug_info(formula_debugger *fdb, int arg_number, const std::string &f_name)
expression_ptr create_function(const std::string &fn, const std::vector< expression_ptr > &args) const
Definition: function.cpp:1666
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1518
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:777
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:532
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:692
#define LOG_SF
Definition: function.cpp:32
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:601
min_function(const args_list &args)
Definition: function.cpp:197
replace_function(const args_list &args)
Definition: function.cpp:481
take_while_function(const args_list &args)
Definition: function.cpp:1073
distance_between_function(const args_list &args)
Definition: function.cpp:1454
std::vector< variant > get_input(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1112
if_function(const args_list &args)
Definition: function.cpp:131
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1281
safe_call_function(const args_list &args)
Definition: function.cpp:1559
debug_float_function(const args_list &args)
Definition: function.cpp:261
debug_function(const args_list &args)
Definition: function.cpp:81
static lg::log_domain log_scripting_formula("scripting/formula")
contains_string_function(const args_list &args)
Definition: function.cpp:930
std::vector< formula_input > formula_input_vector
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1008
const_formula_ptr formula_
Definition: function.hpp:97
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:333
reverse_function(const args_list &args)
Definition: function.cpp:908
substring_function(const args_list &args)
Definition: function.cpp:446
variant_iterator end() const
Definition: variant.cpp:266
std::shared_ptr< formula_function > formula_function_ptr
Definition: function.hpp:138
DIRECTION get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
Definition: location.cpp:225
const std::vector< std::string > items
are_adjacent_function(const args_list &args)
Definition: function.cpp:1488
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1416
#define d
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1366
zip_function(const args_list &args)
Definition: function.cpp:1092
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:450
std::shared_ptr< formula_expression > expression_ptr
Definition: formula.hpp:28
sin_function(const args_list &args)
Definition: function.cpp:571
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1381
index_of_function(const args_list &args)
Definition: function.cpp:772
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:379
asin_function(const args_list &args)
Definition: function.cpp:613
wave_function(const args_list &args)
Definition: function.cpp:835
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1077
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:521
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:618
head_function(const args_list &args)
Definition: function.cpp:1216
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:634
#define b
log_function(const args_list &args)
Definition: function.cpp:705
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1269
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:913
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1547
tolist_function(const args_list &args)
Definition: function.cpp:387
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1492
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:588
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1532
static std::ostream & output()
Definition: log.cpp:52
frac_function(const args_list &args)
Definition: function.cpp:1377
root_function(const args_list &args)
Definition: function.cpp:688
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Definition: location.hpp:339
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:159
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:888
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:799
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:549
map_formula_callable & add(const std::string &key, const variant &value)
Definition: callable.hpp:252
bool as_bool() const
Returns a boolean state of the variant value.
Definition: variant.cpp:320
size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
Definition: location.hpp:382
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:485
std::shared_ptr< function_expression > function_expression_ptr
Definition: function.hpp:103
atan_function(const args_list &args)
Definition: function.cpp:646
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1505
acos_function(const args_list &args)
Definition: function.cpp:630
round_function(const args_list &args)
Definition: function.cpp:1315
static std::shared_ptr< function_symbol_table > get_builtins()
Definition: function.cpp:1695
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:300
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1040
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:840
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:679
sgn_function(const args_list &args)
Definition: function.cpp:1393
cos_function(const args_list &args)
Definition: function.cpp:584
cbrt_function(const args_list &args)
Definition: function.cpp:675
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1444
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1147
find_function(const args_list &args)
Definition: function.cpp:1003
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:562
static int indent
Definition: log.cpp:45
abs_function(const args_list &args)
Definition: function.cpp:178
filter_function(const args_list &args)
Definition: function.cpp:961
Encapsulates the map of the game.
Definition: location.hpp:40
const_formula_ptr precondition_
Definition: function.hpp:116
void float_label(const map_location &loc, const std::string &text, const color_t &color)
Function to float a label above a tile.
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1459
size_t size(const utf8::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
adjacent_locs_function(const args_list &args)
Definition: function.cpp:1468
std::shared_ptr< function_symbol_table > parent
Definition: function.hpp:142
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1220
std::string string_cast() const
Definition: variant.cpp:644
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1397
str_lower_function(const args_list &args)
Definition: function.cpp:558
bool is_empty() const
Definition: variant.cpp:271
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:950
function_expression_ptr generate_function_expression(const std::vector< expression_ptr > &args) const
Definition: function.cpp:1654
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:202
switch_function(const args_list &args)
Definition: function.cpp:154
int as_decimal() const
Returns variant's internal representation of decimal number: ie, 1.234 is represented as 1234...
Definition: variant.cpp:307
variant execute(const formula_callable &, formula_debugger *) const
Definition: function.cpp:752
variant get_keys() const
Definition: variant.cpp:237
action_function_symbol_table(std::shared_ptr< function_symbol_table > parent=nullptr)
Definition: function.cpp:1771
sum_function(const args_list &args)
Definition: function.cpp:1171
int main()
static void expr(LexState *ls, expdesc *v)
Definition: lparser.cpp:1078
const args_list & args() const
Definition: function.hpp:74
static map_location::DIRECTION s
hypot_function(const args_list &args)
Definition: function.cpp:759
ceil_function(const args_list &args)
Definition: function.cpp:1294
type_function(const args_list &args)
Definition: function.cpp:1543
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:266
bool operator()(const variant &a, const variant &b) const
Definition: function.cpp:1108
as_decimal_function(const args_list &args)
Definition: function.cpp:1412
CURSOR_TYPE get()
Definition: cursor.cpp:194
#define i
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:366
const_formula_ptr precondition_
Definition: function.hpp:98
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1175
keys_function(const args_list &args)
Definition: function.cpp:361
#define debug(x)
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1562
std::shared_ptr< const formula > const_formula_ptr
Definition: formula_fwd.hpp:23
reduce_function(const args_list &args)
Definition: function.cpp:1143
static int sort(lua_State *L)
Definition: ltablib.cpp:411
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:709
exp_function(const args_list &args)
Definition: function.cpp:730
variant a_
Definition: function.cpp:851
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1125
std::vector< std::string > arg_names_
Definition: function.hpp:99
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1472
bool is_list() const
Definition: variant.hpp:62
floor_function(const args_list &args)
Definition: function.cpp:1341
sqrt_function(const args_list &args)
Definition: function.cpp:659
bool is_null() const
Functions to test the type of the internal value.
Definition: variant.hpp:58
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1298
variant operator()(const variant &v) const
Definition: function.cpp:1099
#define DECLARE_WFL_FUNCTION(name)
Declares a function name in the local function table functions_table.
Definition: function.hpp:162
variant evaluate(const formula_callable &variables, formula_debugger *fdb=nullptr) const
Definition: function.hpp:36
size_function(const args_list &args)
Definition: function.cpp:1265
const formula_callable * fallback_
Definition: function.cpp:850
display_chat_manager & get_chat_manager()
concatenate_function(const args_list &args)
Definition: function.cpp:528
set_var_function(const args_list &args)
Definition: function.cpp:1572
std::string type_string() const
Gets string name of the current value type.
Definition: variant.hpp:144
bool is_map() const
Definition: variant.hpp:64
function_symbol_table(builtins_tag_t)
Definition: function.hpp:145
#define f
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:575
Definition: contexts.hpp:42
bool find(E event, F functor)
Tests whether an event handler is available.
size_t num_elements() const
Definition: variant.cpp:276
max_function(const args_list &args)
Definition: function.cpp:229
Standard logging facilities (interface).
trunc_function(const args_list &args)
Definition: function.cpp:1362
bool is_string() const
Definition: variant.hpp:63
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
Definition: variant.cpp:649
bool is_decimal() const
Definition: variant.hpp:60
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:734
map_location get_direction(DIRECTION d, unsigned int n=1u) const
Definition: location.hpp:257
static const char * name(const std::vector< SDL_Joystick * > &joysticks, const size_t index)
Definition: joystick.cpp:48
variant_iterator begin() const
Definition: variant.cpp:261
tan_function(const args_list &args)
Definition: function.cpp:597
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1345
static void reverse(lua_State *L, StkId from, StkId to)
Definition: lapi.cpp:193
std::shared_ptr< T > convert_to() const
Definition: variant.hpp:96
find_string_function(const args_list &args)
Definition: function.cpp:945
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:650
Iterator class for the variant.
Definition: variant.hpp:182
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1575
tail_function(const args_list &args)
Definition: function.cpp:1241
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:234
variant get_values() const
Definition: variant.cpp:249
void add_chat_message(const time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
null_function(const args_list &args)
Definition: function.cpp:1277
rotate_loc_around_function(const args_list &args)
Definition: function.cpp:1528
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1622
functions_map custom_formulas_
Definition: function.hpp:143
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1431
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:136
static map_location::DIRECTION n
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:392
static std::string write_direction(DIRECTION dir)
Definition: location.cpp:139
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
static std::deque< std::string > call_stack
Definition: function.cpp:38
expression_ptr expr_
Definition: function.cpp:849
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:1319
variant execute(const formula_callable &variables, formula_debugger *fdb) const
Definition: function.cpp:763
length_function(const args_list &args)
Definition: function.cpp:517
choose_function(const args_list &args)
Definition: function.cpp:794
relative_dir_function(const args_list &args)
Definition: function.cpp:1501
EXIT_STATUS start(const config &game_conf, CVideo &video, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Definition: editor_main.cpp:28
static game_display * get_singleton()
std::vector< std::string > args_
Definition: function.hpp:117
debug_profile_function(const args_list &args)
Definition: function.cpp:328