This repository has been archived by the owner on Jan 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Assemble.py
206 lines (159 loc) · 5.44 KB
/
Assemble.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#from __future__ import print_function
from PIL import Image
#import Image
assemblyMode = ":assemble:complex"
functions = ["nop", "push", "pop", "add", "sub", "jump", "condjump", "ret",
"condkill", "transform", "inp", "dup", "mul", "emptykill",
"reverse", "rot", "over", "swap", "drop", "inpint", "waitfor",
"singlekill", "runifonly"]
'''
Read text file and return content as a list of lines containing lists of
tokens
'''
def readFileContent(fileName):
global assemblyMode
# Read in the assembly mode
assemblyModeCheck = open(fileName).readline().rstrip().lower()
if (assemblyModeCheck == ":assemble:simple"):
assemblyMode = ":assemble:simple"
lines = []
file = open(fileName, "r")
# Read line by line
for line in file:
# Remove start whitespace and lines starting with REM (remarks)
if( line.lstrip()[:3] != "rem" and len(line.lstrip()) > 1 and line.lstrip()[0] != ":"):
# Split remaining lines into tokens (add these to tokens list)
lines.append(line.split())
# Return tokens
return lines
# Write the code to the image
def writeCompiledImg(inputImgName, outputImgName, lines):
# Use the PIL Image library to open the input image
im = Image.open(inputImgName)
pix = im.load()
# Variables used by :assemble:simple
imageWidth, imageHeight = im.size
nextX, nextY = 0, 0
flagDir = 0 # east
# Get the number of tokens
numberLines = len(lines)
# For the number of tokens
for index in range(numberLines):
if (assemblyMode == ":assemble:complex"):
x, y, r, g, b = pixFromLineComplex(lines[index])
if (assemblyMode == ":assemble:simple"):
nextX, nextY, flagDir, x, y, r, g, b = pixFromLineSimple(lines[index],
nextX, nextY, imageWidth,
flagDir)
#print (x, y, r, g, b)
pix[int(x), int(y)] = (int(r), int(g), int(b))
# Save the compiled image
im.save(outputImgName, quality = 95)
return 0
def pixFromLineComplex(line):
# Operates on a stack
#functions = {0: nop, 1: push, 2: pop, 3: add, 4: sub,
# 5: jump, 6: condjump, 7: ret, 8: condkill,
# 9: transform, 10: inp, 11: dup, 12: mul,
# 13: emptykill, 14: reverse, 15: rot, 16: over,
# 17: swap, 18: drop, 19: inpint, 20: waitfor,
# 21: singlekill, 22:runifonly}
# 1111 = WSEN
'''
Syntax should be in the form: x y func data exit_dir
eg 0 0 push 32 s&e (pix[0,0] = (1, 32, 6) - push a space onto the stack
then load instruction to the south and the east [0,1] and [1,0])
'''
x = line[0]
y = line[1]
r = 0
g = line[3]
b = 0
# Convert an function to its int
for function in range (len(functions)):
if line[2].lower() == functions[function]:
r = function
# If data contains : then convert char to ord
if line[3][0] == ":":
g = ord(line[3][1])
# Convert a direction(s) to its int
direction = line[4].lower()
for char in direction:
if 'w' == char:
b = b | 8
if 's' == char:
b = b | 4
if 'e' == char:
b = b | 2
if 'n' == char:
b = b | 1
return x, y, r, g, b
def pixFromLineSimple(line, nextX, nextY, imageWidth, flagDir):
# Operates on a stack
#functions = {0: nop, 1: push, 2: pop, 3: add, 4: sub,
# 5: jump, 6: condjump, 7: ret, 8: condkill,
# 9: transform, 10: inp, 11: dup, 12: mul,
# 13: emptykill, 14: reverse, 15: rot, 16: over,
# 17: swap, 18: drop, 19: inpint, 20: waitfor,
# 21: singlekill, 22:runifonly}
# 1111 = WSEN
# Additional function end
'''
Syntax should be in the form: func data
eg push 32 push a space onto the stack
then load the next instruction)
'''
x = nextX
y = nextY
r = 0
g = line[1]
b = 0
isEnd = False
if line[0] == 'end':
r = 0
isEnd = True
# Convert an function to its int
for function in functions:
if line[0].lower() == function:
r = function
# If data contains : then convert char to ord
if line[1][0] == ":":
g = ord(line[1][1])
if (not isEnd):
if (flagDir == 0):
if(x < imageWidth):
b = 2 # east
nextX = x + 1
else:
b = 4 # south
nextY = y + 1
flagDir = 1
if (flagDir == 1):
if (x > 0):
b = 8 # west
nextX = x - 1
else:
b = 4 # south
nextY = y + 1
flagDir = 0
else:
b = 0
return nextX, nextY, flagDir, x, y, r, g, b
def cli():
print("Assemble or Quit? " +
"(A, q)" )
choice = input(">")[0].lower()
# Quit application
if choice == "q":
return True
# Assemble
print("Type in the path to the code file")
codeFile = input(">")
print("Type in the path to the output image")
outputImgName = input(">")
lines = readFileContent(codeFile)
writeCompiledImg("blank.png", outputImgName, lines)
# Run the CLI while the user has not finished
finished = False
while not finished:
finished = cli()