Back to Supersonic RC Revive
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.

src/game/konami.ts
// 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;
  }
}