【国象AI】棋子移动
数据结构为64位棋盘
- pos 0-63 代表在哪个格子
- Bit64 mask[64]; 把0-63格子转到64位
兵
_Bit64_ move_Pawn[2][64];
//初始化
for (int pos = 0; pos < 64; pos++)
{
pos_bit = mask[pos];
move_Pawn[WHITE_SIDE][pos] = ((pos_bit & 0x00FFFFFFFFFFFF00) >> 8) | ((pos_bit & 0x00FF000000000000) >> 16);
move_Pawn[BLACK_SIDE][pos] = ((pos_bit & 0x00FFFFFFFFFFFF00) << 8) | ((pos_bit & 0x000000000000FF00) << 16);
}
//移动
if (WHITE_SIDE == color)
{
final_position = move_Pawn[WHITE_SIDE][pos];
//去除掉前方一格被挡仍允许走两格的情况
final_position &= (~(((White_All.GetData() | Black_All.GetData()) & mask[pos - 8]) >> 8));
//去除掉前方被敌方棋子阻挡仍允许直线吃子的情况
final_position &= ~(Black_All.GetData());
//斜向吃子,排除<<7引起的同行A列H列互吃的BUG
final_position |= ((posbit & (_Bit64_)0x7F7F7F7F7F7F7F7F) >> 7 | (posbit & (_Bit64_)0xFEFEFEFEFEFEFEFE) >> 9) & Black_All.GetData();
//过路兵判定
if (En_passant != NONE && pos >> 3 == 3)
{
if ((pos & 7) == En_passant - 1)
final_position |= mask[pos] >> 7;
else if ((pos & 7) == En_passant + 1)
final_position |= mask[pos] >> 9;
}
}
马
int knightsq[8] = { -17, -15, -6, 10, 17, 15, 6, -10 };
//初始化
for (int pos = 0; pos < 64; pos++){
tempN = 0;
for (int k = 0; k < KNIGHT_POSSIBLE_MOVE; k++)
{
new_pos = pos + knightsq[k];
if (new_pos >= 0 && new_pos < 64)
{
/* 马所在的格子的行数/列数与它下一步可以走的格子的行数/列数之间的差须小于3 */
if ((((pos >> 3) - (new_pos >> 3))*((pos >> 3) - (new_pos >> 3)) +
((pos & 7) - (new_pos & 7))*((pos & 7) - (new_pos & 7))) == 5)
tempN |= mask[new_pos];
}
}
move_Knight[pos] = tempN;
}
//移动
final_position = move_Knight[pos];
车
这里还记录一个是旋转90度的棋盘
//初始化
static const short getline_shift[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, 48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56 };
static const short getline_shift_trans[64] = { 0, 8, 16, 24, 32, 40, 48, 56, 0, 8, 16, 24, 32, 40, 48, 56, 0, 8, 16, 24, 32, 40, 48, 56, 0, 8, 16, 24, 32, 40, 48, 56, 0, 8, 16, 24, 32, 40, 48, 56, 0, 8, 16, 24, 32, 40, 48, 56, 0, 8, 16, 24, 32, 40, 48, 56, 0, 8, 16, 24, 32, 40, 48, 56 };
//移动
final_position |= rank_attacks[pos][((White_All.GetData() | Black_All.GetData()) >> getline_shift[pos]) & 255];
final_position |= file_attacks[pos][((White_All_trans.GetData() | Black_All_trans.GetData()) >> getline_shift_trans[pos]) & 255];
象
旋转45、-45的棋盘
//初始化
static const short length_A8H1_diag[64] = { 8, 7, 6, 5, 4, 3, 2, 1, 7, 8, 7, 6, 5, 4, 3, 2, 6, 7, 8, 7, 6, 5, 4, 3, 5, 6, 7, 8, 7, 6, 5, 4, 4, 5, 6, 7, 8, 7, 6, 5, 3, 4, 5, 6, 7, 8, 7, 6, 2, 3, 4, 5, 6, 7, 8, 7, 1, 2, 3, 4, 5, 6, 7, 8 };
static const short length_H8A1_diag[64] = { 1, 2, 3, 4, 5, 6, 7, 8, 2, 3, 4, 5, 6, 7, 8, 7, 3, 4, 5, 6, 7, 8, 7, 6, 4, 5, 6, 7, 8, 7, 6, 5, 5, 6, 7, 8, 7, 6, 5, 4, 6, 7, 8, 7, 6, 5, 4, 3, 7, 8, 7, 6, 5, 4, 3, 2, 8, 7, 6, 5, 4, 3, 2, 1 };
static const short shade_A8H1[64] = { 255, 127, 63, 31, 15, 7, 3, 1, 127, 255, 127, 63, 31, 15, 7, 3, 63, 127, 255, 127, 63, 31, 15, 7, 31, 63, 127, 255, 127, 63, 31, 15, 15, 31, 63, 127, 255, 127, 63, 31, 7, 15, 31, 63, 127, 255, 127, 63, 3, 7, 15, 31, 63, 127, 255, 127, 1, 3, 7, 15, 31, 63, 127, 255 };
static const short shade_H8A1[64] = { 1, 3, 7, 15, 31, 63, 127, 255, 3, 7, 15, 31, 63, 127, 255, 127, 7, 15, 31, 63, 127, 255, 127, 63, 15, 31, 63, 127, 255, 127, 63, 31, 31, 63, 127, 255, 127, 63, 31, 15, 63, 127, 255, 127, 63, 31, 15, 7, 127, 255, 127, 63, 31, 15, 7, 3, 255, 127, 63, 31, 15, 7, 3, 1 };
static const _Pos_ start_pos_A8H1[64] = { 28, 21, 15, 10, 6, 3, 1, 0, 36, 28, 21, 15, 10, 6, 3, 1, 43, 36, 28, 21, 15, 10, 6, 3, 49, 43, 36, 28, 21, 15, 10, 6, 54, 49, 43, 36, 28, 21, 15, 10, 58, 54, 49, 43, 36, 28, 21, 15, 61, 58, 54, 49, 43, 36, 28, 21, 63, 61, 58, 54, 49, 43, 36, 28 };
static const _Pos_ start_pos_H8A1[64] = { 0, 1, 3, 6, 10, 15, 21, 28, 1, 3, 6, 10, 15, 21, 28, 36, 3, 6, 10, 15, 21, 28, 36, 43, 6, 10, 15, 21, 28, 36, 43, 49, 10, 15, 21, 28, 36, 43, 49, 54, 15, 21, 28, 36, 43, 49, 54, 58, 21, 28, 36, 43, 49, 54, 58, 61, 28, 36, 43, 49, 54, 58, 61, 63 };
/* 象或后在A8-H1方向移动的预先计算 */
for (int pos = 0; pos < 64; pos++)
{
//求出当前格子在所在斜线中是第几格
const short index = (((pos >> 3) >(pos & 7)) ? (pos & 7) : (pos >> 3));
//传入的pattern中的有效位数应不高于pos所在的斜线长度
for (int pattern = 0; pattern < (1 << length_A8H1_diag[pos]); pattern++)
{
//计算从这个格子朝左上方走的着法
tempx = pos >> 3;
tempy = pos & 7;
pos_bit = mask[pos];
pattern_bit = 1 << index; //获取当前位置在棋形pattern中的位,通过移动pattern_bit判断斜线中是否与棋子冲突
while (1)
{
pos_bit = pos_bit >> 9;
pattern_bit = pattern_bit >> 1;
if (--tempx < 0 || --tempy < 0)
break;
else //未越界
diag_A8H1_attacks[pos][pattern] |= pos_bit;
if (pattern_bit & pattern) //与棋子冲突
break;
}
//计算从这个格子朝右下方走的着法
//.....
}
}
}
/* 象或后在H8-A1方向移动的预先计算 */
//.....
}
//移动
final_position |= diag_A8H1_attacks[pos][((White_All_L45.GetData() | Black_All_L45.GetData()) >> start_pos_A8H1[pos]) & (shade_A8H1[pos])];
final_position |= diag_H8A1_attacks[pos][((White_All_R45.GetData() | Black_All_R45.GetData()) >> start_pos_H8A1[pos]) & (shade_H8A1[pos])];
后
车+象
王
int kingsq[KING_POSSIBLE_MOVE] = { -9, -8, -7, -1, 1, 7, 8, 9 };
//初始化
for (int pos = 0; pos < 64; pos++){
tempK = 0;
for (int k = 0; k < KING_POSSIBLE_MOVE; k++)
{
new_pos = pos + kingsq[k];
if (new_pos >= 0 && new_pos < 64)
{
if (((((pos >> 3) - (new_pos >> 3))*((pos >> 3) - (new_pos >> 3))) <= 1) &&
((((pos & 7) - (new_pos & 7))*((pos & 7) - (new_pos & 7))) <= 1))
tempK |= mask[new_pos];
}
}
move_King[pos] = tempK;
}
//移动
final_position = move_King[pos];
//对于王还有被将等情况的判断
后面
可移动棋子最后要去掉被己方棋子占据的格子
@三三学长 学长负责了很大一部分的优化和调试

浙公网安备 33010602011771号