From: Arun Persaud Date: Sun, 6 Mar 2016 00:32:37 +0000 (-0800) Subject: Merge branch 'v4.8.x' X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=ebd7f78161504e46896f7d96bb41e29714b2fd53;hp=0278ebc80411a20fd23303156285e55ce8d2b0a5;p=xboard.git Merge branch 'v4.8.x' --- diff --git a/Makefile.am b/Makefile.am index 7378e7c..f202a12 100644 --- a/Makefile.am +++ b/Makefile.am @@ -145,6 +145,27 @@ dist_svg_DATA = svg/icon_white.svg svg/icon_black.svg \ svg/BlackHCrown.svg svg/WhiteHCrown.svg \ svg/BlackDolphin.svg svg/WhiteDolphin.svg \ svg/BlackClaw.svg svg/WhiteClaw.svg \ + svg/BlackWolf.svg svg/WhiteWolf.svg \ + svg/BlackCamel.svg svg/WhiteCamel.svg \ + svg/BlackZebra.svg svg/WhiteZebra.svg \ + svg/BlackGnu.svg svg/WhiteGnu.svg \ + svg/BlackWizard.svg svg/WhiteWizard.svg \ + svg/BlackViking.svg svg/WhiteViking.svg \ + svg/BlackIron.svg svg/WhiteIron.svg \ + svg/BlackCopper.svg svg/WhiteCopper.svg \ + svg/BlackTower.svg svg/WhiteTower.svg \ + svg/BlackDragon.svg svg/WhiteDragon.svg \ + svg/BlackCub.svg svg/WhiteCub.svg \ + svg/BlackButterfly.svg svg/WhiteButterfly.svg \ + svg/BlackLeft.svg svg/WhiteLeft.svg \ + svg/BlackRight.svg svg/WhiteRight.svg \ + svg/BlackHat.svg svg/WhiteHat.svg \ + svg/BlackRShield.svg svg/WhiteRShield.svg \ + svg/BlackLShield.svg svg/WhiteLShield.svg \ + svg/BlackAxe.svg svg/WhiteAxe.svg \ + svg/BlackFlag.svg svg/WhiteFlag.svg \ + svg/BlackDuck.svg svg/WhiteDuck.svg \ + svg/BlackPegasus.svg svg/WhitePegasus.svg \ svg/eo_Analyzing.svg svg/eo_Black.svg \ svg/eo_Clear.svg svg/eo_Ponder.svg \ svg/eo_Thinking.svg svg/eo_Unknown.svg \ diff --git a/args.h b/args.h index 0cd2226..56d9916 100644 --- a/args.h +++ b/args.h @@ -517,6 +517,7 @@ ArgDescriptor argDescriptors[] = { { "themeNames", ArgString, (void *) &appData.themeNames, TRUE, (ArgIniType) "native -upf false -ub false -ubt false -pid \"\"\n" }, { "addMasterOption", ArgMaster, NULL, FALSE, INVALID }, { "installEngine", ArgInstall, (void *) &firstChessProgramNames, FALSE, (ArgIniType) "" }, + { "installTheme", ArgInstall, (void *) &appData.themeNames, FALSE, (ArgIniType) "" }, { "initialMode", ArgString, (void *) &appData.initialMode, FALSE, (ArgIniType) "" }, { "mode", ArgString, (void *) &appData.initialMode, FALSE, INVALID }, { "variant", ArgString, (void *) &appData.variant, FALSE, (ArgIniType) "normal" }, @@ -610,7 +611,8 @@ ArgDescriptor argDescriptors[] = { { "ub", ArgBoolean, (void *) &appData.useBorder, FALSE, INVALID }, { "border", ArgFilename, (void *) &appData.border, TRUE, (ArgIniType) "" }, { "finger", ArgFilename, (void *) &appData.finger, FALSE, (ArgIniType) "" }, - { "inscriptions", ArgString, (void *) &appData.inscriptions, XBOARD, (ArgIniType) "" }, + { "epd", ArgTrue, (void *) &appData.epd, FALSE, INVALID }, + { "inscriptions", ArgString, (void *) &appData.inscriptions, FALSE, (ArgIniType) "" }, { "autoInstall", ArgString, (void *) &appData.autoInstall, XBOARD, (ArgIniType) "" }, { "fixedSize", ArgBoolean, (void *) &appData.fixedSize, TRUE, (ArgIniType) FALSE }, diff --git a/backend.c b/backend.c index 1b16f75..f2fc3f3 100644 --- a/backend.c +++ b/backend.c @@ -193,7 +193,6 @@ void GameEnds P((ChessMove result, char *resultDetails, int whosays)); void EditPositionDone P((Boolean fakeRights)); void PrintOpponents P((FILE *fp)); void PrintPosition P((FILE *fp, int move)); -void StartChessProgram P((ChessProgramState *cps)); void SendToProgram P((char *message, ChessProgramState *cps)); void SendMoveToProgram P((int moveNum, ChessProgramState *cps)); void ReceiveFromProgram P((InputSourceRef isr, VOIDSTAR closure, @@ -297,6 +296,8 @@ int promoDefaultAltered; int keepInfo = 0; /* [HGM] to protect PGN tags in auto-step game analysis */ static int initPing = -1; int border; /* [HGM] width of board rim, needed to size seek graph */ +char bestMove[MSG_SIZ]; +int solvingTime, totalTime; /* States for ics_getting_history */ #define H_FALSE 0 @@ -442,6 +443,7 @@ char *currentDebugFile; // [HGM] debug split: to remember name char cmailMove[CMAIL_MAX_GAMES][MOVE_LEN], cmailMsg[MSG_SIZ]; char bookOutput[MSG_SIZ*10], thinkOutput[MSG_SIZ*10], lastHint[MSG_SIZ]; char thinkOutput1[MSG_SIZ*10]; +char promoRestrict[MSG_SIZ]; ChessProgramState first, second, pairing; @@ -514,7 +516,7 @@ AppData appData; Board boards[MAX_MOVES]; /* [HGM] Following 7 needed for accurate legality tests: */ signed char castlingRank[BOARD_FILES]; // and corresponding ranks -signed char initialRights[BOARD_FILES]; +unsigned char initialRights[BOARD_FILES]; int nrCastlingRights; // For TwoKings, or to implement castling-unknown status int initialRulePlies, FENrulePlies; FILE *serverMoves = NULL; // next two for broadcasting (/serverMoves option) @@ -1739,6 +1741,7 @@ InitBackEnd3 P((void)) if(!blackPlaysFirst) { startedFromPositionFile = TRUE; CopyBoard(filePosition, boards[0]); + CopyBoard(initialPosition, boards[0]); } } if (initialMode == AnalyzeMode) { @@ -2126,7 +2129,7 @@ StringToVariant (char *e) } else for (i=0; i= VariantShogi && (p != e || isalpha(p[strlen(variantNames[i])]))) continue; + if(p && i >= VariantShogi && (p != e && !appData.icsActive || isalpha(p[strlen(variantNames[i])]))) continue; v = (VariantClass) i; found = TRUE; break; @@ -4160,6 +4163,7 @@ read_from_ics (InputSourceRef isr, VOIDSTAR closure, char *data, int count, int fprintf(debugFP, "Sending premove:\n"); SendToICS(str); } else if (gotPremove) { + int oldFMM = forwardMostMove; gotPremove = 0; ClearPremoveHighlights(); if (appData.debugMode) @@ -4167,6 +4171,13 @@ read_from_ics (InputSourceRef isr, VOIDSTAR closure, char *data, int count, int UserMoveEvent(premoveFromX, premoveFromY, premoveToX, premoveToY, premovePromoChar); + if(forwardMostMove == oldFMM) { // premove was rejected, highlight last opponent move + if(moveList[oldFMM-1][1] != '@') + SetHighlights(moveList[oldFMM-1][0]-AAA, moveList[oldFMM-1][1]-ONE, + moveList[oldFMM-1][2]-AAA, moveList[oldFMM-1][3]-ONE); + else // (drop) + SetHighlights(-1, -1, moveList[oldFMM-1][2]-AAA, moveList[oldFMM-1][3]-ONE); + } } } @@ -4887,13 +4898,13 @@ ParseBoard12 (char *string) if(fromY == DROP_RANK && k==toY && j==toX) continue; // dropped pieces always stand for themselves old = (k==toY && j==toX) ? boards[moveNum-1][fromY][fromX] : boards[moveNum-1][k][j]; // trace back mover if(old == new) continue; - if(old == PROMOTED new) boards[moveNum][k][j] = old; // prevent promoted pieces to revert to primordial ones + if(old == PROMOTED(new)) boards[moveNum][k][j] = old;// prevent promoted pieces to revert to primordial ones else if(new == WhiteWazir || new == BlackWazir) { if(old < WhiteCannon || old >= BlackPawn && old < BlackCannon) - boards[moveNum][k][j] = PROMOTED old; // choose correct type of Gold in promotion + boards[moveNum][k][j] = PROMOTED(old); // choose correct type of Gold in promotion else boards[moveNum][k][j] = old; // preserve type of Gold } else if((old == WhitePawn || old == BlackPawn) && new != EmptySquare) // Pawn promotions (but not e.p.capture!) - boards[moveNum][k][j] = PROMOTED new; // use non-primordial representation of chosen piece + boards[moveNum][k][j] = PROMOTED(new); // use non-primordial representation of chosen piece } } else { /* Move from ICS was illegal!? Punt. */ @@ -5143,16 +5154,18 @@ SendMoveToProgram (int moveNum, ChessProgramState *cps) } else if(moveList[moveNum][4] == ';') { // [HGM] lion: move is double-step over intermediate square char *m = moveList[moveNum]; + static char c[2]; + *c = m[7]; // promoChar if((boards[moveNum][m[6]-ONE][m[5]-AAA] < BlackPawn) == (boards[moveNum][m[1]-ONE][m[0]-AAA] < BlackPawn)) // move is kludge to indicate castling snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d\n", m[0], m[1] - '0', // convert to two moves m[2], m[3] - '0', m[5], m[6] - '0', m[2] + (m[0] > m[5] ? 1 : -1), m[3] - '0'); else - snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d\n", m[0], m[1] - '0', // convert to two moves + snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d%s\n", m[0], m[1] - '0', // convert to two moves m[5], m[6] - '0', m[5], m[6] - '0', - m[2], m[3] - '0'); + m[2], m[3] - '0', c); SendToProgram(buf, cps); } else if(BOARD_HEIGHT > 10) { // [HGM] big: convert ranks to double-digit where needed @@ -5335,7 +5348,7 @@ UploadGameEvent () SendToICS(ics_type == ICS_ICC ? "tag result Game in progress\n" : "commit\n"); } -int killX = -1, killY = -1, kill2X, kill2Y; // [HGM] lion: used for passing e.p. capture square to MakeMove +int killX = -1, killY = -1, kill2X = -1, kill2Y = -1; // [HGM] lion: used for passing e.p. capture square to MakeMove int legNr = 1; void @@ -5356,6 +5369,10 @@ CoordsToComputerAlgebraic (int rf, int ff, int rt, int ft, char promoChar, char } else { sprintf(move, "%c%c%c%c%c\n", AAA + ff, ONE + rf, AAA + ft, ONE + rt, promoChar); + if(killX >= 0 && killY >= 0) { + sprintf(move+4, ";%c%c\n", AAA + killX, ONE + killY); + if(kill2X >= 0 && kill2Y >= 0) sprintf(move+7, "%c%c%c\n", AAA + killX, ONE + killY, promoChar); + } } } } @@ -5378,12 +5395,22 @@ int dragging; static ClickType lastClickType; int +PieceInString (char *s, ChessSquare piece) +{ + char *p, ID = ToUpper(PieceToChar(piece)), suffix = PieceSuffix(piece); + while((p = strchr(s, ID))) { + if(!suffix || p[1] == suffix) return TRUE; + s = p; + } + return FALSE; +} + +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); + ChessSquare partner = promoPartner[*p]; if(PieceToChar(*p) != '+' && PieceToChar(partner) != '+') return 0; + if(PieceToChar(*p) == '+') partner = boards[currentMove][fromY][fromX]; *p = partner; return 1; } @@ -5406,8 +5433,10 @@ Sweep (int step) else if(promoSweep == BlackPawn && step < 0 && !toggleFlag) promoSweep = WhitePawn; else if(promoSweep == WhiteKing && step > 0 && !toggleFlag) promoSweep = BlackKing; if(!step) step = -1; - } while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || promoSweep == pawn || + } while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || !toggleFlag && PieceToChar(promoSweep) == '+' || // skip promoted versions of other + promoRestrict[0] ? !PieceInString(promoRestrict, promoSweep) : // if choice set available, use it + promoSweep == pawn || appData.testLegality && (promoSweep == king || gameInfo.variant != VariantChuChess && (promoSweep == WhiteLion || promoSweep == BlackLion))); if(toX >= 0) { @@ -5542,6 +5571,7 @@ ParseOneMove (char *move, int moveNum, ChessMove *moveType, int *fromX, int *fro *toX = currentMoveString[2] - AAA; *toY = currentMoveString[3] - ONE; *promoChar = currentMoveString[4]; + if(*promoChar == ';') *promoChar = currentMoveString[7]; if (*fromX < BOARD_LEFT || *fromX >= BOARD_RGHT || *fromY < 0 || *fromY >= BOARD_HEIGHT || *toX < BOARD_LEFT || *toX >= BOARD_RGHT || *toY < 0 || *toY >= BOARD_HEIGHT) { if (appData.debugMode) { @@ -5659,21 +5689,26 @@ ParsePV (char *pv, Boolean storeComments, Boolean atEnd) } int -MultiPV (ChessProgramState *cps) +MultiPV (ChessProgramState *cps, int kind) { // check if engine supports MultiPV, and if so, return the number of the option that sets it int i; - for(i=0; inrOptions; i++) - if(!strcmp(cps->option[i].name, "MultiPV") && cps->option[i].type == Spin) - return i; + for(i=0; inrOptions; i++) { + char *s = cps->option[i].name; + if((kind & 1) && !StrCaseCmp(s, "MultiPV") && cps->option[i].type == Spin) return i; + if((kind & 2) && StrCaseStr(s, "multi") && StrCaseStr(s, "PV") + && StrCaseStr(s, "margin") && cps->option[i].type == Spin) return -i-2; + } return -1; } Boolean extendGame; // signals to UnLoadPV() if walked part of PV has to be appended to game +static int multi, pv_margin; +static ChessProgramState *activeCps; Boolean LoadMultiPV (int x, int y, char *buf, int index, int *start, int *end, int pane) { - int startPV, multi, lineStart, origIndex = index; + int startPV, lineStart, origIndex = index; char *p, buf2[MSG_SIZ]; ChessProgramState *cps = (pane ? &second : &first); @@ -5687,14 +5722,22 @@ LoadMultiPV (int x, int y, char *buf, int index, int *start, int *end, int pane) do{ while(buf[index] && buf[index] != '\n') index++; } while(buf[index] == '\n' && buf[index+1] == '\\' && buf[index+2] == ' ' && index++); // join kibitzed PV continuation line buf[index] = 0; - if(lineStart == 0 && gameMode == AnalyzeMode && (multi = MultiPV(cps)) >= 0) { - int n = cps->option[multi].value; - if(origIndex > 17 && origIndex < 24) { if(n>1) n--; } else if(origIndex > index - 6) n++; + if(lineStart == 0 && gameMode == AnalyzeMode) { + int n = 0; + if(origIndex > 17 && origIndex < 24) n--; else if(origIndex > index - 6) n++; + if(n == 0) { // click not on "fewer" or "more" + if((multi = -2 - MultiPV(cps, 2)) >= 0) { + pv_margin = cps->option[multi].value; + activeCps = cps; // non-null signals margin adjustment + } + } else if((multi = MultiPV(cps, 1)) >= 0) { + n += cps->option[multi].value; if(n < 1) n = 1; snprintf(buf2, MSG_SIZ, "option MultiPV=%d\n", n); if(cps->option[multi].value != n) SendToProgram(buf2, cps); cps->option[multi].value = n; *start = *end = 0; return FALSE; + } } else if(strstr(buf+lineStart, "exclude:") == buf+lineStart) { // exclude moves clicked ExcludeClick(origIndex - lineStart); return FALSE; @@ -5742,6 +5785,16 @@ void UnLoadPV () { int oldFMM = forwardMostMove; // N.B.: this was currentMove before PV was loaded! + if(activeCps) { + if(pv_margin != activeCps->option[multi].value) { + char buf[MSG_SIZ]; + snprintf(buf, MSG_SIZ, "option %s=%d\n", "Multi-PV Margin", pv_margin); + SendToProgram(buf, activeCps); + activeCps->option[multi].value = pv_margin; + } + activeCps = NULL; + return; + } if(endPV < 0) return; if(appData.autoCopyPV) CopyFENToClipboard(); endPV = -1; @@ -5770,6 +5823,17 @@ MovePV (int x, int y, int h) { // step through PV based on mouse coordinates (called on mouse move) int margin = h>>3, step = 0, threshold = (pieceSweep == EmptySquare ? 10 : 15); + if(activeCps) { // adjusting engine's multi-pv margin + if(x > lastX) pv_margin++; else + if(x < lastX) pv_margin -= (pv_margin > 0); + if(x != lastX) { + char buf[MSG_SIZ]; + snprintf(buf, MSG_SIZ, "margin = %d", pv_margin); + DisplayMessage(buf, ""); + } + lastX = x; + return; + } // we must somehow check if right button is still down (might be released off board!) if(endPV < 0 && pieceSweep == EmptySquare) return; // needed in XBoard because lastX/Y is shared :-( if(abs(x - lastX) < threshold && abs(y - lastY) < threshold) return; @@ -5955,7 +6019,7 @@ ptclen (const char *s, char *escapes) { int n = 0; if(!*escapes) return strlen(s); - while(*s) n += (*s != ':' && !strchr(escapes, *s)), s++; + while(*s) n += (*s != '/' && *s != '-' && *s != '^' && *s != '*' && !strchr(escapes, *s)) - 2*(*s == '='), s++; return n; } @@ -5965,27 +6029,57 @@ SetCharTableEsc (unsigned char *table, const char * map, char * escapes) /* Basically a safe strcpy that uses the last character as King */ { int result = FALSE; int NrPieces; + unsigned char partner[EmptySquare]; if( map != NULL && (NrPieces=ptclen(map, escapes)) <= (int) EmptySquare && NrPieces >= 12 && !(NrPieces&1)) { - int i, j = 0; /* [HGM] Accept even length from 12 to 88 */ + int i, ii, offs, j = 0; /* [HGM] Accept even length from 12 to 88 */ for( i=0; i<(int) EmptySquare; i++ ) table[i] = '.'; - for( i=0; ialphaRank) { /* [HGM] shogi: translate coords */ message[1] = BOARD_RGHT - 1 - j + '1'; @@ -6422,12 +6516,12 @@ SendBoard (ChessProgramState *cps, int moveNum) && ((int) *bp >= (int) BlackPawn)) { if(j == BOARD_LEFT-2) snprintf(message, MSG_SIZ, "%c@%d\n", ToUpper(PieceToChar(*bp)), bp[1]); - else snprintf(message,MSG_SIZ, "%c%c%c\n", ToUpper(PieceToChar(*bp)), - AAA + j, ONE + i); + else snprintf(message,MSG_SIZ, "%c%c%d\n", ToUpper(PieceToChar(*bp)), + AAA + j, ONE + i - '0'); if(message[0] == '+' || message[0] == '~') { - snprintf(message, MSG_SIZ,"%c%c%c+\n", - PieceToChar((ChessSquare)(DEMOTED *bp)), - AAA + j, ONE + i); + snprintf(message, MSG_SIZ,"%c%c%d+\n", + PieceToChar((ChessSquare)(DEMOTED(*bp))), + AAA + j, ONE + i - '0'); } if(cps->alphaRank) { /* [HGM] shogi: translate coords */ message[1] = BOARD_RGHT - 1 - j + '1'; @@ -6591,9 +6685,8 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i piece = boards[currentMove][fromY][fromX]; 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; + highestPromotingPiece = (PieceToChar(piece) == '+' || PieceToChar(CHUPROMOTED(piece)) != '+') ? WhitePawn : WhiteKing; } else if(gameInfo.variant == VariantShogi) { promotionZoneSize = BOARD_HEIGHT/3 +(BOARD_HEIGHT == 8); highestPromotingPiece = (int)WhiteAlfil; @@ -6658,7 +6751,7 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i *promoChoice = PieceToChar(p++); if(*promoChoice != '.') break; } - return FALSE; + if(!*engineVariant) return FALSE; // if used as parent variant there might be promotion choice } // no sense asking what we must promote to if it is going to explode... if(gameInfo.variant == VariantAtomic && boards[currentMove][toY][toX] != EmptySquare) { @@ -6875,7 +6968,7 @@ int doubleClick; Boolean addToBookFlag; void -UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) +UserMoveEvent (int fromX, int fromY, int toX, int toY, int promoChar) { ChessMove moveType; ChessSquare pup; @@ -6959,6 +7052,7 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) "fromY %d, toX %d, toY %d\n", fromX, fromY, toX, toY); } + DrawPosition(TRUE, boards[currentMove]); // [HGM] repair animation damage done by premove (in particular emptying from-square) return; } break; @@ -6980,6 +7074,7 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) "fromY %d, toX %d, toY %d\n", fromX, fromY, toX, toY); } + DrawPosition(TRUE, boards[currentMove]); return; } break; @@ -6996,11 +7091,9 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) return; } else if (toX >= 0 && toY >= 0) { if(!appData.pieceMenu && toX == fromX && toY == fromY && boards[0][rf][ff] != EmptySquare) { - ChessSquare q, p = boards[0][rf][ff]; - if(p >= BlackPawn) p = BLACK_TO_WHITE p; - if(CHUPROMOTED p < BlackPawn) p = q = CHUPROMOTED boards[0][rf][ff]; - else p = CHUDEMOTED (q = boards[0][rf][ff]); - if(PieceToChar(q) == '+') gatingPiece = p; + ChessSquare p = boards[0][rf][ff]; + if(PieceToChar(p) == '+') gatingPiece = CHUDEMOTED(p); else + if(PieceToChar(CHUPROMOTED(p)) =='+') gatingPiece = CHUPROMOTED(p); } boards[0][toY][toX] = boards[0][fromY][fromX]; if(fromX == BOARD_LEFT-2) { // handle 'moves' out of holdings @@ -7016,6 +7109,7 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) } } else boards[0][fromY][fromX] = gatingPiece; + ClearHighlights(); DrawPosition(FALSE, boards[currentMove]); return; } @@ -7044,6 +7138,8 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) if(fromY == DROP_RANK && fromX == EmptySquare && (gameMode == AnalyzeMode || gameMode == EditGame || PosFlags(0) & F_NULL_MOVE)) moveType = NormalMove; + if(moveType == IllegalMove && legal[toY][toX] > 1) moveType = NormalMove; // someone explicitly told us this move is legal + /* [HGM] but possibly ignore an IllegalMove result */ if (appData.testLegality) { if (moveType == IllegalMove || moveType == ImpossibleMove) { @@ -7062,7 +7158,8 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) if(addToBookFlag) { // adding moves to book char buf[MSG_SIZ], move[MSG_SIZ]; CoordsToAlgebraic(boards[currentMove], PosFlags(currentMove), fromY, fromX, toY, toX, promoChar, move); - if(killX >= 0) snprintf(move, MSG_SIZ, "%c%dx%c%d-%c%d", fromX + AAA, fromY + ONE - '0', killX + AAA, killY + ONE - '0', toX + AAA, toY + ONE - '0'); + if(killX >= 0) snprintf(move, MSG_SIZ, "%c%dx%c%d-%c%d%c", fromX + AAA, fromY + ONE - '0', + killX + AAA, killY + ONE - '0', toX + AAA, toY + ONE - '0', promoChar); snprintf(buf, MSG_SIZ, " 0.0%% 1 %s\n", move); AddBookMove(buf); addToBookFlag = FALSE; @@ -7279,7 +7376,7 @@ MarkByFEN(char *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') legal[r][f] = 3; 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 @@ -7311,8 +7408,8 @@ Mark (Board board, int flags, ChessMove kind, int rf, int ff, int rt, int ft, VO if(rf == fromY && ff == fromX && (killX < 0 ? !(rt == rf && ft == ff) && legNr & 1 : rt == killY && ft == killX || legNr & 2)) (*m)[rt][ft] = 1 + (board[rt][ft] != EmptySquare || kind == WhiteCapturesEnPassant - || kind == BlackCapturesEnPassant) + 3*(kind == FirstLeg && killX < 0), legal[rt][ft] = 1; - else if(flags & F_MANDATORY_CAPTURE && board[rt][ft] != EmptySquare) (*m)[rt][ft] = 3, legal[rt][ft] = 1; + || kind == BlackCapturesEnPassant) + 3*(kind == FirstLeg && killX < 0), legal[rt][ft] = 3; + else if(flags & F_MANDATORY_CAPTURE && board[rt][ft] != EmptySquare) (*m)[rt][ft] = 3, legal[rt][ft] = 3; } static int hoverSavedValid; @@ -7363,8 +7460,8 @@ CanPromote (ChessSquare piece, int y) // some variants have fixed promotion piece, no promotion at all, or another selection mechanism 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; + (gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || + gameInfo.variant == VariantMakruk) && !*engineVariant) return FALSE; return (piece == BlackPawn && y <= zone || piece == WhitePawn && y >= BOARD_HEIGHT-1-zone || piece == BlackLance && y <= zone || @@ -7526,7 +7623,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) DragPieceBegin(xPix, yPix, FALSE); dragging = 1; if(appData.sweepSelect && CanPromote(piece = boards[currentMove][fromY][fromX], fromY)) { promoSweep = defaultPromoChoice; - selectFlag = 0; lastX = xPix; lastY = yPix; + selectFlag = 0; lastX = xPix; lastY = yPix; *promoRestrict = 0; Sweep(0); // Pawn that is going to promote: preview promotion piece DisplayMessage("", _("Pull pawn backwards to under-promote")); } @@ -7539,7 +7636,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) return; } } -printf("to click %d,%d\n",x,y); + /* fromX != -1 */ if (clickType == Press && gameMode != EditPosition) { ChessSquare fromP; @@ -7591,7 +7688,7 @@ printf("to click %d,%d\n",x,y); DragPieceBegin(xPix, yPix, FALSE); if(appData.sweepSelect && CanPromote(piece = boards[currentMove][y][x], y)) { promoSweep = defaultPromoChoice; - selectFlag = 0; lastX = xPix; lastY = yPix; + selectFlag = 0; lastX = xPix; lastY = yPix; *promoRestrict = 0; Sweep(0); // Pawn that is going to promote: preview promotion piece } } @@ -7602,10 +7699,10 @@ printf("to click %d,%d\n",x,y); // ignore clicks on holdings if(x < BOARD_LEFT || x >= BOARD_RGHT) return; } -printf("A type=%d\n",clickType); - if(x == fromX && y == fromY && gameMode == EditPosition && SubtractTimeMarks(&lastClickTime, &prevClickTime) < 200) { + if(x == fromX && y == fromY && clickType == Press && gameMode == EditPosition && SubtractTimeMarks(&lastClickTime, &prevClickTime) < 200) { gatingPiece = boards[currentMove][fromY][fromX]; // prepare to copy rather than move + DragPieceBegin(xPix, yPix, FALSE); dragging = 1; return; } @@ -7640,7 +7737,7 @@ printf("A type=%d\n",clickType); } clearFlag = 0; -printf("B\n"); + if(gameMode != EditPosition && !appData.testLegality && !legal[y][x] && fromX >= BOARD_LEFT && fromX < BOARD_RGHT && (x != killX || y != killY) && !sweepSelecting) { if(dragging) DragPieceEnd(xPix, yPix), dragging = 0; @@ -7648,7 +7745,7 @@ printf("B\n"); DrawPosition(TRUE, NULL); return; // ignore to-click } -printf("(%d,%d)-(%d,%d) %d %d\n",fromX,fromY,toX,toY,x,y); + /* we now have a different from- and (possibly off-board) to-square */ /* Completed move */ if(!sweepSelecting) { @@ -7677,8 +7774,9 @@ printf("(%d,%d)-(%d,%d) %d %d\n",fromX,fromY,toX,toY,x,y); if(legal[y][x] == 2 || HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, FALSE)) { if(appData.sweepSelect) { promoSweep = defaultPromoChoice; - if(gameInfo.variant != VariantChuChess && PieceToChar(CHUPROMOTED piece) == '+') promoSweep = CHUPROMOTED piece; + if(gameInfo.variant != VariantChuChess && PieceToChar(CHUPROMOTED(piece)) == '+') promoSweep = CHUPROMOTED(piece); selectFlag = 0; lastX = xPix; lastY = yPix; + ReportClick("put", x, y); // extra put to prompt engine for 'choice' command Sweep(0); // Pawn that is going to promote: preview promotion piece sweepSelecting = 1; DisplayMessage("", _("Pull pawn backwards to under-promote")); @@ -7694,6 +7792,7 @@ printf("(%d,%d)-(%d,%d) %d %d\n",fromX,fromY,toX,toY,x,y); } } 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 + *promoRestrict = 0; if (appData.animate || appData.highlightLastMove) { SetHighlights(fromX, fromY, toX, toY); } else { @@ -7709,6 +7808,8 @@ printf("(%d,%d)-(%d,%d) %d %d\n",fromX,fromY,toX,toY,x,y); ClearHighlights(); } #endif + if(PieceToChar(CHUPROMOTED(boards[currentMove][fromY][fromX])) == '+') + defaultPromoChoice = CHUPROMOTED(boards[currentMove][fromY][fromX]); 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 @@ -7891,6 +7992,23 @@ RightClick (ClickType action, int x, int y, int *fromX, int *fromY) } void +Wheel (int dir, int x, int y) +{ + if(gameMode == EditPosition) { + int xSqr = EventToSquare(x, BOARD_WIDTH); + int ySqr = EventToSquare(y, BOARD_HEIGHT); + if(ySqr < 0 || xSqr < BOARD_LEFT || xSqr >= BOARD_RGHT) return; + if(flipView) xSqr = BOARD_WIDTH - 1 - xSqr; else ySqr = BOARD_HEIGHT - 1 - ySqr; + do { + boards[currentMove][ySqr][xSqr] += dir; + if((int) boards[currentMove][ySqr][xSqr] < WhitePawn) boards[currentMove][ySqr][xSqr] = BlackKing; + if((int) boards[currentMove][ySqr][xSqr] > BlackKing) boards[currentMove][ySqr][xSqr] = WhitePawn; + } while(PieceToChar(boards[currentMove][ySqr][xSqr]) == '.'); + DrawPosition(FALSE, boards[currentMove]); + } else if(dir > 0) ForwardEvent(); else BackwardEvent(); +} + +void SendProgramStatsToFrontend (ChessProgramState * cps, ChessProgramStats * cpstats) { // char * hint = lastHint; @@ -8108,7 +8226,7 @@ Adjudicate (ChessProgramState *cps) // most tests only when we understand the game, i.e. legality-checking on if( appData.testLegality ) { /* [HGM] Some more adjudications for obstinate engines */ - int nrW, nrB, bishopColor, staleW, staleB, nr[EmptySquare+1], i; + int nrW, nrB, bishopColor, staleW, staleB, nr[EmptySquare+2], i; static int moveCount = 6; ChessMove result; char *reason = NULL; @@ -8550,7 +8668,7 @@ DeferredBookMove (void) static int savedWhitePlayer, savedBlackPlayer, pairingReceived; static ChessProgramState *stalledEngine; -static char stashedInputMove[MSG_SIZ]; +static char stashedInputMove[MSG_SIZ], abortEngineThink; void HandleMachineMove (char *message, ChessProgramState *cps) @@ -8562,7 +8680,7 @@ HandleMachineMove (char *message, ChessProgramState *cps) ChessMove moveType; char promoChar, roar; char *p, *pv=buf1; - int machineWhite, oldError; + int oldError; char *bookHit; if(cps == &pairing && sscanf(message, "%d-%d", &savedWhitePlayer, &savedBlackPlayer) == 2) { @@ -8633,24 +8751,29 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h return; } + if(cps->usePing) { + /* This method is only useful on engines that support ping */ + if(abortEngineThink) { + if (appData.debugMode) { + fprintf(debugFP, "Undoing move from aborted think of %s\n", cps->which); + } + SendToProgram("undo\n", cps); + return; + } + if (cps->lastPing != cps->lastPong) { - if (gameMode == BeginningOfGame) { /* Extra move from before last new; ignore */ if (appData.debugMode) { fprintf(debugFP, "Ignoring extra move from %s\n", cps->which); } - } else { - if (appData.debugMode) { - fprintf(debugFP, "Undoing extra move from %s, gameMode %d\n", - cps->which, gameMode); - } - - SendToProgram("undo\n", cps); - } return; } + } else { + + int machineWhite = FALSE; + switch (gameMode) { case BeginningOfGame: /* Extra move from before last reset; ignore */ @@ -8696,6 +8819,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } return; } + } if(cps->alphaRank) AlphaRank(machineMove, 4); @@ -8731,7 +8855,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h snprintf(buf1, MSG_SIZ*10, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c via %c%c, %c%c) res=%d", machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, killX+AAA, killY+ONE, kill2X+AAA, kill2Y+ONE, moveType); if (gameMode == TwoMachinesPlay) { - GameEnds(machineWhite ? BlackWins : WhiteWins, + GameEnds(cps->twoMachinesColor[0] == 'w' ? BlackWins : WhiteWins, buf1, GE_XBOARD); } return; @@ -8749,7 +8873,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h if(moveType == IllegalMove) { snprintf(buf1, MSG_SIZ*10, "Xboard: Forfeit due to illegal move: %s (%c%c%c%c)%c", machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, 0); - GameEnds(machineWhite ? BlackWins : WhiteWins, + GameEnds(cps->twoMachinesColor[0] == 'w' ? BlackWins : WhiteWins, buf1, GE_XBOARD); return; } else if(!appData.fischerCastling) @@ -8794,6 +8918,17 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h free(fen); GameEnds(GameUnfinished, NULL, GE_XBOARD); } + if(appData.epd) { + if(solvingTime >= 0) { + snprintf(buf1, MSG_SIZ, "%d. %4.2fs\n", matchGame, solvingTime/100.); + totalTime += solvingTime; first.matchWins++; + } else { + snprintf(buf1, MSG_SIZ, "%d. wrong (%s)\n", matchGame, parseList[backwardMostMove]); + second.matchWins++; + } + OutputKibitz(2, buf1); + GameEnds(GameUnfinished, NULL, GE_XBOARD); + } /* [AS] Adjudicate game if needed (note: remember that forwardMostMove now points past the last move) */ if( gameMode == TwoMachinesPlay && appData.adjudicateLossThreshold != 0 && forwardMostMove >= adjudicateLossPlies ) { @@ -8968,10 +9103,10 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } if(sscanf(message, "piece %s %s", buf2, buf1) == 2) { ChessSquare piece = WhitePawn; - char *p=buf2, *q, *s = SUFFIXES, ID = *p; - if(*p == '+') piece = CHUPROMOTED WhitePawn, ID = *++p; + char *p=message+6, *q, *s = SUFFIXES, ID = *p; + if(*p == '+') piece = CHUPROMOTED(WhitePawn), ID = *++p; if(q = strchr(s, p[1])) ID += 64*(q - s + 1), p++; - piece += CharToPiece(ID) - WhitePawn; + piece += CharToPiece(ID & 255) - WhitePawn; if(cps != &first || appData.testLegality && *engineVariant == NULLCHAR /* always accept definition of */ && piece != WhiteFalcon && piece != BlackFalcon /* wild-card pieces. */ && piece != WhiteCobra && piece != BlackCobra @@ -8983,10 +9118,15 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h if(piece < EmptySquare) { pieceDefs = TRUE; ASSIGN(pieceDesc[piece], buf1); - if(isupper(*p) && p[1] == '&') { ASSIGN(pieceDesc[WHITE_TO_BLACK piece], buf1); } + if((ID & 32) == 0 && p[1] == '&') { ASSIGN(pieceDesc[WHITE_TO_BLACK piece], buf1); } } return; } + if(sscanf(message, "choice %s", promoRestrict) == 1 && promoSweep != EmptySquare) { + promoSweep = CharToPiece(currentMove&1 ? ToLower(*promoRestrict) : ToUpper(*promoRestrict)); + Sweep(0); + return; + } /* [HGM] Allow engine to set up a position. Don't ask me why one would * want this, I was asked to put it in, and obliged. */ @@ -9103,6 +9243,11 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } initPing = -1; } + if(cps->lastPing == cps->lastPong && abortEngineThink) { + abortEngineThink = FALSE; + DisplayMessage("", ""); + ThawUI(); + } return; } if(!strncmp(message, "highlight ", 10)) { @@ -9521,6 +9666,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h buf1[0] = NULLCHAR; if (sscanf(message, "%d%c %d %d " u64Display " %[^\n]\n", &plylev, &plyext, &curscore, &time, &nodes, buf1) >= 5) { + char score_buf[MSG_SIZ]; if(nodes>>32 == u64Const(0xFFFFFFFF)) // [HGM] negative node count read nodes += u64Const(0x100000000); @@ -9543,6 +9689,14 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h if(appData.pvSAN[cps==&second]) pv = PvToSAN(buf1); + if(*bestMove) { // rememer time best EPD move was first found + int ff1, tf1, fr1, tr1, ff2, tf2, fr2, tr2; char pp1, pp2; + ChessMove mt; + int ok = ParseOneMove(bestMove, forwardMostMove, &mt, &ff1, &fr1, &tf1, &tr1, &pp1); + ok &= ParseOneMove(pv, forwardMostMove, &mt, &ff2, &fr2, &tf2, &tr2, &pp2); + solvingTime = (ok && ff1==ff2 && fr1==fr2 && tf1==tf2 && tr1==tr2 && pp1==pp2 ? time : -1); + } + if(serverMoves && (time > 100 || time == 0 && plylev > 7)) { char buf[MSG_SIZ]; FILE *f; @@ -9613,11 +9767,18 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h [AS] Protect the thinkOutput buffer from overflow... this is only useful if buf1 hasn't overflowed first! */ - snprintf(thinkOutput, sizeof(thinkOutput)/sizeof(thinkOutput[0]), "[%d]%c%+.2f %s%s", + if((gameMode == AnalyzeMode && appData.whitePOV || appData.scoreWhite) && !WhiteOnMove(forwardMostMove)) curscore *= -1; + if(curscore >= MATE_SCORE) + snprintf(score_buf, MSG_SIZ, "#%d", curscore - MATE_SCORE); + else if(curscore <= -MATE_SCORE) + snprintf(score_buf, MSG_SIZ, "#%d", curscore + MATE_SCORE); + else + snprintf(score_buf, MSG_SIZ, "%+.2f", ((double) curscore) / 100.0); + snprintf(thinkOutput, sizeof(thinkOutput)/sizeof(thinkOutput[0]), "[%d]%c%s %s%s", plylev, (gameMode == TwoMachinesPlay ? ToUpper(cps->twoMachinesColor[0]) : ' '), - ((double) curscore) / 100.0, + score_buf, prefixHint ? lastHint : "", prefixHint ? " " : "" ); @@ -10064,6 +10225,11 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) board[toY][toX + (killX < fromX ? 1 : -1)] = killed; board[EP_STATUS] = EP_NONE; // capture was fake! } else + if(nrCastlingRights == 0 && board[toY][toX] < EmptySquare && (piece < BlackPawn) == (board[toY][toX] < BlackPawn)) { + board[fromY][fromX] = board[toY][toX]; // capture own will lead to swapping + board[toY][toX] = piece; + board[EP_STATUS] = EP_NONE; // capture was fake! + } else /* Code added by Tord: */ /* FRC castling assumed when king captures friendly rook. [HGM] or RxK for S-Chess */ if (board[fromY][fromX] == WhiteKing && board[toY][toX] == WhiteRook || @@ -10088,6 +10254,9 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) } /* End of code added by Tord */ + } else if (pieceDesc[piece] && piece == king && !strchr(pieceDesc[piece], 'O') && strchr(pieceDesc[piece], 'i')) { + board[fromY][fromX] = EmptySquare; // never castle if King has virgin moves defined on it other than castling + board[toY][toX] = piece; } else if (board[fromY][fromX] == king && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */ && toY == fromY && toX > fromX+1) { @@ -10110,8 +10279,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) ) { /* white pawn promotion */ board[toY][toX] = CharToPiece(ToUpper(promoChar)); - if(board[toY][toX] < WhiteCannon && PieceToChar(PROMOTED board[toY][toX]) == '~') /* [HGM] use shadow piece (if available) */ - board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]); + if(board[toY][toX] < WhiteCannon && PieceToChar(PROMOTED(board[toY][toX])) == '~') /* [HGM] use shadow piece (if available) */ + board[toY][toX] = (ChessSquare) (PROMOTED(board[toY][toX])); board[fromY][fromX] = EmptySquare; } else if ((fromY >= BOARD_HEIGHT>>1) && (oldEP == toX || oldEP == EP_UNKNOWN || appData.testLegality || abs(toX - fromX) > 4) @@ -10175,8 +10344,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) ) { /* black pawn promotion */ board[toY][toX] = CharToPiece(ToLower(promoChar)); - if(board[toY][toX] < BlackCannon && PieceToChar(PROMOTED board[toY][toX]) == '~') /* [HGM] use shadow piece (if available) */ - board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]); + if(board[toY][toX] < BlackCannon && PieceToChar(PROMOTED(board[toY][toX])) == '~') /* [HGM] use shadow piece (if available) */ + board[toY][toX] = (ChessSquare) (PROMOTED(board[toY][toX])); board[fromY][fromX] = EmptySquare; } else if ((fromY < BOARD_HEIGHT>>1) && (oldEP == toX || oldEP == EP_UNKNOWN || appData.testLegality || abs(toX - fromX) > 4) @@ -10250,10 +10419,10 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) p = (int) captured; if (p >= (int) BlackPawn) { p -= (int)BlackPawn; - if(DEMOTED p >= 0 && PieceToChar(p) == '+') { + if(DEMOTED(p) >= 0 && PieceToChar(p) == '+') { /* Restore shogi-promoted piece to its original first */ - captured = (ChessSquare) (DEMOTED captured); - p = DEMOTED p; + captured = (ChessSquare) (DEMOTED(captured)); + p = DEMOTED(p); } p = PieceToNumber((ChessSquare)p); if(p >= gameInfo.holdingsSize) { p = 0; captured = BlackPawn; } @@ -10261,9 +10430,9 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) board[p][BOARD_WIDTH-1] = BLACK_TO_WHITE captured; } else { p -= (int)WhitePawn; - if(DEMOTED p >= 0 && PieceToChar(p) == '+') { - captured = (ChessSquare) (DEMOTED captured); - p = DEMOTED p; + if(DEMOTED(p) >= 0 && PieceToChar(p) == '+') { + captured = (ChessSquare) (DEMOTED(captured)); + p = DEMOTED(p); } p = PieceToNumber((ChessSquare)p); if(p >= gameInfo.holdingsSize) { p = 0; captured = WhitePawn; } @@ -10291,13 +10460,13 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) } else if(promoChar == '+') { /* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite ordinary Pawn promotion) */ - board[toY][toX] = (ChessSquare) (CHUPROMOTED 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 - && pieceToChar[PROMOTED newPiece] == '~') newPiece = PROMOTED newPiece; // but promoted version available + if((newPiece <= WhiteMan || newPiece >= BlackPawn && newPiece <= BlackMan) // unpromoted piece specified + && pieceToChar[PROMOTED(newPiece)] == '~') newPiece = PROMOTED(newPiece);// but promoted version available board[toY][toX] = newPiece; } if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) @@ -10326,10 +10495,10 @@ MakeMove (int fromX, int fromY, int toX, int toY, int promoChar) 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, y, x, promoChar, + fromY, fromX, y, x, (killX < 0)*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'); + sprintf(s + strlen(s), "%c%c%d%c", p == EmptySquare || toX == fromX && toY == fromY ? '-' : 'x', toX + AAA, toY + ONE - '0', promoChar); if(serverMoves != NULL) { /* [HGM] write moves on file for broadcasting (should be separate routine, really) */ int timeLeft; static int lastLoadFlag=0; int king, piece; @@ -11393,16 +11562,17 @@ GameEnds (ChessMove result, char *resultDetails, int whosays) && gameInfo.variant != VariantLosers && gameInfo.variant != VariantGiveaway && gameInfo.variant != VariantSuicide // [HGM] losers: except in losers, of course... && result != GameIsDrawn) - { int i, j, k=0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn); + { int i, j, k=0, oppoKings = 0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn); for(j=BOARD_LEFT; j= 0 && p <= (int)WhiteKing) k++; + oppoKings += (p + color == WhiteKing + BlackPawn - color); } if (appData.debugMode) { fprintf(debugFP, "GE(%d, %s, %d) bare king k=%d color=%d\n", result, resultDetails ? resultDetails : "(null)", whosays, k, color); } - if(k <= 1) { + if(k <= 1 && oppoKings > 0) { // the latter needed in Atomic, where bare K wins if opponent King already destroyed result = GameIsDrawn; snprintf(buf, MSG_SIZ, "%s but bare king", resultDetails); resultDetails = buf; @@ -11989,13 +12159,13 @@ LoadGameOneMove (ChessMove readAhead) case BlackASideCastleFR: /* POP Fabien */ if (appData.debugMode) - fprintf(debugFP, "Parsed %s into %s\n", yy_text, currentMoveString); + fprintf(debugFP, "Parsed %s into %s virgin=%x,%x\n", yy_text, currentMoveString, boards[forwardMostMove][TOUCHED_W], boards[forwardMostMove][TOUCHED_B]); fromX = currentMoveString[0] - AAA; fromY = currentMoveString[1] - ONE; toX = currentMoveString[2] - AAA; toY = currentMoveString[3] - ONE; promoChar = currentMoveString[4]; - if(promoChar == ';') promoChar = NULLCHAR; + if(promoChar == ';') promoChar = currentMoveString[7]; break; case WhiteDrop: @@ -12949,7 +13119,7 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList) gameInfo.event = StrSave(yy_text); } - startedFromSetupPosition = FALSE; + startedFromSetupPosition = startedFromPositionFile; // [HGM] while (cm == PGNTag) { if (appData.debugMode) fprintf(debugFP, "Parsed PGNTag: %s\n", yy_text); @@ -12976,7 +13146,7 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList) return FALSE; } CopyBoard(boards[0], initial_position); - if(*engineVariant) // [HGM] for now, assume FEN in engine-defined variant game is default initial position + if(*engineVariant || gameInfo.variant == VariantFairy) // [HGM] for now, assume FEN in engine-defined variant game is default initial position CopyBoard(initialPosition, initial_position); if (blackPlaysFirst) { currentMove = forwardMostMove = backwardMostMove = 1; @@ -13313,10 +13483,14 @@ LoadPosition (FILE *f, int positionNumber, char *title) } if (fenMode) { + char *p; if (!ParseFEN(initial_position, &blackPlaysFirst, line, TRUE)) { DisplayError(_("Bad FEN position in file"), 0); return FALSE; } + if((p = strstr(line, ";")) && (p = strstr(p+1, "bm "))) { // EPD with best move + sscanf(p+3, "%s", bestMove); + } else *bestMove = NULLCHAR; } else { (void) fgets(line, MSG_SIZ, f); (void) fgets(line, MSG_SIZ, f); @@ -14939,6 +15113,16 @@ EditGameEvent () case MachinePlaysBlack: case BeginningOfGame: SendToProgram("force\n", &first); + if(gameMode == (forwardMostMove & 1 ? MachinePlaysBlack : MachinePlaysWhite)) { // engine is thinking + if (first.usePing) { // [HGM] always send ping when we might interrupt machine thinking + char buf[MSG_SIZ]; + abortEngineThink = TRUE; + snprintf(buf, MSG_SIZ, "ping %d\n", initPing = ++first.lastPing); + SendToProgram(buf, &first); + DisplayMessage("Aborting engine think", ""); + FreezeUI(); + } + } SetUserThinkingEnables(); break; case PlayFromGameFile: @@ -15272,7 +15456,7 @@ EditPositionMenuEvent (ChessSquare selection, int x, int y) case PromotePiece: if(piece >= (int)WhitePawn && piece < (int)WhiteMan || piece >= (int)BlackPawn && piece < (int)BlackMan ) { - selection = (ChessSquare) (PROMOTED piece); + selection = (ChessSquare) (PROMOTED(piece)); } else if(piece == EmptySquare) selection = WhiteSilver; else selection = (ChessSquare)((int)piece - 1); goto defaultlabel; @@ -15280,7 +15464,7 @@ EditPositionMenuEvent (ChessSquare selection, int x, int y) case DemotePiece: if(piece > (int)WhiteMan && piece <= (int)WhiteKing || piece > (int)BlackMan && piece <= (int)BlackKing ) { - selection = (ChessSquare) (DEMOTED piece); + selection = (ChessSquare) (DEMOTED(piece)); } else if(piece == EmptySquare) selection = BlackSilver; else selection = (ChessSquare)((int)piece + 1); goto defaultlabel; @@ -16132,7 +16316,7 @@ PrintPosition (FILE *fp, int move) for (i = BOARD_HEIGHT - 1; i >= 0; i--) { for (j = BOARD_LEFT; j < BOARD_RGHT; j++) { char c = PieceToChar(boards[move][i][j]); - fputc(c == 'x' ? '.' : c, fp); + fputc(c == '?' ? '.' : c, fp); fputc(j == BOARD_RGHT - 1 ? '\n' : ' ', fp); } } @@ -16849,6 +17033,7 @@ ParseOption (Option *opt, ChessProgramState *cps) char *p, *q, buf[MSG_SIZ]; int n, min = (-1)<<31, max = 1<<31, def; + opt->target = &opt->value; // OK for spin/slider and checkbox if(p = strstr(opt->name, " -spin ")) { if((n = sscanf(p, " -spin %d %d %d", &def, &min, &max)) < 3 ) return FALSE; if(max < min) max = min; // enforce consistency @@ -16871,14 +17056,17 @@ ParseOption (Option *opt, ChessProgramState *cps) } else if((p = strstr(opt->name, " -string "))) { opt->textValue = p+9; opt->type = TextBox; + opt->target = &opt->textValue; } else if((p = strstr(opt->name, " -file "))) { // for now -file is a synonym for -string, to already provide compatibility with future polyglots - opt->textValue = p+7; + opt->target = opt->textValue = p+7; opt->type = FileName; // FileName; + opt->target = &opt->textValue; } else if((p = strstr(opt->name, " -path "))) { // for now -file is a synonym for -string, to already provide compatibility with future polyglots - opt->textValue = p+7; + opt->target = opt->textValue = p+7; opt->type = PathName; // PathName; + opt->target = &opt->textValue; } else if(p = strstr(opt->name, " -check ")) { if(sscanf(p, " -check %d", &def) < 1) return FALSE; opt->value = (def != 0); @@ -16942,9 +17130,9 @@ FeatureDone (ChessProgramState *cps, int val) (cb == TwoMachinesEventIfReady)) { CancelDelayedEvent(); ScheduleDelayedEvent(cb, val ? 1 : 3600000); - } + } else if(!val && !cps->reload) ClearOptions(cps); // let 'spurious' done=0 clear engine's option list cps->initDone = val; - if(val) cps->reload = FALSE; + if(val) cps->reload = FALSE, RefreshSettingsDialog(cps, val); } /* Parse feature command from engine */ @@ -17859,7 +18047,7 @@ char * PositionToFEN (int move, char *overrideCastling, int moveCounts) { int i, j, fromX, fromY, toX, toY; - int whiteToPlay; + int whiteToPlay, haveRights = nrCastlingRights; char buf[MSG_SIZ]; char *p, *q; int emptycount; @@ -17886,13 +18074,13 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) if(PieceToChar(piece) == '+') { /* [HGM] write promoted pieces as '+' (Shogi) */ *p++ = '+'; - piece = (ChessSquare)(CHUDEMOTED piece); + piece = (ChessSquare)(CHUDEMOTED(piece)); } *p++ = (piece == DarkSquare ? '*' : PieceToChar(piece)); if(*p = PieceSuffix(piece)) p++; if(p[-1] == '~') { /* [HGM] flag promoted pieces as '~' (Crazyhouse) */ - p[-1] = PieceToChar((ChessSquare)(CHUDEMOTED piece)); + p[-1] = PieceToChar((ChessSquare)(CHUDEMOTED(piece))); *p++ = '~'; } } @@ -17933,10 +18121,28 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) *p++ = whiteToPlay ? 'w' : 'b'; *p++ = ' '; + if(pieceDesc[WhiteKing] && strchr(pieceDesc[WhiteKing], 'i') && !strchr(pieceDesc[WhiteKing], 'O')) { // redefined without castling + haveRights = 0; q = p; + for(i=BOARD_RGHT-1; i>=BOARD_LEFT; i--) { + piece = boards[move][0][i]; + if(piece >= WhitePawn && piece <= WhiteKing && pieceDesc[piece] && strchr(pieceDesc[piece], 'i')) { // piece with initial move + if(!(boards[move][TOUCHED_W] & 1<=BOARD_LEFT; i--) { + piece = boards[move][BOARD_HEIGHT-1][i]; + if(piece >= BlackPawn && piece <= BlackKing && pieceDesc[piece] && strchr(pieceDesc[piece], 'i')) { // piece with initial move + if(!(boards[move][TOUCHED_B] & 1<=BOARD_LEFT+q; i--) @@ -17983,9 +18189,9 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) } if(q) *p++ = 'Q'; k = 0; - if(boards[move][CASTLING][3] == BOARD_RGHT-1 && + if(boards[move][CASTLING][3] != NoRights && boards[move][CASTLING][5] != NoRights ) k = 1, *p++ = 'k'; - q = (boards[move][CASTLING][4] == BOARD_LEFT && + q = (boards[move][CASTLING][4] != NoRights && boards[move][CASTLING][5] != NoRights ); if(handB) { for(i=BOARD_RGHT-1-k; i>=BOARD_LEFT+q; i--) @@ -18062,7 +18268,7 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize) int i, j, k, w=0, subst=0, shuffle=0, wKingRank = -1, bKingRank = -1; char *p, c; int emptycount, virgin[BOARD_FILES]; - ChessSquare piece; + ChessSquare piece, king = (gameInfo.variant == VariantKnightmate ? WhiteUnicorn : WhiteKing); p = fen; @@ -18076,7 +18282,7 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize) while (emptycount--) board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare; if (*p == '/') p++; - else if(autoSize) { // we stumbled unexpectedly into end of board + else if(autoSize && i != BOARD_HEIGHT-1) { // we stumbled unexpectedly into end of board for(k=i; k> 1; // for these variant scanning fails - if(whiteKingFile == NoRights || board[0][whiteKingFile] != WhiteUnicorn - && board[0][whiteKingFile] != WhiteKing) whiteKingFile = NoRights; - if(blackKingFile == NoRights || board[BOARD_HEIGHT-1][blackKingFile] != BlackUnicorn - && board[BOARD_HEIGHT-1][blackKingFile] != BlackKing) blackKingFile = NoRights; + if(whiteKingFile == NoRights || board[castlingRank[2]][whiteKingFile] != WhiteUnicorn + && board[castlingRank[2]][whiteKingFile] != WhiteKing) whiteKingFile = NoRights; + if(blackKingFile == NoRights || board[castlingRank[5]][blackKingFile] != BlackUnicorn + && board[castlingRank[5]][blackKingFile] != BlackKing) blackKingFile = NoRights; switch(c) { case'K': for(i=BOARD_RGHT-1; board[castlingRank[2]][i]!=WhiteRook && i>whiteKingFile; i--); diff --git a/backend.h b/backend.h index 33b6e95..be1906e 100644 --- a/backend.h +++ b/backend.h @@ -218,6 +218,8 @@ void ics_printf P((char *format, ...)); int GetEngineLine P((char *nick, int engine)); void AddGameToBook P((int always)); void FlushBook P((void)); +char PieceToChar P((ChessSquare p)); +int LoadPieceDesc P((char *s)); char *StrStr P((char *string, char *match)); char *StrCaseStr P((char *string, char *match)); @@ -417,13 +419,15 @@ 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)); -int MultiPV P((ChessProgramState *cps)); +int MultiPV P((ChessProgramState *cps, int kind)); void MoveHistorySet P(( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo )); 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)); char *CollectPieceDescriptors P((void)); +void RefreshSettingsDialog P((ChessProgramState *cps, int val)); +void StartChessProgram P((ChessProgramState *cps)); /* A point in time */ diff --git a/board.c b/board.c index baf0680..f0cb1c6 100644 --- a/board.c +++ b/board.c @@ -671,6 +671,7 @@ ChangeDragPiece (ChessSquare piece) { anims[Player].dragPiece = piece; SetDragPiece(Player, piece); + damage[0][fromY][fromX] = True; } void @@ -1190,10 +1191,10 @@ ArrowDamage (int s_col, int s_row, int d_col, int d_row) int hor, vert, i, n = partnerUp * twoBoards; hor = 64*s_col + 32; vert = 64*s_row + 32; for(i=0; i<= 64; i++) { - damage[n][vert+6>>6][hor+6>>6] |= 2; - damage[n][vert-6>>6][hor+6>>6] |= 2; - damage[n][vert+6>>6][hor-6>>6] |= 2; - damage[n][vert-6>>6][hor-6>>6] |= 2; + damage[n][vert+8>>6][hor+8>>6] |= 2; + damage[n][vert-8>>6][hor+8>>6] |= 2; + damage[n][vert+8>>6][hor-8>>6] |= 2; + damage[n][vert-8>>6][hor-8>>6] |= 2; hor += d_col - s_col; vert += d_row - s_row; } } @@ -1212,20 +1213,20 @@ DrawArrowBetweenSquares (int s_col, int s_row, int d_col, int d_row) SquareToPos( s_row, s_col, &s_x, &s_y); SquareToPos( d_row, d_col, &d_x, &d_y); - if( d_y > s_y ) { + if( d_y > s_y && d_y - s_y > abs(d_x - s_x)/2) { d_y += squareSize / 2 - squareSize / 4; // [HGM] round towards same centers on all sides! } - else if( d_y < s_y ) { + else if( d_y < s_y && s_y - d_y > abs(d_x - d_y)/2) { d_y += squareSize / 2 + squareSize / 4; } else { d_y += squareSize / 2; } - if( d_x > s_x ) { + if( d_x > s_x && d_x - s_x > abs(d_y - s_y)/2) { d_x += squareSize / 2 - squareSize / 4; } - else if( d_x < s_x ) { + else if( d_x < s_x && s_x - d_x > abs(d_y - s_y)/2) { d_x += squareSize / 2 + squareSize / 4; } else { diff --git a/book.c b/book.c index 090ae1b..cfc25c8 100644 --- a/book.c +++ b/book.c @@ -315,7 +315,7 @@ hash (int moveNr) if(p != EmptySquare){ int j = (int)p, promoted = 0; j -= (j >= (int)BlackPawn) ? (int)BlackPawn :(int)WhitePawn; - if(j >= CHUPROMOTED WhitePawn) promoted++, j -= CHUPROMOTED WhitePawn; + if(j >= WhitePBishop && j != WhiteKing) promoted++, j -= WhiteTokin; if(j > (int)WhiteQueen) j++; // make space for King if(j > (int) WhiteKing) j = (int)WhiteQueen + 1; p_enc = 2*j + ((int)p < (int)BlackPawn); diff --git a/common.h b/common.h index 40232dd..b4f6c3e 100644 --- a/common.h +++ b/common.h @@ -227,6 +227,7 @@ typedef char *String; #define BELLCHAR '\007' #define NULLCHAR '\000' #define FEATURE_TIMEOUT 10000 /*ms*/ +#define MATE_SCORE 100000 #define CLOCK_FONT 0 #define MESSAGE_FONT 1 @@ -294,18 +295,26 @@ typedef enum { WhiteFerz, WhiteAlfil, WhiteAngel, WhiteMarshall, WhiteWazir, WhiteMan, WhiteCannon, WhiteNightrider, WhiteCardinal, WhiteDragon, WhiteGrasshopper, WhiteSilver, WhiteFalcon, WhiteLance, WhiteCobra, WhiteUnicorn, WhiteLion, - WhiteTokin, WhiteClaw, WhitePCardinal, WhitePDragon, WhiteCat, - WhitePSword, WhiteMonarch, WhiteMother, WhiteNothing, WhitePRook, WhitePDagger, - WhiteDolphin, WhiteStag, WhiteHorned, WhiteEagle, WhiteSword, - WhiteCrown, WhiteHCrown, WhiteHorse, WhiteDrunk, WhitePBishop, WhiteKing, + WhiteSword, WhiteZebra, WhiteCamel, WhiteTower, WhiteWolf, + WhiteHat, WhiteDuck, WhiteAmazon, WhiteFlying, WhiteGnu, WhiteCub, + WhiteShield, WhiteHorse, WhiteWizard, WhiteCopper, WhiteIron, + WhiteViking, WhiteFlag, WhiteAxe, WhiteDolphin, WhiteCat, WhiteClaw, + WhiteWheel, WhiteButterfly, WhitePBishop, WhitePRook, WhiteHCrown, + WhiteShierd, WhiteMonarch, WhiteMother, WhiteNothing, WhiteDrunk, WhiteWheer, + WhiteTokin, WhitePKnight, WhitePCardinal, WhitePDragon, WhitePLance, + WhitePSilver, WhiteDagger, WhitePSword, WhitePDagger, WhiteCrown, WhiteKing, BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackFerz, BlackAlfil, BlackAngel, BlackMarshall, BlackWazir, BlackMan, BlackCannon, BlackNightrider, BlackCardinal, BlackDragon, BlackGrasshopper, BlackSilver, BlackFalcon, BlackLance, BlackCobra, BlackUnicorn, BlackLion, - BlackTokin, BlackClaw, BlackPCardinal, BlackPDragon, BlackCat, - BlackPSword, BlackMonarch, BlackMother, BlackNothing, BlackPRook, BlackPDagger, - BlackDolphin, BlackStag, BlackHorned, BlackEagle, BlackSword, - BlackCrown, BlackHCrown, BlackHorse, BlackDrunk, BlackPBishop, BlackKing, + BlackSword, BlackZebra, BlackCamel, BlackTower, BlackWolf, + BlackHat, BlackDuck, BlackAmazon, BlackFlying, BlackGnu, BlackCub, + BlackShield, BlackHorse, BlackWizard, BlackCopper, BlackIron, + BlackViking, BlackFlag, BlackAxe, BlackDolphin, BlackCat, BlackClaw, + BlackWheel, BlackButterfly, BlackPBishop, BlackPRook, BlackHCrown, + BlackShierd, BlackMonarch, BlackMother, BlackNothing, BlackDrunk, BlackWheer, + BlackTokin, BlackPKnight, BlackPCardinal, BlackPDragon, BlackPLance, + BlackPSilver, BlackDagger, BlackPSword, BlackPDagger, BlackCrown, BlackKing, EmptySquare, DarkSquare, NoRights, // [HGM] gamestate: for castling rights hidden in board[CASTLING] ClearBoard, WhitePlay, BlackPlay, PromotePiece, DemotePiece /*for use on EditPosition menus*/ @@ -314,11 +323,12 @@ typedef enum { /* [HGM] some macros that can be used as prefixes to convert piece types */ #define WHITE_TO_BLACK (int)BlackPawn - (int)WhitePawn + (int) #define BLACK_TO_WHITE (int)WhitePawn - (int)BlackPawn + (int) -#define PROMOTED (int)WhiteDragon - (int)WhiteRook + (int) -#define DEMOTED (int)WhiteRook - (int)WhiteDragon + (int) +#define PROMO (int)WhiteDragon - (int)WhiteRook + (int) +#define PROMOTED(X) (promoPartner[X]) +#define DEMOTED(X) (promoPartner[X]) #define SHOGI (int)EmptySquare + (int) -#define CHUPROMOTED ((int)WhitePDragon - (int)WhiteDragon)*(gameInfo.variant == VariantChu) + PROMOTED -#define CHUDEMOTED ((int)WhiteDragon - (int)WhitePDragon)*(gameInfo.variant == VariantChu) + DEMOTED +#define CHUPROMOTED(X) (promoPartner[X]) +#define CHUDEMOTED(X) (promoPartner[X]) #define IS_SHOGI(V) ((V) == VariantShogi || (V) == VariantChu) #define IS_LION(V) ((V) == WhiteLion || (V) == BlackLion) @@ -523,6 +533,7 @@ typedef struct { Boolean fischerCastling;/* [HGM] fischer: allow Fischr castling in any variant */ Boolean matchMode; int matchGames; + Boolean epd; Boolean monoMode; Boolean debugMode; Boolean clockMode; diff --git a/dialogs.c b/dialogs.c index 8a6a4dd..d19a769 100644 --- a/dialogs.c +++ b/dialogs.c @@ -93,11 +93,13 @@ int SetCurrentComboSelection (Option *opt) { int j; + if(currentCps) ; else if(!opt->textValue) opt->value = *(int*)opt->target; /* numeric */else { for(j=0; opt->choice[j]; j++) // look up actual value in list of possible values, to get selection nr if(*(char**)opt->target && !strcmp(*(char**)opt->target, ((char**)opt->textValue)[j])) break; opt->value = j + (opt->choice[j] == NULL); } + SetComboChoice(opt, opt->value); return opt->value; } @@ -331,8 +333,10 @@ UpgradeParticipant () static void PseudoOK () { + if(matchMode) return; GenericReadout(matchOptions, -2); // read all, but suppress calling of MatchOK ASSIGN(appData.participants, engineName); + ASSIGN(appData.tourneyFile, tfName); PopDown(MasterDlg); // early popdown to prevent FreezeUI called through MatchEvent from causing XtGrab warning } @@ -1458,6 +1462,22 @@ SecondSettingsProc () SettingsPopUp(&second); } +void +RefreshSettingsDialog (ChessProgramState *cps, int val) +{ + if(val == 1) { // option values changed + if(shellUp[TransientDlg] && cps == currentCps) { + GenericUpdate(cps->option, -1); // normally update values when dialog is up + } + return; // and be done + } + if(val == 2) { // option list changed + if(!shellUp[TransientDlg] || cps != currentCps) return; // our dialog is not up, so nothing to do + } + PopDown(TransientDlg); // make sure any other dialog closes first + SettingsPopUp(cps); // and popup new one +} + //----------------------------------------------- Load Engine -------------------------------------- char *engineDir, *engineLine, *nickName, *params; @@ -1669,6 +1689,10 @@ SetTcType (int n) void TimeControlProc () { + if(gameMode != BeginningOfGame) { + DisplayError(_("Changing time control during a game is not implemented"), 0); + return; + } tmpMoves = appData.movesPerSession; tmpInc = appData.timeIncrement; if(tmpInc < 0) tmpInc = 0; tmpOdds1 = tmpOdds2 = 1; tcType = 0; @@ -1771,7 +1795,7 @@ PromotionPopUp (char choice) { // choice depends on variant: prepare dialog acordingly count = 8; SetPromo(_("Cancel"), --count, -1); // Beware: GenericPopUp cannot handle user buttons named "cancel" (lowe case)! - if(choice != '+') { + if(choice != '+' && !IS_SHOGI(gameInfo.variant)) { if (!appData.testLegality || gameInfo.variant == VariantSuicide || gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) || gameInfo.variant == VariantGiveaway) { @@ -1944,6 +1968,7 @@ OutputChatMessage (int partner, char *mess) char *p = texts[partner]; int len = strlen(mess) + 1; + if(!DialogExists(ChatDlg)) return; if(p) len += strlen(p); texts[partner] = (char*) malloc(len); snprintf(texts[partner], len, "%s%s", p ? p : "", mess); @@ -2261,8 +2286,8 @@ ErrorPopUp (char *title, char *label, int modal) { errorUp = True; errorOptions[1].name = label; - if(dialogError = shellUp[TransientDlg]) - GenericPopUp(errorOptions+1, title, FatalDlg, TransientDlg, MODAL, 0); // pop up as daughter of the transient dialog + if(dialogError = shellUp[MasterDlg]) + GenericPopUp(errorOptions+1, title, FatalDlg, MasterDlg, MODAL, 0); // pop up as daughter of the transient dialog else GenericPopUp(errorOptions+modal, title, modal ? FatalDlg: ErrorDlg, BoardWindow, modal, 0); // kludge: option start address indicates modality } @@ -2554,7 +2579,7 @@ MenuCallback (int n) static Option * Exp (int n, int x, int y) { - static int but1, but3, oldW, oldH; + static int but1, but3, oldW, oldH, oldX, oldY; int menuNr = -3, sizing, f, r; TimeMark now; extern Boolean right; @@ -2565,6 +2590,7 @@ Exp (int n, int x, int y) } if(n == 0) { // motion + oldX = x; oldY = y; if(SeekGraphClick(Press, x, y, 1)) return NULL; if((but1 || dragging == 2) && !PromoScroll(x, y)) DragPieceMove(x, y); if(but3) MovePV(x, y, lineGap + BOARD_HEIGHT * (squareSize + lineGap)); @@ -2587,8 +2613,8 @@ Exp (int n, int x, int y) case 3: menuNr = RightClick(Press, x, y, &pmFromX, &pmFromY), but3 = 1; break; case -2: shiftKey = !shiftKey; case -3: menuNr = RightClick(Release, x, y, &pmFromX, &pmFromY), but3 = 0; break; - case 4: BackwardEvent(); break; - case 5: ForwardEvent(); break; + case 4: Wheel(-1, oldX, oldY); break; + case 5: Wheel(1, oldX, oldY); break; case 10: sizing = (oldW != x || oldH != y); oldW = x; oldH = y; diff --git a/dialogs.h b/dialogs.h index 3a7fc2e..9468d52 100644 --- a/dialogs.h +++ b/dialogs.h @@ -154,6 +154,7 @@ void SetWidgetText P((Option *opt, char *buf, int n)); void GetWidgetState P((Option *opt, int *state)); void SetWidgetState P((Option *opt, int state)); void SetWidgetLabel P((Option *opt, char *buf)); +void SetComboChoice P((Option *opt, int choice)); void SetDialogTitle P((DialogClass dlg, char *title)); void LoadListBox P((Option *opt, char *emptyText, int n1, int n2)); void HighlightListBoxItem P((Option *opt, int nr)); diff --git a/draw.c b/draw.c index cd5881d..fca16eb 100644 --- a/draw.c +++ b/draw.c @@ -55,9 +55,9 @@ #include #include #include -#include #include #include +#include #if STDC_HEADERS # include @@ -106,9 +106,9 @@ extern char *getenv(); Boolean cairoAnimate; Option *currBoard; cairo_surface_t *csBoardWindow; -static cairo_surface_t *pngPieceImages[2][(int)BlackPawn+4]; // png 256 x 256 images -static cairo_surface_t *pngPieceBitmaps[2][(int)BlackPawn]; // scaled pieces as used -static cairo_surface_t *pngPieceBitmaps2[2][(int)BlackPawn+4]; // scaled pieces in store +static cairo_surface_t *pngPieceImages[2][(int)BlackPawn]; // png 256 x 256 images +static cairo_surface_t *pngPieceBitmaps[2][(int)BlackPawn]; // scaled pieces as used +static cairo_surface_t *pngPieceBitmaps2[2][(int)BlackPawn]; // scaled pieces in store static RsvgHandle *svgPieces[2][(int)BlackPawn+4]; // vector pieces in store static cairo_surface_t *pngBoardBitmap[2], *pngOriginalBoardBitmap[2]; int useTexture, textureW[2], textureH[2]; @@ -144,9 +144,9 @@ SelectPieces(VariantClass v) pngPieceBitmaps[i][p] = pngPieceBitmaps2[i][p]; // defaults if(v == VariantShogi && BOARD_HEIGHT != 7) { // no exceptions in Tori Shogi pngPieceBitmaps[i][(int)WhiteCannon] = pngPieceBitmaps2[i][(int)WhiteTokin]; - pngPieceBitmaps[i][(int)WhiteNightrider] = pngPieceBitmaps2[i][(int)WhiteKing+2]; - pngPieceBitmaps[i][(int)WhiteGrasshopper] = pngPieceBitmaps2[i][(int)WhiteKing+3]; - pngPieceBitmaps[i][(int)WhiteSilver] = pngPieceBitmaps2[i][(int)WhiteKing+4]; + pngPieceBitmaps[i][(int)WhiteNightrider] = pngPieceBitmaps2[i][(int)WhitePKnight]; + pngPieceBitmaps[i][(int)WhiteGrasshopper] = pngPieceBitmaps2[i][(int)WhitePLance]; + pngPieceBitmaps[i][(int)WhiteSilver] = pngPieceBitmaps2[i][(int)WhitePSilver]; pngPieceBitmaps[i][(int)WhiteQueen] = pngPieceBitmaps2[i][(int)WhiteLance]; pngPieceBitmaps[i][(int)WhiteFalcon] = pngPieceBitmaps2[i][(int)WhiteMonarch]; // for Sho Shogi } @@ -165,12 +165,16 @@ SelectPieces(VariantClass v) if(v == VariantChu) { pngPieceBitmaps[i][(int)WhiteNightrider] = pngPieceBitmaps2[i][(int)WhiteClaw]; pngPieceBitmaps[i][(int)WhiteClaw] = pngPieceBitmaps2[i][(int)WhiteNightrider]; - pngPieceBitmaps[i][(int)WhiteUnicorn] = pngPieceBitmaps2[i][(int)WhiteHorned]; - pngPieceBitmaps[i][(int)WhiteSilver] = pngPieceBitmaps2[i][(int)WhiteStag]; - pngPieceBitmaps[i][(int)WhiteFalcon] = pngPieceBitmaps2[i][(int)WhiteEagle]; - pngPieceBitmaps[i][(int)WhiteHorned] = pngPieceBitmaps2[i][(int)WhiteUnicorn]; - pngPieceBitmaps[i][(int)WhiteStag] = pngPieceBitmaps2[i][(int)WhiteSilver]; - pngPieceBitmaps[i][(int)WhiteEagle] = pngPieceBitmaps2[i][(int)WhiteFalcon]; + pngPieceBitmaps[i][(int)WhiteUnicorn] = pngPieceBitmaps2[i][(int)WhiteCat]; + pngPieceBitmaps[i][(int)WhiteSilver] = pngPieceBitmaps2[i][(int)WhiteSword]; + pngPieceBitmaps[i][(int)WhiteFalcon] = pngPieceBitmaps2[i][(int)WhiteDagger]; + pngPieceBitmaps[i][(int)WhiteCat] = pngPieceBitmaps2[i][(int)WhiteUnicorn]; + pngPieceBitmaps[i][(int)WhiteSword] = pngPieceBitmaps2[i][(int)WhiteSilver]; + pngPieceBitmaps[i][(int)WhiteDagger] = pngPieceBitmaps2[i][(int)WhiteFalcon]; + pngPieceBitmaps[i][(int)WhiteMan] = pngPieceBitmaps2[i][(int)WhiteCopper]; + pngPieceBitmaps[i][(int)WhiteCopper] = pngPieceBitmaps2[i][(int)WhiteMan]; + pngPieceBitmaps[i][(int)WhiteAxe] = pngPieceBitmaps2[i][(int)WhiteCannon]; + pngPieceBitmaps[i][(int)WhiteCannon] = pngPieceBitmaps2[i][(int)WhiteAxe]; } } } @@ -249,7 +253,7 @@ CreatePNGBoard (char *s, int kind) textureW[kind] = 0; // prevents bitmap from being used if not succesfully loaded if(strstr(s, ".png")) { cairo_surface_t *img = cairo_image_surface_create_from_png (s); - if(img) { + if(cairo_surface_status(img) == CAIRO_STATUS_SUCCESS) { char c, *p = s, *q; int r, f; if(pngOriginalBoardBitmap[kind]) cairo_surface_destroy(pngOriginalBoardBitmap[kind]); @@ -288,13 +292,19 @@ CreatePNGBoard (char *s, int kind) 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", "Crown", "Chancellor", "Hawk", "Lance", "Cobra", "Unicorn", "Lion", - "GoldPawn", "Claw", "PromoHorse", "PromoDragon", "GoldLance", "PromoSword", "Prince", "Phoenix", "Kylin", "PromoRook", "PromoHSword", - "Dolphin", "Sword", "Leopard", "HSword", "GoldSilver", "Princess", "HCrown", "Knight", "Elephant", "PromoBishop", "King", - "Claw", "GoldKnight", "GoldLance", "GoldSilver", NULL + "Sword", "Zebra", "Camel", "Tower", "Wolf", "Hat", "Duck", "Lance", "Dragon", "Gnu", "Cub", + "LShield", "Pegasus", "Wizard", "Copper", "Iron", "Viking", "Flag", "Axe", "Dolphin", "Leopard", "Claw", + "Left", "Butterfly", "PromoBishop", "PromoRook", "HCrown", "RShield", "Prince", "Phoenix", "Kylin", "Drunk", "Right", + "GoldPawn", "GoldKnight", "PromoHorse", "PromoDragon", "GoldLance", "GoldSilver", "HSword", "PromoSword", "PromoHSword", "Princess", "King", + NULL }; -char *backupPiece[] = { "Princess", NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, "King", "Queen", "Lion" }; // pieces that map on other when not kanji +char *backupPiece[] = { // pieces that map on other in default theme ("Crown" - "Drunk") + "Princess", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Chancellor", NULL, + NULL, "Knight", NULL, "Commoner", NULL, NULL, NULL, "Canon", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, "King", "Queen", "Lion", "Elephant" +}; RsvgHandle * LoadSVG (char *dir, int color, int piece, int retry) @@ -311,8 +321,15 @@ LoadSVG (char *dir, int color, int piece, int retry) snprintf(buf, MSG_SIZ, "%s/%s%s.svg", dir, color ? "Black" : "White", name); - if(svg || *dir && (svg = rsvg_handle_new_from_file(buf, &svgerror))) { + if(!svg && *dir) { + svg = rsvg_handle_new_from_file(buf, &svgerror); + if(!svg && *appData.inscriptions) { // if there is no piece-specific SVG, but we make inscriptions, try general background + snprintf(buf, MSG_SIZ, "%s/%sTile.svg", dir, color ? "Black" : "White"); + svg = rsvg_handle_new_from_file(buf, &svgerror); + } + } + if(svg) { rsvg_handle_get_dimensions(svg, &svg_dimensions); img = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, squareSize, squareSize); @@ -327,7 +344,7 @@ LoadSVG (char *dir, int color, int piece, int retry) return svg; } - if(!retry && piece >= WhiteGrasshopper && piece <= WhiteNothing) // pieces that are only different in kanji sets + if(!retry && piece >= WhiteGrasshopper && piece <= WhiteDrunk) // pieces that are only different in kanji sets return LoadSVG(dir, color, piece, 1); if(svgerror) g_error_free(svgerror); @@ -358,9 +375,10 @@ ScaleOnePiece (int color, int piece) 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, 0)) && !warned) { // try to fall back on installed svg + if(!(svgPieces[color][piece] = LoadSVG(svgDir, color, piece, 0)) // try to fall back on installed svg + && !warned && strcmp(pngPieceNames[piece], "Tile")) { // but do not complain about missing 'Tile' char *msg = _("No default pieces installed!\nSelect your own using '-pieceImageDirectory'."); - printf("%s\n", msg); // give up + printf("%s (%s)\n", msg, pngPieceNames[piece]); // give up DisplayError(msg, 0); warned = 1; // prevent error message being repeated for each piece type } @@ -646,18 +664,25 @@ DrawLogo (Option *opt, void *logo) cairo_t *cr; int w, h; - if(!logo || !opt) return; - img = cairo_image_surface_create_from_png (logo); - w = cairo_image_surface_get_width (img); - h = cairo_image_surface_get_height (img); + if(!opt) return; cr = cairo_create(DRAWABLE(opt)); -// cairo_scale(cr, (float)appData.logoSize/w, appData.logoSize/(2.*h)); - cairo_scale(cr, (float)opt->max/w, (float)opt->value/h); - cairo_set_source_surface (cr, img, 0, 0); - cairo_paint (cr); + cairo_rectangle (cr, 0, 0, opt->max, opt->value); + cairo_set_source_rgba(cr, 0.5, 0.5, 0.5, 1.0); + cairo_fill(cr); // paint background in case logo does not exist + if(logo) { + img = cairo_image_surface_create_from_png (logo); + if(cairo_surface_status(img) == CAIRO_STATUS_SUCCESS) { + w = cairo_image_surface_get_width (img); + h = cairo_image_surface_get_height (img); +// cairo_scale(cr, (float)appData.logoSize/w, appData.logoSize/(2.*h)); + cairo_scale(cr, (float)opt->max/w, (float)opt->value/h); + cairo_set_source_surface (cr, img, 0, 0); + cairo_paint (cr); + } + cairo_surface_destroy (img); + } cairo_destroy (cr); - cairo_surface_destroy (img); - GraphExpose(opt, 0, 0, appData.logoSize, appData.logoSize/2); + GraphExpose(opt, 0, 0, opt->max, opt->value); } static void @@ -739,6 +764,34 @@ DrawDot (int marker, int x, int y, int r) } static void +DrawUnicode (cairo_surface_t *canvas, char *string, int x, int y, char id, int flip) +{ +// cairo_text_extents_t te; + cairo_t *cr; + int s = 1 - 2*flip; + PangoLayout *layout; + PangoFontDescription *desc; + PangoRectangle r; + char fontName[MSG_SIZ]; + + cr = cairo_create (canvas); + layout = pango_cairo_create_layout(cr); + pango_layout_set_text(layout, string, -1); + snprintf(fontName, MSG_SIZ, "Sans Normal %dpx", 5*squareSize/8); + desc = pango_font_description_from_string(fontName); + pango_layout_set_font_description(layout, desc); + pango_font_description_free(desc); + pango_layout_get_pixel_extents(layout, NULL, &r); + cairo_translate(cr, x + squareSize/2 - s*r.width/2, y + (8+s)*squareSize/16 - s*r.height/2); + if(s < 0) cairo_rotate(cr, G_PI); + cairo_set_source_rgb(cr, (id == '+' ? 1.0 : 0.0), 0.0, 0.0); + pango_cairo_update_layout(cr, layout); + pango_cairo_show_layout(cr, layout); + g_object_unref(layout); + cairo_destroy(cr); +} + +static void DrawText (char *string, int x, int y, int align) { int xx = x, yy = y; @@ -764,12 +817,9 @@ DrawText (char *string, int x, int y, int align) yy += -te.y_bearing + 3; } else if (align == 4) { xx += te.x_bearing + 1, yy += -te.y_bearing + 3; - } else if (align < 0) { - xx += squareSize/2 - te.width/2, yy += 9*squareSize/16 - te.y_bearing/2; } cairo_move_to (cr, xx-1, yy); - if(align == -2) cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); else if(align < 3) cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); else cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_show_text (cr, string); @@ -777,10 +827,10 @@ DrawText (char *string, int x, int y, int align) } void -InscribeKanji (ChessSquare piece, int x, int y) +InscribeKanji (cairo_surface_t *canvas, ChessSquare piece, int x, int y) { char *p, *q, buf[10]; - int n; + int n, flip = appData.upsideDown && flipView == (piece < BlackPawn); if(piece == EmptySquare) return; if(piece >= BlackPawn) piece = BLACK_TO_WHITE piece; p = appData.inscriptions; @@ -798,7 +848,7 @@ InscribeKanji (ChessSquare piece, int x, int y) strncpy(buf, p, 10); for(q=buf; (*++q & 0xC0) == 0x80;); *q = NULLCHAR; - DrawText(buf, x, y, n > WhiteLion ? -2 : -1); + DrawUnicode(canvas, buf, x, y, PieceToChar(n), flip); } void @@ -810,7 +860,7 @@ DrawOneSquare (int x, int y, ChessSquare piece, int square_color, int marker, ch BlankSquare(csBoardWindow, x, y, square_color, piece, 1); } else { pngDrawPiece(csBoardWindow, piece, square_color, x, y); - if(appData.inscriptions[0]) InscribeKanji(piece, x, y); + if(appData.inscriptions[0]) InscribeKanji(csBoardWindow, piece, x, y); } if(align) { // square carries inscription (coord or piece count) @@ -859,6 +909,7 @@ CairoOverlayPiece (ChessSquare piece, cairo_surface_t *dest) if(doubleClick) cairo_paint_with_alpha (pieceSource, 0.6); else cairo_paint(pieceSource); cairo_destroy (pieceSource); + if(appData.inscriptions[0]) InscribeKanji(dest, piece, 0, 0); } void diff --git a/engineoutput.c b/engineoutput.c index 9a92dd0..ac1103e 100644 --- a/engineoutput.c +++ b/engineoutput.c @@ -232,11 +232,14 @@ SetProgramStats (FrontEndProgramStats * stats) // now directly called by back-en header[which][0] = NULLCHAR; if(gameMode == AnalyzeMode) { ChessProgramState *cps = (which ? &second : &first); - if((multi = MultiPV(cps)) >= 0) { - snprintf(header[which], MSG_SIZ, "\t%s viewpoint\t\tfewer / Multi-PV setting = %d / more\n", - appData.whitePOV || appData.scoreWhite ? "white" : "mover", cps->option[multi].value); + char *exclu = cps->excludeMoves ? exclusionHeader : ""; + if((multi = MultiPV(cps, 3)) != -1) { + char *s = "setting"; + if(multi < -1) multi = -2 - multi, s = "margin"; + snprintf(header[which], MSG_SIZ, "\t%s viewpoint\t\tfewer / Multi-PV %s = %d / more\n", + appData.whitePOV || appData.scoreWhite ? "white" : "mover", s, cps->option[multi].value); } - if(!which) snprintf(header[which]+strlen(header[which]), MSG_SIZ-strlen(header[which]), "%s%s", exclusionHeader, columnHeader); + if(!which) snprintf(header[which]+strlen(header[which]), MSG_SIZ-strlen(header[which]), "%s%s", exclu, columnHeader); InsertIntoMemo( which, header[which], 0); } else { snprintf(header[which], MSG_SIZ, "%s", columnHeader); @@ -402,6 +405,14 @@ SetEngineColorIcon (int which) // [HGM] multivar: sort Thinking Output within one depth on score static int +MateFlip (int n) +{ // map mate-score to monotonous scale, so sorting compares them correctly + if(n >= MATE_SCORE) return 2*MATE_SCORE - n; + if(n <= -MATE_SCORE) return -2*MATE_SCORE - n; + return n; +} + +static int InsertionPoint (int len, EngineOutputData *ed) { int i, offs = 0, newScore = ed->score, n = ed->which; @@ -425,7 +436,7 @@ InsertionPoint (int len, EngineOutputData *ed) keys[i+n+2] = ed->moveKey; fail[i+n+2] = failType; if(ed->moveKey != keys[i+n] && // same move always tops previous one (as a higher score must be a fail low) - newScore < scores[i+n] && fail[i+n] == ' ') break; + MateFlip(newScore) < MateFlip(scores[i+n]) && fail[i+n] == ' ') break; // if it had higher score as previous, move previous in stead scores[i+n+2] = ed->moveKey == keys[i+n] ? newScore : scores[i+n]; // correct scores of fail-low/high searches textEnd[i+n+2] = textEnd[i+n] + len; @@ -443,7 +454,6 @@ InsertionPoint (int len, EngineOutputData *ed) return offs + strlen(header[ed->which]); } -#define MATE_SCORE 100000 static char spaces[] = " "; // [HGM] align: spaces for padding static void diff --git a/frontend.h b/frontend.h index b6ed686..bd0f071 100644 --- a/frontend.h +++ b/frontend.h @@ -137,6 +137,7 @@ void DragPieceEnd P((int x, int y)); void DragPieceMove P((int x, int y)); void LeftClick P((ClickType c, int x, int y)); int RightClick P((ClickType c, int x, int y, int *col, int *row)); +void Wheel P((int dir, int x, int y)); int StartChildProcess P((char *cmdLine, char *dir, ProcRef *pr)); void DestroyChildProcess P((ProcRef pr, int/*boolean*/ signal)); diff --git a/gtk/xboard.c b/gtk/xboard.c index c6df31a..de5da12 100644 --- a/gtk/xboard.c +++ b/gtk/xboard.c @@ -63,7 +63,6 @@ #include #include #include -#include #include #if !OMIT_SOCKETS @@ -213,11 +212,13 @@ RETSIGTYPE CmailSigHandler P((int sig)); RETSIGTYPE IntSigHandler P((int sig)); RETSIGTYPE TermSizeSigHandler P((int sig)); char *InsertPxlSize P((char *pattern, int targetPxlSize)); +#ifdef TODO_GTK #if ENABLE_NLS XFontSet CreateFontSet P((char *base_fnt_lst)); #else char *FindFont P((char *pattern, int targetPxlSize)); #endif +#endif void DelayedDrag P((void)); void ICSInputBoxPopUp P((void)); void MoveTypeInProc P((GdkEventKey *eventkey)); @@ -1022,8 +1023,6 @@ main (int argc, char **argv) programName, appData.boardSize); exit(2); } - if(BOARD_WIDTH > 8) - squareSize = (squareSize*8 + BOARD_WIDTH/2)/BOARD_WIDTH; // scale height if (i < 7) { /* Find some defaults; use the nearest known size */ SizeDefaults *szd, *nearest; @@ -1075,6 +1074,10 @@ main (int argc, char **argv) tinyLayout = szd->tinyLayout; // [HGM] font: use defaults from settings file if available and not overruled } + if(BOARD_WIDTH != 8) { + squareSize = (squareSize*8 + BOARD_WIDTH/2)/BOARD_WIDTH; // keep width the same + lineGap = (squareSize < 37 ? 1 : squareSize < 59 ? 2 : squareSize < 116 ? 3 : 4); + } defaultLineGap = lineGap; if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap; @@ -1775,7 +1778,7 @@ void ModeHighlight () { static int oldPausing = FALSE; - static GameMode oldmode = (GameMode) -1; + static GameMode oldMode = (GameMode) -1; char *wname; if (!boardWidget) return; @@ -1793,7 +1796,7 @@ ModeHighlight () } } - wname = ModeToWidgetName(oldmode); + wname = ModeToWidgetName(oldMode); if (wname != NULL) { MarkMenuItem(wname, False); } @@ -1801,8 +1804,9 @@ ModeHighlight () if (wname != NULL) { MarkMenuItem(wname, True); } - oldmode = gameMode; + if(oldMode == TwoMachinesPlay) EnableNamedMenuItem("Mode.MachineMatch", True); MarkMenuItem("Mode.MachineMatch", matchMode && matchGame < appData.matchGames); + oldMode = gameMode; /* Maybe all the enables should be handled here, not just this one */ EnableNamedMenuItem("Mode.Training", gameMode == Training || gameMode == PlayFromGameFile); diff --git a/gtk/xoptions.c b/gtk/xoptions.c index 7e91a24..525d00b 100644 --- a/gtk/xoptions.c +++ b/gtk/xoptions.c @@ -48,7 +48,6 @@ extern char *getenv(); #include #include -#include #include #include #ifdef OSXAPP @@ -244,6 +243,12 @@ SetWidgetLabel (Option *opt, char *buf) } void +SetComboChoice (Option *opt, int n) +{ + gtk_combo_box_set_active(opt->handle, n); +} + +void SetDialogTitle (DialogClass dlg, char *title) { gtk_window_set_title(GTK_WINDOW(shells[dlg]), title); @@ -544,11 +549,11 @@ HighlightText (Option *opt, int from, int to, Boolean highlight) if(!(opt->min & INIT)) { opt->min |= INIT; // each memo its own init flag! gtk_text_buffer_create_tag(opt->handle, "highlight", "background", "yellow", NULL); - gtk_text_buffer_create_tag(opt->handle, "normal", "background", "white", NULL); } gtk_text_buffer_get_iter_at_offset(opt->handle, &start, from); gtk_text_buffer_get_iter_at_offset(opt->handle, &end, to); - gtk_text_buffer_apply_tag_by_name(opt->handle, highlight ? "highlight" : "normal", &start, &end); + if(highlight) gtk_text_buffer_apply_tag_by_name(opt->handle, "highlight", &start, &end); + else gtk_text_buffer_remove_tag_by_name(opt->handle, "highlight", &start, &end); } static char **names; @@ -1465,10 +1470,12 @@ if(appData.debugMode) printf("n=%d, h=%d, w=%d\n",n,height,width); /* set button color on new variant dialog */ if(option[i].textValue) { static char *b = "Bold"; + char *v, *p = NULL, n = option[i].value; + if(n >= 0) v = VariantName(n), p = strstr(first.variants, v); gdk_color_parse( option[i].textValue, &color ); gtk_widget_modify_bg ( GTK_WIDGET(button), GTK_STATE_NORMAL, &color ); gtk_widget_set_sensitive(button, option[i].value >= 0 && (appData.noChessProgram - || strstr(first.variants, VariantName(option[i].value)))); + || p && (!*v || strlen(p) == strlen(v) || p[strlen(v)] == ','))); if(engineVariant[100] ? !strcmp(engineVariant+100, option[i].name) : gameInfo.variant ? option[i].value == gameInfo.variant : !strcmp(option[i].name, "Normal")) SetWidgetFont(gtk_bin_get_child(GTK_BIN(button)), &b); diff --git a/gtk/xtimer.c b/gtk/xtimer.c index e0e0a75..162a265 100644 --- a/gtk/xtimer.c +++ b/gtk/xtimer.c @@ -184,13 +184,14 @@ StartLoadGameTimer (long millisec) guint analysisClockTag = 0; -void +int AnalysisClockCallback(gpointer data) { if (gameMode == AnalyzeMode || gameMode == AnalyzeFile || appData.icsEngineAnalyze) { // [DM] AnalysisPeriodicEvent(0); } + return 1; } void diff --git a/menus.c b/menus.c index 863f2a0..03a2d3c 100644 --- a/menus.c +++ b/menus.c @@ -258,6 +258,8 @@ QuitProc () void MatchProc () { + static Enables matchOff[] = { { "Mode.MachineMatch", False }, { NULL, False } }; + if(matchMode) SetMenuEnables(matchOff); MatchEvent(2); } @@ -699,6 +701,7 @@ MenuItem engineMenu[100] = { {"----", NULL, NULL, NothingProc}, {N_("Engine #1 Settings..."), NULL, "Engine#1Settings", FirstSettingsProc}, {N_("Engine #2 Settings..."), NULL, "Engine#2Settings", SecondSettingsProc}, + {N_("Common Settings..."), "u","CommonEngine", UciMenuProc}, {"----", NULL, NULL, NothingProc}, {N_("Hint"), NULL, "Hint", HintEvent}, {N_("Book"), NULL, "Book", BookEvent}, @@ -713,7 +716,6 @@ MenuItem optionsMenu[] = { {N_("General..."), NULL, "General", OptionsProc}, #endif {N_("Time Control..."), "t", "TimeControl", TimeControlProc}, - {N_("Common Engine..."), "u", "CommonEngine", UciMenuProc}, {N_("Adjudications..."), "j", "Adjudications", EngineMenuProc}, {N_("ICS..."), NULL, "ICS", IcsOptionsProc}, {N_("Tournament..."), NULL, "Match", MatchOptionsProc}, diff --git a/moves.c b/moves.c index e0ad2e1..867a940 100644 --- a/moves.c +++ b/moves.c @@ -72,7 +72,6 @@ int BlackPiece P((ChessSquare)); int SameColor P((ChessSquare, ChessSquare)); int PosFlags(int index); -extern signed char initialRights[BOARD_FILES]; /* [HGM] all rights enabled, set in InitPosition */ int quickFlag; char *pieceDesc[EmptySquare]; char *defaultDesc[EmptySquare] = { @@ -122,12 +121,13 @@ unsigned char pieceToChar[EmptySquare+1] = { 'o', 'h', 'i', 'j', 'g', 'd', 'v', 'l', 's', 'u', 'k', 'x' }; unsigned char pieceNickName[EmptySquare]; +int promoPartner[EmptySquare]; char PieceToChar (ChessSquare p) { int c; - if((int)p < 0 || (int)p >= (int)EmptySquare) return('x'); /* [HGM] for safety */ + if((int)p < 0 || (int)p >= (int)EmptySquare) return('?'); /* [HGM] for safety */ c = pieceToChar[(int) p]; if(c & 128) c = c & 63 | 64; return c; @@ -205,7 +205,7 @@ CollectPieceDescriptors () // dump all engine defined pieces, and pieces with non-standard names, // but suppress black pieces that are the same as their white counterpart ChessSquare p; - static char buf[MSG_SIZ]; + static char buf[MSG_SIZ], s[2]; char *m, c, d, *pieceName = defaultName; int len; *buf = NULLCHAR; @@ -215,22 +215,56 @@ CollectPieceDescriptors () if(gameInfo.variant == VariantXiangqi) pieceName = xqName; for(p=WhitePawn; p= BlackPawn && pieceToChar[BLACK_TO_WHITE p] == toupper(c) - && (c != '+' || pieceToChar[DEMOTED BLACK_TO_WHITE p] == d)) { // black member of normal pair + m = pieceDesc[p]; d = (c == '+' ? pieceToChar[DEMOTED(p)] : c); + if(p >= BlackPawn && pieceToChar[BLACK_TO_WHITE p] == (c & ~32) + && (c != '+' || pieceToChar[DEMOTED(BLACK_TO_WHITE p)] == d)) {// black member of normal pair char *wm = pieceDesc[BLACK_TO_WHITE p]; if(!m && !wm || m && wm && !strcmp(wm, m)) continue; // moves as a white piece } else // white or unpaired black - if((p < BlackPawn || CharToPiece(toupper(d)) != EmptySquare) && // white or lone black + if((p < BlackPawn || CharToPiece(d & ~32) != EmptySquare) && // white or lone black !pieceDesc[p] /*&& pieceName[p] == c*/) continue; // orthodox piece known by its usual name // TODO: listing pieces because of unusual name can only be done if we have accurate Betza of all defaults if(!m) m = defaultDesc[p]; + if(!m) continue; len = strlen(buf); - snprintf(buf+len, MSG_SIZ-len, "%s%s%c:%s", len ? ";" : "", c == '+' ? "+" : "", d, m); + *s = (d > 128 ? SUFFIXES[d-128>>6] : 0); d = 64 + (d & 63); + snprintf(buf+len, MSG_SIZ-len, "%s%s%c%s:%s", len ? ";" : "", c == '+' ? "+" : "", d, s, m); } return buf; } +int +LoadPieceDesc (char *s) +{ + ChessSquare piece; + static char suf[] = SUFFIXES; + char *r, *p, *q = s; + int ok = TRUE, promoted, c; + while(q && *s) { + p = s; + q = strchr(s, ';'); + if(q) *q = 0, s = q+1; + if(*p == '+') promoted = 1, p++; else promoted = 0; + c = *p++; + if(!c) { ok = FALSE; continue; } // bad syntax + if(*p && (r = strchr(suf, *p))) c += 64*(r - suf + 1), p++; + if(*p++ != ':') { ok = FALSE; continue; } // bad syntax + if(!strcmp(p, "(null)")) continue; // handle bug in writing of XBoard 4.8.0 + piece = CharToPiece(c); + if(piece >= EmptySquare) { ok = FALSE; continue; } // non-existent piece + if(promoted) { + piece = promoPartner[piece]; + if(pieceToChar[piece] != '+') { ok = FALSE; continue; } // promoted form does not exist + } + ASSIGN(pieceDesc[piece], p); + if(piece < BlackPawn && (pieceToChar[WHITE_TO_BLACK piece] == pieceToChar[piece] + 32 || promoted)) { + ASSIGN(pieceDesc[WHITE_TO_BLACK piece], p); + } + pieceDefs = TRUE; + } + return ok; +} + // [HGM] gen: configurable move generation from Betza notation sent by engine. // Some notes about two-leg moves: GenPseudoLegal() works in two modes, depending on whether a 'kill- // square has been set: without one is generates all moves, and a global int legNr flags in bits 0 and 1 @@ -286,9 +320,9 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle if(pc == WhitePawn || pc == WhiteLance) promo = WhitePromotion, promoRank = BOARD_HEIGHT-1; else if(pc == BlackPawn || pc == BlackLance) promo = BlackPromotion, promoRank = 0; while(*p) { // more moves to go - int expo = 1, dx, dy, x, y, mode, dirSet, ds2=0, retry=0, initial=0, jump=1, skip = 0, all = 0; + int expo = -1, dx, dy, x, y, mode, dirSet, ds2=0, retry=0, initial=0, jump=1, skip = 0, all = 0; char *cont = NULL; - if(*p == 'i') initial = 1, desc = ++p; + while(*p == 'i') initial++, desc = ++p; while(islower(*p)) p++; // skip prefixes if(!isupper(*p)) return; // syntax error: no atom dx = xStep[*p-'A'] - '0';// step vector of atom @@ -373,12 +407,14 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle if(isdigit(*++p)) expo = atoi(p++); // read exponent if(expo > 9) p++; // allow double-digit desc = p; // this is start of next move + if(initial == 2) { if(board[r][f] != initialPosition[r-2*his+3][f]) continue; } else if(initial && (board[r][f] != initialPosition[r][f] || r == 0 && board[TOUCHED_W] & 1< 1 && dx == 0 && dy == 0) { // castling indicated by O + number + if(expo > 0 && dx == 0 && dy == 0) { // castling indicated by O + number mode |= 1024; dy = 1; } + if(expo < 0) expo = 1; // use 1 for default if(!cont) { if(!(mode & 15)) mode |= his + 4; // no mode spec, use default = mc } else { @@ -409,8 +445,8 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle if(y < 0 || y >= BOARD_HEIGHT) break; // vertically off-board: always done if(x < BOARD_LEFT) { if(mode & 128) x += BOARD_RGHT - BOARD_LEFT, loop++; else break; } if(x >= BOARD_RGHT) { if(mode & 128) x -= BOARD_RGHT - BOARD_LEFT, loop++; else break; } - if(board[y][x] == DarkSquare) break; // black squares are supposed to be off board if(j) { j--; continue; } // skip irrespective of occupation + if(board[y][x] == DarkSquare) break; // black squares are supposed to be off board if(!jump && board[y - vy + vy/2][x - vx + vx/2] != EmptySquare) break; // blocked if(jump > 1 && board[y - vy + vy/2][x - vx + vx/2] == EmptySquare) break; // no hop if(x == f && y == r && !loop) occup = 4; else // start square counts as empty (if not around cylinder!) @@ -449,7 +485,7 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle if(occup == 4) continue; // skip empty squares if((x == BOARD_LEFT + skip || x > BOARD_LEFT + skip && vx < 0 && board[y][x-1-skip] == DarkSquare) && board[y][x] == initialPosition[y][x]) { // reached initial corner piece - if(pc != WhiteKing && pc != BlackKing) { // non-royal castling (to be entered as two-leg move via 'Rook') + if(pc != WhiteKing && pc != BlackKing || expo == 1) { // non-royal castling (to be entered as two-leg move via 'Rook') if(killX < 0) cb(board, flags, FirstLeg, r, f, y, x, cl); if(killX < f) legNr <<= 1, cb(board, flags, NormalMove, r, f, y, f - expo, cl), legNr >>= 1; } else @@ -457,7 +493,7 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle } if((x == BOARD_RGHT-1-skip || x < BOARD_RGHT-1-skip && vx > 0 && board[y][x+1+skip] == DarkSquare) && board[y][x] == initialPosition[y][x]) { - if(pc != WhiteKing && pc != BlackKing) { + if(pc != WhiteKing && pc != BlackKing || expo == 1) { if(killX < 0) cb(board, flags, FirstLeg, r, f, y, x, cl); if(killX > f) legNr <<= 1, cb(board, flags, NormalMove, r, f, y, f + expo, cl), legNr >>= 1; } else @@ -709,7 +745,7 @@ GenPseudoLegal (Board board, int flags, MoveCallback callback, VOIDSTAR closure, if ((flags & F_WHITE_ON_MOVE) != (board[rf][ff] < BlackPawn)) continue; // [HGM] speed: wrong color m = 0; piece = board[rf][ff]; if(PieceToChar(piece) == '~') - piece = (ChessSquare) ( DEMOTED piece ); + piece = (ChessSquare) ( DEMOTED(piece) ); if(filter != EmptySquare && piece != filter) continue; if(pieceDefs && pieceDesc[piece]) { // [HGM] gen: use engine-defined moves MovesFromString(board, flags, ff, rf, -1, -1, 0, pieceDesc[piece], callback, closure); @@ -885,14 +921,14 @@ GenPseudoLegal (Board board, int flags, MoveCallback callback, VOIDSTAR closure, /* Gold General (and all its promoted versions) . First do the */ /* diagonal forward steps, then proceed as normal Wazir */ - case SHOGI (PROMOTED WhitePawn): + case SHOGI (PROMO WhitePawn): if(gameInfo.variant == VariantShogi) goto WhiteGold; - case SHOGI (PROMOTED BlackPawn): + case SHOGI (PROMO BlackPawn): if(gameInfo.variant == VariantShogi) goto BlackGold; SlideVertical(board, flags, rf, ff, callback, closure); break; - case SHOGI (PROMOTED WhiteKnight): + case SHOGI (PROMO WhiteKnight): if(gameInfo.variant == VariantShogi) goto WhiteGold; case SHOGI BlackDrunk: case SHOGI BlackAlfil: @@ -901,7 +937,7 @@ GenPseudoLegal (Board board, int flags, MoveCallback callback, VOIDSTAR closure, StepBackward(board, flags, rf, ff, callback, closure); break; - case SHOGI (PROMOTED BlackKnight): + case SHOGI (PROMO BlackKnight): if(gameInfo.variant == VariantShogi) goto BlackGold; case SHOGI WhiteDrunk: case SHOGI WhiteAlfil: @@ -911,15 +947,15 @@ GenPseudoLegal (Board board, int flags, MoveCallback callback, VOIDSTAR closure, break; - case SHOGI WhiteStag: - case SHOGI BlackStag: + case SHOGI WhiteGnu: + case SHOGI BlackGnu: 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 (PROMO WhiteQueen): case SHOGI WhiteTokin: case SHOGI WhiteWazir: WhiteGold: @@ -927,7 +963,7 @@ GenPseudoLegal (Board board, int flags, MoveCallback callback, VOIDSTAR closure, Wazir(board, flags, rf, ff, callback, closure); break; - case SHOGI (PROMOTED BlackQueen): + case SHOGI (PROMO BlackQueen): case SHOGI BlackTokin: case SHOGI BlackWazir: BlackGold: @@ -1238,9 +1274,9 @@ GenPseudoLegal (Board board, int flags, MoveCallback callback, VOIDSTAR closure, StepVertical(board, flags, rf, ff, callback, closure); break; - case SHOGI (PROMOTED WhiteFerz): + case SHOGI (PROMO WhiteFerz): if(gameInfo.variant == VariantShogi) goto WhiteGold; - case SHOGI (PROMOTED BlackFerz): + case SHOGI (PROMO BlackFerz): if(gameInfo.variant == VariantShogi) goto BlackGold; case SHOGI WhitePSword: case SHOGI BlackPSword: @@ -1276,7 +1312,7 @@ GenPseudoLegal (Board board, int flags, MoveCallback callback, VOIDSTAR closure, SlideVertical(board, flags, rf, ff, callback, closure); break; - case SHOGI WhiteHorned: + case SHOGI WhiteCat: Sting(board, flags, rf, ff, 1, 0, callback, closure); callback(board, flags, NormalMove, rf, ff, rf, ff, closure); if(killX >= 0) break; @@ -1285,7 +1321,7 @@ GenPseudoLegal (Board board, int flags, MoveCallback callback, VOIDSTAR closure, SlideBackward(board, flags, rf, ff, callback, closure); break; - case SHOGI BlackHorned: + case SHOGI BlackCat: Sting(board, flags, rf, ff, -1, 0, callback, closure); callback(board, flags, NormalMove, rf, ff, rf, ff, closure); if(killX >= 0) break; @@ -1294,7 +1330,7 @@ GenPseudoLegal (Board board, int flags, MoveCallback callback, VOIDSTAR closure, SlideForward(board, flags, rf, ff, callback, closure); break; - case SHOGI WhiteEagle: + case SHOGI WhiteDagger: 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); @@ -1303,7 +1339,7 @@ GenPseudoLegal (Board board, int flags, MoveCallback callback, VOIDSTAR closure, SlideDiagBackward(board, flags, rf, ff, callback, closure); break; - case SHOGI BlackEagle: + case SHOGI BlackDagger: 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); @@ -1674,10 +1710,11 @@ CheckTest (Board board, int flags, int rf, int ff, int rt, int ft, int enPassant } ep = board[EP_STATUS]; if( captured == WhiteLion || captured == BlackLion ) { // [HGM] lion: Chu Lion-capture rules - ChessSquare victim = killX < 0 ? EmptySquare : trampled; + ChessSquare victim = saveKill < 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' + (victim == EmptySquare || victim == WhitePawn || victim == BlackPawn // no or worthless 'bridge' + || victim == WhiteCobra || victim == BlackCobra) ) // (Pawn or Go Between) board[EP_STATUS] = EP_ROYAL_LION; // on distant Lion x Lion victim must not be pseudo-legally protected } } @@ -1790,7 +1827,7 @@ LegalityTest (Board board, int flags, int rf, int ff, int rt, int ft, int promoC if(quickFlag) flags = flags & ~1 | quickFlag & 1; // [HGM] speed: in quick mode quickFlag specifies side-to-move. if(rf == DROP_RANK) return LegalDrop(board, flags, ff, rt, ft); piece = filterPiece = board[rf][ff]; - if(PieceToChar(piece) == '~') filterPiece = DEMOTED piece; + if(PieceToChar(piece) == '~') filterPiece = DEMOTED(piece); /* [HGM] Cobra and Falcon are wildcard pieces; consider all their moves legal */ /* (perhaps we should disallow moves that obviously leave us in check?) */ @@ -1830,7 +1867,7 @@ LegalityTest (Board board, int flags, int rf, int ff, int rt, int ft, int promoC if(cl.kind != NormalMove || promoChar == NULLCHAR || promoChar == '=') return cl.kind; if(promoChar != '+') return CharToPiece(promoChar) == EmptySquare ? ImpossibleMove : IllegalMove; - if(PieceToChar(CHUPROMOTED board[rf][ff]) != '+') { + if(PieceToChar(CHUPROMOTED(board[rf][ff])) != '+') { if(PieceToChar(CHUPROMOTED (board[rf][ff] < BlackPawn ? WhitePawn : BlackPawn)) != '.') return ImpossibleMove; } @@ -1877,7 +1914,7 @@ if(appData.debugMode)fprintf(debugFP,"SHOGI promoChar = %c\n", promoChar ? promo // 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; + 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) { @@ -1999,7 +2036,7 @@ DisambiguateCallback (Board board, int flags, ChessMove kind, int rf, int ff, in if ((cl->pieceIn == EmptySquare || cl->pieceIn == board[rf][ff] || PieceToChar(board[rf][ff]) == '~' - && cl->pieceIn == (ChessSquare)(DEMOTED board[rf][ff]) + && cl->pieceIn == (ChessSquare)(DEMOTED(board[rf][ff])) ) && (cl->rfIn == -1 || cl->rfIn == rf) && (cl->ffIn == -1 || cl->ffIn == ff) && @@ -2155,7 +2192,7 @@ Disambiguate (Board board, int flags, DisambiguateClosure *closure) 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) != '+') + 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; @@ -2200,7 +2237,7 @@ CoordsToAlgebraicCallback (Board board, int flags, ChessMove kind, int rf, int f if ((rt == cl->rt && ft == cl->ft || rt == rf && ft == ff) && // [HGM] null move matches any toSquare (board[rf][ff] == cl->piece || PieceToChar(board[rf][ff]) == '~' && - (ChessSquare) (DEMOTED board[rf][ff]) == cl->piece) + (ChessSquare) (DEMOTED(board[rf][ff])) == cl->piece) ) { if (rf == cl->rf) { if (ff == cl->ff) { @@ -2244,7 +2281,7 @@ CoordsToAlgebraic (Board board, int flags, int rf, int ff, int rt, int ft, int p if (promoChar == 'x') promoChar = NULLCHAR; piece = board[rf][ff]; - if(PieceToChar(piece)=='~') piece = (ChessSquare)(DEMOTED piece); + if(PieceToChar(piece)=='~') piece = (ChessSquare)(DEMOTED(piece)); switch (piece) { case WhitePawn: @@ -2336,13 +2373,13 @@ CoordsToAlgebraic (Board board, int flags, int rf, int ff, int rt, int ft, int p cl.kind = IllegalMove; cl.rank = cl.file = cl.either = 0; c = PieceToChar(piece) ; - GenLegal(board, flags, CoordsToAlgebraicCallback, (VOIDSTAR) &cl, c!='~' ? piece : (DEMOTED piece)); // [HGM] speed + GenLegal(board, flags, CoordsToAlgebraicCallback, (VOIDSTAR) &cl, c!='~' ? piece : (DEMOTED(piece))); // [HGM] speed if (cl.kind == IllegalMove && !(flags&F_IGNORE_CHECK)) { /* Generate pretty moves for moving into check, but still return IllegalMove. */ - GenLegal(board, flags|F_IGNORE_CHECK, CoordsToAlgebraicCallback, (VOIDSTAR) &cl, c!='~' ? piece : (DEMOTED piece)); + GenLegal(board, flags|F_IGNORE_CHECK, CoordsToAlgebraicCallback, (VOIDSTAR) &cl, c!='~' ? piece : (DEMOTED(piece))); if (cl.kind == IllegalMove) break; cl.kind = IllegalMove; } @@ -2354,7 +2391,7 @@ CoordsToAlgebraic (Board board, int flags, int rf, int ff, int rt, int ft, int p */ if( c == '~' || c == '+') { /* [HGM] print nonexistent piece as its demoted version */ - piece = (ChessSquare) (DEMOTED piece - 11*(gameInfo.variant == VariantChu)); + piece = (ChessSquare) (CHUDEMOTED(piece)); } if(c=='+') *outp++ = c; *outp++ = ToUpper(PieceToChar(piece)); @@ -2412,7 +2449,10 @@ CoordsToAlgebraic (Board board, int flags, int rf, int ff, int rt, int ft, int p int r, f; for(r=0; r +#include #include #include #include "common.h" @@ -380,6 +381,7 @@ char PromoSuffix (char **p) { char *start = *p; + if(**p == ' ') return NULLCHAR; // common case, test explicitly for speed if(**p == 'e' && (Match("ep", p) || Match("e.p.", p))) { *p = start; return NULLCHAR; } // non-compliant e.p. suffix is no promoChar! if(**p == '+' && IS_SHOGI(gameInfo.variant)) { (*p)++; return '+'; } if(**p == '=' || (gameInfo.variant == VariantSChess) && **p == '/') (*p)++; // optional = (or / for Seirawan gating) @@ -494,7 +496,7 @@ NextUnit (char **p) if(piece) { cl.pieceIn = CharToPiece(wom ? piece : piece + 'a' - 'A'); if(cl.pieceIn == EmptySquare) return ImpossibleMove; // non-existent piece - if(promoted) cl.pieceIn = (ChessSquare) (CHUPROMOTED 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; @@ -526,11 +528,11 @@ NextUnit (char **p) 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(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 + 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); @@ -619,12 +621,12 @@ badMove:// we failed to find algebraic move if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ if (wom) { - rf = 0; - rt = 0; + rf = castlingRank[0]; + rt = castlingRank[0]; king = WhiteKing; } else { - rf = BOARD_HEIGHT-1; - rt = BOARD_HEIGHT-1; + rf = castlingRank[3]; + rt = castlingRank[3]; king = BlackKing; } ff = (BOARD_WIDTH-1)>>1; // this would be d-file @@ -632,8 +634,12 @@ badMove:// we failed to find algebraic move /* ICS wild castling */ ft = castlingType == 1 ? BOARD_LEFT+1 : (gameInfo.variant == VariantJanus ? BOARD_RGHT-2 : BOARD_RGHT-3); } else { + char *q; ff = BOARD_WIDTH>>1; // e-file ft = castlingType == 1 ? BOARD_RGHT-2 : BOARD_LEFT+2; + if(pieceDesc[king] && (q = strchr(pieceDesc[king], 'O'))) { // redefined to non-default King stride + ft = (castlingType == 1 ? ff + atoi(q+1) : ff - atoi(q+1)); + } } if(PosFlags(0) & F_FRC_TYPE_CASTLING) { if (wom) { diff --git a/parser.h b/parser.h index 1892fbe..9ffacc9 100644 --- a/parser.h +++ b/parser.h @@ -63,4 +63,6 @@ extern int yyskipmoves; /* If TRUE, all moves are reported as AmbiguousMove extern char *yy_text; /* Needed because yytext can be either a char[] or a (non-constant) char* */ extern int yyoffset P((void)); -extern signed char initialRights[BOARD_FILES]; +extern unsigned char initialRights[BOARD_FILES]; +extern signed char castlingRank[BOARD_FILES]; + diff --git a/pgntags.c b/pgntags.c index b40c198..9833d10 100644 --- a/pgntags.c +++ b/pgntags.c @@ -119,9 +119,7 @@ ParsePGNTag (char *tag, GameInfo *gameInfo) if(*value && strcmp(value, engineVariant)) // keep current engine-defined variant if it matches gameInfo->variant = StringToVariant(value); } else if (StrCaseCmp(name, "VariantMen") == 0) { - /* for now ignore this tag, as we have no method yet */ - /* for assigning the pieces to XBoard pictograms */ - success = TRUE; + success = LoadPieceDesc(value); } else if (StrCaseCmp(name, PGN_OUT_OF_BOOK) == 0) { /* [AS] Out of book annotation */ success = StrSavePtr(value, &gameInfo->outOfBook) != NULL; diff --git a/svg/BlackAxe.svg b/svg/BlackAxe.svg new file mode 100644 index 0000000..f0bdb80 --- /dev/null +++ b/svg/BlackAxe.svg @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/svg/BlackButterfly.svg b/svg/BlackButterfly.svg new file mode 100644 index 0000000..8045abf --- /dev/null +++ b/svg/BlackButterfly.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/svg/BlackCamel.svg b/svg/BlackCamel.svg new file mode 100644 index 0000000..cc2b4b2 --- /dev/null +++ b/svg/BlackCamel.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/svg/BlackCopper.svg b/svg/BlackCopper.svg new file mode 100644 index 0000000..f5bb595 --- /dev/null +++ b/svg/BlackCopper.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/svg/BlackCub.svg b/svg/BlackCub.svg new file mode 100644 index 0000000..f0b6324 --- /dev/null +++ b/svg/BlackCub.svg @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/svg/BlackDragon.svg b/svg/BlackDragon.svg new file mode 100644 index 0000000..aa84c5b --- /dev/null +++ b/svg/BlackDragon.svg @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/svg/BlackDuck.svg b/svg/BlackDuck.svg new file mode 100644 index 0000000..99e729b --- /dev/null +++ b/svg/BlackDuck.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/svg/BlackFlag.svg b/svg/BlackFlag.svg new file mode 100644 index 0000000..16953d0 --- /dev/null +++ b/svg/BlackFlag.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/svg/BlackGnu.svg b/svg/BlackGnu.svg new file mode 100644 index 0000000..c87489c --- /dev/null +++ b/svg/BlackGnu.svg @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/svg/BlackHat.svg b/svg/BlackHat.svg new file mode 100644 index 0000000..b00a0af --- /dev/null +++ b/svg/BlackHat.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/svg/BlackIron.svg b/svg/BlackIron.svg new file mode 100644 index 0000000..6b42471 --- /dev/null +++ b/svg/BlackIron.svg @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/svg/BlackLShield.svg b/svg/BlackLShield.svg new file mode 100644 index 0000000..630921f --- /dev/null +++ b/svg/BlackLShield.svg @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/svg/BlackLeft.svg b/svg/BlackLeft.svg new file mode 100644 index 0000000..8e3a64a --- /dev/null +++ b/svg/BlackLeft.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/svg/BlackPegasus.svg b/svg/BlackPegasus.svg new file mode 100644 index 0000000..1740e67 --- /dev/null +++ b/svg/BlackPegasus.svg @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/svg/BlackRShield.svg b/svg/BlackRShield.svg new file mode 100644 index 0000000..eb95edb --- /dev/null +++ b/svg/BlackRShield.svg @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/svg/BlackRight.svg b/svg/BlackRight.svg new file mode 100644 index 0000000..e33fa9b --- /dev/null +++ b/svg/BlackRight.svg @@ -0,0 +1,172 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/svg/BlackTower.svg b/svg/BlackTower.svg new file mode 100644 index 0000000..e1fd144 --- /dev/null +++ b/svg/BlackTower.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/svg/BlackUnicorn.svg b/svg/BlackUnicorn.svg index 22933d7..bdd8ade 100644 --- a/svg/BlackUnicorn.svg +++ b/svg/BlackUnicorn.svg @@ -7,13 +7,44 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.0" width="100" height="100" - id="svg2833"> + id="svg2833" + inkscape:version="0.47 r22583" + sodipodi:docname="BlackUnicorn.svg"> + + id="defs2835"> + + @@ -27,7 +58,7 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/svg/BlackWizard.svg b/svg/BlackWizard.svg new file mode 100644 index 0000000..c872615 --- /dev/null +++ b/svg/BlackWizard.svg @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/svg/BlackWolf.svg b/svg/BlackWolf.svg new file mode 100644 index 0000000..8161662 --- /dev/null +++ b/svg/BlackWolf.svg @@ -0,0 +1,86 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/svg/BlackZebra.svg b/svg/BlackZebra.svg new file mode 100644 index 0000000..ec780ba --- /dev/null +++ b/svg/BlackZebra.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/svg/WhiteAxe.svg b/svg/WhiteAxe.svg new file mode 100644 index 0000000..d0739a4 --- /dev/null +++ b/svg/WhiteAxe.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/svg/WhiteButterfly.svg b/svg/WhiteButterfly.svg new file mode 100644 index 0000000..83b686f --- /dev/null +++ b/svg/WhiteButterfly.svg @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/svg/WhiteCamel.svg b/svg/WhiteCamel.svg new file mode 100644 index 0000000..01281b8 --- /dev/null +++ b/svg/WhiteCamel.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/svg/WhiteClaw.svg b/svg/WhiteClaw.svg index 99c4a68..238623d 100644 --- a/svg/WhiteClaw.svg +++ b/svg/WhiteClaw.svg @@ -14,7 +14,7 @@ id="svg2" version="1.1" inkscape:version="0.47 r22583" - sodipodi:docname="New document 1"> + sodipodi:docname="WhiteClaw.svg"> @@ -100,7 +100,7 @@ image/svg+xml - + @@ -110,32 +110,32 @@ id="layer1" transform="translate(0,-952.36218)"> + id="g3610"> + style="fill:#ffffcc;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + style="fill:#ffffcc;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + style="fill:#ffffcc;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + style="fill:#ffffcc;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + style="fill:#ffffcc;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/svg/WhiteCub.svg b/svg/WhiteCub.svg new file mode 100644 index 0000000..605b9ff --- /dev/null +++ b/svg/WhiteCub.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/svg/WhiteDolphin.svg b/svg/WhiteDolphin.svg index c01d573..c990494 100644 --- a/svg/WhiteDolphin.svg +++ b/svg/WhiteDolphin.svg @@ -48,14 +48,14 @@ inkscape:pageshadow="2" inkscape:zoom="4.5167464" inkscape:cx="49.318911" - inkscape:cy="45.354981" + inkscape:cy="67.128756" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" - inkscape:window-width="1280" - inkscape:window-height="726" + inkscape:window-width="1366" + inkscape:window-height="588" inkscape:window-x="0" - inkscape:window-y="25" + inkscape:window-y="24" inkscape:window-maximized="1" /> @@ -75,31 +75,30 @@ id="layer1" transform="translate(0,-952.36218)"> + id="g3597"> + d="m 25.422502,1009.2837 3.64721,-5.9885 4.085169,-6.56537 5.708527,-7.19404 4.800386,-5.25188 5.245237,-4.27474 5.082411,-3.5041 1.946123,-0.99064 1.6641,-2.73841 0.962415,-3.52748 -0.632865,-2.14233 -0.672599,-2.98178 -0.538857,-1.55972 1.891848,-0.73376 2.890098,0.70676 3.063572,2.96828 1.833675,3.65165 1.576843,3.8397 0.376031,2.33037 5.103703,2.56023 5.548553,3.53738 3.967814,3.8262 4.264383,4.47761 3.345595,4.71602 2.184518,4.04622 2.111695,4.21583 1.08172,4.303 0.394076,2.7853 -0.774149,3.9553 -1.327296,3.8618 0.358095,6.9663 0.220603,4.9517 -2.02898,1.0799 -1.768755,-2.6475 -3.591278,-8.7269 -2.55102,-1.9435 -2.810742,-3.6758 -2.991865,-3.2423 -0.142145,2.7315 c -1.121073,2.1006 -0.689228,2.1788 -1.581243,2.8704 l -2.69519,1.7911 -2.936977,0.2938 -3.51896,-1.444 2.889234,-3.0578 1.147291,-2.2168 0.26874,-3.0564 -1.420295,-3.2124 -5.299117,-2.2551 -6.091307,-0.9685 -7.726322,-0.423 -6.525511,1.0865 -5.838372,2.972 -5.798638,3.8114 -4.543551,5.0637 -4.138435,5.2015 5.420085,1.0098 4.07875,2.9434 3.376311,4.809 -1.331302,3.3423 -5.333223,-3.9007 -5.221783,-1.6086 -5.146325,0.3486 0.115952,-3.7133 -3.793479,4.6365 -3.891237,0.1834 -4.328943,0.8646 -5.5362864,2.5972 -0.4024811,-1.0225 2.2487192,-3.6566 4.5144665,-3.314 4.7424668,-2.0465 4.062579,-1.1241 3.564969,-4.871 3.145565,-5.7562 z" + style="fill:#ffffcc;stroke:#000000;stroke-width:2.13330363999999983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + d="m 73.483788,1000.6302 -4.875955,-0.5555 -3.848618,-1.30775 -4.184918,-2.79866 -3.765255,-3.75745 -3.088762,-4.90406 6.521615,3.04205 3.566594,-0.43998 3.552051,0.65635" + style="fill:none;stroke:#000000;stroke-width:2.13330364;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 83.218266,1002.246 1.146534,1.7662" + style="fill:none;stroke:#000000;stroke-width:2.13330364;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 56.140124,975.58326 5.147332,-0.72881 3.917436,-0.0454 2.8901,0.70675" + style="fill:none;stroke:#000000;stroke-width:2.13330364;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 71.620393,1005.0426 7.129947,4.6075" + style="fill:none;stroke:#000000;stroke-width:2.13330364;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> diff --git a/svg/WhiteDragon.svg b/svg/WhiteDragon.svg new file mode 100644 index 0000000..69c48eb --- /dev/null +++ b/svg/WhiteDragon.svg @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/svg/WhiteDuck.svg b/svg/WhiteDuck.svg new file mode 100644 index 0000000..f19e88a --- /dev/null +++ b/svg/WhiteDuck.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/svg/WhiteFlag.svg b/svg/WhiteFlag.svg new file mode 100644 index 0000000..bf734b1 --- /dev/null +++ b/svg/WhiteFlag.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/svg/WhiteGnu.svg b/svg/WhiteGnu.svg new file mode 100644 index 0000000..878c5d0 --- /dev/null +++ b/svg/WhiteGnu.svg @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/svg/WhiteHSword.svg b/svg/WhiteHSword.svg index 90df377..e835915 100644 --- a/svg/WhiteHSword.svg +++ b/svg/WhiteHSword.svg @@ -53,9 +53,9 @@ inkscape:current-layer="layer1" showgrid="false" inkscape:window-width="792" - inkscape:window-height="655" + inkscape:window-height="583" inkscape:window-x="62" - inkscape:window-y="25" + inkscape:window-y="24" inkscape:window-maximized="0" /> @@ -103,5 +103,20 @@ d="m -282.35544,1041.779 -52.24134,0" style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + + + diff --git a/svg/WhiteHat.svg b/svg/WhiteHat.svg new file mode 100644 index 0000000..362c03b --- /dev/null +++ b/svg/WhiteHat.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/svg/WhiteIron.svg b/svg/WhiteIron.svg new file mode 100644 index 0000000..7da0d27 --- /dev/null +++ b/svg/WhiteIron.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/svg/WhiteLShield.svg b/svg/WhiteLShield.svg new file mode 100644 index 0000000..b37f88f --- /dev/null +++ b/svg/WhiteLShield.svg @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/svg/WhiteLeft.svg b/svg/WhiteLeft.svg new file mode 100644 index 0000000..4c8e7df --- /dev/null +++ b/svg/WhiteLeft.svg @@ -0,0 +1,185 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/svg/WhiteLeopard.svg b/svg/WhiteLeopard.svg index 62e318c..069f384 100644 --- a/svg/WhiteLeopard.svg +++ b/svg/WhiteLeopard.svg @@ -14,7 +14,7 @@ id="svg2" version="1.1" inkscape:version="0.47 r22583" - sodipodi:docname="WhiteKnight.svg"> + sodipodi:docname="WhiteLeopard.svg"> @@ -75,95 +75,94 @@ id="layer1" transform="translate(366.71429,-981.93367)"> + id="g3625"> + d="m -316.1258,1002.1094 10.04545,1.3788 7.87879,3.7425 1.57575,-3.7425 3.34849,-3.54543 3.15151,-1.18182 4.92425,-0.39393 2.36364,2.75758 0.39394,4.5303 -1.57577,3.7424 -1.57575,2.7576 -3.15152,1.1818 1.37879,2.9546 -0.98485,2.7575 -1.18182,1.3789 1.37879,5.909 0.59091,4.5303 -0.39394,5.3182 -1.57576,4.9242 -2.95454,5.5152 -3.93939,3.5454 -3.34849,0.197 -3.54545,2.1666 -0.98485,4.9243 -1.37879,6.697 -3.74242,3.9394 -4.13636,1.5757 -4.33334,-0.1969 -5.12121,-3.1516 -2.36363,-2.5605 0.39394,-2.9546 -1.77273,-3.5455 -1.77273,-4.1363 -0.78788,-2.3637 -4.13636,-3.9394 -4.33334,-2.7575 -4.13636,-5.9091 0,-7.2879 0.78788,-5.909 1.37879,-5.1213 -2.56061,-3.1515 -0.19697,-5.3181 -2.36363,-3.1516 -0.98485,-4.1364 1.57575,-4.92421 1.9697,-2.75757 1.77273,0.59091 2.95455,2.75758 3.15151,3.74239 0.98485,2.3636 2.56061,0.591 4.13636,-2.7576 5.71212,-1.1818 4.92424,-0.394 z" + style="fill:#ffffcc;stroke:#000000;stroke-width:1.72730826999999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + d="m -300.17125,1022.9882 -5.75488,0.2657 -1.33603,0.7451 -4.51355,4.3501 3.61419,-1.7987 4.00812,0.4628 2.09794,-0.8734 0.70238,-2.7577 1.18183,-0.3939 z" + style="fill:#000000;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -333.26216,1022.5943 5.71212,0.4627 2.40638,1.1818 1.92695,2.8858 -2.64609,0.085 -2.67209,0.042 -1.74673,-0.8994 -0.89937,-1.3528 -0.30844,-1.8154 1.43075,0.1542 -3.20348,-0.7451 z" + style="fill:#000000;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -316.95642,1039.6024 3.23701,-1.0276 1.42153,0.9421 -1.37879,3.2538 -1.85822,2.3637 -2.08118,0.042 -2.18342,-2.2949 -1.53302,-3.3485 1.0276,-1.0276 3.34849,1.0964 z" + style="fill:#000000;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -316.23728,1047.5927 3.03081,0.8473 3.60519,0.8187 3.12699,-0.01 c 0.63924,-0.493 1.12426,-0.1508 1.45505,-0.548 l -1.43829,6.7991 -0.63366,2.3896 -0.74513,3.7164 -1.71322,1.3361 -3.382,0.3939 -5.09523,0.086 -2.5606,-0.8307 -1.56652,-1.6445 -1.01085,-2.3544 -1.19857,-3.3913 -2.38963,-5.2753 1.96047,0.2396 4.53031,-1.3787 4.02488,-1.1986 0,-10e-5 0,10e-5 z" + style="fill:#000000;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -306.84224,1049.5624 -2.8523,8.6164 -1.49026,-9.276 4.65101,0.8143 -0.30845,-0.1547 z" + style="fill:#ffffff;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -320.16745,1049.0309 -1.84145,8.6424 -1.91019,-2.9897 -0.70239,-4.4021 4.45403,-1.2506 z" + style="fill:#ffffff;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -309.83953,1062.6907 c 1.06225,-0.731 1.71365,-1.5642 1.79871,-2.3469 l 0.92536,-4.4709 c -1.03934,0.8994 -1.92445,1.953 -2.96378,2.8524 l -1.20781,0.5054 c -0.78908,-0.7043 -2.7455,-0.6155 -2.06442,-1.6873 l -0.47942,3.1348 1.44752,2.2354 2.54384,-0.2229 z" + style="fill:#ffffff;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -317.17015,1057.2777 -2.10716,1.559 -0.78789,0 -2.43236,-1.756 -0.0687,3.0921 1.86745,2.3041 2.36364,0.6336 1.71322,-1.9268 -0.54816,-3.906 z" + style="fill:#ffffff;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -295.24702,1009.0034 1.42154,-3.999 3.27975,-3.4004 4.40207,-0.069 0.9421,2.9378 -1.05358,3.5881 -1.22456,2.2095 -2.64611,0.8994 -3.34848,-0.197 -1.77273,-1.9697 z" + style="fill:#000000;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -341.14095,1000.3367 2.99729,2.6721 1.77273,2.4231 0.54816,3.5715 -2.75757,1.5757 -2.40639,-1.6444 -2.05518,-3.2798 0,-2.3804 1.07033,-2.6293 0.83063,-0.3085 z" + style="fill:#000000;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -304.30762,1036.1852 12.40909,-9.2576 10.04545,-6.303 5.71212,-4.5303" + style="fill:none;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -304.11065,1038.9428 12.21212,-3.5455 8.66667,-0.9848 9.06059,0 2.16668,0.5909" + style="fill:none;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -303.32277,1042.4882 8.86363,-2.3636 8.86364,-0.7879 5.90909,0.5909 8.66666,1.7727" + style="fill:none;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -304.30762,1044.8519 8.66666,0.5909 7.28788,3.3485" + style="fill:none;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -330.11064,1037.7609 -8.86364,-4.3333 -6.69697,-2.5606 -7.48485,-1.1818 -8.66666,-0.394" + style="fill:none;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -330.50458,1040.9125 -12.01516,-1.7727 -7.87879,0.1969 -10.63636,3.3485 -7.87878,3.7424" + style="fill:none;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -330.70156,1044.064 -6.30302,0.7879 -8.66667,3.1515 -7.48485,3.9393 c 0,0 -3.74243,3.3485 -4.5303,3.1516" + style="fill:none;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m -326.5652,1046.4276 -5.71211,2.3637 -5.9091,3.5454 -4.13636,3.9394" + style="fill:none;stroke:#000000;stroke-width:1.72730827;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> diff --git a/svg/WhiteLion.svg b/svg/WhiteLion.svg index e5af5af..e959c70 100644 --- a/svg/WhiteLion.svg +++ b/svg/WhiteLion.svg @@ -14,7 +14,7 @@ id="svg3738" version="1.1" inkscape:version="0.47 r22583" - sodipodi:docname="WhiteQueen.svg"> + sodipodi:docname="WhiteLion.svg"> + id="g3626"> + d="m 19.658729,988.24705 2.662046,-6.65512 -1.774696,-3.99306 5.767763,-7.98613 8.873485,-6.21144 11.979202,-0.44368 2.218371,-7.09878 7.542461,0 7.098787,3.99306 10.648179,1.77471 -1.331021,5.76775 11.535527,3.10572 -1.331022,4.43674 6.655112,6.65511 -2.21837,2.21838 7.098788,10.64818 -2.662046,2.66204 4.436742,9.76077 -0.443675,6.2115 0,11.0919 -6.211439,-7.9862 0.443675,16.4159 -2.218371,3.1058 -6.211439,-5.7677 0,8.8734 -4.880415,3.5494 0.887348,-9.7609 -7.098787,11.9793 -3.993067,-4.8805 -4.436742,10.2046 -10.204506,1.331 -9.760832,-1.331 -8.42981,-6.6551 -4.43674,-2.2185 -10.648181,6.6552 -0.443675,-12.4229 -2.21837,-7.5424 -3.105719,2.662 -4.8804165,-3.9931 0.8873482,-8.8734 -2.2183708,-3.9931 0.8873485,-5.3241 -4.8804161,-3.5494 1.3310226,-3.5494 15.0849211,-12.86655 z" + style="fill:#ffffcc;stroke:#000000;stroke-width:1.94107449000000010;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + d="m 37.849371,990.46542 -8.42981,-1.77469 3.549395,1.33102 -5.324091,4.43674 5.324091,-2.66205 3.743499,0.19411 1.136916,-1.52513 z" + style="fill:#000000;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 59.589406,989.1344 0,-6.21144 -0.443675,-7.54246 -1.774697,-4.88042 -3.105719,-2.21837 -6.655113,0.88735 -3.549392,3.99307 -1.774696,3.54939" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 55.152664,985.14134 -0.887349,-4.43675 -2.662044,-3.54939 -3.105719,0 -1.774698,3.99306 0,0 0.887348,0.44367 -0.887348,-0.44367" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 14.334641,1004.2193 0,0 z" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="M 13.128401,1004.8154 2.7991111,1003.332" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 8.1232014,1010.4308 2.2183706,-2.6621 2.21837,-0.4436 0.443676,-2.6621 0,0" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 8.1232014,1017.5296 3.1057196,-0.8874 3.549393,3.9931 4.436742,0 6.211438,2.2184 4.880416,0.4436 0.443674,0 0,0.4437" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 44.06081,1003.7756 -0.443675,8.4299 -3.549393,6.2114 -0.887348,7.0987 -5.32409,6.2115 -3.993067,6.6552" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 72.455957,998.00788 -3.10572,13.31022 -5.767764,10.6482 -6.655112,8.4298 -4.880416,13.3102" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 66.591138,1040.0876 -0.34662,-7.0294 3.993069,-8.8735 4.43674,-9.7608 2.218371,-10.6483 -0.443673,-7.09874" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 79.998418,997.12053 0,7.09877 0,5.3241 0.887347,7.5425 -4.43674,6.6551 -2.662046,5.3241 -1.331022,6.2114" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 72.012283,978.04254 6.655113,7.0988 7.986135,5.76775 -0.09705,20.35351 3.091854,3.9377" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 72.012283,972.71846 7.542461,0.88734 4.880416,2.66205 0,0" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 20.546079,987.94202 11.535527,-8.12478 4.436742,-2.66204" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 16.040012,1011.3181 c 8.318891,-1.7331 7.972271,-1.7331 7.972271,-1.7331" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 16.733253,1014.091 c 11.438475,-0.3466 11.438475,-0.3466 11.438475,-0.3466" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + d="m 17.079873,1016.5174 c 10.745234,4.1594 10.745234,4.1594 10.745234,4.1594" + style="fill:none;stroke:#000000;stroke-width:1.94107449;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> diff --git a/svg/WhitePegasus.svg b/svg/WhitePegasus.svg new file mode 100644 index 0000000..b0175ef --- /dev/null +++ b/svg/WhitePegasus.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/svg/WhitePromoHSword.svg b/svg/WhitePromoHSword.svg index 09fe10a..5ff2149 100644 --- a/svg/WhitePromoHSword.svg +++ b/svg/WhitePromoHSword.svg @@ -14,7 +14,7 @@ id="svg2" version="1.1" inkscape:version="0.47 r22583" - sodipodi:docname="WhiteHSword.svg"> + sodipodi:docname="WhitePromoHSword.svg"> @@ -65,7 +65,7 @@ image/svg+xml - + @@ -75,12 +75,12 @@ id="layer1" transform="translate(366.71429,-981.93367)"> + id="g3593"> + style="fill:#ffffcc;stroke:#000000;stroke-width:2.12071394999999985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + style="fill:#ffffcc;stroke:#000000;stroke-width:2.12071394999999985;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + style="fill:#ffffcc;stroke:#000000;stroke-width:2.12071394999999985;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> diff --git a/svg/WhitePromoSword.svg b/svg/WhitePromoSword.svg index cefeb40..f91d252 100644 --- a/svg/WhitePromoSword.svg +++ b/svg/WhitePromoSword.svg @@ -14,7 +14,7 @@ id="svg2" version="1.1" inkscape:version="0.47 r22583" - sodipodi:docname="WhiteSword.svg"> + sodipodi:docname="WhitePromoSword.svg"> @@ -65,7 +65,7 @@ image/svg+xml - + @@ -75,26 +75,26 @@ id="layer1" transform="translate(366.71429,-981.93367)"> + id="g3593"> + style="fill:#ffffcc;stroke:#000000;stroke-width:2.12079834999999983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + style="fill:#ffffcc;stroke:#000000;stroke-width:2.12079834999999983;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + style="fill:#ffffcc;stroke:#000000;stroke-width:2.12079834999999983;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> diff --git a/svg/WhiteRShield.svg b/svg/WhiteRShield.svg new file mode 100644 index 0000000..1dbf7d0 --- /dev/null +++ b/svg/WhiteRShield.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/svg/WhiteRight.svg b/svg/WhiteRight.svg new file mode 100644 index 0000000..a0e9e25 --- /dev/null +++ b/svg/WhiteRight.svg @@ -0,0 +1,186 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/svg/WhiteSword.svg b/svg/WhiteSword.svg index cdcc108..bbb707f 100644 --- a/svg/WhiteSword.svg +++ b/svg/WhiteSword.svg @@ -48,14 +48,14 @@ inkscape:pageshadow="2" inkscape:zoom="5.6" inkscape:cx="35.248447" - inkscape:cy="51.239847" + inkscape:cy="148.73641" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" inkscape:window-width="792" - inkscape:window-height="655" + inkscape:window-height="583" inkscape:window-x="62" - inkscape:window-y="25" + inkscape:window-y="24" inkscape:window-maximized="0" /> @@ -75,31 +75,30 @@ id="layer1" transform="translate(366.71429,-981.93367)"> + id="g3595"> + d="m -316.26765,986.20384 -10.45897,10.32341 -0.20079,54.35055 21.31911,0 0,-53.89325 -10.65935,-10.78071 z" + style="fill:#ffffcc;stroke:#000000;stroke-width:2.12079834999999983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + style="fill:#ffffcc;stroke:#000000;stroke-width:2.12079834999999983;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + style="fill:#ffffcc;stroke:#000000;stroke-width:2.12079834999999983;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" /> + d="m -316.26786,998.13446 0,52.24134" + style="fill:none;stroke:#000000;stroke-width:2.12079835;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> diff --git a/svg/WhiteTower.svg b/svg/WhiteTower.svg new file mode 100644 index 0000000..07c8095 --- /dev/null +++ b/svg/WhiteTower.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/svg/WhiteUnicorn.svg b/svg/WhiteUnicorn.svg index f386f0d..0327395 100644 --- a/svg/WhiteUnicorn.svg +++ b/svg/WhiteUnicorn.svg @@ -7,13 +7,44 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.0" width="100" height="100" - id="svg2833"> + id="svg2833" + inkscape:version="0.47 r22583" + sodipodi:docname="WhiteUnicorn.svg"> + + id="defs2835"> + + @@ -27,7 +58,7 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/svg/WhiteWizard.svg b/svg/WhiteWizard.svg new file mode 100644 index 0000000..bc1c674 --- /dev/null +++ b/svg/WhiteWizard.svg @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/svg/WhiteWolf.svg b/svg/WhiteWolf.svg new file mode 100644 index 0000000..7334c85 --- /dev/null +++ b/svg/WhiteWolf.svg @@ -0,0 +1,71 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/svg/WhiteZebra.svg b/svg/WhiteZebra.svg new file mode 100644 index 0000000..6d3e626 --- /dev/null +++ b/svg/WhiteZebra.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/winboard/bitmaps/camel49o.bmp b/winboard/bitmaps/camel49o.bmp new file mode 100644 index 0000000..220d53b Binary files /dev/null and b/winboard/bitmaps/camel49o.bmp differ diff --git a/winboard/bitmaps/camel49s.bmp b/winboard/bitmaps/camel49s.bmp new file mode 100644 index 0000000..2a47e99 Binary files /dev/null and b/winboard/bitmaps/camel49s.bmp differ diff --git a/winboard/bitmaps/camel49w.bmp b/winboard/bitmaps/camel49w.bmp new file mode 100644 index 0000000..c9a0501 Binary files /dev/null and b/winboard/bitmaps/camel49w.bmp differ diff --git a/winboard/bitmaps/camel72o.bmp b/winboard/bitmaps/camel72o.bmp new file mode 100644 index 0000000..a2f4068 Binary files /dev/null and b/winboard/bitmaps/camel72o.bmp differ diff --git a/winboard/bitmaps/camel72s.bmp b/winboard/bitmaps/camel72s.bmp new file mode 100644 index 0000000..fe26272 Binary files /dev/null and b/winboard/bitmaps/camel72s.bmp differ diff --git a/winboard/bitmaps/camel72w.bmp b/winboard/bitmaps/camel72w.bmp new file mode 100644 index 0000000..cb2f223 Binary files /dev/null and b/winboard/bitmaps/camel72w.bmp differ diff --git a/winboard/bitmaps/wolf49o.bmp b/winboard/bitmaps/wolf49o.bmp new file mode 100644 index 0000000..efc9df9 Binary files /dev/null and b/winboard/bitmaps/wolf49o.bmp differ diff --git a/winboard/bitmaps/wolf49s.bmp b/winboard/bitmaps/wolf49s.bmp new file mode 100644 index 0000000..4797b18 Binary files /dev/null and b/winboard/bitmaps/wolf49s.bmp differ diff --git a/winboard/bitmaps/wolf49w.bmp b/winboard/bitmaps/wolf49w.bmp new file mode 100644 index 0000000..9c00fbe Binary files /dev/null and b/winboard/bitmaps/wolf49w.bmp differ diff --git a/winboard/bitmaps/wolf72o.bmp b/winboard/bitmaps/wolf72o.bmp new file mode 100644 index 0000000..4b6bb05 Binary files /dev/null and b/winboard/bitmaps/wolf72o.bmp differ diff --git a/winboard/bitmaps/wolf72s.bmp b/winboard/bitmaps/wolf72s.bmp new file mode 100644 index 0000000..2e5c6ce Binary files /dev/null and b/winboard/bitmaps/wolf72s.bmp differ diff --git a/winboard/bitmaps/wolf72w.bmp b/winboard/bitmaps/wolf72w.bmp new file mode 100644 index 0000000..a0858ef Binary files /dev/null and b/winboard/bitmaps/wolf72w.bmp differ diff --git a/winboard/bitmaps/zebra49o.bmp b/winboard/bitmaps/zebra49o.bmp new file mode 100644 index 0000000..0608b95 Binary files /dev/null and b/winboard/bitmaps/zebra49o.bmp differ diff --git a/winboard/bitmaps/zebra49s.bmp b/winboard/bitmaps/zebra49s.bmp new file mode 100644 index 0000000..303533a Binary files /dev/null and b/winboard/bitmaps/zebra49s.bmp differ diff --git a/winboard/bitmaps/zebra72o.bmp b/winboard/bitmaps/zebra72o.bmp new file mode 100644 index 0000000..963ecb2 Binary files /dev/null and b/winboard/bitmaps/zebra72o.bmp differ diff --git a/winboard/bitmaps/zebra72s.bmp b/winboard/bitmaps/zebra72s.bmp new file mode 100644 index 0000000..6446c77 Binary files /dev/null and b/winboard/bitmaps/zebra72s.bmp differ diff --git a/winboard/defaults.h b/winboard/defaults.h index 10c2cd1..ce6ed8e 100644 --- a/winboard/defaults.h +++ b/winboard/defaults.h @@ -57,8 +57,8 @@ #define GAME_FILT "Game files (*.pgn,*.gam)\0*.pgn;*.gam\0All files (*.*)\0*.*\0" #define DIAGRAM_FILT "bitmap files (*.bmp)\0*.bmp\0All files (*.*)\0*.*\0" #define SOUND_FILT "Wave files (*.wav)\0*.wav\0All files (*.*)\0*.*\0" -#define OUTER_MARGIN (tinyLayout ? 0 : 4) -#define INNER_MARGIN (tinyLayout ? 0 : 2) +#define OUTER_MARGIN (tinyLayout == 2 ? 0 : 4) +#define INNER_MARGIN (tinyLayout == 2 ? 0 : 2) #define MESSAGE_LINE_LEFTMARGIN 2 #define MESSAGE_TEXT_MAX 256 /*#define COLOR_ECHOOFF RGB(192,192,192)*/ diff --git a/winboard/jaws.c b/winboard/jaws.c index f8a5c9a..aa843ad 100644 --- a/winboard/jaws.c +++ b/winboard/jaws.c @@ -271,7 +271,7 @@ InitJAWS() AdaptMenu(); menuBarText[0][8] = menuBarText[0][7]; menuBarText[0][7] = "&JAWS"; - for(i=0; i<9; i++) menuBarText[1][i] = menuBarText[0][i]; + for(i=0; i<9; i++) menuBarText[2][i] = menuBarText[1][i] = menuBarText[0][i]; } hAccelJAWS = CreateAcceleratorTable(acceleratorsJAWS, 14); diff --git a/winboard/winboard.c b/winboard/winboard.c index 2183232..ca901bf 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -535,12 +535,12 @@ typedef struct { SizeInfo sizeInfo[] = { - { "tiny", 21, 0, 1, 1, 0, 0 }, - { "teeny", 25, 1, 1, 1, 0, 0 }, - { "dinky", 29, 1, 1, 1, 0, 0 }, - { "petite", 33, 1, 1, 1, 0, 0 }, - { "slim", 37, 2, 1, 0, 0, 0 }, - { "small", 40, 2, 1, 0, 0, 0 }, + { "tiny", 21, 0, 1, 2, 0, 0 }, + { "teeny", 25, 1, 1, 2, 0, 0 }, + { "dinky", 29, 1, 1, 2, 0, 0 }, + { "petite", 33, 1, 1, 2, 0, 0 }, + { "slim", 37, 2, 1, 1, 0, 0 }, + { "small", 40, 2, 1, 1, 0, 0 }, { "mediocre", 45, 2, 1, 0, 0, 0 }, { "middling", 49, 2, 0, 0, 0, 0 }, { "average", 54, 2, 0, 0, 0, 0 }, @@ -588,7 +588,7 @@ typedef struct { WNDPROC wndproc; } MyButtonDesc; -#define BUTTON_WIDTH (tinyLayout ? 16 : 32) +#define BUTTON_WIDTH (tinyLayout == 2 ? 16 : 32) #define N_BUTTONS 5 MyButtonDesc buttonDesc[N_BUTTONS] = @@ -602,8 +602,9 @@ MyButtonDesc buttonDesc[N_BUTTONS] = int tinyLayout = 0, smallLayout = 0; #define MENU_BAR_ITEMS 9 -char *menuBarText[2][MENU_BAR_ITEMS+1] = { +char *menuBarText[3][MENU_BAR_ITEMS+1] = { { N_("&File"), N_("&Edit"), N_("&View"), N_("&Mode"), N_("&Action"), N_("E&ngine"), N_("&Options"), N_("&Help"), NULL }, + { N_("&Fil"), N_("&Ed"), N_("&Vw"), N_("&Mod"), N_("&Act"), N_("E&ng"), N_("&Opt"), N_("&Hlp"), NULL }, { N_("&F"), N_("&E"), N_("&V"), N_("&M"), N_("&A"), N_("&N"), N_("&O"), N_("&H"), NULL }, }; @@ -1106,6 +1107,8 @@ InitGeometry() screenGeometry.bottom = screenGeometry.top + screenHeight; } +ChessProgramState broadcast; + BOOL InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) { @@ -1138,7 +1141,18 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) appData.ringBellAfterMoves = TRUE; } if (appData.debugMode) { - debugFP = fopen(appData.nameOfDebugFile, "w"); + char *c = appData.nameOfDebugFile; + if(strstr(c, "///") == c) { + broadcast.which = "broadcaster"; + broadcast.pr = NoProc; + broadcast.isr = NULL; + broadcast.program = c + 3; + broadcast.dir = "."; + broadcast.host = "localhost"; + StartChessProgram(&broadcast); + debugFP = (FILE*) _fdopen(_open_osfhandle((long)(((ChildProc*)(broadcast.pr))->hTo), _O_WRONLY), "w"); + } else + debugFP = fopen(c, "w"); setbuf(debugFP, NULL); } @@ -1284,6 +1298,8 @@ LFfromMFP(LOGFONT* lf, MyFontParams *mfp) lf->lfCharSet = mfp->charset; lf->lfOutPrecision = OUT_DEFAULT_PRECIS; + + lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; lf->lfQuality = DEFAULT_QUALITY; lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE; @@ -2351,13 +2367,17 @@ InitDrawingSizes(BoardSize boardSize, int flags) minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted */ border = appData.useBorder && appData.border[0] ? squareSize/2 : 0; + // [HGM] decide on tininess based on total board width rather than square size + tinyLayout = squareSize * (BOARD_WIDTH); + tinyLayout = tinyLayout < 35*8 ? 2 : tinyLayout < 43*8 ? 1 : 0; + if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) { lineGap = appData.overrideLineGap; } if (tinyLayout != oldTinyLayout) { long style = GetWindowLongPtr(hwndMain, GWL_STYLE); - if (tinyLayout) { + if (tinyLayout == 2) { style &= ~WS_SYSMENU; InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize, "&Minimize\tCtrl+F4"); @@ -2393,7 +2413,7 @@ InitDrawingSizes(BoardSize boardSize, int flags) ReleaseDC(hwndMain, hdc); /* Compute where everything goes */ - if((first.programLogo || second.programLogo) && !tinyLayout) { + if((first.programLogo || second.programLogo) && tinyLayout != 2) { /* [HGM] logo: if either logo is on, reserve space for it */ logoHeight = 2*clockSize.cy; leftLogoRect.left = OUTER_MARGIN; @@ -2514,7 +2534,7 @@ InitDrawingSizes(BoardSize boardSize, int flags) messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain, (HMENU) buttonDesc[i].id, (HINSTANCE) GetWindowLongPtr(hwndMain, GWLP_HINSTANCE), NULL); - if (tinyLayout) { + if (tinyLayout == 2) { SendMessage(buttonDesc[i].hwnd, WM_SETFONT, (WPARAM)font[boardSize][MESSAGE_FONT]->hf, MAKELPARAM(FALSE, 0)); @@ -2583,10 +2603,12 @@ InitDrawingSizes(BoardSize boardSize, int flags) piece = (ChessSquare) ((int) piece + 1)) { if (pieceBitmap[i][piece] != NULL) DeleteObject(pieceBitmap[i][piece]); + pieceBitmap[i][piece] = NULL; } } fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */ + // Orthodox Chess pieces pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s"); pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s"); @@ -2684,12 +2706,27 @@ InitDrawingSizes(BoardSize boardSize, int flags) pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s"); pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o"); pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w"); + pieceBitmap[0][WhiteAmazon] = DoLoadBitmap(hInst, "l", squareSize, "s"); + pieceBitmap[1][WhiteAmazon] = DoLoadBitmap(hInst, "l", squareSize, "o"); + pieceBitmap[2][WhiteAmazon] = DoLoadBitmap(hInst, "l", squareSize, "w"); pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s"); pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o"); pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w"); pieceBitmap[0][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "s"); pieceBitmap[1][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "o"); pieceBitmap[2][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "w"); + pieceBitmap[0][WhiteCub] = DoLoadBitmap(hInst, "ln", squareSize, "s"); + pieceBitmap[1][WhiteCub] = DoLoadBitmap(hInst, "ln", squareSize, "o"); + pieceBitmap[2][WhiteCub] = DoLoadBitmap(hInst, "ln", squareSize, "w"); + pieceBitmap[0][WhiteWolf] = DoLoadBitmap(hInst, "wolf", squareSize, "s"); + pieceBitmap[1][WhiteWolf] = DoLoadBitmap(hInst, "wolf", squareSize, "o"); + pieceBitmap[2][WhiteWolf] = DoLoadBitmap(hInst, "wolf", squareSize, "w"); + pieceBitmap[0][WhiteCamel] = DoLoadBitmap(hInst, "camel", squareSize, "s"); + pieceBitmap[1][WhiteCamel] = DoLoadBitmap(hInst, "camel", squareSize, "o"); + pieceBitmap[2][WhiteCamel] = DoLoadBitmap(hInst, "camel", squareSize, "w"); + pieceBitmap[0][WhiteZebra] = DoLoadBitmap(hInst, "zebra", squareSize, "s"); + pieceBitmap[1][WhiteZebra] = DoLoadBitmap(hInst, "zebra", squareSize, "o"); + pieceBitmap[2][WhiteZebra] = DoLoadBitmap(hInst, "n", squareSize, "w"); if(gameInfo.variant == VariantShogi && BOARD_HEIGHT != 7) { /* promoted Gold representations (but not in Tori!)*/ pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s"); @@ -2791,6 +2828,15 @@ InitDrawingSizes(BoardSize boardSize, int flags) pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w"); minorSize = 0; } + + if(appData.pieceDirectory[0]) for(i=WhitePawn; ix, lpwp->y, hwndConsole, &wpConsole ); wpMain.x = lpwp->x; wpMain.y = lpwp->y; + } } break; @@ -6705,7 +6756,7 @@ TypeInNameDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case IDOK: GetDlgItemText(hDlg, OPT_Name, move, sizeof(move)); appData.userName = strdup(move); - SetUserLogo(); + SetUserLogo(); DisplayLogos(); SetGameInfo(); if(gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack) { snprintf(move, MSG_SIZ, "%s vs. %s", gameInfo.white, gameInfo.black); @@ -7645,7 +7696,7 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight, if (twoBoards && partnerUp) return; if (appData.clockMode) { - if (tinyLayout) + if (tinyLayout == 2) snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%c %s %s", color[0], TimeString(timeRemaining), flagFell); else snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s:%c%s %s", color, (logoHeight>0 ? 0 : ' '), TimeString(timeRemaining), flagFell); @@ -7661,6 +7712,7 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight, oldFg = SetTextColor(hdc, RGB(0, 0, 0)); /* black */ oldBg = SetBkColor(hdc, RGB(255, 255, 255)); /* white */ } + oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf); JAWS_SILENCE @@ -7977,6 +8029,7 @@ Enables gnuEnables[] = { { IDM_Annotate, MF_BYCOMMAND|MF_GRAYED }, { IDM_NewChat, MF_BYCOMMAND|MF_GRAYED }, + // Needed to switch from ncp to GNU mode on Engine Load { ACTION_POS, MF_BYPOSITION|MF_ENABLED }, { IDM_MachineWhite, MF_BYCOMMAND|MF_ENABLED }, @@ -8206,6 +8259,8 @@ ModeHighlight() nowChecked = 0; break; } + if(prevChecked == IDM_TwoMachines) // [HGM] 'Machine Match' might have gotten disabled when stopping match + EnableMenuItem(GetMenu(hwndMain), IDM_Match, MF_BYCOMMAND|MF_ENABLED); CheckMark(prevChecked, MF_UNCHECKED); CheckMark(nowChecked, MF_CHECKED); CheckMark(IDM_Match, matchMode && matchGame < appData.matchGames ? MF_CHECKED : MF_UNCHECKED); diff --git a/winboard/winboard.rc b/winboard/winboard.rc index 7567c2d..c55c6da 100644 --- a/winboard/winboard.rc +++ b/winboard/winboard.rc @@ -696,7 +696,7 @@ BEGIN PUSHBUTTON "Cancel",IDCANCEL,140,244,50,14 END -DLG_NewVariant DIALOG DISCARDABLE 0, 0, 224, 250 +DLG_NewVariant DIALOG DISCARDABLE 0, 0, 224, 270 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Variants" FONT 8, "MS Sans Serif" @@ -774,20 +774,27 @@ BEGIN CONTROL "",OPT_EngineVariant+4,"Button",BS_AUTORADIOBUTTON,80,144,70,10 CONTROL "",OPT_EngineVariant+5,"Button",BS_AUTORADIOBUTTON,154,144,70,10 CONTROL "",OPT_EngineVariant+6,"Button",BS_AUTORADIOBUTTON,9,154,70,10 + CONTROL "",OPT_EngineVariant+7,"Button",BS_AUTORADIOBUTTON,80,154,70,10 CONTROL "",OPT_EngineVariant+8,"Button",BS_AUTORADIOBUTTON,154,154,70,10 - GROUPBOX "Variant",GPB_Variant,4,4,215,165 - LTEXT "Board size:",GPB_Board,10,183,40,8,WS_TABSTOP - LTEXT "ranks",IDC_Height,77,183,38,8 - EDITTEXT IDC_Ranks,60,179,14,14,ES_AUTOHSCROLL - LTEXT "files",IDC_Width,133,183,80,8 - EDITTEXT IDC_Files,116,179,14,14,ES_AUTOHSCROLL - LTEXT "Holdings with room for:",IDC_Hand,10,201,90,8 - EDITTEXT IDC_Holdings,93,197,14,14,ES_AUTOHSCROLL - LTEXT "pieces",IDC_Pieces,110,201,100,8 - LTEXT "('-1' means defaults for selected variant)",IDC_Def,10,217,210,8 - DEFPUSHBUTTON "OK",IDOK,114,232,50,14 - PUSHBUTTON "Cancel",IDCANCEL,170,232,50,14 + CONTROL "",OPT_EngineVariant+9,"Button",BS_AUTORADIOBUTTON,9,164,70,10 + CONTROL "",OPT_EngineVariant+10,"Button",BS_AUTORADIOBUTTON,80,164,70,10 + CONTROL "",OPT_EngineVariant+11,"Button",BS_AUTORADIOBUTTON,154,164,70,10 + CONTROL "",OPT_EngineVariant+12,"Button",BS_AUTORADIOBUTTON,9,174,70,10 + CONTROL "",OPT_EngineVariant+13,"Button",BS_AUTORADIOBUTTON,80,174,70,10 + CONTROL "",OPT_EngineVariant+14,"Button",BS_AUTORADIOBUTTON,154,174,70,10 + GROUPBOX "Variant",GPB_Variant,4,4,215,185 + LTEXT "Board size:",GPB_Board,10,203,40,8,WS_TABSTOP + LTEXT "ranks",IDC_Height,77,203,38,8 + EDITTEXT IDC_Ranks,60,199,14,14,ES_AUTOHSCROLL + LTEXT "files",IDC_Width,133,203,80,8 + EDITTEXT IDC_Files,116,199,14,14,ES_AUTOHSCROLL + LTEXT "Holdings with room for:",IDC_Hand,10,221,90,8 + EDITTEXT IDC_Holdings,93,217,14,14,ES_AUTOHSCROLL + LTEXT "pieces",IDC_Pieces,110,221,100,8 + LTEXT "('-1' means defaults for selected variant)",IDC_Def,10,237,210,8 + DEFPUSHBUTTON "OK",IDOK,114,252,50,14 + PUSHBUTTON "Cancel",IDCANCEL,170,252,50,14 END DLG_Fonts DIALOG DISCARDABLE 0, 0, 266, 274 @@ -1285,10 +1292,11 @@ BEGIN END POPUP "E&ngine" BEGIN - MENUITEM "Edit Engine List...", IDM_EditProgs1 + MENUITEM "&Edit Engine List...", IDM_EditProgs1 MENUITEM "Load &First Engine...", IDM_LoadProg1 MENUITEM "Load &Second Engine...", IDM_LoadProg2 MENUITEM SEPARATOR + MENUITEM "&Common Settings...\tAlt+Shift+U",IDM_OptionsUCI MENUITEM "Engine #&1 Settings...", IDM_Engine1Options MENUITEM "Engine #&2 Settings...", IDM_Engine2Options MENUITEM SEPARATOR @@ -1304,7 +1312,6 @@ BEGIN MENUITEM SEPARATOR MENUITEM "&General...", IDM_GeneralOptions MENUITEM "&Time Control...\tAlt+Shift+T",IDM_TimeControl - MENUITEM "Common &Engine...\tAlt+Shift+U",IDM_OptionsUCI MENUITEM "Ad&judications...\tAlt+Shift+J",IDM_EnginePlayOptions MENUITEM "Tournament...", IDM_Tourney MENUITEM SEPARATOR @@ -1930,6 +1937,9 @@ S72O BITMAP MOVEABLE PURE "bitmaps/s72o.bmp" L72O BITMAP MOVEABLE PURE "bitmaps/l72o.bmp" DK72O BITMAP MOVEABLE PURE "bitmaps/dk72o.bmp" LN72O BITMAP MOVEABLE PURE "bitmaps/ln72o.bmp" +WOLF72O BITMAP MOVEABLE PURE "bitmaps/wolf72o.bmp" +CAMEL72O BITMAP MOVEABLE PURE "bitmaps/camel72o.bmp" +ZEBRA72O BITMAP MOVEABLE PURE "bitmaps/zebra72o.bmp" WP72O BITMAP MOVEABLE PURE "bitmaps/wp72o.bmp" WN72O BITMAP MOVEABLE PURE "bitmaps/wn72o.bmp" WL72O BITMAP MOVEABLE PURE "bitmaps/wl72o.bmp" @@ -1951,6 +1961,9 @@ S72S BITMAP MOVEABLE PURE "bitmaps/s72s.bmp" L72S BITMAP MOVEABLE PURE "bitmaps/l72s.bmp" DK72S BITMAP MOVEABLE PURE "bitmaps/dk72s.bmp" LN72S BITMAP MOVEABLE PURE "bitmaps/ln72s.bmp" +WOLF72S BITMAP MOVEABLE PURE "bitmaps/wolf72s.bmp" +CAMEL72S BITMAP MOVEABLE PURE "bitmaps/camel72s.bmp" +ZEBRA72S BITMAP MOVEABLE PURE "bitmaps/zebra72s.bmp" WP72S BITMAP MOVEABLE PURE "bitmaps/wp72s.bmp" WN72S BITMAP MOVEABLE PURE "bitmaps/wn72s.bmp" WL72S BITMAP MOVEABLE PURE "bitmaps/wl72s.bmp" @@ -1972,6 +1985,8 @@ S72W BITMAP MOVEABLE PURE "bitmaps/s72w.bmp" L72W BITMAP MOVEABLE PURE "bitmaps/l72w.bmp" DK72W BITMAP MOVEABLE PURE "bitmaps/dk72w.bmp" LN72W BITMAP MOVEABLE PURE "bitmaps/ln72w.bmp" +WOLF72W BITMAP MOVEABLE PURE "bitmaps/wolf72w.bmp" +CAMEL72W BITMAP MOVEABLE PURE "bitmaps/camel72w.bmp" E49O BITMAP MOVEABLE PURE "bitmaps/e49o.bmp" A49O BITMAP MOVEABLE PURE "bitmaps/a49o.bmp" AA49O BITMAP MOVEABLE PURE "bitmaps/as49o.bmp" @@ -1989,6 +2004,9 @@ S49O BITMAP MOVEABLE PURE "bitmaps/s49o.bmp" L49O BITMAP MOVEABLE PURE "bitmaps/l49o.bmp" DK49O BITMAP MOVEABLE PURE "bitmaps/dk49o.bmp" LN49O BITMAP MOVEABLE PURE "bitmaps/ln49o.bmp" +WOLF49O BITMAP MOVEABLE PURE "bitmaps/wolf49o.bmp" +CAMEL49O BITMAP MOVEABLE PURE "bitmaps/camel49o.bmp" +ZEBRA49O BITMAP MOVEABLE PURE "bitmaps/zebra49o.bmp" WP49O BITMAP MOVEABLE PURE "bitmaps/wp49o.bmp" WN49O BITMAP MOVEABLE PURE "bitmaps/wn49o.bmp" WL49O BITMAP MOVEABLE PURE "bitmaps/wl49o.bmp" @@ -1999,6 +2017,7 @@ AA49S BITMAP MOVEABLE PURE "bitmaps/as49s.bmp" C49S BITMAP MOVEABLE PURE "bitmaps/c49s.bmp" CV49S BITMAP MOVEABLE PURE "bitmaps/cv49s.bmp" F49S BITMAP MOVEABLE PURE "bitmaps/f49s.bmp" + M49S BITMAP MOVEABLE PURE "bitmaps/m49s.bmp" W49S BITMAP MOVEABLE PURE "bitmaps/w49s.bmp" O49S BITMAP MOVEABLE PURE "bitmaps/o49s.bmp" @@ -2010,6 +2029,9 @@ S49S BITMAP MOVEABLE PURE "bitmaps/s49s.bmp" L49S BITMAP MOVEABLE PURE "bitmaps/l49s.bmp" DK49S BITMAP MOVEABLE PURE "bitmaps/dk49s.bmp" LN49S BITMAP MOVEABLE PURE "bitmaps/ln49s.bmp" +WOLF49S BITMAP MOVEABLE PURE "bitmaps/wolf49s.bmp" +CAMEL49S BITMAP MOVEABLE PURE "bitmaps/camel49s.bmp" +ZEBRA49S BITMAP MOVEABLE PURE "bitmaps/zebra49s.bmp" WP49S BITMAP MOVEABLE PURE "bitmaps/wp49s.bmp" WN49S BITMAP MOVEABLE PURE "bitmaps/wn49s.bmp" WL49S BITMAP MOVEABLE PURE "bitmaps/wl49s.bmp" @@ -2031,6 +2053,8 @@ S49W BITMAP MOVEABLE PURE "bitmaps/s49w.bmp" L49W BITMAP MOVEABLE PURE "bitmaps/l49w.bmp" DK49W BITMAP MOVEABLE PURE "bitmaps/dk49w.bmp" LN49W BITMAP MOVEABLE PURE "bitmaps/ln49w.bmp" +WOLF49W BITMAP MOVEABLE PURE "bitmaps/wolf49w.bmp" +CAMEL49W BITMAP MOVEABLE PURE "bitmaps/camel49w.bmp" A33O BITMAP MOVEABLE PURE "bitmaps/a33o.bmp" AA33O BITMAP MOVEABLE PURE "bitmaps/as33o.bmp" C33O BITMAP MOVEABLE PURE "bitmaps/c33o.bmp" diff --git a/winboard/woptions.c b/winboard/woptions.c index a512423..0d22012 100644 --- a/winboard/woptions.c +++ b/winboard/woptions.c @@ -884,7 +884,7 @@ VariantWhichRadio(HWND hDlg) if(IsDlgButtonChecked(hDlg, j) && (appData.noChessProgram || strstr(first.variants, VariantName(i-1)))) return (VariantClass) i-1; } - for(i=0; i<9; i++) { // check for engine-defined variants + for(i=0; i<15; i++) { // check for engine-defined variants if(IsDlgButtonChecked(hDlg, OPT_EngineVariant+i) ) { GetDlgItemText(hDlg, OPT_EngineVariant+i, engineVariant, MSG_SIZ); // remember name, so we can resolve it later return VariantUnknown; @@ -905,7 +905,7 @@ VariantShowRadio(HWND hDlg) EnableWindow(GetDlgItem(hDlg, j), appData.noChessProgram || strstr(first.variants, VariantName(i-1))); } *engineVariant = c; - for(i=0; i<9; i++) { // initialize engine-defined variants + for(i=0; i<15; i++) { // initialize engine-defined variants char *v = EngineDefinedVariant(&first, i); // get name of #i if(v) { // there is such a variant EnableWindow(GetDlgItem(hDlg, OPT_EngineVariant+i), TRUE); // and enable the button diff --git a/winboard/wsettings.c b/winboard/wsettings.c index bbf9003..c825d24 100644 --- a/winboard/wsettings.c +++ b/winboard/wsettings.c @@ -456,6 +456,7 @@ GetOptionValues(HWND hDlg, ChessProgramState *cps, Option *optionList) } char *defaultExt[] = { NULL, "pgn", "fen", "exe", "trn", "bin", "log", "ini" }; +HWND settingsDlg; LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { @@ -468,7 +469,7 @@ LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa // CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER)); SetOptionValues(hDlg, activeCps, activeList); - + settingsDlg = hDlg; SetFocus(GetDlgItem(hDlg, IDCANCEL)); break; @@ -478,12 +479,12 @@ LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa case IDOK: if(!GetOptionValues(hDlg, activeCps, activeList)) return FALSE; EndDialog( hDlg, 0 ); - comboCallback = NULL; activeCps = NULL; + comboCallback = NULL; activeCps = NULL; settingsDlg = NULL; return TRUE; case IDCANCEL: EndDialog( hDlg, 1 ); - comboCallback = NULL; activeCps = NULL; + comboCallback = NULL; activeCps = NULL; settingsDlg = NULL; return TRUE; default: @@ -692,6 +693,19 @@ EngineOptionsPopup(HWND hwnd, ChessProgramState *cps) return; } +void +RefreshSettingsDialog (ChessProgramState *cps, int val) +{ + int isUp = (settingsDlg != NULL); + if(val == 1) { + if(activeCps == cps && isUp) SetOptionValues(settingsDlg, cps, activeList); + return; + } + if(settingsDlg) EndDialog(settingsDlg, 1); + comboCallback = NULL; activeCps = NULL; settingsDlg = NULL; + if(val == 3 || isUp) EngineOptionsPopup(hwndMain, cps); +} + int EnterGroup P((HWND hDlg)); static int engineNr, selected; @@ -887,6 +901,7 @@ int MatchOK() void PseudoOK(HWND hDlg) { + if(matchMode) return; okFunc = 0; GetOptionValues(hDlg, activeCps, activeList); EndDialog( hDlg, 0 ); @@ -894,7 +909,12 @@ void PseudoOK(HWND hDlg) if(autoinc) appData.loadGameIndex = appData.loadPositionIndex = -(twice + 1); else if(!appData.loadGameFile[0]) appData.loadGameIndex = -2*twice; // kludge to pass value of "twice" for use in GUI book + if(!autoinc && !twice) { // prevent auto-inc being remembered in index value if checkboxes not ticked + if(appData.loadGameIndex < 0) appData.loadGameIndex = 0; + if(appData.loadPositionIndex < 0) appData.loadPositionIndex = 0; + } if(swiss) { appData.defaultMatchGames = 1; appData.tourneyType = -1; } + ASSIGN(appData.tourneyFile, tfName); } char *GetParticipants(HWND hDlg) diff --git a/xaw/xboard.c b/xaw/xboard.c index 4bca0c1..f1e991d 100644 --- a/xaw/xboard.c +++ b/xaw/xboard.c @@ -149,6 +149,7 @@ extern char *getenv(); #include #endif +#include #include #include #include @@ -1818,7 +1819,7 @@ ModeHighlight () { Arg args[16]; static int oldPausing = FALSE; - static GameMode oldmode = (GameMode) -1; + static GameMode oldMode = (GameMode) -1; char *wname; if (!boardWidget || !XtIsRealized(boardWidget)) return; @@ -1844,7 +1845,7 @@ ModeHighlight () } } - wname = ModeToWidgetName(oldmode); + wname = ModeToWidgetName(oldMode); if (wname != NULL) { MarkMenuItem(wname, False); } @@ -1852,8 +1853,9 @@ ModeHighlight () if (wname != NULL) { MarkMenuItem(wname, True); } - oldmode = gameMode; + if(oldMode == TwoMachinesPlay) EnableNamedMenuItem("Mode.MachineMatch", True); MarkMenuItem("Mode.MachineMatch", matchMode && matchGame < appData.matchGames); + oldMode = gameMode; /* Maybe all the enables should be handled here, not just this one */ EnableNamedMenuItem("Mode.Training", gameMode == Training || gameMode == PlayFromGameFile); diff --git a/xaw/xoptions.c b/xaw/xoptions.c index 28fe260..502aed1 100644 --- a/xaw/xoptions.c +++ b/xaw/xoptions.c @@ -189,6 +189,12 @@ SetWidgetLabel (Option *opt, char *buf) } void +SetComboChoice (Option *opt, char *n) +{ + SetWidgetText(opt, opt->choice[n]); +} + +void SetDialogTitle (DialogClass dlg, char *title) { Arg args[16]; @@ -1130,8 +1136,10 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent option[i].max /* w */, shrink ? textHeight : 0 /* h */, option[i].min & 0xE | chain /* chain */); XtSetArg(args[j], XtNlabel, _(option[i].name)); j++; if(option[i].textValue && *option[i].textValue == '#') { // special for buttons of New Variant dialog + char *p, *v, n = option[i].value; + if(n) v = VariantName(n), p = strstr(first.variants, v); XtSetArg(args[j], XtNsensitive, option[i].value >= 0 && (appData.noChessProgram - || strstr(first.variants, VariantName(option[i].value)))); j++; + || p && (!*v || strlen(p) == strlen(v) || p[strlen(v)] == ','))); j++; XtSetArg(args[j], XtNborderWidth, (gameInfo.variant == option[i].value)+1); j++; } option[i].handle = (void*) diff --git a/xboard.texi b/xboard.texi index 464c756..26bebf2 100644 --- a/xboard.texi +++ b/xboard.texi @@ -90,8 +90,10 @@ As an interface to GNU Chess or another chess engine running on your machine, XBoard lets you play a game against the machine, set up arbitrary positions, force variations, watch a game between two chess engines, interactively analyze your stored games or set up and -analyze arbitrary positions. (Note: Not all chess engines support -analysis.) +analyze arbitrary positions. +To run engines that use the UCI standard XBoard will draw upon +the Polyglot adapter fully transparently, but you will need to have +the polyglot package installed for this to work. @item xboard -ics -icshost hostname [options] As Internet Chess Server (ICS) interface, XBoard lets you play against other ICS users, observe games @@ -120,7 +122,15 @@ instructions. To move a piece, you can drag it with the left mouse button, or you can click the left mouse button once on the piece, then once more on -the destination square. In crazyhouse, bughouse or shogi you can +the destination square. To under-promote a Pawn you can drag it backwards +until it morphs into the piece you want to promote to, after which you +drag that forward to the promotion square. +Or after selecting the pawn with a first click you can then click +the promotion square and move the mouse while keeping the button down +until the piece that you want appears in the promotion square. +To castle you move the King to its destination or, in Chess960, +on top of the Rook you want to castle with. +In crazyhouse, bughouse or shogi you can drag and drop pieces to the board from the holdings squares displayed next to the board. @@ -140,14 +150,14 @@ Lines of play displayed in the engine-output window, or PGN variations in the comment window can similarly be played out on the board, by right-clicking on them. Only in Analysis mode, when you walk along a PV, -releasing the mouse button will forward the game upto that point, +releasing the mouse button might forward the game upto that point, like you entered all previous PV moves. As the display of the PV in that case starts after the first move a simple right-click will play the move the engine indicates. In Analysis mode you can also make a move by grabbing the piece with a double-click of the left mouse button -(or while keeping the Ctrl key pressed). +(or while keeping the @kbd{Ctrl} key pressed). In this case the move you enter will not be played, but will be excluded from the analysis of the current position. (Or included if it was already excluded; it is a toggle.) @@ -171,7 +181,7 @@ frequently used commands also have shortcut keys or on-screen buttons. These shortcut keystrokes are mostly non-printable characters. Typing a letter or digit while the board window has focus will bring up a type-in box with the typed letter already in it. -You can use that to type a move in siuations where it is your +You can use that to type a move in situations where it is your turn to enter a move, type a move number to call up the position after that move in the display, @@ -184,6 +194,11 @@ the settings that are made through menus or command-line options, so they will still apply when you restart XBoard for another session. The settings can be saved into this file automatically when XBoard exits, or on explicit request of the user. +Note that the board window can be sized by the user, but that this +will not affect the size of the clocks above it, and won't be remembered +in the settings file. +To persistently change the size of the clocks, use the @code{size} +command-line option when starting XBoard. The default name for the settings file is /etc/xboard/xboard.conf, but in a standard install this file is only used as a master settings file that determines the system-wide default settings, @@ -244,19 +259,14 @@ Allows you to select a new chess variant in non-ICS mode. (In ICS play, the ICS is responsible for deciding which variant will be played, and XBoard adapts automatically.) The shifted @kbd{Alt+V} key is a keyboard equivalent. If you play with an engine, the engine must -be able to play the selected variant, or the command will be ignored. +be able to play the selected variant, or the corresponding choice will be disabled. XBoard supports all major variants, such as xiangqi, shogi, chess, chess960, -Capablanca Chess, shatranj, crazyhouse, bughouse. -But not every board size has built-in bitmaps for un-orthodox pieces! -Only sizes bulky (72) and middling (49) have all pieces, -while size petite (33) has most. -These sizes would have to be set at startup through the @code{size} -command-line option when you start up XBoard for such variants to be playable. +makruk, Capablanca Chess, shatranj, crazyhouse, bughouse. You can overrule the default board format of the selected variant, (e.g. to play suicide chess on a 6 x 6 board), in this dialog, but normally you would not do that, -and leave them at '-1', which means 'default'. +and leave them at '-1', which means 'default' for the chosen variant. @item Load Game @cindex Load Game, Menu Item Plays a game from a record file. The @kbd{Ctrl-O} key is a keyboard equivalent. @@ -267,7 +277,7 @@ any), and you can select the one you want. Alternatively, you can load the Nth game in the file directly, by typing the number @kbd{N} after the file name, separated by a space. -The game file parser will accept PGN (portable game notation), +The game-file parser will accept PGN (portable game notation), or in fact almost any file that contains moves in algebraic notation. Notation of the form @samp{P@@f7} @@ -423,6 +433,11 @@ Lets you set up an arbitrary board position. The shifted @kbd{Ctrl-E} key is a keyboard equivalent. Use mouse button 1 to drag pieces to new squares, or to delete a piece by dragging it off the board or dragging an empty square on top of it. +When you do this keeping the @kbd{Ctrl} key pressed, +or start dragging with a double-click, +you will move a copy of the piece, leaving the piece itself where it was. +In variants where pieces can promote (such as Shogi), +left-clicking an already selected piece promotes or demotes it. To drop a new piece on a square, press mouse button 2 or 3 over the square. This puts a white or black pawn in the square, respectively, @@ -432,13 +447,27 @@ You will then see the piece on the originally clicked square cycle through the available pieces (including those of opposite color), and can release the button when you see the piece you want. +(Note you can swap the function of button 2 and 3 by pressing +the shift key, and that there is an option @code{monoMouse} +to combine al functions in one button, which then acts as +button 3 over an empty square, and as button 1 over a piece.) To alter the side to move, you can click the clock (the words White and Black above the board) of the side you want to give the move to. To clear the board you can click the clock of the side that -alread has the move (which is highlighted in black). +already has the move (which is highlighted in black). +If you repeat this the board will cycle from empty to a +@code{pallette board} containing every piece once to the initial +position to the one before clearing. +The quickest way to set up a position is usually to start +with the pallette board, and move the pieces to were you +want them, duplicating them where necessary by using the +@kbd{Ctrl} key, dragging those you don't want off board, +and use static button 2 or 3 clicks to place the Pawns. The old behavior with a piece menu can still be configured with the aid of the @code{pieceMenu} option. +Dragging empty squares off board can create boards with +holes (inaccessible black squares) in them. Selecting @samp{Edit Position} causes XBoard to discard all remembered moves in the current game. @@ -492,9 +521,12 @@ Pops up a window listing the moves available in the GUI book from the currently displayed position, together with their weights and (optionally in braces) learn info. You can then edit this list, and the new list will be stored -back into the book when you press OK. +back into the book when you press 'save changes'. +When you press the button 'add next move', and play a move +on the board, that move will be added to the list with weight 1. Note that the listed percentages are neither used, nor updated when you change the weights; they are just there as an optical aid. +When you right-click a move in the list it will be played. @item Revert @itemx Annotate @cindex Revert, Menu Item @@ -531,7 +563,7 @@ The @kbd{End} key is a keyboard equivalent. Steps backward through a series of remembered moves. The @samp{[<]} button and the @kbd{Alt+LeftArrow} key are equivalents, as is turning the mouse wheel towards you. -In addition, pressing the Control key steps back one move, and releasing +In addition, pressing the ??? key steps back one move, and releasing it steps forward again. In most modes, @samp{Backward} only lets you look back at old positions; @@ -625,10 +657,16 @@ right button kept down, will make XBoard play through the PV listed there. The use of the board window as 'variation board' will normally end when you release the right button, or when the opponent plays a move. -But beware: in Analysis mode, moves thus played out will be added to the game. +But beware: in Analysis mode, moves thus played out might be added to the game, +depending on the setting of the option 'Play moves of clicked PV', +when you initiate the click left of the PV in the score area. The Engine-Output pane for each engine will contain a header displaying the multi-PV status and a list of excluded moves in Analysis mode, -which are also responsive to right-clicking. +which are also responsive to right-clicking: +Clicking the words 'fewer' or 'more' will alter the number of variations +shown at each depth, through the engine's MultiPV option, +while clicking in between those and moving the mouse horizontally adjust +the option 'Multi-PV Margin'. (In so far the engines support those.) @item Show Move History @cindex Show Move History, Menu Item Shows or hides a list of moves of the current game. @@ -640,12 +678,34 @@ by clicking on the corresponding move. Shows or hides a window which displays a graph of how the engine score(s) evolved as a function of the move number. The shifted @kbd{Alt+E} key is a keyboard equivalent. +The title bar shows the score (and search depth at which it was obtained) +of the currently displayed position numerically. Clicking on the graph will bring the corresponding position in the board display. +A button 3 click will toggle the display mode between plain and differential +(showing the difference in score between successive half moves). +Using the mouse wheel over the window will change the scale of the +low-score region (from -1 to +1). @item Show Game List @cindex Show Game List, Menu Item Shows or hides the list of games generated by the last @samp{Load Game} command. The shifted @kbd{Alt+G} key is a keyboard equivalent. +The line describing each game is built from a selection of the PGN tags. +Which tags contribute, and in what order, can be changed by the @samp{Game list tags} +menu dialog, which can be popped up through the @samp{Tags} button below the Game List. +Display can be restricted to a sub-set of the games meeting certain criteria. +A text entry below the game list allows you to type a text that the game lines +must contain in order to be displayed. +Games can also be selected based on their Elo PGN tag, +as set in the @samp{Load Game Options} dialog, which can be popped up through the +@samp{Thresholds} button below the Game List. +Finally they can be selected based on containing a position similar to the one +currently displayed in the main window, by pressing the 'Position' button below +the Game List, (which searches the entire list for the position), or the 'Narrow' +button (which only searches the already-selected games). +What counts as similar enough to be selected can also be set in the +@samp{Load Game Options} dialog, and ranges from an exact match to just the +same material. @item Tags @cindex Tags, Menu Item Pops up a window which shows the PGN (portable game notation) @@ -663,19 +723,45 @@ creates an extra window that you can use for typing in ICS commands. The input box is especially useful if you want to type in something long or do some editing on your input, because output from ICS doesn't get mixed in with your typing as it would in the main terminal window. -@item Open Chat Window -@cindex Open Chat Window, Menu Item -This menu item opens a window in which you can conduct upto 5 chats -with other ICS users (or channels). +@item ICS Chat/Console +@cindex ICS Chat/Console, Menu Item +This menu item opens a window in which you can interact with the ICS, +and conduct upto 5 chats with other ICS users (or channels), +so you don't have to use the messy xterm from which you launched XBoard +for that. +The window has a text entry at the bottom where you can type your +commands and messages unhindered by the stream of ICS output. +The latter will be displayed in a large pane above the input field, +the ICS Console. +This pane can be vertically split into two, however, where half of it +is then used to display selected ICS output, belonging to a chat with +another user, or output from an ICS channel. +Such output will then not appear in the Console pane. + To use the window, write the name of your chat partner, the channel number, or the words 'shouts', 'whispers', 'cshouts' in the upper field -(closing with ). +(ending with ). Everything you type in the lowest field will then automatically be sent to the mentioned party, while everything that party sends to you will -appear in the central text box, rather than appear in the ICS console. +appear in the central text pane, rather than appear in the ICS console. The row of buttons allow you to choose between chat; to start a new chat, just select an empty button, and complete the @samp{Chat partner} field. +There are several keyboard accelerators to control this window: +Ctrl-H will hide the private chat, and dedicates the input field to +giving ICS commands. +Ctrl-E will erase the current chat and chat partner. +Ctrl-N will open a new chat with a yet unspecified partner. +Ctrl-O will open a new chat with the last person from which you received +a tell in the ICS console pane. + will transfer keyboard focus to the board window, +allowing you to invoke menu items through accelerator keys; +typing a printable character there transfers focus back to the input field +of the chat window. + will switch to another busy chat, +giving priority to those with content you have not seen yet. +(The buttons for selecting such chats turn orange.) +Up and down arrow keys can be used to recall previous input lines. @item Board @cindex Board, Menu Item Summons a dialog where you can customize the look of the chess board. @@ -685,6 +771,11 @@ when you don't want to use the built-in piece images external images to be used for the board squares (@code{liteBackTextureFile} and @code{darkBackTextureFile} options), and square and piece colors for the default pieces. +The current combination of these settings can be assigned a 'theme' name +by typing one in the text entry in the lower-left of the dialog, +and closing the latter with OK. +It will then appear in the themes listbox next time you open the dialog, +where you can recall the complete settings combination with a double-click. @item Game List Tags @cindex Game List Tags, Menu Item a duplicate of the Game List dialog in the Options menu. @@ -710,6 +801,7 @@ The @kbd{Ctrl-T} key is a keyboard equivalent. @item Analysis Mode @cindex Analysis Mode, Menu Item @cindex null move +@cindex move exclusion XBoard tells the chess engine to start analyzing the current game/position and shows you the analysis as you move pieces around. The @kbd{Ctrl-A} key is a keyboard equivalent. @@ -717,15 +809,10 @@ Note: Some chess engines do not support Analysis mode. To set up a position to analyze, you do the following: -1. Select Edit Position from the Mode Menu - -2. Set up the position. Use the middle and right buttons to -bring up the white and black piece menus. - -3. When you are finished, click on either the Black or White -clock to tell XBoard which side moves first. +1. Set up the position by any means. (E.g. using @samp{Edit Position} +mode, pasing a FEN or loading a game and stepping to the position.) -4. Select Analysis Mode from the Mode Menu to start the analysis. +2. Select Analysis Mode from the Mode Menu to start the analysis. You can now play legal moves to create follow-up positions for the engine to analyze, while the moves will be remembered as a stored game, @@ -757,7 +844,7 @@ toggle the participation of the second engine in the analysis. The output of this engine will then be shown in the lower pane of the Engine Output window. The analysis function can also be used when observing games on an ICS -with an engine loaded (zippy mode); the engine then will analyse +with an engine loaded (zippy mode); the engine then will analyze the positions as they occur in the observed game. @item Analyze Game @@ -826,7 +913,7 @@ have special functions in this mode; see below. @cindex Machine match, Menu Item Starts a match between two chess programs, with a number of games and other parameters set through -the @samp{Match Options} menu dialog. +the @samp{Tournament Options} menu dialog. When a match is already running, selecting this item will make XBoard drop out of match mode after the current game finishes. @item Pause @@ -933,17 +1020,23 @@ by the comment "user adjudication". @cindex Engine Menu @cindex Menu, Engine @table @asis -@item Load Engine +@item Edit Engine List +@cindex Edit Engine List, Menu Item +Opens a window that shows the list of engines registered for use +by XBoard, together with the options that would be used with them +when you would select them from the @samp{Load Engine} dialogs. +You can then edit this list, e.g. for re-ordering the engines, +or adding uncommon options needed by this engine +(e.g. to cure non-compliant behavior). +@item Load New 1st Engine +@itemx Load New 2nd Engine @cindex Load Engine, Menu Item Pops up a dialog where you can select or specify an engine to be loaded. -You will always have to indicate whether you want to load the engine -as first or second engine, through the ‘Load menitioned engine as’ -drop-down list at the bottom of the dialog. You can even replace engines during a game, without disturbing that game. (Beware that after loading an engine, XBoard will always be in Edit Game mode, so you will have to tell the new engine what to do before it does anything!) When you select an already installed engine from the ‘Select Engine from List’ -drop-down list, +listbox, all other fields of the dialog will be ignored. In other cases, you have to specify the engine executable, possible arguments on the engine command line @@ -954,7 +1047,7 @@ You will also have to specify (with the aid of checkboxes) if the engine is UCI. If ‘Add this engine to the list’ is ticked (which it is by default), the engine will be added to the list of installed engines in your settings file, (provided you save the settings!), -so that next time you can select it from the drop-down list. +so that next time you can select it from the listbox. You can also specify a ‘nickname’, under which the engine will then appear in that drop-down list, and even choose to use that nickname for it in PGN files for engine-engine games. @@ -965,11 +1058,8 @@ For obsolete XBoard engines, which would normally take a long delay to load because XBoard is waiting for a response they will not give, you can tick ‘WB protocol v1’ to speed up the loading process. @item Engine #N Settings -@cindex Engine Settings, Menu Item -@cindex Engine #1 Settings, Menu Item -@cindex Engine #2 Settings, Menu Item +@cindex Engine #N Settings, Menu Item Pop up a menu dialog to alter the settings specific to the applicable engine. -(The second engine is only accessible once it has been used in Two-Machines mode.) For each parameter the engine allows to be set, a control element will appear in this dialog that can be used to alter the value. Depending on the type of parameter (text string, number, multiple choice, @@ -982,7 +1072,32 @@ Many engines do not have any parameters that can be set by the user, and in that case the dialog will be empty (except for the OK and cancel buttons). UCI engines usually have many parameters. (But these are only visible with a sufficiently modern version of the Polyglot adapter needed to run UCI engines, -e.g. Polyglot 1.4.55b.) For native XBoard engines this is less common. +e.g. Polyglot 2.0.1.) For native XBoard engines this is less common. + +@item Common Settings +@cindex Common Settings, Menu Item +Pops up a menu dialog where you can set some engine parameters common to most engines, +such as hash-table size, tablebase cache size, maximum number of processors +that SMP engines can use. +The shifted @kbd{Alt+U} key is a keyboard equivalent. +Older XBoard/WinBoard engines might not respond to these settings, +but UCI engines always should. + +It is also possible to specify a GUI opening book here, i.e. an opening +book that XBoard consults for any position a playing engine gets in. +It then forces the engine to play the book move, rather than to think up its own, +if that position is found in the book. +The book can switched on and off independently for either engine. +The way book moves are chosen can be influenced through the settings of +book depth and variety. +After both sides have played more moves than the specified depth, +the book will no longer be consulted. +When the variety is set to 50, moves will be played with the probability +specified in the book. +When set to 0, only the move(s) with the highest probability will be played. +When set to 100, all listed moves will be played with equal pobability. +Other settings interpolate between that. + @item Hint @cindex Hint, Menu Item Displays a move hint from the chess engine. @@ -999,6 +1114,7 @@ engine is out of its book or does not support this feature. @cindex Move Now, Menu Item Forces the chess engine to move immediately. Chess engine mode only. The @kbd{Ctrl-M} key is a keyboard equivalent. +Many engines won't respond to this. @item Retract Move @cindex Retract Move, Menu Item Retracts your last move. In chess engine mode, you can do this only @@ -1016,7 +1132,7 @@ Clicking on such a name will load that engine as first engine, so you won't have to search for it in your list of installed engines, if that is very long. The maximum number of displayed engine names is set by the -@code{recentEngines}command-line option. +@code{recentEngines} command-line option. @end table @node Options Menu @@ -1075,7 +1191,7 @@ In ICS mode, Auto Flag will only call your opponent's flag, not yours, and the ICS may award you a draw instead of a win if you have insufficient mating material. In local chess engine mode, XBoard -may call either player's flag and will not take material into account (?). +may call either player's flag. @item Auto Flip View @cindex Auto Flip View, Menu Item If the Auto Flip View option is on when you start a game, the board @@ -1109,6 +1225,13 @@ while keeping the Shift key pressed will start a new variation. You can then recall the previous line through the @samp{Revert} menu item. When off, playing a move will truncate the game and append the move irreversibly. +@item Headers in Engine Output Window +@cindex Headers in Engine Output Window, Menu Item +Controls the presence of column headers above the variations and +associated information printed by the engine, on which you can issue +button 3 clicks to open or close the columns. +Available columns are search depth, score, node count, time used, +tablebase hits, search speed and selective search depth. @item Hide Thinking @cindex Hide Thinking, Menu Item If this option is off, the chess engine's notion of the score and best @@ -1130,16 +1253,6 @@ be unmade are highlighted. Causes the highlighting described in Highlight Last Move to be done by drawing an arrow between the highlighted squares, so that it is visible even when the width of the grid lines is set to zero. -@item Move Sound -@cindex Move Sound, Menu Item -Enables the sounding of an audible signal when the computer performs a move. -For the selection of the sound, see @samp{Sound Options}. -If you turn on this option when using XBoard with the Internet -Chess Server, you will probably want to give the -@kbd{set bell 0} -command to the ICS, since otherwise the ICS will ring the terminal bell -after every move (not just yours). (The @file{.icsrc} file -is a good place for this; see @ref{ICS options}.) @item One-Click Moving @cindex One-Click Moving, Menu Item If this option is on, XBoard does not wait for you to click both the @@ -1162,12 +1275,16 @@ will only be updated when the analysis changes. If this option is on, the Analysis Window will be updated every two seconds. @item Play Move(s) of Clicked PV @cindex Play Move(s) of Clicked PV, Menu Item -If this option is on, right-clicking a PV in the Engine Output window +If this option is on, right-clicking on the first move of a PV +or on the data fields left of it in the Engine Output window during Analyze mode will cause the first move of that PV to be played. You could also play more than one (or no) PV move by moving the mouse to engage in the PV walk such a right-click will start, to seek out another position along the PV where you want to continue the analysis, before releasing the mouse button. +Clicking on later moves of the PV only temporarily show the moves +for as long you keep the mouse button down, +without adding them to the game. @item Ponder Next Move @cindex Ponder Next Move, Menu Item If this option is off, the chess engine will think only when it is on @@ -1199,9 +1316,17 @@ along the board's left and bottom edges. @item Show Target Squares @cindex Show Target Squares, Menu Item If this option is on, all squares a piece that is 'picked up' with the mouse -can legally move to are highighted with a fat colored dot in the -highlightColor (non-captures) or premoveHighlightColor (captures). -Legality testing must be on for XBoard to know how the piece moves. +can legally move to are highighted with a fat colored dot in +yellow (non-captures) or red (captures). +Special moves might have other colors +(e.g. magenta for promotion, cyan for a partial move). +Legality testing must be on for XBoard to know how the piece moves, +but with legality testing off some engines would offer this information. +@item Sticky Windows +@cindex Sticky Windows, Menu Item +Controls whether the auxiliary windows such as Engine Output, Move History +and Evaluation Graph should keep touching XBoard's main window when +you move the latter. @item Test Legality @cindex Test Legality, Menu Item If this option is on, XBoard tests whether the moves you try to make @@ -1214,6 +1339,11 @@ off this option is useful if you are playing a chess variant with rules that XBoard does not understand. (Bughouse, suicide, and wild variants where the king may castle after starting on the d file are generally supported with Test Legality on.) +@item Top-Level Dialogs +@cindex Top-Level Dialogs, Menu Item +Controls whether the auxiliary windows will appear as icons in the +task bar and independently controllable, or whether they open and +minimize all together with the main window. @item Flash Moves @itemx Flash Rate @cindex Flash Moves, Menu Item @@ -1227,45 +1357,20 @@ Determines the duration (in msec) of an animation step, when @samp{Animate Moving} is swiched on. @item Zoom factor in Evaluation Graph @cindex Zoom factor in Evaluation Graph, Menu Item -Sets the valueof the @code{evalZoom} option, +Sets the value of the @code{evalZoom} option, indicating the factor by which the score interval (-1,1) should be blown up on the vertical axis of the Evaluation Graph. @end table @subsection Time Control @cindex Time Control, Menu Item Pops up a sub-menu where you can set the time-control parameters interactively. +The shifted @kbd{Alt+T} key is a keyboard equivalent. Allows you to select classical or incremental time controls, set the moves per session, session duration, and time increment. Also allows specification of time-odds factors for one or both engines. If an engine is given a time-odds factor N, all time quota it gets, be it at the beginning of a session or through the time increment or fixed time per move, will be divided by N. -The shifted @kbd{Alt+T} key is a keyboard equivalent. - -@subsection Common Engine -@cindex Common Engine, Menu Item -Pops up a sub-menu where you can set some engine parameters common to most engines, -such as hash-table size, tablebase cache size, maximum number of processors -that SMP engines can use, and where to find the Polyglot adapter needed -to run UCI engines under XBoard. The feature that allows setting of these parameters on -engines is new since XBoard 4.3.15, so not many XBoard/WinBoard engines respond -to it yet, but UCI engines should. - -It is also possible to specify a GUI opening book here, i.e. an opening -book that XBoard consults for any position a playing engine gets in. -It then forces the engine to play the book move, rather than to think up its own, -if that position is found in the book. -The book can switched on and off independently for either engine. -The way book moves are chosen can be influenced through the settings of -book depth and variety. -After both sides have played more moves than the specified depth, -the book will no longer be consulted. -When the variety is set to 50, moves will be played with the probability -specified in the book. -When set to 0, only the move(s) with the highest probability will be played. -When set to 100, all listed moves will be played with equal pobability. -Other settings interpolate between that. -The shifted @kbd{Alt+U} key is a keyboard equivalent. @subsection Adjudications @cindex Adjudications, Menu Item @@ -1343,7 +1448,7 @@ option is set, as in that case all games are saved to the specified file. @cindex Background Observe, Menu Item Setting this option will make XBoard suppress display of any boards from observed games while you are playing. -In stead the last such board will be remembered, +Instead the last such board will be remembered, and shown to you when you right-click the board. This allows you to peek at your bughouse partner's game when you want, without disturbing your own game too much. @@ -1385,6 +1490,14 @@ In combination with the @samp{Seek Graph} option this will cause automatic update of the seek graph while it is up. This only works on FICS and ICC, and requires a lot of bandwidth on a busy server. +@item Auto-InputBox PopUp +@cindex Auto-InputBox PopUp, Menu Item +Controls whether the ICS Input Box will pop up automatically when +you type a printable character to the board window in ICS mode. +@item Quit After Game +@cindex Quit After Game, Menu Item +Controls whether XBoard will automatically disconnect from the ICS +and close when the game currently in progress finishes. @item Premove @itemx Premove White @itemx Premove Black @@ -1413,7 +1526,7 @@ of the game. @cindex ICS Alarm Time, Menu Item When this option is on, an alarm sound is played when your clock counts down to the icsAlarmTime in an ICS game. -(By default, the time is 5 seconds, but you can pecify other values +(By default, the time is 5 seconds, but you can specify other values with the Alarm Time spin control.) For games with time controls that include an increment, the alarm will sound each time the clock counts down to the icsAlarmTime. @@ -1428,10 +1541,10 @@ The colors can be individually selected for each type, through the accompanying text edits. @end table -@subsection Match Options -@cindex Match Options, Menu Item +@subsection Tournament Options +@cindex Tournament Options, Menu Item Summons a dialog where you can set options important for playing automatic -matches between two chess programs +matches between two or more chess programs (e.g. by using the @samp{Machine Match} menu item in the @samp{Mode} menu). @table @asis @item Tournament file @@ -1444,7 +1557,7 @@ two-player match with the currently loaded engines, you must not leave this field blank. When you enter the name of an existing tournament file, XBoard will ignore all other input specified in the dialog, -and will take them from that tournament file. +and will take the corresponding info from that tournament file. This resumes an interrupted tournament, or adds another XBoard agent playing games for it to those that are already doing so. Specifying a not-yet-existing file will cause XBoard to create it, @@ -1467,13 +1580,13 @@ Default: sync after cycle, but not after round. @itemx Tourney participants @cindex Select Engine, Menu Item @cindex Tourney participants, Menu Item -With the Select Engine drop-down list you can pick an engine from your list -of installed engines in the settings file, to be added to the tournament. +From the Select Engine listbox you can pick an engine from your list +of engines registered in the settings file, to be added to the tournament. The engines selected so far will be listed in the ‘Tourney participants’ memo. The latter is a normal text edit, so you can use normal text-editing functions -to delete engines you selected by accident, or change their order. -Do not type names yourself there, because names that do not exactly match -one of the names from the drop-down list will lead to undefined behavior. +to delete engines you selected accidentally, or change their order. +Typing names here yourself is not recommended, because names that do not exactly match +one of the names from the selection listbox will lead to undefined behavior. @item Tourney type @cindex Tourney type, Menu Item Here you can specify the type of tournament you want. @@ -1496,8 +1609,8 @@ Such multiple games can be played in a row, as specified by the ‘number of games per pairing’, or by repeating the entire tournament schedule a number of times (specified by the ‘number of tourney cycles’). -The total number of times two engine meet will be the product of these two. -Default is 1 cycle; +The total number of times two engines meet will be the product of these two. +Default is 1 cycle; the number of games per pairing is the same as the default number of match games, stored in your settings file through the @code{defaultMatchGames} option. @item Save Tourney Games @@ -1527,8 +1640,8 @@ In this case the first (odd) games will randomly select from the book, but the second (even) games will select the same moves from the book as the previous game. (Note this leads to the same opening only if both engines use the GUI book!) Default: No game or position file will be used. The default index if such a file is used is 1. -@item Disable own engine bools be default -@cindex Disable own engine bools be default, Menu Item +@item Disable own engine books be default +@cindex Disable own engine books be default, Menu Item Setting this option reverses the default situation for use of the GUI opening book in tournaments from what it normally is, namely not using it. So unless the engine is installed with an option to explicitly specify it should @@ -1559,6 +1672,16 @@ and then puts the originally proposed name for the tourney file back. You can then run a tourney with the same parameters (possibly after changing the proposed name of the tourney file for the new tourney) by pressing 'OK'. +@item Continue Later +@cindex Continue Later, Menu Item +Pressing the @samp{Continue Later} button confirms the current value of all +items in the dialog and closes it, +but will not automatically start the tournament. +This allows you to return to the dialog later without losing the settings you +already entered, to adjust paramenters through other menu dialogs. +(The @samp{Common Engine Setting}, @samp{Time Control} and @samp{General Options} +dialogs can be accessed without closing the @samp{Tournament Options} dialog +through the respective buttons at the bottom of the latter.) @end table @subsection Load Game Options @@ -1567,19 +1690,24 @@ Summons a dialog where you can set the @code{autoDisplayComment} and @code{autoDisplayTags} options, (which control popups when viewing loaded games), and specify the rate at which loaded games are auto-played, in seconds per move (which can be a fractional number, like 1.6). +This rate is also used with the @code{Analyze Game} menu item. You can also set search criteria for determining which games will be displayed in the Game List for a multi-game file, and thus be eligible for loading: @table @asis @item Elo of strongest player @itemx Elo of weakest player -@itemx year +@itemx No games before year @cindex Elo of strongest player, Menu Item @cindex Elo of weakest player, Menu Item -@cindex year, Menu Item +@cindex No games before year, Menu Item These numeric fields set thresholds (lower limits) on the Elo rating of the mentioned player, or the date the game was played. Defaults: 0 +@item Final nr of pieces +@cindex Final nr of pieces, Menu Item +Here you can enter a range (e.g. 8-10), and only games will be selected that +has a number of men in this range on the board in their final position. @item Search mode @cindex Search mode, Menu Item @cindex find position, Menu Item @@ -1605,7 +1733,7 @@ and can thus be used to refine a search based on multiple criteria. @item number of consecutive positions @cindex number of consecutive positions, Menu Item When you are searching by material, rather than for an exact match, -this parameter indicates forhowmany consecutive game positions +this parameter indicates for how many consecutive game positions the same amount of material must be on the board before it is considered a match. @item Also match reversed colors @@ -1646,7 +1774,7 @@ on the lines in the game list, and their order. @subsection Sound Options @cindex Sound Options, Menu Item Summons a dialog where you can specify the sounds that should accompany -various events that can occur XBoard. +various events that can occur in XBoard. Most events are only relevant to ICS play, but the move sound is an important exception. For each event listed in the dialog, @@ -1819,6 +1947,7 @@ interchangeably. * Load and Save options:: Input/output options. * User interface options:: Look and feel options. * Adjudication Options:: Control adjudication of engine-engine games. +* Install options:: Maintaining and extending the XBoard install. * Other options:: Miscellaneous. @end menu @@ -1950,29 +2079,29 @@ Otherwise the same applies as for the @samp{-matchGames} option, over which it takes precedence if both are specified. (See there.) Default: 0 (do not run a match). @item -fcp or -firstChessProgram program +@itemx -scp or -secondChessProgram program @cindex fcp, option @cindex firstChessProgram, option -Name of first chess engine. -Default: @file{Fairy-Max}. -@item -scp or -secondChessProgram program @cindex scp, option @cindex secondChessProgram, option -Name of second chess engine, if needed. -A second chess engine is started only in Two Machines (match) mode. -Default: @file{Fairy-Max}. +Name of first and second chess engine, respectively. +A second chess engine is started only in Two Machines (match) mode, +or in Analyze mode with two engines. +The second engine is by default the same as the first. +Default for the first engine: @file{fairymax}. @item -fe or -firstEngine nickname +@itemx -se or -secondEngine nickname +@cindex se, option +@cindex secondEngine, option @cindex fe, option @cindex firstEngine, option -This is an alternative to the @code{fcp} option for specifying the first engine, -for engines that were already configured (using the @samp{Load Engine} dialog) +This is an alternative to the @code{fcp} and @code{scp} options +for specifying the first and second engine, +for engines that were already registered (using the @samp{Load Engine} dialog) in XBoard's settings file. It will not only retrieve the real name of the engine, but also all options configured with it. (E.g. if it is UCI, whether it should use book.) -@item -se or -secondEngine nickname -@cindex se, option -@cindex secondEngine, option -As @code{fe}, but for the second engine. @item -fb/-xfb or -firstPlaysBlack true/false @cindex fb, option @cindex firstPlaysBlack, option @@ -2111,6 +2240,11 @@ Forces shuffling of the opening setup in variants that normally have a fixed ini Shufflings are symmetric for black and white, and exempt King and Rooks in variants with normal castling. Remains in force until a new variant is selected. +@item -fischerCastling +@cindex fischerCastling, option +Specifies Fischer castling (as in Chess960) should be enabled in variants +that normally would not have it. +Remains in force until a new variant is selected. @end table @node UCI + WB Engine Settings @@ -2124,7 +2258,7 @@ Remains in force until a new variant is selected. @cindex sUCI, option @cindex firstIsUCI, option @cindex secondIsUCI, option -Indicates if the mentioned engine executable file is an UCI engine, +Indicates if the mentioned engine executable file is a UCI engine, and should be run with the aid of the Polyglot adapter rather than directly. Xboard will then pass the other UCI options and engine name to Polyglot on its command line, according to the option @code{adapterCommand}. @@ -2139,11 +2273,11 @@ on its command line, according to the option @code{adapterCommand}. Options similar to @code{fUCI} and @code{sUCI}, except that they use the indicated engine with the protocol adapter specified in the @samp{uxiAdapter} option. -This can then be configured for running an UCCI or USI adapter, +This can then be configured for running a UCCI or USI adapter, as the need arises. @item -adapterCommand string @cindex adapterCommand, option -The string conatins the command that should be issued by XBoard +The string contains the command that should be issued by XBoard to start an engine that is accompanied by the @code{fUCI} option. Any identifier following a percent sign in the command (e.g. %fcp) will be considered the name of an XBoard option, and be replaced @@ -2212,7 +2346,7 @@ in a book buffer. By playing an match in this mode, a book will be built from scratch. The only output are the saved games, which can be converted to an actual book later, with the @samp{Save Games as Book} command. -This command can also be used to pre-fill the book buffer +The latter command can also be used to pre-fill the book buffer before adding new games based on the probing algorithm. @item -fn string or -firstPgnName string @itemx -sn string or -secondPgnName string @@ -2222,7 +2356,7 @@ before adding new games based on the probing algorithm. @cindex sn, option Indicates the name that should be used for the engine in PGN tags of engine-engine games. -Intended to allow you to install verions of the same engine with different settings, +Intended to allow you to install versions of the same engine with different settings, and still distinguish them. Default: "". @item -defaultHashSize n @@ -2248,21 +2382,24 @@ e.g. "nalimov:/usr/local/share/egtb". If the name part matches that of a format that the engine requests through a feature command, xboard will relay the path name for this format to the engine through an egtpath command. One egtpath command for each matching format will be sent. -Popular formats are "nalimov" DTM tablebases and "scorpio" bitbases. +Popular formats are "nalimov" and "gaviota" DTM tablebases, +syzygy DTZ tablebases and "scorpio" bitbases. Default: "". @item -firstChessProgramNames=@{names@} -This option lets you customize the drop-down list of chess engine names -that appears in the @samp{Load Engine} and @samp{Match Options} dialog. +@cindex firstChessProgramNames, option +This option lets you customize the listbox with chess-engine names +that appears in the @samp{Load Engine} and @samp{Tournament Options} dialog. It consists of a list of strings, one per line. When an engine is loaded, the corresponding line is prefixed with "-fcp ", and processed like it appeared on the command line. That means that apart from the engine command, -it can contain any list of XBoard options you want to use with this engine. +it can contain any number of XBoard options you want to use with this engine. (Commonly used options here are -fd, -firstXBook, -fUCI, -variant.) The value of this option is gradually built as you load new engines through the @samp{Load Engine} menu dialog, with @samp{Add to list} ticked. -To change it, edit your settings file with a plain text editor. +To change it in other ways, (e.g. deleting engines), +use the menu item @samp{Edit Engine List} in the @samp{Engine} menu. @end table @node Tournament options @@ -2314,9 +2451,9 @@ The mentioned engines will play in the tourney. Volatile option, but stored in tourney file. @item -results string @cindex results, option -The string of +=- characters lists the result of all played games in a toruney. +The string of +=- characters lists the result of all played games in a tourney. Games currently playing are listed as *, -while a space indicates a game that is not yet played or playing . +while a space indicates a game that is not yet played. Volatile option, but stored in tourney file. @item -defaultTourneyName string @cindex defaultTourneyName, option @@ -2342,7 +2479,7 @@ where A and B are participant numbers (in the range 1-N). @cindex afterGame, option @cindex afterTourney, option When non-empty, the given string will be executed as a system command -after each tournament game, orafterthe tourney completes, respectively. +after each tournament game, or after the tourney completes, respectively. This can be used, for example, to autmatically run a cross-table generator on the PGN file where games are saved, to update the tourney standings. Default: "" @@ -2545,7 +2682,7 @@ will not be automatically displayed. Only a summary of time left and material of both players will appear in the message field above the board. XBoard will remember the last board it has received this way, -and will display it in stead of the position in your own game +and will display it instead of the position in your own game when you press the right mouse button. No other information is stored on such games observed in the background; you cannot save such a game later, or step through its moves. @@ -2689,7 +2826,12 @@ only if the colorizeMessages is on. CShout is synonymous with SShout. @item -soundMove filename @cindex soundMove, option -This sound is used by the Move Sound menu option. Default: "$". +This sound is played when a player other than yourself makes a move. +Default: "$". +@item -soundRoar filename +@cindex soundRoar, option +This sound is played when a Lion makes a hit-and-run or double capture/ +Default: "" (no sound). @item -soundIcsAlarm filename @cindex soundIcsAlarm, option This sound is used by the ICS Alarm menu option. Default: "$". @@ -2790,6 +2932,10 @@ first position of the file when it has reached a specified value. If this option is set, XBoard appends the final position reached in every game played to the specified file. The file name @file{-} specifies the standard output. +@item -positionDir directory +@cindex positionDir, option +Specifies the directory where file browsing should start when using +the @samp{Load Position} menu item. @item -pgnExtendedInfo true/false @cindex pgnExtendedInfo, option If this option is set, XBoard saves depth, score and time used for each @@ -2842,7 +2988,7 @@ So the settings will be saved to the file specified in the last -saveSettingsFile or succesfull -settingsFile / -ini command, if any, and in /etc/xboard/xboard.conf otherwise. Usualy the latter is only accessible for the system administrator, though, -and will be used to contain system-wide default setings, amongst which +and will be used to contain system-wide default settings, amongst which a -saveSettingsFile and -settingsFile options to specify a settings file accessible to the individual user, such as ~/.xboardrc in the user's home directory. @@ -2857,15 +3003,6 @@ Default: true. @cindex User interface options @cindex Options, User interface @table @asis -@item -display -@itemx -geometry -@itemx -iconic -@itemx -name -@cindex display, option -@cindex geometry, option -@cindex iconic, option -@cindex resource name, option -These and most other standard Xt options are accepted. @item -noGUI @cindex noGUI, option Suppresses all GUI functions of XBoard @@ -2886,12 +3023,14 @@ Default: 0. Specify the images to be used as player logos when @code{logoSize} is non-zero, next to the white and black clocks, respectively. @item -autoLogo true/false -@item -logoDir filename +@itemx -logoDir filename @cindex autoLogo, option @cindex logoDir, option When @code{autoLogo} is set, XBoard will search for a PNG image file with the name of the engine or ICS in the directory specified by @code{logoDir}. +For a human player it will look for a file .png in this +directory, but only when ~/.logo.png does not provide one. @item -recentEngines number @itemx -recentEngineList list @cindex recentEngines, option @@ -2906,17 +3045,6 @@ the last one is discarded. Changes in the list will only become visible the next session, provided you saved the settings. Default: 6. -@item -autoInstall list -@cindex autoInstall, option -When the list is set to a non-empty string, XBoard will scan the -operating system's plugin directory for engines supporting UCI -and XBoard protocol at startup. -When it finds an engine that was installed after it last saved -its settings, a line to launch that engine (as per specs in -the plugin file) is appended to the -firstChessProgramNames -list of installed engines. -In the future it will be possible to use the list to limit -this automatic adding of engines to a certain types of variants. @item -oneClickMove true/false @cindex oneClickMove, option When set, this option allows you to enter moves by only clicking the to- @@ -2925,6 +3053,11 @@ is possible. Double-clicking a piece (or clicking an already selected piece) will instruct that piece to make the only capture it can legally do. Default: false. +@item -monoMouse true/false +@cindex monoMouse, option +When set button 1 clicks on empty squares in Edit Position mode +will be interpreted as button 3 clicks, so they place a piece. +Default: false. @item -movesound/-xmovesound or -ringBellAfterMoves true/false @cindex movesound, option @cindex bell, option @@ -3132,7 +3265,8 @@ If the option value is a pattern that does not specify the font size, XBoard tries to choose an appropriate font for the board size being used. Default Xaw: -*-helvetica-medium-r-normal--*-*-*-*-*-*-*-*. -Default GTK: Sans Bold %d. +Default GTK: Sans Bold %d +@item -tagsFont font @cindex tagsFont, option @cindex Font, tags The font used in the Edit Tags dialog. @@ -3140,6 +3274,7 @@ If the option value contains %d, XBoard will replace it by an appropriate font for the board size being used. (Only used in GTK build.) Default: Sans Normal %d. +@item -commentFont font @cindex commentFont, option @cindex Font, comment The font used in the Edit Comment dialog. @@ -3147,6 +3282,7 @@ If the option value contains %d, XBoard will replace it by an appropriate font for the board size being used. (Only used in GTK build.) Default: Sans Normal %d. +@item -icsFont font @cindex icsFont, option @cindex Font, ics The font used to display ICS output in the ICS Chat window. @@ -3156,6 +3292,7 @@ If the option value contains %d, XBoard will replace it by an appropriate font for the board size being used. (Only used in GTK build.) Default: Monospace Normal %d. +@item -moveHistoryFont font @cindex moveHistoryFont, option @cindex Font, moveHistory The font used in Move History and Engine Output windows. @@ -3165,6 +3302,7 @@ If the option value contains %d, XBoard will replace it by an appropriate font for the board size being used. (Only used in GTK build.) Default: Sans Normal %d. +@item -gameListFont font @cindex gameListFont, option @cindex Font, gameList The font used in the listbox of the Game List window. @@ -3190,10 +3328,22 @@ XBoard will look in the specified directory for an image in png or svg format for every piece type, with names like BlackQueen.svg, WhiteKnight.svg etc. When neither of these is found (or no valid directory is specified) -XBoard will use the svg piece that was installed with it +XBoard will first ty to use an image White/BlackTile.svg in that same +directory, and if that is not present either +use the svg piece that was installed with it (from the source-tree directory @samp{svg}). Both svg and png images will be scaled by XBoard to the required size, but the png pieces lose much in quality when scaled too much. +Default: "". +@item -inscriptions utf8string +@cindex inscriptions, option +The positions in the utf8string correspond to XBoard's piece types, +and for each type a glyph can be defined. +This glyph will then be rendered on top of the image for the piece. +This is useful in combination with the White/BlackTile.svg images, +which could be the image of a blank Shogi tile, for writing the +kanji piece name on top of it on the fly. +Default: "". @item -whitePieceColor color @itemx -blackPieceColor color @@ -3327,9 +3477,9 @@ When it is off, the Shift key will be ignored. Default: False. @item -appendPV true|false @cindex appendPV, option -When this option is on, right-clicking a PV in the Engine Output window -will play the first move of that PV in Analyze mode, -or as many moves as you walk through by moving the mouse. +When this option is on, a button 3 click left of a PV in the Engine +Output window will play the first move of that PV in Analyze mode, +or as many moves as you walk through it by moving the mouse. Default: False. @item -absoluteAnalysisScores true|false @cindex absoluteAnalysisScores, option @@ -3346,7 +3496,7 @@ Default: False. @cindex memoHeaders, option When true, column headers will be displayed in the Engine Output window for the depth, score, time and nodes data. -Right-clicking on these headers will hide or show the corresponding data. +A button 3 click on these headers will hide or show the corresponding data. (Not intended for dynamic use, as already printed data of the current search will not be affected!) Defaul: False. @@ -3407,6 +3557,75 @@ Beware that positions that have different castling or en-passant rights do not c as repeats, XBoard is fully e.p. and castling aware! @end table +@node Install options +@section Install options +@cindex Options, install +@table @asis +@item --show-config parameter +@cindex show-config, option +When called with this option, XBoard will close immediately after printing the +value of the indicated configuration parameter, or, when no parameter was given, +after printing a list of all such parameters. +Currently the only valid values for parameter are Datadir and Sysconfdir. +This option can be used by install scripts for board themes +to figure out where the currently active XBoard stores its data. +@item -date timestamp +@itemx -saveDate timestamp +@cindex date, option +@cindex saveDate, option +These options specify an epoch as an integer number. +The @code{saveDate} option is written by XBoard in the settings file every time the +settings are saved, with the current time, so that later runs of XBoard can know this. +The @code{date} option can be included in settings files to indicate when lines +following it were added to those files. +Some options will be ignored if the epoch specified by the latest @code{date} option +predates the -saveDate setting (implying they must have been seen before). +@item -autoInstall list +@cindex autoInstall, option +When the list is set to a non-empty string, XBoard will scan the +operating system's plugin directory for engines supporting UCI +and XBoard protocol at startup. +When it finds an engine that was installed after it last saved +its settings, a line to launch that engine (as per specs in +the plugin file) is appended to the -firstChessProgramNames +list of installed engines. +In the future it will be possible to use the autoInstall list to limit +this automatic adding of engines based on the chess variant they play. +@item -addMasterOption string +@cindex addMasterOption, option +Adds the mentioned string as an additional line of XBoard's master settings file, +after adding a line with a @code{date} option to timestamp it. +Intended to add options of the 'install' type (see below) to the master file, +which will then be processed by any XBoard that has not seen them since +it last saved its settings. +@item -autoClose +@cindex autoClose, option +The presence of this option cause XBoard to close immediately after processing +all its options (from settings file and command line). +Typically used from install scripts together with options that change XBoard's +settings files, so that XBoard can be run in batch mode rather than interactively. +@item -installEngine string +@cindex installEngine, option +Adds the given string as an additional line to the value of the +@code{firstChessProgramNames} option when the -saveDate setting preceeds the -date setting. +Intended for adding to the master settings file with the aid of -addMasterOption +in the install script of engines, as a method for broadcasting the presence +of a new engine to all users, +which would then see it automatically registered with XBoard. +Made obsolete by the advent of the plugin standard (see the @code{autoInstall} option), +which broadcasts such presence in a non-XBoard-specific way +by dropping *.eng files in a certain system directory. +@item -installTheme string +@cindex installTheme, option +Adds the given string as an additional line to the value of the +-themeNames option when the -saveDate setting preceeds the -date setting. +Intended for adding to the master settings file with the aid of -addMasterOption +in the install script of board graphics themes, +as a method for broadcasting the availability of a new theme to all users, +who would then see the theme appear automatically in the listbox in the +View Board menu dialog next time they run XBoard. +@end table + @node Other options @section Other options @cindex Options, miscellaneous @@ -3439,7 +3658,7 @@ Default: "-ncp -engineOutputUp false -saveSettingsOnExit false". When XBoard is invoked with a single argument that is a file with .trn extension, it will assume this argument to be the value of a @code{tourneyFile} option, -and apped the value of the persistent option @code{tourneyOptions} +and append the value of the persistent option @code{tourneyOptions} as stored in the settings file to the command line. Thus the value of @code{tourneyOptions} can be used to configure XBoard to automatically start running a @@ -3456,7 +3675,7 @@ MachineWhite, MachineBlack, TwoMachines, Analysis, AnalyzeFile, EditGame, EditPosition, and Training. @item -variant varname @cindex variant, option -Activates preliminary, partial support for playing chess variants +Activates (sometimes partial) support for playing chess variants against a local engine or editing variant games. This flag is not needed in ICS mode. Recognized variant names are: @@ -3485,37 +3704,44 @@ janus A game with two Archbishops (10x8 board) courier Medieval intermediate between shatranj and modern Chess (on 12x8 board) falcon Patented 10x8 variant with two Falcon pieces -berolina Pawns capture straight ahead, and move diagonal +berolina Pawns capture straight ahead, and move diagonally cylinder Pieces wrap around the board edge knightmate King moves as Knight, and vice versa super Superchess (shuffle variant with 4 exo-pieces) makruk Thai Chess (shatranj-like, P promotes on 6th rank) asean ASEAN Chess (a modernized version of Makruk) spartan Spartan Chess (black has unorthodox pieces) +great Great Shatranj, a 10x8 variant without sliders +grand Grand Chess, on 10x10 with Capablanca pieces +lion Mighty-Lion Chess, with a multi-capturing Lion +elven Eleven Chess, with Lion and crowned sliders on 10x10 +chu Chu Shogi, historic 12x12 variant with 2x46 pieces fairy A catchall variant in which all piece types known to XBoard can participate (8x8) unknown Catchall for other unknown variants @end example -NOT ALL BOARDSIZES PROVIDE A COMPLETE SET OF BUILT-IN BITMAPS FOR ALL -UN-ORTHODOX PIECES, though. Only in @code{boardSize} middling and bulky -all 22 piece types are provided, while -boardSize petite has most -of them. Archbishop, Chancellor and Amazon are supported in every -size from petite to bulky. Kings or Amazons are substituted for -missing bitmaps. You can still play variants needing un-orthodox -pieces in other board sizes providing your own bitmaps through the -@code{bitmapDirectory} or @code{pixmapDirectory} options. - -In the shuffle variants, XBoard now does shuffle the pieces, although +In the shuffle variants, XBoard does shuffle the pieces, although you can still do it by hand using Edit Position. Some variants are supported only in ICS mode, including bughouse, and -kriegspiel. The winning/drawing conditions in crazyhouse (off-board -interposition on mate) are not fully understood, but losers, suicide, -giveaway, atomic, and 3check should be OK. -Berolina and cylinder chess can only be played with legality testing off. -In crazyhouse, XBoard now does keep -track of off-board pieces. In shatranj it does implement the baring -rule when mate detection is switched on. +kriegspiel. +Berolina and cylinder chess are only partially supported, +and can only be played with legality testing off. + +Apart from these standard variants, engines can define variants +of arbitrary names, briefing XBoard transparently on the rules +for piece movement, board size and initial setup, +so that they work nearly as well as fully-supported standard variants. +(But obviously only while using that engine.) +The user might have to alter the adjudication settings for some +variants, however. E.g. it makes no sense to adjudicate a draw +after 50 reversible moves in variants that have a 64-move rule, +or no similar rule at all. + +Default: "normal". Except when the first engine gave an explicit list +of variants it supports, and 'normal' is not amongst those. +In that case the first variant the engine mentioned it did play will +be chosen. @item -boardHeight N @cindex boardHeight, option Allows you to set a non-standard number of board ranks in any variant. @@ -3545,25 +3771,34 @@ Default: -1 @item -pieceToCharTable string @cindex pieceToCharTable, option The characters that are used to represent the piece types XBoard knows in FEN -diagrams and SAN moves. The string argument has to have an even length +diagrams and SAN moves. +You should not have to use this option often: each variant has its own default +setting for the piece representation in FEN, which should be sufficient in normal use. +The string argument has to specify an even number of pieces (or it will be ignored), as white and black pieces have to be given separately (in that order). The last letter for each color will be the King. The letters before that will be PNBRQ and then a whole host of fairy pieces -in an order that has not fully crystallized yet (currently FEACWMOHIJGDVSLU, +in an order that has not fully crystallized yet (currently FEACWMOHIJGDVLSU, F=Ferz, Elephant, A=Archbishop, C=Chancellor, W=Wazir, M=Commoner, O=Cannon, H=Nightrider). You should list at least all pieces that occur in the variant -you are playing. If you have less than 44 characters in the string, the pieces -not mentioned will get assigned a period, and you will not be able to distinguish -them in FENs. You can also explicitly assign pieces a period, in which case they +you are playing. If you have fewer characters in the string than XBoard has +pieces, the pieces not mentioned will get assigned a period, +and will not be usable in the variant. +You can also explicitly assign pieces a period, in which case they will not be counted in deciding which captured pieces can go into the holdings. A tilde '~' as a piece name does mean this piece is used to represent a promoted -Pawn in crazyhouse-like games, i.e. on capture it turns back onto a Pawn. +Pawn in crazyhouse-like games, i.e. on capture it turns back to a Pawn. A '+' similarly indicates the piece is a shogi-style promoted piece, that should revert to its non-promoted version on capture (rather than to a Pawn). -Note that promoted pieces are represented by pieces 11 further in the list. -You should not have to use this option often: each variant has its own default -setting for the piece representation in FEN, which should be sufficient in normal use. -Default: "" +By default the second 11 pieces known to XBoard are the promoted forms of the first 11. +A piece specified by the character combination ^ plus letter will be assumed +to be the promoted form of the piece indicated by that letter, +and get a '+' assigned. +To get around the limitation of the alphabet, +piece IDs can also be 'dressed letters', i.e. a single letter +(upper case for white, lower case for black) +followed by a single quote or an exclamation point. +Default: "" (meaning the default for the variant is used). @item -pieceNickNames string @cindex pieceNickNames, option The characters in the string are interpreted the same way as in the