Conversational German is an interactive language-learning program that teaches vocabulary and phrases through a quiz-and-review system. It stores vocabulary in string arrays G$, E$, R$, and T$ (German words, English words, German phrases, and English phrases respectively), populated via a GOSUB to line 9000. The program offers six modes: reviewing words or phrases in paginated lists, and four quiz modes testing German-to-English and English-to-German translation in both directions for both individual words and complete phrases. A machine code routine embedded in the REM statement at line 1 is invoked via USR 16514 to perform a screen-clear operation efficiently. Random question selection (lines 5200 and 5400) uses an array to track previously asked questions, preventing repeats within a ten-question round, and a running score S is maintained and displayed at the end of each round.
Program Analysis
Program Structure
The program is organized into several functional blocks:
- Lines 1–60: Machine code REM stub and initialization; entry point routes to the title/menu via
GOSUB 9000. - Lines 100–210: Word review mode — paginated display of German/English word pairs from
G$andE$, nine at a time. - Lines 700–890: Quiz modes — German-to-English (700) and English-to-German (800), each running 10 random questions.
- Lines 900–1090: Phrase quiz modes — English-to-German (900) and German-to-English (1000) using
R$andT$. - Lines 1100–1120: Input display subroutine — prints the user’s answer
P$neatly at a fixed screen position. - Lines 2000–3070: Title screen display and main menu with six numbered choices.
- Lines 4000–5100: Score display, wrong-answer feedback, correct-answer celebration, and end-of-round handler.
- Lines 5200–5550: Random question selection subroutines for phrase (
5200) and word (5400) questions, with duplicate prevention. - Lines 6000–6100: “Press any key to continue” pause subroutine with a graphical border.
- Lines 7990–8050: Phrase review mode — paginated display of phrase pairs, six at a time.
- Line 9000–9020: Screen-clear subroutine using the machine code routine and
PRINT AT 0,0;.
Machine Code Routine
Line 1 contains a REM statement whose body is a machine code routine loaded at address 16514 (the byte immediately following the REM token in memory). The hex bytes encode a Z80 routine:
| Hex | Mnemonic | Purpose |
|---|---|---|
16 17 | LD D,17h | Load D with 23 (number of rows) |
2A 0C 40 | LD HL,(400Ch) | Load HL with display file address |
3E 21 | LD A,21h | Load A with 33 (number of columns) |
23 | INC HL | Advance pointer |
36 00 | LD (HL),00 | Write space to screen |
3D | DEC A | Decrement column counter |
FE 01 | CP 01h | Compare with 1 |
20 F8 | JR NZ,-8 | Loop over columns |
23 | INC HL | Skip to next row |
15 | DEC D | Decrement row counter |
5F | LD E,A | Save A into E |
7A | LD A,D | Move row count to A |
FE 01 | CP 01h | Compare with 1 |
7B | LD A,E | Restore A |
20 ED | JR NZ,-19 | Loop over rows |
C9 | RET | Return to BASIC |
This routine rapidly clears the display by writing zeros to the display file directly, bypassing the BASIC CLS command. It is called via LET Z=USR 16514 at line 9000 each time a screen clear is needed.
Random Question Selection and Duplicate Prevention
Two subroutines handle random selection without repeats. The word quiz subroutine at line 5400 picks a random index R in the range 1–220 (implying the vocabulary array holds up to 220 entries), stores it in U(L), then iterates through all previously used values in U to check for a collision, restarting if a duplicate is found. Similarly, the phrase subroutine at line 5200 selects from 1–50 using array V. This is a standard rejection-sampling deduplication approach in BASIC.
Answer Matching with Trailing-Space Trimming
Because the string arrays G$, E$, R$, and T$ are fixed-width (padded with spaces), a substring comparison loop is used to find the effective length of each answer before comparing. For example, lines 735–750 scan E$(R) two characters at a time for a double space, then set A to the last non-space position. The comparison at line 760 is then P$=E$(R,1 TO A), avoiding spurious mismatches due to trailing padding.
Two-Attempt Quiz Logic
Each question allows two attempts via an inner FOR Q=1 TO 2 loop (e.g., lines 715–767). On the first wrong answer, the message “WRONG—TRY AGAIN” is printed; on the second failure (IF Q>1), the correct answer is revealed and the program moves on without awarding a point. This pattern is consistently applied across all four quiz modes.
Score Tracking
The variable S is initialized to 0 at line 2060 and incremented at line 5085 for each correct answer. At the end of a 10-question round (detected at line 5087 when L=10), the program jumps to line 4000, which displays the score in inverse video and returns to the menu. Score is not reset between rounds unless the user navigates back through the menu to line 2060.
Display and Graphics Techniques
The program makes extensive use of block graphics characters to draw decorative borders and dividers. The wrong-answer display at line 4500 uses ▄ characters for a top border and ▀ characters for a bottom border. The “press any key” pause subroutine at line 6000 constructs a three-line bordered box using ▌ and ▐ side characters. Menu separators use checkerboard-pattern graphics for visual flair. All PRINT AT statements are used carefully to write to specific screen coordinates without full redraws.
Subroutine at Line 5000 (Missing)
The correct-answer handler calls GOSUB 5000 (lines 780, 880, 980, 1080), but the listing jumps from line 4500 directly to line 5010. Line 5000 is absent; BASIC will execute from line 5010 as the nearest following line, which is standard behavior — a GOSUB to a non-existent line number executes from the next line present. This is an intentional memory optimization, not an error.
Vocabulary Data
The program does not contain its vocabulary inline; the arrays G$, E$, R$, and T$ are presumably populated by a GOSUB 9000 call or loaded from the tape alongside this program. The absence of DIM or DATA/READ statements in the listing confirms the data is expected to reside elsewhere (likely a second program block or a separate loader). Line 1200 contains a SAVE "GERMA%N" command (the %N being an inverse N) used to save the program.
Content
Image Gallery
Source Code
1 REM 16172A C403E212336 03DFE 120F823155F7AFE 17B20EDC9
50 GOSUB 9000
60 LET X=1
100 PRINT "GERMAN ENGLISH "
110 PRINT "====== ======= "
170 FOR X=X TO X+8
182 PRINT G$(X);TAB 15;E$(X)
183 PRINT
184 IF X=240 THEN GOTO 2056
185 NEXT X
189 PRINT "'''''''''''''''''''''''''''''''''''''''''''''''''''' PRESS C TO CONTINUE, S TO STOP."
192 IF INKEY$="S" THEN GOTO 2049
194 IF INKEY$="C" THEN GOTO 200
195 GOTO 192
200 GOSUB 9000
210 GOTO 170
700 FOR L=1 TO 10
710 GOSUB 5400
715 FOR Q=1 TO 2
718 PRINT AT 9,0;G$(R)
720 PRINT AT 10,0;"IS GERMAN FOR WHAT WORD?"
731 INPUT P$
732 GOSUB 1100
735 FOR A=1 TO 16
737 IF E$(R,A TO A+1)=" " THEN GOTO 750
740 NEXT A
750 LET A=A-1
760 IF P$=E$(R,1 TO A) THEN GOTO 780
765 IF Q>1 THEN GOTO 768
766 PRINT AT 12,0;"WRONG---TRY AGAIN"
767 NEXT Q
768 GOSUB 4500
770 PRINT "THE WORD WAS : ";E$(R)
772 GOSUB 6000
773 GOSUB 5087
775 NEXT L
780 GOSUB 5000
790 NEXT L
800 FOR L=1 TO 10
810 GOSUB 5400
815 FOR Q=1 TO 2
820 PRINT AT 9,0;"WHAT IS THE GERMAN WORD FOR:"
825 PRINT AT 10,0;E$(R)
826 INPUT P$
827 GOSUB 1100
828 FOR A=1 TO 16
829 IF G$(R,A TO A+1)=" " THEN GOTO 831
830 NEXT A
831 LET A=A-1
840 IF P$=G$(R,1 TO A) THEN GOTO 880
845 IF Q>1 THEN GOTO 860
850 PRINT AT 12,0;"WRONG---TRY AGAIN"
855 NEXT Q
860 GOSUB 4500
870 PRINT "THE WORD WAS : ";G$(R)
872 GOSUB 6000
873 GOSUB 5087
875 NEXT L
880 GOSUB 5000
890 NEXT L
900 FOR L=1 TO 10
910 GOSUB 5200
915 FOR Q=1 TO 2
920 PRINT AT 9,0;"WHAT IS THE GERMAN PHRASE FOR:"
925 PRINT AT 10,0;T$(R)
926 INPUT P$
927 GOSUB 1100
928 FOR A=1 TO 32
929 IF R$(R,A TO A+1)=" " THEN GOTO 931
930 NEXT A
931 LET A=A-1
940 IF P$=R$(R,1 TO A) THEN GOTO 980
945 IF Q>1 THEN GOTO 960
950 PRINT AT 12,0;"WRONG---TRY AGAIN"
955 NEXT Q
960 GOSUB 4500
970 PRINT "THE PHRASE WAS : "
971 PRINT R$(R)
972 GOSUB 6000
973 GOSUB 5087
975 NEXT L
980 GOSUB 5000
990 NEXT L
1000 FOR L=1 TO 10
1010 GOSUB 5200
1015 FOR Q=1 TO 2
1020 PRINT AT 9,0;"WHAT IS THE ENGLISH PHRASE FOR:"
1025 PRINT AT 10,0;R$(R)
1026 INPUT P$
1027 GOSUB 1100
1028 FOR A=1 TO 32
1029 IF T$(R,A TO A+1)=" " THEN GOTO 1031
1030 NEXT A
1031 LET A=A-1
1040 IF P$=T$(R,1 TO A) THEN GOTO 1080
1045 IF Q>1 THEN GOTO 1060
1050 PRINT AT 12,0;"WRONG---TRY AGAIN"
1055 NEXT Q
1060 GOSUB 4500
1070 PRINT "THE PHRASE WAS : "
1071 PRINT T$(R)
1072 GOSUB 6000
1073 GOSUB 5087
1075 NEXT L
1080 GOSUB 5000
1090 NEXT L
1100 PRINT AT 11,0;" ";AT 11,0;P$
1110 PRINT AT 12,0;" "
1120 RETURN
1200 SAVE "GERMA%N"
2000 PRINT AT 8,0;A$
2002 PRINT AT 2,0;I$;AT 18,0;I$
2010 PRINT AT 16,4;"PRESS ANY KEY TO BEGIN"
2020 IF INKEY$="" THEN GOTO 2020
2049 GOSUB 9000
2050 PRINT
2055 PRINT
2056 PRINT "% ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;% "
2060 LET S=0
3000 PRINT "CHOOSE MODE:"
3010 PRINT " (1)ENGLISH TO GERMAN"
3020 PRINT " (2)GERMAN TO ENGLISH"
3040 PRINT " (3)ENGLISH TO GERMAN PHRASES"
3041 PRINT " (4)GERMAN TO ENGLISH PHRASES"
3042 PRINT " (5)REVIEW WORDS"
3043 PRINT " (6)REVIEW PHRASES"
3046 PRINT "% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!% "
3050 LET M$=INKEY$
3055 IF M$="1" THEN GOTO 800
3060 IF M$="2" THEN GOTO 700
3065 IF M$="5" THEN GOTO 50
3067 IF M$="3" THEN GOTO 900
3068 IF M$="4" THEN GOTO 1000
3069 IF M$="6" THEN GOTO 7990
3070 GOTO 3050
4000 GOSUB 9000
4001 PRINT " % %Y%O%U%R% %S%C%O%R%E% %I%S%:% ";S
4010 GOTO 2050
4500 PRINT ".................................................... ---WRONG--- '''''''''''''''''''''''''''''''''''''''''''''''''''' "
4510 RETURN
5010 PRINT AT 14,0;" % ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;% % % % % CORRECT % % % % % !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!% "
5080 FOR P=1 TO 15
5081 NEXT P
5085 LET S=S+1
5087 IF L=10 THEN GOTO 4000
5100 RETURN
5200 GOSUB 9000
5210 LET R=INT (50*RND)+1
5220 LET V(L)=R
5230 FOR P=1 TO L-1
5240 IF V(L)=V(P) THEN GOTO 5210
5245 NEXT P
5248 PRINT AT 4,6;"QUESTION NO. ";L
5250 RETURN
5400 GOSUB 9000
5405 LET R=INT (220*RND)+1
5500 LET U(L)=R
5510 FOR P=1 TO L-1
5520 IF U(L)=U(P) THEN GOTO 5405
5540 NEXT P
5545 PRINT AT 4,6;"QUESTION NO. ";L
5550 RETURN
6000 PRINT AT 19,0;"..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..";AT 21,0;"''~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~''";AT 20,0;": PRESS ANY KEY TO CONTINUE :"
6005 IF INKEY$="" THEN GOTO 6005
6100 RETURN
7990 GOSUB 9000
7995 PRINT " PHRASES ============="
8000 LET X=1
8001 FOR X=X TO X+5
8003 PRINT R$(X)
8004 PRINT T$(X)
8005 PRINT
8008 IF X=50 THEN GOTO 2050
8010 NEXT X
8015 PRINT "'''''''''''''''''''''''''''''''''''''''' PRESS C TO CONTINUE, S TO STOP."
8020 IF INKEY$="S" THEN GOTO 2049
8021 IF INKEY$="C" THEN GOTO 8040
8025 GOTO 8020
8040 GOSUB 9000
8050 GOTO 8001
9000 LET Z=USR 16514
9010 PRINT AT 0,0;
9020 RETURN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.