private bool Search(int i, int j, enPiece test_piece, ref bool bIsFound) { //terminate search, since not on board if (i < 0 || i >= m_size || j < 0 || j >= m_size) { return(false); } enPiece piece = m_board[i, j]; //terminate search, since cell is empty if (piece == enPiece.Empty) { return(false); } //figure of the same color if (piece == test_piece) { bIsFound = true; return(false); } //continue return(true); }
//Calculate all possible moves //this is INTERNAL function //1. the move coordinates should be on the board //2. board cell should be empty // this function does not check these things!!! private bool IsMoveLegal(int move_x, int move_y, enPiece piece) { //All Game Logic is here bool bIsFound; int x, y, k; enPiece move_fig = piece; int nCount; for (k = 0; k < m_nTotalDir; k++) { x = move_x + dx[k]; y = move_y + dy[k]; nCount = 0; bIsFound = false; //move in that direction until (end of board || empty cell || same color figure) while (Search(x, y, move_fig, ref bIsFound)) { x += dx[k]; y += dy[k]; nCount++; } if (bIsFound && nCount != 0) { return(true); } } return(false); }
public Game(enPiece humanPlayer, int depth, bool bPerfectEnd) { m_bGameOver = false; m_HumanPlayer = humanPlayer; m_depth = depth; m_board = new Board(); m_vBoards = new LinkedList <Board>(); m_vComputerPlayers = new Dictionary <enPiece, ComputerPlayer>(); if (m_HumanPlayer == enPiece.Empty) { m_vComputerPlayers.Add(enPiece.White, new ComputerPlayerBalanced(enPiece.White, depth, 40, 16, 9, bPerfectEnd)); m_vComputerPlayers.Add(enPiece.Black, new ComputerPlayerBalanced(enPiece.Black, depth, 30, 16, 9, bPerfectEnd)); } else { enPiece piece = Board.FlipPiece(m_HumanPlayer); m_vComputerPlayers.Add(piece, new ComputerPlayerBalanced(piece, depth, 20, 1, 1, bPerfectEnd)); //m_vComputerPlayers.Add(piece, new ComputerPlayerMasked(piece, depth, bPerfectEnd)); //m_vComputerPlayers.Add(piece, new ComputerPlayerDeepSampler(piece)); } }
private bool MakeMove(Move move, bool bSaveBoard) { if (m_board.IsMoveLegal(move)) { //Save board before the move if (bSaveBoard) { m_vBoards.AddLast(new Board(m_board)); } //Make move m_board.MakeMove(move); //Change player m_current_player = Board.FlipPiece(m_current_player); //store gameover flag m_bGameOver = m_board.State.GameOver; //if game is not over but current player has no moves then change the current player if (!m_bGameOver && !m_board.HasMoves(m_current_player)) { m_current_player = Board.FlipPiece(m_current_player); } m_lastMove = move; return(true); } else { return(false); //no moves were made } }
private void aIGameToolStripMenuItem_Click(object sender, EventArgs e) { using (StreamWriter sw = new StreamWriter("ai.game.csv")) { sw.WriteLine(String.Format("{0}\t{1}\t{2}\t{3}\t{4}", "time", "count", "mobility_weight", "mask_weight", "count_weight")); System.Random rng = new Random(); for (int i = 0; i < 1; i++) { Dictionary <enPiece, ComputerPlayer> vComputerPlayers = new Dictionary <enPiece, ComputerPlayer>(); int mobility_weight = 41; int mask_weight = 4; int count_weight = 55; int total_weigth = mobility_weight + mask_weight + count_weight; vComputerPlayers[enPiece.White] = new ComputerPlayerBalanced(enPiece.White, 5, 20, 1, 1, true); // vComputerPlayers[enPiece.Black] = new ComputerPlayerMobility(enPiece.Black, 5); vComputerPlayers[enPiece.Black] = new ComputerPlayerMasked(enPiece.Black, 5, true); m_game = new Game(vComputerPlayers); int maxMoves = 60; int[] pos_delta = new int[maxMoves]; int[] mov_delta = new int[maxMoves]; int[] mask_score = new int[maxMoves]; int index = 0; while (!m_game.Over) { m_game.Play(); if (index < maxMoves) { pos_delta[index] = (m_game.CurrentBoard.CountPieces(enPiece.White) - m_game.CurrentBoard.CountPieces(enPiece.Black)); mov_delta[index] = (m_game.CurrentBoard.CountMoves(enPiece.White) - m_game.CurrentBoard.CountMoves(enPiece.Black)); //mask_score[index] = (vComputerPlayers[enPiece.Black].MaskBasedScore(m_game.CurrentBoard)); index++; } } enPiece winner = m_game.Winner; int white_count = m_game.CurrentBoard.CountPieces(enPiece.White); int black_count = m_game.CurrentBoard.CountPieces(enPiece.Black); StringBuilder sb = new StringBuilder(); sb.Append(String.Format("{0}\t{1}\t{2}\t{3}\t{4}\t", DateTime.Now, white_count - black_count, (double)mobility_weight / total_weigth, (double)mask_weight / total_weigth, (double)count_weight / total_weigth)); sb.Append("pos\t").Append(ListToString(pos_delta, "\t")); sb.Append("mov\t").Append(ListToString(mov_delta, "\t")); sb.Append("msk\t").Append(ListToString(mask_score, "\t")); sw.WriteLine(sb.ToString()); sw.Flush(); } } }
public ComputerPlayer(enPiece piece, int nDepth, bool bPerfectFinish) : base(piece) { m_nDepth = nDepth; m_timer = new HRTimer(); m_bPerfectFinish = bPerfectFinish; }
/// <summary> /// Reset to default /// </summary> public void Reset() { m_nDepth = 5; m_board_color = Color.FromArgb(32, 121, 16); m_hint_color = Color.FromArgb(16, 60, 8); m_last_move_color = Color.FromArgb(0, 200, 250); m_player = enPiece.White; m_bShowAvailableMoves = true; m_bShowLastMove = true; m_bPerfectEnding = true; }
public static enPiece FlipPiece(enPiece piece) { if (piece == enPiece.White) { return(enPiece.Black); } else if (piece == enPiece.Black) { return(enPiece.White); } else { return(piece); } }
public int CountPieces(enPiece piece) { int nCount = 0; for (int i = 0; i < m_size; i++) { for (int j = 0; j < m_size; j++) { if (m_board[i, j] == piece) { nCount++; } } } return(nCount); }
//check if there are any moves available public bool HasMoves(enPiece piece) { for (int i = 0; i < m_size; i++) { for (int j = 0; j < m_size; j++) { if (m_board[i, j] == enPiece.Empty) { if (IsMoveLegal(i, j, piece)) { return(true); } } } } return(false); }
public ComputerPlayerMasked(enPiece piece, int nDepth, bool bPerfectFinish) : base(piece, nDepth, bPerfectFinish) { //mask table was taken from http://samsoft.org.uk/reversi/ //used by Microsoft in their reversi program //Sum of all elements is 352 m_vMask = new int[, ] { { 99, -8, 8, 6, 6, 8, -8, 99 }, { -8, -24, -4, -3, -3, -4, -24, -8 }, { 8, -4, 7, 4, 4, 7, -4, 8 }, { 6, -3, 4, 0, 0, 4, -3, 6 }, { 6, -3, 4, 0, 0, 4, -3, 6 }, { 8, -4, 7, 4, 4, 7, -4, 8 }, { -8, -24, -4, -3, -3, -4, -24, -8 }, { 99, -8, 8, 6, 6, 8, -8, 99 }, }; }
//count available moves public int CountMoves(enPiece piece) { int nCount = 0; for (int i = 0; i < m_size; i++) { for (int j = 0; j < m_size; j++) { if (m_board[i, j] == enPiece.Empty) { if (IsMoveLegal(i, j, piece)) { nCount++; } } } } return(nCount); }
public List <Move> GetAvailableMoves(enPiece piece) { List <Move> vMoves = new List <Move>(); for (int i = 0; i < m_size; i++) { for (int j = 0; j < m_size; j++) { if (m_board[i, j] == enPiece.Empty) { if (IsMoveLegal(i, j, piece)) { vMoves.Add(new Move(i, j, piece)); } } } } return(vMoves); }
private void UpdatedStatus() { if (m_game.Over) { enPiece winner = m_game.Winner; if (winner != enPiece.Empty) { this.toolStripStatusLabel1.Text = winner.ToString() + " won!"; } else { this.toolStripStatusLabel1.Text = "the game is a draw!"; } //Save finished game if (!m_statistics.Games.ContainsValue(m_game) && !m_game.Saved) { m_statistics.Games.Add(DateTime.Now, m_game); m_game.Saved = true; //this.backgroundWorker1.RunWorkerAsync(); } } else { this.toolStripStatusLabel1.Text = "Next Move: " + m_game.CurrentPlayer.ToString(); } string score = String.Empty; score += " White: " + m_game.CurrentBoard.CountPieces(enPiece.White) + " "; score += " Black: " + m_game.CurrentBoard.CountPieces(enPiece.Black) + " "; this.toolStripStatusLabel1.Text += " (" + score + ")"; }
public ComputerPlayerCount(enPiece piece, int nDepth, bool bPerfectFinish) : base(piece, nDepth, bPerfectFinish) { }
private int minimax_ab_advanced(Node node, int nAlpha, int nBeta) { node.alpha = nAlpha; node.beta = nBeta; BoardState state = node.board.State; //check if this is the last node if (node.depth > m_nMinMaxDepth || state.GameOver) { m_nMinMaxCount++; return(GetHeuristic(node.board, state)); } else { //if node is white and there are no moves for white change node to black if (node.max && !state.WhiteMoves) { node.max = false; } //if node is black and there are no moves for black change node to white if (!node.max && !state.BlackMoves) { node.max = true; } //calculate all posible moves int nResult; //Create new node and copy all node moves Node new_node; new_node.depth = node.depth + 1; new_node.alpha = node.alpha; new_node.beta = node.beta; //Get Positions From the Board enPiece piece = node.max ? enPiece.White : enPiece.Black; List <Move> vMoves = node.board.GetAvailableMoves(piece); //Cycle over ALL new nodes foreach (Move move in vMoves) { new_node.max = !node.max; new_node.board = (Board)node.board.Clone(); new_node.board.MakeBlindMove(move); nResult = minimax_ab_advanced(new_node, node.alpha, node.beta); if (node.max) { //max node Alpha = max(Alpha, Result) if (node.alpha < nResult) { node.alpha = nResult; } //Beta is the rating of the best move from min perspective //min will choose move with Beta thus if our Alpha is higher then he will never let us play this move if (node.beta <= node.alpha) { return(node.alpha); } } else { //min node Beta = min(Beta, Result) if (node.beta > nResult) { node.beta = nResult; } //Cut off if (node.beta <= node.alpha) { return(node.beta); } } }//end of cycle return(node.max ? node.alpha : node.beta); } }
public ComputerPlayerMobility(enPiece piece, int nDepth) : base(piece, nDepth, true) { }
public HumanPlayer(enPiece piece) : base(piece) { }
public ComputerPlayer(enPiece piece) : this(piece, 4, true) { }
public Player(enPiece piece) { m_piece = piece; }
public ComputerPlayer3rd(enPiece piece, int nDepth) : base(piece, nDepth, true) { }
public ComputerPlayerBalanced(enPiece piece) : this(piece, 4, 20, 1, 1, true) { }
public Move(Move move) { m_piece = move.m_piece; m_to = move.m_to; }
private void pictureBox1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; Rectangle rect = pictureBox1.DisplayRectangle; rect.Height--; rect.Width--; g.DrawRectangle(Pens.Black, rect); rect.Inflate(-m_nMargin, -m_nMargin); int nSize = m_game.CurrentBoard.Size; //show available moves if (m_settings.ShowAvailableMoves) { List <Move> vMoves = m_game.CurrentBoard.GetAvailableMoves(m_game.CurrentPlayer); foreach (Move move in vMoves) { g.FillRectangle(m_hint_brush, new Rectangle(rect.Left + move.To.X * m_nCellSize, rect.Top + move.To.Y * m_nCellSize, m_nCellSize, m_nCellSize)); } } //show pieces for (int i = 0; i < nSize; i++) { for (int j = 0; j < nSize; j++) { enPiece piece = m_game.CurrentBoard[i, j]; if (m_vPieceImage.ContainsKey(piece)) { Bitmap image = m_vPieceImage[piece]; g.DrawImage(image, rect.Left + i * m_nCellSize, rect.Top + j * m_nCellSize, image.Width, image.Height); } } } //show last move if (m_settings.ShowLastMove) { Move move = m_game.LastMove; if (move != null) { Rectangle last_move_rect = new Rectangle(rect.Left + move.To.X * m_nCellSize + 2, rect.Top + move.To.Y * m_nCellSize + 2, 5, 5); g.FillEllipse(m_last_move_brush, last_move_rect); g.DrawEllipse(Pens.Black, last_move_rect); } } //Draw Grid for (int i = 0; i <= nSize; i++) { g.DrawLine(Pens.Black, rect.Left + i * m_nCellSize, rect.Bottom, rect.Left + i * m_nCellSize, rect.Top); g.DrawLine(Pens.Black, rect.Left, rect.Top + i * m_nCellSize, rect.Right, rect.Top + i * m_nCellSize); } //Draw markers int[] vMarkers = new int[] { 2, 6 }; for (int i = 0; i < vMarkers.Length; i++) { for (int j = 0; j < vMarkers.Length; j++) { Rectangle marker_rect = new Rectangle(rect.Left + vMarkers[i] * m_nCellSize - 2, rect.Top + vMarkers[j] * m_nCellSize - 2, 4, 4); g.FillEllipse(m_marker_brush, marker_rect); g.DrawEllipse(Pens.Black, marker_rect); } } if (m_game.Over) { Font message_font = new Font(FontFamily.GenericSansSerif, 0.7f * (float)m_nCellSize, FontStyle.Bold); enPiece winner = m_game.Winner; string game_status = winner != enPiece.Empty ? (winner == m_game.HumanPlayer ? "You Won!" : "Computer Won!") : "the game is a draw!"; g.DrawString(game_status, message_font, Brushes.Red, rect.Left, rect.Top); } }
public Move(int i, int j, enPiece piece) : this(new Position(i, j), piece) { }
public Move(Position to, enPiece piece) { m_piece = piece; m_to = to; }
public ComputerPlayerRandom(enPiece piece) : base(piece, 1, false) { }
public ComputerPlayerCombination(enPiece piece, int depth) : base(piece, depth, false) { }