diff -r 835776e0338f -r 05fc8a454700 src/chess/rules.c --- a/src/chess/rules.c Fri Jul 24 12:53:58 2026 +0200 +++ b/src/chess/rules.c Fri Jul 24 15:35:06 2026 +0200 @@ -680,27 +680,28 @@ Move threats[16], *threat = NULL; uint8_t threatcount; + /* determine all threats and sort out the unreal threats on our own */ if (get_threats(gamestate, move->torow, move->tofile, color, threats, &threatcount)) { - int reason = PIECE_NOT_FOUND; + bool found = false; /* find threats for the specified position */ - for (uint8_t i = 0 ; i < threatcount ; i++) { + for (uint8_t i = 0 ; i < threatcount ; i++) { if (threats[i].piece == move->piece && (move->fromrow == POS_UNSPECIFIED || move->fromrow == threats[i].fromrow) && (move->fromfile == POS_UNSPECIFIED || move->fromfile == threats[i].fromfile)) { - if (threat) { - return AMBIGUOUS_MOVE; - } else { - /* found threat is no real threat */ - // TODO: why didn't we call get_real_threats() ? - if (is_pinned(gamestate, &(threats[i]))) { - reason = incheck?KING_IN_CHECK: - (piece==KING?KING_MOVES_INTO_CHECK:PIECE_PINNED); + /* found a threat, here it does not matter if it's valid! */ + found = true; + + /* discard pinned pieces */ + if (!is_pinned(gamestate, &(threats[i]))) { + if (threat) { + /* we've already found a valid threat */ + return AMBIGUOUS_MOVE; } else { threat = &(threats[i]); } @@ -710,7 +711,17 @@ /* can't threaten specified position */ if (!threat) { - return reason; + if (found) { + if (piece == KING) { + return KING_MOVES_INTO_CHECK; + } else if (incheck) { + return KING_IN_CHECK; + } else { + return PIECE_PINNED; + } + } else { + return PIECE_NOT_FOUND; + } } /* found a threat, copy the source location */