Annotation of researchv10no/games/atc/atc.c, revision 1.1.1.1

1.1       root        1: /* atc: simulate an air traffic controller at work */
                      2: 
                      3: #define NRAND 1
                      4: #define die nrand
                      5: 
                      6: #include <stdio.h>
                      7: #include <sys/ttyio.h>
                      8: #include <sys/param.h>
                      9: #include <sys/timeb.h>
                     10: #include <ctype.h>
                     11: #include <signal.h>
                     12: #include <pwd.h>
                     13: #include "ahdr.h"
                     14: 
                     15: #define SYNTAX "Usage: atc [-s=<seed>] [-a=<airspace>] [-t=<time>]\n"
                     16: 
                     17: /* size of terminal capability buffer */
                     18: #define TCSIZE 1024
                     19: 
                     20: int cmdx; /* command located using same cursor positioning as screen */
                     21: int cmdy; /* usually will be at 24 lines down */
                     22: 
                     23: char screen[MAXWIDTH][MAXHEIGHT]; /* contents of screen when no planes */
                     24: 
                     25: char *flowfile = 0;             /* no default flow patterns */
                     26: char *airfile = AIRFILE;
                     27: char *airspace = {"Apple1"};    /* default airspace is as on Apple */
                     28: char *protofile = 0;            /* no default protocol file */
                     29: FILE *proto;                    /* stays open all the time if protocol */
                     30: char *moviefile = 0;            /* if in movie mode, here's the file */
                     31: FILE *movie;                    /* and the file descriptor */
                     32: int nextmovie;                  /* next time for a moviefile command */
                     33: char *mcommand;                 /* next movie command */
                     34: int width,height; /* these values set in the airspace file */
                     35: char *bigname = 0;              /* megastatistics file */
                     36: FILE *bigstatsfile;             /* megastatistics stream */
                     37: 
                     38: struct flow fpath[MAXPATHS];
                     39: int maxflow;
                     40: int npaths;
                     41: 
                     42: int nentry = 0; /* number of entries into the board */
                     43: struct pstruct entry[EMAX];
                     44: 
                     45: int nairport = 0;
                     46: struct pstruct airport[AMAX];
                     47: 
                     48: int nnavaid = 0;
                     49: struct pstruct navaid[NMAX];
                     50: 
                     51: int nplanes = PMAX;
                     52: struct astruct plane[PMAX];
                     53: 
                     54: int initseed,seed,game_time,initgame_time,last_update;
                     55: time_t start_time;      /* real time in seconds that game started */
                     56: 
                     57: time_t get_time();
                     58: struct passwd *getpwuid();
                     59: FILE *popen();
                     60: 
                     61: #define BUFSIZE 80      /* buffer for message */
                     62: 
                     63: int remain;
                     64: 
                     65: int bound = 0;          /* number of boundary errors */
                     66: int system = 0;         /* system errors */
                     67: int crash = 0;          /* crashed - out of fuel */
                     68: int fuel = 0;           /* out of fuel on runway - tow truck */
                     69: int goaround = 0;       /* missed an approach */
                     70: int icmds = 0;          /* number of cmds issued (including deferred) */
                     71: int cmds = 0;           /* number of cmds actually executed */
                     72: 
                     73: int fuelused = 0;
                     74: 
                     75: int inaptot=0,outaptot=0;   /* denominators for random entries/exits */
                     76: int inawtot=0,outawtot=0;   /* for airports and airways */
                     77: 
                     78: char tcbuf[TCSIZE];
                     79: char cmbuf[100];       /* buffer for cursor motion strings */
                     80: char clbuf[100];       /* clear screen sequence */
                     81: 
                     82: int rubout = 0;
                     83: 
                     84: catchint(n)
                     85:        int n;
                     86: {
                     87:        rubout = 1;
                     88:        signal (n, catchint);
                     89: }
                     90: 
                     91: struct sgttyb tty_setting;
                     92: short tty_flags;
                     93: 
                     94: main(argc,argv)
                     95: int argc;
                     96: char **argv;
                     97: {       register char *arg;
                     98: 
                     99:        char *ttype;
                    100:        char *getenv();
                    101: 
                    102:        ttype = getenv("TERM");
                    103:        if (ttype == NULL || *ttype == '\0' || tgetent (tcbuf, ttype) <= 0) {
                    104:                fprintf (stderr, "cannot determine terminal type\n");
                    105:                exit (1);
                    106:        }
                    107: 
                    108:        /* get cursor motion and clear screen code into cmbuf and clbuf */
                    109:        {
                    110:                char *p;
                    111:                p = cmbuf;
                    112:                tgetstr ("cm", &p);
                    113:                p = clbuf;
                    114:                tgetstr ("cl", &p);
                    115:        }
                    116: 
                    117:        ioctl(0, TIOCGETP, &tty_setting);
                    118:        tty_flags = tty_setting.sg_flags;
                    119:        seed = 0;
                    120:        for (arg = *++argv; --argc; arg = *++argv) /* read args 1 at a time */
                    121:        {   if (arg[0] == '-')
                    122:                switch(arg[1])
                    123:                {   case 's':
                    124:                        if (arg[2] != '=') err(SYNTAX);
                    125:                        seed = atoi(&arg[3]);
                    126:                        break;
                    127:                    case 'S':
                    128:                        if (arg[2] != '=') err(SYNTAX);
                    129:                        bigname = &arg[3];
                    130:                        break;
                    131:                    case 'a':
                    132:                        if (arg[2] != '=') err(SYNTAX);
                    133:                        airspace = &arg[3];
                    134:                        break;
                    135:                    case 'u':
                    136:                        if (arg[2] != '=') err(SYNTAX);
                    137:                        airfile = &arg[3];
                    138:                        break;
                    139:                    case 't':
                    140:                        if (arg[2] != '=') err(SYNTAX);
                    141:                        initgame_time = game_time = 59 + 60 * atoi(&arg[3]);
                    142:                        break;
                    143:                    case 'f':
                    144:                        if (arg[2] != '=') err(SYNTAX);
                    145:                        flowfile = &arg[3];
                    146:                        break;
                    147:                    case 'p':   /* run a protocol */
                    148:                        if (arg[2] != '=') err(SYNTAX);
                    149:                        protofile = &arg[3];
                    150:                        break;
                    151:                    case 'm':   /* movie mode */
                    152:                        if (arg[2] != '=') err(SYNTAX);
                    153:                        moviefile = &arg[3];
                    154:                        break;
                    155:                    default :
                    156:                        err("Bad arg: %s\n",arg);
                    157:                }
                    158:        }
                    159:        init(); /* set up flight plans, initialize screen */
                    160:        while (command());      /* get commands from user */
                    161:        done(1);
                    162:        exit(0);
                    163: }
                    164: 
                    165: #define CMDSIZE 40
                    166: 
                    167: int inter;      /* non-zero if an alarm went off */
                    168: intp()  /* process interrupt from alarm */
                    169: {       inter++;
                    170: }
                    171: 
                    172: 
                    173: command()
                    174: {       time_t now;
                    175:        char cmd[CMDSIZE];
                    176:        char *c,utype,*d;
                    177:        int i,j;
                    178: 
                    179:        for (utype = i = *(c=cmd) = 0; utype != RETURN; )
                    180:        {
                    181:                if (moviefile) game_time--;     /* 1 sec at a time? */
                    182:                else
                    183:                {       now = get_time();
                    184:                        game_time = initgame_time - (now - start_time);
                    185:                }
                    186:                if (remain == 0) return(0);
                    187:                if (game_time < 0)
                    188:                {       report(OUTOFTIME,0,0);
                    189:                        return(0);
                    190:                }
                    191:                if (i == 0)     /* preserve partial command */
                    192:                {       cursor(cmdx,cmdy);
                    193:                        printf("<%.2d> COMMAND:                  ",game_time/60);
                    194:                }
                    195:                if (last_update - game_time >= UPDATE)
                    196:                {       update();
                    197:                        if (c != cmd) {BEEP;} /* cmd may be obsolete */
                    198:                }
                    199:                while (moviefile && game_time <= nextmovie)
                    200:                {       if (bigname) pcmd(bigstatsfile,mcommand);
                    201:                        if (protofile) pcmd(proto,mcommand);
                    202:                        i = parse(mcommand);
                    203:                        if (!i) return i;
                    204:                        getmcmd();
                    205:                }
                    206:                if (moviefile) continue;        /* no longer accept inputs */
                    207:                cursor(cmdx+7,cmdy);
                    208:                for (j=0; j<i; j++) putchar(cmd[j]);
                    209:                signal(SIGALRM,intp);/* catch the alarm if it goes off */
                    210:                inter = 0;      /* set to >0 if the alarm goes off */
                    211:                if (rubout) return 0;   /* user really wants to quit */
                    212:                alarm(TIMEOUT); /* read for TIMEOUT sec unless he types */
                    213:                utype = getchar() & 0177;
                    214:                alarm(0);
                    215:                if (inter > 0) continue; /* didn't type anything */
                    216:                delmsg(cmdx,cmdy-1);    /* erase previous echo if he types */
                    217:                cursor(cmdx+7,cmdy);
                    218:                if (i != 2 || (*(c-1) != '*' && *(c-1) != ':'))
                    219:                 if (*cmd != '!' || i == 0) /* don't shift CDL filename */
                    220:                  if (*cmd != '@'|| i == 0) /* don't shift location descrip */
                    221:                      if (utype >= 'a' && utype <= 'z')
                    222:                        utype = utype - 'a' + 'A';
                    223:                if (utype == INSMODE) utype = RETURN;
                    224:                if ((*c++ = utype) != RETURN)
                    225:                {       if (++i >= CMDSIZE) c--;
                    226:                        else
                    227:                        switch(utype)   /* echo something reasonable */
                    228:                        { 
                    229: #ifdef ANNARBOR
                    230:                            case MIPAGE:/* check cursor controls */
                    231:                                putchar(*--c = 'N');
                    232:                                putchar(*++c = 'W');
                    233:                                c++; i++;
                    234:                                break;
                    235:                            case HOME:
                    236:                                putchar(*--c = 'N');
                    237:                                c++;
                    238:                                break;
                    239:                            case PLPAGE:
                    240:                                putchar(*--c = 'N');
                    241:                                putchar(*++c = 'E');
                    242:                                c++; i++;
                    243:                                break;
                    244:                            case MISRCH:
                    245:                                putchar(*--c = 'W');
                    246:                                c++;
                    247:                                break;
                    248:                            case UPARROW:
                    249:                                putchar(*--c = '0');
                    250:                                c++;
                    251:                                break;
                    252:                            case PLSRCH:
                    253:                                putchar(*--c = 'E');
                    254:                                c++;
                    255:                                break;
                    256:                            case LEFTARROW:
                    257:                                putchar(*--c = 'S');
                    258:                                putchar(*++c = 'W');
                    259:                                c++; i++;
                    260:                                break;
                    261:                            case DOWNARROW:
                    262:                                putchar(*--c = 'S');
                    263:                                c++;
                    264:                                break;
                    265:                            case RIGHTARROW:
                    266:                                putchar(*--c = 'S');
                    267:                                putchar(*++c = 'E');
                    268:                                c++; i++;
                    269:                                break;
                    270:                            case ':':   /* like a * */
                    271:                                putchar('*');
                    272:                                break;
                    273: #endif
                    274:                            case BS:
                    275:                                if (i<=0) break;
                    276:                                if (i==1) { i = 0; break; }
                    277:                                putchar(BS);
                    278:                                c--; c--; i--; i--;
                    279:                                break;
                    280:                            default: putchar(utype); break;
                    281:                        }
                    282:                }
                    283:        }
                    284:        *c = 0;
                    285:        if (bigname) pcmd(bigstatsfile,cmd);
                    286:        if (protofile) pcmd(proto,cmd);
                    287:        return(parse(cmd));
                    288: }
                    289: 
                    290: pcmd(file,cmd)  /* protocol a command */
                    291: FILE *file;
                    292: char *cmd;
                    293: {       register char *s;
                    294: 
                    295:        if (file == proto)
                    296:             fprintf(file,"%5d: ",game_time);
                    297:        else fprintf(file,"%5d: ",initgame_time - game_time);
                    298:        for (s = cmd; *s && *s != RETURN; s++) fputc(*s,file);
                    299:        fputc('\n',file);
                    300: }
                    301: 
                    302: parse(cmd)      /* command is terminated by RETURN */
                    303: register char *cmd;
                    304: {       time_t now;
                    305:        register int i;
                    306:        register struct astruct *pl;
                    307:        char dest;
                    308:        char *fullcmd;
                    309:        char ubuf[10];
                    310: 
                    311:        fullcmd = cmd;
                    312:        switch(*cmd)        /* parse 1 letter at a time */
                    313:        {   case ' ':  /* time advance */
                    314:                sprintf (ubuf, "%d", UPDATE);
                    315:                echo("%s\" - ROGER",ubuf);
                    316:                now = get_time();
                    317:                start_time = last_update - UPDATE - 1 - initgame_time + now;
                    318:                break;
                    319:            case '$':
                    320:                return(0);
                    321:            case '!':   /* read a file of clearance directive lists */
                    322:                readcdl(++cmd);
                    323:                break;
                    324:            case '@':   /* get a monitoring command */
                    325:                getmon(++cmd);
                    326:                break;
                    327:            default:    /* should be airplane id */
                    328:                /* ASSUMPTION HERE: aircraft are A-Z */
                    329:                if (*cmd < 'A' || *cmd > 'Z')
                    330:                {       echo("%s - UNABLE",fullcmd);
                    331:                        BEEP;
                    332:                        break;
                    333:                }
                    334:                for (pl = &plane[i=0]; i < nplanes; i++,pl++)
                    335:                        if (pl->a_id == *cmd) break;
                    336:                if (i == nplanes)
                    337:                {       echo("%s - NOT ACTIVE",fullcmd);
                    338:                        BEEP;
                    339:                        break;
                    340:                }
                    341: 
                    342:                if (cmd[1] == '?')      /* o.k. to cancel plans */
                    343:                {       if (pl->a_active != ACTIVE &&
                    344:                            pl->a_active != WAITING)
                    345:                        {       echo("%s - NOT ACTIVE",fullcmd);
                    346:                                BEEP;
                    347:                                break;
                    348:                        }
                    349:                }
                    350:                else if (cmd[1] == RETURN)     /* info request only */
                    351:                {       if (pl->a_active != ACTIVE &&
                    352:                            pl->a_active != APPROACHING &&
                    353:                            pl->a_active != WAITING)
                    354:                        {       echo("%s - NOT ACTIVE",fullcmd);
                    355:                                BEEP;
                    356:                                break;
                    357:                        }
                    358:                }
                    359:                else
                    360:                {       if (pl->a_active != ACTIVE && pl->a_active != WAITING)
                    361:                        {       echo("%s - NOT ACTIVE",fullcmd);
                    362:                                BEEP;
                    363:                                break;
                    364:                        }
                    365:                        if (pl->a_active==ACTIVE && pl->a_nextz == 0 && cmd[1]!=RETURN)
                    366:                        {       echo("%s - LANDING",fullcmd);
                    367:                                BEEP;
                    368:                                break;
                    369:                        }
                    370:                }
                    371:                switch(*++cmd)  /* parse second char */
                    372:                {   case RETURN:  /* info request */
                    373:                        strip(pl,cmdy+1,VERBOSE);
                    374:                        break;
                    375:                    case 'A':   /* change altitude */
                    376:                        if (*++cmd < '0' || *cmd > '5')
                    377:                        {       echo("%s - UNABLE",fullcmd);
                    378:                                BEEP;
                    379:                        }
                    380:                        else
                    381:                        {       pl->a_nextz = *cmd - '0';
                    382:                                echo("%s - ROGER",fullcmd);
                    383:                                cmds++;
                    384:                                icmds++;
                    385:                        }
                    386:                        break;
                    387:                    case 'H':   /* hold at beacon */
                    388:                        pl->a_hold = 1;
                    389:                        pl->a_clear = 0;
                    390:                        echo("%s - ROGER",fullcmd);
                    391:                        cmds++;
                    392:                        icmds++;
                    393:                        break;
                    394:                    case 'L':   /* left turn */
                    395:                        rdturn(pl,'L',++cmd,fullcmd);
                    396:                        break;
                    397:                    case 'R':   /* right turn */
                    398:                        rdturn(pl,'R',++cmd,fullcmd);
                    399:                        break;
                    400:                    case 'T':   /* shortest turn */
                    401:                        rdturn(pl,'T',++cmd,fullcmd);
                    402:                        break;
                    403:                    case '*':   /* clearance at navaid */
                    404:                    case ':':
                    405:                        dest = *++cmd;
                    406:                        for (i=0; i<nentry; i++) /* vector to entry? */
                    407:                                if (dest == entry[i].p_sym) break;
                    408:                        if (pl->a_hold == 1) pl->a_hold = 0;
                    409:                        if (i<nentry)
                    410:                        {       echo("%s - ROGER",fullcmd);
                    411:                                pl->a_clear = dest;
                    412:                                cmds++;
                    413:                                icmds++;
                    414:                                break;
                    415:                        }
                    416:                        for (i=0; i<nairport; i++)
                    417:                                if (dest == airport[i].p_sym) break;
                    418:                        if (i<nairport)
                    419:                        {       echo("%s - ROGER",fullcmd);
                    420:                                pl->a_clear = dest;
                    421:                                cmds++;
                    422:                                icmds++;
                    423:                                break;
                    424:                        }
                    425:                        echo("%s - UNABLE",fullcmd);
                    426:                        BEEP;
                    427:                        break;
                    428:                    case '?':   /* delete delayed commands */
                    429:                        ddelay(pl);
                    430:                        echo("%s - ROGER",fullcmd);
                    431:                        cmds++;
                    432:                        icmds++;
                    433:                        break;
                    434:                    default:    /* airport id? - maybe cursor motions? */
                    435:                        echo("%s - UNABLE",fullcmd);
                    436:                        BEEP;
                    437:                        break;
                    438:                }
                    439:        }
                    440:        return(1);
                    441: }
                    442: 
                    443: getmon(cmd)     /* get monitor command from command line */
                    444: register char *cmd;
                    445: {       int x,y;
                    446:        register char *start;
                    447: 
                    448:        start = cmd;
                    449:        if (getloc(cmd,&x,&y) == 0)     /* where did you say? */
                    450:        {       echo("%s - BAD LOC SPEC",cmd);
                    451:                BEEP;
                    452:                return;
                    453:        }
                    454:        while (*cmd)    /* pick up each command that happens here */
                    455:        {       while (*cmd && *cmd != ',') cmd++;
                    456:                if (*cmd == 0) return; /* read last command */
                    457:                putlist(start,x,y,++cmd); /* put the next command on a list */
                    458:        }
                    459: }
                    460: 
                    461: ddelay(pl)      /* delete any delayed commands from this plane's list */
                    462: struct astruct *pl;
                    463: {       struct list *l,*next;
                    464: 
                    465:        if (pl->a_plan == 0) return;
                    466:        for (l = pl->a_plan; l; l = next)
                    467:        {       next = l->l_next;
                    468:                free(l);
                    469:        }
                    470:        pl->a_plan = 0;
                    471: }
                    472: 
                    473: putlist(start,x,y,cmd) /* put some commands on the list for a plane */
                    474: char *start;
                    475: int x,y;
                    476: char *cmd;
                    477: {       register struct list *l;
                    478:        register struct astruct *p;
                    479:        register char *c,*d;
                    480:        int i;
                    481: 
                    482:        d = cmd;
                    483:        for (i = 0; cmd[i] != ',' && cmd[i] != 0 && cmd[i] != RETURN; i++)
                    484:          if (i != 2 || (cmd[i-1] != '*' && cmd[i-1] != ':'))
                    485:            if (cmd[i] >= 'a' && cmd[i] <= 'z') cmd[i] += 'A' - 'a';
                    486:        for (p = &plane[i = 0]; i < nplanes; i++,p++)
                    487:                if (p->a_id == *cmd) break;
                    488:        if (i == nplanes)
                    489:        {       echo("BAD PLANE SPEC: %s",cmd);
                    490:                BEEP;
                    491:                return;
                    492:        }
                    493:        l = p->a_plan;  /* go to the CDL for this plane */
                    494:        if (p->a_plan == 0)
                    495:                l = p->a_plan = (struct list *) malloc(sizeof (struct list));
                    496:        else
                    497:        {       for (l = p->a_plan; l->l_next != 0; l = l->l_next); /* eol */
                    498:                l->l_next = (struct list *) malloc(sizeof (struct list));
                    499:                l = l->l_next;
                    500:        }
                    501:        l->l_next = 0;
                    502:        l->l_x = x;
                    503:        l->l_y = y;
                    504:        c = l->l_cmd;
                    505:        while (*cmd != ',' && *cmd != 0 && *cmd != RETURN)
                    506:                *c++ = *cmd++;
                    507:        *c++ = RETURN;
                    508:        *c = 0;
                    509:        for (c = d; *c; c++) if (*c == RETURN) *c = 0; /* return damages dspla*/
                    510:        echo("%s - WILCO",d);
                    511:        icmds++;
                    512:        /* copy the verbatim direction used by the guy */
                    513:        for (c = start, d = l->l_loc; *c != ','; *d++ = *c++);
                    514:        *d = 0;
                    515: }
                    516: 
                    517: 
                    518: getloc(cmd,px,py)       /* get location description from a monitor command */
                    519: char *cmd;
                    520: int *px,*py;
                    521: {       register char l,*m;     /* location */
                    522:        register int i;
                    523:        register struct pstruct *p;
                    524:        int dx,dy;
                    525:        char buf[300];
                    526: 
                    527:        l = *(m = cmd);
                    528:        p = 0;
                    529:        for (i = 0; i < nentry; i++)
                    530:                if (entry[i].p_sym == l) p = &entry[i];
                    531:        for (i = 0; i < nairport; i++)
                    532:                if (airport[i].p_sym == l) p = &airport[i];
                    533:        for (i = 0; i < nnavaid; i++)
                    534:                if (navaid[i].p_sym == l) p = &navaid[i];
                    535:        if (p == 0) return 0;
                    536:        *px = p->p_x;
                    537:        *py = p->p_y;
                    538:        m++;
                    539:        while (*m != ',')     /* read through the other directions */
                    540:        {       dx = dy = 0;
                    541:                switch(*m)      /* NSEW */
                    542:                {   case 'n': dy = -1; break;
                    543:                    case 's': dy =  1; break;
                    544:                    case 'e': dx =  1; break;
                    545:                    case 'w': dx = -1; break;
                    546:                    default:
                    547:                        sprintf(buf,"Got %c instead of n,s,e,w",*m);
                    548:                        msg(cmdx,cmdy+3,buf);
                    549:                        return 0;
                    550:                }
                    551:                if      (*++m == 'w') { dx = -1; m++;}  /* NW or SW */
                    552:                else if (*m   == 'e') { dx =  1; m++;}  /* NE or SE */
                    553:                if (*m < '0' || *m > '9')
                    554:                {       sprintf(buf,"Got %c instead of digit",*m);
                    555:                        msg(cmdx,cmdy+3,buf);
                    556:                        return 0;
                    557:                }
                    558:                for (i = 0; *m >= '0' && *m <= '9'; m++)
                    559:                        i = 10 * i + *m - '0';
                    560:                *px += i * dx;
                    561:                *py += i * dy;
                    562:        }
                    563:        return 1;
                    564: }
                    565: 
                    566: readcdl(fname)  /* fname points at CDL filename, \r-terminated */
                    567: char *fname;
                    568: {       FILE *cdlfile;
                    569:        char *p;
                    570: 
                    571:        while (*fname == ' ') fname++;  /* skip initial blanks */
                    572:        for (p = fname; *p && *p != RETURN; p++); /* remove newline */
                    573:        *p = 0;
                    574:        if ((cdlfile = fopen(fname,"r")) == NULL)
                    575:        {       echo("Cannot open %s",fname);
                    576:                return;
                    577:        }
                    578:        echo("Reading CDL file...",0);
                    579:        fclose(cdlfile);
                    580: }
                    581: 
                    582: 
                    583: rdturn(pl,dir,cmd,fullcmd)
                    584: struct astruct *pl;
                    585: char dir;
                    586: char *cmd,*fullcmd;
                    587: {       int i,ok,newx,newy,turncount;
                    588: 
                    589:        if (pl->a_nextz == 0)
                    590:        {       echo("%s - WRONG WAY",fullcmd);
                    591:                BEEP;
                    592:                return;
                    593:        }
                    594:        ok = 1; /* check whether this is a legal command */
                    595:        newx = newy = 0;
                    596:        for (i=0; i<2; i++)     /* look at next 2 chars */
                    597:        switch(cmd[i])
                    598:        {   case RETURN:
                    599:                if (i == 0)
                    600:                {       echo("%s - WHICH WAY?",fullcmd);
                    601:                        BEEP;
                    602:                        return;
                    603:                }
                    604:                break;
                    605:            case '0':
                    606:                if (i == 1)     /* can't be second char */
                    607:                {       ok = 0;
                    608:                        break;
                    609:                }
                    610:                pl->a_dxnew = 0;
                    611:                pl->a_dynew = 0;
                    612:                pl->a_turn = 0;
                    613:                pl->a_clear = 0;
                    614:                pl->a_hold = 0;
                    615:                echo("%s - ROGER",fullcmd);
                    616:                cmds++;
                    617:                icmds++;
                    618:                return;
                    619:            case 'N':
                    620:                newy = -1;
                    621:                break;
                    622:            case 'S':
                    623:                newy = 1;
                    624:                break;
                    625:            case 'E':
                    626:                newx = 1;
                    627:                break;
                    628:            case 'W':
                    629:                newx = -1;
                    630:                break;
                    631:            default:    /* numbers (e.g.) no longer acceptable */
                    632:                ok = 0;
                    633:                break;
                    634:        }
                    635:        if (ok)
                    636:        {       echo("%s - ROGER",fullcmd);
                    637:                cmds++;
                    638:                icmds++;
                    639:                pl->a_turn = dir;       /* will replace 'T' with 'L' or 'R' */
                    640:                pl->a_dxnew = newx; pl->a_dynew = newy;
                    641:                pl->a_hold = pl->a_clear = 0;
                    642:                if (dir == 'T')
                    643:                {       newx = pl->a_dx; /* start with this direction */
                    644:                        newy = pl->a_dy; /* and turn until done */
                    645:                        for (turncount = 1; turncount < 9; turncount++)
                    646:                            if (turn(&newx,&newy,'L',pl->a_dxnew,pl->a_dynew))
                    647:                                break;
                    648:                        if (turncount <= 4) pl->a_turn = 'L';
                    649:                        else pl->a_turn = 'R';
                    650:                }
                    651:        }
                    652:        else
                    653:        {       echo("%s - UNABLE",fullcmd);
                    654:                BEEP;
                    655:        }
                    656: }
                    657: 
                    658: echo(format,cmd)
                    659: char *format,*cmd;
                    660: {       char *c;
                    661:        char mbuf[BUFSIZE];
                    662: 
                    663:        for (c=cmd; *c; c++) if (*c == RETURN) *c = 0;
                    664:        sprintf(mbuf,format,cmd);
                    665:        msg(cmdx,cmdy-1,mbuf);
                    666: }
                    667: 
                    668: int parity = 0; /* props move every other update */
                    669: 
                    670: update()
                    671: {       parity = 1 - parity;
                    672:        last_update -= UPDATE;  /* must average out to every UPDATE secs */
                    673:        moveplanes();
                    674:        printplans();
                    675:        if (bigname) activity();
                    676: }
                    677: 
                    678: activity()      /* number of active planes to megastats file */
                    679: {       register int i,active,waiting,approaching,planned;
                    680:        struct astruct *p;
                    681: 
                    682:        for (i=active=waiting=approaching=planned=0; i < nplanes; i++)
                    683:        {       p = &plane[i];
                    684:                switch(p->a_active)
                    685:                {   case ACTIVE:
                    686:                        active++;
                    687:                        break;
                    688:                    case WAITING:
                    689:                        waiting++;
                    690:                        break;
                    691:                    case APPROACHING:
                    692:                        approaching++;
                    693:                        break;
                    694:                }
                    695:                if (p->a_plan && p->a_active != DONE) planned++;
                    696:        }
                    697:        fprintf(bigstatsfile,"%5d: %d active, %d approaching, %d waiting.  ",
                    698:                initgame_time - game_time, active,approaching,waiting);
                    699:        fprintf(bigstatsfile,"%d planned.\n",planned);
                    700:        for (i = 0; i < nplanes; i++)
                    701:        {       int a;
                    702: 
                    703:                p = &plane[i];
                    704:                a = p->a_active;
                    705:                if (a == ACTIVE || a == APPROACHING || a == WAITING)
                    706:                {       p->a_load += active;
                    707:                        p->a_ticks++;
                    708:                        p->a_planned += planned;
                    709:                }
                    710:                if (a == APPROACHING || a == WAITING)
                    711:                {       p->a_aprev += active;
                    712:                        p->a_prev++;
                    713:                        p->a_pprev += planned;
                    714:                        p->a_pplanned = (p->a_plan? YES : NO);
                    715:                }
                    716:        }
                    717: }
                    718: 
                    719: moveplanes()
                    720: {       register struct astruct *pl;
                    721:        register int i,j;
                    722:        register int nextx,nexty;
                    723:        int ax,ay,oldx,oldy;
                    724:        struct pstruct *dst;
                    725: 
                    726:        for (pl = &plane[i = 0]; i < PMAX; i++, pl++)
                    727:        {       if (parity && pl->a_type == PROP)
                    728:                {       pl->a_lastz = pl->a_z;
                    729:                        if (pl->a_active == LANDING) pl->a_active = DONE;
                    730:                        continue;
                    731:                }
                    732:                switch(pl->a_active)
                    733:                {   case INACTIVE:
                    734:                        if (initgame_time - game_time + FPTHRESH>= pl->a_stime
                    735:                            && !pl->a_sair)
                    736:                                pl->a_active = APPROACHING;
                    737: 
                    738:                    case APPROACHING:
                    739:                        if (initgame_time - game_time>= pl->a_stime)
                    740:                        {       pl->a_active = ACTIVE;
                    741:                                if (pl->a_sair) pl->a_active = WAITING;
                    742:                                nextx = pl->a_x;
                    743:                                nexty = pl->a_y;
                    744:                        }
                    745:                        break;
                    746: 
                    747:                    case LANDING: /* to allow for conflicts */
                    748:                        pl->a_active = DONE;
                    749:                        break;
                    750: 
                    751:                    case ACTIVE:
                    752:                        pl->a_dist++;   /* increment distance traveled */
                    753:                        nextx = pl->a_x + pl->a_dx;
                    754:                        nexty = pl->a_y + pl->a_dy;
                    755:                        if (nextx < 0 || nexty < 0 ||
                    756:                            nextx >= width || nexty >= height)
                    757:                        {       leavescreen(pl);
                    758:                                break;
                    759:                        }
                    760: 
                    761:                        /* turning? */
                    762:                        if (pl->a_turn)   /* turn 1 tick in right direction */
                    763:                            if (turn(&pl->a_dx,&pl->a_dy,
                    764:                                pl->a_turn,pl->a_dxnew,pl->a_dynew))
                    765:                                  pl->a_turn = pl->a_dxnew = pl->a_dynew = 0;
                    766: 
                    767: 
                    768:                        if (pl->a_dair) /* landing? */
                    769:                        {       dst = &airport[pl->a_dest];
                    770:                                ax = dst->p_x;
                    771:                                ay = dst->p_y;
                    772:                                if (ax == nextx && ay == nexty)
                    773:                                    if (pl->a_z == 0 &&
                    774:                                          pl->a_dx == dst->p_dx &&
                    775:                                          pl->a_dy == dst->p_dy)
                    776:                                    {   pl->a_active = LANDING;  /* landed */
                    777:                                        erase(pl->a_x,pl->a_y);
                    778:                                        pl->a_x = nextx;
                    779:                                        pl->a_y = nexty;
                    780:                                        remain--;
                    781:                                    }
                    782:                                    else if (pl->a_nextz == 0) /* flyby */
                    783:                                    {   pl->a_nextz = 1; /* down too late*/
                    784:                                        goaround++;
                    785:                                        report(GOAROUND,pl);
                    786:                                    }
                    787:                        }
                    788: 
                    789:                        /* changing altitude? */
                    790:                        if (pl->a_z > pl->a_nextz)
                    791:                                pl->a_lastz = pl->a_z--;
                    792:                        else if (pl->a_z < pl->a_nextz)
                    793:                                pl->a_lastz = pl->a_z++;
                    794:                        else pl->a_lastz = pl->a_z;
                    795: 
                    796:                        /* out of fuel? */
                    797:                        if (--pl->a_fuel <= 0)
                    798:                        {       crash++;
                    799:                                report(CRASH,pl);
                    800:                                pl->a_active = DONE;
                    801:                                remain--;
                    802:                                erase(pl->a_x,pl->a_y);
                    803:                        }
                    804:                        if (pl->a_type == JET) fuelused += 5;
                    805:                        else fuelused += 1;
                    806:                        break;
                    807: 
                    808:                    case WAITING:  /* waiting for takeoff */
                    809:                        if (--pl->a_fuel <= 0)  /* out of fuel on ground? */
                    810:                        {       fuel++;
                    811:                                if (bigname) freport(pl);
                    812:                                report(FUEL,pl);
                    813:                                pl->a_active = DONE;
                    814:                                remain--;
                    815:                        }
                    816:                        if (pl->a_nextz != 0)
                    817:                        {       pl->a_z++;      /* take off */
                    818:                                pl->a_active = ACTIVE;
                    819:                                pl->a_dist++;
                    820:                        }
                    821:                        nextx = pl->a_x + pl->a_dx;
                    822:                        nexty = pl->a_y + pl->a_dy;
                    823: 
                    824:                        /* turning? */
                    825:                        if (pl->a_turn)   /* turn 1 tick in right direction */
                    826:                            if (turn(&pl->a_dx,&pl->a_dy,
                    827:                                pl->a_turn,pl->a_dxnew,pl->a_dynew))
                    828:                                  pl->a_turn = pl->a_dxnew = pl->a_dynew = 0;
                    829: 
                    830:                        if (pl->a_type == JET) fuelused += 5;
                    831:                        else fuelused += 1;
                    832:                        break;
                    833: 
                    834:                    case DONE:  /* off the screen */
                    835:                        break;
                    836:                }
                    837:                if (pl->a_active != ACTIVE) continue;
                    838:                oldx = pl->a_x;
                    839:                oldy = pl->a_y;
                    840:                pl->a_x = nextx;
                    841:                pl->a_y = nexty;
                    842:                cursor(nextx,nexty);
                    843:                printf("%c%c",pl->a_id,(pl->a_z>9? '^' : pl->a_z+'0'));
                    844:                erase(oldx,oldy);
                    845:                if (pl->a_hold || pl->a_clear)
                    846:                        for (j = 0; j < nnavaid; j++)   /* at a navaid? */
                    847:                                if (screen[nextx][nexty] == navaid[j].p_sym)
                    848:                                {       donavaid(pl);   /* right navaid? */
                    849:                                        break;
                    850:                                }
                    851:        }
                    852:        conflict();
                    853:        delays();       /* execute any applicable delayed commands */
                    854: }
                    855: 
                    856: freport(pl)     /* report to big stats file about tow truck */
                    857: struct astruct *pl;
                    858: {
                    859:        fprintf(bigstatsfile,"%5d: %c out of fuel on runway.\n",
                    860:                initgame_time - game_time,pl->a_id);
                    861: }
                    862: 
                    863: delays()        /* execute any applicable delayed actions */
                    864: {       register struct astruct *p;
                    865:        register int i;
                    866:        register struct list *l,*last;
                    867: 
                    868:        /* for each plane, if it is active and if it has a command pending,
                    869:         * and if it is at the right place for the command, then execute it.
                    870:         */
                    871:        for (i = 0; i < PMAX; i++)
                    872:        {       p = &plane[i];
                    873:                if (p->a_active != ACTIVE) continue;
                    874:                if (p->a_plan == 0) continue;
                    875:                last = 0;
                    876:                for (l = p->a_plan; l; )
                    877:                {       if (p->a_x != l->l_x || p->a_y != l->l_y)
                    878:                        {
                    879:                                last = l;
                    880:                                l = l->l_next;
                    881:                        }
                    882:                        else    /* it matched */
                    883:                        {
                    884:                                parse(l->l_cmd); /* execute the command */
                    885: 
                    886:                                /* now delete the command from the list */
                    887:                                if (last == 0)  /* it was the first one */
                    888:                                {       p->a_plan = l->l_next;
                    889:                                        free(l);
                    890:                                        l = p->a_plan;
                    891:                                        /* last stays at 0 */
                    892:                                }
                    893:                                else
                    894:                                {       last->l_next = l->l_next;
                    895:                                        free(l);
                    896:                                        l = last->l_next;
                    897:                                        /* last stays where it was */
                    898:                                }
                    899:                        }
                    900:                }
                    901:        }
                    902: }
                    903: 
                    904: donavaid(pl)    /* take appropriate action at navaid */
                    905: struct astruct *pl; /* the plane has either been vectored or told to hold */
                    906: {       register struct pstruct *d;
                    907:        register int i;
                    908: 
                    909:        if (pl->a_hold)
                    910:        {       pl->a_hold = 2; /* will be holding now */
                    911:                pl->a_turn = 'L'; /* and turning continuously to the left */
                    912:                pl->a_dxnew = pl->a_dx; /* until it reaches this heading agn*/
                    913:                pl->a_dynew = pl->a_dy;
                    914:        }
                    915:        if (pl->a_clear)
                    916:        {       pl->a_turn = pl->a_dxnew = pl->a_dynew = pl->a_hold = 0;
                    917:                /* see what we're vectoring to */
                    918:                for (d = &entry[i=0]; i < nentry; i++,d++)
                    919:                        if (d->p_sym == pl->a_clear) break;
                    920:                if (i != nentry)        /* yes, it was a navaid */
                    921:                {       pl->a_dx = -d->p_dx;    /* opposite of entry heading*/
                    922:                        pl->a_dy = -d->p_dy;
                    923:                        pl->a_clear = 0;
                    924:                        return;
                    925:                }
                    926:                for (d = &airport[i=0]; i < nairport; i++,d++)
                    927:                        if (d->p_sym == pl->a_clear) break;
                    928:                if (i == nairport) return; /* program bug - cleared to ?? */
                    929:                pl->a_dx = d->p_dx; /* assume landing heading for airport */
                    930:                pl->a_dy = d->p_dy;
                    931:                pl->a_clear = 0;
                    932: 
                    933:                if (pl->a_hold == 1)
                    934:                        pl->a_hold = pl->a_dxnew = pl->a_dynew = 0;
                    935:                else if (pl->a_hold == 0)
                    936:                        pl->a_dxnew = pl->a_dynew = 0;
                    937:                return;
                    938:        }
                    939: }
                    940: 
                    941: turn(newx,newy,direc,dx,dy)     /* messy - enumeration of all cases */
                    942: int *newx,*newy;        /* returned values of new heading */
                    943: char direc;
                    944: int dx,dy;
                    945: {       int x,y;
                    946: 
                    947:        x = *newx;
                    948:        y = *newy;
                    949:        switch(direc)
                    950:        {   case 'L': /* cases would be more efficient, but this is clearer*/
                    951:                if (x== -1 && y== -1) {*newx= -1; *newy=  0; break;}
                    952:                if (x== -1 && y==  0) {*newx= -1; *newy=  1; break;}
                    953:                if (x== -1 && y==  1) {*newx=  0; *newy=  1; break;}
                    954:                if (x==  0 && y== -1) {*newx= -1; *newy= -1; break;}
                    955:                if (x==  0 && y==  1) {*newx=  1; *newy=  1; break;}
                    956:                if (x==  1 && y== -1) {*newx=  0; *newy= -1; break;}
                    957:                if (x==  1 && y==  0) {*newx=  1; *newy= -1; break;}
                    958:                if (x==  1 && y==  1) {*newx=  1; *newy=  0; break;}
                    959:                break;
                    960:            case 'R':
                    961:                if (x== -1 && y== -1) {*newx=  0; *newy= -1; break;}
                    962:                if (x== -1 && y==  0) {*newx= -1; *newy= -1; break;}
                    963:                if (x== -1 && y==  1) {*newx= -1; *newy=  0; break;}
                    964:                if (x==  0 && y== -1) {*newx=  1; *newy= -1; break;}
                    965:                if (x==  0 && y==  1) {*newx= -1; *newy=  1; break;}
                    966:                if (x==  1 && y== -1) {*newx=  1; *newy=  0; break;}
                    967:                if (x==  1 && y==  0) {*newx=  1; *newy=  1; break;}
                    968:                if (x==  1 && y==  1) {*newx=  0; *newy=  1; break;}
                    969:                break;
                    970:        }
                    971:        if (*newx == dx && *newy == dy) return(1);      /* finished turn */
                    972:        else return(0);
                    973: }
                    974: 
                    975: 
                    976: report(error,plane1,plane2)
                    977: int error;
                    978: struct astruct *plane1,*plane2;
                    979: {       char mbuf[BUFSIZE];
                    980:        int i;
                    981: 
                    982:        putchar(BELL);
                    983:        switch(error)
                    984:        {   case FUEL:
                    985:                sprintf(mbuf,"Tow truck called for %c (%c)",
                    986:                        plane1->a_id,airport[plane1->a_start].p_sym);
                    987:                break;
                    988:            case CRASH:
                    989:                sprintf(mbuf,"PLANE %c OUT OF GAS",plane1->a_id);
                    990:                break;
                    991:            case BOUND:
                    992:                sprintf(mbuf,"Boundary error - %c",plane1->a_id);
                    993:                break;
                    994:            case SYSTEM:
                    995:                sprintf(mbuf,"%c AND %c: SYSTEM ERROR",
                    996:                        plane1->a_id, plane2->a_id);
                    997:                break;
                    998:            case GOAROUND:
                    999:                sprintf(mbuf,"%c missed approach",plane1->a_id);
                   1000:                break;
                   1001:            case OUTOFTIME:
                   1002:                sprintf(mbuf,"Out of time: %d remain",remain);
                   1003:                break;
                   1004:        }
                   1005:        msg(cmdx,cmdy+2,mbuf);
                   1006: }
                   1007: 
                   1008: 
                   1009: 
                   1010: leavescreen(pl)
                   1011: struct astruct *pl;
                   1012: {       struct pstruct *e;
                   1013: 
                   1014:        pl->a_active = DONE;
                   1015:        pl->a_dist++;
                   1016:        erase(pl->a_x,pl->a_y);
                   1017:        remain--;
                   1018:        e = &entry[pl->a_dest];
                   1019:        if (pl->a_z == 5 && !pl->a_dair && /* leaving at non-airport, 5K' */
                   1020:            screen[pl->a_x][pl->a_y] == e->p_sym &&  /* right exit */
                   1021:            pl->a_dx == -e->p_dx && pl->a_dy == -e->p_dy && /* right direc */
                   1022:            pl->a_turn == 0)    /* and not turning */
                   1023:                return(0);
                   1024:        bound++;
                   1025:        if (bigname)
                   1026:        {       fprintf(bigstatsfile,"%5d: Boundary error - plane %c ",
                   1027:                        initgame_time - game_time,pl->a_id);
                   1028:                fprintf(bigstatsfile,"left at %d000' ",pl->a_z);
                   1029:                if (pl->a_nextz > pl->a_z)
                   1030:                   fprintf(bigstatsfile,"climbing to %d000'",pl->a_nextz);
                   1031:                if (pl->a_nextz < pl->a_z)
                   1032:                   fprintf(bigstatsfile,"descending to %d000'",pl->a_nextz);
                   1033:                fprintf(bigstatsfile,
                   1034:                        "\n\tPosition: (%d,%d)    Bearing: ",pl->a_x,pl->a_y);
                   1035:                if (pl->a_dy < 0) fprintf(bigstatsfile,"N");
                   1036:                else if (pl->a_dy > 0) fprintf(bigstatsfile,"S");
                   1037:                if (pl->a_dx > 0) fprintf(bigstatsfile,"E");
                   1038:                else if (pl->a_dx < 0) fprintf(bigstatsfile,"W");
                   1039:                if (pl->a_turn)
                   1040:                {       fprintf(bigstatsfile," turning %c to ",pl->a_turn);
                   1041:                        if (pl->a_dynew < 0) fprintf(bigstatsfile,"N");
                   1042:                        else if (pl->a_dynew > 0) fprintf(bigstatsfile,"S");
                   1043:                        if (pl->a_dxnew > 0) fprintf(bigstatsfile,"E");
                   1044:                        else if (pl->a_dxnew < 0) fprintf(bigstatsfile,"W");
                   1045:                }
                   1046:                fprintf(bigstatsfile,".\n");
                   1047:        }
                   1048:        report(BOUND,pl);
                   1049:        return(0);
                   1050: }
                   1051: 
                   1052: conflict()      /* check each pair of planes for problems */
                   1053: {       register struct astruct *q,*p;
                   1054:        register int i,j,k;
                   1055:        register int miss;
                   1056: 
                   1057:        for (p = &plane[k=1]; k < nplanes; k++,p++)
                   1058:        {       if (p->a_active != ACTIVE && p->a_active != LANDING) continue;
                   1059:                for (q = &plane[i=0]; i < k; i++,q++)
                   1060:                {       if (q->a_active != ACTIVE) continue;
                   1061:                        if (q->a_z != p->a_z && q->a_z != p->a_lastz &&
                   1062:                            q->a_lastz != p->a_z && q->a_lastz != p->a_lastz)
                   1063:                                continue;
                   1064:                        miss = abs(q->a_x - p->a_x);
                   1065:                        j = abs(q->a_y - p->a_y);
                   1066:                        if (j>miss) miss=j;
                   1067:                        if (miss < 3)   /* too close - system error */
                   1068:                        {       system++;
                   1069:                                if (bigname) bigsyserr(p,q);
                   1070:                                report(SYSTEM,p,q);
                   1071:                                break;
                   1072:                        }
                   1073:                }
                   1074:        }
                   1075: }
                   1076: 
                   1077: bigsyserr(p,q)  /* spew sys err info into the big stats file */
                   1078: struct astruct *p,*q;
                   1079: {
                   1080:        fprintf(bigstatsfile,
                   1081:                "%5d: System error between %c (%d,%d,%d000) and %c (%d,%d,%d000)\n",
                   1082:                initgame_time - game_time,p->a_id,p->a_x,p->a_y,p->a_z,
                   1083:                q->a_id,q->a_x,q->a_y,q->a_z);
                   1084: }
                   1085: 
                   1086: erase(x,y)
                   1087: int x,y;
                   1088: {       register struct astruct *p;
                   1089:        register int i;
                   1090: 
                   1091:        if (x<0 || y < 0) return;
                   1092:        if (x>=width || y>=height) return;
                   1093:        cursor(x,y);
                   1094:        printf("%c ",screen[x][y]);
                   1095:        for (p = &plane[i=0]; i < nplanes; i++,p++)
                   1096:                if (p->a_active == ACTIVE && x == p->a_x && y == p->a_y)
                   1097:                {       cursor(x,y);
                   1098:                        printf("%c%c",p->a_id,(p->a_z>9?'^':p->a_z+'0'));
                   1099:                }
                   1100: }
                   1101: 
                   1102: 
                   1103: int msglen[MAXHEIGHT];  /* length of message string on this row */
                   1104: 
                   1105: init()
                   1106: {       int i,j;
                   1107:        char c,mbuf[BUFSIZE];
                   1108:        int pcompare();
                   1109:        FILE *statfile;
                   1110:        struct passwd *pw;
                   1111:        time_t now;
                   1112:        char *p,*ct;
                   1113:        extern char *ctime();
                   1114:        int nearlies;
                   1115: 
                   1116:        if ((statfile = fopen(STATSFILE,"a")) != NULL)
                   1117:        {       pw = getpwuid(getuid());
                   1118:                now = get_time();
                   1119:                ct = ctime(&now);
                   1120:                for (p= &ct[4]; p <= &ct[16]; p++) fputc(*p,statfile);
                   1121:                fprintf(statfile,"%8s\n",pw->pw_name);
                   1122:                fclose(statfile);
                   1123:        }
                   1124: 
                   1125:        /* go into raw mode, no echo */
                   1126:        if (!moviefile)
                   1127:        {       ioctl(0, TIOCGETP, &tty_setting);
                   1128:                tty_flags = tty_setting.sg_flags;
                   1129: #ifdef CBREAK
                   1130:                tty_setting.sg_flags |= CBREAK;
                   1131:                tty_setting.sg_flags &= ~CRMOD;
                   1132: #else
                   1133:                tty_setting.sg_flags |= RAW;
                   1134: #endif
                   1135:                tty_setting.sg_flags &= ~ECHO;
                   1136:                ioctl(0, TIOCSETP, &tty_setting);
                   1137:                if (signal (SIGINT, SIG_IGN) != SIG_IGN)
                   1138:                        signal (SIGINT, catchint);
                   1139:                if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
                   1140:                        signal (SIGQUIT, catchint);
                   1141:        }
                   1142: 
                   1143:        for (i = 0; i < MAXHEIGHT; i++)
                   1144:                msglen[i] = 0;
                   1145: 
                   1146:        for (i=0; i<MAXWIDTH; i++) for (j=0; j<MAXHEIGHT; j++)
                   1147:                screen[i][j] = '.';
                   1148: 
                   1149:        if (moviefile)
                   1150:        {       if ((movie = fopen(moviefile,"r")) == NULL)
                   1151:                        err("Cannot open %s for reading.\n",moviefile);
                   1152:                minit();        /* initialize from movie file */
                   1153:        }
                   1154: 
                   1155:        if (seed == 0) seed = get_time();
                   1156:        initseed = seed;
                   1157: #ifdef vax
                   1158:        srand(seed);
                   1159: #else
                   1160:        srandom(seed);    /* initialize random number generator */
                   1161: #endif
                   1162: 
                   1163:        clearscreen();
                   1164:        readspace();
                   1165: 
                   1166: 
                   1167:        cmdx = width;  /* start command just to right of display */
                   1168:        cmdy = height-4; /* and a ways from the bottom */
                   1169:        display();      /* initial display */
                   1170:        for (i=0; i<nairport; i++)
                   1171:        {       sprintf(mbuf,"%c : %c%c",
                   1172:                     screen[airport[i].p_x][airport[i].p_y],
                   1173:                     (j = airport[i].p_dy) == 1 ? 'S' : j == -1 ? 'N' : ' ',
                   1174:                     (j = airport[i].p_dx) == 1 ? 'E' : j == -1 ? 'W' : ' ');
                   1175:                msg(cmdx,cmdy-2-i,mbuf);
                   1176:        }
                   1177: 
                   1178:        cdltop.c_next = 0;      /* initially no clearance directive lists */
                   1179:        cdltop.c_list = 0;
                   1180: 
                   1181:        while (game_time < 16*60 || game_time > 99*60+59) /*get time from user */
                   1182:        {       char buf[100];
                   1183:                char *p;
                   1184:                cursor(cmdx,cmdy);
                   1185:                printf("<  >");
                   1186:                cursor(cmdx,cmdy);
                   1187: 
                   1188:                /* move the cursor one space to the right */
                   1189:                p = buf;
                   1190:                tgetstr ("nd", &p);
                   1191:                fwrite (buf, sizeof (*buf), p-buf, stdout);
                   1192: 
                   1193:                game_time = getdigit()*10;   /* get the time as 2 digits */
                   1194:                game_time += getdigit();
                   1195:                initgame_time = game_time = game_time*60+59;
                   1196:        }
                   1197: 
                   1198:        if (protofile)  /* keeping a protocol of the whole game */
                   1199:        {       if ((proto = fopen(protofile,"w")) == NULL)
                   1200:                        err("Cannot open %s for writing.\n",protofile);
                   1201:                protostats(proto);
                   1202:        }
                   1203: 
                   1204:        if (bigname)    /* megastatistics requested */
                   1205:        {       if ((bigstatsfile = fopen(bigname,"w")) == NULL)
                   1206:                        err("Cannot open %s for writing.\n",bigname);
                   1207:                protostats(bigstatsfile);
                   1208:                if (protofile)
                   1209:                        fprintf(bigstatsfile,"Protocol from %s\n",protofile);
                   1210:        }
                   1211: 
                   1212:        last_update = initgame_time+UPDATE; /* force early update */
                   1213:        if (moviefile) last_update += OFFSET;
                   1214: 
                   1215:        for (i=nearlies=0; i<nplanes; i++)   /* construct 26 flight plans */
                   1216:        {       plane[i].a_id = 'A'+i;
                   1217:                flightplan(&plane[i],0);
                   1218:                if (plane[i].a_stime < FPTHRESH) nearlies++;
                   1219:        }
                   1220:        for (i=nearlies; i < NEARLY; i++) /* ensure 2 or so planes in 1st minute */
                   1221:                flightplan(&plane[die(nplanes)],1);
                   1222:        qsort(plane,nplanes,sizeof (struct astruct),pcompare);
                   1223:        remain = nplanes;
                   1224:        if (bigname)
                   1225:                for (i = 0; i < nplanes; i++)
                   1226:                        strip(&plane[i],-1,TERSE);
                   1227: 
                   1228:        for (i=0; i<nairport; i++)      /* erase the approaches */
                   1229:                delmsg(cmdx,cmdy-2-i);
                   1230:        start_time = get_time();
                   1231: }
                   1232: 
                   1233: protostats(proto)    /* bunch of statistics for protocols and stuff */
                   1234: FILE *proto;
                   1235: {       char wd[100];   /* result of a "pwd" command */
                   1236:        FILE *pwd;
                   1237:        char *s,*t,*u;
                   1238:        int c;
                   1239: 
                   1240:        if ((pwd = popen("pwd","r")) == NULL)
                   1241:                err("Cannot open a pipe to pwd.\n");
                   1242:        for (s = wd; (c = getc(pwd)) != EOF;)
                   1243:                if (c != '\n') *s++ = c;
                   1244:        t = s;  /* here's where to put the filename */
                   1245:        *s = 0;
                   1246:        fclose(pwd);
                   1247:        if (*airfile != '/') /* relative airspace file */
                   1248:        {       s = t;
                   1249:                *s++ = '/';
                   1250:                for (u = airfile; *s++ = *u++; );
                   1251:                fprintf(proto,"Airspace file: %s\n",wd);
                   1252:        }
                   1253:        else    fprintf(proto,"Airspace file: %s\n",airfile);
                   1254:        fprintf(proto,"Airspace: %s\n",airspace);
                   1255:        if (flowfile)
                   1256:        {       if (*flowfile != '/') /* relative flowfile */
                   1257:                {       s = t;
                   1258:                        *s++ = '/';
                   1259:                        for (u = flowfile; *s++ = *u++; );
                   1260:                        fprintf(proto,"Flow file: %s\n",wd);
                   1261:                }
                   1262:                else    fprintf(proto,"Flow file: %s\n",flowfile);
                   1263:        }
                   1264:        else    fprintf(proto,"Flow file: \n");
                   1265:        fprintf(proto,"Seed: %d\n",seed);
                   1266:        fprintf(proto,"Time: %d seconds\n",game_time);
                   1267: }
                   1268: 
                   1269: minit() /* initialize the game from a protocol file */
                   1270: {       /* the file is open on stream "movie" */
                   1271:        char buffer[80];
                   1272:        static char airfilebuf[80];
                   1273:        static char airbuf[80];
                   1274:        static char flowbuf[80];
                   1275:        char *s,*t;
                   1276: 
                   1277:        if (fgets(buffer,80,movie) == 0)      /* airspace file line */
                   1278:                err("Unexpected EOF on movie file.\n");
                   1279:        for (s = buffer; *s != ':' && *s; s++); /* scan to colon */
                   1280:        if (*s == 0) err("Bad airspace file line.\n");
                   1281:        s++; s++;       /* skip colon and space */
                   1282:        for (t = airfilebuf; (*t++ = *s++) != '\n';); /* copy airspace file */
                   1283:        *--t = 0;
                   1284:        airfile = airfilebuf;   /* and dummy the pointer */
                   1285:        if (fgets(buffer,80,movie) == 0)      /* airspace line */
                   1286:                err("Unexpected EOF on movie file.\n");
                   1287:        for (s = buffer; *s != ':' && *s; s++); /* scan to colon */
                   1288:        if (*s == 0) err("Bad airspace line.\n");
                   1289:        s++; s++;       /* skip colon and space */
                   1290:        for (t = airbuf; (*t++ = *s++) != '\n';); /* copy airspace name */
                   1291:        *--t = 0;
                   1292:        airspace = airbuf; /* and dummy the pointer */
                   1293:        if (fgets(buffer,80,movie) == 0)      /* flowfile line */
                   1294:                err("Unexpected EOF on movie file.\n");
                   1295:        for (s = buffer; *s != ':' && *s; s++); /* scan to colon */
                   1296:        if (*s == 0) err("Bad flowfile line.\n");
                   1297:        s++; s++;       /* skip colon and space */
                   1298:        if (*s == '\n') flowfile = 0;
                   1299:        else
                   1300:        {       for (t = flowbuf; (*t++ = *s++) != '\n';); /* copy flowfile */
                   1301:                *--t = 0;
                   1302:                flowfile = flowbuf; /* and dummy the pointer */
                   1303:        }
                   1304:        if (fgets(buffer,80,movie) == 0)      /* seed */
                   1305:                err("Unexpected EOF on movie file.\n");
                   1306:        for (s = buffer; *s != ':' && *s; s++); /* scan to colon */
                   1307:        if (*s == 0) err("Bad seed line.\n");
                   1308:        s++; s++;       /* skip colon and space */
                   1309:        seed = atoi(s);
                   1310:        if (fgets(buffer,80,movie) == 0)      /* time line */
                   1311:                err("Unexpected EOF on movie file.\n");
                   1312:        for (s = buffer; *s != ':' && *s; s++); /* scan to colon */
                   1313:        if (*s == 0) err("Bad time line.\n");
                   1314:        s++; s++;       /* skip colon and space */
                   1315:        initgame_time = game_time = atoi(s);
                   1316:        getmcmd();      /* get the first command from movie mode */
                   1317: }
                   1318: 
                   1319: getmcmd()       /* read a command and store time and command */
                   1320: {       static char buff[80];
                   1321:        char *s;
                   1322: 
                   1323:        if (fgets(buff,80,movie) == 0)
                   1324:        {       mcommand = "";
                   1325:                nextmovie = -20;
                   1326:                fclose(movie);
                   1327:                return;
                   1328:        }
                   1329:        for (s = buff; *s == ' '; s++);       /* skip initial blanks */
                   1330:        nextmovie = atoi(s);
                   1331:        while (*s++ != ' ');  /* skip to the command */
                   1332:        mcommand = s;           /* and save it in a global */
                   1333:        for (; *s; s++) if (*s == '\n') *s = RETURN;
                   1334: }
                   1335: 
                   1336: pcompare(p1,p2) /* compare start times for sorting the plane list */
                   1337: struct astruct *p1,*p2;
                   1338: {       if ((p1)->a_stime < (p2)->a_stime) return(-1);
                   1339:        else if ((p1)->a_stime == (p2)->a_stime) return(0);
                   1340:        else return(1);
                   1341: }
                   1342: 
                   1343: 
                   1344: printplans()    /* flight plans for active and near-active planes */
                   1345: {       register int ctr;      /* can only keep cmdy-2 planes on the screen */
                   1346:        register struct astruct *p;
                   1347:        register int i;
                   1348: 
                   1349:        for (i = ctr = 0, p = &plane[0]; i < nplanes && ctr < cmdy - 2; i++,p++)
                   1350:                if (p->a_active == APPROACHING || p->a_active == WAITING)
                   1351:                        strip(p,ctr++,TERSE);
                   1352:        delmsg(cmdx,ctr++);     /* blank line between approaching and active*/
                   1353:        for (p = &plane[i=0]; i < nplanes && ctr < cmdy - 2; i++,p++)
                   1354:                if (p->a_active == ACTIVE)
                   1355:                        strip(p,ctr++,TERSE);
                   1356:        while (ctr < cmdy - 2) delmsg(cmdx,ctr++); /* delete any msg on line*/
                   1357: }
                   1358: 
                   1359: strip(p,y,outstyle)     /* display flight strip for this plane on cmd row y */
                   1360: register struct astruct *p;
                   1361: int y,outstyle;
                   1362: {       char mbuf[80];  /* plan message to appear */
                   1363:        int pfuel;
                   1364:        struct list *l;
                   1365:        char *s;
                   1366: 
                   1367:        if (p->a_active == WAITING) sprintf(mbuf,"  ");
                   1368:        else if (p->a_active == APPROACHING)
                   1369:                sprintf(mbuf,"%d ",
                   1370:                        (p->a_stime - initgame_time + game_time + 14) / 15);
                   1371:        else mbuf[0] = 0;
                   1372:        sprintf(&mbuf[strlen(mbuf)],"%c%c %c->%c ",
                   1373:                p->a_id,
                   1374:                (p->a_type? 'j': 'p'),
                   1375:                screen[p->a_x][p->a_y],
                   1376:                (p->a_dair? airport[p->a_dest].p_sym :
                   1377:                            entry[p->a_dest].p_sym));
                   1378:        sprintf(&mbuf[strlen(mbuf)],"%d%c%c ",
                   1379:                p->a_z,
                   1380:                (p->a_nextz > p->a_z ? '^' :
                   1381:                 p->a_nextz < p->a_z ? 'v' : ' '),
                   1382:                (p->a_nextz != p->a_z ? p->a_nextz + '0' : ' '));
                   1383:        if (p->a_dy>0) sprintf(&mbuf[strlen(mbuf)],"S");
                   1384:        else if (p->a_dy<0) sprintf(&mbuf[strlen(mbuf)],"N");
                   1385:        if (p->a_dx>0) sprintf(&mbuf[strlen(mbuf)],"E");
                   1386:        else if (p->a_dx<0) sprintf(&mbuf[strlen(mbuf)],"W");
                   1387:        if (p->a_dy == 0) sprintf(&mbuf[strlen(mbuf)]," ");
                   1388:        switch(p->a_hold)
                   1389:        {   case 2: sprintf(&mbuf[strlen(mbuf)]," h "); break;
                   1390:            case 1: sprintf(&mbuf[strlen(mbuf)]," * "); break;
                   1391:            case 0: sprintf(&mbuf[strlen(mbuf)]," %c ",p->a_turn-'A'+'a');
                   1392:                    break;
                   1393:        }
                   1394:        if (p->a_clear)
                   1395:                sprintf(&mbuf[strlen(mbuf)],"* %c",p->a_clear);
                   1396:        if (p->a_dynew>0) sprintf(&mbuf[strlen(mbuf)],"S");
                   1397:        else if (p->a_dynew<0) sprintf(&mbuf[strlen(mbuf)],"N");
                   1398:        if (p->a_dxnew>0) sprintf(&mbuf[strlen(mbuf)],"E");
                   1399:        else if (p->a_dxnew<0) sprintf(&mbuf[strlen(mbuf)],"W");
                   1400:        if (p->a_dynew == 0) sprintf(&mbuf[strlen(mbuf)]," ");
                   1401:        pfuel = (p->a_type == JET? p->a_fuel/4 : p->a_fuel/2);
                   1402:        sprintf(&mbuf[strlen(mbuf)]," %c",pfuel>=10?'+':pfuel+'0');
                   1403:        if (p->a_plan)
                   1404:                sprintf(&mbuf[strlen(mbuf)]," P");
                   1405:        if (y < 0)      /* flight strip to file, not screen */
                   1406:        {       if (bigname)
                   1407:                {       int st;
                   1408: 
                   1409:                        st = p->a_stime;
                   1410:                        if (p->a_type == JET)
                   1411:                        {       st = st / 15;
                   1412:                                st = st * 15;
                   1413:                        }
                   1414:                        else
                   1415:                        {       st = (st + 45) / 30;
                   1416:                                st = (st * 30) - 15;
                   1417:                        }
                   1418:                        if (st < FIRST_TIME) st = FIRST_TIME;
                   1419:                        fprintf(bigstatsfile,"%5d: ",st);
                   1420:                        fprintf(bigstatsfile,"%s\n",mbuf);
                   1421:                }
                   1422:        }
                   1423:        else
                   1424:        {       msg(cmdx,y,mbuf);   /* display the string */
                   1425:                if (outstyle == VERBOSE && p->a_plan)
                   1426:                {       for (l = p->a_plan; l; l = l->l_next)
                   1427:                        {       sprintf(mbuf,"%s %s",l->l_loc,l->l_cmd);
                   1428:                                for (s = mbuf; *s; s++) if (*s == RETURN) *s = 0;
                   1429:                                msg(cmdx,++y,mbuf);
                   1430:                        }
                   1431:                }
                   1432:                while (++y < MAXHEIGHT && msglen[y]) msg(cmdx,y,"");/* clr old plans*/
                   1433:        }
                   1434: }
                   1435: 
                   1436: msg(x,y,string) /* put up a message at cursor position x,y */
                   1437: int x,y;
                   1438: char *string;
                   1439: {       int i,l;
                   1440: 
                   1441:        cursor(x,y);
                   1442:        printf("%s",string);
                   1443:        l = strlen(string);
                   1444:        for (i=l; i<msglen[y]; i++) putchar(' ');
                   1445:        msglen[y] = l;
                   1446: }
                   1447: 
                   1448: delmsg(x,y)     /* delete any message starting at cursor posn x,y */
                   1449: int x,y;
                   1450: {       int i;
                   1451: 
                   1452:        if (msglen[y] <= 0) return;
                   1453:        cursor(x,y);
                   1454:        for (i=0; i<msglen[y]; i++) putchar(' ');
                   1455:        msglen[y] = 0;
                   1456: }
                   1457: 
                   1458: 
                   1459: flightplan(p,early)
                   1460: struct astruct *p;
                   1461: int early;      /* 1 if this plane should be rescheduled for early arrival */
                   1462: {       int i,r,cum;
                   1463:        struct astruct *q;
                   1464:        struct pstruct *loc;
                   1465: 
                   1466:        p->a_type = die(2);
                   1467:        /* starting time: no planes in last 15 minutes; pretend interval
                   1468:         * extends negatively from 0 by FUDGE seconds to make it more likely
                   1469:         * that there will be planes available soon.  On the other hand, no
                   1470:         * plane can come on for the first FIRST_TIME seconds.
                   1471:         */
                   1472:        p->a_stime = die(FUDGE + game_time - 15*60) - FUDGE;
                   1473:        if (early) p->a_stime = die(FPTHRESH);
                   1474:        if (p->a_stime <FIRST_TIME) p->a_stime = FIRST_TIME;
                   1475:        if (flowfile)   /* flows have been specified */
                   1476:        {       r = die(maxflow);
                   1477:                for (i = cum = 0; i < npaths; i++)
                   1478:                {       cum += fpath[i].f_freq;
                   1479:                        if (cum >= r) break;
                   1480:                }
                   1481:                if (i >= npaths) i = 0; /* shouldn't ever do this */
                   1482:                p->a_sair = fpath[i].f_fair;
                   1483:                p->a_dair = fpath[i].f_tair;
                   1484:                p->a_hold = (p->a_dair && !p->a_sair? 1 : 0);
                   1485:                p->a_start = fpath[i].f_from;
                   1486:                p->a_dest = fpath[i].f_to;
                   1487: 
                   1488:                if (p->a_sair) loc = &airport[p->a_start];
                   1489:                else           loc = &entry[p->a_start];
                   1490:        }
                   1491:        else
                   1492:        {       p->a_sair = (die(inaptot+inawtot) <= inaptot? 1 : 0);
                   1493:                p->a_dair = (die(outaptot+outawtot) <= outaptot? 1 : 0);
                   1494: 
                   1495:                p->a_hold = (p->a_dair? 1 : 0);
                   1496:                if (p->a_sair)
                   1497:                {       p->a_start =pick(die(inaptot),&airport[0],nairport,1);
                   1498:                        loc = &airport[p->a_start];
                   1499:                        p->a_hold = 0;
                   1500:                        if (p->a_dair) p->a_dest = pick(die(inaptot),
                   1501:                                                        &airport[0],nairport,0);
                   1502:                        else           p->a_dest = pick(die(inawtot),
                   1503:                                                        &entry[0],nentry,0);
                   1504:                }
                   1505:                else
                   1506:                {       p->a_start = pick(die(inawtot),&entry[0],nentry,0);
                   1507:                        loc = &entry[p->a_start];
                   1508:                        if (p->a_dair) p->a_dest = pick(die(inaptot),
                   1509:                                                        &airport[0],nairport,0);
                   1510:                        else do p->a_dest = pick(die(inawtot),
                   1511:                                                 &entry[0],nentry,0);
                   1512:                             while (p->a_dest == p->a_start);
                   1513:                }
                   1514:        }
                   1515:        p->a_active = INACTIVE;
                   1516:        p->a_z = (p->a_sair? 0 : 6);
                   1517:        if (!p->a_sair) /* separate planes by 1000' altitude */
                   1518:            for (q = &plane[0]; q != &plane[PMAX]; q++)
                   1519:            {   if (q == p && !early) break;
                   1520:                if (q == p) continue;
                   1521:                if (p->a_start == q->a_start)
                   1522:                    if (abs(q->a_stime - p->a_stime) < SAFETY)
                   1523:                        if (q->a_z >= p->a_z)
                   1524:                            p->a_z = q->a_z + 1;
                   1525:            }
                   1526:        if (flowfile && p->a_z < NALT)
                   1527:        {       p->a_opt = fpath[i].f_dist[p->a_z];
                   1528:                p->a_cmds = fpath[i].f_cmds;
                   1529:        }
                   1530:        p->a_prev = p->a_pprev = p->a_aprev = 0;
                   1531:        p->a_x = loc->p_x;
                   1532:        p->a_y = loc->p_y;
                   1533:        p->a_dx = loc->p_dx;
                   1534:        p->a_dy = loc->p_dy;
                   1535:        p->a_dxnew = p->a_dynew = 0;
                   1536:        p->a_lastz = p->a_nextz = p->a_z;
                   1537:        p->a_turn = 0;
                   1538:        p->a_fuel = (p->a_type == JET ? JETFUEL : PROPFUEL);
                   1539:        p->a_clear = 0; /* not cleared for any approach */
                   1540:        p->a_plan = 0;  /* no monitor points on the flight plan */
                   1541:        p->a_load = p->a_ticks = p->a_planned = p->a_dist = 0;
                   1542: }
                   1543: 
                   1544: pick(draw,point,num,in)
                   1545: int draw;
                   1546: struct pstruct *point;
                   1547: int num,in;
                   1548: {       register int i,cum;
                   1549: 
                   1550:        for (i = cum = 0; i<num; i++,point++)
                   1551:        {       if (in) cum += point->p_inprop;
                   1552:                else    cum += point->p_outprop;
                   1553:                if (cum >= draw) return(i);
                   1554:        }
                   1555:        return(0); /* should never get here */
                   1556: }
                   1557: 
                   1558: #if !NRAND
                   1559: die(n) /* throw an n-sided die (sides 0 thru n-1) */
                   1560: int n;
                   1561: {       int r;
                   1562: 
                   1563: #ifdef vax
                   1564:        r = rand() >> 10;        /* rightmost bits are not very random */
                   1565: #else
                   1566:        r = random();   /* rightmost bits are not very random */
                   1567: #endif
                   1568:        return(r % n);  /* enough resolution to make this o.k. */
                   1569: }
                   1570: #endif
                   1571: 
                   1572: getdigit()      /* keep reading chars from terminal until get a digit */
                   1573: {       int c;  /* returns digit - '0' */
                   1574: 
                   1575:        do {
                   1576:                if (rubout) return 9;
                   1577:                c = getchar() & 0177;
                   1578:        } while (c < '0' || c > '9');
                   1579:        putchar(c);
                   1580:        return(c-'0');
                   1581: }
                   1582: 
                   1583: time_t
                   1584: get_time()      /* returns time in seconds since 1970 */
                   1585: {
                   1586:        time_t t;
                   1587: 
                   1588:        time(&t);
                   1589:        return(t);     /* seconds since 1970 */
                   1590: }
                   1591: 
                   1592: 
                   1593: display()      /* put up initial screen */
                   1594: {      int i,j;
                   1595: 
                   1596:        for (j=0; j<height; j++)
                   1597:        {       cursor(0,j);    /* general enough to extend to graphics */
                   1598:                for (i=0; i<width; i++)
                   1599:                {       putchar(screen[i][j]);
                   1600:                        putchar(' ');
                   1601:                }
                   1602:        }
                   1603: }
                   1604: 
                   1605: 
                   1606: cursor(x,y)    /* move to location x,y on WIDTHxHEIGHT screen */
                   1607: char x,y;       /* this is in terms of screen, i.e. with x's 2 chars wide */
                   1608: { 
                   1609:        poscur(2*x,y);
                   1610: } 
                   1611: 
                   1612: 
                   1613: poscur(x,y)     /* position cursor at this absolute location on screen */
                   1614: char x,y;
                   1615: {       
                   1616:        char *tgoto();
                   1617:        printf ("%s", tgoto (cmbuf, x, y));
                   1618: }
                   1619: 
                   1620: 
                   1621: clearscreen()
                   1622: {       
                   1623:        printf ("%s", clbuf);
                   1624: }
                   1625: 
                   1626: char *
                   1627: plural(n)       /* returns "s" unless n=1 */
                   1628: int n;
                   1629: {       static char s[2] = "s";
                   1630: 
                   1631:        if (n != 1) return(s);
                   1632:        else return("");
                   1633: }
                   1634: 
                   1635: done(flag)  /* clean up */
                   1636: int flag;
                   1637: {       FILE *statfile;
                   1638:        struct passwd *pw;
                   1639:        time_t now;
                   1640:        char *c,*ct;
                   1641:        extern char *ctime();
                   1642: 
                   1643:        if (!moviefile)
                   1644:        {       tty_setting.sg_flags = tty_flags;/* put terminal back the way it was*/
                   1645:                ioctl(0, TIOCSETP, &tty_setting);
                   1646:        }
                   1647:        if (flag) cursor(LEFT,height+1);
                   1648: 
                   1649:        if ((statfile = fopen(STATSFILE,"a")) != NULL)
                   1650:        {       pw = getpwuid(getuid());
                   1651:                now = get_time();
                   1652:                ct = ctime(&now);
                   1653:                for (c= &ct[4]; c <= &ct[16]; c++) fputc(*c,statfile);
                   1654:                if (!flag) fprintf(statfile,"%8s: aborted\n",pw->pw_name);
                   1655:                else
                   1656:                {  fprintf(statfile,"%8s: %2d %3d %2d %2d %3d %5d   %3d %2d",
                   1657:                           pw->pw_name,crash,system,fuel,bound,goaround,
                   1658:                           fuelused,cmds,remain);
                   1659:                   fprintf(statfile,". %d  %2d %s\n",
                   1660:                           initseed,initgame_time/60,airspace);
                   1661:                   fclose(statfile);
                   1662:                }
                   1663:        }
                   1664:        if (!flag) return;
                   1665:        ttystats(stdout);
                   1666:        if (bigname)
                   1667:        {       int i;
                   1668:                float load,ticks,plans,route,d,stripped;
                   1669: 
                   1670:                for (i = 0; i < nplanes; i++)
                   1671:                {       load = plane[i].a_load;
                   1672:                        ticks = plane[i].a_ticks;
                   1673:                        plans = plane[i].a_planned;
                   1674:                        route = plane[i].a_opt;
                   1675:                        stripped = plane[i].a_prev;
                   1676:                        d = plane[i].a_dist;
                   1677:                        fprintf(bigstatsfile,
                   1678: "%c: %2d tks, %2d/%2d=%1.2f, %d, %.2f a/tk, %.2f p/tk, %.2f a/ptk, %.2f p/ptk, %c, %s\n",
                   1679:                                plane[i].a_id,plane[i].a_ticks,
                   1680:                                plane[i].a_dist,
                   1681:                                plane[i].a_opt,
                   1682:                                d/route,
                   1683:                                plane[i].a_cmds,
                   1684:                                load/ticks,
                   1685:                                plans/ticks,
                   1686:                                plane[i].a_aprev/stripped,
                   1687:                                plane[i].a_pprev/stripped,
                   1688:                                plane[i].a_sair? 'W' : 'A',
                   1689:                                plane[i].a_pplanned? "+P" : "-P"
                   1690:                        );
                   1691:                }
                   1692:        }
                   1693:        if (bigname) ttystats(bigstatsfile);
                   1694:        if (protofile) fclose(proto);
                   1695:        if (bigname) fclose(bigstatsfile);
                   1696: }
                   1697: 
                   1698: ttystats(file)
                   1699: FILE *file;
                   1700: {       char *eol;
                   1701: 
                   1702:        if (file == bigstatsfile) eol = "\n";
                   1703:        else {
                   1704:                clearscreen();
                   1705:                eol = "\n\r";
                   1706:        }
                   1707:        if (crash)  fprintf(file,"%d plane%s out of fuel, crashed%s",
                   1708:                crash,plural(crash),eol);
                   1709:        if (system) fprintf(file,"%d system error%s%s",
                   1710:                system,plural(system),eol);
                   1711:        if (fuel)   fprintf(file,"%d tow truck%s called%s",
                   1712:                fuel,plural(fuel),eol);
                   1713:        if (bound)  fprintf(file,"%d boundary error%s%s",
                   1714:                bound,plural(bound),eol);
                   1715:        if (goaround) fprintf(file,"%d go-around%s%s",
                   1716:                goaround,plural(goaround),eol);
                   1717:        if (crash+system+fuel+bound+remain == 0)
                   1718:        { fprintf(file,"GREAT JOB!!  Have you considered a career in ATC?\n");
                   1719:          fprintf(file,"Now try %d minutes...\n",initgame_time/60-5);
                   1720:        }
                   1721:        fprintf(file,"Fuel used: %d\n",fuelused);
                   1722:        fprintf(file,"Commands issued (including deferred): %d\n",icmds);
                   1723:        fprintf(file,"Commands executed: %d\n",cmds);
                   1724:        fprintf(file,"Airspace: %s; seed: %d; time=%d; %d remaining.%s",
                   1725:                airspace,initseed,initgame_time/60,remain,eol);
                   1726:        if (file == bigstatsfile) fprintf(file,"\f");
                   1727: }
                   1728: 
                   1729: err(msg,arg1,arg2)
                   1730: char *msg; 
                   1731: {       fprintf(stderr,msg,arg1,arg2);
                   1732:        done(0);
                   1733:        exit(1);
                   1734: } 
                   1735: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.