Introduction: Creating a Pixel Screen in Batch

This batch program creates a pixel screen in the CMD window, using variables as pixels, and can be manipulated with input commands to move a cursor, change a pixel or play a game.  This is neat because the CMD line isn't designed to work with pixels or a window-like screen but with lines of text, and though this code won't do anything too extravagant, it's an interesting exercise in scripting and could be useful in scripts with some sort of user interface.

I designed this code about five years ago as a submission to Shadow Ops' Elite Batch Members group, and though that group no longer exists, I think it's still a good bit of work.  I've polished it up and made some modifications to streamline the code, but it was originally designed on Windows XP, so there may be a lot of room for updates.  The program is designed to create a usable space containing a movable cursor, surrounded by a border to keep the cursor from jumping around and to provide a boundary for the screen, but the script can be adapted to look and work however you want.

I'll give you fair warning: this code is pretty intense.  If you're new to CMD scripting you can still run the program, but trying to edit it may prove a nightmare without a good understanding of the batch language.

Step 1: The Program's Anatomy

The program works by echoing a long list of variable onto the CMD line.  Each variable acts as one pixel, and contains a symbol that displays on the screen.  For each pixel you want in a row of pixels, you add another variable to that line, and for each new row you create another line of variables to be echoed under previous one.  This is a simple idea, but the mechanics are complicated because the program has to be able to keep track of the variable and be able to manipulate them.  I have set it up with a cursor-like object that the user can control.  You can move it around and use it to make changes to the contents of the pixel variables.

The program has three main parts.

The first is the main batch program, which controls and maintains the screen's contents and allows you to manipulate the pixels.  This is where the mechanics of the screen lie, and is the script you will have to modify to create a screen for a specific task.  You can label this file whatever you would like.

The second script is the file that structures the pixels on the screen and makes them visible.  This file could easily be incorporated into the main file, but I've found that it's easier to make it a second file in order to set it up properly and modify the program for different-sized screens.  This is the file that contains the lines of pixels.  In my script I have it referenced as "screen.bat," and if you want to rename the file you'll have to change this in the code.

The third file is a short piece of script that allows the program to determine what exists in any particular pixel.  The main program constantly modifies and calls this short program as you input commands.  This is what enables the cursor to move around without disappearing from the screen and to determine the contents of a pixel.  This file will be created automatically when you run the main program.

There is a fourth optional file that allows the screen to work in real time, say for a game.  To move the cursor on the screen, you enter a command and hit enter, and the program runs its loop and moves the cursor, or leaves it be if no recognizable command is given.  This optional file is a VBS file that sends the ENTER command every second or so, sending the program into the loop on its own.  This way the program will keep running, regardless of the commands entered, allowing other elements of the program to continue functioning as you enter or don't enter commands.  This is the script:

set move = CreateObject("WScript.Shell")
wscript.sleep 600
move.sendkeys "{ENTER}"

save it as "move.vbs" and remove "rem" from "rem call move.vbs" in the ScreenLoop section of the code to activate it.

All of these files need to be saved in the same directory.

Step 2: Creating a Screen: Screen.bat

The first thing you need when programming this script is the lines of code that contain the variables that will appear as the screen.

The code will look like this:

echo.
echo  %v1%%v2%%v3%%v4%%v5%%v6%%v7%%v8%%v9%%v10%%v11%%v12%%v13%%v14%%v15%%v16%%v17%%v18%%v19%%v20%%v21%%v22%%v23%%v24%%v25%%v26%%v27%%v28%%v29%%v30%%v31%%v32%%v33%%v34%%v35%%v36%%v37%%v38%%v39%%v40%
echo  %v41%%v42%%v43%%v44%%v45%%v46%%v47%%v48%%v49%%v50%%v51%%v52%%v53%%v54%%v55%%v56%%v57%%v58%%v59%%v60%%v61%%v62%%v63%%v64%%v65%%v66%%v67%%v68%%v69%%v70%%v71%%v72%%v73%%v74%%v75%%v76%%v77%%v78%%v79%%v80%
echo  %v81%%v82%%v83%%v84%%v85%%v86%%v87%%v88%%v89%%v90%%v91%%v92%%v93%%v94%%v95%%v96%%v97%%v98%%v99%%v100%%v101%%v102%%v103%%v104%%v105%%v106%%v107%%v108%%v109%%v110%%v111%%v112%%v113%%v114%%v115%%v116%%v117%%v118%%v119%%v120%
echo  %v121%%v122%%v123%%v124%%v125%%v126%%v127%%v128%%v129%%v130%%v131%%v132%%v133%%v134%%v135%%v136%%v137%%v138%%v139%%v140%%v141%%v142%%v143%%v144%%v145%%v146%%v147%%v148%%v149%%v150%%v151%%v152%%v153%%v154%%v155%%v156%%v157%%v158%%v159%%v160%
echo  %v161%%v162%%v163%%v164%%v165%%v166%%v167%%v168%%v169%%v170%%v171%%v172%%v173%%v174%%v175%%v176%%v177%%v178%%v179%%v180%%v181%%v182%%v183%%v184%%v185%%v186%%v187%%v188%%v189%%v190%%v191%%v192%%v193%%v194%%v195%%v196%%v197%%v198%%v199%%v200%
echo  %v201%%v202%%v203%%v204%%v205%%v206%%v207%%v208%%v209%%v210%%v211%%v212%%v213%%v214%%v215%%v216%%v217%%v218%%v219%%v220%%v221%%v222%%v223%%v224%%v225%%v226%%v227%%v228%%v229%%v230%%v231%%v232%%v233%%v234%%v235%%v236%%v237%%v238%%v239%%v240%
echo  %v241%%v242%%v243%%v244%%v245%%v246%%v247%%v248%%v249%%v250%%v251%%v252%%v253%%v254%%v255%%v256%%v257%%v258%%v259%%v260%%v261%%v262%%v263%%v264%%v265%%v266%%v267%%v268%%v269%%v270%%v271%%v272%%v273%%v274%%v275%%v276%%v277%%v278%%v279%%v280%
echo  %v281%%v282%%v283%%v284%%v285%%v286%%v287%%v288%%v289%%v290%%v291%%v292%%v293%%v294%%v295%%v296%%v297%%v298%%v299%%v300%%v301%%v302%%v303%%v304%%v305%%v306%%v307%%v308%%v309%%v310%%v311%%v312%%v313%%v314%%v315%%v316%%v317%%v318%%v319%%v320%
echo  %v321%%v322%%v323%%v324%%v325%%v326%%v327%%v328%%v329%%v330%%v331%%v332%%v333%%v334%%v335%%v336%%v337%%v338%%v339%%v340%%v341%%v342%%v343%%v344%%v345%%v346%%v347%%v348%%v349%%v350%%v351%%v352%%v353%%v354%%v355%%v356%%v357%%v358%%v359%%v360%
echo  %v361%%v362%%v363%%v364%%v365%%v366%%v367%%v368%%v369%%v370%%v371%%v372%%v373%%v374%%v375%%v376%%v377%%v378%%v379%%v380%%v381%%v382%%v383%%v384%%v385%%v386%%v387%%v388%%v389%%v390%%v391%%v392%%v393%%v394%%v395%%v396%%v397%%v398%%v399%%v400%
echo  %v401%%v402%%v403%%v404%%v405%%v406%%v407%%v408%%v409%%v410%%v411%%v412%%v413%%v414%%v415%%v416%%v417%%v418%%v419%%v420%%v421%%v422%%v423%%v424%%v425%%v426%%v427%%v428%%v429%%v430%%v431%%v432%%v433%%v434%%v435%%v436%%v437%%v438%%v439%%v440%
echo  %v441%%v442%%v443%%v444%%v445%%v446%%v447%%v448%%v449%%v450%%v451%%v452%%v453%%v454%%v455%%v456%%v457%%v458%%v459%%v460%%v461%%v462%%v463%%v464%%v465%%v466%%v467%%v468%%v469%%v470%%v471%%v472%%v473%%v474%%v475%%v476%%v477%%v478%%v479%%v480%
echo  %v481%%v482%%v483%%v484%%v485%%v486%%v487%%v488%%v489%%v490%%v491%%v492%%v493%%v494%%v495%%v496%%v497%%v498%%v499%%v500%%v501%%v502%%v503%%v504%%v505%%v506%%v507%%v508%%v509%%v510%%v511%%v512%%v513%%v514%%v515%%v516%%v517%%v518%%v519%%v520%
echo  %v521%%v522%%v523%%v524%%v525%%v526%%v527%%v528%%v529%%v530%%v531%%v532%%v533%%v534%%v535%%v536%%v537%%v538%%v539%%v540%%v541%%v542%%v543%%v544%%v545%%v546%%v547%%v548%%v549%%v550%%v551%%v552%%v553%%v554%%v555%%v556%%v557%%v558%%v559%%v560%
echo  %v561%%v562%%v563%%v564%%v565%%v566%%v567%%v568%%v569%%v570%%v571%%v572%%v573%%v574%%v575%%v576%%v577%%v578%%v579%%v580%%v581%%v582%%v583%%v584%%v585%%v586%%v587%%v588%%v589%%v590%%v591%%v592%%v593%%v594%%v595%%v596%%v597%%v598%%v599%%v600%
echo  %v601%%v602%%v603%%v604%%v605%%v606%%v607%%v608%%v609%%v610%%v611%%v612%%v613%%v614%%v615%%v616%%v617%%v618%%v619%%v620%%v621%%v622%%v623%%v624%%v625%%v626%%v627%%v628%%v629%%v630%%v631%%v632%%v633%%v634%%v635%%v636%%v637%%v638%%v639%%v640%
echo  %v641%%v642%%v643%%v644%%v645%%v646%%v647%%v648%%v649%%v650%%v651%%v652%%v653%%v654%%v655%%v656%%v657%%v658%%v659%%v660%%v661%%v662%%v663%%v664%%v665%%v666%%v667%%v668%%v669%%v670%%v671%%v672%%v673%%v674%%v675%%v676%%v677%%v678%%v679%%v680%
echo  %v681%%v682%%v683%%v684%%v685%%v686%%v687%%v688%%v689%%v690%%v691%%v692%%v693%%v694%%v695%%v696%%v697%%v698%%v699%%v700%%v701%%v702%%v703%%v704%%v705%%v706%%v707%%v708%%v709%%v710%%v711%%v712%%v713%%v714%%v715%%v716%%v717%%v718%%v719%%v720%
echo  %v721%%v722%%v723%%v724%%v725%%v726%%v727%%v728%%v729%%v730%%v731%%v732%%v733%%v734%%v735%%v736%%v737%%v738%%v739%%v740%%v741%%v742%%v743%%v744%%v745%%v746%%v747%%v748%%v749%%v750%%v751%%v752%%v753%%v754%%v755%%v756%%v757%%v758%%v759%%v760%
echo  %v761%%v762%%v763%%v764%%v765%%v766%%v767%%v768%%v769%%v770%%v771%%v772%%v773%%v774%%v775%%v776%%v777%%v778%%v779%%v780%%v781%%v782%%v783%%v784%%v785%%v786%%v787%%v788%%v789%%v790%%v791%%v792%%v793%%v794%%v795%%v796%%v797%%v798%%v799%%v800%
echo.

This is the code for a screen with twenty rows containing forty pixels, a 40x20 screen.  Paste into Notepad and you'll end up with 22 lines of code.  The first and last create blank lines to create a bit of space around the screen.

The other lines contain a command to echo a string of variables, one after another.  Each of these variables is named "v#," where '#' is a number to designate that particular pixel.  When this code is run, the screen will display the contents of %v1%, followed by %v2%, %v3%, etc, until it comes to the next row.

So for example, if %v1%=H, %v2%=i and %v3%=!, the screen will show "Hi!," followed by the contents of the pixels after.

The numbers allow the program to keep track of what variable contains what, and the v before each variable gives the variable a name that the program can work with, allowing the program to determine what variable it is working with by adding and subtracting numbers while still being able to show the contents of that pixel.  For example, if the program is moving from pixel 43 to pixel 44, it will use addition to move to the new variable and use the variable %v44% to echo the pixel's new content onto the screen.

I've uploaded a copy of this script as a .txt file below.

Step 3: Creating a Screen: Main Program

This is the code for the main script of a 40x20 screen with a cursor:

@echo off
title Screen
color 0a

set/a width=40
set/a height=20
set/a lastlaw=%width% * %height%
set/a bottombarrier=%lastlaw% - %width%
set/a law=0
set/a sidea=%width% +1
set/a sideb=%width% * 2

set marker=O
set barrier=#
set empty=-
set behind=%empty%
set/a place=222
echo.
title Screen %width%x%height%
:LawLoop
if %law%==%lastlaw% goto ObjectPlace
set/a law=%law% +1

if %law% LEQ %width% (
set v%law%=%barrier%
goto LawLoop
)

if %law% GTR %bottombarrier% (
set v%law%=%barrier%
goto LawLoop
)

if %law%==%sidea% (
set v%law%=%barrier%
set/a sidea=%sidea% + %width%
goto LawLoop
)

if %law%==%sideb% (
set v%law%=%barrier%
set/a sideb=%sideb% + %width%
echo  *
goto LawLoop
) else (
set v%law%=%empty%
goto LawLoop
)

:ObjectPlace

set v%place%=%marker%

:ScreenLoop
cls
call screen.bat
set shove=y
rem start move.vbs
set/p shove=    

if %shove%==w (
set shove=-%width%
goto Move
)
if %shove%==s (
set shove=+%width%
goto Move
)
if %shove%==d (
set shove=+1
goto Move
)
if %shove%==a (
set shove=-1
goto Move
)
goto ScreenLoop

:Move
set/a spotcheck=%place% %shove%
set checker=%%v%spotcheck%%%
echo set spotcheck=%checker%>spotcheck.bat
call spotcheck.bat
if %spotcheck%==%barrier% goto ScreenLoop
set v%place%=%behind%
set/a place=%place% %shove%
set v%place%=%marker%
rem if %behind%==%symbol% set behind=%symbol%
set behind=%spotcheck%
goto ScreenLoop


The code is also uploaded as a .txt file below.  Set it up as a batch file in the same directory as screen.bat.

Step 4: Understanding the Code: the General Idea

These next few steps explain how the code works.  I apologize if they read like a textbook, but some of the code is a bit hard to understand.


The purpose of this program is to show a bunch of symbols on the CMD window and keep track of them while being able to manipulate them in response to input.  It's very easy to make a slideshow in batch, by scripting out long pieces of code in which the program echoes symbols on the screen in some sort of picture, clears the screen, and then creates a new image, continuing to create a picture show like "telnet towel.blinkenlights.nl."  The contents won't change, however, and cannot react to input, only showing what they're programmed to show.  This program fixes that.

The program works by setting a bunch of variables with symbols, then displaying them in the CMD window.  The screen has to keep track both of which variable is which and belongs where, enabling the display to be set up and the cursor to move, and of the contents of the variables.

The former is accomplished using a number system.  Each pixel in the screen has a name "v#," with the first pixel in the screen being "v1," the second "v2," and so on.  The program uses the numbers to determine which pixel to make an open space, a barrier or other designation, and to move the cursor around.  The cursor is given a spacial designation (held in the variable %space%) that allows it exist on the screen.  The cursor is seen as a symbol, but the symbol can change under certain conditions, and the numbers tell the program where the cursor is currently.  For example, if %space% is set at 343, then the cursor exists on pixel v343.

The latter is accomplished using symbols.  When you move the cursor, say from the above pixel v343 to v344, one space to the right, the program checks and reacts to the contents of v344.  For example, if v344 contains a barrier, the program will recognize this and so will start the next cycle of ScreenLoop without moving the cursor, and so %place% will stay as 343 and the cursor will stay on pixel v343.  If v344 is empty space, %space% will become 344 and the cursor will move onto v344.  In one of the later steps, I have written code for a game in which you try to kill a monster that is chasing your cursor by laying mines, and the monster goes through the same check/react process: while trying to move from v343 to v344, if v344 contains empty space, it will move; if v344 contains a barrier, it will try to go around it;if v344 contains a mine, it will blow up.

The program also has to be able work with both symbols and numbers at the same time. Numbers are used to determine spacial location, symbols to determine content.  It can't have %space%, and so the cursor, set as v343 and then show the cursor symbol on v265.  The program has to be able to change the symbol inside a pixel, such as changing empty space into the cursor symbol so you know where the cursor is.  It also has to be able to reset pixels as the cursor leaves them: as you move the cursor from v343 to v344, v343 has to go back to displaying empty space, or, as in the case of the game, a mine you've left behind.

Step 5: Understanding the Code: the Setup and LawLoop

The program script has two main sections, LawLoop and ScreenLoop.  The first, LawLoop, is responsible for setting the program up to function.  It designates what symbol means what and the starting values that shape the screen, and then sets all the hundreds of variables to contain their proper symbols.  It looks like this:

@echo off
title Screen
color 0a

set/a width=40
set/a height=20
set/a lastlaw=%width% * %height%
set/a bottombarrier=%lastlaw% - %width%
set/a law=0
set/a sidea=%width% +1
set/a sideb=%width% * 2

set marker=O
set barrier=#
set empty=-
set behind=%empty%
set/a place=222
echo.
title Screen %width%x%height%
:LawLoop
if %law%==%lastlaw% goto ObjectPlace
set/a law=%law% +1

if %law% LEQ %width% (
set v%law%=%barrier%
goto LawLoop
)

if %law% GTR %bottombarrier% (
set v%law%=%barrier%
goto LawLoop
)

if %law%==%sidea% (
set v%law%=%barrier%
set/a sidea=%sidea% + %width%
goto LawLoop
)

if %law%==%sideb% (
set v%law%=%barrier%
set/a sideb=%sideb% + %width%
echo  *
goto LawLoop
) else (
set v%law%=%empty%
goto LawLoop
)

:ObjectPlace

set v%place%=%marker%


The first part is responsible for designating the meaning of the symbols and the starting values of %sidea%, %sideb%, %place% and %law%.

set/a width=40
set/a height=20
set/a lastlaw=%width% * %height%
set/a bottombarrier=%lastlaw% - %width%
set/a law=0
set/a sidea=%width% +1
set/a sideb=%width% * 2

set marker=O
set barrier=#
set empty=-
set behind=%empty%
set/a place=222
echo.

Throughout the script, symbols are designated by variables.  The cursor is %marker%, and as I've written it, %marker%=O.  Later in the code, when you move from v343 to v344 and the program has to set v344 with to display O, the cursor symbol, it does so using

set v344=%marker%

Since %marker%=O, %v344% will also contain O.  I do this so that if you want to change the symbol for a particular function, for example, to use @ to show the cursor instead of O, you only have to change O to @ in this top piece of code rather than hunt through the script for every line that deals with the cursor.

*Note: the program cannot comprehend a space (spacebar) as a symbol.  If you use one, the program will crash.  I use "-" instead, and it makes the screen easy to read.

Another important feature of this part of the code is the %width% and %height% variables, which contain, derp, the width and height of the screen and are used through the entire program to set up the screen and move the cursor.


LawLoop is main piece of the setup phase.  Its job is to take every pixel variable on the screen, from %v1% to %v800% for our 40x20 screen, and set it with the appropriate symbol.  It does this based on the number of the variable, which is why all the pixels are named "v#."  %law% starts at 0 and counts up, making the first variable v1.  The code works like this:

set v%law%=%symbol%

At the start, %law% equals 1, so this line really says

set v1=%symbol%

with %symbol% being whatever symbol the if/then conditions call for.  After setting v1, the code loops and adds 1 to %law%.  Now %law%=2 and the code reads

set v2=%symbol%

%law% continues to count up until it reaches the last variable, v800 for 40x20, at which point the code jumps to ScreenLoop and begins to run.


What the screen looks like once set up depends on if/then statements.  The program uses the %law% numbers to determine what pixel should contain what.  There are two sections of this. the main LawLoop and ObjectPlace.

:LawLoop
if %law%==%lastlaw% goto ObjectPlace
set/a law=%law% +1

if %law% LEQ %width% (
set v%law%=%barrier%
goto LawLoop
)

if %law% GTR %bottombarrier% (
set v%law%=%barrier%
goto LawLoop
)

if %law%==%sidea% (
set v%law%=%barrier%
set/a sidea=%sidea% + %width%
goto LawLoop
)

if %law%==%sideb% (
set v%law%=%barrier%
set/a sideb=%sideb% + %width%
echo  *
goto LawLoop
) else (
set v%law%=%empty%
goto LawLoop
)

LawLoop is designed to create the basics of the screen: a boundary of barrier symbols surrounding empty space.  It has four main pieces of code the keep track of building the barrier segments around the border using the %law% variable and if/then statements.  The first two create the top and bottom barriers by setting barriers in every variable with a %law% number that places it on the top or bottom line of the screen.  For our 40x20 screen, the top line is made up of the pixels with %law% numbers 1-40 (40 variable per line) and the bottom of numbers 761-800, so the program uses 

if %law% LEQ %width%

and

if %law% GTR %bottombarrier%

to set a barrier on pixels in the top and bottom line of the screen.

The side barriers are created using the %sidea% and %sideb% variables.  %sidea% controls the lefthand side and is originally set at the %law% number of the fist variable on the second line (the first line has been taken care of with the LEQ statement).  When %law% equals %sidea%, the program sets that first pixel as a barrier, then adds 40 to %sidea% so that as %law% increases it will set the first pixel of the third line as a barrier, after which another 40 is added to %sidea% for the first pixel of the fourth line, and so on until the %law% number places a variable in the last line of the screen, at which point the GTR statement takes over.  %sideb% works the same way, designating the last pixel on each line as a barrier and creating the righthand boundary.


The last part of the setup is ObjectPlace, which sets variables to contain symbols for the cursor and any other initial conditions.

:ObjectPlace
set v%place%=%marker%

This line sets whatever pixel has the %law% number equal to the value of %space%, the spatial location of the cursor, with the symbol designating the cursor.  You have to program this part of the code yourself, using statements like this to create an environment on the screen, such as barriers in the middle of the screen.  For something like the game later on, you could create several different batch files with lists of conditions to create different levels and use "call level1.bat" to setup the level.

Step 6: Understanding the Code: Program Mechanics and Spotcheck

Once LawLoop has finished, all the pixels in the screen contain symbols and the program enters ScreenLoop, where it echoes the pixels onto the screen and waits for input:

:ScreenLoop
cls
call screen.bat
set shove=y
rem start move.vbs
set/p shove=    

if %shove%==w (
set shove=-%width%
goto Move
)
if %shove%==s (
set shove=+%width%
goto Move
)
if %shove%==d (
set shove=+1
goto Move
)
if %shove%==a (
set shove=-1
goto Move
)
goto ScreenLoop

:Move
set/a spotcheck=%place% %shove%
set checker=%%v%spotcheck%%%
echo set spotcheck=%checker%>spotcheck.bat
call spotcheck.bat
if %spotcheck%==%barrier% goto ScreenLoop
set v%place%=%behind%
set/a place=%place% %shove%
set v%place%=%marker%
rem if %behind%==%symbol% set behind=%symbol%
set behind=%spotcheck%
goto ScreenLoop


Again, there are two sections, the main ScreenLoop section and Move.

ScreenLoop is fairly simple.  Each time it runs, it clears the screen and refreshes the image created by the pixels, showing any changes in the variables.  The loop then designates a new variable, %shove%, for input.  the keys 'w', 's', 'a', and 'd' are used as arrow keys, and determine which section of the code the program goes to.

The four pieces of code that ScreenLoop links to are used to set variables that the program uses to determine what variable to check the contents of, to change the %space% cursor location, and to change the symbol in both the pixel being moved onto and the pixel being left.  The variable %shove% is reset to contain piece of code to be used to change the %place% variable in the Move section of the code.  It becomes +/- 1 if the cursor is moved left or right, and +/- %width% (+/-40 for our 40x20 screen) if the cursor is moved up or down.


The Move section is the bit of code that allows the program to react to the contents of the variables, and this is where the %law% numbers of the pixels come into play with the symbols, as well as the part of the code that makes use of the third file, spotcheck.bat.

Move also has two sections.  The first is the script that checks the value of the pixel that the cursor is trying to move onto.

:Move
set/a spotcheck=%place% %shove%
set checker=%%v%spotcheck%%%
echo set spotcheck=%checker%>spotcheck.bat
call spotcheck.bat
if %spotcheck%==%barrier% goto ScreenLoop

There are several steps in this process.  Firstly, the program sets %spotcheck% by taking %place%, the %law% number of the pixel containing the cursor, and adds or subtracts %width% or 1, based on the values set for %shove% from the command entered, to designate the %law% number of the pixel the cursor is trying to move onto.  For example, if we are on v343 and moving onto v344, the program will take %place%, which is 343, and add 1 (since we're moving to the right) to get a %law% number of 344, which designates the pixel v344.

Now that the program knows the number of the pixel to check, it has to check the value of pixel v344.  This is a difficult task technically because we need to know the value of pixel v344, which is a batch variable %v344%, but the computer only knows the number of the pixel through %spotcheck% but needs the full name %v344%.  This is a problem because the program would have to check the contents of a variable that is designated by a variable, and you'd end up with

if %v%spotcheck%%==%symbol%

with %spotcheck% being the %law% number of the pixel we're checking.  The computer can't make any sense of this, so we have to do a little bit of alchemy on the code.  We do this with a second variable, %checker%:

set checker=%%v%spotcheck%%%

This line sets %checker% equal to the text "%v#%," where "#" is the %law% value of the pixel we're moving onto.  If we're still going from v343 to v344, then %checker% will contain the text "%v344%," which is not a value that the program can use at present, but which is a piece of code that the computer recognizes: the variable %v344% is the pixel whose value the program needs to identify.  Now we just need to put this piece of script into a line of code the computer can use to check the pixel's contents.

This is where spotcheck.bat comes in:

echo set spotcheck=%checker%>spotcheck.bat
call spotcheck.bat

These lines export the text "set spotcheck=%checker%" to spotcheck.bat.  Remember, %checker% now contains the text "%v344%," so the line of text that is exported to the new .bat file reads

set spotcheck=%v344%

which is a usable CMD line.  After exporting this line of text, the program then calls spotcheck.bat and runs that line of script, and suddenly %spotcheck% contains the same symbol as the pixel v344, and can be tested with an if/then code.

You can program this to check for any symbol you want and create any value you want; in the game later on, if the monster moves onto a pixel containing a mine, it loses a life.  There is only one thing that this script inherently checks for, however, and that is a barrier:

if %spotcheck%==%barrier% goto ScreenLoop

If pixel v344 does contain a barrier, then the program does not move the cursor but goes back to ScreenLoop to receive another command.

If there is no obstacle to movement, then the program runs the following lines, the second half of Move, in order to move the cursor into the new pixel:

set v%place%=%empty%
set/a place=%place% %compasssymbol%%compassamount%
set v%place%=%marker%
rem if %behind%==%symbol% set behind=%symbol%
set behind=%spotcheck%
goto ScreenLoop

The first line resets the symbol for the pixel you are currently on.  It does this by setting v%place%, your current pixel variable, equal to %behind%, which was the content of that pixel before you moved onto it (when the program starts, %behind% is set to equal %space%, or any other symbol you want to exist in the starting pixel).  Now the next time ScreenLoop runs and the screen refreshes, the pixel you left will show the content that was there before instead of the cursor symbol.

Next comes the actual move.  The program takes %place%, the variable that contains the number of the pixel designated as the cursor, and adds or subtracts 1 or %width% based on the value of %amount%.  Now %place% is the number of a pixel above, below, right or left of the one we just left.  %place% was equal to 343; now it equals 344.  The cursor has a new location.

The last step is to make this new pixel display the cursor symbol.  This is simple:

set v%place%=%marker%

Now the pixel v#, or v344 in our example, contains the symbol for the cursor, and will show it when echoed on the screen.


There is one final thing that needs done: we need a new %behind% value so that this new pixel can reset when we move off of it.  To do this, we just set %behind% equal to %spotcheck%, which is still set to the symbol of the pixel before we moved onto it.  Say pixel v344 was equal to the letter 'F': when the program checked v344's contents to see if it could move there, it set %spotcheck% equal to F in order to run if/then statements, and now %behind% will set itself equal to F.  Now, when we leave v344 the pixel will be set to display the symbol it showed before we moved onto it.  There is also a line of code that would allow you to change the pixel as you leave it.  Remove "rem" from the line and the script will reset the pixel to a new symbol based on an if/then statement (if pixel was F, leave it as G).  You could also link this to a command in ScreenLoop:

if %shove%==%command% set behind=%symbol%


Once %behind% is set, the move is complete and ScreenLoop repeats.

Step 7: Creating Screens With Different Dimensions: Using Screenbuilder

You may want to create a screen other than the basic 40x20 we've been using.

The first thing you need to create a pixel screen is the code to display the pixels.  Rather than type out all the variables for each line of the screen, I wrote a program to do it for me.  Run the following script as a batch file:

@echo off
title Screenbuilder
color 08
echo.
set/p x=   Units across:
echo.
set/p y=     Units down:
title Building Screen (%x% by %y%)
set/a xcount=0
set/a ycount=0
set/a num=0
set write=
color 0c
:Loop
set/a num=%num% +1
set/a xcount=%xcount% +1
set write=%write%v%num%
echo %write%

if %xcount%==%x% (
echo echo  %write%>>newscreen.bat
set write=
set/a xcount=0
set/a ycount=%ycount% +1
)
if %ycount%==%y% (
cls
color 0a
echo.
echo.
echo     Open newscreen.bat in NotePad. Go to Edit\Replace and replace all v's
echo    with two percent signs followed by a v. Delete one % from the beginning
echo    of each line, and add one to the end.
echo.
pause
exit
)
goto Loop

When you run this file, it will ask you how many units across and how many units down to build the screen.  Enter the number of pixels across and down, then hit enter.  The screen will flash a bunch of numbers, then a new batch file will appear in the same directory as Screenbuilder, named "newscreen.bat."

When the program is finished constructing the screen, it will show a message telling you how to make the screen functional.  In order to make newscreen.bat usable as a pixel screen, you have to edit it slightly.  Open it with NotePad and click on Replace under the Edit tab.  Type "v" into the first box, and "%%V" into the second, the click "Replace All".  When NotePad is finished, you will have variables.  You want a list of variables that read "%v#%, so to complete the screen, delete one of the %'s at the beginning of each line (there will be two after the echo command), and then add one to the end of each line.  You can also add "echo." as many times as you want before and after the variables to create blank lines.  Just keep in mind that the more lines your screen has, the more lag there will be when ScreenLoop refreshes the images.  Rename "newscreen.bat" "screen.bat," and the screen is ready to work.

The code for ScreenBuilder is also uploaded below.

Step 8: Creating Screens With Different Dimensions: Modifying the Main Script

Now that you have a screen with new dimensions, you need to modify the numbers in the main script if you want everything to function properly.  This is wonderfully easy.  Go to the beginning of the script:

@echo off
title Screen
color 0a

set/a width=40
set/a height=20

Change the values for width and height.  With our 60x10 screen, the code will read

set/a width=60
set/a height=10

That's all you have to do as long as screen.bat is set up properly.  You could even program the script to switch between different size screens by changing the values for height and width through commands or if/then statements and calling different versions of  screen.bat in ScreenLoop.

Step 9: MineLayer and the Original Code

I've mentioned the game I created several times throughout this 'ible, and I've uploaded the code below.  I won't pretend it's very entertaining, but it does have some interesting code in terms of changing the contents of pixels and modifying the script in order to incorporate other commands and routines, and it is pretty cool to watch the little monster chase you after programming it yourself.  It is also an antique, as I haven't updated it like the script I've used throughout this instructable.  I've also uploaded the original script I used years ago for a 60x20 screen, and between the two you can see what it originally looked like.  The third file, Paint, is the script for the screen in the intro picture; enter the command "j" and then enter whatever symbol you'd like to appear in the pixel before moving the cursor.

Hopefully you'll find this code useful.