@@ -8,14 +8,10 @@ program game_of_life
88
99 implicit none
1010
11- ! ! Board args
12- integer , parameter :: max_generations = 100 , max_nrows = 100 , max_ncols = 100
13- integer :: nrow, ncol, generation_number
14- integer , dimension (:,:), allocatable :: current_board, new_board
15- logical :: steady_state = .false.
16-
17- ! > Whether to animate the board
1811 logical , parameter :: animate = .true.
12+ integer , dimension (:,:), allocatable :: starting_board
13+ integer :: generation_number
14+ logical :: steady_state = .false.
1915
2016 ! ! CLI args
2117 character (len= :), allocatable :: executable_name, input_filename
@@ -30,9 +26,9 @@ program game_of_life
3026 stop
3127 end if
3228
33- call read_model_from_file()
29+ call read_model_from_file(input_filename, starting_board )
3430
35- call find_steady_state()
31+ call find_steady_state(steady_state, generation_number, starting_board, animate )
3632
3733 if (steady_state) then
3834 write (* ,' (a,i6,a)' ) " Reached steady after " , generation_number, " generations"
@@ -43,7 +39,7 @@ program game_of_life
4339contains
4440
4541 ! > Read a cli arg at a given index and return it as a string (character array)
46- recursive subroutine read_cli_arg (arg_index , arg )
42+ subroutine read_cli_arg (arg_index , arg )
4743 ! > The index of the cli arg to try and read
4844 integer , intent (in ) :: arg_index
4945 ! > The string into which to store the cli arg
@@ -59,12 +55,16 @@ recursive subroutine read_cli_arg(arg_index, arg)
5955 end subroutine read_cli_arg
6056
6157 ! > Populate the board from a provided file
62- subroutine read_model_from_file ()
58+ subroutine read_model_from_file (input_filename , board )
59+ character (len= :), allocatable , intent (in ) :: input_filename
60+ integer , dimension (:,:), allocatable , intent (out ) :: board
61+
6362 ! > A flag to indicate if reading the file was successful
6463 character (len= :), allocatable :: io_error_message
6564
6665 ! Board definition args
67- integer :: row
66+ integer :: row, nrow, ncol
67+ integer , parameter :: max_nrows = 100 , max_ncols = 100
6868
6969 ! File IO args
7070 integer :: input_file_io, iostat
@@ -98,12 +98,12 @@ subroutine read_model_from_file()
9898
9999 if (.not. allocated (io_error_message)) then
100100
101- allocate (current_board (nrow, ncol))
101+ allocate (board (nrow, ncol))
102102
103103 read (input_file_io,' (a)' ) text_to_discard ! Skip next line
104104 ! Populate the boards starting state
105105 do row = 1 , nrow
106- read (input_file_io,* ) current_board (row, :)
106+ read (input_file_io,* ) board (row, :)
107107 end do
108108
109109 end if
@@ -118,14 +118,27 @@ subroutine read_model_from_file()
118118 end subroutine read_model_from_file
119119
120120 ! > Find the steady state of the Game of Life board
121- subroutine find_steady_state ()
121+ subroutine find_steady_state (steady_state , generation_number , input_board , animate )
122+ ! > Whether the board has reached a steady state
123+ logical , intent (out ) :: steady_state
124+ ! > The number of generations that have been processed
125+ integer , intent (out ) :: generation_number
126+ ! > The starting state of the board
127+ integer , dimension (:,:), allocatable , intent (in ) :: input_board
128+ ! > Whether to animate the board
129+ logical , intent (in ) :: animate
130+
131+ integer , dimension (:,:), allocatable :: current_board, new_board
132+ integer , parameter :: max_generations = 100
122133
123134 ! ! Animation args
124135 integer , dimension (8 ) :: date_time_values
125136 integer :: mod_ms_step
126137 integer , parameter :: ms_per_step = 250
127138
128- allocate (new_board(size (current_board,1 ), size (current_board, 2 )))
139+ allocate (current_board(size (input_board,1 ), size (input_board, 2 )))
140+ allocate (new_board(size (input_board,1 ), size (input_board, 2 )))
141+ current_board = input_board
129142 new_board = 0
130143
131144 ! Clear the terminal screen
@@ -143,10 +156,10 @@ subroutine find_steady_state()
143156 end if
144157
145158 if (mod_ms_step == 0 ) then
146- call evolve_board()
147- call check_for_steady_state()
159+ call evolve_board(current_board, new_board )
160+ call check_for_steady_state(steady_state, current_board, new_board )
148161 current_board = new_board
149- if (animate) call draw_board()
162+ if (animate) call draw_board(current_board )
150163
151164 generation_number = generation_number + 1
152165 end if
@@ -155,8 +168,16 @@ subroutine find_steady_state()
155168 end subroutine find_steady_state
156169
157170 ! > Evolve the board into the state of the next iteration
158- subroutine evolve_board ()
159- integer :: row, col, sum
171+ subroutine evolve_board (current_board , new_board )
172+ ! > The current state of the board
173+ integer , dimension (:,:), allocatable , intent (in ) :: current_board
174+ ! > The new state of the board
175+ integer , dimension (:,:), allocatable , intent (inout ) :: new_board
176+
177+ integer :: row, col, sum, nrow, ncol
178+
179+ nrow = size (current_board, 1 )
180+ ncol = size (current_board, 2 )
160181
161182 do row= 2 , nrow-1
162183 do col= 2 , ncol-1
@@ -185,8 +206,18 @@ subroutine evolve_board()
185206 end subroutine evolve_board
186207
187208 ! > Check if we have reached steady state, i.e. current and new board match
188- subroutine check_for_steady_state ()
189- integer :: row, col
209+ subroutine check_for_steady_state (steady_state , current_board , new_board )
210+ ! > Whether the board has reached a steady state
211+ logical , intent (out ) :: steady_state
212+ ! > The current state of the board
213+ integer , dimension (:,:), allocatable , intent (in ) :: current_board
214+ ! > The new state of the board
215+ integer , dimension (:,:), allocatable , intent (inout ) :: new_board
216+
217+ integer :: row, col, nrow, ncol
218+
219+ nrow = size (current_board, 1 )
220+ ncol = size (current_board, 2 )
190221
191222 do row= 1 , nrow
192223 do col= 1 , ncol
@@ -200,17 +231,25 @@ subroutine check_for_steady_state()
200231 end subroutine check_for_steady_state
201232
202233 ! > Output the current board to the terminal
203- subroutine draw_board ()
204- integer :: row, col
205- character (nrow) :: output
234+ subroutine draw_board (board )
235+ ! > The current state of the board
236+ integer , dimension (:,:), allocatable , intent (in ) :: board
237+
238+ integer :: row, col, nrow, ncol
239+ character (:), allocatable :: output
240+
241+ nrow = size (board, 1 )
242+ ncol = size (board, 2 )
243+
244+ allocate (character (nrow) :: output)
206245
207246 ! Clear the terminal screen
208247 call system(" clear" )
209248
210249 do row= 1 , nrow
211250 output = " "
212251 do col= 1 , ncol
213- if (current_board (row,col) == 1 ) then
252+ if (board (row,col) == 1 ) then
214253 output = trim (output)// " #"
215254 else
216255 output = trim (output)// " ."
0 commit comments