具有人工智能的3D国际象棋(openGL)(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/3d-chess-opengl-with-artificial-intelligence-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 4 分钟阅读 - 1919 个词 阅读量 0具有人工智能的3D国际象棋(openGL)(译文)
原文地址:https://www.codeproject.com/Articles/81970/3D-Chess-openGL-with-Artificial-Intelligence
原文作者:Gaurav Kishore, Prateek Vaishnav
译文由本站 robot-v1.0 翻译
前言
A 3D chess game that can be played between a computer and a human
可以在计算机和人之间玩的3D国际象棋游戏
介绍(Introduction)
国际象棋是一种两人战略游戏,玩家轮流尝试检查对手的国王.每一回合,玩家必须移动其棋子之一.每件作品都有一种特殊的移动方式,可在64个正方形的黑白交替板上移动.有关游戏的更多规则,请访问Wikipedia上的国际象棋文章.(Chess is a two-player game of strategy in which players take turns trying check the opponent’s King. On each turn, a player must move one of his pieces. Each piece has a particular way of moving over the board of 64 squares of alternate black & white ones. For further rules of the game, visit the chess article on Wikipedia.)
背景(Background)
国际象棋游戏主要分为五个阶段:(The chess game has been developed in mainly 5 stages:)
- 董事会代表:两名未签名(Board Representation: Two unsigned)
int
由于编译器是32位的,所以数字用于表示板.通过重载所有必需的运算符来创建具有64位所有功能的类.(numbers are used to represent the board since the compiler is 32 bit. A class having all the functions of 64 bit has been made by overloading all the required operators.) - 移动生成:所有不同片段的可能移动已预先计算并存储在位板上.由于只需要移位操作,因此计算变得容易.(Move Generation: All the different pieces' possible moves have been precalculated and stored in bitboard. The calculation becomes easy as it requires only shift operations.)
- 评估功能:得分已分配给各个分块,用于保护和攻击对手的分块.分配了检查和核对国王的点数.(Evaluation function: Points have been allotted to the pieces and for protecting & attacking an opponent’s piece. Points for checking and checkmating the king are allotted.)
- 深度搜索:添加评估功能还不够,需要深入思考,实施了Minmax树.(Depth Searching: Adding evaluation function was not enough, thinking in depth was required, Minmax tree was implemented.)
- 终结游戏:阻止了导致国王检定的可能举动,并实施了将死条件,以便游戏结束.(End game: The possible moves that led itself to king check were blocked and the condition for checkmate was implemented so that the game could end.)
使用代码(Using the Code)
该类定义了一个包含两个U32数字的位板.这样就形成了一个64位的板.所有按位运算符都被重载以使用两个32位数字.(The class defines a bit board which comprises two U32 numbers. This makes a board of 64 bits. All the bitwise operators are overloaded so as to work with two 32 bit numbers.)
class U64
{
public:
U32 l, h;
U64()
{
l = 0x0;
h = 0x0;
}
U64 operator |(U64);
U64 operator &(U64);
U64 operator ^(U64);
U64 operator ~(void);
U64 operator <<(int a);
U64 operator >>(int b);
void operator =(int sq);
void operator |=(int sq);
void display();
int getAndClearLSB();
bool check(){
if( !( l | h) )
return false;
else
return true;
}
};
各个块的类定义位板还定义了预先计算和存储的各种板,例如可能的移动.构造函数声明各个块的所有位板的初始状态.(The class defining bitboard of various pieces also defines various boards that are precalculated and stored such as possible moves. The constructor declares the initial status of all the bitboards of various pieces.)
class CBoard {
public:
int side;
U64 Pieces[2][7];
U64 Knightsmove[64];
U64 Kingmove[64];
U64 right_board[64];
U64 left_board[64];
U64 up_board[64];
U64 down_board[64];
U64 _45deg_board[64];
U64 _225deg_board[64];
U64 _135deg_board[64];
U64 _315deg_board[64];
U64 Pawnsmove[64][2];
U64 Pawnsdoublemove[64][2];
U64 Pawnsattackmove[64][2];
U64 fullboard[2];
U64 occupiedboard[2];
U64 unoccupiedboard[2];
U64 enemyboard[2];
U64 notfriendlyboard[2];
U64 friendlyboard[2];
U64 attackboard[2];
U64 doubledpawn[2];
U64 isolatedpawn[2];
U64 backwardpawn[2];
U64 kngchk[7];
void validmove();
CBoard();
}bitboard;
我想展示使用位移位操作生成rook的可能动作.首先,预先计算以下位板:(I would like to demonstrate the generation of rook’s possible moves using bit shift operations. First, precalculate the following bitboards:)
right_board[64]
-每个正方形的位板,所有正方形位于正方形集的右侧(- A bitboard for every square with all squares to the right of the square set)left_board[64]
-每个正方形的左面板,所有正方形都位于正方形集的左侧(- A bitboard for every square with all squares to the left of the square set)up_board[64]
-每个正方形都高于正方形集的所有正方形的位图板(- A bitboard for every square with all squares above the square set)down_board[64]
-每个正方形都低于正方形集的所有正方形的位图板(- A bitboard for every square with all squares below the square set) 为了计算车可以移动到的右边的平方,我们执行以下操作:(To calculate the squares to the right where the rook can move to, we do the following:)
//right_moves = right_board[sq] AND occupiedboard
我们这样做是因为第一部分将阻止车队向右移动.由于第一个片段会停止该流氓,因此我们需要填写该片段右侧的所有正方形((We do this because the first piece will stop the rook moving to the right. Because the first piece will stop the rook, we need to fill in all the squares to the right of the piece () << 1
表示左移(means shift left one,) < 2
表示左移2,依此类推):(means shift left 2, etc):)
right_moves = (right_moves<<1) OR (right_moves<<2) OR (right_moves<<3) OR
(right_moves<<4) OR (right_moves<<5) OR (right_moves<<6)
为了摆脱溢出到下一行的位,我们(To get rid of the bits that overflowed to the next row, we) AND
结果与(the result with) right_board
:(:)
right_moves = right_moves AND right_board
这是车无法移动到右边的所有正方形.为了获得车可以移动到的方块,我们将独家(This is all the squares to the right where the rook can’t move to. To get the squares where the rook can move to, we exclusive) OR
与董事会(the board with) right_board
:(:)
right_moves = right_moves XOR right_board
您会注意到,车子右边所有可以移动到的方块.但是,如果F3上的棋子是黑色棋子怎么办?然后我们无法捕获它,因此我们需要执行最后一个操作:(You will notice that that all the squares to the right of the rook where it can move to. But what if the pawn on F3 was a black pawn? Then we can’t capture it, thus we need one last operation:) right_moves = right moves AND enemy_and_empty_squares
.(.)
inline U64 genRookAttackBoard(int sq)
{
bool side=bitboard.side;
U64 leftboard = (bitboard.occupiedboard[side] & bitboard.left_board[sq]);
leftboard = (leftboard>>1)|(leftboard>>2)|(leftboard>>3)|
(leftboard>>4)|(leftboard>>5)|(leftboard>>6);
leftboard = (leftboard & bitboard.left_board[sq])^bitboard.left_board[sq];
U64 rightboard = (bitboard.occupiedboard[side] & bitboard.right_board[sq]);
rightboard = (rightboard<<1)|(rightboard<<2)|(rightboard<<3)|
(rightboard<<4)|(rightboard<<5)|(rightboard<<6);
rightboard = (rightboard & bitboard.right_board[sq]) ^ bitboard.right_board[sq];
U64 upboard = (bitboard.occupiedboard[side] & bitboard.up_board[sq]);
upboard = (upboard<<8)|(upboard<<16)|(upboard<<24)|
(upboard<<32)|(upboard<<40)|(upboard<<48);
upboard = (upboard & bitboard.up_board[sq]) ^ bitboard.up_board[sq];
U64 downboard = (bitboard.occupiedboard[side] & bitboard.down_board[sq]);
downboard = (downboard>>8)|(downboard>>16)|(downboard>>24)|
(downboard>>32)|(downboard>>40)|(downboard>>48);
downboard = (downboard & bitboard.down_board[sq]) ^ bitboard.down_board[sq];
return (leftboard | rightboard | upboard | downboard) &
bitboard.notfriendlyboard[side];
}
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
Linux OpenGL 新闻 翻译