2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Jim R. Oldroyd at The Instruction Set and Keith Gabryelski at
7 * Commodore Business Machines.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#) Copyright (c) 1991, 1993 The Regents of the University of California. All rights reserved.
34 * @(#)quiz.c 8.3 (Berkeley) 5/4/95
35 * $FreeBSD: src/games/quiz/quiz.c,v 1.12 1999/12/12 02:29:54 billf Exp $
36 * $DragonFly: src/games/quiz/quiz.c,v 1.7 2007/09/08 10:49:00 swildner Exp $
39 #include <sys/types.h>
50 #include "pathnames.h"
53 static int catone
, cattwo
, tflag
;
56 char *appdstr (char *, char *, size_t);
57 void downcase (char *);
58 void err (const char *, ...) __printflike(1, 2);
59 void get_cats (char *, char *);
60 void get_file (const char *);
61 char *next_cat (char *);
63 void score (u_int
, u_int
, u_int
);
64 void show_index (void);
68 main(int argc
, char **argv
)
71 const char *indexfile
;
76 indexfile
= _PATH_QUIZIDX
;
77 while ((ch
= getopt(argc
, argv
, "i:t")) != -1)
99 get_cats(argv
[0], argv
[1]);
109 get_file(const char *file
)
116 if ((fp
= fopen(file
, "r")) == NULL
)
117 err("%s: %s", file
, strerror(errno
));
121 * Should really free up space from any earlier read list
122 * but there are no reverse pointers to do so with.
126 while ((lp
= fgetln(fp
, &len
)) != NULL
) {
127 if (qp
->q_text
&& qp
->q_text
[strlen(qp
->q_text
) - 1] == '\\')
128 qp
->q_text
= appdstr(qp
->q_text
, lp
, len
);
130 if ((qp
->q_next
= malloc(sizeof(QE
))) == NULL
)
131 err("%s", strerror(errno
));
134 if ((qp
->q_text
= strdup(lp
)) == NULL
)
135 err("%s", strerror(errno
));
136 qp
->q_asked
= qp
->q_answered
= FALSE
;
151 if ((pf
= popen(_PATH_PAGER
, "w")) == NULL
)
152 err("%s: %s", _PATH_PAGER
, strerror(errno
));
153 (void)fprintf(pf
, "Subjects:\n\n");
154 for (qp
= qlist
.q_next
; qp
; qp
= qp
->q_next
) {
155 for (s
= next_cat(qp
->q_text
); s
; s
= next_cat(s
)) {
158 if ((p
= rxp_expand()) != '\0')
159 (void)fprintf(pf
, "%s ", p
);
161 (void)fprintf(pf
, "\n");
163 (void)fprintf(pf
, "\n%s\n%s\n%s\n",
164 "For example, \"quiz victim killer\" prints a victim's name and you reply",
165 "with the killer, and \"quiz killer victim\" works the other way around.",
166 "Type an empty line to get the correct answer.");
171 get_cats(char *cat1
, char *cat2
)
179 for (qp
= qlist
.q_next
; qp
; qp
= qp
->q_next
) {
180 s
= next_cat(qp
->q_text
);
181 catone
= cattwo
= i
= 0;
192 if (catone
&& cattwo
&& catone
!= cattwo
) {
193 if (!rxp_compile(qp
->q_text
))
195 get_file(rxp_expand());
199 err("invalid categories");
208 u_int guesses
, rights
, wrongs
;
210 char *answer
, *s
, *t
, question
[LINE_SZ
];
213 guesses
= rights
= wrongs
= 0;
217 next
= random() % qsize
;
219 for (i
= 0; i
< next
; i
++)
221 while (qp
&& qp
->q_answered
)
227 if (tflag
&& random() % 100 > 20) {
228 /* repeat questions in tutorial mode */
229 while (qp
&& (!qp
->q_asked
|| qp
->q_answered
))
235 for (i
= 0; i
< catone
- 1; i
++)
240 if (!t
|| *t
== '\0') {
241 qp
->q_answered
= TRUE
;
244 (void)strcpy(question
, t
);
246 for (i
= 0; i
< cattwo
- 1; i
++)
251 if (!t
|| *t
== '\0') {
252 qp
->q_answered
= TRUE
;
256 (void)printf("%s?\n", question
);
258 if ((answer
= fgetln(stdin
, &len
)) == NULL
) {
259 score(rights
, wrongs
, guesses
);
262 answer
[len
- 1] = '\0';
264 if (rxp_match(answer
)) {
265 (void)printf("Right!\n");
267 qp
->q_answered
= TRUE
;
270 if (*answer
== '\0') {
271 (void)printf("%s\n", t
);
274 qp
->q_answered
= TRUE
;
277 (void)printf("What?\n");
280 score(rights
, wrongs
, guesses
);
300 appdstr(char *s
, char *tp
, size_t len
)
305 if ((m
= malloc(strlen(s
) + len
+ 1)) == NULL
)
306 err("%s", strerror(errno
));
309 for (; (*mp
++ = *sp
++););
312 if (*(mp
- 1) == '\\')
316 if (mp
[len
- 1] == '\n')
324 score(u_int r
, u_int w
, u_int g
)
326 (void)printf("Rights %d, wrongs %d,", r
, w
);
328 (void)printf(" extra guesses %d,", g
);
329 (void)printf(" score %d%%\n", (r
+ w
+ g
) ? r
* 100 / (r
+ w
+ g
) : 0);
337 for (; (ch
= *p
); ++p
)
338 if (isascii(ch
) && isupper(ch
))
345 (void)fprintf(stderr
, "quiz [-t] [-i file] category1 category2\n");
352 err(const char *fmt
, ...)
356 (void)fprintf(stderr
, "quiz: ");
357 (void)vfprintf(stderr
, fmt
, ap
);
359 (void)fprintf(stderr
, "\n");