X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=3fa521b6988ac25ac20eae0bc37ae9d0a69dd69c;hb=66c168b845b3091bf8a616c3f23606efc36c6bf6;hp=4d23241797751ba1ec4575a83aa3f2f3b1677f73;hpb=4042b38821940cd48e9f3d10b5208da7b6288dfd;p=xboard.git diff --git a/backend.c b/backend.c index 4d23241..3fa521b 100644 --- a/backend.c +++ b/backend.c @@ -5,7 +5,7 @@ * 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 * @@ -242,6 +242,7 @@ int endPV = -1; 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 */ @@ -5791,6 +5792,7 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn) 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]; @@ -5807,6 +5809,7 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn) } } else boards[0][fromY][fromX] = EmptySquare; + rightsBoard[fromY][fromX] = rightsBoard[toY][toX] = 0; return AmbiguousMove; } return ImpossibleMove; @@ -6096,6 +6099,68 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar) 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; iBOARD_RGHT-BOARD_LEFT) { w = BOARD_RGHT - BOARD_LEFT; h = (j+w-1)/w; } + for(i=0; i 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; } @@ -6323,18 +6399,18 @@ void LeftClick(ClickType clickType, int xPix, int yPix) 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(); @@ -6348,7 +6424,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix) } } -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; @@ -6360,6 +6436,16 @@ int RightClick(ClickType action, int x, int y, int *fromX, int *fromY) 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) { @@ -6398,15 +6484,14 @@ int RightClick(ClickType action, int x, int y, int *fromX, int *fromY) 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; } @@ -6972,7 +7057,6 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h if (gameMode == TwoMachinesPlay) { GameEnds(machineWhite ? BlackWins : WhiteWins, buf1, GE_XBOARD); -<<<<<<< HEAD } return; } @@ -7025,39 +7109,11 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h 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) */ @@ -7081,381 +7137,6 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats. 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; iother); // 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 ); @@ -12282,7 +11963,6 @@ EditGameEvent() SetGameInfo(); } - void EditPositionEvent() { @@ -12299,7 +11979,14 @@ 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=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=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 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; @@ -12341,6 +12045,7 @@ EditPositionDone(Boolean fakeRights) 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) { @@ -12438,6 +12143,7 @@ EditPositionMenuEvent(selection, x, y) { 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; @@ -12461,6 +12167,7 @@ EditPositionMenuEvent(selection, x, y) } } else { boards[0][y][x] = p; + rightsBoard[y][x] = 0; // [HGM] editrights: clear all castling rights } } } @@ -12478,6 +12185,18 @@ EditPositionMenuEvent(selection, x, y) 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 @@ -12524,12 +12243,24 @@ EditPositionMenuEvent(selection, x, y) 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) { @@ -12554,6 +12285,7 @@ EditPositionMenuEvent(selection, x, y) } } else boards[0][y][x] = selection; + rightsBoard[y][x] = rights; // [HGM] editrights: set default rights of created piece DrawPosition(TRUE, boards[0]); } break;