comparison interps/fukyorbrane/fukyorbrane.c @ 996:859f9b4339e6

<Gregor> tar xf egobot.tar.xz
author HackBot
date Sun, 09 Dec 2012 19:30:08 +0000
parents
children
comparison
equal deleted inserted replaced
995:6883f5911eb7 996:859f9b4339e6
1 /*
2 * Copyright (c) 2005, 2009 Gregor Richards
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #ifndef MAX_PROG_LEN
29 #define MAX_PROG_LEN 32256
30 #endif
31
32 /* program data */
33 int *progs[2];
34 /* a command is "spent" if it's a fork that's already forked
35 * perhaps later commits will be spendable too */
36 unsigned char *progSpent[2];
37 /* uncommitted program data */
38 int *progMods[2];
39 /* lengths of each program */
40 int proglens[2];
41 /* owner of each process */
42 unsigned char *procs;
43 /* defected processes */
44 unsigned char *procdef;
45 /* program pointer for each proc */
46 int *procpptrs;
47 /* data pointer for each proc */
48 int *procdptrs;
49 /* process count */
50 int procc;
51
52 /* verbose? */
53 unsigned char verbose = 0;
54 /* output turn numbers? */
55 unsigned char outt = 0;
56
57 #define CMD_NOP 0
58 #define CMD_INC 1
59 #define CMD_LFT 2
60 #define CMD_RHT 3
61 #define CMD_INP 4
62 #define CMD_OUT 5
63 #define CMD_COM 6 /* commit */
64 #define CMD_UNC 7 /* uncommit */
65 #define CMD_L1O 8 /* L1 = loop1 = [] = value at pointer != 0 */
66 #define CMD_L1C 9
67 #define CMD_L2O 10 /* L2 = loop2 = {} = enemy program pointer is NOT at data pointer */
68 #define CMD_L2C 11
69 #define CMD_L3O 12 /* L3 = loop3 = :; = fork */
70 #define CMD_L3C 13
71 #define CMD_BOM 14
72 #define CMD_OKB 15 /* "OK" bomb - for killing your own process, doesn't declare enemy winner */
73 #define CMD_DEF 16 /* defect - edit your own program */
74 #define CMD_CNT 17
75
76 /* not actually commands, just here to tell us when we're in comments */
77 #define CMD_CIN 18
78 #define CMD_COT 19
79
80 int cmdToInt(char cmd);
81 char intToCmd(int cmd);
82 char intToCmd(int cmd);
83 int execcmd(int procnum, unsigned char procowner, int *pptr, int *dptr);
84
85 int main(int argc, char **argv)
86 {
87 FILE *fps[2];
88 int prog, inc, proc;
89 long turnn;
90
91 if (argc <= 2) {
92 fprintf(stderr, "\n\nCopyright (c) 2005, 2009 Gregor Richards\n\n"
93 "Permission is hereby granted, free of charge, to any person obtaining a copy of\n"
94 "this software and associated documentation files (the \"Software\"), to deal in\n"
95 "the Software without restriction, including without limitation the rights to\n"
96 "use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n"
97 "of the Software, and to permit persons to whom the Software is furnished to do\n"
98 "so, subject to the following conditions:\n\n"
99 "The above copyright notice and this permission notice shall be included in all\n"
100 "copies or substantial portions of the Software.\n\n"
101 "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
102 "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n"
103 "FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n"
104 "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n"
105 "IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n"
106 "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n");
107
108 fprintf(stderr, "Use: %s <program 1> <program 2> [options]\n"
109 " Options:\n"
110 " v: verbose mode\n"
111 " t: output turn numbers\n", argv[0]);
112 return 1;
113 }
114
115 if (argv[3]) {
116 for (proc = 0; argv[3][proc]; proc++) {
117 switch (argv[3][proc]) {
118 case 'v':
119 verbose = 1;
120 break;
121
122 case 't':
123 outt = 1;
124 break;
125 }
126 }
127 }
128
129 progs[0] = (int *) malloc(MAX_PROG_LEN * sizeof(int));
130 progs[1] = (int *) malloc(MAX_PROG_LEN * sizeof(int));
131 progSpent[0] = (unsigned char *) malloc(MAX_PROG_LEN * sizeof(unsigned char));
132 progSpent[1] = (unsigned char *) malloc(MAX_PROG_LEN * sizeof(unsigned char));
133 progMods[0] = (int *) malloc(MAX_PROG_LEN * sizeof(int));
134 progMods[1] = (int *) malloc(MAX_PROG_LEN * sizeof(int));
135 procs = (unsigned char *) malloc(1024 * sizeof(unsigned char));
136 procdef = (unsigned char *) malloc(1024 * sizeof(unsigned char));
137 procpptrs = (int *) malloc(1024 * sizeof(int));
138 procdptrs = (int *) malloc(1024 * sizeof(int));
139
140 fps[0] = fopen(argv[1], "r");
141 if (!fps[0]) {
142 perror(argv[1]);
143 return 3;
144 }
145
146 fps[1] = fopen(argv[2], "r");
147 if (!fps[1]) {
148 perror(argv[2]);
149 return 3;
150 }
151
152 for (prog = 0; prog <= 1; prog++) {
153 int incomment = 0;
154 proglens[prog] = 0;
155
156 while (!feof(fps[prog])) {
157 inc = cmdToInt(getc(fps[prog]));
158 if (inc == CMD_CIN) {
159 incomment = 1;
160 inc = -1;
161 }
162 if (inc == CMD_COT) {
163 incomment = 0;
164 inc = -1;
165 }
166
167 if (inc != -1 && !incomment) {
168 progs[prog][proglens[prog]] = inc;
169 progMods[prog][proglens[prog]] = inc;
170 progSpent[prog][proglens[prog]] = 0;
171 proglens[prog]++;
172 }
173 }
174 }
175
176 /* the programs must be of equal length to be fair */
177 while (proglens[0] < proglens[1]) {
178 progs[0][proglens[0]] = CMD_NOP;
179 progMods[0][proglens[0]] = CMD_NOP;
180 progSpent[0][proglens[0]] = 0;
181 proglens[0]++;
182 }
183 while (proglens[1] < proglens[0]) {
184 progs[1][proglens[1]] = CMD_NOP;
185 progMods[1][proglens[1]] = CMD_NOP;
186 progSpent[1][proglens[1]] = 0;
187 proglens[1]++;
188 }
189
190 /* now bootstrap the processes ... */
191 procs[0] = 1;
192 procdef[0] = 0;
193 procpptrs[0] = 0;
194 procdptrs[0] = 0;
195 procs[1] = 2;
196 procdef[1] = 0;
197 procpptrs[1] = 0;
198 procdptrs[1] = 0;
199 procc = 2;
200
201 for (turnn = 0; turnn < 10000000; turnn++) {
202 int winner;
203 unsigned char alive[2];
204
205 /* output the board if we're verbose */
206 if (verbose) {
207 int vproc;
208 char *outline;
209 int outll;
210
211 outline = (char *) malloc(MAX_PROG_LEN * sizeof(char));
212
213 for (proc = 0; proc < 2; proc++) {
214
215 fprintf(stderr, "==============================\n");
216 fprintf(stderr, "%s\n\t", argv[proc + 1]);
217 for (inc = 0; inc < proglens[0]; inc++) {
218 fprintf(stderr, "%c", intToCmd(progs[proc][inc]));
219 }
220 fprintf(stderr, "\n");
221
222 for (vproc = 0; vproc < procc; vproc++) {
223 outll = 0;
224 memset(outline, ' ', 32256);
225
226 if (procs[vproc] == proc + 1) {
227 outline[procpptrs[vproc]] = 'p';
228 if (procpptrs[vproc] >= outll)
229 outll = procpptrs[vproc] + 1;
230
231 if (procdef[vproc]) {
232 if (outline[procdptrs[vproc]] == 'p') {
233 outline[procdptrs[vproc]] = 'b';
234 } else {
235 outline[procdptrs[vproc]] = 'd';
236 }
237 if (procdptrs[vproc] >= outll)
238 outll = procdptrs[vproc] + 1;
239 }
240 } else if (procs[vproc] != 0 && !procdef[vproc]) {
241 outline[procdptrs[vproc]] = 'd';
242 if (procdptrs[vproc] >= outll)
243 outll = procdptrs[vproc] + 1;
244 }
245
246 outline[outll] = '\0';
247 fprintf(stderr, "%d:\t%s\n", vproc, outline);
248 }
249 }
250
251 fprintf(stderr, "==============================\n\n");
252
253 free(outline);
254 } else if (outt) {
255 fprintf(stderr, "%ld \r", turnn);
256 }
257
258 for (proc = 0; proc < procc; proc++) {
259 if (procs[proc]) {
260 if ((winner = execcmd(proc, procs[proc], procpptrs + proc, procdptrs + proc))) {
261 if (outt) fprintf(stderr, "\n");
262 printf("%s wins!\n", argv[winner]);
263 return winner;
264 }
265 }
266 }
267
268 // see if anybody accidentally quit themselves
269 alive[0] = 0;
270 alive[1] = 0;
271 for (proc = 0; proc < procc; proc++) {
272 if (procs[proc]) {
273 alive[procs[proc]-1] = 1;
274 }
275 }
276 if (!alive[0]) {
277 if (outt) fprintf(stderr, "\n");
278 printf("%s wins!\n", argv[2]);
279 return 2;
280 }
281 if (!alive[1]) {
282 if (outt) fprintf(stderr, "\n");
283 printf("%s wins!\n", argv[1]);
284 return 1;
285 }
286 }
287
288 printf("It's a draw due to 10,000,000 clocks with no winner!\n");
289
290 return 0;
291 }
292
293 int cmdToInt(char cmd)
294 {
295 switch (cmd) {
296 case '%':
297 return CMD_NOP;
298 case '+':
299 return CMD_INC;
300 case '<':
301 return CMD_LFT;
302 case '>':
303 return CMD_RHT;
304 case ',':
305 return CMD_INP;
306 case '.':
307 return CMD_OUT;
308 case '!':
309 return CMD_COM;
310 case '?':
311 return CMD_UNC;
312 case '[':
313 return CMD_L1O;
314 case ']':
315 return CMD_L1C;
316 case '{':
317 return CMD_L2O;
318 case '}':
319 return CMD_L2C;
320 case ':':
321 return CMD_L3O;
322 case ';':
323 return CMD_L3C;
324 case '*':
325 return CMD_OKB;
326 case '@':
327 return CMD_DEF;
328
329 case '(':
330 return CMD_CIN;
331 case ')':
332 return CMD_COT;
333 }
334 return -1;
335 }
336
337 char intToCmd(int cmd)
338 {
339 switch (cmd) {
340 case CMD_NOP:
341 return '%';
342 case CMD_INC:
343 return '+';
344 case CMD_LFT:
345 return '<';
346 case CMD_RHT:
347 return '>';
348 case CMD_INP:
349 return ',';
350 case CMD_OUT:
351 return '.';
352 case CMD_COM:
353 return '!';
354 case CMD_UNC:
355 return '?';
356 case CMD_L1O:
357 return '[';
358 case CMD_L1C:
359 return ']';
360 case CMD_L2O:
361 return '{';
362 case CMD_L2C:
363 return '}';
364 case CMD_L3O:
365 return ':';
366 case CMD_L3C:
367 return ';';
368 case CMD_BOM:
369 return 'B';
370 case CMD_OKB:
371 return '*';
372 case CMD_DEF:
373 return '@';
374 }
375 return ' ';
376 }
377
378 int execcmd(int procnum, unsigned char procowner, int *pptr, int *dptr)
379 {
380 int i, fnd, origpptr;
381 int procedits;
382 int depth;
383
384 if (procdef[procnum]) {
385 procedits = procowner - 1;
386 } else {
387 procedits = !(procowner - 1);
388 }
389
390 switch (progs[procowner-1][*pptr]) {
391 case CMD_INC:
392 progMods[procedits][*dptr]++;
393 if (progMods[procedits][*dptr] >= CMD_CNT) progMods[procedits][*dptr] = 0;
394 break;
395
396 case CMD_LFT:
397 (*dptr)--;
398 if (*dptr < 0) *dptr = 0;
399 break;
400 case CMD_RHT:
401 (*dptr)++;
402 if (*dptr >= proglens[0]) *dptr -= proglens[0];
403 break;
404
405 case CMD_INP:
406 case CMD_OUT:
407 /* no implementation, but reserved! */
408 break;
409
410 case CMD_COM:
411 progs[procedits][*dptr] = progMods[procedits][*dptr];
412 // if you commit a defect, you defect!
413 if (progs[procedits][*dptr] == CMD_DEF) {
414 procdef[procnum] = !procdef[procnum];
415 *dptr = *pptr;
416 }
417 /* perhaps make commit only work once? */
418 break;
419
420 case CMD_UNC:
421 progMods[procedits][*dptr] = progs[procedits][*dptr];
422 break;
423
424 case CMD_L1O:
425 if (!progMods[procedits][*dptr]) {
426 /* find the counterpart */
427 depth = 0;
428 origpptr = *pptr;
429 (*pptr)++;
430 while (progs[procowner-1][*pptr] != CMD_L1C ||
431 depth != 0) {
432 if (progs[procowner-1][*pptr] == CMD_L1O) depth++;
433 if (progs[procowner-1][*pptr] == CMD_L1C) depth--;
434 (*pptr)++;
435
436 if (*pptr >= proglens[0]) {
437 /* our loop-end was evicerated! */
438 *pptr = origpptr;
439 break;
440 }
441 }
442 }
443 break;
444 case CMD_L1C:
445 /* find the counterpart */
446 depth = 0;
447 origpptr = *pptr;
448 (*pptr)--;
449 if (*pptr < 0) *pptr = 0;
450 while (progs[procowner-1][*pptr] != CMD_L1O ||
451 depth != 0) {
452 if (progs[procowner-1][*pptr] == CMD_L1O) depth++;
453 if (progs[procowner-1][*pptr] == CMD_L1C) depth--;
454 (*pptr)--;
455
456 if (*pptr < 0) {
457 /* our loop-end was evicerated! */
458 *pptr = origpptr + 1;
459 break;
460 }
461 }
462 (*pptr)--;
463 break;
464
465 case CMD_L2O:
466 /* loop through every proc */
467 fnd = 0;
468 for (i = 0; i < procc; i++) {
469 if (procs[i] && procs[i] != procowner) {
470 if (procpptrs[i] == *dptr) {
471 /* got em */
472 fnd = 1;
473 }
474 }
475 }
476 if (fnd) {
477 /* find the counterpart */
478 depth = 0;
479 origpptr = *pptr;
480 (*pptr)++;
481 while (progs[procowner-1][*pptr] != CMD_L2C ||
482 depth != 0) {
483 if (progs[procowner-1][*pptr] == CMD_L2O) depth++;
484 if (progs[procowner-1][*pptr] == CMD_L2C) depth--;
485 (*pptr)++;
486
487 if (*pptr >= proglens[0]) {
488 /* our loop-end was evicerated! */
489 *pptr = origpptr;
490 break;
491 }
492 }
493 }
494 break;
495 case CMD_L2C:
496 /* find the counterpart */
497 depth = 0;
498 origpptr = *pptr;
499 (*pptr)--;
500 if (*pptr < 0) *pptr = 0;
501 while (progs[procowner-1][*pptr] != CMD_L2O ||
502 depth != 0) {
503 if (progs[procowner-1][*pptr] == CMD_L2O) depth++;
504 if (progs[procowner-1][*pptr] == CMD_L2C) depth--;
505 (*pptr)--;
506
507 if (*pptr < 0) {
508 /* our loop-end was evicerated! */
509 *pptr = origpptr + 1;
510 break;
511 }
512 }
513 (*pptr)--;
514 break;
515
516 case CMD_L3O:
517 /* start a new proc! */
518 if (!progSpent[procnum][*pptr]) {
519 procs[procc] = procowner;
520 procpptrs[procc] = *pptr + 1;
521 procdptrs[procc] = *dptr;
522 procdef[procc] = procdef[procnum];
523
524 procc++;
525
526 progSpent[procnum][*pptr] = 1;
527 }
528
529 /* now this proc needs to skip to the end */
530 /* find the counterpart */
531 depth = 0;
532 origpptr = *pptr;
533 (*pptr)++;
534 while (progs[procowner-1][*pptr] != CMD_L3C ||
535 depth != 0) {
536 if (progs[procowner-1][*pptr] == CMD_L3O) depth++;
537 if (progs[procowner-1][*pptr] == CMD_L3C) depth--;
538 (*pptr)++;
539
540 if (*pptr >= proglens[0]) {
541 /* our loop-end was evicerated! */
542 *pptr = origpptr;
543 break;
544 }
545 }
546
547 break;
548 case CMD_L3C:
549 /* we must be in the child proc, skip to the beginning of this proc
550 (really, you shouldn't let a proc do this, you should bomb it */
551 /* find the counterpart */
552 depth = 0;
553 origpptr = *pptr;
554 (*pptr)--;
555 if (*pptr < 0) *pptr = 0;
556 while (progs[procowner-1][*pptr] != CMD_L3O ||
557 depth != 0) {
558 if (progs[procowner-1][*pptr] == CMD_L3O) depth++;
559 if (progs[procowner-1][*pptr] == CMD_L3C) depth--;
560 (*pptr)--;
561
562 if (*pptr < 0) {
563 /* our loop-end was evicerated! */
564 *pptr = origpptr + 1;
565 break;
566 }
567 }
568 break;
569
570 case CMD_BOM:
571 /* boom! */
572 return ((!(procowner-1)) + 1);
573
574 case CMD_OKB:
575 /* sorta boom! */
576 if (procnum < 2) {
577 procs[procnum] = 0;
578 } else {
579 /* only bomb if it's the last command of a thread */
580 if (progs[procowner-1][(*pptr)+1] == CMD_L3C) {
581 procs[procnum] = 0;
582 }
583 }
584 break;
585
586 case CMD_DEF:
587 /* defect - edit your own program */
588 procdef[procnum] = !procdef[procnum];
589 *dptr = *pptr;
590 break;
591 }
592
593 (*pptr)++;
594 if (*pptr >= proglens[0]) *pptr = 0;
595
596 return 0;
597 }