qFelix commited on
Commit
66742cf
·
1 Parent(s): dd44446

Add GIF support in .gitattributes and include new media assets for gameplay, cover, and comic reveal

Browse files
.gitattributes CHANGED
@@ -4,3 +4,4 @@
4
  *.jpeg filter=lfs diff=lfs merge=lfs -text
5
  *.ico filter=lfs diff=lfs merge=lfs -text
6
  *.mp3 filter=lfs diff=lfs merge=lfs -text
 
 
4
  *.jpeg filter=lfs diff=lfs merge=lfs -text
5
  *.ico filter=lfs diff=lfs merge=lfs -text
6
  *.mp3 filter=lfs diff=lfs merge=lfs -text
7
+ *.gif filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -10,109 +10,88 @@ license: mit
10
  short_description: Argue your way to $1M before the quarter ends
11
  ---
12
 
13
- # Brad Did Something
14
 
15
- 2D top-down office comedy game. You are the Head of Sales and Partnerships at
16
- Veloura Technologies. Five unhinged underlings, 15 events, one quarter, one
17
- million dollars. The Office meets Silicon Valley, in cozy daylight pixel art.
18
 
19
- All NPC dialogue and outcomes are generated by llama.cpp (Qwen3.5-9B)
20
- running on Modal, with JSON-schema-enforced output validated in Python before
21
- anything reaches the screen.
22
 
23
- ## Run locally
 
 
 
 
 
24
 
25
- ```
26
- pip install -r requirements.txt
27
- python app.py # → http://localhost:7860
28
- ```
29
 
30
- With no `MODAL_URL` set, the game runs in **mock mode** — fully playable, with
31
- a template-based offline generator standing in for the model.
32
 
33
- ## Wire up live inference (Modal)
34
 
35
- Already deployed to the `qfelix0112` workspaceendpoint:
36
- `https://qfelix0112--brad-did-something-llama-generate.modal.run`
37
- (L4 GPU, warm calls 2-4s, stays warm 5 min between calls). The auth token
38
- lives in `.bds_modal_token` (gitignored never commit/upload it).
 
 
 
 
 
 
 
 
 
 
 
39
 
40
- Play against it: `.\run_modal.ps1`
 
41
 
42
- To redeploy after changing `modal_app/inference.py`:
43
-
44
- ```
45
- set PYTHONUTF8=1 # Windows: avoids a CLI encoding crash
46
- modal deploy modal_app/inference.py # prints the web endpoint URL
47
- python tests/smoke_modal.py # one real call per call type
48
- ```
49
 
50
- `MODAL_URL` is the full generate-endpoint URL (Modal gives each function its
51
- own URL). For the HF Space, set `MODAL_URL` + `MODAL_TOKEN` as Space secrets.
52
 
53
- ## Comic panels (FLUX image generation)
 
 
 
54
 
55
- When a crisis fires, the text model also writes a wordless `image_prompt` (a
56
- single-panel scene) plus a short `comic_caption`. A second Modal GPU app renders
57
- the panel with **FLUX.2 [klein] 4B**; the UI shows it centered over the office
58
- with the caption drawn as crisp text *above* the picture (the image stays
59
- wordless because FLUX garbles in-image text). The art style is prepended
60
- server-side in `/api/comic`, so the model spends its whole budget describing the
61
- scene. Setup renders during the walk to the NPC, payoff after the outcome. It's
62
- purely decorative: if FLUX is unset, slow, or fails, the game shows **no
63
- overlay** and the dialogue opens as usual — the outcome is never blocked.
64
 
65
- ```
66
- set PYTHONUTF8=1
67
- modal secret create huggingface HF_TOKEN=<hf token> # FLUX weights are gated
68
- modal deploy modal_app/image.py # prints the endpoint URL
69
- python tests/probe_comic.py # latency + saves a sample
70
  ```
71
 
72
- Then set `FLUX_URL` (the printed `generate_image` URL) and `FLUX_TOKEN` (the
73
- same `bds-auth` `BDS_TOKEN`) locally or as Space secrets. The model is
74
- env-swappable at deploy: `FLUX_MODEL_ID=black-forest-labs/FLUX.1-schnell`
75
- (Apache-2.0) is a drop-in if FLUX.2's deps/VRAM are troublesome.
76
- **License:** the FLUX.2 line is typically non-commercial — fine for a hackathon
77
- demo; review before any commercial use.
78
 
79
- ## Deploy on Hugging Face (Docker)
80
 
81
- The app is built on **`gr.Server`** (Gradio's FastAPI-based server): it serves a
82
- fully custom canvas/DOM frontend from `static/` with zero default Gradio
83
- widgets, while staying a first-class Gradio app. The Space uses `sdk: docker`
84
- (see frontmatter) because HF's `sdk: gradio` runner only launches a module-level
85
- `demo`; the `Dockerfile` runs `uvicorn app:app` on port 7860 (the `gr.Server`
86
- instance is the ASGI app). Set `MODAL_URL`/`MODAL_TOKEN` and (optional)
87
- `FLUX_URL`/`FLUX_TOKEN` as Space secrets. Dry-run locally:
88
 
89
- ```
90
- docker build -t bds .
91
- docker run -p 7860:7860 bds # http://localhost:7860
92
- ```
 
 
93
 
94
  ## Tests
95
 
96
- ```
97
- pytest tests/ # unit tests (validator, economy, events, comic, idle)
98
- python tests/smoke_http.py # full-quarter API playthrough
99
- python tests/smoke_browser.py # headless-browser UI smoke (playwright)
100
- python tests/probe_mobile.py # touch-controls smoke on an emulated phone
101
- python tests/probe_comic.py # live FLUX render + saves sample panels
102
  ```
103
 
104
- ## Controls
105
-
106
- WASD / arrows move · SPACE talk / pick up / answer / advance comic · G gift ·
107
- 1/2 choose options · ENTER send typed response · ESC close · M mute
108
-
109
- **Touch / mobile:** on phones and tablets an on-screen joystick (move) plus
110
- ACT (= SPACE) and GIFT buttons appear automatically; tapping the floor also
111
- walks the player. Portrait layout stacks the HUD and hides the paper-trail
112
- panel. Comics and dialogue are tap-dismissable.
113
-
114
- ## Docs
115
 
116
- Design docs (GAME_DESIGN, MECHANICS, EVENTS, ) and engineering docs
117
- (ARCHITECTURE, SCHEMAS, AI_PROMPTS, IMPLEMENTATION_PLAN) live in the repo
118
- root. Start with AGENTS.md.
 
10
  short_description: Argue your way to $1M before the quarter ends
11
  ---
12
 
13
+ # 🚀 Brad Did Something
14
 
15
+ ![Brad Did Something](docs/media/cover.gif)
 
 
16
 
17
+ > *Corporate bureaucracy is already a chaotic simulation I just replaced middle management with an LLM to see if the company could survive the quarter.*
 
 
18
 
19
+ A 2D top-down **office comedy game** where every line your coworkers say, every
20
+ unhinged decision, and every dollar of revenue is **generated live by an LLM**.
21
+ You're the new Head of Sales at Veloura Technologies; your five underlings are
22
+ enthusiastic, well-meaning, and completely off the rails. Survive **15 workplace
23
+ crises** and one fiscal quarter, and hit **$1,000,000** — by literally *arguing
24
+ your way there*.
25
 
26
+ **🎮 [Play it now](https://huggingface.co/spaces/build-small-hackathon/brad-did-something) · ▶️ [Watch the trailer](https://youtu.be/BJSE5WDZvPs)**
 
 
 
27
 
28
+ ![Gameplay](docs/media/gameplay.gif)
 
29
 
30
+ ## Not just a chatbot in a trenchcoat
31
 
32
+ - **🧠 The AI is load-bearing.** NPC dialogue isn't decoration through strict
33
+ JSON-schema validation the model's output *directly drives the game economy*.
34
+ Talk Brad into rescuing a deal and revenue jumps; offend him and the pipeline
35
+ collapses. The server hides the morale & relationship scores, so the model
36
+ moves them without ever seeing (or gaming) them.
37
+ - **🎨 Comics on the fly.** Each crisis, the text model writes a scene and a
38
+ second GPU renders a wordless **FLUX.2 [klein] 4B** comic panel that drops over
39
+ the office — the caption is drawn crisp by the UI (FLUX can't spell, so words
40
+ stay out of the image).
41
+ - **🕹️ A genuinely custom frontend.** A hand-built HTML5-canvas + DOM pixel-art
42
+ game served through **`gr.Server`** — zero default Gradio widgets, desktop **and**
43
+ touch.
44
+ - **⚙️ Small models, tight plumbing.** Qwen3.5-9B (llama.cpp) for text, FLUX.2-
45
+ klein-4B for art, both on Modal GPUs, JSON-grammar-locked with a one-shot retry
46
+ and a fast fallback so a slow call never kills the joke's timing.
47
 
48
+ 📖 **The full build story** — the sub-4B model bake-off, fighting the model's
49
+ "helpful AI" reflex, and the comic pipeline — is in the write-up: _[blog link]_.
50
 
51
+ ---
 
 
 
 
 
 
52
 
53
+ ## Run it yourself
 
54
 
55
+ ```bash
56
+ pip install -r requirements.txt
57
+ python app.py # → http://localhost:7860 (mock mode: fully playable, no keys)
58
+ ```
59
 
60
+ With no `MODAL_URL` set it uses a template-based offline generator. For the real
61
+ AI, deploy the two Modal GPU apps and point the game at them:
 
 
 
 
 
 
 
62
 
63
+ ```bash
64
+ modal deploy modal_app/inference.py # Qwen3.5-9B text → MODAL_URL / MODAL_TOKEN
65
+ modal deploy modal_app/image.py # FLUX.2-klein art FLUX_URL / FLUX_TOKEN
 
 
66
  ```
67
 
68
+ On the HF Space these four go in **Settings → Secrets**; locally, `.\run_modal.ps1`
69
+ wires them up for you.
 
 
 
 
70
 
71
+ ## Deploy (HF Docker Space)
72
 
73
+ Built on **`gr.Server`** so the custom FastAPI frontend *is* the app — HF's
74
+ `sdk: gradio` runner only launches a bare `demo`, so the Space runs `sdk: docker`
75
+ with a `Dockerfile` that does `uvicorn app:app` on port 7860. Dry-run locally:
76
+ `docker build -t bds . && docker run -p 7860:7860 bds`.
 
 
 
77
 
78
+ ## Controls
79
+
80
+ **WASD/arrows** move · **SPACE** talk / answer / advance comic · **G** gift ·
81
+ **1/2** choose · **ENTER** send a typed reply · **ESC** close · **M** mute.
82
+ **📱 Mobile:** an on-screen joystick + ACT/GIFT buttons appear automatically, and
83
+ tapping the floor walks you there.
84
 
85
  ## Tests
86
 
87
+ ```bash
88
+ pytest tests/ # unit: validator, economy, events, comic, idle
89
+ python tests/smoke_http.py # full-quarter API playthrough (mock)
90
+ python tests/smoke_browser.py # headless-browser UI smoke
 
 
91
  ```
92
 
93
+ ---
 
 
 
 
 
 
 
 
 
 
94
 
95
+ *Code MIT. Text model: Qwen3.5-9B (Apache-2.0). Image model: FLUX.2 [klein] 4B
96
+ (non-commercial fine for this demo). Built for the Hugging Face **Build Small
97
+ Hackathon**, "An Adventure in Thousand Token Wood."*
docs/media/comic-reveal.gif ADDED

Git LFS Details

  • SHA256: 1c9078bcf68469fc267da99c5bddf42d6ea27beec6ec4c1d755c92d19323e9a2
  • Pointer size: 132 Bytes
  • Size of remote file: 3.39 MB
docs/media/cover.gif ADDED

Git LFS Details

  • SHA256: e9b3e890b64662dde0fc61123cbc598fbebc5175cec31ad10ecd453d2b95dbab
  • Pointer size: 132 Bytes
  • Size of remote file: 7.12 MB
docs/media/gameplay.gif ADDED

Git LFS Details

  • SHA256: f97cf5e9630e70adc0d401c16f0346905625cd825bc8eaca16d457def2c3aa25
  • Pointer size: 132 Bytes
  • Size of remote file: 9.84 MB
docs/media/modal-latency.png ADDED

Git LFS Details

  • SHA256: e223d1bc13965eba1dda33ceefd9d358967c4bfe4cff03a91a70f97883d71e5d
  • Pointer size: 131 Bytes
  • Size of remote file: 122 kB