104 lines
2.6 KiB
C
104 lines
2.6 KiB
C
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
#define width 512
|
|
#define height 512
|
|
|
|
static uint8_t field[width * height];
|
|
static uint8_t nextField[width * height];
|
|
static uint8_t pixels[width * height * 4];
|
|
|
|
static uint8_t rand8(void);
|
|
static int countNeighbours(int x, int y);
|
|
|
|
EXPORT(getWidth) int get_width(void) { return width; }
|
|
EXPORT(getHeight) int get_height(void) { return height; }
|
|
EXPORT(getPixels) uint8_t* get_pixels(void) { return pixels; }
|
|
|
|
EXPORT(step) void step(void)
|
|
{
|
|
for (int y = 0; y < height; y++) {
|
|
for (int x = 0; x < width; x++) {
|
|
int count = countNeighbours(x, y);
|
|
uint8_t currentCell = field[x + y * width];
|
|
int nextCell = currentCell;
|
|
if (currentCell && count < 2) nextCell = 0;
|
|
else if (currentCell && count > 3) nextCell = 0;
|
|
else if (!currentCell && count == 3) nextCell = 1;
|
|
|
|
nextField[x + y * width] = nextCell;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < width * height; i++) {
|
|
field[i] = nextField[i];
|
|
uint8_t px = field[i];
|
|
|
|
if (px) {
|
|
pixels[(i << 2) + 0] = 0;
|
|
pixels[(i << 2) + 1] = 0;
|
|
pixels[(i << 2) + 2] = 0;
|
|
} else {
|
|
pixels[(i << 2) + 0] = 255;
|
|
pixels[(i << 2) + 1] = 255;
|
|
pixels[(i << 2) + 2] = 255;
|
|
}
|
|
pixels[(i << 2) + 3] = 255;
|
|
}
|
|
}
|
|
|
|
static int countNeighbours(int x, int y)
|
|
{
|
|
int count = 0;
|
|
for (int i = -1; i <= 1; i++) {
|
|
for (int j = -1; j <= 1; j++) {
|
|
if (i == 0 && j == 0) continue;
|
|
|
|
int xx = (x + i + width) % width;
|
|
int yy = (y + j + height) % height;
|
|
|
|
if (field[xx + yy * width]) {
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
/** Random generator implementation from https://stackoverflow.com/a/16761955 */
|
|
#define STATE_BYTES 7
|
|
#define MULT 0x13B /* for STATE_BYTES==6 only */
|
|
#define MULT_LO (MULT & 255)
|
|
#define MULT_HI (MULT & 256)
|
|
|
|
static uint8_t rand_state[STATE_BYTES] = { 0x87, 0xdd, 0xdc, 0x10, 0x35, 0xbc, 0x5c };
|
|
|
|
static uint8_t rand8(void)
|
|
{
|
|
static uint16_t c = 0x42;
|
|
static uint32_t i = 0;
|
|
uint16_t t;
|
|
uint8_t x;
|
|
|
|
x = rand_state[i];
|
|
t = (uint16_t)x * MULT_LO + c;
|
|
c = t >> 8;
|
|
#if MULT_HI
|
|
c += x;
|
|
#endif
|
|
x = t & 255;
|
|
rand_state[i] = x;
|
|
if (++i >= sizeof(rand_state))
|
|
i = 0;
|
|
return x;
|
|
}
|
|
|
|
EXPORT(initField) void init_field(uint32_t randomSeed)
|
|
{
|
|
*((uint32_t*)&rand_state[STATE_BYTES - sizeof(uint32_t)]) = randomSeed; // Voodoo
|
|
|
|
for (int i = 0; i < width * height; i++) {
|
|
field[i] = rand8() & 1;
|
|
}
|
|
}
|