* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
static int exiting = 0; /* [HGM] moved to top */
static int setboardSpoiledMachineBlack = 0 /*, errorExitFlag = 0*/;
int startedFromPositionFile = FALSE; Board filePosition; /* [HGM] loadPos */
+int rightsBoard[BOARD_RANKS][BOARD_FILES]; /* [HGM] editrights */
char endingGame = 0; /* [HGM] crash: flag to prevent recursion of GameEnds() */
int whiteNPS, blackNPS; /* [HGM] nps: for easily making clocks aware of NPS */
VariantClass currentlyInitializedVariant; /* [HGM] variantswitch */
click-click move is possible */
if (toX == -2 || toY == -2) {
boards[0][fromY][fromX] = EmptySquare;
+ rightsBoard[fromY][fromX] = 0;
return AmbiguousMove;
} else if (toX >= 0 && toY >= 0) {
boards[0][toY][toX] = boards[0][fromY][fromX];
}
} else
boards[0][fromY][fromX] = EmptySquare;
+ rightsBoard[fromY][fromX] = rightsBoard[toY][toX] = 0;
return AmbiguousMove;
}
return ImpossibleMove;
FinishMove(moveType, fromX, fromY, toX, toY, promoChar);
}
+int hTab[(int)EmptySquare/2+1] = { 1,1,1,1,1,1,2,1,2,3,2,3,3,3,2,3,4,3,3,4,4,3,4 };
+int wTab[(int)EmptySquare/2+1] = { 1,1,2,3,4,5,3,7,4,3,5,4,4,5,7,5,4,6,6,5,5,7,6 };
+Board promoBoard;
+int promotionChoice = 0;
+
+void
+PiecePopUp(int x, int y)
+{
+ int i, j, h, w, nWhite=0, nBlack=0;
+ ChessSquare list[EmptySquare];
+ for(i=0; i<EmptySquare/2; i++) {
+ if(PieceToChar(i) != '.') list[nWhite++] = i;
+ if(PieceToChar(i+EmptySquare/2) != '.') list[EmptySquare - ++nBlack] = i + EmptySquare/2;
+ }
+ CopyBoard(promoBoard, boards[currentMove]);
+ for(i=0; i<BOARD_HEIGHT; i++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++) promoBoard[i][j] = EmptySquare;
+ j = nWhite + nBlack + 1;
+ h = sqrt((j+1)/2 + 1.); w = (j+h-1)/h;
+ if(w>BOARD_RGHT-BOARD_LEFT) { w = BOARD_RGHT - BOARD_LEFT; h = (j+w-1)/w; }
+ for(i=0; i<nWhite; i++) promoBoard[i/w][BOARD_LEFT+i%w] = list[nWhite-1-i];
+ if(h==2 && nWhite == nBlack)
+ for(i=0; i<nWhite; i++) promoBoard[1][BOARD_LEFT+i%w] = list[EmptySquare-nBlack+i];
+ else
+ for(i=0; i<nBlack; i++) promoBoard[h-1-i/w][BOARD_LEFT+w-1-i%w] = list[EmptySquare-nBlack+i];
+ promotionChoice = 3;
+ ClearHighlights();
+ PromoDialog(h, w, promoBoard, TRUE, _("Select piece:"), x, y);
+}
+
+void
+PromoPopUp(ChessSquare piece)
+{ // determine the layout of the piece-choice dialog
+ int w, h, i, j, nr;
+ ChessSquare list[EmptySquare];
+
+ for(i=0; i<BOARD_HEIGHT; i++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++) promoBoard[i][j] = EmptySquare;
+ if(gameInfo.variant == VariantShogi) {
+ // non-Pawn promotes; must be shogi
+ h = 1; w = 1; promoBoard[0][BOARD_LEFT+0] = piece;
+ if(PieceToChar(PROMOTED piece) != '.') {
+ // promoted version is enabled
+ w = 2; promoBoard[0][BOARD_LEFT+1] = PROMOTED piece;
+ }
+ } else {
+ // Pawn, promotes to any enabled other piece
+ h = 1; w = nr = 0;
+ for(i=1; i<EmptySquare/2; i++) {
+ if(PieceToChar(piece+i) != '.'
+ && PieceToChar(piece + i) != '~' // suppress bughouse true pieces
+ ) {
+ list[w++] = piece+i; nr++;
+ }
+ }
+ if(appData.testLegality && gameInfo.variant != VariantSuicide
+ && gameInfo.variant != VariantGiveaway) nr--,w--; // remove King
+ h = hTab[nr]; w = wTab[nr]; // factorize with nice ratio
+ for(i=0; i < nr; i++) promoBoard[i/w][BOARD_LEFT+i%w] = list[i]; // layout
+ }
+ promotionChoice = 2; // wait for click on board
+ PromoDialog(h, w, promoBoard, FALSE, _("Promote to:"), -1, -1);
+}
+
void
Mark(board, flags, kind, rf, ff, rt, ft, closure)
Board board;
{
int x, y;
Boolean saveAnimate;
- static int second = 0, promotionChoice = 0;
+ static int second = 0;
char promoChoice = NULLCHAR;
if(appData.seekGraph && appData.icsActive && loggedOn &&
}
if(promotionChoice) { // we are waiting for a click to indicate promotion piece
+ ChessSquare p = EmptySquare; Boolean inHoldings;
+ if(promotionChoice == 3) {
+ if(clickType == Press) EditPositionMenuEvent(promoBoard[y][x], fromX, fromY);
+ else if(clickType == Release) promotionChoice = 0;
+ fromX = fromY = -1;
+ return;
+ }
if(clickType == Release) return; // ignore upclick of click-click destination
- promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
- if(gameInfo.holdingsWidth &&
+ inHoldings = gameInfo.holdingsWidth &&
(WhiteOnMove(currentMove)
? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
- : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
+ : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1);
// click in right holdings, for determining promotion piece
- ChessSquare p = boards[currentMove][y][x];
+ if(promotionChoice == 1 && inHoldings || promotionChoice == 2 && x >= BOARD_LEFT && x < BOARD_RGHT) {
+ p = promoBoard[y][x];
if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
if(p != EmptySquare) {
- FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
+ char promoChar = PieceToChar(p);
+ if(gameInfo.variant == VariantShogi && promoChar != '+') promoChar = '=';
+ FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(promoChar));
fromX = fromY = -1;
+ promotionChoice = 0;
return;
}
}
+ promotionChoice = 0; // only one chance: if click not OK it is interpreted as cancel
DrawPosition(FALSE, boards[currentMove]);
return;
}
SetHighlights(fromX, fromY, toX, toY);
if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
// [HGM] super: promotion to captured piece selected from holdings
- ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
- promotionChoice = TRUE;
+ ChessSquare p = boards[currentMove][fromY][fromX];
+ promotionChoice = 1;
+ CopyBoard(promoBoard, boards[currentMove]);
// kludge follows to temporarily execute move on display, without promoting yet
- boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
- boards[currentMove][toY][toX] = p;
- DrawPosition(FALSE, boards[currentMove]);
- boards[currentMove][fromY][fromX] = p; // take back, but display stays
- boards[currentMove][toY][toX] = q;
+ promoBoard[fromY][fromX] = EmptySquare; // move Pawn to 8th rank
+ promoBoard[toY][toX] = p;
+ DrawPosition(FALSE, promoBoard);
DisplayMessage("Click in holdings to choose piece", "");
return;
}
- PromotionPopUp();
+ CopyBoard(promoBoard, boards[currentMove]);
+ PromoPopUp(boards[currentMove][fromY][fromX]);
} else {
UserMoveEvent(fromX, fromY, toX, toY, promoChoice);
if (!appData.highlightLastMove || gotPremove) ClearHighlights();
}
}
-int RightClick(ClickType action, int x, int y, int *fromX, int *fromY)
+int RightClick(ClickType action, int x, int y, int *xx, int *yy)
{ // front-end-free part taken out of PieceMenuPopup
int whichMenu; int xSqr, ySqr;
xSqr = EventToSquare(x, BOARD_WIDTH);
ySqr = EventToSquare(y, BOARD_HEIGHT);
+ if (flipView)
+ xSqr = BOARD_WIDTH - 1 - xSqr;
+ else
+ ySqr = BOARD_HEIGHT - 1 - ySqr;
+ if(promotionChoice == 3 && action == Release) {
+ EditPositionMenuEvent(promoBoard[ySqr][xSqr], fromX, fromY);
+ fromX = fromY = -1;
+ promotionChoice = 0;
+ return -1;
+ }
if (action == Release) UnLoadPV(); // [HGM] pv
if (action != Press) return -2; // return code to be ignored
switch (gameMode) {
return -1;
}
- if (((*fromX = xSqr) < 0) ||
- ((*fromY = ySqr) < 0)) {
- *fromX = *fromY = -1;
+ if (((*xx = xSqr) < 0) ||
+ ((*yy = ySqr) < 0)) {
+ *xx = *yy = -1;
return -1;
}
- if (flipView)
- *fromX = BOARD_WIDTH - 1 - *fromX;
- else
- *fromY = BOARD_HEIGHT - 1 - *fromY;
+
+ fromX = *xx; fromY = *yy;
+ if(whichMenu == 0) { PiecePopUp(x, y); return -1; } // suppress EditPosition menu
return whichMenu;
}
if (gameMode == TwoMachinesPlay) {
GameEnds(machineWhite ? BlackWins : WhiteWins,
buf1, GE_XBOARD);
-<<<<<<< HEAD
}
return;
}
if (cps->sendTime == 2) cps->sendTime = 1;
if (cps->offeredDraw) cps->offeredDraw--;
-#if ZIPPY
- if ((gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack) &&
- first.initDone) {
- SendMoveToICS(moveType, fromX, fromY, toX, toY);
- ics_user_moved = 1;
- if(appData.autoKibitz && !appData.icsEngineAnalyze ) { /* [HGM] kibitz: send most-recent PV info to ICS */
- char buf[3*MSG_SIZ];
-
- sprintf(buf, "kibitz !!! %+.2f/%d (%.2f sec, %u nodes, %.0f knps) PV=%s\n",
- programStats.score / 100.,
- programStats.depth,
- programStats.time / 100.,
- (unsigned int)programStats.nodes,
- (unsigned int)programStats.nodes / (10*abs(programStats.time) + 1.),
- programStats.movelist);
- SendToICS(buf);
-if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.nodes, programStats.nodes);
- }
- }
-#endif
/* currentMoveString is set as a side-effect of ParseOneMove */
strcpy(machineMove, currentMoveString);
strcat(machineMove, "\n");
strcpy(moveList[forwardMostMove], machineMove);
- /* [AS] Save move info and clear stats for next move */
- pvInfoList[ forwardMostMove ].score = programStats.score;
- pvInfoList[ forwardMostMove ].depth = programStats.depth;
- pvInfoList[ forwardMostMove ].time = programStats.time; // [HGM] PGNtime: take time from engine stats
- ClearProgramStats();
- thinkOutput[0] = NULLCHAR;
- hiddenThinkOutputState = 0;
-
MakeMove(fromX, fromY, toX, toY, promoChar);/*updates forwardMostMove*/
/* [AS] Adjudicate game if needed (note: remember that forwardMostMove now points past the last move) */
if( count >= adjudicateLossPlies ) {
ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
- GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins,
- "Xboard adjudication",
- GE_XBOARD );
-
- return;
- }
- }
-
- if( gameMode == TwoMachinesPlay ) {
- // [HGM] some adjudications useful with buggy engines
- int k, count = 0; static int bare = 1;
- if(gameInfo.holdingsSize == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
-
-
- if( appData.testLegality )
- { /* [HGM] Some more adjudications for obstinate engines */
- int NrWN=0, NrBN=0, NrWB=0, NrBB=0, NrWR=0, NrBR=0,
- NrWQ=0, NrBQ=0, NrW=0, NrK=0, bishopsColor = 0,
- NrPieces=0, NrPawns=0, PawnAdvance=0, i, j;
- static int moveCount = 6;
- ChessMove result;
- char *reason = NULL;
-
- /* Count what is on board. */
- for(i=0; i<BOARD_HEIGHT; i++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++)
- { ChessSquare p = boards[forwardMostMove][i][j];
- int m=i;
-
- switch((int) p)
- { /* count B,N,R and other of each side */
- case WhiteKing:
- case BlackKing:
- NrK++; break; // [HGM] atomic: count Kings
- case WhiteKnight:
- NrWN++; break;
- case WhiteBishop:
- case WhiteFerz: // [HGM] shatranj: kludge to mke it work in shatranj
- bishopsColor |= 1 << ((i^j)&1);
- NrWB++; break;
- case BlackKnight:
- NrBN++; break;
- case BlackBishop:
- case BlackFerz: // [HGM] shatranj: kludge to mke it work in shatranj
- bishopsColor |= 1 << ((i^j)&1);
- NrBB++; break;
- case WhiteRook:
- NrWR++; break;
- case BlackRook:
- NrBR++; break;
- case WhiteQueen:
- NrWQ++; break;
- case BlackQueen:
- NrBQ++; break;
- case EmptySquare:
- break;
- case BlackPawn:
- m = 7-i;
- case WhitePawn:
- PawnAdvance += m; NrPawns++;
- }
- NrPieces += (p != EmptySquare);
- NrW += ((int)p < (int)BlackPawn);
- if(gameInfo.variant == VariantXiangqi &&
- (p == WhiteFerz || p == WhiteAlfil || p == BlackFerz || p == BlackAlfil)) {
- NrPieces--; // [HGM] XQ: do not count purely defensive pieces
- NrW -= ((int)p < (int)BlackPawn);
- }
- }
-
- /* Some material-based adjudications that have to be made before stalemate test */
- if(gameInfo.variant == VariantAtomic && NrK < 2) {
- // [HGM] atomic: stm must have lost his King on previous move, as destroying own K is illegal
- boards[forwardMostMove][EP_STATUS] = EP_CHECKMATE; // make claimable as if stm is checkmated
- if(appData.checkMates) {
- SendMoveToProgram(forwardMostMove-1, cps->other); // make sure opponent gets move
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
- GameEnds( WhiteOnMove(forwardMostMove) ? BlackWins : WhiteWins,
- "Xboard adjudication: King destroyed", GE_XBOARD );
- return;
- }
- }
-
- /* Bare King in Shatranj (loses) or Losers (wins) */
- if( NrW == 1 || NrPieces - NrW == 1) {
- if( gameInfo.variant == VariantLosers) { // [HGM] losers: bare King wins (stm must have it first)
- boards[forwardMostMove][EP_STATUS] = EP_WINS; // mark as win, so it becomes claimable
- if(appData.checkMates) {
- SendMoveToProgram(forwardMostMove-1, cps->other); // make sure opponent gets to see move
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
- GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins,
- "Xboard adjudication: Bare king", GE_XBOARD );
- return;
- }
- } else
- if( gameInfo.variant == VariantShatranj && --bare < 0)
- { /* bare King */
- boards[forwardMostMove][EP_STATUS] = EP_WINS; // make claimable as win for stm
- if(appData.checkMates) {
- /* but only adjudicate if adjudication enabled */
- SendMoveToProgram(forwardMostMove-1, cps->other); // make sure opponent gets move
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
- GameEnds( NrW > 1 ? WhiteWins : NrPieces - NrW > 1 ? BlackWins : GameIsDrawn,
- "Xboard adjudication: Bare king", GE_XBOARD );
- return;
- }
- }
- } else bare = 1;
-
-
- // don't wait for engine to announce game end if we can judge ourselves
- switch (MateTest(boards[forwardMostMove], PosFlags(forwardMostMove)) ) {
- case MT_CHECK:
- if(gameInfo.variant == Variant3Check) { // [HGM] 3check: when in check, test if 3rd time
- int i, checkCnt = 0; // (should really be done by making nr of checks part of game state)
- for(i=forwardMostMove-2; i>=backwardMostMove; i-=2) {
- if(MateTest(boards[i], PosFlags(i)) == MT_CHECK)
- checkCnt++;
- if(checkCnt >= 2) {
- reason = "Xboard adjudication: 3rd check";
- boards[forwardMostMove][EP_STATUS] = EP_CHECKMATE;
- break;
- }
- }
- }
- case MT_NONE:
- default:
- break;
- case MT_STALEMATE:
- case MT_STAINMATE:
- reason = "Xboard adjudication: Stalemate";
- if((signed char)boards[forwardMostMove][EP_STATUS] != EP_CHECKMATE) { // [HGM] don't touch win through baring or K-capt
- boards[forwardMostMove][EP_STATUS] = EP_STALEMATE; // default result for stalemate is draw
- if(gameInfo.variant == VariantLosers || gameInfo.variant == VariantGiveaway) // [HGM] losers:
- boards[forwardMostMove][EP_STATUS] = EP_WINS; // in these variants stalemated is always a win
- else if(gameInfo.variant == VariantSuicide) // in suicide it depends
- boards[forwardMostMove][EP_STATUS] = NrW == NrPieces-NrW ? EP_STALEMATE :
- ((NrW < NrPieces-NrW) != WhiteOnMove(forwardMostMove) ?
- EP_CHECKMATE : EP_WINS);
- else if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantXiangqi)
- boards[forwardMostMove][EP_STATUS] = EP_CHECKMATE; // and in these variants being stalemated loses
- }
- break;
- case MT_CHECKMATE:
- reason = "Xboard adjudication: Checkmate";
- boards[forwardMostMove][EP_STATUS] = (gameInfo.variant == VariantLosers ? EP_WINS : EP_CHECKMATE);
- break;
-=======
->>>>>>> master
- }
- return;
- }
-
-<<<<<<< HEAD
- switch(i = (signed char)boards[forwardMostMove][EP_STATUS]) {
- case EP_STALEMATE:
- result = GameIsDrawn; break;
- case EP_CHECKMATE:
- result = WhiteOnMove(forwardMostMove) ? BlackWins : WhiteWins; break;
- case EP_WINS:
- result = WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins; break;
- default:
- result = (ChessMove) 0;
- }
- if(appData.checkMates && result) { // [HGM] mates: adjudicate finished games if requested
- SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
- GameEnds( result, reason, GE_XBOARD );
- return;
- }
-
- /* Next absolutely insufficient mating material. */
- if( NrPieces == 2 || gameInfo.variant != VariantXiangqi &&
- gameInfo.variant != VariantShatranj && // [HGM] baring will remain possible
- (NrPieces == 3 && NrWN+NrBN+NrWB+NrBB == 1 ||
- NrPieces == NrBB+NrWB+2 && bishopsColor != 3)) // [HGM] all Bishops (Ferz!) same color
- { /* KBK, KNK, KK of KBKB with like Bishops */
-=======
- /* [HGM] Apparently legal, but so far only tested with EP_UNKOWN */
- /* So we have to redo legality test with true e.p. status here, */
- /* to make sure an illegal e.p. capture does not slip through, */
- /* to cause a forfeit on a justified illegal-move complaint */
- /* of the opponent. */
- if( gameMode==TwoMachinesPlay && appData.testLegality
- && fromY != DROP_RANK /* [HGM] temporary; should still add legality test for drops */
- ) {
- ChessMove moveType;
- moveType = LegalityTest(boards[forwardMostMove], PosFlags(forwardMostMove),
- fromY, fromX, toY, toX, promoChar);
- if (appData.debugMode) {
- int i;
- for(i=0; i< nrCastlingRights; i++) fprintf(debugFP, "(%d,%d) ",
- boards[forwardMostMove][CASTLING][i], castlingRank[i]);
- fprintf(debugFP, "castling rights\n");
- }
- if(moveType == IllegalMove) {
- sprintf(buf1, "Xboard: Forfeit due to illegal move: %s (%c%c%c%c)%c",
- machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, 0);
- GameEnds(machineWhite ? BlackWins : WhiteWins,
- buf1, GE_XBOARD);
- return;
- } else if(gameInfo.variant != VariantFischeRandom && gameInfo.variant != VariantCapaRandom)
- /* [HGM] Kludge to handle engines that send FRC-style castling
- when they shouldn't (like TSCP-Gothic) */
- switch(moveType) {
- case WhiteASideCastleFR:
- case BlackASideCastleFR:
- toX+=2;
- currentMoveString[2]++;
- break;
- case WhiteHSideCastleFR:
- case BlackHSideCastleFR:
- toX--;
- currentMoveString[2]--;
- break;
- default: ; // nothing to do, but suppresses warning of pedantic compilers
- }
- }
- hintRequested = FALSE;
- lastHint[0] = NULLCHAR;
- bookRequested = FALSE;
- /* Program may be pondering now */
- cps->maybeThinking = TRUE;
- if (cps->sendTime == 2) cps->sendTime = 1;
- if (cps->offeredDraw) cps->offeredDraw--;
->>>>>>> master
-
- /* currentMoveString is set as a side-effect of ParseOneMove */
- strcpy(machineMove, currentMoveString);
- strcat(machineMove, "\n");
- strcpy(moveList[forwardMostMove], machineMove);
-
- MakeMove(fromX, fromY, toX, toY, promoChar);/*updates forwardMostMove*/
-
-<<<<<<< HEAD
- /* Then some trivial draws (only adjudicate, cannot be claimed) */
- if(NrPieces == 4 &&
- ( NrWR == 1 && NrBR == 1 /* KRKR */
- || NrWQ==1 && NrBQ==1 /* KQKQ */
- || NrWN==2 || NrBN==2 /* KNNK */
- || NrWN+NrWB == 1 && NrBN+NrBB == 1 /* KBKN, KBKB, KNKN */
- ) ) {
- if(--moveCount < 0 && appData.trivialDraws)
- { /* if the first 3 moves do not show a tactical win, declare draw */
- SendToProgram("force\n", cps->other); // suppress reply
- SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
- GameEnds( GameIsDrawn, "Xboard adjudication: Trivial draw", GE_XBOARD );
- return;
- }
- } else moveCount = 6;
- }
- }
-
- if (appData.debugMode) { int i;
- fprintf(debugFP, "repeat test fmm=%d bmm=%d ep=%d, reps=%d\n",
- forwardMostMove, backwardMostMove, boards[backwardMostMove][EP_STATUS],
- appData.drawRepeats);
- for( i=forwardMostMove; i>=backwardMostMove; i-- )
- fprintf(debugFP, "%d ep=%d\n", i, (signed char)boards[i][EP_STATUS]);
-
- }
-
- /* Check for rep-draws */
- count = 0;
- for(k = forwardMostMove-2;
- k>=backwardMostMove && k>=forwardMostMove-100 &&
- (signed char)boards[k][EP_STATUS] < EP_UNKNOWN &&
- (signed char)boards[k+2][EP_STATUS] <= EP_NONE && (signed char)boards[k+1][EP_STATUS] <= EP_NONE;
- k-=2)
- { int rights=0;
- if(CompareBoards(boards[k], boards[forwardMostMove])) {
- /* compare castling rights */
- if( boards[forwardMostMove][CASTLING][2] != boards[k][CASTLING][2] &&
- (boards[k][CASTLING][0] != NoRights || boards[k][CASTLING][1] != NoRights) )
- rights++; /* King lost rights, while rook still had them */
- if( boards[forwardMostMove][CASTLING][2] != NoRights ) { /* king has rights */
- if( boards[forwardMostMove][CASTLING][0] != boards[k][CASTLING][0] ||
- boards[forwardMostMove][CASTLING][1] != boards[k][CASTLING][1] )
- rights++; /* but at least one rook lost them */
- }
- if( boards[forwardMostMove][CASTLING][5] != boards[k][CASTLING][5] &&
- (boards[k][CASTLING][3] != NoRights || boards[k][CASTLING][4] != NoRights) )
- rights++;
- if( boards[forwardMostMove][CASTLING][5] != NoRights ) {
- if( boards[forwardMostMove][CASTLING][3] != boards[k][CASTLING][3] ||
- boards[forwardMostMove][CASTLING][4] != boards[k][CASTLING][4] )
- rights++;
- }
- if( rights == 0 && ++count > appData.drawRepeats-2
- && appData.drawRepeats > 1) {
- /* adjudicate after user-specified nr of repeats */
- SendToProgram("force\n", cps->other); // suppress reply
- SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
- if(gameInfo.variant == VariantXiangqi && appData.testLegality) {
- // [HGM] xiangqi: check for forbidden perpetuals
- int m, ourPerpetual = 1, hisPerpetual = 1;
- for(m=forwardMostMove; m>k; m-=2) {
- if(MateTest(boards[m], PosFlags(m)) != MT_CHECK)
- ourPerpetual = 0; // the current mover did not always check
- if(MateTest(boards[m-1], PosFlags(m-1)) != MT_CHECK)
- hisPerpetual = 0; // the opponent did not always check
- }
- if(appData.debugMode) fprintf(debugFP, "XQ perpetual test, our=%d, his=%d\n",
- ourPerpetual, hisPerpetual);
- if(ourPerpetual && !hisPerpetual) { // we are actively checking him: forfeit
- GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins,
- "Xboard adjudication: perpetual checking", GE_XBOARD );
- return;
- }
- if(hisPerpetual && !ourPerpetual) // he is checking us, but did not repeat yet
- break; // (or we would have caught him before). Abort repetition-checking loop.
- // Now check for perpetual chases
- if(!ourPerpetual && !hisPerpetual) { // no perpetual check, test for chase
- hisPerpetual = PerpetualChase(k, forwardMostMove);
- ourPerpetual = PerpetualChase(k+1, forwardMostMove);
- if(ourPerpetual && !hisPerpetual) { // we are actively chasing him: forfeit
- GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins,
- "Xboard adjudication: perpetual chasing", GE_XBOARD );
- return;
- }
- if(hisPerpetual && !ourPerpetual) // he is chasing us, but did not repeat yet
- break; // Abort repetition-checking loop.
- }
- // if neither of us is checking or chasing all the time, or both are, it is draw
- }
- GameEnds( GameIsDrawn, "Xboard adjudication: repetition draw", GE_XBOARD );
- return;
- }
- if( rights == 0 && count > 1 ) /* occurred 2 or more times before */
- boards[forwardMostMove][EP_STATUS] = EP_REP_DRAW;
- }
- }
-
- /* Now we test for 50-move draws. Determine ply count */
- count = forwardMostMove;
- /* look for last irreversble move */
- while( (signed char)boards[count][EP_STATUS] <= EP_NONE && count > backwardMostMove )
- count--;
- /* if we hit starting position, add initial plies */
- if( count == backwardMostMove )
- count -= initialRulePlies;
- count = forwardMostMove - count;
- if( count >= 100)
- boards[forwardMostMove][EP_STATUS] = EP_RULE_DRAW;
- /* this is used to judge if draw claims are legal */
- if(appData.ruleMoves > 0 && count >= 2*appData.ruleMoves) {
- SendToProgram("force\n", cps->other); // suppress reply
- SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
- GameEnds( GameIsDrawn, "Xboard adjudication: 50-move rule", GE_XBOARD );
- return;
-=======
- /* [AS] Adjudicate game if needed (note: remember that forwardMostMove now points past the last move) */
- if( gameMode == TwoMachinesPlay && adjudicateLossThreshold != 0 && forwardMostMove >= adjudicateLossPlies ) {
- int count = 0;
-
- while( count < adjudicateLossPlies ) {
- int score = pvInfoList[ forwardMostMove - count - 1 ].score;
-
- if( count & 1 ) {
- score = -score; /* Flip score for winning side */
->>>>>>> master
- }
-
- if( score > adjudicateLossThreshold ) {
- break;
- }
-
- count++;
- }
-
- if( count >= adjudicateLossPlies ) {
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
-
GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins,
"Xboard adjudication",
GE_XBOARD );
SetGameInfo();
}
-
void
EditPositionEvent()
{
SetGameInfo();
if (currentMove > 0)
CopyBoard(boards[0], boards[currentMove]);
-
+ { int i, r, f; // [HGM] editrights: take note of existing rights
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) rightsBoard[r][f] = 0;
+ for(i=0; i<nrCastlingRights; i++) {
+ if(boards[0][CASTLING][i] != NoRights)
+ rightsBoard [castlingRank[i]] [boards[0][CASTLING][i]] = 1 + (i == 2 || i == 5);
+ }
+ }
+
blackPlaysFirst = !WhiteOnMove(currentMove);
ResetClocks();
currentMove = forwardMostMove = backwardMostMove = 0;
startedFromSetupPosition = TRUE;
InitChessProgram(&first, FALSE);
if(fakeRights) { // [HGM] suppress this if we just pasted a FEN.
+ int i, r, f, kf, err;
+ for(i=0; i<nrCastlingRights; i++) boards[0][CASTLING][i] = NoRights;
+ kf = NoRights; err = 0;
+ for(f=BOARD_RGHT-1; f>=0; f--)
+ if(rightsBoard[0][f] == 2) { if(kf != NoRights) err=10; boards[0][CASTLING][2] = kf = f; }
+ if(kf == NoRights) kf = 4;
+ for(f=BOARD_RGHT-1; f>=0; f--)
+ if(rightsBoard[0][f] == 1) { err++; boards[0][CASTLING][f<kf] = f; }
+ kf = NoRights; err = 0;
+ for(f=BOARD_RGHT-1; f>=0; f--)
+ if(rightsBoard[BOARD_HEIGHT-1][f] == 2) { if(kf != NoRights) err=10; boards[0][CASTLING][5] = kf = f; }
+ if(kf == NoRights) kf = 4;
+ for(f=BOARD_RGHT-1; f>=0; f--)
+ if(rightsBoard[BOARD_HEIGHT-1][f] == 1) { err++; boards[0][CASTLING][3+(f<kf)] = f; }
+ if(err + 2 > nrCastlingRights) DisplayError("unclear castling rights", 0);
+
boards[0][EP_STATUS] = EP_NONE;
+#if 0
boards[0][CASTLING][2] = boards[0][CASTLING][5] = BOARD_WIDTH>>1;
if(boards[0][0][BOARD_WIDTH>>1] == king) {
boards[0][CASTLING][1] = boards[0][0][BOARD_LEFT] == WhiteRook ? 0 : NoRights;
boards[0][CASTLING][4] = boards[0][BOARD_HEIGHT-1][BOARD_LEFT] == BlackRook ? 0 : NoRights;
boards[0][CASTLING][3] = boards[0][BOARD_HEIGHT-1][BOARD_RGHT-1] == BlackRook ? BOARD_RGHT-1 : NoRights;
} else boards[0][CASTLING][5] = NoRights;
+#endif
}
SendToProgram("force\n", &first);
if (blackPlaysFirst) {
{
char buf[MSG_SIZ];
ChessSquare piece = boards[0][y][x];
+ int rights = 0; // [HGM] editrights: most new pieces get no castling rights
if (gameMode != EditPosition && gameMode != IcsExamining) return;
}
} else {
boards[0][y][x] = p;
+ rightsBoard[y][x] = 0; // [HGM] editrights: clear all castling rights
}
}
}
SetBlackToPlayEvent();
break;
+ case NoRights:
+ rightsBoard[y][x] = 0;
+ break;
+
+ case GrantRights:
+ { ChessSquare p = boards[0][y][x];
+ rightsBoard[y][x] = 1;
+ if(p == WhiteKing || p == WhiteUnicorn || p == BlackKing || p == BlackUnicorn)
+ rightsBoard[y][x] = 2;
+ }
+ break;
+
case EmptySquare:
if (gameMode == IcsExamining) {
if (x < BOARD_LEFT || x >= BOARD_RGHT) break; // [HGM] holdings
selection = (ChessSquare)((int)selection - (int)WhiteQueen + (int)WhiteFerz);
goto defaultlabel;
+ case WhiteRook: // [HGM] editrights: corner Rooks get castling rights by default
+ if(y == 0 && (x == BOARD_LEFT || x == BOARD_RGHT-1)) rights = 1;
+ goto defaultlabel;
+
+ case BlackRook:
+ if(y == BOARD_HEIGHT-1 && (x == BOARD_LEFT || x == BOARD_RGHT-1)) rights = 1;
+ goto defaultlabel;
+
case WhiteKing:
case BlackKing:
if(gameInfo.variant == VariantXiangqi)
selection = (ChessSquare)((int)selection - (int)WhiteKing + (int)WhiteWazir);
if(gameInfo.variant == VariantKnightmate)
selection = (ChessSquare)((int)selection - (int)WhiteKing + (int)WhiteUnicorn);
+ case WhiteUnicorn:
+ case BlackUnicorn:
+ if(y == (selection <= WhiteKing ? 0 : BOARD_HEIGHT-1) && (x == BOARD_WIDTH>>1))
+ rights = 2; // [HGM] editrights: King on right-center file gets rights
default:
defaultlabel:
if (gameMode == IcsExamining) {
}
} else
boards[0][y][x] = selection;
+ rightsBoard[y][x] = rights; // [HGM] editrights: set default rights of created piece
DrawPosition(TRUE, boards[0]);
}
break;