A Python implementation of The Binding of Isaac: Four Souls focused on one long-term question:
Can we demonstrate, with actual gameplay and statistics, that some cards are so strong that they produce a measurable advantage?
This project is not just a playable clone. It is a rules-driven simulation environment whose end goal is to support:
- accurate game execution,
- reproducible automated matches,
- AI / strategy bots,
- reinforcement learning experiments,
- and statistical analysis of card strength, balance, and meta impact.
- Python 3.11 or later
pip install -e ".[dev]"This installs the foursouls package in editable mode along with pytest.
pytestpython -m foursouls.cliYou will be prompted for the number of players, their names, and an RNG seed. The board is rendered in the terminal after each action and you pick moves from a numbered menu.
from foursouls.cli.app import build_demo_game, run
game = build_demo_game(["Alice", "Bob"], seed=42)
run(game) # interactive loopbuild_demo_game accepts any number of player name strings and an integer seed for full reproducibility.
Bots live in agents/ and can be used to drive the game programmatically:
| Bot | File | Behaviour |
|---|---|---|
combat_bot |
agents/combat_bot.py |
Always attacks when possible |
economy_bot |
agents/economy_bot.py |
Prioritises buying and looting |
pass_bot |
agents/pass_bot.py |
Always passes priority (useful in tests) |
from agents.combat_bot import choose_command
while not game.game_over:
game.step(choose_command(game))The final system should let us:
- Play the game manually and verify that the engine behaves like the real rules.
- Add cards incrementally without rewriting the engine every time.
- Run automated games between bots or AI agents.
- Collect statistics on outcomes, card performance, and decision quality.
- Test hypotheses such as:
- Are some cards overpowered?
- Do certain openings create unfair win rates?
- Does going first matter?
- Which strategies outperform others over large samples?
In short, this repository aims to become both:
- a playable Four Souls engine, and
- a research / simulation platform for balance and strategy analysis.
The current stage of the project is infrastructure first.
Before deep card coverage, AI, or large-scale simulations, we need a solid foundation:
- a deterministic rules engine,
- clear game state transitions,
- stack and priority handling,
- reproducible setup,
- a manually playable CLI,
- expressive events for debugging and UI,
- and enough tests to trust the engine.
Right now, the most important question is not:
"Do we already support every card?"
It is:
"Can developers confidently verify that the game behaves according to the rules?"
That is why the current work emphasizes engine structure, legality checks, event flow, and testability.
The engine should model the actual game structure as closely as practical:
- phases,
- priority,
- the stack,
- combat timing,
- triggered / activated abilities,
- purchases,
- death,
- rewards,
- and victory conditions.
A seeded RNG and explicit state transitions are essential. We want developers to be able to reproduce games, replay bugs, and write reliable tests.
The engine should not be hardcoded around a tiny starter set forever. It should be possible to add more loot, treasure, monsters, bosses, and events over time without breaking the whole architecture.
The same engine should support:
- CLI/manual play,
- scripted tests,
- bots,
- simulations,
- and later, possibly GUI frontends.
The engine should emit rich domain events so developers can:
- understand what happened,
- debug state changes,
- drive a UI,
- and later implement triggers and analysis tooling.
This project has three layers of scope.
The rules engine is the core of everything else.
It is responsible for:
- game setup,
- turn flow,
- phase progression,
- command legality,
- stack resolution,
- combat resolution,
- purchases,
- death and cleanup,
- card movement between zones,
- and victory detection.
This layer should remain independent from any specific UI.
This layer exists so humans can inspect and validate the engine.
It includes:
- CLI play,
- readable board rendering,
- legal action menus,
- debug-friendly event logs,
- deterministic seeds,
- acceptance tests,
- and regression coverage.
This is the layer that lets contributors confirm:
"Yes, the game is behaving correctly."
Once the rules engine is stable enough, the project expands into research and evaluation.
This includes:
- simple strategy bots,
- stronger heuristic agents,
- reinforcement learning agents,
- tournament runners,
- batch simulations,
- telemetry,
- and statistics dashboards / exports.
This is the layer that lets us ask:
"Is this card actually broken?"
This repository is not intended to replace the official rulebook, but developers need a shared mental model of the system the engine is trying to implement.
At a high level, Four Souls is modeled here as:
- a turn-based multiplayer card game,
- with priority passing,
- a stack for actions and effects,
- multiple zones (hands, decks, discard piles, board, shop, monster slots, etc.),
- and a game loop built around setup, turn phases, actions, combat, death, and victory.
A player's turn broadly follows this kind of flow:
-
Start Phase
- Start-of-turn effects occur.
- The active player loots.
- Priority and the stack may matter before the turn moves on.
-
Action Phase
- Players may play loot cards.
- Players may activate character and item abilities.
- The active player may attack.
- The active player may purchase from the shop.
- Priority matters throughout.
-
Combat / Stack interaction
- Attacks, rolls, damage, and deaths are not just "instant math."
- They interact with stack timing and response windows.
-
End Phase
- Cleanup and end-of-turn effects occur.
- Healing / reset timing happens here according to the rules.
- The next player becomes active.
Only the player with priority may currently act. When all players pass in sequence:
- the top of the stack resolves, or
- the game advances if nothing is on the stack and the phase allows it.
Most meaningful actions and effects should be modeled in a way that supports:
- responses,
- resolution order,
- and triggered consequences.
The UI should not invent what is allowed. The engine should expose what actions are legal based on:
- phase,
- active player,
- priority holder,
- combat state,
- taps / activations used,
- stack state,
- and card-specific rules.
Cards and entities move between different areas:
- deck,
- hand,
- discard,
- shop,
- in-play items,
- monster slots,
- souls,
- and so on.
Randomness is part of the game, but for testing and simulations it must be reproducible.
Rules accuracy does not mean:
- every single card is already implemented,
- every edge case exists from day one,
- or the first playable version is full-fidelity.
Rules accuracy means the project is built so that:
- the core timing model is correct,
- the state model is explicit,
- missing features can be added without undoing the architecture,
- and developers can compare implementation behavior against the official rules.
The project can start with a narrow card set and still be "on the right track" if the underlying model is sound.
This project is being built in vertical slices.
That means each sprint tries to deliver a playable, testable piece of the game rather than a huge incomplete abstraction layer.
Examples of slice-oriented progress:
- setup + turn flow,
- loot play + character abilities,
- shop,
- monsters + combat,
- CLI playability,
- event quality,
- then broader rule parity and more cards.
This approach helps us:
- validate architecture early,
- catch bad assumptions fast,
- and always keep the project in a runnable state.
The long-term end state is roughly:
Support a broad set of:
- loot,
- treasure,
- monsters,
- bosses,
- events,
- and other rule objects.
Allow multiple styles of agents:
- random bots,
- simple scripted bots,
- heuristic strategy bots,
- and stronger search-based or learned agents.
Expose the engine in a way that makes it possible to train agents on:
- action selection,
- combat timing,
- resource usage,
- and broader strategic choices.
Support large batches of games and export data such as:
- win rates,
- card appearance vs win correlation,
- damage / reward efficiency,
- first-player advantage,
- matchup performance,
- and card-specific impact metrics.
This is the part that answers the original research question about "broken" cards.
At this stage, this project is not trying to prioritize:
- a polished production GUI,
- complete support for every expansion immediately,
- flashy presentation over correctness,
- or AI before the rules engine is trustworthy.
A bot that plays a wrong game is not useful. A simulator with broken timing rules is not useful. A statistics pipeline on top of inaccurate rules is not useful.
So the order matters: engine first, confidence second, scale third.
When contributing, prefer changes that improve one or more of the following:
- correctness,
- clarity,
- testability,
- determinism,
- observability,
- extensibility.
Be careful about changes that:
- hardcode behavior into the CLI,
- bypass legality checks,
- couple UI to engine internals,
- or solve one card in a way that makes future cards harder to model.
A good contribution is not just "it works once." A good contribution makes the engine easier to trust and easier to grow.
This repo exists because "this card feels broken" is easy to say and hard to prove.
The project's real ambition is to make statements like these testable:
- "Card X increases win rate significantly."
- "Card Y produces unfair tempo swings compared to similar cards."
- "This opening configuration creates a measurable advantage."
- "This strategy dominates under realistic play."
To get there, we first need a game engine that developers can inspect, trust, and extend.
That is the current mission of the project.