X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=winboard%2Fwinboard.c;h=a96aeb6cd25d70e01a3c5f7aa54da42624979aea;hb=93077be9f3009b8eb6ad64067f31d000aaf284c3;hp=d2facc23f4c4559f66aeaf12a1325b6ef21c5308;hpb=056614196635a4730170261fe0e638191f14c620;p=xboard.git diff --git a/winboard/winboard.c b/winboard/winboard.c index d2facc2..a96aeb6 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -92,6 +92,9 @@ void InitEngineUCI( const char * iniDir, ChessProgramState * cps ); void mysrandom(unsigned int seed); extern int whiteFlag, blackFlag; +Boolean flipClock = FALSE; + +void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber); typedef struct { ChessSquare piece; @@ -135,7 +138,7 @@ char installDir[MSG_SIZ]; BoardSize boardSize; BOOLEAN chessProgram; static int boardX, boardY, consoleX, consoleY, consoleW, consoleH; -static int squareSize, lineGap; +static int squareSize, lineGap, minorSize; static int winWidth, winHeight; static RECT messageRect, whiteRect, blackRect; static char messageText[MESSAGE_TEXT_MAX]; @@ -168,6 +171,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]; @@ -420,7 +424,7 @@ VOID EngineOutputPopDown(); BOOL EngineOutputIsUp(); VOID EngineOutputUpdate( FrontEndProgramStats * stats ); -VOID GothicPopUp(char *title); +VOID GothicPopUp(char *title, char up); /* * Setting "frozen" should disable all user input other than deleting * the window. We do this while engines are initializing themselves. @@ -584,6 +588,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"); @@ -690,13 +695,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine) if( gameInfo.variant != VariantFischeRandom ) { EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED ); } -#ifdef FAIRY -#ifdef GOTHIC - /* [HGM] Gothic licensing requirement */ - if(gameInfo.variant == VariantGothic) - GothicPopUp(GOTHIC); -#endif // GOTHIC -#endif // FAIRY + if (hwndConsole) { #if AOT_CONSOLE SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, @@ -1163,11 +1162,19 @@ 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 }, - { "matchPause", ArgInt, (LPVOID) &appData.matchPause, FALSE }, + { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE }, + { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE }, + { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE }, + { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE }, + { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE }, + { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE }, { "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 +1882,20 @@ 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; + appData.allWhite = FALSE; + appData.upsideDown = FALSE; #ifdef ZIPPY appData.zippyTalk = ZIPPY_TALK; @@ -2285,37 +2299,33 @@ enum { PM_WN = (int) WhiteKnight, PM_WB = (int) WhiteBishop, PM_WR = (int) WhiteRook, -#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, -#endif PM_WQ = (int) WhiteQueen, + PM_WF = (int) WhiteFerz, + PM_WW = (int) WhiteWazir, + PM_WE = (int) WhiteAlfil, + PM_WM = (int) WhiteMan, + PM_WO = (int) WhiteCannon, + PM_WU = (int) WhiteUnicorn, + PM_WH = (int) WhiteNightrider, + PM_WA = (int) WhiteCardinal, + PM_WC = (int) WhiteMarshall, + PM_WG = (int) WhiteGrasshopper, PM_WK = (int) WhiteKing, PM_BP = (int) BlackPawn, PM_BN = (int) BlackKnight, PM_BB = (int) BlackBishop, PM_BR = (int) BlackRook, -#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, -#endif PM_BQ = (int) BlackQueen, + PM_BF = (int) BlackFerz, + PM_BW = (int) BlackWazir, + PM_BE = (int) BlackAlfil, + PM_BM = (int) BlackMan, + PM_BO = (int) BlackCannon, + PM_BU = (int) BlackUnicorn, + PM_BH = (int) BlackNightrider, + PM_BA = (int) BlackCardinal, + PM_BC = (int) BlackMarshall, + PM_BG = (int) BlackGrasshopper, PM_BK = (int) BlackKing }; @@ -2324,39 +2334,14 @@ static HBITMAP hPieceMask[(int) EmptySquare]; static HBITMAP hPieceFace[(int) EmptySquare]; static int fontBitmapSquareSize = 0; static char pieceToFontChar[(int) EmptySquare] = - { 'p', 'n', 'b', 'r', -#ifdef FAIRY + { 'p', 'n', 'b', 'r', 'q', 'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k', -#endif - 'q', 'k', 'o', 'm', 'v', 't', -#ifdef FAIRY + 'k', 'o', 'm', 'v', 't', 'w', 'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l', -#endif - 'w', 'l' }; - -static BOOL SetPieceToFontCharTable( const char * map ) -{ - BOOL result = FALSE; int NrPieces; - - if( map != NULL && (NrPieces=strlen(map)) <= (int) EmptySquare - && NrPieces >= 12 && !(NrPieces&1)) { - int i; /* [HGM] Accept even length from 12 to 32 */ - - for( i=0; i<(int) EmptySquare; i++ ) pieceToFontChar[i] = 0; - for( i=0; i= 0 && appData.overrideLineGap <= 5 ) { lineGap = appData.overrideLineGap; @@ -3069,7 +3057,12 @@ InitDrawingSizes(BoardSize boardSize, int flags) } } - if (boardSize == oldBoardSize) return; +#ifdef GOTHIC + /* [HGM] Gothic licensing requirement */ + GothicPopUp( GOTHIC, gameInfo.variant == VariantGothic ); +#endif + +/* if (boardSize == oldBoardSize) return; [HGM] variant might have changed */ oldBoardSize = boardSize; oldTinyLayout = tinyLayout; @@ -3087,55 +3080,151 @@ InitDrawingSizes(BoardSize boardSize, int flags) pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s"); pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s"); pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s"); - pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s"); pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s"); pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o"); pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o"); pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o"); pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o"); - pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o"); pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o"); pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w"); pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w"); pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w"); pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w"); - pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w"); pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w"); -#ifdef FAIRY + if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) { + pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s"); + pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o"); + pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w"); + } else { + pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s"); + pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o"); + pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w"); + } if(squareSize==72 || squareSize==49) { /* experiment with some home-made bitmaps */ + pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s"); + pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o"); + pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w"); + pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s"); + pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o"); + pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w"); + pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s"); + pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o"); + pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w"); + pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s"); + pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o"); + pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w"); + pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s"); + pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o"); + pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w"); pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s"); - pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s"); - pieceBitmap[0][WhiteFairyPawn] = DoLoadBitmap(hInst, "f", squareSize, "s"); - pieceBitmap[0][WhiteFairyKnight] = DoLoadBitmap(hInst, "h", squareSize, "s"); - pieceBitmap[0][WhiteFairyBishop] = DoLoadBitmap(hInst, "e", squareSize, "s"); - pieceBitmap[0][WhiteFairyRook] = DoLoadBitmap(hInst, "w", squareSize, "s"); - pieceBitmap[0][WhiteFairyQueen] = DoLoadBitmap(hInst, "g", squareSize, "s"); - pieceBitmap[0][WhiteFairyCardinal] = DoLoadBitmap(hInst, "u", squareSize, "s"); - pieceBitmap[0][WhiteFairyMarshall] = DoLoadBitmap(hInst, "o", squareSize, "s"); - pieceBitmap[0][WhiteFairyKing] = DoLoadBitmap(hInst, "m", squareSize, "s"); pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o"); - pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o"); - pieceBitmap[1][WhiteFairyPawn] = DoLoadBitmap(hInst, "f", squareSize, "o"); - pieceBitmap[1][WhiteFairyKnight] = DoLoadBitmap(hInst, "h", squareSize, "o"); - pieceBitmap[1][WhiteFairyBishop] = DoLoadBitmap(hInst, "e", squareSize, "o"); - pieceBitmap[1][WhiteFairyRook] = DoLoadBitmap(hInst, "w", squareSize, "o"); - pieceBitmap[1][WhiteFairyQueen] = DoLoadBitmap(hInst, "g", squareSize, "o"); - pieceBitmap[1][WhiteFairyCardinal] = DoLoadBitmap(hInst, "u", squareSize, "o"); - pieceBitmap[1][WhiteFairyMarshall] = DoLoadBitmap(hInst, "o", squareSize, "o"); - pieceBitmap[1][WhiteFairyKing] = DoLoadBitmap(hInst, "m", squareSize, "o"); pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w"); + if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */ + pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "wp", squareSize, "s"); + pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "wp", squareSize, "o"); + pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "w", squareSize, "w"); + pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s"); + pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o"); + pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w"); + pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s"); + pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o"); + pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w"); + pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s"); + pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o"); + pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w"); + } else { + pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s"); + pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o"); + pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w"); + pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s"); + pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o"); + pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w"); + pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s"); + pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o"); + pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w"); + pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "l", squareSize, "s"); + pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "l", squareSize, "o"); + pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "l", squareSize, "w"); + } + if(gameInfo.variant != VariantCrazyhouse && gameInfo.variant != VariantShogi) { + pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s"); + pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o"); pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w"); - pieceBitmap[2][WhiteFairyPawn] = DoLoadBitmap(hInst, "f", squareSize, "w"); - pieceBitmap[2][WhiteFairyKnight] = DoLoadBitmap(hInst, "h", squareSize, "w"); - pieceBitmap[2][WhiteFairyBishop] = DoLoadBitmap(hInst, "e", squareSize, "w"); - pieceBitmap[2][WhiteFairyRook] = DoLoadBitmap(hInst, "w", squareSize, "w"); - pieceBitmap[2][WhiteFairyQueen] = DoLoadBitmap(hInst, "g", squareSize, "w"); - pieceBitmap[2][WhiteFairyCardinal] = DoLoadBitmap(hInst, "u", squareSize, "w"); - pieceBitmap[2][WhiteFairyMarshall] = DoLoadBitmap(hInst, "o", squareSize, "w"); - pieceBitmap[2][WhiteFairyKing] = DoLoadBitmap(hInst, "m", squareSize, "w"); + } else { + pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "s"); + pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "o"); + pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "w"); + } + } else { /* other size, no special bitmaps available. Use smaller symbols */ + if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize; + else minorSize = sizeInfo[(int)boardSize - 2].squareSize; + pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s"); + pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o"); + pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w"); + pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s"); + pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o"); + pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w"); + pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "r", minorSize, "s"); + pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "r", minorSize, "o"); + pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "r", minorSize, "w"); + pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s"); + pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o"); + pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w"); + } + if(gameInfo.variant == VariantShogi && squareSize == 58) + /* special Shogi support in this size */ + { for (i=0; i<=2; i++) { /* replace all bitmaps */ + for (piece = WhitePawn; + (int) piece < (int) BlackPawn; + piece = (ChessSquare) ((int) piece + 1)) { + if (pieceBitmap[i][piece] != NULL) + DeleteObject(pieceBitmap[i][piece]); + } + } + pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o"); + pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o"); + pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o"); + pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o"); + pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o"); + pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o"); + pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o"); + pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o"); + pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "su", squareSize, "o"); + pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o"); + pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o"); + pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "sc", squareSize, "o"); + pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o"); + pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o"); + pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o"); + pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o"); + pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o"); + pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o"); + pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o"); + pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o"); + pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o"); + pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o"); + pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "su", squareSize, "o"); + pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o"); + pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o"); + pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "sc", squareSize, "o"); + pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o"); + pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o"); + pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w"); + pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w"); + pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w"); + pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w"); + pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w"); + pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w"); + pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w"); + pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w"); + pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "sp", squareSize, "w"); + pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w"); + pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w"); + pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "sr", squareSize, "w"); + pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w"); + pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w"); + minorSize = 0; } -#endif - } HBITMAP @@ -3189,7 +3278,7 @@ DrawCoordsOnDC(HDC hdc) oldFont = SelectObject(hdc, font[boardSize][COORD_FONT]->hf); y = boardRect.top + lineGap; - x = boardRect.left + lineGap; + x = boardRect.left + lineGap + gameInfo.holdingsWidth*(squareSize + lineGap); SetTextAlign(hdc, TA_LEFT|TA_TOP); for (i = 0; i < BOARD_HEIGHT; i++) { @@ -3201,7 +3290,7 @@ DrawCoordsOnDC(HDC hdc) start = flipView ? 12-BOARD_WIDTH : 12; SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM); - for (i = 0; i < BOARD_WIDTH; i++) { + for (i = 0; i < BOARD_RGHT - BOARD_LEFT; i++) { str[0] = ranks[start + i]; ExtTextOut(hdc, x + squareSize - 2, y - 1, 0, NULL, str, 1, NULL); x += squareSize + lineGap; @@ -3284,6 +3373,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, { HBITMAP oldBitmap; HBRUSH oldBrush; + int tmpSize; if (appData.blindfold) return; @@ -3323,21 +3413,39 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, sqcolor ? SRCCOPY : NOTSRCCOPY); } else { - if (color) { + tmpSize = squareSize; + if(minorSize && + (piece >= (int)WhiteNightrider && piece <= WhiteGrasshopper || + piece >= (int)BlackNightrider && piece <= BlackGrasshopper) ) { + /* [HGM] no bitmap available for promoted pieces in Crazyhouse */ + /* Bitmaps of smaller size are substituted, but we have to align them */ + x += (squareSize - minorSize)>>1; + y += squareSize - minorSize - 2; + tmpSize = minorSize; + } + if (color || appData.allWhite ) { oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, WHITE_PIECE)); - oldBrush = SelectObject(hdc, whitePieceBrush); - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); + if( color ) + oldBrush = SelectObject(hdc, whitePieceBrush); + else oldBrush = SelectObject(hdc, blackPieceBrush); + if(appData.upsideDown && !color) + StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A); + else + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A); #if 0 /* Use black piece color for outline of white pieces */ /* Not sure this looks really good (though xboard does it). Maybe better to have another selectable color, default black */ SelectObject(hdc, blackPieceBrush); /* could have own brush */ SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE)); - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A); #else /* Use black for outline of white pieces */ SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE)); - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, SRCAND); + if(appData.upsideDown && !color) + StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, SRCAND); + else + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, SRCAND); #endif } else { #if 0 @@ -3348,15 +3456,18 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, Maybe better to have another selectable color, default medium gray? */ oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, BLACK_PIECE)); oldBrush = SelectObject(hdc, whitePieceBrush); /* could have own brush */ - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A); SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE)); SelectObject(hdc, blackPieceBrush); - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A); #else /* Use square color for details of black pieces */ oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE)); oldBrush = SelectObject(hdc, blackPieceBrush); - BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A); + if(appData.upsideDown) + StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A); + else + BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A); #endif } SelectObject(hdc, oldBrush); @@ -3750,13 +3861,37 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc) square_color = ((column + row) % 2) == 1; if(!strcmp(appData.variant, "xiangqi") ) { - square_color = 1; - if( (row < 3 || row > 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 +3919,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 +4040,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 +4149,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 +4197,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 +4268,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 +4385,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) { @@ -4261,18 +4417,22 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (y == -2) { /* Downclick vertically off board; check if on clock */ if (PtInRect((LPRECT) &whiteRect, pt)) { - if (gameMode == EditPosition) { + if (gameMode == EditPosition) { SetWhiteToPlayEvent(); } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) { CallFlagEvent(); - } + } else if (gameMode == EditGame) { + AdjustClock(flipClock, -1); + } } else if (PtInRect((LPRECT) &blackRect, pt)) { if (gameMode == EditPosition) { SetBlackToPlayEvent(); } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) { CallFlagEvent(); + } else if (gameMode == EditGame) { + AdjustClock(!flipClock, -1); } } if (!appData.highlightLastMove) { @@ -4283,54 +4443,68 @@ 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 + /* EditPosition, empty square, or different color piece; + click-click move is possible */ + ) { 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 */ - ChessSquare pdown, pup; - pdown = boards[currentMove][fromY][fromX]; - pup = boards[currentMove][y][x]; - if (gameMode == EditPosition || /* [HGM] max piece > King! */ - !((WhitePawn <= pdown && pdown < BlackPawn && - WhitePawn <= pup && pup < BlackPawn) || - (BlackPawn <= pdown && pdown < EmptySquare && - BlackPawn <= pup && pup < EmptySquare))) { - /* EditPosition, empty square, or different color piece; - click-click move is possible */ + } 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 ! */ + { /* [HGM] now always do UserMoveTest(), and check colors there */ 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); - } - } - if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); - fromX = fromY = -1; - break; + /* [HGM] UserMoveEvent requires two calls now, + to make sure move is legal before showing promotion popup */ + moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR); + if(moveType != ImpossibleMove) { + /* [HGM] We use PromotionToKnight in Shogi to indicate frorced promotion */ + if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight || + (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) && + appData.alwaysPromoteToQueen) { + FinishMove(moveType, fromX, fromY, toX, toY, 'q'); + if (!appData.highlightLastMove) { + ClearHighlights(); + DrawPosition(forceFullRepaint || FALSE, NULL); + } + } else + if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) { + 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); + } + } + break; + } + if (gotPremove) { + /* [HGM] it seemed that braces were missing here */ + SetPremoveHighlights(fromX, fromY, toX, toY); + fromX = fromY = -1; + break; + } } ClearHighlights(); DrawPosition(forceFullRepaint || FALSE, NULL); @@ -4372,21 +4546,28 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* 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) { + /* [HGM] use move type to determine if move is promotion. + Knight is Shogi kludge for mandatory promotion, Queen means choice */ + if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight || + (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) && + appData.alwaysPromoteToQueen) + FinishMove(moveType, fromX, fromY, toX, toY, 'q'); + else + if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) { + 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 +4591,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; } } @@ -4438,6 +4620,14 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (appData.highlightDragging) { ClearHighlights(); } + if(y == -2) { + /* [HGM] right mouse button in clock area edit-game mode ups clock */ + if (PtInRect((LPRECT) &whiteRect, pt)) { + if (gameMode == EditGame) AdjustClock(flipClock, 1); + } else if (PtInRect((LPRECT) &blackRect, pt)) { + if (gameMode == EditGame) AdjustClock(!flipClock, 1); + } + } DrawPosition(TRUE, NULL); switch (gameMode) { @@ -4466,7 +4656,10 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Just have one menu, on the right button. Windows users don't think to try the middle one, and sometimes other software steals it, or it doesn't really exist. */ - MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1); + if(gameInfo.variant != VariantShogi) + MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1); + else + MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1); #endif } break; @@ -4567,17 +4760,32 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) (!appData.testLegality || gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway) ? SW_SHOW : SW_HIDE); -#ifdef FAIRY - /* [HGM] Only allow C & A promotions in Capablanca Chess */ + /* [HGM] Only allow C & A promotions if these pieces are defined */ ShowWindow(GetDlgItem(hDlg, PB_Archbishop), - (gameInfo.variant == VariantCapablanca || - gameInfo.variant == VariantGothic) ? + (PieceToChar(WhiteCardinal) >= 'A' && + PieceToChar(WhiteCardinal) != '~' || + PieceToChar(BlackCardinal) >= 'A' && + PieceToChar(BlackCardinal) != '~' ) ? SW_SHOW : SW_HIDE); ShowWindow(GetDlgItem(hDlg, PB_Chancellor), - (gameInfo.variant == VariantCapablanca || - gameInfo.variant == VariantGothic) ? + (PieceToChar(WhiteMarshall) >= 'A' && + PieceToChar(WhiteMarshall) != '~' || + PieceToChar(BlackMarshall) >= 'A' && + PieceToChar(BlackMarshall) != '~' ) ? + SW_SHOW : SW_HIDE); + /* [HGM] Hide B & R button in Shogi, use Q as promote, N as defer */ + ShowWindow(GetDlgItem(hDlg, PB_Rook), + gameInfo.variant != VariantShogi ? + SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hDlg, PB_Bishop), + gameInfo.variant != VariantShogi ? + SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hDlg, IDC_Yes), + gameInfo.variant == VariantShogi ? + SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hDlg, IDC_No), + gameInfo.variant == VariantShogi ? SW_SHOW : SW_HIDE); -#endif return TRUE; case WM_COMMAND: /* message: received a command */ @@ -4588,33 +4796,35 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) DrawPosition(FALSE, NULL); return TRUE; case PB_King: - promoChar = 'k'; + promoChar = PieceToChar(BlackKing); break; case PB_Queen: - promoChar = 'q'; + promoChar = gameInfo.variant == VariantShogi ? '+' : PieceToChar(BlackQueen); break; case PB_Rook: - promoChar = 'r'; + promoChar = PieceToChar(BlackRook); break; case PB_Bishop: - promoChar = 'b'; + promoChar = PieceToChar(BlackBishop); break; -#ifdef FAIRY case PB_Chancellor: - promoChar = 'c'; + promoChar = PieceToChar(BlackMarshall); break; case PB_Archbishop: - promoChar = 'a'; + promoChar = PieceToChar(BlackCardinal); break; -#endif case PB_Knight: - promoChar = 'n'; + promoChar = gameInfo.variant == VariantShogi ? '=' : PieceToChar(BlackKnight); break; default: 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 +5041,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; @@ -5169,6 +5383,11 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) DrawPosition(FALSE, NULL); break; + case IDM_FlipClock: + flipClock = !flipClock; + DisplayBothClocks(); + break; + case IDM_GeneralOptions: GeneralOptionsPopup(hwnd); DrawPosition(TRUE, NULL); @@ -5318,6 +5537,36 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) fromX = fromY = -1; break; + case EP_WhiteFerz: + EditPositionMenuEvent(WhiteFerz, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteWazir: + EditPositionMenuEvent(WhiteWazir, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteAlfil: + EditPositionMenuEvent(WhiteAlfil, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteCannon: + EditPositionMenuEvent(WhiteCannon, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteCardinal: + EditPositionMenuEvent(WhiteCardinal, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_WhiteMarshall: + EditPositionMenuEvent(WhiteMarshall, fromX, fromY); + fromX = fromY = -1; + break; + case EP_WhiteKing: EditPositionMenuEvent(WhiteKing, fromX, fromY); fromX = fromY = -1; @@ -5348,6 +5597,36 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) fromX = fromY = -1; break; + case EP_BlackFerz: + EditPositionMenuEvent(BlackFerz, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackWazir: + EditPositionMenuEvent(BlackWazir, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackAlfil: + EditPositionMenuEvent(BlackAlfil, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackCannon: + EditPositionMenuEvent(BlackCannon, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackCardinal: + EditPositionMenuEvent(BlackCardinal, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_BlackMarshall: + EditPositionMenuEvent(BlackMarshall, fromX, fromY); + fromX = fromY = -1; + break; + case EP_BlackKing: EditPositionMenuEvent(BlackKing, fromX, fromY); fromX = fromY = -1; @@ -5373,6 +5652,16 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) fromX = fromY = -1; break; + case EP_Promote: + EditPositionMenuEvent(PromotePiece, fromX, fromY); + fromX = fromY = -1; + break; + + case EP_Demote: + EditPositionMenuEvent(DemotePiece, fromX, fromY); + fromX = fromY = -1; + break; + case DP_Pawn: DropMenuEvent(WhitePawn, fromX, fromY); fromX = fromY = -1; @@ -6507,6 +6796,8 @@ ErrorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) } #ifdef GOTHIC +HWND gothicDialog = NULL; + LRESULT CALLBACK GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { @@ -6527,7 +6818,7 @@ GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) and it doesn't work when you resize the dialog. For now, just give it a default position. */ - + gothicDialog = hDlg; SetWindowText(hDlg, errorTitle); hwndText = GetDlgItem(hDlg, OPT_ErrorText); SetDlgItemText(hDlg, OPT_ErrorText, errorMessage); @@ -6550,7 +6841,7 @@ GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) } VOID -GothicPopUp(char *title) +GothicPopUp(char *title, char up) { FARPROC lpProc; char *p, *q; @@ -6558,11 +6849,16 @@ GothicPopUp(char *title) strncpy(errorTitle, title, sizeof(errorTitle)); errorTitle[sizeof(errorTitle) - 1] = '\0'; - + + if(up && gothicDialog == NULL) { lpProc = MakeProcInstance((FARPROC)GothicDialog, hInst); CreateDialog(hInst, MAKEINTRESOURCE(DLG_Error), hwndMain, (DLGPROC)lpProc); FreeProcInstance(lpProc); + } else if(!up && gothicDialog != NULL) { + DestroyWindow(gothicDialog); + gothicDialog = NULL; + } } #endif @@ -7278,6 +7574,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) { @@ -8544,7 +8871,7 @@ DisplayWhiteClock(long timeRemaining, int highlight) char *flag = whiteFlag && gameMode == TwoMachinesPlay ? "(!)" : ""; if (!IsIconic(hwndMain)) { - DisplayAClock(hdc, timeRemaining, highlight, &whiteRect, "White", flag); + DisplayAClock(hdc, timeRemaining, highlight, flipClock ? &blackRect : &whiteRect, "White", flag); } if (highlight && iconCurrent == iconBlack) { iconCurrent = iconWhite; @@ -8566,7 +8893,7 @@ DisplayBlackClock(long timeRemaining, int highlight) hdc = GetDC(hwndMain); if (!IsIconic(hwndMain)) { - DisplayAClock(hdc, timeRemaining, highlight, &blackRect, "Black", flag); + DisplayAClock(hdc, timeRemaining, highlight, flipClock ? &whiteRect : &blackRect, "Black", flag); } if (highlight && iconCurrent == iconWhite) { iconCurrent = iconBlack;