-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGrid.jack
More file actions
339 lines (308 loc) · 9.17 KB
/
Grid.jack
File metadata and controls
339 lines (308 loc) · 9.17 KB
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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
class Grid {
field int cellSize, width, height, area;
field Array cells;
constructor Grid new(int size) {
let cellSize = size;
let width = 512/cellSize;
let height = 256/cellSize;
let area = width * height;
//cell sizes under 4 result in cell count that overflows Jack int type
//perhaps this is an indication that the array structure for grid handling is stupid
//maybe grid needs to be stored as bits (individual ints for each bool is a bit silly after all) like Screen registers
let cells = Array.new(area);
return this;
}
//getters
method Array cells() {
return cells;
}
method Array cell(int i) {
return cells[i];
}
method int area() {
return area;
}
method int cellSize() {
return cellSize;
}
//gets position in 1D array of cells from (x,y)
method int getPos(int x, int y) {
return ((width * y) + x);
}
//gets (x,y) position from a 1D position
method Array getXY(int position) {
var Array coordinates;
var int x, y;
let coordinates = Array.new(2);
let x = MyMath.mod(position, width);
let y = position/width;
let coordinates[0] = x;
let coordinates[1] = y;
return coordinates;
}
//return 1D position of center cell
method int center() {
return getPos((width/2), (height/2));
}
//return (x,y) position of center cell
method Array centerXY() {
return getXY(center());
}
/* Cell fill value set methods */
//set cell to be filled
method void set(int x, int y) {
var int pos;
let pos = getPos(x, y);
let cells[pos] = true;
return;
}
method void setPos(int pos){
let cells[pos] = true;
return;
}
//set all cells to be filled (debugging/shortcut)
method void setAll() {
var int i;
var Array coord;
let i = 0;
while (i < area) {
let coord = getXY(i);
do set(coord[0], coord[1]);
let i = i + 1;
}
do coord.dispose();
return;
}
//set cell to be blank
method void unSet(int x, int y) {
var int pos;
let pos = getPos(x, y);
let cells[pos] = false;
return;
}
method void unSetPos(int pos) {
let cells[pos] = false;
return;
}
//set all cells blank
method void unSetAll() {
var int i;
var Array coord;
let i = 0;
while (i < area) {
let coord = getXY(i);
do unSet(coord[0], coord[1]);
let i = i + 1;
}
return;
}
//Draw grid based on current cell array
method void drawGrid() {
var int pos, i;
while (pos < area) {
do drawPos(pos);
let pos = pos + 1;
}
return;
}
method void drawXY(int x, int y) {
var int pos;
let pos = getPos(x, y);
do drawPos(pos);
return;
}
method void drawPos(int pos) {
var int x, y;
var Array coord;
if (pos > area) {
return;
}
let coord = getXY(pos);
let x = coord[0];
let y = coord[1];
do coord.dispose();
do Screen.setColor(cells[pos]);
do Screen.drawRectangle(x * cellSize, y * cellSize, ((x + 1) * cellSize) -1 , ((y + 1) * cellSize) -1);
return;
}
method void drawCell(int x, int y, bool fill) {
var int pos;
let pos = getPos(x, y);
//don't draw if cell goes past screen edge
if (pos > 512) {
return;
}
do Screen.setColor(cells[pos]);
do Screen.drawRectangle(x * cellSize, y * cellSize, ((x + 1) * cellSize) -1 , ((y + 1) * cellSize) -1);
return;
}
//methods which return 1D value corresponding to directions from current value; should be chainable
method int left(int position) {
return (((position/width) * width) + MyMath.mod((width + (position - 1)), width));
}
method int right(int position) {
return (((position/width) * width) + MyMath.mod((width + (position + 1)), width));
}
method int up(int position) {
return
(MyMath.mod(position, width) + ( // pos % width ==> column +
MyMath.mod( height + ((position/width) - 1), height) //(h + r-1) % h; (new row above)
* width)); // overall current column + new row * width of each row
}
method int down(int position) {
return
(MyMath.mod(position, width) + ( // pos % width ==> column +
MyMath.mod( height + ((position/width) + 1), height) //(h + r+1) % h; (new row below)
* width)); // overall current column + new row * width of each row
}
//array of neighbor positions (indexes in cells array) of a given position, clockwise from upper left
method Array neighbors(int position) {
var Array ret;
let ret = Array.new(8);
let ret[0] = left(up(position));
let ret[1] = up(position);
let ret[2] = right(up(position));
let ret[3] = right(position);
let ret[4] = right(down(position));
let ret[5] = down(position);
let ret[6] = left(down(position));
let ret[7] = left(position);
return ret;
}
//test method to see if neighbors works
method void setNeighbors(int pos) {
var int i;
var Array ns;
let ns = neighbors(pos);
while (i < 8) {
let cells[ns[i]] = true;
let i = i + 1;
}
do ns.dispose();
return;
}
//increase int value of all neighbors of input array by one (for neighborCount)
//set input array to cells to do to self, but intended for a counter array
method void incNeighbors(int pos, Array arr) {
var int i;
var Array ns;
let ns = neighbors(pos);
while (i < 8) {
let arr[ns[i]] = arr[ns[i]] + 1;
let i = i + 1;
}
do ns.dispose();
return;
}
//number of currently live neighbors a given position has
method int liveNeighbors(int pos) {
var int i, l;
var Array ns;
let l = 0;
let i = 0;
let ns = neighbors(pos);
while (i < 8) {
if (cells[ns[i]]) {
let l = l + 1;
}
let i = i + 1;
}
do ns.dispose();
return l;
}
//calculate list of live cells for next frame
method Array nextGen() {
var Array next;
var int i, lns;
let i = 0;
let next = Array.new(area);
while (i < area) {
let next[i] = cellLives(i);
let i = i + 1;
}
let i = 0;
// while (i < area) {
// do Output.printInt(next[i]);
// let i = i + 1;
// }
return next;
}
//potentially faster nextGen that uses alternative neighbor counting
method Array nextGen2() {
var Array next, counts;
var int i;
let counts = liveNeighborCounts();
let i = 0;
let next = Array.new(area);
while (i < area) {
let next[i] = false;
if ((counts[i] = 3) | ((counts[i] = 2) & cells[i])) {
let next[i] = true;
}
let i = i + 1;
}
do counts.dispose();
return next;
}
//returns whether a cell lives in the next generation
method Array cellLives(int pos) {
var int lns;
var bool lives;
let lns = liveNeighbors(pos);
let lives = false;
if (cells[pos]) {
//a live cell with 2 or 3 neighbors survives
if ((lns = 2) | (lns = 3)) {
let lives = true;
}
}
//dead cells with 3 neighbors gain life
else {
if (lns = 3) {
let lives = true;
}
}
return lives;
}
//builds neighborcount of all cells
method Array liveNeighborCounts() {
var int i;
var Array counter;
let counter = Array.new(area);
do MyLib.zeroArray(counter, area);
let i = 0;
//after the loop counter will hold every cells count of live neighbors
//this only runs neighbor methods on live cells instead of all cells
while (i < area) {
if (cells[i]) {
do incNeighbors(i, counter);
}
let i = i + 1;
}
//debug
// do MyLib.prIntArray(counter, area);
// do Sys.wait(5000);
return counter;
}
//replace current board with new one (just the array, doesn't redraw)
method void step() {
var Array temp;
var int i;
let i = 0;
let temp = nextGen2();
// do cells.dispose();
// let cells = temp;
while (i < area) {
let cells[i] = temp[i];
let i = i + 1;
}
do temp.dispose();
return;
}
//dispose grid object
method void dispose() {
do Memory.deAlloc(cells);
do Memory.deAlloc(this);
return;
}
}