平均情况下用一个字节存储国际象棋着法

Store a chess move in one byte at average case

我想要一种高效的单字节方式来存储国际象棋走法。标准代数国际象棋符号占用太多字节,我想出的其他解决方案(例如将方块编号为 0-63 并将数字一个接一个地附加)也不起作用。我也明白像提升这样的东西可能需要超过一个字节,但我希望一个标准的移动平均需要一个字节。有什么标准/算法吗?

Imo,你可以计算棋盘位置,(0-63),国际象棋移动可以是从当前位置到新位置的偏移量,所以你可以从 -63 到 63 进行“移动”。
您可以使用 log_2(64)+1 = 7 bit 执行此操作(因此您可以只使用一个字节)。

那么,知道一个棋子的起始位置,以及所有的偏移量,就可以找到那个棋子到过的所有位置

每位玩家在棋盘上最多有 16 个棋子。您可以通过定义顺序(例如,从 a8 开始逐行)然后按该顺序对片段的索引进行编码(0 到 15,所以 4 位)来识别要移动的片段。

每个棋子都有多个有效位置可以移动到。当皇后在所有方向上都没有阻挡棋子到棋盘末端时,找到最大有效目标位置数。

X • • • X • • •
• X • • X • • X
• • X • X • X •
• • • X X X • •
X X X X Q X X X
• • • X X X • •
• • X • X • X •
• X • • X • • X

如果我没数错的话,那是 27 个目标方格。为此,您需要 5 位。但是,你可以看到一个棋子最多有四个不同的目标方块,2 bit 就足够了(除非它在七级时,它可以提升到四个不同的棋子,所以 12 个目标,需要 4 bits) .一个骑士最多有 8 个,所以 3 位。象和车:4 位。 King:最多8个(只有他在边缘时才可以换位),3位。

然后您可以定义一个移动,以使用第一部分中标识的棋子所指示的尽可能多的附加位。您需要做的就是定义考虑目标移动(包括可能的晋升)的顺序。

您可以使用目标单元格排除大多数候选者,然后按预定义的顺序枚举剩余的,最后 select 正确的。

举个小例子更清楚。假设您从左塔移动到位置 34。假设,在您执行此移动的那一刻,您有 4 个候选者可以到达此单元格:pawn6、左塔、左马、右马。您的举动可以编码如下: 100010(34位的二进制)01(左边的塔是第二个可能的选择)。

当然,如果选择多于4个,就会多出8位;但这些情况是自我标记的(你知道一个职位是否有超过 4 个候选人)并且很少见。

Chess Programming Wiki 告诉我们:

If the generated moves inside a move list are deterministic, one may encode moves as relative list index. Since the maximum number of moves per positions seems 218, one byte is enough to index the move. This encoding was used in early game databases.

          Two Positions with 218 Moves each

因此,这要求您的实施可以为给定位置生成所有有效的国际象棋动作。链接的文章提到了对该方法的一些改进,但如果您只关心保持在 1 字节范围内,那么这就足够了。

您可以按照 Chessprogramming website 所述在 16 位字内对移动进行编码。向下滚动到 Information Required / From-To Based,您会看到一个漂亮的 table,其中解释了如何在不丢失任何重要信息的情况下执行此操作。这是 table 的图像(我不能 copy/paste 它的格式很好):