/** Return a heuristic value for BOARD. This can be improved. */ private int StaticScore(Board board) { BoardStatus status = board.status; if (status == BoardStatus.Checkmate) { if (board.whoseTurn == PieceColor.White) { return(WIN_VALUE); } else { return(-WIN_VALUE); } } else if (status != BoardStatus.Playing) // AI shouldn't need to think about the promote state { return(0); } // TODO: quantify threats int score = 0; foreach (Square s in Square.squares) { PieceData?p = board.GetPiece(s); if (p == null) { continue; } PieceType type = p.Value.type; if (type == PieceType.King) { continue; } if (p.Value.color == PieceColor.White) { score += PIECE_VALUES[(int)type]; } else { score -= PIECE_VALUES[(int)type]; } } return(score); }
private IEnumerator <int?> FindMove(Board board, int depth, bool saveMove, bool max, int alpha, int beta) { BoardStatus status = board.status; if (depth == 0 || (status != BoardStatus.Playing)) // AI shouldn't need to think about the promote state { yield return(StaticScore(board)); yield break; } List <Move> moves = new List <Move>(board.legalMoves); if (saveMove) { Shuffle(moves); } if (max) { int bestVal = -INFINITY; foreach (Move move in moves) { board.MakeMove(move); int moveVal = 0; IEnumerator <int?> enumerator = FindMove(board, depth - 1, false, false, alpha, beta); yield return(null); while (enumerator.MoveNext()) { if (enumerator.Current != null) { moveVal = enumerator.Current.Value; } yield return(null); } bestVal = Math.Max(bestVal, moveVal); board.Undo(); if (bestVal > beta) // prune; black would never let this happen { yield return(bestVal); yield break; } if (bestVal > alpha) // this is the best option for white on the path to root (overall) { alpha = bestVal; if (saveMove) { foundMove = move; } } } yield return(bestVal); // the best (maximal) value for white from this board position (not necessarily overall) } else { int bestVal = INFINITY; foreach (Move move in moves) { board.MakeMove(move); int moveVal = 0; IEnumerator <int?> enumerator = FindMove(board, depth - 1, false, true, alpha, beta); yield return(null); while (enumerator.MoveNext()) { if (enumerator.Current != null) { moveVal = enumerator.Current.Value; } yield return(null); } bestVal = Math.Min(bestVal, moveVal); board.Undo(); if (bestVal < alpha) // prune; white would never let this happen { yield return(bestVal); yield break; } if (bestVal < beta) // this is the best option for black on the path to root (overall) { beta = bestVal; if (saveMove) { foundMove = move; } } } yield return(bestVal); // the best (minimal) value for black from this board position (not necessarily overall) } }