/// <summary>
        /// Finds and marks all sequences hittable using a roll.
        /// </summary>
        /// <param name="patternLength">The length of a single repeating pattern to consider (triplets/quadruplets).</param>
        private void findRolls(int patternLength)
        {
            var history = new LimitedCapacityQueue <TaikoDifficultyHitObject>(2 * patternLength);

            // for convenience, we're tracking the index of the item *before* our suspected repeat's start,
            // as that index can be simply subtracted from the current index to get the number of elements in between
            // without off-by-one errors
            int indexBeforeLastRepeat = -1;

            for (int i = 0; i < hitObjects.Count; i++)
            {
                history.Enqueue(hitObjects[i]);
                if (!history.Full)
                {
                    continue;
                }

                if (!containsPatternRepeat(history, patternLength))
                {
                    // we're setting this up for the next iteration, hence the +1.
                    // right here this index will point at the queue's front (oldest item),
                    // but that item is about to be popped next loop with an enqueue.
                    indexBeforeLastRepeat = i - history.Count + 1;
                    continue;
                }

                int repeatedLength = i - indexBeforeLastRepeat;
                if (repeatedLength < roll_min_repetitions)
                {
                    continue;
                }

                markObjectsAsCheese(i, repeatedLength);
            }
        }
        protected override double StrainValueOf(DifficultyHitObject current)
        {
            if (!(current.BaseObject is Hit))
            {
                return(0.0);
            }

            TaikoDifficultyHitObject hitObject = (TaikoDifficultyHitObject)current;

            if (hitObject.ObjectIndex % 2 == hand)
            {
                double objectStrain = 1;

                if (hitObject.ObjectIndex == 1)
                {
                    return(1);
                }

                notePairDurationHistory.Enqueue(hitObject.DeltaTime + offhandObjectDuration);

                double shortestRecentNote = notePairDurationHistory.Min();
                objectStrain += speedBonus(shortestRecentNote);

                if (hitObject.StaminaCheese)
                {
                    objectStrain *= cheesePenalty(hitObject.DeltaTime + offhandObjectDuration);
                }

                return(objectStrain);
            }

            offhandObjectDuration = hitObject.DeltaTime;
            return(0);
        }
Esempio n. 3
0
        public void TestBelowCapacity(int count)
        {
            for (int i = 0; i < count; ++i)
            {
                queue.Enqueue(i);
            }

            Assert.AreEqual(count, queue.Count);

            for (int i = 0; i < count; ++i)
            {
                Assert.AreEqual(i, queue[i]);
            }

            int j = 0;

            foreach (int item in queue)
            {
                Assert.AreEqual(j++, item);
            }

            for (int i = queue.Count; i < queue.Count + capacity; i++)
            {
                Assert.Throws <ArgumentOutOfRangeException>(() => _ = queue[i]);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Returns a penalty to apply to the current hit object caused by repeating rhythm changes.
        /// </summary>
        /// <remarks>
        /// Repetitions of more recent patterns are associated with a higher penalty.
        /// </remarks>
        /// <param name="hitObject">The current hit object being considered.</param>
        private double repetitionPenalties(TaikoDifficultyHitObject hitObject)
        {
            double penalty = 1;

            rhythmHistory.Enqueue(hitObject);

            for (int mostRecentPatternsToCompare = 2; mostRecentPatternsToCompare <= rhythm_history_max_length / 2; mostRecentPatternsToCompare++)
            {
                for (int start = rhythmHistory.Count - mostRecentPatternsToCompare - 1; start >= 0; start--)
                {
                    if (!samePattern(start, mostRecentPatternsToCompare))
                    {
                        continue;
                    }

                    int notesSince = hitObject.ObjectIndex - rhythmHistory[start].ObjectIndex;
                    penalty *= repetitionPenalty(notesSince);
                    break;
                }
            }

            return(penalty);
        }