Skip to content

A rule engine for customizing and creating TCG games and game logic easily.

License

Notifications You must be signed in to change notification settings

Big-Sky-Tech/Cardinal-Codex

Repository files navigation

Cardinal Codex

A headless, deterministic game engine for trading card games (TCGs). Define your game rules in TOML, and Cardinal handles validation, state management, triggers, and event emission.

Quick Links

Features

Fully Deterministic — Same seed + actions = identical outcome
Data-Driven Rules — Define cards in TOML (no code changes)
14 Builtin Effects — Create cards without scripting (draw partially implemented)
Hybrid Card System — TOML builtins + Rhai scripts for flexibility
Headless — Embed in any interface (web, mobile, terminal, AI)
Event-Based — Complete game log for replays and debugging
Well-Tested — 67 tests covering core systems and scripting
Clean Architecture — Clear separation of concerns
Production-Ready Tooling — Comprehensive validation, compilation, and testing tools

Getting Started

Try the Example Game

# Run the minimal example game
cargo run --bin test-game

The test-game folder contains a complete minimal example showing how to build a game with Cardinal. It's fully functional and ready to copy and customize!

Play the Game

cargo run --bin cardinal-cli

Interactive terminal game with colored output and real-time state rendering.

Validate Your Game Assets

# Validate rules
cardinal-cli validate rules rules.toml

# Validate cards
cardinal-cli validate cards-dir cards/

# Validate an entire pack
cardinal-cli validate pack my-pack/

See CLI_USAGE_GUIDE.md for complete CLI documentation.

Build Game Artifacts

# Compile a pack with validation
cardinal-cli compile pack my-pack/ output/game.ccpack --verbose

# Test the pack
cardinal-cli test pack output/game.ccpack

Run Tests

cargo test

19 integration tests covering triggers, initialization, card abilities, and turn progression. All passing.

Use in Your Project

use cardinal::{GameEngine, Action, PlayerId};

let engine = GameEngine::new_from_file("rules.toml", seed)?;
engine.start_game(deck_0, deck_1)?;

let result = engine.apply_action(player_id, action)?;
for event in &result.events {
    // Process event...
}

What is Cardinal?

Cardinal is a game engine referee:

Player: "I want to play card #1"
         ↓
  Cardinal: Validates action, applies effects, evaluates triggers
         ↓
  Returns: Events describing what happened
         ↓
    UI: Reads events and updates display

Cardinal enforces:

  • Turn structure — Phases, steps, priority rules
  • Zone management — Hand, field, graveyard, stack, deck
  • Action validation — Legality checks before applying
  • Card abilities — Data-driven triggers and effects
  • State consistency — GameState is the single source of truth

Core Principles

1. Determinism

Same starting state + same actions + same seed = identical outcome every time.

2. Headless (No UI)

Cardinal has no knowledge of screens or graphics. Any interface can use it.

3. Actions In, Events Out

Simple, unidirectional interface. Player sends action → Cardinal emits events.

4. GameState is Authoritative

One struct holds all truth. Everything else is derived from it.

Documentation

Document Audience Content
README_DETAILED.md Everyone Overview, concepts, quick start
BUILTIN_EFFECTS.md Card designers Complete reference for TOML-only card effects
SCRIPTING_GUIDE.md Advanced card designers Rhai scripting for custom card effects
ARCHITECTURE.md Developers Design principles, game flow, data structures
crates/cardinal/README.md API users Usage guide, integration examples, concepts
crates/cardinal-cli/README.md Players Terminal game guide, controls, examples
crates/cardinal/explanation.md Code explorers Design patterns, module layout, architecture

Project Structure

crates/
  cardinal/          — The game engine library
  cardinal-cli/      — Interactive terminal game

rules.toml          — Game definitions (cards, abilities, phases)
README_DETAILED.md  — Complete guide
ARCHITECTURE.md     — Design deep dive

Example: Playing a Card

You play "Goblin Scout":

1. Validation
   ✓ Your turn?
   ✓ Main phase?
   ✓ Own the card?
   ✓ In your hand?
   ✓ Have mana?

2. Apply Effect
   - Remove from hand
   - Add to field
   - Subtract mana
   → Event: CardPlayed, CardMoved

3. Evaluate Triggers
   - "enters the battlefield" trigger matches
   → Command: "deal 1 damage"

4. Resolve Stack
   - Opponent takes 1 damage
   → Event: LifeChanged

5. Return to Caller
   - Here are all the events that happened
   - UI renders them

Key Concepts

Concept Meaning
Zone Where a card is (hand, field, graveyard, stack, etc.)
Phase/Step Turn structure (start, main, combat, end)
Priority Whose turn to act (determines action order)
Trigger Card ability that fires on events
Stack Where spells/abilities wait to resolve
Event Something that happened (recorded for replay)
Command Intermediate effect awaiting validation

Tests

All tests passing:

cargo test

31 tests covering:

  • Game initialization
  • Turn progression
  • Action validation
  • Card abilities & triggers
  • Builtin effect execution
  • Scripted effect execution
  • State consistency
  • Determinism

Configuration

Edit rules.toml to:

  • Define new cards using builtin TOML effects (no scripting required!)
  • Add scripted cards (Rhai scripts in examples/scripts/)
  • Change mana costs
  • Add card abilities
  • Customize phases
  • Change game constants

No code changes needed. Cardinal supports both TOML-only cards and Rhai-scripted cards.

Card Design Approaches

1. TOML-Only Cards (Recommended for most cards) Use builtin effects without any scripting. See BUILTIN_EFFECTS.md for the complete reference.

Example:

[[cards]]
id = "lightning_bolt"
name = "Lightning Bolt"
card_type = "spell"
cost = "1"

[[cards.abilities]]
trigger = "on_play"
effect = "damage"
[cards.abilities.params]
amount = "3"

2. Scripted Cards (For complex custom behavior) Use Rhai scripts for unique mechanics. See SCRIPTING_GUIDE.md for details.

Available Builtin Effects

Cardinal supports 14 builtin effect types (1 partially implemented):

  • Life & Damage: damage, gain_life, lose_life, set_life
  • Card Draw: draw (⚠️ not yet fully implemented), move_card
  • Creature Stats: set_stats
  • Keywords: grant_keyword, remove_keyword
  • Resources: gain_resource, spend_resource, set_resource
  • Counters: add_counter, remove_counter
  • Tokens: create_token

See BUILTIN_EFFECTS.md for complete documentation and examples.

VS Code TOML Validation

Cardinal includes JSON schemas for validating TOML files in VS Code:

  1. Install the "Even Better TOML" extension (recommended automatically)
  2. Open any TOML file — invalid fields or values are highlighted
  3. Get autocomplete — Press Ctrl+Space for valid field suggestions
  4. See exact errors — Hover over red squiggles for validation messages

Schemas validate:

  • Individual card files (cards/*.toml)
  • Card array files (cards.toml)
  • Rules definitions (rules.toml)
  • Pack metadata (pack.toml)

See schemas/README.md for details.

Next Steps

  1. test-game/ — See a complete minimal game example
  2. README_DETAILED.md — Understand the system
  3. cargo run --bin cardinal-cli — Play the game
  4. BUILTIN_EFFECTS.md — Design cards without scripting
  5. crates/cardinal/README.md — Learn the API
  6. ARCHITECTURE.md — Deep dive into design
  7. Edit rules.toml — Customize your game

Summary

Cardinal is a clean, deterministic, reusable game engine:

  • One engine for any turn-based TCG
  • Many interfaces (terminal, web, mobile, AI)
  • Hybrid card system (TOML builtins + Rhai scripts)
  • Data-driven rules (TOML configuration)
  • Full determinism (perfect replays)
  • Well-tested (31 tests passing)

It's designed to be embedded, extended, and understood.

About

A rule engine for customizing and creating TCG games and game logic easily.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages