# RosettaStone: a Hearthstone simulator you can train a policy against

> RosettaStone models Hearthstone normal play and Battlegrounds in C++23 behind a reusable library, and exposes the same simulator to Python through pybind11, which is what makes it usable as a reinforcement learning environment rather than only as a game engine.

**utilForever/RosettaStone** — Hearthstone simulator using C++ with some reinforcement learning

- Repository: https://github.com/utilForever/RosettaStone
- Website: https://utilforever.github.io/RosettaStone/
- Stars: 684 · Forks: 83
- Language: C++
- License: AGPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/utilforever-rosettastone

## One simulator, three ways in

RosettaStone models Hearthstone normal play mode and Battlegrounds, and the key structural decision is that the core simulator is shared. The same C++ code is exposed through the C++ API, through the pyRosetta Python extension, and through the console and utility programs, so a policy written in Python and a test written in C++ are exercising identical game logic rather than two implementations that drift apart. The project describes itself as a C++23 Hearthstone simulator with C++, Python, console and tooling interfaces. The scope of what is modelled is stated in a short list: cards, entities, zones, tasks, triggers, auras and game flow, with normal play and Battlegrounds kept in separate simulator trees so the two modes do not contaminate each other's state. The page for the project is at utilforever.github.io/RosettaStone, and the deeper design notes live in ARCHITECTURE.md in the repository, with AGENTS.md holding the rules for coding agents.

## The prerequisites are a C++23 toolchain, vcpkg and Python

The quick start lists what you need before anything else. A C++23 compiler, CMake 3.31.6 or later, vcpkg with VCPKG_ROOT set, Python 3.12 or later for the Python API and the tests, and Git. The CMake version floor and the C++23 requirement are worth noting, because they place the project firmly in recent-toolchain territory. The vcpkg dependency is there for the third-party libraries, and the vcpkg.json file at the repository root is what pins them. The Python version requirement is separate and higher than you might expect, and it applies only to the Python API and the Python tests, so a C++-only user does not need to install it. The repository also ships a Dockerfile, and the Python side has its own requirements file with pinned versions.

## Building and running the tests

Cloning is recursive, because the build depends on submodules.

```bash
git clone https://github.com/utilForever/RosettaStone.git --recursive
cd RosettaStone
```

The build configures with CMake against the vcpkg toolchain file and compiles in Release mode.

```bash
cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"
cmake --build build --config Release
```

The C++ tests are then a single binary, and the path differs on Windows release builds.

```bash
./build/bin/UnitTests
```

```powershell
.\build\bin\Release\UnitTests.exe
```

The Windows path is the one to remember, since a multi-config generator puts the executable in a configuration subdirectory. The C++ test suite uses doctest and the Python one uses pytest, and the coverage is measured with codecov and SonarCloud, with the badges on the project page reporting lines of code, maintainability, reliability, security, bugs and vulnerabilities.

## Installing the Python API

The Python extension is called pyRosetta, and it is built with pybind11 in the Extensions/RosettaPython/ directory. Installing it takes three steps: the test dependencies, the package itself, and then the test run.

```bash
python -m pip install -r requirements.txt
python -m pip install .
python -m pytest Tests/PythonTests/
```

The requirements file pins the test tooling exactly, with pytest at 9.1.1, setuptools at 83.0.0 and wheel at 0.47.0, plus colorama on Windows only. The fact that the package installs with pip install . rather than needing a manual build step means the pybind11 extension is compiled during installation, so a compiler is needed on the machine even when you only want the Python API. The Dockerfile shows the full sequence the project itself uses: it builds with cmake, runs the C++ unit tests as bin/UnitTests, then installs the Python requirements and runs the pytest suite, which is a useful sanity check for a containerised setup.

## The directory layout mirrors the architecture

The architecture table in the overview is unusually clear about where things live. Includes/Rosetta/ holds the public simulator headers and models, and Sources/Rosetta/ holds the core implementation, which the table describes as game flow, loaders, tasks, cards, auras and triggers. Battlegrounds has its own parallel pair, Includes/Rosetta/Battlegrounds/ and Sources/Rosetta/Battlegrounds/, which is how the separate simulator trees are kept separate in the file system as well. Extensions/RosettaPython/ is the pybind11 bindings, Extensions/RosettaConsole/ and Extensions/RosettaTool/ are the console and utility executables, Tests/UnitTests/ and Tests/PythonTests/ hold the C++ doctest and Python pytest coverage, Resources/ and Datas/ hold card metadata and fixtures, and Documents/ holds the build, API, card, task and contribution guides. The presence of a separate Datas/ directory for fixtures and Resources/ for metadata is what lets a test construct a specific board state without loading the whole card pool.

## Card coverage is uneven, and the project measures it

The project is candid about how much of the card pool is actually implemented, and it publishes the numbers per set. Core is at 247 of 250, which is 98.8 percent. Forged in the Barrens is at 139 of 170, or 81.8 percent. United in Stormwind is at 60 of 170 and Fractured in Alterac Valley at 61 of 170, both around 35 percent. Voyage to the Sunken City is at 22 of 170, or 12.9 percent, and Murder at Castle Nathria is at 19 of 170. Implementation progress is generated from the Implemented column in the card lists, and the project tells you to run python Scripts/card_stats.py after updating a list, so the table is generated rather than maintained by hand. This matters for research use. A policy trained on Core behaves differently from one trained on a set where a third of the cards are missing, and the risk of a conclusion being an artefact of unimplemented cards is exactly the kind of thing a coverage table lets you check.

## What the reinforcement learning claim rests on

The repository description calls this a Hearthstone simulator using C++ with some reinforcement learning, and the project topics include reinforcement learning, rl-environment and simulator-game. The architecture that supports that is the shared core with a Python binding, since a reinforcement learning setup typically wants to step the environment thousands of times per episode from a Python training loop, and it is easier to do that when the binding is the same pybind11 extension used by the tests rather than a network protocol or a subprocess. The Python API synchronisation is called out as one of the things the full architecture guide explains, alongside game flow, the runtime model, card loading, effect timing and module boundaries. The Cards directory listing also shows the card lists themselves are the source of truth, which means a training environment can be constrained to a set whose implementation you have verified.

## The build matrix and the licence

The project runs continuous integration on three platforms, with separate workflows for Windows, Ubuntu and macOS, plus a codecov workflow for coverage on Ubuntu and a SonarCloud workflow for static analysis with a quality gate. The SonarCloud badges track the maintainability, reliability and security ratings along with bug and vulnerability counts, so the quality signals are visible on the project page rather than buried in a dashboard nobody opens. The repository top level is a conventional C++ layout with a .clang-format, a CMakeLists.txt, CMakeSettings.json for Visual Studio, a Builds/ directory, a Scripts/ directory, a 3RD-PARTY.md for third-party notices, a sonar-project.properties file and a codecov.yml. The licence is AGPL-3.0, and for a project that is meant to be linked into other software that is a deliberate choice, since the AGPL reaches beyond the boundary of the repository. The last push to the repository was on 2026-10-18 and there are no GitHub releases, so the repository is the only distribution channel.

## Conclusion

RosettaStone fits a reinforcement learning researcher who wants a card game environment with a real rules engine behind it rather than an approximation, since the same C++ simulator is shared by the C++ API, the pyRosetta Python extension and the console tools, and a policy written in Python trains against the same code that the C++ tests exercise. It does not fit a team that needs the full card pool implemented today, because the coverage tables are uneven by set, with Core at 247 of 250 while Voyage to the Sunken City sits at 22 of 170 and Murder at Castle Nathria at 19 of 170. It also does not fit a project that wants a permissive licence, since the project is AGPL-3.0. Before you build on it, run python Scripts/card_stats.py after updating a card list to see the real coverage, and read the set you care about in Documents/ before you assume the rules are modelled correctly.

## FAQ

### What is RosettaStone and what does it simulate?

It is a C++23 Hearthstone simulator modelling normal play mode and Battlegrounds. It models cards, entities, zones, tasks, triggers, auras and game flow, and keeps normal play and Battlegrounds in separate simulator trees.

### How do I build RosettaStone and run its tests?

You need a C++23 compiler, CMake 3.31.6 or later, vcpkg with VCPKG_ROOT set, Python 3.12 or later and Git. Clone with --recursive, configure with cmake -S . -B build pointing the toolchain file at vcpkg, then build and run ./build/bin/UnitTests, or the Release subdirectory path on Windows.

### How much of the Hearthstone card pool is implemented?

The published tables show Core at 247 of 250 cards, Forged in the Barrens at 139 of 170, United in Stormwind at 60 of 170, Fractured in Alterac Valley at 61 of 170, Voyage to the Sunken City at 22 of 170 and Murder at Castle Nathria at 19 of 170. Progress is generated from the card lists by python Scripts/card_stats.py.

### Can I use RosettaStone from Python for reinforcement learning?

Yes. The simulator core is shared with the pyRosetta Python extension built on pybind11, and the package installs with python -m pip install . after installing the requirements. The Python tests are run with python -m pytest Tests/PythonTests/.

## Sources

- [Issues](https://github.com/utilForever/RosettaStone/issues)
- [License: AGPL-3.0](https://github.com/utilForever/RosettaStone/blob/main/LICENSE)
- [Project website](https://utilforever.github.io/RosettaStone/)
- [README](https://github.com/utilForever/RosettaStone/blob/main/README.md)
- [utilForever/RosettaStone on GitHub](https://github.com/utilForever/RosettaStone)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/utilforever-rosettastone
