I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Dragon curve/D/QD

Library: QD
`module lsystem; import qd; interface LSystemI {  void setCallback(void delegate(int, int) cb);  void BaseStep(int depth);  int x(); int y();  int x(int); int y(int);} class LSystem(int ANGLES) : LSystemI {  int angle, _x, _y;  // define as properties so they can appear in the interface description  int x() { return _x; }  int y() { return _y; }  int x(int i) { return _x = i; }  int y(int i) { return _y = i; }   static assert(ANGLES == 4 || ANGLES == 8, "Unsupported number of angles!");  void right() { angle ++; if (angle == ANGLES) angle = 0; }  void left() { angle --; if (angle == -1) angle = ANGLES - 1; }   int stepsize;  void delegate(int, int) dgPoint;  void setCallback(typeof(dgPoint) cb) { dgPoint = cb; }   void step() {    static if (ANGLES == 4) {      //  0      // 3 1      //  2      const xshift = [0, 1, 0, -1];      const yshift = [-1, 0, 1, 0];    } else {      // 701      // 6 2      // 543      const xshift = [-1, 0, 1, 1, 1, 0, -1, -1];      const yshift = [-1, -1, -1, 0, 1, 1, 1, 0];    }    auto      newx = x + xshift[angle] * stepsize,      newy = y + yshift[angle] * stepsize;    dgPoint(newx, newy);    x = newx; y = newy;  }  abstract void BaseStep(int depth);} import tools.base;// compile-time functionstring LSysFunc(string syntax) {  auto namepos = syntax.ctFind("->");  assert(namepos != -1, "LSystem function definition syntax: Varname -> Replacement");  auto name = syntax[0 .. namepos].ctStrip(); syntax = syntax[namepos+2 .. \$].ctStrip();  auto endpos = syntax.ctFind("/");  string endact;  if (endpos != -1) {    endact = syntax[endpos+1 .. \$].ctStrip();    syntax = syntax[0 .. endpos].ctStrip();  }  if (endact.length && endact[\$-1] != ';') endact ~= ';'; // terminate statement  string res = "void "~name~"(int depth) { if (!depth) { "~endact~" return; } ";  foreach (ch; syntax) {    if (ch == '+') res ~= "right; ";    else if (ch == '-') res ~= "left; ";    else if (ch == 'F') res ~= "step; ";    else res ~= ch~"(depth - 1); ";  }  res ~= " }";  return res;} class Heighway : LSystem!(4) {  mixin(LSysFunc("X -> X+YF+"));  mixin(LSysFunc("Y -> -FX-Y"));  override void BaseStep(int depth) { X(depth); }} class Lévy : LSystem!(8) {  mixin(LSysFunc("X -> +X--X+ / step"));  override void BaseStep(int depth) { X(depth); }} void drawSystemFade(rgb start, rgb end, LSystemI ls, int depth) {  with (ls) {    int numPoints;    // acquire number of points    setCallback = (int x, int y) { numPoints ++; };    BaseStep(depth);    // draw with fade from red to green    int count;    setCallback = (int newx, int newy) {      auto color = start.blend(end, count * 1.0 / numPoints);      line(x, y, newx, newy, color);      count ++;    };    BaseStep(depth);  }} import tools.time: sleep;void main() {  screen(640, 480);  auto h = new Heighway;  h.x = screen.width * 5 / 8;  h.y = screen.height * 5 / 6;  h.stepsize = 1;  drawSystemFade(Red, Green, h, 16);  auto l = new Lévy;  l.x = screen.width * 1 / 6;  l.y = screen.height * 5 / 6;  l.stepsize = 1;  l.right;  drawSystemFade(Red, Green, l, 14);  while (true) { flip; events; }}`

Screenshot: [1]