public static Step[] CheckCanMove(World world0, int y, int x, int depth, string[][] screens = null) { for (var limit = screens != null ? 1 : 1; limit <= 3; limit++) { var push = false; foreach (var eatItem in new[] { ":", ":*", ":*O" }) { var wave = new WaveOld(world0.Clone(), "", eatItem, null); wave.Update(y, x, push, 0, int.MaxValue, depth, screens); foreach (var step in wave.Scored) { var path = step.GetPath().Reverse().ToArray(); var world = world0.Clone(); foreach (var st in path) { world.control(st.Move.Dir); world.update(); } var dest = path.Last(); if (world.is_playable() && world.player_x == dest.X && world.player_y == dest.Y) { return(path); } } push = true; } } return(null); }
private WaveOld CloneAtScore(int index) { var path = GetSteps(_scored[index]).Reverse().ToArray(); var world = _world.Clone(); var killed = 0; foreach (var step in path) { var butterflies_killed = world.butterflies_killed; world.control(step.Move.Dir); world.update(); if (killed == 0 && butterflies_killed != world.butterflies_killed) { killed = step.StepsCount; } } if (killed != 0) { //var } if (!world.is_playable()) { return(null); } //var scr = world.render(false, false).ToArray(); // ?????????????????? //var wave = new Wave(world.Clone(), _huntItem, _eatItem, _transform); var wave = new WaveOld(_world.Clone(), _huntItem, _eatItem, _transform); //wave._depth = _depth; wave._initial = _initial; wave._parent = _parent; wave._scored.AddRange(_scored); wave._collected = new HashSet <Tuple <int, int> >(_collected); wave._killed = _parent != null && _parent._killed != 0 ? _parent._killed : killed != 0 ? wave._depth : 0; wave._streak = (_parent != null ? _parent._streak : 0) + (path.Length <= 18 ? 1 : 0); return(wave); }
public WaveOld(WaveOld parent, Step initial) { _parent = parent; _depth = _parent._depth + 1; _initial = initial; _screen = parent._screen.ToArray(); _world = parent._world; _killed = parent._killed; _streak = parent._streak; _transform = parent._transform; //_height = parent._height; //_width = parent._width; _huntItem = _parent._huntItem; _eatItem = _parent._eatItem; //_steps = new Step[_world.height, _world.width]; foreach (var item in _parent._collected) { _collected.Add(item); } _collected.Add(Tuple.Create(_initial.Y, _initial.X)); }
public static Path[] Process(string[] screen, World world) { var dict = new Dictionary <Tuple <int, int>, int>(); for (var y = 0; y < screen.Length; y++) { for (var x = 0; x < screen[y].Length; x++) { if (screen[y][x] == '*') { dict[Tuple.Create(y, x)] = dict.Count; } } } var matrix = new int[dict.Count, dict.Count]; for (var i = 0; i < dict.Count; i++) { for (var j = 0; j < dict.Count; j++) { matrix[i, j] = -1; } } foreach (var item in dict) { var src = item.Value; var wave = new WaveOld(world.Clone(), "*", ":*", null); wave.Update(item.Key.Item1, item.Key.Item2, true, 0); foreach (var scored in wave.Scored) { var coord = Tuple.Create(scored.Y, scored.X); var dst = dict[coord]; matrix[src, dst] = scored.StepsCount; } } return(Process(matrix).ToArray()); }
public static WaveOld[] Process(int y0, int x0, World world, int depth, int width, string huntItem, string eatItem, Func <string[], string[]> transform, bool push, int limit) { var start = new WaveOld(world, huntItem, eatItem, transform); start.Update(y0, x0, push, limit, width); var list = new List <WaveOld>(); list.Add(start); var index = 0; for (var iteration = 0; iteration < depth; iteration++) { var sz = list.Count; if (sz > 1000) { break; } for (var i = index; i < sz; i++) { var wave = list[i]; var range = width > 0 ? Enumerable.Range(0, wave._scored.Count).Take(width) : Enumerable.Range(0, wave._scored.Count).Skip(-width).Take(-width); foreach (var pos in range) { var cloned = wave.CloneAtScore(pos); if (cloned != null) { //var child = new Wave(cloned, wave._scored[pos]); var child = cloned; child._depth++; child._scored.Clear(); child._initial = wave._scored[pos]; // StepCount != 0 !!! //child._initial = new Step(wave._scored[pos].Y, wave._scored[pos].X); child._collected.Add(Tuple.Create(child._initial.Y, child._initial.X)); child.Update(wave._scored[pos].Y, wave._scored[pos].X, push, limit); list.Add(child); } } } index = sz; } foreach (var wave in list) { wave.UpdateStepsCount(); } //if (transform == null && list.Count != 0) System.Diagnostics.Trace.WriteLine("max(depth): " + list.Max(x => x._depth)); //return list.OrderBy(x => -x._world.butterflies_killed).ThenBy(x => -x._world.score).ToArray(); //return list.OrderBy(x => x.StepsCount).ToArray(); //return list.OrderByDescending(x => x._depth).ThenByDescending(x => x._killed).ThenByDescending(x => (float)x.StepsCount / x._depth).ToArray(); // best ??? //return list.OrderByDescending(x => x._killed).ThenByDescending(x => x._depth).ThenByDescending(x => (float)x.StepsCount / x._depth).ToArray(); return(list.OrderBy(x => - x._streak).ThenBy(x => x._killed != 0 && x._killed <= -x._streak ? x._killed : int.MaxValue).ThenBy(x => (float)-x._depth / x.StepsCount).ThenBy(x => - x._depth).ToArray()); //return list.OrderBy(x => x._killed > 0 && x._killed < 7 ? x._killed : int.MaxValue).ThenBy(x => (float)-x._depth / x.StepsCount).ThenBy(x => -x._depth).ToArray(); //return list.OrderBy(x => (float)-x._depth / x.StepsCount).ThenBy(x => -x._depth).ToArray(); }
public char play(string[] screen, World world0) { if (_prevScore != world0.score) { _lastScoredFrame = _frame; _divider = 1; _prevScore = world0.score; } _frame++; if (_frame > 600) { _killer = null; if (_frame - _lastScoredFrame > 40) { _divider = Math.Max(_divider, _rnd.Next(2, 15)); } } else { _lastScoredFrame = _frame; } if (screen[screen.Length - 1][0] != '#') { screen = screen.Take(screen.Length - 1).ToArray(); } var diamondsLeft = screen.Sum(row => row.Count(z => z == '*')); var butterfliesLeft = screen.Sum(row => row.Count(z => @"/|\-".Contains(z))); if (diamondsLeft == 0 && butterfliesLeft == 0) { return('q'); } if (_killer != null) { _diamondsCollected = world0.diamonds_collected; var kkk = _killer.play(screen, world0); if (kkk == 'q') { _killer = null; } else { return(kkk); } } //if (_collector != null && world0.diamonds_collected == _diamondsCollected) //var c = _collector.play(screen, world0); //if (c != Move.None.Control) return c; return(_collector2.play(screen, world0)); //return _collector.play(screen, world0); //var pos = SimpleAI.find_player(screen); var x0 = world0.player_x; //pos[0]; var y0 = world0.player_y; //pos[1]; var h = screen.Length; var w = screen[0].Length; //if (_killPath.Count == 0 && _scanForKills) //{ // var path = KillerFallingAI.FindKillPath(screen, world0); // if (path != null && (path.Length <= 5/*5*/ || diamondsLeft <= 3 || world0.streak <= 3/*0*/)) // _killPath = new Queue<Move>(path); //} //if (_killPath.Count != 0) // return _killPath.Dequeue().Control; if (_scorePath.Count != 0 && _scorePath.Count % _divider != 0) // 1-cycled, %2- no { return(_scorePath.Dequeue().Control); } //if (false && world0.streak_expiry >= 20 && butterfliesLeft != 0 && _scanForRelease) //{ // var wave = new Wave(world0.Clone(), Butterfly.Chars, "", null); // wave.Update(y0, x0, false, 0); // if (wave.Width != butterfliesLeft) // { // var wave2 = new Wave(world0.Clone(), Butterfly.Chars, ":", scr => // { // foreach (var step in wave.Scored) // scr = scr.SetAt(step.Y, step.X, ' '); // //remove reached butterflies // return scr; // }); // wave2.Update(y0, x0, false, 0); // foreach (var scoreStep in wave2.Scored) // { // var path = wave2.GetSteps(scoreStep).Skip(1).Reverse().ToArray(); // var world = world0.Clone(); // foreach (var step in path) // { // world.control(step.Move.Dir); // world.update(); // } // if (world.is_playable() && path.Length > 0) // return path[0].Move.Control; // } // } // else // _scanForRelease = false; //} var depth = 1; var width = 10; var run = 0; foreach (var huntItem in new[] { "*" }) //, "@", "@" }) { Func <string[], string[]> transform = null; //if (run == 0) transform = MarkStones2Fall; if (run == 1) { transform = MarkDirtUpperButterfly; // ??? } //if (run == 2) transform = MarkDirtRowButterfly; if (run == 2) { transform = MarkDirt2Eat; } if (run == 3) { transform = MarkButterfly; } // !!!!!!!!!! //var wavesAll = new List<Wave>(); for (var limit = 1; limit <= 4; limit++) { //var waves = Wave.Process(y0, x0, world0.Clone(), depth, width, huntItem, ":*", transform, run == 0, limit); var wave = new WaveOld(world0.Clone(), huntItem, ":*", null); wave.Update(y0, x0, run == 0, limit); //wavesAll.AddRange(waves); //wavesAll = Wave.Sort(wavesAll).ToList(); foreach (var score in wave.Scored) { var path = score.GetPath().Reverse().ToArray(); if (path.Length > 0) { var world = world0.Clone(); var ok = true; var len = 0; var breakN = 2; for (var n = 0; n < path.Length + 0 && ok /*&& n < path.Length*/; n++) { if (n < path.Length) { world.control(path[n].Move.Dir); len++; } world.update(); ok = world.is_playable() && world.player_can_move();// && CanMove(screen, h, w); if (n < path.Length && path[n].Scored && --breakN <= 0) { break; } } //world.update(); // ????? чуть хуже //ok = world.is_playable() && world.player.can_move(); //var npos = FindItem(world.render(), h, w, "AX").First(); ok = ok && len != 0 && //world.player.point != null && WaveOld.CheckCanMove(world, world.player_y, world.player_x, 6) != null; //ok = len != 0 && ok && _killer.CheckPlayable(screen, world0, 3); if (ok || (butterfliesLeft == 0 && diamondsLeft == 1)) { _scorePath = new Queue <Move>(path.Take(len).Select(x => x.Move)); // get full path to score !!! + n-alive epsilon //scores.Add(Tuple.Create(path, world.score)); //return path[0].Move.Control; _scanForKills = !wave.Killed; return(_scorePath.Dequeue().Control); } } } } //width = -width; run++; } _scanForKills = true; var somePath = WaveOld.CheckCanMove(world0, y0, x0, 5); if (somePath != null) { _scorePath = new Queue <Move>(somePath.Select(x => x.Move)); return(_scorePath.Dequeue().Control); //return somePath[0].Move.Control; } //var moves = (Move[])Move.All.Clone(); //for (var i = 0; i < moves.Length; i++) //{ // var j = _rnd.Next(moves.Length); // var tmp = moves[i]; // moves[i] = moves[j]; // moves[j] = tmp; // foreach (var move in moves) // { // var world = world0.Clone();// Generate.from_ascii(screen); // world.control(move.Dir); // world.update(); // //if (world.is_playable() && _killer.CheckPlayable(screen, world, 3)) // if (world.is_playable() && Wave.CheckCanMove(world, y0, x0, 5)) // return move.Control; // } //} return(' '); }
public static IEnumerable <Method.Path> Process(string[] screen, World world0) { var dict = new Dictionary <Tuple <int, int>, int>(); for (var y = 0; y < screen.Length; y++) { for (var x = 0; x < screen[y].Length; x++) { if (screen[y][x] == '*') { dict[Tuple.Create(y, x)] = dict.Count; } } } var matrix = Enumerable.Range(0, dict.Count) .Select(_ => Enumerable.Range(0, dict.Count).Select(__ => double.PositiveInfinity).ToArray()) .ToArray(); var isolated = new HashSet <int>(); foreach (var item in dict.ToArray()) { var src = item.Value; var wave = new WaveOld(world0.Clone(), "*", ":*", null); wave.Update(item.Key.Item1, item.Key.Item2, true, 0); foreach (var scored in wave.Scored) { var coord = Tuple.Create(scored.Y, scored.X); if (dict.ContainsKey(coord)) { var dst = dict[coord]; var val = scored.StepsCount < 20 ? 20 : 10000; matrix[src][dst] = val; } } if (wave.Scored.Length == 0) { dict.Remove(item.Key); isolated.Add(src); } } if (isolated.Count != 0) { matrix = matrix.Where((x, i) => !isolated.Contains(i)) .Select(z => z.Where((x, i) => !isolated.Contains(i)).ToArray()) .ToArray(); } //for (var i = 0; i < matrix.Length; i++) // System.Diagnostics.Trace.WriteLine("[" + i + "] " + string.Join(" ", matrix[i])); var obj = new TSPSolver(); var step = obj.solve(dict.Count, cloneFull(matrix)); var first = obj.route.Keys.Min(); var prev = first; var next = 0; var found = false; while ((next = obj.getNextRoute(prev, out found)) != first && found) { yield return(new Method.Path { From = prev, To = next, Distance = (int)matrix[prev][next] }); prev = next; } if (found) { yield return new Method.Path { From = prev, To = next, Distance = (int)matrix[prev][next] } } ; }