public double GetScore(IBoard board, PieceType player) { MatchRepository matchRepository; PatternBoard patternBoard = board as PatternBoard; if (patternBoard != null) { matchRepository = patternBoard.Matches; } else { var matches = this.matcher.MatchPatterns(board, positions.Lines); matchRepository = new MatchRepository(); foreach (var match in matches) { matchRepository.Add(match.Pattern.Player, match.Pattern.PatternType, match); } } double myScore = GetScore(player, matchRepository); double oScore = GetScore(player.GetOther(), matchRepository); var nextPlayer = board.Count % 2 == 0 ? PieceType.P1 : PieceType.P2; bool isMyTurn = player == nextPlayer; if (isMyTurn) { myScore *= 1.2; } else { oScore *= 1.2; } return(myScore - oScore); }
private AiSearchResult Search(bool isMaxSearch, IBoard board, PieceType curPlayer, int depth, double minPossibleScore, double maxPossibleScore) { if (depth >= maxDepth || board.IsFull() || HasWinner(board)) { this.leafCount++; // Return the score of current board. double score = scorer.GetScore(board, player); return(new AiSearchResult(score)); } PieceType otherPlayer = curPlayer.GetOther(); double worseScore = isMaxSearch ? minPossibleScore : maxPossibleScore; AiSearchResult bestMove = new AiSearchResult(worseScore); foreach (Position move in this.moveEnumerator.GetMoves(board, curPlayer)) { // Make a move. board.Set(move, curPlayer); // Search deeper moves. AiSearchResult result = Search(!isMaxSearch, board, otherPlayer, depth + 1, minPossibleScore, maxPossibleScore); // Undo the move. board.Set(move, PieceType.Empty); double score = result.Score; if (isMaxSearch) { if (score > bestMove.Score) { result.Moves.Push(new PlayerAndMove(curPlayer, move)); bestMove = result; if (score >= maxPossibleScore) { // Result is better than max possible score, so this whole max search branch is meaningless. // Just stop searching and return meaningless result. break; } minPossibleScore = score; } } else { if (score < bestMove.Score) { result.Moves.Push(new PlayerAndMove(curPlayer, move)); bestMove = result; if (score <= minPossibleScore) { // Result is worse than min possible score, so this whole min search branch is meaningless. // Just stop searching and return meaningless result. break; } maxPossibleScore = score; } } } return(bestMove); }