Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Hintful Puzzles: logic puzzles with hints that explain why. Free, offline, and ad-free.
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
A progressive web app (PWA) of Simon Tatham's Portable Puzzle
Collection, plus additional puzzles from Lennard Sprong's
puzzles-unreleased, maintained by Yoni Lavi: all 57
games implemented natively in TypeScript, with hints that explain the next
move rather than just showing it.檢視完整 README ↗A progressive web app (PWA) of Simon Tatham's Portable Puzzle Collection, plus additional puzzles from Lennard Sprong's puzzles-unreleased, maintained by Yoni Lavi: every game implemented natively in TypeScript, with hints that explain the next move rather than just showing it.
It is a fork of Mike Edmunds' puzzles-web, which adapted the upstream C collection to the browser through WebAssembly. This project replaced that engine with its own, rewriting every game in TypeScript, top-down, so that the codebase can grow beyond upstream: fast iteration on the UI and games, cheap addition of new games, and cross-game features upstream doesn't have (quick-save, mistake-checking, explained hints, per-game play aids). Targets Baseline 2023; works with touch, mouse, and keyboard across screen sizes.
Play it at https://hintful.click. To run it locally, npm install and
then npm run dev.
The app works, and the migration is done. Every puzzle is playable, and every one is a native TypeScript implementation running on this project's own engine. The C/WASM engine it grew up alongside — the sources, the Embind adapter, the Emscripten build, the worker's wasm path — was retired on 2026-08-01 once the last game shipped. There is no C left to build and no wasm in the app.
The migration is deliberate divergence, not a faithful port. We are
not tracking upstream and not preserving byte-identical behavior or old
save-game / shared-ID compatibility from before the pivot. Going forward, a
shared game ID names the board itself (params:desc), never a seed, so it
keeps opening that board.
The code is still rough in places. What the project is for is
docs/doctrine.md;
the authoritative migration rules are the ts-migration capability spec
at openspec/specs/ts-migration/spec.md.
For a bug, or a question about a puzzle, open an issue. Helpful to include:
Simon Tatham's How to Report Bugs Effectively is worth a read.
Everything below is for building or contributing.
src/ is the whole thing: the TypeScript web app, the engine
(src/engine/ — midend, Game interface, drawing and color
contracts) and the games (src/games/<id>/).
It went top-down. A TS midend and a clean Game interface first, then
games in order of user-facing value (simplest first to establish the pattern,
then the ones we wanted to enhance, then outward), with leaf libraries pulled
in lazily as idiomatic TS when a game needed them. Each game ran on C until
its port was accepted at parity, then flipped over and its C was deleted.
puzzles/ was a frozen git subtree of the upstream C collection, read as
a reference while porting. It is gone. What outlived it moved to where it
belongs: upstream's per-puzzle help text into this project's own pages under
help/games/, the MIT
notices to licenses/, and the two unbuilt experimental sources
kept for future greenfield games to the openspec changes that read them. The
C itself is in git history.
This replaced an earlier bottom-up, byte-identical-fidelity plan
(preserved on branch legacy/seam-by-seam-fidelity + tag
pre-ts-pivot).
The web app is a Vite multipage app. Entry pages render at build time
(or in the dev server) via the custom
vite-plugins/extra-pages.ts plugin, from
templates under templates/. src/ is organized by role:
src/screens/ — top-level screen components (one per page).src/dialogs/ — modal / popover overlays.src/components/ — reusable leaf Lit components.src/puzzle/ — the puzzle runtime + the Comlink worker boundary.src/engine/ — the Game interface, the Midend, the game registry,
the drawing/color contracts and the in-process test harness.
src/engine/random/ is the bit-identical RNG port, which the fixtures
and seeded tests rest on.src/games/<id>/ — each game.src/store/ — Dexie (IndexedDB) schema for settings and saved games.main.ts, the old-browser preflight.ts gate, the
sw.ts service worker, and cross-cutting modules at src/ root.src/assets/ holds only committed files — nothing under src/ is
generated. src/assets/icons/ is a committed thumbnail snapshot (see
openspec/specs/puzzle-icons/spec.md).src/puzzle/catalog-data.ts is the committed game catalog.The UI uses Lit web components and Web Awesome design
tokens; reactive state via @lit-labs/signals; offline via a Workbox
service worker; telemetry via Sentry. The in-app help all lives under
help/, in one format: site-level pages at the top level and one page
per game in help/games/, all of them this project's own markdown.
src/help-coverage.test.ts holds that directory and the catalog to each other
in both directions.
Vite bundles the TypeScript PWA. That is the whole build — the games are TypeScript, so there is no compilation step ahead of it, and nothing is generated.
npm install
That is the entire setup, on any platform. The repository has no native toolchain dependency of any kind.
npm run dev # Vite dev server (hot-reloads)
npm run build # production build
npm run preview # preview the production build
npm run check # Biome format + lint
npm run test:run # Vitest
A fresh clone runs npm run dev and npm run build with nothing built first
and nothing installed but Node: the game catalog is committed source
(src/puzzle/catalog-data.ts), the icons are a committed snapshot, and the help
pages are committed markdown.
The guides under docs/ say how work is done here, and each is
written to be looked up by section rather than read through: a guide about
writing a game opens with what every game does and a table of its sections.
This table is the one index of them.
| Working on | Guide |
|---|---|
| A new game, or any game: the route through the guides by kind of game, the lifecycle, the definition of done | docs/new-game.md |
| Params, state, moves, capability hooks, affordances | docs/mechanics.md |
| Pointer, keyboard, touch, the keypad | docs/input.md |
| Redraw, tile cache, palette, animation | docs/rendering.md |
Solver, generator, difficulty tiers, findMistakes | docs/solver-and-generator.md |
| A hint: the quality bar, its words, its plan, refusals, the guards | docs/hints.md |
| A hint's marks on the board, how a step is grouped, the facts it may rest on | docs/hints-marks.md |
| The hint of a game with candidate notes | docs/hints-candidates.md |
| The hint of a game solved by search or a heuristic | docs/hints-search.md |
| A test, a render scenario, a cross-game guard |
Each guide names at its top the spec it rests on, and a game's own rules are
openspec/specs/<game>/spec.md.
Work is tracked with openspec (openspec/): a change is proposed,
specced, implemented, then archived. The rules every
session works under are AGENTS.md, and the guides under
docs/ say how work is done.
The rules of record are the capability specs under openspec/specs/; the record
of what was built is openspec/changes/archive/ and the git log.
The web app code (including local modifications/additions to the puzzles code) is MIT — see LICENSE.md. The upstream notices in licenses/ cover the ported games and the upstream help text adopted into help/games/, also MIT. The built app bundles several open source packages; required notices are in the app's About dialog (open an issue if any seem missing).
docs/testing.md |
| A shared engine helper | docs/engine-catalog.md |
| Judging tests, or quoting a measurement | docs/test-strength.md |
| A check, a census, a bulk edit, a number in a proposal | docs/method.md |
| An openspec change, acceptance, pushing, a deploy | docs/work-management.md |
| A help page | docs/help-pages.md |
| A framework or cross-game design decision | docs/doctrine.md |