Skip to content

Commit

Permalink
New Difficulty Factor + Length Bonus Rework
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDark98 committed Jan 15, 2025
2 parents 69a058e + bc93687 commit b9786a4
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 52 deletions.
12 changes: 6 additions & 6 deletions osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@ public class OsuDifficultyCalculatorTest : DifficultyCalculatorTest
{
protected override string ResourceAssembly => "osu.Game.Rulesets.Osu.Tests";

[TestCase(6.6860329680488437d, 239, "diffcalc-test")]
[TestCase(1.4485740324170036d, 54, "zero-length-sliders")]
[TestCase(6.7331304290522747d, 239, "diffcalc-test")]
[TestCase(1.4602604078137214d, 54, "zero-length-sliders")]
[TestCase(0.43052813047866129d, 4, "very-fast-slider")]
[TestCase(0.14143808967817237d, 2, "nan-slider")]
public void Test(double expectedStarRating, int expectedMaxCombo, string name)
=> base.Test(expectedStarRating, expectedMaxCombo, name);

[TestCase(9.6300773538770041d, 239, "diffcalc-test")]
[TestCase(1.7550155729445993d, 54, "zero-length-sliders")]
[TestCase(9.6779397290273756d, 239, "diffcalc-test")]
[TestCase(1.7691451263718989d, 54, "zero-length-sliders")]
[TestCase(0.55785578988249407d, 4, "very-fast-slider")]
public void TestClockRateAdjusted(double expectedStarRating, int expectedMaxCombo, string name)
=> Test(expectedStarRating, expectedMaxCombo, name, new OsuModDoubleTime());

[TestCase(6.6860329680488437d, 239, "diffcalc-test")]
[TestCase(1.4485740324170036d, 54, "zero-length-sliders")]
[TestCase(6.7331304290522747d, 239, "diffcalc-test")]
[TestCase(1.4602604078137214d, 54, "zero-length-sliders")]
[TestCase(0.43052813047866129d, 4, "very-fast-slider")]
public void TestClassicMod(double expectedStarRating, int expectedMaxCombo, string name)
=> Test(expectedStarRating, expectedMaxCombo, name, new OsuModClassic());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public static double EvaluateDifficultyOf(DifficultyHitObject current, bool with

// Penalize angle repetition.
wideAngleBonus *= 1 - Math.Min(wideAngleBonus, Math.Pow(calcWideAngleBonus(lastAngle), 3));
acuteAngleBonus *= 0.1 + 0.9 * (1 - Math.Min(acuteAngleBonus, Math.Pow(calcAcuteAngleBonus(lastAngle), 3)));
acuteAngleBonus *= 0.08 + 0.92 * (1 - Math.Min(acuteAngleBonus, Math.Pow(calcAcuteAngleBonus(lastAngle), 3)));

// Apply full wide angle bonus for distance more than one diameter
wideAngleBonus *= angleBonus * DifficultyCalculationUtils.Smootherstep(osuCurrObj.LazyJumpDistance, 0, diameter);
Expand Down
5 changes: 3 additions & 2 deletions osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Difficulty.Utils;
using osu.Game.Rulesets.Osu.Difficulty.Skills;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Scoring;
Expand Down Expand Up @@ -412,8 +413,8 @@ private double calculateSpeedHighDeviationNerf(OsuDifficultyAttributes attribute
const double scale = 50;
double adjustedSpeedValue = scale * (Math.Log((speedValue - excessSpeedDifficultyCutoff) / scale + 1) + excessSpeedDifficultyCutoff / scale);

// 200 UR and less are considered tapped correctly to ensure that normal scores will be punished as little as possible
double lerp = 1 - Math.Clamp((speedDeviation.Value - 20) / (24 - 20), 0, 1);
// 220 UR and less are considered tapped correctly to ensure that normal scores will be punished as little as possible
double lerp = 1 - DifficultyCalculationUtils.ReverseLerp(speedDeviation.Value, 22.0, 27.0);
adjustedSpeedValue = double.Lerp(adjustedSpeedValue, speedValue, lerp);

return adjustedSpeedValue / speedValue;
Expand Down
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public Aim(Mod[] mods, bool withSliders)

private double currentStrain;

private double skillMultiplier => 25.18;
private double skillMultiplier => 25.6;
private double strainDecayBase => 0.15;

private readonly List<double> sliderStrains = new List<double>();
Expand Down
4 changes: 4 additions & 0 deletions osu.Game.Rulesets.Taiko/Difficulty/Skills/Reading.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Difficulty.Utils;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Taiko.Difficulty.Evaluators;
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
Expand Down Expand Up @@ -34,6 +35,9 @@ protected override double StrainValueOf(DifficultyHitObject current)
}

var taikoObject = (TaikoDifficultyHitObject)current;
int index = taikoObject.Colour.MonoStreak?.HitObjects.IndexOf(taikoObject) ?? 0;

currentStrain *= DifficultyCalculationUtils.Logistic(index, 4, -1 / 25.0, 0.5) + 0.5;

currentStrain *= StrainDecayBase;
currentStrain += ReadingEvaluator.EvaluateDifficultyOf(taikoObject) * SkillMultiplier;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class TaikoDifficultyCalculator : DifficultyCalculator
private const double stamina_skill_multiplier = 0.375 * difficulty_multiplier;

//The bonus multiplier is a basic multiplier that indicate how strong the impact of Difficulty Factor is.
private const double bonus_multiplier = 0.3;
private const double bonus_multiplier = 0.4;


// The difficulty factor for all the skills interpolated.
Expand Down Expand Up @@ -114,7 +114,7 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat
bool isFlashlight = mods.Any(h => h is TaikoModFlashlight);
bool isHidden = mods.Any(h => h is TaikoModHidden);

bool isConvert = beatmap.BeatmapInfo.OnlineInfo!.Ruleset.OnlineID != 1;
bool isConvert = beatmap.BeatmapInfo.OnlineID != 1;

Rhythm rhythm = (Rhythm)skills.First(x => x is Rhythm);
Reading reading = (Reading)skills.First(x => x is Reading);
Expand Down
48 changes: 8 additions & 40 deletions osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,53 +113,21 @@ private double computeAccuracyValue(ScoreInfo score, TaikoDifficultyAttributes a
/// </summary>
private double? computeDeviationUpperBound(TaikoDifficultyAttributes attributes)
{
if (totalSuccessfulHits == 0 || attributes.GreatHitWindow <= 0)
if (countGreat == 0 || attributes.GreatHitWindow <= 0)
return null;

double h300 = attributes.GreatHitWindow;
double h100 = attributes.OkHitWindow;

const double z = 2.32634787404; // 99% critical value for the normal distribution (one-tailed).

double? deviationGreatWindow = calcDeviationGreatWindow();
double? deviationGoodWindow = calcDeviationGoodWindow();

return deviationGreatWindow is null ? deviationGoodWindow : Math.Min(deviationGreatWindow.Value, deviationGoodWindow!.Value);

// The upper bound on deviation, calculated with the ratio of 300s to objects, and the great hit window.
double? calcDeviationGreatWindow()
{
if (countGreat == 0) return null;

double n = totalHits;

// Proportion of greats hit.
double p = countGreat / n;

// We can be 99% confident that p is at least this value.
double pLowerBound = (n * p + z * z / 2) / (n + z * z) - z / (n + z * z) * Math.Sqrt(n * p * (1 - p) + z * z / 4);

// We can be 99% confident that the deviation is not higher than:
return h300 / (Math.Sqrt(2) * SpecialFunctions.ErfInv(pLowerBound));
}

// The upper bound on deviation, calculated with the ratio of 300s + 100s to objects, and the good hit window.
// This will return a lower value than the first method when the number of 100s is high, but the miss count is low.
double? calcDeviationGoodWindow()
{
if (totalSuccessfulHits == 0) return null;

double n = totalHits;
double n = totalHits;

// Proportion of greats + goods hit.
double p = Math.Max(0, totalSuccessfulHits - 0.0005 * countOk) / n;
// Proportion of greats hit.
double p = countGreat / n;

// We can be 99% confident that p is at least this value.
double pLowerBound = (n * p + z * z / 2) / (n + z * z) - z / (n + z * z) * Math.Sqrt(n * p * (1 - p) + z * z / 4);
// We can be 99% confident that p is at least this value.
double pLowerBound = (n * p + z * z / 2) / (n + z * z) - z / (n + z * z) * Math.Sqrt(n * p * (1 - p) + z * z / 4);

// We can be 99% confident that the deviation is not higher than:
return h100 / (Math.Sqrt(2) * SpecialFunctions.ErfInv(pLowerBound));
}
// We can be 99% confident that the deviation is not higher than:
return attributes.GreatHitWindow / (Math.Sqrt(2) * SpecialFunctions.ErfInv(pLowerBound));
}

private int totalHits => countGreat + countOk + countMeh + countMiss;
Expand Down

0 comments on commit b9786a4

Please sign in to comment.