Page 1 of 1

Asteroid.bat [Primary Release]

Posted: 17 May 2017 18:12
by batnoob
:::::::::::::::::::::::::::::::::::::::::::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

Re: Asteroid.bat [Primary Release]

Posted: 17 May 2017 18:19
by ShadowThief
Speaking of "please comment," comment your code jfc

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

Re: Asteroid.bat [Primary Release]

Posted: 17 May 2017 18:31
by batnoob
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

Re: Asteroid.bat [Primary Release]

Posted: 17 May 2017 18:33
by ShadowThief
How do you know where the goal is?

Re: Asteroid.bat [Primary Release]

Posted: 17 May 2017 18:37
by batnoob
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!=¥"

Re: Asteroid.bat [Primary Release]

Posted: 21 May 2017 21:13
by Aacini
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

Re: Asteroid.bat [Primary Release]

Posted: 11 Jul 2017 11:05
by batnoob
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?

Re: Asteroid.bat [Primary Release]

Posted: 11 Jul 2017 17:53
by batnoob
also, could you give me a link to a topic on this xcopy behavior?

Re: Asteroid.bat [Primary Release]

Posted: 28 Aug 2021 00:58
by Jk123
I want a link of of it also.

Re: Asteroid.bat [Primary Release]

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