Rpg batch level system error? - batch-file

So i seem to find it difficult to put an 'if' statement inside another 'if' statement. I have the labels for gotos set up correctly the error occurs when the code goes to the levelstats
The code is meant, once the player has met the max exp, to go to the next level. The lvlguage checks to see if the exp requirements are met. That works fine. It goes to levelstats and then the prompt closes.
:LvlGuage
If %CharExp% GEQ %CharMaxExp% (
Goto LevelStats
)
Goto MENU
:LevelStats
::the error starts here
If %CharLevel%==1 (
Goto Level2
)
Goto MENU
If %CharLevel%==2 (
Goto Level3
)
Goto MENU
:: This goes on till level 10
:Level2
If %CharExp% GEQ 100 (
Set /a CharExp=%CharExp% -100
Set CharMaxExp=280
Set CharLevel=2
Set /a CharAttack=(%CharAttack% * 1.5) + 1
Goto LEVELUP
)
Goto MENU
:Level3
If %CharExp% GEQ 280 (
Set /a CharExp=%CharExp% -280
Set CharMaxExp=784
Set CharLevel=3
Set /a CharAttack=(%CharAttack% * 1.5) + 1
Goto LEVELUP
)
Goto MENU
:LEVELUP
Cls
Echo You Have Leveled Up.
Timeout 2 >nul
Goto MENU

Your variables are calculated once just when your script starts. Take a look ath this: http://www.ss64.com/nt/delayedexpansion.html
You need to add Setlocal EnableDelayedExpansion at the beginning at your script and adress to your vars with !varname! instead of %varname% when you want to get the changed values. This will always give you the last set value of the variable instead of the first assigned value.

Related

Sum in batch script

How can I make the sum of the imputed numbers given by the user from the keyboard ? I tried a for loop but is endless. I cannot figure out a break statement.
::#ECHO OFF
setlocal EnableDelayedExpansion
set /p X=
SET /A suma=0
:Loop
FOR %%G IN (%X%) DO (
IF %%G GTR 0 (
SET /A suma=%suma%+%%G
)
)
SHIFT
GOTO Loop
:completed
echo %suma%
What i want to do is to make the program more user friendyl like echo somthing for the user to know it is supposed to write somthing. I know the correct code for this question, but the numbers are given as parameters in the command (syntax: script.bat parameter1 parameter2 parameter3).
::#ECHO OFF
SET /A suma=0
:Loop
IF "%1"=="" GOTO completed
FOR %%F IN (%1) DO (
IF %1 GTR 0 (
SET /A suma=%suma%+%1
)
)
SHIFT
GOTO Loop
:completed
echo %suma%
Please give me any idea for the breaking statement in the first example or how can I modify the code to take the numbers from the users imput variable and not as paramaters.
Thank you.
SET /A suma=0
set "X=%*"
if not defined X set /p "X=No parameters detected "
if not defined X ECHO No user-input detected&goto completed
FOR %%G IN (%X%) DO (
IF %%G GTR 0 (
SET /A suma=suma+%%G
)
)
:completed
echo %suma%
%* means the command-line tail. If no tail, then ask user for input. If still no data, issue message and show result.
shift moves the command line tail one position, so %2 becomes %1, etc. You haven't provided a test to exit the routine - and the command-line tail is presumably empty, so you are shifting it (which does nothing) and looping.
The for...%%G.. processes the entire list %X%, so there's no point in the shift/loop - the data has already been processed.

What is the reason for "( was unexpected at this time." on an IF command line with %var%?

When I start the batch file as posted below, I got this error
( was unexpected at this time.
I think this happens on the IF command line if %ad%==60 ( but I am not sure.
( was unexpected at this time.
#echo off
color 0f
title TITLE
mode con cols=50 lines=25
set ad = 0
set s = 0
set m = 0
set h = 0
set d = 0
if exist start.txt (
del start.txt
goto :1
) else (
exit
)
:1
if %ad%==60 (
:: Something here
set ad = 0
)
:: MINUTES
if %s%==60 (
set /a m=m+1
set s = 0
)
:: HOURS
if %m%==60 (
set /a h=h+1
set m = 0
)
:: DAYS
if %h%==24 (
set /a d=d+1
set h = 0
)
cls
echo Something here...
timeout 1 > nul
set /a ad=ad+1
set /a s=s+1
goto :1
What could be the reason for this error message on execution of the batch file?
For a start,
set ad = 60
will not set ad to 60. It will set the variable adspace to space60, leaving ad to whatever it was before the script started.
In your case, it's almost certainly an empty string because the command that would result from that would be the same as that in the following transcript (note the error generated):
d:\pax> if ==60 (
( was unexpected at this time.
If you want nicely spaced out expressions, you already know how to do that, since you used it to increment h. In other words:
set /a "ad = 0"
This isn't technically an answer, (that has already adequately been provided). It is just an example to show you how you may optionally shorten your script a little:
#Echo Off
Color 0F
Title TITLE
Mode 50,25
Set /A ad=s=m=h=d=0
If Not Exist "start.txt" Exit /B
Del "start.txt"
:1
If %ad% Equ 60 (
Rem Something here
Set "ad=0"
)
Rem Minutes
If %s% Equ 60 Set /A m+=1,s-=60
Rem Hours
If %m% Equ 60 Set /A h+=1,m-=60
Rem Days
If %h% Equ 24 Set /A d+=1,h-=24
ClS
Echo Something here...
Timeout 1 >Nul
Set /A ad+=1,s+=1
GoTo :1
Notes: 1. Using Timeout 1 will not increment clocklike (in accurate seconds), it would be approximately one second plus the time taken to run through :1 again. 2. Be careful not to fall into Set /A's octal trap, by ensuring that you don't have leading 0's in your variables.
I have IF command without spaces, and also batched with command in quotes; still got error ( was unexpected at this time. when called batch file from command line. If launched from explorer, the batch file crashed.
Here's the crash code:
if %file%==local (
set miss=n
set /p miss=Any missing?
set miss=%miss:~0,1%
if /I %miss%==y (
Goto check2
)
)
When I echo the value of miss before the IF statement, I get %miss:~0,1%
TO fix this, I enabled delayed expansion, to force values to be updated at runtime, and works ok now.
if %file%==local (
set miss=n
set /p miss=Any missing?
set miss=!miss:~0,1!
if /I !miss!==y (
Goto check2
)
)

Why are mathematical operations and output of environment variables in an ELSE branch not working as expected?

I am trying to use nested if-else statements in order to implement or operator.
The problem is that the code only works outside the last nested else statement and I can't figure out why.
I added some notes marked with // that are not actually in the script to help you get a clue of what I am trying to do.
Here is my batch script:
:computerMakePick
setLocal
set /a currentNumber= 15
set /a addOne=%currentNumber%+1
set /a addTwo=%currentNumber%+2
//the next segment implements OR operator for two conditions using nested if-else statement
if %addOne% == 7 ( //checking first condition.
echo Computer chose: %addOne%
set /a currentNumber= %addOne%
)else (
if %addTwo% == 8 ( // now checking: OR second condition
echo Computer chose: %addTwo%
set /a currentNumber= %addTwo%
)else ( // if not both of the above then do this. NOW this section below doesn't work
set /a bottomlimit= 1
set /a upperlimit= 2
set /a limit=%upperlimit%-%bottomlimit%+1
set /a randomChoice= %bottomlimit% + %RANDOM% %% %limit%
set /a currentNumber= %currentNumber%+%randomChoice%
echo Computer chose: %currentNumber%
)
)
endLocal & set /a currentNumber= %currentNumber%
goto :eof
If I take the last else section to outside like this below, then it works:
:computerMakePick
setLocal
set /a currentNumber= 15
set /a addOne=%currentNumber%+1
set /a addTwo=%currentNumber%+2
//the next segment implements OR operator for two conditions using nested if-else statement
if %addOne% == 7 ( //checking first condition.
echo Computer chose: %addOne%
set /a currentNumber= %addOne%
)else (
if %addTwo% == 8 ( // now checking: OR second condition
echo Computer chose: %addTwo%
set /a currentNumber= %addTwo%
)else (
echo. // need to put something in here or else it doesn't work.
) // could also delete this last else-statment but it doesn't matter
)
//now this below works fine. and I don't understand why under second-else section it doesn't
set /a bottomlimit= 1
set /a upperlimit= 2
set /a limit=%upperlimit%-%bottomlimit%+1
set /a randomChoice= %bottomlimit% + %RANDOM% %% %limit%
set /a currentNumber= %currentNumber%+%randomChoice%
echo Computer chose: %currentNumber%
endLocal & set /a currentNumber= %currentNumber%
goto :eof
By saying it's not working I mean if I print the values of each variable: bottomlimit, upperlimit, limit, etc. when they are defined inside the second else statement, for example for the command line echo value of limit is = %limit% I get blanks (nothing).
Why is this happening and how can I fix it to work inside the second else statement?
Use the following code:
#echo off
:computerMakePick
setLocal
set "currentNumber=15"
set /a addOne=currentNumber + 1
set /a addTwo=currentNumber + 2
rem // the next segment implements OR operator for two conditions using nested if-else statement
if %addOne% == 7 ( rem // checking first condition.
echo Computer chose: %addOne%
set "currentNumber=%addOne%"
) else if %addTwo% == 8 ( rem // now checking: OR second condition
echo Computer chose: %addTwo%
set "currentNumber=%addTwo%"
) else ( rem // if not both of the above then do this. NOW this section below doesn't work
set "bottomlimit=1"
set "upperlimit=2"
set /a limit=upperlimit - bottomlimit + 1
set /a randomChoice=bottomlimit + %RANDOM% %% limit
set /a currentNumber+=randomChoice
setlocal EnableDelayedExpansion
echo Computer chose: !currentNumber!
endlocal
)
endLocal & set "currentNumber=%currentNumber%"
goto :EOF
Environment variables are always of type string. So even on using integers, the numbers are stored in memory as strings and not as integers. Therefore don't use set /a variable=number if there is no real reason to do so as this results in converting number from string to integer for the arithmetic expression, and converting it back from integer to string for assigning the result of this arithmetic expression to environment variable.
Usage of environment variable expansion within an arithmetic expression which is the string after set /a is usually nonsense as Windows command interpreter automatically interprets each string not being a number or an operator as name of an environment variable whose current value has to be converted to an integer for evaluation of the expression.
Yes, whether immediate nor delayed expansion is needed within an arithmetic expression even when the set /a command line is within a command block.
And in batch files // is not a comment, use command REM and take into account that Windows command interpreter first parses the lines with command REM and then executes the command if there is no syntax error, see %~ in REM statement.
For more details:
Run in a command prompt window set /? and really read carefully everything of output help.
If you use any of the logical or modulus operators, you will need to
enclose the expression string in quotes. Any non-numeric strings in the
expression are treated as environment variable names whose values are
converted to numbers before using them. If an environment variable name
is specified but is not defined in the current environment, then a value
of zero is used. This allows you to do arithmetic with environment
variable values without having to type all those % signs to get their
values.
Read the answer Why is no string output with 'echo %var%' after using 'set var = text' on command line?
Read the answer on IF ELSE syntax error within batch file?
Variables within the else-statement are not expanded. Use setlocal enabledelayedexpansion instead and denote your variables with exclamation marks:
:computerMakePick
setLocal enabledelayedexpansion
set /a currentNumber= 15
set /a addOne=%currentNumber%+1
set /a addTwo=%currentNumber%+2
if %addOne% == 7 (
echo Computer chose: %addOne%
set /a currentNumber= %addOne%
)else (
if %addTwo% == 8 (
echo Computer chose: %addTwo%
set /a currentNumber= %addTwo%
)else (
set /a bottomlimit= 1
set /a upperlimit= 2
set /a limit=!upperlimit!-!bottomlimit!+1
set /a randomChoice= !bottomlimit! + !RANDOM! %% !limit!
set /a currentNumber= !currentNumber!+!randomChoice!
echo Computer chose: !currentNumber!
)
)
endLocal & set /a currentNumber= %currentNumber%
goto :eof

Batch file says ( was unexpected at this time during if

So I am making a batch file that will generate a random number, keep it in a variable, and then you try to guess it. If you guess lower than the number, it will make your try counter go up by one, and tell you to guess higher, and vice versa. However, when I enter a number, it says ( was unexpected at this time. Can anyone help me?
Here is the code:
#echo off
cls
:1
setlocal EnableDelayedExpansion
set /a x = 0
set /a x = %RANDOM:~-3%
endlocal
goto 2
:2
set /p v = Enter your guess:
if %v% lss %x% (
echo Greater than that!
set /a g = %g%+1
title %g% Guesses so far!
goto 2
) else if %v% gtr %x% (
echo Less than that!
set /a g = %g%+1
title %g% Guesses so far!
goto 2
) else if %v% equ %x% (
echo Correct! It was %x%! It also took you %g% guesses to find it!
set /a g = 0
title %g% Guesses so far!
goto 1
)
echo That's not a number!
goto 2
Batch is sensitive to spaces in a SET statement. SET FLAG = N sets a variable named "FLAGSpace" to a value of "SpaceN"
consequently, v is not set up and the if is interpreted as if lss 4 (
You will also have problems with setting a variable like g within a ode block (parenthesised sequence of lines). %g% will be evaluated at parse-time - it is not interpreted as the run-time value (ie. as code controlling the block is executed)
Pleas see many SO articles on delayed expansion my using the search facility on the top bar of the page.
Your problem is:
set /a x = 0
:: make it be:
set /a x=0
No Space.

Calling an IF statement | Batch

Error Code:
If was unexpected at this time
The code sets the stats for each player then it calls the function to determine the amount of damage based on the stats and other variables
What I want to do is call a function with two IF statements within it
Example:
#echo off
set /a level=5
set /a opponentLevel=5
set /a movePower=50
set moveType=physical
goto player
:damageCalculator
if %moveType%==physical (
pause
set /a damage=(((( 2 * %level% / 5 + 2) * %attackStat% * %movePower% / %opponentDefenceStat%) / 50) + 2)
set /a opponentHealth-=%damage%
) else if %moveType%==special (
set /a damage=(((( 2 * %level% / 5 + 2) * %spAttackStat% * %movePower% / %opponentSpDefenceStat%) / 50) + 2)
set /a opponentHealth-=%damage%
)
goto :eof
:player
set type=fire
set/a health=19
set/a attackStat=10
set/a defenceStat=10
set/a spAttackStat=11
set/a spDefenceStat=10
set/a speedStat=12
:opponent
set /a opponentHealth=18
set /a opponentAttackStat=10
set /a opponentDefenceStat=9
set /a opponentSpAttackStat=8
set /a opponentSpDefenceStat=9
set /a opponentSpeedStat=13
:attack
pause
cls
call :damageCalculator
echo It did %damage% Damage!!
pause>nul
Is this just one of those things that batch can't do?
update per edited question
Your script has a few small issues. Firstly, I'll point out that it's often helpful to rem out #echo off when trying to track down the cause of a problem. Doing so in this case shows that the line causing your error is your first set /a line.
The reason your if statements are failing is because the parentheses within your math are being treated as the end of your code block. As soon as the closing parenthesis of ...5 + 2) is encountered, the batch interpreter treats that as the end of your if statement, and therefore gets confused when there's more stuff on the line. You need to quote your set /a statements to prevent this.
set /a "damage=(((( 2 * level / 5 + 2) * attackStat * movePower / opponentDefenceStat) / 50) + 2)"
See how I did set /a "variable=value" there? You could also escape the closing parentheses with a caret -- e.g. ^), but quoting the "var=value" is a little easier to read I think. The quotation marks keep the contents within the context of the command. They're basically saying, "This is a single token. It's a distinct part of the set command, not the code block as a whole." As a bonus, you can also see that the % signs aren't needed to retrieve variable values within a set /a command. Neat, huh?
You've got another problem. Since you're setting the %damage% variable within the same parenthetical code block as you're retrieving it, %damage% is going to be evaluated too early. You could setlocal enabledelayedexpansion and retrieve it as !damage!, and that would certainly work. But there's a simpler fix. Just put it outside the if statements. You're doing set /a opponentHealth-=damage regardless of whether the move type is physical or special, anyway, right?
:damageCalculator
if "%moveType%"=="physical" (
set /a "damage=(((( 2 * level / 5 + 2) * attackStat * movePower / opponentDefenceStat) / 50) + 2)"
) else if "%moveType%"=="special" (
set /a "damage=(((( 2 * level / 5 + 2) * spAttackStat * movePower / opponentSpDefenceStat) / 50) + 2)"
)
set /a opponentHealth-=damage
goto :eof
But still, you should include setlocal just below #echo off to keep from junking up your environment with variables that have no meaning outside the scope of this script.
Here's another tip. You can combine many statements within a single set /a line.
Before:
set /a level=5
set /a opponentLevel=5
set /a movePower=50
set "moveType=physical"
After:
set /a level=5, opponentLevel=5, movePower=50
set "moveType=physical"
original answer
Change your second if to else if or add a carriage return before it (after the preceding parenthesis). Also, move your goto :EOF to the next line after the closing parenthesis.
The explanation for this is that the cmd interpreter treats a parenthetical code block as a single command. So in essense,
if [true condition] (
action
) second command
is being evaluated as
if [true condition] (action) second command
which results in an error because there's no line break or other separator between the first command (the if) and the second. Here's an example of a valid compound command:
#echo off & setlocal
Compound command need:
unconditional AND (& -- right side always executes after the left)
example: endlocal & goto :EOF
logical AND (&& -- right side executes only if the preceding command exited zero)
example: find /i "text" "textfile.txt" >NUL && echo Text was found
pipe (| -- makes the command on the right do something with the output generated by the command on the left)
example: dir /s /b | more
logical OR (|| -- right side executes only if the preceding command exited non-zero)
example: tasklist | find /i "iexplore.exe" >NUL || echo Internet Explorer not running
... or in the case of an if statement, else.
if condition 1 (
action 1
) else if condition 2 (
action 2
) else (
action 3
)
Or if you want to check that two conditions are true:
if %var% leq 10 if %var% geq 5 (
echo Variable is between 5 and 10.
)
Of course, you don't have to use compound statements. There's no reason why a function can't have multiple if statements that aren't compound.
:fn <str>
if "%~1"=="fish" (echo Bloop.)
if "%~1"=="cats" (echo Meow.)
if "%~1"=="dogs" (echo Grrrr.)
goto :EOF
... is perfectly valid.

Resources