Advertisement
T3RRYT3RR0R

Conways Game of Life BATCH

Mar 7th, 2020
748
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Batch 5.90 KB | None | 0 0
  1. REM Conways Game of Life. Now supports saving and importing of pattern files.
  2. REM Update May 24th 2020
  3. ::: - Speed of screen refresh improved by using 'screen' files to output the Living cells within the Array via 'TYPE'
  4. ::: - Efficiency of value transfer from calculation array enhanced by using a single For /F loop and string substitution
  5. ::: - as opposed to Nested For /L loops.
  6. ::: - Further speed enhancements achieved by replacing Goto :Loop with an infinite For /L loop construct
  7. REM Update April 18th 2020
  8. ::: - Pattern files are now saved as Batch files and can be run directly, avoiding the load selection screen.
  9. ::: youtube : https://youtu.be/gzvom9UCY0U
  10.  
  11. @ECHO OFF & Setlocal EnableDelayedExpansion
  12.     TITLE Game of Life
  13.     Set "SaveDir=%~dp0CGOL_Saves"
  14.     IF not exist "%SaveDir%" MD "%SaveDir%"
  15. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Build concept:
  16. ::: Nested array Pos[y,x] containing _O / _I (Alive / Dead) values
  17. ::: 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.)
  18. ::: 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
  19. ::: Use intermediary array variables - vPos[x,y] for the above to prevent values changing before all cells in current generation iterated over
  20. ::: Transfer value to real cell, then destroy value of virtual cell.
  21. ::: { Creates variable /AE = Ascii-27 escape code.
  22. ::: - http://www.dostips.com/forum/viewtopic.php?t=1733
  23. ::: - https://stackoverflow.com/a/34923514/12343998
  24. :::
  25. ::: - /AE can be used  with and without DelayedExpansion.
  26.     Setlocal
  27.     For /F "tokens=2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
  28.         Endlocal
  29.         Set "/AE=%%a"
  30.     )
  31. ::: }
  32. If /I "%~1"=="load" Goto :Load_In
  33. REM Time suffix for saving initial state
  34.     Set DateString=%Date:~4,10%
  35.     Set DateString=%DateString:/=%
  36.     Set Filetime=%Time::=_%
  37.     Set Filetime=%Filetime: =0%
  38.     Set Filetime=%DateString%_at%Filetime:~,-3%
  39. REM Folder to save initial state in.
  40.     Set "SaveDir=%~dp0CGOL_Saves"
  41.     IF not exist "%SaveDir%" (
  42.         MD "%SaveDir%"
  43.         PUSHD "%SaveDir%"
  44.         Goto :Dimensions
  45.     )
  46.     PUSHD "%SaveDir%"
  47.     IF Not "%~2"=="" (Goto :Dimensions)
  48.  
  49.         IF Exist "%SaveDir%\*.bat" (
  50.             ECHO(%/AE%[33m && CLS
  51.             CHOICE /N /C yn /M "Load previous? N/Y"
  52.             If Errorlevel 2 (
  53.                 CLS
  54.                 Goto :Dimensions
  55.             )
  56.         ) Else (Goto :Dimensions)
  57.     Explorer.exe "%SaveDir%"
  58. :selectFile
  59.     Set /P "source=%/AE%[35m{%/AE%[36mSelect file: }%/AE%[33m<%/AE%[37m"
  60.     IF exist "!source!" (
  61.         FOR /F "delims=" %%L in ("!source!") DO (Start "" "%%~L" & Exit)
  62.     ) Else (Goto :selectFile)
  63. :Dimensions
  64. REM define grid dimensions. Batch can be called or started with parameters for Width and Hieght, and Density.
  65.     IF Not "%~2"=="" (
  66.         Set /A width=%~1,hieght=%~2
  67.         Goto :Populate
  68.     ) Else (
  69.         Set /P width=%/AE%[35m{%/AE%[36mWidth %/AE%[34m[%/AE%[33m30 %/AE%[34m~ %/AE%[33m125%/AE%[34m]%/AE%[37m
  70.         Set /P hieght=%/AE%[35m{%/AE%[36mHieght %/AE%[34m[%/AE%[33m15 %/AE%[34m~ %/AE%[33m40%/AE%[34m]%/AE%[37m
  71.     )
  72.     For /L %%A IN (30,1,125) Do (IF "!width!"=="%%A" (For /L %%B IN (15,1,40) Do (IF "!hieght!"=="%%B" (Goto :Populate))))
  73.     ECHO(%/AE%[31mInvalid Dimensions.
  74. Goto :Dimensions
  75. :Populate
  76. REM populate grid array with _I cells
  77.     For /L %%Y In (1,1,!hieght!) Do (
  78.         For /L %%X In (1,1,!width!) Do (   
  79.             Set "Pos[%%Y_%%X]=_I"
  80.         )
  81.     )
  82. REM randomly populate grid array with living cells. Density can be selected using a 3rd parameter when calling the batch.
  83.     IF Not "%~3"=="" (
  84.         For /L %%Y In (1,1,!hieght!) Do (
  85.             For /L %%X In (1,1,!width!) Do (
  86.                 Set /A "density=!random! %%%~3 + 1"
  87.                 If "!density!"=="2" (Set "Pos[%%Y_%%X]=_O")
  88.             )
  89.         )
  90.     ) Else (
  91.         For /L %%Y In (1,1,!hieght!) Do (
  92.             For /L %%X In (1,1,!width!) Do (
  93.                 Set /A "density=!random! %%9 + 1"
  94.                 If "!density!"=="2" (Set "Pos[%%Y_%%X]=_O")
  95.             )
  96.         )
  97.     )
  98. REM Option to store the initial state.
  99.     CHOICE /N /C ny /M "Save Initial State? N/Y"
  100.     If Errorlevel 2 (
  101.         ECHO(%/AE%[36mSaving...%/AE%[0m
  102.         >"CGOLfile%Filetime%.bat" (
  103.             ECHO(@Echo OFF
  104.             ECHO(Set "width=!width!"
  105.             ECHO(Set "hieght=!hieght!"
  106.             For /L %%Y in (1,1,!hieght!) DO For /L %%X in (1,1,!width!) Do (ECHO.Set "Pos[%%Y_%%X]=!Pos[%%Y_%%X]!")
  107.             Echo(CD ..
  108.             Echo(%~n0 Load
  109.         )
  110.     )
  111. :Load_In
  112. REM define display characteristics of _O (living) or _I (dead) cells
  113.     Set /A Color=!random! %%7 + 31
  114.     Set "_I=%/AE%[31m%/AE%[7m+%/AE%[0m"
  115.     REM Set "_O=%/AE%[!Color!m%/AE%[7m %/AE%[0m"
  116.     Set tick=0
  117. REM Adjust display size, extra line for cursor overflow.
  118.     Set /A hieght+=1
  119.     Mode Con: cols=%width% lines=%hieght%
  120.     Set /A hieght-=1
  121.     (For /L %%Y In (1,1,!hieght!) Do (
  122.         For /L %%X In (1,1,!width!) Do (
  123.             For %%A in (!Pos[%%Y_%%X]!) DO (Echo(%/AE%[%%Y;%%XH!_I!)               
  124.         )
  125.     ))>"%SaveDir%\BGScreen.txt"
  126.     Set /A Color=!random! %%4 + 34
  127.     (For /F "USEBACKQ Tokens=1,2 Delims==" %%A in (`"Set Pos["`) Do (
  128.         Set ".Y=%%~A"
  129.         Set ".Y=!.Y:Pos[=!"
  130.         Set ".X=!.Y:*_=!"
  131.         Set ".X=!.X:]=!"
  132.         For %%V in (_!.X!]) Do Set ".Y=!.Y:%%V=!"
  133.         If /I "%%~B" == "_O" (Set /A Color=!random! %%4 + 34 & Echo.%/AE%[!.Y!;!.X!H%/AE%[!Color!m%/AE%[7m@%/AE%[0m)
  134.     ))>"%SaveDir%\Screen.txt"
  135.     TYPE "%SaveDir%\BGScreen.txt"
  136.     TYPE "%SaveDir%\Screen.txt"
  137. REM loop to cycle through generations (otherwise known as ticks)
  138. For /L %%. in () Do (
  139.     Set /A tick+=1
  140.     TITLE !TIME:~3,8! !tick!
  141. REM determine _O / _I status for each cells next generation and assign to virtual cells ready for transfer.
  142.     For /L %%Y In (1,1,!hieght!) Do (
  143.         For /L %%X In (1,1,!width!) Do (
  144.     REM calculate positions of nieghbour cells
  145.             Set /A N=%%Y,E=%%X,S=%%Y,W=%%X,B_North=0,B_South=!hieght!,B_East=!width!,B_West=0
  146.             Set /A N-=1,E+=1,S+=1,W-=1,B_East+=1,B_South+=1
  147.     REM horizontal, vertical and diagonal Screen Wrapping. REM prior to below If conditions Disables wrapping.
  148.         REM IF "!N!"=="!B_North!" Set N=!hieght!
  149.         REM IF "!E!"=="!B_East!" Set E=1
  150.         REM IF "!S!"=="!B_South!" Set S=1
  151.         REM IF "!W!"=="!B_West!" Set W=!width!
  152.             Set "NE=!N!_!E!"
  153.             Set "NW=!N!_!W!"
  154.             Set "SE=!S!_!E!"
  155.             Set "SW=!S!_!W!"
  156.             Set "N=!N!_%%X"
  157.             Set "E=%%Y_!E!"
  158.             Set "S=!S!_%%X"
  159.             Set "W=%%Y_!W!"
  160.         REM reset living neighbour cells count
  161.             Set count=0
  162.         REM iterate over each neighbour cell
  163.             For %%A in (Pos[!N!],Pos[!E!],Pos[!S!],Pos[!W!],Pos[!NE!],Pos[!NW!],Pos[!SE!],Pos[!SW!]) Do (
  164.         REM increment count for each live neighbour
  165.                 IF /I "!%%~A!"=="_O" (Set /A count+=1)
  166.             )
  167. REM Game rule implementation
  168.         REM Any cell not meeting the following two critea dies.
  169.             Set "vPos[%%Y_%%X]=_I"
  170.         REM A living Cell with exactly two living neighbours survives
  171.             IF "!count!"=="2" (IF /I "!Pos[%%Y_%%X]!"=="_O" (Set vPos[%%Y_%%X]=_O))
  172.         REM Any cell with exactly three living neighbours is concieved / survives.
  173.             IF "!count!"=="3" (Set vPos[%%Y_%%X]=_O)
  174.         )
  175.     )
  176. REM Build Foreground screen to display current living generation, Transfer array values and 'Undefine' Calculation array variables
  177.     (For /F "USEBACKQ Tokens=1,2 Delims==" %%A in (`"Set vPos["`) Do (
  178.         Set ".Y=%%~A"
  179.         Set ".Y=!.Y:vPos[=!"
  180.         Set ".X=!.Y:*_=!"
  181.         Set ".X=!.X:]=!"
  182.         For %%V in (_!.X!]) Do Set ".Y=!.Y:%%V=!"
  183.         Set "Pos[!.Y!_!.X!]=%%~B"
  184.         If /I "%%~B" == "_O" (Set /A Color=!random! %%4 + 34 & Echo.%/AE%[!.Y!;!.X!H%/AE%[!Color!m%/AE%[7m@%/AE%[0m)
  185.         Set %%~A=
  186.     ))>"%SaveDir%\Screen.txt"
  187.     TYPE "%SaveDir%\BGScreen.txt"
  188.     TYPE "%SaveDir%\Screen.txt"
  189. )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement