--- title: "Cat ‘n’ Mouse" id: 54552 type: "computer_media" slug: "paws" url: "http://localhost/computer_media/paws/" markdown_url: "http://localhost/computer_media/paws.md" published_at: "2024-06-02T16:53:25+00:00" modified_at: "2026-03-30T21:29:24+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "Guide a cat through a crowded playfield, eating 50 mice while dodging deadly rats that multiply with every catch — how fast can you clear the board?" 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/" 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/" - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 51207 title: "CATS Library Tape 6" type: "computer_media" url: "http://localhost/computer_media/cats-library-tape-6/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/06/Cat-n-Mouse-2.png" - url: "http://localhost/wp-content/uploads/2024/06/Cat-n-Mouse-1.png" media_type_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 value | Meaning | | --- | --- | | 59 | Mouse (INK 3, PAPER 7) | | 50 | Rat (INK 2, PAPER 6) | | 57 | Empty 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. ## 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 tbt 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+ss20 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 ```