tenpest - 10-line "Tempest"-ish game in TurboBASIC XL for the Atari 8-bit

Bill Kendrick, March 2016

For the NOMAM 2016 contest

Purpose

A simple game that reminds you of the classic Atari arcade game Tempest, but fits in 10 lines of BASIC!

Objective

tenpest is an offensive-only game, which ends after a time limit runs out. Your goal is to get as high a score as you can, by blasting enemies when they're as far away as possible.

Requirements

Atari XL or XE computer (or 800 with Incognito board, I guess?), capable of running TurboBASIC XL — or an emulator — and a joystick.

Download

Controls

Use a joystick in port 1. Press left/right to move your blaster around the edge of the surface. Any enemies within the same segment as your blaster will be destroyed automatically.

Scoring

The further down the tube an enemy is when your blaster shoots it, the more points you receive. If the enemy is at the very edge, no points are awarded.

As you receive points, they're displayed in the text window at the bottom of the screen.

Game Over

Once time runs out, the game ends. Your final score will have already been visible on the screen. Type "RUN" and press [Return] to start a new game.

Code Breakdown

For each of the 10 lines of source code, the abbreviated version (which fits within 120 characters) is shown, immediately followed by an expanded version that's slightly more readable. Then, each individual command is shown, and its purpose is explained, using nested bullet lists (to show the code's structure within IF/ENDIF, FOR/NEXT, etc. blocks).

Set-up

10 POKE 559,0:DEG:DIM CX(12),CY(12),R(12),BA(5),BR(5),S$(3840):F.A=0TO11:CX(A)=COS(A*30):CY(A)=-SIN(A*30)
10 POKE 559,0:DEG:DIM CX(12),CY(12),R(12),BA(5),BR(5),S$(3840):FOR A=0 TO 11:CX(A)=COS(A*30):CY(A)=-SIN(A*30)

20 R(A)=20+RAND(20):N.A:GR.7:COL.1:CX=79:CY=40:Z=ADR(S$):DPOKE708,36032:PL.CX(0)*R(0)+CX,CY(0)*R(0)+CY:SC=DPEEK(88)
20 R(A)=20+RAND(20):NEXT A:GRAPHCIS 7:COLOR 1:CX=79:CY=40:Z=ADR(S$):DPOKE 708,36032:PLOT CX(0)*R(0)+CX,CY(0)*R(0)+CY:SC=DPEEK(88)

30 F.A=1TO11:DR.CX(A)*R(A)+CX,CY(A)*R(A)+CY:N.A:DR.CX(0)*R(0)+CX,CY(0)*R(0)+CY:PL.CX(0)*R(0)/8+CX,CY(0)*R(0)/8+CY
30 FOR A=1 TO 11:DRAWTO CX(A)*R(A)+CX,CY(A)*R(A)+CY:NEXT A:DRAWTO CX(0)*R(0)+CX,CY(0)*R(0)+CY:PLOT CX(0)*R(0)/8+CX,CY(0)*R(0)/8+CY

40 F.A=1TO11:DR.CX(A)*R(A)/8+CX,CY(A)*R(A)/8+CY:N.A:DR.CX(0)*R(0)/8+CX,CY(0)*R(0)/8+CY:POKE710,66:F.A=0TO11
40 FOR A=1 TO 11:DRAWTO CX(A)*R(A)/8+CX,CY(A)*R(A)/8+CY:NEXT A:DRAWTO CX(0)*R(0)/8+CX,CY(0)*R(0)/8+CY:POKE 710,66:FOR A=0 TO 11

50 PL.CX(A)*R(A)/8+CX,CY(A)*R(A)/8+CY:DR.CX(A)*R(A)+CX,CY(A)*R(A)+CY:N.A:A=0:F.I=0TO4:BA(I)=-1:N.I:MOVE SC,Z,3840
50 PLOT CX(A)*R(A)/8+CX,CY(A)*R(A)/8+CY:DRAWTO CX(A)*R(A)+CX,CY(A)*R(A)+CY:NEXT A:A=0:FOR I=0 TO 4:BA(I)=-1:NEXT I:MOVE SC,Z,3840

Main loop

60 MOVE Z,SC,3840:S=STICK(0):IF S=11:A=(A+1)MOD12:ELSE:IF S=7:A=A-1:IF A<0:A=11:END.:END.:END.:COL.2:GOS.1000
60 MOVE Z,SC,3840:S=STICK(0):IF S=11:A=(A+1) MOD 12:ELSE:IF S=7:A=A-1:IF A<0:A=11:ENDIF:ENDIF:ENDIF:COLOR 2:GOSUB 1000

70 F.I=0TO4:IF BA(I)=A:BA(I)=-1:Q=Q+(1-BR(I))*100:?Q:END.:IF BA(I)=-1:IF RAND(10)=0:BA(I)=RAND(12):BR(I)=0.03:END.:ELSE
70 FOR I=0 TO 4:IF BA(I)=A:BA(I)=-1:Q=Q+(1-BR(I))*100:? Q:ENDIF:IF BA(I)=-1:IF RAND(10)=0:BA(I)=RAND(12):BR(I)=0.03:ENDIF:ELSE

80 BR(I)=BR(I)+0.1:IF BR(I)>1:BA(I)=-1:ELSE:COL.3:GOS.2000:END.:END.:N.I:L=L+1:IF L=200:END:END.:GOTO 60
80 BR(I)=BR(I)+0.1:IF BR(I)>1:BA(I)=-1:ELSE:COLOR 3:GOSUB 2000:ENDIF:ENDIF:NEXT I:L=L+1:IF L=200:END:ENDIF:GOTO 60

Blaster-drawing routine

1000 A2=(A+1)MOD12:R1=R(A):R2=R(A2):PL.CX(A)*R1+CX,CY(A)*R1+CY:DR.CX,CY:DR.CX(A2)*R2+CX,CY(A2)*R2+CY:RET.
1000 A2=(A+1) MOD 12:R1=R(A):R2=R(A2):PLOT CX(A)*R1+CX,CY(A)*R1+CY:DRAWTO CX,CY:DRAWTO CX(A2)*R2+CX,CY(A2)*R2+CY:RETURN

Enemy-drawing routine

2000 BR=BR(I):M=BA(I):R=R(M)*BR:A2=(M+1)MOD12:R2=R(A2)*BR:PL.CX(M)*R+CX,CY(M)*R+CY:DR.CX(A2)*R2+CX,CY(A2)*R2+CY:RET.
2000 BR=BR(I):M=BA(I):R=R(M)*BR:A2=(M+1) MOD 12:R2=R(A2)*BR:PLOT CX(M)*R+CX,CY(M)*R+CY:DRAWTO CX(A2)*R2+CX,CY(A2)*R2+CY:RETURN

Contact