Torpedo

This file is part of and Synchro-Sette April 1983. Download the collection to get this file.
Date: April 1983
Type: Program
Platform(s): TS 1000
Tags: Game

This program implements a torpedo-firing game where a submarine sprite moves across the screen and the player fires torpedoes by pressing keys numbered 1–5, each corresponding to a different firing angle calculated via the TAN function. The submarine is represented using a string of ZX81 block graphics stored in A$, and collision detection compares the torpedo’s Y position (derived from the tangent trajectory) against the submarine’s screen column. A high-score table tracking the best player name and score persists across rounds within the same session, resetting only on a full restart. The game limits each round to 20 combined movement/fire events (variable T) before displaying the score as a percentage of hits to total shots.


Program Analysis

Program Structure

The program is organised into a main loop, two subroutines, and an end-of-round section:

  1. Lines 1–15: Initialisation — clear screen, reset variables, ask for player name, prime turn counter T=-1.
  2. Lines 20–90: Main game loop — reset score display, call submarine movement subroutine (GOSUB 100), then call key/fire subroutine (GOSUB 200), repeat.
  3. Lines 100–160: Submarine movement — decrements column C by a random fraction, wraps back to line 30 when the sub reaches the left edge, draws the submarine sprite and a sea-floor dotted line.
  4. Lines 200–290: Input and torpedo trajectory — reads a keypress, validates it, computes a TAN-based trajectory, plots/unplots the torpedo path, calls collision detection.
  5. Lines 300–399: Collision detection — checks whether the torpedo Y-coordinate at a given X matches the submarine’s position.
  6. Lines 400–470: Hit animation — flashes the submarine position with alternating block-graphic patterns in a loop, then animates the sub sinking downward before returning to line 30.
  7. Lines 500–560: End-of-round scoring — displays hits and percentage score, updates high score if beaten, pauses, clears, and loops back for the next player.
  8. Lines 9998–9999: SAVE the program (with inverse-O in the filename as a cosmetic touch) and GOTO 0 to restart the system after saving.

Submarine Sprite

The submarine graphic is stored in A$ at line 5 as a string of ZX81 block graphics and spaces. The string contains hull, conning tower, and wake characters, printed at row 5 using PRINT AT 5,C;A$. The dotted line at row 7 represents the sea floor or water surface and is redrawn each movement step.

Torpedo Trajectory Calculation

Lines 200–280 implement the firing mechanic. The player presses a key whose CODE falls between 31 and 36 (ZX81 internal codes for keys 15 shifted). The angle is computed as:

M = TAN((10 * VAL B$) * 2 * PI / 360)

This converts VAL B$ (1–5) multiplied by 10 into degrees (10°, 20°, 30°, 40°, 50°) and takes the tangent, giving the slope of the torpedo’s path. The torpedo is then plotted and immediately unplotted (PLOT/UNPLOT at lines 250–260) as it steps across X from 1 to 63, creating a moving dot effect. Firing is also gated by C$=B$ (line 210) to prevent the same key being used twice consecutively.

Collision Detection

The subroutine at lines 300–320 computes the torpedo’s integer Y position (A = INT(INT(M*X)+0.5)) and the submarine’s integer column position (B = INT(INT(C*2)+0.5)). A hit is registered if A is 32 or 33 (the vertical screen rows corresponding to the submarine) and B is within ±2 columns of X. The use of double INT(...+0.5) is an unconventional rounding idiom — the inner INT is redundant since the argument is already the result of arithmetic, making the outer INT(...+0.5) a standard rounding-to-nearest.

Turn Limit and Scoring

The variable T counts turns and is incremented at line 35 (each movement step) and line 215 (each fire event). When T >= 20, the game ends and jumps to line 500. The final score is displayed as a percentage: INT(100*S/T), rewarding accuracy over volume of fire. The high score (HS) and high-score holder’s name (N$) persist in memory across rounds within the same session.

Hit Animation

Lines 400–420 loop 10 times, printing alternating pairs of block-graphic patterns at the submarine’s position to simulate an explosion flash. Eight distinct AT clauses appear within a single PRINT statement at line 410. Lines 440–460 then animate the sub sinking by printing a fragment at successive rows while clearing the previous row, stepping from row 5 down to row 21.

Key Validation

Line 210 checks three conditions with OR: the key code must be ≥ 31, ≤ 36, and not equal to the previously pressed key (C$ = B$). Because all three are combined with OR, the logic is: if the code is out of range or it is a repeat press, do nothing. This effectively blocks both invalid keys and repeated use of the same angle in consecutive moves, adding a tactical element.

Notable Techniques and Anomalies

  • Starting T at -1 (line 15) rather than 0 compensates for the T=T+1 at line 35 executing before the first meaningful turn.
  • The SAVE "TORPED%O" at line 9998 uses the ZX81 inverse-video escape %O to render the final letter of “TORPEDO” in inverse video in the filename.
  • GOTO 9999 / GOTO 0 at the end triggers a system restart after saving, a common ZX81 idiom.
  • The PLOT/UNPLOT pair (lines 250–260) in the torpedo loop creates a single moving pixel without leaving a trail, using the ZX81’s pixel commands rather than character-cell printing.
  • The check CODE B$ < 31 OR CODE B$ > 36 uses ZX81 internal character codes, where digit keys 1–5 have codes 29–33 in some ROM versions; the exact range used here may be platform-specific and worth verifying against the target hardware’s key code table.

Content

Appears On

Cassette to accompany the April 1983 issue of Synchro-Sette.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 CLS 
   2 LET C$=""
   3 LET HS=0
   5 LET A$="):                               ..:!!. -"
  10 PRINT ,,"CURRENT PLAYER 'S NAME?"
  12 INPUT F$
  13 PRINT AT 1,0;F$;" IS NOW PLAYING.                "
  15 LET T=-1
  20 LET S=0
  30 PRINT AT 5,2;"   "
  35 LET T=T+1
  36 IF T>=20 THEN GOTO 500
  40 LET C=28
  50 GOSUB 100
  60 GOSUB 200
  90 GOTO 50
 100 LET C=C-RND
 110 IF C<2 THEN GOTO 30
 120 PRINT AT 5,C;A$
 130 PRINT AT 7,0;". . . . . . . . . . . . . . . ."
 160 RETURN 
 200 LET B$=INKEY$
 210 IF CODE B$<31 OR CODE B$>36 OR C$=B$ THEN RETURN 
 212 LET C$=B$
 215 LET T=T+1
 216 IF T>=20 THEN GOTO 500
 220 LET M=(TAN ((10*VAL B$)*2*PI/360))
 230 FOR X=1 TO 63 STEP 2
 240 IF M*X>43 THEN RETURN 
 250 PLOT X,M*X
 260 UNPLOT X,M*X
 270 GOSUB 300
 280 NEXT X
 290 RETURN 
 300 LET A=INT (INT (M*X)+.5)
 310 LET B=INT (INT (C*2)+.5)
 320 IF (A=32 OR A=33) AND (B>=X-2) AND (B<=X+1) THEN GOTO 400
 399 RETURN 
 400 FOR N=1 TO 10
 410 PRINT AT 5,C-1;"@@##@@##";AT 6,C-1;"##@@##@@";AT 5,C-1;"!!!!!!!!";AT 6,C-1;";;;;;;;;";AT 5,C-1;";;;;;;;;";AT 6,C-1;"!!!!!!!!";AT 5,C-1;"~~~~~~~~";AT 6,C-1;",,,,,,,,";AT 5,C-1;"    ";AT 6,C-1;"    "
 420 NEXT N
 430 LET S=S+1
 440 FOR N=5 TO 21
 450 PRINT AT N,C-1;",,;;,,,,";AT N-1,C-1;"    "
 460 NEXT N
 470 GOTO 30
 500 PRINT AT 21,0;S;" SUBS TORPEDOED - SCORE = ";INT (100*S/T)
 510 IF S<=HS THEN GOTO 540
 520 LET N$=F$
 530 LET HS=S
 540 PRINT AT 19,0;N$;" - HIGH SCORE - ";HS
 550 PAUSE 200
 560 CLS 
 600 GOTO 10
 9998 SAVE "TORPED%O"
 9999 GOTO 0

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top