Changed [set_variable] to work with floats properly. (bug #12546)

Specification at http://www.wesnoth.org/forum/viewtopic.php?p=336743#p336743
This commit is contained in:
Alexander van Gessel 2009-02-03 01:34:57 +01:00
parent abde2f0efe
commit e03f55ca22
2 changed files with 66 additions and 26 deletions

View File

@ -729,12 +729,17 @@ For game purposes, the races group into factions; for example, orcs often cooper
text=0
[/text_input]
[/message]
# To test the math, define MATH_TEST.
# This comments out the [option] blocks which currently cause a VALIDATE failure.
# Once that is fixed, this preprocessor usage can be removed.
#ifndef MATH_TEST
[message]
speaker=narrator
message="What should we do with the number $number|?"
[option]
message="Round it"
[command]
#endif
[message]
speaker=narrator
image=wesnoth-icon.png
@ -756,15 +761,17 @@ For game purposes, the races group into factions; for example, orcs often cooper
image=wesnoth-icon.png
message="Rounding $number| to $round| results in $rounded|."
[/message]
#ifndef MATH_TEST
[/command]
[/option]
[option]
message="Add something"
[command]
#endif
[message]
speaker=narrator
[text_input]
label="Amount"
label="Amount to add"
variable=amount
[/text_input]
[/message]
@ -777,15 +784,17 @@ For game purposes, the races group into factions; for example, orcs often cooper
speaker=narrator
message="Adding $amount| to $number| results in $total|."
[/message]
#ifndef MATH_TEST
[/command]
[/option]
[option]
message="Multiply"
[command]
#endif
[message]
speaker=narrator
[text_input]
label="Amount"
label="Amount to multiply"
variable=amount
[/text_input]
[/message]
@ -798,11 +807,13 @@ For game purposes, the races group into factions; for example, orcs often cooper
speaker=narrator
message="$number| * $amount| = $total|."
[/message]
#ifndef MATH_TEST
[/command]
[/option]
[option]
message="Divide by something"
[command]
#endif
[message]
speaker=narrator
[text_input]
@ -817,13 +828,15 @@ For game purposes, the races group into factions; for example, orcs often cooper
[/set_variable]
[message]
speaker=narrator
message="Dividing $number| by $devisor| results in $total|."
message="Dividing $number| by $divisor| results in $total|."
[/message]
#ifndef MATH_TEST
[/command]
[/option]
[option]
message="Modulo"
[command]
#endif
[message]
speaker=narrator
[text_input]
@ -840,11 +853,13 @@ For game purposes, the races group into factions; for example, orcs often cooper
speaker=narrator
message="$number| % $modulo| = $total|."
[/message]
#ifndef MATH_TEST
[/command]
[/option]
[option]
message="ints&floats"
[command]
#endif
[set_variable]
name=int
ipart=$number
@ -854,9 +869,11 @@ For game purposes, the races group into factions; for example, orcs often cooper
speaker=narrator
message="$number| = $int| + $float|"
[/message]
#ifndef MATH_TEST
[/command]
[/option]
[/message]
#endif
[/event]
[/event]

View File

@ -1117,6 +1117,16 @@ namespace {
}
}
// Helper function(s) for [set_variable]
namespace {
bool isint(const std::string &var) {
return var.find('.') == std::string::npos;
}
bool isint(const t_string &var) {
return isint(var.str());
}
} // End anonymous namespace
WML_HANDLER_FUNCTION(set_variable,/*handler*/,/*event_info*/,cfg)
{
assert(state_of_game != NULL);
@ -1146,46 +1156,45 @@ namespace {
const std::string add = cfg["add"];
if(add.empty() == false) {
int value = int(atof(var.c_str()));
value += atoi(add.c_str());
char buf[50];
snprintf(buf,sizeof(buf),"%d",value);
var = buf;
if(isint(var.str()) && isint(add)) {
var = str_cast( atoi(var.c_str()) + atoi(add.c_str()) );
} else {
var = str_cast( atof(var.c_str()) + atof(add.c_str()) );
}
}
const std::string multiply = cfg["multiply"];
if(multiply.empty() == false) {
int value = int(atof(var.c_str()));
value = int(double(value) * atof(multiply.c_str()));
char buf[50];
snprintf(buf,sizeof(buf),"%d",value);
var = buf;
if(isint(var) && isint(multiply)) {
var = str_cast( atoi(var.c_str()) * atoi(multiply.c_str()) );
} else {
var = str_cast( atof(var.c_str()) * atof(multiply.c_str()) );
}
}
const std::string divide = cfg["divide"];
if(divide.empty() == false) {
int value = int(atof(var.c_str()));
double divider = atof(divide.c_str());
if (divider == 0) {
if (atof(divide.c_str()) == 0) {
ERR_NG << "division by zero on variable " << name << "\n";
return;
}
if(isint(var) && isint(divide)) {
var = str_cast( atoi(var.c_str()) / atoi(divide.c_str()) );
} else {
value = int(double(value) / divider);
char buf[50];
snprintf(buf,sizeof(buf),"%d",value);
var = buf;
var = str_cast( atof(var.c_str()) / atof(divide.c_str()) );
}
}
const std::string modulo = cfg["modulo"];
if(modulo.empty() == false) {
int value = atoi(var.c_str());
int divider = atoi(modulo.c_str());
if (divider == 0) {
if(atof(modulo.c_str()) == 0) {
ERR_NG << "division by zero on variable " << name << "\n";
return;
}
if(isint(var) && isint(modulo)) {
var = str_cast( atoi(var.c_str()) % atoi(modulo.c_str()) );
} else {
value %= divider;
double value = fmod( atof(var.c_str()), atof(modulo.c_str()) );
var = str_cast(value);
}
}
@ -1194,10 +1203,8 @@ namespace {
if(round_val.empty() == false) {
double value = lexical_cast<double>(var.c_str());
if (round_val == "ceil") {
//TODO precision stuff
value = std::ceil(value);
} else if (round_val == "floor") {
//TODO same
value = std::floor(value);
} else {
// We assume the value is an integer.
@ -1211,6 +1218,22 @@ namespace {
var = str_cast(value);
}
const t_string ipart = cfg["ipart"];
if(ipart.empty() == false) {
const std::string orig = state_of_game->get_variable(ipart);
double result;
modf( atof(ipart.c_str()), &result );
var = str_cast(result);
}
const t_string fpart = cfg["fpart"];
if(fpart.empty() == false) {
const std::string orig = state_of_game->get_variable(fpart);
double ignore;
double result = modf( atof(fpart.c_str()), &ignore );
var = str_cast(result);
}
const t_string string_length_target = cfg["string_length"];
if(string_length_target.empty() == false) {
const int value = string_length_target.str().length();