diff --git a/CHANGELOG.md b/CHANGELOG.md index 5eda73d..994d62c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,11 @@ `impl_rich_component!` for `Board` and `Players`, and `impl_soroban_game!` for load/save. Public API is unchanged; all existing tests pass - README rewritten with clean 30-line quick start and full feature documentation +- canonical example set expanded from three (`snake`, `battleship`, `guild_arena`) to ten: + `spawn_and_move` (Starter), `tic_tac_toe` (Rich components), `session_arena` (Session UX), + `hidden_hand`, `fog_explorer`, `dice_duel`, `blind_auction` (ZK circuits), + `snake` (Arcade/GameApp), `battleship` (Hidden information), `guild_arena` (Auth & recovery) +- `session_arena` example added as canonical reference for `session::SessionManager` ### Stability Notes diff --git a/examples/EXAMPLE_STANDARD.md b/examples/EXAMPLE_STANDARD.md index fc55840..b24008b 100644 --- a/examples/EXAMPLE_STANDARD.md +++ b/examples/EXAMPLE_STANDARD.md @@ -13,18 +13,57 @@ Examples are the primary onboarding surface for external developers building gam Every example must declare `cougr-core` using the published crate on crates.io, **not** a local path dependency. ```toml -# Correct +# Correct — external release [dependencies] -cougr-core = "1.0" +cougr-core = "1.1" soroban-sdk = "25.1.0" -# Wrong — breaks for external users +# Wrong for published examples — breaks for external users [dependencies] cougr-core = { path = "../../" } + ``` Path dependencies silently work inside the monorepo but fail for any developer who installs the example independently. The published crate is the contract. +### 1.1 Path Dependencies in Monorepo Development + +Some canonical examples depend on APIs that have not yet been published to crates.io (e.g. `circuits`, `session`, `SorobanGame`). These examples **must** use path dependencies during monorepo development but **must** switch to published versions before any release tag is cut. + +**When path dependencies are permitted:** + +* The example exercises an API that exists only in the workspace copy of `cougr-core` (e.g. `cougr_core::circuits::*`, `cougr_core::session::*`, `cougr_core::test::*`). +* The example is under active development inside the monorepo and no crate version on crates.io yet includes the required API. + +**When path dependencies must be replaced:** + +* Before cutting a release tag (including release candidates), every example's `Cargo.toml` must be updated to reference the published crate version. +* If the required API is available in a published version, the path dependency must be replaced immediately, even outside a release cycle. + +**How to mark a path-dependency example:** + +Add a comment above the dependency line explaining the exception: + +```toml +# path dep — pending cougr-core 1.x publication of circuits::* +cougr-core = { path = "../../" } + +``` + +CI must fail if any example still carries a path dependency at release-tag time. + +**Current examples using path dependencies (as of 1.1.0):** + +| Example | Reason for path dependency | +| --- | --- | +| `spawn_and_move` | Exercises `SorobanGame` / `impl_soroban_game!` | +| `tic_tac_toe` | Exercises `impl_soroban_game!` and `impl_rich_component!` | +| `session_arena` | Exercises `session::SessionManager` (Beta) | +| `hidden_hand` | Exercises `circuits::hidden_cards` (Experimental) | +| `fog_explorer` | Exercises `circuits::fog_of_war` (Experimental) | +| `dice_duel` | Exercises `circuits::fair_dice` (Experimental) | +| `blind_auction` | Exercises `circuits::sealed_bid` (Experimental) | + --- ## 2. Required Validation Commands @@ -34,6 +73,7 @@ Every example must pass both of the following commands without errors or warning ```bash cargo test stellar contract build + ``` `cargo test` validates the game logic in the Soroban test environment. `stellar contract build` validates that the contract compiles to a valid WASM artifact using the Stellar toolchain. A Rust crate that compiles with `cargo build` but fails `stellar contract build` is not a valid Soroban contract. @@ -56,12 +96,13 @@ examples// ├── lib.rs # Contract entrypoints, #[contract] impl, GameApp wiring ├── components.rs # Cougr components (impl_component! types) └── systems.rs # Game systems registered with GameApp + ``` ### Extended layout (use when applicable) | File | When to add | -|---|---| +| --- | --- | | `types.rs` | Domain enums or structs shared across modules but not Cougr components | | `auth.rs` | Session key setup, `CougrAccount` wiring, multi-device logic | | `privacy.rs` | Commit-reveal flows, Merkle proof helpers, hidden-state management | @@ -76,7 +117,7 @@ Do not add files that are not used. Do not collapse `components.rs` and `systems Every example must have a `README.md` that covers all of the following sections. Keep each section concise; depth belongs in inline code comments, not in the README. | Section | Required content | -|---|---| +| --- | --- | | **Purpose and pattern** | One paragraph: what game mechanic does this demonstrate and which Cougr pattern does it showcase? | | **Public contract API** | A table or list of every `#[contractimpl]` function: name, parameters, return type, one-line description | | **Architecture overview** | How systems, components, and the `GameApp` tick interact. A short prose description or ASCII diagram | @@ -95,7 +136,7 @@ Avoid embedding hardcoded contract IDs, testnet addresses, or deployment results Each example must have a test module (typically `src/lib.rs` inline tests or `src/test.rs`) that covers the following categories: | Category | What to test | -|---|---| +| --- | --- | | **Initialization** | Calling the init function produces valid starting state | | **Happy-path gameplay** | One full game round proceeds without errors | | **Invalid actions** | Illegal moves, out-of-turn actions, or bad input return the expected error | @@ -108,10 +149,10 @@ Tests must use the `soroban-sdk` `testutils` feature and `Env::default()`. Do no ## 6. Repository Hygiene -- Do not commit `target/` directories. Each example's `.gitignore` (or the root `.gitignore`) must exclude them. -- Do not commit `.wasm` artifacts, `*.wasm`, or build output. -- `Cargo.lock` should be committed for examples (they are end-user applications, not libraries). -- Keep `Cargo.toml` minimal: only direct dependencies, no unused features, no wildcard version specifiers. +* Do not commit `target/` directories. Each example's `.gitignore` (or the root `.gitignore`) must exclude them. +* Do not commit `.wasm` artifacts, `*.wasm`, or build output. +* `Cargo.lock` should be committed for examples (they are end-user applications, not libraries). +* Keep `Cargo.toml` minimal: only direct dependencies, no unused features, no wildcard version specifiers. --- @@ -121,13 +162,20 @@ Tests must use the `soroban-sdk` `testutils` feature and `Env::default()`. Do no A canonical example is a maintained reference architecture. It is held to the full standard in this document and is expected to stay current as `cougr-core` evolves. Canonical examples are the ones new contributors should read first. -Current canonical examples: - -| Example | Pattern demonstrated | -|---|---| -| `snake` | Arcade loop, `GameApp` tick model, basic ECS | -| `battleship` | Hidden-information, commit-reveal, `privacy::stable` Merkle primitives | -| `guild_arena` | Account abstraction, social recovery, multi-device authorization | +Current canonical examples (aligned with the 1.1.0 release): + +| Example | Category | Pattern demonstrated | +| --- | --- | --- | +| `spawn_and_move` | Starter | Complete idiomatic Cougr pattern: `SorobanGame` + `impl_component_observed!` + typed ECS | +| `tic_tac_toe` | Rich components | Turn-based game with `impl_rich_component!` for `Address` and `Vec` fields | +| `session_arena` | Session UX | `session::SessionManager`, session lifecycle, and multi-round state (Beta) | +| `hidden_hand` | ZK circuits | `circuits::hidden_cards` — hidden-card ZK proof flow (Experimental) | +| `fog_explorer` | ZK circuits | `circuits::fog_of_war` — fog-of-war exploration with Merkle proofs (Experimental) | +| `dice_duel` | ZK circuits | `circuits::fair_dice` — fair dice roll with on-chain verification (Experimental) | +| `blind_auction` | ZK circuits | `circuits::sealed_bid` — sealed-bid auction with commit-reveal ZK (Experimental) | +| `snake` | Arcade (GameApp) | Arcade loop, `GameApp` tick model, basic ECS | +| `battleship` | Hidden information | Commit-reveal and selective state disclosure using `privacy::stable` Merkle primitives | +| `guild_arena` | Authentication & recovery | Account abstraction, social recovery, multi-device authorization | ### Transitional examples @@ -136,6 +184,7 @@ A transitional example is one that was written before the current standard or th ```markdown > **Transitional example**: This example uses an older Cougr pattern and is preserved > for compatibility reference. For the current recommended approach, see `snake`. + ``` Transitional examples are still expected to pass `cargo test` and `stellar contract build`. They are not required to match the module structure or README depth of canonical examples, but they must not mislead readers into thinking the older pattern is preferred. @@ -146,19 +195,47 @@ Transitional examples are still expected to pass `cargo test` and `stellar contr Use the following table to decide which Cougr APIs an example should use and document. -| API | Use when | -|---|---| -| `GameApp` | Any example with more than one system or stage | -| `ScheduleStage` | Systems must run in a defined order within a tick | -| `SimpleWorld` | The example stores and queries entities with multiple components | -| `SimpleQueryBuilder` | The example scans entities by component type (more than one entity type) | -| `auth` (Beta) | The example demonstrates session keys, multi-device flows, or account recovery | -| `privacy::stable` | The example demonstrates commit-reveal, Merkle proofs, or selective disclosure | -| `privacy::experimental` | The example demonstrates Groth16 proof submission or BN254/BLS12-381 operations | -| `ops` standards | The example needs pausability, access control, or ownership transfer | +| API | Use when | Stability | +| --- | --- | --- | +| `SorobanGame` trait | Any example that loads/saves `SimpleWorld` to Soroban storage; implement once with `impl_soroban_game!` | Stable | +| `impl_soroban_game!` macro | Wiring `SorobanGame` to a `#[contract]` struct; replaces manual `load_world` / `save_world` boilerplate | Stable | +| `GameApp` | Any example with more than one system or stage | Stable | +| `ScheduleStage` | Systems must run in a defined order within a tick | Stable | +| `SimpleWorld` | The example stores and queries entities with multiple components | Stable | +| `SimpleQueryBuilder` | The example scans entities by component type (more than one entity type) | Stable | +| `impl_rich_component!` | A component contains `Address` or `Vec` fields that need Soroban-native storage | Stable | +| `session::SessionManager` | The example manages multi-round player sessions, timeouts, or session-key lifecycle | Beta | +| `circuits::hidden_cards` | The example demonstrates hidden-card ZK proof flows | Experimental | +| `circuits::fog_of_war` | The example demonstrates fog-of-war exploration with Merkle proof verification | Experimental | +| `circuits::fair_dice` | The example demonstrates fair dice roll with on-chain Groth16 verification | Experimental | +| `circuits::sealed_bid` | The example demonstrates sealed-bid auctions with commit-reveal ZK proofs | Experimental | +| `test::GameHarness` | Writing integration tests that exercise full game rounds in a sandboxed Soroban environment; pair with `Scenario` and `ReplayLog` | Experimental | +| `auth` (Beta) | The example demonstrates session keys, multi-device flows, or account recovery | Beta | +| `privacy::stable` | The example demonstrates commit-reveal, Merkle proofs, or selective disclosure | Stable | +| `privacy::experimental` | The example demonstrates Groth16 proof submission or BN254/BLS12-381 operations | Experimental | +| `ops` standards | The example needs pausability, access control, or ownership transfer | Stable | When an API is used, the README must explain **why** that API was chosen, not just that it was used. +### API–Example Cross Reference + +The following table maps each canonical example to its primary Cougr APIs: + +| Example | Primary APIs | +| --- | --- | +| `spawn_and_move` | `SorobanGame`, `impl_soroban_game!`, `impl_component_observed!`, `SimpleWorld`, `SimpleQueryBuilder` | +| `tic_tac_toe` | `SorobanGame`, `impl_soroban_game!`, `impl_rich_component!`, `GameApp` | +| `session_arena` | `SorobanGame`, `session::SessionManager`, `GameApp` | +| `hidden_hand` | `SorobanGame`, `circuits::hidden_cards`, `privacy::experimental` | +| `fog_explorer` | `SorobanGame`, `circuits::fog_of_war`, `privacy::stable` | +| `dice_duel` | `SorobanGame`, `circuits::fair_dice`, `privacy::experimental` | +| `blind_auction` | `SorobanGame`, `circuits::sealed_bid`, `privacy::experimental` | +| `snake` | `GameApp`, `ScheduleStage`, `SimpleWorld`, `SimpleQueryBuilder` | +| `battleship` | `privacy::stable`, `GameApp`, `SimpleWorld` | +| `guild_arena` | `auth`, `ops::Ownable`, `ops::RecoveryGuard`, `GameApp` | + +> **Note:** All `circuits::*` functions return a `GameCircuitSpec` and are currently considered **Experimental** (matching the `CHANGELOG.md`). + --- ## Quality Checklist @@ -169,7 +246,7 @@ Copy this checklist into a follow-up cleanup issue for each example: ## Example quality checklist — `` ### Dependencies -- [ ] Uses published `cougr-core` version, not a path dependency +- [ ] Uses published `cougr-core` version, not a path dependency — **or** carries an annotated path dependency exception per §1.1 ### Build validation - [ ] `cargo test` passes @@ -208,5 +285,6 @@ Copy this checklist into a follow-up cleanup issue for each example: ### Classification - [ ] Marked as canonical or transitional in the README +- [ ] If canonical: category matches one listed in §7 (Starter, Rich components, Session UX, ZK circuits, Arcade, Hidden information, Authentication & recovery) - [ ] If transitional: banner note present pointing to preferred alternative -``` + diff --git a/examples/README.md b/examples/README.md index a01b07e..d88fdd3 100644 --- a/examples/README.md +++ b/examples/README.md @@ -23,33 +23,77 @@ stellar contract build `stellar contract build` is required for all examples, not optional. An example that only passes `cargo build` is not a valid Soroban contract. +## Recommended Reading Order + +New contributors and external developers should read the examples in the following order to build understanding incrementally: + +1. **`spawn_and_move`** — Start here. Demonstrates the complete idiomatic Cougr pattern: `SorobanGame` + `impl_component_observed!` + typed ECS. +2. **`tic_tac_toe`** — Turn-based game with `impl_rich_component!` for `Address` and `Vec` fields. Shows how to structure a small-state game. +3. **`snake`** — Arcade loop, `GameApp` tick model, and basic ECS. Introduces the stage-scheduling model for continuous gameplay. +4. **`battleship`** — Hidden-information / commit-reveal flow using `privacy::stable` Merkle primitives. Entry point for privacy-aware games. +5. **`session_arena`** — `session::SessionManager` lifecycle and multi-round state. Demonstrates the session UX pattern (Beta). +6. **`hidden_hand`** — First ZK example. `circuits::HiddenHandBuilder` for hidden-card proof flows (Experimental). +7. **`fog_explorer`** — `circuits::FogExplorerBuilder` for fog-of-war exploration with Merkle proofs (Experimental). +8. **`dice_duel`** — `circuits::FairDiceBuilder` for fair dice roll with on-chain Groth16 verification (Experimental). +9. **`blind_auction`** — `circuits::SealedBidBuilder` for sealed-bid auctions with commit-reveal ZK proofs (Experimental). +10. **`guild_arena`** — Account recovery and multi-device authorization. Demonstrates `auth` and `ops` standards. + +After reading the canonical examples, explore transitional examples for additional patterns and genre-specific techniques. + ## Example Catalog +### Canonical examples + +These are the maintained reference architectures. They are held to the full standard in [EXAMPLE_STANDARD.md](./EXAMPLE_STANDARD.md) and stay current as `cougr-core` evolves. + | Example | Category | Focus | |---|---|---| | `spawn_and_move` | **Starter / canonical** | Complete idiomatic Cougr pattern: `SorobanGame` + `impl_component_observed!` + typed ECS | -| `angry_birds` | Physics-inspired arcade | Projectile logic and destructible-state style gameplay | +| `tic_tac_toe` | **Rich components / canonical** | Turn-based game with `impl_rich_component!` for `Address` and `Vec` fields | +| `session_arena` | **Session UX / canonical** | `session::SessionManager` lifecycle and multi-round state (Beta) | +| `hidden_hand` | **ZK circuits / canonical** | `circuits::HiddenHandBuilder` — hidden-card ZK proof flow (Experimental) | +| `fog_explorer` | **ZK circuits / canonical** | `circuits::FogExplorerBuilder` — fog-of-war exploration with Merkle proofs (Experimental) | +| `dice_duel` | **ZK circuits / canonical** | `circuits::FairDiceBuilder` — fair dice roll with on-chain verification (Experimental) | +| `blind_auction` | **ZK circuits / canonical** | `circuits::SealedBidBuilder` — sealed-bid auction with commit-reveal ZK (Experimental) | +| `snake` | **Arcade (GameApp) / canonical** | Arcade loop, `GameApp` tick model, basic ECS | +| `battleship` | **Hidden information / canonical** | Commit-reveal and selective state disclosure using `privacy::stable` | +| `guild_arena` | **Authentication & recovery / canonical** | Account abstraction, social recovery, multi-device authorization | + +### Transitional examples + +These examples were written before the current standard or intentionally preserve an older pattern for compatibility reference. They still pass `cargo test` and `stellar contract build` but may not follow the latest module structure or README depth. + +| Example | Category | Focus | +|---|---|---| +| `ai_dungeon_master_arena` | ZK / x402 | Proof-backed encounters and x402 premium actions | +| `angry_birds` | Physics-inspired arcade | Projectile logic and destructible-state gameplay | | `arkanoid` | Arcade | Paddle, collision, and brick lifecycle management | | `asteroids` | Arcade | Entity-heavy movement, collisions, and spawning | -| `battleship` | Board / hidden information | Commit-reveal and selective state disclosure | | `bomberman` | Grid action | Tile updates, hazards, and timed interactions | +| `checkers` | Board | Jump/capture rules and multi-step turn validation | | `chess` | Board / strategy | Rule validation and proof-oriented move flow | +| `connect_four` | Board | Gravity-drop column logic and vertical/horizontal/diagonal win detection | +| `cross_asset_racing_league` | Multi-asset racing | Payment-gated boost mechanics with cross-asset payment flows | | `flappy_bird` | Arcade | Tight tick-loop updates and obstacle generation | | `geometry_dash` | Reflex | Deterministic timing and obstacle progression | -| `guild_arena` | Account patterns | Social recovery and multi-device gameplay | +| `guild_treasury_wars` | DAO / ZK | DAO-governed factions with stellar-zk commitments | +| `memory_match` | Card matching | Pair-reveal mechanics and memory-state tracking | +| `minesweeper` | Puzzle | Grid reveal, mine detection, and adjacency logic | | `murdoku` | Puzzle | Ephemeral ECS validation and creator registry | | `pac_man` | Maze action | Grid navigation and adversarial movement patterns | | `pokemon_mini` | Turn-based battle | Combat sequencing and match state transitions | | `pong` | Arcade | Minimal competitive loop and ECS fundamentals | -| `proof_of_hunt` | Hidden-state exploration | stellar-zk style proof verification and x402 premium actions | +| `proof_of_hunt` | Hidden-state exploration | stellar-zk proof verification and x402 premium actions | +| `reversi` | Board | Piece-flipping logic and territory control | | `rock_paper_scissors` | Commit-reveal | Hidden choices and reveal resolution | -| `snake` | Arcade | Growth mechanics and collision rules | +| `shadow_draft_card_game` | Card / hidden-hand | Hidden-hand draft with SHA-256 commit-reveal | | `space_invaders` | Wave shooter | Formation movement and repeated tick systems | +| `sudoku` | Puzzle | Grid constraints and cell-entry validation | | `tap_battle` | Casual competitive | Lightweight action resolution and progression | | `tetris` | Puzzle | Piece state, rotation, and board clearing | -| `treasure_hunt` | Hidden-state exploration | Off-chain Merkle map commitments with on-chain proof-gated discovery and sparse fog-of-war | -| `tic_tac_toe` | Board | Small-state deterministic turn handling | +| `tower_defense` | Strategy | Wave spawning, tower attacks, and health reduction | | `trading_card_game` | Card / strategy | Structured turns, card effects, and state composition | +| `treasure_hunt` | Hidden-state exploration | Off-chain Merkle map commitments with on-chain proof-gated discovery | ## Choosing A Reference @@ -58,30 +102,35 @@ Use examples by pattern, not only by genre: | If you need to study | Good starting points | |---|---| | **First-time onboarding** | `spawn_and_move` | +| `SorobanGame` / `impl_soroban_game!` | `spawn_and_move`, `tic_tac_toe` | | Basic ECS structure | `spawn_and_move`, `pong`, `snake`, `tetris` | | Rich components (`Address`, `Vec`) | `tic_tac_toe`, `trading_card_game` | +| Session management (Beta) | `session_arena` | | Hidden state or commit-reveal | `battleship`, `rock_paper_scissors` | +| ZK circuits (Experimental) | `hidden_hand`, `fog_explorer`, `dice_duel`, `blind_auction` | +| Arcade / GameApp tick loop | `snake`, `asteroids`, `space_invaders` | | Turn-based logic | `tic_tac_toe`, `pokemon_mini`, `chess` | -| Account abstraction patterns | `guild_arena` | +| Account abstraction & recovery | `guild_arena` | +| Testing with `GameHarness` | `spawn_and_move`, `tic_tac_toe` (see `testutils` feature) | | Larger multi-entity loops | `asteroids`, `space_invaders`, `pac_man` | -| ZK proof / fog-of-war | `treasure_hunt`, `proof_of_hunt` | ## Preferred Runtime Shape For new examples and new production contracts, prefer the modern Cougr runtime path: -- `GameApp` as the entrypoint +- `SorobanGame` + `impl_soroban_game!` for load/save boilerplate +- `GameApp` as the entrypoint for multi-system contracts - explicit stage placement for systems - `SimpleQueryBuilder` for non-trivial world scans +- `impl_rich_component!` for components containing `Address` or `Vec` fields - table storage for hot-loop gameplay state -For examples that intentionally preserve older patterns, keep them explicitly -documented as compatibility or transition references rather than presenting -them as the default onboarding path. +For examples that intentionally preserve older patterns, keep them explicitly documented as compatibility or transition references rather than presenting them as the default onboarding path. + +## Path Dependency Note -## Canonical References -The maintained reference architectures for Cougr should be read in this order: +Some canonical examples use `path = "../../"` dependencies because they exercise APIs (`circuits`, `session`, `SorobanGame`) not yet published to crates.io. These path dependencies are permitted during monorepo development but must be replaced with published crate versions before any release tag is cut. See [EXAMPLE_STANDARD.md §1.1](./EXAMPLE_STANDARD.md#11-path-dependencies-in-monorepo-development) for the full policy. - `spawn_and_move`: **start here** — canonical onboarding example showing the full modern Cougr pattern (`SorobanGame`, `impl_component_observed!`, typed ECS) - `tic_tac_toe`: turn-based game showing rich components (`impl_rich_component!`, `impl_soroban_game!`) for `Address` and `Vec` fields @@ -95,6 +144,7 @@ The maintained reference architectures for Cougr should be read in this order: - `dice_duel`: verifiable on-chain dice rolling via `circuits::fair_dice` - `blind_auction`: sealed-bid auction reveals via `circuits::sealed_bid` + ## Conventions - Keep each example self-contained. @@ -110,5 +160,6 @@ Before adding a new example: 2. keep the directory standalone and runnable on its own 3. include a local `README.md` with scope, commands, and design notes 4. add or update a CI workflow if the example should be validated automatically +5. classify the example as canonical or transitional and document its category For contribution expectations across the repository, see [CONTRIBUTING.md](../CONTRIBUTING.md).