| --- |
| title: HuggingWizards |
| emoji: π§ |
| colorFrom: purple |
| colorTo: indigo |
| sdk: gradio |
| sdk_version: 5.9.1 |
| app_file: app.py |
| pinned: false |
| short_description: Nemotron-4B is the Game Master |
| tags: |
| - track:wood |
| - sponsor:nvidia |
| - achievement:offgrid |
| - achievement:sharing |
| --- |
| Social Media Post and Demo Video: https://www.linkedin.com/posts/dean-byrne-02a28b191_huggingwizards-for-hugging-face-hackathon-activity-7472041413648502785-K2rP?utm_source=share&utm_medium=member_desktop&rcm=ACoAAC0RumIBxlIKTkKv5tF-hb2OU7TdZ19kxcQ |
| # π§ HuggingWizards |
|
|
| A small 2D pixel-wizard **co-op arena** that runs as a Gradio Space on **ZeroGPU**. |
| Up to **8 players** join one shared arena, fight a central **boss** and the |
| **minions** it spawns, and upgrade their magic between rounds. Everyone else can |
| **spectate** live. Controls: **WASD** to move, **Space** to attack. |
|
|
| The hackathon twist: **NVIDIA Nemotron-Mini-4B-Instruct** is the **Game Master**. |
| At the end of every round it decides: |
|
|
| - **Rewards** β how much gold each wizard earns (based on damage / survival). |
| - **Blessings** β individual boons for wizards who earned them: any timed aura, |
| a `full_heal`, or even an `extra_life` for a struggling player. |
| - **Boss attack pattern** β `balanced`, `sniper` (fast aimed bolts), `artillery` |
| (slow heavy orbs + dense shockwaves), `swarm` (minion floods), or `berserker` |
| (relentless charges). The active pattern shows next to the boss's name. |
| - **Boss attack speed (with decaying mercy)** β the GM reads every wizard's |
| HP% and lives and tunes `boss_attack_speed` (0.5β2.0): slower for a wounded |
| party, faster for a healthy one. Guardrail: the allowed floor rises each |
| wave (no mercy left by ~wave 13), out-of-range or malformed values are |
| clamped, and every trace records `requested` vs `applied` plus the floor. |
| - **Boss & minion reset** β next-round boss HP, minion count/HP, spawn rate, |
| boss damage, aggression, and the enemy archetype mix. |
| - **Card pool** β which level-up cards may be offered next wave. |
|
|
| Every round produces a structured **agent trace** (prompt β raw model output β |
| parsed decision β applied effect), saved under `traces/` and shown live in the |
| Gradio dashboard. |
|
|
| ## Architecture |
|
|
| - **Client** (`static/`): HTML5 canvas game loop in the browser (rendering + input). |
| - **Server** (`app.py`, `game/`): FastAPI WebSocket + a ~20 Hz authoritative game |
| tick on CPU. Gradio is mounted for the trace/leaderboard dashboard. |
| - **Game Master** (`game/gamemaster.py`): `@spaces.GPU` burst inference at round |
| boundaries only β the pattern ZeroGPU is built for. Falls back to deterministic |
| logic if the model/GPU is unavailable (so it runs locally too). |
|
|
| ## Run locally |
|
|
| ```bash |
| pip install -r requirements.txt |
| python app.py |
| # open http://localhost:7860 |
| ``` |
|
|
| The Game Master uses Nemotron only when a GPU + the `spaces`/`transformers` stack |
| is present; otherwise it transparently uses the deterministic fallback so local |
| dev and CI still work. |
|
|
| ## Game Master model |
|
|
| On a Space the model is loaded **at startup** (the ZeroGPU pattern: weights are |
| downloaded and staged before any `@spaces.GPU` call, so the 60 s GPU window is |
| spent purely on inference). Locally it is lazy-loaded on the first round. |
|
|
| Environment variables: |
|
|
| | Variable | Values | Effect | |
| |---|---|---| |
| | `HUGGINGWIZARDS_NO_LLM` | `1` | Skip the model entirely; deterministic Game Master (CI / quick dev). | |
| | `HUGGINGWIZARDS_QUANT` | `auto` (default), `none`, `4bit`, `8bit` | Quantization via bitsandbytes. `auto` = bf16 on Spaces/big GPUs, NF4 4-bit on local GPUs with <12 GB VRAM. | |
|
|
| Quantization notes: 4-bit NF4 shrinks the 4B model from ~8.5 GB to ~3 GB of |
| VRAM and speeds up cold loads β ideal for small local GPUs. On ZeroGPU's H200 |
| plain bf16 is both comfortable and faster per token, so `auto` keeps bf16 there. |
|
|
| ## Assets |
|
|
| Pixel art / audio from free packs (Tiny RPG Character Pack, Tiny Swords, |
| Free Pixel Effects, Retro Impact Effect Pack, Pixel UI pack 3, Pixel RPG Music |
| Pack). See each pack's license. |
|
|
| - **Maps**: each boss faction has its own territory β the Tiny Swords grass |
| tileset plus a per-theme ground tint, landmark buildings |
| (`static/assets/buildings/`: orc camp huts, the Iron Legion's blue castle, |
| the Lancer Host's red keep, the Archer Coven's monastery & ranges) and a |
| seeded scenery mix (bushland / rockfields / forest). Scenery is purely |
| cosmetic β the server simulation is unchanged. |
| - **Effects**: spell-cast muzzle flashes, impact bursts (on boss/minion/player |
| hits) and death poofs are drawn client-side from the Free Pixel Effects |
| spritesheets, triggered by snapshot flags (`hurt`, attack, minion id removal). |
| Skill activations and GM blessings are server-driven events rendered with |
| more of the pack: freezing novas, felspell blasts, protection circles, |
| vortex summons, sunburn blessings, magic-bubble heals. |
| - **Characters**: pick a champion (Warrior / Archer / Lancer / Pawn) on the |
| name screen β Tiny Swords blue units (`static/assets/chars/`), all size-normalized |
| and growing with level. |
| - **Special bosses**: **Aegis** (red wave, holy-spell attacks) on waves 3/9/15β¦ and |
| **Toaster Bot** (green wave, glitch-portal attacks) on waves 5/11/17β¦ Beat one and |
| every survivor gains its signature attack as a permanent power. |
| - **Timed auras**: rare floor-only power-ups (30β60 s) visualized with the Retro |
| Impact Effect Pack (`static/assets/retro/`) wreathing the wizard. |
| - **Music**: a looping track from the Pixel RPG Music Pack starts on the first |
| join/spectate click (browser autoplay policy); a π button toggles it. |
|
|