#ifdef ENABLE_NLS
# define _(s) gettext (s)
# define N_(s) gettext_noop (s)
+# define T_(s) gettext(s)
#else
-# define _(s) (s)
-# define N_(s) s
+# ifdef WIN32
+# define _(s) T_(s)
+# define N_(s) s
+# else
+# define _(s) (s)
+# define N_(s) s
+# define T_(s) s
+# endif
#endif
/* [AS] Adjudication threshold */
adjudicateLossThreshold = appData.adjudicateLossThreshold;
- first.which = "first";
- second.which = "second";
+ first.which = _("first");
+ second.which = _("second");
first.maybeThinking = second.maybeThinking = FALSE;
first.pr = second.pr = NoProc;
first.isr = second.isr = NULL;
int
DrawSeekGraph()
{
- if(!seekGraphUp) return FALSE;
int i;
+ if(!seekGraphUp) return FALSE;
h = BOARD_HEIGHT * (squareSize + lineGap) + lineGap;
w = BOARD_WIDTH * (squareSize + lineGap) + lineGap;
/* POP Fabien */
sprintf(user_move, "o-o-o\n");
break;
+ case WhiteNonPromotion:
+ case BlackNonPromotion:
+ sprintf(user_move, "%c%c%c%c=\n", AAA + fromX, ONE + fromY, AAA + toX, ONE + toY);
+ break;
case WhitePromotionQueen:
case BlackPromotionQueen:
case WhitePromotionRook:
case BlackPromotionKnight:
case WhitePromotionKing:
case BlackPromotionKing:
+ case WhiteNonPromotion:
+ case BlackNonPromotion:
case NormalMove:
case WhiteCapturesEnPassant:
case BlackCapturesEnPassant:
for(p=WhitePawn; p<=EmptySquare; p++) pCnt[p] = 0;
for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
p = board[r][f];
+ pCnt[p]++;
if(p == WhitePawn && r == BOARD_HEIGHT-1) (*wStale)++; else
- if(p == BlackPawn && r == 0) (*bStale)++; else pCnt[p]++; // count last-Rank Pawns (XQ) separately
+ if(p == BlackPawn && r == 0) (*bStale)++; // count last-Rank Pawns (XQ) separately
if(p <= WhiteKing) (*nW)++; else if(p <= BlackKing) (*nB)++;
if(p == WhiteBishop || p == WhiteFerz || p == WhiteAlfil ||
p == BlackBishop || p == BlackFerz || p == BlackAlfil )
}
int
+SufficientDefence(int pCnt[], int side, int nMine, int nHis)
+{
+ int myPawns = pCnt[WhitePawn+side]; // my total Pawn count;
+ int majorDefense = pCnt[BlackRook-side] + pCnt[BlackCannon-side] + pCnt[BlackKnight-side];
+
+ nMine -= pCnt[WhiteFerz+side] + pCnt[WhiteAlfil+side]; // discount defenders
+ if(nMine - myPawns > 2) return FALSE; // no trivial draws with more than 1 major
+ if(myPawns == 2 && nMine == 3) // KPP
+ return majorDefense || pCnt[BlackFerz-side] + pCnt[BlackAlfil-side] >= 3;
+ if(myPawns == 1 && nMine == 2) // KP
+ return majorDefense || pCnt[BlackFerz-side] + pCnt[BlackAlfil-side] + pCnt[BlackPawn-side] >= 1;
+ if(myPawns == 1 && nMine == 3 && pCnt[WhiteKnight+side]) // KHP
+ return majorDefense || pCnt[BlackFerz-side] + pCnt[BlackAlfil-side]*2 >= 5;
+ if(myPawns) return FALSE;
+ if(pCnt[WhiteRook+side])
+ return pCnt[BlackRook-side] ||
+ pCnt[BlackCannon-side] && (pCnt[BlackFerz-side] >= 2 || pCnt[BlackAlfil-side] >= 2) ||
+ pCnt[BlackKnight-side] && pCnt[BlackFerz-side] + pCnt[BlackAlfil-side] > 2 ||
+ pCnt[BlackFerz-side] + pCnt[BlackAlfil-side] >= 4;
+ if(pCnt[WhiteCannon+side]) {
+ if(pCnt[WhiteFerz+side] + myPawns == 0) return TRUE; // Cannon needs platform
+ return majorDefense || pCnt[BlackAlfil-side] >= 2;
+ }
+ if(pCnt[WhiteKnight+side])
+ return majorDefense || pCnt[BlackFerz-side] >= 2 || pCnt[BlackAlfil-side] + pCnt[BlackPawn-side] >= 1;
+ return FALSE;
+}
+
+int
MatingPotential(int pCnt[], int side, int nMine, int nHis, int stale, int bisColor)
{
VariantClass v = gameInfo.variant;
}
/* Then some trivial draws (only adjudicate, cannot be claimed) */
- if(nrW + nrB == 4 &&
+ if(gameInfo.variant == VariantXiangqi ?
+ SufficientDefence(nr, WhitePawn, nrW, nrB) && SufficientDefence(nr, BlackPawn, nrB, nrW)
+ : 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 */
if(engineOpponent) {
case BlackPromotionKnight:
case WhitePromotionKing:
case BlackPromotionKing:
+ case WhiteNonPromotion:
+ case BlackNonPromotion:
case NormalMove:
case WhiteCapturesEnPassant:
case BlackCapturesEnPassant:
/* [HGM] compute & store e.p. status and castling rights for new position */
/* we can always do that 'in place', now pointers to these rights are passed to ApplyMove */
- { int i;
if(gameInfo.variant == VariantBerolina) berolina = EP_BEROLIN_A;
oldEP = (signed char)board[EP_STATUS];
if( board[toY][toX] != EmptySquare )
board[EP_STATUS] = EP_CAPTURE;
+ /* [HGM] In Shatranj and Courier all promotions are to Ferz */
+ if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier || gameInfo.variant == VariantMakruk)
+ && promoChar != 0) promoChar = PieceToChar(WhiteFerz);
+
+ if (fromY == DROP_RANK) {
+ /* must be first */
+ piece = board[toY][toX] = (ChessSquare) fromX;
+ } else {
+ int i;
+
if( board[fromY][fromX] == WhitePawn ) {
if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers
board[EP_STATUS] = EP_PAWN_MOVE;
) board[CASTLING][i] = NoRights; // revoke for moved or captured piece
}
- }
+ if (fromX == toX && fromY == toY) return;
- /* [HGM] In Shatranj and Courier all promotions are to Ferz */
- if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier || gameInfo.variant == VariantMakruk)
- && promoChar != 0) promoChar = PieceToChar(WhiteFerz);
-
- if (fromX == toX && fromY == toY) return;
-
- if (fromY == DROP_RANK) {
- /* must be first */
- piece = board[toY][toX] = (ChessSquare) fromX;
- } else {
piece = board[fromY][fromX]; /* [HGM] remember, for Shogi promotion */
king = piece < (int) BlackPawn ? WhiteKing : BlackKing; /* [HGM] Knightmate simplify testing for castling */
if(gameInfo.variant == VariantKnightmate)
endingGame = 0; /* [HGM] crash */
return;
} else {
- char buf[MSG_SIZ];
gameMode = nextGameMode;
sprintf(buf, _("Match %s vs. %s: final score %d-%d-%d"),
first.tidy, second.tidy,
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.
+ if(popupRequested) { // [HGM] crash: this calls GameEnds recursively through ExitEvent! Make it a harmless tail recursion.
+ if(matchMode == TRUE) DisplayFatalError(buf, 0, 0); else {
+ matchMode = FALSE; appData.matchGames = matchGame = 0;
+ DisplayNote(buf);
+ }
+ }
}
/* Assumes program was just initialized (initString sent).
case BlackPromotionKnight:
case WhitePromotionKing:
case BlackPromotionKing:
+ case WhiteNonPromotion:
+ case BlackNonPromotion:
case NormalMove:
case WhiteKingSideCastle:
case WhiteQueenSideCastle:
sprintf(res, " %s", PGNResult(gameInfo.result));
} else {
sprintf(res, " {%s} %s",
- gameInfo.resultDetails, PGNResult(gameInfo.result));
+ T_(gameInfo.resultDetails), PGNResult(gameInfo.result));
}
} else {
res[0] = NULLCHAR;
char *fen;
{
int i, j;
- char *p;
+ char *p, c;
int emptycount;
ChessSquare piece;
while(*p == ' ') p++;
/* Active color */
- switch (*p++) {
+ c = *p++;
+ if(appData.colorNickNames) {
+ if( c == appData.colorNickNames[0] ) c = 'w'; else
+ if( c == appData.colorNickNames[1] ) c = 'b';
+ }
+ switch (c) {
case 'w':
*blackPlaysFirst = FALSE;
break;