diff --git a/src/player/malte/Item.java b/src/player/malte/Item.java new file mode 100644 index 0000000..46d68a0 --- /dev/null +++ b/src/player/malte/Item.java @@ -0,0 +1,35 @@ +package player.malte; + +public class Item { + + public final Position pos; + public final int id; + public final boolean hasScaffold; + public final boolean onBoard; + + public Item(Position pos, + int id, + boolean hasScaffold, + boolean onBoard) { + this.pos = pos; + this.id = id; + this.hasScaffold = hasScaffold; + this.onBoard = onBoard; + } + + public String idString(int playerID, int enemyID) { + String s = ""; + if (!onBoard) { + s = "!"; + } else if (this.id == playerID) { + s = "M"; + } else if (this.id == enemyID) { + s = "E"; + } else if (hasScaffold) { + s = "O"; + } else { + s = " "; + } + return s; + } +} diff --git a/src/player/malte/MalteAI.java b/src/player/malte/MalteAI.java index f3bac1d..697d9ad 100644 --- a/src/player/malte/MalteAI.java +++ b/src/player/malte/MalteAI.java @@ -74,14 +74,9 @@ public class MalteAI implements Player{ } public double calculateWeight(int[][] board, int column) { - double W_START = 1.0; - double W_ILLEGAL = -1.0; - double W_WIN = 1.5; - double W_INSTANT_WIN = 5.0; - double W_PREVENT_WIN = 1.4; - double W_PREVENT_INSTANT_WIN= 2.0; + double W_ILLEGAL = Double.MIN_VALUE; double W_DONT = 0.01; - double weight = W_START; + double weight = 1.0; // Prever a place in the center; weight *= 1.0 - Math.abs(3.0 - column) / (3.0 * 100.0); // Relative positions like (-1, -1), (0, -1), etc. @@ -96,59 +91,112 @@ public class MalteAI implements Player{ // Setup Sequences Sequence[] sequences = new Sequence[8]; Sequence[] sequencesAbove = new Sequence[8]; + int[][] futureBoard = makeMove(copyBoard(board), column, this.id); for (int i = 0; i < sequences.length; i++) { sequences[i] = Sequence.readSequenceFromBoard(board, thisPos.add(relAround[i]), - relAround[i]); + relAround[i], + this.id, + this.enemyID); sequences[i].setPlayerID(this.id); sequences[i].setEnemyID(this.enemyID); - sequencesAbove[i] = Sequence.readSequenceFromBoard(board, + sequencesAbove[i] = Sequence.readSequenceFromBoard(futureBoard, thisPos.add(relAround[0]).add(relAround[i]), - relAround[i]); + relAround[i], + this.id, + this.enemyID); sequencesAbove[i].setPlayerID(this.id); sequencesAbove[i].setEnemyID(this.enemyID); } - for (int i = 0; i < sequences.length; i++) { + for (int i = 0; i < sequences.length / 2; i++) { Sequence x = sequences[i]; - if (x.matches("MMM")) { - weight *= W_INSTANT_WIN; - } else if (x.matches("EEE")) { - weight *= W_PREVENT_INSTANT_WIN; - } else if (x.matches("EE ")) { - weight *= W_PREVENT_WIN; - } else if (x.matches("MM ")) { - weight *= W_WIN; - } else if (i < 4) { - Sequence y = sequences[i + 4]; - if ((x.matches("MM") && - y.matches("M")) || - (x.matches("M") && - y.matches("MM"))) { - weight *= W_INSTANT_WIN; - } else if ((x.matches("EE") && - y.matches("E")) || - (x.matches("E") && - y.matches("EE"))) { - weight *= W_PREVENT_INSTANT_WIN; - } else if ((x.matches("MM ") && - y.matches(" ")) || - (x.matches(" ") && - y.matches("MM "))) { - weight *= W_WIN; - } - } + Sequence y = sequences[i + 4]; + weight *= getBaseWeightForSequences(x, y); Sequence xA = sequencesAbove[i]; - if (xA.matches("EEE")) { - // Prevent choosing a bad spot - weight *= W_DONT; - } else if (xA.matches("MMM")) { - // Open the opportunity - weight *= W_WIN; + Sequence yA = sequencesAbove[i + 4]; + // weight *= getBaseWeightForSequences(xA, yA); + if ((xA.matches("EEE") || + yA.matches("EEE")) || + ((xA.matches("E") && + yA.matches("EE")) || + (xA.matches("EE") && + yA.matches("E")))) { + // TODO: Do this right! + weight /= 2<<6; } } return weight; } + private double getBaseWeightForSequences(Sequence x, Sequence y) { + double W_PRIORITY_1 = 2 << 8; + double W_PRIORITY_2 = 2 << 6; + double W_PRIORITY_3 = 2 << 4; + double W_PRIORITY_4 = 2 << 2; + double W_PRIORITY_5 = 2 << 0; + double W_PRIORITY_6 = 1.0; + double W_START = 1.0; + double weight = W_START; + if (x.matches("MMM") || + y.matches("MMM")) { + weight *= W_PRIORITY_1; + System.out.println("1 USED"); + } else if ((x.matches("M") && + y.matches("MM")) || + (x.matches("MM") && + y.matches("M"))) { + weight *= W_PRIORITY_1; + } else if (x.matches("EEE") || + y.matches("EEE")) { + weight *= W_PRIORITY_2; + } else if ((x.matches("E") && + y.matches("EE")) || + (x.matches("EE") && + y.matches("E"))) { + weight *= W_PRIORITY_2; + } else if ((x.matches("O") && + y.matches("MMO")) || + (x.matches("MMO") && + y.matches("O"))) { + weight *= W_PRIORITY_3; + } else if ((x.matches("O") && + y.matches("EEO")) || + (x.matches("EEO") && + y.matches("O"))) { + weight *= W_PRIORITY_4; + } else if (x.matches("EO") && + y.matches("EO")) { + weight *= W_PRIORITY_4; + } else if (x.matches("MMO") || + y.matches("MMO")) { + weight *= W_PRIORITY_5; + } else if ((x.matches("O") && + y.matches("MM")) || + (x.matches("MM") && + y.matches("O"))) { + weight *= W_PRIORITY_5; + } else if ((x.matches("M") && + y.matches("MO")) || + (x.matches("MO") && + y.matches("M"))) { + weight *= W_PRIORITY_5; + } else if (x.matches("EEO") || + y.matches("EEO")) { + weight *= W_PRIORITY_6; + } else if ((x.matches("O") && + y.matches("EE")) || + (x.matches("EE") && + y.matches("O"))) { + weight *= W_PRIORITY_6; + } else if ((x.matches("E") && + y.matches("EO")) || + (x.matches("EO") && + y.matches("E"))) { + weight *= W_PRIORITY_6; + } + return weight; + } + /** * */ diff --git a/src/player/malte/Sequence.java b/src/player/malte/Sequence.java index 3700182..f0347a8 100644 --- a/src/player/malte/Sequence.java +++ b/src/player/malte/Sequence.java @@ -9,12 +9,12 @@ public class Sequence { private Position startingPos; private Position direction; - private List ids; + private List items; private int playerID; private int enemyID; - public Sequence(Position startingPos, Position direction, List ids) { - this.ids = new ArrayList(ids); + public Sequence(Position startingPos, Position direction, List items) { + this.items = new ArrayList(items); this.startingPos = startingPos; this.direction = direction; } @@ -35,7 +35,8 @@ public class Sequence { return false; } if (s.charAt(i) == 'p' && - idStr.charAt(i) == ' ') { + (idStr.charAt(i) != 'm' && + idStr.charAt(i) != 'e')) { return false; } else if (s.charAt(i) != idStr.charAt(i)) { return false; @@ -44,14 +45,28 @@ public class Sequence { return true; } - public static Sequence readSequenceFromBoard(int[][] board, Position pos, Position dir) { + public static Sequence readSequenceFromBoard(int[][] board, + Position pos, + Position dir, + int playerID, + int enemyID) { Position cur = pos; - List ids = new ArrayList(); + List items = new ArrayList(); + Position down = new Position(0, 1); while (isPosOnBoard(cur)) { - ids.add(getIDFromBoard(board, cur)); + boolean hasScaffold = (isPosOnBoard(cur.add(down)) && + getIDFromBoard(board, cur.add(down)) != 0) || cur.getPosY() == 5; + items.add(new Item(cur, + getIDFromBoard(board, cur), + hasScaffold, + true)); cur = cur.add(dir); } - return new Sequence(pos, dir, ids); + items.add(new Item(cur, + -1, + false, + false)); + return new Sequence(pos, dir, items); } private static boolean isPosOnBoard(Position pos) { @@ -63,20 +78,15 @@ public class Sequence { } return false; } + private static Integer getIDFromBoard(int[][] board, Position pos) { return new Integer(board[pos.getPosX()][pos.getPosY()]); } public String idString() { String s = ""; - for (Integer x: ids) { - if (x.intValue() == this.playerID) { - s += "M"; - } else if (x.intValue() == this.enemyID) { - s += "E"; - } else { - s += " "; - } + for (Item x: items) { + s += x.idString(playerID, enemyID); } return s; } diff --git a/src/player/malte/SequencesOrdered b/src/player/malte/SequencesOrdered new file mode 100644 index 0000000..502e42b --- /dev/null +++ b/src/player/malte/SequencesOrdered @@ -0,0 +1,14 @@ +1 XMMM // Vierter in der Reihe +1 MXMM +2 XEEE // Vierter beim Gegner +2 EXEE +3 _XMM_ // Sicherer Sieg nächste Runde +3 _MXM_ +4 _XEE_ // Sicherer Sieg des Gegners nächste Runde +4 _EXE_ +5 XMM_ // Möglicher Sieg nächste Runde +5 _XMM +5 MXM_ +6 XEE_ // Möglicher Sieg des Gegners in der nächsten Runde +6 _XEE +6 EXE_ \ No newline at end of file