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

Refactor generation

This commit is contained in:
smoogipoo 2020-10-14 19:31:31 +09:00
parent 7d2eeb9795
commit e9ebeedbe2

View File

@ -105,10 +105,11 @@ namespace osu.Game.Rulesets.Difficulty
/// </summary>
public Mod[] CreateDifficultyAdjustmentModCombinations()
{
return createDifficultyAdjustmentModCombinations(Array.Empty<Mod>(), DifficultyAdjustmentMods).ToArray();
return createDifficultyAdjustmentModCombinations(DifficultyAdjustmentMods, Array.Empty<Mod>()).ToArray();
static IEnumerable<Mod> createDifficultyAdjustmentModCombinations(IEnumerable<Mod> currentSet, Mod[] adjustmentSet, int currentSetCount = 0, int adjustmentSetStart = 0)
static IEnumerable<Mod> createDifficultyAdjustmentModCombinations(ReadOnlyMemory<Mod> remainingMods, IEnumerable<Mod> currentSet, int currentSetCount = 0)
{
// Return the current set.
switch (currentSetCount)
{
case 0:
@ -128,11 +129,10 @@ namespace osu.Game.Rulesets.Difficulty
break;
}
// Apply mods in the adjustment set recursively. Using the entire adjustment set would result in duplicate multi-mod mod
// combinations in further recursions, so a moving subset is used to eliminate this effect
for (int i = adjustmentSetStart; i < adjustmentSet.Length; i++)
// Apply the rest of the remaining mods recursively.
for (int i = 0; i < remainingMods.Length; i++)
{
var adjustmentMod = adjustmentSet[i];
var adjustmentMod = remainingMods.Span[i];
if (currentSet.Any(c => c.IncompatibleMods.Any(m => m.IsInstanceOfType(adjustmentMod))
|| adjustmentMod.IncompatibleMods.Any(m => m.IsInstanceOfType(c))))
@ -141,27 +141,30 @@ namespace osu.Game.Rulesets.Difficulty
}
// Append the new mod.
int newSetCount = currentSetCount;
var newSet = append(currentSet, adjustmentMod, ref newSetCount);
var (newSet, newSetCount) = flatten(adjustmentMod);
foreach (var combo in createDifficultyAdjustmentModCombinations(newSet, adjustmentSet, newSetCount, i + 1))
foreach (var combo in createDifficultyAdjustmentModCombinations(remainingMods.Slice(i + 1), currentSet.Concat(newSet), currentSetCount + newSetCount))
yield return combo;
}
}
// Appends a mod to an existing enumerable, returning the result. Recurses for MultiMod.
static IEnumerable<Mod> append(IEnumerable<Mod> existing, Mod mod, ref int count)
// Flattens a mod hierarchy (through MultiMod) as an IEnumerable<Mod>
static (IEnumerable<Mod> set, int count) flatten(Mod mod)
{
if (mod is MultiMod multi)
{
foreach (var nested in multi.Mods)
existing = append(existing, nested, ref count);
if (!(mod is MultiMod multi))
return (mod.Yield(), 1);
return existing;
IEnumerable<Mod> set = Enumerable.Empty<Mod>();
int count = 0;
foreach (var nested in multi.Mods)
{
var (nestedSet, nestedCount) = flatten(nested);
set = set.Concat(nestedSet);
count += nestedCount;
}
count++;
return existing.Append(mod);
return (set, count);
}
}