Commit | Line | Data |
---|---|---|
e04f5cf8 KB |
1 | /*- |
2 | * Copyright (c) 1990 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Ed James. | |
7 | * | |
af359dea C |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | |
16 | * 3. All advertising materials mentioning features or use of this software | |
17 | * must display the following acknowledgement: | |
18 | * This product includes software developed by the University of | |
19 | * California, Berkeley and its contributors. | |
20 | * 4. Neither the name of the University nor the names of its contributors | |
21 | * may be used to endorse or promote products derived from this software | |
22 | * without specific prior written permission. | |
23 | * | |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34 | * SUCH DAMAGE. | |
e04f5cf8 KB |
35 | */ |
36 | ||
864befdb KB |
37 | /* |
38 | * Copyright (c) 1987 by Ed James, UC Berkeley. All rights reserved. | |
39 | * | |
40 | * Copy permission is hereby granted provided that this notice is | |
41 | * retained on all partial or complete copies. | |
42 | * | |
43 | * For more info on this and all of my stuff, mail edjames@berkeley.edu. | |
44 | */ | |
45 | ||
46 | #ifndef lint | |
1c15e888 | 47 | static char sccsid[] = "@(#)input.c 5.4 (Berkeley) 4/30/90"; |
864befdb KB |
48 | #endif not lint |
49 | ||
50 | #include "include.h" | |
7abf8d65 | 51 | #include "pathnames.h" |
864befdb KB |
52 | |
53 | #define MAXRULES 6 | |
54 | #define MAXDEPTH 15 | |
55 | ||
56 | #define RETTOKEN '\n' | |
57 | #ifdef SYSV | |
58 | #define CRTOKEN '\r' | |
59 | #endif | |
60 | #define REDRAWTOKEN '\014' /* CTRL(L) */ | |
61 | #define SHELLTOKEN '!' | |
62 | #define HELPTOKEN '?' | |
63 | #define ALPHATOKEN 256 | |
64 | #define NUMTOKEN 257 | |
65 | ||
66 | typedef struct { | |
67 | int token; | |
68 | int to_state; | |
69 | char *str; | |
70 | char *(*func)(); | |
71 | } RULE; | |
72 | ||
73 | typedef struct { | |
74 | int num_rules; | |
75 | RULE *rule; | |
76 | } STATE; | |
77 | ||
78 | typedef struct { | |
79 | char str[20]; | |
80 | int state; | |
81 | int rule; | |
82 | int ch; | |
83 | int pos; | |
84 | } STACK; | |
85 | ||
86 | #define T_RULE stack[level].rule | |
87 | #define T_STATE stack[level].state | |
88 | #define T_STR stack[level].str | |
89 | #define T_POS stack[level].pos | |
90 | #define T_CH stack[level].ch | |
91 | ||
92 | #define NUMELS(a) (sizeof (a) / sizeof (*(a))) | |
93 | ||
94 | #define NUMSTATES NUMELS(st) | |
95 | ||
96 | char *setplane(), *circle(), *left(), *right(), *Left(), *Right(), | |
97 | *beacon(), *ex_it(), *climb(), *descend(), *setalt(), *setrelalt(), | |
98 | *benum(), *to_dir(), *rel_dir(), *delayb(), *mark(), *unmark(), | |
99 | *airport(), *turn(), *ignore(); | |
100 | ||
101 | RULE state0[] = { { ALPHATOKEN, 1, "%c:", setplane}, | |
102 | { RETTOKEN, -1, "", NULL }, | |
103 | #ifdef SYSV | |
104 | { CRTOKEN, -1, "", NULL }, | |
105 | #endif | |
106 | { HELPTOKEN, 12, " [a-z]<ret>", NULL }}, | |
107 | state1[] = { { 't', 2, " turn", turn }, | |
108 | { 'a', 3, " altitude:", NULL }, | |
109 | { 'c', 4, " circle", circle }, | |
110 | { 'm', 7, " mark", mark }, | |
111 | { 'u', 7, " unmark", unmark }, | |
112 | { 'i', 7, " ignore", ignore }, | |
113 | { HELPTOKEN, 12, " tacmui", NULL }}, | |
114 | state2[] = { { 'l', 6, " left", left }, | |
115 | { 'r', 6, " right", right }, | |
116 | { 'L', 4, " left 90", Left }, | |
117 | { 'R', 4, " right 90", Right }, | |
118 | { 't', 11, " towards", NULL }, | |
119 | { 'w', 4, " to 0", to_dir }, | |
120 | { 'e', 4, " to 45", to_dir }, | |
121 | { 'd', 4, " to 90", to_dir }, | |
122 | { 'c', 4, " to 135", to_dir }, | |
123 | { 'x', 4, " to 180", to_dir }, | |
124 | { 'z', 4, " to 225", to_dir }, | |
125 | { 'a', 4, " to 270", to_dir }, | |
126 | { 'q', 4, " to 315", to_dir }, | |
127 | { HELPTOKEN, 12, " lrLRt<dir>", NULL }}, | |
128 | state3[] = { { '+', 10, " climb", climb }, | |
129 | { 'c', 10, " climb", climb }, | |
130 | { '-', 10, " descend", descend }, | |
131 | { 'd', 10, " descend", descend }, | |
132 | { NUMTOKEN, 7, " %c000 feet", setalt }, | |
133 | { HELPTOKEN, 12, " +-cd[0-9]", NULL }}, | |
134 | state4[] = { { '@', 9, " at", NULL }, | |
135 | { 'a', 9, " at", NULL }, | |
136 | { RETTOKEN, -1, "", NULL }, | |
137 | #ifdef SYSV | |
138 | { CRTOKEN, -1, "", NULL }, | |
139 | #endif | |
140 | { HELPTOKEN, 12, " @a<ret>", NULL }}, | |
141 | state5[] = { { NUMTOKEN, 7, "%c", delayb }, | |
142 | { HELPTOKEN, 12, " [0-9]", NULL }}, | |
143 | state6[] = { { '@', 9, " at", NULL }, | |
144 | { 'a', 9, " at", NULL }, | |
145 | { 'w', 4, " 0", rel_dir }, | |
146 | { 'e', 4, " 45", rel_dir }, | |
147 | { 'd', 4, " 90", rel_dir }, | |
148 | { 'c', 4, " 135", rel_dir }, | |
149 | { 'x', 4, " 180", rel_dir }, | |
150 | { 'z', 4, " 225", rel_dir }, | |
151 | { 'a', 4, " 270", rel_dir }, | |
152 | { 'q', 4, " 315", rel_dir }, | |
153 | { RETTOKEN, -1, "", NULL }, | |
154 | #ifdef SYSV | |
155 | { CRTOKEN, -1, "", NULL }, | |
156 | #endif | |
157 | { HELPTOKEN, 12, " @a<dir><ret>",NULL }}, | |
158 | state7[] = { { RETTOKEN, -1, "", NULL }, | |
159 | #ifdef SYSV | |
160 | { CRTOKEN, -1, "", NULL }, | |
161 | #endif | |
162 | { HELPTOKEN, 12, " <ret>", NULL }}, | |
163 | state8[] = { { NUMTOKEN, 4, "%c", benum }, | |
164 | { HELPTOKEN, 12, " [0-9]", NULL }}, | |
165 | state9[] = { { 'b', 5, " beacon #", NULL }, | |
166 | { '*', 5, " beacon #", NULL }, | |
167 | { HELPTOKEN, 12, " b*", NULL }}, | |
168 | state10[] = { { NUMTOKEN, 7, " %c000 ft", setrelalt}, | |
169 | { HELPTOKEN, 12, " [0-9]", NULL }}, | |
170 | state11[] = { { 'b', 8, " beacon #", beacon }, | |
171 | { '*', 8, " beacon #", beacon }, | |
172 | { 'e', 8, " exit #", ex_it }, | |
173 | { 'a', 8, " airport #", airport }, | |
174 | { HELPTOKEN, 12, " b*ea", NULL }}, | |
175 | state12[] = { { -1, -1, "", NULL }}; | |
176 | ||
177 | #define DEF_STATE(s) { NUMELS(s), (s) } | |
178 | ||
179 | STATE st[] = { | |
180 | DEF_STATE(state0), DEF_STATE(state1), DEF_STATE(state2), | |
181 | DEF_STATE(state3), DEF_STATE(state4), DEF_STATE(state5), | |
182 | DEF_STATE(state6), DEF_STATE(state7), DEF_STATE(state8), | |
183 | DEF_STATE(state9), DEF_STATE(state10), DEF_STATE(state11), | |
184 | DEF_STATE(state12) | |
185 | }; | |
186 | ||
187 | PLANE p; | |
188 | STACK stack[MAXDEPTH]; | |
189 | int level; | |
190 | int tval; | |
191 | int dest_type, dest_no, dir; | |
192 | ||
193 | pop() | |
194 | { | |
195 | if (level == 0) | |
196 | return (-1); | |
197 | level--; | |
198 | ||
199 | ioclrtoeol(T_POS); | |
200 | ||
201 | strcpy(T_STR, ""); | |
202 | T_RULE = -1; | |
203 | T_CH = -1; | |
204 | return (0); | |
205 | } | |
206 | ||
207 | rezero() | |
208 | { | |
209 | iomove(0); | |
210 | ||
211 | level = 0; | |
212 | T_STATE = 0; | |
213 | T_RULE = -1; | |
214 | T_CH = -1; | |
215 | T_POS = 0; | |
216 | strcpy(T_STR, ""); | |
217 | } | |
218 | ||
219 | push(ruleno, ch) | |
220 | { | |
221 | int newstate, newpos; | |
222 | ||
e7c6fb2c | 223 | (void)sprintf(T_STR, st[T_STATE].rule[ruleno].str, tval); |
864befdb KB |
224 | T_RULE = ruleno; |
225 | T_CH = ch; | |
226 | newstate = st[T_STATE].rule[ruleno].to_state; | |
227 | newpos = T_POS + strlen(T_STR); | |
228 | ||
229 | ioaddstr(T_POS, T_STR); | |
230 | ||
231 | if (level == 0) | |
232 | ioclrtobot(); | |
233 | level++; | |
234 | T_STATE = newstate; | |
235 | T_POS = newpos; | |
236 | T_RULE = -1; | |
237 | strcpy(T_STR, ""); | |
238 | } | |
239 | ||
240 | getcommand() | |
241 | { | |
242 | int c, i, done; | |
243 | char *s, *(*func)(); | |
244 | PLANE *pp; | |
245 | ||
246 | rezero(); | |
247 | ||
248 | do { | |
249 | c = gettoken(); | |
250 | if (c == tty_new.sg_erase) { | |
251 | if (pop() < 0) | |
252 | noise(); | |
253 | } else if (c == tty_new.sg_kill) { | |
254 | while (pop() >= 0) | |
255 | ; | |
256 | } else { | |
257 | done = 0; | |
258 | for (i = 0; i < st[T_STATE].num_rules; i++) { | |
259 | if (st[T_STATE].rule[i].token == c || | |
260 | st[T_STATE].rule[i].token == tval) { | |
261 | push(i, (c >= ALPHATOKEN) ? tval : c); | |
262 | done = 1; | |
263 | break; | |
264 | } | |
265 | } | |
266 | if (!done) | |
267 | noise(); | |
268 | } | |
269 | } while (T_STATE != -1); | |
270 | ||
271 | if (level == 1) | |
272 | return (1); /* forced update */ | |
273 | ||
274 | dest_type = T_NODEST; | |
275 | ||
276 | for (i = 0; i < level; i++) { | |
277 | func = st[stack[i].state].rule[stack[i].rule].func; | |
278 | if (func != NULL) | |
279 | if ((s = (*func)(stack[i].ch)) != NULL) { | |
280 | ioerror(stack[i].pos, strlen(stack[i].str), s); | |
281 | return (-1); | |
282 | } | |
283 | } | |
284 | ||
285 | pp = findplane(p.plane_no); | |
286 | if (pp->new_altitude != p.new_altitude) | |
287 | pp->new_altitude = p.new_altitude; | |
288 | else if (pp->status != p.status) | |
289 | pp->status = p.status; | |
290 | else { | |
291 | pp->new_dir = p.new_dir; | |
292 | pp->delayd = p.delayd; | |
293 | pp->delayd_no = p.delayd_no; | |
294 | } | |
295 | return (0); | |
296 | } | |
297 | ||
298 | noise() | |
299 | { | |
300 | putchar('\07'); | |
301 | fflush(stdout); | |
302 | } | |
303 | ||
304 | gettoken() | |
305 | { | |
306 | while ((tval = getAChar()) == REDRAWTOKEN || tval == SHELLTOKEN) | |
307 | { | |
308 | if (tval == SHELLTOKEN) | |
309 | { | |
310 | #ifdef BSD | |
311 | struct itimerval itv; | |
312 | itv.it_value.tv_sec = 0; | |
313 | itv.it_value.tv_usec = 0; | |
314 | setitimer(ITIMER_REAL, &itv, NULL); | |
315 | #endif | |
316 | #ifdef SYSV | |
317 | int aval; | |
318 | aval = alarm(0); | |
319 | #endif | |
320 | if (fork() == 0) /* child */ | |
321 | { | |
322 | char *shell, *base, *getenv(), *strrchr(); | |
323 | ||
324 | setuid(getuid()); /* turn off setuid bit */ | |
325 | done_screen(); | |
326 | ||
327 | /* run user's favorite shell */ | |
328 | if ((shell = getenv("SHELL")) != NULL) | |
329 | { | |
330 | base = strrchr(shell, '/'); | |
331 | if (base == NULL) | |
332 | base = shell; | |
333 | else | |
334 | base++; | |
335 | execl(shell, base, 0); | |
336 | } | |
337 | else | |
7abf8d65 | 338 | execl(_PATH_BSHELL, "sh", 0); |
864befdb KB |
339 | |
340 | exit(0); /* oops */ | |
341 | } | |
342 | ||
343 | wait(0); | |
344 | #ifdef BSD | |
345 | ioctl(fileno(stdin), TIOCSETP, &tty_new); | |
346 | itv.it_value.tv_sec = 0; | |
347 | itv.it_value.tv_usec = 1; | |
348 | itv.it_interval.tv_sec = sp->update_secs; | |
349 | itv.it_interval.tv_usec = 0; | |
350 | setitimer(ITIMER_REAL, &itv, NULL); | |
351 | #endif | |
352 | #ifdef SYSV | |
353 | ioctl(fileno(stdin), TCSETAW, &tty_new); | |
354 | alarm(aval); | |
355 | #endif | |
356 | } | |
357 | redraw(); | |
358 | } | |
359 | ||
360 | if (isdigit(tval)) | |
361 | return (NUMTOKEN); | |
362 | else if (isalpha(tval)) | |
363 | return (ALPHATOKEN); | |
364 | else | |
365 | return (tval); | |
366 | } | |
367 | ||
368 | char * | |
369 | setplane(c) | |
370 | { | |
371 | PLANE *pp; | |
372 | ||
373 | pp = findplane(number(c)); | |
374 | if (pp == NULL) | |
375 | return ("Unknown Plane"); | |
376 | bcopy(pp, &p, sizeof (p)); | |
377 | p.delayd = 0; | |
378 | return (NULL); | |
379 | } | |
380 | ||
381 | char * | |
382 | turn(c) | |
383 | { | |
384 | if (p.altitude == 0) | |
385 | return ("Planes at airports may not change direction"); | |
386 | return (NULL); | |
387 | } | |
388 | ||
389 | char * | |
390 | circle(c) | |
391 | { | |
392 | if (p.altitude == 0) | |
393 | return ("Planes cannot circle on the ground"); | |
394 | p.new_dir = MAXDIR; | |
395 | return (NULL); | |
396 | } | |
397 | ||
398 | char * | |
399 | left(c) | |
400 | { | |
401 | dir = D_LEFT; | |
402 | p.new_dir = p.dir - 1; | |
403 | if (p.new_dir < 0) | |
404 | p.new_dir += MAXDIR; | |
405 | return (NULL); | |
406 | } | |
407 | ||
408 | char * | |
409 | right(c) | |
410 | { | |
411 | dir = D_RIGHT; | |
412 | p.new_dir = p.dir + 1; | |
413 | if (p.new_dir > MAXDIR) | |
414 | p.new_dir -= MAXDIR; | |
415 | return (NULL); | |
416 | } | |
417 | ||
418 | char * | |
419 | Left(c) | |
420 | { | |
421 | p.new_dir = p.dir - 2; | |
422 | if (p.new_dir < 0) | |
423 | p.new_dir += MAXDIR; | |
424 | return (NULL); | |
425 | } | |
426 | ||
427 | char * | |
428 | Right(c) | |
429 | { | |
430 | p.new_dir = p.dir + 2; | |
431 | if (p.new_dir > MAXDIR) | |
432 | p.new_dir -= MAXDIR; | |
433 | return (NULL); | |
434 | } | |
435 | ||
436 | char * | |
437 | delayb(c) | |
438 | { | |
439 | int xdiff, ydiff; | |
440 | ||
441 | c -= '0'; | |
442 | ||
443 | if (c >= sp->num_beacons) | |
444 | return ("Unknown beacon"); | |
445 | xdiff = sp->beacon[c].x - p.xpos; | |
446 | xdiff = SGN(xdiff); | |
447 | ydiff = sp->beacon[c].y - p.ypos; | |
448 | ydiff = SGN(ydiff); | |
449 | if (xdiff != displacement[p.dir].dx || ydiff != displacement[p.dir].dy) | |
450 | return ("Beacon is not in flight path"); | |
451 | p.delayd = 1; | |
452 | p.delayd_no = c; | |
453 | ||
454 | if (dest_type != T_NODEST) { | |
455 | switch (dest_type) { | |
456 | case T_BEACON: | |
457 | xdiff = sp->beacon[dest_no].x - sp->beacon[c].x; | |
458 | ydiff = sp->beacon[dest_no].y - sp->beacon[c].y; | |
459 | break; | |
460 | case T_EXIT: | |
461 | xdiff = sp->exit[dest_no].x - sp->beacon[c].x; | |
462 | ydiff = sp->exit[dest_no].y - sp->beacon[c].y; | |
463 | break; | |
464 | case T_AIRPORT: | |
465 | xdiff = sp->airport[dest_no].x - sp->beacon[c].x; | |
466 | ydiff = sp->airport[dest_no].y - sp->beacon[c].y; | |
467 | break; | |
468 | default: | |
469 | return ("Bad case in delayb! Get help!"); | |
470 | break; | |
471 | } | |
472 | if (xdiff == 0 && ydiff == 0) | |
473 | return ("Would already be there"); | |
474 | p.new_dir = DIR_FROM_DXDY(xdiff, ydiff); | |
475 | if (p.new_dir == p.dir) | |
476 | return ("Already going in that direction"); | |
477 | } | |
478 | return (NULL); | |
479 | } | |
480 | ||
481 | char * | |
482 | beacon(c) | |
483 | { | |
484 | dest_type = T_BEACON; | |
485 | return (NULL); | |
486 | } | |
487 | ||
488 | char * | |
489 | ex_it(c) | |
490 | { | |
491 | dest_type = T_EXIT; | |
492 | return (NULL); | |
493 | } | |
494 | ||
495 | char * | |
496 | airport(c) | |
497 | { | |
498 | dest_type = T_AIRPORT; | |
499 | return (NULL); | |
500 | } | |
501 | ||
502 | char * | |
503 | climb(c) | |
504 | { | |
505 | dir = D_UP; | |
506 | return (NULL); | |
507 | } | |
508 | ||
509 | char * | |
510 | descend(c) | |
511 | { | |
512 | dir = D_DOWN; | |
513 | return (NULL); | |
514 | } | |
515 | ||
516 | char * | |
517 | setalt(c) | |
518 | { | |
519 | if ((p.altitude == c - '0') && (p.new_altitude == p.altitude)) | |
520 | return ("Already at that altitude"); | |
521 | p.new_altitude = c - '0'; | |
522 | return (NULL); | |
523 | } | |
524 | ||
525 | char * | |
526 | setrelalt(c) | |
527 | { | |
528 | if (c == 0) | |
529 | return ("altitude not changed"); | |
530 | ||
531 | switch (dir) { | |
532 | case D_UP: | |
533 | p.new_altitude = p.altitude + c - '0'; | |
534 | break; | |
535 | case D_DOWN: | |
536 | p.new_altitude = p.altitude - (c - '0'); | |
537 | break; | |
538 | default: | |
539 | return ("Unknown case in setrelalt! Get help!"); | |
540 | break; | |
541 | } | |
542 | if (p.new_altitude < 0) | |
543 | return ("Altitude would be too low"); | |
544 | else if (p.new_altitude > 9) | |
545 | return ("Altitude would be too high"); | |
546 | return (NULL); | |
547 | } | |
548 | ||
549 | char * | |
550 | benum(c) | |
551 | { | |
552 | dest_no = c -= '0'; | |
553 | ||
554 | switch (dest_type) { | |
555 | case T_BEACON: | |
556 | if (c >= sp->num_beacons) | |
557 | return ("Unknown beacon"); | |
558 | p.new_dir = DIR_FROM_DXDY(sp->beacon[c].x - p.xpos, | |
559 | sp->beacon[c].y - p.ypos); | |
560 | break; | |
561 | case T_EXIT: | |
562 | if (c >= sp->num_exits) | |
563 | return ("Unknown exit"); | |
564 | p.new_dir = DIR_FROM_DXDY(sp->exit[c].x - p.xpos, | |
565 | sp->exit[c].y - p.ypos); | |
566 | break; | |
567 | case T_AIRPORT: | |
568 | if (c >= sp->num_airports) | |
569 | return ("Unknown airport"); | |
570 | p.new_dir = DIR_FROM_DXDY(sp->airport[c].x - p.xpos, | |
571 | sp->airport[c].y - p.ypos); | |
572 | break; | |
573 | default: | |
574 | return ("Unknown case in benum! Get help!"); | |
575 | break; | |
576 | } | |
577 | return (NULL); | |
578 | } | |
579 | ||
580 | char * | |
581 | to_dir(c) | |
582 | { | |
583 | p.new_dir = dir_no(c); | |
584 | return (NULL); | |
585 | } | |
586 | ||
587 | char * | |
588 | rel_dir(c) | |
589 | { | |
590 | int angle; | |
591 | ||
592 | angle = dir_no(c); | |
593 | switch (dir) { | |
594 | case D_LEFT: | |
595 | p.new_dir = p.dir - angle; | |
596 | if (p.new_dir < 0) | |
597 | p.new_dir += MAXDIR; | |
598 | break; | |
599 | case D_RIGHT: | |
600 | p.new_dir = p.dir + angle; | |
601 | if (p.new_dir >= MAXDIR) | |
602 | p.new_dir -= MAXDIR; | |
603 | break; | |
604 | default: | |
605 | return ("Bizarre direction in rel_dir! Get help!"); | |
606 | break; | |
607 | } | |
608 | return (NULL); | |
609 | } | |
610 | ||
611 | char * | |
612 | mark(c) | |
613 | { | |
614 | if (p.altitude == 0) | |
615 | return ("Cannot mark planes on the ground"); | |
616 | if (p.status == S_MARKED) | |
617 | return ("Already marked"); | |
618 | p.status = S_MARKED; | |
619 | return (NULL); | |
620 | } | |
621 | ||
622 | char * | |
623 | unmark(c) | |
624 | { | |
625 | if (p.altitude == 0) | |
626 | return ("Cannot unmark planes on the ground"); | |
627 | if (p.status == S_UNMARKED) | |
628 | return ("Already unmarked"); | |
629 | p.status = S_UNMARKED; | |
630 | return (NULL); | |
631 | } | |
632 | ||
633 | char * | |
634 | ignore(c) | |
635 | { | |
636 | if (p.altitude == 0) | |
637 | return ("Cannot ignore planes on the ground"); | |
638 | if (p.status == S_IGNORED) | |
639 | return ("Already ignored"); | |
640 | p.status = S_IGNORED; | |
641 | return (NULL); | |
642 | } | |
643 | ||
644 | dir_no(ch) | |
645 | char ch; | |
646 | { | |
647 | int dir; | |
648 | ||
649 | switch (ch) { | |
650 | case 'w': dir = 0; break; | |
651 | case 'e': dir = 1; break; | |
652 | case 'd': dir = 2; break; | |
653 | case 'c': dir = 3; break; | |
654 | case 'x': dir = 4; break; | |
655 | case 'z': dir = 5; break; | |
656 | case 'a': dir = 6; break; | |
657 | case 'q': dir = 7; break; | |
658 | default: | |
659 | fprintf(stderr, "bad character in dir_no\n"); | |
660 | break; | |
661 | } | |
662 | return (dir); | |
663 | } |