--- title: "Phasor" id: 57336 type: "computer_media" slug: "phasor" url: "http://localhost/computer_media/phasor/" markdown_url: "http://localhost/computer_media/phasor.md" published_at: "2024-10-04T08:24:52+00:00" modified_at: "2026-04-03T07:58:36+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/09/184_Phas.png" excerpt: "A space shooter where timing your keypress to the alien's screen column is the only weapon — and three difficulty levels keep the pressure rising." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Arcade" slug: "arcade" taxonomy: "genre" url: "http://localhost/type/arcade/" - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 56735 title: "Timex Sinclair Public Domain Library Tape 1004" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1004/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/09/184_Phas.png" article_media: - id: 8618 title: "Program Printout: Phasor" type: "article" url: "http://localhost/article/program-printout-phasor/" media_type_tags: "Arcade, Game" --- PHASOR is a space shooter game in which the player fires phasors at aliens moving across a 26-column play field, managing both a shield count and a phasor count across three difficulty levels. The player fires by pressing the key whose column code matches the alien’s position, detected via CODE INKEY$-38 compared to R6+1. Difficulty controls the inner loop count INP, calculated as (1/INT X)*25, tightening reaction time at higher levels; mid-game rank promotions (Falcon, Hawk, Eagle) are triggered at score thresholds 1050, 2100, and 2850. The fire-explosion sequence in the GOSUB 1000 routine uses layered PRINT AT statements with block graphics to animate an expanding blast, and FAST/SLOW toggling inside the loop creates a flash effect. Reaching zero shields triggers the game-over starfield routine at line 8000, which randomly scatters dot and block-graphic characters across a cleared screen. *** ## Program Analysis ### Program Structure The program is divided into clearly separated functional blocks: 1. Lines 1–18: Initialisation, difficulty selection, and rank-string assignment. 2. Lines 20–180: Main screen setup — starfield rendering, score/status panel drawing. 3. Lines 200–290: Main game loop — alien placement, firing detection, alien movement. 4. Lines 300–380: Hit subroutine — score update and hit animation. 5. Lines 500–600: Miss/alien-fire subroutine — shield deduction and hit reporting. 6. Lines 1000–1240: Explosion graphics subroutine with FAST/SLOW flash effect. 7. Lines 2010–2030: Game-over restart prompt. 8. Lines 7000–7030: Rank promotion congratulations display. 9. Lines 8000–8100: Game-over starfield clear and redraw routine. ### Difficulty and Timing Mechanics Difficulty level `X` (1, 2, or 3) drives the inner loop count `INP` via `LET INP=(1/INT X)*25`, yielding 25, 12, or 8 iterations respectively. Each iteration gives the player one polling opportunity, so higher difficulty dramatically shrinks reaction time. At line 205, once `I` reaches 150, `INP` is decremented by 1 each cycle (unless already at 1), providing an escalating challenge even within a chosen difficulty level. ### Firing Detection Idiom The core shooting mechanic at line 250 uses: `IF CODE INKEY$-38=R6+1 AND P<>0 THEN GOSUB 300` On the ZX81/TS1000 keyboard layout, the digit keys ‘0’–’9′ have character codes 28–37, and the letter keys begin at 38 (‘A’=38, ‘B’=39, …). Subtracting 38 maps key ‘A’ to 0, ‘B’ to 1, and so on across the 26-column display. Since `R6` is an alien column 0–23 and the comparison is against `R6+1`, there is a consistent off-by-one offset built into the mapping, meaning the player must press the key one position to the right of the alien’s column. ### Rank Promotion System Three rank titles are assigned in lines 16–18 using cascading `IF` statements. The ranks escalate with both score and difficulty: | Rank | Conditions | | --- | --- | | Falcon | X=1 (any score) | | Hawk | X=2, or X=1 and S≥2100 | | Eagle | X=3, or X=2 and S≥2100, or X=1 and S≥2850 | The congratulations subroutine at line 7000 is triggered at line 20 when the score equals exactly 1050, 2100, or 2850 — relying on score increments of exactly 10 per hit, so these thresholds are always reachable. ### Screen Layout and Block Graphics The play field occupies columns 0–25 across rows 0–20, while columns 26–31 form a status panel. The starfield is built in two passes: lines 45–90 scatter 80 inverse-space characters (`"%."`) as background stars, then lines 95–130 place 10 block-graphic `"\:'"` (▛) characters as larger star objects. The alien is displayed as `"%(%0%)"` (inverse parentheses around an inverse zero). The explosion subroutine (lines 1000–1240) prints expanding rings of block graphics across rows 10–20 at fixed columns, producing a symmetrical blast pattern centred at column 11. ### FAST/SLOW Flash Effect Inside the explosion loop (lines 1015–1240), `FAST` and `SLOW` are toggled on consecutive lines within a `FOR L=1 TO 5` loop. This causes the display to flicker between the two rendering modes, producing a visible flash effect that accompanies the explosion animation without requiring any additional graphics work. ### Alien Random Fire A random value `R8 = INT(RND*30)+1` is rolled each inner-loop iteration. If `INKEY$=""` (no key pressed) and `R8=1`, the alien fires via `GOSUB 525`. The 1-in-30 probability makes alien fire relatively rare but unpredictable. The alien-hit subroutine further rolls `R7 = INT(RND*3)+1`; only when `R7=1` does the alien shot actually hit the player and reduce `SH` (shields). ### Game-Over Starfield Routine When shields reach zero, subroutine 8000 clears the screen row by row in FAST mode, then in SLOW mode randomly populates it with either a period (`B$="."`) or a block-graphic dot (`B$="\. "`, i.e. ▖) at 80 random positions, generating a sparse star-debris effect as the final display. ### Notable Bugs and Anomalies - Line 241: `IF I=150 THEN GOTO 11` — line 11 does not exist. This causes the program to jump to the next higher line, which is line 12 (`LET P=20`). This appears to be an intentional or accidental partial game reset when the escalation counter reaches 150, resetting phasors but not score or shields. - Line 580: `IF SH<0 THEN GOTO 1000` — the condition is *less than* zero, but `SH` is decremented at line 570 after a shield check. If `SH` was 0 before decrement, it becomes -1, which correctly triggers the game-over path. However, the display at line 590 (`PRINT AT 12,30;SH`) is skipped in this case, leaving the shield count display unchanged. - Line 170: The shield and phasor count labels are printed character-by-character with individual `AT` clauses, and the initial counts (5 and 20) are hardcoded as string literals rather than read from `SH` and `P`. This means if the initial values were changed, the display would not reflect them. - Line 8: `LET INP=(1/INT X)*25` — if `X=0` were allowed, this would cause a division-by-zero error. The guard at line 7 uses `X<0` rather than `X<1`, so entering 0 would pass the check and crash at line 8. ## Source Code ``` 1 SAVE "1018%4" 2 CLS 3 PRINT "PHASOR";AT 1,0;"''''''''''''",, 4 PRINT "WHAT LEVEL OF DIFFICULTY?",,, 5 PRINT "(1,2,OR 3)" 6 INPUT X 7 IF X>3 OR X<0 THEN GOTO 6 8 LET INP=(1/INT X)*25 9 CLS 10 LET S=0 11 LET SH=5 12 LET P=20 13 LET I=0 15 CLS 16 IF X=1 THEN LET A$=" FALCON" 17 IF X=2 OR X=1 AND S=2100 THEN LET A$=" HAWK" 18 IF X=3 OR X=2 AND S=2100 OR X=1 AND S=2850 THEN LET A$=" EAGLE" 20 IF S=1050 OR S=2100 OR S=2850 THEN GOSUB 7000 25 FOR N=1 TO 21 30 PRINT "% % % % % % % % % % % % % % % % % % % % % % % % % % " 40 NEXT N 45 FOR M=1 TO 80 50 LET R1=INT (RND*20) 60 LET R2=INT (RND*26) 80 PRINT AT R1,R2;"%." 90 NEXT M 95 FOR K=1 TO 10 100 LET R3=INT (RND*20) 110 LET R4=INT (RND*26) 120 PRINT AT R3,R4;":'" 130 NEXT K 135 LET Q=38 140 LET Z=0 145 PRINT AT 21,Z;CHR$ Q 150 LET Q=Q+1 155 LET Z=Z+1 156 IF Z=26 THEN GOTO 165 160 GOTO 145 165 PRINT AT 2,26;"SCORE:";AT 3,26;S 170 PRINT AT 6,28;"S";AT 7,28;"H";AT 8,28;"I";AT 9,28;"E";AT 10,28;"L";AT 11,28;"D";AT 12,28;"S";AT 12,29;"=";AT 12,30;"5" 180 PRINT AT 14,28;"P";AT 15,28;"H";AT 16,28;"A";AT 17,28;"S";AT 18,28;"O";AT 19,28;"R";AT 20,28;"S";AT 20,29;"=";AT 20,30;"20" 200 REM %W%A%R%P%-%I%N% % % % % % % % % % % % % % % % 205 IF I=150 AND INP<>1 THEN LET INP=INP-1 210 LET R5=INT (RND*20) 220 LET R6=INT (RND*24) 230 FOR C=1 TO INP 235 LET R8=INT (RND*30)+1 240 PRINT AT R5,R6;"%(%0%)" 241 IF I=150 THEN GOTO 11 245 IF P=0 THEN GOSUB 500 250 IF CODE INKEY$-38=R6+1 AND P<>0 THEN GOSUB 300 260 IF INKEY$<>"" THEN GOSUB 500 265 IF INKEY$="" AND R8=1 THEN GOSUB 525 270 NEXT C 280 PRINT AT R5,R6;"% %.% " 290 GOTO 210 300 REM %H%I%T% % % % % % % % % % % % % % % % % % % % 310 LET P=P-1 320 LET S=S+10 325 LET I=I+10 330 PRINT AT 3,26;" ";AT 3,26;S 335 PRINT AT 20,30;" ";AT 20,30;P 340 FOR F=1 TO 5 350 PRINT AT R5,R6;"% % % " 360 PRINT AT R5,R6;"%(%0%)" 370 NEXT F 375 PRINT AT R5,R6;"% % %." 380 GOTO 200 500 REM %M%I%S%S% % % % % % % % % % % % % % % % % % % 510 IF P<>0 THEN LET P=P-1 520 PRINT AT 20,30;" ";AT 20,30;P 525 FOR J=1 TO 5 530 PRINT AT 0,0;"%A%L%I%E%N% %F%I%R%E%S" 535 NEXT J 540 LET R7=INT (RND*3)+1 545 PRINT AT 0,0;"% %.% %.% % :.%.% % % " 546 GOSUB 1000 550 IF R7<>1 THEN RETURN 555 FOR Y=1 TO 5 560 PRINT AT 0,0;"%A%L%I%E%N% %H%I%T%S" 565 PRINT AT 0,0;"% % % % % % :.% % % " 566 NEXT Y 570 LET SH=SH-1 580 IF SH<0 THEN GOTO 1000 590 PRINT AT 12,30;SH 600 RETURN 1000 REM %F%I%R%E% %G%R%A%P%H%I%C%S% % % % % % % % % % 1005 PRINT AT R5,R6;"% % % " 1010 PRINT AT 10,11;"%(%0%)" 1015 FOR L=1 TO 5 1020 PRINT AT 11,11;":.";TAB 13;".:" 1030 PRINT AT 11,11;"% ";TAB 13;"% " 1040 PRINT AT 12,10;" ";TAB 14;" " 1050 PRINT AT 12,10;"% ";TAB 14;"% " 1060 PRINT AT 13,8;" ";TAB 15;" ";AT 14,8;" ";TAB 15;" " 1070 PRINT AT 13,8;"% %.";TAB 15;"%.%.";AT 14,8;":'% ";TAB 15;"% % " 1080 PRINT AT 15,4;" ";TAB 17;" ";AT 16,4;" ";TAB 17;" ";AT 17,4;" ";TAB 17;" ";AT 18,4;" ";TAB 17;" " 1090 PRINT AT 15,4;"% %.% % ";TAB 17;"% % % % ";AT 16,4;"% % % % ";TAB 17;"% %.%.% ";AT 17,4;"% % % % ";TAB 17;":'% % % ";AT 18,4;"% % % % ";TAB 17;"% % % % " 1100 PRINT AT 19,0;" ";TAB 21;" ";AT 20,0;" ";TAB 21;" " 1110 PRINT AT 19,0;"% % %.% ";TAB 21;"% %.%.% % ";AT 20,0;"% % %.";TAB 21;"% %.% %.% " 1111 IF R7<>1 THEN PRINT AT 10,11;"%.%.% " 1115 IF R7<>1 THEN RETURN 1200 FOR F=1 TO 10 1210 FAST 1220 SLOW 1230 NEXT F 1240 NEXT L 1242 PRINT AT 10,11;"% % %." 1245 IF SH<>0 THEN RETURN 1247 GOSUB 8000 2010 PRINT AT 0,0;"HIT ""R"" FORNEW GAME." 2020 IF INKEY$="R" THEN RUN 2 2030 GOTO 2020 7000 PRINT AT 1,1;"CONGRATULATIONS";AT 2,1;"''''''''''''''''''''''''''''''";AT 4,1;"WE HEREBY AWARD YOU THE TITLE";AT 5,1;"OF: ""STAR";A$;""".";AT 8,1;"KEEP ON FIGHTING, COWBOY." 7010 PAUSE 300 7020 CLS 7030 RETURN 8000 REM %E%N%D% % % % % % % % % % % % % % % % % % % % 8010 FAST 8015 FOR U=0 TO 20 8020 PRINT AT U,0;" " 8025 NEXT U 8030 SLOW 8035 FOR U=1 TO 80 8040 LET R9=INT (RND*4)+1 8050 IF R9>1 THEN LET B$="." 8060 IF R9=1 THEN LET B$=". " 8070 PRINT AT INT (RND*20),INT (RND*26);B$ 8080 NEXT U 8100 RETURN ```