[Scidvspc-users] patch for chess960!
Chess Database and Toolkit program
Brought to you by:
stevenaaus
|
From: Britton F. <bri...@gm...> - 2016-08-01 20:16:17
|
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());
} |