In my code*, I have a simple random number generator and a few ifs to check what number the generator produces. However, even when run in another instance of CMD, in another Batch file, and another instance of this Batch file, it still produces the same number: 4. Every time. I am not using this code in a loop, although it can be looped back to its section. I do, however, have another line of code to generate another number within a different set of parameters that works just fine.
*My code:
:genClass
set /a class=(5 * !random!) / 32768 + 1
if !class!==1 (
set class=Knight
goto genKnightArmor
)
if !class!==2 (
set class=Warrior
goto genWarriorArmor
)
if !class!==3 (
set class=Archer
goto genArcherArmor
)
if !class!==4 (
set class=Thief
goto genThiefArmor
)
if !class!==5 (
set class=Mage
goto genMageArmor
)
:genKnightArmor
set /a armor=(2 * !random!) / 32768 + 1
if !armor!==1 set armor=Light Armor
if !armor!==2 set armor=Heavy Armor
echo !name!
echo !gender!
echo !class!
echo !armor!
pause
exit
:genWarriorArmor
set /a armor=(2 * !random!) / 32768 + 1
if !armor!==1 set armor=Light Armor
if !armor!==2 set armor=Heavy Armor
echo !name!
echo !gender!
echo !class!
echo !armor!
pause
exit
:genArcherArmor
set /a armor=(2 * !random!) / 32768 + 1
if !armor!==1 set armor=Light Armor
if !armor!==2 set armor=Heavy Armor
echo !name!
echo !gender!
echo !class!
echo !armor!
pause
exit
:genThiefArmor
set /a armor=(2 * !random!) / 32768 + 1
if !armor!==1 set armor=Light Armor
if !armor!==2 set armor=Heavy Armor
echo !name!
echo !gender!
echo !class!
echo !armor!
pause
exit
:genMageArmor
set /a armor=(3 * !random!) / 32768 + 1
if !armor!==1 set armor=Light Armor
if !armor!==2 set armor=Heavy Armor
if !armor!==3 set armor=Robes and Hood
echo !name!
echo !gender!
echo !class!
echo !armor!
pause
exit
EDIT: With Monacraft's solution, it now generates a number of 2 and also generates the armor type without error. However, the code to generate the class is still messed up and, as stated before, continues to generate the number 2.
EDIT: I have edited the code once again to change the arithmetic and string variable names. This did not clear anything up, although the class generator is now continuously generating the number 3. I've noticed that, when edited, the generator produces a new number, although, after the first generation, it yields the same number.
EDIT: Fixed mistakes in my code. Such as matching the variables and changing the number 4 in the random generator to 5.
Ok, the main problem with your random number generator is the use of ! instead of %. Unless your using a for loop, you won't need these.
Instead of this:
set /a num=(4 * !random!) / 32768 + 1
Simply use this:
set /a num=(4 * %random%) / 32768 + 1
I tested this in cmd, and it worked fine.
To use ! you need to EnableDelayedExpansion and then use this is a for loop.
Hope this helped with your problem,
Mona.
set /a num=(4 * %random%) / 32768 + 1
if !class!==1 (
Maybe i'm wrong, but, set num and if class does not seem correct
The problem is your expression
set /a num=(4 * !random!) / 32768 + 1
Batch mathematics is integer-only, so this will fail.
Try
set /a num=(%random% %% 4) + 1
Better yet, try in your main code
call :roll armor 3
and add at the end of the code
REM Roll 1..%2
:ROLL
set /a %1=(%random% %% %2) + 1
GOTO :EOF
Note carefully where the colons are - they are critical.
call :roll somevar n
will assign a random number 1..n to the variable somevar
Here's another way to do the selection:
#echo off
:genClass
set name=Slartibartfast
set gender=Alien
set /a num1=%random% %% 5 + 1
set /a num2=%random% %% 2 + 1
if %num1%==1 (
set class=Knight
if %num2%==1 set armor=Light Armor
if %num2%==2 set armor=Heavy Armor
)
set /a num2=%random% %% 2 + 1
if %num1%==2 (
set class=Warrior
if %num2%==1 set armor=Light Armor
if %num2%==2 set armor=Heavy Armor
)
set /a num2=%random% %% 2 + 1
if %num1%==3 (
set class=Archer
if %num2%==1 set armor=Light Armor
if %num2%==2 set armor=Heavy Armor
)
set /a num2=%random% %% 2 + 1
if %num1%==4 (
set class=Thief
if %num2%==1 set armor=Light Armor
if %num2%==2 set armor=Heavy Armor
)
set /a num2=%random% %% 3 + 1
if %num1%==5 (
set class=Mage
if %num2%==1 set armor=Light Armor
if %num2%==2 set armor=Heavy Armor
if %num2%==3 set armor=Robes and Hood
)
echo %name%
echo %gender%
echo %class%
echo %armor%
echo.
pause
goto :genclass
Related
So I've been trying to make the following code:
set /a num1=10
set /a num2=%random% %%60 +%num1%
echo %num2%
(This is simplified)
For this code I need the +%num1% to be a variable because I need to be able to change the lowest number.
For some reason, instead of giving me a random number it gives a totally unrelated number, that isn't random either, but the same every time. My first thought was it was perhaps adding the second variable instead of making a randomizer. That is not the case though, and I'm not sure how to fix this issue.
I have also tried the following code:
set /a num1=10
set /a num2=(%random%*60/32768)+%num1%
echo %num2%
The issue with this code is it never seems to work as randomizer for me even without the variable.
Any help is appreciated.
Here's some examples to assist you:
Set "num1=10"
Set /A "num2 = (%RANDOM% %% 60) + num1"
Echo(%num2%
Set "num1=10"
Set /A "num2 = (%RANDOM% * 60 / 32768) + num1"
Echo(%num2%
Please note, that we have only been provided with a very small portion of your batch file, so if this code is part of a parenthesized block, you may need to enable delayed expansion and use !RANDOM! and possibly !num2! instead of %RANDOM% and %num2% respectively.
In the first form you are have to account for modulus bias, as described further in this question Why do people say there is modulo bias when using a random number generator?
(Note: the accepted answer there has a flaw which I pointed out and provide a solution to in my answer to that question.)
In both the first and the second form they present an incorrect range of values the way it is written. More info can be found here How to use random in BATCH script?
Long story Short:
In both forms, if you want your range to start at 10 and go to 60 you will need to adjust it to be using a modulus of 50, in the first form you must account for modulus bias in your calculations causing some numbers to appear more often.
The first form can be fixed using this method:
SET "Min=10"
SET "Max=60"
SET /A "Discard= 32768 - ( ( ( 32768 %% (Min-Max) ) + 1 ) %% (Min-Max) )"
:Rand
SET /A "num2=%random%"
IF %num2% GTR %Discard% GOTO :Rand
SET /A "num2= num2 %% (Min-Max) + Min"
echo=%num2%
The second form can be fixed using this method:
SET "Min=10"
SET "Max=60"
SET /A "num2= %random% * ( Max - Min + 1 ) / 32768 + Min "
echo=%num2%
Example of Full script:
#(SETLOCAL
ECHO OFF
)
CALL :Main
( ENDLOCAL
EXIT /B
pause
)
:Main
SET "Min=10"
SET "Max=60"
SET /A "Discard= 32768 - ( ( ( 32768 %% (Min-Max) ) + 1 ) %% (Min-Max) )"
ECHO=Form1:
CALL :Form1
ECHO=Form2:
CALL :Form2
pause
GOTO :EOF
:Form1
SET "num2=%random%"
IF %num2% GTR %Discard% GOTO :Form1
SET /A "num2= num2 %% ( Min - Max ) + Min"
echo=%num2%
GOTO :EOF
:Form2
SET /A "num2= %random% * ( Max - Min + 1 ) / 32768 + Min "
echo=%num2%
GOTO :EOF
Results:
C:\WINDOWS\system32>C:\Admin\SE\testrandom.cmd
Form1:
10
Form2:
31
Press any key to continue . . .
C:\WINDOWS\system32>
Hello guys I am very bad at notepad, I want to make a random code generator.
That Generates codes like this 3K2EU-ZGS5L-P3DNL-YM9JC
I want it to work with a notepad .bat file so I can let it run on my PC
This can be done using %random% values to assign numbers and letters as demonstrated
below. If you need letters and numbers in specific places within the 20 digits,
adjust the Condition used to call getLetters or Getnumber to call according to current
%dig%==number
#ECHO OFF
SETLOCAL enableDelayedExpansion
:open
Set dig=0
:main
Set /a dig=%dig% + 1
CALL :digit%dig%
Call LetorNum
IF %dig%==20 goto result
GOTO main
:LetorNum
Set /a pick=%random% * 2 / 32768 + 1
IF %pick%==1 call :getLetter
IF %pick%==2 call :getNumber
GOTO :EOF
:getLetter
Set /a Letter=%random% * 26 / 32768 + 1
IF %letter%==1 Set disp!dig!=a
REM repeat for each letter value between a and z
IF %letter%==26 Set disp!dig!=z
GOTO :EOF
:getNumber
Set /a number=%random% * 10 / 32768 + 1
IF %number%==1 Set disp!dig!=0
REM repeat for every number value between zero and 9
IF %number%==9 Set disp!dig!=9
GOTO :EOF
:result
ECHO %disp1%%disp2%%disp3%%disp4%%disp5%-%disp6%%disp7%%disp8%%disp9%%disp10%-
%disp11%%disp12%%disp13%%disp14%%disp15%-%disp16%%disp17%%disp18%%disp19%%disp20%
pause >nul
GOTO open
I am trying to make a simple RPG game using batch, and for "attacks" that take away both enemy health and "SP". Here is my current code.
#echo off
set /a HP=10
set /a SP=10
echo hp = %HP%
echo SP = %SP%
pause nul
set /p DC= 10 max
set /a NHP=%HP% - %DC%
set /a HP=%NHP%
echo %HP%
pause nul
set /a DCE=10
echo you have %HP% hp
Echo You can 1. Hit (-1 hp to enemy) 2. Kick (-1 hp to enemy) 3 special hit (-2 hp to enemy and -5 SP to you)
Note that HP=Health points and SP= Special points or points that you use for special attacks
And also, The beginning code is just to test a system to take away points., So if you have a better system for that. It would be helpful
set /a EHP = 10
set /a BaseDamage = 1
set /a SpecialDamage = 2
set /a SpecialCost = 5
set /p input = .
if %input% == 1 or %input% == hit (
echo you hit the enemy
set /a EHP = %EHP% - %BaseDamage%
)
if %input% == 2 or %input% == kick (
echo you kick the enemy
set /a EHP = %EHP% - %BaseDamage%
)
if %input% == 3 or %input% == special hit (
echo [insert dialoge here]
set /a EHP = %EHP% - %SpecialDamage%
set /a SP = %SP% - %SpecialCost%
)
goto a
by the way you should probably add :a before echo You can 1.Hit 2.Kick 3.special hit
I am attempting to make a minesweeper in batch but i am having strange errors. When I run the file it lays 5 mines. Then it goes through the rest of the squares and checks to see how many mines are adjacent to each square. My problem is that it only senses an out put to the south-east. The south-east code is no different than the code for any other directions. This is very confusing to me. It seems like no one else has had this error. This is what an example output would be:
M 0 1 0 0
0 1 0 M 0
M 0 M 0 0
0 0 1 0 0
0 0 0 M 0
An answer would be greatly appreciated.
#echo off
setlocal enableDelayedExpansion
setlocal ENABLEEXTENSIONS
title Batch Minesweeper
color 80
set setX=1
set setY=1
set testX=1
set testY=1
set plrX=1
set plyY=1
set mines=0
set mineNum=0
set N=
set NE=
set E=
set SE=
set S=
set SW=
set W=
set NW=
set rect1_1=
set rect2_1=
set rect3_1=
set rect4_1=
set rect5_1=
set rect1_2=
set rect2_2=
set rect3_2=
set rect4_2=
set rect5_2=
set rect1_3=
set rect2_3=
set rect3_3=
set rect4_3=
set rect5_3=
set rect1_4=
set rect2_4=
set rect3_4=
set rect4_4=
set rect5_4=
set rect1_5=
set rect2_5=
set rect3_5=
set rect4_5=
set rect5_5=
set mine1_1=0
set mine2_1=0
set mine3_1=0
set mine4_1=0
set mine5_1=0
set mine1_2=0
set mine2_2=0
set mine3_2=0
set mine4_2=0
set mine5_2=0
set mine1_3=0
set mine2_3=0
set mine3_3=0
set mine4_3=0
set mine5_3=0
set mine1_4=0
set mine2_4=0
set mine3_4=0
set mine4_4=0
set mine5_4=0
set mine1_5=0
set mine2_5=0
set mine3_5=0
set mine4_5=0
set mine5_5=0
cls
echo Batch Minesweeper
echo.
echo [1] - Play
echo [2] - Info
echo [3] - Exit
echo.
echo Batch Minesweeper made by Matt Pauly
choice /c 123 /n /m ""
if %errorlevel%==1 goto startGame
if %errorlevel%==1 goto info
if %errorlevel%==1 goto end
:startGame
cls
set /a ranX=%RANDOM% * 5 / 32768 + 1
set /a ranY=%RANDOM% * 5 / 32768 + 1
if not %mines%==5 (
if !mine%ranX%_%ranY%!==0 (
set mine%ranX%_%ranY%=M
set /a mines=%mines% + 1
goto startGame
)
goto startGame
)
goto setup
:setup
cls
echo Loading...
set curVal=%setX%_%setY%
if %curVal%==1_6 goto display
if %setX%==6 (
set setX=1
set /a setY=%setY% + 1
goto setup
)
if !mine%setX%_%setY%!==M (
set /a setX=%setX% + 1
goto setup
)
set /a testY=%setY% + 1
set testX=%setX%
set N=!mine%testX%_%testY%!
set /a testY=%setY% + 1
set /a testX=%setX% + 1
set NE=!mine%testX%_%testY%!
set testY=%setY%
set /a testX=%setX% + 1
set E=!mine%testX%_%testY%!
set /a testY=%setY% + 1
set /a testX=%setX% - 1
set SE=!mine%testX%_%testY%!
set testY=%setY%
set /a testX=%setX% - 1
set S=!mine%testX%_%testY%!
set /a testY=%setY% - 1
set /a testX=%setX% - 1
set SW=!mine%testX%_%testY%!
set /a testY=%setY% + 1
set testX=%setX%
set W=!mine%testX%_%testY%!
set /a testY=%setY% - 1
set /a testX=%setX% + 1
set NW=!mine%testX%_%testY%!
set mineNum=0
if defined N if "%N%"=="M" set /a mineNum=%mineNum% + 1
if defined NW if "%NW%"=="M" set /a mineNum=%mineNum% + 1
if defined W if "%W%"=="M" set/a mineNum=%mineNum% + 1
if defined SW if "%S%"=="M" set /a mineNum=%mineNum% + 1
if defined S if "%S%"=="M" set /a mineNum=%mineNum% + 1
if defined SE if "%SE%"=="M" set /a mineNum=%mineNum% + 1
if defined E if "%E%"=="M" set /a mineNum=%mineNum% + 1
if defined NE if "%NE%"=="M" set /a mineNum=%mineNum% + 1
set mine%setX%_%setY%=%mineNum%
set /a setX=%setX% + 1
goto setup
:display
cls
::echo 5 %rect1_5% %rect2_5% %rect3_5% %rect4_5% %rect5_5%
::echo.
::echo 4 %rect1_4% %rect2_4% %rect3_4% %rect4_4% %rect5_4%
::echo.
::echo 3 %rect1_3% %rect2_3% %rect3_3% %rect4_3% %rect5_3%
::echo.
::echo 2 %rect1_2% %rect2_2% %rect3_2% %rect4_2% %rect5_2%
::echo.
::echo 1 %rect1_1% %rect2_1% %rect3_1% %rect4_1% %rect5_1%
::echo.
::echo a b c d e
echo 5 %mine1_5% %mine2_5% %mine3_5% %mine4_5% %mine5_5%
echo.
echo 4 %mine1_4% %mine2_4% %mine3_4% %mine4_4% %mine5_4%
echo.
echo 3 %mine1_3% %mine2_3% %mine3_3% %mine4_3% %mine5_3%
echo.
echo 2 %mine1_2% %mine2_2% %mine3_2% %mine4_2% %mine5_2%
echo.
echo 1 %mine1_1% %mine2_1% %mine3_1% %mine4_1% %mine5_1%
echo.
echo a b c d e
pause
:info
:end
exit
Your major problem is trailing spaces on lines. In a conventional set statement, any trailing spaces are included in the value assigned, and "M" and "M " are completely different things, so if you have set X=!something! then the value assigned is different from that assigned by set X=!something!.
You also have a problem where you are confusing your X with your Y. For instance, setting W is done with X and Y+1 - the same as setting N. This should be X-1 and Y.
I've got a set of variables called p1 to p9
I've got 2 vars to set the range I'm interested in.
I want to list all the vars from minimum range +1 to the max.
It looks like that (and it won't work)
set currentvar=5
set maxvar=9
set p1=aaa
set p2=bbb
set p3=ccc
set p4=ddd
set p5=eee
set p6=fff
set p7=ggg
set p8=hhh
set p9=iii
set /a result = %maxvar% - %currentvar%
echo Found %result% vars in the range.
:LOOP
if %currentvar% LSS %maxvar% (
set /a currentvar=%currentvar% + 1
echo %p %currentvar% % //IT WON'T WORK AND I DON'T KNOW HOW TO MAKE IT WORK...
goto LOOP
) else (
goto END
)
:END
The result I'd like to see:
fff
ggg
hhh
iii
this might work for you:
#ECHO OFF &SETLOCAL
set /a currentvar=5
set /a maxvar=9
set /a RangeStart=currentvar+1
set p1=aaa
set p2=bbb
set p3=ccc
set p4=ddd
set p5=eee
set p6=fff
set p7=ggg
set p8=hhh
set p9=iii
set /a result=maxvar-currentvar
echo Found %result% vars in the range.
for /l %%a in (%RangeStart% 1 %maxvar%) do call echo(%%p%%a%%
You need to Enabledelayedexpansion:
#echo off
Setlocal Enabledelayedexpansion
set currentvar=5
set maxvar=9
set p1=aaa
set p2=bbb
set p3=ccc
set p4=ddd
set p5=eee
set p6=fff
set p7=ggg
set p8=hhh
set p9=iii
set /a result = %maxvar% - %currentvar%
echo Found %result% vars in the range.
:LOOP
if %currentvar% LSS %maxvar% (
set /a currentvar=%currentvar% + 1
echo !p%currentvar%! &REM This is how you make a comment in batch
goto LOOP
) else (
goto END
)
:END
Endlocal
And that should do what you want to do. Also to make a comment use a new line and type :: or REM.
Mona