START ESCWYP MUSIC VIDEOS
This script rauzi can print nonperiodic substitution tilings. The substitution rules are from here.
And there are some random ones. The script can genereate random ones if you just give it a number.

#!/usr/bin/perl -w
use strict;

sub gen {
   my $substit = shift;
   my $num_subs = scalar(keys %$substit);
   my $num = shift;
   my $numbers = shift;
   my $greyscale = shift;
   if($num && $num > 0 && $num_subs > 1){
      #print "HOI %$substit UU $num_subs \n";
      my $a = "A"; 
      my $i = 0;
      while($num > 0){ 
         $i = 0;
         for my $s (keys %$substit){
            $a =~ s/$s/,$i,/g; 
            $i++;
         }
         $i = 0;
         for my $s (keys %$substit){
            $a =~ s/,$i,/$$substit{$s}/g;
            $i++;
         }
         $num--;
      } 
      if(defined($numbers) && $numbers == 1){
         my $n = 0.5;
         my $h = 2*$n;
         my $step = $h/($num_subs - 1);
         for my $i (sort keys %$substit){
            $a =~ s/$i/$n\n/g;
            $n -= $step;
         }
         print $a;
      }elsif(defined($greyscale) && $greyscale == 1){
         my @g = (' ', '.', '"', ':', '-', '~', '^', '_', '=', '>', '|', '<', '(', '/', ')', ']', '}', '{', '[', '+', '*', '#', '&', '?', '$', '%', '@');
         my $count = 0;
         for my $i (sort keys %$substit){
            $a =~ s/$i/$g[$count]/g;
            $count++;
            if($count > $#g){
               $count = $#g;
            }
         }
         print $a,"\n";
      }else{
         print $a,"\n";
      }
   }else{
      print "Noe Noe: $num_subs\n";
   }
}

sub genrule {
   my $size = shift;
   unless(defined($size) && $size =~ /^\d+$/ && $size > 0 && $size < 26){
      $size = 4;
   }
   my %b;
   my %stat;
   my @a = "A".."Z";
   for my $az (@a[0..$size]){
      my $i = int(rand(3));
      my $k;
      for my $j (0..$i){
         my $r = $a[int(rand($size+1))];
         push @{$stat{$r}}, $az;
         $k .= $r;
      }
      $b{$az} = $k;
   }
   for my $az (@a[0..$size]){
      if($stat{$az}){
         print "$az: @{$stat{$az}}\n";
      }else{
         print "$az: 0\n";
         delete $b{$az};
      }
   }
   return \%b;
}

{
   my $num, my $numbers;
   my $greyscale = 0;
   my $num_generated_rules = 4;
   my %tilings;
   my $s;
   my %rules;
   my $i = 1;
   #https://tilings.math.uni-bielefeld.de/substitution/a-ab--b-c--c-a/
   $tilings{"f".$i++} = "a-ab--b-c--c-ag";
   $rules{"a-ab--b-c--c-ag"} = {
      "A" => "AB",
      "B" => "C",
      "C" => "A",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/2-component-rauzy-fractal/
   $tilings{"f".$i++} = "2-component-rauzy-fractal";
   $rules{"2-component-rauzy-fractal"} = {
      "A" => "ACCB",
      "B" => "C",
      "C" => "A",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/central-fibonacci/
   $tilings{"f".$i++} = "central-fibonacci";
   $rules{"central-fibonacci"} = {
      "A" => "AC",
      "B" => "DB",
      "C" => "B",
      "D" => "A"
   };
   #https://tilings.math.uni-bielefeld.de/substitution/infinite-component-rauzy-fractal/
   $tilings{"f".$i++} = "infinite-component-rauzy-fractal";
   $rules{"infinite-component-rauzy-fractal"} = {
      "A" => "BACA",
      "B" => "AAC",
      "C" => "A",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/non-invertible-connected-rauzy-fractal/
   $tilings{"f".$i++} = "non-invertible-connected-rauzy-fractal";
   $rules{"non-invertible-connected-rauzy-fractal"} = {
      "A" => "BACB",
      "B" => "ABC",
      "C" => "BA",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/non-reducible-4-letter/
   $tilings{"f".$i++} = "non-reducible-4-letter";
   $rules{"non-reducible-4-letter"} = {
      "A" => "AAD",
      "B" => "CD",
      "C" => "CB",
      "D" => "AB"
   };
   #https://tilings.math.uni-bielefeld.de/substitution/period-doubling/
   $tilings{"f".$i++} = "period-doubling";
   $rules{"period-doubling"} = {
      "A" => "AB",
      "B" => "AA",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/smallest-pv/
   $tilings{"f".$i++} = "smallest-pv";
   $rules{"smallest-pv"} = {
      "A" => "BC",
      "B" => "C",
      "C" => "A",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/thue-morse/
   $tilings{"f".$i++} = "thue-morse";
   $rules{"thue-morse"} = {
      "A" => "AB",
      "B" => "BA",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/tribonacci/
   $tilings{"f".$i++} = "tribonacci";
   $rules{"tribonacci"} = {
      "A" => "AB",
      "B" => "AC",
      "C" => "A",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/kidney/
   $tilings{"f".$i++} = "kidney";
   $rules{"kidney"} = {
      "A" => "AB",
      "B" => "CB",
      "C" => "A",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/kolakoski-3-1-sym/
   $tilings{"f".$i++} = "kolakoski-3-1-sym";
   $rules{"kolakoski-3-1-sym"} = {
      "A" => "ACA",
      "B" => "A",
      "C" => "B",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/kolakoski-3-1-a/
   $tilings{"f".$i++} = "kolakoski-3-1-a";
   $rules{"kolakoski-3-1-a"} = {
      "A" => "BCC",
      "B" => "BA",
      "C" => "BC",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/kolakoski-3-1-b/
   $tilings{"f".$i++} = "kolakoski-3-1-b";
   $rules{"kolakoski-3-1-b"} = {
      "A" => "ABCC",
      "B" => "A",
      "C" => "BC",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/kolakoski-3-1/
   $tilings{"f".$i++} = "kolakoski-3-1";
   $rules{"kolakoski-3-1"} = {
      "A" => "ABC",
      "B" => "AB",
      "C" => "B",
   };
   #https://tilings.math.uni-bielefeld.de/substitution/fibonacci/
   $tilings{"f".$i++} = "fibonacci";
   $rules{"fibonacci"} = {
      "A" => "B",
      "B" => "AB",
   };
   #rnd
   $tilings{"f".$i++} = "rnd";
   $rules{"rnd"} = {
      "A" => "BE",
      "B" => "DAD",
      "C" => "F",
      "D" => "EA",
      "E" => "CBA",
      "F" => "A",
   };
   #rnd2
   $tilings{"f".$i++} = "rnd2";
   $rules{"rnd2"} = {
      "A" => "MWPA",
      "B" => "S",
      "C" => "UWLF",
      "D" => "ABY",
      "E" => "IR",
      "F" => "NDIA",
      "G" => "EZYC",
      "H" => "HSX",
      "I" => "CU",
      "J" => "HTOK",
      "K" => "ZW",
      "L" => "LTY",
      "M" => "GLHS",
      "N" => "MBLU",
      "O" => "O",
      "P" => "PQ",
      "Q" => "X",
      "R" => "YFA",
      "S" => "U",
      "T" => "L",
      "U" => "QD",
      "V" => "JVF",
      "W" => "GN",
      "X" => "LGFO",
      "Y" => "B",
      "Z" => "BFG",
   };
   #rnd3
   $tilings{"f".$i++} = "rnd3";
   $rules{"rnd3"} = {
       "A" => "DE",
       "C" => "CC",
       "D" => "DCD",
       "E" => "CC",
   };
   #rnd4
   $tilings{"f".$i++} = "rnd4";
   $rules{"rnd4"} = {
       "A" => "DE",
       "C" => "CC",
       "D" => "ACD",
       "E" => "DA",
   };
   #rnd5
   $tilings{"f".$i++} = "rnd5";
   $rules{"rnd5"} = {
       "A" => "BDC",
       "B" => "A",
       "C" => "EEE",
       "D" => "C",
       "E" => "CD",
   };
   #rnd6
   $tilings{"f".$i++} = "rnd6";
   $rules{"rnd6"} = {
       "A" => "BC",
       "B" => "ABB",
       "C" => "BAB",
   };
   #rnd7
   $tilings{"f".$i++} = "rnd7";
   $rules{"rnd7"} = {
       "A" => "BEB",
       "B" => "ADD",
       "D" => "B",
       "E" => "DE",
   };
    
   for my $a (@ARGV){
      if($a eq "n"){
         $numbers = 1;
      }elsif($a eq "g"){
         $greyscale = 1;
      }elsif($a =~ /^\d+$/){
         $num = $a;
      }else{
         if($tilings{$a}){
            #print "Using $tilings{$a}\n";
            $s = $rules{$tilings{$a}};
         }elsif($a =~ /^r=/){
            my %ru;
            my @zeug = split(',', substr($a,2));
            if($#zeug < 0){
               print "Error parsing rule $a. Please check.\n";
               exit 1;
            }
            for my $i (@zeug){
               my ($k, $v) = split(':', $i);
               if(defined($k) && $k =~ /^[A-Z]$/ && defined($v) && $v =~ /^[A-Z]+$/){
                  $ru{$k} = $v;
               }else{
                  print "Error parsing rule at string $i in rule $a. Please check.\n";
                  exit 1;
               }
            }
            $s = \%ru;
         }elsif($a =~ /^s\d+$/){
            $num_generated_rules = substr($a, 1);
         }
      }
   }
   if(! $num){
      print "\n   Please give at least a number greater 0.\n";
      print "\n   If you want, you can additionally give parameter n to get numbers\n";
      print "   as output. One on each line. Else you get letters in one line.\n";
      print "\n   If you want, you can additionally give parameter g to get ASCII art.\n";
      print "\n   If you want, you can additionally give a parameter f1 or f2 or ... (see below) to use different tilings.\n";
      print "\n   If you give only a number, a random rule will be generated and the result printed.\n";
      print "\n   For generated random rules the number of rules can be specified by providing s followed by a number.\n";
      print "   for example s9 will generate 9 rules. Maximum is 25.\n";
      print "\n   You can provide a rule by using for example r=A:EAD,C:EDD,D:A,E:CEC\n";
      print "\n   --- LIST OF RULES --- (give the f1 or f2 and so on parameter to select the rule)\n\n";
      for my $i (sort keys %rules){
         for my $k (keys %tilings){
            if($tilings{$k} eq $i){
               print "$k :: ";
               last;
            }
         }
         print "$i\t";
         for my $j (sort keys %{$rules{$i}}){
            print "$j -> ", $rules{$i}{$j}, "\t";
         }
         print "\n";
      }
      print "\n";
      exit 1;
   }else{
      if(! $s){
         print "No tiling selected. Will generate a random one:\n";
         print "---GENRULE---\n";
         $s = genrule($num_generated_rules);
         for my $j (sort keys %{$s}){
            print "$j -> ", $s->{$j}, "\t";
         }
         print "\n";
      }
      gen($s, $num, $numbers, $greyscale);
   }
}
START ESCWYP MUSIC VIDEOS