A hybrid language of Turtle Graphics' Logo and Conway's Game Of Life. Read all about GoLo on my blog.
I've previously played around in creating both Turtle Graphics and Conway's Game of Life.
Lately, I've been exploring creating procedurally generated game levels for a roguelike or dungeon crawler style game.
One technique I've been playing with is using different rule sets of cellular automaton to create different types of level layouts.
I usually ended with a map that I wished I could apply some basic logic to in order to clean up some stray pixels.
Thus, GoLo was born! GoLo is a play on Logo and GoL (Game of Life). The language works around the idea of moving a cursor around a grid and being able to paint the space under the cursor with a color or clear it. I've added variables, functions, logic conditionals and a stack, as well as some basic utilities, to provide a full programming environment.
I've created a couple basic functions you can leverage by default:
FILL is a function that randomly fills the grid's bits with a 50% chance. PUSH N FILL will fill the grid with an N% chance of being painted (0-100).
BORDER draws a border around the perimeter.
LIFE performs, by default, 10 iterations of Conway's Game of Life, leveraging the sub-functions _SCAN (analyzing neighbors) and _STEP (applying the 23/3 rule set). Use PUSH N LIFE to control N iterations.
PAINTALL leverages _PAINT to fill in the contiguous empty spaces of the grid will random colors.
Conway's Game of Life Example:
HOME RT 2 BIT DN 1 BIT DN 1 BIT LT 1 BIT LT 1 UP 1 BIT LIFE
Simple Random Automaton Level Example:
FILL PUSH 1 LIFE BORDER PAINTALL
TO STEPA [HM RP MAXLOC [ SET N POP IFEQ 4 N [ BIT ] [ NULL ] RT 1 ]]
TO STEPB [HM RP MAXLOC [ SET N POP IFGT N 5 [ BIT ] [ NULL ] RT 1 ]]
TO STEPC [HM RP MAXLOC [ SET N POP IFGT N 3 [ NULL ] [ ZBIT ] RT 1 ]]
TO CLEANUP [HM RP MAXLOC [ IFBITS 111101111 [PEN 000 BIT][NULL] IFBITS 000010000 [ZBIT][NULL] IFBITS X01X10XXX [ ZBIT ] [ NULL ] IFBITS XXXX10X01 [ ZBIT ] [ NULL ] IFBITS 10X01XXXX [ ZBIT ] [ NULL ] IFBITS XXX01X10X [ ZBIT ] [ NULL ] RT 1 ]]
TO _PAINTB [IFBITC FILLC [ BIT ADD AREA 1 IFTOP [ NULL ] [ SAVE UP 1 IFBITC FILLC [ PUSH LOC ] [ NULL ] RESTORE ] IFLEFT [ NULL ] [ SAVE LT 1 IFBITC FILLC [ PUSH LOC ] [ NULL ] RESTORE ] IFRIGHT [ NULL ] [ SAVE RT 1 IFBITC FILLC [ PUSH LOC ] [ NULL ] RESTORE ] IFBOTTOM [ NULL ] [ SAVE DN 1 IFBITC FILLC [ PUSH LOC ] [ NULL ] RESTORE ] ] [ NULL ] IFNZ STACKSIZE [ SET LOC POP IFGT MAXLOC LOC [ _PAINTB ] [ NULL ] ] [ NULL ]]
TO PAINTBIG [HM RP MAXLOC [ IFZBIT [ SET FILLC BITC SET AREA 0 PEN RANDC SAVE PUSH MAXLOC _PAINTB RESTORE SET #BITC AREA] [ NULL ] RT 1 ]]
TO CAVE [RESIZE 40 PEN 000 PUSH 26 FILL BORDER RP 3 [ _SCAN STEPA ] _SCAN STEPB _SCAN STEPC CLEANUP BORDER PAINTBIG CONNECT BLEACH PEN 555 GRID ]
TO BLEACH [ HM PEN FFF RP MAXLOC [ IFBITC 000 [NULL][BIT] RT 1 ] ]
TO CONNECT
[
HOME
SET LOCS MAXLOC
RP MAXLOC
[
SUB LOCS 1
PUSH LOCS
]
RP MAXLOC
[
IFNZ STACKSIZE
[
SET LOC RANDPOP
IFGTE 50 RAND
[
CHECK_RIGHT
CHECK_DOWN
]
[
CHECK_DOWN
CHECK_RIGHT
]
]
[
NULL
]
]
]
TO CHECK_RIGHT
[
IFBITS XXXX21XXX
[
SAVE
SET DIST W
SUB DIST X
SUB DIST 1
SET COLOR_A BITC
SET VALID 1
SET COUNT 0
RP DIST
[
IFNZ VALID
[
RT 1
ADD COUNT 1
IFBITS XXX12XXXX
[
IFBITC COLOR_A
[
SET VALID 0
]
[
SET COLOR_B BITC
IFGT #COLOR_A #COLOR_B
[
ADD #COLOR_A #COLOR_B
SET #COLOR_B 0
PEN COLOR_A
SET FILLC COLOR_B
SAVE
PUSH MAXLOC
_PAINTB
RESTORE
RP COUNT
[
LT 1
BIT
]
]
[
ADD #COLOR_B #COLOR_A
SET #COLOR_A 0
PEN COLOR_B
SET FILLC COLOR_A
RP COUNT
[
BIT
LT 1
]
SAVE
PUSH MAXLOC
_PAINTB
RESTORE
]
SET VALID 0
]
]
[
NULL
]
]
[
NULL
]
]
RESTORE
]
[
NULL
]
]
TO CHECK_DOWN
[
IFBITS XXXX2XX1X
[
SAVE
SET DIST H
SUB DIST Y
SUB DIST 1
SET COLOR_A BITC
SET VALID 1
SET COUNT 0
RP DIST
[
IFNZ VALID
[
DN 1
ADD COUNT 1
IFBITS X1XX2XXXX
[
IFBITC COLOR_A
[
SET VALID 0
]
[
SET COLOR_B BITC
IFGT #COLOR_A #COLOR_B
[
ADD #COLOR_A #COLOR_B
SET #COLOR_B 0
PEN COLOR_A
SET FILLC COLOR_B
SAVE
PUSH MAXLOC
_PAINTB
RESTORE
RP COUNT
[
UP 1
BIT
]
]
[
ADD #COLOR_B #COLOR_A
SET #COLOR_A 0
PEN COLOR_B
SET FILLC COLOR_A
RP COUNT
[
BIT
UP 1
]
SAVE
PUSH MAXLOC
_PAINTB
RESTORE
]
SET VALID 0
]
]
[
NULL
]
]
[
NULL
]
]
RESTORE
]
[
NULL
]
]
CAVE
CLEAR : Clears screen (sets PC = '000000FF') (or use CL)HOME : Home (sets LOC = 0) (or use HM)RESIZE value : Resizes bit grid to val width/height (default: 40)GRID : Overlays a grid of current pen color (slows drawing)ZGRID : Hides the grid (default)PEN color : Sets pen color (HTML color names, RGB hex as RGB or RRGGBB, RGBA hex as RGBA or RRGGBBAA)RGB value value value : Sets pen color R G B (integers 0-255)RGBA value value value value : Sets pen color and alpha R G B A (integers 0-255)RGBX value value value : Sets pen color hexidecimal R G B (00-FF)RGBAX value value value value : Sets pen color and alpha hexidecimal R G B A (00-FF)UP value : Moves cursor up value amountDOWN value : Moves cursor down value amount (or use DN)RIGHT value : Moves cursor to right value amount (wraps down) (or use RT)LEFT value : Moves cursor to left value amount (wraps up) (or use LT)BIT : Sets Bit at current LOC to current pen colorZBIT : Clears Bit current LOC to '00000000'SAVE : Saves current Position and Pen Color (pushes onto LIFO state stack)RESTORE : Restores saved Position and Pen Color (pops from LIFO state stack)NULL : Do NothingREPEAT value [...] : Repeats [...] # times (or use RP)TO name [...] : Creates a GoLo function (call the name, or click on the button)SET var value : var = value (variables can use A-Z, 0-9 and _ in their name. Use #var as a variable pointer)INC var : var = var + 1ADD var value : var = var + valueDEC var : var = var - 1SUB var value : var = var - valueMULT var value : var = var * valueDIV var value : var = var / value (rounded integer)MOD var value : var = var % valuePERCENT var value : var = var * value / 100 (rounded integer)PERCENTA var value : var = var * value / 255 (rounded integer)PUSH value : Pushes value onto LIFO variable stackPOP : Pops value from LIFO variable stack (eg SET X POP)RANDPOP : Randomly pops one value from variable stack (eg SET X RANDPOP)RAND : Random number 0-100RANDB : Random byte 0-255RANDL : Random Location Value (0 to max location on screen)RANDC : Random Color (not dark) RRGGBB in hex (666666-FFFFFF)PENC : Pen color in hex RRGGBBAABITC : Color at current LOCBITR : Red channel of color at current LOC (0-255)BITG : Green channel of color at current LOC (0-255)BITB : Blue channel of color at current LOC (0-255)BITA : Alpha channel of color at current LOC (0-255)BITRX : Red channel of color hex at current LOC (00-FF)BITGX : Green channel of color hex at current LOC (00-FF)BITBX : Blue channel of color hex at current LOC (00-FF)BITAX : Alpha channel of color hex at current LOC (00-FF)BITS : Bit Pattern of neighbors and current LOC (9 digits read top-left to lower-right: 0='00000000', 1='000000FF', 2-9=detected colors)NBS : Count of non-empty neighbors 0-8STACKSIZE : Size of variable stackSTATESIZE : Number of saved statesMAXLOC : W * H, note is off screenIFBIT [...][...] : If bit at current location is colored then runs first, otherwise secondIFZBIT [...][...] : If bit at current location is empty then runs first, otherwise secondIFBITC color [...][...] : If bit at current location = color then runs first, otherwise secondIFBITS pattern [...][...] : If bit pattern at current location then runs first, otherwise second (9 digits read top-left to lower-right: 0='00000000', 1='000000FF', 2-9=detected colors, 'C'=any color, 'X'=ignore)IFTOP [...][...] : If LOC is at top of screen then runs first, otherwise secondIFBOTTOM [...][...] : If LOC is at bottom of screen then runs first, otherwise secondIFLEFT [...][...] : If LOC is on left edge of screen then runs first, otherwise secondIFRIGHT [...][...] : If LOC is on right edge of screen then runs first, otherwise secondIFON [...][...] : If LOC is on screen then runs first, otherwise secondIFNZ value [...][...] : If value != 0 then runs first, otherwise secondIFEQ value1 value2 [...][...] : If value1 = value2 then runs first, otherwise secondIFGT value1 value2 [...][...] : If value1 > value2 then runs first, otherwise secondIFGTE value1 value2 [...][...] : If value1 >= value2 then runs first, otherwise second