Quiz Maker

Developer(s): Dale F Lipinski
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Education

This is a quiz-authoring and quiz-taking program published in Syntax Quarterly (Spring 1983), written by Dale F. Lipinski. It allows the user to build a quiz with up to three formats — multiple choice (up to 9 options), true/false, or direct answer — storing all text in a single packed string array A$ with offset pointers held in a 2D numeric array A(). Memory is carefully budgeted before entry begins: line 230 uses PEEK on system variables 16386/16387 (RAMTOP) and 16412/16413 (E_LINE) to calculate available character storage E, which is then reported as total and per-question averages. The program also supports optional wrong-answer explanations, records a running score, and offers to SAVE the completed quiz back to tape at the end.


Program Analysis

Program Structure

The program divides into three broad phases: configuration (lines 10–280), quiz entry (lines 290–760), and quiz delivery (lines 770–1240). A final block at lines 1250–1270 handles the auto-run SAVE of the shell program.

  1. Configuration (10–280): Collects quiz type (C$), number of questions (A), explanation flag (D$), and number of choices (B for multiple choice). Computes available string space E via PEEK, then dimensions both arrays.
  2. Quiz Entry (290–760): For each question, stores question text, answer, optional explanation, and (for multiple choice) each lettered choice into the packed string A$, recording segment offsets in the numeric array A().
  3. Quiz Delivery (770–1240): Prompts for title and player name, then loops through all questions, checks answers, updates score S, and optionally displays explanations for wrong answers.

Memory Management via PEEK

Line 230 is the most technically notable line in the program:

LET E=(PEEK 16386-PEEK 16412+256*(PEEK 16387-PEEK 16413)-50)-1300-(D*(A+1)*5)

This calculates free RAM by subtracting the E_LINE pointer (16412/16413, the current end of BASIC workspace) from RAMTOP (16386/16387), then subtracts an overhead estimate of 1300 bytes plus the space the two arrays will themselves occupy (D*(A+1)*5 bytes, since each numeric array element takes 5 bytes). The result E is used to dimension A$ at line 299, ensuring the string buffer fits in available memory. This is a practical, if fragile, approach — the constants 50 and 1300 are empirical guesses at interpreter overhead.

Packed String / Pointer Array Idiom

All text (questions, answers, explanations, choices) is stored in a single string A$ dimensioned to E characters. Segment boundaries are tracked in a 2D numeric array A(A+1, D) where each row corresponds to one question and each column holds a character offset:

ColumnMeaning
A(F,1)Start of question text
A(F,2)Start of answer
A(F,3)Start of explanation
A(F,4)A(F,D)Start of each multiple-choice option
A(F+1,1)End marker (= A(F,D))

Retrieval during the quiz phase slices A$ with expressions like A$(A(C,1) TO A(C,2)-1). This is an efficient, if error-prone, manual memory management technique for a BASIC environment lacking dynamic data structures.

Answer Encoding for Multiple Choice

Line 705 prepends each choice with CHR$ (C+28), mapping choice numbers 1–9 to ZX81 character codes 29–37 (the inverse-video digits 1–9). Line 735 then checks whether the stored answer text matches the current choice text; if so, it overwrites the first byte of the answer field with that same encoded character. At quiz time (line 955), for multiple-choice mode, K$ is set to just this single encoded byte, so comparison at line 1020 (K$=F$) works correctly without the user knowing about the encoding.

Input Validation Pattern

Throughout the program, single-character inputs are validated by testing CODE against known ZX81 character codes. For example:

  • Line 70: IF CODE C$<=28 OR CODE C$>=32 THEN GOTO 40 — accepts only codes 29, 30, 31 (inverse “1”, “2”, “3”).
  • Line 140: IF CODE D$<=27 OR CODE D$>=30 — accepts codes 28 or 29 (inverse “0” or “1”).
  • Line 270: IF CODE E$<=27 OR CODE E$>=29 — accepts only code 28 (inverse “0”).

This relies on ZX81’s keyboard INPUT returning inverse-video digit characters rather than plain ASCII, a platform-specific behavior hobbyists exploited for simple menu selection.

Notable Idiom: B$ as a Reusable Prompt Banner

Line 30 defines B$ as a long string of block-graphic characters (▀ tiles) followed by the inverse-video text “ENTER ANSWER”. This is PRINTed at the bottom of most input screens as a visual prompt bar. Slicing B$( TO 32) at line 950 prints only the graphic portion, omitting the text label where it would be inappropriate.

Bugs and Anomalies

  • Line 530 condition is always false: IF CODE D$<=28 OR CODE D$>=3 — since CODE D$ is always ≥ 3 for any non-empty string, this condition is always true and execution never falls through to line 540 (the explanation-entry block). The explanation feature is therefore broken; H$ retains whatever value was set at line 160 (a single space). The correct test was probably >=30 (matching the validation at line 140).
  • Line 410/420/520/620/730 off-by-one: Segments are stored as A$(A(F,1) TO A(F,1)+H) where H=LEN E$, which copies H+1 characters (an extra trailing character bleeds into the next segment). This is compensated for at retrieval time by the -1 in slice end indices, but it wastes one byte per segment.
  • Line 1170 comma after TAB 0: PRINT "QUIZ IS COMPLETE. THANK YOU",J$;TAB 0,,... — the comma after TAB 0 produces an extra blank line, which is cosmetic rather than functional.
  • Line 1220 loops to 830 instead of 40: After a wrong answer at the save prompt, execution returns to line 830 (ask for player name) rather than restarting the whole quiz setup, meaning a second run reuses the existing A() and A$() data correctly but skips re-dimensioning.

FAST Mode

Line 20 invokes FAST mode for the entire program, suppressing the display refresh and significantly speeding up string operations during quiz entry. This is appropriate given the volume of string slicing and array writes performed during the authoring phase.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10001 – 10050.

Related Products

Related Content

Image Gallery

Quiz Maker

Source Code

   1 REM %Q%U%I%Z% % % % % % % % % % % % % % % % % % % 
   2 REM %D%A%L%E% %F%.% %L%I%P%I%N%S%K%I% % % % % % % 
   3 REM %S%Y%N%T%A%X% %Q%U%A%R%T%E%R%L%Y% % % % % % % 
   4 REM %S%P%R%I%N%G% %1%9%8%3% % % % % % % % % % % % 
  10 LET S=0
  20 FAST 
  30 LET B$="\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''% %E%N%T%E%R% %A%N%S%W%E%R% "
  40 CLS 
  50 PRINT "WHAT TYPE OF QUIZ DO YOU WISH TOHAVE?",,"1 = MULTIPLE CHOICE","2 = TRUE OR FALSE","3 = DIRECT ANSWER",B$
  60 INPUT C$
  70 IF CODE C$<=28 OR CODE C$>=32 THEN GOTO 40
  80 CLS 
  90 PRINT "HOW MANY QUESTIONS DO YOU WISH  TO ASK?",,B$
 100 INPUT A
 110 CLS 
 120 PRINT "DO YOU WISH TO EXPLAIN THE","ANSWER IF IT IS WRONG?","1 = YES",,"0 = NO",,B$
 130 INPUT D$
 140 IF CODE D$<=27 OR CODE D$>=30 THEN GOTO 110
 160 IF D$="0" THEN LET H$=" "
 170 CLS 
 180 LET D=4
 190 IF C$="2" OR C$="3" THEN GOTO 230
 200 PRINT "WHAT IS THE MAXIMUM NUMBER OF","CHOICES PER QUESTION?","LIMIT OF 9",,B$
 210 INPUT B
 215 IF B>=10 THEN GOTO 170
 220 LET D=B+4
 230 LET E=(PEEK 16386-PEEK 16412+256*(PEEK 16387-PEEK 16413)-50)-1300-(D*(A+1)*5)
 240 CLS 
 250 PRINT "YOU WILL HAVE ";A;" QUESTIONS","WITH A TOTAL CHARACTER INPUT OF",E;TAB 0;"AN AVERAGE OF ";E/A,"CHARACTERS PER QUESTION";TAB 0;"IF THIS IS OKAY ENTER 0","IF NOT ENTER 1",,B$
 260 INPUT E$
 270 IF CODE E$<=27 OR CODE E$>=29 THEN GOTO 40
 280 DIM A(A+1,D)
 290 DIM A$(E)
 300 LET A(1,1)=1
 320 FOR F=1 TO A
 330 CLS 
 340 PRINT "WHAT IS QUESTION NUMBER ";F;"?",B$
 350 INPUT E$
 360 PRINT E$;TAB 0;"INPUT 0 IF THIS IS CORRECT","INPUT 1 IF NOT CORRECT",B$
 370 INPUT F$
 380 IF CODE F$<=27 OR CODE F$>=29 THEN GOTO 330
 390 LET H=LEN E$
 400 LET A(F,2)=A(F,1)+H
 410 LET A$(A(F,1) TO A(F,1)+H)=E$
 420 CLS 
 430 PRINT "WHAT IS THE ANSWER?"
 440 IF C$="2" THEN PRINT "1 = TRUE",,"0 = FALSE"
 450 PRINT B$
 460 INPUT E$
 465 CLS 
 470 PRINT E$;TAB 0;"INPUT 0 IF THIS IS CORRECT","INPUT 1 IF NOT CORRECT",B$
 475 IF C$="2" AND E$="1" THEN PRINT AT 0,0;"1 = TRUE"
 477 IF C$="2" AND E$="0" THEN PRINT AT 0,0;"0 = FALSE"
 480 INPUT F$
 490 IF CODE F$<=27 OR CODE F$>=29 THEN GOTO 420
 495 IF C$="1" THEN LET E$="  = "+E$
 500 LET H=LEN E$
 510 LET A(F,3)=A(F,2)+H
 520 LET A$(A(F,2) TO A(F,2)+H)=E$
 530 IF CODE D$<=28 OR CODE D$>=3 THEN GOTO 600
 540 CLS 
 550 PRINT "WHAT IS THE EXPLANATION","NO EXPLANATION INPUT A SPACE",B$
 560 INPUT H$
 565 CLS 
 570 PRINT H$;TAB 0;"INPUT 0 IF THIS IS CORRECT","INPUT 1 IF NOT CORRECT",B$
 580 INPUT F$
 590 IF CODE F$<=27 OR CODE F$>=29 THEN GOTO 540
 600 LET H=LEN H$
 610 LET A(F,4)=A(F,3)+H
 620 LET A$(A(F,3) TO A(F,3)+H)=H$
 630 IF CODE C$<=28 OR CODE C$>=30 THEN GOTO 750
 640 FOR C=1 TO B
 650 CLS 
 660 PRINT "WHAT IS THE NUMBER ";C;" CHOICE?","FOR NO CHOICE INPUT A SPACE",B$
 670 INPUT E$
 675 CLS 
 680 PRINT C;" = ";E$;TAB 0;"INPUT 0 IF THIS IS CORRECT","INPUT 1 IF NOT CORRECT",B$
 690 INPUT F$
 700 IF CODE F$<=27 OR CODE F$>=29 THEN GOTO 650
 705 LET E$=CHR$ (C+28)+" = "+E$
 710 LET H=LEN E$
 720 LET A(F,4+C)=A(F,3+C)+H
 730 LET A$(A(F,3+C) TO A(F,3+C)+H)=E$
 735 IF A$(A(F,2)+1 TO A(F,3)-1)=E$(2 TO ) THEN LET A$(A(F,2) TO A(F,2))=CHR$ (C+28)
 740 NEXT C
 750 LET A(F+1,1)=A(F,D)
 760 NEXT F
 770 CLS 
 780 PRINT "WHAT IS THE TITLE OF THE QUIZ?",B$
 790 INPUT I$
 795 CLS 
 800 PRINT I$;TAB 0;"INPUT 0 IF THIS IS CORRECT","INPUT 1 IF NOT CORRECT",B$
 810 INPUT F$
 820 IF CODE F$<=27 OR CODE F$>=29 THEN GOTO 770
 830 CLS 
 840 PRINT "WHAT IS YOUR NAME PLEASE?",B$
 850 INPUT J$
 860 CLS 
 870 PRINT "THANK YOU ";J$;TAB 0;"GET READY FOR YOUR QUIZ"
 880 PAUSE 400
 890 CLS 
 900 PRINT TAB 10;"% %Z%X%-%8%1% %Q%U%I%Z% ";TAB 0;I$;TAB 0;"TAKEN BY ";J$
 910 PAUSE 400
 920 FOR C=1 TO A
 930 CLS 
 940 LET E$=A$(A(C,1) TO A(C,2)-1)
 945 LET K$=A$(A(C,2) TO A(C,3)-1)
 950 PRINT "QUESTION NUMBER ";C;TAB 0;E$;TAB 0;B$( TO 32)
 955 IF C$="1" THEN LET K$=A$(A(C,2) TO A(C,2))
 960 IF C$="1" THEN FOR I=4 TO D-1
 970 IF C$="1" THEN PRINT A$(A(C,I) TO A(C,I+1)-1)
 980 IF C$="1" THEN NEXT I
 990 IF C$="2" THEN PRINT "1 = TRUE",,"0 = FALSE"
\n1000 PRINT B$
\n1010 INPUT F$
\n1020 IF K$=F$ THEN PRINT "% %V%E%R%Y% %G%O%O%D% %T%H%A%T% %I%S% %C%O%R%R%E%C%T% "
\n1030 IF K$=F$ THEN PAUSE 400
\n1040 IF K$=F$ THEN LET S=S+1
\n1050 IF K$=F$ THEN GOTO 1150
\n1060 PRINT "% %I% %A%M% %S%O%R%R%Y% %T%H%A%T% %I%S% %N%O%T% %C%O%R%R%E%C%T% "
\n1070 PAUSE 400
\n1080 CLS 
\n1090 PRINT "THE CORRECT ANSWER IS";TAB 0;A$(A(C,2) TO A(C,3)-1)
\n1100 IF C$="2" AND K$="1" THEN PRINT AT 1,0;"1 = TRUE"
\n1110 IF C$="2" AND K$="0" THEN PRINT AT 1,0;"0 = FALSE"
\n1120 PRINT A$(A(C,3) TO A(C,4)-1)
\n1130 PRINT "PRESS % %E%N%T%E%R%  TO CONTINUE",B$
\n1140 INPUT E$
\n1150 NEXT C
\n1160 CLS 
\n1170 PRINT "QUIZ IS COMPLETE. THANK YOU",J$;TAB 0,,"YOUR SCORE IS ";S;" % %C%O%R%R%E%C%T% ","OUT OF A POSSIBLE ";A;" QUESTIONS.";TAB 0;"YOUR GRADE AVERAGE IS ",S/A*100;" PER CENT"
\n1180 PAUSE 400
\n1190 PRINT AT 15,0;"DO YOU WISH TO SAVE THIS PROGRAM1 = NO",,"0 = YES",,B$
\n1200 LET S=0
\n1210 INPUT F$
\n1220 IF CODE F$<=27 OR CODE F$>=29 THEN GOTO 830
\n1230 SAVE "QUIZ"
\n1240 GOTO 830
\n1250 CLEAR 
\n1260 SAVE "1002%0"
\n1270 RUN 

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

Scroll to Top