📄 movegener.cpp
字号:
cnt++;
return cnt;
}
/*
在没有发生和棋前计算棋格被占据的次数
movetab[back..Depth] 包含先前的移动
当 immediate 设置时,只有接连重复才算。
连续三次局面重复算是和棋
*/
REPEATTYPE Repetition(short immediate)
{
DEPTHTYPE lastdep, compdep, tracedep, checkdep, samedepth;
SQUARETYPE tracesq, checksq;
REPEATTYPE repeatcount;
repeatcount = 1;
lastdep = samedepth = DEPTHTYPE(Depth + 1); /* 当前位置的深度 */
compdep = DEPTHTYPE(samedepth - 4); /* 与第一次棋子位置进行比较 */
/*
MoveTable[lastdep..Depth]包含了先前相关的移动
*/
while (RepeatMove(&MoveTable[lastdep - 1]) && (compdep < lastdep ||
!immediate))
lastdep--;
if (compdep < lastdep)
return repeatcount;
checkdep = samedepth;
do
{
checkdep--;
checksq = MoveTable[checkdep].newpos1;
for (tracedep = DEPTHTYPE(checkdep + 2); tracedep < samedepth; tracedep += DEPTHTYPE(2))
if (MoveTable[tracedep].oldpos == checksq) goto TENMOV;
/* 回溯移动,看是否以前出现过悔棋 */
tracedep = checkdep;
tracesq = MoveTable[tracedep].oldpos;
do
{
if (tracedep-2 < lastdep) return repeatcount;
tracedep -= (DEPTHTYPE)2;
/* 检查棋子先前是否移动过 */
if (tracesq == MoveTable[tracedep].newpos1) tracesq =
MoveTable[tracedep].oldpos;
} while (tracesq != checksq || tracedep > compdep + 1);
if (tracedep < compdep) /* 调整比较的深度 */
{
compdep = tracedep;
if ((samedepth - compdep) % 2 == 1)
{
if (compdep == lastdep) return repeatcount;
compdep --;
}
checkdep = samedepth;
}
/*
在同一深度和比较深度之间进行移动检查,决定是否能找到重复局面
*/
TENMOV : if (checkdep <= compdep)
{
repeatcount++;
if (compdep - 2 < lastdep) return repeatcount;
checkdep = samedepth = compdep;
compdep -= (DEPTHTYPE)2;
}
} while (1);
}
/*
把生成的移动保存在缓冲区
*/
static void Generate()
{
BufCount++;
Buffer[BufCount] = Next;
}
/*
根据棋子表生成吃子移动
*/
static void CapMovGen()
{
INDEXTYPE i;
Next.content = ChessBoard[Next.newpos1].piece;
for (i = PawnNumber[Player]; i >= 0; i--)
if (PieceTable[Player][i].ipiece != empty)
if (PieceAttacks(PieceTable[Player][i].ipiece, Player,
PieceTable[Player][i].isquare, Next.newpos1))
{
Next.oldpos = PieceTable[Player][i].isquare;
Next.movpiece = PieceTable[Player][i].ipiece;
Generate();
}
}
/*
根据棋子原先的位置生成非吃子移动
*/
static void NonCapMovGen()
{
DIRTYPE first, last, dir;
int direction;
EDGESQUARETYPE newsq;
int tmpBishopDir,tmpKnightDir;
Next.spe = 0;
Next.movpiece = ChessBoard[Next.oldpos].piece;
Next.content = empty;
switch (Next.movpiece)
{
/* 生成几个方向的非吃子移动。兵未过河时,只有一个方向;过河后,有三个方向 */
case pawn :
newsq = Next.oldpos + 0x10;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == red)
if (( newsq >= 0x40) && ( newsq <= 0x98))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos + 1;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == red)
if (( newsq >= 0x50) && ( newsq <= 0x98))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos - 1;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == red)
if (( newsq >= 0x50) && ( newsq <= 0x98))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos - 0x10;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == black)
if (( newsq <= 0x58) && ( newsq <= 0x98))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos + 1;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == black)
if (( newsq <= 0x48) && ( newsq <= 0x98))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos - 1;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == black)
if (( newsq <= 0x48) && ( newsq <= 0x98))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
break;
/* 生成王四个方向的非吃子移动 */
case king :
newsq = Next.oldpos + 1;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == red)
if (( newsq >=0) && ( newsq <= 0x28) && ((newsq % 16) >=3)
&& ((newsq % 16) <=5))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos - 1;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == red)
if (( newsq >=0) && ( newsq <= 0x28) && ((newsq % 16) >=3)
&& ((newsq % 16) <=5))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos + 0x10;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == red)
if (( newsq >=0) && ( newsq <= 0x28) && ((newsq % 16) >=3)
&& ((newsq % 16) <=5))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos - 0x10;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == red)
if (( newsq >=0) && ( newsq <= 0x28) && ((newsq % 16) >=3)
&& ((newsq % 16) <=5))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos + 1;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == black)
if (( newsq >= 0x70) && ( newsq <= 0x98) && ((newsq % 16) >=3)
&& ((newsq % 16) <=5))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos - 1;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == black)
if (( newsq >= 0x70) && ( newsq <= 0x98) && ((newsq % 16) >=3)
&& ((newsq % 16) <=5))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos + 0x10;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == black)
if (( newsq >= 0x70) && ( newsq <= 0x98) && ((newsq % 16) >=3)
&& ((newsq % 16) <=5))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
newsq = Next.oldpos - 0x10;
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == black)
if (( newsq >= 0x70) && ( newsq <= 0x98) && ((newsq % 16) >=3)
&& ((newsq % 16) <=5))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
break;
/* 生成士四个方向的非吃子移动 */
case assist :
for (dir = 3; dir >= 0; dir--)
{
newsq = Next.oldpos + AssistDir[dir];
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == red)
if (( newsq >=0) && ( newsq <= 0x28) && ((newsq % 16) >=3)
&& ((newsq % 16) <=5))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
}
for (dir = 3; dir >= 0; dir--)
{
newsq = Next.oldpos + AssistDir[dir];
if (((newsq)<=0x98) && (newsq >= 0 ))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (ChessBoard[Next.oldpos].color == black)
if (( newsq >= 0x70) && ( newsq <= 0x98) && ((newsq % 16) >=3)
&& ((newsq % 16) <=5))
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
}
break;
/* 生成象四个方向的非吃子移动 */
case bishop:
first = 3;
last = 0;
for (dir = first; dir >= last; dir--)
{
direction = BishopDir[dir];
newsq = Next.oldpos + direction;
if (BishopDir[dir]== 0x1E)
tmpBishopDir = 0x0F;
if (BishopDir[dir]== -0x1E)
tmpBishopDir= -0x0F;
if (BishopDir[dir]== 0x22)
tmpBishopDir= 0x11;
if (BishopDir[dir]== -0x22)
tmpBishopDir= -0x11;
if ((newsq <= 0x98) && (newsq >=0))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (((newsq-tmpBishopDir) <= 0x98) && ((newsq-tmpBishopDir) >=0))
if ((((newsq-tmpBishopDir)>>4)<10) && (((newsq-tmpBishopDir) % 16)< 9))
if (( ChessBoard[newsq - tmpBishopDir].piece == empty ))
if (ChessBoard[newsq].piece == empty)
if (ChessBoard[Next.oldpos].color == red)
if (( newsq >=0) && ( newsq <= 0x48))
Next.newpos1 = newsq;
Generate();
}
for (dir = first; dir >= last; dir--)
{
direction = BishopDir[dir];
newsq = Next.oldpos + direction;
/* 生成四个方向的非吃子移动 */
if (BishopDir[dir]== 0x1E)
tmpBishopDir = 0x0F;
if (BishopDir[dir]== -0x1E)
tmpBishopDir= -0x0F;
if (BishopDir[dir]== 0x22)
tmpBishopDir= 0x11;
if (BishopDir[dir]== -0x22)
tmpBishopDir= -0x11;
if ((newsq <= 0x98) && (newsq >=0))
if (((newsq>>4)<10) && ((newsq % 16)<9) && ((newsq | 0xff)>=0))
if (((newsq - tmpBishopDir)<= 0x98) && ((newsq - tmpBishopDir) >=0))
if ((((newsq-tmpBishopDir)>>4)<10) && (((newsq-tmpBishopDir) % 16)< 9) &&
(((newsq-tmpBishopDir) | 0xff)>= 0))
if (( ChessBoard[newsq - tmpBishopDir].piece == empty ))
if (ChessBoard[newsq].piece == empty)
if (ChessBoard[Next.oldpos].color == black)
if (( newsq >= 0x50) && ( newsq <= 0x98))
Next.newpos1 = newsq;
Generate();
}
break;
case knight : //马
for (dir = 7; dir >= 0; dir--)
{
newsq = Next.oldpos + KnightDir[dir];
/* 生成八个方向的非吃子移动 */
if (KnightDir[dir] == 0x0E)
tmpKnightDir= 0x0F;
if (KnightDir[dir]== -0x0E)
tmpKnightDir= -0x0F;
if (KnightDir[dir]== 0x12)
tmpKnightDir = 0x11;
if (KnightDir[dir]== -0x12)
tmpKnightDir = -0x11;
if (KnightDir[dir]== 0x1F)
tmpKnightDir = 0x0F;
if (KnightDir[dir]== -0x1F)
tmpKnightDir = -0x0F;
if (KnightDir[dir]== 0x21)
tmpKnightDir = 0x11;
if (KnightDir[dir]== -0x21)
tmpKnightDir = -0x11;
if ((newsq <= 0x98) && (newsq >=0))
if (((newsq % 16)>=0) && ((newsq % 16)< 9) && ((newsq | 0xff)>=0))
if (((newsq-tmpKnightDir) <= 0x98) && ((newsq-tmpKnightDir) >=0))
if ((((newsq-tmpKnightDir) /16)<10) && (((newsq-tmpKnightDir) % 16) < 9) &&
(((newsq-tmpKnightDir) | 0xff) >= 0))
if ( ChessBoard[newsq - tmpKnightDir].piece == empty )
if (ChessBoard[newsq].piece == empty)
{
Next.newpos1 = newsq;
Generate();
}
}
break;
case rook : //车
case gunner : //炮
first = 3;
last = 0;
for (dir = first; dir >= last; dir--)
{
direction = DirectionTab[dir];
newsq = Next.oldpos + direction;
/* 生成四个方向的非吃子移动 */
while (((newsq>>4)<10) && ((newsq % 16)<9) &&
(newsq <= 0x98) && (newsq >=0) && ((newsq | 0xff)>=0))
{
if (ChessBoard[newsq].piece != empty) goto TENNMOV;
Next.newpos1 = newsq;
Generate();
newsq = Next.newpos1 + direction;
}
TENNMOV: continue;
}
break;
} /* switch */
}
/*
生成移动
生成所有可能的移动并把它们逐个放在缓冲区内
开始:
Player 指移动棋子的一方.
MoveTable[Depth-1] 上一次执行过的移动.
结束:
缓冲区包含全部生成的移动
生成移动的顺序:
吃子
非吃子
*/
void InitMovGen()
{
INDEXTYPE index;
BufCount = BufPnt = 0;
/* 从王开始生成吃子移动 */
for (index = 0; index <= PawnNumber[Opponent]; index++)
if (PieceTable[Opponent][index].ipiece != empty)
{
Next.newpos1 = PieceTable[Opponent][index].isquare;
CapMovGen();
}
/* 从兵开始生成非吃子移动 */
for (index = PawnNumber[Player]; index >= 0; index--)
if (PieceTable[Player][index].ipiece != empty)
{
Next.oldpos = PieceTable[Player][index].isquare;
NonCapMovGen();
}
}
/*
把生成的移动一个连一个地保存在Next链表中。没有棋子可移动时生成零移动
*/
void MovGen()
{
if (BufPnt >= BufCount)
Next = ZeroMove;
else
{
BufPnt++;
Next = Buffer[BufPnt];
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -