Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何找到魔法比特板?_C_Bit Manipulation_Chess - Fatal编程技术网

C 如何找到魔法比特板?

C 如何找到魔法比特板?,c,bit-manipulation,chess,C,Bit Manipulation,Chess,边正方形为零,因为它们总是阻塞,减少所需的位数显然是有帮助的 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 因此,在上面的示例中,index_to_uint64采用索引(0到2^位),以及位板(10)和位板中设置的位数 然后,它为每个位数弹出第一个位,然后是另一个移位的代

边正方形为零,因为它们总是阻塞,减少所需的位数显然是有帮助的

0 0 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 
0 0 0 0 1 0 0 0 
0 0 0 0 1 0 0 0 
0 1 1 1 0 1 1 0 
0 0 0 0 1 0 0 0 
0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 0 
因此,在上面的示例中,
index_to_uint64
采用索引(0到2^位),以及位板(10)和位板中设置的位数


然后,它为每个位数弹出第一个位,然后是另一个移位的代码位
pops_1st_位
xOR位板本身减去1(为什么?)。然后它用一个完整的32位对它进行运算,在这附近的某个地方,我的大脑内存用完了。不知怎的,这个神奇的十六进制数字0x783a9b23被牵涉进来了(这是丢失的数字序列吗?)。还有一个荒谬的神秘数组,它是从0到63的随机排序的数字(
位表[64]

好吧,我将试着逐步解决这个问题

/* Bitboard, LSB to MSB, a1 through h8:
 * 56 - - - - - - 63
 *  - - - - - - - -
 *  - - - - - - - -
 *  - - - - - - - -
 *  - - - - - - - -
 *  - - - - - - - -
 *  - - - - - - - -
 *  0 - - - - - - 7
 */
7只是在0和2^10之间随机选择的数字,10是以m为单位设置的位数。m可以用四种方式表示:

index_to_uint64( 7, 10, m ); 
继续。这将被调用10次。它有一个返回值并修改m

bitboard:
0 0 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 
0 0 0 0 1 0 0 0 
0 0 0 0 1 0 0 0 
0 1 1 1 0 1 1 0 
0 0 0 0 1 0 0 0 
0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 0 
dec: 4521262379438080
hex: 0x1010106e101000
bin: 0000 0000 0001 0000 0001 0000 0001 0000 0110 1110 0001 0000 0001 0000 0000 0000
在pop_第一位中,m由bb表示。为了清楚起见,我将它改为m

pop_1st_bit(&m);
m-1部件获取设置的最低有效位,并翻转它和它下面的所有位。在异或之后,所有更改的位现在都设置为1,而所有较高的位都设置为0

uint64 b = m^(m-1);
下一步:

(b&0xffffffff)
部分与具有较低32个设置位的b。这基本上清除了b上半部分的所有位

unsigned int fold = (unsigned) ((b & 0xffffffff) ^ (b >> 32));
…^(b>>32)
部分将b的上半部分移到下半部分,然后将其与上一操作的结果异或。所以它基本上是将b的上半部分与下半部分进行异或运算。这在本例中无效,因为b的上半部分一开始是空的

(b & 0xffffffff)
b: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 1111 1111 1111
&: 0000 0000 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111 1111 1111 1111 1111
=: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 1111 1111 1111
我不明白“折叠”的意义,即使在b的上半部分设置了位

不管怎样,继续前进。下一行实际上通过取消设置最低位来修改m。这是有道理的

>> :0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 
^  :0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 1111 1111 1111 

uint fold = 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 1111 1111 1111
下一部分将
fold
乘以某个十六进制数(素数?),将乘积26右移,并将其用作位表的索引,位表是我们神秘的随机顺序数字0-63数组。此时,我怀疑作者可能正在编写一个伪随机数生成器

m &= (m - 1);
m  : 0000 0000 0001 0000 0001 0000 0001 0000 0110 1110 0001 0000 0001 0000 0000 0000 
m-1: 0000 0000 0001 0000 0001 0000 0001 0000 0110 1110 0001 0000 0000 1111 1111 1111
&  : 0000 0000 0001 0000 0001 0000 0001 0000 0110 1110 0001 0000 0000 0000 0000 0000 
这就结束了波普第一位。所有这些操作都执行了10次(初始设置为m的每一位一次)。对pop_1st_位的10次调用中的每一次都返回一个数字0-63

return BitTable[(fold * 0x783a9b23) >> 26];
j=pop\u第一位(&m);

如果(index&(1好的话,我已经算出了

首先,一些术语:

阻止程序掩码:一种位板,包含所有可以阻止一个块的方块,对于给定的块类型和块所在的方块。它不包括终止边方块,因为它们总是阻止

屏蔽板:一种包含占用方块的位板。它只包含同样位于屏蔽板中的方块

移动板:一种位板,包含一个工件可以移动到的所有方块,给定一个工件类型,一个方块和一个阻挡板。如果工件可以移动到那里,它包括终止边方块

例如e4正方形上的一辆车,e2、e5、e7、b4和c4上有一些随机碎片

j = pop_1st_bit(&m);
if(index & (1 << i)) result |= (1ULL << j);
需要注意的一些事项:

  • 对于给定的方形和块类型(rook或bishop),拦截器掩码始终相同
  • 阻击板包括友方和敌方棋子,它是阻击面具的一个子集
  • 由此产生的移动板可能包括捕获您自己的棋子的移动,但是这些移动在之后很容易被删除:
    moveboard&=~friendly\u棋子)
幻数方法的目标是非常快速地查找预先计算的移动板,查找给定的阻挡板。否则您必须(缓慢地)每次计算移动板。这只适用于滑动件,即车和主教。女王只是车和主教的组合

每个方块和方块类型的组合都可以找到神奇的数字。要做到这一点,你必须计算每个方块/方块组合的每一个可能的阻挡板变化。这就是所讨论的代码所做的。它是如何做的对我来说仍然有点神秘,但是。(感谢@Pradhan的链接)

因此,我所做的是重新实现生成所有可能的拦截器板变体的代码。它使用了不同的技术,虽然速度稍慢,但更易于阅读和理解。事实上,速度稍慢不是问题,因为此代码不是速度关键。程序只需在程序启动时执行一次tup,而且在双核i5上只需要几微秒

 The blocker mask        A blocker board         The move board
 0 0 0 0 0 0 0 0         0 0 0 0 0 0 0 0         0 0 0 0 0 0 0 0 
 0 0 0 0 1 0 0 0         0 0 0 0 1 0 0 0         0 0 0 0 0 0 0 0 
 0 0 0 0 1 0 0 0         0 0 0 0 0 0 0 0         0 0 0 0 0 0 0 0 
 0 0 0 0 1 0 0 0         0 0 0 0 1 0 0 0         0 0 0 0 1 0 0 0 
 0 1 1 1 0 1 1 0         0 1 1 0 0 0 0 0         0 0 1 1 0 1 1 1 
 0 0 0 0 1 0 0 0         0 0 0 0 0 0 0 0         0 0 0 0 1 0 0 0 
 0 0 0 0 1 0 0 0         0 0 0 0 1 0 0 0         0 0 0 0 1 0 0 0 
 0 0 0 0 0 0 0 0         0 0 0 0 0 0 0 0         0 0 0 0 0 0 0 0 
/*给定索引(0..2^位)和阻止程序掩码,生成唯一的阻止程序板
*对于工件/正方形。每个索引将给出一个唯一的阻挡板*/
静态uint64\u t gen\u细木工板(int索引,uint64\u t细木工板)
{
/*从与遮罩相同的细木工板开始*/
uint64_t细木工板=细木工板;
/*循环通过blockermask查找所有设置位的索引*/
int8_t bitindex=0;

例如(int8_t i=0;i在youtube上的国际象棋引擎上观看一系列视频时,我的问题与paulwal222完全相同。似乎涉及到一些高级数学。解释这一难题背景的最佳链接是和。Matt Taylor似乎在2003年的google.group()中(也由pradhan发现)提出了一种现在称为Matt Taylor的折叠技巧,一种32位友好的查找LS1B()位索引的实现。Taylor的折叠技巧显然是对1997年设计的De Bruijn()位扫描的改编,根据Martin Läuter的Donald Knuth,通过最小完美散列()确定LS1B索引。位表(63,30,…)和PopBit中的折叠(0x783a9b23)的编号可能就是所谓的ma
j = pop_1st_bit(&m);
if(index & (1 << i)) result |= (1ULL << j);
 The blocker mask        A blocker board         The move board
 0 0 0 0 0 0 0 0         0 0 0 0 0 0 0 0         0 0 0 0 0 0 0 0 
 0 0 0 0 1 0 0 0         0 0 0 0 1 0 0 0         0 0 0 0 0 0 0 0 
 0 0 0 0 1 0 0 0         0 0 0 0 0 0 0 0         0 0 0 0 0 0 0 0 
 0 0 0 0 1 0 0 0         0 0 0 0 1 0 0 0         0 0 0 0 1 0 0 0 
 0 1 1 1 0 1 1 0         0 1 1 0 0 0 0 0         0 0 1 1 0 1 1 1 
 0 0 0 0 1 0 0 0         0 0 0 0 0 0 0 0         0 0 0 0 1 0 0 0 
 0 0 0 0 1 0 0 0         0 0 0 0 1 0 0 0         0 0 0 0 1 0 0 0 
 0 0 0 0 0 0 0 0         0 0 0 0 0 0 0 0         0 0 0 0 0 0 0 0 
/* Generate a unique blocker board, given an index (0..2^bits) and the blocker mask 
 * for the piece/square. Each index will give a unique blocker board. */
static uint64_t gen_blockerboard (int index, uint64_t blockermask) 
{
    /* Start with a blockerboard identical to the mask. */
    uint64_t blockerboard = blockermask;

    /* Loop through the blockermask to find the indices of all set bits. */
    int8_t bitindex = 0;
    for (int8_t i=0; i<64; i++) {
        /* Check if the i'th bit is set in the mask (and thus a potential blocker). */
        if ( blockermask & (1ULL<<i) ) {
            /* Clear the i'th bit in the blockerboard if it's clear in the index at bitindex. */
            if ( !(index & (1<<bitindex)) ) {
                blockerboard &= ~(1ULL<<i); //Clear the bit.
            }
            /* Increment the bit index in the 0-4096 index, so each bit in index will correspond 
             * to each set bit in blockermask. */
            bitindex++;
        }
    }
    return blockerboard;
}
int bits = count_bits( RookBlockermask[square] );
/* Generate all (2^bits) blocker boards. */ 
for (int i=0; i < (1<<bits); i++) {
    RookBlockerboard[square][i] = gen_blockerboard( i, RookBlockermask[square] );
}