예제 #1
0
파일: Simulator.cs 프로젝트: noelex/Cindeck
        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;
        }
예제 #2
0
파일: Simulator.cs 프로젝트: yowa/Cindeck
        public SimulationResult StartSimulation(Random rng, int id)
        {
            var result = new SimulationResult(id);
            if (SongData == null)
                return result;

            int totalScore = 0;
            int notes = 1;
            double scorePerNote = (TotalAppeal * LevelCoefficients[SongData.Level]) / SongData.Notes;
            double notesPerFrame = SongData.Notes / (SongData.Duration * TimeScale);
            int frame = 0;
            int totalFrame = 0;
            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>();

            while (notes <= SongData.Notes)
            {
                frame++;
                totalFrame++;

                CheckSkillDueTime(totalFrame, scoreUp, comboBonus, overload, damgeGuard, revival);

                if (totalFrame < SongData.Duration * TimeScale)
                {

                    foreach (var slot in Unit.Slots)
                    {
                        if (slot != null && slot.Skill != null)
                        {
                            var sb = slot.Skill as Skill;
                            if (totalFrame % (sb.Interval * TimeScale) == 0)
                            {
                                if (SkillControl != SkillTriggerControl.NeverTrigger &&
                                (SkillControl == SkillTriggerControl.AlwaysTrigger ||
                                rng.NextDouble() < sb.EstimateProbability(slot.SkillLevel) + (skillRateUp != null && skillRateUp.Targets.HasFlag(slot.Category) ? skillRateUp.Rate : 0)))
                                {
                                    var skill = new TriggeredSkill
                                    {
                                        Who = slot,
                                        Since = totalFrame,
                                        Until = totalFrame + sb.EstimateDuration(slot.SkillLevel) * TimeScale
                                    };

                                    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 (notes <= SongData.Notes && (frame * notesPerFrame >= 1 || totalFrame > SongData.Duration * TimeScale))
                {
                    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);

                    frame = 0;
                    notes++;
                }
            }
            result.Score = totalScore;
            result.TriggeredSkills.ForEach(x =>
            {
                x.Since = Math.Round(x.Since / TimeScale, 1);
                x.Until = Math.Round(x.Until / TimeScale, 1);
            });
            result.Duration = SongData.Duration;
            result.RemainingLife = totalLife;
            result.ScorePerNote = (int)Math.Round((double)totalScore / SongData.Notes);
            ResultsUpToDate = true;
            return result;
        }
예제 #3
0
파일: Simulator.cs 프로젝트: noelex/Cindeck
        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);
        }