1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 00:47:24 +08:00

Update with latest changes

This commit is contained in:
smoogipoo 2020-05-22 20:50:21 +09:00
parent d04da46522
commit 9461097b00
4 changed files with 114 additions and 124 deletions

View File

@ -2,6 +2,8 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Collections.Generic;
using System.IO;
using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing; using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
@ -12,130 +14,108 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
public class Colour : Skill public class Colour : Skill
{ {
protected override double SkillMultiplier => 1; protected override double SkillMultiplier => 1;
protected override double StrainDecayBase => 0.3; protected override double StrainDecayBase => 0.4;
private ColourSwitch lastColourSwitch = ColourSwitch.None; private bool prevIsKat = false;
private int sameColourCount = 1;
private readonly int[] previousDonLengths = { 0, 0 }; private int currentMonoLength = 1;
private readonly int[] previousKatLengths = { 0, 0 }; private List<int> monoHistory = new List<int>();
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 double repititionPenalty(int notesSince)
private bool previousIsKat; {
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) 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 (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; if (((TaikoDifficultyHitObject)current).IsKat) sw.WriteLine("k " + Math.Min(1.25, returnVal) * returnMultiplier);
sameColourCount = 1; 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
}
} }
} }

View File

@ -49,9 +49,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
// Penalty for notes so slow that alting is not necessary. // Penalty for notes so slow that alting is not necessary.
private double speedPenalty(double noteLengthMS) private double speedPenalty(double noteLengthMS)
{ {
if (noteLengthMS < 80) return 1; if (noteLengthMS < 80) return 1;
if (noteLengthMS < 160) return Math.Max(0, 1.4 - 0.005 * noteLengthMS); // return Math.Max(0, 1.4 - 0.005 * noteLengthMS);
if (noteLengthMS < 300) return 0.6; if (noteLengthMS < 210) return Math.Max(0, 1.4 - 0.005 * noteLengthMS);
if (noteLengthMS < 210) return 0.6;
currentStrain = 0.0;
return 0.0; return 0.0;
} }

View File

@ -7,6 +7,10 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
{ {
public class TaikoDifficultyAttributes : DifficultyAttributes public class TaikoDifficultyAttributes : DifficultyAttributes
{ {
public double StaminaStrain;
public double RhythmStrain;
public double ColourStrain;
public double ApproachRate;
public double GreatHitWindow; public double GreatHitWindow;
public int MaxCombo; public int MaxCombo;
} }

View File

@ -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 0.79 - Math.Atan(staminaDifficulty / colorDifficulty - 12) / Math.PI / 2;
// return 1;
} }
private double norm(double p, double v1, double v2, double v3) 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; if (sr <= 1) return sr;
sr -= 1; sr -= 1;
sr = 1.5 * Math.Pow(sr, 0.76); sr = 1.6 * Math.Pow(sr, 0.7);
sr += 1; sr += 1;
return sr; 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 difficulty = 0;
double weight = 1; double weight = 1;
@ -64,9 +61,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
for (int i = 0; i < colour.StrainPeaks.Count; i++) 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 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)); peaks.Add(norm(2, colourPeak, rhythmPeak, staminaPeak));
} }
@ -85,11 +82,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
return new TaikoDifficultyAttributes { Mods = mods, Skills = skills }; return new TaikoDifficultyAttributes { Mods = mods, Skills = skills };
double staminaRating = (skills[2].DifficultyValue() + skills[3].DifficultyValue()) * staminaSkillMultiplier; double staminaRating = (skills[2].DifficultyValue() + skills[3].DifficultyValue()) * staminaSkillMultiplier;
double readingPenalty = this.readingPenalty(staminaRating); double colourRating = skills[0].DifficultyValue() * colourSkillMultiplier;
double colourRating = skills[0].DifficultyValue() * colourSkillMultiplier * readingPenalty;
double rhythmRating = skills[1].DifficultyValue() * rhythmSkillMultiplier; 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("colour\t" + colourRating);
// Console.WriteLine("rhythm\t" + rhythmRating); // Console.WriteLine("rhythm\t" + rhythmRating);
@ -107,6 +106,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
{ {
StarRating = starRating, StarRating = starRating,
Mods = mods, 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 // 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, GreatHitWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate,
MaxCombo = beatmap.HitObjects.Count(h => h is Hit), MaxCombo = beatmap.HitObjects.Count(h => h is Hit),