Commit | Line | Data |
---|---|---|
783c5c09 BJ |
1 | /* Copyright (c) 1979 Regents of the University of California */ |
2 | #include <retrofit.h> | |
3 | #include <stdio.h> | |
4 | #include <ctype.h> | |
5 | #include <sgtty.h> | |
6 | #include <signal.h> | |
7 | ||
8 | #define CTRL(x) ('x' & 037) | |
9 | #define DELETE 0177 | |
10 | ||
11 | int btime, wtime; | |
12 | int state; | |
13 | int paused; | |
14 | int move; | |
15 | int movebrk; | |
16 | int cmoves; | |
17 | int ctime; | |
18 | ||
19 | #define WHITE 0 | |
20 | #define BLACK 1 | |
21 | ||
22 | struct sgttyb norm; | |
23 | struct sgttyb raw; | |
24 | ||
25 | char *pt(); | |
26 | ||
27 | main(argc, argv) | |
28 | int argc; | |
29 | char *argv[]; | |
30 | { | |
31 | ||
32 | argc--, argv++; | |
33 | gtty(1, &norm); | |
34 | gtty(1, &raw); /* No structure assignment */ | |
35 | btime = wtime = 300; | |
36 | movebrk = 80, ctime = 0, cmoves = 0; | |
37 | while (argc > 0) { | |
38 | if (argv[0][0] != '-') { | |
39 | usage: | |
40 | fprintf(stderr, "Usage: chessclock [ -m moves ] [ -t tlim ] [ -M xmoves ] [ -T xtime ]\n"); | |
41 | exit (1); | |
42 | } | |
43 | if (argc < 2) | |
44 | goto usage; | |
45 | switch (argv[0][1]) { | |
46 | ||
47 | case 'm': | |
48 | if (!number(argv[1])) | |
49 | goto usage; | |
50 | movebrk = 2 * getn(argv[1]) + 1; | |
51 | break; | |
52 | ||
53 | case 't': | |
54 | if (!istime(argv[1])) | |
55 | goto usage; | |
56 | btime = wtime = gettime(argv[1]); | |
57 | break; | |
58 | ||
59 | case 'M': | |
60 | if (!number(argv[1])) | |
61 | goto usage; | |
62 | cmoves = 2 * getn(argv[1]); | |
63 | break; | |
64 | ||
65 | case 'T': | |
66 | if (!istime(argv[1])) | |
67 | goto usage; | |
68 | ctime = gettime(argv[1]); | |
69 | break; | |
70 | ||
71 | default: | |
72 | goto usage; | |
73 | } | |
74 | argv += 2, argc -= 2; | |
75 | } | |
76 | if (movebrk) { | |
77 | if (cmoves == 0) | |
78 | cmoves = movebrk - 1; | |
79 | if (ctime == 0) | |
80 | ctime = btime; | |
81 | } | |
82 | raw.sg_flags |= RAW; | |
83 | raw.sg_flags &= ~ECHO; | |
84 | stty(1, &raw); | |
85 | printf("Hit space to begin, ? for information\r\n"); | |
86 | state = BLACK; | |
87 | paused = 1; | |
88 | doit(); | |
89 | } | |
90 | ||
91 | onalrm() | |
92 | { | |
93 | char tbuf[10]; | |
94 | ||
95 | signal(SIGALRM, onalrm); | |
96 | if (paused) | |
97 | return; | |
98 | charge(1); | |
99 | printf("\b\b\b\b%s\b", pt(tbuf, state == BLACK ? btime : wtime)); | |
100 | alarm(1); | |
101 | } | |
102 | ||
103 | doit() | |
104 | { | |
105 | int t, c; | |
106 | ||
107 | move = 0; | |
108 | signal(SIGALRM, onalrm); | |
109 | for (;;) { | |
110 | alarm(1); | |
111 | c = readone(); | |
112 | t = 1 - alarm(0); | |
113 | switch (c) { | |
114 | ||
115 | default: | |
116 | printf("\r\n\r\nSpace move\r\n"); | |
117 | printf("p pause\r\n"); | |
118 | printf("c continue\r\n"); | |
119 | printf("q quit\r\n"); | |
120 | printf("! shell escape\r\n"); | |
121 | printf("\r\n"); | |
122 | fixit(); | |
123 | continue; | |
124 | ||
125 | case ' ': | |
126 | if (!paused) { | |
127 | charge(t); | |
128 | if (state == BLACK) | |
129 | printf("\r\n"); | |
130 | } | |
131 | paused = 0; | |
132 | move++; | |
133 | if (move == movebrk && cmoves != 0) { | |
134 | movebrk += cmoves; | |
135 | btime = wtime = ctime; | |
136 | } | |
137 | state = state == WHITE ? BLACK : WHITE; | |
138 | fixit(); | |
139 | continue; | |
140 | ||
141 | case 'c': | |
142 | if (!paused) | |
143 | charge(t); | |
144 | paused = 0; | |
145 | continue; | |
146 | ||
147 | case '!': | |
148 | if (!paused) | |
149 | charge(t); | |
150 | stty(1, &norm); | |
151 | printf("\r\n!"); | |
152 | system("sh -t"); | |
153 | printf("!\r\n"); | |
154 | printf("Hit c to continue\r\n"); | |
155 | stty(1, &raw); | |
156 | t = 0; | |
157 | fixit(); | |
158 | paused = 1; | |
159 | continue; | |
160 | ||
161 | case 'p': | |
162 | if (!paused) | |
163 | charge(t); | |
164 | paused = 1; | |
165 | continue; | |
166 | ||
167 | case 'q': | |
168 | case CTRL(\\\\): | |
169 | case DELETE: | |
170 | printf("\r\n"); | |
171 | exit(1); | |
172 | } | |
173 | } | |
174 | } | |
175 | ||
176 | fixit() | |
177 | { | |
178 | register int i; | |
179 | char wbuf[10], bbuf[10]; | |
180 | ||
181 | printf("\r%3d %s %s", (move + 1) / 2, | |
182 | pt(wbuf, wtime), pt(bbuf, btime)); | |
183 | if (state == WHITE) | |
184 | for (i = 0; i < 8; i++) | |
185 | printf("\b"); | |
186 | printf("\b"); | |
187 | } | |
188 | ||
189 | charge(c) | |
190 | int c; | |
191 | { | |
192 | ||
193 | if (state == WHITE) { | |
194 | wtime -= c; | |
195 | if (wtime <= 0) { | |
196 | printf("\r\n\07\07\07\07\07White loses on time\r\n"); | |
197 | exit(0); | |
198 | } | |
199 | } else { | |
200 | btime -= c; | |
201 | if (btime <= 0) { | |
202 | printf("\r\n\07\07\07\07\07Black loses on time\r\n"); | |
203 | exit(0); | |
204 | } | |
205 | } | |
206 | } | |
207 | ||
208 | readone() | |
209 | { | |
210 | char c; | |
211 | ||
212 | while (read(0, &c, 1) != 1) | |
213 | if (!isatty(0)) | |
214 | exit(1); | |
215 | return (c); | |
216 | } | |
217 | ||
218 | exit(c) | |
219 | int c; | |
220 | { | |
221 | ||
222 | stty(1, &norm); | |
223 | _exit(c); | |
224 | } | |
225 | ||
226 | char * | |
227 | pt(buf, tim) | |
228 | char *buf; | |
229 | int tim; | |
230 | { | |
231 | ||
232 | sprintf(buf, "%2d:%1d%1d", tim / 60, (tim % 60) / 10, tim % 10); | |
233 | return (buf); | |
234 | } | |
235 | ||
236 | number(cp) | |
237 | char *cp; | |
238 | { | |
239 | ||
240 | if (!isdigit(*cp)) | |
241 | return (0); | |
242 | while (isdigit(*cp)) | |
243 | cp++; | |
244 | return (*cp == 0); | |
245 | } | |
246 | ||
247 | istime(cp) | |
248 | char *cp; | |
249 | { | |
250 | ||
251 | if (*cp != ':' && !isdigit(*cp)) | |
252 | return (0); | |
253 | while (isdigit(*cp)) | |
254 | cp++; | |
255 | if (*cp == ':') | |
256 | cp++; | |
257 | while (isdigit(*cp)) | |
258 | cp++; | |
259 | return (*cp == 0); | |
260 | } | |
261 | ||
262 | gettime(cp) | |
263 | char *cp; | |
264 | { | |
265 | int t = 0, s = 0; | |
266 | ||
267 | while (isdigit(*cp)) | |
268 | t = t * 10 + *cp++ - '0'; | |
269 | if (*cp != ':') | |
270 | return (t * 60); | |
271 | cp++; | |
272 | s = 0; | |
273 | while (isdigit(*cp)) | |
274 | s = s * 10 + *cp++ - '0'; | |
275 | return (t * 60 + s); | |
276 | } | |
277 | ||
278 | getn(cp) | |
279 | char *cp; | |
280 | { | |
281 | ||
282 | int i = 0; | |
283 | ||
284 | while (*cp) | |
285 | i = i * 10 + *cp++ - '0'; | |
286 | return (i); | |
287 | } |