11 static int64_t orig
[LIMIT
];
25 static int debug_level
= -1;
27 debug_raw(int level
, const char *fmt
, ...) {
30 debug_level
= atoi(getenv("DEBUG") ?: "0");
31 if (debug_level
>= level
) {
33 vfprintf(stderr
, fmt
, ap
);
37 #define debug(...) debug_raw(1, __VA_ARGS__)
40 dump(struct state
*s
) {
43 debug(" state of id=%d: pc=%d base=%d in=%s%" PRId64
" out=%s%" PRId64
44 " steps=%d\n", s
->id
, s
->pc
, s
->base
,
45 s
->has_in
? "" : "!", s
->in
, s
->has_out
? "" : "!", s
->out
, s
->steps
);
46 for (int i
= 0; i
< len
; i
++)
47 debug_raw(3, "%" PRId64
",", s
->a
[i
]);
51 static void __attribute__((noreturn
))
52 crash(struct state
*s
, const char *msg
) {
53 printf("invalid program id=%d, pc=%d: %s\n", s
->id
, s
->pc
, msg
);
58 get(struct state
*s
, int param
) {
59 int64_t op
= s
->a
[s
->pc
];
64 if (op
> 99999 || op
< 0)
65 crash(s
, "unexpected opcode");
66 if (s
->pc
+ param
> LIMIT
)
67 crash(s
, "memory too short for opcode");
68 value
= s
->a
[s
->pc
+ param
];
71 mode
= (op
/ scale
) % 10;
72 debug_raw(3, "get op=%d mode=%d value=%d\n", op
, mode
, value
);
75 if (value
> LIMIT
|| value
< 0)
76 crash(s
, "in position mode, param beyond memory");
82 if (value
> LIMIT
|| value
< 0)
83 crash(s
, "in relative mode, param beyond memory");
86 crash(s
, "unexpected mode");
91 put(struct state
*s
, int param
, int64_t value
) {
92 int64_t op
= s
->a
[s
->pc
];
97 if (op
> 99999 || op
< 0)
98 crash(s
, "unexpected opcode");
99 if (s
->pc
+ param
> LIMIT
)
100 crash(s
, "memory too short for opcode");
101 offset
= s
->a
[s
->pc
+ param
];
104 mode
= (op
/ scale
) % 10;
105 debug_raw(3, "put op=%d mode=%d value=%d offset=%d\n", op
, mode
, value
, offset
);
108 if (offset
> LIMIT
|| offset
< 0)
109 crash(s
, "in position mode, param beyond memory");
110 s
->a
[offset
] = value
;
114 if (offset
> LIMIT
|| offset
< 0)
115 crash(s
, "in relative mode, param beyond memory");
116 s
->a
[offset
] = value
;
119 crash(s
, "unexpected mode");
124 init(struct state
*s
, int64_t in
) {
125 memset(s
, 0, sizeof *s
);
126 memcpy(s
->a
, orig
, len
* sizeof orig
[0]);
132 /* Returns -1 for stalled on input, 0 for done, 1 for stalled on output */
134 run(struct state
*s
) {
138 debug_raw(2, "executing id=%d step=%d pc=%d base=%" PRId64
" %" PRId64
139 ",%" PRId64
",%" PRId64
",%" PRId64
"\n", s
->id
,
140 s
->steps
++, s
->pc
, s
->base
, s
->a
[s
->pc
], s
->a
[s
->pc
+1],
141 s
->a
[s
->pc
+2], s
->a
[s
->pc
+3]);
142 if (!(s
->steps
% 10000))
143 debug(" steps=%d\n", s
->steps
);
144 if (s
->pc
> LIMIT
|| s
->pc
< 0)
145 crash(s
, "program ran out of bounds");
146 switch (s
->a
[s
->pc
] % 100) {
148 put(s
, 3, get(s
, 1) + get(s
, 2));
152 put(s
, 3, get(s
, 1) * get(s
, 2));
157 debug_raw(2, "id=%d stalling for input\n", s
->id
);
167 debug_raw(2, "id=%d stalling for output\n", s
->id
);
190 put(s
, 3, get(s
, 1) < get(s
, 2));
194 put(s
, 3, get(s
, 1) == get(s
, 2));
198 s
->base
+= get(s
, 1);
199 if (s
->base
< 0 || s
->base
> LIMIT
)
200 crash(s
, "relative base out of bounds");
204 debug_raw(2, "id=%d halting\n", s
->id
);
207 crash(s
, "unexpected opcode");
222 static enum tile grid
[GRID
][GRID
];
223 static int maxx
, maxy
;
225 static int padx
, ballx
;
227 static struct state s
;
233 printf("score %d\n", score
);
234 for (y
= 0; y
<= maxy
; y
++) {
235 for (x
= 0; x
<= maxx
; x
++)
236 putchar(" #x_@"[grid
[y
][x
]]);
242 main(int argc
, char **argv
) {
243 int count
= 0, blocks
= 0;
250 if (!(stdin
= freopen(argv
[1], "r", stdin
))) {
256 begin
= atoi(argv
[2]);
258 while (scanf("%" SCNd64
"%*[,\n]", &orig
[len
]) == 1)
259 if (len
++ > LIMIT
- 3) {
260 printf("recompile with larger LIMIT\n");
263 printf("Read %u slots\n", len
);
272 crash(&s
, "unexpected completion");
274 s
.in
= (ballx
> padx
) - (ballx
< padx
);
276 printf("tilting joystick %" PRId64
"\n", s
.in
);
280 if (s
.out
< -1 || s
.out
> GRID
)
281 crash(&s
, "recompile with larger GRID");
288 crash(&s
, "unexpected completion/input request");
290 crash(&s
, "missing expected output y");
291 if (s
.out
< 0 || s
.out
> GRID
)
292 crash(&s
, "recompile with larger GRID");
295 crash(&s
, "invalid y for displaying score");
303 crash(&s
, "missing expected output tile");
305 if (s
.out
< EMPTY
|| s
.out
> BALL
)
306 crash(&s
, "unexpected output tile");
307 if (s
.out
== BLOCK
&& grid
[y
][x
] != BLOCK
)
309 else if (s
.out
!= BLOCK
&& grid
[y
][x
] == BLOCK
) {
310 debug("hit a block\n");
316 else if (s
.out
== PADDLE
)
318 debug("setting %d,%d to '%c'\n", x
, y
, " #X_@"[s
.out
]);
321 debug("setting score to %d\n", score
);
327 printf("program done: %d tuples, %d.%d grid, %d blocks, final score %d\n",
328 count
, maxx
, maxy
, blocks
, score
);