Author: Michel Langeveld
Date: 08:49:11 12/06/01
Go up one level in this thread
On December 06, 2001 at 08:31:44, Tony Werten wrote:
>On December 06, 2001 at 07:58:14, Michel Langeveld wrote:
>
>>I have a problem in my program (nullmover).
>>
>>My program sees at an early ply (ply 7) already a mate in 5 with extensions and
>>qsearch. This with hashing of alpha bounds and truebounds.
>>
>>When I hash also my beta bounds nullmover does not see it anymore. Does anybody
>>has an idea how this could happen?
>
>Guessing from this little information: Your storing/retrieving of the
>checkmatescore goes wrong.
>
>Tony
>
>>
>>regards,
>>
>>Michel
Thanks for the tip. I have to debug that part then. To be more precise. Here's a
part of my source code. As you can see I have special parts for black and
special parts for white.
//////////////////////////////////////////////////////
//Qsearch of white
//Here only captures and promotions are searched
//////////////////////////////////////////////////////
scoreType qsearchWhite(scoreType alpha, scoreType beta)
{
nodeCounter++;
moveListType ml;
log << cin.eof() << endl;
log << cin.rdbuf()->in_avail() << endl;
checkTest = attackedByBlack(p.whiteKingField);
if (isWhiteCantMove() )
{
//mate or stalemate
if (checkTest) //checkTest is set in previous function
{
return -9999;
}
else
{
return 0;
}
}
scoreType val = generatePositionScore2();
#ifndef QSEARCH
return val;
#endif
if (val >= beta)
{
return beta;
}
if (val > alpha)
{
alpha = val;
}
generateWhiteCapturesMoveList( &ml );
sortMoveList( &ml );
//just for debugging purposes
if (ml.number > 39)
{
printPosition(cout, p, true);
cerr << "!! new maximum found of: " << ml.number << endl;
exit(1);
}
hashType oldHash = p.dynHash;
char oldRights = p.castlingRights;
fieldType oldEpField = p.epField;
for (int i=0; i< ml.number; i++)
{
doWhiteMove(ml.moves[i]);
val = -qsearchBlack(-beta, -alpha);
restoreWhiteMove(ml.moves[i], oldEpField, oldRights, oldHash);
if (val >= beta) return beta;
if (val > alpha) alpha = val;
}
return alpha;
}
//////////////////////////////////////////////////////
//Qsearch of black
//Here only captures and promotions are searched
//////////////////////////////////////////////////////
scoreType qsearchBlack(scoreType alpha, scoreType beta)
{
nodeCounter++;
moveListType ml;
checkTest = attackedByWhite(p.blackKingField);
if (isBlackCantMove() )
{
//mate or stalemate
if (checkTest) //checkTest is set in previous function
{
return -9999;
}
else
{
return 0;
}
}
scoreType val = -generatePositionScore2();
#ifndef QSEARCH
return val;
#endif
if (val >= beta)
{
return beta;
}
if (val > alpha)
{
alpha = val;
}
generateBlackCapturesMoveList( &ml );
sortMoveList( &ml );
if (ml.number > 39)
{
printPosition(cout, p, true);
cerr << "!! new maximum found of: " << ml.number << endl;
exit(1);
}
hashType oldHash = p.dynHash;
char oldRights = p.castlingRights;
fieldType oldEpField = p.epField;
for (int i=0; i< ml.number; i++)
{
doBlackMove(ml.moves[i]);
val = -qsearchWhite(-beta, -alpha);
restoreBlackMove(ml.moves[i], oldEpField, oldRights, oldHash);
if (val >= beta) return beta;
if (val > alpha) alpha = val;
}
return alpha;
}
//////////////////////////////////////////////////////
//Look in the hashtable if our move is present.
//////////////////////////////////////////////////////
scoreType probeHash(int depth, scoreType alpha, scoreType beta /*, moveType
&bestMove*/)
{
hashTableType *pHashRecord = &hashTable[p.dynHash & HASHMASK];
if (pHashRecord->key == p.dynHash)
{
if (pHashRecord->depth >= depth)
{
switch(pHashRecord->flags)
{
case HASH_FLAGS_EXACT:
{
return pHashRecord->value;
}
case HASH_FLAGS_ALPHA:
{
if (pHashRecord->value <= alpha)
{
return alpha;
}
break;
}
case HASH_FLAGS_BETA:
{
if (pHashRecord->value >= beta)
{
return beta;
}
break;
}
}
}
}
return HASH_UNKNOWN_VALUE;
}
//////////////////////////////////////////////////////
//Record the hashmove
//////////////////////////////////////////////////////
void recordHash(int depth, scoreType value, int flags /*, moveType &bestMove*/)
{
hashTableType *pHashRecord = &hashTable[p.dynHash & HASHMASK];
if (depth >= pHashRecord->depth)
{
pHashRecord->key = p.dynHash;
pHashRecord->value = value;
pHashRecord->flags = flags;
pHashRecord->depth = depth;
//pHashRecord->bestMove = bestMove;
}
}
//////////////////////////////////////////////////////
//Alphabeta for white
//////////////////////////////////////////////////////
#ifdef LINE
scoreType alphaBetaWhite(int depth, scoreType alpha, scoreType beta,struct
historyListType* pline)
#else
scoreType alphaBetaWhite(int depth, scoreType alpha, scoreType beta)
#endif
{
nodeCounter++;
moveListType ml;
#ifdef LINE
struct historyListType line;
#endif
#ifdef DOHASHWHITE
//moveType bestHashMove;
scoreType hashvalue = probeHash(depth, alpha, beta/*, bestHashMove*/);
int hashflags;
if (hashvalue != HASH_UNKNOWN_VALUE)
{
#ifdef LINE
pline->number = 0;
#endif
return hashvalue;
}
#endif
if (depth <= 0)
{
nodeCounter--; //don't add the nodecounter too much
scoreType qsearchvalue = qsearchWhite(alpha, beta);
#ifdef HASHQSEARCH
if (qsearchvalue <= alpha)
{
recordHash(depth, alpha, HASH_FLAGS_ALPHA/*, bestHashMove*/);
}
else if (qsearchvalue >= beta)
{
recordHash(depth, beta, HASH_FLAGS_BETA/*, bestHashMove*/);
}
else
{
recordHash(depth, qsearchvalue, HASH_FLAGS_EXACT/*, bestHashMove*/);
}
#endif
#ifdef LINE
pline->number = 0;
#endif
return qsearchvalue;
}
checkTest = attackedByBlack(p.whiteKingField);
if (isWhiteCantMove() )
{
//mate or stalemate
if (checkTest) //checkTest is set in previous function
{
#ifdef LINE
pline->number = 0;
#endif
return -9999;
}
else
{
#ifdef LINE
pline->number = 0;
#endif
return 0;
}
}
scoreType val;
hashType oldHash = p.dynHash;
char oldRights = p.castlingRights;
fieldType oldEpField = p.epField;
#ifdef NULLMOVE_ON
//don't do this if:
//1) We have already done a nullmove
//2) We come into qsearch immediatly
//3) We are in check
if (!nullmoved && depth - 1 - R >= 0 && !checkTest )
{
//do nullmove
doWhiteNullMove();
#ifdef LINE
val = -alphaBetaWhite(depth - 1 - R, -beta, -beta+1, &line);
#else
val = -alphaBetaWhite(depth - 1 - R, -beta, -beta+1);
#endif
restoreWhiteNullMove(oldEpField, oldHash);
if (val >= beta)
{
//set move so we can use this as best move
moveType m;
m.moveKind = NULLMOVE;
#ifdef LINE
pline->moves[0] = m;
memcpy((struct moveType*)&pline->moves[1], line.moves, line.number *
sizeof(moveType));
pline->number = line.number+1;
#endif
return beta;
}
}
#endif
generateWhiteMoveList( &ml );
sortMoveList( &ml );
int orgDepth = depth;
//extend moves that walk away from check
if (checkTest)
{
depth++;
}
//extend single moves
else if (ml.number == 1)
{
depth++;
}
//pawn push extension
//else if (p.board[p.history.moves[p.history.number-1].toField] == BLACKPAWN)
//
// depth++;
//}
#ifdef SEARCHINCDEPTH_ON_WHITE
scoreType orgAlpha = alpha;
scoreType orgBeta = beta;
for (int incdepth=1; incdepth<=depth; incdepth++)
{
alpha = orgAlpha;
beta = orgBeta;
#else
int incdepth=depth;
{
#endif
hashflags = HASH_FLAGS_ALPHA;
for (int i=0; i< ml.number; i++)
{
doWhiteMove(ml.moves[i]);
val = -alphaBetaBlack(incdepth-1, -beta, -alpha
#ifdef LINE
, &line
#endif
);
restoreWhiteMove(ml.moves[i], oldEpField, oldRights, oldHash);
if (incdepth < depth)
{
if (val > alpha)
{
#ifdef DOHASHWHITEINC
hashflags = HASH_FLAGS_EXACT;
#endif
alpha = val;
#ifdef TOP_ON
topMoveList(&ml, i);
#endif
}
if (val >= beta)
{
#ifdef HASHBETASINC
hashflags = HASH_FLAGS_BETA;
recordHash(incdepth, beta, HASH_FLAGS_BETA);
#endif
break;
}
}
else
{
if (val >= beta)
{
#ifdef HASHBETAS
recordHash(depth, beta, HASH_FLAGS_BETA /*, ml.moves[i]*/);
#endif
#ifdef LINE
pline->moves[0] = ml.moves[i];
memcpy((struct moveType*)&pline->moves[1], line.moves,
line.number * sizeof(moveType));
pline->number = line.number+1;
#endif
return beta;
}
if (val > alpha)
{
#ifdef DOHASHWHITE
hashflags = HASH_FLAGS_EXACT;
#endif
alpha = val;
#ifdef LINE
pline->moves[0] = ml.moves[i];
memcpy((struct moveType*)&pline->moves[1], line.moves,
line.number * sizeof(moveType));
pline->number = line.number+1;
#endif
}
}
}
}
#ifdef DOHASHWHITE
//moveType move;
recordHash(depth, alpha, hashflags/*, move*/);
#endif
return alpha;
}
//////////////////////////////////////////////////////
//Alphabeta for black
//////////////////////////////////////////////////////
scoreType alphaBetaBlack(int depth,
scoreType alpha,
scoreType beta
#ifdef LINE
,struct historyListType* pline
#endif
)
{
nodeCounter++;
moveListType ml;
#ifdef LINE
struct historyListType line;
#endif
#ifdef DOHASHBLACK
//moveType bestHashMove;
scoreType hashvalue = probeHash(depth, alpha, beta/*, bestHashMove*/);
int hashflags;
if (hashvalue != HASH_UNKNOWN_VALUE)
{
#ifdef LINE
pline->number = 0;
#endif
return hashvalue;
}
#endif
if (depth <= 0)
{
nodeCounter--; //don't add the nodecounter too much
scoreType qsearchvalue = qsearchBlack(alpha, beta);
#ifdef HASHQSEARCH
if (qsearchvalue <= alpha)
{
recordHash(depth, alpha, HASH_FLAGS_ALPHA/*, bestHashMove*/);
}
else if (qsearchvalue >= beta)
{
recordHash(depth, beta, HASH_FLAGS_BETA/*, bestHashMove*/);
}
else
{
recordHash(depth, qsearchvalue, HASH_FLAGS_EXACT/*, bestHashMove*/);
}
#endif
#ifdef LINE
pline->number = 0;
#endif
return qsearchvalue;
}
checkTest = attackedByWhite(p.blackKingField);
if (isBlackCantMove() )
{
//mate or stalemate
if (checkTest) //checkTest is set in previous function
{
#ifdef LINE
pline->number = 0;
#endif
return -9999;
}
else
{
#ifdef LINE
pline->number = 0;
#endif
return 0;
}
}
scoreType val;
hashType oldHash = p.dynHash;
char oldRights = p.castlingRights;
fieldType oldEpField = p.epField;
#ifdef NULLMOVE_ON
//don't do this if:
//1) We have already done a nullmove
//2) We come into qsearch immediatly
//3) We are in check
if (!nullmoved && depth - 1 - R >= 0 && !checkTest )
{
//do nullmove
doBlackNullMove();
val = -alphaBetaWhite(depth - 1 - R, -beta, -beta+1
#ifdef LINE
, &line
#endif
);
restoreBlackNullMove(oldEpField, oldHash);
if (val >= beta)
{
//set move so we can use this as best move
moveType m;
m.moveKind = NULLMOVE;
pline->moves[0] = m;
memcpy((struct moveType*)&pline->moves[1], line.moves, line.number *
sizeof(moveType));
pline->number = line.number+1;
return beta;
}
}
#endif
checkTest = attackedByWhite(p.blackKingField);
generateBlackMoveList( &ml );
sortMoveList( &ml );
int orgDepth = depth;
//extend moves that walk away from check
if (checkTest)
{
depth++;
}
//extend single moves
else if (ml.number == 1)
{
depth++;
}
//else if (p.board[p.history.moves[p.history.number-1].toField] == WHITEPAWN)
//{
//depth++;
//}
#ifdef SEARCHINCDEPTH_ON_BLACK
scoreType orgAlpha = alpha;
scoreType orgBeta = beta;
for (int incdepth=1; incdepth<=depth; incdepth++)
{
alpha = orgAlpha;
beta = orgBeta;
#else
int incdepth=depth;
{
#endif
hashflags = HASH_FLAGS_ALPHA;
for (int i=0; i< ml.number; i++)
{
doBlackMove(ml.moves[i]);
#ifdef LINE
val = -alphaBetaWhite(incdepth-1, -beta, -alpha, &line);
#else
val = -alphaBetaWhite(incdepth-1, -beta, -alpha);
#endif
restoreBlackMove(ml.moves[i], oldEpField,oldRights, oldHash);
if (incdepth < depth)
{
if (val > alpha)
{
#ifndef DOHASHBLACKINC
hashflags = HASH_FLAGS_EXACT;
#endif
alpha = val;
#ifdef TOP_ON
topMoveList(&ml, i);
#endif
}
if (val >= beta)
{
#ifdef HASHBETASINC
hashflags = HASH_FLAGS_BETA;
#endif
break;
}
}
else
{
if (val >= beta)
{
#ifdef HASHBETAS
hashflags = HASH_FLAGS_BETA;
recordHash(depth, beta, HASH_FLAGS_BETA /*, ml.moves[i]*/);
#endif
#ifdef LINE
pline->moves[0] = ml.moves[i];
memcpy((struct moveType*)&pline->moves[1], line.moves,
line.number * sizeof(moveType));
pline->number = line.number+1;
#endif
return beta;
}
if (val > alpha)
{
#ifdef DOHASHBLACK
hashflags = HASH_FLAGS_EXACT;
#endif
alpha = val;
#ifdef LINE
pline->moves[0] = ml.moves[i];
memcpy((struct moveType*)&pline->moves[1], line.moves,
line.number * sizeof(moveType));
pline->number = line.number+1;
#endif
}
}
}
}
#ifdef DOHASHBLACK
//moveType move;
recordHash(depth, alpha, hashflags/*, move*/);
#endif
return alpha;
}
//////////////////////////////////////////////////////
//Alphabeta for the root node
//////////////////////////////////////////////////////
scoreType alphaBetaRoot(int depth, moveType* bestMove, bool printTrueScore)
{
TimeStamp t;
t.startTimer();
nodeCounter = 1;
moveListType ml;
#ifdef LINE
struct historyListType bestline;
struct historyListType line;
#endif
//look if the side to move is in check
//if so set a global variable checkTest which is used in the move generator.
if (p.moveColor == WHITE)
{
checkTest = attackedByBlack(p.whiteKingField);
}
else
{
checkTest = attackedByWhite(p.blackKingField);
}
//Are we already mated?
if (isMate())
{
#ifdef LINE
bestline.number = 0;
#endif
return -9999;
}
//Are we stalemated?
if (isStaleMate())
{
#ifdef LINE
bestline.number = 0;
#endif
return 0;
}
//generate the movelist
if (p.moveColor == WHITE)
{
generateWhiteMoveList( &ml );
}
else
{
generateBlackMoveList( &ml );
}
//sort the movelist
//first are the captures
sortMoveList(&ml);
scoreType orgAlpha = -9999;
scoreType orgBeta = 9999;
scoreType alpha = orgAlpha;
scoreType beta = orgBeta;
char strScore[100];
int incdepth;
//we have only 1 move
//searching makes no sense then
if (ml.number == 1)
{
*bestMove = ml.moves[0];
alpha = 0;
}
else
{
scoreType val;
hashType oldHash = p.dynHash;
char oldRights = p.castlingRights;
fieldType oldEpField = p.epField;
//loop all moves until depth-1 so that the depth is one smaller
//than the one we give to this function
#ifdef SEARCHINCDEPTH_ON_ROOT
for (incdepth=1; 1; incdepth++)
#else
for (incdepth=depth; ; incdepth++)
#endif
{
#ifdef ASP_WINDOW
scoreType lastWindowAlpha = alpha;
scoreType lastWindowBeta = beta;
#endif
if (!xboardflag)
{
cout << "search on ply: " << incdepth << " alpha = " << alpha << ","
<< "beta = " << beta << endl;
}
else
{
log << "search on ply: " << incdepth << " alpha = " << alpha << ","
<< "beta = " << beta << endl;
}
bool bestMoveFound = false;
for (int i=0; i< ml.number; i++)
{
//set alpha and beta
//for printTrueScore we do this each time
//So that the searched move is allways between alpha and beta.
if (printTrueScore)
{
alpha = -9999;
beta = 9999;
}
if (p.moveColor == WHITE)
{
doWhiteMove(ml.moves[i]);
#ifdef LINE
val = -alphaBetaBlack(incdepth-1, -beta, -alpha, &line);
#else
val = -alphaBetaBlack(incdepth-1, -beta, -alpha);
#endif
restoreWhiteMove(ml.moves[i], oldEpField, oldRights, oldHash);
}
else
{
doBlackMove(ml.moves[i]);
#ifdef LINE
val = -alphaBetaWhite(incdepth-1, -beta, -alpha, &line);
#else
val = -alphaBetaWhite(incdepth-1, -beta, -alpha);
#endif
restoreBlackMove(ml.moves[i], oldEpField, oldRights, oldHash);
}
p.dynHash = oldHash;
p.castlingRights = oldRights;
p.epField = oldEpField;
//Set the score so we can print it later
ml.moves[i].score = val;
//we use !bestMoveFound here so that if the position is lost
//and result val = -9999 we still store a move
//so that we play always something
if (val > alpha || !bestMoveFound)
{
bestMoveFound = true;
alpha = val;
*bestMove = ml.moves[i];
#ifdef LINE
bestline.moves[0] = ml.moves[i];
memcpy(&bestline.moves[1], line.moves, line.number *
sizeof(moveType));
bestline.number = line.number+1;
#endif
/*
if (!xboardflag)
{
printMove(cout, *bestMove, true);
cout << endl;
}
else
{
printMove(log, *bestMove, true);
log << endl;
}*/
#ifdef TOP_ON
topMoveList(&ml, i);
#endif
sprintf(strScore, "%d", alpha);
}
//first set move... then do a break
//so this is an different order as the normal alpha beta
if (val >= beta)
{
break;
}
} //end moves
#ifdef ASP_WINDOW
/*
if (!xboardflag)
{
printAlphas(cout, alpha, beta, lastWindowAlpha, lastWindowBeta,
orgAlpha, orgBeta);
}
else
{
printAlphas(log, alpha, beta, lastWindowBeta, lastWindowAlpha,
orgAlpha, orgBeta);
}
*/
if (alpha > lastWindowAlpha && alpha < lastWindowBeta)
{
if (incdepth != depth)
{
//alpha is between orginal boundries, so we have an exact score
beta = alpha + VAL_WINDOW;
alpha = alpha - VAL_WINDOW;
}
}
else
{
int decDepth = incdepth-1;
if (alpha >= lastWindowBeta)
{
if (lastWindowBeta != orgBeta)
{
//alpha = lastWindowBeta;
//beta = orgBeta;
alpha = -9999;
beta = 9999;
incdepth = decDepth;
strcpy(strScore, "++");
}
else
{
strcpy(strScore, "WIN");
break;
}
}
else if (alpha <= lastWindowAlpha)
{
if (lastWindowAlpha != orgAlpha)
{
//beta = lastWindowAlpha+30;
//alpha = orgAlpha;
alpha = -9999;
beta = 9999;
incdepth = decDepth;
strcpy(strScore, "--");
}
else
{
strcpy(strScore, "LOSS");
break;
}
}
}
#else
if (incdepth != depth)
{
alpha = orgAlpha;
beta = orgBeta;
}
#endif
//
//print line to winboard
//
t.stopTimer();
char strTime[100];
sprintf(strTime, "%.0f", 100*t.diffTime()); //time is centiseconds
char strNodeCounter[100];
sprintf(strNodeCounter, "%I64u", nodeCounter);
cout << incdepth << " "; //depth
cout << strScore << " "; //score
cout << strTime << " ";
cout << strNodeCounter << " "; //nodecounter
#ifdef LINE
printPV(cout, (struct moveListType*)&bestline); //bestline
#endif
cout << endl << flush;
//do we use the time to stop or the clock?
if (depth <= 0)
{
if (chessclock.haveToPlay()) break;
}
else
{
if (incdepth == depth) break;
}
} //end inc depth
}
/////////////////////////////////////////////
//Log a few counters
/////////////////////////////////////////////
t.stopTimer();
double tijd = t.diffTime();
int nodes = (int)nodeCounter;
char strDepth[100];
sprintf(strDepth, "%d", incdepth);
if (!xboardflag)
{
cout << " // Depth: ";
cout << strDepth << endl;
}
log << strDepth << endl;
char strNodes[100];
sprintf(strNodes, "%I64u", nodeCounter);
if (!xboardflag)
{
cout << " // Nodes: ";
cout << strNodes << endl;
}
log << strNodes << endl;
char strTime[100];
sprintf(strTime, "%.2fs", tijd );
if (!xboardflag)
{
cout << " // Time: ";
cout << strTime << endl;
}
log << strTime << endl;
char strNps[100];
if (tijd == 0)
{
sprintf(strNps, "%s", "INFINITE");
}
else
{
sprintf(strNps, "%.2f", nodes / tijd );
}
if (!xboardflag)
{
cout << " // Nps: ";
cout << strNps << endl;
}
log << strNps << endl;
if (!xboardflag)
{
cout << " // Bestmove: ";
printMove(cout, *bestMove, true);
cout << endl;
}
if (xboardflag)
{
cout << "tellics whisper ";
cout << "depth:" << strDepth << ' ';
cout << "score:" << strScore << ' ';
cout << "time:" << strTime << ' ';
cout << "nps:" << strNps << ' ';
cout << "pv:";
printPV(cout, (struct moveListType*)&bestline); //bestline
cout << endl << flush;
}
log << " //bestmove : ";
printMove(log, *bestMove, true);
log << endl;
return alpha;
}
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.