Skip to content

Instantly share code, notes, and snippets.

@dloscutoff
Last active September 22, 2016 07:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dloscutoff/13212291a16e074c8366402e5b1dd082 to your computer and use it in GitHub Desktop.
Save dloscutoff/13212291a16e074c8366402e5b1dd082 to your computer and use it in GitHub Desktop.
Beginnings of a language for programming ASCII art
class CanvasError(Exception):
pass
class Canvas:
def __init__(self, grid=None, default=" "):
if grid:
self.grid = grid
else:
self.grid = [[]]
self.offsetx = 0
self.offsety = 0
self.default = default
self.ptrx = 0
self.ptry = 0
self.direction = (1,0)
def __getitem__(self, coords):
x, y = coords
x += self.offsetx
y += self.offsety
if 0 <= y < len(self.grid) and 0 <= x < len(self.grid[0]):
return self.grid[y][x]
else:
return None
def __setitem__(self, coords, value):
if value is not None and (type(value) is not str or len(value) != 1):
raise CanvasError("Canvas values must be single char or None, not "
"%r" % value)
x, y = coords
x += self.offsetx
y += self.offsety
while y < 0:
# Add row to the top of the grid
row = [None] * len(self.grid[0])
self.grid = [row] + self.grid
self.offsety += 1
y += 1
while y >= len(self.grid):
# Add row to the bottom of the grid
row = [None] * len(self.grid[0])
self.grid += [row]
while x < 0:
# Add column to the left side of the grid
self.grid = [[None] + row for row in self.grid]
self.offsetx += 1
x += 1
while x >= len(self.grid[0]):
# Add row to the right side of the grid
self.grid = [row + [None] for row in self.grid]
self.grid[y][x] = value
def __str__(self):
return "\n".join("".join(c if c else "\0" for c in row)
.rstrip("\0").replace("\0", self.default)
for row in self.grid)
def changeDirection(self, dirCode="."):
if dirCode == "↑":
self.direction = (0,-1)
elif dirCode == "↓":
self.direction = (0,1)
elif dirCode == "→":
self.direction = (1,0)
elif dirCode == "←":
self.direction = (-1,0)
elif dirCode == "↖":
self.direction = (-1,-1)
elif dirCode == "↗":
self.direction = (1,-1)
elif dirCode == "↘":
self.direction = (1,1)
elif dirCode == "↙":
self.direction = (-1,1)
else:
# Unrecognized direction code; for now, ignore silently
pass
return self
def put(self, char):
self[self.ptrx, self.ptry] = char
return self
### Functions that implement language commands start here ###
def printString(self, string, direction=None):
for char in string:
self.put(char).move(direction)
return self
def multiPrint(self, string, directions):
replacements = {ord(key): value
for key, value in [("+", "←↑→↓"),
("x", "↖↗↘↙"),
("*", "←↑→↓↖↗↘↙")]}
directions = directions.translate(replacements)
for direction in directions:
savedPtr = self.ptrx, self.ptry
self.printString(string, direction)
self.ptrx, self.ptry = savedPtr
return self
def move(self, direction=None, length=1):
if direction is not None:
self.changeDirection(direction)
self.ptrx += self.direction[0] * length
self.ptry += self.direction[1] * length
return self
def turn(self, direction):
pass
def jump(self, dx, dy, relative=True):
if relative:
self.ptrx += dx
self.ptry += dy
else:
self.ptrx = dx
self.ptry = dy
return self
def readCanvasChar(self, x=0, y=0, relative=True):
if relative:
result = self[x+self.ptrx, y+self.ptry]
else:
result = self[x, y]
return result
def readCanvasString(self, direction=None, length=1):
result = ""
for i in range(length):
char = self.readCanvasChar()
# TBD: use the canvas default character for empty spaces, or some
# other sentinel value (probably not in the printable ASCII range)?
result += self.default if char is None else char
self.move(direction)
return result
if __name__ == "__main__":
c=Canvas()
c.multiPrint("ascii", "x")
c.jump(5, -1)
c.printString("art", "↓")
print(c)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment