Author: Frank Phillips
Date: 01:57:03 04/02/00
Go up one level in this thread
On April 01, 2000 at 09:22:18, Dave Gomboc wrote:
>On April 01, 2000 at 09:19:52, Frank Phillips wrote:
>
>>I would be grateful if any Linux users could shed any light on the following:
>>
>>Having just upgraded from SuSe 6.2 to Mandrake 7.0 my chess program compiles but
>>does not correctly update the 64bit hash codes (using xor) during the search.
>>This is confirmed by a debug function which compares the incrementally updated
>>value with that calculated from scratch.
>>
>>Mandrake gcc, version 2.95.2 19991024 seems to cause the problem.
>>
>>After forcing version 2.91.66 19990314 to install in Mandrake from an old
>>RedHat 6.0 RPM, everything is back to normal.
>>
>>Frank
>
>You might consider posting a code snippet that people can look at.
Dave
This is embarrassing because I am not a programmer, but learning. Here are some
snippets of code. I have chosen the makemove functions since these update the
hash codes. Lets just say that the code is still developing……….
/*
*****************************************************************************
* *
* Make the move pointed to by pmove on the global board (board). *
* Update various characteristics of the current search position including *
* the hash code, pawn hash code and piece bitboards. *
* Store board and search details in node[ply] for use in unmake move. *
* Check if the move is legal and if not unmake it. *
* *
* board->ep is only set if the xstm can actually make an ep capture, *
* following Bruce Moreland's advice that the alternative is inefficient. *
* And to prevent generating ep moves when there are no actual captures. *
* *
* You may only wish to XOR in en-passant target square info if an *
* en-passant capture appears to be possible, otherwise you end up *
* with a different hash key for 1. e4 e5 2. c4 than you do for *
* 1. c4 e5 2. e4, and that's surprisingly inefficient. *
* bruce *
* *
* Return TRUE if the move is legal, otherwise return false. *
* *
*****************************************************************************
*/
int MakeMove(BoardT *pboard, MoveT *pmove, SearchNodeT *pnode)
{
int stm=pboard->stm;
/*
-------------------------------------------------------------------
| |
| Store board details at this ply to undo later. |
| |
-------------------------------------------------------------------
*/
pnode->ep=pboard->ep;
pnode->castle=pboard->castle;
pnode->fifty=pboard->fifty;
pnode->hash=pboard->hash;
pnode->pawn_hash=pboard->pawn_hash;
pnode->stm=pboard->stm;
pnode->last_move=pboard->last_move; //Move played that _led_ to current pboard.
/*
-------------------------------------------------------------------
| |
| Undo hash code for ep and castle rights. |
| |
-------------------------------------------------------------------
*/
pboard->hash ^= ep_hash[pboard->ep];
pboard->hash ^= castle_hash[pboard->castle];
/*
-------------------------------------------------------------------
| |
| Update the last ply's board variables. |
| |
-------------------------------------------------------------------
*/
pboard->castle=pboard->castle & castle_mask[pmove->from] &
castle_mask[pmove->to];
(pmove->type==CAPTURE_MOVE || pmove->piece==PAWN) ? pboard->fifty=0 :
pboard->fifty++;
pboard->stm = stm^1; //Side to move in this position (after move played).
pboard->last_move=*pmove; //Move made to cause current (next) position.
pboard->ep=0; //ep will be set if there _is_ an ep capture.
/*
-------------------------------------------------------------------
| |
| Make the move. |
| |
-------------------------------------------------------------------
*/
switch (pmove->type)
{
case CASTLE_KINGSIDE: //we already know is legal.
if(stm == WHITE)
{
pboard->piece[E1]=pboard->colour[E1]=EMPTY;
pboard->piece[G1]=KING;
pboard->colour[G1]=WHITE;
pboard->piece[H1]=pboard->colour[H1]=EMPTY;
pboard->piece[F1]=ROOK;
pboard->colour[F1]=WHITE;
pboard->hash ^= (hashcode[WHITE][KING][E1] ^ hashcode[WHITE][KING][G1]);
pboard->hash ^= (hashcode[WHITE][ROOK][H1] ^ hashcode[WHITE][ROOK][F1]);
//Update hash code for new ep and castling rights before returning!
pboard->hash ^= castle_hash[pboard->castle];
pboard->hash ^= ep_hash[pboard->ep];
//Update pboard
pboard->whiteking ^= mask.square[E1];
pboard->whiteking ^= mask.square[G1];
pboard->whiterooks ^= mask.square[H1];
pboard->whiterooks ^= mask.square[F1];
pboard->whitepieces ^= mask.square[E1];
pboard->whitepieces ^= mask.square[G1];
pboard->whitepieces ^= mask.square[H1];
pboard->whitepieces ^= mask.square[F1];
pboard->white_has_castled=TRUE;
pboard->king[WHITE]=G1;
return TRUE;
}
else //stm==BLACK.
{
pboard->piece[E8]=pboard->colour[E8]=EMPTY;
pboard->piece[G8]=KING;
pboard->colour[G8]=BLACK;
pboard->piece[H8]=pboard->colour[H8]=EMPTY;
pboard->piece[F8]=ROOK;
pboard->colour[F8]=BLACK;
pboard->hash ^= (hashcode[BLACK][KING][E8] ^ hashcode[BLACK][KING][G8]);
pboard->hash ^= (hashcode[BLACK][ROOK][H8] ^ hashcode[BLACK][ROOK][F8]);
//Update hash code for new ep and castling rights before returning!
pboard->hash ^= castle_hash[pboard->castle];
pboard->hash ^= ep_hash[pboard->ep];
//Update pboard.
pboard->blackking ^= mask.square[E8];
pboard->blackking ^= mask.square[G8];
pboard->blackrooks ^= mask.square[H8];
pboard->blackrooks ^= mask.square[F8];
pboard->blackpieces ^= mask.square[E8];
pboard->blackpieces ^= mask.square[G8];
pboard->blackpieces ^= mask.square[H8];
pboard->blackpieces ^= mask.square[F8];
pboard->black_has_castled=TRUE;
pboard->king[BLACK]=G8;
return TRUE;
}
break;
case CASTLE_QUEENSIDE: //We already know is legal.
if(stm == WHITE)
{
pboard->piece[E1]=pboard->colour[E1]=EMPTY;
pboard->piece[C1]=KING;
pboard->colour[C1]=WHITE;
pboard->piece[A1]=pboard->colour[A1]=EMPTY;
pboard->piece[D1]=ROOK;
pboard->colour[D1]=WHITE;
pboard->hash ^= (hashcode[WHITE][KING][E1] ^ hashcode[WHITE][KING][C1]);
pboard->hash ^= (hashcode[WHITE][ROOK][A1] ^ hashcode[WHITE][ROOK][D1]);
//Update hash code for new ep and castling rights before returning!
pboard->hash ^= castle_hash[pboard->castle];
pboard->hash ^= ep_hash[pboard->ep];
//Update bitpboard->
pboard->whiteking ^= mask.square[E1];
pboard->whiteking ^= mask.square[C1];
pboard->whiterooks ^= mask.square[A1];
pboard->whiterooks ^= mask.square[D1];
pboard->whitepieces ^= mask.square[E1];
pboard->whitepieces ^= mask.square[C1];
pboard->whitepieces ^= mask.square[A1];
pboard->whitepieces ^= mask.square[D1];
pboard->white_has_castled=TRUE;
pboard->king[WHITE]=C1;
return TRUE;
}
else //stm==BLACK.
{
pboard->piece[E8]=pboard->colour[E8]=EMPTY;
pboard->piece[C8]=KING;
pboard->colour[C8]=BLACK;
pboard->piece[A8]=pboard->colour[A8]=EMPTY;
pboard->piece[D8]=ROOK;
pboard->colour[D8]=BLACK;
pboard->hash ^= (hashcode[BLACK][KING][E8] ^ hashcode[BLACK][KING][C8]);
pboard->hash ^= (hashcode[BLACK][ROOK][A8] ^ hashcode[BLACK][ROOK][D8]);
//Update hash code for new ep and castling rights before returning!
pboard->hash ^= castle_hash[pboard->castle];
pboard->hash ^= ep_hash[pboard->ep];
//Update bitpboard->
pboard->blackking ^= mask.square[E8];
pboard->blackking ^= mask.square[C8];
pboard->blackrooks ^= mask.square[A8];
pboard->blackrooks ^= mask.square[D8];
pboard->blackpieces ^= mask.square[E8];
pboard->blackpieces ^= mask.square[C8];
pboard->blackpieces ^= mask.square[A8];
pboard->blackpieces ^= mask.square[D8];
pboard->black_has_castled=TRUE;
pboard->king[BLACK]=C8;
return TRUE;
}
break;
case NORMAL_MOVE:
UpdateBitBoard(pboard,pmove->from,pmove->to); //Before square colours change!
pboard->colour[pmove->to]=stm;
pboard->piece[pmove->to]=pmove->piece;
pboard->piece[pmove->from]=pboard->colour[pmove->from]=EMPTY;
pboard->hash ^= (hashcode[stm][pmove->piece][pmove->from] ^
hashcode[stm][pmove->piece][pmove->to]);
if (pmove->piece == PAWN)
pboard->pawn_hash ^= (hashcode[stm][PAWN][pmove->from] ^
hashcode[stm][PAWN][pmove->to]);
break;
case CAPTURE_MOVE:
UpdateBitBoard(pboard,pmove->from,pmove->to);
UpdateBitBoardCapture(pboard,pmove->to);
pboard->colour[pmove->to]=stm;
pboard->piece[pmove->to]=pmove->piece;
pboard->piece[pmove->from]=pboard->colour[pmove->from]=EMPTY;
if (pmove->capture == PAWN)
pboard->pawn_hash ^= hashcode[stm^1][PAWN][pmove->to];
pboard->hash ^= hashcode[stm^1][pmove->capture][pmove->to];
pboard->hash ^= (hashcode[stm][pmove->piece][pmove->from] ^
hashcode[stm][pmove->piece][pmove->to]);
if (pmove->piece == PAWN)
pboard->pawn_hash ^= (hashcode[stm][PAWN][pmove->from] ^
hashcode[stm][PAWN][pmove->to]);
break;
case PROMOTION_MOVE:
//Captured piece or empty square is stored in move[m].capture.
if (pmove->capture != EMPTY)
UpdateBitBoardCapture(pboard,pmove->to);
UpdateBitBoardCapture(pboard,pmove->from); //Remove the pawn.
UpdateBitBoardPromotion(pboard,stm,pmove->to,pmove->promote);
pboard->colour[pmove->to]=stm;
pboard->piece[pmove->to]=pmove->promote;
pboard->piece[pmove->from]=pboard->colour[pmove->from]=EMPTY;
if (pmove->capture != EMPTY)
pboard->hash ^= hashcode[stm^1][pmove->capture][pmove->to];
pboard->hash ^= (hashcode[stm][PAWN][pmove->from] ^
hashcode[stm][pmove->promote][pmove->to]);
pboard->pawn_hash ^= hashcode[stm][PAWN][pmove->from];
break;
case ENPASSANT_MOVE:
UpdateBitBoard(pboard,pmove->from,pmove->to);
if (stm == WHITE)
UpdateBitBoardCapture(pboard,pmove->to -8);
else
UpdateBitBoardCapture(pboard,pmove->to +8);
pboard->colour[pmove->to]=stm;
pboard->piece[pmove->to]=PAWN;
pboard->piece[pmove->from]=pboard->colour[pmove->from]=EMPTY;
if(stm == WHITE)
{
pboard->piece[pmove->to -8]=pboard->colour[pmove->to -8]=EMPTY;
pboard->hash ^= hashcode[stm^1][PAWN][pmove->to -8];
pboard->pawn_hash ^= hashcode[stm^1][PAWN][pmove->to -8];
}
else
{
pboard->piece[pmove->to +8]=pboard->colour[pmove->to +8]=EMPTY;
pboard->hash ^= hashcode[stm^1][PAWN][pmove->to +8];
pboard->pawn_hash ^= hashcode[stm^1][PAWN][pmove->to +8];
}
pboard->hash ^= (hashcode[stm][PAWN][pmove->from] ^
hashcode[stm][PAWN][pmove->to]);
pboard->pawn_hash ^= (hashcode[stm][PAWN][pmove->from] ^
hashcode[stm][PAWN][pmove->to]);
break;
case LEAVE_ENPASSANT_SQ:
UpdateBitBoard(pboard,pmove->from,pmove->to);
pboard->colour[pmove->to]=stm;
pboard->piece[pmove->to]=PAWN;
pboard->piece[pmove->from]=pboard->colour[pmove->from]=EMPTY;
//If xstm can actually make an ep capture then set pboard->ep
if (pboard->stm == WHITE)
{
if (pboard->whitepawns & mask.attack_w[pmove->ep])
pboard->ep=pmove->ep;
}
else
if (pboard->blackpawns & mask.attack_b[pmove->ep])
pboard->ep=pmove->ep;
pboard->hash ^= (hashcode[stm][PAWN][pmove->from] ^
hashcode[stm][PAWN][pmove->to]);
pboard->pawn_hash ^= (hashcode[stm][PAWN][pmove->from] ^
hashcode[stm][PAWN][pmove->to]);
break;
case NULL_MOVE:
break;
default:
break;
}
/*
-------------------------------------------------------------------
| |
| Update hash code for ep and castle rights. |
| |
-------------------------------------------------------------------
*/
pboard->hash ^= castle_hash[pboard->castle];
pboard->hash ^= ep_hash[pboard->ep];
/*
-------------------------------------------------------------------
| |
| If the king is not in check return true to signal that |
| a legal move has been made on the <pboard> |
| |
-------------------------------------------------------------------
*/
if (!Attack(pboard,pboard->king[stm],stm^1))
return (TRUE);
/*
-------------------------------------------------------------------
| |
| Otherwise its an illegal move, so we better unmake it all |
| and return (FALSE) to indicate that no move has been made. |
| |
-------------------------------------------------------------------
*/
UnMakeMove(pboard,pmove,pnode);
return (FALSE);
}
**************** This an example of the UpdateBitBoard() functions ********
/*
*****************************************************************************
* *
* Update a board data. *
* Simply XORs the from and to square. *
* *
*****************************************************************************
*/
void UpdateBitBoard(BoardT *pboard, int from, int to)
{
//Combine <from> and <to> squares to update bitboards in one XOR operation.
BITBOARD temp=mask.square[from] | mask.square[to];
if (pboard->colour[from] == WHITE)
switch (pboard->piece[from])
{
case KING:
pboard->whiteking ^= temp;
pboard->whitepieces ^= temp;
pboard->king[WHITE]=to;
break;
case PAWN:
pboard->whitepawns ^= temp;
pboard->whitepieces ^= temp;
break;
case ROOK:
pboard->whiterooks ^= temp;
pboard->whitepieces ^= temp;
break;
*************** And a few macros *****************
#define ZeroSquare(a,b) ((a) &= (~mask.square[b])) //Correct but
#define ClearSquare(a,b) ((a) ^= (mask.square[b])) //Toggle is quicker!
>
>Dave
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.