微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在使用位板的国际象棋引擎中,如何检测边缘?

如何解决在使用位板的国际象棋引擎中,如何检测边缘?

例如,所有白兵的攻击都是通过向左移动 7 位或 9 位(或向右移动,我可能会弄错,但我认为很容易掌握要点)产生的。

所以看起来像这样的白色 pawn bitboard

00000000000000000000000000000000000000001111111100000000

会转成这个

00000000000000000000000000000001111111100000000000000000

但是,如果您尝试在 8x8 阵列中描绘此示例,其中一个棋子会穿过棋盘边缘。

那么当这些位被转移以产生攻击时,引擎如何防止自己产生穿过棋盘边缘的攻击?

解决方法

我们将添加一些空格。假设您从一个棋子位置开始:

00000000
00000000
00000000
00000000
00000000
10000000
01100101
00011010
00000000
00000000

换行符只是为了便于阅读,一切都是压缩的。棋子可以移动到哪里?

00000000
00000000
00000000
00000000
10000000
01100101
00011010
00000000
00000000
00000000

在这里,越过边缘的唯一风险是在顶部,这很容易处理。

接下来,棋子可以去哪里?天真的解决方案是将上面的“移动”掩码向左和向右移动 1。正如您所注意到的,这会导致环绕。

00000000
00000000
00000000
00000001
00000000
11001010
00110100
00000000
00000000
00000000
|
00000000
00000000
00000000
00000000
01000000
00110010
10001101
00000000
00000000
00000000

(如果您不喜欢我选择的字节顺序,请道歉)。

我们可以通过一些掩码来解决这个问题。将环绕的位位于已知位置。所以我们在进行操作之前将它们屏蔽掉。

这个面具:

11111110
11111110
11111110
11111110
11111110
11111110
11111110
11111110

在我们右移之前,和

01111111
01111111
01111111
01111111
01111111
01111111
01111111
01111111

在我们左移之前。

所以要查看受棋子威胁的点,其中“向前”是右移,我们这样做:

auto pawn_moves = pawn_mask >> 8;
auto pawn_left_take = (pawn_moves & not_left_column) << 1;
auto pawn_right_take = (pawn_moves & not_right_column) << 1;
auto pawn_take = pawn_left_take | pawn_right_take;

我们有了。

对于其他情况可以进行类似的掩蔽。例如,如果我们正在计算骑士取掩码,我们需要 8 个掩码和 8 个班次,然后或将它们全部加在一起。

对于右移 3 的车,您屏蔽右 3 列,然后在车蒙版上右移 3。

然而,在某些时候,您可能想要使用内在函数和 SIMD 处理;因此,您所拥有的准确位操作速度将取决于您的硬件。也许将 8 个 8 位值解包为 8 个 24 位值,在那里进行无掩码操作,然后提取中间 8 位是在您的特定硬件上最快的方法。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。