X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=99aceae437f82668867df245f8072c8ee16932a4;hb=fd3bdfd7587b74332180fc829650ce4681890979;hp=bb52007006a024234dcdf8601b640ee48a7887ca;hpb=75c82871211daf66c50935b39427e78922d20a5e;p=xboard.git diff --git a/backend.c b/backend.c index bb52007..99aceae 100644 --- a/backend.c +++ b/backend.c @@ -6591,6 +6591,73 @@ void SendProgramStatsToFrontend( ChessProgramState * cps, ChessProgramStats * cp SetProgramStats( &stats ); } +void +Count(Board board, int pCnt[], int *nW, int *nB, int *wStale, int *bStale, int *bishopColor) +{ // count all piece types + int p, f, r; + *nB = *nW = *wStale = *bStale = *bishopColor = 0; + for(p=WhitePawn; p<=EmptySquare; p++) pCnt[p] = 0; + for(r=0; r 1; // can win through checking / exploding King + + if(v == VariantXiangqi) { + int majors = 5*pCnt[BlackKnight-side] + 7*pCnt[BlackCannon-side] + 7*pCnt[BlackRook-side]; + + nMine -= pCnt[WhiteFerz+side] + pCnt[WhiteAlfil+side] + stale; // discount defensive pieces and back-rank Pawns + if(nMine + stale == 1) return (pCnt[BlackFerz-side] > 1 && pCnt[BlackKnight-side] > 0); // bare K can stalemate KHAA (!) + if(nMine > 2) return TRUE; // if we don't have P, H or R, we must have CC + if(nMine == 2 && pCnt[WhiteCannon+side] == 0) return TRUE; // We have at least one P, H or R + // if we get here, we must have KC... or KP..., possibly with additional A, E or last-rank P + if(stale) // we have at least one last-rank P plus perhaps C + return majors // KPKX + || pCnt[BlackFerz-side] && pCnt[BlackFerz-side] + pCnt[WhiteCannon+side] + stale > 2; // KPKAA, KPPKA and KCPKA + else // KCA*E* + return pCnt[WhiteFerz+side] // KCAK + || pCnt[WhiteAlfil+side] && pCnt[BlackRook-side] + pCnt[BlackCannon-side] + pCnt[BlackFerz-side] // KCEKA, KCEKX (X!=H) + || majors + (12*pCnt[BlackFerz-side] | 6*pCnt[BlackAlfil-side]) > 16; // KCKAA, KCKAX, KCKEEX, KCKEXX (XX!=HH), KCKXXX + // TO DO: cases wih an unpromoted f-Pawn acting as platform for an opponent Cannon + + } else if(pCnt[WhiteKing] == 1 && pCnt[BlackKing] == 1) { // other variants with orthodox Kings + int nBishops = pCnt[WhiteBishop+side] + pCnt[WhiteFerz+side]; + + if(nMine == 1) return FALSE; // bare King + if(nBishops && bisColor == 3) return TRUE; // There must be a second B/A/F, which can either block (his) or attack (mine) the escape square + nMine += (nBishops > 0) - nBishops; // By now all Bishops (and Ferz) on like-colored squares, so count as one + if(nMine > 2 && nMine != pCnt[WhiteAlfil+side] + 1) return TRUE; // At least two pieces, not all Alfils + // by now we have King + 1 piece (or multiple Bishops on the same color) + if(pCnt[WhiteKnight+side]) + return (pCnt[BlackKnight-side] + pCnt[BlackBishop-side] + pCnt[BlackMan-side] + + pCnt[BlackWazir-side] + pCnt[BlackSilver-side] + bisColor // KNKN, KNKB, KNKF, KNKE, KNKW, KNKM, KNKS + || nHis > 3); // be sure to cover suffocation mates in corner (e.g. KNKQCA) + if(nBishops) + return (pCnt[BlackKnight-side]); // KBKN, KFKN + if(pCnt[WhiteAlfil+side]) + return (nHis > 2); // Alfils can in general not reach a corner square, but there might be edge (suffocation) mates + if(pCnt[WhiteWazir+side]) + return (pCnt[BlackKnight-side] + pCnt[BlackWazir-side] + pCnt[BlackAlfil-side]); // KWKN, KWKW, KWKE + } + + return TRUE; +} + int Adjudicate(ChessProgramState *cps) { // [HGM] some adjudications useful with buggy engines @@ -6606,63 +6673,16 @@ Adjudicate(ChessProgramState *cps) 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; + int nrW, nrB, bishopColor, staleW, staleB, nr[EmptySquare+1], i; static int moveCount = 6; ChessMove result; char *reason = NULL; /* Count what is on board. */ - for(i=0; i 1 ? WhiteWins : NrPieces - NrW > 1 ? BlackWins : GameIsDrawn, + GameEnds( nrW > 1 ? WhiteWins : nrB > 1 ? BlackWins : GameIsDrawn, "Xboard adjudication: Bare king", GE_XBOARD ); return 1; } @@ -6730,8 +6750,8 @@ Adjudicate(ChessProgramState *cps) 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) ? + boards[forwardMostMove][EP_STATUS] = nrW == nrB ? EP_STALEMATE : + ((nrW < nrB) != 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 @@ -6762,14 +6782,9 @@ Adjudicate(ChessProgramState *cps) } /* 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 - || gameInfo.variant == VariantXiangqi && - (NrPieces == 3 && (NrWQ==1 && NrWB==0 && NrBB<2 || NrBQ==1 && NrBB==0 && NrWB<2) || - NrPieces == 4 && NrWQ==1 && NrBQ==1 && NrWB==0 && NrBB==0)) - { /* KBK, KNK, KK of KBKB with like Bishops */ + if(!MatingPotential(nr, WhitePawn, nrW, nrB, staleW, bishopColor) && + !MatingPotential(nr, BlackPawn, nrB, nrW, staleB, bishopColor)) + { /* includes KBK, KNK, KK of KBKB with like Bishops */ /* always flag draws, for judging claims */ boards[forwardMostMove][EP_STATUS] = EP_INSUF_DRAW; @@ -6787,11 +6802,11 @@ Adjudicate(ChessProgramState *cps) } /* 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(nrW + nrB == 4 && + ( nr[WhiteRook] == 1 && nr[BlackRook] == 1 /* KRKR */ + || nr[WhiteQueen] && nr[BlackQueen]==1 /* KQKQ */ + || nr[WhiteKnight]==2 || nr[BlackKnight]==2 /* KNNK */ + || nr[WhiteKnight]+nr[WhiteBishop] == 1 && nr[BlackKnight]+nr[BlackBishop] == 1 /* KBKN, KBKB, KNKN */ ) ) { if(--moveCount < 0 && appData.trivialDraws && canAdjudicate) { /* if the first 3 moves do not show a tactical win, declare draw */ @@ -8973,7 +8988,7 @@ GameEnds(result, resultDetails, whosays) { GameMode nextGameMode; int isIcsGame; - char buf[MSG_SIZ]; + char buf[MSG_SIZ], popupRequested = 0; if(endingGame) return; /* [HGM] crash: forbid recursion */ endingGame = 1; @@ -9315,7 +9330,7 @@ GameEnds(result, resultDetails, whosays) first.tidy, second.tidy, first.matchWins, second.matchWins, appData.matchGames - (first.matchWins + second.matchWins)); - DisplayFatalError(buf, 0, 0); + popupRequested++; // [HGM] crash: postpone to after resetting endingGame } } if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile) && @@ -9324,6 +9339,7 @@ GameEnds(result, resultDetails, whosays) gameMode = nextGameMode; ModeHighlight(); endingGame = 0; /* [HGM] crash */ + if(popupRequested) DisplayFatalError(buf, 0, 0); // [HGM] crash: this call GameEnds recursively through ExitEvent! Make it a harmless tail recursion. } /* Assumes program was just initialized (initString sent).