From 1ab928cc6fbcab5645555a1c3eef83ee32bf67f7 Mon Sep 17 00:00:00 2001 From: MrGeorgen Date: Thu, 5 Sep 2024 14:47:47 +0200 Subject: [PATCH] fixed promotion menu computer not working! --- include/chess/move.h | 2 ++ src/chess/main.c | 52 ++++++++++++++++++++++++-------------------- src/chess/move.c | 21 +++++++++++------- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/include/chess/move.h b/include/chess/move.h index f212c26..6000d07 100644 --- a/include/chess/move.h +++ b/include/chess/move.h @@ -28,5 +28,7 @@ void undoMove(uint_least64_t *board, struct move_t move, bool color); struct gameState_t makeMove(struct gameState_t gameState, struct move_t move); void initMagicTable(); bool kingInCheck(const uint_least64_t *board, const bool color); +uint_least8_t getBaseRankI(bool color); +uint_least8_t getBaseRank(bool color); #endif diff --git a/src/chess/main.c b/src/chess/main.c index 2c35086..9ef61cd 100644 --- a/src/chess/main.c +++ b/src/chess/main.c @@ -14,11 +14,6 @@ //#define START_FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" #define START_FEN "rnbqkbnr/PPppppPP/8/8/8/8/ppPPPPpp/RNBQKBNR w KQkq - 0 1" -#define drawPiece(file, rank, piece) do { \ - const RsvgRectangle rect = {xOffset + (file) * fieldSize, yOffset + (rank) * fieldSize, fieldSize, fieldSize};\ - rsvg_handle_render_document(piecesSvg[pieceToSvgI(piece)], cr, &rect, NULL); \ -} while(0) - struct drawData_t { RsvgHandle **piecesSvg; struct gameState_t *gameState; @@ -33,12 +28,19 @@ struct drawData_t { }; const uint_least8_t PROMOTION_PIECES[] = {QUEEN, KNIGHT, BISHOP, ROOK}; -static bool turn = WHITE; static uint_least8_t pieceToSvgI(struct piece_t piece) { return piece.color == WHITE ? piece.type | 8 : piece.type; } +static void drawPiece(struct drawData_t *ctx, cairo_t *cr, uint_least8_t field, struct piece_t piece) { + const uint_least8_t file = field % BOARD_SIZE; + const uint_least8_t rank = field / BOARD_SIZE; + const RsvgRectangle rect = {ctx->xOffset + file * ctx->fieldSize, ctx->yOffset + rank * ctx->fieldSize, ctx->fieldSize, ctx->fieldSize};\ + rsvg_handle_render_document(ctx->piecesSvg[pieceToSvgI(piece)], cr, &rect, NULL); +} + + static void selectCircle(cairo_t *cr, const struct drawData_t *drawData, uint_least8_t field, double radius) { uint_least8_t file = field % BOARD_SIZE; uint_least8_t rank = field / BOARD_SIZE; @@ -50,17 +52,19 @@ static void selectCircle(cairo_t *cr, const struct drawData_t *drawData, uint_le static struct gameState_t userMove(struct gameState_t gameState, struct move_t move) { gameState = makeMove(gameState, move); -#ifdef NO_COMPUTER - turn = !turn; -#else +#ifndef NO_COMPUTER move = bestMove(gameState); gameState = makeMove(gameState, move); #endif return gameState; } -static uint_least8_t promotionUiPos(uint_least8_t dst) { - return dst >= 1 ? dst - 1 : 0; +static uint_least8_t promotionUiPos(uint_least8_t dst, bool color) { + const uint_least8_t rankI = getBaseRankI(!color); + uint_least8_t uiPos = dst >= rankI + 1 ? dst - 1 : dst; + const uint_least8_t overflowI = rankI + BOARD_SIZE; + if(uiPos + LENGTH(PROMOTION_PIECES) > overflowI) uiPos = overflowI - LENGTH(PROMOTION_PIECES); + return uiPos; } static void draw_event(GtkDrawingArea *area, cairo_t *cr, int width, int height, gpointer data) { @@ -68,7 +72,8 @@ static void draw_event(GtkDrawingArea *area, cairo_t *cr, int width, int height, const double xOffset = (width - fieldSize * BOARD_SIZE) / 2; const double yOffset = (height - fieldSize * BOARD_SIZE) / 2; struct drawData_t *drawData = (struct drawData_t*)data; - const uint_least64_t *board = drawData->gameState->board; + const struct gameState_t *gameState = drawData->gameState; + const uint_least64_t *board = gameState->board; RsvgHandle **piecesSvg = drawData->piecesSvg; drawData->xOffset = xOffset; drawData->yOffset = yOffset; @@ -82,7 +87,7 @@ static void draw_event(GtkDrawingArea *area, cairo_t *cr, int width, int height, cairo_fill(cr); if(bitboardGetAllPieces(board, field)) { const struct piece_t piece = pieceAtField(board, rank * BOARD_SIZE + file); - drawPiece(file, rank, piece); + drawPiece(drawData, cr, field, piece); } } } @@ -97,14 +102,13 @@ static void draw_event(GtkDrawingArea *area, cairo_t *cr, int width, int height, } } if(drawData->selectDst != NOT_SELECTED) { - uint_least8_t uiPos = promotionUiPos(drawData->selectDst); - if(uiPos + 3 >= BOARD_SIZE) uiPos = BOARD_SIZE - LENGTH(PROMOTION_PIECES); + uint_least8_t uiPos = promotionUiPos(drawData->selectDst, gameState->color); cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); cairo_rectangle(cr, xOffset + uiPos * fieldSize, yOffset, 4 * fieldSize, fieldSize); cairo_fill(cr); for(uint_least8_t i = 0; i < LENGTH(PROMOTION_PIECES); ++i) { - const struct piece_t piece = {PROMOTION_PIECES[i], true}; - drawPiece(uiPos + i, 0, piece); + const struct piece_t piece = {PROMOTION_PIECES[i], gameState->color}; + drawPiece(drawData, cr, uiPos + i, piece); } } } @@ -121,9 +125,9 @@ static void on_click(GtkGestureClick *gesture, int n_press, double x, double y, const uint_least8_t file = adjustedX / fieldSize; const uint_least8_t rank = adjustedY / fieldSize; const uint_least8_t field = file + rank * BOARD_SIZE; - const bool promotion_field = rank == (gameState->color == WHITE ? 0 : BOARD_SIZE - 1); + const bool onPromotionField = rank == getBaseRank(!gameState->color); if(drawData->selectDst == NOT_SELECTED) { - const struct piece_t allPiece = {ALL_PIECES, turn}; + const struct piece_t allPiece = {ALL_PIECES, gameState->color}; if(bitboardGet(board, allPiece, field)) { // deactivated piece by clicking on it again if(field == drawData->clickedPiece) { @@ -146,7 +150,7 @@ static void on_click(GtkGestureClick *gesture, int n_press, double x, double y, } if(isValidDst) { const struct piece_t piece = pieceAtField(board, drawData->clickedPiece); - if(piece.type == PAWN && promotion_field) { // promotion + if(piece.type == PAWN && onPromotionField) { // promotion drawData->selectDst = field; } else { @@ -166,11 +170,11 @@ static void on_click(GtkGestureClick *gesture, int n_press, double x, double y, drawData->movesLength = 0; } } - else if(promotion_field) { - const uint_least8_t uiPos = promotionUiPos(drawData->selectDst); - const uint_least8_t i = file - uiPos; + else if(onPromotionField) { + const uint_least8_t uiPos = promotionUiPos(drawData->selectDst, gameState->color); + const uint_least8_t i = field - uiPos; if(i >= LENGTH(PROMOTION_PIECES)) return; - const uint_least8_t dstPiece = PROMOTION_PIECES[file - uiPos]; + const uint_least8_t dstPiece = PROMOTION_PIECES[i]; const uint_least8_t capturedPiece = pieceAtField(board, drawData->selectDst).type; const struct move_t move = {drawData->clickedPiece, drawData->selectDst, 0, PAWN, dstPiece, capturedPiece}; *gameState = userMove(*gameState, move); diff --git a/src/chess/move.c b/src/chess/move.c index e31b624..e6bebaa 100644 --- a/src/chess/move.c +++ b/src/chess/move.c @@ -133,17 +133,21 @@ bool kingInCheck(const uint_least64_t *board, const bool color) { return inCheck(board, bitboardGetMask(board, king), color); } -static uint_least8_t getCastleRankI(bool color) { +uint_least8_t getBaseRank(bool color) { if(color == WHITE) { - return (BOARD_SIZE - 1) * BOARD_SIZE; + return BOARD_SIZE - 1; } return 0; } +uint_least8_t getBaseRankI(bool color) { + return getBaseRank(color) * BOARD_SIZE; +} + static void castleMoveRook(uint_least64_t *board, uint_least8_t spezialMove, bool color, bool undo) { if(spezialMove == SHORT_CASTLE || spezialMove == LONG_CASTLE) { - const uint_least8_t rookSrc = getCastleRankI(color) + (spezialMove == SHORT_CASTLE ? BOARD_SIZE - 1 : 0); - const uint_least8_t rookDst = getCastleRankI(color) + (spezialMove == SHORT_CASTLE ? 5 : 3); + const uint_least8_t rookSrc = getBaseRankI(color) + (spezialMove == SHORT_CASTLE ? BOARD_SIZE - 1 : 0); + const uint_least8_t rookDst = getBaseRankI(color) + (spezialMove == SHORT_CASTLE ? 5 : 3); const struct piece_t rook = {ROOK, color}; bitboardSet(board, rook, undo ? rookSrc : rookDst); bitboardClear(board, rook, undo ? rookDst : rookSrc); @@ -226,7 +230,8 @@ static void movePawn(struct addMoveCtx_t ctx, bool color, uint_least8_t src, uin struct move_t *moves = ctx.moves; uint_least8_t *movesLength = ctx.movesLength; const struct piece_t piece = {PAWN, color}; - if(promotion && (color == WHITE && dst < BOARD_SIZE || color == BLACK && dst >= BOARD_SIZE * (BOARD_SIZE - 1))) { + const uint_least8_t rankI = getBaseRankI(color); + if(promotion && (color == WHITE && dst < rankI || color == BLACK && dst >= rankI)) { for(uint_least8_t promotionPiece = QUEEN; promotionPiece < PAWN; ++promotionPiece) { addMove(ctx, piece, src, dst, spezialMove, promotionPiece); } @@ -248,7 +253,7 @@ uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece addPreGenMoves(addmoveCtx, KING_MOVES, src, piece); const struct castle_t canCastle = gameState.canCastle[piece.color]; const uint_least64_t allPiecesMask = bitboardMaskAllPieces(board); - const uint_least8_t rankShift = piece.color == WHITE ? BOARD_SIZE * (BOARD_SIZE - 1) : 0; + const uint_least8_t rankShift = getBaseRankI(piece.color); const uint_least64_t shortCastleMask = (uint_least64_t)0b11 << (5 + rankShift); const uint_least64_t shortCastleCheckMask = (uint_least64_t)0b11 << (4 + rankShift); const uint_least64_t longCastleMask = (uint_least64_t)0b111 << (1 + rankShift); @@ -363,7 +368,7 @@ struct gameState_t makeMove(struct gameState_t gameState, struct move_t move) { canCastleCurrentPlayer->shortCastle = false; } else { - setCastleInfo(canCastleCurrentPlayer, move.src - getCastleRankI(gameState.color)); + setCastleInfo(canCastleCurrentPlayer, move.src - getBaseRankI(gameState.color)); } } } @@ -371,7 +376,7 @@ struct gameState_t makeMove(struct gameState_t gameState, struct move_t move) { // if the rook is captured struct castle_t *canCastleOther = gameState.canCastle + !gameState.color; if(canCastleOther->longCastle || canCastleOther->shortCastle) { - setCastleInfo(canCastleOther, move.dst - getCastleRankI(!gameState.color)); + setCastleInfo(canCastleOther, move.dst - getBaseRankI(!gameState.color)); } } {