Author: Dan Homan
Date: 18:42:58 04/02/01
Go up one level in this thread
Ok, I've looked it over in more detail, and there is definitely a bug
here in EXchess. Thank you for pointing it out.
- Dan
On April 01, 2001 at 18:19:39, Dan Homan wrote:
>
>I wrote this pretty quickly (and a long time ago), so I'll need to look
>at it carefully to be sure, but I think that the "bestval" variable takes
>care of the stand-pat option. The algorithm keeps track of the best
>achievable score and returns that rather than the score at the end of the
>complete exchange.
>
> - Dan
>
>P.S. I've been very busy with work and haven't thought about computer chess in
>months, so I am quite rusty -- even on my own code!
>
>On April 01, 2001 at 10:29:42, Gian-Carlo Pascutto wrote:
>
>>Hi all,
>>
>>in the process of using EXChess's source to design my SEE
>>after, I ran into something which I suspect is either a bug
>>in EXChess, or a misunderstanding from my part about how SEE
>>works.
>>
>>Below is the critical section.
>>
>>int swap(int sq, position p, int side, int from)
>>{
>> int val = value[p.sq[sq].type], lsq;
>>
>> // initalize attackers arrays
>> attackers[0][0].v = 0; attcks[0] = 0;
>> attackers[1][0].v = 0; attcks[1] = 0;
>>
>> // put in the first capture
>> attackers[side][0].v = value[p.sq[from].type];
>> attcks[side]++;
>> p.sq[from] = empty;
>>
>> // find all the attcks on sq
>> dia_attcks(sq, 0, &p);
>> knt_attcks(sq, &p);
>> hor_attcks(sq, 0, &p);
>>
>> attackers[0][attcks[0]].v = 0;
>> attackers[1][attcks[1]].v = 0;
>>
>> // swap off the attacks, starting with other side
>> // and with the least value
>> int swapside = side^1;
>> int count[2] = { 0, 0 }, bestval;
>>
>> if(attcks[swapside]) bestval = val - attackers[side][0].v;
>> else bestval = val;
>>
>> count[side]++; // for the first capture
>>
>> while(count[swapside] < attcks[swapside]) {
>> SSort(&attackers[swapside][count[swapside]],
>>&attackers[swapside][attcks[swapside]-1]);
>> if(swapside == side) {
>> val += attackers[swapside^1][count[swapside^1]-1].v;
>> if(count[side^1] >= attcks[side^1] && val > bestval)
>> bestval = val;
>> } else {
>> val -= attackers[swapside^1][count[swapside^1]-1].v;
>> if(val > bestval)
>> { bestval= val; }
>> }
>> // square from which the capture came
>> lsq = attackers[swapside][count[swapside]].s;
>> // add in any revealed attacks due to this capture
>> if((FILE(lsq) == FILE(sq) || RANK(lsq) == RANK(sq)) && lsq)
>> hor_attcks(sq, lsq, &p);
>> else if(p.sq[lsq].type != KNIGHT && lsq) dia_attcks(sq, lsq, &p);
>> count[swapside]++;
>> swapside ^= 1;
>> }
>>
>> return bestval;
>>}
>>
>>If you look at this code you see the program keeps exchanging off
>>attackers untill one side is exhausted. New best values are remembered
>>if the side that was originally to move can stand pat either after
>>a recapture by the opponent, or after a capture when we know the
>>opponent has no more recaptures.
>>
>>I think this will cause problems when, for example, a bishop and a
>>pawn are attacking a pawn defended by a queen.
>>
>>Correct would be:
>>
>>pawn takes pawn, standpat, score +100
>>
>>but I think the algorithm does:
>>
>>pawn takes pawn, queen takes pawn, bishop takes queen and standpat, score +900
>>
>>because it does not allow a standpat for the opponent.
>>
>>Am I missing something here? I added the (IMHO) corrected algorithm
>>to Sjeng and the results aren't as good as I hoped they would be, even
>>if using SEE to prune losing captures.
>>
>>My SEE function is below (note that I don't do Xray attacks yet):
>>
>>int see(int color, int square, int from)
>>{
>> int sside;
>> int caps[2];
>> int value;
>> int origpiece;
>> int ourbestvalue;
>> int hisbestvalue;
>>
>> /* reset data */
>> see_num_attackers[WHITE] = 0;
>> see_num_attackers[BLACK] = 0;
>>
>> /* remove original capturer from board, exposing his first xray-er */
>> origpiece = board[from];
>> board[from] = npiece;
>>
>> see_num_attackers[color]++;
>> see_attackers[color][0].piece = origpiece;
>> see_attackers[color][0].square = from;
>>
>> /* calculate all attackers to square */
>> setup_attackers(square);
>>
>> /* initially we gain the piece we are capturing */
>> value = abs(material[board[square]]);
>>
>> /* free capture ? */
>> if (!see_num_attackers[!color])
>> {
>> board[from] = origpiece;
>> return value;
>> }
>> else
>> {
>> /* we can never get a higher SEE score than the piece we just captured */
>> /* so that is the current best value for our opponent */
>> /* we arent sure of anything yet, so -INF */
>> hisbestvalue = value;
>> ourbestvalue = -INF;
>> }
>>
>> caps[color] = 1;
>> caps[!color] = 0;
>>
>> /* start with recapture */
>> sside = !color;
>>
>> /* continue as long as there are attackers */
>> while (caps[sside] < see_num_attackers[sside])
>> {
>> /* resort capturelist of sside to put lowest attacker in next position */
>> findlowest(sside, caps[sside]);
>>
>> if (sside == color)
>> {
>> /* capturing more */
>> /* we capture the opponents recapturer */
>> value += abs(material[see_attackers[!sside][caps[!sside]-1].piece]);
>>
>> /* if the opp ran out of attackers we can stand pat now! */
>> if (see_num_attackers[!sside] <= caps[!sside] && value > ourbestvalue)
>> ourbestvalue = value;
>>
>> /* our opponent can always stand pat now */
>> if (value < hisbestvalue) hisbestvalue = value;
>> }
>> else
>> {
>> /* recapture by opp */
>> /* we lose whatever we captured with in last iteration */
>> value -= abs(material[see_attackers[!sside][caps[!sside]-1].piece]);
>>
>> /* we can stand pat if we want to now */
>> /* our best score goes up, opponent is unaffected */
>>
>> if (value > ourbestvalue)
>> {
>> ourbestvalue = value;
>> }
>>
>> if (see_num_attackers[!sside] <= caps[!sside] && value < hisbestvalue)
>> hisbestvalue = value;
>> }
>>
>> /* keep track of capture count */
>> caps[sside]++;
>>
>> /* switch sides */
>> sside ^= 1;
>>
>> }
>>
>> /* restore capturer */
>> board[from] = origpiece;
>>
>> /* we return our best score now, keeping in mind that
>> it can never we better than the best for our opponent */
>> return (ourbestvalue > hisbestvalue) ? hisbestvalue : ourbestvalue;
>>}
>>
>>--
>>GCP
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.