Thanks for coming to the Juiced.GS Web site! Please read more about us, or download some free issues.
Here is the code listing for Plotter II, an update to the original Plotter that demonstrates the concepts of Structured Applesoft, as defined by Juiced.GS staff writer Ivan Drucker in Volume 14, Issue 4, and Volume 15, Issue 1. This code is also available in SHK and ZIP archive formats.
See also the online supplements to the print material.
REM Plotter v1.1, March 2010
REM by Ivan Drucker
REM This program plots random hi-res pixels.
REM It changes color when a user presses a key.
REM If the key is 0-7, it uses that color.
REM C clears the screen. Q or ESC quits.
REM If it's any other key, the computer beeps.
REM This program demonstrates the syntax of Structured Applesoft.
REM It illustrates most of the concepts described in the Structured Applesoft articles
REM in the December 2009 and March 2010, issues of Juiced.GS, as well the online bonus
REM material at http://www.juiced.gs. Specific concepts demonstrated in this program:
REM source code written in editor, then pasted into emulator or EXEC'd on Apple II
REM subroutine-oriented program flow with minimal main routine
REM organization of code (global variable declaration 10-99, 100-9999 main routine, 10000-> subroutines)
REM self-contained, specific-purpose subroutines with labels, parameters and return values
REM IF, FOR, WHILE, and TRY (with bug fix for March 2010 article) structures
REM global and local variable and array declaration, and constant indication
REM indentation as part of structures
REM blank lines for clarity
REM extensive non-numbered commenting
REM user comments separated with :: from structure part comments
REM using QuitFlag to perform shutdown operations along the way to the program end
REM consistent, clear syntax with regard to parantheses, colons, and other details
REM one statement per line except for structure parts or logically related statements
REM temporary variables
REM no GOTO except in structure parts
REM Not demonstrated:
REM SWITCH structure
REM THROWing errors
REM using FINALLY with THROW or RETURN from a catch block
REM every variety of IF and WHILE structure
REM Note: it is strongly recommended that you view this Structured Applesoft
REM source file in TextWrangler (free) or BBEdit (both at http://www.barebones.com)
REM with the Applesoft BASIC language module installed. You can get the module
REM from http://www.juiced.gs in the Dec 2009 Issue Links under Plotter.
REM
REM To install it, right-click on TextWrangler or BBEdit, choose Show Package Contents,
REM and drop it into Contents/Resources/Language Modules. Then restart the editor,
REM open this file, and choose Applesoft BASIC from the language menu at the bottom
REM of the window.
REM ----PROGRAM STARTS HERE-----
NEW
REM lines 0-9 are reserved
10 REM Initial Setup
REM declare global variables
40 LET QT = 0 : REM QT->quitFlag
41 LET PC = 1 : REM PC->pixelColor
REM declare global constants
50 DIM CN$(7) : REM CONSTANT; CN$->colorNames
51 CN$(0) = "BLACK 1" : CN$(1) = "GREEN" : CN$(2) = "VIOLET" : CN$(3) = "WHITE 1"
52 CN$(4) = "BLACK 2" : CN$(5) = "ORANGE" : CN$(6) = "BLUE" : CN$(7) = "WHITE 2"
55 LET E$ = CHR$(27) : REM CONSTANT E$->ESC key
100 REM Main Routine
110 TEXT : HOME
115 HGR
150 P1$ = "INITIAL COLOR?" : GOSUB 11200 : REM AskAndSetColor
160 REM IF
161 ON (NOT QT) GOTO 190 : GOTO 300
190 GOSUB 10400 : REM DisplayColorName
200 REM WHILE
201 ON (NOT QT) GOTO 210 : GOTO 289
210 GOSUB 10100 : REM CheckForKey
220 IF (R1$<>"") THEN P1$ = R1$ : GOSUB 10200 : REM HandleKeyPress
240 GOSUB 10000 : REM ChoosePlotSpot
250 P1 = R1 : P2 = R2 : GOSUB 10700 : REM PlotPixel
260 P1 = 1 : GOSUB 11100 : REM Delay
288 GOTO 200
289 REM END WHILE
290 GOTO 330
300 REM ELSE :: initial color entry error, or ESC
310 GOSUB 11000 : REM DrawBigX
320 P1 = 1 : GOSUB 11100 : REM Delay
330 REM END IF
350 GOSUB 10900 : REM SayGoodbye
499 REM END IF
9999 END
REM Subroutines
10000 REM SUB^ChoosePlotSpot:10000-10099 {}
REM Randomly picks and returns hi-res coordinate
REM in: nothing
REM out: R1->H coordinate (0-279), R2->V coordinate (0-161)
REM indicate use of global variable in this routine
10001 REM global PC
REM get horizontal position
10010 REM IF
10011 ON (PC=0 OR PC=3 OR PC=4 OR PC=7) GOTO 10015 : GOTO 10030
REM if color is black or white, plot any horizontal pixel
10015 ZZ = INT(RND(1) * 279)
10020 GOTO 10060
10025 REM ELSE
REM plot color 1 or 5 on odd horizontal pixels, 2 or 6 on even
10030 ZZ = INT(RND(1) * 139)
10040 ZZ = (ZZ * 2)
10050 IF (PC=1 OR PC=5) THEN ZZ = (ZZ + 1)
10060 REM END IF
10070 R1 = ZZ
REM get vertical position
10080 R2 = INT(RND(1)*160)
10099 RETURN
10100 REM SUB^CheckForKey:10100-10199 {}
REM Checks to see if the user pressed a key, and returns it if so.
REM in: nothing
REM out: R1$ = key pressed or "" if none
REM declare local variable for this subroutine only
10105 LET KB = 0 : REM KB->keyboardBufferValue
10110 KB = PEEK(49152)
10115 REM IF
10116 ON (KB>127) GOTO 10120 : GOTO 10150
10120 R1$ = CHR$(KB - 128) : REM convert ASCII value of key to string
10130 POKE 49168,0 : REM clear KB buffer
10135 GOSUB 10600 : REM QuickBuzz
10140 GOTO 10160
10150 REM ELSE
10155 R1$ = "" : REM indicate no key pressed
10160 REM END IF
10199 RETURN
10200 REM SUB^HandleKeyPress:10200-10299 {}
REM Calls appropriate routine
REM based on which key was pressed
REM in: P1$ = key
REM out: nothing
10210 REM IF
10211 ON (P1$="C" OR P1$="c") GOTO 10215 : GOTO 10230
10215 HGR : REM Clear HiRes Screen
10220 GOTO 10290
10230 REM ELSE IF
10231 ON (P1$="Q" OR P1$="q" OR P1$=E$) GOTO 10235 : GOTO 10250
10235 GOSUB 10800 : REM ShutDown
10240 GOTO 10290
10250 REM ELSE IF
10251 ON (ASC(P1$)>47 AND ASC(P1$)<56) GOTO 10260 : GOTO 10280
REM check for 0 through 7, indicating color should be changed
10260 P1 = VAL(P1$) : GOSUB 10300 : REM ChangePixelColor
10265 GOSUB 10400 : REM DisplayColorName
10270 GOTO 10290
10280 REM ELSE
10285 GOSUB 10500 : REM Beep
10290 REM END IF
10298 RETURN
10300 REM SUB^ChangePixelColor:10300-10399 {}
REM Assigns the pixel color; persists until changed
REM in: P1 = color to be set (0-7)
REM out: nothing
REM globals: PC will contain new color value
10301 REM global PC
10310 PC = P1
10320 HCOLOR = PC
10399 RETURN
10400 REM SUB^DisplayColorName:11200-11299 {}
REM Prints name of current color in text area
REM in/out: nothing
REM indicate use of global in this routine
10401 REM GLOBAL PC
10410 VTAB 22
10420 PRINT CN$(PC);" "
10499 RETURN
10500 REM SUB^Beep:10500-10599 {}
REM Beeps once, and that's all
REM in/out: nothing
10510 CALL -1052
10599 RETURN
10600 REM SUB^QuickBuzz:10600-10699 {}
REM buzzes speaker briefly
REM in/out: nothing
10610 FOR ZZ=1 TO 5 : POKE -16336,0 : NEXT ZZ
10699 RETURN
10700 REM SUB^PlotPixel:10700-10799 {}
REM Draws a dot on the HGR screen, or a big X if quitting
REM parameters: P1:H position, P2:V position
REM indicate use of global variable in this routine
10701 REM GLOBAL QT
REM Declare local vars for this routine
10705 LET PX=P1 : REM PH->pixelHPos
10706 LET PY=P2 : REM PV->pixelVPos
10710 REM IF
10711 ON (NOT QT) GOTO 10730 : GOTO 10750 : REM if not quitting
10730 HPLOT PX,PY : REM plot the point
10740 GOTO 10770
10750 REM ELSE; program is quitting, so handle
10760 GOSUB 11000 : REM DrawBigX
10770 REM END IF
10799 RETURN
10800 REM SUB^ShutDown:10800-10899 {}
REM Initiates program exit. quitFlag is set; other
REM routines can test for it and clean things up
REM if needed.
REM in/out: nothing
REM globals: QT set to 1
10801 REM GLOBAL QT
10810 QT = 1 : REM set quitFlag
10899 RETURN
10900 REM SUB^SayGoodbye:10900-10999 {}
REM sets text mode, clears screen, says bye to user
REM in/out: nothing
10910 TEXT
10920 HOME
10930 PRINT "BYE!"
10999 RETURN
11000 REM SUB^DrawBigX:11000-11099 {}
REM Draws a big white X across the screen and waits for a short duration
REM used during quit
REM in/out: nothing
REM HCOLOR will be 3; note global PC will remain what it was
11010 P1 = 3 : GOSUB 10300 : REM ChangePixelColor
11020 HPLOT 0,0 TO 279,159
11030 HPLOT 0,159 TO 279,0
11050 P1 = 3 : GOSUB 11100 : REM Delay
11099 RETURN
11100 REM SUB^Delay:11100-11199 {}
REM Does nothing for a length of time
REM in: P1->delay multiplier
REM out: nothing
11110 FOR ZZ = 1 TO P1
11115 FOR ZY = 1 TO 75 : NEXT ZY
11120 NEXT ZZ
11199 RETURN
11200 REM SUB^AskAndSetColor:11200-11499 {}
REM Prompts user for color (and demonstrates advanced error handling in a while loop)
REM in: P1$ = prompt string
REM out: nothing
REM for a full explanation of the error handling below, see the article
REM bonus material, in the March 2010 Issue Links at http://www.juiced.gs
11205 LET IC = 0 : REM IC->Initial Color
11206 LET PS$ = P1$ : REM PS$->Prompt String
11207 LET OK = 0 : REM OK->if true, ready to return, if false, loops again
11208 LET R1 = -1 : REM R1$->default return value
11210 REM WHILE
11211 ON (NOT OK) GOTO 11230 : GOTO 11489
11230 REM TRY
11231 Z9 = PEEK(248) : ONERR GOTO 11300
11240 VTAB 21 : HTAB 1 : PRINT PS$;
REM next line could throw a REENTER error on non-numeric input
11250 INPUT "";IC
REM GOSUB 10300 could throw an ILLEGAL QUANTITY error if IC > 7
11260 P1 = IC : GOSUB 10300 : REM ChangePixelColor
REM clean up text
11270 HOME
REM set return value and indicate ready to return
11280 OK = 1
11290 POKE 216,0 : GOTO 11400
11300 REM CATCH
11301 POKE 216,0 : ER = PEEK(222) : POKE 223,Z9 : CALL -3288
11310 REM CATCH ERROR: REENTER :: if user enters a non-number
11311 ON (ER=254) GOTO 11320 : GOTO 11330
11320 PRINT : PRINT SPC(39) : HTAB 1
11321 PRINT "PLEASE ENTER A NUMBER."
11329 GOTO 11400
11330 REM CATCH ERROR: ILLEGAL QUANTITY :: if HCOLOR > 7
11331 ON (ER=53) GOTO 11340 : GOTO 11380
11340 PRINT : PRINT SPC(39) : HTAB 1
11345 PRINT "VALID COLORS ARE 0 THROUGH 7."
11349 GOTO 11400
11380 REM CATCH OTHERS
REM always required, even if it does nothing
REM in this case, only possible other error is BREAK (CTRL-C)
REM if we get that, or anything else unexpected,
REM quit via QuitFlag (flow out of program, shutting down along the way)
11382 OK = 1
11383 GOSUB 10800 : REM ShutDown
11389 GOTO 11400
11400 REM FINALLY
11401 GOSUB 11410 : GOTO 11450
REM always buzzes after entry
11410 GOSUB 10600 : REM QuickBuzz
11420 RETURN
11450 REM END TRY
11488 GOTO 11210
11489 REM END WHILE
11499 RETURN
