Well the only place I saw to post that let attach files was the bug tracker ticket thing. So I will try one more time here. Hopefully this does not spam out the patch file into the page again. I will attach it without the big pgn.
Index: src/game.cpp =================================================================== --- src/game.cpp (revision 2569) +++ src/game.cpp (working copy) @@ -473,7 +473,8 @@ void Game::SaveState () { - if (!SavedPos) { SavedPos = new Position; } + if (!SavedPos) { SavedPos = new Position(this); } + CurrentPos->SetOwner(this); // just in case? SavedPos->CopyFrom (CurrentPos); SavedMove = CurrentMove; SavedPlyCount = CurrentPlyCount; @@ -490,6 +491,7 @@ if (SavedMove) { ASSERT (SavedPos != NULL); CurrentPos->CopyFrom (SavedPos); + CurrentPos->SetOwner(this); CurrentMove = SavedMove; CurrentPlyCount = SavedPlyCount; VarDepth = SavedVarDepth; @@ -591,9 +593,9 @@ StartPos = NULL; #ifdef WINCE if (!LowMem) - CurrentPos = new Position; + CurrentPos = new Position(this); #else - CurrentPos = new Position; + CurrentPos = new Position(this); #endif KeepDecodedMoves = true; SavedPos = NULL; @@ -700,6 +702,10 @@ // Set up standard start CurrentPos->StdStart(); + CurrentPos->SetOwner(this); + if ( ! StartPos ) { StartPos = new Position; } + StartPos->CopyFrom( CurrentPos ); + KeepDecodedMoves = true; } @@ -774,8 +780,12 @@ } VarDepth = 0; if (!StartPos) { StartPos = new Position; } + + pos->SetOwner(this); + StartPos->CopyFrom (pos); CurrentPos->CopyFrom (pos); + // // Now make the material signature: FinalMatSig = matsig_Make (StartPos->GetMaterial()); NonStandardStart = true; @@ -791,7 +801,7 @@ Game::SetStartFen (const char * fenStr) { // First try to read the position: - Position * pos = new Position; + Position * pos = new Position(this); errorT err = pos->ReadFromFEN (fenStr); if (err != OK) { delete pos; return err; } @@ -803,6 +813,7 @@ VarDepth = 0; if (StartPos) { delete StartPos; } StartPos = pos; + StartPos->SetOwner(this); CurrentPos->CopyFrom (StartPos); // Now make the material signature: FinalMatSig = matsig_Make (StartPos->GetMaterial()); @@ -965,6 +976,8 @@ CurrentPos->CopyFrom (StartPos); } else { CurrentPos->StdStart(); + CurrentPos->SetOwner(this); + StartPos->CopyFrom(CurrentPos); } CurrentPlyCount = 0; for (ushort i=0; i < hmNumber; i++) { @@ -1360,6 +1373,7 @@ ASSERT (CurrentMove != NULL); while (MoveExitVariation() == OK); // exit variations if (!StartPos) { StartPos = new Position; } + CurrentPos->SetOwner(this); // just in case? StartPos->CopyFrom (CurrentPos); NonStandardStart = true; CurrentMove->prev->marker = END_MARKER; @@ -3753,7 +3767,7 @@ // encodeKing(): encoding of King moves. // static inline void -encodeKing (ByteBuffer * buf, simpleMoveT * sm) +encodeKing (ByteBuffer * buf, simpleMoveT * sm, Position * pos) { // Valid King difference-from-old-square values are: // -9, -8, -7, -1, 1, 7, 8, 9, and -2 and 2 for castling. @@ -3763,6 +3777,31 @@ ASSERT(sm->pieceNum == 0); // Kings MUST be piece Number zero. int diff = (int) sm->to - (int) sm->from; + + squareT kr = NS; + squareT qr = NS; + rankT krank = square_Rank(sm->from); + + pieceT * board = pos->GetBoard(); + + pieceT friendlyrook = piece_Make( pos->GetToMove(), ROOK ); + + squareT kcur; + + kcur = sm->from; + while ( square_Rank(kcur) == krank ) { + if ( board[kcur] == friendlyrook ) { kr = kcur; break; } + kcur++; + } + kcur = sm->from; + while ( square_Rank(kcur) == krank ) { + if ( board[kcur] == friendlyrook ) { qr = kcur; break; } + kcur--; + } + + if (sm->to == kr) { diff = 2; } + if (sm->to == qr) { diff = -2; } + static const byte val[] = { /* -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 */ 1, 2, 3, 0, 0, 0, 0, 9, 4, 0, 5, 10, 0, 0, 0, 0, 6, 7, 8 @@ -3785,7 +3824,7 @@ // decodeKing(): decoding of King moves. // static inline errorT -decodeKing (byte val, simpleMoveT * sm) +decodeKing (byte val, simpleMoveT * sm, Position * pos) { static const int sqdiff[] = { 0, -9, -8, -7, -1, 1, 7, 8, 9, -2, 2 @@ -3797,8 +3836,34 @@ } if (val < 1 || val > 10) { return ERROR_Decode; } - sm->to = sm->from + sqdiff[val]; - return OK; + if (val >= 1 && val <= 8) { + sm->to = sm->from + sqdiff[val]; + return OK; + } + else { + int direction; + if (val == 9) { direction = -1; } //queenside + if (val == 10) { direction = 1; } //kingside + + squareT kdest; + kdest = NS; + squareT kcur = sm->from; + rankT krank = square_Rank(sm->from); + + pieceT friendlyrook = piece_Make( pos->GetToMove(), ROOK ); + pieceT * board = pos->GetBoard(); + + while ( square_Rank(kcur) == krank ) { + if ( board[kcur] == friendlyrook ) { kdest = kcur; break; } + kcur = kcur + direction; + } + + if (kcur != NS) { + sm->to = kdest; + return OK; + } + } + return ERROR_Decode; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -4129,7 +4194,7 @@ err = decodeBishop (val & 15, sm); break; case KING: - err = decodeKing (val & 15, sm); + err = decodeKing (val & 15, sm, pos); break; // For queen moves: Rook-like moves are in 1 byte, diagonals are in 2. case QUEEN: @@ -4146,7 +4211,7 @@ // Encode one move and output it to the bytebuffer. // static void -encodeMove (ByteBuffer * buf, moveT * m) +encodeMove (ByteBuffer * buf, moveT * m, Position * pos) { simpleMoveT * sm = &(m->moveData); pieceT pt = piece_Type(sm->movingPiece); @@ -4154,7 +4219,7 @@ typedef void encodeFnType (ByteBuffer *, simpleMoveT *); static encodeFnType * encodeFn[] = { NULL /* 0 */, - encodeKing /*1=KING*/, + NULL /*1=KING*/, encodeQueen /*2=QUEEN*/, encodeRook /*3=ROOK*/, encodeBishop /*4=BISHOP*/, @@ -4162,15 +4227,18 @@ encodePawn /*6=PAWN*/ }; ASSERT (pt >= KING && pt <= PAWN); - (encodeFn[pt]) (buf, sm); + if (pt > KING ) { (encodeFn[pt]) (buf, sm); } + else { + encodeKing(buf, sm, pos); + } } - +// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// encodeVariation(): Used by Encode() to encode the game's moves. +// Game::EncodeVariation(): Used by Encode() to encode the game's moves. // Recursive; calls itself to encode subvariations. // -static errorT -encodeVariation (ByteBuffer * buf, moveT * m, uint * subVarCount, +errorT +Game::EncodeVariation (ByteBuffer * buf, moveT * m, uint * subVarCount, uint * nagCount, uint depth) { ASSERT (m != NULL); @@ -4180,8 +4248,14 @@ buf->PutByte (ENCODE_COMMENT); } - while (m->marker != END_MARKER) { - encodeMove (buf, m); + errorT err; + while (m->marker != END_MARKER) { + encodeMove (buf, m, CurrentPos); + err = MoveForward(); + if (err != OK) { + m = m->next; + continue; + } for (uint i=0; i < (uint) m->nagCount; i++) { buf->PutByte (ENCODE_NAG); buf->PutByte (m->nags[i]); @@ -4195,7 +4269,7 @@ for (uint i=0; i < m->numVariations; i++) { *subVarCount += 1; buf->PutByte (ENCODE_START_MARKER); - encodeVariation (buf, subVar->next, subVarCount, nagCount, depth+1); + EncodeVariation (buf, subVar->next, subVarCount, nagCount, depth+1); subVar = subVar->varChild; } } @@ -4501,7 +4575,8 @@ // Now the movelist: uint varCount = 0; uint nagCount = 0; - err = encodeVariation (buf, FirstMove->next, &varCount, &nagCount, 0); + MoveToPly(0); + err = EncodeVariation (buf, FirstMove->next, &varCount, &nagCount, 0); if (err != OK) { return err; } // Now do the comments @@ -4689,6 +4764,7 @@ NonStandardStart = 0; return err; } + StartPos->SetOwner(this); CurrentPos->CopyFrom (StartPos); } @@ -4737,6 +4813,7 @@ NonStandardStart = 0; return err; } + StartPos->SetOwner(this); *CurrentPos = *StartPos; } Index: src/game.h =================================================================== --- src/game.h (revision 2569) +++ src/game.h (working copy) @@ -327,6 +327,8 @@ errorT DecodeTags (ByteBuffer * buf, bool storeTags); errorT DecodeVariation (ByteBuffer * buf, byte flags, uint level); + errorT EncodeVariation (ByteBuffer * buf, moveT * m, uint * subVarCount, uint * nagCount, uint depth); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game: Public Functions public: Index: src/movelist.h =================================================================== --- src/movelist.h (revision 2569) +++ src/movelist.h (working copy) @@ -46,6 +46,11 @@ squareT epSquare; // pre-move information ushort oldHalfMoveClock; int score; // used for alpha/beta ordering. + + squareT kingFrom; + squareT kingTo; + squareT rookFrom; + squareT rookTo; }; inline bool isNullMove (simpleMoveT * sm) Index: src/position.cpp =================================================================== --- src/position.cpp (revision 2569) +++ src/position.cpp (working copy) @@ -14,6 +14,7 @@ #include "common.h" #include "position.h" +#include "game.h" #include "attacks.h" #include "misc.h" #include "sqlist.h" @@ -295,6 +296,32 @@ } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Position::GetRookOrigSq(): +// Get the original square of a rook +// Uses newly programmed pointer to the owner game so we +// can use it to find the rook in it's StartPos +// +squareT +Position::GetRookOrigSq( colorT tomove, int dir ) { + Game * thisgame = GetOwner(); + if ( thisgame != NULL ) { + Position * startpos = thisgame->GetStartPos(); + if ( startpos != NULL ) { + pieceT * startboard = startpos->GetBoard(); + squareT kSquare = startpos->GetKingSquare(tomove); + rankT kRank = square_Rank(kSquare); + pieceT friendlyRook = piece_Make(ToMove, ROOK); + for (squareT sq = kSquare; square_Rank(sq) == kRank; sq=sq+dir) { + if (startboard[sq] == friendlyRook) { + return sq; + } + } + } + } + return NS; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenCastling(): // Generate the legal castling moves. // Assumes the side to move is NOT in check, so the caller @@ -305,44 +332,68 @@ { ASSERT (! IsKingInCheck()); squareT from = GetKingSquare(ToMove); - if (from != (ToMove == WHITE ? E1 : E8)) { return; } squareT enemyKingSq = GetEnemyKingSquare(); - squareT target, skip, rookSq; - pieceT rookPiece; + + squareT krookOrig = GetRookOrigSq ( ToMove, 1 ); + squareT qrookOrig = GetRookOrigSq ( ToMove, -1 ); - // Try kingside first + for ( int dir = -1; dir < 2; dir++ ) { + if ( dir == 0 ) { continue; } + bool ok = false; + if ( dir == -1 and (!StrictCastling || GetCastling (ToMove, QSIDE)) ) { ok = true; } + if ( dir == 1 and (!StrictCastling || GetCastling (ToMove, KSIDE)) ) { ok = true; } + if ( ! ok ) { continue; } - // Kingside Castling: - if (!StrictCastling || GetCastling (ToMove, KSIDE)) { - if (ToMove == WHITE) { - target = G1; skip = F1; rookSq = H1; rookPiece = WR; - } else { - target = G8; skip = F8; rookSq = H8; rookPiece = BR; - } - if (Board[target] == EMPTY && Board[skip] == EMPTY - && Board[rookSq] == rookPiece - && CalcNumChecks (target) == 0 - && CalcNumChecks (skip) == 0 - && ! square_Adjacent (target, enemyKingSq)) { - AddLegalMove (mlist, from, target, EMPTY); - } - } + for ( squareT rookSq = from; square_Rank(rookSq) == square_Rank(from); rookSq=rookSq+dir ) { + if ( Board[rookSq] == piece_Make(ToMove, ROOK) ) { + if ( dir == -1 && rookSq != qrookOrig ) { break; } // correct side, wrong rook + if ( dir == 1 && rookSq != krookOrig ) { break; } // correct side, wrong rook + squareT furthest_left, furthest_right, king_left, king_right; + squareT kdest, rdest; + squareT kingSq = from; - // Queenside Castling: - if (!StrictCastling || GetCastling (ToMove, QSIDE)) { - if (ToMove == WHITE) { - target = C1; skip = D1; rookSq = A1; rookPiece = WR; - } else { - target = C8; skip = D8; rookSq = A8; rookPiece = BR; + if ( dir > 0 ) { + kdest = (ToMove == WHITE ? G1 : G8); + rdest = (ToMove == WHITE ? F1 : F8); + } + if (dir < 0) { + kdest = (ToMove == WHITE ? C1 : C8); + rdest = (ToMove == WHITE ? D1 : D8); + } + furthest_left = kdest; + if (kingSq < furthest_left) { furthest_left = kingSq; } + if (rookSq < furthest_left) { furthest_left = rookSq; } + if (rdest < furthest_left) { furthest_left = rdest; } + + king_left = kdest; + if (kingSq < king_left) { king_left = kingSq; } + + furthest_right = kdest; + if (kingSq > furthest_right) { furthest_right = kingSq; } + if (rookSq > furthest_right) { furthest_right = rookSq; } + if (rdest > furthest_right) { furthest_right = rdest; } + + king_right = kdest; + if (kingSq > king_right) { king_right = kingSq; } + + bool ok2 = true; + for (squareT sq = king_left; sq <= king_right; sq++) { + if (CalcNumChecks(sq) > 0) { ok2 = false; break; } + if (square_Adjacent (sq, enemyKingSq)) { ok2 = false; break; } + } + + if ( ! ok2 ) { break; } + + uint piececount = 0; + for (squareT sq = furthest_left; sq <= furthest_right; sq++) { + if (Board[sq] != EMPTY) { piececount++ ; } + } + if (piececount > 2) { break; } + + AddLegalMove (mlist, from, rookSq, EMPTY); + break; + } } - if (Board[target] == EMPTY && Board[skip] == EMPTY - && Board[rookSq] == rookPiece - && Board[target - 1] == EMPTY // B1 or B8 must be empty too! - && CalcNumChecks (target) == 0 - && CalcNumChecks (skip) == 0 - && ! square_Adjacent (target, enemyKingSq)) { - AddLegalMove (mlist, from, target, EMPTY); - } } } @@ -563,9 +614,10 @@ // Initialise the position after it is constructed. // void -Position::Init (void) +Position::Init (Game * owner) { // Setting up a valid board is left to StdStart() or Clear(). + Owner = owner; Board [COLOR_SQUARE] = EMPTY; Board [NULL_SQUARE] = END_OF_BOARD; LegalMoves.Clear(); @@ -1252,51 +1304,83 @@ squareT kingSq = GetKingSquare(ToMove); sint diff = (int)target - (int) kingSq; - // Valid diffs are: -9, -8, -7, -2, -1, 1, 2, 7, 8, 9. (-2,2: Castling) - - if (diff < -9 || diff > 9) { return ERROR_InvalidMove; } - if (diff > -7 && diff < -2) { return ERROR_InvalidMove; } - if (diff > 2 && diff < 7) { return ERROR_InvalidMove; } if (diff == 0) { return ERROR_InvalidMove; } - if (diff == 2) { // KingSide Castling - if (kingSq != (ToMove == WHITE ? E1 : E8)) { - return ERROR_InvalidMove; + squareT rookSq; + rankT kingRnk = square_Rank(kingSq); + rankT targetRnk = square_Rank(target); + + bool castle_attempt = false; + if ( Board[target] == piece_Make(ToMove, ROOK) ) { + castle_attempt = true; + } + if (! castle_attempt) { + if (targetRnk != kingRnk) { + if (diff < -9 || diff > 9) { return ERROR_InvalidMove; } + if (diff > -6 && diff < 6) { return ERROR_InvalidMove; } } - if (StrictCastling && ! GetCastling (ToMove, KSIDE)) { - return ERROR_InvalidMove; + else if ( diff > 1 || diff < -1 ) { return ERROR_InvalidMove; } + } + + //check for all squares king has to move not touched by king or in check + //check all furthest only occupied by 2 pieces + + squareT enemyKingSq = GetEnemyKingSquare(); + + if (castle_attempt) { + rookSq = target; + + squareT furthest_left, furthest_right, king_left, king_right; + squareT kdest, rdest; + + if ( diff > 0 ) { // KingSide Castling + if ( rookSq != GetRookOrigSq ( ToMove, 1 ) ) { return ERROR_InvalidMove; } + kdest = (ToMove == WHITE ? G1 : G8); + rdest = (ToMove == WHITE ? F1 : F8); } + if (diff < 0) { // Queenside Castling + if ( rookSq != GetRookOrigSq ( ToMove, -1 ) ) { return ERROR_InvalidMove; } + kdest = (ToMove == WHITE ? C1 : C8); + rdest = (ToMove == WHITE ? D1 : D8); + } - // XXX We also need to verify that the target square does not - // lie adjacent to the location of the enemy king! + furthest_left = kdest; + if (kingSq < furthest_left) { furthest_left = kingSq; } + if (rookSq < furthest_left) { furthest_left = rookSq; } + if (rdest < furthest_left) { furthest_left = rdest; } - if (Board[kingSq + 1] != EMPTY || Board[kingSq + 2] != EMPTY - || CalcNumChecks(kingSq) > 0 - || CalcNumChecks(kingSq + 1) > 0 - || CalcNumChecks(kingSq + 2) > 0) { - return ERROR_InvalidMove; + king_left = kdest; + if (kingSq < king_left) { king_left = kingSq; } + + furthest_right = kdest; + if (kingSq > furthest_right) { furthest_right = kingSq; } + if (rookSq > furthest_right) { furthest_right = rookSq; } + if (rdest > furthest_right) { furthest_right = rdest; } + + king_right = kdest; + if (kingSq > king_right) { king_right = kingSq; } + + for (squareT sq = king_left; sq <= king_right; sq++) { + if (CalcNumChecks(sq) > 0) { return ERROR_InvalidMove; } } - AddLegalMove (mlist, kingSq, target, EMPTY); - return OK; - } - if (diff == -2) { // Queenside Castling - if (kingSq != (ToMove == WHITE ? E1 : E8)) { - return ERROR_InvalidMove; + uint piececount = 0; + for (squareT sq = furthest_left; sq <= furthest_right; sq++) { + if (Board[sq] != EMPTY) { piececount++ ; } } - if (StrictCastling && ! GetCastling (ToMove, QSIDE)) { - return ERROR_InvalidMove; + if (piececount > 2) { return ERROR_InvalidMove; } + + bool ok2 = true; + for (squareT sq = king_left; sq <= king_right; sq++) { + if (CalcNumChecks(sq) > 0) { ok2 = false; break; } + if (square_Adjacent (sq, enemyKingSq)) { ok2 = false; break; } } - if (Board[kingSq - 1] != EMPTY || Board[kingSq - 2] != EMPTY - || Board[kingSq - 3] != EMPTY - || CalcNumChecks(kingSq) > 0 - || CalcNumChecks(kingSq - 1) > 0 - || CalcNumChecks(kingSq - 2) > 0) { - return ERROR_InvalidMove; - } + if (!ok2) { return ERROR_InvalidMove; } + AddLegalMove (mlist, kingSq, target, EMPTY); return OK; } + pieceT captured = Board[target]; if (piece_Color(captured) == ToMove) { // Capturing a friendly piece! @@ -1307,6 +1391,8 @@ // leaves the King in check: // XXX We should also check for adjacency to enemy King!! + // why not get rid of : + /* Board[target] = piece_Make(ToMove, KING); Board[kingSq] = EMPTY; if (captured != EMPTY) { Material[captured]--; } @@ -1319,10 +1405,18 @@ AddLegalMove (mlist, kingSq, target, EMPTY); return OK; } + */ + // and just do: + if ( CalcNumChecks(target) == 0 && ! square_Adjacent (target, enemyKingSq) ) { + AddLegalMove (mlist, kingSq, target, EMPTY); + return OK; + } + + + return ERROR_InvalidMove; } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenCheckEvasions(): // Generate legal moves for the side to move when the @@ -1820,6 +1914,25 @@ sm->epSquare = EPTarget; sm->oldHalfMoveClock = HalfMoveClock; + sm->kingTo = NS; + sm->kingFrom = NS; + sm->rookFrom = NS; + sm->rookTo = NS; + + if ( ptype == KING && Board[to] == piece_Make( ToMove, ROOK) ) { + sm->capturedPiece = EMPTY; + sm->kingFrom = from; + sm->rookFrom = to; + if (from < to) { //kingside + sm->kingTo = ( ToMove == WHITE ? G1 : G8 ); + sm->rookTo = ( ToMove == WHITE ? F1 : F8 ); + } + else { //queenside + sm->kingTo = ( ToMove == WHITE ? C1 : C8 ); + sm->rookTo = ( ToMove == WHITE ? D1 : D8 ); + } + } + HalfMoveClock++; PlyCounter++; LegalMoves.Clear(); @@ -1871,28 +1984,30 @@ } // now make the move: - List[ToMove][sm->pieceNum] = to; - ListPos[to] = sm->pieceNum; - RemoveFromBoard (p, from); - AddToBoard (p, to); + if ( sm->kingFrom == NS ) { // not castling + List[ToMove][sm->pieceNum] = to; + ListPos[to] = sm->pieceNum; + RemoveFromBoard (p, from); + AddToBoard (p, to); + } // handle Castling: - if (ptype == KING && square_Fyle(from) == E_FYLE && - (square_Fyle(to) == C_FYLE || square_Fyle(to) == G_FYLE)) { - squareT rookfrom, rookto; + if ( sm->kingFrom != NS ) { // castling pieceT rook = piece_Make (ToMove, ROOK); - if (square_Fyle(to) == C_FYLE) { - rookfrom = to - 2; - rookto = to + 1; - } else { - rookfrom = to + 1; - rookto = to - 1; - } - ListPos[rookto] = ListPos[rookfrom]; - List[ToMove][ListPos[rookto]] = rookto; - RemoveFromBoard (rook, rookfrom); - AddToBoard (rook, rookto); + + byte king_pieceNum = sm->pieceNum; + byte rook_pieceNum = ListPos[sm->rookFrom]; + + List[ToMove][king_pieceNum] = sm->kingTo; + List[ToMove][rook_pieceNum] = sm->rookTo; + ListPos[sm->kingTo] = king_pieceNum; + ListPos[sm->rookTo] = rook_pieceNum; + + RemoveFromBoard (p, sm->kingFrom); + RemoveFromBoard (rook, sm->rookFrom); + AddToBoard (p, sm->kingTo); + AddToBoard (rook, sm->rookTo); } // Handle clearing of castling flags: @@ -1903,6 +2018,7 @@ SetCastling (ToMove, KSIDE, false); } // See if a rook moved or was captured: +/* if (ToMove == WHITE) { if (from == A1) { SetCastling (WHITE, QSIDE, false); } if (from == H1) { SetCastling (WHITE, KSIDE, false); } @@ -1914,6 +2030,24 @@ if (to == A1) { SetCastling (WHITE, QSIDE, false); } if (to == H1) { SetCastling (WHITE, KSIDE, false); } } +*/ + + squareT WKR_sq = GetRookOrigSq ( WHITE, 1 ); + squareT WQR_sq = GetRookOrigSq ( WHITE, -1 ); + squareT BKR_sq = GetRookOrigSq ( BLACK, 1 ); + squareT BQR_sq = GetRookOrigSq ( BLACK, -1 ); + + if (ToMove == WHITE) { + if (from == WQR_sq) { SetCastling (WHITE, QSIDE, false); } + if (from == WKR_sq) { SetCastling (WHITE, KSIDE, false); } + if (to == BQR_sq) { SetCastling (BLACK, QSIDE, false); } + if (to == BKR_sq) { SetCastling (BLACK, KSIDE, false); } + } else { + if (from == BQR_sq) { SetCastling (BLACK, QSIDE, false); } + if (from == BKR_sq) { SetCastling (BLACK, KSIDE, false); } + if (to == WQR_sq) { SetCastling (WHITE, QSIDE, false); } + if (to == WKR_sq) { SetCastling (WHITE, KSIDE, false); } + } } // Set the EPTarget square, if a pawn advanced two squares and an @@ -2000,29 +2134,37 @@ // now make the move: - List[ToMove][m->pieceNum] = from; - ListPos[from] = m->pieceNum; - RemoveFromBoard (p, to); - AddToBoard (p, from); - if (m->capturedPiece != EMPTY) { - AddToBoard (m->capturedPiece, m->capturedSquare); + if ( m->kingFrom > H8 ) { // not castling + List[ToMove][m->pieceNum] = from; + ListPos[from] = m->pieceNum; + RemoveFromBoard (p, to); + AddToBoard (p, from); + if (m->capturedPiece != EMPTY) { + AddToBoard (m->capturedPiece, m->capturedSquare); + } } // handle Castling: - if ((piece_Type(p) == KING) && square_Fyle(from) == E_FYLE - && (square_Fyle(to) == C_FYLE || square_Fyle(to) == G_FYLE)) { - squareT rookfrom, rookto; + if ( m->kingFrom <= H8 ) { // castling + m->pieceNum = ListPos[m->kingTo]; + p = Board[m->kingTo]; pieceT rook = (ToMove == WHITE? WR : BR); - if (square_Fyle(to) == C_FYLE) { - rookfrom = to - 2; rookto = to + 1; - } else { - rookfrom = to + 1; rookto = to - 1; - } - ListPos[rookfrom] = ListPos[rookto]; - List[ToMove][ListPos[rookto]] = rookfrom; - RemoveFromBoard (rook, rookto); - AddToBoard (rook, rookfrom); + + byte king_pieceNum = m->pieceNum; + byte rook_pieceNum = ListPos[m->rookTo]; + + List[ToMove][king_pieceNum] = m->kingFrom; + List[ToMove][rook_pieceNum] = m->rookFrom; + ListPos[m->kingFrom] = king_pieceNum; + ListPos[m->rookFrom] = rook_pieceNum; + + RemoveFromBoard (p, m->kingTo); + RemoveFromBoard (rook, m->rookTo); + AddToBoard (p, m->kingFrom); + AddToBoard (rook, m->rookFrom); + + m->to = m->rookFrom; } #ifdef ASSERTIONS @@ -2136,6 +2278,7 @@ // Make sure m->pieceNum is updated: m->pieceNum = ListPos[m->from]; + pieceT p = piece_Type (Board[List[ToMove][m->pieceNum]]); squareT from = List[ToMove][m->pieceNum]; squareT to = m->to; @@ -2158,11 +2301,13 @@ //*c++ = 'n'; *c++ = 'u'; *c++ = 'l'; *c++ = 'l'; *c++ = '-'; *c++ = '-'; } else - if ((square_Fyle(from)==E_FYLE) && (square_Fyle(to)==G_FYLE)) { - *c++ = 'O'; *c++ = '-'; *c++ = 'O'; - } else - if ((square_Fyle(from)==E_FYLE) && (square_Fyle(to)==C_FYLE)) { - *c++ = 'O'; *c++ = '-'; *c++ = 'O'; *c++ = '-'; *c++ = 'O'; + if ( Board[to] == piece_Make(ToMove,ROOK) ) { + if (from < to) { + *c++ = 'O'; *c++ = '-'; *c++ = 'O'; + } + else { + *c++ = 'O'; *c++ = '-'; *c++ = 'O'; *c++ = '-'; *c++ = 'O'; + } } else { // regular King move *c++ = 'K'; if (Board[to] != EMPTY) *c++ = 'x'; @@ -2430,9 +2575,22 @@ // Here we handle piece moves, including castling if (token != TOKEN_Move_Piece) { // Must be castling move ASSERT (token == TOKEN_Move_Castle_King || token == TOKEN_Move_Castle_Queen); - from = (ToMove == WHITE ? E1 : E8); - if (GetKingSquare(ToMove) != from) { return ERROR_InvalidMove; } - to = (token == TOKEN_Move_Castle_King ? (from + 2) : (from - 2)); + + rankT kingrank; + from = GetKingSquare(ToMove); + kingrank = square_Rank(from); + + int direction = ( token == TOKEN_Move_Castle_King ? 1 : -1 ); + + for (squareT sq = from + direction; square_Rank(sq) == kingrank; sq = sq + direction) { + if ( Board[sq] == piece_Make(ToMove, ROOK) ) { + to = sq; + break; + } + } + + if (to == NS) { return ERROR_InvalidMove; } + if (MatchKingMove (&mlist, to) != OK) { return ERROR_InvalidMove; } else { Index: src/position.h =================================================================== --- src/position.h (revision 2569) +++ src/position.h (working copy) @@ -24,6 +24,8 @@ #include "sqset.h" #include "tokens.h" +class Game; + ////////////////////////////////////////////////////////////////////// // Position: Constants @@ -77,6 +79,8 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position: Data structures + Game * Owner; + pieceT Board[66]; // the actual board + a color square // and a NULL square. uint Count[2]; // count of pieces & pawns each @@ -157,11 +161,12 @@ } #endif - Position() { Init(); } + Position() { Init( NULL ); } + Position(Game * owner) { Init( owner ); } Position(const Position& p); ~Position() {} - void Init(); + void Init(Game * owner); void Clear(); // No pieces on board void StdStart(); // Standard chess starting position bool IsStdStart(); @@ -179,6 +184,10 @@ ushort GetPlyCounter () { return PlyCounter; } ushort GetFullMoveCount () { return PlyCounter / 2 + 1; } + Game * GetOwner() { return Owner; } + void SetOwner(Game * owner) { Owner = owner; } + squareT GetRookOrigSq( colorT tomove, int dir ); + // Methods to get the Board or piece lists -- used in game.cpp to // decode moves: squareT * GetList (colorT c) { return List[c]; } Index: src/tkscid.cpp =================================================================== --- src/tkscid.cpp (revision 2569) +++ src/tkscid.cpp (working copy) @@ -516,8 +516,8 @@ clipbase->backupCache->SetPolicy (TREECACHE_Oldest); currentBase = 0; - scratchPos = new Position; scratchGame = new Game; + scratchPos = new Position(scratchGame); db = &(dbList[currentBase]); #ifndef TCL_ONLY @@ -14947,6 +14947,7 @@ char cboard [40]; pos->PrintCompactStrFlipped (cboard); posFlip->ReadFromCompactStr ((byte *) cboard); + posFlip->SetOwner(db->game); hpSigFlip = posFlip->GetHPSig(); msigFlip = matsig_Make (posFlip->GetMaterial()); }
------------------------------------------------------------------------------
_______________________________________________ Scidvspc-users mailing list Scidvspc-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/scidvspc-users