1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-31 15:52:55 +08:00

Improve convert considerations in osu!taiko (#31546)

* return a higher finger count

* implement isConvert

* diffcalc cleanup

* harshen monostaminafactor accuracy curve

* readd comment

* adjusts tests
This commit is contained in:
Jay Lawton 2025-01-20 07:55:34 +10:00 committed by GitHub
parent e320f17faf
commit e04727afb1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 21 additions and 29 deletions

View File

@ -14,13 +14,13 @@ namespace osu.Game.Rulesets.Taiko.Tests
{
protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko";
[TestCase(3.3167800835687551d, 200, "diffcalc-test")]
[TestCase(3.3167800835687551d, 200, "diffcalc-test-strong")]
[TestCase(3.3056113401782845d, 200, "diffcalc-test")]
[TestCase(3.3056113401782845d, 200, "diffcalc-test-strong")]
public void Test(double expectedStarRating, int expectedMaxCombo, string name)
=> base.Test(expectedStarRating, expectedMaxCombo, name);
[TestCase(4.4631326105105122d, 200, "diffcalc-test")]
[TestCase(4.4631326105105122d, 200, "diffcalc-test-strong")]
[TestCase(4.4473902679506896d, 200, "diffcalc-test")]
[TestCase(4.4473902679506896d, 200, "diffcalc-test-strong")]
public void TestClockRateAdjusted(double expectedStarRating, int expectedMaxCombo, string name)
=> Test(expectedStarRating, expectedMaxCombo, name, new TaikoModDoubleTime());

View File

@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Evaluators
return 2;
}
return 4;
return 8;
}
/// <summary>

View File

@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
private double strainDecayBase => 0.4;
private readonly bool singleColourStamina;
private readonly bool isConvert;
private double currentStrain;
@ -28,10 +29,12 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
/// </summary>
/// <param name="mods">Mods for use in skill calculations.</param>
/// <param name="singleColourStamina">Reads when Stamina is from a single coloured pattern.</param>
public Stamina(Mod[] mods, bool singleColourStamina)
/// <param name="isConvert">Determines if the currently evaluated beatmap is converted.</param>
public Stamina(Mod[] mods, bool singleColourStamina, bool isConvert)
: base(mods)
{
this.singleColourStamina = singleColourStamina;
this.isConvert = isConvert;
}
private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000);
@ -45,7 +48,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
var currentObject = current as TaikoDifficultyHitObject;
int index = currentObject?.Colour.MonoStreak?.HitObjects.IndexOf(currentObject) ?? 0;
double monolengthBonus = 1 + Math.Min(Math.Max((index - 5) / 50.0, 0), 0.30);
double monolengthBonus = isConvert ? 1 : 1 + Math.Min(Math.Max((index - 5) / 50.0, 0), 0.30);
if (singleColourStamina)
return DifficultyCalculationUtils.Logistic(-(index - 10) / 2.0, currentStrain);

View File

@ -32,6 +32,8 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
private double strainLengthBonus;
private double patternMultiplier;
private bool isConvert;
public override int Version => 20241007;
public TaikoDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
@ -44,13 +46,15 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
HitWindows hitWindows = new HitWindows();
hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty);
isConvert = beatmap.BeatmapInfo.Ruleset.OnlineID == 0;
return new Skill[]
{
new Rhythm(mods, hitWindows.WindowFor(HitResult.Great) / clockRate),
new Reading(mods),
new Colour(mods),
new Stamina(mods, false),
new Stamina(mods, true)
new Stamina(mods, false, isConvert),
new Stamina(mods, true, isConvert)
};
}
@ -130,19 +134,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
+ Math.Min(Math.Max((staminaDifficultStrains - 1350) / 5000, 0), 0.15)
+ Math.Min(Math.Max((staminaRating - 7.0) / 1.0, 0), 0.05);
double combinedRating = combinedDifficultyValue(rhythm, reading, colour, stamina, isRelax);
double combinedRating = combinedDifficultyValue(rhythm, reading, colour, stamina, isRelax, isConvert);
double starRating = rescale(combinedRating * 1.4);
// Converts are penalised outside the scope of difficulty calculation, as our assumptions surrounding standard play-styles becomes out-of-scope.
if (beatmap.BeatmapInfo.Ruleset.OnlineID == 0)
{
starRating *= 0.7;
// For maps with relax, multiple inputs are more likely to be abused.
if (isRelax)
starRating *= 0.60;
}
HitWindows hitWindows = new TaikoHitWindows();
hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty);
@ -173,7 +167,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
/// For each section, the peak strains of all separate skills are combined into a single peak strain for the section.
/// The resulting partial rating of the beatmap is a weighted sum of the combined peaks (higher peaks are weighted more).
/// </remarks>
private double combinedDifficultyValue(Rhythm rhythm, Reading reading, Colour colour, Stamina stamina, bool isRelax)
private double combinedDifficultyValue(Rhythm rhythm, Reading reading, Colour colour, Stamina stamina, bool isRelax, bool isConvert)
{
List<double> peaks = new List<double>();
@ -186,14 +180,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
{
double rhythmPeak = rhythmPeaks[i] * rhythm_skill_multiplier * patternMultiplier;
double readingPeak = readingPeaks[i] * reading_skill_multiplier;
double colourPeak = colourPeaks[i] * colour_skill_multiplier;
double colourPeak = isRelax ? 0 : colourPeaks[i] * colour_skill_multiplier; // There is no colour difficulty in relax.
double staminaPeak = staminaPeaks[i] * stamina_skill_multiplier * strainLengthBonus;
if (isRelax)
{
colourPeak = 0; // There is no colour difficulty in relax.
staminaPeak /= 1.5; // Stamina difficulty is decreased with an increased available finger count.
}
staminaPeak /= isConvert || isRelax ? 1.5 : 1.0; // Available finger count is increased by 150%, thus we adjust accordingly.
double peak = DifficultyCalculationUtils.Norm(2, DifficultyCalculationUtils.Norm(1.5, colourPeak, staminaPeak), rhythmPeak, readingPeak);

View File

@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
// Scale accuracy more harshly on nearly-completely mono (single coloured) speed maps.
double accScalingExponent = 2 + attributes.MonoStaminaFactor;
double accScalingShift = 500 - 100 * attributes.MonoStaminaFactor;
double accScalingShift = 500 - 100 * (attributes.MonoStaminaFactor * 3);
return difficultyValue * Math.Pow(DifficultyCalculationUtils.Erf(accScalingShift / (Math.Sqrt(2) * estimatedUnstableRate.Value)), accScalingExponent);
}