Reputation: 91
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?
Upvotes: 1
Views: 375
Reputation: 24466
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"
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:
&
-- right side always executes after the left)
endlocal & goto :EOF
&&
-- right side executes only if the preceding command exited zero)
find /i "text" "textfile.txt" >NUL && echo Text was found
|
-- makes the command on the right do something with the output generated by the command on the left)
dir /s /b | more
||
-- right side executes only if the preceding command exited non-zero)
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.
Upvotes: 3