コード例 #1
0
        /// <summary>
        /// Generates random hold notes that start at an span the same amount of rows.
        /// </summary>
        /// <param name="startTime">Start time of each hold note.</param>
        /// <param name="noteCount">Number of hold notes.</param>
        /// <returns>The <see cref="Pattern"/> containing the hit objects.</returns>
        private Pattern generateRandomHoldNotes(double startTime, int noteCount)
        {
            // - - - -
            // ■ - ■ ■
            // □ - □ □
            // ■ - ■ ■

            var pattern = new Pattern();

            int usableColumns = TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects;
            int nextColumn    = Random.Next(RandomStart, TotalColumns);

            for (int i = 0; i < Math.Min(usableColumns, noteCount); i++)
            {
                while (pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn))  //find available column
                {
                    nextColumn = Random.Next(RandomStart, TotalColumns);
                }
                addToPattern(pattern, nextColumn, startTime, endTime);
            }

            // This is can't be combined with the above loop due to RNG
            for (int i = 0; i < noteCount - usableColumns; i++)
            {
                while (pattern.ColumnHasObject(nextColumn))
                {
                    nextColumn = Random.Next(RandomStart, TotalColumns);
                }
                addToPattern(pattern, nextColumn, startTime, endTime);
            }

            return(pattern);
        }
コード例 #2
0
        /// <summary>
        /// Picks a random column after a column.
        /// </summary>
        /// <param name="start">The starting column.</param>
        /// <returns>A random column after <paramref name="start"/>.</returns>
        private int getNextRandomColumn(int start)
        {
            int nextColumn = Random.Next(start, TotalColumns);

            while (PreviousPattern.ColumnHasObject(nextColumn))
            {
                nextColumn = Random.Next(start, TotalColumns);
            }

            return(nextColumn);
        }
コード例 #3
0
        /// <summary>
        /// Picks a random column after a column.
        /// </summary>
        /// <param name="start">The starting column.</param>
        /// <returns>A random column after <paramref name="start"/>.</returns>
        private int getNextRandomColumn(int start)
        {
            int nextColumn = Random.Next(start, TotalColumns);

            RunWhile(() => PreviousPattern.ColumnHasObject(nextColumn), () =>
            {
                nextColumn = Random.Next(start, TotalColumns);
            });

            return(nextColumn);
        }
コード例 #4
0
        /// <summary>
        /// Generates tiled hold notes. You can think of this as a stair of hold notes.
        /// </summary>
        /// <param name="startTime">The first hold note start time.</param>
        /// <returns>The <see cref="Pattern"/> containing the hit objects.</returns>
        private Pattern generateTiledHoldNotes(double startTime)
        {
            // - - - -
            // ■ ■ ■ ■
            // □ □ □ □
            // □ □ □ □
            // □ □ □ ■
            // □ □ ■ -
            // □ ■ - -
            // ■ - - -

            var pattern = new Pattern();

            int columnRepeat = Math.Min(spanCount, TotalColumns);

            int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);

            if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns)
            {
                while (PreviousPattern.ColumnHasObject(nextColumn))
                {
                    nextColumn = Random.Next(RandomStart, TotalColumns);
                }
            }

            for (int i = 0; i < columnRepeat; i++)
            {
                while (pattern.ColumnHasObject(nextColumn))
                {
                    nextColumn = Random.Next(RandomStart, TotalColumns);
                }

                addToPattern(pattern, nextColumn, startTime, endTime);
                startTime += segmentDuration;
            }

            return(pattern);
        }
コード例 #5
0
        /// <summary>
        /// Generates random notes, with one note per row and no stacking.
        /// </summary>
        /// <param name="startTime">The start time.</param>
        /// <param name="noteCount">The number of notes.</param>
        /// <returns>The <see cref="Pattern"/> containing the hit objects.</returns>
        private Pattern generateRandomNotes(double startTime, int noteCount)
        {
            // - - - -
            // x - - -
            // - - x -
            // - - - x
            // x - - -

            var pattern = new Pattern();

            int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);

            if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns)
            {
                RunWhile(() => PreviousPattern.ColumnHasObject(nextColumn), () =>
                {
                    nextColumn = Random.Next(RandomStart, TotalColumns);
                });
            }

            int lastColumn = nextColumn;

            for (int i = 0; i < noteCount; i++)
            {
                addToPattern(pattern, nextColumn, startTime, startTime);

                RunWhile(() => nextColumn == lastColumn, () =>
                {
                    nextColumn = Random.Next(RandomStart, TotalColumns);
                });

                lastColumn = nextColumn;
                startTime += SegmentDuration;
            }

            return(pattern);
        }
コード例 #6
0
        /// <summary>
        /// Generates random notes, with one note per row and no stacking.
        /// </summary>
        /// <param name="startTime">The start time.</param>
        /// <param name="noteCount">The number of notes.</param>
        /// <returns>The <see cref="Pattern"/> containing the hit objects.</returns>
        private Pattern generateRandomNotes(double startTime, int noteCount)
        {
            // - - - -
            // x - - -
            // - - x -
            // - - - x
            // x - - -

            var pattern = new Pattern();

            int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);

            if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < AvailableColumns)
            {
                while (PreviousPattern.ColumnHasObject(nextColumn))
                {
                    nextColumn = Random.Next(RandomStart, AvailableColumns);
                }
            }

            int lastColumn = nextColumn;

            for (int i = 0; i < noteCount; i++)
            {
                addToPattern(pattern, nextColumn, startTime, startTime);
                while (nextColumn == lastColumn)
                {
                    nextColumn = Random.Next(RandomStart, AvailableColumns);
                }

                lastColumn = nextColumn;
                startTime += segmentDuration;
            }

            return(pattern);
        }
コード例 #7
0
        /// <summary>
        /// Generates random notes.
        /// <para>
        /// This will generate as many as it can up to <paramref name="noteCount"/>, accounting for
        /// any stacks if <see cref="convertType"/> is forcing no stacks.
        /// </para>
        /// </summary>
        /// <param name="noteCount">The amount of notes to generate.</param>
        /// <returns>The <see cref="Pattern"/> containing the hit objects.</returns>
        private Pattern generateRandomNotes(int noteCount)
        {
            var pattern = new Pattern();

            bool allowStacking = !convertType.HasFlag(PatternType.ForceNotStack);

            if (!allowStacking)
            {
                noteCount = Math.Min(noteCount, TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects);
            }

            int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);

            for (int i = 0; i < noteCount; i++)
            {
                while (pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn) && !allowStacking)
                {
                    if (convertType.HasFlag(PatternType.Gathered))
                    {
                        nextColumn++;
                        if (nextColumn == TotalColumns)
                        {
                            nextColumn = RandomStart;
                        }
                    }
                    else
                    {
                        nextColumn = Random.Next(RandomStart, TotalColumns);
                    }
                }

                addToPattern(pattern, nextColumn);
            }

            return(pattern);
        }
コード例 #8
0
        public override IEnumerable <Pattern> Generate()
        {
            Pattern generateCore()
            {
                var pattern = new Pattern();

                if (TotalColumns == 1)
                {
                    addToPattern(pattern, 0);
                    return(pattern);
                }

                int lastColumn = PreviousPattern.HitObjects.FirstOrDefault()?.Column ?? 0;

                if (convertType.HasFlagFast(PatternType.Reverse) && PreviousPattern.HitObjects.Any())
                {
                    // Generate a new pattern by copying the last hit objects in reverse-column order
                    for (int i = RandomStart; i < TotalColumns; i++)
                    {
                        if (PreviousPattern.ColumnHasObject(i))
                        {
                            addToPattern(pattern, RandomStart + TotalColumns - i - 1);
                        }
                    }

                    return(pattern);
                }

                if (convertType.HasFlagFast(PatternType.Cycle) && PreviousPattern.HitObjects.Count() == 1
                    // If we convert to 7K + 1, let's not overload the special key
                    && (TotalColumns != 8 || lastColumn != 0)
                    // Make sure the last column was not the centre column
                    && (TotalColumns % 2 == 0 || lastColumn != TotalColumns / 2))
                {
                    // Generate a new pattern by cycling backwards (similar to Reverse but for only one hit object)
                    int column = RandomStart + TotalColumns - lastColumn - 1;
                    addToPattern(pattern, column);

                    return(pattern);
                }

                if (convertType.HasFlagFast(PatternType.ForceStack) && PreviousPattern.HitObjects.Any())
                {
                    // Generate a new pattern by placing on the already filled columns
                    for (int i = RandomStart; i < TotalColumns; i++)
                    {
                        if (PreviousPattern.ColumnHasObject(i))
                        {
                            addToPattern(pattern, i);
                        }
                    }

                    return(pattern);
                }

                if (PreviousPattern.HitObjects.Count() == 1)
                {
                    if (convertType.HasFlagFast(PatternType.Stair))
                    {
                        // Generate a new pattern by placing on the next column, cycling back to the start if there is no "next"
                        int targetColumn = lastColumn + 1;
                        if (targetColumn == TotalColumns)
                        {
                            targetColumn = RandomStart;
                        }

                        addToPattern(pattern, targetColumn);
                        return(pattern);
                    }

                    if (convertType.HasFlagFast(PatternType.ReverseStair))
                    {
                        // Generate a new pattern by placing on the previous column, cycling back to the end if there is no "previous"
                        int targetColumn = lastColumn - 1;
                        if (targetColumn == RandomStart - 1)
                        {
                            targetColumn = TotalColumns - 1;
                        }

                        addToPattern(pattern, targetColumn);
                        return(pattern);
                    }
                }

                if (convertType.HasFlagFast(PatternType.KeepSingle))
                {
                    return(generateRandomNotes(1));
                }

                if (convertType.HasFlagFast(PatternType.Mirror))
                {
                    if (ConversionDifficulty > 6.5)
                    {
                        return(generateRandomPatternWithMirrored(0.12, 0.38, 0.12));
                    }
                    if (ConversionDifficulty > 4)
                    {
                        return(generateRandomPatternWithMirrored(0.12, 0.17, 0));
                    }

                    return(generateRandomPatternWithMirrored(0.12, 0, 0));
                }

                if (ConversionDifficulty > 6.5)
                {
                    if (convertType.HasFlagFast(PatternType.LowProbability))
                    {
                        return(generateRandomPattern(0.78, 0.42, 0, 0));
                    }

                    return(generateRandomPattern(1, 0.62, 0, 0));
                }

                if (ConversionDifficulty > 4)
                {
                    if (convertType.HasFlagFast(PatternType.LowProbability))
                    {
                        return(generateRandomPattern(0.35, 0.08, 0, 0));
                    }

                    return(generateRandomPattern(0.52, 0.15, 0, 0));
                }

                if (ConversionDifficulty > 2)
                {
                    if (convertType.HasFlagFast(PatternType.LowProbability))
                    {
                        return(generateRandomPattern(0.18, 0, 0, 0));
                    }

                    return(generateRandomPattern(0.45, 0, 0, 0));
                }

                return(generateRandomPattern(0, 0, 0, 0));
            }

            var p = generateCore();

            foreach (var obj in p.HitObjects)
            {
                if (convertType.HasFlagFast(PatternType.Stair) && obj.Column == TotalColumns - 1)
                {
                    StairType = PatternType.ReverseStair;
                }
                if (convertType.HasFlagFast(PatternType.ReverseStair) && obj.Column == RandomStart)
                {
                    StairType = PatternType.Stair;
                }
            }

            return(p.Yield());
        }
コード例 #9
0
        /// <summary>
        /// Generates a hold note alongside normal notes.
        /// </summary>
        /// <param name="startTime">The start time of notes.</param>
        /// <returns>The <see cref="Pattern"/> containing the hit objects.</returns>
        private Pattern generateHoldAndNormalNotes(double startTime)
        {
            // - - - -
            // ■ x x -
            // ■ - x x
            // ■ x - x
            // ■ - x x

            var pattern = new Pattern();

            int holdColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);

            if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns)
            {
                while (PreviousPattern.ColumnHasObject(holdColumn))
                {
                    holdColumn = Random.Next(RandomStart, TotalColumns);
                }
            }

            // Create the hold note
            addToPattern(pattern, holdColumn, startTime, endTime);

            int nextColumn = Random.Next(RandomStart, TotalColumns);
            int noteCount;

            if (ConversionDifficulty > 6.5)
            {
                noteCount = GetRandomNoteCount(0.63, 0);
            }
            else if (ConversionDifficulty > 4)
            {
                noteCount = GetRandomNoteCount(TotalColumns < 6 ? 0.12 : 0.45, 0);
            }
            else if (ConversionDifficulty > 2.5)
            {
                noteCount = GetRandomNoteCount(TotalColumns < 6 ? 0 : 0.24, 0);
            }
            else
            {
                noteCount = 0;
            }
            noteCount = Math.Min(TotalColumns - 1, noteCount);

            bool ignoreHead = !sampleInfoListAt(startTime).Any(s => s.Name == SampleInfo.HIT_WHISTLE || s.Name == SampleInfo.HIT_FINISH || s.Name == SampleInfo.HIT_CLAP);

            var rowPattern = new Pattern();

            for (int i = 0; i <= spanCount; i++)
            {
                if (!(ignoreHead && startTime == HitObject.StartTime))
                {
                    for (int j = 0; j < noteCount; j++)
                    {
                        while (rowPattern.ColumnHasObject(nextColumn) || nextColumn == holdColumn)
                        {
                            nextColumn = Random.Next(RandomStart, TotalColumns);
                        }
                        addToPattern(rowPattern, nextColumn, startTime, startTime);
                    }
                }

                pattern.Add(rowPattern);
                rowPattern.Clear();

                startTime += segmentDuration;
            }

            return(pattern);
        }