“New York By Night” is a Space Invaders-style arcade game in which the player controls a flying disc that destroys descending aliens before they can flatten New York City. The game uses three custom User Defined Graphics (UDGs) — characters A, m, and n/c — whose 8-byte shape data is POKEd directly into the UDG area at startup via READ/DATA statements. Gameplay difficulty is selectable from level 2 to 8 at startup, with the variable `le` controlling the depth range of alien drops. The skyline is generated procedurally using random PLOT calls, and collision detection relies on reading screen attribute bytes with ATTR rather than tracking sprite coordinates, a common Spectrum technique. Attack waves are tracked with variable `aw`, and the game ends when 27 aliens (`i=27`) have been destroyed, triggering a city-destruction animation sequence.
Program Analysis
Program Structure
The program is organized into two broad phases: an initialization/setup subroutine starting at line 620, called via GO SUB 620 at line 50, and the main game loop beginning at line 60. Control flow is largely managed through GO TO jumps rather than structured loops, which is typical for action games of this era.
- Lines 50–80: Call setup, set border/paper/ink, draw the random starfield and city skyline.
- Lines 90–120: Build the buildings column by column using UDG characters printed at incrementing column
z. - Lines 130–320: Main game loop — player movement, alien drop, collision detection, scoring.
- Lines 330–550: Hit/miss resolution, wave completion, alien landing animation, and transition logic.
- Lines 560–610: End-of-game sequence, “another game?” prompt, and port-cycling sound effect.
- Lines 620–870: Setup subroutine — variable initialization, UDG definition, instructions display, difficulty selection.
User Defined Graphics (UDGs)
Three UDG characters are defined by POKEing 8-byte shape data into the UDG memory area. The setup loop at line 660 reads 32 bytes from the DATA statements at lines 670–700 and POKEs them starting at USR "A", defining UDGs A and B (16 bytes each, covering characters A and B). A second loop at line 710 reads 16 bytes into USR "m", defining UDG m.
| UDG | Lines | Used as |
|---|---|---|
\a (A) | 670–680 | Alien sprite |
\c (C) / \b (B) | 670–700 | Building tiles / disc hit effect |
\m (m) | 720–730 | Player flying disc / ship animation |
\n (n) | (shares m block) | Ship animation frame |
Note that the DATA at lines 690 and 700 contain the bare variable name s rather than a numeric literal in two positions (e.g., 60,126,153,s,255,...). At READ time, s will hold whatever value it was last assigned in the loop (the previous byte read), so these act as self-referential fill values — an unintentional but functional quirk.
Collision Detection via ATTR
Rather than maintaining sprite coordinate tables, collision detection at line 280 reads the screen attribute byte at the player’s disc position using ATTR (x,y) and ATTR (x,y+1), checking for the value 71 (INK 7, PAPER 0, BRIGHT 1 — the building color). Similarly, line 290 checks ATTR (k,l)=68 to detect when a falling alien lands on the city floor. This attribute-based collision approach avoids any coordinate bookkeeping for the static city geometry.
Key BASIC Idioms and Techniques
- Variable reuse for zero-initialization: Line
630setsj=0, then reusesjto initializesc,bh, andkat lines640–650, saving tokenized bytes. - Building construction loop: Lines
90–120increment columnzand print UDG characters vertically using a FOR loop, building up the skyline one column at a time untilz>=29. - Port-cycling sound: Line
590loopsOUT 254,bfor b=0 to 224, producing a sweeping border-color sound effect by toggling the EAR/MIC bits of the ULA port. - Starfield generation: Line
70uses 50 random BRIGHT 0 PLOT calls with random INK colors to simulate a night sky behind the city. - Alien drop depth: The FOR loop at line
200runs from 0 to 21 rows, but the building height is influenced byle(difficulty level) at line100:21-INT(RND*le)varies how far down building columns are printed, making higher difficulty produce shorter (more exposed) buildings. - Comma-separated PRINT AT blanking: Line
400usesPRINT AT 5,0,,,,,,,,to overwrite multiple screen positions with empty strings in a single PRINT statement.
Bugs and Anomalies
- DATA with variable
s: Lines690and700includesas a DATA value. During READ,sholds the most recently read numeric value from the DATA list. This will produce valid (if unintended) sprite byte patterns, but the UDG shapes may not exactly match the original program’s intent ifswas meant to be a specific literal. - Wave counter logic: Line
130checksIF aw>=0, which is always true after initialization (aw starts at 1), sobhis unconditionally incremented on every pass through this line, potentially causing the player disc’s rowxto drift upward unexpectedly over many waves. - Line 20 is blank: An empty line at
20with no statement is syntactically harmless but occupies space in the program. - REM at line 40 contains a stray comment inside another line: Line
40begins with whitespace beforeREM, which is valid but unusual formatting likely from the original magazine typesetting. - UDG
\n(char n) is used at lines 430 and 540 but is never explicitly defined in a dedicated DATA/POKE block. It falls within the 16-byte block POKEd toUSR "m"(which covers m and n), so it does receive data — but this is implicit rather than clearly documented in the listing.
Game Flow Summary
After setup and the skyline drawing phase, the main loop repeatedly drops a single alien from the top of the screen while allowing left/right player movement via Q and P. A counter i tracks aliens that reach the city floor; reaching 27 triggers the “city destroyed” ending. A counter c tracks successful interceptions; reaching 20 advances the attack wave. After each wave, an animation sequence at lines 420–540 shows the aliens departing, and the game loops back to the skyline drawing phase for the next wave.
Content
Source Code
10 REM 'New York'
20
30 REM Taken from 'Popular Computing Weekly' 2/8 june 83
40 REM entered by G.F. Chambers
50 GO SUB 620
60 BORDER 0: PAPER 0: INK 7: CLS
70 LET z=0: FOR m=Z TO 50: INK INT (RND*6)+1: PLOT BRIGHT 0;INT (RND*255),175-INT (RND*125): NEXT m
80 PRINT #1; INK 6;" New York By Night": INK 7
90 LET z=z+INT (RND*1)+1
100 FOR u=20 TO (21-INT (RND*le)) STEP -1: PRINT AT u,z; INK 4; BRIGHT 1;"\d": PRINT AT u-1,z; INK 4; BRIGHT 1;"\c": NEXT u
110 IF z<=29 THEN GO TO 90
120 PRINT AT 21,0; BRIGHT 1; INK 4;" "
130 IF aw>=0 THEN LET bh=bh+1: LET x=19-bh: LET y=13
140 REM PRINT #1; INK 6;" New York By Night"
150 PRINT AT 5,9;"Attack Wave ";aw: LET c=0
160 PAUSE 100: PRINT AT 5,9;" "
170 PRINT AT 0,0; FLASH 1;"Score = ";sc: PRINT FLASH 1;"Level ";le: LET c=c+1
180 LET k=0
190 LET l=INT (RND*30)+1
200 FOR f=0 TO 21
210 PRINT AT x,y; INK 2; BRIGHT 1;"__"
220 IF INKEY$="q" AND y>1 THEN LET y=y-2: PRINT AT x,y+2;" "
230 IF INKEY$="p" AND y<28 THEN LET y=y+2: PRINT AT x,y-2;" "
240 PRINT AT k,l; BRIGHT 1;"\a"
250 PRINT AT k-1,l;" "
260 LET k=k+1
270 IF k=21 AND c>=20 THEN LET aw=aw+1: GO TO 380
280 IF ATTR (x,y)=71 OR ATTR (x,y+1)=71 THEN GO TO 330
290 IF f=20 AND ATTR (k,l)=68 THEN LET i=i+1: BEEP .03,30: BEEP .09,45: BEEP .06,20
300 IF i=27 THEN GO TO 360
310 NEXT f
320 GO TO 170
330 BEEP .07,10: PRINT AT x,y;"\b\b"
340 LET sc=sc+1
350 GO TO 170
360 PRINT AT k,l; BRIGHT 1;"\a": PRINT AT k-1,l;" ": PRINT AT 5,0; INK 2; BRIGHT 1; FLASH 1;"A sufficient amount of New York has been destroyed.The aliens are leaving "
370 PRINT AT 5,31;" ": PRINT AT 6,31;" ": PRINT AT 7,31;" "
380 IF i<>27 THEN PRINT AT 5,0; FLASH 1; INK 3;" Attack wave ";aw-1;" is completed, a mother ship will pick up the aliens-Prepare for the next attack wave",
390 FOR v=0 TO 350: NEXT v
400 PRINT AT 5,0,,,,,,,,
410 LET d=31
420 FOR w=1 TO 31: LET q=2: FOR r=20 TO 2 STEP -1
430 PRINT AT q,w-1;"\n\c\m"
440 IF w>=2 THEN PRINT AT q,w-2;" "
450 IF w>=31 THEN GO TO 510
460 IF ATTR (21,w)<>71 AND ATTR (21,w)<>7 AND ATTR (21,w)<>0 THEN NEXT w: PRINT AT r-1,w;"\a"
470 PRINT AT r,w;"\a"
480 IF r<=20 THEN PRINT AT r+1,w;" "
490 IF r=21 THEN BEEP .02,09: BEEP .05,45: BEEP .07,5
500 NEXT r: NEXT w
510 PRINT AT 2,29;" "
520 PRINT AT x,y;" ": LET h=4: FOR t=30 TO 0 STEP -1: PRINT AT h,t;" "
530 LET h=h+INT (RND*3-1)
540 INK (RND*7): PLOT BRIGHT 0;INT (RND*255),175-INT (RND*100): INK 7: PRINT AT h,t;"\n\c\m ": NEXT t
550 PRINT AT h,0;" ": IF i<>27 THEN PAUSE 20: GO TO 120
560 CLS
570 INPUT "Another game ? ";j$
580 IF j$<>"y" AND j$<>"n" THEN GO TO 570
590 FOR b=0 TO 224: OUT 254,b: NEXT b: PRINT AT 10,14;"OK": PAUSE 150
600 IF j$="y" THEN RUN
610 STOP
620 REM SETUP
630 LET aw=1: LET j=0: LET sc=j: LET bh=j
640 BORDER j: PAPER j: INK 7: CLS
650 LET i=j: LET c=i: LET k=i
660 RESTORE : FOR f=0 TO 31: READ s: POKE USR "A"+f,s: NEXT f
670 DATA 0,65,34,28,42,93,73,65
680 DATA 136,105,186,28,255,221,174,107
690 DATA 60,126,153,s,255,153,s,255
700 DATA 255,153,s,s,255,153,s,255
710 FOR f=0 TO 15: READ s: POKE USR "m"+f,s: NEXT f
720 DATA 128,224,88,87,254,248,192,128
730 DATA 1,7,26,234,127,31,3,1
740 PRINT """New York By Night"" is a typical"
750 PRINT '"invader game. The aim is to"
760 PRINT '"destroy the aliens which are"
770 PRINT '"attempting to flatten New York."
780 PRINT '"You are in control of a flying"
790 PRINT '"disc which has an antimatter"
800 PRINT '"surface. The aliens,on contact"
810 PRINT '"with your disc, self-destruct."
820 PRINT '"Your flight controls are:"
830 PRINT '"Q.....Left, P.....Right"
840 PRINT ''"Hit any key to start game"
850 INPUT "Level of Difficulty (2 to 8)";le: LET bh=le
860 IF le<2 OR le>8 THEN GO TO 850
870 RETURN
880 SAVE "New York" LINE 10
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.


