public static OthelloBoard CreateStartingBoard() { OthelloBoard board = new OthelloBoard(SquareState.Black); board.SetToStartingPosition(); return(board); }
public override PlayerResult GetMove(OthelloBoard board) { ArrayList moves = board.GetValidMoves(); int moveIndex = rand.Next(moves.Count); PlayerResult result = new PlayerResult(); result.Move = (OthelloMove)moves[moveIndex]; return(result); }
/* returns the difference of possible moves for the players */ private int Mobility(OthelloBoard board) { int ret = board.CountValidMoves(); board.CurrentPlayer = board.OtherPlayer; ret -= board.CountValidMoves(); board.CurrentPlayer = board.OtherPlayer; return(ret); }
public virtual object Clone() { OthelloBoard ret = new OthelloBoard(); ret._squares = (SquareState[, ]) this._squares.Clone(); ret.CurrentPlayer = this._currentPlayer; ret._playerSquares = this._playerSquares; ret._opponentSquares = this._opponentSquares; return(ret); }
/* Value of the X-squares */ private int XSquareValue(OthelloBoard board) { int ret = 0; const int XSquarePenalty = 10; if (board[0, 0] == SquareState.Empty) { if (board[1, 1] == board.CurrentPlayer) { ret -= XSquarePenalty; } else if (board[1, 1] == board.OtherPlayer) { ret += XSquarePenalty; } } if (board[7, 0] == SquareState.Empty) { if (board[6, 1] == board.CurrentPlayer) { ret -= XSquarePenalty; } else if (board[6, 1] == board.OtherPlayer) { ret += XSquarePenalty; } } if (board[0, 7] == SquareState.Empty) { if (board[1, 6] == board.CurrentPlayer) { ret -= XSquarePenalty; } else if (board[1, 6] == board.OtherPlayer) { ret += XSquarePenalty; } } if (board[7, 7] == SquareState.Empty) { if (board[6, 6] == board.CurrentPlayer) { ret -= XSquarePenalty; } else if (board[6, 6] == board.OtherPlayer) { ret += XSquarePenalty; } } return(ret); }
protected override int GetBoardValue(OthelloBoard board) { int ret = 0; /************** X-SQUARE VALUE *******/ ret += XSquareValue(board); ret += SquareValue(board); /************** MOBILITY ***********/ ret += Mobility(board); return(ret); }
private void DoPostMoveProcessing(SquareState previousPlayerColor) { if (_board.GameOver) { MessageBox.Show("Game over! Black: " + _board.BlackSquares + " White: " + _board.WhiteSquares); } else if (_board.CurrentPlayer == previousPlayerColor) { MessageBox.Show("No moves for " + OthelloBoard.ColorNameFromSquareState( _board.OtherPlayer)); } PlayNextMove(); }
private int SquareValue(OthelloBoard board) { int ret = 0; const int SquarePenalty = 10; if (board[0, 0] == board.CurrentPlayer) { ret += SquarePenalty; } else if (board[0, 0] == board.OtherPlayer) { ret -= SquarePenalty; } if (board[7, 0] == board.CurrentPlayer) { ret += SquarePenalty; } else if (board[7, 0] == board.OtherPlayer) { ret -= SquarePenalty; } if (board[0, 7] == board.CurrentPlayer) { ret += SquarePenalty; } else if (board[0, 7] == board.OtherPlayer) { ret -= SquarePenalty; } if (board[7, 7] == board.CurrentPlayer) { ret += SquarePenalty; } else if (board[7, 7] == board.OtherPlayer) { ret -= SquarePenalty; } return(ret); }
public Game() { this.DataContext = this; p1 = new Player(0, NAME_PLAYER_1, new BitmapImage(uriWhite)); p2 = new Player(1, NAME_PLAYER_2, new BitmapImage(uriBlack)); this.board = new OthelloBoard("Board", BOARD_WIDTH, BOARD_HEIGHT); //TODO : Change name dynamically, using save name ! stackUndo = new Stack <Tuple <int[], bool> >(); stackRedo = new Stack <Tuple <int[], bool> >(); InitializeComponent(); GridGeneration(BOARD_HEIGHT, BOARD_WIDTH); UpdateScore(); initTimer(); }
public static OthelloBoard LoadFromFile(string path) { StreamReader reader = new StreamReader(path); string s = reader.ReadLine(); SquareState currentPlayer = SquareStateFromChar(s[0]); OthelloBoard ret = new OthelloBoard(currentPlayer); for (int y = 0; y < 8; y++) { s = reader.ReadLine(); for (int x = 0; x < 8; x++) { ret[x, y] = SquareStateFromChar(s[x]); } } reader.Close(); return(ret); }
public override bool Equals(object o) { OthelloBoard other = (OthelloBoard)o; if (other.CurrentPlayer != this.CurrentPlayer) { return(false); } for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { if (other[x, y] != this[x, y]) { return(false); } } } return(true); }
public Game(int[] values, bool isWhiteTurn, long timeSaveWhite, long timeSaveBlack, Stack <Tuple <int[], bool> > stackUndo, Stack <Tuple <int[], bool> > stackRedo) { this.DataContext = this; p1 = new Player(0, NAME_PLAYER_1, new BitmapImage(uriWhite)); p2 = new Player(1, NAME_PLAYER_2, new BitmapImage(uriBlack)); this.board = new OthelloBoard("Board", BOARD_WIDTH, BOARD_HEIGHT, values, isWhiteTurn); this.isWhiteTurn = isWhiteTurn; this.timeSaveWhite = timeSaveWhite; this.timeSaveBlack = timeSaveBlack; this.stackUndo = stackUndo; this.stackRedo = stackRedo; InitializeComponent(); GridGeneration(BOARD_HEIGHT, BOARD_WIDTH); UpdateScore(); initTimer(); }
public void SetBoard(OthelloBoard board) { _board = board; }
public abstract PlayerResult GetMove(OthelloBoard board);
static void ReadBook() { #if USE_TRANSPOSITION_TABLE StreamReader reader = null; try { reader = new StreamReader("book.txt"); } catch { // No opening book, oh well... return; } // Each line is a game, and looks like: +d3-c3+c4-e3+c2-b3+d2...-a5+a7-a8+b8-b7: -04 10 // -04 is the final score for black. 10 is always there and should be ignored for (int x = 0; ; x++) { string s = reader.ReadLine(); if (s == null) { break; } OthelloBoard board = OthelloBoard.CreateStartingBoard(); int i; i = s.LastIndexOf(':'); int val = int.Parse(s.Substring(i + 2, 3)); if (val < 0) { val -= 500; } else if (val > 0) { val += 500; } // Only use the first 10 moves to limit size for (i = 0; i < (10 * 3); i += 3) { if (s[i] == ':') { break; } OthelloMove move = new OthelloMove((s[i + 1] - 'a'), (s[i + 2] - '1')); board.PlayMove(move); board.FixUpCurrentPlayer(); _transpositionTable.AddEntry(board.GetHashCode(), 60 /*ply*/, (board.CurrentPlayer == SquareState.Black) ? val : -val, TranspositionTableElementType.Exact, -1, -1); move = null; } board.FixUpCurrentPlayer(); /* * int expectedVal = board.BlackSquares - board.WhiteSquares; * Debug.Assert(val == expectedVal); * Debug.Assert(board.GameOver); */ board = null; } reader.Close(); #endif }
private int GetBoardValueRecursive(OthelloBoard board, int ply, int notStuck, int alpha, int beta) { //MyTrace(ply, "left="+board.EmptySquares+" alpha="+alpha+" beta="+beta); /* If the game is over */ if (notStuck == 0 || board.EmptySquares == 0) { _finalEvaluations++; int squareDifference = board.PlayerSquares - board.OpponentSquares; if (squareDifference > 0) { return(squareDifference + 1000); } if (squareDifference < 0) { return(squareDifference - 1000); } // Tie return(0); } #if USE_TRANSPOSITION_TABLE int moveToTryFirst_X = -1, moveToTryFirst_Y = -1; bool needToTryFirstMove = false; int boardHashCode = board.GetHashCode(); int transpositionValue = _transpositionTable.LookupEntry(boardHashCode, ply, alpha, beta, ref moveToTryFirst_X, ref moveToTryFirst_Y); if (transpositionValue != AlphaBetaOthelloPlayer.INVALID_MOVE) { _transpositionHits++; return(transpositionValue); } if (moveToTryFirst_X >= 0) { needToTryFirstMove = true; } TranspositionTableElementType elementType = TranspositionTableElementType.Alpha; OthelloMoveWithData bestMove = null; #endif if (ply == 0) { _boardEvaluations++; int val = GetBoardValue(board); #if USE_TRANSPOSITION_TABLE _transpositionTable.AddEntry(boardHashCode, 0, val, TranspositionTableElementType.Exact, -1, -1); #endif return(val); } int count = 0; for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { OthelloMoveWithData move; #if USE_TRANSPOSITION_TABLE if (needToTryFirstMove) { move = board.GetMoveInfoIfValid(moveToTryFirst_X, moveToTryFirst_Y); needToTryFirstMove = false; // Set x to -1 to make sure that (0,0) gets process next time around x = -1; // This could happen if we found an incorrect entry in the table if (move == null) { continue; } } else { // Skip this move if we've already tried it if (x == moveToTryFirst_X && y == moveToTryFirst_Y) { continue; } move = board.GetMoveInfoIfValid(x, y); if (move == null) { continue; } } #else move = board.GetMoveInfoIfValid(x, y); if (move == null) { continue; } #endif count++; /* perform the move */ board.PlayMove(move); //MyTrace(ply, move.X + "," + move.Y + " alpha="+alpha+" beta="+beta); int val = (-GetBoardValueRecursive(board, ply - 1, 2, -beta, -alpha)); //MyTrace(ply, move.X + "," + move.Y + " alpha="+alpha+" beta="+beta+" val="+val); board.UnplayMove(move); if (val >= beta) { #if USE_TRANSPOSITION_TABLE _transpositionTable.AddEntry(boardHashCode, ply, beta, TranspositionTableElementType.Beta, move.X, move.Y); #endif return(BEST_MOVE); } if (val > alpha) { alpha = val; #if USE_TRANSPOSITION_TABLE elementType = TranspositionTableElementType.Exact; bestMove = move; #endif } } } if (count == 0) { /* if no possible move */ board.SwitchPlayer(); int val = -GetBoardValueRecursive(board, ply, notStuck - 1, -beta, -alpha); board.SwitchPlayer(); return(val); } #if USE_TRANSPOSITION_TABLE if (bestMove != null) { _transpositionTable.AddEntry(boardHashCode, ply, alpha, elementType, bestMove.X, bestMove.Y); } else { _transpositionTable.AddEntry(boardHashCode, ply, alpha, elementType, -1, -1); } #endif return(alpha); }
protected abstract int GetBoardValue(OthelloBoard board);
private void LoadGame_Click(object sender, System.EventArgs e) { _board = OthelloBoard.LoadFromFile("game.txt"); _lastPlayedMove = null; SyncBoardToUI(); }
private void CreateDefaultBoard() { _board = OthelloBoard.CreateStartingBoard(); }
public override PlayerResult GetMove(OthelloBoard board) { StringBuilder statusString = new StringBuilder();; _finalEvaluations = 0; _boardEvaluations = 0; #if USE_TRANSPOSITION_TABLE _transpositionHits = 0; _transpositionTable._wrongEntriesFound = 0; _transpositionTable._tooShallowEntriesFound = 0; #endif DateTime startTime = DateTime.Now; OthelloMoveWithData[] moves = board.GetValidMovesWithData(); MoveWithValue[] movesWithValue = new MoveWithValue[moves.Length]; for (int i = 0; i < moves.Length; i++) { movesWithValue[i] = new MoveWithValue(); movesWithValue[i].Move = moves[i]; } int currentPly; #if USE_ITERATIVE_DEEPENING for (currentPly = 0; ; currentPly++) { //for (currentPly = 0; currentPly<2; currentPly++) { #else for (int currentPly = ply - 1; currentPly < ply; currentPly++) { #endif statusString.Length = 0; DateTime startIterationTime = DateTime.Now; statusString.Append("Depth " + (currentPly + 1).ToString() + ": "); // Should we do a final search if (board.EmptySquares <= 15 && currentPly > 5) { currentPly = board.EmptySquares; } int alpha = WORST_MOVE; int beta = BEST_MOVE; foreach (MoveWithValue move in movesWithValue) { board.PlayMove(move.Move); statusString.Append(move.Move.ToString()); this.PostStatus(statusString.ToString()); move.Value = (-GetBoardValueRecursive(board, currentPly, 2, -beta, -alpha)); if (move.Value != BEST_MOVE && move.Value != WORST_MOVE) { statusString.Append("(" + move.Value.ToString() + ")"); } statusString.Append(" "); this.PostStatus(statusString.ToString()); board.UnplayMove(move.Move); if (move.Value > alpha) { alpha = move.Value; } if (alpha >= beta) { break; } } Array.Sort(movesWithValue); // If we've already search to the end, we're done if (currentPly == board.EmptySquares) { break; } if (movesWithValue[0].Value < -500 || movesWithValue[0].Value > 500) { break; } TimeSpan t = DateTime.Now - startTime; if (t.TotalSeconds >= 3) { break; } } PlayerResult result = new PlayerResult(); result.Move = movesWithValue[0].Move; TimeSpan processingTime = DateTime.Now - startTime; statusString.Append("\r\nEvals: " + _boardEvaluations + " Final evals: " + _finalEvaluations + "\r\n"); #if USE_TRANSPOSITION_TABLE /* * statusString.Append("Transp: " + _transpositionHits + * " wrong hits: " + _transpositionTable._wrongEntriesFound + * " shallow hits: " + _transpositionTable._tooShallowEntriesFound + "\r\n"); */ #endif statusString.Append("Score: " + movesWithValue[0].Value + " (" + processingTime + ")"); result.Status = statusString.ToString(); return(result); }