Root score sign flipping

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

ZirconiumX
Posts: 1334
Joined: Sun Jul 17, 2011 11:14 am

Root score sign flipping

Post by ZirconiumX »

So, I have a rough search, with unrefined Null-move, LMR, PVS and SEE move sorting (along with a material, PST and mobility eval), but the scores I'm getting are making root move ordering based on the search scores very difficult, with bad results:

Code: Select all

1 70 0 2 b1a3
1 80 0 6 g1f3
1 80 0 42 g1f3
2 -90 0 130 b1a3 d7d5
2 -85 1 270 a2a4 d7d5
2 -75 1 361 b2b3 e7e5
2 -65 1 490 d2d3 e7e5
2 -40 1 584 d2d4 d7d5
2 -40 1 639 d2d4 d7d5
3 75 1 1045 a2a4 c7c5 b1c3
3 90 1 1324 g1f3 b8a6 b1c3
3 90 1 1372 g1f3 b8a6 b1c3
4 -65 3 4504 a2a4 d7d5 d2d4 c8f5
4 -40 4 10613 d2d4 g8f6 c1f4 e7e5
4 -40 4 12147 d2d4 g8f6 c1f4 e7e5
5 70 6 16823 a2a4 g8f6 b1c3 f6g4 g1f3
5 75 9 24517 c2c4 g8f6 b1c3 f6g4 g1f3
5 80 11 33416 e2e3 d7d6 b1c3 b8d7 g1e2
5 80 11 34256 e2e3 d7d6 b1c3 b8d7 g1e2
6 -65 31 111536 a2a4 d7d5 d2d4 b8a6 c1d2 g8f6
6 -45 71 253140 d2d4 g8f6 c1f4 f6e4 f2f3 e7e5
6 -45 71 417746 d2d4 g8f6 c1f4 f6e4 f2f3 e7e5
7 65 146 524520 a2a4 b8a6 d2d3 a6b4 d1d2 c7c5 g1f3
7 75 211 748205 g1f3 b8a6 e2e3 a6b4 d1e2 g8h6 b1c3
7 80 282 1028025 e2e3 d7d6 b1c3 b8d7 g1e2 e7e6 d2d3
7 80 282 1101802 e2e3 d7d6 b1c3 b8d7 g1e2 e7e6 d2d3
8 -75 1265 4432711 a2a4 d7d5 d2d4 b8c6 d1d3 e7e5 d4e5 c6e5
8 -75 1265 4432711 a2a4 d7d5 d2d4 b8c6 d1d3 e7e5 d4e5 c6e5
move a2a4
Is this a side-effect of my evaluation being rough, or do I have a bug somewhere?

Matthew:out
Some believe in the almighty dollar.

I believe in the almighty printf statement.
mar
Posts: 2555
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Root score sign flipping

Post by mar »

Looks certainly like a bug. Do you have qsearch?
Perhaps you forgot to flip eval sign if stm=black? Just guessing.
ZirconiumX
Posts: 1334
Joined: Sun Jul 17, 2011 11:14 am

Re: Root score sign flipping

Post by ZirconiumX »

mar wrote:Looks certainly like a bug. Do you have qsearch?
Perhaps you forgot to flip eval sign if stm=black? Just guessing.
Yes, I do for both.

QSearch code:

Code: Select all

int Quies(struct Board * b, int alpha, int beta)
{
    assert(b != NULL);

    struct Move m[128];
    struct Undo u;
    struct Board c;
    int movecount, i, value;
    int PVFinding = 1;

    Nodes++;

    if ((Nodes & 0x3FF) == 0 && TimeUsed() >= timeinfo.neverExceedLimit) {
        abortSearch = 1;
        return 0;
    }

	value = Eval(b);
	if (value > beta)
		return beta;
	if (value > alpha)
		alpha = value;

    movecount = GenerateCaptures(b, m);

    qsort(m, movecount, sizeof(struct Move), CompareMoves);

    for &#40;i = 0; i < movecount; i++) &#123;

        if &#40;m&#91;i&#93;.score < 0&#41;
            continue;

        c = *b;

        MakeMove&#40;&c, &u, m&#91;i&#93;);

        RecalculateAttacks&#40;&c&#41;;

        if (!IsLegal&#40;&c&#41;)
			continue;

        value = -Quies&#40;&c, -beta, -alpha&#41;;

        if &#40;abortSearch&#41;
            return 0;

		if &#40;value > alpha&#41; &#123;
			if &#40;value >= beta&#41;
				return beta;
			alpha = value;
		&#125;
    &#125;
    return alpha;
&#125;
Eval code:

Code: Select all

int Eval&#40;struct Board * b&#41;
&#123;
	int i, sq, tmp, value;
	int mask;

	value = 0;

	mask = b->piecemask&#91;KNIGHT&#93; | b->piecemask&#91;BISHOP&#93;;

	for &#40;i = 0; i < 64; i++) &#123;
		sq = i;

		if &#40;b->index&#91;i&#93; != INVALID&#41; &#123;
			tmp = 1 << b->index&#91;i&#93;;

			if &#40;tmp & b->sidemask&#91;b->side&#93;) &#123;
				if &#40;b->side == WHITE&#41; sq ^= 56; /* PSTs are rank 8 - 1, so flip the square */

				if &#40;tmp & b->piecemask&#91;PAWN&#93;) &#123;
					value += PawnValue;
					value += PawnPST&#91;sq&#93;;
				&#125;
				if &#40;tmp & b->piecemask&#91;KNIGHT&#93;) &#123;
					value += KnightValue;
					value += KnightPST&#91;sq&#93;;
				&#125;
				if &#40;tmp & b->piecemask&#91;BISHOP&#93;) &#123;
					value += BishopValue;
					value += BishopPST&#91;sq&#93;;
				&#125;
				if &#40;tmp & b->piecemask&#91;ROOK&#93;) &#123;
					value += RookValue;
					value += RookPST&#91;sq&#93;;
				&#125;
				if &#40;tmp & b->piecemask&#91;QUEEN&#93;) &#123;
					value += QueenValue;
					value += QueenPST&#91;sq&#93;;
				&#125;
				if &#40;tmp & b->piecemask&#91;KING&#93;) &#123;
					value += KingValue;
					value += KingPST&#91;sq&#93;;
				&#125;
			&#125; else &#123;
				if &#40;b->side == BLACK&#41; sq ^= 56; /* PSTs are rank 8 - 1, so flip the square */

				if &#40;tmp & b->piecemask&#91;PAWN&#93;) &#123;
					value -= PawnValue;
					value -= PawnPST&#91;sq&#93;;
				&#125;
				if &#40;tmp & b->piecemask&#91;KNIGHT&#93;) &#123;
					value -= KnightValue;
					value -= KnightPST&#91;sq&#93;;
				&#125;
				if &#40;tmp & b->piecemask&#91;BISHOP&#93;) &#123;
					value -= BishopValue;
					value -= BishopPST&#91;sq&#93;;
				&#125;
				if &#40;tmp & b->piecemask&#91;ROOK&#93;) &#123;
					value -= RookValue;
					value -= RookPST&#91;sq&#93;;
				&#125;
				if &#40;tmp & b->piecemask&#91;QUEEN&#93;) &#123;
					value -= QueenValue;
					value -= QueenPST&#91;sq&#93;;
				&#125;
				if &#40;tmp & b->piecemask&#91;KING&#93;) &#123;
					value -= KingValue;
					value -= KingPST&#91;sq&#93;;
				&#125;
			&#125;
		&#125;

		tmp = b->bitlist&#91;sq&#93; & mask;

		/* Safe Mobility */
		if (!&#40;tmp & b->sidemask&#91;!b->side&#93;))
			value += MobilityPoint * __builtin_popcount&#40;tmp & b->sidemask&#91;b->side&#93;);
		if (!&#40;tmp & b->sidemask&#91;b->side&#93;))
			value -= MobilityPoint * __builtin_popcount&#40;tmp & b->sidemask&#91;!b->side&#93;);
	&#125;

	if &#40;b->side == BLACK&#41;
		value = -value;

	return value;
&#125;
The Mobility code looksa bit weird, I know, but I use attack tables, so get the luxury of it being (almost) free.

Matthew:out
Some believe in the almighty dollar.

I believe in the almighty printf statement.
mar
Posts: 2555
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Root score sign flipping

Post by mar »

hmm, looks ok to me.
actually since you get eve-odd flips, at depth 2 (assuming it's startpos) you won't be able to capture anything anyway.

are you sure your eval is symmetric? you could try to setup two flipped positions to see if you get the same result:

rnbqkbnr/pppppppp/8/8/8/7N/PPPPPPPP/RNBQKB1R b KQkq - 1 1
rnbqkb1r/pppppppp/7n/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 1 1

those should give the same eval (for symmetric eval)

i'm afraid otherwise you'll have to do some debugging, perhaps print the tree up to depth 2?
ZirconiumX
Posts: 1334
Joined: Sun Jul 17, 2011 11:14 am

Re: Root score sign flipping

Post by ZirconiumX »

mar wrote:hmm, looks ok to me.
actually since you get eve-odd flips, at depth 2 (assuming it's startpos) you won't be able to capture anything anyway.

are you sure your eval is symmetric? you could try to setup two flipped positions to see if you get the same result:

rnbqkbnr/pppppppp/8/8/8/7N/PPPPPPPP/RNBQKB1R b KQkq - 1 1
rnbqkb1r/pppppppp/7n/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 1 1

those should give the same eval (for symmetric eval)

i'm afraid otherwise you'll have to do some debugging, perhaps print the tree up to depth 2?
And there's the bug. Thank you, Martin.

Code: Select all

setboard rnbqkbnr/pppppppp/8/8/8/7N/PPPPPPPP/RNBQKB1R b KQkq - 1 1
eval
Eval&#58; -70
setboard rnbqkb1r/pppppppp/7n/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 1 1
eval
Eval&#58; -60
Matthew:out
Some believe in the almighty dollar.

I believe in the almighty printf statement.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Root score sign flipping

Post by bob »

ZirconiumX wrote:So, I have a rough search, with unrefined Null-move, LMR, PVS and SEE move sorting (along with a material, PST and mobility eval), but the scores I'm getting are making root move ordering based on the search scores very difficult, with bad results:

Code: Select all

1 70 0 2 b1a3
1 80 0 6 g1f3
1 80 0 42 g1f3
2 -90 0 130 b1a3 d7d5
2 -85 1 270 a2a4 d7d5
2 -75 1 361 b2b3 e7e5
2 -65 1 490 d2d3 e7e5
2 -40 1 584 d2d4 d7d5
2 -40 1 639 d2d4 d7d5
3 75 1 1045 a2a4 c7c5 b1c3
3 90 1 1324 g1f3 b8a6 b1c3
3 90 1 1372 g1f3 b8a6 b1c3
4 -65 3 4504 a2a4 d7d5 d2d4 c8f5
4 -40 4 10613 d2d4 g8f6 c1f4 e7e5
4 -40 4 12147 d2d4 g8f6 c1f4 e7e5
5 70 6 16823 a2a4 g8f6 b1c3 f6g4 g1f3
5 75 9 24517 c2c4 g8f6 b1c3 f6g4 g1f3
5 80 11 33416 e2e3 d7d6 b1c3 b8d7 g1e2
5 80 11 34256 e2e3 d7d6 b1c3 b8d7 g1e2
6 -65 31 111536 a2a4 d7d5 d2d4 b8a6 c1d2 g8f6
6 -45 71 253140 d2d4 g8f6 c1f4 f6e4 f2f3 e7e5
6 -45 71 417746 d2d4 g8f6 c1f4 f6e4 f2f3 e7e5
7 65 146 524520 a2a4 b8a6 d2d3 a6b4 d1d2 c7c5 g1f3
7 75 211 748205 g1f3 b8a6 e2e3 a6b4 d1e2 g8h6 b1c3
7 80 282 1028025 e2e3 d7d6 b1c3 b8d7 g1e2 e7e6 d2d3
7 80 282 1101802 e2e3 d7d6 b1c3 b8d7 g1e2 e7e6 d2d3
8 -75 1265 4432711 a2a4 d7d5 d2d4 b8c6 d1d3 e7e5 d4e5 c6e5
8 -75 1265 4432711 a2a4 d7d5 d2d4 b8c6 d1d3 e7e5 d4e5 c6e5
move a2a4
Is this a side-effect of my evaluation being rough, or do I have a bug somewhere?

Matthew:out
I think you have a bug. When you compute a score, it is generally done in a white-centric way since that's the most natural way to do it, + = good for white, -=bad for white or good for black. But when you call eval, you need to correct the sign to make it match the side on move. something like:

return (white_on_move) ? score : -score;
ZirconiumX
Posts: 1334
Joined: Sun Jul 17, 2011 11:14 am

Re: Root score sign flipping

Post by ZirconiumX »

bob wrote:
ZirconiumX wrote:So, I have a rough search, with unrefined Null-move, LMR, PVS and SEE move sorting (along with a material, PST and mobility eval), but the scores I'm getting are making root move ordering based on the search scores very difficult, with bad results:

Code: Select all

1 70 0 2 b1a3
1 80 0 6 g1f3
1 80 0 42 g1f3
2 -90 0 130 b1a3 d7d5
2 -85 1 270 a2a4 d7d5
2 -75 1 361 b2b3 e7e5
2 -65 1 490 d2d3 e7e5
2 -40 1 584 d2d4 d7d5
2 -40 1 639 d2d4 d7d5
3 75 1 1045 a2a4 c7c5 b1c3
3 90 1 1324 g1f3 b8a6 b1c3
3 90 1 1372 g1f3 b8a6 b1c3
4 -65 3 4504 a2a4 d7d5 d2d4 c8f5
4 -40 4 10613 d2d4 g8f6 c1f4 e7e5
4 -40 4 12147 d2d4 g8f6 c1f4 e7e5
5 70 6 16823 a2a4 g8f6 b1c3 f6g4 g1f3
5 75 9 24517 c2c4 g8f6 b1c3 f6g4 g1f3
5 80 11 33416 e2e3 d7d6 b1c3 b8d7 g1e2
5 80 11 34256 e2e3 d7d6 b1c3 b8d7 g1e2
6 -65 31 111536 a2a4 d7d5 d2d4 b8a6 c1d2 g8f6
6 -45 71 253140 d2d4 g8f6 c1f4 f6e4 f2f3 e7e5
6 -45 71 417746 d2d4 g8f6 c1f4 f6e4 f2f3 e7e5
7 65 146 524520 a2a4 b8a6 d2d3 a6b4 d1d2 c7c5 g1f3
7 75 211 748205 g1f3 b8a6 e2e3 a6b4 d1e2 g8h6 b1c3
7 80 282 1028025 e2e3 d7d6 b1c3 b8d7 g1e2 e7e6 d2d3
7 80 282 1101802 e2e3 d7d6 b1c3 b8d7 g1e2 e7e6 d2d3
8 -75 1265 4432711 a2a4 d7d5 d2d4 b8c6 d1d3 e7e5 d4e5 c6e5
8 -75 1265 4432711 a2a4 d7d5 d2d4 b8c6 d1d3 e7e5 d4e5 c6e5
move a2a4
Is this a side-effect of my evaluation being rough, or do I have a bug somewhere?

Matthew:out
I think you have a bug. When you compute a score, it is generally done in a white-centric way since that's the most natural way to do it, + = good for white, -=bad for white or good for black. But when you call eval, you need to correct the sign to make it match the side on move. something like:

return (white_on_move) ? score : -score;
Yes, Martin raised this point, and it appears that I have an asymmetry in my PSTs (which I don't quite understand, since the PSTs that I was using - found here - don't appear to be asymmetrical down the middle).

Matthew:out
Some believe in the almighty dollar.

I believe in the almighty printf statement.
Daniel Anulliero
Posts: 759
Joined: Fri Jan 04, 2013 4:55 pm
Location: Nice

Re: Root score sign flipping

Post by Daniel Anulliero »

maybe a problem here ?

Code: Select all


if &#40;b->side == WHITE&#41; sq ^= 56; /* PSTs are rank 8 - 1, so flip the square */ 

if &#40;b->side == BLACK&#41; sq ^= 56; /* PSTs are rank 8 - 1, so flip the square */ 

you flip the square with the same value for the two colors?

the pst you found (I use it too :lol: ) are "white (or black) point of view "
JVMerlino
Posts: 1357
Joined: Wed Mar 08, 2006 10:15 pm
Location: San Francisco, California

Re: Root score sign flipping

Post by JVMerlino »

ZirconiumX wrote:So, I have a rough search, with unrefined Null-move, LMR, PVS and SEE move sorting (along with a material, PST and mobility eval), but the scores I'm getting are making root move ordering based on the search scores very difficult, with bad results:

Code: Select all

1 70 0 2 b1a3
1 80 0 6 g1f3
1 80 0 42 g1f3
2 -90 0 130 b1a3 d7d5
2 -85 1 270 a2a4 d7d5
2 -75 1 361 b2b3 e7e5
2 -65 1 490 d2d3 e7e5
2 -40 1 584 d2d4 d7d5
2 -40 1 639 d2d4 d7d5
3 75 1 1045 a2a4 c7c5 b1c3
3 90 1 1324 g1f3 b8a6 b1c3
3 90 1 1372 g1f3 b8a6 b1c3
4 -65 3 4504 a2a4 d7d5 d2d4 c8f5
4 -40 4 10613 d2d4 g8f6 c1f4 e7e5
4 -40 4 12147 d2d4 g8f6 c1f4 e7e5
5 70 6 16823 a2a4 g8f6 b1c3 f6g4 g1f3
5 75 9 24517 c2c4 g8f6 b1c3 f6g4 g1f3
5 80 11 33416 e2e3 d7d6 b1c3 b8d7 g1e2
5 80 11 34256 e2e3 d7d6 b1c3 b8d7 g1e2
6 -65 31 111536 a2a4 d7d5 d2d4 b8a6 c1d2 g8f6
6 -45 71 253140 d2d4 g8f6 c1f4 f6e4 f2f3 e7e5
6 -45 71 417746 d2d4 g8f6 c1f4 f6e4 f2f3 e7e5
7 65 146 524520 a2a4 b8a6 d2d3 a6b4 d1d2 c7c5 g1f3
7 75 211 748205 g1f3 b8a6 e2e3 a6b4 d1e2 g8h6 b1c3
7 80 282 1028025 e2e3 d7d6 b1c3 b8d7 g1e2 e7e6 d2d3
7 80 282 1101802 e2e3 d7d6 b1c3 b8d7 g1e2 e7e6 d2d3
8 -75 1265 4432711 a2a4 d7d5 d2d4 b8c6 d1d3 e7e5 d4e5 c6e5
8 -75 1265 4432711 a2a4 d7d5 d2d4 b8c6 d1d3 e7e5 d4e5 c6e5
move a2a4
Is this a side-effect of my evaluation being rough, or do I have a bug somewhere?

Matthew:out
Something else that should have been pointed out is that your move ordering is clearly either not working or not hooked up properly. The first move being chosen at every depth (but only after depth 2, for some reason) is a2a4, which implies that you're searching moves in the order that they are being generated. However, your first move searched (and therefore reported) at depth N should always be the best (and last) move reported at depth N-1.

So, I'm afraid to say, you have another problem to solve. (and don't we all!)

jm
ZirconiumX
Posts: 1334
Joined: Sun Jul 17, 2011 11:14 am

Re: Root score sign flipping

Post by ZirconiumX »

Daniel Anulliero wrote:maybe a problem here ?

Code: Select all


if &#40;b->side == WHITE&#41; sq ^= 56; /* PSTs are rank 8 - 1, so flip the square */ 

if &#40;b->side == BLACK&#41; sq ^= 56; /* PSTs are rank 8 - 1, so flip the square */ 

you flip the square with the same value for the two colors?

the pst you found (I use it too :lol: ) are "white (or black) point of view "

Code: Select all

         if &#40;tmp & b->sidemask&#91;b->side&#93;) &#123; 
            if &#40;b->side == WHITE&#41; sq ^= 56; /* PSTs are rank 8 - 1, so flip the square */ 
            ...
         &#125; else &#123; 
            if &#40;b->side == BLACK&#41; sq ^= 56; /* PSTs are rank 8 - 1, so flip the square */
            ...
         &#125;
Switching the code to be b->side == WHITE for the second bit would flip the PSTs for Black :wink:
JVMerlino wrote: Something else that should have been pointed out is that your move ordering is clearly either not working or not hooked up properly. The first move being chosen at every depth (but only after depth 2, for some reason) is a2a4, which implies that you're searching moves in the order that they are being generated. However, your first move searched (and therefore reported) at depth N should always be the best (and last) move reported at depth N-1.

So, I'm afraid to say, you have another problem to solve. (and don't we all!)

jm
My root move ordering is sorted by score - when the score is negative, the sort will sort the least negative scoring moves first, resulting in bad move ordering. Thus, if I fix the score flipping bug, I will also fix my root move ordering bug.

I should also add that the score sorting only kicks in after depth 1, when we have move scores to sort on - it before sorts by SEE, which is not very useful most of the time.

Matthew:out
Some believe in the almighty dollar.

I believe in the almighty printf statement.