ZX81 Quiz Builder

This file is part of and Timex Sinclair Public Domain Library Tape 1004. Download the collection to get this file.
Developer(s): Dale F Lipinski
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Education

This program is an interactive quiz-creation and quiz-taking tool that allows a teacher or user to author quizzes of three types: multiple choice, true/false, or direct answer. All question text, answers, explanations, and multiple-choice options are packed sequentially into a single large string array A$(10505,4) using a pointer table stored in the numeric array A(A+1,D), a compact storage technique that avoids wasting memory on fixed-length string slots. Six POKE statements at lines 283–288 directly manipulate memory at a calculated address (derived via PEEK 16400/16401) to set up what appears to be a machine-code or system-variable patch. The quiz engine supports optional wrong-answer explanations, inverse-video prompts built from the B$ banner string, and a final percentage score display; results can be saved to tape under the filename “QUIZ-64K”.


Program Analysis

Program Structure

The program divides cleanly into three phases: configuration (lines 10–270), question authoring (lines 280–760), and quiz playback (lines 770–1260). During configuration the user selects quiz type, number of questions, whether wrong answers should be explained, and (for multiple choice) the maximum number of choices. Authoring collects questions, answers, explanations, and choices one at a time. Playback presents each question, accepts input, scores it, and finally reports a percentage grade.

Packed String Storage

Rather than declaring a 2-D string array with fixed-length rows (which wastes memory), the program stores all text in a single flat string array A$(10505,4) and maintains a pointer table in numeric array A(A+1,D). Each row F of A holds character offsets into A$:

  • A(F,1) — start of question text
  • A(F,2) — start of answer text
  • A(F,3) — start of explanation text
  • A(F,4) onward — start of each multiple-choice option

Slices are written with A$(A(F,n) TO A(F,n)+H)=E$ and read back with A$(A(C,n) TO A(C,n+1)-1). The sentinel value A(F+1,1)=A(F,D) (line 750) chains each question’s last offset to the next question’s start, making the whole array self-indexing.

Memory Manipulation (POKEs)

Lines 282–288 perform direct memory writes after computing a base address from the system variable at addresses 16400–16401:

L = PEEK 16400 + 256*PEEK 16401

The six bytes written starting at L+1 are:

OffsetValueDecimal
L+1410x29 — INC HL (Z80)
L+21640xA4 — AND H
L+310x01 — LD BC,nn (first byte)
L+4380x26 — LD H,n (or low byte of BC)
L+51640xA4 — AND H
L+600x00 — NOP

The exact intent is unclear without knowing the system variable pointed to, but this is a known technique for patching the ZX81/TS1000 BASIC interpreter or I/O routines at run time to extend available memory or modify behaviour before the large DIM statements at lines 280–281 consume RAM.

Quiz Type Logic

The variable C$ encodes quiz type: "1" = multiple choice, "2" = true/false, "3" = direct answer. Branching is handled throughout with inline IF C$="x" THEN … guards rather than a structured subroutine, keeping the code flat but repetitive. For multiple choice, the correct-answer byte is overwritten in A$ at line 735 with CHR$(C+28), encoding the choice number as a low ASCII code to allow a single-character comparison at answer time (line 955).

Input Validation Idiom

Throughout the program, user input is validated by checking CODE of the first character against expected ranges. For example:

  • Line 70: IF CODE C$<=28 OR CODE C$>=32 THEN GOTO 40 — accepts only characters with codes 29, 30, or 31 (digits “1”, “2”, “3” on the ZX81 character set).
  • Line 140: accepts codes 28 or 29 only (“0” or “1”).
  • Lines 270, 380, 490, etc.: similar range checks.

This avoids the overhead of string comparison for single-character inputs and is a common ZX81 BASIC idiom.

Banner String B$

Line 30 builds a reusable prompt banner B$ consisting of a long row of block-graphic characters followed by the inverse-video text ENTER ANSWER. It is printed at the bottom of most input screens as a consistent UI element. At line 950 only the first 32 characters of B$ are printed (B$( TO 32)), omitting the text portion when only a visual divider is needed.

Score and Save

The score accumulator S is reset to 0 at line 1200 (after display) so the quiz can be repeated without restarting. If the user opts to save, line 1230 executes SAVE "QUIZ-64K" which saves the entire program including the populated data arrays, allowing the completed quiz to be reloaded and retaken. Line 1250 (SAVE "1018%9") and line 1260 (RUN) appear to be a secondary save/restart block that would only be reached by a direct GO TO 1250; they are unreachable in normal flow.

Notable Bugs and Anomalies

  • Line 530: IF CODE D$<=28 OR CODE D$>=3 THEN GOTO 600 — the condition CODE D$>=3 is always true for any printable character, so the explanation-entry block (lines 540–590) is never reached. The intended condition was probably CODE D$>=30 (mirroring line 140), meaning “skip if D$≠’1′”.
  • Line 400/410: A(F,2)=A(F,1)+H and A$(A(F,1) TO A(F,1)+H)=E$ — the slice written is H+1 characters wide (inclusive both ends), but A(F,2) is set to A(F,1)+H, so when reading back at line 940 the slice A$(A(C,1) TO A(C,2)-1) is only H characters. This off-by-one means the last character of each stored string is effectively ignored during playback.
  • Line 250: LET E=42022 is a hard-coded constant labelled as “total character input”; it bears no computed relationship to A (number of questions) but is used to display an “average characters per question” figure, so this is cosmetic only.
  • Line 170: serves as a re-entry point for the choices-count screen; jumping here from line 215 on invalid input is correct, but it also re-runs CLS and skips re-printing the number-of-questions prompt, which could confuse a user who enters 10 or more choices.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10176 – 10210.

Related Products

Related Content

Image Gallery

ZX81 Quiz Builder

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=42022
 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)
 281 DIM A$(10505,4)
 282 LET L=PEEK 16400+256*PEEK 16401
 283 POKE L+1,41
 284 POKE L+2,164
 285 POKE L+3,1
 286 POKE L+4,38
 287 POKE L+5,164
 288 POKE L+6,0
 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-64K"
\n1240 GOTO 830
\n1250 SAVE "1018%9"
\n1260 RUN 

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

Scroll to Top