
Created 2025-08-21
/**
 * ============================================================================
 * =                            Mandelbrot Set                                =
 * ============================================================================
 *
 * I'm always fascinated by fractals. It's truly amazing that fractals allows
 * us generate complex and beautiful patterns from simple rules or code.
 *
 * The Mandelbrot set[1] is one of the most famous fractals. So I want to use
 * Recho to draw a text-based Mandelbrot set to demonstrate we can create
 * something appealing with just few lines of code in Recho.
 *
 * I'm not going to explain the details of what the Mandelbrot set is or how to
 * implement it here. The whole idea is that we apply certain math formulas to
 * each point of a plane iteratively until the point satisfies certain
 * conditions. Then we can color the point based on the number of iterations.
 * We're using characters here of course!
 */
const cols = 80;
const rows = 30;
const maxIter = 80;
const colors = ["·", "*", "o", "O", "@"];
//➜ ················································································
//➜ ················································································
//➜ ······················································O@························
//➜ ····················································o@@@@*······················
//➜ ····················································O@@@@*······················
//➜ ·············································@·······@@@*·······················
//➜ ·············································@@·*@@@@@@@@@@@@···················
//➜ ·············································@@@@@@@@@@@@@@@@@@@@···············
//➜ ·········································*OoO@@@@@@@@@@@@@@@@@@@*···············
//➜ ···········································@@@@@@@@@@@@@@@@@@@@@@···············
//➜ ·········································@@@@@@@@@@@@@@@@@@@@@@@@@@·············
//➜ ·······························@·O@**····*@@@@@@@@@@@@@@@@@@@@@@@@O·············
//➜ ······························*@@@@@@@@··@@@@@@@@@@@@@@@@@@@@@@@@@@·············
//➜ ·····························*@@@@@@@@@@*@@@@@@@@@@@@@@@@@@@@@@@@@o·············
//➜ ··························*o*@@@@@@@@@@@o@@@@@@@@@@@@@@@@@@@@@@@@o··············
//➜ ············@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*················
//➜ ··························*o*@@@@@@@@@@@o@@@@@@@@@@@@@@@@@@@@@@@@o··············
//➜ ·····························*@@@@@@@@@@*@@@@@@@@@@@@@@@@@@@@@@@@@o·············
//➜ ······························*@@@@@@@@··@@@@@@@@@@@@@@@@@@@@@@@@@@·············
//➜ ·······························@·O@**····*@@@@@@@@@@@@@@@@@@@@@@@@O·············
//➜ ·········································@@@@@@@@@@@@@@@@@@@@@@@@@@·············
//➜ ···········································@@@@@@@@@@@@@@@@@@@@@@···············
//➜ ·········································*OoO@@@@@@@@@@@@@@@@@@@*···············
//➜ ·············································@@@@@@@@@@@@@@@@@@@@···············
//➜ ·············································@@·*@@@@@@@@@@@@···················
//➜ ·············································@·······@@@*·······················
//➜ ····················································O@@@@*······················
//➜ ····················································o@@@@*······················
//➜ ······················································O@························
//➜ ················································································
{
  let output = "";
  for (let y = 0; y < rows; y++) {
    for (let x = 0; x < cols; x++) {
      const re = map(x, 0, cols, -2.5, 1);
      const im = map(y, 0, rows, -1, 1);
      let [a, b, i] = [0, 0, 0];
      while (i < maxIter) {
        [a, b] = [a * a - b * b + re, 2 * a * b + im];
        if (a * a + b * b > 4) break;
        i++;
      }
      const index = ~~((i / maxIter) * (colors.length - 1));
      output += colors[index];
    }
    output += y === rows - 1 ? "" : "\n";
  }
  echo(output);
}
function map(x, d0, d1, r0, r1) {
  return r0 + ((r1 - r0) * (x - d0)) / (d1 - d0);
}
/**
 * Again, you don't need to completely understand the code above for now. If
 * you find textual outputs can be interesting and creative by this example,
 * that's the point!
 *
 * If you're really curious about Mandelbrot set, here are some examples that
 * I made with Charming.js[2] you may find interesting:
 *
 * - Multibrot Set: https://observablehq.com/d/fc2cfd9ae9e7524c
 * - Multibrot Set Table: https://observablehq.com/d/3028c0d5655345e3
 * - Multibrot Set Transition: https://observablehq.com/d/c040d3db33c0033e
 * - Zoomable Mandelbrot Set (Canvas): https://observablehq.com/d/2e5bdd2365236c2d
 * - Zoomable Mandelbrot Set (WebGL): https://observablehq.com/d/cfe263c1213334e3
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *                              References
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * [1] https://en.wikipedia.org/wiki/Mandelbrot_set
 * [2] https://charmingjs.org/
 */