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);
        }
Example #2
0
        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);
        }