ai advances

This commit is contained in:
Malte Tammena 2017-10-23 20:14:18 +02:00
parent 409d49ea8f
commit d75ac6e20d
4 changed files with 167 additions and 60 deletions

View file

@ -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;
}
}

View file

@ -74,14 +74,9 @@ public class MalteAI implements Player{
} }
public double calculateWeight(int[][] board, int column) { public double calculateWeight(int[][] board, int column) {
double W_START = 1.0; double W_ILLEGAL = Double.MIN_VALUE;
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 W_DONT = 0.01;
double weight = W_START; double weight = 1.0;
// Prever a place in the center; // Prever a place in the center;
weight *= 1.0 - Math.abs(3.0 - column) / (3.0 * 100.0); weight *= 1.0 - Math.abs(3.0 - column) / (3.0 * 100.0);
// Relative positions like (-1, -1), (0, -1), etc. // Relative positions like (-1, -1), (0, -1), etc.
@ -96,59 +91,112 @@ public class MalteAI implements Player{
// Setup Sequences // Setup Sequences
Sequence[] sequences = new Sequence[8]; Sequence[] sequences = new Sequence[8];
Sequence[] sequencesAbove = new Sequence[8]; Sequence[] sequencesAbove = new Sequence[8];
int[][] futureBoard = makeMove(copyBoard(board), column, this.id);
for (int i = 0; i < sequences.length; i++) { for (int i = 0; i < sequences.length; i++) {
sequences[i] = Sequence.readSequenceFromBoard(board, sequences[i] = Sequence.readSequenceFromBoard(board,
thisPos.add(relAround[i]), thisPos.add(relAround[i]),
relAround[i]); relAround[i],
this.id,
this.enemyID);
sequences[i].setPlayerID(this.id); sequences[i].setPlayerID(this.id);
sequences[i].setEnemyID(this.enemyID); sequences[i].setEnemyID(this.enemyID);
sequencesAbove[i] = Sequence.readSequenceFromBoard(board, sequencesAbove[i] = Sequence.readSequenceFromBoard(futureBoard,
thisPos.add(relAround[0]).add(relAround[i]), thisPos.add(relAround[0]).add(relAround[i]),
relAround[i]); relAround[i],
this.id,
this.enemyID);
sequencesAbove[i].setPlayerID(this.id); sequencesAbove[i].setPlayerID(this.id);
sequencesAbove[i].setEnemyID(this.enemyID); 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]; 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]; Sequence y = sequences[i + 4];
if ((x.matches("MM") && weight *= getBaseWeightForSequences(x, y);
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 xA = sequencesAbove[i]; Sequence xA = sequencesAbove[i];
if (xA.matches("EEE")) { Sequence yA = sequencesAbove[i + 4];
// Prevent choosing a bad spot // weight *= getBaseWeightForSequences(xA, yA);
weight *= W_DONT; if ((xA.matches("EEE") ||
} else if (xA.matches("MMM")) { yA.matches("EEE")) ||
// Open the opportunity ((xA.matches("E") &&
weight *= W_WIN; yA.matches("EE")) ||
(xA.matches("EE") &&
yA.matches("E")))) {
// TODO: Do this right!
weight /= 2<<6;
} }
} }
return weight; 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;
}
/** /**
* *
*/ */

View file

@ -9,12 +9,12 @@ public class Sequence {
private Position startingPos; private Position startingPos;
private Position direction; private Position direction;
private List<Integer> ids; private List<Item> items;
private int playerID; private int playerID;
private int enemyID; private int enemyID;
public Sequence(Position startingPos, Position direction, List<Integer> ids) { public Sequence(Position startingPos, Position direction, List<Item> items) {
this.ids = new ArrayList<Integer>(ids); this.items = new ArrayList<Item>(items);
this.startingPos = startingPos; this.startingPos = startingPos;
this.direction = direction; this.direction = direction;
} }
@ -35,7 +35,8 @@ public class Sequence {
return false; return false;
} }
if (s.charAt(i) == 'p' && if (s.charAt(i) == 'p' &&
idStr.charAt(i) == ' ') { (idStr.charAt(i) != 'm' &&
idStr.charAt(i) != 'e')) {
return false; return false;
} else if (s.charAt(i) != idStr.charAt(i)) { } else if (s.charAt(i) != idStr.charAt(i)) {
return false; return false;
@ -44,14 +45,28 @@ public class Sequence {
return true; 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; Position cur = pos;
List<Integer> ids = new ArrayList<Integer>(); List<Item> items = new ArrayList<Item>();
Position down = new Position(0, 1);
while (isPosOnBoard(cur)) { 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); 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) { private static boolean isPosOnBoard(Position pos) {
@ -63,20 +78,15 @@ public class Sequence {
} }
return false; return false;
} }
private static Integer getIDFromBoard(int[][] board, Position pos) { private static Integer getIDFromBoard(int[][] board, Position pos) {
return new Integer(board[pos.getPosX()][pos.getPosY()]); return new Integer(board[pos.getPosX()][pos.getPosY()]);
} }
public String idString() { public String idString() {
String s = ""; String s = "";
for (Integer x: ids) { for (Item x: items) {
if (x.intValue() == this.playerID) { s += x.idString(playerID, enemyID);
s += "M";
} else if (x.intValue() == this.enemyID) {
s += "E";
} else {
s += " ";
}
} }
return s; return s;
} }

View file

@ -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_