endrega
endrega

Reputation: 25

Batch IF statement variable inside another variable

I'm having a problem with a framework for a batch game I'm trying to create. I want to check if a variable is something other than a blank space. However, which variable I'm trying to check is in itself defined by two variables. For example:

if not %px%xplayerlocation%y%yplayerlocation%%==%blank% goto wherever

As you can see, the variable to be checked is determined by the values of %xplayerlocation% and %yplayerlocation%. To my knowledge, only the outermost %% signs are being read as being a variable and the inner ones are being read as literal percent signs. Does anyone know a way around this problem? I'll give any additional information if anyone needs it. Thanks.

Upvotes: 0

Views: 86

Answers (2)

dbenham
dbenham

Reputation: 130839

You have recognized the source of the problem, but your description of the behavior is incorrect. The parser will attempt to expand variables named px and y, and it will convert the final %% into %.

The Magoo solution will work, but using CALL is quite slow. That may not be a problem for many small scripts, but for a batch game it can kill performance.

You want delayed expansion. Include setlocal enableDelayedExpansion near the beginning of your script. Then use the following:

if not !px%xplayerlocation%y%yplayerlocation%!==%blank% goto wherever

Normal %var% expansion occurs early at parse time, and !var! expansion occurs late at execution time, so you get the proper result.

The above will not work if the value of %blank% is a space. The simplest solution would be to use delayed expansion for !blank! as well.

You might find yourself in a situation where the coordinate values need to be set and expanded within the same block of code, like in a FOR loop or IF statement:

setlocal enableDelayedExpansion
...
REM This does not work
for ... in (...) do (
   ...
   set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
   if not !px%xplayerlocation%y%yplayerlocation%!==!blank! REM doSomething
   ...
)

The above will not work because %var% expansion occurs at parse time, and the entire parenthesized block of code is parsed before any code is executed. So the expanded value is constant - it will expand to the value that existed before the loop started.

The solution is to transfer the coordinate values to FOR variables using delayed expansion:

setlocal enableDelayedExpansion
...
REM This works
for ... in (...) do (
   ...
   set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
   for %%X in (!xPlayerLocation!) do for %%Y in (!yPlayerLocation!) do (
     if not !px%%X%y%%Y!==%blank% REM doSomething
   )
   ...
)

or

setlocal enableDelayedExpansion
...
REM This also works
for ... in (...) do (
   ...
   set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
   for /f "tokens=1,2" %%X in ("!xPlayerLocation! !yPlayerLocation!") do (
     if not !px%%X%y%%Y!==%blank% REM doSomething
   )
   ...
)

If you are serious about developing a high quality game using batch, then you may be interested in studying the techniques I used in developing SNAKE.BAT - an arcade style game using only native batch commands. The beginning of the post is a bunch of code, but afterwards I describe a number of techniques I used for improving performance. It is advanced stuff, so don't try to absorb everything at once. Absorb what you can, and then revisit the post later on after you gain more experience.

Upvotes: 0

Magoo
Magoo

Reputation: 80023

@ECHO OFF
SETLOCAL
SET "blank= "
SET xplayerlocation=3
SET yplayerlocation=4

ECHO test with blank================

SET px3y4=%blank%

CALL SET varval=%%px%xplayerlocation%y%yplayerlocation%%%
if not "%varval%"=="%blank%" ECHO goto wherever - NOT blank

ECHO test with "Q"================

SET px3y4=Q

CALL SET varval=%%px%xplayerlocation%y%yplayerlocation%%%
if not "%varval%"=="%blank%" ECHO goto wherever - NOT blank

GOTO :EOF

This should get you out of trouble.

Upvotes: 1

Related Questions