--- title: "London Bridge" id: 57344 type: "computer_media" slug: "london-bridge" url: "http://localhost/computer_media/london-bridge/" markdown_url: "http://localhost/computer_media/london-bridge.md" published_at: "2024-10-04T08:34:37+00:00" modified_at: "2026-04-03T07:58:35+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/09/192_LB.png" excerpt: "Guide your piece across a randomly generated bridge grid using numeric keypad directions — one wrong step and you're in the water!" 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: "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/192_LB.png" article_media: - id: 46376 title: "London Bridge" type: "article" url: "http://localhost/article/london-bridge/" - id: 8620 title: "Program Printout: London Bridge" type: "article" url: "http://localhost/article/program-printout-london-bridge/" media_type_tags: "Game" --- London Bridge is a single-player puzzle/strategy game in which the player navigates a piece across a 5-column grid of numbered cells, trying to reach the far side of a simulated bridge before falling into the water. The board is stored in a 66-element array A(), with cells 11–60 holding random values 1–5 (mapped to characters via CHR$(28+value)), and movement is controlled by a 1–9 numeric keypad-style direction input. The subroutine at line 500 uses integer/fractional decomposition of a cell index to calculate screen AT coordinates in a compact 5×10 grid layout, and the scoring system at line 900 rewards diagonal moves and colour-matched cell pairs. FAST/SLOW mode switching is used to speed up the initial board draw before returning to interactive pace. *** ## Program Analysis ### Program Structure The program is organised into a clear sequence of phases: 1. **Initialisation (lines 1–90):** Screen setup, array allocation, bridge art drawn with block graphics, WR value displayed. 2. **Board population (lines 90–135):** Cells 11–60 in array `A()` are filled with random integers 1–5; each is rendered on screen via `GOSUB 500`. 3. **Game loop (lines 140–440):** Player starts at cell N=8, chooses a direction 1–9, move validity is checked, score is updated, and the loop repeats. 4. **Outcome handlers (lines 600–819):** Falling into water (line 600) or crossing the bridge (line 800) both offer a replay prompt. 5. **Subroutines:** Display cell (500), update score (900), short delay (7000), end screen (6000). ### Array Layout Array `A(66)` serves multiple purposes. Index 1 accumulates the total score. Indices 11–60 represent the 5-column × 10-row bridge grid. Indices beyond 60 represent the far bank. A cell value ≤ 0 indicates an already-vacated or occupied cell; `-28` is used as a sentinel for the player’s current position (chosen so that `CHR$(28 + A(N))` would produce `CHR$(0)`, effectively a null/invisible character). ### Cell-to-Screen Coordinate Mapping (line 500) The subroutine at line 500 is the most technically interesting part of the program. Given a cell index stored in `M`, it decomposes the index into row and column using integer and fractional parts: - `LET M=(N-1)/5` — divides index into a mixed number where `INT M` is the row (0-based) and `M-INT M` is a fractional column selector (0, 0.2, 0.4, 0.6, 0.8 for columns 0–4). - `PRINT AT 5+INT M, 13+5*(M-INT M); A$` — maps row to screen row 5–14 and column fraction × 5 to screen columns 13, 14, 15, 16, 17. This single-subroutine approach avoids separate row/column variables and is a compact ZX81 idiom for two-dimensional array display. ### Movement Direction Encoding (lines 200–230) The direction input `DIR` is a digit 1–9 mimicking a numeric keypad layout. The decoding is: - `LET I=(INT DIR-1)/3` — produces a mixed number where `INT I` encodes the row delta (0=up, 1=same, 2=down) and `I-INT I` encodes the column delta. - `LET J=M-INT M+I-INT I` — the fractional parts are summed; the bounds check `J<0.1 OR J>1.4` catches moves off the left or right edges. - `LET N1=N+5*(INT I-1)+3*(I-INT I)-1` — computes the target cell index from the direction deltas. Direction 5 (centre key, no movement) is implicitly rejected by the `N1<6` guard or the `A(N1)<=0` check since it would land back on the player’s own cell. ### Scoring System (lines 390–410) Score for a valid move is calculated at line 390: - `10*(3-INT I)` rewards upward moves (INT I=0 gives 30, same row gives 20, downward gives 10). - `10*(2-INT I)*(1-INT I)` adds a bonus of 20 only for upward moves (both factors non-zero only when INT I=0). - If the destination cell’s value matches the randomly chosen drop-target cell (`A(N1)=A(DROP)`), the score is tripled (line 400). ### Drop Target Mechanic Each turn, `DROP` is a randomly selected occupied cell (lines 160–170). Its numeric value is displayed (line 180) as a hint. If the player moves onto the `DROP` cell, they fall into the water (line 370 → 600). This creates a risk/reward dynamic: the matching-value bonus encourages targeting cells that may be the trap. ### Display Techniques Inverse video characters (e.g. `%A%N%O%T%H%E%R%`) are used for the replay prompt, a common ZX81 technique for highlighted text without any attribute system. Block graphic characters (`\##`) form the bridge towers in the static art drawn at lines 35–80. The `FAST`/`SLOW` pair (lines 5/145) speeds up the initial board render. ### Delay Subroutine The subroutine at line 7000 is a simple `FOR Z=1 TO 30: NEXT Z` busy-wait loop used for pacing at the end-game message screens. The `WR=1700` variable displayed on screen (line 50) appears to be a high-score or world record placeholder; it is printed but never updated by game logic. ### Anomalies and Notes - Line 140 sets `N=8` as the starting cell, but cells 1–10 are never populated in the board-fill loop (lines 90–135 fill indices 11–60), so the player starts in an unpopulated region — this is intentional as the entry row of the bridge. - Lines 7500–7530 form a save/restart block that is never reached during normal play. - The `RAND 0` at line 10 seeds the random number generator with the system clock value, ensuring a different board each game. - The replay logic at lines 650–680 and 811–819 is duplicated almost identically, which could have been refactored into a subroutine. - Variable `WR` is set to 1700 and displayed but never compared against `A(1)`, so no actual high-score tracking occurs. ## Source Code ``` 1 REM "LONDON BRIDGE" 3 CLS 5 FAST 10 RAND 0 20 DIM A(66) 30 PRINT AT 2,9;"LONDON BRIDGE" 35 PRINT AT 3,8;"X-------------X" 40 LET WR=1700 50 PRINT AT 16,25;"WR=";WR;TAB 11;"## ##";TAB 0;"INPUT";TAB 1;"123";TAB 1;"4%56";TAB 1;"789" 55 PRINT AT 6,11;"#### % ####" 60 FOR I=1 TO 11 70 PRINT TAB 12;"## ##" 80 NEXT I 90 FOR N=11 TO 60 100 LET A(N)=INT (RND*5+1) 110 LET A$=CHR$ (28+A(N)) 120 LET M=(N-1)/5 130 GOSUB 500 135 NEXT N 140 LET N=8 145 SLOW 150 LET A(N)=-28 155 PRINT AT 20,20;"TO COLLAPSE" 160 LET DROP=INT (RND*(67-N)+N-6) 170 IF A(DROP)<=0 THEN GOTO 160 180 PRINT TAB 25;A(DROP) 190 INPUT DIR 200 LET I=(INT DIR-1)/3 205 LET M=(N-1)/5 210 LET J=M-INT M+I-INT I 220 LET N1=N+5*(INT I-1)+3*(I-INT I)-1 230 IF DIR<1 OR DIR>9 OR J<0.1 OR J>1.4 OR N1<6 THEN GOTO 190 235 IF A(N1)<=0 AND N1<=60 THEN GOTO 190 240 IF N1>60 THEN LET A(N1)=-28 250 LET A$=CHR$ (28+A(N)) 260 GOSUB 500 270 LET M=(N1-1)/5 280 LET A$=CHR$ (156+A(N1)) 290 GOSUB 500 300 PRINT AT 20,20;" ";TAB 25;" " 310 FOR J=1 TO 70 320 NEXT J 330 LET M=(DROP-1)/5 350 LET A$=" " 360 GOSUB 500 370 IF N1=DROP THEN GOTO 600 380 IF N1>60 THEN GOTO 800 390 LET SCORE=10*(3-INT I)+10*(2-INT I)*(1-INT I) 400 IF A(N1)=A(DROP) THEN LET SCORE=SCORE*3 410 GOSUB 900 420 LET A(DROP)=0 430 LET N=N1 440 GOTO 155 500 PRINT AT 5+INT M,13+5*(M-INT M);A$ 510 RETURN 600 PRINT AT 20,16;"YOU HAVE FALLEN";TAB 18;"IN THE WATER" 650 PRINT AT 0,0;"%A%N%O%T%H%E%R% %T%R%Y%?%? (1=YES/0=NO)" 655 INPUT CHO 657 GOSUB 7000 660 IF CHO<0 OR CHO>1 THEN GOTO 655 668 IF CHO=1 THEN CLS 670 IF CHO=1 THEN RUN 680 IF CHO=0 THEN GOSUB 6000 800 LET SCORE=1000 810 GOSUB 900 811 PRINT AT 0,0;"%A%N%O%T%H%E%R% %T%R%Y%?%? (1=YES/0=NO)" 813 INPUT CHO 814 GOSUB 7000 815 IF CHO<0 OR CHO>1 THEN GOTO 813 817 IF CHO=1 THEN CLS 818 IF CHO=1 THEN RUN 819 IF CHO=0 THEN GOSUB 6000 900 LET A(1)=A(1)+SCORE 910 PRINT AT 11,22;"SCORE ";SCORE;" " 920 PRINT AT 13,22;"TOTAL ";A(1) 930 RETURN 6000 GOSUB 7000 6020 CLS 6030 PRINT AT 11,10;"%T%H%A%N%K% %Y%O%U" 6050 GOSUB 7000 6060 PRINT AT 11,9;"%C%O%M%E% %A%G%A%I%N" 6070 GOSUB 7000 6090 CLS 6100 STOP 7000 FOR Z=1 TO 30 7003 NEXT Z 7005 RETURN 7500 STOP 7510 CLEAR 7520 SAVE "1019%2" 7530 RUN ```