int main(int ac, char *av[]) { int f_usage = 0, f_list = 0, f_showscore = 0; int f_printpath = 0; const char *file = NULL; char *name, *ptr, *seed; struct sigaction sa; gid_t gid; #ifdef BSD struct itimerval itv; #endif open_score_file(); /* revoke privs */ gid = getgid(); setresgid(gid, gid, gid); start_time = time(0); makenoise = 1; seed = NULL; name = *av++; while (*av) { #ifndef SAVEDASH if (**av == '-') ++*av; else break; #endif ptr = *av++; while (*ptr) { switch (*ptr) { case '?': case 'u': f_usage++; break; case 'l': f_list++; break; case 's': case 't': f_showscore++; break; case 'p': f_printpath++; break; case 'q': makenoise = 0; break; case 'r': seed = *av; av++; break; case 'f': case 'g': file = *av; av++; break; default: warnx("unknown option '%c'", *ptr); f_usage++; break; } ptr++; } } if (seed != NULL) srandom(atol(seed)); else srandomdev(); if (f_usage) fprintf(stderr, "usage: %s [-lpqstu?] [-f game] [-g game] [-r seed]\n", name); if (f_showscore) log_score(1); if (f_list) list_games(); if (f_printpath) { size_t len; char buf[256]; strlcpy(buf, _PATH_GAMES, sizeof buf); len = strlen(buf); if (len != 0 && buf[len - 1] == '/') buf[len - 1] = '\0'; puts(buf); } if (f_usage || f_showscore || f_list || f_printpath) exit(0); if (file == NULL) file = default_game(); else file = okay_game(file); if (file == NULL || read_file(file) < 0) exit(1); setup_screen(sp); addplane(); signal(SIGINT, quit); signal(SIGQUIT, quit); #ifdef BSD signal(SIGTSTP, SIG_IGN); signal(SIGSTOP, SIG_IGN); #endif signal(SIGHUP, log_score_quit); signal(SIGTERM, log_score_quit); tcgetattr(fileno(stdin), &tty_start); tty_new = tty_start; tty_new.c_lflag &= ~(ICANON|ECHO); tty_new.c_iflag |= ICRNL; tty_new.c_cc[VMIN] = 1; tty_new.c_cc[VTIME] = 0; tcsetattr(fileno(stdin), TCSADRAIN, &tty_new); memset(&sa, 0, sizeof sa); sa.sa_handler = update; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGALRM); sigaddset(&sa.sa_mask, SIGINT); sa.sa_flags = 0; sigaction(SIGALRM, &sa, (struct sigaction *)0); #ifdef BSD itv.it_value.tv_sec = 0; itv.it_value.tv_usec = 1; itv.it_interval.tv_sec = sp->update_secs; itv.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); #endif #ifdef SYSV alarm(sp->update_secs); #endif for (;;) { if (getcommand() != 1) planewin(); else { #ifdef BSD itv.it_value.tv_sec = 0; itv.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); #endif #ifdef SYSV alarm(0); #endif update(0); #ifdef BSD itv.it_value.tv_sec = sp->update_secs; itv.it_value.tv_usec = 0; itv.it_interval.tv_sec = sp->update_secs; itv.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); #endif #ifdef SYSV alarm(sp->update_secs); #endif } } }
void update(int dummy) { int i, dir_diff, unclean; PLANE *pp, *p1, *p2; clck++; erase_all(); /* put some planes in the air */ do { unclean = 0; for (pp = ground.head; pp != NULL; pp = pp->next) { if (pp->new_altitude > 0) { delete(&ground, pp); append(&air, pp); unclean = 1; break; } } } while (unclean); /* do altitude change and basic movement */ for (pp = air.head; pp != NULL; pp = pp->next) { /* type 0 only move every other turn */ if (pp->plane_type == 0 && clck & 1) continue; pp->fuel--; if (pp->fuel < 0) loser(pp, "ran out of fuel."); pp->altitude += SGN(pp->new_altitude - pp->altitude); if (!pp->delayd) { dir_diff = pp->new_dir - pp->dir; /* * Allow for circle commands */ if (pp->new_dir >= 0 && pp->new_dir < MAXDIR) { if (dir_diff > MAXDIR/2) dir_diff -= MAXDIR; else if (dir_diff < -(MAXDIR/2)) dir_diff += MAXDIR; } if (dir_diff > 2) dir_diff = 2; else if (dir_diff < -2) dir_diff = -2; pp->dir += dir_diff; if (pp->dir >= MAXDIR) pp->dir -= MAXDIR; else if (pp->dir < 0) pp->dir += MAXDIR; } pp->xpos += displacement[pp->dir].dx; pp->ypos += displacement[pp->dir].dy; if (pp->delayd && pp->xpos == sp->beacon[pp->delayd_no].x && pp->ypos == sp->beacon[pp->delayd_no].y) { pp->delayd = 0; if (pp->status == S_UNMARKED) pp->status = S_MARKED; } switch (pp->dest_type) { case T_AIRPORT: if (pp->xpos == sp->airport[pp->dest_no].x && pp->ypos == sp->airport[pp->dest_no].y && pp->altitude == 0) { if (pp->dir != sp->airport[pp->dest_no].dir) loser(pp, "landed in the wrong direction."); else { pp->status = S_GONE; continue; } } break; case T_EXIT: if (pp->xpos == sp->exit[pp->dest_no].x && pp->ypos == sp->exit[pp->dest_no].y) { if (pp->altitude != 9) loser(pp, "exited at the wrong altitude."); else { pp->status = S_GONE; continue; } } break; default: loser(pp, "has a bizarre destination, get help!"); } if (pp->altitude > 9) /* "this is impossible" */ loser(pp, "exceeded flight ceiling."); if (pp->altitude <= 0) { for (i = 0; i < sp->num_airports; i++) if (pp->xpos == sp->airport[i].x && pp->ypos == sp->airport[i].y) { if (pp->dest_type == T_AIRPORT) loser(pp, "landed at the wrong airport."); else loser(pp, "landed instead of exited."); } loser(pp, "crashed on the ground."); } if (pp->xpos < 1 || pp->xpos >= sp->width - 1 || pp->ypos < 1 || pp->ypos >= sp->height - 1) { for (i = 0; i < sp->num_exits; i++) if (pp->xpos == sp->exit[i].x && pp->ypos == sp->exit[i].y) { if (pp->dest_type == T_EXIT) loser(pp, "exited via the wrong exit."); else loser(pp, "exited instead of landed."); } loser(pp, "illegally left the flight arena."); } } /* * Traverse the list once, deleting the planes that are gone. */ for (pp = air.head; pp != NULL; pp = p2) { p2 = pp->next; if (pp->status == S_GONE) { safe_planes++; delete(&air, pp); } } draw_all(); for (p1 = air.head; p1 != NULL; p1 = p1->next) for (p2 = p1->next; p2 != NULL; p2 = p2->next) if (too_close(p1, p2, 1)) { static char buf[80]; (void)snprintf(buf, sizeof buf, "collided with plane '%c'.", name(p2)); loser(p1, buf); } /* * Check every other update. Actually, only add on even updates. * Otherwise, prop jobs show up *on* entrance. Remember that * we don't update props on odd updates. */ if ((atcrandom() % sp->newplane_time) == 0) addplane(); }
int main(int argc __unused, char *argv[]) { int seed = 0; int f_usage = 0, f_list = 0, f_showscore = 0; int f_printpath = 0; const char *file = NULL; char *p_name, *ptr; struct itimerval itv; /* Open the score file then revoke setgid privileges */ open_score_file(); setregid(getgid(), getgid()); start_time = time(0); p_name = *argv++; while (*argv) { #ifndef SAVEDASH if (**argv == '-') ++*argv; else break; #endif ptr = *argv++; while (*ptr) { switch (*ptr) { case '?': case 'u': f_usage++; break; case 'l': f_list++; break; case 's': case 't': f_showscore++; break; case 'p': f_printpath++; break; case 'r': srandom(atoi(*argv)); seed = 1; argv++; break; case 'f': case 'g': file = *argv; argv++; break; default: fprintf(stderr, "Unknown option '%c'\n", *ptr); f_usage++; break; } ptr++; } } if (!seed) srandomdev(); if (f_usage) fprintf(stderr, "Usage: %s -[u?lstp] [-[gf] game_name] [-r random seed]\n", p_name); if (f_showscore) log_score(1); if (f_list) list_games(); if (f_printpath) { char buf[100]; strcpy(buf, _PATH_GAMES); buf[strlen(buf) - 1] = '\0'; puts(buf); } if (f_usage || f_showscore || f_list || f_printpath) exit(0); if (file == NULL) file = default_game(); else file = okay_game(file); if (file == NULL || read_file(file) < 0) exit(1); init_gr(); setup_screen(sp); addplane(); signal(SIGINT, (sig_t)quit); signal(SIGQUIT, (sig_t)quit); signal(SIGTSTP, SIG_IGN); signal(SIGSTOP, SIG_IGN); signal(SIGHUP, (sig_t)log_score); signal(SIGTERM, (sig_t)log_score); tcgetattr(fileno(stdin), &tty_start); bcopy(&tty_start, &tty_new, sizeof(tty_new)); tty_new.c_lflag &= ~(ICANON|ECHO); tty_new.c_cc[VMIN] = 1; tty_new.c_cc[VTIME] = 0; tcsetattr(fileno(stdin), TCSANOW, &tty_new); signal(SIGALRM, (sig_t)update); itv.it_value.tv_sec = 0; itv.it_value.tv_usec = 1; itv.it_interval.tv_sec = sp->update_secs; itv.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); for (;;) { if (getcommand() != 1) planewin(); else { itv.it_value.tv_sec = 0; itv.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); update(); itv.it_value.tv_sec = sp->update_secs; itv.it_value.tv_usec = 0; itv.it_interval.tv_sec = sp->update_secs; itv.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); } } }