#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <libpmemcto.h>
#include "life.h"
struct game *
game_init(const char *path, int width, int height, int percent)
{
PMEMctopool *pcp = pmemcto_create(path, LAYOUT_NAME, POOL_SIZE, 0666);
if (pcp == NULL)
pcp = pmemcto_open(path, LAYOUT_NAME);
if (pcp == NULL) {
fprintf(stderr, "%s", pmemcto_errormsg());
return NULL;
}
struct game *gp = pmemcto_get_root_pointer(pcp);
if (gp != NULL) {
if (gp->width == width && gp->height == height) {
return gp;
} else {
fprintf(stderr, "board dimensions changed");
pmemcto_free(pcp, gp->board1);
pmemcto_free(pcp, gp->board2);
pmemcto_free(pcp, gp);
}
}
gp = pmemcto_calloc(pcp, 1, sizeof(*gp));
if (gp == NULL) {
fprintf(stderr, "%s", pmemcto_errormsg());
return NULL;
}
pmemcto_set_root_pointer(pcp, gp);
gp->pcp = pcp;
gp->width = width;
gp->height = height;
gp->board1 = (char *)pmemcto_malloc(pcp, width * height);
if (gp->board1 == NULL) {
fprintf(stderr, "%s", pmemcto_errormsg());
return NULL;
}
gp->board2 = (char *)pmemcto_malloc(pcp, width * height);
if (gp->board2 == NULL) {
fprintf(stderr, "%s", pmemcto_errormsg());
return NULL;
}
gp->board = gp->board2;
srand((unsigned)time(NULL));
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
CELL(gp, gp->board, x, y) = (rand() % 100 < percent);
return gp;
}
static int
cell_next(struct game *gp, char *b, int x, int y)
{
int alive = CELL(gp, b, x, y);
int neighbors = CELL(gp, b, x - 1, y - 1) +
CELL(gp, b, x - 1, y) +
CELL(gp, b, x - 1, y + 1) +
CELL(gp, b, x, y - 1) +
CELL(gp, b, x, y + 1) +
CELL(gp, b, x + 1, y - 1) +
CELL(gp, b, x + 1, y) +
CELL(gp, b, x + 1, y + 1);
int next = (alive && (neighbors == 2 || neighbors == 3)) ||
(!alive && (neighbors == 3));
return next;
}
void
game_next(struct game *gp)
{
char *prev = gp->board;
char *next = (gp->board == gp->board2) ? gp->board1 : gp->board2;
for (int x = 0; x < gp->width; x++)
for (int y = 0; y < gp->height; y++)
CELL(gp, next, x, y) = cell_next(gp, prev, x, y);
gp->board = next;
}