/* QST.C Copyright (C) 1993 Fergus Patrick Duniho */ #define MAXLINE 256 typedef struct qnode { int p[2]; int num, ans, first; char *Qtext, *Atext[2]; struct qnode *pv, *nx; } qst; qst *RND_QList (qst *Q, int size); char *Get_QList (char *fname, qst *Q, int size); void AskQuestions (qst *Q, int col); int AskQ (qst *Q, int col); char get_answer(int col); qst *new_qnode (int num); qst *new_qnode (int num) { qst *node; if ((node = (qst *)malloc(sizeof(qst))) == NULL) { perror ("Malloc can't allocate enough memory for a new qnode.\n"); exit (2); } node->ans = -1; node->num = num; return node; } /* Get_QList: Reads questions from a file into a linked list. Returns the version # string from the beginning of the questions file. */ char *Get_QList (char *fname, qst *Q, int size) { FILE *fptr; int i, j; char *V; qst *S; S = Q; RdOpen (fptr, fname); V = clone_line(fptr, MAXLINE); for (i = 1; i <= size; i++) { Q->nx = new_qnode(i); Q->nx->pv = Q; Q = Q->nx; Q->Qtext = clone_line(fptr, MAXLINE); for (j = 0; j < 2; j++) { Q->p[j] = fgetp(fptr); Q->Atext[j] = clone_line(fptr, MAXLINE); } } fclose (fptr); Q->nx = S; return V; } /* nth_qnode: Returns the nth member of a linked list of qst nodes. */ qst *nth_qnode (qst *Q, unsigned int n) { while (n--) Q = Q->nx; return Q; } /* RND_QList: Randomizes a linked list of questions. */ qst *RND_QList (qst *Q, int size) { qst *S, *L, *N, *SN; unsigned int i; SN = N = new_qnode(0); /* Randomizes Question Order */ S = Q; for (; size; size--) { i = (rand() % size) + 1; L = nth_qnode(S, i); L->nx->pv = L->pv; L->pv->nx = L->nx; N->nx = L; L->pv = N; N = L; N->first = rand() % 2; /* Randomizes Answer Order */ } free (S); N->nx = SN; SN->pv = N; return SN; } void AskQuestions (qst *Q, int col) { int more = 1, flag = 1, num; while (more) { for (Q = Q->nx, num = 1; Q->num > 0; Q = Q->nx, num++) { if ((Q->ans != -1) && flag) continue; flag = 1; printf ("\nQuestion #%d\n", num); if (AskQ(Q, col)) { Q = Q->pv->pv; flag = 0; num -= 2; if (num < 0) num = 0; } } more = 0; for (Q = Q->nx; Q->num > 0; Q = Q->nx) if (Q->ans == -1) more = 1; } } /* AskQ: Asks a single question. */ int AskQ (qst *Q, int col) { char A; wrapwrite (stdout, 0, 0, col, Q->Qtext, 0); wrapwrite (stdout, 0, 4, col, "(A)", Q->Atext[0], 0); puts (" ... Or"); wrapwrite (stdout, 0, 4, col, "(B)", Q->Atext[1], 0); if ((A = get_answer(col)) < 2) Q->ans = Q->p[A]; else if (A == 4) exit (2); return A == 3; } char get_answer(int col) { char c; for (;;) { c = fgetc(stdin); while (fgetc(stdin) != '\n'); if (islower(c)) c = toupper(c); if (c == 'A') return 0; if (c == 'B') return 1; if (c == 'S') return 2; if (c == 'P') return 3; if (c == 'Q') return 4; wrapwrite (stdout, 0, 0, col, "Answer with an A or a B.\n", "P = Go back to Previous question\n", "Q = Quit\n", "S = Skip until later.\n", 0); } }