-
Notifications
You must be signed in to change notification settings - Fork 2
/
ant.c
200 lines (167 loc) · 3.61 KB
/
ant.c
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FALSE 0
#define TRUE 1
#define LEFT(X) ( ((X)-1) & 3 )
#define RIGHT(X) ( ((X)+1) & 3 )
size_t *board = NULL;
size_t posX=0, posY=0;
size_t size = 0;
size_t dir = 0;
size_t stateLen = 0;
size_t *state;
const size_t MAX_STEPS = (size_t) 1000*1000*1000;
void freeBoard()
{
if (board) free(board);
if (state) free(state);
board = NULL;
state = NULL;
posX = posY = size = stateLen = dir = 0;
}
typedef enum { OK, NO_MEMORY, ANTSTRING_TOO_LONG, BORING_ANT } InitState;
InitState initBoard(size_t s, const char* stateString)
{
InitState ret = OK;
// clear possible existing old board
freeBoard();
// we support only 256 bits long ants!
// (only reason for this limitation is, that the PGM function
// is not working for larger state lengths)
if (strlen(stateString) >= 256)
{
ret = ANTSTRING_TOO_LONG;
goto cleanup;
}
// allocate board
board = calloc(s*s, sizeof(size_t));
if (board == NULL)
{
ret = NO_MEMORY;
goto cleanup;
}
posX = posY = s/2;
size = s;
// parse the state string, e.g. "1001"
stateLen = strlen(stateString);
state = calloc(stateLen, sizeof(size_t));
if (!state)
{
ret = NO_MEMORY;
goto cleanup;
}
size_t i;
for (i=0; i<stateLen; ++i)
state[i] = (stateString[i] == '0' ? 0 : 1);
// check for boring ant (i.e. only 0 and 1)
// i.e. check if there is at least one different bit
// as the first one (state[0])
int boring = TRUE;
for (i=1; i<stateLen; ++i)
if (state[0] != state[i])
{
boring = FALSE;
break;
}
if (boring == TRUE)
{
ret = BORING_ANT;
goto cleanup;
}
// everything fine, we have successfully initialized a
// non-boring ant!
return OK;
cleanup:
freeBoard();
return ret;
}
int step()
{
size_t tmp = board[posY*size + posX];
// increment current field on board by 1 (modulo stateLen)
board[posY*size + posX] = (board[posY*size + posX] + 1) % stateLen;
// turn in the corresponding direction
if (state[tmp])
dir = RIGHT(dir);
else
dir = LEFT(dir);
// do a step in the correct direction
switch (dir)
{
case 0: // north
if (posY > 0) posY--; else return FALSE;
break;
case 1: // east
if (posX < size-1) posX++; else return FALSE;
break;
case 2: // south
if (posY < size-1) posY++; else return FALSE;
break;
case 3: // west
if (posX > 0) posX--; else return FALSE;
break;
}
return TRUE;
}
int writePGM(char* filename)
{
FILE *f = fopen(filename, "w");
if (!f) return FALSE;
size_t k,l;
fprintf(f, "P5 %d %d %d ", size, size, stateLen);
for (k=0; k<size; ++k)
for (l=0; l<size; ++l)
fputc(board[l*size+k], f);
fclose(f);
return TRUE;
}
void usage()
{
printf("usage:\n");
printf(" ./ant 10 25\n");
printf(" Simulate Langton's Ant 10 on a quadratic board with size 25x25\n");
printf("\n");
printf(" ./ant 10\n");
printf(" Same as above, but with default board size of 500\n");
printf("\n");
}
int main(int argc, char* argv[])
{
if (argc != 2 && argc != 3)
{
usage();
return 1;
}
size_t s = 500;
if (argc == 3)
s = atoi(argv[2]);
switch (initBoard(s, argv[1]))
{
case NO_MEMORY:
fputs("Out of memory!\n", stderr);
return 2;
case ANTSTRING_TOO_LONG:
fputs("Antstring too long!\n", stderr);
return 3;
case BORING_ANT:
fputs("Boring ant!\n", stderr);
return 4;
}
size_t steps = 0;
//while (step() == TRUE);
while (step() == TRUE && steps < MAX_STEPS)
steps++;
if (writePGM("test.pgm") == FALSE)
{
printf("Error saving output\n");
return 5;
}
printf("state ");
size_t i;
for (i=0; i<stateLen; ++i)
putchar('0' + state[i]);
printf(", %d steps\n", steps);
freeBoard();
return 0;
}