Ampersand Hunters, a Batch arcade game
Posted: 07 May 2020 09:47
Introducing Ampersand Hunters, A Batch Arcade Game.
It's no Snake.bat, but one day...
With thanks to Antonio /Aacini for his Getkey.exe program, and to Dave Benham, Ed Dyreen , Jeb and again, Antonio for what I've learned from their posts throughout this site and Stack overflow ( I began learning coding in November as something to fill spare time with )
The premise of the game is fairly simple - Make it to the Escape Cell without being Eaten by Ampersands (I was previously calling this game Escape the Ampersands)
The game becomes increasingly difficult to do so as the number of Enemies scales with the 'Level', and speed increases.
The complete game with sounds and the GetKey.exe can be downloaded in this zip file: https://drive.google.com/uc?export=down ... Lqul4G38GJ (Version 6.0)
There is of course more I could do with the game - Settings Menu's, Walls, Collectibles, 'Patterned' Playfields, Firing at enemies / Obstacles Etc. Perhaps in time I will.
A slightly earlier version of the game can be seen Here: https://www.youtube.com/watch?v=hMqt4JYzQyY
Would love to hear opinions / Feedback - Especially if you encounter any issues using the game.
A few points of note:
It's built for use on Systems running Windows 10 Version 1511 or newer, as the screen is built with the aid of ASCII Escape Codes
Additional Soundfiles and Antonio's getkey.exe are required to play the game in it's intended form - The game is scripted to attempt to download the required files if they aren't located in the necessary folder - After obtaining Permission. The game will not progress if the files are downloaded into the wrong folder, it will instead ask you to download the files again.
Speed of gameplay will vary depending on the capabilities of your computer. The difference between my old Notebook and my new PC is quite significant. Accordingly, The way in which a delay is effected in this game may need adjustment.
I did try build my own xcopy based controller to avoid having to use an external exe, but failed to make a stable version.
It's no Snake.bat, but one day...
With thanks to Antonio /Aacini for his Getkey.exe program, and to Dave Benham, Ed Dyreen , Jeb and again, Antonio for what I've learned from their posts throughout this site and Stack overflow ( I began learning coding in November as something to fill spare time with )
The premise of the game is fairly simple - Make it to the Escape Cell without being Eaten by Ampersands (I was previously calling this game Escape the Ampersands)
The game becomes increasingly difficult to do so as the number of Enemies scales with the 'Level', and speed increases.
The complete game with sounds and the GetKey.exe can be downloaded in this zip file: https://drive.google.com/uc?export=down ... Lqul4G38GJ (Version 6.0)
There is of course more I could do with the game - Settings Menu's, Walls, Collectibles, 'Patterned' Playfields, Firing at enemies / Obstacles Etc. Perhaps in time I will.
A slightly earlier version of the game can be seen Here: https://www.youtube.com/watch?v=hMqt4JYzQyY
Would love to hear opinions / Feedback - Especially if you encounter any issues using the game.
A few points of note:
It's built for use on Systems running Windows 10 Version 1511 or newer, as the screen is built with the aid of ASCII Escape Codes
Additional Soundfiles and Antonio's getkey.exe are required to play the game in it's intended form - The game is scripted to attempt to download the required files if they aren't located in the necessary folder - After obtaining Permission. The game will not progress if the files are downloaded into the wrong folder, it will instead ask you to download the files again.
Speed of gameplay will vary depending on the capabilities of your computer. The difference between my old Notebook and my new PC is quite significant. Accordingly, The way in which a delay is effected in this game may need adjustment.
I did try build my own xcopy based controller to avoid having to use an external exe, but failed to make a stable version.
Code: Select all
@ECHO OFF & Title validating system compatility...
If Not "%~1" == "priority" (start "" /b /high "%~F0" priority && EXIT)
Setlocal EnableExtensions || (Echo Your version of windows does not support this program. Exiting & Timeout 4 & Exit /B)
If not exist "%TEMP%\AmpHunt_1st_run.log" (For /F "Delims=" %%a in ('systeminfo') Do Echo "%%~a" | Find "Windows 10" && > "%TEMP%\AmpHunt_1st_run.log" Echo True & Set _=True) Else < "%TEMP%\AmpHunt_1st_run.log" Set /P _=
IF not defined _ (Echo Your version of windows does not support this program. Exiting & Timeout 4 & Exit /B)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
TITLE Ampersand Hunters
REM ::: Arcade style Batch Game By T3RRY https://www.youtube.com/channel/UCo3tS26Eg-ITbdNgWhB0MRQ
::
:: { Game requirements:
:: Windows 10 Version 1511 or newer.
:: Additional downloads required for controller and sounds unless complete version is downloaded
:: }
:: Youtube: https://youtu.be/hMqt4JYzQyY
::: [Version 7] For Windows 10
:: - 10 June 2020
:: - Enhanced game speed by Building and executing screen display array in a local environment and utilising high priority on game start
:: - Added BG.exe to the package to hide the cursor
:: - Modified Call to sound effect and the Start vbs component of the music player to redirect errors to stderr (2>Nul)
:: as the game iterates over the loop more times per second than the vbs can be started.
:: - 08 May 2020
:: Modified Way the ampersand is displayed to Not require "^" escaping
:: Adjusted Trail coloring to use 24 bit Color with ASCII codes and R G B values %Æ%[38;2;red;green;bluem
:: - Color gradient scales according to X /Y positions, Escape position also scaled to X/Y Coordinates,
:: matching the player trail.
:: Added a Loading bar in the Title
::: [Version 6.0] For Windows 10
:: - 06 May 2020
:: Added Theme.Song
:: - Changed positioning of Call to the Music Stopper and moved movement sound effect to accomadate looping the theme song
:: Added Sound effects For Escaping, Enemy teleport and Death.
:: Modified Delay timing to compensate For the time cost of playing the sound effect during each move instead of looping it
:: Added a loop into the start up component test to ensure all files are downloaded before continuing
:: Simplified the approach used for displaying player / enemy positions
:: Corrected Setlocal recursion issue that was resulting in missing operator after ~ 30 wins / losses
::: [Version 5.0] For Windows 10
:: - 02 May 2020
:: Support For Direct download of all files added
:: Support For movement keys extended to cover both cases
:: Simplified Variable setting For display characters and their Color, Can now be changed from one Location
:: Built in a speed delay that gets reduced with each level
:: Converted enemy Generation into array Form Supporting growth in enemy Numbers
:: Adjusted colors of enemy and player trails to make characters easier to see
:: Modified the display of the screen For smoother initial Display
:: Corrected a typo that allowed enemies to spawn at the Players Location
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::: { Define pathways and create subfolders used For self generated component files
::: - calls subroutines to create component files.
::: [ Test if All component files were Downloaded
If Not Exist "%~dp0AmpHunt_Components" (Set "AmpHunt_Components=%TEMP%\AmpHunt_Components") Else (Set "AmpHunt_Components=%~dp0AmpHunt_Components")
::: ]
::: [ Make folder in Temp drive to download component files if full version not downloaded
If not exist "%AmpHunt_Components%" MD "%AmpHunt_Components%"
::: ]
If not exist "%AmpHunt_Components%" MD "%AmpHunt_Components%"
Set "Player=%AmpHunt_Components%\BatchMusicPlayer.bat"
Set "VBSplayer=%AmpHunt_Components%\playMusic.vbs"
Set "MusicStopper=%AmpHunt_Components%\StopMusic.bat"
Set "Monitor=%AmpHunt_Components%\BatchMonitor.vbs"
::: { GetKeys.exe by Antonio Perez Ayala
::: - https://www.dostips.com/forum/viewtopic.php?t=3428
Set GetKeys="%AmpHunt_Components%\GetKey.exe"
Set "GetKeyTest=%AmpHunt_Components%\GetKey.exe"
::: }
::: { BG.exe Ver 3.9 SE by Carlos Montiers Aguilera
::: - https://github.com/carlos-montiers/consolesoft-mirror/releases
Set "BG.Util=%AmpHunt_Components%\BG.exe"
:::: }
::: [ sound by elmasmalo1. Used and shared under Creative Commons License Attribution 3.0 Unported (CC BY 3.0)
::: - Source: https://freesound.org/people/elmasmalo1/sounds/376968/
::: - License details: https://creativecommons.org/licenses/by/3.0/legalcode
Set "Move.Sound=%AmpHunt_Components%\bubble-pop.wav"
::: ]
::: [ Theme Song by Kai Engel. "Chant of the Nightblades"
::: - Used and shared under creative commons Attribution License 4.0
::: - Source : https://freemusicarchive.org/music/Kai_Engel/Death.Soundless_The_Renaissance/04_-_Chant_Of_Night_Blades
::: - https://creativecommons.org/licenses/by-nc-sa/4.0/
::: - License details: https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
Set "Theme.Song=%AmpHunt_Components%\ChantOfTheNightBlades.mp3"
::: ]
::: [ Escape Sound Effect by EVRetro
::: - Used and shared under creative commons 0 License - Universal Public domain
::: - Source : https://freesound.org/people/EVRetro/sounds/495005/
::: - License Details : https://creativecommons.org/publicdomain/zero/1.0/legalcode
Set "Escape.Sound=%AmpHunt_Components%\Escape.wav"
::: ]
::: [ Death.Sound Sound Effect by Fupicat
::: - Used and shared under creative commons 0 License - Universal Public domain
::: - Source : https://freesound.org/people/Fupicat/sounds/475347/
::: - License Details : https://creativecommons.org/publicdomain/zero/1.0/legalcode
Set "Death.Sound=%AmpHunt_Components%\Death.wav"
::: ]
::: [ Teleport Sound by Chinomaker
::: - Used and shared under creative commons 0 License - Universal Public domain
::: - Source : https://freesound.org/people/chinomaker/sounds/324644/
::: - License Details : https://creativecommons.org/publicdomain/zero/1.0/legalcode
Set "Teleport.Sound=%AmpHunt_Components%\Teleport.wav"
::: ]
::: - Renew component .bat and .vbs files with each launch in case folder location changes
Call :make_components
::: }
CHCP 65001 & CLS & REM Code page allows For use of non standard characters
::: { Commence vbs monitor to close the vbs scripts when cmd.exe is closed
start "" "%Monitor%"
::: }
:ReLoad
TITLE ? Verifiying Components
IF exist "%BG.Util%" %BG.Util% Cursor 0
::: [ Begin playing Theme Song If it's been downloaded
If Exist "%Theme.Song%" CALL "%Player%" "%Theme.Song%" 40 True
::: ]
::: { Starting speed enacted using a For /L loop Delay. Decremented to Increase speed in multiples of 50.
Set "Speed=10000"
::: }
:NewGame
::: { Creates variable Æ = Ascii-27 Escape code.
::: - http://www.dostips.com/Forum/viewtopic.php?t=1733
::: - https://stackoverflow.com/a/34923514/12343998
:::
::: - Æ (Alt 146) 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 "Æ=%%a"
)
::: }
::: { REM Define 'Play Field' Parameters. Allows Play Field Characteristics to be easily Changed. Only Hieght and Width need changing
::: - Outer Border
REM Hieght Max = 35 Min = 20
REM Width Max = 160 Min =35
If NOT "%~2" == "" (
Set "Hieght=%~1"
Set "Width=%~2"
) Else (
Set "Hieght=30"
Set "Width=160"
)
Set /A EndScore=(Hieght * Width)
Set /A Lines=Hieght+5
Set /A Columns=Width+0
::: - Establish Screen size. Larger screen sizes will result in slower Load times and Gameplay.
Cls & Mode Con cols=%Columns% Lines=%Lines% >nul 2>nul || (Echo.Invalid Params For width and hieght. Value must be an Integer. & Exit /B)
::: - Inner Border
Set "Axis_mins=2"
Set /A X_Axis_Boundary=Width - 1,Y_Axis_Boundary=Hieght - 1
:: Move Limits within Borders
Set /A Limit_Axis_Min=3,Limit_X_Max=X_Axis_Boundary - 1,Limit_Y_Max=Y_Axis_Boundary - 1
::: }
::: { Game can be modified to function without GetKey.exe, however, PerFormance is Exceptionally enhanced though it's use.
::: - Test For the existance of Ancillary .Exe required to run this program 'out of the box'
::: - Provide Option to easily download / Abort Game.
Set "Components=True"
For %%A In ("%GetKeyTest%" "%Move.Sound%" "%Theme.Song%" "%Escape.Sound%" "%Death.Sound%" "%Teleport.Sound%" "%BG.Util%") Do If Not Exist %%A Set "Components=False"
If /I "%Components%" == "False" (
PUSHD "%AmpHunt_Components%"
TITLE Components missing For Ampersand Hunters. Downloads required to continue.
Echo.%Æ%[33m This Program requires the following components to be downloaded in the folder:
Echo.%Æ%[32m %AmpHunt_Components%
Echo.
If Not Exist "%GetKeyTest%" Echo.%Æ%[32m Getkey.exe must be saved to %Æ%[34m %GetKeys%
If Not Exist "%Move.Sound%" Echo.%Æ%[32m bubble-pop.wav must be saved to %Æ%[34m %Move.Sound%
If Not Exist "%GetKeyTest%" Echo.%Æ%[32m Getkey.exe must be saved to %Æ%[34m %GetKeys% "%BG.Util%"
If Not Exist "%BG.Util%" Echo.%Æ%[32m BG.exe must be saved to %Æ%[34m "%BG.Util%"
If Not Exist "%Death.Sound%" Echo.%Æ%[32m Death.Sound.wav must be saved to %Æ%[34m %Death.Sound%
If Not Exist "%Theme.Song%" Echo.%Æ%[32m Chant of the NightBlades must be saved to %Æ%[34m %Theme.Song%
If Not Exist "%Teleport.Sound%" Echo.%Æ%[32m Teleport.wav must be saved to %Æ%[34m %Teleport.Sound%
Echo.
Echo.Would You Like to download them Now? %Æ%[33mY/N
For /F "Usebackq Tokens=* Delims=" %%C in (`"Choice /N /C:YN"`) Do If /I "%%C" == "Y" (
Echo.%Æ%[91mAmpersand Hunters will Continue once the Download browser is Closed.
If Not Exist "%GetKeyTest%" start /Wait "" "https://drive.google.com/uc?export=download^&id=1q02Ur2a9Wvjlh-uc_QKgx2c6yaX82lNT"
If Not Exist "%BG.Util%" start /Wait "" "https://drive.google.com/uc?export=download&id=1LMM3pxQlQYaV-w8WfFqnOl_3TMh4gT_f"
If Not Exist "%Move.Sound%" start /Wait "" "https://drive.google.com/uc?export=download^&id=146w6quLBrCxhon5Sk-aaZo2zs_RnGZKt"
If Not Exist "%Escape.Sound%" start /Wait "" "https://drive.google.com/uc?export=download&id=1okOTyKQa-t1zSL0Zf-LCs33y-zVad4mQ"
If Not Exist "%Death.Sound%" start /Wait "" "https://drive.google.com/uc?export=download&id=1eZeesi-cRkk8BIySm2JgpZB0-AwHWgHH"
If Not Exist "%Theme.Song%" start /Wait "" "https://drive.google.com/uc?export=download&id=1yeAYgoFYcxYIcss3IZlF5MW4OT3neKvL"
If Not Exist "%Teleport.Sound%" start /Wait "" "https://drive.google.com/uc?export=download&id=1HNQrQw0USOecPMGl1tdYpUM9qcDbzqqe"
POPD
Pause & CLS & Goto :ReLoad & REM ensure all components are downloaded into the correct folder with the correct name.
) Else (
EXIT
)
)
::: }
::: { Define Base variables used For displaying characters on screen
::: - Characters and their Color are defined here to allow them to be easily changed from the one Location.
Set "Player.Trail=•%Æ%[0m" & REM • Alt 7 ○ Alt 9
Set "Enemy.Trail=•%Æ%[0m" & REM • Alt 7 ○ Alt 9
::: [ FG Set index variable count must match the number of Characters in the set.
Set "FGSet=╬○ʘ¤" & REM Alt 206 ╬ 9 ○ 664 ʘ 207 ¤
Set "FGSet[i]=4"
::: ]
Set "ESCSYMBOL=☼%Æ%[0m" & REM Alt 15
::: [ Display character For enemy when escaped.
Set "space=%Æ%[37m%Æ%[7m %Æ%[0m"
::: ]
::: [ Outer and Inner Border Symbols
Set "BORDER.IN.SYMBOL=%Æ%[7m%Æ%[31m░%Æ%[0m" & rem alt 176
Set "BORDER.OUT.SYMBOL=%Æ%[7m%Æ%[37m▓%Æ%[0m" & rem alt 178
::: ]
::: [ Player character.
Set "P_C=%Æ%[33m☻%Æ%[0m" & REM Alt 21 § 1 ☺ 2 ☻ 3 ♥ 4 ♦ 5 ♣ 6 ♠ 8 ◘ 10 ◙ 11 ♂ 12 ♀
::: ]
::: [ Enemy Character.
Set "E_C=&"
Set "ENEMY=%Æ%[31m%E_C%%Æ%[0m"
::: ]
Set "Esc=%Æ%[37m^%Æ%[0m"
::: [ Define Number of Enemies Incements by 1 with each replay. Number is Decreased by one when Eaten
Set /A Enemies+=1
::: ]
:: Instruction Line Pos - Line number that inFormation is displayed to the player on
Set /A Instructions=hieght + 2
::: }
::: { Define Movement Control Keys
Set "Up=W"
Set "Down=S"
Set "Left=A"
Set "Right=D"
Set "Pause=P"
Set "Keys=%Up% %Left% %Down% %Right%"
Set "MoveKeys=%Keys%"
::: }
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Macro Definitions {
set LF=^
::Above 2 blank lines are required - do not remove
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
::: { Loading bar Macro
Set "Title.Text=Loading "
Set @Load.Title=Set Title.Text=!Title.Text!◘^& TITLE !Title.Text!
::: }
::: { Macro For changing enemy color During each loop
Set @Color.NPC=For %%n in (1 2) do if %%n==2 (%\n%
For /F "tokens=1 delims=," %%G in ("!Param!") do (%\n%
Set /A "Rand_Col=!random! * 6 / 32768 + 1" %\n%
If "!Rand_Col!" == "6" (Set "%%G=%Æ%[31m!E_C!%Æ%[0m") %\n%
If "!Rand_Col!" == "5" (Set "%%G=%Æ%[93m!E_C!%Æ%[0m") %\n%
If "!Rand_Col!" == "4" (Set "%%G=%Æ%[35m!E_C!%Æ%[0m") %\n%
If "!Rand_Col!" == "3" (Set "%%G=%Æ%[37m!E_C!%Æ%[0m") %\n%
If "!Rand_Col!" == "2" (Set "%%G=%Æ%[34m!E_C!%Æ%[0m") %\n%
If "!Rand_Col!" == "1" (Set "%%G=%Æ%[91m!E_C!%Æ%[0m") %\n%
) %\n%
) Else set Param=
::: }
::: { Display player trail and position.
Set "@Display.Player=ECHO(%Æ%[!L_Y_Pos!;!L_X_Pos!H%Æ%[38;2;!L_Y_Pos!0;100;!L_X_Pos!0m!Player.Trail!%Æ%[!Y_Pos!;!X_Pos!H!P_C!"
::: }
::: { Macro For testing player XY pos against NPC's to determine Game State changes
Set @Test.Positions=For %%n in (1 2) do if %%n==2 (%\n%
For /F "tokens=1 delims=, " %%G in ("!Param!") do (%\n%
If "!L_X_Pos!" == "!X_Pos!" If "!L_Y_Pos!" == "!Y_Pos!" ECHO(%Æ%[!Y_Pos!;!X_Pos!H!P_C!%\n%
For /L %%E in (1,1,!Enemies!) Do (%\n%
If "!X_Pos!" == "!AI%%E_X!" If "!Y_Pos!" == "!AI%%E_Y!" (%\n%
ECHO(%Æ%[!Y_Pos!;!X_Pos!H%Æ%[31m%Æ%[7mX%Æ%[0m%\n%
Set "G_Over=%Æ%[!Instructions!;1H%Æ%[K%Æ%[31mYou were Nommed by an Ampersand" ^& Set "Died=True" ^& Goto :end%\n%
) %\n%
)%\n%
If "!X_Pos!" == "!T_X!" If "!Y_Pos!" == "!T_Y!" (%\n%
ECHO(%Æ%[!Y_Pos!;!X_Pos!H%Æ%[31m%Æ%[7mX%Æ%[0m%\n%
Set "G_Over=%Æ%[!Instructions!;1H%Æ%[K%Æ%[31mYou Hit the Trap" ^& Set "Died=True" ^& Goto :end%\n%
) %\n%
If "!X_Pos!" == "!E_X!" If "!Y_Pos!" == "!E_Y!" (%\n%
ECHO(%Æ%[!Y_Pos!;!X_Pos!H%Æ%[36m%Æ%[7m!Esc!%Æ%[0m%\n%
For /L %%E in (1,1,!Enemies!) Do ECHO(%Æ%[!AI%%E_Y!;!AI%%E_X!H!space!%\n%
Set /A Score+=EndScore%\n%
Set "G_Over=%Æ%[!Instructions!;1H%Æ%[K%Æ%[36mYou've Escaped with !Score! points" ^& Goto :end%\n%
) %\n%
) %\n%
) Else set Param=
::: }
::: { Macro For calculating the Players movement
Set @Calculate.Move=For %%n in (1 2) do if %%n==2 (%\n%
For /F "tokens=1 delims=, " %%G in ("!Param!") do (%\n%
If /I "%%G" == "!Up!" If NOT "!Y_Pos!" == "!Limit_Axis_Min!" (Set /A "Y_Pos-=1" ^>nul)%\n%
If /I "%%G" == "!Down!" If NOT "!Y_Pos!" == "!Limit_Y_Max!" (Set /A "Y_Pos+=1" ^>nul)%\n%
If /I "%%G" == "!Left!" If NOT "!X_Pos!" == "!Limit_Axis_Min!" (Set /A "X_Pos-=1" ^>nul)%\n%
If /I "%%G" == "!Right!" If NOT "!X_Pos!" == "!Limit_X_Max!" (Set /A "X_Pos+=1" ^>nul)%\n%
If /I "%%G" == "!Pause!" (%\n%
TITLE Paused%\n%
Pause ^> Nul%\n%
)%\n%
) %\n%
) Else set Param=
::: }
::: { Macro's For calculating NPC's Moves
Set @AI.Move.1=For %%n in (1 2) do if %%n==2 (%\n%
For /F "tokens=1 delims=, " %%G in ("!Param!") do (%\n%
If "!%%G_X!" == "!X_Pos!" (%\n%
If !%%G_Y! LSS !Y_POS! (Set /A "%%G_Y+=1" ^>nul)%\n%
If !%%G_Y! GTR !Y_POS! (Set /A "%%G_Y-=1" ^>nul)%\n%
) Else (%\n%
If !%%G_X! LSS !X_POS! (Set /A "%%G_X+=1" ^>nul)%\n%
If !%%G_X! GTR !X_POS! (Set /A "%%G_X-=1" ^>nul)%\n%
)%\n%
) %\n%
) Else set Param=
Set @AI.Move.2=For %%n in (1 2) do if %%n==2 (%\n%
For /F "tokens=1 delims=, " %%G in ("!Param!") do (%\n%
If "!%%G_Y!" == "!Y_Pos!" (%\n%
If !%%G_X! LSS !X_POS! (Set /A "%%G_X+=1" ^>nul)%\n%
If !%%G_X! GTR !X_POS! (Set /A "%%G_X-=1" ^>nul)%\n%
) Else (%\n%
If !%%G_Y! LSS !Y_POS! (Set /A "%%G_Y+=1" ^>nul)%\n%
If !%%G_Y! GTR !Y_POS! (Set /A "%%G_Y-=1" ^>nul)%\n%
)%\n%
) %\n%
) Else set Param=
Set @AI.Teleport=For %%n in (1 2) do if %%n==2 (%\n%
For /F "tokens=1 delims=, " %%G in ("!Param!") do (%\n%
For %%P in (X Y) Do Set /A "%%G_%%P=!random! %% ( !Limit_%%P_Max! - !Limit_Axis_Min! ) + !Limit_Axis_Min!" ^>nul%\n%
If "!X_Pos!" == "!%%G_X!" If "!Y_Pos!" == "!%%G_Y!" Set /A "%%G_X=!random! %% ( !Limit_X_Max! - !Limit_Axis_Min! ) + !Limit_Axis_Min!" ^>nul%\n%
) %\n%
) Else set Param=
::: }
::: { Macro For updating variables used to show changes in gamestate
Set @LastPos.Update=For %%n in (1 2) do if %%n==2 (%\n%
For /F "tokens=1 delims=, " %%G in ("!Param!") do (%\n%
Set /A %%G+=1 ^>nul%\n%
For %%P in (X Y) Do For /L %%E in (1,1,!Enemies!) Do Set "L_AI%%E_%%P=!AI%%E_%%P!"%\n%
Set "L_Y_Pos=!Y_Pos!"%\n%
Set "L_X_Pos=!X_Pos!"%\n%
) %\n%
) Else set Param=
::: }
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: End Macro Definitions }
::: { Prepare the environment For Building Arrays and Expanding Macros.
Setlocal EnableDelayedExpansion
::: }
%@Load.Title%
::: { Define Variables For mapping errorlevel to Key.
::: - used For mapping Errorlevel to Key - Differs by Case
::: ** Numbers within the below ranges must not be assigned as other variable Names **
Set /A Keypos=47 & REM [48 - 57]
For %%A in (0 1 2 3 4 5 6 7 8 9) Do (
Set /A Keypos+=1
Set "!Keypos!=%%A"
)
%@Load.Title%
Set /A Keypos=64 & REM [65 - 90]
For %%A in (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) Do (
Set /A Keypos+=1
Set "!Keypos!=%%A"
)
%@Load.Title%
Set /A Keypos=96 & REM [97 - 122]
For %%A in (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) Do (
Set /A Keypos+=1
Set "!Keypos!=%%A"
)
::: }
%@Load.Title%
::: { Build screen background using For /L loop to Define each line of the Foreground into an Array
::: - to display in a smooth manner. Done within local environment to reduce memory usage during the game loop
Setlocal EnableDelayedExpansion
:: [ Select random Symbol from defined Foreground Set
Set /A rndFG=!random! %% !FGSet[i]!
Set "FGSYMBOL=%Æ%[32m!FGSet:~%rndFG%,1!%Æ%[0m"
:: ]
:: [ Prepare Playfield, inner and outer border variables For display
For /L %%H IN (%Limit_Axis_Min%,1,%Limit_Y_Max%) DO Set "Play.Field%%H=Echo."
For %%A in (Inner Outer) Do For %%B in (Vert Hor) Do Set "%%A.Border.%%B=Echo."
:: ]
%@Load.Title%
:: [ Define the Play Field
For /L %%A IN (%Limit_Axis_Min%,1,%Limit_X_Max%) DO (
For /L %%B IN (%Limit_Axis_Min%,1,%Limit_Y_Max%) DO (
Set "Play.Field%%B=!Play.Field%%B!%Æ%[%%B;%%AH!FGSYMBOL!"
)
)
:: ]
%@Load.Title%
:: [ Build the Vertical and Horizontal Edges of the Inner Border
For /L %%A IN (%Axis_mins%,1,%Y_Axis_Boundary%) DO (
For %%B IN (%Axis_mins%,%X_Axis_Boundary%) DO (
Set "Inner.Border.Vert=!Inner.Border.Vert!%Æ%[%%A;%%BH!BORDER.IN.SYMBOL!"
)
)
%@Load.Title%
For /L %%A IN (%Axis_mins%,1,%X_Axis_Boundary%) DO (
For %%B IN (%Axis_mins%,%Y_Axis_Boundary%) DO (
Set "Inner.Border.Hor=!Inner.Border.Hor!%Æ%[%%B;%%AH!BORDER.IN.SYMBOL!"
)
)
:: ]
%@Load.Title%
:: [ Build the Vertical and Horizontal Edges of the Outer Border
For /L %%A IN (1,1,%Hieght%) DO Set "Outer.Border.Vert=!Outer.Border.Vert!%Æ%[%%A;1H%BORDER.OUT.SYMBOL%%Æ%[%%A;%Width%H!BORDER.OUT.SYMBOL!"
%@Load.Title%
For /L %%A IN (1,1,%Width%) DO Set "Outer.Border.Hor=!Outer.Border.Hor!%Æ%[1;%%AH%BORDER.OUT.SYMBOL%%Æ%[%hieght%;%%AH!BORDER.OUT.SYMBOL!"
:: ]
%@Load.Title%
:: [ Display the Borders and the Playfield
For %%A in (Inner Outer) Do For %%B in (Vert Hor) Do !%%A.Border.%%B!
For /L %%D in (%Limit_Axis_Min%,1,%Limit_Y_Max%) do !Play.Field%%D!
:: ]
Endlocal & %@Load.Title%
::: }
::: { Define Starting Positions
:startpos
%@Load.Title%
For %%P in (X Y) Do (
Set /A "%%P_Pos=!random! %% ( Limit_%%P_Max - Limit_Axis_Min ) + Limit_Axis_Min"
Set "L_%%P_Pos=!%%P_Pos!"
)
For /L %%E in (1,1,!Enemies!) Do For %%P in (X,Y) Do (
Set /A "AI%%E_%%P=!random! %% ( Limit_%%P_Max - Limit_Axis_Min ) + Limit_Axis_Min"
Set "L_AI%%E_%%P=!AI%%E_%%P!"
)
For /L %%E In (1,1,!Enemies!) Do If "%X_Pos%" == "!AI%%E_X!" If "%Y_Pos%" == "!AI%%E_Y!" GOTO :startpos
::: - Initialise Teleport properties. Teleport properties are calculated based on starting score, which is Area based
Set Teleport=0
Set /A Teleport_Freq=(Hieght * Width) / 100
Set /A Teleport_Reset=Teleport_Freq * 5
::: [ define win condition 'Escape' and additional Loss condition 'Trap', ensuring values differ and within 'play field'
:Objects
%@Load.Title%
::: - %%O Object - %%P positional axis
For %%O in (E T) Do For %%P in (X,Y) Do Set /A "%%O_%%P=!random! %% ( Limit_%%P_Max - Limit_Axis_Min ) + Limit_Axis_Min"
For %%O in (E T) Do For %%P in (X,Y) Do If "!%%O_%%P!" == "!%%P_Pos!" GOTO :Objects
If "%E_X%" == "%T_X%" If "%E_Y%" == "%T_Y%" (GOTO :Objects)
Set "@Display.Escape=Echo.%Æ%[%E_Y%;%E_X%H%Æ%[48;2;%E_Y%0;100;%E_X%0m!ESCSYMBOL!"
::: ]
::: [ Condition a pause and holding value to intiate a choice option to begin gameplay.
Set "Key=!Pause!"
Set "Last.Key=NG"
::: ]
::: }
::: { Game Loop.
:Move
TITLE !Enemies! Ampersand Hunters pursue you.
Set /A Teleport+=1 & REM Increment count until next enemy teleport
%@Color.NPC% ENEMY
::: - Display Player and Enemies
(
%@Display.Player%
%@Display.Escape%& REM The escape is refreshed prior to Displaying Enemy Locations so the player can see all enemy locations
For /L %%E in (1,1,!Enemies!) do ECHO(%Æ%[!L_AI%%E_Y!;!L_AI%%E_X!H%Æ%[38;2;175;!L_AI%%E_Y!0;!L_AI%%E_X!m!Enemy.Trail!%Æ%[!AI%%E_Y!;!AI%%E_X!H!ENEMY!
)>"%AmpHunt_Components%\Animate.txt"
TYPE "%AmpHunt_Components%\Animate.txt"
%@Test.Positions% screen
%@LastPos.Update% Score
ECHO(%Æ%[%instructions%;1H%Æ%[K%Æ%[37m Escape the Ampersands [%Æ%[33m!MoveKeys!%Æ%[37m]
ECHO(%Æ%[K %Æ%[33mScore : %Æ%[36m !Score!%Æ%[0m
::: - Pause prior to opening Move.
If "!Last.Key!" == "NG" (
TITLE Ampersand Hunters. Level !Enemies! - Select a Move to Start.
For /F "UsebackQ Tokens=* Delims=" %%K in (`"Choice /N /C:!Up!!Left!!Down!!Right!"`) Do (
Set "Last.Key=%%K"
Set "Key=%%K"
)
)
::: [ Movement Move.Sound.
CALL "%Player%" "%Move.Sound%" 15 false > Nul 2> Nul
::: ]
::: [ If you do not wish to download GetKeys.exe, Enable Choice and REM out indicated lines, and the Download If Conditions.]
::: - Returns the Key literal instead of the errorlevel.
If Not Exist "%GetKeyTest%" For /F "Usebackq Tokens=* Delims=" %%K in (`"Choice /T 1 /N /C:0123456789abcdefghijklmnopqrstuvwxyz /D 0"`) Do Set "Key.In=%%K"
::: - Not used as a macro as the expansion of the choice command within the For Loop is significantly slower than executing the For loop Directly.
::: - Default switch results in a Free Move For the AI
::: ] Else :
::: [ GetKey.exe by Antonio - A.K.A Aacini https://stackoverflow.com/users/778560/aacini
::: - Can be found at: https://www.dostips.com/Forum/viewtopic.php?f=3&t=3428#p17101
If Exist "%GetKeyTest%" (
Set "Key.In="
%GetKeys% /N & REM out if GetKey.exe is not downloaded
::: - Assign Errorlevel from Getkey.exe to a variable, test if valid predefined Key.
Set "Key.In=!Errorlevel!" & REM out if GetKey.exe is not downloaded
::: - Return the Key literal instead of the errorlevel:
For %%K in ("!Key.In!") do Set "Key.In=!%%~K!" & REM out if GetKey.exe is not downloaded
)
::: ] End of GetKeys
::: [ Determine game action dependant on last Key in. Pause handley by Key.In and Key variables
::: - preserves movement direction when pause has completed.
For %%K in (!keys! !Pause!) Do (If /I "!Key.In!" == "%%K" Set "Key=%%K" & If /I Not "%%K" == "!Pause!" Set Last.Key=%%K)
%@Calculate.Move% !Key!
If /I "!Key!" == "!Pause!" Set "Key=!Last.Key!"
::: ]
::: [ Use substring modification and ASCII color codes to display last key press
For %%K in (!Key!) do Set "MoveKeys=!Keys:%%K=%Æ%[35m%%K%Æ%[33m!"
::: ]
::: [ expand Selected Macro's to calculate enemies movements.
::: - Positioned prior to Teleport so an enemy cant teleport to an adjacent cell and Consume you within the same Move.
For /L %%E in (1,1,!Enemies!) Do (
Set /A AI%%E_Move=!random! %%2 + 1
If "!AI%%E_Move!" == "1" %@AI.Move.1% AI%%E
If "!AI%%E_Move!" == "2" %@AI.Move.2% AI%%E
)
::: ]
::: [ Warp the enemy characters to a new position Only if they are not on the same ? axis at defined intervals
For /L %%A in (%Teleport_Freq%,%Teleport_Freq%,%Teleport_Reset%) Do (
If "!Teleport!" == "%%A" (
(CALL "%Player%" "%Teleport.Sound%" 20 false > Nul 2> Nul) || CALL "%Player%" "%Teleport.Sound%" 20 false > Nul 2> Nul
For /L %%O in (1,2,!Enemies!) Do If Not "!X_Pos!" == "!AI%%O_X!" %@AI.Teleport% AI%%O
For /L %%E in (2,2,!Enemies!) Do If Not "!Y_Pos!" == "!AI%%E_Y!" %@AI.Teleport% AI%%E
If "%%A" == "%Teleport_Reset%" (Set /A "Score+=Teleport_Reset" && Set "Teleport=0")
)
)
::: ]
::: { Enact Speed Delay
If !Enemies! LEQ 10 For /L %%A in (0,1,!Speed!) Do REM Delay
::: }
Goto :Move
::: } End of movement Loop
::: { * Script break * }
::: { Subroutine used to create sound related subporgrams }
:Make_Components
::: [ creates a companion batch file that's called with arguments For trackpath, volume and loop tf values
::: Parameters required For Player: [filepath.ext] [0-100] [True-False]
(
Echo.@ECHO OFF
Echo.Set "MusicPath=%%~1"
Echo.Set "vol=%%~2"
Echo.Set "Loop_TF=%%~3"
::: - Change to the Directory you want to create the Music Launcher in.
Echo.PUSHD "%%AmpHunt_Components%%"
::: - Ensure no Conflict with the Previous Script.
Echo For %%%%A In ^("%%MusicPath%%"^) Do Set "SoundSUFFIX=%%%%~nA"
::: - Creates a vbs Script to Launch the music (Occurs without any visual indication or prompting)
Echo.^( echo Set Sound = CreateObject^("WMPlayer.OCX.7"^^^)
Echo.echo Sound.URL = "%%MusicPath%%"
Echo.echo Sound.settings.volume = %%vol%%
Echo.echo Sound.settings.setMode "loop", %%Loop_TF%%
Echo.echo Sound.Controls.play
Echo.echo While Sound.playState ^^^<^^^> 1
Echo.echo WScript.Sleep 10
Echo.echo Wend
Echo.^)^>PlayMusic%%SoundSUFFIX%%.vbs
Echo.start /min PlayMusic%%SoundSUFFIX%%.vbs ^> Nul 2^> Nul
::: - Return to the Previous Directory
Echo.POPD
::: - Exit the Launcher and return to Previous batch program.
Echo.Goto :EOF
)>"%Player%"
::: ]
::: [ Monitor checks process status of cmd.exe every 1500 ms and calls StopMusic batch file to taskill all vbs scripts when
::: - cmd.exe process count is 0. Delay is to reduce CPU usage of the WMI service
(
ECHO Set objWMIService = GetObject ("winmgmts:"^)
ECHO Set proc = objWMIService.ExecQuery("select * from Win32_Process Where Name='cmd.exe'"^)
ECHO DO while proc.count ^> 0
ECHO Set proc = objWMIService.ExecQuery("select * from Win32_Process Where Name='cmd.exe'"^)
ECHO if proc.count ^< 1 then exit do
ECHO wscript.sleep 2000
ECHO loop
ECHO Set WshShell=createobject("wscript.shell"^)
ECHO WshShell.run "%MusicStopper%", 0, true
)>"%Monitor%"
::: ]
::: [ Simple taskkill script to terminate vbs scripts on program exit
(
Echo.@ECHO OFF
Echo.taskkill /pid WScript.exe /f /t ^>nul 2^> nul
Echo.Goto :EOF
)>"%MusicStopper%"
Timeout 1 >nul
Exit /B
::: } End of Subroutines
::: { Script exit and cleanup
:end
If /I "!Died!" == "True" (
CALL "%Player%" "%Death.Sound%" 80 False
Set /A Enemies-=1
If "!Score!" GEQ "!EndScore!" Set /A Score-=EndScore
) Else (
::: [ Increase Speed By reducing For /L Loop Iterations
If !Speed! GTR 1000 (Set /A Speed-=1000)
CALL "%Player%" "%Escape.Sound%" 60 False
)
::: ]
ECHO(%G_over%
Set /A Instructions+=1
:ExitMenu
ECHO(%Æ%[%Instructions%;1H%Æ%[K%Æ%[34m[E]xit [C]onitnue
For /F "Usebackq Tokens=* Delims=" %%K in (`"Choice /N /C:0123456789abcdefghijklmnopqrstuvwxyz"`) Do (
If /I "%%K" == "E" (
CALL "%MusicStopper%"
Del /Q "%Monitor%"
Del /Q "%MusicStopper%"
Del /Q "%Player%"
Del /Q "%VBSplayer%"
EXIT
)
If /I "%%K" == "C" (
Endlocal & Set "Score=%Score%" & Set "Enemies=%Enemies%" & Set "Speed=%Speed%"
GOTO :NewGame
)
)
Goto :ExitMenu
::: }