From: H.G. Muller Date: Sun, 19 Apr 2009 16:39:19 +0000 (-0700) Subject: changes by H.G. Muller; version 4.3.4 X-Git-Tag: v4.3.4 X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=7e4f4f5718bf4efee8be4abfc981d18cfd6f8438;p=xboard.git changes by H.G. Muller; version 4.3.4 --- diff --git a/backend.c b/backend.c index 29ebca6..f3cffc5 100644 --- a/backend.c +++ b/backend.c @@ -421,36 +421,47 @@ ChessSquare twoKingsArray[2][BOARD_SIZE] = { { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteKing, WhiteKing, WhiteKnight, WhiteRook }, { BlackRook, BlackKnight, BlackBishop, BlackQueen, - BlackKing, BlackKing, BlackKnight, BlackRook } + BlackKing, BlackKing, BlackKnight, BlackRook } }; #ifdef FAIRY +ChessSquare KnightmateArray[2][BOARD_SIZE] = { + { WhiteRook, WhiteMan, WhiteBishop, WhiteQueen, + WhiteUnicorn, WhiteBishop, WhiteMan, WhiteRook }, + { BlackRook, BlackMan, BlackBishop, BlackQueen, + BlackUnicorn, BlackBishop, BlackMan, BlackRook } +}; + ChessSquare fairyArray[2][BOARD_SIZE] = { /* [HGM] Queen side differs from King side */ - { WhiteFairyRook, WhiteFairyKnight, WhiteFairyBishop, WhiteQueen, + { WhiteCannon, WhiteNightrider, WhiteAlfil, WhiteQueen, WhiteKing, WhiteBishop, WhiteKnight, WhiteRook }, - { BlackFairyRook, BlackFairyKnight, BlackFairyBishop, BlackQueen, + { BlackCannon, BlackNightrider, BlackAlfil, BlackQueen, BlackKing, BlackBishop, BlackKnight, BlackRook } }; ChessSquare ShatranjArray[2][BOARD_SIZE] = { /* [HGM] (movGen knows about Shatranj Q and P) */ - { WhiteRook, WhiteKnight, WhiteFairyBishop, WhiteFairyPawn, - WhiteKing, WhiteFairyBishop, WhiteKnight, WhiteRook }, - { BlackRook, BlackKnight, BlackFairyBishop, BlackFairyPawn, - BlackKing, BlackFairyBishop, BlackKnight, BlackRook } + { WhiteRook, WhiteKnight, WhiteAlfil, WhiteFerz, + WhiteKing, WhiteAlfil, WhiteKnight, WhiteRook }, + { BlackRook, BlackKnight, BlackAlfil, BlackFerz, + BlackKing, BlackAlfil, BlackKnight, BlackRook } +}; + + +#if (BOARD_SIZE>=10) +ChessSquare ShogiArray[2][BOARD_SIZE] = { + { WhiteQueen, WhiteKnight, WhiteFerz, WhiteWazir, + WhiteKing, WhiteWazir, WhiteFerz, WhiteKnight, WhiteQueen }, + { BlackQueen, BlackKnight, BlackFerz, BlackWazir, + BlackKing, BlackWazir, BlackFerz, BlackKnight, BlackQueen } }; -#if (BOARD_SIZE>=9) ChessSquare XiangqiArray[2][BOARD_SIZE] = { - { WhiteRook, WhiteKnight, WhiteFairyBishop, WhiteFairyPawn, - WhiteKing, WhiteFairyPawn, WhiteFairyBishop, WhiteKnight, WhiteRook }, - { BlackRook, BlackKnight, BlackFairyBishop, BlackFairyPawn, - BlackKing, BlackFairyPawn, BlackFairyBishop, BlackKnight, BlackRook } + { WhiteRook, WhiteKnight, WhiteAlfil, WhiteFerz, + WhiteWazir, WhiteFerz, WhiteAlfil, WhiteKnight, WhiteRook }, + { BlackRook, BlackKnight, BlackAlfil, BlackFerz, + BlackWazir, BlackFerz, BlackAlfil, BlackKnight, BlackRook } }; -#else -#define XiangqiPosition FIDEPosition -#endif -#if (BOARD_SIZE>=10) ChessSquare CapablancaArray[2][BOARD_SIZE] = { { WhiteRook, WhiteKnight, WhiteCardinal, WhiteBishop, WhiteQueen, WhiteKing, WhiteBishop, WhiteMarshall, WhiteKnight, WhiteRook }, @@ -470,16 +481,17 @@ ChessSquare GothicArray[2][BOARD_SIZE] = { #endif // !GOTHIC #else // !(BOARD_SIZE>=10) +#define XiangqiPosition FIDEArray #define CapablancaArray FIDEArray #define GothicArray FIDEArray #endif // !(BOARD_SIZE>=10) #if (BOARD_SIZE>=12) ChessSquare CourierArray[2][BOARD_SIZE] = { - { WhiteRook, WhiteKnight, WhiteFairyBishop, WhiteBishop, WhiteFairyKing, WhiteKing, - WhiteFairyPawn, WhiteFairyRook, WhiteBishop, WhiteFairyBishop, WhiteKnight, WhiteRook }, - { BlackRook, BlackKnight, BlackFairyBishop, BlackBishop, BlackFairyKing, BlackKing, - BlackFairyPawn, BlackFairyRook, BlackBishop, BlackFairyBishop, BlackKnight, BlackRook } + { WhiteRook, WhiteKnight, WhiteAlfil, WhiteBishop, WhiteMan, WhiteKing, + WhiteFerz, WhiteWazir, WhiteBishop, WhiteAlfil, WhiteKnight, WhiteRook }, + { BlackRook, BlackKnight, BlackAlfil, BlackBishop, BlackMan, BlackKing, + BlackFerz, BlackWazir, BlackBishop, BlackAlfil, BlackKnight, BlackRook } }; #else // !(BOARD_SIZE>=12) #define CourierArray CapablancaArray @@ -733,25 +745,31 @@ InitBackEnd1() case VariantLoadable: case Variant29: case Variant30: -#ifndef FAIRY case Variant31: case Variant32: case Variant33: case Variant34: case Variant35: case Variant36: -#endif default: sprintf(buf, "Unknown variant name %s", appData.variant); DisplayFatalError(buf, 0, 2); return; + case VariantXiangqi: /* [HGM] repetition rules not implemented */ + case VariantFairy: /* [HGM] TestLegality definitely off! */ + case VariantGothic: /* [HGM] should work */ + case VariantCapablanca: /* [HGM] should work */ + case VariantCourier: /* [HGM] initial forced moves not implemented */ + case VariantShogi: /* [HGM] drops not tested for legality */ + case VariantShowgi: /* [HGM] not a valid variant */ + case VariantKnightmate: /* [HGM] should work */ + case VariantCrazyhouse: /* holdings not shown, ([HGM] fixed that!) + offboard interposition not understood */ case VariantNormal: /* definitely works! */ case VariantWildCastle: /* pieces not automatically shuffled */ case VariantNoCastle: /* pieces not automatically shuffled */ case VariantFischeRandom: /* Fabien: pieces not automatically shuffled */ - case VariantCrazyhouse: /* holdings not shown, - offboard interposition not understood */ case VariantLosers: /* should work except for win condition, and doesn't know captures are mandatory */ case VariantSuicide: /* should work except for win condition, @@ -762,14 +780,6 @@ InitBackEnd1() case VariantAtomic: /* should work except for win condition */ case Variant3Check: /* should work except for win condition */ case VariantShatranj: /* might work if TestLegality is off */ -#ifdef FAIRY - case VariantShogi: - case VariantXiangqi: - case VariantFairy: /* [HGM] TestLegality definitely off! */ - case VariantGothic: - case VariantCapablanca: - case VariantCourier: -#endif break; } } @@ -1355,7 +1365,14 @@ StringToVariant(e) char buf[MSG_SIZ]; if (!e) return v; - + + /* [HGM] skip over optional board-size prefixes */ + if( sscanf(e, "%dx%d+%d_", &i, &i, &i) == 3 ) { + while( *e++ != '_'); + } else if( sscanf(e, "%dx%d_", &i, &i) == 2 ) { + while( *e++ != '_'); + } + for (i=0; i= BlackPawn ) { + holdingsColumn = 0; + countsColumn = 1; + holdingsStartRow = BOARD_HEIGHT-1; + direction = 1; + } else { + holdingsColumn = BOARD_WIDTH-1; + countsColumn = BOARD_WIDTH-2; + holdingsStartRow = 0; + direction = 1; + } + + for(i=0; i= gameInfo.holdingsSize) continue; /* ignore pieces that do not fit */ + if(j < 0) continue; /* should not happen */ + piece = (ChessSquare) ( (int)piece + (int)lowestPiece ); + board[holdingsStartRow+i*direction][holdingsColumn] = piece; + board[holdingsStartRow+i*direction][countsColumn]++; + } + +} + static int loggedOn = FALSE; /*-- Game start info cache: --*/ @@ -2725,9 +2781,9 @@ read_from_ics(isr, closure, data, count, error) ClearPremoveHighlights(); if (appData.debugMode) fprintf(debugFP, "Sending premove:\n"); - UserMoveEvent(premoveFromX, premoveFromY, + UserMoveEvent(premoveFromX, premoveFromY, premoveToX, premoveToY, - premovePromoChar); + premovePromoChar); } } @@ -2780,6 +2836,10 @@ read_from_ics(isr, closure, data, count, error) gameInfo.white, white_holding, gameInfo.black, black_holding); } + + /* [HGM] copy holdings to board holdings area */ + CopyHoldings(boards[currentMove], white_holding, WhitePawn); + CopyHoldings(boards[currentMove], black_holding, BlackPawn); DrawPosition(FALSE, NULL); DisplayTitle(str); } @@ -2997,6 +3057,20 @@ ParseBoard12(string) movesPerSession = 0; gameInfo.timeControl = TimeControlTagValue(); gameInfo.variant = StringToVariant(gameInfo.event); + gameInfo.holdingsSize = 5; /* [HGM] prepare holdings */ + switch(gameInfo.variant) { + case VariantShogi: + case VariantShowgi: + gameInfo.boardWidth = gameInfo.boardHeight = 9; + gameInfo.holdingsSize += 2; + case VariantBughouse: + case VariantCrazyhouse: + gameInfo.boardWidth = gameInfo.boardHeight = 8; + gameInfo.holdingsWidth = 2; break; + default: + gameInfo.boardWidth = gameInfo.boardHeight = 8; + gameInfo.holdingsWidth = 0; + } gameInfo.outOfBook = NULL; /* Do we have the ratings? */ @@ -3343,9 +3417,9 @@ SendMoveToProgram(moveNum, cps) * the engine. It would be nice to have a better way to identify castle * moves here. */ if(gameInfo.variant == VariantFischeRandom && cps->useOOCastle) { - int fromX = moveList[moveNum][0] - 'a'; + int fromX = moveList[moveNum][0] - AAA; int fromY = moveList[moveNum][1] - ONE; - int toX = moveList[moveNum][2] - 'a'; + int toX = moveList[moveNum][2] - AAA; int toY = moveList[moveNum][3] - ONE; if((boards[currentMove][fromY][fromX] == WhiteKing && boards[currentMove][toY][toX] == WhiteRook) @@ -3411,21 +3485,21 @@ SendMoveToICS(moveType, fromX, fromY, toX, toY) case BlackPromotionArchbishop: #endif sprintf(user_move, "%c%c%c%c=%c\n", - 'a' + fromX, ONE + fromY, 'a' + toX, ONE + toY, + AAA + fromX, ONE + fromY, AAA + toX, ONE + toY, PieceToChar(PromoPiece(moveType))); break; case WhiteDrop: case BlackDrop: sprintf(user_move, "%c@%c%c\n", ToUpper(PieceToChar((ChessSquare) fromX)), - 'a' + toX, ONE + toY); + AAA + toX, ONE + toY); break; case NormalMove: case WhiteCapturesEnPassant: case BlackCapturesEnPassant: case IllegalMove: /* could be a variant we don't quite understand */ sprintf(user_move, "%c%c%c%c\n", - 'a' + fromX, ONE + fromY, 'a' + toX, ONE + toY); + AAA + fromX, ONE + fromY, AAA + toX, ONE + toY); break; } SendToICS(user_move); @@ -3439,16 +3513,17 @@ CoordsToComputerAlgebraic(rf, ff, rt, ft, promoChar, move) { if (rf == DROP_RANK) { sprintf(move, "%c@%c%c\n", - ToUpper(PieceToChar((ChessSquare) ff)), 'a' + ft, ONE + rt); + ToUpper(PieceToChar((ChessSquare) ff)), AAA + ft, ONE + rt); } else { if (promoChar == 'x' || promoChar == NULLCHAR) { sprintf(move, "%c%c%c%c\n", - 'a' + ff, ONE + rf, 'a' + ft, ONE + rt); + AAA + ff, ONE + rf, AAA + ft, ONE + rt); } else { sprintf(move, "%c%c%c%c%c\n", - 'a' + ff, ONE + rf, 'a' + ft, ONE + rt, promoChar); + AAA + ff, ONE + rf, AAA + ft, ONE + rt, promoChar); } } + AlphaRank(move, 4); } void @@ -3465,6 +3540,22 @@ ProcessICSInitScript(f) } +/* [HGM] Shogi move preprocessor: swap digits for letters, vice versa */ +void +AlphaRank(char *move, int n) +{ + char *p = move, c; + + if( !appData.alphaRank ) return; + + while(c = *p) { + if(c>='0' && c<='9') *p += 'a'-'0'; else + if(c>='a' && c<='z') *p -= 'a'-'0'; + p++; + if(--n < 1) break; + } +} + /* Parser for moves from gnuchess, ICS, or user typein box */ Boolean ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar) @@ -3474,6 +3565,10 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar) int *fromX, *fromY, *toX, *toY; char *promoChar; { + if (appData.debugMode) { + fprintf(debugFP, "move to parse: %s\n", move); + } + AlphaRank(move, 10); *moveType = yylexstr(moveNum, move); switch (*moveType) { @@ -3511,13 +3606,13 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar) case BlackASideCastleFR: /* End of code added by Tord */ case IllegalMove: /* bug or odd chess variant */ - *fromX = currentMoveString[0] - 'a'; + *fromX = currentMoveString[0] - AAA; *fromY = currentMoveString[1] - ONE; - *toX = currentMoveString[2] - 'a'; + *toX = currentMoveString[2] - AAA; *toY = currentMoveString[3] - ONE; *promoChar = currentMoveString[4]; - if (*fromX < 0 || *fromX >= BOARD_WIDTH || *fromY < 0 || *fromY >= BOARD_HEIGHT || - *toX < 0 || *toX >= BOARD_WIDTH || *toY < 0 || *toY >= BOARD_HEIGHT) { + if (*fromX < BOARD_LEFT || *fromX >= BOARD_RGHT || *fromY < 0 || *fromY >= BOARD_HEIGHT || + *toX < BOARD_LEFT || *toX >= BOARD_RGHT || *toY < 0 || *toY >= BOARD_HEIGHT) { *fromX = *fromY = *toX = *toY = 0; return FALSE; } @@ -3533,7 +3628,7 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar) (int) CharToPiece(ToUpper(currentMoveString[0])) : (int) CharToPiece(ToLower(currentMoveString[0])); *fromY = DROP_RANK; - *toX = currentMoveString[2] - 'a'; + *toX = currentMoveString[2] - AAA; *toY = currentMoveString[3] - ONE; *promoChar = NULLCHAR; return TRUE; @@ -3591,7 +3686,7 @@ static void ShuffleFRC( Board board ) board[0][FindEmptySquare(board, 0)] = WhiteKing; board[0][FindEmptySquare(board, 0)] = WhiteRook; - for( i=0; i>1; - castlingRights[0][3] = initialRights[3] = BOARD_WIDTH-1; - castlingRights[0][4] = initialRights[4] = 0; + castlingRights[0][3] = initialRights[3] = BOARD_RGHT-1; + castlingRights[0][4] = initialRights[4] = BOARD_LEFT; castlingRights[0][5] = initialRights[5] = BOARD_WIDTH>>1; castlingRank[0] = castlingRank[1] = castlingRank[2] = 0; @@ -3683,15 +3781,17 @@ InitPosition(redraw) /* empty squares. This initial position is then copied to boards[0], */ /* possibly after shuffling, so that it remains available. */ + gameInfo.holdingsWidth = 0; /* default board sizes */ + gameInfo.boardWidth = 8; + gameInfo.boardHeight = 8; + gameInfo.holdingsSize = 0; + switch (gameInfo.variant) { default: - pieces = BOARD_WIDTH <= 8 ? FIDEArray : - BOARD_WIDTH <= 10 ? CapablancaArray : CourierArray; + pieces = FIDEArray; break; case VariantShatranj: pieces = ShatranjArray; - CharToPiece('E'); /* associate PGN/FEN letter with internal piece type */ - CharToPiece('e'); nrCastlingRights = 0; for(i=0; i= 0) { + if(gameInfo.boardWidth != appData.NrFiles) overrule++; + gameInfo.boardWidth = appData.NrFiles; + } + if(appData.NrRanks >= 0) { + if(gameInfo.boardHeight != appData.NrRanks) overrule++; + gameInfo.boardHeight = appData.NrRanks; + } + if(appData.holdingsSize >= 0) { + i = appData.holdingsSize; + if(i > gameInfo.boardHeight) i = gameInfo.boardHeight; + gameInfo.holdingsSize = i; + } + if(gameInfo.holdingsSize) gameInfo.holdingsWidth = 2; + if(BOARD_HEIGHT > BOARD_SIZE || BOARD_WIDTH > BOARD_SIZE) + DisplayFatalError("Recompile to support this BOARD_SIZE!", 0, 2); + + pawnRow = gameInfo.boardHeight - 7; /* seems to work in all variants */ + + /* User pieceToChar list overrules defaults */ + if(appData.pieceToCharTable != NULL) + strcpy(pieceToChar, appData.pieceToCharTable); + + for( j=0; j= BOARD_RGHT || overrule) continue; + initialPosition[0][j] = pieces[0][j-gameInfo.holdingsWidth]; + initialPosition[pawnRow][j] = WhitePawn; + initialPosition[BOARD_HEIGHT-pawnRow-1][j] = BlackPawn; if(gameInfo.variant == VariantXiangqi) { if(j&1) { - initialPosition[3][j] = - initialPosition[BOARD_HEIGHT-4][j] = EmptySquare; - if(j==1 || j>=BOARD_WIDTH-2) { - initialPosition[2][j] = WhiteFairyMarshall; - initialPosition[BOARD_HEIGHT-3][j] = BlackFairyMarshall; + initialPosition[pawnRow][j] = + initialPosition[BOARD_HEIGHT-pawnRow-1][j] = EmptySquare; + if(j==BOARD_LEFT+1 || j>=BOARD_RGHT-2) { + initialPosition[2][j] = WhiteCannon; + initialPosition[BOARD_HEIGHT-3][j] = BlackCannon; } - } else { - initialPosition[3][j] = WhitePawn; - initialPosition[BOARD_HEIGHT-4][j] = BlackPawn; } - } else { - initialPosition[1][j] = WhitePawn; - initialPosition[BOARD_HEIGHT-2][j] = BlackPawn; } - initialPosition[BOARD_HEIGHT-1][j] = pieces[1][j]; + initialPosition[BOARD_HEIGHT-1][j] = pieces[1][j-gameInfo.holdingsWidth]; + } + if( (gameInfo.variant == VariantShogi + ||gameInfo.variant == VariantShowgi + ) && !overrule ) { + j=BOARD_LEFT+1; + initialPosition[1][j] = WhiteBishop; + initialPosition[BOARD_HEIGHT-2][j] = BlackRook; + j=BOARD_RGHT-2; + initialPosition[1][j] = WhiteRook; + initialPosition[BOARD_HEIGHT-2][j] = BlackBishop; } if(gameInfo.variant == VariantFischeRandom) { @@ -3770,6 +3940,11 @@ InitPosition(redraw) CopyBoard(boards[0], initialPosition); + if(oldx != gameInfo.boardWidth || + oldy != gameInfo.boardHeight || + oldh != gameInfo.holdingsWidth ) + InitDrawingSizes(-1 ,0); + if (redraw) DrawPosition(TRUE, boards[currentMove]); } @@ -3799,10 +3974,10 @@ SendBoard(cps, moveNum) SendToProgram("#\n", cps); for (i = BOARD_HEIGHT - 1; i >= 0; i--) { bp = &boards[moveNum][i][0]; - for (j = 0; j < BOARD_WIDTH; j++, bp++) { + for (j = BOARD_LEFT; j < BOARD_RGHT; j++, bp++) { if ((int) *bp < (int) BlackPawn) { sprintf(message, "%c%c%c\n", PieceToChar(*bp), - 'a' + j, ONE + i); + AAA + j, ONE + i); SendToProgram(message, cps); } } @@ -3811,11 +3986,11 @@ SendBoard(cps, moveNum) SendToProgram("c\n", cps); for (i = BOARD_HEIGHT - 1; i >= 0; i--) { bp = &boards[moveNum][i][0]; - for (j = 0; j < BOARD_WIDTH; j++, bp++) { + for (j = BOARD_LEFT; j < BOARD_RGHT; j++, bp++) { if (((int) *bp != (int) EmptySquare) && ((int) *bp >= (int) BlackPawn)) { sprintf(message, "%c%c%c\n", ToUpper(PieceToChar(*bp)), - 'a' + j, ONE + i); + AAA + j, ONE + i); SendToProgram(message, cps); } } @@ -3829,19 +4004,45 @@ int IsPromotion(fromX, fromY, toX, toY) int fromX, fromY, toX, toY; { - return gameMode != EditPosition && gameInfo.variant != VariantXiangqi && - fromX >=0 && fromY >= 0 && toX >= 0 && toY >= 0 && - ((boards[currentMove][fromY][fromX] == WhitePawn && toY == BOARD_HEIGHT-1) || - (boards[currentMove][fromY][fromX] == BlackPawn && toY == 0)); + /* [HGM] add Shogi promotions */ + int promotionZoneSize=1, highestPromotingPiece = (int)WhitePawn; + ChessSquare piece; + + if(gameMode == EditPosition || gameInfo.variant == VariantXiangqi || + !(fromX >=0 && fromY >= 0 && toX >= 0 && toY >= 0) ) return FALSE; + /* [HGM] Note to self: line above also weeds out drops */ + piece = boards[currentMove][fromY][fromX]; + if(gameInfo.variant == VariantShogi) { + promotionZoneSize = 3; + highestPromotingPiece = (int)WhiteFerz; /* Silver */ + } + if((int)piece >= BlackPawn) { + if(toY >= promotionZoneSize && fromY >= promotionZoneSize) + return FALSE; + highestPromotingPiece = WHITE_TO_BLACK highestPromotingPiece; + } else { + if( toY < BOARD_HEIGHT - promotionZoneSize && + fromY < BOARD_HEIGHT - promotionZoneSize) return FALSE; + } + return ( (int)piece <= highestPromotingPiece ); } +int +InPalace(row, column) + int row, column; +{ /* [HGM] for Xiangqi */ + if( (row < 3 || row > BOARD_HEIGHT-4) && + column < (BOARD_WIDTH + 4)/2 && + column > (BOARD_WIDTH - 5)/2 ) return TRUE; + return FALSE; +} int PieceForSquare (x, y) int x; int y; { - if (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT) + if (x < BOARD_LEFT || x >= BOARD_RGHT || y < 0 || y >= BOARD_HEIGHT) return -1; else return boards[currentMove][y][x]; @@ -3958,17 +4159,19 @@ char lastLoadGameTitle[MSG_SIZ], lastLoadPositionTitle[MSG_SIZ]; ChessMove lastLoadGameStart = (ChessMove) 0; -void -UserMoveEvent(fromX, fromY, toX, toY, promoChar) +ChessMove +UserMoveTest(fromX, fromY, toX, toY, promoChar) int fromX, fromY, toX, toY; int promoChar; { ChessMove moveType; - if (fromX < 0 || fromY < 0) return; + if (fromX < 0 || fromY < 0) return ImpossibleMove; if ((fromX == toX) && (fromY == toY)) { - return; + return ImpossibleMove; } + /* [HGM] suppress all moves into holdings area and guard band */ + if( toX < BOARD_LEFT || toX >= BOARD_RGHT ) return ImpossibleMove; /* Check if the user is playing in turn. This is complicated because we let the user "pick up" a piece before it is his turn. So the piece he @@ -3990,13 +4193,13 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar) case IcsIdle: /* We switched into a game mode where moves are not accepted, perhaps while the mouse button was down. */ - return; + return ImpossibleMove; case MachinePlaysWhite: /* User is moving for Black */ if (WhiteOnMove(currentMove)) { DisplayMoveError("It is White's turn"); - return; + return ImpossibleMove; } break; @@ -4004,7 +4207,7 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar) /* User is moving for White */ if (!WhiteOnMove(currentMove)) { DisplayMoveError("It is Black's turn"); - return; + return ImpossibleMove; } break; @@ -4018,13 +4221,13 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar) /* User is moving for Black */ if (WhiteOnMove(currentMove)) { DisplayMoveError("It is White's turn"); - return; + return ImpossibleMove; } } else { /* User is moving for White */ if (!WhiteOnMove(currentMove)) { DisplayMoveError("It is Black's turn"); - return; + return ImpossibleMove; } } break; @@ -4046,7 +4249,7 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar) "fromY %d, toX %d, toY %d\n", fromX, fromY, toX, toY); } - return; + return ImpossibleMove; } break; @@ -4067,7 +4270,7 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar) "fromY %d, toX %d, toY %d\n", fromX, fromY, toX, toY); } - return; + return ImpossibleMove; } break; @@ -4083,10 +4286,17 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar) boards[0][fromY][fromX] = EmptySquare; DrawPosition(FALSE, boards[currentMove]); } - return; + return ImpossibleMove; + } + + if (toX < 0 || toY < 0) return ImpossibleMove; + + /* [HGM] If move started in holdings, it means a drop */ + if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) { + if( boards[currentMove][toY][toX] != EmptySquare ) return ImpossibleMove; + return WhiteDrop; /* Not needed to specify white or black yet */ } - if (toX < 0 || toY < 0) return; userOfferedDraw = FALSE; if (appData.testLegality) { @@ -4095,12 +4305,45 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar) fromY, fromX, toY, toX, promoChar); if (moveType == IllegalMove || moveType == ImpossibleMove) { DisplayMoveError("Illegal move"); - return; + return ImpossibleMove; } } else { moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar); } + return moveType; + /* [HGM] in stead of calling FinishMove directly, this + function is made into one that returns an OK move type if FinishMove + should be called. This to give the calling driver routine the + opportunity to finish the userMove input with a promotion popup, + without bothering the user with this for invalid or illegal moves */ + +/* FinishMove(moveType, fromX, fromY, toX, toY, promoChar); */ +} + +/* Common tail of UserMoveEvent and DropMenuEvent */ +void +FinishMove(moveType, fromX, fromY, toX, toY, promoChar) + ChessMove moveType; + int fromX, fromY, toX, toY; + /*char*/int promoChar; +{ + /* [HGM] kludge to avoid having know the exact promotion + move type in caller when we know the move is a legal promotion */ + if(moveType == NormalMove) + moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar); + + /* [HGM] convert drag-and-drop piece drops to standard form */ + if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) { + moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop; + fromX = boards[currentMove][fromY][fromX]; + fromY = DROP_RANK; + } + + /* [HGM] The following if has been moved here from + UserMoveEnevt(). Because it seemed to belon here (why not allow + piece drops in training games?), and because it can only be + performed after it is known to what we promote. */ if (gameMode == Training) { /* compare the move played on the board to the next move in the * game. If they match, display the move and the opponent's response. @@ -4136,16 +4379,6 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar) return; } - FinishMove(moveType, fromX, fromY, toX, toY, promoChar); -} - -/* Common tail of UserMoveEvent and DropMenuEvent */ -void -FinishMove(moveType, fromX, fromY, toX, toY, promoChar) - ChessMove moveType; - int fromX, fromY, toX, toY; - /*char*/int promoChar; -{ /* Ok, now we know that the move is good, so we can kill the previous line in Analysis Mode */ if (gameMode == AnalyzeMode && currentMove < forwardMostMove) { @@ -4236,6 +4469,26 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar) } } +void +UserMoveEvent(fromX, fromY, toX, toY, promoChar) + int fromX, fromY, toX, toY; + int promoChar; +{ + /* [HGM] This routine was added to allow calling of its two logical + parts from other modules in the old way. Before, UserMoveEvent() + automatically called FinishMove() if the move was OK, and returned + otherwise. I separated the two, in order to make it possible to + slip a promotion popup in between. But that it always needs two + calls, to the first part, (now called UserMoveTest() ), and to + FinishMove if the first part succeeded. Calls that do not need + to do anything in between, can call this routine the old way. + */ + ChessMove moveType = UserMoveTest(fromX, fromY, toX, toY, promoChar); + + if(moveType != ImpossibleMove) + FinishMove(moveType, fromX, fromY, toX, toY, promoChar); +} + void SendProgramStatsToFrontend( ChessProgramState * cps, ChessProgramStats * cpstats ) { char * hint = lastHint; @@ -4370,15 +4623,17 @@ HandleMachineMove(message, cps) return; } - if (!ParseOneMove(machineMove, forwardMostMove, &moveType, - &fromX, &fromY, &toX, &toY, &promoChar)) { + if (!ParseOneMove(machineMove, forwardMostMove, &moveType, + &fromX, &fromY, &toX, &toY, &promoChar)) { /* Machine move could not be parsed; ignore it. */ sprintf(buf1, "Illegal move \"%s\" from %s machine", machineMove, cps->which); DisplayError(buf1, 0); + sprintf(buf1, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c) res=%d%c", + machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, 0); if (gameMode == TwoMachinesPlay) { GameEnds(machineWhite ? BlackWins : WhiteWins, - "Forfeit due to illegal move", GE_XBOARD); + buf1, GE_XBOARD); } return; } @@ -4389,19 +4644,21 @@ HandleMachineMove(message, cps) /* to cause a forfeit on a justified illegal-move complaint */ /* of the opponent. */ if(gameMode==TwoMachinesPlay && appData.testLegality && + fromY != DROP_RANK && /* [HGM] temporary; should still add legality test for drops */ LegalityTest(boards[forwardMostMove], PosFlags(forwardMostMove), epStatus[forwardMostMove], castlingRights[forwardMostMove], fromY, fromX, toY, toX, promoChar) == IllegalMove) - { static char buf[MSG_SIZ]; + { if (appData.debugMode) { int i; for(i=0; i< nrCastlingRights; i++) fprintf(debugFP, "(%d,%d) ", castlingRights[forwardMostMove][i], castlingRank[i]); fprintf(debugFP, "castling rights\n"); } - sprintf(buf, "Xboard: Forfeit due to illegal move %s (%c%c%c%c)%c", - machineMove, fromX+'a', fromY+ONE, toX+'a', toY+ONE, 0); - GameEnds(machineWhite ? BlackWins : WhiteWins, buf, GE_XBOARD); + sprintf(buf1, "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, + buf1, GE_XBOARD); } hintRequested = FALSE; lastHint[0] = NULLCHAR; @@ -4464,10 +4721,11 @@ HandleMachineMove(message, cps) #ifdef ADJUDICATE // [HGM] some adjudications useful with buggy engines - if( gameMode == TwoMachinesPlay ) { + if( gameMode == TwoMachinesPlay && gameInfo.holdingsSize == 0) { int count = 0, epFile = epStatus[forwardMostMove]; - if(appData.testLegality) // don't wait for engine to announce game end if we can judge ourselves + if(appData.testLegality && appData.checkMates) + // don't wait for engine to announce game end if we can judge ourselves switch (MateTest(boards[forwardMostMove], PosFlags(forwardMostMove), epFile, castlingRights[forwardMostMove]) ) { @@ -4496,7 +4754,7 @@ HandleMachineMove(message, cps) static int moveCount; /* First absolutely insufficient mating material. Count what is on board. */ - for(i=0; i appData.drawRepeats-2 - && adjudicateLossThreshold != 0) { + && appData.drawRepeats > 1) { /* adjudicate after user-specified nr of repeats */ ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/ GameEnds( GameIsDrawn, "Xboard adjudication: repetition draw", GE_XBOARD ); @@ -4628,7 +4886,7 @@ HandleMachineMove(message, cps) if( count >= 100) epStatus[forwardMostMove] = EP_RULE_DRAW; /* this is used to judge if draw claims are legal */ - if(adjudicateLossThreshold != 0 && count >= 2*appData.ruleMoves) { + if(appData.ruleMoves > 0 && count >= 2*appData.ruleMoves) { ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/ GameEnds( GameIsDrawn, "Xboard adjudication: 50-move rule", GE_XBOARD ); return; @@ -4868,11 +5126,8 @@ HandleMachineMove(message, cps) /* [HGM] illegal-move claim should forfeit game when Xboard */ /* only passes fully legal moves */ if( appData.testLegality && gameMode == TwoMachinesPlay ) { - static char buf[MSG_SIZ]; - sprintf(buf, "False illegal-move claim on %s (%c%c%c%c)%c", - machineMove, fromX+'a', fromY+ONE, toX+'a', toY+ONE, 0); GameEnds( cps->twoMachinesColor[0] == 'w' ? BlackWins : WhiteWins, - buf, GE_XBOARD ); + "False illegal-move claim", GE_XBOARD ); } return; } @@ -5420,9 +5675,9 @@ ParseGameHistory(game) case BlackASideCastleFR: /* POP Fabien */ case IllegalMove: /* maybe suicide chess, etc. */ - fromX = currentMoveString[0] - 'a'; + fromX = currentMoveString[0] - AAA; fromY = currentMoveString[1] - ONE; - toX = currentMoveString[2] - 'a'; + toX = currentMoveString[2] - AAA; toY = currentMoveString[3] - ONE; promoChar = currentMoveString[4]; break; @@ -5432,7 +5687,7 @@ ParseGameHistory(game) (int) CharToPiece(ToUpper(currentMoveString[0])) : (int) CharToPiece(ToLower(currentMoveString[0])); fromY = DROP_RANK; - toX = currentMoveString[2] - 'a'; + toX = currentMoveString[2] - AAA; toY = currentMoveString[3] - ONE; promoChar = NULLCHAR; break; @@ -5533,11 +5788,12 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) int promoChar; Board board; { + ChessSquare captured = board[toY][toX], piece; int p; + /* [HGM] In Shatranj and Courier all promotions are to Ferz */ if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier) - && promoChar != 0) promoChar = 'f'; + && promoChar != 0) promoChar = 'F'; - ChessSquare captured = board[toY][toX]; if (fromY == DROP_RANK) { /* must be first */ board[toY][toX] = (ChessSquare) fromX; @@ -5545,6 +5801,8 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) return; } + piece = board[fromY][fromX]; + /* Code added by Tord: */ /* FRC castling assumed when king captures friendly rook. */ else if (board[fromY][fromX] == WhiteKing && @@ -5552,18 +5810,18 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) board[fromY][fromX] = EmptySquare; board[toY][toX] = EmptySquare; if(toX > fromX) { - board[0][BOARD_WIDTH-2] = WhiteKing; board[0][BOARD_WIDTH-3] = WhiteRook; + board[0][BOARD_RGHT-2] = WhiteKing; board[0][BOARD_RGHT-3] = WhiteRook; } else { - board[0][2] = WhiteKing; board[0][3] = WhiteRook; + board[0][BOARD_LEFT+2] = WhiteKing; board[0][BOARD_LEFT+3] = WhiteRook; } } else if (board[fromY][fromX] == BlackKing && board[toY][toX] == BlackRook) { board[fromY][fromX] = EmptySquare; board[toY][toX] = EmptySquare; if(toX > fromX) { - board[BOARD_HEIGHT-1][BOARD_WIDTH-2] = BlackKing; board[BOARD_HEIGHT-1][BOARD_WIDTH-3] = BlackRook; + board[BOARD_HEIGHT-1][BOARD_RGHT-2] = BlackKing; board[BOARD_HEIGHT-1][BOARD_RGHT-3] = BlackRook; } else { - board[BOARD_HEIGHT-1][2] = BlackKing; board[BOARD_HEIGHT-1][3] = BlackRook; + board[BOARD_HEIGHT-1][BOARD_LEFT+2] = BlackKing; board[BOARD_HEIGHT-1][BOARD_LEFT+3] = BlackRook; } /* End of code added by Tord */ @@ -5572,14 +5830,14 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) && toY == fromY && toX > fromX+1) { board[fromY][fromX] = EmptySquare; board[toY][toX] = WhiteKing; - board[fromY][BOARD_WIDTH-1] = EmptySquare; + board[fromY][BOARD_RGHT-1] = EmptySquare; board[toY][toX-1] = WhiteRook; } else if (initialPosition[fromY][fromX] == WhiteKing && board[fromY][fromX] == WhiteKing && toY == fromY && toX < fromX-1) { board[fromY][fromX] = EmptySquare; board[toY][toX] = WhiteKing; - board[fromY][0] = EmptySquare; + board[fromY][BOARD_LEFT] = EmptySquare; board[toY][toX+1] = WhiteRook; } else if (fromY == 0 && fromX == 3 && board[fromY][fromX] == WhiteKing @@ -5606,6 +5864,8 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) if (board[toY][toX] == EmptySquare) { board[toY][toX] = WhiteQueen; } + if(gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */ + board[toY][toX] += (int) WhiteAlfil - (int) WhitePawn; board[fromY][fromX] = EmptySquare; } else if ((fromY == BOARD_HEIGHT-4) && (toX != fromX) @@ -5620,14 +5880,14 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) && toY == fromY && toX > fromX+1) { board[fromY][fromX] = EmptySquare; board[toY][toX] = BlackKing; - board[fromY][BOARD_WIDTH-1] = EmptySquare; + board[fromY][BOARD_RGHT-1] = EmptySquare; board[toY][toX-1] = BlackRook; } else if (initialPosition[fromY][fromX] == BlackKing && board[fromY][fromX] == BlackKing && toY == fromY && toX < fromX-1) { board[fromY][fromX] = EmptySquare; board[toY][toX] = BlackKing; - board[fromY][0] = EmptySquare; + board[fromY][BOARD_LEFT] = EmptySquare; board[toY][toX+1] = BlackRook; } else if (fromY == 7 && fromX == 3 && board[fromY][fromX] == BlackKing @@ -5654,6 +5914,8 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) if (board[0][toX] == EmptySquare) { board[0][toX] = BlackQueen; } + if(gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */ + board[toY][toX] += (int) WhiteAlfil - (int) WhitePawn; board[fromY][fromX] = EmptySquare; } else if ((fromY == 3) && (toX != fromX) @@ -5667,28 +5929,62 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) board[toY][toX] = board[fromY][fromX]; board[fromY][fromX] = EmptySquare; } - if (gameInfo.variant == VariantCrazyhouse) { -#if 0 - /* !!A lot more code needs to be written to support holdings */ + if (gameInfo.holdingsWidth != 0) { + + /* !!A lot more code needs to be written to support holdings */ + /* [HGM] OK, so I have written it. Holdings are stored in the */ + /* penultimate board files, so they are automaticlly stored */ + /* in the game history. */ if (fromY == DROP_RANK) { - /* Delete from holdings */ - if (holdings[(int) fromX] > 0) holdings[(int) fromX]--; + /* Delete from holdings, by decreasing count */ + /* and erasing image if necessary */ + p = (int) fromX; + if(p < (int) BlackPawn) { /* white drop */ + p -= (int)WhitePawn; + if(p >= gameInfo.holdingsSize) p = 0; + if(--board[p][BOARD_WIDTH-2] == 0) + board[p][BOARD_WIDTH-1] = EmptySquare; + } else { /* black drop */ + p -= (int)BlackPawn; + if(p >= gameInfo.holdingsSize) p = 0; + if(--board[BOARD_HEIGHT-1-p][1] == 0) + board[BOARD_HEIGHT-1-p][0] = EmptySquare; + } } - if (captured != EmptySquare) { - /* Add to holdings */ - if (captured < BlackPawn) { - holdings[(int)captured - (int)BlackPawn + (int)WhitePawn]++; + if (captured != EmptySquare && gameInfo.holdingsSize > 0 + && gameInfo.variant != VariantBughouse ) { + /* Add to holdings, if holdings exist */ + p = (int) captured; + if (p >= (int) BlackPawn) { + p -= (int)BlackPawn; + if(gameInfo.variant == VariantShogi && DEMOTED p >= 0) { + /* in Shogi restore piece to its original first */ + captured = (ChessSquare) (DEMOTED captured); + p = DEMOTED p; + } + if(p >= gameInfo.holdingsSize) { p = 0; captured = BlackPawn; } + board[p][BOARD_WIDTH-2]++; + board[p][BOARD_WIDTH-1] = + BLACK_TO_WHITE captured; } else { - holdings[(int)captured - (int)WhitePawn + (int)BlackPawn]++; + p -= (int)WhitePawn; + if(gameInfo.variant == VariantShogi && DEMOTED p >= 0) { + captured = (ChessSquare) (DEMOTED captured); + p = DEMOTED p; + } + if(p >= gameInfo.holdingsSize) { p = 0; captured = WhitePawn; } + board[BOARD_HEIGHT-1-p][1]++; + board[BOARD_HEIGHT-1-p][0] = + WHITE_TO_BLACK captured; } } -#endif + } else if (gameInfo.variant == VariantAtomic) { if (captured != EmptySquare) { int y, x; for (y = toY-1; y <= toY+1; y++) { for (x = toX-1; x <= toX+1; x++) { - if (y >= 0 && y < BOARD_WIDTH && x >= 0 && x < BOARD_WIDTH && + if (y >= 0 && y < BOARD_HEIGHT && x >= BOARD_LEFT && x < BOARD_RGHT && board[y][x] != WhitePawn && board[y][x] != BlackPawn) { board[y][x] = EmptySquare; } @@ -5697,6 +5993,11 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) board[toY][toX] = EmptySquare; } } + if(gameInfo.variant == VariantShogi && promoChar != NULLCHAR) { + /* [HGM] Shogi promotions */ + board[toY][toX] = (ChessSquare) (PROMOTED piece); + } + } /* Updates forwardMostMove */ @@ -5731,15 +6032,15 @@ MakeMove(fromX, fromY, toX, toY, promoChar) if( boards[forwardMostMove][fromY][fromX] == WhitePawn ) { epStatus[forwardMostMove] = EP_PAWN_MOVE; if( toY-fromY==2 && - (toX>1 && boards[forwardMostMove][toY][toX-1] == BlackPawn || - toXBOARD_LEFT+1 && boards[forwardMostMove][toY][toX-1] == BlackPawn || + toX1 && boards[forwardMostMove][toY][toX-1] == WhitePawn || - toXBOARD_LEFT+1 && boards[forwardMostMove][toY][toX-1] == WhitePawn || + toXinitString, cps); if (gameInfo.variant != VariantNormal && - gameInfo.variant != VariantLoadable) { + gameInfo.variant != VariantLoadable + /* [HGM] also send variant if board size non-standard */ + || gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 + ) { char *v = VariantName(gameInfo.variant); if (StrStr(cps->variants, v) == NULL) { sprintf(buf, "Variant %s not supported by %s", v, cps->tidy); DisplayFatalError(buf, 0, 1); return; } - sprintf(buf, "variant %s\n", VariantName(gameInfo.variant)); + b = buf; + /* [HGM] make prefix for non-standard board size. Awkward testing... */ + overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0; + if( gameInfo.variant == VariantXiangqi ) + overruled = gameInfo.boardWidth != 9 || gameInfo.boardHeight != 10 || gameInfo.holdingsSize != 0; + if( gameInfo.variant == VariantShogi ) + overruled = gameInfo.boardWidth != 9 || gameInfo.boardHeight != 9 || gameInfo.holdingsSize != 7; + if( gameInfo.variant == VariantBughouse || gameInfo.variant == VariantCrazyhouse ) + overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 5; + if( gameInfo.variant == VariantCapablanca || gameInfo.variant == VariantGothic ) + overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0; + if( gameInfo.variant == VariantCourier ) + overruled = gameInfo.boardWidth != 12 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0; + + if(overruled) { +#if 0 + // doesn't work in protocol 1 + if (StrStr(cps->variants, "boardsize") == NULL,) { + sprintf(buf, "Board size %dx%d+%d not supported by %s", + gameInfo.boardWidth, gameInfo.boardHeight, gameInfo.holdingsSize, cps->tidy); + DisplayFatalError(buf, 0, 1); + return; + } +#endif + sprintf(buf, "%dx%d+%d_", gameInfo.boardWidth, + gameInfo.boardHeight, gameInfo.holdingsSize ); + while(*b++ != '_'); + } + sprintf(b, "variant %s\n", VariantName(gameInfo.variant)); SendToProgram(buf, cps); } if (cps->sendICS) { @@ -6397,7 +6729,7 @@ AutoPlayOneMove() return FALSE; } - toX = moveList[currentMove][2] - 'a'; + toX = moveList[currentMove][2] - AAA; toY = moveList[currentMove][3] - ONE; if (moveList[currentMove][1] == '@') { @@ -6405,7 +6737,7 @@ AutoPlayOneMove() SetHighlights(-1, -1, toX, toY); } } else { - fromX = moveList[currentMove][0] - 'a'; + fromX = moveList[currentMove][0] - AAA; fromY = moveList[currentMove][1] - ONE; HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove); /* [AS] */ @@ -6503,9 +6835,9 @@ LoadGameOneMove(readAhead) /* POP Fabien */ if (appData.debugMode) fprintf(debugFP, "Parsed %s into %s\n", yy_text, currentMoveString); - fromX = currentMoveString[0] - 'a'; + fromX = currentMoveString[0] - AAA; fromY = currentMoveString[1] - ONE; - toX = currentMoveString[2] - 'a'; + toX = currentMoveString[2] - AAA; toY = currentMoveString[3] - ONE; promoChar = currentMoveString[4]; break; @@ -6518,7 +6850,7 @@ LoadGameOneMove(readAhead) (int) CharToPiece(ToUpper(currentMoveString[0])) : (int) CharToPiece(ToLower(currentMoveString[0])); fromY = DROP_RANK; - toX = currentMoveString[2] - 'a'; + toX = currentMoveString[2] - AAA; toY = currentMoveString[3] - ONE; break; @@ -6627,9 +6959,9 @@ LoadGameOneMove(readAhead) if (appData.debugMode) fprintf(debugFP, "Parsed %s into IllegalMove %s\n", yy_text, currentMoveString); - fromX = currentMoveString[0] - 'a'; + fromX = currentMoveString[0] - AAA; fromY = currentMoveString[1] - ONE; - toX = currentMoveString[2] - 'a'; + toX = currentMoveString[2] - AAA; toY = currentMoveString[3] - ONE; promoChar = currentMoveString[4]; } @@ -6738,9 +7070,9 @@ MakeRegisteredMove() thinkOutput[0] = NULLCHAR; strcpy(moveList[currentMove], cmailMove[lastLoadGameNumber - 1]); - fromX = cmailMove[lastLoadGameNumber - 1][0] - 'a'; + fromX = cmailMove[lastLoadGameNumber - 1][0] - AAA; fromY = cmailMove[lastLoadGameNumber - 1][1] - ONE; - toX = cmailMove[lastLoadGameNumber - 1][2] - 'a'; + toX = cmailMove[lastLoadGameNumber - 1][2] - AAA; toY = cmailMove[lastLoadGameNumber - 1][3] - ONE; promoChar = cmailMove[lastLoadGameNumber - 1][4]; MakeMove(fromX, fromY, toX, toY, promoChar); @@ -7167,7 +7499,7 @@ LoadGame(f, gameNumber, title, useList) if (!startedFromSetupPosition) { p = yy_text; for (i = BOARD_HEIGHT - 1; i >= 0; i--) - for (j = 0; j < BOARD_WIDTH; p++) + for (j = BOARD_LEFT; j < BOARD_RGHT; p++) switch (*p) { case '[': case '-': @@ -7437,7 +7769,7 @@ LoadPosition(f, positionNumber, title) for (i = BOARD_HEIGHT - 1; i >= 0; i--) { (void) fgets(line, MSG_SIZ, f); - for (p = line, j = 0; j < BOARD_WIDTH; p++) { + for (p = line, j = BOARD_LEFT; j < BOARD_RGHT; p++) { if (*p == ' ') continue; initial_position[i][j++] = CharToPiece(*p); @@ -9021,7 +9353,7 @@ EditPositionMenuEvent(selection, x, y) if (gameMode == IcsExamining) { if (boards[currentMove][y][x] != EmptySquare) { sprintf(buf, "%sx@%c%c\n", ics_prefix, - 'a' + x, ONE + y); + AAA + x, ONE + y); SendToICS(buf); } } else { @@ -9045,7 +9377,7 @@ EditPositionMenuEvent(selection, x, y) case EmptySquare: if (gameMode == IcsExamining) { - sprintf(buf, "%sx@%c%c\n", ics_prefix, 'a' + x, ONE + y); + sprintf(buf, "%sx@%c%c\n", ics_prefix, AAA + x, ONE + y); SendToICS(buf); } else { boards[0][y][x] = EmptySquare; @@ -9056,7 +9388,7 @@ EditPositionMenuEvent(selection, x, y) default: if (gameMode == IcsExamining) { sprintf(buf, "%s%c@%c%c\n", ics_prefix, - PieceToChar(selection), 'a' + x, ONE + y); + PieceToChar(selection), AAA + x, ONE + y); SendToICS(buf); } else { boards[0][y][x] = selection; @@ -9350,14 +9682,14 @@ ForwardInner(target) if (target > 0 && moveList[target - 1][0]) { int fromX, fromY, toX, toY; - toX = moveList[target - 1][2] - 'a'; + toX = moveList[target - 1][2] - AAA; toY = moveList[target - 1][3] - ONE; if (moveList[target - 1][1] == '@') { if (appData.highlightLastMove) { SetHighlights(-1, -1, toX, toY); } } else { - fromX = moveList[target - 1][0] - 'a'; + fromX = moveList[target - 1][0] - AAA; fromY = moveList[target - 1][1] - ONE; if (target == currentMove + 1) { AnimateMove(boards[currentMove], fromX, fromY, toX, toY); @@ -9453,14 +9785,14 @@ BackwardInner(target) if (moveList[target][0]) { int fromX, fromY, toX, toY; - toX = moveList[target][2] - 'a'; + toX = moveList[target][2] - AAA; toY = moveList[target][3] - ONE; if (moveList[target][1] == '@') { if (appData.highlightLastMove) { SetHighlights(-1, -1, toX, toY); } } else { - fromX = moveList[target][0] - 'a'; + fromX = moveList[target][0] - AAA; fromY = moveList[target][1] - ONE; if (target == currentMove - 1) { AnimateMove(boards[currentMove], toX, toY, fromX, fromY); @@ -9733,10 +10065,10 @@ PrintPosition(fp, move) int i, j; for (i = BOARD_HEIGHT - 1; i >= 0; i--) { - for (j = 0; j < BOARD_WIDTH; j++) { + for (j = BOARD_LEFT; j < BOARD_RGHT; j++) { char c = PieceToChar(boards[move][i][j]); fputc(c == 'x' ? '.' : c, fp); - fputc(j == BOARD_WIDTH - 1 ? '\n' : ' ', fp); + fputc(j == BOARD_RGHT - 1 ? '\n' : ' ', fp); } } if ((gameMode == EditPosition) ? !blackPlaysFirst : (move % 2 == 0)) @@ -11124,6 +11456,7 @@ PositionToFEN(move, useFEN960) char buf[128]; char *p, *q; int emptycount; + ChessSquare piece; whiteToPlay = (gameMode == EditPosition) ? !blackPlaysFirst : (move % 2 == 0); @@ -11132,7 +11465,7 @@ PositionToFEN(move, useFEN960) /* Piece placement data */ for (i = BOARD_HEIGHT - 1; i >= 0; i--) { emptycount = 0; - for (j = 0; j < BOARD_WIDTH; j++) { + for (j = BOARD_LEFT; j < BOARD_RGHT; j++) { if (boards[move][i][j] == EmptySquare) { emptycount++; } else { @@ -11142,7 +11475,15 @@ PositionToFEN(move, useFEN960) else { *p++ = '0' + emptycount/10; *p++ = '0' + emptycount%10; } emptycount = 0; } - *p++ = PieceToChar(boards[move][i][j]); + *p++ = PieceToChar(boards[move][i][j]); + if(gameInfo.variant == VariantCrazyhouse) { + /* [HGM] flag Crazyhouse promoted pieces */ + if( (int)boards[move][i][j] > (int) WhiteQueen && (int)boards[move][i][j] < (int) WhiteKing || + (int)boards[move][i][j] > (int) BlackQueen && (int)boards[move][i][j] < (int) BlackKing ) { + p[-1] = PieceToChar((ChessSquare)((int)boards[move][i][j]-(int)WhiteAlfil+(int)WhitePawn)); + *p++ = '~'; + } + } } } if (emptycount > 0) { @@ -11174,18 +11515,18 @@ PositionToFEN(move, useFEN960) /* White castling rights */ - for (fk = 1; fk < BOARD_WIDTH-1; fk++) { + for (fk = BOARD_LEFT+1; fk < BOARD_RGHT-1; fk++) { if (boards[move][0][fk] == WhiteKing) { - for (fr = BOARD_WIDTH-1; fr > fk; fr--) { /* H side */ + for (fr = BOARD_RGHT-1; fr > fk; fr--) { /* H side */ if (boards[move][0][fr] == WhiteRook) { *p++ = useFEN960 ? 'A' + fr : 'K'; break; } } - for (fr = 0; fr < fk; fr++) { /* A side */ + for (fr = BOARD_LEFT; fr < fk; fr++) { /* A side */ if (boards[move][0][fr] == WhiteRook) { *p++ = useFEN960 ? 'A' + fr : 'Q'; break; @@ -11196,18 +11537,18 @@ PositionToFEN(move, useFEN960) /* Black castling rights */ - for (fk = 1; fk < BOARD_WIDTH-1; fk++) { + for (fk = BOARD_LEFT+1; fk < BOARD_RGHT-1; fk++) { if (boards[move][BOARD_HEIGHT-1][fk] == BlackKing) { - for (fr = BOARD_WIDTH-1; fr > fk; fr--) { /* H side */ + for (fr = BOARD_RGHT-1; fr > fk; fr--) { /* H side */ if (boards[move][BOARD_HEIGHT-1][fr] == BlackRook) { *p++ = useFEN960 ? 'a' + fr : 'k'; break; } } - for (fr = 0; fr < fk; fr++) { /* A side */ + for (fr = BOARD_LEFT; fr < fk; fr++) { /* A side */ if (boards[move][BOARD_HEIGHT-1][fr] == BlackRook) { *p++ = useFEN960 ? 'a' + fr : 'q'; break; @@ -11224,23 +11565,23 @@ PositionToFEN(move, useFEN960) #ifdef OLDCASTLINGCODE if (boards[move][0][BOARD_WIDTH>>1] == WhiteKing) { - if (boards[move][0][BOARD_WIDTH-1] == WhiteRook) *p++ = 'K'; - if (boards[move][0][0] == WhiteRook) *p++ = 'Q'; + if (boards[move][0][BOARD_RGHT-1] == WhiteRook) *p++ = 'K'; + if (boards[move][0][BOARD_LEFT] == WhiteRook) *p++ = 'Q'; } if (boards[move][BOARD_HEIGHT-1][BOARD_WIDTH>>1] == BlackKing) { if (boards[move][BOARD_HEIGHT-1][BOARD_HEIGHT-1] == BlackRook) *p++ = 'k'; - if (boards[move][BOARD_HEIGHT-1][0] == BlackRook) *p++ = 'q'; + if (boards[move][BOARD_HEIGHT-1][BOARD_LEFT] == BlackRook) *p++ = 'q'; } #else /* [HGM] write true castling rights */ if( nrCastlingRights == 6 ) { - if(castlingRights[move][0] == BOARD_WIDTH-1 && + if(castlingRights[move][0] == BOARD_RGHT-1 && castlingRights[move][2] >= 0 ) *p++ = 'K'; - if(castlingRights[move][1] == 0 && + if(castlingRights[move][1] == BOARD_LEFT && castlingRights[move][2] >= 0 ) *p++ = 'Q'; - if(castlingRights[move][3] == BOARD_WIDTH-1 && + if(castlingRights[move][3] == BOARD_RGHT-1 && castlingRights[move][5] >= 0 ) *p++ = 'k'; - if(castlingRights[move][4] == 0 && + if(castlingRights[move][4] == BOARD_LEFT && castlingRights[move][5] >= 0 ) *p++ = 'q'; } #endif @@ -11252,16 +11593,16 @@ PositionToFEN(move, useFEN960) /* En passant target square */ if (move > backwardMostMove) { - fromX = moveList[move - 1][0] - 'a'; + fromX = moveList[move - 1][0] - AAA; fromY = moveList[move - 1][1] - ONE; - toX = moveList[move - 1][2] - 'a'; + toX = moveList[move - 1][2] - AAA; toY = moveList[move - 1][3] - ONE; if (fromY == (whiteToPlay ? BOARD_HEIGHT-2 : 1) && toY == (whiteToPlay ? BOARD_HEIGHT-4 : 3) && boards[move][toY][toX] == (whiteToPlay ? BlackPawn : WhitePawn) && fromX == toX) { /* 2-square pawn move just happened */ - *p++ = toX + 'a'; + *p++ = toX + AAA; *p++ = whiteToPlay ? '6'+BOARD_HEIGHT-8 : '3'; } else { *p++ = '-'; @@ -11270,6 +11611,26 @@ PositionToFEN(move, useFEN960) *p++ = '-'; } + /* [HGM] print Crazyhouse holdings */ + if( gameInfo.variant == VariantCrazyhouse ) { + *p++ = ' '; q = p; + for(i=0; i= 0; i--) { j = 0; for (;;) { if (*p == '/' || *p == ' ') { if (*p == '/') p++; - emptycount = BOARD_WIDTH - j; - while (emptycount--) board[i][j++] = EmptySquare; + emptycount = gameInfo.boardWidth - j; + while (emptycount--) + board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare; break; #if(BOARD_SIZE >= 10) } else if(*p=='x' || *p=='X') { /* [HGM] X means 10 */ p++; emptycount=10; - if (j + emptycount > BOARD_WIDTH) return FALSE; - while (emptycount--) board[i][j++] = EmptySquare; + if (j + emptycount > gameInfo.boardWidth) return FALSE; + while (emptycount--) + board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare; #endif } else if (isdigit(*p)) { emptycount = *p++ - '0'; while(isdigit(*p)) emptycount = 10*emptycount + *p++ - '0'; /* [HGM] allow > 9 */ - if (j + emptycount > BOARD_WIDTH) return FALSE; - while (emptycount--) board[i][j++] = EmptySquare; + if (j + emptycount > gameInfo.boardWidth) return FALSE; + while (emptycount--) + board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare; } else if (isalpha(*p)) { - if (j >= BOARD_WIDTH) return FALSE; - board[i][j++] = CharToPiece(*p++); + if (j >= gameInfo.boardWidth) return FALSE; + piece = CharToPiece(*p++); + if(*p == '~') { /* [HGM] make it a promoted piece for Crazyhouse */ + piece = (ChessSquare) ((int)piece + (int)WhiteAlfil - (int)WhitePawn); + p++; + } + board[i][(j++)+gameInfo.holdingsWidth] = piece; } else { return FALSE; } @@ -11353,18 +11733,18 @@ ParseFEN(board, blackPlaysFirst, fen) for(i=0; i=0 && board[castlingRank[0]][initialRights[0]] != WhiteRook) FENcastlingRights[0] = -1; + if(initialRights[1]>=0 && board[castlingRank[1]][initialRights[1]] != WhiteRook) FENcastlingRights[1] = -1; + if(initialRights[2]>=0 && board[castlingRank[2]][initialRights[2]] != WhiteKing) FENcastlingRights[2] = -1; + if(initialRights[3]>=0 && board[castlingRank[3]][initialRights[3]] != BlackRook) FENcastlingRights[3] = -1; + if(initialRights[4]>=0 && board[castlingRank[4]][initialRights[4]] != BlackRook) FENcastlingRights[4] = -1; + if(initialRights[5]>=0 && board[castlingRank[5]][initialRights[5]] != BlackKing) FENcastlingRights[5] = -1; FENrulePlies = 0; while(*p==' ') p++; if(*p=='K' || *p=='Q' || *p=='k' || *p=='q' || *p=='-') { - /* castling indicator present, so default is impossible */ + /* castling indicator present, so default is no castlings */ for(i=0; i>1; break; case'Q': - FENcastlingRights[1] = 0; + FENcastlingRights[1] = BOARD_LEFT; FENcastlingRights[2] = BOARD_WIDTH>>1; break; case'k': - FENcastlingRights[3] = BOARD_WIDTH-1; + FENcastlingRights[3] = BOARD_RGHT-1; FENcastlingRights[5] = BOARD_WIDTH>>1; break; case'q': - FENcastlingRights[4] = 0; + FENcastlingRights[4] = BOARD_LEFT; FENcastlingRights[5] = BOARD_WIDTH>>1; break; /* Tord! FRC! */ @@ -11397,13 +11777,39 @@ ParseFEN(board, blackPlaysFirst, fen) if(*p=='-') { p++; FENepStatus = EP_NONE; } else { - char c = *p++ - 'a'; + char c = *p++ - AAA; - if(c < 0 || c >= BOARD_WIDTH) return TRUE; + if(c < BOARD_LEFT || c >= BOARD_RGHT) return TRUE; if(*p >= '0' && *p <='9') *p++; FENepStatus = c; } + /* [HGM] look for Crazyhouse holdings here */ + while(*p==' ') p++; + if( !isdigit(*p) ) { + if(*p == '-' ) *p++; /* empty holdings */ else { + if( !gameInfo.holdingsWidth ) return FALSE; /* no room to put holdings! */ + /* if we would allow FEN reading to set board size, we would */ + /* have to add holdings and shift the board read so far here */ + while( (piece = CharToPiece(*p) ) != EmptySquare ) { + *p++; + if((int) piece >= (int) BlackPawn ) { + i = (int)piece - (int)BlackPawn; + if( i >= BOARD_HEIGHT ) return FALSE; + board[BOARD_HEIGHT-1-i][0] = piece; /* black holdings */ + board[BOARD_HEIGHT-1-i][1]++; /* black counts */ + } else { + i = (int)piece - (int)WhitePawn; + if( i >= BOARD_HEIGHT ) return FALSE; + board[i][BOARD_WIDTH-1] = piece; /* white holdings */ + board[i][BOARD_WIDTH-2]++; /* black holdings */ + } + } + } + } + + + if(sscanf(p, "%d", &i) == 1) { FENrulePlies = i; /* 50-move ply counter */ /* (The move number is still ignored) */ diff --git a/backend.h b/backend.h index 5058ac3..0057b9d 100644 --- a/backend.h +++ b/backend.h @@ -1,263 +1,266 @@ -/* - * backend.h -- Interface exported by XBoard back end - * $Id: backend.h,v 2.1 2003/10/27 19:21:00 mann Exp $ - * - * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. - * Enhancements Copyright 1992-95 Free Software Foundation, Inc. - * - * The following terms apply to Digital Equipment Corporation's copyright - * interest in XBoard: - * ------------------------------------------------------------------------ - * All Rights Reserved - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice appear in all copies and that - * both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of Digital not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * - * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING - * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL - * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR - * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * ------------------------------------------------------------------------ - * - * The following terms apply to the enhanced version of XBoard distributed - * by the Free Software Foundation: - * ------------------------------------------------------------------------ - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * ------------------------------------------------------------------------ - */ -#ifndef _BACKEND -#define _BACKEND - -#include "lists.h" -#include "frontend.h" - -extern int gotPremove; -extern GameMode gameMode; -extern int pausing, cmailMsgLoaded, flipView; -extern char white_holding[], black_holding[]; -extern int currentMove, backwardMostMove, forwardMostMove; -extern int blackPlaysFirst; -extern FILE *debugFP; -extern char* programVersion; -extern ProcRef firstProgramPR, secondProgramPR; -extern Board boards[]; - -char *CmailMsg P((void)); -/* Tord: Added the useFEN960 parameter in PositionToFEN() below */ -char *PositionToFEN P((int move, int useFEN960)); -void EditPositionPasteFEN P((char *fen)); -void TimeDelay P((long ms)); -void SendMultiLineToICS P(( char *text )); -void AnalysisPeriodicEvent P((int force)); -void SetWhiteToPlayEvent P((void)); -void SetBlackToPlayEvent P((void)); -void InitBackEnd1 P((void)); -void InitBackEnd2 P((void)); -int IsPromotion P((int fromX, int fromY, int toX, int toY)); -int PieceForSquare P((int x, int y)); -int OKToStartUserMove P((int x, int y)); -void Reset P((int redraw, int init)); -void ResetGameEvent P((void)); -int LoadGame P((FILE *f, int n, char *title, int useList)); -int LoadGameFromFile P((char *filename, int n, char *title, int useList)); -int CmailLoadGame P((FILE *f, int n, char *title, int useList)); -int ReloadGame P((int offset)); -int SaveGame P((FILE *f, int dummy, char *dummy2)); -int SaveGameToFile P((char *filename, int append)); -int LoadPosition P((FILE *f, int n, char *title)); -int ReloadPosition P((int offset)); -int SavePosition P((FILE *f, int dummy, char *dummy2)); -void EditPositionEvent P((void)); -void FlipViewEvent P((void)); -void MachineWhiteEvent P((void)); -void MachineBlackEvent P((void)); -void TwoMachinesEvent P((void)); -void EditGameEvent P((void)); -void TrainingEvent P((void)); -void IcsClientEvent P((void)); -void ForwardEvent P((void)); -void BackwardEvent P((void)); -void ToEndEvent P((void)); -void ToStartEvent P((void)); -void ToNrEvent P((int to)); -void RevertEvent P((void)); -void RetractMoveEvent P((void)); -void MoveNowEvent P((void)); -void TruncateGameEvent P((void)); -void PauseEvent P((void)); -void CallFlagEvent P((void)); -void AcceptEvent P((void)); -void DeclineEvent P((void)); -void RematchEvent P((void)); -void DrawEvent P((void)); -void AbortEvent P((void)); -void AdjournEvent P((void)); -void ResignEvent P((void)); -void UserAdjudicationEvent P((int result)); -void StopObservingEvent P((void)); -void StopExaminingEvent P((void)); -void PonderNextMoveEvent P((int newState)); -void ShowThinkingEvent P((int newState)); -void PeriodicUpdatesEvent P((int newState)); -void HintEvent P((void)); -void BookEvent P((void)); -void AboutGameEvent P((void)); -void ExitEvent P((int status)); -char *DefaultFileName P((char *)); -void UserMoveEvent P((int fromX, int fromY, int toX, int toY, int promoChar)); -void DecrementClocks P((void)); -char *TimeString P((long millisec)); -void AutoPlayGameLoop P((void)); -void DisplayBothClocks P((void)); -void EditPositionMenuEvent P((ChessSquare selection, int x, int y)); -void DropMenuEvent P((ChessSquare selection, int x, int y)); -int ParseTimeControl P((char *tc, int ti, int mps)); -void ProcessICSInitScript P((FILE * f)); -void EditCommentEvent P((void)); -void ReplaceComment P((int index, char *text)); -int ReplaceTags P((char *tags, GameInfo *gi));/* returns nonzero on error */ -void AppendComment P((int index, char *text)); -void ReloadCmailMsgEvent P((int unregister)); -void MailMoveEvent P((void)); -void EditTagsEvent P((void)); -void GetMoveListEvent P((void)); -void ExitAnalyzeMode P((void)); -void AnalyzeModeEvent P((void)); -void AnalyzeFileEvent P((void)); -void DoEcho P((void)); -void DontEcho P((void)); -void TidyProgramName P((char *prog, char *host, char *buf)); -void AskQuestionEvent P((char *title, char *question, - char *replyPrefix, char *which)); -Boolean ParseOneMove P((char *move, int moveNum, - ChessMove *moveType, int *fromX, int *fromY, - int *toX, int *toY, char *promoChar)); -char *VariantName P((VariantClass v)); -VariantClass StringToVariant P((char *e)); - -char *StrStr P((char *string, char *match)); -char *StrCaseStr P((char *string, char *match)); -char *StrSave P((char *s)); -char *StrSavePtr P((char *s, char **savePtr)); - -#ifndef _amigados -int StrCaseCmp P((char *s1, char *s2)); -int ToLower P((int c)); -int ToUpper P((int c)); -#else -#define StrCaseCmp Stricmp /* Use utility.library functions */ -#include -#endif - -extern GameInfo gameInfo; - - -/* pgntags.c prototypes - */ -char *PGNTags P((GameInfo *)); -void PrintPGNTags P((FILE *f, GameInfo *)); -int ParsePGNTag P((char *, GameInfo *)); -char *PGNResult P((ChessMove result)); - - -/* gamelist.c prototypes - */ -/* A game node in the double linked list of games. - */ -typedef struct _ListGame { - ListNode node; - int number; - unsigned long offset; /* Byte offset of game within file. */ - GameInfo gameInfo; /* Note that some entries may be NULL. */ -} ListGame; - -extern List gameList; -void ClearGameInfo P((GameInfo *)); -int GameListBuild P((FILE *)); -void GameListInitGameInfo P((GameInfo *)); -char *GameListLine P((int, GameInfo *)); -char * GameListLineFull P(( int, GameInfo *)); - -extern char* StripHighlight P((char *)); /* returns static data */ -extern char* StripHighlightAndTitle P((char *)); /* returns static data */ - -typedef struct _CPS { - char *which; - int maybeThinking; - ProcRef pr; - InputSourceRef isr; - char *twoMachinesColor; /* "white\n" or "black\n" */ - char *program; - char *host; - char *dir; - struct _CPS *other; - char *initString; - char *computerString; - int sendTime; /* 0=don't, 1=do, 2=test */ - int sendDrawOffers; - int useSigint; - int useSigterm; - int offeredDraw; /* countdown */ - int reuse; - int useSetboard; /* 0=use "edit"; 1=use "setboard" */ - int useSAN; /* 0=use coordinate notation; 1=use SAN */ - int usePing; /* 0=not OK to use ping; 1=OK */ - int lastPing; - int lastPong; - int usePlayother;/* 0=not OK to use playother; 1=OK */ - int useColors; /* 0=avoid obsolete white/black commands; 1=use them */ - int useUsermove; /* 0=just send move; 1=send "usermove move" */ - int sendICS; /* 0=don't use "ics" command; 1=do */ - int sendName; /* 0=don't use "name" command; 1=do */ - int sdKludge; /* 0=use "sd DEPTH" command; 1=use "depth\nDEPTH" */ - int stKludge; /* 0=use "st TIME" command; 1=use "level 1 TIME" */ - char tidy[MSG_SIZ]; - int matchWins; - char variants[MSG_SIZ]; - int analysisSupport; - int analyzing; - int protocolVersion; - int initDone; - - /* Added by Tord: */ - int useFEN960; /* 0=use "KQkq" style FENs, 1=use "HAha" style FENs */ - int useOOCastle; /* 0="O-O" notation for castling, 1="king capture rook" notation */ - /* End of additions by Tord */ - - int scoreIsAbsolute; /* [AS] 0=don't know (standard), 1=score is always from white side */ - int isUCI; /* [AS] 0=no (Winboard), 1=UCI (requires Polyglot) */ - int hasOwnBookUCI; /* [AS] 0=use GUI or Polyglot book, 1=has own book */ -} ChessProgramState; - -extern ChessProgramState first, second; - -/* [AS] Search stats from chessprogram, for the played move */ -typedef struct { - int score; /* Centipawns */ - int depth; /* Plies */ - int time; /* Milliseconds */ -} ChessProgramStats_Move; - -extern ChessProgramStats_Move pvInfoList[MAX_MOVES]; - -#endif /* _BACKEND */ +/* + * backend.h -- Interface exported by XBoard back end + * $Id: backend.h,v 2.1 2003/10/27 19:21:00 mann Exp $ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-95 Free Software Foundation, Inc. + * + * The following terms apply to Digital Equipment Corporation's copyright + * interest in XBoard: + * ------------------------------------------------------------------------ + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Digital not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * ------------------------------------------------------------------------ + * + * The following terms apply to the enhanced version of XBoard distributed + * by the Free Software Foundation: + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ +#ifndef _BACKEND +#define _BACKEND + +#include "lists.h" +#include "frontend.h" + +extern int gotPremove; +extern GameMode gameMode; +extern int pausing, cmailMsgLoaded, flipView; +extern char white_holding[], black_holding[]; +extern int currentMove, backwardMostMove, forwardMostMove; +extern int blackPlaysFirst; +extern FILE *debugFP; +extern char* programVersion; +extern ProcRef firstProgramPR, secondProgramPR; +extern Board boards[]; + +char *CmailMsg P((void)); +/* Tord: Added the useFEN960 parameter in PositionToFEN() below */ +char *PositionToFEN P((int move, int useFEN960)); +void AlphaRank P((char *s, int n)); /* [HGM] Shogi move preprocessor */ +void EditPositionPasteFEN P((char *fen)); +void TimeDelay P((long ms)); +void SendMultiLineToICS P(( char *text )); +void AnalysisPeriodicEvent P((int force)); +void SetWhiteToPlayEvent P((void)); +void SetBlackToPlayEvent P((void)); +void InitBackEnd1 P((void)); +void InitBackEnd2 P((void)); +int IsPromotion P((int fromX, int fromY, int toX, int toY)); +int InPalace P((int row, int column)); +int PieceForSquare P((int x, int y)); +int OKToStartUserMove P((int x, int y)); +void Reset P((int redraw, int init)); +void ResetGameEvent P((void)); +int LoadGame P((FILE *f, int n, char *title, int useList)); +int LoadGameFromFile P((char *filename, int n, char *title, int useList)); +int CmailLoadGame P((FILE *f, int n, char *title, int useList)); +int ReloadGame P((int offset)); +int SaveGame P((FILE *f, int dummy, char *dummy2)); +int SaveGameToFile P((char *filename, int append)); +int LoadPosition P((FILE *f, int n, char *title)); +int ReloadPosition P((int offset)); +int SavePosition P((FILE *f, int dummy, char *dummy2)); +void EditPositionEvent P((void)); +void FlipViewEvent P((void)); +void MachineWhiteEvent P((void)); +void MachineBlackEvent P((void)); +void TwoMachinesEvent P((void)); +void EditGameEvent P((void)); +void TrainingEvent P((void)); +void IcsClientEvent P((void)); +void ForwardEvent P((void)); +void BackwardEvent P((void)); +void ToEndEvent P((void)); +void ToStartEvent P((void)); +void ToNrEvent P((int to)); +void RevertEvent P((void)); +void RetractMoveEvent P((void)); +void MoveNowEvent P((void)); +void TruncateGameEvent P((void)); +void PauseEvent P((void)); +void CallFlagEvent P((void)); +void AcceptEvent P((void)); +void DeclineEvent P((void)); +void RematchEvent P((void)); +void DrawEvent P((void)); +void AbortEvent P((void)); +void AdjournEvent P((void)); +void ResignEvent P((void)); +void UserAdjudicationEvent P((int result)); +void StopObservingEvent P((void)); +void StopExaminingEvent P((void)); +void PonderNextMoveEvent P((int newState)); +void ShowThinkingEvent P((int newState)); +void PeriodicUpdatesEvent P((int newState)); +void HintEvent P((void)); +void BookEvent P((void)); +void AboutGameEvent P((void)); +void ExitEvent P((int status)); +char *DefaultFileName P((char *)); +ChessMove UserMoveTest P((int fromX, int fromY, int toX, int toY, int promoChar)); +void UserMoveEvent P((int fromX, int fromY, int toX, int toY, int promoChar)); +void DecrementClocks P((void)); +char *TimeString P((long millisec)); +void AutoPlayGameLoop P((void)); +void DisplayBothClocks P((void)); +void EditPositionMenuEvent P((ChessSquare selection, int x, int y)); +void DropMenuEvent P((ChessSquare selection, int x, int y)); +int ParseTimeControl P((char *tc, int ti, int mps)); +void ProcessICSInitScript P((FILE * f)); +void EditCommentEvent P((void)); +void ReplaceComment P((int index, char *text)); +int ReplaceTags P((char *tags, GameInfo *gi));/* returns nonzero on error */ +void AppendComment P((int index, char *text)); +void ReloadCmailMsgEvent P((int unregister)); +void MailMoveEvent P((void)); +void EditTagsEvent P((void)); +void GetMoveListEvent P((void)); +void ExitAnalyzeMode P((void)); +void AnalyzeModeEvent P((void)); +void AnalyzeFileEvent P((void)); +void DoEcho P((void)); +void DontEcho P((void)); +void TidyProgramName P((char *prog, char *host, char *buf)); +void AskQuestionEvent P((char *title, char *question, + char *replyPrefix, char *which)); +Boolean ParseOneMove P((char *move, int moveNum, + ChessMove *moveType, int *fromX, int *fromY, + int *toX, int *toY, char *promoChar)); +char *VariantName P((VariantClass v)); +VariantClass StringToVariant P((char *e)); + +char *StrStr P((char *string, char *match)); +char *StrCaseStr P((char *string, char *match)); +char *StrSave P((char *s)); +char *StrSavePtr P((char *s, char **savePtr)); + +#ifndef _amigados +int StrCaseCmp P((char *s1, char *s2)); +int ToLower P((int c)); +int ToUpper P((int c)); +#else +#define StrCaseCmp Stricmp /* Use utility.library functions */ +#include +#endif + +extern GameInfo gameInfo; + + +/* pgntags.c prototypes + */ +char *PGNTags P((GameInfo *)); +void PrintPGNTags P((FILE *f, GameInfo *)); +int ParsePGNTag P((char *, GameInfo *)); +char *PGNResult P((ChessMove result)); + + +/* gamelist.c prototypes + */ +/* A game node in the double linked list of games. + */ +typedef struct _ListGame { + ListNode node; + int number; + unsigned long offset; /* Byte offset of game within file. */ + GameInfo gameInfo; /* Note that some entries may be NULL. */ +} ListGame; + +extern List gameList; +void ClearGameInfo P((GameInfo *)); +int GameListBuild P((FILE *)); +void GameListInitGameInfo P((GameInfo *)); +char *GameListLine P((int, GameInfo *)); +char * GameListLineFull P(( int, GameInfo *)); + +extern char* StripHighlight P((char *)); /* returns static data */ +extern char* StripHighlightAndTitle P((char *)); /* returns static data */ + +typedef struct _CPS { + char *which; + int maybeThinking; + ProcRef pr; + InputSourceRef isr; + char *twoMachinesColor; /* "white\n" or "black\n" */ + char *program; + char *host; + char *dir; + struct _CPS *other; + char *initString; + char *computerString; + int sendTime; /* 0=don't, 1=do, 2=test */ + int sendDrawOffers; + int useSigint; + int useSigterm; + int offeredDraw; /* countdown */ + int reuse; + int useSetboard; /* 0=use "edit"; 1=use "setboard" */ + int useSAN; /* 0=use coordinate notation; 1=use SAN */ + int usePing; /* 0=not OK to use ping; 1=OK */ + int lastPing; + int lastPong; + int usePlayother;/* 0=not OK to use playother; 1=OK */ + int useColors; /* 0=avoid obsolete white/black commands; 1=use them */ + int useUsermove; /* 0=just send move; 1=send "usermove move" */ + int sendICS; /* 0=don't use "ics" command; 1=do */ + int sendName; /* 0=don't use "name" command; 1=do */ + int sdKludge; /* 0=use "sd DEPTH" command; 1=use "depth\nDEPTH" */ + int stKludge; /* 0=use "st TIME" command; 1=use "level 1 TIME" */ + char tidy[MSG_SIZ]; + int matchWins; + char variants[MSG_SIZ]; + int analysisSupport; + int analyzing; + int protocolVersion; + int initDone; + + /* Added by Tord: */ + int useFEN960; /* 0=use "KQkq" style FENs, 1=use "HAha" style FENs */ + int useOOCastle; /* 0="O-O" notation for castling, 1="king capture rook" notation */ + /* End of additions by Tord */ + + int scoreIsAbsolute; /* [AS] 0=don't know (standard), 1=score is always from white side */ + int isUCI; /* [AS] 0=no (Winboard), 1=UCI (requires Polyglot) */ + int hasOwnBookUCI; /* [AS] 0=use GUI or Polyglot book, 1=has own book */ +} ChessProgramState; + +extern ChessProgramState first, second; + +/* [AS] Search stats from chessprogram, for the played move */ +typedef struct { + int score; /* Centipawns */ + int depth; /* Plies */ + int time; /* Milliseconds */ +} ChessProgramStats_Move; + +extern ChessProgramStats_Move pvInfoList[MAX_MOVES]; + +#endif /* _BACKEND */ diff --git a/common.h b/common.h index fc2b999..be6d4e8 100644 --- a/common.h +++ b/common.h @@ -100,10 +100,27 @@ int pclose(FILE *); #define PROTOVER 2 /* engine protocol version */ -#define BOARD_SIZE 12 /* [HGM] for in declarations */ -#define BOARD_WIDTH (appData.NrFiles) /* [HGM] made user adjustable */ -#define BOARD_HEIGHT (appData.NrRanks) -#define ONE ('1'-(BOARD_HEIGHT>9)) /* [HGM] foremost board rank */ +/* [HGM] Some notes about board sizes: + In games that allow piece drops, the holdings are considered part of the + board, in the leftmost and rightmost two files. This way they are + automatically part of the game-history states, and enjoy all display + functions (including drag-drop and click-click moves to the regular part + of the board). The drawback of this is that the internal numbering of + files starts at 2 for the a-file if holdings are displayed. To ensure + consistency, this shifted numbering system is used _everywhere_ in the + code, and conversion to the 'normal' system only takes place when the + file number is converted to or from ASCII (by redefining the character + constant 'a'). This works because Winboard only communicates with the + outside world in ASCII. In a similar way, the different rank numbering + systems (starting at rank 0 or 1) are implemented by redefining '1'. +*/ +#define BOARD_SIZE 16 /* [HGM] for in declarations */ +#define BOARD_HEIGHT (gameInfo.boardHeight) // [HGM] made user adjustable +#define BOARD_WIDTH (gameInfo.boardWidth + 2*gameInfo.holdingsWidth) +#define BOARD_LEFT (gameInfo.holdingsWidth) // [HGM] play-board edges +#define BOARD_RGHT (gameInfo.boardWidth + gameInfo.holdingsWidth) +#define ONE ('1'-(BOARD_HEIGHT>9)) // [HGM] foremost board rank +#define AAA ('a'-BOARD_LEFT) // [HGM] leftmost board file #define DROP_RANK -3 #define MAX_MOVES 1000 #define MSG_SIZ 512 @@ -168,24 +185,32 @@ typedef enum { } GameMode; typedef enum { - WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, + WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, #ifdef FAIRY - WhiteCardinal, WhiteMarshall, WhiteFairyPawn, WhiteFairyKnight, - WhiteFairyBishop, WhiteFairyRook, WhiteFairyCardinal, WhiteFairyMarshall, - WhiteFairyQueen, WhiteFairyKing, + /* [HGM] the order here is crucial for Crazyhouse & Shogi: */ + /* only the first N pieces can go into the holdings, and */ + /* promotions in those variants shift P-W to E-M */ + WhiteFerz, WhiteWazir, WhiteAlfil, WhiteNightrider, WhiteCardinal, + WhiteMarshall, WhiteGrasshopper, WhiteCannon, WhiteMan, WhiteUnicorn, #endif - WhiteQueen, WhiteKing, - BlackPawn, BlackKnight, BlackBishop, BlackRook, + WhiteKing, BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, #ifdef FAIRY - BlackCardinal, BlackMarshall, BlackFairyPawn, BlackFairyKnight, - BlackFairyBishop, BlackFairyRook, BlackFairyCardinal, BlackFairyMarshall, - BlackFairyQueen, BlackFairyKing, + BlackFerz, BlackWazir, BlackAlfil, BlackNightrider, BlackCardinal, + BlackMarshall, BlackGrasshopper, BlackCannon, BlackMan, BlackUnicorn, #endif - BlackQueen, BlackKing, + BlackKing, EmptySquare, ClearBoard, WhitePlay, BlackPlay /*for use on EditPosition menus*/ } ChessSquare; +/* [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)WhiteAlfil - (int)WhitePawn + (int) +#define DEMOTED (int)WhitePawn - (int)WhiteAlfil + (int) +#define SHOGI (int)EmptySquare + (int) + + typedef ChessSquare Board[BOARD_SIZE][BOARD_SIZE]; typedef enum { @@ -243,52 +268,23 @@ typedef enum { VariantShatranj, /* Unsupported (ICC wild 28) */ Variant29, /* Temporary name for possible future ICC wild 29 */ Variant30, /* Temporary name for possible future ICC wild 30 */ -#ifdef FAIRY - VariantShogi, /* [HGM] To be supported in next version */ - VariantXiangqi, - VariantCourier, - VariantGothic, - VariantCapablanca, - VariantFairy, /* [HGM] allow more piece types */ -#else Variant31, /* Temporary name for possible future ICC wild 31 */ Variant32, /* Temporary name for possible future ICC wild 32 */ - Variant33, + Variant33, /* Temporary name for possible future ICC wild 33 */ Variant34, /* Temporary name for possible future ICC wild 34 */ Variant35, /* Temporary name for possible future ICC wild 35 */ Variant36, /* Temporary name for possible future ICC wild 36 */ -#endif + VariantShogi, /* [HGM] added variants */ + VariantXiangqi, + VariantCourier, + VariantGothic, + VariantCapablanca, + VariantKnightmate, + VariantFairy, + VariantShowgi, VariantUnknown /* Catchall for other unknown variants */ } VariantClass; -#ifdef FAIRY -#define VARIANT_NAMES { \ - "normal", \ - "normal", \ - "wildcastle", \ - "nocastle", \ - "fischerandom", \ - "bughouse", \ - "crazyhouse", \ - "losers", \ - "suicide", \ - "giveaway", \ - "twokings", \ - "kriegspiel", \ - "atomic", \ - "3check", \ - "shatranj", \ - "wild29", \ - "wild30", \ - "shogi", \ - "xiangqi", \ - "courier", \ - "gothic", \ - "capablanca", \ - "fairy", \ - "unknown" \ -} -#else #define VARIANT_NAMES { \ "normal", \ "normal", \ @@ -313,9 +309,16 @@ typedef enum { "wild34", \ "wild35", \ "wild36", \ + "shogi", \ + "xiangqi", \ + "courier", \ + "gothic", \ + "capablanca", \ + "knightmate", \ + "fairy", \ + "showgi", \ "unknown" \ } -#endif typedef struct { #if !defined(_amigados) @@ -516,10 +519,16 @@ typedef struct { /* [HGM] Board size */ int NrFiles; int NrRanks; + int holdingsSize; int matchPause; + Boolean alphaRank; Boolean testClaims; + Boolean checkMates; + Boolean materialDraws; + Boolean trivialDraws; int ruleMoves; int drawRepeats; + char * pieceToCharTable; #if ZIPPY char *zippyLines; @@ -580,7 +589,16 @@ typedef struct { int blackRating; /* -1 if unknown */ VariantClass variant; char *outOfBook; /* [AS] Move and score when engine went out of book */ + int boardWidth; /* [HGM] adjustable board size */ + int boardHeight; +/* [HGM] For Shogi and Crazyhouse: */ + int holdingsSize; /* number of different piece types in holdings */ + int holdingsWidth; /* number of files left and right of board, 0 or 2 */ } GameInfo; #endif + +/* extern int holdingsWidth; +extern int holdingsHeight; +/*extern int holdings[(int) EmptySquare];*/ diff --git a/config.h b/config.h index b29bde6..ec3ac90 100644 --- a/config.h +++ b/config.h @@ -47,7 +47,7 @@ #define LAST_PTY_LETTER 'q' -#define PATCHLEVEL "2" +#define PATCHLEVEL "4" #define PRODUCT "WinBoard" diff --git a/moves.c b/moves.c index 57e350e..2070ef3 100644 --- a/moves.c +++ b/moves.c @@ -119,13 +119,13 @@ ChessSquare PromoPiece(moveType) return BlackKing; #ifdef FAIRY case WhitePromotionChancellor: - return WhiteFairyRook; + return WhiteMarshall; case BlackPromotionChancellor: - return BlackFairyRook; + return BlackMarshall; case WhitePromotionArchbishop: - return WhiteFairyBishop; + return WhiteCardinal; case BlackPromotionArchbishop: - return BlackFairyBishop; + return BlackCardinal; #endif } } @@ -196,15 +196,15 @@ ChessMove PromoCharToMoveType(whiteOnMove, promoChar) } char pieceToChar[] = { - 'P', 'N', 'B', 'R', + 'P', 'N', 'B', 'R', 'Q', #ifdef FAIRY - 'A', 'C', 'F', 'H', 'E', 'W', 'D', 'O', 'G', 'M', + 'F', 'W', 'E', 'H', 'A', 'C', 'G', 'O', 'M', 'U', #endif - 'Q', 'K', 'p', 'n', 'b', 'r', + 'K', 'p', 'n', 'b', 'r', 'q', #ifdef FAIRY - 'a', 'c', 'f', 'h', 'e', 'w', 'd', 'o', 'g', 'm', + 'f', 'w', 'e', 'h', 'a', 'c', 'g', 'o', 'm', 'u', #endif - 'q', 'k', 'x' + 'k', 'x' }; char PieceToChar(p) @@ -215,7 +215,13 @@ char PieceToChar(p) ChessSquare CharToPiece(c) int c; -{ switch (c) { +{ + int i; + for(i=0; i< (int) EmptySquare; i++) + if(pieceToChar[i] == c) return (ChessSquare) i; + return EmptySquare; +/* [HGM] code marked for deletion + switch (c) { default: case 'x': return EmptySquare; case 'P': return WhitePawn; @@ -233,28 +239,29 @@ ChessSquare CharToPiece(c) #ifdef FAIRY case 'A': return WhiteCardinal; case 'C': return WhiteMarshall; - case 'F': return WhiteFairyPawn; - case 'H': return WhiteFairyKnight; - case 'E': return WhiteFairyBishop; - case 'W': return WhiteFairyRook; - case 'D': return WhiteFairyCardinal; - case 'O': return WhiteFairyMarshall; - case 'G': return WhiteFairyQueen; - case 'M': return WhiteFairyKing; + case 'F': return WhiteFerz; + case 'H': return WhiteNightrider; + case 'E': return WhiteAlfil; + case 'W': return WhiteWazir; + case 'U': return WhiteUnicorn; + case 'O': return WhiteCannon; + case 'G': return WhiteGrasshopper; + case 'M': return WhiteMan; case 'a': return BlackCardinal; case 'c': return BlackMarshall; - case 'f': return BlackFairyPawn; - case 'h': return BlackFairyKnight; - case 'e': return BlackFairyBishop; - case 'w': return BlackFairyRook; - case 'd': return BlackFairyCardinal; - case 'o': return BlackFairyMarshall; - case 'g': return BlackFairyQueen; - case 'm': return BlackFairyKing; + case 'f': return BlackFerz; + case 'h': return BlackNightrider; + case 'e': return BlackAlfil; + case 'w': return BlackWazir; + case 'u': return BlackUnicorn; + case 'o': return BlackCannon; + case 'g': return BlackGrasshopper; + case 'm': return BlackMan; #endif } +*/ } void CopyBoard(to, from) @@ -300,15 +307,24 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) int i, j, d, s, fs, rs, rt, ft, m; for (rf = 0; rf < BOARD_HEIGHT; rf++) - for (ff = 0; ff < BOARD_WIDTH; ff++) { + for (ff = BOARD_LEFT; ff < BOARD_RGHT; ff++) { + ChessSquare piece; + if (flags & F_WHITE_ON_MOVE) { if (!WhitePiece(board[rf][ff])) continue; } else { if (!BlackPiece(board[rf][ff])) continue; } - m = 0; - switch (board[rf][ff]) { - case EmptySquare: + m = 0; piece = board[rf][ff]; + if(gameInfo.variant == VariantCrazyhouse && + ( (int) piece > (int) WhiteQueen && (int) piece < (int) WhiteKing + || (int) piece > (int) BlackQueen && (int) piece < (int) BlackKing )) + piece = (ChessSquare) ( DEMOTED piece ); + if(gameInfo.variant == VariantShogi) + piece = (ChessSquare) ( SHOGI piece ); + + switch (piece) { + /* case EmptySquare: [HGM] this is nonsense, and conflicts with Shogi cases */ default: /* can't happen ([HGM] except for faries...) */ break; @@ -325,7 +341,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) /* and move sideways when across the river */ for (s = -1; s <= 1; s += 2) { if (rf >= BOARD_HEIGHT>>1 && - ff + s >= 0 && ff + s < BOARD_WIDTH && + ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && !WhitePiece(board[rf][ff+s]) ) { callback(board, flags, NormalMove, rf, ff, rf, ff+s, closure); @@ -341,12 +357,13 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) } if (rf == 1 && board[2][ff] == EmptySquare && gameInfo.variant != VariantShatranj && /* [HGM] */ + gameInfo.variant != VariantCourier && /* [HGM] */ board[3][ff] == EmptySquare ) { callback(board, flags, NormalMove, rf, ff, 3, ff, closure); } for (s = -1; s <= 1; s += 2) { - if (rf < BOARD_HEIGHT-1 && ff + s >= 0 && ff + s < BOARD_WIDTH && + if (rf < BOARD_HEIGHT-1 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && ((flags & F_KRIEGSPIEL_CAPTURE) || BlackPiece(board[rf + 1][ff + s]))) { callback(board, flags, @@ -354,7 +371,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) rf, ff, rf + 1, ff + s, closure); } if (rf == BOARD_HEIGHT-4) { - if (ff + s >= 0 && ff + s < BOARD_WIDTH && + if (ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && (epfile == ff + s || epfile == EP_UNKNOWN) && board[BOARD_HEIGHT-4][ff + s] == BlackPawn && board[BOARD_HEIGHT-3][ff + s] == EmptySquare) { @@ -376,7 +393,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) /* and move sideways when across the river */ for (s = -1; s <= 1; s += 2) { if (rf < BOARD_HEIGHT>>1 && - ff + s >= 0 && ff + s < BOARD_WIDTH && + ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && !BlackPiece(board[rf][ff+s]) ) { callback(board, flags, NormalMove, rf, ff, rf, ff+s, closure); @@ -392,12 +409,13 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) } if (rf == BOARD_HEIGHT-2 && board[BOARD_HEIGHT-3][ff] == EmptySquare && gameInfo.variant != VariantShatranj && /* [HGM] */ + gameInfo.variant != VariantCourier && /* [HGM] */ board[BOARD_HEIGHT-4][ff] == EmptySquare) { callback(board, flags, NormalMove, rf, ff, BOARD_HEIGHT-4, ff, closure); } for (s = -1; s <= 1; s += 2) { - if (rf > 0 && ff + s >= 0 && ff + s < BOARD_WIDTH && + if (rf > 0 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && ((flags & F_KRIEGSPIEL_CAPTURE) || WhitePiece(board[rf - 1][ff + s]))) { callback(board, flags, @@ -405,7 +423,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) rf, ff, rf - 1, ff + s, closure); } if (rf == 3) { - if (ff + s >= 0 && ff + s < BOARD_WIDTH && + if (ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && (epfile == ff + s || epfile == EP_UNKNOWN) && board[3][ff + s] == WhitePawn && board[2][ff + s] == EmptySquare) { @@ -416,6 +434,10 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) } break; +#ifdef FAIRY + case WhiteUnicorn: + case BlackUnicorn: +#endif case WhiteKnight: case BlackKnight: mounted: @@ -424,22 +446,46 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) for (s = 1; s <= 2; s++) { rt = rf + i*s; ft = ff + j*(3-s); - if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) continue; - if (SameColor(board[rf][ff], board[rt][ft])) continue; + if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) + && ( gameInfo.variant != VariantXiangqi || board[rf+i*(s-1)][ff+j*(2-s)] == EmptySquare) + && !SameColor(board[rf][ff], board[rt][ft])) callback(board, flags, NormalMove, rf, ff, rt, ft, closure); } break; + #ifdef FAIRY - case WhiteFairyMarshall: - case BlackFairyMarshall: + case SHOGI WhiteKnight: + for (s = -1; s <= 1; s += 2) { + if (rf < BOARD_HEIGHT-2 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && + !SameColor(board[rf][ff], board[rf + 2][ff + s])) { + callback(board, flags, + rf == BOARD_HEIGHT-2 ? WhitePromotionQueen : NormalMove, + rf, ff, rf + 2, ff + s, closure); + } + } + break; + + case SHOGI BlackKnight: + for (s = -1; s <= 1; s += 2) { + if (rf > 1 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && + !SameColor(board[rf][ff], board[rf - 2][ff + s])) { + callback(board, flags, + rf == 1 ? BlackPromotionQueen : NormalMove, + rf, ff, rf - 2, ff + s, closure); + } + } + break; + + case WhiteCannon: + case BlackCannon: for (d = 0; d <= 1; d++) for (s = -1; s <= 1; s += 2) { m = 0; for (i = 1;; i++) { rt = rf + (i * s) * d; ft = ff + (i * s) * (1 - d); - if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) break; + if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break; if (m == 0 && board[rt][ft] == EmptySquare) callback(board, flags, NormalMove, rf, ff, rt, ft, closure); @@ -452,35 +498,82 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) } break; - case WhiteFairyRook: - case BlackFairyRook: + /* Gold General (and all its promoted versions) . First do the */ + /* diagonal forward steps, then proceed as normal Wazir */ + case SHOGI WhiteWazir: + case SHOGI (PROMOTED WhitePawn): + case SHOGI (PROMOTED WhiteKnight): + case SHOGI (PROMOTED WhiteQueen): + case SHOGI (PROMOTED WhiteFerz): + for (s = -1; s <= 1; s += 2) { + if (rf < BOARD_HEIGHT-1 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && + !SameColor(board[rf][ff], board[rf + 1][ff + s])) { + callback(board, flags, + rf == BOARD_HEIGHT-2 ? WhitePromotionQueen : NormalMove, + rf, ff, rf + 1, ff + s, closure); + } + } + goto finishGold; + + case SHOGI BlackWazir: + case SHOGI (PROMOTED BlackPawn): + case SHOGI (PROMOTED BlackKnight): + case SHOGI (PROMOTED BlackQueen): + case SHOGI (PROMOTED BlackFerz): + for (s = -1; s <= 1; s += 2) { + if (rf > 0 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && + !SameColor(board[rf][ff], board[rf - 1][ff + s])) { + callback(board, flags, + rf == 1 ? BlackPromotionQueen : NormalMove, + rf, ff, rf - 1, ff + s, closure); + } + } + + case WhiteWazir: + case BlackWazir: + finishGold: for (d = 0; d <= 1; d++) - for (s = -1; s <= 1; s += 2) + for (s = -1; s <= 1; s += 2) { rt = rf + s * d; ft = ff + s * (1 - d); - if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) - && !SameColor(board[rf][ff], board[rt][ft])) + if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) + && !SameColor(board[rf][ff], board[rt][ft]) && + (gameInfo.variant != VariantXiangqi || InPalace(rt, ft) ) ) callback(board, flags, NormalMove, rf, ff, rt, ft, closure); + } break; - case WhiteFairyBishop: - case BlackFairyBishop: + case WhiteAlfil: + case BlackAlfil: /* [HGM] support Shatranj pieces */ for (rs = -1; rs <= 1; rs += 2) for (fs = -1; fs <= 1; fs += 2) { rt = rf + 2 * rs; ft = ff + 2 * fs; - if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) + if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) + && ( gameInfo.variant != VariantXiangqi || + board[rf+rs][ff+fs] == EmptySquare && (2*rf < BOARD_HEIGHT) == (2*rt < BOARD_HEIGHT) ) + && !SameColor(board[rf][ff], board[rt][ft])) callback(board, flags, NormalMove, rf, ff, rt, ft, closure); } break; + /* Shogi Dragon Horse has to continue with Wazir after Bishop */ + case SHOGI WhiteCardinal: + case SHOGI BlackCardinal: + m++; + + /* Capablanca Archbishop continues as Knight */ case WhiteCardinal: case BlackCardinal: m++; + + /* Shogi Bishops are ordinary Bishops */ + case SHOGI WhiteBishop: + case SHOGI BlackBishop: #endif case WhiteBishop: case BlackBishop: @@ -489,19 +582,56 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) for (i = 1;; i++) { rt = rf + (i * rs); ft = ff + (i * fs); - if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) break; + if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break; if (SameColor(board[rf][ff], board[rt][ft])) break; callback(board, flags, NormalMove, rf, ff, rt, ft, closure); if (board[rt][ft] != EmptySquare) break; } - if(m) goto mounted; + if(m==1) goto mounted; + if(m==2) goto finishGold; + /* Bishop falls through */ break; #ifdef FAIRY + /* Shogi Lance is unlike anything, and asymmetric at that */ + case SHOGI WhiteQueen: + for(i = 1;; i++) { + rt = rf + i; + ft = ff; + if (rt >= BOARD_HEIGHT) break; + if (SameColor(board[rf][ff], board[rt][ft])) break; + callback(board, flags, NormalMove, + rf, ff, rt, ft, closure); + if (board[rt][ft] != EmptySquare) break; + } + break; + + case SHOGI BlackQueen: + for(i = 1;; i++) { + rt = rf - i; + ft = ff; + if (rt < 0) break; + if (SameColor(board[rf][ff], board[rt][ft])) break; + callback(board, flags, NormalMove, + rf, ff, rt, ft, closure); + if (board[rt][ft] != EmptySquare) break; + } + break; + + /* Shogi Dragon King has to continue as Ferz after Rook moves */ + case SHOGI WhiteMarshall: + case SHOGI BlackMarshall: + m++; + + /* Capablanca Chancellor sets flag to continue as Knight */ case WhiteMarshall: case BlackMarshall: m++; + + /* Shogi Rooks are ordinary Rooks */ + case SHOGI WhiteRook: + case SHOGI BlackRook: #endif case WhiteRook: case BlackRook: @@ -510,13 +640,14 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) for (i = 1;; i++) { rt = rf + (i * s) * d; ft = ff + (i * s) * (1 - d); - if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) break; + if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break; if (SameColor(board[rf][ff], board[rt][ft])) break; callback(board, flags, NormalMove, rf, ff, rt, ft, closure); if (board[rt][ft] != EmptySquare) break; } - if(m) goto mounted; + if(m==1) goto mounted; + if(m==2) goto walking; break; case WhiteQueen: @@ -527,7 +658,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) for (i = 1;; i++) { rt = rf + (i * rs); ft = ff + (i * fs); - if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) break; + if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break; if (SameColor(board[rf][ff], board[rt][ft])) break; callback(board, flags, NormalMove, rf, ff, rt, ft, closure); @@ -537,31 +668,55 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) break; #ifdef FAIRY - case WhiteFairyPawn: - case BlackFairyPawn: + /* Shogi Pawn and Silver General: first the Pawn move, */ + /* then the General continues like a Ferz */ + case SHOGI WhitePawn: + case SHOGI WhiteFerz: + if (rf < BOARD_HEIGHT-1 && + !SameColor(board[rf][ff], board[rf + 1][ff]) ) + callback(board, flags, NormalMove, + rf, ff, rf + 1, ff, closure); + if(piece != SHOGI WhitePawn) goto finishSilver; + break; + + case SHOGI BlackPawn: + case SHOGI BlackFerz: + if (rf > 0 && + !SameColor(board[rf][ff], board[rf - 1][ff]) ) + callback(board, flags, NormalMove, + rf, ff, rf - 1, ff, closure); + if(piece == SHOGI BlackPawn) break; + + case WhiteFerz: + case BlackFerz: + finishSilver: /* [HGM] support Shatranj pieces */ for (rs = -1; rs <= 1; rs += 2) for (fs = -1; fs <= 1; fs += 2) { rt = rf + rs; ft = ff + fs; - if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) break; - if (!SameColor(board[rf][ff], board[rt][ft])) + if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break; + if (!SameColor(board[rf][ff], board[rt][ft]) && + (gameInfo.variant != VariantXiangqi || InPalace(rt, ft) ) ) callback(board, flags, NormalMove, rf, ff, rt, ft, closure); } break; - case WhiteFairyKing: - case BlackFairyKing: + case WhiteMan: + case BlackMan: + case SHOGI WhiteKing: + case SHOGI BlackKing: #endif case WhiteKing: case BlackKing: + walking: for (i = -1; i <= 1; i++) for (j = -1; j <= 1; j++) { if (i == 0 && j == 0) continue; rt = rf + i; ft = ff + j; - if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) continue; + if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) continue; if (SameColor(board[rf][ff], board[rt][ft])) continue; callback(board, flags, NormalMove, rf, ff, rt, ft, closure); @@ -602,7 +757,7 @@ void GenLegalCallback(board, flags, kind, rf, ff, rt, ft, closure) if (board[rf][ff] == king) return; for (r = rt-1; r <= rt+1; r++) { for (f = ft-1; f <= ft+1; f++) { - if (r >= 0 && r < BOARD_HEIGHT && f >= 0 && f < BOARD_WIDTH && + if (r >= 0 && r < BOARD_HEIGHT && f >= BOARD_LEFT && f < BOARD_RGHT && board[r][f] == king) return; } } @@ -648,79 +803,79 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure) for (ff = BOARD_WIDTH>>1; ff >= (BOARD_WIDTH-1)>>1; ff-- /*ics wild 1*/) { if ((flags & F_WHITE_ON_MOVE) && (flags & F_WHITE_KCASTLE_OK) && - board[0][ff] == WhiteKing && - board[0][ff + 1] == EmptySquare && - board[0][ff + 2] == EmptySquare && - board[0][BOARD_WIDTH-3] == EmptySquare && - board[0][BOARD_WIDTH-2] == EmptySquare && - board[0][BOARD_WIDTH-1] == WhiteRook && + board[0][ff] == WhiteKing && + board[0][ff + 1] == EmptySquare && + board[0][ff + 2] == EmptySquare && + board[0][BOARD_RGHT-3] == EmptySquare && + board[0][BOARD_RGHT-2] == EmptySquare && + board[0][BOARD_RGHT-1] == WhiteRook && castlingRights[0] >= 0 && /* [HGM] check rights */ ( castlingRights[2] == ff || castlingRights[6] == ff ) && (ignoreCheck || (!CheckTest(board, flags, 0, ff, 0, ff + 1, FALSE) && - !CheckTest(board, flags, 0, ff, 0, BOARD_WIDTH-3, FALSE) && + !CheckTest(board, flags, 0, ff, 0, BOARD_RGHT-3, FALSE) && !CheckTest(board, flags, 0, ff, 0, ff + 2, FALSE)))) { callback(board, flags, ff==4 ? WhiteKingSideCastle : WhiteKingSideCastleWild, - 0, ff, 0, ff + ((BOARD_WIDTH+2)>>2), closure); + 0, ff, 0, ff + ((gameInfo.boardWidth+2)>>2), closure); } if ((flags & F_WHITE_ON_MOVE) && (flags & F_WHITE_QCASTLE_OK) && board[0][ff] == WhiteKing && board[0][ff - 1] == EmptySquare && board[0][ff - 2] == EmptySquare && - board[0][2] == EmptySquare && - board[0][1] == EmptySquare && - board[0][0] == WhiteRook && + board[0][BOARD_LEFT+2] == EmptySquare && + board[0][BOARD_LEFT+1] == EmptySquare && + board[0][BOARD_LEFT+0] == WhiteRook && castlingRights[1] >= 0 && /* [HGM] check rights */ ( castlingRights[2] == ff || castlingRights[6] == ff ) && (ignoreCheck || (!CheckTest(board, flags, 0, ff, 0, ff - 1, FALSE) && - !CheckTest(board, flags, 0, ff, 0, 3, FALSE) && + !CheckTest(board, flags, 0, ff, 0, BOARD_LEFT+3, FALSE) && !CheckTest(board, flags, 0, ff, 0, ff - 2, FALSE)))) { callback(board, flags, ff==BOARD_WIDTH>>1 ? WhiteQueenSideCastle : WhiteQueenSideCastleWild, - 0, ff, 0, ff - ((BOARD_WIDTH+2)>>2), closure); + 0, ff, 0, ff - ((gameInfo.boardWidth+2)>>2), closure); } if (!(flags & F_WHITE_ON_MOVE) && (flags & F_BLACK_KCASTLE_OK) && board[BOARD_HEIGHT-1][ff] == BlackKing && board[BOARD_HEIGHT-1][ff + 1] == EmptySquare && board[BOARD_HEIGHT-1][ff + 2] == EmptySquare && - board[BOARD_HEIGHT-1][BOARD_WIDTH-3] == EmptySquare && - board[BOARD_HEIGHT-1][BOARD_WIDTH-2] == EmptySquare && - board[BOARD_HEIGHT-1][BOARD_WIDTH-1] == BlackRook && + board[BOARD_HEIGHT-1][BOARD_RGHT-3] == EmptySquare && + board[BOARD_HEIGHT-1][BOARD_RGHT-2] == EmptySquare && + board[BOARD_HEIGHT-1][BOARD_RGHT-1] == BlackRook && castlingRights[3] >= 0 && /* [HGM] check rights */ ( castlingRights[5] == ff || castlingRights[7] == ff ) && (ignoreCheck || (!CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff + 1, FALSE) && - !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, BOARD_WIDTH-3, FALSE) && + !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, BOARD_RGHT-3, FALSE) && !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff + 2, FALSE)))) { callback(board, flags, ff==BOARD_WIDTH>>1 ? BlackKingSideCastle : BlackKingSideCastleWild, - BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff + ((BOARD_WIDTH+2)>>2), closure); + BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff + ((gameInfo.boardWidth+2)>>2), closure); } if (!(flags & F_WHITE_ON_MOVE) && (flags & F_BLACK_QCASTLE_OK) && board[BOARD_HEIGHT-1][ff] == BlackKing && board[BOARD_HEIGHT-1][ff - 1] == EmptySquare && board[BOARD_HEIGHT-1][ff - 2] == EmptySquare && - board[BOARD_HEIGHT-1][2] == EmptySquare && - board[BOARD_HEIGHT-1][1] == EmptySquare && - board[BOARD_HEIGHT-1][0] == BlackRook && + board[BOARD_HEIGHT-1][BOARD_LEFT+2] == EmptySquare && + board[BOARD_HEIGHT-1][BOARD_LEFT+1] == EmptySquare && + board[BOARD_HEIGHT-1][BOARD_LEFT+0] == BlackRook && castlingRights[4] >= 0 && /* [HGM] check rights */ ( castlingRights[5] == ff || castlingRights[7] == ff ) && (ignoreCheck || (!CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - 1, FALSE) && - !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, 3, FALSE) && + !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, BOARD_LEFT+3, FALSE) && !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - 1, FALSE)))) { callback(board, flags, ff==BOARD_WIDTH>>1 ? BlackQueenSideCastle : BlackQueenSideCastleWild, - BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - ((BOARD_WIDTH+2)>>2), closure); + BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - ((gameInfo.boardWidth+2)>>2), closure); } } @@ -731,9 +886,9 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure) if ((flags & F_WHITE_ON_MOVE) != 0) { - for (ff = 1; ff < BOARD_WIDTH-1; ff++) { + for (ff = BOARD_LEFT+1; ff < BOARD_RGHT-1; ff++) { if (board[0][ff] == WhiteKing) { - for (ft = 0; ft < BOARD_WIDTH; ft++) { + for (ft = BOARD_LEFT+0; ft < BOARD_RGHT; ft++) { if (board[0][ft] == WhiteRook) { callback(board, flags, (ft > ff) ? WhiteHSideCastleFR : WhiteASideCastleFR, @@ -745,9 +900,9 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure) } else { - for (ff = 1; ff < BOARD_WIDTH-1; ff++) { + for (ff = BOARD_LEFT+1; ff < BOARD_RGHT-1; ff++) { if (board[BOARD_HEIGHT-1][ff] == BlackKing) { - for (ft = 0; ft < BOARD_WIDTH; ft++) { + for (ft = BOARD_LEFT+0; ft < BOARD_RGHT; ft++) { if (board[BOARD_HEIGHT-1][ft] == BlackRook) { callback(board, flags, (ft > ff) ? BlackHSideCastleFR : BlackASideCastleFR, @@ -805,6 +960,11 @@ int CheckTest(board, flags, rf, ff, rt, ft, enPassant) ChessSquare captured = EmptySquare; /* Suppress warnings on uninitialized variables */ + if(gameInfo.variant == VariantXiangqi) + king = flags & F_WHITE_ON_MOVE ? WhiteWazir : BlackWazir; + if(gameInfo.variant == VariantKnightmate) + king = flags & F_WHITE_ON_MOVE ? WhiteUnicorn : BlackUnicorn; + if (rf >= 0) { if (enPassant) { captured = board[rf][ft]; @@ -820,9 +980,9 @@ int CheckTest(board, flags, rf, ff, rt, ft, enPassant) order a1, a2, a3, ... b1, b2, ..., h8 to find the first king, and we test only whether that one is in check. */ cl.check = 0; - for (cl.fking = 0; cl.fking < BOARD_WIDTH; cl.fking++) + for (cl.fking = BOARD_LEFT+0; cl.fking < BOARD_RGHT; cl.fking++) for (cl.rking = 0; cl.rking < BOARD_HEIGHT; cl.rking++) { - if (board[cl.rking][cl.fking] == king) { + if (board[cl.rking][cl.fking] == king) { GenPseudoLegal(board, flags ^ F_WHITE_ON_MOVE, -1, CheckTestCallback, (VOIDSTAR) &cl); goto undo_move; /* 2-level break */ @@ -858,6 +1018,9 @@ void LegalityTestCallback(board, flags, kind, rf, ff, rt, ft, closure) { register LegalityTestClosure *cl = (LegalityTestClosure *) closure; + if (appData.debugMode) { + fprintf(debugFP, "Legality test: %c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE); + } if (rf == cl->rf && ff == cl->ff && rt == cl->rt && ft == cl->ft) cl->kind = kind; } @@ -921,7 +1084,8 @@ int MateTest(board, flags, epfile, castlingRights) if (cl.count > 0) { return inCheck ? MT_CHECK : MT_NONE; } else { - return inCheck ? MT_CHECKMATE : MT_STALEMATE; + return inCheck || gameInfo.variant == VariantXiangqi ? + MT_CHECKMATE : MT_STALEMATE; } } @@ -1063,11 +1227,12 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, /* Bughouse piece drop */ *outp++ = ToUpper(PieceToChar((ChessSquare) ff)); *outp++ = '@'; - *outp++ = ft + 'a'; + *outp++ = ft + AAA; if(rt+ONE <= '9') *outp++ = rt + ONE; else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; } *outp = NULLCHAR; + AlphaRank(out, 5); return (flags & F_WHITE_ON_MOVE) ? WhiteDrop : BlackDrop; } @@ -1086,7 +1251,7 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, kind = IllegalMove; } /* Pawn move */ - *outp++ = ff + 'a'; + *outp++ = ff + AAA; if (ff == ft && board[rt][ft] == EmptySquare) { /* [HGM] Xiangqi has straight noncapts! */ /* Non-capture; use style "e5" */ if(rt+ONE <= '9') @@ -1096,7 +1261,7 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, /* Capture; use style "exd5" */ if(gameInfo.variant != VariantXiangqi || board[rt][ft] != EmptySquare ) *outp++ = 'x'; /* [HGM] Xiangqi has sideway noncaptures across river! */ - *outp++ = ft + 'a'; + *outp++ = ft + AAA; if(rt+ONE <= '9') *outp++ = rt + ONE; else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; } @@ -1107,7 +1272,8 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, *outp++ = ToUpper(promoChar); } *outp = NULLCHAR; - return kind; + AlphaRank(out, 10); + return kind; case WhiteKing: @@ -1125,9 +1291,9 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, /* Use style "O-O" (oh-oh) for PGN compatibility */ else if (rf == rt && rf == ((piece == WhiteKing) ? 0 : BOARD_HEIGHT-1) && - ((ff == BOARD_WIDTH>>1 && (ft == 2 || ft == BOARD_WIDTH-2)) || - (ff == (BOARD_WIDTH-1)>>1 && (ft == 1 || ft == BOARD_WIDTH-3)))) { - if(ft==1 || ft==BOARD_WIDTH-2) + ((ff == BOARD_WIDTH>>1 && (ft == BOARD_LEFT+2 || ft == BOARD_RGHT-2)) || + (ff == (BOARD_WIDTH-1)>>1 && (ft == BOARD_LEFT+1 || ft == BOARD_RGHT-3)))) { + if(ft==BOARD_LEFT+1 || ft==BOARD_RGHT-2) strcpy(out, "O-O"); else strcpy(out, "O-O-O"); @@ -1175,7 +1341,7 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, *outp++ = ToUpper(PieceToChar(piece)); if (cl.file || (cl.either && !cl.rank)) { - *outp++ = ff + 'a'; + *outp++ = ff + AAA; } if (cl.rank) { if(rf+ONE <= '9') @@ -1186,21 +1352,20 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, if(board[rt][ft] != EmptySquare) *outp++ = 'x'; - *outp++ = ft + 'a'; + *outp++ = ft + AAA; if(rt+ONE <= '9') *outp++ = rt + ONE; else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; } *outp = NULLCHAR; - return cl.kind; + AlphaRank(out, 10); + return cl.kind; #ifdef FAIRY /* [HGM] Always long notation for fairies, don't know how they move */ - case WhiteFairyRook: - case BlackFairyRook: - case WhiteFairyKnight: - case BlackFairyKnight: - case WhiteFairyQueen: - case BlackFairyQueen: + case WhiteNightrider: + case BlackNightrider: + case WhiteGrasshopper: + case BlackGrasshopper: #endif case EmptySquare: /* Moving a nonexistent piece */ @@ -1219,12 +1384,12 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, if (piece != EmptySquare && piece != WhitePawn && piece != BlackPawn) { *outp++ = ToUpper(PieceToChar(piece)); } - *outp++ = ff + 'a'; + *outp++ = ff + AAA; if(rf+ONE <= '9') *outp++ = rf + ONE; else { *outp++ = (rf+ONE-'0')/10 + '0';*outp++ = (rf+ONE-'0')%10 + '0'; } if (board[rt][ft] != EmptySquare) *outp++ = 'x'; - *outp++ = ft + 'a'; + *outp++ = ft + AAA; if(rt+ONE <= '9') *outp++ = rt + ONE; else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; } @@ -1235,6 +1400,7 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, } *outp = NULLCHAR; + AlphaRank(out, 0); return IllegalMove; } diff --git a/moves.h b/moves.h index 764aef7..8324ef6 100644 --- a/moves.h +++ b/moves.h @@ -53,6 +53,7 @@ extern ChessSquare CharToPiece P((int c)); extern void CopyBoard P((Board to, Board from)); extern int CompareBoards P((Board board1, Board board2)); +extern char pieceToChar[(int)EmptySquare+1]; typedef void (*MoveCallback) P((Board board, int flags, ChessMove kind, int rf, int ff, int rt, int ft, diff --git a/parser.l b/parser.l index e35de38..03e0adc 100644 --- a/parser.l +++ b/parser.l @@ -1,997 +1,4091 @@ -%a 10000 -%o 10000 -%e 2000 -%k 2500 -%p 7000 -%n 1000 -%{ -/* - * parser.l -- lex parser of algebraic chess moves for XBoard - * $Id: parser.l,v 2.1 2003/10/27 19:21:00 mann Exp $ - * - * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. - * Enhancements Copyright 1992-95 Free Software Foundation, Inc. - * - * The following terms apply to Digital Equipment Corporation's copyright - * interest in XBoard: - * ------------------------------------------------------------------------ - * All Rights Reserved - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice appear in all copies and that - * both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of Digital not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * - * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING - * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL - * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR - * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * ------------------------------------------------------------------------ - * - * The following terms apply to the enhanced version of XBoard distributed - * by the Free Software Foundation: - * ------------------------------------------------------------------------ - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * ------------------------------------------------------------------------ - */ - -/* This parser handles all forms of promotion. - * The parser resolves ambiguous moves by searching and check-testing. - * It also parses comments of the form [anything] or (anything). - */ - -#include "config.h" - -#define NO_CONSTRAINT -1 -#undef YYLMAX -#define YYLMAX 4096 -#define UNPUT_BUF_SIZE YYLMAX - -#ifdef FLEX_SCANNER -/* yytext is probably a char*, but could be a char[]. yy_text is set - in YY_DECL below, because if yytext is a char*, its value is not - constant. */ -char *yy_text; -#else /*!FLEX_SCANNER*/ -/* yytext is definitely a char[], so yy_text can be set here, statically. */ -char *yy_text = (char *) yytext; -#endif - -#ifdef FLEX_SCANNER -/* This is flex */ -#undef YY_INPUT -#define YY_INPUT(buf, result, max_size) my_yy_input(buf, &result, max_size) -#undef YY_DECL -#define YY_DECL \ - int _yylex YY_PROTO((void)); \ - int yylex YY_PROTO((void)) \ - { \ - int result = _yylex(); \ - yy_text = (char *) yytext; \ - return(result); \ - } \ - int _yylex YY_PROTO((void)) -#else -/* This is lex */ -#undef input -#undef output -#undef unput -#endif - -/* The includes must be here, below the #undef input */ - -#include - -#if STDC_HEADERS -# include -# include -#else /* not STDC_HEADERS */ -# if HAVE_STRING_H -# include -# else /* not HAVE_STRING_H */ -# include -# endif /* not HAVE_STRING_H */ -#endif /* not STDC_HEADERS */ - -#if HAVE_UNISTD_H -# include -#endif - -#if defined(_amigados) -# include -# if HAVE_FCNTL_H -# include /* isatty() prototype */ -# endif /* HAVE_FCNTL_H */ -#endif /* defined(_amigados) */ - -#include "common.h" -#include "backend.h" -#include "frontend.h" -#include "parser.h" -#include "moves.h" - -extern int PosFlags P((int)); - -extern Board boards[MAX_MOVES]; -int yyboardindex; -int yyskipmoves = FALSE; -char currentMoveString[YYLMAX]; -#ifndef FLEX_SCANNER -char unputBuffer[UNPUT_BUF_SIZE]; -int unputCount = 0; -#endif - -#ifdef FLEX_SCANNER -void my_yy_input P((char *buf, int *result, int max_size)); -#else /*!FLEX_SCANNER*/ -static int input P((void)); -static void output P((int ch)); -static void unput P((int ch)); -int yylook P((void)); -int yyback P((int *, int)); -#endif -#undef yywrap -int yywrap P((void)); -extern void CopyBoard P((Board to, Board from)); - -%} -%% - -[RrBbNnQqKkPpACDEFGHMWO][/]?[a-l][0-9][xX:-]?[a-l][0-9](=?\(?[RrBbNnQqKkAaCc]\)?)? { - /* - * Fully-qualified algebraic move, possibly with promotion - * [HGM] Bigger-than-8x8 boards must rely on long algebraic formats - * where I allowed piece types A & C (also as promotions) - * files a-l and ranks 0-9 - */ - int skip1 = 0, skip2 = 0; - ChessSquare piece; - ChessMove result; - - if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ - - /* remove the / */ - if (yytext[1] == '/') skip1 = 1; - - /* remove the [xX:-] */ - if ((yytext[3+skip1] == 'x') || (yytext[3+skip1] == 'X') || - (yytext[3+skip1] == '-') || (yytext[3+skip1] == ':')) skip2 = 1; - - currentMoveString[0] = yytext[1+skip1]; - currentMoveString[1] = yytext[2+skip1]; - currentMoveString[2] = yytext[3+skip1+skip2]; - currentMoveString[3] = yytext[4+skip1+skip2]; - currentMoveString[4] = NULLCHAR; - - if (yyleng-skip1-skip2 > 5) { - if (yytext[yyleng-1] == ')') { - currentMoveString[4] = ToLower(yytext[yyleng-2]); - } else { - currentMoveString[4] = ToLower(yytext[yyleng-1]); - } - currentMoveString[5] = NULLCHAR; - } - - /* [HGM] do not allow values beyond board size */ - if(currentMoveString[1] - ONE >= BOARD_HEIGHT || - currentMoveString[0] - 'a' >= BOARD_WIDTH || - currentMoveString[3] - ONE >= BOARD_HEIGHT || - currentMoveString[2] - 'a' >= BOARD_WIDTH ) - return 0; - - piece = boards[yyboardindex] - [currentMoveString[1] - ONE][currentMoveString[0] - 'a']; - if (ToLower(yytext[0]) != ToLower(PieceToChar(piece))) - return (int) IllegalMove; - - result = LegalityTest(boards[yyboardindex], - PosFlags(yyboardindex), EP_UNKNOWN, - initialRights, /* [HGM] assume all castlings allowed */ - currentMoveString[1] - ONE, - currentMoveString[0] - 'a', - currentMoveString[3] - ONE, - currentMoveString[2] - 'a', - currentMoveString[4]); - - if (currentMoveString[4] == NULLCHAR && - (result == WhitePromotionQueen || result == BlackPromotionQueen)) { - currentMoveString[4] = 'q'; - currentMoveString[5] = NULLCHAR; - } - - return (int) result; -} - -[a-l][0-9][xX:-]?[a-l][0-9](=?\(?[RrBbNnQqKkAaCc]\)?)? { - /* - * Simple algebraic move, possibly with promotion - * [HGM] Bigger-than-8x8 boards must rely on this format - * where I allowed piece types A & C (also as promotions) - * files a-l and ranks 0-9 - */ - int skip = 0; - ChessMove result; - - if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ - - /* remove the [xX:-] */ - if ((yytext[2] == 'x') || (yytext[2] == 'X') || - (yytext[2] == '-') || (yytext[2] == ':')) skip = 1; - - currentMoveString[0] = yytext[0]; - currentMoveString[1] = yytext[1]; - currentMoveString[2] = yytext[2+skip]; - currentMoveString[3] = yytext[3+skip]; - currentMoveString[4] = NULLCHAR; - - if (yyleng-skip > 4) { - if (yytext[yyleng-1] == ')') { - currentMoveString[4] = ToLower(yytext[yyleng-2]); - } else { - currentMoveString[4] = ToLower(yytext[yyleng-1]); - } - currentMoveString[5] = NULLCHAR; - } - - /* [HGM] do not allow values beyond board size */ - if(currentMoveString[1] - ONE >= BOARD_HEIGHT || - currentMoveString[0] - 'a' >= BOARD_WIDTH || - currentMoveString[3] - ONE >= BOARD_HEIGHT || - currentMoveString[2] - 'a' >= BOARD_WIDTH ) - return 0; - - result = LegalityTest(boards[yyboardindex], - PosFlags(yyboardindex), EP_UNKNOWN, - initialRights, /* [HGM] assume all castlings allowed */ - currentMoveString[1] - ONE, - currentMoveString[0] - 'a', - currentMoveString[3] - ONE, - currentMoveString[2] - 'a', - currentMoveString[4]); - - if (currentMoveString[4] == NULLCHAR && - (result == WhitePromotionQueen || result == BlackPromotionQueen)) { - currentMoveString[4] = 'q'; - currentMoveString[5] = NULLCHAR; - } - - return (int) result; -} - -[a-l][0-9](=?\(?[RrBbNnQqKkAaCc]\)?)? { - /* - * Pawn move, possibly with promotion - */ - DisambiguateClosure cl; - int skip = 0; - - if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ - - /* remove the =() */ - if (yytext[2] == '=') skip++; - if (yytext[2+skip] == '(') skip++; - - cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn; - cl.rfIn = -1; - cl.ffIn = yytext[0] - 'a'; - cl.rtIn = yytext[1] - ONE; - cl.ftIn = yytext[0] - 'a'; - cl.promoCharIn = yytext[2+skip]; - - /* [HGM] do not allow values beyond board size */ - if(cl.rtIn >= BOARD_HEIGHT || - cl.ffIn >= BOARD_WIDTH || - cl.ftIn >= BOARD_WIDTH ) - return 0; - - - Disambiguate(boards[yyboardindex], - PosFlags(yyboardindex), EP_UNKNOWN, &cl); - - currentMoveString[0] = cl.ff + 'a'; - currentMoveString[1] = cl.rf + ONE; - currentMoveString[2] = cl.ft + 'a'; - currentMoveString[3] = cl.rt + ONE; - currentMoveString[4] = cl.promoChar; - currentMoveString[5] = NULLCHAR; - - return (int) cl.kind; -} - - -(ab|bc|cd|de|ef|fg|gh|hi|ij|jk|kl|lk|kj|ji|ih|hg|gf|fe|ed|dc|cb|ba|aa|bb|cc|dd|ee|ff|gg|hh|ii|jj|kk|ll|([a-l][xX:-][a-l]))(=?\(?[RrBbNnQqKkAaCc]\)?)?(ep|"e.p.")? { - /* - * Pawn capture, possibly with promotion, possibly ambiguous - */ - DisambiguateClosure cl; - int skip1 = 0, skip2 = 0; - - if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ - - /* remove trailing ep or e.p. (nonstandard PGN) */ - if (yytext[yyleng-1] == 'p') { - yyleng -= 2; - yytext[yyleng] = NULLCHAR; - } else if (yytext[yyleng-1] == '.') { - yyleng -= 4; - yytext[yyleng] = NULLCHAR; - } - - /* remove the [xX:-] and =() */ - if ((yytext[1] == 'x') || (yytext[1] == 'X') - || (yytext[1] == ':') || (yytext[1] == '-')) skip1 = 1; - if (yytext[2+skip1] == '=') skip2++; - if (yytext[2+skip1+skip2] == '(') skip2++; - - cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn; - cl.rfIn = -1; - cl.ffIn = yytext[0] - 'a'; - cl.rtIn = -1; - cl.ftIn = yytext[1+skip1] - 'a'; - cl.promoCharIn = yytext[2+skip1+skip2]; - - /* [HGM] do not allow values beyond board size */ - if(cl.ffIn >= BOARD_WIDTH || - cl.ftIn >= BOARD_WIDTH ) - return 0; - - Disambiguate(boards[yyboardindex], - PosFlags(yyboardindex), EP_UNKNOWN, &cl); - - currentMoveString[0] = cl.ff + 'a'; - currentMoveString[1] = cl.rf + ONE; - currentMoveString[2] = cl.ft + 'a'; - currentMoveString[3] = cl.rt + ONE; - currentMoveString[4] = cl.promoChar; - currentMoveString[5] = NULLCHAR; - - return (int) cl.kind; -} - -[a-l][xX:]?[a-l][0-9](=?\(?[RrBbNnQqKkAaCc]\)?)?(ep|"e.p.")? { - /* - * unambiguously abbreviated Pawn capture, possibly with promotion - */ - int skip = 0; - ChessMove result; - - if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ - - /* remove trailing ep or e.p. (nonstandard PGN) */ - if (yytext[yyleng-1] == 'p') { - yyleng -= 2; - yytext[yyleng] = NULLCHAR; - } else if (yytext[yyleng-1] == '.') { - yyleng -= 4; - yytext[yyleng] = NULLCHAR; - } - - /* remove the [xX:-] */ - if ((yytext[1] == 'x') || (yytext[1] == 'X') - || (yytext[1] == ':') || (yytext[1] == '-')) skip = 1; - - currentMoveString[0] = yytext[0]; - currentMoveString[2] = yytext[1+skip]; - currentMoveString[3] = yytext[2+skip]; - - /* [HGM] do not allow values beyond board size */ - if(currentMoveString[0] - 'a' >= BOARD_WIDTH || - currentMoveString[3] - ONE >= BOARD_HEIGHT || - currentMoveString[2] - 'a' >= BOARD_WIDTH ) - return 0; - - if (gameInfo.variant == VariantXiangqi && /* [HGM] In Xiangqi rank stays same */ - currentMoveString[0] != currentMoveString[2] ) { - if (yytext[2+skip] == ONE) return (int) ImpossibleMove; - currentMoveString[1] = yytext[2+skip]; - } else - if (WhiteOnMove(yyboardindex)) { - if (yytext[2+skip] == ONE) return (int) ImpossibleMove; - currentMoveString[1] = yytext[2+skip] - 1; - } else { - currentMoveString[1] = currentMoveString[3] + 1; - if (currentMoveString[3] == ONE+BOARD_HEIGHT-1) return (int) ImpossibleMove; - } - if (yyleng-skip > 3) { - if (yytext[yyleng-1] == ')') - currentMoveString[4] = ToLower(yytext[yyleng-2]); - else - currentMoveString[4] = ToLower(yytext[yyleng-1]); - currentMoveString[5] = NULLCHAR; - } else { - currentMoveString[4] = NULLCHAR; - } - - result = LegalityTest(boards[yyboardindex], - PosFlags(yyboardindex), EP_UNKNOWN, - initialRights, /* [HGM] assume all castlings allowed */ - currentMoveString[1] - ONE, - currentMoveString[0] - 'a', - currentMoveString[3] - ONE, - currentMoveString[2] - 'a', - currentMoveString[4]); - - if (currentMoveString[4] == NULLCHAR && - (result == WhitePromotionQueen || result == BlackPromotionQueen)) { - currentMoveString[4] = 'q'; - currentMoveString[5] = NULLCHAR; - } - - if (result != IllegalMove) return (int) result; - - /* Special case: improperly written en passant capture */ - if (WhiteOnMove(yyboardindex)) { - if (currentMoveString[3] == '5') { - currentMoveString[1] = '5'; - currentMoveString[3] = '6'; - } else { - return (int) IllegalMove; - } - } else { - if (currentMoveString[3] == '4') { - currentMoveString[1] = '4'; - currentMoveString[3] = '3'; - } else { - return (int) IllegalMove; - } - } - - result = LegalityTest(boards[yyboardindex], - PosFlags(yyboardindex), EP_UNKNOWN, - initialRights, /* [HGM] assume all castlings allowed */ - currentMoveString[1] - ONE, - currentMoveString[0] - 'a', - currentMoveString[3] - ONE, - currentMoveString[2] - 'a', - currentMoveString[4]); - - if (result == WhiteCapturesEnPassant || result == BlackCapturesEnPassant) - return (int) result; - else - return (int) IllegalMove; -} - -[RrBbNnQqKkACDEFGHMWO][xX:-]?[a-l][0-9] { - /* - * piece move, possibly ambiguous - */ - DisambiguateClosure cl; - int skip = 0; - - if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ - - /* remove the [xX:-] */ - if ((yytext[1] == 'x') || (yytext[1] == 'X') - || (yytext[1] == ':') || (yytext[1] == '-')) skip = 1; - - if (WhiteOnMove(yyboardindex)) { - cl.pieceIn = CharToPiece(ToUpper(yytext[0])); - } else { - cl.pieceIn = CharToPiece(ToLower(yytext[0])); - } - cl.rfIn = -1; - cl.ffIn = -1; - cl.rtIn = yytext[2+skip] - ONE; - cl.ftIn = yytext[1+skip] - 'a'; - cl.promoCharIn = NULLCHAR; - - /* [HGM] but do not allow values beyond board size */ - if(cl.rtIn >= BOARD_HEIGHT || - cl.ftIn >= BOARD_WIDTH ) - return 0; - - Disambiguate(boards[yyboardindex], - PosFlags(yyboardindex), EP_UNKNOWN, &cl); - - currentMoveString[0] = cl.ff + 'a'; - currentMoveString[1] = cl.rf + ONE; - currentMoveString[2] = cl.ft + 'a'; - currentMoveString[3] = cl.rt + ONE; - currentMoveString[4] = cl.promoChar; - currentMoveString[5] = NULLCHAR; - - return (int) cl.kind; -} - -[RrBbNnQqKkACDEFGHMWO][a-l0-9][xX:-]?[a-l][0-9] { - /* - * piece move with rank or file disambiguator - */ - DisambiguateClosure cl; - int skip = 0; - - if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ - - /* remove the [xX:-] */ - if ((yytext[2] == 'x') || (yytext[2] == 'X') - || (yytext[2] == ':') || (yytext[2] == '-')) skip = 1; - - if (WhiteOnMove(yyboardindex)) { - cl.pieceIn = CharToPiece(ToUpper(yytext[0])); - } else { - cl.pieceIn = CharToPiece(ToLower(yytext[0])); - } - if (isalpha(yytext[1])) { - cl.rfIn = -1; - cl.ffIn = yytext[1] - 'a'; - } else { - cl.rfIn = yytext[1] - ONE; - cl.ffIn = -1; - } - cl.rtIn = yytext[3+skip] - ONE; - cl.ftIn = yytext[2+skip] - 'a'; - cl.promoCharIn = NULLCHAR; - - /* [HGM] do not allow values beyond board size */ - if(cl.rtIn >= BOARD_HEIGHT || - cl.rfIn >= BOARD_HEIGHT || - cl.ffIn >= BOARD_WIDTH || - cl.ftIn >= BOARD_WIDTH ) - return 0; - - Disambiguate(boards[yyboardindex], - PosFlags(yyboardindex), EP_UNKNOWN, &cl); - - currentMoveString[0] = cl.ff + 'a'; - currentMoveString[1] = cl.rf + ONE; - currentMoveString[2] = cl.ft + 'a'; - currentMoveString[3] = cl.rt + ONE; - currentMoveString[4] = cl.promoChar; - currentMoveString[5] = NULLCHAR; - - return (int) cl.kind; -} - -000|0-0-0|ooo|OOO|o-o-o|O-O-O { - int rf, ff, rt, ft; - - if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ - - /* [HGM] all squares referenced to board edges in stead of absolute */ - if (WhiteOnMove(yyboardindex)) { - if (boards[yyboardindex][0][(BOARD_WIDTH-1)>>1] == WhiteKing) { - /* ICS wild castling */ - rf = 0; - ff = (BOARD_WIDTH-1)>>1; - rt = 0; - ft = BOARD_WIDTH-3; - sprintf(currentMoveString, "%c%c%c%c",ff+'a',rf+ONE,ft+'a',rt+ONE); - } else { - rf = 0; - ff = BOARD_WIDTH>>1; - rt = 0; - ft = 2; - sprintf(currentMoveString, "%c%c%c%c",ff+'a',rf+ONE,ft+'a',rt+ONE); - } - } else{ - if (boards[yyboardindex][BOARD_HEIGHT-1][3] == BlackKing) { - /* ICS wild castling */ - rf = BOARD_HEIGHT-1; - ff = (BOARD_WIDTH-1)>>1; - rt = BOARD_HEIGHT-1; - ft = BOARD_WIDTH-3; - sprintf(currentMoveString, "%c%c%c%c",ff+'a',rf+ONE,ft+'a',rt+ONE); - } else { - rf = BOARD_HEIGHT-1; - ff = BOARD_WIDTH>>1; - rt = BOARD_HEIGHT-1; - ft = 2; - sprintf(currentMoveString, "%c%c%c%c",ff+'a',rf+ONE,ft+'a',rt+ONE); - } - } - return (int) LegalityTest(boards[yyboardindex], - PosFlags(yyboardindex), EP_UNKNOWN, - initialRights, /* [HGM] assume all castlings allowed */ - rf, ff, rt, ft, NULLCHAR); -} - -00|0-0|oo|OO|o-o|O-O { - int rf, ff, rt, ft; - - if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ - - if (WhiteOnMove(yyboardindex)) { - if (boards[yyboardindex][0][(BOARD_WIDTH-1)>>1] == WhiteKing) { - /* ICS wild castling */ - rf = 0; - ff = (BOARD_WIDTH-1)>>1; - rt = 0; - ft = 1; - sprintf(currentMoveString, "%c%c%c%c",ff+'a',rf+ONE,ft+'a',rt+ONE); - } else { - rf = 0; - ff = BOARD_WIDTH>>1; - rt = 0; - ft = BOARD_WIDTH-2; - sprintf(currentMoveString, "%c%c%c%c",ff+'a',rf+ONE,ft+'a',rt+ONE); - } - } else { - if (boards[yyboardindex][BOARD_HEIGHT-1][(BOARD_WIDTH-1)>>1] == BlackKing) { - /* ICS wild castling */ - rf = BOARD_HEIGHT-1; - ff = (BOARD_WIDTH-1)>>1; - rt = BOARD_HEIGHT-1; - ft = 1; - sprintf(currentMoveString, "%c%c%c%c",ff+'a',rf+ONE,ft+'a',rt+ONE); - } else { - rf = BOARD_HEIGHT-1; - ff = BOARD_WIDTH>>1; - rt = BOARD_HEIGHT-1; - ft = BOARD_WIDTH-2; - sprintf(currentMoveString, "%c%c%c%c",ff+'a',rf+ONE,ft+'a',rt+ONE); - } - } - return (int) LegalityTest(boards[yyboardindex], - PosFlags(yyboardindex), EP_UNKNOWN, - initialRights, /* [HGM] assume all castlings allowed */ - rf, ff, rt, ft, NULLCHAR); -} - -[PpNnBbRrQqAaCc]@[a-l][0-9] { - /* Bughouse piece drop. No legality checking for now. */ - currentMoveString[1] = '@'; - currentMoveString[2] = yytext[2]; - currentMoveString[3] = yytext[3]; - currentMoveString[4] = NULLCHAR; - - /* [HGM] do not allow values beyond board size */ - if(currentMoveString[1] - ONE >= BOARD_HEIGHT || - currentMoveString[0] - 'a' >= BOARD_WIDTH || - currentMoveString[3] - ONE >= BOARD_HEIGHT || - currentMoveString[2] - 'a' >= BOARD_WIDTH ) - return 0; - - if (WhiteOnMove(yyboardindex)) { - currentMoveString[0] = ToUpper(yytext[0]); - return (int) WhiteDrop; - } else { - currentMoveString[0] = ToLower(yytext[0]); - return (int) BlackDrop; - } -} - -[Rr]esign(s|ed)? { - if (WhiteOnMove(yyboardindex)) - return (int) BlackWins; - else - return (int) WhiteWins; -} - -(([Ww](hite)?)|([Bb](lack)?))" "(([Rr]esign)|([Ff]orfeit))(s|ed)? { - return (int) (ToUpper(yytext[0]) == 'W' ? BlackWins : WhiteWins); -} - -(([Ww](hite)?)|([Bb](lack)?))" "[Dd]isconnect(s|ed) { - return (int) GameUnfinished; -} - -[Ss]talemate { - return (int) GameIsDrawn; -} - -"+-+" { - return (int) GameIsDrawn; -} - -([Cc]heck)?[Mm]ate { - if (WhiteOnMove(yyboardindex)) - return (int) BlackWins; - else - return (int) WhiteWins; -} - -"++" { - if (WhiteOnMove(yyboardindex)) - return (int) BlackWins; - else - return (int) WhiteWins; -} - -[Dd]raw(n)?(" "by)?(" "[Rr]epetition)|(" "[Aa]gree(d|ment)) { - return (int) GameIsDrawn; -} - -[Dd]raw(n)?(" (".*")")? { - return (int) GameIsDrawn; -} - -(([Ww](hite)?)|([Bb](lack)?))" "([Mm]ate(s|ed)?)|([Ww][io]n(s)?.*) { - return (int) (ToUpper(yytext[0]) == 'W' ? WhiteWins : BlackWins); -} - -(([Ww](hite)?)|([Bb](lack)?))" "([Mm]ate(s|ed)?)|([Ll]os[tes]+.*) { - return (int) (ToUpper(yytext[0]) == 'W' ? BlackWins : WhiteWins); -} - -("{"[^\}\n]*"} ")?(1-0|"1 - 0"|"1/0"|"1 / 0"|"1:0"|"1 : 0")(" (".*")"|" {".*"}")? { - return (int) WhiteWins; -} - -("{"[^\}\n]*"} ")?(0-1|"0 - 1"|"0/1"|"0 / 1"|"0:1"|"0 : 1")(" (".*")"|" {".*"}")? { - return (int) BlackWins; -} - -("{"[^\}\n]*"} ")?("1/2"|"1 / 2")(" "?[-:]" "?("1/2"|"1 / 2"))?(" (".*")"|" {".*"}")? { - return (int) GameIsDrawn; -} - -("{"[^\}\n]*"} ")?"*"(" (".*")"|" {".*"}")? { - return (int) GameUnfinished; -} - -[1-9][0-9]*/"."?[ \t\n]*[a-lNnPpRrBQqKACFEWDGHOo] { - /* move numbers */ - if ((yyleng == 1) && (yytext[0] == '1')) - return (int) MoveNumberOne; -} - -\([0-9]+:[0-9][0-9](\.[0-9]+)?\)|\{[0-9]+:[0-9][0-9](\.[0-9]+)?\} { - /* elapsed time indication, e.g. (0:12) or {10:21.071} */ - return (int) ElapsedTime; -} - -"[--"[^\]]*"--]" { - /* position diagram enclosed in [-- --] */ - return (int) PositionDiagram; -} - -^"{--------------"\n[^\}]*\n"--------------}"$ { - /* position diagram enclosed in {-- --} */ - return (int) PositionDiagram; -} - -\[[ \t\n]*[A-Za-z0-9][A-Za-z0-9_+#=-]*[ \t\n]*\"[^"]*\"[ \t\n]*\] { - return (int) PGNTag; -} - -[Gg](nu|NU)" "?[Cc](hess|HESS).*[Gg](ame|AME) { - return (int) GNUChessGame; -} - -^[#;%]" "[^ ]*(" game file"|" position file").*$ { - return (int) XBoardGame; -} - -\$[0-9]+ { /* numeric annotation glyph */ - return (int) NAG; -} - -\{[^\}]*\} { /* anything in {} */ - return (int) Comment; -} - -;.*$ { /* ; to end of line */ - return (int) Comment; -} - -\[[^\]]*\] { /* anything in [] */ - return (int) Comment; -} - -\([^()]*(\([^()]*\)[^()]*)+[^()]*\) { /* nested () */ - return (int) Comment; -} - -\([^)][^)]+\) { /* >=2 chars in () */ - return (int) Comment; -} - -^[-a-zA-Z0-9]+:" ".*(\n[ \t]+.*)* { - /* Skip mail headers */ -} - -[a-zA-Z0-9'-]+ { - /* Skip random words */ -} - -.|\n { - /* Skip everything else */ -} - -%% - - -static char *StringToLex; - -#ifndef FLEX_SCANNER -static FILE *lexFP; - -static int input() -{ - int ret; - - if (StringToLex != NULL) { - ret = *StringToLex; - if (ret == NULLCHAR) - ret = EOF; - else - StringToLex++; - } else if (unputCount > 0) { - ret = unputBuffer[--unputCount]; - } else { - ret = fgetc(lexFP); - } - - if (ret == EOF) - return 0; - else - return ret; -} - -/* - * Return offset of next pattern within current file - */ -int yyoffset() -{ - int offset = ftell(lexFP) - unputCount; - - if (offset < 0) { - offset = 0; - } - return(offset); -} - -static void output(ch) - int ch; -{ - fprintf(stderr, "PARSER BUG: unmatched character '%c' (0%o)\n", - ch, ch); -} - -static void unput(ch) - int ch; -{ - if (ch == 0) return; - if (StringToLex != NULL) { - StringToLex--; - } else { - if (unputCount >= UNPUT_BUF_SIZE) - fprintf(stderr, "PARSER BUG: unput buffer overflow '%c' (0%o)\n", - ch, ch); - unputBuffer[unputCount++] = ch; - } -} - -/* Get ready to lex from a new file. Kludge below sticks - an artificial newline at the front of the file, which the - above grammar ignores, but which makes ^ at start of pattern - match at the real start of the file. -*/ -void yynewfile(f) - FILE *f; -{ - lexFP = f; - StringToLex = NULL; - unputCount = 0; - unput('\n'); /* kludge */ -} - -/* Get ready to lex from a string. ^ at start of pattern WON'T - match at the start of the string! -*/ -void yynewstr(s) - char *s; -{ - lexFP = NULL; - StringToLex = s; - unputCount = 0; -} -#endif /*!FLEX_SCANNER*/ - -#ifdef FLEX_SCANNER -void my_yy_input(buf, result, max_size) - char *buf; - int *result; - int max_size; -{ - int count; - - if (StringToLex != NULL) { - count = 0; - while (*StringToLex != NULLCHAR) { - *buf++ = *StringToLex++; - count++; - } - *result = count; - return; - } else { - count = fread(buf, 1, max_size, yyin); - if (count == 0) { - *result = YY_NULL; - } else { - *result = count; - } - return; - } -} - -static YY_BUFFER_STATE my_file_buffer = NULL; - -/* - Return offset of next pattern in the current file. -*/ -int yyoffset() -{ - int pos = yy_c_buf_p - yy_current_buffer->yy_ch_buf; - - return(ftell(yy_current_buffer->yy_input_file) - - yy_n_chars + pos); -} - - -void yynewstr(s) - char *s; -{ - if (my_file_buffer != NULL) - yy_delete_buffer(my_file_buffer); - StringToLex = s; - my_file_buffer = yy_create_buffer(stdin, YY_BUF_SIZE); - yy_switch_to_buffer(my_file_buffer); -} - -void yynewfile(f) - FILE *f; -{ - if (my_file_buffer != NULL) - yy_delete_buffer(my_file_buffer); - StringToLex = NULL; - my_file_buffer = yy_create_buffer(f, YY_BUF_SIZE); - yy_switch_to_buffer(my_file_buffer); -} -#endif /*FLEX_SCANNER*/ - -int yywrap() -{ - return TRUE; -} - -/* Parse a move from the given string s */ -/* ^ at start of pattern WON'T work here unless using flex */ -ChessMove yylexstr(boardIndex, s) - int boardIndex; - char *s; -{ - ChessMove ret; - char *oldStringToLex; -#ifdef FLEX_SCANNER - YY_BUFFER_STATE buffer, oldBuffer; -#endif - - yyboardindex = boardIndex; - oldStringToLex = StringToLex; - StringToLex = s; -#ifdef FLEX_SCANNER - buffer = yy_create_buffer(stdin, YY_BUF_SIZE); - oldBuffer = YY_CURRENT_BUFFER; - yy_switch_to_buffer(buffer); -#endif /*FLEX_SCANNER*/ - - ret = (ChessMove) yylex(); - -#ifdef FLEX_SCANNER - if (oldBuffer != NULL) - yy_switch_to_buffer(oldBuffer); - yy_delete_buffer(buffer); -#endif /*FLEX_SCANNER*/ - StringToLex = oldStringToLex; - - return ret; -} +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include +#include + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#ifndef _WIN32 +#include +#endif + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define YY_USES_REJECT +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 42 +#define YY_END_OF_BUFFER 43 +static yyconst short int yy_acclist[709] = + { 0, + 43, 41, 42, 41, 42, 41, 42, 40, 41, 42, + 41, 42, 25, 41, 42, 41, 42, 40, 41, 42, + 40, 41, 42,16410, 40, 41, 42,16410, 41, 42, + 40, 41, 42, 40, 41, 42, 40, 41, 42, 40, + 41, 42, 40, 41, 42, 40, 41, 42, 40, 41, + 42, 40, 41, 42, 40, 41, 42, 40, 41, 42, + 40, 41, 42, 40, 41, 42, 40, 41, 42, 41, + 42, 40, 41, 42, 40, 41, 42, 40, 41, 42, + 40, 41, 42, 40, 41, 42, 40, 41, 42, 40, + 41, 42, 40, 41, 42, 40, 41, 42, 40, 41, + + 42, 40, 41, 42, 40, 41, 42, 40, 41, 42, + 40, 41, 42, 40, 41, 42, 41, 42, 41, 42, + 40, 41, 42, 40, 41, 42, 40, 41, 42,16410, + 40, 41, 42,16410, 41, 42, 40, 41, 42, 40, + 41, 42, 40, 41, 42, 40, 41, 42, 40, 41, + 42, 40, 41, 42, 40, 41, 42, 40, 41, 42, + 40, 41, 42, 40, 41, 42, 40, 41, 42, 40, + 41, 42, 40, 41, 42, 40, 41, 42, 40, 41, + 42, 40, 41, 42, 40, 41, 42, 40, 41, 42, + 40, 41, 42, 40, 41, 42, 40, 41, 42, 40, + + 41, 42, 40, 41, 42, 40, 41, 42, 40, 41, + 42, 40, 41, 42, 40, 41, 42, 40, 41, 42, + 41, 42, 33, 40, 17, 40, 9, 40, 40, 40, + 16410, 8218, 40, 35, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 9, 40, 40, 40, 40, + 40, 40, 40, 36, 40, 3, 40, 40, 4, 40, + 40, 40, 3, 40, 40, 4, 40, 40, 40, 40, + 40, 40, 9, 40, 40, 34, 40, 40, 9, 40, + 40, 40,16410, 8218, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 9, 40, 40, 40, + + 40, 40, 40, 40, 40, 3, 40, 40, 4, 40, + 40, 40, 3, 40, 40, 4, 40, 40, 40, 40, + 40, 40, 9, 40, 40, 15, 9, 40, 23, 40, + 23, 8, 40, 8218, 22, 40, 22, 24, 40, 40, + 40, 6, 40, 40, 40, 40, 40, 40, 40, 9, + 40, 40, 40, 40, 40, 20, 40, 4, 40, 40, + 3, 40, 3, 40, 40, 4, 5, 40, 4, 40, + 40, 4, 40, 40, 3, 40, 40, 4, 4, 40, + 5, 6, 40, 4, 40, 40, 40, 9, 40, 40, + 34, 39, 9, 40, 23, 40, 8, 40, 22, 40, + + 35, 40, 40, 40, 6, 40, 40, 40, 40, 40, + 40, 40, 9, 40, 40, 40, 40, 40, 20, 40, + 4, 40, 40, 3, 40, 3, 40, 40, 5, 40, + 4, 40, 40, 4, 40, 40, 3, 40, 40, 4, + 40, 5, 6, 40, 4, 40, 40, 40, 9, 40, + 40, 38, 38, 37, 25, 25, 40, 6, 40, 7, + 40, 6, 10, 40, 40, 40, 40, 19, 40, 40, + 21, 40, 16, 40, 40, 40, 40, 40, 20, 20, + 40, 20, 40, 36, 3, 3, 2, 40, 5, 4, + 5, 40, 40, 4, 4, 40, 2, 7, 40, 5, + + 6, 5, 6, 40, 5, 40, 40, 40, 25, 39, + 40, 6, 40, 7, 40, 40, 40, 40, 40, 19, + 40, 40, 21, 40, 16, 40, 40, 40, 40, 40, + 20, 40, 20, 20, 40, 2, 40, 5, 40, 40, + 4, 40, 2, 7, 40, 5, 6, 40, 5, 40, + 40, 40, 7, 1, 40, 40, 40, 19, 40, 40, + 40, 21, 21, 40, 21, 40, 40, 40, 40, 30, + 36, 2, 2, 40, 5, 4, 5, 5, 40, 2, + 7, 39, 1, 40, 40, 40, 19, 40, 40, 40, + 21, 40, 21, 21, 40, 40, 40, 40, 20, 39, + + 2, 40, 5, 40, 27, 38, 23, 23, 22, 22, + 24, 24, 1, 1, 40, 20, 21, 40, 40, 40, + 11, 40, 40, 28, 36, 30, 2, 2, 5, 27, + 34, 39, 39, 1, 40, 40, 40, 40, 21, 39, + 11, 40, 40, 20, 39, 18, 24, 1, 1, 20, + 21, 19, 40, 40, 40, 11, 40, 40, 40, 40, + 21, 39, 40, 11, 40, 40, 12, 40, 40, 40, + 40, 12, 40, 40, 14, 40, 40, 40, 14, 40, + 40, 40, 39, 40, 40, 40, 40, 39, 39, 40, + 40, 31, 40, 39, 39, 31, 40, 13, 31, 32, + + 32, 35, 39, 39, 31, 39, 34, 29 + } ; + +static yyconst short int yy_accept[736] = + { 0, + 1, 1, 1, 2, 4, 6, 8, 11, 13, 16, + 18, 21, 25, 29, 31, 34, 37, 40, 43, 46, + 49, 52, 55, 58, 61, 64, 67, 70, 72, 75, + 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, + 108, 111, 114, 117, 119, 121, 124, 127, 131, 135, + 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, + 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, + 197, 200, 203, 206, 209, 212, 215, 218, 221, 223, + 223, 224, 225, 225, 225, 225, 225, 226, 226, 226, + 227, 227, 229, 229, 229, 229, 230, 230, 230, 232, + + 232, 234, 234, 235, 236, 236, 237, 237, 237, 238, + 238, 239, 240, 241, 242, 243, 244, 245, 246, 248, + 249, 250, 251, 252, 253, 254, 254, 254, 254, 254, + 255, 256, 258, 258, 259, 261, 262, 263, 265, 265, + 266, 268, 269, 270, 271, 272, 273, 275, 276, 276, + 276, 276, 277, 277, 278, 278, 279, 281, 281, 282, + 284, 284, 286, 286, 287, 288, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 299, 300, 301, 302, + 303, 304, 305, 306, 308, 308, 309, 311, 312, 313, + 315, 315, 316, 318, 319, 320, 321, 322, 323, 325, + + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + 326, 326, 327, 327, 327, 327, 329, 331, 332, 334, + 335, 335, 335, 335, 337, 338, 339, 340, 340, 341, + 341, 342, 342, 342, 344, 344, 344, 344, 344, 345, + 346, 347, 348, 349, 350, 352, 353, 354, 355, 356, + 358, 358, 358, 358, 358, 360, 360, 361, 361, 361, + 363, 365, 366, 367, 367, 369, 369, 371, 372, 374, + 375, 375, 377, 378, 379, 381, 384, 386, 387, 388, + 390, 391, 392, 392, 392, 392, 392, 393, 395, 397, + 399, 401, 401, 402, 402, 403, 404, 404, 405, 407, + + 408, 409, 410, 411, 412, 413, 415, 416, 417, 418, + 419, 421, 423, 424, 424, 426, 428, 429, 431, 433, + 434, 436, 437, 437, 439, 440, 442, 445, 447, 448, + 449, 451, 452, 452, 452, 453, 454, 454, 454, 455, + 455, 455, 456, 456, 457, 457, 457, 457, 458, 458, + 458, 458, 458, 458, 458, 458, 460, 460, 460, 462, + 463, 464, 465, 465, 466, 466, 466, 466, 466, 467, + 468, 470, 470, 471, 473, 475, 476, 477, 478, 479, + 480, 482, 484, 484, 484, 484, 484, 485, 486, 486, + 487, 489, 490, 491, 491, 491, 491, 493, 494, 495, + + 495, 497, 497, 500, 502, 505, 507, 508, 509, 509, + 510, 510, 510, 510, 510, 511, 511, 512, 512, 512, + 514, 516, 517, 517, 518, 519, 520, 522, 523, 525, + 527, 528, 529, 530, 531, 533, 534, 536, 538, 540, + 541, 543, 546, 549, 551, 552, 553, 553, 553, 553, + 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 554, 556, 556, 556, 556, 556, 557, 558, 558, 560, + 560, 561, 562, 563, 565, 567, 568, 569, 570, 570, + 570, 572, 572, 572, 573, 573, 573, 575, 576, 576, + 577, 578, 578, 580, 580, 582, 582, 582, 582, 582, + + 582, 582, 583, 583, 583, 585, 586, 587, 589, 590, + 591, 593, 594, 596, 597, 598, 599, 601, 603, 605, + 605, 605, 607, 607, 607, 608, 608, 609, 609, 610, + 610, 611, 611, 612, 612, 613, 613, 613, 614, 614, + 614, 616, 616, 616, 618, 618, 619, 619, 619, 619, + 619, 619, 620, 621, 623, 624, 626, 626, 627, 628, + 629, 630, 630, 630, 632, 632, 632, 633, 634, 634, + 634, 636, 637, 638, 639, 641, 643, 644, 646, 646, + 647, 647, 647, 647, 648, 649, 650, 650, 650, 650, + 652, 652, 652, 653, 653, 653, 653, 653, 654, 655, + + 656, 658, 659, 659, 659, 659, 659, 659, 660, 661, + 663, 664, 666, 667, 667, 667, 667, 667, 667, 667, + 668, 668, 668, 668, 668, 669, 670, 670, 670, 670, + 670, 671, 672, 672, 672, 672, 672, 673, 673, 673, + 673, 674, 675, 677, 677, 677, 677, 677, 678, 678, + 679, 681, 681, 681, 681, 681, 682, 683, 683, 683, + 683, 683, 684, 685, 686, 686, 686, 686, 686, 686, + 687, 688, 688, 688, 688, 688, 689, 690, 691, 692, + 692, 692, 692, 692, 692, 694, 694, 694, 694, 694, + 695, 696, 698, 698, 698, 699, 699, 700, 700, 701, + + 701, 701, 703, 703, 704, 705, 705, 705, 705, 705, + 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, + 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, + 707, 707, 708, 709, 709 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 5, 6, 7, 8, 1, 9, 10, + 11, 12, 13, 1, 14, 15, 16, 17, 18, 19, + 20, 20, 20, 20, 20, 20, 20, 21, 22, 1, + 23, 1, 1, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 33, 43, 33, 44, 45, 33, 33, + 46, 1, 47, 1, 48, 1, 49, 50, 51, 52, + + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 40, 65, 66, 67, 68, 33, 69, 45, + 70, 33, 71, 1, 72, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[73] = + { 0, + 1, 2, 3, 2, 1, 1, 1, 1, 4, 5, + 6, 1, 1, 7, 1, 1, 8, 8, 8, 8, + 9, 1, 10, 1, 11, 11, 11, 12, 12, 12, + 12, 12, 4, 11, 4, 4, 11, 12, 12, 11, + 11, 4, 4, 12, 7, 1, 1, 1, 13, 13, + 13, 14, 15, 14, 14, 14, 14, 14, 13, 14, + 4, 11, 12, 12, 11, 4, 4, 4, 4, 4, + 1, 1 + } ; + +static yyconst short int yy_base[824] = + { 0, + 0, 72, 2710, 5057, 120, 129, 0, 140, 2705, 138, + 149, 169, 160, 2705, 226, 157, 2651, 151, 2679, 130, + 2639, 131, 227, 271, 2648, 2633, 244, 331, 390, 447, + 203, 239, 332, 338, 375, 340, 370, 428, 430, 249, + 2650, 201, 254, 397, 2694, 147, 253, 506, 344, 257, + 568, 189, 2641, 229, 2672, 339, 294, 248, 335, 620, + 2642, 284, 574, 667, 724, 318, 640, 555, 608, 709, + 590, 610, 690, 746, 761, 462, 449, 644, 577, 2639, + 455, 0, 2683, 303, 781, 309, 5057, 2679, 439, 354, + 2673, 2673, 2671, 419, 692, 2671, 491, 160, 809, 2670, + + 0, 2683, 5057, 782, 0, 829, 0, 0, 499, 862, + 712, 582, 2636, 2641, 2615, 2616, 736, 2640, 2639, 717, + 797, 2627, 769, 829, 2613, 2627, 927, 336, 999, 5057, + 1023, 1074, 0, 1091, 1142, 834, 1159, 1206, 0, 1218, + 1265, 838, 847, 842, 2606, 2609, 2608, 2613, 303, 2597, + 890, 2664, 2663, 572, 2662, 594, 633, 298, 634, 1324, + 401, 688, 429, 1386, 1433, 2661, 851, 927, 900, 903, + 751, 689, 892, 946, 2626, 946, 951, 960, 973, 968, + 972, 690, 1445, 1496, 2659, 1513, 1565, 1010, 1582, 1629, + 2658, 1641, 1688, 1018, 1036, 1040, 972, 1003, 1023, 694, + + 804, 2596, 446, 503, 518, 2649, 542, 1153, 1167, 2648, + 2586, 5057, 2649, 2648, 2647, 2636, 2643, 2638, 0, 5057, + 2632, 2627, 2626, 2625, 2624, 808, 1023, 1045, 1073, 0, + 1072, 1085, 1136, 1735, 2570, 2563, 2576, 2571, 1179, 1229, + 2554, 1154, 930, 2569, 2607, 0, 2563, 2559, 1214, 1795, + 569, 1240, 605, 1867, 1930, 0, 1947, 0, 2608, 2606, + 1218, 1204, 1278, 0, 1998, 2606, 755, 398, 1272, 2015, + 0, 1288, 1317, 1395, 1379, 2062, 1405, 1391, 2564, 2600, + 2546, 5057, 1446, 750, 2608, 127, 2608, 885, 1185, 996, + 1447, 789, 2606, 1238, 1410, 2114, 2602, 1452, 2161, 1602, + + 1652, 1181, 1707, 1458, 1506, 1412, 0, 1100, 1179, 1637, + 2221, 2285, 2302, 2601, 1101, 1701, 1706, 2353, 1523, 1580, + 1383, 2370, 2600, 1742, 1748, 1457, 2417, 1803, 1816, 1411, + 1499, 1608, 1103, 2550, 5057, 817, 834, 2591, 5057, 1828, + 2590, 2589, 2527, 2526, 2579, 2578, 2577, 2577, 388, 2576, + 349, 2575, 890, 1761, 1029, 0, 1326, 1560, 0, 5057, + 5057, 2429, 1436, 1590, 2525, 2525, 2522, 2522, 2528, 2522, + 815, 503, 841, 2489, 0, 2542, 2524, 2525, 2522, 0, + 2561, 2633, 858, 907, 910, 1727, 2565, 2553, 1645, 5057, + 2696, 1760, 1085, 618, 1805, 2549, 1241, 1003, 2505, 2493, + + 0, 1759, 0, 1834, 2752, 1875, 1834, 2491, 1882, 2549, + 1901, 1902, 2503, 2488, 2547, 434, 1522, 653, 953, 1219, + 1291, 2809, 2545, 1912, 1875, 1888, 1899, 1572, 2869, 1505, + 1519, 1604, 1898, 1915, 2941, 2544, 3013, 3077, 1916, 1951, + 1591, 0, 3133, 1967, 2025, 1841, 1663, 2494, 2535, 1637, + 2534, 2472, 2532, 2469, 2529, 2467, 2520, 1748, 1924, 5057, + 3189, 2483, 2479, 2479, 2474, 2526, 1268, 1972, 2525, 870, + 2498, 2473, 0, 3254, 3326, 2463, 2463, 2519, 1299, 1946, + 5057, 2515, 1971, 1097, 1394, 1506, 2508, 1319, 1239, 5057, + 2454, 2439, 0, 2483, 1817, 2013, 2474, 1582, 2448, 2400, + + 2393, 1048, 1250, 1594, 3389, 2005, 2020, 2073, 2069, 1937, + 3454, 2440, 3526, 2041, 1956, 2075, 2440, 2084, 2010, 2077, + 430, 5057, 2114, 2425, 2424, 2360, 2345, 2405, 2403, 2341, + 2339, 2397, 2394, 2328, 2326, 2379, 2373, 1850, 2076, 2077, + 2380, 2325, 2315, 2035, 2311, 2293, 2330, 2286, 2267, 2304, + 2279, 2288, 2263, 2044, 2278, 5057, 2008, 5057, 2312, 5057, + 5057, 2306, 2123, 2296, 2238, 2232, 2283, 1861, 872, 1450, + 2118, 2127, 2135, 2136, 2278, 2137, 2129, 2273, 2177, 5057, + 2187, 2142, 2203, 2200, 2177, 5057, 2125, 2129, 2103, 5057, + 2089, 2136, 2126, 2064, 2105, 2066, 1992, 2011, 1986, 1984, + + 0, 1960, 2180, 1990, 1924, 1065, 1113, 2229, 2175, 1960, + 2172, 2083, 2180, 2191, 1900, 1933, 1299, 1883, 1859, 2126, + 1806, 1072, 1787, 1760, 3598, 1728, 1719, 1697, 1506, 1747, + 3670, 2230, 2232, 1665, 1664, 1616, 5057, 1582, 1880, 1999, + 3742, 2081, 0, 1530, 1479, 1752, 1163, 3814, 2244, 2160, + 2244, 2252, 1487, 1478, 2229, 1476, 1419, 1392, 1372, 1591, + 1710, 2254, 1312, 1271, 2256, 1158, 1136, 2225, 2227, 1106, + 942, 906, 918, 1045, 1456, 2259, 2315, 875, 756, 2293, + 2211, 733, 2243, 2248, 0, 701, 584, 603, 1827, 2312, + 2314, 0, 2299, 538, 5057, 421, 2242, 473, 5057, 304, + + 315, 5057, 2151, 2378, 2346, 2302, 234, 206, 1795, 2379, + 2317, 203, 1623, 1642, 1664, 1887, 2369, 2370, 2382, 2383, + 2434, 2436, 2437, 2442, 2443, 2444, 2446, 2449, 2450, 2514, + 2030, 159, 5057, 5057, 3883, 3898, 3913, 3928, 3943, 3955, + 3970, 3985, 3999, 4002, 4005, 4008, 4023, 4038, 4041, 4044, + 4059, 4074, 4086, 4101, 4116, 4131, 4146, 4161, 4176, 4191, + 4194, 4209, 4224, 4239, 4254, 4269, 1899, 4272, 4283, 2048, + 4286, 4301, 4316, 4328, 4343, 4358, 4373, 4388, 4403, 4418, + 4433, 4448, 4457, 4472, 4487, 4502, 4517, 4532, 4547, 4562, + 4573, 4588, 4603, 4618, 4633, 4648, 4663, 4678, 4693, 4708, + + 4723, 4738, 4753, 4768, 4783, 4798, 4813, 4828, 4839, 4852, + 4867, 4882, 4897, 4908, 4921, 4936, 4951, 4966, 4981, 4996, + 5011, 5026, 5041 + } ; + +static yyconst short int yy_def[824] = + { 0, + 734, 734, 734, 734, 734, 734, 735, 736, 734, 734, + 735, 734, 12, 737, 735, 15, 15, 15, 15, 15, + 735, 15, 15, 735, 15, 735, 15, 738, 15, 15, + 29, 29, 29, 29, 29, 29, 29, 29, 30, 29, + 735, 735, 735, 739, 734, 740, 740, 734, 48, 737, + 740, 51, 51, 51, 51, 51, 740, 51, 51, 740, + 51, 740, 51, 51, 51, 64, 64, 64, 64, 64, + 64, 64, 64, 65, 64, 740, 740, 740, 739, 734, + 734, 735, 741, 742, 741, 734, 734, 734, 734, 735, + 734, 735, 734, 743, 743, 735, 743, 734, 12, 734, + + 735, 737, 734, 735, 744, 735, 745, 746, 106, 734, + 106, 106, 735, 735, 735, 735, 106, 104, 735, 735, + 106, 735, 106, 106, 735, 747, 738, 747, 748, 734, + 735, 735, 749, 735, 735, 735, 735, 132, 750, 735, + 135, 106, 106, 735, 735, 735, 735, 735, 739, 751, + 739, 734, 752, 753, 734, 753, 753, 734, 753, 734, + 734, 753, 754, 753, 164, 745, 165, 165, 165, 753, + 753, 753, 753, 165, 164, 753, 753, 165, 753, 165, + 165, 753, 164, 164, 749, 164, 753, 753, 164, 184, + 750, 164, 187, 165, 165, 753, 753, 753, 753, 753, + + 739, 734, 755, 756, 756, 757, 758, 755, 755, 759, + 760, 734, 734, 734, 734, 735, 735, 734, 735, 734, + 734, 734, 734, 735, 734, 734, 735, 734, 106, 761, + 735, 734, 734, 735, 734, 734, 734, 734, 735, 735, + 735, 735, 735, 735, 735, 234, 735, 735, 735, 762, + 763, 764, 765, 766, 735, 767, 735, 768, 767, 735, + 735, 735, 769, 770, 735, 770, 735, 735, 255, 735, + 771, 735, 735, 770, 255, 265, 735, 735, 735, 735, + 735, 734, 739, 734, 772, 734, 773, 774, 774, 774, + 774, 775, 772, 776, 774, 774, 761, 774, 296, 774, + + 774, 774, 774, 774, 774, 774, 299, 774, 774, 774, + 777, 774, 296, 768, 774, 774, 774, 312, 774, 774, + 312, 296, 771, 774, 774, 312, 318, 774, 774, 774, + 774, 774, 739, 734, 734, 778, 778, 779, 734, 780, + 781, 781, 782, 782, 734, 734, 734, 735, 734, 734, + 734, 734, 734, 734, 734, 735, 783, 734, 735, 734, + 734, 735, 783, 735, 734, 734, 734, 734, 735, 735, + 735, 734, 735, 784, 735, 735, 735, 735, 735, 785, + 786, 786, 787, 787, 788, 789, 790, 734, 734, 734, + 735, 791, 734, 734, 791, 395, 735, 735, 734, 734, + + 735, 734, 391, 395, 391, 735, 735, 735, 739, 734, + 734, 734, 734, 734, 792, 734, 774, 793, 793, 774, + 774, 774, 363, 774, 774, 774, 774, 774, 794, 774, + 774, 774, 774, 774, 795, 785, 795, 774, 774, 774, + 774, 438, 438, 774, 774, 774, 739, 734, 796, 797, + 798, 799, 800, 801, 802, 803, 734, 734, 734, 734, + 735, 734, 734, 734, 734, 735, 735, 734, 735, 734, + 735, 735, 804, 805, 805, 735, 735, 735, 806, 807, + 734, 808, 734, 809, 809, 809, 735, 734, 734, 734, + 734, 734, 735, 734, 809, 739, 734, 734, 734, 734, + + 734, 810, 811, 811, 438, 774, 774, 774, 774, 774, + 812, 804, 812, 774, 774, 774, 813, 774, 774, 739, + 734, 734, 797, 798, 798, 799, 799, 800, 800, 801, + 801, 802, 802, 803, 803, 734, 734, 814, 814, 814, + 735, 734, 734, 734, 734, 735, 815, 734, 734, 734, + 734, 735, 735, 735, 735, 734, 734, 734, 734, 734, + 734, 734, 739, 734, 734, 734, 810, 810, 811, 811, + 774, 774, 774, 774, 816, 774, 774, 813, 739, 734, + 734, 797, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 815, 815, 734, 734, 734, 734, 735, 735, 735, + + 735, 735, 739, 734, 734, 811, 811, 774, 774, 816, + 774, 774, 774, 739, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 817, 735, 734, 734, 811, 811, + 818, 774, 739, 734, 734, 734, 734, 734, 819, 819, + 817, 641, 735, 734, 734, 811, 811, 818, 819, 648, + 774, 739, 734, 734, 819, 641, 641, 734, 734, 811, + 811, 820, 648, 648, 739, 734, 734, 819, 819, 641, + 641, 734, 734, 811, 811, 820, 820, 648, 648, 739, + 734, 734, 819, 819, 641, 821, 734, 822, 811, 820, + 820, 648, 739, 734, 734, 734, 819, 821, 734, 734, + + 822, 734, 811, 820, 820, 739, 734, 734, 811, 820, + 739, 734, 811, 739, 823, 823, 823, 823, 823, 823, + 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, + 823, 734, 734, 0, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734 + } ; + +static yyconst short int yy_nxt[5130] = + { 0, + 4, 4, 4, 5, 4, 4, 6, 4, 7, 8, + 4, 9, 10, 7, 4, 4, 11, 12, 13, 13, + 4, 14, 4, 4, 15, 16, 17, 18, 19, 19, + 20, 19, 7, 19, 21, 22, 15, 23, 24, 15, + 25, 26, 7, 27, 7, 28, 4, 4, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 15, 42, 24, 25, 26, 7, 7, 43, 7, + 44, 4, 4, 4, 4, 5, 4, 45, 6, 45, + 7, 8, 4, 9, 10, 46, 4, 4, 47, 48, + 49, 49, 4, 50, 4, 4, 51, 52, 53, 54, + + 55, 55, 56, 55, 46, 55, 57, 58, 51, 59, + 60, 51, 61, 62, 46, 63, 46, 28, 4, 4, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 51, 77, 60, 61, 62, 46, 46, + 78, 46, 79, 4, 80, 81, 81, 81, 81, 84, + 87, 88, 89, 734, 734, 82, 85, 85, 85, 85, + 110, 733, 90, 94, 91, 92, 114, 155, 80, 93, + 94, 94, 95, 82, 734, 734, 225, 82, 226, 117, + 734, 413, 96, 97, 98, 99, 99, 99, 99, 100, + 414, 115, 110, 101, 101, 101, 101, 101, 101, 101, + + 101, 82, 101, 82, 82, 101, 101, 101, 101, 101, + 82, 82, 101, 82, 146, 113, 111, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 82, + 101, 101, 101, 101, 82, 82, 82, 82, 82, 104, + 118, 105, 106, 106, 106, 106, 107, 110, 168, 108, + 734, 136, 734, 135, 135, 686, 89, 110, 144, 103, + 163, 82, 734, 147, 119, 712, 156, 734, 91, 157, + 104, 734, 734, 158, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 105, 136, 136, 135, + 135, 135, 82, 170, 108, 580, 174, 136, 136, 123, + + 124, 287, 82, 113, 155, 150, 125, 135, 135, 148, + 125, 116, 206, 207, 155, 218, 125, 702, 210, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 126, 127, 127, 127, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 128, 126, 126, 94, 175, 251, + 179, 126, 126, 126, 126, 734, 173, 154, 734, 734, + 708, 734, 734, 734, 155, 225, 188, 226, 187, 187, + 216, 217, 176, 196, 152, 171, 126, 130, 126, 211, + 136, 136, 130, 135, 135, 135, 136, 136, 136, 136, + 135, 135, 135, 734, 135, 135, 135, 451, 734, 150, + + 172, 126, 126, 131, 287, 734, 132, 132, 132, 132, + 133, 114, 400, 151, 151, 151, 151, 225, 136, 136, + 94, 94, 94, 136, 136, 135, 135, 135, 135, 135, + 135, 293, 294, 734, 134, 502, 115, 502, 135, 135, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 110, 734, 213, 734, 214, 204, 335, 82, 452, 215, + 137, 401, 198, 138, 138, 138, 138, 139, 152, 155, + 82, 81, 81, 81, 81, 699, 136, 136, 142, 142, + 142, 580, 155, 707, 135, 135, 135, 141, 141, 141, + 581, 140, 94, 94, 94, 141, 141, 141, 142, 142, + + 142, 142, 142, 142, 142, 142, 143, 94, 94, 95, + 197, 199, 206, 336, 82, 234, 234, 234, 234, 159, + 97, 98, 160, 160, 160, 160, 161, 206, 336, 470, + 162, 162, 162, 162, 162, 162, 162, 162, 154, 162, + 154, 154, 162, 162, 162, 162, 162, 154, 154, 162, + 154, 338, 339, 470, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 154, 162, 162, 162, + 162, 154, 154, 154, 154, 154, 82, 110, 734, 150, + 82, 164, 384, 105, 165, 165, 165, 165, 166, 695, + 201, 108, 155, 151, 151, 151, 151, 734, 234, 234, + + 234, 234, 82, 188, 188, 702, 187, 187, 187, 386, + 288, 289, 164, 734, 155, 130, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 82, 180, + 181, 734, 400, 734, 240, 105, 182, 700, 188, 188, + 155, 82, 82, 108, 187, 187, 187, 110, 152, 290, + 291, 387, 82, 155, 155, 103, 188, 188, 188, 188, + 187, 187, 187, 734, 155, 187, 187, 187, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 183, 490, 734, 184, 184, 184, 184, 185, 188, 188, + 187, 187, 187, 94, 94, 94, 82, 82, 82, 200, + + 182, 503, 82, 699, 170, 221, 182, 222, 155, 155, + 155, 186, 223, 734, 155, 187, 187, 188, 188, 188, + 188, 188, 188, 188, 188, 188, 188, 110, 234, 234, + 234, 234, 734, 246, 246, 246, 246, 189, 188, 188, + 190, 190, 190, 190, 191, 171, 187, 187, 187, 734, + 332, 311, 234, 234, 234, 234, 303, 188, 188, 82, + 239, 410, 187, 187, 187, 399, 411, 412, 192, 734, + 172, 155, 193, 193, 193, 194, 194, 194, 194, 194, + 194, 194, 194, 195, 734, 234, 234, 234, 234, 696, + 204, 293, 294, 303, 194, 194, 194, 208, 208, 208, + + 208, 209, 244, 193, 193, 193, 150, 268, 692, 188, + 188, 354, 94, 234, 234, 234, 234, 333, 468, 187, + 187, 355, 82, 173, 734, 249, 338, 339, 355, 734, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 227, 227, 229, 338, 339, 234, 234, 234, 234, 230, + 265, 265, 265, 265, 276, 276, 276, 276, 265, 265, + 265, 265, 247, 276, 276, 276, 276, 299, 299, 299, + 299, 384, 471, 229, 103, 152, 469, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 235, + 250, 236, 150, 82, 279, 239, 472, 237, 417, 453, + + 82, 550, 238, 692, 130, 155, 151, 151, 151, 151, + 283, 82, 155, 235, 386, 236, 299, 299, 299, 299, + 479, 687, 237, 155, 606, 551, 238, 126, 127, 127, + 127, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 299, 299, 299, 299, 126, 126, 126, + 126, 302, 301, 130, 82, 103, 387, 304, 686, 82, + 454, 152, 299, 299, 299, 299, 155, 307, 307, 307, + 307, 155, 126, 130, 126, 300, 299, 299, 299, 299, + 82, 82, 374, 290, 299, 299, 299, 299, 299, 299, + 299, 299, 155, 155, 685, 374, 374, 126, 126, 126, + + 252, 252, 252, 253, 82, 126, 126, 126, 126, 126, + 126, 82, 305, 126, 126, 504, 155, 492, 82, 126, + 126, 309, 126, 155, 310, 308, 318, 318, 318, 318, + 155, 82, 457, 311, 327, 327, 327, 327, 305, 356, + 356, 356, 356, 155, 126, 130, 458, 103, 82, 568, + 416, 568, 327, 327, 327, 327, 318, 318, 318, 318, + 155, 357, 357, 357, 357, 331, 493, 103, 629, 126, + 126, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 256, 300, 290, 82, 257, 359, 359, + 359, 359, 330, 734, 258, 399, 259, 688, 260, 260, + + 260, 360, 360, 360, 360, 150, 485, 260, 82, 82, + 260, 390, 548, 260, 260, 103, 447, 82, 257, 486, + 155, 155, 261, 261, 261, 262, 262, 262, 262, 262, + 262, 262, 261, 262, 685, 260, 548, 394, 260, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 264, 361, 361, 361, 361, 432, 372, 265, 265, + 265, 265, 204, 335, 266, 103, 267, 267, 267, 208, + 208, 208, 208, 209, 152, 267, 204, 335, 267, 630, + 373, 267, 267, 340, 340, 340, 340, 82, 349, 82, + 267, 267, 267, 82, 268, 359, 359, 359, 359, 155, + + 267, 155, 682, 267, 373, 155, 267, 269, 269, 269, + 269, 269, 269, 269, 269, 269, 269, 269, 269, 270, + 391, 391, 391, 391, 681, 661, 271, 82, 390, 369, + 359, 359, 359, 359, 391, 391, 391, 391, 433, 155, + 103, 252, 252, 252, 253, 359, 359, 359, 359, 427, + 270, 491, 103, 492, 272, 272, 272, 273, 273, 273, + 273, 273, 273, 273, 272, 273, 275, 275, 275, 275, + 275, 275, 275, 275, 275, 275, 275, 275, 229, 370, + 379, 276, 276, 276, 276, 230, 130, 264, 356, 356, + 356, 356, 418, 398, 392, 392, 392, 392, 390, 82, + + 266, 419, 561, 546, 403, 403, 403, 403, 455, 229, + 569, 155, 479, 277, 277, 277, 231, 278, 231, 231, + 231, 231, 231, 277, 231, 94, 94, 94, 546, 491, + 394, 679, 82, 403, 403, 403, 403, 154, 97, 363, + 160, 160, 160, 160, 155, 556, 363, 678, 162, 162, + 162, 162, 162, 162, 162, 162, 154, 162, 154, 154, + 162, 162, 162, 162, 162, 154, 154, 162, 154, 456, + 363, 489, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 154, 162, 162, 162, 162, 154, + 154, 154, 154, 154, 82, 405, 405, 405, 405, 420, + + 420, 420, 420, 734, 264, 400, 155, 359, 359, 359, + 359, 404, 404, 404, 404, 399, 734, 266, 82, 82, + 82, 359, 359, 359, 359, 431, 420, 420, 420, 420, + 155, 155, 155, 673, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 296, 394, 150, 734, + 353, 672, 103, 297, 401, 82, 734, 268, 103, 689, + 82, 426, 409, 409, 409, 409, 82, 155, 421, 421, + 421, 421, 155, 443, 443, 443, 443, 296, 155, 671, + 734, 298, 298, 298, 298, 298, 298, 298, 298, 298, + 298, 298, 298, 312, 312, 312, 312, 312, 312, 312, + + 312, 312, 312, 312, 312, 256, 607, 82, 103, 313, + 429, 670, 446, 82, 82, 485, 314, 152, 259, 155, + 315, 315, 315, 429, 429, 155, 155, 82, 734, 315, + 82, 82, 315, 399, 667, 315, 315, 666, 290, 155, + 313, 659, 155, 155, 316, 316, 316, 317, 317, 317, + 317, 317, 317, 317, 316, 317, 290, 315, 430, 646, + 315, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 82, 264, 320, 460, 460, 460, 460, + 82, 318, 318, 318, 318, 155, 658, 266, 82, 319, + 319, 319, 155, 103, 400, 221, 103, 222, 319, 82, + + 155, 319, 223, 509, 319, 319, 461, 461, 461, 461, + 82, 155, 82, 319, 319, 319, 82, 320, 421, 421, + 421, 421, 155, 319, 155, 103, 319, 510, 155, 319, + 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 322, 441, 715, 82, 204, 522, 654, 323, + 674, 523, 425, 421, 421, 421, 421, 155, 514, 570, + 82, 484, 484, 484, 484, 150, 717, 637, 421, 421, + 421, 421, 155, 322, 434, 688, 520, 324, 324, 324, + 325, 325, 325, 325, 325, 325, 325, 324, 325, 326, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + + 326, 296, 426, 434, 327, 327, 327, 327, 297, 82, + 372, 390, 103, 152, 82, 82, 653, 438, 438, 438, + 438, 155, 438, 438, 438, 438, 155, 155, 480, 480, + 480, 580, 296, 428, 152, 282, 328, 328, 328, 298, + 329, 298, 298, 298, 298, 298, 328, 298, 362, 103, + 82, 536, 390, 645, 103, 363, 82, 428, 442, 442, + 442, 442, 155, 537, 442, 442, 442, 442, 155, 395, + 455, 675, 644, 481, 355, 495, 495, 495, 495, 362, + 643, 355, 396, 364, 364, 364, 364, 364, 364, 364, + 364, 364, 364, 364, 364, 380, 380, 103, 380, 380, + + 380, 380, 380, 647, 380, 380, 380, 380, 660, 380, + 380, 82, 489, 399, 734, 380, 380, 380, 380, 421, + 421, 421, 421, 155, 82, 639, 485, 734, 639, 103, + 400, 456, 421, 421, 421, 421, 155, 204, 335, 486, + 380, 380, 380, 395, 450, 450, 450, 450, 492, 82, + 461, 461, 461, 461, 713, 320, 396, 734, 638, 539, + 382, 155, 568, 416, 568, 380, 380, 126, 252, 252, + 252, 253, 540, 126, 126, 126, 126, 126, 126, 441, + 703, 126, 126, 82, 150, 491, 489, 126, 126, 717, + 126, 461, 461, 461, 461, 155, 82, 493, 496, 496, + + 496, 496, 468, 290, 89, 498, 82, 82, 155, 388, + 655, 388, 126, 130, 497, 499, 91, 98, 155, 155, + 82, 93, 100, 82, 82, 620, 491, 398, 505, 505, + 505, 505, 155, 506, 655, 155, 155, 126, 126, 264, + 538, 538, 538, 538, 635, 82, 507, 480, 480, 480, + 515, 584, 266, 152, 267, 267, 267, 155, 282, 82, + 508, 634, 416, 267, 82, 492, 267, 516, 440, 267, + 267, 155, 557, 557, 557, 82, 155, 491, 267, 267, + 267, 547, 268, 505, 505, 505, 505, 155, 267, 574, + 628, 267, 481, 627, 267, 262, 262, 262, 262, 262, + + 262, 262, 262, 262, 262, 262, 262, 395, 110, 557, + 557, 557, 548, 82, 519, 150, 577, 558, 82, 440, + 396, 549, 397, 397, 397, 155, 626, 563, 82, 655, + 155, 397, 717, 82, 397, 601, 548, 397, 397, 492, + 155, 505, 505, 505, 505, 155, 397, 397, 397, 82, + 398, 625, 625, 655, 558, 572, 397, 624, 393, 397, + 393, 155, 397, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 362, 468, 82, 110, 150, + 572, 82, 363, 82, 564, 734, 539, 589, 519, 155, + 579, 82, 82, 155, 560, 155, 600, 573, 734, 734, + + 590, 732, 576, 155, 155, 656, 362, 623, 622, 601, + 406, 406, 406, 364, 407, 364, 364, 364, 364, 364, + 406, 364, 82, 204, 335, 150, 82, 621, 586, 657, + 582, 582, 582, 582, 155, 82, 593, 82, 155, 603, + 603, 603, 603, 82, 82, 82, 593, 155, 152, 155, + 620, 204, 522, 103, 590, 155, 155, 155, 582, 582, + 582, 582, 298, 298, 298, 298, 298, 298, 298, 298, + 298, 298, 298, 298, 422, 197, 608, 613, 636, 150, + 82, 423, 150, 82, 663, 619, 618, 586, 82, 611, + 614, 637, 155, 150, 152, 155, 603, 603, 603, 603, + + 155, 609, 612, 617, 633, 422, 616, 709, 664, 424, + 424, 424, 424, 424, 424, 424, 424, 424, 424, 424, + 424, 380, 380, 612, 380, 380, 380, 380, 380, 381, + 380, 380, 380, 380, 150, 380, 380, 82, 82, 615, + 631, 436, 380, 380, 380, 652, 632, 662, 152, 155, + 155, 564, 82, 668, 150, 655, 416, 655, 150, 655, + 683, 416, 152, 694, 155, 665, 380, 380, 380, 680, + 631, 697, 655, 655, 655, 416, 695, 669, 655, 655, + 416, 655, 651, 655, 677, 416, 437, 684, 605, 677, + 604, 380, 380, 82, 264, 150, 655, 655, 655, 284, + + 697, 150, 655, 152, 150, 155, 693, 266, 677, 319, + 319, 319, 706, 677, 416, 711, 416, 416, 319, 150, + 561, 319, 560, 152, 319, 319, 602, 152, 599, 598, + 714, 597, 596, 319, 319, 319, 595, 320, 594, 690, + 593, 145, 677, 319, 677, 677, 319, 704, 416, 319, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, + 317, 317, 395, 691, 152, 591, 677, 588, 677, 677, + 152, 717, 717, 152, 705, 396, 677, 439, 439, 439, + 416, 416, 718, 719, 717, 717, 439, 587, 152, 439, + 586, 584, 439, 439, 583, 720, 721, 535, 710, 535, + + 677, 439, 439, 439, 533, 440, 710, 533, 677, 677, + 531, 439, 531, 529, 439, 529, 527, 439, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, + 422, 527, 677, 677, 525, 525, 717, 423, 717, 717, + 282, 282, 416, 575, 717, 717, 717, 722, 717, 723, + 724, 717, 717, 282, 282, 725, 726, 727, 566, 728, + 565, 422, 729, 730, 225, 444, 444, 444, 424, 445, + 424, 424, 424, 424, 424, 444, 424, 364, 364, 364, + 364, 364, 364, 364, 364, 364, 364, 364, 364, 473, + 473, 218, 473, 473, 473, 473, 473, 490, 473, 473, + + 473, 473, 562, 473, 473, 282, 489, 282, 282, 473, + 473, 473, 473, 282, 282, 282, 717, 282, 560, 483, + 282, 282, 110, 555, 554, 553, 552, 731, 468, 110, + 545, 544, 543, 542, 473, 473, 473, 458, 535, 533, + 531, 475, 529, 527, 525, 207, 521, 517, 287, 416, + 501, 500, 86, 219, 475, 475, 494, 394, 395, 473, + 473, 380, 380, 390, 380, 380, 380, 380, 380, 483, + 380, 380, 380, 380, 478, 380, 380, 477, 476, 219, + 467, 380, 380, 380, 380, 282, 466, 465, 464, 463, + 462, 225, 225, 219, 218, 218, 218, 344, 344, 342, + + 342, 207, 448, 287, 287, 287, 380, 380, 380, 286, + 416, 286, 379, 408, 370, 264, 390, 256, 378, 377, + 376, 375, 371, 368, 367, 366, 365, 353, 353, 352, + 351, 380, 380, 380, 380, 350, 380, 380, 380, 380, + 380, 349, 380, 380, 380, 380, 349, 380, 380, 348, + 347, 346, 345, 380, 380, 380, 380, 344, 342, 335, + 334, 287, 287, 306, 287, 287, 286, 284, 282, 281, + 219, 280, 244, 130, 250, 248, 219, 245, 380, 380, + 380, 243, 242, 242, 241, 103, 225, 224, 218, 219, + 218, 212, 204, 202, 178, 734, 169, 153, 145, 122, + + 121, 116, 734, 380, 380, 485, 112, 103, 86, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 486, 734, + 487, 487, 487, 734, 734, 734, 734, 734, 734, 487, + 734, 734, 487, 734, 734, 487, 487, 734, 734, 734, + 734, 734, 734, 734, 487, 487, 487, 734, 734, 734, + 734, 734, 734, 734, 487, 734, 734, 487, 734, 734, + 487, 395, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 396, 734, 397, 397, 397, 734, + 734, 734, 734, 734, 734, 397, 734, 734, 397, 734, + 734, 397, 397, 734, 734, 734, 734, 734, 734, 734, + + 397, 397, 397, 734, 398, 734, 734, 734, 734, 734, + 397, 734, 734, 397, 734, 734, 397, 82, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 155, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 424, 424, 424, + 424, 424, 424, 424, 424, 424, 424, 424, 424, 473, + 473, 734, 473, 473, 473, 473, 473, 474, 473, 473, + 473, 473, 734, 473, 473, 734, 734, 734, 734, 512, + 473, 473, 473, 734, 734, 734, 734, 734, 734, 734, + + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 473, 473, 473, 734, 734, 734, + 734, 513, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 513, 513, 734, 734, 734, 473, + 473, 380, 380, 734, 380, 380, 380, 380, 380, 381, + 380, 380, 380, 380, 734, 380, 380, 734, 734, 734, + 734, 436, 380, 380, 380, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 380, 380, 380, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 380, 380, 380, 380, 734, 380, 380, 380, 380, + 380, 381, 380, 380, 380, 380, 734, 380, 380, 734, + 734, 734, 734, 436, 380, 380, 380, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 380, 380, + 380, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 380, 380, 82, 485, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 155, 734, 486, + + 734, 518, 518, 518, 734, 734, 734, 734, 734, 734, + 518, 734, 734, 518, 734, 734, 518, 518, 734, 734, + 734, 734, 734, 734, 734, 518, 518, 518, 734, 734, + 734, 734, 734, 734, 734, 518, 734, 734, 518, 734, + 734, 518, 395, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 396, 734, 439, 439, 439, + 734, 734, 734, 734, 734, 734, 439, 734, 734, 439, + 734, 734, 439, 439, 734, 734, 734, 734, 734, 734, + 734, 439, 439, 439, 734, 440, 734, 734, 734, 734, + 734, 439, 734, 734, 439, 734, 734, 439, 539, 734, + + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 540, 734, 541, 541, 541, 734, 734, 734, 734, + 734, 734, 541, 734, 734, 541, 734, 734, 541, 541, + 734, 734, 734, 734, 734, 734, 734, 541, 541, 541, + 734, 734, 734, 734, 734, 734, 734, 541, 734, 734, + 541, 734, 734, 541, 473, 473, 734, 473, 473, 473, + 473, 473, 734, 473, 473, 473, 473, 734, 473, 473, + 734, 734, 734, 734, 473, 473, 473, 473, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 473, + + 473, 473, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 473, 473, 473, 473, 734, 473, + 473, 473, 473, 473, 734, 473, 473, 473, 473, 734, + 473, 473, 734, 734, 734, 734, 473, 473, 473, 473, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 473, 473, 473, 734, 734, 734, 734, 475, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 475, 475, 734, 734, 734, 473, 473, 539, 734, + + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 540, 734, 571, 571, 571, 734, 734, 734, 734, + 734, 734, 571, 734, 734, 571, 734, 734, 571, 571, + 734, 734, 734, 734, 734, 734, 734, 571, 571, 571, + 734, 734, 734, 734, 734, 734, 734, 571, 734, 734, + 571, 734, 734, 571, 473, 473, 734, 473, 473, 473, + 473, 473, 474, 473, 473, 473, 473, 734, 473, 473, + 734, 734, 734, 734, 512, 473, 473, 473, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 473, + + 473, 473, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 473, 473, 473, 473, 734, 473, + 473, 473, 473, 473, 474, 473, 473, 473, 473, 734, + 473, 473, 734, 734, 734, 734, 512, 473, 473, 473, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 473, 473, 473, 734, 734, 734, 734, 513, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 513, 513, 734, 734, 734, 473, 473, 640, 640, + + 734, 640, 640, 640, 640, 640, 734, 640, 640, 640, + 640, 734, 640, 640, 734, 734, 734, 734, 640, 640, + 640, 640, 734, 734, 734, 734, 734, 734, 642, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 640, 640, 640, 734, 734, 734, 734, + 734, 734, 642, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 640, 640, + 640, 640, 734, 640, 640, 640, 640, 640, 641, 640, + 640, 640, 640, 734, 640, 640, 734, 734, 734, 734, + 649, 640, 640, 640, 734, 734, 734, 734, 734, 734, + + 650, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 640, 640, 640, 734, 734, + 734, 734, 734, 734, 650, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 640, 640, 640, 640, 734, 640, 640, 640, 640, 640, + 734, 640, 640, 640, 640, 734, 640, 640, 734, 734, + 734, 734, 640, 640, 640, 640, 734, 734, 734, 734, + 734, 734, 642, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 640, 640, 640, + 734, 734, 734, 734, 734, 734, 642, 734, 734, 734, + + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 640, 640, 640, 640, 734, 640, 640, 640, + 640, 640, 641, 640, 640, 640, 640, 734, 640, 640, + 734, 734, 734, 734, 649, 640, 640, 640, 734, 734, + 734, 734, 734, 734, 650, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 640, + 640, 640, 734, 734, 734, 734, 734, 734, 650, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 640, 640, 82, 734, 734, 82, + 82, 734, 734, 82, 82, 82, 82, 82, 83, 83, + + 83, 83, 83, 734, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 154, 734, + 734, 154, 154, 154, 734, 154, 154, 154, 154, 154, + 203, 203, 203, 203, 203, 734, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + + 220, 220, 734, 734, 734, 734, 734, 734, 734, 220, + 220, 220, 220, 220, 228, 228, 228, 232, 232, 232, + 233, 233, 233, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 263, 263, 263, 274, 274, 274, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 285, 285, 285, 285, 285, 285, + 285, 285, 285, 285, 285, 285, 285, 285, 285, 154, + 734, 734, 154, 154, 154, 734, 154, 154, 154, 154, + + 154, 292, 292, 292, 292, 292, 292, 292, 292, 292, + 292, 292, 292, 292, 292, 292, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 341, 341, 734, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 343, 343, 734, 343, 343, 343, 343, 343, 343, + + 343, 343, 343, 343, 343, 343, 358, 358, 358, 381, + 381, 734, 381, 381, 381, 381, 381, 381, 381, 381, + 381, 381, 381, 381, 383, 383, 383, 383, 383, 383, + 383, 383, 383, 383, 383, 383, 383, 383, 383, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 385, 385, 385, 385, 385, 385, + 385, 385, 385, 385, 385, 385, 385, 385, 385, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 389, 389, 389, 393, 734, 734, + 393, 734, 393, 393, 734, 393, 734, 393, 402, 402, + + 402, 285, 285, 285, 285, 285, 285, 285, 285, 285, + 285, 285, 285, 285, 285, 285, 415, 415, 415, 415, + 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, + 415, 154, 734, 734, 154, 154, 154, 734, 154, 154, + 154, 154, 154, 292, 292, 292, 292, 292, 292, 292, + 292, 292, 292, 292, 292, 292, 292, 292, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 435, 435, 734, 435, 435, 435, 435, + 435, 435, 435, 435, 435, 435, 435, 435, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + + 337, 337, 337, 449, 449, 449, 449, 734, 449, 449, + 449, 449, 449, 449, 449, 449, 449, 449, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 341, 341, 734, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 343, 343, + 734, 343, 343, 343, 343, 343, 343, 343, 343, 343, + 343, 343, 343, 459, 734, 459, 734, 734, 734, 459, + 459, 459, 474, 474, 734, 474, 474, 474, 474, 474, + 474, 474, 474, 474, 474, 474, 474, 380, 380, 734, + 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, + + 380, 380, 381, 381, 734, 381, 381, 381, 381, 381, + 381, 381, 381, 381, 381, 381, 381, 383, 383, 383, + 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, + 383, 383, 385, 385, 385, 385, 385, 385, 385, 385, + 385, 385, 385, 385, 385, 385, 385, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 482, 482, 482, 482, 482, 482, 482, 482, + 482, 482, 482, 482, 482, 482, 482, 488, 734, 734, + 734, 734, 488, 488, 734, 488, 734, 488, 415, 415, + 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, + + 415, 415, 415, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 511, 511, + 734, 511, 511, 511, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 435, 435, 734, 435, 435, 435, 435, + 435, 435, 435, 435, 435, 435, 435, 435, 449, 449, + 449, 449, 734, 449, 449, 449, 449, 449, 449, 449, + 449, 449, 449, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 524, 524, + 734, 524, 524, 524, 524, 524, 524, 524, 524, 524, + 524, 524, 524, 526, 526, 734, 526, 526, 526, 526, + + 526, 526, 526, 526, 526, 526, 526, 526, 528, 528, + 734, 528, 528, 528, 528, 528, 528, 528, 528, 528, + 528, 528, 528, 530, 530, 734, 530, 530, 530, 530, + 530, 530, 530, 530, 530, 530, 530, 530, 532, 532, + 734, 532, 532, 532, 532, 532, 532, 532, 532, 532, + 532, 532, 532, 534, 534, 734, 534, 534, 534, 534, + 534, 534, 534, 534, 534, 534, 534, 534, 473, 473, + 734, 473, 473, 473, 473, 473, 473, 473, 473, 473, + 473, 473, 473, 474, 474, 734, 474, 474, 474, 474, + 474, 474, 474, 474, 474, 474, 474, 474, 383, 383, + + 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, + 383, 383, 383, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 482, 482, + 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, + 482, 482, 482, 559, 734, 734, 734, 734, 559, 559, + 734, 559, 567, 567, 567, 567, 567, 567, 567, 567, + 567, 567, 567, 567, 567, 567, 567, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 511, 511, 734, 511, 511, 511, 511, 511, + 511, 511, 511, 511, 511, 511, 511, 578, 578, 578, + + 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, + 578, 578, 585, 734, 734, 734, 734, 585, 585, 734, + 585, 592, 592, 734, 592, 592, 592, 592, 592, 592, + 592, 592, 592, 592, 592, 592, 610, 610, 610, 610, + 610, 610, 610, 610, 610, 610, 610, 610, 610, 610, + 610, 641, 641, 734, 641, 641, 641, 641, 641, 641, + 641, 641, 641, 641, 641, 641, 648, 648, 734, 648, + 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, + 648, 640, 640, 734, 640, 640, 640, 640, 640, 640, + 640, 640, 640, 640, 640, 640, 676, 676, 676, 676, + + 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + 676, 698, 698, 698, 698, 698, 698, 698, 698, 698, + 698, 698, 698, 698, 698, 698, 701, 701, 701, 701, + 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, + 701, 716, 716, 716, 716, 716, 716, 716, 716, 716, + 716, 716, 716, 716, 716, 716, 3, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734 + } ; + +static yyconst short int yy_chk[5130] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 5, 6, 6, 6, 6, 8, + 10, 10, 11, 20, 22, 46, 8, 8, 8, 8, + 16, 732, 11, 13, 11, 11, 20, 46, 5, 11, + 12, 12, 12, 13, 18, 13, 98, 12, 98, 22, + 13, 286, 12, 12, 12, 12, 12, 12, 12, 12, + 286, 20, 52, 12, 12, 12, 12, 12, 12, 12, + + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 42, 18, 16, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 15, + 23, 15, 15, 15, 15, 15, 15, 27, 52, 15, + 23, 31, 54, 31, 31, 712, 47, 43, 31, 50, + 50, 47, 32, 42, 23, 708, 47, 27, 47, 47, + 15, 58, 40, 47, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 24, 32, 32, 32, + 32, 32, 62, 54, 24, 707, 58, 40, 40, 27, + + 27, 158, 57, 32, 62, 149, 27, 40, 40, 43, + 43, 40, 84, 84, 57, 158, 43, 701, 86, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 49, 59, 128, + 62, 28, 28, 28, 28, 33, 57, 49, 59, 49, + 700, 34, 56, 36, 49, 351, 66, 351, 66, 66, + 90, 90, 59, 66, 149, 56, 28, 28, 28, 86, + 33, 33, 128, 33, 33, 33, 34, 34, 36, 36, + 34, 34, 34, 37, 36, 36, 36, 349, 35, 44, + + 56, 28, 28, 29, 161, 29, 29, 29, 29, 29, + 29, 35, 268, 44, 44, 44, 44, 161, 37, 37, + 94, 94, 94, 35, 35, 37, 37, 37, 35, 35, + 35, 163, 163, 39, 29, 416, 35, 416, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 30, 38, 89, 39, 89, 203, 203, 77, 349, 89, + 30, 268, 77, 30, 30, 30, 30, 30, 44, 77, + 76, 81, 81, 81, 81, 698, 38, 38, 39, 39, + 39, 521, 76, 696, 38, 38, 38, 39, 39, 39, + 521, 30, 97, 97, 97, 30, 30, 30, 30, 30, + + 30, 30, 30, 30, 30, 30, 30, 48, 48, 48, + 76, 77, 204, 204, 48, 109, 109, 109, 109, 48, + 48, 48, 48, 48, 48, 48, 48, 205, 205, 372, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 207, 207, 372, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 51, 63, 68, 79, + 154, 51, 251, 51, 51, 51, 51, 51, 51, 694, + 79, 51, 154, 79, 79, 79, 79, 63, 112, 112, + + 112, 112, 156, 68, 68, 688, 68, 68, 68, 253, + 156, 156, 51, 71, 156, 251, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 60, 63, + 63, 69, 394, 72, 112, 60, 63, 687, 71, 71, + 60, 157, 159, 60, 71, 71, 71, 78, 79, 157, + 159, 253, 78, 157, 159, 418, 69, 69, 72, 72, + 69, 69, 69, 67, 78, 72, 72, 72, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 64, 394, 64, 64, 64, 64, 64, 64, 67, 67, + 67, 67, 67, 95, 95, 95, 162, 172, 182, 78, + + 78, 418, 200, 686, 67, 95, 78, 95, 162, 172, + 182, 64, 95, 73, 200, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 65, 111, 111, + 111, 111, 70, 120, 120, 120, 120, 65, 73, 73, + 65, 65, 65, 65, 65, 70, 73, 73, 73, 74, + 200, 182, 117, 117, 117, 117, 172, 70, 70, 171, + 111, 284, 70, 70, 70, 267, 284, 284, 65, 74, + 70, 171, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 75, 123, 123, 123, 123, 682, + 85, 292, 292, 171, 74, 74, 74, 85, 85, 85, + + 85, 85, 117, 74, 74, 74, 201, 267, 679, 75, + 75, 226, 99, 121, 121, 121, 121, 201, 371, 75, + 75, 226, 99, 75, 99, 123, 336, 336, 226, 99, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 106, 337, 337, 124, 124, 124, 124, 106, + 136, 136, 136, 136, 142, 142, 142, 142, 144, 144, + 144, 144, 121, 143, 143, 143, 143, 167, 167, 167, + 167, 383, 373, 106, 569, 201, 371, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 110, + 124, 110, 151, 288, 144, 143, 373, 110, 288, 353, + + 173, 470, 110, 678, 383, 288, 151, 151, 151, 151, + 151, 170, 173, 110, 385, 110, 169, 169, 169, 169, + 384, 673, 110, 170, 569, 470, 110, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 168, 168, 168, 168, 127, 127, 127, + 127, 170, 169, 384, 176, 419, 385, 173, 672, 177, + 353, 151, 174, 174, 174, 174, 176, 177, 177, 177, + 177, 177, 127, 127, 127, 168, 178, 178, 178, 178, + 197, 179, 243, 176, 180, 180, 180, 180, 181, 181, + 181, 181, 197, 179, 671, 243, 243, 127, 127, 129, + + 129, 129, 129, 129, 290, 129, 129, 129, 129, 129, + 129, 198, 174, 129, 129, 419, 290, 398, 188, 129, + 129, 179, 129, 198, 180, 178, 188, 188, 188, 188, + 188, 199, 355, 181, 194, 194, 194, 194, 197, 227, + 227, 227, 227, 199, 129, 129, 355, 674, 196, 502, + 502, 502, 195, 195, 195, 195, 196, 196, 196, 196, + 196, 228, 228, 228, 228, 198, 398, 606, 606, 129, + 129, 131, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 132, 195, 199, 229, 132, 231, 231, + 231, 231, 196, 229, 132, 393, 132, 674, 132, 132, + + 132, 232, 232, 232, 232, 333, 484, 132, 308, 315, + 132, 315, 622, 132, 132, 607, 333, 229, 132, 484, + 308, 315, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 670, 132, 622, 393, 132, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 135, 233, 233, 233, 233, 308, 242, 135, 135, + 135, 135, 208, 208, 135, 647, 135, 135, 135, 208, + 208, 208, 208, 208, 333, 135, 209, 209, 135, 607, + 242, 135, 135, 209, 209, 209, 209, 309, 289, 302, + 135, 135, 135, 289, 135, 239, 239, 239, 239, 309, + + 135, 302, 667, 135, 242, 289, 135, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 138, + 262, 262, 262, 262, 666, 647, 138, 420, 261, 239, + 249, 249, 249, 249, 261, 261, 261, 261, 309, 420, + 294, 252, 252, 252, 252, 240, 240, 240, 240, 302, + 138, 397, 503, 489, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 141, 240, + 249, 141, 141, 141, 141, 141, 252, 263, 269, 269, + 269, 269, 294, 397, 263, 263, 263, 263, 272, 421, + + 263, 294, 489, 467, 272, 272, 272, 272, 617, 141, + 503, 421, 479, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 160, 160, 160, 467, 488, + 263, 664, 160, 273, 273, 273, 273, 160, 160, 357, + 160, 160, 160, 160, 160, 479, 357, 663, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 617, + 357, 488, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 164, 275, 275, 275, 275, 321, + + 321, 321, 321, 485, 274, 278, 164, 278, 278, 278, + 278, 274, 274, 274, 274, 277, 485, 274, 295, 330, + 306, 277, 277, 277, 277, 306, 295, 295, 295, 295, + 295, 330, 306, 659, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 165, 274, 283, 363, + 291, 658, 570, 165, 278, 291, 363, 277, 675, 675, + 298, 330, 283, 283, 283, 283, 304, 291, 298, 298, + 298, 298, 298, 326, 326, 326, 326, 165, 304, 657, + 363, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 183, 183, 183, 183, 183, 183, 183, + + 183, 183, 183, 183, 183, 184, 570, 331, 629, 184, + 304, 656, 331, 430, 305, 486, 184, 283, 184, 331, + 184, 184, 184, 304, 304, 430, 305, 431, 486, 184, + 417, 319, 184, 319, 654, 184, 184, 653, 417, 431, + 184, 645, 417, 319, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 431, 184, 305, 629, + 184, 186, 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 186, 187, 187, 319, 358, 358, 358, 358, + 428, 187, 187, 187, 187, 187, 644, 187, 320, 187, + 187, 187, 428, 660, 320, 498, 504, 498, 187, 441, + + 320, 187, 498, 428, 187, 187, 364, 364, 364, 364, + 300, 441, 432, 187, 187, 187, 332, 187, 300, 300, + 300, 300, 300, 187, 432, 713, 187, 428, 332, 187, + 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 189, 190, 320, 714, 310, 450, 450, 638, 190, + 660, 450, 300, 310, 310, 310, 310, 310, 432, 504, + 301, 389, 389, 389, 389, 447, 715, 636, 301, 301, + 301, 301, 301, 190, 332, 713, 447, 190, 190, 190, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + + 192, 193, 301, 310, 193, 193, 193, 193, 193, 316, + 303, 316, 661, 714, 317, 303, 635, 316, 316, 316, + 316, 316, 317, 317, 317, 317, 317, 303, 386, 386, + 386, 634, 193, 303, 447, 715, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 234, 630, + 324, 458, 324, 628, 646, 234, 325, 303, 324, 324, + 324, 324, 324, 458, 325, 325, 325, 325, 325, 392, + 354, 661, 627, 386, 354, 402, 402, 402, 402, 234, + 626, 354, 392, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 250, 250, 709, 250, 250, + + 250, 250, 250, 630, 250, 250, 250, 250, 646, 250, + 250, 328, 392, 328, 395, 250, 250, 250, 250, 328, + 328, 328, 328, 328, 329, 624, 495, 395, 623, 689, + 329, 354, 329, 329, 329, 329, 329, 340, 340, 495, + 250, 250, 250, 404, 340, 340, 340, 340, 407, 446, + 407, 407, 407, 407, 709, 328, 404, 395, 621, 538, + 250, 446, 568, 568, 568, 250, 250, 254, 254, 254, + 254, 254, 538, 254, 254, 254, 254, 254, 254, 329, + 689, 254, 254, 425, 409, 406, 404, 254, 254, 716, + 254, 406, 406, 406, 406, 425, 426, 407, 409, 409, + + 409, 409, 427, 446, 411, 412, 433, 427, 426, 767, + 639, 767, 254, 254, 411, 412, 411, 412, 433, 427, + 424, 411, 412, 434, 439, 619, 439, 406, 424, 424, + 424, 424, 424, 425, 639, 434, 439, 254, 254, 255, + 459, 459, 459, 459, 618, 510, 426, 480, 480, 480, + 433, 616, 255, 409, 255, 255, 255, 510, 716, 440, + 427, 615, 610, 255, 515, 440, 255, 434, 439, 255, + 255, 440, 483, 483, 483, 444, 515, 444, 255, 255, + 255, 468, 255, 444, 444, 444, 444, 444, 255, 510, + 605, 255, 480, 604, 255, 257, 257, 257, 257, 257, + + 257, 257, 257, 257, 257, 257, 257, 265, 506, 557, + 557, 557, 468, 506, 440, 496, 515, 483, 519, 444, + 265, 468, 265, 265, 265, 506, 602, 496, 507, 640, + 519, 265, 731, 445, 265, 600, 468, 265, 265, 445, + 507, 445, 445, 445, 445, 445, 265, 265, 265, 514, + 265, 599, 598, 640, 557, 507, 265, 597, 770, 265, + 770, 514, 265, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 276, 508, 509, 516, 520, + 507, 508, 276, 516, 496, 539, 540, 544, 445, 509, + 520, 612, 518, 508, 518, 516, 554, 509, 539, 540, + + 544, 731, 514, 612, 518, 642, 276, 596, 595, 554, + 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, + 276, 276, 296, 523, 523, 563, 571, 594, 571, 642, + 523, 523, 523, 523, 296, 572, 593, 577, 571, 563, + 563, 563, 563, 573, 574, 576, 592, 572, 520, 577, + 591, 582, 582, 703, 589, 573, 574, 576, 582, 582, + 582, 582, 296, 296, 296, 296, 296, 296, 296, 296, + 296, 296, 296, 296, 299, 572, 573, 577, 620, 579, + 611, 299, 603, 609, 650, 588, 587, 585, 613, 576, + 579, 620, 611, 614, 563, 609, 603, 603, 603, 603, + + 613, 574, 576, 584, 614, 299, 583, 703, 650, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 311, 311, 611, 311, 311, 311, 311, 311, 311, + 311, 311, 311, 311, 633, 311, 311, 608, 632, 581, + 609, 311, 311, 311, 311, 633, 613, 649, 579, 608, + 632, 603, 651, 655, 652, 668, 662, 669, 665, 655, + 668, 676, 614, 681, 651, 652, 311, 311, 311, 665, + 608, 683, 697, 683, 649, 578, 681, 655, 684, 668, + 575, 669, 632, 655, 662, 567, 311, 669, 566, 676, + 565, 311, 311, 312, 312, 680, 697, 683, 649, 564, + + 684, 693, 684, 633, 706, 312, 680, 312, 662, 312, + 312, 312, 693, 676, 690, 706, 691, 677, 312, 711, + 562, 312, 559, 652, 312, 312, 555, 665, 553, 552, + 711, 551, 550, 312, 312, 312, 549, 312, 548, 677, + 547, 546, 690, 312, 691, 677, 312, 690, 705, 312, + 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, + 313, 313, 318, 677, 680, 545, 690, 543, 691, 677, + 693, 717, 718, 706, 691, 318, 705, 318, 318, 318, + 704, 710, 717, 718, 719, 720, 318, 542, 711, 318, + 541, 537, 318, 318, 536, 719, 720, 535, 705, 534, + + 705, 318, 318, 318, 533, 318, 704, 532, 704, 710, + 531, 318, 530, 529, 318, 528, 527, 318, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + 327, 526, 704, 710, 525, 524, 721, 327, 722, 723, + 717, 718, 517, 512, 724, 725, 726, 721, 727, 722, + 723, 728, 729, 719, 720, 724, 725, 726, 501, 727, + 500, 327, 728, 729, 499, 327, 327, 327, 327, 327, + 327, 327, 327, 327, 327, 327, 327, 362, 362, 362, + 362, 362, 362, 362, 362, 362, 362, 362, 362, 374, + 374, 497, 374, 374, 374, 374, 374, 494, 374, 374, + + 374, 374, 492, 374, 374, 721, 491, 722, 723, 374, + 374, 374, 374, 724, 725, 726, 730, 727, 487, 482, + 728, 729, 478, 477, 476, 472, 471, 730, 469, 466, + 465, 464, 463, 462, 374, 374, 374, 457, 456, 455, + 454, 374, 453, 452, 451, 449, 448, 436, 423, 415, + 414, 413, 410, 408, 374, 374, 400, 399, 396, 374, + 374, 381, 381, 388, 381, 381, 381, 381, 381, 387, + 381, 381, 381, 381, 379, 381, 381, 378, 377, 376, + 370, 381, 381, 381, 381, 730, 369, 368, 367, 366, + 365, 352, 350, 348, 347, 346, 345, 344, 343, 342, + + 341, 338, 334, 323, 314, 297, 381, 381, 381, 293, + 287, 285, 281, 280, 279, 266, 260, 259, 248, 247, + 245, 244, 241, 238, 237, 236, 235, 225, 224, 223, + 222, 381, 381, 382, 382, 221, 382, 382, 382, 382, + 382, 218, 382, 382, 382, 382, 217, 382, 382, 216, + 215, 214, 213, 382, 382, 382, 382, 211, 210, 206, + 202, 191, 185, 175, 166, 155, 153, 152, 150, 148, + 147, 146, 145, 126, 125, 122, 119, 118, 382, 382, + 382, 116, 115, 114, 113, 102, 100, 96, 93, 92, + 91, 88, 83, 80, 61, 55, 53, 45, 41, 26, + + 25, 21, 19, 382, 382, 391, 17, 14, 9, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 391, 0, + 391, 391, 391, 0, 0, 0, 0, 0, 0, 391, + 0, 0, 391, 0, 0, 391, 391, 0, 0, 0, + 0, 0, 0, 0, 391, 391, 391, 0, 0, 0, + 0, 0, 0, 0, 391, 0, 0, 391, 0, 0, + 391, 405, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 405, 0, 405, 405, 405, 0, + 0, 0, 0, 0, 0, 405, 0, 0, 405, 0, + 0, 405, 405, 0, 0, 0, 0, 0, 0, 0, + + 405, 405, 405, 0, 405, 0, 0, 0, 0, 0, + 405, 0, 0, 405, 0, 0, 405, 422, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 422, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 422, 422, 422, + 422, 422, 422, 422, 422, 422, 422, 422, 422, 429, + 429, 0, 429, 429, 429, 429, 429, 429, 429, 429, + 429, 429, 0, 429, 429, 0, 0, 0, 0, 429, + 429, 429, 429, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 429, 429, 429, 0, 0, 0, + 0, 429, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 429, 429, 0, 0, 0, 429, + 429, 435, 435, 0, 435, 435, 435, 435, 435, 435, + 435, 435, 435, 435, 0, 435, 435, 0, 0, 0, + 0, 435, 435, 435, 435, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 435, 435, 435, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 435, 435, 437, 437, 0, 437, 437, 437, 437, + 437, 437, 437, 437, 437, 437, 0, 437, 437, 0, + 0, 0, 0, 437, 437, 437, 437, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 437, 437, + 437, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 437, 437, 438, 438, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 438, 0, 438, + + 0, 438, 438, 438, 0, 0, 0, 0, 0, 0, + 438, 0, 0, 438, 0, 0, 438, 438, 0, 0, + 0, 0, 0, 0, 0, 438, 438, 438, 0, 0, + 0, 0, 0, 0, 0, 438, 0, 0, 438, 0, + 0, 438, 443, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 443, 0, 443, 443, 443, + 0, 0, 0, 0, 0, 0, 443, 0, 0, 443, + 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, + 0, 443, 443, 443, 0, 443, 0, 0, 0, 0, + 0, 443, 0, 0, 443, 0, 0, 443, 461, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 461, 0, 461, 461, 461, 0, 0, 0, 0, + 0, 0, 461, 0, 0, 461, 0, 0, 461, 461, + 0, 0, 0, 0, 0, 0, 0, 461, 461, 461, + 0, 0, 0, 0, 0, 0, 0, 461, 0, 0, + 461, 0, 0, 461, 474, 474, 0, 474, 474, 474, + 474, 474, 0, 474, 474, 474, 474, 0, 474, 474, + 0, 0, 0, 0, 474, 474, 474, 474, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 474, + + 474, 474, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 474, 474, 475, 475, 0, 475, + 475, 475, 475, 475, 0, 475, 475, 475, 475, 0, + 475, 475, 0, 0, 0, 0, 475, 475, 475, 475, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 475, 475, 475, 0, 0, 0, 0, 475, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 475, 475, 0, 0, 0, 475, 475, 505, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 505, 0, 505, 505, 505, 0, 0, 0, 0, + 0, 0, 505, 0, 0, 505, 0, 0, 505, 505, + 0, 0, 0, 0, 0, 0, 0, 505, 505, 505, + 0, 0, 0, 0, 0, 0, 0, 505, 0, 0, + 505, 0, 0, 505, 511, 511, 0, 511, 511, 511, + 511, 511, 511, 511, 511, 511, 511, 0, 511, 511, + 0, 0, 0, 0, 511, 511, 511, 511, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 511, + + 511, 511, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 511, 511, 513, 513, 0, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 0, + 513, 513, 0, 0, 0, 0, 513, 513, 513, 513, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 513, 513, 513, 0, 0, 0, 0, 513, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 513, 513, 0, 0, 0, 513, 513, 625, 625, + + 0, 625, 625, 625, 625, 625, 0, 625, 625, 625, + 625, 0, 625, 625, 0, 0, 0, 0, 625, 625, + 625, 625, 0, 0, 0, 0, 0, 0, 625, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 625, 625, 625, 0, 0, 0, 0, + 0, 0, 625, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 625, 625, + 631, 631, 0, 631, 631, 631, 631, 631, 631, 631, + 631, 631, 631, 0, 631, 631, 0, 0, 0, 0, + 631, 631, 631, 631, 0, 0, 0, 0, 0, 0, + + 631, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 631, 631, 631, 0, 0, + 0, 0, 0, 0, 631, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 631, 631, 641, 641, 0, 641, 641, 641, 641, 641, + 0, 641, 641, 641, 641, 0, 641, 641, 0, 0, + 0, 0, 641, 641, 641, 641, 0, 0, 0, 0, + 0, 0, 641, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 641, 641, 641, + 0, 0, 0, 0, 0, 0, 641, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 641, 641, 648, 648, 0, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 0, 648, 648, + 0, 0, 0, 0, 648, 648, 648, 648, 0, 0, + 0, 0, 0, 0, 648, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 648, + 648, 648, 0, 0, 0, 0, 0, 0, 648, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 648, 648, 735, 0, 0, 735, + 735, 0, 0, 735, 735, 735, 735, 735, 736, 736, + + 736, 736, 736, 0, 736, 736, 736, 736, 736, 736, + 736, 736, 736, 737, 737, 737, 737, 737, 737, 737, + 737, 737, 737, 737, 737, 737, 737, 737, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 738, 738, 738, + 738, 738, 738, 739, 739, 739, 739, 739, 739, 739, + 739, 739, 739, 739, 739, 739, 739, 739, 740, 0, + 0, 740, 740, 740, 0, 740, 740, 740, 740, 740, + 741, 741, 741, 741, 741, 0, 741, 741, 741, 741, + 741, 741, 741, 741, 741, 742, 742, 742, 742, 742, + 742, 742, 742, 742, 742, 742, 742, 742, 742, 742, + + 743, 743, 0, 0, 0, 0, 0, 0, 0, 743, + 743, 743, 743, 743, 744, 744, 744, 745, 745, 745, + 746, 746, 746, 747, 747, 747, 747, 747, 747, 747, + 747, 747, 747, 747, 747, 747, 747, 747, 748, 748, + 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, + 748, 748, 748, 749, 749, 749, 750, 750, 750, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 751, 751, 752, 752, 752, 752, 752, 752, + 752, 752, 752, 752, 752, 752, 752, 752, 752, 753, + 0, 0, 753, 753, 753, 0, 753, 753, 753, 753, + + 753, 754, 754, 754, 754, 754, 754, 754, 754, 754, + 754, 754, 754, 754, 754, 754, 755, 755, 755, 755, + 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, + 755, 756, 756, 756, 756, 756, 756, 756, 756, 756, + 756, 756, 756, 756, 756, 756, 757, 757, 757, 757, + 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, + 757, 758, 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 759, 759, 0, 759, + 759, 759, 759, 759, 759, 759, 759, 759, 759, 759, + 759, 760, 760, 0, 760, 760, 760, 760, 760, 760, + + 760, 760, 760, 760, 760, 760, 761, 761, 761, 762, + 762, 0, 762, 762, 762, 762, 762, 762, 762, 762, + 762, 762, 762, 762, 763, 763, 763, 763, 763, 763, + 763, 763, 763, 763, 763, 763, 763, 763, 763, 764, + 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, 765, 766, + 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, + 766, 766, 766, 766, 768, 768, 768, 769, 0, 0, + 769, 0, 769, 769, 0, 769, 0, 769, 771, 771, + + 771, 772, 772, 772, 772, 772, 772, 772, 772, 772, + 772, 772, 772, 772, 772, 772, 773, 773, 773, 773, + 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, + 773, 774, 0, 0, 774, 774, 774, 0, 774, 774, + 774, 774, 774, 775, 775, 775, 775, 775, 775, 775, + 775, 775, 775, 775, 775, 775, 775, 775, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 777, 777, 0, 777, 777, 777, 777, + 777, 777, 777, 777, 777, 777, 777, 777, 778, 778, + 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, + + 778, 778, 778, 779, 779, 779, 779, 0, 779, 779, + 779, 779, 779, 779, 779, 779, 779, 779, 780, 780, + 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, + 780, 780, 780, 781, 781, 0, 781, 781, 781, 781, + 781, 781, 781, 781, 781, 781, 781, 781, 782, 782, + 0, 782, 782, 782, 782, 782, 782, 782, 782, 782, + 782, 782, 782, 783, 0, 783, 0, 0, 0, 783, + 783, 783, 784, 784, 0, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 785, 785, 0, + 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, + + 785, 785, 786, 786, 0, 786, 786, 786, 786, 786, + 786, 786, 786, 786, 786, 786, 786, 787, 787, 787, + 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, + 787, 787, 788, 788, 788, 788, 788, 788, 788, 788, + 788, 788, 788, 788, 788, 788, 788, 789, 789, 789, + 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, + 789, 789, 790, 790, 790, 790, 790, 790, 790, 790, + 790, 790, 790, 790, 790, 790, 790, 791, 0, 0, + 0, 0, 791, 791, 0, 791, 0, 791, 792, 792, + 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, + + 792, 792, 792, 793, 793, 793, 793, 793, 793, 793, + 793, 793, 793, 793, 793, 793, 793, 793, 794, 794, + 0, 794, 794, 794, 794, 794, 794, 794, 794, 794, + 794, 794, 794, 795, 795, 0, 795, 795, 795, 795, + 795, 795, 795, 795, 795, 795, 795, 795, 796, 796, + 796, 796, 0, 796, 796, 796, 796, 796, 796, 796, + 796, 796, 796, 797, 797, 797, 797, 797, 797, 797, + 797, 797, 797, 797, 797, 797, 797, 797, 798, 798, + 0, 798, 798, 798, 798, 798, 798, 798, 798, 798, + 798, 798, 798, 799, 799, 0, 799, 799, 799, 799, + + 799, 799, 799, 799, 799, 799, 799, 799, 800, 800, + 0, 800, 800, 800, 800, 800, 800, 800, 800, 800, + 800, 800, 800, 801, 801, 0, 801, 801, 801, 801, + 801, 801, 801, 801, 801, 801, 801, 801, 802, 802, + 0, 802, 802, 802, 802, 802, 802, 802, 802, 802, + 802, 802, 802, 803, 803, 0, 803, 803, 803, 803, + 803, 803, 803, 803, 803, 803, 803, 803, 804, 804, + 0, 804, 804, 804, 804, 804, 804, 804, 804, 804, + 804, 804, 804, 805, 805, 0, 805, 805, 805, 805, + 805, 805, 805, 805, 805, 805, 805, 805, 806, 806, + + 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, + 806, 806, 806, 807, 807, 807, 807, 807, 807, 807, + 807, 807, 807, 807, 807, 807, 807, 807, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 809, 0, 0, 0, 0, 809, 809, + 0, 809, 810, 810, 810, 810, 810, 810, 810, 810, + 810, 810, 810, 810, 810, 810, 810, 811, 811, 811, + 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, + 811, 811, 812, 812, 0, 812, 812, 812, 812, 812, + 812, 812, 812, 812, 812, 812, 812, 813, 813, 813, + + 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, + 813, 813, 814, 0, 0, 0, 0, 814, 814, 0, + 814, 815, 815, 0, 815, 815, 815, 815, 815, 815, + 815, 815, 815, 815, 815, 815, 816, 816, 816, 816, + 816, 816, 816, 816, 816, 816, 816, 816, 816, 816, + 816, 817, 817, 0, 817, 817, 817, 817, 817, 817, + 817, 817, 817, 817, 817, 817, 818, 818, 0, 818, + 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, + 818, 819, 819, 0, 819, 819, 819, 819, 819, 819, + 819, 819, 819, 819, 819, 819, 820, 820, 820, 820, + + 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, + 820, 821, 821, 821, 821, 821, 821, 821, 821, 821, + 821, 821, 821, 821, 821, 821, 822, 822, 822, 822, + 822, 822, 822, 822, 822, 822, 822, 822, 822, 822, + 822, 823, 823, 823, 823, 823, 823, 823, 823, 823, + 823, 823, 823, 823, 823, 823, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734 + } ; + +static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr; +static char *yy_full_match; +static int yy_lp; +static int yy_looking_for_trail_begin = 0; +static int yy_full_lp; +static int *yy_full_state; +#define YY_TRAILING_MASK 0x2000 +#define YY_TRAILING_HEAD_MASK 0x4000 +#define REJECT \ +{ \ +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \ +yy_cp = yy_full_match; /* restore poss. backed-over text */ \ +yy_lp = yy_full_lp; /* restore orig. accepting pos. */ \ +yy_state_ptr = yy_full_state; /* restore orig. state */ \ +yy_current_state = *yy_state_ptr; /* restore curr. state */ \ +++yy_lp; \ +goto find_rule; \ +} +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#define INITIAL 0 +/* + * parser.l -- lex parser of algebraic chess moves for XBoard + * $Id: parser.l,v 2.1 2003/10/27 19:21:00 mann Exp $ + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. + * Enhancements Copyright 1992-95 Free Software Foundation, Inc. + * + * The following terms apply to Digital Equipment Corporation's copyright + * interest in XBoard: + * ------------------------------------------------------------------------ + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Digital not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * ------------------------------------------------------------------------ + * + * The following terms apply to the enhanced version of XBoard distributed + * by the Free Software Foundation: + * ------------------------------------------------------------------------ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------ + */ + +/* This parser handles all forms of promotion. + * The parser resolves ambiguous moves by searching and check-testing. + * It also parses comments of the form [anything] or (anything). + */ + +#include "config.h" + +#define NO_CONSTRAINT -1 +#undef YYLMAX +#define YYLMAX 4096 +#define UNPUT_BUF_SIZE YYLMAX + +#ifdef FLEX_SCANNER +/* yytext is probably a char*, but could be a char[]. yy_text is set + in YY_DECL below, because if yytext is a char*, its value is not + constant. */ +char *yy_text; +#else /*!FLEX_SCANNER*/ +/* yytext is definitely a char[], so yy_text can be set here, statically. */ +char *yy_text = (char *) yytext; +#endif + +#ifdef FLEX_SCANNER +/* This is flex */ +#undef YY_INPUT +#define YY_INPUT(buf, result, max_size) my_yy_input(buf, &result, max_size) +#undef YY_DECL +#define YY_DECL \ + int _yylex YY_PROTO((void)); \ + int yylex YY_PROTO((void)) \ + { \ + int result = _yylex(); \ + yy_text = (char *) yytext; \ + return(result); \ + } \ + int _yylex YY_PROTO((void)) +#else +/* This is lex */ +#undef input +#undef output +#undef unput +#endif + +/* The includes must be here, below the #undef input */ + +#include + +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#if HAVE_UNISTD_H +# include +#endif + +#if defined(_amigados) +# include +# if HAVE_FCNTL_H +# include /* isatty() prototype */ +# endif /* HAVE_FCNTL_H */ +#endif /* defined(_amigados) */ + +#include "common.h" +#include "backend.h" +#include "frontend.h" +#include "parser.h" +#include "moves.h" + +extern int PosFlags P((int)); + +extern Board boards[MAX_MOVES]; +int yyboardindex; +int yyskipmoves = FALSE; +char currentMoveString[YYLMAX]; +#ifndef FLEX_SCANNER +char unputBuffer[UNPUT_BUF_SIZE]; +int unputCount = 0; +#endif + +#ifdef FLEX_SCANNER +void my_yy_input P((char *buf, int *result, int max_size)); +#else /*!FLEX_SCANNER*/ +static int input P((void)); +static void output P((int ch)); +static void unput P((int ch)); +int yylook P((void)); +int yyback P((int *, int)); +#endif +#undef yywrap +int yywrap P((void)); +extern void CopyBoard P((Board to, Board from)); + + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + } +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + if ( yyleng > 0 ) \ + yy_current_buffer->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + + + + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); + yy_state_ptr = yy_state_buf; + *yy_state_ptr++ = yy_current_state; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 735 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + *yy_state_ptr++ = yy_current_state; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 5057 ); + +yy_find_action: + yy_current_state = *--yy_state_ptr; + yy_lp = yy_accept[yy_current_state]; +find_rule: /* we branch to this label when backing up */ + for ( ; ; ) /* until we find what rule we matched */ + { + if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] ) + { + yy_act = yy_acclist[yy_lp]; + if ( yy_act & YY_TRAILING_HEAD_MASK || + yy_looking_for_trail_begin ) + { + if ( yy_act == yy_looking_for_trail_begin ) + { + yy_looking_for_trail_begin = 0; + yy_act &= ~YY_TRAILING_HEAD_MASK; + break; + } + } + else if ( yy_act & YY_TRAILING_MASK ) + { + yy_looking_for_trail_begin = yy_act & ~YY_TRAILING_MASK; + yy_looking_for_trail_begin |= YY_TRAILING_HEAD_MASK; + } + else + { + yy_full_match = yy_cp; + yy_full_state = yy_state_ptr; + yy_full_lp = yy_lp; + break; + } + ++yy_lp; + goto find_rule; + } + --yy_cp; + yy_current_state = *--yy_state_ptr; + yy_lp = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +YY_RULE_SETUP +{ + /* + * Fully-qualified algebraic move, possibly with promotion + * [HGM] Bigger-than-8x8 boards must rely on long algebraic formats + * where I allowed piece types A & C (also as promotions) + * files a-l and ranks 0-9 + */ + int skip1 = 0, skip2 = 0; + ChessSquare piece; + ChessMove result; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove the / */ + if (yytext[1] == '/') skip1 = 1; + + /* remove the [xX:-] */ + if ((yytext[3+skip1] == 'x') || (yytext[3+skip1] == 'X') || + (yytext[3+skip1] == '-') || (yytext[3+skip1] == ':')) skip2 = 1; + + currentMoveString[0] = yytext[1+skip1]; + currentMoveString[1] = yytext[2+skip1]; + currentMoveString[2] = yytext[3+skip1+skip2]; + currentMoveString[3] = yytext[4+skip1+skip2]; + currentMoveString[4] = NULLCHAR; + + if (yyleng-skip1-skip2 > 5) { + if (yytext[yyleng-1] == ')') { + currentMoveString[4] = ToLower(yytext[yyleng-2]); + } else { + currentMoveString[4] = ToLower(yytext[yyleng-1]); + } + currentMoveString[5] = NULLCHAR; + } + + if (appData.debugMode) { + fprintf(debugFP, "parser: %s\n", currentMoveString); + } + /* [HGM] do not allow values beyond board size */ + if(currentMoveString[1] - ONE >= BOARD_HEIGHT || + currentMoveString[0] - AAA >= BOARD_WIDTH || + currentMoveString[3] - ONE >= BOARD_HEIGHT || + currentMoveString[2] - AAA >= BOARD_WIDTH ) + return 0; + + piece = boards[yyboardindex] + [currentMoveString[1] - ONE][currentMoveString[0] - AAA]; + if (ToLower(yytext[0]) != ToLower(PieceToChar(piece))) + return (int) IllegalMove; + + result = LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + initialRights, /* [HGM] assume all castlings allowed */ + currentMoveString[1] - ONE, + currentMoveString[0] - AAA, + currentMoveString[3] - ONE, + currentMoveString[2] - AAA, + currentMoveString[4]); + + if (currentMoveString[4] == NULLCHAR && + (result == WhitePromotionQueen || result == BlackPromotionQueen)) { + currentMoveString[4] = 'q'; + currentMoveString[5] = NULLCHAR; + } + + return (int) result; +} + YY_BREAK +case 2: +YY_RULE_SETUP +{ + /* + * Simple algebraic move, possibly with promotion + * [HGM] Bigger-than-8x8 boards must rely on this format + * where I allowed piece types A & C (also as promotions) + * files a-l and ranks 0-9 + */ + int skip = 0; + ChessMove result; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove the [xX:-] */ + if ((yytext[2] == 'x') || (yytext[2] == 'X') || + (yytext[2] == '-') || (yytext[2] == ':')) skip = 1; + + currentMoveString[0] = yytext[0]; + currentMoveString[1] = yytext[1]; + currentMoveString[2] = yytext[2+skip]; + currentMoveString[3] = yytext[3+skip]; + currentMoveString[4] = NULLCHAR; + + if (yyleng-skip > 4) { + if (yytext[yyleng-1] == ')') { + currentMoveString[4] = ToLower(yytext[yyleng-2]); + } else { + currentMoveString[4] = ToLower(yytext[yyleng-1]); + } + currentMoveString[5] = NULLCHAR; + } + + /* [HGM] do not allow values beyond board size */ + if(currentMoveString[1] - ONE >= BOARD_HEIGHT || + currentMoveString[0] - AAA >= BOARD_WIDTH || + currentMoveString[3] - ONE >= BOARD_HEIGHT || + currentMoveString[2] - AAA >= BOARD_WIDTH ) + return 0; + + result = LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + initialRights, /* [HGM] assume all castlings allowed */ + currentMoveString[1] - ONE, + currentMoveString[0] - AAA, + currentMoveString[3] - ONE, + currentMoveString[2] - AAA, + currentMoveString[4]); + + if (currentMoveString[4] == NULLCHAR && + (result == WhitePromotionQueen || result == BlackPromotionQueen)) { + currentMoveString[4] = 'q'; + currentMoveString[5] = NULLCHAR; + } + + return (int) result; +} + YY_BREAK +case 3: +YY_RULE_SETUP +{ + /* + * Pawn move, possibly with promotion + */ + DisambiguateClosure cl; + int skip = 0; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove the =() */ + if (yytext[2] == '=') skip++; + if (yytext[2+skip] == '(') skip++; + + cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn; + cl.rfIn = -1; + cl.ffIn = yytext[0] - AAA; + cl.rtIn = yytext[1] - ONE; + cl.ftIn = yytext[0] - AAA; + cl.promoCharIn = yytext[2+skip]; + + /* [HGM] do not allow values beyond board size */ + if(cl.rtIn >= BOARD_HEIGHT || + cl.ffIn >= BOARD_WIDTH || + cl.ftIn >= BOARD_WIDTH ) + return 0; + + + Disambiguate(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, &cl); + + currentMoveString[0] = cl.ff + AAA; + currentMoveString[1] = cl.rf + ONE; + currentMoveString[2] = cl.ft + AAA; + currentMoveString[3] = cl.rt + ONE; + currentMoveString[4] = cl.promoChar; + currentMoveString[5] = NULLCHAR; + + return (int) cl.kind; +} + YY_BREAK +case 4: +YY_RULE_SETUP +{ + /* + * Pawn capture, possibly with promotion, possibly ambiguous + */ + DisambiguateClosure cl; + int skip1 = 0, skip2 = 0; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove trailing ep or e.p. (nonstandard PGN) */ + if (yytext[yyleng-1] == 'p') { + yyleng -= 2; + yytext[yyleng] = NULLCHAR; + } else if (yytext[yyleng-1] == '.') { + yyleng -= 4; + yytext[yyleng] = NULLCHAR; + } + + /* remove the [xX:-] and =() */ + if ((yytext[1] == 'x') || (yytext[1] == 'X') + || (yytext[1] == ':') || (yytext[1] == '-')) skip1 = 1; + if (yytext[2+skip1] == '=') skip2++; + if (yytext[2+skip1+skip2] == '(') skip2++; + + cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn; + cl.rfIn = -1; + cl.ffIn = yytext[0] - AAA; + cl.rtIn = -1; + cl.ftIn = yytext[1+skip1] - AAA; + cl.promoCharIn = yytext[2+skip1+skip2]; + + /* [HGM] do not allow values beyond board size */ + if(cl.ffIn >= BOARD_WIDTH || + cl.ftIn >= BOARD_WIDTH ) + return 0; + + Disambiguate(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, &cl); + + currentMoveString[0] = cl.ff + AAA; + currentMoveString[1] = cl.rf + ONE; + currentMoveString[2] = cl.ft + AAA; + currentMoveString[3] = cl.rt + ONE; + currentMoveString[4] = cl.promoChar; + currentMoveString[5] = NULLCHAR; + + return (int) cl.kind; +} + YY_BREAK +case 5: +YY_RULE_SETUP +{ + /* + * unambiguously abbreviated Pawn capture, possibly with promotion + */ + int skip = 0; + ChessMove result; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove trailing ep or e.p. (nonstandard PGN) */ + if (yytext[yyleng-1] == 'p') { + yyleng -= 2; + yytext[yyleng] = NULLCHAR; + } else if (yytext[yyleng-1] == '.') { + yyleng -= 4; + yytext[yyleng] = NULLCHAR; + } + + /* remove the [xX:-] */ + if ((yytext[1] == 'x') || (yytext[1] == 'X') + || (yytext[1] == ':') || (yytext[1] == '-')) skip = 1; + + currentMoveString[0] = yytext[0]; + currentMoveString[2] = yytext[1+skip]; + currentMoveString[3] = yytext[2+skip]; + + /* [HGM] do not allow values beyond board size */ + if(currentMoveString[0] - AAA >= BOARD_WIDTH || + currentMoveString[3] - ONE >= BOARD_HEIGHT || + currentMoveString[2] - AAA >= BOARD_WIDTH ) + return 0; + + if (gameInfo.variant == VariantXiangqi && /* [HGM] In Xiangqi rank stays same */ + currentMoveString[0] != currentMoveString[2] ) { + if (yytext[2+skip] == ONE) return (int) ImpossibleMove; + currentMoveString[1] = yytext[2+skip]; + } else + if (WhiteOnMove(yyboardindex)) { + if (yytext[2+skip] == ONE) return (int) ImpossibleMove; + currentMoveString[1] = yytext[2+skip] - 1; + } else { + currentMoveString[1] = currentMoveString[3] + 1; + if (currentMoveString[3] == ONE+BOARD_HEIGHT-1) return (int) ImpossibleMove; + } + if (yyleng-skip > 3) { + if (yytext[yyleng-1] == ')') + currentMoveString[4] = ToLower(yytext[yyleng-2]); + else + currentMoveString[4] = ToLower(yytext[yyleng-1]); + currentMoveString[5] = NULLCHAR; + } else { + currentMoveString[4] = NULLCHAR; + } + + result = LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + initialRights, /* [HGM] assume all castlings allowed */ + currentMoveString[1] - ONE, + currentMoveString[0] - AAA, + currentMoveString[3] - ONE, + currentMoveString[2] - AAA, + currentMoveString[4]); + + if (currentMoveString[4] == NULLCHAR && + (result == WhitePromotionQueen || result == BlackPromotionQueen)) { + currentMoveString[4] = 'q'; + currentMoveString[5] = NULLCHAR; + } + + if (result != IllegalMove) return (int) result; + + /* Special case: improperly written en passant capture */ + if (WhiteOnMove(yyboardindex)) { + if (currentMoveString[3] == '5') { + currentMoveString[1] = '5'; + currentMoveString[3] = '6'; + } else { + return (int) IllegalMove; + } + } else { + if (currentMoveString[3] == '4') { + currentMoveString[1] = '4'; + currentMoveString[3] = '3'; + } else { + return (int) IllegalMove; + } + } + + result = LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + initialRights, /* [HGM] assume all castlings allowed */ + currentMoveString[1] - ONE, + currentMoveString[0] - AAA, + currentMoveString[3] - ONE, + currentMoveString[2] - AAA, + currentMoveString[4]); + + if (result == WhiteCapturesEnPassant || result == BlackCapturesEnPassant) + return (int) result; + else + return (int) IllegalMove; +} + YY_BREAK +case 6: +YY_RULE_SETUP +{ + /* + * piece move, possibly ambiguous + */ + DisambiguateClosure cl; + int skip = 0; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove the [xX:-] */ + if ((yytext[1] == 'x') || (yytext[1] == 'X') + || (yytext[1] == ':') || (yytext[1] == '-')) skip = 1; + + if (WhiteOnMove(yyboardindex)) { + cl.pieceIn = CharToPiece(ToUpper(yytext[0])); + } else { + cl.pieceIn = CharToPiece(ToLower(yytext[0])); + } + cl.rfIn = -1; + cl.ffIn = -1; + cl.rtIn = yytext[2+skip] - ONE; + cl.ftIn = yytext[1+skip] - AAA; + cl.promoCharIn = NULLCHAR; + + /* [HGM] but do not allow values beyond board size */ + if(cl.rtIn >= BOARD_HEIGHT || + cl.ftIn >= BOARD_WIDTH ) + return 0; + + Disambiguate(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, &cl); + + currentMoveString[0] = cl.ff + AAA; + currentMoveString[1] = cl.rf + ONE; + currentMoveString[2] = cl.ft + AAA; + currentMoveString[3] = cl.rt + ONE; + currentMoveString[4] = cl.promoChar; + currentMoveString[5] = NULLCHAR; + + return (int) cl.kind; +} + YY_BREAK +case 7: +YY_RULE_SETUP +{ + /* + * piece move with rank or file disambiguator + */ + DisambiguateClosure cl; + int skip = 0; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* remove the [xX:-] */ + if ((yytext[2] == 'x') || (yytext[2] == 'X') + || (yytext[2] == ':') || (yytext[2] == '-')) skip = 1; + + if (WhiteOnMove(yyboardindex)) { + cl.pieceIn = CharToPiece(ToUpper(yytext[0])); + } else { + cl.pieceIn = CharToPiece(ToLower(yytext[0])); + } + if (isalpha(yytext[1])) { + cl.rfIn = -1; + cl.ffIn = yytext[1] - AAA; + } else { + cl.rfIn = yytext[1] - ONE; + cl.ffIn = -1; + } + cl.rtIn = yytext[3+skip] - ONE; + cl.ftIn = yytext[2+skip] - AAA; + cl.promoCharIn = NULLCHAR; + + /* [HGM] do not allow values beyond board size */ + if(cl.rtIn >= BOARD_HEIGHT || + cl.rfIn >= BOARD_HEIGHT || + cl.ffIn >= BOARD_WIDTH || + cl.ftIn >= BOARD_WIDTH ) + return 0; + + Disambiguate(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, &cl); + + currentMoveString[0] = cl.ff + AAA; + currentMoveString[1] = cl.rf + ONE; + currentMoveString[2] = cl.ft + AAA; + currentMoveString[3] = cl.rt + ONE; + currentMoveString[4] = cl.promoChar; + currentMoveString[5] = NULLCHAR; + + return (int) cl.kind; +} + YY_BREAK +case 8: +YY_RULE_SETUP +{ + int rf, ff, rt, ft; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + /* [HGM] all squares referenced to board edges in stead of absolute */ + if (WhiteOnMove(yyboardindex)) { + if (boards[yyboardindex][0][(BOARD_WIDTH-1)>>1] == WhiteKing) { + /* ICS wild castling */ + rf = 0; + ff = (BOARD_WIDTH-1)>>1; + rt = 0; + ft = BOARD_RGHT-3; + sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE); + } else { + rf = 0; + ff = BOARD_WIDTH>>1; + rt = 0; + ft = BOARD_LEFT+2; + sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE); + } + } else{ + if (boards[yyboardindex][BOARD_HEIGHT-1][3] == BlackKing) { + /* ICS wild castling */ + rf = BOARD_HEIGHT-1; + ff = (BOARD_WIDTH-1)>>1; + rt = BOARD_HEIGHT-1; + ft = BOARD_RGHT-3; + sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE); + } else { + rf = BOARD_HEIGHT-1; + ff = BOARD_WIDTH>>1; + rt = BOARD_HEIGHT-1; + ft = BOARD_LEFT+2; + sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE); + } + } + return (int) LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + initialRights, /* [HGM] assume all castlings allowed */ + rf, ff, rt, ft, NULLCHAR); +} + YY_BREAK +case 9: +YY_RULE_SETUP +{ + int rf, ff, rt, ft; + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + + if (WhiteOnMove(yyboardindex)) { + if (boards[yyboardindex][0][(BOARD_WIDTH-1)>>1] == WhiteKing) { + /* ICS wild castling */ + rf = 0; + ff = (BOARD_WIDTH-1)>>1; + rt = 0; + ft = BOARD_LEFT+1; + sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE); + } else { + rf = 0; + ff = BOARD_WIDTH>>1; + rt = 0; + ft = BOARD_RGHT-2; + sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE); + } + } else { + if (boards[yyboardindex][BOARD_HEIGHT-1][(BOARD_WIDTH-1)>>1] == BlackKing) { + /* ICS wild castling */ + rf = BOARD_HEIGHT-1; + ff = (BOARD_WIDTH-1)>>1; + rt = BOARD_HEIGHT-1; + ft = BOARD_LEFT+1; + sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE); + } else { + rf = BOARD_HEIGHT-1; + ff = BOARD_WIDTH>>1; + rt = BOARD_HEIGHT-1; + ft = BOARD_RGHT-2; + sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE); + } + } + return (int) LegalityTest(boards[yyboardindex], + PosFlags(yyboardindex), EP_UNKNOWN, + initialRights, /* [HGM] assume all castlings allowed */ + rf, ff, rt, ft, NULLCHAR); +} + YY_BREAK +case 10: +YY_RULE_SETUP +{ + /* Bughouse piece drop. No legality checking for now. */ + currentMoveString[1] = '@'; + currentMoveString[2] = yytext[2]; + currentMoveString[3] = yytext[3]; + currentMoveString[4] = NULLCHAR; + + if (appData.debugMode) { + fprintf(debugFP, "Drop: %s\n", currentMoveString); + } + /* [HGM] do not allow values beyond board size */ + if(currentMoveString[3] - ONE >= BOARD_HEIGHT || + currentMoveString[2] - AAA >= BOARD_WIDTH ) + return 0; + + if (WhiteOnMove(yyboardindex)) { + currentMoveString[0] = ToUpper(yytext[0]); + return (int) WhiteDrop; + } else { + currentMoveString[0] = ToLower(yytext[0]); + return (int) BlackDrop; + } +} + YY_BREAK +case 11: +YY_RULE_SETUP +{ + if (WhiteOnMove(yyboardindex)) + return (int) BlackWins; + else + return (int) WhiteWins; +} + YY_BREAK +case 12: +YY_RULE_SETUP +{ + return (int) (ToUpper(yytext[0]) == 'W' ? BlackWins : WhiteWins); +} + YY_BREAK +case 13: +YY_RULE_SETUP +{ + return (int) GameUnfinished; +} + YY_BREAK +case 14: +YY_RULE_SETUP +{ + return (int) GameIsDrawn; +} + YY_BREAK +case 15: +YY_RULE_SETUP +{ + return (int) GameIsDrawn; +} + YY_BREAK +case 16: +YY_RULE_SETUP +{ + if (WhiteOnMove(yyboardindex)) + return (int) BlackWins; + else + return (int) WhiteWins; +} + YY_BREAK +case 17: +YY_RULE_SETUP +{ + if (WhiteOnMove(yyboardindex)) + return (int) BlackWins; + else + return (int) WhiteWins; +} + YY_BREAK +case 18: +YY_RULE_SETUP +{ + return (int) GameIsDrawn; +} + YY_BREAK +case 19: +YY_RULE_SETUP +{ + return (int) GameIsDrawn; +} + YY_BREAK +case 20: +YY_RULE_SETUP +{ + return (int) (ToUpper(yytext[0]) == 'W' ? WhiteWins : BlackWins); +} + YY_BREAK +case 21: +YY_RULE_SETUP +{ + return (int) (ToUpper(yytext[0]) == 'W' ? BlackWins : WhiteWins); +} + YY_BREAK +case 22: +YY_RULE_SETUP +{ + return (int) WhiteWins; +} + YY_BREAK +case 23: +YY_RULE_SETUP +{ + return (int) BlackWins; +} + YY_BREAK +case 24: +YY_RULE_SETUP +{ + return (int) GameIsDrawn; +} + YY_BREAK +case 25: +YY_RULE_SETUP +{ + return (int) GameUnfinished; +} + YY_BREAK +case 26: +YY_RULE_SETUP +{ + /* move numbers */ + if ((yyleng == 1) && (yytext[0] == '1')) + return (int) MoveNumberOne; +} + YY_BREAK +case 27: +YY_RULE_SETUP +{ + /* elapsed time indication, e.g. (0:12) or {10:21.071} */ + return (int) ElapsedTime; +} + YY_BREAK +case 28: +YY_RULE_SETUP +{ + /* position diagram enclosed in [-- --] */ + return (int) PositionDiagram; +} + YY_BREAK +case 29: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +{ + /* position diagram enclosed in {-- --} */ + return (int) PositionDiagram; +} + YY_BREAK +case 30: +YY_RULE_SETUP +{ + return (int) PGNTag; +} + YY_BREAK +case 31: +YY_RULE_SETUP +{ + return (int) GNUChessGame; +} + YY_BREAK +case 32: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +{ + return (int) XBoardGame; +} + YY_BREAK +case 33: +YY_RULE_SETUP +{ /* numeric annotation glyph */ + return (int) NAG; +} + YY_BREAK +case 34: +YY_RULE_SETUP +{ /* anything in {} */ + return (int) Comment; +} + YY_BREAK +case 35: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +{ /* ; to end of line */ + return (int) Comment; +} + YY_BREAK +case 36: +YY_RULE_SETUP +{ /* anything in [] */ + return (int) Comment; +} + YY_BREAK +case 37: +YY_RULE_SETUP +{ /* nested () */ + return (int) Comment; +} + YY_BREAK +case 38: +YY_RULE_SETUP +{ /* >=2 chars in () */ + return (int) Comment; +} + YY_BREAK +case 39: +YY_RULE_SETUP +{ + /* Skip mail headers */ +} + YY_BREAK +case 40: +YY_RULE_SETUP +{ + /* Skip random words */ +} + YY_BREAK +case 41: +YY_RULE_SETUP +{ + /* Skip everything else */ +} + YY_BREAK +case 42: +YY_RULE_SETUP +ECHO; + YY_BREAK + case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); + yy_state_ptr = yy_state_buf; + *yy_state_ptr++ = yy_current_state; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 735 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + *yy_state_ptr++ = yy_current_state; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + + register YY_CHAR yy_c = 1; + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 735 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 734); + if ( ! yy_is_jam ) + *yy_state_ptr++ = yy_current_state; + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + yy_current_buffer->yy_at_bol = (c == '\n'); + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef _WIN32 +#include +#else +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif + + + +static char *StringToLex; + +#ifndef FLEX_SCANNER +static FILE *lexFP; + +static int input() +{ + int ret; + + if (StringToLex != NULL) { + ret = *StringToLex; + if (ret == NULLCHAR) + ret = EOF; + else + StringToLex++; + } else if (unputCount > 0) { + ret = unputBuffer[--unputCount]; + } else { + ret = fgetc(lexFP); + } + + if (ret == EOF) + return 0; + else + return ret; +} + +/* + * Return offset of next pattern within current file + */ +int yyoffset() +{ + int offset = ftell(lexFP) - unputCount; + + if (offset < 0) { + offset = 0; + } + return(offset); +} + +static void output(ch) + int ch; +{ + fprintf(stderr, "PARSER BUG: unmatched character '%c' (0%o)\n", + ch, ch); +} + +static void unput(ch) + int ch; +{ + if (ch == 0) return; + if (StringToLex != NULL) { + StringToLex--; + } else { + if (unputCount >= UNPUT_BUF_SIZE) + fprintf(stderr, "PARSER BUG: unput buffer overflow '%c' (0%o)\n", + ch, ch); + unputBuffer[unputCount++] = ch; + } +} + +/* Get ready to lex from a new file. Kludge below sticks + an artificial newline at the front of the file, which the + above grammar ignores, but which makes ^ at start of pattern + match at the real start of the file. +*/ +void yynewfile(f) + FILE *f; +{ + lexFP = f; + StringToLex = NULL; + unputCount = 0; + unput('\n'); /* kludge */ +} + +/* Get ready to lex from a string. ^ at start of pattern WON'T + match at the start of the string! +*/ +void yynewstr(s) + char *s; +{ + lexFP = NULL; + StringToLex = s; + unputCount = 0; +} +#endif /*!FLEX_SCANNER*/ + +#ifdef FLEX_SCANNER +void my_yy_input(buf, result, max_size) + char *buf; + int *result; + int max_size; +{ + int count; + + if (StringToLex != NULL) { + count = 0; + while (*StringToLex != NULLCHAR) { + *buf++ = *StringToLex++; + count++; + } + *result = count; + return; + } else { + count = fread(buf, 1, max_size, yyin); + if (count == 0) { + *result = YY_NULL; + } else { + *result = count; + } + return; + } +} + +static YY_BUFFER_STATE my_file_buffer = NULL; + +/* + Return offset of next pattern in the current file. +*/ +int yyoffset() +{ + int pos = yy_c_buf_p - yy_current_buffer->yy_ch_buf; + + return(ftell(yy_current_buffer->yy_input_file) - + yy_n_chars + pos); +} + + +void yynewstr(s) + char *s; +{ + if (my_file_buffer != NULL) + yy_delete_buffer(my_file_buffer); + StringToLex = s; + my_file_buffer = yy_create_buffer(stdin, YY_BUF_SIZE); + yy_switch_to_buffer(my_file_buffer); +} + +void yynewfile(f) + FILE *f; +{ + if (my_file_buffer != NULL) + yy_delete_buffer(my_file_buffer); + StringToLex = NULL; + my_file_buffer = yy_create_buffer(f, YY_BUF_SIZE); + yy_switch_to_buffer(my_file_buffer); +} +#endif /*FLEX_SCANNER*/ + +int yywrap() +{ + return TRUE; +} + +/* Parse a move from the given string s */ +/* ^ at start of pattern WON'T work here unless using flex */ +ChessMove yylexstr(boardIndex, s) + int boardIndex; + char *s; +{ + ChessMove ret; + char *oldStringToLex; +#ifdef FLEX_SCANNER + YY_BUFFER_STATE buffer, oldBuffer; +#endif + + yyboardindex = boardIndex; + oldStringToLex = StringToLex; + StringToLex = s; +#ifdef FLEX_SCANNER + buffer = yy_create_buffer(stdin, YY_BUF_SIZE); + oldBuffer = YY_CURRENT_BUFFER; + yy_switch_to_buffer(buffer); +#endif /*FLEX_SCANNER*/ + + ret = (ChessMove) yylex(); + +#ifdef FLEX_SCANNER + if (oldBuffer != NULL) + yy_switch_to_buffer(oldBuffer); + yy_delete_buffer(buffer); +#endif /*FLEX_SCANNER*/ + StringToLex = oldStringToLex; + + return ret; +} diff --git a/winboard/resource.h b/winboard/resource.h index 0dd963e..67f2932 100644 --- a/winboard/resource.h +++ b/winboard/resource.h @@ -55,6 +55,7 @@ #define IDM_PasteGame 181 #define IDM_CopyPosition 182 #define IDM_PastePosition 183 +#define IDM_NewVariant 184 #define OPT_TCtext1 202 #define OPT_TCTime 203 #define OPT_TCtext2 204 @@ -419,6 +420,31 @@ #define IDC_SizeOfEGTB 1467 #define IDC_UseBook 1469 #define IDC_BookFile 1470 +#define DLG_NewVariant 1500 +#define OPT_VariantGothic 1501 +#define OPT_VariantCrazyhouse 1502 +#define OPT_VariantBughouse 1503 +#define OPT_VariantCourier 1504 +#define OPT_VariantShatranj 1505 +#define OPT_VariantShogi 1506 +#define OPT_VariantXiangqi 1507 +#define OPT_VariantCapablanca 1508 +#define OPT_VariantTwoKings 1509 +#define OPT_VariantKnightmate 1510 +#define OPT_VariantLosers 1511 +#define OPT_VariantSuicide 1512 +#define OPT_VariantAtomic 1513 +#define OPT_VariantNormal 1514 +#define OPT_VariantFairy 1515 +#define IDC_Files 1550 +#define IDC_Ranks 1551 +#define IDC_Holdings 1552 +#define IDC_TestClaims 1600 +#define IDC_DetectMates 1601 +#define IDC_MaterialDraws 1602 +#define IDC_TrivialDraws 1603 +#define IDC_RuleMoves 1604 +#define IDC_DrawRepeats 1605 #define IDC_STATIC -1 // Next default values for new objects diff --git a/winboard/winboard.c b/winboard/winboard.c index d2facc2..21460fd 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -93,6 +93,8 @@ void InitEngineUCI( const char * iniDir, ChessProgramState * cps ); extern int whiteFlag, blackFlag; +void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber); + typedef struct { ChessSquare piece; POINT pos; /* window coordinates of current pos */ @@ -168,6 +170,7 @@ HWND hCommPort = NULL; /* currently open comm port */ static HWND hwndPause; /* pause button */ static HBITMAP pieceBitmap[3][(int) BlackPawn]; /* [HGM] nr of bitmaps referred to bP in stead of wK */ static HBRUSH lightSquareBrush, darkSquareBrush, + blackSquareBrush, /* [HGM] for band between board and holdings */ whitePieceBrush, blackPieceBrush, iconBkgndBrush, outlineBrush; static POINT gridEndpoints[(BOARD_SIZE + 1) * 4]; static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2]; @@ -584,6 +587,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) } else { GetCurrentDirectory(MSG_SIZ, installDir); } + gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] won't have open window otherwise InitAppData(lpCmdLine); /* Get run-time parameters */ if (appData.debugMode) { debugFP = fopen(appData.nameOfDebugFile, "w"); @@ -1163,11 +1167,16 @@ ArgDescriptor argDescriptors[] = { { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE }, { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE }, - /* [HGM] User-selectable board size */ + /* [HGM] board-size, adjudication and misc. options */ { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE }, { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE }, + { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE }, { "matchPause", ArgInt, (LPVOID) &appData.matchPause, FALSE }, + { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, TRUE }, { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE }, + { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE }, + { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE }, + { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE }, { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE }, { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE }, @@ -1875,13 +1884,18 @@ InitAppData(LPSTR lpCmdLine) InitWindowPlacement( &wpEvalGraph ); InitWindowPlacement( &wpEngineOutput ); - /* [HGM] User-selectable board size */ - appData.NrFiles = 8; - appData.NrRanks = 8; - appData.matchPause = 10000; - appData.testClaims = FALSE; - appData.ruleMoves = 51; - appData.drawRepeats = 6; + /* [HGM] User-selectable board size, adjudication control, miscellaneous */ + appData.NrFiles = -1; + appData.NrRanks = -1; + appData.holdingsSize = -1; + appData.testClaims = FALSE; + appData.checkMates = FALSE; + appData.materialDraws= FALSE; + appData.trivialDraws = FALSE; + appData.ruleMoves = 51; + appData.drawRepeats = 6; + appData.matchPause = 10000; + appData.alphaRank = FALSE; #ifdef ZIPPY appData.zippyTalk = ZIPPY_TALK; @@ -2285,37 +2299,37 @@ enum { PM_WN = (int) WhiteKnight, PM_WB = (int) WhiteBishop, PM_WR = (int) WhiteRook, + PM_WQ = (int) WhiteQueen, #ifdef FAIRY - PM_WA = (int) WhiteCardinal, - PM_WC = (int) WhiteMarshall, - PM_WFP = (int) WhiteFairyPawn, - PM_WFN = (int) WhiteFairyKnight, - PM_WFB = (int) WhiteFairyBishop, - PM_WFR = (int) WhiteFairyRook, - PM_WFA = (int) WhiteFairyCardinal, - PM_WFC = (int) WhiteFairyMarshall, - PM_WFQ = (int) WhiteFairyQueen, - PM_WFK = (int) WhiteFairyKing, + PM_WF = (int) WhiteFerz, + PM_WW = (int) WhiteWazir, + PM_WE = (int) WhiteAlfil, + PM_WH = (int) WhiteNightrider, + PM_WA = (int) WhiteCardinal, + PM_WC = (int) WhiteMarshall, + PM_WG = (int) WhiteGrasshopper, + PM_WO = (int) WhiteCannon, + PM_WM = (int) WhiteMan, + PM_WU = (int) WhiteUnicorn, #endif - PM_WQ = (int) WhiteQueen, PM_WK = (int) WhiteKing, PM_BP = (int) BlackPawn, PM_BN = (int) BlackKnight, PM_BB = (int) BlackBishop, PM_BR = (int) BlackRook, + PM_BQ = (int) BlackQueen, #ifdef FAIRY - PM_BA = (int) BlackCardinal, - PM_BC = (int) BlackMarshall, - PM_BFP = (int) BlackFairyPawn, - PM_BFN = (int) BlackFairyKnight, - PM_BFB = (int) BlackFairyBishop, - PM_BFR = (int) BlackFairyRook, - PM_BFA = (int) BlackFairyCardinal, - PM_BFC = (int) BlackFairyMarshall, - PM_BFQ = (int) BlackFairyQueen, - PM_BFK = (int) BlackFairyKing, + PM_BF = (int) BlackFerz, + PM_BW = (int) BlackWazir, + PM_BE = (int) BlackAlfil, + PM_BH = (int) BlackNightrider, + PM_BA = (int) BlackCardinal, + PM_BC = (int) BlackMarshall, + PM_BG = (int) BlackGrasshopper, + PM_BO = (int) BlackCannon, + PM_BM = (int) BlackMan, + PM_BU = (int) BlackUnicorn, #endif - PM_BQ = (int) BlackQueen, PM_BK = (int) BlackKing }; @@ -2324,15 +2338,15 @@ static HBITMAP hPieceMask[(int) EmptySquare]; static HBITMAP hPieceFace[(int) EmptySquare]; static int fontBitmapSquareSize = 0; static char pieceToFontChar[(int) EmptySquare] = - { 'p', 'n', 'b', 'r', + { 'p', 'n', 'b', 'r', 'q', #ifdef FAIRY 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k', #endif - 'q', 'k', 'o', 'm', 'v', 't', + 'k', 'o', 'm', 'v', 't', 'w', #ifdef FAIRY 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l', #endif - 'w', 'l' }; + 'l' }; static BOOL SetPieceToFontCharTable( const char * map ) { @@ -2343,13 +2357,11 @@ static BOOL SetPieceToFontCharTable( const char * map ) int i; /* [HGM] Accept even length from 12 to 32 */ for( i=0; i<(int) EmptySquare; i++ ) pieceToFontChar[i] = 0; - for( i=0; i BOARD_HEIGHT-4) && - column < (BOARD_WIDTH + 4)/2 && - column > (BOARD_WIDTH - 5)/2 ) square_color = 0; + square_color = !InPalace(row, column); + if(BOARD_HEIGHT&1) { if(row==BOARD_HEIGHT/2) square_color ^= 1; } + else if(row < BOARD_HEIGHT/2) square_color ^= 1; } piece_color = (int) piece < (int) BlackPawn; + +#ifdef FAIRY + /* [HGM] holdings file: light square or black */ + if(column == BOARD_LEFT-2) { + if( row > BOARD_HEIGHT - gameInfo.holdingsSize - 1 ) + square_color = 1; + else { + DisplayHoldingsCount(hdc, x, y, 0, 0); /* black out */ + continue; + } + } else + if(column == BOARD_RGHT + 1 ) { + if( row < gameInfo.holdingsSize ) + square_color = 1; + else { + DisplayHoldingsCount(hdc, x, y, 0, 0); + continue; + } + } + if(column == BOARD_LEFT-1 ) /* left align */ + DisplayHoldingsCount(hdc, x, y, 0, (int) board[row][column]); + else if( column == BOARD_RGHT) /* right align */ + DisplayHoldingsCount(hdc, x, y, 1, (int) board[row][column]); + else +#endif if (appData.monoMode) { if (piece == EmptySquare) { BitBlt(hdc, x, y, squareSize, squareSize, 0, 0, 0, @@ -3784,8 +3853,9 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc) } } else { - oldBrush = SelectObject(hdc, square_color ? - lightSquareBrush : darkSquareBrush); + HBRUSH brush = square_color ? lightSquareBrush : darkSquareBrush; + + oldBrush = SelectObject(hdc, brush ); BitBlt(hdc, x, y, squareSize, squareSize, 0, 0, 0, PATCOPY); SelectObject(hdc, oldBrush); if (piece != EmptySquare) @@ -3904,6 +3974,22 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) hdcmem = CreateCompatibleDC(hdc); tmphdc = CreateCompatibleDC(hdc); + /* If dragging is in progress, we temporarely remove the piece */ + /* [HGM] or temporarily decrease count if stacked */ + /* !! Moved to before board compare !! */ + if (dragInfo.from.x >= 0 && dragInfo.pos.x >= 0) { + dragged_piece = board[dragInfo.from.y][dragInfo.from.x]; + if(dragInfo.from.x == BOARD_LEFT-2 ) { + if(--board[dragInfo.from.y][dragInfo.from.x+1] == 0 ) + board[dragInfo.from.y][dragInfo.from.x] = EmptySquare; + } else + if(dragInfo.from.x == BOARD_RGHT+1) { + if(--board[dragInfo.from.y][dragInfo.from.x-1] == 0 ) + board[dragInfo.from.y][dragInfo.from.x] = EmptySquare; + } else + board[dragInfo.from.y][dragInfo.from.x] = EmptySquare; + } + /* Figure out which squares need updating by comparing the * newest board with the last drawn board and checking if * flipping has changed. @@ -3997,12 +4083,6 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) } } - /* If dragging is in progress, we temporarely remove the piece */ - if (dragInfo.from.x >= 0 && dragInfo.pos.x >= 0) { - dragged_piece = board[dragInfo.from.y][dragInfo.from.x]; - board[dragInfo.from.y][dragInfo.from.x] = EmptySquare; - } - /* Are we animating a move? * If so, * - remove the piece from the board (temporarely) @@ -4051,8 +4131,17 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) DrawCoordsOnDC(hdcmem); - /* Put the dragged piece back into place and draw it */ - if (dragged_piece != EmptySquare) { + CopyBoard(lastDrawn, board); /* [HGM] Moved to here from end of routine, */ + /* to make sure lastDrawn contains what is actually drawn */ + + /* Put the dragged piece back into place and draw it (out of place!) */ + if (dragged_piece != EmptySquare) { + /* [HGM] or restack */ + if(dragInfo.from.x == BOARD_LEFT-2 ) + board[dragInfo.from.y][dragInfo.from.x+1]++; + else + if(dragInfo.from.x == BOARD_RGHT+1 ) + board[dragInfo.from.y][dragInfo.from.x-1]++; board[dragInfo.from.y][dragInfo.from.x] = dragged_piece; x = dragInfo.pos.x - squareSize / 2; y = dragInfo.pos.y - squareSize / 2; @@ -4113,7 +4202,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) CheckMenuItem(GetMenu(hwndMain),IDM_FlipView, MF_BYCOMMAND|MF_UNCHECKED); } - CopyBoard(lastDrawn, board); +/* CopyBoard(lastDrawn, board);*/ lastDrawnHighlight = highlightInfo; lastDrawnPremove = premoveHighlightInfo; lastDrawnFlipView = flipView; @@ -4230,6 +4319,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) BOOLEAN saveAnimate; BOOLEAN forceFullRepaint = IsFullRepaintPreferrable(); /* [AS] */ static BOOLEAN sameAgain = FALSE; + ChessMove moveType; if (recursive) { if (message == WM_MBUTTONUP) { @@ -4283,15 +4373,24 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) dragInfo.start.x = dragInfo.start.y = -1; dragInfo.from = dragInfo.start; break; - } else if (x < 0 || y < 0) { + } else if (x < 0 || y < 0 + /* [HGM] block clicks between board and holdings */ + || x == BOARD_LEFT-1 || x == BOARD_RGHT + || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize + || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize + ) { break; } else if (fromX == x && fromY == y) { /* Downclick on same square again */ ClearHighlights(); DrawPosition(forceFullRepaint || FALSE, NULL); sameAgain = TRUE; - } else if (fromX != -1) { - /* Downclick on different square */ + } else if (fromX != -1 && + x != BOARD_LEFT-2 && x != BOARD_RGHT+1 + ) { + /* Downclick on different square. */ + /* [HGM] if on holdings file, should count as new first click ! */ + ChessSquare pdown, pup; pdown = boards[currentMove][fromY][fromX]; pup = boards[currentMove][y][x]; @@ -4304,30 +4403,37 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) click-click move is possible */ toX = x; toY = y; - if (IsPromotion(fromX, fromY, toX, toY)) { - if (appData.alwaysPromoteToQueen) { - UserMoveEvent(fromX, fromY, toX, toY, 'q'); - if (!appData.highlightLastMove) { - ClearHighlights(); - DrawPosition(forceFullRepaint || FALSE, NULL); - } - } else { - SetHighlights(fromX, fromY, toX, toY); - DrawPosition(forceFullRepaint || FALSE, NULL); - PromotionPopup(hwnd); - } - } else { /* not a promotion */ - if (appData.animate || appData.highlightLastMove) { - SetHighlights(fromX, fromY, toX, toY); - } else { - ClearHighlights(); - } - UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR); - if (appData.animate && !appData.highlightLastMove) { - ClearHighlights(); - DrawPosition(forceFullRepaint || FALSE, NULL); - } - } + moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR); + if(moveType != ImpossibleMove) { + if (IsPromotion(fromX, fromY, toX, toY)) { + /* [HGM] UserMoveEvent requires two calls now, + to make sure move is legal before showing promotion popup */ + if (appData.alwaysPromoteToQueen) { + FinishMove(moveType, fromX, fromY, toX, toY, 'q'); + if (!appData.highlightLastMove) { + ClearHighlights(); + DrawPosition(forceFullRepaint || FALSE, NULL); + } + } else { + SetHighlights(fromX, fromY, toX, toY); + DrawPosition(forceFullRepaint || FALSE, NULL); + /* [HGM] Popup calls FinishMove now. + If promotion to Q is legal, all are legal! */ + PromotionPopup(hwnd); + } + } else { /* not a promotion */ + if (appData.animate || appData.highlightLastMove) { + SetHighlights(fromX, fromY, toX, toY); + } else { + ClearHighlights(); + } + FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR); + if (appData.animate && !appData.highlightLastMove) { + ClearHighlights(); + DrawPosition(forceFullRepaint || FALSE, NULL); + } + } + } if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); fromX = fromY = -1; break; @@ -4356,7 +4462,6 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ReleaseCapture(); if (fromX == -1) break; if (x == fromX && y == fromY) { - dragInfo.from.x = dragInfo.from.y = -1; /* Upclick on same square */ if (sameAgain) { /* Clicked same square twice: abort click-click move */ @@ -4367,26 +4472,31 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* First square clicked: start click-click move */ SetHighlights(fromX, fromY, -1, -1); } + dragInfo.from.x = dragInfo.from.y = -1; DrawPosition(forceFullRepaint || FALSE, NULL); } else if (dragInfo.from.x < 0 || dragInfo.from.y < 0) { /* Errant click; ignore */ break; } else { - /* Finish drag move */ + /* Finish drag move. */ + if (appData.debugMode) { + fprintf(debugFP, "release\n"); + } dragInfo.from.x = dragInfo.from.y = -1; toX = x; toY = y; saveAnimate = appData.animate; /* sorry, Hawk :) */ appData.animate = appData.animate && !appData.animateDragging; - if (IsPromotion(fromX, fromY, toX, toY)) { - if (appData.alwaysPromoteToQueen) { - UserMoveEvent(fromX, fromY, toX, toY, 'q'); - } else { - DrawPosition(forceFullRepaint || FALSE, NULL); - PromotionPopup(hwnd); - } - } else { - UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR); + moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR); + if(moveType != ImpossibleMove) { + if (IsPromotion(fromX, fromY, toX, toY)) { + if (appData.alwaysPromoteToQueen) + FinishMove(moveType, fromX, fromY, toX, toY, 'q'); + else { + DrawPosition(forceFullRepaint || FALSE, NULL); + PromotionPopup(hwnd); /* [HGM] Popup now calls FinishMove */ + } + } else FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR); } if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); appData.animate = saveAnimate; @@ -4410,12 +4520,13 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { BOOL full_repaint = FALSE; + sameAgain = FALSE; /* [HGM] if we drag something around, do keep square selected */ if (appData.animateDragging) { dragInfo.pos = pt; } if (appData.highlightDragging) { SetHighlights(fromX, fromY, x, y); - if( IsDrawArrowEnabled() && (x < 0 || x >= BOARD_WIDTH || y < 0 || y > BOARD_WIDTH) ) { + if( IsDrawArrowEnabled() && (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT) ) { full_repaint = TRUE; } } @@ -4614,7 +4725,11 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) return FALSE; } EndDialog(hDlg, TRUE); /* Exit the dialog */ - UserMoveEvent(fromX, fromY, toX, toY, promoChar); + /* [HGM] Call FinishMove rather than UserMoveEvent, as we + only show the popup when we are already sure the move is valid or + legal. We pass a faulty move type, but the kludge is that FinishMove + will figure out it is a promotion from the promoChar. */ + FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar); if (!appData.highlightLastMove) { ClearHighlights(); DrawPosition(FALSE, NULL); @@ -4831,6 +4946,10 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } break; + case IDM_NewVariant: + NewVariantPopup(hwnd); + break; + case IDM_LoadGame: LoadGameDialog(hwnd, "Load Game from File"); break; @@ -7278,6 +7397,37 @@ ConsoleOutput(char* data, int length, int forceVisible) void +DisplayHoldingsCount(HDC hdc, int x, int y, int rightAlign, int copyNumber) +{ + char buf[100]; + char *str; + COLORREF oldFg, oldBg; + HFONT oldFont; + RECT rect; + + if(copyNumber > 1) sprintf(buf, "%d", copyNumber); else buf[0] = 0; + + oldFg = SetTextColor(hdc, RGB(255, 255, 255)); /* white */ + oldBg = SetBkColor(hdc, RGB(0, 0, 0)); /* black */ + oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf); + + rect.left = x; + rect.right = x + squareSize; + rect.top = y; + rect.bottom = y + squareSize; + str = buf; + + ExtTextOut(hdc, x + MESSAGE_LINE_LEFTMARGIN + + (rightAlign ? (squareSize*2)/3 : 0), + y, ETO_CLIPPED|ETO_OPAQUE, + &rect, str, strlen(str), NULL); + + (void) SetTextColor(hdc, oldFg); + (void) SetBkColor(hdc, oldBg); + (void) SelectObject(hdc, oldFont); +} + +void DisplayAClock(HDC hdc, int timeRemaining, int highlight, RECT *rect, char *color, char *flagFell) { diff --git a/winboard/winboard.rc b/winboard/winboard.rc index 452d2cc..d9387f9 100644 --- a/winboard/winboard.rc +++ b/winboard/winboard.rc @@ -592,6 +592,55 @@ BEGIN WS_DISABLED | NOT WS_BORDER | NOT WS_TABSTOP END +DLG_NewVariant DIALOG DISCARDABLE 0, 0, 194, 250 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Variants" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,84,232,50,14 + PUSHBUTTON "Cancel",IDCANCEL,140,232,50,14 + CONTROL "&normal",OPT_VariantNormal,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,9,14,50,10 + CONTROL "&gothic",OPT_VariantGothic,"Button",BS_AUTORADIOBUTTON,9,24, + 50,10 + CONTROL "cra&zyhouse",OPT_VariantCrazyhouse,"Button",BS_AUTORADIOBUTTON,9,34, + 50,10 + CONTROL "&shogi",OPT_VariantShogi,"Button",BS_AUTORADIOBUTTON,9, + 44,50,10 + CONTROL "&xiangqi",OPT_VariantXiangqi,"Button",BS_AUTORADIOBUTTON,9,54,50, + 10 + CONTROL "cou&rier",OPT_VariantCourier,"Button",BS_AUTORADIOBUTTON,9,64, + 50,10 + CONTROL "&knightmate",OPT_VariantKnightmate,"Button",BS_AUTORADIOBUTTON, + 70,14,50,10 + CONTROL "&atomic",OPT_VariantAtomic,"Button",BS_AUTORADIOBUTTON, + 70,24,50,10 + CONTROL "&losers",OPT_VariantLosers,"Button",BS_AUTORADIOBUTTON, + 70,34,50,10 + CONTROL "s&uicide",OPT_VariantSuicide,"Button",BS_AUTORADIOBUTTON, + 70,44,50,10 + CONTROL "&capablanca",OPT_VariantCapablanca,"Button",BS_AUTORADIOBUTTON,70, + 54,50,10 + CONTROL "&twokings",OPT_VariantTwoKings,"Button",BS_AUTORADIOBUTTON,70,64, + 50,10 + CONTROL "&fairy",OPT_VariantFairy,"Button",BS_AUTORADIOBUTTON,134, + 14,50,10 + CONTROL "&bughouse",OPT_VariantBughouse,"Button",BS_AUTORADIOBUTTON,134,24,50, + 10 + CONTROL "Shatran&j",OPT_VariantShatranj,"Button",BS_AUTORADIOBUTTON,134, + 34,50,10 + GROUPBOX "Variant",IDC_STATIC,4,4,185,75 + LTEXT "Board size:",IDC_STATIC,10,95,40,8 + EDITTEXT IDC_Ranks,60,91,14,14,ES_AUTOHSCROLL + LTEXT "ranks",IDC_STATIC,77,95,22,8 + EDITTEXT IDC_Files,116,91,14,14,ES_AUTOHSCROLL + LTEXT "files",IDC_STATIC,133,95,37,8 + LTEXT "Holdings with room for:",IDC_STATIC,10,113,90,8 + EDITTEXT IDC_Holdings,93,109,14,14,ES_AUTOHSCROLL + LTEXT "pieces",IDC_STATIC,110,113,22,8 + LTEXT "('-1' means defaults for selected variant)",IDC_STATIC,10,131,150,8 +END + DLG_Fonts DIALOG DISCARDABLE 0, 0, 266, 226 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Fonts" @@ -705,12 +754,12 @@ BEGIN ICON IDI_TRANS_14,IDC_StateIcon2,164,84,20,20 END -DLG_EnginePlayOptions DIALOG DISCARDABLE 0, 0, 208, 129 +DLG_EnginePlayOptions DIALOG DISCARDABLE 0, 0, 208, 177 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Engine Options" FONT 8, "MS Sans Serif" BEGIN - CONTROL "Ponder Next Move",IDC_EpPonder,"Button",BS_AUTOCHECKBOX | + CONTROL "Ponder Next Move",IDC_EpPonder,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,4,75,10 CONTROL "Enable and Show Thinking (recommended)", IDC_EpShowThinking,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, @@ -721,7 +770,7 @@ BEGIN CONTROL "Periodic Updates (for Analysis Mode)", IDC_EpPeriodicUpdates,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,40,131,10 - GROUPBOX "Engine-engine matches",IDC_STATIC,4,56,200,50 + GROUPBOX "Engine-engine matches",IDC_STATIC,4,56,200,98 LTEXT "Adjudicate draw after:",IDC_STATIC,10,72,70,8 EDITTEXT IDC_EpDrawMoveCount,116,68,40,14,ES_AUTOHSCROLL LTEXT "moves",IDC_STATIC,158,72,22,8 @@ -729,8 +778,24 @@ BEGIN 8 EDITTEXT IDC_EpAdjudicationThreshold,116,86,40,14,ES_AUTOHSCROLL LTEXT "centipawns",IDC_STATIC,158,90,37,8 - DEFPUSHBUTTON "OK",IDOK,98,112,50,14 - PUSHBUTTON "Cancel",IDCANCEL,154,112,50,14 + CONTROL "&Verify Engine Claims",IDC_TestClaims,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,108,100,10 + CONTROL "Detect &Mates", + IDC_DetectMates,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 10,118,100,10 + CONTROL "Draw if &Insufficient Material", + IDC_MaterialDraws,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,128,100,10 + CONTROL "Adjudicate &Trivial Draws", + IDC_TrivialDraws,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,138,100,10 + GROUPBOX "Apply",IDC_STATIC,115,102,81,47 + EDITTEXT IDC_RuleMoves,120,113,20,14,ES_AUTOHSCROLL + LTEXT "-move rule",IDC_STATIC,142,117,35,8 + EDITTEXT IDC_DrawRepeats,120,130,20,14,ES_AUTOHSCROLL + LTEXT "-fold repeats",IDC_STATIC,142,134,50,8 + DEFPUSHBUTTON "OK",IDOK,98,160,50,14 + PUSHBUTTON "Cancel",IDCANCEL,154,160,50,14 END DLG_OptionsUCI DIALOG DISCARDABLE 0, 0, 228, 124 @@ -912,6 +977,7 @@ BEGIN BEGIN MENUITEM "New &Game\tCtrl-N", IDM_NewGame MENUITEM "New FRC Game...", IDM_NewGameFRC + MENUITEM "New Variant...", IDM_NewVariant MENUITEM SEPARATOR MENUITEM "&Load Game...\tCtrl-O", IDM_LoadGame MENUITEM "Load &Next Game\tAlt+PgDn", IDM_LoadNextGame @@ -1542,6 +1608,12 @@ W72O BITMAP MOVEABLE PURE "bitmaps\\w72o.bmp" O72O BITMAP MOVEABLE PURE "bitmaps\\o72o.bmp" U72O BITMAP MOVEABLE PURE "bitmaps\\u72o.bmp" H72O BITMAP MOVEABLE PURE "bitmaps\\h72o.bmp" +G72O BITMAP MOVEABLE PURE "bitmaps\\g72o.bmp" +DK72O BITMAP MOVEABLE PURE "bitmaps\\dk72o.bmp" +WP72O BITMAP MOVEABLE PURE "bitmaps\\wp72o.bmp" +WN72O BITMAP MOVEABLE PURE "bitmaps\\wn72o.bmp" +WL72O BITMAP MOVEABLE PURE "bitmaps\\wl72o.bmp" +WS72O BITMAP MOVEABLE PURE "bitmaps\\ws72o.bmp" E72S BITMAP MOVEABLE PURE "bitmaps\\e72s.bmp" A72S BITMAP MOVEABLE PURE "bitmaps\\a72s.bmp" C72S BITMAP MOVEABLE PURE "bitmaps\\c72s.bmp" @@ -1551,6 +1623,12 @@ W72S BITMAP MOVEABLE PURE "bitmaps\\w72s.bmp" O72S BITMAP MOVEABLE PURE "bitmaps\\o72s.bmp" U72S BITMAP MOVEABLE PURE "bitmaps\\u72s.bmp" H72S BITMAP MOVEABLE PURE "bitmaps\\h72s.bmp" +G72S BITMAP MOVEABLE PURE "bitmaps\\g72s.bmp" +DK72S BITMAP MOVEABLE PURE "bitmaps\\dk72s.bmp" +WP72S BITMAP MOVEABLE PURE "bitmaps\\wp72s.bmp" +WN72S BITMAP MOVEABLE PURE "bitmaps\\wn72s.bmp" +WL72S BITMAP MOVEABLE PURE "bitmaps\\wl72s.bmp" +WS72S BITMAP MOVEABLE PURE "bitmaps\\ws72s.bmp" E72W BITMAP MOVEABLE PURE "bitmaps\\e72w.bmp" A72W BITMAP MOVEABLE PURE "bitmaps\\a72w.bmp" C72W BITMAP MOVEABLE PURE "bitmaps\\c72w.bmp" @@ -1560,6 +1638,8 @@ W72W BITMAP MOVEABLE PURE "bitmaps\\w72w.bmp" O72W BITMAP MOVEABLE PURE "bitmaps\\o72w.bmp" U72W BITMAP MOVEABLE PURE "bitmaps\\u72w.bmp" H72W BITMAP MOVEABLE PURE "bitmaps\\h72w.bmp" +G72W BITMAP MOVEABLE PURE "bitmaps\\g72w.bmp" +DK72W BITMAP MOVEABLE PURE "bitmaps\\dk72w.bmp" E49O BITMAP MOVEABLE PURE "bitmaps\\e49o.bmp" A49O BITMAP MOVEABLE PURE "bitmaps\\a49o.bmp" C49O BITMAP MOVEABLE PURE "bitmaps\\c49o.bmp" @@ -1569,6 +1649,12 @@ W49O BITMAP MOVEABLE PURE "bitmaps\\w49o.bmp" O49O BITMAP MOVEABLE PURE "bitmaps\\o49o.bmp" U49O BITMAP MOVEABLE PURE "bitmaps\\u49o.bmp" H49O BITMAP MOVEABLE PURE "bitmaps\\h49o.bmp" +G49O BITMAP MOVEABLE PURE "bitmaps\\g49o.bmp" +DK49O BITMAP MOVEABLE PURE "bitmaps\\dk49o.bmp" +WP49O BITMAP MOVEABLE PURE "bitmaps\\wp49o.bmp" +WN49O BITMAP MOVEABLE PURE "bitmaps\\wn49o.bmp" +WL49O BITMAP MOVEABLE PURE "bitmaps\\wl49o.bmp" +WS49O BITMAP MOVEABLE PURE "bitmaps\\ws49o.bmp" E49S BITMAP MOVEABLE PURE "bitmaps\\e49s.bmp" A49S BITMAP MOVEABLE PURE "bitmaps\\a49s.bmp" C49S BITMAP MOVEABLE PURE "bitmaps\\c49s.bmp" @@ -1578,6 +1664,12 @@ W49S BITMAP MOVEABLE PURE "bitmaps\\w49s.bmp" O49S BITMAP MOVEABLE PURE "bitmaps\\o49s.bmp" U49S BITMAP MOVEABLE PURE "bitmaps\\u49s.bmp" H49S BITMAP MOVEABLE PURE "bitmaps\\h49s.bmp" +G49S BITMAP MOVEABLE PURE "bitmaps\\g49s.bmp" +DK49S BITMAP MOVEABLE PURE "bitmaps\\dk49s.bmp" +WP49S BITMAP MOVEABLE PURE "bitmaps\\wp49s.bmp" +WN49S BITMAP MOVEABLE PURE "bitmaps\\wn49s.bmp" +WL49S BITMAP MOVEABLE PURE "bitmaps\\wl49s.bmp" +WS49S BITMAP MOVEABLE PURE "bitmaps\\ws49s.bmp" E49W BITMAP MOVEABLE PURE "bitmaps\\e49w.bmp" A49W BITMAP MOVEABLE PURE "bitmaps\\a49w.bmp" C49W BITMAP MOVEABLE PURE "bitmaps\\c49w.bmp" @@ -1587,6 +1679,8 @@ W49W BITMAP MOVEABLE PURE "bitmaps\\w49w.bmp" O49W BITMAP MOVEABLE PURE "bitmaps\\o49w.bmp" U49W BITMAP MOVEABLE PURE "bitmaps\\u49w.bmp" H49W BITMAP MOVEABLE PURE "bitmaps\\h49w.bmp" +G49W BITMAP MOVEABLE PURE "bitmaps\\g49w.bmp" +DK49W BITMAP MOVEABLE PURE "bitmaps\\dk49w.bmp" #ifdef APSTUDIO_INVOKED diff --git a/winboard/woptions.c b/winboard/woptions.c index a740f8f..1d92129 100644 --- a/winboard/woptions.c +++ b/winboard/woptions.c @@ -1,6 +1,6 @@ /* * woptions.c -- Options dialog box routines for WinBoard - * $Id: woptions.c,v 2.1 2003/10/27 19:21:02 mann Exp $ + * $Id: woptions.c,v 2.1 2003/10/27 19:21:02 mann Exp $ * * Copyright 2000 Free Software Foundation, Inc. * @@ -26,7 +26,7 @@ #include /* required for all Windows applications */ #include #include -#include /* [AS] Requires NT 4.0 or Win95 */ +#include /* [AS] Requires NT 4.0 or Win95 */ #include "common.h" #include "winboard.h" @@ -60,7 +60,7 @@ extern ColorClass currentColorClass; extern HWND hwndConsole; extern char *defaultTextAttribs[]; extern HWND commentDialog; -extern HWND moveHistoryDialog; +extern HWND moveHistoryDialog; extern char installDir[]; extern HWND hCommPort; /* currently open comm port */ extern DCB dcb; @@ -82,6 +82,7 @@ typedef struct { LRESULT CALLBACK GeneralOptions(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK BoardOptions(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK NewVariant(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK IcsOptions(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK FontOptions(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK CommPortOptions(HWND, UINT, WPARAM, LPARAM); @@ -169,10 +170,10 @@ GeneralOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) CHECK_BOX(OPT_ShowCoordinates, appData.showCoords); CHECK_BOX(OPT_ShowThinking, appData.showThinking); CHECK_BOX(OPT_TestLegality, appData.testLegality); - CHECK_BOX(OPT_HideThinkFromHuman, appData.hideThinkingFromHuman); - CHECK_BOX(OPT_SaveExtPGN, appData.saveExtendedInfoInPGN); - CHECK_BOX(OPT_ExtraInfoInMoveHistory, appData.showEvalInMoveHistory); - CHECK_BOX(OPT_HighlightMoveArrow, appData.highlightMoveWithArrow); + CHECK_BOX(OPT_HideThinkFromHuman, appData.hideThinkingFromHuman); + CHECK_BOX(OPT_SaveExtPGN, appData.saveExtendedInfoInPGN); + CHECK_BOX(OPT_ExtraInfoInMoveHistory, appData.showEvalInMoveHistory); + CHECK_BOX(OPT_HighlightMoveArrow, appData.highlightMoveWithArrow); #undef CHECK_BOX @@ -214,10 +215,10 @@ GeneralOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) appData.showCoords = IS_CHECKED(OPT_ShowCoordinates); ShowThinkingEvent( IS_CHECKED(OPT_ShowThinking)); appData.testLegality = IS_CHECKED(OPT_TestLegality); - appData.hideThinkingFromHuman= IS_CHECKED(OPT_HideThinkFromHuman); - appData.saveExtendedInfoInPGN= IS_CHECKED(OPT_SaveExtPGN); - appData.showEvalInMoveHistory= IS_CHECKED(OPT_ExtraInfoInMoveHistory); - appData.highlightMoveWithArrow=IS_CHECKED(OPT_HighlightMoveArrow); + appData.hideThinkingFromHuman= IS_CHECKED(OPT_HideThinkFromHuman); + appData.saveExtendedInfoInPGN= IS_CHECKED(OPT_SaveExtPGN); + appData.showEvalInMoveHistory= IS_CHECKED(OPT_ExtraInfoInMoveHistory); + appData.highlightMoveWithArrow=IS_CHECKED(OPT_HighlightMoveArrow); #undef IS_CHECKED @@ -728,6 +729,161 @@ BoardOptionsPopup(HWND hwnd) FreeProcInstance(lpProc); } +VariantClass +VariantWhichRadio(HWND hDlg) +{ + return (IsDlgButtonChecked(hDlg, OPT_VariantFairy) ? VariantFairy : + (IsDlgButtonChecked(hDlg, OPT_VariantGothic) ? VariantGothic : + (IsDlgButtonChecked(hDlg, OPT_VariantCrazyhouse) ? VariantCrazyhouse : + (IsDlgButtonChecked(hDlg, OPT_VariantBughouse) ? VariantBughouse : + (IsDlgButtonChecked(hDlg, OPT_VariantCourier) ? VariantCourier : + (IsDlgButtonChecked(hDlg, OPT_VariantShatranj) ? VariantShatranj : + (IsDlgButtonChecked(hDlg, OPT_VariantShogi) ? VariantShogi : + (IsDlgButtonChecked(hDlg, OPT_VariantXiangqi) ? VariantXiangqi : + (IsDlgButtonChecked(hDlg, OPT_VariantCapablanca) ? VariantCapablanca : + (IsDlgButtonChecked(hDlg, OPT_VariantTwoKings) ? VariantTwoKings : + (IsDlgButtonChecked(hDlg, OPT_VariantKnightmate) ? VariantKnightmate : + (IsDlgButtonChecked(hDlg, OPT_VariantLosers) ? VariantLosers : + (IsDlgButtonChecked(hDlg, OPT_VariantSuicide) ? VariantSuicide : + (IsDlgButtonChecked(hDlg, OPT_VariantAtomic) ? VariantAtomic : + (IsDlgButtonChecked(hDlg, OPT_VariantShatranj) ? VariantShatranj : + VariantNormal ))))))))))))))); +} + +LRESULT CALLBACK +NewVariantDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static Boolean mono; + static VariantClass v; + static COLORREF lsc, dsc, wpc, bpc, hsc, phc; + static HBITMAP pieces[3]; + static int n1_ok, n2_ok, n3_ok; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + /* Initialize the dialog items */ + switch (gameInfo.variant) { + case VariantNormal: + CheckDlgButton(hDlg, OPT_VariantNormal, TRUE); + break; + case VariantCrazyhouse: + CheckDlgButton(hDlg, OPT_VariantCrazyhouse, TRUE); + break; + case VariantBughouse: + CheckDlgButton(hDlg, OPT_VariantBughouse, TRUE); + break; + case VariantShogi: + CheckDlgButton(hDlg, OPT_VariantShogi, TRUE); + break; + case VariantXiangqi: + CheckDlgButton(hDlg, OPT_VariantXiangqi, TRUE); + break; + case VariantCapablanca: + CheckDlgButton(hDlg, OPT_VariantCapablanca, TRUE); + break; + case VariantGothic: + CheckDlgButton(hDlg, OPT_VariantGothic, TRUE); + break; + case VariantCourier: + CheckDlgButton(hDlg, OPT_VariantCourier, TRUE); + break; + case VariantKnightmate: + CheckDlgButton(hDlg, OPT_VariantKnightmate, TRUE); + break; + case VariantTwoKings: + CheckDlgButton(hDlg, OPT_VariantTwoKings, TRUE); + break; + case VariantFairy: + CheckDlgButton(hDlg, OPT_VariantFairy, TRUE); + break; + case VariantAtomic: + CheckDlgButton(hDlg, OPT_VariantAtomic, TRUE); + break; + case VariantSuicide: + CheckDlgButton(hDlg, OPT_VariantSuicide, TRUE); + break; + case VariantLosers: + CheckDlgButton(hDlg, OPT_VariantLosers, TRUE); + break; + case VariantShatranj: + CheckDlgButton(hDlg, OPT_VariantShatranj, TRUE); + break; + } + + SetDlgItemInt( hDlg, IDC_Files, -1, TRUE ); + SendDlgItemMessage( hDlg, IDC_Files, EM_SETSEL, 0, -1 ); + + SetDlgItemInt( hDlg, IDC_Ranks, -1, TRUE ); + SendDlgItemMessage( hDlg, IDC_Ranks, EM_SETSEL, 0, -1 ); + + SetDlgItemInt( hDlg, IDC_Holdings, -1, TRUE ); + SendDlgItemMessage( hDlg, IDC_Ranks, EM_SETSEL, 0, -1 ); + + n1_ok = n2_ok = n3_ok = FALSE; + + return TRUE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + case IDOK: + /* + * if we call EndDialog() after the call to ChangeBoardSize(), + * then ChangeBoardSize() does not take effect, although the new + * boardSize is saved. Go figure... + */ + EndDialog(hDlg, TRUE); + + v = VariantWhichRadio(hDlg); + + gameInfo.variant = v; + appData.variant = VariantName(v); + + appData.NrFiles = (int) GetDlgItemInt(hDlg, IDC_Files, NULL, FALSE ); + appData.NrRanks = (int) GetDlgItemInt(hDlg, IDC_Ranks, NULL, FALSE ); + appData.holdingsSize = (int) GetDlgItemInt(hDlg, IDC_Holdings, NULL, FALSE ); + + if(!n1_ok) appData.NrFiles = -1; + if(!n2_ok) appData.NrRanks = -1; + if(!n3_ok) appData.holdingsSize = -1; + + Reset(TRUE, TRUE); + + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + case IDC_Ranks: + case IDC_Files: + case IDC_Holdings: + if( HIWORD(wParam) == EN_CHANGE ) { + + GetDlgItemInt(hDlg, IDC_Files, &n1_ok, FALSE ); + GetDlgItemInt(hDlg, IDC_Ranks, &n2_ok, FALSE ); + GetDlgItemInt(hDlg, IDC_Holdings, &n3_ok, FALSE ); + + /*EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok ? TRUE : FALSE );*/ + } + return TRUE; + } + break; + } + return FALSE; +} + + +VOID +NewVariantPopup(HWND hwnd) +{ + FARPROC lpProc = MakeProcInstance((FARPROC)NewVariantDialog, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_NewVariant), hwnd, + (DLGPROC) lpProc); + FreeProcInstance(lpProc); +} + /*---------------------------------------------------------------------------*\ * * ICS Options Dialog functions @@ -1321,7 +1477,7 @@ FontOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]); SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]); SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]); - SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]); + SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]); firstPaint = FALSE; } break; @@ -1349,7 +1505,7 @@ FontOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) CopyFont(font[i][EDITTAGS_FONT], &workFont[EDITTAGS_FONT]); CopyFont(font[i][CONSOLE_FONT], &workFont[CONSOLE_FONT]); CopyFont(font[i][COMMENT_FONT], &workFont[COMMENT_FONT]); - CopyFont(font[i][MOVEHISTORY_FONT], &workFont[MOVEHISTORY_FONT]); + CopyFont(font[i][MOVEHISTORY_FONT], &workFont[MOVEHISTORY_FONT]); } /* end sad necessity */ @@ -1372,13 +1528,13 @@ FontOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) InvalidateRect(editTagsDialog, &rect, TRUE); } - if( moveHistoryDialog != NULL ) { - SendDlgItemMessage(moveHistoryDialog, IDC_MoveHistory, - WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf, - MAKELPARAM(TRUE, 0)); - InvalidateRect(editTagsDialog, NULL, TRUE); - } - + if( moveHistoryDialog != NULL ) { + SendDlgItemMessage(moveHistoryDialog, IDC_MoveHistory, + WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf, + MAKELPARAM(TRUE, 0)); + InvalidateRect(editTagsDialog, NULL, TRUE); + } + if (hwndConsole) { ChangedConsoleFont(); } @@ -1424,11 +1580,11 @@ FontOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]); break; - case OPT_ChooseMoveHistoryFont: - MyCreateFont(hDlg, &workFont[MOVEHISTORY_FONT]); - SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]); - break; - + case OPT_ChooseMoveHistoryFont: + MyCreateFont(hDlg, &workFont[MOVEHISTORY_FONT]); + SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]); + break; + case OPT_DefaultFonts: for (i=0; i= 0 ? (n) : -(n)) - -LRESULT CALLBACK EnginePlayOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_INITDIALOG: /* message: initialize dialog box */ - - /* Center the dialog over the application window */ - CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); - - /* Initialize the dialog items */ - CHECK_BOX(IDC_EpPeriodicUpdates, appData.periodicUpdates); - CHECK_BOX(IDC_EpPonder, appData.ponderNextMove); - CHECK_BOX(IDC_EpShowThinking, appData.showThinking); - CHECK_BOX(IDC_EpHideThinkingHuman, appData.hideThinkingFromHuman); - - SetDlgItemInt( hDlg, IDC_EpDrawMoveCount, appData.adjudicateDrawMoves, TRUE ); - SendDlgItemMessage( hDlg, IDC_EpDrawMoveCount, EM_SETSEL, 0, -1 ); - - SetDlgItemInt( hDlg, IDC_EpAdjudicationThreshold, INT_ABS(appData.adjudicateLossThreshold), TRUE ); - SendDlgItemMessage( hDlg, IDC_EpAdjudicationThreshold, EM_SETSEL, 0, -1 ); - - return TRUE; - - case WM_COMMAND: /* message: received a command */ - switch (LOWORD(wParam)) { - case IDOK: - /* Read changed options from the dialog box */ - PeriodicUpdatesEvent( IS_CHECKED(IDC_EpPeriodicUpdates)); - PonderNextMoveEvent( IS_CHECKED(IDC_EpPonder)); - ShowThinkingEvent( IS_CHECKED(IDC_EpShowThinking)); - appData.hideThinkingFromHuman= IS_CHECKED(IDC_EpHideThinkingHuman); - - appData.adjudicateDrawMoves = GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, NULL, FALSE ); - appData.adjudicateLossThreshold = - (int) GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, NULL, FALSE ); - - EndDialog(hDlg, TRUE); - return TRUE; - - case IDCANCEL: - EndDialog(hDlg, FALSE); - return TRUE; - - case IDC_EpDrawMoveCount: - case IDC_EpAdjudicationThreshold: - if( HIWORD(wParam) == EN_CHANGE ) { - int n1_ok; - int n2_ok; - - GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, &n1_ok, FALSE ); - GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, &n2_ok, FALSE ); - - EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok ? TRUE : FALSE ); - } - return TRUE; - } - break; - } - return FALSE; -} - -VOID EnginePlayOptionsPopup(HWND hwnd) -{ - FARPROC lpProc; - - lpProc = MakeProcInstance((FARPROC)EnginePlayOptionsDialog, hInst); - DialogBox(hInst, MAKEINTRESOURCE(DLG_EnginePlayOptions), hwnd, (DLGPROC) lpProc); - FreeProcInstance(lpProc); -} - -/*---------------------------------------------------------------------------*\ - * - * UCI Options Dialog functions - * -\*---------------------------------------------------------------------------*/ -static BOOL BrowseForFolder( const char * title, char * path ) -{ - BOOL result = FALSE; - BROWSEINFO bi; - LPITEMIDLIST pidl; - - ZeroMemory( &bi, sizeof(bi) ); - - bi.lpszTitle = title == 0 ? "Choose Folder" : title; - bi.ulFlags = BIF_RETURNONLYFSDIRS; - - pidl = SHBrowseForFolder( &bi ); - - if( pidl != 0 ) { - IMalloc * imalloc = 0; - - if( SHGetPathFromIDList( pidl, path ) ) { - result = TRUE; - } - - if( SUCCEEDED( SHGetMalloc ( &imalloc ) ) ) { - imalloc->lpVtbl->Free(imalloc,pidl); - imalloc->lpVtbl->Release(imalloc); - } - } - - return result; -} - -LRESULT CALLBACK UciOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - char buf[MAX_PATH]; - - switch (message) { - case WM_INITDIALOG: /* message: initialize dialog box */ - - /* Center the dialog over the application window */ - CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); - - /* Initialize the dialog items */ - SetDlgItemText( hDlg, IDC_PolyglotDir, appData.polyglotDir ); - SetDlgItemInt( hDlg, IDC_HashSize, appData.defaultHashSize, TRUE ); - SetDlgItemText( hDlg, IDC_PathToEGTB, appData.defaultPathEGTB ); - SetDlgItemInt( hDlg, IDC_SizeOfEGTB, appData.defaultCacheSizeEGTB, TRUE ); - CheckDlgButton( hDlg, IDC_UseBook, (BOOL) appData.usePolyglotBook ); - SetDlgItemText( hDlg, IDC_BookFile, appData.polyglotBook ); - - SendDlgItemMessage( hDlg, IDC_PolyglotDir, EM_SETSEL, 0, -1 ); - - return TRUE; - - case WM_COMMAND: /* message: received a command */ - switch (LOWORD(wParam)) { - case IDOK: - GetDlgItemText( hDlg, IDC_PolyglotDir, buf, sizeof(buf) ); - appData.polyglotDir = strdup(buf); - appData.defaultHashSize = GetDlgItemInt(hDlg, IDC_HashSize, NULL, FALSE ); - appData.defaultCacheSizeEGTB = GetDlgItemInt(hDlg, IDC_SizeOfEGTB, NULL, FALSE ); - GetDlgItemText( hDlg, IDC_PathToEGTB, buf, sizeof(buf) ); - appData.defaultPathEGTB = strdup(buf); - GetDlgItemText( hDlg, IDC_BookFile, buf, sizeof(buf) ); - appData.polyglotBook = strdup(buf); - appData.usePolyglotBook = (Boolean) IsDlgButtonChecked( hDlg, IDC_UseBook ); - - EndDialog(hDlg, TRUE); - return TRUE; - - case IDCANCEL: - EndDialog(hDlg, FALSE); - return TRUE; - - case IDC_BrowseForBook: - { - char filter[] = { - 'A','l','l',' ','F','i','l','e','s', 0, - '*','.','*', 0, - 'B','I','N',' ','F','i','l','e','s', 0, - '*','.','b','i','n', 0, - 0 }; - - OPENFILENAME ofn; - - strcpy( buf, "" ); - - ZeroMemory( &ofn, sizeof(ofn) ); - - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hDlg; - ofn.hInstance = hInst; - ofn.lpstrFilter = filter; - ofn.lpstrFile = buf; - ofn.nMaxFile = sizeof(buf); - ofn.lpstrTitle = "Choose Book"; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_HIDEREADONLY; - - if( GetOpenFileName( &ofn ) ) { - SetDlgItemText( hDlg, IDC_BookFile, buf ); - } - } - return TRUE; - - case IDC_BrowseForPolyglotDir: - if( BrowseForFolder( "Choose Polyglot Directory", buf ) ) { - SetDlgItemText( hDlg, IDC_PolyglotDir, buf ); - - strcat( buf, "\\polyglot.exe" ); - - if( GetFileAttributes(buf) == 0xFFFFFFFF ) { - MessageBox( hDlg, "Polyglot was not found in the specified folder!", "Warning", MB_OK | MB_ICONWARNING ); - } - } - return TRUE; - - case IDC_BrowseForEGTB: - if( BrowseForFolder( "Choose EGTB Directory:", buf ) ) { - SetDlgItemText( hDlg, IDC_PathToEGTB, buf ); - } - return TRUE; - - case IDC_HashSize: - case IDC_SizeOfEGTB: - if( HIWORD(wParam) == EN_CHANGE ) { - int n1_ok; - int n2_ok; - - GetDlgItemInt(hDlg, IDC_HashSize, &n1_ok, FALSE ); - GetDlgItemInt(hDlg, IDC_SizeOfEGTB, &n2_ok, FALSE ); - - EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok ? TRUE : FALSE ); - } - return TRUE; - } - break; - } - return FALSE; -} - -VOID UciOptionsPopup(HWND hwnd) -{ - FARPROC lpProc; - - lpProc = MakeProcInstance((FARPROC)UciOptionsDialog, hInst); - DialogBox(hInst, MAKEINTRESOURCE(DLG_OptionsUCI), hwnd, (DLGPROC) lpProc); - FreeProcInstance(lpProc); -} +/*---------------------------------------------------------------------------*\ + * + * Engine Options Dialog functions + * +\*---------------------------------------------------------------------------*/ +#define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y)) +#define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x)) + +#define INT_ABS( n ) ((n) >= 0 ? (n) : -(n)) + +LRESULT CALLBACK EnginePlayOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + + /* Initialize the dialog items */ + CHECK_BOX(IDC_EpPeriodicUpdates, appData.periodicUpdates); + CHECK_BOX(IDC_EpPonder, appData.ponderNextMove); + CHECK_BOX(IDC_EpShowThinking, appData.showThinking); + CHECK_BOX(IDC_EpHideThinkingHuman, appData.hideThinkingFromHuman); + + CHECK_BOX(IDC_TestClaims, appData.testClaims); + CHECK_BOX(IDC_DetectMates, appData.checkMates); + CHECK_BOX(IDC_MaterialDraws, appData.materialDraws); + CHECK_BOX(IDC_TrivialDraws, appData.trivialDraws); + + SetDlgItemInt( hDlg, IDC_EpDrawMoveCount, appData.adjudicateDrawMoves, TRUE ); + SendDlgItemMessage( hDlg, IDC_EpDrawMoveCount, EM_SETSEL, 0, -1 ); + + SetDlgItemInt( hDlg, IDC_EpAdjudicationThreshold, INT_ABS(appData.adjudicateLossThreshold), TRUE ); + SendDlgItemMessage( hDlg, IDC_EpAdjudicationThreshold, EM_SETSEL, 0, -1 ); + + SetDlgItemInt( hDlg, IDC_RuleMoves, appData.ruleMoves, TRUE ); + SendDlgItemMessage( hDlg, IDC_RuleMoves, EM_SETSEL, 0, -1 ); + + SetDlgItemInt( hDlg, IDC_DrawRepeats, INT_ABS(appData.drawRepeats), TRUE ); + SendDlgItemMessage( hDlg, IDC_DrawRepeats, EM_SETSEL, 0, -1 ); + + return TRUE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + case IDOK: + /* Read changed options from the dialog box */ + PeriodicUpdatesEvent( IS_CHECKED(IDC_EpPeriodicUpdates)); + PonderNextMoveEvent( IS_CHECKED(IDC_EpPonder)); + ShowThinkingEvent( IS_CHECKED(IDC_EpShowThinking)); + appData.hideThinkingFromHuman= IS_CHECKED(IDC_EpHideThinkingHuman); + appData.testClaims = IS_CHECKED(IDC_TestClaims); + appData.checkMates = IS_CHECKED(IDC_DetectMates); + appData.materialDraws = IS_CHECKED(IDC_MaterialDraws); + appData.trivialDraws = IS_CHECKED(IDC_TrivialDraws); + + appData.adjudicateDrawMoves = GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, NULL, FALSE ); + appData.adjudicateLossThreshold = - (int) GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, NULL, FALSE ); + appData.ruleMoves = GetDlgItemInt(hDlg, IDC_RuleMoves, NULL, FALSE ); + appData.drawRepeats = (int) GetDlgItemInt(hDlg, IDC_DrawRepeats, NULL, FALSE ); + + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + case IDC_EpDrawMoveCount: + case IDC_EpAdjudicationThreshold: + case IDC_DrawRepeats: + case IDC_RuleMoves: + if( HIWORD(wParam) == EN_CHANGE ) { + int n1_ok; + int n2_ok; + int n3_ok; + int n4_ok; + + GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, &n1_ok, FALSE ); + GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, &n2_ok, FALSE ); + GetDlgItemInt(hDlg, IDC_RuleMoves, &n3_ok, FALSE ); + GetDlgItemInt(hDlg, IDC_DrawRepeats, &n4_ok, FALSE ); + + EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok && n4_ok ? TRUE : FALSE ); + } + return TRUE; + } + break; + } + return FALSE; +} + +VOID EnginePlayOptionsPopup(HWND hwnd) +{ + FARPROC lpProc; + + lpProc = MakeProcInstance((FARPROC)EnginePlayOptionsDialog, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_EnginePlayOptions), hwnd, (DLGPROC) lpProc); + FreeProcInstance(lpProc); +} + +/*---------------------------------------------------------------------------*\ + * + * UCI Options Dialog functions + * +\*---------------------------------------------------------------------------*/ +static BOOL BrowseForFolder( const char * title, char * path ) +{ + BOOL result = FALSE; + BROWSEINFO bi; + LPITEMIDLIST pidl; + + ZeroMemory( &bi, sizeof(bi) ); + + bi.lpszTitle = title == 0 ? "Choose Folder" : title; + bi.ulFlags = BIF_RETURNONLYFSDIRS; + + pidl = SHBrowseForFolder( &bi ); + + if( pidl != 0 ) { + IMalloc * imalloc = 0; + + if( SHGetPathFromIDList( pidl, path ) ) { + result = TRUE; + } + + if( SUCCEEDED( SHGetMalloc ( &imalloc ) ) ) { + imalloc->lpVtbl->Free(imalloc,pidl); + imalloc->lpVtbl->Release(imalloc); + } + } + + return result; +} + +LRESULT CALLBACK UciOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[MAX_PATH]; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + + /* Center the dialog over the application window */ + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + + /* Initialize the dialog items */ + SetDlgItemText( hDlg, IDC_PolyglotDir, appData.polyglotDir ); + SetDlgItemInt( hDlg, IDC_HashSize, appData.defaultHashSize, TRUE ); + SetDlgItemText( hDlg, IDC_PathToEGTB, appData.defaultPathEGTB ); + SetDlgItemInt( hDlg, IDC_SizeOfEGTB, appData.defaultCacheSizeEGTB, TRUE ); + CheckDlgButton( hDlg, IDC_UseBook, (BOOL) appData.usePolyglotBook ); + SetDlgItemText( hDlg, IDC_BookFile, appData.polyglotBook ); + + SendDlgItemMessage( hDlg, IDC_PolyglotDir, EM_SETSEL, 0, -1 ); + + return TRUE; + + case WM_COMMAND: /* message: received a command */ + switch (LOWORD(wParam)) { + case IDOK: + GetDlgItemText( hDlg, IDC_PolyglotDir, buf, sizeof(buf) ); + appData.polyglotDir = strdup(buf); + appData.defaultHashSize = GetDlgItemInt(hDlg, IDC_HashSize, NULL, FALSE ); + appData.defaultCacheSizeEGTB = GetDlgItemInt(hDlg, IDC_SizeOfEGTB, NULL, FALSE ); + GetDlgItemText( hDlg, IDC_PathToEGTB, buf, sizeof(buf) ); + appData.defaultPathEGTB = strdup(buf); + GetDlgItemText( hDlg, IDC_BookFile, buf, sizeof(buf) ); + appData.polyglotBook = strdup(buf); + appData.usePolyglotBook = (Boolean) IsDlgButtonChecked( hDlg, IDC_UseBook ); + + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + case IDC_BrowseForBook: + { + char filter[] = { + 'A','l','l',' ','F','i','l','e','s', 0, + '*','.','*', 0, + 'B','I','N',' ','F','i','l','e','s', 0, + '*','.','b','i','n', 0, + 0 }; + + OPENFILENAME ofn; + + strcpy( buf, "" ); + + ZeroMemory( &ofn, sizeof(ofn) ); + + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hDlg; + ofn.hInstance = hInst; + ofn.lpstrFilter = filter; + ofn.lpstrFile = buf; + ofn.nMaxFile = sizeof(buf); + ofn.lpstrTitle = "Choose Book"; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_HIDEREADONLY; + + if( GetOpenFileName( &ofn ) ) { + SetDlgItemText( hDlg, IDC_BookFile, buf ); + } + } + return TRUE; + + case IDC_BrowseForPolyglotDir: + if( BrowseForFolder( "Choose Polyglot Directory", buf ) ) { + SetDlgItemText( hDlg, IDC_PolyglotDir, buf ); + + strcat( buf, "\\polyglot.exe" ); + + if( GetFileAttributes(buf) == 0xFFFFFFFF ) { + MessageBox( hDlg, "Polyglot was not found in the specified folder!", "Warning", MB_OK | MB_ICONWARNING ); + } + } + return TRUE; + + case IDC_BrowseForEGTB: + if( BrowseForFolder( "Choose EGTB Directory:", buf ) ) { + SetDlgItemText( hDlg, IDC_PathToEGTB, buf ); + } + return TRUE; + + case IDC_HashSize: + case IDC_SizeOfEGTB: + if( HIWORD(wParam) == EN_CHANGE ) { + int n1_ok; + int n2_ok; + + GetDlgItemInt(hDlg, IDC_HashSize, &n1_ok, FALSE ); + GetDlgItemInt(hDlg, IDC_SizeOfEGTB, &n2_ok, FALSE ); + + EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok ? TRUE : FALSE ); + } + return TRUE; + } + break; + } + return FALSE; +} + +VOID UciOptionsPopup(HWND hwnd) +{ + FARPROC lpProc; + + lpProc = MakeProcInstance((FARPROC)UciOptionsDialog, hInst); + DialogBox(hInst, MAKEINTRESOURCE(DLG_OptionsUCI), hwnd, (DLGPROC) lpProc); + FreeProcInstance(lpProc); +} diff --git a/winboard/woptions.h b/winboard/woptions.h index 294b5f9..0674317 100644 --- a/winboard/woptions.h +++ b/winboard/woptions.h @@ -32,5 +32,7 @@ VOID CommPortOptionsPopup(HWND hwnd); VOID LoadOptionsPopup(HWND hwnd); VOID SaveOptionsPopup(HWND hwnd); VOID TimeControlOptionsPopup(HWND hwnd); -VOID EnginePlayOptionsPopup(HWND hwnd); -VOID UciOptionsPopup(HWND hwnd); \ No newline at end of file +VOID EnginePlayOptionsPopup(HWND hwnd); +VOID UciOptionsPopup(HWND hwnd); + +