Remarks: Maze Walker

From Maze

Revision as of 18:56, 29 July 2011 by MichaelMateas (Talk | contribs)
Jump to: navigation, search

The abstract visual pattern produced by 10 PRINT can be appreciated purely for its formal, compositional qualities, like an abstract painting or a fabric pattern. [reference other sections of the book that discuss 10 PRINT as a formal pattern]. However, as has been discussed in [reference to section/chapter on cultural history of mazes and 10 PRINT's location and context within this history], the 10 PRINT pattern can also be interpreted as a maze. In this chapter, we investigate how it is that 10 PRINT, as an abstract machine, succeeds in representing a maze or labyrinth. More specifically, we employ our software studies methodology of writing programs to interpret programs, writing a series of hermeneutic probes in Commodore BASIC that employ representational machinery of increasing complexity to ever more elaborately cash out the interpretation of the 10 PRINT pattern as a maze.

The first step in this process is to stabilize the pattern so that it can be contemplated as a fixed maze. Throughout this book we have shown figures of static rectangular patterns produced by 10 PRINT [reference to a figure depicting such a pattern]. But this is not what someone running 10 PRINT on a Commodore 64 experiences; rather than a fixed maze, 10 PRINT produces an endlessly scrolling sequence of symbols. Figure [fig] shows a sequence of screen shots as 10 PRINT executes. As the program starts executing, a growing line of symbols starts printing out below the typed command RUN 10, continuing in the first column of the next line as each line becomes full. When the line at the bottom of the screen fills with symbols, the screen begins scrolling, moving all lines up by one on the screen, pushing the line at the top off the screen. The bottom line of the screen is blank after this scroll operation, and the bottom line again refills with symbols. Eventually, any text that was on the screen above the RUN 10 command has been pushed off the screen. At this point, when the bottom line fills with symbols, the screen scrolls upwards by two lines instead of one, pushing the top two lines of the pattern off the top of the screen, and creating two blank lines at the bottom of the screen (this apparently anomalous scrolling behavior is explained below). From this point on, the two blank lines are continuously filled with randomly selected symbols, scrolling by two when the bottom line fills. Only for the fraction of a second when a line has filled, and before the first symbol of the next line is drawn, is there ever a rectangular maze pattern present on the screen. And not even for that fraction of second is there ever a maze pattern filling the whole screen, as the pattern immediately scrolls up by two lines when the symbol in the last row and column is drawn.

To draw a fixed rectangular maze pattern, 10 PRINT must be modified to draw a finite number of symbols, rather than an infinite sequence. Instead of repeating the PRINT statement forever (which the GOTO statement does), we should repeat the PRINT statement a fixed number of times. How many symbols should be drawn? To avoid the extra complexity of having to format maze rows that are narrower than the width of the screen (by either centering the maze pattern by padding each line with blank spaces on each side of the maze pattern, or by having to explicitly terminate each maze line if not centering), consider only rectangular mazes that are as wide as the entire screen. Forty text symbols (characters or graphic symbols) can fit on one line of the C64 screen. Therefore, any rectangular pattern will consist of a multiple of 40 symbols. To make this concrete, consider a modified version of 10 PRINT that will create a rectangular pattern 10 lines high; it will consist of 10 x 40 = 400 maze symbols.

Now 10 PRINT must be modified to execute the PRINT statement 400 times. One way would be to write the following 400 line program:

1 PRINT CHR$(205.5 + RND(1));
2 PRINT CHR$(205.5 + RND(1));
…
400 PRINT CHR$(205.5 + RND(1));

There are, however, significant problems with writing the program this way. For one thing, the program is long; the programmer must engage in the repetitive task of writing the same line over and over again (changing the line numbers). Computers are good at repetition; whenever a program involves tedious and repetitive steps, programmers look for ways to make the computer do the repetitive work. More significantly, this version of the program is very hard to change. To create a longer sequence of 600 symbols, 200 more lines must be added to the program. To create a shorter sequence of 100 symbols, 300 lines must be deleted from the program. To create a pattern of two different symbols, or to change the relative frequency with which the two symbols appear, the number 205.5 must be changed in every line. Clearly the best way to write this program is to write the PRINT line once and have the computer execute the line 400 times. The program must somehow count to 400, so that it can keep track of how many times it has executed the PRINT line and stop after 400 times. The following program does this, introducing the FOR NEXT construct in BASIC.

5 FOR X = 1 to 400
10 PRINT CHR$(205.5 + RND(1));
15 NEXT X

The purpose of the FOR NEXT construct is to repeatedly execute lines (to loop over them) a fixed number of times. The lines to loop over are placed between the line with the FOR statement and the line with NEXT statement. In this case there is only one line between FOR and NEXT - the PRINT line that randomly prints one of two symbols to the screen. The FOR statement specifies a starting and ending number to count between, as well as a variable to hold the count. In this case, the count starts at 1 and ends at 400 (thus looping 400 times), and specifies a variable named X to store the count. [Not sure if we'll need to go into the concept of a variable in more detail - hopefully the concept of a variable has been introduced elsewhere]. The NEXT statement increments the counting variable, in this case, X. If the value of the count variable (X) is less than or equal to the maximum count specified in the FOR statement, control returns to the line after the FOR (in this case line 10 with the PRINT statement) and execution continues, looping one more time over the lines between FOR and NEXT. Otherwise, if the value of the count variable (X) is greater than the maximum count, execution continues on the line after the NEXT statement - the loop is done. In this case, since there is no program line after the NEXT statement, the program terminates. By utilizing the FOR NEXT looping construct, this very short program produces the desired rectangular pattern of 400 symbols, producing the first screen pattern that can be stably contemplated as a maze. [Reference screen image showing 10 line maze pattern followed by READY. and blinking cursor.]

It is interesting to note that in this program no use is made in the PRINT statement of the counting variable X. This counting variable is employed only by the FOR and NEXT statements to keep track of how many iterations have occurred. This involves repeatedly testing the current value of X against the maximum value to decide whether to increment the count and loop one more time or to leave the loop. This increment and test logic is performed by the BASIC interpreter, in its implementation of the semantics of FOR and NEXT. A BASIC program can also reference the count value in the lines appearing between the FOR and NEXT statements, though the maze program does not do this.

The increment and test logic, which is implemented within the interpreter, can also be implemented directly in BASIC. This makes fully explicit the work that the counting variable X is performing in our program.

This program loops from 1 to 10, doing nothing but maintaining the count through each iteration:

10 FOR X = 1 TO 10
20 NEXT X

This is the equivalent BASIC program where the initialization, incrementing and testing of the count variable is made explicit, without using the FOR and NEXT statements:

10 LET X = 1
20 IF X > 10 THEN GOTO 50
30 LET X = X + 1
40 GOTO 20
50 END

The rectangular maze, though now a stabilized pattern, still does not appear on the screen by itself. The space above the maze contains whatever characters were already on the screen above the prompt where the RUN command was typed, while the space below the maze contains the READY prompt [reference figure above showing the 10 line rectangular maze]. Clearing the screen and moving the active print location to the top of the screen before printing the maze would eliminate stray characters appearing above the maze. The C64 keyboard has a special key, named CLR, which clears the screen. By printing this special CLR character within our program, we can clear the screen before printing the maze characters. [If the chapter on the C64 and BASIC don't talk about control characters, say more about control characters here]. There are two ways to refer to any keyboard character within a program: either by pushing the appropriate keyboard key within quotes, or using the character code with the CHR$ function. The control characters all have a visual counterpart for use within quoted strings. The CLR key can thus be referred to within a program by either "[CLR symbol]" or by CHR$(147). Printing this character clears the screen.

The program:

1 PRINT CHR$(147);
5 FOR X = 1 TO 400
10 PRINT CHR$(205.5 + RND(1));
15 NEXT X

now generates a rectangular maze, 10 lines high, with the READY prompt appearing below the maze. The semicolon on the first line tells the PRINT statement not to start a new line after printing the CLR character. Without the semicolon, there would be one blank line above the maze, resulting from the PRINT on line 1 starting a new line. The READY prompt is generated by BASIC when a program terminates. In our case, after the FOR and NEXT statements increment X to 401, program execution continues past line 15, terminating the program and returning control of the C64 to the BASIC operating environment. In order to prevent the READY prompt from being printed, control must not return to BASIC; the maze program must execute forever. The original 10-print program already demonstrated how to use a GOTO statement to make a program loop forever. Now, however, we don't want the maze program to keep on printing forever, but rather to do nothing forever, so as not to return control to the BASIC operating environment and the resulting printing of the READY prompt. This is accomplished by including a line at the end of the program with a GOTO statement that loops to itself.

1 PRINT CHR$(147);
5 FOR X = 1 TO 400
10 PRINT CHR$(205.5 + RND(1));
15 NEXT X
20 GOTO 20

This finally results in the generation of a pristine rectangular maze sitting on a screen by itself [reference figure depicting clean maze]. The next step is to fill the entire screen with a stabilized maze pattern.

Before moving onto this step, however, let us reflect on the additional complexity that has been introduced in our efforts to stabilize the maze. Our original one line program has grown to five lines, though the original kernel of the program, which randomly prints a forward or backward slanting character, still appears on line 10. The additional complexity comes from the need to produce a finite number of forward and back slashes, and from the formatting requirements of placing the maze on a blank screen. To produce a finite number of symbols, the FOR and NEXT statements, with their corresponding count variable X, are introduced. To place the maze on a clear screen, the CLR control character is printed and an infinite loop that prevents the return to the BASIC prompt is introduced. This is a common experience in programming, that the input and output behavior of the program, the formatting and interface, the "surface" of the program, requires more programming complexity than the simulation or calculation that defines the kernel or "depth" of the program.

Personal tools