1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 23:12:56 +08:00

[WIP] Colour evaluator for new colour encoding

This commit is contained in:
vun 2022-06-28 10:38:58 +08:00
parent 55e5b41c03
commit cba47f8202
7 changed files with 61 additions and 43 deletions

View File

@ -12,9 +12,19 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Evaluators
return Math.Tanh(Math.E * -(val - center) / width);
}
public static double EvaluateDifficultyOf(TaikoDifficultyHitObjectColour colour)
public static double EvaluateDifficultyOf(TaikoDifficultyHitObjectColour? colour)
{
return 1;
if (colour == null) return 0;
double difficulty = 7.5 * Math.Log(colour.Encoding.Payload.Length + 1, 10);
// foreach (ColourEncoding encoding in colour.Encoding.Payload)
// {
// difficulty += sigmoid(encoding.MonoRunLength, 1, 1) * 0.4 + 0.6;
// }
difficulty *= -sigmoid(colour.RepetitionInterval, 1, 7);
// difficulty *= -sigmoid(colour.RepetitionInterval, 2, 2) * 0.5 + 0.5;
return difficulty;
}
public static double EvaluateDifficultyOf(DifficultyHitObject current)

View File

@ -16,7 +16,8 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Evaluators
/// <param name="interval">The interval between the current and previous note hit using the same key.</param>
private static double speedBonus(double interval)
{
return Math.Pow(0.8, interval / 1000);
// return 10 / Math.Pow(interval, 0.6);
return Math.Pow(0.1, interval / 1000);
}
/// <summary>
@ -40,7 +41,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Evaluators
return 0.0;
}
double objectStrain = 0.85;
double objectStrain = 1;
objectStrain *= speedBonus(taikoCurrent.StartTime - keyPrevious.StartTime);
return objectStrain;
}

View File

@ -14,7 +14,12 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
/// Amount of consecutive encoding with the same <see cref="MonoRunLength" />
/// </summary>
public int EncodingRunLength = 1;
/// <summary>
/// How many notes are encoded with this encoding
/// </summary>
public int NoteLength => MonoRunLength + EncodingRunLength;
/// <summary>
/// Beginning index in the data that this encodes
/// </summary>
@ -27,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
public static List<ColourEncoding> Encode(List<DifficultyHitObject> data)
{
// Encoding mono lengths
// Compute mono lengths
List<ColourEncoding> firstPass = new List<ColourEncoding>();
ColourEncoding? lastEncoded = null;
for (int i = 0; i < data.Count; i++)
@ -36,7 +41,11 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
// This ignores all non-note objects, which may or may not be the desired behaviour
TaikoDifficultyHitObject previousObject = (TaikoDifficultyHitObject)taikoObject.PreviousNote(0);
if (previousObject == null || lastEncoded == null || taikoObject.HitType != previousObject.HitType)
if (
previousObject == null ||
lastEncoded == null ||
taikoObject.HitType != previousObject.HitType ||
taikoObject.Rhythm.Ratio > 1.9) // Reset colour after a slow down of 2x (set as 1.9x for margin of error)
{
lastEncoded = new ColourEncoding();
lastEncoded.StartIndex = i;
@ -47,7 +56,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
lastEncoded.MonoRunLength += 1;
}
// Encode encoding lengths
// Compute encoding lengths
List<ColourEncoding> secondPass = new List<ColourEncoding>();
lastEncoded = null;
for (int i = 0; i < firstPass.Count; i++)

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
@ -19,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
/// </summary>
public class TaikoDifficultyHitObject : DifficultyHitObject
{
private readonly IReadOnlyList<TaikoDifficultyHitObject> monoDifficultyHitObjects;
private readonly IReadOnlyList<TaikoDifficultyHitObject>? monoDifficultyHitObjects;
public readonly int MonoIndex;
private readonly IReadOnlyList<TaikoDifficultyHitObject> noteObjects;
public readonly int NoteIndex;
@ -34,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
/// by other skills in the future.
/// This need to be writeable by TaikoDifficultyHitObjectColour so that it can assign potentially reused instances
/// </summary>
public TaikoDifficultyHitObjectColour Colour;
public TaikoDifficultyHitObjectColour? Colour;
/// <summary>
/// The hit type of this hit object.
@ -65,14 +63,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
centreObjects, rimObjects, noteObjects, difficultyHitObjects.Count)
);
}
List<TaikoDifficultyHitObjectColour> colours = TaikoDifficultyHitObjectColour.EncodeAndAssign(difficultyHitObjects);
// Pre-evaluate colours
for (int i = 0; i < colours.Count; i++)
{
colours[i].EvaluatedDifficulty = ColourEvaluator.EvaluateDifficultyOf(colours[i]);
}
TaikoDifficultyHitObjectColour.EncodeAndAssign(difficultyHitObjects);
return difficultyHitObjects;
}

View File

@ -5,12 +5,11 @@ using osu.Game.Rulesets.Difficulty.Preprocessing;
namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
{
/// <summary>
/// Stores colour compression information for a <see cref="TaikoDifficultyHitObject"/>.
/// Stores colour compression information for a <see cref="TaikoDifficultyHitObject"/>. This is only present for the
/// first <see cref="TaikoDifficultyHitObject"/> in a <see cref="CoupledColourEncoding"/> chunk.
/// </summary>
public class TaikoDifficultyHitObjectColour
{
public CoupledColourEncoding Encoding { get; private set; }
private const int max_repetition_interval = 16;
/// <summary>
@ -21,11 +20,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
public int RepetitionInterval { get; private set; } = max_repetition_interval + 1;
/// <summary>
/// Evaluated colour difficulty is cached here, as difficulty don't need to be calculated per-note.
/// Encoding information of <see cref="TaikoDifficultyHitObjectColour"/>.
/// </summary>
/// TODO: Consider having all evaluated difficulty cached in TaikoDifficultyHitObject instead, since we may be
/// reusing evaluator results in the future.
public double EvaluatedDifficulty = 0;
public CoupledColourEncoding Encoding { get; private set; }
public TaikoDifficultyHitObjectColour? Previous { get; private set; } = null;
@ -60,8 +57,8 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
}
/// <summary>
/// Finds the closest previous <see cref="TaikoDifficultyHitObjectColour"/> that has the identical delta value
/// and run length with the current instance, and returns the amount of notes between them.
/// Finds the closest previous <see cref="TaikoDifficultyHitObjectColour"/> that has the identical <see cref="CoupledColourEncoding.Payload"/>.
/// Interval is defined as the amount of <see cref="CoupledColourEncoding"/> chunks between the current and repeated encoding.
/// </summary>
public void FindRepetitionInterval()
{
@ -72,7 +69,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
}
TaikoDifficultyHitObjectColour? other = Previous.Previous;
int interval = this.Encoding.StartIndex - other.Encoding.EndIndex;
int interval = 2;
while (interval < max_repetition_interval)
{
if (Encoding.hasIdenticalPayload(other.Encoding))
@ -84,7 +81,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
other = other.Previous;
if (other == null) break;
interval = this.Encoding.StartIndex - other.Encoding.EndIndex;
++interval;
}
RepetitionInterval = max_repetition_interval + 1;

View File

@ -1,12 +1,12 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
using osu.Game.Rulesets.Taiko.Difficulty.Evaluators;
namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
{
@ -18,6 +18,15 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
protected override double SkillMultiplier => 1;
protected override double StrainDecayBase => 0.4;
/// <summary>
/// Applies a speed bonus dependent on the time since the last hit.
/// </summary>
/// <param name="interval">The interval between the current and previous note hit using the same key.</param>
private static double speedBonus(double interval)
{
return Math.Pow(0.4, interval / 1000);
}
public Colour(Mod[] mods)
: base(mods)
{
@ -25,18 +34,20 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
protected override double StrainValueOf(DifficultyHitObject current)
{
TaikoDifficultyHitObjectColour colour = ((TaikoDifficultyHitObject)current).Colour;
double difficulty = colour == null ? 0 : colour.EvaluatedDifficulty;
// if (current != null && colour != null)
double difficulty = ColourEvaluator.EvaluateDifficultyOf(current);
// difficulty *= speedBonus(current.DeltaTime);
// TaikoDifficultyHitObject? taikoCurrent = (TaikoDifficultyHitObject)current;
// TaikoDifficultyHitObjectColour? colour = taikoCurrent?.Colour;
// if (taikoCurrent != null && colour != null)
// {
// ColourEncoding[] payload = colour.Encoding.Payload;
// string payloadDisplay = "";
// for (int i = 0; i < payload.Length; ++i)
// {
// payloadDisplay += $",({payload[i].MonoRunLength},{payload[i].EncodingRunLength})";
// payloadDisplay += $",({payload[i].MonoRunLength}|{payload[i].EncodingRunLength})";
// }
// System.Console.WriteLine($"{current.StartTime},{colour.RepetitionInterval},{colour.Encoding.RunLength}{payloadDisplay}");
// System.Console.WriteLine($"{current.StartTime},{difficulty},{colour.RepetitionInterval},{colour.Encoding.RunLength}{payloadDisplay}");
// }
return difficulty;

View File

@ -4,17 +4,16 @@ using System.Linq;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Taiko.Difficulty.Evaluators;
namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
{
public class Peaks : Skill
{
private const double rhythm_skill_multiplier = 0.32 * final_multiplier;
private const double colour_skill_multiplier = 0.33 * final_multiplier;
private const double stamina_skill_multiplier = 0.4 * final_multiplier;
private const double rhythm_skill_multiplier = 0.3 * final_multiplier;
private const double colour_skill_multiplier = 0.39 * final_multiplier;
private const double stamina_skill_multiplier = 0.33 * final_multiplier;
private const double final_multiplier = 0.047;
private const double final_multiplier = 0.06;
private readonly Rhythm rhythm;
private readonly Colour colour;