Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- REM Conways Game of Life. Now supports saving and importing of pattern files.
- REM Update May 24th 2020
- ::: - Speed of screen refresh improved by using 'screen' files to output the Living cells within the Array via 'TYPE'
- ::: - Efficiency of value transfer from calculation array enhanced by using a single For /F loop and string substitution
- ::: - as opposed to Nested For /L loops.
- ::: - Further speed enhancements achieved by replacing Goto :Loop with an infinite For /L loop construct
- REM Update April 18th 2020
- ::: - Pattern files are now saved as Batch files and can be run directly, avoiding the load selection screen.
- ::: youtube : https://youtu.be/gzvom9UCY0U
- @ECHO OFF & Setlocal EnableDelayedExpansion
- TITLE Game of Life
- Set "SaveDir=%~dp0CGOL_Saves"
- IF not exist "%SaveDir%" MD "%SaveDir%"
- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Build concept:
- ::: Nested array Pos[y,x] containing _O / _I (Alive / Dead) values
- ::: Calculate offset values for adjacent Cells. EG: Pos[1,3] (using For /L %%Y %%X values as starting point, and N E S W NE NW SE SW as offset Variables.)
- ::: If statements to test value of neighbour cells N,E,S,W,NE,NW,SE,SW and counter to indicate how many cells are _O / _I and update status accordingly
- ::: Use intermediary array variables - vPos[x,y] for the above to prevent values changing before all cells in current generation iterated over
- ::: Transfer value to real cell, then destroy value of virtual cell.
- ::: { Creates variable /AE = Ascii-27 escape code.
- ::: - http://www.dostips.com/forum/viewtopic.php?t=1733
- ::: - https://stackoverflow.com/a/34923514/12343998
- :::
- ::: - /AE can be used with and without DelayedExpansion.
- Setlocal
- For /F "tokens=2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
- Endlocal
- Set "/AE=%%a"
- )
- ::: }
- If /I "%~1"=="load" Goto :Load_In
- REM Time suffix for saving initial state
- Set DateString=%Date:~4,10%
- Set DateString=%DateString:/=%
- Set Filetime=%Time::=_%
- Set Filetime=%Filetime: =0%
- Set Filetime=%DateString%_at%Filetime:~,-3%
- REM Folder to save initial state in.
- Set "SaveDir=%~dp0CGOL_Saves"
- IF not exist "%SaveDir%" (
- MD "%SaveDir%"
- PUSHD "%SaveDir%"
- Goto :Dimensions
- )
- PUSHD "%SaveDir%"
- IF Not "%~2"=="" (Goto :Dimensions)
- IF Exist "%SaveDir%\*.bat" (
- ECHO(%/AE%[33m && CLS
- CHOICE /N /C yn /M "Load previous? N/Y"
- If Errorlevel 2 (
- CLS
- Goto :Dimensions
- )
- ) Else (Goto :Dimensions)
- Explorer.exe "%SaveDir%"
- :selectFile
- Set /P "source=%/AE%[35m{%/AE%[36mSelect file: }%/AE%[33m<%/AE%[37m"
- IF exist "!source!" (
- FOR /F "delims=" %%L in ("!source!") DO (Start "" "%%~L" & Exit)
- ) Else (Goto :selectFile)
- :Dimensions
- REM define grid dimensions. Batch can be called or started with parameters for Width and Hieght, and Density.
- IF Not "%~2"=="" (
- Set /A width=%~1,hieght=%~2
- Goto :Populate
- ) Else (
- Set /P width=%/AE%[35m{%/AE%[36mWidth %/AE%[34m[%/AE%[33m30 %/AE%[34m~ %/AE%[33m125%/AE%[34m]%/AE%[37m
- Set /P hieght=%/AE%[35m{%/AE%[36mHieght %/AE%[34m[%/AE%[33m15 %/AE%[34m~ %/AE%[33m40%/AE%[34m]%/AE%[37m
- )
- For /L %%A IN (30,1,125) Do (IF "!width!"=="%%A" (For /L %%B IN (15,1,40) Do (IF "!hieght!"=="%%B" (Goto :Populate))))
- ECHO(%/AE%[31mInvalid Dimensions.
- Goto :Dimensions
- :Populate
- REM populate grid array with _I cells
- For /L %%Y In (1,1,!hieght!) Do (
- For /L %%X In (1,1,!width!) Do (
- Set "Pos[%%Y_%%X]=_I"
- )
- )
- REM randomly populate grid array with living cells. Density can be selected using a 3rd parameter when calling the batch.
- IF Not "%~3"=="" (
- For /L %%Y In (1,1,!hieght!) Do (
- For /L %%X In (1,1,!width!) Do (
- Set /A "density=!random! %%%~3 + 1"
- If "!density!"=="2" (Set "Pos[%%Y_%%X]=_O")
- )
- )
- ) Else (
- For /L %%Y In (1,1,!hieght!) Do (
- For /L %%X In (1,1,!width!) Do (
- Set /A "density=!random! %%9 + 1"
- If "!density!"=="2" (Set "Pos[%%Y_%%X]=_O")
- )
- )
- )
- REM Option to store the initial state.
- CHOICE /N /C ny /M "Save Initial State? N/Y"
- If Errorlevel 2 (
- ECHO(%/AE%[36mSaving...%/AE%[0m
- >"CGOLfile%Filetime%.bat" (
- ECHO(@Echo OFF
- ECHO(Set "width=!width!"
- ECHO(Set "hieght=!hieght!"
- For /L %%Y in (1,1,!hieght!) DO For /L %%X in (1,1,!width!) Do (ECHO.Set "Pos[%%Y_%%X]=!Pos[%%Y_%%X]!")
- Echo(CD ..
- Echo(%~n0 Load
- )
- )
- :Load_In
- REM define display characteristics of _O (living) or _I (dead) cells
- Set /A Color=!random! %%7 + 31
- Set "_I=%/AE%[31m%/AE%[7m+%/AE%[0m"
- REM Set "_O=%/AE%[!Color!m%/AE%[7m %/AE%[0m"
- Set tick=0
- REM Adjust display size, extra line for cursor overflow.
- Set /A hieght+=1
- Mode Con: cols=%width% lines=%hieght%
- Set /A hieght-=1
- (For /L %%Y In (1,1,!hieght!) Do (
- For /L %%X In (1,1,!width!) Do (
- For %%A in (!Pos[%%Y_%%X]!) DO (Echo(%/AE%[%%Y;%%XH!_I!)
- )
- ))>"%SaveDir%\BGScreen.txt"
- Set /A Color=!random! %%4 + 34
- (For /F "USEBACKQ Tokens=1,2 Delims==" %%A in (`"Set Pos["`) Do (
- Set ".Y=%%~A"
- Set ".Y=!.Y:Pos[=!"
- Set ".X=!.Y:*_=!"
- Set ".X=!.X:]=!"
- For %%V in (_!.X!]) Do Set ".Y=!.Y:%%V=!"
- If /I "%%~B" == "_O" (Set /A Color=!random! %%4 + 34 & Echo.%/AE%[!.Y!;!.X!H%/AE%[!Color!m%/AE%[7m@%/AE%[0m)
- ))>"%SaveDir%\Screen.txt"
- TYPE "%SaveDir%\BGScreen.txt"
- TYPE "%SaveDir%\Screen.txt"
- REM loop to cycle through generations (otherwise known as ticks)
- For /L %%. in () Do (
- Set /A tick+=1
- TITLE !TIME:~3,8! !tick!
- REM determine _O / _I status for each cells next generation and assign to virtual cells ready for transfer.
- For /L %%Y In (1,1,!hieght!) Do (
- For /L %%X In (1,1,!width!) Do (
- REM calculate positions of nieghbour cells
- Set /A N=%%Y,E=%%X,S=%%Y,W=%%X,B_North=0,B_South=!hieght!,B_East=!width!,B_West=0
- Set /A N-=1,E+=1,S+=1,W-=1,B_East+=1,B_South+=1
- REM horizontal, vertical and diagonal Screen Wrapping. REM prior to below If conditions Disables wrapping.
- REM IF "!N!"=="!B_North!" Set N=!hieght!
- REM IF "!E!"=="!B_East!" Set E=1
- REM IF "!S!"=="!B_South!" Set S=1
- REM IF "!W!"=="!B_West!" Set W=!width!
- Set "NE=!N!_!E!"
- Set "NW=!N!_!W!"
- Set "SE=!S!_!E!"
- Set "SW=!S!_!W!"
- Set "N=!N!_%%X"
- Set "E=%%Y_!E!"
- Set "S=!S!_%%X"
- Set "W=%%Y_!W!"
- REM reset living neighbour cells count
- Set count=0
- REM iterate over each neighbour cell
- For %%A in (Pos[!N!],Pos[!E!],Pos[!S!],Pos[!W!],Pos[!NE!],Pos[!NW!],Pos[!SE!],Pos[!SW!]) Do (
- REM increment count for each live neighbour
- IF /I "!%%~A!"=="_O" (Set /A count+=1)
- )
- REM Game rule implementation
- REM Any cell not meeting the following two critea dies.
- Set "vPos[%%Y_%%X]=_I"
- REM A living Cell with exactly two living neighbours survives
- IF "!count!"=="2" (IF /I "!Pos[%%Y_%%X]!"=="_O" (Set vPos[%%Y_%%X]=_O))
- REM Any cell with exactly three living neighbours is concieved / survives.
- IF "!count!"=="3" (Set vPos[%%Y_%%X]=_O)
- )
- )
- REM Build Foreground screen to display current living generation, Transfer array values and 'Undefine' Calculation array variables
- (For /F "USEBACKQ Tokens=1,2 Delims==" %%A in (`"Set vPos["`) Do (
- Set ".Y=%%~A"
- Set ".Y=!.Y:vPos[=!"
- Set ".X=!.Y:*_=!"
- Set ".X=!.X:]=!"
- For %%V in (_!.X!]) Do Set ".Y=!.Y:%%V=!"
- Set "Pos[!.Y!_!.X!]=%%~B"
- If /I "%%~B" == "_O" (Set /A Color=!random! %%4 + 34 & Echo.%/AE%[!.Y!;!.X!H%/AE%[!Color!m%/AE%[7m@%/AE%[0m)
- Set %%~A=
- ))>"%SaveDir%\Screen.txt"
- TYPE "%SaveDir%\BGScreen.txt"
- TYPE "%SaveDir%\Screen.txt"
- )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement