Skip to content

About

Stateloop publishing fork of yubajefffries/keyboard-warrior. Original game and MIT license by its upstream authors.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

Keyboard Warrior

Type like your life depends on it. A first-person action typing game and touch-typing tutor for one household. Desktop browser, US QWERTY, physical keyboard required. Export your save once profiles exist (Phase 1a); browser storage is volatile.

Play it: keyboard-warrior-nine.vercel.app or yubajefffries.github.io/keyboard-warrior. Profiles live in your browser's localStorage; the Progress screen's export button is your save file.

Status: the full ten-stage curriculum and Survival mode are live. From finding the F and J bumps to typing transmissions under fire: capitals with opposite-hand Shift visually demonstrated, punctuation, the number row, sentences, and paragraph bosses. Remaining Phase 2 scope: Practice mode, 5m speed test, more weapons and enemies (Screamer next). See docs/PRD_v0_4.md for the full product spec.

Run it

npm install
npm run dev
  • / is the game: profile, 60-second placement, Stage 1-5 lessons in the gray-box encounter, speed test, progress screen. Type the prompt to fire. Wrong key is a dry-fire; backspace does nothing in combat. The next words sit to the right of the active one so you can read ahead: F2 cycles how many (0-4).

  • /harness/input-fidelity.html is the Input Fidelity Test harness (PRD 3.1). Run it in Chrome, Edge, and Firefox and export a log per browser into docs/input-fidelity-logs/.

  • /harness/legibility.html is the Text Legibility harness (PRD 3.2): worst-case fog, motion, and flash behind the real prompt renderer with a measured WCAG contrast ratio.

  • The robot typist plays the game for you at an exact speed so 100+ WPM can be tested without being able to type 100+ WPM: F9 runs a burst, F4 picks 80-200 WPM. Same test lives in the harness (panel 2) for a renderer-free run. What it proves and what it cannot: docs/BURST_TESTING.md.

npm test runs the unit tests for the input-independent core (typing engine, stats, content). npm run build type-checks and bundles all three pages.

What is built

Phase 1a requirement State
Profile create, 60s placement, routing done
Stages 1-2 lessons, pass criteria, diagnosis line done
On-screen keyboard, force on/off/auto done
Learn-mode health: only a reached player dies done
Progress screen: WPM/accuracy history, per-key heatmap, stage gates done
Export / import JSON with validation and migration done
Speed Test 15s / 30s / 60s / 2m done
Environment pass: the abandoned laboratory, inside the performance budget done
Mastery engine: windows, decay, staleness, low-exposure done
Phase 1b settings: finger guide, text size, high contrast, intensity, motion reduction, volume, pause-on-blur done
Warm-up offer (day away; accuracy counts, latency excluded) done
Break suggestion on accuracy collapse done
Scoring and combo: 10/25/50/100 ladder, accuracy over speed (PRD 17) done
Crawler + Brute enemies, per-enemy words, boundary-only target switching (PRD 6, 14) done
Revolver from Stage 3: one word, one shot (PRD 15) done
Stage gate: taught frequent keys mastered + final lesson passed done
Keyboard auto-hide, and the finger hint that makes it safe done
Weak-key injection into lesson content (PRD 13) done
Adaptive difficulty: enemy timing from demonstrated pace, timer-was-wrong easing (PRD 13) done
Stages 3-5: upper row, lower row, common words (14 new lessons) done
Stages 6-10: capitals (opposite-hand Shift shown on the keyboard), punctuation, numbers, sentences, paragraph transmissions done
Stage 6+ middle band: tighter pacing for Intermediate+ (PRD 16) done
Survival: waves, complexity-not-speed scaling, health, records (PRD 16/18) done

Architecture rules

  • src/input/pipeline.ts never imports the renderer. Every keystroke the game consumes flows through it as a stamped KeyRecord (seq, key, code, repeat, modifiers, timeStamp, frameTime).
  • The active prompt is screen-space DOM. Recoil, camera motion, and enemy lunges cannot move it.
  • Errors log once against the expected key; the pressed key feeds the confusion matrix. Corrections never erase errors.
  • Repeats never advance combat text. Modifier chords are ignored. Caps Lock and stuck Shift are surfaced, never silently rewritten.
  • Blur pauses combat and resume is explicit; blur during a timed drill discards the attempt instead, because a paused-and-resumed clock produces a WPM number that means nothing.
  • Upcoming prompts come from a TokenQueue, so what is drawn as "coming up" is exactly what arrives. The display can never promise a word the source then changes.
  • Browser storage is volatile and treated that way: every write is best-effort, a blocked store is surfaced rather than swallowed, and the export file is the durable copy.
  • Import validates every profile before accepting any of them. A newer format is refused with a message; a malformed file changes nothing.
  • Per-key history is capped by construction (rolling windows, not raw samples), so a long-lived family profile cannot grow without bound.
  • Every mastery rule reads a window, never a lifetime total. A player who was 60% on K last month and is 98% today has mastered K.
  • Nothing about mastery is announced. A decayed key quietly turns up more often; the game never says "you forgot R".
  • Saves loaded from browser storage go through the same migration and validation as an imported file. Code that reads an old blob without upgrading it gets a profile missing every field the current engine expects.
  • Enemy pacing never demands more than the player has demonstrated: the spawn interval has no upper clamp, because capping it for a slow typist would quietly reintroduce the demand the 20-40% buffer exists to remove. A lesson consistently failed at >=90% accuracy widens the buffer: the timer is wrong, not the player.

Phase 0 exit gates: CLEARED

Verified by the product owner on real hardware, 2026-08-22: input fidelity, legibility, feel, and frame rate all pass on an actual machine with an actual keyboard. The robot burst covers the app-layer half of gate 1 in CI forever; harness logs can still be exported to docs/input-fidelity-logs/ per browser whenever a formal record is wanted.

License

Code is MIT. See LICENSES.md for the asset policy.

About

Stateloop publishing fork of yubajefffries/keyboard-warrior. Original game and MIT license by its upstream authors.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages