Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: SEE and possible EXChess bug

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.