Go Down

Topic: Conway's Game of Life Code with auto restart? (Read 486 times) previous topic - next topic

GeekGuyMJ

Does any one have code for Conway's Game of Life that will restart itself when it either dies out, gets stuck on a still image, or gets stuck in a repeating pattern?  I have tried for awhile but can't seem to make it work right and would like some help.

This is the original code I had and I know works, but only runs "one game."  It is from http://www.instructables.com/id/810-LED-Matrix-with-4017/

Code: [Select]
// 10*8 LED matrix with 4017 IC
// Made by Vadim S.
//On 25.06.2009
#define XSIZE 10
#define YSIZE 8
int DataPin = 9;
int LatchPin = 11;
int ClockPin = 10;
int clock = 13;
int Reset = 12;
int a;
byte world[10][8][2];
long density = 50; // The density of the population on the the screen
byte bank[] = {
  B00000001,B00000010,B00000100,B00001000,B00010000,B00100000,B01000000,B10000000}; // a pool of bytes
// set up
byte leds_1[10] = {
  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000};
byte leds_2[10] = {
  B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000};
void setup(){
  pinMode(DataPin,OUTPUT);
  pinMode(ClockPin,OUTPUT);
  pinMode(LatchPin,OUTPUT);
  //simple stuff here
  pinMode(clock,OUTPUT);
  pinMode(Reset,OUTPUT);
  //reseting the 4017 IC, you have to do this
  digitalWrite(Reset,HIGH);
  delayMicroseconds(5);
  digitalWrite(Reset,LOW);
  randomSeed(analogRead(5));// a random seed for the random start pattern
  // random papulation of the screen
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 8; j++) {
      if (random(100) < density) {
        world[i][j][0] = 1;
        leds_1[i]+=bank[j];
        leds_2[i] = leds_1[i];
      }
      else {
        world[i][j][0] = 0;
      }
      world[i][j][1] = 0;
    }
  }
}


void loop(){
  display_pattern_1(50);
  // Birth and death cycle
  for (int x = 0; x < 10; x++) {
    for (int y = 0; y < 8; y++) {
      // Default is for cell to stay the same
      world[x][y][1] = world[x][y][0];
      int count = neighbours(x, y);
      if (count == 3 && world[x][y][0] == 0) {
        // A new cell is born
        world[x][y][1] = 1;
        leds_2[x] += bank[y];
      }
      if ((count < 2 || count > 3) && world[x][y][0] == 1) {
        // Cell dies
        world[x][y][1] = 0;
        leds_2[x] -= bank[y];
      }
    }
  }

  // Copy next generation into place
  for (int x = 0; x < 10; x++) {
    for (int y = 0; y < 8; y++) {
      world[x][y][0] = world[x][y][1];
      leds_1[x] = leds_2[x];
    }
  }
}

// This function is for the 4 laws in conway's game of life
int neighbours(int x, int y) {
  return world[(x + 1) % XSIZE][y][0] +
    world[x][(y + 1) % YSIZE][0] +
    world[(x + XSIZE - 1) % XSIZE][y][0] +
    world[x][(y + YSIZE - 1) % YSIZE][0] +
    world[(x + 1) % XSIZE][(y + 1) % YSIZE][0] +
    world[(x + XSIZE - 1) % XSIZE][(y + 1) % YSIZE][0] +
    world[(x + XSIZE - 1) % XSIZE][(y + YSIZE - 1) % YSIZE][0] +
    world[(x + 1) % XSIZE][(y + YSIZE - 1) % YSIZE][0];
}


void display_pattern_1(int loops){
  for(int t=0;t<loops;t++){
    for(a=0;a<10;a++){
      digitalWrite(LatchPin, 0);
      shiftOut(DataPin, ClockPin,MSBFIRST,leds_1[a]);
      digitalWrite(LatchPin, 1);
      delayMicroseconds(800);
      digitalWrite(LatchPin, 0);
      shiftOut(DataPin, ClockPin,MSBFIRST,0);
      digitalWrite(LatchPin, 1);
      digitalWrite(clock,HIGH);
      digitalWrite(clock,LOW);
    }
  }
}



Also I would like to make another LED matrix with a max7219 IC.  Is there a port of "Game of Life" for use with this IC?  Preferably one that also has an auto restart when it dies out. 

jwatte

"detect that the game is stuck in a cycle" is pretty much the Halting Problem, and not feasible. Detecting cycles up to a particular length is possible using memory -- but if you have a large game field, and a small amount of RAM, that, too, can be a challenge.

Detecting "die out" and detecting "static frame" is the same thing -- each iteration, clear a flag; evolve cells; if you change the life/death of a cell, set the flag; after the iteration is done, if the flag is still clear, you have a static image. You probably want to display that for a second or two before re-starting, though.

WizenedEE

I just made this tonight for fun; it uses the MAX7219 and arduino1.0. The LEDArray library is attached. DataIn is on pin 2, Clock is on pin 3, and Latch is on pin 4.
Code: [Select]
#include <LEDArray.h>

LEDArray disp(2, 3, 4);

const unsigned long iterationTime = 500;
byte defaultGrid[8] = {128,96,192,0,0,0,0,0};

void setup() {
    Serial.begin(9600);
    Serial.println(F(
        "Welcome to Conway's Game of life!\n"
        "We will start with a default pattern, but you can override that\n"
        "by typing into the box above.\n"
        "Make sure you set the line ending to \"Newline\"\n\n"
        "The syntax is: 8 lines of 8 characters each\n"
        "Representing each of the 8 rows and columns on the LED Matrix.\n"
        "Each 0 represents a dead cell and anything else represents a\n"
        "living cell."
    ));
}

byte serialGrid[8]; // Grid that user is inputting

void loop() {
    static byte curGrid[8] = {128,96,192,0, 0,0,0,0}; //Start off with glider
    static byte nextGrid[8]; //Place where the next grid is calculated

    static unsigned long currentTime;
    static unsigned long lastDrawTime;
   
    currentTime = millis();
   
    if (checkSerial()) for (byte i=0;i<8;i++)  curGrid[i] = defaultGrid[i] = serialGrid[i];
     
   
    if (currentTime - lastDrawTime >= iterationTime) {
        disp.drawPic(curGrid);

        for (byte j=0;j<8;j++) {
            for (byte i=0;i<8;i++) {
                byte neighbors = numNeighbors(curGrid, j, i);
                if (bitRead(curGrid[j], i)) {
                    if (neighbors == 2 || neighbors == 3) {
                        bitSet(nextGrid[j], i);
                    }
                    else {
                        bitClear(nextGrid[j], i);
                    }
                }
                else {
                    if (neighbors == 3) {
                        bitSet(nextGrid[j], i);
                    }
                    else {
                        bitClear(nextGrid[j], i);
                    }
                }
            }
        }

        lastDrawTime = currentTime;
        bool dead = true;
        for (byte i=0;i<8;i++) {
            if (curGrid[i] != nextGrid[i]) dead = false;
            curGrid[i] = nextGrid[i];
        }
        if (dead) {
            for (byte i=0;i<8;i++) {
                curGrid[i] = defaultGrid[i];
            }
        }
    }
}

byte numNeighbors(byte* grid, byte row, byte column) {
    byte neighbors = 0;
    for (int8_t j = -1; j <= 1; j++) {
        for (int8_t i = -1; i <= 1; i++) {
            int8_t rowToRead = row + j;
            int8_t columnToRead = column + i;

            if ((j != 0 || i != 0) &&
                (rowToRead >= 0 && columnToRead >= 0) &&
                (rowToRead <= 7 && columnToRead <= 7) &&
                 bitRead(grid[rowToRead], columnToRead)) {
                    neighbors++;
            }
        }
    }
    return neighbors;
}

bool checkSerial() {
    static byte serialColumn = 0; // Current column that user is inputting
    static byte serialRow = 0; // Current row that user is inputting
    while (Serial.available()) {
        byte incoming = Serial.read();
        Serial.write(incoming);
        if ((incoming == '0' || incoming == ' ') && serialColumn < 8) {
            // Clear the "column"th bit of serialgrid
            bitClear(serialGrid[serialRow], serialColumn);
        }
        else if (incoming != '\n' && serialColumn < 8){
            // Set the "column"th bit of serialgrid
            bitSet(serialGrid[serialRow], serialColumn);
        }
        serialColumn++;

        if ( incoming == '\n'){
          serialRow++;
          serialColumn = 0;
        }
        if (serialRow == 8) {
          serialRow = 0;
          Serial.println("\nSetting...");
          return true;
        }
    }
    return false;
}

Go Up