extern int chatCount;
int chattingPartner;
char marker[BOARD_RANKS][BOARD_FILES]; /* [HGM] marks for target squares */
+ChessSquare pieceSweep = EmptySquare;
/* States for ics_getting_history */
#define H_FALSE 0
/* [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;
if(channel >= 0) // channel broadcast; look if there is a chatbox for this channel
for(p=0; p<MAX_CHAT; p++) {
- if(channel == atoi(chatPartner[p])) {
+ if(chatPartner[p][0] >= '0' && chatPartner[p][0] <= '9' && channel == atoi(chatPartner[p])) {
talker[0] = '['; strcat(talker, "] ");
Colorize(channel == 1 ? ColorChannel1 : ColorChannel, FALSE);
chattingPartner = p; break;
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
+ if(gameInfo.holdingsWidth && !appData.disguise && gameInfo.variant != VariantSuper
+ && gameInfo.variant != VariantGreat) // inherit info that ICS does not give from previous board
for(k=0; k<ranks; k++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++) {
ChessSquare old, new = boards[moveNum][k][j];
if(fromY == DROP_RANK && k==toY && j==toX) continue; // dropped pieces always stand for themselves
}
+void
+NextPiece(int step)
+{
+ ChessSquare piece = boards[currentMove][toY][toX];
+ do {
+ pieceSweep += step;
+ if(pieceSweep == EmptySquare) pieceSweep = WhitePawn; // wrap
+ if((int)pieceSweep == -1) pieceSweep = BlackKing;
+ if(!step) step = 1;
+ } while(PieceToChar(pieceSweep) == '.');
+ boards[currentMove][toY][toX] = pieceSweep;
+ DrawPosition(FALSE, boards[currentMove]);
+ boards[currentMove][toY][toX] = piece;
+}
/* [HGM] Shogi move preprocessor: swap digits for letters, vice versa */
void
AlphaRank(char *move, int n)
void
MovePV(int x, int y, int h)
{ // step through PV based on mouse coordinates (called on mouse move)
- int margin = h>>3, step = 0;
+ int margin = h>>3, step = 0, dist;
- if(endPV < 0) return;
// we must somehow check if right button is still down (might be released off board!)
- if(y < margin && (abs(x - lastX) > 6 || abs(y - lastY) > 6)) step = 1; else
- if(y > h - margin && (abs(x - lastX) > 6 || abs(y - lastY) > 6)) step = -1; else
- if( y > lastY + 6 ) step = -1; else if(y < lastY - 6) step = 1;
+ if(abs(x - lastX) < 7 && abs(y - lastY) < 7) return;
+ if( y > lastY + 2 ) step = -1; else if(y < lastY - 2) step = 1;
if(!step) return;
lastX = x; lastY = y;
+
+ if(pieceSweep != EmptySquare) { NextPiece(step); return; }
+ if(endPV < 0) return;
+ if(y < margin) step = 1; else
+ if(y > h - margin) step = -1;
if(currentMove + step > endPV || currentMove + step < forwardMostMove) step = 0;
currentMove += step;
if(currentMove == forwardMostMove) ClearPremoveHighlights(); else
*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
- else *promoChoice = PieceToChar(BlackQueen);
- return FALSE;
- }
+ // give caller the default choice even if we will not make it
+ if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway)
+ *promoChoice = PieceToChar(BlackKing); // in Suicide Q is the last thing we want
+ else *promoChoice = PieceToChar(BlackQueen);
+ if(autoQueen) return FALSE; // predetermined
// suppress promotion popup on illegal moves that are not premoves
premove = gameMode == IcsPlayingWhite && !WhiteOnMove(currentMove) ||
MakeMove(fromX, fromY, toX, toY, promoChar); /*updates forwardMostMove*/
- if(Adjudicate(NULL)) return 1; // [HGM] adjudicate: take care of automtic game end
+ if(Adjudicate(NULL)) { // [HGM] adjudicate: take care of automatic game end
+ ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
+ return 1;
+ }
if (gameMode == BeginningOfGame) {
if (appData.noChessProgram) {
xSqr = EventToSquare(x, BOARD_WIDTH);
ySqr = EventToSquare(y, BOARD_HEIGHT);
- if (action == Release) UnLoadPV(); // [HGM] pv
+ if (action == Release) {
+ if(pieceSweep != EmptySquare) {
+ EditPositionMenuEvent(pieceSweep, toX, toY);
+ pieceSweep = EmptySquare;
+ } else UnLoadPV(); // [HGM] pv
+ }
if (action != Press) return -2; // return code to be ignored
switch (gameMode) {
case IcsExamining:
if(xSqr < BOARD_LEFT || xSqr >= BOARD_RGHT) return -1;\r
case EditPosition:
if (xSqr == BOARD_LEFT-1 || xSqr == BOARD_RGHT) return -1;\r
- if (xSqr < 0 || ySqr < 0) return -1;\r
- whichMenu = 0; // edit-position menu
- break;
+ if (xSqr < 0 || ySqr < 0) return -1;
+ if(appData.pieceMenu) { whichMenu = 0; break; } // edit-position menu
+ pieceSweep = shiftKey ? BlackPawn : WhitePawn; // [HGM] sweep: prepare selecting piece by mouse sweep
+ toX = xSqr; toY = ySqr; lastX = x, lastY = y;
+ if(flipView) toX = BOARD_WIDTH - 1 - toX; else toY = BOARD_HEIGHT - 1 - toY;
+ NextPiece(0);
+ return -2;\r
case IcsObserving:
if(!appData.icsEngineAnalyze) return -1;
case IcsPlayingWhite:
&fromX, &fromY, &toX, &toY, &promoChar)) {
/* Machine move could not be parsed; ignore it. */
snprintf(buf1, MSG_SIZ*10, _("Illegal move \"%s\" from %s machine"),
- machineMove, cps->which);
+ machineMove, _(cps->which));
DisplayError(buf1, 0);
snprintf(buf1, MSG_SIZ*10, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c) res=%d",
machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, moveType);
SwitchClocks(forwardMostMove-1); // [HGM] race
DisplayBothClocks();
snprintf(buf1, 10*MSG_SIZ, _("Illegal move \"%s\" (rejected by %s chess program)"),
- parseList[currentMove], cps->which);
+ parseList[currentMove], _(cps->which));
DisplayMoveError(buf1);
DrawPosition(FALSE, boards[currentMove]);
return;
cps->maybeThinking = FALSE;
snprintf(buf1, sizeof(buf1), _("Failed to start %s chess program %s on %s: %s\n"),
- cps->which, cps->program, cps->host, message);
+ _(cps->which), cps->program, cps->host, message);
RemoveInputSource(cps->isr);
DisplayFatalError(buf1, 0, 1);
return;
/* Hint move could not be parsed!? */
snprintf(buf2, sizeof(buf2),
_("Illegal hint move \"%s\"\nfrom %s chess program"),
- buf1, cps->which);
+ buf1, _(cps->which));
DisplayError(buf2, 0);
}
} else {
if( gameInfo.variant == VariantBughouse || gameInfo.variant == VariantCrazyhouse )
overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 5;
if( gameInfo.variant == VariantCapablanca || gameInfo.variant == VariantCapaRandom ||
- gameInfo.variant == VariantGothic || gameInfo.variant == VariantFalcon )
+ gameInfo.variant == VariantGothic || gameInfo.variant == VariantFalcon || gameInfo.variant == VariantJanus )
overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;
if( gameInfo.variant == VariantCourier )
overruled = gameInfo.boardWidth != 12 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;
for (i = BOARD_HEIGHT - 1; i >= 0; i--)
for (j = BOARD_LEFT; j < BOARD_RGHT; p++)
switch (*p) {
+ case '{':
case '[':
case '-':
case ' ':
{ // [HGM] code moved to back-end from winboard.c
if(which) { // black clock
if (gameMode == EditPosition || gameMode == IcsExamining) {
+ if(!appData.pieceMenu && blackPlaysFirst) EditPositionMenuEvent(ClearBoard, 0, 0);
SetBlackToPlayEvent();
} else if (gameMode == EditGame || shiftKey) {
AdjustClock(which, -1);
}
} else { // white clock
if (gameMode == EditPosition || gameMode == IcsExamining) {
+ if(!appData.pieceMenu && !blackPlaysFirst) EditPositionMenuEvent(ClearBoard, 0, 0);
SetWhiteToPlayEvent();
} else if (gameMode == EditGame || shiftKey) {
AdjustClock(which, -1);
outCount = OutputToProcess(cps->pr, message, count, &error);
if (outCount < count && !exiting
&& !endingGame) { /* [HGM] crash: to not hang GameEnds() writing to deceased engines */
- snprintf(buf, MSG_SIZ, _("Error writing to %s chess program"), cps->which);
+ snprintf(buf, MSG_SIZ, _("Error writing to %s chess program"), _(cps->which));
if(gameInfo.resultDetails==NULL) { /* [HGM] crash: if game in progress, give reason for abort */
if((signed char)boards[forwardMostMove][EP_STATUS] <= EP_DRAWS) {
gameInfo.result = GameIsDrawn; /* [HGM] accept exit as draw claim */
- snprintf(buf, MSG_SIZ, "%s program exits in draw position (%s)", cps->which, cps->program);
+ snprintf(buf, MSG_SIZ, _("%s program exits in draw position (%s)"), _(cps->which), cps->program);
} else {
gameInfo.result = cps->twoMachinesColor[0]=='w' ? BlackWins : WhiteWins;
}
if (count <= 0) {
if (count == 0) {
snprintf(buf, MSG_SIZ, _("Error: %s chess program (%s) exited unexpectedly"),
- cps->which, cps->program);
+ _(cps->which), cps->program);
if(gameInfo.resultDetails==NULL) { /* [HGM] crash: if game in progress, give reason for abort */
if((signed char)boards[forwardMostMove][EP_STATUS] <= EP_DRAWS) {
gameInfo.result = GameIsDrawn; /* [HGM] accept exit as draw claim */
- snprintf(buf, MSG_SIZ, _("%s program exits in draw position (%s)"), cps->which, cps->program);
+ snprintf(buf, MSG_SIZ, _("%s program exits in draw position (%s)"), _(cps->which), cps->program);
} else {
gameInfo.result = cps->twoMachinesColor[0]=='w' ? BlackWins : WhiteWins;
}
if(!cps->userError || !appData.popupExitMessage) DisplayFatalError(buf, 0, 1); else errorExitStatus = 1;
} else {
snprintf(buf, MSG_SIZ, _("Error reading from %s chess program (%s)"),
- cps->which, cps->program);
+ _(cps->which), cps->program);
RemoveInputSource(cps->isr);
/* [AS] Program is misbehaving badly... kill it */
SendToProgram(buf, cps);
}
- if(cps->nps > 0) { /* [HGM] nps */
+ if(cps->nps >= 0) { /* [HGM] nps */
if(cps->supportsNPS == FALSE)
cps->nps = -1; // don't use if engine explicitly says not supported!
else {
} else if((p = strstr(opt->name, " -file "))) {
// for now -file is a synonym for -string, to already provide compatibility with future polyglots
opt->textValue = p+7;
- opt->type = TextBox; // FileName;
+ opt->type = FileName; // FileName;
} else if((p = strstr(opt->name, " -path "))) {
// for now -file is a synonym for -string, to already provide compatibility with future polyglots
opt->textValue = p+7;
- opt->type = TextBox; // PathName;
+ opt->type = PathName; // PathName;
} else if(p = strstr(opt->name, " -check ")) {
if(sscanf(p, " -check %d", &def) < 1) return FALSE;
opt->value = (def != 0);
opt->type = Button;
} else if(p = strstr(opt->name, " -save")) {
opt->type = SaveButton;
- } else if(p = strstr(opt->name, " -reset")) {
- opt->type = ResetButton;
} else return FALSE;
*p = 0; // terminate option name
// now look if the command-line options define a setting for this engine option.
}
if(cps->nrOptions >= MAX_OPTIONS) {
cps->nrOptions--;
- snprintf(buf, MSG_SIZ, "%s engine has too many options\n", cps->which);
+ snprintf(buf, MSG_SIZ, _("%s engine has too many options\n"), _(cps->which));
DisplayError(buf, 0);
}
continue;