当前位置: 首页 > 知识库问答 >
问题:

魔术比特板不会加速国际象棋引擎

唐俊英
2023-03-14

我刚刚开始编写国际象棋引擎,但最近刚刚完成了我的第一个程序。但它运行得很慢,所以我切换到了比特板,现在切换到了魔法比特板。我经常使用国际象棋编程维基。

我现在尝试一个测试位置和perft函数,看看程序每秒可以计算多少节点(包括批量计数)。现在,我的perft函数被设置为只计算伪合法移动,我已经设置make_move函数不切换回合。因此我可以用perft分析位置R7/8/8/8/8/8/8 w。

然而我的问题是,如果没有魔术比特板,我每秒得到622万个节点,而有了我只得到6.29。似乎我的魔术比特板没有正常工作。直觉上感觉魔术比特板的速度应该要大得多。此外,95%的计算时间花在我的伪合法移动生成器中。

正如我所提到的,我是国际象棋引擎的新手,尤其是魔术比特板。我不知道如何正确地完成搜寻列表,现在我有一个64*8192条目的表(用于rooks)。我在程序开始时初始化这个表,通过计算每个方块的所有不同的阻止器组合。然后我的索引由(occ给出

我缓慢的魔术比特板的原因是我巨大的表大小吗?有没有其他方法可以更有效地做到这一点?

速度如此之小的原因完全有可能是因为时间不是花在生成移动上,而是在不同的位板上迭代。有没有办法加快这个过程?似乎(通过谷歌搜索)我的功能

int ls1b(u64 bitboard) {
    if (bitboard) {
        return count((bitboard & -bitboard) - 1);
    }
    return -1;
}

int count(u64 bitboard) {
    int count = 0;
    while(bitboard) {
        count++;
        bitboard &= bitboard - 1;
    }
    return count;
}

尽可能快。stockfish(或其他c引擎)是如何进行这种迭代的?

共有1个答案

石臻
2023-03-14

我无法对程序的其余部分发表评论,因为我看不到它,但对于您的位函数,它们可以改进,请参见:

https://www.chessprogramming.org/BitScan#Trailing_Zero_Counthttps://en.wikipedia.org/wiki/Hamming_weight

int lsb(uint64_t bb) {
   static const int lookup67[67+1] = {
      64,  0,  1, 39,  2, 15, 40, 23,
       3, 12, 16, 59, 41, 19, 24, 54,
       4, -1, 13, 10, 17, 62, 60, 28,
      42, 30, 20, 51, 25, 44, 55, 47,
       5, 32, -1, 38, 14, 22, 11, 58,
      18, 53, 63,  9, 61, 27, 29, 50,
      43, 46, 31, 37, 21, 57, 52,  8,
      26, 49, 45, 36, 56,  7, 48, 35,
       6, 34, 33, -1 };
   return lookup67[(bb & -bb) % 67];
}

const uint64_t m1  = 0x5555555555555555; //binary: 0101...
const uint64_t m2  = 0x3333333333333333; //binary: 00110011..
const uint64_t m4  = 0x0f0f0f0f0f0f0f0f; //binary:  4 zeros,  4 ones ...
const uint64_t h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3...

int count(uint64_t x)
{
    x -= (x >> 1) & m1;             //put count of each 2 bits into those 2 bits
    x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits 
    x = (x + (x >> 4)) & m4;        //put count of each 8 bits into those 8 bits 
    return (x * h01) >> 56;  //returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ... 
}
 类似资料:
  • DreamChess 是一款开放源码、跨平台(可在 Windows、Mac OS X 及 Linux 上运行)的 3D 国际象棋游戏。该游戏包含自身的引擎 Dreamer,提供各种国际象棋棋盘,并具有背景音乐及声效等其他附属功能。

  • 我已经有一个Board对象,包含一个碎片列表。Piece是一个抽象类,有一个位置(x,y)和一个颜色(黑色或白色)。然后是King、Queen、Knight这三个类,实现了Piece类。 谢谢

  • 我正在下国际象棋,除了一件事,我几乎得到了所有的东西:我需要使棋手不可能将棋子移动到棋盘上。我很难解决这个问题。 我现在用伪代码生成的有效移动是:类getMoveLocations(我定义了一个位置为国际象棋中的一个方块):如果这个位置在边界内,这个位置的棋子是敌人的棋子,并且模拟的移动不会导致棋盘被检查,然后将该位置添加到工件可以移动到的可能位置。 问题是我如何检查棋盘是否“在检查中”。在我的代

  • 所以我一直在思考一个问题。我目前正在用Java编写一个基于比特板的国际象棋引擎(这是一个解决所有问题的过程)。到目前为止,所有的棋子/国王/骑士的动作都按预期进行,而且没有bug。 我需要帮助理解的是滑动件移动生成。我已经为每个方块/棋子生成了一系列空棋盘动作。根据我目前的理解,我还需要开发一个数组,包含每个广场上的每个可能占用空间——然后根据各种方法查找该数组。 这种想法正确吗?这是不是一个从0

  • 我正在做一个项目,在那里我采取一个象棋棋盘位置(FEN字符串转换成二进制)&它的评估分数,并将它馈送给一个神经网络。我的目的是让神经网络区分好的和坏的仓位。 我是如何编码位置的:国际象棋中有12个独特的棋子,即棋子,棋子,骑士,主教,王后和国王,白棋和黑棋一样。我使用4位编码每一个片段,其中0000表示一个空的正方形。所以64个方块被编码成256位,我用另外6位来表示游戏状态,比如轮到谁移动,国王

  • 上面的代码显示了一个可以上下移动的部分的示例。这不是一个有效的棋步。所以,如果我要移动一个皇后,我该怎么做呢?我们只是假设我们已经有了一个矩阵(x,y)8×8的板。