This program implements the Vigenère cipher, a classical polyalphabetic substitution cipher, offering both encoding and decoding functions. The keyword is repeated (by string concatenation in a loop at lines 150–155 and 350–355) until it matches or exceeds the length of the plaintext message, forming a running key. Encoding adds the ASCII codes of the message and key characters together, then subtracts 65 or 91 to wrap back into a printable range depending on whether the sum exceeds 155. Decoding reverses the process by subtracting key character codes and adding 65 or 91 accordingly. The program uses POKE 23658,8 to enable CAPS LOCK and POKE 23609,100 to set the keyboard repeat delay, and restricts messages to 32 characters to fit within the display column range used for output.
Program Structure
The program is divided into three functional blocks, clearly delineated by REM banners:
- Main menu (lines 10–60): displays a title and polls
INKEY$in a tight loop, branching to the encoder, decoder, or STOP. - Encoder (lines 100–245): accepts a keyword and plaintext, builds a running key, computes ciphertext, and displays it.
- Decoder (lines 300–445): mirrors the encoder but subtracts key values to recover plaintext.
Cipher Algorithm
The Vigenère cipher is implemented by treating each character as its ASCII code. The running key is built by repeatedly concatenating k$ to h$ until LEN h$ >= s (lines 150–155 / 350–355). For encoding, line 190 computes c(n) = a(n) + b(n); for decoding, line 390 computes c(n) = a(n) - b(n).
The output mapping uses two thresholds to keep results in a printable letter range:
| Condition | Encoder output | Decoder output |
|---|---|---|
c(n) <= 155 / c(n) >= 0 | CHR$ (c(n)-65) | CHR$ (c(n)+65) |
c(n) > 155 / c(n) < 0 | CHR$ (c(n)-91) | CHR$ (c(n)+91) |
The magic constant 155 is 2 × 65 + 25 (i.e., ‘A’+’Z’), and 91 = 65 + 26, providing a one-alphabet wrap. The arithmetic assumes both message and keyword consist of uppercase ASCII letters (codes 65–90); non-uppercase input will produce unpredictable results.
Key BASIC Idioms
- Running-key construction: the string loop
LET h$=h$+k$followed byIF LEN h$<s THEN GO TO 150is a compact way to tile the keyword to the required length without aFORloop. - Parallel numeric arrays:
DIM a(s),DIM b(s), andDIM c(s)store message codes, key codes, and combined values separately, keeping the arithmetic loop (lines 170–200 / 370–400) simple and the display loop (lines 210–240 / 410–440) separate. - PAUSE 0 at lines 244 and 444 halts execution until any key is pressed before returning to the main menu.
- System POKEs: line 25 uses
POKE 23658,8to force CAPS LOCK on (so uppercase entry is easier) andPOKE 23609,100to set the keyboard click/repeat parameter.
Notable Techniques and Anomalies
- Column-per-character display: ciphertext and deciphered text are printed one character at a time with
PRINT AT 14,n;, sondirectly maps to the screen column. This elegantly avoids string concatenation for the output but limits messages to 32 characters (columns 1–32 of a 32-column display). - Menu polling bug: lines 40–60 sample
INKEY$three separate times in sequence rather than capturing it once to a variable. If a key is pressed between checks, it may be missed, and the program falls through to redraw the menu at line 60 causing a flicker loop. SavingINKEY$to a variable at the top of the loop would be more reliable. - No input validation: the program does not check that the message is 32 characters or fewer, nor that all characters are uppercase letters. Lowercase or punctuation in the message or keyword will produce incorrect output or out-of-range
CHR$arguments. - Decoder symmetry flaw: the encoder subtracts 65 when
c(n) <= 155and 91 whenc(n) > 155. The decoder mirrors this with +65 whenc(n) >= 0and +91 whenc(n) < 0. This is internally consistent for the two-branch wrap, but it is not a standard modular arithmetic Vigenère and will only correctly round-trip text encoded by this same program. - Array re-dimensioning:
DIM a(s),DIM b(s),DIM c(s)are declared fresh each time the encoder or decoder is entered (sincesmay differ between runs), which correctly resets them.
Source Code
5 REM Vignere Cipher by T.S.Thomas
10 REM *******************
11 REM ** MAIN PROG **
12 REM *******************
20 BORDER 0:INK 7:PAPER 0:CLS
25 POKE 23658,8:POKE 23609,100
27 PRINT AT 2,9;"VIGNERE CIPHER"
30 PRINT AT 5,0;"PLEASE SELECT A FUNCTION:"; TAB 1;" "; TAB 1;"E - Encode"; TAB 1;"D - Decode"; TAB 1;"S - Stop"
40 IF INKEY$="E" OR INKEY$="e" THEN GO TO 100
50 IF INKEY$="D" OR INKEY$="d" THEN GO TO 300
55 IF INKEY$="S" OR INKEY$="s" THEN GO TO 1000
60 GO TO 30
99 REM
100 REM *******************
101 REM ** ENCODER **
102 REM *******************
103 REM
104 CLS
105 PRINT AT 2,9;"VIGNERE CIPHER"
106 PRINT AT 3,13;"ENCODER"
107 PRINT AT 5,0;"ENTER A 32 CHARACTER OR LESS "; TAB 0;"MESSAGE IN CAPITAL LETTERS"
110 INPUT "ENTER KEYWORD: "; LINE k$
115 PRINT AT 8,1;"KEYWORD = ";k$
120 INPUT "ENTER MESSAGE: "; LINE m$
125 PRINT AT 10,1;"MESSAGE = ";m$
130 LET s= LEN m$
140 LET h$=k$
150 LET h$=h$+k$
155 IF LEN h$<s THEN GO TO 150
160 DIM a(s):DIM b(s)
165 DIM c(s)
170 FOR n=1 TO s
175 LET a(n)= CODE m$(n)
180 LET b(n)= CODE h$(n)
190 LET c(n)=a(n)+b(n)
200 NEXT n
210 FOR n=1 TO s
215 PRINT AT 13,0;"CIPHERED MESSAGE BELOW:"
220 IF c(n) <=155 THEN PRINT AT 14,n; CHR$ (c(n)-65)
230 IF c(n)>155 THEN PRINT AT 14,n; CHR$ (c(n)-91)
240 NEXT n
241 PRINT AT 16,0;"PRESS ANY KEY TO CONTINUE "; TAB 0;" "
244 PAUSE 0
245 GO TO 10
299 REM
300 REM *******************
301 REM ** DECODER **
302 REM *******************
303 REM
304 CLS
305 PRINT AT 2,9;"VIGNERE CIPHER"
306 PRINT AT 3,13;"DECODER"
307 PRINT AT 5,0;"ENTER A 32 CHARACTER OR LESS "; TAB 0;"MESSAGE IN CAPITAL LETTERS"
310 INPUT "ENTER KEYWORD: "; LINE k$
315 PRINT AT 8,1;"KEYWORD = ";k$
320 INPUT "ENTER MESSAGE: "; LINE m$
325 PRINT AT 10,1;"MESSAGE = ";m$
330 LET s= LEN m$
340 LET h$=k$
350 LET h$=h$+k$
355 IF LEN h$<s THEN GO TO 350
360 DIM a(s):DIM b(s)
365 DIM c(s)
370 FOR n=1 TO s
375 LET a(n)= CODE m$(n)
380 LET b(n)= CODE h$(n)
390 LET c(n)=a(n)-b(n)
400 NEXT n
410 FOR n=1 TO s
415 PRINT AT 13,0;"DECIPHERED MESSAGE BELOW:"
420 IF c(n)<0 THEN PRINT AT 14,n; CHR$ (c(n)+91)
430 IF c(n) >=0 THEN PRINT AT 14,n; CHR$ (c(n)+65)
440 NEXT n
441 PRINT AT 16,0;"PRESS ANY KEY TO CONTINUE "; TAB 0;" "
444 PAUSE 0
445 GO TO 10
1000 STOP Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

