private void HashBlockers(int sqInd, bool rook)
        {
            ulong mask = SaveMask(sqInd, rook);

            int[] bitsArr      = rook ? RBits : BBits;
            int   bits         = bitsArr[sqInd];
            int   combinations = 1 << bits;

            ulong[] blockers = new ulong[combinations];
            ulong[] attacks  = new ulong[combinations];

            for (int i = 0; i < combinations; i++)
            {
                blockers[i] = GetBlockersByIndex(i, mask);
                attacks[i]  = rook ? SlidingPieceUtils.GetRookAtt(sqInd, blockers[i]) : SlidingPieceUtils.GetBishopAtt(sqInd, blockers[i]);
            }

            ulong magic = rook ? rookMagics[sqInd] : bishopMagics[sqInd];

            ulong[][] attacksTable = rook ? rookAttacksTable : bishopAttacksTable;
            attacksTable[sqInd] = new ulong[combinations];

            for (int i = 0; i < combinations; i++)
            {
                ulong hashed = ApplyMagic(blockers[i], magic, bits);
                attacksTable[sqInd][hashed] = attacks[i];
            }
        }
        private ulong SaveMask(int sqInd, bool rook)
        {
            ulong mask;

            if (rook)
            {
                mask = rookMasks[sqInd] = SlidingPieceUtils.GetRookMask(sqInd);
            }
            else
            {
                mask = bishopMasks[sqInd] = SlidingPieceUtils.GetBishopMask(sqInd);
            }
            return(mask);
        }
        private ulong FindMagic(int sqInd, bool rook, out ulong[] hashTable)
        {
            ulong mask = SaveMask(sqInd, rook);

            int[] bitsArr      = rook ? RBits : BBits;
            int   bits         = bitsArr[sqInd];
            int   combinations = 1 << bits;

            ulong[] blockers = new ulong[combinations];
            ulong[] attacks  = new ulong[combinations];
            hashTable = new ulong[combinations];

            for (int i = 0; i < combinations; i++)
            {
                blockers[i] = GetBlockersByIndex(i, mask);
                attacks[i]  = rook ? SlidingPieceUtils.GetRookAtt(sqInd, blockers[i]) : SlidingPieceUtils.GetBishopAtt(sqInd, blockers[i]);
            }

            for (int k = 0; k < 100000000; k++)
            {
                ulong   magic        = RandomUInt64FewBits();
                ulong[] attacksTable = new ulong[combinations];
                bool    fail         = false;
                for (int i = 0; i < combinations && !fail; i++)
                {
                    ulong hashed = ApplyMagic(blockers[i], magic, bits);
                    if (attacksTable[hashed] == 0)
                    {
                        attacksTable[hashed] = attacks[i];
                    }
                    else if (attacksTable[hashed] != attacks[i])
                    {
                        fail = true;
                    }
                }
                if (!fail)
                {
                    hashTable = attacksTable;
                    return(magic);
                }
            }
            throw new Exception("Failed to find magic");
        }