Пример #1
0
        /// <summary>
        /// Look up a position's hash in the table.
        /// </summary>
        /// <param name="hash">The hash to search for.</param>
        /// <param name="entry">The found entry.</param>
        /// <returns>True if the lookup was successful and the out-param contains the correct record.</returns>
        public bool TryGetValue(ulong hash, out TTEntry entry) {

            entry = table[GetIndex(hash)];

            if (null == entry) return false;
            if (entry.Hash == hash) return true;
            return false;
        }
Пример #2
0
        /// <summary>
        /// Submit an entry to the tablebase. It will decide for itself whether it keeps it or prefers the previous record.
        /// </summary>
        public void Write(TTEntry entry) {

            //CURRENT STRATEGY: "Replace with higher depth"

            int index = GetIndex(entry.Hash);
            TTEntry oldEntry = table[index];
            if ((null == oldEntry) || (entry.Depth > oldEntry.Depth)) table[index] = entry;

        }
Пример #3
0
        /// <summary>
        /// Recursively calculates the value of the current position, up to the given depth.
        /// </summary>
        /// <param name="move">The last move. Win is checked in its neighborhood.</param>
        /// <param name="depth">The remaining available depth.</param>
        /// <param name="color">The color of the player to move. 1 ~ black, -1 ~ white.</param>
        /// <param name="alpha">The lower boundary on "interesting" scores.</param>
        /// <param name="beta">The upper boundary on "interesting" scores.</param>
        private int negamax(Square move, int depth, int color, int alpha, int beta)
        {
            Square localBestMove = move;
            int    origAlpha     = alpha;

            //TT lookup
            TTEntry ttEntry;

            if (tt.TryGetValue(currentHash, out ttEntry))
            {
                localBestMove = ttEntry.BestMove; //for ordering purposes, just take the best move regardless of depth. For the rest, depth does matter.
                if (ttEntry.Depth >= depth)
                {
                    switch (ttEntry.Flag)
                    {
                    case TTFlag.Exact:
                        return(ttEntry.Score);

                    case TTFlag.Upper:
                        if (ttEntry.Score < beta)
                        {
                            beta = ttEntry.Score;
                        }
                        break;

                    case TTFlag.Lower:
                        if (ttEntry.Score > alpha)
                        {
                            alpha = ttEntry.Score;
                        }
                        break;

                    default:
                        break;
                    }
                    if (alpha >= beta)
                    {
                        return(ttEntry.Score);
                    }
                }
            }

            //if state is terminal, return:
            if (checkWin(move, color == -1))
            {
                return(-12345678); //someone won, so the score [calculated always for black] is +inf * (previous color). We return (color to move)*(score for black) --> always -inf
            }
            if (moveCount >= Gamestate.maxMoves)
            {
                return(0); //draw, return 0
            }
            if (depth <= 0)
            {
                int result = color * evaluate(); //not a win, not a draw, but reached maximum depth (0 remaining depth), return evaluation
                return(result);
            }

            //otherwise keep searching children
            int value = -12345678;
            int candidateValue;

            foreach (Square child in GenerateShuffledMoves(localBestMove))
            {
                if (stopSearch)
                {
                    return(value);            //do not visit any more children if search is stopped
                }
                incrementBoard(child, color == 1);
                candidateValue = -negamax(child, depth - 1, -color, -beta, -alpha);
                decrementBoard(child);

                if (candidateValue > value)
                {
                    value         = candidateValue;
                    localBestMove = child;
                }
                if (value > alpha)
                {
                    alpha = value;
                }
                if (alpha >= beta)
                {
                    break;
                }
            }

            if (stopSearch)
            {
                return(value);           //do not update TT if search is stopped
            }
            //TT update
            TTFlag flag;

            if (value <= origAlpha)
            {
                flag = TTFlag.Upper;
            }
            else if (value >= beta)
            {
                flag = TTFlag.Lower;
            }
            else
            {
                flag = TTFlag.Exact;
            }
            ttEntry = new TTEntry(currentHash, localBestMove, depth, value, flag);
            tt.Write(ttEntry);

            return(value);
        }