chore: rename app from Solitaire Quest to Ferrous Solitaire
Replace all display-name occurrences across web pages, Rust source, docs, and Cargo metadata. Update localStorage token key from sq_token to fs_token. Tagline "Klondike Solitaire" retained as genre descriptor. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
# Solitaire Quest — Architecture Document
|
# Ferrous Solitaire — Architecture Document
|
||||||
|
|
||||||
> **Version:** 1.3
|
> **Version:** 1.3
|
||||||
> **Language:** Rust (Edition 2024)
|
> **Language:** Rust (Edition 2024)
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
## 1. Project Overview
|
## 1. Project Overview
|
||||||
|
|
||||||
Solitaire Quest is a cross-platform Klondike Solitaire game written in Rust, targeting macOS, Windows, and Linux desktops. It features a full progression system with XP, levels, achievements, daily challenges, and an optional self-hosted sync server so statistics and progress are available across all of a player's devices.
|
Ferrous Solitaire is a cross-platform Klondike Solitaire game written in Rust, targeting macOS, Windows, and Linux desktops. It features a full progression system with XP, levels, achievements, daily challenges, and an optional self-hosted sync server so statistics and progress are available across all of a player's devices.
|
||||||
|
|
||||||
### Sync Backend by Platform
|
### Sync Backend by Platform
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
All notable changes to Solitaire Quest are documented here. The format is
|
All notable changes to Ferrous Solitaire are documented here. The format is
|
||||||
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this
|
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this
|
||||||
project follows [Semantic Versioning](https://semver.org/).
|
project follows [Semantic Versioning](https://semver.org/).
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
# Credits
|
# Credits
|
||||||
|
|
||||||
Solitaire Quest is MIT-licensed (see [LICENSE](LICENSE)). It is built on top of
|
Ferrous Solitaire is MIT-licensed (see [LICENSE](LICENSE)). It is built on top of
|
||||||
the work of many open-source projects and a small handful of third-party
|
the work of many open-source projects and a small handful of third-party
|
||||||
assets. This file lists every component that ships in the binary or in the
|
assets. This file lists every component that ships in the binary or in the
|
||||||
`assets/` directory.
|
`assets/` directory.
|
||||||
@@ -43,7 +43,7 @@ copyleft code is statically linked into the game binary.
|
|||||||
| File(s) | Source | License |
|
| File(s) | Source | License |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `solitaire_engine/assets/themes/default/{suit}_{rank}.svg` (52 SVGs) | [hayeah/playing-cards-assets](https://github.com/hayeah/playing-cards-assets) | MIT |
|
| `solitaire_engine/assets/themes/default/{suit}_{rank}.svg` (52 SVGs) | [hayeah/playing-cards-assets](https://github.com/hayeah/playing-cards-assets) | MIT |
|
||||||
| `solitaire_engine/assets/themes/default/back.svg` | Original — Solitaire Quest | MIT (this project) |
|
| `solitaire_engine/assets/themes/default/back.svg` | Original — Ferrous Solitaire | MIT (this project) |
|
||||||
| `assets/cards/faces/{RANK}{SUIT}.png` (52 PNGs) | Pre-rendered from the same `playing-cards-assets` SVGs | MIT (passed through from hayeah) |
|
| `assets/cards/faces/{RANK}{SUIT}.png` (52 PNGs) | Pre-rendered from the same `playing-cards-assets` SVGs | MIT (passed through from hayeah) |
|
||||||
| `assets/cards/backs/back_0.png` – `back_4.png` | Original — generated by `solitaire_assetgen::gen_art` | MIT (this project) |
|
| `assets/cards/backs/back_0.png` – `back_4.png` | Original — generated by `solitaire_assetgen::gen_art` | MIT (this project) |
|
||||||
|
|
||||||
@@ -107,6 +107,6 @@ Audio files are MIT-licensed alongside the rest of this project.
|
|||||||
backs, every audio file) are original work covered by this project's MIT
|
backs, every audio file) are original work covered by this project's MIT
|
||||||
license.
|
license.
|
||||||
|
|
||||||
If you redistribute Solitaire Quest, you must ship this `CREDITS.md` and the
|
If you redistribute Ferrous Solitaire, you must ship this `CREDITS.md` and the
|
||||||
`LICENSE` file alongside the binary so the MIT (project + hayeah card art)
|
`LICENSE` file alongside the binary so the MIT (project + hayeah card art)
|
||||||
and OFL (FiraMono) notices remain visible to end users.
|
and OFL (FiraMono) notices remain visible to end users.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Solitaire Quest
|
# Ferrous Solitaire
|
||||||
|
|
||||||
A cross-platform Klondike Solitaire game written in Rust, with a card-theme
|
A cross-platform Klondike Solitaire game written in Rust, with a card-theme
|
||||||
system, full progression (XP / levels / achievements / daily challenges), and
|
system, full progression (XP / levels / achievements / daily challenges), and
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
# Solitaire Quest — Self-Hosting Guide
|
# Ferrous Solitaire — Self-Hosting Guide
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
# Solitaire Quest — Session Handoff
|
# Ferrous Solitaire — Session Handoff
|
||||||
|
|
||||||
**Last updated:** 2026-05-12 — Leaderboard display name shipped (`03be4fc`). All commits pushed to origin.
|
**Last updated:** 2026-05-12 — Leaderboard display name shipped (`03be4fc`). All commits pushed to origin.
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ Items missing from the doc:
|
|||||||
## Resume prompt
|
## Resume prompt
|
||||||
|
|
||||||
```
|
```
|
||||||
You are a senior Rust + Bevy developer working on Solitaire Quest.
|
You are a senior Rust + Bevy developer working on Ferrous Solitaire.
|
||||||
Working directory: <Rusty_Solitaire clone path>.
|
Working directory: <Rusty_Solitaire clone path>.
|
||||||
Branch: master. v0.23.0 is the current version (HEAD: 03be4fc). Fully pushed.
|
Branch: master. v0.23.0 is the current version (HEAD: 03be4fc). Fully pushed.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Solitaire Quest — Session Handoff (ARCHIVED)
|
# Ferrous Solitaire — Session Handoff (ARCHIVED)
|
||||||
|
|
||||||
> **This file is from Phase 2 (2026-04-25, 242 tests). It is kept for historical
|
> **This file is from Phase 2 (2026-04-25, 242 tests). It is kept for historical
|
||||||
> reference only. The authoritative session handoff is at the repo root:
|
> reference only. The authoritative session handoff is at the repo root:
|
||||||
@@ -24,7 +24,7 @@ All seven Cargo crates created and compiling cleanly:
|
|||||||
| `solitaire_engine` | Stub | Bevy ECS systems — all plugins added in Phase 3 |
|
| `solitaire_engine` | Stub | Bevy ECS systems — all plugins added in Phase 3 |
|
||||||
| `solitaire_server` | Stub | Axum sync server — implemented in Phase 8C |
|
| `solitaire_server` | Stub | Axum sync server — implemented in Phase 8C |
|
||||||
| `solitaire_gpgs` | Compile-time stub | Google Play Games bridge — Android only, JNI in Phase: Android |
|
| `solitaire_gpgs` | Compile-time stub | Google Play Games bridge — Android only, JNI in Phase: Android |
|
||||||
| `solitaire_app` | Working | Opens blank Bevy window titled "Solitaire Quest" at 1280×800 |
|
| `solitaire_app` | Working | Opens blank Bevy window titled "Ferrous Solitaire" at 1280×800 |
|
||||||
|
|
||||||
Fast compile profiles, `assets/` directory structure, and `.env.example` are all in place.
|
Fast compile profiles, `assets/` directory structure, and `.env.example` are all in place.
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
> **Date:** 2026-04-28
|
> **Date:** 2026-04-28
|
||||||
> **Author:** Claude Code
|
> **Author:** Claude Code
|
||||||
> **Scope:** Feasibility analysis for porting Solitaire Quest to Android using cargo-mobile2
|
> **Scope:** Feasibility analysis for porting Ferrous Solitaire to Android using cargo-mobile2
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Solitaire Quest — Phase 1 + 2: Workspace & Core Game Engine
|
# Ferrous Solitaire — Phase 1 + 2: Workspace & Core Game Engine
|
||||||
|
|
||||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
@@ -555,7 +555,7 @@ fn main() {
|
|||||||
.add_plugins(
|
.add_plugins(
|
||||||
DefaultPlugins.set(WindowPlugin {
|
DefaultPlugins.set(WindowPlugin {
|
||||||
primary_window: Some(Window {
|
primary_window: Some(Window {
|
||||||
title: "Solitaire Quest".into(),
|
title: "Ferrous Solitaire".into(),
|
||||||
resolution: (1280.0, 800.0).into(),
|
resolution: (1280.0, 800.0).into(),
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
@@ -571,7 +571,7 @@ fn main() {
|
|||||||
```bash
|
```bash
|
||||||
cargo run -p solitaire_app --features bevy/dynamic_linking
|
cargo run -p solitaire_app --features bevy/dynamic_linking
|
||||||
```
|
```
|
||||||
Expected: A blank Bevy window titled "Solitaire Quest" opens. Press Escape or close the window to exit. No panics or errors in the terminal.
|
Expected: A blank Bevy window titled "Ferrous Solitaire" opens. Press Escape or close the window to exit. No panics or errors in the terminal.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1210,7 +1210,7 @@ fn main() {
|
|||||||
.add_plugins(
|
.add_plugins(
|
||||||
DefaultPlugins.set(WindowPlugin {
|
DefaultPlugins.set(WindowPlugin {
|
||||||
primary_window: Some(Window {
|
primary_window: Some(Window {
|
||||||
title: "Solitaire Quest".into(),
|
title: "Ferrous Solitaire".into(),
|
||||||
resolution: (1280.0, 800.0).into(),
|
resolution: (1280.0, 800.0).into(),
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
### Infrastructure
|
### Infrastructure
|
||||||
|
|
||||||
- Two machines (or VMs) referred to as **Machine A** and **Machine B** throughout this runbook. Both must be able to reach the sync server over the network.
|
- Two machines (or VMs) referred to as **Machine A** and **Machine B** throughout this runbook. Both must be able to reach the sync server over the network.
|
||||||
- A running Solitaire Quest sync server reachable at a known URL, e.g. `https://solitaire.example.com`. See `README_SERVER.md` for setup.
|
- A running Ferrous Solitaire sync server reachable at a known URL, e.g. `https://solitaire.example.com`. See `README_SERVER.md` for setup.
|
||||||
- Verify the server is live before starting:
|
- Verify the server is live before starting:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
> **Why this exists.** The 24 mockups in this directory are mobile
|
> **Why this exists.** The 24 mockups in this directory are mobile
|
||||||
> (390 × 844 logical, iPhone 14 Pro frame) with one exception
|
> (390 × 844 logical, iPhone 14 Pro frame) with one exception
|
||||||
> (`home-menu-desktop.html`). The Stitch project that produced them
|
> (`home-menu-desktop.html`). The Stitch project that produced them
|
||||||
> is named "Solitaire Quest *Mobile* Redesign" — the mobile-first
|
> is named "Ferrous Solitaire *Mobile* Redesign" — the mobile-first
|
||||||
> framing was deliberate when the new Android target opened, but
|
> framing was deliberate when the new Android target opened, but
|
||||||
> desktop is still the primary delivery surface. Porting the mobile
|
> desktop is still the primary delivery surface. Porting the mobile
|
||||||
> mockups 1:1 would land a 390-px-wide column floating in the middle
|
> mockups 1:1 would land a 390-px-wide column floating in the middle
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ required = true
|
|||||||
name = "android.permission.INTERNET"
|
name = "android.permission.INTERNET"
|
||||||
|
|
||||||
[package.metadata.android.application]
|
[package.metadata.android.application]
|
||||||
label = "Solitaire Quest"
|
label = "Ferrous Solitaire"
|
||||||
# Launcher icon — references the density-bucketed mipmap resource above.
|
# Launcher icon — references the density-bucketed mipmap resource above.
|
||||||
icon = "@mipmap/ic_launcher"
|
icon = "@mipmap/ic_launcher"
|
||||||
# `debuggable` defaults to false on release builds; cargo-apk flips it
|
# `debuggable` defaults to false on release builds; cargo-apk flips it
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ pub fn run() {
|
|||||||
DefaultPlugins
|
DefaultPlugins
|
||||||
.set(WindowPlugin {
|
.set(WindowPlugin {
|
||||||
primary_window: Some(Window {
|
primary_window: Some(Window {
|
||||||
title: "Solitaire Quest".into(),
|
title: "Ferrous Solitaire".into(),
|
||||||
// X11/Wayland WM_CLASS so taskbar managers group
|
// X11/Wayland WM_CLASS so taskbar managers group
|
||||||
// multiple windows of this app correctly.
|
// multiple windows of this app correctly.
|
||||||
name: Some("solitaire-quest".into()),
|
name: Some("solitaire-quest".into()),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Generates PNG assets for Solitaire Quest.
|
//! Generates PNG assets for Ferrous Solitaire.
|
||||||
//!
|
//!
|
||||||
//! Produces:
|
//! Produces:
|
||||||
//! - 52 card face PNGs (120×168) — one per card, with rank, suit symbol, and
|
//! - 52 card face PNGs (120×168) — one per card, with rank, suit symbol, and
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ pub enum SyncBackend {
|
|||||||
#[default]
|
#[default]
|
||||||
#[serde(rename = "local")]
|
#[serde(rename = "local")]
|
||||||
Local,
|
Local,
|
||||||
/// Sync with a self-hosted Solitaire Quest server.
|
/// Sync with a self-hosted Ferrous Solitaire server.
|
||||||
#[serde(rename = "solitaire_server")]
|
#[serde(rename = "solitaire_server")]
|
||||||
SolitaireServer {
|
SolitaireServer {
|
||||||
/// Base URL of the server, e.g. `"https://solitaire.example.com"`.
|
/// Base URL of the server, e.g. `"https://solitaire.example.com"`.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//! | Struct | Backend |
|
//! | Struct | Backend |
|
||||||
//! |---|---|
|
//! |---|---|
|
||||||
//! | [`LocalOnlyProvider`] | No-op; used when sync is disabled |
|
//! | [`LocalOnlyProvider`] | No-op; used when sync is disabled |
|
||||||
//! | [`SolitaireServerClient`] | Self-hosted Solitaire Quest server (JWT auth) |
|
//! | [`SolitaireServerClient`] | Self-hosted Ferrous Solitaire server (JWT auth) |
|
||||||
//!
|
//!
|
||||||
//! Use [`provider_for_backend`] to obtain a `Box<dyn SyncProvider + Send + Sync>`
|
//! Use [`provider_for_backend`] to obtain a `Box<dyn SyncProvider + Send + Sync>`
|
||||||
//! without matching on [`SyncBackend`] anywhere else in the codebase.
|
//! without matching on [`SyncBackend`] anywhere else in the codebase.
|
||||||
@@ -55,7 +55,7 @@ impl SyncProvider for LocalOnlyProvider {
|
|||||||
// SolitaireServerClient
|
// SolitaireServerClient
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
/// HTTP sync client for the self-hosted Solitaire Quest server.
|
/// HTTP sync client for the self-hosted Ferrous Solitaire server.
|
||||||
///
|
///
|
||||||
/// Authenticates via JWT stored in the OS keychain. On a 401 response the
|
/// Authenticates via JWT stored in the OS keychain. On a 401 response the
|
||||||
/// client automatically attempts a token refresh and retries the request once
|
/// client automatically attempts a token refresh and retries the request once
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! SVG builder for the Solitaire Quest application icon.
|
//! SVG builder for the Ferrous Solitaire application icon.
|
||||||
//!
|
//!
|
||||||
//! Renders the project's signature `▌RS` Terminal mark (the same
|
//! Renders the project's signature `▌RS` Terminal mark (the same
|
||||||
//! cursor-block + monogram pair used on the splash boot-screen and
|
//! cursor-block + monogram pair used on the splash boot-screen and
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Bevy integration layer for Solitaire Quest.
|
//! Bevy integration layer for Ferrous Solitaire.
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
pub mod android_clipboard;
|
pub mod android_clipboard;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Slides:
|
//! Slides:
|
||||||
//!
|
//!
|
||||||
//! 1. **Welcome** — brief introduction to Solitaire Quest.
|
//! 1. **Welcome** — brief introduction to Ferrous Solitaire.
|
||||||
//! 2. **How to play** — drag-and-drop, double-click, and right-click hints.
|
//! 2. **How to play** — drag-and-drop, double-click, and right-click hints.
|
||||||
//! 3. **Keyboard shortcuts** — a summary pulled from the same canonical list
|
//! 3. **Keyboard shortcuts** — a summary pulled from the same canonical list
|
||||||
//! used in `HelpScreen`. Accelerators: `Esc` anywhere in the flow skips
|
//! used in `HelpScreen`. Accelerators: `Esc` anywhere in the flow skips
|
||||||
@@ -292,10 +292,10 @@ fn spawn_slide(commands: &mut Commands, index: u8, font_res: Option<&FontResourc
|
|||||||
/// Slide 1 — Welcome.
|
/// Slide 1 — Welcome.
|
||||||
fn spawn_slide_welcome(commands: &mut Commands, font_res: Option<&FontResource>) {
|
fn spawn_slide_welcome(commands: &mut Commands, font_res: Option<&FontResource>) {
|
||||||
spawn_modal(commands, OnboardingScreen, Z_ONBOARDING, |card| {
|
spawn_modal(commands, OnboardingScreen, Z_ONBOARDING, |card| {
|
||||||
spawn_modal_header(card, "Welcome to Solitaire Quest", font_res);
|
spawn_modal_header(card, "Welcome to Ferrous Solitaire", font_res);
|
||||||
spawn_modal_body_text(
|
spawn_modal_body_text(
|
||||||
card,
|
card,
|
||||||
"Solitaire Quest is a free, offline-first Klondike Solitaire game. \
|
"Ferrous Solitaire is a free, offline-first Klondike Solitaire game. \
|
||||||
Play classic draw-1 or draw-3 Klondike, earn XP, unlock achievements, \
|
Play classic draw-1 or draw-3 Klondike, earn XP, unlock achievements, \
|
||||||
and compete on the leaderboard. Your progress is saved locally — \
|
and compete on the leaderboard. Your progress is saved locally — \
|
||||||
optional sync to your own server keeps it in step across all your devices.",
|
optional sync to your own server keeps it in step across all your devices.",
|
||||||
|
|||||||
@@ -2343,7 +2343,7 @@ fn sync_row(
|
|||||||
row,
|
row,
|
||||||
SettingsButton::ConnectSync,
|
SettingsButton::ConnectSync,
|
||||||
"Connect",
|
"Connect",
|
||||||
"Connect to a self-hosted Solitaire Quest sync server.".to_string(),
|
"Connect to a self-hosted Ferrous Solitaire sync server.".to_string(),
|
||||||
button_font,
|
button_font,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -2920,7 +2920,7 @@ mod tests {
|
|||||||
.expect("Connect button should spawn with a Tooltip when backend is Local");
|
.expect("Connect button should spawn with a Tooltip when backend is Local");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
connect_tip.as_ref(),
|
connect_tip.as_ref(),
|
||||||
"Connect to a self-hosted Solitaire Quest sync server.",
|
"Connect to a self-hosted Ferrous Solitaire sync server.",
|
||||||
"ConnectSync tooltip must use the canonical microcopy"
|
"ConnectSync tooltip must use the canonical microcopy"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//!
|
//!
|
||||||
//! On app start the engine spawns a fullscreen, high-Z overlay that
|
//! On app start the engine spawns a fullscreen, high-Z overlay that
|
||||||
//! reads the Terminal-style "boot screen" — an accent-coloured cursor block, the
|
//! reads the Terminal-style "boot screen" — an accent-coloured cursor block, the
|
||||||
//! "Solitaire Quest" wordmark, a short fixture boot log, a progress
|
//! "Ferrous Solitaire" wordmark, a short fixture boot log, a progress
|
||||||
//! bar, and a footer with the design-system palette swatches and the
|
//! bar, and a footer with the design-system palette swatches and the
|
||||||
//! build version. The overlay fades in over 300 ms, holds for ~1 s,
|
//! build version. The overlay fades in over 300 ms, holds for ~1 s,
|
||||||
//! then fades out for 300 ms before despawning. The deal animation
|
//! then fades out for 300 ms before despawning. The deal animation
|
||||||
@@ -383,7 +383,7 @@ fn spawn_header_section(parent: &mut ChildSpawnerCommands, font_handle: &Handle<
|
|||||||
));
|
));
|
||||||
hdr.spawn((
|
hdr.spawn((
|
||||||
SplashFadable { base_color: TEXT_PRIMARY },
|
SplashFadable { base_color: TEXT_PRIMARY },
|
||||||
Text::new("Solitaire Quest"),
|
Text::new("Ferrous Solitaire"),
|
||||||
title_font,
|
title_font,
|
||||||
TextColor(transparent(TEXT_PRIMARY)),
|
TextColor(transparent(TEXT_PRIMARY)),
|
||||||
));
|
));
|
||||||
@@ -1170,7 +1170,7 @@ mod tests {
|
|||||||
"expected the cursor block (▌) on the splash, got: {texts:?}"
|
"expected the cursor block (▌) on the splash, got: {texts:?}"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
texts.iter().any(|t| t == "Solitaire Quest"),
|
texts.iter().any(|t| t == "Ferrous Solitaire"),
|
||||||
"expected the wordmark on the splash, got: {texts:?}"
|
"expected the wordmark on the splash, got: {texts:?}"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Backend-agnostic sync plugin for Solitaire Quest.
|
//! Backend-agnostic sync plugin for Ferrous Solitaire.
|
||||||
//!
|
//!
|
||||||
//! On startup, the plugin spawns an async pull task on [`AsyncComputeTaskPool`]
|
//! On startup, the plugin spawns an async pull task on [`AsyncComputeTaskPool`]
|
||||||
//! that fetches the remote payload from the active [`SyncProvider`]. Once the
|
//! that fetches the remote payload from the active [`SyncProvider`]. Once the
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ mod tests {
|
|||||||
ThemeMeta {
|
ThemeMeta {
|
||||||
id: "default".into(),
|
id: "default".into(),
|
||||||
name: "Default".into(),
|
name: "Default".into(),
|
||||||
author: "Solitaire Quest".into(),
|
author: "Ferrous Solitaire".into(),
|
||||||
version: "1.0.0".into(),
|
version: "1.0.0".into(),
|
||||||
card_aspect: (2, 3),
|
card_aspect: (2, 3),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ mod tests {
|
|||||||
let meta = ThemeMeta {
|
let meta = ThemeMeta {
|
||||||
id: "default".into(),
|
id: "default".into(),
|
||||||
name: "Default".into(),
|
name: "Default".into(),
|
||||||
author: "Solitaire Quest".into(),
|
author: "Ferrous Solitaire".into(),
|
||||||
version: "1.0.0".into(),
|
version: "1.0.0".into(),
|
||||||
card_aspect: (2, 3),
|
card_aspect: (2, 3),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ fn default_entry() -> ThemeEntry {
|
|||||||
meta: ThemeMeta {
|
meta: ThemeMeta {
|
||||||
id: "default".to_string(),
|
id: "default".to_string(),
|
||||||
name: "Default".to_string(),
|
name: "Default".to_string(),
|
||||||
author: "Solitaire Quest".to_string(),
|
author: "Ferrous Solitaire".to_string(),
|
||||||
version: "1.0".to_string(),
|
version: "1.0".to_string(),
|
||||||
card_aspect: (2, 3),
|
card_aspect: (2, 3),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! Keyboard focus ring for modal buttons (Phase 1).
|
//! Keyboard focus ring for modal buttons (Phase 1).
|
||||||
//!
|
//!
|
||||||
//! Solitaire Quest's 11 modals (Help, Stats, Achievements, Settings,
|
//! Ferrous Solitaire's 11 modals (Help, Stats, Achievements, Settings,
|
||||||
//! Profile, Leaderboard, Pause, Forfeit confirm, GameOver, Confirm new
|
//! Profile, Leaderboard, Pause, Forfeit confirm, GameOver, Confirm new
|
||||||
//! game, Onboarding) ship without any keyboard focus support. Phase 1
|
//! game, Onboarding) ship without any keyboard focus support. Phase 1
|
||||||
//! gives every button spawned via [`crate::ui_modal::spawn_modal_button`]
|
//! gives every button spawned via [`crate::ui_modal::spawn_modal_button`]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Solitaire Quest sync server library.
|
//! Ferrous Solitaire sync server library.
|
||||||
//!
|
//!
|
||||||
//! Exposes [`build_router`] so integration tests can construct the full Axum
|
//! Exposes [`build_router`] so integration tests can construct the full Axum
|
||||||
//! application against an in-memory SQLite database without starting a real
|
//! application against an in-memory SQLite database without starting a real
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Solitaire Quest sync server entry point.
|
//! Ferrous Solitaire sync server entry point.
|
||||||
//!
|
//!
|
||||||
//! Reads configuration from environment variables (via `dotenvy`), initialises
|
//! Reads configuration from environment variables (via `dotenvy`), initialises
|
||||||
//! the SQLite database, runs migrations, then starts the Axum HTTP server.
|
//! the SQLite database, runs migrations, then starts the Axum HTTP server.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Solitaire Quest — interactive game page.
|
/* Ferrous Solitaire — interactive game page.
|
||||||
Palette mirrors the Bevy app's Terminal (base16-eighties) design system.
|
Palette mirrors the Bevy app's Terminal (base16-eighties) design system.
|
||||||
Card faces/backs are PNG images served from /assets/cards/. */
|
Card faces/backs are PNG images served from /assets/cards/. */
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Solitaire Quest — Play</title>
|
<title>Ferrous Solitaire — Play</title>
|
||||||
<link rel="stylesheet" href="/web/game.css">
|
<link rel="stylesheet" href="/web/game.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<div class="hud-left">
|
<div class="hud-left">
|
||||||
<a href="/" class="home-link" title="Home">←</a>
|
<a href="/" class="home-link" title="Home">←</a>
|
||||||
<span class="logo">Solitaire Quest</span>
|
<span class="logo">Ferrous Solitaire</span>
|
||||||
<span id="hud-seed" class="muted"></span>
|
<span id="hud-seed" class="muted"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="hud-center">
|
<div class="hud-center">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Solitaire Quest — interactive browser game.
|
// Ferrous Solitaire — interactive browser game.
|
||||||
//
|
//
|
||||||
// Architecture:
|
// Architecture:
|
||||||
// - `SolitaireGame` (Rust/WASM via solitaire_core) owns all rule logic.
|
// - `SolitaireGame` (Rust/WASM via solitaire_core) owns all rule logic.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Solitaire Quest</title>
|
<title>Ferrous Solitaire</title>
|
||||||
<style>
|
<style>
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "FiraMono";
|
font-family: "FiraMono";
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="logo">Solitaire Quest</div>
|
<div class="logo">Ferrous Solitaire</div>
|
||||||
<div class="tagline">Klondike Solitaire</div>
|
<div class="tagline">Klondike Solitaire</div>
|
||||||
|
|
||||||
<nav class="cards">
|
<nav class="cards">
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Solitaire Quest — Replay</title>
|
<title>Ferrous Solitaire — Replay</title>
|
||||||
<link rel="stylesheet" href="/web/replay.css">
|
<link rel="stylesheet" href="/web/replay.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1>Solitaire Quest <span class="muted">— Replay</span></h1>
|
<h1>Ferrous Solitaire <span class="muted">— Replay</span></h1>
|
||||||
<div id="caption" class="muted">Loading…</div>
|
<div id="caption" class="muted">Loading…</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Solitaire Quest — Leaderboard</title>
|
<title>Ferrous Solitaire — Leaderboard</title>
|
||||||
<style>
|
<style>
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "FiraMono";
|
font-family: "FiraMono";
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
</table>
|
</table>
|
||||||
</main>
|
</main>
|
||||||
<script>
|
<script>
|
||||||
const TOKEN_KEY = 'sq_token';
|
const TOKEN_KEY = 'fs_token';
|
||||||
function fmtTime(secs) {
|
function fmtTime(secs) {
|
||||||
if (!secs) return '—';
|
if (!secs) return '—';
|
||||||
const m = Math.floor(secs / 60), s = secs % 60;
|
const m = Math.floor(secs / 60), s = secs % 60;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Solitaire Quest replay viewer — Terminal (base16-eighties) palette,
|
/* Ferrous Solitaire replay viewer — Terminal (base16-eighties) palette,
|
||||||
matching the Bevy desktop/Android app's ui_theme.rs tokens exactly. */
|
matching the Bevy desktop/Android app's ui_theme.rs tokens exactly. */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Solitaire Quest replay viewer.
|
// Ferrous Solitaire replay viewer.
|
||||||
//
|
//
|
||||||
// Pulls the replay JSON from `/api/replays/:id`, hands it to the
|
// Pulls the replay JSON from `/api/replays/:id`, hands it to the
|
||||||
// `solitaire_wasm` ReplayPlayer (which owns a real solitaire_core
|
// `solitaire_wasm` ReplayPlayer (which owns a real solitaire_core
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Solitaire Quest — Recent Replays</title>
|
<title>Ferrous Solitaire — Recent Replays</title>
|
||||||
<style>
|
<style>
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "FiraMono";
|
font-family: "FiraMono";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Shared API types and merge logic for Solitaire Quest.
|
//! Shared API types and merge logic for Ferrous Solitaire.
|
||||||
//!
|
//!
|
||||||
//! This crate is the contract between the game client (`solitaire_data`) and
|
//! This crate is the contract between the game client (`solitaire_data`) and
|
||||||
//! the sync server (`solitaire_server`). Changing any public type here is a
|
//! the sync server (`solitaire_server`). Changing any public type here is a
|
||||||
|
|||||||
Reference in New Issue
Block a user