From e6193e8b98cd95b8c7136f480a6d4c45957a7609 Mon Sep 17 00:00:00 2001 From: apollo-dw <83023433+apollo-dw@users.noreply.github.com> Date: Wed, 10 Aug 2022 19:09:42 +0100 Subject: [PATCH] Use past objects for note density --- .../Evaluators/CognitionEvaluator.cs | 60 ++++++++----------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/CognitionEvaluator.cs b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/CognitionEvaluator.cs index 66473cad28..4f2f5b05f8 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/CognitionEvaluator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/CognitionEvaluator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using FFmpeg.AutoGen; using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; @@ -12,6 +13,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators { public static class CognitionEvaluator { + private const double cognition_window_size = 2000; + public static double EvaluateDifficultyOf(DifficultyHitObject current, bool hidden) { if (current.BaseObject is Spinner || current.Index == 0) @@ -20,44 +23,33 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators var currObj = (OsuDifficultyHitObject)current; double currVelocity = currObj.LazyJumpDistance / currObj.StrainTime; - List pastVisibleObjects = retrievePastVisibleObjects(currObj); - List currentVisibleObjects = retrieveCurrentVisibleObjects(currObj); + List pastVisibleObjects = retrievePastVisibleObjects(currObj); + List currentVisibleObjects = retrieveCurrentVisibleObjects(currObj); // Rather than note density being the number of on-screen objects visible at the current object, // consider it as how many objects the current object has been visible for. - double noteDensity = 1.0; + double noteDensityDifficulty = 1.0; - double loopOpacity = 1.0; - int previousIndex = 0; - - while (loopOpacity > 0) + foreach (var loopObj in pastVisibleObjects) { - var loopObj = (OsuDifficultyHitObject)currObj.Previous(previousIndex); + var prevLoopObj = (OsuDifficultyHitObject)loopObj.Previous(0); - if (loopObj.IsNull()) - break; + double loopDifficulty = currObj.OpacityAt(loopObj.BaseObject.StartTime, false); - loopOpacity = currObj.OpacityAt(loopObj.StartTime, false); + // Small distances means objects may be cheesed, so it doesn't matter whether they are arranged confusingly. + loopDifficulty *= logistic((loopObj.MinimumJumpDistance - 125) / 15); - if (loopOpacity <= 0) - break; + // Objects that are arranged in a mostly-linear fashion should be easy to read (such as circles in a stream). + //if (loopObj.Angle.IsNotNull() && prevLoopObj.Angle.IsNotNull()) + // loopDifficulty *= 1 - Math.Pow(Math.Sin(0.5 * loopObj.Angle.Value), 5); - noteDensity += loopOpacity; - previousIndex++; + noteDensityDifficulty += loopDifficulty; } - double noteDensityDifficulty = Math.Pow(Math.Max(0, noteDensity - 2), 2); + noteDensityDifficulty = Math.Pow(3 * Math.Log(Math.Max(1, noteDensityDifficulty - 1)), 2.3); double hiddenDifficulty = 0; - if (hidden) - { - noteDensityDifficulty *= 3.2; - - // Really not sure about this, but without this a lot of normal HD plays become underweight. - hiddenDifficulty = 7 * currObj.LazyJumpDistance / currObj.StrainTime; - } - double preemptDifficulty = 0.0; if (currObj.preempt < 400) preemptDifficulty += Math.Pow(400 - currObj.preempt, 1.5) / 14; @@ -72,18 +64,18 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators // Returns a list of objects that are visible on screen at // the point in time at which the current object becomes visible. - private static List retrievePastVisibleObjects(OsuDifficultyHitObject current) + private static List retrievePastVisibleObjects(OsuDifficultyHitObject current) { - List objects = new List(); + List objects = new List(); for (int i = 0; i < current.Index; i++) { - DifficultyHitObject currentObj = current.Previous(i); + OsuDifficultyHitObject loopObj = (OsuDifficultyHitObject)current.Previous(i); - if (current.OpacityAt(currentObj.StartTime, false) <= 0) + if (loopObj.IsNull() || current.StartTime - loopObj.StartTime > cognition_window_size) break; - objects.Add(currentObj); + objects.Add(loopObj); } return objects; @@ -91,18 +83,18 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators // Returns a list of objects that are visible on screen at // the point in time at which the current object needs is clicked. - private static List retrieveCurrentVisibleObjects(OsuDifficultyHitObject current) + private static List retrieveCurrentVisibleObjects(OsuDifficultyHitObject current) { - List objects = new List(); + List objects = new List(); for (int i = 0; i < current.Count; i++) { - OsuDifficultyHitObject currentObj = (OsuDifficultyHitObject)current.Next(i); + OsuDifficultyHitObject loopObj = (OsuDifficultyHitObject)current.Next(i); - if (currentObj.IsNull() || currentObj.OpacityAt(current.StartTime, false) <= 0) + if (loopObj.IsNull() || (loopObj.StartTime - current.StartTime) > cognition_window_size) break; - objects.Add(currentObj); + objects.Add(loopObj); } return objects;