ai advances
This commit is contained in:
parent
409d49ea8f
commit
d75ac6e20d
35
src/player/malte/Item.java
Normal file
35
src/player/malte/Item.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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")) {
|
Sequence y = sequences[i + 4];
|
||||||
weight *= W_INSTANT_WIN;
|
weight *= getBaseWeightForSequences(x, y);
|
||||||
} 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 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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
14
src/player/malte/SequencesOrdered
Normal file
14
src/player/malte/SequencesOrdered
Normal 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_
|
Loading…
Reference in a new issue