0

I've recently started to learn batch for the sake of writing batch sims for a game that I've been playing. I was wondering if its possible to somehow iterate through like named variables (since I can't seem to find anything about a list?). Also I'm not sure if I can put a label to call to as a variable passed.

Code Example:

:: Enemy Fortress level.
SET EFORTLVL=4

:: Don't mess with anything below here only the variables above.

:: Enemy Fortress that will be simmmed against. Note this batch sim is  only built to run against one tower, as this is what you should be doing.
SET EFORTRESS1="Foreboding Archway-%EFORTLVL%"
SET EFORTRESS2="Illuminary Blockade-%EFORTLVL%"
SET EFORTRESS3="Tesla Coil-%EFORTLVL%"
SET EFORTRESS4="Minefield-%EFORTLVL%"
SET EFORTRESS5="Forcefield-%EFORTLVL%"

call :sim 1

:sim
SET /a "COUNTER=1"
SETLOCAL enabledelayedexpansion
SET times=!ITERATIONS%1!
ENDLOCAL & SET TIMES=%times%
:whilesim
SETLOCAL enabledelayedexpansion
SET fort=!EFORTRESS%COUNTER%!
ENDLOCAL & SET FORT=%fort%
tuo.exe %DECK0% %ENEMY% surge random -v efort %FORT% yfort %YFORTRESSES% climb %TIMES% >> %PATH%\WarDefClimbData%DECK0%.txt
SET /a "COUNTER=COUNTER+1"
if %COUNTER% leq 5 GOTO :whilesim else GOTO :eof

The result that I get for the line on the console:

RESOLVED: What I want to do is get a value from a variable that holds a string name that relates to the variable in question. (Ex when the for loop passes 1 I want to get EFORTRESS1 value, 2 I want EFORTRESS2 value etc).

E:\Programs\Tyrant Unleashed Optimizer>tuo.exe oconzer "VetDecks" surge random -v efort EFORTRESS1 yfort "Inspiring Altar #2" climb ITERATIONS1  1>>"e:\Programs\Tyrant Unleashed Optimizer\BatchSimResults"WarDefClimbDataoconzer.txt
Error: unrecognized fortress EFORTRESS1

Now I understand why its saying the error, what I don't understand is why its not getting the value from the string that is contained in FORT.

RESOLVED Getting an endless loop, where the iteration variable isn't updating.

  • 1
    Could you reduce the problem to a batch-only problem, stating inputs and desired outputs? Also, show what you've tried so far. – dovetalk Mar 14 '16 at 01:45
  • 1
    I don't have an answer for you, but I do recommend you look at PowerShell, which is much more programmer-friendly than cmd.. – Mark Reed Mar 14 '16 at 01:45
  • It is a batch only problem. I'm trying to read a value from %FORT% as the variable %EFORTRESS1%, %EFORTRESS2%.... If i put in the variables as %EFORTRESS1, %EFORTRESS2%.... it works, but I"m trying to make a function to short hand that so I don't have to write the same code multiple times. :S – Thomas Morse Mar 14 '16 at 01:45
  • I'm almost positive that you need to add the line `setlocal enabledelayedexpansion` to the beginning of your code and then say `set FORT=!EFORTRESS%1!`, but I'm not entirely sure what you're asking. – SomethingDark Mar 14 '16 at 01:49
  • That works for what I wanted SomethingDark. :D – Thomas Morse Mar 14 '16 at 01:55
  • Now i'm just trying to figure out how to get it to loop the way I want. :S – Thomas Morse Mar 14 '16 at 02:04
  • @ThomasMorse: I suggest you to look at [this answer](http://stackoverflow.com/questions/10166386/arrays-linked-lists-and-other-data-structures-in-cmd-exe-batch-script/10167990#10167990), that explain this management with detail... – Aacini Mar 14 '16 at 04:33
  • @MarkReed: You should not do _unrequested_ recommendations on using PowerShell instead Batch; doing that may introduce errors not present in the Batch code, like in http://stackoverflow.com/questions/35313953/findstr-always-fails-to-find-hash-string-in-text-file/35324145#35324145, or be worst than the Batch code, like in http://stackoverflow.com/questions/35637893/replace-multiple-lines-in-powershell/35728994#35728994. If you don't like Batch files, just don't read these questions! PowerShell is _not_ "much more programmer-friendly" than Batch files, and there are a lot of proofs of this point – Aacini Mar 14 '16 at 05:43
  • @aacini you're right, i shouldn't do that. I try not to answer questions about technology X with recommendations to use Y instead, at least not without providing an actual X solution first. Not going to get in a debate about the relative merits in the comments; Powershell has its own problems and pitfalls and is certainly no magic bullet to fix all your batch file woes. I just find that people who have some programming background in other systems often find PowerShell the easier environment to adapt to. – Mark Reed Mar 14 '16 at 14:08

1 Answers1

0
:sim
SETLOCAL ENABLEDELAYEDEXPANSION
SET "FORT=!EFORTRESS%1!"
ENDLOCAL&SET "fort=%fort%"
SET TIMES=ITERATIONS%2
SET LABEL=%3

The issue is to get the contents of (the contents of a variable), often call "indirection".

This is probably the easiest way. It uses setlocal enabledelayedexpansion which places cmd in delayedexpansion mode, where !var! is evaluated after its contents.

The drawback is that it must be invoked using setlocal, which establishes a local environment. The loacl environment must eventually be closed (you cannot keep opening more) and at that time, all changes to the environment are discarded and it is restored to its state at the point of executing setlocal.

The endlocal&... uses a parsing trick to transfer the changes out of the setlocal/endlocal bracket.

As for the other questions - yes, you can goto a variable (and the contents of the variable need not have a leading colon). It is quite possible to use goto somewhere%1 for instance, and supply %1 as a parameter as you've done. The text somewhere would be simply prepended to the value %1.

BTW - it would appear that you are changing path. This is not a good idea. path is the variable that contains a ;-separated list of directories which are searched for an executable if that executable is invoked and not found in the current directory. Best left well alone. Same goes for tmp and temp (which point to a temporary directory) and date and time and random and cd (the current date, time, a random number and the current directory)

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • Ok I've updated it to have the endlocal like you suggested, now I've ran into the issue that my for loop is not updating the first variable (the counter %G). Its staying 1. :S As far as path, I'm setting it as a variable at the very top so I don't have to keep retyping the path that I want the results to save at. Like so: SET PATH="e:\Programs\Tyrant Unleashed Optimizer\BatchSimResults" – Thomas Morse Mar 14 '16 at 02:17
  • Think about what happens when you get to your final `if`. The routine will go to the label `step1` and then do what? Here's a clue: `goto :eof` means `go to end-of-physical-file` which will terminate a subroutine. As for `path` - Don't say I didn't warn you... – Magoo Mar 14 '16 at 03:04