static MovementScore FindMovementScoreExplore(MapStates[,] map, int startx, int starty, Bot[] bots, int endx, int endy) { int[] directionX = new int[] { 0, -1, 0, 1, 0 }; int[] directionY = new int[] { 0, 0, -1, 0, 1 }; int width = map.GetLength(0); int height = map.GetLength(1); int[,] distances = new int[width, height]; MovementScore score = new MovementScore(); score.certainDeath = 0; score.closestPoints = int.MaxValue; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { distances[x, y] = -1; } } Queue <Point> queue = new Queue <Point>(); Queue <Point> newQueue = new Queue <Point>(); if (map[startx, starty] != MapStates.Wall) { queue.Enqueue(new Point { X = startx, Y = starty }); } for (int step = 1; queue.Count > 0; step++) { score.certainDeath = step; while (queue.Count > 0) { Point p = queue.Dequeue(); if (distances[p.X, p.Y] < 0) { bool death = false; foreach (Bot bot in bots) { if (bot.Nostradamus.IsThere(p.X, p.Y, step)) { death = true; break; } } if (!death) { if (map[p.X, p.Y] != MapStates.Visited && score.closestPoints > step) { score.closestPoints = step; } distances[p.X, p.Y] = step; for (int i = 0; i < directionX.Length; i++) { int newx = p.X + directionX[i]; int newy = p.Y + directionY[i]; if (newx < 0) { newx += width; } if (newx >= width) { newx -= width; } if (newy < 0) { newy += height; } if (newy >= height) { newy -= height; } if (distances[newx, newy] == -1 && map[newx, newy] != MapStates.Wall) { newQueue.Enqueue(new Point { X = newx, Y = newy }); distances[newx, newy] = -2; } } } } } var q = queue; queue = newQueue; newQueue = q; } if (score.certainDeath > 0) { int[,] d = FindDistancesMap(map, startx, starty); score.closestPoints = d[endx, endy]; } return(score); }
public Movement Step(Point[] playerPositions, bool wallLeft, bool wallUp, bool wallRight, bool wallDown) { Point me = playerPositions[playerPositions.Length - 1]; for (int i = 0; i < playerPositions.Length; i++) { if (i < bots.Length) { int x = playerPositions[i].X, y = playerPositions[i].Y; bots[i].AddPoint(map, x, y); if (map[x, y] == MapStates.Unknown) { map[x, y] = i + MapStates.Visited2; } } } map[me.X, me.Y] = MapStates.Visited; frame++; if (wallUp) { map[me.X, me.Y - 1] = MapStates.Wall; } if (wallDown) { map[me.X, me.Y + 1] = MapStates.Wall; } if (wallLeft) { map[me.X - 1, me.Y] = MapStates.Wall; } if (wallRight) { map[me.X + 1, me.Y] = MapStates.Wall; } // Dump some stats int width = map.GetLength(0); int height = map.GetLength(1); int visited = 0; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (map[x, y] == MapStates.Visited) { visited++; } } } DumpLine("Position: ({0}, {1})", me.X, me.Y); DumpLine("Visited: {0}", visited); // Decide where to go int[] directionX = new int[] { 0, -1, 0, 1, 0 }; int[] directionY = new int[] { 0, 0, -1, 0, 1 }; Movement[] direction = new Movement[] { Movement.Stand, Movement.Left, Movement.Up, Movement.Right, Movement.Down }; Movement movement = Movement.Stand; MovementScore bestMoveScore = new MovementScore(); bool testCloseDeath = !IsOnlyUnknownConnected(map, me.X, me.Y); DumpLine("TCD: {0}", testCloseDeath); bestMoveScore.certainDeath = 0; bestMoveScore.closestPoints = int.MaxValue; for (int i = 0; i < directionX.Length; i++) { int newX = directionX[i] + me.X; int newY = directionY[i] + me.Y; if (newX < 0) { newX += width; } if (newX >= width) { newX -= width; } if (newY < 0) { newY += height; } if (newY >= height) { newY -= height; } MovementScore score; if (!explore) { score = FindMovementScore(map, newX, newY, bots); } else { score = FindMovementScoreExplore(map, newX, newY, bots, explorex, explorey); if (direction[i] == Movement.Stand) { continue; } } Dump("{0}: {1} [{2}, {3}]", direction[i], map[newX, newY], score.certainDeath, score.closestPoints); bool s1e = score.certainDeath < 13 && testCloseDeath; bool s2e = bestMoveScore.certainDeath < 13 && testCloseDeath; if (s1e && !s2e) { DumpLine(); continue; } bool betterScore = !s1e && s2e; if (!betterScore && s1e && s2e) { betterScore = score.certainDeath > bestMoveScore.certainDeath; } if (betterScore || (score.closestPoints < bestMoveScore.closestPoints || (score.closestPoints == bestMoveScore.closestPoints && score.certainDeath > bestMoveScore.certainDeath))) { movement = direction[i]; bestMoveScore = score; Dump(" *"); } DumpLine(); } foreach (Bot bot in bots) { DumpLine("{0} {1} {2} {3}", bot.IsRepeating, bot.RepeatStart, bot.PointPosition, bot.Points.Count); } for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (x == me.X && y == me.Y) { Dump("X "); } else { int foundIndex = -1; for (int i = 0; i < bots.Length; i++) { if (bots[i].Position.X == x && bots[i].Position.Y == y) { foundIndex = i; break; } } if (foundIndex != -1) { Dump("{0} ", (char)('A' + foundIndex)); } else if (map[x, y] == MapStates.Wall) { Dump("# "); } else if (map[x, y] == MapStates.Unknown) { Dump(" "); } else { Dump("{0} ", (int)map[x, y]); } } } DumpLine(); } if (fullDumpEnabled && frame == fullDumpFrame) { Console.Error.WriteLine("width: {0}, height = {1}", width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (map[x, y] == MapStates.Wall) { Console.Error.Write("#"); } else if (map[x, y] == MapStates.Unknown) { Console.Error.Write(" "); } else { Console.Error.Write("."); } } Console.Error.WriteLine(); } foreach (Bot bot in bots) { foreach (Point p in bot.Path) { Console.Error.Write("{0}{1}", (char)('A' + p.X), (char)('A' + p.Y)); } Console.Error.WriteLine(); } } return(movement); }
static void Test1() { const string mapInput = @" B A C D # X 1 # # "; Bot[] bots; Point me; MapStates[,] map = ParseMap(mapInput, out me, out bots); int width = map.GetLength(0); int height = map.GetLength(1); PrintMap(map, me.X, me.Y, bots); for (int i = 0; i < bots.Length; i++) { if (bots[i].Nostradamus is PesimisticNostradamus) { Console.WriteLine((char)(i + 'A')); PesimisticNostradamus pn = bots[i].Nostradamus as PesimisticNostradamus; int[,] distances = pn.Distances; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (distances[x, y] == -1) { Console.Write(" # "); } else { Console.Write("{0,2} ", distances[x, y]); } } Console.WriteLine(); } Console.WriteLine(); } } MovementScore score = Game.FindMovementScore(map, me.X + 1, me.Y, bots); }