<?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: László Kővári</title>
    <description>The latest articles on DEV Community by László Kővári (@lkovari).</description>
    <link>https://dev.to/lkovari</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4022098%2F71a685e5-6b07-41aa-9eae-fe6c0701da31.png</url>
      <title>DEV Community: László Kővári</title>
      <link>https://dev.to/lkovari</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lkovari"/>
    <language>en</language>
    <item>
      <title>From Turbo Pascal to TypeScript: A 35-Year-Old Maze Algorithm Comes Back to Life</title>
      <dc:creator>László Kővári</dc:creator>
      <pubDate>Thu, 09 Jul 2026 16:13:39 +0000</pubDate>
      <link>https://dev.to/lkovari/from-turbo-pascal-to-typescript-a-35-year-old-maze-algorithm-comes-back-to-life-4j6b</link>
      <guid>https://dev.to/lkovari/from-turbo-pascal-to-typescript-a-35-year-old-maze-algorithm-comes-back-to-life-4j6b</guid>
      <description>&lt;p&gt;In 1991, on a DOS machine with a BGI graphics driver, I wrote a small program that draw colored trees on screen. It wasn't meant to generate mazes. It became one by accident. Last weekend, 35 years and two rewrites later, I finally gave it a home in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it started: trees, not mazes
&lt;/h2&gt;

&lt;p&gt;The idea didn't begin as "let me build a maze generator." It began with drawing trees.&lt;/p&gt;

&lt;p&gt;First came binary trees — each branch splitting into two. Then I moved to trees with three branches instead of two. At some point those three branches were arranged so they met at 45-degree angles from one another, and that's when it clicked: a tree that never crosses itself, that always has exactly one path from the root to any point on it, &lt;em&gt;is&lt;/em&gt; a maze. A "perfect maze" is nothing more than a spanning tree with no cycles. I arrived at that property by drawing branches, not by studying graph theory.&lt;/p&gt;

&lt;p&gt;What came out of that was a recursive backtracking routine: pick a point, grow a branch in one of several directions, recurse, and if a direction is blocked, back up and try another. This is, in retrospect, a randomized depth-first search — the same family of technique used by what's now widely known as the "recursive backtracker" maze algorithm. I want to be precise about what I'm claiming here, because it matters: I'm not claiming to have invented backtracking, or randomized DFS, or even maze generation via spanning trees. Backtracking as a formal technique goes back to D.H. Lehmer's work in the 1950s, and randomized DFS on a grid is a fairly natural thing for anyone to land on once they're generating trees programmatically. What I &lt;em&gt;am&lt;/em&gt; saying is that I arrived at this specific approach independently, through a visual/geometric route rather than an algorithmic one, before I'd ever seen it written up as a named "maze generation algorithm" anywhere. The technique got its wider recognition in the developer community mostly through Jamis Buck's well-known 2010–2011 blog series cataloging maze algorithms — nearly twenty years after I'd written &lt;code&gt;LABYR.PAS&lt;/code&gt;. That's the honest version of the story, and it's a more interesting one than a discovery claim: two people, two decades apart, arriving at the same idea from completely different directions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The original: LABYR.PAS
&lt;/h2&gt;

&lt;p&gt;The 1991 source, &lt;code&gt;LABYR.PAS&lt;/code&gt;, is pure Turbo Pascal, built on the &lt;code&gt;crt&lt;/code&gt; and &lt;code&gt;graph&lt;/code&gt; units, targeting BGI (Borland Graphics Interface) output. A few design choices in it still hold up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A precomputed permutation table.&lt;/strong&gt; From any given heading, the algorithm can turn toward three possible directions (never back the way it came). Rather than shuffling those three options at runtime, I precomputed all six permutations of three items into a lookup table and just picked one at random each time a branch needed a direction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt;
  &lt;span class="n"&gt;dn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1..6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;1..3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a small, DOS-era trick for getting randomized turn order without runtime permutation logic — cheap on a resource-constrained machine, and honestly still a reasonable move today if you want to avoid a shuffle allocation in a hot loop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The canvas as the state.&lt;/strong&gt; Instead of maintaining a separate grid or graph structure to track which cells had been visited, the algorithm asked the screen itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight pascal"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;dotchk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;getpixel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;backgr&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="n"&gt;dotchk&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;dotchk&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the pixel wasn't the background color, something had already been drawn there. The rendered image &lt;em&gt;was&lt;/em&gt; the occupancy map — an efficient use of memory on a resource-constrained machine, at the cost of tightly coupling rendering to algorithm state in a way I wouldn't design today.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Probabilistic branching.&lt;/strong&gt; Two tunable parameters — &lt;code&gt;p&lt;/code&gt; (probability of continuing to recurse) and &lt;code&gt;plr&lt;/code&gt; (probability of turning left or right versus going straight) — shape how organic or how disciplined the resulting tree looks. That's what gives the output its distinctive, hand-drawn character rather than a uniform grid maze.&lt;/p&gt;

&lt;p&gt;It ran, it worked, and then it sat untouched for years.&lt;/p&gt;

&lt;h2&gt;
  
  
  1998: the Delphi rewrite
&lt;/h2&gt;

&lt;p&gt;Later, I ported it to Delphi — same logic, a more structured language, still native, still Windows-era. It was less a rewrite than a translation: the algorithm's bones didn't change, just the syntax and the toolchain around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Last weekend: TypeScript, and a chance to actually improve it
&lt;/h2&gt;

&lt;p&gt;I found the old source again recently and spent a weekend bringing it into the present: an Angular component with a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; renderer, running entirely in the browser. This wasn't just a syntax port. A few things needed to be genuinely rethought, and this is where 35 years of engineering practice actually shows up in the diff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recursion became an explicit stack.&lt;/strong&gt; The original relied on native Pascal recursion, which the DOS environment tolerated within its own stack segment. In JavaScript, a recursion depth of several hundred (the &lt;code&gt;depth&lt;/code&gt; parameter defaults to 700) risks a stack overflow — browsers don't give you nearly as much headroom. The TypeScript version replaces the recursive call with an explicit stack and a small state machine that reproduces the exact backtracking behavior of the original &lt;code&gt;wall&lt;/code&gt;/&lt;code&gt;backstep&lt;/code&gt; procedures — just safely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;WallFrame&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;posx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;posy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;sel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;dotn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;dotnm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;initialized&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;needBackstep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;savedLastHeading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WallFrame&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="cm"&gt;/* seed frame */&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="c1"&gt;// process frame, push a child frame instead of recursing&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;State and rendering were separated.&lt;/strong&gt; Instead of asking the canvas "is this pixel drawn," a plain typed array now tracks which cells are occupied:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OccupancyBitmap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;occupied&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;occupied&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;isFree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;py&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;py&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;px&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;py&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;occupied&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;py&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a small change, but it removes a dependency that never should have existed between what's on screen and what the algorithm knows — the kind of coupling that's easy to justify under DOS-era memory constraints and much harder to justify with a few kilobytes of typed array.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The main thread stays responsive.&lt;/strong&gt; The original's &lt;code&gt;repeat ... until keypressed&lt;/code&gt; loop was a blocking native loop — fine for DOS, fatal for a browser tab. The async version yields control back to the browser every 50 iterations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;yieldEvery&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;so generating a large, dense maze doesn't freeze the page.&lt;/p&gt;

&lt;p&gt;A couple of things also got added along the way that weren't in the 1991 version at all: a curated 18-color palette for the generated trees, and a "toothed" border effect where small random gaps are cut into the frame — details that have nothing to do with the algorithm's core logic, just an extra layer of visual character.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stayed exactly the same
&lt;/h2&gt;

&lt;p&gt;The interesting part, to me, is how much of the &lt;em&gt;behavior&lt;/em&gt; carried over unchanged across three languages and 35 years. The direction logic, the rule preventing a branch from immediately reversing on itself, and the left/right turning bias all map almost one-to-one from the original Pascal &lt;code&gt;case&lt;/code&gt; statements to their TypeScript equivalents. The algorithm itself never needed fixing — only the infrastructure around it did. That's a decent argument for getting the core logic right the first time, even on a machine with 640KB of conventional memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The live version is here: &lt;strong&gt;&lt;a href="https://lkovari.github.io/LKovariHome/#/playground/components/labyrinth-generator" rel="noopener noreferrer"&gt;Labyrinth Generator&lt;/a&gt;&lt;/strong&gt; — click the info icon on the page to see the original 1991 Pascal source alongside the current implementation.&lt;/p&gt;

&lt;p&gt;The source lives at &lt;code&gt;src/app/playground/components/labyrinth-generator&lt;/code&gt; in the &lt;a href="https://github.com/lkovari/LKovariHome" rel="noopener noreferrer"&gt;LKovariHome&lt;/a&gt; repository. If you find it interesting, a ⭐ on the repo is always appreciated.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you remember writing something similar back in the Turbo Pascal / BGI days — or if you've independently landed on the same randomized-backtracking idea from a completely different direction — I'd like to hear about it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>algorithms</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
