214 lines
14 KiB
Markdown
214 lines
14 KiB
Markdown
# Einreichung – Texte und Checkliste
|
||
|
||
Sammelstelle für alle Texte und Assets rund um Devpost und das Developer Portal. Texte auf Englisch (Jam-Vorgabe),
|
||
Erklärungen auf Deutsch. Stand: 2026-11-13.
|
||
|
||
## Developer Portal – In-app catalog
|
||
|
||
App: developers.reddit.com → `ninelands-game` → Developer Settings → In-app catalog.
|
||
|
||
| Feld | Text | Zeichen |
|
||
| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- | :------ |
|
||
| Tile tagline | Claim the nine lands. A new map every day. | 42 |
|
||
| Featuring description | A fresh 9×9 map every day. Place your castle, farmers, knights and bishops, claim land and gold, earn three stars and climb today's leaderboard. | 147 |
|
||
| Description (15–200) | Daily strategy puzzle: one 9×9 map for everyone. Build your realm piece by piece, claim lands and gold, chase three stars and keep your streak alive. | 151 |
|
||
| Game category | Game → Strategy | – |
|
||
| App icon | Icon aus dem Hauptspiel (Ninelands) | – |
|
||
|
||
### Assets
|
||
|
||
Erzeugen mit `npm run capture` → `dist/marketing/` (nicht im Repo). Vor der Einreichung neu aufnehmen (z. B. mit
|
||
Winter-Brett).
|
||
|
||
| Datei | Feld | Vorgabe Portal | Stand |
|
||
| :-------------- | :------------------- | :----------------------------------------------------- | :------------------------ |
|
||
| `featuring.mp4` | Featuring asset | MP4, 3:2, 1000–1500 px breit, 6–15 s, ≤ 30 fps, ≤ 3 MB | 1500×1000, 11,3 s, 1,7 MB |
|
||
| `fallback.gif` | Fallback (animiert) | 3:2, 1000–1500 px, 3–10 s Schleife, Ziel ≤ 2 MB | 1000×667, 6 s, 1,8 MB |
|
||
| `fallback.png` | Fallback (Standbild) | 1500×1000 empfohlen, ≤ 800 KB | 52 KB |
|
||
| `tile.png` | Tile image | 560×256 empfohlen, ≤ 800 KB | 58 KB |
|
||
|
||
Nur die Spielfläche, keine Menüs (Wunsch Besitzer). Karte vom 2026-10-10 – läuft nie als Tageskarte (kein Spoiler).
|
||
|
||
## Devpost – Project overview
|
||
|
||
### Elevator pitch (≤ 200 Zeichen)
|
||
|
||
Empfehlung (176 Zeichen):
|
||
|
||
> Ninelands is a daily strategy puzzle on Reddit: one 9×9 map for everyone, place castles, farmers and knights to
|
||
> claim lands and gold, earn three stars and climb the leaderboard.
|
||
|
||
Alternativen:
|
||
|
||
- (179) A daily port of the strategy game Ninelands: everyone gets the same 9×9 map each day. Build your realm, chase
|
||
three stars, keep your streak and compare strategies in the comments.
|
||
- (141) One map. Nine lands. Every day. Build your realm piece by piece, chase three stars and climb today's
|
||
leaderboard, right inside a Reddit post.
|
||
|
||
### About the project (Markdown, LaTeX erlaubt)
|
||
|
||
> Abschnitt „Inspiration“ bei Bedarf persönlicher machen (eigene Worte des Besitzers). Ob die KI-Unterstützung
|
||
> erwähnt wird, entscheidet der Besitzer (die Regeln erlauben technische Hilfe, solange Ideen und Rechte beim
|
||
> Teilnehmer liegen).
|
||
|
||
```markdown
|
||
## Inspiration
|
||
|
||
Ninelands started as a strategy board game on a 9×9 board split into nine lands: you place a castle, farmers,
|
||
knights and bishops, every piece claims land, and the goal is to rule the nine lands. It runs on the web, desktop,
|
||
Android and itch.io, and its most popular mode has always been the **map of the day**, where everyone plays the same
|
||
map and compares results.
|
||
|
||
Reddit felt like the natural home for that mode. A daily map is a shared puzzle, and a shared puzzle wants a place to
|
||
talk about it: _Where did you put your castle? How did you get 9/9 lands?_ So I built **Ninelands for Reddit**: a
|
||
focused, bite-sized daily edition that lives inside a post, with the comment thread as the place to compare realms.
|
||
|
||
## What it does
|
||
|
||
- **One 9×9 map per day, the same for everyone.** A new post appears automatically every day.
|
||
- **Easy to start, hard to master.** Tap to preview what a piece would claim and how much gold it brings; tap again to
|
||
place it. The line below the board explains why a cell fits or not. No wall of rules.
|
||
- **Three stars per map:** reach the gold target, rule the lands target, and both in one game. Targets come from
|
||
computer games on that very map, so every day is fair.
|
||
- **Leaderboard and streaks.** Only your first game counts. More stars first, then more gold, then the earlier
|
||
submission.
|
||
- **Your realm.** Unlock board themes with your streak and new banners and factions (orcs, pirates) with your stars.
|
||
- **Reddit-native.** Post your result to the comments with one tap, earn a 🔥 streak flair, and the best player of the
|
||
day wears 👑 _Ruler of the day_ the next day.
|
||
|
||
## How we built it
|
||
|
||
- **Devvit Web** with plain TypeScript, bundled by esbuild; no UI framework. An inline start screen in the feed, the
|
||
full board in expanded mode.
|
||
- **The original engine, untouched.** The Ninelands engine is pure TypeScript (seeded RNG, `legalMoves`,
|
||
`applyMove`, replay). A sync script copies it, plus the SVG board renderer, from a tagged release, so the Reddit
|
||
edition plays exactly like the original and fixes flow in one direction only.
|
||
- **A server that trusts nothing.** The client sends only its moves. The server replays them with the same engine and
|
||
computes gold, lands and stars itself, so results cannot be faked.
|
||
- **Redis leaderboards.** Each day is a sorted set. To rank by stars, then gold, then submission time in a single
|
||
score, I use
|
||
|
||
$$\text{score} = 100\,000 \cdot \text{stars} + \text{gold} + \frac{1}{\text{seq} + 1}$$
|
||
|
||
where $\text{seq}$ is the running number of the submission. The fraction lies in $(0, \tfrac12]$, so it only breaks
|
||
ties, and it makes every score unique, which turns a player's rank into a simple
|
||
$\text{rank} = \text{count} - \text{zRank}$.
|
||
- **First attempt only**, enforced atomically with `hSetNX`: two parallel submissions can never both count.
|
||
- **Daily posts** via the Devvit scheduler, **Devvit Journeys** for analytics (journey starts when the castle is
|
||
placed, a progress event per star, the end carries the gold as score).
|
||
- **Privacy by design:** all user data expires 30 days after a player's last game.
|
||
|
||
## Challenges we ran into
|
||
|
||
- **Making the daily map unspoilable.** The website has a map of the day too, including a replay of the best game.
|
||
The Reddit edition therefore uses its own seed, so its daily map can never be looked up elsewhere.
|
||
- **Knowing when to stop.** In the original, a game ends when no move is left. On a phone that can drag on, especially
|
||
under the law _One farm per land_, where only costly knights remain. I added an _End game_ button, and the game now
|
||
detects when no remaining move earns gold and suggests ending.
|
||
- **Fitting a strategy board into a post.** The board, the goals and nine piece costs have to be readable on a phone in
|
||
portrait mode. Container queries keep the board as large as possible without pushing the hint line away.
|
||
- **Platform details:** a template workflow my CI runner didn't understand, Redis commands that are not enabled for
|
||
every app, `localStorage` that is cleared on every app update (so all choices live in Redis), and an analytics router
|
||
that expects Express while my server has no framework, so I rebuilt its five endpoints by hand.
|
||
|
||
## What we learned
|
||
|
||
- A daily game lives from **one shared moment**: same map, same day, one first attempt. Every feature I kept serves
|
||
that moment; menus and settings did not make the cut.
|
||
- Contextual hints beat tutorials. Showing _why_ a move doesn't fit teaches the rules faster than any rules screen.
|
||
- Porting is easiest when the game logic is pure: the engine moved to a new platform without a single change.
|
||
|
||
## What's next
|
||
|
||
- Seasonal events beyond the winter festival, and more unlockable banners and boards.
|
||
- A weekly challenge with a twist (fog of war, bandit camps); both already exist in the original engine.
|
||
- An optional duel against the computer after the daily map.
|
||
```
|
||
|
||
### Built with (Tags, max. 25)
|
||
|
||
typescript, javascript, html5, css3, svg, node.js, devvit, devvit-web, reddit, reddit-api, redis, devvit-scheduler,
|
||
devvit-journeys, esbuild, biome, playwright, ffmpeg, pixel-art
|
||
|
||
### „Try it out“-Links
|
||
|
||
- App: `https://developers.reddit.com/apps/ninelands-game`
|
||
- Spielen: `https://www.reddit.com/r/Ninelands/` (angelegt 2026-11-13, Restricted; erst eintragen, wenn der erste Post
|
||
steht)
|
||
- Original-Spiel: `https://ninelands.stackteam.at`
|
||
- Code: Repo ist privat – nur eintragen, wenn es öffentlich wird (optional)
|
||
|
||
### Devpost – Project media und Video
|
||
|
||
Erzeugen mit `npm run capture:trailer` → `dist/marketing/` (nicht im Repo, ≈ 2 min). Das echte Spiel läuft in einer
|
||
Bühne (links Untertitel, rechts Handy), API als Attrappe, ein Bot spielt die Karte vom 2026-10-10 (3 Sterne, beendet
|
||
per „End game“). Leaderboard-Namen sind erfunden.
|
||
|
||
| Datei | Wofür | Vorgabe | Stand |
|
||
| :-------------------- | :------------------------------------------- | :--------------------------------------- | :---------------------------- |
|
||
| `trailer.mp4` | Video (Vimeo/YouTube, Devpost-Link) | < 1 min, öffentlich | 1920×1080, ≈ 47 s, ≈ 9 MB |
|
||
| `vimeo-cover.png` | Vorschaubild (Thumbnail) auf Vimeo | 16:9, 1920×1080 | Logo + Brett mit 3 Sternen |
|
||
| `gallery/00…06-*.png` | Devpost „Image gallery“ (Reihenfolge = Name) | JPG/PNG/GIF, ≤ 5 MB, 3:2 empfohlen, ≤ 15 | 7 Bilder, 1800×1200, ≤ 150 KB |
|
||
|
||
Galerie: 00 Titel, 01 Tagespost, 02 Land beanspruchen (Vorschau), 03 drei Sterne, 04 Ergebniskarte mit Bestenliste
|
||
und Freischaltung, 05 Realm, 06 Schluss. Ergänzen lassen sich echte Reddit-Screenshots (Kommentar im Thread, Flair).
|
||
|
||
**Bildunterschriften (Devpost-Caption je Bild, Englisch):**
|
||
|
||
| Bild | Caption |
|
||
| :------------------- | :--------------------------------------------------------------------------------------------------------- |
|
||
| `00-cover.png` | Ninelands: a daily strategy game on Reddit. One 9×9 map a day, the same for everyone. |
|
||
| `01-daily-post.png` | The daily post: today's map, its law, three goals, your streak and today's best. One tap to play. |
|
||
| `02-claim-land.png` | Place castle, knights, farmers and bishops to mine gold. A live preview shows what each move earns. |
|
||
| `03-three-stars.png` | One star each for the gold goal, for ruling all nine lands, and for doing both in one game. |
|
||
| `04-result.png` | The result card: stars, rank, streak and new unlocks. Post your result to the comments with one tap. |
|
||
| `05-realm.png` | Your realm: colours, factions, boards and banners, unlocked by stars and streaks. Same rules for everyone. |
|
||
| `06-outro.png` | A new map every day at 00:01 UTC on r/Ninelands. A port of Ninelands (ninelands.stackteam.at). |
|
||
|
||
**Eigene Reddit-Aufnahmen (optional):** hochkant (Handy oder Handy-Ansicht im Browser) als
|
||
`dist/trailer/input/feed.mp4` (Tagespost im Feed, ≤ 8 s) und `dist/trailer/input/comment.mp4` (der Ergebnis-Kommentar
|
||
im Thread, ≤ 8 s) ablegen (auch `.mov`/`.webm`), dann `npm run capture:trailer` neu laufen lassen – sie erscheinen im
|
||
Handy an passender Stelle. Keine aktuelle Tageskarte zeigen (Spoiler) und keine fremden Nutzernamen.
|
||
|
||
**Vimeo-Beschreibung** (Musik ist CC BY-SA 4.0, Nennung nötig):
|
||
|
||
```text
|
||
Ninelands: a daily strategy game on Reddit (Devvit Web). A new 9×9 map every day, one shared leaderboard per
|
||
subreddit, streaks, unlockable realms and your result in the comments. Port of Ninelands (ninelands.stackteam.at).
|
||
|
||
Music: "Dreamscape (part I)" by Vee Ray, CC BY-SA 4.0 (re-encoded).
|
||
Graphics: "Mini World Sprites" by Shade and octoshrimpy, CC0. Font: Pixelify Sans, SIL OFL 1.1.
|
||
```
|
||
|
||
### Noch zu schreiben
|
||
|
||
- **Portierung angeben** (Kategorie „Best Ported Daily Game“): Ninelands gehört StackTeam; erklären, was seit dem
|
||
11. Nov. neu entstanden ist (Pflicht für bestehende Projekte): neue Codebasis auf Devvit Web, neuer Tagesmodus mit
|
||
eigenem Seed, serverseitig nachgespielte Bestenliste in Redis, Streak, Realm-Freischaltungen, Flair, Ergebnis als
|
||
Kommentar, Devvit Journeys. Übernommen: Engine und Brett-Darstellung (Kopie mit festem Stand `v0.11.0`), Sprites,
|
||
Musik.
|
||
- **Testanleitung** für die Jury (kurz, Englisch).
|
||
|
||
## Checkliste Einreichung (Abgabe 9. Dez. 2026, 03:00 MEZ)
|
||
|
||
Pflicht laut offiziellen Regeln:
|
||
|
||
- [ ] Devpost: Text-Beschreibung (Funktionen)
|
||
- [ ] App-Link: `https://developers.reddit.com/apps/ninelands-game` (entsteht beim Upload; ohne Anmeldung 403 „You do not have permission…“, weil nicht veröffentlicht – so gewollt, die Regeln verlangen trotzdem nur diesen Link, Reddit-Admins sehen die Seite)
|
||
- [ ] `README.md` im Repo-Wurzelverzeichnis (Spiel und Anleitung) – vorhanden, vor Abgabe prüfen
|
||
- [ ] Demo: Link zum Subreddit (`r/Ninelands`, öffentlich, < 200 Mitglieder) **und** zu einem Post mit dem Spiel
|
||
- [ ] Angabe „Portierung“ + was im Jam-Zeitraum neu entstanden ist
|
||
|
||
Optional:
|
||
|
||
- [ ] Video < 1 min, öffentlich auf YouTube/Vimeo (die Jury darf allein danach urteilen)
|
||
- [ ] Öffentliches Repo (Repo ist derzeit privat)
|
||
- [ ] Developer-Platform-Feedback-Umfrage (eigener Preis)
|
||
|
||
Nicht tun:
|
||
|
||
- [ ] **Kein `devvit publish`** – hochladen und playtesten reicht, die App darf privat bleiben.
|
||
- [ ] Während der Bewertung (9.–16. Dez.) keine riskanten Uploads; Tagesposts müssen weiterlaufen.
|
||
|
||
Besitzer entscheidet bei der Anmeldung: Einzelperson oder Organisation (StackTeam) – betrifft Preisgeld und
|
||
Steuerformulare (W-8BEN).
|