Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
sas12028 committed Apr 30, 2017
2 parents 54fca15 + 606c0b0 commit a7779ca
Show file tree
Hide file tree
Showing 10 changed files with 2,652 additions and 60 deletions.
2,276 changes: 2,276 additions & 0 deletions gamesAgainstOtherAGroup.txt

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/CheckersGameState.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ public interface CheckersGameState {
int winner();
void printState ();
public double[] getFeatures(int player);
public boolean isEndGame();
public double[] getEndGameFeatures(int player);
}
90 changes: 53 additions & 37 deletions src/CheckersGameState3.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import java.util.List;
import java.util.LinkedList;
import java.util.ArrayList;

public class CheckersGameState3 implements CheckersGameState{

Expand Down Expand Up @@ -388,9 +389,9 @@ else if(player == 2){

/* computes feature vector:
[0: piece-ratio,
1: loners,
2: safes,
3: 1*#pawns+ 2*#kings
1: loners, //toss?
2: safes, /toss?
3: 1*#pawns+ 2*#kings //toss?
4: # of moveable pawns + 2*#of moveable kings
5: aggregate distance of all pawns to promotion line
6: promotion line opening
Expand All @@ -399,6 +400,9 @@ else if(player == 2){
9: central pieces
10: # pawns on diagonal + 2 * # kings on diagonal
11: ^ same but for the two smaller diagonals
12: bridge pattern TODO!!!
13: triangle pattern TODO
14: dog pattern TODO, also take out useless features
]
*/
private boolean king(int piece){
Expand Down Expand Up @@ -452,53 +456,53 @@ else if(this.board[i] == player+2){

/* computes feature vector:
[0: piece-ratio,
1: # of moveable pawns + 2*#of moveable kings
2: num attacking pieces
3: central pieces
4: # pawns on diagonal + 2 * # kings on diagonal
5: bridge pattern
6: triangle pattern
7: dog pattern
8: opponents kings are on the side.
1: num attacking pieces
2: dist to oppon
]
*/
public double[] getEndGameFeatures(int player){
double[] features = new double[9];
double[] features = new double[3];
double total = 0.0;
double mypieces = 0.0;
ArrayList<Integer> mykingloc = new ArrayList<Integer>();
ArrayList<Integer> opponpieceloc = new ArrayList<Integer>();
for(int i = 0; i<this.board.length; i++){
if(i%9!=8){ //valid square
if(this.board[i] != 0 ) total+=1.0;
/****my pieces (pawns and kings)*****/
if(myPiece(this.board[i], player)){
mypieces+=1.0;
/*****pawns features****/
if(this.board[i] == player){
if(pawn_can_move(i)) features[1] += 1.0; //moveable pawns
if(i == 10 || i == 11 || i == 14 || i == 15 || i == 19 || i == 20 || i == 23 || i ==24){
features[3] +=1.0; //central pawns
}
}
/****kings features****/
else if(this.board[i] == player+2){
if(king_can_move(i)) features[1] += 2.0; //add to aggregate distance of the kings
if(i == 10 || i == 11 || i == 14 || i == 15 || i == 19 || i == 20 || i == 23 || i ==24){
features[3] +=2.0; //central kings
if(this.board[i] != 0 ) {
total+=1.0;
if(myPiece(this.board[i], player)){
mypieces+=1.0;
if(this.board[i] == player+2){ //king
mykingloc.add(i);
}
}
else{
opponpieceloc.add(i);
}
}
}
}
}
features[0] = mypieces/total; //piece ratio
features[2] = numAttacking(player);
features[4] = numOnDiag1(player) + numOnDiag2(player);
features[5] = bridge(player);
features[6] = triangle(player);
features[7] = dog(player);
features[8] = opponKingsOnSide(player);
features[1] = numAttacking(player);
features[2] = distToOppon(mykingloc, opponpieceloc);
return features;
}

/* takes in list of all my and all my opponent's pieces locations on the board
and returns an accumulative sum of the distances between our pieces*/
private double distToOppon(ArrayList<Integer> myloc, ArrayList<Integer> opploc){
int myrow, opprow;
int sum = 0;
for(int i = 0; i< myloc.size(); i++){
myrow = (myloc.get(i)-((myloc.get(i))/9))/4;
for(int j=0; j< opploc.size(); j++){
opprow = (opploc.get(j)-((opploc.get(j))/9))/4;
sum += Math.abs(myrow - opprow);
}
}
return sum * 1.0;
}

/* number of pawns and kings on the long diagonal*/
public int numOnMainDiag(int player){
int count = 0;
Expand Down Expand Up @@ -626,7 +630,7 @@ else if(player == 2){
}
return 0.0;
}
/* feature: triangle patter*/
/* feature: triangle pattern*/
public double triangle(int player){
if(player==2){
if((this.board[33]==2 || this.board[33]==4)
Expand Down Expand Up @@ -682,7 +686,19 @@ public int numPieces(int player){
return tot;
}


public boolean isEndGame(){
int mypieces = 0, others = 0, maxPieces =3;
for(int i=0; i<board.length; i++){
if(board[i]!=0){
if(myPiece(board[i],player)) mypieces+=1;
else others+=1;
}
}
if(mypieces <= maxPieces || others <= maxPieces){
return true;
}
else return false;
}

public void printState(){
boolean leading = false;
Expand Down
63 changes: 45 additions & 18 deletions src/Learn.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import java.util.Random;

public class Learn{
CheckersAI alpha;
CheckersAI beta;
LearningEvaluator le;
LearningEvaluator endle;
BaseEvaluator be;
BaseEvaluator endbe;

public static void main(String[] args){
LearningEvaluator le = new LearningEvaluator("../src/weights/alpha.csv");
BaseEvaluator be = new BaseEvaluator("../src/weights/beta.csv");
CheckersAI alpha = new CheckersAI(le, 1);
CheckersAI beta = new CheckersAI(be, 2);
learn(alpha, beta, le, be);

Learn learn = new Learn();
learn.learn();
}
public Learn(){
alpha = new CheckersAI(le, 1);
beta = new CheckersAI(be, 2);
le = new LearningEvaluator("../src/weights/alpha.csv");
be = new BaseEvaluator("../src/weights/beta.csv");
endle = new LearningEvaluator("../src/weights/endalpha.csv");
endbe = new BaseEvaluator("../src/weights/endbeta.csv");
}

// need to decide what to do if we are going on the wrong track
Expand All @@ -18,20 +28,23 @@ public static void main(String[] args){
// for draws, make function called is_improved that checks if piece count is greater than 4 (king is worth 2)
// for learning rate, first 30 with .1, next 30 with .05, then final 30 with .01 and see what happens

public static void learn(CheckersAI alpha, CheckersAI beta, LearningEvaluator le, BaseEvaluator be){
public void learn(){
final int num_games = 30;
final int iterations = 7;

Random rand = new Random();
for(int j = 0; j < iterations; j++){
for(int i = 1; i <= num_games; i++){ // play num_games amount of games
alpha.eval = le;
beta.eval = be;
System.out.println("playing game " + i);
int player = rand.nextInt(2) + 1; // choose which player alpha plays as
play(alpha, beta, le, player, true); // alpha and beta play a game
play(player, true); // alpha and beta play a game
le.updateWeights(learningParameter(i, num_games)); // get new weights using data from game
endle.updateWeights(learningParameter(i, num_games)); // get new weights using data from game
//le.updateWeights(.1); // get new weights using data from game
}
faceBeta(alpha, beta, le, be);
faceBeta();
}
}

Expand All @@ -46,33 +59,38 @@ public static double learningParameter(int played, int games){
}
}

public static void faceBeta(CheckersAI alpha, CheckersAI beta, LearningEvaluator le, BaseEvaluator be){
public void faceBeta(){
boolean w1;
boolean w2;
CheckersGameState s;
System.out.println("facing beta");
s = new CheckersGameState3();
w1 = play(alpha, beta, le, 1, false);
w2 = play(alpha, beta, le, 2, false);
w1 = play(1, false);
w2 = play(2, false);

System.out.println("alpha won " + w1 + " " + w2);
if(w1 && w2){
System.out.println("updating beta");
le.commitWeights("../src/weights/beta.csv");
endle.commitWeights("../src/weights/endbeta.csv");
be.refreshWeights();
endbe.refreshWeights();
}
else{
be.commitWeights("../src/weights/alpha.csv");
le.refreshWeights();
endbe.commitWeights("../src/weights/endalpha.csv");
endle.refreshWeights();
}



}



public static boolean play(CheckersAI alpha, CheckersAI beta, LearningEvaluator le, int player, boolean learning){
public boolean play(int player, boolean learning){
int min_ply = 7;
int incr_ply = 0;
boolean switchedToEndGame = false;
CheckersGameState current = new CheckersGameState3();
int other = 1 - (player - 1) + 1;
alpha.setPlayer(player);
Expand All @@ -86,23 +104,32 @@ public static boolean play(CheckersAI alpha, CheckersAI beta, LearningEvaluator
Move lastmove = null;
Move secondlast = null;
while(!current.isTerminal() && same_moves <= 3 && moves <= 200){
Move next = alpha.minimax(current, 7); // get alpha's move
if(current.isEndGame() && !switchedToEndGame){
switchedToEndGame = true;
alpha.eval = endle;
beta.eval = endbe;
min_ply += incr_ply;
}
Move next = alpha.minimax(current, min_ply); // get alpha's move
moves++;
if(secondlast != null && next.toString().equals(secondlast.toString())){
same_moves++;
}
secondlast = lastmove;
lastmove = next;
if(learning){
if(learning && !switchedToEndGame){
le.addData(current.getFeatures(alpha.getPlayer()), next.getValue()); // add this moves data to the data set (the value of the state is stored in the move. there is probably a better way to do this)
}
else if(learning && switchedToEndGame){
endle.addData(current.getEndGameFeatures(alpha.getPlayer()), next.getValue());
}
current = current.result(next); // make the move
moves++;
//current.printState();
if(current.isTerminal()){ // if alpha won, then break
break;
}
current = current.result(beta.minimax(current, 7)); // beta's move
current = current.result(beta.minimax(current, min_ply)); // beta's move

}
current.printState();
Expand Down
7 changes: 5 additions & 2 deletions src/LearningEvaluator.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import java.util.ArrayList;
import org.apache.commons.math3.stat.regression.OLSMultipleLinearRegression;
import org.apache.commons.math3.linear.SingularMatrixException;
import org.apache.commons.math3.exception.MathIllegalArgumentException;
import java.util.Arrays;

public class LearningEvaluator extends BaseEvaluator{
Expand Down Expand Up @@ -40,9 +41,9 @@ public void updateWeights(double alpha){
System.out.println(Arrays.toString(params.get(i)));
}
//System.out.println(pars);
reg.newSampleData(vals, pars); //add data
reg.setNoIntercept(true);
try {
reg.newSampleData(vals, pars); //add data
reg.setNoIntercept(true);
double[] new_weights = reg.estimateRegressionParameters(); //get parameters
for(double x: new_weights){
if(Math.abs(x) > 100000){
Expand All @@ -57,6 +58,8 @@ public void updateWeights(double alpha){
commitWeights(this.file);
} catch(SingularMatrixException e) {
System.out.println("Matrix was singular, not updating weights");
} catch(MathIllegalArgumentException e){
System.out.println("Not enough data, not updating end game weights");
}
values.clear();
params.clear();
Expand Down
10 changes: 7 additions & 3 deletions src/RmCheckersClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ public class RmCheckersClient {

public Evaluator e;
public CheckersAI ai;
public CheckersGameState currentState;
public CheckersGameState3 currentState;

public RmCheckersClient(){
_socket = openSocket();
//e = new Evaluator00();
e = new BaseEvaluator("weights/beta.csv");
e = new BaseEvaluator("weights/beta-hisotry.csv");
currentState = new CheckersGameState3();
user = _user1;
password = _password1;
Expand All @@ -63,7 +63,7 @@ public RmCheckersClient(){

public RmCheckersClient(int player, String opponent){
_socket = openSocket();
e = new BaseEvaluator("weights/beta.csv");
e = new BaseEvaluator("../src/weights/beta-history.csv");
currentState = new CheckersGameState3();
user = player==1 ? _user1 : _user2;
password = player==1 ? _password1 : _password2;
Expand Down Expand Up @@ -150,6 +150,7 @@ public static void main(String[] argv){

public void playGame(int player) {
int minPly = 8;
int maxPly = 15;
try {
String msg = readAndEcho(); // initial message
if(player == 1) { // black
Expand All @@ -161,6 +162,9 @@ else if(player == 2) { // white
readAndEcho(); // move query
}
while(currentState.actions().size()>0){
if(currentState.isEndGame() && minPly < maxPly){
minPly = maxPly;
}
currentState.printState();
Move myMove = ai.minimax(currentState, minPly);
writeMessageAndEcho(myMove.toString());
Expand Down
Loading

0 comments on commit a7779ca

Please sign in to comment.