Skip to content

Instantly share code, notes, and snippets.

@mikezila
Created January 23, 2017 01:38
Show Gist options
  • Save mikezila/1f78db377f605e96db1af1b7d84def12 to your computer and use it in GitHub Desktop.
Save mikezila/1f78db377f605e96db1af1b7d84def12 to your computer and use it in GitHub Desktop.
Game of Life in C using OpenMP.
#include <stdlib.h>
#include <stdio.h>
#include "stopwatch.h"
#include <time.h>
#include <omp.h>
int wrappedLookup(int);
void seedGame(char *);
void playRound(char *, char *, char *);
void seedGlider(char *);
void clearField(char *);
#define FIELD_WIDTH 4000
#define FIELD_HEIGHT 3000
#define FIELD_SIZE FIELD_WIDTH * FIELD_HEIGHT
#define PLAY_ROUNDS 5
#define TRUE 1
#define FALSE 0
int main(int argc, char **argv) {
printf("Life Engine v0.1\n\n");
srand((unsigned int) time(NULL));
// Memory for two game fields, one current and one for next round.
// Also a bool to indicate which "buffer" we should be using as which
char *frontField = (char *) malloc(FIELD_SIZE);
char *backField = (char *) malloc(FIELD_SIZE);
char *bufferSwapped = (char *) malloc(1);
*bufferSwapped = FALSE;
// Randomize the board
seedGame(frontField);
clearField(backField);
// Stopwatch
stopwatch_t timer;
for (int i = 0; i < PLAY_ROUNDS; i++) {
StartTimer(&timer);
playRound(frontField, backField, bufferSwapped);
StopTimer(&timer);
printf("%ims\n", (int) ReadTimer(&timer));
}
free(frontField);
free(backField);
free(bufferSwapped);
return 0;
}
void playRound(char *fieldA, char *fieldB, char *swapped) {
char *currentRound;
char *nextRound;
// Setup a couple pointers and swap the field buffer.
if (*swapped == FALSE) {
currentRound = fieldA;
nextRound = fieldB;
*swapped = TRUE;
} else {
nextRound = fieldA;
currentRound = fieldB;
*swapped = FALSE;
}
// I didn't take any precautions for using openmp when I made this, which
// may be kind of spicy? It doesn't matter the order the game of life is
// evaluated in, so I don't think there should be any problems.
#pragma omp parallel for
for (int i = 0; i < FIELD_SIZE; i++) {
char liveNeighbors = 0;
// left, right, bottom, top
liveNeighbors += currentRound[wrappedLookup(i - 1)];
liveNeighbors += currentRound[wrappedLookup(i + 1)];
liveNeighbors += currentRound[wrappedLookup(i + FIELD_WIDTH)];
liveNeighbors += currentRound[wrappedLookup(i - FIELD_WIDTH)];
// tLeft, tRight, bLeft, bRight
liveNeighbors += currentRound[wrappedLookup(i - 1 - FIELD_WIDTH)];
liveNeighbors += currentRound[wrappedLookup(i + 1 - FIELD_WIDTH)];
liveNeighbors += currentRound[wrappedLookup(i - 1 + FIELD_WIDTH)];
liveNeighbors += currentRound[wrappedLookup(i + 1 + FIELD_WIDTH)];
if (currentRound[i] == TRUE) {
if (liveNeighbors < 2) {
nextRound[i] = FALSE;
continue;
}
if (liveNeighbors > 3) {
nextRound[i] = FALSE;
continue;
}
if (liveNeighbors == 2 || liveNeighbors == 3) {
nextRound[i] = TRUE;
continue;
}
} else {
if (liveNeighbors == 3) {
nextRound[i] = TRUE;
} else {
nextRound[i] = FALSE;
}
}
}
}
// Fill the front buffer with random 1/0.
void seedGame(char *buffer) {
for (int i = 0; i < FIELD_SIZE; i++) {
buffer[i] = (char) rand() & 1;
}
return;
}
void clearField(char *buffer) {
for (int i = 0; i < FIELD_SIZE; i++) {
buffer[i] = 0;
}
}
void seedGlider(char *buffer) {
buffer[2 + (FIELD_WIDTH * 2)] = 1;
buffer[3 + (FIELD_WIDTH * 3)] = 1;
buffer[1 + (FIELD_WIDTH * 4)] = 1;
buffer[2 + (FIELD_WIDTH * 4)] = 1;
buffer[3 + (FIELD_WIDTH * 4)] = 1;
}
int wrappedLookup(int index) {
if (index < 0) {
return (FIELD_SIZE - 1) + (index % (FIELD_SIZE - 1));
} else {
return index % (FIELD_SIZE - 1);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment