I found this tutorial to make a game on Notepad++ and make a batch file to run on CMD. Well here's what I have so far:
:ChooseWeapon
cls
echo "I almost forgot. Here are the weapons I have avaliable, choose one and begin your quest."
echo.
set /p weapon=What is your weapon? (Sword, Double-Bladed Axe, Dagger):
The point to this is to choose a weapon you wish to use by typing what you want. Now, the thing is I'm able to type "ghregff" and it would say that is my weapon. How do I make it so you have to choose either: Sword, Double-Bladed Axe, or Dagger?
You could make it a choice menu like below, and if they choose a number not 1 2 or 3, it will kick them back to enter a selection again.
#echo off
:chooseweapon
cls
echo "I almost forgot. Here are the weapons I have avaliable, choose one and begin your quest."
echo.
echo What is your weapon? (Sword, Double-Bladed Axe, Dagger):
echo 1 - Sword
echo 2 - Double-Bladed Axe
echo 3 - Dagger
echo.
set /P Weapon="Enter a choice: "
echo --------------------------------------------------------------------
for %%I in (1 2 3) do if #%Weapon%==#%%I goto wp%%I
goto chooseweapon
:wp1
Set weapon=Sword
goto end
:wp2
Set weapon=Double-Bladed Axe
goto end
:wp3
Set weapon=Dagger
goto end
:end
echo %weapon%
pause
#echo off
set "NumberWeapons=3"
:ChooseWeapon
color 07
cls
echo."I almost forgot. Here are the weapons I have avaliable, choose one and begin your quest."
echo.
echo.1 Sword
echo.2 Double-Bladed Axe
echo.3 Dagger
set /p Weapon=What is your weapon? (1-%NumberWeapons%):
echo.
if %Weapon% lss 1 goto :ChoiceError
IF %Weapon% gtr %NumberWeapons% goto :ChoiceError
GOTO :Start
:ChoiceError
COLOR CF
ECHO.Error! Choose a valid choice.
pause
goto :ChooseWeapon
:Start
echo.Replace this line with the rest of your stuff & pause
#ECHO OFF
SETLOCAL
SET setprompt=What is your weapon?
CALL :chooselist Sword, "Double-Bladed Axe", Dagger
ECHO(Choice made was %response%
CALL :chooselist2 Sword, "Double-Bladed Axe", Dagger
ECHO(Choice made was %response%
CALL :choosemenu Sword, "Double-Bladed Axe", Dagger
ECHO(Choice made was %response%
GOTO :EOF
:chooselist
SET valid=%*
SET "nchoices="
CALL :choose "%setprompt% (%valid:"=%):"
GOTO :eof
:chooselist2
SET valid=%*
SET "nchoices="
FOR %%Z IN (%*) DO ECHO %%~Z
CALL :choose "%setprompt%:"
GOTO :eof
:choosemenu
SET valid=%*
SET /a nchoices=0
FOR %%Z IN (%*) DO SET /a nchoices+=1&CALL ECHO %%nchoices%% : %%~Z
CALL :choose "%setprompt%:"
GOTO :eof
:choose
SET /p "response=%~1 "
IF NOT DEFINED response GOTO choose
IF DEFINED nchoices FOR /l %%Z IN (1,1,%nchoices%) DO IF "%%Z"=="%response%" CALL :setresp %valid%&GOTO :eof
SET /a cmatch=0
CALL :countresp %valid%
IF NOT %cmatch%==1 GOTO choose
GOTO :eof
:setresp
IF %response% neq 1 SET /a response-=1&shift&GOTO setresp
SET response=%~1
GOTO :eof
:countresp
SET $1=%~1
IF NOT DEFINED $1 (
IF %cmatch%==1 (SET response=%$3%)
GOTO :eof
)
CALL SET $2=%%$1:*%response%=%%
IF /i "%response%%$2%"=="%$1%" SET /a cmatch+=1&SET "$3=%~1"
shift&GOTO countresp
GOTO :eof
This is a flexible piece of code that allows you to make your choice in ne of three manners:
Using chooselist, the parameter-list is appended to setprompt and the user may choose to enter any response in full, or simply sufficient to unambiguously define the requirement. "s" would define Sword, for instance, but "do" would be required for "Double-Bladed Axe" and "da" for "Dagger" since "d" is ambiguous.
Using chooselist2 is similar, it simply lists the choices each on its separate line and asks for input.
Finally, choosemenu does the same, but numbers the line and the choice can be made using either the number or an unambiguous start-string.
The response will always be in response
The easiest way seems to be doing it through the findstr command.
:Choice
set /p weapon=What is your weapon? (Sword, Double-Bladed Axe, Dagger):
echo %weapon%| findstr /r "^Sword$ ^Double-Bladed Axe$ ^Dagger$">nul
if errorlevel 1 (
echo %weapon% was sadly not an option.
goto :Choice
)
echo you chose %weapon%.
(you need ^ and $. ^ means start of line, $ means end of line)
OR
if you want to use that system several times you could use findstr with parameters and a return value
:MakeChoice
set /p answer= :
echo %answer%| findstr /r "^%~2$ ^%~3$ ^%~4$ ^%~5$ ">nul
if errorlevel 1 (
echo "%answer%" is sadly not a valid choice, choose again.
goto :MakeChoice
)
set %~1=%answer%
goto :eof
You can than call the function this way:
echo choose a weapon(Sword, Axe, Dagger)
call :MakeChoice chosenOption "Sword" "Double-Bladed Axe" "Dagger"
echo you chose %chosenOption%
This works with 1-4 variables, but if you want more, you can always add ^%~6$ ^%~7$... after ^%~5$.
Related
Im making an rpg game in batch, and here is the code for the stat system so far
:SPSPEND
CLS
Echo You have %SP% stat points to spend, every stat point used increases that skill by 5.
Echo 1. Strength=%Strength%
Echo 2. Agility=%Agility%
Echo 3. Magic=%Magic%
Echo 4. Vitality=%MaxHP%
Echo 5. Defence=%Defence%
Echo 6. Archery=%Archery%
set /p choice=Choose what to put points into:
if %choice%=="1" Set /a Strength==%strength%+5
if %choice%=="2"
if %choice%=="3"
if %choice%=="4"
if %choice%=="5"
if %choice%=="6"
cls
set /a SP==%SP%-1
goto :rest
Not sure how to format soz. i need help with two things : how can i make it so that it doesnt close out and actually works, and how can i make a failsafe incase a person enters something other than what i already have set up.
Thanks in advance
I believe this is what you want.
I have tested it and am fairly certain it will work
:SPSPEND
CLS
if %SP% leq 0 goto end
Echo You have %SP% stat points to spend, every stat point used increases that skill by 5.
Echo 1. Strength=%Strength%
Echo 2. Agility=%Agility%
Echo 3. Magic=%Magic%
Echo 4. Vitality=%MaxHP%
Echo 5. Defence=%Defence%
Echo 6. Archery=%Archery%
set /p choice=Choose what to put points into:
if "%choice%"=="1" Set /a Strength=%Strength%+5& set /a SP=%SP%-1& goto SPSPEND
if "%choice%"=="2" Set /a Agility=%Agility%+5& set /a SP=%SP%-1& goto SPSPEND
if "%choice%"=="3" Set /a Magic=%Magic%+5& set /a SP=%SP%-1& goto SPSPEND
if "%choice%"=="4" Set /a MaxHP=%MaxHP%+5& set /a SP=%SP%-1& goto SPSPEND
if "%choice%"=="5" Set /a Defence=%Defence%+5& set /a SP=%SP%-1& goto SPSPEND
if "%choice%"=="6" Set /a Archery=%Archery%+5& set /a SP=%SP%-1& goto SPSPEND
echo invalid choice
pause
goto SPSPEND
cls
:end
pause
goto :rest
(This is my first post here, so bear with me)
Can you show the last user-input in a batch file? I'm gonna try to keep it simple here.
#echo off
:menu
echo Type 1 to proceed.
set /p example=
if "%example%" == "1" GOTO :proceed
GOTO :error
:proceed
pause
:error
cls
echo You wrote (last user input), that's not correct.
timeout 30
GOTO :menu
I know that I could replace the (last user input) with %example%, but then I'd have to make custom error messages for every category, and there are about 50 of them. It'd be easier with a last input command.
By the way, I've taught myself everything that I know about batch, so my example probably has major issues right now, but it works somehow.
You could centralize all user input into a function (user_input)
:menu1
echo Type 1 to proceed.
call :userInput example
if "%example%" == "1" GOTO :proceed
GOTO :error
:menu2
echo Type 42 to proceed.
call :userInput answer
if "%answer%" == "42" GOTO :proceed
GOTO :error
:userInput
set /p LAST_INPUT=
set "%1=%LAST_INPUT%"
exit /b
:proceed
pause
:error
cls
echo You wrote "%LAST_INPUT%", that's not correct.
timeout 30
GOTO :menu
I don't know how to do it without temp file. TO get the things written int the console you need the doskey /history (this will skip the running of the script itself):
#echo off
setlocal enableDelayedExpansion
set "last="
set "but_last="
doskey /history > log.txt
for /f "tokens=* delims=" %%# in (log.txt) do (
set "but_last=!last!"
set "last=%%#"
)
echo "%but_last%"
del /s /q log.txt >nul 2>nul
I've been reading how to avoid spaghetti code in batch files.
In the example of what spaghetti code is, I realized that the batch file that I use when I logon almost fits this example. Could someone please help me make my batch file not have spaghetti code?
#ECHO OFF
CLS
:MENU
echo Welcome %USERNAME%
echo 1 - Start KeePass
echo 2 - Backup
echo 3 - FireFox
echo 4 - Exit
SET /P M=Please Enter Selection, then Press Enter:
IF %M%==1 GOTO StarKeePass
IF %M%==2 GOTO Backup
IF %M%==3 GOTO FireFox
IF %M%==4 GOTO :EOF
GOTO MENU
:StarKeePass
SET keePass="%USERPROFILE%\KeePass\KeePass-2.30\KeePass.exe"
SET kdb="%USERPROFILE%\KeePass\PasswordDatabase\PasswordDatabase.kdbx"
echo I'll start KeePass for You
START "" %keePass% %kdb%
GOTO MENU
:Backup
SET backup="%USERPROFILE%\backup.bat"
call %backup%
GOTO MENU
:FireFox
cd "C:\Program Files (x86)\Mozilla Firefox\"
start firefox.exe
GOTO MENU
In this case, if you want to use subroutines you should do this:
#ECHO OFF
CLS
:MENU
echo Welcome %USERNAME%
echo 1 - Start KeePass
echo 2 - Backup
echo 3 - FireFox
echo 4 - Exit
SET /P M=Please Enter Selection, then Press Enter:
IF %M%==1 CALL :StartKeePass
IF %M%==2 CALL :Backup
IF %M%==3 CALL :FireFox
IF %M%==4 GOTO :EOF
GOTO MENU
:StartKeePass
SET "keePass=%USERPROFILE%\KeePass\KeePass-2.30\KeePass.exe"
SET "kdb=%USERPROFILE%\KeePass\PasswordDatabase\PasswordDatabase.kdbx"
echo I'll start KeePass for You
START "" %keePass% %kdb%
GOTO :EOF
:Backup
SET "backup=%USERPROFILE%\backup.bat"
call %backup%
GOTO :EOF
:FireFox
cd "C:\Program Files (x86)\Mozilla Firefox\"
start firefox.exe
GOTO :EOF
Note that I changed a few things. Instead of goto... goto menu, you should use call :label goto :eof/ exit /b. Besides that, you had a spelling error StartKeePass, and instead of set variable="value", it's better to use set "variable=value". This will also accept spaces in the value, but it won't add quotes to your variable
Next time you should probably post this to code review, because these things aren't really errors
If you wanted to remove gotos altogether, you can simply call the script again to keep using it. Also, look into the choice command if you're using a version of Windows later than XP, since it will eliminate the need to check if the user entered invalid input.
#echo off
cls
echo Welcome %USERNAME%
echo 1 - Start KeePass
echo 2 - Backup
echo 3 - FireFox
echo 4 - Exit
choice /C:1234 /M "Please enter your selection: " /N
:: The first option listed by choice's /C option will return an errorlevel value of 1, the second 2, and so on
if %errorlevel% equ 1 (
SET keePass="%USERPROFILE%\KeePass\KeePass-2.30\KeePass.exe"
SET kdb="%USERPROFILE%\KeePass\PasswordDatabase\PasswordDatabase.kdbx"
echo I'll start KeePass for You
START "" %keePass% %kdb%
)
:: I've converted these to one-liners simply for personal preference.
:: You can keep these the way you had them if you put them inside of parentheses like with option 1.
if %errorlevel% equ 2 call "%USERPROFILE%\backup.bat"
if %errorlevel% equ 3 start "" "C:\Program Files (x86)\Mozilla Firefox\firefox.exe"
if %errorlevel% equ 4 exit /b
:: Calls this script again, simulating a goto :MENU
:: Personally, I'd stick with a label and a goto in this instance,
:: but this is how you could do it if you don't want to use goto at all
call %0
If each choice the user can make is fairly simple (i.e. it can be simplified to one or two commands), you might want to code this way; otherwise, definitely use subroutines like Dennis suggested.
My take on organizing this, added a reset to m variable, allowed some accidental input to be dealt with, and made it all checked in one block of code.
Nothing wrong with 'Dennis van Gils' answer, figured i would show you a different approach.
#echo off
setlocal enableDelayedExpansion
:menu
set "m="
cls
echo/Welcome !username!
echo/
echo/1 - Start keepass
echo/2 - Backup
echo/3 - Firefox
echo/4 - Exit
echo/
set /p "m=Please enter selection, then press enter:"
if not defined m (
cls
echo/Error: Empty input.
pause
) else (
if "!m!" equ "1" (
set "keepass=!userprofile!\keepass\keepass-2.30\keepass.exe"
set "kdb=!userprofile!\keepass\passworddatabase\passworddatabase.kdbx"
echo/I'll start keepass for you
start "" !keepass! !kdb!
) else (
if "!m!" equ "2" (
set "backup=!userprofile!\backup.bat"
call !backup!
) else (
if "!m!" equ "3" (
cd "c:\program files (x86)\mozilla firefox\"
start firefox.exe
) else (
if "!m!" equ "4" (
goto :eof
) else (
cls
echo/Error: ["!m!"] not recognized.
pause
)
)
)
)
)
goto :menu
Note: echo/ is used as a habit, as echo: and echo\ i mistake for parts of a file path/url, and echo. is so painstakingly noted for its longer command time.
Also, i prefer using ! over % along with setlocal enableDelayedExpansion by pure preference, and ease of block coding.
I'm trying to make a simple text-based game and am trying to design fighting mechanics. Right now, once you enter a fight you have to either type "1" to attack or "2" to enter the fightmenu. I want to change it so that you can just press space to do a regular attack, but still be able to type "1" to open the fightmenu. Here is the code so far if you're interested:
:fighting
cls
set /a yourhit=%random% %%dmg%
set /a theirhit=%random% %%theirdmg%
set /a armor = %armor% - %theirhit%
if %theirhit% gtr %armor% set /a armor = 0 & set /a hp = %hp% - %theirhit%
if %yourhit% geq %theirhp% goto winner
if %theirhit% gtr %hp% goto loser
set /a theirhp = %theirhp% - %yourhit%
echo.
call :fightheadsup
echo - You hit them for %yourhit%!
echo.
echo - They hit you for %theirhit%!
echo.
echo 1.Continue Attacking
echo 2.Return to Fight Menu
echo.
set /p input12=Enter:
if %input12% equ 1 goto fighting
if %input12% equ 2 goto fightmenu
goto fightmenu
Enclose compared values in a pair of "double quotes" as follows (get used that always as a value could be empty or could contain a blank space character, in particular a value entered by a user):
if "%input12%" equ " " goto fighting
if "%input12%" equ "1" goto fightmenu
Another approach: set a default value in advance (self-explained in code):
echo.
echo 1. Continue Attacking ^(default choice, hitting ^<Enter^> suffices^)
echo 2. Return to Fight Menu
echo.
set "input12=1"
set /p "input12=Your entry [default=%input12%]:"
if "%input12%" equ "1" goto fighting
rem superabundant: if "%input12%" equ "2" goto fightmenu
goto fightmenu
Note proper escaping <, >, ( and ) characters in echo 1. ... command
In this type of applications is preferable to use choice command instead of set /P, because CHOICE get one key and continue without need to press Enter key:
choice /C 12 /N /M "Enter: "
if %errorlevel% equ 2 goto fightmenu
if %errorlevel% equ 1 goto fighting
The disadvantage of CHOICE command is that it can not read a space key. However, in important advantage of CHOICE over SET /P is that in CHOICE command you never will get a wrong input, so you may directly use CHOICE answer this way:
choice /C 12 /N /M "Enter: "
goto option-%errorlevel%
. . .
:option-1 fighting
. . .
:option-2 fightmenu
. . .
Well if you were to put this code onto a batch file:
it doesn't choose a random number (or if it does it always has the same result)
it does't seem to lose or win if you choose to fight
i've been teaching myself coding and this is my first time on a forum so please go easy on me :)
here is my code:
#echo off
title template
color 0F
pause
:menu
cls
echo 1.start
echo 2.instructions
echo 3.exit
set /p answer=Type the number of your option and press enter
if %answer%==1 goto start_1
if %answer%==2 goto instructions
if %answer%==3 goto exit
:exit
echo thanks for playing
pause
exit /b
:instructions
cls
echo instructions
echo.
echo This game is case-sensitive!
echo Just have fun with it!
pause
goto menu
:start_1
set /a s1=%random% * 3 / 32768 + 1
if %s1%==1 goto prefight_1
if %s1%==2 goto prefight_2
if %s1%==3 goto prefight_3
:prefight_1
cls
echo You have discovered 3 Turtles!
echo They dont see you!
set /p answer=would you like to (1)FIGHT or (2)RUN?
if %answer%==1 goto fight_1
if %answer%==2 goto run_1
:fight_1
set /a f1=%random% * 4 / 32768 + 1
if %f1%==1 goto lose_fight_1
if %f1%==2 goto win_fight_1
if %f1%==3 goto win_fight_1
if %f1%==4 goto win_fight_1
:prefight_2
cls
echo You have discovered 3 Turtles!
echo They see you!
set /p answer=would you like to (1)FIGHT or (2)RUN?
if %answer%==1 goto fight_2
if %answer%==2 goto run_1
:fight_2
set /a f2=%random% * 4 / 32768 + 1
if %f2% gtr 4 goto fight_2
if %f2% lss 1 goto fight_2
if %f2%==1 goto lose_fight_1
if %f2%==2 goto lose_fight_1
if %f2%==3 goto win_fight_1
if %f2%==4 goto win_fight_1
:prefight_3
cls
echo You have discovered 3 Turtles!
echo They see you!
echo They seem angry!
set /p answer=would you like to (1)FIGHT or (2)RUN?
if %answer%==1 goto fight_3
if %answer%==2 goto run_1
:fight_3
set /a f3=%random% * 4 / 32768 + 1
if %f3%==1 goto lose_fight_1
if %f3%==2 goto lose_fight_1
if %f3%==3 goto lose_fight_1
if %f3%==4 goto win_fight_1
:lose_fight_1
cls
echo Sorry,You LOST!
echo Thank you for playing!
echo made by: JEREMY
set /p answer==(1)continue or (2)quit?
if %answer%==1 goto start_1
if %answer%==2 goto menu
pause
:run_1
cls
echo You ran away
pause
goto start_1
First off it's better for humans to read when it's "equ" instead of "==".
The set /p VARIABLE= is easier to use when clear so use echo like so:
:Jelly_Attack_1
cls
echo AH! There's a swarm of angry jellyfish!
echo Act fast!
echo.
echo You can (1) fight or (2) RUN
set /p VARIABLE=
if %VARIABLE% equ 1 goto Fight_Jelly_1
if %VARIABLE% equ 2 goto Run
if %VARIABLE% neq 1 goto TEST
The fight part should look something like this:
:Fight_Jelly_1
cls
echo The jellyfish are more annoying than harmful!
echo You have a great advantage!
pause
set /a FIGHTNO=%random%
if %FIGHTNO% gtr 4 goto Fight_Jelly_1
if %FIGHTNO% lss 1 goto Fight_Jelly_1
if %FIGHTNO% equ 1 goto FAILED
if %FIGHTNO% equ 2 goto Fight_Jelly_1_Win
if %FIGHTNO% equ 3 goto Fight_Jelly_1_Win
if %FightNO% geq 4 goto Fight_Jelly_1_Win
Then when wanting to give gold or a reward on winning do this:
:Fight_Jelly_1_Win
cls
echo The fight was easy and you found some gold!
pause
set gold=0 (if you didn't have a gold variable)
set /a gold=gold+5 (to add gold)
goto FRAMENAME
I hope I helped!
I strongly suspect that you have set a variable random. If you've done that, then the value that you set in the environment overrides the magic variable.
You can clear it by set "random="
It's normal practice to use a setlocal after your #echo off. That way, any changes you make to the envirnment are backed out when the batch terminates. Without it, any changes made will remain until they are explicitly changed again.
Personally, I prefer
set /a value=%random% %% limit + 1
to generate a value 1..limit. If for no other reason, it's easier to type.
#echo off
setlocal
rem environment changes made after here will be backed-out when the batch finishes...
....whatever....
The setlocal command sets up a 'local' environment which exists only until the batch ends or an endlocal command is encountered.
see setlocal /? from the prompt for more info.
Your batch appears to work fine once I'd added a win_fight_1 routine.
Note however that batch will barf on set /p answer==(1)continue or (2)quit? but removing one of those = will fix it.
Beyond that, just watch whether you want to go to menu or start_1.
And the
if %f2% gtr 4 goto fight_2
if %f2% lss 1 goto fight_2
will be ineffective - certainly if you've used set /a f2=%random% %% 4 + 1
Fake random--
I confirmed that %random% is driven by system clock-- http://blogs.msdn.com/b/oldnewthing/archive/2010/06/17/10026183.aspx
use the clock MS to get a random number from 1 to 1000
here is one way to get milliseconds: https://answers.yahoo.com/question/index?qid=20100816021807AAz6eL3
Another possibility to introduce randomness is to start the game and then wait for user input i.e. "ready to start?" and when they start will introduce some randomness into the amount of time since cmd.exe started.