Skip to content

Instantly share code, notes, and snippets.

@hornc
Last active January 10, 2023 23:36
Show Gist options
  • Save hornc/7860821f7642e58c9bf217d663ea655e to your computer and use it in GitHub Desktop.
Save hornc/7860821f7642e58c9bf217d663ea655e to your computer and use it in GitHub Desktop.
G_arD^EN CorUtY@rD esolang interpreter
#!/usr/bin/env python
"""
Esoteric programming language interpreter for
G_arD^EN CorUtY@rD
https://esolangs.org/wiki/G_arD%5EEN_CorUtY@rD
Interpreter by Salpynx, 2022.
"""
import sys
import re
from time import sleep
NAME = 'G_arD^EN CorUtY@rD'
ARROWS = '>v<^'
PAUSE = 0.1 # pause time between frames in seconds
DEBUG = False
LIMIT = 3000
PRE = '\033['
RST = PRE + '0m'
CLR = '\033c'
WHITE = '1;37m'
BROWN = '0;33m'
SOIL = BROWN
FENCE = WHITE
LCYAN = '1;36m'
RED = '1;31m'
GREEN = '0;32m'
LG = '1;32m'
BLUE = '0;34m'
PATH = '1;33m'
LGREY = '1;37m'
GREY = '1;30m'
MAGENTA = '1;35m'
COLORS = {
'x': FENCE,
'X': FENCE,
'K': FENCE,
'L': LCYAN,
'#': RED,
'~': GREEN,
'=': SOIL,
'+': BLUE,
'-': PATH,
':': GREY,
'E': GREY,
'T': WHITE,
'_': RED,
'>': LG,
'<': LG,
'^': LG,
'v': LG,
'@': MAGENTA,
}
def color(s):
"""Return an ANSI colored string based on first symbol."""
c = COLORS.get(s[0], '0m')
return PRE + c + s + RST
class GardenCourtyard:
def __init__(self, source):
self.source = source
self.width = len(source[0])
self.height = min([n for n,v in enumerate(source) if '_' in v])
self.ip = self.findfirstchair()
self.dir = 0 # 0: right (down, left, up)
self.soil = self.source[0][:self.source[0].find('K')].replace('x', '0').replace('X', '1')
self.cq = '' # Command queue
self.oq = '' # Output queue
self.output = ''
def findfirstchair(self):
for y, line in enumerate(self.source):
for x, c in enumerate(line):
if c == 'L':
return [x, y]
def show(self):
print(CLR + PRE + MAGENTA + NAME + RST)
for j, line in enumerate(self.source):
if j == 0: # soil / datastring / fence
if len(self.soil) < self.width:
line = self.soil + 'K' + line[len(self.soil) + 1:]
else:
line = self.soil
line = line.replace('0', 'x').replace('1', 'X')
if j == self.ip[1]:
x = self.ip[0]
c = line[x]
line = line[:x] + '@' + line[x+1:]
runs = re.findall(r'((.)\2*)', line)
for run in runs:
block, symbol = run
print(color(block), end='')
print()
def process(self, c):
if c == '~':
self.cq += '0'
self.dir = 1
elif c == '+':
self.cq += '1'
self.dir = 0
elif c == '-':
if self.soil[-1] == '0':
self.dir = 0
else:
self.dir = 1
elif c == ':':
self.cq += c
self.dir = 1
elif c == '=':
cc = self.cq[0]
self.cq = self.cq[1:]
if cc == ':':
self.soil = self.soil[1:]
else:
if self.soil[0] == '1':
self.soil = self.soil + cc
elif c == 'E':
self.oq += self.soil[0]
self.soil = self.soil[1:]
if len(self.oq) == 8:
self.output += chr(int(self.oq, 2))
self.oq = ''
#self.dir = 0
elif c in ARROWS:
self.dir = ARROWS.find(c)
d = self.dir
x, y = self.ip
if d & 1:
y += 1 - (d - 1)
else:
x += 1 - d
self.ip = [x, y]
def run(self):
running = True
i = 0
while running:
x, y = self.ip
if y == self.height:
break
self.show()
c = self.source[y][x]
self.process(c)
if DEBUG:
print('Current command:', c)
print(self.ip, self.dir)
print('DATA STRING:', self.soil)
print(i)
print('CQ:', self.cq)
print('OQ:', self.oq)
print(f'>:{self.output}')
sleep(PAUSE)
i += 1
if i > LIMIT:
break
if __name__ == '__main__':
sourcefile = sys.argv[1]
source = []
width = 0
with open(sourcefile, 'r') as f:
for line in f.readlines():
line = line.strip("\n")
width = len(line)
source.append(line)
gc = GardenCourtyard(source)
gc.run()
@hornc
Copy link
Author

hornc commented Aug 3, 2022

I've figured out what is wrong with the reversed output. I mis-interpreted K as ignorable padding. It actually ends the initial datastring. That makes more sense and I know what to fix. Won't happen today though.

UPDATE: FIXED K:
I've also made the first fence row update to represent the current datastring / 'soil' as the program runs to indicate the current internal state.
The 'soil' modifies the 'fence' -- not sure that makes sense, but it's more to look at.
The command queue is not represented on screen, that might be nice, but all the current examples never get beyong one item in the command queue anyway.

@hornc
Copy link
Author

hornc commented Jan 10, 2023

Moved to a repo, now part of: https://github.com/hornc/esointerpreters

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment