From 17aed26f854ee5c45de5e84bb2ea5639446e708a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Oct 2024 13:03:58 +0200 Subject: [PATCH 1/2] Fix shuffle not actually changing the track sometimes See https://github.com/ppy/osu/pull/30215#issuecomment-2407775408 for context. Turns out the test failures were more correct than I'd thought. The long-and-short of it is that both in "pure random" mode and in "permutation" mode, when running out of track history to fall back on, it was possible for the random algorithm to pick the same song twice in a row - which is probably not desired, and which this explicit exclude should make impossible. --- osu.Game/Overlays/MusicController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index a269dbdf4f..0f88765593 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -376,7 +376,7 @@ namespace osu.Game.Overlays { Live result; - var possibleSets = getBeatmapSets().Where(s => !s.Value.Protected || allowProtectedTracks).ToArray(); + var possibleSets = getBeatmapSets().Where(s => !s.Value.Equals(current?.BeatmapSetInfo) && (!s.Value.Protected || allowProtectedTracks)).ToArray(); if (possibleSets.Length == 0) return null; From 8cec318c1fc2ec9d6eafd0b4a00d8320ca2c5123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Oct 2024 15:28:32 +0200 Subject: [PATCH 2/2] Loop track even if shuffling if there is only one available Co-authored-by: Dean Herbert --- osu.Game/Overlays/MusicController.cs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 0f88765593..87920fdf55 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -376,11 +376,19 @@ namespace osu.Game.Overlays { Live result; - var possibleSets = getBeatmapSets().Where(s => !s.Value.Equals(current?.BeatmapSetInfo) && (!s.Value.Protected || allowProtectedTracks)).ToArray(); + var possibleSets = getBeatmapSets().Where(s => !s.Value.Protected || allowProtectedTracks).ToList(); - if (possibleSets.Length == 0) + if (possibleSets.Count == 0) return null; + // if there is only one possible set left, play it, even if it is the same as the current track. + // looping is preferable over playing nothing. + if (possibleSets.Count == 1) + return possibleSets.Single(); + + // now that we actually know there is a choice, do not allow the current track to be played again. + possibleSets.RemoveAll(s => s.Value.Equals(current?.BeatmapSetInfo)); + // condition below checks if the signs of `randomHistoryDirection` and `direction` are opposite and not zero. // if that is the case, it means that the user had previously chosen next track `randomHistoryDirection` times and wants to go back, // or that the user had previously chosen previous track `randomHistoryDirection` times and wants to go forward. @@ -410,20 +418,20 @@ namespace osu.Game.Overlays switch (randomSelectAlgorithm.Value) { case RandomSelectAlgorithm.Random: - result = possibleSets[RNG.Next(possibleSets.Length)]; + result = possibleSets[RNG.Next(possibleSets.Count)]; break; case RandomSelectAlgorithm.RandomPermutation: - var notYetPlayedSets = possibleSets.Except(previousRandomSets).ToArray(); + var notYetPlayedSets = possibleSets.Except(previousRandomSets).ToList(); - if (notYetPlayedSets.Length == 0) + if (notYetPlayedSets.Count == 0) { notYetPlayedSets = possibleSets; previousRandomSets.Clear(); randomHistoryDirection = 0; } - result = notYetPlayedSets[RNG.Next(notYetPlayedSets.Length)]; + result = notYetPlayedSets[RNG.Next(notYetPlayedSets.Count)]; break; default: