initial commit
This commit is contained in:
commit
807034a634
29
.gitignore
vendored
Normal file
29
.gitignore
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
85
src/Bot.java
Normal file
85
src/Bot.java
Normal file
@ -0,0 +1,85 @@
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public abstract class Bot {
|
||||
|
||||
// Ein Bot ist ein Programm, das sich mit einem Server verbindet und
|
||||
// mit diesem kommuniziert. Der Server sendet dem Bot eine Zeichenkette,
|
||||
// die das Spielfeld repräsentiert. Der Bot sendet dem Server ein Zeichen,
|
||||
// das die nächste Bewegung des Bots repräsentiert.
|
||||
|
||||
|
||||
private final String host; // Hostname oder IP-Adresse des Servers
|
||||
private final int port; // Port des Servers
|
||||
|
||||
protected Bot(String[] args) {
|
||||
host = args.length > 0 ? args[0] : "localhost";
|
||||
port = args.length > 1 ? Integer.parseInt(args[1]) : 63187;
|
||||
}
|
||||
|
||||
// Diese Methode stellt die Verbindung zum Server her und startet die
|
||||
// Kommunikation mit dem Server. Die Methode wird von der main-Methode
|
||||
// aufgerufen.
|
||||
protected void run() {
|
||||
try (Socket socket = new Socket()) {
|
||||
socket.connect(new InetSocketAddress(host, port));
|
||||
OutputStream out = socket.getOutputStream();
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
View view = new View();
|
||||
while (true) {
|
||||
view.read(in);
|
||||
view.print();
|
||||
try {
|
||||
char ch = nextMove(view);
|
||||
out.write(ch);
|
||||
}
|
||||
catch (Exception e) { break; }
|
||||
}
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Diese Methode ermittelt den nächsten Zug des Bots. Sie wird von der
|
||||
// run-Methode aufgerufen, nachdem der Server das Spielfeld gesendet hat.
|
||||
// Subklassen müssen diese Methode implementieren.
|
||||
abstract protected char nextMove(View view) throws Exception;
|
||||
|
||||
// Diese Klasse repräsentiert das Spielfeld. Sie wird von der run-Methode
|
||||
// verwendet, um das Spielfeld zu lesen und auszugeben.
|
||||
// Subklassen können diese Klasse verwenden, um das Spielfeld zu analysieren.
|
||||
public static class View {
|
||||
protected String data;
|
||||
protected int width;
|
||||
|
||||
// Diese Methode liest das Spielfeld vom Server.
|
||||
private void read(BufferedReader in) throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
data = in.readLine();
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
sb.append(data);
|
||||
width = data.length();
|
||||
for (int i = 1; i < width; ++i) {
|
||||
sb.append(in.readLine());
|
||||
}
|
||||
data = sb.toString();
|
||||
}
|
||||
|
||||
// Diese Methode gibt das Spielfeld aus.
|
||||
protected void print() {
|
||||
if (data == null || width < 1) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0, len = data.length(); i < len; i += width) {
|
||||
System.out.println(data.substring(i, i + width));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
140
src/CollectBot.java
Normal file
140
src/CollectBot.java
Normal file
@ -0,0 +1,140 @@
|
||||
import java.util.Stack;
|
||||
|
||||
public class CollectBot extends SmartBot {
|
||||
|
||||
private int maxNumberOfTilesToMove = 15;
|
||||
|
||||
private int tilesMoved;
|
||||
|
||||
private char directionBias;
|
||||
|
||||
private final Stack<Character> moves;
|
||||
|
||||
protected CollectBot(String[] args) {
|
||||
super(args);
|
||||
tilesMoved = 0;
|
||||
directionBias = LEFT;
|
||||
moves = new Stack<Character>();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Bot bot = new CollectBot(args);
|
||||
bot.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char nextMove(View view) throws Exception {
|
||||
char move = '^';
|
||||
|
||||
// Search larger areas after a time
|
||||
if (moves.size() != 0 && moves.size() % 100 == 0 && maxNumberOfTilesToMove <=30) {
|
||||
maxNumberOfTilesToMove += 5;
|
||||
}
|
||||
|
||||
// Look for Gems
|
||||
int turn = scanView(view);
|
||||
if (turn == 3) {
|
||||
tilesMoved++;
|
||||
// Change up direction after not encountering anything for a while
|
||||
if (tilesMoved >= maxNumberOfTilesToMove) {
|
||||
tilesMoved = 0;
|
||||
move = switchBias(true);
|
||||
}
|
||||
} else {
|
||||
tilesMoved = 0;
|
||||
move = switch (turn) {
|
||||
case -1 -> LEFT;
|
||||
case 0 -> FORWARD;
|
||||
case 1 -> RIGHT;
|
||||
default -> move;
|
||||
};
|
||||
}
|
||||
moves.push(move);
|
||||
return move;
|
||||
}
|
||||
|
||||
/***
|
||||
* This Method can be either used to detect potential spiral collision paths or to periodically change the direction bias
|
||||
* @param numberOfTurns The number of turns that should be equal
|
||||
* @return true, if the last n turns were equal in the given distance covered
|
||||
*/
|
||||
private boolean evaluateNumberOfEqualTurns(int numberOfTurns) {
|
||||
if (this.moves.isEmpty() || this.moves.size() < 3) {
|
||||
return false;
|
||||
}
|
||||
Stack<Character> moves = (Stack<Character>) this.moves.clone();
|
||||
int numberOfEqualTurns = 0;
|
||||
int distanceCovered = 0;
|
||||
char directionToCompare = '#';
|
||||
while (numberOfEqualTurns <= numberOfTurns && !moves.isEmpty()) {
|
||||
char lastMove = moves.pop();
|
||||
if (lastMove == FORWARD) {
|
||||
distanceCovered++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (numberOfEqualTurns == 0) {
|
||||
numberOfEqualTurns++;
|
||||
directionToCompare = lastMove;
|
||||
} else {
|
||||
if (lastMove != directionToCompare) {
|
||||
return false;
|
||||
}
|
||||
numberOfEqualTurns++;
|
||||
}
|
||||
}
|
||||
return numberOfEqualTurns == 3;
|
||||
}
|
||||
|
||||
/***
|
||||
* Changes up the direction bias every two turns which achieves a rough zig-zag pattern
|
||||
* @return the next direction bias
|
||||
*/
|
||||
protected char switchBias(boolean forcedSwitch) {
|
||||
if(!evaluateNumberOfEqualTurns(2) && !forcedSwitch) {
|
||||
return directionBias;
|
||||
}
|
||||
directionBias = switch (directionBias) {
|
||||
case LEFT -> {
|
||||
directionBias = RIGHT;
|
||||
yield RIGHT;
|
||||
}
|
||||
case RIGHT -> {
|
||||
directionBias = LEFT;
|
||||
yield LEFT;
|
||||
}
|
||||
default -> directionBias;
|
||||
};
|
||||
return directionBias;
|
||||
}
|
||||
|
||||
protected char switchBias() {
|
||||
return switchBias(false);
|
||||
}
|
||||
|
||||
protected int scanView(View view) {
|
||||
if (view.data.contains("@")) {
|
||||
int stone = view.data.indexOf("@") + 1;
|
||||
|
||||
// Check Front:
|
||||
switch (stone) {
|
||||
case 3, 8:
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If possible, prefer direction Bias
|
||||
if (directionBias == LEFT) {
|
||||
switch (stone) {
|
||||
case 11, 12: return -1; // left
|
||||
case 14, 15: return 1; // right
|
||||
}
|
||||
} else {
|
||||
switch (stone) {
|
||||
case 14, 15: return 1; // right
|
||||
case 11, 12: return -1; // left
|
||||
}
|
||||
}
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
}
|
29
src/DummyBot.java
Normal file
29
src/DummyBot.java
Normal file
@ -0,0 +1,29 @@
|
||||
import java.util.Random;
|
||||
|
||||
public class DummyBot extends SmartBot {
|
||||
|
||||
Random random;
|
||||
|
||||
protected DummyBot(String[] args) {
|
||||
super(args);
|
||||
random = new Random();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Bot bot = new DummyBot(args);
|
||||
bot.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char nextMove(View view) throws Exception {
|
||||
int move = random.nextInt(0, 7);
|
||||
return switch (move) {
|
||||
case 1,2,3 -> FORWARD;
|
||||
case 4 -> LEFT;
|
||||
case 5 -> RIGHT;
|
||||
case 6 -> SHOOT;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
67
src/EscapeBot.java
Normal file
67
src/EscapeBot.java
Normal file
@ -0,0 +1,67 @@
|
||||
public class EscapeBot extends Bot {
|
||||
|
||||
int unitsMoved;
|
||||
|
||||
int unitsToMove;
|
||||
|
||||
int timesTurned;
|
||||
|
||||
protected EscapeBot(String[] args) {
|
||||
super(args);
|
||||
unitsMoved = 0;
|
||||
unitsToMove = 5;
|
||||
timesTurned = 0;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Bot bot = new EscapeBot(args);
|
||||
bot.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char nextMove(View view) throws Exception {
|
||||
//boolean found = false;
|
||||
|
||||
if (unitsMoved % 5 == 0) {
|
||||
char c = checkView(view);
|
||||
switch (c) {
|
||||
case '0': break;
|
||||
case '1': throw new Exception("found!");
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
|
||||
if (unitsMoved < unitsToMove) {
|
||||
unitsMoved++;
|
||||
return '^';
|
||||
} else if (unitsMoved == unitsToMove) {
|
||||
unitsMoved = 0;
|
||||
timesTurned++;
|
||||
|
||||
if (timesTurned % 2 == 0) {
|
||||
unitsToMove += 5;
|
||||
}
|
||||
return '>';
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
private char checkView(View view) {
|
||||
if (view.data.contains("o")) {
|
||||
int spaceship = view.data.indexOf("o") + 1;
|
||||
if (spaceship == 13) {
|
||||
return '1';
|
||||
} else if (spaceship <= 10) {
|
||||
return '^';
|
||||
} else if (spaceship >= 15) {
|
||||
return 'v';
|
||||
} else if (spaceship%5 < 3) {
|
||||
return '<';
|
||||
} else if (spaceship%5 > 3) {
|
||||
return '>';
|
||||
}
|
||||
}
|
||||
return '0';
|
||||
}
|
||||
}
|
163
src/RumbleBot.java
Normal file
163
src/RumbleBot.java
Normal file
@ -0,0 +1,163 @@
|
||||
import java.util.Random;
|
||||
|
||||
public class RumbleBot extends SmartBot {
|
||||
|
||||
private int tilesToMove;
|
||||
|
||||
private int escapeMove;
|
||||
|
||||
private final Random random;
|
||||
|
||||
private final int[] leftVectorIndizes = new int[] {36,37,38,39};
|
||||
private final int[] rightVectorIndizes = new int[] {23,24,25,26};
|
||||
private final int[] frontVectorIndizes = new int[] {4,13,22,31};
|
||||
|
||||
protected RumbleBot(String[] args) {
|
||||
super(args);
|
||||
this.random = new Random();
|
||||
this.escapeMove = 0;
|
||||
this.tilesToMove = random.nextInt(5, 15);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Bot bot = new RumbleBot(args);
|
||||
bot.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char nextMove(View view) throws Exception {
|
||||
char move = FORWARD;
|
||||
|
||||
// if (tilesToMove >= tilesMoved) {
|
||||
// tilesMoved = 0;
|
||||
// tilesToMove = random.nextInt(5, 15);
|
||||
// move = directionBias;
|
||||
// }
|
||||
|
||||
if (escapeMove != 0) {
|
||||
escapeMove--;
|
||||
return FORWARD;
|
||||
}
|
||||
|
||||
// Check for enemies
|
||||
Enemy enemy = evaluateEnemy(view);
|
||||
if (enemy != null) {
|
||||
move = calculateOptimalMove(view, enemy);
|
||||
escapeMove = 3;
|
||||
}
|
||||
|
||||
if (directionBlocked(view,FORWARD)) {
|
||||
if (directionBlocked(view,RIGHT)) {
|
||||
move = LEFT;
|
||||
} else {
|
||||
move = RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
return move;
|
||||
}
|
||||
|
||||
private Enemy evaluateEnemy(View view) {
|
||||
int enemyPos;
|
||||
if (view.data.contains("^")) {
|
||||
enemyPos = view.data.indexOf('^');
|
||||
} else if (view.data.contains("v")) {
|
||||
enemyPos = view.data.indexOf('v');
|
||||
} else if (view.data.contains("<")) {
|
||||
enemyPos = view.data.indexOf('<');
|
||||
} else if (view.data.contains(">")) {
|
||||
enemyPos = view.data.indexOf('>');
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return new Enemy(enemyPos + 1, view.data.charAt(enemyPos));
|
||||
}
|
||||
|
||||
public boolean directionBlocked(View view, char direction) {
|
||||
if (direction == FORWARD) {
|
||||
for (int i = 4; i < 32; i+=9) {
|
||||
if (view.data.charAt(i) == 'X') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (direction == LEFT) {
|
||||
for (int i = 36; i < 40; i++) {
|
||||
if (view.data.charAt(i) == 'X') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (direction == RIGHT) {
|
||||
for (int i = 41; i < 45; i++) {
|
||||
if (view.data.charAt(i) == 'X') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private char calculateOptimalMove(View view, Enemy enemy) {
|
||||
int pos = enemy.position;
|
||||
char dir = enemy.direction;
|
||||
|
||||
|
||||
// Top Sector
|
||||
if (pos <= 18) {
|
||||
// Left Half
|
||||
if (pos % 9 < 5) {
|
||||
return !directionBlocked(view,RIGHT) ? RIGHT : SHOOT;
|
||||
}
|
||||
|
||||
// Right Half
|
||||
else if (pos % 9 > 5) {
|
||||
return !directionBlocked(view,LEFT) ? LEFT : SHOOT;
|
||||
}
|
||||
// Center
|
||||
else {
|
||||
return SHOOT;
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom Sector
|
||||
if (pos >= 24) {
|
||||
// Left or Right Half
|
||||
if (pos % 9 != 5) {
|
||||
return !directionBlocked(view,FORWARD) ? FORWARD : randomDirection(view);
|
||||
}
|
||||
// Center
|
||||
else {
|
||||
return randomDirection(view);
|
||||
}
|
||||
}
|
||||
|
||||
// Left or Right
|
||||
return randomDirection(view);
|
||||
}
|
||||
|
||||
private char randomDirection(View view) {
|
||||
int rand = random.nextInt(0, 1);
|
||||
char dir = rand == 0 ? '<' : '>';
|
||||
return !directionBlocked(view,dir) ? dir : flipDirection(dir);
|
||||
}
|
||||
|
||||
private char flipDirection(char direction) {
|
||||
return switch (direction) {
|
||||
case RIGHT -> LEFT;
|
||||
case LEFT -> RIGHT;
|
||||
case FORWARD -> BACKWARD;
|
||||
default -> FORWARD;
|
||||
};
|
||||
}
|
||||
|
||||
private static class Enemy {
|
||||
final int position;
|
||||
final char direction;
|
||||
|
||||
public Enemy(int position, char direction) {
|
||||
this.position = position;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
28
src/SmartBot.java
Normal file
28
src/SmartBot.java
Normal file
@ -0,0 +1,28 @@
|
||||
import java.util.Stack;
|
||||
|
||||
public abstract class SmartBot extends Bot {
|
||||
|
||||
protected static final char FORWARD = '^';
|
||||
protected static final char BACKWARD = 'v';
|
||||
protected static final char LEFT = '<';
|
||||
protected static final char RIGHT = '>';
|
||||
protected static final char SHOOT = 'f';
|
||||
|
||||
protected int tilesMoved;
|
||||
|
||||
protected final Stack<Character> moves;
|
||||
|
||||
|
||||
protected SmartBot(String[] args) {
|
||||
super(args);
|
||||
this.tilesMoved = 0;
|
||||
this.moves = new Stack<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char nextMove(View view) throws Exception {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
199
src/SnakeBot.java
Normal file
199
src/SnakeBot.java
Normal file
@ -0,0 +1,199 @@
|
||||
import java.util.Stack;
|
||||
|
||||
public class SnakeBot extends SmartBot {
|
||||
|
||||
private int maxNumberOfTilesToMove = 15;
|
||||
|
||||
private int tilesMoved;
|
||||
|
||||
private int tailLength;
|
||||
|
||||
private int escapeSequence;
|
||||
|
||||
private char directionBias;
|
||||
|
||||
private final Stack<Character> moves;
|
||||
|
||||
protected SnakeBot(String[] args) {
|
||||
super(args);
|
||||
tilesMoved = 0;
|
||||
tailLength = 0;
|
||||
escapeSequence = 0;
|
||||
directionBias = LEFT;
|
||||
moves = new Stack<Character>();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Bot bot = new SnakeBot(args);
|
||||
bot.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char nextMove(View view) throws Exception {
|
||||
char move = '^';
|
||||
|
||||
// Avoid potential spiral paths
|
||||
if (evaluateNumberOfEqualTurns(3, tailLength)) {
|
||||
moves.push(switchBias());
|
||||
System.out.println("Potential Spiral detected. Next Move: " + directionBias);
|
||||
escapeSequence = 2;
|
||||
return directionBias;
|
||||
}
|
||||
|
||||
// Way must be free
|
||||
if (!checkFrontCollisions(view)) {
|
||||
escapeSequence = 1;
|
||||
moves.push(switchBias());
|
||||
System.out.println("Collision ahead. Next Move: " + directionBias);
|
||||
|
||||
return directionBias;
|
||||
}
|
||||
|
||||
// Escape after potential collision or spiral turn loops
|
||||
if (escapeSequence != 0) {
|
||||
switch (escapeSequence) {
|
||||
case 1:
|
||||
escapeSequence = 0;
|
||||
moves.push(FORWARD);
|
||||
return FORWARD;
|
||||
case 2:
|
||||
escapeSequence = 1;
|
||||
moves.push(switchBias());
|
||||
return directionBias;
|
||||
}
|
||||
}
|
||||
|
||||
// Search larger areas after a time
|
||||
if (moves.size() != 0 && moves.size() % 100 == 0 && maxNumberOfTilesToMove <=30) {
|
||||
maxNumberOfTilesToMove += 5;
|
||||
}
|
||||
|
||||
// Look for Gems
|
||||
int turn = scanView(view);
|
||||
if (turn == 3) {
|
||||
tilesMoved++;
|
||||
// Change up direction after not encountering anything for a while
|
||||
if (tilesMoved >= maxNumberOfTilesToMove) {
|
||||
tilesMoved = 0;
|
||||
move = switchBias(true);
|
||||
}
|
||||
} else {
|
||||
tilesMoved = 0;
|
||||
move = switch (turn) {
|
||||
case -1 -> LEFT;
|
||||
case 0 -> FORWARD;
|
||||
case 1 -> RIGHT;
|
||||
default -> move;
|
||||
};
|
||||
}
|
||||
moves.push(move);
|
||||
return move;
|
||||
}
|
||||
|
||||
/***
|
||||
* This Method can be either used to detect potential spiral collision paths or to periodically change the direction bias
|
||||
* @param numberOfTurns The number of turns that should be equal
|
||||
* @param maxDepth The distance in wich the turns must have occurred to be considered
|
||||
* @return true, if the last n turns were equal in the given distance covered
|
||||
*/
|
||||
private boolean evaluateNumberOfEqualTurns(int numberOfTurns, int maxDepth) {
|
||||
if (this.moves.isEmpty() || this.moves.size() < 3) {
|
||||
return false;
|
||||
}
|
||||
Stack<Character> moves = (Stack<Character>) this.moves.clone();
|
||||
int numberOfEqualTurns = 0;
|
||||
int distanceCovered = 0;
|
||||
char directionToCompare = '#';
|
||||
while (numberOfEqualTurns <= numberOfTurns && distanceCovered <= maxDepth && !moves.isEmpty()) {
|
||||
char lastMove = moves.pop();
|
||||
if (lastMove == FORWARD) {
|
||||
distanceCovered++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (numberOfEqualTurns == 0) {
|
||||
numberOfEqualTurns++;
|
||||
directionToCompare = lastMove;
|
||||
} else {
|
||||
if (lastMove != directionToCompare) {
|
||||
return false;
|
||||
}
|
||||
numberOfEqualTurns++;
|
||||
}
|
||||
}
|
||||
return numberOfEqualTurns == 3;
|
||||
}
|
||||
|
||||
private boolean evaluateNumberOfEqualTurns(int numberOfTurns) {
|
||||
return evaluateNumberOfEqualTurns(numberOfTurns, 32);
|
||||
}
|
||||
|
||||
/***
|
||||
* Changes up the direction bias every two turns which achieves a rough zig-zag pattern
|
||||
* @return the next direction bias
|
||||
*/
|
||||
protected char switchBias(boolean forcedSwitch) {
|
||||
if(!evaluateNumberOfEqualTurns(2) && !forcedSwitch) {
|
||||
return directionBias;
|
||||
}
|
||||
directionBias = switch (directionBias) {
|
||||
case LEFT -> {
|
||||
directionBias = RIGHT;
|
||||
yield RIGHT;
|
||||
}
|
||||
case RIGHT -> {
|
||||
directionBias = LEFT;
|
||||
yield LEFT;
|
||||
}
|
||||
default -> directionBias;
|
||||
};
|
||||
return directionBias;
|
||||
}
|
||||
|
||||
protected char switchBias() {
|
||||
return switchBias(false);
|
||||
}
|
||||
|
||||
private boolean checkFrontCollisions(View view) {
|
||||
return view.data.charAt(2) != '*' &&
|
||||
view.data.charAt(7) != '*';
|
||||
}
|
||||
|
||||
private boolean checkSideCollisions(View view, int side) {
|
||||
if (side == -1) {
|
||||
return view.data.charAt(11) != '*';
|
||||
} else if (side == 1) {
|
||||
return view.data.indexOf(13) != '*';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected int scanView(View view) {
|
||||
if (view.data.contains("@")) {
|
||||
int stone = view.data.indexOf("@") + 1;
|
||||
|
||||
// Check Front:
|
||||
switch (stone) {
|
||||
case 3:
|
||||
tailLength++;
|
||||
return 0;
|
||||
case 8:
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If possible, prefer direction Bias
|
||||
if (directionBias == LEFT) {
|
||||
switch (stone) {
|
||||
case 11, 12: return checkSideCollisions(view, -1)? -1 : 3; // left
|
||||
case 14, 15: return checkSideCollisions(view, 1)? 1 : 3; // right
|
||||
}
|
||||
} else {
|
||||
switch (stone) {
|
||||
case 14, 15: return checkSideCollisions(view, 1)? 1 : 3; // right
|
||||
case 11, 12: return checkSideCollisions(view, -1)? -1 : 3; // left
|
||||
}
|
||||
}
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user