Asteroid.bat [Primary Release]

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
batnoob
Posts: 56
Joined: 19 Apr 2017 12:23

Asteroid.bat [Primary Release]

#1 Post by batnoob » 17 May 2017 18:12

:::::::::::::::::::::::::::::::::::::::::::Asteroids.bat:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Code: Select all

@echo off
setlocal EnableDelayedExpansion
set _cls=%5
set _lns=%6
:::: game Function ::::
:11aCreator

set cols=!_cls!
set /a num=%_COLS%/3
set lines=!_lns!
set winPos=%4
if defined %3 (set prev=%3)
set "sx=%1"

set "sy=%2"

set ship=!sx!-!sy!
set "!prev!= "
set /a cls=%cols%+3
set /a lns=%lines%+3
mode con cols=%cls% lines=%lns%
for /l %%a in (1 1 !num!) do (
   %=== declare the positions of the asteroids ===%
   set /a w=!RANDOM! %%!cols!
   set /a h=!RANDOM! %%!lines!
   set /a a=!RANDOM! %%!cols!
   cls
   set "charsp=!w!-!h!"
   set "char=!a!-!w!"
   set "top="
   for /l %%w in (1 1 !_cls!) do (
      set "top=Û!top!"
   )
   
   for /l %%h in (1 1 !_lns!) do (
      for /l %%w in (1 1 !_cls!) do (
         if %%w-%%h==!char! (
            set "%%w-%%h=±"
         ) Else if not defined %%w-%%h (set "%%w-%%h= ")
         set "!charsp!=Û"
         set "!winPos!= "
         if %%w-%%h==!ship! (
            set "%%w-%%h="
         if !ship!==%winPos% (cls&echo You win!!&pause&exit/b 1
         ) Else if !ship!==!charsp! (echo You lose D:&pause&exit/b 1
         ) Else if !ship!==!char! (echo You took damage.&pause&exit/b 0)
         )
      )
   )

)
cls
for /l %%h in (1 1 !_lns!) do (
   if %%h == 1 (echo Û%top%Û)

   set "row="
   for /l %%w in (1 1 !_cls!) do (
      set "row=!row!!%%w-%%h!"
   )
   echo Û!row!Û
)
echo Û!top!Û


:::::::::::::::::::::::::::::::::::::::::::PLAY.bat:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Code: Select all

@echo off
setlocal EnableDelayedExpansion
color 8A
title Asteroid Field
set _COLS=25
set /a _LINS=%_COLS%/2
if not exist Asteroids.bat (
   echo This game requires Asteroids.bat to be in the same folder.
   pause
   exit
)
:menu
mode 100,30
echo      _         ______    _______     _______     ______     _______     ______     ____
echo     /^^\       ^|______^|  ^|__   __^|   ^|^|______^|   ^|  __  ^|   ^|  ___  ^|   ^|__  __^|   ^| __ \
echo    // \\      ^|            ^| ^|      ^|^|          ^| ^|__^| ^|   ^| ^|   ^| ^|      ^|^|      ^|^|  \ \
echo   /=====\     ^|======^|     ^| ^|      ^|^|====      ^|______^|   ^| ^|   ^| ^|      ^|^|      ^|^|  ^| ^|
echo  //     \\     ______^|     ^| ^|      ^|^|______    ^|^|   \\    ^| ^|___^| ^|    __^|^|__    ^|^|__/ /
echo  ^|^|     ^|^|    ^|______^|     ^|_^|      ^|^|______^|   ^|^|    \\   ^|_______^|   ^|______^|   ^|____/       v1.5
echo.
echo  ______________
echo /              \
echo ^|1. Origial    ^|
echo ^|2. Impossible ^|
echo ^|3. Size       ^|
echo ^|              ^|
echo ^|              ^|
echo \______________/
choice /c 123 /n
set coice=%ERRORLEVEL%
if %coice%==2 goto :begin2
if %coice%==3 (set /p "_COLS=Columns: "&goto:menu)
:begin
cls
echo Use WASD keys to move X to exit
set "posX=%_LINS%"
set "posY=%_LINS%"
set /a bord1=%_COLS%-1
set /a bord2=%_LINS%-1
set /a zx=%RANDOM% %%!bord1!
set /a zy=%RANDOM% %%!bord2!
set "posZ=!zx!-!zy!"

timeout -t 02
:game
   if defined posX if defined posY (set prev=!posX!-!posY!)
   Call Asteroids.bat !posX! !posY! !prev! !posZ! !_COLS! !_LINS!
   if %ERRORLEVEL%==1 (goto :menu)
   choice /c WASDXÛ /d Û /t 01>nul
   set mov=%ERRORLEVEL%
   if %mov% EQU 1 (
      call :up
   ) else if %mov% EQU 2 (
      call :left
   ) else if %mov% EQU 3 (
      call :down
   ) else if %mov% EQU 4 (
      call :right
   ) else if %mov% EQU 5 (
      del Board.txt&&exit
   ) else (
      goto :game
   )
goto :game
exit



:begin2
cls
echo Use WASD keys to move X to exit
set "posX=%_LINS%"
set "posY=%_LINS%"
set /a zx=%RANDOM% %%!bord1!
set "posZ=!bord1!-5"
timeout -t 02
:game2
   if defined posX if defined posY (set prev=!posX!-!posY!)
   Call :Asteroids !posX! !posY! !prev! !posZ!
   if %ERRORLEVEL%==1 goto:menu
   choice /c WASDXÛ /d Û /t 01>nul
   set mov=%ERRORLEVEL%
   if %mov% EQU 1 (
      call :up
   ) else if %mov% EQU 2 (
      call :left
   ) else if %mov% EQU 3 (
      call :down
   ) else if %mov% EQU 4 (
      call :right
   ) else if %mov% EQU 5 (
      del Board.txt&&exit
   ) else (
      goto :game2
   )
goto :game2

::::::::::::::::::::::::::::::::::::::FUNCTIONS:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:up
set /a posY=%posY%-1
goto:eof


:left
set /a posX=%posX%-1
goto:eof


:down
set /a posY=%posY%+1
goto:eof


:right
set /a posX=%posX%+1
goto:eof


:::: game Function ::::
setlocal EnableDelayedExpansion
:Asteroids


set cols=%_COLS%
set /a num=%_COLS%/3
set lines=%_LINS%
set winPos=%4
if defined %3 (set prev=%3)
set "sx=%1"

set "sy=%2"

set ship=!sx!-!sy!
set "!prev!= "
set /a cls=%cols%+3
set /a lns=%lines%+3
mode con cols=%cls% lines=%lns%
for /l %%a in (1 1 !num!) do (
   set /a w=!RANDOM! %%!cols!
   set /a h=!RANDOM! %%!lines!
   set /a a=!RANDOM! %%!cols!
   cls
   set "charsp=!w!-!h!"
   set "char=!a!-!w!"
   set "top="
   for /l %%w in (1 1 !_COLS!) do (
      set "top=Û!top!"
   )
   
   for /l %%h in (1 1 !_LINS!) do (
      for /l %%w in (1 1 !_COLS!) do (
         if %%w-%%h==!char! (
            set "%%w-%%h=±"
         ) Else if not defined %%w-%%h (set "%%w-%%h= ")
         set "!charsp!=Û"
         set "!winPos!= "
         if %%w-%%h==!ship! (
            set "%%w-%%h="
         if !ship!==%winPos% (cls&echo You win!!&pause&exit/b 1
         ) Else if !ship!==!charsp! (cls&echo You lose D:&pause&exit/b 1
         ) Else if !ship!==!char! (cls&echo You took damage.&pause&exit/b 0)
         )
      )
   )

)
cls
for /l %%h in (1 1 !_LINS!) do (
   if %%h == 1 (echo Û%top%Û)

   set "row="
   for /l %%w in (1 1 !_COLS!) do (
      set "row=!row!!%%w-%%h!"
   )
   echo Û!row!Û
)
echo Û!top!Û

Please Comment Below

Also, I noticed that if you set the columns too big, then it takes forever to load each time it clears.
I thought i heard dbenham say something about using macros... but i couldn't figure it out.
if anybody could help me, it would be greatly appreciated.

Thanks,
BatNoob
Last edited by batnoob on 18 May 2017 10:27, edited 1 time in total.

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Asteroid.bat [Primary Release]

#2 Post by ShadowThief » 17 May 2017 18:19

Speaking of "please comment," comment your code jfc

The win condition is... landing on a random tile?

batnoob
Posts: 56
Joined: 19 Apr 2017 12:23

Re: Asteroid.bat [Primary Release]

#3 Post by batnoob » 17 May 2017 18:31

ShadowThief wrote:Speaking of "please comment," comment your code jfc

Sorry, i didn't even know about comments until i joined here, and i am still stuck in the habit of running and reading my code to figure out what it does.
ShadowTheif wrote:The win condition is... landing on a random tile?

Yes, the main goal is to avoid the constantly moving asteroids and get to the goal.

BatNoob

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Asteroid.bat [Primary Release]

#4 Post by ShadowThief » 17 May 2017 18:33

How do you know where the goal is?

batnoob
Posts: 56
Joined: 19 Apr 2017 12:23

Re: Asteroid.bat [Primary Release]

#5 Post by batnoob » 17 May 2017 18:37

Ohh... crap i wasn't able to copy/paste the character

Solution:
after pasting the code into your editor, wherever the code says

Code: Select all

set "!winPos!="

just type a character e.g.:

Code: Select all

set "!winPos!=¥"

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Asteroid.bat [Primary Release]

#6 Post by Aacini » 21 May 2017 21:13

Ok. There are *a lot* of modifications that could be done on your code, from changes in the original game concept up to include proven methods that allows a smoother animation.

I don't like the current Asteroids game concept: the fact that the asteroids may appear in random positions in each movement makes the player to lost interest; besides, the method to generate the random asteroids takes too much time (and is entirely incomprehensible to me!)


:arrow: Is totally absurd that a programmer waste its time trying to understand a complex code written by another person just because such a code have not any documentation! You may review the Software Crisis term (coined at end of the 60's) to appreciate the importance of write good software documentation :!:


So I just put your method to create random asteroids in the waste and created another, simpler and much faster one; this method may be easily modified to move the asteroids or other effects. In order to make the game more interesting, I changed the cell-by-cell ship movement by an inertial movement: the WASD control keys activates an acceleration to the ship, so you must be careful to not accelerate it to much; otherwise you will have not enough space to stop it! Several additions may be done to this concept, like limited fuel or time, etc. However, the most important points in the modification of this program are not in the game concept.

The CHOICE method to get input for an animated game is not reliable. The XCOPY method has been extensively tested instead and is used in several animated games, like dbenham's SNAKE.BAT or my Tetris.bat pure Batch file version. I changed your CHOICE /T 1 method by a combination of XCOPY and TIMEOUT /T 1 commands, that gives an equivalent behavior. However, the most important point of use TIMEOUT is not just to have input/output parts one time per second. As explained in this topic, the TIMEOUT command may also be used to move the cursor to screen home! This capability allows to have an animated game with no flicker at all, because it is not neccessary to clear the screen before each screen refresh.

As a matter of fact, I completed all these modifications in your Asteroids game just to test the method to use TIMEOUT command to control an animated game that refresh the screen once every second with no flicker. There is a small disadvantage on this method: in the last line of the screen always appear the "Waiting 1 seconds, ..." TIMEOUT message; however, such a message could be hidden if the screen size is adjusted so the screen buffer have a few lines more than the window buffer. In this way, the screen scrolls up when the TIMEOUT message is displayed, but such a message is hidden below the screen limits when the cursor is moved to Home. This adjustment may even be completed via a small PowerShell code (using $Host.UI.RawUI.WindowsSize and $Host.UI.RawUI.BufferSize values).

I invite you to research and review all the new concepts introduced in this modification of your code before you post simple questions about them. However, if after doing such a research, some parts remain unclear, please post your questions...

Code: Select all

@echo off
setlocal EnableDelayedExpansion

if "%~1" neq "" goto %1

color 0A

:menu
cls
echo     _       ______    _______    _______    ______    _______    ____    ____
echo    /^^\     ^|______^|  ^|__   __^|  ^|^|______^|  ^|  __  ^|  ^|  ___  ^|  ^|_  _^|  ^| __ \
echo   // \\    ^|            ^| ^|     ^|^|         ^| ^|__^| ^|  ^| ^|   ^| ^|    ^|^|    ^|^|  \ \
echo  /=====\   ^|======^|     ^| ^|     ^|^|====     ^|______^|  ^| ^|   ^| ^|    ^|^|    ^|^|  ^| ^|
echo //     \\   ______^|     ^| ^|     ^|^|______   ^|^|   \\   ^| ^|___^| ^|   _^|^|_   ^|^|__/ /
echo ^|^|     ^|^|  ^|______^|     ^|_^|     ^|^|______^|  ^|^|    \\  ^|_______^|  ^|____^|  ^|____/
echo/
echo /---------\
echo ^|1. Play  ^|
echo ^|         ^|
echo ^|         ^|
echo ^|         ^|
echo ^|         ^|
echo \---------/
<nul set/p "=[1]"
pause>nul


rem Field dimensions
set /A cols=50, lines=25

set /A cls=cols+4, lns=lines+8
mode con cols=%cls% lines=%lns%

rem Start the "Timeout" asynchronous module
cd . > Playing
del InTimeout 2>NUL
start "" /B "%~F0" Timeout

rem Start the two parts of the game: Input -> pipeFile.txt -> Main
cd . > pipeFile.txt
"%~F0" Input >> pipeFile.txt  |  "%~F0" Main < pipeFile.txt
ping localhost -n 2 > NUL
del pipeFile.txt
color
cls
goto :EOF



rem :Timeout module use "InTimeout" file to synchronize it with the :Main part

:Timeout
if not exist Playing exit
if exist InTimeout goto Timeout
rem When :Main part delete InTimeout file, it requests a new Timeout cycle
timeout /T 1 /NOBREAK > CON
rem Create InTimeout file as signal to :Main part that the cycle is complete
cd . > InTimeout
goto Timeout



:Input
set "com[W]=Dy=-1"
set "com[A]=Dx=-1"
set "com[S]=Dy=1"
set "com[D]=Dx=1"
set "com[X]=exit=1"

for /L %%# in () do (
   if not exist Playing exit
   set "key="
   for /F "delims=" %%k in ('xcopy /W "%~F0" "%~F0" 2^>NUL') do if not defined key set "key=%%k"
   for /F %%k in ("!key:~-1!") do echo/!com[%%k]!
)
rem exit



:Main

rem Initialize the board
set "topBot="
for /L %%w in (1 1 %cols%) do (
   set "topBot=!topBot!Û"
)
for /L %%h in (1 1 %lines%) do (
   for /L %%w in (1 1 %cols%) do (
      set "%%w-%%h= "
   )
)

rem Insert the asteroids
set "num=25"
for /L %%a in (1 1 %num%) do (
   set /A w=!RANDOM! %% cols, h=!RANDOM! %% lines
   set "!w!-!h!=±"
   set /A w=!RANDOM! %% cols, h=!RANDOM! %% lines
   set "!w!-!h!=Û"
)

rem Insert the ship and base
set /A "posX=cols/2, posY=lines, movX=0, movY=0, move=0"
set "%posX%-%posY%="
set /A "w=!RANDOM! %% cols + 1, h=!RANDOM! %% (lines/3) + 1"
set "winPos=%w%-%h%"
set "!winPos!= "

rem Game animation loop
for /L %%# in () do (

   rem Control module: Change ship speed as requested via keys
   set /A "Dx=Dy=0"
   set "com="
   set /P "com="
   if defined com set /A "!com!, movX+=Dx, movY+=Dy"
   if defined exit del Playing 2>NUL & exit

   set "!posX!-!posY!= "
   set /A "posX+=movX, posY+=movY"
   for /f "tokens=1,2" %%x in ("!posX! !posY!") do (
      if "!%%x-%%y!" equ " " (
         set "%%x-%%y="
      ) else (
         call :WaitForTimeout
         del Playing 2>NUL
         for /L %%i in (4,1,%lns%) do echo/
         if "%%x-%%y" equ "%winPos%" (
            color 0F
            set /P "=You win^!^!" < NUL
         ) else (
            color 0C
            set /P "=You lose D:" < NUL
         )
         echo      Press Enter key to exit...   
         exit
      )
   )

   rem Wait that the cursor be placed at screen Home
   call :WaitForTimeout

   rem Show the board
   echo  Û%topBot%Û
   for /L %%h in (1 1 %lines%) do (
      set "row="
      for /L %%w in (1 1 %cols%) do (
         set "row=!row!!%%w-%%h!"
      )
      echo  Û!row!Û
   )
   echo  Û%topBot%Û
   echo/
   set /A move+=1
   echo   move #!move!:   posX=!posX!,  posY=!posY!,  movX=!movX!,  movY=!movY!   
   rem Previous line have 4 spaces at end of line, until this point:              ^

   rem Request a new Timeout cycle, so the cursor be moved to screen Home
   del InTimeout

)


rem Wait until previous Timeout cycle is completed, that is, until the cursor is placed at Home
:WaitForTimeout
if not exist InTimeout goto WaitForTimeout
exit /B

Antonio

batnoob
Posts: 56
Joined: 19 Apr 2017 12:23

Re: Asteroid.bat [Primary Release]

#7 Post by batnoob » 11 Jul 2017 11:05

So, to be clear, the timeout command moves the cursor to the position of the first character, then writes a new board over the previous one, right?

batnoob
Posts: 56
Joined: 19 Apr 2017 12:23

Re: Asteroid.bat [Primary Release]

#8 Post by batnoob » 11 Jul 2017 17:53

also, could you give me a link to a topic on this xcopy behavior?

Jk123
Posts: 1
Joined: 28 Aug 2021 00:52

Re: Asteroid.bat [Primary Release]

#9 Post by Jk123 » 28 Aug 2021 00:58

I want a link of of it also.

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Asteroid.bat [Primary Release]

#10 Post by Squashman » 28 Aug 2021 12:33

Jk123 wrote:
28 Aug 2021 00:58
I want a link of of it also.
viewtopic.php?f=3&t=5519

Post Reply