Fastchess

repository·master·Indexed 42 days ago

https://github.com/disservin/fastchess

A high-performance, concurrent command-line tool written in C++17 for orchestrating chess engine tournaments. It is designed to handle high concurrency and short time controls with minimal timeouts, featuring a built-in UCI compliance checker and support for GZIP compressed logs.

Tokens
28.6K
Snippets
132
Records
177
Agent score
43%

What's inside Fastchess

  1. Overview of the {fmt} library API

    master

    The {fmt} library provides a wide range of formatting capabilities through several specialized headers. All functions and types reside in the fmt namespace, and macros are prefixed with FMT_.

    Core Components:

    • fmt/base.h: Base API for char/UTF-8 with C++20 compile-time checks. Minimal dependencies.
    • fmt/format.h: Main formatting functions (like fmt::format) and locale support.
    • fmt/ranges.h: Formatting for ranges and tuples (e.g., std::vector).
    • fmt/chrono.h: Date and time formatting.
    • fmt/std.h: Formatters for standard library types.
    • fmt/compile.h: Format string compilation.
    • fmt/color.h: Terminal colors and text styles.
    • fmt/os.h: System APIs.
    • fmt/ostream.h: std::ostream support.
    • fmt/args.h: Dynamic argument lists.
    • fmt/printf.h: Safe printf implementation.
    • fmt/xchar.h: Optional wchar_t support.
  2. Overview of the {fmt} library

    master

    The {fmt} library is a high-performance C++ formatting library designed to address the limitations of existing methods like printf, iostreams, and Boost Format. It provides a safe, fast, and feature-rich alternative for string formatting, supporting positional arguments (useful for i18n), user-defined types, and advanced formatting options like leading zeros and hexadecimal encoding that other fast libraries (like FastFormat) may lack.

    Key advantages include:

    • Performance: Faster than iostreams and Boost Format.
    • Safety: Provides type safety and avoids the pitfalls of printf.
    • Flexibility: Supports positional arguments, runtime width/alignment, and various encodings.
  3. Core features of the {fmt} library

    master

    The {fmt} library is a modern C++ formatting library designed as a safe, fast, and extensible replacement for the printf family of functions and C++ iostreams. Key features include:

    • Safety: Provides compile-time checks for format strings (e.g., detecting invalid specifiers) and prevents buffer overflows via automatic memory management.
    • Extensibility: Supports standard types, containers, dates, and times out-of-the-box. Users can also define custom formatters for user-defined types (UDTs).
    • Performance: Significantly faster than iostreams and sprintf (up to 20-30x faster for numeric formatting) by minimizing dynamic memory allocations.
    • Unicode Support: Provides portable UTF-8 support across Linux, macOS, and Windows.
    • Fast Compilation & Small Footprint: Uses type erasure to minimize template bloat and reduce compilation times. The core consists of just three headers with no external dependencies.
    • Portability: Requires only a minimal subset of C++11 (compatible with GCC 4.9, Clang 3.6, MSVC 19.10+).
  4. Set up a tournament with -tournament and -seeds

    master

    You can define the tournament structure using the following options:

    • -tournament (roundrobin|gauntlet):
      • roundrobin: Each engine plays every other engine (default).
      • gauntlet: The first N engines (defined by -seeds) play against all other engines.
    • -seeds (1|N): Specifies how many engines are playing the gauntlet (default is 1).
    • -variant (standard|fischerandom): Choose between standard (default) or fischerandom chess.
    • -concurrency (1|N): Number of games to play concurrently (default is 1). Use -force-concurrency to ignore hardware thread limits.
  5. Use MemoryWriter for buffer management

    master

    In versions 0.12.0 and later, fmt::Writer is an abstract base class and cannot be instantiated directly. For default buffer management (using small stack allocations), use fmt::MemoryWriter instead. Note that you can still pass fmt::Writer by reference to functions expecting it.

    // Instead of:
    // fmt::Writer w;
    
    // Use:
    fmt::MemoryWriter w;
    
    // But you can still pass by reference:
    void f(fmt::Writer &w);
  6. Compatibility with C++20 std::format

    master

    The {fmt} library is a near-complete implementation of the C++20 <format> library, with a few key differences:

    1. Namespace: Names are in the fmt namespace instead of std to avoid collisions.
    2. Width Calculation: {fmt} does not currently use grapheme clusterization for width calculation.
    3. Floating-Point Representation: {fmt} uses the smallest precision providing round-trip guarantees (similar to Python/Java), whereas std::format (via std::to_chars) may produce more decimal digits than necessary.
  7. Resume or recover tournaments with -config and -recover

    master

    To handle long-running tournaments or crashes:

    • -config [file=NAME] [discard=(false|true)] [outname=(config.json|NAME)] [stats=(true|false)]: Load engine configurations to resume games from a previous session.
      • file: The configuration file to load.
      • discard: If true, the loaded config is discarded after loading.
      • outname: The filename for the auto-generated config (default config.json).
      • stats: If true, loads stats from the config file (default true).
    • -recover: Enables crash recovery to attempt to recover engines and continue the tournament.
    • -autosaveinterval (20|N): Automatically saves the tournament state every N games (default 20).
  8. Format String Syntax in fmt

    master

    Formatting functions like fmt::format and fmt::print use replacement fields enclosed in curly braces {} to insert values into a string. Text outside of braces is treated as literal text.

    Escaping Braces

    To include literal curly braces in your output, escape them by doubling them:

    • Use {{ for a literal {.
    • Use }} for a literal }.

    Replacement Field Structure

    A replacement field follows this grammar: { [arg_id] [: [format_spec | chrono_format_spec]] }

    • arg_id: An integer or identifier specifying which argument to format. If arguments are provided in sequence (0, 1, 2...), the arg_id can be omitted (e.g., {}).
    • format_spec: An optional specification preceded by a colon (:) that defines how the value is presented (width, alignment, precision, etc.).
    • Nested Fields: A format_spec can contain nested replacement fields that only contain an arg_id (no further specifications allowed). This allows for dynamic formatting specifications.
    // Explicit argument indexing
    fmt::print("First, thou shalt count to {0}", 1);
    
    // Implicit argument indexing (uses 0, 1, 2... in order)
    fmt::print("Bring me a {}", "sword");
    
    // Multiple implicit arguments
    fmt::print("From {} to {}", 1, 10);
    
    // Escaping braces
    fmt::print("The set is {{1, 2, 3}}"); // Output: The set is {1, 2, 3}
  9. Compare {fmt} with other formatting methods

    master

    When choosing a formatting method in C++, consider the following trade-offs documented by {fmt}:

    MethodProsCons
    printfFast, standard C library availabilityNo user-defined type support, safety issues
    iostreamsSupports user-defined types, safeVerbose syntax ("chevron hell"), no positional arguments
    Boost FormatPowerful, supports positional argumentsSlow performance, high build times, code bloat
    FastFormatFast, safe, positional argumentsLacks leading zeros, octal/hex encoding, and runtime width/alignment
    {fmt}Fast, safe, positional arguments, full feature set(N/A)
  10. How to format user-defined types

    master

    There are two primary ways to make your custom types formattable with {fmt}:

    1. Using format_as (Simple)

    Use format_as if you want your type to be treated as another existing formattable type (e.g., an enum class behaving like its underlying integer). Define format_as in the same namespace as your type.

    2. Specializing fmt::formatter (Advanced)

    Use this for full control over parsing and formatting. You must implement parse and format methods. It is highly recommended to inherit from an existing formatter (like formatter<string_view>) to reuse standard specifiers like alignment and width.

    Note: You cannot provide both a formatter specialization and a format_as overload for the same type.

    // Method 1: format_as for enums
    namespace my_ns {
      enum class color { red, blue };
      auto format_as(color c) { return static_cast<int>(c); }
    }
    
    // Method 2: formatter specialization for complex types
    template <> struct fmt::formatter<my_type> : formatter<string_view> {
      auto format(my_type c, format_context& ctx) const -> format_context::iterator {
        string_view name = "custom";
        return formatter<string_view>::format(name, ctx);
      }
    };