Batch File Randomising from 0 to Variable - variables

For a long time I have wanted to program a game and I always thought it would be too difficult, so I started programming in the popular site Scratch (https://www.scratch.mit.edu) and doing websites with html and css.
I started to want to actually make a game with code so I am learning batch files. Unfortunately I only just started and am confused with a section on the game. I am making a game to try and recreate the game Swords and Sandals 2 to improve my knowledge of batch files. The important part of the game is the damage you deal to your opposition. Obviously you need a percentage chance for your attack to work to input luck into the game. I could easily do that but I want it so that if you have a higher level variable you will have a higher percentage chance, but if your opponent has some defence it will reduce the chance.
I did some basic maths to come up with some equations I was happy with, so here is the section of code :
if %move% equ 2 set /a tauntchance=%RANDOM%*(100+(%oppdefence%*5))/32768+1
if %move% equ 2 set /a tauntchance1=(7+(%charisma%*3))
if %move% equ 2 if tauntchance leq %tauntchance1% set /a damage= ((%charisma%*2)-%RANDOM%*1/32768+1)
if %move% equ 2 set /a energy=%energy%-%charisma%
move=The chosen option
tauntchance=A random number from 0-(100+(The opponents defence*5))
tauntchance1=(7+(Your charisma level*3))
3rd Line= If tauntchance is less than or equal to tauntchance1 then set your damage to Your Charisma Level*2 with a 50% chance to remove 1 or 0, which just stays the same.
4th Line= External variables including your energy amount.
When I run this code the window crashes. If you know if this is possible please let me know!
I have done lots of previous research without any results on this specific topic.
EDIT
With your answers it still just closes the window so I thought I would update the code from the problem onwards.
if %move% equ 2 set /a tauntchance=%RANDOM%*(100+(%oppdefence%*5)+1)/32768+1
if %move% equ 2 set /a tauntchance1=(7+(%charisma%*3))
if %move% equ 2 if %tauntchance% leq %tauntchance1% set /a damage=((%charisma%*2)-%RANDOM%*2/32768+1)
if %move% equ 2 set /a energy=%energy%-%charisma%
echo You have %energy%/%maxenergy% energy left.
echo.
echo You dealt %damage% damage.
echo.
pause >nul
Thank you for the responses anyway!
RESOLVED
I found the problem in some variables before in the code and have fixed it, thank you for the help.

set /a tauntchance=%RANDOM%*(100+(%oppdefence%*5))/32768+1
The value of %tauntchance% variable will never be equal to 0. To obtain the desirable result you should use this line
set /a tauntchance=%RANDOM%*(100+(%oppdefence%*5)+1)/32768
There is a problem with the 3rd line also. This part of the code
%random%*1/32768+1
will generate a sequence of 1's only, so the value of %damage% variable will always stay the same. To fix that use %random%*2/32768 instead.
Is that a complete code? Because you either have to initialise your variables first or better yet put them in quotation marks when you use them with if command. The code below runs fine, except that it is meaningless without the proper values of the variables.
#echo off
if "%move%" equ "2" set /a tauntchance=%RANDOM%*(100 + (%oppdefence%*5) + 1)/32768
if "%move%" equ "2" set /a tauntchance1=(7 + (%charisma%*3))
if "%move%" equ "2" if "%tauntchance%" leq "%tauntchance1%" set /a damage=((%charisma%*2) - %RANDOM% %% 2)
if "%move%" equ "2" set /a energy=%energy% - %charisma%
echo You have %energy%/%maxenergy% energy left.
echo.
echo You dealt %damage% damage.
echo.
pause > nul

Related

Calling variables do not work, what to do?

Hey StackOverflow Community,
I am currently programming my own life simulator called "XinsLife". Currently I want to call a variable that I set before. But it just doesn't work. I tried everything on YouTube and SS64 and could not find what the error was. So I thought I'd ask on StackOverflow. I know this problem is basic and probably everyone can do this, but I am very new to Batch.
Any help would be appreciated.
I am currently at country choosing, so when I choose a country it has to do a variable of what I chose, then goto :savesettings, and display the country that I chose. But it does not work.
C o d e :
:countrychoosing
cls
title New Life -- Country choosing
echo.
echo Choose your country:
call :echo-align center "United States"
call :echo-align center "United Kingdom"
call :echo-align center "China"
call :echo-align center "India"
call :echo-align center "More countries to come soon!"
set /p choosecountry=
if "%choosecountry%" equ 1 (
set chosecountry = United States
goto savesettings
)
if "%choosecountry%" equ 2 (
set chosecountry = United Kingdom
goto savesettings
)
if "%choosecountry%" equ 3 (
set chosecountry = China
goto savesettings
)
if "%choosecountry%" equ 4 (
set chosecountry = India
goto savesettings
)
:savesettings
call %chosecountry%
echo You chose the country "%chosecountry%". Do you want to create a save file?
choice /C:YN
if "%errorlevel%" equ 255 goto savesettings
if "%errorlevel%" equ N goto continuetest
if "%errorlevel%" equ Y goto createsavefiletest
if "%errorlevel%" equ 0 goto savesettings
Why you should use "choice", not "set /p" to accept user-input.
When you use set /p "var=Some user prompt" then var is set to the string entered from the keyboard.
But note that if the user's response is simply Enter then var will remain unchanged
All fine in theory, if you can be certain that your users will never enter an unexpected string.
Suppose the user enters 2 to your first prompt
The if statement would be interpreted as if "2" equ 2 (
Since "2" and 2 are different, the if statement will be evaluated as false. You need if "%choosecountry%" equ "2" (
So the code now becomes if "%choosecountry%" equ "2" (
Suppose the user enters United Kingdom to your first prompt, instead of the expected 2.
The if statement would be interpreted as if "United Kingdom" equ "2" ( - well, that could be fixed with some more code.
But suppose the user enters UK -yes. More code...
Suppose the entry was x"y. This would lead to a syntax error - and there are oodles of other examples like %hello which the user could enter but batch would object to.
Well - most, but probably not all of these unexpected input strings could probably be massaged to allow the cmd processor to handle them smoothly, but that's a lot of unnecessary work and code.
The better solution is to use choice which you use (but incorrectly, sorry) later in your code.
If you enter choice /? from the prompt, you get a full description of choice. In summary, you can use the command choice /C:YN where YN can be any string of unique alphamerics - a to z or a digit.
choice waits for a single character and will beep if one of the choices set by the /c: is not used.
If one of the allowed options is used, then it sets the magic variable errorlevel to a value that depends on the position of the character within the allowed string, so pressing N in response to choice /C:YN would set errorlevel to 2; for choice /C:NY to 1; for choice /C:ORANGES to 4.
magic variables are those that are set automatically like DATE, TIME, RANDOM and others. These variables should not be set as part of a program as the value set into the variable then overrides the value that the system sets.
magic variables otherwise work identically to normal user-variables, and ALL VARIABLES are strings. If the string is purely numeric then the set /a command can be used to perform some mathematical operations. (there are some esoteric exceptions to the pure-numeric string requirement - see set /? from the prompt for details)
So, to structure a choice for use from a menu, you might have
choice /C:YN
if "%errorlevel%" equ "255" goto savesettings
if "%errorlevel%" equ "2" goto continuetest
if "%errorlevel%" equ "1" goto createsavefiletest
Note that each side of the if operator ("equ") must be quoted.
OR - you may have
choice /C:YN
if errorlevel 255 goto savesettings
if errorlevel 2 goto continuetest
if errorlevel 1 goto createsavefiletest
Note that these tests must be performed in reverse-numerical order as the meaning of if errorlevel n is "if errorlevel is n or greater than n"
You could even use
choice /C:YN
goto point%errorlevel%
where :point1 is located at :createsavefiletest, :point2 at :continuetest and :point255 at :savesettings.
Note that a label is simply a location in a file, so
some code...
:xyz
:abc
:hyg
some more code...
would mean that goto xyz,goto abc andgoto hyg all do exectly the same thing.
This should enable you to solve your problem.
Batch is sensitive to spaces in an ordinary string SET statement. SET FLAG = N sets a variable named "FLAGSpace" to a value of "SpaceN". Remove Space from both sides of the =.
Use set "var=value" for setting string values - this avoids problems caused by trailing spaces. Don't assign " or a terminal backslash or Space. Build pathnames from the elements - counterintuitively, it is likely to make the process easier. If the syntax set var="value" is used, then the quotes become part of the value assigned.

Batch for loop - Variable issue

I have to do a few things in bash and batch. I'm stuck on the batch for-loop part. The instructions for part of my assignment are as follows:
::Doing a for loop from 1 to 100,
:: - Find the results of calculating each number from 1 to 100 mod 5.
:: - Append each number to the results.txt file
:: - After the for loop ends calculate and display the average of the results
:: - Append the average of the numbers to the results.txt file
::Code
:forLoop
echo.
::set /A temp-0
for /L %%x in (1, 1, 100) do (
set /A result="%%x %% 5"
call echo %%result%% >> results.txt
::%%temp+=%%result%%
)
::average=temp/100
::append average
GOTO exit
Other users helped me with result variable and the mod 5. However, I'm currently having trouble with temp. I think once I get temp to work I should be able to get the average part working without too much issue. My professor also mentioned that there are 3 different kinds of for-loops in batch, so I'm not even sure if I'm using the right one. Can anyone please help me figure this out.
echo.
set /A temp=0
for /L %%x in (1, 1, 100) do (
set /A result="%%x %% 5"
call echo %%result%%
CALL SET /a temp+=%%result%%
)
SET /a average=temp/100
ECHO %average% %temp%
This is quite straight-forward. Don't use :: comment-style within a block (parenthesised series of statements) as it's actually a broken-label which breaks the loop.
Beyond that, you need to call the set because you are not using delayedexpansion - hence the requirement to double the customary number of %s - same as call echo.
I've taken out the redirection so that the result simply appears on screen.

Syntax error when asking if a variable equals another variable in batch

Here is my code:
if %magic%==%weakness% set /a damage=%random%*3/32767+12
if %magic==%resistance% set /a damage=%random%*3/32767+5
echo Your attack does %damage% damage.
I keep getting a syntax error when I run this. What am I doing wrong?
You should always use quotes around your variables or use delayed expansion, to avoid problems when one or both variables are empty.
Btw. in the second line you missed one percent
if "%magic%"=="%weakness%" set /a damage=%random%*3/32767+12
if "%magic%"=="%resistance%" set /a damage=%random%*3/32767+5
echo Your attack does %damage% damage.
Or with delayed expansion
setlocal EnableDelayedExpansion
if !magic!==!weakness! set /a damage=%random%*3/32767+12
if !magic!==!resistance! set /a damage=%random%*3/32767+5
echo Your attack does !damage! damage.

Batch decimal variable calculator

I am currently working on a game in batch script and in one place, I need to make a multiplication of decimals. The problem is, the end result is always 0.
This is the code:
#echo off
echo Calcultating New Values
echo ...
ping localhost -n 2 >nul
set /p coal_price_buy_brt=<coal_price_buy_brt.wss
set /p coal_ind_buy=<coal_ind_buy.wss
cls
echo First Values :
echo ################################
echo ## Coal Price Brutto ## %coal_price_buy_brt% ##
echo ################################
echo ## Coal Index Buy ## %coal_ind_buy% ##
echo ################################
ping localhost -n 3 >nul
echo %coal_price_buy_brt%
echo %coal_ind_buy%
set ENABLEDELAYEDEXPANSION=coal_price_buy_net
set /p coal_price_buy_net=<calc %coal_price_buy_brt%*%coal_ind_buy%
echo Complete Table :
echo ################################
echo ## Coal Price Brutto ## %coal_price_buy_brt% ##
echo ################################
echo ## Coal Index Buy ## %coal_ind_buy% ##
echo ################################
echo ## Coal Price Netto ## %coal_price_buy_net% ##
echo ################################
The file data are:
coal_price_buy_brt = 150
coal_ind_buy = 0.84
EDIT :
4 years after this post, i'm now in IT Studies and realize that there is a difference between integers and floats in coding...
Thanks for having helped me back then !
The arithmetic operations of SET /A command can only manage integer numbers. Imagine you have a calculator that does NOT have the key for decimal point. How could you achieve this operation: 150*0.84? Well, if you know that the second value is always less than one with two decimals, you may execute 150*84 instead and insert a decimal point before the second digit (from right to left) of the result:
#echo off
set coal_price_buy_brt=150
set coal_ind_buy=0.84
rem Convert coal_ind_buy to integer
set coal_ind_buy=%coal_ind_buy:0.=%
rem Execute the multiplication
set /A result=coal_price_buy_brt*coal_ind_buy
echo Result as integer: %result%
echo Result as fixed point with two decimals: %result:~0,-2%.%result:~-2%
If the values may have integer part, then you may achieve the appropriate conversion to integer values, execute the multiplication, and insert the decimal point in the right place; however, you always must select a fixed number of decimal places ("fixed point arithmetic"), unless you want to convert the values to floating point (with an exponent of ten) and achieve all the apropriate conversions!
For further details about fixed point arithmetic operations in Batch, see: http://www.dostips.com/forum/viewtopic.php?f=3&t=2704&p=12523#p12523
I know this is an older question, but I have had a similar question come up with some scripting of my own. Perhaps my answer can still help someone out there with the same/similar question. My question to myself was, "How can use floating point decimal numbers in my batch script?" After much pondering and researching other personal questions on StackOverflow, I came up with the following example script. It pretty much converts a floating point number into a fraction in the form of two variables that can be used in the rest of your script. It can be used in tandem with this answer https://stackoverflow.com/a/20531384/2464491 to a similar question.
#echo off
setlocal EnableExtensions
setlocal EnableDelayedExpansion
REM This is how I do a block comment.
goto SOF
========Begin Comment========
Title: deciTest.bat
This batch script checks to see if the number inputed is an interger or a floating point number.
If it is a floating point number, it determines to how many decimal places up to 4096 places.
It then informes the user of how to use the floating point number in arithmatic equations.
Of course, if you include within your script, you can simply call upon the !intOut! and
!multiplier! variables elswhere in your script.
=========End Comment=========
:SOF
REM Check to see if the user supplied a number.
if "%1"=="" (
REM If not, tell them how to use the file.
echo Usage: deciTest.bat [number]
echo.
echo [number] The number to check. Enter either an integer
echo or a floating point number.
echo.
goto eof
)
REM Assign the user input to variable decNum
set decNum=%1
REM Plop the number into a file
echo !decNum!>decNum.tmp
REM Check to see if there is a decimal point
findstr /c:"." decNum.tmp >null
REM If it is found, the number is a floating point number
REM So lets make it so we can use it.
if %errorlevel%==0 (
REM Separate our Characteristic (before the .) and Mantissa (after the .)
for /f "tokens=1-18* delims=." %%a in (decNum.tmp) do (
REM Count the length of our Mantissa (How may decimal places?)
set "s=%%b"
set "s=!s!#"
set "decPlaces=0"
for %%P in (4096 2048 1024 512 128 64 32 16 8 4 2 1) do (
if "!s:~%%P,1!" NEQ "" (
set /a "decPlaces+=%%P"
set "s=!S:~%%P!"
)
)
REM Inform the user of our findings.
echo %%a.%%b is a floating point number with !decPlaces! decimal places
call :Integrate
echo.
REM Create the variable !intOUt! for use elswhere in the code
set /a intOut=%%a*!multiple!+%%b
REM Tell the user how to use this particular floating number
echo Your batch file can use !intOut! in your arithmatic equations.
echo Simply divide your result by !multiple!.
)
) else (
REM If it aint floatin', it's an integer
echo %1 is an integer
)
goto eof
:Integrate REM Create the !multiple! variable to be used elsewhere in the script
set count=!decPlaces!
set multiple=1
:startloop
set /a multiple*=10
set /a count-=1
if not !count!==0 goto startloop
:eof
The code demonstrates how to handle floating point numbers. Essentially, it turns floating point numbers into fractions (!intOut!/!multipler!). If you adjust your arithmetic a bit. Multiply by !intOut!, then send !intOut!/!multiplier! with however many decimal places you want to the example script found here: https://stackoverflow.com/a/20531384/2464491
I hope this helps anyone who has run into the same problem when trying to work with floating point numbers in a batch script. Sure it's not designed to work with such numbers, but you can always script your way around the problem.
You can call this batch file to do a mathematical evaluation.
Name it vbs.bat and then use call vbs 150*0.84 and the result will be in a variable called %val%
#echo off
>"%temp%\VBS.vbs" echo Set fso = CreateObject("Scripting.FileSystemObject") : Wscript.echo (%*)
for /f "delims=" %%a in ('cscript /nologo "%temp%\VBS.vbs"') do set "val=%%a"
del "%temp%\VBS.vbs"
Batch mathematics is INTEGER, hence 0.84 will either be interpreted as 0 or as an invalid number.
You may use an hybrid Batch-JScript file as described in this answer: looking for a way to calculate logarithm in a DOS batch file
This method allows you to evaluate any floating point operation, including logarithms, square roots, etc.
#if (#CodeSection == #Batch) #then
#echo off
rem Evaluate floating point expressions via JScript, for example:
call :Expr result=%coal_price_buy_brt%*%coal_ind_buy%
echo %result%
goto :EOF
:Expr result=expression
for /F "delims=" %%a in ('Cscript //nologo //E:JScript "%~F0" "%2"') do set "%1=%%a"
exit /B
#end
WScript.Echo(eval(WScript.Arguments.Unnamed.Item(0)));
For further details on available JScript mathemathic operations, see: http://msdn.microsoft.com/en-us/library/ie/b272f386(v=vs.94).aspx

windows command line giving error on calculation

I found this nice little tidbit of code here: https://stackoverflow.com/a/5262637/2128987
#echo off
set starttime=%TIME%
set startcsec=%STARTTIME:~9,2%
set startsecs=%STARTTIME:~6,2%
set startmins=%STARTTIME:~3,2%
set starthour=%STARTTIME:~0,2%
set /a starttime=(%starthour%*60*60*100)+(%startmins%*60*100)+(%startsecs%*100)+(%startcsec%)
:TimeThis
robocopy /e /NFL /NDL /NJH /NJS /nc /ns /np folder%rndfolder% %drvltr%:\f%dirnew%\
set endtime=%time%
set endcsec=%endTIME:~9,2%
set endsecs=%endTIME:~6,2%
set endmins=%endTIME:~3,2%
set endhour=%endTIME:~0,2%
if %endhour% LSS %starthour% set /a endhour+=24
set /a endtime=(%endhour%*60*60*100)+(%endmins%*60*100)+(%endsecs%*100)+(%endcsec%)
set /a timetaken= ( %endtime% - %starttime% )
set /a timetakens= %timetaken% / 100
set timetaken=%timetakens%.%timetaken:~-2%
echo.
echo Took: %timetaken% sec.
As a standalone program it works great. I am using it with a robocopy command basically to determine how long it takes to write a file.
I add one extra variable in it because I want to keep the raw seconds for calculation purposes. So I add the extra line set timeraw=%timetaken%:
set /a timetaken= ( %endtime% - %starttime% )
***set timeraw=%timetaken%***
set /a timetakens= %timetaken% / 100
set timetaken=%timetakens%.%timetaken:~-2%
My batch file also uses setlocal enabledelayedexpansion
Well sometimes it does not properly calculate the "starttime" or "endtime". It's keeps it as the raw time in 08:30:22.35 type format and results in the error:
Invalid number. Numeric constants are either decimal (17),hexadecima (0x11), or octal (021)
Well obviously because it contains non-numeric characters like the : character.
My batch file goes in a continuous loop forever as I am using it to read, write, delete files and folders for a specific torture test condition.
Any idea why it would intermittently not calculate the starttime or endtime variables?
edit:
I made some changes to my overall script. I no longer need enabledelayedexpansion, cleaned up some if then statements, and simplified code a little. But I still occasionally get it where the starttime or endtime variables remain as the raw time format of HH:MM:SS.CS and causes error in calculation.
Old question, but there are probably blocks of parentheses and when you change a variable within parentheses then you need to use delayed expansion.
Run this and examine the differences.
#echo off
set a=nothing
if z==z (
set a=b
echo %a%
)
pause
setlocal enabledelayedexpansion
set a=nothing
if z==z (
set a=b
echo !a!
)
pause
Gee - a question nearly a year old, with no answer.
I'll assume that the problem has now been solved, so as a matter of record, I'd conclude that the
"sometimes it does not properly calculate" is because the hour/minute/second/hundredths will contain "08" or "09" which are not octal numbers.
The solution is
set /a startcsec=1%STARTTIME:~9,2% - 100
and repeat with each of the other 3 start time-segments; then repeat again with the end parts.
In addition, it could be that the hour is being presented with 0s suppressed. In this case, I'd suggest
set starttime=0%TIME: =%
set starttime=%startTIME:~-11%
set /a startcsec=1%STARTTIME:~9,2% - 100
where the first line prefixes the time with a '0', and replaces Space with [nothing]
the second selects just the last 11 characters of the result
and the last is the familiar form, using the resultant hh:mm:ss.cc format.
(obviously, the remainder of the substring-and-calculate method needs also to be implemented)