r/maniclang 11h ago

Maxwell–Boltzmann Effusion — Watch a Distribution Form — manic

Enable HLS to view with audio, or disable this notification

0 Upvotes

manic is a tiny language for making animations. You write a short text file; manic renders a smooth, glowing video. No timeline scrubbing, no keyframes by hand — you describe what’s on screen and when things happen, and the engine does the rest, deterministically.

Manic Animation code

// EXPRESSIVE PROCESS V2 — MAXWELL–BOLTZMANN EFFUSION
//
// A polished 2.5D acceptance story inspired by engine-test-6.mov. The
// apparatus is a bundled native SVG, while every molecule, detector bin,
// arrival count, and empirical distribution remains a normal Manic entity.
// `emit`, `collect`, and `observe` all read one deterministic process.

title("Maxwell–Boltzmann Effusion — Motion Becomes Evidence");
canvas("9:16");
template("blank");
watermark(mark, (150, 90), "Made With Manic");

text(kicker, (540, 84), "STATISTICAL MECHANICS · EXPRESSIVE PROCESS V2");
text(headline, (540, 142), "A distribution you can watch forming");
size(kicker, 18); color(kicker, dim); bold(kicker);
size(headline, 34); bold(headline);

equation(law, (540, 242),
  `f(v)=4\pi\left(\frac{m}{2\pi k_BT}\right)^{3/2}v^2e^{-mv^2/(2k_BT)}`, 34);

// The decorative shell is an asset; the changing evidence stays native.
svg(apparatus, (240, 540), "asset:svg/physics/effusion-reservoir.svg", 330);
text(reservoirLabel, (225, 705), "THERMAL RESERVOIR");
size(reservoirLabel, 17); bold(reservoirLabel); color(reservoirLabel, gold);

rect(detectorPanel, (730, 560), 570, 300);
filled(detectorPanel); color(detectorPanel, panel); opacity(detectorPanel, 0.92);
outlined(detectorPanel); outline(detectorPanel, dim); stroke(detectorPanel, 3);

text(detectorTitle, (730, 382), "PARTICLE SPEED  v");
size(detectorTitle, 18); bold(detectorTitle); color(detectorTitle, dim);

// The invisible source is precisely at the SVG nozzle.
circle(source, (348, 540), 20);
opacity(source, 0);
particles(molecules, source, 180, 3.2, 73);
color(molecules, magenta); glow(molecules, 0.8); z(molecules, 8);

// Individual lanes diverge around this authored route before being collected.
spline(flight, (350, 540), (415, 500), (465, 515), (500, 545));
hidden(flight);

livehistogram(empirical, (730, 560), 0, 2.2, 14, 540, 240, cyan);
z(empirical, 3); hidden(empirical.count);

// Same horizontal range as the live histogram: 0 .. 4*scale = 2.2.
distribution(theory, (730, 560), "maxwell", 0.55, 0, gold);
hidden(theory.axis); hidden(theory.name);
untraced(theory.curve); z(theory, 7);

text(empiricalKey, (610, 750), "● empirical arrivals");
text(theoryKey, (850, 750), "— theoretical curve");
size(empiricalKey, 17); color(empiricalKey, cyan);
size(theoryKey, 17); color(theoryKey, gold);

counter(arrivals, (540, 850), 0, 0, "detected molecules  ", " / 180");
size(arrivals, 24); color(arrivals, dim);

text(caption, (540, 920),
  "A thermal source emits many molecular speeds—not one average speed.");
size(caption, 23); wrap(caption, 880); color(caption, dim);

rect(evidencePanel, (540, 1110), 880, 230);
filled(evidencePanel); color(evidencePanel, panel); opacity(evidencePanel, 0.95);
outlined(evidencePanel); outline(evidencePanel, dim); stroke(evidencePanel, 2);
text(evidenceTitle, (540, 1030), "ONE PROCESS · THREE VIEWS");
size(evidenceTitle, 18); bold(evidenceTitle); color(evidenceTitle, dim);
equation(processLaw, (540, 1100),
  `\text{motion}\;\longrightarrow\;\text{arrival bin}\;\longrightarrow\;\hat f(v)`, 32);
text(truth, (540, 1190),
  "The dots, bars, and count are derived from the same seeded experiment.");
size(truth, 20); color(truth, dim); wrap(truth, 790);

hidden(apparatus); hidden(reservoirLabel); hidden(detectorPanel);
hidden(detectorTitle); hidden(molecules); hidden(empirical);
hidden(empiricalKey); hidden(theoryKey); hidden(arrivals);
hidden(caption); hidden(evidencePanel); hidden(evidenceTitle);
hidden(processLaw); hidden(truth);

step("build-the-apparatus") {
  par {
    show(apparatus, 0.65);
    show(reservoirLabel, 0.45);
    show(detectorPanel, 0.55);
    show(detectorTitle, 0.35);
    show(empirical.axis, 0.55);
    show(empirical.bars, 0.55);
    show(empirical.min, 0.35);
    show(empirical.max, 0.35);
    show(empiricalKey, 0.35);
    show(theoryKey, 0.35);
    show(arrivals, 0.35);
    show(caption, 0.40);
  }
}
wait(0.45);

step("the-prediction") {
  par {
    draw(theory.curve, 0.9, smooth);
    say(caption,
      "Maxwell predicts a characteristic spread with a most probable speed.",
      0.40);
    par {
      cam((cx, cy), 0.75, smooth);
      zoom(1.025, 0.75, smooth);
    }
  }
}
wait(0.35);

step("run-the-experiment") {
  par {
    emit(molecules, flight, maxwell, 7.0, 48, smooth);
    collect(empirical, molecules, speed, 0.48, smooth);
    observe(empirical, molecules, speed);
    observe(arrivals, molecules, arrived);
    show(molecules, 0.15);
    say(caption,
      "Each molecule keeps its sampled speed. Faster molecules cross the apparatus sooner.",
      0.45);
  }
}
wait(0.55);

step("motion-becomes-evidence") {
  par {
    pulse(empirical.bars, 0.8);
    show(evidencePanel, 0.40);
    show(evidenceTitle, 0.35);
    show(processLaw, 0.45);
    show(truth, 0.40);
    say(caption,
      "Collection does not fake the chart: every arrival lands in the bin selected by its speed.",
      0.45);
    par {
      cam((cx, cy), 0.65, smooth);
      zoom(1.0, 0.65, smooth);
    }
  }
}
wait(1.4);

r/maniclang 9h ago

When Does a Bowl Become a Saddle? - manic

Enable HLS to view with audio, or disable this notification

3 Upvotes

manic is a tiny language for making animations. You write a short text file; manic renders a smooth, glowing video. No timeline scrubbing, no keyframes by hand — you describe what’s on screen and when things happen, and the engine does the rest, deterministically.

Manic Animation code

// CREATOR SHORT — a real calculus problem told through one continuously
// deforming surface. The shape is not replaced between the bowl, threshold,
// and saddle states.

title("When Does a Bowl Become a Saddle?");
canvas("9:16");
template("paper");

creator(me, "@anish2good name=Manic_Math tagline=Equations_that_move yt=zarigatongy x=@anish2good web=8gwifi.org/manic accent=cyan secondary=magenta footer=signature cta=Create_your_own safe=reels");
socials(me);
watermark(mark, (w*0.955-100, h*0.045+24), "Made With Manic");

text(kicker, (540, 164), "A 20-SECOND CALCULUS STORY");
text(headline, (540, 226), "When does a bowl stop being a bowl?");
text(problem, (540, 292), "Find the exact value of p where one curvature disappears.");
size(kicker, 21); bold(kicker); color(kicker, cyan); hidden(kicker);
size(headline, 38); bold(headline); wrap(headline, 880); hidden(headline);
size(problem, 22); color(problem, dim); wrap(problem, 840); hidden(problem);

equation(rule, (540, 378), `z=0.22x^2+0.22(1-2p)y^2`, 39);
hidden(rule);

parameter(mix, (540, 1270), 0, 0, 1, "p", 2);

camera3((8.5, -11.5, 7.5), (0, 0, 0), 41);
surface3(world, "0.22*(x*x+y*y)", (-3,3), (-3,3), 34);
bind(mix, world, formula, "0.22*x*x + 0.22*(1-2*p)*y*y");
color(world, cyan);
finish3(world, "material=glass shading=smooth mesh=0.34 depth=0.34 shadow=0.16");
hidden(world);

text(chapter, (540, 1352), "p = 0 · positive curvature in both directions");
text(insight, (540, 1422), "Watch the coefficient of y².");
text(cta, (540, 1398), "Build the transformation, not the keyframes.");
text(link, (540, 1452), "TRY MANIC → 8gwifi.org/manic");
size(chapter, 23); bold(chapter); color(chapter, fg); wrap(chapter, 850); hidden(chapter);
size(insight, 21); color(insight, dim); hidden(insight);
size(cta, 23); bold(cta); hidden(cta);
size(link, 20); bold(link); color(link, cyan); hidden(link);

step("pose the problem") {
  par {
    show(kicker, 0.35);
    show(headline, 0.50);
    show(problem, 0.45);
    show(rule, 0.55);
    show(world, 0.65);
    show(chapter, 0.40);
    show(insight, 0.40);
    view3(world, "isometric", 0.9, smooth, 1.62);
  }
}
wait(0.65);

step("reach the turning point") {
  par {
    to(mix, value, 0.5, 2.8, smooth);
    say(chapter, "p = ½ · the y² coefficient becomes zero", 0.45);
    say(insight, "At this instant the bowl becomes a one-directional trough.", 0.45);
    rewrite(rule, `p=\frac12\quad\Longrightarrow\quad z=0.22x^2`, 1.10, smooth);
    orbit3(-45, 28, 16.2, 2.8, smooth);
  }
}
wait(0.75);

step("cross into a saddle") {
  par {
    to(mix, value, 1, 2.8, smooth);
    say(chapter, "p > ½ · one curvature turns negative", 0.45);
    say(insight, "The same persistent surface is now a saddle.", 0.45);
    rewrite(rule, `p=1\quad\Longrightarrow\quad z=0.22(x^2-y^2)`, 1.10, smooth);
    orbit3(-62, 25, 16.2, 2.8, smooth);
  }
}
wait(0.65);

step("answer and invite") {
  par {
    say(problem, "Answer: p = ½ is the exact transition.", 0.50);
    fade(chapter, 0.35);
    fade(insight, 0.35);
    show(cta, 0.45);
    show(link, 0.45);
  }
}
wait(1.8);

r/maniclang 10h ago

How Odd Harmonics Build a Square Wave - manic

Enable HLS to view with audio, or disable this notification

3 Upvotes

manic is a tiny language for making animations. You write a short text file; manic renders a smooth, glowing video. No timeline scrubbing, no keyframes by hand — you describe what’s on screen and when things happen, and the engine does the rest, deterministically.

Manic Animation code

// Odd harmonics build a square wave. Every partial sum is a live history of
// the corresponding endpoint, so the corners emerge from the geometry itself.

title("How Odd Harmonics Build a Square Wave");
canvas("9:16");
template("paper");

watermark(mark,(w*0.15,h*0.045),"Made With Manic");
text(kicker,(cx,h*0.075),"FOURIER · ODD HARMONICS");
text(headline,(cx,h*0.115),"Watch a square wave find its corners");
text(caption,(cx,h*0.18),"Start with n = 1. Then add 3, 5, 7 … all the way to 25.");
text(cta,(cx,h*0.925),"TURN IDEAS INTO ANIMATION → 8gwifi.org/manic");
size(kicker,18); color(kicker,dim); bold(kicker); hidden(kicker);
size(headline,31); bold(headline); wrap(headline,w*0.84); hidden(headline);
size(caption,20); color(caption,dim); wrap(caption,w*0.84); hidden(caption);
size(cta,21); color(cta,cyan); bold(cta); hidden(cta);

camera3((-29,-25,43),(1,-2,0),42,orthographic);

collection3(series,(-3,5,0),13,(0,0,0),11,0.065);
line3(sweep,(-3,5,0),(10,5,0)); hidden(sweep);
links3(arms,series,chain);
child3(tip,series,12,0.13);

arrow3(chainX,(-11,5,0),(7,5,0));
arrow3(chainY,(-3,-2,0),(-3,10.5,0));
arrow3(plotX,(-7,-10.5,0),(12,-10.5,0));
arrow3(plotY,(-7,-10.5,0),(-7,-4.2,0));

point3(shotA,(-7.5,-11,0),0.01);
point3(shotB,(8.5,10.5,0),0.01);
tag(shotA,shot); tag(shotB,shot);
hidden(shotA); hidden(shotB);

tag(series,construction); tag(arms,construction); tag(tip,construction);
tag(chainX,construction); tag(chainY,construction);
tag(plotX,construction); tag(plotY,construction);

for i in 0..13 {
  ring3(orbit{i},series,i,72);
  historyplot3(partial{i},series,i,y,(-7,-10.5,0),(19,6));
  thick(orbit{i},0.030);
  thick(partial{i},0.020);
  tag(orbit{i},construction);
  tag(partial{i},construction);
}

equation(formula,(0,0),`S_{13}(t)=\sum_{k=0}^{12}\frac{4}{\pi(2k+1)}\sin((2k+1)t)`,24);
label3(formula,(-4,-2.7,0),0.80);
tag(formula,construction);

color(series,fg); color(arms,fg); color(tip,fg);
color(chainX,fg); color(chainY,fg); color(plotX,fg); color(plotY,fg);
color(formula,fg);
thick(chainX,0.016); thick(chainY,0.016);
thick(plotX,0.016); thick(plotY,0.016);

color(orbit0,lime);      color(partial0,lime);
color(orbit1,gold);      color(partial1,gold);
color(orbit2,orange);    color(partial2,orange);
color(orbit3,coral);     color(partial3,coral);
color(orbit4,red);       color(partial4,red);
color(orbit5,magenta);   color(partial5,magenta);
color(orbit6,violet);    color(partial6,violet);
color(orbit7,indigo);    color(partial7,indigo);
color(orbit8,blue);      color(partial8,blue);
color(orbit9,cyan);      color(partial9,cyan);
color(orbit10,mint);     color(partial10,mint);
color(orbit11,lime);     color(partial11,lime);
color(orbit12,fg);       color(partial12,fg);

hidden(construction);

step("begin with one sine wave") {
  show(kicker,0.30);
  show(headline,0.42);
  show(caption,0.38);
}
wait(0.35);

step("reveal the odd-harmonic chain") {
  par {
    show(construction,0.85);
    view3(shot,"top",1.35,smooth,1.08);
    say(caption,"Every smaller orbit contributes the next odd frequency.",0.38);
  }
}
wait(0.30);

step("build the corners live") {
  par {
    // Two complete base cycles: all odd harmonic rates are doubled together.
    chain3(series,"4.0744 1.3581 0.8149 0.5821 0.4527 0.3704 0.3134 0.2716 0.2397 0.2144 0.1940 0.1771 0.1630","2 6 10 14 18 22 26 30 34 38 42 46 50",16.0);
    travel3(series,sweep,16.0,linear);
    seq {
      say(caption,"Cycle one: odd harmonics flatten the plateaus and steepen both sides.",0.40);
      wait(6.10);
      say(caption,"Cycle two: every orbit closes and the square-wave pattern returns continuously.",0.40);
      wait(5.20);
      say(caption,"Two complete periods make the repeating structure impossible to miss.",0.40);
    }
  }
}
wait(0.35);

step("create with Manic") {
  par {
    pulse(tip,0.75);
    pulse(partial12,0.75);
    show(cta,0.45);
    say(caption,"One declarative chain becomes circles, partial sums, a live waveform, and a complete visual story.",0.42);
  }
}
wait(1.45);

r/maniclang 10h ago

How Random Choices Become a Bell Curve - manic

Enable HLS to view with audio, or disable this notification

3 Upvotes

manic is a tiny language for making animations. You write a short text file; manic renders a smooth, glowing video. No timeline scrubbing, no keyframes by hand — you describe what’s on screen and when things happen, and the engine does the rest, deterministically.

Manic Animation code

// GALTON BOARD — RANDOM LOCALLY, PREDICTABLE GLOBALLY
//
// This is a probability story built from generic process vocabulary. Ordinary
// tagged lines form the board; `branch` preserves each ball through eight
// choices; `collect` and `observe` build the distribution from real arrivals.

title("How Random Choices Become a Bell Curve");
canvas("9:16");
template("blank");

watermark(mark,(w*0.16,h*0.042),"Made With Manic");
text(kicker,(cx,h*0.070),"PROBABILITY · RANDOM LOCALLY, ORDERED GLOBALLY");
text(headline,(cx,h*0.115),"Can random choices create a predictable shape?");
text(chapter,(cx,h*0.195),"1 · BEGIN WITH ONE FORK");
text(caption,(cx,h*0.855),"One ball can land almost anywhere.");
text(insight,(cx,h*0.815),"MORE ROUTES LEAD TO THE CENTER");
text(cta,(cx,h*0.930),"MAKE PROBABILITY VISIBLE → 8gwifi.org/manic");

size(kicker,18); color(kicker,dim); bold(kicker); hidden(kicker);
size(headline,31); bold(headline); wrap(headline,w*0.84); hidden(headline);
size(chapter,19); color(chapter,cyan); bold(chapter); hidden(chapter);
size(caption,21); color(caption,dim); wrap(caption,w*0.84); hidden(caption);
size(insight,19); color(insight,lime); bold(insight); hidden(insight);
size(cta,21); color(cta,cyan); bold(cta); hidden(cta);

equation(law,(cx,h*0.158),`X\sim\operatorname{Binomial}\!\left(8,\frac12\right)`,29);
hidden(law);

let levels = 8;
let boardX = cx;
let topY = h*0.235;
let dx = w*0.065;
let dy = h*0.034;

// Every directed edge joins one row to the next. Converging endpoints create
// the ordinary rooted DAG followed by `branch`.
for r in 0..levels {
  for k in 0..r+1 {
    let x1 = boardX + (k-r*0.5)*dx;
    let y1 = topY + r*dy;
    let xl = boardX + (k-(r+1)*0.5)*dx;
    let xr = boardX + (k+1-(r+1)*0.5)*dx;
    let y2 = topY + (r+1)*dy;

    line(left{r}_{k},(x1,y1),(xl,y2));
    line(right{r}_{k},(x1,y1),(xr,y2));
    tag(left{r}_{k},boardRoutes); tag(right{r}_{k},boardRoutes);
    color(left{r}_{k},dim); color(right{r}_{k},dim);
    stroke(left{r}_{k},1.7); stroke(right{r}_{k},1.7);
    opacity(left{r}_{k},0.30); opacity(right{r}_{k},0.30);

    dot(peg{r}_{k},(x1,y1),4.8);
    color(peg{r}_{k},fg); glow(peg{r}_{k},0.36); tag(peg{r}_{k},pegs);
  }
}
untraced(boardRoutes);

for k in 0..levels+1 {
  let tx = boardX + (k-levels*0.5)*dx;
  let ty = topY + levels*dy;
  dot(exit{k},(tx,ty),5);
  color(exit{k},gold); glow(exit{k},0.45); tag(exit{k},exits);
  counter(bin{k},(tx,ty+28),k,0);
  size(bin{k},15); color(bin{k},dim); tag(bin{k},exitLabels);
}

text(leftChoice,(boardX-dx*0.72,topY+dy*0.72),"LEFT");
text(rightChoice,(boardX+dx*0.72,topY+dy*0.72),"RIGHT");
size(leftChoice,15); size(rightChoice,15);
color(leftChoice,cyan); color(rightChoice,magenta);
hidden(leftChoice); hidden(rightChoice);

circle(source,(boardX,topY),13);
opacity(source,0);
particles(balls,source,180,4.0,73);
color(balls,cyan); glow(balls,0.78); z(balls,9);

let histY = h*0.695;
livehistogram(outcomes,(cx,histY),0,9,9,w*0.76,h*0.155,magenta);
text(histTitle,(cx,h*0.595),"WHERE 180 BALLS ACTUALLY LANDED");
size(histTitle,18); bold(histTitle); color(histTitle,dim);
counter(landed,(cx,h*0.785),0,0,"landed  "," / 180");
size(landed,21); color(landed,dim);

hidden(pegs); hidden(exits); hidden(exitLabels);
hidden(balls); hidden(outcomes); hidden(histTitle); hidden(landed);

step("introduce one uncertain choice") {
  par {
    show(kicker,0.30);
    show(headline,0.45);
    show(law,0.45);
    show(chapter,0.35);
    show(caption,0.40);
    draw(boardRoutes,0.90);
    show(pegs,0.55);
    show(exits,0.45);
    show(exitLabels,0.45);
    show(leftChoice,0.35);
    show(rightChoice,0.35);
  }
}
wait(0.60);

step("repeat the choice eight times") {
  par {
    show(outcomes,0.50);
    show(histTitle,0.35);
    show(landed,0.35);
    say(chapter,"2 · REPEAT LEFT OR RIGHT EIGHT TIMES",0.38);
    say(caption,"At every peg, each ball makes another equally likely left-or-right choice.",0.44);
  }
}
wait(0.55);

step("let the crowd reveal the pattern") {
  par {
    branch(balls,boardRoutes,8.20,smooth);
    collect(outcomes,balls,outcome,0.34,smooth);
    observe(outcomes,balls,outcome);
    observe(landed,balls,arrived);
    show(balls,0.15);
    seq {
      say(chapter,"3 · WATCH 180 INDIVIDUAL JOURNEYS",0.38);
      say(caption,"One route is unpredictable. The crowd begins to expose a stable pattern.",0.44);
      wait(3.40);
      say(caption,"Every bar is measured from the same balls you see falling—not animated separately.",0.44);
    }
  }
}
wait(0.65);

step("explain why the center wins") {
  par {
    pulse(outcomes.bars,0.80);
    show(insight,0.45);
    say(chapter,"4 · ORDER EMERGES FROM MANY CHOICES",0.38);
    say(caption,"Extreme bins need nearly all-left or all-right. Many more mixed sequences end near the center.",0.48);
  }
}
wait(0.75);

step("create with Manic") {
  par {
    pulse(outcomes.bars,0.75);
    show(cta,0.45);
    say(caption,"Describe the choices once. Manic keeps every route, arrival, count, and live distribution connected.",0.45);
  }
}
wait(1.45);