Suryagiri232

Ular CMD

Feb 4th, 2017
12,207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Batch 27.11 KB | None | 0 0
  1. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2. :: SNAKE.BAT - A pure native Windows batch implementation of the classic game
  3. :: ------------------------------------------------------------------------------
  4. :: Written by Dave Benham with some debugging help and technique pointers from
  5. :: DosTips users - See http://www.dostips.com/forum/viewtopic.php?f=3&t=4741
  6. ::
  7. :: The game should work on any Windows machine from XP onward using only batch
  8. :: and native external commands. However, there will most likely be some screen
  9. :: flicker due to the CLS command issued upon every screen refresh.
  10. ::
  11. :: The screen flicker can be eliminated by adding Aacini's CursorPos.exe to the
  12. :: same folder that contains SNAKE.BAT. The flicker free feature is "cheating"
  13. :: in that it is not pure native batch since it relies on a 3rd party tool.
  14. :: But it really improves the game experience. A script to create CursorPos.exe
  15. :: is available at http://goo.gl/hr6Kkn.
  16. ::
  17. :: Note that user preferences and high scores are stored in %USERPROFILE%\Snake
  18. :: User saved games have an implicit .snake.txt "extension", and are saved and
  19. :: loaded from the current directory.
  20. ::
  21. :: Version History
  22. ::
  23. :: 3.8  2015-02-16
  24. ::   - Improve performance of Replay abort
  25. ::   - Eliminate flicker at game start when using CursorPos.exe
  26. ::   - Use symbols (variables) for lock, key and cmd streams.
  27. ::
  28. :: 3.7  2014-08-03
  29. ::   - Reduced screen flicker when playing without CursorPos.exe by building
  30. ::     entire screen in one variable before CLS and ECHOing the screen.
  31. ::
  32. :: 3.6  2014-04-09
  33. ::   - Pause after displaying CursorPos.exe message at end if game was launced
  34. ::     via double click or START menu.
  35. ::
  36. :: 3.5  2014-02-03
  37. ::   - Made growth rate user configurable. High scores are now stored for each
  38. ::     growth rate played.
  39. ::   - Added optional support for Aacini's CursorPos.exe to eliminate screen
  40. ::     flicker.
  41. ::   - Redesigned storage of configuration options within saved games to make
  42. ::     it easier to extend in the future. Existing saved games are automatically
  43. ::     converted to the new format.
  44. ::   - Simplified replay abort mechanics.
  45. ::
  46. :: 3.4  2013-12-26
  47. ::   - Added ability to abort a game replay.
  48. ::
  49. :: 3.3  2013-12-24
  50. ::   - Added Pause functionality.
  51. ::
  52. :: 3.2  2013-12-08
  53. ::   - Fixed a replay bug. Note that attempting to delete a non-existent file
  54. ::     does not raise an error!
  55. ::   - Added ability to save a previous game or a High score game to a user
  56. ::     named file in the current directory.
  57. ::   - Added ability to load and replay a user saved game from the current
  58. ::     directory.
  59. ::
  60. :: 3.1  2013-12-08
  61. ::   - Fixed a bug with the game logs. Must include key mappings in log.
  62. ::     High scores from version 3.0 should be deleted from %USERPROFILE%\Snake.
  63. ::
  64. :: 3.0  2013-12-07
  65. ::   - Made control keys user configurable, including option for 2 key
  66. ::     (left/right) or 4 key (left/right/up/down) input.
  67. ::   - Made graphics user configurable.
  68. ::   - Added ability to display replay of previous game.
  69. ::   - Added High Score list, with ability to display replay of High Score games.
  70. ::
  71. :: 2.3  2013-12-01
  72. ::   - Added elapsed game time to the display.
  73. ::
  74. :: 2.2  2013-08-06
  75. ::   - Improved comments / internal documentation
  76. ::   - A few inconsequential code changes
  77. ::
  78. :: 2.1  2013-07-20
  79. ::   - Reworked interprocess communication. No more hanging games (I hope).
  80. ::   - Fixed parameterization of movement key definition.
  81. ::   - Temp file location now controlled by TEMP (or TMP) environment variable.
  82. ::   - Implemented a game session lock into temp file names so multiple game
  83. ::     instances can share the same TEMP folder without interference.
  84. ::
  85. :: 2.0  2013-07-17
  86. ::   - First attempt at using XCOPY instead of CHOICE. Game now runs as
  87. ::     pure native batch on all Windows versions from XP onward.
  88. ::
  89. :: 1.0  2013-07-13  to  1.x
  90. ::   - Game required CHOICE command, so did not work on XP without download of
  91. ::     a non-standard exe or com file.
  92. ::
  93. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  94.  
  95. @echo off
  96. if "%~1" == "startGame" goto :game
  97. if "%~1" == "startController" goto :controller
  98.  
  99.  
  100. ::---------------------------------------------------------------------
  101. :: setup some global variables used by both the game and the controller
  102.  
  103. setlocal disableDelayedExpansion
  104. :getSession
  105. if defined temp (set "tempFileBase=%temp%\") else if defined tmp set "tempFileBase=%tmp%\"
  106. set "tempFileBase=%tempFileBase%Snake%time::=_%"
  107. set "keyFile=%tempFileBase%_key.txt"
  108. set "cmdFile=%tempFileBase%_cmd.txt"
  109. set "gameLock=%tempFileBase%_gameLock.txt"
  110. set "gameLog=%tempFileBase%_gameLog.txt"
  111. set "signal=%tempFileBase%_signal.txt"
  112. set "saveLoc=%userprofile%\Snake"
  113. set "userPref=%saveLoc%\SnakeUserPref.txt"
  114. set "hiFile=%saveLoc%\Snake!growth!Hi"
  115. set "keyStream=9"
  116. set "cmdStream=8"
  117. set "lockStream=7"
  118.  
  119.  
  120. ::------------------------------------------
  121. :: Lock this game session and launch.
  122. :: Loop back and try a new session if failure.
  123. :: Cleanup and exit when finished
  124.  
  125. call :launch %lockStream%>"%gameLock%" || goto :getSession
  126. del "%tempFileBase%*"
  127. exit /b
  128.  
  129.  
  130. ::------------------------------------------
  131. :launch the game and the controller
  132.  
  133. call :fixLogs
  134. copy nul "%keyFile%" >nul
  135. copy nul "%cmdFile%" >nul
  136. start "" /b cmd /c ^""%~f0" startController %keyStream%^>^>"%keyFile%" %cmdStream%^<"%cmdFile%" 2^>nul ^>nul^"
  137. cmd /c ^""%~f0" startGame %keyStream%^<"%keyFile%" %cmdStream%^>^>"%cmdFile%" ^<nul^"
  138. echo(
  139.  
  140.  
  141. ::--------------------------------------------------------------
  142. :: Upon exit, wait for the controller to close before returning
  143.  
  144. :close
  145. 2>nul (>>"%keyFile%" call )||goto :close
  146. if not exist "%~dp0CursorPos.exe" (
  147.   echo Game play can be improved by installing
  148.   echo Aacini's CursorPos.exe, available at
  149.   echo http://goo.gl/hr6Kkn
  150.   echo(
  151.   echo %cmdcmdline%|find /i "%~f0">nul&&pause
  152. )
  153. exit /b 0
  154.  
  155.  
  156. ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  157. :game
  158. title %~nx0
  159. cls
  160.  
  161. ::---------------------------------------
  162. :: Playfield size
  163. :: max playing field: (width-2)*(height-2) <= 1365
  164.  
  165. set "width=40"   max=99
  166. set "height=25"  max=99
  167.  
  168. ::----------------------------
  169. :: resize the console window
  170.  
  171. set /a cols=width+1, lines=height+10, area=(width-2)*(height-2)
  172. if %area% gtr 1365 (
  173.   echo ERROR: Playfield area too large
  174.   %sendCmd% quit
  175.   exit
  176. )
  177. if %lines% lss 14 set lines=14
  178. if %cols% lss 46 set cols=46
  179. mode con: cols=%cols% lines=%lines%
  180.  
  181.  
  182. ::----------------------------
  183. :: define variables
  184.  
  185. set "configOptions=diffCode difficulty growth moveKeys up down left right"
  186. set "configOptionCnt=9"
  187.  
  188. set "moveKeys=4"
  189.  
  190. set "up=W"
  191. set "down=S"
  192. set "left=A"
  193. set "right=D"
  194. set "pause=P"
  195.  
  196. set "space= "
  197. set "bound=#"
  198. set "food=+"
  199. set "head=@"
  200. set "body=O"
  201. set "death=X"
  202.  
  203. set "growth=1"
  204.  
  205. if exist "%userPref%" for /f "usebackq delims=" %%V in ("%userPref%") do set "%%V"
  206.  
  207. set "spinner1=-"
  208. set "spinner2=\"
  209. set "spinner3=|"
  210. set "spinner4=/"
  211. set "spinner= spinner1 spinner2 spinner3 spinner4 "
  212.  
  213. set "delay1=20"
  214. set "delay2=15"
  215. set "delay3=10"
  216. set "delay4=7"
  217. set "delay5=5"
  218. set "delay6=3"
  219.  
  220. set "desc1=Sluggard"
  221. set "desc2=Crawl"
  222. set "desc3=Slow"
  223. set "desc4=Normal"
  224. set "desc5=Fast"
  225. set "desc6=Insane"
  226.  
  227. set "spinnerDelay=3"
  228.  
  229. set /a "width-=1, height-=1"
  230.  
  231. :: define LF as a Line Feed (newline) character
  232. set ^"LF=^
  233.  
  234. ^" Above empty line is required - do not remove
  235.  
  236. :: define CR as a Carriage Return character
  237. for /f %%A in ('copy /Z "%~dpf0" nul') do set "CR=%%A"
  238.  
  239. :: define BS as a BackSpace character
  240. for /f %%A in ('"prompt $H&for %%B in (1) do rem"') do set "BS=%%A"
  241.  
  242. set "upper=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
  243. set "invalid=*~="
  244.  
  245.  
  246. ::---------------------------
  247. :: define macros
  248.  
  249. if exist "%~dp0CursorPos.exe" (
  250.   set "cls=CursorPos 0 0"
  251.   set "ClearLine=echo(                                   &CursorPos 0 -1"
  252.   set "ClearPrev=CursorPos 0 -0&echo(                                   "
  253. ) else (
  254.   set "cls=cls"
  255.   set "ClearLine="
  256.   set "ClearPrev="
  257. )
  258.  
  259. :: define a newline with line continuation
  260. set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
  261.  
  262. :: setErr
  263. :::  Sets the ERRORLEVEL to 1
  264. set "setErr=(call)"
  265.  
  266. :: clrErr
  267. :::  Sets the ERRORLEVEL to 0
  268. set "clrErr=(call )"
  269.  
  270.  
  271. :: sendCmd  command
  272. :::  sends a command to the controller
  273. set "sendCmd=>&%cmdStream% echo"
  274.  
  275.  
  276. :: getKey  [ValidKey]  [ValidKey...]
  277. ::: Check for keypress from the controller. Only accept a ValidKey.
  278. ::: Token delimiters and poison characters must be quoted.
  279. ::: Accept any key if no ValidKey specified.
  280. ::: Return result in Key variable. Key is undefined if no valid keypress.
  281. set getKey=%\n%
  282. for %%# in (1 2) do if %%#==2 (%\n%
  283.   set key=%\n%
  284.   set inKey=%\n%
  285.   set keyTest=%\n%
  286.   ^<^&%keyStream% set /p "inKey="%\n%
  287.   if defined inKey (%\n%
  288.     set inKey=!inKey:~0,-1!%\n%
  289.     for %%C in (!args!) do set /a keyTest=1^&if /i !inKey! equ %%~C set key=!inKey!%\n%
  290.   )%\n%
  291.   if not defined keyTest set key=!inKey!%\n%
  292. ) else set args=
  293.  
  294.  
  295. :: draw
  296. :::  draws the board
  297. set draw=%\n%
  298. set screen=%\n%
  299. for /l %%Y in (0,1,%height%) do set screen=!screen!!line%%Y!!LF!%\n%
  300. set screen=!screen!Speed = !Difficulty! !replay!!LF!Growth Rate = !growth!   HighScore = !hi!!LF!Score = !score!   Time = !m!:!s!%\n%
  301. if defined replay if not defined replayFinished (%\n%
  302.   set screen=!screen!!LF!!LF!Press a key to abort the replay%\n%
  303. )%\n%
  304. %cls%^&echo(!screen!
  305.  
  306. :: test  X  Y  ValueListVar
  307. :::  tests if value at coordinates X,Y is within contents of ValueListVar
  308. set test=%\n%
  309. for %%# in (1 2) do if %%#==2 (for /f "tokens=1-3" %%1 in ("!args!") do (%\n%
  310.   for %%A in ("!line%%2:~%%1,1!") do if "!%%3:%%~A=!" neq "!%%3!" %clrErr% else %setErr%%\n%
  311. )) else set args=
  312.  
  313.  
  314. :: plot  X  Y  ValueVar
  315. :::  places contents of ValueVar at coordinates X,Y
  316. set plot=%\n%
  317. for %%# in (1 2) do if %%#==2 (for /f "tokens=1-3" %%1 in ("!args!") do (%\n%
  318.   set "part2=!line%%2:~%%1!"%\n%
  319.   set "line%%2=!line%%2:~0,%%1!!%%3!!part2:~1!"%\n%
  320. )) else set args=
  321.  
  322.  
  323. ::--------------------------------------
  324. :: start the game
  325. setlocal enableDelayedExpansion
  326. if not exist "%saveLoc%\" md "%saveLoc%"
  327. set "replay= Aborting... "
  328. set "replayAvailable="
  329. call :loadHighScores
  330. call :mainMenu
  331.  
  332.  
  333. ::--------------------------------------
  334. :: main loop (infinite loop)
  335. for /l %%. in () do (
  336.  
  337.   %=== check for and process abort signal if in replay mode ===%
  338.   if defined replay if exist "%signal%" (
  339.     del "%signal%"
  340.     set "replayFinished=1"
  341.     %draw%
  342.     echo(
  343.     %ClearLine%
  344.     <nul set /p "=Aborting... "
  345.     findstr "^" >nul <&%keyStream%
  346.     for %%A in (!configOptions!) do set "%%A=!%%ASave!"
  347.     call :mainMenu
  348.   )
  349.  
  350.   %=== compute time since last move ===%
  351.   for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "t2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, tDiff=t2-t1"
  352.   if !tDiff! lss 0 set /a tDiff+=24*60*60*100
  353.  
  354.   if !tDiff! geq !delay! (
  355.     %=== delay has expired, so time for movement ===%
  356.     set /a t1=t2
  357.  
  358.     %=== compute game time ===%
  359.     if not defined gameStart set "gameStart=!t2!"
  360.     set /a "gameTime=(t2-gameStart)"
  361.     if !gameTime! lss 0 set /a "gameTime+=24*60*60*100"
  362.     set /a "gameTime=(gameTime-pauseTime)/100, m=gameTime/60, s=gameTime%%60"
  363.     if !m! lss 10 set "m=0!m!"
  364.     if !s! lss 10 set "s=0!s!"
  365.  
  366.     %=== get keypress ===%
  367.     %getKey% !keys!
  368.     if /i !key! equ !pause! (
  369.  
  370.       %=== pause game ===%
  371.       echo(
  372.       call :ask "PAUSED - Press a key to continue..."
  373.       %ClearPrev%
  374.       %sendCmd% go
  375.       for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "t2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, tDiff=t2-t1"
  376.       if !tDiff! lss 0 set /a tDiff+=24*60*60*100
  377.       set /a pauseTime+=tDiff
  378.  
  379.     ) else (
  380.  
  381.       %=== establish direction ===%
  382.       if not defined replay (echo(!key!.) >>"!gameLog!"
  383.       for %%K in (!key!) do if !moveKeys! equ 2 (
  384.         set /a "xDiff=xTurn%%K*!yDiff!, yDiff=yTurn%%K*!xDiff!"
  385.       ) else if "!%%KAxis!" neq "!axis!" (
  386.         set /a "xDiff=xDiff%%K, yDiff=yDiff%%K"
  387.         set "axis=!%%KAxis!"
  388.       )
  389.  
  390.       %=== erase the tail ===%
  391.       set "TX=!snakeX:~-2!"
  392.       set "TY=!snakeY:~-2!"
  393.       set "snakeX=!snakeX:~0,-2!"
  394.       set "snakeY=!snakeY:~0,-2!"
  395.       %plot% !TX! !TY! space
  396.  
  397.       %=== compute new head location and attempt to move ===%
  398.       set /a "X=PX+xDiff, Y=PY+yDiff"
  399.       set "X= !X!"
  400.       set "Y= !Y!"
  401.       set "X=!X:~-2!"
  402.       set "Y=!Y:~-2!"
  403.       (%test% !X! !Y! playerSpace) && (
  404.  
  405.         %=== move successful ===%
  406.  
  407.         %=== remove the new head location from the empty list ===%
  408.         for %%X in ("!X!") do for %%Y in ("!Y!") do set "empty=!empty:#%%~X %%~Y=!"
  409.  
  410.         %=== eat any food that may be present ===%
  411.         (%test% !X! !Y! food) && (
  412.           %=== initiate growth ===%
  413.           set /a grow+=growth
  414.  
  415.           %=== locate and draw new food ===%
  416.           if defined replay (
  417.             <&%keyStream% set /p "F="
  418.           ) else (
  419.             set /a "F=(!random!%%(emptyCnt-1))*6+1"
  420.             (echo !F!) >>"!gameLog!"
  421.           )
  422.           for %%F in (!F!) do (%plot% !empty:~%%F,5! food)
  423.         )
  424.  
  425.         if !grow! gtr 0 (
  426.           %=== restore the tail ===%
  427.           %plot% !TX! !TY! body
  428.           set "snakeX=!snakeX!!TX!"
  429.           set "snakeY=!snakeY!!TY!"
  430.           set /a emptyCnt-=1
  431.  
  432.           %=== manage score ===%
  433.           set /a "score+=1, grow-=1"
  434.           if not defined replay if !score! gtr !hi! set /a "hi+=1, newHi=1"
  435.  
  436.         ) else (
  437.           %=== add the former tail position to the empty list ===%
  438.           set "empty=!empty!#!TX! !TY!"
  439.         )
  440.  
  441.         %=== draw the new head ===%
  442.         if defined snakeX (%plot% !PX! !PY! body)
  443.         %plot% !X! !Y! head
  444.  
  445.         %=== Add the new head position to the snake strings ===%
  446.         set "snakeX=!X!!snakeX!"
  447.         set "snakeY=!Y!!snakeY!"
  448.         set "PX=!X!"
  449.         set "PY=!Y!"
  450.  
  451.         %draw%
  452.  
  453.       ) || (
  454.  
  455.         %=== failed move - game over ===%
  456.         set "replayFinished=1"
  457.         %plot% !TX! !TY! body
  458.         call :spinner !PX! !PY! death
  459.         %draw%
  460.         if defined newHi (
  461.           echo(
  462.           echo New High Score - Congratulations^^!
  463.           set "hi!diffCode!=!score!"
  464.           copy "!gameLog!" "%hiFile%!diffCode!.txt" >nul
  465.           >>"%hiFile%!diffCode!.txt" echo ::!score!
  466.         )
  467.         echo(
  468.         %ClearLine%
  469.         call :ask "Press a key to continue..."
  470.         for %%A in (!configOptions!) do set "%%A=!%%ASave!"
  471.         call :mainMenu
  472.       )
  473.     )
  474.   )
  475. )
  476.  
  477.  
  478. ::-------------------------------------
  479. :getString  Prompt  Var  MaxLen
  480. :: Prompt for a string with max lengh of MaxLen.
  481. :: Valid keys are alpha-numeric, space, underscore, and dash
  482. :: String is terminated by Enter
  483. :: Backspace works to delete previous character
  484. :: Result is returned in Var
  485. set /a "maxLen=%3"
  486. set "%2="
  487. %sendCmd% prompt
  488. <nul set /p "=%~1 "
  489. call :purge
  490. :getStringLoop
  491. (%getKey% !upper! 0 1 2 3 4 5 6 7 8 9 " " _ - {Enter} !BS!)
  492. if defined key (
  493.   if !key! equ {Enter} (
  494.     echo(
  495.     exit /b
  496.   )
  497.   if !key! neq !BS! if !maxLen! gtr 0 (
  498.     set /a maxLen-=1
  499.     <nul set /p "=.!BS!!key!"
  500.     set "%2=!%2!!key!
  501.   )
  502.   if !key! equ !BS! if defined %2 (
  503.     set /a maxLen+=1
  504.     <nul set /p "=!BS! !BS!"
  505.     set "%2=!%2:~0,-1!"
  506.   )
  507. )
  508. if defined inKey %sendCmd% one
  509. goto :getStringLoop
  510.  
  511.  
  512. ::-------------------------------------
  513. :ask  Prompt  ValidKey [Validkey]...
  514. :: Prompt for a keypress.
  515. :: Wait until a ValidKey is pressed and return result in Key variable.
  516. :: Token delimiters, ), and poison characters must be quoted.
  517. %sendCmd% prompt
  518. <nul set /p "=%~1 "
  519. (set validKeys=%*)
  520. (set validKeys=!validKeys:%1=!)
  521. call :purge
  522. :getResponse
  523. (%getKey% !validKeys!)
  524. if not defined key (
  525.   if defined inKey %sendCmd% one
  526.   goto :getResponse
  527. )
  528. exit /b
  529.  
  530.  
  531. :purge
  532. set "inKey="
  533. for /l %%N in (1 1 1000) do (
  534.   set /p "inKey="
  535.   if "!inKey!" equ "{purged}." exit /b
  536. )<&%keyStream%
  537. goto :purge
  538.  
  539.  
  540. ::-------------------------------------
  541. :spinner  X  Y  ValueVar
  542. set /a d1=-1000000
  543. for /l %%N in (1 1 5) do for %%C in (%spinner%) do (
  544.   call :spinnerDelay
  545.   %plot% %1 %2 %%C
  546.   %draw%
  547. )
  548. call :spinnerDelay
  549. (%plot% %1 %2 %3)
  550. exit /b
  551.  
  552.  
  553. ::-------------------------------------
  554. :delay  centiSeconds
  555. setlocal
  556. for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "spinnerDelay=%1, d1=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100"
  557. :: fall through to :spinnerDelay
  558.  
  559. ::-------------------------------------
  560. :spinnerDelay
  561. for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "d2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, dDiff=d2-d1"
  562. if %dDiff% lss 0 set /a dDiff+=24*60*60*100
  563. if %dDiff% lss %spinnerDelay% goto :spinnerDelay
  564. set /a d1=d2
  565. exit /b
  566.  
  567.  
  568. ::-------------------------------------
  569. :mainMenu
  570. cls
  571. set "loadAvailable="
  572. echo Growth rate = !growth!
  573. echo(
  574. echo Main Menu:
  575. echo(
  576. echo   N - New game
  577. if defined replayAvailable echo   R - Replay previous game
  578. if defined saveAvailable   echo   S - Save a game
  579. if exist *.snake.txt       echo   L - Load and watch a saved game&set "loadAvailable=L"
  580.  
  581. echo   C - Control options
  582. echo   G - Graphic options
  583. echo   Q - Quit
  584. echo(
  585. set "hiAvailable="
  586. for /l %%N in (1 1 6) do if defined hi%%N (
  587.   if not defined hiAvailable (
  588.     echo Replay High Score:
  589.     echo(
  590.   )
  591.   set "desc=!desc%%N!........"
  592.   set "hiAvailable=!hiAvailable! %%N"
  593.   echo   %%N - !desc:~0,8! !hi%%N!
  594. )
  595. if defined hiAvailable echo(
  596. set "keys=N C G Q !hiAvailable! !replayAvailable! !saveAvailable! !loadAvailable!"
  597. call :ask ">" !keys!
  598. if /i !key! equ Q (
  599.   %sendCmd% quit
  600.   cls
  601.   exit
  602. )
  603. if /i !key! equ N (
  604.   set "replay="
  605.   set "replayAvailable=R"
  606.   set "saveAvailable=S"
  607.   goto :initialize
  608. )
  609. if /i !key! equ S (
  610.   if defined replayAvailable (
  611.     call :ask "HighScore # or P for Previous:" !hiAvailable! P
  612.   ) else (
  613.     call :ask "HighScore #:" !hiAvailable!
  614.   )
  615.   echo !key!
  616.   if /i !key! equ P (set "src=!gameLog!") else set "src=%hiFile%!key!.txt"
  617.   call :getString "Save file name:" file 20
  618.   copy "!src!" "!file!.snake.txt"
  619.   call :ask "Press a key to continue..."
  620. )
  621. if /i !key! equ L (
  622.   call :getString "Load file name:" file 20
  623.   if exist "!file!.snake.txt" (
  624.     set "replay=!file!.snake.txt"
  625.     goto :initialize
  626.   )
  627.   echo Error: File "!file!.snake.txt" not found
  628.   call :ask "Press a key to continue..."
  629. )
  630. if /i !key! equ R (
  631.   set "replay=!gameLog!"
  632.   goto :initialize
  633. )
  634. if !key! geq 1 if !key! leq 6 (
  635.   set "replay=%hiFile%!key!.txt"
  636.   goto :initialize
  637. )
  638. if /i !key! equ C call :controlOptions
  639. if /i !key! equ G call :graphicOptions
  640. goto :mainMenu
  641.  
  642.  
  643. ::-------------------------------------
  644. :controlOptions
  645. cls
  646. set "keys={Enter} T L R P"
  647. if !moveKeys! equ 4 set "keys=!keys! U D"
  648.                     echo Control Options:
  649.                     echo(
  650.                     echo   T - Type... = !moveKeys! keys
  651.                     echo(
  652.                     echo   L - Left... = !left!
  653.                     echo   R - Right.. = !right!
  654. if !moveKeys! equ 4 echo   U - Up..... = !up!
  655. if !moveKeys! equ 4 echo   D - Down... = !down!
  656.                     echo(
  657.                     echo   P - Pause.. = !pause!
  658.                     echo(
  659.                     echo   {Enter} - Return to Main Menu
  660.                     echo(
  661. call :ask ">" !keys!
  662. if !key! equ {Enter} goto :saveUserPrefs
  663. if /i !key! equ T (
  664.   if !moveKeys! equ 2 (set "moveKeys=4") else set "moveKeys=2"
  665.   goto :controlOptions
  666. )
  667. set "option= LLeft RRight UUp DDown PPause"
  668. for /f %%O in ("!option:* %key%=!") do (
  669.   call :ask "Press a key for %%O:"
  670.   for %%K in (0 1 2) do if "!key!" equ "!invalid:~%%K,1!" goto :controlOptions
  671.   for %%C in (!upper!) do set "key=!key:%%C=%%C!"
  672.   set "%%O=!key!"
  673. )
  674. goto :controlOptions
  675.  
  676.  
  677. ::-------------------------------------
  678. :graphicOptions
  679. cls
  680. echo Graphic Options:
  681. echo(
  682. echo   B - Border...... = !bound!
  683. echo   E - Empty space. = !space!
  684. echo   H - snake Head.. = !head!
  685. echo   S - Snake body.. = !body!
  686. echo   F - Food........ = !food!
  687. echo   D - Death....... = !death!
  688. echo(
  689. echo   G - Growth rate. = !growth!
  690. echo(
  691. echo   {Enter} - Rturn to Main Menu
  692. echo(
  693. call :ask ">" B E H S F D G {Enter}
  694. if !key! equ {Enter} goto :saveUserPrefs
  695. if /i !key! equ G (
  696.   call :ask "Press a digit for growth rate (0 = 10)" 0 1 2 3 4 5 6 7 8 9
  697.   if !key! equ 0 set "key=10"
  698.   set "growth=!key!"
  699.   call :loadHighScores
  700. ) else (
  701.   set "option=-BBorder:bound:-EEmpty Space:space:-HSnake Head:head:-SSnake Body:body:-FFood:food:-DDeath:death:"
  702.   for /f "tokens=1,2 delims=:" %%A in ("!option:*-%key%=!") do (
  703.     call :ask "Press a key for %%A"
  704.     for %%K in (0 1 2) do if "!key!" equ "!invalid:~%%K,1!" goto :graphicOptions
  705.     set "%%B=!key!"
  706.   )
  707. )
  708. goto :graphicOptions
  709.  
  710.  
  711. ::------------------------------------
  712. :saveUserPrefs
  713. (for %%V in (moveKeys up down left right space bound food head body death pause growth) do echo %%V=!%%V!) >"%userPref%"
  714. exit /b
  715.  
  716.  
  717. ::-------------------------------------
  718. :initialize
  719. cls
  720. if defined replay (
  721.   echo Replay Speed Options:
  722. ) else (
  723.   echo Speed Options:
  724. )
  725. echo                       delay
  726. echo    #   Description  (seconds)
  727. echo   ---  -----------  ---------
  728. for /l %%N in (1 1 6) do (
  729.   set "delay=0!delay%%N!"
  730.   set "desc=!desc%%N!           "
  731.   echo    %%N   !desc:~0,11!    0.!delay:~-2!
  732. )
  733. echo(
  734. call :ask "Pick a speed (1-6):" 1 2 3 4 5 6
  735. set "difficulty=!desc%key%!"
  736. set "delay=!delay%key%!"
  737. set "diffCode=%key%"
  738. echo %key% - %difficulty%
  739. echo(
  740. <nul set /p "=Initializing."
  741. set "axis=X"
  742. set "xDiff=+1"
  743. set "yDiff=+0"
  744. set "empty="
  745. set /a "PX=1, PY=height/2, FX=width/2+1, FY=PY, score=0, emptyCnt=0, t1=-1000000"
  746. set "gameStart="
  747. set "m=00"
  748. set "s=00"
  749. set "snakeX= %PX%"
  750. set "snakeY= %PY%"
  751. set "snakeX=%snakeX:~-2%"
  752. set "snakeY=%snakeY:~-2%"
  753. for /l %%Y in (0 1 %height%) do (
  754.   <nul set /p "=."
  755.   set "line%%Y="
  756.   for /l %%X in (0,1,%width%) do (
  757.     set "cell="
  758.     if %%Y equ 0        set "cell=%bound%"
  759.     if %%Y equ %height% set "cell=%bound%"
  760.     if %%X equ 0        set "cell=%bound%"
  761.     if %%X equ %width%  set "cell=%bound%"
  762.     if %%X equ %PX% if %%Y equ %PY% set "cell=%head%"
  763.     if not defined cell (
  764.       set "cell=%space%"
  765.       set "eX= %%X"
  766.       set "eY= %%Y"
  767.       set "empty=!empty!#!eX:~-2! !eY:~-2!"
  768.       set /a emptyCnt+=1
  769.     )
  770.     if %%X equ %FX% if %%Y equ %FY% set "cell=%food%"
  771.     set "line%%Y=!line%%Y!!cell!"
  772.   )
  773. )
  774. for %%A in (!configOptions!) do set "%%ASave=!%%A!"
  775. set "replayFinished="
  776. if defined replay (
  777.   %sendCmd% replay
  778.   %sendCmd% !replay!
  779.   call :waitForSignal
  780.   set "replay=(REPLAY at !difficulty!)"
  781.   set "read=1"
  782.   <&%keyStream% (
  783.     for /l %%N in (1 1 !configOptionCnt!) do if defined read (
  784.       set /p "ln="
  785.       if "!ln!" equ "END" (set read=) else set "!ln!"
  786.     )
  787.   )
  788.   set "keys="
  789.   set "hi=0"
  790.   for /f "delims=:" %%A in ('findstr "^::" "%hiFile%!diffCode!.txt" 2^>nul') do set "hi=%%A"
  791.   (%draw%)
  792.   call :delay 100
  793. ) else (
  794.   if defined hi%diffCode% (set "hi=!hi%diffCode%!") else set "hi=0"
  795.   (%draw%)
  796.   >"!gameLog!" (
  797.     for %%A in (!configOptions!) do (echo %%A=!%%A!)
  798.     (echo END)
  799.   )
  800.   echo(
  801.   if !moveKeys! equ 4 (
  802.     echo Controls: !up!=up !down!=down !left!=left !right!=right !pause!=pause
  803.   ) else (
  804.     echo Controls: !left!=left !right!=right !pause!=pause
  805.   )
  806.   echo Avoid running into yourself (!body!!body!!head!^) or wall (!bound!^)
  807.   echo Eat food (!food!^) to grow.
  808.   echo(
  809.   call :ask "Press a key to start..."
  810.   %sendCmd% go
  811. )
  812. set "pauseTime=0"
  813. set "xDiff!up!=+0"
  814. set "xDiff!down!=+0"
  815. set "xDiff!left!=-1"
  816. set "xDiff!right!=+1"
  817. set "yDiff!up!=-1"
  818. set "yDiff!down!=+1"
  819. set "yDiff!left!=+0"
  820. set "yDiff!right!=+0"
  821. set "!up!Axis=Y"
  822. set "!down!Axis=Y"
  823. set "!left!Axis=X"
  824. set "!right!Axis=X"
  825. set "xTurn!left!=1"
  826. set "xTurn!right!=-1"
  827. set "yTurn!left!=-1"
  828. set "yTurn!right!=1"
  829. set "playerSpace=!space!!food!"
  830. set ^"keys="!left!" "!right!" "!pause!"^"
  831. set "newHi="
  832. set "grow=0"
  833. if !moveKeys! equ 4 set ^"keys=!keys! "!up!" "!down!"^"
  834. if exist "%~dp0CursorPos.exe" if not defined replay (
  835.   cursorpos 0 -4
  836.   for /l %%N in (1 1 5) do (echo(                                             )
  837. )
  838. exit /b
  839.  
  840.  
  841. ::-------------------------------------
  842. :waitForSignal
  843. if not exist "%signal%" goto :waitForSignal
  844. del "%signal%"
  845. exit /b
  846.  
  847.  
  848. ::-------------------------------------
  849. :loadHighScores
  850. set "saveAvailable="
  851. for /l %%N in (1 1 6) do (
  852.   set "hi%%N="
  853.   for /f "delims=:" %%A in ('findstr "^::" "%hiFile%%%N.txt" 2^>nul') do (
  854.     set "hi%%N=%%A"
  855.     set "saveAvailable=S"
  856.   )
  857. )
  858. exit /b
  859.  
  860.  
  861. ::-------------------------------------
  862. :fixLogs
  863. setlocal enableDelayedExpansion
  864. for %%F in (*.snake) do (
  865.   ren "%%F" "%%F.txt"
  866.   call :fixLog "%%F.txt"
  867. )
  868. pushd "%SaveLoc%"
  869. for /f "delims=" %%F in ('dir /b SnakeHi*.txt 2^>nul') do (
  870.   set "file=%%~nF"
  871.   set "file=Snake1Hi!file:~-1!.txt"
  872.   ren "%%F" "!file!"
  873.   call :fixLog "!file!"
  874. )
  875. popd
  876. exit /b
  877.  
  878. :fixLog  filePath
  879. >"%~1.new" (
  880.   <"%~1" (
  881.     for %%A in (diffCode difficulty moveKeys up down left right) do (
  882.       set /p "val="
  883.       (echo %%A=!val!)
  884.     )
  885.   )
  886.   (echo growth=1)
  887.   (echo END)
  888.   more +7 "%~1"
  889. )
  890. move /y "%~1.new" "%~1" >nul
  891. exit /b
  892.  
  893.  
  894. ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  895. :controller
  896. :: Detects keypresses and sends the information to the game via a key file.
  897. :: The controller has various modes of input that are activated by commands sent
  898. :: from the game via a cmd file.
  899. ::
  900. :: Modes:
  901. ::
  902. ::   hold   - No input, wait for command
  903. ::
  904. ::   go     - Continuously get/send key presses
  905. ::
  906. ::   prompt - Send {purged} marker to allow game to purge input buffer, then
  907. ::            get/send a single key press and hold
  908. ::
  909. ::   one    - Get/send a single key press and hold
  910. ::
  911. ::   replay - Copy a game log to the key file. The next line in cmd file
  912. ::            specifies name of log file to copy. During replay, the controller
  913. ::            will send an abort signal to the game if a key is pressed.
  914. ::
  915. ::   quit   - Immediately exit the controller process
  916. ::
  917. :: As written, this routine incorrectly reports ! as ), but that doesn't matter
  918. :: since we don't need that key. Both <CR> and Enter key are reported as {Enter}.
  919. :: An extra character is appended to the output to preserve any control chars
  920. :: when read by SET /P.
  921.  
  922. setlocal enableDelayedExpansion
  923. for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
  924. set "cmd=hold"
  925. set "inCmd="
  926. set "key="
  927. for /l %%. in () do (
  928.   if "!cmd!" neq "hold" (
  929.     for /f "delims=" %%A in ('xcopy /w "%~f0" "%~f0" 2^>nul') do (
  930.       if not defined key set "key=%%A"
  931.     )
  932.     set "key=!key:~-1!"
  933.     if !key! equ !CR! set "key={Enter}"
  934.   )
  935.   <&%cmdStream% set /p "inCmd="
  936.   if defined inCmd (
  937.     if !inCmd! equ quit exit
  938.     set "cmd=!inCmd!"
  939.     if !inCmd! equ replay (
  940.       <&%cmdStream% set /p "file="
  941.       type "!file!" >&%keyStream%
  942.       copy nul "%signal%"
  943.     )
  944.     set "inCmd="
  945.   )
  946.   if defined key (
  947.     if "!cmd!" equ "prompt" (echo {purged}.)
  948.     if "!cmd!" equ "replay" (
  949.       copy nul "%signal%" >nul
  950.       set "cmd=go"
  951.     ) else (echo(!key!.)
  952.     if "!cmd!" neq "go" set "cmd=hold"
  953.     set "key="
  954.   )>&%keyStream%
  955. )
Advertisement
Add Comment
Please, Sign In to add comment