# Computer Chess Club Archives

## Messages

### Subject: Re: Question about static exchange evaluation

Author: jonathan Baxter

Date: 13:25:19 11/12/98

Go up one level in this thread

```On November 12, 1998 at 14:34:16, Robert Hyatt wrote:

>On November 12, 1998 at 12:13:26, Larry Coon wrote:
>
>>(Long question follows -- sorry.)
>>
>>I know I saw SEE talked about recently, but I couldn't
>>locate the discussion here, on rgcc or anybody's web
>>page (I don't remember where I saw it).  Can somebody
>

SEE is nothing more than negamax (or minimax) where at each node in the tree
you have two options: make the next capture or sit (with an eval equal to the
current material balance). I found that once I thought of it that way, the code
was easy to write. Note that the resulting tree looks like:

+
| \
|  \
+   +
| \
|  \
+   +
| \
|  \
+   +

with a depth equal to the number of captures in the exchange.

Here's my "swap.c" (note that "topieces" for each square is a 32 bit mask
indicating which pieces are attacking that square. It is ordered so that
the next bit is always the next highest value piece. "ff_one" finds the first
set bit in its argument, fl_one finds the last set bit).

/* swap routines. */

#include "includes.h"
#include "tdchess.h"

static int debug = 0;
extern struct state *state;

/* does a crude static search to determine the material gain of
move. It is mainly used for move ordering. */
etype swap(Position *b, Move *m)
{
etype swap_score, next, gain;
int pi, tomove, i;
uint32 topieces, discovered, used;
Square from=m->from, to=m->to;

gain = mat_value(ABS(b->board[to]));

swap_score = gain;

/* the first capture is from the "from" square. */
next = -mat_value(ABS(b->board[from]));
used = 1<<b->pboard[from];
topieces = b->topieces[to] & ~used;
if (debug)
lprintf(0, "from: %s gain: %d\n", posstr(from), gain);

/* moving this piece might expose a new capture possibility by
another sliding piece. */
discovered = b->topieces[from] & b->sliding_mask & ~used;
while (discovered) {
pi = ff_one(discovered);
discovered &= ~(1<<pi);
if (same_line(b->pieces[pi].pos, from, to)) {
topieces |= (1<<pi);
if (debug)
lprintf(0, "discovered: %s\n",
posstr(b->pieces[pi].pos));
break;
}
}

/* now we go through and work out the rest of the scores. */
tomove = 1;
i = 1;
gain += next;
swap_score[i++] = gain;
from = b->pieces[pi].pos;
if (debug)
lprintf(0, "from: %s gain: %d\n", posstr(from), gain);
topieces &= ~(1<<pi);
used |= (1<<pi);
discovered = b->topieces[from] & b->sliding_mask & ~used;
while (discovered) {
pi = ff_one(discovered);
discovered &= ~(1<<pi);
if (same_line(b->pieces[pi].pos, from, to)) {
topieces |= (1<<pi);
if (debug)
lprintf(0, "discovered: %s\n",
posstr(b->pieces[pi].pos));
break;
}
}
next = tomove*mat_value(ABS(b->board[from]));
tomove = -tomove;
}

/* now "minimax" the swap scores to determine the optimal
point to stop. */
--i;
while (i) {
if (tomove < 0) {
if (swap_score[i] < swap_score[i-1])
swap_score[i-1] = swap_score[i];
} else {
if (swap_score[i] > swap_score[i-1])
swap_score[i-1] = swap_score[i];
}
--i;
tomove = -tomove;
}

return swap_score;
}

```