finished conway

This commit is contained in:
Steffen Vogel 2010-11-29 15:00:41 +01:00
parent c0d35383ad
commit 3147b711e9
2 changed files with 217 additions and 78 deletions

BIN
bin/conway Executable file

Binary file not shown.

View file

@ -1,36 +1,69 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <curses.h>
/* configuration */
#define CELL_CHAR '#'
#define CURSOR_CHAR 'X'
#define WIDTH 80
#define HEIGHT 24
#define ESC 27
#define FRAME_RATE 5
#define FRAME_RATE 17
void clear_screen() {
printf("%c[2J", ESC);
}
/* start pattern */
uint8_t start[3][3] = {
{0, 1, 1},
{1, 1, 0},
{0, 1, 0}
};
void set_cursor(int row, int col) {
printf("%c[%d;%dH", ESC, row, col);
}
uint8_t glider[3][3] = {
{0, 1, 0},
{0, 0, 1},
{1, 1, 1}
};
void clean_world(uint8_t world[WIDTH][HEIGHT]) {
size_t a, b;
struct cursor {
uint8_t x;
uint8_t y;
};
for (a = 0; a < WIDTH; a++) {
for (b = 0; b < HEIGHT; b++) {
world[a][b] = 0;
}
void clean_world(uint8_t ** world, uint8_t width, uint8_t height) {
int a;
for (a = 0; a < width; a++) {
memset(world[a], 0, height * sizeof(uint8_t));
}
}
void inhabit_world(uint8_t pattern[3][3], size_t x, size_t y, uint8_t world[WIDTH][HEIGHT]) {
size_t a, b;
uint8_t ** create_world(uint8_t width, uint8_t height) {
uint8_t ** world = malloc(width * sizeof(uint8_t *));
int a;
for (a = 0; a < width; a++) {
world[a] = malloc(height * sizeof(uint8_t));
if (world[a] == NULL) {
endwin();
fprintf(stderr, "Cant allocate memory!\n");
exit(-1);
}
}
clean_world(world, width, height);
return world;
}
void destroy_world(uint8_t ** world, uint8_t width) {
uint8_t a;
for (a = 0; a < width; a++) {
free(world[a]);
}
free(world);
}
void inhabit_world(uint8_t pattern[3][3], uint8_t x, uint8_t y, uint8_t ** world) {
uint8_t a, b;
for (a = 0; a < 3; a++) {
for (b = 0; b < 3; b++) {
@ -39,14 +72,31 @@ void inhabit_world(uint8_t pattern[3][3], size_t x, size_t y, uint8_t world[WIDT
}
}
uint8_t calc_cell_neighbours(size_t x, size_t y, uint8_t world[WIDTH][HEIGHT]) {
uint8_t calc_cell_count(uint8_t ** world, uint8_t width, uint8_t height) {
int cell_count = 0;
uint8_t a, b;
for (a = 0; a < width; a++) {
for (b = 0; b < height; b++) {
cell_count += (world[a][b]) ? 1 : 0;
}
}
return cell_count;
}
uint8_t calc_cell_neighbours(uint8_t x, uint8_t y, uint8_t ** world, uint8_t width, uint8_t height) {
uint8_t neighbours = 0;
int8_t a, b;
int a, b;
for (a = x-1; a <= x+1; a++) {
for (b = y-1; b <= y+1; b++) {
if (a >= 0 && b >= 0 && a != x && b != y && world[a][b] > 0) {
neighbours++;
if (a == x && b == y)
continue;
if (a >= 0 && b >= 0 &&
a < width && b < height) {
neighbours += (world[a][b] > 0) ? 1 : 0;
}
}
}
@ -54,84 +104,173 @@ uint8_t calc_cell_neighbours(size_t x, size_t y, uint8_t world[WIDTH][HEIGHT]) {
return neighbours;
}
uint8_t calc_next_cell_gen(size_t x, size_t y, uint8_t world[WIDTH][HEIGHT]) {
uint8_t neighbours = calc_cell_neighbours(x, y, world);
uint8_t calc_next_cell_gen(uint8_t x, uint8_t y, uint8_t ** world, uint8_t width, uint8_t height) {
fflush(stdout);
uint8_t neighbours = calc_cell_neighbours(x, y, world, width, height);
uint8_t alive = world[x][y];
if (neighbours < 2) {
return 0;
if (alive) {
if (neighbours > 3 || neighbours < 2) {
return 0; /* died by over-/underpopulation */
}
else {
return neighbours;
}
}
else if (neighbours > 3) {
return 0;
}
else if (neighbours == 2 || neighbours == 3) {
return 1;
else if (neighbours == 3) {
return neighbours;
}
else {
return -1;
return 0;
}
}
void calc_next_gen(uint8_t world[WIDTH][HEIGHT]) {
uint8_t next_gen[WIDTH][HEIGHT];
size_t x, y;
void calc_next_gen(uint8_t ** world, uint8_t ** next_gen, uint8_t width, uint8_t height) {
uint8_t x, y;
clean_world(next_gen);
for (x = 0; x < WIDTH; x++) {
for (y = 0; y < HEIGHT; y++) {
next_gen[x][y] = calc_next_cell_gen(x, y, world);
for (x = 0; x < width; x++) {
for (y = 0; y < height; y++) {
next_gen[x][y] = calc_next_cell_gen(x, y, world, width, height);
}
}
memcpy(world, next_gen, WIDTH*HEIGHT);
}
void print_world(uint8_t world[WIDTH][HEIGHT]) {
size_t x, y;
/* reset cursor */
set_cursor(0, 0);
for (y = 0; y < HEIGHT; y++) {
for (x = 0; x < WIDTH; x++) {
/*printf("%c", (world[x][y]) ? CELL_CHAR : ' ');*/
printf("%d,", (world[x][y] != 0) ? (int) world[x][y] : ' ');
/* copy world */
for (x = 0; x < width; x++) {
for (y = 0; y < height; y++) {
world[x][y] = next_gen[x][y];
}
printf("\n"); /* new line */
}
for (y = 0; y < HEIGHT; y++) {
printf("|");
for (x = 0; x < WIDTH; x++) {
printf("%c", (world[x][y]) ? CELL_CHAR : ' ');
}
printf("|\n"); /* new line */
}
}
/* start pattern */
uint8_t glider[3][3] = {
{0, 1, 0},
{0, 0, 1},
{1, 1, 1}
};
void print_world(uint8_t ** world, uint8_t width, uint8_t height) {
uint8_t x, y;
move(0, 0); /* reset cursor */
/* cells */
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
printw("%c", (world[x][y] > 0) ? CELL_CHAR : ' ');
}
}
}
void print_cursor(uint8_t ** world, struct cursor cur) {
uint8_t color = (world[cur.x][cur.y]
move(cur.y, cur.x);
attron(COLOR_PAIR(1));
addch(CURSOR_CHAR);
attroff(COLOR_PAIR(1));
}
WINDOW * init_screen() {
WINDOW * win = initscr();
noecho();
timeout(0);
keypad(win, 1);
mousemask(BUTTON1_CLICKED, NULL);
mouseinterval(200);
curs_set(0);
start_color();
init_pair(1, COLOR_RED, COLOR_BLACK);
init_pair(2, COLOR_GREEN, COLOR_BLACK);
return win;
}
int main(int argc, char * argv[]) {
uint8_t world[WIDTH][HEIGHT];
int counter = 0;
WINDOW * win = init_screen();
MEVENT event;
clean_world(world); /* initialize world */
inhabit_world(glider, WIDTH/2, HEIGHT/2, world); /* inhabit world */
clear_screen();
print_world(world);
struct cursor cur = {0, 0};
int generation = 0;
uint8_t width, height, paused = 1;
uint8_t ** world, ** next_gen;
getmaxyx(win, height, width);
/* initialize world */
world = create_world(width, height);
next_gen = create_world(width, height);
inhabit_world(start, width/2, height/2, world);
/* simulation loop */
while(0) {
calc_next_gen(world);
print_world(world);
usleep((float) 1 / FRAME_RATE * 1000000); /* sleep */
printf("frame: %d\n", counter++);
while(1) {
/* handle events */
switch (getch()) {
case 'q':
endwin();
exit(0);
break;
case 'p':
paused ^= 1;
break;
case 'c':
clean_world(world, width, height);
break;
case 'g':
inhabit_world(glider, cur.x, cur.y, world);
break;
case ' ':
world[cur.x][cur.y] = (world[cur.x][cur.y]) ? 0 : 1;
break;
case KEY_MOUSE:
if (getmouse(&event) == OK && event.bstate & BUTTON1_CLICKED) {
cur.x = event.x;
cur.y = event.y;
world[cur.x][cur.y] = (world[cur.x][cur.y]) ? 0 : 1;
}
break;
case KEY_UP:
if (cur.y > 0) {
cur.y--;
}
break;
case KEY_DOWN:
if (cur.y < height-1) {
cur.y++;
}
break;
case KEY_LEFT:
if (cur.x > 0) {
cur.x--;
}
break;
case KEY_RIGHT:
if (cur.x < width-1) {
cur.x++;
}
break;
}
if (!paused) {
usleep((float) 1 / FRAME_RATE * 1000000); /* sleep */
calc_next_gen(world, next_gen, width, height);
generation++;
}
print_world(world, width, height);
print_cursor(world, cur);
attron(COLOR_PAIR(2));
mvprintw(0, 0, "generation: %d\tcells: %d framerate: %d fps\twidth: %d\theight: %d cursor: (%d|%d)\n", generation, calc_cell_count(world, width, height), FRAME_RATE, width, height, cur.x, cur.y);
if (paused) mvprintw(0, width-6, "PAUSED");
attroff(COLOR_PAIR(2));
refresh();
}
endwin();
return 0;
}