diff --git a/.idea/misc.xml b/.idea/misc.xml
index 2ac9e35931b9ef45775c1e4d81e72f9e331a2135..2f57a3fb3ab327fb51536ae1f2d469f4652a1cad 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="ExternalStorageConfigurationManager" enabled="true" />
   <component name="MavenProjectsManager">
@@ -8,7 +7,7 @@
       </list>
     </option>
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_20" project-jdk-name="temurin-20" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_19" project-jdk-name="temurin-17" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/out" />
   </component>
 </project>
\ No newline at end of file
diff --git a/src/main/java/de/fossag/hackatron/AlgConfig.java b/src/main/java/de/fossag/hackatron/AlgConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e4d1778e5dace47de43229bcbd405ca2c87021e
--- /dev/null
+++ b/src/main/java/de/fossag/hackatron/AlgConfig.java
@@ -0,0 +1,8 @@
+package de.fossag.hackatron;
+
+public class AlgConfig {
+
+    public static final int maxDepth = 2; // How far we look into the future
+    public static final int dfsBestScore = 23; // Which score is considered "best" to stop searching early
+
+}
diff --git a/src/main/java/de/fossag/hackatron/GameEngine.java b/src/main/java/de/fossag/hackatron/GameEngine.java
new file mode 100644
index 0000000000000000000000000000000000000000..25bedb83a2d23d9e4b2cf3e13c119cedb8d75dc2
--- /dev/null
+++ b/src/main/java/de/fossag/hackatron/GameEngine.java
@@ -0,0 +1,67 @@
+package de.fossag.hackatron;
+
+import java.util.*;
+
+public class GameEngine {
+    public enum Move {
+        Up("up"), Down("down"), Left("left"), Right("right");
+        private final String name;
+
+        Move(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    public static Move generateNextMove(GameState gameState) {
+        ArrayList<Map.Entry<Move, Integer>> bestMoves = new ArrayList<>(AlgConfig.maxDepth);
+        double[] weightedScores = new double[AlgConfig.maxDepth];
+        for (int i = AlgConfig.maxDepth-1; i >= 0; i--) {
+            Map.Entry<Move, Integer> currentMove = dfs(gameState.ownX, gameState.ownY, gameState.getMap(), 0);
+
+            bestMoves.add(0, currentMove);
+            weightedScores[i] = currentMove.getValue()/(Math.min(Math.pow(2,i+1),AlgConfig.dfsBestScore));
+
+            gameState.cleanupMap(-i-2);
+        }
+
+        int highestScoreIndex = weightedScores.length-1;
+        for (int i = weightedScores.length - 2; i >= 0; i--) {
+            if (weightedScores[i] > weightedScores[highestScoreIndex]) {
+                highestScoreIndex = i;
+            }
+        }
+
+        return bestMoves.get(highestScoreIndex).getKey();
+    }
+
+    public static Map.Entry<Move, Integer> dfs(int x, int y, Integer[][] map, int depth) {
+        int bestMoveScore = 0;
+        Move bestMove = Move.Up;
+        Move[] moves = Move.values();
+        if(depth == 0) {
+            List<Move> listOfMoves = Arrays.asList(moves);
+            Collections.shuffle(listOfMoves);
+            moves = listOfMoves.toArray(new Move[0]);
+        }
+        for (Move m : moves) {
+            int[] nextPos = GameUtils.getNextPosition(map, x, y, m);
+            if (map[nextPos[0]][nextPos[1]] != null) continue;
+            map[nextPos[0]][nextPos[1]] = -1;
+            int score = dfs(nextPos[0], nextPos[1], map, depth+1).getValue() + 1;
+            map[nextPos[0]][nextPos[1]] = null;
+            if (score > bestMoveScore) {
+                if (score > AlgConfig.dfsBestScore) {
+                    return Map.entry(m, score);
+                }
+                bestMoveScore = score;
+                bestMove = m;
+            }
+        }
+        return Map.entry(bestMove, bestMoveScore);
+    }
+}
diff --git a/src/main/java/de/fossag/hackatron/GameState.java b/src/main/java/de/fossag/hackatron/GameState.java
new file mode 100644
index 0000000000000000000000000000000000000000..f2f0b79777e9df0a22772cee06f345295270c8c1
--- /dev/null
+++ b/src/main/java/de/fossag/hackatron/GameState.java
@@ -0,0 +1,93 @@
+package de.fossag.hackatron;
+
+import java.util.HashMap;
+
+public class GameState {
+    public int ownID, ownX, ownY;
+    public GameEngine.Move lastMove = GameEngine.Move.Up;
+    private int mapWidth, mapHeight;
+    private final Integer[][] map;  //[width][height]
+    private final HashMap<Integer, String> playerNames;
+
+    public GameState(int mapWidth, int mapHeight, int ownID) {
+        playerNames = new HashMap<>();
+        this.ownID = ownID;
+        map = new Integer[mapWidth][mapHeight];
+
+        this.mapWidth = mapWidth;
+        this.mapHeight = mapHeight;
+    }
+
+    public Integer[][] getMap() {
+        return map;
+    }
+
+    public void cleanupMap(int untilPriority) {
+        for (int x = 0; x < mapWidth; x++) {
+            for (int y = 0; y < mapHeight; y++) {
+                if (map[x][y] != null && map[x][y] <= untilPriority) map[x][y] = null;
+            }
+        }
+    }
+
+    public void addPos(int id, int x, int y) {
+        if (x < 0 | y < 0 | x >= mapWidth || y >= mapHeight) {
+            throw new UnsupportedOperationException("Position: (" + x + "," + y + ") out of bounds");
+        }
+        map[x][y] = id;
+
+        if (id == ownID) return;
+        addLookaheadPosRec(x, y, 1);
+    }
+
+    public void addLookaheadPosRec(int x, int y, int depth) {
+        if (depth >= AlgConfig.maxDepth) return;
+
+        for (GameEngine.Move m : GameEngine.Move.values()) {
+            int[] nextPos = GameUtils.getNextPosition(getMap(), x, y, m);
+            int newX = nextPos[0];
+            int newY = nextPos[1];
+            Integer currentCell = map[newX][newY];
+
+            if (currentCell == null || currentCell < -1 - depth) {
+                map[newX][newY] = -1 - depth;
+                addLookaheadPosRec(newX, newY, depth + 1);
+            }
+        }
+    }
+
+    public void setPlayerInfo(int playerId, String name) {
+        playerNames.put(playerId, name);
+    }
+
+    public void printMap() {
+        System.out.println("------------");
+        for (int y = 0; y < mapHeight; y++) {
+            System.out.print("|");
+            for (int x = 0; x < mapWidth; x++) {
+                Integer currentPixel = map[x][y];
+                if(currentPixel == null) {
+                    System.out.print(" ");
+                } else if(currentPixel == ownID) {
+                    System.out.print("X");
+                } else {
+                    System.out.print((char) (map[x][y] + 64+1));
+                }
+            }
+            System.out.println("|");
+        }
+        System.out.println("------------");
+    }
+
+    public void playerDies(int playerId) {
+        playerNames.remove(playerId);
+        for (int i = 0; i < mapWidth; i++) {
+            for (int j = 0; j < mapHeight; j++) {
+                Integer val = map[i][j];
+                if (val != null && val == playerId) {
+                    map[i][j] = null;
+                }
+            }
+        }
+    }
+}
diff --git a/src/main/java/de/fossag/hackatron/GameUtils.java b/src/main/java/de/fossag/hackatron/GameUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..5609737fee565c08fb3a48e660a5eb7e2c87107b
--- /dev/null
+++ b/src/main/java/de/fossag/hackatron/GameUtils.java
@@ -0,0 +1,21 @@
+package de.fossag.hackatron;
+
+public class GameUtils {
+
+    public static int[] getNextPosition(Integer[][] map, int x, int y, GameEngine.Move m) {
+        int mapWidth = map.length;
+        int mapHeight = map[0].length;
+
+        int newX = x;
+        int newY = y;
+        switch (m) {
+            case Up -> newY = (y - 1 + mapHeight) % mapHeight;
+            case Left -> newX = (x - 1 + mapWidth) % mapWidth;
+            case Right -> newX = (x + 1) % mapWidth;
+            case Down -> newY = (y + 1) % mapHeight;
+        }
+
+        return new int[]{newX, newY};
+    }
+
+}
diff --git a/src/main/java/de/fossag/hackatron/HackatronClient.java b/src/main/java/de/fossag/hackatron/HackatronClient.java
index 9989ba40fd1daab4959b14492857f8ddc1224d8c..9661283ac6b53bab852f6f478da61831b9d5a0e6 100644
--- a/src/main/java/de/fossag/hackatron/HackatronClient.java
+++ b/src/main/java/de/fossag/hackatron/HackatronClient.java
@@ -2,30 +2,81 @@ package de.fossag.hackatron;
 
 public class HackatronClient implements IHackatronClient {
 
-  private IMessageSender messageSender;
-  private static final String CLIENT_NAME = "dummyclient";
-  private static final String CLIENT_SECRET = "changeme";
+    private IMessageSender messageSender;
+    private static final String CLIENT_NAME = "Schatten";
+    private static final String CLIENT_SECRET = "ThisIsASuperSecretClientSecretToMakeSureNoOneStealsOurClient";
+    private int losses = 0;
+    private int wins = 0;
 
-  @Override
-  public void setMessageSender(IMessageSender messageSender) {
-    this.messageSender = messageSender;
-  }
+    GameState game;
 
-  @Override
-  public void onMessage(String message) {
-    String[] parts = message.split("\\|");
-    String messageType = parts[0];
+    @Override
+    public void setMessageSender(IMessageSender messageSender) {
+        this.messageSender = messageSender;
+    }
+
+    long lastTick = System.nanoTime();
+    int curTick = 0;
+    @Override
+    public void onMessage(String message) {
+        String[] parts = message.split("\\|");
+        String messageType = parts[0];
 
-    switch (messageType) {
-      case "motd":
-        messageSender.send("join|" + CLIENT_NAME + "|" + CLIENT_SECRET);
-        break;
-      case "tick":
-        messageSender.send("move|up");
-        break;
-      default:
-        System.out.println("Unknown message type :(");
-        System.exit(1);
+        switch (messageType) {
+            case "motd":
+                messageSender.send("join|" + CLIENT_NAME + "|" + CLIENT_SECRET);
+                break;
+            case "tick":
+                long timeStart = System.nanoTime();
+                game.lastMove = GameEngine.generateNextMove(game);
+                long timeEnd = System.nanoTime();
+                //System.out.println("Time spent: " + (timeEnd - timeStart) / 1_000_000.0 + "ms, going " + game.lastMove);
+                messageSender.send("move|" + game.lastMove);
+                game.cleanupMap(-2);
+                curTick++;
+                //System.out.println("Last tick time: "+(timeStart-lastTick)/1_000_000.0);
+                //System.out.println("Expected Tick: "+(1/(Math.ceil(curTick/10.d))));
+                lastTick = timeStart;
+                //if(game != null) game.printMap();
+                break;
+            case "game":
+                if (wins + losses > 0)
+                    System.out.printf("Starting a new game, current stats: %d-%d, %d\n", wins, losses, wins / (wins + losses));
+                game = new GameState(Integer.parseInt(parts[1]), Integer.parseInt(parts[2]), Integer.parseInt(parts[3]));
+                curTick = 0;
+                break;
+            case "pos":
+                int id = Integer.parseInt(parts[1]);
+                int x = Integer.parseInt(parts[2]);
+                int y = Integer.parseInt(parts[3]);
+                game.addPos(id, x, y);
+                if (id == game.ownID) {
+                    game.ownX = x;
+                    game.ownY = y;
+                }
+                break;
+            case "player":
+                game.setPlayerInfo(Integer.parseInt(parts[1]), parts[2]);
+                break;
+            case "die":
+                System.out.println(parts[1] + " has died");
+                game.playerDies(Integer.parseInt(parts[1]));
+                break;
+            case "lose":
+                System.out.printf("LOST! Died at %d|%d, last move: %s\n", game.ownX, game.ownY, game.lastMove);
+                game.printMap();
+                losses++;
+                break;
+            case "win":
+                System.out.println("WON!");
+                wins++;
+                break;
+            case "error":
+                System.out.println("SERVER ERROR: " + parts[1]);
+                break;
+            default:
+                System.out.println("Unknown message type :(");
+                System.exit(1);
+        }
     }
-  }
 }
diff --git a/src/main/java/de/fossag/hackatron/HackatronWrapper.java b/src/main/java/de/fossag/hackatron/HackatronWrapper.java
index 7adf7f33badc183bcb887d0a5cbdab2e47aa172f..9b42df5f55e5ffd9dc0b42217737283be15ebcb2 100644
--- a/src/main/java/de/fossag/hackatron/HackatronWrapper.java
+++ b/src/main/java/de/fossag/hackatron/HackatronWrapper.java
@@ -14,46 +14,44 @@ import java.net.Socket;
  */
 public class HackatronWrapper {
 
-  private String host;
-  private int port;
-
-  private IHackatronClient hackatronClient;
-
-  public HackatronWrapper(String host, int port, IHackatronClient hackatronClient) {
-    this.host = host;
-    this.port = port;
-    this.hackatronClient = hackatronClient;
-  }
-
-  public void run() throws IOException {
-    System.out.println("Connecting to " + host + ":" + port);
-
-    // Set up socket and wire up streams
-    Socket socket = new Socket(host, port);
-    OutputStream out = socket.getOutputStream();
-    PrintWriter writer = new PrintWriter(out, true);
-    InputStream in = socket.getInputStream();
-    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
-
-    System.out.println("Connection successful");
-
-    // The message sender logs the outgoing message and stuffs it into the output stream
-    hackatronClient.setMessageSender(s -> {
-      System.out.println("OUT MSG: " + s);
-      writer.println(s);
-    });
-
-    while (true) {
-      if (socket.isClosed()) {
-        return;
-      }
-      String line = reader.readLine();
-      if (line == null) {
-        return;
-      }
-      System.out.println("IN MSG: " + line);
-      hackatronClient.onMessage(line);
+    private String host;
+    private int port;
+
+    private IHackatronClient hackatronClient;
+
+    public HackatronWrapper(String host, int port, IHackatronClient hackatronClient) {
+        this.host = host;
+        this.port = port;
+        this.hackatronClient = hackatronClient;
     }
 
-  }
+    public void run() throws IOException {
+        System.out.println("Connecting to " + host + ":" + port);
+
+        // Set up socket and wire up streams
+        Socket socket = new Socket(host, port);
+        OutputStream out = socket.getOutputStream();
+        PrintWriter writer = new PrintWriter(out, true);
+        InputStream in = socket.getInputStream();
+        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+
+        System.out.println("Connection successful");
+
+        // The message sender logs the outgoing message and stuffs it into the output stream
+        hackatronClient.setMessageSender(s -> {
+            writer.println(s);
+        });
+
+        while (true) {
+            if (socket.isClosed()) {
+                return;
+            }
+            String line = reader.readLine();
+            if (line == null) {
+                return;
+            }
+            hackatronClient.onMessage(line);
+        }
+
+    }
 }
diff --git a/src/main/java/de/fossag/hackatron/IHackatronClient.java b/src/main/java/de/fossag/hackatron/IHackatronClient.java
index 82a8589c0939335280ba4ac6bd6ad621820f5704..e4fba652ea8776e6860a0a632746f6a94d4bdf87 100644
--- a/src/main/java/de/fossag/hackatron/IHackatronClient.java
+++ b/src/main/java/de/fossag/hackatron/IHackatronClient.java
@@ -2,20 +2,20 @@ package de.fossag.hackatron;
 
 public interface IHackatronClient {
 
-  /**
-   * Gets called one time after instance creation to set the {@link IMessageSender} instance. You
-   * can use that to send reply messages back to the game server.
-   *
-   * @param messageSender IMessageSender instance
-   */
-  void setMessageSender(IMessageSender messageSender);
+    /**
+     * Gets called one time after instance creation to set the {@link IMessageSender} instance. You
+     * can use that to send reply messages back to the game server.
+     *
+     * @param messageSender IMessageSender instance
+     */
+    void setMessageSender(IMessageSender messageSender);
 
-  /**
-   * Gets called every time a new message from the game server arrives.
-   *
-   * See PROTOCOL.md for details
-   *
-   * @param message Message string
-   */
-  void onMessage(String message);
+    /**
+     * Gets called every time a new message from the game server arrives.
+     * <p>
+     * See PROTOCOL.md for details
+     *
+     * @param message Message string
+     */
+    void onMessage(String message);
 }
diff --git a/src/main/java/de/fossag/hackatron/IMessageSender.java b/src/main/java/de/fossag/hackatron/IMessageSender.java
index 1ff86423e6477931a31b48d88de58aeaa77bed92..5e9fec30191c958efc16f5485ac15c1d95bf066d 100644
--- a/src/main/java/de/fossag/hackatron/IMessageSender.java
+++ b/src/main/java/de/fossag/hackatron/IMessageSender.java
@@ -2,5 +2,5 @@ package de.fossag.hackatron;
 
 public interface IMessageSender {
 
-  void send(String message);
+    void send(String message);
 }
diff --git a/src/main/java/de/fossag/hackatron/Main.java b/src/main/java/de/fossag/hackatron/Main.java
index a69d6420dd0b0d06392328737cced5585f83aca4..b6f878a51a1a0338fde3795c5545349d1b65ee27 100644
--- a/src/main/java/de/fossag/hackatron/Main.java
+++ b/src/main/java/de/fossag/hackatron/Main.java
@@ -4,11 +4,11 @@ import java.io.IOException;
 
 public class Main {
 
-  public static void main(String[] args) throws IOException {
-    HackatronWrapper client = new HackatronWrapper(
-        "game.hackatron.de",
-        4000,
-        new HackatronClient());
-    client.run();
-  }
+    public static void main(String[] args) throws IOException {
+        HackatronWrapper client = new HackatronWrapper(
+                "game.hackatron.de",
+                4000,
+                new HackatronClient());
+        client.run();
+    }
 }
\ No newline at end of file