Wordfind

Developer(s): Bruce J. Schaffer
Date: 1984
Type: Program
Platform(s): TS 2068
Tags: Education

A word-search game played with a joystick. An 11-by-11 grid of letters in a custom typeface fills the right of the screen, and five words from a list of about 370 are listed on the left. One of them is hidden in the grid, across, down or diagonally and sometimes backwards. You move a flashing cursor with the joystick and press FIRE on each letter of the word in turn. Get it right and the word fills the screen with “IS CORRECT!”; press a wrong letter and the answer is shown. If you take too long the hidden word is highlighted in the list as a hint. Z prints the screen. The words are mostly harder vocabulary, such as ISOSCELES, PALINDROME and SOLILOQUY.

A REM dates the program 4/9/84. The opening screen spells WORDFIND in the grid and ©B.SCHAFFER diagonally through it.

Program Analysis

Structure

  • Lines 20–170: set-up, the title animation and the “Press FIRE BUTTON to begin” prompt, which takes either joystick port.
  • Lines 180–390: the cursor loop, reading STICK for direction and fire and checking each pressed letter against the stored positions in C(11,2).
  • Lines 400–530: the correct and wrong-answer displays.
  • Lines 540–1010: choose five words, place one in the grid at a random angle, fill the rest with random letters and print it.
  • Lines 1020–1060: read the word list into W$(400,10). Lines 1070–1150: the character set. Lines 1330–2110: the words.

Two character sets

Lines 1090–1150 POKE new shapes for the capital letters A–Z, the full stop and the © sign into memory above RAMT=63000, laid out as a character set that starts at 62744. The program switches between that set and the ROM set by POKEing CHARS (23606/7), so the grid uses the bold letters and the messages use the normal ones.

Notable Techniques

  • ON ERR GO TO 1060 ends the word-list READ loop when the DATA runs out, so the number of words never has to be stored.
  • Joystick input uses the TS2068 STICK function for both direction and fire.
  • For a backwards word the stored letter positions are reversed by packing them into a string with CHR$ (n+50) and reading it back the other way (line 860).

Potential Issues

  • The game needs a TS2068 joystick. There is no keyboard control.

This program came from an Oliger (JLO SAFE) disk, a copy of the SNUG library disk 17/18, and was converted to load from tape. The SAVE / in line 2120 became a plain SAVE. It was tested in ZEsarUX up to the fire-button prompt. ZEsarUX does not emulate the TS2068 joystick, so a test-only copy that skipped the prompt was used to show the puzzle screen; joystick play itself was not tested.

Image Gallery

Source Code

   10 REM *** program WORDFIND   UPDATED 4/9/84
   20 CLEAR 62999: LET RAMT=63000: RANDOMIZE 
   30 LET ink=INT (RND*6)+1
   40 OVER NOT PI: FLASH NOT PI: BRIGHT NOT PI: INVERSE NOT PI: PAPER ink: BORDER ink: INK 9: CLS : PRINT FLASH SGN PI;"PLEASE WAIT"
   50 DIM I(9): DIM Y(10): DIM D(22,32): DIM W(5): DIM C(11,2): DIM L(400): DIM W$(400,10)
   60 LET tog1=24: LET tog2=245
   70 GO SUB 1070
   80 LET A$="WORDFIND": LET B$=A$: LET flag=1: LET flag2=flag: GO SUB 540
   90 PAUSE VAL "60": GO SUB 450: PAUSE VAL "30"
  100 LET A$="*B.SCHAFFER": LET B$=A$: FOR L=SGN PI TO 15: BEEP .02,INT (RND*25): NEXT L: GO SUB 540
  110 PAUSE VAL "60": GO SUB 450: GO SUB 1020: FOR L=SGN PI TO 15: BEEP .02,INT (RND*25): NEXT L
  120 PAUSE 30: LET flag=0
  130 POKE 23606,0: POKE 23607,60
  140 PRINT AT 7,2;"Press "''"  FIRE"''" BUTTON"''"to begin": FOR L=SGN PI TO 4: BEEP .02,20: NEXT L
  150 IF |(2,1)=1 THEN BEEP .2,20: LET port=1: PAPER NOT PI: BORDER NOT PI: CLS : GO TO 540
  160 IF |(2,2)=1 THEN BEEP .2,20: LET port=2: PAPER NOT PI: BORDER NOT PI: CLS : GO TO 540
  170 GO TO 150
  180 REM ***|
  190 LET CT=0: LET TIME=INT (RND*200)+100: LET COUNT=ct
  200 LET A=10: LET B=21: IF ATTR (A,B)<>7 THEN LET A=8: LET B=25
  210 LET A1=A: LET B1=B: PRINT FLASH SGN PI;AT A,B;CHR$ D(A+1,B)
  220 LET INV=0
  230 IF |(1,port)=5 OR |(1,port)=1 OR |(1,port)=9 THEN LET A=A-2: BEEP .01,A
  240 IF |(1,port)=6 OR |(1,port)=2 OR |(1,port)=10 THEN LET A=A+2: BEEP .01,A
  250 IF |(1,port)=6 OR |(1,port)=5 OR |(1,port)=4 THEN LET B=B-2: BEEP .01,B
  260 IF |(1,port)=8 OR |(1,port)=9 OR |(1,port)=10 THEN LET B=B+2: BEEP .01,B
  270 LET CT=CT+1: IF CT=TIME THEN FOR N=SGN PI TO LEN A$: BEEP .01,N*4: PRINT INK 3; INVERSE SGN PI;AT 4+(XWORD-1)*3,N-1;W$(W(XWORD),N): NEXT N
  280 IF B>31 THEN LET B=31
  290 IF B<11 THEN LET B=11
  300 IF A>20 THEN LET A=20
  310 IF A<0 THEN LET A=0
  320 IF ATTR (A,B)<>7 THEN LET INV=1: LET A=A1: LET B=B1: GO TO 340
  330 IF A<>A1 OR B<>B1 THEN POKE 23606,tog1: POKE 23607,tog2: PRINT INVERSE INV; INK (9-3*INV);AT A1,B1;CHR$ D(A1+1,B1): POKE 23606,0: POKE 23607,60: PRINT FLASH SGN PI;AT A,B;CHR$ D(A+1,B): LET A1=A: LET B1=B
  340 IF INKEY$="Z" OR INKEY$="z" THEN POKE 23606,tog1: POKE 23607,tog2: PRINT AT A,B;CHR$ D(A+1,B): COPY : LPRINT : LPRINT : CLS : GO TO 540
  350 IF |(2,port)=0 THEN GO TO 220
  360 LET TIME=1000: POKE 23606,0: POKE 23607,60: PRINT AT A,B;CHR$ D(A+1,B)
  370 BEEP .2,10+INT (RND*10): PRINT INVERSE SGN PI; INK 6;AT A,B;CHR$ D(A+1,B): LET COUNT=COUNT+1: IF A<>C(COUNT,1) OR B<>C(COUNT,2) THEN POKE 23606,tog1: POKE 23607,tog2: PRINT AT A,B;CHR$ D(A+1,B): GO TO 450
  380 IF (ROT=0 OR ROT=2) AND COUNT<>1 THEN PRINT AT INT ((C(COUNT,1)+C(COUNT-1,1))/2+.5),INT ((C(COUNT,2)+C(COUNT-1,2))/2+.5); INK 6;"::"
  390 IF COUNT<>LEN A$ THEN GO TO 200
  400 REM *** G
  410 PAUSE 30: POKE 23606,0: POKE 23607,60
  420 LET K$=" ": LET K$=K$+W$(WORD): FOR K=SGN PI TO 6: LET K$=K$+K$: NEXT K
  430 CLS : LET ink=INT (RND*5)+1: FOR K=NOT PI TO 4: PRINT INK I(ink+K);AT 0,0;K$: NEXT K: PRINT FLASH SGN PI; INK I(ink+4);AT 9,4;"                        ";AT 10,4;"                        "; OVER 1;AT 10,INT ((32-(LEN A$+14))/2);" ";W$(WORD,1 TO LEN A$);" IS CORRECT! "; OVER 0;AT 11,4;"                        "
  440 FOR K=SGN PI TO INT (RND*6)+6: BEEP .2,INT (RND*25): NEXT K: GO TO 540
  450 REM *** ERROR
  460 POKE 23606,0: POKE 23607,60
  470 IF flag<>1 THEN FOR N=SGN PI TO LEN A$: PRINT INK 5; INVERSE SGN PI;AT 4+(XWORD-1)*3,N-1;W$(W(XWORD),N): NEXT N
  480 IF flag THEN FOR N=SGN PI TO LEN B$: PRINT FLASH SGN PI;AT C(N,1),C(N,2);CHR$ D(C(N,1)+1,C(N,2)): BEEP .01,0: NEXT N
  490 IF flag THEN IF ROT=0 OR ROT=2 THEN FOR N=SGN PI TO LEN A$-1: PRINT AT INT ((C(N,1)+C(N+1,1))/2+.5),INT ((C(N,2)+C(N+1,2))/2+.5); FLASH SGN PI;" ": NEXT N
  500 IF flag THEN RETURN 
  510 PRINT AT A,B;SCREEN$ (A,B): FOR N=SGN PI TO LEN A$: PRINT FLASH SGN PI;AT C(N,1),C(N,2);CHR$ D(C(N,1)+1,C(N,2)): BEEP .01,0: NEXT N: IF ROT=0 OR ROT=2 THEN FOR N=SGN PI TO LEN A$-1: PRINT AT INT ((C(N,1)+C(N+1,1))/2+.5),INT ((C(N,2)+C(N+1,2))/2+.5); FLASH SGN PI;" ": NEXT N
  520 IF flag THEN RETURN 
  530 PAUSE VAL "30": BEEP .5,-10: BEEP 1,-20
  540 REM *** MAIN
  550 POKE 23606,0: POKE 23607,60
  560 IF flag THEN LET REV=0: GO TO 650
  570 LET REV=INT (RND*2): LET A$=""
  580 LET W(1)=INT (RND*WORDS)+1: FOR J=2 TO 5
  590 LET W(J)=INT (RND*WORDS)+1: FOR L=SGN PI TO J-1: IF W(J)=W(L) THEN GO TO 590
  600 NEXT L: NEXT J
  610 LET XWORD=(INT (RND*5)+1): LET WORD=W(XWORD): FOR J=SGN PI TO L(WORD)
  620 LET A$=A$+W$(WORD,J): NEXT J
  630 IF REV=1 THEN LET K$="": FOR J=LEN A$ TO 1 STEP -1: LET K$=K$+A$(J): NEXT J: LET A$=K$
  640 LET D(C(1,1)+1,C(1,2))=INT (RND*26)+65
  650 IF NOT flag2 THEN FOR M=SGN PI TO 11: FOR N=(INT (RND*3)+1) TO 11 STEP INT (RND*3)+1
  660 IF flag2 THEN FOR M=SGN PI TO 11: FOR N=SGN PI TO 11: IF NOT flag THEN LET flag2=flag
  670 LET D((M-1)*2+1,11+(N-1)*2)=INT (RND*26)+65
  680 NEXT N: NEXT M
  690 LET X=INT (RND*(11-LEN A$))+1
  700 LET Y=INT (RND*(11-LEN A$))+1
  710 LET R=INT (RND*4): LET ROT=R
  720 IF NOT R THEN LET Y=INT (RND*11)+1
  730 IF R=2 THEN LET X=INT (RND*11)+1
  740 IF R=1 THEN LET Y=12-Y
  750 GO TO 760+R*20
  760 FOR L=SGN PI TO LEN A$: LET C(L,1)=(X+L-2)*2: LET C(L,2)=11+(Y-1)*2: LET D(C(L,1)+1,C(L,2))=CODE A$(L): NEXT L: GO TO 840
  770 REM 
  780 IF Y-(LEN A$-1)<1 THEN LET Y=LEN A$
  790 FOR L=SGN PI TO LEN A$: LET C(L,1)=(X+L-2)*2: LET C(L,2)=11+(Y-L)*2: LET D(C(L,1)+1,C(L,2))=CODE A$(L): NEXT L: GO TO 840
  800 FOR L=SGN PI TO LEN A$: LET C(L,1)=(X-1)*2: LET C(L,2)=11+(Y+L-2)*2: LET D(C(L,1)+1,C(L,2))=CODE A$(L): NEXT L: GO TO 840
  810 REM 
  820 FOR L=SGN PI TO LEN A$: LET C(L,1)=(X+L-2)*2: LET C(L,2)=11+(Y+L-2)*2: LET D(C(L,1)+1,C(L,2))=CODE A$(L): NEXT L: GO TO 840
  830 REM 
  840 REM *** PRINT 
  850 POKE 23606,tog1: POKE 23607,tog2
  860 IF REV=1 THEN FOR M=SGN PI TO 2: LET K$="": FOR J=LEN A$ TO 1 STEP -1: LET K$=K$+CHR$ (C(J,M)+50): NEXT J: FOR J=SGN PI TO LEN A$: LET C(J,M)=CODE K$(J)-50: NEXT J: NEXT M
  870 CLS : LET COL=11: LET M=0
  880 FOR R=NOT PI TO 20 STEP 2
  890 LET M=M+1
  900 FOR N=SGN PI TO 11
  910 PRINT AT R,COL+(N-1)*2;CHR$ D((M-1)*2+1,11+(N-1)*2)
  920 NEXT N: BEEP .005,20: NEXT R
  930 IF flag THEN RETURN 
  940 POKE 23606,0: POKE 23607,60
  950 LET N=NOT PI
  960 FOR R=4 TO 16 STEP 3
  970 LET N=N+1
  980 PRINT AT R,0;W$(W(N))
  990 BEEP .02,20: NEXT R
 1000 PRINT #1;TAB 8;"Press Z to COPY "
 1010 GO TO 180
 1020 REM *** READ 
 1030 LET C=NOT PI: ON ERR GO TO 1060
 1040 READ A$: IF CODE A$(1)>90 THEN FOR L=SGN PI TO LEN A$: LET A$(L)=CHR$ (CODE A$(L)-32): NEXT L
 1050 LET C=C+1: LET L(C)=LEN A$: LET W$(C)=A$: GO TO 1040
 1060 ON ERR RESET : LET WORDS=C: RETURN 
 1070 REM *** CHARS
 1080 FOR L=SGN PI TO 9: READ I(L): NEXT L
 1090 RESTORE 1170: FOR N=NOT PI TO 7
 1100 READ U: POKE RAMT+N+760,U: NEXT N
 1110 FOR N=NOT PI TO 7
 1120 READ U: POKE RAMT+N+112,U: NEXT N
 1130 FOR N=NOT PI TO 207
 1140 READ U: POKE RAMT+N+264,U
 1150 NEXT N: RETURN 
 1160 DATA 5,3,2,6,4,5,3,2,6
 1170 DATA 60,66,153,161,u,153,66,60
 1180 DATA 0,u,u,u,u,24,u,0
 1190 DATA 60,102,195,u,255,195,u,u
 1200 DATA 254,195,u,254,195,u,u,254
 1210 DATA 60,102,192,u,u,195,102,60,252,198,195,u,u,u,198,252
 1220 DATA 255,192,u,254,192,u,u,255,u,192,u,254,192,u,u,u
 1230 DATA 60,102,192,u,207,195,102,60,195,u,u,255,195,U,u,u
 1240 DATA 255,24,u,u,u,u,u,255,3,u,u,u,u,195,102,60
 1250 DATA 204,216,240,u,216,204,198,195,192,u,u,u,u,u,u,255
 1260 DATA 195,231,u,165,189,153,195,u,u,u,227,211,203,199,195,u
 1270 DATA 60,102,195,u,u,u,102,60,254,195,u,u,254,192,u,u
 1280 DATA 60,102,195,u,203,207,102,61,254,195,u,u,254,204,198,195
 1290 DATA 126,195,192,126,3,u,195,126,255,24,u,u,u,u,u,u
 1300 DATA 195,u,u,u,u,u,102,60,195,u,u,102,u,36,60,24
 1310 DATA 195,u,219,u,u,u,u,102,195,102,60,24,u,60,102,195
 1320 DATA 195,u,102,60,24,u,u,u,127,3,6,12,24,48,96,127
 1330 DATA "CURRENCY","ACIDS","ALKALI","BEVEL","STRATA"
 1340 DATA "MORTGAGE","OBLIQUE","VOLTAGE","MUSEUM","ENVELOPE"
 1350 DATA "ALUMINUM","OLYMPICS","CEREAL","NEBULA","ANTONYMS"
 1360 DATA "AMPERE","SYNONYMS","VEHICLE","ELEMENTS","PALLETS"
 1370 DATA "FUNCTION","PALETTE","MYSTERY","PALATE","ONYX"
 1380 DATA "NUMERIC","YOGURT","BOUNDARY","MEMORY","LIQUID"
 1390 DATA "SCULPTOR","AZTECS","THOUGHT","INCA","CERAMIC","MAYA"
 1400 DATA "MODEM","LIBRARY","STOMACH","OPERANDS","MIRAGE"
 1410 DATA "ARRAY","INTAGLIO","ARGUMENT","RELIEF","SILICON"
 1420 DATA "GAZEBO","EIGHT","COLUMNS","JUVENILE","THEATER"
 1430 DATA "EXTINCT","QUOTIENT","MALADY","ANSWER","MELODY"
 1440 DATA "ANTIQUE","TURBINE","HEIRLOOM","AUGER","PROPHECY"
 1450 DATA "SYMBOL","PROPHESY","ISLAND","ASTERISK","SEPARATE"
 1460 DATA "TRUNCATE","MACABRE","CELSIUS","CALENDAR","KELVIN"
 1470 DATA "MACHINE","EXHAUST","ACCESS","KIOSK","GRAPHICS"
 1480 DATA "ICICLE","COMPILER","STELLAR","SERIAL","HOMONYMS"
 1490 DATA "FOREIGN","NUCLEAR","IMAGINE","MERGE","LANGUAGE"
 1500 DATA "HEXAGON","BYTES","VESSEL","ECSTASY","FEBRUARY"
 1510 DATA "SCIMITAR","SCIENCES","SWAHILI","VERTIGO","HINDU"
 1520 DATA "VARIABLE","DECADE","OBELISK","BATON","BINARY"
 1530 DATA "ABALONE","DECIMAL","SANDWICH","RANDOM","VALID","VOID"
 1540 DATA "SYSTEM","AMATEUR","DELETE","SYNTAX","DIGITIZE"
 1550 DATA "MATRIX","PARALLEL","CIRCUITS","RECEIVE","ZENITH"
 1560 DATA "PRISM","BICYCLE","SPECTRUM","ELECTRIC","INDEX"
 1570 DATA "CURSOR","AERIAL","MAGNETIC","VERIFY","NUTRIENT"
 1580 DATA "PIXEL","OXYGEN","ERSATZ","ALPHABET","QUICHE","QUEUE"
 1590 DATA "UNIVERSE","SYRINGE","GALAXY","INVERSE","OBVERSE"
 1600 DATA "REVERSE","CATEGORY","ELIGIBLE","KITCHEN","AXIOM"
 1610 DATA "PRIMARY","HOURS","CEILING","SPECIFIC","ENERGY"
 1620 DATA "ADROIT","MEDIA","OASIS","TRIVET","TRIPOD","TRIVIA"
 1630 DATA "CARAFE","MYTHS","DESERTS","DESSERT","DUNES","CAMEO"
 1640 DATA "AFGHAN","VERTEBRA","VIDEO","FUSION","FISSION"
 1650 DATA "GRAFFITI","ARTERY","THERAPY","OBSERVE","ACRYLIC"
 1660 DATA "ACQUIT","ANNEAL","ACRONYM","CHARISMA","OPTICS"
 1670 DATA "GYRATE","GUSSET","INTERIM","MATTE","MEDIAN","PLASMA"
 1680 DATA "POISE","PRECEDE","PROCEED","SUCCOMB","FLOTSAM"
 1690 DATA "LIAISON","CABOCHON","FILIGREE","BIZARRE","BAZAAR"
 1700 DATA "OPAQUE","SOLSTICE","EQUINOX","AZIMUTH","NADIR"
 1710 DATA "HYPNOSIS","INDELIBLE","INEDIBLE","PSYCHE","CODEX"
 1720 DATA "GRANITE","TEXTURE","GOUACHE","ULTIMATE","EXONERATE"
 1730 DATA "ARTHROPOD","SYNERGY","QUARTZ","DRAIN","SPIRIT"
 1740 DATA "LIBEL","LIABLE","CARNIVORE","HERBIVORE","OMNISCIENT"
 1750 DATA "OBTUSE","ABSTRUSE","AUGMENT","RENEGE","VIGILANTE"
 1760 DATA "ABSTRACT","SQUELCH","INDEMNIFY","AMPLIFY","LEAGUE"
 1770 DATA "ANTENNAE","ECLAIR","TOURNAMENT","DICTIONARY","EXCISE"
 1780 DATA "THESAURUS","EMBRYO","FANTASY","DEFICIT","PROVISO"
 1790 DATA "ISOSCELES","PALINDROME","METAPHOR","SIMILE","IDIOM"
 1800 DATA "MOLECULE","SOLILOQUY","INTREPID","ISOTOPE","PACIFY"
 1810 DATA "LUCID","DEBUTANTE","MILITIA","HYPOCRISY","METABOLISM"
 1820 DATA "LABYRINTH","SLURRY","CALAMITY","ALGEBRA","LATTICE"
 1830 DATA "BAZOOKA","GAUCHE","DEFUSE","DIFFUSE","STRIATION"
 1840 DATA "atrium","synapse","apogee","perigee","parity"
 1850 DATA "spoof","spoonerism","sleuth","cadaver","carrion"
 1860 DATA "pedigree","sobriety","flagrant","fragile","synopsis"
 1870 DATA "scion","facile","docile","domicile","eulogy"
 1880 DATA "APOCRYPHAL","ECLECTIC","ATHEIST","ALTRUISM","DIODE"
 1890 DATA "SYMMETRY","SIMIAN","INUNDATE","DECIPHER","MACADAM"
 1900 DATA "SLUICE","RECLUSE","INDUCE","IMPEL","COMPEL","SATYR"
 1910 DATA "SATIRE","SAPPHIRE","STAMINA","CALCIFY","ATROPHY"
 1920 DATA "DENSITY","FLUX","FLOC","ABSCISSA","ORDINATE"
 1930 DATA "ABDICATE","ABSCESS","LACQUER","CALCULUS","INTEGER"
 1940 DATA "ANALYSIS","DYNAMIC","STATIC","KINETIC","NEUROTIC"
 1950 DATA "PSYCHOTIC","GOURMET","STALAGMITE","STALACTITE"
 1960 DATA "COERCE","VIRTUOSITY","PIRACY","ENIGMA","DILEMMA"
 1970 DATA "RHETORIC","COGNITIVE","TRAUMA","TROUBADOR","CHASM"
 1980 DATA "DICHOTOMY","MARVEL","MARAUDER","TRANSIENT","SECEDE"
 1990 DATA "PERPLEXED","VEXATION","SUCCEED","EXCEED","ACCEDE"
 2000 DATA "REVEAL","PANORAMA","REVILE","ABSORB","ADSORB"
 2010 DATA "HYBRID","ORGANISM","ALLOY","THESPIAN","DEBONAIR"
 2020 DATA "ORATORY","DEBUT","PANTOGRAPH","ENZYME","PANTOMIME"
 2030 DATA "ABORIGINE","PYGMY","QUANTIFY","REFLEX","QUANTUM"
 2040 DATA "TORQUE","RAKU","EQUESTRIAN","SHELLAC","PEDESTRIAN"
 2050 DATA "MONOPOLY","CANNIBAL","MONOCHROME","CAROUSEL","JETSAM"
 2060 DATA "VULNERABLE","STOIC","DECIMATE","BOURSE","ANNIHILATE"
 2070 DATA "CHAMOIS","REVERIE","VICUNA","IGUANA"
 2080 DATA "SAUNA","TRUANT","VAULT","MORGUE","BAROQUE","ERUDITE"
 2090 DATA "BOVINE","MAORI","ZIGGURAT","EMULSIFY","HARLEQUIN"
 2100 DATA "CHASTE","CASTE","CALIPER","CREMATE","VOLATILE"
 2110 DATA "CHASTISE","MARSUPIAL","FRENETIC","SYRUP"
 2120 CLEAR : SAVE "WORDFIND" LINE 1

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