Cindeck.Core.Simulator.StartSimulation C# (CSharp) Method

StartSimulation() public method

public StartSimulation ( Random rng, int id, Queue pattern = null ) : SimulationResult
rng System.Random
id int
pattern Queue
return SimulationResult
        public SimulationResult StartSimulation(Random rng, int id, Queue<Note> pattern=null)
        {
            var result = new SimulationResult(id);
            if (SongData == null)
                return result;

            int totalScore = 0;
            double scorePerNote = (TotalAppeal * LevelCoefficients[SongData.Level]) / SongData.Notes;
            int totalLife = Life, maxLife = Life;
            CenterEffect.SkillTriggerProbabilityUp skillRateUp = null;

            if (Unit.Center != null && Unit.Center.CenterEffect != null && Unit.Center.CenterEffect is CenterEffect.SkillTriggerProbabilityUp)
            {
                skillRateUp = Unit.Center.CenterEffect as CenterEffect.SkillTriggerProbabilityUp;
            }

            double comboRate = 1;

            List<TriggeredSkill> scoreUp = new List<TriggeredSkill>(),
                comboBonus = new List<TriggeredSkill>(), overload = new List<TriggeredSkill>(),
                damgeGuard = new List<TriggeredSkill>(), revival = new List<TriggeredSkill>();

            if (pattern == null)
            {
                var interval = (double)SongData.Duration / SongData.Notes;
                pattern = new Queue<Note>(Enumerable.Range(1, SongData.Notes).Select(x => new Note { Id = x, Time = x * interval }));
            }

            double currentTime = .01;
            int notes=0;
            bool sync = false;
            while (currentTime <= SongData.Duration)
            {
                CheckSkillDueTime(currentTime, scoreUp, comboBonus, overload, damgeGuard, revival);
                if (currentTime < SongData.Duration && !sync)
                {
                    var f = (int)Math.Round(currentTime * TimeScale);
                    foreach (var slot in Unit.Slots)
                    {
                        if (slot != null && slot.Skill != null)
                        {
                            var sb = slot.Skill as Skill;
                            if (f % (sb.Interval*TimeScale) == 0)
                            {
                                //var propability = sb.EstimateProbability(slot.SkillLevel) * //素の確率
                                //                   (1 + (Song.Type.HasFlag(slot.Category) ? 0.3 : 0) +  //属性一致ボーナス
                                //                        (skillRateUp != null && skillRateUp.Targets.HasFlag(slot.Category) ? skillRateUp.Rate : 0)); //センター効果
                                var propability = GetSkillTriggerProbability(slot, Unit.Center, Guest, Song);
                                if (SkillControl != SkillTriggerControl.NeverTrigger &&
                                    (SkillControl == SkillTriggerControl.AlwaysTrigger || rng.NextDouble() < propability))
                                {
                                    var skill = new TriggeredSkill
                                    {
                                        Who = slot,
                                        Since = currentTime,
                                        Until = currentTime + sb.EstimateDuration(slot.SkillLevel)
                                    };

                                    switch (sb.GetType().Name)
                                    {
                                        case nameof(Skill.DamageGuard):
                                            damgeGuard.Add(skill);
                                            break;
                                        case nameof(Skill.Revival):
                                            revival.Add(skill);
                                            break;
                                        case nameof(Skill.ScoreBonus):
                                            scoreUp.Add(skill);
                                            break;
                                        case nameof(Skill.ComboBonus):
                                            comboBonus.Add(skill);
                                            break;
                                        case nameof(Skill.Overload):
                                            var o = sb as Skill.Overload;
                                            if (totalLife - o.ConsumingLife > 0)
                                            {
                                                if (!damgeGuard.Any())
                                                {
                                                    totalLife -= o.ConsumingLife;
                                                }
                                                overload.Add(skill);
                                            }
                                            else
                                            {
                                                continue;
                                            }
                                            break;
                                        default:
                                            break;
                                    }

                                    result.TriggeredSkills.Add(skill);
                                }
                            }
                        }
                    }
                }

                if (pattern.Count > 0 && pattern.Peek().Time <= currentTime)
                {
                    comboRate = CalculateComboRate(notes, SongData.Notes);

                    totalLife += revival.Select(x => x.Who.Skill).Cast<Skill.Revival>().Select(x => x.Amount).DefaultIfEmpty(0).Max();
                    if (totalLife > maxLife) totalLife = maxLife;

                    var scoreUpRate = 1 + scoreUp.Select(x => x.Rate).Concat(overload.Select(x => x.Rate)).DefaultIfEmpty(0).Max();
                    var comboUpRate = 1 + comboBonus.Select(x => x.Rate).DefaultIfEmpty(0).Max();
                    totalScore += (int)Math.Round(scorePerNote * comboRate * scoreUpRate * comboUpRate);

                    notes++;
                    var note = pattern.Dequeue();

                    if (pattern.Count > 0 && note.Time == pattern.Peek().Time)
                    {
                        sync = true;
                        continue;
                    }
                    sync = false;
                }

                currentTime += 0.01;
            }

            result.Score = totalScore;
            result.Duration = SongData.Duration;
            result.RemainingLife = totalLife;
            result.ScorePerNote = (int)Math.Round((double)totalScore / SongData.Notes);
            ResultsUpToDate = true;
            return result;
        }