Are my modifications correct?

Discussion of chess software programming and technical issues.

Moderator: Ras

tttony
Posts: 276
Joined: Sun Apr 24, 2011 12:33 am

Are my modifications correct?

Post by tttony »

Long time without asking here, now it's time to ask

The engine that I try to create it's based from Vice 1.0 --> https://chessprogramming.wikispaces.com/Vice

The things that I added to the engine are:

SqAttacked bitboard version
Added SearchRoot with PVS and Aspiration Window
Alphabeta PVS with LMR --> http://www.glaurungchess.com/lmr.html
IID for: pvnode && depth >= 4
IID for: cut_node && depth >= 6
And few other details

Now some code

Here is the "think" function:

Code: Select all

BestScore = SearchRoot(-INFINITE, INFINITE, 1, pos, info, RootInCheck);
for (currentDepth = 2; currentDepth <= info->depth; ++currentDepth) {
   rootDepth = currentDepth;
   BestScore = SearchWithAspiration(currentDepth, BestScore, pos, info, RootInCheck);
   if (info->stopped) {
     break;
   }
}
SearchWithAspiration function:

Code: Select all

int TempScore = Score;
	int alpha = Score - ASPIRATION; // ASPIRATION = 50
	int beta  = Score + ASPIRATION; 

	TempScore = SearchRoot(alpha, beta, depth, pos, info, InCheck);
	if (info->stopped) {
		return 0;
	}
	if (TempScore <= alpha || TempScore >= beta) {
		TempScore = SearchRoot(-INFINITE, INFINITE, depth, pos, info, InCheck);
		if (info->stopped) {
			return 0;
		}
	}
	return TempScore;
SearchRoot:

Code: Select all

int givesCheck = SqAttacked(pos->KingSq[pos->side], pos->side ^ 1, pos);

		if (BestScore == -INFINITE) {
			Score = -AlphaBeta(-beta, -alpha, depth - 1, pos, info, PV_NODE, givesCheck);
		}
		else {
			Score = -AlphaBeta(-alpha - 1, -alpha, depth - 1, pos, info, CUT_NODE, givesCheck);
			if (!info->stopped && Score > alpha && Score < beta) {
				Score = -AlphaBeta(-beta, -alpha, depth - 1, pos, info, PV_NODE, givesCheck);
			}
		}

  //....

if (Score > BestScore) {
			BestScore = Score;

			if (Score > alpha) {

				BestMove = rootMove;

				if (Score >= beta) {
					if (Legal == 1) {
						info->fhf++;
					}
					info->fh++;
					StoreHashEntry(pos, BestMove, beta, HFBETA, depth);
					return beta;
				}
				alpha = Score;

				_pvMove[rootDepth - 1] = rootMove;

				info->bound = EXACT_BOUND;
				DisplayPv(BestScore, pos, info);

			}
		}

//...

AlphaBeta:

Code: Select all

if (BestScore == -INFINITE) {
			Score = -AlphaBeta(-beta, -alpha, depth - 1, pos, info, NEW_NODE(nodeType), givesCheck);
		}
		else {
			if (!pvNode &&
				Legal >= FullDepthMoves &&
				depth >= ReductionLimit &&
				!InCheck &&
				!givesCheck &&
				!ISCAPTURE(move) &&
				move != ttMove &&
				!PROMOTED(move)) {
				Score = -AlphaBeta(-(alpha + 1), -alpha, depth - 2, pos, info, NEW_NODE(nodeType), givesCheck);
			} 
			else
				Score = alpha + 1;

			if (Score > alpha) {
				Score = -AlphaBeta(-(alpha + 1), -alpha, depth - 1, pos, info, CUT_NODE, givesCheck);
				if (!info->stopped && Score > alpha && Score < beta)
					Score = -AlphaBeta(-beta, -alpha, depth - 1, pos, info, PV_NODE, givesCheck);
			}
		}

   //.....


if (Score > BestScore) {

			BestScore = Score;
			BestMove = move;

			if (Score > alpha) {

				if (Score >= beta) {
					if (Legal == 1) {
						info->fhf++;
					}
					info->fh++;

					if (!ISCAPTURE(BestMove) && !InCheck) {
						if (BestMove != pos->searchKillers[0][pos->ply]) {
							pos->searchKillers[1][pos->ply] = pos->searchKillers[0][pos->ply];
							pos->searchKillers[0][pos->ply] = BestMove;
						}
					}
					StoreHashEntry(pos, BestMove, beta, HFBETA, depth);
					return beta;
				}
				alpha = Score;
				if (!ISCAPTURE(BestMove)) {
					pos->searchHistory[pos->pieces[FROMSQ(BestMove)]][TOSQ(BestMove)] += depth;
				}

				if (pvNode) {
					_pvMoves[pos->ply][0] = BestMove;
					int j = 0;
					for (j = 0; j < _pvLength[pos->ply + 1]; j++) {
						_pvMoves[pos->ply][j + 1] = _pvMoves[pos->ply + 1][j];
					}
					_pvLength[pos->ply] = _pvLength[pos->ply + 1] + 1;
				}
			}
		}

Sorry for long post, I'm trying to show the code where I think there is something wrong

With this new code and the same Evaluation function from Vice, running 1000 games vs Vice 1.0 1m+1s(can't play bullet games yet) the new version is not giving good results, like 40-45%

I'm expecting 50/55%(without touching eval function) score vs V1.0, I'm sure that there is something wrong, or something I have to change based on the things I've added
Aleks Peshkov
Posts: 979
Joined: Sun Nov 19, 2006 9:16 pm
Location: Russia
Full name: Aleks Peshkov

Re: Are my modifications correct?

Post by Aleks Peshkov »

I suggest you to restart from the root and implement features one by one with proper testing.
Ferdy
Posts: 4852
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Are my modifications correct?

Post by Ferdy »

Check limits.
tttony wrote: int TempScore = Score;
int alpha = Score - ASPIRATION; // ASPIRATION = 50
assert(alpha >= -INFINITE);
int beta = Score + ASPIRATION;
assert(beta <= INFINITE);

TempScore = SearchRoot(alpha, beta, depth, pos, info, InCheck);
if (info->stopped) {
return 0;
}
if (TempScore <= alpha || TempScore >= beta) {
TempScore = SearchRoot(-INFINITE, INFINITE, depth, pos, info, InCheck);
if (info->stopped) {
return 0;
}
}
assert(TempScore <= MAX_SCORE && TempScore >= MIN_SCORE);
return TempScore;
Verify new routine.
tttony wrote:int givesCheck = SqAttacked(pos->KingSq[pos->side], pos->side ^ 1, pos);
int givesCheckOld = SqAttackedOld();
assert(givesCheck == givesCheckOld);


if (BestScore == -INFINITE) {
Score = -AlphaBeta(-beta, -alpha, depth - 1, pos, info, PV_NODE, givesCheck);
}
else {
Score = -AlphaBeta(-alpha - 1, -alpha, depth - 1, pos, info, CUT_NODE, givesCheck);
if (!info->stopped && Score > alpha && Score < beta) {
Score = -AlphaBeta(-beta, -alpha, depth - 1, pos, info, PV_NODE, givesCheck);
}
}

//....
Disable LMR and test, to see if new modification is right, putting aside LMR out of the equation.
if (BestScore == -INFINITE) {
Score = -AlphaBeta(-beta, -alpha, depth - 1, pos, info, NEW_NODE(nodeType), givesCheck);
}
else {
if (!pvNode &&
Legal >= FullDepthMoves &&
depth >= ReductionLimit &&
!InCheck &&
!givesCheck &&
!ISCAPTURE(move) &&
move != ttMove &&
!PROMOTED(move)) {
Score = -AlphaBeta(-(alpha + 1), -alpha, depth - 2, pos, info, NEW_NODE(nodeType), givesCheck);

}
else
Score = alpha + 1;

if (Score > alpha) {
Score = -AlphaBeta(-(alpha + 1), -alpha, depth - 1, pos, info, CUT_NODE, givesCheck);
if (!info->stopped && Score > alpha && Score < beta)
Score = -AlphaBeta(-beta, -alpha, depth - 1, pos, info, PV_NODE, givesCheck);
}
}

//.....
User avatar
velmarin
Posts: 1600
Joined: Mon Feb 21, 2011 9:48 am

Re: Are my modifications correct?

Post by velmarin »

Vice has a good initial perfomance, 40,45 % seems a good increase.

The Vice evaluation is very basic, perhaps you should expand it more.
There comes a time that if there is no knowledge is not improved.
tttony
Posts: 276
Joined: Sun Apr 24, 2011 12:33 am

Re: Are my modifications correct?

Post by tttony »

Ferdinand Mosca, thanks for remind me about the INFINITE macro in Vice 1.0

Here is the INFINITE macro from V1.0

Code: Select all

#define INFINITE 30000
#define ISMATE (INFINITE - MAXDEPTH)
I've added this:

Code: Select all

#define INFINITE        (30000)
#define MAX_MATE_VALUE	(INFINITE - MAXDEPTH + 1)
#define MIN_MATE_VALUE	(MAX_MATE_VALUE - MAXDEPTH)
#define MAX_EVAL        (32767)
But I have to debug more here because is not showing mate in the PVs, right now I'm using the original Vice values

When using ASPIRATION = 50, the debug mode will trigger an assert when checking if the score is in between INFINITE or -INFINITE

Code: Select all

assert(alpha >= -INFINITE);
The INFINITE macro should be

Code: Select all

#define INFINITE        (30000 + ASPIRATION) 
The problem is when is a mate value, I have to debug more here

jose mº velasco: Vice has a very basic eval and search, the first thing that I want to improve is the search or better to say I want to expand the search function, the next step will be the eval
Ferdy
Posts: 4852
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Are my modifications correct?

Post by Ferdy »

tttony wrote:Ferdinand Mosca, thanks for remind me about the INFINITE macro in Vice 1.0

Here is the INFINITE macro from V1.0

Code: Select all

#define INFINITE 30000
#define ISMATE (INFINITE - MAXDEPTH)
I've added this:

Code: Select all

#define INFINITE        (30000)
#define MAX_MATE_VALUE	(INFINITE - MAXDEPTH + 1)
#define MIN_MATE_VALUE	(MAX_MATE_VALUE - MAXDEPTH)
#define MAX_EVAL        (32767)
But I have to debug more here because is not showing mate in the PVs, right now I'm using the original Vice values

When using ASPIRATION = 50, the debug mode will trigger an assert when checking if the score is in between INFINITE or -INFINITE

Code: Select all

assert(alpha >= -INFINITE);
The INFINITE macro should be

Code: Select all

#define INFINITE        (30000 + ASPIRATION) 
The problem is when is a mate value, I have to debug more here

jose mº velasco: Vice has a very basic eval and search, the first thing that I want to improve is the search or better to say I want to expand the search function, the next step will be the eval
Just leave the INFINITE macro as it is.
Instead disable aspiration windowing when the score is a mate score.
int TempScore = Score, alpha, beta;
if (score >= ISMATE || SCORE <= -ISMATE){
alpha = -INFINITE;
beta = INFINITE;
}
else{
alpha = Score - ASPIRATION; // ASPIRATION = 50
assert(alpha >= -INFINITE);
beta = Score + ASPIRATION;
assert(beta <= INFINITE);
}


TempScore = SearchRoot(alpha, beta, depth, pos, info, InCheck);
if (info->stopped) {
return 0;
}
if (TempScore <= alpha || TempScore >= beta) {
TempScore = SearchRoot(-INFINITE, INFINITE, depth, pos, info, InCheck);
if (info->stopped) {
return 0;
}
}
assert(TempScore <= MAX_SCORE && TempScore >= MIN_SCORE);
return TempScore;
tttony
Posts: 276
Joined: Sun Apr 24, 2011 12:33 am

Re: Are my modifications correct?

Post by tttony »

pfff you are right, a simple if can solve the problem

Will test it
tttony
Posts: 276
Joined: Sun Apr 24, 2011 12:33 am

Re: Are my modifications correct?

Post by tttony »

Allright, I've found a bug in this position: (I'm pretty sure that is the bug that makes loose many games)

[d] r4k2/3n4/2p5/p1pb3P/4rP2/1P1Q4/P5P1/2R3K1 b - - 0 30

Here is the output:

Code: Select all

FEN: r4k2/3n4/2p5/p1pb3P/4rP2/1P1Q4/P5P1/2R3K1 b - - 0 30 

ViceBB 1.0 x64:
  1/1	00:00	          12	12	-4,70	Bd5xb3
  1/1	00:00	          22	22	+1,10	Re4xf4
  2/1	00:00	         118	118	+0,80	Re4xf4 h5-h6
  3/2	00:00	       1.187	1.187	+0,95	Re4xf4 h5-h6 Nd7-e5
  4/4	00:00	       6.235	6.235	+0,70	Re4xf4 Qd3-h7 Kf8-e8 h5-h6
  5/5	00:00	      28.987	28.987	+0,65	Re4xf4 Qd3-h7 Kf8-e8 Rc1-e1+ Ke8-d8
  6/8	00:00	      57.316	3.821.067	+0,45	Re4xf4 Qd3-h7 Kf8-e8 Rc1-e1+ Ke8-d8 Qh7-e7+
  7/8	00:00	     268.254	3.439.154	+0,20	Re4xf4 h5-h6 Rf4-e4 Rc1-f1+ Kf8-e7 h6-h7 Nd7-e5
  8/10	00:00	     888.485	3.568.213	+0,60	Re4xf4 h5-h6 Rf4-f7 h6-h7 Kf8-g7 Rc1-f1 Rf7xf1+ Kg1xf1
  9/12	00:01	   5.101.321	3.479.000	-5,55	Bd5xb3 Qd3xe4 Bb3-d5 Qe4-h7 Ra8-a7 Rc1xc5 Nd7xc5 Qh7xa7 Nc5-d3 <--- BLUNDER HERE!
  9/12	00:01	   5.306.975	3.507.000	+0,10	Re4xf4 h5-h6 Rf4-f7 Qd3-g6 Kf8-e7 Rc1-e1+ Ke7-d8 h6-h7 Rf7-f8
 10/12	00:02	   7.148.039	3.471.000	+0,20	Re4xf4 h5-h6 Rf4-e4 Qd3-h3 Kf8-e7 h6-h7 Ra8-h8 Qh3-h6 Ke7-e8 Rc1-d1

Look the deph 9, there are two moves from that depth and one of these mode is a big blunder -5,55 :shock:

Well is not easy to solve the bug, I'm using VS 2013 and debugging the position, the engine does not show that PV, the engine only show the buggy PV in release mode, in VS I can't debug in release mode, so using a viking way, putting printf(), printing score, bestscore, alpha, beta in that depth I've discovered that the engine choose that move because the variables:

SearchRoot function

Code: Select all

alpha = -30000;
BestScore = -30000;
Score = -555;

if (Score > BestScore) {

     if (Score > alpha) {
        // Display Blunder Pv here
     }
}
Using this code in SearchWithAspiration:

Code: Select all

if (Abs(TempScore) > (MIN_MATE_VALUE - ASPIRATION)) {
		alpha = -INFINITE;
		beta = INFINITE;
	}
	else {
		alpha = Score - ASPIRATION;
		ASSERT(alpha >= -INFINITE);
		beta = Score + ASPIRATION;
		ASSERT(beta <= INFINITE);
	}
If I set ASPIRATION macro to 0 the blunder is not showed, so the ASPIRATION is giving headache :x

Ok, while writing here I've partially solved the bug, just puting in the SearchRoot ttMove = PreviousPvMove(); now is not showing the blunder for now :D