
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/ */