Exemplo n.º 1
0
        /// <summary>
        /// Search pawn and king hash table for a pawn and king specific score for the specific position hash.
        /// </summary>
        /// <param name="hashCodeA">
        /// Hash Code for Board position A
        /// </param>
        /// <param name="hashCodeB">
        /// Hash Code for Board position B
        /// </param>
        /// <param name="colour">
        /// The player colour.
        /// </param>
        /// <returns>
        /// Pawn and king specific score for the specified position.
        /// </returns>
        public static unsafe int ProbeHash(ulong hashCodeA, ulong hashCodeB, Player.PlayerColourNames colour)
        {
            if (colour == Player.PlayerColourNames.Black)
            {
                hashCodeA |= 0x1;
                hashCodeB |= 0x1;
            }
            else
            {
                hashCodeA &= 0xFFFFFFFFFFFFFFFE;
                hashCodeB &= 0xFFFFFFFFFFFFFFFE;
            }

            Probes++;

            fixed(HashEntry *phashBase = &hashTableEntries[0])
            {
                HashEntry *phashEntry = phashBase;

                phashEntry += (uint)(hashCodeA % hashTableSize);

                if (phashEntry->HashCodeA == hashCodeA && phashEntry->HashCodeB == hashCodeB)
                {
                    Hits++;
                    return(phashEntry->Points);
                }
            }

            return(NotFoundInHashTable);
        }
Exemplo n.º 2
0
        /// <summary>
        /// The lines first piece.
        /// </summary>
        /// <param name="colour">
        /// The colour.
        /// </param>
        /// <param name="pieceName">
        /// The piece name.
        /// </param>
        /// <param name="squareStart">
        /// The square start.
        /// </param>
        /// <param name="offset">
        /// The offset.
        /// </param>
        /// <returns>
        /// The first piece on the line, or null.
        /// </returns>
        public static Piece LinesFirstPiece(
            Player.PlayerColourNames colour, Piece.PieceNames pieceName, Square squareStart, int offset)
        {
            int    intOrdinal = squareStart.Ordinal;
            Square square;

            intOrdinal += offset;
            while ((square = GetSquare(intOrdinal)) != null)
            {
                if (square.Piece == null)
                {
                }
                else if (square.Piece.Player.Colour != colour)
                {
                    return(null);
                }
                else if (square.Piece.Name == pieceName || square.Piece.Name == Piece.PieceNames.Queen)
                {
                    return(square.Piece);
                }
                else
                {
                    return(null);
                }

                intOrdinal += offset;
            }

            return(null);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Search Hash table for a previously stored score.
        /// </summary>
        /// <param name="hashCodeA">
        /// Hash Code for Board position A
        /// </param>
        /// <param name="hashCodeB">
        /// Hash Code for Board position B
        /// </param>
        /// <param name="depth">
        /// The search depth.
        /// </param>
        /// <param name="alpha">
        /// Apha value.
        /// </param>
        /// <param name="beta">
        /// Beta value.
        /// </param>
        /// <param name="colour">
        /// The player colour.
        /// </param>
        /// <returns>
        /// The positional score.
        /// </returns>
        public static unsafe int ProbeHash(
            ulong hashCodeA, ulong hashCodeB, int depth, int alpha, int beta, Player.PlayerColourNames colour)
        {
            Probes++;

            fixed(HashEntry *phashBase = &hashTableEntries[0])
            {
                HashEntry *phashEntry = phashBase;

                phashEntry += (uint)(hashCodeA % hashTableSize);

                int intAttempt = 0;

                while (phashEntry >= phashBase
                       &&
                       (phashEntry->HashCodeA != hashCodeA || phashEntry->HashCodeB != hashCodeB ||
                        phashEntry->Depth < depth))
                {
                    phashEntry--;
                    intAttempt++;
                    if (intAttempt == HashTableSlotDepth)
                    {
                        break;
                    }
                }

                if (phashEntry < phashBase)
                {
                    phashEntry = phashBase;
                }

                if (phashEntry->HashCodeA == hashCodeA && phashEntry->HashCodeB == hashCodeB &&
                    phashEntry->Depth >= depth)
                {
                    if (phashEntry->Colour == colour)
                    {
                        if (phashEntry->Type == HashTypeNames.Exact)
                        {
                            Hits++;
                            return(phashEntry->Result);
                        }

                        if ((phashEntry->Type == HashTypeNames.Alpha) && (phashEntry->Result <= alpha))
                        {
                            Hits++;
                            return(alpha);
                        }

                        if ((phashEntry->Type == HashTypeNames.Beta) && (phashEntry->Result >= beta))
                        {
                            Hits++;
                            return(beta);
                        }
                    }
                }
            }

            return(NotFoundInHashTable);
        }
Exemplo n.º 4
0
 /// <summary>
 /// Record a new history entry.
 /// </summary>
 /// <param name="colour">
 /// The player colour.
 /// </param>
 /// <param name="ordinalFrom">
 /// The From square ordinal.
 /// </param>
 /// <param name="ordinalTo">
 /// The To square ordinal.
 /// </param>
 /// <param name="value">
 /// The history heuristic weighting value.
 /// </param>
 public static void Record(Player.PlayerColourNames colour, int ordinalFrom, int ordinalTo, int value)
 {
     if (colour == Player.PlayerColourNames.White)
     {
         HistoryTableEntriesforWhite[ordinalFrom, ordinalTo] += value;
     }
     else
     {
         HistoryTableEntriesforBlack[ordinalFrom, ordinalTo] += value;
     }
 }
Exemplo n.º 5
0
        /// <summary>
        /// Record a new history entry.
        /// </summary>
        /// <param name="colour">
        /// The player colour.
        /// </param>
        /// <param name="ordinalFrom">
        /// The From square ordinal.
        /// </param>
        /// <param name="ordinalTo">
        /// The To square ordinal.
        /// </param>
        /// <param name="value">
        /// The history heuristic weighting value.
        /// </param>
        public static void Record(Player.PlayerColourNames colour, int ordinalFrom, int ordinalTo, int value)
        {
            // Disable if this feature when switched off.
            if (!Game.EnableHistoryHeuristic)
            {
                return;
            }

            if (colour == Player.PlayerColourNames.White)
            {
                HistoryTableEntriesforWhite[ordinalFrom, ordinalTo] += value;
            }
            else
            {
                HistoryTableEntriesforBlack[ordinalFrom, ordinalTo] += value;
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Calculates a positional penalty score for a single open line to a square (usually the king square), in a specified direction.
        /// </summary>
        /// <param name="colour">
        /// The player's colour.
        /// </param>
        /// <param name="squareStart">
        /// The square piece (king) is on.
        /// </param>
        /// <param name="directionOffset">
        /// The direction offset.
        /// </param>
        /// <returns>
        /// The open line penalty.
        /// </returns>
        public static int OpenLinePenalty(Player.PlayerColourNames colour, Square squareStart, int directionOffset)
        {
            int    intOrdinal     = squareStart.Ordinal;
            int    intSquareCount = 0;
            int    intPenalty     = 0;
            Square square;

            intOrdinal += directionOffset;

            while (intSquareCount <= 2
                   &&
                   ((square = GetSquare(intOrdinal)) != null
                    &&
                    (square.Piece == null ||
                     (square.Piece.Name != Piece.PieceNames.Pawn && square.Piece.Name != Piece.PieceNames.Rook) ||
                     square.Piece.Player.Colour != colour)))
            {
                intPenalty += 75;
                intSquareCount++;
                intOrdinal += directionOffset;
            }

            return(intPenalty);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Record a hash new hash entry in the hash table.
        /// </summary>
        /// <param name="hashCodeA">
        /// Hash Code for Board position A
        /// </param>
        /// <param name="hashCodeB">
        /// Hash Code for Board position B
        /// </param>
        /// <param name="depth">
        /// The search depth.
        /// </param>
        /// <param name="val">
        /// The score of the position to record.
        /// </param>
        /// <param name="type">
        /// The position type: alpha, beta or exact value.
        /// </param>
        /// <param name="from">
        /// From square ordinal.
        /// </param>
        /// <param name="to">
        /// To square ordinal.
        /// </param>
        /// <param name="moveName">
        /// The move name.
        /// </param>
        /// <param name="colour">
        /// The player colour.
        /// </param>
        public static unsafe void RecordHash(
            ulong hashCodeA,
            ulong hashCodeB,
            int depth,
            int val,
            HashTypeNames type,
            int from,
            int to,
            Move.MoveNames moveName,
            Player.PlayerColourNames colour)
        {
            Writes++;
            fixed(HashEntry *phashBase = &hashTableEntries[0])
            {
                HashEntry *phashEntry = phashBase;

                phashEntry += (uint)(hashCodeA % hashTableSize);

                int intAttempt = 0;

                while (phashEntry >= phashBase && phashEntry->HashCodeA != 0 && phashEntry->Depth > depth)
                {
                    phashEntry--;
                    intAttempt++;
                    if (intAttempt == HashTableSlotDepth)
                    {
                        break;
                    }
                }

                if (phashEntry < phashBase)
                {
                    phashEntry = phashBase;
                }

                if (phashEntry->HashCodeA != 0)
                {
                    Collisions++;
                    if (phashEntry->HashCodeA != hashCodeA || phashEntry->HashCodeB != hashCodeB)
                    {
                        Overwrites++;
                        phashEntry->WhiteFrom = -1;
                        phashEntry->BlackFrom = -1;
                    }
                }

                phashEntry->HashCodeA = hashCodeA;
                phashEntry->HashCodeB = hashCodeB;
                phashEntry->Result    = val;
                phashEntry->Type      = type;
                phashEntry->Depth     = (sbyte)depth;
                phashEntry->Colour    = colour;
                if (from > -1)
                {
                    if (colour == Player.PlayerColourNames.White)
                    {
                        phashEntry->WhiteMoveName = moveName;
                        phashEntry->WhiteFrom     = (sbyte)from;
                        phashEntry->WhiteTo       = (sbyte)to;
                    }
                    else
                    {
                        phashEntry->BlackMoveName = moveName;
                        phashEntry->BlackFrom     = (sbyte)from;
                        phashEntry->BlackTo       = (sbyte)to;
                    }
                }
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Search for best move in hash table.
        /// </summary>
        /// <param name="hashCodeA">
        /// Hash Code for Board position A
        /// </param>
        /// <param name="hashCodeB">
        /// Hash Code for Board position B
        /// </param>
        /// <param name="colour">
        /// The player colour.
        /// </param>
        /// <returns>
        /// Best move, or null.
        /// </returns>
        public static unsafe Move ProbeForBestMove(ulong hashCodeA, ulong hashCodeB, Player.PlayerColourNames colour)
        {
            // TODO Unit test Hash Table. What happens when same position stored at different depths in diffenent slots with the same hash?
            fixed(HashEntry *phashBase = &hashTableEntries[0])
            {
                HashEntry *phashEntry = phashBase;

                phashEntry += (uint)(hashCodeA % hashTableSize);

                int intAttempt = 0;

                while (phashEntry >= phashBase &&
                       (phashEntry->HashCodeA != hashCodeA || phashEntry->HashCodeB != hashCodeB))
                {
                    phashEntry--;
                    intAttempt++;
                    if (intAttempt == HashTableSlotDepth)
                    {
                        break;
                    }
                }

                if (phashEntry < phashBase)
                {
                    phashEntry = phashBase;
                }

                if (phashEntry->HashCodeA == hashCodeA && phashEntry->HashCodeB == hashCodeB)
                {
                    if (colour == Player.PlayerColourNames.White)
                    {
                        if (phashEntry->WhiteFrom >= 0)
                        {
                            return(new Move(
                                       0,
                                       0,
                                       phashEntry->WhiteMoveName,
                                       Board.GetPiece(phashEntry->WhiteFrom),
                                       Board.GetSquare(phashEntry->WhiteFrom),
                                       Board.GetSquare(phashEntry->WhiteTo),
                                       Board.GetSquare(phashEntry->WhiteTo).Piece,
                                       0,
                                       phashEntry->Result));
                        }
                    }
                    else
                    {
                        if (phashEntry->BlackFrom >= 0)
                        {
                            return(new Move(
                                       0,
                                       0,
                                       phashEntry->BlackMoveName,
                                       Board.GetPiece(phashEntry->BlackFrom),
                                       Board.GetSquare(phashEntry->BlackFrom),
                                       Board.GetSquare(phashEntry->BlackTo),
                                       Board.GetSquare(phashEntry->BlackTo).Piece,
                                       0,
                                       phashEntry->Result));
                        }
                    }
                }
            }

            return(null);
        }
Exemplo n.º 9
0
 /// <summary>
 /// Retrieve a value from the History Heuristic table.
 /// </summary>
 /// <param name="colour">
 /// The player colour.
 /// </param>
 /// <param name="ordinalFrom">
 /// The From square ordinal.
 /// </param>
 /// <param name="ordinalTo">
 /// The To square ordinal.
 /// </param>
 /// <returns>
 /// The history heuristic weighting value.
 /// </returns>
 public static int Retrieve(Player.PlayerColourNames colour, int ordinalFrom, int ordinalTo)
 {
     return(colour == Player.PlayerColourNames.White ? HistoryTableEntriesforWhite[ordinalFrom, ordinalTo] : HistoryTableEntriesforBlack[ordinalFrom, ordinalTo]);
 }
Exemplo n.º 10
0
        /// <summary>
        /// Record the pawn and kind specific positional score in the pawn king hash table.
        /// </summary>
        /// <param name="hashCodeA">
        /// Hash Code for Board position A
        /// </param>
        /// <param name="hashCodeB">
        /// Hash Code for Board position B
        /// </param>
        /// <param name="val">
        /// Pawn king specific score.
        /// </param>
        /// <param name="colour">
        /// Player colour.
        /// </param>
        public static unsafe void RecordHash(ulong hashCodeA, ulong hashCodeB, int val, Player.PlayerColourNames colour)
        {
            if (colour == Player.PlayerColourNames.Black)
            {
                hashCodeA |= 0x1;
                hashCodeB |= 0x1;
            }
            else
            {
                hashCodeA &= 0xFFFFFFFFFFFFFFFE;
                hashCodeB &= 0xFFFFFFFFFFFFFFFE;
            }

            fixed(HashEntry *phashBase = &hashTableEntries[0])
            {
                HashEntry *phashEntry = phashBase;

                phashEntry           += (uint)(hashCodeA % hashTableSize);
                phashEntry->HashCodeA = hashCodeA;
                phashEntry->HashCodeB = hashCodeB;
                phashEntry->Points    = val;
            }

            Writes++;
        }
Exemplo n.º 11
0
        /// <summary>
        /// Record a hash new hash entry in the hash table.
        /// </summary>
        /// <param name="hashCodeA">
        /// Hash Code for Board position A
        /// </param>
        /// <param name="hashCodeB">
        /// Hash Code for Board position B
        /// </param>
        /// <param name="from">
        /// From square ordinal.
        /// </param>
        /// <param name="to">
        /// To square ordinal.
        /// </param>
        /// <param name="moveName">
        /// The move name.
        /// </param>
        /// <param name="colour">
        /// The player colour.
        /// </param>
        private static unsafe void RecordHash(ulong hashCodeA, ulong hashCodeB, byte from, byte to, Move.MoveNames moveName, Player.PlayerColourNames colour)
        {
            if (colour == Player.PlayerColourNames.Black)
            {
                hashCodeA |= 0x1;
                hashCodeB |= 0x1;
            }
            else
            {
                hashCodeA &= 0xFFFFFFFFFFFFFFFE;
                hashCodeB &= 0xFFFFFFFFFFFFFFFE;
            }

            fixed(HashEntry *phashBase = &HashTableEntries[0])
            {
                HashEntry *phashEntry = phashBase;

                phashEntry += (uint)(hashCodeA % HashTableSize);

                phashEntry->HashCodeA = hashCodeA;
                phashEntry->HashCodeB = hashCodeB;
                phashEntry->From      = from;
                phashEntry->To        = to;
                phashEntry->MoveName  = moveName;
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// The probe opening book (hash table) for best move for the specied board position (hash code).
        /// </summary>
        /// <param name="hashCodeA">
        /// The hash code for board position A.
        /// </param>
        /// <param name="hashCodeB">
        /// The hash code for board position B.
        /// </param>
        /// <param name="colour">
        /// The player colour.
        /// </param>
        /// <returns>
        /// The best move in the opening book (hash table) or null if there is no opening book entry for the specified board position.
        /// </returns>
        private static unsafe Move ProbeForBestMove(ulong hashCodeA, ulong hashCodeB, Player.PlayerColourNames colour)
        {
            if (colour == Player.PlayerColourNames.Black)
            {
                hashCodeA |= 0x1;
                hashCodeB |= 0x1;
            }
            else
            {
                hashCodeA &= 0xFFFFFFFFFFFFFFFE;
                hashCodeB &= 0xFFFFFFFFFFFFFFFE;
            }

            fixed(HashEntry *phashBase = &HashTableEntries[0])
            {
                HashEntry *phashEntry = phashBase;

                phashEntry += (uint)(hashCodeA % HashTableSize);

                if (phashEntry->HashCodeA == hashCodeA && phashEntry->HashCodeB == hashCodeB)
                {
                    return(new Move(0, 0, phashEntry->MoveName, Board.GetPiece(phashEntry->From), Board.GetSquare(phashEntry->From), Board.GetSquare(phashEntry->To), null, 0, 0));
                }
            }

            return(NotFoundInHashTable);
        }
Exemplo n.º 13
0
 /// <summary>
 /// The search for best move in opening book.
 /// </summary>
 /// <param name="boardHashCodeA">
 /// The board hash code a.
 /// </param>
 /// <param name="boardHashCodeB">
 /// The board hash code b.
 /// </param>
 /// <param name="colour">
 /// The colour.
 /// </param>
 /// <returns>
 /// The best move from the opening book.
 /// </returns>
 public static Move SearchForGoodMove(ulong boardHashCodeA, ulong boardHashCodeB, Player.PlayerColourNames colour)
 {
     return(ProbeForBestMove(boardHashCodeA, boardHashCodeB, colour));
 }