see

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Maarten Claessens
Posts: 106
Joined: Mon May 12, 2014 10:08 am
Location: Near Nijmegen

Re: see

Post by Maarten Claessens »

What about the see-value of fxe5 in this position:
[d]8/2q2k2/4rb2/4pR2/5P2/3N4/Q7/4K3 w - - 0 1
Nothing is unstable (Lawrence Krauss)
flok

Re: see

Post by flok »

I would say +975.

(for pawn 100, knight 325, bishop 325, rook 500, queen 975, king 10000)
elcabesa
Posts: 855
Joined: Sun May 23, 2010 1:32 pm

Re: see

Post by elcabesa »

Why?
My see doesn't take in account checks and maybe pinned pieces.(I have to check the source).
I think the result depend on how you calculate it.
Maarten Claessens
Posts: 106
Joined: Mon May 12, 2014 10:08 am
Location: Near Nijmegen

Re: see

Post by Maarten Claessens »

WaDuuttie calculates +100 (with pin detection: PxP, not followed by QxP because of NxQ) or 0 (without pin detection: PxP BxP NxB RxN RxR QxR).
Nothing is unstable (Lawrence Krauss)
AlvaroBegue
Posts: 931
Joined: Tue Mar 09, 2010 3:46 pm
Location: New York
Full name: Álvaro Begué (RuyDos)

Re: see

Post by AlvaroBegue »

flok wrote:I would say +975.

(for pawn 100, knight 325, bishop 325, rook 500, queen 975, king 10000)
That makes no sense. A [non-promoting] capture can't have an SEE value higher than the value of the captured piece, because the opponent could just stand pat after it.
flok

Re: see

Post by flok »

(I'll respond later to this; no access to my development machine (my laptop at home) right now)
flok

Re: see

Post by flok »

Hi Steve,

I followed your post -leaving out the early bailouts for now.
That works in some cases but not all. E.g. [d]8/2q2k2/4rb2/4pR2/5P2/3N4/Q7/4K3 w - - 0 1[/d] gives 1200.
It's probably due to that threshold. My question now is: what is the value of the threshold compared to the piece values?

Code: Select all

// xy are of the victim
int Scene::getSEE(const int x, const int y, const ChessPiece *const attacker) const
{
	const ChessPiece *const victim = b.getAt(x, y);

	const PlayerColor c = attacker -> getColor();

	// bit 0...15: if set, then a white piece can walk over and/or attack this field, 16...31 black
	const uint32_t bits = ss.back().tcs.cells[y][x];

	int see_val = victim -> getEvalVal();
	int trophy_val = attacker -> getEvalVal();

	PlayerColor sc = opponentColor(c);
	int so[] = { 0, 16 }; // where to start to search in the bit pattern. so[0] is for white
	constexpr int soe[] = { 16, 32 }; // where to stop searching. soe[0] is for white

	for&#40;; so&#91;sc&#93; < soe&#91;sc&#93;;) &#123;
		// find a 1 bit
		while&#40;&#40;bits & &#40;1 << so&#91;sc&#93;)) == 0&#41; &#123;
			// if end of pattern, stop searching
			if (++so&#91;sc&#93; == soe&#91;sc&#93;)
				break;
		&#125;

		if &#40;so&#91;sc&#93; >= soe&#91;sc&#93;)
			break;

		if &#40;sc == c&#41;
			see_val += trophy_val;
		else
			see_val -= trophy_val;

		// get eval val. bit number is an index in pieces&#91;color&#93;&#91;index&#93; pointing to the
		// piece.
		trophy_val = sc == WHITE ? pieces&#91;sc&#93;&#91;so&#91;sc&#93;&#93; -> getEvalVal&#40;) &#58; pieces&#91;sc&#93;&#91;so&#91;sc&#93; - 16&#93; -> getEvalVal&#40;);

		// on to the next bit!
		so&#91;sc&#93;++;

		sc = opponentColor&#40;sc&#41;;
	&#125;

	return see_val;
&#125;
User avatar
Steve Maughan
Posts: 1221
Joined: Wed Mar 08, 2006 8:28 pm
Location: Florida, USA

Re: see

Post by Steve Maughan »

Folkert,

The threshold is normally zero i.e. You only want winning SEE captures. But it may be higher of you're entering qsearch and you're 400 centi pawns down. In this case you could set the threshold to 400 and only find SEE moves that are better than 400 centi pawns.

Note, SEE usually doesn't take into account pinned pieces.

Steve
http://www.chessprogramming.net - Maverick Chess Engine
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: see

Post by Sven »

flok wrote:

Code: Select all

// xy are of the victim
int Scene&#58;&#58;getSEE&#40;const int x, const int y, const ChessPiece *const attacker&#41; const
&#123;
	const ChessPiece *const victim = b.getAt&#40;x, y&#41;;

	const PlayerColor c = attacker -> getColor&#40;);

	// bit 0...15&#58; if set, then a white piece can walk over and/or attack this field, 16...31 black
	const uint32_t bits = ss.back&#40;).tcs.cells&#91;y&#93;&#91;x&#93;;

	int see_val = victim -> getEvalVal&#40;);
	int trophy_val = attacker -> getEvalVal&#40;);

	PlayerColor sc = opponentColor&#40;c&#41;;
	int so&#91;&#93; = &#123; 0, 16 &#125;; // where to start to search in the bit pattern. so&#91;0&#93; is for white
	constexpr int soe&#91;&#93; = &#123; 16, 32 &#125;; // where to stop searching. soe&#91;0&#93; is for white

	for&#40;; so&#91;sc&#93; < soe&#91;sc&#93;;) &#123;
		// find a 1 bit
		while&#40;&#40;bits & &#40;1 << so&#91;sc&#93;)) == 0&#41; &#123;
			// if end of pattern, stop searching
			if (++so&#91;sc&#93; == soe&#91;sc&#93;)
				break;
		&#125;

		if &#40;so&#91;sc&#93; >= soe&#91;sc&#93;)
			break;

		if &#40;sc == c&#41;
			see_val += trophy_val;
		else
			see_val -= trophy_val;

		// get eval val. bit number is an index in pieces&#91;color&#93;&#91;index&#93; pointing to the
		// piece.
		trophy_val = sc == WHITE ? pieces&#91;sc&#93;&#91;so&#91;sc&#93;&#93; -> getEvalVal&#40;) &#58; pieces&#91;sc&#93;&#91;so&#91;sc&#93; - 16&#93; -> getEvalVal&#40;);

		// on to the next bit!
		so&#91;sc&#93;++;

		sc = opponentColor&#40;sc&#41;;
	&#125;

	return see_val;
&#125;
I think this is not a correct SEE implementation. Whenever you find a new attacker for the target square you always have the choice between "making the capture" and "standing pat" (i.e., doing nothing). So at any point in your loop over pieces attacking the target square (not just in the root!) you would have to calculate the outcome of the capture but then ignore it if it loses material (so in fact you would also need to modify your algorithm). Just like in QS. What you seem to do in the code shown above is to always make the capture with the lowest remaining attacker, until no more attackers are left. But that is incorrect because it does not consider standing pat. For instance if the last enemy piece that did a capture was a knight and your next attacker is a queen but the enemy has another knight as attacker (defender) then you must detect that QxN NxQ is worse than not capturing.

It is slightly harder to do that correctly with an iterative algorithm compared to the very simple recursive one, but of course it is possible (by definition).
AlvaroBegue
Posts: 931
Joined: Tue Mar 09, 2010 3:46 pm
Location: New York
Full name: Álvaro Begué (RuyDos)

Re: see

Post by AlvaroBegue »

Sven wrote:It is slightly harder to do that correctly with an iterative algorithm compared to the very simple recursive one, but of course it is possible (by definition).
I actually showed how to do it in a previous post in this thread.