char *buf, int count, int error));
void read_from_ics P((InputSourceRef isr, VOIDSTAR closure,
char *buf, int count, int error));
-void ics_printf P((char *format, ...));
void SendToICS P((char *s));
void SendToICSDelayed P((char *s, long msdelay));
void SendMoveToICS P((ChessMove moveType, int fromX, int fromY, int toX, int toY, char promoChar));
long time, increment;
char *s = tcString;
- if(!*s) return 0; // empty TC string means we ran out of the last sudden-death version
+ if(!s || !*s) return 0; // empty TC string means we ran out of the last sudden-death version
do {
if(moves) NextSessionFromString(&s, &moves, &time, &increment, &incType);
nextSession = s; suddenDeath = moves == 0 && increment == 0;
board[i][j+newHoldingsWidth-gameInfo.holdingsWidth] =
board[i][j];
}
+ board[HOLDINGS_SET] = 0;
gameInfo.boardWidth = newWidth;
gameInfo.boardHeight = newHeight;
gameInfo.holdingsWidth = newHoldingsWidth;
xList[i] = yList[i] = -100; // outside graph, so cannot be clicked
if(r < minRating+100 && r >=0 ) r = minRating+100;
if(r > maxRating) r = maxRating;
- if(tc < 1.) tc = 1.;
- if(tc > 95.) tc = 95.;
+ if(tc < 1.f) tc = 1.f;
+ if(tc > 95.f) tc = 95.f;
x = (w-hMargin-squareSize/8-7)* log(tc)/log(95.) + hMargin;
y = ((double)r - minRating)/(maxRating - minRating)
* (h-vMargin-squareSize/8-1) + vMargin;
break;
}
- if((gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack)
+ if((gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||
+ gameMode == IcsObserving && appData.dualBoard) // also allow use of second board for observing two games
&& newGameMode == IcsObserving && gamenum != ics_gamenum && appData.bgObserve) {
// [HGM] bughouse: don't act on alien boards while we play. Just parse the board and save it */
int fac = strchr(elapsed_time, '.') ? 1 : 1000;
+ static int lastBgGame = -1;
char *toSqr;
for (k = 0; k < ranks; k++) {
for (j = 0; j < files; j++)
DisplayWhiteClock(white_time*fac, to_play == 'W');
DisplayBlackClock(black_time*fac, to_play != 'W');
activePartner = to_play;
+ if(gamenum != lastBgGame) {
+ char buf[MSG_SIZ];
+ snprintf(buf, MSG_SIZ, "%s %s %s", white, _("vs."), black);
+ DisplayTitle(buf);
+ }
+ lastBgGame = gamenum;
activePartnerTime = to_play == 'W' ? white_time*fac : black_time*fac;
partnerUp = 0; flipView = !flipView; } // [HGM] dual
snprintf(partnerStatus, MSG_SIZ,"W: %d:%02d B: %d:%02d (%d-%d) %c", white_time*fac/60000, (white_time*fac%60000)/1000,
return;
}
+ if(appData.dualBoard && appData.bgObserve) {
+ if((newGameMode == IcsPlayingWhite || newGameMode == IcsPlayingBlack) && moveNum == 1)
+ SendToICS(ics_prefix), SendToICS("pobserve\n");
+ else if(newGameMode == IcsObserving && (gameMode == BeginningOfGame || gameMode == IcsIdle)) {
+ char buf[MSG_SIZ];
+ snprintf(buf, MSG_SIZ, "%spobserve %s\n", ics_prefix, white);
+ SendToICS(buf);
+ }
+ }
+
/* Modify behavior for initial board display on move listing
of wild games.
*/
}
if (gameInfo.boardHeight != ranks || gameInfo.boardWidth != files ||
+ move_str[1] == '@' && !gameInfo.holdingsWidth ||
weird && (int)gameInfo.variant < (int)VariantShogi) {
/* [HGM] We seem to have switched variant unexpectedly
* Try to guess new variant from board size
if(ranks == 10 && files == 9) newVariant = VariantXiangqi; else
if(ranks == 8 && files == 12) newVariant = VariantCourier; else
if(ranks == 9 && files == 9) newVariant = VariantShogi; else
- if(!weird) newVariant = VariantNormal;
+ if(ranks == 10 && files == 10) newVariant = VariantGrand; else
+ if(!weird) newVariant = move_str[1] == '@' ? VariantCrazyhouse : VariantNormal;
VariantSwitch(boards[currentMove], newVariant); /* temp guess */
/* Get a move list just to see the header, which
will tell us whether this is really bug or zh */
} while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || promoSweep == pawn ||
appData.testLegality && (promoSweep == king ||
gameInfo.variant == VariantShogi && promoSweep != PROMOTED last && last != PROMOTED promoSweep && last != promoSweep));
+ if(toX >= 0) {
+ int victim = boards[currentMove][toY][toX];
+ boards[currentMove][toY][toX] = promoSweep;
+ DrawPosition(FALSE, boards[currentMove]);
+ boards[currentMove][toY][toX] = victim;
+ } else
ChangeDragPiece(promoSweep);
}
}
static int
-ExcludeOneMove (int fromY, int fromX, int toY, int toX, signed char promoChar, char state)
+ExcludeOneMove (int fromY, int fromX, int toY, int toX, char promoChar, char state)
{ // include or exclude the given move, as specified by state ('+' or '-'), or toggle
char buf[MSG_SIZ];
int j, k;
ChessMove moveType;
- if(promoChar == -1) { // kludge to indicate best move
+ if((signed char)promoChar == -1) { // kludge to indicate best move
if(!ParseOneMove(lastPV[0], currentMove, &moveType, &fromX, &fromY, &toX, &toY, &promoChar)) // get current best move from last PV
return 1; // if unparsable, abort
}
UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar)
{
ChessMove moveType;
- ChessSquare pdown, pup;
+ ChessSquare pup;
int ff=fromX, rf=fromY, ft=toX, rt=toY;
-
/* Check if the user is playing in turn. This is complicated because we
let the user "pick up" a piece before it is his turn. So the piece he
tried to pick up may have been captured by the time he puts it down!
}
if(toX < 0 || toY < 0) return;
- pdown = boards[currentMove][fromY][fromX];
pup = boards[currentMove][toY][toX];
/* [HGM] If move started in holdings, it means a drop. Convert to standard form */
for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) if(marker[y][x] == 1) marker[y][x] = 0;
}
}
- DrawPosition(TRUE, NULL);
+ DrawPosition(FALSE, NULL);
}
int
{
int x, y;
Boolean saveAnimate;
- static int second = 0, promotionChoice = 0, clearFlag = 0;
+ static int second = 0, promotionChoice = 0, clearFlag = 0, sweepSelecting = 0;
char promoChoice = NULLCHAR;
ChessSquare piece;
static TimeMark lastClickTime, prevClickTime;
defaultPromoChoice = promoSweep;
promoSweep = EmptySquare; // terminate sweep
promoDefaultAltered = TRUE;
- if(!selectFlag && (x != toX || y != toY)) x = fromX, y = fromY; // and fake up-click on same square if we were still selecting
+ if(!selectFlag && !sweepSelecting && (x != toX || y != toY)) x = fromX, y = fromY; // and fake up-click on same square if we were still selecting
}
if(promotionChoice) { // we are waiting for a click to indicate promotion piece
}
if (appData.highlightDragging) {
SetHighlights(fromX, fromY, -1, -1);
+ } else {
+ ClearHighlights();
}
} else fromX = fromY = -1;
return;
/* Undo animation damage if any */
DrawPosition(FALSE, NULL);
}
- if (second) {
+ if (second || sweepSelecting) {
/* Second up/down in same square; just abort move */
- second = 0;
+ if(sweepSelecting) DrawPosition(FALSE, boards[currentMove]);
+ second = sweepSelecting = 0;
fromX = fromY = -1;
gatingPiece = EmptySquare;
ClearHighlights();
/* we now have a different from- and (possibly off-board) to-square */
/* Completed move */
- toX = x;
- toY = y;
+ if(!sweepSelecting) {
+ toX = x;
+ toY = y;
+ } else sweepSelecting = 0; // this must be the up-click corresponding to the down-click that started the sweep
+
saveAnimate = appData.animate;
- MarkTargetSquares(1);
if (clickType == Press) {
if(gameMode == EditPosition && boards[currentMove][fromY][fromX] == EmptySquare) {
// must be Edit Position mode with empty-square selected
if(x >= BOARD_LEFT && x < BOARD_RGHT) clearFlag = 1; // and defer click-click move of empty-square to up-click
return;
}
- /* Finish clickclick move */
- if (appData.animate || appData.highlightLastMove) {
- SetHighlights(fromX, fromY, toX, toY);
- } else {
- ClearHighlights();
- }
if(HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, FALSE)) {
if(appData.sweepSelect) {
ChessSquare piece = boards[currentMove][fromY][fromX];
- DragPieceBegin(xPix, yPix, TRUE); dragging = 1;
promoSweep = defaultPromoChoice;
if(PieceToChar(PROMOTED piece) == '+') promoSweep = PROMOTED piece;
selectFlag = 0; lastX = xPix; lastY = yPix;
Sweep(0); // Pawn that is going to promote: preview promotion piece
+ sweepSelecting = 1;
DisplayMessage("", _("Pull pawn backwards to under-promote"));
- DrawPosition(FALSE, boards[currentMove]);
+ MarkTargetSquares(1);
}
return; // promo popup appears on up-click
}
+ /* Finish clickclick move */
+ if (appData.animate || appData.highlightLastMove) {
+ SetHighlights(fromX, fromY, toX, toY);
+ } else {
+ ClearHighlights();
+ }
} else {
/* Finish drag move */
if (appData.highlightLastMove) {
/* Don't animate move and drag both */
appData.animate = FALSE;
}
+ MarkTargetSquares(1);
// moves into holding are invalid for now (except in EditPosition, adapting to-square)
if(x >= 0 && x < BOARD_LEFT || x >= BOARD_RGHT) {
continue;
if (appData.timeDelay < 0)
return;
- StartLoadGameTimer((long)(1000.0 * appData.timeDelay));
+ StartLoadGameTimer((long)(1000.0f * appData.timeDelay));
break;
}
}
int
QuickScan (Board board, Move *move)
{ // reconstruct game,and compare all positions in it
- int cnt=0, stretch=0, total = MakePieceList(board, counts), delayedKing = -1;
+ int cnt=0, stretch=0, total = MakePieceList(board, counts);
do {
int piece = move->piece;
int to = move->to, from = pieceList[piece];
move++;
continue;
} else if(piece <= Q_BCASTL) { // castling, encoded as (Q_XCASTL, king-to) + (rook, rook-to)
- int rook;
piece = pieceList[piece]; // first two elements of pieceList contain King numbers
from = pieceList[piece]; // so this must be King
quickBoard[from] = 0;
if(stretch++ == 0) for(i=0; i<EmptySquare; i++) lastCounts[i] = counts[i]; // remember actual material
} else stretch = 0;
if(stretch && (appData.searchMode == 1 || stretch >= appData.stretch)) return cnt + 1 - stretch;
- move++; delayedKing = -1;
+ move++;
} while(1);
}
SaveGamePGN (FILE *f)
{
int i, offset, linelen, newblock;
- time_t tm;
// char *movetext;
char numtext[32];
int movelen, numlen, blank;
offset = backwardMostMove & (~1L); /* output move numbers start at 1 */
- tm = time((time_t *) NULL);
-
PrintPGNTags(f, &gameInfo);
if(appData.numberTag && matchMode) fprintf(f, "[Number \"%d\"]\n", nextGame+1); // [HGM] number tag
StartAnalysisClock();
GetTimeMark(&lastNodeCountTime);
lastNodeCount = 0;
- if(appData.timeDelay > 0) StartLoadGameTimer((long)(1000.0 * appData.timeDelay));
+ if(appData.timeDelay > 0) StartLoadGameTimer((long)(1000.0f * appData.timeDelay));
}
void
if (appData.noChessProgram) return;
- if(second.protocolVersion >= 2 && !strstr(second.variants, VariantName(gameInfo.variant))) {
- DisplayError("second engine does not play this", 0);
- return;
- }
-
switch (gameMode) {
case TwoMachinesPlay:
return;
ScheduleDelayedEvent(TwoMachinesEventIfReady, 10);
return;
}
+
+ if(second.protocolVersion >= 2 && !strstr(second.variants, VariantName(gameInfo.variant))) {
+ DisplayError("second engine does not play this", 0);
+ return;
+ }
+
if(!stalling) {
InitChessProgram(&second, FALSE); // unbalances ping of second engine
SendToProgram("force\n", &second);
(gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom) &&
( *p >= 'a' && *p < 'a' + gameInfo.boardWidth) ||
( *p >= 'A' && *p < 'A' + gameInfo.boardWidth) ) {
- char c = *p++; int whiteKingFile=NoRights, blackKingFile=NoRights;
+ int c = *p++, whiteKingFile=NoRights, blackKingFile=NoRights;
for(i=BOARD_LEFT; i<BOARD_RGHT; i++) {
if(board[BOARD_HEIGHT-1][i] == BlackKing) blackKingFile = i;