* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
typedef enum {
ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
- ArgSettingsFilename, ArgBackupSettingsFile, ArgTwo,
+ ArgSettingsFilename, ArgBackupSettingsFile, ArgTwo, ArgInstall, ArgMaster,
ArgX, ArgY, ArgZ // [HGM] placement: for window-placement options stored relative to main window
} ArgType;
IcsTextMenuEntry icsTextMenuEntry[ICS_TEXT_MENU_SIZE];
int junk;
+unsigned int saveDate;
+unsigned int dateStamp;
Boolean singleList;
+Boolean autoClose;
char *homeDir;
char *firstEngineLine;
char *secondEngineLine;
{ "loadGameFile", ArgFilename, (void *) &appData.loadGameFile, FALSE, INVALID },
{ "", ArgNone, NULL, FALSE, INVALID },
/* keyword arguments */
+ { "saveDate", ArgInt, (void *) &saveDate, TRUE, 0 },
+ { "date", ArgInt, (void *) &dateStamp, FALSE, 0 },
+ { "autoClose", ArgTrue, (void *) &autoClose, FALSE, FALSE },
JAWS_ARGS
{ "whitePieceColor", ArgColor, (void *) 0, TRUE, (ArgIniType) WHITE_PIECE_COLOR },
{ "wpc", ArgColor, (void *) 0, FALSE, INVALID },
{ "soundSeek", ArgFilename, (void *) &appData.soundSeek, TRUE, (ArgIniType) "" },
{ "soundMove", ArgFilename, (void *) &appData.soundMove, TRUE, (ArgIniType) "" },
{ "soundBell", ArgFilename, (void *) &appData.soundBell, TRUE, (ArgIniType) SOUND_BELL },
+ { "soundRoar", ArgFilename, (void *) &appData.soundRoar, TRUE, (ArgIniType) "" },
{ "soundIcsWin", ArgFilename, (void *) &appData.soundIcsWin, TRUE, (ArgIniType) "" },
{ "soundIcsLoss", ArgFilename, (void *) &appData.soundIcsLoss, TRUE, (ArgIniType) "" },
{ "soundIcsDraw", ArgFilename, (void *) &appData.soundIcsDraw, TRUE, (ArgIniType) "" },
{ "secondChessProgramNames", ArgString, (void *) &secondChessProgramNames,
!XBOARD, (ArgIniType) SCP_NAMES },
{ "themeNames", ArgString, (void *) &appData.themeNames, !XBOARD, (ArgIniType) "native -upf false -ub false -ubt false -pid \"\"\n" },
+ { "addMasterOption", ArgMaster, NULL, FALSE, INVALID },
+ { "installEngine", ArgInstall, (void *) &firstChessProgramNames, FALSE, (ArgIniType) "" },
{ "initialMode", ArgString, (void *) &appData.initialMode, FALSE, (ArgIniType) "" },
{ "mode", ArgString, (void *) &appData.initialMode, FALSE, INVALID },
{ "variant", ArgString, (void *) &appData.variant, FALSE, (ArgIniType) "normal" },
{ "useBorder", ArgBoolean, (void *) &appData.useBorder, TRUE, (ArgIniType) FALSE },
{ "ub", ArgBoolean, (void *) &appData.useBorder, FALSE, INVALID },
{ "border", ArgFilename, (void *) &appData.border, TRUE, (ArgIniType) "" },
+ { "finger", ArgFilename, (void *) &appData.finger, FALSE, (ArgIniType) "" },
// [HGM] tournament options
{ "tourneyFile", ArgFilename, (void *) &appData.tourneyFile, FALSE, (ArgIniType) "" },
{ "topLevel", ArgBoolean, (void *) &appData.topLevel, XBOARD, (ArgIniType) TOPLEVEL },
{ "dialogColor", ArgString, (void *) &appData.dialogColor, XBOARD, (ArgIniType) "" },
{ "buttonColor", ArgString, (void *) &appData.buttonColor, XBOARD, (ArgIniType) "" },
+ { "firstDrawDepth", ArgInt, (void *) &appData.drawDepth[0], FALSE, (ArgIniType) 0 },
+ { "secondDrawDepth", ArgInt, (void *) &appData.drawDepth[1], FALSE, (ArgIniType) 0 },
#if ZIPPY
{ "zippyTalk", ArgBoolean, (void *) &appData.zippyTalk, FALSE, (ArgIniType) ZIPPY_TALK },
exit(2);
}
+void
+AppendToSettingsFile (char *line)
+{
+ char buf[MSG_SIZ];
+ FILE *f;
+ int c;
+ if(f = fopen(SETTINGS_FILE, "r")) {
+ do {
+ int i = 0;
+ while((buf[i] = c = fgetc(f)) != '\n' && c != EOF) if(i < MSG_SIZ-1) i++;
+ buf[i] = NULLCHAR;
+ if(!strcmp(line, buf)) return; // line occurs
+ } while(c != EOF);
+ // line did not occur; add it
+ fclose(f);
+ if(f = fopen(SETTINGS_FILE, "a")) {
+ TimeMark now;
+ GetTimeMark(&now);
+ fprintf(f, "-date %10lu\n%s\n", now.sec, line);
+ fclose(f);
+ }
+ }
+}
+
int
ValidateInt(char *s)
{
}
if (ok) {
f = fopen(fullname, "r");
+#ifdef DATADIR
+ if(f == NULL && *fullname != '/') { // when a relative name did not work
+ MySearchPath(DATADIR "/themes/conf", name, fullname); // also look in standard place
+ f = fopen(fullname, "r");
+ }
+#endif
if (f != NULL) {
if (addr != NULL) {
ASSIGN(*addr, fullname);
ParseCommPortSettings(argValue);
break;
+ case ArgMaster:
+ AppendToSettingsFile(argValue);
+ break;
+
+ case ArgInstall:
+ q = *(char **) ad->argLoc;
+ if((saveDate == 0 || saveDate - dateStamp < 0) && !strstr(q, argValue) ) {
+ int l = strlen(q) + strlen(argValue);
+ *(char **) ad->argLoc = malloc(l+2);
+ snprintf(*(char **) ad->argLoc, l+2, "%s%s\n", q, argValue);
+ free(q);
+ }
+ break;
+
case ArgNone:
ExitArgError(_("Unrecognized argument %s"), argValue, TRUE);
break;
appData.savePositionFile = strdup(buf);
}
+ if(autoClose) { // was called for updating settingsfile only
+ if(saveSettingsOnExit) SaveSettings(settingsFileName);
+ exit(0);
+ }
+
/* Finish initialization for fonts and sounds */
CreateFonts();
ArgDescriptor *ad;
char dir[MSG_SIZ], buf[MSG_SIZ];
int mps = appData.movesPerSession;
+ TimeMark now;
+
+ if (!MainWindowUp() && !autoClose) return;
- if (!MainWindowUp()) return;
+ GetTimeMark(&now); saveDate = now.sec;
GetCurrentDirectory(MSG_SIZ, dir);
if(MySearchPath(installDir, name, buf)) {
case ArgNone:
case ArgBackupSettingsFile:
case ArgSettingsFilename: ;
+ case ArgMaster: ;
+ case ArgInstall: ;
}
}
fclose(f);
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
#ifdef WIN32
#include <windows.h>
-int flock(int f, int code);
-#define LOCK_EX 2
-#define SLASH '\\'
+ int flock(int f, int code);
+# define LOCK_EX 2
+# define SLASH '\\'
+
+# ifdef ARC_64BIT
+# define EGBB_NAME "egbbdll64.dll"
+# else
+# define EGBB_NAME "egbbdll.dll"
+# endif
#else
-#include <sys/file.h>
-#define SLASH '/'
+# include <sys/file.h>
+# define SLASH '/'
+
+# include <dlfcn.h>
+# ifdef ARC_64BIT
+# define EGBB_NAME "egbbso64.so"
+# else
+# define EGBB_NAME "egbbso.so"
+# endif
+ // kludge to allow Windows code in back-end by converting it to corresponding Linux code
+# define CDECL
+# define HMODULE void *
+# define LoadLibrary(x) dlopen(x, RTLD_LAZY)
+# define GetProcAddress dlsym
#endif
static void ExcludeClick P((int index));
void ToggleSecond P((void));
void PauseEngine P((ChessProgramState *cps));
-static int NonStandardBoardSize P((void));
+static int NonStandardBoardSize P((VariantClass v, int w, int h, int s));
#ifdef WIN32
extern void ConsoleCreate();
extern int chatCount;
int chattingPartner;
char marker[BOARD_RANKS][BOARD_FILES]; /* [HGM] marks for target squares */
+char legal[BOARD_RANKS][BOARD_FILES]; /* [HGM] legal target squares */
char lastMsg[MSG_SIZ];
ChessSquare pieceSweep = EmptySquare;
ChessSquare promoSweep = EmptySquare, defaultPromoChoice;
int promoDefaultAltered;
int keepInfo = 0; /* [HGM] to protect PGN tags in auto-step game analysis */
+static int initPing = -1;
/* States for ics_getting_history */
#define H_FALSE 0
case VariantShatranj:
case VariantCourier:
case VariantMakruk:
+ case VariantASEAN:
case VariantGrand:
flags &= ~F_ALL_CASTLE_OK;
break;
BlackKing, BlackMan, BlackKnight, BlackRook }
};
+ChessSquare aseanArray[2][BOARD_FILES] = { /* [HGM] (movGen knows about Shatranj Q and P) */
+ { WhiteRook, WhiteKnight, WhiteMan, WhiteFerz,
+ WhiteKing, WhiteMan, WhiteKnight, WhiteRook },
+ { BlackRook, BlackKnight, BlackMan, BlackFerz,
+ BlackKing, BlackMan, BlackKnight, BlackRook }
+};
+
+ChessSquare lionArray[2][BOARD_FILES] = {
+ { WhiteRook, WhiteLion, WhiteBishop, WhiteQueen,
+ WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
+ { BlackRook, BlackLion, BlackBishop, BlackQueen,
+ BlackKing, BlackBishop, BlackKnight, BlackRook }
+};
+
#if (BOARD_FILES>=10)
ChessSquare ShogiArray[2][BOARD_FILES] = {
BlackMarshall, BlackAngel, BlackBishop, BlackKnight, EmptySquare }
};
+ChessSquare ChuChessArray[2][BOARD_FILES] = {
+ { WhiteMan, WhiteKnight, WhiteBishop, WhiteCardinal, WhiteLion,
+ WhiteQueen, WhiteDragon, WhiteBishop, WhiteKnight, WhiteMan },
+ { BlackMan, BlackKnight, BlackBishop, BlackDragon, BlackQueen,
+ BlackLion, BlackCardinal, BlackBishop, BlackKnight, BlackMan }
+};
+
#ifdef GOTHIC
ChessSquare GothicArray[2][BOARD_FILES] = {
{ WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteMarshall,
{ BlackRook, BlackKnight, BlackAlfil, BlackBishop, BlackMan, BlackKing,
BlackFerz, BlackWazir, BlackBishop, BlackAlfil, BlackKnight, BlackRook }
};
+ChessSquare ChuArray[6][BOARD_FILES] = {
+ { WhiteLance, WhiteUnicorn, WhiteMan, WhiteFerz, WhiteWazir, WhiteKing,
+ WhiteAlfil, WhiteWazir, WhiteFerz, WhiteMan, WhiteUnicorn, WhiteLance },
+ { BlackLance, BlackUnicorn, BlackMan, BlackFerz, BlackWazir, BlackAlfil,
+ BlackKing, BlackWazir, BlackFerz, BlackMan, BlackUnicorn, BlackLance },
+ { WhiteCannon, EmptySquare, WhiteBishop, EmptySquare, WhiteNightrider, WhiteMarshall,
+ WhiteAngel, WhiteNightrider, EmptySquare, WhiteBishop, EmptySquare, WhiteCannon },
+ { BlackCannon, EmptySquare, BlackBishop, EmptySquare, BlackNightrider, BlackAngel,
+ BlackMarshall, BlackNightrider, EmptySquare, BlackBishop, EmptySquare, BlackCannon },
+ { WhiteFalcon, WhiteSilver, WhiteRook, WhiteCardinal, WhiteDragon, WhiteLion,
+ WhiteQueen, WhiteDragon, WhiteCardinal, WhiteRook, WhiteSilver, WhiteFalcon },
+ { BlackFalcon, BlackSilver, BlackRook, BlackCardinal, BlackDragon, BlackQueen,
+ BlackLion, BlackDragon, BlackCardinal, BlackRook, BlackSilver, BlackFalcon }
+};
#else // !(BOARD_FILES>=12)
#define CourierArray CapablancaArray
+#define ChuArray CapablancaArray
#endif // !(BOARD_FILES>=12)
/* [HGM] debug */
cps->debug = FALSE;
+ cps->drawDepth = appData.drawDepth[n];
cps->supportsNPS = UNKNOWN;
cps->memSize = FALSE;
cps->maxCores = FALSE;
cps->scoreIsAbsolute = appData.scoreIsAbsolute[n]; /* [AS] */
cps->isUCI = appData.isUCI[n]; /* [AS] */
cps->hasOwnBookUCI = appData.hasOwnBookUCI[n]; /* [AS] */
+ cps->highlight = 0;
if (appData.protocolVersion[n] > PROTOVER
|| appData.protocolVersion[n] < 1)
void
Load (ChessProgramState *cps, int i)
{
- char *p, *q, buf[MSG_SIZ], command[MSG_SIZ], buf2[MSG_SIZ];
+ char *p, *q, buf[MSG_SIZ], command[MSG_SIZ], buf2[MSG_SIZ], buf3[MSG_SIZ], jar;
if(engineLine && engineLine[0]) { // an engine was selected from the combo box
snprintf(buf, MSG_SIZ, "-fcp %s", engineLine);
SwapEngines(i); // kludge to parse -f* / -first* like it is -s* / -second*
p[-1] = SLASH;
if(SLASH == '/' && p - engineName > 1) *(p -= 2) = '.'; // for XBoard use ./exeName as command after split!
} else { ASSIGN(appData.directory[i], "."); }
+ jar = (strstr(p, ".jar") == p + strlen(p) - 4);
if(params[0]) {
if(strchr(p, ' ') && !strchr(p, '"')) snprintf(buf2, MSG_SIZ, "\"%s\"", p), p = buf2; // quote if it contains spaces
snprintf(command, MSG_SIZ, "%s %s", p, params);
p = command;
}
+ if(jar) { snprintf(buf3, MSG_SIZ, "java -jar %s", p); p = buf3; }
ASSIGN(appData.chessProgram[i], p);
appData.isUCI[i] = isUCI;
appData.protocolVersion[i] = v1 ? 1 : PROTOVER;
case VariantCapablanca: /* [HGM] should work */
case VariantCourier: /* [HGM] initial forced moves not implemented */
case VariantShogi: /* [HGM] could still mate with pawn drop */
+ case VariantChu: /* [HGM] experimental */
case VariantKnightmate: /* [HGM] should work */
case VariantCylinder: /* [HGM] untested */
case VariantFalcon: /* [HGM] untested */
case Variant3Check: /* should work except for win condition */
case VariantShatranj: /* should work except for all win conditions */
case VariantMakruk: /* should work except for draw countdown */
+ case VariantASEAN : /* should work except for draw countdown */
case VariantBerolina: /* might work if TestLegality is off */
case VariantCapaRandom: /* should work */
case VariantJanus: /* should work */
case VariantSChess: /* S-Chess, should work */
case VariantGrand: /* should work */
case VariantSpartan: /* should work */
+ case VariantLion: /* should work */
+ case VariantChuChess: /* should work */
break;
}
}
NextTourneyGame(-1, &dummy);
ReserveGame(-1, 0);
if(nextGame <= appData.matchGames) {
- DisplayNote(_("You restarted an already completed tourney\nOne more cycle will now be added to it\nGames commence in 10 sec"));
+ DisplayNote(_("You restarted an already completed tourney.\nOne more cycle will now be added to it.\nGames commence in 10 sec."));
matchMode = mode;
ScheduleDelayedEvent(NextMatchGame, 10000);
return;
char buf[MSG_SIZ];
int err, len;
+ if(!appData.icsActive && !appData.noChessProgram && !appData.matchMode && // mode involves only first engine
+ !strcmp(appData.variant, "normal") && // no explicit variant request
+ appData.NrRanks == -1 && appData.NrFiles == -1 && appData.holdingsSize == -1 && // no size overrides requested
+ !SupportedVariant(first.variants, VariantNormal, 8, 8, 0, first.protocolVersion, "") && // but 'normal' won't work with engine
+ !SupportedVariant(first.variants, VariantFischeRandom, 8, 8, 0, first.protocolVersion, "") ) { // nor will Chess960
+ char c, *q = first.variants, *p = strchr(q, ',');
+ if(p) *p = NULLCHAR;
+ if(StringToVariant(q) != VariantUnknown) { // the engine can play a recognized variant, however
+ int w, h, s;
+ if(sscanf(q, "%dx%d+%d_%c", &w, &h, &s, &c) == 4) // get size overrides the engine needs with it (if any)
+ appData.NrFiles = w, appData.NrRanks = h, appData.holdingsSize = s, q = strchr(q, '_') + 1;
+ ASSIGN(appData.variant, q); // fake user requested the first variant played by the engine
+ Reset(TRUE, FALSE); // and re-initialize
+ }
+ if(p) *p = ',';
+ }
+
InitChessProgram(&first, startedFromSetupPosition);
if(!appData.noChessProgram) { /* [HGM] tidy: redo program version to use name from myname feature */
return retbuf;
}
+char engineVariant[MSG_SIZ];
char *variantNames[] = VARIANT_NAMES;
char *
VariantName (VariantClass v)
{
+ if(v == VariantUnknown || *engineVariant) return engineVariant;
return variantNames[v];
}
found = TRUE;
} else
for (i=0; i<sizeof(variantNames)/sizeof(char*); i++) {
- if (StrCaseStr(e, variantNames[i])) {
+ if (p = StrCaseStr(e, variantNames[i])) {
+ if(p && i >= VariantShogi && isalpha(p[strlen(variantNames[i])])) continue;
v = (VariantClass) i;
found = TRUE;
break;
} else {
char tmp[MSG_SIZ];
if(gameMode == IcsObserving) // restore original ICS messages
+ /* TRANSLATORS: to 'kibitz' is to send a message to all players and the game observers */
snprintf(tmp, MSG_SIZ, "%s kibitzes: %s", star_match[0], parse);
else
+ /* TRANSLATORS: to 'kibitz' is to send a message to all players and the game observers */
snprintf(tmp, MSG_SIZ, _("your opponent kibitzes: %s"), parse);
SendToPlayer(tmp, strlen(tmp));
}
default:
break;
case MT_CHECK:
- if(gameInfo.variant != VariantShogi)
+ if(!IS_SHOGI(gameInfo.variant))
strcat(parseList[moveNum - 1], "+");
break;
case MT_CHECKMATE:
char buf[MSG_SIZ];
if(moveList[moveNum][1] == '@' && moveList[moveNum][0] == '@') {
+ if(gameInfo.variant == VariantLion || gameInfo.variant == VariantChuChess || gameInfo.variant == VariantChu) {
+ sprintf(buf, "%s@@@@\n", cps->useUsermove ? "usermove " : "");
+ SendToProgram(buf, cps);
+ return;
+ }
// null move in variant where engine does not understand it (for analysis purposes)
SendBoard(cps, moveNum + 1); // send position after move in stead.
return;
}
else SendToProgram(moveList[moveNum], cps);
} else
+ if(moveList[moveNum][4] == ';') { // [HGM] lion: move is double-step over intermediate square
+ snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d\n", moveList[moveNum][0], moveList[moveNum][1] - '0', // convert to two moves
+ moveList[moveNum][5], moveList[moveNum][6] - '0',
+ moveList[moveNum][5], moveList[moveNum][6] - '0',
+ moveList[moveNum][2], moveList[moveNum][3] - '0');
+ SendToProgram(buf, cps);
+ } else
if(BOARD_HEIGHT > 10) { // [HGM] big: convert ranks to double-digit where needed
if(moveList[moveNum][1] == '@' && (BOARD_HEIGHT < 16 || moveList[moveNum][0] <= 'Z')) { // drop move
if(moveList[moveNum][0]== '@') snprintf(buf, MSG_SIZ, "@@@@\n"); else
break;
case WhitePromotion:
case BlackPromotion:
- if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk)
+ if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
+ gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN)
snprintf(user_move, MSG_SIZ, "%c%c%c%c=%c\n",
AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,
PieceToChar(WhiteFerz));
SendToICS(ics_prefix);
SendToICS(buf);
if(startedFromSetupPosition || backwardMostMove != 0) {
- fen = PositionToFEN(backwardMostMove, NULL);
+ fen = PositionToFEN(backwardMostMove, NULL, 1);
if(ics_type == ICS_ICC) { // on ICC we can simply send a complete FEN to set everything
snprintf(buf, MSG_SIZ,"loadfen %s\n", fen);
SendToICS(buf);
SendToICS(ics_type == ICS_ICC ? "tag result Game in progress\n" : "commit\n");
}
+int killX = -1, killY = -1; // [HGM] lion: used for passing e.p. capture square to MakeMove
+
void
CoordsToComputerAlgebraic (int rf, int ff, int rt, int ft, char promoChar, char move[7])
{
if (promoChar == 'x' || promoChar == NULLCHAR) {
sprintf(move, "%c%c%c%c\n",
AAA + ff, ONE + rf, AAA + ft, ONE + rt);
+ if(killX >= 0 && killY >= 0) sprintf(move+4, ";%c%c\n", AAA + killX, ONE + killY);
} else {
sprintf(move, "%c%c%c%c%c\n",
AAA + ff, ONE + rf, AAA + ft, ONE + rt, promoChar);
}
-static int lastX, lastY, selectFlag, dragging;
+static int lastX, lastY, lastLeftX, lastLeftY, selectFlag;
+int dragging;
+static ClickType lastClickType;
+
+int
+Partner (ChessSquare *p)
+{ // change piece into promotion partner if one shogi-promotes to the other
+ int stride = gameInfo.variant == VariantChu ? 22 : 11;
+ ChessSquare partner;
+ partner = (*p/stride & 1 ? *p - stride : *p + stride);
+ if(PieceToChar(*p) != '+' && PieceToChar(partner) != '+') return 0;
+ *p = partner;
+ return 1;
+}
void
Sweep (int step)
{
ChessSquare king = WhiteKing, pawn = WhitePawn, last = promoSweep;
+ static int toggleFlag;
if(gameInfo.variant == VariantKnightmate) king = WhiteUnicorn;
if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway) king = EmptySquare;
if(promoSweep >= BlackPawn) king = WHITE_TO_BLACK king, pawn = WHITE_TO_BLACK pawn;
if(gameInfo.variant == VariantSpartan && pawn == BlackPawn) pawn = BlackLance, king = EmptySquare;
- if(fromY != BOARD_HEIGHT-2 && fromY != 1) pawn = EmptySquare;
+ if(fromY != BOARD_HEIGHT-2 && fromY != 1 && gameInfo.variant != VariantChuChess) pawn = EmptySquare;
+ if(!step) toggleFlag = Partner(&last); // piece has shogi-promotion
do {
- promoSweep -= step;
+ if(step && !(toggleFlag && Partner(&promoSweep))) promoSweep -= step;
if(promoSweep == EmptySquare) promoSweep = BlackPawn; // wrap
else if((int)promoSweep == -1) promoSweep = WhiteKing;
else if(promoSweep == BlackPawn && step < 0) promoSweep = WhitePawn;
else if(promoSweep == WhiteKing && step > 0) promoSweep = BlackKing;
if(!step) step = -1;
} while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || promoSweep == pawn ||
- appData.testLegality && (promoSweep == king ||
- gameInfo.variant == VariantShogi && promoSweep != PROMOTED last && last != PROMOTED promoSweep && last != promoSweep));
+ !toggleFlag && PieceToChar(promoSweep) == '+' || // skip promoted versions of other
+ appData.testLegality && (promoSweep == king || gameInfo.variant != VariantChuChess &&
+ (promoSweep == WhiteLion || promoSweep == BlackLion)));
if(toX >= 0) {
int victim = boards[currentMove][toY][toX];
boards[currentMove][toY][toX] = promoSweep;
case WhiteNonPromotion:
case BlackNonPromotion:
case NormalMove:
+ case FirstLeg:
case WhiteCapturesEnPassant:
case BlackCapturesEnPassant:
case WhiteKingSideCastle:
if (appData.testLegality) {
return (*moveType != IllegalMove);
} else {
- return !(*fromX == *toX && *fromY == *toY) && boards[moveNum][*fromY][*fromX] != EmptySquare &&
+ return !(*fromX == *toX && *fromY == *toY && killX < 0) && boards[moveNum][*fromY][*fromX] != EmptySquare &&
+ // [HGM] lion: if this is a double move we are less critical
WhiteOnMove(moveNum) == (boards[moveNum][*fromY][*fromX] < BlackPawn);
}
InitPosition (int redraw)
{
ChessSquare (* pieces)[BOARD_FILES];
- int i, j, pawnRow, overrule,
+ int i, j, pawnRow=1, pieceRows=1, overrule,
oldx = gameInfo.boardWidth,
oldy = gameInfo.boardHeight,
oldh = gameInfo.holdingsWidth;
case VariantMakruk:
pieces = makrukArray;
nrCastlingRights = 0;
- startedFromSetupPosition = TRUE;
SetCharTable(pieceToChar, "PN.R.M....SKpn.r.m....sk");
break;
+ case VariantASEAN:
+ pieces = aseanArray;
+ nrCastlingRights = 0;
+ SetCharTable(pieceToChar, "PN.R.Q....BKpn.r.q....bk");
+ break;
case VariantTwoKings:
pieces = twoKingsArray;
break;
nrCastlingRights = 0;
SetCharTable(pieceToChar, "PNBRLS...G.++++++Kpnbrls...g.++++++k");
break;
+ case VariantChu:
+ pieces = ChuArray; pieceRows = 3;
+ gameInfo.boardWidth = 12;
+ gameInfo.boardHeight = 12;
+ nrCastlingRights = 0;
+ SetCharTable(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN+.++.++++++++++.+++++K"
+ "p.brqsexogcathd.vmlifn+.++.++++++++++.+++++k");
+ break;
case VariantCourier:
pieces = CourierArray;
gameInfo.boardWidth = 12;
pieces = SpartanArray;
SetCharTable(pieceToChar, "PNBRQ................K......lwg.....c...h..k");
break;
+ case VariantLion:
+ pieces = lionArray;
+ SetCharTable(pieceToChar, "PNBRQ................LKpnbrq................lk");
+ break;
+ case VariantChuChess:
+ pieces = ChuChessArray;
+ gameInfo.boardWidth = 10;
+ gameInfo.boardHeight = 10;
+ SetCharTable(pieceToChar, "PNBRQ.....M.+++......LKpnbrq.....m.+++......lk");
+ break;
case VariantFairy:
pieces = fairyArray;
SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVLSUKpnbrqfeacwmohijgdvlsuk");
pawnRow = gameInfo.boardHeight - 7; /* seems to work in all common variants */
if(pawnRow < 1) pawnRow = 1;
- if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand) pawnRow = 2;
+ if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN ||
+ gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess) pawnRow = 2;
+ if(gameInfo.variant == VariantChu) pawnRow = 3;
/* User pieceToChar list overrules defaults */
if(appData.pieceToCharTable != NULL)
initialPosition[i][j] = s;
if(j < BOARD_LEFT || j >= BOARD_RGHT || overrule) continue;
- initialPosition[gameInfo.variant == VariantGrand][j] = pieces[0][j-gameInfo.holdingsWidth];
+ initialPosition[gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess][j] = pieces[0][j-gameInfo.holdingsWidth];
initialPosition[pawnRow][j] = WhitePawn;
initialPosition[BOARD_HEIGHT-pawnRow-1][j] = gameInfo.variant == VariantSpartan ? BlackLance : BlackPawn;
if(gameInfo.variant == VariantXiangqi) {
}
}
}
- if(gameInfo.variant == VariantGrand) {
+ if(gameInfo.variant == VariantChu) {
+ if(j == (BOARD_WIDTH-2)/3 || j == BOARD_WIDTH - (BOARD_WIDTH+1)/3)
+ initialPosition[pawnRow+1][j] = WhiteCobra,
+ initialPosition[BOARD_HEIGHT-pawnRow-2][j] = BlackCobra;
+ for(i=1; i<pieceRows; i++) {
+ initialPosition[i][j] = pieces[2*i][j-gameInfo.holdingsWidth];
+ initialPosition[BOARD_HEIGHT-1-i][j] = pieces[2*i+1][j-gameInfo.holdingsWidth];
+ }
+ }
+ if(gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess) {
if(j==BOARD_LEFT || j>=BOARD_RGHT-1) {
initialPosition[0][j] = WhiteRook;
initialPosition[BOARD_HEIGHT-1][j] = BlackRook;
}
}
- initialPosition[BOARD_HEIGHT-1-(gameInfo.variant == VariantGrand)][j] = pieces[1][j-gameInfo.holdingsWidth];
+ initialPosition[BOARD_HEIGHT-1-(gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess)][j] = pieces[1][j-gameInfo.holdingsWidth];
}
+ if(gameInfo.variant == VariantChuChess) initialPosition[0][BOARD_WIDTH/2] = WhiteKing, initialPosition[BOARD_HEIGHT-1][BOARD_WIDTH/2-1] = BlackKing;
if( (gameInfo.variant == VariantShogi) && !overrule ) {
j=BOARD_LEFT+1;
char message[MSG_SIZ];
if (cps->useSetboard) {
- char* fen = PositionToFEN(moveNum, cps->fenOverride);
+ char* fen = PositionToFEN(moveNum, cps->fenOverride, 1);
snprintf(message, MSG_SIZ,"setboard %s\n", fen);
SendToProgram(message, cps);
free(fen);
DefaultPromoChoice (int white)
{
ChessSquare result;
- if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk)
+ if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
+ gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN)
result = WhiteFerz; // no choice
else if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway)
result= WhiteKing; // in Suicide Q is the last thing we want
/* [HGM] rewritten IsPromotion to only flag promotions that offer a choice */
/* [HGM] add Shogi promotions */
int promotionZoneSize=1, highestPromotingPiece = (int)WhitePawn;
- ChessSquare piece;
+ ChessSquare piece, partner;
ChessMove moveType;
Boolean premove;
return FALSE;
piece = boards[currentMove][fromY][fromX];
- if(gameInfo.variant == VariantShogi) {
+ if(gameInfo.variant == VariantChu) {
+ int p = piece >= BlackPawn ? BLACK_TO_WHITE piece : piece;
+ promotionZoneSize = BOARD_HEIGHT/3;
+ highestPromotingPiece = (p >= WhiteLion || PieceToChar(piece + 22) == '.') ? WhitePawn : WhiteLion;
+ } else if(gameInfo.variant == VariantShogi || gameInfo.variant == VariantChuChess) {
promotionZoneSize = BOARD_HEIGHT/3;
- highestPromotingPiece = (int)WhiteFerz;
- } else if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand) {
+ highestPromotingPiece = (int)WhiteAlfil;
+ } else if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess) {
promotionZoneSize = 3;
}
if((int)piece >= BlackPawn) {
if(toY >= promotionZoneSize && fromY >= promotionZoneSize)
return FALSE;
+ if(fromY < promotionZoneSize && gameInfo.variant == VariantChuChess) return FALSE;
highestPromotingPiece = WHITE_TO_BLACK highestPromotingPiece;
} else {
if( toY < BOARD_HEIGHT - promotionZoneSize &&
fromY < BOARD_HEIGHT - promotionZoneSize) return FALSE;
+ if(fromY >= BOARD_HEIGHT - promotionZoneSize && gameInfo.variant == VariantChuChess)
+ return FALSE;
}
if( (int)piece > highestPromotingPiece ) return FALSE; // non-promoting piece
}
// we either have a choice what to promote to, or (in Shogi) whether to promote
- if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk) {
- *promoChoice = PieceToChar(BlackFerz); // no choice
+ if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
+ gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN) {
+ ChessSquare p=BlackFerz; // no choice
+ while(p < EmptySquare) { //but make sure we use piece that exists
+ *promoChoice = PieceToChar(p++);
+ if(*promoChoice != '.') break;
+ }
return FALSE;
}
// no sense asking what we must promote to if it is going to explode...
}
// give caller the default choice even if we will not make it
*promoChoice = ToLower(PieceToChar(defaultPromoChoice));
- if(gameInfo.variant == VariantShogi) *promoChoice = (defaultPromoChoice == piece ? '=' : '+');
+ partner = piece; // pieces can promote if the pieceToCharTable says so
+ if(IS_SHOGI(gameInfo.variant)) *promoChoice = (defaultPromoChoice == piece && sweepSelect ? '=' : '+'); // obsolete?
+ else if(Partner(&partner)) *promoChoice = (defaultPromoChoice == piece && sweepSelect ? NULLCHAR : '+');
if( sweepSelect && gameInfo.variant != VariantGreat
&& gameInfo.variant != VariantGrand
&& gameInfo.variant != VariantSuper) return FALSE;
gameMode == IcsPlayingBlack && WhiteOnMove(currentMove);
if(appData.testLegality && !premove) {
moveType = LegalityTest(boards[currentMove], PosFlags(currentMove),
- fromY, fromX, toY, toX, gameInfo.variant == VariantShogi ? '+' : NULLCHAR);
+ fromY, fromX, toY, toX, IS_SHOGI(gameInfo.variant) || gameInfo.variant == VariantChuChess ? '+' : NULLCHAR);
+ if(moveType == IllegalMove) *promoChoice = NULLCHAR; // could be the fact we promoted was illegal
if(moveType != WhitePromotion && moveType != BlackPromotion)
return FALSE;
}
}
void
+MarkByFEN(char *fen)
+{
+ int r, f;
+ if(!appData.markers || !appData.highlightDragging) return;
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) legal[r][f] = 0;
+ r=BOARD_HEIGHT-1; f=BOARD_LEFT;
+ while(*fen) {
+ int s = 0;
+ marker[r][f] = 0;
+ if(*fen == 'M') legal[r][f] = 2; else // request promotion choice
+ if(*fen >= 'A' && *fen <= 'Z') legal[r][f] = 1; else
+ if(*fen >= 'a' && *fen <= 'z') *fen += 'A' - 'a';
+ if(*fen == '/' && f > BOARD_LEFT) f = BOARD_LEFT, r--; else
+ if(*fen == 'T') marker[r][f++] = 0; else
+ if(*fen == 'Y') marker[r][f++] = 1; else
+ if(*fen == 'G') marker[r][f++] = 3; else
+ if(*fen == 'B') marker[r][f++] = 4; else
+ if(*fen == 'C') marker[r][f++] = 5; else
+ if(*fen == 'M') marker[r][f++] = 6; else
+ if(*fen == 'W') marker[r][f++] = 7; else
+ if(*fen == 'D') marker[r][f++] = 8; else
+ if(*fen == 'R') marker[r][f++] = 2; else {
+ while(*fen <= '9' && *fen >= '0') s = 10*s + *fen++ - '0';
+ f += s; fen -= s>0;
+ }
+ while(f >= BOARD_RGHT) f -= BOARD_RGHT - BOARD_LEFT, r--;
+ if(r < 0) break;
+ fen++;
+ }
+ DrawPosition(TRUE, NULL);
+}
+
+static char baseMarker[BOARD_RANKS][BOARD_FILES], baseLegal[BOARD_RANKS][BOARD_FILES];
+
+void
Mark (Board board, int flags, ChessMove kind, int rf, int ff, int rt, int ft, VOIDSTAR closure)
{
typedef char Markers[BOARD_RANKS][BOARD_FILES];
Markers *m = (Markers *) closure;
- if(rf == fromY && ff == fromX)
+ if(rf == fromY && ff == fromX && (killX < 0 && !(rt == rf && ft == ff) || abs(ft-killX) < 2 && abs(rt-killY) < 2))
(*m)[rt][ft] = 1 + (board[rt][ft] != EmptySquare
|| kind == WhiteCapturesEnPassant
- || kind == BlackCapturesEnPassant);
+ || kind == BlackCapturesEnPassant) + 3*(kind == FirstLeg && killX < 0);
else if(flags & F_MANDATORY_CAPTURE && board[rt][ft] != EmptySquare) (*m)[rt][ft] = 3;
}
+static int hoverSavedValid;
+
void
MarkTargetSquares (int clear)
{
- int x, y;
- if(clear) // no reason to ever suppress clearing
- for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) marker[y][x] = 0;
- if(!appData.markers || !appData.highlightDragging || appData.icsActive && gameInfo.variant < VariantShogi ||
- !appData.testLegality || gameMode == EditPosition) return;
- if(!clear) {
+ int x, y, sum=0;
+ if(clear) { // no reason to ever suppress clearing
+ for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) sum += marker[y][x], marker[y][x] = 0;
+ hoverSavedValid = 0;
+ if(!sum) return; // nothing was cleared,no redraw needed
+ } else {
int capt = 0;
+ if(!appData.markers || !appData.highlightDragging || appData.icsActive && gameInfo.variant < VariantShogi ||
+ !appData.testLegality || gameMode == EditPosition) return;
GenLegal(boards[currentMove], PosFlags(currentMove), Mark, (void*) marker, EmptySquare);
if(PosFlags(0) & F_MANDATORY_CAPTURE) {
for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) if(marker[y][x]>1) capt++;
int
CanPromote (ChessSquare piece, int y)
{
+ int zone = (gameInfo.variant == VariantChuChess ? 3 : 1);
if(gameMode == EditPosition) return FALSE; // no promotions when editing position
// some variants have fixed promotion piece, no promotion at all, or another selection mechanism
- if(gameInfo.variant == VariantShogi || gameInfo.variant == VariantXiangqi ||
+ if(IS_SHOGI(gameInfo.variant) || gameInfo.variant == VariantXiangqi ||
gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat ||
gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
- gameInfo.variant == VariantMakruk) return FALSE;
- return (piece == BlackPawn && y == 1 ||
- piece == WhitePawn && y == BOARD_HEIGHT-2 ||
+ gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN) return FALSE;
+ return (piece == BlackPawn && y <= zone ||
+ piece == WhitePawn && y >= BOARD_HEIGHT-1-zone ||
piece == BlackLance && y == 1 ||
piece == WhiteLance && y == BOARD_HEIGHT-2 );
}
void
+HoverEvent (int xPix, int yPix, int x, int y)
+{
+ static int oldX = -1, oldY = -1, oldFromX = -1, oldFromY = -1;
+ int r, f;
+ if(!first.highlight) return;
+ if(fromX != oldFromX || fromY != oldFromY) oldX = oldY = -1; // kludge to fake entry on from-click
+ if(x == oldX && y == oldY) return; // only do something if we enter new square
+ oldFromX = fromX; oldFromY = fromY;
+ if(oldX == -1 && oldY == -1 && x == fromX && y == fromY) { // record markings after from-change
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++)
+ baseMarker[r][f] = marker[r][f], baseLegal[r][f] = legal[r][f];
+ hoverSavedValid = 1;
+ } else if(oldX != x || oldY != y) {
+ // [HGM] lift: entered new to-square; redraw arrow, and inform engine
+ if(hoverSavedValid) // don't restore markers that are supposed to be cleared
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++)
+ marker[r][f] = baseMarker[r][f], legal[r][f] = baseLegal[r][f];
+ if((marker[y][x] == 2 || marker[y][x] == 6) && legal[y][x]) {
+ char buf[MSG_SIZ];
+ snprintf(buf, MSG_SIZ, "hover %c%d\n", x + AAA, y + ONE - '0');
+ SendToProgram(buf, &first);
+ }
+ oldX = x; oldY = y;
+// SetHighlights(fromX, fromY, x, y);
+ }
+}
+
+void ReportClick(char *action, int x, int y)
+{
+ char buf[MSG_SIZ]; // Inform engine of what user does
+ int r, f;
+ if(action[0] == 'l') // mark any target square of a lifted piece as legal to-square, clear markers
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) legal[r][f] = 1, marker[r][f] = 0;
+ if(!first.highlight || gameMode == EditPosition) return;
+ snprintf(buf, MSG_SIZ, "%s %c%d%s\n", action, x+AAA, y+ONE-'0', controlKey && action[0]=='p' ? "," : "");
+ SendToProgram(buf, &first);
+}
+
+void
LeftClick (ClickType clickType, int xPix, int yPix)
{
int x, y;
prevClickTime = lastClickTime; GetTimeMark(&lastClickTime);
if (clickType == Press) ErrorPopDown();
+ lastClickType = clickType, lastLeftX = xPix, lastLeftY = yPix; // [HGM] alien: remember state
x = EventToSquare(xPix, BOARD_WIDTH);
y = EventToSquare(yPix, BOARD_HEIGHT);
if(gameMode == AnalyzeMode && (pausing || controlKey) && first.excludeMoves) { // use pause state to exclude moves
doubleClick = TRUE; gatingPiece = boards[currentMove][y][x];
}
- fromX = x; fromY = y; toX = toY = -1;
+ fromX = x; fromY = y; toX = toY = killX = killY = -1;
if(!appData.oneClick || !OnlyMove(&x, &y, FALSE) ||
// even if only move, we treat as normal when this would trigger a promotion popup, to allow sweep selection
appData.sweepSelect && CanPromote(boards[currentMove][fromY][fromX], fromY) && originalY != y) {
/* First square */
if (OKToStartUserMove(fromX, fromY)) {
second = 0;
+ ReportClick("lift", x, y);
MarkTargetSquares(0);
if(gameMode == EditPosition && controlKey) gatingPiece = boards[currentMove][fromY][fromX];
DragPieceBegin(xPix, yPix, FALSE); dragging = 1;
fromP = boards[currentMove][fromY][fromX];
toP = boards[currentMove][y][x];
frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom || gameInfo.variant == VariantSChess;
- if ((WhitePawn <= fromP && fromP <= WhiteKing &&
+ if( (killX < 0 || x != fromX || y != fromY) && // [HGM] lion: do not interpret igui as deselect!
+ ((WhitePawn <= fromP && fromP <= WhiteKing &&
WhitePawn <= toP && toP <= WhiteKing &&
!(fromP == WhiteKing && toP == WhiteRook && frc) &&
!(fromP == WhiteRook && toP == WhiteKing && frc)) ||
(BlackPawn <= fromP && fromP <= BlackKing &&
BlackPawn <= toP && toP <= BlackKing &&
!(fromP == BlackRook && toP == BlackKing && frc) && // allow also RxK as FRC castling
- !(fromP == BlackKing && toP == BlackRook && frc))) {
+ !(fromP == BlackKing && toP == BlackRook && frc)))) {
/* Clicked again on same color piece -- changed his mind */
second = (x == fromX && y == fromY);
+ killX = killY = -1;
if(second && gameMode == AnalyzeMode && SubtractTimeMarks(&lastClickTime, &prevClickTime) < 200) {
second = FALSE; // first double-click rather than scond click
doubleClick = first.excludeMoves; // used by UserMoveEvent to recognize exclude moves
else gatingPiece = doubleClick ? fromP : EmptySquare;
fromX = x;
fromY = y; dragging = 1;
+ ReportClick("lift", x, y);
MarkTargetSquares(0);
DragPieceBegin(xPix, yPix, FALSE);
if(appData.sweepSelect && CanPromote(piece = boards[currentMove][y][x], y)) {
if(x < BOARD_LEFT || x >= BOARD_RGHT) return;
}
- if (clickType == Release && x == fromX && y == fromY) {
+ if (clickType == Release && x == fromX && y == fromY && killX < 0) {
DragPieceEnd(xPix, yPix); dragging = 0;
if(clearFlag) {
// a deferred attempt to click-click move an empty square on top of a piece
clearFlag = 0;
+ if(gameMode != EditPosition && !appData.testLegality && !legal[y][x] && (x != killX || y != killY) && !sweepSelecting) {
+ if(dragging) DragPieceEnd(xPix, yPix), dragging = 0;
+ DisplayMessage(_("only marked squares are legal"),"");
+ DrawPosition(TRUE, NULL);
+ return; // ignore to-click
+ }
+
/* we now have a different from- and (possibly off-board) to-square */
/* Completed move */
if(!sweepSelecting) {
toX = x;
toY = y;
- } else sweepSelecting = 0; // this must be the up-click corresponding to the down-click that started the sweep
+ }
+
+ piece = boards[currentMove][fromY][fromX];
saveAnimate = appData.animate;
if (clickType == Press) {
+ if(gameInfo.variant == VariantChuChess && piece != WhitePawn && piece != BlackPawn) defaultPromoChoice = piece;
if(gameMode == EditPosition && boards[currentMove][fromY][fromX] == EmptySquare) {
// must be Edit Position mode with empty-square selected
fromX = x; fromY = y; DragPieceBegin(xPix, yPix, FALSE); dragging = 1; // consider this a new attempt to drag
if(x >= BOARD_LEFT && x < BOARD_RGHT) clearFlag = 1; // and defer click-click move of empty-square to up-click
return;
}
- if(HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, FALSE)) {
+ if(dragging == 2) { // [HGM] lion: just turn buttonless drag into normal drag, and let release to the job
+ return;
+ }
+ if(x == killX && y == killY) { // second click on this square, which was selected as first-leg target
+ killX = killY = -1; // this informs us no second leg is coming, so treat as to-click without intermediate
+ } else
+ if(marker[y][x] == 5) return; // [HGM] lion: to-click on cyan square; defer action to release
+ if(legal[y][x] == 2 || HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, FALSE)) {
if(appData.sweepSelect) {
- ChessSquare piece = boards[currentMove][fromY][fromX];
promoSweep = defaultPromoChoice;
- if(PieceToChar(PROMOTED piece) == '+') promoSweep = PROMOTED piece;
+ if(gameInfo.variant != VariantChuChess && PieceToChar(CHUPROMOTED piece) == '+') promoSweep = CHUPROMOTED piece;
selectFlag = 0; lastX = xPix; lastY = yPix;
Sweep(0); // Pawn that is going to promote: preview promotion piece
sweepSelecting = 1;
} else {
ClearHighlights();
}
+ } else if(sweepSelecting) { // this must be the up-click corresponding to the down-click that started the sweep
+ sweepSelecting = 0; appData.animate = FALSE; // do not animate, a selected piece already on to-square
+ if (appData.animate || appData.highlightLastMove) {
+ SetHighlights(fromX, fromY, toX, toY);
+ } else {
+ ClearHighlights();
+ }
} else {
#if 0
// [HGM] this must be done after the move is made, as with arrow it could lead to a board redraw with piece still on from square
ClearHighlights();
}
#endif
+ if(gameInfo.variant == VariantChuChess && piece != WhitePawn && piece != BlackPawn) defaultPromoChoice = piece;
+ if(marker[y][x] == 5) { // [HGM] lion: this was the release of a to-click or drag on a cyan square
+ dragging *= 2; // flag button-less dragging if we are dragging
+ MarkTargetSquares(1);
+ if(x == killX && y == killY) killX = killY = -1; else {
+ killX = x; killY = y; //remeber this square as intermediate
+ ReportClick("put", x, y); // and inform engine
+ ReportClick("lift", x, y);
+ MarkTargetSquares(0);
+ return;
+ }
+ }
DragPieceEnd(xPix, yPix); dragging = 0;
/* Don't animate move and drag both */
appData.animate = FALSE;
// off-board moves should not be highlighted
if(x < 0 || y < 0) ClearHighlights();
+ else ReportClick("put", x, y);
if(gatingPiece != EmptySquare && gameInfo.variant == VariantSChess) promoChoice = ToLower(PieceToChar(gatingPiece));
DisplayMessage("Click in holdings to choose piece", "");
return;
}
- PromotionPopUp();
+ PromotionPopUp(promoChoice);
} else {
int oldMove = currentMove;
UserMoveEvent(fromX, fromY, toX, toY, promoChoice);
case MT_NONE:
default:
break;
+ case MT_STEALMATE:
case MT_STALEMATE:
case MT_STAINMATE:
reason = "Xboard adjudication: Stalemate";
return 0;
}
+typedef int (CDECL *PPROBE_EGBB) (int player, int *piece, int *square);
+typedef int (CDECL *PLOAD_EGBB) (char *path, int cache_size, int load_options);
+static int egbbCode[] = { 6, 5, 4, 3, 2, 1 };
+
+static int
+BitbaseProbe ()
+{
+ int pieces[10], squares[10], cnt=0, r, f, res;
+ static int loaded;
+ static PPROBE_EGBB probeBB;
+ if(!appData.testLegality) return 10;
+ if(BOARD_HEIGHT != 8 || BOARD_RGHT-BOARD_LEFT != 8) return 12;
+ if(gameInfo.holdingsSize && gameInfo.variant != VariantSuper && gameInfo.variant != VariantSChess) return 12;
+ if(loaded == 2 && forwardMostMove < 2) loaded = 0; // retry on new game
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
+ ChessSquare piece = boards[forwardMostMove][r][f];
+ int black = (piece >= BlackPawn);
+ int type = piece - black*BlackPawn;
+ if(piece == EmptySquare) continue;
+ if(type != WhiteKing && type > WhiteQueen) return 12; // unorthodox piece
+ if(type == WhiteKing) type = WhiteQueen + 1;
+ type = egbbCode[type];
+ squares[cnt] = r*(BOARD_RGHT - BOARD_LEFT) + f - BOARD_LEFT;
+ pieces[cnt] = type + black*6;
+ if(++cnt > 5) return 11;
+ }
+ pieces[cnt] = squares[cnt] = 0;
+ // probe EGBB
+ if(loaded == 2) return 13; // loading failed before
+ if(loaded == 0) {
+ loaded = 2; // prepare for failure
+ char *p, *path = strstr(appData.egtFormats, "scorpio:"), buf[MSG_SIZ];
+ HMODULE lib;
+ PLOAD_EGBB loadBB;
+ if(!path) return 13; // no egbb installed
+ strncpy(buf, path + 8, MSG_SIZ);
+ if(p = strchr(buf, ',')) *p = NULLCHAR; else p = buf + strlen(buf);
+ snprintf(p, MSG_SIZ - strlen(buf), "%c%s", SLASH, EGBB_NAME);
+ lib = LoadLibrary(buf);
+ if(!lib) { DisplayError(_("could not load EGBB library"), 0); return 13; }
+ loadBB = (PLOAD_EGBB) GetProcAddress(lib, "load_egbb_xmen");
+ probeBB = (PPROBE_EGBB) GetProcAddress(lib, "probe_egbb_xmen");
+ if(!loadBB || !probeBB) { DisplayError(_("wrong EGBB version"), 0); return 13; }
+ p[1] = NULLCHAR; loadBB(buf, 64*1028, 2); // 2 = SMART_LOAD
+ loaded = 1; // success!
+ }
+ res = probeBB(forwardMostMove & 1, pieces, squares);
+ return res > 0 ? 1 : res < 0 ? -1 : 0;
+}
+
char *
SendMoveToBookUser (int moveNr, ChessProgramState *cps, int initial)
{ // [HGM] book: this routine intercepts moves to simulate book replies
char *bookHit = NULL;
+ if(cps->drawDepth && BitbaseProbe() == 0) { // [HG} egbb: reduce depth in drawn position
+ char buf[MSG_SIZ];
+ snprintf(buf, MSG_SIZ, "sd %d\n", cps->drawDepth);
+ SendToProgram(buf, cps);
+ }
//first determine if the incoming move brings opponent into his book
if(appData.usePolyglotBook && (cps == &first ? !appData.firstHasOwnBookUCI : !appData.secondHasOwnBookUCI))
bookHit = ProbeBook(moveNr+1, appData.polyglotBook); // returns move
void
HandleMachineMove (char *message, ChessProgramState *cps)
{
+ static char firstLeg[20];
char machineMove[MSG_SIZ], buf1[MSG_SIZ*10], buf2[MSG_SIZ];
char realname[MSG_SIZ];
int fromX, fromY, toX, toY;
ChessMove moveType;
- char promoChar;
+ char promoChar, roar;
char *p, *pv=buf1;
int machineWhite, oldError;
char *bookHit;
}
if(cps->alphaRank) AlphaRank(machineMove, 4);
+
+ // [HGM] lion: (some very limited) support for Alien protocol
+ killX = killY = -1;
+ if(machineMove[strlen(machineMove)-1] == ',') { // move ends in coma: non-final leg of composite move
+ safeStrCpy(firstLeg, machineMove, 20); // just remember it for processing when second leg arrives
+ return;
+ } else if(firstLeg[0]) { // there was a previous leg;
+ // only support case where same piece makes two step (and don't even test that!)
+ char buf[20], *p = machineMove+1, *q = buf+1, f;
+ safeStrCpy(buf, machineMove, 20);
+ while(isdigit(*q)) q++; // find start of to-square
+ safeStrCpy(machineMove, firstLeg, 20);
+ while(isdigit(*p)) p++;
+ safeStrCpy(p, q, 20); // glue to-square of second leg to from-square of first, to process over-all move
+ sscanf(buf, "%c%d", &f, &killY); killX = f - AAA; killY -= ONE - '0'; // pass intermediate square to MakeMove in global
+ firstLeg[0] = NULLCHAR;
+ }
+
if (!ParseOneMove(machineMove, forwardMostMove, &moveType,
&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));
DisplayMoveError(buf1);
- 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);
+ snprintf(buf1, MSG_SIZ*10, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c via %c%c) res=%d",
+ machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, killX+AAA, killY+ONE, moveType);
if (gameMode == TwoMachinesPlay) {
GameEnds(machineWhite ? BlackWins : WhiteWins,
buf1, GE_XBOARD);
MakeMove(fromX, fromY, toX, toY, promoChar);/*updates forwardMostMove*/
+ /* Test suites abort the 'game' after one move */
+ if(*appData.finger) {
+ static FILE *f;
+ char *fen = PositionToFEN(backwardMostMove, NULL, 0); // no counts in EPD
+ if(!f) f = fopen(appData.finger, "w");
+ if(f) fprintf(f, "%s bm %s;\n", fen, parseList[backwardMostMove]), fflush(f);
+ else { DisplayFatalError("Bad output file", errno, 0); return; }
+ free(fen);
+ GameEnds(GameUnfinished, NULL, GE_XBOARD);
+ }
+
/* [AS] Adjudicate game if needed (note: remember that forwardMostMove now points past the last move) */
if( gameMode == TwoMachinesPlay && adjudicateLossThreshold != 0 && forwardMostMove >= adjudicateLossPlies ) {
int count = 0;
cps->other->maybeThinking = TRUE;
}
+ roar = (killX >= 0 && IS_LION(boards[forwardMostMove][toY][toX]));
+
ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
if (!pausing && appData.ringBellAfterMoves) {
- RingBell();
+ if(!roar) RingBell();
}
/*
}
if (!strncmp(message, "setup ", 6) &&
- (!appData.testLegality || gameInfo.variant == VariantFairy || NonStandardBoardSize())
+ (!appData.testLegality || gameInfo.variant == VariantFairy || gameInfo.variant == VariantUnknown ||
+ NonStandardBoardSize(gameInfo.variant, gameInfo.boardWidth, gameInfo.boardHeight, gameInfo.holdingsSize))
) { // [HGM] allow first engine to define opening position
- int dummy, s=6; char buf[MSG_SIZ];
+ int dummy, w, h, hand, s=6; char buf[MSG_SIZ], varName[MSG_SIZ];
if(appData.icsActive || forwardMostMove != 0 || cps != &first) return;
+ *buf = NULLCHAR;
if(sscanf(message, "setup (%s", buf) == 1) s = 8 + strlen(buf), buf[s-9] = NULLCHAR, SetCharTable(pieceToChar, buf);
if(startedFromSetupPosition) return;
- if(sscanf(message+s, "%dx%d+%d", &dummy, &dummy, &dummy) == 3) while(message[s] && message[s++] != ' '); // for compatibility with Alien Edition
- ParseFEN(boards[0], &dummy, message+s);
+ dummy = sscanf(message+s, "%dx%d+%d_%s", &w, &h, &hand, varName);
+ if(dummy >= 3) {
+ while(message[s] && message[s++] != ' ');
+ if(BOARD_HEIGHT != h || BOARD_WIDTH != w + 4*(hand != 0) || gameInfo.holdingsSize != hand ||
+ dummy == 4 && gameInfo.variant != StringToVariant(varName) ) { // engine wants to change board format or variant
+ appData.NrFiles = w; appData.NrRanks = h; appData.holdingsSize = hand;
+ if(dummy == 4) gameInfo.variant = StringToVariant(varName); // parent variant
+ InitPosition(1); // calls InitDrawingSizes to let new parameters take effect
+ if(*buf) SetCharTable(pieceToChar, buf); // do again, for it was spoiled by InitPosition
+ }
+ }
+ ParseFEN(boards[0], &dummy, message+s, FALSE);
DrawPosition(TRUE, boards[0]);
startedFromSetupPosition = TRUE;
return;
GameEnds(GameUnfinished, "Engine aborts game", GE_XBOARD);
- if (!ParseFEN(initial_position, &blackPlaysFirst, message + 9)) {
+ if (!ParseFEN(initial_position, &blackPlaysFirst, message + 9, FALSE)) {
DisplayError(_("Bad FEN received from engine"), 0);
return ;
} else {
}
}
if (sscanf(message, "pong %d", &cps->lastPong) == 1) {
+ if(initPing == cps->lastPong) {
+ if(gameInfo.variant == VariantUnknown) {
+ DisplayError(_("Engine did not send setup for non-standard variant"), 0);
+ *engineVariant = NULLCHAR; appData.variant = VariantNormal; // back to normal as error recovery?
+ GameEnds(GameUnfinished, NULL, GE_XBOARD);
+ }
+ initPing = -1;
+ }
+ return;
+ }
+ if(!strncmp(message, "highlight ", 10)) {
+ if(appData.testLegality && appData.markers) return;
+ MarkByFEN(message+10); // [HGM] alien: allow engine to mark board squares
+ return;
+ }
+ if(!strncmp(message, "click ", 6)) {
+ char f, c=0; int x, y; // [HGM] alien: allow engine to finish user moves (i.e. engine-driven one-click moving)
+ if(appData.testLegality || !appData.oneClick) return;
+ sscanf(message+6, "%c%d%c", &f, &y, &c);
+ x = f - 'a' + BOARD_LEFT, y -= ONE - '0';
+ if(flipView) x = BOARD_WIDTH-1 - x; else y = BOARD_HEIGHT-1 - y;
+ x = x*squareSize + (x+1)*lineGap + squareSize/2;
+ y = y*squareSize + (y+1)*lineGap + squareSize/2;
+ f = first.highlight; first.highlight = 0; // kludge to suppress lift/put in response to own clicks
+ if(lastClickType == Press) // if button still down, fake release on same square, to be ready for next click
+ LeftClick(Release, lastLeftX, lastLeftY);
+ controlKey = (c == ',');
+ LeftClick(Press, x, y);
+ LeftClick(Release, x, y);
+ first.highlight = f;
return;
}
/*
DisplayInformation(_("Machine accepts your draw offer"));
GameEnds(GameIsDrawn, "Draw agreed", GE_XBOARD);
} else {
- DisplayInformation(_("Machine offers a draw\nSelect Action / Draw to agree"));
+ DisplayInformation(_("Machine offers a draw.\nSelect Action / Draw to accept."));
}
}
}
if(f = fopen(buf, "w")) { // export PV to applicable PV file
fprintf(f, "%5.2f/%-2d %s", curscore/100., plylev, pv);
fclose(f);
- } else DisplayError(_("failed writing PV"), 0);
+ }
+ else
+ /* TRANSLATORS: PV = principal variation, the variation the chess engine thinks is the best for everyone */
+ DisplayError(_("failed writing PV"), 0);
}
tempStats.depth = plylev;
case WhiteNonPromotion:
case BlackNonPromotion:
case NormalMove:
+ case FirstLeg:
case WhiteCapturesEnPassant:
case BlackCapturesEnPassant:
case WhiteKingSideCastle:
default:
break;
case MT_CHECK:
- if(gameInfo.variant != VariantShogi)
+ if(!IS_SHOGI(gameInfo.variant))
strcat(parseList[boardIndex - 1], "+");
break;
case MT_CHECKMATE:
ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
{
ChessSquare captured = board[toY][toX], piece, king; int p, oldEP = EP_NONE, berolina = 0;
- int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand ? 3 : 1;
+ int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess ? 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 */
}
piece = board[toY][toX] = (ChessSquare) fromX;
} else {
+ ChessSquare victim;
int i;
- if( board[toY][toX] != EmptySquare )
+ if( killX >= 0 && killY >= 0 ) // [HGM] lion: Lion trampled over something
+ victim = board[killY][killX],
+ board[killY][killX] = EmptySquare,
board[EP_STATUS] = EP_CAPTURE;
+ if( board[toY][toX] != EmptySquare ) {
+ board[EP_STATUS] = EP_CAPTURE;
+ if( (fromX != toX || fromY != toY) && // not igui!
+ (captured == WhiteLion && board[fromY][fromX] != BlackLion ||
+ captured == BlackLion && board[fromY][fromX] != WhiteLion ) ) { // [HGM] lion: Chu Lion-capture rules
+ board[EP_STATUS] = EP_IRON_LION; // non-Lion x Lion: no counter-strike allowed
+ }
+ }
+
if( board[fromY][fromX] == WhiteLance || board[fromY][fromX] == BlackLance ) {
if( gameInfo.variant != VariantSuper && gameInfo.variant != VariantShogi )
board[EP_STATUS] = EP_PAWN_MOVE; // Lance is Pawn-like in most variants
board[toY][toX+1] = board[fromY][BOARD_LEFT];
board[fromY][BOARD_LEFT] = EmptySquare;
} else if ((board[fromY][fromX] == WhitePawn && gameInfo.variant != VariantXiangqi ||
- board[fromY][fromX] == WhiteLance && gameInfo.variant != VariantSuper && gameInfo.variant != VariantShogi)
+ board[fromY][fromX] == WhiteLance && gameInfo.variant != VariantSuper && gameInfo.variant != VariantChu)
&& toY >= BOARD_HEIGHT-promoRank && promoChar // defaulting to Q is done elsewhere
) {
/* white pawn promotion */
board[fromY][0] = EmptySquare;
board[toY][2] = BlackRook;
} else if ((board[fromY][fromX] == BlackPawn && gameInfo.variant != VariantXiangqi ||
- board[fromY][fromX] == BlackLance && gameInfo.variant != VariantSuper && gameInfo.variant != VariantShogi)
+ board[fromY][fromX] == BlackLance && gameInfo.variant != VariantSuper && gameInfo.variant != VariantChu)
&& toY < promoRank && promoChar
) {
/* black pawn promotion */
board[fromY][fromX+1] = EmptySquare;
}
} else {
- board[toY][toX] = board[fromY][fromX];
+ ChessSquare piece = board[fromY][fromX]; // [HGM] lion: allow for igui (where from == to)
board[fromY][fromX] = EmptySquare;
+ board[toY][toX] = piece;
}
}
board[toY][toX] = EmptySquare;
}
}
+
if(gameInfo.variant == VariantSChess && promoChar != NULLCHAR && promoChar != '=' && piece != WhitePawn && piece != BlackPawn) {
board[fromY][fromX] = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar)); // S-Chess gating
} else
if(promoChar == '+') {
/* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite ordinary Pawn promotion) */
- board[toY][toX] = (ChessSquare) (PROMOTED piece);
+ board[toY][toX] = (ChessSquare) (CHUPROMOTED piece);
+ if(gameInfo.variant == VariantChuChess && (piece == WhiteKnight || piece == BlackKnight))
+ board[toY][toX] = piece + WhiteLion - WhiteKnight; // adjust Knight promotions to Lion
} else if(!appData.testLegality && promoChar != NULLCHAR && promoChar != '=') { // without legality testing, unconditionally believe promoChar
ChessSquare newPiece = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar));
if((newPiece <= WhiteMan || newPiece >= BlackPawn && newPiece <= BlackMan) // unpromoted piece specified
board[BOARD_HEIGHT-1-k][0] = EmptySquare;
}
}
-
}
/* Updates forwardMostMove */
void
MakeMove (int fromX, int fromY, int toX, int toY, int promoChar)
{
+ int x = toX, y = toY;
+ char *s = parseList[forwardMostMove];
+ ChessSquare p = boards[forwardMostMove][toY][toX];
// forwardMostMove++; // [HGM] bare: moved downstream
+ if(killX >= 0 && killY >= 0) x = killX, y = killY; // [HGM] lion: make SAN move to intermediate square, if there is one
(void) CoordsToAlgebraic(boards[forwardMostMove],
PosFlags(forwardMostMove),
- fromY, fromX, toY, toX, promoChar,
- parseList[forwardMostMove]);
+ fromY, fromX, y, x, promoChar,
+ s);
+ if(killX >= 0 && killY >= 0)
+ sprintf(s + strlen(s), "%c%c%d", p == EmptySquare || toX == fromX && toY == fromY ? '-' : 'x', toX + AAA, toY + ONE - '0');
if(serverMoves != NULL) { /* [HGM] write moves on file for broadcasting (should be separate routine, really) */
int timeLeft; static int lastLoadFlag=0; int king, piece;
default:
break;
case MT_CHECK:
- if(gameInfo.variant != VariantShogi)
+ if(!IS_SHOGI(gameInfo.variant))
strcat(parseList[forwardMostMove - 1], "+");
break;
case MT_CHECKMATE:
strcat(parseList[forwardMostMove - 1], "#");
break;
}
-
}
/* Updates currentMove if not pausing */
currentMove = forwardMostMove;
}
+ killX = killY = -1; // [HGM] lion: used up
+
if (instant) return;
DisplayMove(currentMove - 1);
}
static int
-NonStandardBoardSize ()
-{
- /* [HGM] Awkward testing. Should really be a table */
- int overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;
- if( gameInfo.variant == VariantXiangqi )
- overruled = gameInfo.boardWidth != 9 || gameInfo.boardHeight != 10 || gameInfo.holdingsSize != 0;
- if( gameInfo.variant == VariantShogi )
- overruled = gameInfo.boardWidth != 9 || gameInfo.boardHeight != 9 || gameInfo.holdingsSize != 7;
- 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 == 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;
- if( gameInfo.variant == VariantSuper )
- overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 8;
- if( gameInfo.variant == VariantGreat )
- overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 8;
- if( gameInfo.variant == VariantSChess )
- overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 7;
- if( gameInfo.variant == VariantGrand )
- overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 10 || gameInfo.holdingsSize != 7;
- return overruled;
+NonStandardBoardSize (VariantClass v, int boardWidth, int boardHeight, int holdingsSize)
+{
+ int width = 8, height = 8, holdings = 0; // most common sizes
+ if( v == VariantUnknown || *engineVariant) return 0; // engine-defined name never needs prefix
+ // correct the deviations default for each variant
+ if( v == VariantXiangqi ) width = 9, height = 10;
+ if( v == VariantShogi ) width = 9, height = 9, holdings = 7;
+ if( v == VariantBughouse || v == VariantCrazyhouse) holdings = 5;
+ if( v == VariantCapablanca || v == VariantCapaRandom ||
+ v == VariantGothic || v == VariantFalcon || v == VariantJanus )
+ width = 10;
+ if( v == VariantCourier ) width = 12;
+ if( v == VariantSuper ) holdings = 8;
+ if( v == VariantGreat ) width = 10, holdings = 8;
+ if( v == VariantSChess ) holdings = 7;
+ if( v == VariantGrand ) width = 10, height = 10, holdings = 7;
+ if( v == VariantChuChess) width = 10, height = 10;
+ if( v == VariantChu ) width = 12, height = 12;
+ return boardWidth >= 0 && boardWidth != width || // -1 is default,
+ boardHeight >= 0 && boardHeight != height || // and thus by definition OK
+ holdingsSize >= 0 && holdingsSize != holdings;
+}
+
+char variantError[MSG_SIZ];
+
+char *
+SupportedVariant (char *list, VariantClass v, int boardWidth, int boardHeight, int holdingsSize, int proto, char *engine)
+{ // returns error message (recognizable by upper-case) if engine does not support the variant
+ char *p, *variant = VariantName(v);
+ static char b[MSG_SIZ];
+ if(NonStandardBoardSize(v, boardWidth, boardHeight, holdingsSize)) { /* [HGM] make prefix for non-standard board size. */
+ snprintf(b, MSG_SIZ, "%dx%d+%d_%s", boardWidth, boardHeight,
+ holdingsSize, variant); // cook up sized variant name
+ /* [HGM] varsize: try first if this deviant size variant is specifically known */
+ if(StrStr(list, b) == NULL) {
+ // specific sized variant not known, check if general sizing allowed
+ if(proto != 1 && StrStr(list, "boardsize") == NULL) {
+ snprintf(variantError, MSG_SIZ, "Board size %dx%d+%d not supported by %s",
+ boardWidth, boardHeight, holdingsSize, engine);
+ return NULL;
+ }
+ /* [HGM] here we really should compare with the maximum supported board size */
+ }
+ } else snprintf(b, MSG_SIZ,"%s", variant);
+ if(proto == 1) return b; // for protocol 1 we cannot check and hope for the best
+ p = StrStr(list, b);
+ while(p && (p != list && p[-1] != ',' || p[strlen(b)] && p[strlen(b)] != ',') ) p = StrStr(p+1, b);
+ if(p == NULL) {
+ // occurs not at all in list, or only as sub-string
+ snprintf(variantError, MSG_SIZ, _("Variant %s not supported by %s"), b, engine);
+ if(p = StrStr(list, b)) { // handle requesting parent variant when only size-overridden is supported
+ int l = strlen(variantError);
+ char *q;
+ while(p != list && p[-1] != ',') p--;
+ q = strchr(p, ',');
+ if(q) *q = NULLCHAR;
+ snprintf(variantError + l, MSG_SIZ - l, _(", but %s is"), p);
+ if(q) *q= ',';
+ }
+ return NULL;
+ }
+ return b;
}
void
InitChessProgram (ChessProgramState *cps, int setup)
/* setup needed to setup FRC opening position */
{
- char buf[MSG_SIZ], b[MSG_SIZ];
+ char buf[MSG_SIZ], *b;
if (appData.noChessProgram) return;
hintRequested = FALSE;
bookRequested = FALSE;
if (gameInfo.variant != VariantNormal &&
gameInfo.variant != VariantLoadable
/* [HGM] also send variant if board size non-standard */
- || gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0
- ) {
- char *v = VariantName(gameInfo.variant);
- if (cps->protocolVersion != 1 && StrStr(cps->variants, v) == NULL) {
- /* [HGM] in protocol 1 we have to assume all variants valid */
- snprintf(buf, MSG_SIZ, _("Variant %s not supported by %s"), v, cps->tidy);
- DisplayFatalError(buf, 0, 1);
+ || gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0) {
+
+ b = SupportedVariant(cps->variants, gameInfo.variant, gameInfo.boardWidth,
+ gameInfo.boardHeight, gameInfo.holdingsSize, cps->protocolVersion, cps->tidy);
+ if (b == NULL) {
+ DisplayFatalError(variantError, 0, 1);
return;
}
- if(NonStandardBoardSize()) { /* [HGM] make prefix for non-standard board size. */
- snprintf(b, MSG_SIZ, "%dx%d+%d_%s", gameInfo.boardWidth, gameInfo.boardHeight,
- gameInfo.holdingsSize, VariantName(gameInfo.variant)); // cook up sized variant name
- /* [HGM] varsize: try first if this defiant size variant is specifically known */
- if(StrStr(cps->variants, b) == NULL) {
- // specific sized variant not known, check if general sizing allowed
- if (cps->protocolVersion != 1) { // for protocol 1 we cannot check and hope for the best
- if(StrStr(cps->variants, "boardsize") == NULL) {
- snprintf(buf, MSG_SIZ, "Board size %dx%d+%d not supported by %s",
- gameInfo.boardWidth, gameInfo.boardHeight, gameInfo.holdingsSize, cps->tidy);
- DisplayFatalError(buf, 0, 1);
- return;
- }
- /* [HGM] here we really should compare with the maximum supported board size */
- }
- }
- } else snprintf(b, MSG_SIZ,"%s", VariantName(gameInfo.variant));
snprintf(buf, MSG_SIZ, "variant %s\n", b);
SendToProgram(buf, cps);
}
SendToProgram("easy\n", cps);
}
if (cps->usePing) {
- snprintf(buf, MSG_SIZ, "ping %d\n", ++cps->lastPing);
+ snprintf(buf, MSG_SIZ, "ping %d\n", initPing = ++cps->lastPing);
SendToProgram(buf, cps);
}
cps->initDone = TRUE;
SWAP(fenOverride, p)
SWAP(NPS, h)
SWAP(accumulateTC, h)
+ SWAP(drawDepth, h)
SWAP(host, p)
}
result, resultDetails ? resultDetails : "(null)", whosays);
}
- fromX = fromY = -1; // [HGM] abort any move the user is entering.
+ fromX = fromY = killX = killY = -1; // [HGM] abort any move the user is entering. // [HGM] lion
if(pausing) PauseEvent(); // can happen when we abort a paused game (New Game or Quit)
PlayIcsUnfinishedSound();
}
}
+ if(appData.quitNext) { ExitEvent(0); return; }
} else if (gameMode == EditGame ||
gameMode == PlayFromGameFile ||
gameMode == AnalyzeMode ||
if(currentlyInitializedVariant != gameInfo.variant) {
char buf[MSG_SIZ];
// [HGM] variantswitch: make engine aware of new variant
- if(cps->protocolVersion > 1 && StrStr(cps->variants, VariantName(gameInfo.variant)) == NULL)
+ if(!SupportedVariant(cps->variants, gameInfo.variant, gameInfo.boardWidth,
+ gameInfo.boardHeight, gameInfo.holdingsSize, cps->protocolVersion, ""))
return; // [HGM] refrain from feeding moves altogether if variant is unsupported!
snprintf(buf, MSG_SIZ, "variant %s\n", VariantName(gameInfo.variant));
SendToProgram(buf, cps);
lastHint[0] = NULLCHAR;
ClearGameInfo(&gameInfo);
gameInfo.variant = StringToVariant(appData.variant);
+ if(gameInfo.variant == VariantNormal && strcmp(appData.variant, "normal")) gameInfo.variant = VariantUnknown;
ics_user_moved = ics_clock_paused = FALSE;
ics_getting_history = H_FALSE;
ics_gamenum = -1;
ClearPremoveHighlights();
gotPremove = FALSE;
alarmSounded = FALSE;
+ killX = killY = -1; // [HGM] lion
GameEnds(EndOfFile, NULL, GE_PLAYER);
if(appData.serverMovesName != NULL) {
case WhiteNonPromotion:
case BlackNonPromotion:
case NormalMove:
+ case FirstLeg:
case WhiteKingSideCastle:
case WhiteQueenSideCastle:
case BlackKingSideCastle:
toX = currentMoveString[2] - AAA;
toY = currentMoveString[3] - ONE;
promoChar = currentMoveString[4];
+ if(promoChar == ';') promoChar = NULLCHAR;
break;
case WhiteDrop:
thinkOutput[0] = NULLCHAR;
MakeMove(fromX, fromY, toX, toY, promoChar);
+ killX = killY = -1; // [HGM] lion: used up
currentMove = forwardMostMove;
return TRUE;
}
PackMove (int fromX, int fromY, int toX, int toY, ChessSquare promoPiece)
{
int sq = fromX + (fromY<<4);
- int piece = quickBoard[sq];
+ int piece = quickBoard[sq], rook;
quickBoard[sq] = 0;
moveDatabase[movePtr].to = pieceList[piece] = sq = toX + (toY<<4);
- if(piece == pieceList[1] && fromY == toY && (toX > fromX+1 || toX < fromX-1) && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1) {
+ if(piece == pieceList[1] && fromY == toY) {
+ if((toX > fromX+1 || toX < fromX-1) && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1) {
int from = toX>fromX ? BOARD_RGHT-1 : BOARD_LEFT;
moveDatabase[movePtr++].piece = Q_WCASTL;
quickBoard[sq] = piece;
piece = quickBoard[from]; quickBoard[from] = 0;
moveDatabase[movePtr].to = pieceList[piece] = sq = toX>fromX ? sq-1 : sq+1;
+ } else if((rook = quickBoard[sq]) && pieceType[rook] == WhiteRook) { // FRC castling
+ quickBoard[sq] = 0; // remove Rook
+ moveDatabase[movePtr].to = sq = (toX>fromX ? BOARD_RGHT-2 : BOARD_LEFT+2); // King to-square
+ moveDatabase[movePtr++].piece = Q_WCASTL;
+ quickBoard[sq] = pieceList[1]; // put King
+ piece = rook;
+ moveDatabase[movePtr].to = pieceList[rook] = sq = toX>fromX ? sq-1 : sq+1;
+ }
} else
- if(piece == pieceList[2] && fromY == toY && (toX > fromX+1 || toX < fromX-1) && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1) {
+ if(piece == pieceList[2] && fromY == toY) {
+ if((toX > fromX+1 || toX < fromX-1) && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1) {
int from = (toX>fromX ? BOARD_RGHT-1 : BOARD_LEFT) + (BOARD_HEIGHT-1 <<4);
moveDatabase[movePtr++].piece = Q_BCASTL;
quickBoard[sq] = piece;
piece = quickBoard[from]; quickBoard[from] = 0;
moveDatabase[movePtr].to = pieceList[piece] = sq = toX>fromX ? sq-1 : sq+1;
+ } else if((rook = quickBoard[sq]) && pieceType[rook] == BlackRook) { // FRC castling
+ quickBoard[sq] = 0; // remove Rook
+ moveDatabase[movePtr].to = sq = (toX>fromX ? BOARD_RGHT-2 : BOARD_LEFT+2);
+ moveDatabase[movePtr++].piece = Q_BCASTL;
+ quickBoard[sq] = pieceList[2]; // put King
+ piece = rook;
+ moveDatabase[movePtr].to = pieceList[rook] = sq = toX>fromX ? sq-1 : sq+1;
+ }
} else
if(epOK && (pieceType[piece] == WhitePawn || pieceType[piece] == BlackPawn) && fromX != toX && quickBoard[sq] == 0) {
quickBoard[(fromY<<4)+toX] = 0;
for(next = WhitePawn; next<EmptySquare; next++) keys[next] = random()>>8 ^ random()<<6 ^random()<<20;
initDone = TRUE;
}
- if(lg->gameInfo.fen) ParseFEN(boards[scratch], &btm, lg->gameInfo.fen);
+ if(lg->gameInfo.fen) ParseFEN(boards[scratch], &btm, lg->gameInfo.fen, FALSE);
else CopyBoard(boards[scratch], initialPosition); // default start position
if(lg->moves) {
turn = btm + 1;
case WhiteNonPromotion:
case BlackNonPromotion:
case NormalMove:
+ case FirstLeg:
case WhiteKingSideCastle:
case WhiteQueenSideCastle:
case BlackKingSideCastle:
if (gameMode != BeginningOfGame) {
Reset(FALSE, TRUE);
}
+ killX = killY = -1; // [HGM] lion: in case we did not Reset
gameFileFP = f;
if (lastLoadGameFP != NULL && lastLoadGameFP != f) {
break;
case NormalMove:
+ case FirstLeg:
/* Only a NormalMove can be at the start of a game
* without a position diagram. */
if (lastLoadGameStart == EndOfFile ) {
if (gameInfo.fen != NULL) {
Board initial_position;
startedFromSetupPosition = TRUE;
- if (!ParseFEN(initial_position, &blackPlaysFirst, gameInfo.fen)) {
+ if (!ParseFEN(initial_position, &blackPlaysFirst, gameInfo.fen, TRUE)) {
Reset(TRUE, TRUE);
DisplayError(_("Bad FEN position in file"), 0);
return FALSE;
AnalyzeFileEvent();
}
+ if(gameInfo.result == GameUnfinished && gameInfo.resultDetails && appData.clockMode) {
+ long int w, b; // [HGM] adjourn: restore saved clock times
+ char *p = strstr(gameInfo.resultDetails, "(Clocks:");
+ if(p && sscanf(p+8, "%ld,%ld", &w, &b) == 2) {
+ timeRemaining[0][forwardMostMove] = whiteTimeRemaining = 1000*w + 500;
+ timeRemaining[1][forwardMostMove] = blackTimeRemaining = 1000*b + 500;
+ }
+ }
+
if(creatingBook) return TRUE;
if (!matchMode && pos > 0) {
ToNrEvent(pos); // [HGM] no autoplay if selected on position
}
if (fenMode) {
- if (!ParseFEN(initial_position, &blackPlaysFirst, line)) {
+ if (!ParseFEN(initial_position, &blackPlaysFirst, line, TRUE)) {
DisplayError(_("Bad FEN position in file"), 0);
return FALSE;
}
if(appData.numberTag && matchMode) fprintf(f, "[Number \"%d\"]\n", nextGame+1); // [HGM] number tag
if (backwardMostMove > 0 || startedFromSetupPosition) {
- char *fen = PositionToFEN(backwardMostMove, NULL);
+ char *fen = PositionToFEN(backwardMostMove, NULL, 1);
fprintf(f, "[FEN \"%s\"]\n[SetUp \"1\"]\n", fen);
fprintf(f, "\n{--------------\n");
PrintPosition(f, backwardMostMove);
/* Print result */
if (gameInfo.resultDetails != NULL &&
gameInfo.resultDetails[0] != NULLCHAR) {
- fprintf(f, "{%s} %s\n\n", gameInfo.resultDetails,
- PGNResult(gameInfo.result));
+ char buf[MSG_SIZ], *p = gameInfo.resultDetails;
+ if(gameInfo.result == GameUnfinished && appData.clockMode &&
+ (gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack || gameMode == TwoMachinesPlay)) // [HGM] adjourn: save clock settings
+ snprintf(buf, MSG_SIZ, "%s (Clocks: %ld, %ld)", p, whiteTimeRemaining/1000, blackTimeRemaining/1000), p = buf;
+ fprintf(f, "{%s} %s\n\n", p, PGNResult(gameInfo.result));
} else {
fprintf(f, "%s\n\n", PGNResult(gameInfo.result));
}
PrintPosition(f, currentMove);
fprintf(f, "--------------]\n");
} else {
- fen = PositionToFEN(currentMove, NULL);
+ fen = PositionToFEN(currentMove, NULL, 1);
fprintf(f, "%s\n", fen);
free(fen);
}
case MachinePlaysWhite:
case MachinePlaysBlack:
if (WhiteOnMove(forwardMostMove) == (gameMode == MachinePlaysWhite)) {
- DisplayError(_("Wait until your turn,\nor select Move Now"), 0);
+ DisplayError(_("Wait until your turn,\nor select 'Move Now'."), 0);
return;
}
/* fall through */
}
if(WaitForEngine(&second, TwoMachinesEventIfReady)) return; // (if needed:) started up second engine, so wait for features
- if(second.protocolVersion >= 2 && !strstr(second.variants, VariantName(gameInfo.variant))) {
+ if(!SupportedVariant(second.variants, gameInfo.variant, gameInfo.boardWidth,
+ gameInfo.boardHeight, gameInfo.holdingsSize, second.protocolVersion, second.tidy)) {
startingEngine = FALSE;
DisplayError("second engine does not play this", 0);
return;
{
char buf[MSG_SIZ];
ChessSquare piece = boards[0][y][x];
+ static Board erasedBoard, currentBoard, menuBoard, nullBoard;
+ static int lastVariant;
if (gameMode != EditPosition && gameMode != IcsExamining) return;
switch (selection) {
case ClearBoard:
+ CopyBoard(currentBoard, boards[0]);
+ CopyBoard(menuBoard, initialPosition);
if (gameMode == IcsExamining && ics_type == ICS_FICS) {
SendToICS(ics_prefix);
SendToICS("bsetup clear\n");
SendToICS(ics_prefix);
SendToICS("clearboard\n");
} else {
+ int nonEmpty = 0;
for (x = 0; x < BOARD_WIDTH; x++) { ChessSquare p = EmptySquare;
if(x == BOARD_LEFT-1 || x == BOARD_RGHT) p = (ChessSquare) 0; /* [HGM] holdings */
for (y = 0; y < BOARD_HEIGHT; y++) {
SendToICS(buf);
}
} else {
+ if(boards[0][y][x] != p) nonEmpty++;
boards[0][y][x] = p;
}
}
+ menuBoard[1][x] = menuBoard[BOARD_HEIGHT-2][x] = p;
+ }
+ if(gameMode != IcsExamining) { // [HGM] editpos: cycle trough boards
+ for(x = BOARD_LEFT; x < BOARD_RGHT; x++) { // create 'menu board' by removing duplicates
+ ChessSquare p = menuBoard[0][x];
+ for(y = x + 1; y < BOARD_RGHT; y++) if(menuBoard[0][y] == p) menuBoard[0][y] = EmptySquare;
+ p = menuBoard[BOARD_HEIGHT-1][x];
+ for(y = x + 1; y < BOARD_RGHT; y++) if(menuBoard[BOARD_HEIGHT-1][y] == p) menuBoard[BOARD_HEIGHT-1][y] = EmptySquare;
+ }
+ DisplayMessage("Clicking clock again restores position", "");
+ if(gameInfo.variant != lastVariant) lastVariant = gameInfo.variant, CopyBoard(erasedBoard, boards[0]);
+ if(!nonEmpty) { // asked to clear an empty board
+ CopyBoard(boards[0], menuBoard);
+ } else
+ if(CompareBoards(currentBoard, menuBoard)) { // asked to clear an empty board
+ CopyBoard(boards[0], initialPosition);
+ } else
+ if(CompareBoards(currentBoard, initialPosition) && !CompareBoards(currentBoard, erasedBoard)
+ && !CompareBoards(nullBoard, erasedBoard)) {
+ CopyBoard(boards[0], erasedBoard);
+ } else
+ CopyBoard(erasedBoard, currentBoard);
+
}
}
if (gameMode == EditPosition) {
if(gameInfo.variant == VariantShatranj ||
gameInfo.variant == VariantXiangqi ||
gameInfo.variant == VariantCourier ||
+ gameInfo.variant == VariantASEAN ||
gameInfo.variant == VariantMakruk )
selection = (ChessSquare)((int)selection - (int)WhiteQueen + (int)WhiteFerz);
goto defaultlabel;
case MachinePlaysWhite:
case MachinePlaysBlack:
if (WhiteOnMove(forwardMostMove) == (gameMode == MachinePlaysWhite)) {
- DisplayError(_("Wait until your turn,\nor select Move Now"), 0);
+ DisplayError(_("Wait until your turn,\nor select 'Move Now'."), 0);
return;
}
if (forwardMostMove < 2) return;
switch (gameMode) {
case MachinePlaysWhite:
if (WhiteOnMove(forwardMostMove)) {
- DisplayError(_("Wait until your turn"), 0);
+ DisplayError(_("Wait until your turn."), 0);
return;
}
break;
case BeginningOfGame:
case MachinePlaysBlack:
if (!WhiteOnMove(forwardMostMove)) {
- DisplayError(_("Wait until your turn"), 0);
+ DisplayError(_("Wait until your turn."), 0);
return;
}
break;
switch (gameMode) {
case MachinePlaysWhite:
if (WhiteOnMove(forwardMostMove)) {
- DisplayError(_("Wait until your turn"), 0);
+ DisplayError(_("Wait until your turn."), 0);
return;
}
break;
case BeginningOfGame:
case MachinePlaysBlack:
if (!WhiteOnMove(forwardMostMove)) {
- DisplayError(_("Wait until your turn"), 0);
+ DisplayError(_("Wait until your turn."), 0);
return;
}
break;
SendToProgram(message, cps);
}
+char *
+EngineDefinedVariant (ChessProgramState *cps, int n)
+{ // return name of n-th unknown variant that engine supports
+ static char buf[MSG_SIZ];
+ char *p, *s = cps->variants;
+ if(!s) return NULL;
+ do { // parse string from variants feature
+ VariantClass v;
+ p = strchr(s, ',');
+ if(p) *p = NULLCHAR;
+ v = StringToVariant(s);
+ if(v == VariantNormal && strcmp(s, "normal") && !strstr(s, "_normal")) v = VariantUnknown; // garbage is recognized as normal
+ if(v == VariantUnknown) { // non-standard variant in list of engine-supported variants
+ if(--n < 0) safeStrCpy(buf, s, MSG_SIZ);
+ }
+ if(p) *p++ = ',';
+ if(n < 0) return buf;
+ } while(s = p);
+ return NULL;
+}
+
int
BoolFeature (char **p, char *name, int *loc, ChessProgramState *cps)
{
/* End of additions by Tord */
/* [HGM] added features: */
+ if (BoolFeature(&p, "highlight", &cps->highlight, cps)) continue;
if (BoolFeature(&p, "debug", &cps->debug, cps)) continue;
if (BoolFeature(&p, "nps", &cps->supportsNPS, cps)) continue;
if (IntFeature(&p, "level", &cps->maxNrOfSessions, cps)) continue;
ChessMove moveType;
// [HGM] FENedit
- if(gameMode == EditPosition && ParseFEN(board, &n, move) ) {
+ if(gameMode == EditPosition && ParseFEN(board, &n, move, TRUE) ) {
EditPositionPasteFEN(move);
return;
}
char *
-PositionToFEN (int move, char *overrideCastling)
+PositionToFEN (int move, char *overrideCastling, int moveCounts)
{
int i, j, fromX, fromY, toX, toY;
int whiteToPlay;
*p++ = '+';
piece = (ChessSquare)(DEMOTED piece);
}
- *p++ = PieceToChar(piece);
+ *p++ = (piece == DarkSquare ? '*' : PieceToChar(piece));
if(p[-1] == '~') {
/* [HGM] flag promoted pieces as '<promoted>~' (Crazyhouse) */
p[-1] = PieceToChar((ChessSquare)(DEMOTED piece));
}
if(gameInfo.variant != VariantShogi && gameInfo.variant != VariantXiangqi &&
- gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier && gameInfo.variant != VariantMakruk ) {
+ gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier &&
+ gameInfo.variant != VariantMakruk && gameInfo.variant != VariantASEAN ) {
/* En passant target square */
if (move > backwardMostMove) {
fromX = moveList[move - 1][0] - AAA;
}
}
- /* [HGM] find reversible plies */
+ if(moveCounts)
{ int i = 0, j=move;
+ /* [HGM] find reversible plies */
if (appData.debugMode) { int k;
fprintf(debugFP, "write FEN 50-move: %d %d %d\n", initialRulePlies, forwardMostMove, backwardMostMove);
for(k=backwardMostMove; k<=forwardMostMove; k++)
if( j == backwardMostMove ) i += initialRulePlies;
sprintf(p, "%d ", i);
p += i>=100 ? 4 : i >= 10 ? 3 : 2;
- }
- /* Fullmove number */
- sprintf(p, "%d", (move / 2) + 1);
+
+ /* Fullmove number */
+ sprintf(p, "%d", (move / 2) + 1);
+ } else *--p = NULLCHAR;
return StrSave(buf);
}
Boolean
-ParseFEN (Board board, int *blackPlaysFirst, char *fen)
+ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize)
{
- int i, j;
+ int i, j, k, w=0;
char *p, c;
int emptycount, virgin[BOARD_FILES];
ChessSquare piece;
p = fen;
- /* [HGM] by default clear Crazyhouse holdings, if present */
- if(gameInfo.holdingsWidth) {
- for(i=0; i<BOARD_HEIGHT; i++) {
- board[i][0] = EmptySquare; /* black holdings */
- board[i][BOARD_WIDTH-1] = EmptySquare; /* white holdings */
- board[i][1] = (ChessSquare) 0; /* black counts */
- board[i][BOARD_WIDTH-2] = (ChessSquare) 0; /* white counts */
- }
- }
-
/* Piece placement data */
for (i = BOARD_HEIGHT - 1; i >= 0; i--) {
j = 0;
for (;;) {
- if (*p == '/' || *p == ' ' || (*p == '[' && i == 0) ) {
- if (*p == '/') p++;
+ if (*p == '/' || *p == ' ' || *p == '[' ) {
+ if(j > w) w = j;
emptycount = gameInfo.boardWidth - j;
while (emptycount--)
board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare;
+ if (*p == '/') p++;
+ else if(autoSize) { // we stumbled unexpectedly into end of board
+ for(k=i; k<BOARD_HEIGHT; k++) { // too few ranks; shift towards bottom
+ for(j=0; j<BOARD_WIDTH; j++) board[k-i][j] = board[k][j];
+ }
+ appData.NrRanks = gameInfo.boardHeight - i; i=0;
+ }
break;
#if(BOARD_FILES >= 10)
} else if(*p=='x' || *p=='X') { /* [HGM] X means 10 */
while (emptycount--)
board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare;
#endif
+ } else if (*p == '*') {
+ board[i][(j++)+gameInfo.holdingsWidth] = DarkSquare; p++;
} else if (isdigit(*p)) {
emptycount = *p++ - '0';
while(isdigit(*p)) emptycount = 10*emptycount + *p++ - '0'; /* [HGM] allow > 9 */
if(*p=='+') {
piece = CharToPiece(*++p);
if(piece == EmptySquare) return FALSE; /* unknown piece */
- piece = (ChessSquare) (PROMOTED piece ); p++;
+ piece = (ChessSquare) (CHUPROMOTED piece ); p++;
if(PieceToChar(piece) != '+') return FALSE; /* unpromotable piece */
} else piece = CharToPiece(*p++);
}
while (*p == '/' || *p == ' ') p++;
+ if(autoSize) appData.NrFiles = w, InitPosition(TRUE);
+
+ /* [HGM] by default clear Crazyhouse holdings, if present */
+ if(gameInfo.holdingsWidth) {
+ for(i=0; i<BOARD_HEIGHT; i++) {
+ board[i][0] = EmptySquare; /* black holdings */
+ board[i][BOARD_WIDTH-1] = EmptySquare; /* white holdings */
+ board[i][1] = (ChessSquare) 0; /* black counts */
+ board[i][BOARD_WIDTH-2] = (ChessSquare) 0; /* white counts */
+ }
+ }
+
/* [HGM] look for Crazyhouse holdings here */
while(*p==' ') p++;
if( gameInfo.holdingsWidth && p[-1] == '/' || *p == '[') {
/* 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 != VariantMakruk ) {
+ gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier &&
+ gameInfo.variant != VariantMakruk && gameInfo.variant != VariantASEAN ) {
if(*p=='-') {
p++; board[EP_STATUS] = EP_NONE;
} else {
if (fen != NULL) {
Board initial_position;
- if (!ParseFEN(initial_position, &blackPlaysFirst, fen)) {
+ if (!ParseFEN(initial_position, &blackPlaysFirst, fen, TRUE)) {
DisplayError(_("Bad FEN position in clipboard"), 0);
return ;
} else {
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
#ifndef XB_BACKEND
#define XB_BACKEND
- /* unsigned int 64 for engine nodes work and display */
- #ifdef WIN32
- /* I don't know the name for this type of other compiler
- * If it not work, just modify here
- * This is for MS Visual Studio
- */
- #ifdef _MSC_VER
- #define u64 unsigned __int64
- #define s64 signed __int64
- #define u64Display "%I64u"
- #define s64Display "%I64d"
- #define u64Const(c) (c ## UI64)
- #define s64Const(c) (c ## I64)
- #else
- /* place holder
- * or dummy types for other compiler
- * [HGM] seems that -mno-cygwin comple needs %I64?
- */
- #define u64 unsigned long long
- #define s64 signed long long
- #ifdef USE_I64
- #define u64Display "%I64u"
- #define s64Display "%I64d"
- #else
- #define u64Display "%llu"
- #define s64Display "%lld"
- #endif
- #define u64Const(c) (c ## ULL)
- #define s64Const(c) (c ## LL)
- #endif
- #else
- /* GNU gcc */
- #define u64 unsigned long long
- #define s64 signed long long
- #define u64Display "%llu"
- #define s64Display "%lld"
- #define u64Const(c) (c ## ull)
- #define s64Const(c) (c ## ll)
- #endif
-
#include "lists.h"
typedef int (*FileProc) P((FILE *f, int n, char *title));
extern Boolean bookUp;
extern int tinyLayout, smallLayout;
extern Boolean mcMode;
+extern int dragging;
+extern char variantError[];
void MarkMenuItem P((char *menuRef, int state));
char *CmailMsg P((void));
/* Tord: Added the useFEN960 parameter in PositionToFEN() below */
-char *PositionToFEN P((int move, char* useFEN960));
+char *PositionToFEN P((int move, char* useFEN960, int moveCounts));
void AlphaRank P((char *s, int n)); /* [HGM] Shogi move preprocessor */
void EditPositionPasteFEN P((char *fen));
void TimeDelay P((long ms));
void EditBookEvent P((void));
Boolean DisplayBook P((int moveNr));
void SaveToBook P((char *text));
+void HoverEvent P((int hiX, int hiY, int x, int y));
int PackGame P((Board board));
-Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));
+Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen, Boolean autoSize));
void ApplyMove P((int fromX, int fromY, int toX, int toY, int promoChar, Board board));
void PackMove P((int fromX, int fromY, int toX, int toY, ChessSquare promoPiece));
void ics_printf P((char *format, ...));
int debug; /* [HGM] ignore engine debug lines starting with '#' */
int maxNrOfSessions; /* [HGM] secondary TC: max args in 'level' command */
int accumulateTC; /* [HGM] secondary TC: how to handle extra sessions */
+ int drawDepth; /* [HGM] egbb: search depth to play egbb draws */
int nps; /* [HGM] nps: factor for node count to replace time */
int supportsNPS;
int alphaRank; /* [HGM] shogi: engine uses shogi-type coordinates */
char *egtFormats; /* [HGM] EGT: supported tablebase formats */
int bookSuspend; /* [HGM] book: go was deferred because of book hit */
int pause; /* [HGM] pause: 1=supports it, 2=actually paused */
+ int highlight; /* [HGM] engine wants to get lift and put commands */
int nrOptions; /* [HGM] options: remembered option="..." features */
#define MAX_OPTIONS 200
Option option[MAX_OPTIONS];
extern char *recentEngines;
extern char *comboLine;
extern Boolean partnerUp, twoBoards;
+extern char engineVariant[];
+char *EngineDefinedVariant P((ChessProgramState *cps, int n));
void SettingsPopUp P((ChessProgramState *cps)); // [HGM] really in front-end, but CPS not known in frontend.h
int WaitForEngine P((ChessProgramState *cps, DelayedEventCallback x));
void Load P((ChessProgramState *cps, int n));
void MakeEngineOutputTitle P((void));
void LoadTheme P((void));
void CreateBookEvent P((void));
+char *SupportedVariant P((char *list, VariantClass v, int w, int h, int s, int proto, char *engine));
/* A point in time */
typedef struct {
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* The following terms apply to Digital Equipment Corporation's copyright
* interest in XBoard:
AnimateMove (Board board, int fromX, int fromY, int toX, int toY)
{
ChessSquare piece;
- int hop;
+ int hop, x = toX, y = toY;
Pnt start, finish, mid;
Pnt frames[kFactor * 2 + 1];
int nFrames, startColor, endColor;
+ if(killX >= 0 && IS_LION(board[fromY][fromX])) Roar();
+
/* Are we animating? */
if (!appData.animate || appData.blindfold)
return;
piece = board[fromY][fromX];
if (piece >= EmptySquare) return;
+ if(killX >= 0) toX = killX, toY = killY; // [HGM] lion: first to kill square
+
+again:
+
#if DONT_HOP
hop = FALSE;
#else
/* Be sure end square is redrawn */
damage[0][toY][toX] |= True;
+
+ if(toX != x || toY != y) { fromX = toX; fromY = toY; toX = x; toY = y; goto again; } // second leg
}
void
snprintf(tString, 3, "%d", piece);
align = 4; // holdings count in upper-left corner
}
+ if(piece == DarkSquare) square_color = 2;
if(square_color == 2 || appData.blindfold) piece = EmptySquare;
if (do_flash && piece != EmptySquare && appData.flashCount > 0) {
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
/* End compatibility grunge */
+ /* unsigned int 64 for engine nodes work and display */
+ #ifdef WIN32
+ /* I don't know the name for this type of other compiler
+ * If it not work, just modify here
+ * This is for MS Visual Studio
+ */
+ #ifdef _MSC_VER
+ #define u64 unsigned __int64
+ #define s64 signed __int64
+ #define u64Display "%I64u"
+ #define s64Display "%I64d"
+ #define u64Const(c) (c ## UI64)
+ #define s64Const(c) (c ## I64)
+ #else
+ /* place holder
+ * or dummy types for other compiler
+ * [HGM] seems that -mno-cygwin comple needs %I64?
+ */
+ #define u64 unsigned long long
+ #define s64 signed long long
+ #ifdef USE_I64
+ #define u64Display "%I64u"
+ #define s64Display "%I64d"
+ #else
+ #define u64Display "%llu"
+ #define s64Display "%lld"
+ #endif
+ #define u64Const(c) (c ## ULL)
+ #define s64Const(c) (c ## LL)
+ #endif
+ #else
+ /* GNU gcc */
+ #define u64 unsigned long long
+ #define s64 signed long long
+ #define u64Display "%llu"
+ #define s64Display "%lld"
+ #define u64Const(c) (c ## ull)
+ #define s64Const(c) (c ## ll)
+ #endif
+
#define PROTOVER 2 /* engine protocol version */
// [HGM] license: Messages that engines must print to satisfy their license requirements for patented variants
outside world in ASCII. In a similar way, the different rank numbering
systems (starting at rank 0 or 1) are implemented by redefining '1'.
*/
-#define BOARD_RANKS 11 /* [HGM] for in declarations */
+#define BOARD_RANKS 17 /* [HGM] for in declarations */
#define BOARD_FILES 16 /* [HGM] for in declarations */
#define BOARD_HEIGHT (gameInfo.boardHeight) /* [HGM] made user adjustable */
#define BOARD_WIDTH (gameInfo.boardWidth + 2*gameInfo.holdingsWidth)
#define VIRGIN (BOARD_RANKS-2) /* [HGM] pieces not moved */
#define EP_STATUS CASTLING][(BOARD_FILES-2) /* [HGM] in upper rank */
#define HOLDINGS_SET CASTLING][(BOARD_FILES-1) /* [HGM] in upper-right corner*/
-#define ONE ('1'-(BOARD_HEIGHT>9)) /* [HGM] foremost board rank */
+#define ONE ('1'-(BOARD_HEIGHT==10)) /* [HGM] foremost board rank */
#define AAA ('a'-BOARD_LEFT) /* [HGM] leftmost board file */
#define VIRGIN_W 1 /* [HGM] flags in Board[VIRGIN][X] */
#define VIRGIN_B 2
WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen,
WhiteFerz, WhiteAlfil, WhiteAngel, WhiteMarshall, WhiteWazir, WhiteMan,
WhiteCannon, WhiteNightrider, WhiteCardinal, WhiteDragon, WhiteGrasshopper,
- WhiteSilver, WhiteFalcon, WhiteLance, WhiteCobra, WhiteUnicorn, WhiteKing,
+ WhiteSilver, WhiteFalcon, WhiteLance, WhiteCobra, WhiteUnicorn, WhiteLion,
+ WhiteTokin, WhiteDagger, WhitePCardinal, WhitePDragon, WhiteCat,
+ WhitePSword, WhiteMonarch, WhiteMother, WhiteNothing, WhitePRook, WhitePDagger,
+ WhiteDolphin, WhiteStag, WhiteHorned, WhiteEagle, WhiteSword,
+ WhiteCrown, WhiteHCrown, WhiteHorse, WhiteDrunk, WhitePBishop, WhiteKing,
BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen,
BlackFerz, BlackAlfil, BlackAngel, BlackMarshall, BlackWazir, BlackMan,
BlackCannon, BlackNightrider, BlackCardinal, BlackDragon, BlackGrasshopper,
- BlackSilver, BlackFalcon, BlackLance, BlackCobra, BlackUnicorn, BlackKing,
- EmptySquare,
+ BlackSilver, BlackFalcon, BlackLance, BlackCobra, BlackUnicorn, BlackLion,
+ BlackTokin, BlackDagger, BlackPCardinal, BlackPDragon, BlackCat,
+ BlackPSword, BlackMonarch, BlackMother, BlackNothing, BlackPRook, BlackPDagger,
+ BlackDolphin, BlackStag, BlackHorned, BlackEagle, BlackSword,
+ BlackCrown, BlackHCrown, BlackHorse, BlackDrunk, BlackPBishop, BlackKing,
+ EmptySquare, DarkSquare,
NoRights, // [HGM] gamestate: for castling rights hidden in board[CASTLING]
ClearBoard, WhitePlay, BlackPlay, PromotePiece, DemotePiece /*for use on EditPosition menus*/
} ChessSquare;
#define PROMOTED (int)WhiteDragon - (int)WhiteRook + (int)
#define DEMOTED (int)WhiteRook - (int)WhiteDragon + (int)
#define SHOGI (int)EmptySquare + (int)
+#define CHUPROMOTED ((int)WhitePDragon - (int)WhiteDragon)*(gameInfo.variant == VariantChu) + PROMOTED
+#define IS_SHOGI(V) ((V) == VariantShogi || (V) == VariantChu)
+#define IS_LION(V) ((V) == WhiteLion || (V) == BlackLion)
typedef ChessSquare Board[BOARD_RANKS][BOARD_FILES];
WhitePromotion, WhiteNonPromotion,
BlackPromotion, BlackNonPromotion,
WhiteCapturesEnPassant, BlackCapturesEnPassant,
- WhiteDrop, BlackDrop,
+ WhiteDrop, BlackDrop, FirstLeg,
NormalMove, AmbiguousMove, IllegalMove, ImpossibleMove,
WhiteWins, BlackWins, GameIsDrawn, GameUnfinished,
GNUChessGame, XBoardGame, MoveNumberOne, Open, Close, Nothing,
} ColorClass;
typedef enum {
- SoundMove, SoundBell, SoundAlarm, SoundIcsWin, SoundIcsLoss,
+ SoundMove, SoundBell, SoundRoar, SoundAlarm, SoundIcsWin, SoundIcsLoss,
SoundIcsDraw, SoundIcsUnfinished, NSoundClasses
} SoundClass;
Variant35, /* Temporary name for possible future ICC wild 35 */
Variant36, /* Temporary name for possible future ICC wild 36 */
VariantShogi, /* [HGM] added variants */
+ VariantChu,
VariantXiangqi,
VariantCourier,
VariantGothic,
VariantGreat,
VariantTwilight,
VariantMakruk,
+ VariantASEAN,
VariantSChess,
VariantGrand,
VariantSpartan,
+ VariantLion,
+ VariantChuChess,
VariantUnknown /* Catchall for other unknown variants */
} VariantClass;
"wild35", \
"wild36", \
"shogi", \
+ "chu", \
"xiangqi", \
"courier", \
"gothic", \
"great",\
"twilight",\
"makruk",\
+ "asean",\
"seirawan",\
"grand",\
"spartan",\
+ "lion",\
+ "chuchess",\
"unknown" \
}
char *soundSeek;
char *soundMove; // [HGM] IMPORTANT: order must be as in SoundClass
char *soundBell;
+ char *soundRoar;
char *soundIcsAlarm;
char *soundIcsWin;
char *soundIcsLoss;
int zippyShortGame; /* [HGM] aborter */
#endif
Boolean lowTimeWarning; /* [HGM] low time */
+ Boolean quitNext;
char *lowTimeWarningColor;
char *serverFileName;
char *serverMovesName;
+ char *finger;
Boolean suppressLoadMoves;
int serverPause;
int timeOdds[ENGINES];
+ int drawDepth[ENGINES];
int timeOddsMode;
int accumulateTC[ENGINES];
int NPS[ENGINES];
dnl| configure.in
dnl|
dnl| Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, 2007,
- dnl| 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ dnl| 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
dnl|
dnl| GNU XBoard is free software: you can redistribute it and/or modify
dnl| it under the terms of the GNU General Public License as published by
dnl| the standard version of xboard.
dnl| define second argument as VERSION.PATCHLEVEL. e.g. 4.4.0j
-AC_INIT([xboard],[4.7.2],[bug-xboard@gnu.org])
+AC_INIT([xboard],[master-20130828],[bug-xboard@gnu.org])
dnl| need this to be able to compile some files in a subdir (filebrowser)
AM_INIT_AUTOMAKE([subdir-objects])
AH_TEMPLATE([X_WCHAR],[template])
AH_TEMPLATE([ATTENTION],[template])
AH_TEMPLATE([DEFINED_SYS_ERRLIST],[template])
-AH_TEMPLATE([HAVE_LIBXPM],[template])
AH_TEMPLATE([USE_XAW3D],[template])
AH_TEMPLATE([X_LOCALE],[template])
AC_ARG_WITH([gtk],
[AS_HELP_STRING([--with-gtk],[use GTK front-end (experimental)])],
- [with_GTK=yes],
- [with_GTK=no])
+ [with_GTK=$withval],
+ [with_GTK="no"])
AC_ARG_WITH([Xaw3d],
[AS_HELP_STRING([--with-Xaw3d],[use Xaw3d front-end (not fully supported anymore)])],
- [with_Xaw3d=yes],
- [with_Xaw3d=no])
+ [with_Xaw3d="$withval"],
+ [with_Xaw3d="no"])
AC_ARG_WITH([Xaw],
[AS_HELP_STRING([--with-Xaw],[use Xaw front-end (default)])],
- [with_Xaw=yes],
- [with_Xaw=no])
+ [with_Xaw="$withval"],
+ [with_Xaw="yes"])
+
+AC_ARG_WITH([iconsdir],
+ [AS_HELP_STRING([--with-iconsdir=DIR],
+ [path where icons get installed (default: $datadir/icons/hicolor/48x48/apps)])],
+ [ICONSDIR="$withval"],
+ [ICONSDIR='$(datadir)/icons/hicolor/48x48/apps'])
+
+AC_ARG_WITH([svgiconsdir],
+ [AS_HELP_STRING([--with-svgiconsdir=DIR],
+ [path where svg icons get installed (default: $datadir/icons/hicolor/scalable/apps)])],
+ [SVGICONSDIR="$withval"],
+ [SVGICONSDIR='$(datadir)/icons/hicolor/scalable/apps'])
+
+AC_ARG_WITH([desktopdir],
+ [AS_HELP_STRING([--with-desktopdir=DIR],
+ [path where desktop files get installed (default: $datadir/applications)])],
+ [DESKTOPDIR="$withval"],
+ [DESKTOPDIR='$(datadir)/applications'])
+
+AC_ARG_WITH([mimedir],
+ [AS_HELP_STRING([--with-mimedir=DIR],
+ [path where mime files get installed (default: $datadir/mime/packages)])],
+ [MIMEDIR="$withval"],
+ [MIMEDIR='$(datadir)/mime/packages'])
+
+AC_ARG_WITH([gamedatadir],
+ [AS_HELP_STRING([--with-gamedatadir=DIR],
+ [path where game data files get installed (default: $datadir/games/xboard)])],
+ [GAMEDATADIR="$withval"],
+ [GAMEDATADIR='$(datadir)/games/xboard'])
+
+AC_SUBST(ICONSDIR)
+AC_SUBST(SVGICONSDIR)
+AC_SUBST(DESKTOPDIR)
+AC_SUBST(MIMEDIR)
+AC_SUBST(GAMEDATADIR)
dnl | check for libraries
if test x"$with_GTK" = x"yes" ; then
PKG_CHECK_MODULES([GTK], [ gtk+-2.0 >= 2.16.0 gmodule-2.0 ])
FRONTEND_CFLAGS=$GTK_CFLAGS
FRONTEND_LIBS=$GTK_LIBS
+ with_Xaw="no"
fi
if test x"$with_GTK" = x"no" ; then
dnl | make results available in Makefile.am
AM_CONDITIONAL([withGTK], [test x"$with_GTK" = x"yes"])
-AM_CONDITIONAL([withXaw], [test x"$with_Xaw3d" = x"yes"])
-AM_CONDITIONAL([withXaw], [test x"$with_Xaw" = x"yes"])
+AM_CONDITIONAL([withXaw], [test x"$with_Xaw3d" = x"yes" || test x"$with_Xaw" = x"yes"])
AC_SUBST(FRONTEND_CFLAGS)
;;
esac
-AC_ARG_ENABLE( [xpm],
- [AS_HELP_STRING([--enable-xpm],[libXpm will be used if found (default)])],
- [enable_xpm="$enableval"],
- [enable_xpm="yes"])
-
-if test x"$enable_xpm" != "xno"; then
- save_cflags="$CFLAGS"
- save_cppflags="$CPPFLAGS"
- CFLAGS="$CFLAGS $X_CFLAGS"
- CPPFLAGS="$CPPFLAGS $X_CFLAGS"
- AC_CHECK_HEADERS(X11/xpm.h)
- CFLAGS="$save_cflags"
- CPPFLAGS="$save_cppflags"
- if test "$ac_cv_header_X11_xpm_h" = "yes"; then
- save_ldflags="$LDFLAGS"
- LDFLAGS="$LDFLAGS $X_LIBS"
- AC_CHECK_LIB(Xpm, XpmReadFileToPixmap,
- [X_PRE_LIBS="-lXpm $X_PRE_LIBS"; AC_DEFINE(HAVE_LIBXPM)], [],
- [$X_PRE_LIBS -lX11 $X_EXTRA_LIBS])
- LDFLAGS="$save_ldflags"
- fi
-fi
-
AC_SUBST(PRE_XMULIB)
AC_SUBST(POST_XMULIB)
AC_SUBST(CONF_CFLAGS)
AC_SUBST(XDG_ICON_RESOURCE)
fi
+dnl create a string with configure options that can be passed to the
+dnl program, good for bug reports and version printout, see output below
+CONFIGURE_OPTIONS="prefix=$prefix; datarootdir=$datarootdir; \
+datadir=$datadir; gamedatadir=$GAMEDATADIR; desktopdir=$DESKTOPDIR; \
+mimedir=$MIMEDIR; iconsdir=$ICONSDIR; svgiconsdir=$SVGICONSDIR; infodir=$infodir; \
+sysconfigdir=$sysconfigdir; update_mimedb=$enable_mimedb; NLS=$USE_NLS; \
+GKT=$with_GTK; Xaw3d=$with_Xaw3d; Xaw=$with_Xaw; \
+ptys=$enable_ptys; zippy=$enable_zippy; sigint=$enable_sigint"
+
+AC_SUBST(CONFIGURE_OPTIONS)
+
dnl | output Makefile
AC_CONFIG_FILES([Makefile cmail po/Makefile.in])
AC_CONFIG_COMMANDS([test-stamp-h],[test -z "$CONFIG_HEADERS" || date > stamp-h])
echo ""
echo " prefix: $prefix "
echo " datarootdir: $datarootdir "
-echo " datadir: $datadir (icons will go in \$datadir/icons/hicolor/...)"
-echo " (bitmaps will go in \$datadir/games/xboard/...)"
+echo " datadir: $datadir "
+echo " gamedatadir: $GAMEDATADIR "
+echo " desktopdir: $DESKTOPDIR "
+echo " mimedir: $MIMEDIR "
+echo " iconsdir: $ICONSDIR "
+echo " svgiconsdir: $SVGICONSDIR "
echo " infodir: $infodir (info files will go here)"
echo " sysconfdir: $sysconfdir (xboard.conf will go here)"
echo ""
echo " Xaw3d: $with_Xaw3d"
echo " Xaw: $with_Xaw"
echo ""
-echo " xpm: $enable_xpm"
echo " ptys: $enable_ptys"
echo " zippy: $enable_zippy"
echo " sigint: $enable_sigint"
/*
* dialogs.c -- platform-independent code for dialogs of XBoard
*
- * Copyright 2000, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * Copyright 2000, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
* ------------------------------------------------------------------------
*
* GNU XBoard is free software: you can redistribute it and/or modify
if(x < opts[i].min) x = opts[i].min;
if(opts[i].type == Fractional)
*(float*) opts[i].target = x; // engines never have float options!
- else if(opts[i].value != x) {
- opts[i].value = x;
+ else {
if(currentCps) {
+ if(opts[i].value != x) { // only to engine if changed
snprintf(buf, MSG_SIZ, "option %s=%.0f\n", opts[i].name, x);
SendToProgram(buf, currentCps);
+ }
} else *(int*) opts[i].target = x;
+ opts[i].value = x;
}
break;
case CheckBox:
case SaveButton:
case Label:
case Break:
+ case -1:
break;
}
if(opts[i].type == EndMark) break;
static Option matchOptions[] = {
{ 0, 0, 0, NULL, (void*) &tfName, ".trn", NULL, FileName, N_("Tournament file: ") },
+{ 0, 0, 0, NULL, NULL, "", NULL, Label, N_("For concurrent playing of tourney with multiple XBoards:") },
{ 0, 0, 0, NULL, (void*) &appData.roundSync, "", NULL, CheckBox, N_("Sync after round") },
-{ 0, SAME_ROW|LL, 0, NULL, NULL, "", NULL, Label, N_(" (for concurrent playing of a single") },
{ 0, 0, 0, NULL, (void*) &appData.cycleSync, "", NULL, CheckBox, N_("Sync after cycle") },
-{ 0, SAME_ROW|LL, 0, NULL, NULL, "", NULL, Label, N_(" tourney with multiple XBoards)") },
{ 0, LR, 175, NULL, NULL, "", NULL, Label, N_("Tourney participants:") },
{ 0, SAME_ROW|RR, 175, NULL, NULL, "", NULL, Label, N_("Select Engine:") },
{ 150, T_VSCRL | T_FILL | T_WRAP,
ASSIGN(tfName, appData.tourneyFile[0] ? appData.tourneyFile : MakeName(appData.defName));
ASSIGN(engineName, appData.participants);
ASSIGN(engineMnemonic[0], "");
- GenericPopUp(matchOptions, _("Match Options"), TransientDlg, BoardWindow, MODAL, 0);
+ GenericPopUp(matchOptions, _("Tournament Options"), TransientDlg, BoardWindow, MODAL, 0);
}
// ------------------------------------------- General Options --------------------------------------------------
{ 0, 0, 0, NULL, (void*) &appData.autoCallFlag, "", NULL, CheckBox, N_("Auto Flag") },
{ 0, 0, 0, NULL, (void*) &appData.autoFlipView, "", NULL, CheckBox, N_("Auto Flip View") },
{ 0, 0, 0, NULL, (void*) &appData.blindfold, "", NULL, CheckBox, N_("Blindfold") },
+/* TRANSLATORS: the drop menu is used to drop a piece, e.g. during bughouse or editing a position */
{ 0, 0, 0, NULL, (void*) &appData.dropMenu, "", NULL, CheckBox, N_("Drop Menu") },
{ 0, 0, 0, NULL, (void*) &appData.variations, "", NULL, CheckBox, N_("Enable Variation Trees") },
{ 0, 0, 0, NULL, (void*) &appData.hideThinkingFromHuman, "", NULL, CheckBox, N_("Hide Thinking from Human") },
static void Pick P((int n));
static char warning[MSG_SIZ];
+static int ranksTmp, filesTmp, sizeTmp;
static Option variantDescriptors[] = {
-{ VariantNormal, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("normal")},
-{ VariantMakruk, SAME_ROW, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("makruk")},
+{ VariantNormal, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("Normal")},
+{ VariantMakruk, SAME_ROW, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("Makruk")},
{ VariantFischeRandom, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("FRC")},
-{ VariantShatranj,SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("shatranj")},
-{ VariantWildCastle, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("wild castle")},
-{ VariantKnightmate,SAME_ROW,135,NULL,(void*) &Pick, "#FFFFFF", NULL, Button, N_("knightmate")},
-{ VariantNoCastle, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("no castle")},
-{ VariantCylinder,SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("cylinder *")},
+{ VariantShatranj,SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("Shatranj")},
+{ VariantWildCastle, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("Wild castle")},
+{ VariantKnightmate,SAME_ROW,135,NULL,(void*) &Pick, "#FFFFFF", NULL, Button, N_("Knightmate")},
+{ VariantNoCastle, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("No castle")},
+{ VariantCylinder,SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("Cylinder *")},
{ Variant3Check, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("3-checks")},
{ VariantBerolina,SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("berolina *")},
{ VariantAtomic, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("atomic")},
{ VariantTwoKings,SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("two kings")},
+{ -1, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_(" ")}, // dummy, to have good alignment
+{ VariantSpartan,SAME_ROW, 135, NULL, (void*) &Pick, "#FF0000", NULL, Button, N_("Spartan")},
{ 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("Board size ( -1 = default for selected variant):")},
-{ 0, -1, BOARD_RANKS-1, NULL, (void*) &appData.NrRanks, "", NULL, Spin, N_("Number of Board Ranks:") },
-{ 0, -1, BOARD_FILES, NULL, (void*) &appData.NrFiles, "", NULL, Spin, N_("Number of Board Files:") },
-{ 0, -1, BOARD_RANKS-1, NULL, (void*) &appData.holdingsSize, "", NULL, Spin, N_("Holdings Size:") },
+{ 0, -1, BOARD_RANKS-1, NULL, (void*) &ranksTmp, "", NULL, Spin, N_("Number of Board Ranks:") },
+{ 0, -1, BOARD_FILES, NULL, (void*) &filesTmp, "", NULL, Spin, N_("Number of Board Files:") },
+{ 0, -1, BOARD_RANKS-1, NULL, (void*) &sizeTmp, "", NULL, Spin, N_("Holdings Size:") },
{ 0, 0, 275, NULL, NULL, NULL, NULL, Label, warning },
-{ 0, 0, 275, NULL, NULL, NULL, NULL, Label, "Variants marked with * can only be played\nwith legality testing off"},
+{ 0, 0, 275, NULL, NULL, NULL, NULL, Label, N_("Variants marked with * can only be played\nwith legality testing off.")},
{ 0, SAME_ROW, 0, NULL, NULL, NULL, NULL, Break, ""},
-{ VariantFairy, 0, 135, NULL, (void*) &Pick, "#BFBFBF", NULL, Button, N_("fairy")},
+{ VariantASEAN, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("ASEAN")},
{ VariantGreat, SAME_ROW, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("Great Shatranj (10x8)")},
{ VariantSChess, 0, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("Seirawan")},
-{ VariantFalcon, SAME_ROW, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("falcon (10x8)")},
+{ VariantFalcon, SAME_ROW, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("Falcon (10x8)")},
{ VariantSuper, 0, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("Superchess")},
{ VariantCapablanca,SAME_ROW,135,NULL,(void*) &Pick, "#BFBFFF", NULL, Button, N_("Capablanca (10x8)")},
-{ VariantCrazyhouse, 0, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("crazyhouse")},
+{ VariantCrazyhouse, 0, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("Crazyhouse")},
{ VariantGothic, SAME_ROW, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("Gothic (10x8)")},
-{ VariantBughouse, 0, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("bughouse")},
-{ VariantJanus, SAME_ROW, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("janus (10x8)")},
-{ VariantSuicide, 0, 135, NULL, (void*) &Pick, "#FFFFBF", NULL, Button, N_("suicide")},
+{ VariantBughouse, 0, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("Bughouse")},
+{ VariantJanus, SAME_ROW, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("Janus (10x8)")},
+{ VariantSuicide, 0, 135, NULL, (void*) &Pick, "#FFFFBF", NULL, Button, N_("Suicide")},
{ VariantCapaRandom,SAME_ROW,135,NULL,(void*) &Pick, "#BFBFFF", NULL, Button, N_("CRC (10x8)")},
{ VariantGiveaway, 0, 135, NULL, (void*) &Pick, "#FFFFBF", NULL, Button, N_("give-away")},
{ VariantGrand, SAME_ROW, 135, NULL, (void*) &Pick, "#5070FF", NULL, Button, N_("grand (10x10)")},
{ VariantLosers, 0, 135, NULL, (void*) &Pick, "#FFFFBF", NULL, Button, N_("losers")},
{ VariantShogi, SAME_ROW, 135, NULL, (void*) &Pick, "#BFFFFF", NULL, Button, N_("shogi (9x9)")},
-{ VariantSpartan, 0, 135, NULL, (void*) &Pick, "#FF0000", NULL, Button, N_("Spartan")},
+{ VariantFairy, 0, 135, NULL, (void*) &Pick, "#BFBFBF", NULL, Button, N_("fairy")},
{ VariantXiangqi, SAME_ROW,135, NULL, (void*) &Pick, "#BFFFFF", NULL, Button, N_("xiangqi (9x10)")},
-{ -1, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_(" ")}, // dummy, to have good alignment
+{ VariantLion, 0, 135, NULL, (void*) &Pick, "#BFBFBF", NULL, Button, N_("mighty lion")},
{ VariantCourier, SAME_ROW,135, NULL, (void*) &Pick, "#BFFFBF", NULL, Button, N_("courier (12x8)")},
+{ VariantChuChess, 0, 135, NULL, (void*) &Pick, "#BFBFBF", NULL, Button, N_("chu chess (10x10)")},
+{ VariantChu, SAME_ROW, 135, NULL, (void*) &Pick, "#BFFFBF", NULL, Button, N_("chu shogi (12x12)")},
+//{ -1, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_(" ")}, // dummy, to have good alignment
+// optional buttons for engine-defined variants
+{ VariantUnknown, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
{ 0, NO_OK, 0, NULL, NULL, "", NULL, EndMark , "" }
};
Pick (int n)
{
VariantClass v = variantDescriptors[n].value;
+ if(v == VariantUnknown) safeStrCpy(engineVariant, variantDescriptors[n].name, MSG_SIZ); else *engineVariant = NULLCHAR;
+ GenericReadout(variantDescriptors, -1); // read new ranks and file settings
if(!appData.noChessProgram) {
- char *name = VariantName(v), buf[MSG_SIZ];
- if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) {
- /* [HGM] in protocol 2 we check if variant is suported by engine */
- snprintf(buf, MSG_SIZ, _("Variant %s not supported by %s"), name, first.tidy);
- DisplayError(buf, 0);
+ char buf[MSG_SIZ];
+ if (!SupportedVariant(first.variants, v, filesTmp, ranksTmp, sizeTmp, first.protocolVersion, first.tidy)) {
+ DisplayError(variantError, 0);
return; /* ignore OK if first engine does not support it */
} else
- if (second.initDone && second.protocolVersion > 1 && StrStr(second.variants, name) == NULL) {
- snprintf(buf, MSG_SIZ, _("Warning: second engine (%s) does not support this!"), second.tidy);
+ if (second.initDone &&
+ !SupportedVariant(second.variants, v, filesTmp, ranksTmp, sizeTmp, second.protocolVersion, second.tidy)) {
+ snprintf(buf, MSG_SIZ, _("Warning: second engine (%s) does not support this!"), second.tidy);
DisplayError(buf, 0); /* use of second engine is optional; only warn user */
}
}
- GenericReadout(variantDescriptors, -1); // make sure ranks and file settings are read
-
gameInfo.variant = v;
appData.variant = VariantName(v);
shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */
startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */
+ appData.NrRanks = ranksTmp;
+ appData.NrFiles = filesTmp;
+ appData.holdingsSize = sizeTmp;
appData.pieceToCharTable = NULL;
appData.pieceNickNames = "";
appData.colorNickNames = "";
void
NewVariantProc ()
{
- if(appData.noChessProgram) sprintf(warning, _("Only bughouse is not available in viewer mode")); else
- sprintf(warning, _("All variants not supported by first engine\n(currently %s) are disabled"), first.tidy);
+ static int start;
+ int i, last;
+ char buf[MSG_SIZ];
+ ranksTmp = filesTmp = sizeTmp = -1; // prefer defaults over actual settings
+ if(appData.noChessProgram) sprintf(warning, _("Only bughouse is not available in viewer mode.")); else
+ sprintf(warning, _("All variants not supported by the first engine\n(currently %s) are disabled."), first.tidy);
+ if(!start) while(variantDescriptors[start].type != -1) start++; // locate first spare
+ last = -1;
+ for(i=0; variantDescriptors[start+i].type != EndMark; i++) { // create buttons for engine-defined variants
+ char *v = EngineDefinedVariant(&first, i);
+ if(v) {
+ last = i;
+ ASSIGN(variantDescriptors[start+i].name, v);
+ variantDescriptors[start+i].type = Button;
+ } else variantDescriptors[start+i].type = -1;
+ }
+ if(!(last&1)) { // odd number, add filler
+ ASSIGN(variantDescriptors[start+last+1].name, " ");
+ variantDescriptors[start+last+1].type = Button;
+ variantDescriptors[start+last+1].value = -1;
+ }
+ safeStrCpy(buf, engineVariant, MSG_SIZ); *engineVariant = NULLCHAR; // yeghh...
GenericPopUp(variantDescriptors, _("New Variant"), TransientDlg, BoardWindow, MODAL, 0);
+ safeStrCpy(engineVariant, buf, MSG_SIZ); // must temporarily clear to avoid enabling all variant buttons
}
//------------------------------------------- Common Engine Options -------------------------------------
{ 0, 0, 0, NULL, (void*) &appData.seekGraph, "", NULL, CheckBox, N_("Seek Graph") },
{ 0, 0, 0, NULL, (void*) &appData.autoRefresh, "", NULL, CheckBox, N_("Auto-Refresh Seek Graph") },
{ 0, 0, 0, NULL, (void*) &appData.autoBox, "", NULL, CheckBox, N_("Auto-InputBox PopUp") },
+{ 0, 0, 0, NULL, (void*) &appData.quitNext, "", NULL, CheckBox, N_("Quit after game") },
{ 0, 0, 0, NULL, (void*) &appData.premove, "", NULL, CheckBox, N_("Premove") },
{ 0, 0, 0, NULL, (void*) &appData.premoveWhite, "", NULL, CheckBox, N_("Premove for White") },
{ 0, 0, 0, NULL, (void*) &appData.premoveWhiteText, "", NULL, TextBox, N_("First White Move:") },
N_("Penalty"),
N_("Phone"),
N_("Pop"),
+ N_("Roar"),
N_("Slap"),
N_("Wood Thunk"),
NULL,
"penalty.wav",
"phone.wav",
"pop2.wav",
+ "roar.wav",
"slap.wav",
"woodthunk.wav",
NULL,
{ 0, 0, 0, NULL, (void*) &appData.soundTell, (char*) soundFiles, soundNames, ComboBox, N_("Tell:") },
{ 0, 0, 0, NULL, (void*) &appData.soundKibitz, (char*) soundFiles, soundNames, ComboBox, N_("Kibitz:") },
{ 0, 0, 0, NULL, (void*) &appData.soundRequest, (char*) soundFiles, soundNames, ComboBox, N_("Request:") },
+{ 0, 0, 0, NULL, (void*) &appData.soundRoar, (char*) soundFiles, soundNames, ComboBox, N_("Lion roar:") },
{ 0, 0, 0, NULL, (void*) &appData.soundSeek, (char*) soundFiles, soundNames, ComboBox, N_("Seek:") },
{ 0, SAME_ROW, 0, NULL, NULL, "", NULL, EndMark , "" }
};
{ 0, 0, 0, NULL, (void*) &appData.upsideDown, "", NULL, CheckBox, N_("Flip Pieces Shogi Style (Colored buttons restore default)") },
//{ 0, 0, 0, NULL, (void*) &appData.allWhite, "", NULL, CheckBox, N_("Use Outline Pieces for Black") },
{ 0, 0, 0, NULL, (void*) &appData.monoMode, "", NULL, CheckBox, N_("Mono Mode") },
-{ 0,-1, 5, NULL, (void*) &appData.overrideLineGap, "", NULL, Spin, N_("Line Gap ( -1 = default for board size):") },
+{ 0,-1, 5, NULL, (void*) &appData.overrideLineGap, "", NULL, Spin, N_("Line Gap (-1 = default for board size):") },
{ 0, 0, 0, NULL, (void*) &appData.useBitmaps, "", NULL, CheckBox, N_("Use Board Textures") },
{ 0, 0, 0, NULL, (void*) &appData.liteBackTextureFile, ".png", NULL, FileName, N_("Light-Squares Texture File:") },
{ 0, 0, 0, NULL, (void*) &appData.darkBackTextureFile, ".png", NULL, FileName, N_("Dark-Squares Texture File:") },
static int
NewTagsCallback (int n)
{
- ReplaceTags(tagsText, &gameInfo);
+ if(!bookUp) ReplaceTags(tagsText, &gameInfo);
return 1;
}
changeTags (int n)
{
GenericReadout(tagsOptions, 1);
- if(bookUp) SaveToBook(tagsText); else
+ if(bookUp) SaveToBook(tagsText), DisplayBook(currentMove); else
ReplaceTags(tagsText, &gameInfo);
}
}
static Option shuffleOptions[] = {
- { 0, 0, 50, NULL, (void*) &shuffleOpenings, NULL, NULL, CheckBox, N_("shuffle") },
+ { 0, 0, 0, NULL, (void*) &shuffleOpenings, NULL, NULL, CheckBox, N_("shuffle") },
{ 0,-1,2000000000, NULL, (void*) &appData.defaultFrcPosition, "", NULL, Spin, N_("Start-position number:") },
{ 0, 0, 0, NULL, (void*) &SetRandom, NULL, NULL, Button, N_("randomize") },
{ 0, SAME_ROW, 0, NULL, (void*) &SetRandom, NULL, NULL, Button, N_("pick fixed") },
ClearHighlights();
return;
}
+ if(promoChar == '=' && !IS_SHOGI(gameInfo.variant)) promoChar = NULLCHAR;
UserMoveEvent(fromX, fromY, toX, toY, promoChar);
if (!appData.highlightLastMove || gotPremove) ClearHighlights();
}
void
-PromotionPopUp ()
+PromotionPopUp (char choice)
{ // choice depends on variant: prepare dialog acordingly
count = 8;
- SetPromo(_("Cancel"), --count, 0); // Beware: GenericPopUp cannot handle user buttons named "cancel" (lowe case)!
- if(gameInfo.variant != VariantShogi) {
+ SetPromo(_("Cancel"), --count, -1); // Beware: GenericPopUp cannot handle user buttons named "cancel" (lowe case)!
+ if(choice != '+') {
if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) ||
gameInfo.variant == VariantGiveaway) {
SetPromo(_("Chancellor"), --count, 'c');
}
SetPromo(_("Queen"), --count, 'q');
+ if(gameInfo.variant == VariantChuChess)
+ SetPromo(_("Lion"), --count, 'l');
}
} else // [HGM] shogi
{
Exp (int n, int x, int y)
{
static int but1, but3, oldW, oldH;
- int menuNr = -3, sizing;
+ int menuNr = -3, sizing, f, r;
if(n == 0) { // motion
if(SeekGraphClick(Press, x, y, 1)) return NULL;
- if(but1 && !PromoScroll(x, y)) DragPieceMove(x, y);
+ if((but1 || dragging == 2) && !PromoScroll(x, y)) DragPieceMove(x, y);
if(but3) MovePV(x, y, lineGap + BOARD_HEIGHT * (squareSize + lineGap));
+ if(appData.highlightDragging) {
+ f = EventToSquare(x, BOARD_WIDTH); if ( flipView && f >= 0) f = BOARD_WIDTH - 1 - f;
+ r = EventToSquare(y, BOARD_HEIGHT); if (!flipView && r >= 0) r = BOARD_HEIGHT - 1 - r;
+ HoverEvent(x, y, f, r);
+ }
return NULL;
}
if(n != 10 && PopDown(PromoDlg)) fromX = fromY = -1; // user starts fiddling with board when promotion dialog is up
".trn",
".bin",
".wav",
-".xpm",
".ini",
".log",
"",
SetWidgetLabel(&browseOptions[0], title);
}
+ static char msg1[] = N_("FIRST TYPE DIRECTORY NAME HERE");
+ static char msg2[] = N_("TRY ANOTHER NAME");
+
void
CreateDir (int n)
{
char *name, *errmsg = "";
GetWidgetText(&browseOptions[n-1], &name);
- if(!name[0]) errmsg = _("FIRST TYPE DIRECTORY NAME HERE"); else
- if(mkdir(name, 0755)) errmsg = _("TRY ANOTHER NAME");
+ if(!strcmp(name, msg1) || !strcmp(name, msg2)) return;
+ if(!name[0]) errmsg = _(msg1); else
+ if(mkdir(name, 0755)) errmsg = _(msg2);
else {
chdir(name);
Refresh(-1);
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* The following terms apply to Digital Equipment Corporation's copyright
* interest in XBoard:
for(p=0; p<=(int)WhiteKing; p++)
pngPieceBitmaps[i][p] = pngPieceBitmaps2[i][p]; // defaults
if(v == VariantShogi) {
- pngPieceBitmaps[i][(int)WhiteCannon] = pngPieceBitmaps2[i][(int)WhiteKing+1];
+ pngPieceBitmaps[i][(int)WhiteCannon] = pngPieceBitmaps2[i][(int)WhiteTokin];
pngPieceBitmaps[i][(int)WhiteNightrider] = pngPieceBitmaps2[i][(int)WhiteKing+2];
- pngPieceBitmaps[i][(int)WhiteSilver] = pngPieceBitmaps2[i][(int)WhiteKing+3];
- pngPieceBitmaps[i][(int)WhiteGrasshopper] = pngPieceBitmaps2[i][(int)WhiteKing+4];
+ pngPieceBitmaps[i][(int)WhiteGrasshopper] = pngPieceBitmaps2[i][(int)WhiteKing+3];
+ pngPieceBitmaps[i][(int)WhiteSilver] = pngPieceBitmaps2[i][(int)WhiteKing+4];
pngPieceBitmaps[i][(int)WhiteQueen] = pngPieceBitmaps2[i][(int)WhiteLance];
+ pngPieceBitmaps[i][(int)WhiteFalcon] = pngPieceBitmaps2[i][(int)WhiteMonarch]; // for Sho Shogi
}
#ifdef GOTHIC
if(v == VariantGothic) {
pngPieceBitmaps[i][(int)WhiteAngel] = pngPieceBitmaps2[i][(int)WhiteFalcon];
pngPieceBitmaps[i][(int)WhiteMarshall] = pngPieceBitmaps2[i][(int)WhiteAlfil];
}
+ if(v == VariantChuChess) {
+ pngPieceBitmaps[i][(int)WhiteNightrider] = pngPieceBitmaps2[i][(int)WhiteLion];
+ }
+ if(v == VariantChu) {
+ pngPieceBitmaps[i][(int)WhiteNightrider] = pngPieceBitmaps2[i][(int)WhiteKing+1];
+ pngPieceBitmaps[i][(int)WhiteUnicorn] = pngPieceBitmaps2[i][(int)WhiteCat];
+ pngPieceBitmaps[i][(int)WhiteSilver] = pngPieceBitmaps2[i][(int)WhiteSword];
+ pngPieceBitmaps[i][(int)WhiteFalcon] = pngPieceBitmaps2[i][(int)WhiteDagger];
+ }
}
}
char *pngPieceNames[] = // must be in same order as internal piece encoding
{ "Pawn", "Knight", "Bishop", "Rook", "Queen", "Advisor", "Elephant", "Archbishop", "Marshall", "Gold", "Commoner",
- "Canon", "Nightrider", "CrownedBishop", "CrownedRook", "Princess", "Chancellor", "Hawk", "Lance", "Cobra", "Unicorn", "King",
- "GoldKnight", "GoldLance", "GoldPawn", "GoldSilver", NULL
+ "Canon", "Nightrider", "CrownedBishop", "CrownedRook", "Princess", "Chancellor", "Hawk", "Lance", "Cobra", "Unicorn", "Lion",
+ "GoldPawn", "HSword", "PromoHorse", "PromoDragon", "Leopard", "PromoSword", "Prince", "Phoenix", "Kylin", "PromoRook", "PromoHSword",
+ "Dolphin", "Chancellor", "Unicorn", "Hawk", "Sword", "Princess", "HCrown", "Knight", "Elephant", "PromoBishop", "King",
+ "Claw", "GoldKnight", "GoldLance", "GoldSilver", NULL
};
+char *backupPiece[] = { "King", "Queen", "Lion" }; // pieces that map on other when not kanji
+
RsvgHandle *
-LoadSVG (char *dir, int color, int piece)
+LoadSVG (char *dir, int color, int piece, int retry)
{
char buf[MSG_SIZ];
RsvgHandle *svg=svgPieces[color][piece];
cairo_surface_t *img;
cairo_t *cr;
- snprintf(buf, MSG_SIZ, "%s/%s%s.svg", dir, color ? "Black" : "White", pngPieceNames[piece]);
+ snprintf(buf, MSG_SIZ, "%s/%s%s.svg", dir, color ? "Black" : "White",
+ retry ? backupPiece[piece - WhiteMonarch] : pngPieceNames[piece]);
if(svg || *dir && (svg = rsvg_handle_new_from_file(buf, &svgerror))) {
return svg;
}
+ if(!retry && piece >= WhiteMonarch && piece <= WhiteNothing) // pieces that are only different in kanji sets
+ return LoadSVG(dir, color, piece, 1);
if(svgerror)
g_error_free(svgerror);
return NULL;
g_type_init ();
- svgPieces[color][piece] = LoadSVG("", color, piece); // this fills pngPieceImages if we had cached svg with bitmap of wanted size
+ svgPieces[color][piece] = LoadSVG("", color, piece, 0); // this fills pngPieceImages if we had cached svg with bitmap of wanted size
if(!pngPieceImages[color][piece]) { // we don't have cached bitmap (implying we did not have cached svg)
if(*appData.pieceDirectory) { // user specified piece directory
snprintf(buf, MSG_SIZ, "%s/%s%s.png", appData.pieceDirectory, color ? "Black" : "White", pngPieceNames[piece]);
img = cairo_image_surface_create_from_png (buf); // try if there are png pieces there
if(cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) { // there were not
- svgPieces[color][piece] = LoadSVG(appData.pieceDirectory, color, piece); // so try if he has svg there
+ svgPieces[color][piece] = LoadSVG(appData.pieceDirectory, color, piece, 0); // so try if he has svg there
} else pngPieceImages[color][piece] = img;
}
}
if(!pngPieceImages[color][piece]) { // we still did not manage to acquire a piece bitmap
static int warned = 0;
- if(!(svgPieces[color][piece] = LoadSVG(SVGDIR, color, piece)) && !warned) { // try to fall back on installed svg
- char *msg = _("No default pieces installed\nSelect your own -pieceImageDirectory");
+ if(!(svgPieces[color][piece] = LoadSVG(SVGDIR, color, piece, 0)) && !warned) { // try to fall back on installed svg
+ char *msg = _("No default pieces installed!\nSelect your own using '-pieceImageDirectory'.");
printf("%s\n", msg); // give up
DisplayError(msg, 0);
warned = 1; // prevent error message being repeated for each piece type
cairo_destroy (cr);
}
+static char *markerColor[8] = { "#FFFF00", "#FF0000", "#00FF00", "#0000FF", "#00FFFF", "#FF00FF", "#FFFFFF", "#000000" };
+
void
DoDrawDot (cairo_surface_t *cs, int marker, int x, int y, int r)
{
cairo_stroke_preserve(cr);
SetPen(cr, 2, marker == 2 ? "#FFFFFF" : "#000000", 0);
} else {
- SetPen(cr, 2, marker == 2 ? "#FF0000" : "#FFFF00", 0);
+ SetPen(cr, 2, markerColor[marker-1], 0);
}
cairo_fill(cr);
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
void PopUpMoveDialog P((char first));
void RingBell P((void));
+int Roar P((void));
void PlayIcsWinSound P((void));
void PlayIcsLossSound P((void));
void PlayIcsDrawSound P((void));
void PlayIcsUnfinishedSound P((void));
void PlayAlarmSound P((void));
void PlayTellSound P((void));
-void PlaySoundFile P((char *name));
+int PlaySoundFile P((char *name));
void PlaySoundByColor P((void));
void EchoOn P((void));
void EchoOff P((void));
void CancelDelayedEvent P((void));
// [HGM] mouse: next six used by mouse handler, which was moved to backend
extern int fromX, fromY, toX, toY;
-void PromotionPopUp P((void));
+void PromotionPopUp P((char choice));
void DragPieceBegin P((int x, int y, Boolean instantly));
void DragPieceEnd P((int x, int y));
void DragPieceMove P((int x, int y));
typedef struct FrontEndProgramStats_TAG {
int which;
int depth;
- unsigned long nodes;
+ u64 nodes;
int score;
int time;
char * pv;
/*
* gamelist.c -- Functions to manage a gamelist
*
- * Copyright 1995, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * Copyright 1995, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
} while (cm == PGNTag || cm == Comment);
if(1) {
int btm=0;
- if(currentListGame->gameInfo.fen) ParseFEN(boards[scratch], &btm, currentListGame->gameInfo.fen);
+ if(currentListGame->gameInfo.fen) ParseFEN(boards[scratch], &btm, currentListGame->gameInfo.fen, FALSE);
else CopyBoard(boards[scratch], initialPosition);
plyNr = (btm != 0);
currentListGame->moves = PackGame(boards[scratch]);
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* The following terms apply to Digital Equipment Corporation's copyright
* interest in XBoard:
#include "gettext.h"
#include "draw.h"
- #ifdef OSX
- # include "gtkmacintegration/gtkosxapplication.h"
+ #ifdef __APPLE__
+ # include <gtkmacintegration/gtkosxapplication.h>
// prevent pathname of positional file argument provided by OS X being be mistaken for option name
// (price is that we won't recognize Windows option format anymore).
# define SLASH '-'
// redefine some defaults
# undef ICS_LOGON
# undef SYSCONFDIR
+# undef DATADIR
# define ICS_LOGON "Library/Preferences/XboardICS.conf"
# define SYSCONFDIR "../etc"
# define DATADIR dataDir
char *dataDir; // for expanding ~~
#else
# define SLASH '/'
+ # define DATADIR "~~"
#endif
#ifdef __EMX__
case ArgTwo:
case ArgNone:
case ArgCommSettings:
+ default:
break;
}
return p;
gtk_window_resize(GTK_WINDOW(shells[DummyDlg]), slaveW + opt->max, slaveH + opt->value);
}
- #ifdef OSX
+ #ifdef __APPLE__
static char clickedFile[MSG_SIZ];
static int suppress;
debugFP = stderr;
if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
- printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+ printf("%s version %s\n\n configure options: %s\n", PACKAGE_NAME, PACKAGE_VERSION, CONFIGURE_OPTIONS);
exit(0);
}
/* set up GTK */
gtk_init (&argc, &argv);
- #ifdef OSX
+ #ifdef __APPLE__
{ // prepare to catch OX OpenFile signal, which will tell us the clicked file
GtkosxApplication *theApp = g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
dataDir = gtkosx_application_get_bundle_path();
void
ManProc ()
{ // called from menu
- #ifdef OSX
+ #ifdef __APPLE__
system("%s ./man.command", appData.sysOpen);
#else
system("xterm -e man xboard &");
/*
* xoptions.c -- Move list window, part of X front end for XBoard
*
- * Copyright 2000, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * Copyright 2000, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
* ------------------------------------------------------------------------
*
* GNU XBoard is free software: you can redistribute it and/or modify
#include <cairo/cairo-xlib.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
- #ifdef OSX
- # include "gtkmacintegration/gtkosxapplication.h"
+ #ifdef __APPLE__
+ # include <gtkmacintegration/gtkosxapplication.h>
#endif
#include "common.h"
{
char *msg = mb[i].string;
if(!msg) break;
- #ifdef OSX
+ #ifdef __APPLE__
if(!strcmp(msg, "Quit ")) continue; // Quit item will appear automatically in App menu
if(!strcmp(msg, "About XBoard")) msg = "About"; // 'XBoard' will be appended automatically when moved to App menu 1st item
#endif
GdkModifierType accelerator_mods;
gtk_accelerator_parse(mb[i].accel, &accelerator_key, &accelerator_mods);
- #ifdef OSX
+ #ifdef __APPLE__
if(accelerator_mods & GDK_CONTROL_MASK) { // in OSX use Meta where Linux uses Ctrl
accelerator_mods &= ~GDK_CONTROL_MASK; // clear Ctrl flag
accelerator_mods |= GDK_META_MASK; // set Meta flag
-- }
++ }
#endif
gtk_widget_add_accelerator (GTK_WIDGET(entry), "activate",GtkAccelerators,
accelerator_key, accelerator_mods, GTK_ACCEL_VISIBLE);
break;
case BarEnd:
top--;
- #ifndef OSX
+ #ifndef __APPLE__
gtk_table_attach(GTK_TABLE(table), menuBar, left, left+r, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 1);
if(option[i].target) ((ButtonCallback*)option[i].target)(boxStart); // callback that can make sizing decisions
gtkosx_application_set_menu_bar(theApp, GTK_MENU_SHELL(menuBar));
gtkosx_application_insert_app_menu_item(theApp, GTK_MENU_ITEM(helpMenu[8].handle), 0); // hack
gtkosx_application_sync_menubar(theApp);
-- }
++ }
#endif
break;
case BoxEnd:
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* The following terms apply to Digital Equipment Corporation's copyright
* interest in XBoard:
static char *selected_fen_position=NULL;
if(gameMode == EditPosition) EditPositionDone(TRUE);
if (selected_fen_position) free(selected_fen_position);
- selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
+ selected_fen_position = (char *)PositionToFEN(currentMove, NULL, 1);
if (!selected_fen_position) return;
CopySomething(selected_fen_position);
}
MenuItem fileMenu[] = {
{N_("New Game"), "<Ctrl>n", "NewGame", ResetGameEvent},
- {N_("New Shuffle Game ..."), NULL, "NewShuffleGame", ShuffleMenuProc},
- {N_("New Variant ..."), "<Alt><Shift>v", "NewVariant", NewVariantProc},// [HGM] variant: not functional yet
+ {N_("New Shuffle Game..."), NULL, "NewShuffleGame", ShuffleMenuProc},
+ {N_("New Variant..."), "<Alt><Shift>v", "NewVariant", NewVariantProc},// [HGM] variant: not functional yet
{"----", NULL, NULL, NothingProc},
{N_("Load Game"), "<Ctrl>o", "LoadGame", LoadGameProc, CHECK},
{N_("Load Position"), "<Ctrl><Shift>o", "LoadPosition", LoadPositionProc},
};
MenuItem engineMenu[100] = {
- {N_("Load New 1st Engine ..."), NULL, "LoadNew1stEngine", LoadEngine1Proc},
- {N_("Load New 2nd Engine ..."), NULL, "LoadNew2ndEngine", LoadEngine2Proc},
+ {N_("Load New 1st Engine..."), NULL, "LoadNew1stEngine", LoadEngine1Proc},
+ {N_("Load New 2nd Engine..."), NULL, "LoadNew2ndEngine", LoadEngine2Proc},
{"----", NULL, NULL, NothingProc},
- {N_("Engine #1 Settings ..."), NULL, "Engine#1Settings", FirstSettingsProc},
- {N_("Engine #2 Settings ..."), NULL, "Engine#2Settings", SecondSettingsProc},
+ {N_("Engine #1 Settings..."), NULL, "Engine#1Settings", FirstSettingsProc},
+ {N_("Engine #2 Settings..."), NULL, "Engine#2Settings", SecondSettingsProc},
{"----", NULL, NULL, NothingProc},
{N_("Hint"), NULL, "Hint", HintEvent},
{N_("Book"), NULL, "Book", BookEvent},
MenuItem optionsMenu[] = {
#ifdef OPTIONSDIALOG
- {N_("General ..."), NULL, "General", OptionsProc},
+ {N_("General..."), NULL, "General", OptionsProc},
#endif
- {N_("Time Control ..."), "<Alt><Shift>t", "TimeControl", TimeControlProc},
- {N_("Common Engine ..."), "<Alt><Shift>u", "CommonEngine", UciMenuProc},
- {N_("Adjudications ..."), "<Alt><Shift>j", "Adjudications", EngineMenuProc},
- {N_("ICS ..."), NULL, "ICS", IcsOptionsProc},
- {N_("Match ..."), NULL, "Match", MatchOptionsProc},
- {N_("Load Game ..."), NULL, "LoadGame", LoadOptionsProc},
- {N_("Save Game ..."), NULL, "SaveGame", SaveOptionsProc},
- {N_("Game List ..."), NULL, "GameList", GameListOptionsProc},
- {N_("Sounds ..."), NULL, "Sounds", SoundOptionsProc},
+ {N_("Time Control..."), "<Alt><Shift>t", "TimeControl", TimeControlProc},
+ {N_("Common Engine..."), "<Alt><Shift>u", "CommonEngine", UciMenuProc},
+ {N_("Adjudications..."), "<Alt><Shift>j", "Adjudications", EngineMenuProc},
+ {N_("ICS..."), NULL, "ICS", IcsOptionsProc},
+ {N_("Tournament..."), NULL, "Match", MatchOptionsProc},
+ {N_("Load Game..."), NULL, "LoadGame", LoadOptionsProc},
+ {N_("Save Game..."), NULL, "SaveGame", SaveOptionsProc},
+ {N_("Game List..."), NULL, "GameList", GameListOptionsProc},
+ {N_("Sounds..."), NULL, "Sounds", SoundOptionsProc},
{"----", NULL, NULL, NothingProc},
#ifndef OPTIONSDIALOG
{N_("Always Queen"), "<Ctrl><Shift>q", "AlwaysQueen", AlwaysQueenProc},
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
(int) piece2 < (int) EmptySquare);
}
#else
-#define SameColor(piece1, piece2) (piece1 < EmptySquare && piece2 < EmptySquare && (piece1 < BlackPawn) == (piece2 < BlackPawn))
+#define SameColor(piece1, piece2) (piece1 < EmptySquare && piece2 < EmptySquare && (piece1 < BlackPawn) == (piece2 < BlackPawn) || piece1 == DarkSquare || piece2 == DarkSquare)
#endif
char pieceToChar[] = {
return TRUE;
}
+// [HGM] move generation now based on hierarchy of subroutines for rays and combinations of rays
+
+void
+SlideForward (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ int i, rt, ft = ff;
+ for (i = 1;; i++) {
+ rt = rf + i;
+ if (rt >= BOARD_HEIGHT) break;
+ if (SameColor(board[rf][ff], board[rt][ft])) break;
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+ if (board[rt][ft] != EmptySquare) break;
+ }
+}
+
+void
+SlideBackward (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ int i, rt, ft = ff;
+ for (i = 1;; i++) {
+ rt = rf - i;
+ if (rt < 0) break;
+ if (SameColor(board[rf][ff], board[rt][ft])) break;
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+ if (board[rt][ft] != EmptySquare) break;
+ }
+}
+
+void
+SlideVertical (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ SlideForward(board, flags, rf, ff, callback, closure);
+ SlideBackward(board, flags, rf, ff, callback, closure);
+}
+
+void
+SlideSideways (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ int i, s, rt = rf, ft;
+ for(s = -1; s <= 1; s+= 2) {
+ for (i = 1;; i++) {
+ ft = ff + i*s;
+ if (ft < BOARD_LEFT || ft >= BOARD_RGHT) break;
+ if (SameColor(board[rf][ff], board[rt][ft])) break;
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+ if (board[rt][ft] != EmptySquare) break;
+ }
+ }
+}
+
+void
+SlideDiagForward (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ int i, s, rt, ft;
+ for(s = -1; s <= 1; s+= 2) {
+ for (i = 1;; i++) {
+ rt = rf + i;
+ ft = ff + i * s;
+ if (rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break;
+ if (SameColor(board[rf][ff], board[rt][ft])) break;
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+ if (board[rt][ft] != EmptySquare) break;
+ }
+ }
+}
+
+void
+SlideDiagBackward (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ int i, s, rt, ft;
+ for(s = -1; s <= 1; s+= 2) {
+ for (i = 1;; i++) {
+ rt = rf - i;
+ ft = ff + i * s;
+ if (rt < 0 || ft < BOARD_LEFT || ft >= BOARD_RGHT) break;
+ if (SameColor(board[rf][ff], board[rt][ft])) break;
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+ if (board[rt][ft] != EmptySquare) break;
+ }
+ }
+}
+
+void
+Rook (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ SlideVertical(board, flags, rf, ff, callback, closure);
+ SlideSideways(board, flags, rf, ff, callback, closure);
+}
+
+void
+Bishop (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ SlideDiagForward(board, flags, rf, ff, callback, closure);
+ SlideDiagBackward(board, flags, rf, ff, callback, closure);
+}
+
+void
+Sting (Board board, int flags, int rf, int ff, int dy, int dx, MoveCallback callback, VOIDSTAR closure)
+{ // Lion-like move of Horned Falcon and Souring Eagle
+ int ft = ff + dx, rt = rf + dy;
+ if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) return;
+ if (!SameColor(board[rf][ff], board[rt][ft]))
+ callback(board, flags, board[rt][ft] != EmptySquare ? FirstLeg : NormalMove, rf, ff, rt, ft, closure);
+ ft += dx; rt += dy;
+ if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) return;
+ if (!SameColor(board[rf][ff], board[rt][ft]))
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+}
+
+void
+StepForward (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ int ft = ff, rt = rf + 1;
+ if (rt >= BOARD_HEIGHT) return;
+ if (SameColor(board[rf][ff], board[rt][ft])) return;
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+}
+
+void
+StepBackward (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ int ft = ff, rt = rf - 1;
+ if (rt < 0) return;
+ if (SameColor(board[rf][ff], board[rt][ft])) return;
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+}
+
+void
+StepSideways (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ int ft, rt = rf;
+ ft = ff + 1;
+ if (!(rt >= BOARD_HEIGHT || ft >= BOARD_RGHT) && !SameColor(board[rf][ff], board[rt][ft]))
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+ ft = ff - 1;
+ if (!(rt >= BOARD_HEIGHT || ft < BOARD_LEFT) && !SameColor(board[rf][ff], board[rt][ft]))
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+}
+
+void
+StepDiagForward (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ int ft, rt = rf + 1;
+ if (rt >= BOARD_HEIGHT) return;
+ ft = ff + 1;
+ if (!(rt >= BOARD_HEIGHT || ft >= BOARD_RGHT) && !SameColor(board[rf][ff], board[rt][ft]))
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+ ft = ff - 1;
+ if (!(rt >= BOARD_HEIGHT || ft < BOARD_LEFT) && !SameColor(board[rf][ff], board[rt][ft]))
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+}
+
+void
+StepDiagBackward (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ int ft, rt = rf - 1;
+ if(rt < 0) return;
+ ft = ff + 1;
+ if (!(rt < 0 || ft >= BOARD_RGHT) && !SameColor(board[rf][ff], board[rt][ft]))
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+ ft = ff - 1;
+ if (!(rt < 0 || ft < BOARD_LEFT) && !SameColor(board[rf][ff], board[rt][ft]))
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+}
+
+void
+StepVertical (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ StepForward(board, flags, rf, ff, callback, closure);
+ StepBackward(board, flags, rf, ff, callback, closure);
+}
+
+void
+Ferz (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ StepDiagForward(board, flags, rf, ff, callback, closure);
+ StepDiagBackward(board, flags, rf, ff, callback, closure);
+}
+
+void
+Wazir (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ StepVertical(board, flags, rf, ff, callback, closure);
+ StepSideways(board, flags, rf, ff, callback, closure);
+}
+
+void
+Knight (Board board, int flags, int rf, int ff, MoveCallback callback, VOIDSTAR closure)
+{
+ int i, j, s, rt, ft;
+ for (i = -1; i <= 1; i += 2)
+ for (j = -1; j <= 1; j += 2)
+ for (s = 1; s <= 2; s++) {
+ rt = rf + i*s;
+ ft = ff + j*(3-s);
+ if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT)
+ && ( gameInfo.variant != VariantXiangqi || board[rf+i*(s-1)][ff+j*(2-s)] == EmptySquare)
+ && !SameColor(board[rf][ff], board[rt][ft]))
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+ }
+}
/* Call callback once for each pseudo-legal move in the given
position, except castling moves. A move is pseudo-legal if it is
int rf, ff;
int i, j, d, s, fs, rs, rt, ft, m;
int epfile = (signed char)board[EP_STATUS]; // [HGM] gamestate: extract ep status from board
- int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand ? 3 : 1;
+ int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess ? 3 : 1;
for (rf = 0; rf < BOARD_HEIGHT; rf++)
for (ff = BOARD_LEFT; ff < BOARD_RGHT; ff++) {
if(PieceToChar(piece) == '~')
piece = (ChessSquare) ( DEMOTED piece );
if(filter != EmptySquare && piece != filter) continue;
- if(gameInfo.variant == VariantShogi)
+ if(IS_SHOGI(gameInfo.variant))
piece = (ChessSquare) ( SHOGI piece );
switch ((int)piece) {
case BlackUnicorn:
case WhiteKnight:
case BlackKnight:
- mounted:
for (i = -1; i <= 1; i += 2)
for (j = -1; j <= 1; j += 2)
for (s = 1; s <= 2; s++) {
/* Gold General (and all its promoted versions) . First do the */
/* diagonal forward steps, then proceed as normal Wazir */
- case SHOGI WhiteWazir:
case SHOGI (PROMOTED WhitePawn):
+ if(gameInfo.variant == VariantShogi) goto WhiteGold;
+ case SHOGI (PROMOTED BlackPawn):
+ if(gameInfo.variant == VariantShogi) goto BlackGold;
+ SlideVertical(board, flags, rf, ff, callback, closure);
+ break;
+
case SHOGI (PROMOTED WhiteKnight):
- case SHOGI (PROMOTED WhiteQueen):
- case SHOGI (PROMOTED WhiteFerz):
- for (s = -1; s <= 1; s += 2) {
- if (rf < BOARD_HEIGHT-1 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&
- !SameColor(board[rf][ff], board[rf + 1][ff + s])) {
- callback(board, flags, NormalMove,
- rf, ff, rf + 1, ff + s, closure);
- }
- }
- goto finishGold;
+ if(gameInfo.variant == VariantShogi) goto WhiteGold;
+ case SHOGI BlackDrunk:
+ case SHOGI BlackAlfil:
+ Ferz(board, flags, rf, ff, callback, closure);
+ StepSideways(board, flags, rf, ff, callback, closure);
+ StepBackward(board, flags, rf, ff, callback, closure);
+ break;
- case SHOGI BlackWazir:
- case SHOGI (PROMOTED BlackPawn):
case SHOGI (PROMOTED BlackKnight):
+ if(gameInfo.variant == VariantShogi) goto BlackGold;
+ case SHOGI WhiteDrunk:
+ case SHOGI WhiteAlfil:
+ Ferz(board, flags, rf, ff, callback, closure);
+ StepSideways(board, flags, rf, ff, callback, closure);
+ StepForward(board, flags, rf, ff, callback, closure);
+ break;
+
+
+ case SHOGI WhiteStag:
+ case SHOGI BlackStag:
+ if(gameInfo.variant == VariantShogi) goto BlackGold;
+ SlideVertical(board, flags, rf, ff, callback, closure);
+ Ferz(board, flags, rf, ff, callback, closure);
+ StepSideways(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI (PROMOTED WhiteQueen):
+ case SHOGI WhiteTokin:
+ case SHOGI WhiteWazir:
+ WhiteGold:
+ StepDiagForward(board, flags, rf, ff, callback, closure);
+ Wazir(board, flags, rf, ff, callback, closure);
+ break;
+
case SHOGI (PROMOTED BlackQueen):
- case SHOGI (PROMOTED BlackFerz):
- for (s = -1; s <= 1; s += 2) {
- if (rf > 0 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&
- !SameColor(board[rf][ff], board[rf - 1][ff + s])) {
- callback(board, flags, NormalMove,
- rf, ff, rf - 1, ff + s, closure);
- }
- }
+ case SHOGI BlackTokin:
+ case SHOGI BlackWazir:
+ BlackGold:
+ StepDiagBackward(board, flags, rf, ff, callback, closure);
+ Wazir(board, flags, rf, ff, callback, closure);
+ break;
case WhiteWazir:
case BlackWazir:
- finishGold:
- for (d = 0; d <= 1; d++)
- for (s = -1; s <= 1; s += 2) {
- rt = rf + s * d;
- ft = ff + s * (1 - d);
- if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT)
- && !SameColor(board[rf][ff], board[rt][ft]) &&
- (gameInfo.variant != VariantXiangqi || InPalace(rt, ft) ) )
- callback(board, flags, NormalMove,
- rf, ff, rt, ft, closure);
- }
- break;
+ Wazir(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI WhiteMarshall:
+ case SHOGI BlackMarshall:
+ Ferz(board, flags, rf, ff, callback, closure);
+ for (d = 0; d <= 1; d++)
+ for (s = -2; s <= 2; s += 4) {
+ rt = rf + s * d;
+ ft = ff + s * (1 - d);
+ if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) continue;
+ if (!SameColor(board[rf][ff], board[rt][ft]) )
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+ }
+ break;
+
+ case SHOGI WhiteAngel:
+ case SHOGI BlackAngel:
+ Wazir(board, flags, rf, ff, callback, closure);
case WhiteAlfil:
case BlackAlfil:
&& !SameColor(board[rf][ff], board[rt][ft]))
callback(board, flags, NormalMove,
rf, ff, rt, ft, closure);
- if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier
- || gameInfo.variant == VariantXiangqi) continue; // classical Alfil
+ if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
+ gameInfo.variant == VariantChu || gameInfo.variant == VariantXiangqi) continue; // classical Alfil
rt = rf + rs; // in unknown variant we assume Modern Elephant, which can also do one step
ft = ff + fs;
if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT)
/* Make Dragon-Horse also do Dababba moves outside Shogi, for better disambiguation in variant Fairy */
case WhiteCardinal:
case BlackCardinal:
+ if(gameInfo.variant == VariantChuChess) goto DragonHorse;
for (d = 0; d <= 1; d++) // Dababba moves that Rook cannot do
for (s = -2; s <= 2; s += 4) {
rt = rf + s * d;
/* Shogi Dragon Horse has to continue with Wazir after Bishop */
case SHOGI WhiteCardinal:
case SHOGI BlackCardinal:
- m++;
+ case SHOGI WhitePCardinal:
+ case SHOGI BlackPCardinal:
+ DragonHorse:
+ Bishop(board, flags, rf, ff, callback, closure);
+ Wazir(board, flags, rf, ff, callback, closure);
+ break;
/* Capablanca Archbishop continues as Knight */
case WhiteAngel:
case BlackAngel:
- m++;
+ Knight(board, flags, rf, ff, callback, closure);
/* Shogi Bishops are ordinary Bishops */
case SHOGI WhiteBishop:
case SHOGI BlackBishop:
+ case SHOGI WhitePBishop:
+ case SHOGI BlackPBishop:
case WhiteBishop:
case BlackBishop:
- for (rs = -1; rs <= 1; rs += 2)
- for (fs = -1; fs <= 1; fs += 2)
- for (i = 1;; i++) {
- rt = rf + (i * rs);
- ft = ff + (i * fs);
- if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break;
- if (SameColor(board[rf][ff], board[rt][ft])) break;
- callback(board, flags, NormalMove,
- rf, ff, rt, ft, closure);
- if (board[rt][ft] != EmptySquare) break;
- }
- if(m==1) goto mounted;
- if(m==2) goto finishGold;
- /* Bishop falls through */
- break;
+ Bishop(board, flags, rf, ff, callback, closure);
+ break;
/* Shogi Lance is unlike anything, and asymmetric at that */
case SHOGI WhiteQueen:
+ if(gameInfo.variant == VariantChu) goto doQueen;
for(i = 1;; i++) {
rt = rf + i;
ft = ff;
break;
case SHOGI BlackQueen:
+ if(gameInfo.variant == VariantChu) goto doQueen;
for(i = 1;; i++) {
rt = rf - i;
ft = ff;
/* Make Dragon-King Dababba & Rook-like outside Shogi, for better disambiguation in variant Fairy */
case WhiteDragon:
case BlackDragon:
+ if(gameInfo.variant == VariantChuChess) goto DragonKing;
for (d = 0; d <= 1; d++) // Dababba moves that Rook cannot do
for (s = -2; s <= 2; s += 4) {
rt = rf + s * d;
/* Shogi Dragon King has to continue as Ferz after Rook moves */
case SHOGI WhiteDragon:
case SHOGI BlackDragon:
+ case SHOGI WhitePDragon:
+ case SHOGI BlackPDragon:
+ DragonKing:
+ Rook(board, flags, rf, ff, callback, closure);
+ Ferz(board, flags, rf, ff, callback, closure);
+ break;
m++;
/* Capablanca Chancellor sets flag to continue as Knight */
case WhiteMarshall:
case BlackMarshall:
- m++;
- m += (gameInfo.variant == VariantSpartan); // in Spartan Chess Chancellor is used for Dragon King.
+ Rook(board, flags, rf, ff, callback, closure);
+ if(gameInfo.variant == VariantSpartan) // in Spartan Chess Chancellor is used for Dragon King.
+ Ferz(board, flags, rf, ff, callback, closure);
+ else
+ Knight(board, flags, rf, ff, callback, closure);
+ break;
/* Shogi Rooks are ordinary Rooks */
case SHOGI WhiteRook:
case SHOGI BlackRook:
+ case SHOGI WhitePRook:
+ case SHOGI BlackPRook:
case WhiteRook:
case BlackRook:
doRook:
- for (d = 0; d <= 1; d++)
- for (s = -1; s <= 1; s += 2)
- for (i = 1;; i++) {
- rt = rf + (i * s) * d;
- ft = ff + (i * s) * (1 - d);
- if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break;
- if (SameColor(board[rf][ff], board[rt][ft])) break;
- callback(board, flags, NormalMove,
- rf, ff, rt, ft, closure);
- if (board[rt][ft] != EmptySquare || i == rookRange) break;
- }
- if(m==1) goto mounted;
- if(m==2) goto finishSilver;
- break;
+ Rook(board, flags, rf, ff, callback, closure);
+ break;
case WhiteQueen:
case BlackQueen:
- for (rs = -1; rs <= 1; rs++)
- for (fs = -1; fs <= 1; fs++) {
- if (rs == 0 && fs == 0) continue;
- for (i = 1;; i++) {
- rt = rf + (i * rs);
- ft = ff + (i * fs);
- if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break;
- if (SameColor(board[rf][ff], board[rt][ft])) break;
- callback(board, flags, NormalMove,
- rf, ff, rt, ft, closure);
- if (board[rt][ft] != EmptySquare) break;
- }
- }
- break;
+ case SHOGI WhiteMother:
+ case SHOGI BlackMother:
+ doQueen:
+ Rook(board, flags, rf, ff, callback, closure);
+ Bishop(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI WhitePawn:
+ StepForward(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI BlackPawn:
+ StepBackward(board, flags, rf, ff, callback, closure);
+ break;
- /* Shogi Pawn and Silver General: first the Pawn move, */
- /* then the General continues like a Ferz */
case WhiteMan:
- if(gameInfo.variant != VariantMakruk) goto commoner;
- case SHOGI WhitePawn:
+ if(gameInfo.variant != VariantMakruk && gameInfo.variant != VariantASEAN) goto commoner;
case SHOGI WhiteFerz:
- if (rf < BOARD_HEIGHT-1 &&
- !SameColor(board[rf][ff], board[rf + 1][ff]) )
- callback(board, flags, NormalMove,
- rf, ff, rf + 1, ff, closure);
- if(piece != SHOGI WhitePawn) goto finishSilver;
- break;
+ Ferz(board, flags, rf, ff, callback, closure);
+ StepForward(board, flags, rf, ff, callback, closure);
+ break;
case BlackMan:
- if(gameInfo.variant != VariantMakruk) goto commoner;
- case SHOGI BlackPawn:
+ if(gameInfo.variant != VariantMakruk && gameInfo.variant != VariantASEAN) goto commoner;
case SHOGI BlackFerz:
- if (rf > 0 &&
- !SameColor(board[rf][ff], board[rf - 1][ff]) )
- callback(board, flags, NormalMove,
- rf, ff, rf - 1, ff, closure);
- if(piece == SHOGI BlackPawn) break;
+ StepBackward(board, flags, rf, ff, callback, closure);
case WhiteFerz:
case BlackFerz:
- finishSilver:
/* [HGM] support Shatranj pieces */
- for (rs = -1; rs <= 1; rs += 2)
- for (fs = -1; fs <= 1; fs += 2) {
- rt = rf + rs;
- ft = ff + fs;
- if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) continue;
- if (!SameColor(board[rf][ff], board[rt][ft]) &&
- (gameInfo.variant != VariantXiangqi || InPalace(rt, ft) ) )
- callback(board, flags, NormalMove,
- rf, ff, rt, ft, closure);
- }
- break;
+ Ferz(board, flags, rf, ff, callback, closure);
+ break;
case WhiteSilver:
case BlackSilver:
- m++; // [HGM] superchess: use for Centaur
+ Knight(board, flags, rf, ff, callback, closure); // [HGM] superchess: use for Centaur
+
commoner:
+ case SHOGI WhiteMonarch:
+ case SHOGI BlackMonarch:
case SHOGI WhiteKing:
case SHOGI BlackKing:
case WhiteKing:
case BlackKing:
-// walking:
- for (i = -1; i <= 1; i++)
- for (j = -1; j <= 1; j++) {
- if (i == 0 && j == 0) continue;
- rt = rf + i;
- ft = ff + j;
- if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) continue;
- if (SameColor(board[rf][ff], board[rt][ft])) continue;
- callback(board, flags, NormalMove,
- rf, ff, rt, ft, closure);
- }
- if(m==1) goto mounted;
- break;
+ Ferz(board, flags, rf, ff, callback, closure);
+ Wazir(board, flags, rf, ff, callback, closure);
+ break;
case WhiteNightrider:
case BlackNightrider:
break;
Amazon:
- /* First do Bishop,then continue like Chancellor */
- for (rs = -1; rs <= 1; rs += 2)
- for (fs = -1; fs <= 1; fs += 2)
- for (i = 1;; i++) {
- rt = rf + (i * rs);
- ft = ff + (i * fs);
- if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break;
- if (SameColor(board[rf][ff], board[rt][ft])) break;
- callback(board, flags, NormalMove,
- rf, ff, rt, ft, closure);
- if (board[rt][ft] != EmptySquare) break;
- }
- m++;
- goto doRook;
+ Bishop(board, flags, rf, ff, callback, closure);
+ Rook(board, flags, rf, ff, callback, closure);
+ Knight(board, flags, rf, ff, callback, closure);
+ break;
// Use Lance as Berolina / Spartan Pawn.
case WhiteLance:
}
break;
+ case SHOGI WhiteNothing:
+ case SHOGI BlackNothing:
+ case SHOGI WhiteLion:
+ case SHOGI BlackLion:
+ case WhiteLion:
+ case BlackLion:
+ for(rt = rf - 2; rt <= rf + 2; rt++) for(ft = ff - 2; ft <= ff + 2; ft++) {
+ if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) continue;
+ if (!(ff == ft && rf == rt) && SameColor(board[rf][ff], board[rt][ft])) continue;
+ callback(board, flags, (rt-rf)*(rt-rf) + (ff-ft)*(ff-ft) < 3 && board[rt][ft] != EmptySquare ? FirstLeg : NormalMove,
+ rf, ff, rt, ft, closure);
+ }
+ break;
+
+ case SHOGI WhiteFalcon:
+ case SHOGI BlackFalcon:
+ case SHOGI WhitePDagger:
+ case SHOGI BlackPDagger:
+ SlideSideways(board, flags, rf, ff, callback, closure);
+ StepVertical(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI WhiteCobra:
+ case SHOGI BlackCobra:
+ StepVertical(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI (PROMOTED WhiteFerz):
+ if(gameInfo.variant == VariantShogi) goto WhiteGold;
+ case SHOGI (PROMOTED BlackFerz):
+ if(gameInfo.variant == VariantShogi) goto BlackGold;
+ case SHOGI WhitePSword:
+ case SHOGI BlackPSword:
+ SlideVertical(board, flags, rf, ff, callback, closure);
+ StepSideways(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI WhiteUnicorn:
+ case SHOGI BlackUnicorn:
+ Ferz(board, flags, rf, ff, callback, closure);
+ StepVertical(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI WhiteMan:
+ StepDiagForward(board, flags, rf, ff, callback, closure);
+ StepVertical(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI BlackMan:
+ StepDiagBackward(board, flags, rf, ff, callback, closure);
+ StepVertical(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI WhiteHCrown:
+ case SHOGI BlackHCrown:
+ Bishop(board, flags, rf, ff, callback, closure);
+ SlideSideways(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI WhiteCrown:
+ case SHOGI BlackCrown:
+ Bishop(board, flags, rf, ff, callback, closure);
+ SlideVertical(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI WhiteHorned:
+ Sting(board, flags, rf, ff, 1, 0, callback, closure);
+ callback(board, flags, NormalMove, rf, ff, rf, ff, closure);
+ if(killX >= 0) break;
+ Bishop(board, flags, rf, ff, callback, closure);
+ SlideSideways(board, flags, rf, ff, callback, closure);
+ SlideBackward(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI BlackHorned:
+ Sting(board, flags, rf, ff, -1, 0, callback, closure);
+ callback(board, flags, NormalMove, rf, ff, rf, ff, closure);
+ if(killX >= 0) break;
+ Bishop(board, flags, rf, ff, callback, closure);
+ SlideSideways(board, flags, rf, ff, callback, closure);
+ SlideForward(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI WhiteEagle:
+ Sting(board, flags, rf, ff, 1, 1, callback, closure);
+ Sting(board, flags, rf, ff, 1, -1, callback, closure);
+ callback(board, flags, NormalMove, rf, ff, rf, ff, closure);
+ if(killX >= 0) break;
+ Rook(board, flags, rf, ff, callback, closure);
+ SlideDiagBackward(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI BlackEagle:
+ Sting(board, flags, rf, ff, -1, 1, callback, closure);
+ Sting(board, flags, rf, ff, -1, -1, callback, closure);
+ callback(board, flags, NormalMove, rf, ff, rf, ff, closure);
+ if(killX >= 0) break;
+ Rook(board, flags, rf, ff, callback, closure);
+ SlideDiagForward(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI WhiteDolphin:
+ case SHOGI BlackHorse:
+ SlideDiagBackward(board, flags, rf, ff, callback, closure);
+ SlideVertical(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI BlackDolphin:
+ case SHOGI WhiteHorse:
+ SlideDiagForward(board, flags, rf, ff, callback, closure);
+ SlideVertical(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI WhiteLance:
+ SlideForward(board, flags, rf, ff, callback, closure);
+ break;
+
+ case SHOGI BlackLance:
+ SlideBackward(board, flags, rf, ff, callback, closure);
+ break;
+
case WhiteFalcon: // [HGM] wild: for wildcards, self-capture symbolizes move to anywhere
case BlackFalcon:
case WhiteCobra:
if(rFilter >= 0 && rFilter != rt || fFilter >= 0 && fFilter != ft) return; // [HGM] speed: ignore moves with wrong to-square
+ if (board[EP_STATUS] == EP_IRON_LION && (board[rt][ft] == WhiteLion || board[rt][ft] == BlackLion)) return; //[HGM] lion
+
if (!(flags & F_IGNORE_CHECK) ) {
int check, promo = (gameInfo.variant == VariantSpartan && kind == BlackPromotion);
if(promo) {
if(ff <= BOARD_LEFT+2) { left = ff+1; right = BOARD_LEFT+3; }
for(k=left; k<=right && ft != NoRights; k++) /* first test if blocked */
if(k != ft && board[0][k] != EmptySquare) ft = NoRights;
+ if(ft == 0 && ff != 1 && board[0][1] != EmptySquare) ft = NoRights; /* Rook can be blocked on b1 */
if(ff > BOARD_LEFT+2)
for(k=left+1; k<=right && ft != NoRights; k++) /* then if not checked */
if(!ignoreCheck && CheckTest(board, flags, 0, ff, 0, k, FALSE)) ft = NoRights;
if(ff <= BOARD_LEFT+2) { left = ff+1; right = BOARD_LEFT+3; }
for(k=left; k<=right && ft != NoRights; k++) /* first test if blocked */
if(k != ft && board[BOARD_HEIGHT-1][k] != EmptySquare) ft = NoRights;
+ if(ft == 0 && ff != 1 && board[BOARD_HEIGHT-1][1] != EmptySquare) ft = NoRights; /* Rook can be blocked on b8 */
if(ff > BOARD_LEFT+2)
for(k=left+1; k<=right && ft != NoRights; k++) /* then if not checked */
if(!ignoreCheck && CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, k, FALSE)) ft = NoRights;
cl->check++;
xqCheckers[rf][ff] = xqCheckers[EP_STATUS] & 1; // remember who is checking (if status == 1)
}
+ if( board[EP_STATUS] == EP_ROYAL_LION && (board[rt][ft] == WhiteLion || board[rt][ft] == BlackLion)
+ && (gameInfo.variant != VariantLion || board[rf][ff] != WhiteKing && board[rf][ff] != BlackKing) )
+ cl->check++; // [HGM] lion: forbidden counterstrike against Lion equated to putting yourself in check
}
{
CheckTestClosure cl;
ChessSquare king = flags & F_WHITE_ON_MOVE ? WhiteKing : BlackKing;
- ChessSquare captured = EmptySquare;
+ ChessSquare captured = EmptySquare, ep, trampled;
/* Suppress warnings on uninitialized variables */
if(gameInfo.variant == VariantXiangqi)
king = flags & F_WHITE_ON_MOVE ? WhiteWazir : BlackWazir;
if(gameInfo.variant == VariantKnightmate)
king = flags & F_WHITE_ON_MOVE ? WhiteUnicorn : BlackUnicorn;
+ if(gameInfo.variant == VariantChu) { // strictly speaking this is not needed, as Chu officially has no check
+ int r, f, k = king, royals=0, prince = flags & F_WHITE_ON_MOVE ? WhiteMonarch : BlackMonarch;
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
+ if(board[r][f] == k || board[r][f] == prince) {
+ if(++royals > 1) return FALSE; // no check if we have two royals (ignores double captureby Lion!)
+ king = board[r][f]; // remember hich one we had
+ }
+ }
+ }
if (rt >= 0) {
if (enPassant) {
captured = board[rf][ft];
board[rf][ft] = EmptySquare;
} else {
- captured = board[rt][ft];
+ captured = board[rt][ft];
+ if(killX >= 0) { trampled = board[killY][killX]; board[killY][killX] = EmptySquare; }
}
if(rf == DROP_RANK) board[rt][ft] = ff; else { // [HGM] drop
board[rt][ft] = board[rf][ff];
board[rf][ff] = EmptySquare;
}
+ ep = board[EP_STATUS];
+ if( captured == WhiteLion || captured == BlackLion ) { // [HGM] lion: Chu Lion-capture rules
+ ChessSquare victim = killX < 0 ? EmptySquare : trampled;
+ if( (board[rt][ft] == WhiteLion || board[rt][ft] == BlackLion) && // capturer is Lion
+ (ff - ft > 1 || ft - ff > 1 || rf - rt > 1 || rt - rf > 1) && // captures from a distance
+ (victim == EmptySquare || victim == WhitePawn || victim == BlackPawn) ) // no or worthless 'bridge'
+ board[EP_STATUS] = EP_ROYAL_LION; // on distant Lion x Lion victim must not be pseudo-legally protected
+ }
}
/* For compatibility with ICS wild 9, we scan the board in the
board[rf][ft] = captured;
board[rt][ft] = EmptySquare;
} else {
+ if(killX >= 0) board[killY][killX] = trampled;
board[rt][ft] = captured;
}
+ board[EP_STATUS] = ep;
}
return cl.fking < BOARD_RGHT ? cl.check : 1000; // [HGM] atomic: return 1000 if we have no king
}
+int
+HasLion (Board board, int flags)
+{
+ int lion = F_WHITE_ON_MOVE & flags ? WhiteLion : BlackLion;
+ int r, f;
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++)
+ if(board[r][f] == lion) return 1;
+ return 0;
+}
+
ChessMove
LegalDrop (Board board, int flags, ChessSquare piece, int rt, int ft)
{ // [HGM] put drop legality testing in separate routine for clarity
if(board[BOARD_HEIGHT-1-PieceToNumber(CharToPiece(ToLower(promoChar)))][1] == 0) return ImpossibleMove;
}
} else
+ if(gameInfo.variant == VariantChu) {
+ if(cl.kind != NormalMove || promoChar == NULLCHAR || promoChar == '=') return cl.kind;
+ if(promoChar != '+')
+ return CharToPiece(promoChar) == EmptySquare ? ImpossibleMove : IllegalMove;
+ if(PieceToChar(CHUPROMOTED board[rf][ff]) != '+') return ImpossibleMove;
+ return flags & F_WHITE_ON_MOVE ? WhitePromotion : BlackPromotion;
+ } else
if(gameInfo.variant == VariantShogi) {
/* [HGM] Shogi promotions. '=' means defer */
if(rf != DROP_RANK && cl.kind == NormalMove) {
}
} else
if (promoChar != NULLCHAR) {
+ if(cl.kind == NormalMove && promoChar == '+') { // allow shogi-style promotion is pieceToChar specifies them
+ ChessSquare piece = board[rf][ff];
+ if(piece < BlackPawn ? piece > WhiteMan : piece > BlackMan) return ImpossibleMove; // already promoted
+ // should test if in zone, really
+ if(gameInfo.variant == VariantChuChess && (piece == WhiteKnight || piece == BlackKnight) && HasLion(board, flags))
+ return IllegalMove;
+ if(PieceToChar(PROMOTED piece) == '+') return flags & F_WHITE_ON_MOVE ? WhitePromotion : BlackPromotion;
+ } else
if(promoChar == '=') cl.kind = IllegalMove; else // [HGM] shogi: no deferred promotion outside Shogi
if (cl.kind == WhitePromotion || cl.kind == BlackPromotion) {
ChessSquare piece = CharToPiece(flags & F_WHITE_ON_MOVE ? ToUpper(promoChar) : ToLower(promoChar));
if(piece == EmptySquare)
cl.kind = ImpossibleMove; // non-existing piece
- if(gameInfo.variant == VariantSpartan && cl.kind == BlackPromotion ) {
+ if(gameInfo.variant == VariantChuChess && promoChar == 'l' && HasLion(board, flags)) {
+ cl.kind = IllegalMove; // no two Lions
+ } else if(gameInfo.variant == VariantSpartan && cl.kind == BlackPromotion ) {
if(promoChar != PieceToChar(BlackKing)) {
if(CheckTest(board, flags, rf, ff, rt, ft, FALSE)) cl.kind = IllegalMove; // [HGM] spartan: only promotion to King was possible
if(piece == BlackLance) cl.kind = ImpossibleMove;
- } else { // promotion to King allowed only if we do not haave two yet
+ } else { // promotion to King allowed only if we do not have two yet
int r, f, kings = 0;
for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) kings += (board[r][f] == BlackKing);
if(kings == 2) cl.kind = IllegalMove;
else if(gameInfo.variant == VariantGiveaway) return MT_STEALMATE; // no check exists, stalemated = win
return inCheck ? MT_CHECKMATE
- : (gameInfo.variant == VariantXiangqi || gameInfo.variant == VariantShatranj || gameInfo.variant == VariantShogi) ?
+ : (gameInfo.variant == VariantXiangqi || gameInfo.variant == VariantShatranj || IS_SHOGI(gameInfo.variant)) ?
MT_STAINMATE : MT_STALEMATE;
}
}
if(board[BOARD_HEIGHT-1-PieceToNumber(CharToPiece(ToLower(c)))][1] == 0) closure->kind = ImpossibleMove;
}
} else
+ if(gameInfo.variant == VariantChu) {
+ if(c == '+') closure->kind = (flags & F_WHITE_ON_MOVE ? WhitePromotion : BlackPromotion); // for now, accept any
+ } else
if(gameInfo.variant == VariantShogi) {
/* [HGM] Shogi promotions. On input, '=' means defer, '+' promote. Afterwards, c is set to '+' for promotions, NULL other */
if(closure->rfIn != DROP_RANK && closure->kind == NormalMove) {
} else
if (closure->kind == WhitePromotion || closure->kind == BlackPromotion) {
if(c == NULLCHAR) { // missing promoChar on mandatory promotion; use default for variant
- if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk)
+ if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
+ gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN)
c = PieceToChar(BlackFerz);
else if(gameInfo.variant == VariantGreat)
c = PieceToChar(BlackMan);
else
c = PieceToChar(BlackQueen);
} else if(c == '=') closure->kind = IllegalMove; // no deferral outside Shogi
+ else if(c == 'l' && gameInfo.variant == VariantChuChess && HasLion(board, flags)) closure->kind = IllegalMove;
+ } else if (c == '+') { // '+' outside shogi, check if pieceToCharTable enabled it
+ ChessSquare p = closure->piece;
+ if(p > WhiteMan && p < BlackPawn || p > BlackMan || PieceToChar(PROMOTED p) != '+')
+ closure->kind = ImpossibleMove; // used on non-promotable piece
+ else if(gameInfo.variant == VariantChuChess && HasLion(board, flags)) closure->kind = IllegalMove;
} else if (c != NULLCHAR) closure->kind = IllegalMove;
closure->promoChar = ToLower(c); // this can be NULLCHAR! Note we keep original promoChar even if illegal.
/* Use promotion suffix style "=Q" */
*outp = NULLCHAR;
if (promoChar != NULLCHAR) {
- if(gameInfo.variant == VariantShogi) {
+ if(IS_SHOGI(gameInfo.variant)) {
/* [HGM] ... but not in Shogi! */
*outp++ = promoChar == '=' ? '=' : '+';
} else {
*/
if( c == '~' || c == '+') {
/* [HGM] print nonexistent piece as its demoted version */
- piece = (ChessSquare) (DEMOTED piece);
+ piece = (ChessSquare) (DEMOTED piece - 11*(gameInfo.variant == VariantChu));
}
if(c=='+') *outp++ = c;
*outp++ = ToUpper(PieceToChar(piece));
if(rt+ONE <= '9')
*outp++ = rt + ONE;
else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; }
- if (gameInfo.variant == VariantShogi) {
+ if (IS_SHOGI(gameInfo.variant)) {
/* [HGM] in Shogi non-pawns can promote */
*outp++ = promoChar; // Don't bother to correct move type, return value is never used!
}
- else if (gameInfo.variant != VariantSuper && promoChar &&
+ else if (gameInfo.variant == VariantChuChess && promoChar ||
+ gameInfo.variant != VariantSuper && promoChar &&
(piece == WhiteLance || piece == BlackLance) ) { // Lance sometimes represents Pawn
*outp++ = '=';
*outp++ = ToUpper(promoChar);
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
#define F_MANDATORY_CAPTURE 0x200
/* Special epfile values. [HGM] positive values are non-reversible moves! */
-#define EP_NONE (-4) /* [HGM] Tricky! order matters: */
-#define EP_UNKNOWN (-1) /* >= EP_UNKNOWN spils rep-draw */
+#define EP_NONE (-6) /* [HGM] Tricky! order matters: */
+#define EP_UNKNOWN (-1) /* >= EP_UNKNOWN spoils rep-draw */
#define EP_CAPTURE (-2) /* <= EP_NONE is reversible move */
#define EP_PAWN_MOVE (-3)
+#define EP_IRON_LION (-4)
+#define EP_ROYAL_LION (-5)
#define EP_REP_DRAW (-15)
#define EP_RULE_DRAW (-14)
#define EP_INSUF_DRAW (-13)
int rf, int ff, int rt, int ft,
int promoChar, char out[MOVE_LEN]));
-extern int quickFlag;
+extern int quickFlag, killX, killY;
*
* Copyright 2005 Alessandro Scotti
*
- * Enhancements Copyright 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * Enhancements Copyright 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* ------------------------------------------------------------------------
*
int MemoProc P((Option *opt, int n, int x, int y, char *text, int index));
Option engoutOptions[] = {
-{ 0, LL|T2T, 17, NULL, NULL, NULL, NULL, Icon, " " },
-{ 0, L2L|T2T|SAME_ROW, 163, NULL, NULL, NULL, NULL, Label, N_("engine name") },
+{ 0, LL|T2T, 18, NULL, NULL, NULL, NULL, Icon, " " },
+{ 0, L2L|T2T|SAME_ROW, 162, NULL, NULL, NULL, NULL, Label, N_("engine name") },
{ 0, T2T|SAME_ROW, 30, NULL, NULL, NULL, NULL, Icon, " " },
+/* TRANSLATORS: noun, as in "the move Nf3"*/
{ 0, R2R|T2T|SAME_ROW, 188, NULL, NULL, NULL, NULL, Label, N_("move") },
{ 0, RR|T2T|SAME_ROW, 80, NULL, NULL, NULL, NULL, Label, N_("NPS") },
{200, T_VSCRL | T_TOP, 500, NULL, (void*) &mem1, "", (char**) MemoProc, TextBox, "" },
{ 0, 0, 0, NULL, NULL, "", NULL, Break , "" },
-{ 0, LL|T2T, 17, NULL, NULL, NULL, NULL, Icon, " " },
-{ 0, L2L|T2T|SAME_ROW, 163, NULL, NULL, NULL, NULL, Label, N_("engine name") },
+{ 0, LL|T2T, 18, NULL, NULL, NULL, NULL, Icon, " " },
+{ 0, L2L|T2T|SAME_ROW, 162, NULL, NULL, NULL, NULL, Label, N_("engine name") },
{ 0, T2T|SAME_ROW, 30, NULL, NULL, NULL, NULL, Icon, " " },
+/* TRANSLATORS: noun, as in "the move Nf3"*/
{ 0, R2R|T2T|SAME_ROW, 188, NULL, NULL, NULL, NULL, Label, N_("move") },
{ 0, RR|T2T|SAME_ROW, 80, NULL, NULL, NULL, NULL, Label, N_("NPS") },
{200, T_VSCRL | T_TOP, 500, NULL, (void*) &mem2, "", (char**) MemoProc, TextBox, "" },
/*
* parser.c --
*
- * Copyright 2011, 2012, 2013 Free Software Foundation, Inc.
+ * Copyright 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
* ------------------------------------------------------------------------
*
* GNU XBoard is free software: you can redistribute it and/or modify
{
char *start = *p;
if(**p == 'e' && (Match("ep", p) || Match("e.p.", p))) { *p = start; return NULLCHAR; } // non-compliant e.p. suffix is no promoChar!
- if(**p == '+' && gameInfo.variant == VariantShogi) { (*p)++; return '+'; }
+ if(**p == '+' && IS_SHOGI(gameInfo.variant)) { (*p)++; return '+'; }
if(**p == '=' || (gameInfo.variant == VariantSChess) && **p == '/') (*p)++; // optional = (or / for Seirawan gating)
if(**p == '(' && (*p)[2] == ')' && isalpha( (*p)[1] )) { (*p) += 3; return ToLower((*p)[-2]); }
- if(isalpha(**p)) return ToLower(*(*p)++);
- if(*p != start) return '='; // must be the optional =
+ if(isalpha(**p) && **p != 'x') return ToLower(*(*p)++); // reserve 'x' for multi-leg captures?
+ if(*p != start) return **p == '+' ? *(*p)++ : '='; // must be the optional = (or =+)
return NULLCHAR; // no suffix detected
}
if(fromString) return 0; // we are parsing string, so the end is really the end
*p = inPtr = inputBuf;
if(!ReadLine()) return 0; // EOF
+ } else if(inPtr > inputBuf + PARSEBUFSIZE/2) { // buffer fills up with already parsed stuff
+ char *q = *p, *r = inputBuf;
+ while(*r++ = *q++);
+ *p = inputBuf; inPtr = r - 1;
}
parseStart = oldp = *p; // remember where we begin
} else if(n == 1 && type[0] == NUMERIC && coord[0] > 1) { while(**p == '.') (*p)++; return Nothing; } // fast exit for move numbers
if(n == 4 && type[2] != type[3] && // we have a valid to-square (kludge: type[3] can be NOTHING on fxg type move)
(piece || !promoted) && // promoted indicator only valid on named piece type
- (type[2] == ALPHABETIC || gameInfo.variant == VariantShogi)) { // in Shogi also allow alphabetic rank
+ (type[2] == ALPHABETIC || IS_SHOGI(gameInfo.variant))) { // in Shogi also allow alphabetic rank
DisambiguateClosure cl;
int fromX, fromY, toX, toY;
if(piece) {
cl.pieceIn = CharToPiece(wom ? piece : ToLower(piece));
if(cl.pieceIn == EmptySquare) return ImpossibleMove; // non-existent piece
- if(promoted) cl.pieceIn = (ChessSquare) (PROMOTED cl.pieceIn);
+ if(promoted) cl.pieceIn = (ChessSquare) (CHUPROMOTED cl.pieceIn);
} else cl.pieceIn = EmptySquare;
if(separator == '@' || separator == '*') { // drop move. We only get here without from-square or promoted piece
fromY = DROP_RANK; fromX = cl.pieceIn;
fromY = (currentMoveString[1] = coord[1] + '0') - ONE;
currentMoveString[4] = cl.promoCharIn = PromoSuffix(p);
currentMoveString[5] = NULLCHAR;
+ if(!cl.promoCharIn && (**p == '-' || **p == 'x')) { // Lion-type multi-leg move
+ currentMoveString[5] = (killX = toX) + AAA; // what we thought was to-square is in fact kill-square
+ currentMoveString[6] = (killY = toY) + ONE; // append it as suffix behind long algebraic move
+ currentMoveString[4] = ';';
+ currentMoveString[7] = NULLCHAR;
+ // read new to-square (VERY non-robust! Assumes correct (non-alpha-rank) syntax, and messes up on errors)
+ toX = cl.ftIn = (currentMoveString[2] = *++*p) - AAA; ++*p;
+ toY = cl.rtIn = (currentMoveString[3] = Number(p) + '0') - ONE;
+ }
if(type[0] != NOTHING && type[1] != NOTHING && type[3] != NOTHING) { // fully specified.
+ ChessSquare realPiece = boards[yyboardindex][fromY][fromX];
// Note that Disambiguate does not work for illegal moves, but flags them as impossible
if(piece) { // check if correct piece indicated
if(PieceToChar(realPiece) == '~') realPiece = (ChessSquare) (DEMOTED realPiece);
if(!(appData.icsActive && PieceToChar(realPiece) == '+') && // trust ICS if it moves promoted pieces
piece && realPiece != cl.pieceIn) return ImpossibleMove;
+ } else if(!separator && **p == '+') { // could be a protocol move, where bare '+' suffix means shogi-style promotion
+ if(realPiece < (wom ? WhiteCannon : BlackCannon) && PieceToChar(PROMOTED realPiece) == '+') // seems to be that
+ currentMoveString[4] = cl.promoCharIn = *(*p)++; // append promochar after all
}
result = LegalityTest(boards[yyboardindex], PosFlags(yyboardindex), fromY, fromX, toY, toX, cl.promoCharIn);
if (currentMoveString[4] == NULLCHAR) { // suppy missing mandatory promotion character
currentMoveString[0] = cl.ff + AAA;
currentMoveString[1] = cl.rf + ONE;
currentMoveString[3] = cl.rt + ONE;
+ if(killX < 0) // [HGM] lion: do not overwrite kill-square suffix
currentMoveString[4] = cl.promoChar;
if((cl.kind == WhiteCapturesEnPassant || cl.kind == BlackCapturesEnPassant) && (Match("ep", p) || Match("e.p.", p)));
msgstr ""
"Project-Id-Version: GNU xboard master-20110507\n"
"Report-Msgid-Bugs-To: bug-xboard@gnu.org\n"
-"POT-Creation-Date: 2013-08-28 21:49-0700\n"
+"POT-Creation-Date: 2013-08-28 22:03-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+ "Language: ru\n"
-#: args.h:820
+#: args.h:821
#, c-format
msgid "%s in settings file\n"
msgstr ""
-#: args.h:830
+#: args.h:831
#, c-format
msgid "Bad integer value %s"
msgstr ""
-#: args.h:923 args.h:1164
+#: args.h:924 args.h:1165
#, c-format
msgid "Unrecognized argument %s"
msgstr ""
-#: args.h:954
+#: args.h:955
#, c-format
msgid "No value provided for argument %s"
msgstr ""
-#: args.h:1014
+#: args.h:1015
#, c-format
msgid "Incomplete \\ escape in value for %s"
msgstr ""
-#: args.h:1119
+#: args.h:1120
#, c-format
msgid "Failed to open indirection file %s"
msgstr ""
-#: args.h:1136
+#: args.h:1137
#, c-format
msgid "Unrecognized boolean argument value %s"
msgstr ""
#. TRANSLATORS: "first" is the first of possible two chess engines. It is inserted into strings
#. such as "%s engine" / "%s chess program" / "%s machine" - all meaning the same thing
-#: backend.c:744
+#: backend.c:753
msgid "first"
msgstr ""
#. TRANSLATORS: "second" is the second of possible two chess engines. It is inserted into strings
#. such as "%s engine" / "%s chess program" / "%s machine" - all meaning the same thing
-#: backend.c:747
+#: backend.c:756
msgid "second"
msgstr ""
-#: backend.c:827
+#: backend.c:837
#, c-format
msgid "protocol version %d not supported"
msgstr "версия протокола %d не поддерживается"
-#: backend.c:933
+#: backend.c:943
msgid "You did not specify the engine executable"
msgstr ""
-#: backend.c:989
+#: backend.c:999
#, c-format
msgid "bad timeControl option %s"
msgstr "timeControl: неверный параметр %s"
-#: backend.c:1004
+#: backend.c:1014
#, c-format
msgid "bad searchTime option %s"
msgstr "searchTime: неверный параметр %s"
-#: backend.c:1110
+#: backend.c:1120
#, c-format
msgid "Variant %s supported only in ICS mode"
msgstr "Вариант %s поддерживается только в режиме ICS"
-#: backend.c:1128
+#: backend.c:1138
#, c-format
msgid "Unknown variant name %s"
msgstr "Неизвестный вариант %s"
-#: backend.c:1375
+#: backend.c:1386
msgid "Starting chess program"
msgstr "Запускается шахматная программа"
-#: backend.c:1398
+#: backend.c:1409
msgid "Bad game file"
msgstr "Неправильный формат файла"
-#: backend.c:1405
+#: backend.c:1416
msgid "Bad position file"
msgstr "Неправильный формат файла позиции"
-#: backend.c:1419
+#: backend.c:1430
msgid "Pick new game"
msgstr ""
-#: backend.c:1488
+#: backend.c:1499
msgid ""
"You restarted an already completed tourney\n"
"One more cycle will now be added to it\n"
"Games commence in 10 sec"
msgstr ""
-#: backend.c:1495
+#: backend.c:1506
#, c-format
msgid "All games in tourney '%s' are already played or playing"
msgstr ""
-#: backend.c:1502
+#: backend.c:1513
msgid "Can't have a match with no chess programs"
msgstr "Не подключено ни одной шахматной программы"
-#: backend.c:1539
+#: backend.c:1550
#, c-format
msgid "Could not open comm port %s"
msgstr "Не могу открыть COM-порт %s"
-#: backend.c:1542
+#: backend.c:1553
#, c-format
msgid "Could not connect to host %s, port %s"
msgstr "Не могу установить связь с %s, порт %s"
-#: backend.c:1598
+#: backend.c:1609
#, c-format
msgid "Unknown initialMode %s"
msgstr "initialMode: неизвестный режим %s"
-#: backend.c:1624
+#: backend.c:1635
msgid "AnalyzeFile mode requires a game file"
msgstr "Режим анализа: не указан файл для анализа"
-#: backend.c:1651
+#: backend.c:1662
msgid "Analysis mode requires a chess engine"
msgstr "Для анализа необходима шахматная программа"
-#: backend.c:1655
+#: backend.c:1666
msgid "Analysis mode does not work with ICS mode"
msgstr "Режим анализа не совместим с режимом ICS"
-#: backend.c:1666
+#: backend.c:1677
msgid "MachineWhite mode requires a chess engine"
msgstr "В режиме \"Компьютер белыми\" нужна шахматная программа"
-#: backend.c:1671
+#: backend.c:1682
msgid "MachineWhite mode does not work with ICS mode"
msgstr "Режим \"Компьютер белыми\" не совместим с режимом ICS"
-#: backend.c:1678
+#: backend.c:1689
msgid "MachineBlack mode requires a chess engine"
msgstr "В режиме \"Компьютер черными\" нужна шахматная программа (движок)"
-#: backend.c:1683
+#: backend.c:1694
msgid "MachineBlack mode does not work with ICS mode"
msgstr "Режим \"Компьютер черными\" не совместим с режимом ICS"
-#: backend.c:1690
+#: backend.c:1701
msgid "TwoMachines mode requires a chess engine"
msgstr "В режиме \"Два движка\" нужна шахматная программа"
-#: backend.c:1695
+#: backend.c:1706
msgid "TwoMachines mode does not work with ICS mode"
msgstr "Режим \"Два движка\" не совместим с режимом ICS"
-#: backend.c:1706
+#: backend.c:1717
msgid "Training mode requires a game file"
msgstr "Для тренировки необходимо загрузить шахматную партию из файла"
-#: backend.c:1869 backend.c:1924 backend.c:1947 backend.c:2346
+#: backend.c:1880 backend.c:1935 backend.c:1958 backend.c:2357
msgid "Error writing to ICS"
msgstr "Ошибка записи на вход сервера ICS"
-#: backend.c:1884
+#: backend.c:1895
msgid "Error reading from keyboard"
msgstr "Ошибка клавиатуры"
-#: backend.c:1887
+#: backend.c:1898
msgid "Got end of file from keyboard"
msgstr "Получен символ конца файла с клавиатуры"
-#: backend.c:2192
+#: backend.c:2203
#, c-format
msgid "Unknown wild type %d"
msgstr ""
-#: backend.c:2263 usystem.c:329
+#: backend.c:2274 usystem.c:329
msgid "Error writing to display"
msgstr "Ошибка записи на дисплей"
-#: backend.c:3019
+#: backend.c:3030
#, c-format
msgid "your opponent kibitzes: %s"
msgstr ""
-#: backend.c:3548
+#: backend.c:3559
msgid "Error gathering move list: two headers"
msgstr "Ошибка чтения списка ходов: два заголовка"
-#: backend.c:3595
+#: backend.c:3606
msgid "Error gathering move list: nested"
msgstr "Ошибка чтения списка ходов: вложенные списки"
-#: backend.c:3699 backend.c:4117 backend.c:4321 backend.c:4880 backend.c:4884
-#: backend.c:6900 backend.c:12082 backend.c:13797 backend.c:13874
-#: backend.c:13920 backend.c:13926 backend.c:13931 backend.c:13936
+#: backend.c:3710 backend.c:4128 backend.c:4332 backend.c:4891 backend.c:4895
+#: backend.c:6919 backend.c:12213 backend.c:13928 backend.c:14005
+#: backend.c:14051 backend.c:14057 backend.c:14062 backend.c:14067
msgid "vs."
msgstr ""
-#: backend.c:3827
+#: backend.c:3838
msgid "Illegal move (rejected by ICS)"
msgstr ""
-#: backend.c:4165
+#: backend.c:4176
msgid "Connection closed by ICS"
msgstr "Сервер ICS разорвал соединение"
-#: backend.c:4167
+#: backend.c:4178
msgid "Error reading from ICS"
msgstr "Ошибка чтения с сервера ICS"
-#: backend.c:4244
+#: backend.c:4255
#, c-format
msgid ""
"Failed to parse board string:\n"
"\"%s\""
msgstr ""
-#: backend.c:4253 backend.c:9755
+#: backend.c:4264 backend.c:9885
msgid "Game too long; increase MAX_MOVES and recompile"
msgstr ""
"Слишком длинная партия: увеличьте значение MAX_MOVES и перекомпилируйте "
"программу"
-#: backend.c:4372
+#: backend.c:4383
msgid "Error gathering move list: extra board"
msgstr "Ошибка чтения списка ходов: лишняя доска"
-#: backend.c:4804 backend.c:4826
+#: backend.c:4815 backend.c:4837
#, c-format
msgid "Couldn't parse move \"%s\" from ICS"
msgstr "Странный ход \"%s\" получен с сервера ICS"
-#: backend.c:5063
+#: backend.c:5074
#, c-format
msgid "say Internal error; bad moveType %d (%d,%d-%d,%d)"
msgstr ""
-#: backend.c:5133
+#: backend.c:5145
msgid "You cannot do this while you are playing or observing"
msgstr ""
-#: backend.c:6029
+#: backend.c:6046
msgid "Recompile to support this BOARD_RANKS or BOARD_FILES!"
msgstr ""
-#: backend.c:6491
+#: backend.c:6510
msgid "You are playing Black"
msgstr "Вы играете черными"
-#: backend.c:6500 backend.c:6527
+#: backend.c:6519 backend.c:6546
msgid "You are playing White"
msgstr "Вы играете белыми"
-#: backend.c:6509 backend.c:6535 backend.c:6655 backend.c:6680 backend.c:6696
-#: backend.c:14573
+#: backend.c:6528 backend.c:6554 backend.c:6674 backend.c:6699 backend.c:6715
+#: backend.c:14705
msgid "It is White's turn"
msgstr "Ход белых"
-#: backend.c:6513 backend.c:6539 backend.c:6663 backend.c:6686 backend.c:6717
-#: backend.c:14565
+#: backend.c:6532 backend.c:6558 backend.c:6682 backend.c:6705 backend.c:6736
+#: backend.c:14697
msgid "It is Black's turn"
msgstr "Ход черных"
-#: backend.c:6552
+#: backend.c:6571
msgid "Displayed position is not current"
msgstr "Показанная позиция не соответствует положению в игре"
-#: backend.c:6790
+#: backend.c:6809
msgid "Illegal move"
msgstr "Неправильный ход"
-#: backend.c:6857
+#: backend.c:6876
msgid "End of game"
msgstr "Сыгран последний записанный ход"
-#: backend.c:6860
+#: backend.c:6879
msgid "Incorrect move"
msgstr "Неверный ход"
-#: backend.c:7169 backend.c:7296
+#: backend.c:7257 backend.c:7392
msgid "Pull pawn backwards to under-promote"
msgstr ""
-#: backend.c:7527
+#: backend.c:7364
+msgid "only marked squares are legal"
+msgstr ""
+
+#: backend.c:7624
msgid "Swiss tourney finished"
msgstr ""
-#: backend.c:8102
+#: backend.c:8199
msgid "Invalid pairing from pairing engine"
msgstr ""
-#: backend.c:8235
+#: backend.c:8332
#, c-format
msgid "Illegal move \"%s\" from %s machine"
msgstr "Неправильный ход \"%s\" пытается выполнить движок %s"
-#: backend.c:8456
+#: backend.c:8564
msgid "Bad FEN received from engine"
msgstr ""
-#: backend.c:8600 backend.c:13662 backend.c:13727
+#: backend.c:8730 backend.c:13793 backend.c:13858
#, c-format
msgid "%s does not support analysis"
msgstr "%s не поддерживает режим анализа"
-#: backend.c:8666
+#: backend.c:8796
#, c-format
msgid "Illegal move \"%s\" (rejected by %s chess program)"
msgstr "Неправильный ход \"%s\" (не принят движком %s)"
-#: backend.c:8693
+#: backend.c:8823
#, c-format
msgid "Failed to start %s chess program %s on %s: %s\n"
msgstr "Не удалось запустить %s движок %s на %s: %s\n"
-#: backend.c:8714
+#: backend.c:8844
#, c-format
msgid "Hint: %s"
msgstr "Подсказка: %s"
-#: backend.c:8719
+#: backend.c:8849
#, c-format
msgid ""
"Illegal hint move \"%s\"\n"
"from %s chess program"
msgstr ""
-#: backend.c:8894
+#: backend.c:9024
msgid "Machine accepts your draw offer"
msgstr "Компьютер согласился на ничью"
-#: backend.c:8897
+#: backend.c:9027
msgid ""
"Machine offers a draw\n"
"Select Action / Draw to agree"
msgstr ""
-#: backend.c:8976
+#: backend.c:9106
msgid "failed writing PV"
msgstr ""
-#: backend.c:9274
+#: backend.c:9404
#, c-format
msgid "Ambiguous move in ICS output: \"%s\""
msgstr "Неоднозначный ход с сервера ICS: \"%s\""
-#: backend.c:9284
+#: backend.c:9414
#, c-format
msgid "Illegal move in ICS output: \"%s\""
msgstr "Неправильный ход с сервера ICS: \"%s\""
-#: backend.c:9295
+#: backend.c:9425
msgid "Gap in move list"
msgstr "Пропуск в записи ходов"
-#: backend.c:9916 dialogs.c:460
+#: backend.c:10046 dialogs.c:461
#, c-format
msgid "Variant %s not supported by %s"
msgstr "Вариант %s не поддерживается %s"
-#: backend.c:10037
+#: backend.c:10167
#, c-format
msgid "Startup failure on '%s'"
msgstr "Ошибка при запуске программы '%s'"
-#: backend.c:10068
+#: backend.c:10198
msgid "Waiting for first chess program"
msgstr "Ждем первую шахматную программу"
-#: backend.c:10073 backend.c:13945
+#: backend.c:10203 backend.c:14076
msgid "Waiting for second chess program"
msgstr "Ждем вторую шахматную программу"
-#: backend.c:10122
+#: backend.c:10252
msgid "Could not write on tourney file"
msgstr ""
-#: backend.c:10196
+#: backend.c:10326
msgid ""
"You cannot replace an engine while it is engaged!\n"
"Terminate its game first."
msgstr ""
-#: backend.c:10210
+#: backend.c:10340
msgid "No engine with the name you gave is installed"
msgstr ""
-#: backend.c:10212
+#: backend.c:10342
msgid ""
"First change an engine by editing the participants list\n"
"of the Tournament Options dialog"
msgstr ""
-#: backend.c:10213
+#: backend.c:10343
msgid "You can only change one engine at the time"
msgstr ""
-#: backend.c:10228 backend.c:10375
+#: backend.c:10358 backend.c:10505
#, c-format
msgid "No engine %s is installed"
msgstr ""
-#: backend.c:10248
+#: backend.c:10378
msgid ""
"You must supply a tournament file,\n"
"for storing the tourney progress"
msgstr ""
-#: backend.c:10258
+#: backend.c:10388
msgid "Not enough participants"
msgstr ""
-#: backend.c:10459
+#: backend.c:10589
msgid "Bad tournament file"
msgstr ""
-#: backend.c:10471
+#: backend.c:10601
msgid "Waiting for other game(s)"
msgstr ""
-#: backend.c:10484
+#: backend.c:10614
msgid "No pairing engine specified"
msgstr ""
-#: backend.c:10961
+#: backend.c:11092
#, c-format
msgid "Match %s vs. %s: final score %d-%d-%d"
msgstr "Матч %s против %s: финальный результат %d-%d-%d"
-#: backend.c:11423 backend.c:11454
+#: backend.c:11554 backend.c:11585
#, c-format
msgid "Illegal move: %d.%s%s"
msgstr "Неправильный ход: %d.%s%s"
-#: backend.c:11443
+#: backend.c:11574
#, c-format
msgid "Ambiguous move: %d.%s%s"
msgstr "Неоднозначный ход: %d.%s%s"
-#: backend.c:11496 backend.c:12505 backend.c:12698 backend.c:13059
+#: backend.c:11627 backend.c:12636 backend.c:12829 backend.c:13190
#, c-format
msgid "Can't open \"%s\""
msgstr "Не могу открыть файл \"%s\""
-#: backend.c:11508 menus.c:116
+#: backend.c:11639 menus.c:116
msgid "Cannot build game list"
msgstr "Не удалось создать список партий"
-#: backend.c:11593
+#: backend.c:11724
msgid "No more games in this message"
msgstr "В этом сообщении больше нет шахматных партий"
-#: backend.c:11633
+#: backend.c:11764
msgid "No game has been loaded yet"
msgstr "Нет загруженных шахматных партий"
-#: backend.c:11637 backend.c:12486 ngamelist.c:129
+#: backend.c:11768 backend.c:12617 ngamelist.c:129
msgid "Can't back up any further"
msgstr "Достигнуто начало списка"
-#: backend.c:12058
+#: backend.c:12189
msgid "Game number out of range"
msgstr "Номер партии - вне диапазона"
-#: backend.c:12069
+#: backend.c:12200
msgid "Can't seek on game file"
msgstr "Поиск в файлах записей партий не предусмотрен"
-#: backend.c:12127
+#: backend.c:12258
msgid "Game not found in file"
msgstr "Партия не найдена в файле"
-#: backend.c:12255 backend.c:12582
+#: backend.c:12386 backend.c:12713
msgid "Bad FEN position in file"
msgstr "Неправильная позиция формата FEN в файле"
-#: backend.c:12407
+#: backend.c:12538
msgid "No moves in game"
msgstr "Нет записанных ходов"
-#: backend.c:12482
+#: backend.c:12613
msgid "No position has been loaded yet"
msgstr "Нет загруженных позиций"
-#: backend.c:12543 backend.c:12554
+#: backend.c:12674 backend.c:12685
msgid "Can't seek on position file"
msgstr "Поиск в файлах позиций не предусмотрен"
-#: backend.c:12561 backend.c:12573
+#: backend.c:12692 backend.c:12704
msgid "Position not found in file"
msgstr "Позиция не найдена в файле"
-#: backend.c:12613
+#: backend.c:12744
msgid "Black to play"
msgstr "Ход черных"
-#: backend.c:12616
+#: backend.c:12747
msgid "White to play"
msgstr "Ход белых"
-#: backend.c:12703 backend.c:13064
+#: backend.c:12834 backend.c:13195
msgid "Waiting for access to save file"
msgstr ""
-#: backend.c:12705
+#: backend.c:12836
msgid "Saving game"
msgstr ""
-#: backend.c:12706
+#: backend.c:12837
msgid "Bad Seek"
msgstr ""
-#: backend.c:13066
+#: backend.c:13197
msgid "Saving position"
msgstr ""
-#: backend.c:13192
+#: backend.c:13323
msgid ""
"You have edited the game history.\n"
"Use Reload Same Game and make your move again."
msgstr ""
-#: backend.c:13197
+#: backend.c:13328
msgid ""
"You have entered too many moves.\n"
"Back up to the correct position and try again."
msgstr ""
-#: backend.c:13202
+#: backend.c:13333
msgid ""
"Displayed position is not current.\n"
"Step forward to the correct position and try again."
msgstr ""
-#: backend.c:13249
+#: backend.c:13380
msgid "You have not made a move yet"
msgstr "Вы еще не сделали ход"
-#: backend.c:13270
+#: backend.c:13401
msgid ""
"The cmail message is not loaded.\n"
"Use Reload CMail Message and make your move again."
msgstr ""
-#: backend.c:13275
+#: backend.c:13406
msgid "No unfinished games"
msgstr "Нет неоконченных партий"
-#: backend.c:13281
+#: backend.c:13412
#, c-format
msgid ""
"You have already mailed a move.\n"
"on the command line."
msgstr ""
-#: backend.c:13296
+#: backend.c:13427
msgid "Failed to invoke cmail"
msgstr "Ошибка запуска cmail"
-#: backend.c:13358
+#: backend.c:13489
#, c-format
msgid "Waiting for reply from opponent\n"
msgstr "Ожидание ответного хода\n"
-#: backend.c:13380
+#: backend.c:13511
#, c-format
msgid "Still need to make move for game\n"
msgstr "Все еще ваша очередь ходить в этой партии\n"
-#: backend.c:13384
+#: backend.c:13515
#, c-format
msgid "Still need to make moves for both games\n"
msgstr "Все еще ваша очередь ходить в обеих партиях\n"
-#: backend.c:13388
+#: backend.c:13519
#, c-format
msgid "Still need to make moves for all %d games\n"
msgstr "Все еще ваш ход во всех %d партиях\n"
-#: backend.c:13395
+#: backend.c:13526
#, c-format
msgid "Still need to make a move for game %s\n"
msgstr "Все еще ваш ход в партии %s\n"
-#: backend.c:13401
+#: backend.c:13532
#, c-format
msgid "No unfinished games\n"
msgstr "Нет неоконченных партий\n"
-#: backend.c:13403
+#: backend.c:13534
#, c-format
msgid "Ready to send mail\n"
msgstr "Можно отсылать почту\n"
-#: backend.c:13408
+#: backend.c:13539
#, c-format
msgid "Still need to make moves for games %s\n"
msgstr "Все еще ваша очередь ходить в партиях %s\n"
-#: backend.c:13612
+#: backend.c:13743
msgid "Edit comment"
msgstr "Правка комментария"
-#: backend.c:13614
+#: backend.c:13745
#, c-format
msgid "Edit comment on %d.%s%s"
msgstr "Правка комментария к %d.%s%s"
-#: backend.c:13669
+#: backend.c:13800
#, c-format
msgid "You are not observing a game"
msgstr ""
-#: backend.c:13777
+#: backend.c:13908
msgid "It is not White's turn"
msgstr "Сейчас не ход белых"
-#: backend.c:13858
+#: backend.c:13989
msgid "It is not Black's turn"
msgstr "Сейчас не ход черных"
-#: backend.c:13966
+#: backend.c:14097
#, c-format
msgid "Starting %s chess program"
msgstr ""
-#: backend.c:13994 backend.c:15108
+#: backend.c:14125 backend.c:15240
msgid ""
"Wait until your turn,\n"
"or select Move Now"
msgstr ""
-#: backend.c:14128
+#: backend.c:14259
msgid "Training mode off"
msgstr "Тренировка окончена"
-#: backend.c:14136
+#: backend.c:14267
msgid "Training mode on"
msgstr "Тренировка"
-#: backend.c:14139
+#: backend.c:14270
msgid "Already at end of game"
msgstr "Сыграны все ходы данной партии"
-#: backend.c:14219
+#: backend.c:14350
msgid "Warning: You are still playing a game"
msgstr "Предупреждение: вы все еще продолжаете играть"
-#: backend.c:14222
+#: backend.c:14353
msgid "Warning: You are still observing a game"
msgstr "Предупреждение: вы все еще наблюдаете за игрой"
-#: backend.c:14225
+#: backend.c:14356
msgid "Warning: You are still examining a game"
msgstr "Предупреждение: вы все еще изучаете игру"
-#: backend.c:14292
+#: backend.c:14423
msgid "Click clock to clear board"
msgstr ""
-#: backend.c:14302
+#: backend.c:14433
msgid "Close ICS engine analyze..."
msgstr ""
-#: backend.c:14590
+#: backend.c:14722
msgid "That square is occupied"
msgstr "Это поле занято"
-#: backend.c:14614 backend.c:14640
+#: backend.c:14746 backend.c:14772
msgid "There is no pending offer on this move"
msgstr "К данному ходу никаких предложений не сделано"
-#: backend.c:14676 backend.c:14687
+#: backend.c:14808 backend.c:14819
msgid "Your opponent is not out of time"
msgstr "У вашего соперника еще есть время"
-#: backend.c:14753
+#: backend.c:14885
msgid "You must make your move before offering a draw"
msgstr "Вы должны сделать свой ход прежде, чем предлагать ничью"
-#: backend.c:15090
+#: backend.c:15222
msgid "You are not examining a game"
msgstr "Не включен режим изучения шахматных партий"
-#: backend.c:15094
+#: backend.c:15226
msgid "You can't revert while pausing"
msgstr "Нельзя вернуться к началу пока выбрана \"Пауза\""
-#: backend.c:15148 backend.c:15155
+#: backend.c:15280 backend.c:15287
msgid "It is your turn"
msgstr "Ваш ход"
-#: backend.c:15206 backend.c:15213 backend.c:15266 backend.c:15273
+#: backend.c:15338 backend.c:15345 backend.c:15398 backend.c:15405
msgid "Wait until your turn"
msgstr "Подождите своей очереди ходить"
-#: backend.c:15218
+#: backend.c:15350
msgid "No hint available"
msgstr "Подсказок нет"
-#: backend.c:15234 ngamelist.c:355
+#: backend.c:15366 ngamelist.c:355
#, fuzzy
msgid "Game list not loaded or empty"
msgstr "Нет загруженных шахматных партий"
-#: backend.c:15241
+#: backend.c:15373
msgid "Book file exists! Try again for overwrite."
msgstr ""
-#: backend.c:15719
+#: backend.c:15851
#, c-format
msgid "Error writing to %s chess program"
msgstr "Ошибка записи на вход движка %s"
-#: backend.c:15722 backend.c:15753
+#: backend.c:15854 backend.c:15885
#, c-format
msgid "%s program exits in draw position (%s)"
msgstr ""
-#: backend.c:15748
+#: backend.c:15880
#, c-format
msgid "Error: %s chess program (%s) exited unexpectedly"
msgstr "Ошибка: движок %s (%s) завершил работу"
-#: backend.c:15766
+#: backend.c:15898
#, c-format
msgid "Error reading from %s chess program (%s)"
msgstr "Ошибка чтения с выхода движка %s (%s)"
-#: backend.c:16168
+#: backend.c:16301
#, c-format
msgid "%s engine has too many options\n"
msgstr ""
-#: backend.c:16324
+#: backend.c:16457
msgid "Displayed move is not current"
msgstr "Позиция не отвечает положению в игре"
-#: backend.c:16333
+#: backend.c:16466
msgid "Could not parse move"
msgstr "Невозможно интерпретировать ход"
-#: backend.c:16458 backend.c:16480
+#: backend.c:16591 backend.c:16613
msgid "Both flags fell"
msgstr "У обоих игроков время вышло"
-#: backend.c:16460
+#: backend.c:16593
msgid "White's flag fell"
msgstr "У белых упал флажок"
-#: backend.c:16482
+#: backend.c:16615
msgid "Black's flag fell"
msgstr "У черных упал флажок"
-#: backend.c:16613
+#: backend.c:16746
msgid "Clock adjustment not allowed in auto-flag mode"
msgstr ""
-#: backend.c:17448
+#: backend.c:17585
msgid "Bad FEN position in clipboard"
msgstr "Позиция в буфере обмена не соответствует формату FEN"
msgid "First you must specify an existing tourney file to clone"
msgstr ""
-#: dialogs.c:332 dialogs.c:1320
+#: dialogs.c:332 dialogs.c:1322
msgid "# no engines are installed"
msgstr ""
msgid "Play Move(s) of Clicked PV (Analysis)"
msgstr ""
-#: dialogs.c:379 dialogs.c:514 menus.c:728
+#: dialogs.c:379 dialogs.c:515 menus.c:728
msgid "Ponder Next Move"
msgstr "Думать всегда"
msgstr ""
#: dialogs.c:429
-msgid "fairy"
+msgid "ASEAN"
msgstr ""
#: dialogs.c:430
msgstr ""
#: dialogs.c:447
-msgid " "
+msgid "fairy"
msgstr ""
-#: dialogs.c:448
+#: dialogs.c:449
msgid "courier (12x8)"
msgstr ""
-#: dialogs.c:465
+#: dialogs.c:466
#, c-format
msgid "Warning: second engine (%s) does not support this!"
msgstr "Предупреждение: второй движок (%s) не поддерживает это!"
-#: dialogs.c:488
+#: dialogs.c:489
#, c-format
msgid "Only bughouse is not available in viewer mode"
msgstr ""
-#: dialogs.c:489
+#: dialogs.c:490
#, c-format
msgid ""
"All variants not supported by first engine\n"
"(currently %s) are disabled"
msgstr ""
-#: dialogs.c:490
+#: dialogs.c:491
msgid "New Variant"
msgstr "Варианты"
-#: dialogs.c:515
+#: dialogs.c:516
msgid "Maximum Number of CPUs per Engine:"
msgstr "Max число CPU:"
-#: dialogs.c:516
+#: dialogs.c:517
msgid "Polygot Directory:"
msgstr ""
-#: dialogs.c:517
+#: dialogs.c:518
msgid "Hash-Table Size (MB):"
msgstr "Размер хеша (МБ):"
-#: dialogs.c:518
+#: dialogs.c:519
msgid "Nalimov EGTB Path:"
msgstr "Путь к ЭБД:"
-#: dialogs.c:519
+#: dialogs.c:520
msgid "EGTB Cache Size (MB):"
msgstr "Кеш ЭБД (МБ):"
-#: dialogs.c:520
+#: dialogs.c:521
msgid "Use GUI Book"
msgstr ""
-#: dialogs.c:521
+#: dialogs.c:522
msgid "Opening-Book Filename:"
msgstr ""
-#: dialogs.c:522
+#: dialogs.c:523
msgid "Book Depth (moves):"
msgstr "Глубина книги:"
-#: dialogs.c:523
+#: dialogs.c:524
msgid "Book Variety (0) vs. Strength (100):"
msgstr "Варьирование:"
-#: dialogs.c:524
+#: dialogs.c:525
msgid "Engine #1 Has Own Book"
msgstr "Своя книга у движка 1"
-#: dialogs.c:525
+#: dialogs.c:526
msgid "Engine #2 Has Own Book "
msgstr ""
-#: dialogs.c:534
+#: dialogs.c:535
msgid "Common Engine Settings"
msgstr "Общие настройки движков"
-#: dialogs.c:540
+#: dialogs.c:541
msgid "Detect all Mates"
msgstr "Определять мат"
-#: dialogs.c:541
+#: dialogs.c:542
msgid "Verify Engine Result Claims"
msgstr "Проверять требования движка"
-#: dialogs.c:542
+#: dialogs.c:543
msgid "Draw if Insufficient Mating Material"
msgstr "Ничья при нехватке материала"
-#: dialogs.c:543
+#: dialogs.c:544
msgid "Adjudicate Trivial Draws (3-Move Delay)"
msgstr "Ничья в технич. окончаниях"
-#: dialogs.c:544
+#: dialogs.c:545
msgid "N-Move Rule:"
msgstr ""
-#: dialogs.c:545
+#: dialogs.c:546
msgid "N-fold Repeats:"
msgstr ""
-#: dialogs.c:546
+#: dialogs.c:547
msgid "Draw after N Moves Total:"
msgstr "Присудить ничью после"
-#: dialogs.c:547
+#: dialogs.c:548
msgid "Win / Loss Threshold:"
msgstr "Победа/поражение при перевесе в"
-#: dialogs.c:548
+#: dialogs.c:549
msgid "Negate Score of Engine #1"
msgstr "Оценка движка 1 - абсолютная"
-#: dialogs.c:549
+#: dialogs.c:550
msgid "Negate Score of Engine #2"
msgstr "Оценка движка 2 - абсолютная"
-#: dialogs.c:556
+#: dialogs.c:557
#, fuzzy
msgid "Adjudicate non-ICS Games"
msgstr "Присудить победу белым"
-#: dialogs.c:569
+#: dialogs.c:570
msgid "Auto-Kibitz"
msgstr ""
-#: dialogs.c:570
+#: dialogs.c:571
msgid "Auto-Comment"
msgstr "Комментарии"
-#: dialogs.c:571
+#: dialogs.c:572
msgid "Auto-Observe"
msgstr "Следить за игрой"
-#: dialogs.c:572
+#: dialogs.c:573
msgid "Auto-Raise Board"
msgstr "Раскрывать доску"
-#: dialogs.c:573
+#: dialogs.c:574
msgid "Auto-Create Logon Script"
msgstr ""
-#: dialogs.c:574
+#: dialogs.c:575
msgid "Background Observe while Playing"
msgstr "Следить в фоне"
-#: dialogs.c:575
+#: dialogs.c:576
msgid "Dual Board for Background-Observed Game"
msgstr "Двойная доска"
-#: dialogs.c:576
+#: dialogs.c:577
msgid "Get Move List"
msgstr "Запрашивать запись ходов"
-#: dialogs.c:577
+#: dialogs.c:578
msgid "Quiet Play"
msgstr "Спокойная игра"
-#: dialogs.c:578
+#: dialogs.c:579
msgid "Seek Graph"
msgstr "График поиска"
-#: dialogs.c:579
+#: dialogs.c:580
msgid "Auto-Refresh Seek Graph"
msgstr "Автообновление"
-#: dialogs.c:580
+#: dialogs.c:581
msgid "Auto-InputBox PopUp"
msgstr ""
-#: dialogs.c:581
+#: dialogs.c:582
+msgid "Quit after game"
+msgstr ""
+
+#: dialogs.c:583
msgid "Premove"
msgstr "Предварительный ход"
-#: dialogs.c:582
+#: dialogs.c:584
msgid "Premove for White"
msgstr ""
-#: dialogs.c:583
+#: dialogs.c:585
msgid "First White Move:"
msgstr "1-й ход белых"
-#: dialogs.c:584
+#: dialogs.c:586
msgid "Premove for Black"
msgstr ""
-#: dialogs.c:585
+#: dialogs.c:587
msgid "First Black Move:"
msgstr "1-й ход черных"
-#: dialogs.c:587
+#: dialogs.c:589
msgid "Alarm"
msgstr "Звонок"
-#: dialogs.c:588
+#: dialogs.c:590
msgid "Alarm Time (msec):"
msgstr ""
-#: dialogs.c:590
+#: dialogs.c:592
msgid "Colorize Messages"
msgstr ""
-#: dialogs.c:591
+#: dialogs.c:593
msgid "Shout Text Colors:"
msgstr ""
-#: dialogs.c:592
+#: dialogs.c:594
msgid "S-Shout Text Colors:"
msgstr ""
-#: dialogs.c:593
+#: dialogs.c:595
msgid "Channel #1 Text Colors:"
msgstr ""
-#: dialogs.c:594
+#: dialogs.c:596
msgid "Other Channel Text Colors:"
msgstr ""
-#: dialogs.c:595
+#: dialogs.c:597
msgid "Kibitz Text Colors:"
msgstr ""
-#: dialogs.c:596
+#: dialogs.c:598
msgid "Tell Text Colors:"
msgstr ""
-#: dialogs.c:597
+#: dialogs.c:599
msgid "Challenge Text Colors:"
msgstr ""
-#: dialogs.c:598
+#: dialogs.c:600
msgid "Request Text Colors:"
msgstr ""
-#: dialogs.c:599
+#: dialogs.c:601
msgid "Seek Text Colors:"
msgstr ""
-#: dialogs.c:606
+#: dialogs.c:608
msgid "ICS Options"
msgstr "Настройки соединения с ICS"
-#: dialogs.c:611
+#: dialogs.c:613
msgid "Exact position match"
msgstr ""
-#: dialogs.c:611
+#: dialogs.c:613
msgid "Shown position is subset"
msgstr ""
-#: dialogs.c:611
+#: dialogs.c:613
msgid "Same material with exactly same Pawn chain"
msgstr ""
-#: dialogs.c:612
+#: dialogs.c:614
msgid "Same material"
msgstr ""
-#: dialogs.c:612
+#: dialogs.c:614
msgid "Material range (top board half optional)"
msgstr ""
-#: dialogs.c:612
+#: dialogs.c:614
msgid "Material difference (optional stuff balanced)"
msgstr ""
-#: dialogs.c:624
+#: dialogs.c:626
msgid "Auto-Display Tags"
msgstr ""
-#: dialogs.c:625
+#: dialogs.c:627
msgid "Auto-Display Comment"
msgstr ""
-#: dialogs.c:626
+#: dialogs.c:628
msgid ""
"Auto-Play speed of loaded games\n"
"(0 = instant, -1 = off):"
msgstr ""
-#: dialogs.c:627
+#: dialogs.c:629
msgid "Seconds per Move:"
msgstr ""
-#: dialogs.c:628
+#: dialogs.c:630
msgid ""
"\n"
"options to use in game-viewer mode:"
msgstr ""
-#: dialogs.c:630
+#: dialogs.c:632
msgid ""
"\n"
"Thresholds for position filtering in game list:"
msgstr ""
-#: dialogs.c:631
+#: dialogs.c:633
msgid "Elo of strongest player at least:"
msgstr ""
-#: dialogs.c:632
+#: dialogs.c:634
msgid "Elo of weakest player at least:"
msgstr ""
-#: dialogs.c:633
+#: dialogs.c:635
#, fuzzy
msgid "No games before year:"
msgstr "Нет загруженных шахматных партий"
-#: dialogs.c:634
+#: dialogs.c:636
msgid "Minimum nr consecutive positions:"
msgstr ""
-#: dialogs.c:635
+#: dialogs.c:637
msgid "Search mode:"
msgstr ""
-#: dialogs.c:636
+#: dialogs.c:638
msgid "Also match reversed colors"
msgstr ""
-#: dialogs.c:637
+#: dialogs.c:639
msgid "Also match left-right flipped position"
msgstr ""
-#: dialogs.c:645
+#: dialogs.c:647
msgid "Load Game Options"
msgstr "Параметры загрузки"
-#: dialogs.c:657
+#: dialogs.c:659
msgid "Auto-Save Games"
msgstr ""
-#: dialogs.c:658
+#: dialogs.c:660
msgid "Own Games Only"
msgstr ""
-#: dialogs.c:659
+#: dialogs.c:661
msgid "Save Games on File:"
msgstr ""
-#: dialogs.c:660
+#: dialogs.c:662
msgid "Save Final Positions on File:"
msgstr ""
-#: dialogs.c:661
+#: dialogs.c:663
msgid "PGN Event Header:"
msgstr ""
-#: dialogs.c:662
+#: dialogs.c:664
msgid "Old Save Style (as opposed to PGN)"
msgstr ""
-#: dialogs.c:663
+#: dialogs.c:665
msgid "Include Number Tag in tourney PGN"
msgstr ""
-#: dialogs.c:664
+#: dialogs.c:666
msgid "Save Score/Depth Info in PGN"
msgstr ""
-#: dialogs.c:665
+#: dialogs.c:667
msgid "Save Out-of-Book Info in PGN "
msgstr ""
-#: dialogs.c:672
+#: dialogs.c:674
msgid "Save Game Options"
msgstr "Настройки сохранения"
-#: dialogs.c:681
+#: dialogs.c:683
msgid "No Sound"
msgstr "Без звука"
-#: dialogs.c:682
+#: dialogs.c:684
msgid "Default Beep"
msgstr "Простой сигнал"
-#: dialogs.c:683
+#: dialogs.c:685
msgid "Above WAV File"
msgstr ""
-#: dialogs.c:684
+#: dialogs.c:686
msgid "Car Horn"
msgstr ""
-#: dialogs.c:685
+#: dialogs.c:687
msgid "Cymbal"
msgstr ""
-#: dialogs.c:686
+#: dialogs.c:688
msgid "Ding"
msgstr ""
-#: dialogs.c:687
+#: dialogs.c:689
msgid "Gong"
msgstr ""
-#: dialogs.c:688
+#: dialogs.c:690
msgid "Laser"
msgstr ""
-#: dialogs.c:689
+#: dialogs.c:691
msgid "Penalty"
msgstr ""
-#: dialogs.c:690
+#: dialogs.c:692
msgid "Phone"
msgstr ""
-#: dialogs.c:691
+#: dialogs.c:693
msgid "Pop"
msgstr ""
-#: dialogs.c:692
+#: dialogs.c:694
msgid "Slap"
msgstr ""
-#: dialogs.c:693
+#: dialogs.c:695
msgid "Wood Thunk"
msgstr ""
-#: dialogs.c:695
+#: dialogs.c:697
msgid "User File"
msgstr ""
-#: dialogs.c:717
+#: dialogs.c:719
msgid "User WAV File:"
msgstr ""
-#: dialogs.c:718
+#: dialogs.c:720
msgid "Sound Program:"
msgstr ""
-#: dialogs.c:719
+#: dialogs.c:721
msgid "Try-Out Sound:"
msgstr ""
-#: dialogs.c:720
+#: dialogs.c:722
msgid "Play"
msgstr "Послушать"
-#: dialogs.c:721
+#: dialogs.c:723
msgid "Move:"
msgstr ""
-#: dialogs.c:722
+#: dialogs.c:724
msgid "Win:"
msgstr ""
-#: dialogs.c:723
+#: dialogs.c:725
msgid "Lose:"
msgstr ""
-#: dialogs.c:724
+#: dialogs.c:726
msgid "Draw:"
msgstr ""
-#: dialogs.c:725
+#: dialogs.c:727
msgid "Unfinished:"
msgstr ""
-#: dialogs.c:726
+#: dialogs.c:728
msgid "Alarm:"
msgstr ""
-#: dialogs.c:727
+#: dialogs.c:729
msgid "Challenge:"
msgstr ""
-#: dialogs.c:729
+#: dialogs.c:731
msgid "Sounds Directory:"
msgstr ""
-#: dialogs.c:730
+#: dialogs.c:732
msgid "Shout:"
msgstr ""
-#: dialogs.c:731
+#: dialogs.c:733
msgid "S-Shout:"
msgstr ""
-#: dialogs.c:732
+#: dialogs.c:734
msgid "Channel:"
msgstr ""
-#: dialogs.c:733
+#: dialogs.c:735
msgid "Channel 1:"
msgstr ""
-#: dialogs.c:734
+#: dialogs.c:736
msgid "Tell:"
msgstr ""
-#: dialogs.c:735
+#: dialogs.c:737
msgid "Kibitz:"
msgstr ""
-#: dialogs.c:736
+#: dialogs.c:738
msgid "Request:"
msgstr ""
-#: dialogs.c:737
+#: dialogs.c:739
msgid "Seek:"
msgstr ""
-#: dialogs.c:753
+#: dialogs.c:755
msgid "Sound Options"
msgstr "Звуки"
-#: dialogs.c:774
+#: dialogs.c:776
msgid "White Piece Color:"
msgstr ""
#. TRANSLATORS: R = single letter for the color red
-#: dialogs.c:777 dialogs.c:786 dialogs.c:792 dialogs.c:798 dialogs.c:804
-#: dialogs.c:810
+#: dialogs.c:779 dialogs.c:788 dialogs.c:794 dialogs.c:800 dialogs.c:806
+#: dialogs.c:812
msgid "R"
msgstr ""
#. TRANSLATORS: G = single letter for the color green
-#: dialogs.c:779 dialogs.c:787 dialogs.c:793 dialogs.c:799 dialogs.c:805
-#: dialogs.c:811
+#: dialogs.c:781 dialogs.c:789 dialogs.c:795 dialogs.c:801 dialogs.c:807
+#: dialogs.c:813
msgid "G"
msgstr ""
#. TRANSLATORS: B = single letter for the color blue
-#: dialogs.c:781 dialogs.c:788 dialogs.c:794 dialogs.c:800 dialogs.c:806
-#: dialogs.c:812
+#: dialogs.c:783 dialogs.c:790 dialogs.c:796 dialogs.c:802 dialogs.c:808
+#: dialogs.c:814
msgid "B"
msgstr ""
#. TRANSLATORS: D = single letter to make a color darker
-#: dialogs.c:783 dialogs.c:789 dialogs.c:795 dialogs.c:801 dialogs.c:807
-#: dialogs.c:813
+#: dialogs.c:785 dialogs.c:791 dialogs.c:797 dialogs.c:803 dialogs.c:809
+#: dialogs.c:815
msgid "D"
msgstr ""
-#: dialogs.c:784
+#: dialogs.c:786
msgid "Black Piece Color:"
msgstr "Черные фигуры"
-#: dialogs.c:790
+#: dialogs.c:792
msgid "Light Square Color:"
msgstr "Белые поля"
-#: dialogs.c:796
+#: dialogs.c:798
msgid "Dark Square Color:"
msgstr "Черные поля"
-#: dialogs.c:802
+#: dialogs.c:804
msgid "Highlight Color:"
msgstr "Выделенное поле"
-#: dialogs.c:808
+#: dialogs.c:810
msgid "Premove Highlight Color:"
msgstr "Предварит. ход"
-#: dialogs.c:814
+#: dialogs.c:816
msgid "Flip Pieces Shogi Style (Colored buttons restore default)"
msgstr ""
-#: dialogs.c:816
+#: dialogs.c:818
msgid "Mono Mode"
msgstr "Монохромная"
-#: dialogs.c:817
+#: dialogs.c:819
msgid "Line Gap ( -1 = default for board size):"
msgstr ""
-#: dialogs.c:818
+#: dialogs.c:820
msgid "Use Board Textures"
msgstr ""
-#: dialogs.c:819
+#: dialogs.c:821
msgid "Light-Squares Texture File:"
msgstr ""
-#: dialogs.c:820
+#: dialogs.c:822
msgid "Dark-Squares Texture File:"
msgstr ""
-#: dialogs.c:821
+#: dialogs.c:823
msgid "Use external piece bitmaps with their own colors"
msgstr ""
-#: dialogs.c:822
+#: dialogs.c:824
msgid "Directory with Pieces Images:"
msgstr ""
-#: dialogs.c:872
+#: dialogs.c:874
msgid "Board Options"
msgstr "Настройки доски"
-#: dialogs.c:925 menus.c:634
+#: dialogs.c:927 menus.c:634
msgid "ICS text menu"
msgstr ""
-#: dialogs.c:947
+#: dialogs.c:949
msgid "clear"
msgstr ""
-#: dialogs.c:948 dialogs.c:1036
+#: dialogs.c:950 dialogs.c:1038
msgid "save changes"
msgstr ""
-#: dialogs.c:1051
+#: dialogs.c:1053
#, fuzzy
msgid "Edit book"
msgstr "Правка"
-#: dialogs.c:1051 menus.c:636
+#: dialogs.c:1053 menus.c:636
msgid "Tags"
msgstr "Описание"
-#: dialogs.c:1193
+#: dialogs.c:1195
msgid "ICS input box"
msgstr ""
-#: dialogs.c:1225
+#: dialogs.c:1227
msgid "Type a move"
msgstr ""
-#: dialogs.c:1251
+#: dialogs.c:1253
msgid "Engine has no options"
msgstr ""
-#: dialogs.c:1253
+#: dialogs.c:1255
msgid "Engine Settings"
msgstr ""
-#: dialogs.c:1278
+#: dialogs.c:1280
msgid "Select engine from list:"
msgstr ""
-#: dialogs.c:1281
+#: dialogs.c:1283
msgid "or specify one below:"
msgstr ""
-#: dialogs.c:1282
+#: dialogs.c:1284
msgid "Nickname (optional):"
msgstr ""
-#: dialogs.c:1283
+#: dialogs.c:1285
msgid "Use nickname in PGN player tags of engine-engine games"
msgstr ""
-#: dialogs.c:1284
+#: dialogs.c:1286
msgid "Engine Directory:"
msgstr ""
-#: dialogs.c:1285
+#: dialogs.c:1287
msgid "Engine Command:"
msgstr ""
-#: dialogs.c:1286
+#: dialogs.c:1288
msgid "(Directory will be derived from engine path when empty)"
msgstr ""
-#: dialogs.c:1287
+#: dialogs.c:1289
msgid "UCI"
msgstr ""
-#: dialogs.c:1288
+#: dialogs.c:1290
msgid "WB protocol v1 (do not wait for engine features)"
msgstr ""
-#: dialogs.c:1289
+#: dialogs.c:1291
msgid "Must not use GUI book"
msgstr ""
-#: dialogs.c:1290
+#: dialogs.c:1292
msgid "Add this engine to the list"
msgstr ""
-#: dialogs.c:1291
+#: dialogs.c:1293
msgid "Force current variant with this engine"
msgstr ""
-#: dialogs.c:1341
+#: dialogs.c:1343
msgid "Load first engine"
msgstr ""
-#: dialogs.c:1347
+#: dialogs.c:1349
msgid "Load second engine"
msgstr ""
-#: dialogs.c:1370
+#: dialogs.c:1372
msgid "shuffle"
msgstr ""
-#: dialogs.c:1371
+#: dialogs.c:1373
msgid "Start-position number:"
msgstr "Номер позиции:"
-#: dialogs.c:1372
+#: dialogs.c:1374
#, fuzzy
msgid "randomize"
msgstr "Случайно"
-#: dialogs.c:1373
+#: dialogs.c:1375
msgid "pick fixed"
msgstr ""
-#: dialogs.c:1390
+#: dialogs.c:1392
msgid "New Shuffle Game"
msgstr "Новая в смешанные шахматы..."
-#: dialogs.c:1409
+#: dialogs.c:1411
msgid "classical"
msgstr ""
-#: dialogs.c:1410
+#: dialogs.c:1412
msgid "incremental"
msgstr ""
-#: dialogs.c:1411
+#: dialogs.c:1413
msgid "fixed max"
msgstr ""
-#: dialogs.c:1412
+#: dialogs.c:1414
msgid "Moves per session:"
msgstr ""
-#: dialogs.c:1413
+#: dialogs.c:1415
msgid "Initial time (min):"
msgstr ""
-#: dialogs.c:1414
+#: dialogs.c:1416
msgid "Increment or max (sec/move):"
msgstr ""
-#: dialogs.c:1415
+#: dialogs.c:1417
#, fuzzy
msgid "Time-Odds factors:"
msgstr "Фактор времени движков:"
-#: dialogs.c:1416
+#: dialogs.c:1418
#, fuzzy
msgid "Engine #1"
msgstr "Движок"
-#: dialogs.c:1417
+#: dialogs.c:1419
#, fuzzy
msgid "Engine #2 / Human"
msgstr "Своя книга у движка 1"
-#: dialogs.c:1457 dialogs.c:1460 dialogs.c:1465 dialogs.c:1466
+#: dialogs.c:1459 dialogs.c:1462 dialogs.c:1467 dialogs.c:1468
#: gtk/xoptions.c:191
msgid "Unused"
msgstr ""
-#: dialogs.c:1478
+#: dialogs.c:1480
msgid "Time Control"
msgstr ""
-#: dialogs.c:1507
+#: dialogs.c:1509
msgid "Error writing to chess program"
msgstr "Ошибка подключения к шахматной программе"
-#: dialogs.c:1574
+#: dialogs.c:1576
#, fuzzy
msgid "Cancel"
msgstr "Отмена"
-#: dialogs.c:1579 dialogs.c:1971 dialogs.c:1975
+#: dialogs.c:1581 dialogs.c:1973 dialogs.c:1977
msgid "King"
msgstr "Король"
-#: dialogs.c:1582
+#: dialogs.c:1584
msgid "Captain"
msgstr ""
-#: dialogs.c:1583
+#: dialogs.c:1585
msgid "Lieutenant"
msgstr ""
-#: dialogs.c:1584
+#: dialogs.c:1586
msgid "General"
msgstr "Общие..."
-#: dialogs.c:1585
+#: dialogs.c:1587
msgid "Warlord"
msgstr ""
-#: dialogs.c:1587 dialogs.c:1970 dialogs.c:1974 dialogs.c:1993
+#: dialogs.c:1589 dialogs.c:1972 dialogs.c:1976 dialogs.c:1995
msgid "Knight"
msgstr "Конь"
-#: dialogs.c:1588 dialogs.c:1970 dialogs.c:1974 dialogs.c:1993
+#: dialogs.c:1590 dialogs.c:1972 dialogs.c:1976 dialogs.c:1995
msgid "Bishop"
msgstr "Слон"
-#: dialogs.c:1589 dialogs.c:1970 dialogs.c:1974 dialogs.c:1993
+#: dialogs.c:1591 dialogs.c:1972 dialogs.c:1976 dialogs.c:1995
msgid "Rook"
msgstr "Ладья"
-#: dialogs.c:1593 dialogs.c:1972 dialogs.c:1976
+#: dialogs.c:1595 dialogs.c:1974 dialogs.c:1978
msgid "Archbishop"
msgstr "Архиепископ"
-#: dialogs.c:1594 dialogs.c:1972 dialogs.c:1976
+#: dialogs.c:1596 dialogs.c:1974 dialogs.c:1978
msgid "Chancellor"
msgstr "Канцлер"
-#: dialogs.c:1596 dialogs.c:1971 dialogs.c:1975 dialogs.c:1993
+#: dialogs.c:1598 dialogs.c:1973 dialogs.c:1977 dialogs.c:1995
msgid "Queen"
msgstr "Ферзь"
-#: dialogs.c:1600
+#: dialogs.c:1602
msgid "Defer"
msgstr ""
-#: dialogs.c:1601 dialogs.c:1972 dialogs.c:1976
+#: dialogs.c:1603 dialogs.c:1974 dialogs.c:1978
msgid "Promote"
msgstr "Превратить"
-#: dialogs.c:1616
+#: dialogs.c:1618
msgid "Chat partner:"
msgstr ""
-#: dialogs.c:1701
+#: dialogs.c:1703
msgid "Chat box"
msgstr ""
-#: dialogs.c:1742
+#: dialogs.c:1744
msgid "factory"
msgstr "Стандарт"
-#: dialogs.c:1743
+#: dialogs.c:1745
msgid "up"
msgstr "Вверх"
-#: dialogs.c:1744
+#: dialogs.c:1746
msgid "down"
msgstr "Вниз"
-#: dialogs.c:1762
+#: dialogs.c:1764
msgid "No tag selected"
msgstr ""
-#: dialogs.c:1793
+#: dialogs.c:1795
#, fuzzy
msgid "Game-list options"
msgstr "Параметры загрузки"
-#: dialogs.c:1869 dialogs.c:1883
+#: dialogs.c:1871 dialogs.c:1885
msgid "Error"
msgstr "Ошибка"
-#: dialogs.c:1906
+#: dialogs.c:1908
msgid "Fatal Error"
msgstr "Неисправимая ошибка"
-#: dialogs.c:1906
+#: dialogs.c:1908
msgid "Exiting"
msgstr "Выход"
-#: dialogs.c:1917
+#: dialogs.c:1919
msgid "Information"
msgstr "Информация"
-#: dialogs.c:1924
+#: dialogs.c:1926
msgid "Note"
msgstr "Примечание"
-#: dialogs.c:1970 dialogs.c:2245 dialogs.c:2248
+#: dialogs.c:1972 dialogs.c:2252 dialogs.c:2255
msgid "White"
msgstr "Белые"
-#: dialogs.c:1970 dialogs.c:1974 dialogs.c:1993
+#: dialogs.c:1972 dialogs.c:1976 dialogs.c:1995
msgid "Pawn"
msgstr "Пешка"
-#: dialogs.c:1971 dialogs.c:1975
+#: dialogs.c:1973 dialogs.c:1977
msgid "Elephant"
msgstr "Слон (стар.)"
-#: dialogs.c:1971 dialogs.c:1975
+#: dialogs.c:1973 dialogs.c:1977
msgid "Cannon"
msgstr "Пушка"
-#: dialogs.c:1972 dialogs.c:1976
+#: dialogs.c:1974 dialogs.c:1978
msgid "Demote"
msgstr "Разжаловать"
-#: dialogs.c:1973 dialogs.c:1977
+#: dialogs.c:1975 dialogs.c:1979
msgid "Empty square"
msgstr "Пустое поле"
-#: dialogs.c:1973 dialogs.c:1977
+#: dialogs.c:1975 dialogs.c:1979
msgid "Clear board"
msgstr "Очистить доску"
-#: dialogs.c:1974 dialogs.c:2257 dialogs.c:2260
+#: dialogs.c:1976 dialogs.c:2264 dialogs.c:2267
msgid "Black"
msgstr "Черные"
-#: dialogs.c:2073 menus.c:787
+#: dialogs.c:2075 menus.c:787
msgid "File"
msgstr "Файл"
-#: dialogs.c:2074 menus.c:788
+#: dialogs.c:2076 menus.c:788
msgid "Edit"
msgstr "Правка"
-#: dialogs.c:2075 menus.c:789
+#: dialogs.c:2077 menus.c:789
msgid "View"
msgstr "Вид"
-#: dialogs.c:2076 menus.c:790
+#: dialogs.c:2078 menus.c:790
msgid "Mode"
msgstr "Режим"
-#: dialogs.c:2077 menus.c:791
+#: dialogs.c:2079 menus.c:791
msgid "Action"
msgstr "Игра"
-#: dialogs.c:2078 menus.c:792
+#: dialogs.c:2080 menus.c:792
msgid "Engine"
msgstr "Движок"
-#: dialogs.c:2079 menus.c:793
+#: dialogs.c:2081 menus.c:793
msgid "Options"
msgstr "Настройки"
-#: dialogs.c:2080 menus.c:794
+#: dialogs.c:2082 menus.c:794
msgid "Help"
msgstr "Справка"
-#: dialogs.c:2090
+#: dialogs.c:2092
msgid "<<"
msgstr ""
-#: dialogs.c:2091
+#: dialogs.c:2093
msgid "<"
msgstr ""
-#: dialogs.c:2093
+#: dialogs.c:2095
msgid ">"
msgstr ""
-#: dialogs.c:2094
+#: dialogs.c:2096
msgid ">>"
msgstr ""
-#: dialogs.c:2364
+#: dialogs.c:2371
msgid "Directories:"
msgstr ""
-#: dialogs.c:2365
+#: dialogs.c:2372
#, fuzzy
msgid "Files:"
msgstr "Файл"
-#: dialogs.c:2366
+#: dialogs.c:2373
msgid "by name"
msgstr ""
-#: dialogs.c:2367
+#: dialogs.c:2374
msgid "by type"
msgstr ""
-#: dialogs.c:2370
+#: dialogs.c:2377
#, fuzzy
msgid "Filename:"
msgstr "Фильтр"
-#: dialogs.c:2371
+#: dialogs.c:2378
msgid "New directory"
msgstr ""
-#: dialogs.c:2372
+#: dialogs.c:2379
#, fuzzy
msgid "File type:"
msgstr "Фильтр"
-#: dialogs.c:2447
+#: dialogs.c:2454
#, fuzzy
msgid "Contents of"
msgstr "Комментарии"
-#: dialogs.c:2473
+#: dialogs.c:2480
msgid " next page"
msgstr ""
-#: dialogs.c:2495
+#: dialogs.c:2502
msgid "FIRST TYPE DIRECTORY NAME HERE"
msgstr ""
-#: dialogs.c:2496
+#: dialogs.c:2503
msgid "TRY ANOTHER NAME"
msgstr ""
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* The following terms apply to Digital Equipment Corporation's copyright
* interest in XBoard:
#include "frontend.h"
-void
+int
PlaySoundFile (char *name)
{
if (*name == NULLCHAR) {
- return;
+ return 0;
} else if (strcmp(name, "$") == 0) {
putc(BELLCHAR, stderr);
} else {
char buf[2048];
char *prefix = "", *sep = "";
- if(appData.soundProgram[0] == NULLCHAR) return;
+ if(appData.soundProgram[0] == NULLCHAR) return 1;
if(!strchr(name, '/')) { prefix = appData.soundDirectory; sep = "/"; }
snprintf(buf, sizeof(buf), "%s '%s%s%s' &", appData.soundProgram, prefix, sep, name);
system(buf);
}
+ return 1;
}
void
PlaySoundFile(appData.soundTell);
}
+int
+Roar ()
+{
+ return PlaySoundFile(appData.soundRoar);
+}
+
void
PlaySoundForColor (ColorClass cc)
{
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* The following terms apply to Digital Equipment Corporation's copyright
* interest in XBoard:
parse_cpair (ColorClass cc, char *str)
{
if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
- fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
+ fprintf(stderr, _("%s: can't parse foreground color in '%s'\n"),
programName, str);
return -1;
}
}
if (*s == '~') {
+ if(s[1] == '~') { // use ~~ for XBoard's private data directory
+ snprintf(d, 4*MSG_SIZ, DATADIR "%s", s+2);
+ } else
if (*(s+1) == '/') {
safeStrCpy(d, getpwuid(getuid())->pw_dir, 4*MSG_SIZ );
strcat(d, s+1);
* Massachusetts.\r
*\r
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,\r
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.\r
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.\r
*\r
* Enhancements Copyright 2005 Alessandro Scotti\r
*\r
#define BUILT_IN_SOUND_NAMES {\\r
"Beepbeep", "Ching", "Click", "Cymbal", "Ding", "Drip", \\r
"Gong", "Laser", "Move", "Penalty", "Phone", "Pop", "Pop2", \\r
- "Slap", "Squeak", "Swish", "Thud", "Whipcrack", \\r
+ "Roar", "Slap", "Squeak", "Swish", "Thud", "Whipcrack", \\r
"Alarm", "Challenge", "Channel", "Channel1", "Draw", "Kibitz", \\r
"Lose", "Request", "Seek", "Shout", "SShout", "Tell", "Unfinished", \\r
"Win", NULL \\r
}\r
\r
#define SETTINGS_FILE "winboard.ini"\r
-#define DEBUG_FILE "winboard.debug"
+#define DEBUG_FILE "winboard.debug"\r
\r
#define ICS_LOGON "ics.ini"\r
\r
/*\r
* wclipbrd.c -- Clipboard routines for WinBoard\r
*\r
- * Copyright 2000, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.\r
+ * Copyright 2000, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.\r
*\r
* Enhancements Copyright 2005 Alessandro Scotti\r
*\r
\r
/* Imports from winboard.c */\r
extern HWND hwndMain;\r
-Boolean ParseFEN(Board b, int *stm, char *FEN);\r
\r
/* File globals */\r
static char *copyTemp;\r
char *fen = NULL;\r
\r
if(gameMode == EditPosition) EditPositionDone(TRUE); // [HGM] mak sure castling rights are set consistently\r
- fen = PositionToFEN(currentMove, NULL);\r
+ fen = PositionToFEN(currentMove, NULL, 1);\r
if (!fen) {\r
DisplayError(_("Unable to convert position to FEN."), 0);\r
return;\r
}\r
\r
// [HGM] paste any: make still smarter, to allow pasting of games without tags, recognize FEN in stead\r
- if(!ParseFEN(dummyBoard, &dummy, buf) ) {\r
+ if(!ParseFEN(dummyBoard, &dummy, buf, 0) ) {\r
PasteGameFromString( buf );\r
}\r
else {\r
/*\r
* wedittags.c -- EditTags window for WinBoard\r
*\r
- * Copyright 1995, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.\r
+ * Copyright 1995, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.\r
*\r
* Enhancements Copyright 2005 Alessandro Scotti\r
*\r
case WM_COMMAND:\r
switch (LOWORD(wParam)) {\r
case IDOK:\r
+ case OPT_TagsSave:\r
if (canEditTags) {\r
char *p, *q;\r
/* Read changed options from the dialog box */\r
}\r
*p = NULLCHAR; err = 0;\r
if(resPtr) *resPtr = strdup(str); else\r
- if(bookUp) SaveToBook(str); else\r
+ if(bookUp) SaveToBook(str), DisplayBook(currentMove); else\r
err = ReplaceTags(str, &gameInfo);\r
if (err) DisplayError(_("Error replacing tags."), err);\r
\r
free(str);\r
}\r
- TagsPopDown();\r
+ if(LOWORD(wParam) == IDOK) TagsPopDown();\r
return TRUE;\r
\r
case IDCANCEL:\r
* WinBoard.c -- Windows NT front end to XBoard\r
*\r
* Copyright 1991 by Digital Equipment Corporation, Maynard,\r
- * Massachusetts. \r
+ * Massachusetts.\r
*\r
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,\r
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.\r
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.\r
*\r
* Enhancements Copyright 2005 Alessandro Scotti\r
*\r
int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,\r
/*char*/int promoChar));\r
void DisplayMove P((int moveNumber));\r
-Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));\r
void ChatPopUp P((char *s));\r
typedef struct {\r
ChessSquare piece; \r
RECT boardRect;\r
COLORREF lightSquareColor, darkSquareColor, whitePieceColor, \r
blackPieceColor, highlightSquareColor, premoveHighlightColor;\r
+COLORREF markerColor[8] = { 0x00FFFF, 0x0000FF, 0x00FF00, 0xFF0000, 0xFFFF00, 0xFF00FF, 0xFFFFFF, 0x000000 };\r
HPALETTE hPal;\r
ColorClass currentColorClass;\r
\r
static HBRUSH lightSquareBrush, darkSquareBrush,\r
blackSquareBrush, /* [HGM] for band between board and holdings */\r
explodeBrush, /* [HGM] atomic */\r
- markerBrush, /* [HGM] markers */\r
+ markerBrush[8], /* [HGM] markers */\r
whitePieceBrush, blackPieceBrush, iconBkgndBrush /*, outlineBrush*/;\r
static POINT gridEndpoints[(BOARD_RANKS + BOARD_FILES + 2) * 2];\r
static DWORD gridVertexCounts[BOARD_RANKS + BOARD_FILES + 2];\r
#define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */\r
#else\r
\r
-\r
-\r
#if defined(_winmajor)\r
#define oldDialog (_winmajor < 4)\r
#else\r
\r
/* Set by InitInstance, used by EnsureOnScreen */\r
int screenHeight, screenWidth;\r
+ RECT screenGeometry;\r
\r
void\r
EnsureOnScreen(int *x, int *y, int minX, int minY)\r
{\r
// int gap = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);\r
/* Be sure window at (x,y) is not off screen (or even mostly off screen) */\r
- if (*x > screenWidth - 32) *x = 0;\r
- if (*y > screenHeight - 32) *y = 0;\r
- if (*x < minX) *x = minX;\r
- if (*y < minY) *y = minY;\r
+ if (*x > screenGeometry.right - 32) *x = screenGeometry.left;\r
+ if (*y > screenGeometry.bottom - 32) *y = screenGeometry.top;\r
+ if (*x < screenGeometry.left + minX) *x = screenGeometry.left + minX;\r
+ if (*y < screenGeometry.top + minY) *y = screenGeometry.top + minY;\r
}\r
\r
VOID\r
}\r
}\r
\r
+ #ifndef SM_CXVIRTUALSCREEN\r
+ #define SM_CXVIRTUALSCREEN 78\r
+ #endif\r
+ #ifndef SM_CYVIRTUALSCREEN\r
+ #define SM_CYVIRTUALSCREEN 79\r
+ #endif\r
+ #ifndef SM_XVIRTUALSCREEN \r
+ #define SM_XVIRTUALSCREEN 76\r
+ #endif\r
+ #ifndef SM_YVIRTUALSCREEN \r
+ #define SM_YVIRTUALSCREEN 77\r
+ #endif\r
+ \r
+ VOID\r
+ InitGeometry()\r
+ {\r
+ screenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);\r
+ if( !screenHeight ) screenHeight = GetSystemMetrics(SM_CYSCREEN);\r
+ screenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);\r
+ if( !screenWidth ) screenWidth = GetSystemMetrics(SM_CXSCREEN);\r
+ screenGeometry.left = GetSystemMetrics(SM_XVIRTUALSCREEN);\r
+ screenGeometry.top = GetSystemMetrics(SM_YVIRTUALSCREEN);\r
+ screenGeometry.right = screenGeometry.left + screenWidth;\r
+ screenGeometry.bottom = screenGeometry.top + screenHeight;\r
+ }\r
+ \r
BOOL\r
InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)\r
{\r
GetCurrentDirectory(MSG_SIZ, installDir);\r
}\r
gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise\r
- screenWidth = screenHeight = 1000; // [HGM] placement: kludge to allow calling EnsureOnScreen from InitAppData\r
+ InitGeometry();\r
InitAppData(lpCmdLine); /* Get run-time parameters */\r
/* xboard, and older WinBoards, controlled the move sound with the\r
appData.ringBellAfterMoves option. In the current WinBoard, we\r
iconBlack = LoadIcon(hInstance, "icon_black");\r
iconCurrent = iconWhite;\r
InitDrawingColors();\r
- screenHeight = GetSystemMetrics(SM_CYSCREEN);\r
- screenWidth = GetSystemMetrics(SM_CXSCREEN);\r
+ \r
InitPosition(0); // to set nr of ranks and files, which might be non-default through command-line args\r
for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {\r
/* Compute window size for each board size, and use the largest\r
VOID\r
InitDrawingColors()\r
{\r
+ int i;\r
if (pLogPal == NULL) {\r
/* Allocate enough memory for a logical palette with\r
* PALETTESIZE entries and set the size and version fields\r
blackPieceBrush = CreateSolidBrush(blackPieceColor);\r
iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));\r
explodeBrush = CreateSolidBrush(highlightSquareColor); // [HGM] atomic\r
- markerBrush = CreateSolidBrush(premoveHighlightColor); // [HGM] markers\r
- /* [AS] Force rendering of the font-based pieces */\r
+ for(i=0; i<8;i++) markerBrush[i] = CreateSolidBrush(markerColor[i]); // [HGM] markers\r
+\r
+ /* [AS] Force rendering of the font-based pieces */\r
if( fontBitmapSquareSize > 0 ) {\r
fontBitmapSquareSize = 0;\r
}\r
&& (boardSize < SizePetite || boardSize > SizeBulky) // Archbishop and Chancellor available in entire middle range\r
|| (v == VariantShogi && boardSize != SizeModerate) // Japanese-style Shogi\r
|| v == VariantKnightmate || v == VariantSChess || v == VariantXiangqi || v == VariantSpartan\r
- || v == VariantShatranj || v == VariantMakruk || v == VariantGreat || v == VariantFairy ) {\r
+ || v == VariantShatranj || v == VariantMakruk || v == VariantGreat || v == VariantFairy || v == VariantLion ) {\r
if(boardSize < SizeMediocre) boardSize = SizePetite; else\r
if(boardSize > SizeModerate) boardSize = SizeBulky; else\r
boardSize = SizeMiddling;\r
pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");\r
pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");\r
pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");\r
+ pieceBitmap[0][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "s");\r
+ pieceBitmap[1][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "o");\r
+ pieceBitmap[2][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "w");\r
\r
if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */\r
pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");\r
}\r
\r
return result;\r
+\r
+\r
+\r
}\r
\r
BOOL IsDrawArrowEnabled()\r
DisplayHoldingsCount(hdc, x, y, flipView, (int) board[row][column]);\r
else if( column == BOARD_RGHT) /* right align */\r
DisplayHoldingsCount(hdc, x, y, !flipView, (int) board[row][column]);\r
+ else if( piece == DarkSquare) DisplayHoldingsCount(hdc, x, y, 0, 0);\r
else\r
if (appData.monoMode) {\r
if (piece == EmptySquare) {\r
{\r
int square = color & 0x80;\r
HBRUSH oldBrush = SelectObject(hdcSeek, \r
- color == 0 ? markerBrush : color == 1 ? darkSquareBrush : explodeBrush);\r
+ color == 0 ? markerBrush[1] : color == 1 ? darkSquareBrush : explodeBrush);\r
color &= 0x7F;\r
if(square)\r
Rectangle(hdcSeek, boardRect.left+x - squareSize/9, boardRect.top+y - squareSize/9,\r
for (row = 0; row < BOARD_HEIGHT; row++) {\r
for (column = 0; column < BOARD_WIDTH; column++) {\r
if (marker[row][column]) { // marker changes only occur with full repaint!\r
- HBRUSH oldBrush = SelectObject(hdcmem, \r
- marker[row][column] == 2 ? markerBrush : explodeBrush);\r
+ HBRUSH oldBrush = SelectObject(hdcmem, markerBrush[marker[row][column]-1]);\r
SquareToPos(row, column, &x, &y);\r
Ellipse(hdcmem, x + squareSize/4, y + squareSize/4,\r
x + 3*squareSize/4, y + 3*squareSize/4);\r
} else if (PtInRect((LPRECT) &blackRect, pt)) {\r
ClockClick(!flipClock); break;\r
}\r
+ if(dragging) { // [HGM] lion: don't destroy dragging info if we are already dragging\r
dragInfo.start.x = dragInfo.start.y = -1;\r
dragInfo.from = dragInfo.start;\r
+ }\r
if(fromX == -1 && frozen) { // not sure where this is for\r
fromX = fromY = -1; \r
DrawPosition(forceFullRepaint || FALSE, NULL); /* [AS] */\r
if(PromoScroll(pt.x - boardRect.left, pt.y - boardRect.top)) break;\r
MovePV(pt.x - boardRect.left, pt.y - boardRect.top, boardRect.bottom - boardRect.top);\r
if ((appData.animateDragging || appData.highlightDragging)\r
- && (wParam & MK_LBUTTON)\r
+ && (wParam & MK_LBUTTON || dragging == 2)\r
&& dragInfo.from.x >= 0) \r
{\r
BOOL full_repaint = FALSE;\r
dragInfo.pos = pt;\r
}\r
if (appData.highlightDragging) {\r
- SetHighlights(fromX, fromY, x, y);\r
+ HoverEvent(highlightInfo.sq[1].x, highlightInfo.sq[1].y, x, y);\r
if( IsDrawArrowEnabled() && (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT) ) {\r
full_repaint = TRUE;\r
}\r
return CallWindowProc(buttonDesc[i].wndproc, hwnd, message, wParam, lParam);\r
}\r
\r
+static int promoStyle;\r
+\r
/* Process messages for Promotion dialog box */\r
LRESULT CALLBACK\r
Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
PieceToChar(BlackMarshall) != '~') ) ?\r
SW_SHOW : SW_HIDE);\r
/* [HGM] Hide B & R button in Shogi, use Q as promote, N as defer */\r
- ShowWindow(GetDlgItem(hDlg, PB_Rook),\r
- gameInfo.variant != VariantShogi ?\r
- SW_SHOW : SW_HIDE);\r
- ShowWindow(GetDlgItem(hDlg, PB_Bishop), \r
- gameInfo.variant != VariantShogi ?\r
- SW_SHOW : SW_HIDE);\r
- if(gameInfo.variant == VariantShogi) {\r
+ ShowWindow(GetDlgItem(hDlg, PB_Rook), !promoStyle ? SW_SHOW : SW_HIDE);\r
+ ShowWindow(GetDlgItem(hDlg, PB_Bishop), !promoStyle ? SW_SHOW : SW_HIDE);\r
+ if(promoStyle) {\r
SetDlgItemText(hDlg, PB_Queen, "YES");\r
SetDlgItemText(hDlg, PB_Knight, "NO");\r
SetWindowText(hDlg, "Promote?");\r
promoChar = gameInfo.variant == VariantSuper ? PieceToChar(BlackSilver) : PieceToChar(BlackKing);\r
break;\r
case PB_Queen:\r
- promoChar = gameInfo.variant == VariantShogi ? '+' : ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen));\r
+ promoChar = promoStyle ? '+' : ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen));\r
break;\r
case PB_Rook:\r
promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteRook : BlackRook));\r
promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteAngel : BlackAngel));\r
break;\r
case PB_Knight:\r
- promoChar = gameInfo.variant == VariantShogi ? '=' : PieceToChar(WhiteOnMove(currentMove) ? WhiteKnight : BlackKnight);\r
+ promoChar = gameInfo.variant == VariantShogi ? '=' : promoStyle ? NULLCHAR : \r
+ ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteKnight : BlackKnight));\r
break;\r
default:\r
return FALSE;\r
}\r
\r
void\r
-PromotionPopUp()\r
+PromotionPopUp(char choice)\r
{\r
+ promoStyle = (choice == '+');\r
DrawPosition(TRUE, NULL);\r
PromotionPopup(hwndMain);\r
}\r
nnew = RealizePalette(hdc);\r
if (nnew > 0) {\r
paletteChanged = TRUE;\r
+\r
InvalidateRect(hwnd, &boardRect, FALSE);\r
}\r
ReleaseDC(hwnd, hdc);\r
break;\r
\r
case IDM_Rematch:\r
+\r
RematchEvent();\r
break;\r
\r
SwapEngines(singleList); // temporarily swap first and second, to load a second 'first', ...\r
ParseArgs(StringGet, &p);\r
SwapEngines(singleList); // ... and then make it 'second'\r
+\r
appData.noChessProgram = FALSE;\r
appData.icsActive = FALSE;\r
} else if (IsDlgButtonChecked(hDlg, OPT_ChessServer)) {\r
static char *history[HISTORY_SIZE];\r
int histIn = 0, histP = 0;\r
\r
+\r
VOID\r
SaveInHistory(char *cmd)\r
{\r
histIn = (histIn + 1) % HISTORY_SIZE;\r
if (history[histIn] != NULL) {\r
free(history[histIn]);\r
+\r
history[histIn] = NULL;\r
}\r
histP = histIn;\r
else\r
err = GetLastError();\r
}\r
+\r
}\r
return err;\r
}\r
\r
// low-level front-end: clear text edit / list widget\r
void\r
+\r
GLT_ClearList()\r
{\r
SendDlgItemMessage( gameListOptionsDialog, IDC_GameListTags, LB_RESETCONTENT, 0, 0 );\r
}\r
\r
\r
+int\r
+Roar()\r
+{\r
+ MyPlaySound(&sounds[(int)SoundRoar]);\r
+ return 1;\r
+}\r
+\r
VOID\r
RingBell()\r
{\r
HDC hdc;\r
char *flag = blackFlag && gameMode == TwoMachinesPlay ? "(!)" : "";\r
\r
+\r
if(appData.noGUI) return;\r
hdc = GetDC(hwndMain);\r
if (!IsIconic(hwndMain)) {\r
int toY;\r
{\r
ChessSquare piece;\r
+ int x = toX, y = toY;\r
POINT start, finish, mid;\r
POINT frames[kFactor * 2 + 1];\r
int nFrames, n;\r
\r
+ if(killX >= 0 && IS_LION(board[fromY][fromX])) Roar();\r
+\r
if (!appData.animate) return;\r
if (doingSizing) return;\r
if (fromY < 0 || fromX < 0) return;\r
piece = board[fromY][fromX];\r
if (piece >= EmptySquare) return;\r
\r
+ if(killX >= 0) toX = killX, toY = killY; // [HGM] lion: first to kill square\r
+\r
+again:\r
+\r
ScreenSquare(fromX, fromY, &start);\r
ScreenSquare(toX, toY, &finish);\r
\r
}\r
animInfo.pos = finish;\r
DrawPosition(FALSE, NULL);\r
+\r
+ if(toX != x || toY != y) { fromX = toX; fromY = toY; toX = x; toY = y; goto again; } // second leg\r
+\r
animInfo.piece = EmptySquare;\r
Explode(board, fromX, fromY, toX, toY);\r
}\r
LTEXT "Chessboard for Windows",400,25,15,121,8\r
LTEXT "Copyright 1991 Digital Equipment Corporation",201,6,34,\r
149,8\r
- LTEXT "Enhancements Copyright 1992-2013 Free Software Foundation",\r
+ LTEXT "Enhancements Copyright 1992-2014 Free Software Foundation",\r
OPT_TCtext1,6,45,121,17\r
CONTROL "",OPT_TCTime,"Static",SS_BLACKRECT,4,28,159,1\r
LTEXT "WinBoard 0.0.0",ABOUTBOX_Version,25,5,160,8\r
RTEXT "Chessboard for Windows",IDC_ChessBoard,196,154,80,8\r
LTEXT "Copyright 1991 Digital Equipment Corporation",201,4,168,\r
151,8\r
- LTEXT "Enhancements Copyright 1992-2013 Free Software Foundation",\r
+ LTEXT "Enhancements Copyright 1992-2014 Free Software Foundation",\r
OPT_TCtext1,4,179,126,17\r
CONTROL "",OPT_TCTime,"Static",SS_BLACKRECT,4,164,272,1\r
LTEXT "WinBoard 0.0.0",ABOUTBOX_Version,4,154,64,8\r
EDITTEXT IDC_GameListFilter,201,136,78,14,ES_AUTOHSCROLL\r
END\r
\r
-DLG_EditTags DIALOG DISCARDABLE 6, 18, 167, 140\r
+DLG_EditTags DIALOG DISCARDABLE 6, 18, 223, 140\r
STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME\r
CAPTION "Edit Tags"\r
FONT 8, "MS Sans Serif"\r
BEGIN\r
- PUSHBUTTON "OK",IDOK,58,122,50,14\r
- PUSHBUTTON "Cancel",OPT_TagsCancel,114,122,50,14\r
+ PUSHBUTTON "OK",IDOK,114,122,50,14\r
+ PUSHBUTTON "Cancel",OPT_TagsCancel,170,122,50,14\r
+ PUSHBUTTON "Save",OPT_TagsSave,58,122,50,14\r
CONTROL "",OPT_TagsText,"RICHEDIT",ES_MULTILINE | ES_AUTOVSCROLL | \r
ES_AUTOHSCROLL | ES_WANTRETURN | WS_BORDER | WS_VSCROLL | \r
- WS_HSCROLL | WS_TABSTOP,2,2,162,115\r
+ WS_HSCROLL | WS_TABSTOP,2,2,218,115\r
PUSHBUTTON "&Edit",OPT_EditTags,2,122,50,14\r
END\r
\r
PUSHBUTTON "Cancel",IDCANCEL,208,86,50,14\r
END\r
\r
-DLG_GeneralOptions DIALOG DISCARDABLE 0, 0, 300, 197\r
+DLG_GeneralOptions DIALOG DISCARDABLE 0, 0, 300, 211\r
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
CAPTION "General Options"\r
FONT 8, "MS Sans Serif"\r
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,160,151,10\r
CONTROL "One-Click Move",OPT_SmartMove,\r
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,156,160,151,10\r
- DEFPUSHBUTTON "OK",IDOK,180,178,50,14\r
- PUSHBUTTON "Cancel",IDCANCEL,236,178,50,14\r
+ CONTROL "auto-Display Tags",OPT_AutoTags,\r
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,174,151,10\r
+ CONTROL "auto-Display Comment",OPT_AutoComment,\r
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,156,174,151,10\r
+ DEFPUSHBUTTON "OK",IDOK,180,192,50,14\r
+ PUSHBUTTON "Cancel",IDCANCEL,236,192,50,14\r
END\r
\r
DLG_IcsOptions DIALOGEX 0, 0, 302, 268\r
70,10\r
CONTROL "&atomic",OPT_VariantAtomic,"Button",BS_AUTORADIOBUTTON,\r
9,104,70,10\r
+ CONTROL "&Mighty Lion",OPT_VariantLion,"Button",BS_AUTORADIOBUTTON,\r
+ 9,114,70,10\r
CONTROL "cra&zyhouse",OPT_VariantCrazyhouse,"Button",BS_AUTORADIOBUTTON,80,14,\r
70,10\r
CONTROL "&bughouse",OPT_VariantBughouse,"Button",BS_AUTORADIOBUTTON,80,24,70,\r
94,70,10\r
CONTROL "&makruk",OPT_VariantMakruk,"Button",BS_AUTORADIOBUTTON,80,\r
104,70,10\r
+ CONTROL "&ASEAN",OPT_VariantASEAN,"Button",BS_AUTORADIOBUTTON,80,\r
+ 114,70,10\r
CONTROL "&gothic",OPT_VariantGothic,"Button",BS_AUTORADIOBUTTON,154,14,\r
70,10\r
CONTROL "&capablanca",OPT_VariantCapablanca,"Button",BS_AUTORADIOBUTTON,154,\r
10\r
CONTROL "&xiangqi",OPT_VariantXiangqi,"Button",BS_AUTORADIOBUTTON,154,114,70,\r
10\r
- GROUPBOX "Variant",GPB_Variant,4,4,215,125\r
- LTEXT "Board size:",GPB_Board,10,165,40,8,WS_TABSTOP\r
- LTEXT "ranks",IDC_Height,77,165,38,8\r
- EDITTEXT IDC_Ranks,60,161,14,14,ES_AUTOHSCROLL\r
- LTEXT "files",IDC_Width,133,165,80,8\r
- EDITTEXT IDC_Files,116,161,14,14,ES_AUTOHSCROLL\r
- LTEXT "Holdings with room for:",IDC_Hand,10,183,90,8\r
- EDITTEXT IDC_Holdings,93,179,14,14,ES_AUTOHSCROLL\r
- LTEXT "pieces",IDC_Pieces,110,183,100,8\r
- LTEXT "('-1' means defaults for selected variant)",IDC_Def,10,201,210,8\r
+ CONTROL "",OPT_EngineVariant+0,"Button",BS_AUTORADIOBUTTON,9,134,70,10\r
+ CONTROL "",OPT_EngineVariant+1,"Button",BS_AUTORADIOBUTTON,80,134,70,10\r
+ CONTROL "",OPT_EngineVariant+2,"Button",BS_AUTORADIOBUTTON,154,134,70,10\r
+ CONTROL "",OPT_EngineVariant+3,"Button",BS_AUTORADIOBUTTON,9,144,70,10\r
+ CONTROL "",OPT_EngineVariant+4,"Button",BS_AUTORADIOBUTTON,80,144,70,10\r
+ CONTROL "",OPT_EngineVariant+5,"Button",BS_AUTORADIOBUTTON,154,144,70,10\r
+ CONTROL "",OPT_EngineVariant+6,"Button",BS_AUTORADIOBUTTON,9,154,70,10\r
+ CONTROL "",OPT_EngineVariant+7,"Button",BS_AUTORADIOBUTTON,80,154,70,10\r
+ CONTROL "",OPT_EngineVariant+8,"Button",BS_AUTORADIOBUTTON,154,154,70,10\r
+ GROUPBOX "Variant",GPB_Variant,4,4,215,165\r
+ LTEXT "Board size:",GPB_Board,10,183,40,8,WS_TABSTOP\r
+ LTEXT "ranks",IDC_Height,77,183,38,8\r
+ EDITTEXT IDC_Ranks,60,179,14,14,ES_AUTOHSCROLL\r
+ LTEXT "files",IDC_Width,133,183,80,8\r
+ EDITTEXT IDC_Files,116,179,14,14,ES_AUTOHSCROLL\r
+ LTEXT "Holdings with room for:",IDC_Hand,10,201,90,8\r
+ EDITTEXT IDC_Holdings,93,197,14,14,ES_AUTOHSCROLL\r
+ LTEXT "pieces",IDC_Pieces,110,201,100,8\r
+ LTEXT "('-1' means defaults for selected variant)",IDC_Def,10,217,210,8\r
DEFPUSHBUTTON "OK",IDOK,114,232,50,14\r
PUSHBUTTON "Cancel",IDCANCEL,170,232,50,14\r
END\r
S72O BITMAP MOVEABLE PURE "bitmaps/s72o.bmp"\r
L72O BITMAP MOVEABLE PURE "bitmaps/l72o.bmp"\r
DK72O BITMAP MOVEABLE PURE "bitmaps/dk72o.bmp"\r
+LN72O BITMAP MOVEABLE PURE "bitmaps/ln72o.bmp"\r
WP72O BITMAP MOVEABLE PURE "bitmaps/wp72o.bmp"\r
WN72O BITMAP MOVEABLE PURE "bitmaps/wn72o.bmp"\r
WL72O BITMAP MOVEABLE PURE "bitmaps/wl72o.bmp"\r
S72S BITMAP MOVEABLE PURE "bitmaps/s72s.bmp"\r
L72S BITMAP MOVEABLE PURE "bitmaps/l72s.bmp"\r
DK72S BITMAP MOVEABLE PURE "bitmaps/dk72s.bmp"\r
+LN72S BITMAP MOVEABLE PURE "bitmaps/ln72s.bmp"\r
WP72S BITMAP MOVEABLE PURE "bitmaps/wp72s.bmp"\r
WN72S BITMAP MOVEABLE PURE "bitmaps/wn72s.bmp"\r
WL72S BITMAP MOVEABLE PURE "bitmaps/wl72s.bmp"\r
S72W BITMAP MOVEABLE PURE "bitmaps/s72w.bmp"\r
L72W BITMAP MOVEABLE PURE "bitmaps/l72w.bmp"\r
DK72W BITMAP MOVEABLE PURE "bitmaps/dk72w.bmp"\r
+LN72W BITMAP MOVEABLE PURE "bitmaps/ln72w.bmp"\r
E49O BITMAP MOVEABLE PURE "bitmaps/e49o.bmp"\r
A49O BITMAP MOVEABLE PURE "bitmaps/a49o.bmp"\r
AA49O BITMAP MOVEABLE PURE "bitmaps/as49o.bmp"\r
S49O BITMAP MOVEABLE PURE "bitmaps/s49o.bmp"\r
L49O BITMAP MOVEABLE PURE "bitmaps/l49o.bmp"\r
DK49O BITMAP MOVEABLE PURE "bitmaps/dk49o.bmp"\r
+LN49O BITMAP MOVEABLE PURE "bitmaps/ln49o.bmp"\r
WP49O BITMAP MOVEABLE PURE "bitmaps/wp49o.bmp"\r
WN49O BITMAP MOVEABLE PURE "bitmaps/wn49o.bmp"\r
WL49O BITMAP MOVEABLE PURE "bitmaps/wl49o.bmp"\r
S49S BITMAP MOVEABLE PURE "bitmaps/s49s.bmp"\r
L49S BITMAP MOVEABLE PURE "bitmaps/l49s.bmp"\r
DK49S BITMAP MOVEABLE PURE "bitmaps/dk49s.bmp"\r
+LN49S BITMAP MOVEABLE PURE "bitmaps/ln49s.bmp"\r
WP49S BITMAP MOVEABLE PURE "bitmaps/wp49s.bmp"\r
WN49S BITMAP MOVEABLE PURE "bitmaps/wn49s.bmp"\r
WL49S BITMAP MOVEABLE PURE "bitmaps/wl49s.bmp"\r
S49W BITMAP MOVEABLE PURE "bitmaps/s49w.bmp"\r
L49W BITMAP MOVEABLE PURE "bitmaps/l49w.bmp"\r
DK49W BITMAP MOVEABLE PURE "bitmaps/dk49w.bmp"\r
+LN49W BITMAP MOVEABLE PURE "bitmaps/ln49w.bmp"\r
A33O BITMAP MOVEABLE PURE "bitmaps/a33o.bmp"\r
AA33O BITMAP MOVEABLE PURE "bitmaps/as33o.bmp"\r
C33O BITMAP MOVEABLE PURE "bitmaps/c33o.bmp"\r
M33O BITMAP MOVEABLE PURE "bitmaps/m33o.bmp"\r
O33O BITMAP MOVEABLE PURE "bitmaps/o33o.bmp"\r
DK33O BITMAP MOVEABLE PURE "bitmaps/dk33o.bmp"\r
+LN33O BITMAP MOVEABLE PURE "bitmaps/ln33o.bmp"\r
WP33O BITMAP MOVEABLE PURE "bitmaps/wp33o.bmp"\r
WN33O BITMAP MOVEABLE PURE "bitmaps/wn33o.bmp"\r
WL33O BITMAP MOVEABLE PURE "bitmaps/wl33o.bmp"\r
M33W BITMAP MOVEABLE PURE "bitmaps/m33w.bmp"\r
O33W BITMAP MOVEABLE PURE "bitmaps/o33w.bmp"\r
DK33W BITMAP MOVEABLE PURE "bitmaps/dk33w.bmp"\r
+LN33W BITMAP MOVEABLE PURE "bitmaps/ln33w.bmp"\r
A33S BITMAP MOVEABLE PURE "bitmaps/a33s.bmp"\r
AA33S BITMAP MOVEABLE PURE "bitmaps/as33s.bmp"\r
C33S BITMAP MOVEABLE PURE "bitmaps/c33s.bmp"\r
M33S BITMAP MOVEABLE PURE "bitmaps/m33s.bmp"\r
O33S BITMAP MOVEABLE PURE "bitmaps/o33s.bmp"\r
DK33S BITMAP MOVEABLE PURE "bitmaps/dk33s.bmp"\r
+LN33S BITMAP MOVEABLE PURE "bitmaps/ln33s.bmp"\r
WP33S BITMAP MOVEABLE PURE "bitmaps/wp33s.bmp"\r
WN33S BITMAP MOVEABLE PURE "bitmaps/wn33s.bmp"\r
WL33S BITMAP MOVEABLE PURE "bitmaps/wl33s.bmp"\r
TELL WAVE DISCARDABLE "sounds/tell.wav"\r
UNFINISHED WAVE DISCARDABLE "sounds/unfinished.wav"\r
WIN WAVE DISCARDABLE "sounds/win.wav"\r
+ROAR WAVE DISCARDABLE "sounds/roar.wav"\r
\r
/////////////////////////////////////////////////////////////////////////////\r
//\r
/*\r
* woptions.c -- Options dialog box routines for WinBoard\r
*\r
- * Copyright 2000, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.\r
+ * Copyright 2000, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.\r
*\r
* Enhancements Copyright 2005 Alessandro Scotti\r
*\r
CHECK_BOX(OPT_HighlightMoveArrow, appData.highlightMoveWithArrow);\r
CHECK_BOX(OPT_AutoLogo, appData.autoLogo); // [HGM] logo\r
CHECK_BOX(OPT_SmartMove, appData.oneClick); // [HGM] one-click\r
+ CHECK_BOX(OPT_AutoTags, appData.autoDisplayTags); // [HGM]\r
+ CHECK_BOX(OPT_AutoComment, appData.autoDisplayComment); // [HGM]\r
\r
#undef CHECK_BOX\r
\r
appData.highlightMoveWithArrow=IS_CHECKED(OPT_HighlightMoveArrow);\r
appData.autoLogo =IS_CHECKED(OPT_AutoLogo); // [HGM] logo\r
appData.oneClick =IS_CHECKED(OPT_SmartMove); // [HGM] one-click\r
+ appData.autoDisplayTags =IS_CHECKED(OPT_AutoTags); // [HGM]\r
+ appData.autoDisplayComment =IS_CHECKED(OPT_AutoComment); // [HGM]\r
\r
#undef IS_CHECKED\r
\r
}\r
DeleteObject(pieces[0]);\r
DeleteObject(pieces[1]);\r
+\r
DeleteObject(pieces[2]);\r
return TRUE;\r
\r
-1,\r
-1,\r
OPT_VariantShogi,\r
+ -1, // Chu\r
OPT_VariantXiangqi,\r
OPT_VariantCourier,\r
OPT_VariantGothic,\r
OPT_VariantGreat,\r
-1, // Twilight,\r
OPT_VariantMakruk,\r
+ OPT_VariantASEAN,\r
OPT_VariantSChess,\r
OPT_VariantGrand,\r
OPT_VariantSpartan, // Spartan\r
+ OPT_VariantLion,\r
-2 // sentinel\r
};\r
\r
VariantWhichRadio(HWND hDlg)\r
{\r
int i=0, j;\r
+ *engineVariant = NULLCHAR;\r
while((j = radioButton[i++]) != -2) {\r
if(j == -1) continue; // no menu button\r
if(IsDlgButtonChecked(hDlg, j) &&\r
(appData.noChessProgram || strstr(first.variants, VariantName(i-1)))) return (VariantClass) i-1;\r
}\r
+ for(i=0; i<9; i++) { // check for engine-defined variants\r
+ if(IsDlgButtonChecked(hDlg, OPT_EngineVariant+i) ) {\r
+ GetDlgItemText(hDlg, OPT_EngineVariant+i, engineVariant, MSG_SIZ); // remember name, so we can resolve it later\r
+ return VariantUnknown;\r
+ }\r
+ }\r
return gameInfo.variant; // If no button checked, keep old\r
}\r
\r
void\r
VariantShowRadio(HWND hDlg)\r
{\r
+ char c = *engineVariant;\r
int i=0, j;\r
CheckDlgButton(hDlg, radioButton[gameInfo.variant], TRUE);\r
+ *engineVariant = NULLCHAR; // [HGM] kludge to prevent VariantName will always return engineVariant\r
while((j = radioButton[i++]) != -2) {\r
if(j == -1) continue; // no menu button\r
EnableWindow(GetDlgItem(hDlg, j), appData.noChessProgram || strstr(first.variants, VariantName(i-1)));\r
}\r
+ *engineVariant = c;\r
+ for(i=0; i<9; i++) { // initialize engine-defined variants\r
+ char *v = EngineDefinedVariant(&first, i); // get name of #i\r
+ if(v) { // there is such a variant\r
+ EnableWindow(GetDlgItem(hDlg, OPT_EngineVariant+i), TRUE); // and enable the button\r
+ SetDlgItemText(hDlg, OPT_EngineVariant+i, v); // put its name on button\r
+ } else EnableWindow(GetDlgItem(hDlg, OPT_EngineVariant+i), FALSE); // no such variant; disable button\r
+ }\r
}\r
\r
LRESULT CALLBACK\r
UpdateSampleText(hDlg, OPT_SampleSeek, &mca[ColorSeek]);\r
break;\r
\r
+\r
+\r
+\r
case OPT_ChooseNormalColor:\r
ColorizeTextPopup(hDlg, ColorNormal);\r
UpdateSampleText(hDlg, OPT_SampleNormal, &mca[ColorNormal]);\r
SoundComboData soundComboData[] = {\r
{N_("Move"), NULL},\r
{N_("Bell"), NULL},\r
+ {N_("Roar"), NULL},\r
{N_("ICS Alarm"), NULL},\r
{N_("ICS Win"), NULL},\r
{N_("ICS Loss"), NULL},\r
return result;\r
}\r
\r
+int\r
+IsMultiFormat(char *s)\r
+{\r
+ char *p = strchr(s, ':');\r
+ return p && p != s+1;\r
+}\r
+\r
LRESULT CALLBACK UciOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
{\r
char buf[MAX_PATH];\r
/* Initialize the dialog items */\r
SetDlgItemText( hDlg, IDC_PolyglotDir, appData.polyglotDir );\r
SetDlgItemInt( hDlg, IDC_HashSize, appData.defaultHashSize, TRUE );\r
+ if(appData.defaultPathEGTB[0])\r
SetDlgItemText( hDlg, IDC_PathToEGTB, appData.defaultPathEGTB );\r
+ else\r
+ SetDlgItemText( hDlg, IDC_PathToEGTB, appData.egtFormats );\r
SetDlgItemInt( hDlg, IDC_SizeOfEGTB, appData.defaultCacheSizeEGTB, TRUE );\r
CheckDlgButton( hDlg, IDC_UseBook, (BOOL) appData.usePolyglotBook );\r
SetDlgItemText( hDlg, IDC_BookFile, appData.polyglotBook );\r
appData.defaultHashSize = GetDlgItemInt(hDlg, IDC_HashSize, NULL, FALSE );\r
appData.defaultCacheSizeEGTB = GetDlgItemInt(hDlg, IDC_SizeOfEGTB, NULL, FALSE );\r
GetDlgItemText( hDlg, IDC_PathToEGTB, buf, sizeof(buf) );\r
- appData.defaultPathEGTB = strdup(buf);\r
+ if(IsMultiFormat(buf)) {\r
+ ASSIGN(appData.egtFormats, buf);\r
+ } else {\r
+ ASSIGN(appData.defaultPathEGTB, buf);\r
+ }\r
GetDlgItemText( hDlg, IDC_BookFile, buf, sizeof(buf) );\r
appData.polyglotBook = strdup(buf);\r
appData.usePolyglotBook = (Boolean) IsDlgButtonChecked( hDlg, IDC_UseBook );\r
/*\r
+ * woptions.h -- Options dialog box routines for WinBoard\r
+ *\r
+ * Copyright 2003, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.\r
+ *\r
+ * ------------------------------------------------------------------------\r
+ *\r
+ * GNU XBoard is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or (at\r
+ * your option) any later version.\r
+ *\r
+ * GNU XBoard is distributed in the hope that it will be useful, but\r
+ * WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ * General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program. If not, see http://www.gnu.org/licenses/. *\r
+ *\r
+ *------------------------------------------------------------------------\r
+ ** See the file ChangeLog for a revision history. */\r
+ \r
+ /*\r
* Engine-settings dialog. The complexity come from an attempt to present the engine-defined options\r
* in a nicey formatted layout. To this end we first run a back-end pre-formatter, which will distribute\r
* the controls over two columns (the minimum required, as some are double width). It also takes care of\r
if(j == -2) {\r
char filter[] =\r
"All files\0*.*\0Game files\0*.pgn;*.gam\0Position files\0*.fen;*.epd;*.pos\0"\r
- "EXE files\0*.exe\0Tournament files (*.trn)\0*.trn\0"\r
+ "EXE files\0*.exe;*.jar\0Tournament files (*.trn)\0*.trn\0"\r
"BIN Files\0*.bin\0LOG Files\0*.log\0INI Files\0*.ini\0"\r
"Image files\0*.bmp\0\0";\r
OPENFILENAME ofn;\r
{ 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("or specify one below:") },\r
{ 0, 0, 0, NULL, (void*) &nickName, NULL, NULL, TextBox, N_("Nickname (optional):") },\r
{ 0, 0, 0, NULL, (void*) &useNick, NULL, NULL, CheckBox, N_("Use nickname in PGN tag") },\r
- { 0, 0, 32+3, NULL, (void*) &engineName, NULL, NULL, FileName, N_("Engine (*.exe):") },\r
+ { 0, 0, 32+3, NULL, (void*) &engineName, NULL, NULL, FileName, N_("Engine (.exe or .jar):") },\r
{ 0, 0, 0, NULL, (void*) ¶ms, NULL, NULL, TextBox, N_("command-line parameters:") },\r
{ 0, 0, 0, NULL, (void*) &wbOptions, NULL, NULL, TextBox, N_("Special WinBoard options:") },\r
{ 0, 0, 0, NULL, (void*) &engineDir, NULL, NULL, PathName, N_("directory:") },\r
* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* The following terms apply to Digital Equipment Corporation's copyright
* interest in XBoard:
// [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
#include "common.h"
-#if HAVE_LIBXPM
-#include <X11/xpm.h>
-#define IMAGE_EXT "xpm"
-#else
-#define IMAGE_EXT "xim"
-#endif
-
#include "bitmaps/icon_white.bm"
#include "bitmaps/icon_black.bm"
#include "bitmaps/checkmark.bm"
/* Max possible square size */
#define MAXSQSIZE 256
-static int xpm_avail[MAXSQSIZE];
-
-#ifdef HAVE_DIR_STRUCT
-
-/* Extract piece size from filename */
-static int
-xpm_getsize (char *name, int len, char *ext)
-{
- char *p, *d;
- char buf[10];
-
- if (len < 4)
- return 0;
-
- if ((p=strchr(name, '.')) == NULL ||
- StrCaseCmp(p+1, ext) != 0)
- return 0;
-
- p = name + 3;
- d = buf;
-
- while (*p && isdigit(*p))
- *(d++) = *(p++);
-
- *d = 0;
- return atoi(buf);
-}
-
-/* Setup xpm_avail */
-static int
-xpm_getavail (char *dirname, char *ext)
-{
- DIR *dir;
- struct dirent *ent;
- int i;
-
- for (i=0; i<MAXSQSIZE; ++i)
- xpm_avail[i] = 0;
-
- if (appData.debugMode)
- fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
-
- dir = opendir(dirname);
- if (!dir)
- {
- fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
- programName, dirname);
- exit(1);
- }
-
- while ((ent=readdir(dir)) != NULL) {
- i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
- if (i > 0 && i < MAXSQSIZE)
- xpm_avail[i] = 1;
- }
-
- closedir(dir);
-
- return 0;
-}
-
-void
-xpm_print_avail (FILE *fp, char *ext)
-{
- int i;
-
- fprintf(fp, _("Available `%s' sizes:\n"), ext);
- for (i=1; i<MAXSQSIZE; ++i) {
- if (xpm_avail[i])
- printf("%d\n", i);
- }
-}
-
-/* Return XPM piecesize closest to size */
-int
-xpm_closest_to (char *dirname, int size, char *ext)
-{
- int i;
- int sm_diff = MAXSQSIZE;
- int sm_index = 0;
- int diff;
-
- xpm_getavail(dirname, ext);
-
- if (appData.debugMode)
- xpm_print_avail(stderr, ext);
-
- for (i=1; i<MAXSQSIZE; ++i) {
- if (xpm_avail[i]) {
- diff = size - i;
- diff = (diff<0) ? -diff : diff;
- if (diff < sm_diff) {
- sm_diff = diff;
- sm_index = i;
- }
- }
- }
-
- if (!sm_index) {
- fprintf(stderr, _("Error: No `%s' files!\n"), ext);
- exit(1);
- }
-
- return sm_index;
-}
-#else /* !HAVE_DIR_STRUCT */
-/* If we are on a system without a DIR struct, we can't
- read the directory, so we can't collect a list of
- filenames, etc., so we can't do any size-fitting. */
-int
-xpm_closest_to (char *dirname, int size, char *ext)
-{
- fprintf(stderr, _("\
-Warning: No DIR structure found on this system --\n\
- Unable to autosize for XPM/XIM pieces.\n\
- Please report this error to %s.\n\
- Include system type & operating system in message.\n"), PACKAGE_BUGREPORT););
- return size;
-}
-#endif /* HAVE_DIR_STRUCT */
-
-
/* Arrange to catch delete-window events */
Atom wm_delete_window;
void
case ArgTwo:
case ArgNone:
case ArgCommSettings:
+ case ArgMaster:
+ case ArgInstall:
break;
}
return p;
debugFP = stderr;
if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
- printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+ printf("%s version %s\n\n configure options: %s\n", PACKAGE_NAME, PACKAGE_VERSION, CONFIGURE_OPTIONS);
exit(0);
}
*
* Copyright 2005 Alessandro Scotti
*
- * Enhancements Copyright 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * Enhancements Copyright 2009, 2010, 2011, 2012, 2013,
+ * 2014 Free Software Foundation, Inc.
*
* ------------------------------------------------------------------------
*
# define N_(s) s
#endif
-#include <X11/xpm.h>
+// [HGM] bitmaps of some ICONS used in the engine-outut window
+
+static unsigned char CLEAR_14[28];
+
+static unsigned char WHITE_14[] = {
+0xe0, 0x01, 0x18, 0x06, 0x04, 0x08, 0x02, 0x10, 0x02, 0x10, 0x01, 0x20, 0x01, 0x20,
+0x01, 0x20, 0x01, 0x20, 0x02, 0x10, 0x02, 0x10, 0x04, 0x08, 0x18, 0x06, 0xe0, 0x01
+};
+
+static unsigned char BLACK_14[] = {
+0xe0, 0x01, 0xf8, 0x07, 0xfc, 0x0f, 0xfe, 0x1f, 0xfe, 0x1f, 0xff, 0x3f, 0xff, 0x3f,
+0xff, 0x3f, 0xff, 0x3f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfc, 0x0f, 0xf8, 0x07, 0xe0, 0x01
+};
+
+static unsigned char ANALYZE_14[] = {
+0x80, 0x03, 0x60, 0x0c, 0x10, 0x10, 0x90, 0x10, 0xc8, 0x20, 0x08, 0x20, 0x08, 0x20,
+0x10, 0x10, 0x10, 0x10, 0x68, 0x0c, 0x94, 0x03, 0x0a, 0x00, 0x07, 0x00, 0x00, 0x00
+};
+
+static unsigned char THINK_14[] = {
+0xe0, 0x00, 0x18, 0x03, 0x44, 0x04, 0x42, 0x08, 0x42, 0x08, 0x41, 0x10, 0xe1, 0x13,
+0x41, 0x10, 0x02, 0x08, 0x02, 0x08, 0x04, 0x04, 0x18, 0x03, 0xe0, 0x00, 0x00, 0x00
+};
+
+static unsigned char PONDER_14[] = {
+0x30, 0x03, 0x8c, 0x0c, 0x02, 0x10, 0x01, 0x08, 0x01, 0x10, 0x06, 0x20, 0x04, 0x20,
+0x02, 0x10, 0x04, 0x0c, 0xc8, 0x04, 0x34, 0x03, 0x0e, 0x00, 0x01, 0x00, 0x00, 0x00
+};
+
+static unsigned char UNKNOWN_14[] = {
+0xe0, 0x01, 0x58, 0x07, 0xac, 0x0a, 0x56, 0x15, 0xaa, 0x1a, 0x55, 0x35, 0xab, 0x2a,
+0x55, 0x35, 0xab, 0x2a, 0x56, 0x15, 0xaa, 0x1a, 0x54, 0x0d, 0xb8, 0x06, 0xe0, 0x01
+};
-// [HGM] pixmaps of some ICONS used in the engine-outut window
-#include "pixmaps/WHITE_14.xpm"
-#include "pixmaps/BLACK_14.xpm"
-#include "pixmaps/CLEAR_14.xpm"
-#include "pixmaps/UNKNOWN_14.xpm"
-#include "pixmaps/THINKING_14.xpm"
-#include "pixmaps/PONDER_14.xpm"
-#include "pixmaps/ANALYZING_14.xpm"
/* Module variables */
static void
-ReadIcon (char *pixData[], int iconNr, Widget w)
+ReadIcon (unsigned char pixData[], int iconNr, Widget w)
{
- int r;
-
- if ((r=XpmCreatePixmapFromData(xDisplay, XtWindow(w),
- pixData,
- &(icons[iconNr]),
- NULL, NULL /*&attr*/)) != 0) {
- fprintf(stderr, _("Error %d loading icon image\n"), r);
- exit(1);
- }
+ icons[iconNr] = XCreateBitmapFromData(xDisplay, XtWindow(w), (char*) pixData, 14, 14);
}
void
/*
* xoptions.c -- Move list window, part of X front end for XBoard
*
- * Copyright 2000, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * Copyright 2000, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
* ------------------------------------------------------------------------
*
* GNU XBoard is free software: you can redistribute it and/or modify
} else texts[h] = dialog = NULL; // kludge to position from left margin
w = option[i].type == Spin || option[i].type == Fractional ? 70 : option[i].max ? option[i].max : 205;
if(option[i].type == FileName || option[i].type == PathName) w -= 55;
+ if(squareSize > 33) w += (squareSize - 33)/2;
j = SetPositionAndSize(args, dialog, last, 1 /* border */,
w /* w */, option[i].type == TextBox ? option[i].value : 0 /* h */, 0x91 /* chain full width */);
if(option[i].type == TextBox) { // decorations for multi-line text-edits
XtAddCallback(b_ok, XtNcallback, GenericCallback, (XtPointer)(intptr_t) (30001 + (dlgNr<<16)));
if(!(option[i].min & NO_CANCEL)) {
XtSetArg(args[1], XtNfromHoriz, b_ok); // overwrites!
- b_cancel = XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
+ b_cancel = XtCreateManagedWidget(_("Cancel"), commandWidgetClass, form, args, j);
XtAddCallback(b_cancel, XtNcallback, GenericCallback, (XtPointer)(intptr_t) (30000 + (dlgNr<<16)));
}
}
+ /*
+ * xboard2.h -- Move list window, part of X front end for XBoard
+ *
+ * Copyright 2012, 2013, 2014 Free Software Foundation, Inc.
+ * ------------------------------------------------------------------------
+ *
+ * GNU XBoard is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU XBoard is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/. *
+ *
+ *------------------------------------------------------------------------
+ ** See the file ChangeLog for a revision history. */
+
void SendToProgram P((char *message, ChessProgramState *cps));
void SendToICS P((char *buf));
void InitDrawingSizes P((int i, int j));
extern int squareSize, lineGap, defaultLineGap;
extern int startedFromPositionFile;
extern char *icsTextMenuString;
-
+extern int hi2X, hi2Y;