Created
June 21, 2015 20:01
-
-
Save GreenLightning/35e5872b53c9eac92533 to your computer and use it in GitHub Desktop.
TIS-100 SCATTER PLOT VIEWER SPECIFICATION
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- For anyone who liked the SCATTER PLOT VIEWER puzzle included in some of the early | |
-- access builds of TIS-100... | |
-- INSTALLATION: Copy everything in this file. Open TIS-100. Go to the SPECIFICATION | |
-- EDITOR. Click on IMPORT SPECIFICATION FROM CLIPBOARD. Done! | |
-- The function get_name() should return a single string that is the name of the puzzle. | |
-- | |
function get_name() | |
return "SCATTER PLOT VIEWER" | |
end | |
-- The function get_description() should return an array of strings, where each string is | |
-- a line of description for the puzzle. The text you return from get_description() will | |
-- be automatically formatted and wrapped to fit inside the puzzle information box. | |
-- | |
function get_description() | |
return { | |
"READ AN X VALUE FROM IN", | |
"READ A Y VALUE FROM IN", | |
"READ A SPRITE VALUE FROM IN", | |
"IF SPRITE = 1, DRAW A WHITE PLUS", | |
"IF SPRITE = 2, DRAW A RED X" | |
} | |
end | |
-- The function get_streams() should return an array of streams. Each stream is described | |
-- by an array with exactly four values: a STREAM_* value, a name, a position, and an array | |
-- of integer values between -999 and 999 inclusive. | |
-- | |
-- STREAM_INPUT: An input stream containing up to 39 numerical values. | |
-- STREAM_OUTPUT: An output stream containing up to 39 numerical values. | |
-- STREAM_IMAGE: An image output stream, containing exactly 30*18 numerical values between 0 | |
-- and 4, representing the full set of "pixels" for the target image. | |
-- | |
-- NOTE: Arrays in Lua are implemented as tables (dictionaries) with integer keys that start | |
-- at 1 by convention. The sample code below creates an input array of 39 random values | |
-- and an output array that doubles all of the input values. | |
-- | |
-- NOTE: To generate random values you should use math.random(). However, you SHOULD NOT seed | |
-- the random number generator with a new seed value, as that is how TIS-100 ensures that | |
-- the first test run is consistent for all users, and thus something that allows for the | |
-- comparison of cycle scores. | |
-- | |
-- NOTE: Position values for streams should be between 0 and 3, which correspond to the far | |
-- left and far right of the TIS-100 segment grid. Input streams will be automatically | |
-- placed on the top, while output and image streams will be placed on the bottom. | |
-- | |
function get_streams() | |
local image = create_blank_image() | |
local generate_x = create_horizontal_generator() | |
local generate_y = create_vertical_generator() | |
local input = {} | |
for i = 1,39,3 do -- 39 values allow us to provide 13 inputs consisting of 3 values | |
local x = generate_x() | |
local y = generate_y() | |
local sprite = math.random(2); | |
input[i + 0] = x | |
input[i + 1] = y | |
input[i + 2] = sprite | |
if sprite == 1 then | |
-- white plus | |
set_pixel(image, x, y-1, 3) | |
set_pixel(image, x-1, y, 3) | |
set_pixel(image, x, y, 3) | |
set_pixel(image, x+1, y, 3) | |
set_pixel(image, x, y+1, 3) | |
elseif sprite == 2 then | |
-- red x | |
set_pixel(image, x-1, y-1, 4) | |
set_pixel(image, x+1, y-1, 4) | |
set_pixel(image, x, y, 4) | |
set_pixel(image, x-1, y+1, 4) | |
set_pixel(image, x+1, y+1, 4) | |
end | |
end | |
return { | |
{ STREAM_INPUT, "IN", 1, input }, | |
{ STREAM_IMAGE, "IMAGE", 2, image }, | |
} | |
end | |
-- Returns a properly sized image array (30 * 18 pixel) containing all zeros (black). | |
-- | |
function create_blank_image() | |
local image = {} | |
for i = 1,30*18 do | |
image[i] = 0 | |
end | |
return image | |
end | |
-- Sets the pixel at x and y to the specified color value | |
-- | |
function set_pixel(image, x, y, color) | |
-- add 1 because array indices start with 1 in lua | |
image[1 + 30*y + x] = color | |
end | |
-- The function get_layout() should return an array of exactly 12 TILE_* values, which | |
-- describe the layout and type of tiles found in the puzzle. | |
-- | |
-- TILE_COMPUTE: A basic execution node (node type T21). | |
-- TILE_MEMORY: A stack memory node (node type T30). | |
-- TILE_DAMAGED: A damaged execution node, which acts as an obstacle. | |
-- | |
function get_layout() | |
return { | |
TILE_COMPUTE, TILE_COMPUTE, TILE_COMPUTE, TILE_DAMAGED, | |
TILE_COMPUTE, TILE_COMPUTE, TILE_COMPUTE, TILE_COMPUTE, | |
TILE_COMPUTE, TILE_COMPUTE, TILE_COMPUTE, TILE_COMPUTE, | |
} | |
end | |
-- These functions create simple pseudo-random number generators | |
-- for the x and y values. | |
-- They are linear congruential generators and their parameters | |
-- are carefully chosen so that they have a full period, i. e. | |
-- they generate all possible numbers in a pseudo-random order | |
-- before starting over. | |
-- The resulting plots look a lot nicer than those created with | |
-- the lua random number generator because they are not | |
-- clustered as much. | |
-- | |
-- The generators work by applying the following formula | |
-- repeatedly to the current seed (start) value: | |
-- | |
-- s_1 = (a * s_0 + c) mod m | |
-- | |
-- The ordering generated by these generators is hard-coded | |
-- in form of the three parameters a, c and m, however the | |
-- seed value is generated using math.random() which | |
-- results in enough variety. | |
-- The modulus value m determines the maximum number the | |
-- generator can output and also the maximum length of the | |
-- period. | |
-- The parameters a and c need to be adjusted to m to ensure | |
-- that the generator has a full period for all possible | |
-- seed values. | |
-- | |
-- The generators generate values between 0 (inclusive) and | |
-- m (exclusive), however the generator functions add 1 | |
-- to the result before returning it so that the horizontal | |
-- generator generates values between 1 and 28 and the | |
-- vertical generator generates values between 1 and 16. | |
-- The first and last indices (0 and 29 and 0 and 17 for | |
-- the 30x18 pixel large display) are not generated so | |
-- that all pixels of the resulting plot fall inside the | |
-- bounds of the display. | |
-- | |
-- See also: https://en.wikipedia.org/wiki/Linear_congruential_generator | |
function create_horizontal_generator() | |
local m = 28 | |
local c = 23 | |
local a = 29 | |
local s = math.random(m) - 1 | |
return function () | |
s = next(s, a, c, m) | |
return s + 1 | |
end | |
end | |
function create_vertical_generator() | |
local m = 16 | |
local c = 11 | |
local a = 9 | |
local s = math.random(m) - 1 | |
return function () | |
s = next(s, a, c, m) | |
return s + 1 | |
end | |
end | |
function next(value, multiplier, increment, modulus) | |
return (multiplier * value + increment) % modulus | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment