19 #include "formula/callable_objects.hpp"
27 #include <boost/algorithm/string.hpp>
28 #include <boost/math/constants/constants.hpp>
34 using namespace boost::math::constants;
37 #define DBG_NG LOG_STREAM(debug, log_engine)
39 #define LOG_SF LOG_STREAM(info, log_scripting_formula)
40 #define WRN_SF LOG_STREAM(warn, log_scripting_formula)
41 #define ERR_SF LOG_STREAM(err, log_scripting_formula)
53 call_stack_manager::call_stack_manager(
const std::string& str)
58 call_stack_manager::~call_stack_manager()
65 std::ostringstream res;
68 res <<
" " << frame <<
"\n";
75 std::string function_expression::str()
const
80 bool first_arg =
true;
97 std::shared_ptr<formula_debugger> fdbp;
98 bool need_wrapper =
false;
106 if(args().
size() == 1) {
108 return args()[0]->evaluate(variables, fdb);
119 variant var = args()[0]->evaluate(variables, fdb);
124 std::vector<variant> res;
125 for(std::size_t
i = 0;
i < inputs.size(); ++
i) {
127 res.emplace_back(input.
name);
135 for(std::size_t
n = 0;
n < args().size() - 1;
n += 2) {
136 if(args()[
n]->evaluate(variables, fdb).as_bool()) {
137 return args()[
n + 1]->evaluate(variables, fdb);
141 if((args().
size() % 2) != 0) {
142 return args().back()->evaluate(variables, fdb);
150 variant var = args()[0]->evaluate(variables, fdb);
152 for(std::size_t
n = 1;
n < args().size() - 1;
n += 2) {
153 variant val = args()[
n]->evaluate(variables, fdb);
156 return args()[
n + 1]->evaluate(variables, fdb);
160 if((args().
size() % 2) == 0) {
161 return args().back()->evaluate(variables, fdb);
169 const variant input = args()[0]->evaluate(variables, fdb);
172 return variant(
n >= 0 ?
n : -
n, variant::DECIMAL_VARIANT);
181 variant res = args()[0]->evaluate(variables, fdb);
187 res = *std::min_element(res.
begin(), res.
end());
190 for(std::size_t
n = 1;
n < args().size(); ++
n) {
191 variant v = args()[
n]->evaluate(variables, fdb);
198 v = *std::min_element(v.
begin(), v.
end());
211 variant res = args()[0]->evaluate(variables, fdb);
217 res = *std::max_element(res.
begin(), res.
end());
220 for(std::size_t
n = 1;
n < args().size(); ++
n) {
221 variant v = args()[
n]->evaluate(variables, fdb);
228 v = *std::max_element(v.
begin(), v.
end());
241 void display_float(
const map_location& location,
const std::string& text)
249 const args_list& arguments = args();
250 const variant var0 = arguments[0]->evaluate(variables, fdb);
251 variant var1 = arguments[1]->evaluate(variables, fdb);
256 if(arguments.size() == 2) {
258 display_float(location, text);
261 const variant var2 = arguments[2]->evaluate(variables, fdb);
263 display_float(location, text);
270 std::string speaker =
"WFL";
273 if(args().
size() == 2) {
274 speaker = args()[0]->evaluate(variables, fdb).string_cast();
278 variant value = args()[i_value]->evaluate(variables, fdb);
281 LOG_SF << speaker <<
": " << str;
293 std::string speaker =
"WFL";
296 if(args().
size() == 2) {
297 speaker = args()[0]->evaluate(variables, fdb).string_cast();
301 const variant value = args()[i_value]->evaluate(variables, fdb);
302 const int run_count = 1000;
303 std::chrono::steady_clock::duration run_time;
305 for(
int i = 0;
i < run_count;
i++) {
306 const auto start = std::chrono::steady_clock::now();
307 args()[i_value]->evaluate(variables, fdb);
308 run_time += std::chrono::steady_clock::now() -
start;
312 auto average_ms = std::chrono::duration_cast<std::chrono::milliseconds>(run_time / run_count);
314 std::ostringstream str;
315 #ifdef __cpp_lib_format
316 str <<
"Evaluated in " << average_ms <<
" on average";
318 str <<
"Evaluated in " << average_ms.count() <<
" ms on average";
321 LOG_SF << speaker <<
": " << str.str();
333 const variant map = args()[0]->evaluate(variables, fdb);
339 const variant map = args()[0]->evaluate(variables, fdb);
345 const variant var = args()[0]->evaluate(variables, fdb);
347 std::vector<variant> tmp;
357 const variant var_1 = args()[0]->evaluate(variables, fdb);
359 std::map<variant, variant> tmp;
361 if(args().
size() == 2) {
362 const variant var_2 = args()[1]->evaluate(variables, fdb);
368 tmp[var_1[
i]] = var_2[
i];
373 tmp[kv->query_value(
"key")] = kv->query_value(
"value");
375 auto map_it = tmp.find(*it);
377 if(map_it == tmp.end()) {
380 map_it->second =
variant(map_it->second.as_int() + 1);
391 std::string result = args()[0]->evaluate(variables, fdb).as_string();
393 int offset = args()[1]->evaluate(variables, fdb).as_int();
395 offset += result.size();
401 if(
static_cast<std::size_t
>(offset) >= result.size()) {
406 if(args().
size() > 2) {
407 int size = args()[2]->evaluate(variables, fdb).as_int();
411 offset = std::max(0, offset -
size + 1);
417 return variant(result.substr(offset));
422 std::string result = args()[0]->evaluate(variables, fdb).as_string();
423 std::string replacement = args().back()->evaluate(variables, fdb).as_string();
425 int offset = args()[1]->evaluate(variables, fdb).as_int();
427 offset += result.size();
433 if(
static_cast<std::size_t
>(offset) >= result.size()) {
438 if(args().
size() > 3) {
439 int size = args()[2]->evaluate(variables, fdb).as_int();
443 offset = std::max(0, offset -
size + 1);
446 return variant(result.replace(offset,
size, replacement));
449 return variant(result.replace(offset, std::string::npos, replacement));
454 std::string result = args()[0]->evaluate(variables, fdb).as_string();
455 std::string needle = args()[1]->evaluate(variables, fdb).as_string();
456 std::string replacement = args().back()->evaluate(variables, fdb).as_string();
457 boost::replace_all(result, needle, replacement);
463 std::string str = args()[0]->evaluate(variables, fdb).as_string();
464 std::string prefix = args()[1]->evaluate(variables, fdb).as_string();
465 return variant(boost::starts_with(str, prefix));
470 std::string str = args()[0]->evaluate(variables, fdb).as_string();
471 std::string prefix = args()[1]->evaluate(variables, fdb).as_string();
472 return variant(boost::ends_with(str, prefix));
477 std::string result = args()[0]->evaluate(variables, fdb).as_string();
478 std::string
insert = args().back()->evaluate(variables, fdb).as_string();
480 int offset = args()[1]->evaluate(variables, fdb).as_int();
482 offset += result.size();
487 }
else if(
static_cast<std::size_t
>(offset) >= result.size()) {
496 return variant(args()[0]->evaluate(variables, fdb).as_string().length());
502 args()[0]->evaluate(variables, fdb).as_string(),
503 args()[1]->evaluate(variables, fdb).as_int()));
510 result += arg->evaluate(variables, fdb).string_cast();
518 std::string str = args()[0]->evaluate(variables, fdb).as_string();
519 std::transform(str.begin(), str.end(), str.begin(),
static_cast<int (*)(
int)
>(std::toupper));
525 std::string str = args()[0]->evaluate(variables, fdb).as_string();
526 std::transform(str.begin(), str.end(), str.begin(),
static_cast<int (*)(
int)
>(std::tolower));
532 const double angle = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
533 const double result = std::sin(angle * pi<double>() / 180.0);
534 return variant(result, variant::DECIMAL_VARIANT);
539 const double angle = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
540 const double result = std::cos(angle * pi<double>() / 180.0);
541 return variant(result, variant::DECIMAL_VARIANT);
546 const double angle = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
547 const double result = std::tan(angle * pi<double>() / 180.0);
548 if(std::isnan(result) || result <= std::numeric_limits<int>::min() || result >= std::numeric_limits<int>::max()) {
552 return variant(result, variant::DECIMAL_VARIANT);
557 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
558 const double result = std::asin(num) * 180.0 / pi<double>();
559 if(std::isnan(result)) {
563 return variant(result, variant::DECIMAL_VARIANT);
568 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
569 const double result = std::acos(num) * 180.0 / pi<double>();
570 if(std::isnan(result)) {
574 return variant(result, variant::DECIMAL_VARIANT);
579 if(args().
size() == 1) {
580 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
581 const double result = std::atan(num) * 180.0 / pi<double>();
582 return variant(result, variant::DECIMAL_VARIANT);
584 const double y = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
585 const double x = args()[1]->evaluate(variables, fdb).as_decimal() / 1000.0;
586 const double result = std::atan2(y, x) * 180.0 / pi<double>();
587 return variant(result, variant::DECIMAL_VARIANT);
593 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
594 const double result = std::sqrt(num);
595 if(std::isnan(result)) {
599 return variant(result, variant::DECIMAL_VARIANT);
604 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
605 const double result = num < 0 ? -std::pow(-num, 1.0 / 3.0) : std::pow(num, 1.0 / 3.0);
606 return variant(result, variant::DECIMAL_VARIANT);
611 const double base = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
612 const double root = args()[1]->evaluate(variables, fdb).as_decimal() / 1000.0;
613 const double result = base < 0 && std::fmod(root, 2) == 1 ? -std::pow(-base, 1.0 / root) : std::pow(base, 1.0 / root);
614 if(std::isnan(result)) {
618 return variant(result, variant::DECIMAL_VARIANT);
623 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
624 if(args().
size() == 1) {
625 const double result = std::log(num);
626 if(std::isnan(result)) {
630 return variant(result, variant::DECIMAL_VARIANT);
633 const double base = args()[1]->evaluate(variables, fdb).as_decimal() / 1000.0;
634 const double result = std::log(num) / std::log(base);
635 if(std::isnan(result)) {
639 return variant(result, variant::DECIMAL_VARIANT);
644 const double num = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
645 const double result = std::exp(num);
646 if(result == 0 || result >= std::numeric_limits<int>::max()) {
652 return variant(result, variant::DECIMAL_VARIANT);
657 return variant(pi<double>(), variant::DECIMAL_VARIANT);
662 const double x = args()[0]->evaluate(variables, fdb).as_decimal() / 1000.0;
663 const double y = args()[1]->evaluate(variables, fdb).as_decimal() / 1000.0;
664 return variant(std::hypot(x, y), variant::DECIMAL_VARIANT);
669 const variant value = args()[0]->evaluate(variables, fdb);
670 const variant list = args()[1]->evaluate(variables, fdb);
673 if(list[
i] == value) {
683 const variant items = args()[0]->evaluate(variables, fdb);
687 if(args().
size() == 2) {
698 const std::string
self = args()[1]->evaluate(variables, fdb).as_string();
701 self_callable.
add(
self, *it);
703 const variant val = args().back()->evaluate(
722 const int value = args()[0]->evaluate(variables, fdb).as_int() % 1000;
723 const double angle = 2.0 * pi<double>() * (
static_cast<double>(value) / 1000.0);
724 return variant(
static_cast<int>(std::sin(angle) * 1000.0));
729 const double lo = args()[0]->evaluate(variables,
add_debug_info(fdb, 0,
"lerp:lo")).as_decimal() / 1000.0;
730 const double hi = args()[1]->evaluate(variables,
add_debug_info(fdb, 1,
"lerp:hi")).as_decimal() / 1000.0;;
731 const double alpha = args()[2]->evaluate(variables,
add_debug_info(fdb, 2,
"lerp:alpha")).as_decimal() / 1000.0;;
732 return variant(
static_cast<int>((lo + alpha * (hi - lo)) * 1000.0), variant::DECIMAL_VARIANT);
737 const std::vector<variant> items = args()[0]->evaluate(variables, fdb).as_list();
738 if(items.empty())
return variant();
739 const double alpha = args()[1]->evaluate(variables, fdb).as_decimal() / 1000.0;
741 const double val_scaled = std::clamp(0.01 * alpha, 0.0, 1.0);
742 const int idx = int(std::nearbyint((items.size() - 1) * val_scaled));
748 const std::string name = args()[0]->evaluate(variables, fdb).as_string();
749 std::vector<color_t> colors;
750 if(name ==
"red_green_scale") {
752 }
else if(name ==
"red_green_scale_text") {
754 }
else if(name ==
"blue_white_scale") {
756 }
else if(name ==
"blue_white_scale_text") {
761 std::vector<variant> result;
762 result.reserve(colors.size());
763 for(
auto clr : colors) {
764 result.emplace_back(std::make_shared<color_callable>(clr));
793 bool operator()(
const variant& a,
const variant&
b)
const
797 return expr_->evaluate(*this).as_bool();
801 variant get_value(
const std::string& key)
const
805 }
else if(key ==
"b") {
825 variant list = args()[0]->evaluate(variables, fdb);
827 std::vector<variant> vars;
831 vars.push_back(list[
n]);
834 if(args().
size() == 1) {
835 std::sort(vars.begin(), vars.end());
837 std::sort(vars.begin(), vars.end(), variant_comparator(args()[1], variables));
845 const variant& arg = args()[0]->evaluate(variables, fdb);
848 std::string str = args()[0]->evaluate(variables, fdb).
as_string();
853 std::vector<variant> list = args()[0]->evaluate(variables, fdb).as_list();
864 std::string str = args()[0]->evaluate(variables, fdb).as_string();
865 std::string key = args()[1]->evaluate(variables, fdb).as_string();
867 return variant(str.find(key) != std::string::npos);
872 const std::string str = args()[0]->evaluate(variables, fdb).as_string();
873 const std::string key = args()[1]->evaluate(variables, fdb).as_string();
875 std::size_t pos = str.find(key);
876 return variant(
static_cast<int>(pos));
881 std::vector<variant> list_vars;
882 std::map<variant, variant> map_vars;
884 const variant items = args()[0]->evaluate(variables, fdb);
886 if(args().
size() == 2) {
892 map_vars[(*it).get_member(
"key")] = (*it).
get_member(
"value");
894 list_vars.push_back(*it);
900 const std::string
self = args()[1]->evaluate(variables, fdb).as_string();
903 self_callable.
add(
self, *it);
905 const variant val = args()[2]->evaluate(
910 map_vars[(*it).get_member(
"key")] = (*it).
get_member(
"value");
912 list_vars.push_back(*it);
927 const variant items = args()[0]->evaluate(variables, fdb);
929 if(args().
size() == 2) {
938 const std::string
self = args()[1]->evaluate(variables, fdb).as_string();
941 self_callable.
add(
self, *it);
943 const variant val = args().back()->evaluate(
957 std::vector<variant> list_vars;
958 std::map<variant, variant> map_vars;
959 const variant items = args()[0]->evaluate(variables, fdb);
961 if(args().
size() == 2) {
965 map_vars[(*it).get_member(
"key")] = val;
967 list_vars.push_back(val);
972 const std::string
self = args()[1]->evaluate(variables, fdb).as_string();
975 self_callable.
add(
self, *it);
977 const variant val = args().back()->evaluate(
981 map_vars[(*it).get_member(
"key")] = val;
983 list_vars.push_back(val);
997 const variant& items = args()[0]->evaluate(variables, fdb);
1000 for(; it != items.
end(); ++it) {
1008 std::vector<variant> result(items.
begin(), it);
1016 explicit indexer(std::size_t
i)
1021 variant operator()(
const variant& v)
const
1023 if(
i >= v.num_elements()) {
1036 bool operator()(
const variant& a,
const variant&
b)
const
1038 return a.num_elements() <
b.num_elements();
1042 std::vector<variant> get_input(
1043 const function_expression::args_list& args,
1044 const formula_callable& variables,
1045 formula_debugger* fdb)
1047 if(args.size() == 1) {
1048 const variant list = args[0]->evaluate(variables, fdb);
1049 return std::vector<variant>(list.begin(), list.end());
1051 std::vector<variant> input;
1052 input.reserve(args.size());
1055 input.push_back(
expr->evaluate(variables, fdb));
1065 const std::vector<variant> input = get_input(args(), variables, fdb);
1066 std::vector<variant>
output;
1070 std::size_t max_i = std::max_element(input.begin(), input.end(), comparator())->num_elements();
1073 for(std::size_t
i = 0;
i < max_i;
i++) {
1074 std::vector<variant> elem(input.size());
1076 output.emplace_back(elem);
1084 const variant items = args()[0]->evaluate(variables, fdb);
1085 variant initial = args().size() == 2 ?
variant() : args()[1]->evaluate(variables, fdb);
1093 if(res != initial) {
1098 for(; it != items.
end(); ++it) {
1099 self_callable.
add(
"a", res);
1100 self_callable.
add(
"b", *it);
1101 res = args().back()->evaluate(
1111 const variant items = args()[0]->evaluate(variables, fdb);
1113 if(items[0].is_list()) {
1114 std::vector<variant> tmp;
1116 if(args().
size() >= 2) {
1117 res = args()[1]->evaluate(variables, fdb);
1121 }
else if(items[0].
is_map()) {
1122 std::map<variant, variant> tmp;
1124 if(args().
size() >= 2) {
1125 res = args()[1]->evaluate(variables, fdb);
1130 if(args().
size() >= 2) {
1131 res = args()[1]->evaluate(variables, fdb);
1137 res = res + items[
n];
1145 const variant items = args()[0]->evaluate(variables, fdb);
1147 if(it == items.
end()) {
1151 if(args().
size() == 1) {
1155 const int n = items.
num_elements(), req = args()[1]->evaluate(variables, fdb).as_int();
1156 const int count = req < 0 ?
n - std::min(-req,
n) : std::min(req,
n);
1159 std::advance(end, count);
1161 std::vector<variant> res;
1162 std::copy(it, end, std::back_inserter(res));
1168 const variant items = args()[0]->evaluate(variables, fdb);
1170 if(it == items.
begin()) {
1174 if(args().
size() == 1) {
1178 const int n = items.
num_elements(), req = args()[1]->evaluate(variables, fdb).as_int();
1179 const int count = req < 0 ?
n - std::min(-req,
n) : std::min(req,
n);
1181 std::advance(it, -count);
1182 std::vector<variant> res;
1184 std::copy(it, items.
end(), std::back_inserter(res));
1190 const variant items = args()[0]->evaluate(variables, fdb);
1196 if(!args().empty()) {
1197 for(std::size_t
i = 0;
i < args().size(); ++
i) {
1198 args()[
i]->evaluate(variables, fdb);
1207 variant decimal = args()[0]->evaluate(variables, fdb);
1208 int d = decimal.as_decimal();
1210 if((
d >= 0) && (
d % 1000 != 0)) {
1221 variant decimal = args()[0]->evaluate(variables, fdb);
1222 int d = decimal.as_decimal();
1228 }
else if(
f <= -500) {
1239 variant decimal = args()[0]->evaluate(variables, fdb);
1240 int d = decimal.as_decimal();
1242 if((
d < 0) && (
d % 1000 != 0)) {
1253 variant decimal = args()[0]->evaluate(variables, fdb);
1254 int d = decimal.as_int();
1261 variant decimal = args()[0]->evaluate(variables, fdb);
1262 int d = decimal.as_decimal();
1265 return variant(
d, variant::DECIMAL_VARIANT);
1270 variant decimal = args()[0]->evaluate(variables, fdb);
1271 int d = decimal.as_decimal();
1282 variant decimal = args()[0]->evaluate(variables, fdb);
1283 int d = decimal.as_decimal();
1285 return variant(
d, variant::DECIMAL_VARIANT);
1291 args()[0]->evaluate(variables,
add_debug_info(fdb, 0,
"loc:x")).as_int(),
1298 return variant(std::make_shared<key_value_pair>(
1299 args()[0]->evaluate(variables,
add_debug_info(fdb, 0,
"pair:key")),
1300 args()[1]->evaluate(variables,
add_debug_info(fdb, 1,
"pair_value"))
1307 ->evaluate(variables,
add_debug_info(fdb, 0,
"distance_between:location_A"))
1312 ->evaluate(variables,
add_debug_info(fdb, 1,
"distance_between:location_B"))
1322 ->evaluate(variables,
add_debug_info(fdb, 0,
"adjacent_locs:location"))
1326 std::vector<variant> v;
1328 v.emplace_back(std::make_shared<location_callable>(adj));
1338 int range = args()[1]->evaluate(variables, fdb).as_int();
1345 return variant(std::make_shared<location_callable>(
loc));
1348 std::vector<map_location> res;
1352 std::vector<variant> v;
1353 v.reserve(res.size() + 1);
1354 v.emplace_back(std::make_shared<location_callable>(
loc));
1356 for(std::size_t
n = 0;
n != res.size(); ++
n) {
1357 v.emplace_back(std::make_shared<location_callable>(res[
n]));
1366 ->evaluate(variables,
add_debug_info(fdb, 0,
"are_adjacent:location_A"))
1371 ->evaluate(variables,
add_debug_info(fdb, 1,
"are_adjacent:location_B"))
1381 ->evaluate(variables,
add_debug_info(fdb, 0,
"relative_dir:location_A"))
1386 ->evaluate(variables,
add_debug_info(fdb, 1,
"relative_dir:location_B"))
1396 ->evaluate(variables,
add_debug_info(fdb, 0,
"direction_from:location"))
1400 const std::string dir_str =
1401 args()[1]->evaluate(variables,
add_debug_info(fdb, 1,
"direction_from:dir")).as_string();
1403 int n = args().size() == 3
1404 ? args()[2]->evaluate(variables,
add_debug_info(fdb, 2,
"direction_from:count")).as_int()
1413 ->evaluate(variables,
add_debug_info(fdb, 0,
"direction_from:center"))
1418 ->evaluate(variables,
add_debug_info(fdb, 1,
"direction_from:location"))
1422 int n = args().size() == 3
1423 ? args()[2]->evaluate(variables,
add_debug_info(fdb, 2,
"direction_from:count")).as_int()
1431 const variant& v = args()[0]->evaluate(variables, fdb);
1441 const variant main = args()[0]->evaluate(variables, fdb);
1444 return variant(std::make_shared<safe_call_callable>(
main, backup_formula));
1449 return variant(std::make_shared<set_var_callable>(
1450 args()[0]->evaluate(variables,
add_debug_info(fdb, 0,
"set_var:key")).as_string(),
1451 args()[1]->evaluate(variables,
add_debug_info(fdb, 1,
"set_var:value"))));
1456 variant key_value_pair::get_value(
const std::string& key)
const
1460 }
else if(key ==
"value") {
1469 add_input(inputs,
"key");
1470 add_input(inputs,
"value");
1473 void key_value_pair::serialize_to_string(std::string& str)
const
1476 str += key_.serialize_to_string();
1478 str +=
value_.serialize_to_string();
1482 formula_function_expression::formula_function_expression(
const std::string& name,
1486 const std::vector<std::string>& arg_names)
1488 , formula_(std::move(
formula))
1489 , precondition_(std::move(precondition))
1490 , arg_names_(arg_names)
1504 static std::string
indent;
1509 const auto begin_time = std::chrono::steady_clock::now();
1523 DBG_NG <<
"FAILED function precondition for function '" <<
formula_->str() <<
"' with arguments: ";
1526 DBG_NG <<
" arg " << (
n + 1) <<
": " <<
args()[
n]->evaluate(variables, fdb).to_debug_string();
1533 const auto taken = std::chrono::steady_clock::now() - begin_time;
1542 const std::vector<expression_ptr>& args)
const
1548 : parent(parent ? parent : get_builtins())
1558 const std::string& fn,
const std::vector<expression_ptr>& args)
const
1562 return i->second->generate_function_expression(args);
1577 std::set<std::string> res;
1579 res =
parent->get_function_names();
1593 if(functions_table.
empty()) {
1594 functions_table.
parent =
nullptr;
1596 using namespace builtins;
std::unique_ptr< PangoAttribute, void(*)(PangoAttribute *)> value_
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)
static game_display * get_singleton()
display_chat_manager & get_chat_manager()
void float_label(const map_location &loc, const std::string &text, const color_t &color)
Function to float a label above a tile.
action_function_symbol_table(const std::shared_ptr< function_symbol_table > &parent=nullptr)
const args_list & args() const
std::vector< expression_ptr > args_list
static std::shared_ptr< function_symbol_table > get_builtins()
expression_ptr create_function(const std::string &fn, const std::vector< expression_ptr > &args) const
function_symbol_table(const std::shared_ptr< function_symbol_table > &parent=nullptr)
void add_function(const std::string &name, formula_function_ptr &&fcn)
std::set< std::string > get_function_names() const
std::shared_ptr< function_symbol_table > parent
functions_map custom_formulas_
Iterator class for the variant.
int as_decimal() const
Returns variant's internal representation of decimal number: ie, 1.234 is represented as 1234.
variant_iterator begin() const
variant get_values() const
const_formula_callable_ptr as_callable() const
std::size_t num_elements() const
std::shared_ptr< T > convert_to() const
variant get_member(const std::string &name) const
const std::string & as_string() const
std::string string_cast() const
variant_iterator end() const
bool as_bool() const
Returns a boolean state of the variant value.
std::string type_string() const
Gets string name of the current value type.
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
bool is_null() const
Functions to test the type of the internal value.
const formula_callable * fallback_
static lg::log_domain log_engine("engine")
static lg::log_domain log_scripting_formula("scripting/formula")
#define DEFINE_WFL_FUNCTION(name, min_args, max_args)
Helper macro to declare an associated class for a WFL function.
#define DECLARE_WFL_FUNCTION(name)
Declares a function name in the local function table functions_table.
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
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.
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
static std::ostream & output()
Standard logging facilities (interface).
EXIT_STATUS start(bool clear_id, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
bool is_map(const std::string &filename)
Returns true if the file ends with the mapfile extension.
std::vector< color_t > red_green_scale_text
const std::vector< color_t > & tc_info(std::string_view name)
std::vector< color_t > blue_white_scale
std::vector< color_t > red_green_scale
std::vector< color_t > blue_white_scale_text
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::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
formula_debugger * add_debug_info(formula_debugger *fdb, int arg_number, const std::string &f_name)
std::vector< formula_input > formula_input_vector
std::shared_ptr< const formula > const_formula_ptr
std::shared_ptr< formula_expression > 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 ...
std::shared_ptr< function_expression > function_expression_ptr
std::shared_ptr< formula_function > formula_function_ptr
void get_tiles_in_radius(const map_location ¢er, const int radius, std::vector< map_location > &result)
Function that will add to result all locations within radius tiles of center (excluding center itself...
The basic class for representing 8-bit RGB or RGBA colour values.
Encapsulates the map of the game.
static std::string write_direction(direction dir)
map_location get_direction(direction dir, unsigned int n=1u) const
map_location rotate_right_around_center(const map_location ¢er, int k) const
direction get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
static direction parse_direction(const std::string &str)
static map_location::direction n
static map_location::direction s