Tic Tac Toe Batch Game - batch-file

I'm trying to code a tictactoe game in batch.
But I ran into several problems I can't solve.
After the third move of player 1, the game has to check if player 1 has won.
I tried to do that by making 8 variables of all possible 8 winlines. And then the game checks if any of the winlines equals to XXX or OOO.
The Problem is that the field variables (_f1, _f2, etc.) don't change to X or O. I set them at the beginning of the script by their numbers, but I dont understand why they dont change once a player put a X or O in that field/variable.
The code is very ugly and unnecessarily long. I'm aware of the for command and i can do basic loops, but I cant wrap my head around the syntax if the command gets too complicated. How can I put all the repititions in for loops?
#echo off
setlocal enabledelayedexpansion
title .:TIC TAC TOE:.
mode con: cols=40 lines=20
color 02
cls
goto :main
:check
if !_win1!==XXX (
echo END OF GAME
pause
)
if !_win2!==XXX (
echo END OF GAME
pause
)
if !_win3!==XXX (
echo END OF GAME
pause
)
if !_win4!==XXX (
echo END OF GAME
pause
)
if !_win5!==XXX (
echo END OF GAME
pause
)
if !_win6!==XXX (
echo END OF GAME
pause
)
if !_win7!==XXX (
echo END OF GAME
pause
)
if !_win8!==XXX (
echo END OF GAME
pause
)
goto :eof
:player2turn
choice /c 123456789 /n /m "!_player2!, it's your turn!"
if !errorlevel!==1 (
if !_f1!==1 (
set _f1=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==2 (
if !_f2!==2 (
set _f2=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==3 (
if !_f3!==3 (
set _f3=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==4 (
if !_f4!==4 (
set _f4=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==5 (
if !_f5!==5 (
set _f5=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==6 (
if !_f6!==6 (
set _f6=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==7 (
if !_f7!==7 (
set _f7=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==8 (
if !_f8!==8 (
set _f8=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==9 (
if !_f9!==9 (
set _f9=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
goto :eof
:player1turn
choice /c 123456789 /n /m "!_player1!, it's your turn!"
if !errorlevel!==1 (
if !_f1!==1 (
set _f1=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==2 (
if !_f2!==2 (
set _f2=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==3 (
if !_f3!==3 (
set _f3=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==4 (
if !_f4!==4 (
set _f4=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==5 (
if !_f5!==5 (
set _f5=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==6 (
if !_f6!==6 (
set _f6=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==7 (
if !_f7!==7 (
set _f7=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==8 (
if !_f8!==8 (
set _f8=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==9 (
if !_f9!==9 (
set _f9=!_player1symbol!
echo !_win1!
echo !_player1symbol!
pause
goto :eof
) else (
goto :player1turn
)
)
goto :eof
::displaying the map
:map
echo.
echo.
echo.
echo !_f7! ^| !_f8! ^| !_f9!
echo ---------
echo !_f4! ^| !_f5! ^| !_f6!
echo ---------
echo !_f1! ^| !_f2! ^| !_f3!
echo.
echo.
echo.
goto :eof
::setting variables
:setvar
set _f1=1
set _f2=2
set _f3=3
set _f4=4
set _f5=5
set _f6=6
set _f7=7
set _f8=8
set _f9=9
set _win1=!_f7!!_f8!!_f9!
set /a _win2=!_f4!+!_f5!+!_f6!
set /a _win3=!_f1!+!_f2!+!_f3!
set /a _win4=!_f7!+!_f4!+!_f1!
set /a _win5=!_f8!+!_f5!+!_f2!
set /a _win6=!_f9!+!_f6!+!_f3!
set /a _win7=!_f7!+!_f5!+!_f3!
set /a _win8=!_f9!+!_f5!+!_f1!
goto :eof
::player settings
:setup
echo.
set /p _player1=Enter name for Player 1:
echo.
choice /c xo /n /m "!_player1! do you want to play as X or O?"
if !errorlevel!==1 (
set _player1symbol=X
set _player2symbol=O
) else (
set _player1symbol=O
set _player2symbol=X
)
echo.
echo.
set /p _player2=Enter name for Player 2:
echo.
cls
echo.
echo.
echo.
echo !_player1!(!_player1symbol!) vs. !_player2!(!_player2symbol!)
pause>nul
goto :eof
:main
setlocal
call :setup
cls
call :setvar
call :map
call :player1turn
cls
call :map
call :player2turn
cls
call :map
call :player1turn
cls
call :map
call :player2turn
cls
call :map
call :player1turn
call :check
endlocal
goto :eof

You should research and define your coding approach before write a single line of program. Also, you should learn the language features in order to make good use of its facilities. This applies to any programming language.
This is the way I would do it:
#echo off
setlocal EnableDelayedExpansion
rem Test for win: Horizontal rows
set "win[1]=%%pos[1]%%%%pos[2]%%%%pos[3]%%"
set "win[2]=%%pos[4]%%%%pos[5]%%%%pos[6]%%"
set "win[3]=%%pos[7]%%%%pos[8]%%%%pos[9]%%"
rem Test for win: Vertical cols
set "win[4]=%%pos[1]%%%%pos[4]%%%%pos[7]%%"
set "win[5]=%%pos[2]%%%%pos[5]%%%%pos[8]%%"
set "win[6]=%%pos[3]%%%%pos[6]%%%%pos[9]%%"
rem Test for win: Diagonals
set "win[7]=%%pos[1]%%%%pos[5]%%%%pos[9]%%"
set "win[8]=%%pos[7]%%%%pos[5]%%%%pos[3]%%"
for /L %%i in (1,1,9) do set "pos[%%i]=%%i"
set "taken=_"
cls
set /P "player[X]=Enter player 1 (X) name: "
set /P "player[O]=Enter player 2 (O) name: "
call :showBoard
set "players=XO"
for /L %%n in (1,1,9) do (
call :playerTurn !players:~0,1!
if !result! equ 1 echo You win^^^! & goto :EOF
set "players=!players:~1,1!!players:~0,1!"
)
echo Game was a draw...
goto :EOF
:playerTurn wichOne
choice /C 123456789 /N /M "!player[%1]!, it's your turn: "
set "choice=%errorlevel%"
if "!taken:%choice%=!" neq "%taken%" echo Bad position & goto playerTurn
set "taken=%taken%%choice%"
set "pos[%choice%]=%1"
call :showBoard
rem Test if win
set "result=0"
for /L %%i in (1,1,8) do if !result! equ 0 (
call set "line=!win[%%i]!
if "!line!" equ "%1%1%1" set "result=1"
)
exit /B
:showBoard
echo/
echo/
echo %pos[1]% ^| %pos[2]% ^| %pos[3]%
echo ---------
echo %pos[4]% ^| %pos[5]% ^| %pos[6]%
echo ---------
echo %pos[7]% ^| %pos[8]% ^| %pos[9]%
echo/
echo/
exit /B
EDIT 2021/12/08: New version added
The original version of this program was simple enough to be understand by the OP. The next version below was written with the purpose of be as efficient and short as possible:
#echo off
setlocal EnableDelayedExpansion
set "win=" & set "out="
for %%a in (1:2:3 4:5:6 7:8:9 1:4:7 2:5:8 3:6:9 1:5:9 3:5:7) do (
for /F "tokens=1-3 delims=:" %%x in ("%%a") do (
set "win=!win! ^!pos[%%x]^!^!pos[%%y]^!^!pos[%%z]^!"
if "!out:~-3,1!" neq "9" set "out=!out!$^!pos[%%x]^! ^^| ^!pos[%%y]^! ^^| ^!pos[%%z]^!"
)
)
set "out=!out:~1!"
:menu
cls
set /P "player[X]=Enter player 1 (X) name: "
set /P "player[O]=Enter player 2 (O) name: "
for /L %%i in (1,1,9) do set "pos[%%i]=%%i"
set "options=123456789" & set "filler=asdfghjkl"
for %%n in (X O X O X O X O X) do (
cls
echo/& echo/& echo %out:$=& echo --+---+--& echo %& echo/& echo/
choice /C !options! /N /M "!player[%%n]!, it's your turn: "
for /F "tokens=1,2" %%e in ("!errorlevel! !filler:~0,1!") do (
set "options=!options:%%e=%%f!" & set "filler=!filler:~1!" & set "pos[%%e]=%%n"
)
set "line=%win%"
if "!line:%%n%%n%%n=!" neq "!line!" echo You win^^^! & goto nextGame
)
echo Game was a draw...
:nextGame
echo/
pause
goto :menu

#Aacini posted a great answer, so I decided to post my own as well. As they say, there are many ways to skin a cat.
#echo off & Title Tic-Tac-Toe
setlocal enabledelayedexpansion & mode con: cols=40 lines=20 & color 02
for /F %%i in ('echo prompt $E ^| cmd') do set "n=%%iE"
:menu
cls & set gone=. & for %%p in (player[X] player[O]) do set /p "%%~p=enter name %%p: "
for /l %%i in (1,1,9) do set a%%i=%%i
for /L %%i in (1,1,4) do for %%a in (X O) do (
for %%x in (!a1!!a2!!a3! !a4!!a5!!a6! !a7!!a8!!a9! !a1!!a4!!a7! !a2!!a5!!a8! !a3!!a6!!a9! !a1!!a5!!a9! !a3!!a5!!a7!) do (
if "%%x" == "!_h!!_h!!_h!" echo !pl! wins & timeout /t 4 /NOBREAK >nul & goto :menu
)
set "pl=!player[%%a]!" & set _h=%%a
call :play
set "a!ch!=%%a"
if %%i geq 4 echo No winners & timeout /t 4 /NOBREAK >nul & goto :menu
)
:play
cls & echo(
echo !a1! ^| !a2! ^| !a3!%n% ----------%n% !a4! ^| !a5! ^| !a6!%n% ----------%n% !a7! ^| !a8! ^| !a9!%n%
choice /c 123456789 /m "!pl!'s turn"
set ch=!errorlevel!
if !ch! equ 0 exit /b
if "!gone:%ch%=!" neq "%gone%" echo That spot has been taken, try again & timeout /t 3 /NOBREAK >nul & goto :play
set "gone=%gone%!ch!"
goto :eof
And a version for older windows that does not support VT100:
#echo off & Title Tic-Tac-Toe
setlocal enabledelayedexpansion & mode con: cols=40 lines=20 & color 02
:menu
cls & set gone=. & for %%p in (player[X] player[O]) do set /p "%%~p=enter name %%p: "
for /l %%i in (1,1,9) do set a%%i=%%i
for /L %%i in (1,1,4) do for %%a in (X O) do (
for %%x in (!a1!!a2!!a3! !a4!!a5!!a6! !a7!!a8!!a9! !a1!!a4!!a7! !a2!!a5!!a8! !a3!!a6!!a9! !a1!!a5!!a9! !a3!!a5!!a7!) do (
if "%%x" == "!_h!!_h!!_h!" echo !pl! wins & timeout /t 4 /NOBREAK >nul & goto :menu
)
set "pl=!player[%%a]!" & set _h=%%a
call :play
set "a!ch!=%%a"
if %%i geq 4 echo No winners & timeout /t 4 /NOBREAK >nul & goto :menu
)
:play
cls & echo(
echo !a1! ^| !a2! ^| !a3!&echo ----------&echo !a4! ^| !a5! ^| !a6!&echo ----------&echo !a7! ^| !a8! ^| !a9!&echo(
choice /c 123456789 /m "!pl!'s turn"
set ch=!errorlevel!
if !ch! equ 0 exit /b
if "!gone:%ch%=!" neq "%gone%" echo That spot has been taken, try again & timeout /t 3 /NOBREAK >nul & goto :play
set "gone=%gone%!ch!"
goto :eof

I got the solution
All i had to do was to set the win variables later, when checking the winlines.

For the task of testing, string substitution can be used with variables to test a list of winning cell combinations concisely.
#Echo off & CHCP 65001 > nul
Set LF=^
%= Above empty line required =%
For /l %%i in (1 1 9)Do Set c%%i=_
Set Screen=Player: !Player!!LF!!LF! [!c7!][!c8!][!c9!]!LF! [!c4!][!c5!][!c6!]!LF! [!c1!][!c2!][!c3!]!LF!
Set state=!c1!!c2!!c3!,!c1!!c4!!c7!,!c1!!c5!!c9!,!c4!!c5!!c6!,!c7!!c8!!c9!,!c7!!c5!!c3!,!c3!!c6!!c9!,!c2!!c5!!c8!
Set "p1=X" & Set "p2=O"
Set /A "choices=123456789","Move=0","p%p1%%p1%%p1%=1","p%p2%%p2%%p2%=2"
Setlocal EnableDelayedExpansion & For /l %%m in (1 1 9)Do (
Set /A "player=((%%m-1) %% 2)+1"
cls & Echo(%Screen%
For /f "Delims=" %%e in ('Choice /n /c:!choices!')Do (
Set "choices=!choices:%%e=!"
For %%i in (!player!)Do Set "c%%e=!p%%i!"
)
cls & Echo(%Screen%
If %%m GTR 4 (
Set "test=%State%"
For %%i in (!p1!!p1!!p1! !p2!!p2!!p2!)Do if not "!test:%%i=!"=="!test!" (
Echo(player !p%%i! won
Goto:Eof
) ) )
Echo(draw & Endlocal

Related

Echo output for each value in given list in bat file

With below code I'm struggling to print calculation for each value in a given list. Currently it prints total combined time for both users, I want to echo individual time for each user which is listed in 2nd row of this code.\
Any help will be appreciated.
#Echo off
For %%U in (a3rgcw shukla) Do (
PushD "H:\Syslogs\" ||(Echo couldn't find dir & Pause & Exit /B 1)
Set "TotalSecs=0"
For %%F in ("*%U%*.txt") Do For /F "delims=" %%A in ('
findstr /I "system.log.created End.of.session" "%%F"
') Do (
Set "Flag="
Echo=%%A|findstr /I "system.log.created" 2>&1>Nul && Set "Flag=Start"
if defined Flag (
FOR /F "tokens=11" %%T in ("%%A") Do Call :TimeToSecs Start "%%T"
) Else (
FOR /F "tokens=8" %%T in ("%%A") Do Call :TimeToSecs Stop "%%T"
)
)
Echo TotalDuration for %%U:%TotalDur%
)
Echo:
PopD
Goto :Eof
:TimeToSecs
Set "%1_HMS=%~2"
Echo:%~2|Findstr "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" 2>&1>Nul || (Echo wrong format %2&Goto :Eof)
For /F "tokens=1-3 delims=:" %%H in ("%~2"
) Do Set /A "%1=(1%%H-100)*60*60+(1%%I-100)*60+(1%%J-100)"
If %1 neq Stop Goto :Eof
Set /A "Diff=Stop-Start,TotalSecs+=Diff"
Call :Secs2HMS Dur %Diff%
Call :Secs2HMS TotalDur %TotalSecs%
::Echo Session from %Start_HMS% to %Stop_HMS% Duration:%Dur% TotalDuration:%TotalDur%
Goto :Eof
:Secs2HMS var value
setlocal
set /a "HH=%2/3600,mm=(%2-HH*3600)/60+100,ss=%2 %% 60+100"
Set "HHmmss= %HH%:%mm:~-2%:%ss:~-2%"
endlocal&set "%1=%HHmmss:~-10%
Goto :Eof
Current output:
TotalDuration for a3rgcw: 7:15:00
TotalDuration for shukla: 7:15:00
Desired output:
TotalDuration for a3rgcw: 5:15:00
TotalDuration for shukla: 2:00:00
Sample file named shukladfdf for 2nd user:
sdsdf system log created on ghg Thursday, 9 August 2018, 20:30:45 on India
Standard Time
dfg
drdwewed
end of session as 9 August 2018, 22:30:45 on India Standard Time
#Echo off
Setlocal
PushD "H:\Syslogs\" ||(Echo couldn't find dir & Pause & Exit /B 1)
For %%U in (a3rgcw shukla) Do (
Set "TotalDur="
Set "TotalSecs=0"
For %%F in ("*%%U*.txt") Do For /F "delims=" %%A in ('
findstr /I "system.log.created End.of.session" "%%F"
') Do (
Set "FileName=%%F"
Set "Flag="
Echo=%%A|findstr /I "system.log.created" 2>&1>Nul && Set "Flag=Start"
if defined Flag (
FOR /F "tokens=11" %%T in ("%%A") Do Call :TimeToSecs Start "%%T"
) Else (
FOR /F "tokens=8" %%T in ("%%A") Do Call :TimeToSecs Stop "%%T"
)
)
Set "UsrName=%%U: "
Call :Print UsrName
)
Echo:
PopD
Goto :Eof
:Print
If /i "%~1" == "UsrName" (
Echo TotalDuration for %UsrName:~,10% %TotalDur%
) else If /i "%~1" == "FileName" (
Echo Session (%FileName%^) from %Start_HMS% to %Stop_HMS% Duration:%Dur% TotalDuration:%TotalDur%
)
Goto :Eof
:TimeToSecs
Set "%1_HMS=%~2"
Echo:%~2|Findstr "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" 2>&1>Nul || (Echo wrong format %2&Goto :Eof)
For /F "tokens=1-3 delims=:" %%H in ("%~2"
) Do Set /A "%1=(1%%H-100)*60*60+(1%%I-100)*60+(1%%J-100)"
If %1 neq Stop Goto :Eof
Set /A "Diff=Stop-Start,TotalSecs+=Diff"
Call :Secs2HMS Dur %Diff%
Call :Secs2HMS TotalDur %TotalSecs%
Call :Print FileName
Goto :Eof
:Secs2HMS var value
setlocal
set /a "HH=%2/3600,mm=(%2-HH*3600)/60+100,ss=%2 %% 60+100"
Set "HHmmss= %HH%:%mm:~-2%:%ss:~-2%"
endlocal&set "%1=%HHmmss:~-10%"
Goto :Eof
Changed %U% to %%U.
Changed Echo TotalDuration for %%U:%TotalDur% to
Call Echo TotalDuration for %%U:%%TotalDur%% which
delays expansion until time of execution, instead of
parse time.
Added missing double quote with 2nd last line to close.
Added Setlocal to top of script as perhaps a 2nd run
of the script in the same CMD session could set
predined variables with values.
Added label :Print to echo the output to avoid
use of delayed expansion.

variables not carried over from this script

this script takes a video file as input and after preliminary renaming extrapolates values such as title and year or episode along with a search strings strict for finding duplicate videos and loose for finding all episodes of a series. it then does a controlled filebot rename for the file.
set "filename=%~n1"
set "parentdir=%~2"
:: =============================================================================================================================
:: 1. FILENAME VALIDATOR
:: =============================================================================================================================
set "original=%filename%"
set "filename=%filename:!=%"
set "filename=%filename:&=and%"
setlocal enabledelayedexpansion
set "filename=!filename:%%=_percent!"
for /l %%s in (0,1,9) do set "filename=!filename:series.%%s=S0%%s!"
for /l %%e in (0,1,9) do set "filename=!filename:%%eof2=E0%%e!"
for /l %%e in (0,1,9) do set "filename=!filename:%%eof3=E0%%e!"
for /l %%e in (0,1,9) do set "filename=!filename:%%eof4=E0%%e!"
for /l %%e in (0,1,9) do set "filename=!filename:%%eof5=E0%%e!"
for /l %%e in (0,1,9) do set "filename=!filename:%%eof6=E0%%e!"
for /l %%e in (0,1,9) do set "filename=!filename:%%eof7=E0%%e!"
for /l %%e in (0,1,9) do set "filename=!filename:%%eof8=E0%%e!"
for /l %%e in (0,1,9) do set "filename=!filename:%%eof9=E0%%e!"
setlocal disabledelayedexpansion
if not "%filename%"=="%original%" ren "%~1" "%filename%%~x1" && echo validated "%original%"
:: =============================================================================================================================
:: 2. EXTRAS RENAMER
:: =============================================================================================================================
echo "%~p1" | find /i "extras" >nul || goto skip_extras
echo "%~p1" | find /i "featurettes" >nul || goto skip_extras
if not defined parentdir echo detected featurette but parentdir was not delivered && exit /b
call :extrapolate "%parentdir%"
ren "%filename%%~x1" "%name% extras - %filename%%~x1" && echo renamed extra "%name% extras - %filename%%~x1" && exit /b
:skip_extras
:: =============================================================================================================================
:: 3. EXTRAPOLATOR
:: =============================================================================================================================
:extrapolate
set "type=" & set "year=" & set "ss=" & set "ep=" & set "episode="
set "name=%filename%"
echo "%name%"| find " " >nul || set "name=%name:.= %" & rem if no spaces then then safer to replace dots
:: episode number: last tag first
SETLOCAL enabledelayedexpansion
FOR /L %%e IN (100,1,199) DO (
SET "modname=!name:E%%e=!"
IF "!modname!" neq "%name%" (
SET "setcmd=set name=!name:E%%e=& set ep=E%%e& set type=show& rem !"
GOTO gotep
)
)
FOR /L %%e IN (10,1,99) DO (
SET "modname=!name:E%%e=!"
IF "!modname!" neq "%name%" (
SET "setcmd=set name=!name:E%%e=& set ep=E%%e& set type=show& rem !"
GOTO gotep
)
SET "modname=!name:E0%%e=!"
IF "!modname!" neq "%name%" (
SET "setcmd=set name=!name:E0%%e=& set ep=E0%%e& set type=show& rem !"
GOTO gotep
)
)
FOR /L %%e IN (0,1,9) DO (
SET "modname=!name:E0%%e=!"
IF "!modname!" neq "%name%" (
SET "setcmd=set name=!name:E0%%e=& set ep=E0%%e& set type=show& rem !"
GOTO gotep
)
SET "modname=!name:E00%%e=!"
IF "!modname!" neq "%name%" (
SET "setcmd=set name=!name:E00%%e=& set ep=E00%%e& set type=show& rem !"
GOTO gotep
)
SET "modname=!name:%%eof=!"
IF "!modname!" neq "%name%" (
SET "setcmd=set name=!name:%%eof=& set ep=E0%%e& set type=show& rem !"
GOTO gotep
)
SET "modname=!name:x0%%e=!"
IF "!modname!" neq "%name%" (
SET "setcmd=set name=!name:x0%%e=& set ep=E0%%e& set type=show& rem !"
GOTO gotep
)
)
ENDLOCAL
GOTO skipep
:gotep
%setcmd%
ENDLOCAL & SET "type=%type%" & SET "ep=%ep%" & SET name=%name%
:skipep
:: season number: second to last tag second
SETLOCAL enabledelayedexpansion
FOR /L %%e IN (0,1,9) DO (
SET "modname=!name:S0%%e=!"
IF "!modname!" neq "%name%" (
SET "setcmd=set name=!name:S0%%e=& set ss=S0%%e& set type=show& rem !"
GOTO gotss
)
)
FOR /L %%e IN (10,1,99) DO (
SET "modname=!name:S%%e=!"
IF "!modname!" neq "%name%" (
SET "setcmd=set name=!name:S%%e=& set ss=S%%e& set type=show& rem !"
GOTO gotss
)
)
FOR /L %%e IN (0,1,9) DO (
SET "modname=!name:series.%%e=!"
IF "!modname!" neq "%name%" (
SET "setcmd=set name=!name:series.%%e=& set ss=S0%%e& set type=show& rem !"
GOTO gotss
)
)
ENDLOCAL
GOTO skipss
:gotss
%setcmd%
ENDLOCAL & SET "type=%type%" & SET "ss=%ss%" & SET name=%name%
:skipss
if defined ep if not defined ss set ss=S01
SET "episode=%ss%%ep%"
:: year number: first tag last
SETLOCAL enabledelayedexpansion
FOR /L %%e IN (1957,1,2057) DO (
SET "modname=!name:%%e=!"
IF "!modname!" neq "%name%" (
SET "setcmd=set name=!name:%%e=& set year=%%e& if not defined type set type=film& rem !"
GOTO gotyear
)
)
ENDLOCAL
GOTO skipyear
:gotyear
%setcmd%
ENDLOCAL & SET "year=%year%" & SET "type=%type%" & SET name=%name%
:skipyear
:: finalize
:: changes for general use
set name=%name: - = %
:: trim last useless letter from name
set "name=%name%endtrimmer"
set "name=%name:(endtrimmer=endtrimmer%"
set "name=%name:[endtrimmer=endtrimmer%"
set "name=%name: endtrimmer=endtrimmer%"
set "name=%name: endtrimmer=%"
set "name=%name:_endtrimmer=%"
set "name=%name:endtrimmer=%"
:: set strings
if "%type%"=="film" set "strict=%name: =?%?(%year%)"
if "%type%"=="show" if defined year set "strict=%name: =?%?(%year%)?%episode%"
if "%type%"=="show" if not defined year set "strict=%name: =?%?%episode%"
if "%type%"=="show" if defined year set "loose=%name: =?%?(%year%)?s"
if "%type%"=="show" if not defined year set "loose=%name: =?%?s"
SETLOCAL enabledelayedexpansion
FOR %%a IN (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO SET "name=!name:%%a=%%a!"
endlocal & SET "name=%name%"
:: declare (disable never delete)
if "%type%"=="film" echo extrapolated film %strict:?= %
if "%type%"=="show" echo extrapolated episode %strict:?= %
:: =============================================================================================================================
:: 4. FILEBOT MODERATOR
:: =============================================================================================================================
if not defined type exit /b
:: prep fake temp file
set tempdir=%temp%\%date:~3,2%%date:~6,2%%date:~11,2%%time:~1,1%%time:~3,2%%time:~6,2%%time:~9,2%
mkdir "%tempdir%" && copy /y nul "%tempdir%\%filename%.mkv" >nul
:: variables (to shorten lines)
if "%type%"=="film" set cf=--db TheMovieDb --format "{n} ({y}) {director} {genres} r{rating} {vf} {vc} {ac} {imdbid}"
if "%type%"=="show" set cf=--db TheTVDb --format "{n} {s00e00} {t} {vf} {vc} {ac} {imdbid}"
:: rename fake temp file
filebot -rename "%tempdir%\%filename%%~x1" --q "%name% %year%" %cf% >nul 2>nul
:: new name into variable
for /r "%tempdir%" %%i in (*) do set "new=%%~ni"
:: declare failure
if "%filename%"=="%new%" echo filebot refused to rename "%~n1" && exit /b
:: if what expected rename 4real
echo %%new:^&=^^^&%% | findstr /i /b /c:"%strict:?= %" >nul && goto 4real
:: if not reformat and try again
set "new=%new:'=%"
set "new=%new:,=%"
echo %%new:^&=^^^&%% | findstr /i /b /c:"%strict:?= %" >nul && goto 4real
:: declare failure and confirm override
echo "%new%" does not match "%string%"
choice /t 20 /c yn /n /d n /m "override and approve rename? [Y]es or [N]o: "
if "%errorlevel%"=="1" goto 4real
exit /b
:4real
filebot -rename "%~dp1%filename%%~x1" --q "%name% %year%" %cf% >nul 2>nul
if not exist "%filename%" echo successfully renamed "%filename%"
exit /b
none of the variables are carried over to the script that called for them. I can't for the life of me figure out why except it must have something to do with endlocal or disabledelayedexpansion, which look fine to me as far as I can tell.

Batch : Multiple for /f commands

I'm trying to do "game" for my friend but when i try to load from save file it will do half of it's job
Code
set penize=0
set penizesekunda=0
for /f "EOL=: tokens=* Delims=0" %%a in (penize.txt) do (
set penize=%%a
)
for /f "EOL=: tokens=* Delims=1" %%b in (penize.txt) do (
set penizesekunda=%%b
)
echo Penize %penize% penize za sekundu %penizesekunda%
sorry it in my language (penize = money, penizesekunda = money per second)
And input is 200 200 but it should be 500 200.
If you want full code :
#echo off
title Hra (Imui)
color 6a
echo Ahoj %computername% cas %time% datum %date%
echo.
echo.
echo Vitej ve hre
echo.
echo.
echo.
echo Tvym cilem bude ovladnout cely VESMIR
echo.
timeout>nul /t 3 /nobreak
echo Nacitani!
set penize=0
set penizesekunda=0
for /f "EOL=: tokens=* Delims=0" %%a in (penize.txt) do (
set penize=%%a
)
for /f "EOL=: tokens=* Delims=1" %%b in (penize.txt) do (
set penizesekunda=%%b
)
if errorlevel 1 do (
echo Pozor nebyla nalezena zadna ulozena hra nebo doslo k chybe startovani! (hry se nachazeji v souboru penize.txt)
timeout>nul /t 3 /nobreak
cls
goto Start
)
:Start
cls
set /p "Password=Zadej heslo > "
if %Password%== Admin goto RMV
if NOT %Password%== Imui goto FAIL
if %Password%== Imui goto HesloSpravne
goto Start
:Fail
cls
echo Spatne heslo!
echo Zadej heslo prosim (zbyvaji 2 pokusy)
set /p "Password=Zadej heslo > "
if %Password%== Admin goto RMVCzech
if NOT %Password%== Imui goto FailTwo
if %Password%== Imui goto HesloSpravne
goto Fail
:FailDva
cls
echo Spatne heslo!
color ac
echo Pozor! Mas uz jenom jeden pokus!
echo Prosim zadej heslo!
set /p "Password=Zadej heslo > "
if %Password%== Admin goto RMV
if NOT %Password%== Imui goto RMV
if %Password%== Imui goto HesloSpravne
goto FailTwo
:RMV
echo Smazavam ti tvoji hru
#ECHO ON
del "Hra.exe" /P /Q /F
echo Smazavani dokonceno!
Pause>nul
exit
:HesloSpravne
cls
echo Heslo bylo spravne
goto HlavniMenu
:HlavniMenu
echo Vitej
echo %penizesekunda% %penize%
Pause>nul
Content of penize.txt :
500
200
Another (more efficient) option is to use SET /P to read each line:
<penize.txt (
set "penize="
set /p "penize="
set "penizesekunda="
set /p "penizesekunda="
)
The simple SET statements that clear each variable are there just in case the line happens to be empty or missing in the file, in which case SET /P would preserve any pre-existing variable value.
The code can be shortened by using a FOR loop, especially if you have many more lines to read:
<penize.txt ( for %%V in (penize penizesekunda) do (
set "%%V="
set /p "%%V="
))
Note that you can list the variables on separate lines, which can help readability:
<penize.txt (
for %%V in (
penize
penizesekunda
) do (
set "%%V="
set /p "%%V="
)
)
Here is some example code for you:
REM Get first line of a file
set /p penize=<penize.txt
REM Get second line of a file
for /f "skip=1" %%a in (penize.txt) do set penizesekunda=%%a

goto Was Unexpected At This Time {BATCH}

Im am trying to make a simple coin game in batch. The problem I have is once the delay is completed (ping) "goto was unexpected at this time" is all I get before the window closes. Any help would be appreciated!
#echo off
color f0
title Nim In Batch
::: Main Menu
:main
set /a coins=12
set /a time=0
cls
echo Nim In Batch!
echo.
choice /n /c pr /m "Play Or See Rules?"
if %errorlevel%==1 (
goto play
)
if %errorlevel%==2 (
goto rules
)
::: Rules
:rules
cls
echo Objective: Be the one to claim the last coin
echo.
echo Rules:
echo -You Play First
echo -You Must Remove 1,2 Or 3 Coins Each Turn
echo -Turns Switch Once Coins Are Removed
echo -Coins Must Be Removed In Order
echo.
echo Ready?
pause>nul
goto main
::: Game
:play
cls
echo (%coins%) Coins
echo.
choice /n /c 123 /m "How Many Coins Do You Wish To Remove?"
if %errorlevel%==1 (
set /a Coins=%coins%-1
)
if %errorlevel%==2 (
set /a Coins=%coins%-2
)
if %errorlevel%==3 (
set /a Coins=%coins%-3
)
cls
echo (%coins%) Coins
echo.
echo Computer Is Thinking
ping 1.1.1.1 -n 1 -w 3250 >NUL
if %errorlevel%==1 (
set /a Coins=%coins%-3
)
if %errorlevel%==2 (
set /a Coins=%coins%-2
)
if %errorlevel%==3 (
set /a Coins=%coins%-1
)
if %coin%==0 (
goto end
) else (
goto play
)
:end
cls
echo Computer Wins!
echo He Collected The Final Coin!
echo.
pause
goto main
You forget an s in %coins% here :
if %coins%==0 (
goto end
) else (
goto play
)

Batch script that needs ENABLEDELAYEDEXPANSION, but where and how?

The following is part of a batch script I'm testing, but the 2nd IF-statement at the bottom just won't work. I'm confident I need ENABLEDELAYEDEXPANSION, but I just don't know where and how.
FOR /F "delims==" %%B IN ("Filename_example.m4v") DO (
FOR /F "tokens=1 delims=." %%C IN ("%%B") DO SET name=%%C
FOR /F "tokens=2 delims=." %%D IN ("%%B") DO (
IF "%%D" EQU "m4v" SET ext=mp4
IF "%%D" EQU "m3u8" SET ext=mp4
IF "%%D" EQU "wmv" SET ext=wmv
)
)
ECHO Filename: %name%.%ext%
SET /P name1=Rename file (Y/N) {Y}?
IF /I "%name1%" EQU "N" SET filename=%name%.%ext%
IF /I "%name1%" NEQ "N" (
ECHO New filename:
SET /P name2=
SET filename=%name2%.%ext%
)
ECHO %filename%
You can use delayed expansion (see npocmaka's answer) or, keeping the same behaviour
for %%B in ("Filename_example.m4v") do (
set "name=%%~nB"
set "ext=%%~xB"
if /i "%%~xB"==".m4v" set "ext=.mp4"
if /i "%%~xB"==".m3u8" set "ext=.mp4"
)
echo Filename: %name%%ext%
set /p "rename=Renamefile (Y/N) {Y}?"
if /i not "%rename%"=="N" (
set /p "filename=New filename"
) else (
set "filename=%name%%ext%
)
echo %filename%
To turn on delayed expansion, use the setlocal command.
setlocal enableDelayedExpansion
FOR /F "delims==" %%B IN ("Filename_example.m4v") DO (
FOR /F "tokens=1 delims=." %%C IN ("%%B") DO SET name=%%C
FOR /F "tokens=2 delims=." %%D IN ("%%B") DO (
IF "%%D" EQU "m4v" SET ext=mp4
IF "%%D" EQU "m3u8" SET ext=mp4
IF "%%D" EQU "wmv" SET ext=wmv
)
)
ECHO Filename: %name%.%ext%
SET /P name1=Rename file (Y/N) {Y}?
IF /I "%name1%" EQU "N" SET filename=%name%.%ext%
IF /I "%name1%" NEQ "N" (
ECHO New filename:
SET /P name2=
SET filename=!name2!.!ext!
)
ECHO %filename%
From what I see you need to use delayedExpansion only on the last SET.To use the delayed expansion you need ! instead of %
Next script shows
where (minimal use, but could be extended to whole script, see npocmaka's answer) and
how to use EnableDelayedExpansion (SETLOCAL).
See also %%~nB, %%~xB and other ~ modifiers in Command Line arguments (Parameters)
Moreover, minimizes user's input to the only set /P.
#ECHO OFF >NUL
SETLOCAL enableextensions
FOR %%B IN (
"FN_example.m4v"
"fn_example2.WMV"
"fn_example3.xyz"
) DO (
set "name=%%~nB"
set "ext=%%~xB"
IF /I "%%~xB" EQU ".m4v" SET "ext=.mp4"
IF /I "%%~xB" EQU ".m3u8" SET "ext=.mp4"
IF /I "%%~xB" EQU ".wmv" SET "ext=.wmv"
SETLOCAL enabledelayedexpansion
ECHO orig. filename: !name!!ext!
SET /P "name=Type new filename (or hit <Enter> to keep '!name!'): "
SET "filename=!name!!ext!"
IF /I "!name!" EQU "%%~nB" (
ECHO name unchanged: !filename!
) else (
ECHO new file name: !filename!
)
ENDLOCAL
echo(
)
Thanks for all your help thus far. I have a working script. I'm sure things could be more efficient, but at least it's working! :) Sorry for the Dutch-language usage, the code may still be useful:
#ECHO off
CLS
REM BatchGemist geschreven door Reino Wijnsma, 2015 (reino#degeelebosch.nl)
SET batchname=BatchGemist
SET version=1.0
TITLE %batchname% %version%
IF NOT EXIST youtube-dl.exe (
ECHO 'youtube-dl.exe' niet gevonden.
ECHO.
GOTO Help
)
IF NOT EXIST ffmpeg.exe (
ECHO 'ffmpeg.exe' niet gevonden.
ECHO.
GOTO Help
)
FOR /F %%A IN ('youtube-dl.exe --version') DO ECHO (youtube-dl %%A)
ECHO Voer "?" in voor Hulp
ECHO.
:Input
ECHO Voer npo.nl, rtlxl.nl, kijk.nl, of youtube programma-link in:
SET url=
SET /P url=
IF "%url%"=="?" GOTO Help
IF "%url%"=="U" GOTO Update
:: stop script bij geen Input (enter-toets)
IF "%url%"=="" GOTO:eof
:: spaties in Input niet toestaan
IF NOT "%url: =%"=="%url%" (
ECHO.
ECHO Spaties in programma-link niet toegestaan.
ECHO.
GOTO Input
)
:: alleen bepaalde websites als input toestaan
IF NOT "%url:http://www.npo.nl=%"=="%url%" GOTO Input2
IF NOT "%url:http://www.rtlxl.nl=%"=="%url%" GOTO Input2
IF NOT "%url:http://www.kijk.nl=%"=="%url%" GOTO Input2
IF NOT "%url:http://www.youtube.com=%"=="%url%" GOTO Input2
IF NOT "%url:https://www.youtube.com=%"=="%url%" GOTO Input2
IF NOT "%url:http://youtu.be=%"=="%url%" GOTO Input2
IF NOT "%url:https://youtu.be=%"=="%url%" GOTO Input2
ECHO.
ECHO Ongeldige programma-link.
ECHO.
GOTO Input
:Input2
ECHO.
youtube-dl.exe --no-warnings -F "%url%"
ECHO.
SET "format="
SET /P "format=Voer gewenst formaat in {best}: "
IF "%format%"=="" SET "format=best"
ECHO.
SET /P "task=Video-link achterhalen (J), of Downloaden (N) {J}? "
IF /I "%task%"=="N" GOTO :Download
:: voer youtube-dl uit en kopiëer video-link zonder eol-character naar het klembord
FOR /F %%B IN ('youtube-dl.exe --no-warnings -gf "%format%" "%url%"') DO (
ECHO.
ECHO Video-link:
ECHO %%B
ECHO|SET /P ="%%B"|clip.exe
ECHO.
ECHO Video-link gekopi‰erd naar het klembord.
ECHO.
ECHO.
)
:: ‰ (Alt+0137, ANSI CP-1252) wordt in cmd.exe als ë (Alt+137, OEM CP-437 en CP-850) weergegeven
:: https://en.wikipedia.org/wiki/Code_page_437
:: https://en.wikipedia.org/wiki/Code_page_850
:: https://en.wikipedia.org/wiki/Windows-1252
GOTO Input
:Download
ECHO.
ECHO Doelmap: %~dp0
SET /P "remap=Wijzigen (J/N) {J}? "
IF /I "%remap%"=="N" (
SET "map=%~dp0"
) ELSE (
SET /P "map=Opslaan in: "
)
IF NOT "%map:~-1%"=="\" SET "map=%map%\"
FOR /F "delims==" %%C IN ('youtube-dl.exe --no-warnings --get-filename -f "%format%" "%url%"') DO (
SET "name=%%~nC"
IF /I "%%~xC"==".m4a" SET "ext=.m4a"
IF /I "%%~xC"==".m4v" SET "ext=.mp4"
IF /I "%%~xC"==".m3u8" SET "ext=.mp4"
IF /I "%%~xC"==".wmv" SET "ext=.wmv"
)
ECHO.
ECHO Bestandsnaam: %name%%ext%
SETLOCAL ENABLEDELAYEDEXPANSION
SET /P "rename=Wijzigen (J/N) {J}? "
IF /I "%rename%"=="N" (
SET "filename=%name%%ext%"
) ELSE (
SET /P "rename2=Nieuwe bestandsnaam: "
SET "filename=!rename2!%ext%
)
ECHO.
SET /P "part=Fragment downloaden (J/N) {N}? "
IF /I "%part%"=="J" (
SET /P "ss=Voer begintijd in (in seconden, of in uu:mm:ss[.xxx] vorm): "
SET /P "t=Voer tijdsduur in (in seconden, of in uu:mm:ss[.xxx] vorm): "
ECHO.
FOR /F %%D IN ('youtube-dl.exe --no-warnings -gf "%format%" "%url%"') DO (
ffmpeg.exe -hide_banner -ss "!ss!" -i "%%D" -c copy -bsf:a aac_adtstoasc -t "!t!" "%map%%filename%"
)
) ELSE (
ECHO.
FOR /F %%E IN ('youtube-dl.exe --no-warnings -gf "%format%" "%url%"') DO (
ffmpeg.exe -hide_banner -i "%%E" -c copy -bsf:a aac_adtstoasc "%map%%filename%"
)
)
ENDLOCAL
ECHO.
ECHO.
GOTO Input
:Update
youtube-dl.exe -U
ECHO.
ECHO.
GOTO Input
:Help
ECHO.
ECHO H U L P
ECHO.
GOTO Input

Resources