X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=a3a06b79d0467673ca042bad806e02685b11e3d9;hb=9d270b7479328210b4f4f47ad3c769c60e4ce200;hp=6547358de7c82572d4dcd8f625bdf3d2294ea72d;hpb=b9cdd7422ad1037d7376bce4f8f2db2669396e83;p=xboard.git diff --git a/backend.c b/backend.c index 6547358..a3a06b7 100644 --- a/backend.c +++ b/backend.c @@ -449,6 +449,7 @@ int adjudicateLossPlies = 6; char white_holding[64], black_holding[64]; TimeMark lastNodeCountTime; long lastNodeCount=0; +int shiftKey; // [HGM] set by mouse handler int have_sent_ICS_logon = 0; int sending_ICS_login = 0; @@ -1083,7 +1084,6 @@ ParseTimeControl(tc, ti, mps) long tc2; char buf[MSG_SIZ], buf2[MSG_SIZ], *mytc = tc; int min, sec=0; - int len; if(ti >= 0 && !strchr(tc, '+') && !strchr(tc, '/') ) mps = 0; if(!strchr(tc, '+') && !strchr(tc, '/') && sscanf(tc, "%d:%d", &min, &sec) >= 1) @@ -4008,7 +4008,7 @@ ParseBoard12(string) } if (gameInfo.boardHeight != ranks || gameInfo.boardWidth != files || - weird && (int)gameInfo.variant <= (int)VariantShogi) { + weird && (int)gameInfo.variant < (int)VariantShogi) { /* [HGM] We seem to have switched variant unexpectedly * Try to guess new variant from board size */ @@ -4337,6 +4337,8 @@ ParseBoard12(string) // So we parse the long-algebraic move string in stead of the SAN move int valid; char buf[MSG_SIZ], *prom; + if(gameInfo.variant == VariantShogi && !strchr(move_str, '=') && !strchr(move_str, '@')) + strcat(move_str, "="); // if ICS does not say 'promote' on non-drop, we defer. // str looks something like "Q/a1-a2"; kill the slash if(str[1] == '/') snprintf(buf, MSG_SIZ,"%c%s", str[0], str+2); @@ -4375,8 +4377,24 @@ ParseBoard12(string) strcat(parseList[moveNum - 1], " "); strcat(parseList[moveNum - 1], elapsed_time); /* currentMoveString is set as a side-effect of ParseOneMove */ + if(gameInfo.variant == VariantShogi && currentMoveString[4]) currentMoveString[4] = '^'; safeStrCpy(moveList[moveNum - 1], currentMoveString, sizeof(moveList[moveNum - 1])/sizeof(moveList[moveNum - 1][0])); strcat(moveList[moveNum - 1], "\n"); + + if(gameInfo.holdingsWidth && !appData.disguise) // inherit info that ICS does not give from previous board + for(k=0; k= BlackPawn && old < BlackCannon) + boards[moveNum][k][j] = PROMOTED old; // choose correct type of Gold in promotion + else boards[moveNum][k][j] = old; // preserve type of Gold + } else if((old == WhitePawn || old == BlackPawn) && new != EmptySquare) // Pawn promotions (but not e.p.capture!) + boards[moveNum][k][j] = PROMOTED new; // use non-primordial representation of chosen piece + } } else { /* Move from ICS was illegal!? Punt. */ if (appData.debugMode) { @@ -4666,7 +4684,7 @@ SendMoveToICS(moveType, fromX, fromY, toX, toY, promoChar) break; case WhiteNonPromotion: case BlackNonPromotion: - sprintf(user_move, "%c%c%c%c=\n", AAA + fromX, ONE + fromY, AAA + toX, ONE + toY); + sprintf(user_move, "%c%c%c%c==\n", AAA + fromX, ONE + fromY, AAA + toX, ONE + toY); break; case WhitePromotion: case BlackPromotion: @@ -4685,14 +4703,16 @@ SendMoveToICS(moveType, fromX, fromY, toX, toY, promoChar) break; case WhiteDrop: case BlackDrop: + drop: snprintf(user_move, MSG_SIZ, "%c@%c%c\n", - ToUpper(PieceToChar((ChessSquare) fromX)), - AAA + toX, ONE + toY); + ToUpper(PieceToChar((ChessSquare) fromX)), + AAA + toX, ONE + toY); break; + case IllegalMove: /* could be a variant we don't quite understand */ + if(fromY == DROP_RANK) goto drop; // We need 'IllegalDrop' move type? case NormalMove: case WhiteCapturesEnPassant: case BlackCapturesEnPassant: - case IllegalMove: /* could be a variant we don't quite understand */ snprintf(user_move, MSG_SIZ,"%c%c%c%c\n", AAA + fromX, ONE + fromY, AAA + toX, ONE + toY); break; @@ -4864,9 +4884,6 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar) int *fromX, *fromY, *toX, *toY; char *promoChar; { - if (appData.debugMode) { - fprintf(debugFP, "move to parse: %s\n", move); - } *moveType = yylexstr(moveNum, move, yy_textstr, sizeof yy_textstr); switch (*moveType) { @@ -5701,6 +5718,11 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice) *promoChoice = PieceToChar(BlackFerz); // no choice return FALSE; } + // no sense asking what we must promote to if it is going to explode... + if(gameInfo.variant == VariantAtomic && boards[currentMove][toY][toX] != EmptySquare) { + *promoChoice = PieceToChar(BlackQueen); // Queen as good as any + return FALSE; + } if(autoQueen) { // predetermined if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantLosers) *promoChoice = PieceToChar(BlackKing); // in Suicide Q is the last thing we want @@ -5713,7 +5735,7 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice) gameMode == IcsPlayingBlack && WhiteOnMove(currentMove); if(appData.testLegality && !premove) { moveType = LegalityTest(boards[currentMove], PosFlags(currentMove), - fromY, fromX, toY, toX, NULLCHAR); + fromY, fromX, toY, toX, gameInfo.variant == VariantShogi ? '+' : NULLCHAR); if(moveType != WhitePromotion && moveType != BlackPromotion) return FALSE; } @@ -5855,6 +5877,8 @@ OnlyMove(int *x, int *y, Boolean captures) { case IcsPlayingBlack: if(WhiteOnMove(currentMove)) return FALSE; break; + case EditGame: + break; default: return FALSE; } @@ -6141,7 +6165,8 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar) the previous line in Analysis Mode */ if ((gameMode == AnalyzeMode || gameMode == EditGame) && currentMove < forwardMostMove) { - PushTail(currentMove, forwardMostMove); // [HGM] vari: save tail of game + if(appData.variations && shiftKey) PushTail(currentMove, forwardMostMove); // [HGM] vari: save tail of game + else forwardMostMove = currentMove; } /* If we need the chess program but it's dead, restart it */ @@ -6291,6 +6316,20 @@ MarkTargetSquares(int clear) DrawPosition(TRUE, NULL); } +int +Explode(Board board, int fromX, int fromY, int toX, int toY) +{ + if(gameInfo.variant == VariantAtomic && + (board[toY][toX] != EmptySquare || // capture? + toX != fromX && (board[fromY][fromX] == WhitePawn || // e.p. ? + board[fromY][fromX] == BlackPawn ) + )) { + AnimateAtomicCapture(board, fromX, fromY, toX, toY); + return TRUE; + } + return FALSE; +} + void LeftClick(ClickType clickType, int xPix, int yPix) { int x, y; @@ -6501,9 +6540,13 @@ void LeftClick(ClickType clickType, int xPix, int yPix) } PromotionPopUp(); } else { + int oldMove = currentMove; UserMoveEvent(fromX, fromY, toX, toY, promoChoice); if (!appData.highlightLastMove || gotPremove) ClearHighlights(); if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); + if(saveAnimate && !appData.animate && currentMove != oldMove && // drag-move was performed + Explode(boards[currentMove-1], fromX, fromY, toX, toY)) + DrawPosition(TRUE, boards[currentMove]); fromX = fromY = -1; } appData.animate = saveAnimate; @@ -8601,8 +8644,8 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) if(promoChar == '+') { /* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite orinary Pawn promotion) */ board[toY][toX] = (ChessSquare) (PROMOTED piece); - } else if(!appData.testLegality) { // without legality testing, unconditionally believe promoChar - board[toY][toX] = CharToPiece(promoChar); + } else if(!appData.testLegality && promoChar != NULLCHAR && promoChar != '=') { // without legality testing, unconditionally believe promoChar + board[toY][toX] = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar)); } if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) && promoChar != NULLCHAR && gameInfo.holdingsSize) { @@ -13285,7 +13328,7 @@ if(appData.debugMode) fprintf(debugFP, "Append: in='%s' %d\n", text, addBraces); } else { commentList[index] = (char *) malloc(len + 6); // perhaps wastes 4... if(addBraces) - safeStrCpy(commentList[index], "{\n", sizeof(commentList[index])/sizeof(commentList[index][0])); + safeStrCpy(commentList[index], "{\n", 3); else commentList[index][0] = NULLCHAR; strcat(commentList[index], text); strcat(commentList[index], "\n"); @@ -13554,10 +13597,10 @@ SendTimeControl(cps, mps, tc, inc, sd, st) /* Note old gnuchess bug -- minutes:seconds used to not work. Fixed in later versions, but still avoid :seconds when seconds is 0. */ - snprintf(buf, MSG_SIZ, "level %d %ld %g\n", mps, tc/60000, inc/1000); + snprintf(buf, MSG_SIZ, "level %d %ld %g\n", mps, tc/60000, inc/1000.); } else { snprintf(buf, MSG_SIZ, "level %d %ld:%02d %g\n", mps, tc/60000, - seconds, inc/1000); + seconds, inc/1000.); } } SendToProgram(buf, cps); @@ -14313,7 +14356,7 @@ DecrementClocks() if (WhiteOnMove(forwardMostMove)) { if(whiteNPS >= 0) lastTickLength = 0; timeRemaining = whiteTimeRemaining -= lastTickLength; - if(timeRemaining < 0) { + if(timeRemaining < 0 && !appData.icsActive) { GetTimeQuota((forwardMostMove-whiteStartMove-1)/2, 0, whiteTC); // sets suddenDeath & nextSession; if(suddenDeath) { // [HGM] if we run out of a non-last incremental session, go to the next whiteStartMove = forwardMostMove; whiteTC = nextSession; @@ -14325,7 +14368,7 @@ DecrementClocks() } else { if(blackNPS >= 0) lastTickLength = 0; timeRemaining = blackTimeRemaining -= lastTickLength; - if(timeRemaining < 0) { // [HGM] if we run out of a non-last incremental session, go to the next + if(timeRemaining < 0 && !appData.icsActive) { // [HGM] if we run out of a non-last incremental session, go to the next GetTimeQuota((forwardMostMove-blackStartMove-1)/2, 0, blackTC); if(suddenDeath) { blackStartMove = forwardMostMove;