- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 3 von 3

Thema: Conway's "Game of Life" als Turing-Maschine?

  1. #1
    HaWe
    Gast

    Conway's "Game of Life" als Turing-Maschine?

    Anzeige

    Powerstation Test
    hallo,
    eine Frage zum Verständnis:
    Ich habe bisher Conway's "Game of Life" nur als eine hübsche und interessante Spielerei betrachtet, wie bestimmte Muster sich schrittweise in neue Muster verwandeln und sich dadurch teilweise scheinbar bewegen oder auch zusätzliche weitere Muster erzeugen - allerdings ist "Game of Life" offenbar sogar Turing-vollständig:
    Game of Life als Rechnermodell: Es ist möglich, mithilfe komplexer Startmuster eine Universelle Turing Maschine und deren Eingabe zu modellieren. Conway’s Game of Life ist damit Turing-vollständig. Theoretisch lässt sich jedes algorithmische Problem, das man mit einem Computer lösen kann, auch allein durch Game of Life berechnen
    https://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens

    Es wurden auch offenbar sogar schon Turing-Maschinen damit gebaut:
    http://rendell-attic.org/gol/tm.htm

    Hat jemand verstanden, wie solche Conway's "Game of Life" als Turing-Maschinen im Prinzip und im Detail funktionieren?
    Lässt sich z.B. eine stark vereinfachte Version programmieren, die z.B. für sehr einfache Aufgaben mit variablen Inputs auf einem Arduino (z.B. ARM Cortex) verwendet werden kann? (AVRs sind ntl zu klein)

    Eine kleine GoL-Version für 128x64 Felder habe ich jetzt mal portiert (ESP8266), das soll jetzt für M3/M4 mit ILI9341 etc. hochskaliert werden:

    Code:
    // Arduino-Game-Of-Life
    
    // Game of life
    // http://en.wikipedia.org/wiki/Conway's_Game_of_Life
    // Code adapted from
    // http://cboard.cprogramming.com/c-programming/128982-simple-life-game-code-near-end.html 
    // basic ideas courtesy of Xander Soldaat
    // ported to Arduino by HaWe aka dsyleixa
    
    
    // supported displays:
    // OLED 128x64 SSD1306 (Adafruit_SSD1306) 
    // and different Afadruit-GFX-compatible ones 
    // (adjust libs+resolutions!)
    
    
    
    #include <Arduino.h>
    // I2C
    #include <Wire.h>         // Incl I2C comm, but needed for not getting compile error
    
    //-----------------------------------------------------------------------
    // display driver
    //-----------------------------------------------------------------------
    #include <Adafruit_GFX.h>   // https://github.com/adafruit/Adafruit-GFX-Library 
    // Adafruit Arduino OLED driver
    #include <Adafruit_SSD1306.h> // https://github.com/esp8266/arduino 
    
     Adafruit_SSD1306 display(128, 64, &Wire); // new Adafruit lib
     
    // fonts
    #include <Fonts/FreeSans9pt7b.h>             // optional
    #include <Fonts/FreeMono12pt7b.h>            // optional  
    #include <Fonts/FreeMono9pt7b.h>       // used here by default
    //#include <Fonts/FreeMonoBold7pt7b.h>    // optional, custom font
    
    
    //---------------------------------------------------------------------------
    // preferences and settings
    //---------------------------------------------------------------------------
    // The blocks are blockSize * blockSize big
    // 2...6 seems to be a good value for this
    
    int blockSize = 3;
    
    
    
    // The size of the OLED screen
    
    const int screenWidth = 128;   // <~~~~~~~~~~~~ adjust screen dimensions !
    const int screenHeight = 64;
    const int frame = 10;
    
    
    
    
    // Make the board larger on either side to ensure that there's an invisible border of dead cells
    int yrows = (screenHeight / blockSize) + 2*frame;
    int xcols = (screenWidth / blockSize) + 2*frame;
    
    #define centeryrow (yrows/2)-1 
    #define centerxcol (xcols/2)-1 
    
    // two boards, one for the current generation and one for calculating the next one
    char board[screenHeight + 2*frame][screenWidth + 2*frame];
    char tmpboard[screenHeight + 2*frame][screenWidth + 2*frame];
    
    
    //---------------------------------------------------------------------------
    // GoL functions
    //---------------------------------------------------------------------------
    // Count thy neighbours
    int countNeighbours(int yrow, int xcol)
    {
      int count = 0;
      for (int x = -1; x <= +1; x++)  {
        for (int y = -1; y <= +1; y++) {
          if ((board[yrow + y][xcol + x] == 1) && (x != 0 || y != 0))
            count++;
        }
      }
      return count;
    }
    
    
    //---------------------------------------------------------------------------
    // Calculate the cells that will live and die for the next generation
    void calculateGeneration()
    {
      int aliveNeighbours = 0;
    
      // Clear the board for the next generation
      memset(tmpboard, 0, sizeof(tmpboard));
    
      for (int yrow = 1; yrow < (yrows-1); yrow++)  {
        for (int xcol = 1; xcol < (xcols-1); xcol++)   {
          aliveNeighbours = countNeighbours(yrow, xcol);
    
          // Any live cell with fewer than two live neighbours dies, as if caused by under-population.
          if(aliveNeighbours < 2)
            tmpboard[yrow][xcol] = 0;
    
          // Any live cell with two or three live neighbours lives on to the next calculateGeneration
          if (aliveNeighbours >= 2  &&  aliveNeighbours <= 3 )
            tmpboard[yrow][xcol] = board[yrow][xcol];
    
          // Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction
          if(aliveNeighbours == 3 && board[yrow][xcol]==0)
            tmpboard[yrow][xcol] = 1;
    
          // Any live cell with more than three live neighbours dies, as if by overcyrowding
          if(aliveNeighbours > 3)
            tmpboard[yrow][xcol] = 0;
        }
      }
      // Copy the new board to the old one
      memcpy(board, tmpboard, sizeof(tmpboard));
    }
    
    
    //---------------------------------------------------------------------------
    // Draw all the cells
    //---------------------------------------------------------------------------
    
    void drawBoard()
    {
      // Wipe the screen
      display.clearDisplay();
      for (int yrow=frame; yrow <(yrows-frame); yrow++)
      { 
        for (int xcol=frame; xcol<(xcols-frame); xcol++)
        {
          // Draw all the "live" cells.
          if (board[yrow][xcol])
            display.fillRect((xcol-frame)*blockSize, (yrow-frame)*blockSize, 
                              blockSize, blockSize, WHITE);
        }
      }
      display.display();
    }
    
    
    //---------------------------------------------------------------------------
    // patterns
    //---------------------------------------------------------------------------
    
    void put_Blinker3x1(int starty, int startx) {       //  
    
      board[starty][startx]   = 1;
      board[starty][startx+1] = 1;
      board[starty][startx+2] = 1;
      
    }
    
    //---------------------------------------------------------------------------
    void put_Block2x2(int starty, int startx) {       //  
    
      board[starty][startx]     = 1;
      board[starty][startx+1]   = 1;
      board[starty+1][startx]   = 1;
      board[starty+1][startx+1] = 1;
    }
    
    
    //---------------------------------------------------------------------------
    void put_Bar5x1(int starty, int startx) {       //  
    
      board[starty][startx]   = 1;
      board[starty][startx+1] = 1;
      board[starty][startx+2] = 1;
      board[starty][startx+3] = 1;
      board[starty][startx+4] = 1;
    }
    
    
    void put_Clock(int starty, int startx) {    //  
      int x,y;
    
      char sprite[4][4] = {  //  
      {0,0,1,0},
      {1,1,0,0},
      {0,0,1,1},
      {0,1,0,0},
      } ;
    
      for(x=0; x<4; ++x) {
        for(y=0; y<4; ++y) {
          board[starty+y][startx+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    
    void put_F_Pentomino(int starty, int startx) {    //  == R-Pentomino
      int x,y;
    
      char sprite[3][3] = {  //  
      {0,1,1},
      {1,1,0},
      {0,1,0},
      } ;
    
      for(x=0; x<3; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+y][startx+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_Pi_Heptomino(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[3][5] = {  //  
      {0,0,1,0,0},
      {0,1,0,1,0},
      {1,1,0,1,1}
      } ;
    
      for(x=0; x<5; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+y][startx+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_23334M(int starty, int startx) {    //  
      int x,y;
    
      char sprite[8][5] = {  //  
      {0,0,1,0,0},
      {1,1,0,0,0},
      {0,1,0,0,0},
      {1,0,0,1,0},
      {0,0,0,0,1},
      {0,1,0,0,1},
      {0,0,1,0,1},
      {0,1,0,0,0},
      } ;
    
      for(x=0; x<5; ++x) {
        for(y=0; y<8; ++y) {
          board[starty+y][startx+x]=sprite[y][x] ;
        }
      }
    }
    
    
    
    //---------------------------------------------------------------------------
    void put_Glider(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[3][3] = {  //  
      {0,1,0,},
      {0,0,1,},
      {1,1,1,}
      } ;
      
      for(x=0; x<3; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+y][startx+x]=sprite[y][x] ;
        }
      }
    }
    
    //---------------------------------------------------------------------------
    void put_GliderUp(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[3][3] = {  //  
      {0,1,1,},
      {1,0,1,},
      {0,0,1,}
      } ;
      
      for(x=0; x<3; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+y][startx+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_LWSpaceship(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[4][5] = {  //  
      {1,0,0,1,0},
      {0,0,0,0,1},
      {1,0,0,0,1},
      {0,1,1,1,1},
    
      } ;
    
      for(x=0; x<5; ++x) {
        for(y=0; y<4; ++y) {
          board[starty+y][startx+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_HWSpaceship(int starty, int startx) {    // 
    
      int x,y;
    
      char sprite[5][7] = {  //  
      {0,0,1,1,0,0,0},
      {0,0,0,0,0,1,0},
      {0,0,0,0,0,0,1},
      {1,0,0,0,0,0,1},
      {0,1,1,1,1,1,1},
    
      } ;
    
      for(x=0; x<7; ++x) {
        for(y=0; y<5; ++y) {
          board[starty+y][startx+x]=sprite[y][x] ;
        }
      }
    }
    
    
    
    
    
    //---------------------------------------------------------------------------
    void put_GliderGun(int starty, int startx) {
    
      int x,y;
    
      char sprite[9][37] = {  //  
      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
      {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
      {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
      {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
      } ;
      
      for(x=0; x<37; ++x) {   // NXT screen (0,0) is bottom left, not top left  !
        for(y=0; y<9; ++y) {
        
          board[starty+y][startx+x] = sprite[y][x] ;
        }
      }
    }
    
    
    
    //---------------------------------------------------------------------------
    // This adds some random live cells to the board
    void put_randomBoard(int seedChance)
    {
      for (int yrow = 1; yrow < (yrows - 1); yrow++)
      {
        for (int xcol = 1; xcol < (xcols - 1); xcol++)
        {
          board[yrow][xcol] = !(rand() % seedChance);
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    // setup
    //---------------------------------------------------------------------------
    void setup() {
      Serial.begin(115200);
      delay(3000); // wait for Serial()
      Serial.println("Serial started");
    
     
      // Start Wire (SDA, SCL)
      Wire.begin();
    
      // SSD1306 Init  
      //display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // old Adafruit lib
      display.begin(SSD1306_SWITCHCAPVCC, 0x3C, true, false); // new Adafruit lib
      
      display.setRotation(2);  
      display.clearDisplay();  // Clear the buffer.
    
      // text display tests
      display.setTextSize(1);
      display.setFont();
      display.setTextColor(WHITE);
      display.setCursor(0,0);
      display.println("This is ");  
      display.println("Conway's Game of Live");  
      display.setCursor(0,30);
      display.println("yrows, xcols =");
      display.println(yrows);
      display.println(xcols);
      display.display();
      delay(3000);
    
      srand(analogRead(A0)+millis() );
    
        
       put_Blinker3x1( 10, 10 );                      // blockSize = 3-4 
       put_Block2x2( 10, centerxcol );
       put_Bar5x1( centeryrow, xcols-20 ); 
       put_Clock( yrows-20, centerxcol-10);
        
      
      //put_F_Pentomino( centeryrow+1, centerxcol );   // blockSize = 1 !!
      //put_Pi_Heptomino( centeryrow+2, centerxcol );  // blockSize = 1 !!             
      //put_23334M( centeryrow-1, centerxcol-1 );      // blockSize = 1 !!
    
      //put_Glider(30, 30 );  
      
    /*
        // unit of 3 //
      put_GliderUp(centeryrow+5, 20 );     // rec. blockSize = 2; crash with LW_Spaceship
      put_LWSpaceship( (yrows/4)+5, 12 );  // rec. blockSize = 2; crash with Glider 
      put_HWSpaceship( yrows-19, 10 );     // rec. blockSize = 2;
    */   
      
      //put_GliderGun( 10, 10 );
      
      //put_randomBoard(3);
      
      drawBoard();
      delay(500);  
    }
    
    
    //---------------------------------------------------------------------------
    // loop
    //---------------------------------------------------------------------------
    void loop()
    {
        calculateGeneration();
        drawBoard();
        delay(200);
    }
    - - - Aktualisiert - - -

    update:
    hier ist eine portierte Version für M4 mit einem TFT 3.5 480x320, das M4-RAM reicht aber nur für max. etwa ein 320x240 subscreen window:

    Code:
    // Arduino-Game-Of-Life
    
    // Game of life
    // http://en.wikipedia.org/wiki/Conway's_Game_of_Life
    // Code adapted from
    // http://cboard.cprogramming.com/c-programming/128982-simple-life-game-code-near-end.html 
    // basic ideas courtesy of Xander Soldaat
    // ported to Arduino by dsyleixa
    
    
    // MCU: Adafruit Feather M4
    
    // supported display:
    // Adafruit Featherwing TFT35
    // and different Afadruit-GFX-compatible ones 
    // (adjust libs+resolutions!)
    
    
    
    #include <Arduino.h>
    // i2c, SPI
    #include <Wire.h>         // Incl I2C comm, but needed for not getting compile error
    #include <SPI.h>
    
    
    //-----------------------------------------------------------------------
    // display driver
    //-----------------------------------------------------------------------
    #include <Adafruit_GFX.h>   // https://github.com/adafruit/Adafruit-GFX-Library 
    // Adafruit TFT35 LED driver
    
    #include <Adafruit_HX8357.h>
    #include <Adafruit_STMPE610.h>
     
    // fonts
    #include <Fonts/FreeSans9pt7b.h>             // optional
    #include <Fonts/FreeMono12pt7b.h>            // optional  
    #include <Fonts/FreeMono9pt7b.h>       // used here by default
    //#include <Fonts/FreeMonoBold7pt7b.h>    // optional, custom font
    
    // TFT pins
    #ifdef ESP8266
       #define STMPE_CS 16
       #define TFT_CS   0
       #define TFT_DC   15
       #define SD_CS    2
     
    #elif defined ESP32
       #define STMPE_CS 32
       #define TFT_CS   15
       #define TFT_DC   33
       #define SD_CS    14
     
    #elif defined TEENSYDUINO
       #define TFT_DC   10
       #define TFT_CS   4
       #define STMPE_CS 3
       #define SD_CS    8
      
    #elif defined ARDUINO_STM32_FEATHER
       #define TFT_DC   PB4
       #define TFT_CS   PA15
       #define STMPE_CS PC7
       #define SD_CS    PC5
      
    #elif defined ARDUINO_FEATHER52
       #define STMPE_CS 30
       #define TFT_CS   13
       #define TFT_DC   11
       #define SD_CS    27
    
    #elif  defined(ARDUINO_MAX32620FTHR) || defined(ARDUINO_MAX32630FTHR)
       #define TFT_DC   P5_4
       #define TFT_CS   P5_3
       #define STMPE_CS P3_3
       #define SD_CS    P3_2
    
    // Something else!
    #elif  defined (__AVR_ATmega32U4__) || defined(ARDUINO_SAMD_FEATHER_M0) || defined (__AVR_ATmega328P__) || defined(ARDUINO_SAMD_ZERO) || defined(__SAMD51__)   
       #define STMPE_CS 6
       #define TFT_CS   9
       #define TFT_DC   10
       #define SD_CS    5
    
     // default 
    #else
       #define STMPE_CS 6
       #define TFT_CS   9
       #define TFT_DC   10
       #define SD_CS    5
    #endif
    
    
    #define TFT_RST -1
    
    // display instance
    Adafruit_HX8357    display = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
    Adafruit_STMPE610  ts = Adafruit_STMPE610(STMPE_CS);
    
    
    // color defs
    
    #define BLACK       HX8357_BLACK
    #define DARKGREY    HX8357_DARKGREY 
    #define WHITE       HX8357_WHITE
    #define RED         HX8357_RED
    #define YELLOW      HX8357_YELLOW
    #define CYAN        HX8357_CYAN
    #define DARKCYAN    HX8357_DARKCYAN
    #define BLUE        HX8357_BLUE
    #define GREENYELLOW HX8357_GREENYELLOW
    
    #define COLOR_BKGR  BLACK
    
    //---------------------------------------------------------------------------
    // preferences and settings
    //---------------------------------------------------------------------------
    // The blocks are blockSize * blockSize big
    // 2...6 seems to be a good value for this
    
    int blockSize = 3;
    
    
    
    // The size of the GoL screen window
    
    const int screenWidth = 240;   // <~~~~~~~~~~~~ adjust screen dimensions !
    const int screenHeight= 240;
    const int frame = 10;
    
    
    
    
    // Make the board larger on either side to ensure that there's an invisible border of dead cells
    
    int yvisrows = (screenHeight / blockSize);
    int xviscols = (screenWidth / blockSize);
    
    int yrows = yvisrows + 2*frame;
    int xcols = xviscols + 2*frame;
    
    #define centeryrow (yrows/2)-1 
    #define centerxcol (xcols/2)-1 
    
    // two boards, one for the current generation and one for calculating the next one
    char board[screenHeight + 2*frame][screenWidth + 2*frame];
    char tmpboard[screenHeight + 2*frame][screenWidth + 2*frame];
    
    
    //---------------------------------------------------------------------------
    // GoL functions
    //---------------------------------------------------------------------------
    // Count thy neighbours
    int countNeighbours(int yrow, int xcol)
    {
      int count = 0;
      for (int x = -1; x <= +1; x++)  {
        for (int y = -1; y <= +1; y++) {
          if ((board[yrow + y][xcol + x] == 1) && (x != 0 || y != 0))
            count++;
        }
      }
      return count;
    }
    
    
    //---------------------------------------------------------------------------
    // Calculate the cells that will live and die for the next generation
    void calculateGeneration()
    {
      int aliveNeighbours = 0;
    
      // Clear the board for the next generation
      memset(tmpboard, 0, sizeof(tmpboard));
    
      for (int yrow = 1; yrow < (yrows-1); yrow++)  {
        for (int xcol = 1; xcol < (xcols-1); xcol++)   {
          aliveNeighbours = countNeighbours(yrow, xcol);
    
          // Any live cell with fewer than two live neighbours dies, as if caused by under-population.
          if(aliveNeighbours < 2)
            tmpboard[yrow][xcol] = 0;
    
          // Any live cell with two or three live neighbours lives on to the next calculateGeneration
          if (aliveNeighbours >= 2  &&  aliveNeighbours <= 3 )
            tmpboard[yrow][xcol] = board[yrow][xcol];
    
          // Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction
          if(aliveNeighbours == 3 && board[yrow][xcol]==0)
            tmpboard[yrow][xcol] = 1;
    
          // Any live cell with more than three live neighbours dies, as if by overcyrowding
          if(aliveNeighbours > 3)
            tmpboard[yrow][xcol] = 0;
        }
      }
      // Copy the new board to the old one
      memcpy(board, tmpboard, sizeof(tmpboard));
    }
    
    
    //---------------------------------------------------------------------------
    // Draw all the cells
    //---------------------------------------------------------------------------
    
    void drawBoard()
    {
      // Wipe the screen
      display.fillRect(1, 1, screenWidth+1, screenHeight+1, COLOR_BKGR);
        
      for (int yrow=frame; yrow <(yrows-frame); yrow++) { 
        for (int xcol=frame; xcol<(xcols-frame); xcol++)  {
          // Draw all the "live" cells.
          if (board[yrow][xcol])
            display.fillRect((xcol-frame+1)*blockSize, (yrow-frame+1)*blockSize, 
                              blockSize, blockSize, WHITE);
        }
      }
      //display.display();
    }
    
    
    //---------------------------------------------------------------------------
    // patterns
    //---------------------------------------------------------------------------
    
    void put_Blinker3x1(int starty, int startx) {       //  
    
      board[starty+frame][startx+frame]   = 1;
      board[starty+frame][startx+frame+1] = 1;
      board[starty+frame][startx+frame+2] = 1;
      
    }
    
    //---------------------------------------------------------------------------
    void put_Block2x2(int starty, int startx) {       //  
    
      board[starty+frame][startx+frame]     = 1;
      board[starty+frame][startx+frame+1]   = 1;
      board[starty+frame+1][startx+frame]   = 1;
      board[starty+frame+1][startx+frame+1] = 1;
    }
    
    
    //---------------------------------------------------------------------------
    void put_Bar5x1(int starty, int startx) {       //  
    
      board[starty+frame][startx+frame]   = 1;
      board[starty+frame][startx+frame+1] = 1;
      board[starty+frame][startx+frame+2] = 1;
      board[starty+frame][startx+frame+3] = 1;
      board[starty+frame][startx+frame+4] = 1;
    }
    
    
    void put_Clock(int starty, int startx) {    //  
      int x,y;
    
      char sprite[4][4] = {  //  
      {0,0,1,0},
      {1,1,0,0},
      {0,0,1,1},
      {0,1,0,0},
      } ;
    
      for(x=0; x<4; ++x) {
        for(y=0; y<4; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    
    void put_F_Pentomino(int starty, int startx) {    //  == R-Pentomino
      int x,y;
    
      char sprite[3][3] = {  //  
      {0,1,1},
      {1,1,0},
      {0,1,0},
      } ;
    
      for(x=0; x<3; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_Pi_Heptomino(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[3][5] = {  //  
      {0,0,1,0,0},
      {0,1,0,1,0},
      {1,1,0,1,1}
      } ;
    
      for(x=0; x<5; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_23334M(int starty, int startx) {    //  
      int x,y;
    
      char sprite[8][5] = {  //  
      {0,0,1,0,0},
      {1,1,0,0,0},
      {0,1,0,0,0},
      {1,0,0,1,0},
      {0,0,0,0,1},
      {0,1,0,0,1},
      {0,0,1,0,1},
      {0,1,0,0,0},
      } ;
    
      for(x=0; x<5; ++x) {
        for(y=0; y<8; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    
    //---------------------------------------------------------------------------
    void put_Glider(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[3][3] = {  //  
      {0,1,0,},
      {0,0,1,},
      {1,1,1,}
      } ;
      
      for(x=0; x<3; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    //---------------------------------------------------------------------------
    void put_GliderUp(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[3][3] = {  //  
      {0,1,1,},
      {1,0,1,},
      {0,0,1,}
      } ;
      
      for(x=0; x<3; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_LWSpaceship(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[4][5] = {  //  
      {1,0,0,1,0},
      {0,0,0,0,1},
      {1,0,0,0,1},
      {0,1,1,1,1},
    
      } ;
    
      for(x=0; x<5; ++x) {
        for(y=0; y<4; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_HWSpaceship(int starty, int startx) {    // 
    
      int x,y;
    
      char sprite[5][7] = {  //  
      {0,0,1,1,0,0,0},
      {0,0,0,0,0,1,0},
      {0,0,0,0,0,0,1},
      {1,0,0,0,0,0,1},
      {0,1,1,1,1,1,1},
    
      } ;
    
      for(x=0; x<7; ++x) {
        for(y=0; y<5; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    
    
    
    //---------------------------------------------------------------------------
    void put_GliderGun(int starty, int startx) {
    
      int x,y;
    
      char sprite[9][37] = {  //  
      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
      {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
      {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
      {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
      } ;
      
      for(x=0; x<37; ++x) {   // NXT screen (0,0) is bottom left, not top left  !
        for(y=0; y<9; ++y) {
        
          board[starty+frame+y][startx+frame+x] = sprite[y][x] ;
        }
      }
    }
    
    bool put_GliderEater(int starty, int startx, int V) {
      int x,y;
    
      char sprite[4][4] = {  //  
      {1 ,1 ,0 ,0 },
      {1 ,0 ,0 ,0 },
      {V ,1 ,1 ,1 },
      {0 ,0 ,0 ,1 },
    
      } ;
    
      for(x=0; x<4; ++x) {
        for(y=0; y<4; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }  
    }
    
    
    //---------------------------------------------------------------------------
    // This adds some random live cells to the board
    void put_randomBoard(int seedChance)
    {
      for (int yrow = 1; yrow < (yrows - 1); yrow++)
      {
        for (int xcol = 1; xcol < (xcols - 1); xcol++)
        {
          board[yrow][xcol] = !(rand() % seedChance);
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    // setup
    //---------------------------------------------------------------------------
    void setup() {
      Serial.begin(115200);
      delay(3000); // wait for Serial()
      Serial.println("Serial started");
      
      // Start Wire (SDA, SCL)
      Wire.begin();
    
      // TFT
      display.begin(HX8357D);    
      display.setRotation(1);
      display.fillScreen(COLOR_BKGR);  // Clear Screen
    
      // text display tests
      display.setTextSize(1);
      display.setFont();
      display.setTextColor(WHITE);
      display.setCursor(0,0);
      display.println("This is ");  
      display.println("Conway's Game of Live");  
      display.setCursor(0,30);
      display.print("xcols="); display.println(xviscols);
      display.print("yrows="); display.println(yvisrows);
      
      //display.display();
      delay(1000);
      srand(analogRead(A0)+millis() );
      
      display.drawRect(0, 0, screenWidth+3, screenHeight+3, WHITE);
    
      // test
      // put_Glider(yvisrows-20, centerxcol);
      // put_GliderUp(10, centerxcol);
      
      int x=1, y=1;
      put_GliderGun( y, x );
      
      bool vanish=1;
      int deltaXY=10;
      put_GliderEater( 10 +y+deltaXY, 24 +x+deltaXY, vanish);
    
      vanish=0;
      deltaXY=33;
      put_GliderEater( 10 +y+deltaXY, 24 +x+deltaXY, vanish);
      
      drawBoard();
      delay(50);  
    }
    
    
    //---------------------------------------------------------------------------
    // loop
    //---------------------------------------------------------------------------
    void loop()
    {
        calculateGeneration();
        drawBoard();
        delay(100);
    }
    (Die "GliderGun" (s. Code) kann ja als Generator eines Bit-Streams verstanden werden, unklar ist mir aber, wie man sie a) mit Inputs moduliert, b) liest und c) Ergebnisse ermittelt und ausgibt)


    edit:
    habe jetzt einen Artikel gefunden:
    http://www.rennard.org/alife/english...tml#LCellFcnmt
    Geändert von HaWe (12.02.2019 um 20:27 Uhr)

  2. #2
    HaWe
    Gast
    kann jetzt eine GliderGun als Bit-Generator (b) und GliderEater bauen, die diese vernichten und die Vernichtung melden.
    Damit werden die Verknüpfungen (b AND TRUE) und/oder (b AND FALSE) generiert und ausgelesen.

    edit: bug fixed
    angeblich soll es 1 spez. Bit geben, das "glider zerstört" anzeigt, das finde ich aber nicht.
    Ich finde aber ein spezielles Bitmuster, das auch genau das tut, auch wenn ein Glider über einen inaktiven Eater fliegt:

    Code:
    // Arduino-Game-Of-Life
    
    // Game of life
    // http://en.wikipedia.org/wiki/Conway's_Game_of_Life
    // Code adapted from
    // http://cboard.cprogramming.com/c-programming/128982-simple-life-game-code-near-end.html
    // basic ideas courtesy of Xander Soldaat 
    // ported to Arduino by dsyleixa
    
    
    // MCU: Adafruit Feather M4
    
    // supported display:
    // Adafruit Featherwing TFT35
    // and different Afadruit-GFX-compatible ones 
    // (adjust libs+resolutions!)
    
    
    
    #include <Arduino.h>
    // i2c, SPI
    #include <Wire.h>         // Incl I2C comm, but needed for not getting compile error
    #include <SPI.h>
    
    
    //-----------------------------------------------------------------------
    // display driver
    //-----------------------------------------------------------------------
    #include <Adafruit_GFX.h>   // https://github.com/adafruit/Adafruit-GFX-Library 
    // Adafruit TFT35 LED driver
    
    #include <Adafruit_HX8357.h>
    #include <Adafruit_STMPE610.h>
     
    // fonts
    #include <Fonts/FreeSans9pt7b.h>             // optional
    #include <Fonts/FreeMono12pt7b.h>            // optional  
    #include <Fonts/FreeMono9pt7b.h>       // used here by default
    //#include <Fonts/FreeMonoBold7pt7b.h>    // optional, custom font
    
    // TFT pins
    #ifdef ESP8266
       #define STMPE_CS 16
       #define TFT_CS   0
       #define TFT_DC   15
       #define SD_CS    2
     
    #elif defined ESP32
       #define STMPE_CS 32
       #define TFT_CS   15
       #define TFT_DC   33
       #define SD_CS    14
     
    #elif defined TEENSYDUINO
       #define TFT_DC   10
       #define TFT_CS   4
       #define STMPE_CS 3
       #define SD_CS    8
      
    #elif defined ARDUINO_STM32_FEATHER
       #define TFT_DC   PB4
       #define TFT_CS   PA15
       #define STMPE_CS PC7
       #define SD_CS    PC5
      
    #elif defined ARDUINO_FEATHER52
       #define STMPE_CS 30
       #define TFT_CS   13
       #define TFT_DC   11
       #define SD_CS    27
    
    #elif  defined(ARDUINO_MAX32620FTHR) || defined(ARDUINO_MAX32630FTHR)
       #define TFT_DC   P5_4
       #define TFT_CS   P5_3
       #define STMPE_CS P3_3
       #define SD_CS    P3_2
    
    // Something else!
    #elif  defined (__AVR_ATmega32U4__) || defined(ARDUINO_SAMD_FEATHER_M0) || defined (__AVR_ATmega328P__) || defined(ARDUINO_SAMD_ZERO) || defined(__SAMD51__)   
       #define STMPE_CS 6
       #define TFT_CS   9
       #define TFT_DC   10
       #define SD_CS    5
    
     // default 
    #else
       #define STMPE_CS 6
       #define TFT_CS   9
       #define TFT_DC   10
       #define SD_CS    5
    #endif
    
    
    #define TFT_RST -1
    
    // display instance
    Adafruit_HX8357    display = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
    Adafruit_STMPE610  ts = Adafruit_STMPE610(STMPE_CS);
    
    
    // color defs
    
    #define BLACK       HX8357_BLACK
    #define DARKGREY    HX8357_DARKGREY 
    #define WHITE       HX8357_WHITE
    #define RED         HX8357_RED
    #define YELLOW      HX8357_YELLOW
    #define CYAN        HX8357_CYAN
    #define DARKCYAN    HX8357_DARKCYAN
    #define BLUE        HX8357_BLUE
    #define GREENYELLOW HX8357_GREENYELLOW
    
    #define COLOR_BKGR  BLACK
    
    int tftheight, 
        tftwidth;
    
    //---------------------------------------------------------------------------
    // preferences and settings
    //---------------------------------------------------------------------------
    // The blocks are blockSize * blockSize big
    // 2...6 seems to be a good value for this
    
    int blockSize = 4;
    
    
    
    // The size of the GoL screen window
    
    const int screenWidth = 240;   // <~~~~~~~~~~~~ adjust screen dimensions !
    const int screenHeight= 240;
    const int frame = 10;
    
    
    
    
    // Make the board larger on either side to ensure that there's an invisible border of dead cells
    
    int yvisrows = (screenHeight / blockSize);
    int xviscols = (screenWidth / blockSize);
    
    int yrows = yvisrows + 2*frame;
    int xcols = xviscols + 2*frame;
    
    #define centeryrow (yrows/2)-1 
    #define centerxcol (xcols/2)-1 
    
    // two boards, one for the current generation and one for calculating the next one
    char board[screenHeight + 2*frame][screenWidth + 2*frame];
    char tmpboard[screenHeight + 2*frame][screenWidth + 2*frame];
    
    
    //---------------------------------------------------------------------------
    // GoL functions
    //---------------------------------------------------------------------------
    
    uint32_t GenerationCnt=1;
    
        
    // Count thy neighbours
    int countNeighbours(int yrow, int xcol)
    {
      int count = 0;
      for (int x = -1; x <= +1; x++)  {
        for (int y = -1; y <= +1; y++) {
          if ((board[yrow + y][xcol + x] == 1) && (x != 0 || y != 0))
            count++;
        }
      }
      return count;
    }
    
    
    //---------------------------------------------------------------------------
    // Calculate the cells that will live and die for the next generation
    void calculateGeneration()
    {
      int aliveNeighbours = 0;
    
      // Clear the board for the next generation
      memset(tmpboard, 0, sizeof(tmpboard));
    
      for (int yrow = 1; yrow < (yrows-1); yrow++)  {
        for (int xcol = 1; xcol < (xcols-1); xcol++)   {
          aliveNeighbours = countNeighbours(yrow, xcol);
    
          // Any live cell with fewer than two live neighbours dies, as if caused by under-population.
          if(aliveNeighbours < 2)
            tmpboard[yrow][xcol] = 0;
    
          // Any live cell with two or three live neighbours lives on to the next calculateGeneration
          if (aliveNeighbours >= 2  &&  aliveNeighbours <= 3 )
            tmpboard[yrow][xcol] = board[yrow][xcol];
    
          // Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction
          if(aliveNeighbours == 3 && board[yrow][xcol]==0)
            tmpboard[yrow][xcol] = 1;
    
          // Any live cell with more than three live neighbours dies, as if by overcyrowding
          if(aliveNeighbours > 3)
            tmpboard[yrow][xcol] = 0;
        }
      }
      // Copy the new board to the old one
      memcpy(board, tmpboard, sizeof(tmpboard));
    }
    
    
    //---------------------------------------------------------------------------
    // Draw all the cells
    //---------------------------------------------------------------------------
    
    void drawBoard()
    {
      // Wipe the screen
      display.fillRect(1, 1, screenWidth+1, screenHeight+1, COLOR_BKGR);
        
      for (int yrow=frame; yrow <(yrows-frame); yrow++) { 
        for (int xcol=frame; xcol<(xcols-frame); xcol++)  {
          // Draw all the "live" cells.
          if (board[yrow][xcol])
            display.fillRect((xcol-frame+1)*blockSize, (yrow-frame+1)*blockSize, 
                              blockSize, blockSize, WHITE);
        }
      }
      //display.display();
    }
    
    
    //---------------------------------------------------------------------------
    // patterns
    //---------------------------------------------------------------------------
    
    int Eater1x, Eater1y, Eater2x, Eater2y;
    
    
    //---------------------------------------------------------------------------
    // This adds some random live cells to the board
    void put_randomBoard(int seedChance)
    {
      for (int yrow = 1; yrow < (yrows - 1); yrow++)
      {
        for (int xcol = 1; xcol < (xcols - 1); xcol++)
        {
          board[yrow][xcol] = !(rand() % seedChance);
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    
    void put_Blinker3x1(int starty, int startx) {       //  
     char sprite[1][5] = {  //  
        {1,1,1}
      } ;
    
      for(int x=0; x<3; ++x) {
           board[starty+frame][startx+frame+x]=sprite[0][x] ;
      }
    
      
    }
    
    //---------------------------------------------------------------------------
    void put_Block2x2(int starty, int startx) {       //  
    
      char sprite[2][2] = {  //  
        {1,1},
        {1,1}
      } ; 
    
      for(int x=0; x<2; ++x) {
        for(int y=0; y<2; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      } 
    }
    
    
    
    //---------------------------------------------------------------------------
    void put_Bar5x1(int starty, int startx) {       //  
    
      char sprite[1][5] = {  //  
        {1,1,1,1,1}
      } ;
    
      for(int x=0; x<5; ++x) {
           board[starty+frame][startx+frame+x]=sprite[0][x] ;
      }
    
      
    }
    
    
    //---------------------------------------------------------------------------
    void put_Clock(int starty, int startx) {    //  
      int x,y;
    
      char sprite[4][4] = {  //  
        {0,0,1,0},
        {1,1,0,0},
        {0,0,1,1},
        {0,1,0,0},
      } ;
    
      for(x=0; x<4; ++x) {
        for(y=0; y<4; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    
    void put_F_Pentomino(int starty, int startx) {    //  == R-Pentomino
      int x,y;
    
      char sprite[3][3] = {  //  
      {0,1,1},
      {1,1,0},
      {0,1,0},
      } ;
    
      for(x=0; x<3; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_Pi_Heptomino(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[3][5] = {  //  
      {0,0,1,0,0},
      {0,1,0,1,0},
      {1,1,0,1,1}
      } ;
    
      for(x=0; x<5; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_23334M(int starty, int startx) {    //  
      int x,y;
    
      char sprite[8][5] = {  //  
      {0,0,1,0,0},
      {1,1,0,0,0},
      {0,1,0,0,0},
      {1,0,0,1,0},
      {0,0,0,0,1},
      {0,1,0,0,1},
      {0,0,1,0,1},
      {0,1,0,0,0},
      } ;
    
      for(x=0; x<5; ++x) {
        for(y=0; y<8; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    
    //---------------------------------------------------------------------------
    void put_Glider(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[3][3] = {  //  
      {0,1,0,},
      {0,0,1,},
      {1,1,1,}
      } ;
      
      for(x=0; x<3; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    //---------------------------------------------------------------------------
    void put_GliderUp(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[3][3] = {  //  
      {0,1,1,},
      {1,0,1,},
      {0,0,1,}
      } ;
      
      for(x=0; x<3; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_LWSpaceship(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[4][5] = {  //  
      {1,0,0,1,0},
      {0,0,0,0,1},
      {1,0,0,0,1},
      {0,1,1,1,1},
    
      } ;
    
      for(x=0; x<5; ++x) {
        for(y=0; y<4; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_HWSpaceship(int starty, int startx) {    // 
    
      int x,y;
    
      char sprite[5][7] = {  //  
      {0,0,1,1,0,0,0},
      {0,0,0,0,0,1,0},
      {0,0,0,0,0,0,1},
      {1,0,0,0,0,0,1},
      {0,1,1,1,1,1,1},
    
      } ;
    
      for(x=0; x<7; ++x) {
        for(y=0; y<5; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void put_GliderGun(int starty, int startx) {  // Gosper Glider Gun, period=30
    
      int x,y;
    
      char sprite[9][37] = {  //  
      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
      {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
      {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
      {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
      } ;
      
      for(x=0; x<37; ++x) {   // NXT screen (0,0) is bottom left, not top left  !
        for(y=0; y<9; ++y) {
        
          board[starty+frame+y][startx+frame+x] = sprite[y][x] ;
        }
      }
    }
    
    //---------------------------------------------------------------------------
    void put_GliderEater(int starty, int startx, int V) {
      int x,y;
    
      char sprite[6][6] = {  //  
      {0 ,0 ,0 ,0 ,0 ,0 },    
      //~~~~~^               // returns 1=TRUE when glider destroyed   
      {0 ,1 ,1 ,0 ,0 ,0 },  
      {0 ,1 ,0 ,0 ,0 ,0 },
      {0 ,V ,1 ,1 ,1 ,0 },
      {0 ,0 ,0 ,0 ,1 ,0 },
      {0 ,0 ,0 ,0 ,0 ,0 }, 
      } ;
    
      for(x=0; x<6; ++x) {
        for(y=0; y<6; ++y) {      board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }  
    }
    
    //---------------------------------------------------------------------------
    bool get_GliderEater(int starty, int startx, int ID) {
       static uint32_t count=0;   
    
       
       bool isdestroyed= !board[starty+frame+0][startx+frame+0]                
                      &&  board[starty+frame+0][startx+frame+2]                  
                      && !board[starty+frame+1][startx+frame+0]
                      &&  board[starty+frame+1][startx+frame+2]
                      &&  board[starty+frame+2][startx+frame+1]
                      && !board[starty+frame+2][startx+frame+2];   
                       
       if(isdestroyed) {
          Serial.println( (String)(++count) 
                       + " gliders destroyed by Eater " +(String)ID 
                       + " generation=" +(String)GenerationCnt);
       }
       return isdestroyed;
    }
    
    
    
    
    //---------------------------------------------------------------------------
    // setup
    //---------------------------------------------------------------------------
    void setup() {
      Serial.begin(115200);
      delay(3000); // wait for Serial()
      Serial.println("Serial started");
      
      // Start Wire (SDA, SCL)
      Wire.begin();
    
      // TFT
      display.begin(HX8357D);    
      display.setRotation(1);
      tftheight=display.height(); 
      tftwidth =display.width();
      display.fillScreen(COLOR_BKGR);  // Clear Screen
    
      // text display tests
      display.setTextSize(1);
      display.setFont();
      display.setTextColor(WHITE);
      display.setCursor(0,0);
      display.println("This is ");  
      display.println("Conway's Game of Live");  
      display.setCursor(0,30);
      display.print("xcols="); display.println(xviscols);
      display.print("yrows="); display.println(yvisrows);
      
      //display.display();
      delay(1000);
      srand(analogRead(A0)+millis() );
      
      display.drawRect(0, 0, screenWidth+3, screenHeight+3, WHITE);
    
      // test
      // put_Glider(yvisrows-20, centerxcol);
      // put_GliderUp(10, centerxcol);
      
      int x=1, y=1;
      put_GliderGun( y, x );
    
      bool vanish;
      // Eater 1
      int deltaXY=10;
      Eater1y = 9 +y +deltaXY;
      Eater1x =23 +x +deltaXY;
      vanish=1;   // 0: GliderEater solid (active) - 1: GliderEater vanishes (inactive)
      put_GliderEater( Eater1y, Eater1x, vanish);
    
      // Eater 2
      deltaXY=22;
      Eater2y = 9 +y +deltaXY;
      Eater2x =23 +x +deltaXY;
      vanish=0;   // 0: GliderEater solid (active) - 1: GliderEater vanishes (inactive)
      put_GliderEater( Eater2y, Eater2x, vanish);
      
      drawBoard();
      delay(50);  
    }
    
    
    //---------------------------------------------------------------------------
    // loop
    //---------------------------------------------------------------------------
    void loop()
    {   volatile int ID;
        calculateGeneration();
        drawBoard();   
    
        // glider (bit) monitoring    
        ID=1;
        get_GliderEater(Eater1y, Eater1x, ID); // coordinates of Eater no.1
        delay(1);
        ID=2;
        get_GliderEater(Eater2y, Eater2x, ID); // coordinates of Eater no.2
    
        // generation monitor
        display.setCursor(0, display.height()-10);
        display.fillRect(0, tftheight-10, tftwidth-1, 10, COLOR_BKGR);
        GenerationCnt++;
        display.println((String)"Generation "+(String)GenerationCnt);  
    
        delay(100);
    }
    Geändert von HaWe (12.02.2019 um 20:27 Uhr)

  3. #3
    HaWe
    Gast
    so, isch abe fertisch!
    Ich habe es noch etwas erweitert im Vergleich zum obigen Link, mit einem zusätzlichen Clock-Ticker:
    Das Gate kann im Sync mit einem Clock Tick ausgelesen werden (praktisch für Monitoring, beeinflusst aber nicht die Gatter-Funktion, die jederzeit automatisch allein über die Conway-Vererbungsregeln funktioniert).

    Hier ein NOR-Gatter:
    4 (jetzt 5) Glider Guns:
    (Invert_Gun,) Input_A, Input_B, Gatter-Gun, Clock_Gun

    Prinzipiell sieht es ähnlich aus wie hier:
    Klicke auf die Grafik für eine größere Ansicht

Name:	or.gif
Hits:	19
Größe:	3,2 KB
ID:	33983

    und hier der Code - ich bin selber überrascht, dass es funktioniert!

    Code:
    // Conway's Game-Of-Life
    // as a Turing machine
    // Platform: Arduino
    
    // Game of life
    // http://en.wikipedia.org/wiki/Conway's_Game_of_Life
    // Code adapted from
    // http://cboard.cprogramming.com/c-programming/128982-simple-life-game-code-near-end.html
    // http://www.rennard.org/alife/english/logicellgb.html#LCellFcnmt 
    // (modified)
    // basic ideas courtesy of Xander Soldaat
    // ported to Arduino by dsyleixa
    
    
    // MCU: Adafruit Feather M4
    
    // supported display:
    // Adafruit Featherwing TFT35
    // and different Afadruit-GFX-compatible ones 
    // (adjust libs+resolutions!)
    //-----------------------------------------------------------------------
    // Simulation: NOR Gate
    //-----------------------------------------------------------------------
    
    //-----------------------------------------------------------------------
    // new: enhanced version to opt. also invert output (=> OR) 
    //-----------------------------------------------------------------------
    
    int blockSize = 2;
    
    
    
    #include <Arduino.h>
    // i2c, SPI
    #include <Wire.h>         // Incl I2C comm, but needed for not getting compile error
    #include <SPI.h>
    
    
    //-----------------------------------------------------------------------
    // display driver
    //-----------------------------------------------------------------------
    #include <Adafruit_GFX.h>   // https://github.com/adafruit/Adafruit-GFX-Library 
    // Adafruit TFT35 LED driver
    #include <Adafruit_HX8357.h>
    #include <Adafruit_STMPE610.h>
     
    // fonts
    #include <Fonts/FreeSans9pt7b.h>             // optional
    #include <Fonts/FreeMono12pt7b.h>            // optional  
    #include <Fonts/FreeMono9pt7b.h>       // used here by default
    //#include <Fonts/FreeMonoBold7pt7b.h>    // optional, custom font
    
    // TFT pins
    #ifdef ESP8266
       #define STMPE_CS 16
       #define TFT_CS   0
       #define TFT_DC   15
       #define SD_CS    2
     
    #elif defined ESP32
       #define STMPE_CS 32
       #define TFT_CS   15
       #define TFT_DC   33
       #define SD_CS    14
     
    #elif defined TEENSYDUINO
       #define TFT_DC   10
       #define TFT_CS   4
       #define STMPE_CS 3
       #define SD_CS    8
      
    #elif defined ARDUINO_STM32_FEATHER
       #define TFT_DC   PB4
       #define TFT_CS   PA15
       #define STMPE_CS PC7
       #define SD_CS    PC5
      
    #elif defined ARDUINO_FEATHER52
       #define STMPE_CS 30
       #define TFT_CS   13
       #define TFT_DC   11
       #define SD_CS    27
    
    #elif  defined(ARDUINO_MAX32620FTHR) || defined(ARDUINO_MAX32630FTHR)
       #define TFT_DC   P5_4
       #define TFT_CS   P5_3
       #define STMPE_CS P3_3
       #define SD_CS    P3_2
    
    // Something else!
    #elif  defined (__AVR_ATmega32U4__) || defined(ARDUINO_SAMD_FEATHER_M0) || defined (__AVR_ATmega328P__) || defined(ARDUINO_SAMD_ZERO) || defined(__SAMD51__)   
       #define STMPE_CS 6
       #define TFT_CS   9
       #define TFT_DC   10
       #define SD_CS    5
    
     // default 
    #else // to be adjusted
       #define STMPE_CS 6
       #define TFT_CS   9
       #define TFT_DC   10
       #define SD_CS    5
    #endif
    
    #define TFT_RST -1
    
    // display instance
    Adafruit_HX8357    display = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
    Adafruit_STMPE610  ts = Adafruit_STMPE610(STMPE_CS);
    
    
    // color defs 16bit
    
    #define  WHITE       0xFFFF  ///< 255, 255, 255
    #define  LIGHTGRAY   0xC618  ///< 198, 195, 198
    #define  GRAY        0x7BEF  ///< 123, 125, 123
    #define  DARKGRAY    0x39E7  ///<  63,  63,  63  
    #define  BLACK       0x0000  ///<   0,   0,   0
    #define  RED         0xF800  ///< 255,   0,   0
    #define  MAROON      0x7800  ///< 123,   0,   0
    #define  ORANGE      0xFD20  ///< 255, 165,   0
    #define  YELLOW      0xFFE0  ///< 255, 255,   0
    #define  GREENYELLOW 0xAFE5  ///< 173, 255,  41
    #define  LIME        0x07E0  ///<   0, 255,   0
    #define  GREEN       0x03E0  ///<   0, 125,   0  
    #define  DARKGREEN   0x01E0  ///<   0,  63,   0   
    #define  CYAN        0x07FF  ///<   0, 255, 255
    #define  DARKCYAN    0x03EF  ///<   0, 125, 123
    #define  OLIVE       0x7BE0  ///< 123, 125,   0
    #define  BLUE        0x001F  ///<   0,   0, 255
    #define  NAVY        0x000F  ///<   0,   0, 123
    #define  PINK        0xFC18  ///< 255, 130, 198
    #define  MAGENTA     0xF81F  ///< 255,   0, 255
    #define  PURPLE      0x780F  ///< 123,   0, 123
    
    
    #define  COLOR_BKGR  BLACK
    
    int tftheight, 
        tftwidth;
    
    //---------------------------------------------------------------------------
    // preferences and settings
    //---------------------------------------------------------------------------
    
    // The size of the GoL screen window
    
    const int GOLwindowWidth = 420;   // <~~~~~~~~~~~~ adjust GOL window dimensions !
    const int GOLwindowHeight= 190;
    const int frame = 10;
    
    
    //enlarge on either side to create an invisible border of dead cells
    
    int yvisrows = (GOLwindowHeight / blockSize);
    int xviscols = (GOLwindowWidth / blockSize);
    
    int yrows = yvisrows + 2*frame;
    int xcols = xviscols + 2*frame;
    
    #define centeryrow (yrows/2)
    #define centerxcol (xcols/2)
    
    // two boards, one for the current generation and one for calculating the next one
    char board[GOLwindowHeight + 2*frame][GOLwindowWidth + 2*frame];
    char tmpboard[GOLwindowHeight + 2*frame][GOLwindowWidth + 2*frame];
    
    
    //---------------------------------------------------------------------------
    // GoL functions
    //---------------------------------------------------------------------------
    
    uint32_t GenerationCnt=1;
        
    // Count neighbours
    int countNeighbours(int yrow, int xcol)
    {
      int count = 0;
      for (int x = -1; x <= +1; x++)  {
        for (int y = -1; y <= +1; y++) {
          if ((board[yrow + y][xcol + x] == 1) && (x != 0 || y != 0))
            count++;
        }
      }
      return count;
    }
    
    
    //---------------------------------------------------------------------------
    // Calculate the cells that will live and die for the next generation
    void calculateGeneration()
    {
      int aliveNeighbours = 0;
    
      // Clear the board for the next generation
      memset(tmpboard, 0, sizeof(tmpboard));
    
      for (int yrow = 1; yrow < (yrows-1); yrow++)  {
        for (int xcol = 1; xcol < (xcols-1); xcol++)   {
          aliveNeighbours = countNeighbours(yrow, xcol);
    
          // a live cell with < 2 live neighbours dies, as if caused by under-population.
          if( board[yrow][xcol]==1 && aliveNeighbours < 2 )
            tmpboard[yrow][xcol] = 0;
    
          // a live cell with 2 or 3 live neighbours lives on to the next Generation
          if ( board[yrow][xcol]==1 && aliveNeighbours >= 2  &&  aliveNeighbours <= 3 )
            tmpboard[yrow][xcol] = board[yrow][xcol];
    
          // a dead cell with exactly 3 live neighbours becomes alive, as if by reproduction
          if( board[yrow][xcol]==0 && aliveNeighbours == 3 )
            tmpboard[yrow][xcol] = 1;
    
          // a live cell with > 3 live neighbours dies, as if by overcrowding
          if( board[yrow][xcol]==1 && aliveNeighbours > 3 )
            tmpboard[yrow][xcol] = 0;
        }
      }
      // Copy the new board to the old one
      memcpy(board, tmpboard, sizeof(tmpboard));
    }
    
    
    //---------------------------------------------------------------------------
    // Draw all the cells
    //---------------------------------------------------------------------------
    
    void drawBoard()
    {
      // Wipe the GOLwindow
      display.fillRect(1, 1, GOLwindowWidth+1, GOLwindowHeight+1, COLOR_BKGR);
        
      for (int yrow=frame; yrow <(yrows-frame); yrow++) { 
        for (int xcol=frame; xcol<(xcols-frame); xcol++)  {
          // Draw all the "live" cells.
          if (board[yrow][xcol])
            display.fillRect((xcol-frame+1)*blockSize, (yrow-frame+1)*blockSize, 
                              blockSize, blockSize, WHITE);
        }
      }
      //display.display();
    }
    
    
    //---------------------------------------------------------------------------
    // patterns
    //---------------------------------------------------------------------------
    
    
    //---------------------------------------------------------------------------
    void poke_Glider(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[3][3] = {  //  
      {0,1,0,},
      {0,0,1,},
      {1,1,1,}
      } ;
      
      for(x=0; x<3; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    //---------------------------------------------------------------------------
    void poke_GliderUp(int starty, int startx) {    //  
    
      int x,y;
    
      char sprite[3][3] = {  //  
      {0,1,1,},
      {1,0,1,},
      {0,0,1,}
      } ;
      
      for(x=0; x<3; ++x) {
        for(y=0; y<3; ++y) {
          board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void poke_GliderGun(int starty, int startx) {  // Gosper Glider Gun, period=30
    
      int x,y;
    
      char sprite[9][37] = {  //  
      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
      {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
      {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
      {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
      } ;
      
      for(x=0; x<37; ++x) {    
        for(y=0; y<9; ++y) {
        
          board[starty+frame+y][startx+frame+x] = sprite[y][x] ;
        }
      }
    }
    
    
    //---------------------------------------------------------------------------
    void poke_GliderGunRev(int starty, int startx) {  // Gosper Glider Gun, period=30
    
      int x,y;
    
      char sprite[9][37] = {  //  
      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
      {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
      {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
      {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
      } ;
      
      for(x=0; x<37; ++x) {    
        for(y=0; y<9; ++y) {
        
          board[starty+frame+y][startx+frame+x] = sprite[y][37-x] ;
        }
      }
    }
    
    //---------------------------------------------------------------------------
    void poke_GliderEater(int starty, int startx, int V) { // V=input; 0=stable, 1=vanish
      int x,y;
    
      char sprite[6][6] = {  //  
      {0 ,0 ,0 ,0 ,0 ,0 },     
      {0 ,1 ,1 ,0 ,0 ,0 },  
      {0 ,1 ,0 ,0 ,0 ,0 },
      {0 ,V ,1 ,1 ,1 ,0 },   // <~~~ V=input
      {0 ,0 ,0 ,0 ,1 ,0 },
      {0 ,0 ,0 ,0 ,0 ,0 }, 
      } ;
    
      for(x=0; x<6; ++x) {
        for(y=0; y<6; ++y) {      
           board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }  
    }
    
    //---------------------------------------------------------------------------
    void poke_GliderEaterRev(int starty, int startx, int V) {  // V=input; 0=stable, 1=vanish
      int x,y;
    
      char sprite[6][6] = {  //  
      {0 ,0 ,0 ,0 ,0 ,0 },     
      {0 ,0 ,0 ,1 ,1 ,0 },  
      {0 ,0 ,0 ,0 ,1 ,0 },
      {0 ,1 ,1 ,1 ,V ,0 },   // <~~~ V=input 
      {0 ,1 ,0 ,0 ,0 ,0 },
      {0 ,0 ,0 ,0 ,0 ,0 }, 
      } ;
    
      for(x=0; x<6; ++x) {
        for(y=0; y<6; ++y) {      
           board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
        }
      }  
    }
    
    //---------------------------------------------------------------------------
    bool peek_GliderEater(int starty, int startx, int ID) {
       
       bool isdestroyed= !board[starty+frame+0][startx+frame+0]                
                      &&  board[starty+frame+0][startx+frame+2]                  
                      && !board[starty+frame+1][startx+frame+0]
                      &&  board[starty+frame+1][startx+frame+2]
                      &&  board[starty+frame+2][startx+frame+1]
                      && !board[starty+frame+2][startx+frame+2];  
    
       //debug       
       //if(isdestroyed) { Serial.println( "ID " +(String)ID + " Input=FALSE =>  OUT=FALSE " + " gen=" +(String)GenerationCnt); }
       
       return isdestroyed;
    }
    
    //---------------------------------------------------------------------------
    bool peek_GliderEaterRev(int starty, int startx, int ID) {
       
       bool isdestroyed= !board[starty+frame+0][startx+frame+5-0]                
                      &&  board[starty+frame+0][startx+frame+5-2]                  
                      && !board[starty+frame+1][startx+frame+5-0]
                      &&  board[starty+frame+1][startx+frame+5-2]
                      &&  board[starty+frame+2][startx+frame+5-1]
                      && !board[starty+frame+2][startx+frame+5-2];  
          
       return isdestroyed;
    }
    
    //---------------------------------------------------------------------------
    bool InputA, InputB;
    
    int  Eatercx, Eatercy,                    // CLOCK
         Eater0x, Eater0y,                    // Inverter
         Eater1x, Eater1y, Eater2x, Eater2y,  // A, B
         Eater3x, Eater3y ;                   // GATE
    
    bool ClockTick=0;
    
    
    //---------------------------------------------------------------------------
    void labelBoard() {
         display.setFont(&FreeMono9pt7b);
         display.setTextColor(ORANGE);  display.setCursor(5,19*blockSize); 
         display.print("^GUN"); //  not in use for "NOR", but used for "OR"
         display.setTextColor(LIME); display.setCursor(28+1*blockSize*39,19*blockSize); 
         display.print("A");
         display.setTextColor(LIME); display.setCursor(28+2*blockSize*39,19*blockSize); 
         display.print("B");
         display.setTextColor(ORANGE); display.setCursor(28+3*blockSize*39,19*blockSize); 
         display.print("GUN");     
         display.setTextColor(YELLOW); display.setCursor(68*blockSize, 80*blockSize ); 
         display.print("GATE");
         display.setTextColor(BLUE); display.setCursor(28+4*blockSize*39,19*blockSize); 
         display.print("CLK");
    }
    
    
    //---------------------------------------------------------------------------
    void ResetGate() {
      
      int yc= 1, xc=(37+2)*4,    // CLOCK
          y0= 1, x0=0,
          y1= 1, x1=1+(37+2)*1,  // A
          y2= 1, x2=(37+2)*2,    // B
          y3= 1, x3=(37+2)*3 ;   // GATE
          
      int deltaXY;  
    
      memset(board, 0, sizeof(board));
      memset(tmpboard, 0, sizeof(tmpboard));
      display.fillRect(1, 1, GOLwindowWidth+1, GOLwindowHeight+1, COLOR_BKGR);
      
      
      // --------------------------------- 
      poke_GliderGun( y0, x0 );    // InvertGATE 
      // Gun Eater 1
      deltaXY=4;          // no InvertGATE
      //deltaXY=37+20;      // InvertGATE instead of GATE
      Eater0y = 9 +y0 +deltaXY;
      Eater0x =23 +x0 +deltaXY;     
      // 0: GliderEater solid (active) 
      poke_GliderEater( Eater0y, Eater0x, 0);
      
    
      // --------------------------------- 
      poke_GliderGun( y1, x1 );    // Input A 
      // Gun Eater 1
      deltaXY=4;
      Eater1y = 9 +y1 +deltaXY;
      Eater1x =23 +x1 +deltaXY;  
      // input 0: GliderEater active => output 0 (blocked)
      
      InputA=0;  
      poke_GliderEater( Eater1y, Eater1x, InputA);
      poke_GliderEater( Eater1y+37, Eater1x+37, 0); // infinity blocker
    
    
      // ---------------------------------
      poke_GliderGun( y2, x2 );    // Input B
      // Gun Eater 2
      deltaXY=4;
      Eater2y = 9 +y2 +deltaXY;
      Eater2x =23 +x2 +deltaXY;
      // 0: Glider blocked - 1: Glider passes
      
      InputB=0;  
      poke_GliderEater( Eater2y, Eater2x, InputB);    
    
      
      // ---------------------------------
      poke_GliderGunRev( y3, x3 ); // GATE
      // Gun Eater 3 = gate detector
      deltaXY=37+20;
      Eater3y =  9     +y3 +deltaXY;
      Eater3x = 23-14  +x3 -deltaXY;
      // 0: GliderEater always solid (active)  
      poke_GliderEaterRev( Eater3y, Eater3x, 0);
    
    
      // ---------------------------------
      poke_GliderGunRev( yc, xc );      // CLOCK: duplicate of GATE, different x/y offsets
      // Gun Eater 0 = clock detector
      deltaXY=37+20;
      Eatercy =  9     +yc +deltaXY;
      Eatercx = 23-14  +xc -deltaXY;
      // 0: GliderEater solid (active)  
      poke_GliderEaterRev( Eatercy, Eatercx, 0);
      
         
      // ---------------------------------
      drawBoard();
      labelBoard();
      
      delay(1);  
    }
    
    
    //---------------------------------------------------------------------------
    // setup
    //---------------------------------------------------------------------------
    void setup() {
      Serial.begin(115200);
      delay(3000); // wait for Serial()
      Serial.println("Serial started");
      
      // Start Wire (SDA, SCL)
      Wire.begin();
    
      // TFT
      display.begin(HX8357D);    
      display.setRotation(1);
      tftheight=display.height(); 
      tftwidth =display.width();
      display.fillScreen(COLOR_BKGR);  // Clear Screen
    
      // text display tests
      display.setTextSize(1);
      display.setFont();
      display.setTextColor(WHITE);
      display.setCursor(0,0);
      display.println("This is ");  
      display.println("Conway's Game of Live");  
      display.setCursor(0,30);
      display.print("xcols="); display.println(xviscols);
      display.print("yrows="); display.println(yvisrows);  
      //display.display();
      delay(1000);
      
      srand(analogRead(A0)+millis() );  
      display.drawRect(0, 0, GOLwindowWidth+3, GOLwindowHeight+3, WHITE);
    
      ResetGate();   
      
    }
    
    
    
    //---------------------------------------------------------------------------
    // loop
    //---------------------------------------------------------------------------
    void loop()
    {   
        int ID;    
        static int8_t  GATE=-1;  // init as -1=undefined; 1=true, 0=false;
        static uint32_t ticker=0, period=0, counter=0;
    
        display.setFont(&FreeMono12pt7b);
        display.setCursor(0, display.height()-20);
        display.setTextColor(YELLOW);    
        display.print("NOR");   
            
        calculateGeneration();
        drawBoard();  
        labelBoard();    
        
         
        // Input Simulation
    
        if(counter>=1600) counter=0;
        
        if(counter==0)   { 
          ResetGate();
          GATE=-1;
          ticker=0; 
          InputA=0; InputB=0;  
          poke_GliderEater( Eater1y, Eater1x, InputA); 
          poke_GliderEater( Eater2y, Eater2x, InputB);
          Serial.println();
          Serial.println("processing...  A="+(String)InputA + " B="+(String)InputB ); 
          display.fillRect(220, tftheight-34, tftwidth-220, 34, COLOR_BKGR); 
                display.setCursor(220, tftheight-20);
                display.print("  A="+(String)InputA + " B="+(String)InputB  + " processing...");             
        } 
        
        if(counter==400)   {      
          ResetGate(); 
          GATE=-1;
          ticker=0; 
          InputA=0; InputB=1;
          poke_GliderEater( Eater1y, Eater1x, InputA); 
          poke_GliderEater( Eater2y, Eater2x, InputB);
          Serial.println();
          Serial.println("processing...  A="+(String)InputA + " B="+(String)InputB );      
          display.fillRect(220, tftheight-34, tftwidth-220, 34, COLOR_BKGR); 
                display.setCursor(220, tftheight-20);
                display.print("  A="+(String)InputA + " B="+(String)InputB  + " processing...");        
        } 
    
        if(counter==800)   { 
          ResetGate();
          GATE=-1;
          ticker=0; 
          InputA=1; InputB=0;  
          poke_GliderEater( Eater1y, Eater1x, InputA); 
          poke_GliderEater( Eater2y, Eater2x, InputB);
          Serial.println();
          Serial.println("processing...  A="+(String)InputA + " B="+(String)InputB );          
          display.fillRect(220, tftheight-34, tftwidth-220, 34, COLOR_BKGR); 
                display.setCursor(220, tftheight-20);
                display.print("  A="+(String)InputA + " B="+(String)InputB  + " processing...");        
        } 
        
        if(counter==1200)   { 
          ResetGate();
          GATE=-1;
          ticker=0; 
          InputA=1; InputB=1;
          poke_GliderEater( Eater1y, Eater1x, InputA); 
          poke_GliderEater( Eater2y, Eater2x, InputB);
          Serial.println();
          Serial.println("processing...  A="+(String)InputA + " B="+(String)InputB );      
          display.fillRect(220, tftheight-34, tftwidth-220, 34, COLOR_BKGR); 
                display.setCursor(220, tftheight-20);
                display.print("  A="+(String)InputA + " B="+(String)InputB  + " processing...");        
        } 
        
        display.setTextColor(WHITE);
        //---------------------------------
        // debug: only for screen messages, not for functionality    
        // outcomment optionally:    
           
            // get clock signal
            ID=-1;  ClockTick= peek_GliderEaterRev(Eatercy, Eatercx, ID); // Eater no.-1 (c=CLOCK)  
    
            // show A(1) + B(2) gun eater states      
            ID=1;   peek_GliderEater(Eater1y, Eater1x, ID); // Eater no.1 (B)    
            ID=2;   peek_GliderEater(Eater2y, Eater2x, ID); // Eater no.2 (A)
    
            if(ClockTick) {   
               GATE= peek_GliderEaterRev(Eater3y, Eater3x, ID); // Eater no.3 (GATE)    
            }
           
            // show current gate states on screen
            display.setFont(&FreeMono12pt7b);
            display.setTextColor(WHITE); 
            display.setCursor(80, display.height()-20);
            display.fillRect(80, tftheight-34, 140, 34, COLOR_BKGR);  
            display.print(GenerationCnt); 
            
            if(ClockTick) {
                Serial.println("  A="+(String)InputA + " B="+(String)InputB  
                    + " => GATE=" + (String)GATE + "     count="+(String)counter);
                    
                display.fillRect(220, tftheight-34, tftwidth-220, 34, COLOR_BKGR); 
                display.setCursor(220, tftheight-20);
                display.setTextColor(YELLOW);
                display.print("A="+(String)InputA + " B="+(String)InputB  
                    + " => GATE=" + (String)GATE);
            }
         
        // end debug
        //---------------------------------     
            
        counter++;
        ticker++;      
        GenerationCnt++; 
        
        delay(1);  // <~~~~~~~~~~ adjust for slow motion
    }
    
    
    
    //--------------------------------- 
    // EOF
    //---------------------------------
    aktualisierte Codes, jetzt auch für "NOT", "OR", "AND" und "NAND":
    https://github.com/dsyleixa/Arduino/...waysGameOfLife
    Geändert von HaWe (15.02.2019 um 17:26 Uhr) Grund: aufgehübscht

Ähnliche Themen

  1. Antworten: 10
    Letzter Beitrag: 01.11.2017, 13:53
  2. Conway's Game of Life auf einem ATmega32
    Von Torrentula im Forum C - Programmierung (GCC u.a.)
    Antworten: 17
    Letzter Beitrag: 18.11.2011, 10:38
  3. Antworten: 2
    Letzter Beitrag: 15.06.2011, 22:18
  4. RP6Control M32: Conway's Game Of Life
    Von Dirk im Forum Robby RP6
    Antworten: 3
    Letzter Beitrag: 02.05.2011, 20:41
  5. [Erste Schritte] IR-Tag-Game -"Lasertag"
    Von nietzsche im Forum Vorstellung+Bilder+Ideen zu geplanten eigenen Projekten/Bots
    Antworten: 7
    Letzter Beitrag: 09.06.2009, 00:52

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress