public char play(string[] screen, World world0)
        {
            if (_path.Count != 0)
            {
                return(_path.Dequeue().Control);
            }

            var player = screen.FindItem("A").FirstOrDefault();

            var diamonds = screen.FindItem("*").ToList();

            if (diamonds.Count == 0)
            {
                return('q');
            }
            if (_diamondsTotal == -1)
            {
                _diamondsTotal = diamonds.Count;
            }
            var  collected       = _diamondsTotal - diamonds.Count;
            bool startFromPlayer = world0.streak > 5 || collected > 0;

            //if (startFromPlayer)
            //    diamonds = diamonds
            //        .OrderBy(x => Math.Abs(x[0] - player[0]) + Math.Abs(x[1] - player[1]))
            //        .Take(30)
            //        .ToList();
            if (startFromPlayer)
            {
                diamonds.Insert(0, player);
            }

            var waves = diamonds
                        .Select(pos => new
            {
                Coord = pos,
                Fall  = CalcFalling(screen, pos[0], pos[1]),
                //Scored = Wave.CreatePaths(screen, pos[0], pos[1], startFromPlayer ? "A*" : "*", ":", true, 0, 0, null, Move.Moves2),
                Scored = Wave.CreatePaths(screen, pos[0], pos[1], "", ":*", true, 0, 0, diamonds.ToArray(), Move.Moves2),
            })
                        //.Where(x => x.Scored.Length != 0)
                        .ToArray();
            var dict = waves.Select((x, i) => new { Id = i, Key = x.Coord[0] + ":" + x.Coord[1] })
                       .ToDictionary(x => x.Key, x => x.Id);

            var matrix = Enumerable.Range(0, waves.Length)
                         .Select(y => Enumerable.Range(0, waves.Length).Select(x => double.PositiveInfinity).ToArray())
                         .ToArray();

            var solution = default(List <Method.Path>);

            if (matrix.Length > 2)
            {
                foreach (var item in waves)
                {
                    var fromId = dict[item.Coord[0] + ":" + item.Coord[1]];
                    foreach (var scored in item.Scored)
                    {
                        var toId  = dict[scored.Y + ":" + scored.X];
                        var steps = scored.StepsCount + waves[toId].Fall;
                        //if (!startFromPlayer || (fromId != 0 && toId != 0)) // ???????
                        //steps = steps < 10 && (!startFromPlayer || toId != 0) ? steps : 10000 + steps;
                        //if (steps > 20) steps *= 4;
                        matrix[fromId][toId] = steps;
                    }
                }
                solution = TSPSolver.Process(matrix).ToList();
                if (!startFromPlayer && collected == 0)// && solution.Any(x => x.Distance > 20))
                {
                    //if (solution.Any(x => x.Distance > 19))
                    //    while (solution[solution.Count - 1].Distance <= 19)
                    //    {
                    //        var last = solution[solution.Count - 1];
                    //        solution.RemoveAt(solution.Count - 1);
                    //        solution.Insert(0, last);
                    //    }

                    //var idx = CalcRing(solution.Select(x => x.Distance).ToArray());
                    //while (idx-- > 0)
                    //{
                    //    var fst = solution[0];
                    //    solution.RemoveAt(0);
                    //    solution.Add(fst);
                    //}

                    foreach (var id in new[] { solution[0].From }.Concat(solution.Select(x => x.To)))
                    {
                        var scored = Wave.CreatePaths(screen, player[0], player[1], "", ":", true, 0, 0, new[] { waves[id].Coord }, Move.Moves2).FirstOrDefault();
                        if (scored != null)
                        {
                            var path = scored.GetPath().Reverse().Select(x => x.Move).ToArray();
                            if (KillerFallingAI.ValidatePath(path, world0.Clone(), 3, false, "CollectorAI"))
                            {
                                _path = new Queue <Move>(path);
                                return(_path.Dequeue().Control);
                            }
                        }
                    }
                }
            }

            if (dict.Count != 0)
            {
                var toId   = solution != null && solution.Count != 0 ? solution[0].To : dict.Values.Max();
                var to     = waves[toId].Coord;
                var scored = waves[0].Scored.FirstOrDefault(item => item.Y == to[0] && item.X == to[1]);
                if (scored != null)
                {
                    if (scored.StepsCount >= 20)
                    {
                        var best = waves[0].Scored.OrderBy(x => x.StepsCount).First();
                        if (best.StepsCount < 20)
                        {
                            scored = best;
                        }
                    }
                    var path = scored.GetPath().Reverse().Select(x => x.Move).ToArray();
                    if (KillerFallingAI.ValidatePath(path, world0.Clone(), 3, false, "CollectorAI"))
                    {
                        _path = new Queue <Move>(path);
                        return(_path.Dequeue().Control);
                    }
                }
            }

            {
                foreach (var scored in Wave.CreatePathsFull(world0, player[0], player[1], "*", ":", true, 2, false, 0, null))
                {
                    var path  = scored.GetPath().Reverse().Take(3).ToArray();
                    var moves = path.Select(x => x.Move).ToArray();
                    var last  = (Step2)path.Last();
                    if (KillerFallingAI.ValidatePath(moves, last.World.Clone(), 3, false, "CollectorAI"))
                    {
                        _path = new Queue <Move>(moves);
                        return(_path.Dequeue().Control);
                    }
                }
            }

            return(Move.None.Control);
        }
Exemple #2
0
        public char play(string[] screen, World world0)
        {
            if (world0.frame < 0)
            {
                return(' ');
            }

            var pos = screen.FindItem(Butterfly.Chars).ToArray();

            foreach (var p in pos)
            {
                _bpos.Enqueue(p);
            }
            while (_bpos.Count > 2 * pos.Length)
            {
                _bpos.Dequeue();
            }
            //_bpos = new Queue<int[]>(pos);

            var butterfliesCount = pos.Count();
            var killed           = world0.frame != 0 && _prevButterfliesCount != butterfliesCount;

            _prevButterfliesCount = butterfliesCount;
            if (killed)
            {
                _lastKillFrame = world0.frame;
            }

            if (world0.frame < 10)
            {
                return(' ');
            }
            if (pos.Length == 0 && screen.FindItem("1234").Count() == 0)
            {
                //var path = Method.Process(screen, world0).OrderBy(x => x.From).ToArray();
                var w    = new System.Diagnostics.Stopwatch();
                var path = TSPSolver.Process(screen, world0).ToArray();
                w.Stop();
                log("path len: {0}, dist: {1}, breaks: {2}, time: {3} ms",
                    path.Length, path.Sum(x => x.Distance), path.Count(x => x.Distance > 20), w.ElapsedMilliseconds);
                return('q');
            }

            var t0 = Timings.Start(0);

            if (_killPath.Count == 0 || _scanForKills)
            {
                var path = FindKillPath(screen, world0);
                if (path != null && (_killPath.Count == 0 || path.Length < _killPath.Count))// || !_isKillPath))
                {
                    log("kill path found: {0}", path.Length);
                    _killPath   = new Queue <Move>(path);
                    _isKillPath = true;
                    _time2kill  = Math.Max(3 * path.Length, _time2kill);
                    //_scanForKills = false;
                }
            }
            t0.Stop();

            if (_killPath.Count != 0)
            {
                log("{0}: {1} / {2} [{3}]", world0.frame, _killPath.Peek(), _killPath.Count, world0.get_hash());
                return(_killPath.Dequeue().Control);
            }
            _scanForKills = true;
            _num++;
            _isKillPath = false;

            if (FindOpenPath(world0) || FindEmptyPath(world0))
            {
                log("{0}: {1} / {2} [{3}]", world0.frame, _killPath.Peek(), _killPath.Count, world0.get_hash());
                return(_killPath.Dequeue().Control);
            }
            log("{0}: {1} [{2}]", world0.frame, Move.None, world0.get_hash());
            return(Move.None.Control);
        }