* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
void ParseGameHistory P((char *game));
void ParseBoard12 P((char *string));
+void KeepAlive P((void));
void StartClocks P((void));
-void SwitchClocks P((void));
+void SwitchClocks P((int nr));
void StopClocks P((void));
void ResetClocks P((void));
char *PGNDate P((void));
int whiteNPS, blackNPS; /* [HGM] nps: for easily making clocks aware of NPS */
VariantClass currentlyInitializedVariant; /* [HGM] variantswitch */
int lastIndex = 0; /* [HGM] autoinc: last game/position used in match mode */
+Boolean connectionAlive;/* [HGM] alive: ICS connection status from probing */
int opponentKibitzes;
int lastSavedGame; /* [HGM] save: ID of game */
char chatPartner[MAX_CHAT][MSG_SIZ]; /* [HGM] chat: list of chatting partners */
case VariantNoCastle:
case VariantShatranj:
case VariantCourier:
+ case VariantMakruk:
flags &= ~F_ALL_CASTLE_OK;
break;
default:
BlackUnicorn, BlackBishop, BlackMan, BlackRook }
};
-ChessSquare fairyArray[2][BOARD_SIZE] = { /* [HGM] Queen side differs from King side */
- { WhiteCannon, WhiteNightrider, WhiteAlfil, WhiteQueen,
+ChessSquare fairyArray[2][BOARD_SIZE] = { /* [HGM] white and black different armies! */
+ { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
- { BlackCannon, BlackNightrider, BlackAlfil, BlackQueen,
- BlackKing, BlackBishop, BlackKnight, BlackRook }
+ { BlackLance, BlackAlfil, BlackMarshall, BlackAngel,
+ BlackKing, BlackMarshall, BlackAlfil, BlackLance }
};
ChessSquare ShatranjArray[2][BOARD_SIZE] = { /* [HGM] (movGen knows about Shatranj Q and P) */
BlackFerz, BlackAlfil, BlackKnight, BlackRook }
};
+ChessSquare makrukArray[2][BOARD_SIZE] = { /* [HGM] (movGen knows about Shatranj Q and P) */
+ { WhiteRook, WhiteKnight, WhiteMan, WhiteKing,
+ WhiteFerz, WhiteMan, WhiteKnight, WhiteRook },
+ { BlackRook, BlackKnight, BlackMan, BlackFerz,
+ BlackKing, BlackMan, BlackKnight, BlackRook }
+};
+
#if (BOARD_SIZE>=10)
ChessSquare ShogiArray[2][BOARD_SIZE] = {
/* [HGM] time odds: set factor for each machine */
first.timeOdds = appData.firstTimeOdds;
second.timeOdds = appData.secondTimeOdds;
- { int norm = 1;
+ { float norm = 1;
if(appData.timeOddsMode) {
norm = first.timeOdds;
if(norm > second.timeOdds) norm = second.timeOdds;
case VariantAtomic: /* should work except for win condition */
case Variant3Check: /* should work except for win condition */
case VariantShatranj: /* should work except for all win conditions */
+ case VariantMakruk: /* should work except for daw countdown */
case VariantBerolina: /* might work if TestLegality is off */
case VariantCapaRandom: /* should work */
case VariantJanus: /* should work */
AddInputSource(icsPR, FALSE, read_from_ics, &telnetISR);
fromUserISR =
AddInputSource(NoProc, FALSE, read_from_player, &fromUserISR);
+ if(appData.keepAlive) // [HGM] alive: schedule sending of dummy 'date' command
+ ScheduleDelayedEvent(KeepAlive, appData.keepAlive*60*1000);
} else if (appData.noChessProgram) {
SetNCPMode();
} else {
void
KeepAlive()
{ // [HGM] alive: periodically send dummy (date) command to ICS to prevent time-out
+ if(!connectionAlive) DisplayFatalError("No response from ICS", 0, 1);
+ connectionAlive = FALSE; // only sticks if no response to 'date' command.
SendToICS("date\n");
if(appData.keepAlive) ScheduleDelayedEvent(KeepAlive, appData.keepAlive*60*1000);
}
int count;
int error;
{
-#define BUF_SIZE 8192
+#define BUF_SIZE (16*1024) /* overflowed at 8K with "inchannel 1" on FICS? */
#define STARTED_NONE 0
#define STARTED_MOVES 1
#define STARTED_BOARD 2
char talker[MSG_SIZ]; // [HGM] chat
int channel;
+ connectionAlive = TRUE; // [HGM] alive: I think, therefore I am...
+
if (appData.debugMode) {
if (!error) {
fprintf(debugFP, "<ICS: ");
}
buf[buf_len] = NULLCHAR;
- next_out = leftover_len;
+// next_out = leftover_len; // [HGM] should we set this to 0, and not print it in advance?
+ next_out = 0;
leftover_start = 0;
i = 0;
if(!suppressKibitz) // [HGM] kibitz
AppendComment(forwardMostMove, StripHighlight(parse));
else { // [HGM kibitz: divert memorized engine kibitz to engine-output window
- int nrDigit = 0, nrAlph = 0, i;
+ int nrDigit = 0, nrAlph = 0, j;
if(parse_pos > MSG_SIZ - 30) // defuse unreasonably long input
{ parse_pos = MSG_SIZ-30; parse[parse_pos - 1] = '\n'; }
parse[parse_pos] = NULLCHAR;
// try to be smart: if it does not look like search info, it should go to
// ICS interaction window after all, not to engine-output window.
- for(i=0; i<parse_pos; i++) { // count letters and digits
- nrDigit += (parse[i] >= '0' && parse[i] <= '9');
- nrAlph += (parse[i] >= 'a' && parse[i] <= 'z');
- nrAlph += (parse[i] >= 'A' && parse[i] <= 'Z');
+ for(j=0; j<parse_pos; j++) { // count letters and digits
+ nrDigit += (parse[j] >= '0' && parse[j] <= '9');
+ nrAlph += (parse[j] >= 'a' && parse[j] <= 'z');
+ nrAlph += (parse[j] >= 'A' && parse[j] <= 'Z');
}
if(nrAlph < 9*nrDigit) { // if more than 10% digit we assume search info
int depth=0; float score;
pvInfoList[forwardMostMove-1].score = 100*score;
}
OutputKibitz(suppressKibitz, parse);
+ next_out = i+1; // [HGM] suppress printing in ICS window
} else {
char tmp[MSG_SIZ];
sprintf(tmp, _("your opponent kibitzes: %s"), parse);
}
started = STARTED_NONE;
} else {
- /* Don't match patterns against characters in chatter */
+ /* Don't match patterns against characters in comment */
i++;
continue;
}
}
continue;
} else
- if(looking_at(buf, &i, "kibitzed to")) { // suppress the acknowledgements of our own autoKibitz
- started = STARTED_CHATTER;
- suppressKibitz = TRUE;
+ if(looking_at(buf, &i, "kibitzed to *\n") && atoi(star_match[0])) {
+ // suppress the acknowledgements of our own autoKibitz
+ char *p;
+ if(p = strchr(star_match[0], ' ')) p[1] = NULLCHAR; // clip off "players)" on FICS
+ SendToPlayer(star_match[0], strlen(star_match[0]));
+ looking_at(buf, &i, "*% "); // eat prompt
+ next_out = i;
}
} // [HGM] kibitz: end of patch
if(started == STARTED_NONE && (looking_at(buf, &i, "* tells you:") || looking_at(buf, &i, "* says:") ||
looking_at(buf, &i, "* whispers:") ||
looking_at(buf, &i, "*(*):") && (sscanf(star_match[1], "%d", &channel),1) ||
- looking_at(buf, &i, "*(*)(*):") && sscanf(star_match[2], "%d", &channel) == 1 )) {
+ looking_at(buf, &i, "*(*)(*):") && (sscanf(star_match[2], "%d", &channel),1) ||
+ looking_at(buf, &i, "*(*)(*)(*):") && (sscanf(star_match[3], "%d", &channel),1) ||
+ looking_at(buf, &i, "*(*)(*)(*)(*):") && sscanf(star_match[4], "%d", &channel) == 1 )) {
int p;
sscanf(star_match[0], "%[^(]", talker+1); // strip (C) or (U) off ICS handle
chattingPartner = -1;
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])) {
- talker[0] = '['; strcat(talker, "]");
+ talker[0] = '['; strcat(talker, "] ");
chattingPartner = p; break;
}
} else
if(buf[i-3] == 'r') // whisper; look if there is a WHISPER chatbox
for(p=0; p<MAX_CHAT; p++) {
if(!strcmp("WHISPER", chatPartner[p])) {
- talker[0] = '['; strcat(talker, "]");
+ talker[0] = '['; strcat(talker, "] ");
chattingPartner = p; break;
}
}
if(chattingPartner<0) i = oldi; else {
started = STARTED_COMMENT;
parse_pos = 0; parse[0] = NULLCHAR;
- savingComment = TRUE;
+ savingComment = 3 + chattingPartner; // counts as TRUE
suppressKibitz = TRUE;
}
} // [HGM] chat: end of patch
memcpy(parse, &buf[oldi], parse_pos);
parse[parse_pos] = NULLCHAR;
started = STARTED_COMMENT;
+ if(savingComment >= 3) // [HGM] chat: continuation of line for chat box
+ chattingPartner = savingComment - 3; // kludge to remember the box
} else {
started = STARTED_CHATTER;
}
if (looking_at(buf, &i, "% ") ||
((started == STARTED_MOVES || started == STARTED_MOVES_NOHIDE)
&& looking_at(buf, &i, "}*"))) { char *bookHit = NULL; // [HGM] book
+ if(suppressKibitz) next_out = i;
savingComment = FALSE;
+ suppressKibitz = 0;
switch (started) {
case STARTED_MOVES:
case STARTED_MOVES_NOHIDE:
looking_at(buf, &i, "It is not your move")) {
/* Illegal move */
if (ics_user_moved && forwardMostMove > backwardMostMove) { // only backup if we already moved
- currentMove = --forwardMostMove;
+ currentMove = forwardMostMove-1;
DisplayMove(currentMove - 1); /* before DMError */
DrawPosition(FALSE, boards[currentMove]);
- SwitchClocks();
+ SwitchClocks(forwardMostMove-1); // [HGM] race
DisplayBothClocks();
}
DisplayMoveError(_("Illegal move (rejected by ICS)")); // [HGM] but always relay error msg
while(looking_at(buf, &i, "\n")); // [HGM] skip empty lines
if (looking_at(buf, &i, "*% ")) {
savingComment = FALSE;
+ suppressKibitz = 0;
}
}
next_out = i;
if (looking_at(buf, &i, "*% ")) {
if(strchr(star_match[0], 7)) SendToPlayer("\007", 1); // Bell(); // FICS fuses bell for next board with prompt in zh captures
savingComment = FALSE;
+ suppressKibitz = 0;
}
next_out = i;
}
i++; /* skip unparsed character and loop back */
}
- if (started != STARTED_MOVES && started != STARTED_BOARD && !suppressKibitz && // [HGM] kibitz suppress printing in ICS interaction window
- started != STARTED_HOLDINGS && i > next_out) {
- SendToPlayer(&buf[next_out], i - next_out);
+ if (started != STARTED_MOVES && started != STARTED_BOARD && !suppressKibitz && // [HGM] kibitz
+// started != STARTED_HOLDINGS && i > next_out) { // [HGM] should we compare to leftover_start in stead of i?
+// SendToPlayer(&buf[next_out], i - next_out);
+ started != STARTED_HOLDINGS && leftover_start > next_out) {
+ SendToPlayer(&buf[next_out], leftover_start - next_out);
next_out = i;
}
- suppressKibitz = FALSE; // [HGM] kibitz: has done its duty in if-statement above
leftover_len = buf_len - leftover_start;
/* if buffer ends with something we couldn't parse,
for(k=BOARD_LEFT; k<BOARD_RGHT; k++)
if(board[BOARD_HEIGHT-1][k] == bKing)
initialRights[5] = castlingRights[moveNum][5] = k;
+ if(gameInfo.variant == VariantTwoKings) {
+ // In TwoKings looking for a King does not work, so always give castling rights to a King on e1/e8
+ if(board[0][4] == wKing) initialRights[2] = castlingRights[moveNum][2] = 4;
+ if(board[BOARD_HEIGHT-1][4] == bKing) initialRights[5] = castlingRights[moveNum][5] = 4;
+ }
} else { int r;
r = castlingRights[moveNum][0] = initialRights[0];
if(board[0][r] != WhiteRook) castlingRights[moveNum][0] = -1;
case BlackPromotionChancellor:
case WhitePromotionArchbishop:
case BlackPromotionArchbishop:
- if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier)
+ if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk)
sprintf(user_move, "%c%c%c%c=%c\n",
AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,
PieceToChar(WhiteFerz));
if (appData.testLegality) {
return (*moveType != IllegalMove);
} else {
- return !(fromX == fromY && toX == toY);
+ return !(*fromX == *toX && *fromY == *toY);
}
case WhiteDrop:
nrCastlingRights = 0;
SetCharTable(pieceToChar, "PN.R.QB...Kpn.r.qb...k");
break;
+ case VariantMakruk:
+ pieces = makrukArray;
+ nrCastlingRights = 0;
+ startedFromSetupPosition = TRUE;
+ SetCharTable(pieceToChar, "PN.R.M....SKpn.r.m....sk");
+ break;
case VariantTwoKings:
pieces = twoKingsArray;
break;
break;
case VariantFairy:
pieces = fairyArray;
- SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
+ SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVLSUKpnbrqfeacwmohijgdvlsuk");
break;
case VariantGreat:
pieces = GreatArray;
pawnRow = gameInfo.boardHeight - 7; /* seems to work in all common variants */
if(pawnRow < 1) pawnRow = 1;
+ if(gameInfo.variant == VariantMakruk) pawnRow = 2;
/* User pieceToChar list overrules defaults */
if(appData.pieceToCharTable != NULL)
if(gameInfo.variant == VariantShogi) {
promotionZoneSize = 3;
highestPromotingPiece = (int)WhiteFerz;
+ } else if(gameInfo.variant == VariantMakruk) {
+ promotionZoneSize = 3;
}
// next weed out all moves that do not touch the promotion zone at all
}
// we either have a choice what to promote to, or (in Shogi) whether to promote
- if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier) {
+ if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk) {
*promoChoice = PieceToChar(BlackFerz); // no choice
return FALSE;
}
gameMode = EditGame;
ModeHighlight();
}
- currentMove = --forwardMostMove;
+ currentMove = forwardMostMove-1;
DisplayMove(currentMove-1); /* before DisplayMoveError */
- SwitchClocks();
+ SwitchClocks(forwardMostMove-1); // [HGM] race
DisplayBothClocks();
sprintf(buf1, _("Illegal move \"%s\" (rejected by %s chess program)"),
parseList[currentMove], cps->which);
char *ep;
{
ChessSquare captured = board[toY][toX], piece, king; int p, oldEP = EP_NONE, berolina = 0;
+ int promoRank = gameInfo.variant == VariantMakruk ? 3 : 1;
/* [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 */
}
/* [HGM] In Shatranj and Courier all promotions are to Ferz */
- if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier)
+ if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier || gameInfo.variant == VariantMakruk)
&& promoChar != 0) promoChar = PieceToChar(WhiteFerz);
if (fromX == toX && fromY == toY) return;
board[toY][toX+1] = board[fromY][BOARD_LEFT];
board[fromY][BOARD_LEFT] = EmptySquare;
} else if (board[fromY][fromX] == WhitePawn
- && toY == BOARD_HEIGHT-1
+ && toY >= BOARD_HEIGHT-promoRank
&& gameInfo.variant != VariantXiangqi
) {
/* white pawn promotion */
board[fromY][0] = EmptySquare;
board[toY][2] = BlackRook;
} else if (board[fromY][fromX] == BlackPawn
- && toY == 0
+ && toY < promoRank
&& gameInfo.variant != VariantXiangqi
) {
/* black pawn promotion */
- board[0][toX] = CharToPiece(ToLower(promoChar));
- if (board[0][toX] == EmptySquare) {
- board[0][toX] = BlackQueen;
+ board[toY][toX] = CharToPiece(ToLower(promoChar));
+ if (board[toY][toX] == EmptySquare) {
+ board[toY][toX] = BlackQueen;
}
if(gameInfo.variant==VariantBughouse ||
gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */
{int i; for(i=0; i<BOARD_SIZE; i++) castlingRights[forwardMostMove+1][i] = castlingRights[forwardMostMove][i];}
ApplyMove(fromX, fromY, toX, toY, promoChar, boards[forwardMostMove+1],
castlingRights[forwardMostMove+1], &epStatus[forwardMostMove+1]);
- forwardMostMove++; // [HGM] bare: moved to after ApplyMove, to make sure clock interrupt finds complete board
- SwitchClocks(); // uses forwardMostMove, so must be done after incrementing it !
+ // forwardMostMove++; // [HGM] bare: moved to after ApplyMove, to make sure clock interrupt finds complete board
+ SwitchClocks(forwardMostMove+1); // [HGM] race: incrementing move nr inside
timeRemaining[0][forwardMostMove] = whiteTimeRemaining;
timeRemaining[1][forwardMostMove] = blackTimeRemaining;
gameInfo.result = GameUnfinished;
result, resultDetails ? resultDetails : "(null)", whosays);
}
+ fromX = fromY = -1; // [HGM] abort any move the user is entering.
+
if (appData.icsActive && (whosays == GE_ENGINE || whosays >= GE_ENGINE1)) {
/* If we are playing on ICS, the server decides when the
game is over, but the engine can offer to draw, claim
case BlackQueen:
if(gameInfo.variant == VariantShatranj ||
gameInfo.variant == VariantXiangqi ||
- gameInfo.variant == VariantCourier )
+ gameInfo.variant == VariantCourier ||
+ gameInfo.variant == VariantMakruk )
selection = (ChessSquare)((int)selection - (int)WhiteQueen + (int)WhiteFerz);
goto defaultlabel;
/* [HGM] translate opponent's time by time-odds factor */
otime = (otime * cps->other->timeOdds) / cps->timeOdds;
if (appData.debugMode) {
- fprintf(debugFP, "time odds: %d %d \n", cps->timeOdds, cps->other->timeOdds);
+ fprintf(debugFP, "time odds: %f %f \n", cps->timeOdds, cps->other->timeOdds);
}
if (time <= 0) time = 1;
from the color that is *not* on move now.
*/
void
-SwitchClocks()
+SwitchClocks(int newMoveNr)
{
long lastTickLength;
TimeMark now;
if (StopClockTimer() && appData.clockMode) {
lastTickLength = SubtractTimeMarks(&now, &tickStartTM);
- if (WhiteOnMove(forwardMostMove)) {
+ if (!WhiteOnMove(forwardMostMove)) {
if(blackNPS >= 0) lastTickLength = 0;
blackTimeRemaining -= lastTickLength;
/* [HGM] PGNtime: save time for PGN file if engine did not give it */
}
flagged = CheckFlags();
}
+ forwardMostMove = newMoveNr; // [HGM] race: change stm when no timer interrupt scheduled
CheckTimeControl();
if (flagged || !appData.clockMode) return;
*p++ = ' ';
if(q = overrideCastling) { // [HGM] FRC: override castling & e.p fields for non-compliant engines
- while(*p++ = *q++); if(q != overrideCastling+1) p[-1] = ' ';
+ while(*p++ = *q++); if(q != overrideCastling+1) p[-1] = ' '; else --p;
} else {
if(nrCastlingRights) {
q = p;
}
if(gameInfo.variant != VariantShogi && gameInfo.variant != VariantXiangqi &&
- gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier ) {
+ gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier && gameInfo.variant != VariantMakruk ) {
/* En passant target square */
if (move > backwardMostMove) {
fromX = moveList[move - 1][0] - AAA;
} /* assume possible unless obviously impossible */
if(initialRights[0]>=0 && board[castlingRank[0]][initialRights[0]] != WhiteRook) FENcastlingRights[0] = -1;
if(initialRights[1]>=0 && board[castlingRank[1]][initialRights[1]] != WhiteRook) FENcastlingRights[1] = -1;
- if(initialRights[2]>=0 && board[castlingRank[2]][initialRights[2]] != WhiteKing) FENcastlingRights[2] = -1;
+ if(initialRights[2]>=0 && board[castlingRank[2]][initialRights[2]] != WhiteUnicorn
+ && board[castlingRank[2]][initialRights[2]] != WhiteKing) FENcastlingRights[2] = -1;
if(initialRights[3]>=0 && board[castlingRank[3]][initialRights[3]] != BlackRook) FENcastlingRights[3] = -1;
if(initialRights[4]>=0 && board[castlingRank[4]][initialRights[4]] != BlackRook) FENcastlingRights[4] = -1;
- if(initialRights[5]>=0 && board[castlingRank[5]][initialRights[5]] != BlackKing) FENcastlingRights[5] = -1;
+ if(initialRights[5]>=0 && board[castlingRank[5]][initialRights[5]] != BlackUnicorn
+ && board[castlingRank[5]][initialRights[5]] != BlackKing) FENcastlingRights[5] = -1;
FENrulePlies = 0;
while(*p==' ') p++;
if(board[BOARD_HEIGHT-1][i] == BlackKing) blackKingFile = i;
if(board[0 ][i] == WhiteKing) whiteKingFile = i;
}
+ if(gameInfo.variant == VariantTwoKings || gameInfo.variant == VariantKnightmate)
+ whiteKingFile = blackKingFile = BOARD_WIDTH >> 1; // scanning fails in these variants
+ if(whiteKingFile<0 || board[0][whiteKingFile]!=WhiteUnicorn
+ && board[0][whiteKingFile]!=WhiteKing) whiteKingFile = -1;
+ if(blackKingFile<0 || board[BOARD_HEIGHT-1][blackKingFile]!=BlackUnicorn
+ && board[BOARD_HEIGHT-1][blackKingFile]!=BlackKing) blackKingFile = -1;
switch(c) {
case'K':
- for(i=BOARD_RGHT-1; board[0][i]!=WhiteRook && i>whiteKingFile; i--);
+ for(i=BOARD_RGHT-1; i>whiteKingFile && board[0][i]!=WhiteRook; i--);
FENcastlingRights[0] = i != whiteKingFile ? i : -1;
FENcastlingRights[2] = whiteKingFile;
break;
FENcastlingRights[2] = whiteKingFile;
break;
case'k':
- for(i=BOARD_RGHT-1; board[BOARD_HEIGHT-1][i]!=BlackRook && i>blackKingFile; i--);
+ for(i=BOARD_RGHT-1; i>blackKingFile && board[BOARD_HEIGHT-1][i]!=BlackRook; i--);
FENcastlingRights[3] = i != blackKingFile ? i : -1;
FENcastlingRights[5] = blackKingFile;
break;
}
}
}
+ for(i=0; i<nrCastlingRights; i++)
+ if(FENcastlingRights[i] >= 0) initialRights[i] = FENcastlingRights[i];
if (appData.debugMode) {
fprintf(debugFP, "FEN castling rights:");
for(i=0; i<nrCastlingRights; i++)
/* read e.p. field in games that know e.p. capture */
if(gameInfo.variant != VariantShogi && gameInfo.variant != VariantXiangqi &&
- gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier ) {
+ gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier && gameInfo.variant != VariantMakruk ) {
if(*p=='-') {
p++; FENepStatus = EP_NONE;
} else {