# Sandbox Visualization Module Emulator

The Zachtronics game TIS-100 contains a graphics display called the visualization module. I could try and explain the specs of this module, but the game's manual will do a better job:

(As you may have guessed, the motivation of this problem is to create a code golf challenge in which TIS-100 is the optimal language.)

Your job is to, in as few characters as possible, implement a program which will output the correct image for any valid input sequence. There are no requirements on what happens for an invalid input sequence. This can be a graphical window or console output. This includes strings of more than 1 command! If it has multiple -1s, multiple lines should be drawn.

# Test Cases:

Input:

3, 4, 4, 3, 2, 1, 0, 1, 2, 3, 4, -1

Output:



Input:

1, 1, 4, 4, -1, 8, 8, 4, 4, -1

Output:



Input:

5, 5, 4, -1, 5, 5, 0, -1

Output:



The simple TIS implementation is:

# TIS-100, 64 55 Bytes

-9 thanks to feersum

@1
MOV UP ANY
@5
MOV UP ANY
@9
MOV UP ANY
@10
MOV ANY ANY


An additional byte is added as a single character in the filename is relevant.

• I think you could golf all of the directions other than UP to ANY. Jun 26, 2017 at 3:30
• Some test cases of valid programs and their outputs would be nice. Jun 26, 2017 at 12:35
• What's the relavence of "Sandbox" in the title? Jun 27, 2017 at 9:10
• The "image console sandbox" contains a different size image console than the standard one. Jun 27, 2017 at 16:18
• Is creating an image file an acceptable form of output? Jun 30, 2017 at 19:45

# Ruby, 114 bytes

->h,g=[0]*792{h.chunk{|x|x<0&&p}.map{|z,(x,y,*r)|g[36*y+x,r.size]=r}
puts'P3 36 22 5',g.map{|i|i>3?'5 0 0':[i]*3}}


This function takes its input as an array of ints, and writes the resulting image to STDOUT in the human readable version of PPM format. For those unfamiliar, the PPM image format is an uncompressed image format that's, essentially, a whitespace separated list of RGB values.

More particularly, it begins with a short header of the format P3 W H M, where P3 is a magic number, W is the width of the image, H is the height of the image, and M is an int from 1 to 65536 representing the maximum possible value a color channel can have. For instance, if M = 255, then the RGB triplet (255, 255, 255) represents white. If M = 10, then (10, 10, 10) is white.

After the header, each pixel is described, row by row, by providing an RGB triplet for its color, with each value separated by spaces. It has the neat property that you can use it to represent an image as human readable text. For instance, a 3x1 pixel image containing a red pixel, a green pixel, and a blue pixel would be:

3 1 255
255 0 0   0 255 0   0 0 255


The precise whitespace used doesn't matter, so the above image is equivalent to, among many others:

3 1 255
255
0    0          0       255        0
0     0       255


### Explanation of Code

The reason all that was necessary was to explain why, when you run the program, you'll see output that looks like this:

P3 36 22 5
0
0
0
3
0 # And so on...


It's a PPM! And it's generated like this:

# Create an array g, full of 0s, of size (36*22) to hold the image
g = [0] * 792
# Break the input array into chunks, splitting on values < 0
h.chunk{|x|x < 0 && p}
# Use each chunk to fill the subarray of g beginning at its x and y coordinates
.map{|z,(x,y,*r)|g[36*y+x,r.size]=r}
puts'P3 36 22 5',
# ... and the colors, replacing each color id with itself repeated 3 times
# (for the various shades of gray) or '5 0 0', in the case of red, and
# separating each item with a newline.
g.map{|i|i>3?'5 0 0':[i]*3}


If you take this output and paste it into a text file, you'll be able to view it in any image viewer capable of opening PPMs.

Try it online!

.COM in 94B

00000000h: 68 00 B8 07 BF 09 01 31 DB B4 07 CD 21 3C 2D 72
00000010h: 41 6B DB 0A 2D 30 07 01 C3 BF 1E 01 EB EB 89 DD
00000020h: 83 06 1A 01 09 EB DD 69 ED A0 00 6B F3 02 EB F0
00000030h: 85 DB 7D 07 83 2E 1A 01 12 EB C9 83 FE 48 73 C4
00000040h: 81 FD C0 0D 73 BE FF B7 58 01 26 8F 02 83 C6 02
00000050h: EB B2 3C 20 72 02 FF E7 C3 00 88 77 FF 44


No extra optimize. Lots of code doing input

• input from stdin or <file.txt, output to screen, assuming 80*25 screen
– l4m2
Nov 27, 2017 at 19:48

# SmileBASIC 3, 163 bytes

Draws the image in the top-left corner of the graphic screen at 1px scale. DEF V A takes an int array A as input.

DEF V A
GCLS
@_
X=A[I]Y=A[I+1]FOR I=I+1TO LEN(A)-1C=A[I]IF.>C THEN I=I+1GOTO@_
IF X>35||Y>21GOTO@N
R=(3AND C)*85GPSET X,Y,RGB(R+255*!!(4AND C),R,R)@N
X=X+1NEXT
END


## Test Harness

The output is very small and other graphics leftover from the console etc. makes this function hard to test (in addition to the fact that it's a function and not a standalone program...) Write this (ungolfed) test harness below the function and run to verify.

ACLS
DATA 3,4,4,3,2,1,0,1,2,3,4,-1,-10

DIM SEQ%[0]
WHILE C%!=-10
PUSH SEQ%,C%
WEND

GPAGE 0,4
SPSET 0,0,0,36,22
SPSCALE 0,8,8

V SEQ%

REPEAT VSYNC UNTIL BUTTON(2)


Change the DATA statement to change the test sequence. The test sequence must end with -10 so the tester knows to stop reading it (DATA is used because SB lacks array literals.) This is done so you can use -1 in a sequence.

The program may end in an error; this is normal.

• Typo. i fixed it. Apr 16, 2019 at 20:26

# APL (Dyalog Unicode), 73 bytes

'P3 36 22 5'
+/{{⍵≠4:3/⍵⋄4 0 0}¨(-1⊃⍵)⊖(-0⊃⍵)⌽36 22↑1(≢2↓⍵)⍴2↓⍵}¨¯1(≠⊆⊢)⎕


Try it online!

A full program, which takes the indices as specified. Requires ⎕IO←0 for 0-indexing.

Outputs a netpbm image, like in the Ruby answer.

## Explanation

Netpbm header:
'P3 36 22 5'

Grid Generator:
+/{{⍵≠4:3/⍵⋄4 0 0}¨(-1⊃⍵)⊖(-0⊃⍵)⌽36 22↑1(≢2↓⍵)⍴2↓⍵}¨¯1(≠⊆⊢)⎕
⎕ Take the input
¯1(≠⊆⊢)  split on -1s
{                                                  }¨         do the following for each subarray i:
2↓⍵            Drop the 2 coordinates
1(≢2↓⍵)⍴                Convert i to a 1-row matrix
36 22↑                        create a 36x22 matrix with zeros, containing i
(-0⊃⍵)⌽                              rotate i to the required x coordinate
(-1⊃⍵)⊖                                     rotate i to the required y coordinate
{             }¨                                            apply the following to each element:
⍵≠4:3/⍵                                                    if it's not red, assign a shade of grey
⋄4 0 0                                              otherwise assign red
+/                                                              sum all the resulting matrices