Hangcat

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

Hangcat is a two-player word-guessing game in the Hangman tradition, where one player enters a secret word and the second player attempts to guess it letter by letter within nine lives. The program uses a dash-filled string `g$` as a mask that reveals correctly guessed letters in place, and tracks used letters in the string `u$` for display. A subroutine at line 2000 renders an animated title by copying character ROM data into two UDG slots (`\a` and `\b`) on a per-character basis, effectively scrolling custom-shaped glyphs across two display rows. BEEP sequences signal both incorrect guesses and a winning fanfare, and FLASH 1 highlights the win/loss message.


Program Analysis

Program Structure

The program is organized into three logical phases: setup (lines 5–95), the main game loop (lines 100–330), and a title-screen subroutine (lines 2000–2030). A SAVE statement at line 9999 acts as a standalone utility line for archiving the program with auto-run at line 1 (which falls through to line 5).

  1. Initialization (lines 10–95): Sets screen colors, calls the title subroutine, prompts Player 1 for a secret word, and builds the dash-mask string g$.
  2. Game loop (lines 100–330): Displays the current mask, lives remaining, used letters, and solicits a letter guess each iteration.
  3. Title subroutine (lines 2000–2030): Renders the title string using dynamically loaded UDGs.

Word Masking and Guess Matching

The secret word is stored in a$. The mask string g$ is initialized to a string of dashes equal in length to a$ (lines 60–90). When the player guesses a letter x$, lines 160–200 iterate over each character of a$; a match sets the flag f=1 and writes x$ directly into the corresponding position of g$ via LET g$(z)=x$ (line 190), exploiting Sinclair BASIC’s in-place string character assignment.

Win detection at line 260 is a simple string equality test: g$=a$. When all dashes are replaced by correct letters, the condition becomes true. The lives counter t starts at 9 and decrements by 1 for each incorrect guess (line 250).

UDG-Based Title Rendering (Subroutine 2000)

The most technically distinctive feature is the animated title. Line 2020 loops over every character in the title string m$. For each character, it calculates the ROM font address: c = 15616 + (8 * (CODE m$(a) - 32)). This is the standard TS2068/Spectrum formula for locating the 8-byte bitmap of a character in the ROM font (font starts at address 15616).

It then copies those 8 bytes into two UDG slots simultaneously — UDG \a and UDG \b — by writing each byte to both USR "a" + (b*2) and USR "a" + (b*2) + 1. This doubles the width of each glyph horizontally, producing a wider, blocky title character. Each character is then printed at row y and row y+1 using INVERSE 1, giving a two-row tall inverse-video title.

Key BASIC Idioms and Techniques

  • In-place string assignment: LET g$(z)=x$ replaces a single character within a string, a Spectrum/TS2068 BASIC feature not available on all platforms.
  • Used-letters tracking: u$ starts as a single space and grows by concatenation each turn (line 145). The condition IF u$<>" " at line 125 suppresses display until at least one guess has been made.
  • Centered text: TAB 15-(LEN g$/2) (line 220) and AT y, (32-LEN m$)/2 (line 2010) perform runtime centering calculations.
  • BEEP fanfares: A losing sequence uses three discrete BEEP calls (line 270); a winning sequence uses a FOR loop ascending in pitch (line 280).
  • Input validation: Both the word input (line 55) and the letter input (line 142) reject empty strings with a redirect back to the INPUT line.

Variable Summary

VariableRole
a$Secret word entered by Player 1
g$Current guess mask (dashes replaced by correct letters)
u$Accumulated string of letters guessed so far
x$Current letter guess
tLives remaining (starts at 9)
fFlag: 1 if last guess was correct, 0 otherwise
m$Title string used in subroutine 2000
cROM font address for current title character
dUDG destination address during title rendering

Bugs and Anomalies

  • Used-letters string grows unbounded: u$ appends every guess including repeats, so a player who guesses the same letter twice will see it listed twice. There is no duplicate-guess check.
  • Line 290 layout: The comma after a$ before TAB (PRINT "..."-,;TAB...) produces a comma-separator print, which may cause unexpected column advancement depending on the current print position; the semicolon modifier on ,; is redundant but harmless.
  • Play-again loop: Lines 320–330 poll INKEY$ in a tight loop but only check for "y"; pressing "n" does nothing and the loop continues indefinitely. The program can only be exited by pressing BREAK or entering "y".
  • UDG byte stride: The title subroutine writes each font byte to USR "a" + (b*2), stepping by 2 rather than 1 through the UDG area. This means only bytes at even offsets from USR "a" are written, which spans into UDG \b territory — intentional, as it populates both UDGs, but the approach is unusual and tightly coupled to UDG memory layout.

Content

Appears On

Pure fun — land on the moon, herd sheep, hunt submarines, race cricketers, eat dots as Pac-Man, and dodge alien swarms across a nighttime skyline. SINCUS Tape 101 is a deep bench of TS 2068 arcade action, card games, and sports simulations.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

    5 REM hangcat  Version 3.0
   10 BORDER 1: PAPER 1: INK 7: CLS 
   15 GO SUB 2000
   20 PRINT AT 16,4;"Player 1 - Type in a word."
   25 PRINT AT 18,5;"(Player 2 - DON'T LOOK!)"
   50 INPUT a$
   55 IF a$="" THEN GO TO 50
   60 LET g$="-"
   70 FOR z=1 TO LEN a$-1
   80 LET g$=g$+"-"
   90 NEXT z
   95 LET u$=" "
  100 LET t=9
  110 CLS 
  111 PRINT : PRINT : PRINT AT 4,(32-LEN g$-1)/2;g$: PRINT : PRINT : PRINT 
  115 IF t<2 THEN PRINT "        You have 1 life.": GO TO 123
  120 PRINT "       You have ";t;" lives."
  123 PRINT : PRINT 
  125 IF u$<>" " THEN PRINT "Letters used=";u$
  127 PRINT : PRINT 
  130 PRINT "  GUESS A LETTER OF THE WORD."
  140 INPUT x$
  142 IF x$="" THEN GO TO 140
  143 CLS 
  145 LET u$=u$+x$
  150 LET f=0
  160 FOR z=1 TO LEN a$
  170 IF x$<>a$(z) THEN GO TO 200
  180 LET f=1
  190 LET g$(z)=x$
  200 NEXT z
  210 PRINT : PRINT : PRINT : PRINT 
  220 PRINT TAB 15-(LEN g$/2);g$
  225 PRINT : PRINT : PRINT 
  230 IF f=0 THEN PRINT TAB 11;"INCORRECT"
  240 IF f=1 THEN PRINT TAB 12;"CORRECT"
  245 PRINT : PRINT 
  250 IF f=0 THEN LET t=t-1
  260 IF t>0 AND g$<>a$ THEN GO TO 115
  270 IF g$<>a$ THEN PRINT "        "; FLASH 1;"YOU'RE A GONER.": BEEP 0.7,1: BEEP 0.5,1: BEEP 1,6
  280 IF g$=a$ THEN PRINT "        "; FLASH 1;"CONGRATULATIONS!": FOR x=1 TO 30: BEEP .01,x: NEXT x
  285 PRINT : PRINT 
  290 PRINT "     The correct word was-",;TAB 15-(LEN g$/2);a$
  300 PRINT 
  310 PRINT "    Want to play again? (y/n)"
  320 IF INKEY$="y" THEN RUN 
  330 GO TO 320
 2000 REM   title
 2010 LET m$=" H A N G C A T ": LET y=8: LET x=((32-LEN m$)/2)
 2020 FOR a=1 TO LEN m$: LET c=15616+(8*(CODE m$(a)-32)): FOR b=0 TO 7: LET d=(USR "a"+(b*2)): POKE d,PEEK (c+b): POKE (d+1),PEEK (c+b): NEXT b: PRINT AT y,x; INVERSE 1;"\a";AT y+1,x;"\b": LET x=x+1: NEXT a
 2030 RETURN 
 9999 SAVE "hangcat" LINE 1: BEEP 1,33

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

People

No people associated with this content.

Scroll to Top