Move Generation

inline std::generator<UciMove> legalUciMoves(const Game &game)

Generates all legal moves in UCI (Universal Chess Interface) format from the current position in the given game.

Note

The moves are not guaranteed to be generated in any specific order.

Parameters:

game – The game whose current position is used to generate moves.

Returns:

A generator yielding legal moves in UCI format.

inline std::generator<SanMove> legalSanMoves(const Game &game)

Generates all legal moves in SAN (Standard Algebraic Notation) format from the current position in the given game.

Note

The moves are not guaranteed to be generated in any specific order.

Parameters:

game – The game whose current position is used to generate moves.

Returns:

A generator yielding legal moves in SAN format.

Examples

Full game

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

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

namespace {
void verify(const auto& check) {
  if (!static_cast<bool>(check)) std::abort();
}
auto parseSanMove(std::string_view str) -> chesscxx::SanMove {
  auto parsed_san_move = chesscxx::parse<chesscxx::SanMove>(str);
  verify(parsed_san_move);
  return parsed_san_move.value();
}

void printGame(const auto& game) {
  std::println("{:fen}", game);
  std::println("{}", chesscxx::legalUciMoves(game));
  std::println("{}\n", chesscxx::legalSanMoves(game));
}
}  // namespace

auto main() -> int {
  chesscxx::Game game;
  printGame(game);

  verify(game.move(parseSanMove("e4")));
  printGame(game);

  verify(game.move(parseSanMove("g5")));
  printGame(game);

  verify(game.move(parseSanMove("Nc3")));
  printGame(game);

  verify(game.move(parseSanMove("f5")));
  printGame(game);

  verify(game.move(parseSanMove("Qh5")));
  printGame(game);
}

Output:

rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
[g1h3, g1f3, b1c3, b1a3, h2h3, h2h4, g2g3, g2g4, f2f3, f2f4, e2e3, e2e4, d2d3, d2d4, c2c3, c2c4, b2b3, b2b4, a2a3, a2a4]
[Nh3, Nf3, Nc3, Na3, h3, h4, g3, g4, f3, f4, e3, e4, d3, d4, c3, c4, b3, b4, a3, a4]

rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1
[h7h6, h7h5, g7g6, g7g5, f7f6, f7f5, e7e6, e7e5, d7d6, d7d5, c7c6, c7c5, b7b6, b7b5, a7a6, a7a5, g8h6, g8f6, b8c6, b8a6]
[h6, h5, g6, g5, f6, f5, e6, e5, d6, d5, c6, c5, b6, b5, a6, a5, Nh6, Nf6, Nc6, Na6]

rnbqkbnr/pppppp1p/8/6p1/4P3/8/PPPP1PPP/RNBQKBNR w KQkq g6 0 2
[e1e2, d1e2, d1f3, d1g4, d1h5, f1e2, f1d3, f1c4, f1b5, f1a6, g1h3, g1f3, g1e2, b1c3, b1a3, h2h3, h2h4, g2g3, g2g4, f2f3, f2f4, d2d3, d2d4, c2c3, c2c4, e4e5, b2b3, b2b4, a2a3, a2a4]
[Ke2, Qe2, Qf3, Qg4, Qh5, Be2, Bd3, Bc4, Bb5, Ba6, Nh3, Nf3, Ne2, Nc3, Na3, h3, h4, g3, g4, f3, f4, d3, d4, c3, c4, e5, b3, b4, a3, a4]

rnbqkbnr/pppppp1p/8/6p1/4P3/2N5/PPPP1PPP/R1BQKBNR b KQkq - 1 2
[g5g4, h7h6, h7h5, f7f6, f7f5, e7e6, e7e5, d7d6, d7d5, c7c6, c7c5, b7b6, b7b5, a7a6, a7a5, f8g7, f8h6, g8h6, g8f6, b8c6, b8a6]
[g4, h6, h5, f6, f5, e6, e5, d6, d5, c6, c5, b6, b5, a6, a5, Bg7, Bh6, Nh6, Nf6, Nc6, Na6]

rnbqkbnr/ppppp2p/8/5pp1/4P3/2N5/PPPP1PPP/R1BQKBNR w KQkq f6 0 3
[e1e2, d1e2, d1f3, d1g4, d1h5, f1e2, f1d3, f1c4, f1b5, f1a6, c3e2, c3d5, c3b1, c3b5, c3a4, g1h3, g1f3, g1e2, a1b1, h2h3, h2h4, g2g3, g2g4, f2f3, f2f4, d2d3, d2d4, e4e5, e4f5, b2b3, b2b4, a2a3, a2a4]
[Ke2, Qe2, Qf3, Qg4, Qh5#, Be2, Bd3, Bc4, Bb5, Ba6, Nce2, Nd5, Nb1, Nb5, Na4, Nh3, Nf3, Nge2, Rb1, h3, h4, g3, g4, f3, f4, d3, d4, e5, exf5, b3, b4, a3, a4]

rnbqkbnr/ppppp2p/8/5ppQ/4P3/2N5/PPPP1PPP/R1B1KBNR b KQkq - 1 3
[]
[]

Castling

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

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

namespace {
void verify(const auto& check) {
  if (!static_cast<bool>(check)) std::abort();
}
auto parseSanMove(std::string_view str) -> chesscxx::SanMove {
  auto parsed_san_move = chesscxx::parse<chesscxx::SanMove>(str);
  verify(parsed_san_move);
  return parsed_san_move.value();
}

auto parseFen(std::string_view str) -> chesscxx::Game {
  auto parsed_game =
      chesscxx::parse<chesscxx::Game>(str, chesscxx::parse_as::Fen{});
  verify(parsed_game);

  return parsed_game.value();
}

void printGame(const auto& game) {
  std::println("{:fen}", game);
  std::println("{}", chesscxx::legalUciMoves(game));
  std::println("{}\n", chesscxx::legalSanMoves(game));
}
}  // namespace

auto main() -> int {
  chesscxx::Game game = parseFen("r3k2r/8/8/8/8/8/8/R3K2R w KQkq - 0 1");
  printGame(game);

  verify(game.move(parseSanMove("O-O-O")));
  printGame(game);

  verify(game.move(parseSanMove("O-O")));
  printGame(game);
}

Output:

r3k2r/8/8/8/8/8/8/R3K2R w KQkq - 0 1
[e1g1, e1c1, e1f1, e1f2, e1e2, e1d1, e1d2, h1h2, h1h3, h1h4, h1h5, h1h6, h1h7, h1h8, h1g1, h1f1, a1a2, a1a3, a1a4, a1a5, a1a6, a1a7, a1a8, a1b1, a1c1, a1d1]
[O-O, O-O-O, Kf1, Kf2, Ke2, Kd1, Kd2, Rh2, Rh3, Rh4, Rh5, Rh6, Rh7, Rxh8+, Rg1, Rf1, Ra2, Ra3, Ra4, Ra5, Ra6, Ra7, Rxa8+, Rb1, Rc1, Rd1]

r3k2r/8/8/8/8/8/8/2KR3R b kq - 1 1
[e8g8, e8f7, e8f8, e8e7, h8h7, h8h6, h8h5, h8h4, h8h3, h8h2, h8h1, h8g8, h8f8, a8a7, a8a6, a8a5, a8a4, a8a3, a8a2, a8a1, a8b8, a8c8, a8d8]
[O-O, Kf7, Kf8, Ke7, Rh7, Rh6, Rh5, Rh4, Rh3, Rh2, Rxh1, Rg8, Rf8, Ra7, Ra6, Ra5, Ra4, Ra3, Ra2, Ra1+, Rb8, Rc8+, Rd8]

r4rk1/8/8/8/8/8/8/2KR3R w - - 2 2
[c1d2, c1c2, c1b1, c1b2, d1d2, d1d3, d1d4, d1d5, d1d6, d1d7, d1d8, d1e1, d1f1, d1g1, h1h2, h1h3, h1h4, h1h5, h1h6, h1h7, h1h8, h1g1, h1f1, h1e1]
[Kd2, Kc2, Kb1, Kb2, Rd2, Rd3, Rd4, Rd5, Rd6, Rd7, Rd8, Rde1, Rdf1, Rdg1+, Rh2, Rh3, Rh4, Rh5, Rh6, Rh7, Rh8+, Rhg1+, Rhf1, Rhe1]

Promotion

#include <chesscxx/game.h>
#include <chesscxx/movegen.h>
#include <chesscxx/parse.h>

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

namespace {
void verify(const auto& check) {
  if (!static_cast<bool>(check)) std::abort();
}
auto parseFen(std::string_view str) -> chesscxx::Game {
  auto parsed_game =
      chesscxx::parse<chesscxx::Game>(str, chesscxx::parse_as::Fen{});
  verify(parsed_game);

  return parsed_game.value();
}

void printGame(const auto& game) {
  std::println("{:fen}", game);
  std::println("{}", chesscxx::legalUciMoves(game));
  std::println("{}\n", chesscxx::legalSanMoves(game));
}
}  // namespace

auto main() -> int {
  chesscxx::Game const game =
      parseFen("3r1bnr/kPpppppp/2R5/8/8/8/1PPPPPPP/1NBQKBNR w K - 1 9");

  printGame(game);
}

Output:

3r1bnr/kPpppppp/2R5/8/8/8/1PPPPPPP/1NBQKBNR w K - 1 9
[g1h3, g1f3, b1c3, b1a3, c6c5, c6c4, c6c3, c6c7, c6b6, c6a6, c6d6, c6e6, c6f6, c6g6, c6h6, h2h3, h2h4, g2g3, g2g4, f2f3, f2f4, e2e3, e2e4, d2d3, d2d4, c2c3, c2c4, b2b3, b2b4, b7b8n, b7b8b, b7b8r, b7b8q]
[Nh3, Nf3, Nc3, Na3, Rc5, Rc4, Rc3, Rxc7, Rb6, Ra6+, Rd6, Re6, Rf6, Rg6, Rh6, h3, h4, g3, g4, f3, f4, e3, e4, d3, d4, c3, c4, b3, b4, b8=N, b8=B+, b8=R, b8=Q+]