|
|
|
|
|
|
|
|
|
|
|
import java.util.Random; |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* RumbleBot. |
|
|
* RumbleBot. |
|
|
* Der Rover ist auch mit einem Geschütz ausgestattet, dass nur in Fahrrichtung feuern kann. |
|
|
* Der Rover ist auch mit einem Geschütz ausgestattet, dass nur in Fahrrichtung feuern kann. |
|
|
|
|
|
|
|
|
* Der Rover ist beim ersten Treffer zerstört. Wer überlebt am längsten? |
|
|
* Der Rover ist beim ersten Treffer zerstört. Wer überlebt am längsten? |
|
|
* docker run --rm -p 63187:63187 mediaeng/bots rumble |
|
|
* docker run --rm -p 63187:63187 mediaeng/bots rumble |
|
|
*/ |
|
|
*/ |
|
|
public class RumbleBot extends Bot |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
public class RumbleBot extends Bot{ |
|
|
private String moves = ""; |
|
|
private String moves = ""; |
|
|
private boolean frontIsBlocked, backIsBlocked, leftIsBlocked, rightIsBlocked, trapped; |
|
|
|
|
|
public static void main(String[] args) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
private int spiralFactor = 1; |
|
|
|
|
|
private char spiralDirection = '>'; |
|
|
|
|
|
private boolean goesForward = true; |
|
|
|
|
|
private boolean frontIsBlocked, leftIsBlocked, rightIsBlocked; |
|
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) { |
|
|
Bot rumbleBot = new RumbleBot(args); |
|
|
Bot rumbleBot = new RumbleBot(args); |
|
|
rumbleBot.run(); |
|
|
rumbleBot.run(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
super(args); |
|
|
super(args); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//@TODO: add nextMove() logic |
|
|
|
|
|
protected char nextMove(View view) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
protected char nextMove(View view){ |
|
|
|
|
|
char nextMove = checkForEnemy(view) ? takeAimAndShoot(view) : walkByColumns(view); |
|
|
|
|
|
|
|
|
checkBarriers(view); |
|
|
checkBarriers(view); |
|
|
if (inDanger(view)) |
|
|
|
|
|
{ |
|
|
|
|
|
//run away |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nextMove = checkMove(nextMove); |
|
|
|
|
|
|
|
|
|
|
|
return nextMove; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private char takeAimAndShoot(View view) { |
|
|
|
|
|
resetMovesSequence(); |
|
|
|
|
|
|
|
|
|
|
|
int[] frontIndexes = getFrontIndexes(view); |
|
|
|
|
|
int[] leftIndexes = getLeftIndexes(view); |
|
|
|
|
|
int[] rightIndexes = getRightIndexes(view); |
|
|
|
|
|
|
|
|
|
|
|
char[] enemies = {'^', '<', '>', 'v'}; |
|
|
|
|
|
|
|
|
|
|
|
for (int index : frontIndexes) { |
|
|
|
|
|
for (char enemy : enemies) { |
|
|
|
|
|
if (view.data.charAt(index) == enemy) return 'f'; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
if(moves.isEmpty()) |
|
|
|
|
|
{ |
|
|
|
|
|
moves += ' '; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int index : leftIndexes) { |
|
|
|
|
|
for (char enemy : enemies) { |
|
|
|
|
|
if (view.data.charAt(index) == '>') return 'v'; |
|
|
|
|
|
else if (view.data.charAt(index) == enemy) return '<'; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
char nextMove = moves.charAt(0); |
|
|
|
|
|
moves = moves.substring(1); |
|
|
|
|
|
return nextMove; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int index : rightIndexes) { |
|
|
|
|
|
for (char enemy : enemies) { |
|
|
|
|
|
if (view.data.charAt(index) == '<') return 'v'; |
|
|
|
|
|
else if (view.data.charAt(index) == enemy) return '>'; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return '^'; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private int[] getLeftIndexes(View view) { |
|
|
|
|
|
int center = view.width / 2; |
|
|
|
|
|
int[] leftIndexes = new int[center]; |
|
|
|
|
|
int index = 0; |
|
|
|
|
|
|
|
|
//checks if we are in the line of fire of other players. returns true if that is the case. bot should try it's best to move away |
|
|
|
|
|
private boolean inDanger(View ciew) |
|
|
|
|
|
{ |
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
for (int col = 0; col < center; col++) { |
|
|
|
|
|
leftIndexes[index++] = getCharIndexFromCoordinates(view.width, col, center); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return leftIndexes; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private int[] getRightIndexes(View view) { |
|
|
|
|
|
int center = view.width / 2; |
|
|
|
|
|
int[] rightIndexes = new int[center]; |
|
|
|
|
|
int index = 0; |
|
|
|
|
|
|
|
|
|
|
|
for (int col = center + 1; col < view.width; col++) { |
|
|
|
|
|
rightIndexes[index++] = getCharIndexFromCoordinates(view.width, col, center); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return rightIndexes; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private int[] getFrontIndexes(View view) { |
|
|
|
|
|
int center = view.width / 2; |
|
|
|
|
|
int[] frontIndexes = new int[center]; |
|
|
|
|
|
int index = 0; |
|
|
|
|
|
|
|
|
|
|
|
for (int row = 0; row < center; row++) { |
|
|
|
|
|
frontIndexes[index++] = getCharIndexFromCoordinates(view.width, center, row); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return frontIndexes; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//returns the index number in the string at the specified "coordinate" |
|
|
|
|
|
//x is left to right, y is top to bottom |
|
|
|
|
|
private int IndexAt(int width, int x, int y) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
private int getCharIndexFromCoordinates(int width, int x, int y) { |
|
|
return width * y + x; |
|
|
return width * y + x; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void resetMovesSequence() { |
|
|
|
|
|
moves = ""; |
|
|
|
|
|
spiralFactor = 1; |
|
|
|
|
|
spiralDirection = (spiralDirection == '>') ? '<' : '>'; |
|
|
|
|
|
goesForward = true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean checkForEnemy(View view) { |
|
|
|
|
|
char[] enemies = {'^', '<', '>', 'v'}; |
|
|
|
|
|
|
|
|
|
|
|
boolean enemyDetected = false; |
|
|
|
|
|
|
|
|
|
|
|
for (char enemy : enemies) { |
|
|
|
|
|
if (view.data.contains(Character.toString(enemy))) { |
|
|
|
|
|
enemyDetected = true; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return enemyDetected; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
//sets several variables based on the bot's current position that help with navigating |
|
|
|
|
|
private void checkBarriers(View view) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
private void checkBarriers(View view) { |
|
|
int centerCoordinates = view.width / 2; |
|
|
int centerCoordinates = view.width / 2; |
|
|
int centerIndex = IndexAt(view.width, centerCoordinates, centerCoordinates); |
|
|
|
|
|
|
|
|
int centerIndex = getCharIndexFromCoordinates(view.width, centerCoordinates, centerCoordinates); |
|
|
|
|
|
|
|
|
int frontIndex = IndexAt(view.width, centerCoordinates, centerCoordinates - 1); |
|
|
|
|
|
int backIndex = IndexAt(view.width, centerCoordinates, centerCoordinates + 1); |
|
|
|
|
|
|
|
|
int frontIndex = getCharIndexFromCoordinates(view.width, centerCoordinates, centerCoordinates - 1); |
|
|
int leftIndex = centerIndex - 1; |
|
|
int leftIndex = centerIndex - 1; |
|
|
int rightIndex = centerIndex + 1; |
|
|
int rightIndex = centerIndex + 1; |
|
|
|
|
|
|
|
|
|
|
|
char[] obstacles = {'#', '~', 'X'}; |
|
|
|
|
|
|
|
|
|
|
|
frontIsBlocked = containsChar(obstacles, view.data.charAt(frontIndex)); |
|
|
|
|
|
leftIsBlocked = containsChar(obstacles, view.data.charAt(leftIndex)); |
|
|
|
|
|
rightIsBlocked = containsChar(obstacles, view.data.charAt(rightIndex)); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private boolean containsChar(char[] array, char target) { |
|
|
|
|
|
for (char c : array) { |
|
|
|
|
|
if (c == target) { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private char checkMove(char move) { |
|
|
|
|
|
if (frontIsBlocked) { |
|
|
|
|
|
resetMovesSequence(); |
|
|
|
|
|
if (leftIsBlocked) move = '>'; |
|
|
|
|
|
else if (rightIsBlocked) move = '<'; |
|
|
|
|
|
} |
|
|
|
|
|
return move; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
frontIsBlocked = view.data.charAt(frontIndex) == '~' || view.data.charAt(frontIndex) == '#' || view.data.charAt(frontIndex) == 'X' || view.data.charAt(frontIndex) == '^' || view.data.charAt(frontIndex) == '<' || view.data.charAt(frontIndex) == '>' || view.data.charAt(frontIndex) == 'v'; |
|
|
|
|
|
backIsBlocked = view.data.charAt(backIndex) == '~' || view.data.charAt(frontIndex) == '#' || view.data.charAt(frontIndex) == 'X' || view.data.charAt(frontIndex) == '^' || view.data.charAt(frontIndex) == '<' || view.data.charAt(frontIndex) == '>' || view.data.charAt(frontIndex) == 'v'; |
|
|
|
|
|
leftIsBlocked = view.data.charAt(leftIndex) == '~' || view.data.charAt(frontIndex) == '#' || view.data.charAt(frontIndex) == 'X' || view.data.charAt(frontIndex) == '^' || view.data.charAt(frontIndex) == '<' || view.data.charAt(frontIndex) == '>' || view.data.charAt(frontIndex) == 'v'; |
|
|
|
|
|
rightIsBlocked = view.data.charAt(rightIndex) == '~' || view.data.charAt(frontIndex) == '#' || view.data.charAt(frontIndex) == 'X' || view.data.charAt(frontIndex) == '^' || view.data.charAt(frontIndex) == '<' || view.data.charAt(frontIndex) == '>' || view.data.charAt(frontIndex) == 'v'; |
|
|
|
|
|
trapped = frontIsBlocked && backIsBlocked && leftIsBlocked && rightIsBlocked; |
|
|
|
|
|
|
|
|
private char walkBySpiral(View view) { |
|
|
|
|
|
if (moves.isEmpty()) { |
|
|
|
|
|
spiralFactor++; |
|
|
|
|
|
moves += "^".repeat(view.width * spiralFactor) + spiralDirection + "^".repeat(view.width * spiralFactor) + spiralDirection; |
|
|
|
|
|
} |
|
|
|
|
|
char nextMove = moves.charAt(0); |
|
|
|
|
|
moves = moves.substring(1); |
|
|
|
|
|
return nextMove; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private char walkByColumns(View view) { |
|
|
|
|
|
if (moves.isEmpty()) { |
|
|
|
|
|
int min = 10; |
|
|
|
|
|
int max = 100; |
|
|
|
|
|
|
|
|
|
|
|
Random random = new Random(); |
|
|
|
|
|
int steps = random.nextInt((max - min) + 1) + min; |
|
|
|
|
|
//int steps = 32 - view.width; |
|
|
|
|
|
|
|
|
|
|
|
moves = "^".repeat(steps); |
|
|
|
|
|
moves += (goesForward ? ">" + "^".repeat(view.width) + ">" : "<" + "^".repeat(view.width) + "<"); |
|
|
|
|
|
goesForward = !goesForward; |
|
|
|
|
|
} |
|
|
|
|
|
char nextMove = moves.charAt(0); |
|
|
|
|
|
moves = moves.substring(1); |
|
|
|
|
|
return nextMove; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |