MoveError

enum class chesscxx::MoveError : uint8_t

Represents various reasons a move may be considered invalid.

Values:

enumerator kKingOrRookMoved

Castling failed because the king or rook has already moved.

enumerator kKingPathBlocked

Castling is blocked by pieces in the king’s path.

enumerator kRookPathBlocked

Castling is blocked by pieces in the rook’s path.

enumerator kKingPathUnderAttack

Castling is not allowed because the king would move through or into a square under attack.

enumerator kNoValidOrigin

No valid origin square found for the specified SAN move.

enumerator kAmbiguousOrigin

The origin square specified in SAN notation is ambiguous.

enumerator kIllegalMove

The piece at the origin cannot legally move to the destination square (UCI).

enumerator kWrongPieceColorAtOrigin

The piece at the origin does not belong to the player making the move (UCI).

enumerator kNoPieceAtOrigin

The origin square is empty (UCI).

enumerator kMoveLeavesOwnKingInCheck

The move would leave the player’s own king in check.

enumerator kPromotionOnInvalidRank

Promotion attempted on a non-final rank.

enumerator kNonPawnPromotionAttempt

Attempted to promote a piece that is not a pawn.

enumerator kMissingPromotionPiece

Promotion piece was not specified when required.

enumerator kHalfmoveClockOverflow

The move would cause the halfmove clock to overflow.

enumerator kFullmoveNumberOverflow

The move would cause the fullmove number to overflow.

Helper classes

template<>
struct formatter : public chesscxx::internal::NoSpec
#include <move_error_formatter.h>

formatting support for chesscxx::MoveError

Examples

#include <chesscxx/game.h>
#include <chesscxx/move_error.h>
#include <chesscxx/parse.h>
#include <chesscxx/san_move.h>

#include <cstdlib>
#include <print>
#include <string_view>

namespace {
auto parseSan(std::string_view str) {
  auto parsed_move = chesscxx::parse<chesscxx::SanMove>(str);
  if (!parsed_move) std::abort();
  return parsed_move.value();
}

void moveAndPrint(chesscxx::Game& game, const auto& move) {
  auto move_result = game.move(move);
  if (move_result) {
    std::println("{} -> {:fen}", move, game);
  } else {
    std::println("{} -> {}", move, move_result.error());
  }
}
}  // namespace

auto main() -> int {
  std::println("{}", chesscxx::MoveError::kMissingPromotionPiece);
  std::println("{}\n", chesscxx::MoveError::kKingOrRookMoved);

  chesscxx::Game game;
  std::println("{:fen}\n", game);

  moveAndPrint(game, parseSan("e5"));
  moveAndPrint(game, parseSan("O-O"));
  moveAndPrint(game, parseSan("e4"));
  moveAndPrint(game, parseSan("d5"));
  moveAndPrint(game, parseSan("c4"));
  moveAndPrint(game, parseSan("e6"));
  moveAndPrint(game, parseSan("d5"));
  moveAndPrint(game, parseSan("exd5"));
  moveAndPrint(game, parseSan("d5"));
  moveAndPrint(game, parseSan("Qe2"));
  moveAndPrint(game, parseSan("Nf6"));
  moveAndPrint(game, parseSan("Ne7"));
}

Output:

Missing promotion piece
King or rook moved

rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

e5 -> No valid origin
O-O -> King path blocked
e4 -> rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1
d5 -> rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq d6 0 2
c4 -> rnbqkbnr/ppp1pppp/8/3p4/2P1P3/8/PP1P1PPP/RNBQKBNR b KQkq c3 0 2
e6 -> rnbqkbnr/ppp2ppp/4p3/3p4/2P1P3/8/PP1P1PPP/RNBQKBNR w KQkq - 0 3
d5 -> Ambiguous origin
exd5 -> rnbqkbnr/ppp2ppp/4p3/3P4/2P5/8/PP1P1PPP/RNBQKBNR b KQkq - 0 3
d5 -> rnbqkbnr/ppp2ppp/8/3p4/2P5/8/PP1P1PPP/RNBQKBNR w KQkq - 0 4
Qe2 -> rnbqkbnr/ppp2ppp/8/3p4/2P5/8/PP1PQPPP/RNB1KBNR b KQkq - 1 4
Nf6 -> Move leaves own king in check
Ne7 -> rnbqkb1r/ppp1nppp/8/3p4/2P5/8/PP1PQPPP/RNB1KBNR w KQkq - 2 5