Talk:Wireworld/C: Difference between revisions

no edit summary
No edit summary
No edit summary
 
Line 1:
===Code replacement===
<s>Proposing to replace C code with new code below, depending on if there are objections. Reason: new code is more functional.</s>
<snipped: replaced example with new code>
 
<s>Replace or not, here are some more test files:</s>
This is still using OpenGL and glut. Hotkeys: "+"/"-" zoom, arrow keys: pan, "&gt;" and "&lt;": increase/decrease speed; space: pause; "q"/Esc: quit.
<lang C>#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <GL/glut.h>
 
enum {
empty = 0,
head,
tail,
conductor,
};
 
int gwin, width = 0, height = 0;
int win_w, win_h;
int off_x = 0, off_y = 0;
int paused = 1;
long sleep_time = 1L << 18;
 
unsigned char **cells, **cell_bak;
unsigned long non_empty = 0;
unsigned long zoom = 1;
 
int clamp(int x, int min, int max)
{
if (x < min) x = min;
if (x >= max) x = max - 1;
return x;
}
 
void render()
{
int i, j;
double x0, x1, y0, y1;
double cx, cy;
if (zoom <= 0) zoom = 1;
if (win_w > width * zoom) off_x = 0;
cx = off_x + width / 2.;
if (win_h > height* zoom) off_y = 0;
cy = off_y + height/ 2.;
double ex0 = cx - win_w / 2. / zoom, ex1 = cx + win_w / 2. / zoom;
double ey0 = cy - win_h / 2. / zoom, ey1 = cy + win_h / 2. / zoom;
int i0 = floor(ex0), i1 = floor(ex1), j0 = floor(ey0), j1 = floor(ey1);
i0 = clamp(i0, 1, width - 1);
i1 = clamp(i1, 1, width - 1);
j0 = clamp(j0, 1, height - 1);
j1 = clamp(j1, 1, height - 1);
 
glClear(GL_COLOR_BUFFER_BIT);
 
glLoadIdentity();
glOrtho(ex0, ex1, ey1, ey0, -1, 1);
for (i = i0; i <= i1; i++) {
x0 = i;
if (x0 > win_w) continue;
x1 = (i + 1);
if (x1 < 0) continue;
for (j = j0; j <= j1; j++) {
if (cells[j][i] == empty) continue;
 
y0 = j;
if (y0 >= win_h) continue;
y1 = (j + 1);
if (y1 < 0) continue;
 
switch(cells[j][i]) {
case head: glColor3ub(255, 0, 0); break;
case tail: glColor3ub(0, 128, 255); break;
default: glColor3ub(40, 80, 0); break;
}
glRectd(x0, y0, x1, y1);
}
}
glFlush();
}
 
void evolve()
{
int i, j, l, cnt;
int offsets[][2] = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}, {0, 1}, {0, -1}, {1, 0}, {-1, 0}};
if (paused) goto skip;
memcpy(cell_bak[0], cells[0], sizeof(unsigned char) * width * height);
for (i = 1; i < height - 1; i++) {
for (j = 1; j < width - 1; j++) {
switch(cell_bak[i][j]) {
case tail: cells[i][j] = conductor; break;
case head: cells[i][j] = tail; break;
case conductor:
cnt = 0;
for (l = 0; l < 8; l++) {
cnt += (cell_bak[i + offsets[l][0]][j + offsets[l][1]] == head);
if (cnt > 2) break;
}
if (cnt ==1 || cnt == 2)
cells[i][j] = head;
}
}
}
render();
skip: if (sleep_time)
usleep(sleep_time);
}
 
void resize(int w, int h)
{
win_w = w;
win_h = h;
glViewport(0, 0, w, h);
render();
}
 
void handle_key(unsigned char key, int x, int y)
{
switch(key) {
case 'q': case '\033':
glFinish();
glutDestroyWindow(gwin);
return;
case '+': case '=':
zoom ++;
break;
case '-': case '_':
zoom --;
break;
case ' ':
paused = !paused;
break;
case '>': case '.':
sleep_time /= 2;
break;
case '<': case ',':
sleep_time *= 2;
if (!sleep_time) sleep_time = 1;
break;
}
render();
}
 
void handle_special(int key, int x, int y)
{
switch(key) {
case GLUT_KEY_LEFT: off_x -= 1; break;
case GLUT_KEY_RIGHT: off_x += 1; break;
case GLUT_KEY_UP: off_y -= 1; break;
case GLUT_KEY_DOWN: off_y += 1; break;
}
render();
}
 
int read_file(char * fn)
{
struct stat st;
char *buf, *ptr;
int i, j, line_len;
 
int fd = open(fn, O_RDONLY);
if (fd == -1) return 0;
fstat(fd, &st);
 
ptr = buf = malloc(st.st_size + 1);
read(fd, buf, st.st_size);
buf[st.st_size] = '\0';
close(fd);
 
height = width = line_len = 0;
while (*ptr != '\0') {
switch(*ptr) {
case '\n':
if (width < line_len) width = line_len;
line_len = 0;
height ++;
break;
case 't': case 'H': case ' ': case '.':
non_empty++;
line_len++;
break;
default:
fprintf(stderr, "bad char %d at line %d, %d\n",
*ptr, height + 1, line_len);
}
ptr++;
}
printf("%lu non empty cells\n", non_empty);
height += 2;
width += 2;
cells = malloc(sizeof(unsigned char*) * height);
cell_bak = malloc(sizeof(unsigned char*) * height);
cells[0] = calloc(sizeof(unsigned char), width * height);
cell_bak[0] = calloc(sizeof(unsigned char), width * height);
for (i = 1; i < height; i++) {
cells[i] = cells[i - 1] + width;
cell_bak[i] = cell_bak[i - 1] + width;
}
 
ptr = buf;
i = j = 1;
while (*ptr != '\0') {
switch(*(ptr++)) {
case '\n': i++; j = 1; continue;
case 't': cells[i][j++] = tail; continue;
case 'H': cells[i][j++] = head; continue;
case '.': cells[i][j++] = conductor; continue;
default: j++;
}
}
 
return 1;
}
 
int main(int c, char **v)
{
glutInit(&c, v);
if (c <= 1) {
fprintf(stderr, "usage: %s filename\n", v[0]);
return 0;
}
 
if (!read_file(v[1])) exit(1);
 
glutInitWindowPosition(-1, -1);
 
win_w = width;
win_h = height;
if (win_w < 300) win_w = 300;
if (win_h < 200) win_h = 200;
glutInitWindowSize(win_w, win_h);
glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH);
gwin = glutCreateWindow("Wireworld");
glutKeyboardUpFunc(handle_key);
glutSpecialFunc(handle_special);
glutDisplayFunc(render);
glutReshapeFunc(resize);
glutIdleFunc(evolve);
glLoadIdentity();
glutMainLoop();
return 0;
}</lang>
 
Replace or not, here are some more test files:
<pre> .................. .........................
. . . .
Anonymous user