evaluation without special white/black code

Discussion of chess software programming and technical issues.

Moderator: Ras

Uri Blass
Posts: 10903
Joined: Thu Mar 09, 2006 12:37 am
Location: Tel-Aviv Israel

evaluation without special white/black code

Post by Uri Blass »

I wonder how you write your evaluation without special code for white/black.

The original code of strelka has code like the following

endgame += cnt * mobility_knight_endgame;//black minus
opening += cnt * mobility_knight_opening;//black minus

I can simply have array of 2 numbers 1 and -1 and have

endgame += cnt * mobility_knight_endgame*mult[side]
opening += cnt * mobility_knight_opening*mult[side]//black minus

Second alternative is to have special arrays and have
endgame[side]+=cnt*mobility_knight_endgame


In this case you need in the end to substract in order to find the score.
Third alternative is to have

Code: Select all

#define eval(a,side) ((side)==White)?(a):(0-(a)))
endgame[side]+=cnt*eval(mobility_knight_endgame,side)
I wonder which alternative is better.
Harald Johnsen

Re: evaluation without special white/black code

Post by Harald Johnsen »

The second alternative is the best, *one* subtraction does not cost anything.

Code: Select all

#define eval(a,side) ((side)==White)?(a):(0-(a)))
endgame +=cnt*eval(mobility_knight_endgame,side)
I've corrected your code, your don't need to compute the sign *and* storing in a 2 slots array.

Of course your eval code is supposed to be in inlined functions or in templates so that the compiler optimizes your macro. Then there won't be any color testing at run-time

HJ.
Karlo Bala
Posts: 373
Joined: Wed Mar 22, 2006 10:17 am
Location: Novi Sad, Serbia
Full name: Karlo Balla

Re: evaluation without special white/black code

Post by Karlo Bala »

Uri Blass wrote:I wonder how you write your evaluation without special code for white/black.

The original code of strelka has code like the following

endgame += cnt * mobility_knight_endgame;//black minus
opening += cnt * mobility_knight_opening;//black minus

I can simply have array of 2 numbers 1 and -1 and have

endgame += cnt * mobility_knight_endgame*mult[side]
opening += cnt * mobility_knight_opening*mult[side]//black minus

Second alternative is to have special arrays and have
endgame[side]+=cnt*mobility_knight_endgame


In this case you need in the end to substract in order to find the score.
Third alternative is to have

Code: Select all

#define eval(a,side) ((side)==White)?(a):(0-(a)))
endgame[side]+=cnt*eval(mobility_knight_endgame,side)
I wonder which alternative is better.
I like second alternative. Score everything separately for white and black and in the end return eval[sideonmove]-eval[sideonmove^1].

I would like to know what do you think about this line of code from strelka:


if ((MaskPawnAttacksW1[square] & Board->mp[BlackPawn]) ||
((MaskPawnAttacksW2[square] & Board->mp[BlackPawn]) && ((MaskPawnAttacks[0][square] & Board->mp[WhitePawn])==0))) {
if (open_file) opening -= 872; else opening -= 406;
endgame -= 297;

Is it bug or intentional? :wink:
Best Regards,
Karlo Balla Jr.
Tony

Re: evaluation without special white/black code

Post by Tony »

If the variable names do what they are supposed to do, I see nothing wrong with this code.

Tony
Karlo Bala
Posts: 373
Joined: Wed Mar 22, 2006 10:17 am
Location: Novi Sad, Serbia
Full name: Karlo Balla

Re: evaluation without special white/black code

Post by Karlo Bala »

Tony wrote:If the variable names do what they are supposed to do, I see nothing wrong with this code.

Tony
Hmmm,
if we change code:
(MaskPawnAttacksW2[square] & Board->mp[BlackPawn]) && ((MaskPawnAttacks[0][square] & Board->mp[WhitePawn])==0)

to

(MaskPawnAttacksW2[square] & Board->mp[BlackPawn]) && ((MaskPawnAttacks[0][square] & Board->mp[WhitePawn])!=0)

we get classical backward pawn, or not? :?
Am I missing something? What could be another meaning of original code?
Best Regards,
Karlo Balla Jr.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: evaluation without special white/black code

Post by bob »

Uri Blass wrote:I wonder how you write your evaluation without special code for white/black.

The original code of strelka has code like the following

endgame += cnt * mobility_knight_endgame;//black minus
opening += cnt * mobility_knight_opening;//black minus

I can simply have array of 2 numbers 1 and -1 and have

endgame += cnt * mobility_knight_endgame*mult[side]
opening += cnt * mobility_knight_opening*mult[side]//black minus

Second alternative is to have special arrays and have
endgame[side]+=cnt*mobility_knight_endgame


In this case you need in the end to substract in order to find the score.
Third alternative is to have

Code: Select all

#define eval(a,side) ((side)==White)?(a):(0-(a)))
endgame[side]+=cnt*eval(mobility_knight_endgame,side)
I wonder which alternative is better.
I decided to go this way:

1. a procedure that evaluates the pieces for just one side, and returns a score +=good for that side, -=bad for that side...

then

value += EvaluateKnight(white) - EvaluateKnight(black)

does the trick. Somewhere you obviously have to have special-case code, since white and black are different, the above minimizes the differences pretty nicely and now you never have to look at the above line, you just modify EvaluateKnights() and you are done...
Uri Blass
Posts: 10903
Joined: Thu Mar 09, 2006 12:37 am
Location: Tel-Aviv Israel

Re: evaluation without special white/black code

Post by Uri Blass »

Karlo Bala wrote:
Uri Blass wrote:I wonder how you write your evaluation without special code for white/black.

The original code of strelka has code like the following

endgame += cnt * mobility_knight_endgame;//black minus
opening += cnt * mobility_knight_opening;//black minus

I can simply have array of 2 numbers 1 and -1 and have

endgame += cnt * mobility_knight_endgame*mult[side]
opening += cnt * mobility_knight_opening*mult[side]//black minus

Second alternative is to have special arrays and have
endgame[side]+=cnt*mobility_knight_endgame


In this case you need in the end to substract in order to find the score.
Third alternative is to have

Code: Select all

#define eval(a,side) ((side)==White)?(a):(0-(a)))
endgame[side]+=cnt*eval(mobility_knight_endgame,side)
I wonder which alternative is better.
I like second alternative. Score everything separately for white and black and in the end return eval[sideonmove]-eval[sideonmove^1].

I would like to know what do you think about this line of code from strelka:


if ((MaskPawnAttacksW1[square] & Board->mp[BlackPawn]) ||
((MaskPawnAttacksW2[square] & Board->mp[BlackPawn]) && ((MaskPawnAttacks[0][square] & Board->mp[WhitePawn])==0))) {
if (open_file) opening -= 872; else opening -= 406;
endgame -= 297;

Is it bug or intentional? :wink:
I see no bug

This code is about evaluating weak non isolated pawns.

Example:Suppose white has pawn at b3 and white has at least one pawn in the a file or the c file but no pawns at a2 a3 or c2 c3.

b3 is considered to be a weak pawn by strelka if one the following conditions happen:
1)black has a pawn at a5 or c5 so black controls b4
2)black has a pawn at a6 or c6 when white has no pawns at a4 or c4

In the endgame the score for weak pawns is the same for close file and open file.
Karlo Bala
Posts: 373
Joined: Wed Mar 22, 2006 10:17 am
Location: Novi Sad, Serbia
Full name: Karlo Balla

Re: evaluation without special white/black code

Post by Karlo Bala »

Uri Blass wrote:
Karlo Bala wrote:
Uri Blass wrote:I wonder how you write your evaluation without special code for white/black.

The original code of strelka has code like the following

endgame += cnt * mobility_knight_endgame;//black minus
opening += cnt * mobility_knight_opening;//black minus

I can simply have array of 2 numbers 1 and -1 and have

endgame += cnt * mobility_knight_endgame*mult[side]
opening += cnt * mobility_knight_opening*mult[side]//black minus

Second alternative is to have special arrays and have
endgame[side]+=cnt*mobility_knight_endgame


In this case you need in the end to substract in order to find the score.
Third alternative is to have

Code: Select all

#define eval(a,side) ((side)==White)?(a):(0-(a)))
endgame[side]+=cnt*eval(mobility_knight_endgame,side)
I wonder which alternative is better.
I like second alternative. Score everything separately for white and black and in the end return eval[sideonmove]-eval[sideonmove^1].

I would like to know what do you think about this line of code from strelka:


if ((MaskPawnAttacksW1[square] & Board->mp[BlackPawn]) ||
((MaskPawnAttacksW2[square] & Board->mp[BlackPawn]) && ((MaskPawnAttacks[0][square] & Board->mp[WhitePawn])==0))) {
if (open_file) opening -= 872; else opening -= 406;
endgame -= 297;

Is it bug or intentional? :wink:
I see no bug

This code is about evaluating weak non isolated pawns.

Example:Suppose white has pawn at b3 and white has at least one pawn in the a file or the c file but no pawns at a2 a3 or c2 c3.

b3 is considered to be a weak pawn by strelka if one the following conditions happen:
1)black has a pawn at a5 or c5 so black controls b4
2)black has a pawn at a6 or c6 when white has no pawns at a4 or c4

In the endgame the score for weak pawns is the same for close file and open file.
Yes, you are right :wink: I mixed 8x8 vs. 16x16 board representation.

Thanks Uri!
Best Regards,
Karlo Balla Jr.
Uri Blass
Posts: 10903
Joined: Thu Mar 09, 2006 12:37 am
Location: Tel-Aviv Israel

Re: evaluation without special white/black code

Post by Uri Blass »

bob wrote:
Uri Blass wrote:I wonder how you write your evaluation without special code for white/black.

The original code of strelka has code like the following

endgame += cnt * mobility_knight_endgame;//black minus
opening += cnt * mobility_knight_opening;//black minus

I can simply have array of 2 numbers 1 and -1 and have

endgame += cnt * mobility_knight_endgame*mult[side]
opening += cnt * mobility_knight_opening*mult[side]//black minus

Second alternative is to have special arrays and have
endgame[side]+=cnt*mobility_knight_endgame


In this case you need in the end to substract in order to find the score.
Third alternative is to have

Code: Select all

#define eval(a,side) ((side)==White)?(a):(0-(a)))
endgame[side]+=cnt*eval(mobility_knight_endgame,side)
I wonder which alternative is better.
I decided to go this way:

1. a procedure that evaluates the pieces for just one side, and returns a score +=good for that side, -=bad for that side...

then

value += EvaluateKnight(white) - EvaluateKnight(black)

does the trick. Somewhere you obviously have to have special-case code, since white and black are different, the above minimizes the differences pretty nicely and now you never have to look at the above line, you just modify EvaluateKnights() and you are done...
This mean that you call EvaluateKnight twice in your code and the same for some other functions.

I wonder what is the advantage relative to value+=Evaluate(white)-Evaluate(black) when Evaluate(side) calls only to Evaluateknight(side)

In the case of Strelka the program has no EvaluateKnight function but
even if I change it and add EvaluateKnight function then
value += EvaluateKnight(white) - EvaluateKnight(black) is not a solution

The problem is that EvaluateKnight not only change the evaluation by calculating mobility but also updates some variables at the same time(controling squares near the king) and these variables are used later in the evaluation.

Uri
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: evaluation without special white/black code

Post by bob »

Uri Blass wrote:
bob wrote:
Uri Blass wrote:I wonder how you write your evaluation without special code for white/black.

The original code of strelka has code like the following

endgame += cnt * mobility_knight_endgame;//black minus
opening += cnt * mobility_knight_opening;//black minus

I can simply have array of 2 numbers 1 and -1 and have

endgame += cnt * mobility_knight_endgame*mult[side]
opening += cnt * mobility_knight_opening*mult[side]//black minus

Second alternative is to have special arrays and have
endgame[side]+=cnt*mobility_knight_endgame


In this case you need in the end to substract in order to find the score.
Third alternative is to have

Code: Select all

#define eval(a,side) ((side)==White)?(a):(0-(a)))
endgame[side]+=cnt*eval(mobility_knight_endgame,side)
I wonder which alternative is better.
I decided to go this way:

1. a procedure that evaluates the pieces for just one side, and returns a score +=good for that side, -=bad for that side...

then

value += EvaluateKnight(white) - EvaluateKnight(black)

does the trick. Somewhere you obviously have to have special-case code, since white and black are different, the above minimizes the differences pretty nicely and now you never have to look at the above line, you just modify EvaluateKnights() and you are done...
This mean that you call EvaluateKnight twice in your code and the same for some other functions.

I wonder what is the advantage relative to value+=Evaluate(white)-Evaluate(black) when Evaluate(side) calls only to Evaluateknight(side)

In the case of Strelka the program has no EvaluateKnight function but
even if I change it and add EvaluateKnight function then
value += EvaluateKnight(white) - EvaluateKnight(black) is not a solution

The problem is that EvaluateKnight not only change the evaluation by calculating mobility but also updates some variables at the same time(controling squares near the king) and these variables are used later in the evaluation.

Uri
Almost right. Since EvaluateKnights() is defined in the same source file as Evaluate() where it is called, the two calls get inlined and there is no function call overhead. But it makes it easier to read...

As far as the latter problem, I deal with that in Crafty. You just have a variable such as xxx[2] where xxx[0] is the stuff black knights do, and xxx[1] is the stuff white knights do (I have those for mobility, and any sort of other information that needs to be passed around (white candidate pawns, black candidates becomes candidates[2] for example...)