-2

So I decided to learn Batch and I'm trying to program a small RPG/adventure game that is narrative driven for the RPG snuffs at the office. So I'm having a few problems and have a few questions.

@echo off
color F0
title The Kingdom of Kovalor
type Titlescreen.txt
pause >nul
goto MainMenu

:MainMenu
cls
type mainmenu.txt
echo.
echo Type in option and press Enter.
Set /p menu=
if "%menu%" equ "new game" goto NewGame
if %menu% equ credits goto Credits
if "%menu%" equ "load game" goto LGame
echo Try again.
if %menu% neq new game goto MainMenu
if %menu% neq credits goto MainMenu
if %menu% neq load game goto MainMenu
pause >nul

:Credits
cls
echo Made by XXXXXXXXX
echo.
echo.
echo Press any key to return to Main Menu.
pause >nul
goto MainMenu

:NewGame
cls
echo What is your name, adventurer?
echo.
Set /p name=
echo.
echo %name%, are you a man or woman?
echo.
Set /p sex=
goto Stats

:SaveGame
@echo @ECHO OFF                 > save%name%.bat
@echo SET name=%name%           >> save%name%.bat
@echo SET sex=%sex%             >> save%name%.bat
@echo SET playerHP=%playerHP%   >> save%name%.bat
@echo SET playerATK=%playerATK% >> save%name%.bat
@echo SET playerDEF=%playerDEF% >> save%name%.bat
@echo SET playerLVL=%playerLVL% >> save%name%.bat
echo.
echo Game saved correctly.
echo Press any key to continue.
pause >n
exit

:LGame
cls
echo.
echo What's your name?
echo.
Set /p name=
echo Load successful.
pause >nul
exit

:Stats
cls
set /a playerHP = 25
set /a playerATK = 5
set /a playerDEF = 0
set /a playerLVL = 1
echo These are your stats.
echo Health, when it depletes, you die.                       %playerHP%
echo Attack. The ammount of damage you deal.                  %playerATK%
echo Defense. Armor which reduces the damage you take.        %playerDEF%
echo Level dictates the experience you have as an adventurer. %playerLVL%
echo You can improve these as you go.
echo For now you have no weapons nor armor.
pause >nul
if %sex% equ man goto StartAdventureMan
if %sex% equ woman goto StartAdventureWoman


:StartAdventureMan
cls
echo Kovalor wasn't always like this. There was a time where one could
echo walk around town without being disturbed. The so-called king has
echo placed himself on the throne with the help of twisted creatures.
echo.
echo TUTORIAL *Press Space Bar to continue narrative.*
pause >nul
echo.
echo There have been talks about a coup or silent assasinations but 
echo nothing has been proven to be but a rumor.
echo Nonetheless, the King must fall.
pause >nul
echo.
echo %name% got out of bed that morning with a headache born from heavy
echo drinking the previous night. He got dressed and left for the tool
echo shed outside his house. The cold early-spring air snipping at his 
echo bare arms. His best hoe laid on the floor.
pause >nul
goto PickUpHoe

:StartAdventureWoman
cls
echo Kovalor wasn't always like this. There was a time where one could
echo walk around town without being disturbed. The so-called king has
echo placed himself on the throne with the help of twisted creatures.
echo.
echo TUTORIAL *Press Space Bar to continue narrative.*
pause >nul
echo.
echo There have been talks about a coup or silent assasinations but 
echo nothing has been proven to be but a rumor.
echo Nonetheless, the King must fall.
pause >nul
echo.
echo %name% got out of bed that morning with a headache born from heavy
echo drinking the previous night. She got dressed and left for the tool
echo shed outside her house. The cold early-spring air snipping at her 
echo bare arms. Her best hoe laid on the floor.
pause >nul
goto PickUpHoe

:PickUpHoe
echo.
echo TUTORIAL *Type take followed by an object and press enter in order 
echo to pick it up and add it to your inventory.*
set /p action1=
if "%action1%" neq "take hoe" echo TUTORIAL *Type take hoe followed by Enter.*
goto PickUpHoe
echo *Picked up hoe.*
pause >nul
goto SaveTutorial

:SaveTutorial
echo.
echo TUTORIAL *You can save progress whenever you can type by typing Save Game.*
echo *Try saving now.*
Set /p action2=
if "%action2%" equ "Save Game" goto SaveGame
if "%action2%" neq "Save Game" goto SaveTutorial
pause >nul  
exit

As you may notice, this isn't really too far along. And as I'm adding code I'm testing it. So the thing is that I can't get the LGame method (I don't know how you call that in Batch, complete beginner at programming in general so bear with me). For the moment it's just supposed to print the message, but if I run it it just crashes. Everything else works correctly.

Now for questions.

  • How could I make it so when you save the game, you go back to the point where you were?
  • When I get LGame to work, how exactly would you call the save file?

And, if possible, some pointers on an inventory system and a pause menu that you can bring up at any time and then go back to the screen you were in before. Any pointer in general?

Rishav
  • 3,818
  • 1
  • 31
  • 49
DavidRM
  • 25
  • 1
  • 4
  • 3
    Unfortunately this question is super broad, and is actually five questions, so it's not really a good fit for Stack Overflow. That said, you might have better luck on [Reddit](https://www.reddit.com/r/Batch/) or [SS64](https://ss64.org/viewforum.php?id=2). Also, assuming you're using something after Windows XP, you by default have access to batch, PowerShell, VBScript, and JScript. – SomethingDark Mar 28 '18 at 02:56
  • for your last question: just `call "save%name%.bat"` – Stephan Mar 28 '18 at 10:14
  • I am not compleatly sure how, but you can save information to a text file and then recall it later. That may be the best way to d it. There are many tutorials online on how to save to a .txt file from batch. – Jack Koskie Jan 26 '20 at 17:34

1 Answers1

0

First, I suggest to bookmark in your browser:

You can get help for every Windows command by running in a command prompt window the command with /? as parameter, for example if /?, set /?, ...


Second, I suggest to avoid echo. and use instead echo/ to output an empty line. Take a look on DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/ for the explanation.


Third, read my answer on Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files. The comparison operator EQU is for integer comparisons, not for string comparisons. It works also for string comparisons as fall-back if Windows command interpreter recognizes that one of the two arguments to compare is not an integer. But better is to use == for comparing two strings.


Fourth, don't use set /p if the user should choose one of several options. There are multiple facts which must be taken into account on prompting user for entering a string and assigning it to an environment variable:

  1. On usage of set /P "MyVar=Your choice: " the environment variable MyVar is not modified if the user presses intentionally or by mistake just RETURN or ENTER. This means if the environment variable MyVar is not defined already before the user prompt, it is still not defined after user prompt finished with just hitting key RETURN. And if MyVar is defined already before user prompt, it keeps its value unmodified in case of user presses just RETURN or ENTER.

  2. The user has the freedom to type any string on being prompted with set /P. The batch file writer has no control on what the user really enters. So the batch file writer must take into account that the user enters by mistake or intentionally a string which could result in an exit of batch file execution because of a syntax error or it does something completely different as it is defined for.

A simple example:

@echo on
:MainMenu
@set /P "menu=Your choice: "
if "%menu%" == "new game" goto NewGame
if %menu% == credits goto Credits
goto MainMenu

:NewGame
@echo Start a new game ...
goto :EOF

:Credits
@echo Made by XXXXXXXXX

This batch file with echo on instead of echo off at top is started from within a command prompt window for debugging purposes.

Just RETURN is pressed on user prompt on first run. Windows command interpreter exits batch processing because second IF condition is preprocessed before execution of IF command to:

if  == credits goto Credits

There is obviously missing the first argument. cmd.exe encounters this syntax error and exits batch processing with an appropriate error message. The reason is environment variable menu is not defined before user prompt and is still not defined after user prompt.

On second run of the batch file from within command prompt window credits is entered and the batch file works as expected.

On third run of the batch file from within same command prompt window again just RETURN is pressed on user prompt. The batch file prints again the credits. Why? The environment variable menu is still defined from second batch file execution with that string and the variable was not modified on pressing RETURN.

Okay, let us modify the example batch file to:

@echo on
:MainMenu
@set "menu=credits"
@set /P "menu=Your choice: "
if /I "%menu%" == "new game" goto NewGame
if /I "%menu%" == "credits" goto Credits
goto MainMenu

:NewGame
@echo Start a new game ...
goto :EOF

:Credits
@echo Made by XXXXXXXXX

This is already better as now environment variable menu is always predefined with value credits. So if the user enters nothing, the credits are displayed. Also the value of previous run of variable menu has no effect anymore on execution of batch file. And the string comparisons are case-insensitive now.

But is that really secure and fail safe now?

No, it isn't. The user still can enter by mistake a wrong string.

For example the user enters by mistake " instead of 2 which is easy on German keyboards as CapsLock+2 or Shift+2 results in entering ". The first IF command line after preprocessing is now:

if /I """ == "new game" goto NewGame

And this is again an invalid command line resulting in an exit of batch file processing because of a syntax error.

Let us assume a user enters on prompt the string:

" == "" call dir "%USERPROFILE%\Desktop" & rem 

Note: There is a space at end.

The first IF condition is preprocessed by Windows command interpreter to:

if /I "" == "" call dir "%USERPROFILE%\Desktop"   & rem " == "new game" goto NewGame

It can be seen that the batch files executes now a command not written in the batch file at all on both IF conditions.

How to get a user prompt fail safe and secure?

By using delayed environment variable expansion at least around code evaluating the user input string.

@echo on
:MainMenu
@setlocal EnableDelayedExpansion
@set "menu=credits"
@set "Label=MainMenu"
@set /P "menu=Your choice: "
if /I "!menu!" == "new game" set "Label=NewGame"
if /I "!menu!" == "credits" set "Label=Credits"
endlocal & goto %Label%

:NewGame
@echo Start a new game ...
goto :EOF

:Credits
@echo Made by XXXXXXXXX

Now the user input string does not modify anymore the command lines executed by Windows command interpreter. So an exit of batch file processing because of a syntax error caused by user input is not possible anymore. And the batch file never executes commands not written in batch file.

But there is a better command than set /P for a simple choice menu – choice.

@echo off
:MainMenu
cls
echo/
echo    1 ... Start a new game
echo    2 ... Load a game
echo    C ... Show credits
echo    E ... Exit
echo/
%SystemRoot%\System32\choice.exe /C 12CE /N /M "Your choice: "
if errorlevel 4 goto :EOF
if errorlevel 3 goto Credits
if errorlevel 2 goto LoadGame

:NewGame
echo Start a new game ...
goto :EOF

:Credits
echo Made by XXXXXXXXX
echo/
pause
goto MainMenu

:LoadGame
echo Loading game ...
goto :EOF

The user has no freedom anymore to enter something not defined by batch file writer. The batch file continues immediately after the user has pressed either 1, 2, c, Shift+C, e or Shift+E. Everything else is ignored by choice with exception of Ctrl+C.

The environment variable ERRORLEVEL has with four options always a value in range 1 to 4 after choice terminated with returning 1 to 4 as exit code to calling cmd.exe.

Note: if errorlevel X means IF GREATER OR EQUAL X. So it is always necessary to start with highest possible exit code of command choice.

As the exit code assigned to ERRORLEVEL is well known, it is possible on larger menus to optimize the code further by using appropriate labels:

@echo off
:MainMenu
cls
echo/
echo    1 ... Start a new game
echo    2 ... Load a game
echo    C ... Show credits
echo    E ... Exit
echo/
choice.exe /C 12CE /N /M "Your choice: "
goto Option%ERRORLEVEL%

:Option1
echo Start a new game ...
goto :EOF

:Option2
echo Loading game ...
goto :EOF

:Option3
echo Made by XXXXXXXXX
echo/
pause
goto MainMenu

:Option4

The usage of command CHOICE can make choice menus very simple to code.


Fifth, don't use command exit in a batch file without option /B. exit without /B always immediately exits entire command process independent on cmd.exe being started with /K to keep command process running and console window open after running a batch file like on explicitly opening a command prompt window and running a batch file, or on cmd.exe being started with /C to close after execution of batch file finished for whatever reason like on double clicking a batch file.

An exit of command process independent on starting option /K or /C and independent on calling hierarchy is not good for debugging a batch file from within a command prompt window.

See also answer on Where does GOTO :EOF return to?

Mofi
  • 46,139
  • 17
  • 80
  • 143