Any DOS Batch game recommendations?
Moderator: DosItHelp
Any DOS Batch game recommendations?
Hello, Nifty here! Been reading DosTips tutorials for a few years now, and DOS Batch was literally the first programming language I ever heard anyone talk about, when I was six or seven years old, though life happened to take an interesting turn several years later and it ended up not being my first programming language (I started with JavaScript), but a year later I hopped back on that DOS train, where I should have started. This year, I became a fan of YouTube Dr. Al, known for his Lands of Death game written entirely in DOS Batch, made in 2016, as well as TheBatchGuy on Itch.io, who has a list of other DOS games on the platform, including a fairly popular game in the DOS community or so I've been told, Batch Town. Now I am about to start programming my own DOS game, The Twenty-Somethings, and I want more games that I can play and even look at the source code for inspiration. Do you recommend any DOS Batch games?
Re: Any DOS Batch game recommendations?
Mmm... I just could talk about the games I wrote by myself:
- 2012/06/20: SNAKE.BAT: Example of basic animated game (at end of
this post) - 2014/06/24: 2048.bat game in color (using auxiliary .exe files).
- 2015/11/27: Tetris game in a pure Batch file
- 2016/04/12: Tetris in color (using Read arrow keys and show color text PowerShell engine)
- 2016/04/24: 2048.bat game (using the PowerShell engine)
- 2018/06/06: VIBORAS.bat: A multi-player version in color of Snake game
Re: Any DOS Batch game recommendations?
These sound great! Nothing against PowerShell, I might even learn PowerShell one day, but I'm sticking to standard Batch for now, but I'm sure some of these games will help. I actually heard about the Snake one on some YouTube post, maybe it was a game demo with a link to this forum, and I think Snake games used to be a common thing in BASIC, so why not DOS? I will probably love this one! I will pass on the PowerShell for now, but it still seems interesting, like something I might look into one day.
-
- Posts: 184
- Joined: 17 Jan 2016 23:55
Re: Any DOS Batch game recommendations?
I also made a version of snake earlier this year.
https://github.com/IcarusLivesHF/Batch- ... main/snake
https://github.com/IcarusLivesHF/Batch- ... main/snake
Re: Any DOS Batch game recommendations?
These are nice! I wonder if there's a website that hosts Batch games from across the web, in the same way there is a website devoted to general text games, and a website devoted to audio games. At first, I thought DosTips itself was this because of the batch files link on the home page, but it's pretty much all tools, no games, I thought for sure that this Snake game, which I had heard of before, would be in there, but I guess they focus on just tools or something.
Re: Any DOS Batch game recommendations?
Oh wow! I'm a lifelong fan of Colossal Cave Adventure! I'm glad to see that someone made a version for DOS, this is so nifty!
-
- Posts: 235
- Joined: 01 Oct 2012 13:32
- Location: Ireland
- Contact:
Re: Any DOS Batch game recommendations?
Hello All! 
This discussion includes variants of Mastermind by Dave Benham, Foxidrive, Aacini, and T3RRY.
And this discussion contains a link to a game called Sokobox by Carlos, which requires his BG utility.
Have fun!
- SB

This discussion includes variants of Mastermind by Dave Benham, Foxidrive, Aacini, and T3RRY.
And this discussion contains a link to a game called Sokobox by Carlos, which requires his BG utility.
Have fun!

- SB
-
- Posts: 184
- Joined: 17 Jan 2016 23:55
-
- Posts: 2
- Joined: 31 May 2025 18:11
Re: Any DOS Batch game recommendations?
I have made a couple of batch games without external exes that have audio and using VT100 sequences so they have colour. Here are some of them:
Rainy Day Teeko : Visual novel where you can play Teeko https://lowsun.itch.io/rainy-day-teeko
neocircuits : Match 3 puzzle game https://lowsun.itch.io/neocircuits
Love, Kyoko : Rogue like game https://lowsun.itch.io/love-kyoko
Prism Song : Platformer https://lowsun.itch.io/prism-song
Dodge Dungeon : Projectile dodging game https://lowsun.itch.io/dodge-dungeon
The one below needs the latest Windows Terminal since it uses Sixel capabilities for real sprites:
Momodora : Lunar Glow
Puzzle platformer based on the Momodora series https://lowsun.itch.io/momodora-lunar-glow
Keep in mind some of them are older, so the code is not very good.
Rainy Day Teeko : Visual novel where you can play Teeko https://lowsun.itch.io/rainy-day-teeko
neocircuits : Match 3 puzzle game https://lowsun.itch.io/neocircuits
Love, Kyoko : Rogue like game https://lowsun.itch.io/love-kyoko
Prism Song : Platformer https://lowsun.itch.io/prism-song
Dodge Dungeon : Projectile dodging game https://lowsun.itch.io/dodge-dungeon
The one below needs the latest Windows Terminal since it uses Sixel capabilities for real sprites:
Momodora : Lunar Glow
Puzzle platformer based on the Momodora series https://lowsun.itch.io/momodora-lunar-glow
Keep in mind some of them are older, so the code is not very good.
Re: Any DOS Batch game recommendations?
feel free to give my stacker game a try.
Code: Select all
===================================
@REM Stacker by T3RRY. Save with utf-8 encoding.
@REM Requires windows 10 v10589 or newer. Some features will not work as intended in Windows Terminal.
===================================
%= Do not modify Thread Launcher =%
@Echo off
(Title )
REM execute target threads
If not "%~1"=="" Goto:%1
Set "ForceQuit="
For /F "Delims=" %%G in ('Where Powershell.exe')Do If not Defined ForceQuit Set "ForceQuit=%%G -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('{TAB}')"
If not defined ForceQuit (
Call:Error 0x01
Exit /b
)
(1>"%~f0:Status" Echo(verify.NTFS) || (
Call:Error 0x04
Exit /b
)
for /F %%a in ('Echo(prompt $E^| cmd')Do Set \E=%%a
Set "fontsize="
CD /D "%~dp0"
:LoadDefaults
(For /F "UsebackQ delims=" %%G in ("%~f0:defaults:$data")Do Set "%%~G") 2> nul || (
( Echo("fontSize=16"
Echo("fontType=Lucida Console"
Echo("s[1]col=1"
Echo("FGcol=255"
Echo("BGi[1]=0"
Echo("BGi[2]=1"
Echo("SPi=2"
Echo("Difficulty=1"
) >"%~f0:defaults:$data"
Goto:LoadDefaults
)
CHCP 65001 > nul
Set "CharSet= *✚✮-+ΦΞ❦•○Δ✸✹✼✾❀❂❈❣✜✟✠✥✪✫✰▄▬▀█░▒▓▲▼►◄┼═╬❤❥♥♦♣♠◙x"
:menu
Call:Setfont %FontSize% "%fontType%"
CLS
Setlocal EnableDelayedExpansion
Echo( [0] Start the game
Echo( [P] Block Color: %\E%[5m%\E%[38;5;%s[1]col%m%s[1]col%%\E%[0m
Echo( [WS] Block Char: "!CharSet:~%SPi%,1!"
Echo( [ED] Background Char1: "!CharSet:~%BGi[1]%,1!"
Echo( [RF] Background Char2: "!CharSet:~%BGi[2]%,1!"
Echo( [C] Background Color: %\E%[5m%\E%[38;5;%FGcol%m%\E%[?12h%FGcol%%\E%[?12l%\E%[0m
Echo( [Z] Change Fontsize: !FontSize!
Echo( [1~9] Difficulty: !Difficulty!%\E%[1E%\E%7
Endlocal
For /F "delims=" %%G in ('%SystemRoot%\System32\Choice.exe /n /C:WPCFR0ZEDS123456789')Do (
If /i "%%G" == "W" Set /A "SPi=SPi %% 48 + 1"
If /i "%%G" == "P" Call:GetInt s[1]col "Block color"
If /i "%%G" == "C" Call:GetInt FGcol "Background color"
If /i "%%G" == "F" If %BGi[2]% GTR 0 Set /A "BGi[2]-=1"
If /i "%%G" == "R" Set /A "BGi[2]=BGi[2] %% 48 + 1"
If /i "%%G" == "0" Goto:Setup
If /i "%%G" == "Z" Set /a "fontsize=fontsize %%30 + 2"
If /i "%%G" == "E" Set /A "BGi[1]=BGi[1] %% 48 + 1"
If /i "%%G" == "D" If %BGi[1]% GTR 0 Set /A "BGi[1]-=1"
If /i "%%G" == "S" If %SPi% GTR 0 Set /A "SPi-=1"
For /f "Delims=WPCFR0ZEDS" %%K in ("%%G") Do Set "Difficulty=%%G"
)
If %fontsize% LSS 10 Set "fontsize=10"
Goto:menu
===================================
EXIT & Rem this line never executed
! Error Handling !
Error:1 Powershell not found in %Path%
Error:2 Xcopy not in C:\Windows\System32
Error:3 No write permission
Error:4 Non NTFS system
===================================
:GameInit %= Define any initialization variables / output pre-loop screen =%
Setlocal EnableDelayedExpansion
REM some math assigned to key array kKEY to handle directional movement.
REM uses divide by zero error to abort movement if it would take the player OOBounds
REM uses -ve & +ve Modulo to adjust Current X/Y index within Bounds.
REM E,W ; A,D ; 4,6
Set "kD="1/(P[1]x-MaxX)","P[1]x=P[1]x %%MaxX + 1""
Set "kA="1/(P[1]x-1)","P[1]x=((P[1]x - MaxX) %%MaxX) + (MaxX-1)""
Set "k6="1/(P[1]x-MaxX)","P[1]x=P[1]x %%MaxX + 1""
Set "k4="1/(P[1]x-1)","P[1]x=((P[1]x - MaxX) %%MaxX) + (MaxX-1)""
REM Initial Delay Interval.
REM If you find this game runs too fast or too slow at Difficulty 1, decrease the value of ControlSpeed.
Set /A "ControlSpeed=100000", "Modifier=controlSpeed/30"
Set /A "BaseDelay=ControlSpeed-(Difficulty*Modifier)"
REM maximum delay interval
Set "MaxDelay=100000"
Set /A "ModuloStep=ControlSpeed / 100"
REM Set "ModuloStep=1250"
REM 'Delay Time' control key definitions.
REM -ve Modulo constrained to 0 lower limit by 1/Basedelay - Divide by zero error halts execution of line.
Set "k-="1/BaseDelay","BaseDelay=((BaseDelay - MaxDelay) %%MaxDelay) + (MaxDelay-ModuloStep)""
REM +ve Modulo constrained to 100000 [ModuloStep offset is to accomadate -ve modulo.]
Set "k+="1/(MaxDelay-ModuloStep-BaseDelay)","BaseDelay=BaseDelay %%(MaxDelay-ModuloStep) + ModuloStep""
REM Field Dims
Set /A "MaxX=30","MaxY=24","oMaxX=MaxX"
mode 31,25
REM initial starting pos
Set /A "P[1]x=MaxX/2","P[1]y=MaxY"
Set "Tail=!CharSet:~%SPi%,1!!CharSet:~%SPi%,1!!CharSet:~%SPi%,1!!CharSet:~%SPi%,1!!CharSet:~%SPi%,1!!CharSet:~%SPi%,1!!CharSet:~%SPi%,1!"
Set "p[1]Sprite=%\E%[^!P[1]y^!;^!P[1]x^!H!\E![5m!\E![48;5;!S[1]col!m!\E![38;5;1m^!Tail^!"
Set "P[1]len=7"
Set "screen=%\E%[38;5;%FGcol%m"
Set "num=0"
for /l %%y in (1,1,%MaxY%) do (
for /l %%x in (1,1,%MaxX%) do (
set /a "num=num %% 2 + 1"
if !num! equ 2 (
Set "screen=!Screen!!CharSet:~%BGi[2]%,1!"
) Else Set "screen=!Screen!!CharSet:~%BGi[1]%,1!"
)
Set "screen=!screen!!LF!"
)
REM Supress Cursor
<nul Set /P "=%\E%[?25l"
Title Place:Space Quit:TAB
REM Example Gameloop
Set /A "MaxX=oMaxX-P[1]len+1"
Set "Tower="
Set "Key=!k6!"
Set "LastKey=!Key!"
2> nul 1> Con (
For /L %%. in ()Do (
%= Read last key press from input buffer without waiting. aka Non blocking input =%
If not "!Lastkey!"=="Pause" If not "!Lastkey!"=="+" If not "!Lastkey!"=="-" Set "LastKey=!Key!"
Set "NewKey="
Set /P "NewKey="
If "!NewKey!"=="4" Set "Newkey="
If "!NewKey!"=="6" Set "Newkey="
If /I "!NewKey!"=="A" Set "Newkey="
If /I "!NewKey!"=="D" Set "Newkey="
If !p[1]y! LSS 1 (
Set "NewKey=quit"
For /L %%i in (-1000000 1 1000000)Do rem game won
%ForceQuit%
Call:cleanup
EXIT
)
If not "!NewKey!"=="" (
If /I "!NewKey:~-4!" == "quit" (
Call:Cleanup
)
If not "!NewKey:{ENTER}!"=="!NewKey!" (
Set "NewKey=!NewKey:~-1!"
)Else Set "NewKey={ENTER}"
For /f "delims=" %%v in ("!NewKey!")Do (
If not "!k%%v!"=="" (
%= assign key array item to key =%
Set "key=!k%%v!"
)
)
)
%= Implement Control actions. =%
If not "!Key!"=="" (
If "!NewKey!"=="+" (
REM Set /A !Key!
Set "Key=!LastKey!"
)Else If "!NewKey!"=="-" (
REM Set /A !Key!
Set "Key=!LastKey!"
)
If "!Key!"=="Pause" (
Set "NewKey="
If not "!LastDropX!"=="" (
Set "oldsprite=%p[1]sprite:[38=[48%"
Set /A "TrimLeft=0","trimRight=0","right1=(p[1]x+p[1]len)","right2=(LastDropX+LastDropLen)"
If !LastDropX! GTR !p[1]X! (
Set /A "TrimLeft=LastDropX-p[1]x","p[1]x=LastDropX","p[1]len-=TrimLeft","MaxX=oMaxX-P[1]len+1"
)Else (
If !right1! GTR !right2! (
Set /A "TrimRight=Right1-Right2","p[1]len-=TrimRight","MaxX=oMaxX-P[1]len+1"
)
)
If !p[1]len! LSS 1 (
<nul Set /p "=!\E![1;1H!screen!!Tower!!oldsprite!%\E%[0m
Echo/|Choice /n
For /L %%i in (-20000 1 20000)Do (Call )
%ForceQuit%
Call:cleanup
EXIT
)
REM Set /A "P[1]len=P[1]len-trimLeft-trimRight"
If not "!Tail!"=="" For /F "delims=" %%i in ("!P[1]len!")Do Set "Tail=!Tail:~-%%i!"
Set "Tower=!Tower!%p[1]Sprite%"
Set /A "LastDropX=p[1]x","LastDropLen=p[1]Len"
)Else (
Set /A "LastDropX=p[1]x","LastDropLen=p[1]Len"
Set "Tower=!Tower!%p[1]Sprite%"
)
Set /A "NewDir=!Random! %% 2",!k-!
If !NewDir! EQU 0 (
Set /A "p[1]y-=1","p[1]x=1"
Set "Key=!k6!"
)Else (
Set /A "p[1]y-=1","p[1]x=MaxX"
Set "Key=!k4!"
)
)
)
%= bounce horizontally =%
If "!key!"=="!k4!" If "!P[1]x!"=="1" Set "key=!k6!"
If "!key!"=="!k6!" If "!P[1]x!"=="!maxX!" Set "key=!k4!"
If not "!key!"=="" Set /A !Key!
<nul Set /p "=!\E![1;1H!screen!!Tower!%P[1]Sprite%%\E%[0m"
Set /A "Delay=baseDelay"
Set /A "Delay=Delay*((MaxX*1000/(MaxY*1000))"
For /L %%i in (1 1 !Delay!)Do rem we go way to fast without a delay
)
)
REM the bellow line should never execute.
EXIT
==========================================================================================================
REM no changes should be made to the below utilities
==========================================================================================================
:Setup
(
Echo("fontSize=%fontSize%"
Echo("fontType=%fontType%"
Echo("s[1]col=%s[1]col%"
Echo("FGcol=%FGcol%"
Echo("BGi[1]=%BGi[1]%"
Echo("BGi[2]=%BGi[2]%"
Echo("SPi=%Spi%"
Echo("Difficulty=%Difficulty%"
) >"%~f0:defaults:$data"
REM Define essential vars for multithreaded controller
REM Signal file that the Controller uses to pass keypress to the game via without blocking execution.
REM - Note - This is modified later to a Lockfile in format: %TEMP%\%~n0_%PID%_Signal.cmd
Set "SignalFile=%TEMP%\%~n0__Signal.cmd"
REM Control Key Definitions
Call :createChars || (
Exit /B 1
)
REM QuitKey must be defined prior to starting Multithreaded controller. TAB is recommended
Set "QUITKEY=%TAB%"
Set "kP=Pause" & Set "Pause=1" & Set "k =Pause"
(Title %~n0)
:GetSession
REM get session ID to prevent File Read / write error if multiple instances running
For /F "Skip=2 tokens=2" %%G in ('Tasklist /fi "windowtitle eq %~n0"')Do Set "Lock=%%G"
CALL Set "SignalFile=%%SignalFile:__=_%Lock%_%%"
For /F "tokens=2 Delims=:" %%G in ('CHCP')Do >"%TEMP%\%~n0_%Lock%_restore.cmd" Echo(@CHCP %%G ^> nul
Del "%SignalFile:Signal=Abort%" 2> nul
CHCP 65001 > nul
Start /Wait /B "" "%~F0" XCOPYCONTROLLER 1>"%SignalFile%" 2> nul | "%~F0" GameInit <"%SignalFile%" 2> nul
REM game has resolved; end script.
DEL "%SignalFile%" 2> nul 1> nul
Endlocal & Goto:Eof
=========================
:createChars
for /f "Delims=" %%e in ('Echo Prompt $E^|cmd') Do Set "\E=%%e"
for /f "delims= " %%T in ('robocopy /L . . /njh /njs' )do set "TAB=%%T"
for /f %%C in ('copy /Z "%~dpf0" nul') do set "CR=%%C"
for /F "delims=#" %%B in ('"prompt #$H# &echo on &for %%b in (1) do rem"') do Set "BS=%%B"
Set "BS=%BS:~0,1%"
del sub.tmp 2> nul
copy nul sub.tmp /a > nul
If not exist sub.tmp (
Call:Error 0x03
Exit /B 1
)
for /F %%a in (sub.tmp) DO (
set "sub=%%a"
)
del sub.tmp
(Set LF=^
)%= Do Not Modify. Linefeed Variable =%
exit /b
:XCOPYCONTROLLER
If not exist %SystemRoot%\System32\Xcopy.exe (
Call:Error 0x02 >"%SignalFile:Signal=Abort%"
<nul Set /P "=quit"
EXIT
)
Setlocal DISABLEdelayedExpansion
REM Environment handling allows use of ! key
For /l %%C in () do (
Set "Key="
for /f "delims=" %%A in ('C:\Windows\System32\xcopy.exe /w "%~f0" "%~f0" 2^>nul') do If not Defined Key (
set "key=%%A"
Setlocal ENABLEdelayedExpansion
set key=^!KEY:~-1!
If "!key!" == "!QUITKEY!" (
>"%SignalFile:Signal=Abort%" Echo(
<nul Set /P "=quit"
EXIT
)
If not "!Key!" == "%BS%" If not "!Key!" == "!CR!" (%= Echo without Linefeed. Allows output of equal and and Space keys =%
1> %~n0txt.tmp (echo(!key!!sub!)
copy %~n0txt.tmp /a %~n0txt2.tmp /b > nul
type %~n0txt2.tmp
del %~n0txt.tmp %~n0txt2.tmp
)Else (
If "!Key!" == "%BS%" <nul Set /p "={BACKSPACE}"
If "!Key!" == "!CR!" <nul Set /p "={ENTER}"
)
Endlocal
)
)
:Cleanup
<Nul Set /P "=%\E%[1;1H%\E%[2J%\E%[?25h%\E%[0mGame over. "
<"%SignalFile:Signal=Abort%" Set /P "XcopyError="
If Defined XcopyError Echo(!XcopyError!
CALL "%TEMP%\%~n0_%Lock%_restore.cmd" > nul
Del %TEMP%\%~n0_%lock%_*.cmd 1> nul 2> nul
(Title )
EXIT
:GetInt <VarName> <"Description Text">
Set "input="
Set /p "input=%\E%8%\E%[32m%\E%[0JEnter a value for %~2: %\E%[0m"
2>nul Set /A "input+=0","1/input" || Goto:GetInt
If %input% LEQ 0 Goto:GetInt
If %input% GTR 255 Goto:GetInt
Set /A "%~1=input"
Exit /b 0
:delTemp
REM this file creates signal files to identify the session and communicate input.
REM If the game is force closed instead of Quit with TAB key
REM the files will persist. To remove them, Call this file from the command line with The argument: deltemp
Del "%TEMP%\%~n0_*_*.cmd"
Goto:Eof
:setFont <integerSize> <stringFontName>
REM from the StdLibrary created by IcarusLives
REM https://github.com/IcarusLivesHF/Windows-Batch-Library/tree/8812670566744d2ee14a9a68a06be333a27488cc
if "%~2" equ "" goto :eof
call :init_setfont
%setFont% %~1 %~2
goto :eof
:init_setfont DON'T CALL
:: - BRIEF -
:: Get or set the console font size and font name.
:: - SYNTAX -
:: %setfont% [fontSize [fontName]]
:: fontSize Size of the font. (Can be 0 to preserve the size.)
:: fontName Name of the font. (Can be omitted to preserve the name.)
:: - EXAMPLES -
:: Output the current console font size and font name:
:: %setfont%
:: Set the console font size to 14 and the font name to Lucida Console:
:: %setfont% 14 Lucida Console
setlocal DisableDelayedExpansion
set setfont=for /l %%# in (1 1 2) do if %%#==2 (^
%=% for /f "tokens=1,2*" %%- in ("? ^^!arg^^!") do endlocal^&powershell.exe -nop -ep Bypass -c ^"Add-Type '^
%===% using System;^
%===% using System.Runtime.InteropServices;^
%===% [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)] public struct FontInfo{^
%=====% public int objSize;^
%=====% public int nFont;^
%=====% public short fontSizeX;^
%=====% public short fontSizeY;^
%=====% public int fontFamily;^
%=====% public int fontWeight;^
%=====% [MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)] public string faceName;}^
%===% public class WApi{^
%=====% [DllImport(\"kernel32.dll\")] public static extern IntPtr CreateFile(string name,int acc,int share,IntPtr sec,int how,int flags,IntPtr tmplt);^
%=====% [DllImport(\"kernel32.dll\")] public static extern void GetCurrentConsoleFontEx(IntPtr hOut,int maxWnd,ref FontInfo info);^
%=====% [DllImport(\"kernel32.dll\")] public static extern void SetCurrentConsoleFontEx(IntPtr hOut,int maxWnd,ref FontInfo info);^
%=====% [DllImport(\"kernel32.dll\")] public static extern void CloseHandle(IntPtr handle);}';^
%=% $hOut=[WApi]::CreateFile('CONOUT$',-1073741824,2,[IntPtr]::Zero,3,0,[IntPtr]::Zero);^
%=% $fInf=New-Object FontInfo;^
%=% $fInf.objSize=84;^
%=% [WApi]::GetCurrentConsoleFontEx($hOut,0,[ref]$fInf);^
%=% If('%%~.'){^
%===% $fInf.nFont=0; $fInf.fontSizeX=0; $fInf.fontFamily=0; $fInf.fontWeight=0;^
%===% If([Int16]'%%~.' -gt 0){$fInf.fontSizeY=[Int16]'%%~.'}^
%===% If('%%~/'){$fInf.faceName='%%~/'}^
%===% [WApi]::SetCurrentConsoleFontEx($hOut,0,[ref]$fInf);}^
%=% Else{(''+$fInf.fontSizeY+' '+$fInf.faceName)}^
%=% [WApi]::CloseHandle($hOut);^") else setlocal EnableDelayedExpansion^&set arg=
endlocal &set "setfont=%setfont%"
if !!# neq # set "setfont=%setfont:^^!=!%"
exit /b
:Error
<nul Set /p "=Error:" & CMD /C Set /A %1
PAUSE
Exit /B