How to resolve the algorithm Conway's Game of Life step by step in the Fortran programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Conway's Game of Life step by step in the Fortran programming language

Table of Contents

Problem Statement

The Game of Life is a   cellular automaton   devised by the British mathematician   John Horton Conway   in 1970.   It is the best-known example of a cellular automaton. Conway's game of life is described   here: A cell   C   is represented by a   1   when alive,   or   0   when dead,   in an   m-by-m   (or m×m)   square array of cells. We calculate   N   - the sum of live cells in C's   eight-location neighbourhood,   then cell   C   is alive or dead in the next generation based on the following table: Assume cells beyond the boundary are always dead. The "game" is actually a zero-player game, meaning that its evolution is determined by its initial state, needing no input from human players.   One interacts with the Game of Life by creating an initial configuration and observing how it evolves.

Although you should test your implementation on more complex examples such as the   glider   in a larger universe,   show the action of the blinker   (three adjoining cells in a row all alive),   over three generations, in a 3 by 3 grid.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Conway's Game of Life step by step in the Fortran programming language

Source code in the fortran programming language

 PROGRAM LIFE_2D
   IMPLICIT NONE
 
   INTEGER, PARAMETER :: gridsize = 10
   LOGICAL :: cells(0:gridsize+1,0:gridsize+1) = .FALSE.
   INTEGER :: i, j, generation=0
   REAL :: rnums(gridsize,gridsize)
 
 !  Start patterns
 !  **************
 !  cells(2,1:3) = .TRUE.                                                  ! Blinker
 !  cells(3,4:6) = .TRUE. ; cells(4,3:5) = .TRUE.                          ! Toad
 !  cells(1,2) = .TRUE. ; cells(2,3) = .TRUE. ; cells(3,1:3) = .TRUE.      ! Glider
    cells(3:5,3:5) = .TRUE. ; cells(6:8,6:8) = .TRUE.                      ! Figure of Eight
 !  CALL RANDOM_SEED
 !  CALL RANDOM_NUMBER(rnums)
 !  WHERE (rnums>0.6) cells(1:gridsize,1:gridsize) = .TRUE.                ! Random universe
   
   CALL Drawgen(cells(1:gridsize, 1:gridsize), generation)
   DO generation = 1, 8
      CALL NextgenV2(cells)
      CALL Drawgen(cells(1:gridsize, 1:gridsize), generation)
   END DO
 
 CONTAINS
 
   SUBROUTINE Drawgen(cells, gen)
     LOGICAL, INTENT(IN OUT) :: cells(:,:)
     INTEGER, INTENT(IN) :: gen
 
     WRITE(*, "(A,I0)") "Generation ", gen 
     DO i = 1, SIZE(cells,1)
        DO j = 1, SIZE(cells,2)
           IF (cells(i,j)) THEN
              WRITE(*, "(A)", ADVANCE = "NO") "#"
           ELSE
              WRITE(*, "(A)", ADVANCE = "NO") " "
           END IF
        END DO
        WRITE(*,*)
     END DO
     WRITE(*,*)
   END SUBROUTINE Drawgen
 
  SUBROUTINE Nextgen(cells)
     LOGICAL, INTENT(IN OUT) :: cells(0:,0:)
     LOGICAL :: buffer(0:SIZE(cells, 1)-1, 0:SIZE(cells, 2)-1)
     INTEGER :: neighbours, i, j
   
     buffer = cells   ! Store current status
     DO j = 1, SIZE(cells, 2)-2
        DO i = 1, SIZE(cells, 1)-2
          if(buffer(i, j)) then
            neighbours = sum(count(buffer(i-1:i+1, j-1:j+1), 1)) - 1
          else
            neighbours = sum(count(buffer(i-1:i+1, j-1:j+1), 1))
          end if
  
          SELECT CASE(neighbours)
            CASE (0:1, 4:8)
               cells(i,j) = .FALSE.
  
            CASE (2)
               ! No change
  
            CASE (3)
               cells(i,j) = .TRUE.
          END SELECT
          
        END DO
     END DO
  END SUBROUTINE Nextgen

!###########################################################################
!   In this version instead of cycling through all points an integer array
! is used the sum the live neighbors of all points. The sum is done with
! the entire array cycling through the eight positions of the neighbors.
!   Executing a grid size of 10000 in 500 generations this version gave a 
! speedup of almost 4 times.
!###########################################################################
  PURE SUBROUTINE NextgenV2(cells)
     LOGICAL, INTENT(IN OUT) :: cells(:,:)
     INTEGER(KIND=1) :: buffer(1:SIZE(cells, 1)-2,1:SIZE(cells, 2)-2)
     INTEGER :: gridsize, i, j
     
     gridsize=SIZE(cells, 1)
     buffer=0
     
     DO j=-1, 1
        DO i=-1,1
           IF(i==0 .AND. j==0) CYCLE
           WHERE(cells(i+2:gridsize-i-1,j+2:gridsize-j-1)) buffer=buffer+1
        END DO
     END DO

     WHERE(buffer<2 .or. buffer>3) cells(2:gridsize-1,2:gridsize-1) = .FALSE.
     WHERE(buffer==3) cells(2:gridsize-1,2:gridsize-1) = .TRUE.
  END SUBROUTINE NextgenV2
!###########################################################################
 END PROGRAM LIFE_2D


  

You may also check:How to resolve the algorithm Horner's rule for polynomial evaluation step by step in the FreeBASIC programming language
You may also check:How to resolve the algorithm Factors of a Mersenne number step by step in the Tcl programming language
You may also check:How to resolve the algorithm Literals/String step by step in the Erlang programming language
You may also check:How to resolve the algorithm Naming conventions step by step in the zkl programming language
You may also check:How to resolve the algorithm Check that file exists step by step in the UNIX Shell programming language