Skip to content
99ersstudio
All work
Games/Live

Card Games Portfolio

Schafkopf, Doppelkopf, Skat, Hearts, Shithead — five card games on one shared Flutter platform. 878 tests, zero analyzer issues.

5
games
878
tests
6
app shells

The problem

Shipping five card games tempts you toward one of two failure modes: one giant engine that tries to model every regional rule and collapses under Schafkopf's Davonlaufen edge case, or five independent codebases that explode maintenance, store presence, and onboarding cost. We wanted a shared platform that proves itself under genuinely different game shapes — 3 vs 4 players, 32 vs 48 cards, trick-taking vs shedding, scoring-up vs avoidance — without compromising on per-game authenticity.

How we built it

  1. 01Split the monorepo into a shared platform (`card_core`, `game_runtime`, `persistence_core`, `monetization_core`, `ui_kit`, `shared_test_tools`) and per-game cores (`schafkopf_core`, `doppelkopf_core`, `skat_core`, `hearts_core`, `shithead_core`, `watten_core`). Game-specific rules live in game packages and never leak into shared.
  2. 02Kept all rules / AI / scoring / serialisation in pure Dart so the full 878-test suite runs without Flutter. Each game implements the same five contracts: `RulesEngine`, `ScoringResolver`, `AiAdapter`, `Serializer`, `StateMachine`, plus a `TutorialAdapter` with phase-aware hints.
  3. 03Used each new game as a platform-validation forcing function: Schafkopf (4-player, 32-card, Bavarian, Contra/Retour) shipped first, then Doppelkopf (4-player, 48-card double deck, Re/Kontra, Hochzeit) and Skat (3-player, competitive bidding, Matadors chain, overbid detection) — both added with zero shared-package modifications.
  4. 04Hardened with a DRY refactor: extracted `GameControllerBase` (377 lines) and three generic `SharedPrefs` stores into `ui_kit`, removing ~1,700 lines of duplication from the five app shells. All shells now extend `GameControllerBase` and prefix their local storage keys.
  5. 05Wired Melos 7 (pub workspaces) for one-shot `melos run analyze` / `test:dart` / `test:flutter` / `format:check` / `build:android` plus a release-gate script that fails the build on any analyzer issue or test failure across the workspace.

Outcome

Milestone F complete — polish, AI (relaxed / standard / strong, MCTS for trick games), Firebase-based multiplayer rooms for all five games with a cross-game browser in the launcher, and store readiness (SVG icons, listings DE+EN, privacy policy, R8 minification, resource shrinking, applicationId namespace `com.ninetyninersstudio.*`). 878 tests passing, zero `dart analyze` / `flutter analyze` issues, all five apps versioned 1.0.0+1 and ready for keystore + release build.

Stack

FlutterDartMelosFirebase

Flutter 3.41.4 · Dart 3.11.1 · Melos 7 (pub workspaces) · pure-Dart per-game cores · Firebase for optional multiplayer rooms · `flutter_launcher_icons` for SVG → mipmap pipeline · GitHub Actions CI running the full Melos test suite.

Next up

Real PNG launcher icons, release keystore, Firebase project for production multiplayer, device testing across the five shells. Sixth game (Watten) cores already in the workspace; the platform-validation pattern is the same as games four and five.

More case studies