Omniracle

How can I implement a simple pattern prediction algorithm similar to Brain Frog's frog in JavaScript?

You don’t need a PhD in frog psychology—just a few lines of JavaScript that learn from what the player just did. The Brain Frog opponent works by “reading your moves” and hitting you hard when you become predictable [1]. Under the hood, that’s a classic next-symbol predictor, and we can build one using simple techniques.

What kind of predictor can you use?

  • Frequency‑based – pick the move that has appeared most often in the history so far [20].
  • Markov chain (1‑step) – predict the next move based only on the most recent move, using a transition table built from past play [12][13][14].
  • N‑gram (generalised Markov) – look at the last (n‑1) moves to guess the next one [9].
  • Fixed rules – hard‑code patterns like “if the player alternates A‑B‑A‑B, guess A next” [19].
  • Random sampling – a fallback that just picks any possible move at random [18].

All of these can be implemented in vanilla JavaScript; the most flexible for a game like Brain Frog is the Markov chain approach.

A plain‑JavaScript Markov predictor

Below is a simplified version based on the idea of splitting a sequence into elements and recording what follows each one, similar to the snippet in [14].

// Build a transition map from a history array of moves
function buildMarkovChain(history) {
  const chain = {};
  for (let i = 0; i < history.length - 1; i++) {
    const current = history[i];
    const next = history[i + 1];
    if (!chain[current]) {
      chain[current] = [];
    }
    chain[current].push(next);
  }
  return chain;
}

// Predict the next move given the last observed move
function predictNext(chain, lastMove) {
  const possible = chain[lastMove];
  if (!possible || possible.length === 0) {
    // fallback: random or most frequent
    return 'ROCK'; // replace with sensible fallback
  }
  // pick a random follower from the training data
  return possible[Math.floor(Math.random() * possible.length)];
}

You train it with the player’s move history (e.g., ['ROCK', 'PAPER', 'SCISSORS', 'ROCK', ...]). Then, after each round, feed the latest move to predictNext—the returned value is your best guess of what the player will do next. If the player tends to repeat sequences, the Markov chain will catch that.

Making it faster or deeper

  • For O(1) look‑ups, you can store the transitions in a trie‑like structure, going down a “letter” (move) at a time [2].
  • To consider more context, use an n‑gram model where the key is the last (n‑1) moves and the value is the next move [9].
  • A frequency‑based shortcut: just count occurrences of each move and always guess the most common one [20]—simpler but misses order.

Countering like the frog

Once you’ve predicted the next move, you can counter it just like the Brain Frog does: play the move that beats the prediction [1]. That turns your predictor into an opponent that punishes lazy players who fall into patterns.

So go ahead, grab that history array, wrap it in a Markov chain (or a frequency counter), and let your frog start out‑smarting button‑mashing humans. Ribbit.