20 Questions: Engineering a 16,000+ Entity Bayesian Mind Oracle, Shannon Entropy Questioning, and a Living Cybernetic Eyeball in Pure Vanilla JS
How we built an in-browser 20 Questions Mind Oracle capable of reading thoughts across 16,000+ entities with zero server round-trips: information-theoretic Shannon entropy question selection, soft Bayesian likelihood updates, popularity prior weighting, a living SVG vector eyeball with real-time mouse tracking and autonomous blinking, full turn rollback, and procedural Web Audio orchestration.
Twenty Questions is one of the oldest and most fascinating parlour games in human history. At its core lies a profound mathematical truth discovered by Claude Shannon in the 1940s: each well-chosen yes-or-no question can bisect a possibility space in half, extracting exactly one bit of information. In theory, twenty optimal questions provide $2^{20} = 1,048,576$ distinct binary leaves — enough resolution to pinpoint a single needle in an astronomical haystack.
Yet almost every digital implementation of Twenty Questions over the last two decades falls into one of two extremes. Either it is a simplistic high-school programming exercise hardcoding a static decision tree of fifty animals, or it is a proprietary server-side black box like Akinator that streams opaque network calls to a remote database. If the server is offline or lagging, the magic evaporates.
With 20 Questions: The Mind Oracle, we set out to build something radically different: a completely self-contained, client-side Bayesian deduction engine capable of reading a player's thoughts across more than 16,000 distinct entities with zero network latency, zero external API keys, a living vector eyeball that tracks your pointer in real time, full turn rollback, and procedural Web Audio orchestration. Here is the complete technical story of how the Mind Oracle was built.
1. The 16,221-Entity Knowledge Matrix
The first and most daunting hurdle was scale. If an AI claims to "read your mind," it cannot merely know that a tiger is a striped animal and an airplane flies. It must know about Darth Vader, the James Webb Space Telescope, the Platypus, Sourdough Bread, the Parthenon, Quantum Entanglement, Mjolnir, the Mona Lisa, and the Archimedes Screw.
However, shipping tens of thousands of deeply annotated entities to a mobile browser poses an immediate bandwidth problem. A naive JSON dump of 16,000 items with rich descriptions, categories, icons, and hundreds of trait annotations easily balloons into an unwieldy 45MB network payload.
We solved this through a hierarchical taxonomy matrix combined with sparse boolean trait mapping across 10 distinct knowledge realms:
- Nature & Biology (Animals, plants, fungi, organs, prehistoric beasts, ecosystems)
- History & Mythology (Deities, historical figures, legendary artifacts, ancient monuments)
- Science & Technology (Inventions, computing hardware, physics concepts, lab apparatus)
- Food & Culinary (Dishes, baked goods, beverages, fruits, spices, kitchen tools)
- Pop Culture & Media (Fictional heroes, villains, sci-fi spacecraft, anime icons, video games)
- Astronomy & Cosmos (Planets, constellations, nebulae, space probes, celestial phenomena)
- Geography & Landmarks (Wonders of the world, capitals, mountain peaks, bodies of water)
- Everyday Objects & Tools (Musical instruments, stationery, apparel, workshop implements)
- Arts & Philosophy (Movements, classical masterpieces, philosophical paradoxes, literature)
- Sports & Leisure (Athletics equipment, Olympic disciplines, games, vehicles)
By storing primary entities with compact trait fingerprints (— boolean flags such as living, human_made, handheld, edible, fictional, aquatic, celestial, and electric —), the entire 16,221-entity dataset compresses down into a clean 2.4MB static script that parses in under 35 milliseconds on modern V8 engines.
2. Popularity Priors: Why Power-Law Weighting Matters
In a naive uniform probability model, every entity starts with an equal prior probability:
P_initial = 1 / 16221 = 0.0000616;
This creates an infuriating player experience. If a player is thinking of an Apple, and the oracle has narrowed the field to edible, red, handheld fruits grown on trees, a uniform model gives equal weight to a standard Honeycrisp Apple and an obscure 18th-century French cider cultivar like the Calville Blanc d'Hiver. Without priors, the AI constantly blurts out hyper-obscure dictionary footnotes instead of the universally obvious answer.
To mirror human cognition, we implemented a power-law prior distribution weighted by cultural ubiquity ($1 \le \text{pop} \le 10$):
const w = Math.pow(item.pop || 5, 1.8);
sumWeights += w;
// Normalized P0(item) = w / sumWeights
An exponent of 1.8 gives ubiquitous household objects (pop 9–10) approximately fifteen times higher starting cognitive probability than obscure esoteric relics (pop 1–2), while keeping every single item reachable if specific discriminators confirm it.
3. Shannon Entropy & Maximum Information Gain
How does the Mind Oracle decide what to ask next? Random questions or hardcoded orderings will fail catastrophically: asking "Is it manufactured in Japan?" on turn 1 is useless because 99% of things aren't.
Instead, our engine executes an information-theoretic search over all unasked questions on every single turn. The Shannon Entropy $H$ of a discrete probability distribution over candidate items is:
To maximize the expected information gain $\Delta H$, the optimal question is the one whose binary partition splits the remaining active probability mass as close to 50/50 as possible:
let pTrue = 0;
for (const c of viablePool) {
if (c.item.traits[q.trait]) pTrue += c.prob;
}
// Optimal question minimizes distance to 0.5 (ideal binary bisection)
const ratio = pTrue / totalViableProb;
const diffFromHalf = Math.abs(ratio - 0.5);
If a question splits the remaining viable candidate mass at exactly 50%, an answer of either Yes or No cuts the uncertainty directly in half, yielding 1.0 full bit of Shannon information. Over 14 consecutive bisections, $2^{14} = 16,384$ entities are isolated down to a single candidate. That is why the Oracle consistently guesses items by question 12–15!
4. Soft Bayesian Likelihood Updates & Fuzzy Logic
Rigid binary decision trees possess a catastrophic fatal flaw: they cannot tolerate human error. If a player mistakenly thinks a Tomato is a vegetable instead of a botanical fruit, a hard tree instantly discards the tomato forever. Similarly, is a Mushroom a plant? Biologically no (it's a fungus), but a casual player might answer "Probably."
To eliminate hard failures, the Mind Oracle implements soft likelihood updates across a 5-button certainty console:
case "YES": matchMult = 1.00; nonMatchMult = 0.06; break;
case "PROBABLY": matchMult = 0.82; nonMatchMult = 0.24; break;
case "UNSURE": matchMult = 0.50; nonMatchMult = 0.50; break;
case "PROBABLY_NOT": matchMult = 0.24; nonMatchMult = 0.82; break;
case "NO": matchMult = 0.06; nonMatchMult = 1.00; break;
}
Notice that answering "No" does not set non-matching items to zero ($0.0\times$), but to $0.06\times$. If the player made a single mistake early on, strong affirmative answers on subsequent questions can still pull the true entity back into top contention. After every turn, probabilities are re-normalized ($\sum P = 1.0$) and sorted in descending rank order.
5. The Living Arcane Cybernetic Eyeball Core
In early prototype builds, the Oracle was represented by a plain text header and an emoji: 👁️. While functional, it looked static, sterile, and failed to communicate the feeling of an ancient, sentient entity scrutinizing your mind.
We completely replaced that placeholder with a custom-engineered Living Vector Eyeball Organism rendered via SVG:
- Astrolabe Orbit Dials: Two counter-rotating dashed celestial brass and cyan rings rotate continuously around the sclera, evoking an ancient astrolabe measuring celestial alignments.
- Multi-tier Sclera & Synaptic Veins: A deep cosmic sphere with radial lighting and delicate cyan synaptic circuit lines pulsating across the cornea.
-
Corneal Lens Reflection: A delicate curved white gloss arc (
opacity="0.12") simulates true spherical 3D glass curvature. -
Limbal Glow Ring & Specular Highlights: An outer limbal ring enhanced by an SVG Gaussian bloom filter (
stdDeviation="3") with dual-point corneal specular highlights.
Smooth Pointer Tracking via Eased Lerp Interpolation
The pupil doesn't stare blankly ahead. As you move your mouse or touch the screen, the iris and pupil smoothly pivot to follow your cursor wherever you move:
const dx = pointerX - eyeCenterX;
const dy = pointerY - eyeCenterY;
const dist = Math.hypot(dx, dy);
const maxRadius = 24; // SVG units max displacement
const pull = Math.min(dist / 320, 1);
targetX = (dx / dist) * (pull * maxRadius);
targetY = (dy / dist) * (pull * maxRadius);
// Animation frame loop with inertia lerping
currentX += (targetX - currentX) * 0.16;
currentY += (targetY - currentY) * 0.16;
tracker.setAttribute("transform", `translate(${currentX.toFixed(2)}, ${currentY.toFixed(2)})`);
Autonomous Eyelid Kinematics & Reactive Moods
To feel truly alive, the eye cannot remain continuously wide open. We engineered curved eyelid paths in SVG that rest well outside the visible cornea (translateY(-84px) and translateY(84px)). Every 3.5–6.7 seconds, an autonomous timer triggers a rapid, lifelike blink (translateY(0px) for 130ms), with a 22% chance of executing a natural double-blink.
Furthermore, the eyeball physically reacts to your responses:
- Affirmative (Yes / Probably): Sclera glows with an emerald aura; pupil dilates to $r = 16\text{px}$ in inquisitive excitement.
- Negative (No / Probably Not): Crimson analytical pulse; pupil constricts to a focused $r = 9\text{px}$ as impossible hypotheses are purged.
- Ambiguity (Unsure): Amethyst aura pulse with neutral calibration.
- Revelation (Dramatic Accusation): Intense solar gold aura pulse with rhythmic pulsing and accelerated astrolabe spin.
6. The Time-Travel Rollback Engine: Instant Back & Undo
One of the most requested features from early testers was simple: "What if I misclicked or misunderstood a question? Let me go back!"
In a Bayesian probabilistic system, you cannot simply "divide out" the last multiplier. Because candidate arrays are sorted, truncated, and normalized with floating-point precision on every single turn, attempting to reverse the math introduces catastrophic rounding drift.
Instead, we built a zero-drift Snapshot Stack (turnHistory = []). Before modifying candidate arrays or advancing the turn index, we push a snapshot of the exact game state:
turnHistory.push({
candidates: candidates.map(c => ({ item: c.item, prob: c.prob, initialProb: c.initialProb })),
askedQuestions: [...askedQuestions],
currentQuestion: currentQuestion,
currentQuestionIndex: currentQuestionIndex,
remainingHealth: remainingHealth,
currentScore: currentScore,
oracleConfidence: oracleConfidence
});
When the player clicks the dedicated ↩ BACK button on the Question Card, the ↩ UNDO button in the header, or presses Backspace / Ctrl+Z, the top snapshot is popped. Candidates, probabilities, question history, health, score, and confidence are restored with 100% mathematical fidelity, while the living eyeball flutters in a rapid temporal rewind animation.
7. Web Audio Synthesis & Soundtrack Interaction Gating
Audio is half the immersion. We engineered a dual-layer audio architecture:
- Procedural Acoustic SFX: Pure Web Audio API synthesizers generating triangle and sine oscillator clicks, question arrival chimes (ascending C5–E5–G5–C6 arpeggios), affirmative pings, and deep revelation chords without loading external sound files.
-
The Background Soundtrack (
20_questions.mp3): A mystical, atmospheric ambient synth score engineered specifically for deep contemplation.
Crucially, we implemented a strict Main Menu Interaction Gate:
- The soundtrack is completely dormant during page load, preloading, or on unrelated views.
- It only starts when the game's main menu view (
#tq-view-menu) is actively presented. - Browser autoplay restrictions are seamlessly handled via an automatic gesture unlock listener (
pointerdown/keydown/click), guaranteeing that the user's very first click on the menu card immediately starts the soundtrack without console warnings. - Music pauses during game pause (Esc / P), resumes cleanly upon return, and stays in sync with the global M audio toggle.
8. Dual Modes & The Minnich Arcade Standard
To provide infinite replayability, the game includes two distinct operational modes:
- Mind Oracle Mode: The player thinks of any entity in the universe (or picks one from the searchable 16,000+ Item Codex), and the AI interrogates the player with 20 questions to deduce the secret.
- Detective Mode: The Oracle selects a secret mystery entity from the vault, and the player interrogates the Oracle by selecting strategic diagnostic questions before making a formal accusation.
Both modes fully integrate with the standard Minnich Top-Left Arcade GameHUD: health degrades as questions are spent, high-confidence deductions award massive multiplier scores, and victories submit directly to the Minnich Global Leaderboard suite.
20 Questions: The Mind Oracle is live now on Minnich.Awesome. Think of anything in the universe — and see if you can stump the Oracle.