From 0b69e9671e24090df24ab4aa568945f26ebba4ae Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Sat, 21 Oct 2017 20:27:52 +0200 Subject: [PATCH 01/11] File changes --- Makefile | 4 +- src/player/malte/Item.java | 109 -------------- src/player/malte/MalteAI.java | 122 +-------------- src/player/malte/Pattern.java | 197 ------------------------- src/player/malte/PatternGenerator.java | 138 ----------------- 5 files changed, 7 insertions(+), 563 deletions(-) delete mode 100644 src/player/malte/Item.java delete mode 100644 src/player/malte/Pattern.java delete mode 100644 src/player/malte/PatternGenerator.java diff --git a/Makefile b/Makefile index 8015138..55f771b 100644 --- a/Makefile +++ b/Makefile @@ -19,9 +19,7 @@ src/game/PlayerObject.java \ src/player/Player.java \ src/player/Human.java \ src/player/malte/MalteAI.java \ -src/player/malte/Pattern.java \ -src/player/malte/Item.java \ -src/player/malte/PatternGenerator.java \ +src/player/malte/Position.java \ src/player/maurizio/MaurizioAI.java OBJECTS=$($(subst $(CLASSPATH),$(BUILDS),$(CLASSES)):.java=.class) diff --git a/src/player/malte/Item.java b/src/player/malte/Item.java deleted file mode 100644 index e28e1cb..0000000 --- a/src/player/malte/Item.java +++ /dev/null @@ -1,109 +0,0 @@ -package player.malte; - -/** - * An item of a pattern for the game of Connect Four. - */ -public class Item { - - /** - * The relative horizontal position of the item. - */ - private int posX; - - /** - * The relative vertical position of the item. - */ - private int posY; - - /** - * The IDs this item recognizes valid. - */ - private int[] ids; - - /** - * Basic constructor. - * - * @param posX Relative horizontal position. - * @param posY Relative vertical position. - * @param The accepted id. - */ - public Item(int posX, int posY, int id) { - this(posX, posY, new int[]{id}); - } - - /** - * Basic constructor for multiple IDs. - * - * @param posX Relative horizontal position. - * @param posY Relative vertical position. - * @param The accepted IDs. - */ - public Item(int posX, int posY, int[] ids) { - this.posX = posX; - this.posY = posY; - this.ids = ids; - } - - public int getPosX() { - return this.posX; - } - - public int getPosY() { - return this.posY; - } - - public int[] getIDs() { - return this.ids; - } - - public boolean hasID(int id) { - for (int i: ids) { - if (i == id) { - return true; - } - } - return false; - } - - /** - * Changes the given oldID to the newID. - * If newID already exists, do nothing. - * IF oldID does not exist, do nothing. - * - * @param oldID The ID to be replaced. - * @param newID The new ID. - */ - public void changeID(int oldID, int newID) { - // If the ID already exists, do nothing. - for (int id: ids) { - if (id == newID) { - return; - } - } - // Otherwise replace it, if oldID exists. - for (int i = 0; i < ids.length; i++) { - if (ids[i] == oldID) { - ids[i] = newID; - return; - } - } - } - - @Override - public String toString() { - String s = String.format("(%d, %d, [", posX, posY); - for (int i: ids) { - s += i + " "; - } - return s + "])"; - } - - /** - * Returns a deep copy of the item. - * - * @return A deep copy of this element. - */ - public Item copy() { - return new Item(posX, posY, ids); - } -} diff --git a/src/player/malte/MalteAI.java b/src/player/malte/MalteAI.java index 2116dab..9fcab0d 100644 --- a/src/player/malte/MalteAI.java +++ b/src/player/malte/MalteAI.java @@ -55,67 +55,15 @@ public class MalteAI implements Player{ @Override public int move(int[][] board){ - // Create a set of all possible options. - Set options = new HashSet<>(Arrays.asList(0,1,2,3,4,5,6)); - // Remove impossible options. - for (Integer i: copySet(options)) { - if (board[i][0] != 0) { - options.remove(i); - } + double[] weights = new double[Game.GAME_COLUMNS]; + for (int i = 0; i < weights.length; i++) { + weights[i] = calculateWeight(board, i); } - // Get options which would lead to instant win. - Set winningOptions = getRowCompletionOptions(options, board, id); - for (Integer i: winningOptions) { - // System.out.println("Choose to win"); - return i.intValue(); - } - // Get options which would prevent an instant win of the enemy. - Set preventionsOptions = getRowCompletionOptions(options, board, enemyID); - for (Integer i: preventionsOptions) { - // System.out.println("Choose to prevent"); - return i.intValue(); - } - // Choose a move that will continue a sequence that already exists. - Set twoOfFour = getTwoOfFourOptions(options, board, id); - for (Integer i: twoOfFour) { - // System.out.println("Choose to progress"); - return i.intValue(); - } - // Choose a move that will not lead to an instant win of the enemy - Set choosewisely = new HashSet<>(options); - while (choosewisely.size() > 0){ - Integer i = takeRandom(choosewisely); - choosewisely.remove(i); - int[][] fakeBoard = makeMove(copyBoard(board), i, id); - if (getRowCompletionOptions(options, fakeBoard, enemyID).size() == 0) { - // System.out.println("Choose random but smart"); - return i.intValue(); - } - } - // If nothing applies, take a random valied one. - // System.out.println("Choose random and stupid"); - return takeRandom(options).intValue(); + return 0; } - private Set getTwoOfFourOptions(Set options, int[][] board, int id) { - Set twoOfFourPattern = PatternGenerator.winInTwoPatterns(id); - // Get patterns, that match anywhere on the board. - Set matches = Pattern.matchingPatterns(twoOfFourPattern, board); - // Create set to be returned. - Set ret = new HashSet<>(); - // Iterate over all matches. - for (Pattern p: matches) { - // Get all positions, this pattern matches. - Set positions = p.matches(board); - // Get empty spaces in the pattern. - for (Item i: p.getZeros()) { - // Add all options to the set. - for(Position pos: positions) { - ret.add(new Integer(i.getPosX() + pos.getPosX())); - } - } - } - return ret; + public double calculateWeight(int[][] board, int row) { + return 0.0; } /** @@ -160,64 +108,6 @@ public class MalteAI implements Player{ return board; } - /** - * Instant winning options. - * Returns a set of options for the player to choose from. If any one is choosen and - * played by the player with the given id, a win is certain. - * - * @param options The options, that are valid, a subset is returned. - * @param board The current game's board. - * @param id The players id. - * @return A subset of options which would lead to a win. - */ - private Set getRowCompletionOptions(Set options, int[][] board, int id) { - // Get winning patterns from Generator. - Set pats = PatternGenerator.winningPatterns(id); - // Get patterns, that match anywhere on the board. - Set matches = Pattern.matchingPatterns(pats, board); - // Create set to be returned. - Set ret = new HashSet<>(); - // Iterate over all matches. - for (Pattern p: matches) { - // Get all positions, this pattern matches. - Set positions = p.matches(board); - // Get empty spaces in the pattern. - for (Item i: p.getZeros()) { - // Add all options to the set. - for(Position pos: positions) { - ret.add(new Integer(i.getPosX() + pos.getPosX())); - } - } - } - return ret; - } - - /** - * Copies a set of Integer. - */ - private Set copySet(Set s) { - return new HashSet(s); - } - - /** - * Takes a random Integer from a set of Integer. - * - * @param s The set to take from. - * @return A random element of s. - */ - private Integer takeRandom(Set s) { - int item = ran.nextInt(s.size()); - int i = 0; - for (Object obj: s) { - if (i == item) { - return (Integer) obj; - } - i++; - } - // TODO: Change this - return 0; - } - /** * Get the player's name. */ diff --git a/src/player/malte/Pattern.java b/src/player/malte/Pattern.java deleted file mode 100644 index af3a129..0000000 --- a/src/player/malte/Pattern.java +++ /dev/null @@ -1,197 +0,0 @@ -package player.malte; - -import java.util.Set; -import java.util.HashSet; -import java.util.Arrays; - -import game.Game; - -/** - * A Connect Four Pattern. - * Every part has a relative position and a number of IDs that it matches. - * When Pattern.matches(int[][]) is called, all possible positions on the board - * are checked against every part of the pattern. If all parts match, the whole - * pattern matches. - */ -public class Pattern { - - /** - * The parts of the pattern. - */ - private Set parts; - - /** - * Constructor. - * - * @param parts The parts of the pattern. - */ - public Pattern(Item... parts) { - this.parts = new HashSet(Arrays.asList(parts)); - } - - /** - * Constructor. - * - * @param parts The parts of the pattern. - */ - public Pattern(Set parts) { - this.parts = parts; - } - - /** - * Returns the matching positions. - * Checks the given board for matches. The positions of the matches are returned. - * - * @param board The game's board. - * @return The positions of the matches. - */ - public Set matches(int[][] board) { - // Preparing iteration - int maxLeft = 0, - maxRight = 0, - maxUp = 0, - maxDown = 0; - for (Item i: parts) { - if (i.hasID(-1)) { - continue; - } - if (maxLeft < -i.getPosX()) { - maxLeft = -i.getPosX(); - } - if (maxRight > -i.getPosX()) { - maxRight = -i.getPosX(); - } - if (maxUp < -i.getPosY()) { - maxUp = -i.getPosY(); - } - if (maxDown > -i.getPosY()) { - maxDown = -i.getPosY(); - } - } - // Iteration + Position accumulation - Set set = new HashSet<>(); - for (int i = maxLeft; i < Game.GAME_COLUMNS + maxRight; i++) { - inner:for (int j = maxUp; j < Game.GAME_ROWS + maxDown; j++) { - for (Item k: parts) { - int posX = i + k.getPosX(); - int posY = j + k.getPosY(); - if ((!isOnBoard(new Position(posX, posY)) && - !k.hasID(-1)) || - (isOnBoard(new Position(posX, posY)) && - !k.hasID(board[posX][posY]))) { - continue inner; - } - } - set.add(new Position(i, j)); - } - } - return set; - } - - /** - * Is the given position on the Board. - * - * @param pos The position to check. - * @return Whether the position is on the board. - */ - private boolean isOnBoard(Position pos) { - if (pos.getPosX() < 0 || - pos.getPosX() > Game.GAME_COLUMNS - 1 || - pos.getPosY() < 0 || - pos.getPosY() > Game.GAME_ROWS - 1) { - return false; - } - return true; - } - - /** - * Replaces a part of the Pattern. - * - * @param oldItem The part to be replaced. - * @param newItem The part to added. - */ - public void replaceItem(Item oldItem, Item newItem) { - if (this.parts.contains(oldItem)) { - this.parts.remove(oldItem); - this.parts.add(newItem); - } - } - - /** - * Adds a part to the pattern. - * - * @param part The new part. - */ - public void addItem(Item part) { - this.parts.add(part); - } - - /** - * Returns the zeros in this pattern. - * Returns a set of all parts which contain a zero in their valid IDs. - * - * @return The set of parts - */ - public Set getZeros() { - Set ret = new HashSet<>(); - for (Item i: parts) { - if (i.hasID(0)) { - ret.add(i); - } - } - return ret; - } - - /** - * Returns a deep copy of this pattern. - * - * @return This pattern... only copied. - */ - public Pattern copy() { - Set itemCopy = new HashSet<>(); - for (Item i: parts) { - itemCopy.add(i.copy()); - } - return new Pattern(itemCopy); - } - - /** - * Static matching method for a set of pattern. - * Returns a set of all positions any one pattern matches against. - * - * @param pats The patterns to match. - * @param board The board to match against. - */ - public static Set matches(Set pats, int[][] board) { - Set ret = new HashSet<>(); - for (Pattern p: pats) { - ret.addAll(p.matches(board)); - } - return ret; - } - - /** - * Returns the subset of all patterns, that do have a match on the board. - * - * @param pats The patterns to check. - * @param board The board to match against. - */ - public static Set matchingPatterns(Set pats, int[][] board) { - Set ret = new HashSet<>(); - for (Pattern p: pats) { - if (p.matches(board).size() > 0) { - ret.add(p); - } - } - return ret; - } - - @Override - public String toString() { - String s = ""; - for (Item i: parts) { - s += i + ", "; - } - return s + "\n"; - } -} diff --git a/src/player/malte/PatternGenerator.java b/src/player/malte/PatternGenerator.java deleted file mode 100644 index 5b34f2b..0000000 --- a/src/player/malte/PatternGenerator.java +++ /dev/null @@ -1,138 +0,0 @@ -package player.malte; - -import java.util.Set; -import java.util.HashSet; - -/** - * A generator for patterns for the game of Connect Four. - */ -public class PatternGenerator { - - /** - * Do not instanciate. - */ - private PatternGenerator() {} - - /** - * Returns the winning patterns. - * X | X | XXXX | X - * X | X | | X - * X | X | | X - * X | X | | X - * Any of the above with an empty space is considered a winning pattern. - * Except the first one, in which only the topmost space can be empty. - * - * @param id The player's id. - */ - public static Set winningPatterns(int id) { - // Four in a row with one hole - Set pats = PatternGenerator.emptySpaceGenerator(new Item(0, 0, id), - new Item(1, 0, id), - new Item(2, 0, id), - new Item(3, 0, id)); - // Four in a diagonal line from lower left to upper right with one hole - pats.addAll(PatternGenerator.emptySpaceGenerator(new Item(0, 0, id), - new Item(-1, 1, id), - new Item(-2, 2, id), - new Item(-3, 3, id))); - // Four in a diagonal line from upper left to lower right with one hole - pats.addAll(PatternGenerator.emptySpaceGenerator(new Item(0, 0, id), - new Item(1, 1, id), - new Item(2, 2, id), - new Item(3, 3, id))); - // Three on top of each other. - pats.add(new Pattern(new Item(0, 0, 0), - new Item(0, 1, id), - new Item(0, 2, id), - new Item(0, 3, id))); - return pats; - } - - public static Set winInTwoPatterns(int id) { - // Four in a row with two holes - Set pats = PatternGenerator.empty2SpaceGenerator(new Item(0, 0, id), - new Item(1, 0, id), - new Item(2, 0, id), - new Item(3, 0, id)); - // Four in a diagonal line from lower left to upper right with two holes - pats.addAll(PatternGenerator.empty2SpaceGenerator(new Item(0, 0, id), - new Item(-1, 1, id), - new Item(-2, 2, id), - new Item(-3, 3, id))); - // Four in a diagonal line from upper left to lower right with two holes - pats.addAll(PatternGenerator.empty2SpaceGenerator(new Item(0, 0, id), - new Item(1, 1, id), - new Item(2, 2, id), - new Item(3, 3, id))); - // Three on top of each other. - pats.add(new Pattern(new Item(0, 0, 0), - new Item(0, 1, id), - new Item(0, 2, id))); - return pats; - } - - /** - * Creates patterns with one empty space. - * Returns a set of patterns, each one containing an empty space. - * Each element of model is replaced once with an empty space Item. - * Always adds one support Item beneath the hole. - * - * @param model The basis of the pattern. - * @return A set of patterns created by the above rule. - */ - public static Set emptySpaceGenerator(Item... model) { - Set ret = new HashSet<>(); - // Iterate over all models. - for (int i = 0; i < model.length; i++) { - // Create a new pattern. - Pattern newP = new Pattern(model); - Item x = model[i]; - Item newI = new Item(x.getPosX(), x.getPosY(), 0); - // Replace one item with the new 0-one. - newP.replaceItem(x, newI); - // Add the support. - newP.addItem(new Item(x.getPosX(), x.getPosY() + 1, new int[]{-1, 1, 2})); - // Add the pattern to the set. - ret.add(newP); - } - return ret; - } - - /** - * Generates Patterns with two empty holes. - * Generates all possible patterns given the parts, which contain - * two empty spaces supported by two parts. - * - * @param model The pattern's basis. - * @return All possible patterns with two holes. - */ - public static Set empty2SpaceGenerator(Item... model) { - Set ret = new HashSet<>(); - // Iterate over all models. - for (int i = 0; i < model.length; i++) { - for (int j = 0; j < model.length; j++) { - // If we're looking at the same model, skip. - if (i == j) { - continue; - } - // Create a new Pattern with the models. - Pattern newP = new Pattern(model); - Item x = model[i]; - Item y = model[j]; - // Create new Items to replace two items. - Item newXI = new Item(x.getPosX(), x.getPosY(), 0); - Item newYI = new Item(y.getPosX(), y.getPosY(), 0); - // Actually replace them. - newP.replaceItem(x, newXI); - newP.replaceItem(y, newYI); - // Add support items. - newP.addItem(new Item(x.getPosX(), x.getPosY() + 1, new int[]{-1, 1, 2})); - newP.addItem(new Item(y.getPosX(), y.getPosY() + 1, new int[]{-1, 1, 2})); - // Add the pattern to the set. - ret.add(newP); - } - } - return ret; - } - -} From cbd763ac476c204eb3c1adf2166634e53d9da03e Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Sat, 21 Oct 2017 22:24:15 +0200 Subject: [PATCH 02/11] Implementing alternate ai --- src/player/malte/MalteAI.java | 106 ++++++++++++++++++++++++++++++++- src/player/malte/Position.java | 18 ++++++ 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/src/player/malte/MalteAI.java b/src/player/malte/MalteAI.java index 9fcab0d..2450240 100644 --- a/src/player/malte/MalteAI.java +++ b/src/player/malte/MalteAI.java @@ -4,6 +4,7 @@ import java.util.Random; import java.util.Set; import java.util.HashSet; import java.util.Arrays; +import java.lang.Math; import player.Player; import game.Game; @@ -59,13 +60,116 @@ public class MalteAI implements Player{ for (int i = 0; i < weights.length; i++) { weights[i] = calculateWeight(board, i); } - return 0; + double max = -1; + for (double d: weights) { + max = max > d ? max: d; + } + System.out.println(Arrays.toString(weights)); + for (int i = 0; i < weights.length; i++) { + if (Math.abs(max - weights[i]) < 0.01) { + return i; + } + } + return 0; } public double calculateWeight(int[][] board, int row) { + /* The amount of equal ideas, stretching out in star-like form. + * ^ ^ ^ + * \ | / + * 701 + * <-6X2-> + * 543 + * / | \ + * V V V + * ids contains the id of the direction. + */ + int[] nrs = new int[8]; + int[] ids = new int[8]; + Position[] relAround = Position.getRelCirclePositions(); + Position thisPos = getLastEmpty(board, row); + if (thisPos == null) { + return -1.0; + } + for (int i = 0; i < nrs.length; i++) { + Position curPos = thisPos.add(relAround[i]); + if (isPosOnBoard(curPos)) { + ids[i] = getIDFromBoard(board, curPos); + nrs[i] = countIDsInDir(board, ids[i], curPos, relAround[i]); + } else { + ids[i] = -1; + nrs[i] = -1; + } + } + for (int i = 0; i < 8; i++) { + if (ids[i] == this.id && + nrs[i] == 3) { + return 1.0; + } else if (ids[i] == this.enemyID && + nrs[i] == 3) { + return 0.9; + } + } + for (int i = 0; i < 4; i++) { + if (ids[i] == ids[i + 4]) { + if (nrs[i] + nrs[i + 4] > 3) { + if (ids[i] == this.id) { + return 1.0; + } else if (ids[i] == this.enemyID) { + return 0.9; + } + } + } + } return 0.0; } + /** + * + */ + private Position getLastEmpty(int[][] board, int column) { + if (board[column][0] != 0) { + return null; + } + int row = 0; + while (row < Game.GAME_ROWS - 1 && + board[column][row + 1] == 0) { + row++; + } + return new Position(column, row); + } + + /** + * + */ + private int countIDsInDir(int[][] board, int id, Position pos, Position dir) { + if (isPosOnBoard(pos) && + board[pos.getPosX()][pos.getPosY()] == id) { + return countIDsInDir(board, id, pos.add(dir), dir) + 1; + } + return 0; + } + + /** + * + */ + private boolean isPosOnBoard(Position pos) { + if (pos.getPosX() <= Game.GAME_COLUMNS - 1 && + pos.getPosX() >= 0 && + pos.getPosY() <= Game.GAME_ROWS - 1 && + pos.getPosY() >= 0) { + return true; + } + return false; + } + + /** + * + */ + private int getIDFromBoard(int[][] board, Position pos) { + return board[pos.getPosX()][pos.getPosY()]; + } + /** * Copies the given board. * diff --git a/src/player/malte/Position.java b/src/player/malte/Position.java index 3f28b12..54d559f 100644 --- a/src/player/malte/Position.java +++ b/src/player/malte/Position.java @@ -20,8 +20,26 @@ public class Position { return this.posY; } + public Position add(Position pos) { + return new Position(this.getPosX() + pos.getPosX(), + this.getPosY() + pos.getPosY()); + } + @Override public String toString() { return String.format("(%d, %d)", posX, posY); } + + public static Position[] getRelCirclePositions() { + return new Position[]{ + new Position(0, -1), + new Position(1, -1), + new Position(1, 0), + new Position(1, 1), + new Position(0, 1), + new Position(-1, 1), + new Position(-1, 0), + new Position(-1, -1) + }; + } } From 5d4815b73bd684c1c47bd70fa12ecc7755c1ebef Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Mon, 23 Oct 2017 11:57:15 +0200 Subject: [PATCH 03/11] Changed output format --- src/game/Game.java | 6 +++++- src/player/Human.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/game/Game.java b/src/game/Game.java index 81387b9..3f88ce6 100644 --- a/src/game/Game.java +++ b/src/game/Game.java @@ -301,7 +301,11 @@ public class Game { } System.out.println("|"); } - System.out.println(); + System.out.println("+-+-+-+-+-+-+-+"); + for (int i = 0; i < board.length; i++) { + System.out.print("|" + i); + } + System.out.println("|"); } public static boolean checkWin(int[][] board, int player){ diff --git a/src/player/Human.java b/src/player/Human.java index 84d792e..ad9e512 100644 --- a/src/player/Human.java +++ b/src/player/Human.java @@ -28,7 +28,7 @@ public class Human implements Player { } int choice = -1; while (!options.contains(new Integer(choice))) { - System.out.print("Choose a move from " + options + ": "); + System.out.println("Choose a move from " + options + ": "); choice = sc.nextInt(); } return choice; From 19bcbec099ee2ed7b81b81f23de75db488af27f2 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Mon, 23 Oct 2017 12:38:52 +0200 Subject: [PATCH 04/11] Ai advances --- src/player/malte/MalteAI.java | 66 +++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/src/player/malte/MalteAI.java b/src/player/malte/MalteAI.java index 2450240..70450eb 100644 --- a/src/player/malte/MalteAI.java +++ b/src/player/malte/MalteAI.java @@ -66,14 +66,18 @@ public class MalteAI implements Player{ } System.out.println(Arrays.toString(weights)); for (int i = 0; i < weights.length; i++) { - if (Math.abs(max - weights[i]) < 0.01) { + if (Math.abs(max - weights[i]) < 0.000001) { return i; } } return 0; } - public double calculateWeight(int[][] board, int row) { + public double calculateWeight(int[][] board, int column) { + double W_START = 1.0; + double W_ILLEGAL = -1.0; + double W_INSTANT_WIN = 2; + double W_PREVENT_INSTANT_WIN = 1.9; /* The amount of equal ideas, stretching out in star-like form. * ^ ^ ^ * \ | / @@ -86,42 +90,74 @@ public class MalteAI implements Player{ */ int[] nrs = new int[8]; int[] ids = new int[8]; + double weight = W_START; + // 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. Position[] relAround = Position.getRelCirclePositions(); - Position thisPos = getLastEmpty(board, row); + // The position we're looking at + Position thisPos = getLastEmpty(board, column); + // There is no space left in this row. if (thisPos == null) { - return -1.0; + weight *= W_ILLEGAL; + return weight; } + // Collect information about our surroundings. for (int i = 0; i < nrs.length; i++) { + // The postion around us we're collecting information from. Position curPos = thisPos.add(relAround[i]); + // Check whether this position is on the board at all. if (isPosOnBoard(curPos)) { + // Get the ID in this position. ids[i] = getIDFromBoard(board, curPos); + // Get the number of IDs in this direction. nrs[i] = countIDsInDir(board, ids[i], curPos, relAround[i]); } else { + // If not on board, -1 is the way to go. ids[i] = -1; nrs[i] = -1; } } - for (int i = 0; i < 8; i++) { - if (ids[i] == this.id && - nrs[i] == 3) { - return 1.0; - } else if (ids[i] == this.enemyID && - nrs[i] == 3) { - return 0.9; + // Look for problems/options in one direction at a time. + for (int i = 0; i < nrs.length; i++) { + if (nrs[i] == 3) { + if (ids[i] == this.id) { + // We can win like this! + weight *= W_INSTANT_WIN; + } else if (ids[i] == this.enemyID) { + // We can at least prevent him from winning. + weight *= W_PREVENT_INSTANT_WIN; + } } } - for (int i = 0; i < 4; i++) { + // Look for problems/options in two directions at a time. + for (int i = 0; i < nrs.length / 2; i++) { + // Same ID on opposite sides. if (ids[i] == ids[i + 4]) { + // Almost a finished row. if (nrs[i] + nrs[i + 4] > 3) { if (ids[i] == this.id) { - return 1.0; + // Its our ID. + weight *= W_INSTANT_WIN; } else if (ids[i] == this.enemyID) { - return 0.9; + // Its the enemy's ID. + weight *= W_PREVENT_INSTANT_WIN; } } } } - return 0.0; + // Maybe we get lucky TODO: Expand this. + int nrOfMyIDAround = 0; + int nrOfEnemyIDAround = 0; + for (int i = 0; i < ids.length; i++) { + if (ids[i] == this.id) { + nrOfMyIDAround++; + } else if (ids[i] == this.enemyID) { + nrOfEnemyIDAround++; + } + } + weight *= 1.0 + (nrOfEnemyIDAround + nrOfMyIDAround) / (8.0 * 10.0); + return weight; } /** From 8cab8c8deb884fc158888e1fcdfc4a6465e32a65 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Mon, 23 Oct 2017 13:44:42 +0200 Subject: [PATCH 05/11] Playing with the weights --- src/player/malte/MalteAI.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/player/malte/MalteAI.java b/src/player/malte/MalteAI.java index 70450eb..fd14a0e 100644 --- a/src/player/malte/MalteAI.java +++ b/src/player/malte/MalteAI.java @@ -147,16 +147,16 @@ public class MalteAI implements Player{ } } // Maybe we get lucky TODO: Expand this. - int nrOfMyIDAround = 0; - int nrOfEnemyIDAround = 0; + double extraWeight = 0.0; for (int i = 0; i < ids.length; i++) { if (ids[i] == this.id) { - nrOfMyIDAround++; + extraWeight += Math.pow(nrs[i], 2) * 2; } else if (ids[i] == this.enemyID) { - nrOfEnemyIDAround++; + extraWeight += Math.pow(nrs[i], 2); } } - weight *= 1.0 + (nrOfEnemyIDAround + nrOfMyIDAround) / (8.0 * 10.0); + extraWeight /= 10 * 126; + weight *= extraWeight + 1.0; return weight; } From 0c3623a45e083b3c70cf3312de44d35081e76158 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Mon, 23 Oct 2017 14:07:25 +0200 Subject: [PATCH 06/11] Switching to Sequence approach --- Makefile | 1 + src/player/malte/MalteAI.java | 29 +++++----------------- src/player/malte/Sequence.java | 45 ++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 23 deletions(-) create mode 100644 src/player/malte/Sequence.java diff --git a/Makefile b/Makefile index de9915b..6b5513d 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ src/player/Player.java \ src/player/Human.java \ src/player/malte/MalteAI.java \ src/player/malte/Position.java \ +src/player/malte/Sequence.java \ src/player/maurizio/MaurizioAI.java OBJECTS=$($(subst $(CLASSPATH),$(BUILDS),$(CLASSES)):.java=.class) diff --git a/src/player/malte/MalteAI.java b/src/player/malte/MalteAI.java index fd14a0e..b1aae36 100644 --- a/src/player/malte/MalteAI.java +++ b/src/player/malte/MalteAI.java @@ -78,18 +78,6 @@ public class MalteAI implements Player{ double W_ILLEGAL = -1.0; double W_INSTANT_WIN = 2; double W_PREVENT_INSTANT_WIN = 1.9; - /* The amount of equal ideas, stretching out in star-like form. - * ^ ^ ^ - * \ | / - * 701 - * <-6X2-> - * 543 - * / | \ - * V V V - * ids contains the id of the direction. - */ - int[] nrs = new int[8]; - int[] ids = new int[8]; double weight = W_START; // Prever a place in the center; weight *= 1.0 - Math.abs(3.0 - column) / (3.0 * 100.0); @@ -102,6 +90,12 @@ public class MalteAI implements Player{ weight *= W_ILLEGAL; return weight; } + // Setup Sequences + Sequence[] sequences = new Sequence[8]; + for (int i = 0; i < sequences.length; i++) { + sequences[i] = Sequence.readSequenceFromBoard(board, thisPos, relAround[i]); + } + // Collect information about our surroundings. for (int i = 0; i < nrs.length; i++) { // The postion around us we're collecting information from. @@ -175,17 +169,6 @@ public class MalteAI implements Player{ return new Position(column, row); } - /** - * - */ - private int countIDsInDir(int[][] board, int id, Position pos, Position dir) { - if (isPosOnBoard(pos) && - board[pos.getPosX()][pos.getPosY()] == id) { - return countIDsInDir(board, id, pos.add(dir), dir) + 1; - } - return 0; - } - /** * */ diff --git a/src/player/malte/Sequence.java b/src/player/malte/Sequence.java new file mode 100644 index 0000000..52d7e6b --- /dev/null +++ b/src/player/malte/Sequence.java @@ -0,0 +1,45 @@ +package player.malte; + +import java.util.List; +import java.util.ArrayList; + +import game.Game; + +public class Sequence { + + private Position startingPos; + private Position direction; + private List ids; + + public Sequence(List ids) { + this.ids = new ArrayList(ids); + } + + public static Sequence readSequenceFromBoard(int[][] board, Position pos, Position dir) { + Position cur = pos; + List ids = new ArrayList(); + while (isPosOnBoard(cur)) { + cur = cur.add(dir); + ids.add(getIDFromBoard(board, cur)); + } + return new Sequence(ids); + } + + private static boolean isPosOnBoard(Position pos) { + if (pos.getPosX() <= Game.GAME_COLUMNS - 1 && + pos.getPosX() >= 0 && + pos.getPosY() <= Game.GAME_ROWS - 1 && + pos.getPosY() >= 0) { + return true; + } + return false; + } + private static Integer getIDFromBoard(int[][] board, Position pos) { + return new Integer(board[pos.getPosX()][pos.getPosY()]); + } + + @Override + public String toString() { + return String.format("START: %s, DIR: %s, %s", startingPos, direction, ids); + } +} From 6394e2d3237efde85b8e6f93bbc052f0aa98038e Mon Sep 17 00:00:00 2001 From: Maurizio Bruetsch Date: Mon, 23 Oct 2017 14:40:40 +0200 Subject: [PATCH 07/11] removed unnecessary output --- src/player/Human.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/player/Human.java b/src/player/Human.java index 244523c..3d73f4f 100644 --- a/src/player/Human.java +++ b/src/player/Human.java @@ -36,7 +36,6 @@ public class Human implements Player { System.out.println("This is not a legal move!"); } } - System.out.println(choice); return choice; } From 8f984e653f37479ba71020029ba4561b2d941cc1 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Mon, 23 Oct 2017 15:13:54 +0200 Subject: [PATCH 08/11] Implemented sequences --- src/player/malte/MalteAI.java | 104 +++++++++++++++------------------ src/player/malte/Position.java | 2 +- src/player/malte/Sequence.java | 51 ++++++++++++++-- 3 files changed, 96 insertions(+), 61 deletions(-) diff --git a/src/player/malte/MalteAI.java b/src/player/malte/MalteAI.java index b1aae36..311efa2 100644 --- a/src/player/malte/MalteAI.java +++ b/src/player/malte/MalteAI.java @@ -74,11 +74,14 @@ public class MalteAI implements Player{ } public double calculateWeight(int[][] board, int column) { - double W_START = 1.0; - double W_ILLEGAL = -1.0; - double W_INSTANT_WIN = 2; - double W_PREVENT_INSTANT_WIN = 1.9; - double weight = W_START; + 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_DONT = 0.01; + double weight = W_START; // 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. @@ -92,65 +95,54 @@ public class MalteAI implements Player{ } // Setup Sequences Sequence[] sequences = new Sequence[8]; + Sequence[] sequencesAbove = new Sequence[8]; for (int i = 0; i < sequences.length; i++) { - sequences[i] = Sequence.readSequenceFromBoard(board, thisPos, relAround[i]); + sequences[i] = Sequence.readSequenceFromBoard(board, + thisPos.add(relAround[i]), + relAround[i]); + sequences[i].setPlayerID(this.id); + sequences[i].setEnemyID(this.enemyID); + sequencesAbove[i] = Sequence.readSequenceFromBoard(board, + thisPos.add(relAround[0]).add(relAround[i]), + relAround[i]); + sequencesAbove[i].setPlayerID(this.id); + sequencesAbove[i].setEnemyID(this.enemyID); } - - // Collect information about our surroundings. - for (int i = 0; i < nrs.length; i++) { - // The postion around us we're collecting information from. - Position curPos = thisPos.add(relAround[i]); - // Check whether this position is on the board at all. - if (isPosOnBoard(curPos)) { - // Get the ID in this position. - ids[i] = getIDFromBoard(board, curPos); - // Get the number of IDs in this direction. - nrs[i] = countIDsInDir(board, ids[i], curPos, relAround[i]); - } else { - // If not on board, -1 is the way to go. - ids[i] = -1; - nrs[i] = -1; - } - } - // Look for problems/options in one direction at a time. - for (int i = 0; i < nrs.length; i++) { - if (nrs[i] == 3) { - if (ids[i] == this.id) { - // We can win like this! + for (int i = 0; i < sequences.length; 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 (ids[i] == this.enemyID) { - // We can at least prevent him from winning. + } 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; } } - } - // Look for problems/options in two directions at a time. - for (int i = 0; i < nrs.length / 2; i++) { - // Same ID on opposite sides. - if (ids[i] == ids[i + 4]) { - // Almost a finished row. - if (nrs[i] + nrs[i + 4] > 3) { - if (ids[i] == this.id) { - // Its our ID. - weight *= W_INSTANT_WIN; - } else if (ids[i] == this.enemyID) { - // Its the enemy's ID. - weight *= W_PREVENT_INSTANT_WIN; - } - } + // Prevent choosing a bad spot + Sequence xA = sequencesAbove[i]; + if (sequencesAbove[i].matches("EEE")) { + weight *= W_DONT; } } - // Maybe we get lucky TODO: Expand this. - double extraWeight = 0.0; - for (int i = 0; i < ids.length; i++) { - if (ids[i] == this.id) { - extraWeight += Math.pow(nrs[i], 2) * 2; - } else if (ids[i] == this.enemyID) { - extraWeight += Math.pow(nrs[i], 2); - } - } - extraWeight /= 10 * 126; - weight *= extraWeight + 1.0; return weight; } diff --git a/src/player/malte/Position.java b/src/player/malte/Position.java index 54d559f..7f85d6a 100644 --- a/src/player/malte/Position.java +++ b/src/player/malte/Position.java @@ -27,7 +27,7 @@ public class Position { @Override public String toString() { - return String.format("(%d, %d)", posX, posY); + return String.format("(%+d, %+d)", posX, posY); } public static Position[] getRelCirclePositions() { diff --git a/src/player/malte/Sequence.java b/src/player/malte/Sequence.java index 52d7e6b..3700182 100644 --- a/src/player/malte/Sequence.java +++ b/src/player/malte/Sequence.java @@ -10,19 +10,48 @@ public class Sequence { private Position startingPos; private Position direction; private List ids; + private int playerID; + private int enemyID; - public Sequence(List ids) { + public Sequence(Position startingPos, Position direction, List ids) { this.ids = new ArrayList(ids); + this.startingPos = startingPos; + this.direction = direction; + } + + public void setPlayerID(int playerID) { + this.playerID = playerID; + } + + public void setEnemyID(int enemyID) { + this.enemyID = enemyID; + } + + public boolean matches(String s) { + String idStr = idString().toLowerCase(); + s = s.toLowerCase(); + for (int i = 0; i < s.length(); i++) { + if (i >= idStr.length()) { + return false; + } + if (s.charAt(i) == 'p' && + idStr.charAt(i) == ' ') { + return false; + } else if (s.charAt(i) != idStr.charAt(i)) { + return false; + } + } + return true; } public static Sequence readSequenceFromBoard(int[][] board, Position pos, Position dir) { Position cur = pos; List ids = new ArrayList(); while (isPosOnBoard(cur)) { - cur = cur.add(dir); ids.add(getIDFromBoard(board, cur)); + cur = cur.add(dir); } - return new Sequence(ids); + return new Sequence(pos, dir, ids); } private static boolean isPosOnBoard(Position pos) { @@ -38,8 +67,22 @@ public class Sequence { 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 += " "; + } + } + return s; + } + @Override public String toString() { - return String.format("START: %s, DIR: %s, %s", startingPos, direction, ids); + return String.format("START: %s, DIR: %s, \"%s\"", startingPos, direction, idString()); } } From 60d6668408319e4991c1a27d9e8f43faf7b87909 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Mon, 23 Oct 2017 15:16:15 +0200 Subject: [PATCH 09/11] Added sequence moves --- src/player/malte/MalteAI.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/player/malte/MalteAI.java b/src/player/malte/MalteAI.java index 311efa2..f3bac1d 100644 --- a/src/player/malte/MalteAI.java +++ b/src/player/malte/MalteAI.java @@ -137,10 +137,13 @@ public class MalteAI implements Player{ weight *= W_WIN; } } - // Prevent choosing a bad spot Sequence xA = sequencesAbove[i]; - if (sequencesAbove[i].matches("EEE")) { + if (xA.matches("EEE")) { + // Prevent choosing a bad spot weight *= W_DONT; + } else if (xA.matches("MMM")) { + // Open the opportunity + weight *= W_WIN; } } return weight; From d75ac6e20d24852bc6ebb81be79f8bb9313b1e3b Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Mon, 23 Oct 2017 20:14:18 +0200 Subject: [PATCH 10/11] ai advances --- src/player/malte/Item.java | 35 ++++++++ src/player/malte/MalteAI.java | 136 ++++++++++++++++++++---------- src/player/malte/Sequence.java | 42 +++++---- src/player/malte/SequencesOrdered | 14 +++ 4 files changed, 167 insertions(+), 60 deletions(-) create mode 100644 src/player/malte/Item.java create mode 100644 src/player/malte/SequencesOrdered 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 From ad9edad93f81ff047e1b9e3da64c45d099bfd162 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Tue, 24 Oct 2017 21:23:00 +0200 Subject: [PATCH 11/11] Removed output --- src/player/malte/MalteAI.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/player/malte/MalteAI.java b/src/player/malte/MalteAI.java index 697d9ad..e5a7141 100644 --- a/src/player/malte/MalteAI.java +++ b/src/player/malte/MalteAI.java @@ -64,7 +64,6 @@ public class MalteAI implements Player{ for (double d: weights) { max = max > d ? max: d; } - System.out.println(Arrays.toString(weights)); for (int i = 0; i < weights.length; i++) { if (Math.abs(max - weights[i]) < 0.000001) { return i; @@ -140,7 +139,6 @@ public class MalteAI implements Player{ 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") &&