8
\$\begingroup\$

Just for fun I have written a Conway's Game of Life in cmd batch file. I like writing in batch - its restrictions and limits are its appeal.

However - it is slow, very slow on a large grid. Any tips to speed it up?

I think the slowest part is the function GETNCOUNT - this gets the count of the neighbouring 'live' cells so it is called once per cell.

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

IF "%3"=="" GOTO HELP
SET WIDTH=%1
SET HEIGHT=%2
SET DENSITY=%3
SET LIFECYCLE=0

::::::::::::::::::::
:: Generate Grid 'A'
:: Also for safety, delete any Grid 'B' cells that might be in memory
FOR /L %%h IN (1, 1, %HEIGHT%) DO (
        FOR /L %%w IN (1, 1, %WIDTH%) DO (

            SET /A RAND=!RANDOM!*100/32768
            SET /A RAND=!RAND!+1

            IF !DENSITY! GEQ !RAND! (
                SET A[%%w][%%h]=@
            ) ELSE (
                SET "A[%%w][%%h]= "
            )

            SET B[%%w][%%h]=
        )   
)


::::::::::::::::::::::::::::::
:: TOP OF MAIN PROCESSING LOOP
::
:: Loop through all the Grid 'A' cells
::  - Count number of neighbours
::  - Check if alive or not
::  - If required assign new alive/dead status in Grid 'B'
::
:PROCESS
SET /A LIFECYCLE=%LIFECYCLE%+1

CLS
ECHO Conway's Game of Life. 
CALL :DISPLAY
ECHO Current lifecycle: %LIFECYCLE%

FOR /L %%h IN (1, 1, %HEIGHT%) DO (
        FOR /L %%w IN (1, 1, %WIDTH%) DO (

            CALL :GETNCOUNT %%w %%h
            IF "!A[%%w][%%h]!"=="@" (SET ALIVE=Y) ELSE (SET ALIVE=N)

            IF "!ALIVE!"=="Y" (
                IF !NCOUNT! LSS 2 (
                    SET "B[%%w][%%h]= "
                )
                IF !NCOUNT! EQU 2 (
                    SET B[%%w][%%h]=@
                )
                IF !NCOUNT! EQU 3 (
                    SET B[%%w][%%h]=@
                )
                IF !NCOUNT! GTR 3 (
                    SET "B[%%w][%%h]= "
                )
            )

            IF "!ALIVE!"=="N" (
                IF !NCOUNT! EQU 3 (
                    SET B[%%w][%%h]=@
                )
            )           
        )   
)

:: Now check if we have any Grid 'B' cells 
:: If so, assign these to Grid 'A' cells
FOR /L %%h IN (1, 1, %HEIGHT%) DO (
        FOR /L %%w IN (1, 1, %WIDTH%) DO (

            IF DEFINED B[%%w][%%h] (
                IF "!B[%%w][%%h]!"==" " (
                    SET "A[%%w][%%h]= "
                )
                IF "!B[%%w][%%h]!"=="@" (
                    SET A[%%w][%%h]=@
                )
            )       
        )   
)

:: loop back to the top of process to start again
GOTO PROCESS
::::::::::::::::::::::::::
:: BOTTOM OF PROCESS LOOP
::::::::::::::::::::::::::


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: THIS FUNCTION COUNTS THE NUMBER OF NEIGHBOURS FOR THE GIVEN X AND Y CO-ORDINATES
:: THE COUNT IS STORED IN VARIABLE 'NCOUNT'
::
:: TL | TM | TR
:: ML |    | MR
:: BL | BM | BR
::
:: %1=x %2=y
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:GETNCOUNT
SET NCOUNT=0

::::::
:: TOP
IF %2 EQU 1 (SET Y=%HEIGHT%) ELSE (SET /A Y=%2-1)
:: TOP-LEFT
IF %1 EQU 1 (SET X=%WIDTH%) ELSE (SET /A X=%1-1)
IF !A[%X%][%Y%]! EQU @ (SET /A NCOUNT=!NCOUNT!+1)
:: TOP-MIDDLE
SET X=%1
IF !A[%X%][%Y%]! EQU @ (SET /A NCOUNT=!NCOUNT!+1)
:: TOP-RIGHT
IF %1 EQU %WIDTH% (SET X=1) ELSE (SET /A X=%1+1)
IF !A[%X%][%Y%]! EQU @ (SET /A NCOUNT=!NCOUNT!+1)

:::::::::
:: MIDDLE
SET Y=%2
:: MIDDLE-LEFT
IF %1 EQU 1 (SET X=%WIDTH%) ELSE (SET /A X=%1-1)
IF !A[%X%][%Y%]! EQU @ (SET /A NCOUNT=!NCOUNT!+1)
:: MIDDLE-RIGHT
IF %1 EQU %WIDTH% (SET X=1) ELSE (SET /A X=%1+1)
IF !A[%X%][%Y%]! EQU @ (SET /A NCOUNT=!NCOUNT!+1)

:::::::::
:: BOTTOM
IF %2 EQU %HEIGHT% (SET Y=1) ELSE (SET /A Y=%2+1)
:: BOTTOM-LEFT
IF %1 EQU 1 (SET X=%WIDTH%) ELSE (SET /A X=%1-1)
IF !A[%X%][%Y%]! EQU @ (SET /A NCOUNT=!NCOUNT!+1)
:: BOTTOM-MIDDLE
SET X=%1
IF !A[%X%][%Y%]! EQU @ (SET /A NCOUNT=!NCOUNT!+1)
:: BOTTOM-RIGHT
IF %1 EQU %WIDTH% (SET X=1) ELSE (SET /A X=%1+1)
IF !A[%X%][%Y%]! EQU @ (SET /A NCOUNT=!NCOUNT!+1)
::ECHO BR=X:%X% Y:%Y%

GOTO EOF


::::::::::::::::::::::::::::::::::::::::::::
:: THIS FUNCTION DISPLAYS GRID 'A' ON SCREEN 
::::::::::::::::::::::::::::::::::::::::::::
:DISPLAY
SET TOP=
SET BOT=
FOR /L %%h IN (1, 1, %height%) DO (

    IF %%h EQU 1 (FOR /L %%w IN (1, 1, %width%) DO (SET TOP=_!TOP!))
    IF %%h EQU 1 ECHO .!TOP!.

    SET ROW=
    FOR /L %%w IN (1, 1, %WIDTH%) DO (
            SET ROW=!ROW!!A[%%w][%%h]!
    )

    ECHO ^|!ROW!^|

    IF %%h EQU %height% (FOR /L %%w IN (1, 1, %width%) DO (SET BOT=~!BOT!))
    IF %%h EQU %height% ECHO `!BOT!'    
)
GOTO EOF


:HELP
ECHO/
ECHO 'Conway's Game of Life' - Batch Edition - Chazjn 25/02/2017
ECHO ===========================================================
ECHO Usage is as follows:
ECHO    life [width] [height] [%%density]
ECHO E.g.
ECHO    life 8 5 25
ECHO/
ECHO For more infomation visit: https://en.wikipedia.org/wiki/Conway's_Game_of_Life

GOTO EOF


:EOF
\$\endgroup\$
1
  • \$\begingroup\$ To speed it up, use Take Command from JP Software. This is the descendant of 4DOS which is a replacement command processor. You can use the free TCC/LE edition which is ordinary text mode like CMD, and use the "BTM" file extension so it loads the whole thing into memory rather than reading one line at a time and opening the file for every line, which batch files normally do. \$\endgroup\$
    – JDługosz
    Sep 27, 2021 at 14:19

2 Answers 2

4
\$\begingroup\$

Ok so it turns out that the using CALL in a batch script is very slow. So calling a function once per cell was very expensive time-wise.

So I knew I had to move the logic from the function GETNCOUNT into the main processing loop. However the main issue I ran into here was variable expansion.

I am storing each cell value in a variable named A[x][y] e.g. A[1][1], A[1][2], A[1][3] etc. So after I had calculated the x and y value of the neighbouring cell that I wanted to check, I had to get the value of that variable somehow.

I tried all kinds of double-expansion-nested syntax, e.g. !A[!X!][!Y!]! but this just resulted in XY because the script was trying to expand variables !A[! !][! !]!.

In the end I tried a FOR loop and this worked very nicely. E.g.:

FOR /F "tokens=1,2" %%a IN ("!X! !Y!") DO (ECHO !A[%%a][%%b]!)

So what this is doing is expanding and assigning !X! and !Y! to variables local to the FOR loop %%a and %%b. Thus I can inject them into my cell variable and expand this to get the value its assigned.

So here is the 'final' code, it works much much faster than before. I am pretty satisfied with the performance now, I don't think I can get much more speed out of it.

What I would like to do next is figure out a way to exit gracefully as the only way currently is to press CTRL+C. But that's for another time...

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

IF "%3"=="" GOTO HELP
SET WIDTH=%1
SET HEIGHT=%2
SET DENSITY=%3
SET GENERATION=0
SET /A CELLCOUNT=%WIDTH%*%HEIGHT%
SET ALIVECOUNT=0

::::::::::::::::::::
:: Generate grid 'A'. This grid holds the cell layout for display
:: Also for safety, delete any grid 'B' cells that might be in memory
:: Grid 'B' used to store temporary cell values before they are assigned to grid 'A' 
FOR /L %%h IN (1, 1, %HEIGHT%) DO (
        FOR /L %%w IN (1, 1, %WIDTH%) DO (

            SET /A RAND=!RANDOM!*100/32768

            IF !DENSITY! GEQ !RAND! (
                SET A[%%w][%%h]=@
                SET /A ALIVECOUNT=!ALIVECOUNT!+1
            ) ELSE (
                SET "A[%%w][%%h]= "
            )

            SET B[%%w][%%h]=
        )   
)

::::::::::::::::::::::::::::::
:: TOP OF MAIN PROCESSING LOOP
::
:: Display grid 'A'
:: Loop through all the Grid 'A' cells:
::  - Get values neighbouring cells
::  - Get count of alive neighbours 
::  - Apply 'Game of Life' rules and store resulting value in grid 'b' cell
:: Assign grid 'b' cell values to grid 'a' cell values
:: Loop back to start process again
:PROCESS
SET /A GENERATION=%GENERATION%+1
CLS
ECHO Conway's Game of Life. 
ECHO Generation: %GENERATION%
ECHO Live Cells: %ALIVECOUNT%/%CELLCOUNT%
CALL :DISPLAY

IF "%ALIVECOUNT%"=="0" (GOTO EOF)

SET ALIVECOUNT=0
SET COUNTER=0
FOR /L %%h IN (1, 1, %HEIGHT%) DO (
    FOR /L %%w IN (1, 1, %WIDTH%) DO (

        SET /A COUNTER=!COUNTER!+1
        TITLE Calculating Cell !COUNTER!/%CELLCOUNT%

        SET X=0
        SET Y=0
        SET NCOUNT=0

        REM Find the 3 cells above this cell
        IF %%h EQU 1 (SET Y=%HEIGHT%) ELSE (SET /A Y=%%h-1)
        IF %%w EQU 1 (SET X=%WIDTH%) ELSE (SET /A X=%%w-1)
        FOR /F "tokens=1,2" %%a IN ("!X! !Y!") DO (IF "!A[%%a][%%b]!"=="@" (SET /A NCOUNT=!NCOUNT!+1))  
        SET X=%%w
        FOR /F "tokens=1,2" %%a IN ("!X! !Y!") DO (IF "!A[%%a][%%b]!"=="@" (SET /A NCOUNT=!NCOUNT!+1))
        IF %%w EQU %WIDTH% (SET X=1) ELSE (SET /A X=%%w+1)
        FOR /F "tokens=1,2" %%a IN ("!X! !Y!") DO (IF "!A[%%a][%%b]!"=="@" (SET /A NCOUNT=!NCOUNT!+1))

        REM Find the 2 cells left and right of this cell
        SET Y=%%h
        IF %%w EQU 1 (SET X=%WIDTH%) ELSE (SET /A X=%%w-1)
        FOR /F "tokens=1,2" %%a IN ("!X! !Y!") DO (IF "!A[%%a][%%b]!"=="@" (SET /A NCOUNT=!NCOUNT!+1))
        IF %%w EQU %WIDTH% (SET X=1) ELSE (SET /A X=%%w+1)
        FOR /F "tokens=1,2" %%a IN ("!X! !Y!") DO (IF "!A[%%a][%%b]!"=="@" (SET /A NCOUNT=!NCOUNT!+1))

        REM Find the 3 cells below this cell
        IF %%h EQU %HEIGHT% (SET Y=1) ELSE (SET /A Y=%%h+1)
        IF %%w EQU 1 (SET X=%WIDTH%) ELSE (SET /A X=%%w-1)
        FOR /F "tokens=1,2" %%a IN ("!X! !Y!") DO (IF "!A[%%a][%%b]!"=="@" (SET /A NCOUNT=!NCOUNT!+1))
        SET X=%%w
        FOR /F "tokens=1,2" %%a IN ("!X! !Y!") DO (IF "!A[%%a][%%b]!"=="@" (SET /A NCOUNT=!NCOUNT!+1))
        IF %%w EQU %WIDTH% (SET X=1) ELSE (SET /A X=%%w+1)
        FOR /F "tokens=1,2" %%a IN ("!X! !Y!") DO (IF "!A[%%a][%%b]!"=="@" (SET /A NCOUNT=!NCOUNT!+1))  

        REM Check if this cell is alive or not
        IF "!A[%%w][%%h]!"=="@" (
            SET ALIVE=Y
            SET /A ALIVECOUNT=!ALIVECOUNT!+1
        ) ELSE (
            SET ALIVE=N
        )

        REM Assign live status to grid 'B' based on rules
        IF "!ALIVE!"=="Y" (
            IF !NCOUNT! LSS 2 (
                SET "B[%%w][%%h]= "
            )
            IF !NCOUNT! EQU 2 (
                SET B[%%w][%%h]=@
            )
            IF !NCOUNT! EQU 3 (
                SET B[%%w][%%h]=@
            )
            IF !NCOUNT! GTR 3 (
                SET "B[%%w][%%h]= "
            )
        )

        REM Assign dead status to grid 'B' based on rules
        IF "!ALIVE!"=="N" (
            IF !NCOUNT! EQU 3 (
                SET B[%%w][%%h]=@
            )
        )   
    )   
)

:: Now check if we have set any Grid 'B' cells 
:: If so, assign these cell values to Grid 'A' cells
FOR /L %%h IN (1, 1, %HEIGHT%) DO (
        FOR /L %%w IN (1, 1, %WIDTH%) DO (

            IF DEFINED B[%%w][%%h] (
                IF "!B[%%w][%%h]!"==" " (
                    SET "A[%%w][%%h]= "
                )
                IF "!B[%%w][%%h]!"=="@" (
                    SET A[%%w][%%h]=@
                )
            )       
        )   
)

:: Loop back to the top of process to start again
GOTO PROCESS


::::::::::::::::::::::::::::::::::::::::::::
:: THIS FUNCTION DISPLAYS GRID 'A' ON SCREEN 
::::::::::::::::::::::::::::::::::::::::::::
:DISPLAY
SET TOP=
SET BOT=
FOR /L %%h IN (1, 1, %height%) DO (

    IF %%h EQU 1 (FOR /L %%w IN (1, 1, %width%) DO (SET TOP=_!TOP!))
    IF %%h EQU 1 ECHO .!TOP!.

    SET ROW=
    FOR /L %%w IN (1, 1, %WIDTH%) DO (
            SET ROW=!ROW!!A[%%w][%%h]!
    )

    ECHO ^|!ROW!^|

    IF %%h EQU %height% (FOR /L %%w IN (1, 1, %width%) DO (SET BOT=~!BOT!))
    IF %%h EQU %height% ECHO `!BOT!'    
)
GOTO EOF

:HELP
ECHO/
ECHO 'Conway's Game of Life' - Batch Edition - Chazjn 01/03/2017
ECHO ===========================================================
ECHO Usage is as follows:
ECHO    life [width] [height] [%%density]
ECHO E.g.
ECHO    life 15 10 25
ECHO/
ECHO For more infomation visit: https://en.wikipedia.org/wiki/Conway's_Game_of_Life
GOTO EOF

:EOF
\$\endgroup\$
3
\$\begingroup\$

A few years late to the party, but there are some more things that can be done to improve efficiency.

  • Utilise an "infinite" For /L loop as opposed to the slower Goto :label loop.
    • Note : requires delayed expansion to be enabled and !expansion! must be used for any variable modified within the loop.
    For /L %%. in () Do (
        Loop Commands
    )

  • Move your display logic into the primary loop.

  • Use the least number of outputs / redirections possible - if all the data can be output in one hit, do so.

  • Use predefined information wherever possible to reduce operations in your main loop

  • Example: the logic for calculating adjacent cell locations can be reduced to a sum by predefining an array for each cells adjacent coordinates and using a single Set /A operation to sum the values of the adjacent cells.

    • This is possible due to the fact Set /A expands variables without requiring expansion characters % or !, meaning a list of variable names may be assigned as a sum to the array, and when Set /A is used to sum them, you'll have the a count of all the adjacent cells current values - when using 0 or 1 to represent state, this equates to the total count of living cells.
  • In the same manner, Conditional tests for rules implementation can be substituted for a Set /a assignment from a predefined array of combinations of adjacent cell counts [n] and own cell state [s]. Any cell with the [n][s] combinations: 21 30 and 31 will be defined as living (1). all other combinations result in cell death. (0).

  • What you refer to as Grid A and Grid B is more commonly referred to as Arrays, and the transfer of values From 'Grid B' to 'Grid A' can also be reduced significantly using a for /f loop with tokens and delims options to parse over the set command and all variables that share a common prefix.

    • Unfortunately, For a strictly batch only solution the need to use a temporary array and transfer its values is unavoidable as you cannot modify the original arrays state during the neighbour cell count without causing false counts in array indexes of cells following the one being assessed.
  • Structuring arrays to contain related information that can be isolated using the delims option can help minimise the total number of actions needed in a loop to reference data.

  • Minimise the number of nested For loops, and where you need to use a nested loop, perform as few actions as possible in inner loops. For game of life, only 2 actions need to be implemented for each cell:

    • Sum of adjacent living cells
    • Definition of new array with cell state based on adjacent sum and own state

For further reference to the above points, This is my own version [requires windows 10 supporting VT sequences]:

GOL.bat

@Echo off

:# Windows Version control. Assigns flag true if system is windows 10 build GTR 10586
:# https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows
:# Version 1511 build number = 10.0.10586
 Set "Win10="
 For /f "tokens=3 delims=." %%v in ('Ver')Do if %%v GTR 10586 Set "Win10=True"

:# If Win10 true ; Test if virtual terminal codes enabled ; attempt to enable if false
:# removes win10 flag definition if version does not support Virtual Terminal sequences
 If defined Win10 (
  Reg Query HKCU\Console | %SystemRoot%\System32\findstr.exe /LIC:"VirtualTerminalLevel    REG_DWORD    0x1" > nul || (
    Reg Add HKCU\Console /f /v VirtualTerminalLevel /t REG_DWORD /d 1
  ) > Nul || Set "Win10="
 )
 If not defined Win10 Exit /b

 For /f %%e in ('echo prompt $E^|cmd')Do set "\E=%%e"

%= Display info - do not modify ^ escaping =% Set info=%\E%[!_Yi!;1H%\E%[K%\E%[35m !time: =0!%\E%[0m^
 %\E%[E%\E%[K Gen:%\E%[32m!Gen!%\E%[31m^
 %\E%[E%\E%[K CTRL + C to quit%\E%[0m^
 %\E%[E%\E%[K %\E%[0mhieght!TAB!width!TAB!density!TAB! wrapping%\E%[90m^
 %\E%[E%\E%[K ^^^<Y:%\E%[33m!_Y!%\E%[90m^^^>!TAB!^^^<X:%\E%[33m!_X!%\E%[90m^^^> [H^^^|M^^^|L:%\E%[33m!_D!%\E%[90m] [W^^^|N:%\E%[33m!_W!%\E%[90m]%\E%[%Live.color%m

 Setlocal EnableDelayedExpansion & CHCP 65001 > nul
 For /f "delims= " %%T in ('robocopy /L . . /njh /njs' )do set "TAB=%%T"

 Set /a "_Y=10,_Yi=12,_X=20,Col=36"

:# Define States array '#[n]s' for rule implementation; default is cell death.
 For /l %%n in (0 1 9)Do For %%s in (0 1)Do Set "#%%n%%s=0"
:# Override defaults for #[neighbour]state pairings required to implement rules.
:# 21 = Lives ['2' living neighbours; cell alive '1']
:# 30 / 31 = Repopulates ['3' living neighbours; cell dead '0' or alive '1'.]
 Set /A "#21=1,#30=1,#31=1"

 Set "density[M]=110011000100101010101010100010101010110010100010101"
 Set "density[H]=101110101101110101011101101101101010101110101101111"
 Set "density[L]=001001010000100010100101001000001010101101000101000"

  Set "_D=M"
%= Custom Density =% If not "%~2"=="" (
 If "%~3" =="" (Echo(Select Density [H]igh [M]edium [L]ow
  For /f "Delims=" %%K in ('choice /n /c:HML')Do ( Set "density=!density[%%K]!" & Set "_D=%%K" )
  %= Custom Density by optional 3rd arg =%) Else if not "!density[%~3]!"=="" (Set "density=!density[%~3]!") Else Set "Density=%Density[M]%"
  %= Default Density if no args =%       ) Else Set "density=%Density[M]%"

 Set "_W=Off"
%= Screen wrapping option =%
 If /I "%~4"=="w" (Set "wrap=t"& Set "_W=On") else If /I "%~3"=="w" (Set "wrap=t") else If /I not "%~4"=="n" If /I not "%~3"=="n" (
   Echo(Screen Wrapping: [Y]es [N]o
   For /f "Delims=" %%K in ('choice /n /c:YN')Do If %%K==Y Set "wrap=t"
  )Else  Set "wrap="

%= Custom Y;X =% cls & If not "%~2"=="" (
  Set "Args=%~1%~2"
  Echo("!Args!"|%__APPDIR__%findstr.exe /R "^\"[0-9]*\"$" > nul && Set /A "_Y=%~1,_X=%~2,Cells=%~1*%~2" || (
   Echo(Invalid args: %~n0 "%~1" "%~2"
   Exit /b 1
  )
  If !Cells! GTR 750 (
   Echo(Screen Dimensions too large. Max 750 cells - IE: 30x25
   Exit /b 1
  )
 )

 Set "t}="
%= Define initial array values =% Set /A "cells=0,tl=0"& For /l %%y in (1 1 %_Y%)Do For /l %%x in (1 1 %_X%) Do If not !Cells! GTR 750 (
%= random index of density var =%  For /f "delims=" %%v in ('Set /a !random! %% 50 + 1')Do (
%= Define n e s w offset array =%   Set /A "n.%%y;%%x=%%y-1","e.%%y;%%x=%%x+1","s.%%y;%%x=%%y+1","w.%%y;%%x=%%x-1","Cells+=1","_Yi=%%y+2"
%= Modify offsets if wrapping  =%   If defined wrap (
                                     If %%y EQU 1    Set "n.%%y;%%x=%_Y%"
                                     If %%y EQU %_Y% Set "s.%%y;%%x=1"
                                     If %%x EQU 1    Set "w.%%y;%%x=%_X%"
                                     If %%x EQU %_X% Set "e.%%y;%%x=1"
                                    )
 %= Build y;x[adj] array to sum adjacent cell states =%
  Set "%%y;%%x[adj]=}!n.%%y;%%x!;%%x + }%%y;!e.%%y;%%x! + }!s.%%y;%%x!;%%x + }%%y;!w.%%y;%%x! + }!n.%%y;%%x!;!e.%%y;%%x!"
  Set "%%y;%%x[adj]=!%%y;%%x[adj]! + }!n.%%y;%%x!;!w.%%y;%%x! + }!s.%%y;%%x!;!e.%%y;%%x! + }!s.%%y;%%x!;!w.%%y;%%x!"
  %= add cell to t} array list   =%  Set "t}=!t}!}%%y;%%xe!density:~%%v,1!,"
%= End definition loops =%))

<nul set /p "=%\E%[?25l"
%=________________________________________________=%
%= Game of life loop        =% For /l %%. in ()Do (
%= New screen from t} array =%  Set "screen=%\E%[%Col%m!t}:}=%\E%[!"
%= modified to show cells   =%  Set "screen=!screen:e1,=H▓!"
%= Display screen           =%  Echo(%\E%[7m!Screen:e0,=H┼!%\E%[0m%info%
%= transfer t} array;Counts =%  Set /A "!t}:e==!Gen+=1"
%= Evaluate } array states  =%  Set "t}="& For /f "tokens=1-2 delims=}=" %%1 in ('Set }')Do (
%= Sum adjacent cell states =%   Set /A "[n]=!%%1[adj]!"
%= Assign !#[n]state! to }t =%   For %%s in ("![n]!%%2")Do Set "t}=!t}!}%%1e!#%%~s!,"
%= End State eval loop     =%  ))
\$\endgroup\$
1
  • \$\begingroup\$ For a version that allows clean exit without control+C [on pressing escape] or identifying pattern as static / period LSS 9 [with minimal overhead], See here \$\endgroup\$
    – T3RR0R
    Oct 17, 2021 at 15:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.