From 9461097b0070c15f275c69ea67be7df638e80208 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 22 May 2020 20:50:21 +0900 Subject: [PATCH] Update with latest changes --- .../Difficulty/Skills/Colour.cs | 198 ++++++++---------- .../Difficulty/Skills/SpeedInvariantRhythm.cs | 8 +- .../Difficulty/TaikoDifficultyAttributes.cs | 4 + .../Difficulty/TaikoDifficultyCalculator.cs | 28 +-- 4 files changed, 114 insertions(+), 124 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs index da255dcdd7..bd94c8aa65 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using System.IO; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing; @@ -12,130 +14,108 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills public class Colour : Skill { protected override double SkillMultiplier => 1; - protected override double StrainDecayBase => 0.3; + protected override double StrainDecayBase => 0.4; - private ColourSwitch lastColourSwitch = ColourSwitch.None; - private int sameColourCount = 1; + private bool prevIsKat = false; - private readonly int[] previousDonLengths = { 0, 0 }; - private readonly int[] previousKatLengths = { 0, 0 }; + private int currentMonoLength = 1; + private List monoHistory = new List(); + private readonly int mono_history_max_length = 5; + private int monoHistoryLength = 0; - private int sameTypeCount = 1; + private double sameParityPenalty() + { + return 0.0; + } - // TODO: make this smarter (dont initialise with "Don") - private bool previousIsKat; + private double repititionPenalty(int notesSince) + { + double d = notesSince; + return Math.Atan(d / 30) / (Math.PI / 2); + } + + private double patternLengthPenalty(int patternLength) + { + double shortPatternPenalty = Math.Min(0.25 * patternLength, 1.0); + double longPatternPenalty = Math.Max(Math.Min(2.5 - 0.15 * patternLength, 1.0), 0.0); + return Math.Min(shortPatternPenalty, longPatternPenalty); + } protected override double StrainValueOf(DifficultyHitObject current) { - return StrainValueOfNew(current); - } + double objectDifficulty = 0.0; - protected double StrainValueOfNew(DifficultyHitObject current) - { - double returnVal = 0.0; - double returnMultiplier = 1.0; - - if (previousIsKat != ((TaikoDifficultyHitObject)current).IsKat) - { - returnVal = 1.5 - (1.75 / (sameTypeCount + 0.65)); - - if (previousIsKat) - { - if (sameTypeCount % 2 == previousDonLengths[0] % 2) - { - returnMultiplier *= 0.8; - } - - if (previousKatLengths[0] == sameTypeCount) - { - returnMultiplier *= 0.525; - } - - if (previousKatLengths[1] == sameTypeCount) - { - returnMultiplier *= 0.75; - } - - previousKatLengths[1] = previousKatLengths[0]; - previousKatLengths[0] = sameTypeCount; - } - else - { - if (sameTypeCount % 2 == previousKatLengths[0] % 2) - { - returnMultiplier *= 0.8; - } - - if (previousDonLengths[0] == sameTypeCount) - { - returnMultiplier *= 0.525; - } - - if (previousDonLengths[1] == sameTypeCount) - { - returnMultiplier *= 0.75; - } - - previousDonLengths[1] = previousDonLengths[0]; - previousDonLengths[0] = sameTypeCount; - } - - sameTypeCount = 1; - previousIsKat = ((TaikoDifficultyHitObject)current).IsKat; - } - - else - { - sameTypeCount += 1; - } - - return Math.Min(1.25, returnVal) * returnMultiplier; - } - - protected double StrainValueOfOld(DifficultyHitObject current) - { - double addition = 0; - - // We get an extra addition if we are not a slider or spinner if (current.LastObject is Hit && current.BaseObject is Hit && current.DeltaTime < 1000) { - if (hasColourChange(current)) - addition = 0.75; + + TaikoDifficultyHitObject currentHO = (TaikoDifficultyHitObject)current; + + if (currentHO.IsKat == prevIsKat) + { + currentMonoLength += 1; + } + + else + { + + objectDifficulty = 1.0; + + if (monoHistoryLength > 0 && (monoHistory[monoHistoryLength - 1] + currentMonoLength) % 2 == 0) + { + objectDifficulty *= sameParityPenalty(); + } + + monoHistory.Add(currentMonoLength); + monoHistoryLength += 1; + + if (monoHistoryLength > mono_history_max_length) + { + monoHistory.RemoveAt(0); + monoHistoryLength -= 1; + } + + for (int l = 2; l <= mono_history_max_length / 2; l++) + { + for (int start = monoHistoryLength - l - 1; start >= 0; start--) + { + bool samePattern = true; + + for (int i = 0; i < l; i++) + { + if (monoHistory[start + i] != monoHistory[monoHistoryLength - l + i]) + { + samePattern = false; + } + } + + if (samePattern) // Repitition found! + { + int notesSince = 0; + for (int i = start; i < monoHistoryLength; i++) notesSince += monoHistory[i]; + objectDifficulty *= repititionPenalty(notesSince); + break; + } + } + } + + currentMonoLength = 1; + prevIsKat = currentHO.IsKat; + + } + } - else + + /* + string path = @"out.txt"; + using (StreamWriter sw = File.AppendText(path)) { - lastColourSwitch = ColourSwitch.None; - sameColourCount = 1; + if (((TaikoDifficultyHitObject)current).IsKat) sw.WriteLine("k " + Math.Min(1.25, returnVal) * returnMultiplier); + else sw.WriteLine("d " + Math.Min(1.25, returnVal) * returnMultiplier); } + */ - return addition; + return objectDifficulty; } - private bool hasColourChange(DifficultyHitObject current) - { - var taikoCurrent = (TaikoDifficultyHitObject)current; - - if (!taikoCurrent.HasTypeChange) - { - sameColourCount++; - return false; - } - - var oldColourSwitch = lastColourSwitch; - var newColourSwitch = sameColourCount % 2 == 0 ? ColourSwitch.Even : ColourSwitch.Odd; - - lastColourSwitch = newColourSwitch; - sameColourCount = 1; - - // We only want a bonus if the parity of the color switch changes - return oldColourSwitch != ColourSwitch.None && oldColourSwitch != newColourSwitch; - } - - private enum ColourSwitch - { - None, - Even, - Odd - } } } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/SpeedInvariantRhythm.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/SpeedInvariantRhythm.cs index 2d99bac7a9..28198612b2 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/SpeedInvariantRhythm.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/SpeedInvariantRhythm.cs @@ -49,9 +49,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills // Penalty for notes so slow that alting is not necessary. private double speedPenalty(double noteLengthMS) { + if (noteLengthMS < 80) return 1; - if (noteLengthMS < 160) return Math.Max(0, 1.4 - 0.005 * noteLengthMS); - if (noteLengthMS < 300) return 0.6; + // return Math.Max(0, 1.4 - 0.005 * noteLengthMS); + if (noteLengthMS < 210) return Math.Max(0, 1.4 - 0.005 * noteLengthMS); + if (noteLengthMS < 210) return 0.6; + + currentStrain = 0.0; return 0.0; } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs index 75d3807bba..783f1ba696 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs @@ -7,6 +7,10 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { public class TaikoDifficultyAttributes : DifficultyAttributes { + public double StaminaStrain; + public double RhythmStrain; + public double ColourStrain; + public double ApproachRate; public double GreatHitWindow; public int MaxCombo; } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 6e1fae01ee..2a6fa81a57 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -29,10 +29,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { } - private double readingPenalty(double staminaDifficulty) + private double simpleColourPenalty(double staminaDifficulty, double colorDifficulty) { - return Math.Max(0, 1 - staminaDifficulty / 14); - // return 1; + return 0.79 - Math.Atan(staminaDifficulty / colorDifficulty - 12) / Math.PI / 2; } private double norm(double p, double v1, double v2, double v3) @@ -48,15 +47,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { if (sr <= 1) return sr; sr -= 1; - sr = 1.5 * Math.Pow(sr, 0.76); + sr = 1.6 * Math.Pow(sr, 0.7); sr += 1; return sr; } - private double combinedDifficulty(Skill colour, Skill rhythm, Skill stamina1, Skill stamina2) + private double combinedDifficulty(double staminaPenalty, Skill colour, Skill rhythm, Skill stamina1, Skill stamina2) { - double staminaRating = (stamina1.DifficultyValue() + stamina2.DifficultyValue()) * staminaSkillMultiplier; - double readingPenalty = this.readingPenalty(staminaRating); double difficulty = 0; double weight = 1; @@ -64,9 +61,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty for (int i = 0; i < colour.StrainPeaks.Count; i++) { - double colourPeak = colour.StrainPeaks[i] * colourSkillMultiplier * readingPenalty; + double colourPeak = colour.StrainPeaks[i] * colourSkillMultiplier; double rhythmPeak = rhythm.StrainPeaks[i] * rhythmSkillMultiplier; - double staminaPeak = (stamina1.StrainPeaks[i] + stamina2.StrainPeaks[i]) * staminaSkillMultiplier; + double staminaPeak = (stamina1.StrainPeaks[i] + stamina2.StrainPeaks[i]) * staminaSkillMultiplier * staminaPenalty; peaks.Add(norm(2, colourPeak, rhythmPeak, staminaPeak)); } @@ -85,11 +82,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty return new TaikoDifficultyAttributes { Mods = mods, Skills = skills }; double staminaRating = (skills[2].DifficultyValue() + skills[3].DifficultyValue()) * staminaSkillMultiplier; - double readingPenalty = this.readingPenalty(staminaRating); - - double colourRating = skills[0].DifficultyValue() * colourSkillMultiplier * readingPenalty; + double colourRating = skills[0].DifficultyValue() * colourSkillMultiplier; double rhythmRating = skills[1].DifficultyValue() * rhythmSkillMultiplier; - double combinedRating = combinedDifficulty(skills[0], skills[1], skills[2], skills[3]); + + double staminaPenalty = simpleColourPenalty(staminaRating, colourRating); + staminaRating *= staminaPenalty; + + double combinedRating = combinedDifficulty(staminaPenalty, skills[0], skills[1], skills[2], skills[3]); // Console.WriteLine("colour\t" + colourRating); // Console.WriteLine("rhythm\t" + rhythmRating); @@ -107,6 +106,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { StarRating = starRating, Mods = mods, + StaminaStrain = staminaRating, + RhythmStrain = rhythmRating, + ColourStrain = colourRating, // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future GreatHitWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate, MaxCombo = beatmap.HitObjects.Count(h => h is Hit),