I use the term "gainer" to indicate a move that is a capture or a promotion or both. Underpromotions are included. (The opposite of a gainer is a "holder".) So, what some call a "capture search", I call a "gainer search". And if a program has a gainer search, it has to have a gainer move generator.
Here's Bozo's gainer move generator:
Code: Select all
procedure PosGenerateGainers(var pos: postype; var gms: gmstype);
var
goodkingsq: sqtype;
goodbb, evilbb: bbtype;
frbb, tobb: bbtype;
frsq, tosq: sqxtype;
frman: manrtype;
r7brank: branktype;
r7flag: Boolean;
advdir, capdir: dirtype;
resdir: dirxtype;
pawnatkbb: bbtype;
epmove: movetype;
begin
GmsReset(gms);
with pos, board, bbdb do
begin
{ Initialize for the good man scan }
goodkingsq := ksqv[good]; goodbb := locbc[good]; evilbb := locbc[evil];
BbAnd2C2(frbb, goodbb, fmbb);
r7brank := normalbrank[good, brank7]; advdir := pawnadvdir[good];
{ Loop once for each possible moving man }
repeat
frsq := BbNextSq(frbb);
if frsq <> sqnil then
begin
{ Fetch the moving man and process by its piece kind }
frman := sqv[frsq];
case mantopiece[frman] of
piecep:
begin
{ Set various pre-generation data for this pawn }
r7flag := MapSqToBrank(frsq) = r7brank;
if BbTestSq(pmbb, frsq) then
resdir := compass[goodkingsq, frsq]
else
resdir := dirnil;
pawnatkbb := pawnatkbbvec[good, frsq];
{ Pawn noncapture promotions }
if (resdir = dirnil) or IsDirxOrtho(resdir) then
if r7flag then
begin
tosq := advance[frsq, advdir];
if not BbTestSq(merge, tosq) then GmsPushPsHold(gms, frsq, tosq, frman)
end;
{ Pawn capture moves (includes capture promotions; not en passant) }
BbAnd2(tobb, pawnatkbb, evilbb);
repeat
tosq := BbNextSq(tobb);
if tosq <> sqnil then
begin
capdir := compass[frsq, tosq];
if (resdir = dirnil) or (resdir = capdir) then
if r7flag then
GmsPushPsCapt(gms, frsq, tosq, frman, sqv[tosq])
else
GmsPushM2(gms, frsq, tosq, frman, sqv[tosq])
end
until tosq = sqnil;
{ En passant capture }
if epsq <> sqnil then
if BbTestSq(pawnatkbb, epsq) then
begin
MoveSynthM4(epmove, frsq, epsq, frman, mscepc);
if PosIsEnPassantMoveLegal(pos, epmove) then GmsPush(gms, epmove)
end
end;
piecen:
begin
{ Regular knight capturing moves }
BbAnd2(tobb, atkfs[frsq], evilbb);
repeat
tosq := BbNextSq(tobb);
if tosq <> sqnil then GmsPushM2(gms, frsq, tosq, frman, sqv[tosq])
until tosq = sqnil
end;
pieceb, piecer, pieceq:
begin
{ Regular sweeper capturing moves }
BbAnd2(tobb, atkfs[frsq], evilbb);
if BbTestSq(pmbb, frsq) then BbAnd2D(tobb, beamerbbvec[goodkingsq, frsq]);
repeat
tosq := BbNextSq(tobb);
if tosq <> sqnil then GmsPushM2(gms, frsq, tosq, frman, sqv[tosq])
until tosq = sqnil
end;
piecek:
begin
{ Regular king capturing moves }
BbAnd2(tobb, atkfs[frsq], evilbb); BbAnd2C2D(tobb, atkbc[evil]);
repeat
tosq := BbNextSq(tobb);
if tosq <> sqnil then GmsPushM2(gms, frsq, tosq, frman, sqv[tosq])
until tosq = sqnil;
end;
end
end
until frsq = sqnil
end
end; { PosGenerateGainers }