Sun, 02 Aug 2026 15:08:43 +0200
fix regression: pieces could not threaten fields when pinned
relates to #960
| src/chess/rules.c | file | annotate | diff | comparison | revisions | |
| src/chess/rules.h | file | annotate | diff | comparison | revisions |
--- a/src/chess/rules.c Sat Aug 01 11:26:48 2026 +0200 +++ b/src/chess/rules.c Sun Aug 02 15:08:43 2026 +0200 @@ -142,6 +142,7 @@ piece_color(move->piece), candidates, &ccount)) { unsigned int ambrows = 0, ambfiles = 0, ambpiece = 0; for (size_t i = 0 ; i < ccount ; i++) { + // TODO: check if we need to discard pinned pieces here if (candidates[i].piece == move->piece) { ambpiece++; if (candidates[i].fromrow == move->fromrow) { @@ -548,11 +549,15 @@ return INVALID_MOVE_SYNTAX; } - /* cancel processing to save resources */ - if (!chkrules) { - return RULES_VIOLATED; + return chkrules ? VALID_MOVE_SEMANTICS : RULES_VIOLATED; +} + +int validate_move(const GameState *gamestate, const Move *move) { + int result = validate_move_rules(gamestate, move); + if (result != VALID_MOVE_SEMANTICS) { + return result; } - + /* test if the move would expose our own king */ GameState simulation = gamestate_copy_sim(gamestate); Move simmove = *move; @@ -570,9 +575,7 @@ } } } - int result = VALID_MOVE_SEMANTICS; if (is_covered(&simulation, kingrow, kingfile, oppcolor)) { - gamestate_cleanup(&simulation); if (piece_type(move->piece) == KING) { result = KING_MOVES_INTO_CHECK; } else { @@ -585,15 +588,6 @@ } gamestate_cleanup(&simulation); - return result; -} - -int validate_move(const GameState *gamestate, const Move *move) { - int result = validate_move_rules(gamestate, move); - if (result != VALID_MOVE_SEMANTICS) { - return result; - } - /* validate check and checkmate flags */ int cocm = determine_check_or_checkmate(gamestate, move); if (cocm == 2) { @@ -609,7 +603,6 @@ } else if (move->check) { return INVALID_CHECK; } - return VALID_MOVE_SEMANTICS; } @@ -675,6 +668,7 @@ Color color, Move *threats, size_t *threatcount) { /* simulate a capturing move on the target position */ + // TODO: this does NOT disregard the pin, as stated in the spec! Color opcolor = opponent_color(color); GameState simulation = gamestate_copy_sim(gamestate); if (piece_color(piece_at(&simulation, row, file)) != opcolor) {
--- a/src/chess/rules.h Sat Aug 01 11:26:48 2026 +0200 +++ b/src/chess/rules.h Sun Aug 02 15:08:43 2026 +0200 @@ -288,7 +288,9 @@ } /** - * Determines a list of possible moves to the specified field. + * Determines a list of theoretically possible moves to the specified field. + * + * This will also list moves for pieces that are actually pinned. * * The out-parameters may both be NULL, but if any of them is set, the other * must be set, too. @@ -301,7 +303,7 @@ * (must be large enough, 16 is always enough) * @param movecount a pointer where the number of moves is stored * @return true, if any piece of the specified color can move to the specified - * field + * field regardless of being pinned */ bool get_candidates(const GameState *gamestate, Row row, File file, Color color, Move* moves, size_t* movecount);