Noobish Question - How to set XY Coordinates?

Microsoft Windows
Post Reply
User avatar
MigrationUser
Posts: 336
Joined: 2021-Jul-12, 1:37 pm
Contact:

Noobish Question - How to set XY Coordinates?

Post by MigrationUser »

16 Apr 2013 03:13
Jake123

Well me and my friend are going to program a batch Pokémon game! Exciting right? One problem though. I am trying to figure out how to make the XY Coordinate thingy for the entire area where the character moves in. And also trying to figure out the all important question: how to make the character move on this XY coordinate and when they reach a certain part of it something happens (like a wild pokemon appears). IT would be helpful if someone showed me an example code of this and EXPLAINED each part of it so I understand better. I am still a noob so cut me some slack. Thank you for your help.

----------------------------

#2 18 Apr 2013 16:51
jeb


Simple answer: Batch can't do this.

But you can add this functionality by a small program (google: dostips batch gotoxy).

Or you build the complete screen in variables, clear the screen and print the new screen

----------------------------

#3 18 Apr 2013 23:41
Jake123


Hmmm actually it can do this... almost at least.

Code: Select all

@echo off
setlocal enabledelayedexpansion
:variables
set player=@
set space=
set bound=Û

set /a A=3
set /a B=8

set X!A!Y!B!=!player!

set X1Y9=!bound!
set X1Y8=!bound!
set X1Y7=!bound!
set X1Y6=!bound!
set X1Y5=!bound!
set X1Y4=!bound!
set X1Y3=!bound!
set X1Y2=!bound!
set X1Y1=!bound!
set X2Y1=!bound!
set X3Y1=!bound!
set X4Y1=!bound!
set X5Y1=!bound!
set X5Y2=!bound!
set X5Y3=!bound!
set X5Y4=!bound!
set X5Y5=!bound!
set X5Y6=!bound!
set X5Y7=!bound!
set X5Y8=!bound!
set X5Y9=!bound!
set X4Y9=!bound!
set X3Y9=!bound!
set X2Y9=!bound!
set X1Y9=!bound!

set X2Y8=!space!
set X4Y8=!space!
set X2Y7=!space!
set X3Y7=!space!
set X4Y7=!space!
set X2Y6=!space!
set X3Y6=!space!
set X4Y6=!space!
set X2Y5=!space!
set X3Y5=!space!
set X4Y5=!space!
set X2Y4=!space!
set X3Y4=!space!
set X4Y4=!space!
set X2Y3=!space!
set X3Y3=!space!
set X4Y3=!space!
set X2Y2=!space!
set X3Y2=!space!
set X4Y2=!space!

:game
cls
echo.
echo !X1Y9!!X2Y9!!X3Y9!!X4Y9!!X5Y9!
echo !X1Y8!!X2Y8!!X3Y8!!X4Y8! !X5Y8!
echo !X1Y7!!X2Y7!!X3Y7!!X4Y7! !X5Y7!
echo !X1Y6!!X2Y6!!X3Y6!!X4Y6!!X5Y6!
echo !X1Y5!!X2Y5!!X3Y5!!X4Y5!!X5Y5!
echo !X1Y4!!X2Y4!!X3Y4!!X4Y4!!X5Y4!
echo !X1Y3!!X2Y3!!X3Y3!!X4Y3! !X5Y3!
echo !X1Y2!!X2Y2!!X3Y2!!X4Y2! !X5Y2!
echo !X1Y1!!X2Y1!!X3Y1!!X4Y1!!X5Y1!
echo.
call :movement

:movement
choice /c:wasdl /n
if %errorlevel% equ 1 goto :Y+
if %errorlevel% equ 2 goto :X-
if %errorlevel% equ 3 goto :Y-
if %errorlevel% equ 4 goto :X+
if %errorlevel% equ 5 exit
goto :eof

:Y+
set /a B=!B! + 1
set X!A!Y!B!=!player!
goto game

:X-
set /a A=!A! - 1
set X!A!Y!B!=!player!
goto game

:Y-
set /a B=!B! - 1
set X!A!Y!B!=!player!
goto game

:X+
set /a A=!A! + 1
set X!A!Y!B!=!player!
goto game
That is the code so far. I only have one problem. Whenever the "player" moves the player icon moves yet still stays in the same position. Can someone fix the code a bit for me so this doesn't happen?

----------------------------

#4 19 Apr 2013 07:11
foxidrive


You will run into performance issues, even if you manage to get a block of characters to move on a screen refresh.

A compiled language is probably a better choice, rather than interpreted.

----------------------------

#5 19 Apr 2013 11:18
Jake123


Yeah man but I really want to do this thing with one batch file. It would be a challenge for me. All I need is for someone to fix the code so that the player icon moves without leaving a trail of itself as it moves.

----------------------------

#6 23 Apr 2013 09:05
bluesxman


You aren't blanking the previous location when you move.

For example:

Code: Select all

:Y+
set X!A!Y!B!=!space!
set /a B=!B! + 1
set X!A!Y!B!=!player!
goto game
cmd | *sh | ruby | chef

----------------------------

#7 23 Apr 2013 12:35
Jake123


ok I tried running that through the file and it creates even more problems. It moves the boundary (bound) closer and closer to the player icon until everything is gone and it just reads ECHO IS OFF. Any ideas how to combat this issue?

----------------------------

#8 23 Apr 2013 13:19
bluesxman


At a guess, try changing this line:

set space=

To this:

set "space= "

In fact, I'd recommend using quotes on all "set" commands, thus:

set "variable=sometext"
set /a "expression=x + y"

Last edited by bluesxman (23 Apr 2013 13:21)

cmd | *sh | ruby | chef

----------------------------

#9 23 Apr 2013 13:47
bluesxman


OK I've actually run the code and found a couple of issues.

Below I've addressed (in a slightly dirty fashion) the problem of exceeding the bounds of the play field. I don't actually have "choice" on this PC so I've frigged a way round that with "set /p".

Code: Select all

@echo off
setlocal enabledelayedexpansion
:variables
set player=@
set "space= "
set bound=Û

set /a A=3
set /a B=8

set X!A!Y!B!=!player!

set X1Y9=!bound!
set X1Y8=!bound!
set X1Y7=!bound!
set X1Y6=!bound!
set X1Y5=!bound!
set X1Y4=!bound!
set X1Y3=!bound!
set X1Y2=!bound!
set X1Y1=!bound!
set X2Y1=!bound!
set X3Y1=!bound!
set X4Y1=!bound!
set X5Y1=!bound!
set X5Y2=!bound!
set X5Y3=!bound!
set X5Y4=!bound!
set X5Y5=!bound!
set X5Y6=!bound!
set X5Y7=!bound!
set X5Y8=!bound!
set X5Y9=!bound!
set X4Y9=!bound!
set X3Y9=!bound!
set X2Y9=!bound!
set X1Y9=!bound!

set X2Y8=!space!
set X4Y8=!space!
set X2Y7=!space!
set X3Y7=!space!
set X4Y7=!space!
set X2Y6=!space!
set X3Y6=!space!
set X4Y6=!space!
set X2Y5=!space!
set X3Y5=!space!
set X4Y5=!space!
set X2Y4=!space!
set X3Y4=!space!
set X4Y4=!space!
set X2Y3=!space!
set X3Y3=!space!
set X4Y3=!space!
set X2Y2=!space!
set X3Y2=!space!
set X4Y2=!space!

:game
cls
echo.
echo:!X1Y9!!X2Y9!!X3Y9!!X4Y9!!X5Y9!
echo:!X1Y8!!X2Y8!!X3Y8!!X4Y8!!X5Y8!
echo:!X1Y7!!X2Y7!!X3Y7!!X4Y7!!X5Y7!
echo:!X1Y6!!X2Y6!!X3Y6!!X4Y6!!X5Y6!
echo:!X1Y5!!X2Y5!!X3Y5!!X4Y5!!X5Y5!
echo:!X1Y4!!X2Y4!!X3Y4!!X4Y4!!X5Y4!
echo:!X1Y3!!X2Y3!!X3Y3!!X4Y3!!X5Y3!
echo:!X1Y2!!X2Y2!!X3Y2!!X4Y2!!X5Y2!
echo:!X1Y1!!X2Y1!!X3Y1!!X4Y1!!X5Y1!
echo.
call :movement
goto game

:movement
choice /c:wasdl /n 2>nul
if errorlevel 9009 call :choice w a s d l
if %errorlevel% equ 1 goto :Y+
if %errorlevel% equ 2 goto :X-
if %errorlevel% equ 3 goto :Y-
if %errorlevel% equ 4 goto :X+
if %errorlevel% equ 5 exit
goto :eof

:Y+
set X!A!Y!B!=!space!
set /a B=!B! + 1
if "!X%A%Y%B%!" equ "%bound%" set /a "B-=1" goto game
set X!A!Y!B!=!player!
goto game

:X-
set X!A!Y!B!=!space!
set /a A=!A! - 1
if "!X%A%Y%B%!" equ "%bound%" set /a "A+=1" goto game
set X!A!Y!B!=!player!
goto game

:Y-
set X!A!Y!B!=!space!
set /a B=!B! - 1
if "!X%A%Y%B%!" equ "%bound%" set /a "B+=1" goto game
set X!A!Y!B!=!player!
goto game

:X+
set X!A!Y!B!=!space!
set /a A=!A! + 1
if "!X%A%Y%B%!" equ "%bound%" set /a "A-=1" goto game
set X!A!Y!B!=!player!
goto game

:choice
set "choice="
set /p "choice=>: "
if "%choice%" EQU "%~1" exit /b 1
if "%choice%" EQU "%~2" exit /b 2
if "%choice%" EQU "%~3" exit /b 3
if "%choice%" EQU "%~4" exit /b 4
if "%choice%" EQU "%~5" exit /b 5
exit /b 0
As a general comment, you'd be better off building the play field using a couple of "for /l" commands. And the "movement" logic could quite easily be a single called procedure.

Last edited by bluesxman (23 Apr 2013 13:57)

cmd | *sh | ruby | chef

----------------------------

#10 23 Apr 2013 21:49
Jake123


That is awesome man thanks!

----------------------------

#11 25 Apr 2013 09:35
bluesxman


Made some more modifications.
* The play field can be of arbitrary size (though larger sizes will be quite slow to draw)
* Obstacles appear in random locations (frequency is configurable, higher = fewer; frequency value over 32767 disables them)
* Screen flashes if the player attempts to breach the boundary or step on an obstacle

To be done: drop a bomb to clear obstacles from surrounding cells

I'm getting quite interested in this from a "to see if I can" type perspective :-)

EDIT: Fixed key stroke bug noted by AiroNG -- thanks. I have in mind a better way to configure the key strokes which I'll look at later.
EDIT: Starting location randomised (2013/04/26 bug fixed whereby you could spawn in top or left boundary)

Code: Select all

::
:: http://ss64.org/oldforum/viewtopic.php?id=1688
::

@echo off
title %~nx0
setlocal enabledelayedexpansion
:variables
set "player=@"
set "space= "
set "bound=#"
set "obstacle=+"
set "obstacle.freq=10"

set "width=40"
set "height=20"

REM key stroke set up (for future use)

set "key.w=move up"
set "key.s=move down"
set "key.a=move left"
set "key.d=move right"
set "key.b=bomb" & REM destroy all surrounding obstacles at cost of 4 gold or specific at cost of 1
set "key.l=quit"
set "key.p=panic" & REM warp to a random grid location (not current, not obstacle, not boundary)
set "key.j=jump" & REM jump a number of cells (at cost of gold)

REM == IDEAS ==
REM destroyed obstacles randomly spawns nothing or gold (for buying bombs/jumps)
REM collect randomly spawned dots -- every X collected increments gold
REM health - gold can be booby trapped, maybe?
REM what increases health?  dots?
REM hang on, what's the aim of the game?!

REM random starting location
set /a "A=(%random% %% (%width%  - 2)) + 2"
set /a "B=(%random% %% (%height% - 2)) + 2"

REM set /a A=3
REM set /a B=8

call :init

:game
cls
set location=x!A!y!B!
call :draw
REM set X!A!Y!B!=!player!

call :movement
goto :game

:init
REM sets up the playing field
for /l %%Y in (1,1,%height%) do (
	REM set "line="
	for /l %%X in (1,1,%width%) do (
		set "cell=%space%"
		if %%Y EQU 1        set "cell=%bound%"
		if %%Y EQU %height% set "cell=%bound%"
		if %%X EQU 1        set "cell=%bound%"
		if %%X EQU %width%  set "cell=%bound%"
		if "!cell!" EQU "!space!" (
			set /a "obstacle.mod=!random! %% obstacle.freq"
			REM set obstacle.mod
			if !obstacle.mod! EQU 0 set "cell=%obstacle%"
		)
		if "x%%Xy%%Y" EQU "%location%" set "cell=%player%"
		set "x%%Xy%%Y=!cell!"
	)
	REM echo:!line!
)
goto :EOF

:draw
set "%location%=%player%"
REM draw the playing field
for /l %%Y in (1,1,%height%) do (
	set "line="
	for /l %%X in (1,1,%width%) do (
		set "line=!line!!x%%Xy%%Y!"
	)
	echo:!line!
)

goto :EOF

:movement
set location
set "commands=w a s d b l"
choice /c:%commands: =% /n 2>nul
if errorlevel 9009 call :choice %commands%
if %errorlevel% equ 1 call :move up    & goto :EOF
if %errorlevel% equ 2 call :move left  & goto :EOF
if %errorlevel% equ 3 call :move down  & goto :EOF
if %errorlevel% equ 4 call :move right & goto :EOF
if %errorlevel% equ 5 call :bomb       & goto :EOF
if %errorlevel% equ 6 exit
goto :EOF

:bomb

REM remove obstacles from the 8 surrounding cells
REM -- calulate surrounding 8 cells, turn to space if "+"
REM -- %1 = direction key to bomb 2 cells in that direction only
REM -- bombing has a cost
call :color.cycle 2 "c7 07"
:: TBC

goto :EOF

:move
::echo %0 %*
if "%1" EQU "up" (
	set op=-
	set var=B
)
if "%1" EQU "down" (
	set op=+
	set var=B
)
if "%1" EQU "left" (
	set op=-
	set var=A
)

if "%1" EQU "right" (
	set op=+
	set var=A
)

set A.new=%A%
set B.new=%B%

::set "%var%.new=%var%"
set /a "%var%.new%op%=1"
::set var
::echo %var%=!%var%!
::set %var%.new
::echo:new cell x%A.new%y%B.new% contains [!x%A.new%y%B.new%!]
if "!x%A.new%y%B.new%!" EQU "%space%" (
	set "%var%=!%var%.new!"
	set "x%A%y%B%=%space%"
	set "x!A!y!B!=%player%"
) else (
	call :color.cycle 2 "70 07"
)

set "location=x%A%y%B%"

goto :EOF

:color.cycle

for /l %%i in (1,1,%1) do (
	for %%C in (%~2) do (
		color %%C
		ping 127.1 -n 1 >nul
	)
)

goto :EOF

:choice
REM last movement latches if you don't blank choice
REM set "choice="
set /p "choice=>: "
set count=0
for %%C in (%*) do (
	set /a "count+=1"
	if "%choice%" EQU "%%C" exit /b !count!
)

exit /b 0
Last edited by bluesxman (26 Apr 2013 09:57)

cmd | *sh | ruby | chef

----------------------------

#12 25 Apr 2013 10:05
foxidrive


Nice work.

----------------------------

#13 25 Apr 2013 10:58
AiroNG


You can include Choice on WinXP-Machines, it only works on 32bit Systems however.
I found it here: http://winworldpc.com/library_m2.shtml and it works on my WindowsXP 32bit.
Search for "Microsoft DOS 6.22 (Upgrade) (3.5).7z" in "/Abandonware Operating Systems/PC/DOS/Microsoft/",
unzipp it and get the choice.com from disk1.img. Once that is done simply put it in your windows\ folder

I discovered a small mistake in your code bluesxman
You forgot the "b" in:

Code: Select all

choice /c:wasdl /n 2>nul
So "l" would be "call :bomb" instead of "exit"

I don't suffer from insanity, I enjoy every minute of it.

----------------------------

#14 25 Apr 2013 11:13
bluesxman


Thanks, fixed above.

cmd | *sh | ruby | chef

----------------------------

#15 25 Apr 2013 12:08
bluesxman


Starting location is now randomised (update above).

Last edited by bluesxman (26 Apr 2013 09:58)

cmd | *sh | ruby | chef

----------------------------

#16 29 Apr 2013 06:20
dbenham


bluesxman - I like your :choice solution :)

I've got some significant techniques to dramatically improve performance. My script below can easily handle a 60x40 screen.

1) No need to build each line character by character on every refresh when most of the "pixels" remain constant. Instead, build an array of lines once. Then use SET substring operations to move a character. Only 2 assignments are required to change the value of a pixel. Once a turn is over, simply ECHO the array of modified lines. This change makes a HUGE difference.

2) Much of the logic can be replaced by creative use of variable names and SET /A

3) CALLs are quite slow. Place blocks of logic directly in the main loop instead of using CALL whenever possible.

4) Blocks of code that perform a useful action can be stored in variables as "macros" instead of in CALLed subroutines. There is even a nifty trick to create "macros" that accept arguments. Macros with arguments actually take a bit more code than traditional CALLed routines. But the macros are MUCH faster. See the following DosTips threads for more info about batch macros:

https://www.dostips.com/forum/viewtopic ... lit=macros

https://www.dostips.com/forum/viewtopic ... lit=macros

Here is a complete, functioning game: HUNTER.BAT

There are a number of configurable options near the top of the script. One obvious improvement would be prompts to allow the user to configure the game, without having to edit the file.

There are lots of directions the game could be taken. It has a solid foundation for expansion. A lot more logic could be added and still the game would have decent performance.

Code: Select all

::
:: https://ss64.org/oldforum/viewtopic.php?id=1688
::
@echo off
if "%~1" neq "StartTheGame" (
  cmd /c "%~f0" StartTheGame
  exit /b
)

title %~nx0
setlocal disableDelayedExpansion
cls

::::::::::::::::::::::::::::::::::::::::::::::::
:: User configurable options

set "keyUp=W"
set "keyDown=S"
set "keyLeft=A"
set "keyRight=D"
set "keyBomb=B"
set "keyFire=F"
set "keyHelp=H"
set "keyExit=L"
set "keyPanic=P"
set "keyWait=N"
set "keyWhereAmI=M"

set "width=40"
set "height=20"

set "monsterCount=10"
set "monsterStrength=3"  Value from 1 to 3
set "monsterVision=8"    Value >= 1

set "obstacleFreq=15"    Roughly 1 out of N will be obstacle

set "bombTicks=6"        Value from 2 to 9
set "bombSpread=2"       Reasonable values are 1, 2 or 3

set "boardColor=07"      white on black
set "bombColor=C7"       white on bright red
set "collideColor=0E"    bright yellow on black
set "fireColor=70"       black on white

set "monsterDeathPoints=25"
set "hitMonsterPoints=10"
set "dotPoints=1"
set "penaltyPoints=-1"
set "penaltyTicks=2"     subract penaltyPoints every PenaltyTicks


::::::::::::::::::::::::::::::::::::::::::::::::
:: Define variables

set /a "time=score=0"

set "up=1"
set "left=2"
set "down=3"
set "right=4"
set "bomb=5"
set "fire=6"
set "help=7"
set "exit=8"
set "whereAmI=9"
set "panic=10"
set "wait=11"
set "commands=%keyUp% %keyLeft% %keyDown% %keyRight% %keyBomb% %keyFire% %keyHelp% %keyExit% %keyWhereAmI% %keyPanic% %keyWait%"

set "spinner1=-"
set "spinner2=\"
set "spinner3=|"
set "spinner4=/"
set "spinner= spinner1 spinner2 spinner3 spinner4 "
set "playerDir=%up%"
set "space= "
set "bound=#"
set "obstacle=+"
set "dot=."
set "monster3=M"
set "monster2=N"
set "monster1=O"
set "death=X"
set "empty=%space%"

set "xDiff%up%=+0"
set "xDiff%left%=-1"
set "xDiff%down%=+0"
set "xDiff%right%=+1"

set "yDiff%up%=-1"
set "yDiff%left%=+0"
set "yDiff%down%=+1"
set "yDiff%right%=+0"

set "player%up%=^"
set "player%left%=<"
set "player%down%=v"
set "player%right%=>"

set "bombList="
set "nextBomb=0"

set /a "monsterVision*=monsterVision"


::::::::::::::::::::::::::::::::::::::::::::::::
:: Define macros

::define a Line Feed (newline) string (normally only used as !LF!)
set LF=^


::Above 2 blank lines are required - do not remove

::define a newline with line continuation
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

:: setErr
:::  Sets the ERRORLEVEL to 1
set "setErr=(call)"

:: clrErr
:::  Sets the ERRORLEVEL to 0
set "clrErr=(call )"

:: choice
:::  Gets command input, returns result in errorlevel
2>nul >nul choice /? && (
  set "choice=choice /c:%commands: =% /n >nul"
) || (
  set "choice=call :choice %commands%"
)

:: draw
:::  draws the board
set draw=%\n%
cls%\n%
for /l %%Y in (1,1,%height%) do echo(!line%%Y!%\n%
echo score=!score!   time=!time!

:: test  X  Y  ValueListVar
:::  tests if value at coordinates X,Y is within contents of ValueListVar
set test=%\n%
for %%# in (1 2) do if %%#==2 (for /f "tokens=1-3" %%1 in ("!args!") do (%\n%
  for %%A in ("!x%%1y%%2!") do if "!%%3:%%~A=!" neq "!%%3!" %clrErr% else %setErr%%\n%
)) else set args=

:: plot  X  Y  ValueVar
:::  places contents of ValueVar at coordinates X,Y
set plot=%\n%
for %%# in (1 2) do if %%#==2 (for /f "tokens=1-3" %%1 in ("!args!") do (%\n%
  set "x%%1y%%2=!%%3!"%\n%
  set "part1=!line%%2:~0,%%1!"%\n%
  set "line%%2=!part1:~0,-1!!%%3!!line%%2:~%%1!"%\n%
)) else set args=


::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Define additional variables that require delayed expansion

setlocal enableDelayedExpansion

set "playerClass=!player%up%!!player%down%!!player%left%!!player%right%!"
set "monsterClass=%monster1%%monster2%%monster3%"
set "playerSpace=%space%%dot%"
set "fireSpace=%space%%dot%%playerClass%"
set "bombSpace=%space%%dot%"
set "monsterSpace=%space%%dot%%playerClass%"
set "bombEffect=%dot%%obstacle%%playerClass%%monsterClass%0"

set "nextMonster%monster3%=%monster2%"
set "nextMonster%monster2%=%monster1%"
set "nextMonster%monster1%=%space%"

for /f "tokens=* delims=:." %%L in ('findstr /bl :::. "%~f0"') do @echo(%%L

::::::::::::::::::::::::::::::::::::::::::::::::
:: Initialize the board
<nul set /p "=Initializing."
call :place P player%playerDir%
set "monsterList="
for /l %%N in (1 1 %monsterCount%) do (
  set "monsterList=!monsterList!M%%N "
  call :place M%%N monster%monsterStrength%
  set "M%%NDir="
)
for /l %%Y in (1 1 %height%) do (
  <nul set /p "=."
  set "line%%Y="
  for /l %%X in (1,1,%width%) do (
    if %%Y EQU 1        set "x%%Xy%%Y=%bound%"
    if %%Y EQU %height% set "x%%Xy%%Y=%bound%"
    if %%X EQU 1        set "x%%Xy%%Y=%bound%"
    if %%X EQU %width%  set "x%%Xy%%Y=%bound%"
    if not defined x%%Xy%%Y 2>nul set /a "1/(!random!%%obstacleFreq)" && (
      set "x%%Xy%%Y=%empty%"
    ) || (
      set "x%%Xy%%Y=%obstacle%"
    )
    set "line%%Y=!line%%Y!!x%%Xy%%Y!"
  )
)
echo(
echo(
pause
call :spinner !PX! !PY! player!playerDir!


::::::::::::::::::::::::::::::::::::::::::::::::
:: Main Loop (infinite loop)

for /l %%. in (0 0 2) do (

  %draw%

  %========== player actions =======%
  set "hold="
  %choice%
  for %%C in (!errorlevel!) do (
    if %%C leq %right% (
      if %%C equ !playerDir! (
        %== attempt to move forward in same direction ==%
        set /a "X=PX+xDiff%%C, Y=PY+yDiff%%C"
        (%test% !X! !Y! playerSpace) && (
          %== successfull move ==%
          (%test% !X! !Y! dot) && set /a score+=dotPoints
          %plot% !PX! !PY! space
          set /a "PX=X, PY=Y"
          %plot% !PX! !PY! player%%C
        ) || (
          %== failed move ==%
          call :flash %collideColor%
        )
      ) else (
        %== change direction with no movement ==%
        set "playerDir=%%C"
        set "player=!player%%C!"
        %plot% !PX! !PY! player%%C
      )
    )
    if %%C equ %fire% (
      %== fire a "gun" forward until it hits something ==%
      call :flash %fireColor%
      set /a "X=xDiff!playerDir!, xDiff=X+^!X, xMax=^!^!X*(1+X)/2*width+^!X*PX, Y=yDiff!playerDir!, yDiff=Y+^!Y, yMax=^!^!Y*(1+Y)/2*height+^!Y*PY"
      set "hit="
      for /l %%X in (!PX! !xDiff! !xMax!) do for /l %%Y in (!PY! !yDiff! !yMax!) do (
        if not defined hit (%test% %%X %%Y fireSpace) || (
          %== Hit detected ==%
          set "hit=1"
          (%test% %%X %%Y monsterClass) && (
            %== Hit a monster ==%
            for %%M in (!x%%Xy%%Y!) do set "M=!nextMonster%%M!"
            call :spinner %%X %%Y M
            set /a score+=hitMonsterPoints
          )
        )
      )
    )
    if %%C equ %bomb% (
      %== attempt to place bomb behind player ==%
      set /a "X=PX-xDiff!playerDir!, Y=PY-yDiff!playerDir!"
      (%test% !X! !Y! bombSpace) && (
        %== successful bomb ==%
        set "bombList=!bombList!B!nextBomb! "
        set /a "B!nextBomb!X=X, B!nextBomb!Y=Y, B!nextBomb!Ticks=bombTicks, nextBomb+=1"
      ) || (
        %== failed bomb ==%
        call :flash %collideColor%
      )
    )
    if %%C equ %panic% (
      %== attempt random jump ==%
      set /a "X=(!random!%%(width-2))+2, Y=(!random!%%(height-2))+2"
      (%test% !X! !Y! playerSpace) && (
        %== successfull move ==%
        (%test% !X! !Y! dot) && set /a score+=dotPoints
        %plot% !PX! !PY! space
        set /a "PX=X, PY=Y"
        call :spinner !PX! !PY! player!playerDir!
      ) || (
        %== failed move ==%
        call :flash %collideColor%
      )
    )
    if %%C equ %whereAmI% (
      call :spinner !PX! !PY! player!playerDir!
      set "hold=1"
    )
    if %%C equ %help% (
      cls
      for /f "tokens=* delims=:." %%L in ('findstr /bl :::. "%~f0"') do @echo(%%L
      pause
      set "hold=1"
    )
    if %%C equ %exit% call :exit "You quit :|"
  )

  if not defined hold (

    %========== bomb countdown ========%
    set "boomList="
    for %%B in (!bombList!) do (
      2>nul set /a "%%BTicks-=1, 1/%%BTicks" || (
        set "boomList=!boomList!%%B "
        set "bombList=!bombList:%%B =!"
      )
      %plot% !%%BX! !%%BY! %%BTicks
    )

    %========== bomb explosion ========%
    if defined boomList (
      %draw%
      call :flash %bombColor%
      for %%B in (!boomList!) do (
        set /a "x1=%%BX-%bombSpread%, x2=%%BX+%bombSpread%, y1=%%BY-%bombSpread%, y2=%%BY+%bombSpread%"
        if !x1! lss 1 set "x1=1"
        if !x2! gtr %width% set "x2=%width%
        if !y1! lss 1 set "y1=1"
        if !y2! gtr %height% set "y2=%height%
        for /l %%X in (!x1! 1 !x2!) do for /l %%Y in (!y1! 1 !y2!) do (
          (%test% %%X %%Y bombEffect) && (%plot% %%X %%Y space)
        )
        set "%%BTicks="
        set "%%BX="
        set "%%BY="
      )
    )

    %========== monster actions ========%
    for %%M in (!monsterList!) do (
      (%test% !%%MX! !%%MY! monsterClass) && (
        %== monster is alive ==%
        %== First establish movement direction ==%
        set /a "DX=PX-%%MX, DY=PY-%%MY, DX2=DX*DX, DY2=DY*DY, D=DX2+DY2"
        if !D! leq !monsterVision! (
           %== monster sees player - the chase is on ==%
           if !DX2! equ !DY2! set /a "T=!random!%%2, DX2+=T, DY2+=^!T"
           if !DX2! gtr !DY2! (
             if !DX! lss 0 (set %%MDir=%left%) else (set %%MDir=%right%)
           ) else (
             if !DY! lss 0 (set %%MDir=%up%) else (set %%MDir=%down%)
           )
        ) else (
           %== continue current direction, set random direction if stationary ==%
           if not defined %%MDir set /a "%%MDir=!random! %% 4 + 1"
        )
        %== attempt movement ==%
        set /a "X=%%MX+xDiff!%%MDir!, Y=%%MY+yDiff!%%MDir!"
        (%test% !X! !Y! monsterSpace) && (
          %== successfull move ==%
          for %%A in (x!%%MX!y!%%MY!) do set "M=!%%A!"
          %plot% !%%MX! !%%MY! space
          set /a "%%MX=X, %%MY=Y"
          %plot% !%%MX! !%%MY! M
        ) || (
          %== failed move, clear direction and wait turn ==%
          set "%%MDir="
        )
      ) || (
        %== monster died, place bomb at death site ==%
        set "bombList=!bombList!B!nextBomb! "
        set /a "B!nextBomb!X=%%MX, B!nextBomb!Y=%%MY, B=B!nextBomb!Ticks=bombTicks-1, nextBomb+=1"
        %plot% !%%MX! !%%MY! B
        set "monsterList=!monsterList:%%M =!"
        set /a "score+=monsterDeathPoints"
      )
    )

    %========== player death ========%
    (%test% !PX! !PY! playerClass) || (
      call :spinner !PX! !PY! death
      %draw%
      call :exit "You died :("
    )

    %========== monsters cleared ========%
    if not defined bombList if not defined monsterList (
      call :exit "You slayed the monsters :)"
    )

    set /a "time+=1, score-=^!(time%%%penaltyTicks%)"
  )
)


:choice
set /p "key=>Enter Command (%key%): "
if defined key set "key=!key:~0,1!"
set count=0
for %%C in (%*) do (
  set /a "count+=1"
  if /i "%key%" equ "%%C" exit /b !count!
)
set "key="
%draw%
goto :choice


:place  CoordinatePrefix  ObjectName  ValueVar
set /a "%1X=(!random!%%(width-2))+2, %1Y=(!random!%%(height-2))+2"
(%test% !%1X! !%1Y! space) || goto :place
set "x!%1X!y!%1Y!=!%2!"
exit /b


:spinner  X  Y  ValueVar
for /l %%N in (1 1 5) do for %%C in (%spinner%) do (
  %plot% %1 %2 %%C
  %draw%
  ping 127.1 -n 1 >nul
)
(%plot% %1 %2 %3)
exit /b


:flash  color
for /l %%i in (1,1,2) do (
  for %%C in (%1 %boardColor%) do (
    color %%C
    ping 127.1 -n 1 >nul
  )
)
exit /b


:exit  Message
set "message=%~1"
echo GAME OVER: !message!
pause
cls
echo score=!score!   time=!time!
echo GAME OVER: !message!
exit

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Help text

:::. Characters                       Control Keys
:::.------------------------------   --------------------------------------------
:::. Monster = !monster3! (3 hits left)        Movement: !keyUp! = up
:::.           !monster2! (2 hits left)                  !keyDown! = down
:::.           !monster1! (1 hit left)                   !keyLeft! = left
:::.                                            !keyRight! = right
:::.  Player = !player1! (facing up)                    !keyPanic! = panic (random jump, may fail)
:::.           !player3! (facing down)                  !keyWait! = nothing (sit still)
:::.           !player2! (facing left)
:::.           !player4! (facing right)       Weaponry: !keyBomb! = release bomb to rear
:::.                                            !keyFire! = fire gun forward
:::.  Border = !bound! (permanent)
:::.Obstacle = !obstacle! (can be blown up)       Other: !keyWhereAmI! = where am I
:::.                                            !keyHelp! = help
:::.                                            !keyExit! = quit (leave)
:::. Scoring
:::.------------------------------
:::. Hit monster  = !hitMonsterPoints!
:::. Kill monster = !monsterDeathPoints!
:::. !penaltyTicks! time units = !penaltyPoints!
:::.

Dave Benham

Last edited by dbenham (29 Apr 2013 14:32)

----------------------------

#17 01 May 2013 09:11
npocmaka


:)
very inspirational thread...

----------------------------

#18 14 Jul 2013 19:02
Simon Sheppard


I've edited the title of this thread slightly to make it a bit more descriptive.

Also I have added a new page to SS64.com describing the Batch Macro technique
https://ss64.com/nt/syntax-macros.html
Post Reply