stellar

Stellar - UCI Chess engine written in C++20
git clone git://git.dimitrijedobrota.com/stellar.git
Log | Files | Refs | README | LICENSE

game.cpp (3877B)


      1 #include "game.hpp"
      2 
      3 #include "board.hpp"
      4 #include "logger.hpp"
      5 #include "timer.hpp"
      6 #include "utils_ui.hpp"
      7 
      8 #include <format>
      9 
     10 bool Game::san = true;
     11 const std::string Game::startPosition = start_position;
     12 
     13 uint16_t Game::id_t = 0;
     14 Game::~Game() { logger::log(std::format("Game {}: destroyed", id), logger::Debug); }
     15 Game::Game(const uint16_t match_id, const std::string &white, const std::string &black,
     16            const std::string &fen)
     17     : match_id(match_id), white(white), black(black), fen(fen) {
     18     logger::log(std::format("Game {}: started", id), logger::Debug);
     19 }
     20 
     21 const std::string Game::get_moves() const {
     22     std::string res;
     23     if (list.size()) res += (std::string)list[0];
     24     for (int i = 1; i < list.size(); i++)
     25         res += " " + (std::string)list[i];
     26     return res;
     27 }
     28 
     29 const std::string Game::to_san(const Board &board, const Move move) {
     30     Board copy = board;
     31     if (!move.make(copy)) {
     32         logger::log("illegal move", logger::Critical);
     33         throw std::runtime_error("illegal move");
     34     }
     35 
     36     if (move.is_castle_king()) return "O-O";
     37     if (move.is_castle_queen()) return "O-O-O";
     38 
     39     const Type piece = board.get_square_piece_type(move.source());
     40     const Type target = board.get_square_piece_type(move.target());
     41 
     42     std::string res;
     43     if (piece != PAWN) {
     44         res += piece::get_code(piece, WHITE);
     45 
     46         U64 potential = board.get_bitboard_square_land(move.target(), piece, board.get_side());
     47         if (bit::count(potential) > 1) {
     48             int file[9] = {0}, rank[9] = {0};
     49             uint8_t square_i = 0;
     50             bitboard_for_each_bit(square_i, potential) {
     51                 const std::string crd = to_coordinates(static_cast<Square>(square_i));
     52                 file[crd[0] & 0x3]++;
     53                 rank[crd[1] & 0x3]++;
     54             }
     55 
     56             const std::string crd = to_coordinates(move.source());
     57             if (file[crd[0] & 0x3] == 1) res += crd[0];
     58             else if (rank[crd[1] & 0x3] == 1)
     59                 res += crd[1];
     60             else
     61                 res += crd;
     62         }
     63 
     64         if (target != Type::NO_TYPE) res += "x";
     65         res += to_coordinates(move.target());
     66     } else {
     67         if (target != Type::NO_TYPE) res += std::format("{}x", to_coordinates(move.source())[0]);
     68         res += to_coordinates(move.target());
     69         if (move.is_promote()) res += piece::get_code(move.promoted(), WHITE);
     70         if (move.is_enpassant()) res += " e.p.";
     71     }
     72 
     73     if (!MoveList(copy, false, true).size()) res += "#";
     74     else if (copy.is_check())
     75         res += "+";
     76 
     77     return res;
     78 }
     79 
     80 std::ostream &operator<<(std::ostream &os, const Game &game) {
     81     static const std::string name[] = {"death", "time forfeit", "rules infraction", "repetition"};
     82     os << std::format("[Event \"Match {}\"]", game.match_id);
     83     os << std::format("\n[Site \"{}\"]", "Stellar Arena");
     84     os << std::format("\n[Date \"{}\"]", timer::get_ms());
     85     os << std::format("\n[Round \"{}\"]", game.id);
     86     os << std::format("\n[White \"{}\"]", game.get_white());
     87     os << std::format("\n[Black \"{}\"]", game.get_black());
     88     os << std::format("\n[Result \"{}-{}\"]", (int)game.is_win_white(), (int)game.is_win_black());
     89     os << std::format("\n[Termination \"{}\"]", name[game.get_terminate()]);
     90     if (game.fen != Game::startPosition) {
     91         os << std::format("\n[SetUp \"1\"]");
     92         os << std::format("\n[FEN \"{}\"]", game.fen);
     93     }
     94     os << '\n';
     95 
     96     if (!game.list.size()) return os;
     97     Board board(game.fen);
     98 
     99     const Color side = board.get_side();
    100     if (side == BLACK) os << std::format("1. ... ");
    101     for (int i = 0; i < game.list.size(); i++) {
    102         if (i % 2 == side) os << std::format("{}. ", i / 2 + 1);
    103         os << std::format("{} ", Game::san ? Game::to_san(board, game.list[i]) : (std::string)game.list[i]);
    104         game.list[i].make(board);
    105     }
    106 
    107     return os;
    108 }