#!/usr/bin perl # ASCII Tortise: # Tortise parses the string contained in $script, and moves # a pen around inside of a two-dimensional array according to # the directions in $script. # Whitespace has no significance between complete command # chunks within the tortise script. # Therefore you may break up complex designs into simpler # subdesigns, represented as seperate lines of script. # To make it a little easer, stick to my here-document # format for scripting. # The script commands are as follows: # U - Pen up (don't draw). # D - Pen down (draw). # N, NE, E, SE, S, SW, W, NW, followed by number of # repititions. In other words, E5 would draw an # eastward (rightward) line, five pixels long. # The repitition number is required for all directional # commands, even if there is only one repitition. # For the most part, anything that doesn't match the # described script format will just confuse the # parser. As mentioned before, whitespace is noncritical, # and the parser ignores it. The parser ignores a lot # of other things too, but play it safe by only using # whitespace as delimiters. Delimiters are not required. use strict; use warnings; my $script = <[-1, 0 ], "NE"=>[-1, 1 ], "E" =>[ 0, 1 ], "SE"=>[ 1, 1 ], "S" =>[ 1, 0 ], "SW"=>[ 1,-1 ], "W" =>[ 0,-1 ], "NW"=>[-1,-1 ] ); # %pen is cool. %pen holds the tortise's location, # his most recent direction command, his pen state, # how many moves he has to make before receiving his # next command. my %pen = ( "State" => "U", "Moves" => 0 , "Dir" => "" , "X" => 0 , "Y" => 0 ); # $dot and $blank just define what colors Tortise uses. my $dot = "#"; my $blank = " "; # Read the script, and pass commands on to Tortise. foreach ( $script =~ /[UD]|[NESW]+[0-9]+/g ) { if ( /U|D/ ) { $pen{State} = $_; if ( $pen{State} eq "D" ) { $screen[$pen{Y}][$pen{X}] = $dot; } } else { ( $pen{Dir}, $pen{Moves} ) = /([NSEW]+)([0-9]+)/; } # Keep moving until Tortise runs out of moves. # Then he sits and waits for the next command chunk. while ( $pen{Moves} ) { $pen{Y} += $delta{$pen{Dir}}[0]; $pen{X} += $delta{$pen{Dir}}[1]; if ( $pen{State} eq "D" ) { $screen[$pen{Y}][$pen{X}] = $dot; } $pen{Moves}--; } } # Now we can show the world Tortise's poop trail. for ( my $y = 0; $y < @screen; $y++ ) { if (!defined @{$screen[$y]}) { print "\n"; next; } for ( my $x = 0; $x < @{$screen[$y]}; $x++ ) { if ( $screen[$y][$x] ) { print $screen[$y][$x]; } else { print $blank; } } print "\n"; }