X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=1c25faa84bb50908572645cdfa93715473ac6288;hb=c551a728b8fa7649b043fffb32b7f1d11c67b38a;hp=742bf03ccf2aa17a34d8ebb0713de5e984af610d;hpb=5091c2a8e906c2358ce5aad116b8ce3f13a61a14;p=xboard.git diff --git a/backend.c b/backend.c index 742bf03..1c25faa 100644 --- a/backend.c +++ b/backend.c @@ -234,6 +234,7 @@ char *ProbeBook P((int moveNr, char *book)); // [HGM] book: returns a book move char *SendMoveToBookUser P((int nr, ChessProgramState *cps, int initial)); // [HGM] book void ics_update_width P((int new_width)); extern char installDir[MSG_SIZ]; +VariantClass startVariant; /* [HGM] nicks: initial variant */ extern int tinyLayout, smallLayout; ChessProgramStats programStats; @@ -637,6 +638,7 @@ InitBackEnd1() int matched, min, sec; ShowThinkingEvent(); // [HGM] thinking: make sure post/nopost state is set according to options + startVariant = StringToVariant(appData.variant); // [HGM] nicks: remember original variant GetTimeMark(&programStartTime); srandom((programStartTime.ms + 1000*programStartTime.sec)*0x1001001); // [HGM] book: makes sure random is unpredictabe to msec level @@ -2836,18 +2838,9 @@ read_from_ics(isr, closure, data, count, error) /* [DM] Backup address for color zippy lines */ backup = i; #if ZIPPY - #ifdef WIN32 if (loggedOn == TRUE) if (ZippyControl(buf, &backup) || ZippyConverse(buf, &backup) || (appData.zippyPlay && ZippyMatch(buf, &backup))); - #else - if (ZippyControl(buf, &i) || - ZippyConverse(buf, &i) || - (appData.zippyPlay && ZippyMatch(buf, &i))) { - loggedOn = TRUE; - if (!appData.colorize) continue; - } - #endif #endif } // [DM] 'else { ' deleted if ( @@ -5260,7 +5253,10 @@ InitPosition(redraw) for(i=0; i 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,61 +6669,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; } @@ -6728,8 +6746,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 @@ -6760,11 +6778,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 - { /* 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; @@ -6782,11 +6798,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 */ @@ -6897,6 +6913,17 @@ Adjudicate(ChessProgramState *cps) if( count == backwardMostMove ) count -= initialRulePlies; count = forwardMostMove - count; + if(gameInfo.variant == VariantXiangqi && ( count >= 100 || count >= 2*appData.ruleMoves ) ) { + // adjust reversible move counter for checks in Xiangqi + int i = forwardMostMove - count, inCheck = 0, lastCheck; + if(i < backwardMostMove) i = backwardMostMove; + while(i <= forwardMostMove) { + lastCheck = inCheck; // check evasion does not count + inCheck = (MateTest(boards[i], PosFlags(i)) == MT_CHECK); + if(inCheck || lastCheck) count--; // check does not count + i++; + } + } if( count >= 100) boards[forwardMostMove][EP_STATUS] = EP_RULE_DRAW; /* this is used to judge if draw claims are legal */ @@ -8957,7 +8984,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; @@ -9299,7 +9326,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) && @@ -9308,6 +9335,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). @@ -10172,6 +10200,7 @@ LoadGame(f, gameNumber, title, useList) /* [HGM] PGNvariant: automatically switch to variant given in PGN tag */ if(gameInfo.variant != oldVariant) { startedFromPositionFile = FALSE; /* [HGM] loadPos: variant switch likely makes position invalid */ + ResetFrontEnd(); // [HGM] might need other bitmaps. Cannot use Reset() because it clears gameInfo :-( InitPosition(TRUE); oldVariant = gameInfo.variant; if (appData.debugMode) @@ -13787,7 +13816,6 @@ ParseFeatures(args, cps) } continue; } - if (BoolFeature(&p, "smp", &cps->maxCores, cps)) continue; /* End of additions by HGM */ /* unknown feature: complain and skip */ @@ -13851,17 +13879,17 @@ PonderNextMoveEvent(newState) } void -NewSettingEvent(option, command, value) +NewSettingEvent(option, feature, command, value) char *command; - int option, value; + int option, value, *feature; { char buf[MSG_SIZ]; if (gameMode == EditPosition) EditPositionDone(TRUE); sprintf(buf, "%s%s %d\n", (option ? "option ": ""), command, value); - SendToProgram(buf, &first); + if(feature == NULL || *feature) SendToProgram(buf, &first); if (gameMode == TwoMachinesPlay) { - SendToProgram(buf, &second); + if(feature == NULL || feature[(int*)&second - (int*)&first]) SendToProgram(buf, &second); } }