* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
BlackUnicorn, BlackBishop, BlackMan, BlackRook }
};
+ChessSquare SpartanArray[2][BOARD_FILES] = {
+ { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
+ WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
+ { BlackAlfil, BlackMarshall, BlackKing, BlackDragon,
+ BlackDragon, BlackKing, BlackAngel, BlackAlfil }
+};
+
ChessSquare fairyArray[2][BOARD_FILES] = { /* [HGM] Queen side differs from King side */
{ WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
/* [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;
case VariantSuper: /* experimental */
case VariantGreat: /* experimental, requires legality testing to be off */
case VariantSChess: /* S-Chess, should work */
+ case VariantSpartan: /* should work */
break;
}
}
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;
int i, j, pawnRow, overrule,
oldx = gameInfo.boardWidth,
oldy = gameInfo.boardHeight,
- oldh = gameInfo.holdingsWidth,
- oldv = gameInfo.variant;
+ oldh = gameInfo.holdingsWidth;
+ static int oldv;
if(appData.icsActive) shuffleOpenings = FALSE; // [HGM] shuffle: in ICS mode, only shuffle on ICS request
pieces = KnightmateArray;
SetCharTable(pieceToChar, "P.BRQ.....M.........K.p.brq.....m.........k.");
break;
+ case VariantSpartan:
+ pieces = SpartanArray;
+ SetCharTable(pieceToChar, "PNBRQ................K......lwg.....c...h..k");
+ break;
case VariantFairy:
pieces = fairyArray;
SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVLSUKpnbrqfeacwmohijgdvlsuk");
if(j < BOARD_LEFT || j >= BOARD_RGHT || overrule) continue;
initialPosition[0][j] = pieces[0][j-gameInfo.holdingsWidth];
initialPosition[pawnRow][j] = WhitePawn;
- initialPosition[BOARD_HEIGHT-pawnRow-1][j] = BlackPawn;
+ initialPosition[BOARD_HEIGHT-pawnRow-1][j] = gameInfo.variant == VariantSpartan ? BlackLance : BlackPawn;
if(gameInfo.variant == VariantXiangqi) {
if(j&1) {
initialPosition[pawnRow][j] =
if(oldx != gameInfo.boardWidth ||
oldy != gameInfo.boardHeight ||
+ oldv != gameInfo.variant ||
oldh != gameInfo.holdingsWidth
-#ifdef GOTHIC
- || oldv == VariantGothic || // For licensing popups
- gameInfo.variant == VariantGothic
-#endif
-#ifdef FALCON
- || oldv == VariantFalcon ||
- gameInfo.variant == VariantFalcon
-#endif
)
InitDrawingSizes(-2 ,0);
+ oldv = gameInfo.variant;
if (redraw)
DrawPosition(TRUE, boards[currentMove]);
}
case BeginningOfGame:
case AnalyzeMode:
case Training:
+ if(fromY == DROP_RANK) break; // [HGM] drop moves (entered through move type-in) are automatically assigned to side-to-move
if ((int) boards[currentMove][fromY][fromX] >= (int) BlackPawn &&
(int) boards[currentMove][fromY][fromX] < (int) EmptySquare) {
/* User is moving for Black */
pup = boards[currentMove][toY][toX];
/* [HGM] If move started in holdings, it means a drop. Convert to standard form */
- if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {
+ if( (fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) && fromY != DROP_RANK ) {
if( pup != EmptySquare ) return;
moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop;
if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n",
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) {
switch (gameMode) {
case EditGame:
+ if(appData.testLegality)
switch (MateTest(boards[currentMove], PosFlags(currentMove)) ) {
case MT_NONE:
case MT_CHECK:
if(canAdjudicate && appData.checkMates) {
if(engineOpponent)
SendMoveToProgram(forwardMostMove-1, engineOpponent); // make sure opponent gets move
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
GameEnds( WhiteOnMove(forwardMostMove) ? BlackWins : WhiteWins,
"Xboard adjudication: King destroyed", GE_XBOARD );
return 1;
if(canAdjudicate && appData.checkMates) {
if(engineOpponent)
SendMoveToProgram(forwardMostMove-1, engineOpponent); // make sure opponent gets to see move
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins,
"Xboard adjudication: Bare king", GE_XBOARD );
return 1;
/* but only adjudicate if adjudication enabled */
if(engineOpponent)
SendMoveToProgram(forwardMostMove-1, engineOpponent); // make sure opponent gets move
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
GameEnds( nrW > 1 ? WhiteWins : nrB > 1 ? BlackWins : GameIsDrawn,
"Xboard adjudication: Bare king", GE_XBOARD );
return 1;
if(canAdjudicate && appData.checkMates && result) { // [HGM] mates: adjudicate finished games if requested
if(engineOpponent)
SendMoveToProgram(forwardMostMove-1, engineOpponent); /* make sure opponent gets to see move */
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
GameEnds( result, reason, GE_XBOARD );
return 1;
}
SendToProgram("force\n", engineOpponent); // suppress reply
SendMoveToProgram(forwardMostMove-1, engineOpponent); /* make sure opponent gets to see last move */
}
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
GameEnds( GameIsDrawn, "Xboard adjudication: Insufficient mating material", GE_XBOARD );
return 1;
}
SendToProgram("force\n", engineOpponent); // suppress reply
SendMoveToProgram(forwardMostMove-1, engineOpponent); /* make sure opponent gets to see move */
}
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
GameEnds( GameIsDrawn, "Xboard adjudication: Trivial draw", GE_XBOARD );
return 1;
}
SendToProgram("force\n", engineOpponent); // suppress reply
SendMoveToProgram(forwardMostMove-1, engineOpponent); /* make sure opponent gets to see move */
}
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
GameEnds( result, details, GE_XBOARD );
return 1;
}
SendToProgram("force\n", engineOpponent); // suppress reply
SendMoveToProgram(forwardMostMove-1, engineOpponent); /* make sure opponent gets to see move */
}
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
GameEnds( GameIsDrawn, "Xboard adjudication: 50-move rule", GE_XBOARD );
return 1;
}
SendToProgram("force\n", engineOpponent); // suppress reply
SendMoveToProgram(forwardMostMove-1, engineOpponent); /* make sure opponent gets to see move */
}
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
GameEnds( GameIsDrawn, p, GE_XBOARD );
return 1;
}
SendToProgram("force\n", engineOpponent); // suppress reply
SendMoveToProgram(forwardMostMove-1, engineOpponent); /* make sure opponent gets to see move */
}
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
GameEnds( GameIsDrawn, "Xboard adjudication: long game", GE_XBOARD );
return 1;
}
&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);
if (cps->sendTime == 2) cps->sendTime = 1;
if (cps->offeredDraw) cps->offeredDraw--;
- /* currentMoveString is set as a side-effect of ParseOneMove */
- safeStrCpy(machineMove, currentMoveString, sizeof(machineMove)/sizeof(machineMove[0]));
- strcat(machineMove, "\n");
- safeStrCpy(moveList[forwardMostMove], machineMove, sizeof(moveList[forwardMostMove])/sizeof(moveList[forwardMostMove][0]));
-
/* [AS] Save move info*/
pvInfoList[ forwardMostMove ].score = programStats.score;
pvInfoList[ forwardMostMove ].depth = programStats.depth;
}
}
- if(Adjudicate(cps)) return; // [HGM] adjudicate: for all automatic game ends
+ if(Adjudicate(cps)) {
+ ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
+ return; // [HGM] adjudicate: for all automatic game ends
+ }
#if ZIPPY
if ((gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack) &&
gameMode = EditGame;
ModeHighlight();
}
+ /* [HGM] illegal-move claim should forfeit game when Xboard */
+ /* only passes fully legal moves */
+ if( appData.testLegality && gameMode == TwoMachinesPlay ) {
+ GameEnds( cps->twoMachinesColor[0] == 'w' ? BlackWins : WhiteWins,
+ "False illegal-move claim", GE_XBOARD );
+ return; // do not take back move we tested as valid
+ }
currentMove = forwardMostMove-1;
DisplayMove(currentMove-1); /* before DisplayMoveError */
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]);
-
- /* [HGM] illegal-move claim should forfeit game when Xboard */
- /* only passes fully legal moves */
- if( appData.testLegality && gameMode == TwoMachinesPlay ) {
- GameEnds( cps->twoMachinesColor[0] == 'w' ? BlackWins : WhiteWins,
- "False illegal-move claim", GE_XBOARD );
- }
return;
}
if (strncmp(message, "time", 4) == 0 && StrStr(message, "Illegal")) {
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 {
int i;
if( board[fromY][fromX] == WhiteLance || board[fromY][fromX] == BlackLance ) {
- if( gameInfo.variant == VariantFairy ) board[EP_STATUS] = EP_PAWN_MOVE; // Lance in fairy is Pawn-like
+ if( gameInfo.variant != VariantSuper && gameInfo.variant != VariantShogi )
+ board[EP_STATUS] = EP_PAWN_MOVE; // Lance is Pawn-like in most variants
} else
if( board[fromY][fromX] == WhitePawn ) {
if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers
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;
first.matchWins, second.matchWins,
appData.matchGames - (first.matchWins + second.matchWins));
popupRequested++; // [HGM] crash: postpone to after resetting endingGame
+ if (appData.firstPlaysBlack) { // [HGM] match: back to original for next match
+ first.twoMachinesColor = "black\n";
+ second.twoMachinesColor = "white\n";
+ } else {
+ first.twoMachinesColor = "white\n";
+ second.twoMachinesColor = "black\n";
+ }
}
}
if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile) &&
return FALSE;
} else {
/* currentMoveString is set as a side-effect of yylex */
- strcat(currentMoveString, "\n");
- safeStrCpy(moveList[forwardMostMove], currentMoveString, sizeof(moveList[forwardMostMove])/sizeof(moveList[forwardMostMove][0]));
thinkOutput[0] = NULLCHAR;
MakeMove(fromX, fromY, toX, toY, promoChar);
for (i = BOARD_HEIGHT - 1; i >= 0; i--)
for (j = BOARD_LEFT; j < BOARD_RGHT; p++)
switch (*p) {
+ case '{':
case '[':
case '-':
case ' ':
}
void
+ClockClick(int which)
+{ // [HGM] code moved to back-end from winboard.c
+ if(which) { // black clock
+ if (gameMode == EditPosition || gameMode == IcsExamining) {
+ SetBlackToPlayEvent();
+ } else if (gameMode == EditGame || shiftKey) {
+ AdjustClock(which, -1);
+ } else if (gameMode == IcsPlayingWhite ||
+ gameMode == MachinePlaysBlack) {
+ CallFlagEvent();
+ }
+ } else { // white clock
+ if (gameMode == EditPosition || gameMode == IcsExamining) {
+ SetWhiteToPlayEvent();
+ } else if (gameMode == EditGame || shiftKey) {
+ AdjustClock(which, -1);
+ } else if (gameMode == IcsPlayingBlack ||
+ gameMode == MachinePlaysWhite) {
+ CallFlagEvent();
+ }
+ }
+}
+
+void
DrawEvent()
{
/* Offer draw or accept pending draw offer from opponent */
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 {
}
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;
if(blackNPS >= 0) lastTickLength = 0;
blackTimeRemaining -= lastTickLength;
/* [HGM] PGNtime: save time for PGN file if engine did not give it */
-// if(pvInfoList[forwardMostMove-1].time == -1)
- pvInfoList[forwardMostMove-1].time = // use GUI time
+// if(pvInfoList[forwardMostMove].time == -1)
+ pvInfoList[forwardMostMove].time = // use GUI time
(timeRemaining[1][forwardMostMove-1] - blackTimeRemaining)/10;
} else {
if(whiteNPS >= 0) lastTickLength = 0;
whiteTimeRemaining -= lastTickLength;
/* [HGM] PGNtime: save time for PGN file if engine did not give it */
-// if(pvInfoList[forwardMostMove-1].time == -1)
- pvInfoList[forwardMostMove-1].time =
+// if(pvInfoList[forwardMostMove].time == -1)
+ pvInfoList[forwardMostMove].time =
(timeRemaining[0][forwardMostMove-1] - whiteTimeRemaining)/10;
}
flagged = CheckFlags();