--- title: "Snaker" id: 71410 type: "computer_media" slug: "snaker" url: "http://localhost/computer_media/snaker/" markdown_url: "http://localhost/computer_media/snaker.md" published_at: "2026-09-09T08:59:54+00:00" modified_at: "2026-09-09T08:59:55+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/09/snaker.png" excerpt: "Guide a growing snake around a dot-filled playfield, racing the clock while dodging your own body in this attribute-based collision game with machine code sound." 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 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" basic: - name: "User Defined Graphics (UDG)" slug: "user-defined-graphics-udg" taxonomy: "basic" url: "http://localhost/basic/user-defined-graphics-udg/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Arcade" slug: "arcade" taxonomy: "genre" url: "http://localhost/type/arcade/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Snaker%20(198x)(van%20Vuren%2C%20M.F.)(TS2068)(UK)(Program).zip" tsrun_member: "Snaker (198x)(van Vuren, M.F.)(TS2068)(UK)(Program).tap" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/09/snaker.png" media_type_tags: "Arcade" --- # Snaker Snaker is a snake-movement game where the player steers a growing snake around a playfield, eating dots while avoiding collisions with the snake’s own body and managing a countdown timer. The playfield is generated with randomly placed food dots using INK, PAPER, and FLASH attributes, and collision detection relies on reading screen attributes via the ATTR function rather than tracking object positions in arrays. Two custom UDG characters are defined—one for the snake body and one for the food dots—using POKE USR with bitmap data read from DATA statements. A 55-byte machine code routine is loaded into RAM at address 65200 via POKE, called through USR, and handles sound effects (writing to port 254) and screen operations using direct Z80 instructions. The game tracks waves, score accumulation based on remaining time and wave number, and maintains a top-10 high score table with four-character initials, stored in arrays across sessions within a single run. *** ### Program Structure The program is organized into functional blocks across its line numbers. Lines `20`–`27` form an initialization routine: setting screen attributes, defining UDGs, poking machine code, and seeding the high score table. Lines `1`–`9` are the core game loop handling movement, collision, and display. Lines `10`–`13` generate the playfield and advance the wave. Lines `14`–`19` handle death, the high score screen, and the instructions screen. Line `30` is a cleanup/quit routine, and lines `35`, `110`, and `9990` form a tape-loading subroutine. ### UDG Definition Two UDG characters are defined in lines `21`–`23`. The program reads each character name (`"\\o"` for the snake body, a filled circle shape; `"\\a"` for the food dot, a smaller square) and eight bytes of bitmap data, then POKEs them into `USR b$`—the standard Spectrum method for writing UDG pixel patterns. This allows the playfield and snake to use readable, distinctive glyphs rather than standard character set symbols. ### Machine Code Routines Two machine code entry points are embedded at addresses `65200` and `65232` within a 55-byte block poked in line `24` from DATA at line `25`. Both are invoked via `USR` assigned to a dummy variable `u`. The routine at `65200` appears to produce a sound effect by writing to I/O port 254 (`OUT 254`, opcode `D3 FE`), looping with a counter. The routine at `65232` is called during normal snake movement and food consumption. Because USR returns a value, assigning it to `u` is the standard BASIC idiom for calling machine code as a statement without losing the return value. ### Collision Detection via ATTR Rather than maintaining a full collision map or checking coordinate arrays, the game uses `ATTR (x,y)` to read the screen attribute byte at the snake’s new head position. A result of `242` identifies a food dot cell (INK 2, PAPER 6, FLASH 1, BRIGHT 0 encodes to this value), while `67` identifies the snake’s own body (INK 3, PAPER 0 encodes accordingly). This is a compact and efficient technique that offloads collision state entirely to the display file. ### Snake Position Tracking The snake’s segment positions are stored in parallel arrays `x()` and `y()`, dimensioned to 1005 elements each at line `2`. The variable `a` is an index that advances by 2 each step (line `5`), storing both a midpoint and the new head. The tail is erased by printing a space at position `x(a-l), y(a-l)`, where `l` tracks the effective length. This sliding-window approach avoids shifting array contents on each move. ### Movement and Direction Logic Direction is encoded in `c$` (a single INKEY$ character). At line `3`, the deltas `xt` and `yt` are computed using Boolean arithmetic: `2*(c$="6")-2*(c$="7")` gives horizontal movement, and `2*(c$="8")-2*(c$="5")` gives vertical movement, corresponding to the Spectrum’s cursor keys. The step size of 2 is used because the playfield uses even-numbered columns (the food is placed at even coordinates in line `11`), keeping the snake aligned to the grid. ### Playfield Generation Line `11` scatters food dots on even rows (0, 2, 4 … 18) using random even column positions. A mild collision-avoidance check `LET q=q-2*(q=o)` shifts one dot if both would land on the same column. Line `12` prints a row of UDG-A characters on odd rows to create a textured background pattern. The score display line at row 21 shows the countdown timer `t`, accumulated score `s`, current wave `w`, and remaining lives represented as snake-body glyphs conditionally printed based on `sl`. ### Scoring and Wave Progression Score is accumulated at two points: on completing a wave (`s=s+t*w` at line `10`, rewarding speed and wave depth) and on losing a life (`s=s+w*(550-t)` at line `14`). The food counter `p` is checked against 20 at line `6`; eating 20 dots advances to the next wave. The snake starting length `bl` increases by 3 each wave up to a cap of 31, and the time limit `t` decreases as `550-10*a` where `a=bl+1`, making each wave harder. ### High Score Table Lines `15`–`16` implement a 10-entry high score table using numeric array `h(10)` and string array `h$(10,4)` for four-character initials. A reverse loop from 10 to 2 shifts entries downward using the Boolean expression `h(f-(h(f-1)20 OR y+yt<0 OR y+yt>30 THEN GO TO 9 5 LET x=x+xt:LET y=y+yt:LET x(a)=x+(xt=-2)-(xt=2):LET y(a)=y+(yt=-2)-(yt=2):LET x(a+1)=x:LET y(a+1)=y:LET a=a+2:LET l=l+1 6 IF ATTR (x,y)=242 THEN LET u= USR 65232:LET p=p+1:IF p=20 THEN GO TO 10 7 IF ATTR (x,y)=67 OR t <=0 THEN GO TO 14 8 PRINT AT x(a-l),y(a-l);" "; AT x(a-2),y(a-2); INK 3;"\o"; AT x,y;"\o" 9 LET c$= INKEY$:LET t=t-1:PRINT AT 21,5;t;" ":GO TO 3+(c$="") 10 LET p=0:LET w=w+1:LET bl=bl+3*(bl<31):LET s=s+t*w:CLS 11 FOR f=0 TO 18 STEP 2:LET q=(INT (RND*14)*2)+2:LET o= INT (RND*16)*2:LET q=q-2*(q=o):PRINT AT f,q; INK 2; PAPER 6; FLASH 1;"\a"; AT f,o;"\a":NEXT f 12 FOR f=1 TO 19 STEP 2:PRINT AT f,1;"\a \a \a \a \a \a \a \a \a \a \a \a \a \a \a":NEXT f 13 PRINT AT 21,0;,,; AT 21,0;"TIME:"; AT 21,9;"SCORE:";s; AT 21,22;"WAVE:";w; AT 21,30;"\o" AND sl >=2;"\o" AND sl=3:GO TO 2 14 PRINT AT x(a-2),y(a-2);"\o":LET u= USR 65200:FOR f=a-l TO a-2:PRINT AT x(f),y(f);" ":NEXT f:LET sl=sl-1:LET s=s+w*(550-t):GO TO 13+2*(sl=0) 15 CLS :PRINT AT 2,12; INK 3;"SNAKER":IF s>h(10) THEN PRINT AT 4,7;"CONGRATULATIONS!!!":INPUT "YOUR INITIALS,PLEASE!!!"; LINE n$:FOR f=10 TO 2 STEP -1:LET h(f)=h(f-(h(f-1)