Go Down

Topic: Conway's Game of Life Code with auto restart? (Read 572 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
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy