From f771643880b08d069b318b426a170f626f2de8df Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Tue, 5 Sep 2023 22:52:49 -0700 Subject: [PATCH] fix rounding in division expressions --- src/Episode3/CardSpecial.cc | 18 ++++++++++++++++-- src/Episode3/CardSpecial.hh | 2 +- src/Episode3/Server.cc | 2 +- system/config.example.json | 3 ++- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Episode3/CardSpecial.cc b/src/Episode3/CardSpecial.cc index d2d9a172..89441e26 100644 --- a/src/Episode3/CardSpecial.cc +++ b/src/Episode3/CardSpecial.cc @@ -1537,6 +1537,8 @@ int32_t CardSpecial::evaluate_effect_expr( const AttackEnvStats& ast, const char* expr, DiceRoll& dice_roll) const { + this->debug_log("evaluate_effect_expr(ast, expr=\"%s\", dice_roll=(client_id=%02hhX, a2=%02hhX, value=%02hhX, value_used_in_expr=%s, a5=%04hX))", expr, dice_roll.client_id, dice_roll.unknown_a2, dice_roll.value, dice_roll.value_used_in_expr ? "true" : "false", dice_roll.unknown_a5); + // Note: This implementation is not based on the original code because the // original code was hard to follow - it used a look-behind approach with lots // of local variables instead of the look-ahead approach that this @@ -1566,6 +1568,7 @@ int32_t CardSpecial::evaluate_effect_expr( // Operators are evaluated left-to-right - there are no operator precedence // rules int32_t value = 0; + this->debug_log("evaluate_effect_expr: value=%" PRId32 " (start)", value); for (size_t token_index = 0; token_index < tokens.size(); token_index++) { auto token_type = tokens[token_index].first; int32_t token_value = tokens[token_index].second; @@ -1574,6 +1577,7 @@ int32_t CardSpecial::evaluate_effect_expr( } if (token_type == ExpressionTokenType::NUMBER) { value = token_value; + this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=NUMBER, token_value=%" PRId32 ")", value, token_value); } else { if (token_index >= tokens.size() - 1) { throw runtime_error("no token on right side of binary operator"); @@ -1586,19 +1590,24 @@ int32_t CardSpecial::evaluate_effect_expr( } switch (token_type) { case ExpressionTokenType::ROUND_DIVIDE: - value = lround(value / right_value); + value = lround(static_cast(value) / right_value); + this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=ROUND_DIVIDE, right_token_value=%" PRId32 ")", value, right_value); break; case ExpressionTokenType::SUBTRACT: value -= right_value; + this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=SUBTRACT, right_token_value=%" PRId32 ")", value, right_value); break; case ExpressionTokenType::ADD: value += right_value; + this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=ADD, right_token_value=%" PRId32 ")", value, right_value); break; case ExpressionTokenType::MULTIPLY: value *= right_value; + this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=MULTIPLY, right_token_value=%" PRId32 ")", value, right_value); break; case ExpressionTokenType::FLOOR_DIVIDE: value = floor(value / right_value); + this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=FLOOR_DIVIDE, right_token_value=%" PRId32 ")", value, right_value); break; default: throw logic_error("invalid binary operator"); @@ -1606,6 +1615,7 @@ int32_t CardSpecial::evaluate_effect_expr( } } + this->debug_log("evaluate_effect_expr: value=%" PRId32 " (result)", value); return value; } @@ -1615,8 +1625,12 @@ bool CardSpecial::execute_effect( int16_t expr_value, int16_t unknown_p5, ConditionType cond_type, - uint unknown_p7, + uint32_t unknown_p7, uint16_t attacker_card_ref) { + { + string cond_str = cond.str(); + this->debug_log("execute_effect(cond=%s, card=%04hX, expr_value=%hd, unknown_p5=%hd, cond_type=%s, unknown_p7=%" PRIu32 ", attacker_card_ref=%04hX)", cond_str.c_str(), ref_for_card(card), expr_value, unknown_p5, name_for_condition_type(cond_type), unknown_p7, attacker_card_ref); + } int16_t clamped_expr_value = clamp(expr_value, -99, 99); int16_t clamped_unknown_p5 = clamp(unknown_p5, -99, 99); diff --git a/src/Episode3/CardSpecial.hh b/src/Episode3/CardSpecial.hh index 4742d0f7..5ce416e3 100644 --- a/src/Episode3/CardSpecial.hh +++ b/src/Episode3/CardSpecial.hh @@ -196,7 +196,7 @@ public: int16_t expr_value, int16_t unknown_p5, ConditionType cond_type, - uint unknown_p7, + uint32_t unknown_p7, uint16_t attacker_card_ref); const Condition* find_condition_with_parameters( std::shared_ptr card, diff --git a/src/Episode3/Server.cc b/src/Episode3/Server.cc index 64b56f87..9c89d981 100644 --- a/src/Episode3/Server.cc +++ b/src/Episode3/Server.cc @@ -35,7 +35,7 @@ ServerBase::ServerBase( card_index(card_index), map_index(map_index), behavior_flags(behavior_flags), - log(lobby->log.prefix + "[Ep3::Server] "), + log(lobby->log.prefix + "[Ep3::Server] ", lobby->log.min_level), random_crypt(random_crypt), is_tournament(!!map_if_tournament), last_chosen_map(map_if_tournament) {} diff --git a/system/config.example.json b/system/config.example.json index 3d433060..d3b2f414 100644 --- a/system/config.example.json +++ b/system/config.example.json @@ -196,7 +196,8 @@ // License manager messages describe the creation of new license files. "LicenseManager": "INFO", // Lobby messages describe creation and deletion of lobbies and games, as - // well as item tracking events within games. + // well as item tracking events within games. On Episode 3, debug messages + // during battles go to this stream as well; use "DEBUG" here to see them. "Lobbies": "INFO", // Patch file index messages describe finding and preloading the patch files // available for download to BB and PC clients.