/* Extended by Lenny Volchok */ import java.applet.*; import java.awt.*; import java.awt.image.*; import java.net.*; import java.io.*; import java.util.*; public class OthelloNoisyEdgar extends OthelloPlayer { static final int WHITE = 1; // This is the "learning" that was done and will be used // to decide what to do in a particular situation double DecisionsValue[][][] = new double[60][8][8]; double DecisionsValueNumber[][][] = new double[60][8][8]; double DecisionsValueWeight[][][] = new double[60][8][8]; double DecisionsFlipWeight[][][] = new double[60][8][8]; int CornerPenalty; OthelloNoisyEdgar() { super(WHITE); // if (FirstTime) //{ /* ------------- Read in FinalWeights ---------------- */ try { //URL myURL = new URL(getDocumentBase(),"FinalWeights"); FileInputStream myStream = new FileInputStream("FinalWeights"); StreamTokenizer myTok = new StreamTokenizer(myStream); myTok.parseNumbers(); int counter = 0; do { myTok.nextToken(); if (myTok.ttype == myTok.TT_NUMBER) { double thisNum = myTok.nval; switch (counter % 5) { case 0: break; case 1: DecisionsValue[counter/(8*8*5)] [(counter/(5*8)) % 8] [(counter/5) % 8] = thisNum; break; case 2: DecisionsValueNumber[counter/(8*8*5)] [(counter/(5*8)) % 8] [(counter/5) % 8] = thisNum; break; case 3: DecisionsValueWeight[counter/(8*8*5)] [(counter/(5*8)) % 8] [(counter/5) % 8] = thisNum; break; case 4: DecisionsFlipWeight[counter/(8*8*5)] [(counter/(5*8)) % 8] [(counter/5) % 8] = thisNum; break; } counter++; } else { /* System.out.println("Read a string: " + myTok.sval + "at counter " + counter); */ } } while (myTok.ttype != myTok.TT_EOF); } catch (Exception e) {System.out.println("An Error Occured Reading the data file.");} /* ------------- Print out FinalWeights ---------------- */ CornerPenalty = ((int) DecisionsValue[0][0][0]); /* System.out.println("Corner Penalty is " + CornerPenalty); */ } public double evalMove(OthelloBoard board, Move move) { return (double)rankLEARNEDMove(WHITE, move.col(), move.row(), board); } /* Add randomness to this method */ public Move bestMove(OthelloBoard board) { Vector rankedMoves = rankMoves(board); int n = rankedMoves.size(); Move bestMove = (Move)rankedMoves.elementAt(n-1); if(n > 1){ int total = 0; int i; for(i=1; i<=n; i++){ total += i; } /* Get a random integer in the range 0 - total */ Random random = new Random(); int pos = random.nextInt(); if(pos < 0) pos = -pos; pos = pos % total; /* Add a bit more to the total, so the best move has a better probability */ // total = total*2; for(i=1; i<=n; i++){ total -= i; if(pos >= total){ bestMove = (Move)rankedMoves.elementAt(i-1); break; } } } return bestMove; } /* --------------------------------------------------*/ boolean SetUpForCorner(int color, int col, int row, OthelloBoard board) { int scoretemp[] = new int[3]; int boardtemp[][] = new int[9][9]; int opponent = OthelloBoard.BLACK + OthelloBoard.WHITE - color; boolean toreturn; scoretemp[OthelloBoard.BLACK] = board.score[OthelloBoard.BLACK]; scoretemp[OthelloBoard.WHITE] = board.score[OthelloBoard.WHITE]; for(int i = 0;i<9;i++) for(int j = 0;j<9;j++) boardtemp[i][j] = board.board[i][j]; board.FakemakeMove(color, col, row); if ((board.isLegalMove(opponent,1,1)) || (board.isLegalMove(opponent,1,8)) || (board.isLegalMove(opponent,8,1)) || (board.isLegalMove(opponent,8,8))) toreturn = true; else toreturn = false; board.score[OthelloBoard.BLACK] = scoretemp[OthelloBoard.BLACK]; board.score[OthelloBoard.WHITE] = scoretemp[OthelloBoard.WHITE]; for(int i = 0;i<9;i++) for(int j = 0;j<9;j++) board.board[i][j] = boardtemp[i][j]; return toreturn; } /* --------------------------------------------------*/ int rankLEARNEDMove (int color, int col, int row, OthelloBoard board) { int count = 0; int rowinc,colinc; double Value; double Flip; /* somebody's piece is already in this location */ if ((board.board[col][row] != OthelloBoard.EMPTY) && (board.board[col][row] != OthelloBoard.OKMOVE)) return 0; for (colinc = -1; colinc < 2; colinc++) for (rowinc = -1; rowinc < 2; rowinc++) count += board.flipRow(color, col, row, colinc, rowinc, false, false); if (count == 0) return count; Flip = ((double)count)*(DecisionsFlipWeight[board.GameTime][col-1][row-1]); Value = (DecisionsValue[board.GameTime][col-1][row-1])* (DecisionsValueWeight[board.GameTime][col-1][row-1]); Value = (Value + Flip); if (SetUpForCorner(color,col,row, board)) count = ((int)(Value * 10)) - CornerPenalty; else count = ((int)(Value * 200.0)); if (count == 0) count = 1; //System.out.println("Game Time = " + board.GameTime + " Column = " + col + " Row = " + row + " Value = " + count); return count; } /* --------------------------------------------------*/ }