REM KEYS REM J/K/L: left/down/right REM F/G or U/O: rotate left/right REM I: quick drop REM P: PAUSE REM Q: quit REM GAME LOOP FROM 1 TO 740 0 GOTO 1000 1 IF W>LV THEN W=Z: GOTO 4 2 W=W+U: ON PEEK(L)-V GOTO 11,9,1,380,7,3,8,1,1,9,740,720,1,1,1,11: GOTO 1 3 POKE KC,Z REM DOWN 4 Y=Y+U: J=J+O: R=U REM erase_check_n_restore 5 INVERSE: HTAB M:VTAB N:PRINT Z$;: POKE FA,FI: IF SCRN(I+A,J+B)+ SCRN(I+C,J+D)+SCRN(I+E,J+F)+ SCRN(I+G,J+H) THEN Y=N: X=M: HTAB X: VTAB Y: PRINT A$; : ON R GOTO 400: I=X-U: GOTO 1 REM draw new position 6 M=X:N=Y: R=Z: HTAB X: VTAB Y: PRINT A$;: GOTO 1 REM LEFT 7 POKE KC,Z: X=I: I=X-U:GOTO 5 REM RIGHT 8 POKE KC,Z: I=X: X=X+U: GOTO 5 REM ROT_RIGHT 9 POKE KC,Z: SS=S: S=S-Q: TT=T: T=T-U: IF TJ THEN LJ=J 420 R=Z: RN=-U: K= J+Q+Q: IF K>NY THEN K=NY 430 FOR JJ = J TO K STEP O: G=U: FOR I = MX TO NX: IF NOT SCRN(I,JJ) THEN I=NX+U: G=Z 440 NEXT 450 IF G THEN RN=RN+U: R(RN) = JJ 460 NEXT 470 IF RN=NL THEN NL=NL+TL: LV=LV-U: IF LV>> GAME OVER <<<";:VTAB 23:HTAB N0:CALL A 705 VTAB T4:HTAB U:NORMAL:PRINT "PLAY AGAIN (Y/N) ? ";:CALL A:GET K$:IF K$<>"N" THEN 2020 710 TEXT: HOME: NORMAL: PRINT "THANKS FOR PLAYING ! ": IF DS THEN CALL 43089: REM RECONNECT DOS 715 END 720 POKE KC,Z: VTAB T4: HTAB U: INVERSE: ? "ARE YOU SURE (Y/N)?"; : GET K$ : IF K$ = "Y" THEN 710 730 HTAB U: CALL - 868: GOSUB 2600: POKE FA,FI: GOTO 1 REM PAUSE 740 POKE KC,Z: VTAB T4: HTAB O: FLASH: PRINT ">>> PAUSED <<<";: GET K$: POKE KC,Z: VTAB T4: HTAB 1: CALL - 868: GOSUB 2600: POKE FA,FI: GOTO 1 REM VARIABLES REM A$: STRING REPRESENTING THE SHAPE TO PRINT REM A/B/C/D/E/F/G/H: X/Y OFFSETS TO CHECK REM AA/BB/CC/DD/EE/FF/GG/HH PREVIOUS VALUES OF A/B/C/D/E/F/G/H REM AA$: PREVIOUS VALUE OF A$ REM E8: CONSTANT 8 REM FA: CONSTANT 50 REM FI: INVERSE FLAG TO POKE REM I/J: PIECE POSITION ON LORES SCREEN REM K: MISC. COUNTER REM KC: CLEAR KBD STROBE CONSTANT (49168) REM L: CONSTANT 49152 (LAST KEY HIT ADDR.) REM LV: LEVEL REM M/N: PREVIOUS X/Y POSITION REM MX/NX: PIT LEFT AND PIT RIGHT POSITIONS (15/24) REM MY/NY: PIT TOP/BOTTOM POS REM ML: MAX LEVEL REM NS: SHAPE # REM N0: CONSTANT 10 REM O: CONSTANT 2 REM P: CONSTANT 3 REM Q: CONSTANT 4 REM R: PIECE GOING DOWN FLAG (0/1) REM S: SHAPE OFFSET NUMBER 0..27 REM SS: PREVIOUS SHAPE OFFSET 0..27 REM SP: CONSTANT 49200 (SPEAKER) REM T: 0-3 COUNTER REM TT: PREVIOUS VALUE OF T REM T0, T1, T2, T4: CONSTANTS 20, 21, 22, 24 REM U: CONSTANT 1 REM V: CONSTANT 197 = MIN. KEY # REM X/Y: PIECE POSITION ON TEXT SCREEN REM Z: CONSTANT 0 REM Z$: STRING TO ERASE SHAPE REM ZZ$: PREVIOUS VALUE OF Z$ REM DECLARE MOST USED VARIABLES FIRST ! 1000 U=1:X=0:Y=0:Z=0:S=0:O=2:M=0:N=0:K=0:R=0:SS=0:A$="":Z$="":A=0:B=0:C=0:D=0:E=0:F=0:G=0:H=0:T=0:TT=0:P=3:Q=4:L=49152:V=197:CE=62248:FA=50:FI=0:KC=49168:S6=16:MX=15:NX=24:MY=4:NY=36:SP=49200:N5=5:N0=10:T1=21:T2=22:T4=24:T0=20:E8=8 1010 GOSUB 3000: TEXT: HOME: NORMAL: HTAB 5: PRINT "A TETRIS CLONE IN PURE APPLESOFT": HTAB 13: PRINT "BY FVL (C) 2022" 1020 VTAB 4: HTAB 17: PRINT "KEYS:" 1030 VTAB 6: PRINT " J/K/L : MOVE LEFT/DOWN/RIGHT" 1040 PRINT " F/G OR U/O : ROTATE LEFT/RIGHT" 1050 PRINT " I : QUICK DROP" 1060 PRINT " P : PAUSE" 1070 PRINT " Q : QUIT" 1080 VTAB 12: HTAB 15: PRINT "POINTS:" 1090 VTAB 14: PRINT " 1 LINE : 40 POINTS" 1100 PRINT " 2 LINES : 100 POINTS" 1110 PRINT " 3 LINES : 300 POINTS" 1120 PRINT " 4 LINES : 1200 POINTS" 1130 PRINT " QUICK DROP : 0-30 POINTS": HTAB 15: PRINT "(HEIGHT DEPENDENT)" 1140 VTAB 21: HTAB 9: PRINT "NEW LEVEL EVERY 5 LINES": VTAB 22: HTAB 5: PRINT "SPEED INCREASES WITH EACH LEVEL" 1380 VTAB T4: HTAB 8: PRINT "PLEASE WAIT >>> .......";: TH= PEEK(36): TA = PEEK(40)+PEEK(41)*256+TH-7 1390 DIM X(111), Y(111), A$(27), Z$(27), C(6): FOR S=0 TO 6: POKE TA+S, PEEK(TA+S)-128 : FOR J=0 TO 3: FOR I=0 TO 3: READ X(S*S6 + J*Q + I), Y(S*S6 + J*Q + I): NEXT: NEXT: READ C(S): NEXT 1400 D$ = CHR$(10): L$=CHR$(8): Q$=CHR$(34): F$=CHR$(102) REM SQUARE SHAPE REM .xX. REM .xx. 1410 A$(0) = L$+"QQ"+D$+L$+L$+"QQ": A$(1)=A$(0): A$(2)=A$(0): A$(3)=A$(0) 1420 Z$(0) = L$+"@@"+D$+L$+L$+"@@": Z$(1)=Z$(0): Z$(2)=Z$(0): Z$(3)=Z$(0): POKE TA, 160 REM BAR REM ..O. REM xxxx 1430 A$(4) = D$ + L$ + L$ + Q$+ Q$+ Q$+ Q$: Z$(4) = + L$ + L$ + D$ + "@@@@" REM .xO. REM .x.. REM .x.. REM .x.. 1440 A$(5) = L$ + Q$ + D$+L$+Q$+ D$+L$+Q$+ D$+L$+Q$ 1450 Z$(5) = L$ + "@" + D$+L$+"@"+ D$+L$+"@"+ D$+L$+"@" 1460 A$(6) = A$(4): A$(7)=A$(5): Z$(6) = Z$(4): Z$(7)=Z$(5): POKE TA+1, 160 REM T-SHAPE REM .xO. REM xxx. 1470 A$(8) = L$ + "L" + D$ + L$ + L$ + "LLL": Z$(8) = L$ + "@" + D$+L$ + L$ +"@@@" REM .xO. REM xx.. REM .x.. 1480 A$(9) = L$ + "L" + D$+L$+L$+ "LL" + D$+L$+"L": Z$(9) = L$ + "@" + D$+L$+L$+ "@@" + D$+L$+"@" REM ..O. REM xxx. REM .x.. 1490 A$(10) = D$ + L$ + L$ + "LLL" + D$+L$+L$+"L": Z$(10) = D$ + L$ + L$ + "@@@" + D$+L$+L$+"@" REM .xO. REM .xx. REM .x.. 1500 A$(11) = L$ + "L" + D$ + L$+"LL" + D$+L$+L$+ "L": Z$(11) = L$ + "@" + D$ + L$+"@@" + D$+L$+L$+ "@": POKE TA+2, 160 REM L-SHAPE REM ..O. REM xxx. REM x... 1510 A$(12) = D$ + L$ + L$ + "]]]" + D$ + L$+ L$+ L$+"]": Z$(12) = D$ + L$ + L$ + "@@@" + D$ + L$+ L$+ L$+"@" REM .xO. REM .x.. REM .xx. 1520 A$(13) = L$ + "]"+ D$ + L$ + "]"+ D$ + L$ + "]]": Z$(13) = L$ + "@"+ D$ + L$ + "@"+ D$ + L$ + "@@" REM ..X. REM xxx. 1530 A$(14) = "]" + D$ + L$+ L$+ L$+"]]]": Z$(14) = "@" + D$ + L$+ L$+ L$+"@@@" REM xxO. REM .x.. REM .x.. 1540 A$(15) = L$+L$+"]]" + D$ + L$ + "]" + D$ + L$ + "]": Z$(15) = L$+L$+"@@" + D$ + L$ + "@" + D$ + L$ + "@": POKE TA+3, 160 REM L-SHAPE INVERTED REM ..O. REM xxx. REM ..x. 1550 A$(16) = D$ + L$ + L$ + F$ + F$ + F$ + D$ + L$+ F$: Z$(16) = D$ + L$ + L$ + "@@@" + D$ + L$+ "@" REM .xX. REM .x.. REM .x.. 1560 A$(17) = L$ + F$ + F$ + D$ + L$+L$ + F$+ D$ + L$ + F$: Z$(17) = L$ + "@@" + D$ + L$+L$ + "@"+ D$ + L$ + "@" REM x.O. REM xxx. 1570 A$(18) = L$ + L$ + F$ + D$ + L$ + F$ + F$ + F$: Z$(18) = L$ + L$ + "@" + D$ + L$ + "@@@" REM .xO. REM .x.. REM xx.. 1580 A$(19) = L$ + F$ + D$+L$ + F$ + D$+L$ + L$ + F$ + F$: Z$(19) = L$ + "@" + D$+L$ + "@" + D$+L$+L$ + "@@": POKE TA+4, 160 REM Z-SHAPE REM xxO. REM .xx. 1590 A$(20) = L$ + L$ + "33" + D$ + L$ + "33": Z$(20) = L$ + L$ + "@@" + D$ + L$ + "@@" REM .xO. REM xx.. REM x... 1600 A$(21) = L$ + "3" + D$ + L$ + L$ + "33" + D$ + L$ + L$ + "3": Z$(21) = L$ + "@" + D$ + L$ + L$ + "@@" + D$ + L$ + L$ + "@" 1610 A$(22) = A$(20): A$(23) = A$(21): Z$(22) = Z$(20): Z$(23) = Z$(21): POKE TA+5, 160 REM S-SHAPE REM .xX. REM xx.. 1620 A$(24) = L$ + ";;" + D$ + L$ + L$ + L$ + ";;": Z$(24) = L$ + "@@" + D$ + L$ + L$ + L$ + "@@" REM x.O. REM xx.. REM .x.. 1630 A$(25) = L$ + L$ + ";" + D$ + L$ + ";;" + D$ + L$ + ";": Z$(25) = L$ + L$ + "@" + D$ + L$ + "@@" + D$ + L$ + "@" 1640 A$(26) = A$(24): A$(27) = A$(25): Z$(26) = Z$(24): Z$(27) = Z$(25): POKE TA+6, 160 1700 VTAB 24: CALL - 868: HTAB 1: INVERSE: PRINT " <<< ANY KEY TO CONTINUE >>> "; : POKE TA-TH+39+7,32: WAIT 49152, 128 2000 P(0)=40: P(1)=100: P(2)=300:P(3)=1200: DS= PEEK(40672) = 162: IF DS THEN CALL 40672: REM DISCONNECT DOS FOR FASTER PRINT 2010 Q$ = CHR$(119) + CHR$(119) + CHR$(119) + CHR$(119) + CHR$(119): Q$=Q$+Q$+Q$+Q$+Q$+Q$+Q$+Q$: SL=1: OD=0: OL=5 2020 HOME: GR: FLASH: FOR I=1 TO 20: VTAB I: ? Q$;: NEXT: INVERSE: FOR I = 1 TO 19: HTAB 16: VTAB I: ? "@@@@@@@@@@";: NEXT: FOR I= 9 TO 13: VTAB I: HTAB 5: PRINT "@@@@@@";: NEXT 2080 NORMAL 2090 POKE KC, Z: VTAB 21: HTAB 7: PRINT "STARTING LEVEL: ";: INVERSE: PRINT SL;: NORMAL : PRINT SPC(SL<10)" (+/-) TO CHANGE"; 2100 VTAB 22: HTAB 4: PRINT "OBSTACLES DENSITY: ";: INVERSE: PRINT OD;: NORMAL: PRINT " (O/P) TO CHANGE"; 2110 VTAB 23: HTAB 1: PRINT "OBSTACLES UP TO LINE: ";: INVERSE: PRINT OL;: NORMAL: PRINT SPC(OL<10)" (L/M) TO CHANGE"; 2120 INVERSE: VTAB 24: HTAB 3: PRINT "<<< PRESS ANY OTHER KEY TO START >>>"; : GET K$: NORMAL 2130 IF K$<>"+" AND K$<>"-" THEN 2170 REM CHANGE LEVEL 2140 SL=SL+44-ASC(K$): IF SL<1 THEN SL=40: GOTO 2090 2150 IF SL>40 THEN SL=1 2160 GOTO 2090 2170 IF K$="L" OR K$="M" THEN 2250: REM CHANGE OBSTACLES LINE 2180 IF K$<>"O" AND K$<>"P" THEN 2300: REM START GAME REM CHANGE OBSTACLES DENSITY 2190 OD=OD-2*ASC(K$)+159: IF OD>7 THEN OD=0 2200 IF OD<0 THEN OD=7 2210 GOTO 2090 REM CHANGE OBSTACLES FINAL LINE 2250 OL=OL-2*ASC(K$)+153: IF OL>15 THEN OL=5 2260 IF OL<5 THEN OL=15 2270 GOTO 2090 2300 HOME: SC=0: LJ=40: ML=41: LV=ML-SL: PS=INT(RND(U)*7): LI=0: TL=5: NL=TL: GOSUB 2600 2310 IF NOT OD THEN 2400 2320 FOR J=NY TO NY+2-OL*2 STEP -2: K=0: FOR I=0 TO 9 2330 IF K<9 AND RND(1)*10<=OD THEN CC=INT(RND(1)*16): CC=CC*(CC<>7): COLOR=CC: PLOT I+MX,J: PLOT I+MX,J+1: K=K+(CC>0) 2340 NEXT: NEXT 2400 GOTO 600 2600 NORMAL: VTAB 21: HTAB 19: PRINT "J/K/L: LEFT/DOWN/RIGHT";: HTAB 15: PRINT "F/G - U/O: ROTATE L/R": HTAB 23: PRINT "I: QUICK DROP": HTAB 21: PRINT "P/Q: PAUSE/QUIT";: HTAB 2: INVERSE: PRINT "=== TETRIS ===";: RETURN REM =========== ONERR GOTO REM ALSO PREPARE AMPERSAND VECTOR TO JMP TO $F328 (RESET STACK POSITION WITHOUT RESUME) REM ANYTHING AFTER ON ERR ON THE SAME LINE IS IGNORED BY APPLESOFT 3000 ON ERR GOTO 3100 3010 POKE 1013, 76: POKE 1014,40: POKE 1015,243: RETURN REM === 3072 is next multiple of 256, so going to line 3100 in case of error will only skip line 3010 ! REM USE AMPERSAND TO DO A CALL 62248 (-3288) TO SPARE A FEW CYCLES. 3100 &: GOTO 1 REM ======================================= CHECKING POINTS REM BECAUSE PRINT CAN ONLY MOVE THE CURSOR LEFT AND DOWN, WE HAVE TO ASSUME WE START IN POS (3,0) REM X MARKS A PLOTTED STARTING POINT, O MARKS AN UNPLOTTED STARTING POINT REM 0123 REM 0..X. REM 1.... REM 2.... REM 3.... REM SQUARE SHAPE REM .xX. REM .xx. 10010 DATA 0, 0,-1, 0, 0, 2,-1, 2 10020 DATA 0, 0,-1, 0, 0, 2,-1, 2 10030 DATA 0, 0,-1, 0, 0, 2,-1, 2 10040 DATA 0, 0,-1, 0, 0, 2,-1, 2,63 : REM [] COLOR=MAGENTA (Q INVERSED) REM BAR REM ..O. REM xxxx 10050 DATA 0, 2,-1, 2,-2, 2, 1, 2 REM .xO. REM .x.. REM .x.. REM .x.. 10060 DATA -1, 0,-1, 2,-1, 4,-1, 6 10070 DATA 0, 2,-1, 2,-2, 2, 1, 2 10080 DATA -1, 0,-1, 2,-1, 4,-1, 6 10090 DATA 63: REM COLOR=DARK BLUE (" INVERSED) REM T-SHAPE REM .xO. REM xxx. 10100 DATA -1, 0,-2, 2,-1, 2, 0, 2 REM .xO. REM xx.. REM .x.. 10110 DATA -1, 0,-2, 2,-1, 2, -1, 4 REM ..O. REM xxx. REM .x.. 10120 DATA -2, 2,-1, 2, 0, 2, -1, 4 REM .xO. REM .xx. REM .x.. 10130 DATA -1, 0,-1, 2, 0, 2,-1, 4 10140 DATA 255: REM COLOR=GREEN (L NORMAL) REM L-SHAPE REM ..O. REM xxx. REM x... 10150 DATA -2,2,-1,2,0,2,-2,4 REM .xO. REM .x.. REM .xx. 10160 DATA -1,0,-1,2,-1,4,0,4 REM ..X. REM xxx. 10170 DATA 0,0,-2,2,-1,2,0,2 REM xxO. REM .x.. REM .x.. 10180 DATA -2,0,-1,0,-1,2,-1,4 10190 DATA 255: REM COLOR=YELLOW (] NORMAL) REM L-SHAPE INVERTED REM ..O. REM xxx. REM ..x. 10200 DATA -2,2,-1,2,0,2,0,4 REM .xX. REM .x.. REM .x.. 10210 DATA 0,0,-1,0,-1,2,-1,4 REM x.O. REM xxx. 10220 DATA -2,0,-2,2,-1,2,0,2 REM .xO. REM .x.. REM xx.. 10230 DATA -1,0,-1,2,-1,4,-2,4 10240 DATA 127: REM COLOR=MEDIUM BLUE (CHAR 102 AND FLAG 127) REM Z-SHAPE REM xxO. REM .xx. 10250 DATA -2,0,-1,0,-1,2,0,2 REM .xO. REM xx.. REM x... 10260 DATA -1,0,-1,2,-2,2,-2,4 10270 DATA -2,0,-1,0,-1,2,0,2 10280 DATA -1,0,-1,2,-2,2,-2,4 10290 DATA 63: REM COLOR=PURPLE (3 INVERSE) REM S-SHAPE REM .xX. REM xx.. 10300 DATA 0,0,-1,0,-1,2,-2,2 REM x.O. REM xx.. REM .x.. 10310 DATA -2,0,-2,2,-1,2,-1,4 10320 DATA 0,0,-1,0,-1,2,-2,2 10330 DATA -2,0,-2,2,-1,2,-1,4 10340 DATA 255: REM COLOR=PINK (; NORMAL)