Skip to content

// project

Gaddi

A Hinglish social-deduction bluffing game of power, satire & second chances. Gaddi ke liye kuch bhi karega.

The brief

Gaddi is a Hinglish social-deduction bluffing game set in a satirical India corporate-political underworld where six archetypes scheme for an empty chair, the Gaddi, and everyone is lying about what they hold. The Neta makes promises he'll forget tomorrow, the Bhai owns silence, the Babu approves nothing, the Jugaadu knows a shortcut, the Vakil has read every exception. Satire targets the archetype, never the person. Under the deadpan Hinglish voice ("सब मिले हुए हैं") sits a serious engineering exercise: one deterministic Kotlin engine that runs identically on Android, iOS, desktop and the web, and powers the AI, the UI and a server-authoritative backend from the same code.

What shipped

  • Pure (GameState, Intent) → GameState reducer drives the AI, UI, and a future server.
  • ISMCTS AI with 10 bot personas plus a DARBAR social layer for bluffing and alliances.
Kotlin MultiplatformCompose MultiplatformAndroidiOSDesktopWeb (Wasm)
GitHub Install it 15 modules · 4 platforms · 10 bot personas
built on
kmp-build-logic
kmp-toolkit
ships to
Headless CLI

no public push in the last 20 events

// case study

The short version

The problem

A hidden-information bluffing game handed every player the same expert board on turn one, suspicion odds and a live teleprinter log included, which is exactly the kind of interface that loses a first-timer before their first bluff.

The decision

Split the board into three density layers a player graduates through by playing, not a settings toggle: FOCUS shows only whose turn it is, one plain-language line, and your legal moves; GUIDED adds coaching; ANALYST is the full instrument panel.

The result

All three layers, the AI, and a future server read the same deterministic (GameState, Intent) → GameState engine: the density decision is a UI skin, not a fork in the rules.

4 platforms · one engine

Watch the two-minute tour ↓
Evidence: All three layers, the AI, and a future server read the same deterministic (GameState, Intent) → GameState engine: the density decision is a UI skin, not a fork in the rules.
Go deeper

Analyst view: Gaddi draws on 6 stack entries and links to 4 outside sources, and shares 2 shared foundations with 3 other builds.

// guided tour

The product, narrated

A recorded walkthrough of the app with sample content. Tap the speaker for the voiceover, or read the captions. In-app figures describe the recorded demo, not live production activity.

Gaddi — narrated product tour

// shipping

Where you can actually get it

Every line below is checkable. Add the repository in an F-Droid client and the app installs, signed with the same key its listing pins.

  • F-DroidLive in a self-hosted repository. 16.5 MB, signed, with no Google Play Services and no Firebase in the build. open
  • GitHub ReleasesSigned APK per tag, plus desktop and web builds. open
  • Headless CLIThe engine runs with no UI at all. ./gradlew :cli:run simulates 500 games and reports per-seat win rates.

// pipeline

The build that put it there

Read live from GitHub Actions and the F-Droid index. Not a badge: the actual runs, what shipped, and the certificate you can check the download against.

reading the pipeline

4

platforms · one engine

10

AI bot personas

6

roles · 4 story arcs

7

toggle rule variants

// multiplatform

One codebase, every surface

Recorded app screens and, where available, the running build. Sample content inside a screen is separate from the source-linked project metrics.

Android screen (1 of 6)

Rendered at phone dimensions from the shared Compose UI.

// design notes

How it works

Deterministic engine

The whole game is a pure function: (GameState, Intent) → GameState, with the RNG seed living inside the state. The same module drives single-player, the bots and a future server. Any match can be replayed byte-for-byte from its seed and intent log.

Same game, three depths (launch overhaul)

The board reveals itself in three density layers so a first-timer isn't handed an expert's dashboard. FOCUS shows only whose turn it is, one plain-language line of what just happened, your hand and your legal moves; GUIDED adds gentle coaching; ANALYST is the full instrument panel (suspicion pips, odds, teleprinter log). Players graduate FOCUS → GUIDED → ANALYST by playing. Paired with a tap-to-continue beat gate so the round never resolves faster than you can read it, and a tutorial-first onboarding funnel that teaches one mechanic at a time.

AI Munshi narrator

A diegetic court-scribe turns raw engine events into one calm in-character line, grounded strictly on the redacted PlayerView so it narrates the beat without ever leaking a hidden card or inventing the board. It renders the deterministic templated line instantly and upgrades in place if an LLM is available (on-device Gemini Nano / Apple FoundationModels / BYOK cloud), never enters the intent log, and leaves byte-for-byte replay untouched.

ISMCTS expert AI + DARBAR social layer

Bots use Information Set Monte Carlo Tree Search (1.5k-16k iterations depending on difficulty tier) with an optional cloud-LLM upgrade (Anthropic / OpenAI / Gemini). Built on kmp-toolkit's own generic bots-policy shell (Policy/GameRules/Ismcts/SearchBudget, zero deps), not a bespoke search implementation. Ten personas each have a personality profile driving targeting and bluff frequency. The DARBAR layer lets bots form alliances, hold grudges and trade Hinglish table-talk across four story arcs. Social manipulation that never breaks engine determinism.

Secrecy boundary

A hidden-information game needs strict secrecy: redact(state, viewer) → PlayerView guarantees a client only ever sees what its player should. Two independent narrative RNG streams keep flavour separate from game logic.

“Sarkari Noir” visual system

A bespoke lamplit visual language: teak/brass/cream palette, Rozha One display type, Canvas-drawn intaglio role glyphs and stamped-instrument motifs. The launch overhaul pushed it to an AAA bar: every screen dissolved from bordered boxes into one continuous lit table (depth via shadow, never outline), a shared component vocabulary, and an AGSL/Skia runtime-shader material layer (film grain + warm bloom on the felt) with a graceful no-shader fallback. All behind a full Fastlane + CI pipeline with headless screenshot rendering.

Game modes

New Game (1v1-1v9, Easy→Grandmaster), a KISSA story campaign, GAUNTLET (Tarakki ki Seedhi, a 5-rung ladder ending in 6-player Grandmaster), TAMASHA (spectate ten AI personas scheme and betray), Team Khel (faction play with un-targetable allies), a Tutorial you can't leave until you catch a bluff, local pass-and-play with a handoff screen guard, and online + LAN multiplayer.

DARBAR: four live story arcs

Four narrative arcs run at once, fuelled or suppressed by your chat suggestions: GATHBANDHAN (a quiet coalition, watch who breaks first), AFWAAH (a rumour the table acts on even when false), STING (a leaked claim that forces a read), and BADLA (a vendetta that outlives the round). They run on a separate deterministic narrative RNG that never touches card state and resumes byte-for-byte.

Built for everyone

All six roles use the Okabe-Ito colourblind-safe palette plus a unique engraved bezel pattern (ring, hatch, dots, weave, double-rule, ticks) so identity reads without colour. Reduced-motion mode swaps every beat for a bespoke static end-frame (GHOTALA = held stamp, SUPARI = tipped chair). Accessibility never flattens the narrative.

Provider-agnostic AI

An AiProvider interface abstracts Anthropic, OpenAI, Gemini, on-device Gemini Nano (Android) and Apple FoundationModels (iOS 26); ISMCTS is the always-available offline fallback. Bring-your-own-key, stored in each platform's encrypted storage.

Server-authoritative online

Online and LAN play (private room codes, quick-match, Bonjour/mDNS discovery) run on a Ktor/Netty server that holds all state; clients receive only their redacted PlayerView, so another player's face-down roles can't appear on the wire by construction.

Seven toggle variants

Seven additive rule variants (Bail Pe Bahar, Bali Khel, Hawala, Adhyadesh, Khazana Raj, Mehengai, Tangi) combine freely and default off. The engine is byte-for-byte unchanged when they're disabled, expanding the surface without touching core logic.

// cast

The roster

Netaji Vachan

The Politician: Tax +3 (GHOTALA); blocks Foreign Aid

Bhai Teja

The Don: Assassinate −3 (SUPARI); unblockable except by the Vakil

Babu Filewala

The Bureaucrat: Steal 2 (VASOOLI); blocks Steal

Jugaadu Chhotu

The Fixer: Exchange cards (SETTING); blocks Steal

Vakil Loophole

The Lawyer: no action; blocks Assassinate only (power through procedure)

Patrakaar

The Journalist: Investigate a card (JAANCH); unblockable

// architecture

How it's built

Deterministic engine: one pure function

Secrecy boundary: redact per viewer

// under the hood

Tech stack

Language & UI

  • Kotlin 2.4.20-RC
  • Compose Multiplatform 1.12.0-rc01
  • Canvas + AGSL/Skia runtime shaders

Engine

  • Deterministic (GameState, Intent) → GameState
  • RNG-in-state
  • replay from (seed, intentLog)

AI

  • ISMCTS (offline)
  • Anthropic / OpenAI / Gemini
  • on-device Gemini Nano · Apple FoundationModels
  • BYOK (encrypted)

Online

  • Ktor / Netty server
  • server-authoritative
  • Bonjour/mDNS LAN

Platforms

  • Android
  • iOS (arm64)
  • Desktop (JVM)
  • Web (Wasm)

Build & quality

  • Koin
  • Fastlane
  • CI

// directions

Same screen, 3 treatments

Pick a treatment to see it whole. Where one ships a dark counterpart, drag the divider to compare the two faces of it — same layout, same content, only the light changes.

density — focus, light
focussingle mode — no dark counterpart

// gallery

Screens (32)

Swipe or use the arrows · tap a screen to enlarge

See how everything connects →