Real time keyboard inputs in batch - batch-file

This link
https://www.youtube.com/watch?v=eULe3DNS8DM
Shows a game made in batch. The game, called viewpoint, allows you to move around and shoot at enemies. This game seems to accept keyboard input in real time to perform actions. Is there any way I can get my batch file to accept keyboard input in real time as well?
(Guessing by the "Core" folder I saw in the game folder, there might be some other program or command involved.)

You could use the choice command (which is what snake.bat uses) however it can only take alpha-numeric input one at a time.
Here is a quick program I whipped up which uses choice to take WASD input.
#setlocal enableextensions enabledelayedexpansion
#echo off
prompt $$$G
title movement
color 0a
set length=
for %%a in (1 2 3) do (
set "length=!length! "
)
:controls
cls
echo Use WASD to move your character ([]).
echo.
echo %length%[]
choice /c wasd /n
if %errorlevel% equ 1 call:up
if %errorlevel% equ 2 call:left
if %errorlevel% equ 3 call:down
if %errorlevel% equ 4 call:right
:left
set length=!length:~0,-1!
goto controls
:right
set "length= %length%"
goto controls
:up
set length=!length:~0,-80!
goto controls
:down
set "length= %length%"
goto controls
The main thing you should focus on is the :controls label and how it uses the choice command to read input.

Related

How do I save variables from a batch file then load them to use them?

I'm a pretty inexperienced coder and I love batch because its one of the more straight forward coding languages but I want to save multiple variables to a txt file or other format then "load" those same variables to the batch file not to type so the player can see but so that I can use it
This is what I have so far for loading:
:nick
cls
color 02
set /p nick= Enter your nickname:
if exist ((savegame%nick%.txt) goto load)
goto instructions
:load
for /f "blevel=" %%a in (savegame%nick%.txt) do set blevel=%%a&goto loadexist
for /f "mlevel=" %%a in (savegame%nick%.txt) do set mlevel=%%a&goto loadexist
for /f "alevel=" %%a in (savegame%nick%.txt) do set alevel=%%a&goto loadexist
this is what I have for saving:
:save
cls
echo Saving please wait...
(echo blevel=%blevel%)> savegame%nick%.txt
(echo mlevel=%mlevel%)>> savegame%nick%.txt
(echo alevel=%alevel%)>> savegame%nick%.txt
timeout /t 5 /nobreak >nul
exit
Like I said I'm very inexperienced and my goal is to create a game please feel free to point out any flaws. In my game I have 3 characters Brutus, Mediana, and Achilles. blevel, mlevel, and alevel refers to the place in the game where you are and the character you chose to play as so you don't have to play the whole game to get to where you were.
As this is obviously still a work in progress I only have one instance where you can save and its in the first Brutus promt:
:brutus 1
set blevel=1
cls
echo.
echo.
echo.
echo You chose brutus good choice but are you sure this is who you want?
echo 1) go back and choose
echo 2) continue
echo 0) save
set /p c=C:\
if "%c%" == 1 goto choose character
if "%c%" == 2 goto brutus 2
if "%c%" == 0 goto save
goto brutus 1
So when you get to a choice like this your respective level goes up. Every time I reopen the game it either closes cmd when I type the nickname I used to save the file or it doesn't work and skips over it like the file or the variables in it don't exist. My intention is to do this with all three characters at every crucial choice so in the end I will probably have at least 100 per character.
your "save" logic is ok.
For loading, you need just a single line:
for /f "delims=" %%i in (savegame%nick%.txt) do set "%%i"
When you run it with echo on, you see that it processes every line and sets your variables.

batch file - 'The Syntax of the command is incorrect'

I've been making a text-adventure, but towards the end of my coding it came up with this error. Every time I try to continue from scene 5 to scene 5.1 it goes to a different scene and skips through it. Help?
Here is my code:
cls
echo You walk in through the doorframe, and into the dark room. You can't see a thing in the gloom, but when you put your hand on the wall you recognise the shape of a lightswitch.
echo.
pause
goto scene5.1
cls
echo You walk in through the doorframe, and into the dark room. You can't see a thing in the gloom, but when you put your hand on the wall you recognise the shape of a lightswitch.
echo.
pause
goto scene5.1
:scene5.1
cls
echo You flip the lightswitch down, and slowly the glowing bulbs switch on; illuminating the living room. In the gradually increasing light you see a table in the corner, and a large sofa that streches across the back wall. A few metres in front of the couch is a fireplace.
echo.
echo 1) Table
echo 2) Sofa
echo 3) Fireplace
echo 4) Go back
set /p type
if %type%==1 goto scene5.1.1
if %type%==2 goto scene5.1.2
if %type%==3 goto scene5.1.3
if %type%==4 goto scene5.1.4
C:\Windows\system32>echo 4) Go back
4) Go back
C:\Windows\system32>set /p type
The syntax of the command is incorrect.
goto was unexpected at this time.
It's probably the lack of an equals sign in set /p (well I know it is).
PS: Set /p var = PromptText is not the best command. It doesn't prevent wrong entry, and you don't check for it. Use Choice command instead. It only takes allowed entry.
The reason most examples use set /p is because choice was dropped from one windows version 15 years ago. That was along time ago.
CHOICE [/C choices] [/N] [/CS] [/T timeout /D choice] [/M text]
Description:
This tool allows users to select one item from a list
of choices and returns the index of the selected choice.
Parameter List:
/C choices Specifies the list of choices to be created.
Default list is "YN".
/N Hides the list of choices in the prompt.
The message before the prompt is displayed
and the choices are still enabled.
/CS Enables case-sensitive choices to be selected.
By default, the utility is case-insensitive.
/T timeout The number of seconds to pause before a default
choice is made. Acceptable values are from 0 to
9999. If 0 is specified, there will be no pause
and the default choice is selected.
/D choice Specifies the default choice after nnnn seconds.
Character must be in the set of choices specified
by /C option and must also specify nnnn with /T.
/M text Specifies the message to be displayed before
the prompt. If not specified, the utility
displays only a prompt.
/? Displays this help message.
NOTE:
The ERRORLEVEL environment variable is set to the index of the
key that was selected from the set of choices. The first choice
listed returns a value of 1, the second a value of 2, and so on.
If the user presses a key that is not a valid choice, the tool
sounds a warning beep. If tool detects an error condition,
it returns an ERRORLEVEL value of 255. If the user presses
CTRL+BREAK or CTRL+C, the tool returns an ERRORLEVEL value
of 0. When you use ERRORLEVEL parameters in a batch program, list
them in decreasing order.
Examples:
CHOICE /?
CHOICE /C YNC /M "Press Y for Yes, N for No or C for Cancel."
CHOICE /T 10 /C ync /CS /D y
CHOICE /C ab /M "Select a for option 1 and b for option 2."
CHOICE /C ab /N /M "Select a for option 1 and b for option 2."
As help says use errorlevels in descending order
if errorlevel 4 dosomething
if errorlevel 3 dosomething
if errorlevel 2 dosomething
if errorlevel 1 dosomething
if errorlevel 0 UserPressedCtrl+C
or in any order
if errorlevel 1 if not errorlevel 2 dosomething for 1
Do not use %errorlevel% as it can be overwritten by other programs.
#ECHO OFF
SETLOCAL
:scene4.6.1
:scene5.1
SET "scene=5.1"
cls
echo You flip the lightswitch down, and slowly the glowing bulbs switch on; illuminating the living room. In the gradually increasing light you see a table in the corner, and a large sofa that streches across the back wall. A few metres in front of the couch is a fireplace.
echo.
CALL :addchoice Table Sofa Fireplace "Go back"
GOTO makechoice
:scene5.1.1
ECHO AT table
goto :eof
:scene5.1.2
ECHO AT sofa
goto :eof
:scene5.1.3
ECHO AT fireplace
goto :eof
:scene5.1.4
:scene4.6
SET "scene=4.6"
echo You are IN a dank corridor dimly lit by sputtering torches
echo.
CALL :addchoice Doorway Corridor
GOTO makechoice
:makechoice
CHOICE /C %choices%
SET "scene=%scene%.%errorlevel%"
SET /a choicecount=0
SET "choices="
GOTO scene%scene%
:addchoice
SET /a choicecount+=1
ECHO %choicecount%) %~1
SET "choices=%choices%%choicecount%"
SHIFT
IF "%~1" neq "" GOTO addchoice
GOTO :EOF
This may save you a heap of programming. Please do not accept it as an answer since bgalea's answer actually answers your question. This is just an approach to make the construct-an-adventure exercise faster and easier.
For each scene, describe the scene and call :addchoice with parameters of the available choices. If a choice is multiple words, "enclose them in quotes".
The routine assigns 1 to the first choice in the list, 2 to the next and so on. The available choices are then recorded in choices.
go to makechoice. This prompts for an entry using the list in choices. Then append dot+the errorlevel of the response to the current scene number, clear the choices and goto scene+the calculated scene number.
Note that you can use an empy command-sequence to move between scenes by using the structure like in scene5.1.4 to scene4.6 (iow, scene 5.1+choice4 moves to 4.6)
This way, your response-sets become one line after your scene description and you never need to use a series of if-commands to move between scenes.

batch file sub routine

I'm trying to re-use the batch file code in order to perform a similar tasks in a menu pages.
The main menu consists of 10+ options.
When I go inside the each menu items, I need to display a following in text
Press [C] to Continue or [X] to exit [C/X]: _
I created labels in each menu time and re-direct to the code which is responsible for prompting the message and do necessary actions.
How can I use this following code as a subroutine, so that I don't have to re-write the code several times.At the moment I hard code it in each menu item. It would have been easy to call it as a sub routine.
:MiniMenu1
SET INPUT1=
SET /P INPUT1=Press [Y] to Continue Installation or [N] to go back [Y/N]:
IF /I '%INPUT1%'=='y' GOTO Mini_cont1
IF /I '%INPUT1%'=='n' GOTO Mini_back1
ECHO ============INVALID INPUT============
ECHO Please select a number from the Menu Options
ECHO -------------------------------------
ECHO ======PRESS ANY KEY TO CONTINUE======
PAUSE > NUL
GOTO MiniMenu1
Where as my code for main menu item pages are
:Selection1
:: MAin menu item 1
GOTO MiniMenu1
:Mini_cont1
:: xCopy update.zip C:\python27\ /y
#echo Update Completed.
pause
:Mini_back1
:: end
GOTO MENU
Ah - thinking along the right lines. Very good.
#echo off
setlocal
call :ask Question number one
if errorlevel 2 goto Q1X
call :ask Question number two
if errorlevel 2 goto Q2X
::get here for Q1Q2 responses both C
goto :eof
:ask
choice /c CX /N /M "%*"
goto :eof
Here's a basic template. From the prompt, type choice /? for instructions about options.
Hint: set "choices=wqzk" then in the subroutine choice /c %choices% /N /M "%*" would allow you to change the choices available. /n prompts with the available choices, so you've no need to specify that in the text, just make it obvious - Whatever, Quit, Zap, Kill should be obvious for wqzk for instance.
The return in %errorlevel% will the the sequence-number of the character chosen. W==>1, Q==>2..K==>4. In the traditional construct, if errorlevel n the comparison is true if errorlevel is n or greater than n so it would be traditional to use
if errorlevel 4 goto QnA4
if errorlevel 3 goto QnA3
if errorlevel 2 goto QnA2
:: if it gets here, errorlevel is 1 hence choice was first character.
which is shorter than the "modern" way
if %errorlevel%==1 goto QnA1
if %errorlevel%==2 goto QnA2
if %errorlevel%==3 goto QnA3
:: if it gets here, errorlevel is 4 or more hence choice was fourth or later character.
Note: %* means all of the arguments passed to the subroutine so /m "%*" neatly shows the arguments passed as a prompt. There's no voodoo about that. But be careful - text only and a few symbols if you like. Symbols with a special meaning to cmd may cause unexpected results
Variables created/changed/deleted after a setlocal will be deleted/restored/resurrected when a matching endlocal is encountered. Consequently, setlocal is often used as the first "action statement" in a batch - the environment is restored to pristine when the batch ends.
To remove variables within a batch using a subroutine, you could use
call :zap we dont want these variables
:zap
if "%1" neq "" set "%1="&shift&goto zap
goto :eof
(to delete variables we dont want these and variables
or :zap version 2
:zap
for %%a in (%*) do set "%%a="
goto :eof
To remove variables which all start with an identical character-pattern, use
FOR /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
(which will remove all variables starting $. $ isn't holy - you could substitute xyz for $ here and zap xyz123 xyz789 and xyzylofone for instance)
Naturally, you could also combine the techniques...
But - it's not expensive to ask a new question on SO. Not expensive at all. Cheap even. Asking a new question rather than tagging more issues onto an existing one makes finding a solution easier (like.. someone wanting to know how to delete variables possibly wouldn't expect to find it under a question titled "batch file sub routine" for instance. It also prevents the question from becoming a saga.

how does this batch script works?

i got this script for a site but i have some problems how the script works
the script
#setlocal enableextensions enabledelayedexpansion
#echo off
title movement
color 0a
set length=
set height=a
:controls
cls
echo Use WASD to move your character ([]).
echo.
for %%a in ( %height% ) do echo.
echo %length%[]
choice /c wasd /n
if %errorlevel% equ 1 call:up
if %errorlevel% equ 2 call:left
if %errorlevel% equ 3 call:down
if %errorlevel% equ 4 call:right
:left
set length=!length:~0,-1!
goto controls
:right
set length=%length%
goto controls
:up
set height=!height:~0,-2!
goto controls
:down
set height=%height% a
goto controls
ok now can someone explain the first line?
i serached the web and i think it will give value to variables when the command is reached
also i dont know what this means
set height=!height:~0,-2!
and this
set length=!length:~0,-1!
For enabledelayedexpansion see this blog post. (In short it makes variables work in a sane fashion.)
enableextensions seems to be a safety feature in case the command extensions have been disabled (though they appear to be on by default). It also isn't clear to me from a quick read what they are exactly (other than some newer command features).
Edit: Linked from the page #user3245060 mentions in hist comment is the Cmd page which indicates (at least some) commands that are affected by enableextensions and indicates that further details may be available in those commands specific pages. (It would also seem that Noodles has some idea about what is involved here.)
set height=!height:~0,-2! appears to be string processing (as per this link.

Batch Making Passwords

I have made a batch game where users can log in / register. But there is no point in having passwords if a person standing nearby can peep at the password. Normal password fields mask the characters with asterisks (*).
How can mask characters on a batch file?
I've seen this done on cmd before but I have no clue how.
You can use XCOPY for a hidden input, it can handle nearly all characters and you can also implement a backspace logic.
#echo off
setlocal EnableDelayedExpansion
call :input
echo(
echo '!input!'
if "!input!"=="password" echo OK
exit /b
:input
for /F "tokens=1 delims=# " %%a in ('"prompt #$H# & echo on & for %%b in (1) do rem"') do (
set "\b=%%a"
)
set "input="
:keyLoop
call :GetKey
if not defined key exit /b
if "!key!"=="!\b!" (
if defined input (
set "input=!input:~0,-1!"
<nul set /p ".=!\b! !\b!"
)
) ELSE (
<nul set /p ".=*"
set "input=!input!!key!"
)
goto :keyLoop
:GetKey
setlocal DisableDelayedExpansion
set "key="
for /F "usebackq delims=" %%L in (`xcopy /L /w "%~f0" "%~f0" 2^>NUL`) do (
if not defined key set "key=%%L"
)
(
endlocal
set "key=^%key:~-1%" !
exit /b
)
This code should be able to handle all characters, like ^!&%<>.
It's also possible to use backspace to delete the last entered character.
The line set "key=^%key:~-1%" ! seems odd, but it's used to escape the ! character with set "key=^!" ! in the delayed expansion context.
And to avoid problems for all other characters the last ! removes the caret, like in set "key=^A" ! will be evaluated to ``set "key=A"`
Ok, this is a bit different to what you may have had in mind, but that's you're fault for choosing batch for game dev.
The way I see it is you have 3 options:
Use an external program you self made in C#, C++, Python, [etc.]
Howver this requires an application to already do this for you (Which there probably is) or for you to have a knowledge in one of these languages
Use the choice command, to continuously take one key input and wait for the user to hit space to signify the end of the password
However this limits the password characters choice, and makes the program look ugly
Use 2 Batch threads, one that masks and tallies input while the other stores it to a variable.
This may be a bit dodgey at times, at would be a bit complicated but may be the only choice you have.
Now, as I was typing this an idea stuck my head on how to achieve this. Since it might take some time to test I thought I'd post the idea (as it seems to be a soloution to this problem, which has been around for a while).
Logic
One Batch Thread will simply use set /p to store all the input into a variable and upon completion will communicate to the other batch thread through the use of waitfor or a simple directory file.
Another Batch Thread would loop the pause >nul statement and would tally the number of times the pause statement is looped, printing out the appropriate amount of *'s. The other important job of this thread is to sense when the user has finished typing the password, upon which it exits.
Im starting to make this batch program now, but for now I'll just keep you informed of my idea so far.
Code
Login.bat
#echo off
Title Password Please:
:: This is the main code
REM This code relies on Masker.bat
REM SET password to be first and thrid letter,
REM of the day of the week.
set pass=%Date:~0,1%%Date:~2,1%
REM START Masker in the same window using /b tag and create hold.pass:
Echo 0 >%temp%\hold.pass
start /b Masker.bat "%pass%" *
REM Simply take input an leave the rest to Masker.bat
set /p pass_input=:
Echo 1 >>%temp%\hold.pass
cls
if /i "%pass%" NEQ "%pass_input%" (
Title Worng Password
Echo Wrong Password... Sorry.
Sleep 5
Exit
)
Pause > nul
REM Rest of Main game code is below or simply
:: START Main.bat & Exit
Masker.bat
#echo off
Title Password Please:
setlocal enabledelayedexpansion
:: This is not the main code
REM This code is called upon by Login.bat (or the Main.bat game code)
REM CREATE the variables "passlen" and "mask":
set password=%~1
set passlen=0
:miniloop
set /a passlen+=1
if "!password:~%passlen%,1!" NEQ "" goto :miniloop
set password=
set mask=%~2
if "%mask%" EQU "" set mask=*
REM MAIN loop
:loop
cls
for /l %%a in (1,1,%passlen%) do (<nul set /p=%mask%)
sleep -m 150
for /f "usebackq" %%a in ("%temp%\hold.pass") do (if "%%~a" EQU "1" Del %temp%\hold.pass & Exit)
goto :loop
It still needs some more improvements, but I've spent aroung 30 min on it with little success to make it dynamically tell you how many characters you have typed in.
Anyone cane take this up, be my guest. Everything else works fine
Mona
This works without pressing enter after input of the password.
If you enter the correct password, ok.
if you enter a wrong password, it will stop when you enter the 9th character (can be adapted).
It does not care about capitalization.
Problem: the password is stored as pure text in the code
#echo off
setlocal enabledelayedexpansion
set "s= abcdefghijklmnopqrstuvwxyz"
set p=
:loop
choice /C %s% /N >nul
set p=%p%!s:~%errorlevel%,1!&set /p =*<nul
if /i "%p%"=="secured" goto :right
if not "%p:~8,1%"=="" goto :wrong
goto :loop
goto :wrong
:right
echo you entered correct password: %p%
goto :eof
:wrong
echo you entered wrong password: %p%
goto :eof
You may use ReadFormattedLine subroutine for all kind of formatted input. For example, the command below read a password of 8 characters, display asterisks in the screen, and continue automatically with no need to press Enter:
call :ReadFormattedLine password="********" /M "Enter password (8 chars): "
This subroutine is written in pure Batch so it does not require any additional program, and it allows several formatted input operations, like read just numbers, convert letters to uppercase, etc. You may download ReadFormattedLine subroutine from Read a line with specific format.

Resources