How-to; Echo entire "goto" section - variables

I am working on a text based adventure game for a few friends and I to work through in batch. I'd like to make the option to have an entire section of variables echoed when wanted. Below is the entry code. The first section, Variables, is not an accessed section, but creates variables prior to the game starting. The second section, stats, provides these variables echoed.
#ECHO OFF
::Variables
set Name=Und
set Gender=Und
set Age=Und
set Gold=0
set Hunger=Satisfied
set Illness=None
set Wounds=None
set CHP=10
set MHP=10
set CMP=0
set MMP=0
goto Start
::Stats
:Stats
cls
echo Name: %Name%
echo Gender: %Gender%
echo Age: %Age%
echo Gold: 0
echo.
echo Health
echo Hunger: %Hunger%
echo Illness: %Illness%
echo Wounds: %Wounds%
echo.
echo Stats
echo HP: %CHP%/%MHP%
echo MP: %CMP%/%MMP%
My current solution to this issue is using
set /p "situation"= :
if "%situation%"=="1" goto nextpart
if "%situation%"=="2" goto nextpart
if "%situation%"=="3" goto nextpart
if "%situation%"=="Stats" goto Stats.
The issue with this method, however, is that once in stats, I have no way to jump to the previous section. It would require me making an exit gateway to every possible section I've created. So the question:
Can I have a series of variables echoed without leaving the current section?

You can use Call:stats in place of goto:stats.
Like this it will comme back in the current section
Edit :
#echo off
set $var=1000
call:aff
echo done
exit/b
:aff
echo %$var%

You can get Lua here
There's a somewhat out of date version of the Lua book here.
Here's an example of how you could write this in Lua:
-- create a bunch of variables
Name = nil
Gender = nil
Age = nil
Gold = 0
Hunger = 'Satisfied'
Illness = 'None'
Wounds = 'None'
CHP = 10
MHP = 10
CMP = 0
MMP = 0
-- create a routine whose job it is to print the variables
function stats()
print(' Name: ' .. Name )
print('Gender: ' .. Gender )
print(' Age: ' .. Age )
print(' Gold: ' .. Gold )
print('Health' )
print(' Hunger: ' .. Hunger )
print('Illness: ' .. Illness )
print(' Wounds: ' .. Wounds )
print('' )
print('Stats' )
print(' HP: ' .. CHP .. '/' .. MHP )
print(' MP: ' .. CMP .. '/' .. MMP )
end
-- call the routine
stats()
This appears more verbose that your BAT code, but once your game logic starts to get complicated, using a real programming language will make it much easier and more rewarding.

The easy way to arrange a save/restore regime in batch is to reserve a prefix for the variables to be saved/restored. For instance, if you were to reserve $ for the variables of interest, then
set $>savefile
is all you'd need to save all of the $ variables to a file and
for /f "delims=" %%a in (savefile) do set %%a
would restore them.

Related

$? tcsh script issue

I am confused with a tcsh shell script issue. (for work, no choice in shell, I'm stuck with it)
The enableThingN items below are shell enviroment variables set by other things before running this csh script, using tcsh shell. These are not set within the same script here at all, only evaluated here.
Error message is:
enableThing1: Undefined variable.
Code is:
if ( ( $?enableThing1 && ($enableThing1 == 1) ) || \
( $?enableThing2 && ($enableThing2 == 1) ) || \
( $?enableThing3 && ($enableThing3 == 1) ) || \
( $?enableThing4 && ($enableThing4 == 1) ) ) then
set someScriptVar = FALSE
else
set someScriptVar = TRUE
endif
So, as I understand things, the first part of the big if condition is to check if enableThing1 is defined at all or not, using the $?enableThing1 magic. If it is defined, then move on and check the value is 1 or something else. If not defined, then skip the ==1 part of the check for the same shell variable, and move on to see if enableThing2 is defined at all or not, and so on.
As it seems like I am checking for existence, and intend to avoid checking value if it is not defined at all, where have I gone wrong?
I have searched here on stackoverflow and on Google at large, but there are few results and don't get me to an answer, such as:
https://stackoverflow.com/questions/16975968/what-does-var-mean-in-csh
An if statement to check the value of the variable requires that the variable exists.
if ( ( $?enableThing1 && ($enableThing1 == 1) ) || \
# ^ this will fail if the variable is not defined.
So the if condition turns into
if ( ( 0 && don'tknowaboutthis ) || \
and it falls flat.
Assuming you don't want an if ladder, and functionality to add to this list of variables to check for, you can try the following solution:
#!/bin/csh -f
set enableThings = ( enableThing1 enableThing2 enableThing3 enableThing4 ... )
# setting to false initially
set someScriptVar = FALSE
foreach enableThing ($enableThings)
# since we can't use $'s in $? we'll have to do something like this.
set testEnableThing = `env | grep $enableThing`
# this part is for checking if it exists or not, and if it's enabled or not
if (($testEnableThing != "") && (`echo $testEnableThing | cut -d= -f2` == 1 )) then
# ^ this is to check if the variable is defined ^ this is to take the part after the =
# d stands for delimiter
# for example, the output of testEnableThing, if it exists, would be enableThing1=1
# then we take that and cut it to get the value of the variable, in our example it's 1
# if it exists and is enabled, set your someScriptVar
set someScriptVar = TRUE
# you can put a break here since it's irrelevant to check
# for other variables after this becomes true
break
endif
end
This works because we are only working with one variable, "testEnableThing", which is always defined due to the way this works. It can be a blank string, but it will be defined so our if statement won't fall flat.
Hope this solves it for you.

Add character before and after every character in a file - make every character a variable

I want to "encrypt" a file. This is just for fun, not intending to store or send any sensetive data using this "encryption".
This code example is meant to ilistrate what I would like to do...
SET A=D
SET B=S
SET C=Q
SET D=G
ECHO %A%%B%%C%%D%
The text ABCD will now be displayed as DSQG insted (if I wrote something meaningfull the "encrypted" result would not mean anything).
My question is:
Can I (if so, how?) add '%' before and after every character in the file?
I searched on how to read a file using batch, found this (jeb's answer):
Batch files: How to read a file?
Is there a soulution where I could read a normal file, encrypt it and store as an encrypted version aswell?
Thanks so much for any answer!
This borrows strlen from jeb,
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET PT_FILE=plain.txt
IF NOT "%~1"=="" SET "PT_FILE=%~1"
CALL :INIT_CIPHER
FOR /F "tokens=*" %%l IN ('findstr.exe /R /N "^" "%PT_FILE%"') DO #(
REM #ECHO(
REM #ECHO( %%l
SET "LINE=%%~l"
SET "LINE=!LINE:*:=!"
REM #ECHO(!LINE!
CALL :strlen LINE_LEN LINE
REM #ECHO(Length(!LINE_LEN!^)
IF !LINE_LEN! EQU 0 (
ECHO(
) ELSE (
SET OUTLINE_E=
FOR /L %%i IN (0,1,!LINE_LEN!) DO (
SET "CHAR=!LINE:~%%i,1!"
IF "!CHAR!"==" " (
SET "OUTLINE_E=!OUTLINE_E! "
) ELSE (
#ECHO !CHAR!|findstr.exe /R "[A-Za-z]" >NUL
IF ERRORLEVEL 1 (
SET "OUTLINE_E=!OUTLINE_E!!CHAR!"
) ELSE (
SET CHAR_E=
CALL :ENC "!CHAR!" "CHAR_E"
REM #ECHO '!CHAR!' =^> E(!CHAR_E!^)
SET "OUTLINE_E=!OUTLINE_E!!CHAR_E!"
)
)
)
ECHO(!OUTLINE_E!
)
)
GOTO :EOF
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:ENC
CALL SET "%~2=!%~1!"
REM ECHO E(!%~2!^)
EXIT /B
:: https://stackoverflow.com/questions/5837418/how-do-you-get-the-string-length-in-a-batch-file
:strlen <resultVar> <stringVar>
(
setlocal EnableDelayedExpansion
set "s=!%~2!#"
set "len=0"
for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!s:~%%P,1!" NEQ "" (
set /a "len+=%%P"
set "s=!s:~%%P!"
)
)
)
(
endlocal
set "%~1=%len%"
exit /b
)
:: Substitution Cipher
:: ABCDEFGHIJKLMNOPQRSTUVWXYZ
:: ZYXWVUTSRQPONMLKJIHGFEDCBA
:: perl -e "#a=('a'..'z');for ($i=0; $i<#a; $i++) { print('SET '.uc($a[$i]).'='.uc($a[$#a-$i]).qq(\n)); }"
:INIT_CIPHER
SET A=Z
SET B=Y
SET C=X
SET D=W
SET E=V
SET F=U
SET G=T
SET H=S
SET I=R
SET J=Q
SET K=P
SET L=O
SET M=N
SET N=M
SET O=L
SET P=K
SET Q=J
SET R=I
SET S=H
SET T=G
SET U=F
SET V=E
SET W=D
SET X=C
SET Y=B
SET Z=A
EXIT /B
Notes:
It is very slow.
It loses the case of the source plaintext.
It doesn't insert % around every character (which wouldn't work for special characters anyway), but does what it sounds like you want.
Results:
>>> type plain.txt
This is a simple file to be encrypted.
This is a second line. A blank line follows.
This is the fourth line.
This line has a colon (:) in the middle of it.
This line has quotes: "I said, 'Pass the bread, please,' as politely as possible."
>>> enc plain.txt
GSRH RH Z HRNKOV UROV GL YV VMXIBKGVW.
GSRH RH Z HVXLMW ORMV. Z YOZMP ORMV ULOOLDH.
GSRH RH GSV ULFIGS ORMV.
GSRH ORMV SZH Z XLOLM (:) RM GSV NRWWOV LU RG.
GSRH ORMV SZH JFLGVH: "R HZRW, 'KZHH GSV YIVZW, KOVZHV,' ZH KLORGVOB ZH KLHHRYOV."
>>> enc > cipher.txt
enc > cipher.txt
>>> enc cipher.txt
THIS IS A SIMPLE FILE TO BE ENCRYPTED.
THIS IS A SECOND LINE. A BLANK LINE FOLLOWS.
THIS IS THE FOURTH LINE.
THIS LINE HAS A COLON (:) IN THE MIDDLE OF IT.
THIS LINE HAS QUOTES: "I SAID, 'PASS THE BREAD, PLEASE,' AS POLITELY AS POSSIBLE."

Batch Adding 1 to a number untill Modulo divide 4

I'm gonna try to explain how my case is:
Lets say I have the number 30 and I want to make a batch script that adds 1 to that number untill its modulo divide 4
set /a number = 30 %% 4
how can I make it know to add 2 to 30 to make it mod 4 ?
Thx in advance
Is this what you need?
#echo off
set num=30
:loop
set /a num=num+1
set /a number=num %% 4
if %number% NEQ 0 goto :loop
echo %num%

Generate passwords from list in pairs of two

I've recently found an old TrueCrypt volume file of mine, but after an hour of trying out different passwords I haven't found the right one. I know for a fact that I used a combination of old passwords, but it would take a very long time to try all combinations by hand. I've tried different programs (such as Crunch) to construct a wordlist, but all they do is to generate combinations of every single entry in the .txt-file.
So my question is: does anyone know of a program that could combine all the entries in the file, but only in pairs of two?
For example:
String 1 = hello
String 2 = bye
output =
hellobye
byehello
Under windows, the following command will combine all combinations of two passwords into a new file, using a plain text file as input with line-seperated passwords.
for /F "tokens=*" %i in (passwords.txt) do #(
for /F "tokens=*" %j in (passwords.txt) do
#echo %i%j
)>> combinations.txt
Sample wordlist: cat list.txt
a
b
c
d
Script: cat list.py:
words = []
file = open('list.txt', 'r')
for word in file.readlines():
words.append(word.replace('\n', ''))
#i - 1 is to prevent extending past the end of the list on last try
for i in range(len(words) - 1):
#i + 1 is to prevent "wordword"
for j in range(i + 1, len(words)):
print words[i] + words[j]
print words[j] + words[i]
Output: python list.py
ab
ba
ac
ca
ad
da
bc
cb
bd
db
cd
dc

Add minutes to time in batch (using arithmetic)

I'm running into a dilemma. I want to send a preemptive email to users telling them that an upcoming task is about to happen. In order to do that I'm defining some variables, sending an email via blat, sleeping the batch for 5 minutes, then executing the rest of the script.
When executing %time% at 4:00PM, I get 16:00:00.00. If I add 5 minutes to it, only for display purposes in the email with the following code:
#echo on
SET /a timeminute = 00 + 5 << --- test code
::SET /a timeminute = %time:~3,2% + 5 << --- actual code in GoLive
IF %timeminute% LEQ 9 (
GOTO :resetTime
) ELSE (
GOTO :end
)
:resetTime
SET timeminute = "0%timeminute%"
:end
echo %timeminute%
pause
I get 5, not 05 like expected. Using arithmetic on time drops leading zeros, so I try to add it back in later but the later SET is within the IF statement and cannot be seen? How can I see that? Is there a such thing as an environment variable in batch?
Keep in mind this issue only happens within the first 9 minute of the hour, after that time, there are no more leading zeros.
Bonus: What happens when the minutes in a hour is 55-59? In my example, it will be 60-64, so I need a way of rounding up an hour and take care of the remaining minutes. Right now, I see that as a bug, but I do not foresee this script running at those odd times. But if it is an easy fix please let me know as I have not even tried to tackle that problem.
Thank you kindly
A more compact form to do the same thing is this:
#echo on
for /F "tokens=1-3 delims=:." %%a in ("%time%") do (
set timeHour=%%a
set timeMinute=%%b
set timeSeconds=%%c
)
rem Convert HH:MM to minutes + 5
set /A newTime=timeHour*60 + timeMinute + 5
rem Convert new time back to HH:MM
set /A timeHour=newTime/60, timeMinute=newTime%%60
rem Adjust new hour and minute
if %timeHour% gtr 23 set timeHour=0
if %timeHour% lss 10 set timeHour=0%timeHour%
if %timeMinute% lss 10 set timeMinute=0%timeMinute%
echo %timeHour%:%timeMinute%:%timeSeconds%
pause
Answered my own question with the following:
#echo on
setlocal enabledelayedexpansion
set timehour=%time:~0,2%
set timeminute=%time:~3,2%
set timeseconds=%time:~6,2%
set addTime=5
IF %timeminute:~0,1% lss 1 set timeminute=!timeminute:~1,1!
IF %timeminute:~0,1% lss 1 set timeminute=!timeminute:~1,1!
set /a timeminute=%timeminute% + %addTime%
IF %timeminute% lss 10 set timeminute=0!timeminute!
IF %timeminute% equ 60 (
set timeminute=00
set /a timehour=%timehour% + 1
)
IF %timeminute% equ 61 (
set timeminute=01
set /a timehour=%timehour% + 1
)
IF %timeminute% equ 62 (
set timeminute=02
set /a timehour=%timehour% + 1
)
IF %timeminute% equ 63 (
set timeminute=03
set /a timehour=%timehour% + 1
)
IF %timeminute% equ 64 (
set timeminute=04
set /a timehour=%timehour% + 1
)
IF %timehour% equ 25 (
set timehour=00
)
IF %timehour% lss 10 set timehour=0!timehour!
echo %timehour%:%timeminute%:%timeseconds%
pause