19 #include "formula/callable_objects.hpp" 26 #include <boost/math/constants/constants.hpp> 33 #define DBG_NG LOG_STREAM(debug, log_engine) 35 #define LOG_SF LOG_STREAM(info, log_scripting_formula) 36 #define WRN_SF LOG_STREAM(warn, log_scripting_formula) 37 #define ERR_SF LOG_STREAM(err, log_scripting_formula) 49 call_stack_manager::call_stack_manager(
const std::string& str)
51 call_stack.push_back(str);
54 call_stack_manager::~call_stack_manager()
56 call_stack.pop_back();
61 std::ostringstream res;
62 for(
const auto& frame : call_stack) {
64 res <<
" " << frame <<
"\n";
71 std::string function_expression::str()
const 76 bool first_arg =
true;
93 std::shared_ptr<formula_debugger> fdbp;
94 bool need_wrapper =
false;
102 if(args().
size() == 1) {
104 return args()[0]->evaluate(variables, fdb);
115 variant var = args()[0]->evaluate(variables, fdb);
120 std::vector<variant> res;
121 for(std::size_t
i = 0;
i < inputs.size(); ++
i) {
123 res.emplace_back(input.
name);
131 for(std::size_t
n = 0;
n < args().size() - 1;
n += 2) {
132 if(args()[
n]->evaluate(variables, fdb).as_bool()) {
133 return args()[
n + 1]->evaluate(variables, fdb);
137 if((args().
size() % 2) != 0) {
138 return args().back()->evaluate(variables, fdb);
146 variant var = args()[0]->evaluate(variables, fdb);
148 for(std::size_t
n = 1;
n < args().size() - 1;
n += 2) {
149 variant val = args()[
n]->evaluate(variables, fdb);
152 return args()[
n + 1]->evaluate(variables, fdb);
156 if((args().
size() % 2) == 0) {
157 return args().back()->evaluate(variables, fdb);
165 const variant input = args()[0]->evaluate(variables, fdb);
168 return variant(n >= 0 ? n : -n, variant::DECIMAL_VARIANT);
171 return variant(n >= 0 ? n : -n);
177 variant res = args()[0]->evaluate(variables, fdb);
183 res = *std::min_element(res.
begin(), res.
end());
186 for(std::size_t
n = 1;
n < args().size(); ++
n) {
187 variant v = args()[
n]->evaluate(variables, fdb);
194 v = *std::min_element(v.
begin(), v.
end());
207 variant res = args()[0]->evaluate(variables, fdb);
213 res = *std::max_element(res.
begin(), res.
end());
216 for(std::size_t
n = 1;
n < args().size(); ++
n) {
217 variant v = args()[
n]->evaluate(variables, fdb);
224 v = *std::max_element(v.
begin(), v.
end());
237 void display_float(
const map_location& location,
const std::string& text)
245 const args_list& arguments = args();
246 const variant var0 = arguments[0]->evaluate(variables, fdb);
247 const variant var1 = arguments[1]->evaluate(variables, fdb);
252 if(arguments.size() == 2) {
254 display_float(location, text);
257 const variant var2 = arguments[2]->evaluate(variables, fdb);
259 display_float(location, text);
266 const variant var1 = args()[0]->evaluate(variables, fdb);
268 std::string str1, str2;
270 if(args().
size() == 1) {
284 const variant var2 = args()[1]->evaluate(variables, fdb);
287 LOG_SF << str1 <<
": " << str2;
300 std::string speaker =
"WFL";
303 if(args().
size() == 2) {
304 speaker = args()[0]->evaluate(variables, fdb).string_cast();
308 const variant value = args()[i_value]->evaluate(variables, fdb);
311 for(
int i = 1;
i < 1000;
i++) {
312 const long start = SDL_GetTicks();
313 args()[i_value]->evaluate(variables, fdb);
314 run_time += SDL_GetTicks() -
start;
317 std::ostringstream str;
318 str <<
"Evaluated in " << (run_time / 1000.0) <<
" ms on average";
320 LOG_SF << speaker <<
": " << str.str();
332 const variant map = args()[0]->evaluate(variables, fdb);
338 const variant map = args()[0]->evaluate(variables, fdb);
344 const variant var = args()[0]->evaluate(variables, fdb);
346 std::vector<variant> tmp;
356 const variant var_1 = args()[0]->evaluate(variables, fdb);
358 std::map<variant, variant> tmp;
360 if(args().
size() == 2) {
361 const variant var_2 = args()[1]->evaluate(variables, fdb);
367 tmp[var_1[
i]] = var_2[
i];
372 tmp[kv->query_value(
"key")] = kv->query_value(
"value");
374 auto map_it = tmp.find(*it);
376 if(map_it == tmp.end()) {
379 map_it->second =
variant(map_it->second.as_int() + 1);
390 std::string result = args()[0]->evaluate(variables, fdb).as_string();
392 int offset = args()[1]->evaluate(variables, fdb).as_int();
394 offset += result.size();
400 if(static_cast<std::size_t>(offset) >= result.size()) {
405 if(args().
size() > 2) {
406 int size = args()[2]->evaluate(variables, fdb).as_int();
410 offset = std::max(0, offset - size + 1);
413 return variant(result.substr(offset, size));
416 return variant(result.substr(offset));
421 std::string result = args()[0]->evaluate(variables, fdb).as_string();
422 std::string replacement = args().back()->evaluate(variables, fdb).as_string();
424 int offset = args()[1]->evaluate(variables, fdb).as_int();
426 offset += result.size();
432 if(static_cast<std::size_t>(offset) >= result.size()) {
437 if(args().
size() > 3) {
438 int size = args()[2]->evaluate(variables, fdb).as_int();
442 offset = std::max(0, offset - size + 1);
445 return variant(result.replace(offset, size, replacement));
448 return variant(result.replace(offset, std::string::npos, replacement));
453 std::string result = args()[0]->evaluate(variables, fdb).as_string();
454 std::string
insert = args().back()->evaluate(variables, fdb).as_string();
456 int offset = args()[1]->evaluate(variables, fdb).as_int();
458 offset += result.size();
463 }
else if(static_cast<std::size_t>(offset) >= result.size()) {
464 return variant(result + insert);
467 return variant(result.insert(offset, insert));
472 return variant(args()[0]->evaluate(variables, fdb).as_string().length());
479 result += arg->evaluate(variables, fdb).string_cast();
487 std::string str = args()[0]->evaluate(variables, fdb).as_string();
488 std::transform(str.begin(), str.end(), str.begin(),
static_cast<int (*)(
int)
>(std::toupper));
494 std::string str = args()[0]->evaluate(variables, fdb).as_string();
495 std::transform(str.begin(), str.end(), str.begin(),
static_cast<int (*)(
int)
>(std::tolower));
501 const double angle = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
502 const double result = std::sin(angle * pi<double>() / 180.0);
503 return variant(result, variant::DECIMAL_VARIANT);
508 const double angle = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
509 const double result = std::cos(angle * pi<double>() / 180.0);
510 return variant(result, variant::DECIMAL_VARIANT);
515 const double angle = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
516 const double result = std::tan(angle * pi<double>() / 180.0);
517 if(std::isnan(result) || result <= INT_MIN || result >= INT_MAX) {
521 return variant(result, variant::DECIMAL_VARIANT);
526 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
527 const double result = std::asin(num) * 180.0 / pi<double>();
528 if(std::isnan(result)) {
532 return variant(result, variant::DECIMAL_VARIANT);
537 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
538 const double result = std::acos(num) * 180.0 / pi<double>();
539 if(std::isnan(result)) {
543 return variant(result, variant::DECIMAL_VARIANT);
548 if(args().
size() == 1) {
549 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
550 const double result = std::atan(num) * 180.0 / pi<double>();
551 return variant(result, variant::DECIMAL_VARIANT);
553 const double y = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
554 const double x = args()[1]->evaluate(variables, fdb).as_decimal() / 1000.0;
555 const double result = std::atan2(y, x) * 180.0 / pi<double>();
556 return variant(result, variant::DECIMAL_VARIANT);
562 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
563 const double result = std::sqrt(num);
564 if(std::isnan(result)) {
568 return variant(result, variant::DECIMAL_VARIANT);
573 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
574 const double result = num < 0 ? -std::pow(-num, 1.0 / 3.0) : std::pow(num, 1.0 / 3.0);
575 return variant(result, variant::DECIMAL_VARIANT);
580 const double base = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
581 const double root = args()[1]->evaluate(variables, fdb).as_decimal() / 1000.0;
582 const double result = base < 0 && std::fmod(root, 2) == 1 ? -std::pow(-base, 1.0 / root) : std::pow(base, 1.0 / root);
583 if(std::isnan(result)) {
587 return variant(result, variant::DECIMAL_VARIANT);
592 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
593 if(args().
size() == 1) {
594 const double result = std::log(num);
595 if(std::isnan(result)) {
599 return variant(result, variant::DECIMAL_VARIANT);
602 const double base = args()[1]->evaluate(variables, fdb).as_decimal() / 1000.0;
603 const double result = std::log(num) / std::log(base);
604 if(std::isnan(result)) {
608 return variant(result, variant::DECIMAL_VARIANT);
613 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
614 const double result = std::exp(num);
615 if(result == 0 || result >= INT_MAX) {
621 return variant(result, variant::DECIMAL_VARIANT);
628 return variant(pi<double>(), variant::DECIMAL_VARIANT);
633 const double x = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
634 const double y = args()[1]->evaluate(variables, fdb).as_decimal() / 1000.0;
635 return variant(std::hypot(x, y), variant::DECIMAL_VARIANT);
640 const variant value = args()[0]->evaluate(variables, fdb);
641 const variant list = args()[1]->evaluate(variables, fdb);
644 if(list[
i] == value) {
654 const variant items = args()[0]->evaluate(variables, fdb);
658 if(args().
size() == 2) {
669 const std::string
self = args()[1]->evaluate(variables, fdb).as_string();
672 self_callable.
add(
self, *it);
674 const variant val = args().back()->evaluate(
693 const int value = args()[0]->evaluate(variables, fdb).as_int() % 1000;
694 const double angle = 2.0 * pi<double>() * (static_cast<double>(value) / 1000.0);
695 return variant(static_cast<int>(std::sin(angle) * 1000.0));
700 const double lo = args()[0]->evaluate(variables,
add_debug_info(fdb, 0,
"lerp:lo")).as_decimal() / 1000.0;
701 const double hi = args()[1]->evaluate(variables,
add_debug_info(fdb, 1,
"lerp:hi")).as_decimal() / 1000.0;;
702 const double alpha = args()[2]->evaluate(variables,
add_debug_info(fdb, 2,
"lerp:alpha")).as_decimal() / 1000.0;;
703 return variant(static_cast<int>((lo + alpha * (hi - lo)) * 1000.0), variant::DECIMAL_VARIANT);
734 return expr_->evaluate(*this).as_bool();
738 variant get_value(
const std::string& key)
const 742 }
else if(key ==
"b") {
762 variant list = args()[0]->evaluate(variables, fdb);
764 std::vector<variant> vars;
768 vars.push_back(list[
n]);
771 if(args().
size() == 1) {
772 std::sort(vars.begin(), vars.end());
774 std::sort(vars.begin(), vars.end(), variant_comparator(args()[1], variables));
782 const variant& arg = args()[0]->evaluate(variables, fdb);
785 std::string str = args()[0]->evaluate(variables, fdb).
as_string();
786 std::reverse(str.begin(), str.end());
790 std::vector<variant> list = args()[0]->evaluate(variables, fdb).as_list();
791 std::reverse(list.begin(), list.end());
801 std::string str = args()[0]->evaluate(variables, fdb).as_string();
802 std::string key = args()[1]->evaluate(variables, fdb).as_string();
804 return variant(str.find(key) != std::string::npos);
809 const std::string str = args()[0]->evaluate(variables, fdb).as_string();
810 const std::string key = args()[1]->evaluate(variables, fdb).as_string();
812 std::size_t pos = str.find(key);
813 return variant(static_cast<int>(pos));
818 std::vector<variant> list_vars;
819 std::map<variant, variant> map_vars;
821 const variant items = args()[0]->evaluate(variables, fdb);
823 if(args().
size() == 2) {
829 map_vars[(*it).get_member(
"key")] = (*it).get_member(
"value");
831 list_vars.push_back(*it);
837 const std::string
self = args()[1]->evaluate(variables, fdb).as_string();
840 self_callable.
add(
self, *it);
842 const variant val = args()[2]->evaluate(
847 map_vars[(*it).get_member(
"key")] = (*it).get_member(
"value");
849 list_vars.push_back(*it);
864 const variant items = args()[0]->evaluate(variables, fdb);
866 if(args().
size() == 2) {
875 const std::string
self = args()[1]->evaluate(variables, fdb).as_string();
878 self_callable.
add(
self, *it);
880 const variant val = args().back()->evaluate(
894 std::vector<variant> list_vars;
895 std::map<variant, variant> map_vars;
896 const variant items = args()[0]->evaluate(variables, fdb);
898 if(args().
size() == 2) {
902 map_vars[(*it).get_member(
"key")] = val;
904 list_vars.push_back(val);
909 const std::string
self = args()[1]->evaluate(variables, fdb).as_string();
912 self_callable.
add(
self, *it);
914 const variant val = args().back()->evaluate(
918 map_vars[(*it).get_member(
"key")] = val;
920 list_vars.push_back(val);
934 const variant&
items = args()[0]->evaluate(variables, fdb);
937 for(; it != items.
end(); ++it) {
945 std::vector<variant> result(items.
begin(), it);
953 explicit indexer(std::size_t
i)
973 bool operator()(
const variant&
a,
const variant&
b)
const 975 return a.num_elements() < b.num_elements();
979 std::vector<variant> get_input(
980 const function_expression::args_list& args,
981 const formula_callable& variables,
982 formula_debugger* fdb)
984 if(args.size() == 1) {
985 const variant list = args[0]->evaluate(variables, fdb);
986 return std::vector<variant>(list.begin(), list.end());
988 std::vector<variant> input;
989 input.reserve(args.size());
992 input.push_back(
expr->evaluate(variables, fdb));
1002 const std::vector<variant> input = get_input(args(), variables, fdb);
1003 std::vector<variant>
output;
1007 std::size_t max_i = std::max_element(input.begin(), input.end(), comparator())->num_elements();
1008 output.reserve(max_i);
1010 for(std::size_t
i = 0;
i < max_i;
i++) {
1011 std::vector<variant> elem(input.size());
1012 std::transform(input.begin(), input.end(), elem.begin(), indexer(
i));
1013 output.emplace_back(elem);
1021 const variant items = args()[0]->evaluate(variables, fdb);
1022 const variant initial = args().size() == 2 ?
variant() : args()[1]->evaluate(variables, fdb);
1030 if(res != initial) {
1035 for(; it != items.
end(); ++it) {
1036 self_callable.
add(
"a", res);
1037 self_callable.
add(
"b", *it);
1038 res = args().back()->evaluate(
1048 const variant items = args()[0]->evaluate(variables, fdb);
1050 if(items[0].is_list()) {
1051 std::vector<variant> tmp;
1053 if(args().
size() >= 2) {
1054 res = args()[1]->evaluate(variables, fdb);
1058 }
else if(items[0].is_map()) {
1059 std::map<variant, variant> tmp;
1061 if(args().
size() >= 2) {
1062 res = args()[1]->evaluate(variables, fdb);
1067 if(args().size() >= 2) {
1068 res = args()[1]->evaluate(variables, fdb);
1074 res = res + items[
n];
1082 const variant items = args()[0]->evaluate(variables, fdb);
1084 if(it == items.
end()) {
1088 if(args().
size() == 1) {
1092 const int n = items.
num_elements(), req = args()[1]->evaluate(variables, fdb).as_int();
1093 const int count = req < 0 ? n - std::min(-req, n) : std::min(req, n);
1096 std::advance(end, count);
1098 std::vector<variant> res;
1099 std::copy(it, end, std::back_inserter(res));
1105 const variant items = args()[0]->evaluate(variables, fdb);
1107 if(it == items.
begin()) {
1111 if(args().
size() == 1) {
1115 const int n = items.
num_elements(), req = args()[1]->evaluate(variables, fdb).as_int();
1116 const int count = req < 0 ? n - std::min(-req, n) : std::min(req, n);
1118 std::advance(it, -count);
1119 std::vector<variant> res;
1121 std::copy(it, items.
end(), std::back_inserter(res));
1127 const variant items = args()[0]->evaluate(variables, fdb);
1133 if(!args().empty()) {
1134 for(std::size_t
i = 0;
i < args().size(); ++
i) {
1135 args()[
i]->evaluate(variables, fdb);
1144 variant decimal = args()[0]->evaluate(variables, fdb);
1147 if((d >= 0) && (d % 1000 != 0)) {
1158 variant decimal = args()[0]->evaluate(variables, fdb);
1165 }
else if(f <= -500) {
1176 variant decimal = args()[0]->evaluate(variables, fdb);
1179 if((d < 0) && (d % 1000 != 0)) {
1190 variant decimal = args()[0]->evaluate(variables, fdb);
1198 variant decimal = args()[0]->evaluate(variables, fdb);
1202 return variant(d, variant::DECIMAL_VARIANT);
1207 variant decimal = args()[0]->evaluate(variables, fdb);
1219 variant decimal = args()[0]->evaluate(variables, fdb);
1222 return variant(d, variant::DECIMAL_VARIANT);
1228 args()[0]->evaluate(variables,
add_debug_info(fdb, 0,
"loc:x")).as_int(),
1235 return variant(std::make_shared<key_value_pair>(
1236 args()[0]->evaluate(variables,
add_debug_info(fdb, 0,
"pair:key")),
1237 args()[1]->evaluate(variables,
add_debug_info(fdb, 1,
"pair_value"))
1244 ->evaluate(variables,
add_debug_info(fdb, 0,
"distance_between:location_A"))
1249 ->evaluate(variables,
add_debug_info(fdb, 1,
"distance_between:location_B"))
1259 ->evaluate(variables,
add_debug_info(fdb, 0,
"adjacent_locs:location"))
1263 std::vector<variant> v;
1265 v.emplace_back(std::make_shared<location_callable>(adj));
1274 ->evaluate(variables,
add_debug_info(fdb, 0,
"are_adjacent:location_A"))
1279 ->evaluate(variables,
add_debug_info(fdb, 1,
"are_adjacent:location_B"))
1289 ->evaluate(variables,
add_debug_info(fdb, 0,
"relative_dir:location_A"))
1294 ->evaluate(variables,
add_debug_info(fdb, 1,
"relative_dir:location_B"))
1304 ->evaluate(variables,
add_debug_info(fdb, 0,
"direction_from:location"))
1308 const std::string dir_str =
1309 args()[1]->evaluate(variables,
add_debug_info(fdb, 1,
"direction_from:dir")).as_string();
1311 int n = args().size() == 3
1312 ? args()[2]->evaluate(variables,
add_debug_info(fdb, 2,
"direction_from:count")).as_int()
1321 ->evaluate(variables,
add_debug_info(fdb, 0,
"direction_from:center"))
1326 ->evaluate(variables,
add_debug_info(fdb, 1,
"direction_from:location"))
1330 int n = args().size() == 3
1331 ? args()[2]->evaluate(variables,
add_debug_info(fdb, 2,
"direction_from:count")).as_int()
1339 const variant& v = args()[0]->evaluate(variables, fdb);
1349 const variant main = args()[0]->evaluate(variables, fdb);
1352 return variant(std::make_shared<safe_call_callable>(main, backup_formula));
1357 return variant(std::make_shared<set_var_callable>(
1358 args()[0]->evaluate(variables,
add_debug_info(fdb, 0,
"set_var:key")).as_string(),
1359 args()[1]->evaluate(variables,
add_debug_info(fdb, 1,
"set_var:value"))));
1364 variant key_value_pair::get_value(
const std::string& key)
const 1368 }
else if(key ==
"value") {
1377 add_input(inputs,
"key");
1378 add_input(inputs,
"value");
1381 void key_value_pair::serialize_to_string(std::string& str)
const 1384 str += key_.serialize_to_string();
1386 str += value_.serialize_to_string();
1390 formula_function_expression::formula_function_expression(
const std::string& name,
1394 const std::vector<std::string>& arg_names)
1397 , precondition_(precondition)
1398 , arg_names_(arg_names)
1412 static std::string
indent;
1417 const int begin_time = SDL_GetTicks();
1431 DBG_NG <<
"FAILED function precondition for function '" <<
formula_->str() <<
"' with arguments: ";
1434 DBG_NG <<
" arg " << (
n + 1) <<
": " <<
args()[
n]->evaluate(variables, fdb).to_debug_string();
1441 const int taken = SDL_GetTicks() - begin_time;
1442 DBG_NG << indent <<
"returning: " << taken;
1444 indent.resize(indent.size() - 2);
1450 const std::vector<expression_ptr>&
args)
const 1456 : parent(parent ? parent : get_builtins())
1466 const std::string& fn,
const std::vector<expression_ptr>& args)
const 1470 return i->second->generate_function_expression(args);
1485 std::set<std::string> res;
1487 res =
parent->get_function_names();
1501 if(functions_table.
empty()) {
1502 functions_table.
parent =
nullptr;
1504 using namespace builtins;
static DIRECTION parse_direction(const std::string &str)
static lg::log_domain log_engine("engine")
std::string type_string() const
Gets string name of the current value type.
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
DIRECTION get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
int main(int, char **argv)
std::vector< expression_ptr > args_list
formula_debugger * add_debug_info(formula_debugger *fdb, int arg_number, const std::string &f_name)
static lg::log_domain log_scripting_formula("scripting/formula")
std::vector< formula_input > formula_input_vector
const std::vector< std::string > items
std::shared_ptr< formula_function > formula_function_ptr
std::shared_ptr< formula_expression > expression_ptr
void add_chat_message(const std::time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
map_location get_direction(DIRECTION dir, unsigned int n=1u) const
const std::string & as_string() const
int as_decimal() const
Returns variant's internal representation of decimal number: ie, 1.234 is represented as 1234...
static std::ostream & output()
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
EXIT_STATUS start(const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
map_location rotate_right_around_center(const map_location ¢er, int k) const
std::shared_ptr< function_expression > function_expression_ptr
static thread_local std::deque< std::string > call_stack
For printing error messages when WFL parsing or evaluation fails, this contains the names of the WFL ...
The basic class for representing 8-bit RGB or RGBA colour values.
static std::shared_ptr< function_symbol_table > get_builtins()
variant_iterator end() const
Encapsulates the map of the game.
void float_label(const map_location &loc, const std::string &text, const color_t &color)
Function to float a label above a tile.
std::string string_cast() const
const_formula_callable_ptr as_callable() const
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
std::shared_ptr< function_symbol_table > parent
function_symbol_table(std::shared_ptr< function_symbol_table > parent=nullptr)
action_function_symbol_table(std::shared_ptr< function_symbol_table > parent=nullptr)
static map_location::DIRECTION s
std::string & insert(std::string &str, const std::size_t pos, const std::string &insert)
Insert a UTF-8 string at the specified position.
std::shared_ptr< const formula > const_formula_ptr
std::set< std::string > get_function_names() const
#define DECLARE_WFL_FUNCTION(name)
Declares a function name in the local function table functions_table.
const formula_callable * fallback_
display_chat_manager & get_chat_manager()
bool is_null() const
Functions to test the type of the internal value.
std::size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
const args_list & args() const
variant_iterator begin() const
#define DEFINE_WFL_FUNCTION(name, min_args, max_args)
Helper macro to declare an associated class for a WFL function.
expression_ptr create_function(const std::string &fn, const std::vector< expression_ptr > &args) const
Standard logging facilities (interface).
variant get_values() const
void add_function(const std::string &name, formula_function_ptr &&fcn)
std::size_t num_elements() const
Iterator class for the variant.
bool as_bool() const
Returns a boolean state of the variant value.
functions_map custom_formulas_
static map_location::DIRECTION n
static std::string write_direction(DIRECTION dir)
std::shared_ptr< T > convert_to() const
static game_display * get_singleton()
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const