Spider

Date: 198
Type: Program
Platform(s): TS 2068
Tags: Game

Spider is a three-stage game in which the player controls a spider navigating through a plughole, across a bath, and out of a bathroom. The program defines two UDG characters using eight bytes each loaded via POKE USR “b”+z in a setup loop, and it uses USR base (where base is calculated from PEEK 23635/23636) to perform pixel-level collision detection by reading character data back from the display file. The main plughole section (lines 100–330) moves two drips down the screen while the player repositions the spider using keys 5, 7, and 8. The bath-descent section (lines 820–1170) uses an INPUT for bath height and simulates swinging on a web with directional keys 1–9 mapped to swing positions. The bathroom escape sequence (lines 1370–1810) adds randomly placed obstacles and tracks how many times the player collides, incrementing a “lumbered” counter with humorous item names drawn from a DATA list.


Program Analysis

Program Structure

The program is organized into three distinct games accessed sequentially, with a shared instruction menu starting at line 2200. The main flow is:

  1. Lines 0–20: UDG initialization and base address calculation
  2. Lines 30–550: Game 1 — The Plughole (main spider/drip gameplay loop)
  3. Lines 560–620: Death/game-over handler
  4. Lines 630–810: Game 1 completion screen
  5. Lines 820–1170: Game 2 — The Bath (web-swinging descent)
  6. Lines 1180–1810: Game 3 — The Bathroom (escape with obstacle avoidance)
  7. Lines 1820–2190: Final exit animation
  8. Lines 2200–2780: Instructions menu and sub-page display routines

UDG Setup and Collision Detection

Line 10 calculates base from PEEK 23635 and PEEK 23636, which are the system variables holding the display file address. Adding 5 offsets into the character cell under the cursor position after a bare PRINT AT x,y; statement. This is the standard technique for reading back a character’s pixel data from the display file to perform collision detection without a separate sprite array.

Line 20 loads 24 bytes into UDG “b” (two UDG slots, “b” and the next), defining the spider sprite as alternating checkerboard patterns (85=01010101, 170=10101010) with a solid midline (255). The DATA at line 20 also references variable a mid-list (the lowercase letter a in the DATA statement is likely a typo or corruption that would cause a syntax error or unexpected value at runtime).

Collision detection throughout the program follows the pattern:

  • PRINT AT x,y; (bare print positions the cursor without output)
  • USR base reads the pixel byte at that screen position
  • Comparisons against 0, 32, 128–138 detect empty, space, or graphic characters

Game 1 — The Plughole

The plughole screens (lines 340–480) are randomly generated using RND: each of 22 rows is filled with a block-graphic string, with a gap inserted at one of two positions depending on whether RND falls below 0.3 or above 0.7, giving three possible row patterns. The player sprite s$ is set at line 80 as a two-character string using block graphics.

Two drips (d1x/d1y and d2x/d2y) descend independently. Drip 2’s advance is gated by c>rnd (line 140), where c is an incrementing counter and rnd is a fixed random threshold set per screen — this creates variable drip speed. Movement uses keys 5 (left), 8 (right), and 7 (up), with the up move restricted to columns 13–15 (line 310).

Line 300 uses the Boolean arithmetic idiom LET y=y+(INKEY$="8" AND USR base <>0), combining a keypress test and a collision check into a single assignment. Line 290 uses PI (≈3.14159, truncated to 3 by integer context) as a literal constant for y+3, which is an unusual but functional substitution.

Game 2 — The Bath

After completing five plughole screens, the player enters the bath descent at line 820. The player inputs a target height r (100–1000) and the spider descends, printing random UDG characters (CHR$ 129–137) as obstacles on row 21. The swing mechanic in the subroutine at line 1030 iterates from column 15 to a target column derived from a-38 (where a is the key code), stepping toward or away from center based on whether the key code is below 53 (key “5”).

Line 960 uses POKE 23692,255 to reset the scroll counter, preventing the “scroll?” prompt from appearing during intensive printing activity. The bare PRINT AT 21,0' (with apostrophe) forces a newline which would otherwise trigger the scroll.

Game 3 — The Bathroom

The bathroom escape (lines 1380–1810) uses keys 5–8 to move the player s$ (reset to "*" at line 1380). The goal marker “D” is placed near the bottom-right corner. Obstacles are block graphic characters (CHR$ 128–138) randomly placed; hitting one invokes subroutine 1710, which adds a new obstacle, increments a “lumbered” counter h, and prints a humorous item name from a DATA list at line 1760. Three collisions end the game.

The movement at lines 1600–1610 uses the Boolean arithmetic idiom for all four directions simultaneously, adding/subtracting the results of INKEY$ comparisons for keys 5, 6, 7, 8.

Instruction Menu

The instruction system at line 2240 presents a choice of five options. Line 2290 uses PRINT (VAL a$*100)+2200 which prints a number (e.g., 2300, 2400, 2500, 2600, 2700) rather than performing a GO TO — this appears to be a bug where the intended GO TO was omitted, causing execution to fall through to line 2300 regardless of selection. The individual instruction pages are at lines 2300, 2400, 2500, and 2600, each falling through to line 2360 which waits for a keypress before returning to the menu.

Notable Techniques and Anomalies

  • The base calculation via PEEK of display-file system variables is a portable collision detection method that works regardless of where the display file sits in RAM.
  • PI is used as an integer constant (evaluating to 3) in lines 290 and 600, avoiding a literal 3 which costs more bytes to store in tokenized BASIC.
  • The random delay subroutine at line 1230 multiplies RND thirteen times to produce a very small number, effectively creating a near-zero busy-wait used for character-by-character print animation in the “NOW, ESCAPE FROM THE BATHROOM” sequence.
  • Line 240 reads IF x=2 THEN GO SUB 120, but line 120 is the spider print line rather than a subroutine — this is a GO TO/GO SUB mismatch that would cause a RETURN to send execution back to line 240 unexpectedly.
  • The DATA statement at line 20 contains bare variable name references (a,a,a and a,a,a) where numeric literals were presumably intended, which would cause a syntax or type error when READ a encounters them.
  • Line 1670 checks IF c= CODE "[UDG-B]", comparing the collision value against the code of UDG “b” — this is the wall-detection branch that prevents horizontal movement into obstacles.
  • The exit animation at lines 1820–2190 draws a decorative room scene using block graphics and then loops PRINT AT 12,10;"GOODBYE*=-" indefinitely.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   0 REM [\*$><(5(O0205*6$ _###[\ #y*\!
   10 LET base= PEEK 23635+256* PEEK 23636+5:RESTORE :FOR z=0 TO 23:READ a:POKE USR "b"+z,a:NEXT z
   20 DATA 85,170,85,170,85,170,85,170,0,a,a,a,85,170,85,170,85,170,85,170,255,a,a,a
   30 CLS 
   40 RANDOMIZE 
   50 GO SUB 2200
   60 LET ult= INT (RND*5)+1
   70 LET sc=0
   80 LET s$="▚""▞"
   90 GO SUB 340
  100 GO SUB 490
  110 GO SUB 520
  120 PRINT AT x,y;s$
  130 PRINT AT d1x,d1y;" "; AT d2x,d2y;" "
  140 IF c>rnd AND d2x <>20 THEN LET d2x=d2x+1
  150 IF d2x=20 THEN GO SUB 520
  160 IF d1x <>20 THEN LET d1x=d1x+1
  170 IF d1x=20 THEN GO SUB 490
  180 PRINT AT d1x,d1y;
  190 IF USR base <>32 THEN GO TO 560
  200 PRINT AT d2x,d2y;
  210 IF USR base <>32 THEN GO TO 560
  220 PRINT AT d1x,d1y;"[UDG-B]"; AT d2x,d2y;"[UDG-B]"
  230 FOR a=1 TO 70:NEXT a
  240 IF x=2 THEN GO SUB 120
  250 IF INKEY$="" THEN GO TO 130
  260 PRINT AT x,y;"   "
  270 PRINT AT x,y-1;
  280 IF INKEY$="5" AND USR base <>0 THEN LET y=y-1
  290 PRINT AT x,y+ PI;
  300 LET y=y+(INKEY$="8" AND USR base <>0)
  310 IF INKEY$="7" AND y>13 AND y<16 THEN LET x=x-1
  320 LET c=c+1
  330 GO TO 120
  340 LET sc=sc+1
  350 IF sc=5 THEN GO TO 630
  360 CLS 
  370 LET rnd= INT (RND*9)+1
  380 FOR l=0 TO 21
  390 LET n$="████████████████████████████████"
  400 LET rn= RND
  410 IF rn<.3 THEN LET n$="███████████       ██████████████"
  420 IF rn>.7 THEN LET n$="██████████████       ███████████"
  430 PRINT n$
  440 NEXT l
  450 LET x=20
  460 LET y=15
  470 PRINT AT x,y;s$
  480 RETURN 
  490 LET d1x=0
  500 LET d1y=15+ INT (RND*3)
  510 RETURN 
  520 LET d2y=15+ INT (RND*3)
  530 LET c=0
  540 LET d2x=c
  550 RETURN 
  560 CLS 
  570 LET c$=" SCREENS"
  580 IF sc=1 THEN LET c$=c$( TO 7)
  590 PRINT AT 10,0;"THE TERRIBLE DROP HAS KILLED YOU"
  600 PRINT AT 15, PI;"YOU WENT THROUGH ";sc;c$
  610 PRINT AT 5,13;"OUCH"
  620 GO TO 610
  630 CLS 
  640 FOR q=1 TO 15
  650 PRINT "▐"; TAB 31;"▌"
  660 NEXT q
  670 PRINT "▟▄▄▄▄▄▄▄▄▄▄▄▄▄▄£  ▄▄▄▄▄▄▄▄▄▄▄▄▄▙"
  680 FOR q=1 TO 6
  690 PRINT "██████████████   ███████████████"
  700 NEXT q
  710 FOR q=21 TO 10 STEP -1
  720 PRINT AT q,14;s$; AT q,14;"   "
  730 NEXT q
  740 PRINT AT 12,0;"CONGRATULATIONS-YOU HAVE MADE IT"
  750 PRINT 
  760 PRINT "DO█YOU█WISH█TO█DESCEND█FROM█THE██████BATH█ONTO█THE█FLOOR?"
  770 IF INKEY$="" THEN GO TO 740
  780 IF INKEY$="y" THEN RUN 820
  790 PRINT 
  800 PRINT AT 16,12;"OKAY,BYE"
  810 GO TO 810
  820 CLS 
  830 PRINT AT 10,0;"INPUT HEIGHT OF BATH (100-1000)"
  840 LET v=0
  850 INPUT r
  860 PRINT AT 10,0,,
  870 LET s$="▚""▞"
  880 LET x=10
  890 LET y=15
  900 PRINT AT 4,0;"[UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-D][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B]▐[UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B] LEN [UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B]▌[UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B]▐[UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-D][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B]▌[UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B][UDG-B]"
  910 LET a= CODE INKEY$
  920 IF v >=r THEN GO TO 1180
  930 IF a <>0 THEN GO SUB 1030
  940 PRINT AT 21, INT (RND*31)+1; CHR$ (INT (RND*9)+129)
  950 PRINT AT x,y;s$; AT x-1,15;" ▐ "
  960 POKE 23692,255:PRINT AT 21,0'
  970 PRINT AT x+1,y+1;
  980 LET l= USR base
  990 IF l>128 AND l<138 THEN GO TO 1150
 1000 LET v=v+1
 1010 GO TO 910
 1020 IF l=32 THEN GO TO 1150
 1030 LET z=x
 1040 LET t=1
 1050 IF a<53 THEN LET t=-1
 1060 FOR b=15 TO (a-38) STEP t
 1070 LET z=z-1
 1080 PRINT AT z+1,b+1;
 1090 IF USR base>128 AND USR base<138 THEN GO TO 1150
 1100 LET v=v+1
 1110 PRINT AT z,b;s$; AT z,b;" ▐ "
 1120 POKE 23692,255:PRINT AT 21,0'
 1130 NEXT b
 1140 RETURN 
 1150 LET c$=" TURNS"
 1160 LET sc=v
 1170 GO TO 600
 1180 FOR a=1 TO 200
 1190 PRINT AT INT (RND*20)+1, INT (RND*21)+1;"WELL DONE"
 1200 NEXT a
 1210 CLS 
 1220 GO TO 1250
 1230 LET time= RND* RND* RND* RND* RND* RND* RND*99* RND* RND* RND* RND* RND
 1240 RETURN 
 1250 PRINT AT 5,0;"N";
 1260 GO SUB 1230
 1270 PRINT "O";
 1280 GO SUB 1230
 1290 PRINT "W";
 1300 GO SUB 1230
 1310 PRINT ","; AT 10,5;"ESCAPE ";
 1320 GO SUB 1230
 1330 PRINT "FROM THE ";
 1340 GO SUB 1230
 1350 PRINT "BATHROOM"
 1360 PAUSE 150
 1370 CLS 
 1380 LET s$="*"
 1390 LET s1=1
 1400 LET s=s1
 1410 FOR a=0 TO 31
 1420 PRINT AT 0,a;"[UDG-B]"; AT 20,a;"[UDG-A]"
 1430 IF a<20 THEN PRINT AT a,0;"[UDG-B]"; AT a,31;"[UDG-B]"
 1440 NEXT a
 1450 PRINT AT s,s1;s$; AT INT (RND*5)+14, INT (RND*4)+24;"D"
 1460 LET a1=3
 1470 LET h=0
 1480 FOR a=1 TO a1
 1490 LET o= INT (RND*20)+1
 1500 LET o1= INT (RND*30)+1
 1510 PRINT AT o,o1;
 1520 IF USR base=0 THEN GO SUB 1710
 1530 PRINT AT o,o1; CHR$ (INT (RND*11)+128)
 1540 NEXT a
 1550 LET t=s
 1560 LET t1=s1
 1570 GO TO 1600
 1580 LET c= USR base
 1590 RETURN 
 1600 LET t=t+(INKEY$="6")-(INKEY$="7")
 1610 LET t1=t1+(INKEY$="8")-(INKEY$="5")
 1620 PRINT AT t,t1;
 1630 GO SUB 1580
 1640 IF c= CODE "D" THEN GO TO 1820
 1650 IF c>127 THEN GO SUB 1710
 1660 PRINT AT s,s1;" "
 1670 IF c= CODE "[UDG-B]" THEN GO TO 1690
 1680 LET s1=t1
 1690 PRINT AT s,s1;s$
 1700 GO TO 1480
 1710 LET h=h+1
 1720 IF h=3 THEN GO TO 1800
 1730 PRINT AT INT (RND*5)+15, INT (RND*5)+26;"D"
 1740 PRINT AT 21,0;"YOUR NOW LUMBERED WITH ";
 1750 LET z= INT (RND*10)+1
 1760 DATA "A TOWEL  ","SOME SOAP","A COMB   ","A BRUSH  ","A GLASS  ","A RAZOR  ","A SPOON  ","A FLANNEL","SHAMPOO  "
 1770 RESTORE 1760:FOR a=1 TO z:READ a$:NEXT a:PRINT a$
 1780 LET a1=a1+1
 1790 RETURN 
 1800 PRINT AT INT (RND*20)+1, INT (RND*15)+1;"OUCH YOUR DEAD"
 1810 GO TO 1800
 1820 CLS 
 1830 FOR a=5 TO 19
 1840 PRINT AT A,10;"██████████"
 1850 NEXT a
 1860 PRINT AT 12,17;"<=-"
 1870 PRINT AT 5,20;"▘▘▘▘▘"; AT 19,20;"▖▖▖▖▖"
 1880 PRINT AT 5,5;"▝▝▝▝▝"; AT 19,5;"▗▗▗▗▗"
 1890 FOR a=0 TO 4
 1900 PRINT AT a,a;"▞"
 1910 PRINT AT a,29-a;"▚"
 1920 NEXT a
 1930 FOR a=20 TO 21
 1940 PRINT AT a,24-a;"▚"
 1950 PRINT AT a,5+a;"▞"
 1960 NEXT a
 1970 FOR a=5 TO 19
 1980 IF a>5 AND a<19 THEN PRINT AT a,5;"▐"; AT a,24;"▌"
 1990 PRINT AT a,17;"██ "
 2000 NEXT a
 2020 FOR a=21 TO 19 STEP -1
 2030 PRINT AT 20,a;"▚""▞"
 2040 FOR b=1 TO 10
 2050 NEXT b
 2060 PRINT AT 20,a;"   "
 2070 NEXT a
 2080 PRINT AT 19,19;"""""▞▖"
 2090 LET ss= RND* RND* RND* RND* RND* RND* RND* RND* RND* RND* RND* RND* RND
 2100 PRINT AT 19,19;"▞▖"
 2110 FOR a=1 TO 25
 2120 NEXT a
 2130 PRINT AT 19,19;"▖"
 2140 FOR a=5 TO 19
 2150 PRINT AT a,18;"██"
 2160 NEXT a
 2180 PRINT AT 12,10;"GOODBYE*=-"
 2190 GO TO 2180
 2200 PRINT AT 5,5;"INSTRUCTIONS? (Y/N)"
 2210 IF INKEY$ <>"" THEN GO TO 2210
 2220 IF INKEY$="" THEN GO TO 2220
 2230 IF INKEY$="n" THEN RETURN 
 2240 CLS 
 2250 PRINT AT 5,5;"GAME 1...1"''"     GAME 2...2"''"     GAME 3...3"''"     SCORING..4"''"     TO BEGIN.5"
 2260 LET a$= INKEY$
 2270 IF a$<"1" OR a$>"5" THEN GO TO 2260
 2280 CLS 
 2290 PRINT (VAL a$*100)+2200
 2300 PRINT TAB 5;"GAME 1-THG PLUGHOLE"
 2310 PRINT "Beware of the drips and make it through 5 screens of plughole."
 2320 PRINT "     DIRECTIONS:"
 2330 GO SUB 2670
 2340 GO SUB 2700
 2350 GO SUB 2730
 2360 PRINT AT 21,10;"PRESS A KEY"
 2370 GO TO 2640
 2400 PRINT "     GAME 2-THE BATH"
 2410 PRINT "Swing on the web to avoid the   obstacles placed in your path."
 2420 PRINT "     DIRECTIONS:"
 2430 PRINT AT 6,0;"1     -     FOUR SWINGS LEFT    2     -     THREE SWINGS LEFT   3     -     TWO SWINGS LEFT","4     -     ONE SWING LEFT"
 2440 PRINT '"5     -     NEUTRAL POSITION"
 2450 PRINT '"6     -     ONE SWING RIGHT","7     -     TWO SWINGS RIGHT","8     -     THREE SWINGS RIGHT  9     -     FOUR SWINGS RIGHT"
 2460 GO TO 2360
 2500 PRINT "     GAME 3-THE BATHROOM"
 2510 PRINT "Escape from the bathroom before you are lumbered with 3 objects."
 2520 GO TO 2330
 2600 PRINT "     SCORING"
 2610 PRINT AT 5,0;"GAME 1 - Screens passed"'''''"GAME 2 - How far down bath"'''''"GAME 3 - Most number of doors on         screen loses"
 2620 GO TO 2360
 2630 RETURN 
 2640 IF INKEY$ <>"" THEN GO TO 2640
 2650 IF INKEY$="" THEN GO TO 2650
 2660 GO TO 2240
 2670 PRINT AT 4,2;"▚"; AT 5,1;"▚▄▄▄"; AT 6,1;"▞▀▀▀"; AT 7,2;"▞"
 2680 PRINT AT 6,6;".....5"
 2690 RETURN 
 2700 PRINT AT 4,29;"▞"; AT 5,27;"▄▄▄▞"; AT 6,27;"▀▀▀▚"; AT 7,29;"▚"
 2710 PRINT AT 6,20;"8..... "
 2720 RETURN 
 2730 PRINT AT 10,3;"▚▞"; AT 11,2;"▚▌▐▞"; TAB 3;"▌▐"; TAB 3;"▌▐"
 2740 PRINT AT 13,6;".....7"
 2750 RETURN 
 2760 PRINT AT 10,28;"▌▐"; TAB 28;"▌▐"; TAB 27;"▞▌▐▚"; TAB 28;"▞▚"
 2770 PRINT AT 13,20;"6....."
 2780 RETURN 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top