So I am working on creating a batch file game analogious to a "Memory" game. (ie where the player is presented a list of objects for a short time, then asked to repeat the pattern)
My problem comes in how to decrease the time the pattern is exposed to the player as the round # increases.
Here is my current code:
#echo off
set /a y=50
set /a x=1000
:foo
set /a y=%y% + %y%
set /a x= %x% - %y%
echo %y%
echo %x%
ping -n 10 -w %x% 127.0.0.1 > nul
goto foo
When run, the above code does present x and y values that change as expected, however the wait time is always the same. Why is this and how can I fix it?
Thank you for your time.
Firstly why dont you use sleep? It would work fine (type sleep /? for more info)
However, here is another way of doing this with for /l loops
#echo off
setlocal enabledelayedexpansion
set score=0
title Memory Test : Current Score = !score!
for /l %%a in (0,1,20) do (
Rem In the above sequence, increase 20 to the amount of times you want the test to be performed
set number[%%a] = !random!!random!
echo Number: !number[%%a]!
set /a wait=21-%%a
set /a wait=!wait!*1000/4
sleep -m !wait!
cls
set /p "input=What was the last number youy saw? "
if !number[%%a]! equ "!input!" (
set /a score=!score!+1
Echo Correct !
title Memory Test : Current Score = !score!
)else(
Echo Incorrect! Coreect Answer = !number[%%a]!
)
)
echo Calculating score...
pause
cls
echo.
if %score% leq 14 set msg="Nice Try! But you can do better!"
if %score% geq 15 set msg="Good Job! Your on your way to the top!"
if %score% equ 20 set msg="Your So Close! Almost a perfect socre!"
if %score% equ 21 set msg="You got a perfect score! Woderful!"
Echo %score%/21 : %msg%
echo.
pause
And that should work fine. Note you can change how long the test goes for, but for the first game they'll have a bit more then 5 seconds to study the question, and in the last round a quarter of a second!
Mona
In order for the ping/wait trick to work, the ip address must not exist. 127.0.0.1 is your own computer, so it has no opportunity to timeout since the ping response is successful and immediate.
Instead, choose an ip address that doesn't exist. E.g. 10.20.30.40 (assuming that doesn't exist.)
You can adjust the 10 in this to give approximately second resolution. Is that sufficient for your code?
ping -n 10 127.0.0.1 > nul
This is another option for later windows.
timeout /t 10 >nul
Related
I need help with an unknown issue in a recent batch file executed on Windows 10.
Proper function:
I am trying to make a math quiz which generates two numbers, a basic operand (+-x/), finds the answer, then checks it against an answer from a user. Additionally, the program is made to track certain information after a user has put in their answer. (Question number, the problem and answer, and the users response.)
My issue:
In certain scenarios the program will display the problem/answer in the "game" window rather than writing the problem/answer in the text file as intended.
The command is:
echo [Q]%m%>>"C:\Users\%username%\Desktop\%fname%.txt"
It is comment marked in the code below.
What I've done to fix the issue?
After testing for a descent while I discovered the issue seemed to revolve around the portion where it tries to move a problem/answer combo with division as the operation. This helped, but the issue started randomly popping up throughout future attempts to debug.
While I feel it is a bit frowned upon to ask two things at once I have two more issues.
Why does an operation like %a%%b%%c%=%d% (a,c,d being numbers and b being a /) break a certain command in my code consistently and how can I fix it?
Why does the same issue still randomly appear even if I erase all traces of division / which seems to cause my issue in the first place.
Here is the batch file:
::Initialization
#echo off
set /a prb=3
set file=Stat
set sss=s.
if %prb%==1 set tst=.
echo.
echo Welcome to math fire, you will get randomly generated
echo multiplication, addition, and subtraction problems. You
echo will go through a specified number before the game ends
echo and this window closes. You will be tracked in a file on
echo your desktop. You will have %prb% problem%sss%
echo.
pause
CLS
echo Get ready
timeout 5
set start=%time%
CLS
set /a num=1
set /a good=0
set /a bad=0
::===========================Set up beggining of stat file.
echo =-=-=-=-=-=>>"C:\Users\%username%\Desktop\%fname%.txt"
echo ===Start===>>"C:\Users\%username%\Desktop\%fname%.txt"
echo =-=-=-=-=-=>>"C:\Users\%username%\Desktop\%fname%.txt"
echo.>>"C:\Users\%username%\Desktop\%fname%.txt"
::===================================Main Body============
::[A] Num1 [B] Operator [C] Num2 [D] Answer [E] The problem [M] Problem and answer
:main
set /a a=%random% %% 30 + 1
::To remove the division section I changed the 4 below to 3
set /a b=%random% %% 4 + 1
set /a c=%random% %% 20 + 1
if %b%==1 set b=+
if %b%==2 set b=-
if %b%==3 set b=*
if %b%==4 set b=/
set /a d=%a%%b%%c%
set e=%a%%b%%c%
echo.
echo =============================%e%=?
echo.
timeout 1
set /p ans=+++++++++++++++++++++++++++++Answer:
set m=%e%=%d%
echo ===%num%===>>"C:\Users\%username%\Desktop\%fname%.txt"
::The following line is the glitching code
echo [Q]%m%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo [A]%ans%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo.>>"C:\Users\%username%\Desktop\%fname%.txt"
if %ans%==%d% goto p
CLS
echo.
echo -----------------------------Incorrect
set /a bad=%bad%+1
goto re
:p
CLS
echo.
echo -----------------------------Correct
set /a good=%good%+1
goto re
:re
if %num%==%prb% goto end
set /a num=%num%+1
goto main
:end
echo ===========>>"C:\Users\%username%\Desktop\%fname%.txt"
echo.>>"C:\Users\%username%\Desktop\%fname%.txt"
echo [Start]%start%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo [-End-]%time%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo [Right]%good%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo [Wrong]%bad%>>"C:\Users\%username%\Desktop\%fname%.txt"
echo.>>"C:\Users\%username%\Desktop\%fname%.txt"
echo =-=-=-=-=-=>>"C:\Users\%username%\Desktop\%fname%.txt"
echo ===-End-===>>"C:\Users\%username%\Desktop\%fname%.txt"
echo =-=-=-=-=-=>>"C:\Users\%username%\Desktop\%fname%.txt"
echo.>>"C:\Users\%username%\Desktop\%fname%.txt"
CLS
echo.
echo.
echo.
echo Congrats, check your desktop for your play info.
echo.
echo.
echo.
pause
exit
Use the syntax
>>"%filename1%" echo [Q]%m%
(my testfiles are allotted in variables)
Noting that m will contain a string such as 13/14=0
The character just before a redirector redirects the logical device number. You can get around this by moving the redirction to the start of the command or inserting a space before the redirector or using
>>"%filename1%" (
echo [Q]%m%
echo something else
echo more text
)
or
(
echo [Q]%m%
echo something else
echo more text
)>>"%filename1%"
which does the same thing - gather the output of the echoes and redirect the sum-output to the file.
Oh, BTW - batch does integer mathematics, so 13/4=3 - no decimals.
I have a batch script that I desperately need help with. I use a batch script to grab files from folders and move them. The script sweeps the folders every 30 sec but you can "press a key to continue" also. I need to change it so I can press a specific key, doesn't matter what key, and have it GO TO the top location of my script to reset.
Below is a striped down version of what I currently have.
#echo off
set /p username=ENTER LOGIN:
echo.
:pc
echo 1 -- Flats
echo 2 -- Simple Tabletop
set /P rmFunc="Enter a choice: "
for %%I in (1 x) do if #%rmFunc%==#%%I goto run%%I
:run1
set pc=300
goto begin
:run2
set pc=400
goto begin
:begin
set studio=TT
set computer=Handbag_1
set setnumber=
set studiosetnumber=%studio%_%setnumber%
set delay_swch=5
set delay_loop=30
:bottom
echo logged in as: %username%
timeout /t %delay_loop%
GOTO BOTTOM
It is not possible to determine what key was pressed when using TIMEOUT, so that command is of no help.
You could use the CHOICE command with the /T (timeout) and /D (default) options instead. You can no longer simply press any key. Instead you can only press one key to restart, and another specific key to continue, or wait till the default value (continue) is returned. The biggest drawback is it no longer has a visual countdown.
echo Press C to Continue, or R to Restart
choice /c cr /d c /t 30 /n /m "The process will automatically continue in 30 seconds "
if errorlevel 2 goto pc
goto bottom
You could display a countdown timer by adding a third undocumented default option and setting the timeout to 1 second. If the default is returned, then it decrements the counter. Once the counter reaches 0 then the desired time has elapsed and you treat it as Continue.
I use the SET /P trick to display the prompt with a without a newline. I end with a carriage return so that the next prompt displays from the beginning of the same line.
The countdown timing will be a bit off, but it should be plenty good enough.
The carriage return variable must be defined and delayed expansion must be enabled near the top (before any loop label).
:: Define CR to hold a carriage return (0x0D)
for /f %%A in ('copy /Z "%~dpf0" nul') do set "CR=%%A"
:: Delayed expansion must be enabled to use the CR variable
setlocal enableDelayedExpansion
The timer code then becomes
set wait=15
:waitLoop
<nul set /p ="Press C to Continue, or R to Restart. Auto continue in %wait% seconds. !CR!"
choice /c 0cr /t 1 /d 0 >nul
if errorlevel 3 echo(&goto pc
if errorlevel 2 echo(&goto bottom
set /a wait-=1
if %wait% equ 0 echo(&goto bottom
goto :waitLoop
timeout does not return errorlevel if interrupted, so perhaps one way to solve this is to time timeout
#ECHO Off
SETLOCAL
SET /a "starttime=1%time:~-5,2%%time:~-2%"
timeout /t 30
SET /a "endtime=1%time:~-5,2%%time:~-2%"
IF %endtime% lss %starttime% SET /a endtime +=6000
SET /a elapsed=endtime - starttime
ECHO %elapsed%
GOTO :EOF
elapsed should contain the resultant time in tens-of-milliseconds. It's unlikely to be exactly 3000 for a 'no keypress' situation, but perhaps if %elapsed% gtr 2980 echo no keypress would suffice.
Note that I use a time format of hh:mm:ss.hh so if yours is different, you'd need to adjust the time substringing.
Since the target here is a timeout of about 30 seconds, the calculations can be performed on the seconds digits only. The values are accumulated as 1ss(.)hh which ensures that there is not a leading zero so set /a will not attempt to enter octal mode. Since it's entirely possible that the end time will be in the next minute, the adding of 6000 compensates by adding-in the minute (6000 tens-of-milliseconds)
Since it seems to be necessary to build the entire batch,
#echo off
set /p username=ENTER LOGIN:
echo.
:pc
echo 1 -- Flats
echo 2 -- Simple Tabletop
set /P rmFunc="Enter a choice: "
:
for %%I in (1 x) do if #%rmFunc%==#%%I goto run%%I
:run1
set pc=300
goto begin
:run2
set pc=400
goto begin
:begin
set studio=TT
set computer=Handbag_1
set setnumber=
set studiosetnumber=%studio%_%setnumber%
set delay_swch=5
set delay_loop=30
:bottom
echo logged in as: %username%
SET /a "starttime=1%time:~-5,2%%time:~-2%"
timeout /t %delay_loop%
SET /a "endtime=1%time:~-5,2%%time:~-2%"
IF %endtime% lss %starttime% SET /a endtime +=6000
SET /a elapsed=endtime - starttime
if %elapsed% leq 2980 goto ???
GOTO BOTTOM
And - well there I'd have to leave it. You are setting studio and setnumber to constants within your code. Are these somehow related to "Process Class?" If you want to re-enter this data, then you'd need ??? above to be begin - but you'd need to set /p those values (which you haven't shown.) As for the file sweep - there's nowhere in your code that shows this filesweep happening. The modifications I have indicated will allow you to press any key to interrupt the 30-second bottom loop and re-enter the data.
I am trying to make a batch roguelike but I am running in to three main problems. First of all my message system is not working. Second there is a glitch where if i try to move somewhere where I can't the choice statement keeps writing the W, S, A, and D's at the bottom. Third and most importantly there is a very annoying flashing of the screen. I tried to minimize the time it takes to load but to no avail. Here is my code:
#echo off
setlocal enableextensions
mode con: cols=54 lines=30
set num=1
set nextVar=1
set oldVar=103
set message=a
cls
echo Loading...
:startup
if not %num%==1001 (
set b%num%=.
set /a num = %num% + 1
goto startup
)
cls
set b103=#
goto update
:update
choice /c wsad /n /m ""
if %errorlevel%==1 set /a nextVar = %oldVar% - 50
if %errorlevel%==2 set /a nextVar = %oldVar% + 50
if %errorlevel%==3 set /a nextVar = %oldVar% - 1
if %errorlevel%==4 set /a nextVar = %oldVar% + 1
if defined b%nextVar% (
set b%nextVar%=#
set b%oldVar%=.
set oldVar=%nextVar%
set message="a"
goto display
)
set message="You can not move there."
goto update
:display
set ln1=%b1%%b2%%b3%...
set ln2=%b51%%b52%%b53%...
set ln3=%b101%%b102%...
...
...
...
set ln8=%b351%%b352%...
set ln18=%b851%%b852%%b853%
set ln19=%b901%%b902%%b903%%b904%...
set ln20=%b951%%b952%%b953%%b954%%b955%%b956%...%b1000%
cls
if not "%message%"=="a" (
echo %message%
goto next
)
echo.
:next
echo.
echo %ln1%
echo %ln2%
echo %ln3%
echo %ln4%
echo %ln5%
echo %ln6%
echo %ln7%
echo %ln8%
echo %ln9%
echo %ln10%
echo %ln11%
echo %ln12%
echo %ln13%
echo %ln14%
echo %ln15%
echo %ln16%
echo %ln17%
echo %ln18%
echo %ln19%
echo %ln20%
echo.
goto update
I had to ... some sections to save space. If anyone can solve these problems in particularity the screen flashing that would be super helpful. Also if anyone has ideas on generation NetHack like dungeons that would also be appreciated. Thank you.
So problems 1 and 2 are related.
First of all my message system is not working. Second there is a glitch where if i try to move somewhere where I can't the choice statement keeps writing the W, S, A, and D's at the bottom.
Change the error goto statement for the update section. You want to go to the display section so the screen is redrawn (removing the old used choice prompt) and the error message is displayed.
set message="You can not move there."
goto display
Problem 3 is a bit more difficult due to the nature of batch.
Third and most importantly there is a very annoying flashing of the screen.
The flashing is caused primarily because of one command. The cls command. Instead of just redrawing the screen it is first causing the screen to turn black before the new output is drawn causing the flicker.
Step 1: Remove the cls command. This means that you will have to output 30 lines each time to fill the screen.
Reducing the flicker even more will require a bigger overhaul on your script. Instead of echoing each line use the natural ability of the command window to wrap lines to draw the whole screen. This will reduce the amount of echo calls to a couple. Your canvas is set to 54 x 30 so that equals 1620 characters to fill the whole screen at one time.
Step 2: Output the entire screen with a single or as few calls as possible to prevent drawing/scrolling delay and use the natural line wrapping ability of the console window.
Here is an example I put together to illustrate this second step. Let me know if you have any questions.
#echo off
( if "%~1"=="" start "" /HIGH %0 1 & exit /b 1 )
setlocal enabledelayedexpansion
mode con: cols=80 lines=25
set "mark=0"
set "switch=0"
:next
if %mark% geq 920 set "mark=0" & if %switch% equ 0 ( set "switch=1" ) else set "switch=0"
set top=........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
set bot=........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
if %switch% equ 0 set top=!top:~0,%mark%!^|!top:~%mark%!
if %switch% equ 1 set bot=!bot:~0,%mark%!^|!bot:~%mark%!
goto display
:display
echo %mark%
set /p "=%top:~0,920%" <nul
set /p "=%bot:~0,920%" <nul
ping 192.0.2.2 -n 1 -w 200 >nul
set /a mark+=1
goto next
Step 3: An additional step that helps would be to increase the processes priority level. I have also added this to my example script above on the second line.
I want to make a basic pinger in batch as my learning project and i came into a problem.Here is the code:
#echo off
color B
title Pinger v1.0
:OK
echo.
echo.
set /p t=Target I.P.:
echo.
echo.
echo This is not an IP address!
echo.
goto OK
set /p a=Packet size:
echo.
:start
set ifer=
set /p ifer=Start Ping (y/n):
if %ifer%==y goto 8
if %ifer%==Y goto 8
if %ifer%==n goto OK
if %ifer%==N goto OK
:8
echo.
echo.
echo.
echo.
ping %t% -t -l %a%
My question is, How can i check if t contains a valid IP address an not some random data?
and also, how can i make a code that translates a web address to an ip address(Don't have to answer this though)
I don't know exactly what you're trying to get at here. I made a program that will take your IP or host name and ping it with a user determined packet size, and amount of times to ping. I only tried 1.1.1.1 and www.google.com, but it should work for anything else.
#echo off
#title Pinger v1.1
color B
setlocal EnableDelayedExpansion
:ipInput
cls
set /p tryIP=Target IP:
:: pinging ip once (-n 1) with one byte of data (-l 1) to check if it's valid
ping -n 1 -l 1 !tryIP! >nul & if errorlevel 1 (
echo IP: !tryIP! is invalid, try correcting your input or using a different IP
pause
goto ipInput
)
cls
echo IP: !tryIP! is Valid
set /p pingCount=Enter number of pings:
set /p packets=Enter packet size:
echo Pinging !tryIP! with !packets! bytes for !pingCount! time^(s^)
:: You can either use this line (beneath)
REM ping -n !pingCount! -l !packets! !tryIP!
:: Or you can use this for loop from here.........
:: for /l indicates type of operation in this case it will take (start at, add or
subtract by, end at)
:: %%a in this case, based on /l will always equal the number
:: of times it's looped through..
:: (starting at 1, moving up by 1 each time, and ending after 32)
for /l %%a in (1,1,%pingCount%) do (
ping -n 1 -l !packets! !tryIP! >nul
cls
echo Pinging !tryIP! with !packets! bytes for !pingCount! time^(s^)
set /a percentage=%%a*10000/!pingCount!
if !percentage! LSS 100 echo ......!percentage:~0,0!.!percentage:~0,2!%%
if !percentage! GEQ 100 if !percentage! LSS 1000 echo ......!percentage:~0,1!.!percentage:~1,2!%%
if !percentage! GEQ 1000 echo ......!percentage:~0,2!.!percentage:~2,2!%%
)
:: the if statements are used to correct the formating on the percentages
:: since batch can't use floating point decimals,
:: you have to get a little creative sometimes.
:: dual % signs are so it doesn't think you're trying to set a variable
:: using ( or ) without that >>>^ (eg on lines 20 and 34)
:: will sometimes mess things up.
:: ........ to here. the benefit of a for loop is that you can see your progress,
:: and it's much much faster as the ping command will wait between pings.
echo Done
pause
goto ipInput
I created a batch file that selects a random playing card using the variable %random%. the batch script keeps looping until %random% is between 1 and 13, and does it again for the suit. I then convert the variables that are set as numbers into text, so the batch file would say something like this: Four of Hearts, or King of Spades. The only problem is, it takes forever! If you open CMD.exe and type in
Echo %random%
and do that until the number is between 1 and four, you will be there FOREVER. Even if you put it into a batch file and use a loop, It still takes about twenty seconds. Is there a way to cut down the time, by perhaps narrowing down the search BEFORE the random number generation? I'm really not sure. In case it helps, or you can't understand me, here's the code:
#echo off
:loop
cls
echo generating card...
set num=%random%
if /i %num% GTR 13 goto loop
if /i %num% LSS 1 goto loop
goto next
:next
set suit=%random%
if /i %suit% GTR 4 goto next
if /i %suit% LSS 1 goto next
goto next2
:next2
if %num%==11 set num=jack
if %num%==12 set num=queen
if %num%==13 set num=king
goto next3
:next3
if %suit%==1 set suiter=Hearts
if %suit%==2 set suiter=Diamonds
if %suit%==3 set suiter=Clubs
if %suit%==4 set suiter=Spades
goto ech
:ech
echo %num% of %suiter%
echo.
echo.
echo.
echo press any key to choose again
pause >nul
goto loop
You can use a little math to get a number between 1 and 13 on the first try:
set /a num=13*%random%/32768+1
and the same thing for 1 and 4
set /a suit=4*%random%/32768+1
See How to use random in BATCH script? - very similar to what you're asking
You can completely eliminate the search using a simple remainder operation, thus limiting the generated random numbers to be in the range [1,13] and [1,4]. This will also simplify the code much. You can achieve this using the 'set /a' command which can be used for arithmetic.
Just change your script to read:
#echo off
:loop
cls
echo generating card...
set /a num=%random% %% 13 + 1
set /a suit=%random% %% 4 + 1
if %num%==11 set num=jack
if %num%==12 set num=queen
if %num%==13 set num=king
if %suit%==1 set suiter=Hearts
if %suit%==2 set suiter=Diamonds
if %suit%==3 set suiter=Clubs
if %suit%==4 set suiter=Spades
goto ech
:ech
echo %num% of %suiter%
echo.
echo.
echo.
echo press any key to choose again
pause >nul
goto loop
Good luck!