Cat ‘n’ Mouse

This file is part of and CATS Library Tape 6. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Arcade, Game

Maze game where the player controls a cat character (rendered using custom UDG graphics) to eat 50 mice while avoiding rats on a bordered playfield. The program defines four UDG characters at lines 1–2 using POKEs into the UDG memory area, representing the cat, a rat, a mouse, and a venom/spit graphic. It supports both keyboard (cursor keys 5/6/7/8) and Atari joystick input via the STICK function, with full 8-directional diagonal movement available on joystick. Difficulty levels control how many additional rats spawn each time a mouse is eaten, with the subroutine at line 9980 spawning replacements and levels 2 and 3 adding progressively more rats per eaten mouse. An on-screen timer is maintained by reading system frame counters at addresses 23672–23673, and best time and best score are preserved across replays for the session.


Program Analysis

Program Structure

The program is organized into several functional regions:

  1. Lines 1–2: UDG definition — four custom characters are POKEd into memory.
  2. Lines 3–19: Title screen, instructions, difficulty selection, and input mode selection (keyboard or joystick).
  3. Lines 20–26: Optional in-game instructions describing gameplay.
  4. Lines 30–55: Board drawing — animated border construction and title overlay.
  5. Lines 60–110: Entity placement — 50 mice and 4 rats placed randomly, collision-checked by ATTR.
  6. Lines 130–245: Main keyboard game loop.
  7. Lines 400–420: Win/end-of-game scoring and replay logic (note: line 400 is referenced by GO TO but not listed; line 405 is the first present line, suggesting line 400 is missing or the jump falls through to 405).
  8. Lines 450–475: Death sequence (eaten by rat).
  9. Lines 2500–2575: Joystick game loop, mirroring the keyboard loop.
  10. Lines 3000–3005: Restart handler.
  11. Lines 9980–9996: Rat-spawning subroutine (called inline via GO TO, not GO SUB).
  12. Line 9997: Melody subroutine (jingle played at key moments).
  13. Lines 9998–9999: SAVE and STOP.

UDG Character Setup

Line 1 defines four UDGs (\a, \b, \c, \d) by POKEing 8 bytes each into memory starting at USR "\a", USR "\b", USR "\c", and USR "\d". The data in line 2 provides 32 bytes total. These represent: a mouse (\a), the cat body (\b), a rat (\c), and what appears to be a cat-facing-left or venom sprite (\d). The cat is shown as \b in normal movement and flipped to \d when moving right or spitting.

Dual Input System

The program supports two input modes selected at line 11–14, stored in variable zz:

  • Keyboard mode: zz=155; the main loop runs at lines 155–245 using INKEY$ checks for keys 5, 6, 7, 8 (standard cursor keys).
  • Joystick mode: zz=2500; execution branches at line 165 to the joystick loop at lines 2500–2575 using the STICK function (TS2068-specific keyword, here written as | in source).

The joystick loop supports 8-directional movement via diagonal STICK values (5, 6, 9, 10) in addition to the cardinal directions. The keyboard loop only supports 4 directions.

Collision Detection via ATTR

The game uses ATTR reads exclusively for collision detection — no coordinate arrays are maintained for entity positions. Key attribute values are:

ATTR valueMeaning
59Mouse (INK 3, PAPER 7)
50Rat (INK 2, PAPER 6)
57Empty playfield cell (PAPER 7, INK 1 border is excluded; 57 = plain white cell)

Eating a mouse is detected at line 225 (keyboard) or 2550 (joystick) when the cat’s new position has ATTR 59. Rat collision is detected at lines 240/2560 with ATTR 50.

Timer Implementation

The elapsed time is read from the system frame counter via PEEK 23672 + 256*PEEK 23673, divided by 60 to convert frames to seconds. This is updated continuously during gameplay at lines 243–244 and 2565–2570. The variable t holds the elapsed time. The timer is reset at line 150 by POKEing 0 to both 23672 and 23673.

Difficulty and Rat Spawning

Each time a mouse is eaten, the subroutine starting at line 9980 spawns a replacement rat. The variable w (1, 2, or 3 for Easy, Tricky, Difficult) controls how many rats are spawned per mouse eaten. The logic uses the counter ab and a series of conditional GO TOs that loop back to 9980 to spawn additional rats:

  • Level 1 (w=1): 1 rat spawned per mouse.
  • Level 2 (w=2): Lines 9983–9984 cause the spawner to loop twice more, adding 3 rats total per mouse.
  • Level 3 (w=3): Lines 9986–9991 cause four loops, adding 4 rats per mouse.

This explains the stated maximum scores at line 414: Level 1:156 2:352 3:450, which reflect the increasing rat counts (each rat kill is worth 2 points via ss).

Venom/Spit Mechanic

Pressing "0" on keyboard (line 181) or the joystick fire button (line 2521, STICK (2,2)=1) triggers a spit attack. The condition checks ATTR (x,y-1)=50 — the cell immediately to the left must contain a rat. If so, a flashing "*" is shown with an ascending/descending tone sweep, the rat is erased, and ss is incremented by 2. The instruction text at line 7 notes the cat can only destroy a rat moving to the left, consistent with checking column y-1.

Notable Bugs and Anomalies

  • Line 400 is referenced by GO TO 400 at lines 232 and 2555 but does not exist; execution falls through to line 405. This is functionally harmless as 405 is the intended win-sequence start.
  • Line 408 is referenced at line 420 (GO TO 408) but does not exist, creating an infinite loop escape path from the post-game replay prompt that would cause a “Line not found” error.
  • Line 470 references variable a$ which is never defined elsewhere in the program, making it a dead code path.
  • Lines 9 and 10 (difficulty selection) are only reached if INKEY$ at line 8 is not “1” due to the lack of a PAUSE between key checks; the PAUSE 0 at line 8 waits for any key but the subsequent IF INKEY$ chain may misread the key state.
  • The joystick direction check at line 2502 and 2525 both test STICK (1,2)=8 (right), meaning the cat sprite toggles to the \d graphic AND moves right simultaneously, but the sprite print at 2500 uses \b — the facing logic partially duplicates keyboard line 160.
  • Variable ab is set to 0 at lines 232 and 2555 before the check, but the rat-spawning routine at 9980 increments ab as a local counter; this reset is correct for per-mouse-eaten spawning.

Subroutine and Flow Control

The jingle at line 9997 is called with GO SUB 9997 at multiple points (lines 23, 24, 55, 405–413, 450). The rat-spawner at 9980 is entered via GO TO 9980 from lines 225/2550 and exits via GO TO 232 or GO TO 2555 through line 9996, avoiding the use of GO SUB/RETURN for this inline routine. The RESTORE calls at lines 15 and 3000 reset the DATA pointer for re-reads, though the DATA at line 2 (UDG bytes) has already been consumed by line 1 and the subsequent RESTOREs point back for the board DATA at line 49.

Content

Appears On

Capital Area Timex Sinclair User Group’s Library Tape.

Related Products

Related Articles

Related Content

Image Gallery

Cat ‘n’ Mouse

Source Code

    1 RESTORE : FOR m=0 TO 7: READ a: POKE USR "\a"+m,a: NEXT m: FOR r=0 TO 7: READ b: POKE USR "\c"+r,b: NEXT r: FOR d=0 TO 7: READ c: POKE USR "\b"+d,c: NEXT d: FOR z=0 TO 7: READ d: POKE USR "\d"+z,d: NEXT z
    2 DATA 0,36,24,24,60,60,126,0,33,114,122,25,249,58,218,188,35,225,225,51,63,62,33,66,196,135,135,204,252,188,132,66
    3 CLS 
    4 LET bt=100000: LET bs=0
    5 BORDER 7: PAPER 7: INK 1: CLS : PRINT AT 0,0;"This game has been produced for Atari Joystick  (Right side)    OR Keyboard (use arrows).The cat can spit a deadly poisonous     venom.."; BRIGHT 1;"Press button on joystick OR ""0""on key board."; BRIGHT 0: PRINT INK 2;AT 11,0;"There is an on-screen timer and both time AND scor are showen at the end of each game.If you can successfully complete the game,the "; BRIGHT 1;TAB 4;"'best time'"; BRIGHT 0;TAB 16;"and "; BRIGHT 1;TAB 20;"'best score'"; BRIGHT 0;"(since loading) are displayed.": PAUSE 750
    6 PRINT AT 20,0;"Press any Key to Continue.": PAUSE 0: CLS 
    7 PRINT INK 2;"MICE = 1 POINT : RATS = 2 POINTS";AT 3,0; BRIGHT 1;"THE CAT  CAN ONLY DESTROY A RAT  WHEN IT IS MOVING TO THE LEFT  ": BRIGHT 0: PAUSE 400: PRINT INK 3;AT 8,0;"Your overall objective is to EATall the MICE and to DESTROY all the RATS as QUICKLY as you can."' INK 2;"          TAKE CARE!": PAUSE 500: PRINT AT 15,0; INK 1;"A  simpler  version might be to see how quickly you can eat allthe MICE while avouiding the RATS"; INK 2;AT 19,7;"BEWARE AT LEVEL 3!"; INK 4;AT 21,9;"Happy Hunting!": PAUSE 750: CLS 
    8 PRINT AT 4,0;"Select difficulty  1  2  3";AT 10,8;"1.Easy";AT 12,8;"2.Tricky";AT 14,8;"3.Difficult.": PAUSE 0: IF INKEY$="1" THEN LET w=1
    9 IF INKEY$="2" THEN LET w=2
   10 IF INKEY$="3" THEN LET w=3
   11 CLS : PAPER 3: BORDER 3: CLS : PRINT INK 7;AT 9,3;"  Press 'j' for joystick ";AT 14,3;" Press 'k' for keyboard": PAUSE 0
   12 IF INKEY$="j" THEN LET zz=2500: GO TO 15
   13 IF INKEY$="k" THEN LET zz=155: GO TO 15
   14 GO TO 11
   15 RESTORE 
   17 PRINT FLASH 1; INK 6;AT 3,2;"Do you want instructions? y/n";AT 20,27; FLASH 0: PAUSE 0: IF INKEY$="y" OR INKEY$="Y" THEN GO TO 20
   18 IF INKEY$="n" OR INKEY$="N" THEN GO TO 30
   19 GO TO 17
   20 PAPER 7: BORDER 7: CLS : PRINT INK 2;AT 0,2; FLASH 1;"PRESS 'Q' TO STOP GAME": GO SUB 9997
   21 PRINT INK 1;AT 2,2;"There are fifty mice....their   positions change  with  each  new game.  The CAT  has  to     EAT all the mice.": PAUSE 100: PRINT INK 1;AT 21,2; INK 3; BRIGHT 1;"\a\a\a\a\a\a\a\a\a\a": PAUSE 200: PRINT AT 21,2; PAPER 7; INK 3; BRIGHT 0;"\a\a\a\a\a\a\a\a\a\a"
   22 PRINT INK 3;AT 7,2;"There are also four rats ...to  begin with ....their positions change with each new game.": PAUSE 100: PRINT INK 3;AT 21,15; PAPER 6; INK 2; BRIGHT 1;"\c \c \c \c": PAUSE 200: PRINT AT 21,15; PAPER 6; INK 2; BRIGHT 0;"\c \c \c \c"
   23 PRINT INK 2;AT 11,2;"BUT  EVERY  TIME  A  MOUSE  IS EATEN , MORE   RATS   APPEAR!": GO SUB 9997
   24 PRINT INK 0;AT 15,2;"WARNING!!!     CAT.....BEWARE!  IF YOU TRY TO CATCH A RAT.....  THE RAT WILL EAT YOU!": PRINT OVER 1; INK 0;AT 16,2;"________________________         ____________________": OVER 0: PRINT AT 21,27; INK 0; BRIGHT 1;"\d \b": GO SUB 9997: PAUSE 250: PRINT AT 21,27; BRIGHT 0;"\d \b"
   26 PAPER 7: BORDER 7: CLS : PRINT ; FLASH 1; INK 0;AT 4,1;"CAT IS IN TOP LEFT HAND CORNER";AT 0,0;"\b"; INK 0;AT 10,10;"GET READY": PAUSE 350: FLASH 0: CLS 
   30 PAPER 7: BORDER 7: CLS : FOR A=0 TO 21: PRINT INK 1;AT A,0;"\  ": NEXT a
   35 FOR b=0 TO 31: PRINT INK 1;AT 21,b;" ": NEXT b
   40 FOR c=21 TO 0 STEP -1: PRINT INK 1;AT c,31;" ": NEXT c
   45 FOR d=31 TO 0 STEP -1: PRINT INK 1;AT 0,d;" ": NEXT d
   46 FOR a=0 TO 21: PRINT PAPER 4; INK 1; OVER 1;AT a,0;"*": NEXT a: FOR c=21 TO 0 STEP -1: PRINT PAPER 4; INK 1; OVER 1;AT c,31;"*": NEXT c
   47 RESTORE 47: FOR a=1 TO 10: READ b,c: PRINT PAPER 4; INK 1; OVER 1;AT 0,b;"*";AT 21,c;"*": NEXT a
   49 DATA 24,1,25,2,26,3,27,4,28,5,29,26,30,27,1,28,7,29,8,30
   55 PRINT INK 8; OVER 1;AT 0,10;"CAT 'n' MOUSE";AT 21,7;"  T.Braverman     ": GO SUB 9997
   60 FOR n=1 TO 50
   65 LET e=2+INT (RND*18): LET f=2+INT (RND*28)
   70 IF ATTR (e,f)=59 THEN GO TO 65
   80 PAPER 7: PRINT INK 3;AT e,f;"\a"
   85 NEXT n
   98 FOR o=1 TO 4
  100 LET g=2+INT (RND*18): LET h=2+INT (RND*28)
  105 IF ATTR (g,h)=59 THEN GO TO 100
  108 IF ATTR (g,h)=50 THEN GO TO 100
  110 PAPER 7: PRINT PAPER 6; INK 2;AT g,h;"\c": NEXT o
  130 LET s=0: LET ss=0
  140 LET y=1: LET x=1
  150 POKE 23692,0: POKE 23673,0
  155 PAPER 7: PRINT INK 0;AT x,y;"\b"
  160 IF INKEY$="8" THEN PRINT PAPER 7; INK 0;AT x,y;"\d"
  165 IF zz=2500 THEN GO TO 2500
  166 IF INKEY$="" THEN BEEP .04,-25: GO TO 243
  170 LET lx=x: LET ly=y
  180 IF INKEY$="q" THEN GO TO 9999
  181 IF INKEY$="0" AND ATTR (x,y-1)=50 THEN PRINT FLASH 1; INK 2;AT x,y-1;"*": FOR n=0 TO 20: BEEP (.25*.1),n: NEXT n: FOR n=20 TO 0 STEP -1: BEEP (.25*.1),n: NEXT n: PRINT AT x,y-1;" ": LET ss=ss+2
  186 IF INKEY$="5" THEN LET y=y-1: BEEP .05,-50
  191 IF INKEY$="8" THEN LET y=y+1: BEEP .05,-50
  196 IF INKEY$="6" THEN LET x=x+1: BEEP .05,-50
  201 IF INKEY$="7" THEN LET x=x-1: BEEP .05,-50
  203 PRINT AT lx,ly;" "
  210 IF x<1 OR x>20 THEN LET x=lx
  215 IF y<1 OR y>30 THEN LET y=ly
  225 IF ATTR (x,y)=59 THEN LET s=s+1: BEEP .025,30: BEEP .025,12: GO TO 9980
  232 LET ab=0: IF s=50 THEN CLS : GO TO 400
  240 IF ATTR (x,y)=50 THEN PRINT AT x,y; FLASH 1;"\c": LET b=.025: FOR t=1 TO 20: BEEP b,24: BEEP b,20: BEEP b,17: BEEP b,12: NEXT t: PRINT INK 0;AT x,y; FLASH 0;"\c": GO TO 450
  243 LET t=(PEEK 23672+256*PEEK 23673)/60
  244 PRINT INK 2;AT 0,2;t
  245 GO TO 155
  405 PRINT TAB 8; INK 2;"Score = ";s+ss;AT 3,8;t;" seconds ": GO SUB 9997: PAUSE 75
  406 IF t<bt THEN LET bt=t: PRINT INK 4;AT 6,4;"BEST TIME ";bt;" SECONDS";AT 9,7;"CONGRATULATIONS!": GO SUB 9997
  407 IF t>bt THEN PRINT INK 4;AT 6,4;"BEST TIME ";bt;" SECONDS";AT 9,1;"SLOWCOACH! I'M SUPRISED YOU           CATCH ANYTHING!": PRINT OVER 1;AT 10,14;"________": GO SUB 9997
  410 IF s+ss>bs THEN LET bs=s+ss: PRINT INK 2;AT 19,7;"Best score is ";bs
  412 IF s+ss=50 OR s+ss<bs THEN PRINT INK 2;AT 12,0;"Can't you do better? Try again!"
  413 PRINT AT 19,7;"Best score is ";bs
  414 PRINT AT 21,0;"MAXIMUM: Level 1:156  2:352  3:450": PAUSE 150
  416 PRINT INK 1; FLASH 1;AT 15,1;"Do you want to play again? y/n": PAUSE 0: IF INKEY$="y" OR INKEY$="Y" THEN FLASH 0: GO TO 3000
  418 IF INKEY$="n" OR INKEY$="N" THEN FLASH 0: GO TO 9999
  420 GO TO 408
  450 PRINT INK 2;AT 8,1;"CATastrophe! Eaten by THE RAT!";AT 10,7; FLASH 1;"Your score is ";s+ss: GO SUB 9997: FLASH 0
  455 PAUSE 150
  460 PRINT INK 2; FLASH 1;AT 12,1;"Do you want to play again? y/n"
  465 IF INKEY$="y" OR INKEY$="Y" THEN FLASH 0: GO TO 3000
  467 IF INKEY$="n" OR INKEY$="N" THEN FLASH 0: GO TO 9999
  468 GO TO 460
  470 IF a$="y" THEN GO TO 10
  475 CLS : GO TO 9999
 2500 PRINT PAPER 7: PRINT INK 0;AT x,y;"\b"
 2502 IF STICK (1,2)=8 THEN PRINT PAPER 7; INK 0;AT x,y;"\d"
 2505 IF STICK (1,2)=0 THEN BEEP .04,-25: GO TO 243
 2510 LET lx=x: LET ly=y
 2520 IF STICK (1,2)=4 THEN LET y=y-1: BEEP .05,-50
 2521 IF STICK (2,2)=1 AND ATTR (x,y-1)=50 THEN PRINT INK 2; FLASH 1;AT x,y-1;"*": FOR n=0 TO 20: BEEP (.25*.1),n: NEXT n: FOR n=20 TO 0 STEP -1: BEEP (.25*.1),n: NEXT n: PRINT AT x,y-1;" ": LET ss=ss+2
 2525 IF STICK (1,2)=8 THEN LET y=y+1: BEEP .05,-50
 2530 IF STICK (1,2)=2 THEN LET x=x+1: BEEP .05,-50
 2531 IF STICK (1,2)=5 THEN LET x=x-1: LET y=y-1: BEEP .05,-15
 2532 IF STICK (1,2)=6 THEN LET x=x+1: LET y=y-1: BEEP .05,-15
 2533 IF STICK (1,2)=9 THEN LET x=x-1: LET y=y+1: BEEP .05,-15
 2534 IF STICK (1,2)=10 THEN LET x=x+1: LET y=y+1: BEEP .05,-15
 2535 IF STICK (1,2)=1 THEN LET x=x-1: BEEP .05,-50
 2537 PRINT AT lx,ly;" "
 2540 IF x<1 OR x>20 THEN LET x=lx
 2545 IF y<1 OR y>30 THEN LET y=ly
 2550 IF ATTR (x,y)=59 THEN LET s=s+1: BEEP .025,30: BEEP .025,12: GO TO 9980
 2555 LET ab=0: IF s=50 THEN CLS : GO TO 400
 2560 IF ATTR (x,y)=50 THEN PRINT AT x,y; FLASH 1;"\c": LET b=.025: FOR t=1 TO 20: BEEP b,24: BEEP b,20: BEEP b,17: BEEP b,12: NEXT t: PRINT INK 0;AT x,y; FLASH 0;"\c": GO TO 450
 2565 LET t=(PEEK 23672+256*PEEK 23673)/60
 2570 PRINT INK 2;AT 0,2;t;"                   "
 2573 IF STICK (1,2)=1 THEN GO TO 160
 2575 GO TO 155
 3000 RESTORE 
 3005 CLS : GO TO 8
 9980 LET i=2+INT (RND*18): LET j=2+INT (RND*28)
 9981 LET ab=ab+1: IF ATTR (i,j)<>57 THEN GO TO 9980
 9982 PRINT PAPER 6; INK 2;AT i,j;"\c"
 9983 IF w=2 AND ab=1 THEN GO TO 9980
 9984 IF w=2 AND ab=2 THEN GO TO 9980
 9986 IF w=3 AND ab=1 THEN GO TO 9980
 9990 IF w=3 AND ab=2 THEN GO TO 9980
 9991 IF w=3 AND ab=3 THEN GO TO 9980
 9996 GO TO 232
 9997 BEEP .25,0: BEEP .25,5: BEEP .25,0: BEEP .25,-3: BEEP .25,0: BEEP .25,5: BEEP .25,0: BEEP .25,-3: BEEP .25,0: BEEP .25,5: BEEP .25,9: BEEP .25,7: BEEP .25,5: BEEP .25,7: RETURN 
 9998 SAVE "PAWS*" LINE 1
 9999 STOP 

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

People

No people associated with this content.

Scroll to Top