Hi, I'm busy writing a small RPG game in batch just to lean BATCH scripting a bit more.
But now I have a annoying problem that a variable stays kinda "local".
I have a function to create random numbers.
:RandomNumber
SET /a ValRange=%2-%1+1
SET /a RND=((%random%/3) %% %ValRange%)+%1
GOTO:EOF
Which should be called as CALL :RandomNumber minValue maxValue
This function works great.
I have declared the RND variable at the beginning of the batch file to make it kinda global.
The problem is.
A piece of code uses this RND function to choose which action should happen next.
IF RND==1 CALL action1
IF RND==2 CALL action2
But those actions theirselves also use the RND function
:ACTION1
// GENERATE RND here
// Do something based on the new RND
GOTO:EOF
The problem is that in function ACTION1 or ACTION2, the RND value keeps the same as it was before.
I tried echoing it and the GenerateNumber does make a new funciton, but when action1 tries to use it, it's the old RND again.
Very weird.
Does anyone know how this can happeN,
Variable doesn't get overwritten
Moderator: DosItHelp
-
- Posts: 126
- Joined: 10 Jun 2011 10:30
Re: Variable doesn't get overwritten
Welcome to the forums!
Without seeing more of your script, it will be hard to tell for sure, but I think you're doing 1 of two things:
1. You're declaring the %RND% variable before doing any SetLocal and expecting that this is now a global variable and all mods to it would then also be global. The problem is that if you then Setlocal, mod the variable and then endlocal, the mod was not global, any changes made to it end with the endlocal.
Or...
2. You're modifying it and then testing for it within the same block of code (IF ELSE or FOR ... DO) You need to use EnableDelayedExpansion for this to work.
Here are some examples:
Without seeing more of your script, it will be hard to tell for sure, but I think you're doing 1 of two things:
1. You're declaring the %RND% variable before doing any SetLocal and expecting that this is now a global variable and all mods to it would then also be global. The problem is that if you then Setlocal, mod the variable and then endlocal, the mod was not global, any changes made to it end with the endlocal.
Or...
2. You're modifying it and then testing for it within the same block of code (IF ELSE or FOR ... DO) You need to use EnableDelayedExpansion for this to work.
Here are some examples:
Code: Select all
@Echo OFF
REM This code will echo Test1
Set Var1=Test1
FOR /F %%a IN ("%Var1%") DO (
SET Var1=Test2
ECHO %Var1%
)
REM This code will echo Test2
Set Var1=Test1
FOR /F %%a IN ("%VAR1%") DO (
SetLocal EnableDelayedExpansion
SET Var1=Test2
Echo !Var1!
)
Endlocal
REM This will Echo Test1
SET Var1=Test1
Setlocal
SET Var1=Test2
Endlocal
Echo %Var1%
pause
exit/b
-
- Posts: 3
- Joined: 29 Jul 2011 08:03
Re: Variable doesn't get overwritten
The weird thing is, it works the first time. And it keeps working in that section. But it doesn't in another section.
I'll post the code, but hold one because it's very very long already . Well not extremely long, but long enough to get confusing.
So the random works in the :Adventure label piece of code.
But it doesn't work in the :Battle label when the user is trying to flee (option 2)
Basicly, when the user goes to :adventure, the code selects a random step to be taken and then calls the :Battle. When you are in battle and you try to flee, the random is off and keeps the value of the random value selected by the :adventure piece to select what should happen.
The weird thing is, when I go back to adventure after I got back to :town, the random does work, so this might have something to do with the amount of calls or something?
I'll post the code, but hold one because it's very very long already . Well not extremely long, but long enough to get confusing.
Code: Select all
:: Created by Gilles Lesire
:: Copy, reproduce and edit all you like, as long as you don't infringe copyrights.
@ECHO OFF
SETLOCAL EnableDelayedExpansion
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
set "DEL=%%a"
)
SET varGameName=HellTown
SET varGameVersion=v0.6
REM Extra calculation variables
SET RND=0
REM Color settings
SET clrTitle=0F
SET clrYou=09
SET clrOther=0D
SET clrLevelUp=06
SET clrAttack=02
SET clrDefend=04
SET clrWin=02
SET clrLose=04
REM Game settings
SET stgIncreaseHP=10
SET stgIncreaseShield=1
SET stgIncreaseDamage=1
SET stgMultiplierXP=2
SET stgPriceInn=25
SET stgWinGold=15
SET stgWinXP=10
REM Default settings
SET dftUsername=unknown
SET dftLevel=1
SET dftXP=0
SET dftMaxXP=100
SET dftHP=20
SET dftMaxHP=20
SET dftCash=50
SET dftDamage=2
SET dftSnacks=0
REM Player settings
SET varLevel=%dftLevel%
SET varXP=%dftXP%
SET varMaxXP=%dftMaxXP%
SET varHP=%dftHP%
SET varMaxHP=%dftMaxHP%
SET varUsername=%dftUsername%
SET varCash=%dftCash%
SET varDamage=%dftDamage%
SET varSnacks=%dftSnacks%
REM Monster settings
SET monsterName=unknown
SET monsterLevel=1
SET monsterHP=10
SET monsterMaxHP=10
SET monsterDamage=1
REM Zone settings
SET exploreZone=unkown
:welcome
cls
CALL :ColorText %clrTitle% "Welcome to %varGameName% %varGameVersion%"
ECHO.
ECHO.
ECHO You enter a small town but it looks almost like it's deserted.
ECHO Everything is closed, all windows nailed down and there is not
ECHO a living soul in sight.
ECHO.
ECHO You see an old man in the distance, you decide to go talk to him.
ECHO.
CALL :ColorText %clrOther% "Hi stranger"
ECHO ^^!
CALL :ColorText %clrOther% "Welcome to our town"
ECHO ^^!
CALL :ColorText %clrOther% "What's your name"
ECHO ?
ECHO.
:whileWelcome
SET /p varUsername=Type your name:
IF %varUsername%==%dftUsername% (GOTO:whileWelcome)
ECHO.
CALL :ColorText %clrYou% "My name is %varUsername%"
ECHO .
ECHO.
CALL :ColorText %clrOther% "Okay, I'll tell the town about your arrival"
ECHO .
ECHO.
CALL :ColorText %clrYou% "Wait"
ECHO ^^!
CALL :ColorText %clrYou% "Where on Earth am I"
ECHO ?
ECHO.
CALL :ColorText %clrOther% "You'll find out soon enough"
ECHO ^^!
ECHO.
ECHO The old man quickly walks off...
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
GOTO:menu
:menu
cls
CALL :ColorText %clrTitle% "%varGameName% main menu"
ECHO.
ECHO.
ECHO You are now playing with the character %varUsername%.
ECHo.
ECHO 1. Begin adventure
ECHO.
ECHO 2. Change character name
ECHO 3. Save character
ECHO 4. Load character
ECHO 5. Reset character
ECHO.
ECHO 8. How to play
ECHO 9. About
ECHO.
ECHO 0. Exit game
ECHO.
:whileTown
SET varAction=100
SET /p varAction=Choose an action:
IF %varAction%==1 (GOTO:town)
IF %varAction%==2 (GOTO:changeName)
IF %varAction%==5 (GOTO:resetCharacter)
IF %varAction%==8 (GOTO:howto)
IF %varAction%==9 (GOTO:about)
IF %varAction%==0 (GOTO:exit)
GOTO:whileTown
:town
cls
CALL :ColorText %clrTitle% "Town square"
ECHO.
ECHO.
ECHO You have %varCash% gold in your pocket and %varHP%/%varMaxHP%HP.
ECHO.
ECHO 1. Go exploring
ECHO 2. Take a rest at the inn
ECHO 3. Drink from square fountain
ECHO 4. Go to shop
ECHO.
ECHO 0. Back to main menu
ECHO.
:whileTown
SET varAction=100
SET /p varAction=Choose an action:
IF %varAction%==1 (GOTO:adventure)
IF %varAction%==2 (GOTO:inn)
IF %varAction%==3 (GOTO:fountain)
IF %varAction%==0 (GOTO:menu)
GOTO:whileTown
:adventure
cls
CALL :ColorText %clrTitle% "Exploration - %exploreZone%"
ECHO.
ECHO.
CALL :RandomNumber 1 2
IF %RND%==1 (
CALL :Fight
)
IF %RND%==2 (
CALL :Ambushed
)
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
GOTO:town
:inn
cls
CALL :ColorText %clrTitle% "Take a rest at the inn"
ECHO.
ECHO.
ECHO You walk into the inn and wait at the desk. A chubby old man greets
ECHO you from behind the counter.
ECHO.
CALL :ColorText %clrOther% "Hi there fella, I'm the inn keeper"
ECHO .
CALL :ColorText %clrOther% "Can I book you for a room"
ECHO ?
CALL :ColorText %clrOther% "It's only %stgPriceInn% gold for one night"
ECHO ^^!
ECHO.
ECHO 1. Yeah sure^^!
ECHO 2. I don't have enough money...
ECHO 3. No thanks, I'm A-okay^^!
ECHO.
:whileInn
SET varAction=100
SET /p varAction=What are you going to do?:
IF %varAction%==1 (GOTO:innYes)
IF %varAction%==2 (GOTO:innCheap)
IF %varAction%==3 (GOTO:innNo)
GOTO:whileInn
:innYes
ECHO.
CALL :ColorText %clrYou% "Yes, I'd like a room please"
ECHO .
ECHO.
IF %varCash% LSS %stgPriceInn% (
ECHO.
ECHO You look in your pocket and you realise you don't have enough money...
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
GOTO:innCheap
)
SET /a varCash-=%stgPriceInn%
SET /a varHP=%varMaxHP%
ECHO The innkeeper provides you with a key to your room.
ECHO You go up and you see simple room with a bed and a dresser, it's not much
ECHO but it will do. You go lie on the bed and fall asleep immediatly.
ECHO.
ECHO After a long night of sleep you feel completely rested.
ECHO You have regained all your HP^^!
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
GOTO:town
:innCheap
ECHO.
CALL :ColorText %clrYou% "Oh no"
ECHO ...
CALL :ColorText %clrYou% "It looks like I don't have enough gold"
ECHO .
ECHO.
CALL :ColorText %clrOther% "Oh that's no problem my friend but you look awfully tired"
ECHO ^^!
CALL :ColorText %clrOther% "If you want to you can sleep on some hay in my barn"
ECHO .
CALL :ColorText %clrOther% "It's not that comfy, but at least you'll get some rest"
ECHO .
CALL :ColorText %clrOther% "It's not safe to sleep outside these days anyway"
ECHO ...
CALL :ColorText %clrOther% "You can sleep there as long as you want"
ECHO ^^!
ECHO.
CALL :ColorText %clrYou% "Great thanks"
ECHO ^^!
ECHO.
ECHO You go inside the barn and you see a bale of hay in the corner.
ECHO There are some cows stalled. It is not much, but it will have to do...
GOTO:innCheapSlept
:innCheapSlept
SET /a increaseHP=%varMaxHP%/10
SET /a varHP=%varHP%+%increaseHP%
IF %varMaxHP% LSS %varHP% (
SET varHP=%varMaxHP%
)
ECHO.
ECHO You wake up the next morning because of the tail of one of the cows
ECHO slapping you in the face.
ECHO It was a terrible night but at least you got some rest.
ECHO You have regained %increaseHP%HP.
ECHO.
ECHO Your HP level is now %varHP%/%varMaxHP%HP^^!
ECHO.
:whileInnCheapSlept
SET varAction=100
SET /p varAction=Do you want to stay another night to get some more rest? (Y/N):
IF /I %varAction%==y (GOTO:innCheapSlept)
IF /I %varAction%==n (GOTO:town)
GOTO:whileInnCheapSlept
:innNo
ECHO.
CALL :ColorText %clrOther% "Oh, okay"
ECHO ...
CALL :ColorText %clrOther% "See you next time"
ECHO ^^!
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
GOTO:town
:fountain
cls
CALL :ColorText %clrTitle% "Drink from square fountain"
ECHO.
ECHO.
ECHO The flowing sound of the fountain in the middle of the square
ECHO draws your attention. You hastly walk towards it.
ECHO After taking a few doubtful sips you start drinking but when you
ECHO getting back up, you notice in the reflection of the water your
ECHO face is full of mud and your hands are still coverd in blood.
ECHO.
ECHO After washing the dirt from your face and your hands are clean again
ECHO you feel refreshed^^!
ECHO.
ECHO It's important to keep yourself hydrated... Especially when you are fighting
ECHO all kind of creatures^^!
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
GOTO:town
:howto
cls
CALL :ColorText %clrTitle% "How to play %varGameName% %varGameVersion%"
ECHO.
ECHO.
ECHO %varGameName% is fairly easy to play. The goal of the game is to slay
ECHO as many monsters as possible and to explore the world of %varGameName%.
ECHO.
ECHO To navigate through the game works the same way as the menu. Every time
ECHO you'll get a few options and you have to pick one.
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
GOTO:menu
:about
cls
CALL :ColorText %clrTitle% "About %varGameName% %varGameVersion%"
ECHO.
ECHO.
ECHO This game has been written with Batch Scripting Code.
ECHO.
ECHO Design and programming by Gilles Lesire.
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
GOTO:menu
:resetCharacter
cls
CALL :ColorText %clrTitle% "Reset character"
ECHO.
ECHO.
ECHO By resetting your character all your experience will be gone^^!
ECHO.
:whileReset
SET varAction=100
SET /p varAction=Are you sure you want to reset your character? (Y/N):
IF /I %varAction%==y (
CALL :ResetSettings
ECHO.
ECHO Your character has been resetted!
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
GOTO:menu
)
IF /I %varAction%==n (GOTO:menu)
GOTO:whileReset
:changeName
cls
CALL :ColorText %clrTitle% "Change character name"
ECHO.
ECHO.
ECHO Luckely it's fairly easy for travellers to change their name^^!
ECHO.
SET /p varUsername=Choose a new name:
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
GOTO:menu
:exit
cls
CALL :ColorText %clrTitle% "Exit game"
ECHO.
ECHO.
ECHO Your game will not be saved, you need to do this before you quit.
ECHO.
:whileExit
SET varAction=100
SET /p varAction=Are you sure you want to exit? (Y/N):
IF /I %varAction%==y (GOTO:EOF)
IF /I %varAction%==n (GOTO:menu)
GOTO:whileExit
REM "Functions"
:Ambushed
ECHO.
ECHO You got ambushed by a level %monsterLevel% %monsterName%!
ECHO.
CALL :Defend
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
CALL :Battle
GOTO:EOF
:Fight
ECHO.
ECHO You see a level %monsterLevel% %monsterName% in the distance.
ECHO The %monsterName% hasn't noticed you yet so you could suprise attack it,
ECHO or you could still safely flee...
ECHO.
ECHO What are you going to do?
ECHO.
ECHO 1. I'm going to rip that %monsterName% in pieces^^!
ECHO 2. Run^^!^^!^^!
ECHO.
:whileFight
SET varAction=100
SET /p varAction=What are you going to do?:
IF %varAction%==1 (
CALL :Battle
GOTO:EOF
)
IF %varAction%==2 (
ECHO.
ECHO You safely got away^^!
GOTO:EOF
)
GOTO:whileFight
:LevelUp
SET /a varLevel+=1
SET /a varMaxHP=%varMaxHP%+%stgIncreaseHP%
SET /a varDamage+=%stgIncreaseDamage%
SET /a varMaxXP*=%stgMultiplierXP%
SET varHP=%varMaxHP%
ECHO.
CALL :ColorText %clrLevelUp% "You have leveled up"
ECHO ^^!
ECHO.
CALL :ColorText %clrLevelUp% "You are now level %varLevel%"
ECHO .
CALL :ColorText %clrLevelUp% "Your HP has been restored to %varHP%HP"
ECHO ^^!
ECHO.
ECHO Press any key to continue...
PAUSE>NUL
GOTO:EOF
:FindSnack
SET /a varSnacks+=1
CALL :RandomNumber 1 2
ECHO.
IF %RND%==1 (
ECHO You found some mushrooms with healing powers^^!
)
IF %RND%==2 (
ECHO You found an apple, this might give you a little boost!
)
ECHO.
GOTO:EOF
:Battle
ECHO.
REM Check if monster is dead
IF %monsterHP% LEQ 0 (
CALL :WinBattle
GOTO:EOF
)
REM Check if player is dead
IF %varHP% LEQ 0 (
CALL :LoseBattle
GOTO:EOF
)
ECHO %varUsername%: %varHP%/%varMaxHP%HP %monsterName%: %monsterHP%/%monsterMaxHP%HP
ECHO.
ECHO 1. Attack
ECHO 2. Flee
IF %varSnacks% GTR 0 (
ECHO 3. Eat a snack (%varSnacks% left)
)
ECHO.
:whileBattle
SET varAction=100
SET /p varAction=What are you going to do?:
IF %varAction%==1 (
ECHO.
CALL :Attack
CALL :Defend
CALL :Battle
GOTO:EOF
)
IF %varAction%==2 (
IF %varLevel% LSS %monsterLevel% (
CALL :RandomNumber 1 5
)
IF %varLevel% EQU %monsterLevel% (
CALL :RandomNumber 1 4
)
IF %varLevel% GTR %monsterLevel% (
CALL :RandomNumber 1 3
)
CALL :RandomNumber 1 5
ECHO IF %RND% LEQ 2
IF %RND% LEQ 2 (
ECHO You safely got away^^!
GOTO:EOF
) ELSE (
ECHO You failed to flee!
ECHO The monster attacked you...
ECHO.
CALL :Defend
CALL :Battle
GOTO:EOF
)
)
IF %varAction%==3 (
IF %varSnacks% GTR 0 (
CALL :EatSnack
CALL :Battle
GOTO:EOF
)
)
GOTO:whileBattle
:Defend
SET inflictedDamage=%monsterDamage%
SET /a varHP-=%inflictedDamage%
CALL :ColorText %clrDefend% "The %monsterName% did %inflictedDamage% to %varUsername%"
ECHO ^^!
GOTO:EOF
:Attack
SET inflictedDamage=%varDamage%
SET /a monsterHP-=%inflictedDamage%
CALL :ColorText %clrAttack% "%varUsername% inflicted %inflictedDamage% to the %monsterName%"
ECHO ^^!
GOTO:EOF
:EatSnack
ECHO You ate a snack and regained XP!
GOTO:EOF
:WinBattle
SET earnedGold=%stgWinGold%
SET earnedXP=%stgWinXP%
SET /a varCash+=%earnedGold%
SET /a varXP+=%earnedXP%
ECHO.
CALL :ColorText %clrWin% "%varUsername% defeated the %monsterName%"
ECHO .
CALL :ColorText %clrWin% "You have won %earnedGold% gold and %earnedXP%XP"
ECHO ^^!
GOTO:EOF
:LoseBattle
ECHO.
CALL :ColorText %clrLose% "The %monsterName% has overpowered %varUsername%"
ECHO ^^!
CALL :ColorText %clrLose% "%varUsername% collapses on the ground"
ECHO ...
GOTO:EOF
:ResetSettings
SET varLevel=%dftLevel%
SET varXP=%dftXP%
SET varMaxXP=%dftMaxXP%
SET varHP=%dftHP%
SET varMaxHP=%dftMaxHP%
SET varCash=%dftCash%
SET varDamage=%dftDamage%
SET varSnacks=%dftSnacks%
GOTO:EOF
:RandomNumber
SET /a ValRange=%2-%1+1
SET /a RND=((%random%/3) %% %ValRange%)+%1
ECHO %RND%
GOTO:EOF
:ColorText
@ECHO OFF
<NUL SET /p ".=%DEL%" > "%~2"
FINDSTR /v /x /a:%1 /R "^$" "%~2" NUL
DEL "%~2" > NUL 2>&1
GOTO:EOF
So the random works in the :Adventure label piece of code.
But it doesn't work in the :Battle label when the user is trying to flee (option 2)
Basicly, when the user goes to :adventure, the code selects a random step to be taken and then calls the :Battle. When you are in battle and you try to flee, the random is off and keeps the value of the random value selected by the :adventure piece to select what should happen.
The weird thing is, when I go back to adventure after I got back to :town, the random does work, so this might have something to do with the amount of calls or something?
Re: Variable doesn't get overwritten
That is because you are referencing %RND% within an IF block
The value of %RND% is fixed when the IF statement is originally parsed. Everything is parsed at once, including the contents of the ().
Acy correctly suggested you need to SETLOCAL EnableDelayedExpansion. He forgot to tell you to use !RND! when you want to reference a value using delayed expansion. (Actually his example demonstrated the technique, but he didn't spell it out in his text)
The value of %RND% is determined at parse time.
The value of !RND! is determined at execution time (hence the term "delayed expansion").
Dave Benham
Code: Select all
IF %varAction%==2 (
... bunch of code
)
Acy correctly suggested you need to SETLOCAL EnableDelayedExpansion. He forgot to tell you to use !RND! when you want to reference a value using delayed expansion. (Actually his example demonstrated the technique, but he didn't spell it out in his text)
The value of %RND% is determined at parse time.
The value of !RND! is determined at execution time (hence the term "delayed expansion").
Dave Benham
Last edited by dbenham on 29 Jul 2011 15:14, edited 1 time in total.
-
- Posts: 3
- Joined: 29 Jul 2011 08:03
Re: Variable doesn't get overwritten
Yes that does work!
Thanks for the information.
Thanks for the information.