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