Save and Load .bat game -- Error with single numbers - batch-file

In this qustion, Save and Load .bat game I used Mat's answer.
But now I have a problem with "saving" numbers using said answer.
If the variable is not double digits (for example 1 or 0) it will "save" the variable as " " and thus will crash the game whenever you do anything that needs that variable. The game sets the variable fine before that.
For example if I pick up the rag, then type Inv, it will say I'm holding the rag. If I then save and load again, then type Inv, it wont say I'm holding anything!
It also won't echo "Nothing" which it should do if %raghave% = 00
(I also have the save file open in Notepad++ and so can see that set RagHave=)
(Also if I use Mat's code with the spaces, then the variable is set as "set RagHave=1" and so adds a space at the end)

The problem is Mat's solution!
For better understanding I repeat his solution
#echo #ECHO OFF > savegame.cmd
#echo SET ITEMS=%ITEMS% >> savegame.cmd
#echo SET HEALTH=%HEALTH% >> savegame.cmd
#echo SET MONEY=%MONEY% >> savegame.cmd
In my opinion, it has multiple disadvantages.
The # prefix isn't necessaray.
The redirection is repeated for each line (I don't like redundancy).
It needs the spaces, as without spaces you got problems with numbers.
Sample with items=1
#echo set ITEMS=1>>savegame.cmd
This results not in writeing set items=1 it writes set items= to 1>>savegame.cmd 1>> is the standard stream.
You can solve all problems with
(
echo #ECHO OFF
echo SET "ITEMS=%ITEMS%"
echo SET "HEALTH=%HEALTH%"
echo SET "MONEY=%MONEY%"
) > savegame.cmd
The quotes are used to ensure that "hidden" spaces after the set are ignored.
Btw. It's a bad idea to use a construct like if %raghave% = 00, (you need two equal signs), as 00 isn't a normal number you can't count or calculate with it, it's better to use 0 instead.
Then also this should work
set /a items=0
set /a items=items+1
set /a items=items-1
if %items%==0 echo There are no items

Related

Batch File - How to copy text from file, and then update it to a new value

Each time I open the batch file, I would like it to read the information currently stored in the text file, and then apply that stored information it pulled to calculating a new integer.
I'm trying to figure out how to get a number copied from a text file, stored as a variable, and then updated to a new integer in that text file, say adding 1 to the value.
I've been sifting through information online, and everything seems to point in a different direction.
Here is a test code I've gotten from digging thus-far:
set file="Test.txt"
set /a _Counter =< %file%
echo:%_Counter%
set /a "_Update=%_Counter%+1"
echo:%_Update% >%file%
timeout /t 10
For some reason when I try to get the information for the counter, it doesn't pull any data from the text file, and I'm left with this line output by the batch file.
F:\Users\Test\Documents\JumbledDirectory> set /a _Counter = Directory\Test.txt 0<F:\Users\Test\Documents\Jumbled
The most common answer I've seen is to use something along the lines of
set /p _Counter=< Test.txt
echo %_Counter%
As seen here: Windows batch command(s) to read first line from text file
But upon doing this I've either ended up with
echo:%_Counter%
being completely blank, or it defaults to 0 each time.
Any help would be appreciated as I've sadly been trying to find how to get this simple function for around 6 hours now.
#ECHO Off
SETLOCAL
set "file=q72474185.txt"
set /p _Counter=< "%file%"
echo:%_Counter%
set /a _Update=_Counter+1
echo:%_Update% >"%file%"
TYPE "%file%"
GOTO :EOF
When you use the point-click-and-giggle method of executing a batch, the batch window will close if a syntax-error is found or the script runs to completion. You can put a pause after statements and home in on the error, but better to open a 'command prompt' and run your batch from there so that the window remains open and any (error) messages will be displayed.
The error message would be about missing operand.
I've changed the filename as I track each question I respond to with its own set of data.
Use set "var=value" for setting string values - this avoids problems caused by trailing spaces. Don't assign a terminal \, Space or " - build pathnames from the elements - counterintuitively, it is likely to make the process easier.
set /a does not expect input from anywhere, it simply performs the calculation and assigns the result. Quotes are not necessary so I've removed them. % are also not required in a set /a but can be required if you are using delayedexpansion.
set /p expects input, so I've used that to read the file. Note that set /a disregards spaces, but set and set /p will include the space before the = in the variablename assigned, and _Counter & _Counter are different variables.
So having the batch in the same directory as the textfile this will work:
REM get input of file as Counter
set /p Counter=<number.txt
REM add a number to Counter and assign it as Counter
set /a "Counter=%Counter%+3
REM empty the file
break>number.txt
REM write Counter in the file
echo %Counter% >> number.txt

How do I extract a single digit from a string in a .txt file on CMD?

I tried Googling this but I didn't quite find a clear solution so I'm asking you.
I'm not sure how to put this but, let's say we have a TEXTFile.txt that contains a line of a string with random letters and numbers (like AJS12U3254FU8AD). Now, what I want to do is ask the user to enter a number with set /p number=, and then echo the digit/character from the string that this number represents. For instance (on the previous string example) if the user inputs number 3, I want the batch script to echo the letter S, if he inputs 4 to echo 1 and so on.
In my little experience, i think this problem comes down to echoing certain digits from a variable, like echo %var:~0,1% but instead of using integer numbers to specify the digits, I want to insert the user's number in that process. Something like echo %var:~0,%number%%.
Is that possible? Or is there any other way I could do this?
Variables (with the exception of command line arguments) in batch is wrapped around with %, so you can't write %var:~0,%number%% because the variable ends at the first % and results in syntax error
You need to use delayed expansion
setlocal EnableDelayedExpansion
for /f "delims=" %%x in (TEXTFile.txt) do set var=%%x
set /p number="Input number: "
echo !var:~%number%,1!
Assuming you had the line of text you want as a variable line, you could do something like
#echo off
set number=3
set line=AJS12U3254FU8AD
for /l %%i in (%number%,1,%number%) do (
call set character=%%line:~%%i,1%%
)
echo %character%
A different method to force delayed expansion (which doesn't conflict with exclamation marks in the variable) is using a pseudo call.
The call forces another parsing of the line.
The first pass resolves the %number% while the doubled %% are reduced to a single one.
The second pass resolves the now single %.
#Echo off
Set "var=AJS12U3254FU8AD"
set /p "number=Enter a number:"
Call echo %%var:~%number%,1%%

8 Variables in one line (Batch)

I have tried multiple things with a code like this.
#echo off
set %1%=A
set %2%=B
set %3%=C
set %4%=D
set %5%=E
set %6%=F
set %7%=G
set %8%=H
echo %1%%2%%3%%4%%5%%6%%7%%8%%9%
But kinda nothing worked, the output was this:
1%2%3%4%5%6%7%8
How do I get it to output ABCDEFGH?
Try with
#echo off
set _1=A
set _2=B
set _3=C
set _4=D
set _5=E
set _6=F
set _7=G
set _8=H
echo %_1%%_2%%_3%%_4%%_5%%_6%%_7%%_8%
Starting from the concept, your problem is that %n with n in the range 0..9 is handled by the batch parser as an command line argument to the batch file, not a variable expansion operation.
You can use number prefixed variable names, but then you will require to enable delayed expansion and change the variable expansion syntax from %varName% in to !varName! to be able to retrieve the value. It is easier not use number prefixed variables names.
The second problem is that the syntax %varName% is only used where the variable value needs to be retrieved. When you set the value, the syntax is set varName=varValue, or still better you can quote the operation as set "varName=varValue" to avoid problems with special characters and inclusion of unneeded ending spaces.
Your question is not clear. The code below do exactly what you requested:
#echo off
set A=A
set B=B
set C=C
set D=D
set E=E
set F=F
set G=G
set H=H
echo %A%%B%%C%%D%%E%%F%%G%%H%
However, is likely that this obvious solution is not what you are looking for...
If you want to know if is there a way to "automatically" define a series of variables and process they all, then the solution is to use an array. You may read the description of the array concept in this Wikipedia article and a detailed explanation of array management in Batch files at this answer. For example:
#echo off
setlocal EnableDelayedExpansion
rem Create "a" array with all elements given:
set n=0
for %%a in (A B C D E F G H) do (
set /A n=n+1
set a[!n!]=%%a
)
rem Show the 8 elements of "a" array
echo %a[1]%%a[2]%%a[3]%%a[4]%%a[5]%%a[6]%%a[7]%%a[8]%
rem Join *all* the elements of "a" array in a single variable
set "all="
for /L %%i in (1,1,%n%) do set "all=!all!!a[%%i]!"
echo %all%
Note that the last example works correctly no matters how many elements have been defined in "a" array.
Although you may also write the array elements in a shorter way, ommiting the braquets: set "a1=A" & set "a2=B", etc, and then use echo %a1%%a2%..., you should remember that the use of braquets is a standard notation used in many other programming languages, so it is convenient to keep it.

How to return the value of a increasing variable in Batch file?

As you can see in my script bellow, the %pin%count%% (maybe obviously for some of you) won't return the wanted value but the string value of the wanted variable, as %pin5% for instance.
I've created a script where the number of variables will depend on how many colors the user chose for his pins. The troubling part of the script is:
Echo - Please type the colors of the pins allowed in the purchase,
or type dot (.) to finish this part of the script.
set count=0
:Pin
set /a count=%count%+1
set /p pin%count%=
if not %pin%count%%=="." goto Pin
I cannot use the IF statement because %pin%count%% returns %pin1% or %pin2% but not the value itself, how to solve this?
It seems like a simple enough syntax problem, but i'm trying everything and haven't managed to solve it yet and asking may be the fastest solution.
to evaluate a composite variable name, you have to use setlocal enabledelayedexpansion so you can specify ! as an extra delimiter,
The other problem you had is that you compared the variable with ".". Batch does not remove quotes like bash does. Don't put the quotes, or put some quotes on the left end too.
Fixed code:
#echo off
Echo - Please type the colors of the pins allowed in the purchase,
echo or type dot (.) to finish this part of the script.
setlocal enabledelayedexpansion
set count=0
:Pin
set /a count+=1
set /p pin%count%=
rem echo the variable for debug purposes
echo pin%count% = !pin%count%!
rem here's the tricky line
if not !pin%count%!==. goto Pin

SET command advanced /A features resource

Have done quite a bit of searching for a guide (of any substance) for the above to no avail. Can anyone refer me to one?
In the present tense however, I am trying to understand the below code example, which returns a two digit representation of the month, that corresponds to the 3 character month name set in v:
SET v=May
SET map=Jan-01;Feb-02;Mar-03;Apr-04;May-05;Jun-06;Jul-07;Aug-08;Sep-09;Oct-10;Nov-11;Dec-12
CALL SET v=%%map:*%v%-=%%
SET v=%v:;=&rem.%
ECHO.%v%
SET v=May Set the variable
SET map=Jan-01;Feb-02;Mar-03;Apr-04;May-05;Jun-06;Jul-07;Aug-08;Sep-09;Oct-10;Nov-11;Dec-12 Set the substitution string
CALL SET v=%%map:*%v%-=%% - Set %v to the map, but replace everything up to %v%- with nothing
(: replace * everything up to and including May- with nothing (no substitution code after =) - v is now 05;Jun-06;Jul-07;Aug-08;Sep-09;Oct-10;Nov-11;Dec-12
SET v=%v:;=&rem.% replace ; with &rem sets up a line that sets v to 05 and the & rem comments out all the other parts of the command. The command executed is SET v=05 & rem.Jun-06 & rem.Jul-07 & rem.Aug-08 & rem.Sep-09 & rem.Oct-10 & rem.Nov-11 & rem.Dec-12
ECHO.%v% gives the answer
This site gives a lot of info, but running the batch file, and putting echo %v% will also help
Excuse me. I don't like this type of code. In my personal opinion, it is much clear to manage these values as an array this way:
rem Prepare the array of two-digits values for each 3-letters month names:
for %%a in ("Jan=01" "Feb=02" "Mar=03" "Apr=04" "May=05" "Jun=06" "Jul=07" "Aug=08" "Sep=09" "Oct=10" "Nov=11" "Dec=12") do (
set month%%~a
)
rem Previous code is equivalent to these 12 lines:
rem set monthJan=01
rem set monthFeb=02
. . . .
rem set monthDec=12
rem This way, the result is immediately accessible:
SET v=May
CALL SET v=%%month%v%%%
rem Or in the clearer way using Delayed Expansion:
SET v=!month%v%!
monthXXX is an array of values for 12 different 3-letters month names.
SET v=May set the value of the index to an element array.
SET v=!month%v%! is first expanded to SET v=!monthMay! (normal expansion), and then to SET v=05 (Delayed Expansion).
I had explained the reasons I have to prefer this notation with every detail in these posts:
Arrays, linked lists and other data structures in cmd.exe (batch) script
DIR output into BAT array?
I apologize if someone thinks this answer is off-topic...
Antonio
For those who wants the other way around, and wanted an error if the entered month number is wrong, put this in a file named script.cmd:
#echo off
set mNum=%1
set mMap=01-Jan;02-Feb;03-Mar;04-Apr;05-May;06-Jun;07-Jul;08-Aug;09-Sep;10-Oct;11-Nov;12-Dec
call set mName=%%mMap:*%mNum%-=%%
set mName=%mName:;=&rem.%
if "%mName%" == "01-Jan" (
echo Wrong month number "%mNum%"!
goto :EOF
)
echo Month %mNum% is "%mName%".
And start the script with a parameter:
> script 02
Month 02 is "Feb".
> script 13
Wrong month number "13"!
> script foo
Wrong month number "foo"!
However, it does not cover an empty value:
> script
Month is "Jan".

Resources