Beispiel #1
0
        public static ReportData GetReport(Level level, TimeSpan ts, TweakStats tweakStats = null)
        {
            var res = new ReportData();

            res.lcStr        = level.LevelConfiguration.GetStr();
            res.totalSeconds = ts.TotalSeconds;
            res.segCount     = level.Segs.Count;
            res.levelSize    = $"{level.Width - 2}x{level.Height - 2}";

            var decisions = GetDecisions(level);

            //hard decisions not done yet. doable now.
            var easyDecisions = decisions.Item1;
            var hardDecisions = decisions.Item2;

            res.decisionCount = easyDecisions.Count + hardDecisions.Count;

            res.coveragePercent = GetCoveragePercent(level, out int sqs);
            res.sqs             = sqs;

            res.hardDecisionPercent = hardDecisions.Count * 1.0 / sqs * 100;

            res.easyDecisionPercent = easyDecisions.Count * 1.0 / sqs * 100;

            //Divergence = per seg, how distant other segs does it see?
            //problem - this prioritizes long paths.
            res.divergence = GetDivergence(level);

            res.avgNeighborCount = GetAvgNeighborCount(level);

            res.avgSegLen = GetAvgSegLen(level);

            var tweakTrySum         = (tweakStats.SuccessCt + tweakStats.NoTweaks + tweakStats.NoTweaksQualify);
            var tweakSuccessPercent = tweakStats.SuccessCt * 100.0 / tweakTrySum;

            res.tweakSuccessPercent = tweakSuccessPercent;

            //TODO it would be cool to sparkline render various things like periodic segment length.
            return(res);
        }
Beispiel #2
0
        public static void AfterLevelGenerated(Level level, LevelGenerationConfig config, string levelstem, LevelConfiguration lc, TweakStats tweakStats, TimeSpan ts, CsvWriter csv, Log log, int runcount)
        {
            var repdata = GetReport(level, ts, tweakStats);
            var rep     = Report(repdata, multiline: true);

            log.Info(Report(repdata, multiline: false));
            SaveLevelAsText(level, config.seed);
            if (config.saveCsv)
            {
                csv.Write(repdata);
            }

            if (config.saveEmpty)
            {
                SaveEmpty(level, $"{levelstem}/{lc.GetStr()}-empty-{config.seed} {runcount}.png", subtitle: rep, quiet: true);
            }
            if (config.saveEmptyUpperCorner)
            {
                SaveEmpty(level, $"{levelstem}/{lc.GetStr()}-corner-{config.seed} {runcount}.png", subtitle: rep, quiet: true, corner: true);
            }
            if (config.saveWithPath)
            {
                SaveWithPath(level, $"{levelstem}/{lc.GetStr()}-path-{config.seed} {runcount}.png", subtitle: rep, quiet: true);
            }
            if (config.saveArrows)
            {
                SaveArrowVersions(level, config.seed, levelstem, config.arrowLengthMin);
            }
        }
Beispiel #3
0
        public override LinkedListNode <Seg> PickSeg(List <LinkedListNode <Seg> > newSegs, List <LinkedListNode <Seg> > modifiedSegs, TweakStats stats, bool success)
        {
            if (LastReturnedSeg == null)
            {
                LastReturnedSeg = Level.Segs.Last;
                return(Level.Segs.Last);
            }
            if (newSegs != null)
            {
                Success = true;
                var last = newSegs.Last();
                LastReturnedSeg = last;
                return(last);
            }

            var val = LastReturnedSeg.Previous;

            if (val == null)
            {
                //we got all the way back to the start.
                if (Success)
                {
                    val             = Level.Segs.Last;
                    LastReturnedSeg = val;
                    Success         = false;
                    return(val);
                }
                else
                {
                    return(null);
                }
            }
            val             = LastReturnedSeg.Previous;
            LastReturnedSeg = val;
            return(val);
        }
Beispiel #4
0
 public abstract LinkedListNode <Seg> PickSeg(List <LinkedListNode <Seg> > newSegs, List <LinkedListNode <Seg> > modifiedSegs, TweakStats stats, bool success);
Beispiel #5
0
        /// <summary>
        /// When a seg length changes, I need to know about it - SL tweaks can do this invisibly which is annoying.
        /// </summary>
        public override LinkedListNode <Seg> PickSeg(List <LinkedListNode <Seg> > newSegs, List <LinkedListNode <Seg> > modifiedSegs, TweakStats stat, bool success)
        {
            //put in the new segs.
            if (newSegs != null)
            {
                foreach (var newSeg in newSegs)
                {
                    AddSafely(newSeg);
                }
            }
            if (modifiedSegs != null)
            {
                foreach (var modseg in modifiedSegs)
                {
                    RemoveSafely(modseg);
                    AddSafely(modseg);
                }
            }
            if (success)
            {
                LoopStats.SuccessCt++;
                Success = true;
            }
            else
            {
                LoopStats.NoTweaks++;
            }

            if (Heap.Count == 0)
            {
                if (Success)
                {
                    RedoHeap();
                    Success = false;
                    stat.loopct++;

                    var lastLoopSuccessPercentage = LoopStats.SuccessCt * 1.0 / (LoopStats.SuccessCt + LoopStats.NoTweaksQualify + LoopStats.NoTweaks);
                    WL($"lastLoopSuccessPercentage: {stat.loopct} {lastLoopSuccessPercentage}");
                    //fail condition.
                    if (stat.loopct > 2)
                    {
                        //hardcore return early.
                        return(null);
                    }
                }
                else
                {
                    return(null);
                }
            }

            //the item will still hang around in the handles dict.
            var el = Heap.DeleteMax();

            //WL($"Returning seg {el.Value.Index} of len {el.Value.Len}");
            return(el);
        }
Beispiel #6
0
 public override void Init(int seed, Level level)
 {
     BaseInit(seed, level);
     RedoHeap();
     LoopStats = new TweakStats();
 }
Beispiel #7
0
        public TweakStats RepeatedlyTweak(bool saveState, int saveEvery, Stopwatch st)
        {
            //after doing the tweak we will call the segpicker with previous, new segs, next seg, success

            //initial setup.

            //change to do this all in the picker itself - it should keep state

            var stats = new TweakStats();

            var current    = LevelConfiguration.SegPicker.PickSeg(null, null, stats, false);
            var tweakct    = 0;
            var lastLoopCt = 0;

            while (current != null)
            {
                var tweaks = new List <Tweak>()
                {
                };

                tweaks.AddRange(GetTweaks(current, true));
                tweaks.AddRange(GetTweaks(current, false));
                //WL($"Generated {tweaks.Count} for {current.Value}: {current.Value.History}");
                if (!tweaks.Any())
                {
                    stats.NoTweaks++;
                    current = LevelConfiguration.SegPicker.PickSeg(null, null, stats, false);
                    //WL("NOtweaks");
                    if (current != null)
                    {
                        current.Value.History += " no";
                    }
                    continue;
                }

                //TODO is it bad that when we loop, we re-add every seg even ones which clearly haven't had anything change in the neighborhood.
                //most of the time the algo runs is recalculating things downstream of this decision

                var tweak = LevelConfiguration.TweakPicker.Picker.Invoke(tweaks);
                //if (tweak == null)
                //{
                //    //this should never happen now that I'm not using exclusionary tweakpickers.
                //    stats.NoTweaksQualify++;
                //    current = LevelConfiguration.SegPicker.PickSeg(null, null, stats, false);
                //    WL("noqualifying");
                //    current.Value.History += " noq";
                //    continue;
                //}
                //WL($"\tGottweak {tweak}");

                //seg is always destroyed. BUT, prev/next can also be modified.
                //can I just pass that along and have it removed/added with new len?
                var newSegs = ApplyTweak(tweak);
                stats.SuccessCt++;
                var modifiedSegs = new List <LinkedListNode <Seg> >()
                {
                };

                //these should never be null since we don't allow longtweaks where next is null, or shorts to start.
                if (tweak.LongTweak)
                {
                    modifiedSegs.Add(newSegs.Last().Next);
                }
                if (tweak.ShortTweak)
                {
                    modifiedSegs.Add(newSegs.First().Previous);
                }

                //var nei = Solverutil.GetNeighbors(newSegs.Last().Value);

                var newLoop = false;
                if (stats.loopct > lastLoopCt)
                {
                    lastLoopCt = stats.loopct;
                    newLoop    = true;
                }
                PossiblySaveDuringTweak(saveState, saveEvery, stats, newLoop: newLoop);

                if (stats.SuccessCt != 0 && stats.SuccessCt % 10000 == 0)
                {
                    WL($"{stats.loopct} Segs={Segs.Count} Cov={GetCoveragePercent(this, out int _)} {st.Elapsed} tweakSuccess:{(stats.SuccessCt * 1.0 / (stats.NoTweaks+stats.NoTweaksQualify+stats.SuccessCt)* 100.0).ToString("##0.0")}%");
                }
                current = LevelConfiguration.SegPicker.PickSeg(newSegs, modifiedSegs, stats, true);
                //WL($"success, advanced to: {current?.Value}");
            }

            return(stats);
        }
Beispiel #8
0
 public void PossiblySaveDuringTweak(bool saveState, int saveEvery, TweakStats stats, List <(int, int)> neighbors = null, bool newLoop = false)