<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Donovan Lafferty</title>
    <description>The latest articles on DEV Community by Donovan Lafferty (@donovanlafferty).</description>
    <link>https://dev.to/donovanlafferty</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3955210%2F3be071d9-26b2-4886-a93c-bd0f3d2dd68b.jpg</url>
      <title>DEV Community: Donovan Lafferty</title>
      <link>https://dev.to/donovanlafferty</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/donovanlafferty"/>
    <language>en</language>
    <item>
      <title>Building a 1980s Mainframe Slot Machine in Vanilla JS: RNG Math, Web Audio, and CLI Integration</title>
      <dc:creator>Donovan Lafferty</dc:creator>
      <pubDate>Wed, 27 May 2026 21:34:32 +0000</pubDate>
      <link>https://dev.to/donovanlafferty/building-a-1980s-mainframe-slot-machine-in-vanilla-js-rng-math-web-audio-and-cli-integration-59c6</link>
      <guid>https://dev.to/donovanlafferty/building-a-1980s-mainframe-slot-machine-in-vanilla-js-rng-math-web-audio-and-cli-integration-59c6</guid>
      <description>&lt;p&gt;Hello, my name is Donovan Lafferty. For my latest project showcase, I wanted to build something that blended the rigid constraints of vintage computing aesthetics with modern browser-native engineering.&lt;/p&gt;

&lt;p&gt;The result is a fully functional, text-based dot-matrix slot machine emulator designed to mimic the look, feel, and sound of an early 1980s microcomputer text terminal. Built entirely from scratch using vanilla JavaScript (ES6+), HTML5, and Tailwind CSS, the project operates completely without external game engines, libraries, or dependencies.&lt;/p&gt;

&lt;p&gt;In this build log, I’ll break down the core software architecture, the casino math engine driving the volatility, and how I approached procedural retro sound synthesis.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Watch the full gameplay demonstration on YouTube:&lt;/strong&gt; &lt;a href="https://youtu.be/OWGsAOXGGtE" rel="noopener noreferrer"&gt;https://youtu.be/OWGsAOXGGtE&lt;/a&gt;&lt;br&gt;
👉 &lt;strong&gt;Play the live build right in your browser:&lt;/strong&gt; &lt;a href="https://silver-nadia-34.tiiny.site" rel="noopener noreferrer"&gt;https://silver-nadia-34.tiiny.site&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  1. The Visual Architecture: High-Contrast Monospace Styling
&lt;/h2&gt;

&lt;p&gt;To establish a pure retro engineering aesthetic, I bypassed classic analog textures or simulated CRT scanline filters. Instead, the layout prioritizes razor-sharp, high-DPI custom monospace typography (utilizing the Fira Mono typeface) optimized for flat, pixel-sharp monochrome displays.&lt;/p&gt;

&lt;p&gt;The terminal chassis selection lets the user swap between classic hardware profiles on the fly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;*&lt;em&gt;P1 Phosphor Green *&lt;/em&gt;(Classic terminal VFD style)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VT100 Amber Plasma&lt;/strong&gt; (DEC plasma emulation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teletype Paper White&lt;/strong&gt; (Early paper terminal output)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lab VFD Cobalt&lt;/strong&gt; (Compact laboratory vacuum fluorescent style)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make winning combinations visually striking within a flat text space, the engine maps the winning payline vector coordinates and injects a synchronized, inverted-color blink cycle (.win-blink) directly into the VT100 grid cells.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. The Casino Math Engine: Volatility Tuning &amp;amp; Hit Frequency
&lt;/h2&gt;

&lt;p&gt;Designing a slot machine that feels authentic requires moving beyond uniform randomness. If every symbol has an equal chance of appearing on every reel, the game fails to replicate a genuine casino experience.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Virtual Reel Strips &amp;amp; Symbol Weighting&lt;/em&gt;&lt;br&gt;
The mathematics engine utilizes a high-density, weighted simulation array. Each virtual reel strip is an array of custom symbol objects defined with varying frequencies (weights). Lower-tier symbols appear frequently to keep line hits steady, while top-tier symbols are intentionally scarce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[7] LUCKY SEVEN (Jackpot Multiplier: 120x) — Weight: 2&lt;/li&gt;
&lt;li&gt;[@] MONITOR (Multiplier: 45x) — Weight: 3&lt;/li&gt;
&lt;li&gt;[$] CORE (Multiplier: 20x) — Weight: 4&lt;/li&gt;
&lt;li&gt;[♣] CLOVER (Multiplier: 10x) — Weight: 4&lt;/li&gt;
&lt;li&gt;[▲] SHIELD (Multiplier: 5x) — Weight: 5&lt;/li&gt;
&lt;li&gt;[≈] COMMS (Multiplier: 2x) — Weight: 6&lt;/li&gt;
&lt;li&gt;[?] PORT (Scatter/Wild Utility) — Weight: 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Math Balancing&lt;/em&gt;&lt;br&gt;
In standard play, each strip contains 25 symbols with exactly 1 Scatter Port. The probability ($p$) of a scatter landing anywhere in the 3 visible rows of a single column is exactly $\frac{3}{25} = 12.0\%$.&lt;/p&gt;

&lt;p&gt;By mapping this across a 5-reel matrix using a binomial distribution, the bonus trigger probability calculates to roughly 1.43%, meaning a player will experience the main bonus sequence approximately once every 70 spins. This creates an incredibly engaging standard-play loop.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Advanced Gameplay Logic: Dual-Utility Scatter Wilds
&lt;/h2&gt;

&lt;p&gt;One of the most complex algorithmic tasks in this project was engineering a payline scoring engine capable of processing symbols left-to-right while factoring in &lt;strong&gt;Dual-Utility Scatter Wilds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When the [?] Port symbol lands on the grid, the payline evaluator runs a two-tier check:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Global Scatter Array Scan:&lt;/strong&gt; It tracks the total quantity of [?] symbols across all 5 columns to check for bonus game triggers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wild Substitution Algorithm:&lt;/strong&gt; On active paylines, it treats the [?] symbol as a wildcard. The evaluator dynamically searches the array for the first non-wild symbol on the path to establish the winning target type, smoothly computing payouts even if a line is a mixture of standard symbols and scatters.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Additionally, I hardcoded a &lt;strong&gt;2-of-a-Kind Momentum Mechanic&lt;/strong&gt; specifically for the highest-paying symbol. Landing just two consecutive [7] symbols (or a [7] and a Wild [?]) on an active payline returns an exciting 15x line bet payback, ensuring close calls still reward the player.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The "Core Intrusion" Bonus Loop &amp;amp; Screen-Collapse Transition&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Landing 3, 4, or 5 Scatters activates the &lt;strong&gt;Core Intrusion Free Spins Mode&lt;/strong&gt;, granting &lt;strong&gt;8, 12, or 20 Free Spins&lt;/strong&gt; respectively.&lt;/p&gt;

&lt;p&gt;To heighten the cinematic experience, the game pauses user inputs and triggers an automated terminal cutscene. The screen undergoes a dramatic "CRT power shutdown" style horizontal collapse animation before reopening into a warning-red emergency interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// A look at the automated cutscene staging
function executeTransitionCutscene(onMidpoint, onComplete) {
  const shutter = document.getElementById('crt-shutter');
  shutter.classList.add('crt-turn-off'); // Collapses screen horizontally

  setTimeout(() =&amp;gt; {
    if (onMidpoint) onMidpoint();
    shutter.classList.remove('crt-turn-off');
    shutter.classList.add('crt-turn-on'); // Re-opens screen to new theme

    setTimeout(() =&amp;gt; {
      shutter.classList.remove('crt-turn-on');
      if (onComplete) onComplete();
    }, 700);
  }, 750);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During this free spins loop, the mathematics change entirely to maximize volatility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lower-paying symbols (&lt;strong&gt;SHIELD&lt;/strong&gt; and &lt;strong&gt;COMMS&lt;/strong&gt;) are completely purged from the reels.&lt;/li&gt;
&lt;li&gt;The jackpot &lt;strong&gt;LUCKY SEVEN&lt;/strong&gt; symbol doubles its frequency weight.&lt;/li&gt;
&lt;li&gt;The reel strips shrink to just &lt;strong&gt;16 symbols&lt;/strong&gt;, driving the retrigger probability up to &lt;strong&gt;4.87% (about 1 in 20.5 spins)&lt;/strong&gt;. If 3, 4, or 5 scatters land during the bonus, they cleanly stack &lt;strong&gt;+5, +10, or +15 extra spins&lt;/strong&gt; onto the player's remaining total without freezing the automatic game progression.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Procedural Audio Synthesis via Web Audio API
&lt;/h2&gt;

&lt;p&gt;To keep the game truly lightweight and completely self-contained in a single file, I refused to load external .mp3 or .wav sound samples. Instead, the entire soundscape is synthetically generated on the fly using the browser's native &lt;strong&gt;Web Audio API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By building custom oscillator chains and exponential gain envelope decays, the game mimics vintage hardware components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mechanical Keystrokes:&lt;/strong&gt; High-frequency, ultra-short sine wave burst ($950\text{Hz} - 1200\text{Hz}$ over $0.012$ seconds).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teletype Relays &amp;amp; Reel Locks:&lt;/strong&gt; Short, crisp sawtooth waves mimicking physical stepper motors clicking into place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jackpot Chimes:&lt;/strong&gt; A cascading, musical arpeggio array of pure sine frequencies scaling up to $1046\text{Hz}$.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Emergency Siren Warbles:&lt;/strong&gt; Alternating, low-frequency sawtooth wave sweeps that pitch up and down to build tension during the Core Intrusion transition.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Interactive Command Line Interface (CLI)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The control panel bridge connects the physical button layout directly to an interactive input terminal channel. When a user changes their active lines or stakes via the deck interface, an automated autotyping function types out the raw system instructions (e.g., THEME COBALT, BET +5, LINES 5) character-by-character inside the input field alongside real mechanical typing sound effects before executing the change. Users can also select the input bar and type these diagnostic terminal commands manually.&lt;/p&gt;

&lt;p&gt;Thanks for checking out my work! If you have any questions about the pseudo-RNG logic, the Web Audio architecture, or vintage interface replication in vanilla JS, let's chat in the comments section below.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Developed by Donovan Lafferty.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By building custom oscillator chains and exponential gain envelope decays, the game mimics vintage hardware components:&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>gamedev</category>
      <category>webdev</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
