--- title: "Slalom" id: 57428 type: "computer_media" slug: "slalom" url: "http://localhost/computer_media/slalom/" markdown_url: "http://localhost/computer_media/slalom.md" published_at: "2024-10-05T13:18:31+00:00" modified_at: "2026-03-30T21:18:00+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/229_Sla.png" excerpt: "Guide a moving dot through six randomly placed gates using just two keys — one missed gap ends the run instantly in this compact slalom game." 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: 56736 title: "Timex Sinclair Public Domain Library Tape 1005" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1005/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/229_Sla.png" media_type_tags: "Game" --- # Slalom This ZX81/TS1000 BASIC program implements a horizontal slalom skiing game in which the player steers a dot through six gates displayed across the screen. Gates are randomly positioned using an array of six Y-coordinates, each drawn as two pixels with a one-pixel gap between them. The player uses keys “7” and “6” to move the dot up and down respectively, with movement handled by subtracting the INKEY$ comparisons directly in arithmetic. Line 100 tests gate collisions using a compact Boolean expression: `30 AND V>=C(B/10) AND V<=C(B/10)+1` routes to line 110 (continue) or line 138 (a non-existent line, triggering a BASIC error/stop) depending on whether the dot passes cleanly through the gate gap. *** ## Program Analysis ### Program Structure The program is divided into three logical phases: setup, play loop, and restart. 1. **Setup (lines 10–70):** Dimensions array `C(6)`, clears the screen, then randomly places six gates. Each gate occupies column `A*10` and consists of two pixels at `C(A)-1` and `C(A)+2`, leaving a one-pixel gap at `C(A)` and `C(A)+1` for the player to pass through. 2. **Play loop (lines 80–150):** Iterates `B` from 3 to 63 (the horizontal pixel range), moving the player dot column by column. At every gate column (`B/10` is an integer), a collision check is performed. 3. **Restart (line 160):**`RUN` loops the game indefinitely with fresh random gates each time. ### Gate Drawing Each gate is drawn with two `PLOT` calls: one at `C(A)-1` (below the gap) and one at `C(A)+2` (above the gap). This leaves exactly two pixels of clear passage at Y positions `C(A)` and `C(A)+1`, which is the window the player’s dot must occupy. Gate X positions are `10, 20, 30, 40, 50, 60`, all within the ZX81’s 64×44 pixel display. ### Collision Detection Technique Line 100 uses a compact boolean arithmetic trick for gate collision: `100 IF B/10=INT(B/10) THEN GOTO 80+(30 AND V>=C(B/10) AND V<=C(B/10)+1)` On the ZX81, boolean expressions evaluate to 1 (true) or 0 (false). The sub-expression `30 AND V>=C(B/10) AND V<=C(B/10)+1` evaluates to 30 if the player is inside the gate gap, or 0 if not. This is added to 80, producing either `GOTO 110` (pass — continue plotting) or `GOTO 80`… wait, actually `80+0=80` sends execution back to line 80 which resets `V` to `C(1)`, effectively resetting the player to the first gate’s Y position rather than stopping play. When the player is safely through the gap, the target is `80+30=110`, which falls through to the next line normally. ### Player Movement Line 130 handles input using arithmetic on INKEY$ comparisons: `LET V=V+(INKEY$="7")-(INKEY$="6")` This is a standard ZX81 BASIC idiom. If “7” is held, the boolean true (1) is added, moving the dot up. If “6” is held, 1 is subtracted, moving it down. Both keys pressed simultaneously cancel out. There is no boundary clamping, so the dot can wander off-screen. ### Animation Method The dot is animated by plotting at the new position (`PLOT B,V`) and then unplotting the previous position (`UNPLOT B,X`) using the saved value `X=V`. Since `B` advances by one pixel per iteration, this produces a smooth single-pixel trail-free movement across the screen. ### Variable Summary | Variable | Role | | --- | --- | | `C(6)` | Array of gate Y-coordinates | | `A` | Gate index (1–6) during setup | | `B` | Current horizontal pixel column (3–63) | | `V` | Current vertical position of player dot | | `X` | Previous vertical position (for UNPLOT) | ### Notable Anomalies - When a gate is missed (`GOTO 80`), rather than ending the game, the player’s Y position is silently reset to `C(1)` (the first gate’s Y value) and the loop continues. This may be an unintended consequence of the `80+0` arithmetic rather than a deliberate design choice — a “game over” would more typically jump to a non-existent line. - Gate Y-coordinates range from 13 to 25 (`INT(RND*12)+14`), keeping them well within the lower half of the 44-pixel-high display. - The play loop starts at `B=3`, giving the player a small lead before the first gate at column 10. ## Source Code ``` 5 REM "SLALOM" 10 DIM C(6) 20 CLS 30 FOR A=1 TO 6 40 LET C(A)=INT (RND*12)+14 50 PLOT A*10,C(A)-1 60 PLOT A*10,C(A)+2 70 NEXT A 80 LET V=C(1) 90 FOR B=3 TO 63 100 IF B/10=INT (B/10) THEN GOTO 80+(30 AND V>=C(B/10) AND V<=C(B/10)+1) 110 PLOT B,V 120 LET X=V 130 LET V=V+(INKEY$="7")-(INKEY$="6") 140 UNPLOT B,X 150 NEXT B 160 RUN 170 SAVE "1022%9" 180 RUN ```