Sheep Dog Trials

This file is part of SINCUS Exchange Tape 101 - Entertainment, and Timex Sinclair Public Domain Library Tape 2004. Download the collection to get this file.
Type: Program
Platform(s): TS 2068
Tags: Game

This program implements a four-stage sheepdog trials game in which the player maneuvers a sheepdog UDG character to herd three sheep UDGs into a pen. Two UDG characters are defined at startup: a sheep (UDG “a”) and a dog (UDG “b”), loaded via a READ/POKE loop writing 32 bytes into USR “a” and USR “a”+8 through USR “a”+31. The movement engine in the subroutine at line 8000 supports both keyboard (T/Y/U/G/H/V/B/N) and joystick input via the STICK keyword, with collision detection using SCREEN$ to prevent the dog and sheep from walking through obstacles. Stage scoring counts down from 20 based on the number of move cycles elapsed, calculated at line 8020 as a decreasing function of the counter variable nm. Stage four requires all three sheep to occupy a specific rectangular pen region defined by character-cell coordinate bounds, checked at line 1440.


Program Analysis

Program Structure

The program is organized into four main game stages plus shared subroutines. Lines 10–240 handle initialization, UDG setup, and the instruction screen. Lines 250–545 implement Stage One (open field herding). Lines 570–860 cover Stage Two (pond obstacles). Lines 900–1200 handle Stage Three (a maze-like layout). Lines 1250–1600 implement Stage Four (pen herding). Three key subroutines appear at the end of the listing:

  • 7000: A short musical fanfare using BEEP, played between stages.
  • 8000: The main movement and AI engine, called repeatedly as the game loop.
  • 9000: Stage initialization — reads starting coordinates for the dog and three sheep from DATA statements, places the UDGs, and resets counters.

Stage data is distributed across four DATA lines (9040–9070), one per stage, each containing the dog’s starting x/y and three sheep x/y pairs (eight values total).

UDG Definition

Lines 30–60 define two UDGs by POKEing 32 bytes into memory starting at USR "a". The loop runs a from 0 to 31, reading each byte and writing it to USR "a"+a, thus populating UDG “a” (sheep, 8 bytes) and UDG “b” (sheepdog, 8 bytes) as well as two further UDGs (“c” and “d”, used as obstacle/fence tiles). UDG characters are then referenced throughout PRINT statements using the zmakebas escape sequences \a, \b, \c, and \d.

Movement and Collision Detection (Subroutine 8000)

The movement engine at line 8000 is the heart of the program. It handles both the player-controlled dog and the AI-driven sheep in a single subroutine call per game-loop iteration.

Player input is read at line 8040 into a$. Lines 8050–8060 compute candidate new positions px and py by adding Boolean expressions (which evaluate to 0 or 1 in Sinclair BASIC) for each direction. Both keyboard letters and joystick values via STICK(1,1) (the | keyword) are checked simultaneously in a single expression, supporting the T/Y/U/G/H/V/B/N key layout as an approximated directional pad.

Collision detection uses SCREEN$ to test whether the target cell is a space character. The resolution order is:

  1. Try moving to (py, px) — both axes.
  2. If blocked, try sliding along the y-axis only ((py, x)).
  3. If still blocked, try sliding along the x-axis only ((y, px)).
  4. If all blocked, stay in place.

The same three-step slide resolution is applied to sheep movement at lines 8180–8215, with an additional random-walk escape (line 8210) that fires with probability 0.99 when all direct paths are blocked, moving the sheep one step in a random direction and retrying.

Sheep AI

Each sheep’s AI is driven by proximity to the dog. At line 8150, the squared distance d = dx*dx + dy*dy is computed. If d > 9 (more than ~3 cells away), the sheep does not move. An extra check at line 8165 prevents movement when d=9 and fewer than three sheep remain active (n<3), which is relevant to Stage Four’s “all sheep remain active until the last one is penned” rule. When within range, the sheep moves one step away from the dog using SGN dx and SGN dy.

Scoring System

A move counter nm is incremented at line 8000 on each call. The stage score ss is calculated at line 8020 as:

a = 20 - INT((nm - 50) / 40)

This gives a maximum of 20 points (for the first 50 moves), declining by 1 for each additional 40 moves, and clamped to 0 at line 8030. The total across four stages gives a maximum possible score of 80, referenced in the end screen at line 1560.

Stage Completion Logic

In Stages One through Three, sheep are removed from the active set when their y-coordinate drops below a threshold (rows 13 or 15 depending on stage), representing the pen at the bottom of the screen. The active count n is decremented by swapping the penned sheep’s data with the last active sheep’s data — a compact array-shrinking technique. In Stage Four, completion requires all three sheep to simultaneously satisfy x(a) > 12 AND x(a) < 17 AND y(a) > 9 AND y(a) < 13 (line 1440), checked by counting qualifying sheep into ct.

Notable Techniques

  • The POKE 23692,255 calls (lines 500, 810, 1520) reset the scroll prompt counter, preventing “scroll?” from appearing during rapid PRINT output.
  • The Stage One field includes a curved fence drawn with DRAW arc commands (lines 290–320, 380) alongside character-cell obstacles, mixing pixel-level and character-level graphics in the same stage.
  • Stage Two pond obstacles are drawn as filled circles using a scanline fill loop (lines 640–680): for each radius step a, the chord half-width b = INT(SQR(49 - a*a) + 0.5) is computed and a vertical line of height 2*b is drawn at both x+a and x-a.
  • The Stage Four checkerboard border is generated procedurally at lines 1270–1300 using a - 3*INT(a/3) = 2 as a modulo-3 test to alternate between \c and \d border tiles.
  • Line 1350 uses CHR$(146 + RND) to print either UDG “b” (char 146) or UDG “c” (char 147) randomly as background decoration, though RND returns a real number so 146 + RND always truncates to 146 — this is likely a bug intended to randomize between two UDG tiles but effectively always prints the same one.

Bugs and Anomalies

  • Line 1540 contains a spelling error: “COMPLEATED” instead of “COMPLETED”.
  • The CHR$(146 + RND) issue noted above always evaluates to CHR$(146) since INT is not applied; CHR$(146 + INT(RND*2)) was likely intended.
  • The instruction text at line 216 runs words together without spaces between print-string segments (e.g., “SPACE AT THE BASE OF THE SCREEN.” and “EACH SHEEP BECOMES INACTIVE WHENIN ITS PEN”), indicating the programmer relied on line wrap rather than explicit spaces at string boundaries.
  • The loop at line 460 uses NEXT a but the only exit after the pen check at line 430 is GO TO 480, skipping to line 490 — line 480 does not exist, so penned sheep processing falls through directly to the NEXT a at line 460 via the non-existent line target, which is a deliberate Sinclair BASIC technique rather than a bug.

Content

Appears On

One of a series of library tapes. Programs on these tapes were renamed to a number series. This tape contained

Related Products

Related Articles

Related Content

Image Gallery

Sheep Dog Trials

Source Code

   10 PAPER 7: INK 0: FLASH 0: BRIGHT 0: OVER 0: INVERSE 0: BORDER 0: CLS 
   20 PRINT INVERSE 1;AT 2,13;"SHEEP";AT 4,14;"DOG";AT 6,13;"TRIALS"
   30 FOR a=0 TO 31
   40 READ b: POKE USR "a"+a,b
   50 NEXT a
   60 DATA 0,0,127,255,91,17,17,0,0,0,65,254,63,33,33,0,8,28,28,62,62,127,8,28,0,129,255,129,255,129,255,129
   65 GO SUB 7000
   70 PRINT ''" IN THIS GAME YOU MUST MAKE"
   80 PRINT " YOUR SHEEPDOG  \b  GUIDE THREE"
   90 PRINT " SHEEP  \a  THROUGH A SERIES OF"
  100 PRINT " OBSTACLES."
  110 PRINT ''"CONTROLS ARE: -"
  120 PRINT TAB 12;"T  Y  U"
  130 PRINT 'TAB 12;"G     H"
  140 PRINT 'TAB 12;"V  B  N"
  150 FOR a=0 TO 2*PI STEP PI/4
  160 PLOT 123,28: DRAW 12*COS a,9*SIN a
  170 NEXT a
  180 PRINT ''"THERE ARE FOUR STAGES TO THE "
  190 PRINT "TEST. POINTS ARE LOST FOR TAKING"
  200 PRINT "TOO LONG OVER A STAGE.THE SHEEP"
  210 PRINT "WILL ONLY MOVE WHEN THE DOG GETS"
  215 PRINT "CLOSE TO THEM": PRINT 
  216 PRINT "IN THE FIRST THREE STAGES YOU   MUST CHASE THE SHEEP INTO THE   SPACE AT THE BASE OF THE SCREEN."
  217 PRINT "EACH SHEEP BECOMES INACTIVE WHENIN ITS PEN": PRINT 
  218 PRINT "IN STAGE TWO THE BLUE AREAS ARE PONDS WHICH THE SHEEP WILL NOT  CROSS,BUT IF THERE ARE GAPS IN  THE FENCING BETWEEN THE PONDS,  THE SHEEP WILL GO THROUGH THEM.": PRINT 
  220 PRINT "IN STAGE FOUR ALL THE SHEEP WILLREMAIN ACTIVE UNTIL THE THIRD   ONE IS PENNED."
  225 DIM x(3): DIM y(3): LET p=0
  230 PRINT ''"Press any key to start"
  240 PAUSE 0
  250 PAPER 4: CLS 
  260 PRINT ''TAB 8;"\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d"
  270 PRINT TAB 8;"\d     ooooo    \d"
  280 FOR a=4 TO 12: PRINT AT a,8;"\d";TAB 23;"\d": NEXT a
  290 PLOT 73,110
  300 FOR a=1 TO 12
  310 DRAW 9,0,-PI+RND-.5
  320 NEXT a
  330 PRINT AT 7,12;"\c\c   \c\c";AT 8,12;"\c\c   \c\c"
  340 PRINT AT 5,19;"/\"
  360 PRINT AT 11,10;"####         ^"
  370 PRINT AT 13,8;"\d\d\d\d\d\d\d   \d\d\d\d\d\d"            
  380 PLOT 117,62: DRAW 27,0,1.5*PI
  390 GO SUB 9000
  400 PRINT AT 18,0;"STAGE SCORE:";ss;"  "
  410 GO SUB 8000
  420 FOR a=1 TO n
  430 IF y(a)<=13 THEN GO TO 480
  440 LET y(a)=y(n): LET x(a)=x(n): LET n=n-1
  450 BEEP .3,0
  460 NEXT a
  490 IF n>0 THEN GO TO 400
  495 FOR a=1 TO 200: NEXT a
  500 POKE 23692,255
  510 FOR a=1 TO 25: PRINT : NEXT a
  520 PRINT ''TAB 6;"STAGE ONE COMPLETED"
  530 PRINT ''TAB 11;"SCORE:";ss'''''''''''
  540 LET p=ss
  545 GO SUB 7000
  550 PRINT '"  Press any key for stage two"'''
  560 IF INKEY$="" THEN GO TO 560
  570 CLS 
  590 PLOT 71,60: DRAW 0,100,-PI: DRAW 115,0: DRAW 0,-100,-PI
  600 PLOT 70,60: DRAW 0,100,-PI: DRAW 115,0: DRAW 0,-100,-PI
  610 DRAW -33,0: DRAW -20,-40: DRAW -15,0: DRAW -20,40: DRAW -32,0
  620 DRAW 0,70
  625 INK 1
  630 FOR x=80 TO 200 STEP 24
  640 FOR a=0 TO 7
  650 LET b=INT (SQR (49-a*a)+.5)
  660 PLOT x+a,100-b: DRAW 0,2*b
  670 PLOT x-a,100-b: DRAW 0,2*b
  680 NEXT a
  690 NEXT x
  700 INK 0
  710 FOR a=11 TO 23 STEP 3
  720 IF RND<.7 THEN PRINT AT 9,a;"\d"
  730 NEXT a
  740 GO SUB 9000
  745 PRINT AT 20,0;"RUNNING SCORE:  ";p'"STAGE SCORE: ";
  748 PRINT AT 21,13;ss;" ";
  750 GO SUB 8000
  760 FOR a=1 TO n
  770 IF y(a)<15 THEN GO TO 790
  780 LET x(a)=x(n): LET y(a)=y(n): LET n=n-1
  785 BEEP .3,0
  790 NEXT a
  800 IF n>0 THEN GO TO 748
  803 GO SUB 7000
  805 FOR a=1 TO 200: NEXT a
  810 POKE 23692,255
  820 FOR a=1 TO 25: PRINT : NEXT a
  830 PRINT TAB 6;"STAGE TWO COMPLETED"
  840 PRINT ''"SCORE SO FAR:  ";ss+p
  850 LET p=p+ss
  860 PRINT ''"Press any key for stage three"
  870 PRINT ''''''''''
  880 IF INKEY$="" THEN GO TO 880
  900 CLS 
  910 PRINT ''TAB 6;"\c\c\c\c\c\c\c\c\c\c\c\c\c\c\c\c\c\c\c"
  920 PRINT TAB 6;"\c\c\c\c\c\c\c\c\c        \c\c\c"
  930 PRINT TAB 6;"\c\c               \c\c\c"
  940 PRINT TAB 6;"\c           \c\c\c    \c"
  950 PRINT TAB 6;"\c\c         \c\c\c\c\c   \c\c"
  960 PRINT TAB 6;"\c\c\c\c      \c\c\c\c\c   \c\c"
  970 PRINT TAB 6;"\c\c\c\c\c\c\c\c\c\c\c\c\c\c     \d"
  980 PRINT TAB 6;"\c        \c\c\c\c\c\c    \d"
  990 PRINT TAB 6;"\c           \c\c\c  \d\d\d"
 1000 PRINT TAB 6;"\c\c\c      ^^     \d\d"
 1010 PRINT TAB 6;"\c\c\c\c      ^^ \c\c\c\c\d\d"
 1020 PRINT TAB 6;"\c\c\c\c\c   \c\c\c\c\c\c\c\d"
 1030 PRINT TAB 6;"\c\c\c\c     \c\c\c\c\c\c"
 1040 PRINT TAB 6;"\c\c\c\c     \c\c\c\c\c\c"
 1050 PRINT ''"RUNNING SCORE: ";p
 1060 PRINT "STAGE SCORE: "
 1070 GO SUB 9000
 1080 PRINT AT 19,13;ss;" "
 1090 GO SUB 8000
 1100 FOR a=1 TO n
 1110 IF y(a)<15 THEN GO TO 1130
 1120 LET y(a)=y(n): LET x(a)=x(n): LET n=n-1
 1125 BEEP .3,0
 1130 NEXT a
 1140 IF n>0 THEN GO TO 1080
 1150 GO SUB 7000
 1160 FOR a=1 TO 200: NEXT a
 1170 CLS 
 1180 PRINT '''TAB 5;"STAGE THREE COMPLETED"
 1190 PRINT ''"SCORE: ";ss+p
 1200 LET p=p+ss
 1210 PRINT '''"NOW YOU HAVE TO GET THE"
 1220 PRINT "SHEEP INTO THEIR PEN"
 1230 PRINT ''''"Press any key"
 1240 PAUSE 0
 1250 CLS 
 1260 PRINT ''"  \c\d\d\d\c\d\d\d\c\d\d\d\c\d\d\d\c\d\d\d\c\d\d\d\c\d\d\d\c"
 1270 FOR a=3 TO 16
 1280 IF a-3*INT (a/3)=2 THEN PRINT AT a,2;"\c";TAB 30;"\c": GO TO 1300
 1290 PRINT AT a,2;"\d";TAB 30;"\d"
 1300 NEXT a
 1310 PRINT "  \c\d\d\d\c\d\d\d\c\d\d\d\c\d\d\d\c\d\d\d\c\d\d\d\c\d\d\d\c"
 1320 FOR a=1 TO 20
 1330 LET x=RND*25+4: LET y=RND*12+4
 1340 PRINT AT y,x;CHR$ (146+RND)
 1350 NEXT a
 1360 GO SUB 9000
 1370 PRINT AT 19,0;"RUNNING SCORE: ";p'"STAGE SCORE:"
 1390 PRINT AT 10,13;"    ";AT 11,13;"    ";AT 12,13;"     "
 1400 PLOT 104,73: DRAW 0,23: DRAW 31,0: DRAW 0,-23
 1405 PRINT AT 20,13;ss;"  "
 1410 GO SUB 8000
 1420 LET ct=0
 1430 FOR a=1 TO 3
 1440 IF x(a)>12 THEN IF x(a)<17 THEN IF y(a)>9 THEN IF y(a)<13 THEN LET ct=ct+1
 1450 NEXT a
 1460 IF ct<>3 THEN GO TO 1405
 1470 FOR a=1 TO 5
 1480 FOR b=7 TO 0 STEP -1
 1485 BORDER b
 1490 PAUSE 10
 1500 NEXT b
 1510 NEXT a
 1520 POKE 23692,255
 1530 FOR a=1 TO 25: PRINT : NEXT a
 1535 CLS 
 1540 PRINT AT 10,10;"YOU HAVE NOW                COMPLEATED THE TRIAL"
 1550 PRINT ''"        YOUR DOG SCORED ": FLASH 1: PRINT AT 15,14;ss+p: FLASH 0: PRINT TAB 8;" POINTS OUT OF"
 1560 PRINT TAB 9;"A POSSIBLE 80."
 1561 GO SUB 7000
 1570 PRINT ''"Do you wish to play again?  Y/N"
 1580 IF INKEY$="y" OR INKEY$="Y" THEN RUN 
 1590 IF INKEY$="n" OR INKEY$="N" THEN GO TO 9990
 1600 GO TO 1580
 7000 FOR a=10 TO 25: BEEP .06,a: NEXT a
 7010 FOR a=10 TO 25: BEEP .06,a: NEXT a
 7015 FOR a=1 TO 20: NEXT a
 7020 FOR a=25 TO 10 STEP -1: BEEP .06,a: NEXT a
 7030 RETURN 
 8000 LET nm=nm+1
 8010 LET a=20-INT ((nm-50)/40)
 8020 IF a>20 THEN GO TO 8040
 8030 LET ss=a: IF ss<0 THEN LET ss=0
 8040 LET a$=INKEY$
 8050 LET px=x+(a$="u" OR |(1,1)=9 OR a$="h" OR |(1,1)=8 OR a$="n" OR |(1,1)=10)-(a$="t" OR |(1,1)=5 OR a$="g" OR |(1,1)=4 OR a$="v" OR |(1,1)=6)
 8060 LET py=y-(a$="t" OR |(1,1)=5 OR a$="y" OR |(1,1)=1 OR a$="u" OR |(1,1)=9)+(a$="v" OR |(1,1)=6 OR a$="b" OR |(1,1)=2 OR a$="n" OR |(1,1)=10)
 8070 IF SCREEN$ (py,px)=" " THEN GO TO 8120
 8080 IF SCREEN$ (py,x)=" " THEN LET px=x: GO TO 8120
 8090 IF SCREEN$ (y,px)=" " THEN LET py=y: GO TO 8120
 8100 LET px=x: LET py=y
 8120 PRINT AT y,x;" ";AT py,px;"\b"
 8130 LET x=px: LET y=py
 8140 FOR a=1 TO n
 8150 LET dx=x(a)-x: LET dy=y(a)-y: LET d=dx*dx+dy*dy
 8160 IF d>9 THEN GO TO 8230
 8165 IF d=9 AND n<3 THEN GO TO 8230
 8170 LET px=x(a)+SGN dx: LET py=y(a)+SGN dy
 8180 IF SCREEN$ (py,px)=" " THEN GO TO 8220
 8190 IF SCREEN$ (py,x(a))=" " THEN LET px=x(a): GO TO 8220
 8200 IF SCREEN$ (y(a),px)=" " THEN LET py=y(a): GO TO 8220
 8210 IF RND>.01 THEN LET px=x(a)+SGN (RND-.5): LET py=y(a)+SGN (RND-.5): GO TO 8180
 8215 LET px=x(a): LET py=y(a)
 8220 PRINT AT y(a),x(a);" "; INK 7;AT py,px;"\a"
 8225 LET x(a)=px: LET y(a)=py
 8230 NEXT a
 8240 RETURN 
 9000 LET ss=20: READ x,y: LET nm=0: LET n=3
 9010 FOR a=1 TO 3: READ x(a),y(a): PRINT AT y(a),x(a); INK 7;"\a": NEXT a
 9020 PRINT AT y,x;"\b"
 9030 RETURN 
 9040 DATA 10,3,12,6,14,4,16,5
 9050 DATA 6,12,4,8,6,8,6,9
 9060 DATA 8,5,10,4,11,6,14,4
 9070 DATA 5,5,18,11,5,14,24,6
 9990 CLS : BORDER 1: PAPER 1: INK 6: FLASH 1: PRINT AT 11,0;"    LASSIE SAYS GOODBYE        ": FLASH 0
 9995 STOP 
 9999 SAVE "sheep dog" LINE 10

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

People

No people associated with this content.

Scroll to Top