SOURCE / PINNED RELEASE
Made of little things.
Supersonic RC Revive
- Release
- 1ba42f1ca1d6…
- Author-recorded commit
- baecad10b1cd…
- License
- LICENSE
- Author’s source reference
- nostr://npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr/wss%3A%2F%2Fgit.napplet.soy%2F/n-143146b0d6f
Archive hash verified: 90d22b206672eba4…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
// The secret code: the classic ↑ ↑ ↓ ↓ ← → ← → B A, matched from raw keyboard
// codes and controller menu intents alike — either can enter it, and a mix of
// both works. src/main.ts decides what completing it does; keys and buttons
// outside the code's alphabet are simply not fed to the matcher.
import type { MenuIntent } from './input.js';
/** The inputs the code is made of ("b" and "a" are the controller's B and A). */
export type CodeToken = 'up' | 'down' | 'left' | 'right' | 'b' | 'a';
const CODE: readonly CodeToken[] = ['up', 'up', 'down', 'down', 'left', 'right', 'left', 'right', 'b', 'a'];
/** KMP failure table: after a mismatch at progress `p`, fall back to `FAILURE[p]`. */
const FAILURE: readonly number[] = [0, ...CODE.map((_, i) => {
for (let k = i; k > 0; k--) {
if (CODE.slice(0, k).every((t, j) => t === CODE[i - k + 1 + j])) return k;
}
return 0;
})];
/** A KeyboardEvent.code as a code token; undefined for a key outside the code's alphabet. */
export function keyToToken(code: string): CodeToken | undefined {
switch (code) {
case 'ArrowUp':
return 'up';
case 'ArrowDown':
return 'down';
case 'ArrowLeft':
return 'left';
case 'ArrowRight':
return 'right';
case 'KeyB':
return 'b';
case 'KeyA':
return 'a';
default:
return undefined;
}
}
/** A controller MenuIntent as a code token (B is "back", A is "select"); undefined for "start". */
export function intentToToken(intent: MenuIntent): CodeToken | undefined {
if (intent === 'back') return 'b';
if (intent === 'select') return 'a';
if (intent === 'start') return undefined;
return intent;
}
/** Matches the code against a stream of tokens. */
export class KonamiCode {
private progress = 0;
/** Feed one token; true when it completed the code (the matcher then restarts). */
feed(token: CodeToken): boolean {
// The KMP automaton: a wrong key falls back to the longest prefix that is
// still a suffix of what was entered (↑ ↑ ↑ stays at "↑ ↑").
while (this.progress > 0 && token !== CODE[this.progress]) this.progress = FAILURE[this.progress]!;
if (token === CODE[this.progress]) this.progress++;
if (this.progress === CODE.length) {
this.progress = 0;
return true;
}
return false;
}
/** Forget any partial entry (a race started, the pack panel opened). */
reset(): void {
this.progress = 0;
}
}
