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.01 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.