Pitcher is a text-and-graphics baseball simulation in which the human player bats against a computer-controlled pitcher over nine innings. The player chooses between a risky “up” swing for a potential home run or a safer “down” swing, with outcome probabilities calculated from a randomly generated pitch factor and the swing choice. The program animates a pitcher figure and ball trajectory using UDGs and PLOT/OVER 1 commands to draw and erase a moving ball across the screen. Base-running logic tracks each of nine named players through arrays, advancing runners and scoring them according to further RND comparisons. UDG shape data is stored in a REM statement at line 9950 and installed via a PEEK-based address calculation in the subroutine at line 9900/9940.
Program Structure
The program is organized into a main game loop at lines 60–280 covering nine innings, with clearly separated subroutines:
- Lines 450–820: Human batting subroutine — handles player swing input, strike counting, hit resolution, and base advancement.
- Lines 830–980: Computer batting subroutine — automates the computer team’s at-bats.
- Lines 990–1190: Ball animation subroutine for a hit (pitch plus hit trajectory).
- Lines 1200–1340: Strike animation subroutine (ball passes the batter).
- Lines 1350–1420: “Down” swing ball trajectory animation.
- Lines 1430–1490: Variable initialization and player name loading via
READ/DATA. - Lines 9910–9950: UDG installation via a
PEEK-based calculation and aREMline holding the raw UDG bitmap data.
UDG and Graphics Setup
The subroutine at lines 9900/9940 relocates the UDG table by peeking system variables 23637–23638 to find the top of BASIC memory, adding 6, then poking the result (split into low and high bytes using FN l and FN h) into addresses 23675–23676. The UDG pixel data itself is embedded in the REM statement at line 9950. UDGs labeled \\a through \\l (and possibly more) are used throughout lines 990–1230 to render a two-cell-wide pitcher figure in two pose states.
Ball movement is rendered using PLOT OVER 1 to draw and immediately erase the ball pixel at each position in the animation loop, giving a smooth motion effect without leaving trails. INK 8 (transparent ink) is used for the ball plot calls, which on this platform renders using the underlying paper/ink colors of the cell.
Batting and Probability Model
Each at-bat begins with a random pitch factor f in the range 1–10 (line 480). The player chooses “u” (up/aggressive) or “d” (down/safe). The chance of being caught is computed at line 520 as ch = ((-f)+10)*10, giving a percentage from 0 to 90. If “u” is chosen, an additional 50 is added to an (line 530), which scales ch proportionally at line 540 to produce ce, the catch probability. A random number rn in 0–24 is then compared against ce at line 550; if less, the player is caught.
Strikes are accumulated in str. A RND>0.9 test (lines 560–570) triggers the strike subroutine; on the third strike the batter is retired. The number of bases stolen on a hit is calculated at line 620 as INT(RND * INT((f-1)) / 1.5) + 1, capped at 4 (home run).
Base-Running Logic
The array t() tracks each player’s base position; a value of 4 indicates the player has scored or been retired from base-running. The array w() tracks whether each player is still active (1) or out (0). When a hit occurs (lines 670–750), a loop iterates over preceding batters; depending on RND comparisons, runners either return safely, are run out, or score. A home run (line 760) triggers a further loop that attempts to bring all on-base runners home or runs them out.
Computer Team Logic
The computer’s batting (lines 830–980) is greatly simplified: swing direction is chosen randomly (lines 840–860), and outcomes are determined purely by RND thresholds rather than the full probability model used for the human player. Notably, the out counter co is incremented directly rather than via the w() array. The computer team terminates its half-inning when co=3 (line 240).
Notable Idioms and Techniques
SGN PIis used throughout as a compact way to write 1 (sinceSGN PI = 1), starting allFORloops from 1 rather than 0.NOT ais used at lines 190 and 1470 to initializecoto 0 (since after the preceding loopa=9,NOT 9 = 0).- Conditional string expressions like
("s are" AND pla<>1)at line 610 select grammatically correct plural/singular suffixes inline withinPRINT. DEF FN h(x)andDEF FN l(x)at line 20 provide high-byte and low-byte extraction for the UDG address POKE at line 9940.INPUT LINE a$is used throughout as a simple “press ENTER to continue” pause that accepts any input including empty strings.
Bugs and Anomalies
- Line 740 contains
RETURN : PRINT p$(a);" is run out.": LET w(a)=0: RETURN— thePRINTandLETstatements after the firstRETURNare unreachable dead code; the “run out” message is never displayed. - At line 960, the condition
a$ <> "d"tests a variable that has just been used as a loop counter or input string from a prior prompt, not the computer’s swing direction — this appears to be a logic error whereh$was intended. - The draw-game extra innings at lines 360–440 reset the human team’s
w()array but do not resetcofor the computer team, potentially causing the computer’s inning to terminate immediately ifcois already 3. - Line 620 divides by 1.5 without ensuring
f>1; iff=1,INT((f-1)) = 0andrnwill always be 1 regardless ofRND, making base count deterministic for the weakest pitch.
Source Code
20 DEF FN h(x)= INT (x/256):DEF FN l(x)=x-256* FN h(x):GO SUB 9900
30 PRINT AT 10,10;"Please wait"
50 GO SUB 1430:REM variables
60 CLS
70 FOR i= SGN PI TO 9
80 PRINT "Your innings"
90 FOR a= SGN PI TO 9:LET w(a)=1:NEXT a:LET pla=0
100 FOR m= SGN PI TO 9
110 IF w(m)=1 THEN GO SUB 450
120 IF w(m)=0 THEN LET pla=pla+1:IF pla=3 THEN GO TO 150
130 NEXT m
140 GO TO 100
150 PRINT "Your team is out!"
160 PRINT "At the end of innings ";i
170 PRINT "Your team has scored ";hsc
180 PRINT "The computer now plays!"
190 LET co= NOT a
200 INPUT "Press ENTER to continue "; LINE a$
210 CLS
220 FOR m= SGN PI TO 9
230 GO SUB 830
240 IF co=3 THEN GO TO 260
250 NEXT m
260 PRINT "The computer team is out!"
270 INPUT "Press ENTER to continue "; LINE a$
280 NEXT i
290 IF csc>hsc THEN GO TO 330
300 IF csc=hsc THEN GO TO 350
310 PRINT "Your team wins ";hsc;" runs to ";csc
320 INPUT "Press ENTER to play again "; LINE a$:GO TO 50
330 PRINT "The computer wins ";csc;" to ";hsc
340 GO TO 320
350 PRINT "It's a draw, we must have a second innings!"
360 FOR a= SGN PI TO 9:LET w(a)=1:NEXT a:LET pla=0
370 FOR m= SGN PI TO 9
380 IF w(m)=1 THEN GO SUB 450
390 IF w(m)=0 THEN LET pla=pla+1:IF pla=3 THEN GO TO 250
400 NEXT m
410 FOR m= SGN PI TO 9
420 GO SUB 830
430 NEXT m
440 GO TO 290
450 LET str=1
460 PRINT "________________________________"
470 PRINT p$(m);" comes into bat,"
480 LET f= INT (RND*10)+1
490 PRINT "Will ";p$(m);" hit up, and try for a home run, or will he hit down and play safe? (d or u)"
500 INPUT LINE h$
510 CLS
520 LET ch=((-f)+10)*10
530 LET an=0:IF h$="u" OR h$="U" THEN LET an=50
540 LET ce=(ch*an)/100:LET rn= INT (RND*25)
550 IF rn<ce THEN GO TO 810
560 IF str=3 AND RND>.9 THEN GO SUB 1200:LET w(m)=0:RETURN
570 IF RND>.9 THEN GO SUB 1200:LET str=str+1:INPUT "Press ENTER for next strike "; LINE a$:GO TO 540
580 GO SUB 990:INPUT "Press ENTER to continue "; LINE a$:CLS
590 IF f>5 AND (h$="u" OR h$="U") THEN PRINT "The ball is in the outfield,"
600 IF f<6 AND (h$="d" OR h$="D") THEN PRINT "The ball is in the infield"
610 PRINT "Your score so far is ";hsc:PRINT pla;" player";("s are" AND pla <>1);(" is" AND pla=1);" out so far"
620 LET rn= INT (RND* INT ((f-1))/1.5)+1:IF rn>4 THEN LET rn=4
630 IF rn=4 THEN GO TO 650
640 PRINT p$(m);" steals ";rn;("st" AND rn=1);("nd" AND rn=2);("rd" AND rn=3);" base"
650 LET t(m)=rn
660 IF rn=4 THEN GO TO 760
670 LET ba=0
680 FOR a= SGN PI TO m-1
690 IF t(a) <>4 THEN LET ba=ba+1:IF ba>2 THEN GO TO 750
700 IF RND>.5 AND t(a) <>4 THEN GO TO 730
710 NEXT a
720 RETURN
730 IF RND>.3 THEN GO TO 750
740 RETURN :PRINT p$(a);" is run out.":LET w(a)=0:RETURN
750 PRINT p$(a);" gets home":LET hsc=hsc+1:LET t(a)=4:RETURN
760 PRINT p$(m);" gets a home run !!":LET hsc=hsc+1
770 FOR c= SGN PI TO m
780 IF RND>.7 AND t(c) <>4 AND rn <>4 THEN PRINT p$(c);" is run out":LET t(c)=4:LET w(c)=0:GO TO 800
790 IF t(c) <>4 THEN LET t(c)=4:PRINT p$(c);" also gets home ":LET hsc=hsc+1
800 NEXT c:RETURN
810 PRINT p$(m);" is caught":LET w(m)=0:LET t(m)=4
820 RETURN
830 CLS :LET str=1
840 LET a= INT (RND*2)
850 IF a=1 THEN LET h$="d"
860 IF a=0 THEN LET h$="u"
870 LET f= INT (RND*10)+1
880 IF str=3 THEN RETURN
890 IF RND>.9 THEN GO SUB 1200:LET str=str+1:INPUT "Press ENTER for next pitch "; LINE a$:GO TO 890
900 PRINT AT 0,0;"________________________________"
910 PRINT "The computer has ";csc;" runs"
920 PRINT "You pitch,",,
930 GO SUB 990
940 PRINT AT 2,10;"and they hit!"
950 IF RND>.9 THEN PRINT "They score a home run !":LET csc=csc+1:GO TO 970
960 IF RND>.4 AND a$ <>"d" AND a$ <>"D" THEN PRINT "Your team catches the ball":LET co=co+1
970 INPUT "Press ENTER for next pitch "; LINE a$
980 RETURN
990 PRINT AT 10,4; INK 6;"\g\i"; AT 11,4;"\c\d"
1000 PRINT AT 10,20; INK 5;"\e\f"; AT 11,20;"\c\d"
1010 PAUSE 10
1020 PRINT AT 10,4; INK 6;"\c\d"; AT 11,4;"\h\j"
1030 LET di=.1:LET ff=.2
1040 FOR a=45 TO 165 STEP 2
1050 PLOT OVER 1; INK 8;a,95+di
1060 PLOT OVER 1; INK 8;a,95+di
1070 LET di=di+ff
1080 IF a>100 THEN LET ff=ff-.03
1090 NEXT a
1100 PRINT AT 10,20; INK 5;"\a\b"
1110 IF h$="d" OR h$="D" THEN GO TO 1350
1120 LET s=95
1130 FOR a=165 TO 0 STEP -5
1140 PLOT INK 8;a,s
1150 PAUSE 2
1160 PLOT OVER 1; INK 8;a,s
1170 LET s=s+1
1180 NEXT a
1190 RETURN
1200 PRINT AT 10,4; INK 6;"\g\i"; AT 11,4;"\c\d"
1210 PRINT AT 10,20; INK 5;"\e\f"; AT 11,20;"\c\d"
1220 PAUSE 10
1230 PRINT AT 10,4; INK 6;"\k\l"; AT 11,4;"\h\j"
1240 LET di=.1:LET ff=.2
1250 FOR a=45 TO 190 STEP 2
1260 PLOT OVER 1; INK 8;a,95+di
1270 PAUSE 1
1280 PLOT OVER 1; INK 8;a,95+di
1290 LET di=di+ff
1300 IF a>100 THEN LET ff=ff-.03
1310 NEXT a
1320 PRINT AT 0,0;"Strike ";str
1330 IF str=3 THEN PRINT "You're out !":LET co=co+1
1340 RETURN
1350 LET ff=.3
1360 FOR a=165 TO 30 STEP -3
1370 PLOT INK 8;a,95-ff
1380 PLOT OVER 1; INK 8;a,95-ff
1390 LET ff=ff+.5
1400 IF ff>5 THEN LET ff=-ff
1410 NEXT a
1420 RETURN
1430 BORDER 1:PAPER 1:INK 7:CLS
1440 DIM w(9):DIM p$(9,8):DIM c(9):DIM t(9)
1450 LET hsc=0:LET csc=hsc
1460 RESTORE 1430:FOR a= SGN PI TO 9:READ p$(a):NEXT a
1470 LET co= NOT a
1480 DATA "Jenkins","Harwood","Zeber","Holtop","Gregelis","Todd","Bruda","Pulsman","Fogan"
1490 RETURN
9910 REM UDG's
9940 LET x= VAL "(PEEK 23637+ PEEK 23638*256)+6":POKE 23675, FN l(x):POKE 23676, FN h(x):RETURN
9950 REM \{7}\{7}\{7}\{7}\{7}\{7}\{3}\{3}\{0}\{0}\{0}LPRINT \i\'.\ \ \{7}\{15}\{31}\{25}\{25}\{17} `\ \ \ \ USR SAVE \{12}\{4}\{3}\{3}\{3}\{3}\{7}\{31}a\{1}\{0}\{0}USR USR USR USR USR USR \{12}\{12}\{15}\{7}\{15}\{31}?\{31}\{7}\{15}\{14}<00`USR \{0}\{0}\{0}USR LPRINT LIST LIST LPRINT LPRINT LPRINT p08\{24}\{12}\{15}\{7}\{7}\{7}\{7}\{15}\{15}\{31}\{31}\{0}\{0}\{28}DRAW LPRINT \ \ \ ?\{7}\{7}\{7}\{7}\{7}\{7}\{7}\{15}<<~ffffINPUT \{0}\{0}\{0}0x\{24}\{25}\{31}\{31}\{30}\{31}\{30}\{14}\{4}\{4}\{12}\{31}\{30}\{30}\{30}\{14}\{10}\{10}\{0}|BB|DB\{0}\{0}<@<\{2}B<\{0}\{0}RETURN \{16}\{16}\{16}\{16}\{16}\{0}\{0}BBBBB<\''
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

