HANG-MAN

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

HANG-MAN is a word-guessing game that selects a random word from a large DATA pool of over 400 entries spanning science, geography, computing, and everyday vocabulary. The gallows and hanged figure are rendered using seven custom UDG characters (A through G) defined by POKEing bitmap data into the UDG area, with a 13-frame animation stored in the string array b$(13,5) that plays before each round. Wrong guesses cause the program to print wrong letters incrementally across the screen using INVERSE and INK attributes, while correct guesses are revealed in-place using SCREEN$ to compare displayed characters against the target word. The game tracks wrong-letter positions with variables h, v, and d, spreading them across the display in a zigzag pattern as errors accumulate.


Program Structure

The program is organized into a main flow with several subroutines:

  • Lines 10–80: Title screen animation, playing the gallows graphic frame-by-frame using b$() and printing the word “HANG-MAN” letter by letter.
  • Lines 90–280: Core game loop — word selection, guess input, right/wrong letter handling, win/loss detection.
  • Lines 290–380: End-of-game display (win or lose), with a defeat fanfare using chained BEEP calls.
  • Lines 390–430: Wrong-guess subroutine, placing the guessed letter on-screen and advancing the UDG gallows animation.
  • Line 440: Short ascending-pitch sound effect subroutine (used as a fanfare/transition).
  • Lines 450–640: Word-selection subroutine using RESTORE and random READ skipping.
  • Lines 650–730: Initialization subroutine — sets border/paper/ink, dimensions the string array, reads UDG frame strings, and POKEs the UDG bitmaps.
  • Lines 740–800: UDG bitmap DATA for characters A–G.

Word Selection Technique

The word-selection subroutine at line 450 uses a notable idiom: RESTORE 450 resets the DATA pointer to the start of the word list, then a FOR loop performs READ w$ a random number of times (1 to 400) before exiting, leaving w$ holding whichever word was landed on. This is a well-known technique for random DATA selection without needing to load words into an array. The word pool spans over 400 entries across thirteen DATA statements (lines 480–630), covering computing terms, geography, science, grammar, and common vocabulary.

UDG Graphics and Animation

Seven UDGs (A through G) are defined in lines 710–800. The bitmap data is POKEd into USR "[UDG-A]" and subsequent bytes for all seven characters (7 bytes × 8 rows each, totaling 56 bytes read from DATA). The placeholder U appears repeatedly in the DATA lines — this is likely intended to represent 0 but may be a bug, since U is not a numeric value and would cause a BASIC error; it may be a tokenized or substituted value in the original file.

The 13-frame gallows animation is stored in the string array b$(13,5), each element being a 5-character string composed of UDG characters. These frames are printed sequentially in the title sequence (line 30) using TAB 13, building up the gallows image row by row.

SCREEN$ Letter-Reveal Mechanic

Correct letter reveals use an interesting approach: rather than maintaining a separate “guessed so far” string, the program reads back what is currently displayed on screen using SCREEN$(0,(a*2)-2) in line 230, concatenating the on-screen characters into c$ and comparing against w$. This technique avoids needing a separate tracking array and doubles the display as program state, but it is sensitive to screen layout — the word underscores are printed starting at row 0 with two-character spacing, and correct letters are printed into those exact positions at line 260.

Wrong Guess Tracking

Wrong letters are placed on-screen with INVERSE 1; INK 4 at line 400, and their screen positions are managed by three variables:

  • h: horizontal column, starting at 18 and incrementing by 2 each wrong guess.
  • v: vertical row, starting at 0 and incrementing when h exceeds column 31.
  • d: an offset counter tied to the gallows animation frame index via INT((d-16)/2) at line 420.

When the gallows animation reaches frame 13 (all 13 UDG frames displayed), the game branches to the loss screen at line 290.

Input Handling

Line 150 uses the PAUSE 0/INKEY$ idiom to wait for a keypress efficiently. An additional check discards the Enter key (CHR$ 13) to prevent accidental blank submissions. The letter matching loop (lines 170–190) counts occurrences of the guessed letter in the word, storing the count in r; a non-zero result routes to the correct-guess handler at line 250.

Notable Bugs and Anomalies

  • The DATA lines 740–800 contain the identifier U as a numeric value (e.g., DATA 0,U,U,7,15,28,24,U). Since U is not a defined variable in BASIC at that point and is unquoted, this would cause a “Variable not found” error at runtime. It is likely a transcription artifact where zeros or a specific byte value have been replaced with a placeholder symbol.
  • Line 510 contains "EPLOY", which is probably a truncated word (possibly “EMPLOY” missing its first two letters) — a data-entry error.
  • Line 510 also contains "JUVINILE" (misspelling of “JUVENILE”) and "THEAAER" (likely “THEATER” or “THEATRE” with corrupted characters).
  • Line 530 contains "HIGHT" (likely intended as “HEIGHT”).
  • Line 630 contains "DILEMA" (misspelling of “DILEMMA”) and "SODRIETY" (likely “SOBRIETY”).
  • Line 540 contains "OVERSEA" (typically “OVERSEAS”).
  • The subroutine at line 450 reads up to INT(RND*400)+1 words, but there are fewer than 400 words in the DATA, which will cause an “Out of DATA” error on some calls. The actual word count is closer to 350.
  • Line 610 contains "GESSET", which does not appear to be a real English word; likely a typo.
  • Line 620 contains "SUCCOMB" (misspelling of “SUCCUMB”), though this appears in a DATA line not reached by the word-selector if DATA runs out first.

Sound Effects

The game makes extensive use of BEEP throughout: a rising chromatic scale in the transition subroutine (line 440), random-pitch tones on correct guesses (line 260), a wrong-guess click (line 400), and a multi-note defeat fanfare across lines 320–340. The title animation also uses repeated short beeps synchronized with graphic display (line 30).

Key Variables Summary

VariablePurpose
w$The target word for the current round
n$The player’s current guess letter
t$String of wrong guesses (for display)
c$Characters read back from screen for win check
b$(13,5)13-frame gallows UDG animation strings
rCount of occurrences of guessed letter in word
d, h, vWrong-guess position and gallows frame counters

Image Gallery

Source Code

  10 GO SUB 440
  20 GO SUB 650
  30 FOR a=1 TO 13:PAUSE 10:BEEP .011,30:PRINT INK 6; TAB 13;b$(a):NEXT a
  40 FOR a=7 TO 22 STEP 2:PRINT AT 15,a+1;"_ ":PAUSE 5:NEXT a
  50 LET a=6
  60 BEEP .011,30:PRINT AT 15,a+2;"H "; AT 15,a+4;"A "; AT 15,a+6;"N"
  70  PRINT  AT 15,a+8;"G"; AT 15,a+10;"-"; AT 15,a+12;"M"; AT 15,a+14;"A"; AT 15,a+16;"N"
  80 GO SUB 440:CLS :REM SPELLING
  90 RANDOMIZE :POKE 23658,8
 100 GO SUB 690
 110 GO SUB 450
 120 FOR a=1 TO LEN w$
 130 PRINT "_ ";:NEXT a
 140 BEEP .2, RND*30
 150 PRINT AT 21,4;"Guess (only 1 letter) ":PAUSE 0:LET N$= INKEY$:IF N$= CHR$ 13 THEN GO TO 150
 160 PRINT AT 21,27;N$
 170 LET r=0:FOR a=1 TO LEN w$
 180 IF w$(a)=n$ THEN LET r=r+1
 190 NEXT a
 200 IF r <>0 THEN GO TO 250
 210 LET t$=t$+n$+" "
 220 GO SUB 390
 230 LET c$="":FOR a=1 TO LEN w$:LET d$= SCREEN$ (0,(a*2)-2):LET c$=c$+d$:NEXT a:IF c$=w$ THEN GO TO 360
 240 PRINT AT 21,27;" ":GO TO 150
 250 FOR a=1 TO LEN w$
 260 IF w$(a)=n$ THEN BEEP .1, RND*20+10:PRINT AT 0,(a*2)-2;n$
 270 NEXT a
 280 GO TO 230
 290 PRINT AT 5,19;"[UDG-F]"
 300 PRINT AT 5,0;"You killed him!!"
 310 PRINT AT 7,0;"The word was "; AT 8,0;w$
 320 BEEP 1,4:BEEP 1,4:BEEP .3,4:BEEP 1.2,4
 330 BEEP .75,7:BEEP .5,6:BEEP 1,6:BEEP .3,4
 340 BEEP .7,4:BEEP .5,3:BEEP 1,4
 350 GO TO 380
 360 PRINT AT 5,0;"YOU GOT IT!!!"
 370 GO SUB 440
 380 PRINT INK 2; AT 21,0;"  Press any key to play again   ":PAUSE 0:BEEP .1, RND*30:GO TO 100                     
 390 LET d=d+2:LET h=h+2:IF h>31 THEN LET v=v+1 :LET h=18
 400 BEEP .1,-10:PRINT AT v,h; INK 4; INVERSE 1;n$
 410 PRINT AT INT (d/2)+2-5,17; INK 6;b$(INT ((d-16)/2))
 420 IF INT ((d-16)/2)=13 THEN GO TO 290
 430 RETURN 
 440 FOR a=0 TO 50:BEEP .011,a:NEXT a:RETURN 
 450 RESTORE 450
 460 FOR a=1 TO INT (RND*400)+1
 470 READ w$:NEXT a
 480 DATA "RECEIVE","MISSISSIPPI","DIGITIZE","ANVIL","WHICH","WITCH","SEE","SEA","SPECTRUM","INFORMATION","DEFINE","UTAH","U.S.A.","CLEVELAND","MEMPHIS","PACIFIC OCEAN","ATLANTIC OCEAN","MAIN","U.S.S.R.","FREE","APE","CAT","APPLE","ARTHROPOD","BINARY","BIT","BYTE","VALENTINE"
 490 DATA "CURRENCY","ACIDS","OBLIQUE","ALKALI","BEVEL","STRATA","MORTGAGE","VOLTAGE","MUSEUM","ENVELOPE","ALUMINUM","OLYMPICS","CEREA","NEBULA","ANTONYMS","AMPERE","SYNONYMS","VEHICLE","ELEMENTS","PALLETS","FUNCTION","PALETTE","MYSTERY","PALATE","ONYX"
 500 DATA "CALCIFY","MACADAM","DOUBLET","DUCKLING","DUNE","DUEL","DWARF","EMBANK","EPLOY","ENCOUNTER","ENGINE","ENLIVEN","ENVELOPE","EQUINOX","FADE","FEEL","FENCE","FILL","FINISH","FISH","FLAG"
 510 DATA "NUMERIC","YOGURT","BOUNDARY","MEMORY","LIQUID","SCULPTOR","AZTECS","THOUGHT","INCA","CERAMIC","MAYA","MODEM","LIBRARY","STOMACH","OPERANDS","CABBAGE","ARRAY","INTAGLIO","ARGUMENTS","RELIEF","SILICON","GAZEBO","EIGHT","COLUMNS","JUVINILE","THEAAER"
 520 DATA "PRIMARY","BLUE","ELIGIBLE","VERTEBRA","CARE","CASTANETS","CATCH","CELL","SYRINGE","CHAPEL","CLASSIC","COACH","LIP","BORDER","LIGHT","HIGHT","POET","POETRY","REVENUE","GEAR","PI","REVERIE","OPEN","CLOSE","LINE","TRUE","VIDEO"
 530 DATA "EXTINCT","QUOTIENT","MALADY","ANSWER","MELODY","ANTIQUE","TURBINE","HEIRLOOM","AUGER","PROPHESY","ISLAND","ASTERISK","SEPARATE","TRUNCATE","MACABRE","CELSIUS","CALENDAR","KELVIN","MACHINE","EXHAUST","ACCESS","KIOSK","GRAPHICS"
 540 DATA "MASS","MATCH","MAZE","MELT","MILL","MEDIUM","MELLOW","MOUNT","MOON","MOTOR","MYSTIFY","NERVE","NICHE","NOSTALGIA","OBJECT","ONCE","OPTICAL","ORANGE","ORB","ORDINARY","ORPHAN","OBTUSE","OZONE","OVERSEA"
 550 DATA "ICICLE","COMPILER","STELLAR","SERIAL","HOMONYMS","FOREIGN","NUCLEAR","IMAGINE","HEXAGON","LANGUAGE","VESSEL","ECSTASY","SCIMITAR","BLOOD","SCIENCES","SWAHILI","VERTIGO","HINDU","VARIABLE","DECADE","OBELISK"
 560 DATA "COMPUTER","AUGUST","DATA","ZOO","ZOOM","NOW","ENTERED","KILL","FOR","GET","AND","INK","LET","ONLY","NEXT","GO","TO","OF","THE","WORD","PRINT","AT","ARE","WHO","MISTER","NO","YES","WHY","MOVE","EDIT","LOCK","COPY","DRAW","WILL"
 570 DATA "ABALONE","DECIMAL","SANDWICH","RANDOM","VALID","VOID","SYSTEM","AMATEUR","CREEPY","SYNTAX","DIGITIZE","MATRIX","PARALLEL","CIRCUITS","ZENITH","PRISM","SPECTRUM","ELECTRIC","INDEX","CURSOR","AERIAL","MAGNETIC","NUTRIENT"
 580 DATA "PROTOCOL","NOT","ERSATZ","MASTER","GONE","BE","BEEP","LESSON","IMAGINE","GNU","CHARIOT","YO-YO","SCHOOL","MY","ME","RETURN","DOCTOR","STOP"
 590 DATA "PIXEL","OXYGEN","ALPHABET","GUIDE","QUICHE","QUEUE","UNIVERSE","MATTE","GALAXY","OBVERSE","REVERSE","CATEGORY","GREEN","KITCHEN","AXIOM","CEILING","SPECIFIC","ENERGY","ADROIT","MEDIA","OASIS","TRIVET","TRIPOD","TRIVIA"
 600 DATA "JETSAM","ASTERISK","DIDN'T","ERASE","PERSONAL","RED","MOVE","DRAW","AIRSHIP","AIRCRAFT","APPLY","ARCTIC","BARROW","BINARY","BIRCH","BIZARRE","BYTES","BLISTER","BLOOD","BOBTAIL","WHIPPET","BRAIN","CAMERA","CANOE","CAP"
 610 DATA "GRAFFITI","ARTERY","THERAPY","OBSERVE","ACRYLIC","ACQUIT","ANNEAL","ACRONYM","CHARISMA","OPTICS","GYRATE","GESSET","INTERIM","DASH","MEDIAN","PLASMA","POISE","PRECEDE","PROCEED","SUCCOMB","FLOTSAM"
 620 DATA "POWER","IF","LIST","PAPER","FLASH","OVER","CODE","CLEAR","BRIGHT","SCREEN","SOUND","STICK","SON","SUN","CIRCLE","MERGE","ON","OFF","VERIFY","SAVE","OR","PAUSE","IN","OUT","PLOT","NEW","BLACK","CYAN","RESET","THEN","FOUR","FORMAT","BATON","KIOSK","FUNCTION"
 630 DATA "SLUICE","RECLUSE","APOCRYPHAL","ENIGMA","DILEMA","COMPEL","DECIPHER","SYMMETRY","SIMIAN","FLUX","SATIRE","DOMICILE","ATRIUM","PARITY","SPOOF","SODRIETY","CADAVER","APOGEE","PSYCHOTIC","ABSCISSA","IMPEL","INDUCE","FLOC","SATYR","DENSITY"
 640 RETURN 
 650 BORDER 1:PAPER 0:INK 9:CLS 
 660 DIM b$(13,5)
 670 RESTORE 680:FOR a=1 TO 13:READ b$(a):NEXT a
 680 DATA " [UDG-A][UDG-E][UDG-C]"," [UDG-F][UDG-G][UDG-F]"," [UDG-B][UDG-E][UDG-D]","[UDG-A][UDG-E][UDG-E][UDG-E][UDG-C]","[UDG-F][UDG-F] [UDG-F][UDG-F]","[UDG-F][UDG-F] [UDG-F][UDG-F]","[UDG-F][UDG-F] [UDG-F][UDG-F]","[UDG-F][UDG-F] [UDG-F][UDG-F]","[UDG-B][UDG-D][UDG-E][UDG-B][UDG-D]"," [UDG-F][UDG-F][UDG-F]"," [UDG-F][UDG-F][UDG-F]"," [UDG-F][UDG-F][UDG-F]","[UDG-A][UDG-C] [UDG-A][UDG-C]"
 690 LET t$=""
 700 LET h=16:LET v=0:LET d=h
 710 RESTORE 710:FOR a=0 TO 55
 720 READ u:POKE USR "[UDG-A]"+a,u
 730 NEXT a:RETURN 
 740 DATA 0,U,U,7,15,28,24,U
 750 DATA 24,U,28,15,7,0,U,U
 760 DATA 0,U,U,224,240,56,24,U
 770 DATA 24,U,56,240,224,0,U,U
 780 DATA 0,U,U,255,U,0,U,U
 790 DATA 24,U,U,U,U,U,U,U
 800 DATA 0,U,102,U,0,U,U,U
 810 REM A=[UDG-A] B=[UDG-B] C=[UDG-C] D=[UDG-D] E=[UDG-E] F=[UDG-F] G=[UDG-G]
 999 SAVE "HANGMAN" LINE 1

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