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