The Konami Code Challenge

If you’ve ever played some old-school/classic video games published by the game company Konami, you may have entered (or heard of) the following sequence of button presses:


This is a companion discussion topic for the original entry at https://www.kirupa.com/html5/konami_code.htm

Below is my attempt at solving this, which I explain the ins and outs of in the article:

let keys = {
  37: "left",
  38: "up",
  39: "right",
  40: "down",
  65: "a",
  66: "b"
};

let konamiCode = ["up", "up", "down", "down", "left", "right", "left", "right", "b", "a"];
let keyCount = 0;

let timerID;

document.addEventListener("keydown", checkCode, false);

function checkCode(e) {
  let keyPressed = keys[e.keyCode];

  if (keyPressed === konamiCode[keyCount]) {
    keyCount++;

    // clear timer
    window.clearTimeout(timerID);

    // start timer with a 1 second delay before resetting state
    timerID = window.setTimeout(resetKeyState, 1000);

    // check if we are still on the right path
    if (keyCount === konamiCode.length) {
      cheatCodeActivated();
      resetKeyState();
    }
  } else {
    resetKeyState();
  }
}

function cheatCodeActivated() {
  alert("Cheat code activated!");
}

function resetKeyState() {
  console.log("Resetting state!");
  window.clearTimeout(timerID);
  keyCount = 0;
}

Here’s a nice convoluted example :wink:

class Deferred {
  constructor () {
    this.promise = new Promise((resolve, reject) => {
      this.resolve = resolve
      this.reject = reject
    })
  }
}

function* iterateEvents (type) {
  let nextEvent = new Deferred()
  const onEvent = event => {
    nextEvent.resolve(event)
    nextEvent = new Deferred()
  }
  document.addEventListener(type, onEvent)
  try {
    while (true) {
      yield nextEvent.promise
    }
  } finally {
    document.removeEventListener(type, onEvent)
  }
}

class Buffer {
  static from (array) {
    const buffer = new Buffer(array.length)
    return buffer.push(...array)
  }
  
  constructor (length) {
    this.length = length
    this.data = Array(length).fill(undefined)
  }
  
  push (...values) {
    this.data.push(...values)
    this.data = this.data.slice(-this.length)
    return this
  }
  
  values () {
    return this.data.slice().values()
  }
  
  equals (buffer) {
    return this.data.every((value, index) => value === buffer.data[index])
  }
}

async function matchKeyboardSequence (sequence, timeoutTime, callback) {
  let pressed
  const clearPressed = () => pressed = new Buffer(sequence.length)
  clearPressed()
  
  let timeoutId
  const resetTimeout = () => {
    clearTimeout(timeoutId)
    timeoutId = setTimeout(() => {
      clearPressed()
      resetTimeout()
    }, timeoutTime)
  }
  resetTimeout()
  
  for await (event of iterateEvents('keydown')) {
    resetTimeout()
    if (pressed.push(event.keyCode).equals(sequence)) {
      clearPressed()
      callback()
    }
  }
}

const konami = Buffer.from([38, 38, 40, 40, 37, 39, 37, 39, 66, 65])
matchKeyboardSequence(konami, 1000, () => alert('Cheat code activated!'))
1 Like

Haha, that is great! :stuck_out_tongue: