Roll-n-rolling with the Piet ROLL command
Mr. Young and a few others questioned how QuickPiet‘s command worked …. and to be honest, at first I didn’t either. It turns out that the Piet ROLL command works fairly simply and is extremely powerful (according to npiet which I used as the basis for my testing).
The ROLL command pops two values off of the stack puts nothing back. The top value from the stack defines how many “turns” the roll executes. A turn will put the top value on the bottom and shift all other values “up” one place toward the top of the stack. The second value defines the “depth” of the roll or how many elements should be included in each turn starting at the top of the stack.
As the main Piet page suggests, a ROLL to a depth of X and a single turn will effectively bury the top of the stack down X spots. If that is as clear as mud, check out this image which shows two roll actions executed on a already populated stack.
[EDIT: Correction, the last roll in the above image shows a roll of depth 5, 2 turns. Not 3. My bad.)
I used the nPiet command line Win32 interpreter to test this and the following program shown with 1 pixel per codel** and again with 20x20 pixels per codel. nPiet is the most stable interpreter I have found and has some nice features like creating trace output images, tracing/logging statements, and automatically guessing codel sizes. Below is the 20x20 codel version and nPiet trace output.
$ ./npiet.exe -v -t ben/roll-big.gifinfo: verbose set to 1info: trace set to 1info: using file ben/roll-big.gifinfo: got gif image with 320 x 120 pixelinfo: codelsize guessed is 20 pixeltrace: step 0 (0,0/r,l nR -> 1,0/r,l dR):action: push, value 1trace: stack (1 values): 1trace: step 1 (1,0/r,l dR -> 2,0/r,l lR):action: push, value 2trace: stack (2 values): 2 1trace: step 2 (2,0/r,l lR -> 3,0/r,l nR):action: push, value 3trace: stack (3 values): 3 2 1trace: step 3 (3,0/r,l nR -> 4,0/r,l dR):action: push, value 4trace: stack (4 values): 4 3 2 1trace: step 4 (4,0/r,l dR -> 5,0/r,l lR):action: push, value 5trace: stack (5 values): 5 4 3 2 1trace: step 5 (5,0/r,l lR -> 6,0/r,l nR):action: push, value 3trace: stack (6 values): 3 5 4 3 2 1trace: step 6 (6,0/r,l nR -> 7,0/r,l dR):action: push, value 2trace: stack (7 values): 2 3 5 4 3 2 1trace: step 7 (7,0/r,l dR -> 8,0/r,l lB):action: rolltrace: stack (5 values): 3 5 4 2 1trace: step 8 (8,0/r,l lB -> 9,0/r,l nB):action: push, value 3trace: stack (6 values): 3 3 5 4 2 1trace: step 9 (9,0/r,l nB -> 10,0/r,l dB):action: push, value 2trace: stack (7 values): 2 3 3 5 4 2 1trace: step 10 (10,0/r,l dB -> 11,0/r,l lG):action: rolltrace: stack (5 values): 4 3 5 2 1trace: entering white block at 12,0 (like the perl interpreter would)...trace: step 11 (11,0/r,l lG -> 12,0/r,l WW):trace: special case: we at a white codel - continuingtrace: white cell(s) crossed - continuing with no command at 12,2...trace: step 12 (12,0/r,l WW -> 12,2/d,r lG):info: program end
** Since small Piet programs are TINY, instead of using 1×1 pixels as the unit block or codel, Piet interpreters should be able to use codels of larger sizes. Codels of larger sizes allow Piet programs to be easier to see and work with.