📄 movgen.cpp
字号:
// ObjectWindows - (C) Copyright 1992 by Borland International
#include <math.h>
#include "wcdefs.h"
#include "externs.h"
/*
* Globals
*/
static ATTACKTABTYPE attack[240];
ATTACKTABTYPE *AttackTab = &attack[120];
SETOFPIECE BitTab[7] = {0, 1, 2, 4, 8, 0x10, 0x20};
int DirTab[8] = { 1, -1, 0x10, -0x10, 0x11, -0x11, 0x0f, -0x0f};
int KnightDir[8] = {0x0E, -0x0E, 0x12, -0x12, 0x1f, -0x1f, 0x21, -0x21};
int PawnDir[2] = {0x10, -0x10};
MOVETYPE Next;
int BufCount, BufPnt;
MOVETYPE Buffer[81];
CASTMOVETYPE CastMove[2][2] = { {{2, 4}, {6, 4}}, {{0x72, 0x74}, {0x76, 0x74}} };
void CalcAttackTab(void)
{
DIRTYPE dir;
int sq;
unsigned char i;
for (sq = -0x77; sq <= 0x77; sq++)
{
AttackTab[sq].pieceset = 0;
AttackTab[sq].direction = 0;
}
for (dir = 7; dir >=0; dir--)
{
for (i = 1; i < 8; i++)
{
if (dir < 4)
AttackTab[DirTab[dir]*i].pieceset = BitTab[queen]+BitTab[rook];
else
AttackTab[DirTab[dir]*i].pieceset = BitTab[queen]+BitTab[bishop];
AttackTab[DirTab[dir]*i].direction = DirTab[dir];
}
AttackTab[DirTab[dir]].pieceset += BitTab[king];
AttackTab[KnightDir[dir]].pieceset = BitTab[knight];
AttackTab[KnightDir[dir]].direction = KnightDir[dir];
}
}
/*
* calculate whether apiece placed on asquare attacks the square
*/
short PieceAttacks(PIECETYPE apiece, COLORTYPE acolor,
SQUARETYPE asquare, SQUARETYPE square)
{
EDGESQUARETYPE sq;
int x;
x = square - asquare;
if (apiece == pawn) /* pawn attacks */
return (abs(x - PawnDir[acolor]) == 1);
/* other attacks: can the piece move to the square? */
else if (AttackTab[x].pieceset & BitTab[apiece])
{
if (apiece == king || apiece == knight)
return 1;
else
{
/* are there any blocking pieces in between? */
sq = asquare;
do
{
sq += AttackTab[x].direction;
} while (sq != square && Board[sq].piece == empty );
return (sq == square);
}
}
else
return 0;
}
/*
* calculate whether acolor attacks the square with at pawn
*/
short PawnAttacks(COLORTYPE acolor, SQUARETYPE square)
{
EDGESQUARETYPE sq;
sq = square - PawnDir[acolor] - 1; /* left square */
if (!(sq & 0x88))
if (Board[sq].piece == pawn && Board[sq].color == acolor)
return 1;
sq += 2; /* right square */
if (!(sq & 0x88))
if (Board[sq].piece == pawn && Board[sq].color == acolor)
return 1;
return 0;
}
/*
* Calculates whether acolor attacks the square
*/
short Attacks(COLORTYPE acolor, SQUARETYPE square)
{
INDEXTYPE i;
if (PawnAttacks(acolor, square)) /* pawn attacks */
return 1;
/* Other attacks: try all pieces, starting with the smallest */
for (i = OfficerNo[acolor]; i >= 0; i--)
if (PieceTab[acolor][i].ipiece != empty)
if (PieceAttacks(PieceTab[acolor][i].ipiece, acolor,
PieceTab[acolor][i].isquare, square))
return 1;
return 0;
}
/*
* check whether inpiece is placed on square and has never moved
*/
short Check(SQUARETYPE square, PIECETYPE inpiece, COLORTYPE incolor)
{
DEPTHTYPE dep;
if(Board[square].piece == inpiece && Board[square].color == incolor)
{
dep = Depth - 1;
while (MovTab[dep].movpiece != empty)
{
if (MovTab[dep].new1 == square)
return 0;
dep--;
}
return 1;
}
return 0;
}
/*
* Calculate whether incolor can castle
*/
void CalcCastling(COLORTYPE incolor, CASTDIRTYPE *cast)
{
SQUARETYPE square = 0;
if (incolor == black) square = 0x70;
*cast = zero;
if (Check(square + 4, king, incolor)) /* check king */
{
if (Check(square, rook, incolor))
((int)*cast) += lng; /* check a-rook */
if (Check(square + 7, rook, incolor))
((int)*cast) += shrt; /* check h-rook */
}
}
/*
* check if move is a pawn move or a capture
*/
inline short RepeatMove(MOVETYPE *move)
{
return (move->movpiece != empty && move->movpiece != pawn &&
move->content == empty && !move->spe);
}
/****************************************************************************/
/*
* Count the number of moves since last capture or pawn move
* The game is a draw when fiftymovecnt = 100
*/
FIFTYTYPE FiftyMoveCnt(void)
{
FIFTYTYPE cnt = 0;
while (RepeatMove(&MovTab[Depth - cnt]))
cnt++;
return cnt;
}
/*
* Calculate how many times the position has occured before
* The game is a draw when repetition = 3;
* movetab[back..Depth] contains the previous moves
* When immediate is set, only immediate repetion is checked
*/
REPEATTYPE Repetition(short immediate)
{
DEPTHTYPE lastdep, compdep, tracedep, checkdep, samedepth;
SQUARETYPE tracesq, checksq;
REPEATTYPE repeatcount;
repeatcount = 1;
lastdep = samedepth = Depth + 1; /* current postion */
compdep = samedepth - 4; /* First position to compare */
/* MovTab[lastdep..Depth] contains previous relevant moves */
while (RepeatMove(&MovTab[lastdep - 1]) && (compdep < lastdep ||
!immediate))
lastdep--;
if (compdep < lastdep)
return repeatcount;
checkdep = samedepth;
do
{
checkdep--;
checksq = MovTab[checkdep].new1;
for (tracedep = checkdep + 2; tracedep < samedepth; tracedep += 2)
if (MovTab[tracedep].old == checksq) goto TEN;
/* Trace the move backward to see if it has been 'undone' earlier */
tracedep = checkdep;
tracesq = MovTab[tracedep].old;
do
{
if (tracedep-2 < lastdep) return repeatcount;
tracedep -= 2;
/* Check if piece has been moved before */
if (tracesq == MovTab[tracedep].new1) tracesq =
MovTab[tracedep].old;
} while (tracesq != checksq || tracedep > compdep + 1);
if (tracedep < compdep) /* Adjust evt. compdep */
{
compdep = tracedep;
if ((samedepth - compdep) % 2 == 1)
{
if (compdep == lastdep) return repeatcount;
compdep --;
}
checkdep = samedepth;
}
/* All moves between SAMEDEP and compdep have been checked,
so a repetition is found */
TEN : if (checkdep <= compdep)
{
repeatcount++;
if (compdep - 2 < lastdep) return repeatcount;
checkdep = samedepth = compdep;
compdep -= 2;
}
} while (1);
}
/*
* Test whether a move is possible
*
* On entry:
* Move contains a full description of a move, which
* has been legally generated in a different position.
* MovTab[Depth - 1] contains last performed move.
*
* On exit:
* KillMovGen indicates whether the move is possible
*/
short KillMovGen(MOVETYPE *move)
{
SQUARETYPE castsq;
PIECETYPE promote;
CASTDIRTYPE castdir;
CASTTYPE cast;
short killmov;
killmov = 0;
if (move->spe && (move->movpiece == king))
{
CalcCastling(Player, &cast); /* Castling */
if (move->new1 > move->old)
castdir = shrt;
else
castdir = lng;
if (cast & castdir) /* Has king or rook moved before */
{
castsq = (int)((move->new1 + move->old) / 2);
/* Are the squares empty ? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -