diff --git a/escapetest.sh b/escapetest.sh new file mode 100755 index 0000000..4f07b36 --- /dev/null +++ b/escapetest.sh @@ -0,0 +1,4 @@ +while true +do +docker run --rm -p 63187:63187 mediaeng/bots escape +done diff --git a/src/EscapeBot.java b/src/EscapeBot.java index df611ff..ab26d5c 100644 --- a/src/EscapeBot.java +++ b/src/EscapeBot.java @@ -1,7 +1,11 @@ +import java.util.LinkedList; +import java.util.Queue; + public class EscapeBot extends Bot { - boolean offByOne = true; - int currentStepCount = 0; - int steps = 0; + protected final static String obstacles = "~#X*"; + protected boolean offByOne = true; + protected int currentStepCount = 0; + protected int steps = 0; public static void main(String[] args) { Bot bot = new EscapeBot(args); @@ -15,27 +19,87 @@ public class EscapeBot extends Bot { @Override protected char nextMove(View view) { System.out.println(); - if (view.data.contains("o")) { - int index = view.data.indexOf('o'); - if (index < view.width * 2 && !(index > view.width * 3)) { - return '^'; - } else if (index % 5 < 2) { - return '<'; - } else if (index % 5 > 2) { - return '>'; - } - return ' '; - } else if (steps == 0) { - currentStepCount += 1; + String data = view.data + .replace('^', '*') + .replace('<', '*') + .replace('>', '*') + .replace('v', '*'); + char[][] grid = dataToGrid(data, view.width); + + if (data.contains("o")) { + return breadthFirstSearch(grid); + } else { + return walkAround(grid); + } + } + + protected char[][] dataToGrid(String data, int size) { + char[][] grid = new char[size][size]; + for (int i = 0; i < data.length(); i++) { + grid[i % size][i / size] = data.charAt(i); + } + return grid; + } + + protected char walkAround(char[][] grid) { + if (steps == 0) { + currentStepCount++; if (offByOne) { - currentStepCount += 1; + currentStepCount++; } offByOne = !offByOne; steps = currentStepCount; return '>'; } else { - steps -= 1; + steps--; + return safeMove(grid); + } + } + + protected char safeMove(char[][] grid) { + int size = grid.length; + if (grid[size / 2][size / 2 - 1] == '*') { + return '<'; + } else { return '^'; } } + + protected char breadthFirstSearch(char[][] grid) { + int size = grid.length; + int start = size / 2; + + boolean[][] visited = new boolean[size][size]; + Queue queue = new LinkedList<>(); + + int[][] directions = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}}; + char[] commands = {'^', '>', '>', '<'}; + for (int i = 0; i < 4; i++) { + queue.add(new Move(start + directions[i][0], start + directions[i][1], commands[i])); + } + + queue.add(new Move(start, start - 1, '^')); + queue.add(new Move(start, start + 1, '>')); + queue.add(new Move(start + 1, start, '>')); + queue.add(new Move(start - 1, start, '<')); + + while (!queue.isEmpty()) { + Move move = queue.poll(); + if (move.x < 0 || move.x >= size || move.y < 0 || move.y >= size || visited[move.x][move.y]) continue; + visited[move.x][move.y] = true; + if (obstacles.contains("" + grid[move.x][move.y])) continue; + if (grid[move.x][move.y] == 'o') return move.direction; + + for (int[] direction : directions) { + queue.add(new Move(move.x + direction[0], move.y + direction[1], move.direction)); + } + } + + System.err.println("No path found"); + return safeMove(grid); + } + + protected record Move(int x, int y, char direction) { + } + }