Created
January 23, 2017 01:38
-
-
Save mikezila/1f78db377f605e96db1af1b7d84def12 to your computer and use it in GitHub Desktop.
Game of Life in C using OpenMP.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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